📄 eth.c
字号:
} eth_fd->ef_rd_buf= 0;}PRIVATE int eth_checkopt (eth_fd)eth_fd_t *eth_fd;{/* bug: we don't check access modes yet */ unsigned long flags; unsigned int en_di_flags; eth_port_t *eth_port; acc_t *acc, *acc2; eth_port= eth_fd->ef_port; flags= eth_fd->ef_ethopt.nweo_flags;#if DEBUG & 256 { where(); printf("eth_fd_table[%d].ef_ethopt.nweo_flags= 0x%x\n", eth_fd-eth_fd_table, flags); }#endif en_di_flags= (flags >>16) | (flags & 0xffff); if ((en_di_flags & NWEO_ACC_MASK) && (en_di_flags & NWEO_LOC_MASK) && (en_di_flags & NWEO_BROAD_MASK) && (en_di_flags & NWEO_MULTI_MASK) && (en_di_flags & NWEO_PROMISC_MASK) && (en_di_flags & NWEO_REM_MASK) && (en_di_flags & NWEO_TYPE_MASK) && (en_di_flags & NWEO_RW_MASK)) { eth_fd->ef_flags |= EFF_OPTSET; eth_fd->ef_pack_stat= EPS_EMPTY; if (flags & NWEO_EN_LOC) eth_fd->ef_pack_stat |= EPS_LOC; if (flags & NWEO_EN_BROAD) eth_fd->ef_pack_stat |= EPS_BROAD; if (flags & NWEO_EN_MULTI) eth_fd->ef_pack_stat |= EPS_MULTI; if (flags & NWEO_EN_PROMISC) eth_fd->ef_pack_stat |= (EPS_PROMISC|EPS_MULTI| EPS_BROAD); } else eth_fd->ef_flags &= ~EFF_OPTSET; for (acc= eth_fd->ef_rd_buf; acc;) { acc2= acc->acc_ext_link; bf_afree(acc); acc= acc2; } eth_fd->ef_rd_buf= 0; return NW_OK;}PUBLIC int eth_get_work(eth_port)eth_port_t *eth_port;{ eth_fd_t *eth_fd; int i;#if DEBUG & 256 { where(); printf("eth_get_work called\n"); }#endif if (eth_port->etp_wr_pack) return 0; if (!(eth_port->etp_flags & EPF_MORE2WRITE)) return 0; for (i=0, eth_fd= eth_fd_table; i<ETH_FD_NR; i++, eth_fd++) { if ((eth_fd->ef_flags & (EFF_INUSE|EFF_WRITE_IP)) != (EFF_INUSE|EFF_WRITE_IP)) continue; if (eth_fd->ef_port != eth_port) continue;#if DEBUG & 256 { where(); printf("eth_get_work calling restart_write_fd\n"); }#endif restart_write_fd(eth_fd); if (eth_port->etp_wr_pack) return 1; } eth_port->etp_flags &= ~EPF_MORE2WRITE; return 0;}PUBLIC void eth_arrive (eth_port, pack)eth_port_t *eth_port;acc_t *pack;{ time_t exp_tim; eth_hdr_t *eth_hdr; static ether_addr_t broadcast= {255, 255, 255, 255, 255, 255}, multi_addr, rem_addr, packaddr; int pack_stat; ether_type_t type; eth_fd_t *eth_fd, *share_fd; acc_t *acc; int i;#if DEBUG & 256 { where(); printf("eth_arrive(0x%x, 0x%x) called\n", eth_port, pack); }#endifassert(pack->acc_linkC); exp_tim= get_time() + EXPIRE_TIME; pack= bf_packIffLess(pack, ETH_HDR_SIZE); eth_hdr= (eth_hdr_t*)ptr2acc_data(pack);#if DEBUG & 256 { where(); printf("src= "); writeEtherAddr(ð_hdr->eh_src); printf(" dst= "); writeEtherAddr(ð_hdr->eh_dst); printf(" proto= 0x%x\n", ntohs(eth_hdr->eh_proto)); printf(" my addr= "); writeEtherAddr(ð_port->etp_ethaddr); printf("\n"); }#endif packaddr= eth_hdr->eh_dst; if (packaddr.ea_addr[0] & 0x01) { /* multi cast or broadcast */ if (!eth_addrcmp(packaddr, broadcast)) pack_stat= EPS_BROAD; else { pack_stat= EPS_MULTI;#if DEBUG { where(); printf("Got a multicast packet\n"); }#endif } } else { if (!eth_addrcmp (packaddr, eth_port->etp_ethaddr)) pack_stat= EPS_LOC; else pack_stat= EPS_PROMISC; } type= eth_hdr->eh_proto;#if DEBUG & 256 { where(); printf("pack_stat= 0x%x\n", pack_stat); }#endif share_fd= 0; for (i=0, eth_fd=eth_fd_table; i<ETH_FD_NR; i++, eth_fd++) { if (!(eth_fd->ef_flags & EFF_OPTSET)) {#if DEBUG & 256 { where(); printf("fd %d doesn't have EFF_OPTSET\n", i); }#endif continue; } if (eth_fd->ef_port != eth_port) {#if DEBUG { where(); printf("fd %d uses port %d, packet is on port %d\n", i, eth_fd->ef_port-eth_port_table, eth_port-eth_port_table); }#endif continue; } if (!(eth_fd->ef_pack_stat & pack_stat)) {#if DEBUG & 256 { where(); printf("fd %d has ef_pack_stat 0x%x, expecting 0x%x\n", i, eth_fd->ef_pack_stat, pack_stat); }#endif continue; } if ((eth_fd->ef_ethopt.nweo_flags & NWEO_TYPESPEC) && type != eth_fd->ef_ethopt.nweo_type) {#if DEBUG & 256 { where(); printf("fd %d uses type 0x%x, expecting 0x%x\n", i, eth_fd->ef_ethopt.nweo_type, type); }#endif continue; }#if DEBUG & 256 { where(); printf("multi OK\n"); }#endif if (eth_fd->ef_ethopt.nweo_flags & NWEO_REMSPEC) { rem_addr= eth_fd->ef_ethopt.nweo_rem; if (eth_addrcmp (eth_hdr->eh_src, rem_addr)) continue; }#if DEBUG & 256 { where(); printf("rem NW_OK\n"); }#endif if (eth_fd->ef_rd_buf) { if (eth_fd->ef_ethopt.nweo_flags == NWEO_SHARED) { share_fd= eth_fd; continue; } } acc= bf_dupacc(pack); acc->acc_ext_link= NULL; if (!eth_fd->ef_rd_buf) { eth_fd->ef_rd_buf= acc; eth_fd->ef_exp_tim= exp_tim; } else eth_fd->ef_rd_tail->acc_ext_link= acc; eth_fd->ef_rd_tail= acc; if (eth_fd->ef_flags & EFF_READ_IP) packet2user(eth_fd); if ((eth_fd->ef_ethopt.nweo_flags & NWEO_ACC_MASK) != NWEO_COPY) { bf_afree(pack); pack= 0; break; } } if (share_fd && pack) { acc= bf_dupacc(pack); acc->acc_ext_link= NULL; if (!share_fd->ef_rd_buf) { share_fd->ef_rd_buf= acc; share_fd->ef_exp_tim= exp_tim; } else share_fd->ef_rd_tail->acc_ext_link= acc; share_fd->ef_rd_tail= acc; } if (pack) bf_afree(pack);}PRIVATE int packet2user (eth_fd)eth_fd_t *eth_fd;{ acc_t *pack, *header; int result; size_t size;#if DEBUG & 256 { where(); printf("packet2user() called\n"); }#endif pack= eth_fd->ef_rd_buf; eth_fd->ef_rd_buf= pack->acc_ext_link; if (eth_fd->ef_ethopt.nweo_flags & NWEO_RWDATONLY) { pack= bf_packIffLess (pack, ETH_HDR_SIZE); assert (pack->acc_length >= ETH_HDR_SIZE); if (pack->acc_linkC >1) { header= bf_dupacc (pack); bf_afree(pack); pack= header; } assert (pack->acc_linkC == 1); pack->acc_offset += ETH_HDR_SIZE; pack->acc_length -= ETH_HDR_SIZE; } size= bf_bufsize (pack); eth_fd->ef_flags &= ~EFF_READ_IP; result= (*eth_fd->ef_put_userdata)(eth_fd->ef_srfd, (size_t)0, pack, FALSE); if (result >=0) reply_thr_put(eth_fd, size, FALSE); return result<0 ? result : NW_OK;}PRIVATE int ok_for_me (eth_fd, pack)eth_fd_t *eth_fd;acc_t *pack;{ eth_port_t *eth_port; eth_hdr_t *eth_hdr; ether_type_t type; static ether_addr_t broadcast= {255, 255, 255, 255, 255, 255}, packaddr, portaddr, multi_addr, rem_addr; int pack_kind; assert (pack->acc_length >= ETH_HDR_SIZE); eth_port= eth_fd->ef_port; eth_hdr= (eth_hdr_t *)ptr2acc_data(pack); packaddr= eth_hdr->eh_dst; if (packaddr.ea_addr[0] & 0x01) /* multi cast or broadcast */ if (!eth_addrcmp (packaddr, broadcast)) pack_kind= EPS_BROAD; else pack_kind= EPS_MULTI; else { portaddr= eth_port->etp_ethaddr; if (!eth_addrcmp(packaddr, portaddr)) pack_kind= EPS_LOC; else pack_kind= EPS_PROMISC; } pack_kind &= eth_fd->ef_pack_stat; if (!pack_kind) return FALSE; type= eth_hdr->eh_proto; if ((eth_fd->ef_ethopt.nweo_flags & NWEO_TYPESPEC) && type != eth_fd->ef_ethopt.nweo_type) return FALSE; if (eth_fd->ef_ethopt.nweo_flags & NWEO_REMSPEC) { rem_addr= eth_fd->ef_ethopt.nweo_rem; if (eth_addrcmp(eth_hdr->eh_src, rem_addr)) return FALSE; } return TRUE;}PRIVATE void eth_buffree (priority, reqsize)int priority;size_t reqsize;{ int i, once_more; time_t curr_tim; acc_t *acc; if (priority <ETH_PRI_EXP_FDBUFS) return;#if DEBUG & 256 { where(); printf("eth_buffree called\n"); }#endif curr_tim= get_time(); for (i=0; i<ETH_FD_NR; i++) { if (!(eth_fd_table[i].ef_flags & EFF_INUSE) ) continue; acc= eth_fd_table[i].ef_rd_buf; if (acc && eth_fd_table[i].ef_exp_tim < curr_tim) { eth_fd_table[i].ef_rd_buf= acc->acc_ext_link; bf_afree(acc); if (bf_free_buffsize >= reqsize) return; } } if (priority <ETH_PRI_FDBUFS) return; once_more= 1; while (once_more) { once_more= 0; for (i=0; i<ETH_FD_NR; i++) { if (!(eth_fd_table[i].ef_flags & EFF_INUSE)) continue; acc= eth_fd_table[i].ef_rd_buf; if (acc) { eth_fd_table[i].ef_rd_buf= acc->acc_ext_link; bf_afree(acc); if (bf_free_buffsize >= reqsize) return; once_more= 1; } } }}PRIVATE void restart_write_fd(eth_fd)eth_fd_t *eth_fd;{ eth_port_t *eth_port; acc_t *user_data, *header; int size; unsigned long nweo_flags; eth_hdr_t *eth_hdr; eth_port= eth_fd->ef_port; if (eth_port->etp_wr_pack) { eth_port->etp_flags |= EPF_MORE2WRITE; return; }assert (eth_fd->ef_flags & EFF_WRITE_IP); eth_fd->ef_flags &= ~EFF_WRITE_IP;assert (!eth_port->etp_wr_pack);#if DEBUG & 256 { where(); printf("calling *get_userdata\n"); }#endif user_data= (*eth_fd->ef_get_userdata)(eth_fd->ef_srfd, 0, eth_fd->ef_write_count, FALSE); if (!user_data) { eth_fd->ef_flags &= ~EFF_WRITE_IP; reply_thr_get (eth_fd, EFAULT, FALSE); return; } size= bf_bufsize (user_data); nweo_flags= eth_fd->ef_ethopt.nweo_flags; if (nweo_flags & NWEO_RWDATONLY) { header= bf_memreq(ETH_HDR_SIZE); header->acc_next= user_data; user_data= header; } user_data= bf_packIffLess (user_data, ETH_HDR_SIZE); eth_hdr= (eth_hdr_t *)ptr2acc_data(user_data); if (nweo_flags & NWEO_REMSPEC) eth_hdr->eh_dst= eth_fd->ef_ethopt.nweo_rem; eth_hdr->eh_src= eth_port->etp_ethaddr; if (nweo_flags & NWEO_TYPESPEC) eth_hdr->eh_proto= eth_fd->ef_ethopt.nweo_type;assert (!eth_port->etp_wr_pack); eth_port->etp_wr_pack= user_data; if (!(eth_port->etp_flags & EPF_WRITE_IP)) { eth_write_port(eth_port); } reply_thr_get (eth_fd, size, FALSE);}PRIVATE void reply_thr_get (eth_fd, result, for_ioctl)eth_fd_t *eth_fd;size_t result;int for_ioctl;{ acc_t *data;#if DEBUG & 256 { where(); printf("calling *get_userdata(fd= %d, %d, 0)\n", eth_fd-> ef_srfd, result, 0); }#endif data= (*eth_fd->ef_get_userdata)(eth_fd->ef_srfd, result, 0, for_ioctl);assert (!data); }PRIVATE void reply_thr_put (eth_fd, result, for_ioctl)eth_fd_t *eth_fd;size_t result;int for_ioctl;{ int error; error= (*eth_fd->ef_put_userdata)(eth_fd->ef_srfd, result, (acc_t *)0, for_ioctl);assert(!error);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -