📄 icmp.c
字号:
return; /*---------------------------------------------------------------*/ /* Complete ICMP reply packet fields. */ /*---------------------------------------------------------------*/ reply = rbuf->ip_data; reply->type = ICT_ECHORP; /* ** Copy the consecutive identifier, seq_num, and data fields. */ memcpy(&reply->identifier, ip_data + id_offset, RxBuf->length - id_offset); /*---------------------------------------------------------------*/ /* Calculate checksum on completed ICMP packet. */ /*---------------------------------------------------------------*/ reply->checksum = 0; reply->checksum = IpChecksum(reply, RxBuf->length); /*---------------------------------------------------------------*/ /* Request IP to send this datagram. */ /*---------------------------------------------------------------*/ ip_out = (Ip *)rbuf->ip_pkt; ip_out->src_ip = Net.Ip->dst_ip; ip_out->dst_ip = Net.Ip->src_ip; icmp_send(rbuf, RxBuf->length, ip_in->ip_tos); } break; case ICT_ECHORP: /*-----------------------------------------------------------------*/ /* Received echo response. Pass to waiting task if possible. */ /*-----------------------------------------------------------------*/ { Echo *echo = (Echo *)ip_data; PingEntry *entry; /*---------------------------------------------------------------*/ /* Try to match sequence number with entry in Ping Table. */ /*---------------------------------------------------------------*/ for (entry = &PingTbl[0];; ++entry) { if (entry == &PingTbl[PING_TBL_SZ]) return; if (entry->taskid == 0) continue; if (entry->seq_num == echo->seq_num) break; } /*---------------------------------------------------------------*/ /* Matched! Assign buf and use id to wake task. */ /*---------------------------------------------------------------*/ entry->buf = RxBuf; RxBuf = NULL; taskWake(entry->taskid); entry->taskid = 0; return; } case ICT_REDIRECT: /*-----------------------------------------------------------------*/ /* Received indication of a better route. */ /*-----------------------------------------------------------------*/ { Route *route; ui32 mask, orig_dst; /*---------------------------------------------------------------*/ /* Get destination IP address from header of original datagam. */ /*---------------------------------------------------------------*/ memcpy(&orig_dst, ip_data + offsetof(Icmp, datagram) + offsetof(Ip, dst_ip), sizeof(orig_dst)); /*---------------------------------------------------------------*/ /* Search for a route to this distination. */ /*---------------------------------------------------------------*/ route = RtSearch(orig_dst); /*---------------------------------------------------------------*/ /* Check if route gateway is source of redirect message. */ /*---------------------------------------------------------------*/ if (route && (route->gw == Net.Ip->src_ip)) { ui32 new_gw; ui8 code = *(ip_data + offsetof(Icmp, code)) & 3; /*-------------------------------------------------------------*/ /* Determine appropriate subnet mask. */ /*-------------------------------------------------------------*/ if (code == ICC_HOSTRD) mask = 0xFFFFFFFF; else mask = IpSubnetMask(orig_dst); /*-------------------------------------------------------------*/ /* Get new gateway address from REDIRECT message. */ /*-------------------------------------------------------------*/ memcpy(&new_gw, ip_data + offsetof(Icmp, lword), sizeof(new_gw)); /*-------------------------------------------------------------*/ /* Delete old route and add new one. */ /*-------------------------------------------------------------*/ RtDel(route->gw, mask, route->addr); RtAdd(new_gw, mask, route->addr, route->ni, RT_GATEWAY); } } break; case ICT_MASKRQ: /*-----------------------------------------------------------------*/ /* Received subnet mask request. */ /*-----------------------------------------------------------------*/ if (Net.IsGateway) { NetBuf *rbuf; Mask *reply; Ip *ip_out; int id_offset = offsetof(Mask, identifier); /*---------------------------------------------------------------*/ /* Get network buffer for subnet mask reply. */ /*---------------------------------------------------------------*/ rbuf = tcpGetBuf(NIMHLEN + IPMHLEN + sizeof(Mask)); if (rbuf == NULL) break; /*---------------------------------------------------------------*/ /* Start ICMP header initialization. */ /*---------------------------------------------------------------*/ reply = rbuf->ip_data; reply->type = ICT_MASKRP; reply->code = 0; /* ** Copy the consecutive identifier and seq_num fields. */ memcpy(&reply->identifier, ip_data + id_offset, 2 * sizeof(ui16)); reply->mask = IpSubnetMask(Net.Ip->dst_ip); /*---------------------------------------------------------------*/ /* Calculate checksum on completed ICMP packet. */ /*---------------------------------------------------------------*/ reply->checksum = 0; reply->checksum = IpChecksum(reply, ICMP_HLEN + sizeof(Mask)); /*---------------------------------------------------------------*/ /* Request IP to send this datagram. */ /*---------------------------------------------------------------*/ ip_out = (Ip *)rbuf->ip_pkt; if (Net.Ip->dst_ip == INADDR_ANY) ip_out->src_ip = INADDR_BROADCAST; else ip_out->src_ip = Net.Ip->dst_ip; ip_out->dst_ip = Net.Ip->src_ip; icmp_send(rbuf, ICMP_HLEN + sizeof(Mask), ICMP_TOS); } break; case ICT_DESTUR: /*-----------------------------------------------------------------*/ /* Received indication that destination is unreachable. */ /*-----------------------------------------------------------------*/ { Icmp *icmp = (Icmp *)ip_data; /*---------------------------------------------------------------*/ /* Update statistics. */ /*---------------------------------------------------------------*/ ++Stats.IcmpDestUr; switch (icmp->code) { case ICC_NETUR: /* network unreachable */ ++DstUrNetUr; apply2sock(EHOSTUNREACH); break; case ICC_HOSTUR: /* host unreachable */ ++DstUrHostUr; apply2sock(EHOSTUNREACH); break; case ICC_PROTOUR: /* protocol unreachable */ ++DstUrProtoUr; apply2sock(ECONNREFUSED); break; case ICC_PORTUR: /* port unreachable */ ++DstUrPortUr; apply2sock(ECONNREFUSED); break; case ICC_FRAGREQ: /* frag required but DF bit is set */ ++DstUrFragReq; apply2sock(EMSGSIZE); break; case ICC_SRCRT: /* source route failed */ ++DstUrSRCRT; apply2sock(EHOSTUNREACH); break; case ICC_NETUNK: /* destination network unknown */ ++DstUrNetUnk; apply2sock(EHOSTUNREACH); break; case ICC_HOSTUNK: /* destination host unknown */ ++DstUrHostUnk; apply2sock(EHOSTUNREACH); break; case ICC_NETTYP: /* network unreachable for type of service */ ++DstUrNetTyp; apply2sock(EHOSTUNREACH); break; case ICC_HOSTTYP: /* host unreachable for type of service */ ++DstUrHostTyp; apply2sock(EHOSTUNREACH); break; case ICC_COMMPRO: /* comm administratively prohibited */ ++DstUrCommPro; break; case ICC_PRECVIO: /* host precedence violation */ ++DstUrPrecVio; break; case ICC_PRECCUT: /* precedence cutoff in effect */ ++DstUrPrecCut; break; } } break; case ICT_SRCQ: /*-----------------------------------------------------------------*/ /* Received request to throttle output, apply slow start. */ /*-----------------------------------------------------------------*/ ++SrcQuench; apply2sock(SOURCE_QUENCH); break; case ICT_PARAMP: /*-----------------------------------------------------------------*/ /* Parameter problem: IP header bad or required option missing. */ /*-----------------------------------------------------------------*/ apply2sock(ENOPROTOOPT); break; }}#if TCP_PROBE/***********************************************************************//* IcmpDecode: Parse and decode ICMP packet on stdout *//* *//***********************************************************************/void IcmpDecode(const NetBuf *buf){ ui8 type = *(ui8 *)buf->ip_data; printf("ICMP: "); switch (type) { case ICT_ECHORQ: printf("Echo request"); break; case ICT_ECHORP: printf("Echo response"); break; case ICT_REDIRECT: printf("Redirect"); break; case ICT_TIMEX: printf("Time expired"); break; case ICT_MASKRQ: printf("Mask request"); break; case ICT_DESTUR: printf("Destination unreachable"); break; case ICT_SRCQ: printf("Source quench"); break; default: printf("Type = 0x%02X", type); break; } putchar('\n');}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -