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