Dirk-Willem van Gulik (NXP/mbed)
/
Bonjour
Bonjour/Zerconf library
Embed:
(wiki syntax)
Show/hide line numbers
ip.c
Go to the documentation of this file.
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 #if 0 00302 /* or is this to our multicast interface? DIRKX */ 00303 || ip_addr_ismulticast(&(iphdr->dest)) 00304 #endif 00305 ) { 00306 LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n", 00307 netif->name[0], netif->name[1])); 00308 /* break out of for loop */ 00309 break; 00310 } 00311 #if LWIP_AUTOIP 00312 /* connections to link-local addresses must persist after changing 00313 the netif's address (RFC3927 ch. 1.9) */ 00314 if ((netif->autoip != NULL) && 00315 ip_addr_cmp(&(iphdr->dest), &(netif->autoip->llipaddr))) { 00316 LWIP_DEBUGF(IP_DEBUG, ("ip_input: LLA packet accepted on interface %c%c\n", 00317 netif->name[0], netif->name[1])); 00318 /* break out of for loop */ 00319 break; 00320 } 00321 #endif /* LWIP_AUTOIP */ 00322 } 00323 if (first) { 00324 first = 0; 00325 netif = netif_list; 00326 } else { 00327 netif = netif->next; 00328 } 00329 if (netif == inp) { 00330 netif = netif->next; 00331 } 00332 } while(netif != NULL); 00333 } 00334 00335 #if LWIP_DHCP 00336 /* Pass DHCP messages regardless of destination address. DHCP traffic is addressed 00337 * using link layer addressing (such as Ethernet MAC) so we must not filter on IP. 00338 * According to RFC 1542 section 3.1.1, referred by RFC 2131). 00339 */ 00340 if (netif == NULL) { 00341 /* remote port is DHCP server? */ 00342 if (IPH_PROTO(iphdr) == IP_PROTO_UDP) { 00343 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: UDP packet to DHCP client port %"U16_F"\n", 00344 ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen))->dest))); 00345 if (ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen))->dest) == DHCP_CLIENT_PORT) { 00346 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: DHCP packet accepted.\n")); 00347 netif = inp; 00348 check_ip_src = 0; 00349 } 00350 } 00351 } 00352 #endif /* LWIP_DHCP */ 00353 00354 /* broadcast or multicast packet source address? Compliant with RFC 1122: 3.2.1.3 */ 00355 #if LWIP_DHCP 00356 /* DHCP servers need 0.0.0.0 to be allowed as source address (RFC 1.1.2.2: 3.2.1.3/a) */ 00357 if (check_ip_src && !ip_addr_isany(&iphdr->src)) 00358 #endif /* LWIP_DHCP */ 00359 { if ((ip_addr_isbroadcast(&(iphdr->src), inp)) || 00360 (ip_addr_ismulticast(&(iphdr->src)))) { 00361 /* packet source is not valid */ 00362 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("ip_input: packet source is not valid.\n")); 00363 /* free (drop) packet pbufs */ 00364 pbuf_free(p); 00365 IP_STATS_INC(ip.drop); 00366 snmp_inc_ipinaddrerrors(); 00367 snmp_inc_ipindiscards(); 00368 return ERR_OK; 00369 } 00370 } 00371 00372 /* packet not for us? */ 00373 if (netif == NULL) { 00374 /* packet not for us, route or discard */ 00375 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: packet not for us.\n")); 00376 #if IP_FORWARD 00377 /* non-broadcast packet? */ 00378 if (!ip_addr_isbroadcast(&(iphdr->dest), inp)) { 00379 /* try to forward IP packet on (other) interfaces */ 00380 ip_forward(p, iphdr, inp); 00381 } else 00382 #endif /* IP_FORWARD */ 00383 { 00384 snmp_inc_ipinaddrerrors(); 00385 snmp_inc_ipindiscards(); 00386 } 00387 pbuf_free(p); 00388 return ERR_OK; 00389 } 00390 /* packet consists of multiple fragments? */ 00391 if ((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) { 00392 #if IP_REASSEMBLY /* packet fragment reassembly code present? */ 00393 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", 00394 ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & htons(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8)); 00395 /* reassemble the packet*/ 00396 p = ip_reass(p); 00397 /* packet not fully reassembled yet? */ 00398 if (p == NULL) { 00399 return ERR_OK; 00400 } 00401 iphdr = (struct ip_hdr *)p->payload; 00402 #else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */ 00403 pbuf_free(p); 00404 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n", 00405 ntohs(IPH_OFFSET(iphdr)))); 00406 IP_STATS_INC(ip.opterr); 00407 IP_STATS_INC(ip.drop); 00408 /* unsupported protocol feature */ 00409 snmp_inc_ipinunknownprotos(); 00410 return ERR_OK; 00411 #endif /* IP_REASSEMBLY */ 00412 } 00413 00414 #if IP_OPTIONS_ALLOWED == 0 /* no support for IP options in the IP header? */ 00415 00416 #if LWIP_IGMP 00417 /* there is an extra "router alert" option in IGMP messages which we allow for but do not police */ 00418 if((iphdr_hlen > IP_HLEN) && (IPH_PROTO(iphdr) != IP_PROTO_IGMP)) { 00419 #else 00420 if (iphdr_hlen > IP_HLEN) { 00421 #endif /* LWIP_IGMP */ 00422 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since there were IP options (while IP_OPTIONS_ALLOWED == 0).\n")); 00423 pbuf_free(p); 00424 IP_STATS_INC(ip.opterr); 00425 IP_STATS_INC(ip.drop); 00426 /* unsupported protocol feature */ 00427 snmp_inc_ipinunknownprotos(); 00428 return ERR_OK; 00429 } 00430 #endif /* IP_OPTIONS_ALLOWED == 0 */ 00431 00432 /* send to upper layers */ 00433 LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n")); 00434 ip_debug_print(p); 00435 LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len)); 00436 00437 current_netif = inp; 00438 current_header = iphdr; 00439 00440 #if LWIP_RAW 00441 /* raw input did not eat the packet? */ 00442 if (raw_input(p, inp) == 0) 00443 #endif /* LWIP_RAW */ 00444 { 00445 00446 switch (IPH_PROTO(iphdr)) { 00447 #if LWIP_UDP 00448 case IP_PROTO_UDP: 00449 #if LWIP_UDPLITE 00450 case IP_PROTO_UDPLITE: 00451 #endif /* LWIP_UDPLITE */ 00452 snmp_inc_ipindelivers(); 00453 udp_input(p, inp); 00454 break; 00455 #endif /* LWIP_UDP */ 00456 #if LWIP_TCP 00457 case IP_PROTO_TCP: 00458 snmp_inc_ipindelivers(); 00459 tcp_input(p, inp); 00460 break; 00461 #endif /* LWIP_TCP */ 00462 #if LWIP_ICMP 00463 case IP_PROTO_ICMP: 00464 snmp_inc_ipindelivers(); 00465 icmp_input(p, inp); 00466 break; 00467 #endif /* LWIP_ICMP */ 00468 #if LWIP_IGMP 00469 case IP_PROTO_IGMP: 00470 igmp_input(p,inp,&(iphdr->dest)); 00471 break; 00472 #endif /* LWIP_IGMP */ 00473 default: 00474 #if LWIP_ICMP 00475 /* send ICMP destination protocol unreachable unless is was a broadcast */ 00476 if (!ip_addr_isbroadcast(&(iphdr->dest), inp) && 00477 !ip_addr_ismulticast(&(iphdr->dest))) { 00478 p->payload = iphdr; 00479 icmp_dest_unreach(p, ICMP_DUR_PROTO); 00480 } 00481 #endif /* LWIP_ICMP */ 00482 pbuf_free(p); 00483 00484 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Unsupported transport protocol %"U16_F"\n", IPH_PROTO(iphdr))); 00485 00486 IP_STATS_INC(ip.proterr); 00487 IP_STATS_INC(ip.drop); 00488 snmp_inc_ipinunknownprotos(); 00489 } 00490 } 00491 00492 current_netif = NULL; 00493 current_header = NULL; 00494 00495 return ERR_OK; 00496 } 00497 00498 /** 00499 * Sends an IP packet on a network interface. This function constructs 00500 * the IP header and calculates the IP header checksum. If the source 00501 * IP address is NULL, the IP address of the outgoing network 00502 * interface is filled in as source address. 00503 * If the destination IP address is IP_HDRINCL, p is assumed to already 00504 * include an IP header and p->payload points to it instead of the data. 00505 * 00506 * @param p the packet to send (p->payload points to the data, e.g. next 00507 protocol header; if dest == IP_HDRINCL, p already includes an IP 00508 header and p->payload points to that IP header) 00509 * @param src the source IP address to send from (if src == IP_ADDR_ANY, the 00510 * IP address of the netif used to send is used as source address) 00511 * @param dest the destination IP address to send the packet to 00512 * @param ttl the TTL value to be set in the IP header 00513 * @param tos the TOS value to be set in the IP header 00514 * @param proto the PROTOCOL to be set in the IP header 00515 * @param netif the netif on which to send this packet 00516 * @return ERR_OK if the packet was sent OK 00517 * ERR_BUF if p doesn't have enough space for IP/LINK headers 00518 * returns errors returned by netif->output 00519 * 00520 * @note ip_id: RFC791 "some host may be able to simply use 00521 * unique identifiers independent of destination" 00522 */ 00523 err_t 00524 ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, 00525 u8_t ttl, u8_t tos, 00526 u8_t proto, struct netif *netif) 00527 { 00528 #if IP_OPTIONS_SEND 00529 return ip_output_if_opt(p, src, dest, ttl, tos, proto, netif, NULL, 0); 00530 } 00531 00532 /** 00533 * Same as ip_output_if() but with the possibility to include IP options: 00534 * 00535 * @ param ip_options pointer to the IP options, copied into the IP header 00536 * @ param optlen length of ip_options 00537 */ 00538 err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, 00539 u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, 00540 u16_t optlen) 00541 { 00542 #endif /* IP_OPTIONS_SEND */ 00543 struct ip_hdr *iphdr; 00544 static u16_t ip_id = 0; 00545 00546 /* pbufs passed to IP must have a ref-count of 1 as their payload pointer 00547 gets altered as the packet is passed down the stack */ 00548 LWIP_ASSERT("p->ref == 1", p->ref == 1); 00549 00550 snmp_inc_ipoutrequests(); 00551 00552 /* Should the IP header be generated or is it already included in p? */ 00553 if (dest != IP_HDRINCL) { 00554 u16_t ip_hlen = IP_HLEN; 00555 #if IP_OPTIONS_SEND 00556 u16_t optlen_aligned = 0; 00557 if (optlen != 0) { 00558 /* round up to a multiple of 4 */ 00559 optlen_aligned = ((optlen + 3) & ~3); 00560 ip_hlen += optlen_aligned; 00561 /* First write in the IP options */ 00562 if (pbuf_header(p, optlen_aligned)) { 00563 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_output_if_opt: not enough room for IP options in pbuf\n")); 00564 IP_STATS_INC(ip.err); 00565 snmp_inc_ipoutdiscards(); 00566 return ERR_BUF; 00567 } 00568 MEMCPY(p->payload, ip_options, optlen); 00569 if (optlen < optlen_aligned) { 00570 /* zero the remaining bytes */ 00571 memset(((char*)p->payload) + optlen, 0, optlen_aligned - optlen); 00572 } 00573 } 00574 #endif /* IP_OPTIONS_SEND */ 00575 /* generate IP header */ 00576 if (pbuf_header(p, IP_HLEN)) { 00577 LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_output: not enough room for IP header in pbuf\n")); 00578 00579 IP_STATS_INC(ip.err); 00580 snmp_inc_ipoutdiscards(); 00581 return ERR_BUF; 00582 } 00583 00584 iphdr = (struct ip_hdr *)p->payload; 00585 LWIP_ASSERT("check that first pbuf can hold struct ip_hdr", 00586 (p->len >= sizeof(struct ip_hdr))); 00587 00588 IPH_TTL_SET(iphdr, ttl); 00589 IPH_PROTO_SET(iphdr, proto); 00590 00591 /* dest cannot be NULL here */ 00592 ip_addr_copy(iphdr->dest, *dest); 00593 00594 IPH_VHLTOS_SET(iphdr, 4, ip_hlen / 4, tos); 00595 IPH_LEN_SET(iphdr, htons(p->tot_len)); 00596 IPH_OFFSET_SET(iphdr, 0); 00597 IPH_ID_SET(iphdr, htons(ip_id)); 00598 ++ip_id; 00599 00600 if (ip_addr_isany(src)) { 00601 ip_addr_copy(iphdr->src, netif->ip_addr); 00602 } else { 00603 /* src cannot be NULL here */ 00604 ip_addr_copy(iphdr->src, *src); 00605 } 00606 00607 IPH_CHKSUM_SET(iphdr, 0); 00608 #if CHECKSUM_GEN_IP 00609 IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, ip_hlen)); 00610 #endif 00611 } else { 00612 /* IP header already included in p */ 00613 iphdr = (struct ip_hdr *)p->payload; 00614 dest = &(iphdr->dest); 00615 } 00616 00617 IP_STATS_INC(ip.xmit); 00618 00619 LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num)); 00620 ip_debug_print(p); 00621 00622 #if ENABLE_LOOPBACK 00623 if (ip_addr_cmp(dest, &netif->ip_addr)) { 00624 /* Packet to self, enqueue it for loopback */ 00625 LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()")); 00626 return netif_loop_output(netif, p, dest); 00627 } 00628 #endif /* ENABLE_LOOPBACK */ 00629 #if IP_FRAG 00630 /* don't fragment if interface has mtu set to 0 [loopif] */ 00631 if (netif->mtu && (p->tot_len > netif->mtu)) { 00632 return ip_frag(p,netif,dest); 00633 } 00634 #endif 00635 00636 LWIP_DEBUGF(IP_DEBUG, ("netif->output()")); 00637 return netif->output(netif, p, dest); 00638 } 00639 00640 /** 00641 * Simple interface to ip_output_if. It finds the outgoing network 00642 * interface and calls upon ip_output_if to do the actual work. 00643 * 00644 * @param p the packet to send (p->payload points to the data, e.g. next 00645 protocol header; if dest == IP_HDRINCL, p already includes an IP 00646 header and p->payload points to that IP header) 00647 * @param src the source IP address to send from (if src == IP_ADDR_ANY, the 00648 * IP address of the netif used to send is used as source address) 00649 * @param dest the destination IP address to send the packet to 00650 * @param ttl the TTL value to be set in the IP header 00651 * @param tos the TOS value to be set in the IP header 00652 * @param proto the PROTOCOL to be set in the IP header 00653 * 00654 * @return ERR_RTE if no route is found 00655 * see ip_output_if() for more return values 00656 */ 00657 err_t 00658 ip_output(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, 00659 u8_t ttl, u8_t tos, u8_t proto) 00660 { 00661 struct netif *netif; 00662 00663 /* pbufs passed to IP must have a ref-count of 1 as their payload pointer 00664 gets altered as the packet is passed down the stack */ 00665 LWIP_ASSERT("p->ref == 1", p->ref == 1); 00666 00667 if ((netif = ip_route(dest)) == NULL) { 00668 LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", 00669 ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); 00670 IP_STATS_INC(ip.rterr); 00671 return ERR_RTE; 00672 } 00673 00674 return ip_output_if(p, src, dest, ttl, tos, proto, netif); 00675 } 00676 00677 #if LWIP_NETIF_HWADDRHINT 00678 /** Like ip_output, but takes and addr_hint pointer that is passed on to netif->addr_hint 00679 * before calling ip_output_if. 00680 * 00681 * @param p the packet to send (p->payload points to the data, e.g. next 00682 protocol header; if dest == IP_HDRINCL, p already includes an IP 00683 header and p->payload points to that IP header) 00684 * @param src the source IP address to send from (if src == IP_ADDR_ANY, the 00685 * IP address of the netif used to send is used as source address) 00686 * @param dest the destination IP address to send the packet to 00687 * @param ttl the TTL value to be set in the IP header 00688 * @param tos the TOS value to be set in the IP header 00689 * @param proto the PROTOCOL to be set in the IP header 00690 * @param addr_hint address hint pointer set to netif->addr_hint before 00691 * calling ip_output_if() 00692 * 00693 * @return ERR_RTE if no route is found 00694 * see ip_output_if() for more return values 00695 */ 00696 err_t 00697 ip_output_hinted(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, 00698 u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint) 00699 { 00700 struct netif *netif; 00701 err_t err; 00702 00703 /* pbufs passed to IP must have a ref-count of 1 as their payload pointer 00704 gets altered as the packet is passed down the stack */ 00705 LWIP_ASSERT("p->ref == 1", p->ref == 1); 00706 00707 if ((netif = ip_route(dest)) == NULL) { 00708 LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", 00709 ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest))); 00710 IP_STATS_INC(ip.rterr); 00711 return ERR_RTE; 00712 } 00713 00714 netif->addr_hint = addr_hint; 00715 err = ip_output_if(p, src, dest, ttl, tos, proto, netif); 00716 netif->addr_hint = NULL; 00717 00718 return err; 00719 } 00720 #endif /* LWIP_NETIF_HWADDRHINT*/ 00721 00722 #if IP_DEBUG 00723 /* Print an IP header by using LWIP_DEBUGF 00724 * @param p an IP packet, p->payload pointing to the IP header 00725 */ 00726 void 00727 ip_debug_print(struct pbuf *p) 00728 { 00729 struct ip_hdr *iphdr = (struct ip_hdr *) p->payload; 00730 u8_t *payload; 00731 00732 payload = (u8_t *)iphdr + IP_HLEN; 00733 00734 LWIP_DEBUGF(IP_DEBUG, ("IP header:\n")); 00735 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); 00736 LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" |%2"S16_F" | 0x%02"X16_F" | %5"U16_F" | (v, hl, tos, len)\n", 00737 IPH_V(iphdr), 00738 IPH_HL(iphdr), 00739 IPH_TOS(iphdr), 00740 ntohs(IPH_LEN(iphdr)))); 00741 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); 00742 LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" |%"U16_F"%"U16_F"%"U16_F"| %4"U16_F" | (id, flags, offset)\n", 00743 ntohs(IPH_ID(iphdr)), 00744 ntohs(IPH_OFFSET(iphdr)) >> 15 & 1, 00745 ntohs(IPH_OFFSET(iphdr)) >> 14 & 1, 00746 ntohs(IPH_OFFSET(iphdr)) >> 13 & 1, 00747 ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)); 00748 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); 00749 LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | 0x%04"X16_F" | (ttl, proto, chksum)\n", 00750 IPH_TTL(iphdr), 00751 IPH_PROTO(iphdr), 00752 ntohs(IPH_CHKSUM(iphdr)))); 00753 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); 00754 LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (src)\n", 00755 ip4_addr1_16(&iphdr->src), 00756 ip4_addr2_16(&iphdr->src), 00757 ip4_addr3_16(&iphdr->src), 00758 ip4_addr4_16(&iphdr->src))); 00759 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); 00760 LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (dest)\n", 00761 ip4_addr1_16(&iphdr->dest), 00762 ip4_addr2_16(&iphdr->dest), 00763 ip4_addr3_16(&iphdr->dest), 00764 ip4_addr4_16(&iphdr->dest))); 00765 LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); 00766 } 00767 #endif /* IP_DEBUG */
Generated on Tue Jul 12 2022 18:38:37 by 1.7.2