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_chksum.h" 00047 #include "lwip/netif.h" 00048 #include "lwip/icmp.h" 00049 #include "lwip/igmp.h" 00050 #include "lwip/raw.h" 00051 #include "lwip/udp.h" 00052 #include "lwip/tcp_impl.h" 00053 #include "lwip/snmp.h" 00054 #include "lwip/dhcp.h " 00055 #include "lwip/autoip.h" 00056 #include "lwip/stats.h" 00057 #include "arch/perf.h" 00058 00059 #include <string.h> 00060 00061 /** 00062 * The interface that provided the packet for the current callback 00063 * invocation. 00064 */ 00065 struct netif *current_netif; 00066 00067 /** 00068 * Header of the input packet currently being processed. 00069 */ 00070 const struct ip_hdr *current_header; 00071 00072 /** 00073 * Finds the appropriate network interface for a given IP address. It 00074 * searches the list of network interfaces linearly. A match is found 00075 * if the masked IP address of the network interface equals the masked 00076 * IP address given to the function. 00077 * 00078 * @param dest the destination IP address for which to find the route 00079 * @return the netif on which to send to reach dest 00080 */ 00081 struct netif * 00082 ip_route(ip_addr_t *dest) 00083 { 00084 struct netif *netif; 00085 00086 /* iterate through netifs */ 00087 for(netif = netif_list; netif != NULL; netif = netif->next) { 00088 /* network mask matches? */ 00089 if (netif_is_up(netif)) { 00090 if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) { 00091 /* return netif on which to forward IP packet */ 00092 return netif; 00093 } 00094 } 00095 } 00096 if ((netif_default == NULL) || (!netif_is_up(netif_default))) { 00097 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_route: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", 00098 ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); 00099 IP_STATS_INC(ip.rterr); 00100 snmp_inc_ipoutnoroutes(); 00101 return NULL; 00102 } 00103 /* no matching netif found, use default netif */ 00104 return netif_default; 00105 } 00106 00107 #if IP_FORWARD 00108 /** 00109 * Forwards an IP packet. It finds an appropriate route for the 00110 * packet, decrements the TTL value of the packet, adjusts the 00111 * checksum and outputs the packet on the appropriate interface. 00112 * 00113 * @param p the packet to forward (p->payload points to IP header) 00114 * @param iphdr the IP header of the input packet 00115 * @param inp the netif on which this packet was received 00116 * @return the netif on which the packet was sent (NULL if it wasn't sent) 00117 */ 00118 static struct netif * 00119 ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp) 00120 { 00121 struct netif *netif; 00122 ip_addr_t dest; 00123 00124 PERF_START; 00125 dest = iphdr->dest; 00126 00127 /* RFC3927 2.7: do not forward link-local addresses */ 00128 if (ip_addr_islinklocal(&dest)) { 00129 LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not forwarding LLA %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", 00130 ip4_addr1_16(&dest), ip4_addr2_16(&dest), ip4_addr3_16(&dest), ip4_addr4_16(&dest))); 00131 snmp_inc_ipoutnoroutes(); 00132 return (struct netif *)NULL; 00133 } 00134 00135 /* Find network interface where to forward this IP packet to. */ 00136 netif = ip_route(&dest); 00137 if (netif == NULL) { 00138 LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for %"U16_F".%"U16_F".%"U16_F".%"U16_F" found\n", 00139 ip4_addr1_16(&dest), ip4_addr2_16(&dest), ip4_addr3_16(&dest), ip4_addr4_16(&dest))); 00140 snmp_inc_ipoutnoroutes(); 00141 return (struct netif *)NULL; 00142 } 00143 /* Do not forward packets onto the same network interface on which 00144 * they arrived. */ 00145 if (netif == inp) { 00146 LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not bouncing packets back on incoming interface.\n")); 00147 snmp_inc_ipoutnoroutes(); 00148 return (struct netif *)NULL; 00149 } 00150 00151 /* decrement TTL */ 00152 IPH_TTL_SET(iphdr, IPH_TTL(iphdr) - 1); 00153 /* send ICMP if TTL == 0 */ 00154 if (IPH_TTL(iphdr) == 0) { 00155 snmp_inc_ipinhdrerrors(); 00156 #if LWIP_ICMP 00157 /* Don't send ICMP messages in response to ICMP messages */ 00158 if (IPH_PROTO(iphdr) != IP_PROTO_ICMP) { 00159 icmp_time_exceeded(p, ICMP_TE_TTL); 00160 } 00161 #endif /* LWIP_ICMP */ 00162 return (struct netif *)NULL; 00163 } 00164 00165 /* Incrementally update the IP checksum. */ 00166 if (IPH_CHKSUM(iphdr) >= htons(0xffff - 0x100)) { 00167 IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100) + 1); 00168 } else { 00169 IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100)); 00170 } 00171 00172 LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", 00173 ip4_addr1_16(&dest), ip4_addr2_16(&dest), ip4_addr3_16(&dest), ip4_addr4_16(&dest))); 00174 00175 IP_STATS_INC(ip.fw); 00176 IP_STATS_INC(ip.xmit); 00177 snmp_inc_ipforwdatagrams(); 00178 00179 PERF_STOP("ip_forward"); 00180 /* transmit pbuf on chosen interface */ 00181 netif->output(netif, p, &dest); 00182 return netif; 00183 } 00184 #endif /* IP_FORWARD */ 00185 00186 /** 00187 * This function is called by the network interface device driver when 00188 * an IP packet is received. The function does the basic checks of the 00189 * IP header such as packet size being at least larger than the header 00190 * size etc. If the packet was not destined for us, the packet is 00191 * forwarded (using ip_forward). The IP checksum is always checked. 00192 * 00193 * Finally, the packet is sent to the upper layer protocol input function. 00194 * 00195 * @param p the received IP packet (p->payload points to IP header) 00196 * @param inp the netif on which this packet was received 00197 * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't 00198 * processed, but currently always returns ERR_OK) 00199 */ 00200 err_t 00201 ip_input(struct pbuf *p, struct netif *inp) 00202 { 00203 struct ip_hdr *iphdr; 00204 struct netif *netif; 00205 u16_t iphdr_hlen; 00206 u16_t iphdr_len; 00207 #if LWIP_DHCP 00208 int check_ip_src=1; 00209 #endif /* LWIP_DHCP */ 00210 00211 IP_STATS_INC(ip.recv); 00212 snmp_inc_ipinreceives(); 00213 00214 /* identify the IP header */ 00215 iphdr = (struct ip_hdr *)p->payload; 00216 if (IPH_V(iphdr) != 4) { 00217 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IP packet dropped due to bad version number %"U16_F"\n", IPH_V(iphdr))); 00218 ip_debug_print(p); 00219 pbuf_free(p); 00220 IP_STATS_INC(ip.err); 00221 IP_STATS_INC(ip.drop); 00222 snmp_inc_ipinhdrerrors(); 00223 return ERR_OK; 00224 } 00225 00226 /* obtain IP header length in number of 32-bit words */ 00227 iphdr_hlen = IPH_HL(iphdr); 00228 /* calculate IP header length in bytes */ 00229 iphdr_hlen *= 4; 00230 /* obtain ip length in bytes */ 00231 iphdr_len = ntohs(IPH_LEN(iphdr)); 00232 00233 /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */ 00234 if ((iphdr_hlen > p->len) || (iphdr_len > p->tot_len)) { 00235 if (iphdr_hlen > p->len) { 00236 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, 00237 ("IP header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n", 00238 iphdr_hlen, p->len)); 00239 } 00240 if (iphdr_len > p->tot_len) { 00241 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, 00242 ("IP (len %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n", 00243 iphdr_len, p->tot_len)); 00244 } 00245 /* free (drop) packet pbufs */ 00246 pbuf_free(p); 00247 IP_STATS_INC(ip.lenerr); 00248 IP_STATS_INC(ip.drop); 00249 snmp_inc_ipindiscards(); 00250 return ERR_OK; 00251 } 00252 00253 /* verify checksum */ 00254 #if CHECKSUM_CHECK_IP 00255 if (inet_chksum(iphdr, iphdr_hlen) != 0) { 00256 00257 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, 00258 ("Checksum (0x%"X16_F") failed, IP packet dropped.\n", inet_chksum(iphdr, iphdr_hlen))); 00259 ip_debug_print(p); 00260 pbuf_free(p); 00261 IP_STATS_INC(ip.chkerr); 00262 IP_STATS_INC(ip.drop); 00263 snmp_inc_ipinhdrerrors(); 00264 return ERR_OK; 00265 } 00266 #endif 00267 00268 /* Trim pbuf. This should have been done at the netif layer, 00269 * but we'll do it anyway just to be sure that its done. */ 00270 pbuf_realloc(p, iphdr_len); 00271 00272 /* match packet against an interface, i.e. is this packet for us? */ 00273 #if LWIP_IGMP 00274 if (ip_addr_ismulticast(&(iphdr->dest))) { 00275 if ((inp->flags & NETIF_FLAG_IGMP) && (igmp_lookfor_group(inp, &(iphdr->dest)))) { 00276 netif = inp; 00277 } else { 00278 netif = NULL; 00279 } 00280 } else 00281 #endif /* LWIP_IGMP */ 00282 { 00283 /* start trying with inp. if that's not acceptable, start walking the 00284 list of configured netifs. 00285 'first' is used as a boolean to mark whether we started walking the list */ 00286 int first = 1; 00287 netif = inp; 00288 do { 00289 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", 00290 ip4_addr_get_u32(&iphdr->dest), ip4_addr_get_u32(&netif->ip_addr), 00291 ip4_addr_get_u32(&iphdr->dest) & ip4_addr_get_u32(&netif->netmask), 00292 ip4_addr_get_u32(&netif->ip_addr) & ip4_addr_get_u32(&netif->netmask), 00293 ip4_addr_get_u32(&iphdr->dest) & ~ip4_addr_get_u32(&netif->netmask))); 00294 00295 /* interface is up and configured? */ 00296 if ((netif_is_up(netif)) && (!ip_addr_isany(&(netif->ip_addr)))) { 00297 /* unicast to this interface address? */ 00298 if (ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr)) || 00299 /* or broadcast on this interface network address? */ 00300 ip_addr_isbroadcast(&(iphdr->dest), netif)) { 00301 LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n", 00302 netif->name[0], netif->name[1])); 00303 /* break out of for loop */ 00304 break; 00305 } 00306 #if LWIP_AUTOIP 00307 /* connections to link-local addresses must persist after changing 00308 the netif's address (RFC3927 ch. 1.9) */ 00309 if ((netif->autoip != NULL) && 00310 ip_addr_cmp(&(iphdr->dest), &(netif->autoip->llipaddr))) { 00311 LWIP_DEBUGF(IP_DEBUG, ("ip_input: LLA packet accepted on interface %c%c\n", 00312 netif->name[0], netif->name[1])); 00313 /* break out of for loop */ 00314 break; 00315 } 00316 #endif /* LWIP_AUTOIP */ 00317 } 00318 if (first) { 00319 first = 0; 00320 netif = netif_list; 00321 } else { 00322 netif = netif->next; 00323 } 00324 if (netif == inp) { 00325 netif = netif->next; 00326 } 00327 } while(netif != NULL); 00328 } 00329 00330 #if LWIP_DHCP 00331 /* Pass DHCP messages regardless of destination address. DHCP traffic is addressed 00332 * using link layer addressing (such as Ethernet MAC) so we must not filter on IP. 00333 * According to RFC 1542 section 3.1.1, referred by RFC 2131). 00334 */ 00335 if (netif == NULL) { 00336 /* remote port is DHCP server? */ 00337 if (IPH_PROTO(iphdr) == IP_PROTO_UDP) { 00338 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: UDP packet to DHCP client port %"U16_F"\n", 00339 ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen))->dest))); 00340 if (ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen))->dest) == DHCP_CLIENT_PORT) { 00341 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: DHCP packet accepted.\n")); 00342 netif = inp; 00343 check_ip_src = 0; 00344 } 00345 } 00346 } 00347 #endif /* LWIP_DHCP */ 00348 00349 /* broadcast or multicast packet source address? Compliant with RFC 1122: 3.2.1.3 */ 00350 #if LWIP_DHCP 00351 /* DHCP servers need 0.0.0.0 to be allowed as source address (RFC 1.1.2.2: 3.2.1.3/a) */ 00352 if (check_ip_src && !ip_addr_isany(&iphdr->src)) 00353 #endif /* LWIP_DHCP */ 00354 { if ((ip_addr_isbroadcast(&(iphdr->src), inp)) || 00355 (ip_addr_ismulticast(&(iphdr->src)))) { 00356 /* packet source is not valid */ 00357 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("ip_input: packet source is not valid.\n")); 00358 /* free (drop) packet pbufs */ 00359 pbuf_free(p); 00360 IP_STATS_INC(ip.drop); 00361 snmp_inc_ipinaddrerrors(); 00362 snmp_inc_ipindiscards(); 00363 return ERR_OK; 00364 } 00365 } 00366 00367 /* packet not for us? */ 00368 if (netif == NULL) { 00369 /* packet not for us, route or discard */ 00370 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: packet not for us.\n")); 00371 #if IP_FORWARD 00372 /* non-broadcast packet? */ 00373 if (!ip_addr_isbroadcast(&(iphdr->dest), inp)) { 00374 /* try to forward IP packet on (other) interfaces */ 00375 ip_forward(p, iphdr, inp); 00376 } else 00377 #endif /* IP_FORWARD */ 00378 { 00379 snmp_inc_ipinaddrerrors(); 00380 snmp_inc_ipindiscards(); 00381 } 00382 pbuf_free(p); 00383 return ERR_OK; 00384 } 00385 /* packet consists of multiple fragments? */ 00386 if ((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) { 00387 #if IP_REASSEMBLY /* packet fragment reassembly code present? */ 00388 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", 00389 ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & htons(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8)); 00390 /* reassemble the packet*/ 00391 p = ip_reass(p); 00392 /* packet not fully reassembled yet? */ 00393 if (p == NULL) { 00394 return ERR_OK; 00395 } 00396 iphdr = (struct ip_hdr *)p->payload; 00397 #else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */ 00398 pbuf_free(p); 00399 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n", 00400 ntohs(IPH_OFFSET(iphdr)))); 00401 IP_STATS_INC(ip.opterr); 00402 IP_STATS_INC(ip.drop); 00403 /* unsupported protocol feature */ 00404 snmp_inc_ipinunknownprotos(); 00405 return ERR_OK; 00406 #endif /* IP_REASSEMBLY */ 00407 } 00408 00409 #if IP_OPTIONS_ALLOWED == 0 /* no support for IP options in the IP header? */ 00410 00411 #if LWIP_IGMP 00412 /* there is an extra "router alert" option in IGMP messages which we allow for but do not police */ 00413 if((iphdr_hlen > IP_HLEN) && (IPH_PROTO(iphdr) != IP_PROTO_IGMP)) { 00414 #else 00415 if (iphdr_hlen > IP_HLEN) { 00416 #endif /* LWIP_IGMP */ 00417 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since there were IP options (while IP_OPTIONS_ALLOWED == 0).\n")); 00418 pbuf_free(p); 00419 IP_STATS_INC(ip.opterr); 00420 IP_STATS_INC(ip.drop); 00421 /* unsupported protocol feature */ 00422 snmp_inc_ipinunknownprotos(); 00423 return ERR_OK; 00424 } 00425 #endif /* IP_OPTIONS_ALLOWED == 0 */ 00426 00427 /* send to upper layers */ 00428 LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n")); 00429 ip_debug_print(p); 00430 LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len)); 00431 00432 current_netif = inp; 00433 current_header = iphdr; 00434 00435 #if LWIP_RAW 00436 /* raw input did not eat the packet? */ 00437 if (raw_input(p, inp) == 0) 00438 #endif /* LWIP_RAW */ 00439 { 00440 00441 switch (IPH_PROTO(iphdr)) { 00442 #if LWIP_UDP 00443 case IP_PROTO_UDP: 00444 #if LWIP_UDPLITE 00445 case IP_PROTO_UDPLITE: 00446 #endif /* LWIP_UDPLITE */ 00447 snmp_inc_ipindelivers(); 00448 udp_input(p, inp); 00449 break; 00450 #endif /* LWIP_UDP */ 00451 #if LWIP_TCP 00452 case IP_PROTO_TCP: 00453 snmp_inc_ipindelivers(); 00454 tcp_input(p, inp); 00455 break; 00456 #endif /* LWIP_TCP */ 00457 #if LWIP_ICMP 00458 case IP_PROTO_ICMP: 00459 snmp_inc_ipindelivers(); 00460 icmp_input(p, inp); 00461 break; 00462 #endif /* LWIP_ICMP */ 00463 #if LWIP_IGMP 00464 case IP_PROTO_IGMP: 00465 igmp_input(p,inp,&(iphdr->dest)); 00466 break; 00467 #endif /* LWIP_IGMP */ 00468 default: 00469 #if LWIP_ICMP 00470 /* send ICMP destination protocol unreachable unless is was a broadcast */ 00471 if (!ip_addr_isbroadcast(&(iphdr->dest), inp) && 00472 !ip_addr_ismulticast(&(iphdr->dest))) { 00473 p->payload = iphdr; 00474 icmp_dest_unreach(p, ICMP_DUR_PROTO); 00475 } 00476 #endif /* LWIP_ICMP */ 00477 pbuf_free(p); 00478 00479 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Unsupported transport protocol %"U16_F"\n", IPH_PROTO(iphdr))); 00480 00481 IP_STATS_INC(ip.proterr); 00482 IP_STATS_INC(ip.drop); 00483 snmp_inc_ipinunknownprotos(); 00484 } 00485 } 00486 00487 current_netif = NULL; 00488 current_header = NULL; 00489 00490 return ERR_OK; 00491 } 00492 00493 /** 00494 * Sends an IP packet on a network interface. This function constructs 00495 * the IP header and calculates the IP header checksum. If the source 00496 * IP address is NULL, the IP address of the outgoing network 00497 * interface is filled in as source address. 00498 * If the destination IP address is IP_HDRINCL, p is assumed to already 00499 * include an IP header and p->payload points to it instead of the data. 00500 * 00501 * @param p the packet to send (p->payload points to the data, e.g. next 00502 protocol header; if dest == IP_HDRINCL, p already includes an IP 00503 header and p->payload points to that IP header) 00504 * @param src the source IP address to send from (if src == IP_ADDR_ANY, the 00505 * IP address of the netif used to send is used as source address) 00506 * @param dest the destination IP address to send the packet to 00507 * @param ttl the TTL value to be set in the IP header 00508 * @param tos the TOS value to be set in the IP header 00509 * @param proto the PROTOCOL to be set in the IP header 00510 * @param netif the netif on which to send this packet 00511 * @return ERR_OK if the packet was sent OK 00512 * ERR_BUF if p doesn't have enough space for IP/LINK headers 00513 * returns errors returned by netif->output 00514 * 00515 * @note ip_id: RFC791 "some host may be able to simply use 00516 * unique identifiers independent of destination" 00517 */ 00518 err_t 00519 ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, 00520 u8_t ttl, u8_t tos, 00521 u8_t proto, struct netif *netif) 00522 { 00523 #if IP_OPTIONS_SEND 00524 return ip_output_if_opt(p, src, dest, ttl, tos, proto, netif, NULL, 0); 00525 } 00526 00527 /** 00528 * Same as ip_output_if() but with the possibility to include IP options: 00529 * 00530 * @ param ip_options pointer to the IP options, copied into the IP header 00531 * @ param optlen length of ip_options 00532 */ 00533 err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, 00534 u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, 00535 u16_t optlen) 00536 { 00537 #endif /* IP_OPTIONS_SEND */ 00538 struct ip_hdr *iphdr; 00539 static u16_t ip_id = 0; 00540 00541 /* pbufs passed to IP must have a ref-count of 1 as their payload pointer 00542 gets altered as the packet is passed down the stack */ 00543 LWIP_ASSERT("p->ref == 1", p->ref == 1); 00544 00545 snmp_inc_ipoutrequests(); 00546 00547 /* Should the IP header be generated or is it already included in p? */ 00548 if (dest != IP_HDRINCL) { 00549 u16_t ip_hlen = IP_HLEN; 00550 #if IP_OPTIONS_SEND 00551 u16_t optlen_aligned = 0; 00552 if (optlen != 0) { 00553 /* round up to a multiple of 4 */ 00554 optlen_aligned = ((optlen + 3) & ~3); 00555 ip_hlen += optlen_aligned; 00556 /* First write in the IP options */ 00557 if (pbuf_header(p, optlen_aligned)) { 00558 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_output_if_opt: not enough room for IP options in pbuf\n")); 00559 IP_STATS_INC(ip.err); 00560 snmp_inc_ipoutdiscards(); 00561 return ERR_BUF; 00562 } 00563 MEMCPY(p->payload, ip_options, optlen); 00564 if (optlen < optlen_aligned) { 00565 /* zero the remaining bytes */ 00566 memset(((char*)p->payload) + optlen, 0, optlen_aligned - optlen); 00567 } 00568 } 00569 #endif /* IP_OPTIONS_SEND */ 00570 /* generate IP header */ 00571 if (pbuf_header(p, IP_HLEN)) { 00572 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_output: not enough room for IP header in pbuf\n")); 00573 00574 IP_STATS_INC(ip.err); 00575 snmp_inc_ipoutdiscards(); 00576 return ERR_BUF; 00577 } 00578 00579 iphdr = (struct ip_hdr *)p->payload; 00580 LWIP_ASSERT("check that first pbuf can hold struct ip_hdr", 00581 (p->len >= sizeof(struct ip_hdr))); 00582 00583 IPH_TTL_SET(iphdr, ttl); 00584 IPH_PROTO_SET(iphdr, proto); 00585 00586 /* dest cannot be NULL here */ 00587 ip_addr_copy(iphdr->dest, *dest); 00588 00589 IPH_VHLTOS_SET(iphdr, 4, ip_hlen / 4, tos); 00590 IPH_LEN_SET(iphdr, htons(p->tot_len)); 00591 IPH_OFFSET_SET(iphdr, 0); 00592 IPH_ID_SET(iphdr, htons(ip_id)); 00593 ++ip_id; 00594 00595 if (ip_addr_isany(src)) { 00596 ip_addr_copy(iphdr->src, netif->ip_addr); 00597 } else { 00598 /* src cannot be NULL here */ 00599 ip_addr_copy(iphdr->src, *src); 00600 } 00601 00602 IPH_CHKSUM_SET(iphdr, 0); 00603 #if CHECKSUM_GEN_IP 00604 IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, ip_hlen)); 00605 #endif 00606 } else { 00607 /* IP header already included in p */ 00608 iphdr = (struct ip_hdr *)p->payload; 00609 dest = &(iphdr->dest); 00610 } 00611 00612 IP_STATS_INC(ip.xmit); 00613 00614 LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num)); 00615 ip_debug_print(p); 00616 00617 #if ENABLE_LOOPBACK 00618 if (ip_addr_cmp(dest, &netif->ip_addr)) { 00619 /* Packet to self, enqueue it for loopback */ 00620 LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()")); 00621 return netif_loop_output(netif, p, dest); 00622 } 00623 #endif /* ENABLE_LOOPBACK */ 00624 #if IP_FRAG 00625 /* don't fragment if interface has mtu set to 0 [loopif] */ 00626 if (netif->mtu && (p->tot_len > netif->mtu)) { 00627 return ip_frag(p,netif,dest); 00628 } 00629 #endif 00630 00631 LWIP_DEBUGF(IP_DEBUG, ("netif->output()")); 00632 return netif->output(netif, p, dest); 00633 } 00634 00635 /** 00636 * Simple interface to ip_output_if. It finds the outgoing network 00637 * interface and calls upon ip_output_if to do the actual work. 00638 * 00639 * @param p the packet to send (p->payload points to the data, e.g. next 00640 protocol header; if dest == IP_HDRINCL, p already includes an IP 00641 header and p->payload points to that IP header) 00642 * @param src the source IP address to send from (if src == IP_ADDR_ANY, the 00643 * IP address of the netif used to send is used as source address) 00644 * @param dest the destination IP address to send the packet to 00645 * @param ttl the TTL value to be set in the IP header 00646 * @param tos the TOS value to be set in the IP header 00647 * @param proto the PROTOCOL to be set in the IP header 00648 * 00649 * @return ERR_RTE if no route is found 00650 * see ip_output_if() for more return values 00651 */ 00652 err_t 00653 ip_output(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, 00654 u8_t ttl, u8_t tos, u8_t proto) 00655 { 00656 struct netif *netif; 00657 00658 /* pbufs passed to IP must have a ref-count of 1 as their payload pointer 00659 gets altered as the packet is passed down the stack */ 00660 LWIP_ASSERT("p->ref == 1", p->ref == 1); 00661 00662 if ((netif = ip_route(dest)) == NULL) { 00663 LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", 00664 ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); 00665 IP_STATS_INC(ip.rterr); 00666 return ERR_RTE; 00667 } 00668 00669 return ip_output_if(p, src, dest, ttl, tos, proto, netif); 00670 } 00671 00672 #if LWIP_NETIF_HWADDRHINT 00673 /** Like ip_output, but takes and addr_hint pointer that is passed on to netif->addr_hint 00674 * before calling ip_output_if. 00675 * 00676 * @param p the packet to send (p->payload points to the data, e.g. next 00677 protocol header; if dest == IP_HDRINCL, p already includes an IP 00678 header and p->payload points to that IP header) 00679 * @param src the source IP address to send from (if src == IP_ADDR_ANY, the 00680 * IP address of the netif used to send is used as source address) 00681 * @param dest the destination IP address to send the packet to 00682 * @param ttl the TTL value to be set in the IP header 00683 * @param tos the TOS value to be set in the IP header 00684 * @param proto the PROTOCOL to be set in the IP header 00685 * @param addr_hint address hint pointer set to netif->addr_hint before 00686 * calling ip_output_if() 00687 * 00688 * @return ERR_RTE if no route is found 00689 * see ip_output_if() for more return values 00690 */ 00691 err_t 00692 ip_output_hinted(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, 00693 u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint) 00694 { 00695 struct netif *netif; 00696 err_t err; 00697 00698 /* pbufs passed to IP must have a ref-count of 1 as their payload pointer 00699 gets altered as the packet is passed down the stack */ 00700 LWIP_ASSERT("p->ref == 1", p->ref == 1); 00701 00702 if ((netif = ip_route(dest)) == NULL) { 00703 LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", 00704 ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); 00705 IP_STATS_INC(ip.rterr); 00706 return ERR_RTE; 00707 } 00708 00709 netif->addr_hint = addr_hint; 00710 err = ip_output_if(p, src, dest, ttl, tos, proto, netif); 00711 netif->addr_hint = NULL; 00712 00713 return err; 00714 } 00715 #endif /* LWIP_NETIF_HWADDRHINT*/ 00716 00717 #if IP_DEBUG 00718 /* Print an IP header by using LWIP_DEBUGF 00719 * @param p an IP packet, p->payload pointing to the IP header 00720 */ 00721 void 00722 ip_debug_print(struct pbuf *p) 00723 { 00724 struct ip_hdr *iphdr = (struct ip_hdr *) p->payload; 00725 u8_t *payload; 00726 00727 payload = (u8_t *)iphdr + IP_HLEN; 00728 00729 LWIP_DEBUGF(IP_DEBUG, ("IP header:\n")); 00730 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); 00731 LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" |%2"S16_F" | 0x%02"X16_F" | %5"U16_F" | (v, hl, tos, len)\n", 00732 IPH_V(iphdr), 00733 IPH_HL(iphdr), 00734 IPH_TOS(iphdr), 00735 ntohs(IPH_LEN(iphdr)))); 00736 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); 00737 LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" |%"U16_F"%"U16_F"%"U16_F"| %4"U16_F" | (id, flags, offset)\n", 00738 ntohs(IPH_ID(iphdr)), 00739 ntohs(IPH_OFFSET(iphdr)) >> 15 & 1, 00740 ntohs(IPH_OFFSET(iphdr)) >> 14 & 1, 00741 ntohs(IPH_OFFSET(iphdr)) >> 13 & 1, 00742 ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)); 00743 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); 00744 LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | 0x%04"X16_F" | (ttl, proto, chksum)\n", 00745 IPH_TTL(iphdr), 00746 IPH_PROTO(iphdr), 00747 ntohs(IPH_CHKSUM(iphdr)))); 00748 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); 00749 LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (src)\n", 00750 ip4_addr1_16(&iphdr->src), 00751 ip4_addr2_16(&iphdr->src), 00752 ip4_addr3_16(&iphdr->src), 00753 ip4_addr4_16(&iphdr->src))); 00754 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); 00755 LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (dest)\n", 00756 ip4_addr1_16(&iphdr->dest), 00757 ip4_addr2_16(&iphdr->dest), 00758 ip4_addr3_16(&iphdr->dest), 00759 ip4_addr4_16(&iphdr->dest))); 00760 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); 00761 } 00762 #endif /* IP_DEBUG */
Generated on Tue Jul 12 2022 11:17:51 by
