Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
ip.c
00001 /** 00002 * @file 00003 * This is the IPv4 layer implementation for incoming and outgoing IP traffic. 00004 * 00005 * @see ip_frag.c 00006 * 00007 */ 00008 00009 /* 00010 * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 00011 * All rights reserved. 00012 * 00013 * Redistribution and use in source and binary forms, with or without modification, 00014 * are permitted provided that the following conditions are met: 00015 * 00016 * 1. Redistributions of source code must retain the above copyright notice, 00017 * this list of conditions and the following disclaimer. 00018 * 2. Redistributions in binary form must reproduce the above copyright notice, 00019 * this list of conditions and the following disclaimer in the documentation 00020 * and/or other materials provided with the distribution. 00021 * 3. The name of the author may not be used to endorse or promote products 00022 * derived from this software without specific prior written permission. 00023 * 00024 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00025 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00026 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00027 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00028 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00029 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00030 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00031 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00032 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00033 * OF SUCH DAMAGE. 00034 * 00035 * This file is part of the lwIP TCP/IP stack. 00036 * 00037 * Author: Adam Dunkels <adam@sics.se> 00038 * 00039 */ 00040 00041 #include "lwip/opt.h" 00042 #include "lwip/ip.h" 00043 #include "lwip/def.h" 00044 #include "lwip/mem.h" 00045 #include "lwip/ip_frag.h" 00046 #include "lwip/inet.h" 00047 #include "lwip/inet_chksum.h" 00048 #include "lwip/netif.h" 00049 #include "lwip/icmp.h" 00050 #include "lwip/igmp.h" 00051 #include "lwip/raw.h" 00052 #include "lwip/udp.h" 00053 #include "lwip/tcp.h" 00054 #include "lwip/snmp.h" 00055 #include "lwip/dhcp.h " 00056 #include "lwip/stats.h" 00057 #include "arch/perf.h" 00058 00059 /** 00060 * Finds the appropriate network interface for a given IP address. It 00061 * searches the list of network interfaces linearly. A match is found 00062 * if the masked IP address of the network interface equals the masked 00063 * IP address given to the function. 00064 * 00065 * @param dest the destination IP address for which to find the route 00066 * @return the netif on which to send to reach dest 00067 */ 00068 struct netif * 00069 ip_route(struct ip_addr *dest) 00070 { 00071 struct netif *netif; 00072 00073 /* iterate through netifs */ 00074 for(netif = netif_list; netif != NULL; netif = netif->next) { 00075 /* network mask matches? */ 00076 if (netif_is_up(netif)) { 00077 if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) { 00078 /* return netif on which to forward IP packet */ 00079 return netif; 00080 } 00081 } 00082 } 00083 if ((netif_default == NULL) || (!netif_is_up(netif_default))) { 00084 LWIP_DEBUGF(IP_DEBUG | 2, ("ip_route: No route to 0x%"X32_F"\n", dest->addr)); 00085 IP_STATS_INC(ip.rterr); 00086 snmp_inc_ipoutnoroutes(); 00087 return (struct netif *)(NULL); // static_cast<struct netif *>(x) 00088 } 00089 /* no matching netif found, use default netif */ 00090 return netif_default; 00091 } 00092 00093 #if IP_FORWARD 00094 /** 00095 * Forwards an IP packet. It finds an appropriate route for the 00096 * packet, decrements the TTL value of the packet, adjusts the 00097 * checksum and outputs the packet on the appropriate interface. 00098 * 00099 * @param p the packet to forward (p->payload points to IP header) 00100 * @param iphdr the IP header of the input packet 00101 * @param inp the netif on which this packet was received 00102 * @return the netif on which the packet was sent (NULL if it wasn't sent) 00103 */ 00104 static struct netif * 00105 ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp) 00106 { 00107 struct netif *netif; 00108 00109 PERF_START; 00110 /* Find network interface where to forward this IP packet to. */ 00111 netif = ip_route((struct ip_addr *)&(iphdr->dest)); 00112 if (netif == NULL) { 00113 LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for 0x%"X32_F" found\n", 00114 iphdr->dest.addr)); 00115 snmp_inc_ipoutnoroutes(); 00116 return (struct netif *)NULL; 00117 } 00118 /* Do not forward packets onto the same network interface on which 00119 * they arrived. */ 00120 if (netif == inp) { 00121 LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not bouncing packets back on incoming interface.\n")); 00122 snmp_inc_ipoutnoroutes(); 00123 return (struct netif *)NULL; 00124 } 00125 00126 /* decrement TTL */ 00127 IPH_TTL_SET(iphdr, IPH_TTL(iphdr) - 1); 00128 /* send ICMP if TTL == 0 */ 00129 if (IPH_TTL(iphdr) == 0) { 00130 snmp_inc_ipinhdrerrors(); 00131 #if LWIP_ICMP 00132 /* Don't send ICMP messages in response to ICMP messages */ 00133 if (IPH_PROTO(iphdr) != IP_PROTO_ICMP) { 00134 icmp_time_exceeded(p, ICMP_TE_TTL); 00135 } 00136 #endif /* LWIP_ICMP */ 00137 return (struct netif *)NULL; 00138 } 00139 00140 /* Incrementally update the IP checksum. */ 00141 if (IPH_CHKSUM(iphdr) >= htons(0xffff - 0x100)) { 00142 IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100) + 1); 00143 } else { 00144 IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100)); 00145 } 00146 00147 LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to 0x%"X32_F"\n", 00148 iphdr->dest.addr)); 00149 00150 IP_STATS_INC(ip.fw); 00151 IP_STATS_INC(ip.xmit); 00152 snmp_inc_ipforwdatagrams(); 00153 00154 PERF_STOP("ip_forward"); 00155 /* transmit pbuf on chosen interface */ 00156 netif->output(netif, p, (struct ip_addr *)&(iphdr->dest)); 00157 return netif; 00158 } 00159 #endif /* IP_FORWARD */ 00160 00161 /** 00162 * This function is called by the network interface device driver when 00163 * an IP packet is received. The function does the basic checks of the 00164 * IP header such as packet size being at least larger than the header 00165 * size etc. If the packet was not destined for us, the packet is 00166 * forwarded (using ip_forward). The IP checksum is always checked. 00167 * 00168 * Finally, the packet is sent to the upper layer protocol input function. 00169 * 00170 * @param p the received IP packet (p->payload points to IP header) 00171 * @param inp the netif on which this packet was received 00172 * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't 00173 * processed, but currently always returns ERR_OK) 00174 */ 00175 err_t 00176 ip_input(struct pbuf *p, struct netif *inp) 00177 { 00178 struct ip_hdr *iphdr; 00179 struct netif *netif; 00180 u16_t iphdr_hlen; 00181 u16_t iphdr_len; 00182 #if LWIP_DHCP 00183 int check_ip_src=1; 00184 #endif /* LWIP_DHCP */ 00185 00186 IP_STATS_INC(ip.recv); 00187 snmp_inc_ipinreceives(); 00188 00189 /* identify the IP header */ 00190 iphdr = (struct ip_hdr *)(p->payload); // static_cast<struct ip_hdr *>(x) 00191 if (IPH_V(iphdr) != 4) { 00192 LWIP_DEBUGF(IP_DEBUG | 1, ("IP packet dropped due to bad version number %"U16_F"\n", IPH_V(iphdr))); 00193 ip_debug_print(p); 00194 pbuf_free(p); 00195 IP_STATS_INC(ip.err); 00196 IP_STATS_INC(ip.drop); 00197 snmp_inc_ipinhdrerrors(); 00198 return ERR_OK; 00199 } 00200 00201 /* obtain IP header length in number of 32-bit words */ 00202 iphdr_hlen = IPH_HL(iphdr); 00203 /* calculate IP header length in bytes */ 00204 iphdr_hlen *= 4; 00205 /* obtain ip length in bytes */ 00206 iphdr_len = ntohs(IPH_LEN(iphdr)); 00207 00208 /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */ 00209 if ((iphdr_hlen > p->len) || (iphdr_len > p->tot_len)) { 00210 if (iphdr_hlen > p->len) 00211 LWIP_DEBUGF(IP_DEBUG | 2, ("IP header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n", 00212 iphdr_hlen, p->len)); 00213 if (iphdr_len > p->tot_len) 00214 LWIP_DEBUGF(IP_DEBUG | 2, ("IP (len %"U16_F") is longer than pbuf (len %"U16_F"), " 00215 "IP packet dropped.\n", 00216 iphdr_len, p->tot_len)); 00217 /* free (drop) packet pbufs */ 00218 pbuf_free(p); 00219 IP_STATS_INC(ip.lenerr); 00220 IP_STATS_INC(ip.drop); 00221 snmp_inc_ipindiscards(); 00222 return ERR_OK; 00223 } 00224 00225 /* verify checksum */ 00226 #if CHECKSUM_CHECK_IP 00227 if (inet_chksum(iphdr, iphdr_hlen) != 0) { 00228 00229 LWIP_DEBUGF(IP_DEBUG | 2, ("Checksum (0x%"X16_F") failed, IP packet dropped.\n", inet_chksum(iphdr, iphdr_hlen))); 00230 ip_debug_print(p); 00231 pbuf_free(p); 00232 IP_STATS_INC(ip.chkerr); 00233 IP_STATS_INC(ip.drop); 00234 snmp_inc_ipinhdrerrors(); 00235 return ERR_OK; 00236 } 00237 #endif 00238 00239 /* Trim pbuf. This should have been done at the netif layer, 00240 * but we'll do it anyway just to be sure that its done. */ 00241 pbuf_realloc(p, iphdr_len); 00242 00243 /* match packet against an interface, i.e. is this packet for us? */ 00244 #if LWIP_IGMP 00245 if (ip_addr_ismulticast(&(iphdr->dest))) { 00246 if ((inp->flags & NETIF_FLAG_IGMP) && (igmp_lookfor_group(inp, &(iphdr->dest)))) { 00247 netif = inp; 00248 } else { 00249 netif = NULL; 00250 } 00251 } else 00252 #endif /* LWIP_IGMP */ 00253 { 00254 /* start trying with inp. if that's not acceptable, start walking the 00255 list of configured netifs. 00256 'first' is used as a boolean to mark whether we started walking the list */ 00257 int first = 1; 00258 netif = inp; 00259 do { 00260 LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%"X32_F" netif->ip_addr 0x%"X32_F" (0x%"X32_F", 0x%"X32_F", 0x%"X32_F")\n", 00261 iphdr->dest.addr, netif->ip_addr.addr, 00262 iphdr->dest.addr & netif->netmask.addr, 00263 netif->ip_addr.addr & netif->netmask.addr, 00264 iphdr->dest.addr & ~(netif->netmask.addr))); 00265 00266 /* interface is up and configured? */ 00267 if ((netif_is_up(netif)) && (!ip_addr_isany(&(netif->ip_addr)))) { 00268 /* unicast to this interface address? */ 00269 if (ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr)) || 00270 /* or broadcast on this interface network address? */ 00271 ip_addr_isbroadcast(&(iphdr->dest), netif)) { 00272 LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n", 00273 netif->name[0], netif->name[1])); 00274 /* break out of for loop */ 00275 break; 00276 } 00277 } 00278 if (first) { 00279 first = 0; 00280 netif = netif_list; 00281 } else { 00282 netif = netif->next; 00283 } 00284 if (netif == inp) { 00285 netif = netif->next; 00286 } 00287 } while(netif != NULL); 00288 } 00289 00290 #if LWIP_DHCP 00291 /* Pass DHCP messages regardless of destination address. DHCP traffic is addressed 00292 * using link layer addressing (such as Ethernet MAC) so we must not filter on IP. 00293 * According to RFC 1542 section 3.1.1, referred by RFC 2131). 00294 */ 00295 if (netif == NULL) { 00296 /* remote port is DHCP server? */ 00297 if (IPH_PROTO(iphdr) == IP_PROTO_UDP) { 00298 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | 1, ("ip_input: UDP packet to DHCP client port %"U16_F"\n", 00299 ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen))->dest))); 00300 if (ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen))->dest) == DHCP_CLIENT_PORT) { 00301 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | 1, ("ip_input: DHCP packet accepted.\n")); 00302 netif = inp; 00303 check_ip_src = 0; 00304 } 00305 } 00306 } 00307 #endif /* LWIP_DHCP */ 00308 00309 /* broadcast or multicast packet source address? Compliant with RFC 1122: 3.2.1.3 */ 00310 #if LWIP_DHCP 00311 if (check_ip_src) 00312 #endif /* LWIP_DHCP */ 00313 { if ((ip_addr_isbroadcast(&(iphdr->src), inp)) || 00314 (ip_addr_ismulticast(&(iphdr->src)))) { 00315 /* packet source is not valid */ 00316 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | 1, ("ip_input: packet source is not valid.\n")); 00317 /* free (drop) packet pbufs */ 00318 pbuf_free(p); 00319 IP_STATS_INC(ip.drop); 00320 snmp_inc_ipinaddrerrors(); 00321 snmp_inc_ipindiscards(); 00322 return ERR_OK; 00323 } 00324 } 00325 00326 /* packet not for us? */ 00327 if (netif == NULL) { 00328 /* packet not for us, route or discard */ 00329 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | 1, ("ip_input: packet not for us.\n")); 00330 #if IP_FORWARD 00331 /* non-broadcast packet? */ 00332 if (!ip_addr_isbroadcast(&(iphdr->dest), inp)) { 00333 /* try to forward IP packet on (other) interfaces */ 00334 ip_forward(p, iphdr, inp); 00335 } else 00336 #endif /* IP_FORWARD */ 00337 { 00338 snmp_inc_ipinaddrerrors(); 00339 snmp_inc_ipindiscards(); 00340 } 00341 pbuf_free(p); 00342 return ERR_OK; 00343 } 00344 /* packet consists of multiple fragments? */ 00345 if ((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) { 00346 #if IP_REASSEMBLY /* packet fragment reassembly code present? */ 00347 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", 00348 ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & htons(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8)); 00349 /* reassemble the packet*/ 00350 p = ip_reass(p); 00351 /* packet not fully reassembled yet? */ 00352 if (p == NULL) { 00353 return ERR_OK; 00354 } 00355 iphdr = (struct ip_hdr *)(p->payload); // static_cast<struct ip_hdr *>(x) 00356 #else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */ 00357 pbuf_free(p); 00358 LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n", 00359 ntohs(IPH_OFFSET(iphdr)))); 00360 IP_STATS_INC(ip.opterr); 00361 IP_STATS_INC(ip.drop); 00362 /* unsupported protocol feature */ 00363 snmp_inc_ipinunknownprotos(); 00364 return ERR_OK; 00365 #endif /* IP_REASSEMBLY */ 00366 } 00367 00368 #if IP_OPTIONS_ALLOWED == 0 /* no support for IP options in the IP header? */ 00369 00370 #if LWIP_IGMP 00371 /* there is an extra "router alert" option in IGMP messages which we allow for but do not police */ 00372 if((iphdr_hlen > IP_HLEN && (IPH_PROTO(iphdr) != IP_PROTO_IGMP)) { 00373 #else 00374 if (iphdr_hlen > IP_HLEN) { 00375 #endif /* LWIP_IGMP */ 00376 LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since there were IP options (while IP_OPTIONS_ALLOWED == 0).\n")); 00377 pbuf_free(p); 00378 IP_STATS_INC(ip.opterr); 00379 IP_STATS_INC(ip.drop); 00380 /* unsupported protocol feature */ 00381 snmp_inc_ipinunknownprotos(); 00382 return ERR_OK; 00383 } 00384 #endif /* IP_OPTIONS_ALLOWED == 0 */ 00385 00386 /* send to upper layers */ 00387 LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n")); 00388 ip_debug_print(p); 00389 LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len)); 00390 00391 #if LWIP_RAW 00392 /* raw input did not eat the packet? */ 00393 if (raw_input(p, inp) == 0) 00394 #endif /* LWIP_RAW */ 00395 { 00396 00397 switch (IPH_PROTO(iphdr)) { 00398 #if LWIP_UDP 00399 case IP_PROTO_UDP: 00400 #if LWIP_UDPLITE 00401 case IP_PROTO_UDPLITE: 00402 #endif /* LWIP_UDPLITE */ 00403 snmp_inc_ipindelivers(); 00404 udp_input(p, inp); 00405 break; 00406 #endif /* LWIP_UDP */ 00407 #if LWIP_TCP 00408 case IP_PROTO_TCP: 00409 snmp_inc_ipindelivers(); 00410 tcp_input(p, inp); 00411 break; 00412 #endif /* LWIP_TCP */ 00413 #if LWIP_ICMP 00414 case IP_PROTO_ICMP: 00415 snmp_inc_ipindelivers(); 00416 icmp_input(p, inp); 00417 break; 00418 #endif /* LWIP_ICMP */ 00419 #if LWIP_IGMP 00420 case IP_PROTO_IGMP: 00421 igmp_input(p,inp,&(iphdr->dest)); 00422 break; 00423 #endif /* LWIP_IGMP */ 00424 default: 00425 #if LWIP_ICMP 00426 /* send ICMP destination protocol unreachable unless is was a broadcast */ 00427 if (!ip_addr_isbroadcast(&(iphdr->dest), inp) && 00428 !ip_addr_ismulticast(&(iphdr->dest))) { 00429 p->payload = iphdr; 00430 icmp_dest_unreach(p, ICMP_DUR_PROTO); 00431 } 00432 #endif /* LWIP_ICMP */ 00433 pbuf_free(p); 00434 00435 LWIP_DEBUGF(IP_DEBUG | 2, ("Unsupported transport protocol %"U16_F"\n", IPH_PROTO(iphdr))); 00436 00437 IP_STATS_INC(ip.proterr); 00438 IP_STATS_INC(ip.drop); 00439 snmp_inc_ipinunknownprotos(); 00440 } 00441 } 00442 00443 return ERR_OK; 00444 } 00445 00446 /** 00447 * Sends an IP packet on a network interface. This function constructs 00448 * the IP header and calculates the IP header checksum. If the source 00449 * IP address is NULL, the IP address of the outgoing network 00450 * interface is filled in as source address. 00451 * If the destination IP address is IP_HDRINCL, p is assumed to already 00452 * include an IP header and p->payload points to it instead of the data. 00453 * 00454 * @param p the packet to send (p->payload points to the data, e.g. next 00455 protocol header; if dest == IP_HDRINCL, p already includes an IP 00456 header and p->payload points to that IP header) 00457 * @param src the source IP address to send from (if src == IP_ADDR_ANY, the 00458 * IP address of the netif used to send is used as source address) 00459 * @param dest the destination IP address to send the packet to 00460 * @param ttl the TTL value to be set in the IP header 00461 * @param tos the TOS value to be set in the IP header 00462 * @param proto the PROTOCOL to be set in the IP header 00463 * @param netif the netif on which to send this packet 00464 * @return ERR_OK if the packet was sent OK 00465 * ERR_BUF if p doesn't have enough space for IP/LINK headers 00466 * returns errors returned by netif->output 00467 * 00468 * @note ip_id: RFC791 "some host may be able to simply use 00469 * unique identifiers independent of destination" 00470 */ 00471 err_t 00472 ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, 00473 u8_t ttl, u8_t tos, 00474 u8_t proto, struct netif *netif) 00475 { 00476 struct ip_hdr *iphdr; 00477 static u16_t ip_id = 0; 00478 00479 snmp_inc_ipoutrequests(); 00480 00481 /* Should the IP header be generated or is it already included in p? */ 00482 if (dest != IP_HDRINCL) { 00483 /* generate IP header */ 00484 if (pbuf_header(p, IP_HLEN)) { 00485 LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: not enough room for IP header in pbuf\n")); 00486 00487 IP_STATS_INC(ip.err); 00488 snmp_inc_ipoutdiscards(); 00489 return ERR_BUF; 00490 } 00491 00492 iphdr = (struct ip_hdr *)(p->payload); // static_cast<struct ip_hdr *>(x) 00493 LWIP_ASSERT("check that first pbuf can hold struct ip_hdr", 00494 (p->len >= sizeof(struct ip_hdr))); 00495 00496 IPH_TTL_SET(iphdr, ttl); 00497 IPH_PROTO_SET(iphdr, proto); 00498 00499 ip_addr_set(&(iphdr->dest), dest); 00500 00501 IPH_VHLTOS_SET(iphdr, 4, IP_HLEN / 4, tos); 00502 IPH_LEN_SET(iphdr, htons(p->tot_len)); 00503 IPH_OFFSET_SET(iphdr, 0); 00504 IPH_ID_SET(iphdr, htons(ip_id)); 00505 ++ip_id; 00506 00507 if (ip_addr_isany(src)) { 00508 ip_addr_set(&(iphdr->src), &(netif->ip_addr)); 00509 } else { 00510 ip_addr_set(&(iphdr->src), src); 00511 } 00512 00513 IPH_CHKSUM_SET(iphdr, 0); 00514 #if CHECKSUM_GEN_IP 00515 IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN)); 00516 #endif 00517 } else { 00518 /* IP header already included in p */ 00519 iphdr = (struct ip_hdr *)(p->payload); // static_cast<struct ip_hdr *>(x) 00520 struct ip_addr dest_addr; 00521 dest_addr.addr = iphdr->dest.addr; 00522 dest = &dest_addr; 00523 } 00524 00525 #if IP_FRAG 00526 /* don't fragment if interface has mtu set to 0 [loopif] */ 00527 if (netif->mtu && (p->tot_len > netif->mtu)) 00528 return ip_frag(p,netif,dest); 00529 #endif 00530 00531 IP_STATS_INC(ip.xmit); 00532 00533 LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num)); 00534 ip_debug_print(p); 00535 00536 #if (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF) 00537 if (ip_addr_cmp(dest, &netif->ip_addr)) { 00538 /* Packet to self, enqueue it for loopback */ 00539 LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()")); 00540 00541 return netif_loop_output(netif, p, dest); 00542 } else 00543 #endif /* (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF) */ 00544 { 00545 LWIP_DEBUGF(IP_DEBUG, ("netif->output()")); 00546 00547 return netif->output(netif, p, dest); 00548 } 00549 } 00550 00551 /** 00552 * Simple interface to ip_output_if. It finds the outgoing network 00553 * interface and calls upon ip_output_if to do the actual work. 00554 * 00555 * @param p the packet to send (p->payload points to the data, e.g. next 00556 protocol header; if dest == IP_HDRINCL, p already includes an IP 00557 header and p->payload points to that IP header) 00558 * @param src the source IP address to send from (if src == IP_ADDR_ANY, the 00559 * IP address of the netif used to send is used as source address) 00560 * @param dest the destination IP address to send the packet to 00561 * @param ttl the TTL value to be set in the IP header 00562 * @param tos the TOS value to be set in the IP header 00563 * @param proto the PROTOCOL to be set in the IP header 00564 * 00565 * @return ERR_RTE if no route is found 00566 * see ip_output_if() for more return values 00567 */ 00568 err_t 00569 ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, 00570 u8_t ttl, u8_t tos, u8_t proto) 00571 { 00572 struct netif *netif; 00573 00574 if ((netif = ip_route(dest)) == NULL) { 00575 LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to 0x%"X32_F"\n", dest->addr)); 00576 IP_STATS_INC(ip.rterr); 00577 return ERR_RTE; 00578 } 00579 00580 return ip_output_if(p, src, dest, ttl, tos, proto, netif); 00581 } 00582 00583 #if LWIP_NETIF_HWADDRHINT 00584 /** Like ip_output, but takes and addr_hint pointer that is passed on to netif->addr_hint 00585 * before calling ip_output_if. 00586 * 00587 * @param p the packet to send (p->payload points to the data, e.g. next 00588 protocol header; if dest == IP_HDRINCL, p already includes an IP 00589 header and p->payload points to that IP header) 00590 * @param src the source IP address to send from (if src == IP_ADDR_ANY, the 00591 * IP address of the netif used to send is used as source address) 00592 * @param dest the destination IP address to send the packet to 00593 * @param ttl the TTL value to be set in the IP header 00594 * @param tos the TOS value to be set in the IP header 00595 * @param proto the PROTOCOL to be set in the IP header 00596 * @param addr_hint address hint pointer set to netif->addr_hint before 00597 * calling ip_output_if() 00598 * 00599 * @return ERR_RTE if no route is found 00600 * see ip_output_if() for more return values 00601 */ 00602 err_t 00603 ip_output_hinted(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, 00604 u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint) 00605 { 00606 struct netif *netif; 00607 err_t err; 00608 00609 if ((netif = ip_route(dest)) == NULL) { 00610 LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to 0x%"X32_F"\n", dest->addr)); 00611 IP_STATS_INC(ip.rterr); 00612 return ERR_RTE; 00613 } 00614 00615 netif->addr_hint = addr_hint; 00616 err = ip_output_if(p, src, dest, ttl, tos, proto, netif); 00617 netif->addr_hint = NULL; 00618 00619 return err; 00620 } 00621 #endif /* LWIP_NETIF_HWADDRHINT*/ 00622 00623 #if IP_DEBUG 00624 /* Print an IP header by using LWIP_DEBUGF 00625 * @param p an IP packet, p->payload pointing to the IP header 00626 */ 00627 void 00628 ip_debug_print(struct pbuf *p) 00629 { 00630 struct ip_hdr *iphdr = (struct ip_hdr *)p->payload; // static_cast<struct ip_hdr *>(x) 00631 u8_t *payload; 00632 00633 payload = (u8_t *)iphdr + IP_HLEN; 00634 00635 LWIP_DEBUGF(IP_DEBUG, ("IP header:\n")); 00636 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); 00637 LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" |%2"S16_F" | 0x%02"X16_F" | %5"U16_F" | (v, hl, tos, len)\n", 00638 IPH_V(iphdr), 00639 IPH_HL(iphdr), 00640 IPH_TOS(iphdr), 00641 ntohs(IPH_LEN(iphdr)))); 00642 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); 00643 LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" |%"U16_F"%"U16_F"%"U16_F"| %4"U16_F" | (id, flags, offset)\n", 00644 ntohs(IPH_ID(iphdr)), 00645 ntohs(IPH_OFFSET(iphdr)) >> 15 & 1, 00646 ntohs(IPH_OFFSET(iphdr)) >> 14 & 1, 00647 ntohs(IPH_OFFSET(iphdr)) >> 13 & 1, 00648 ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)); 00649 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); 00650 LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | 0x%04"X16_F" | (ttl, proto, chksum)\n", 00651 IPH_TTL(iphdr), 00652 IPH_PROTO(iphdr), 00653 ntohs(IPH_CHKSUM(iphdr)))); 00654 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); 00655 LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (src)\n", 00656 ip4_addr1(&iphdr->src), 00657 ip4_addr2(&iphdr->src), 00658 ip4_addr3(&iphdr->src), 00659 ip4_addr4(&iphdr->src))); 00660 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); 00661 LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (dest)\n", 00662 ip4_addr1(&iphdr->dest), 00663 ip4_addr2(&iphdr->dest), 00664 ip4_addr3(&iphdr->dest), 00665 ip4_addr4(&iphdr->dest))); 00666 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); 00667 } 00668 #endif /* IP_DEBUG */
Generated on Tue Jul 12 2022 19:24:05 by
1.7.2