📄 icmp.c
字号:
#endif bf_afree(ip_data); bf_afree(icmp_data); return; } if (icmp_len < ICMP_MIN_HDR_LEN + sizeof(icmp_id_seq_t)) {#if DEBUG { where(); printf("got an incomplete icmp echo request\n"); }#endif bf_afree(ip_data); bf_afree(icmp_data); return; }#if DEBUG & 256 { where(); printf("got an icmp echo request, ident= %u, seq= %u\n", ntohs(icmp_hdr->ih_hun.ihh_idseq.iis_id), ntohs(icmp_hdr->ih_hun.ihh_idseq.iis_seq)); }#endif repl_ip_hdr= make_repl_ip(ip_hdr, ip_len); repl_icmp= bf_memreq (ICMP_MIN_HDR_LEN);assert (repl_icmp->acc_length == ICMP_MIN_HDR_LEN); repl_icmp_hdr= (icmp_hdr_t *)ptr2acc_data(repl_icmp); repl_icmp_hdr->ih_type= ICMP_TYPE_ECHO_REPL; repl_icmp_hdr->ih_code= 0; tmp_chksum= ~icmp_hdr->ih_chksum - *(u16_t *)&icmp_hdr->ih_type+ *(u16_t *)&repl_icmp_hdr->ih_type; tmp_chksum= (tmp_chksum >> 16) + (tmp_chksum & 0xffff); tmp_chksum= (tmp_chksum >> 16) + (tmp_chksum & 0xffff); repl_icmp_hdr->ih_chksum= ~tmp_chksum; repl_ip_hdr->acc_next= repl_icmp; repl_icmp->acc_next= bf_cut (icmp_data, ICMP_MIN_HDR_LEN, icmp_len - ICMP_MIN_HDR_LEN); bf_afree(ip_data); bf_afree(icmp_data); enqueue_pack(icmp_port, repl_ip_hdr);}PRIVATE u16_t icmp_pack_oneCsum(icmp_pack)acc_t *icmp_pack;{ u16_t prev; int odd_byte; char *data_ptr; int length; char byte_buf[2]; assert (icmp_pack); prev= 0; odd_byte= FALSE; for (; icmp_pack; icmp_pack= icmp_pack->acc_next) { data_ptr= ptr2acc_data(icmp_pack); length= icmp_pack->acc_length; if (!length) continue; if (odd_byte) { byte_buf[1]= *data_ptr; prev= oneC_sum(prev, (u16_t *)byte_buf, 2); data_ptr++; length--; odd_byte= FALSE; } if (length & 1) { odd_byte= TRUE; length--; byte_buf[0]= data_ptr[length]; } if (!length) continue; prev= oneC_sum (prev, (u16_t *)data_ptr, length); } if (odd_byte) prev= oneC_sum (prev, (u16_t *)byte_buf, 1); return prev;}PRIVATE acc_t *make_repl_ip(ip_hdr, ip_len)ip_hdr_t *ip_hdr;int ip_len;{ ip_hdr_t *repl_ip_hdr; acc_t *repl; int repl_hdr_len; if (ip_len>IP_MIN_HDR_SIZE) {#if DEBUG { where(); printf("ip_hdr options NOT supported (yet?)\n"); }#endif ip_len= IP_MIN_HDR_SIZE; } repl_hdr_len= IP_MIN_HDR_SIZE; repl= bf_memreq(repl_hdr_len);assert (repl->acc_length == repl_hdr_len); repl_ip_hdr= (ip_hdr_t *)ptr2acc_data(repl); repl_ip_hdr->ih_vers_ihl= repl_hdr_len >> 2; repl_ip_hdr->ih_tos= ip_hdr->ih_tos; repl_ip_hdr->ih_ttl= ICMP_DEF_TTL; repl_ip_hdr->ih_proto= IPPROTO_ICMP; repl_ip_hdr->ih_dst= ip_hdr->ih_src; repl_ip_hdr->ih_flags_fragoff= 0; return repl;}PRIVATE void enqueue_pack(icmp_port, reply_ip_hdr)icmp_port_t *icmp_port;acc_t *reply_ip_hdr;{ reply_ip_hdr->acc_ext_link= 0; if (icmp_port->icp_head_queue) { icmp_port->icp_tail_queue->acc_ext_link= reply_ip_hdr; } else { icmp_port->icp_head_queue= reply_ip_hdr; icmp_port->icp_tail_queue= reply_ip_hdr; } if (!(icmp_port->icp_flags & ICPF_WRITE_IP)) icmp_write(icmp_port);}PRIVATE void icmp_write(icmp_port)icmp_port_t *icmp_port;{ int result;assert (!(icmp_port->icp_flags & (ICPF_WRITE_IP|ICPF_WRITE_SP) || (icmp_port->icp_flags & (ICPF_WRITE_IP|ICPF_WRITE_SP)) == (ICPF_WRITE_IP|ICPF_WRITE_SP))); for (;icmp_port->icp_head_queue;) { icmp_port->icp_write_pack= icmp_port->icp_head_queue; icmp_port->icp_head_queue= icmp_port->icp_head_queue-> acc_ext_link; icmp_port->icp_flags |= ICPF_WRITE_IP; icmp_port->icp_flags &= ~ICPF_WRITE_SP;#if DEBUG & 256 { where(); printf("calling ip_write\n"); }#endif result= ip_write(icmp_port->icp_ipfd, bf_bufsize(icmp_port->icp_write_pack)); if (result == NW_SUSPEND) {#if DEBUG & 256 { where(); printf("ip_write replied NW_SUSPEND\n"); }#endif icmp_port->icp_flags |= ICPF_WRITE_SP; return; }#if DEBUG & 256 { where(); printf("ip_write done\n"); }#endif } icmp_port->icp_flags &= ~ICPF_WRITE_IP;}PRIVATE void icmp_buffree(priority, reqsize)int priority;size_t reqsize;{ acc_t *tmp_acc; int donesomething,i; icmp_port_t *icmp_port; donesomething= 0; if (priority < ICMP_PRI_QUEUE) return; while (bf_free_buffsize < reqsize) { for (i=0, icmp_port= icmp_port_table; i<ICMP_PORT_NR; i++, icmp_port++) { if (icmp_port->icp_head_queue) { tmp_acc= icmp_port->icp_head_queue; icmp_port->icp_head_queue= tmp_acc-> acc_ext_link; bf_afree(tmp_acc); if (bf_free_buffsize >= reqsize) break; donesomething= 1; } } if (!donesomething) break; }}static void icmp_dst_unreach(icmp_port, ip_pack, ip_hdr_len, ip_hdr, icmp_pack, icmp_len, icmp_hdr)icmp_port_t *icmp_port;acc_t *ip_pack;int ip_hdr_len;ip_hdr_t *ip_hdr;acc_t *icmp_pack;int icmp_len;icmp_hdr_t *icmp_hdr;{ acc_t *old_ip_pack; ip_hdr_t *old_ip_hdr; if (icmp_len < 8 + IP_MIN_HDR_SIZE) {#if DEBUG { where(); printf("dest unrch with wrong size\n"); }#endif return; } old_ip_pack= bf_cut (icmp_pack, 8, icmp_len-8); old_ip_pack= bf_packIffLess(old_ip_pack, IP_MIN_HDR_SIZE); old_ip_hdr= (ip_hdr_t *)ptr2acc_data(old_ip_pack); if (old_ip_hdr->ih_src != ip_hdr->ih_dst) {#if DEBUG { where(); printf("dest unrch based on wrong packet\n"); }#endif bf_afree(old_ip_pack); return; } switch(icmp_hdr->ih_code) { case ICMP_NET_UNRCH: ipr_destunrch (old_ip_hdr->ih_dst, ip_get_netmask(old_ip_hdr->ih_dst), IPR_UNRCH_TIMEOUT); break; case ICMP_HOST_UNRCH: ipr_destunrch (old_ip_hdr->ih_dst, (ipaddr_t)-1, IPR_UNRCH_TIMEOUT); break; default:#if DEBUG { where(); printf("got strange code: %d\n", icmp_hdr->ih_code); }#endif break; } bf_afree(old_ip_pack);}static void icmp_time_exceeded(icmp_port, ip_pack, ip_hdr_len, ip_hdr, icmp_pack, icmp_len, icmp_hdr)icmp_port_t *icmp_port;acc_t *ip_pack;int ip_hdr_len;ip_hdr_t *ip_hdr;acc_t *icmp_pack;int icmp_len;icmp_hdr_t *icmp_hdr;{ acc_t *old_ip_pack; ip_hdr_t *old_ip_hdr; if (icmp_len < 8 + IP_MIN_HDR_SIZE) {#if DEBUG { where(); printf("time exceeded with wrong size\n"); }#endif return; } old_ip_pack= bf_cut (icmp_pack, 8, icmp_len-8); old_ip_pack= bf_packIffLess(old_ip_pack, IP_MIN_HDR_SIZE); old_ip_hdr= (ip_hdr_t *)ptr2acc_data(old_ip_pack); if (old_ip_hdr->ih_src != ip_hdr->ih_dst) {#if DEBUG { where(); printf("time exceeded based on wrong packet\n"); }#endif bf_afree(old_ip_pack); return; } switch(icmp_hdr->ih_code) { case ICMP_TTL_EXC: ipr_ttl_exc (old_ip_hdr->ih_dst, (ipaddr_t)-1, IPR_TTL_TIMEOUT); break; default: where(); printf("got strange code: %d\n", icmp_hdr->ih_code); break; } bf_afree(old_ip_pack);}static void icmp_router_advertisement(icmp_port, icmp_pack, icmp_len, icmp_hdr)icmp_port_t *icmp_port;acc_t *icmp_pack;int icmp_len;icmp_hdr_t *icmp_hdr;{ int entries; int entry_size; u16_t lifetime; int i; char *bufp; if (icmp_len < 8) {#if DEBUG { where(); printf("router advertisement with wrong size (%d)\n", icmp_len); }#endif return; } if (icmp_hdr->ih_code != 0) {#if DEBUG { where(); printf("router advertisement with wrong code (%d)\n", icmp_hdr->ih_code); }#endif return; } entries= icmp_hdr->ih_hun.ihh_ram.iram_na; entry_size= icmp_hdr->ih_hun.ihh_ram.iram_aes * 4; if (entries < 1) {#if DEBUG { where(); printf("router advertisement with wrong number of entries (%d)\n", entries); }#endif return; } if (entry_size < 8) {#if DEBUG { where(); printf("router advertisement with wrong entry size (%d)\n", entry_size); }#endif return; } if (icmp_len < 8 + entries * entry_size) {#if DEBUG { where(); printf("router advertisement with wrong size\n"); printf("\t(entries= %d, entry_size= %d, icmp_len= %d)\n", entries, entry_size, icmp_len); }#endif return; } lifetime= ntohs(icmp_hdr->ih_hun.ihh_ram.iram_lt); if (lifetime > 9000) {#if DEBUG { where(); printf("router advertisement with wrong lifetime (%d)\n", lifetime); }#endif return; } for (i= 0, bufp= (char *)&icmp_hdr->ih_dun.uhd_data[0]; i< entries; i++, bufp += entry_size) { ipr_add_route(HTONL(0L), HTONL(0L), *(ipaddr_t *)bufp, icmp_port->icp_ipport, lifetime * HZ, 1, 0, ntohl(*(i32_t *)(bufp+4))); }} static void icmp_redirect(icmp_port, ip_hdr, icmp_pack, icmp_len, icmp_hdr)icmp_port_t *icmp_port;ip_hdr_t *ip_hdr;acc_t *icmp_pack;int icmp_len;icmp_hdr_t *icmp_hdr;{ acc_t *old_ip_pack; ip_hdr_t *old_ip_hdr; int port; if (icmp_len < 8 + IP_MIN_HDR_SIZE) {#if DEBUG { where(); printf("redirect with wrong size\n"); }#endif return; } old_ip_pack= bf_cut (icmp_pack, 8, icmp_len-8); old_ip_pack= bf_packIffLess(old_ip_pack, IP_MIN_HDR_SIZE); old_ip_hdr= (ip_hdr_t *)ptr2acc_data(old_ip_pack); port= icmp_port->icp_ipport; switch(icmp_hdr->ih_code) { case ICMP_REDIRECT_NET: ipr_redirect (old_ip_hdr->ih_dst, ip_get_netmask(old_ip_hdr->ih_dst), ip_hdr->ih_src, icmp_hdr->ih_hun.ihh_gateway, port, IPR_REDIRECT_TIMEOUT); break; case ICMP_REDIRECT_HOST: ipr_redirect (old_ip_hdr->ih_dst, (ipaddr_t)-1, ip_hdr->ih_src, icmp_hdr->ih_hun.ihh_gateway, port, IPR_REDIRECT_TIMEOUT); break; default: where(); printf("got strange code: %d\n", icmp_hdr->ih_code); break; } bf_afree(old_ip_pack);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -