/[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.1.1.1 by likewise, Sat Oct 19 13:00:16 2002 UTC revision 1.2 by likewise, Mon Nov 4 14:56:40 2002 UTC
# Line 1  Line 1 
1    /**
2     * @file
3     * Address Resolution Protocol module for IP over Ethernet
4     *
5     * $Log$
6     * Revision 1.2  2002/11/04 14:56:40  likewise
7     * Fixed NULL pointer bug (#1493). Fix for memory leak bug (#1601), etharp_output_sent(). Added etharp_query for DHCP.
8     *
9     */
10    
11  /*  /*
12   * Copyright (c) 2001, 2002 Swedish Institute of Computer Science.   * Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
13   * All rights reserved.   * All rights reserved.
# Line 28  Line 38 
38   *   *
39   * Author: Adam Dunkels <adam@sics.se>   * Author: Adam Dunkels <adam@sics.se>
40   *   *
  *  
41   */   */
42    
43  #include "lwip/opt.h"  #include "lwip/opt.h"
# Line 100  static const struct eth_addr ethbroadcas Line 109  static const struct eth_addr ethbroadcas
109  static struct etharp_entry arp_table[ARP_TABLE_SIZE];  static struct etharp_entry arp_table[ARP_TABLE_SIZE];
110  static u8_t ctime;  static u8_t ctime;
111    
112  /*-----------------------------------------------------------------------------------*/  /**
113     * Initializes ARP module.
114     */
115  void  void
116  etharp_init(void)  etharp_init(void)
117  {  {
118    u8_t i;    u8_t i;
119        /* clear ARP entries */
120    for(i = 0; i < ARP_TABLE_SIZE; ++i) {    for(i = 0; i < ARP_TABLE_SIZE; ++i) {
121      arp_table[i].state = ETHARP_STATE_EMPTY;      arp_table[i].state = ETHARP_STATE_EMPTY;
122    }    }
123  }  }
124  /*-----------------------------------------------------------------------------------*/  
125    /**
126     * Clears expired entries in the ARP table.
127     *
128     * This function should be called every ETHARP_TMR_INTERVAL microseconds (10 seconds),
129     * in order to expire entries in the ARP table.
130     */
131  void  void
132  etharp_tmr(void)  etharp_tmr(void)
133  {  {
134    u8_t i;    u8_t i;
135        
136    ++ctime;    ++ctime;
137      /* remove expired entries from the ARP table */
138    for(i = 0; i < ARP_TABLE_SIZE; ++i) {    for(i = 0; i < ARP_TABLE_SIZE; ++i) {
139      if(arp_table[i].state == ETHARP_STATE_STABLE &&            if(arp_table[i].state == ETHARP_STATE_STABLE &&      
140         ctime - arp_table[i].ctime >= ARP_MAXAGE) {         ctime - arp_table[i].ctime >= ARP_MAXAGE) {
# Line 127  etharp_tmr(void) Line 145  etharp_tmr(void)
145        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 %d - dequeueing %p.\n", i, arp_table[i].p));
146        arp_table[i].state = ETHARP_STATE_EMPTY;        arp_table[i].state = ETHARP_STATE_EMPTY;
147        pbuf_free(arp_table[i].p);              pbuf_free(arp_table[i].p);      
148          arp_table[i].p = NULL;
149      }      }
150    }      }  
151  }  }
152  /*----------------------------------------------------------------------------------*/  
153    /**
154     * Return an empty ARP entry or, if the table is full, ARP_TABLE_SIZE if all
155     * entries are pending, otherwise the oldest entry.
156     *
157     * @return The ARP entry index that is available, ARP_TABLE_SIZE if no usable
158     * entry is found.
159     */
160  static u8_t  static u8_t
161  find_arp_entry(void)  find_arp_entry(void)
162  {  {
# Line 159  find_arp_entry(void) Line 185  find_arp_entry(void)
185    }    }
186    return i;    return i;
187  }  }
188  /*-----------------------------------------------------------------------------------*/  
189  static struct pbuf *  static struct pbuf *
190  update_arp_entry(struct ip_addr *ipaddr, struct eth_addr *ethaddr)  update_arp_entry(struct ip_addr *ipaddr, struct eth_addr *ethaddr)
191  {  {
# Line 227  update_arp_entry(struct ip_addr *ipaddr, Line 253  update_arp_entry(struct ip_addr *ipaddr,
253        
254    return NULL;    return NULL;
255  }  }
256  /*-----------------------------------------------------------------------------------*/  
257    /**
258     * Updates the ARP table and may return any queued packet to be sent
259     *
260     * Should be called for all incoming packets of IP kind. The function
261     * does not alter the packet in any way, it just updates the ARP
262     * table. After this function has been called, the normal TCP/IP stack
263     * input function should be called.
264     *
265     * The function may return a pbuf containing a packet that had
266     * previously been queued for transmission. The device driver must
267     * transmit this packet onto the network, and call pbuf_free() for the
268     * pbuf.
269     */
270  struct pbuf *  struct pbuf *
271  etharp_ip_input(struct netif *netif, struct pbuf *p)  etharp_ip_input(struct netif *netif, struct pbuf *p)
272  {  {
# Line 243  etharp_ip_input(struct netif *netif, str Line 282  etharp_ip_input(struct netif *netif, str
282    DEBUGF(ETHARP_DEBUG, ("etharp_ip_input: updating ETHARP table.\n"));    DEBUGF(ETHARP_DEBUG, ("etharp_ip_input: updating ETHARP table.\n"));
283    return update_arp_entry(&(hdr->ip.src), &(hdr->eth.src));    return update_arp_entry(&(hdr->ip.src), &(hdr->eth.src));
284  }  }
285  /*-----------------------------------------------------------------------------------*/  
286    
287    /**
288     * Updates the ARP table and may return any queued packet to be sent
289     *
290     * Should be called for incoming ARP packets. The pbuf in the argument
291     * is freed by this function. If the function returns a pbuf (i.e.,
292     * returns non-NULL), that pbuf constitutes an ARP reply and should be
293     * sent out on the Ethernet.
294     *
295     * @note The driver must call pbuf_free() for the returned pbuf when the
296     * packet has been sent.
297     */
298  struct pbuf *  struct pbuf *
299  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)
300  {  {
# Line 290  etharp_arp_input(struct netif *netif, st Line 341  etharp_arp_input(struct netif *netif, st
341      /* ARP reply. We insert or update the ARP table. */      /* ARP reply. We insert or update the ARP table. */
342      DEBUGF(ETHARP_DEBUG, ("etharp_arp_input: ARP reply\n"));      DEBUGF(ETHARP_DEBUG, ("etharp_arp_input: ARP reply\n"));
343      if(ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr))) {          if(ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr))) {    
344          struct pbuf *q;
345  #if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)  #if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
346        dhcp_arp_reply(&hdr->sipaddr);        dhcp_arp_reply(&hdr->sipaddr);
347  #endif  #endif
348        /* update_arp_entry() will return a pbuf that has previously been        /* update_arp_entry() will return a pbuf that has previously been
349           queued waiting for an ARP reply. */           queued waiting for an ARP reply. */
350          q = update_arp_entry(&(hdr->sipaddr), &(hdr->shwaddr));
351        pbuf_free(p);        pbuf_free(p);
352        p = update_arp_entry(&(hdr->sipaddr), &(hdr->shwaddr));        p = NULL;
353          return q;
       return p;  
354      }      }
355      break;      break;
356    default:    default:
# Line 309  etharp_arp_input(struct netif *netif, st Line 361  etharp_arp_input(struct netif *netif, st
361    pbuf_free(p);    pbuf_free(p);
362    return NULL;    return NULL;
363  }  }
364  /*-----------------------------------------------------------------------------------*/  
365    /**
366     * Resolve Ethernet address and append header to the outgoing packet.
367     *
368     * The etharp_output() function should be called for all outgoing
369     * packets. The pbuf returned by the function should be sent out on
370     * the Ethernet. This pbuf must then be passed to etharp_output_sent().
371     *
372     * The function prepares the packet for transmission over the Ethernet
373     * by adding an Ethernet header. If there is no IP -> MAC address
374     * mapping, the function will queue the outgoing packet and return an
375     * ARP request packet instead.
376     *
377     * @param netif The lwIP network interface which the IP packet will be sent on.
378     * @param ipaddr The IP address of the packet destination.
379     * @param pbuf The pbuf(s) containing the IP packet.
380     *
381     * @return The packet which should be sent on the network and must be freed by
382     * the caller.
383     *
384     * @see etharp_output_sent()
385     */
386  struct pbuf *  struct pbuf *
387  etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)  etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
388  {  {
# Line 319  etharp_output(struct netif *netif, struc Line 392  etharp_output(struct netif *netif, struc
392    struct pbuf *p;    struct pbuf *p;
393    u8_t i;    u8_t i;
394    
395      /* obtain source Ethernet address of the given interface */
396    srcaddr = (struct eth_addr *)netif->hwaddr;    srcaddr = (struct eth_addr *)netif->hwaddr;
397    
398    /* Make room for Ethernet header. */    /* Make room for Ethernet header. */
# Line 332  etharp_output(struct netif *netif, struc Line 406  etharp_output(struct netif *netif, struc
406      return NULL;      return NULL;
407    }    }
408    
409      /* assume unresolved Ethernet address */
410    dest = NULL;    dest = NULL;
411    /* Construct Ethernet header. Start with looking up deciding which    /* Construct Ethernet header. Start with looking up deciding which
412       MAC address to use as a destination address. Broadcasts and       MAC address to use as a destination address. Broadcasts and
413       multicasts are special, all other addresses are looked up in the       multicasts are special, all other addresses are looked up in the
414       ARP table. */       ARP table. */
415      /* destination IP address is an IP broadcast address? */
416    if(ip_addr_isany(ipaddr) ||    if(ip_addr_isany(ipaddr) ||
417       ip_addr_isbroadcast(ipaddr, &(netif->netmask))) {       ip_addr_isbroadcast(ipaddr, &(netif->netmask))) {
418        /* broadcast on Ethernet also */
419      dest = (struct eth_addr *)&ethbroadcast;      dest = (struct eth_addr *)&ethbroadcast;
420    } else if(ip_addr_ismulticast(ipaddr)) {    } else if(ip_addr_ismulticast(ipaddr)) {
421      /* Hash IP multicast address to MAC address. */      /* Hash IP multicast address to MAC address. */
# Line 349  etharp_output(struct netif *netif, struc Line 425  etharp_output(struct netif *netif, struc
425      mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;      mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;
426      mcastaddr.addr[4] = ip4_addr3(ipaddr);      mcastaddr.addr[4] = ip4_addr3(ipaddr);
427      mcastaddr.addr[5] = ip4_addr4(ipaddr);      mcastaddr.addr[5] = ip4_addr4(ipaddr);
428        /* destination Ethernet address is multicast */
429      dest = &mcastaddr;      dest = &mcastaddr;
430      /* destination IP unicast address */
431    } else {    } else {
432        /* the destination IP network address does not match the interface's
433           network address */
434      if(!ip_addr_maskcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) {      if(!ip_addr_maskcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) {
435        /* Use the IP address of the default gateway if the destination        /* Use the IP address of the default gateway if the destination
436           is on the same subnet as we are. */                 is not on the same subnet as we are. */      
437        ipaddr = &(netif->gw);        ipaddr = &(netif->gw);
438      }      }
439    
440      /* We try to find a stable mapping. */      /* Try to find a stable IP-to-Ethernet address mapping for this IP
441           destination address */
442      for(i = 0; i < ARP_TABLE_SIZE; ++i) {          for(i = 0; i < ARP_TABLE_SIZE; ++i) {    
443        if(arp_table[i].state == ETHARP_STATE_STABLE &&        if(arp_table[i].state == ETHARP_STATE_STABLE &&
444           ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {           ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
# Line 367  etharp_output(struct netif *netif, struc Line 448  etharp_output(struct netif *netif, struc
448      }      }
449    }    }
450        
451      /* could not find a destination Ethernet address? */
452    if(dest == NULL) {    if(dest == NULL) {
453      /* No destination address has been found, so we'll have to send      /* No destination address has been found, so we'll have to send
454         out an ARP request for the IP address. The outgoing packet is         out an ARP request for the IP address. The outgoing packet is
455         queued unless the queue is full. */         queued unless the queue is full. */
456          
457        /* TODO: The host requirements RFC states that ARP should save at least one
458           packet, and this should be the _latest_ packet. */
459            
460      /* We check if we are already querying for this address. If so,      /* We check if we are already querying for this address. If so,
461         we'll bail out. */         we'll bail out. */
# Line 382  etharp_output(struct netif *netif, struc Line 467  etharp_output(struct netif *netif, struc
467        }        }
468      }      }
469    
470        /* find a usable ARP entry */
471      i = find_arp_entry();      i = find_arp_entry();
472            
473      /* If all table entries were in pending state, we won't send out any      /* If all table entries were in pending state, we won't send out any
# Line 393  etharp_output(struct netif *netif, struc Line 479  etharp_output(struct netif *netif, struc
479      /* Now, i is the ARP table entry which we will fill with the new      /* Now, i is the ARP table entry which we will fill with the new
480         information. */         information. */
481      ip_addr_set(&arp_table[i].ipaddr, ipaddr);      ip_addr_set(&arp_table[i].ipaddr, ipaddr);
     /*    for(k = 0; k < 6; ++k) {  
           arp_table[i].ethaddr.addr[k] = dest->addr[k];  
           }*/  
482      arp_table[i].ctime = ctime;      arp_table[i].ctime = ctime;
483      arp_table[i].state = ETHARP_STATE_PENDING;      arp_table[i].state = ETHARP_STATE_PENDING;
484  #if 1  #if 1
# Line 404  etharp_output(struct netif *netif, struc Line 487  etharp_output(struct netif *netif, struc
487      arp_table[i].len = q->len;      arp_table[i].len = q->len;
488      arp_table[i].tot_len = q->tot_len;      arp_table[i].tot_len = q->tot_len;
489            
490      /* Because the pbuf will be queued, we'll increase the refernce      /* Because the pbuf will be queued, we'll increase the reference
491         count. */         count. */
492      DEBUGF(ETHARP_DEBUG, ("etharp_output: queueing %p\n", q));      DEBUGF(ETHARP_DEBUG, ("etharp_output: queueing %p\n", q));
493      pbuf_ref(q);      pbuf_ref(q);
# Line 468  etharp_output(struct netif *netif, struc Line 551  etharp_output(struct netif *netif, struc
551        
552      return q;      return q;
553    }    }
554      }
555    
556    /**
557     * Clean up the ARP request that was allocated by ARP.
558     *
559     * This must be called after you have sent the packet
560     * returned by etharp_output(). It frees any pbuf
561     * allocated for an ARP request.
562     */
563    struct pbuf *
564    etharp_output_sent(struct pbuf *p)
565    {
566      struct etharp_hdr *hdr;
567      hdr=p->payload;
568      if (hdr->opcode == htons(ARP_REQUEST)) {
569        pbuf_free(p); p=NULL;
570      };
571      return p;
572    }
573    
574    /**
575     * Initiate an ARP query for the given IP address.
576     *
577     * Used by the DHCP module to support "gratuitous" ARP,
578     * i.e. send ARP requests for one's own IP address, to
579     * see if others have the IP address in use.
580     *
581     * Might be used in the future by manual IP configuration
582     * as well.
583     *
584     */
585    
586    struct pbuf *etharp_query(struct netif *netif, struct ip_addr *ipaddr)
587    {
588      struct eth_addr *srcaddr;
589      struct etharp_hdr *hdr;
590      struct pbuf *p;
591      u8_t i, j;
592      u8_t maxtime;
593    
594      srcaddr = (struct eth_addr *)netif->hwaddr;
595      /* We check if we are already querying for this address. If so,
596      we'll bail out. */
597      for(i = 0; i < ARP_TABLE_SIZE; ++i)
598      {
599        if(arp_table[i].state == ETHARP_STATE_PENDING && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr))
600        {
601          DEBUGF(ETHARP_DEBUG, ("etharp_output: already queued\n"));
602          return NULL;
603        }
604      }
605      /* We now try to find an unused entry in the ARP table that we
606      will setup and queue the outgoing packet. */
607      for(i = 0; i < ARP_TABLE_SIZE; ++i)
608      {
609        if(arp_table[i].state == ETHARP_STATE_EMPTY)
610        {
611          break;
612        }
613      }
614    
615      /* If no unused entry is found, we try to find the oldest entry and
616      throw it away. */
617      if(i == ARP_TABLE_SIZE)
618      {
619        maxtime = 0;
620        j = 0;
621        for(i = 0; i < ARP_TABLE_SIZE; ++i)
622        {
623          if(arp_table[i].state == ETHARP_STATE_STABLE && ctime - arp_table[i].ctime > maxtime)
624          {
625            maxtime = ctime - arp_table[i].ctime;
626            j = i;
627          }
628        }
629        i = j;
630      }
631    
632      /* If all table entries were in pending state, we won't send out any
633      more ARP requests. We'll just give up. */
634      if(i == ARP_TABLE_SIZE)
635      {
636        DEBUGF(ETHARP_DEBUG, ("etharp_output: no more ARP table entries available.\n"));
637        return NULL;
638      }
639    
640      /* Now, i is the ARP table entry which we will fill with the new
641      information. */
642      ip_addr_set(&arp_table[i].ipaddr, ipaddr);
643      /*    for(k = 0; k < 6; ++k) {
644      arp_table[i].ethaddr.addr[k] = dest->addr[k];
645      }*/
646      arp_table[i].ctime = ctime;
647      arp_table[i].state = ETHARP_STATE_PENDING;
648      arp_table[i].p = NULL;
649    
650      /* We allocate a pbuf for the outgoing ARP request packet. */
651      p = pbuf_alloc(PBUF_LINK, sizeof(struct etharp_hdr), PBUF_RAM);
652      if(p == NULL)
653      {
654        /* No ARP request packet could be allocated, so we forget about
655        the ARP table entry. */
656        if(i != ARP_TABLE_SIZE)
657        {
658          arp_table[i].state = ETHARP_STATE_EMPTY;
659        }      
660        return NULL;
661      }
662    
663      hdr = p->payload;
664    
665      hdr->opcode = htons(ARP_REQUEST);
666    
667      for(i = 0; i < 6; ++i)
668      {
669        hdr->dhwaddr.addr[i] = 0x00;
670        hdr->shwaddr.addr[i] = srcaddr->addr[i];
671      }
672    
673      ip_addr_set(&(hdr->dipaddr), ipaddr);
674      ip_addr_set(&(hdr->sipaddr), &(netif->ip_addr));
675    
676      hdr->hwtype = htons(HWTYPE_ETHERNET);
677      ARPH_HWLEN_SET(hdr, 6);
678    
679      hdr->proto = htons(ETHTYPE_IP);
680      ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));
681    
682      for(i = 0; i < 6; ++i)
683      {
684        hdr->ethhdr.dest.addr[i] = 0xff;
685        hdr->ethhdr.src.addr[i] = srcaddr->addr[i];
686      }
687    
688      hdr->ethhdr.type = htons(ETHTYPE_ARP);      
689      return p;
690  }  }
 /*-----------------------------------------------------------------------------------*/  

Legend:
Removed from v.1.1.1.1  
changed lines
  Added in v.1.2

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