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

etharp.c
Go to the documentation of this file.
00001 
00014 /*
00015  * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
00016  * Copyright (c) 2003-2004 Leon Woestenberg <leon.woestenberg@axon.tv>
00017  * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands.
00018  * All rights reserved.
00019  *
00020  * Redistribution and use in source and binary forms, with or without modification,
00021  * are permitted provided that the following conditions are met:
00022  *
00023  * 1. Redistributions of source code must retain the above copyright notice,
00024  *    this list of conditions and the following disclaimer.
00025  * 2. Redistributions in binary form must reproduce the above copyright notice,
00026  *    this list of conditions and the following disclaimer in the documentation
00027  *    and/or other materials provided with the distribution.
00028  * 3. The name of the author may not be used to endorse or promote products
00029  *    derived from this software without specific prior written permission.
00030  *
00031  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
00032  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00033  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
00034  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00035  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
00036  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00037  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00038  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
00039  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
00040  * OF SUCH DAMAGE.
00041  *
00042  * This file is part of the lwIP TCP/IP stack.
00043  *
00044  */
00045  
00046 #include "lwip/opt.h"
00047 
00048 #if LWIP_ARP || LWIP_ETHERNET
00049 
00050 #include "lwip/ip_addr.h"
00051 #include "lwip/def.h"
00052 #include "lwip/ip.h"
00053 #include "lwip/stats.h"
00054 #include "lwip/snmp.h"
00055 #include "lwip/dhcp.h"
00056 #include "lwip/autoip.h"
00057 #include "netif/etharp.h"
00058 
00059 #if PPPOE_SUPPORT
00060 #include "netif/ppp_oe.h"
00061 #endif /* PPPOE_SUPPORT */
00062 
00063 #include <string.h>
00064 
00065 const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
00066 const struct eth_addr ethzero = {{0,0,0,0,0,0}};
00067 
00068 #if LWIP_ARP /* don't build if not configured for use in lwipopts.h */
00069 
00074 #define ARP_MAXAGE 240
00075 
00082 #define ARP_MAXPENDING 2
00083 
00084 #define HWTYPE_ETHERNET 1
00085 
00086 enum etharp_state {
00087   ETHARP_STATE_EMPTY = 0,
00088   ETHARP_STATE_PENDING,
00089   ETHARP_STATE_STABLE
00090 };
00091 
00092 struct etharp_entry {
00093 #if ARP_QUEUEING
00094 
00095   struct etharp_q_entry *q;
00096 #else /* ARP_QUEUEING */
00097 
00098   struct pbuf *q;
00099 #endif /* ARP_QUEUEING */
00100   ip_addr_t ipaddr;
00101   struct eth_addr ethaddr;
00102 #if LWIP_SNMP
00103   struct netif *netif;
00104 #endif /* LWIP_SNMP */
00105   u8_t state;
00106   u8_t ctime;
00107 #if ETHARP_SUPPORT_STATIC_ENTRIES
00108   u8_t static_entry;
00109 #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
00110 };
00111 
00112 static struct etharp_entry arp_table[ARP_TABLE_SIZE];
00113 
00114 #if !LWIP_NETIF_HWADDRHINT
00115 static u8_t etharp_cached_entry;
00116 #endif /* !LWIP_NETIF_HWADDRHINT */
00117 
00120 #define ETHARP_FLAG_TRY_HARD     1
00121 #define ETHARP_FLAG_FIND_ONLY    2
00122 #define ETHARP_FLAG_STATIC_ENTRY 4
00123 
00124 #if LWIP_NETIF_HWADDRHINT
00125 #define ETHARP_SET_HINT(netif, hint)  if (((netif) != NULL) && ((netif)->addr_hint != NULL))  \
00126                                       *((netif)->addr_hint) = (hint);
00127 #else /* LWIP_NETIF_HWADDRHINT */
00128 #define ETHARP_SET_HINT(netif, hint)  (etharp_cached_entry = (hint))
00129 #endif /* LWIP_NETIF_HWADDRHINT */
00130 
00131 static err_t update_arp_entry(struct netif *netif, ip_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags);
00132 
00133 
00134 /* Some checks, instead of etharp_init(): */
00135 #if (LWIP_ARP && (ARP_TABLE_SIZE > 0x7f))
00136   #error "ARP_TABLE_SIZE must fit in an s8_t, you have to reduce it in your lwipopts.h"
00137 #endif
00138 
00139 
00140 #if ARP_QUEUEING
00141 
00146 static void
00147 free_etharp_q(struct etharp_q_entry *q)
00148 {
00149   struct etharp_q_entry *r;
00150   LWIP_ASSERT("q != NULL", q != NULL);
00151   LWIP_ASSERT("q->p != NULL", q->p != NULL);
00152   while (q) {
00153     r = q;
00154     q = q->next;
00155     LWIP_ASSERT("r->p != NULL", (r->p != NULL));
00156     pbuf_free(r->p);
00157     memp_free(MEMP_ARP_QUEUE, r);
00158   }
00159 }
00160 #else /* ARP_QUEUEING */
00161 
00163 #define free_etharp_q(q) pbuf_free(q)
00164 
00165 #endif /* ARP_QUEUEING */
00166 
00168 static void
00169 free_entry(int i)
00170 {
00171   /* remove from SNMP ARP index tree */
00172   snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr);
00173   /* and empty packet queue */
00174   if (arp_table[i].q != NULL) {
00175     /* remove all queued packets */
00176     LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: freeing entry %"U16_F", packet queue %p.\n", (u16_t)i, (void *)(arp_table[i].q)));
00177     free_etharp_q(arp_table[i].q);
00178     arp_table[i].q = NULL;
00179   }
00180   /* recycle entry for re-use */      
00181   arp_table[i].state = ETHARP_STATE_EMPTY;
00182 #if ETHARP_SUPPORT_STATIC_ENTRIES
00183   arp_table[i].static_entry = 0;
00184 #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
00185 #ifdef LWIP_DEBUG
00186   /* for debugging, clean out the complete entry */
00187   arp_table[i].ctime = 0;
00188 #if LWIP_SNMP
00189   arp_table[i].netif = NULL;
00190 #endif /* LWIP_SNMP */
00191   ip_addr_set_zero(&arp_table[i].ipaddr);
00192   arp_table[i].ethaddr = ethzero;
00193 #endif /* LWIP_DEBUG */
00194 }
00195 
00202 void
00203 etharp_tmr(void)
00204 {
00205   u8_t i;
00206 
00207   LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n"));
00208   /* remove expired entries from the ARP table */
00209   for (i = 0; i < ARP_TABLE_SIZE; ++i) {
00210     u8_t state = arp_table[i].state;
00211     if (state != ETHARP_STATE_EMPTY
00212 #if ETHARP_SUPPORT_STATIC_ENTRIES
00213       && (arp_table[i].static_entry == 0)
00214 #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
00215       ) {
00216       arp_table[i].ctime++;
00217       if ((arp_table[i].ctime >= ARP_MAXAGE) ||
00218           ((arp_table[i].state == ETHARP_STATE_PENDING)  &&
00219            (arp_table[i].ctime >= ARP_MAXPENDING))) {
00220         /* pending or stable entry has become old! */
00221         LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired %s entry %"U16_F".\n",
00222              arp_table[i].state == ETHARP_STATE_STABLE ? "stable" : "pending", (u16_t)i));
00223         /* clean up entries that have just been expired */
00224         free_entry(i);
00225       }
00226 #if ARP_QUEUEING
00227       /* still pending entry? (not expired) */
00228       if (arp_table[i].state == ETHARP_STATE_PENDING) {
00229         /* resend an ARP query here? */
00230       }
00231 #endif /* ARP_QUEUEING */
00232     }
00233   }
00234 }
00235 
00257 static s8_t
00258 find_entry(ip_addr_t *ipaddr, u8_t flags)
00259 {
00260   s8_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE;
00261   s8_t empty = ARP_TABLE_SIZE;
00262   u8_t i = 0, age_pending = 0, age_stable = 0;
00263   /* oldest entry with packets on queue */
00264   s8_t old_queue = ARP_TABLE_SIZE;
00265   /* its age */
00266   u8_t age_queue = 0;
00267 
00274   /* a) in a single search sweep, do all of this
00275    * 1) remember the first empty entry (if any)
00276    * 2) remember the oldest stable entry (if any)
00277    * 3) remember the oldest pending entry without queued packets (if any)
00278    * 4) remember the oldest pending entry with queued packets (if any)
00279    * 5) search for a matching IP entry, either pending or stable
00280    *    until 5 matches, or all entries are searched for.
00281    */
00282 
00283   for (i = 0; i < ARP_TABLE_SIZE; ++i) {
00284     u8_t state = arp_table[i].state;
00285     /* no empty entry found yet and now we do find one? */
00286     if ((empty == ARP_TABLE_SIZE) && (state == ETHARP_STATE_EMPTY)) {
00287       LWIP_DEBUGF(ETHARP_DEBUG, ("find_entry: found empty entry %"U16_F"\n", (u16_t)i));
00288       /* remember first empty entry */
00289       empty = i;
00290     } else if (state != ETHARP_STATE_EMPTY) {
00291       LWIP_ASSERT("state == ETHARP_STATE_PENDING || state == ETHARP_STATE_STABLE",
00292         state == ETHARP_STATE_PENDING || state == ETHARP_STATE_STABLE);
00293       /* if given, does IP address match IP address in ARP entry? */
00294       if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
00295         LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: found matching entry %"U16_F"\n", (u16_t)i));
00296         /* found exact IP address match, simply bail out */
00297         return i;
00298       }
00299       /* pending entry? */
00300       if (state == ETHARP_STATE_PENDING) {
00301         /* pending with queued packets? */
00302         if (arp_table[i].q != NULL) {
00303           if (arp_table[i].ctime >= age_queue) {
00304             old_queue = i;
00305             age_queue = arp_table[i].ctime;
00306           }
00307         } else
00308         /* pending without queued packets? */
00309         {
00310           if (arp_table[i].ctime >= age_pending) {
00311             old_pending = i;
00312             age_pending = arp_table[i].ctime;
00313           }
00314         }
00315       /* stable entry? */
00316       } else if (state == ETHARP_STATE_STABLE) {
00317 #if ETHARP_SUPPORT_STATIC_ENTRIES
00318         /* don't record old_stable for static entries since they never expire */
00319         if (arp_table[i].static_entry == 0)
00320 #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
00321         {
00322           /* remember entry with oldest stable entry in oldest, its age in maxtime */
00323           if (arp_table[i].ctime >= age_stable) {
00324             old_stable = i;
00325             age_stable = arp_table[i].ctime;
00326           }
00327         }
00328       }
00329     }
00330   }
00331   /* { we have no match } => try to create a new entry */
00332    
00333   /* don't create new entry, only search? */
00334   if (((flags & ETHARP_FLAG_FIND_ONLY) != 0) ||
00335       /* or no empty entry found and not allowed to recycle? */
00336       ((empty == ARP_TABLE_SIZE) && ((flags & ETHARP_FLAG_TRY_HARD) == 0))) {
00337     LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: no empty entry found and not allowed to recycle\n"));
00338     return (s8_t)ERR_MEM;
00339   }
00340   
00341   /* b) choose the least destructive entry to recycle:
00342    * 1) empty entry
00343    * 2) oldest stable entry
00344    * 3) oldest pending entry without queued packets
00345    * 4) oldest pending entry with queued packets
00346    * 
00347    * { ETHARP_FLAG_TRY_HARD is set at this point }
00348    */ 
00349 
00350   /* 1) empty entry available? */
00351   if (empty < ARP_TABLE_SIZE) {
00352     i = empty;
00353     LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting empty entry %"U16_F"\n", (u16_t)i));
00354   } else {
00355     /* 2) found recyclable stable entry? */
00356     if (old_stable < ARP_TABLE_SIZE) {
00357       /* recycle oldest stable*/
00358       i = old_stable;
00359       LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i));
00360       /* no queued packets should exist on stable entries */
00361       LWIP_ASSERT("arp_table[i].q == NULL", arp_table[i].q == NULL);
00362     /* 3) found recyclable pending entry without queued packets? */
00363     } else if (old_pending < ARP_TABLE_SIZE) {
00364       /* recycle oldest pending */
00365       i = old_pending;
00366       LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i));
00367     /* 4) found recyclable pending entry with queued packets? */
00368     } else if (old_queue < ARP_TABLE_SIZE) {
00369       /* recycle oldest pending (queued packets are free in free_entry) */
00370       i = old_queue;
00371       LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F", freeing packet queue %p\n", (u16_t)i, (void *)(arp_table[i].q)));
00372       /* no empty or recyclable entries found */
00373     } else {
00374       LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: no empty or recyclable entries found\n"));
00375       return (s8_t)ERR_MEM;
00376     }
00377 
00378     /* { empty or recyclable entry found } */
00379     LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE);
00380     free_entry(i);
00381   }
00382 
00383   LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE);
00384   LWIP_ASSERT("arp_table[i].state == ETHARP_STATE_EMPTY",
00385     arp_table[i].state == ETHARP_STATE_EMPTY);
00386 
00387   /* IP address given? */
00388   if (ipaddr != NULL) {
00389     /* set IP address */
00390     ip_addr_copy(arp_table[i].ipaddr, *ipaddr);
00391   }
00392   arp_table[i].ctime = 0;
00393 #if ETHARP_SUPPORT_STATIC_ENTRIES
00394   arp_table[i].static_entry = 0;
00395 #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
00396   return (err_t)i;
00397 }
00398 
00409 static err_t
00410 etharp_send_ip(struct netif *netif, struct pbuf *p, struct eth_addr *src, struct eth_addr *dst)
00411 {
00412   struct eth_hdr *ethhdr = (struct eth_hdr *)p->payload;
00413 
00414   LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!",
00415               (netif->hwaddr_len == ETHARP_HWADDR_LEN));
00416   ETHADDR32_COPY(&ethhdr->dest, dst);
00417   ETHADDR16_COPY(&ethhdr->src, src);
00418   ethhdr->type = PP_HTONS(ETHTYPE_IP);
00419   LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_send_ip: sending packet %p\n", (void *)p));
00420   /* send the packet */
00421   return netif->linkoutput(netif, p);
00422 }
00423 
00442 static err_t
00443 update_arp_entry(struct netif *netif, ip_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags)
00444 {
00445   s8_t i;
00446   LWIP_ASSERT("netif->hwaddr_len == ETHARP_HWADDR_LEN", netif->hwaddr_len == ETHARP_HWADDR_LEN);
00447   LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n",
00448     ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr),
00449     ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2],
00450     ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5]));
00451   /* non-unicast address? */
00452   if (ip_addr_isany(ipaddr) ||
00453       ip_addr_isbroadcast(ipaddr, netif) ||
00454       ip_addr_ismulticast(ipaddr)) {
00455     LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry: will not add non-unicast IP address to ARP cache\n"));
00456     return ERR_ARG;
00457   }
00458   /* find or create ARP entry */
00459   i = find_entry(ipaddr, flags);
00460   /* bail out if no entry could be found */
00461   if (i < 0) {
00462     return (err_t)i;
00463   }
00464 
00465 #if ETHARP_SUPPORT_STATIC_ENTRIES
00466   if (flags & ETHARP_FLAG_STATIC_ENTRY) {
00467     /* record static type */
00468     arp_table[i].static_entry = 1;
00469   }
00470 #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
00471 
00472   /* mark it stable */
00473   arp_table[i].state = ETHARP_STATE_STABLE;
00474 
00475 #if LWIP_SNMP
00476   /* record network interface */
00477   arp_table[i].netif = netif;
00478 #endif /* LWIP_SNMP */
00479   /* insert in SNMP ARP index tree */
00480   snmp_insert_arpidx_tree(netif, &arp_table[i].ipaddr);
00481 
00482   LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry: updating stable entry %"S16_F"\n", (s16_t)i));
00483   /* update address */
00484   ETHADDR32_COPY(&arp_table[i].ethaddr, ethaddr);
00485   /* reset time stamp */
00486   arp_table[i].ctime = 0;
00487   /* this is where we will send out queued packets! */
00488 #if ARP_QUEUEING
00489   while (arp_table[i].q != NULL) {
00490     struct pbuf *p;
00491     /* remember remainder of queue */
00492     struct etharp_q_entry *q = arp_table[i].q;
00493     /* pop first item off the queue */
00494     arp_table[i].q = q->next;
00495     /* get the packet pointer */
00496     p = q->p;
00497     /* now queue entry can be freed */
00498     memp_free(MEMP_ARP_QUEUE, q);
00499 #else /* ARP_QUEUEING */
00500   if (arp_table[i].q != NULL) {
00501     struct pbuf *p = arp_table[i].q;
00502     arp_table[i].q = NULL;
00503 #endif /* ARP_QUEUEING */
00504     /* send the queued IP packet */
00505     etharp_send_ip(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr);
00506     /* free the queued IP packet */
00507     pbuf_free(p);
00508   }
00509   return ERR_OK;
00510 }
00511 
00512 #if ETHARP_SUPPORT_STATIC_ENTRIES
00513 
00521 err_t
00522 etharp_add_static_entry(ip_addr_t *ipaddr, struct eth_addr *ethaddr)
00523 {
00524   struct netif *netif;
00525   LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_add_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n",
00526     ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr),
00527     ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2],
00528     ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5]));
00529 
00530   netif = ip_route(ipaddr);
00531   if (netif == NULL) {
00532     return ERR_RTE;
00533   }
00534 
00535   return update_arp_entry(netif, ipaddr, ethaddr, ETHARP_FLAG_TRY_HARD | ETHARP_FLAG_STATIC_ENTRY);
00536 }
00537 
00546 err_t
00547 etharp_remove_static_entry(ip_addr_t *ipaddr)
00548 {
00549   s8_t i;
00550   LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_remove_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
00551     ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr)));
00552 
00553   /* find or create ARP entry */
00554   i = find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY);
00555   /* bail out if no entry could be found */
00556   if (i < 0) {
00557     return (err_t)i;
00558   }
00559 
00560   if ((arp_table[i].state != ETHARP_STATE_STABLE) ||
00561     (arp_table[i].static_entry == 0)) {
00562     /* entry wasn't a static entry, cannot remove it */
00563     return ERR_ARG;
00564   }
00565   /* entry found, free it */
00566   free_entry(i);
00567   return ERR_OK;
00568 }
00569 #endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
00570 
00582 s8_t
00583 etharp_find_addr(struct netif *netif, ip_addr_t *ipaddr,
00584          struct eth_addr **eth_ret, ip_addr_t **ip_ret)
00585 {
00586   s8_t i;
00587 
00588   LWIP_ASSERT("eth_ret != NULL && ip_ret != NULL",
00589     eth_ret != NULL && ip_ret != NULL);
00590 
00591   LWIP_UNUSED_ARG(netif);
00592 
00593   i = find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY);
00594   if((i >= 0) && arp_table[i].state == ETHARP_STATE_STABLE) {
00595       *eth_ret = &arp_table[i].ethaddr;
00596       *ip_ret = &arp_table[i].ipaddr;
00597       return i;
00598   }
00599   return -1;
00600 }
00601 
00602 #if ETHARP_TRUST_IP_MAC
00603 
00618 static void
00619 etharp_ip_input(struct netif *netif, struct pbuf *p)
00620 {
00621   struct eth_hdr *ethhdr;
00622   struct ip_hdr *iphdr;
00623   ip_addr_t iphdr_src;
00624   LWIP_ERROR("netif != NULL", (netif != NULL), return;);
00625 
00626   /* Only insert an entry if the source IP address of the
00627      incoming IP packet comes from a host on the local network. */
00628   ethhdr = (struct eth_hdr *)p->payload;
00629   iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
00630 #if ETHARP_SUPPORT_VLAN
00631   if (ethhdr->type == PP_HTONS(ETHTYPE_VLAN)) {
00632     iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR);
00633   }
00634 #endif /* ETHARP_SUPPORT_VLAN */
00635 
00636   ip_addr_copy(iphdr_src, iphdr->src);
00637 
00638   /* source is not on the local network? */
00639   if (!ip_addr_netcmp(&iphdr_src, &(netif->ip_addr), &(netif->netmask))) {
00640     /* do nothing */
00641     return;
00642   }
00643 
00644   LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n"));
00645   /* update the source IP address in the cache, if present */
00646   /* @todo We could use ETHARP_FLAG_TRY_HARD if we think we are going to talk
00647    * back soon (for example, if the destination IP address is ours. */
00648   update_arp_entry(netif, &iphdr_src, &(ethhdr->src), ETHARP_FLAG_FIND_ONLY);
00649 }
00650 #endif /* ETHARP_TRUST_IP_MAC */
00651 
00667 static void
00668 etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
00669 {
00670   struct etharp_hdr *hdr;
00671   struct eth_hdr *ethhdr;
00672   /* these are aligned properly, whereas the ARP header fields might not be */
00673   ip_addr_t sipaddr, dipaddr;
00674   u8_t for_us;
00675 #if LWIP_AUTOIP
00676   const u8_t * ethdst_hwaddr;
00677 #endif /* LWIP_AUTOIP */
00678 
00679   LWIP_ERROR("netif != NULL", (netif != NULL), return;);
00680 
00681   /* drop short ARP packets: we have to check for p->len instead of p->tot_len here
00682      since a struct etharp_hdr is pointed to p->payload, so it musn't be chained! */
00683   if (p->len < SIZEOF_ETHARP_PACKET) {
00684     LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
00685       ("etharp_arp_input: packet dropped, too short (%"S16_F"/%"S16_F")\n", p->tot_len,
00686       (s16_t)SIZEOF_ETHARP_PACKET));
00687     ETHARP_STATS_INC(etharp.lenerr);
00688     ETHARP_STATS_INC(etharp.drop);
00689     pbuf_free(p);
00690     return;
00691   }
00692 
00693   ethhdr = (struct eth_hdr *)p->payload;
00694   hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
00695 #if ETHARP_SUPPORT_VLAN
00696   if (ethhdr->type == PP_HTONS(ETHTYPE_VLAN)) {
00697     hdr = (struct etharp_hdr *)(((u8_t*)ethhdr) + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR);
00698   }
00699 #endif /* ETHARP_SUPPORT_VLAN */
00700 
00701   /* RFC 826 "Packet Reception": */
00702   if ((hdr->hwtype != PP_HTONS(HWTYPE_ETHERNET)) ||
00703       (hdr->hwlen != ETHARP_HWADDR_LEN) ||
00704       (hdr->protolen != sizeof(ip_addr_t)) ||
00705       (hdr->proto != PP_HTONS(ETHTYPE_IP)))  {
00706     LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
00707       ("etharp_arp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n",
00708       hdr->hwtype, hdr->hwlen, hdr->proto, hdr->protolen));
00709     ETHARP_STATS_INC(etharp.proterr);
00710     ETHARP_STATS_INC(etharp.drop);
00711     pbuf_free(p);
00712     return;
00713   }
00714   ETHARP_STATS_INC(etharp.recv);
00715 
00716 #if LWIP_AUTOIP
00717   /* We have to check if a host already has configured our random
00718    * created link local address and continously check if there is
00719    * a host with this IP-address so we can detect collisions */
00720   autoip_arp_reply(netif, hdr);
00721 #endif /* LWIP_AUTOIP */
00722 
00723   /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without
00724    * structure packing (not using structure copy which breaks strict-aliasing rules). */
00725   IPADDR2_COPY(&sipaddr, &hdr->sipaddr);
00726   IPADDR2_COPY(&dipaddr, &hdr->dipaddr);
00727 
00728   /* this interface is not configured? */
00729   if (ip_addr_isany(&netif->ip_addr)) {
00730     for_us = 0;
00731   } else {
00732     /* ARP packet directed to us? */
00733     for_us = (u8_t)ip_addr_cmp(&dipaddr, &(netif->ip_addr));
00734   }
00735 
00736   /* ARP message directed to us?
00737       -> add IP address in ARP cache; assume requester wants to talk to us,
00738          can result in directly sending the queued packets for this host.
00739      ARP message not directed to us?
00740       ->  update the source IP address in the cache, if present */
00741   update_arp_entry(netif, &sipaddr, &(hdr->shwaddr),
00742                    for_us ? ETHARP_FLAG_TRY_HARD : ETHARP_FLAG_FIND_ONLY);
00743 
00744   /* now act on the message itself */
00745   switch (hdr->opcode) {
00746   /* ARP request? */
00747   case PP_HTONS(ARP_REQUEST):
00748     /* ARP request. If it asked for our address, we send out a
00749      * reply. In any case, we time-stamp any existing ARP entry,
00750      * and possiby send out an IP packet that was queued on it. */
00751 
00752     LWIP_DEBUGF (ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: incoming ARP request\n"));
00753     /* ARP request for our address? */
00754     if (for_us) {
00755 
00756       LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: replying to ARP request for our IP address\n"));
00757       /* Re-use pbuf to send ARP reply.
00758          Since we are re-using an existing pbuf, we can't call etharp_raw since
00759          that would allocate a new pbuf. */
00760       hdr->opcode = htons(ARP_REPLY);
00761 
00762       IPADDR2_COPY(&hdr->dipaddr, &hdr->sipaddr);
00763       IPADDR2_COPY(&hdr->sipaddr, &netif->ip_addr);
00764 
00765       LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!",
00766                   (netif->hwaddr_len == ETHARP_HWADDR_LEN));
00767 #if LWIP_AUTOIP
00768       /* If we are using Link-Local, all ARP packets that contain a Link-Local
00769        * 'sender IP address' MUST be sent using link-layer broadcast instead of
00770        * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */
00771       ethdst_hwaddr = ip_addr_islinklocal(&netif->ip_addr) ? (u8_t*)(ethbroadcast.addr) : hdr->shwaddr.addr;
00772 #endif /* LWIP_AUTOIP */
00773 
00774       ETHADDR16_COPY(&hdr->dhwaddr, &hdr->shwaddr);
00775 #if LWIP_AUTOIP
00776       ETHADDR16_COPY(&ethhdr->dest, ethdst_hwaddr);
00777 #else  /* LWIP_AUTOIP */
00778       ETHADDR16_COPY(&ethhdr->dest, &hdr->shwaddr);
00779 #endif /* LWIP_AUTOIP */
00780       ETHADDR16_COPY(&hdr->shwaddr, ethaddr);
00781       ETHADDR16_COPY(&ethhdr->src, ethaddr);
00782 
00783       /* hwtype, hwaddr_len, proto, protolen and the type in the ethernet header
00784          are already correct, we tested that before */
00785 
00786       /* return ARP reply */
00787       netif->linkoutput(netif, p);
00788     /* we are not configured? */
00789     } else if (ip_addr_isany(&netif->ip_addr)) {
00790       /* { for_us == 0 and netif->ip_addr.addr == 0 } */
00791       LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: we are unconfigured, ARP request ignored.\n"));
00792     /* request was not directed to us */
00793     } else {
00794       /* { for_us == 0 and netif->ip_addr.addr != 0 } */
00795       LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: ARP request was not for us.\n"));
00796     }
00797     break;
00798   case PP_HTONS(ARP_REPLY):
00799     /* ARP reply. We already updated the ARP cache earlier. */
00800     LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n"));
00801 #if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
00802     /* DHCP wants to know about ARP replies from any host with an
00803      * IP address also offered to us by the DHCP server. We do not
00804      * want to take a duplicate IP address on a single network.
00805      * @todo How should we handle redundant (fail-over) interfaces? */
00806     dhcp_arp_reply(netif, &sipaddr);
00807 #endif /* (LWIP_DHCP && DHCP_DOES_ARP_CHECK) */
00808     break;
00809   default:
00810     LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %"S16_F"\n", htons(hdr->opcode)));
00811     ETHARP_STATS_INC(etharp.err);
00812     break;
00813   }
00814   /* free ARP packet */
00815   pbuf_free(p);
00816 }
00817 
00836 err_t
00837 etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr)
00838 {
00839   struct eth_addr *dest, mcastaddr;
00840 
00841   /* make room for Ethernet header - should not fail */
00842   if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) {
00843     /* bail out */
00844     LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
00845       ("etharp_output: could not allocate room for header.\n"));
00846     LINK_STATS_INC(link.lenerr);
00847     return ERR_BUF;
00848   }
00849 
00850   /* assume unresolved Ethernet address */
00851   dest = NULL;
00852   /* Determine on destination hardware address. Broadcasts and multicasts
00853    * are special, other IP addresses are looked up in the ARP table. */
00854 
00855   /* broadcast destination IP address? */
00856   if (ip_addr_isbroadcast(ipaddr, netif)) {
00857     /* broadcast on Ethernet also */
00858     dest = (struct eth_addr *)&ethbroadcast;
00859   /* multicast destination IP address? */
00860   } else if (ip_addr_ismulticast(ipaddr)) {
00861     /* Hash IP multicast address to MAC address.*/
00862     mcastaddr.addr[0] = 0x01;
00863     mcastaddr.addr[1] = 0x00;
00864     mcastaddr.addr[2] = 0x5e;
00865     mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;
00866     mcastaddr.addr[4] = ip4_addr3(ipaddr);
00867     mcastaddr.addr[5] = ip4_addr4(ipaddr);
00868     /* destination Ethernet address is multicast */
00869     dest = &mcastaddr;
00870   /* unicast destination IP address? */
00871   } else {
00872     /* outside local network? */
00873     if (!ip_addr_netcmp(ipaddr, &(netif->ip_addr), &(netif->netmask)) &&
00874         !ip_addr_islinklocal(ipaddr)) {
00875 #if LWIP_AUTOIP
00876       struct ip_hdr *iphdr = (struct ip_hdr*)((u8_t*)q->payload +
00877         sizeof(struct eth_hdr));
00878       /* According to RFC 3297, chapter 2.6.2 (Forwarding Rules), a packet with
00879          a link-local source address must always be "directly to its destination
00880          on the same physical link. The host MUST NOT send the packet to any
00881          router for forwarding". */
00882       if (!ip_addr_islinklocal(&iphdr->src))
00883 #endif /* LWIP_AUTOIP */
00884       {
00885         /* interface has default gateway? */
00886         if (!ip_addr_isany(&netif->gw)) {
00887           /* send to hardware address of default gateway IP address */
00888           ipaddr = &(netif->gw);
00889         /* no default gateway available */
00890         } else {
00891           /* no route to destination error (default gateway missing) */
00892           return ERR_RTE;
00893         }
00894       }
00895     }
00896 #if LWIP_NETIF_HWADDRHINT
00897     if (netif->addr_hint != NULL) {
00898       /* per-pcb cached entry was given */
00899       u8_t etharp_cached_entry = *(netif->addr_hint);
00900       if (etharp_cached_entry < ARP_TABLE_SIZE) {
00901 #endif /* LWIP_NETIF_HWADDRHINT */
00902         if ((arp_table[etharp_cached_entry].state == ETHARP_STATE_STABLE) &&
00903             (ip_addr_cmp(ipaddr, &arp_table[etharp_cached_entry].ipaddr))) {
00904           /* the per-pcb-cached entry is stable and the right one! */
00905           ETHARP_STATS_INC(etharp.cachehit);
00906           return etharp_send_ip(netif, q, (struct eth_addr*)(netif->hwaddr),
00907             &arp_table[etharp_cached_entry].ethaddr);
00908         }
00909 #if LWIP_NETIF_HWADDRHINT
00910       }
00911     }
00912 #endif /* LWIP_NETIF_HWADDRHINT */
00913     /* queue on destination Ethernet address belonging to ipaddr */
00914     return etharp_query(netif, ipaddr, q);
00915   }
00916 
00917   /* continuation for multicast/broadcast destinations */
00918   /* obtain source Ethernet address of the given interface */
00919   /* send packet directly on the link */
00920   return etharp_send_ip(netif, q, (struct eth_addr*)(netif->hwaddr), dest);
00921 }
00922 
00956 err_t
00957 etharp_query(struct netif *netif, ip_addr_t *ipaddr, struct pbuf *q)
00958 {
00959   struct eth_addr * srcaddr = (struct eth_addr *)netif->hwaddr;
00960   err_t result = ERR_MEM;
00961   s8_t i; /* ARP entry index */
00962 
00963   /* non-unicast address? */
00964   if (ip_addr_isbroadcast(ipaddr, netif) ||
00965       ip_addr_ismulticast(ipaddr) ||
00966       ip_addr_isany(ipaddr)) {
00967     LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: will not add non-unicast IP address to ARP cache\n"));
00968     return ERR_ARG;
00969   }
00970 
00971   /* find entry in ARP cache, ask to create entry if queueing packet */
00972   i = find_entry(ipaddr, ETHARP_FLAG_TRY_HARD);
00973 
00974   /* could not find or create entry? */
00975   if (i < 0) {
00976     LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not create ARP entry\n"));
00977     if (q) {
00978       LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: packet dropped\n"));
00979       ETHARP_STATS_INC(etharp.memerr);
00980     }
00981     return (err_t)i;
00982   }
00983 
00984   /* mark a fresh entry as pending (we just sent a request) */
00985   if (arp_table[i].state == ETHARP_STATE_EMPTY) {
00986     arp_table[i].state = ETHARP_STATE_PENDING;
00987   }
00988 
00989   /* { i is either a STABLE or (new or existing) PENDING entry } */
00990   LWIP_ASSERT("arp_table[i].state == PENDING or STABLE",
00991   ((arp_table[i].state == ETHARP_STATE_PENDING) ||
00992    (arp_table[i].state == ETHARP_STATE_STABLE)));
00993 
00994   /* do we have a pending entry? or an implicit query request? */
00995   if ((arp_table[i].state == ETHARP_STATE_PENDING) || (q == NULL)) {
00996     /* try to resolve it; send out ARP request */
00997     result = etharp_request(netif, ipaddr);
00998     if (result != ERR_OK) {
00999       /* ARP request couldn't be sent */
01000       /* We don't re-send arp request in etharp_tmr, but we still queue packets,
01001          since this failure could be temporary, and the next packet calling
01002          etharp_query again could lead to sending the queued packets. */
01003     }
01004     if (q == NULL) {
01005       return result;
01006     }
01007   }
01008 
01009   /* packet given? */
01010   LWIP_ASSERT("q != NULL", q != NULL);
01011   /* stable entry? */
01012   if (arp_table[i].state == ETHARP_STATE_STABLE) {
01013     /* we have a valid IP->Ethernet address mapping */
01014     ETHARP_SET_HINT(netif, i);
01015     /* send the packet */
01016     result = etharp_send_ip(netif, q, srcaddr, &(arp_table[i].ethaddr));
01017   /* pending entry? (either just created or already pending */
01018   } else if (arp_table[i].state == ETHARP_STATE_PENDING) {
01019     /* entry is still pending, queue the given packet 'q' */
01020     struct pbuf *p;
01021     int copy_needed = 0;
01022     /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but
01023      * to copy the whole queue into a new PBUF_RAM (see bug #11400) 
01024      * PBUF_ROMs can be left as they are, since ROM must not get changed. */
01025     p = q;
01026     while (p) {
01027       LWIP_ASSERT("no packet queues allowed!", (p->len != p->tot_len) || (p->next == 0));
01028       if(p->type != PBUF_ROM) {
01029         copy_needed = 1;
01030         break;
01031       }
01032       p = p->next;
01033     }
01034     if(copy_needed) {
01035       /* copy the whole packet into new pbufs */
01036       p = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
01037       if(p != NULL) {
01038         if (pbuf_copy(p, q) != ERR_OK) {
01039           pbuf_free(p);
01040           p = NULL;
01041         }
01042       }
01043     } else {
01044       /* referencing the old pbuf is enough */
01045       p = q;
01046       pbuf_ref(p);
01047     }
01048     /* packet could be taken over? */
01049     if (p != NULL) {
01050       /* queue packet ... */
01051 #if ARP_QUEUEING
01052       struct etharp_q_entry *new_entry;
01053       /* allocate a new arp queue entry */
01054       new_entry = (struct etharp_q_entry *)memp_malloc(MEMP_ARP_QUEUE);
01055       if (new_entry != NULL) {
01056         new_entry->next = 0;
01057         new_entry->p = p;
01058         if(arp_table[i].q != NULL) {
01059           /* queue was already existent, append the new entry to the end */
01060           struct etharp_q_entry *r;
01061           r = arp_table[i].q;
01062           while (r->next != NULL) {
01063             r = r->next;
01064           }
01065           r->next = new_entry;
01066         } else {
01067           /* queue did not exist, first item in queue */
01068           arp_table[i].q = new_entry;
01069         }
01070         LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i));
01071         result = ERR_OK;
01072       } else {
01073         /* the pool MEMP_ARP_QUEUE is empty */
01074         pbuf_free(p);
01075         LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q));
01076         result = ERR_MEM;
01077       }
01078 #else /* ARP_QUEUEING */
01079       /* always queue one packet per ARP request only, freeing a previously queued packet */
01080       if (arp_table[i].q != NULL) {
01081         LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: dropped previously queued packet %p for ARP entry %"S16_F"\n", (void *)q, (s16_t)i));
01082         pbuf_free(arp_table[i].q);
01083       }
01084       arp_table[i].q = p;
01085       result = ERR_OK;
01086       LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i));
01087 #endif /* ARP_QUEUEING */
01088     } else {
01089       ETHARP_STATS_INC(etharp.memerr);
01090       LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q));
01091       result = ERR_MEM;
01092     }
01093   }
01094   return result;
01095 }
01096 
01112 #if !LWIP_AUTOIP
01113 static
01114 #endif /* LWIP_AUTOIP */
01115 err_t
01116 etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
01117            const struct eth_addr *ethdst_addr,
01118            const struct eth_addr *hwsrc_addr, const ip_addr_t *ipsrc_addr,
01119            const struct eth_addr *hwdst_addr, const ip_addr_t *ipdst_addr,
01120            const u16_t opcode)
01121 {
01122   struct pbuf *p;
01123   err_t result = ERR_OK;
01124   struct eth_hdr *ethhdr;
01125   struct etharp_hdr *hdr;
01126 #if LWIP_AUTOIP
01127   const u8_t * ethdst_hwaddr;
01128 #endif /* LWIP_AUTOIP */
01129 
01130   /* allocate a pbuf for the outgoing ARP request packet */
01131   p = pbuf_alloc(PBUF_RAW, SIZEOF_ETHARP_PACKET, PBUF_RAM);
01132   /* could allocate a pbuf for an ARP request? */
01133   if (p == NULL) {
01134     LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
01135       ("etharp_raw: could not allocate pbuf for ARP request.\n"));
01136     ETHARP_STATS_INC(etharp.memerr);
01137     return ERR_MEM;
01138   }
01139   LWIP_ASSERT("check that first pbuf can hold struct etharp_hdr",
01140               (p->len >= SIZEOF_ETHARP_PACKET));
01141 
01142   ethhdr = (struct eth_hdr *)p->payload;
01143   hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);
01144   LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_raw: sending raw ARP packet.\n"));
01145   hdr->opcode = htons(opcode);
01146 
01147   LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!",
01148               (netif->hwaddr_len == ETHARP_HWADDR_LEN));
01149 #if LWIP_AUTOIP
01150   /* If we are using Link-Local, all ARP packets that contain a Link-Local
01151    * 'sender IP address' MUST be sent using link-layer broadcast instead of
01152    * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */
01153   ethdst_hwaddr = ip_addr_islinklocal(ipsrc_addr) ? (u8_t*)(ethbroadcast.addr) : ethdst_addr->addr;
01154 #endif /* LWIP_AUTOIP */
01155   /* Write the ARP MAC-Addresses */
01156   ETHADDR16_COPY(&hdr->shwaddr, hwsrc_addr);
01157   ETHADDR16_COPY(&hdr->dhwaddr, hwdst_addr);
01158   /* Write the Ethernet MAC-Addresses */
01159 #if LWIP_AUTOIP
01160   ETHADDR16_COPY(&ethhdr->dest, ethdst_hwaddr);
01161 #else  /* LWIP_AUTOIP */
01162   ETHADDR16_COPY(&ethhdr->dest, ethdst_addr);
01163 #endif /* LWIP_AUTOIP */
01164   ETHADDR16_COPY(&ethhdr->src, ethsrc_addr);
01165   /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without
01166    * structure packing. */ 
01167   IPADDR2_COPY(&hdr->sipaddr, ipsrc_addr);
01168   IPADDR2_COPY(&hdr->dipaddr, ipdst_addr);
01169 
01170   hdr->hwtype = PP_HTONS(HWTYPE_ETHERNET);
01171   hdr->proto = PP_HTONS(ETHTYPE_IP);
01172   /* set hwlen and protolen */
01173   hdr->hwlen = ETHARP_HWADDR_LEN;
01174   hdr->protolen = sizeof(ip_addr_t);
01175 
01176   ethhdr->type = PP_HTONS(ETHTYPE_ARP);
01177   /* send ARP query */
01178   result = netif->linkoutput(netif, p);
01179   ETHARP_STATS_INC(etharp.xmit);
01180   /* free ARP query packet */
01181   pbuf_free(p);
01182   p = NULL;
01183   /* could not allocate pbuf for ARP request */
01184 
01185   return result;
01186 }
01187 
01197 err_t
01198 etharp_request(struct netif *netif, ip_addr_t *ipaddr)
01199 {
01200   LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_request: sending ARP request.\n"));
01201   return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, &ethbroadcast,
01202                     (struct eth_addr *)netif->hwaddr, &netif->ip_addr, &ethzero,
01203                     ipaddr, ARP_REQUEST);
01204 }
01205 #endif /* LWIP_ARP */
01206 
01215 err_t
01216 ethernet_input(struct pbuf *p, struct netif *netif)
01217 {
01218   struct eth_hdr* ethhdr;
01219   u16_t type;
01220   s16_t ip_hdr_offset = SIZEOF_ETH_HDR;
01221 
01222   if (p->len <= SIZEOF_ETH_HDR) {
01223     /* a packet with only an ethernet header (or less) is not valid for us */
01224     ETHARP_STATS_INC(etharp.proterr);
01225     ETHARP_STATS_INC(etharp.drop);
01226     goto free_and_return;
01227   }
01228 
01229   /* points to packet payload, which starts with an Ethernet header */
01230   ethhdr = (struct eth_hdr *)p->payload;
01231   LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE,
01232     ("ethernet_input: dest:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", src:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", type:%"X16_F"\n",
01233      (unsigned)ethhdr->dest.addr[0], (unsigned)ethhdr->dest.addr[1], (unsigned)ethhdr->dest.addr[2],
01234      (unsigned)ethhdr->dest.addr[3], (unsigned)ethhdr->dest.addr[4], (unsigned)ethhdr->dest.addr[5],
01235      (unsigned)ethhdr->src.addr[0], (unsigned)ethhdr->src.addr[1], (unsigned)ethhdr->src.addr[2],
01236      (unsigned)ethhdr->src.addr[3], (unsigned)ethhdr->src.addr[4], (unsigned)ethhdr->src.addr[5],
01237      (unsigned)htons(ethhdr->type)));
01238 
01239   type = ethhdr->type;
01240 #if ETHARP_SUPPORT_VLAN
01241   if (type == PP_HTONS(ETHTYPE_VLAN)) {
01242     struct eth_vlan_hdr *vlan = (struct eth_vlan_hdr*)(((char*)ethhdr) + SIZEOF_ETH_HDR);
01243     if (p->len <= SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) {
01244       /* a packet with only an ethernet/vlan header (or less) is not valid for us */
01245       ETHARP_STATS_INC(etharp.proterr);
01246       ETHARP_STATS_INC(etharp.drop);
01247       goto free_and_return;
01248     }
01249 #ifdef ETHARP_VLAN_CHECK /* if not, allow all VLANs */
01250     if (VLAN_ID(vlan) != ETHARP_VLAN_CHECK) {
01251       /* silently ignore this packet: not for our VLAN */
01252       pbuf_free(p);
01253       return ERR_OK;
01254     }
01255 #endif /* ETHARP_VLAN_CHECK */
01256     type = vlan->tpid;
01257     ip_hdr_offset = SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR;
01258   }
01259 #endif /* ETHARP_SUPPORT_VLAN */
01260 
01261 #if LWIP_ARP_FILTER_NETIF
01262   netif = LWIP_ARP_FILTER_NETIF_FN(p, netif, htons(type));
01263 #endif /* LWIP_ARP_FILTER_NETIF*/
01264 
01265   switch (type) {
01266 #if LWIP_ARP
01267     /* IP packet? */
01268     case PP_HTONS(ETHTYPE_IP):
01269       if (!(netif->flags & NETIF_FLAG_ETHARP)) {
01270         goto free_and_return;
01271       }
01272 #if ETHARP_TRUST_IP_MAC
01273       /* update ARP table */
01274       etharp_ip_input(netif, p);
01275 #endif /* ETHARP_TRUST_IP_MAC */
01276       /* skip Ethernet header */
01277       if(pbuf_header(p, -ip_hdr_offset)) {
01278         LWIP_ASSERT("Can't move over header in packet", 0);
01279         goto free_and_return;
01280       } else {
01281         /* pass to IP layer */
01282         ip_input(p, netif);
01283       }
01284       break;
01285       
01286     case PP_HTONS(ETHTYPE_ARP):
01287       if (!(netif->flags & NETIF_FLAG_ETHARP)) {
01288         goto free_and_return;
01289       }
01290       /* pass p to ARP module */
01291       etharp_arp_input(netif, (struct eth_addr*)(netif->hwaddr), p);
01292       break;
01293 #endif /* LWIP_ARP */
01294 #if PPPOE_SUPPORT
01295     case PP_HTONS(ETHTYPE_PPPOEDISC): /* PPP Over Ethernet Discovery Stage */
01296       pppoe_disc_input(netif, p);
01297       break;
01298 
01299     case PP_HTONS(ETHTYPE_PPPOE): /* PPP Over Ethernet Session Stage */
01300       pppoe_data_input(netif, p);
01301       break;
01302 #endif /* PPPOE_SUPPORT */
01303 
01304     default:
01305       ETHARP_STATS_INC(etharp.proterr);
01306       ETHARP_STATS_INC(etharp.drop);
01307       goto free_and_return;
01308   }
01309 
01310   /* This means the pbuf is freed or consumed,
01311      so the caller doesn't have to free it again */
01312   return ERR_OK;
01313 
01314 free_and_return:
01315   pbuf_free(p);
01316   return ERR_OK;
01317 }
01318 #endif /* LWIP_ARP || LWIP_ETHERNET */

Generated on Sun May 27 2012 04:36:05 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.