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