📄 ip.c
字号:
/*ip.cCopyright 1995 Philip Homburg*/#include "inet.h"#include "buf.h"#include "event.h"#include "type.h"#include "arp.h"#include "assert.h"#include "clock.h"#include "eth.h"#include "icmp.h"#include "icmp_lib.h"#include "io.h"#include "ip.h"#include "ip_int.h"#include "ipr.h"#include "sr.h"THIS_FILEFORWARD void ip_close ARGS(( int fd ));FORWARD int ip_cancel ARGS(( int fd, int which_operation ));FORWARD int ip_select ARGS(( int fd, unsigned operations ));FORWARD void ip_buffree ARGS(( int priority ));#ifdef BUF_CONSISTENCY_CHECKFORWARD void ip_bufcheck ARGS(( void ));#endifFORWARD void ip_bad_callback ARGS(( struct ip_port *ip_port ));PUBLIC ip_port_t *ip_port_table;PUBLIC ip_fd_t ip_fd_table[IP_FD_NR];PUBLIC ip_ass_t ip_ass_table[IP_ASS_NR];PUBLIC void ip_prep(){ ip_port_table= alloc(ip_conf_nr * sizeof(ip_port_table[0])); icmp_prep();}PUBLIC void ip_init(){ int i, j, result; ip_ass_t *ip_ass; ip_fd_t *ip_fd; ip_port_t *ip_port; struct ip_conf *icp; assert (BUF_S >= sizeof(struct nwio_ethopt)); assert (BUF_S >= IP_MAX_HDR_SIZE + ETH_HDR_SIZE); assert (BUF_S >= sizeof(nwio_ipopt_t)); assert (BUF_S >= sizeof(nwio_route_t)); for (i=0, ip_ass= ip_ass_table; i<IP_ASS_NR; i++, ip_ass++) { ip_ass->ia_frags= 0; ip_ass->ia_first_time= 0; ip_ass->ia_port= 0; } for (i=0, ip_fd= ip_fd_table; i<IP_FD_NR; i++, ip_fd++) { ip_fd->if_flags= IFF_EMPTY; ip_fd->if_rdbuf_head= 0; } for (i=0, ip_port= ip_port_table, icp= ip_conf; i<ip_conf_nr; i++, ip_port++, icp++) { ip_port->ip_port= i; ip_port->ip_flags= IPF_EMPTY; ip_port->ip_dev_main= (ip_dev_t)ip_bad_callback; ip_port->ip_dev_set_ipaddr= (ip_dev_t)ip_bad_callback; ip_port->ip_dev_send= (ip_dev_send_t)ip_bad_callback; ip_port->ip_dl_type= icp->ic_devtype; ip_port->ip_mtu= IP_DEF_MTU; ip_port->ip_mtu_max= IP_MAX_PACKSIZE; switch(ip_port->ip_dl_type) { case IPDL_ETH: ip_port->ip_dl.dl_eth.de_port= icp->ic_port; result= ipeth_init(ip_port); if (result == -1) continue; assert(result == NW_OK); break; case IPDL_PSIP: ip_port->ip_dl.dl_ps.ps_port= icp->ic_port; result= ipps_init(ip_port); if (result == -1) continue; assert(result == NW_OK); break; default: ip_panic(( "unknown ip_dl_type %d", ip_port->ip_dl_type )); break; } ip_port->ip_loopb_head= NULL; ip_port->ip_loopb_tail= NULL; ev_init(&ip_port->ip_loopb_event); ip_port->ip_routeq_head= NULL; ip_port->ip_routeq_tail= NULL; ev_init(&ip_port->ip_routeq_event); ip_port->ip_flags |= IPF_CONFIGURED; ip_port->ip_proto_any= NULL; for (j= 0; j<IP_PROTO_HASH_NR; j++) ip_port->ip_proto[j]= NULL; }#ifndef BUF_CONSISTENCY_CHECK bf_logon(ip_buffree);#else bf_logon(ip_buffree, ip_bufcheck);#endif icmp_init(); ipr_init(); for (i=0, ip_port= ip_port_table; i<ip_conf_nr; i++, ip_port++) { if (!(ip_port->ip_flags & IPF_CONFIGURED)) continue; ip_port->ip_frame_id= (u16_t)get_time(); sr_add_minor(if2minor(ip_conf[i].ic_ifno, IP_DEV_OFF), i, ip_open, ip_close, ip_read, ip_write, ip_ioctl, ip_cancel, ip_select); (*ip_port->ip_dev_main)(ip_port); }}PRIVATE int ip_cancel (fd, which_operation)int fd;int which_operation;{ ip_fd_t *ip_fd; acc_t *repl_res; int result; ip_fd= &ip_fd_table[fd]; switch (which_operation) { case SR_CANCEL_IOCTL: assert (ip_fd->if_flags & IFF_IOCTL_IP); ip_fd->if_flags &= ~IFF_IOCTL_IP; repl_res= (*ip_fd->if_get_userdata)(ip_fd->if_srfd, (size_t)EINTR, (size_t)0, TRUE); assert (!repl_res); break; case SR_CANCEL_READ: assert (ip_fd->if_flags & IFF_READ_IP); ip_fd->if_flags &= ~IFF_READ_IP; result= (*ip_fd->if_put_userdata)(ip_fd->if_srfd, (size_t)EINTR, (acc_t *)0, FALSE); assert (!result); break;#if 0 case SR_CANCEL_WRITE: assert(0); assert (ip_fd->if_flags & IFF_WRITE_MASK); ip_fd->if_flags &= ~IFF_WRITE_MASK; repl_res= (*ip_fd->if_get_userdata)(ip_fd->if_srfd, (size_t)EINTR, (size_t)0, FALSE); assert (!repl_res); break;#endif default: ip_panic(( "unknown cancel request" )); break; } return NW_OK;}PRIVATE int ip_select(fd, operations)int fd;unsigned operations;{ printf("ip_select: not implemented\n"); return 0;}PUBLIC int ip_open (port, srfd, get_userdata, put_userdata, put_pkt, select_res)int port;int srfd;get_userdata_t get_userdata;put_userdata_t put_userdata;put_pkt_t put_pkt;select_res_t select_res;{ int i; ip_fd_t *ip_fd; ip_port_t *ip_port; ip_port= &ip_port_table[port]; if (!(ip_port->ip_flags & IPF_CONFIGURED)) return ENXIO; for (i=0; i<IP_FD_NR && (ip_fd_table[i].if_flags & IFF_INUSE); i++); if (i>=IP_FD_NR) { DBLOCK(1, printf("out of fds\n")); return EAGAIN; } ip_fd= &ip_fd_table[i]; ip_fd->if_flags= IFF_INUSE; ip_fd->if_ipopt.nwio_flags= NWIO_DEFAULT; ip_fd->if_ipopt.nwio_tos= 0; ip_fd->if_ipopt.nwio_df= FALSE; ip_fd->if_ipopt.nwio_ttl= 255; ip_fd->if_ipopt.nwio_hdropt.iho_opt_siz= 0; ip_fd->if_port= ip_port; ip_fd->if_srfd= srfd; assert(ip_fd->if_rdbuf_head == NULL); ip_fd->if_get_userdata= get_userdata; ip_fd->if_put_userdata= put_userdata; ip_fd->if_put_pkt= put_pkt; return i;}PRIVATE void ip_close (fd)int fd;{ ip_fd_t *ip_fd; acc_t *pack; ip_fd= &ip_fd_table[fd]; assert ((ip_fd->if_flags & IFF_INUSE) && !(ip_fd->if_flags & IFF_BUSY)); if (ip_fd->if_flags & IFF_OPTSET) ip_unhash_proto(ip_fd); while (ip_fd->if_rdbuf_head) { pack= ip_fd->if_rdbuf_head; ip_fd->if_rdbuf_head= pack->acc_ext_link; bf_afree(pack); } ip_fd->if_flags= IFF_EMPTY;}PRIVATE void ip_buffree(priority)int priority;{ int i; ip_port_t *ip_port; ip_fd_t *ip_fd; ip_ass_t *ip_ass; acc_t *pack, *next_pack; for (i= 0, ip_port= ip_port_table; i<ip_conf_nr; i++, ip_port++) { if (ip_port->ip_dl_type == IPDL_ETH) { /* Can't free de_frame. * bf_check_acc(ip_port->ip_dl.dl_eth.de_frame); */ if (priority == IP_PRI_PORTBUFS) { next_pack= ip_port->ip_dl.dl_eth.de_arp_head; while(next_pack != NULL) { pack= next_pack; next_pack= pack->acc_ext_link; bf_afree(pack); } ip_port->ip_dl.dl_eth.de_arp_head= next_pack; next_pack= ip_port->ip_dl.dl_eth.de_q_head; while(next_pack != NULL) { pack= next_pack; next_pack= pack->acc_ext_link; bf_afree(pack); } ip_port->ip_dl.dl_eth.de_q_head= next_pack; } } else if (ip_port->ip_dl_type == IPDL_PSIP) { if (priority == IP_PRI_PORTBUFS) { next_pack= ip_port->ip_dl.dl_ps.ps_send_head; while (next_pack != NULL) { pack= next_pack; next_pack= pack->acc_ext_link; bf_afree(pack); } ip_port->ip_dl.dl_ps.ps_send_head= next_pack; } } if (priority == IP_PRI_PORTBUFS) { next_pack= ip_port->ip_loopb_head; while(next_pack && next_pack->acc_ext_link) { pack= next_pack; next_pack= pack->acc_ext_link; bf_afree(pack); } if (next_pack) { if (ev_in_queue(&ip_port->ip_loopb_event)) {#if DEBUG printf("not freeing ip_loopb_head, ip_loopb_event enqueued\n");#endif } else { bf_afree(next_pack); next_pack= NULL; } } ip_port->ip_loopb_head= next_pack; next_pack= ip_port->ip_routeq_head; while(next_pack && next_pack->acc_ext_link) { pack= next_pack; next_pack= pack->acc_ext_link; bf_afree(pack); } if (next_pack) { if (ev_in_queue(&ip_port->ip_routeq_event)) {#if DEBUG printf("not freeing ip_loopb_head, ip_routeq_event enqueued\n");#endif } else { bf_afree(next_pack); next_pack= NULL; } } ip_port->ip_routeq_head= next_pack; } } if (priority == IP_PRI_FDBUFS_EXTRA) { for (i= 0, ip_fd= ip_fd_table; i<IP_FD_NR; i++, ip_fd++) { while (ip_fd->if_rdbuf_head && ip_fd->if_rdbuf_head->acc_ext_link) { pack= ip_fd->if_rdbuf_head; ip_fd->if_rdbuf_head= pack->acc_ext_link; bf_afree(pack); } } } if (priority == IP_PRI_FDBUFS) { for (i= 0, ip_fd= ip_fd_table; i<IP_FD_NR; i++, ip_fd++) { while (ip_fd->if_rdbuf_head) { pack= ip_fd->if_rdbuf_head; ip_fd->if_rdbuf_head= pack->acc_ext_link; bf_afree(pack); } } } if (priority == IP_PRI_ASSBUFS) { for (i= 0, ip_ass= ip_ass_table; i<IP_ASS_NR; i++, ip_ass++) { next_pack= ip_ass->ia_frags; while(ip_ass->ia_frags != NULL) { pack= ip_ass->ia_frags; ip_ass->ia_frags= pack->acc_ext_link; bf_afree(pack); } ip_ass->ia_first_time= 0; } }}#ifdef BUF_CONSISTENCY_CHECKPRIVATE void ip_bufcheck(){ int i; ip_port_t *ip_port; ip_fd_t *ip_fd; ip_ass_t *ip_ass; acc_t *pack; for (i= 0, ip_port= ip_port_table; i<ip_conf_nr; i++, ip_port++) { if (ip_port->ip_dl_type == IPDL_ETH) { bf_check_acc(ip_port->ip_dl.dl_eth.de_frame); for (pack= ip_port->ip_dl.dl_eth.de_q_head; pack; pack= pack->acc_ext_link) { bf_check_acc(pack); } for (pack= ip_port->ip_dl.dl_eth.de_arp_head; pack; pack= pack->acc_ext_link) { bf_check_acc(pack); } } else if (ip_port->ip_dl_type == IPDL_PSIP) { for (pack= ip_port->ip_dl.dl_ps.ps_send_head; pack; pack= pack->acc_ext_link) { bf_check_acc(pack); } } for (pack= ip_port->ip_loopb_head; pack; pack= pack->acc_ext_link) { bf_check_acc(pack); } for (pack= ip_port->ip_routeq_head; pack; pack= pack->acc_ext_link) { bf_check_acc(pack); } } for (i= 0, ip_fd= ip_fd_table; i<IP_FD_NR; i++, ip_fd++) { for (pack= ip_fd->if_rdbuf_head; pack; pack= pack->acc_ext_link) { bf_check_acc(pack); } } for (i= 0, ip_ass= ip_ass_table; i<IP_ASS_NR; i++, ip_ass++) { for (pack= ip_ass->ia_frags; pack; pack= pack->acc_ext_link) bf_check_acc(pack); }}#endif /* BUF_CONSISTENCY_CHECK */PRIVATE void ip_bad_callback(ip_port)struct ip_port *ip_port;{ ip_panic(( "no callback filled in for port %d", ip_port->ip_port ));}/* * $PchId: ip.c,v 1.19 2005/06/28 14:17:40 philip Exp $ */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -