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