Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

ip.c File Reference

#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/ip.h"
#include "lwip/ip_frag.h"
#include "lwip/inet.h"
#include "lwip/netif.h"
#include "lwip/icmp.h"
#include "lwip/udp.h"
#include "lwip/tcp.h"
#include "lwip/stats.h"
#include "lwip/snmp.h"

Include dependency graph for ip.c:

Go to the source code of this file.

Defines

#define htons   HTONS
#define htonl   HTONL

Functions

void ip_init (void)
netifip_route (struct ip_addr *dest)
err_t ip_input (struct pbuf *p, struct netif *inp)
err_t ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, u8_t ttl, u8_t proto, struct netif *netif)
err_t ip_output (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, u8_t ttl, u8_t proto)


Define Documentation

#define htonl   HTONL
 

Definition at line 59 of file ip.c.

#define htons   HTONS
 

Definition at line 58 of file ip.c.


Function Documentation

void ip_init void   ) 
 

Definition at line 75 of file ip.c.

Referenced by tcpip_thread().

00076 {
00077 }

err_t ip_input struct pbuf p,
struct netif inp
 

Definition at line 230 of file ip.c.

00230                                             {
00231   static struct ip_hdr *iphdr;
00232   static struct netif *netif;
00233   static u16_t iphdrlen;
00234   
00235 #ifdef IP_STATS
00236   ++lwip_stats.ip.recv;
00237 #endif /* IP_STATS */
00238   snmp_inc_ipinreceives();
00239 
00240   /* identify the IP header */
00241   iphdr = p->payload;
00242   if(IPH_V(iphdr) != 4) {
00243     DEBUGF(IP_DEBUG | 1, ("IP packet dropped due to bad version number %d\n", IPH_V(iphdr)));
00244 #if IP_DEBUG
00245     ip_debug_print(p);
00246 #endif /* IP_DEBUG */
00247     pbuf_free(p);
00248 #ifdef IP_STATS
00249     ++lwip_stats.ip.err;
00250     ++lwip_stats.ip.drop;
00251 #endif /* IP_STATS */
00252     snmp_inc_ipunknownprotos();
00253     return ERR_OK;
00254   }
00255   /* obtain IP header length in number of 32-bit words */
00256   iphdrlen = IPH_HL(iphdr);
00257   /* calculate IP header length in bytes */
00258   iphdrlen *= 4;
00259 
00260   /* header length exceeds first pbuf length? */  
00261   if(iphdrlen > p->len) {
00262     DEBUGF(IP_DEBUG | 2, ("IP header (len %u) does not fit in first pbuf (len %u), IP packet droppped.\n",
00263       iphdrlen, p->len));
00264     /* free (drop) packet pbufs */
00265     pbuf_free(p);
00266 #ifdef IP_STATS
00267     ++lwip_stats.ip.lenerr;
00268     ++lwip_stats.ip.drop;
00269 #endif /* IP_STATS */
00270     snmp_inc_ipindiscards();
00271     return ERR_OK;
00272   }
00273 
00274   /* verify checksum */
00275   if(inet_chksum(iphdr, iphdrlen) != 0) {
00276 
00277     DEBUGF(IP_DEBUG | 2, ("Checksum (0x%x) failed, IP packet dropped.\n", inet_chksum(iphdr, iphdrlen)));
00278 #if IP_DEBUG
00279     ip_debug_print(p);
00280 #endif /* IP_DEBUG */
00281     pbuf_free(p);
00282 #ifdef IP_STATS
00283     ++lwip_stats.ip.chkerr;
00284     ++lwip_stats.ip.drop;
00285 #endif /* IP_STATS */
00286     snmp_inc_ipindiscards();
00287     return ERR_OK;
00288   }
00289   
00290   /* Trim pbuf. This should have been done at the netif layer,
00291      but we'll do it anyway just to be sure that its done. */
00292   pbuf_realloc(p, ntohs(IPH_LEN(iphdr)));
00293 
00294   /* is this packet for us? */
00295   for(netif = netif_list; netif != NULL; netif = netif->next) {
00296 
00297     DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%lx netif->ip_addr 0x%lx (0x%lx, 0x%lx, 0x%lx)\n",
00298                       iphdr->dest.addr, netif->ip_addr.addr,
00299                       iphdr->dest.addr & netif->netmask.addr,
00300                       netif->ip_addr.addr & netif->netmask.addr,
00301                       iphdr->dest.addr & ~(netif->netmask.addr)));
00302 
00303     /* interface configured? */
00304     if(!ip_addr_isany(&(netif->ip_addr)))
00305     {
00306       /* unicast to this interface address? */
00307       if(ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr)) ||
00308         /* or broadcast matching this interface network address? */
00309         (ip_addr_isbroadcast(&(iphdr->dest), &(netif->netmask)) &&
00310          ip_addr_maskcmp(&(iphdr->dest), &(netif->ip_addr), &(netif->netmask))) ||
00311          /* or restricted broadcast? */
00312          ip_addr_cmp(&(iphdr->dest), IP_ADDR_BROADCAST)) {
00313          DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n",
00314                        netif->name[0], netif->name[1]));
00315          /* break out of for loop */
00316          break;
00317       }
00318     }
00319   }
00320 #if LWIP_DHCP
00321   /* Pass DHCP messages regardless of destination address. DHCP traffic is addressed
00322      using link layer addressing (such as Ethernet MAC) so we must not filter on IP.
00323      According to RFC 1542 section 3.1.1, referred by RFC 2131). */
00324   if(netif == NULL) {
00325     /* remote port is DHCP server? */
00326     if(IPH_PROTO(iphdr) == IP_PROTO_UDP) {
00327       DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: UDP packet to DHCP client port %u\n",
00328         ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdrlen))->dest)));
00329       if (ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdrlen))->dest) == DHCP_CLIENT_PORT) {
00330         DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: DHCP packet accepted.\n"));
00331         netif = inp;
00332       }
00333     }
00334   }
00335 #endif /* LWIP_DHCP */
00336         /* packet not for us? */  
00337   if(netif == NULL) {
00338     /* packet not for us, route or discard */
00339     DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: packet not for us.\n"));
00340 #if IP_FORWARD
00341     /* non-broadcast packet? */
00342     if(!ip_addr_isbroadcast(&(iphdr->dest), &(inp->netmask))) {
00343       /* try to forward IP packet on (other) interfaces */
00344       ip_forward(p, iphdr, inp);
00345     }
00346     else
00347 #endif /* IP_FORWARD */
00348     {
00349       snmp_inc_ipindiscards();
00350     }
00351     pbuf_free(p);
00352     return ERR_OK;
00353   }
00354 
00355 #if IP_REASSEMBLY
00356   if((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) {
00357     DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04x tot_len=%u len=%u MF=%u offset=%u), calling ip_reass()\n", ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & htons(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8));
00358     p = ip_reass(p);
00359     if(p == NULL) {
00360       return ERR_OK;
00361     }
00362     iphdr = p->payload;
00363   }
00364 #else /* IP_REASSEMBLY */
00365   if((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) {
00366     pbuf_free(p);
00367     DEBUGF(IP_DEBUG | 2, ("IP packet dropped since it was fragmented (0x%x) (while IP_REASSEMBLY == 0).\n",
00368                   ntohs(IPH_OFFSET(iphdr))));
00369 #ifdef IP_STATS
00370     ++lwip_stats.ip.opterr;
00371     ++lwip_stats.ip.drop;
00372 #endif /* IP_STATS */
00373     snmp_inc_ipunknownprotos();
00374     return ERR_OK;
00375   }
00376 #endif /* IP_REASSEMBLY */
00377   
00378 #if IP_OPTIONS == 0
00379   if (iphdrlen > IP_HLEN) {
00380     DEBUGF(IP_DEBUG | 2, ("IP packet dropped since there were IP options (while IP_OPTIONS == 0).\n"));
00381     pbuf_free(p);    
00382 #ifdef IP_STATS
00383     ++lwip_stats.ip.opterr;
00384     ++lwip_stats.ip.drop;
00385 #endif /* IP_STATS */
00386     snmp_inc_ipunknownprotos();
00387     return ERR_OK;
00388   }  
00389 #endif /* IP_OPTIONS == 0 */
00390 
00391   /* send to upper layers */
00392 #if IP_DEBUG
00393   DEBUGF(IP_DEBUG, ("ip_input: \n"));
00394   ip_debug_print(p);
00395   DEBUGF(IP_DEBUG, ("ip_input: p->len %d p->tot_len %d\n", p->len, p->tot_len));
00396 #endif /* IP_DEBUG */   
00397 
00398   switch(IPH_PROTO(iphdr)) {
00399 #if LWIP_UDP > 0    
00400   case IP_PROTO_UDP:
00401     snmp_inc_ipindelivers();
00402     udp_input(p, inp);
00403     break;
00404 #endif /* LWIP_UDP */
00405 #if LWIP_TCP > 0    
00406   case IP_PROTO_TCP:
00407     snmp_inc_ipindelivers();
00408     tcp_input(p, inp);
00409     break;
00410 #endif /* LWIP_TCP */
00411   case IP_PROTO_ICMP:
00412     snmp_inc_ipindelivers();
00413     icmp_input(p, inp);
00414     break;
00415   default:
00416     /* send ICMP destination protocol unreachable unless is was a broadcast */
00417     if(!ip_addr_isbroadcast(&(iphdr->dest), &(inp->netmask)) &&
00418        !ip_addr_ismulticast(&(iphdr->dest))) {
00419       p->payload = iphdr;
00420       icmp_dest_unreach(p, ICMP_DUR_PROTO);
00421     }
00422     pbuf_free(p);
00423 
00424     DEBUGF(IP_DEBUG | 2, ("Unsupported transport protocol %d\n", IPH_PROTO(iphdr)));
00425 
00426 #ifdef IP_STATS
00427     ++lwip_stats.ip.proterr;
00428     ++lwip_stats.ip.drop;
00429 #endif /* IP_STATS */
00430     snmp_inc_ipunknownprotos();
00431 
00432   }
00433   return ERR_OK;
00434 }

err_t ip_output struct pbuf p,
struct ip_addr src,
struct ip_addr dest,
u8_t  ttl,
u8_t  proto
 

Definition at line 518 of file ip.c.

00520 {
00521   struct netif *netif;
00522   
00523   if((netif = ip_route(dest)) == NULL) {
00524     DEBUGF(IP_DEBUG | 2, ("ip_output: No route to 0x%lx\n", dest->addr));
00525 
00526 #ifdef IP_STATS
00527     ++lwip_stats.ip.rterr;
00528 #endif /* IP_STATS */
00529     snmp_inc_ipoutdiscards();
00530     return ERR_RTE;
00531   }
00532 
00533   return ip_output_if(p, src, dest, ttl, proto, netif);
00534 }

err_t ip_output_if struct pbuf p,
struct ip_addr src,
struct ip_addr dest,
u8_t  ttl,
u8_t  proto,
struct netif netif
 

Definition at line 446 of file ip.c.

00449 {
00450   static struct ip_hdr *iphdr;
00451   static u16_t ip_id = 0;
00452 
00453   snmp_inc_ipoutrequests();
00454   
00455   if(dest != IP_HDRINCL) {
00456     if(pbuf_header(p, IP_HLEN)) {
00457       DEBUGF(IP_DEBUG | 2, ("ip_output: not enough room for IP header in pbuf\n"));
00458       
00459 #ifdef IP_STATS
00460       ++lwip_stats.ip.err;
00461 #endif /* IP_STATS */
00462       snmp_inc_ipoutdiscards();
00463       return ERR_BUF;
00464     }
00465     
00466     iphdr = p->payload;
00467     
00468     IPH_TTL_SET(iphdr, ttl);
00469     IPH_PROTO_SET(iphdr, proto);
00470     
00471     ip_addr_set(&(iphdr->dest), dest);
00472 
00473     IPH_VHLTOS_SET(iphdr, 4, IP_HLEN / 4, 0);
00474     IPH_LEN_SET(iphdr, htons(p->tot_len));
00475     IPH_OFFSET_SET(iphdr, htons(IP_DF));
00476     IPH_ID_SET(iphdr, htons(ip_id));
00477     ++ip_id;
00478 
00479     if(ip_addr_isany(src)) {
00480       ip_addr_set(&(iphdr->src), &(netif->ip_addr));
00481     } else {
00482       ip_addr_set(&(iphdr->src), src);
00483     }
00484 
00485     IPH_CHKSUM_SET(iphdr, 0);
00486     IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
00487   } else {
00488     iphdr = p->payload;
00489     dest = &(iphdr->dest);
00490   }
00491 
00492 #if IP_FRAG     
00493   /* don't fragment if interface has mtu set to 0 [loopif] */
00494   if (netif->mtu && (p->tot_len > netif->mtu))
00495     return ip_frag(p,netif,dest);
00496 #endif
00497   
00498 #ifdef IP_STATS
00499   lwip_stats.ip.xmit++;
00500 #endif /* IP_STATS */
00501   DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%u\n", netif->name[0], netif->name[1], netif->num));
00502 #if IP_DEBUG
00503   ip_debug_print(p);
00504 #endif /* IP_DEBUG */
00505 
00506   DEBUGF(IP_DEBUG, ("netif->output()"));
00507 
00508   return netif->output(netif, p, dest);  
00509 }

struct netif* ip_route struct ip_addr dest  ) 
 

Definition at line 138 of file ip.c.

00139 {
00140   struct netif *netif;
00141 
00142   /* iterate through netifs */  
00143   for(netif = netif_list; netif != NULL; netif = netif->next) {
00144     /* network mask matches? */
00145     if(ip_addr_maskcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
00146       /* return netif on which to forward IP packet */
00147       return netif;
00148     }
00149   }
00150   /* no matching netif found, use default netif */
00151   return netif_default;
00152 }


Generated on Wed Jan 14 12:59:05 2004 for RTL-lwIP-0.4 by doxygen 1.3.4