📄 ip.c
字号:
if ((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) {#if IP_REASSEMBLY /* packet fragment reassembly code present? */ LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04"X16_F" tot_len=%"U16_F" len=%"U16_F" MF=%"U16_F" offset=%"U16_F"), calling ip_reass()\n", ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & htons(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8)); /* reassemble the packet*/ p = ip_reass(p); /* packet not fully reassembled yet? */ if (p == NULL) { return ERR_OK; } iphdr = p->payload;#else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */ pbuf_free(p); LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n", ntohs(IPH_OFFSET(iphdr)))); IP_STATS_INC(ip.opterr); IP_STATS_INC(ip.drop); /* unsupported protocol feature */ snmp_inc_ipinunknownprotos(); return ERR_OK;#endif /* IP_REASSEMBLY */ }#if IP_OPTIONS_ALLOWED == 0 /* no support for IP options in the IP header? */#if LWIP_IGMP /* there is an extra "router alert" option in IGMP messages which we allow for but do not police */ if((iphdr_hlen > IP_HLEN && (IPH_PROTO(iphdr) != IP_PROTO_IGMP)) {#else if (iphdr_hlen > IP_HLEN) {#endif /* LWIP_IGMP */ LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since there were IP options (while IP_OPTIONS_ALLOWED == 0).\n")); pbuf_free(p); IP_STATS_INC(ip.opterr); IP_STATS_INC(ip.drop); /* unsupported protocol feature */ snmp_inc_ipinunknownprotos(); return ERR_OK; }#endif /* IP_OPTIONS_ALLOWED == 0 */ /* send to upper layers */ LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n")); ip_debug_print(p); LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len)); current_netif = inp; current_header = iphdr;#if LWIP_RAW /* raw input did not eat the packet? */ if (raw_input(p, inp) == 0)#endif /* LWIP_RAW */ { switch (IPH_PROTO(iphdr)) {#if LWIP_UDP case IP_PROTO_UDP:#if LWIP_UDPLITE case IP_PROTO_UDPLITE:#endif /* LWIP_UDPLITE */ snmp_inc_ipindelivers(); udp_input(p, inp); break;#endif /* LWIP_UDP */#if LWIP_TCP case IP_PROTO_TCP: snmp_inc_ipindelivers(); tcp_input(p, inp); break;#endif /* LWIP_TCP */#if LWIP_ICMP case IP_PROTO_ICMP: snmp_inc_ipindelivers(); icmp_input(p, inp); break;#endif /* LWIP_ICMP */#if LWIP_IGMP case IP_PROTO_IGMP: igmp_input(p,inp,&(iphdr->dest)); break;#endif /* LWIP_IGMP */ default:#if LWIP_ICMP /* send ICMP destination protocol unreachable unless is was a broadcast */ if (!ip_addr_isbroadcast(&(iphdr->dest), inp) && !ip_addr_ismulticast(&(iphdr->dest))) { p->payload = iphdr; icmp_dest_unreach(p, ICMP_DUR_PROTO); }#endif /* LWIP_ICMP */ pbuf_free(p); LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Unsupported transport protocol %"U16_F"\n", IPH_PROTO(iphdr))); IP_STATS_INC(ip.proterr); IP_STATS_INC(ip.drop); snmp_inc_ipinunknownprotos(); } } current_netif = NULL; current_header = NULL; return ERR_OK;}/** * Sends an IP packet on a network interface. This function constructs * the IP header and calculates the IP header checksum. If the source * IP address is NULL, the IP address of the outgoing network * interface is filled in as source address. * If the destination IP address is IP_HDRINCL, p is assumed to already * include an IP header and p->payload points to it instead of the data. * * @param p the packet to send (p->payload points to the data, e.g. next protocol header; if dest == IP_HDRINCL, p already includes an IP header and p->payload points to that IP header) * @param src the source IP address to send from (if src == IP_ADDR_ANY, the * IP address of the netif used to send is used as source address) * @param dest the destination IP address to send the packet to * @param ttl the TTL value to be set in the IP header * @param tos the TOS value to be set in the IP header * @param proto the PROTOCOL to be set in the IP header * @param netif the netif on which to send this packet * @return ERR_OK if the packet was sent OK * ERR_BUF if p doesn't have enough space for IP/LINK headers * returns errors returned by netif->output * * @note ip_id: RFC791 "some host may be able to simply use * unique identifiers independent of destination" */err_tip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, u8_t ttl, u8_t tos, u8_t proto, struct netif *netif){#if IP_OPTIONS_SEND return ip_output_if_opt(p, src, dest, ttl, tos, proto, netif, NULL, 0);}/** * Same as ip_output_if() but with the possibility to include IP options: * * @ param ip_options pointer to the IP options, copied into the IP header * @ param optlen length of ip_options */err_t ip_output_if_opt(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, u16_t optlen){#endif /* IP_OPTIONS_SEND */ struct ip_hdr *iphdr; static u16_t ip_id = 0; snmp_inc_ipoutrequests(); /* Should the IP header be generated or is it already included in p? */ if (dest != IP_HDRINCL) { u16_t ip_hlen = IP_HLEN;#if IP_OPTIONS_SEND u16_t optlen_aligned = 0; if (optlen != 0) { /* round up to a multiple of 4 */ optlen_aligned = ((optlen + 3) & ~3); ip_hlen += optlen_aligned; /* First write in the IP options */ if (pbuf_header(p, optlen_aligned)) { LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_output_if_opt: not enough room for IP options in pbuf\n")); IP_STATS_INC(ip.err); snmp_inc_ipoutdiscards(); return ERR_BUF; } MEMCPY(p->payload, ip_options, optlen); if (optlen < optlen_aligned) { /* zero the remaining bytes */ memset(((char*)p->payload) + optlen, 0, optlen_aligned - optlen); } }#endif /* IP_OPTIONS_SEND */ /* generate IP header */ if (pbuf_header(p, IP_HLEN)) { LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_output: not enough room for IP header in pbuf\n")); IP_STATS_INC(ip.err); snmp_inc_ipoutdiscards(); return ERR_BUF; } iphdr = p->payload; LWIP_ASSERT("check that first pbuf can hold struct ip_hdr", (p->len >= sizeof(struct ip_hdr))); IPH_TTL_SET(iphdr, ttl); IPH_PROTO_SET(iphdr, proto); ip_addr_set(&(iphdr->dest), dest); IPH_VHLTOS_SET(iphdr, 4, ip_hlen / 4, tos); IPH_LEN_SET(iphdr, htons(p->tot_len)); IPH_OFFSET_SET(iphdr, 0); IPH_ID_SET(iphdr, htons(ip_id)); ++ip_id; if (ip_addr_isany(src)) { ip_addr_set(&(iphdr->src), &(netif->ip_addr)); } else { ip_addr_set(&(iphdr->src), src); } IPH_CHKSUM_SET(iphdr, 0);#if CHECKSUM_GEN_IP IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, ip_hlen));#endif } else { /* IP header already included in p */ iphdr = p->payload; dest = &(iphdr->dest); } IP_STATS_INC(ip.xmit); LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num)); ip_debug_print(p);#if ENABLE_LOOPBACK if (ip_addr_cmp(dest, &netif->ip_addr)) { /* Packet to self, enqueue it for loopback */ LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()")); return netif_loop_output(netif, p, dest); }#endif /* ENABLE_LOOPBACK */#if IP_FRAG /* don't fragment if interface has mtu set to 0 [loopif] */ if (netif->mtu && (p->tot_len > netif->mtu)) { return ip_frag(p,netif,dest); }#endif LWIP_DEBUGF(IP_DEBUG, ("netif->output()")); return netif->output(netif, p, dest);}/** * Simple interface to ip_output_if. It finds the outgoing network * interface and calls upon ip_output_if to do the actual work. * * @param p the packet to send (p->payload points to the data, e.g. next protocol header; if dest == IP_HDRINCL, p already includes an IP header and p->payload points to that IP header) * @param src the source IP address to send from (if src == IP_ADDR_ANY, the * IP address of the netif used to send is used as source address) * @param dest the destination IP address to send the packet to * @param ttl the TTL value to be set in the IP header * @param tos the TOS value to be set in the IP header * @param proto the PROTOCOL to be set in the IP header * * @return ERR_RTE if no route is found * see ip_output_if() for more return values */err_tip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, u8_t ttl, u8_t tos, u8_t proto){ struct netif *netif; if ((netif = ip_route(dest)) == NULL) { LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to 0x%"X32_F"\n", dest->addr)); IP_STATS_INC(ip.rterr); return ERR_RTE; } return ip_output_if(p, src, dest, ttl, tos, proto, netif);}#if LWIP_NETIF_HWADDRHINT/** Like ip_output, but takes and addr_hint pointer that is passed on to netif->addr_hint * before calling ip_output_if. * * @param p the packet to send (p->payload points to the data, e.g. next protocol header; if dest == IP_HDRINCL, p already includes an IP header and p->payload points to that IP header) * @param src the source IP address to send from (if src == IP_ADDR_ANY, the * IP address of the netif used to send is used as source address) * @param dest the destination IP address to send the packet to * @param ttl the TTL value to be set in the IP header * @param tos the TOS value to be set in the IP header * @param proto the PROTOCOL to be set in the IP header * @param addr_hint address hint pointer set to netif->addr_hint before * calling ip_output_if() * * @return ERR_RTE if no route is found * see ip_output_if() for more return values */err_tip_output_hinted(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint){ struct netif *netif; err_t err; if ((netif = ip_route(dest)) == NULL) { LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to 0x%"X32_F"\n", dest->addr)); IP_STATS_INC(ip.rterr); return ERR_RTE; } netif->addr_hint = addr_hint; err = ip_output_if(p, src, dest, ttl, tos, proto, netif); netif->addr_hint = NULL; return err;}#endif /* LWIP_NETIF_HWADDRHINT*/#if IP_DEBUG/* Print an IP header by using LWIP_DEBUGF * @param p an IP packet, p->payload pointing to the IP header */voidip_debug_print(struct pbuf *p){ struct ip_hdr *iphdr = p->payload; u8_t *payload; payload = (u8_t *)iphdr + IP_HLEN; LWIP_DEBUGF(IP_DEBUG, ("IP header:\n")); LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" |%2"S16_F" | 0x%02"X16_F" | %5"U16_F" | (v, hl, tos, len)\n", IPH_V(iphdr), IPH_HL(iphdr), IPH_TOS(iphdr), ntohs(IPH_LEN(iphdr)))); LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" |%"U16_F"%"U16_F"%"U16_F"| %4"U16_F" | (id, flags, offset)\n", ntohs(IPH_ID(iphdr)), ntohs(IPH_OFFSET(iphdr)) >> 15 & 1, ntohs(IPH_OFFSET(iphdr)) >> 14 & 1, ntohs(IPH_OFFSET(iphdr)) >> 13 & 1, ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)); LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | 0x%04"X16_F" | (ttl, proto, chksum)\n", IPH_TTL(iphdr), IPH_PROTO(iphdr), ntohs(IPH_CHKSUM(iphdr)))); LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (src)\n", ip4_addr1(&iphdr->src), ip4_addr2(&iphdr->src), ip4_addr3(&iphdr->src), ip4_addr4(&iphdr->src))); LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (dest)\n", ip4_addr1(&iphdr->dest), ip4_addr2(&iphdr->dest), ip4_addr3(&iphdr->dest), ip4_addr4(&iphdr->dest))); LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));}#endif /* IP_DEBUG */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -