/[lwip]/lwip/src/netif/etharp.c
ViewVC logotype

Diff of /lwip/src/netif/etharp.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.5 by likewise, Fri Nov 8 22:14:24 2002 UTC revision 1.6 by likewise, Mon Nov 11 14:34:29 2002 UTC
# Line 3  Line 3 
3   * Address Resolution Protocol module for IP over Ethernet   * Address Resolution Protocol module for IP over Ethernet
4   *   *
5   * $Log$   * $Log$
6     * Revision 1.6  2002/11/11 14:34:29  likewise
7     * Changed static etharp_query() to support queueing packets. This fix  missed in last commit.
8     *
9   * Revision 1.5  2002/11/08 22:14:24  likewise   * Revision 1.5  2002/11/08 22:14:24  likewise
10   * Fixed numerous bugs. Re-used etharp_query()  in etharp_output(). Added comments and JavaDoc documentation.   * Fixed numerous bugs. Re-used etharp_query()  in etharp_output(). Added comments and JavaDoc documentation.
11   *   *
# Line 57  Line 60 
60  #include "netif/etharp.h"  #include "netif/etharp.h"
61  #include "lwip/ip.h"  #include "lwip/ip.h"
62  #include "lwip/stats.h"  #include "lwip/stats.h"
63    #include "lwipopts.h"
64    
65  /* ARP needs to inform DHCP of any ARP replies? */  /* ARP needs to inform DHCP of any ARP replies? */
66  #if (LWIP_DHCP && DHPC_DOES_ARP_CHECK)  #if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
67  #  include "lwip/dhcp.h"  #  include "lwip/dhcp.h"
68  #endif  #endif
69    
# Line 134  static const struct eth_addr ethbroadcas Line 138  static const struct eth_addr ethbroadcas
138  static struct etharp_entry arp_table[ARP_TABLE_SIZE];  static struct etharp_entry arp_table[ARP_TABLE_SIZE];
139  static u8_t ctime;  static u8_t ctime;
140    
141    static struct pbuf *insert_arp_entry(struct ip_addr *ipaddr, struct eth_addr *ethaddr);
142    
143  /**  /**
144   * Initializes ARP module.   * Initializes ARP module.
145   */   */
# Line 145  etharp_init(void) Line 151  etharp_init(void)
151    for(i = 0; i < ARP_TABLE_SIZE; ++i) {    for(i = 0; i < ARP_TABLE_SIZE; ++i) {
152      arp_table[i].state = ETHARP_STATE_EMPTY;      arp_table[i].state = ETHARP_STATE_EMPTY;
153    }    }
154      ctime = 0;
155  }  }
156    
157  /**  /**
# Line 161  etharp_tmr(void) Line 168  etharp_tmr(void)
168    ++ctime;    ++ctime;
169    /* remove expired entries from the ARP table */    /* remove expired entries from the ARP table */
170    for(i = 0; i < ARP_TABLE_SIZE; ++i) {    for(i = 0; i < ARP_TABLE_SIZE; ++i) {
171      if(arp_table[i].state == ETHARP_STATE_STABLE &&            if((arp_table[i].state == ETHARP_STATE_STABLE) &&      
172         ctime - arp_table[i].ctime >= ARP_MAXAGE) {         (ctime - arp_table[i].ctime >= ARP_MAXAGE)) {
173        DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired stable entry %d.\n", i));        DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired stable entry %u.\n", i));
174        arp_table[i].state = ETHARP_STATE_EMPTY;        arp_table[i].state = ETHARP_STATE_EMPTY;
175      } else if(arp_table[i].state == ETHARP_STATE_PENDING &&      } else if((arp_table[i].state == ETHARP_STATE_PENDING) &&
176                ctime - arp_table[i].ctime >= ARP_MAXPENDING) {                (ctime - arp_table[i].ctime >= ARP_MAXPENDING)) {
177        DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired pending entry %d - dequeueing %p.\n", i, arp_table[i].p));        DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired pending entry %u - dequeueing %p.\n", i, arp_table[i].p));
178        arp_table[i].state = ETHARP_STATE_EMPTY;        arp_table[i].state = ETHARP_STATE_EMPTY;
179          /* remove any queued packet */
180        pbuf_free(arp_table[i].p);              pbuf_free(arp_table[i].p);      
181        arp_table[i].p = NULL;        arp_table[i].p = NULL;
182      }      }
# Line 190  find_arp_entry(void) Line 198  find_arp_entry(void)
198    /* Try to find an unused entry in the ARP table. */    /* Try to find an unused entry in the ARP table. */
199    for(i = 0; i < ARP_TABLE_SIZE; ++i) {    for(i = 0; i < ARP_TABLE_SIZE; ++i) {
200      if(arp_table[i].state == ETHARP_STATE_EMPTY) {      if(arp_table[i].state == ETHARP_STATE_EMPTY) {
201          DEBUGF(ETHARP_DEBUG, ("find_arp_entry: found empty entry %u\n", i));
202        break;        break;
203      }      }
204    }    }
# Line 200  find_arp_entry(void) Line 209  find_arp_entry(void)
209      maxtime = 0;      maxtime = 0;
210      j = ARP_TABLE_SIZE;      j = ARP_TABLE_SIZE;
211      for(i = 0; i < ARP_TABLE_SIZE; ++i) {      for(i = 0; i < ARP_TABLE_SIZE; ++i) {
212        if(arp_table[i].state == ETHARP_STATE_STABLE &&        /* remember entry with oldest stable entry in j*/
213           ctime - arp_table[i].ctime > maxtime) {        if((arp_table[i].state == ETHARP_STATE_STABLE) &&
214          maxtime = ctime - arp_table[i].ctime;        (ctime - arp_table[i].ctime > maxtime)) {
215          j = i;          maxtime = ctime - arp_table[i].ctime;
216                  j = i;
217        }        }
218      }      }
219        DEBUGF(ETHARP_DEBUG, ("find_arp_entry: found oldest stable entry %u\n", j));
220      i = j;      i = j;
221    }    }
222    return i;    return i;
223  }  }
224    
225    /**
226     * Insert an entry into the ARP cache, or update an existing one.
227     *
228     * @param ipaddr IP address of the inserted ARP entry.
229     * @param ethaddr Ethernet address of the inserted ARP entry.
230     *
231     * @return pbuf If non-NULL, a packet that was queued on a pending entry.
232     * You should sent it and must call pbuf_free().
233     *
234     * @see pbuf_free()
235     */
236  static struct pbuf *  static struct pbuf *
237  update_arp_entry(struct ip_addr *ipaddr, struct eth_addr *ethaddr)  insert_arp_entry(struct ip_addr *ipaddr, struct eth_addr *ethaddr)
238  {  {
239    u8_t i, k;    u8_t i, k;
240    struct pbuf *p;    struct pbuf *p;
241    struct eth_hdr *ethhdr;    struct eth_hdr *ethhdr;
242      
243    /* Walk through the ARP mapping table and try to find an entry to    /* Walk through the ARP mapping table and try to find an entry to
244       update. If none is found, the IP -> MAC address mapping is    update. If none is found, the IP -> MAC address mapping is
245       inserted in the ARP table. */    inserted in the ARP table. */
246    for(i = 0; i < ARP_TABLE_SIZE; ++i) {    for(i = 0; i < ARP_TABLE_SIZE; ++i) {
247      /* Check if the source IP address of the incoming packet matches      /* Check if the source IP address of the incoming packet matches
248         the IP address in this ARP table entry. */      the IP address in this ARP table entry. */
249      if(ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {      if(ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
250          
251        /* First, check those entries that are already in use. */        /* check those entries that are already in use. */
252        if(arp_table[i].state == ETHARP_STATE_STABLE) {        if(arp_table[i].state == ETHARP_STATE_STABLE) {
253          /* An old entry found, update this and return. */          DEBUGF(ETHARP_DEBUG, ("insert_arp_entry: updating stable entry %u\n", i));
254          for(k = 0; k < 6; ++k) {          /* An old entry found, update this and return. */
255            arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];          for(k = 0; k < 6; ++k) {
256          }            arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
257          arp_table[i].ctime = ctime;          }
258          return NULL;          arp_table[i].ctime = ctime;
259            return NULL;
260        }        }
261        if(arp_table[i].state == ETHARP_STATE_PENDING) {        else if(arp_table[i].state == ETHARP_STATE_PENDING) {
262          /* A pending entry was found, so we fill this in and return          /* A pending entry was found, so we fill this in and return
263             the queued packet (if any). */             the queued packet (if any). */
264          for(k = 0; k < 6; ++k) {          DEBUGF(ETHARP_DEBUG, ("insert_arp_entry: pending entry %u made stable\n", i));
265            arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];          for(k = 0; k < 6; ++k) {
266          }            arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
267          arp_table[i].ctime = ctime;          }
268          arp_table[i].state = ETHARP_STATE_STABLE;          arp_table[i].ctime = ctime;
269          p = arp_table[i].p;          arp_table[i].state = ETHARP_STATE_STABLE;
270          if(p != NULL) {          p = arp_table[i].p;
271            p->payload = arp_table[i].payload;              // queued packet present? */
272            p->len = arp_table[i].len;          if(p != NULL) {
273            p->tot_len = arp_table[i].tot_len;                  /* remove queued packet from ARP entry (must be freed by the caller) */
274            arp_table[i].p = NULL;                    arp_table[i].p = NULL;        
275              
276            ethhdr = p->payload;            /* fill-in Ethernet header */
277                        ethhdr = p->payload;
278            for(k = 0; k < 6; ++k) {  
279              ethhdr->dest.addr[k] = ethaddr->addr[k];            for(k = 0; k < 6; ++k) {
280            }              ethhdr->dest.addr[k] = ethaddr->addr[k];
281                        }
282            ethhdr->type = htons(ETHTYPE_IP);                        
283          }            ethhdr->type = htons(ETHTYPE_IP);                      
284          return p;            DEBUGF(ETHARP_DEBUG, ("insert_arp_entry: returning queued packet %p\n", p));
285            }
286            /* return queued packet, if any */
287            return p;
288        }        }
289      }      }
290    }    }
291    /* We get here if no ARP entry was found. If so, we create one. */    /* no matching ARP entry was found. find an empty or old entry. */
292    i = find_arp_entry();    i = find_arp_entry();
293    if(i == ARP_TABLE_SIZE) {    if(i == ARP_TABLE_SIZE) {
294        DEBUGF(ETHARP_DEBUG, ("insert_arp_entry: no available entry found\n"));
295      return NULL;      return NULL;
296    }    }
297    
298      if (arp_table[i].state == ETHARP_STATE_STABLE) {
299        DEBUGF(ETHARP_DEBUG, ("insert_arp_entry: overwriting old stable entry %u\n", i));
300      }
301      else {
302        DEBUGF(ETHARP_DEBUG, ("insert_arp_entry: using empty entry %u\n", i));
303      }  
304    ip_addr_set(&arp_table[i].ipaddr, ipaddr);    ip_addr_set(&arp_table[i].ipaddr, ipaddr);
305    for(k = 0; k < 6; ++k) {    for(k = 0; k < 6; ++k) {
306      arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];      arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
# Line 275  update_arp_entry(struct ip_addr *ipaddr, Line 308  update_arp_entry(struct ip_addr *ipaddr,
308    arp_table[i].ctime = ctime;    arp_table[i].ctime = ctime;
309    arp_table[i].state = ETHARP_STATE_STABLE;    arp_table[i].state = ETHARP_STATE_STABLE;
310    arp_table[i].p = NULL;    arp_table[i].p = NULL;
311      
312    return NULL;    return NULL;
313  }  }
314    
315  /**  /**
316   * Updates the ARP table and may return any queued packet to be sent   * Updates the ARP table and may return any queued packet to be sent.
317     *
318     * Should be called for all incoming packets of IP kind. It updates
319     * the ARP table for the local network. The function does not alter
320     * the packet in any way and does not free it. After this function has
321     * been called, the packet p must be given to the IP layer.
322     *
323     * @param netif The lwIP network interface on which the IP packet pbuf arrived.
324     *
325     * @param pbuf The IP packet that arrived on netif.
326     *
327     * @return If non-NULL, a pbuf that was queued on an ARP entry. The device
328     * driver must transmit this packet onto the network, and call pbuf_free()
329     * for the pbuf.
330   *   *
331   * Should be called for all incoming packets of IP kind. The function   * @see pbuf_free()
  * does not alter the packet in any way, it just updates the ARP  
  * table. After this function has been called, the normal TCP/IP stack  
  * input function should be called.  
  *  
  * The function may return a pbuf containing a packet that had  
  * previously been queued for transmission. The device driver must  
  * transmit this packet onto the network, and call pbuf_free() for the  
  * pbuf.  
332   */   */
333  struct pbuf *  struct pbuf *
334  etharp_ip_input(struct netif *netif, struct pbuf *p)  etharp_ip_input(struct netif *netif, struct pbuf *p)
# Line 301  etharp_ip_input(struct netif *netif, str Line 339  etharp_ip_input(struct netif *netif, str
339        
340    /* Only insert/update an entry if the source IP address of the    /* Only insert/update an entry if the source IP address of the
341       incoming IP packet comes from a host on the local network. */       incoming IP packet comes from a host on the local network. */
342        
343      /* source is on local network? */
344    if(!ip_addr_maskcmp(&(hdr->ip.src), &(netif->ip_addr), &(netif->netmask))) {    if(!ip_addr_maskcmp(&(hdr->ip.src), &(netif->ip_addr), &(netif->netmask))) {
345        /* do nothing */
346      return NULL;      return NULL;
347    }    }
348    DEBUGF(ETHARP_DEBUG, ("etharp_ip_input: updating ETHARP table.\n"));    DEBUGF(ETHARP_DEBUG, ("etharp_ip_input: updating ETHARP table.\n"));
349    return update_arp_entry(&(hdr->ip.src), &(hdr->eth.src));    /* update ARP table */
350      return insert_arp_entry(&(hdr->ip.src), &(hdr->eth.src));
351  }  }
352    
353    
354  /**  /**
355   * Updates the ARP table and may return any queued packet to be sent   * Updates the ARP table and returns an ARP reply or a queued IP packet.
356   *   *
357   * Should be called for incoming ARP packets. The pbuf in the argument   * Should be called for incoming ARP packets. The pbuf in the argument
358   * is freed by this function. If the function returns a pbuf (i.e.,   * is freed by this function. The returned pbuf is to be sent and then
359   * returns non-NULL), that pbuf constitutes an ARP reply and should be   * freed by the caller.
360   * sent out on the Ethernet.   *
361     * @param netif The lwIP network interface on which the ARP packet pbuf arrived.
362     * @param pbuf The ARP packet that arrived on netif. Is freed by this function.
363     * @param ethaddr Ethernet address of netif.
364   *   *
365   * @note The driver must call pbuf_free() for the returned pbuf when the   * @return pbuf to be sent and freed by the caller.
366   * packet has been sent.   *
367     * @see pbuf_free()
368   */   */
369  struct pbuf *  struct pbuf *
370  etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)  etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
371  {  {
372    struct etharp_hdr *hdr;    struct etharp_hdr *hdr;
373    u8_t i;    u8_t i;
374      
375      /* drop short ARP packets */
376    if(p->tot_len < sizeof(struct etharp_hdr)) {    if(p->tot_len < sizeof(struct etharp_hdr)) {
377      DEBUGF(ETHARP_DEBUG, ("etharp_etharp_input: packet too short (%d/%d)\n", p->tot_len, sizeof(struct etharp_hdr)));      DEBUGF(ETHARP_DEBUG, ("etharp_etharp_input: packet too short (%d/%d)\n", p->tot_len, sizeof(struct etharp_hdr)));
378      pbuf_free(p);      pbuf_free(p);
# Line 333  etharp_arp_input(struct netif *netif, st Line 380  etharp_arp_input(struct netif *netif, st
380    }    }
381    
382    hdr = p->payload;    hdr = p->payload;
383      
384    switch(htons(hdr->opcode)) {    switch(htons(hdr->opcode)) {
385      /* ARP request? */
386    case ARP_REQUEST:    case ARP_REQUEST:
387      /* ARP request. If it asked for our address, we send out a      /* ARP request. If it asked for our address, we send out a
388         reply. */      reply. */
389      DEBUGF(ETHARP_DEBUG, ("etharp_arp_input: ARP request\n"));      DEBUGF(ETHARP_DEBUG, ("etharp_arp_input: ARP request\n"));
390        /* ARP request for our address? */
391      if(ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr))) {      if(ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr))) {
392    
393          DEBUGF(ETHARP_DEBUG, ("etharp_arp_input: ARP request for our address\n"));
394          /* re-use pbuf to send ARP reply */
395        hdr->opcode = htons(ARP_REPLY);        hdr->opcode = htons(ARP_REPLY);
396    
397        ip_addr_set(&(hdr->dipaddr), &(hdr->sipaddr));        ip_addr_set(&(hdr->dipaddr), &(hdr->sipaddr));
398        ip_addr_set(&(hdr->sipaddr), &(netif->ip_addr));        ip_addr_set(&(hdr->sipaddr), &(netif->ip_addr));
399    
400        for(i = 0; i < 6; ++i) {        for(i = 0; i < 6; ++i) {
401          hdr->dhwaddr.addr[i] = hdr->shwaddr.addr[i];          hdr->dhwaddr.addr[i] = hdr->shwaddr.addr[i];
402          hdr->shwaddr.addr[i] = ethaddr->addr[i];          hdr->shwaddr.addr[i] = ethaddr->addr[i];
403          hdr->ethhdr.dest.addr[i] = hdr->dhwaddr.addr[i];          hdr->ethhdr.dest.addr[i] = hdr->dhwaddr.addr[i];
404          hdr->ethhdr.src.addr[i] = ethaddr->addr[i];          hdr->ethhdr.src.addr[i] = ethaddr->addr[i];
405        }        }
406    
407        hdr->hwtype = htons(HWTYPE_ETHERNET);        hdr->hwtype = htons(HWTYPE_ETHERNET);
408        ARPH_HWLEN_SET(hdr, 6);        ARPH_HWLEN_SET(hdr, 6);
409          
410        hdr->proto = htons(ETHTYPE_IP);          hdr->proto = htons(ETHTYPE_IP);
411        ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));              ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));      
412          
413        hdr->ethhdr.type = htons(ETHTYPE_ARP);                hdr->ethhdr.type = htons(ETHTYPE_ARP);      
414          /* return ARP reply */
415        return p;        return p;
416      }      }
417    #if 0
418          /* ARP request, NOT for our address */
419          else
420        {
421        }
422    #endif
423      break;      break;
424    case ARP_REPLY:        case ARP_REPLY:    
425      /* ARP reply. We insert or update the ARP table. */      /* ARP reply. We insert or update the ARP table. */
426      DEBUGF(ETHARP_DEBUG, ("etharp_arp_input: ARP reply\n"));      DEBUGF(ETHARP_DEBUG, ("etharp_arp_input: ARP reply\n"));
     if(ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr))) {      
       struct pbuf *q;  
427  #if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)  #if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
428          /* DHCP needs to know about ARP replies */
429        dhcp_arp_reply(&hdr->sipaddr);        dhcp_arp_reply(&hdr->sipaddr);
430  #endif  #endif
431        /* update_arp_entry() will return a pbuf that has previously been      /* for our address? */
432           queued waiting for an ARP reply. */      if(ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr))) {    
433        q = update_arp_entry(&(hdr->sipaddr), &(hdr->shwaddr));        struct pbuf *q;
434          DEBUGF(ETHARP_DEBUG, ("etharp_arp_input: ARP reply for us\n"));
435          /* insert_arp_entry() can return a pbuf that has previously been
436          queued waiting for this IP address to become ARP stable. */
437          q = insert_arp_entry(&(hdr->sipaddr), &(hdr->shwaddr));
438          /* free incoming ARP reply pbuf */
439        pbuf_free(p);        pbuf_free(p);
440        p = NULL;        p = NULL;
441        return q;        return q;
442      }      }
443    #if 0
444          /* ARP reply, NOT for our address */
445          else
446        {
447        }
448    #endif
449      break;      break;
450    default:    default:
451      DEBUGF(ETHARP_DEBUG, ("etharp_arp_input: unknown type %d\n", htons(hdr->opcode)));      DEBUGF(ETHARP_DEBUG, ("etharp_arp_input: unknown type %d\n", htons(hdr->opcode)));
# Line 388  etharp_arp_input(struct netif *netif, st Line 457  etharp_arp_input(struct netif *netif, st
457  }  }
458    
459  /**  /**
460   * Resolve Ethernet address and append header to the outgoing packet.   * Resolve and fill-in Ethernet address header for outgoing packet.
461   *   *
462   * The etharp_output() function should be called for all outgoing   * If ARP has the Ethernet address in cache, the given packet is
463   * packets. The pbuf returned by the function should be sent out on   * returned, ready to be sent.
464   * the Ethernet. This pbuf must then be passed to etharp_output_sent().   *
465   *   * If ARP does not have the Ethernet address in cache the packet is
466   * The function prepares the packet for transmission over the Ethernet   * queued and a ARP request is sent (on a best-effort basis). This
467   * by adding an Ethernet header. If there is no IP -> MAC address   * ARP request is returned as a pbuf, which should be sent by the
468   * mapping, the function will queue the outgoing packet and return an   * caller.
469   * ARP request packet instead.   *
470     * If ARP failed to allocate resources, NULL is returned.
471     *
472     * A returned non-NULL packet should be sent by the caller and
473     * etharp_output_sent() must be called afterwards to free any ARP
474     * request.
475   *   *
476   * @param netif The lwIP network interface which the IP packet will be sent on.   * @param netif The lwIP network interface which the IP packet will be sent on.
477   * @param ipaddr The IP address of the packet destination.   * @param ipaddr The IP address of the packet destination.
478   * @param pbuf The pbuf(s) containing the IP packet.   * @param pbuf The pbuf(s) containing the IP packet to be sent.
479   *   *
480   * @return The packet which should be sent on the network and must be freed by   * @return If non-NULL, a packet ready to be sent.
  * the caller.  
  *  
481   * @see etharp_output_sent()   * @see etharp_output_sent()
482   */   */
483  struct pbuf *  struct pbuf *
# Line 413  etharp_output(struct netif *netif, struc Line 485  etharp_output(struct netif *netif, struc
485  {  {
486    struct eth_addr *dest, *srcaddr, mcastaddr;    struct eth_addr *dest, *srcaddr, mcastaddr;
487    struct eth_hdr *ethhdr;    struct eth_hdr *ethhdr;
   struct etharp_hdr *hdr;  
488    struct pbuf *p;    struct pbuf *p;
489    u8_t i;    u8_t i;
490    
   /* obtain source Ethernet address of the given interface */  
   srcaddr = (struct eth_addr *)netif->hwaddr;  
   
491    /* Make room for Ethernet header. */    /* Make room for Ethernet header. */
492    if(pbuf_header(q, sizeof(struct eth_hdr)) != 0) {        if(pbuf_header(q, sizeof(struct eth_hdr)) != 0) {    
493      /* The pbuf_header() call shouldn't fail, and we'll just bail      /* The pbuf_header() call shouldn't fail, and we'll just bail
494         out if it does.. */      out if it does.. */
495      DEBUGF(ETHARP_DEBUG, ("etharp_output: could not allocate room for header.\n"));      DEBUGF(ETHARP_DEBUG, ("etharp_output: could not allocate room for header.\n"));
496  #ifdef LINK_STATS  #ifdef LINK_STATS
497      ++stats.link.lenerr;      ++stats.link.lenerr;
# Line 431  etharp_output(struct netif *netif, struc Line 499  etharp_output(struct netif *netif, struc
499      return NULL;      return NULL;
500    }    }
501    
502      /* obtain source Ethernet address of the given interface */
503      srcaddr = (struct eth_addr *)netif->hwaddr;
504    
505    /* assume unresolved Ethernet address */    /* assume unresolved Ethernet address */
506    dest = NULL;    dest = NULL;
507    /* Construct Ethernet header. Start with looking up deciding which    /* Construct Ethernet header. Start with looking up deciding which
508       MAC address to use as a destination address. Broadcasts and    MAC address to use as a destination address. Broadcasts and
509       multicasts are special, all other addresses are looked up in the    multicasts are special, all other addresses are looked up in the
510       ARP table. */    ARP table. */
511    
512    /* destination IP address is an IP broadcast address? */    /* destination IP address is an IP broadcast address? */
513    if(ip_addr_isany(ipaddr) ||    if(ip_addr_isany(ipaddr) ||
514       ip_addr_isbroadcast(ipaddr, &(netif->netmask))) {      ip_addr_isbroadcast(ipaddr, &(netif->netmask))) {
515      /* broadcast on Ethernet also */      /* broadcast on Ethernet also */
516      dest = (struct eth_addr *)&ethbroadcast;      dest = (struct eth_addr *)&ethbroadcast;
517    } else if(ip_addr_ismulticast(ipaddr)) {    }
518      /* destination IP address is an IP multicast address? */
519      else if(ip_addr_ismulticast(ipaddr)) {
520      /* Hash IP multicast address to MAC address. */      /* Hash IP multicast address to MAC address. */
521      mcastaddr.addr[0] = 0x01;      mcastaddr.addr[0] = 0x01;
522      mcastaddr.addr[1] = 0x0;      mcastaddr.addr[1] = 0x0;
# Line 452  etharp_output(struct netif *netif, struc Line 526  etharp_output(struct netif *netif, struc
526      mcastaddr.addr[5] = ip4_addr4(ipaddr);      mcastaddr.addr[5] = ip4_addr4(ipaddr);
527      /* destination Ethernet address is multicast */      /* destination Ethernet address is multicast */
528      dest = &mcastaddr;      dest = &mcastaddr;
529    /* destination IP unicast address */    }
530    } else {    /* destination IP address is an IP unicast address */
531      /* the destination IP network address does not match the interface's    else {
532         network address */      /* destination IP network address not on local network? */
533      if(!ip_addr_maskcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) {      if(!ip_addr_maskcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) {
534        /* Use the IP address of the default gateway if the destination        /* gateway available? */
535           is not on the same subnet as we are. */              if (netif->gw.addr != 0)
536        ipaddr = &(netif->gw);        {
537      }          /* use the default gateway IP address */
538            ipaddr = &(netif->gw);
539      /* Try to find a stable IP-to-Ethernet address mapping for this IP        }
540         destination address */        else
541      for(i = 0; i < ARP_TABLE_SIZE; ++i) {            {
542        if(arp_table[i].state == ETHARP_STATE_STABLE &&          /* IP destination address outside local network, but no gateway available */
543           ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {          return NULL;
         dest = &arp_table[i].ethaddr;  
         break;  
544        }        }
545      }      }
546    }  
547          /* Ethernet address for IP destination address is in ARP cache? */
   /* could not find a destination Ethernet address? */  
   if(dest == NULL) {  
     /* No destination address has been found, so we'll have to send  
        out an ARP request for the IP address. The outgoing packet is  
        queued unless the queue is full. */  
         
     /* TODO: The host requirements RFC states that ARP should save at least one  
        packet, and this should be the _latest_ packet. */  
       
     /* We check if we are already querying for this address. If so,  
        we'll bail out. */  
548      for(i = 0; i < ARP_TABLE_SIZE; ++i) {      for(i = 0; i < ARP_TABLE_SIZE; ++i) {
549        if(arp_table[i].state == ETHARP_STATE_PENDING &&        /* match found? */    
550           ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {        if(arp_table[i].state == ETHARP_STATE_STABLE &&
551          DEBUGF(ETHARP_DEBUG, ("etharp_output: already queued\n"));          ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
552          return NULL;          dest = &arp_table[i].ethaddr;
553            break;
554        }        }
555      }      }
556        /* could not find the destination Ethernet address in ARP cache? */
557      /* find a usable ARP entry */      if (dest == NULL) {
558      i = find_arp_entry();        /* query for the IP address using ARP request */
559              p = etharp_query(netif, ipaddr, q);
560      /* If all table entries were in pending state, we won't send out any        /* return the ARP request */
561         more ARP requests. We'll just give up. */        return p;
     if(i == ARP_TABLE_SIZE) {  
       return NULL;  
562      }      }
563            /* destination Ethernet address resolved from ARP cache*/
564      /* Now, i is the ARP table entry which we will fill with the new      else
565         information. */      {
566      ip_addr_set(&arp_table[i].ipaddr, ipaddr);        /* fallthrough */
     arp_table[i].ctime = ctime;  
     arp_table[i].state = ETHARP_STATE_PENDING;  
 #if 1  
     arp_table[i].p = q;  
     arp_table[i].payload = q->payload;  
     arp_table[i].len = q->len;  
     arp_table[i].tot_len = q->tot_len;  
       
     /* Because the pbuf will be queued, we'll increase the reference  
        count. */  
     DEBUGF(ETHARP_DEBUG, ("etharp_output: queueing %p\n", q));  
     pbuf_ref(q);  
 #else  
     arp_table[i].p = NULL;  
 #endif /* 0 */  
   
       
     /* We allocate a pbuf for the outgoing ARP request packet. */  
     p = pbuf_alloc(PBUF_LINK, sizeof(struct etharp_hdr), PBUF_RAM);  
     if(p == NULL) {  
       /* No ARP request packet could be allocated, so we forget about  
          the ARP table entry. */  
       if(i != ARP_TABLE_SIZE) {  
         arp_table[i].state = ETHARP_STATE_EMPTY;  
         /* We decrease the reference count of the queued pbuf (which now  
            is dequeued). */  
         DEBUGF(ETHARP_DEBUG, ("etharp_output: couldn't alloc pbuf for query, dequeueing %p\n", q));  
         pbuf_free(q);  
       }        
       return NULL;  
567      }      }
568          }
569      hdr = p->payload;  
570          /* destination Ethernet address known */
571      hdr->opcode = htons(ARP_REQUEST);    if (dest != NULL) {
       
     for(i = 0; i < 6; ++i) {  
       hdr->dhwaddr.addr[i] = 0x00;  
       hdr->shwaddr.addr[i] = srcaddr->addr[i];  
     }  
       
     ip_addr_set(&(hdr->dipaddr), ipaddr);  
     ip_addr_set(&(hdr->sipaddr), &(netif->ip_addr));  
       
     hdr->hwtype = htons(HWTYPE_ETHERNET);  
     ARPH_HWLEN_SET(hdr, 6);  
       
     hdr->proto = htons(ETHTYPE_IP);  
     ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));  
       
     for(i = 0; i < 6; ++i) {  
       hdr->ethhdr.dest.addr[i] = 0xff;  
       hdr->ethhdr.src.addr[i] = srcaddr->addr[i];  
     }  
       
     hdr->ethhdr.type = htons(ETHTYPE_ARP);        
     return p;  
   } else {  
572      /* A valid IP->MAC address mapping was found, so we construct the      /* A valid IP->MAC address mapping was found, so we construct the
573         Ethernet header for the outgoing packet. */      Ethernet header for the outgoing packet. */
574    
575      ethhdr = q->payload;      ethhdr = q->payload;
576        
577      for(i = 0; i < 6; i++) {      for(i = 0; i < 6; i++) {
578        ethhdr->dest.addr[i] = dest->addr[i];        ethhdr->dest.addr[i] = dest->addr[i];
579        ethhdr->src.addr[i] = srcaddr->addr[i];        ethhdr->src.addr[i] = srcaddr->addr[i];
580      }      }
581        
582      ethhdr->type = htons(ETHTYPE_IP);      ethhdr->type = htons(ETHTYPE_IP);
583          /* return the outgoing packet */
584      return q;      return q;
585    }    }
586      // never reached; here for safety
587      return NULL;
588  }  }
589    
590  /**  /**
591   * Clean up the ARP request that was allocated by ARP.   * Free the ARP request pbuf.
592   *   *
593   * This must be called after you have sent the packet   * Free the ARP request pbuf that was allocated by ARP
594   * returned by etharp_output(). It frees any pbuf   *
595   * allocated for an ARP request.   * as a result of calling etharp_output(). Must be called
596     * with the pbuf returned by etharp_output(), after you
597     * have sent that packet.
598     *
599     * @param p pbuf returned earlier by etharp_output().
600     *
601     * @see etharp_output().
602   */   */
603  struct pbuf *  struct pbuf *
604  etharp_output_sent(struct pbuf *p)  etharp_output_sent(struct pbuf *p)
# Line 591  etharp_output_sent(struct pbuf *p) Line 606  etharp_output_sent(struct pbuf *p)
606    struct etharp_hdr *hdr;    struct etharp_hdr *hdr;
607    hdr=p->payload;    hdr=p->payload;
608    if (hdr->opcode == htons(ARP_REQUEST)) {    if (hdr->opcode == htons(ARP_REQUEST)) {
609      pbuf_free(p); p=NULL;      pbuf_free(p);
610    };      p = NULL;
611      }
612    return p;    return p;
613  }  }
614    
615  /**  /**
616   * Initiate an ARP query for the given IP address.   * Send an ARP request for the given IP address.
617     *
618     * Sends an ARP request for the given IP address, unless
619     * a request for this address is already pending. Optionally
620     * queues an outgoing packet on the resulting ARP entry.
621   *   *
622   * Used by the DHCP module to support "gratuitous" ARP,   * @param netif The lwIP network interface where ipaddr
623   * i.e. send ARP requests for one's own IP address, to   * must be queried for.
624   * see if others have the IP address in use.   * @param ipaddr The IP address to be resolved.
625     * @param q If non-NULL, a pbuf that must be queued on the
626     * ARP entry for the ipaddr IP address.
627   *   *
628   * Might be used in the future by manual IP configuration   * @return pbuf containing the ARP request, NULL on failure.
629     *
630     * @note Might be used in the future by manual IP configuration
631   * as well.   * as well.
632   *   *
633   */   */
634    struct pbuf *etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
 struct pbuf *etharp_query(struct netif *netif, struct ip_addr *ipaddr)  
635  {  {
636    struct eth_addr *srcaddr;    struct eth_addr *srcaddr;
637    struct etharp_hdr *hdr;    struct etharp_hdr *hdr;
638    struct pbuf *p;    struct pbuf *p;
639    u8_t i, j;    u8_t i;
   u8_t maxtime;  
640    
641    srcaddr = (struct eth_addr *)netif->hwaddr;    srcaddr = (struct eth_addr *)netif->hwaddr;
642    /* We check if we are already querying for this address. If so,    /* bail out if this IP address is pending */
643    we'll bail out. */    for(i = 0; i < ARP_TABLE_SIZE; ++i) {
644    for(i = 0; i < ARP_TABLE_SIZE; ++i)      if(arp_table[i].state == ETHARP_STATE_PENDING &&
645    {        ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
646      if(arp_table[i].state == ETHARP_STATE_PENDING && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr))        DEBUGF(ETHARP_DEBUG, ("etharp_query: request already pending\n"));
647      {        /* TODO: enqueue q here if possible (BEWARE: possible other packet already
648        DEBUGF(ETHARP_DEBUG, ("etharp_output: already queued\n"));           queued. */
649          /* TODO: The host requirements RFC states that ARP should save at least one
650             packet, and this should be the _latest_ packet. */
651          /* TODO: use the ctime field to see how long ago an ARP request was sent,
652             possibly retry. */
653        return NULL;        return NULL;
654      }      }
655    }    }
656    /* We now try to find an unused entry in the ARP table that we    i = find_arp_entry();
657    will setup and queue the outgoing packet. */    /* bail out if no ARP entries are available */
   for(i = 0; i < ARP_TABLE_SIZE; ++i)  
   {  
     if(arp_table[i].state == ETHARP_STATE_EMPTY)  
     {  
       break;  
     }  
   }  
   
   /* If no unused entry is found, we try to find the oldest entry and  
   throw it away. */  
   if(i == ARP_TABLE_SIZE)  
   {  
     maxtime = 0;  
     j = 0;  
     for(i = 0; i < ARP_TABLE_SIZE; ++i)  
     {  
       if(arp_table[i].state == ETHARP_STATE_STABLE && ctime - arp_table[i].ctime > maxtime)  
       {  
         maxtime = ctime - arp_table[i].ctime;  
         j = i;  
       }  
     }  
     i = j;  
   }  
   
   /* If all table entries were in pending state, we won't send out any  
   more ARP requests. We'll just give up. */  
658    if(i == ARP_TABLE_SIZE)    if(i == ARP_TABLE_SIZE)
659    {    {
660      DEBUGF(ETHARP_DEBUG, ("etharp_output: no more ARP table entries available.\n"));      DEBUGF(ETHARP_DEBUG, ("etharp_query: no more ARP table entries available.\n"));
661      return NULL;      return NULL;
662    }    }
663    
664    /* Now, i is the ARP table entry which we will fill with the new    /* i is an available ARP table entry */
665    information. */    /* allocate a pbuf for the outgoing ARP request packet */
   ip_addr_set(&arp_table[i].ipaddr, ipaddr);  
   /*    for(k = 0; k < 6; ++k) {  
   arp_table[i].ethaddr.addr[k] = dest->addr[k];  
   }*/  
   arp_table[i].ctime = ctime;  
   arp_table[i].state = ETHARP_STATE_PENDING;  
   arp_table[i].p = NULL;  
   
   /* We allocate a pbuf for the outgoing ARP request packet. */  
666    p = pbuf_alloc(PBUF_LINK, sizeof(struct etharp_hdr), PBUF_RAM);    p = pbuf_alloc(PBUF_LINK, sizeof(struct etharp_hdr), PBUF_RAM);
667    if(p == NULL)    /* could allocate pbuf? */
668    {    if (p != NULL) {
669      /* No ARP request packet could be allocated, so we forget about      ip_addr_set(&arp_table[i].ipaddr, ipaddr);
670      the ARP table entry. */      arp_table[i].ctime = ctime;
671      if(i != ARP_TABLE_SIZE)      arp_table[i].state = ETHARP_STATE_PENDING;
672      {      /* remember pbuf to queue, if any */
673        arp_table[i].state = ETHARP_STATE_EMPTY;      arp_table[i].p = q;
674      }            /* any pbuf to queue? */
675        if (q != NULL) {
676          /* pbufs are queued, increase the reference count */
677          pbuf_ref_chain(q);
678        }
679      }
680      /* could not allocate pbuf for ARP request */
681      else {
682      return NULL;      return NULL;
683    }    }
684      /* p is the allocated pbuf */
685      
686    hdr = p->payload;    hdr = p->payload;
   
687    hdr->opcode = htons(ARP_REQUEST);    hdr->opcode = htons(ARP_REQUEST);
688    
689    for(i = 0; i < 6; ++i)    for(i = 0; i < 6; ++i)

Legend:
Removed from v.1.5  
changed lines
  Added in v.1.6

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26