📄 ip_write.c
字号:
#if DEBUG & 256 { where(); printf("processing arp_pack\n"); }#endif assert (ip_port->ip_dl.dl_eth.de_arp_pack); ip_port->ip_dl.dl_eth.de_wr_ipaddr= (ipaddr_t)0; ip_port->ip_dl.dl_eth.de_wr_ethaddr= ip_port->ip_dl. dl_eth.de_arp_ethaddr; ip_port->ip_dl.dl_eth.de_wr_frag= ip_port->ip_dl.dl_eth. de_arp_pack; ip_port->ip_dl.dl_eth.de_flags &= ~IEF_ARP_MASK; return; } for (i=0, ip_fd= ip_fd_table; i<IP_FD_NR; i++, ip_fd++) { if (!(ip_fd->if_flags & IFF_INUSE)) continue; if (!(ip_fd->if_flags & IFF_DLL_WR_IP)) continue; if (ip_fd->if_wr_port != ip_port) continue;#if DEBUG & 256 { where(); printf("calling restart_fd_write\n"); }#endif restart_fd_write(ip_fd); if (ip_port->ip_dl.dl_eth.de_wr_frag) return; }}PRIVATE void restart_netbroad_fd(ip_fd)ip_fd_t *ip_fd;{ assert (!(netbroad_flags & NF_INUSE)); assert (ip_fd->if_flags & IFF_NETBROAD_IP); ip_fd->if_flags &= ~IFF_NETBROAD_IP; netbroad_flags |= NF_INUSE; netbroad_dst= ip_fd->if_wr_dstaddr; netbroad_netmask= ip_get_netmask(netbroad_dst); netbroad_pack= get_packet(ip_fd, (int)get_time()); if (!netbroad_pack) { netbroad_flags &= ~NF_INUSE; return; } netbroad_port= ip_port_table; restart_netbroadcast(); error_reply(ip_fd, ip_fd->if_wr_count);}PRIVATE void restart_fd_write(ip_fd)ip_fd_t *ip_fd;{ ip_port_t *ip_port; ipaddr_t dstaddr; acc_t *pack; int result; assert (ip_fd->if_flags & IFF_DLL_WR_IP); ip_port= ip_fd->if_wr_port; dstaddr= ip_fd->if_wr_dstaddr; result= dll_ready(ip_port, dstaddr); if (result == NW_SUSPEND) { return; } if (result == EDSTNOTRCH) {#if DEBUG { where(); printf("dll_ready returned EDSTNOTRCH, gateway= "); writeIpAddr(ip_fd->if_wr_dstaddr); printf(", the packet was %s\n", (ip_fd->if_flags & IFF_ROUTED) ? "routed" : "not routed"); }#endif if (!(ip_fd->if_flags & IFF_ROUTED)) { error_reply (ip_fd, result); return; } else { ipr_gateway_down (ip_fd->if_wr_dstaddr, IPR_GW_DOWN_TIMEOUT); error_reply(ip_fd, NW_OK); return; } }assert (result == NW_OK); ip_fd->if_flags &= ~IFF_DLL_WR_IP; ip_port->ip_frame_id++; pack= get_packet(ip_fd, ip_port->ip_frame_id); if (!pack) { return; } dll_write(ip_port, dstaddr, pack); error_reply(ip_fd, ip_fd->if_wr_count);}PRIVATE void ip_remroute_addr(ip_fd, ttl)ip_fd_t *ip_fd;u8_t ttl;{ ipaddr_t dstaddr, nexthop; ip_port_t *ip_port; int result, port; dstaddr= ip_fd->if_wr_dstaddr; result= iproute_frag (dstaddr, ttl, &nexthop, &port);#if DEBUG & 256 { where(); printf("ip_remroute_addr("); writeIpAddr(dstaddr); printf(", %d)= %d\n", ttl, result); }#endif if (result>0) { ip_port= &ip_port_table[port]; ip_fd->if_flags |= IFF_DLL_WR_IP|IFF_ROUTED; ip_fd->if_wr_dstaddr= nexthop; ip_fd->if_wr_port= ip_port;#if DEBUG & 256 { where(); printf("calling restart_fd_write\n"); }#endif restart_fd_write(ip_fd); return; } if (result<0) { error_reply (ip_fd, result); return; }#if IP_ROUTER ip_panic(( "not implemented" ));#else ip_panic(( "shouldn't be here" ));#endif}PRIVATE acc_t *ip_split_pack (ref_last, first_size)acc_t **ref_last;int first_size;{ int pack_siz; ip_hdr_t *first_hdr, *second_hdr; int first_hdr_len, second_hdr_len; int first_data_len, second_data_len; int new_first_data_len; int first_opt_size, second_opt_size; acc_t *first_pack, *second_pack, *tmp_pack, *tmp_pack1; u8_t *first_optptr, *second_optptr; int i, optlen; first_pack= *ref_last; *ref_last= 0; second_pack= 0; first_pack= bf_packIffLess(first_pack, IP_MIN_HDR_SIZE); assert (first_pack->acc_length >= IP_MIN_HDR_SIZE); first_hdr= (ip_hdr_t *)ptr2acc_data(first_pack);#if DEBUG & 256 { where(); writeIpAddr(first_hdr->ih_dst); printf("\n"); }#endif first_hdr_len= (first_hdr->ih_vers_ihl & IH_IHL_MASK) * 4;#if DEBUG & 256 { where(); printf("fist_hdr_len= %d\n", first_hdr_len); }#endif pack_siz= bf_bufsize(first_pack); if (pack_siz > first_size) {#if DEBUG & 256 { where(); printf("splitting pack\n"); }#endif if (first_hdr->ih_flags_fragoff & HTONS(IH_DONT_FRAG)) {assert (!(first_hdr->ih_flags_fragoff) & HTONS(IH_FRAGOFF_MASK)); icmp_dont_frag(first_pack); return 0; } first_data_len= ntohs(first_hdr->ih_length) - first_hdr_len; new_first_data_len= (first_size- first_hdr_len) & ~7; /* data goes in 8 byte chuncks */ second_data_len= first_data_len-new_first_data_len; second_pack= bf_cut(first_pack, first_hdr_len+ new_first_data_len, second_data_len); tmp_pack= first_pack; first_data_len= new_first_data_len; first_pack= bf_cut (tmp_pack, 0, first_hdr_len+first_data_len); bf_afree(tmp_pack); tmp_pack= bf_memreq(first_hdr_len); tmp_pack->acc_next= second_pack; second_pack= tmp_pack; second_hdr= (ip_hdr_t *)ptr2acc_data(second_pack); *second_hdr= *first_hdr; second_hdr->ih_flags_fragoff= htons( ntohs(first_hdr->ih_flags_fragoff)+(first_data_len/8)); first_opt_size= first_hdr_len-IP_MIN_HDR_SIZE; second_opt_size= 0; if (first_opt_size) { first_pack= bf_packIffLess (first_pack, first_hdr_len); first_hdr= (ip_hdr_t *)ptr2acc_data(first_pack); assert (first_pack->acc_length>=first_hdr_len); first_optptr= (u8_t *)ptr2acc_data(first_pack)+ IP_MIN_HDR_SIZE; second_optptr= (u8_t *)ptr2acc_data( second_pack)+IP_MIN_HDR_SIZE; i= 0; while (i<first_opt_size) { switch (*first_optptr & IP_OPT_NUMBER) { case 0: case 1: optlen= 1; break; default: optlen= first_optptr[1]; break; } assert (i + optlen <= first_opt_size); i += optlen; if (*first_optptr & IP_OPT_COPIED) { second_opt_size += optlen; while (optlen--) *second_optptr++= *first_optptr++; } else first_optptr += optlen; } while (second_opt_size & 3) { *second_optptr++= 0; second_opt_size++; } } second_hdr_len= IP_MIN_HDR_SIZE + second_opt_size;#if DEBUG & 256 { where(); printf("second_opt_size= %d, second_hdr_len= %d\n", second_opt_size, second_hdr_len); }#endif second_hdr->ih_vers_ihl= second_hdr->ih_vers_ihl & 0xf0 + (second_hdr_len/4); second_hdr->ih_length= htons(second_data_len+ second_hdr_len); second_pack->acc_length= second_hdr_len; if (first_pack->acc_buffer->buf_linkC>1) { tmp_pack= bf_cut(first_pack, 0, IP_MIN_HDR_SIZE); tmp_pack1= bf_cut(first_pack, IP_MIN_HDR_SIZE, bf_bufsize(first_pack)- IP_MIN_HDR_SIZE); bf_afree(first_pack);#if DEBUG { where(); printf("calling bf_pack\n"); }#endif first_pack= bf_pack(tmp_pack); first_pack->acc_next= tmp_pack1; first_hdr= (ip_hdr_t *)ptr2acc_data( first_pack); } assert (first_pack->acc_buffer->buf_linkC == 1); first_hdr->ih_flags_fragoff |= HTONS(IH_MORE_FRAGS); first_hdr->ih_length= htons(first_data_len+ first_hdr_len);assert (!(second_hdr->ih_flags_fragoff & HTONS(IH_DONT_FRAG))); } if (first_pack->acc_buffer->buf_linkC>1) { tmp_pack= bf_cut(first_pack, 0, IP_MIN_HDR_SIZE); tmp_pack1= bf_cut(first_pack, IP_MIN_HDR_SIZE, bf_bufsize(first_pack)-IP_MIN_HDR_SIZE); bf_afree(first_pack);#if DEBUG { where(); printf("calling bf_pack\n"); }#endif first_pack= bf_pack(tmp_pack); first_pack->acc_next= tmp_pack1; first_hdr= (ip_hdr_t *)ptr2acc_data(first_pack); } assert (first_hdr->ih_ttl);#if DEBUG & 256 { where(); printf("ip_write.c: ip_split_pack: first_hdr_len= %d\n", first_hdr_len); }#endif first_hdr->ih_hdr_chk= 0; first_hdr->ih_hdr_chk= ~oneC_sum (0, (u16_t *)first_hdr, first_hdr_len); *ref_last= second_pack; return first_pack;}PRIVATE void restart_netbroadcast(){ int was_suspended, result, i; ip_port_t *ip_port, *hi_port; ip_fd_t *ip_fd; assert (netbroad_flags & NF_INUSE); was_suspended= !!(netbroad_flags & NF_SUSPENDED); hi_port= &ip_port_table[IP_PORT_NR]; for (; netbroad_port < hi_port; netbroad_port++) { if (!(netbroad_port->ip_flags & IPF_IPADDRSET)) continue; if (!((netbroad_dst ^ netbroad_port->ip_ipaddr) & netbroad_netmask)) continue; result= dll_ready (netbroad_port, (ipaddr_t)-1); if (result == NW_SUSPEND) { netbroad_flags |= NF_SUSPENDED; return; }assert (result >= 0); netbroad_pack->acc_linkC++;#if DEBUG { where(); printf("calling dll_write\n"); }#endif dll_write (netbroad_port, (ipaddr_t)(-1), netbroad_pack); } netbroad_flags &= ~NF_INUSE; bf_afree(netbroad_pack); netbroad_pack= 0; if (!was_suspended) return; for (i=0, ip_fd= ip_fd_table; i<IP_FD_NR; i++, ip_fd++) { if (!(ip_fd->if_flags & IFF_INUSE) || !(ip_fd->if_flags & IFF_NETBROAD_IP)) continue; restart_netbroad_fd(ip_fd); if (netbroad_flags & NF_INUSE) return; }}PRIVATE void error_reply (ip_fd, error)ip_fd_t *ip_fd;int error;{ ip_fd->if_flags &= ~IFF_WRITE_MASK; if ((*ip_fd->if_get_userdata)(ip_fd->if_srfd, (size_t)error, (size_t)0, FALSE)) ip_panic(( "can't error_reply" ));}PRIVATE acc_t *get_packet (ip_fd, id)ip_fd_t *ip_fd;u16_t id;{ acc_t *pack, *tmp_pack, *tmp_pack1; ip_hdr_t *hdr, *tmp_hdr; int pack_len, hdr_len, hdr_opt_len, error; pack_len= ip_fd->if_wr_count; pack= (*ip_fd->if_get_userdata)(ip_fd->if_srfd, (size_t)0, pack_len, FALSE); if (!pack) return pack;assert(pack_len == bf_bufsize(pack)); if (ip_fd->if_ipopt.nwio_flags & NWIO_RWDATONLY) { tmp_pack= bf_memreq (IP_MIN_HDR_SIZE); tmp_pack->acc_next= pack; pack= tmp_pack; pack_len += IP_MIN_HDR_SIZE; } if (pack_len<IP_MIN_HDR_SIZE) { bf_afree(pack); error_reply(ip_fd, EPACKSIZE); return 0; } pack= bf_packIffLess(pack, IP_MIN_HDR_SIZE);assert (pack->acc_length >= IP_MIN_HDR_SIZE); hdr= (ip_hdr_t *)ptr2acc_data(pack); if (pack->acc_linkC != 1 || pack->acc_buffer->buf_linkC != 1) { tmp_pack= bf_memreq(IP_MIN_HDR_SIZE); tmp_hdr= (ip_hdr_t *)ptr2acc_data(tmp_pack); *tmp_hdr= *hdr; tmp_pack->acc_next= bf_cut(pack, IP_MIN_HDR_SIZE, pack_len-IP_MIN_HDR_SIZE); bf_afree(pack); hdr= tmp_hdr;#if DEBUG & 256 { where(); printf("ih_vers_ihl= 0x%x\n", hdr->ih_vers_ihl); }#endif pack= tmp_pack;assert (pack->acc_length >= IP_MIN_HDR_SIZE); }assert (pack->acc_linkC == 1 && pack->acc_buffer->buf_linkC == 1); if (ip_fd->if_ipopt.nwio_flags & NWIO_HDR_O_SPEC) {#if DEBUG & 256 { where(); printf("ih_vers_ihl= 0x%x\n", hdr->ih_vers_ihl); }#endif hdr_opt_len= ip_fd->if_ipopt.nwio_hdropt.iho_opt_siz; if (hdr_opt_len) { tmp_pack= bf_cut(pack, 0, IP_MIN_HDR_SIZE); tmp_pack1= bf_cut (pack, IP_MIN_HDR_SIZE, pack_len-IP_MIN_HDR_SIZE); bf_afree(pack); pack= bf_packIffLess(tmp_pack, IP_MIN_HDR_SIZE); hdr= (ip_hdr_t *)ptr2acc_data(pack); { where(); printf("ih_vers_ihl= 0x%x\n", hdr->ih_vers_ihl); } tmp_pack= bf_memreq (hdr_opt_len); memcpy (ptr2acc_data(tmp_pack), ip_fd->if_ipopt. nwio_hdropt.iho_data, hdr_opt_len); { where(); printf("ih_vers_ihl= 0x%x\n", hdr->ih_vers_ihl); } pack->acc_next= tmp_pack; tmp_pack->acc_next= tmp_pack1; hdr_len= IP_MIN_HDR_SIZE+hdr_opt_len; } else hdr_len= IP_MIN_HDR_SIZE; hdr->ih_vers_ihl= hdr_len/4;#if DEBUG & 256 { where(); printf("ih_vers_ihl= 0x%x\n", hdr->ih_vers_ihl); }#endif hdr->ih_tos= ip_fd->if_ipopt.nwio_tos; hdr->ih_flags_fragoff= 0; if (ip_fd->if_ipopt.nwio_df) hdr->ih_flags_fragoff |= HTONS(IH_DONT_FRAG); hdr->ih_ttl= ip_fd->if_ipopt.nwio_ttl;#if DEBUG & 256 { where(); printf("ih_vers_ihl= 0x%x\n", hdr->ih_vers_ihl); }#endif } else {assert (ip_fd->if_ipopt.nwio_flags & NWIO_HDR_O_ANY); hdr_len= (hdr->ih_vers_ihl & IH_IHL_MASK)*4;#if DEBUG & 256 { where(); printf("ih_vers_ihl= 0x%x\n", hdr->ih_vers_ihl); }#endif error= NW_OK; if (hdr_len<IP_MIN_HDR_SIZE) error= EINVAL; else if (hdr_len>pack_len) error= EPACKSIZE; else if (!hdr->ih_ttl) error= EINVAL; if (error<0) { bf_afree(pack); error_reply (ip_fd, error); return 0; } pack= bf_packIffLess(pack, hdr_len); hdr= (ip_hdr_t *)ptr2acc_data(pack);#if DEBUG & 256 { where(); printf("ih_vers_ihl= 0x%x\n", hdr->ih_vers_ihl); }#endif if (hdr_len != IP_MIN_HDR_SIZE) { error= ip_chk_hdropt((u8_t *)(ptr2acc_data(pack) + IP_MIN_HDR_SIZE), hdr_len-IP_MIN_HDR_SIZE); if (error<0) { bf_afree(pack); error_reply (ip_fd, error); return 0; } }#if DEBUG & 256 { where(); printf("ih_vers_ihl= 0x%x\n", hdr->ih_vers_ihl); }#endif }#if DEBUG & 256 if (hdr->ih_flags_fragoff & HTONS(IH_DONT_FRAG)) { where(); printf("proto= %d\n", hdr->ih_proto); }#endifassert (!(hdr->ih_flags_fragoff & HTONS(IH_DONT_FRAG)));#if DEBUG & 256 { where(); printf("ih_vers_ihl= 0x%x\n", hdr->ih_vers_ihl); }#endif hdr->ih_vers_ihl= (hdr->ih_vers_ihl & IH_IHL_MASK) | (IP_VERSION << 4);#if DEBUG & 256 { where(); printf("ih_vers_ihl= 0x%x\n", hdr->ih_vers_ihl); }#endif hdr->ih_length= htons(pack_len); hdr->ih_flags_fragoff &= ~HTONS(IH_FRAGOFF_MASK | IH_FLAGS_UNUSED | IH_MORE_FRAGS); if (ip_fd->if_ipopt.nwio_flags & NWIO_PROTOSPEC) hdr->ih_proto= ip_fd->if_ipopt.nwio_proto; hdr->ih_id= htons(id); hdr->ih_src= ip_fd->if_port->ip_ipaddr; if (ip_fd->if_ipopt.nwio_flags & NWIO_REMSPEC) hdr->ih_dst= ip_fd->if_ipopt.nwio_rem; else {assert (ip_fd->if_ipopt.nwio_flags & NWIO_REMANY); error= chk_dstaddr(hdr->ih_dst); if (error<0) { bf_afree(pack); error_reply(ip_fd, error); return 0; } } return pack;}PRIVATE chk_dstaddr (dst)ipaddr_t dst;{ ipaddr_t hostrep_dst, netmask; hostrep_dst= ntohl(dst); if (hostrep_dst == (ipaddr_t)-1) return NW_OK; if ((hostrep_dst & 0xe0000000l) == 0xe0000000l) return EBADDEST; netmask= ip_get_netmask(dst); if (!(dst & ~netmask)) return EBADDEST; return NW_OK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -