These are the examples provided for [[/users/frank26080115/libraries/LPC1700CMSIS_Lib/]] Note, the entire "program" is not compilable!

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers uip_arp.c Source File

uip_arp.c

Go to the documentation of this file.
00001 /**
00002  * \addtogroup uip
00003  * @{
00004  */
00005 
00006 /**
00007  * \defgroup uiparp uIP Address Resolution Protocol
00008  * @{
00009  *
00010  * The Address Resolution Protocol ARP is used for mapping between IP
00011  * addresses and link level addresses such as the Ethernet MAC
00012  * addresses. ARP uses broadcast queries to ask for the link level
00013  * address of a known IP address and the host which is configured with
00014  * the IP address for which the query was meant, will respond with its
00015  * link level address.
00016  *
00017  * \note This ARP implementation only supports Ethernet.
00018  */
00019 
00020 /**
00021  * \file
00022  * Implementation of the ARP Address Resolution Protocol.
00023  * \author Adam Dunkels <adam@dunkels.com>
00024  *
00025  */
00026 
00027 /*
00028  * Copyright (c) 2001-2003, Adam Dunkels.
00029  * All rights reserved.
00030  *
00031  * Redistribution and use in source and binary forms, with or without
00032  * modification, are permitted provided that the following conditions
00033  * are met:
00034  * 1. Redistributions of source code must retain the above copyright
00035  *    notice, this list of conditions and the following disclaimer.
00036  * 2. Redistributions in binary form must reproduce the above copyright
00037  *    notice, this list of conditions and the following disclaimer in the
00038  *    documentation and/or other materials provided with the distribution.
00039  * 3. The name of the author may not be used to endorse or promote
00040  *    products derived from this software without specific prior
00041  *    written permission.
00042  *
00043  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
00044  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00045  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00046  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
00047  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00048  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00049  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00050  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00051  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00052  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00053  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00054  *
00055  * This file is part of the uIP TCP/IP stack.
00056  *
00057  * $Id: uip_arp.c,v 1.8 2006/06/02 23:36:21 adam Exp $
00058  *
00059  */
00060 
00061 
00062 #include "uip_arp.h"
00063 
00064 #include <string.h>
00065 
00066 #ifdef __ICCARM__
00067     #pragma pack(1)
00068 #endif
00069 
00070 //#if defined ( __CC_ARM   )
00071 //__packed
00072 //#elif defined   (  __GNUC__  )
00073 //__attribute__ ((__packed__))
00074 //#endif
00075 struct arp_hdr {
00076   struct uip_eth_hdr ethhdr;
00077   u16_t hwtype;
00078   u16_t protocol;
00079   u8_t hwlen;
00080   u8_t protolen;
00081   u16_t opcode;
00082   struct uip_eth_addr shwaddr;
00083   u16_t sipaddr[2];
00084   struct uip_eth_addr dhwaddr;
00085   u16_t dipaddr[2];
00086 } /*PACK_STRUCT_END*/;
00087 
00088 #ifdef __ICCARM__
00089     #pragma pack()
00090 #endif
00091 
00092 #ifdef __ICCARM__
00093     #pragma pack(1)
00094 #endif
00095 
00096 //#if defined ( __CC_ARM   )
00097 //__packed
00098 //#elif defined   (  __GNUC__  )
00099 //__attribute__ ((__packed__))
00100 //#endif
00101 struct ethip_hdr {
00102   struct uip_eth_hdr ethhdr;
00103   /* IP header. */
00104   u8_t vhl,
00105     tos,
00106     len[2],
00107     ipid[2],
00108     ipoffset[2],
00109     ttl,
00110     proto;
00111   u16_t ipchksum;
00112   u16_t srcipaddr[2],
00113     destipaddr[2];
00114 } /*PACK_STRUCT_END*/;
00115 
00116 #ifdef __ICCARM__
00117     #pragma pack()
00118 #endif
00119 
00120 #define ARP_REQUEST 1
00121 #define ARP_REPLY   2
00122 
00123 #define ARP_HWTYPE_ETH 1
00124 
00125 struct arp_entry {
00126   u16_t ipaddr[2];
00127   struct uip_eth_addr ethaddr;
00128   u8_t time;
00129 };
00130 
00131 static const struct uip_eth_addr broadcast_ethaddr =
00132   {{0xff,0xff,0xff,0xff,0xff,0xff}};
00133 static const u16_t broadcast_ipaddr[2] = {0xffff,0xffff};
00134 
00135 static struct arp_entry arp_table[UIP_ARPTAB_SIZE];
00136 static u16_t ipaddr[2];
00137 static u8_t i, c;
00138 
00139 static u8_t arptime;
00140 static u8_t tmpage;
00141 
00142 #define BUF   ((struct arp_hdr *)&uip_buf[0])
00143 #define IPBUF ((struct ethip_hdr *)&uip_buf[0])
00144 /*-----------------------------------------------------------------------------------*/
00145 /**
00146  * Initialize the ARP module.
00147  *
00148  */
00149 /*-----------------------------------------------------------------------------------*/
00150 void
00151 uip_arp_init(void)
00152 {
00153   for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
00154     memset(arp_table[i].ipaddr, 0, 4);
00155   }
00156 }
00157 /*-----------------------------------------------------------------------------------*/
00158 /**
00159  * Periodic ARP processing function.
00160  *
00161  * This function performs periodic timer processing in the ARP module
00162  * and should be called at regular intervals. The recommended interval
00163  * is 10 seconds between the calls.
00164  *
00165  */
00166 /*-----------------------------------------------------------------------------------*/
00167 void
00168 uip_arp_timer(void)
00169 {
00170   struct arp_entry *tabptr;
00171 
00172   ++arptime;
00173   for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
00174     tabptr = &arp_table[i];
00175     if((tabptr->ipaddr[0] | tabptr->ipaddr[1]) != 0 &&
00176        arptime - tabptr->time >= UIP_ARP_MAXAGE) {
00177       memset(tabptr->ipaddr, 0, 4);
00178     }
00179   }
00180 
00181 }
00182 /*-----------------------------------------------------------------------------------*/
00183 static void
00184 uip_arp_update(u16_t *ipaddr, struct uip_eth_addr *ethaddr)
00185 {
00186   register struct arp_entry *tabptr;
00187   /* Walk through the ARP mapping table and try to find an entry to
00188      update. If none is found, the IP -> MAC address mapping is
00189      inserted in the ARP table. */
00190   for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
00191 
00192     tabptr = &arp_table[i];
00193     /* Only check those entries that are actually in use. */
00194     if(tabptr->ipaddr[0] != 0 &&
00195        tabptr->ipaddr[1] != 0) {
00196 
00197       /* Check if the source IP address of the incoming packet matches
00198          the IP address in this ARP table entry. */
00199       if(ipaddr[0] == tabptr->ipaddr[0] &&
00200      ipaddr[1] == tabptr->ipaddr[1]) {
00201 
00202     /* An old entry found, update this and return. */
00203     memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6);
00204     tabptr->time = arptime;
00205 
00206     return;
00207       }
00208     }
00209   }
00210 
00211   /* If we get here, no existing ARP table entry was found, so we
00212      create one. */
00213 
00214   /* First, we try to find an unused entry in the ARP table. */
00215   for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
00216     tabptr = &arp_table[i];
00217     if(tabptr->ipaddr[0] == 0 &&
00218        tabptr->ipaddr[1] == 0) {
00219       break;
00220     }
00221   }
00222 
00223   /* If no unused entry is found, we try to find the oldest entry and
00224      throw it away. */
00225   if(i == UIP_ARPTAB_SIZE) {
00226     tmpage = 0;
00227     c = 0;
00228     for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
00229       tabptr = &arp_table[i];
00230       if(arptime - tabptr->time > tmpage) {
00231     tmpage = arptime - tabptr->time;
00232     c = i;
00233       }
00234     }
00235     i = c;
00236     tabptr = &arp_table[i];
00237   }
00238 
00239   /* Now, i is the ARP table entry which we will fill with the new
00240      information. */
00241   memcpy(tabptr->ipaddr, ipaddr, 4);
00242   memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6);
00243   tabptr->time = arptime;
00244 }
00245 /*-----------------------------------------------------------------------------------*/
00246 /**
00247  * ARP processing for incoming IP packets
00248  *
00249  * This function should be called by the device driver when an IP
00250  * packet has been received. The function will check if the address is
00251  * in the ARP cache, and if so the ARP cache entry will be
00252  * refreshed. If no ARP cache entry was found, a new one is created.
00253  *
00254  * This function expects an IP packet with a prepended Ethernet header
00255  * in the uip_buf[] buffer, and the length of the packet in the global
00256  * variable uip_len.
00257  */
00258 /*-----------------------------------------------------------------------------------*/
00259 #if 1
00260 void
00261 uip_arp_ipin(void)
00262 {
00263   uip_len -= sizeof(struct uip_eth_hdr);
00264 
00265   /* Only insert/update an entry if the source IP address of the
00266      incoming IP packet comes from a host on the local network. */
00267   if((IPBUF->srcipaddr[0] & uip_netmask[0]) !=
00268      (uip_hostaddr[0] & uip_netmask[0])) {
00269     return;
00270   }
00271   if((IPBUF->srcipaddr[1] & uip_netmask[1]) !=
00272      (uip_hostaddr[1] & uip_netmask[1])) {
00273     return;
00274   }
00275   uip_arp_update(IPBUF->srcipaddr, &(IPBUF->ethhdr.src));
00276 
00277   return;
00278 }
00279 #endif /* 0 */
00280 /*-----------------------------------------------------------------------------------*/
00281 /**
00282  * ARP processing for incoming ARP packets.
00283  *
00284  * This function should be called by the device driver when an ARP
00285  * packet has been received. The function will act differently
00286  * depending on the ARP packet type: if it is a reply for a request
00287  * that we previously sent out, the ARP cache will be filled in with
00288  * the values from the ARP reply. If the incoming ARP packet is an ARP
00289  * request for our IP address, an ARP reply packet is created and put
00290  * into the uip_buf[] buffer.
00291  *
00292  * When the function returns, the value of the global variable uip_len
00293  * indicates whether the device driver should send out a packet or
00294  * not. If uip_len is zero, no packet should be sent. If uip_len is
00295  * non-zero, it contains the length of the outbound packet that is
00296  * present in the uip_buf[] buffer.
00297  *
00298  * This function expects an ARP packet with a prepended Ethernet
00299  * header in the uip_buf[] buffer, and the length of the packet in the
00300  * global variable uip_len.
00301  */
00302 /*-----------------------------------------------------------------------------------*/
00303 void
00304 uip_arp_arpin(void)
00305 {
00306 
00307   if(uip_len < sizeof(struct arp_hdr)) {
00308     uip_len = 0;
00309     return;
00310   }
00311   uip_len = 0;
00312 
00313   switch(BUF->opcode) {
00314   case HTONS(ARP_REQUEST):
00315     /* ARP request. If it asked for our address, we send out a
00316        reply. */
00317     if(uip_ipaddr_cmp(BUF->dipaddr, uip_hostaddr)) {
00318       /* First, we register the one who made the request in our ARP
00319      table, since it is likely that we will do more communication
00320      with this host in the future. */
00321       uip_arp_update(BUF->sipaddr, &BUF->shwaddr);
00322 
00323       /* The reply opcode is 2. */
00324       BUF->opcode = HTONS(2);
00325 
00326       memcpy(BUF->dhwaddr.addr, BUF->shwaddr.addr, 6);
00327       memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6);
00328       memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
00329       memcpy(BUF->ethhdr.dest.addr, BUF->dhwaddr.addr, 6);
00330 
00331       BUF->dipaddr[0] = BUF->sipaddr[0];
00332       BUF->dipaddr[1] = BUF->sipaddr[1];
00333       BUF->sipaddr[0] = uip_hostaddr[0];
00334       BUF->sipaddr[1] = uip_hostaddr[1];
00335 
00336       BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP);
00337       uip_len = sizeof(struct arp_hdr);
00338     }
00339     break;
00340   case HTONS(ARP_REPLY):
00341     /* ARP reply. We insert or update the ARP table if it was meant
00342        for us. */
00343     if(uip_ipaddr_cmp(BUF->dipaddr, uip_hostaddr)) {
00344       uip_arp_update(BUF->sipaddr, &BUF->shwaddr);
00345     }
00346     break;
00347   }
00348 
00349   return;
00350 }
00351 /*-----------------------------------------------------------------------------------*/
00352 /**
00353  * Prepend Ethernet header to an outbound IP packet and see if we need
00354  * to send out an ARP request.
00355  *
00356  * This function should be called before sending out an IP packet. The
00357  * function checks the destination IP address of the IP packet to see
00358  * what Ethernet MAC address that should be used as a destination MAC
00359  * address on the Ethernet.
00360  *
00361  * If the destination IP address is in the local network (determined
00362  * by logical ANDing of netmask and our IP address), the function
00363  * checks the ARP cache to see if an entry for the destination IP
00364  * address is found. If so, an Ethernet header is prepended and the
00365  * function returns. If no ARP cache entry is found for the
00366  * destination IP address, the packet in the uip_buf[] is replaced by
00367  * an ARP request packet for the IP address. The IP packet is dropped
00368  * and it is assumed that they higher level protocols (e.g., TCP)
00369  * eventually will retransmit the dropped packet.
00370  *
00371  * If the destination IP address is not on the local network, the IP
00372  * address of the default router is used instead.
00373  *
00374  * When the function returns, a packet is present in the uip_buf[]
00375  * buffer, and the length of the packet is in the global variable
00376  * uip_len.
00377  */
00378 /*-----------------------------------------------------------------------------------*/
00379 void
00380 uip_arp_out(void)
00381 {
00382   struct arp_entry *tabptr;
00383 
00384   /* Find the destination IP address in the ARP table and construct
00385      the Ethernet header. If the destination IP addres isn't on the
00386      local network, we use the default router's IP address instead.
00387 
00388      If not ARP table entry is found, we overwrite the original IP
00389      packet with an ARP request for the IP address. */
00390 
00391   /* First check if destination is a local broadcast. */
00392   if(uip_ipaddr_cmp(IPBUF->destipaddr, broadcast_ipaddr)) {
00393     memcpy(IPBUF->ethhdr.dest.addr, broadcast_ethaddr.addr, 6);
00394   } else {
00395     /* Check if the destination address is on the local network. */
00396     if(!uip_ipaddr_maskcmp(IPBUF->destipaddr, uip_hostaddr, uip_netmask)) {
00397       /* Destination address was not on the local network, so we need to
00398      use the default router's IP address instead of the destination
00399      address when determining the MAC address. */
00400       uip_ipaddr_copy(ipaddr, uip_draddr);
00401     } else {
00402       /* Else, we use the destination IP address. */
00403       uip_ipaddr_copy(ipaddr, IPBUF->destipaddr);
00404     }
00405 
00406     for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
00407       tabptr = &arp_table[i];
00408       if(uip_ipaddr_cmp(ipaddr, tabptr->ipaddr)) {
00409     break;
00410       }
00411     }
00412 
00413     if(i == UIP_ARPTAB_SIZE) {
00414       /* The destination address was not in our ARP table, so we
00415      overwrite the IP packet with an ARP request. */
00416 
00417       memset(BUF->ethhdr.dest.addr, 0xff, 6);
00418       memset(BUF->dhwaddr.addr, 0x00, 6);
00419       memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
00420       memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6);
00421 
00422       uip_ipaddr_copy(BUF->dipaddr, ipaddr);
00423       uip_ipaddr_copy(BUF->sipaddr, uip_hostaddr);
00424       BUF->opcode = HTONS(ARP_REQUEST); /* ARP request. */
00425       BUF->hwtype = HTONS(ARP_HWTYPE_ETH);
00426       BUF->protocol = HTONS(UIP_ETHTYPE_IP);
00427       BUF->hwlen = 6;
00428       BUF->protolen = 4;
00429       BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP);
00430 
00431       uip_appdata = &uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN];
00432 
00433       uip_len = sizeof(struct arp_hdr);
00434       return;
00435     }
00436 
00437     /* Build an ethernet header. */
00438     memcpy(IPBUF->ethhdr.dest.addr, tabptr->ethaddr.addr, 6);
00439   }
00440   memcpy(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
00441 
00442   IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP);
00443 
00444   uip_len += sizeof(struct uip_eth_hdr);
00445 }
00446 /*-----------------------------------------------------------------------------------*/
00447 
00448 /** @} */
00449 /** @} */