ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

ip.c
Go to the documentation of this file.
00001 
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 
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 
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(dst_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 
00100 struct netif *current_netif;
00101 
00105 const struct ip_hdr *current_header;
00107 ip_addr_t current_iphdr_src;
00109 ip_addr_t current_iphdr_dest;
00110 
00112 static u16_t ip_id;
00113 
00123 struct netif *
00124 ip_route(ip_addr_t *dest)
00125 {
00126   struct netif *netif;
00127 
00128   /* iterate through netifs */
00129   for(netif = netif_list; netif != NULL; netif = netif->next) {
00130     /* network mask matches? */
00131     if (netif_is_up(netif)) {
00132       if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
00133         /* return netif on which to forward IP packet */
00134         return netif;
00135       }
00136     }
00137   }
00138   if ((netif_default == NULL) || (!netif_is_up(netif_default))) {
00139     LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_route: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
00140       ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest)));
00141     IP_STATS_INC(ip.rterr);
00142     snmp_inc_ipoutnoroutes();
00143     return NULL;
00144   }
00145   /* no matching netif found, use default netif */
00146   return netif_default;
00147 }
00148 
00149 #if IP_FORWARD
00150 
00159 static void
00160 ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
00161 {
00162   struct netif *netif;
00163 
00164   PERF_START;
00165 
00166   /* RFC3927 2.7: do not forward link-local addresses */
00167   if (ip_addr_islinklocal(&current_iphdr_dest)) {
00168     LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not forwarding LLA %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
00169       ip4_addr1_16(&current_iphdr_dest), ip4_addr2_16(&current_iphdr_dest),
00170       ip4_addr3_16(&current_iphdr_dest), ip4_addr4_16(&current_iphdr_dest)));
00171     goto return_noroute;
00172   }
00173 
00174   /* Find network interface where to forward this IP packet to. */
00175   netif = ip_route(&current_iphdr_dest);
00176   if (netif == NULL) {
00177     LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for %"U16_F".%"U16_F".%"U16_F".%"U16_F" found\n",
00178       ip4_addr1_16(&current_iphdr_dest), ip4_addr2_16(&current_iphdr_dest),
00179       ip4_addr3_16(&current_iphdr_dest), ip4_addr4_16(&current_iphdr_dest)));
00180     goto return_noroute;
00181   }
00182   /* Do not forward packets onto the same network interface on which
00183    * they arrived. */
00184   if (netif == inp) {
00185     LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not bouncing packets back on incoming interface.\n"));
00186     goto return_noroute;
00187   }
00188 
00189   /* decrement TTL */
00190   IPH_TTL_SET(iphdr, IPH_TTL(iphdr) - 1);
00191   /* send ICMP if TTL == 0 */
00192   if (IPH_TTL(iphdr) == 0) {
00193     snmp_inc_ipinhdrerrors();
00194 #if LWIP_ICMP
00195     /* Don't send ICMP messages in response to ICMP messages */
00196     if (IPH_PROTO(iphdr) != IP_PROTO_ICMP) {
00197       icmp_time_exceeded(p, ICMP_TE_TTL);
00198     }
00199 #endif /* LWIP_ICMP */
00200     return;
00201   }
00202 
00203   /* Incrementally update the IP checksum. */
00204   if (IPH_CHKSUM(iphdr) >= PP_HTONS(0xffffU - 0x100)) {
00205     IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100) + 1);
00206   } else {
00207     IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100));
00208   }
00209 
00210   LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
00211     ip4_addr1_16(&current_iphdr_dest), ip4_addr2_16(&current_iphdr_dest),
00212     ip4_addr3_16(&current_iphdr_dest), ip4_addr4_16(&current_iphdr_dest)));
00213 
00214   IP_STATS_INC(ip.fw);
00215   IP_STATS_INC(ip.xmit);
00216   snmp_inc_ipforwdatagrams();
00217 
00218   PERF_STOP("ip_forward");
00219   /* transmit pbuf on chosen interface */
00220   netif->output(netif, p, &current_iphdr_dest);
00221   return;
00222 return_noroute:
00223   snmp_inc_ipoutnoroutes();
00224 }
00225 #endif /* IP_FORWARD */
00226 
00241 err_t
00242 ip_input(struct pbuf *p, struct netif *inp)
00243 {
00244   struct ip_hdr *iphdr;
00245   struct netif *netif;
00246   u16_t iphdr_hlen;
00247   u16_t iphdr_len;
00248 #if IP_ACCEPT_LINK_LAYER_ADDRESSING
00249   int check_ip_src=1;
00250 #endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
00251 
00252   IP_STATS_INC(ip.recv);
00253   snmp_inc_ipinreceives();
00254 
00255   /* identify the IP header */
00256   iphdr = (struct ip_hdr *)p->payload;
00257   if (IPH_V(iphdr) != 4) {
00258     LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IP packet dropped due to bad version number %"U16_F"\n", IPH_V(iphdr)));
00259     ip_debug_print(p);
00260     pbuf_free(p);
00261     IP_STATS_INC(ip.err);
00262     IP_STATS_INC(ip.drop);
00263     snmp_inc_ipinhdrerrors();
00264     return ERR_OK;
00265   }
00266 
00267   /* obtain IP header length in number of 32-bit words */
00268   iphdr_hlen = IPH_HL(iphdr);
00269   /* calculate IP header length in bytes */
00270   iphdr_hlen *= 4;
00271   /* obtain ip length in bytes */
00272   iphdr_len = ntohs(IPH_LEN(iphdr));
00273 
00274   /* header length exceeds first pbuf length, or ip length exceeds total pbuf length? */
00275   if ((iphdr_hlen > p->len) || (iphdr_len > p->tot_len)) {
00276     if (iphdr_hlen > p->len) {
00277       LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
00278         ("IP header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet dropped.\n",
00279         iphdr_hlen, p->len));
00280     }
00281     if (iphdr_len > p->tot_len) {
00282       LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
00283         ("IP (len %"U16_F") is longer than pbuf (len %"U16_F"), IP packet dropped.\n",
00284         iphdr_len, p->tot_len));
00285     }
00286     /* free (drop) packet pbufs */
00287     pbuf_free(p);
00288     IP_STATS_INC(ip.lenerr);
00289     IP_STATS_INC(ip.drop);
00290     snmp_inc_ipindiscards();
00291     return ERR_OK;
00292   }
00293 
00294   /* verify checksum */
00295 #if CHECKSUM_CHECK_IP
00296   if (inet_chksum(iphdr, iphdr_hlen) != 0) {
00297 
00298     LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
00299       ("Checksum (0x%"X16_F") failed, IP packet dropped.\n", inet_chksum(iphdr, iphdr_hlen)));
00300     ip_debug_print(p);
00301     pbuf_free(p);
00302     IP_STATS_INC(ip.chkerr);
00303     IP_STATS_INC(ip.drop);
00304     snmp_inc_ipinhdrerrors();
00305     return ERR_OK;
00306   }
00307 #endif
00308 
00309   /* Trim pbuf. This should have been done at the netif layer,
00310    * but we'll do it anyway just to be sure that its done. */
00311   pbuf_realloc(p, iphdr_len);
00312 
00313   /* copy IP addresses to aligned ip_addr_t */
00314   ip_addr_copy(current_iphdr_dest, iphdr->dest);
00315   ip_addr_copy(current_iphdr_src, iphdr->src);
00316 
00317   /* match packet against an interface, i.e. is this packet for us? */
00318 #if LWIP_IGMP
00319   if (ip_addr_ismulticast(&current_iphdr_dest)) {
00320     if ((inp->flags & NETIF_FLAG_IGMP) && (igmp_lookfor_group(inp, &current_iphdr_dest))) {
00321       netif = inp;
00322     } else {
00323       netif = NULL;
00324     }
00325   } else
00326 #endif /* LWIP_IGMP */
00327   {
00328     /* start trying with inp. if that's not acceptable, start walking the
00329        list of configured netifs.
00330        'first' is used as a boolean to mark whether we started walking the list */
00331     int first = 1;
00332     netif = inp;
00333     do {
00334       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",
00335           ip4_addr_get_u32(&iphdr->dest), ip4_addr_get_u32(&netif->ip_addr),
00336           ip4_addr_get_u32(&iphdr->dest) & ip4_addr_get_u32(&netif->netmask),
00337           ip4_addr_get_u32(&netif->ip_addr) & ip4_addr_get_u32(&netif->netmask),
00338           ip4_addr_get_u32(&iphdr->dest) & ~ip4_addr_get_u32(&netif->netmask)));
00339 
00340       /* interface is up and configured? */
00341       if ((netif_is_up(netif)) && (!ip_addr_isany(&(netif->ip_addr)))) {
00342         /* unicast to this interface address? */
00343         if (ip_addr_cmp(&current_iphdr_dest, &(netif->ip_addr)) ||
00344             /* or broadcast on this interface network address? */
00345             ip_addr_isbroadcast(&current_iphdr_dest, netif)) {
00346           LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n",
00347               netif->name[0], netif->name[1]));
00348           /* break out of for loop */
00349           break;
00350         }
00351 #if LWIP_AUTOIP
00352         /* connections to link-local addresses must persist after changing
00353            the netif's address (RFC3927 ch. 1.9) */
00354         if ((netif->autoip != NULL) &&
00355             ip_addr_cmp(&current_iphdr_dest, &(netif->autoip->llipaddr))) {
00356           LWIP_DEBUGF(IP_DEBUG, ("ip_input: LLA packet accepted on interface %c%c\n",
00357               netif->name[0], netif->name[1]));
00358           /* break out of for loop */
00359           break;
00360         }
00361 #endif /* LWIP_AUTOIP */
00362       }
00363       if (first) {
00364         first = 0;
00365         netif = netif_list;
00366       } else {
00367         netif = netif->next;
00368       }
00369       if (netif == inp) {
00370         netif = netif->next;
00371       }
00372     } while(netif != NULL);
00373   }
00374 
00375 #if IP_ACCEPT_LINK_LAYER_ADDRESSING
00376   /* Pass DHCP messages regardless of destination address. DHCP traffic is addressed
00377    * using link layer addressing (such as Ethernet MAC) so we must not filter on IP.
00378    * According to RFC 1542 section 3.1.1, referred by RFC 2131).
00379    *
00380    * If you want to accept private broadcast communication while a netif is down,
00381    * define LWIP_IP_ACCEPT_UDP_PORT(dst_port), e.g.:
00382    *
00383    * #define LWIP_IP_ACCEPT_UDP_PORT(dst_port) ((dst_port) == PP_NTOHS(12345))
00384    */
00385   if (netif == NULL) {
00386     /* remote port is DHCP server? */
00387     if (IPH_PROTO(iphdr) == IP_PROTO_UDP) {
00388       struct udp_hdr *udphdr = (struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen);
00389       LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: UDP packet to DHCP client port %"U16_F"\n",
00390         ntohs(udphdr->dest)));
00391       if (IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(udphdr->dest)) {
00392         LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: DHCP packet accepted.\n"));
00393         netif = inp;
00394         check_ip_src = 0;
00395       }
00396     }
00397   }
00398 #endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
00399 
00400   /* broadcast or multicast packet source address? Compliant with RFC 1122: 3.2.1.3 */
00401 #if IP_ACCEPT_LINK_LAYER_ADDRESSING
00402   /* DHCP servers need 0.0.0.0 to be allowed as source address (RFC 1.1.2.2: 3.2.1.3/a) */
00403   if (check_ip_src && !ip_addr_isany(&current_iphdr_src))
00404 #endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
00405   {  if ((ip_addr_isbroadcast(&current_iphdr_src, inp)) ||
00406          (ip_addr_ismulticast(&current_iphdr_src))) {
00407       /* packet source is not valid */
00408       LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("ip_input: packet source is not valid.\n"));
00409       /* free (drop) packet pbufs */
00410       pbuf_free(p);
00411       IP_STATS_INC(ip.drop);
00412       snmp_inc_ipinaddrerrors();
00413       snmp_inc_ipindiscards();
00414       return ERR_OK;
00415     }
00416   }
00417 
00418   /* packet not for us? */
00419   if (netif == NULL) {
00420     /* packet not for us, route or discard */
00421     LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: packet not for us.\n"));
00422 #if IP_FORWARD
00423     /* non-broadcast packet? */
00424     if (!ip_addr_isbroadcast(&current_iphdr_dest, inp)) {
00425       /* try to forward IP packet on (other) interfaces */
00426       ip_forward(p, iphdr, inp);
00427     } else
00428 #endif /* IP_FORWARD */
00429     {
00430       snmp_inc_ipinaddrerrors();
00431       snmp_inc_ipindiscards();
00432     }
00433     pbuf_free(p);
00434     return ERR_OK;
00435   }
00436   /* packet consists of multiple fragments? */
00437   if ((IPH_OFFSET(iphdr) & PP_HTONS(IP_OFFMASK | IP_MF)) != 0) {
00438 #if IP_REASSEMBLY /* packet fragment reassembly code present? */
00439     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",
00440       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));
00441     /* reassemble the packet*/
00442     p = ip_reass(p);
00443     /* packet not fully reassembled yet? */
00444     if (p == NULL) {
00445       return ERR_OK;
00446     }
00447     iphdr = (struct ip_hdr *)p->payload;
00448 #else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */
00449     pbuf_free(p);
00450     LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n",
00451       ntohs(IPH_OFFSET(iphdr))));
00452     IP_STATS_INC(ip.opterr);
00453     IP_STATS_INC(ip.drop);
00454     /* unsupported protocol feature */
00455     snmp_inc_ipinunknownprotos();
00456     return ERR_OK;
00457 #endif /* IP_REASSEMBLY */
00458   }
00459 
00460 #if IP_OPTIONS_ALLOWED == 0 /* no support for IP options in the IP header? */
00461 
00462 #if LWIP_IGMP
00463   /* there is an extra "router alert" option in IGMP messages which we allow for but do not police */
00464   if((iphdr_hlen > IP_HLEN) &&  (IPH_PROTO(iphdr) != IP_PROTO_IGMP)) {
00465 #else
00466   if (iphdr_hlen > IP_HLEN) {
00467 #endif /* LWIP_IGMP */
00468     LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since there were IP options (while IP_OPTIONS_ALLOWED == 0).\n"));
00469     pbuf_free(p);
00470     IP_STATS_INC(ip.opterr);
00471     IP_STATS_INC(ip.drop);
00472     /* unsupported protocol feature */
00473     snmp_inc_ipinunknownprotos();
00474     return ERR_OK;
00475   }
00476 #endif /* IP_OPTIONS_ALLOWED == 0 */
00477 
00478   /* send to upper layers */
00479   LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n"));
00480   ip_debug_print(p);
00481   LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len));
00482 
00483   current_netif = inp;
00484   current_header = iphdr;
00485 
00486 #if LWIP_RAW
00487   /* raw input did not eat the packet? */
00488   if (raw_input(p, inp) == 0)
00489 #endif /* LWIP_RAW */
00490   {
00491 
00492     switch (IPH_PROTO(iphdr)) {
00493 #if LWIP_UDP
00494     case IP_PROTO_UDP:
00495 #if LWIP_UDPLITE
00496     case IP_PROTO_UDPLITE:
00497 #endif /* LWIP_UDPLITE */
00498       snmp_inc_ipindelivers();
00499       udp_input(p, inp);
00500       break;
00501 #endif /* LWIP_UDP */
00502 #if LWIP_TCP
00503     case IP_PROTO_TCP:
00504       snmp_inc_ipindelivers();
00505       tcp_input(p, inp);
00506       break;
00507 #endif /* LWIP_TCP */
00508 #if LWIP_ICMP
00509     case IP_PROTO_ICMP:
00510       snmp_inc_ipindelivers();
00511       icmp_input(p, inp);
00512       break;
00513 #endif /* LWIP_ICMP */
00514 #if LWIP_IGMP
00515     case IP_PROTO_IGMP:
00516       igmp_input(p, inp, &current_iphdr_dest);
00517       break;
00518 #endif /* LWIP_IGMP */
00519     default:
00520 #if LWIP_ICMP
00521       /* send ICMP destination protocol unreachable unless is was a broadcast */
00522       if (!ip_addr_isbroadcast(&current_iphdr_dest, inp) &&
00523           !ip_addr_ismulticast(&current_iphdr_dest)) {
00524         p->payload = iphdr;
00525         icmp_dest_unreach(p, ICMP_DUR_PROTO);
00526       }
00527 #endif /* LWIP_ICMP */
00528       pbuf_free(p);
00529 
00530       LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Unsupported transport protocol %"U16_F"\n", IPH_PROTO(iphdr)));
00531 
00532       IP_STATS_INC(ip.proterr);
00533       IP_STATS_INC(ip.drop);
00534       snmp_inc_ipinunknownprotos();
00535     }
00536   }
00537 
00538   current_netif = NULL;
00539   current_header = NULL;
00540   ip_addr_set_any(&current_iphdr_src);
00541   ip_addr_set_any(&current_iphdr_dest);
00542 
00543   return ERR_OK;
00544 }
00545 
00571 err_t
00572 ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
00573              u8_t ttl, u8_t tos,
00574              u8_t proto, struct netif *netif)
00575 {
00576 #if IP_OPTIONS_SEND
00577   return ip_output_if_opt(p, src, dest, ttl, tos, proto, netif, NULL, 0);
00578 }
00579 
00586 err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
00587        u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options,
00588        u16_t optlen)
00589 {
00590 #endif /* IP_OPTIONS_SEND */
00591   struct ip_hdr *iphdr;
00592   ip_addr_t dest_addr;
00593 #if CHECKSUM_GEN_IP_INLINE
00594   u32_t chk_sum = 0;
00595 #endif /* CHECKSUM_GEN_IP_INLINE */
00596 
00597   /* pbufs passed to IP must have a ref-count of 1 as their payload pointer
00598      gets altered as the packet is passed down the stack */
00599   LWIP_ASSERT("p->ref == 1", p->ref == 1);
00600 
00601   snmp_inc_ipoutrequests();
00602 
00603   /* Should the IP header be generated or is it already included in p? */
00604   if (dest != IP_HDRINCL) {
00605     u16_t ip_hlen = IP_HLEN;
00606 #if IP_OPTIONS_SEND
00607     u16_t optlen_aligned = 0;
00608     if (optlen != 0) {
00609 #if CHECKSUM_GEN_IP_INLINE
00610       int i;
00611 #endif /* CHECKSUM_GEN_IP_INLINE */
00612       /* round up to a multiple of 4 */
00613       optlen_aligned = ((optlen + 3) & ~3);
00614       ip_hlen += optlen_aligned;
00615       /* First write in the IP options */
00616       if (pbuf_header(p, optlen_aligned)) {
00617         LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_output_if_opt: not enough room for IP options in pbuf\n"));
00618         IP_STATS_INC(ip.err);
00619         snmp_inc_ipoutdiscards();
00620         return ERR_BUF;
00621       }
00622       MEMCPY(p->payload, ip_options, optlen);
00623       if (optlen < optlen_aligned) {
00624         /* zero the remaining bytes */
00625         memset(((char*)p->payload) + optlen, 0, optlen_aligned - optlen);
00626       }
00627 #if CHECKSUM_GEN_IP_INLINE
00628       for (i = 0; i < optlen_aligned/2; i++) {
00629         chk_sum += ((u16_t*)p->payload)[i];
00630       }
00631 #endif /* CHECKSUM_GEN_IP_INLINE */
00632     }
00633 #endif /* IP_OPTIONS_SEND */
00634     /* generate IP header */
00635     if (pbuf_header(p, IP_HLEN)) {
00636       LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_output: not enough room for IP header in pbuf\n"));
00637 
00638       IP_STATS_INC(ip.err);
00639       snmp_inc_ipoutdiscards();
00640       return ERR_BUF;
00641     }
00642 
00643     iphdr = (struct ip_hdr *)p->payload;
00644     LWIP_ASSERT("check that first pbuf can hold struct ip_hdr",
00645                (p->len >= sizeof(struct ip_hdr)));
00646 
00647     IPH_TTL_SET(iphdr, ttl);
00648     IPH_PROTO_SET(iphdr, proto);
00649 #if CHECKSUM_GEN_IP_INLINE
00650     chk_sum += LWIP_MAKE_U16(proto, ttl);
00651 #endif /* CHECKSUM_GEN_IP_INLINE */
00652 
00653     /* dest cannot be NULL here */
00654     ip_addr_copy(iphdr->dest, *dest);
00655 #if CHECKSUM_GEN_IP_INLINE
00656     chk_sum += ip4_addr_get_u32(&iphdr->dest) & 0xFFFF;
00657     chk_sum += ip4_addr_get_u32(&iphdr->dest) >> 16;
00658 #endif /* CHECKSUM_GEN_IP_INLINE */
00659 
00660     IPH_VHLTOS_SET(iphdr, 4, ip_hlen / 4, tos);
00661 #if CHECKSUM_GEN_IP_INLINE
00662     chk_sum += iphdr->_v_hl_tos;
00663 #endif /* CHECKSUM_GEN_IP_INLINE */
00664     IPH_LEN_SET(iphdr, htons(p->tot_len));
00665 #if CHECKSUM_GEN_IP_INLINE
00666     chk_sum += iphdr->_len;
00667 #endif /* CHECKSUM_GEN_IP_INLINE */
00668     IPH_OFFSET_SET(iphdr, 0);
00669     IPH_ID_SET(iphdr, htons(ip_id));
00670 #if CHECKSUM_GEN_IP_INLINE
00671     chk_sum += iphdr->_id;
00672 #endif /* CHECKSUM_GEN_IP_INLINE */
00673     ++ip_id;
00674 
00675     if (ip_addr_isany(src)) {
00676       ip_addr_copy(iphdr->src, netif->ip_addr);
00677     } else {
00678       /* src cannot be NULL here */
00679       ip_addr_copy(iphdr->src, *src);
00680     }
00681 
00682 #if CHECKSUM_GEN_IP_INLINE
00683     chk_sum += ip4_addr_get_u32(&iphdr->src) & 0xFFFF;
00684     chk_sum += ip4_addr_get_u32(&iphdr->src) >> 16;
00685     chk_sum = (chk_sum >> 16) + (chk_sum & 0xFFFF);
00686     chk_sum = (chk_sum >> 16) + chk_sum;
00687     chk_sum = ~chk_sum;
00688     iphdr->_chksum = chk_sum; /* network order */
00689 #else /* CHECKSUM_GEN_IP_INLINE */
00690     IPH_CHKSUM_SET(iphdr, 0);
00691 #if CHECKSUM_GEN_IP
00692     IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, ip_hlen));
00693 #endif
00694 #endif /* CHECKSUM_GEN_IP_INLINE */
00695   } else {
00696     /* IP header already included in p */
00697     iphdr = (struct ip_hdr *)p->payload;
00698     ip_addr_copy(dest_addr, iphdr->dest);
00699     dest = &dest_addr;
00700   }
00701 
00702   IP_STATS_INC(ip.xmit);
00703 
00704   LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num));
00705   ip_debug_print(p);
00706 
00707 #if ENABLE_LOOPBACK
00708   if (ip_addr_cmp(dest, &netif->ip_addr)) {
00709     /* Packet to self, enqueue it for loopback */
00710     LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()"));
00711     return netif_loop_output(netif, p, dest);
00712   }
00713 #if LWIP_IGMP
00714   if ((p->flags & PBUF_FLAG_MCASTLOOP) != 0) {
00715     netif_loop_output(netif, p, dest);
00716   }
00717 #endif /* LWIP_IGMP */
00718 #endif /* ENABLE_LOOPBACK */
00719 #if IP_FRAG
00720   /* don't fragment if interface has mtu set to 0 [loopif] */
00721   if (netif->mtu && (p->tot_len > netif->mtu)) {
00722     return ip_frag(p, netif, dest);
00723   }
00724 #endif /* IP_FRAG */
00725 
00726   LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
00727   return netif->output(netif, p, dest);
00728 }
00729 
00747 err_t
00748 ip_output(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
00749           u8_t ttl, u8_t tos, u8_t proto)
00750 {
00751   struct netif *netif;
00752 
00753   /* pbufs passed to IP must have a ref-count of 1 as their payload pointer
00754      gets altered as the packet is passed down the stack */
00755   LWIP_ASSERT("p->ref == 1", p->ref == 1);
00756 
00757   if ((netif = ip_route(dest)) == NULL) {
00758     LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
00759       ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest)));
00760     IP_STATS_INC(ip.rterr);
00761     return ERR_RTE;
00762   }
00763 
00764   return ip_output_if(p, src, dest, ttl, tos, proto, netif);
00765 }
00766 
00767 #if LWIP_NETIF_HWADDRHINT
00768 
00786 err_t
00787 ip_output_hinted(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
00788           u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint)
00789 {
00790   struct netif *netif;
00791   err_t err;
00792 
00793   /* pbufs passed to IP must have a ref-count of 1 as their payload pointer
00794      gets altered as the packet is passed down the stack */
00795   LWIP_ASSERT("p->ref == 1", p->ref == 1);
00796 
00797   if ((netif = ip_route(dest)) == NULL) {
00798     LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
00799       ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest)));
00800     IP_STATS_INC(ip.rterr);
00801     return ERR_RTE;
00802   }
00803 
00804   netif->addr_hint = addr_hint;
00805   err = ip_output_if(p, src, dest, ttl, tos, proto, netif);
00806   netif->addr_hint = NULL;
00807 
00808   return err;
00809 }
00810 #endif /* LWIP_NETIF_HWADDRHINT*/
00811 
00812 #if IP_DEBUG
00813 /* Print an IP header by using LWIP_DEBUGF
00814  * @param p an IP packet, p->payload pointing to the IP header
00815  */
00816 void
00817 ip_debug_print(struct pbuf *p)
00818 {
00819   struct ip_hdr *iphdr = (struct ip_hdr *)p->payload;
00820   u8_t *payload;
00821 
00822   payload = (u8_t *)iphdr + IP_HLEN;
00823 
00824   LWIP_DEBUGF(IP_DEBUG, ("IP header:\n"));
00825   LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
00826   LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" |%2"S16_F" |  0x%02"X16_F" |     %5"U16_F"     | (v, hl, tos, len)\n",
00827                     IPH_V(iphdr),
00828                     IPH_HL(iphdr),
00829                     IPH_TOS(iphdr),
00830                     ntohs(IPH_LEN(iphdr))));
00831   LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
00832   LWIP_DEBUGF(IP_DEBUG, ("|    %5"U16_F"      |%"U16_F"%"U16_F"%"U16_F"|    %4"U16_F"   | (id, flags, offset)\n",
00833                     ntohs(IPH_ID(iphdr)),
00834                     ntohs(IPH_OFFSET(iphdr)) >> 15 & 1,
00835                     ntohs(IPH_OFFSET(iphdr)) >> 14 & 1,
00836                     ntohs(IPH_OFFSET(iphdr)) >> 13 & 1,
00837                     ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK));
00838   LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
00839   LWIP_DEBUGF(IP_DEBUG, ("|  %3"U16_F"  |  %3"U16_F"  |    0x%04"X16_F"     | (ttl, proto, chksum)\n",
00840                     IPH_TTL(iphdr),
00841                     IPH_PROTO(iphdr),
00842                     ntohs(IPH_CHKSUM(iphdr))));
00843   LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
00844   LWIP_DEBUGF(IP_DEBUG, ("|  %3"U16_F"  |  %3"U16_F"  |  %3"U16_F"  |  %3"U16_F"  | (src)\n",
00845                     ip4_addr1_16(&iphdr->src),
00846                     ip4_addr2_16(&iphdr->src),
00847                     ip4_addr3_16(&iphdr->src),
00848                     ip4_addr4_16(&iphdr->src)));
00849   LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
00850   LWIP_DEBUGF(IP_DEBUG, ("|  %3"U16_F"  |  %3"U16_F"  |  %3"U16_F"  |  %3"U16_F"  | (dest)\n",
00851                     ip4_addr1_16(&iphdr->dest),
00852                     ip4_addr2_16(&iphdr->dest),
00853                     ip4_addr3_16(&iphdr->dest),
00854                     ip4_addr4_16(&iphdr->dest)));
00855   LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
00856 }
00857 #endif /* IP_DEBUG */

Generated on Sat May 26 2012 04:34:53 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.