Ethernet for Nucleo and Disco board STM32F746 works with gcc and arm. IAC is untested
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 Tue Jul 12 2022 21:19:01 by 1.7.2