| 1 | 606 | jeremybenn | /**
 | 
      
         | 2 |  |  |  * \addtogroup uip
 | 
      
         | 3 |  |  |  * @{
 | 
      
         | 4 |  |  |  */
 | 
      
         | 5 |  |  |  
 | 
      
         | 6 |  |  | /**
 | 
      
         | 7 |  |  |  * \defgroup uiparp uIP Address Resolution Protocol
 | 
      
         | 8 |  |  |  * @{
 | 
      
         | 9 |  |  |  *
 | 
      
         | 10 |  |  |  * The Address Resolution Protocol ARP is used for mapping between IP
 | 
      
         | 11 |  |  |  * addresses and link level addresses such as the Ethernet MAC
 | 
      
         | 12 |  |  |  * addresses. ARP uses broadcast queries to ask for the link level
 | 
      
         | 13 |  |  |  * address of a known IP address and the host which is configured with
 | 
      
         | 14 |  |  |  * the IP address for which the query was meant, will respond with its
 | 
      
         | 15 |  |  |  * link level address.
 | 
      
         | 16 |  |  |  *
 | 
      
         | 17 |  |  |  * \note This ARP implementation only supports Ethernet.
 | 
      
         | 18 |  |  |  */
 | 
      
         | 19 |  |  |  
 | 
      
         | 20 |  |  | /**
 | 
      
         | 21 |  |  |  * \file
 | 
      
         | 22 |  |  |  * Implementation of the ARP Address Resolution Protocol.
 | 
      
         | 23 |  |  |  * \author Adam Dunkels <adam@dunkels.com>
 | 
      
         | 24 |  |  |  *
 | 
      
         | 25 |  |  |  */
 | 
      
         | 26 |  |  |  
 | 
      
         | 27 |  |  | /*
 | 
      
         | 28 |  |  |  * Copyright (c) 2001-2003, Adam Dunkels.
 | 
      
         | 29 |  |  |  * All rights reserved.
 | 
      
         | 30 |  |  |  *
 | 
      
         | 31 |  |  |  * Redistribution and use in source and binary forms, with or without
 | 
      
         | 32 |  |  |  * modification, are permitted provided that the following conditions
 | 
      
         | 33 |  |  |  * are met:
 | 
      
         | 34 |  |  |  * 1. Redistributions of source code must retain the above copyright
 | 
      
         | 35 |  |  |  *    notice, this list of conditions and the following disclaimer.
 | 
      
         | 36 |  |  |  * 2. Redistributions in binary form must reproduce the above copyright
 | 
      
         | 37 |  |  |  *    notice, this list of conditions and the following disclaimer in the
 | 
      
         | 38 |  |  |  *    documentation and/or other materials provided with the distribution.
 | 
      
         | 39 |  |  |  * 3. The name of the author may not be used to endorse or promote
 | 
      
         | 40 |  |  |  *    products derived from this software without specific prior
 | 
      
         | 41 |  |  |  *    written permission.
 | 
      
         | 42 |  |  |  *
 | 
      
         | 43 |  |  |  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
 | 
      
         | 44 |  |  |  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 | 
      
         | 45 |  |  |  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
      
         | 46 |  |  |  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 | 
      
         | 47 |  |  |  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | 
      
         | 48 |  |  |  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 | 
      
         | 49 |  |  |  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
      
         | 50 |  |  |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 | 
      
         | 51 |  |  |  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 | 
      
         | 52 |  |  |  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 | 
      
         | 53 |  |  |  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
      
         | 54 |  |  |  *
 | 
      
         | 55 |  |  |  * This file is part of the uIP TCP/IP stack.
 | 
      
         | 56 |  |  |  *
 | 
      
         | 57 |  |  |  * $Id: uip_arp.c 2 2011-07-17 20:13:17Z filepang@gmail.com $
 | 
      
         | 58 |  |  |  *
 | 
      
         | 59 |  |  |  */
 | 
      
         | 60 |  |  |  
 | 
      
         | 61 |  |  |  
 | 
      
         | 62 |  |  | #include "uip_arp.h"
 | 
      
         | 63 |  |  |  
 | 
      
         | 64 |  |  | #include <string.h>
 | 
      
         | 65 |  |  |  
 | 
      
         | 66 |  |  | #ifdef __ICCARM__
 | 
      
         | 67 |  |  |         #pragma pack(1)
 | 
      
         | 68 |  |  | #endif
 | 
      
         | 69 |  |  |  
 | 
      
         | 70 |  |  | struct arp_hdr {
 | 
      
         | 71 |  |  |   struct uip_eth_hdr ethhdr;
 | 
      
         | 72 |  |  |   u16_t hwtype;
 | 
      
         | 73 |  |  |   u16_t protocol;
 | 
      
         | 74 |  |  |   u8_t hwlen;
 | 
      
         | 75 |  |  |   u8_t protolen;
 | 
      
         | 76 |  |  |   u16_t opcode;
 | 
      
         | 77 |  |  |   struct uip_eth_addr shwaddr;
 | 
      
         | 78 |  |  |   u16_t sipaddr[2];
 | 
      
         | 79 |  |  |   struct uip_eth_addr dhwaddr;
 | 
      
         | 80 |  |  |   u16_t dipaddr[2];
 | 
      
         | 81 |  |  | } PACK_STRUCT_END;
 | 
      
         | 82 |  |  |  
 | 
      
         | 83 |  |  | #ifdef __ICCARM__
 | 
      
         | 84 |  |  |         #pragma pack()
 | 
      
         | 85 |  |  | #endif
 | 
      
         | 86 |  |  |  
 | 
      
         | 87 |  |  | #ifdef __ICCARM__
 | 
      
         | 88 |  |  |         #pragma pack(1)
 | 
      
         | 89 |  |  | #endif
 | 
      
         | 90 |  |  |  
 | 
      
         | 91 |  |  | struct ethip_hdr {
 | 
      
         | 92 |  |  |   struct uip_eth_hdr ethhdr;
 | 
      
         | 93 |  |  |   /* IP header. */
 | 
      
         | 94 |  |  |   u8_t vhl,
 | 
      
         | 95 |  |  |     tos,
 | 
      
         | 96 |  |  |     len[2],
 | 
      
         | 97 |  |  |     ipid[2],
 | 
      
         | 98 |  |  |     ipoffset[2],
 | 
      
         | 99 |  |  |     ttl,
 | 
      
         | 100 |  |  |     proto;
 | 
      
         | 101 |  |  |   u16_t ipchksum;
 | 
      
         | 102 |  |  |   u16_t srcipaddr[2],
 | 
      
         | 103 |  |  |     destipaddr[2];
 | 
      
         | 104 |  |  | } PACK_STRUCT_END;
 | 
      
         | 105 |  |  |  
 | 
      
         | 106 |  |  | #ifdef __ICCARM__
 | 
      
         | 107 |  |  |         #pragma pack()
 | 
      
         | 108 |  |  | #endif
 | 
      
         | 109 |  |  |  
 | 
      
         | 110 |  |  | #define ARP_REQUEST 1
 | 
      
         | 111 |  |  | #define ARP_REPLY   2
 | 
      
         | 112 |  |  |  
 | 
      
         | 113 |  |  | #define ARP_HWTYPE_ETH 1
 | 
      
         | 114 |  |  |  
 | 
      
         | 115 |  |  | struct arp_entry {
 | 
      
         | 116 |  |  |   u16_t ipaddr[2];
 | 
      
         | 117 |  |  |   struct uip_eth_addr ethaddr;
 | 
      
         | 118 |  |  |   u8_t time;
 | 
      
         | 119 |  |  | };
 | 
      
         | 120 |  |  |  
 | 
      
         | 121 |  |  | static const struct uip_eth_addr broadcast_ethaddr =
 | 
      
         | 122 |  |  |   {{0xff,0xff,0xff,0xff,0xff,0xff}};
 | 
      
         | 123 |  |  | static const u16_t broadcast_ipaddr[2] = {0xffff,0xffff};
 | 
      
         | 124 |  |  |  
 | 
      
         | 125 |  |  | static struct arp_entry arp_table[UIP_ARPTAB_SIZE];
 | 
      
         | 126 |  |  | static u16_t ipaddr[2];
 | 
      
         | 127 |  |  | static u8_t i, c;
 | 
      
         | 128 |  |  |  
 | 
      
         | 129 |  |  | static u8_t arptime;
 | 
      
         | 130 |  |  | static u8_t tmpage;
 | 
      
         | 131 |  |  |  
 | 
      
         | 132 |  |  | #define BUF   ((struct arp_hdr *)&uip_buf[0])
 | 
      
         | 133 |  |  | #define IPBUF ((struct ethip_hdr *)&uip_buf[0])
 | 
      
         | 134 |  |  | /*-----------------------------------------------------------------------------------*/
 | 
      
         | 135 |  |  | /**
 | 
      
         | 136 |  |  |  * Initialize the ARP module.
 | 
      
         | 137 |  |  |  *
 | 
      
         | 138 |  |  |  */
 | 
      
         | 139 |  |  | /*-----------------------------------------------------------------------------------*/
 | 
      
         | 140 |  |  | void
 | 
      
         | 141 |  |  | uip_arp_init(void)
 | 
      
         | 142 |  |  | {
 | 
      
         | 143 |  |  |   for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
 | 
      
         | 144 |  |  |     memset(arp_table[i].ipaddr, 0, 4);
 | 
      
         | 145 |  |  |   }
 | 
      
         | 146 |  |  | }
 | 
      
         | 147 |  |  | /*-----------------------------------------------------------------------------------*/
 | 
      
         | 148 |  |  | /**
 | 
      
         | 149 |  |  |  * Periodic ARP processing function.
 | 
      
         | 150 |  |  |  *
 | 
      
         | 151 |  |  |  * This function performs periodic timer processing in the ARP module
 | 
      
         | 152 |  |  |  * and should be called at regular intervals. The recommended interval
 | 
      
         | 153 |  |  |  * is 10 seconds between the calls.
 | 
      
         | 154 |  |  |  *
 | 
      
         | 155 |  |  |  */
 | 
      
         | 156 |  |  | /*-----------------------------------------------------------------------------------*/
 | 
      
         | 157 |  |  | void
 | 
      
         | 158 |  |  | uip_arp_timer(void)
 | 
      
         | 159 |  |  | {
 | 
      
         | 160 |  |  |   struct arp_entry *tabptr;
 | 
      
         | 161 |  |  |  
 | 
      
         | 162 |  |  |   ++arptime;
 | 
      
         | 163 |  |  |   for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
 | 
      
         | 164 |  |  |     tabptr = &arp_table[i];
 | 
      
         | 165 |  |  |     if((tabptr->ipaddr[0] | tabptr->ipaddr[1]) != 0 &&
 | 
      
         | 166 |  |  |        arptime - tabptr->time >= UIP_ARP_MAXAGE) {
 | 
      
         | 167 |  |  |       memset(tabptr->ipaddr, 0, 4);
 | 
      
         | 168 |  |  |     }
 | 
      
         | 169 |  |  |   }
 | 
      
         | 170 |  |  |  
 | 
      
         | 171 |  |  | }
 | 
      
         | 172 |  |  | /*-----------------------------------------------------------------------------------*/
 | 
      
         | 173 |  |  | static void
 | 
      
         | 174 |  |  | uip_arp_update(u16_t *ipaddr, struct uip_eth_addr *ethaddr)
 | 
      
         | 175 |  |  | {
 | 
      
         | 176 |  |  |   register struct arp_entry *tabptr;
 | 
      
         | 177 |  |  |   /* Walk through the ARP mapping table and try to find an entry to
 | 
      
         | 178 |  |  |      update. If none is found, the IP -> MAC address mapping is
 | 
      
         | 179 |  |  |      inserted in the ARP table. */
 | 
      
         | 180 |  |  |   for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
 | 
      
         | 181 |  |  |  
 | 
      
         | 182 |  |  |     tabptr = &arp_table[i];
 | 
      
         | 183 |  |  |     /* Only check those entries that are actually in use. */
 | 
      
         | 184 |  |  |     if(tabptr->ipaddr[0] != 0 &&
 | 
      
         | 185 |  |  |        tabptr->ipaddr[1] != 0) {
 | 
      
         | 186 |  |  |  
 | 
      
         | 187 |  |  |       /* Check if the source IP address of the incoming packet matches
 | 
      
         | 188 |  |  |          the IP address in this ARP table entry. */
 | 
      
         | 189 |  |  |       if(ipaddr[0] == tabptr->ipaddr[0] &&
 | 
      
         | 190 |  |  |          ipaddr[1] == tabptr->ipaddr[1]) {
 | 
      
         | 191 |  |  |  
 | 
      
         | 192 |  |  |         /* An old entry found, update this and return. */
 | 
      
         | 193 |  |  |         memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6);
 | 
      
         | 194 |  |  |         tabptr->time = arptime;
 | 
      
         | 195 |  |  |  
 | 
      
         | 196 |  |  |         return;
 | 
      
         | 197 |  |  |       }
 | 
      
         | 198 |  |  |     }
 | 
      
         | 199 |  |  |   }
 | 
      
         | 200 |  |  |  
 | 
      
         | 201 |  |  |   /* If we get here, no existing ARP table entry was found, so we
 | 
      
         | 202 |  |  |      create one. */
 | 
      
         | 203 |  |  |  
 | 
      
         | 204 |  |  |   /* First, we try to find an unused entry in the ARP table. */
 | 
      
         | 205 |  |  |   for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
 | 
      
         | 206 |  |  |     tabptr = &arp_table[i];
 | 
      
         | 207 |  |  |     if(tabptr->ipaddr[0] == 0 &&
 | 
      
         | 208 |  |  |        tabptr->ipaddr[1] == 0) {
 | 
      
         | 209 |  |  |       break;
 | 
      
         | 210 |  |  |     }
 | 
      
         | 211 |  |  |   }
 | 
      
         | 212 |  |  |  
 | 
      
         | 213 |  |  |   /* If no unused entry is found, we try to find the oldest entry and
 | 
      
         | 214 |  |  |      throw it away. */
 | 
      
         | 215 |  |  |   if(i == UIP_ARPTAB_SIZE) {
 | 
      
         | 216 |  |  |     tmpage = 0;
 | 
      
         | 217 |  |  |     c = 0;
 | 
      
         | 218 |  |  |     for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
 | 
      
         | 219 |  |  |       tabptr = &arp_table[i];
 | 
      
         | 220 |  |  |       if(arptime - tabptr->time > tmpage) {
 | 
      
         | 221 |  |  |         tmpage = arptime - tabptr->time;
 | 
      
         | 222 |  |  |         c = i;
 | 
      
         | 223 |  |  |       }
 | 
      
         | 224 |  |  |     }
 | 
      
         | 225 |  |  |     i = c;
 | 
      
         | 226 |  |  |     tabptr = &arp_table[i];
 | 
      
         | 227 |  |  |   }
 | 
      
         | 228 |  |  |  
 | 
      
         | 229 |  |  |   /* Now, i is the ARP table entry which we will fill with the new
 | 
      
         | 230 |  |  |      information. */
 | 
      
         | 231 |  |  |   memcpy(tabptr->ipaddr, ipaddr, 4);
 | 
      
         | 232 |  |  |   memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6);
 | 
      
         | 233 |  |  |   tabptr->time = arptime;
 | 
      
         | 234 |  |  | }
 | 
      
         | 235 |  |  | /*-----------------------------------------------------------------------------------*/
 | 
      
         | 236 |  |  | /**
 | 
      
         | 237 |  |  |  * ARP processing for incoming IP packets
 | 
      
         | 238 |  |  |  *
 | 
      
         | 239 |  |  |  * This function should be called by the device driver when an IP
 | 
      
         | 240 |  |  |  * packet has been received. The function will check if the address is
 | 
      
         | 241 |  |  |  * in the ARP cache, and if so the ARP cache entry will be
 | 
      
         | 242 |  |  |  * refreshed. If no ARP cache entry was found, a new one is created.
 | 
      
         | 243 |  |  |  *
 | 
      
         | 244 |  |  |  * This function expects an IP packet with a prepended Ethernet header
 | 
      
         | 245 |  |  |  * in the uip_buf[] buffer, and the length of the packet in the global
 | 
      
         | 246 |  |  |  * variable uip_len.
 | 
      
         | 247 |  |  |  */
 | 
      
         | 248 |  |  | /*-----------------------------------------------------------------------------------*/
 | 
      
         | 249 |  |  | #if 1
 | 
      
         | 250 |  |  | void
 | 
      
         | 251 |  |  | uip_arp_ipin(void)
 | 
      
         | 252 |  |  | {
 | 
      
         | 253 |  |  |   uip_len -= sizeof(struct uip_eth_hdr);
 | 
      
         | 254 |  |  |  
 | 
      
         | 255 |  |  |   /* Only insert/update an entry if the source IP address of the
 | 
      
         | 256 |  |  |      incoming IP packet comes from a host on the local network. */
 | 
      
         | 257 |  |  |   if((IPBUF->srcipaddr[0] & uip_netmask[0]) !=
 | 
      
         | 258 |  |  |      (uip_hostaddr[0] & uip_netmask[0])) {
 | 
      
         | 259 |  |  |     return;
 | 
      
         | 260 |  |  |   }
 | 
      
         | 261 |  |  |   if((IPBUF->srcipaddr[1] & uip_netmask[1]) !=
 | 
      
         | 262 |  |  |      (uip_hostaddr[1] & uip_netmask[1])) {
 | 
      
         | 263 |  |  |     return;
 | 
      
         | 264 |  |  |   }
 | 
      
         | 265 |  |  |   uip_arp_update(IPBUF->srcipaddr, &(IPBUF->ethhdr.src));
 | 
      
         | 266 |  |  |  
 | 
      
         | 267 |  |  |   return;
 | 
      
         | 268 |  |  | }
 | 
      
         | 269 |  |  | #endif /* 0 */
 | 
      
         | 270 |  |  | /*-----------------------------------------------------------------------------------*/
 | 
      
         | 271 |  |  | /**
 | 
      
         | 272 |  |  |  * ARP processing for incoming ARP packets.
 | 
      
         | 273 |  |  |  *
 | 
      
         | 274 |  |  |  * This function should be called by the device driver when an ARP
 | 
      
         | 275 |  |  |  * packet has been received. The function will act differently
 | 
      
         | 276 |  |  |  * depending on the ARP packet type: if it is a reply for a request
 | 
      
         | 277 |  |  |  * that we previously sent out, the ARP cache will be filled in with
 | 
      
         | 278 |  |  |  * the values from the ARP reply. If the incoming ARP packet is an ARP
 | 
      
         | 279 |  |  |  * request for our IP address, an ARP reply packet is created and put
 | 
      
         | 280 |  |  |  * into the uip_buf[] buffer.
 | 
      
         | 281 |  |  |  *
 | 
      
         | 282 |  |  |  * When the function returns, the value of the global variable uip_len
 | 
      
         | 283 |  |  |  * indicates whether the device driver should send out a packet or
 | 
      
         | 284 |  |  |  * not. If uip_len is zero, no packet should be sent. If uip_len is
 | 
      
         | 285 |  |  |  * non-zero, it contains the length of the outbound packet that is
 | 
      
         | 286 |  |  |  * present in the uip_buf[] buffer.
 | 
      
         | 287 |  |  |  *
 | 
      
         | 288 |  |  |  * This function expects an ARP packet with a prepended Ethernet
 | 
      
         | 289 |  |  |  * header in the uip_buf[] buffer, and the length of the packet in the
 | 
      
         | 290 |  |  |  * global variable uip_len.
 | 
      
         | 291 |  |  |  */
 | 
      
         | 292 |  |  | /*-----------------------------------------------------------------------------------*/
 | 
      
         | 293 |  |  | void
 | 
      
         | 294 |  |  | uip_arp_arpin(void)
 | 
      
         | 295 |  |  | {
 | 
      
         | 296 |  |  |  
 | 
      
         | 297 |  |  |   if(uip_len < sizeof(struct arp_hdr)) {
 | 
      
         | 298 |  |  |     uip_len = 0;
 | 
      
         | 299 |  |  |     return;
 | 
      
         | 300 |  |  |   }
 | 
      
         | 301 |  |  |   uip_len = 0;
 | 
      
         | 302 |  |  |  
 | 
      
         | 303 |  |  |   switch(BUF->opcode) {
 | 
      
         | 304 |  |  |   case HTONS(ARP_REQUEST):
 | 
      
         | 305 |  |  |     /* ARP request. If it asked for our address, we send out a
 | 
      
         | 306 |  |  |        reply. */
 | 
      
         | 307 |  |  |     if(uip_ipaddr_cmp(BUF->dipaddr, uip_hostaddr)) {
 | 
      
         | 308 |  |  |       /* First, we register the one who made the request in our ARP
 | 
      
         | 309 |  |  |          table, since it is likely that we will do more communication
 | 
      
         | 310 |  |  |          with this host in the future. */
 | 
      
         | 311 |  |  |       uip_arp_update(BUF->sipaddr, &BUF->shwaddr);
 | 
      
         | 312 |  |  |  
 | 
      
         | 313 |  |  |       /* The reply opcode is 2. */
 | 
      
         | 314 |  |  |       BUF->opcode = HTONS(2);
 | 
      
         | 315 |  |  |  
 | 
      
         | 316 |  |  |       memcpy(BUF->dhwaddr.addr, BUF->shwaddr.addr, 6);
 | 
      
         | 317 |  |  |       memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6);
 | 
      
         | 318 |  |  |       memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
 | 
      
         | 319 |  |  |       memcpy(BUF->ethhdr.dest.addr, BUF->dhwaddr.addr, 6);
 | 
      
         | 320 |  |  |  
 | 
      
         | 321 |  |  |       BUF->dipaddr[0] = BUF->sipaddr[0];
 | 
      
         | 322 |  |  |       BUF->dipaddr[1] = BUF->sipaddr[1];
 | 
      
         | 323 |  |  |       BUF->sipaddr[0] = uip_hostaddr[0];
 | 
      
         | 324 |  |  |       BUF->sipaddr[1] = uip_hostaddr[1];
 | 
      
         | 325 |  |  |  
 | 
      
         | 326 |  |  |       BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP);
 | 
      
         | 327 |  |  |       uip_len = sizeof(struct arp_hdr);
 | 
      
         | 328 |  |  |     }
 | 
      
         | 329 |  |  |     break;
 | 
      
         | 330 |  |  |   case HTONS(ARP_REPLY):
 | 
      
         | 331 |  |  |     /* ARP reply. We insert or update the ARP table if it was meant
 | 
      
         | 332 |  |  |        for us. */
 | 
      
         | 333 |  |  |     if(uip_ipaddr_cmp(BUF->dipaddr, uip_hostaddr)) {
 | 
      
         | 334 |  |  |       uip_arp_update(BUF->sipaddr, &BUF->shwaddr);
 | 
      
         | 335 |  |  |     }
 | 
      
         | 336 |  |  |     break;
 | 
      
         | 337 |  |  |   }
 | 
      
         | 338 |  |  |  
 | 
      
         | 339 |  |  |   return;
 | 
      
         | 340 |  |  | }
 | 
      
         | 341 |  |  | /*-----------------------------------------------------------------------------------*/
 | 
      
         | 342 |  |  | /**
 | 
      
         | 343 |  |  |  * Prepend Ethernet header to an outbound IP packet and see if we need
 | 
      
         | 344 |  |  |  * to send out an ARP request.
 | 
      
         | 345 |  |  |  *
 | 
      
         | 346 |  |  |  * This function should be called before sending out an IP packet. The
 | 
      
         | 347 |  |  |  * function checks the destination IP address of the IP packet to see
 | 
      
         | 348 |  |  |  * what Ethernet MAC address that should be used as a destination MAC
 | 
      
         | 349 |  |  |  * address on the Ethernet.
 | 
      
         | 350 |  |  |  *
 | 
      
         | 351 |  |  |  * If the destination IP address is in the local network (determined
 | 
      
         | 352 |  |  |  * by logical ANDing of netmask and our IP address), the function
 | 
      
         | 353 |  |  |  * checks the ARP cache to see if an entry for the destination IP
 | 
      
         | 354 |  |  |  * address is found. If so, an Ethernet header is prepended and the
 | 
      
         | 355 |  |  |  * function returns. If no ARP cache entry is found for the
 | 
      
         | 356 |  |  |  * destination IP address, the packet in the uip_buf[] is replaced by
 | 
      
         | 357 |  |  |  * an ARP request packet for the IP address. The IP packet is dropped
 | 
      
         | 358 |  |  |  * and it is assumed that they higher level protocols (e.g., TCP)
 | 
      
         | 359 |  |  |  * eventually will retransmit the dropped packet.
 | 
      
         | 360 |  |  |  *
 | 
      
         | 361 |  |  |  * If the destination IP address is not on the local network, the IP
 | 
      
         | 362 |  |  |  * address of the default router is used instead.
 | 
      
         | 363 |  |  |  *
 | 
      
         | 364 |  |  |  * When the function returns, a packet is present in the uip_buf[]
 | 
      
         | 365 |  |  |  * buffer, and the length of the packet is in the global variable
 | 
      
         | 366 |  |  |  * uip_len.
 | 
      
         | 367 |  |  |  */
 | 
      
         | 368 |  |  | /*-----------------------------------------------------------------------------------*/
 | 
      
         | 369 |  |  | void
 | 
      
         | 370 |  |  | uip_arp_out(void)
 | 
      
         | 371 |  |  | {
 | 
      
         | 372 |  |  |   struct arp_entry *tabptr;
 | 
      
         | 373 |  |  |  
 | 
      
         | 374 |  |  |   /* Find the destination IP address in the ARP table and construct
 | 
      
         | 375 |  |  |      the Ethernet header. If the destination IP addres isn't on the
 | 
      
         | 376 |  |  |      local network, we use the default router's IP address instead.
 | 
      
         | 377 |  |  |  
 | 
      
         | 378 |  |  |      If not ARP table entry is found, we overwrite the original IP
 | 
      
         | 379 |  |  |      packet with an ARP request for the IP address. */
 | 
      
         | 380 |  |  |  
 | 
      
         | 381 |  |  |   /* First check if destination is a local broadcast. */
 | 
      
         | 382 |  |  |   if(uip_ipaddr_cmp(IPBUF->destipaddr, broadcast_ipaddr)) {
 | 
      
         | 383 |  |  |     memcpy(IPBUF->ethhdr.dest.addr, broadcast_ethaddr.addr, 6);
 | 
      
         | 384 |  |  |   } else {
 | 
      
         | 385 |  |  |     /* Check if the destination address is on the local network. */
 | 
      
         | 386 |  |  |     if(!uip_ipaddr_maskcmp(IPBUF->destipaddr, uip_hostaddr, uip_netmask)) {
 | 
      
         | 387 |  |  |       /* Destination address was not on the local network, so we need to
 | 
      
         | 388 |  |  |          use the default router's IP address instead of the destination
 | 
      
         | 389 |  |  |          address when determining the MAC address. */
 | 
      
         | 390 |  |  |       uip_ipaddr_copy(ipaddr, uip_draddr);
 | 
      
         | 391 |  |  |     } else {
 | 
      
         | 392 |  |  |       /* Else, we use the destination IP address. */
 | 
      
         | 393 |  |  |       uip_ipaddr_copy(ipaddr, IPBUF->destipaddr);
 | 
      
         | 394 |  |  |     }
 | 
      
         | 395 |  |  |  
 | 
      
         | 396 |  |  |     for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
 | 
      
         | 397 |  |  |       tabptr = &arp_table[i];
 | 
      
         | 398 |  |  |       if(uip_ipaddr_cmp(ipaddr, tabptr->ipaddr)) {
 | 
      
         | 399 |  |  |         break;
 | 
      
         | 400 |  |  |       }
 | 
      
         | 401 |  |  |     }
 | 
      
         | 402 |  |  |  
 | 
      
         | 403 |  |  |     if(i == UIP_ARPTAB_SIZE) {
 | 
      
         | 404 |  |  |       /* The destination address was not in our ARP table, so we
 | 
      
         | 405 |  |  |          overwrite the IP packet with an ARP request. */
 | 
      
         | 406 |  |  |  
 | 
      
         | 407 |  |  |       memset(BUF->ethhdr.dest.addr, 0xff, 6);
 | 
      
         | 408 |  |  |       memset(BUF->dhwaddr.addr, 0x00, 6);
 | 
      
         | 409 |  |  |       memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
 | 
      
         | 410 |  |  |       memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6);
 | 
      
         | 411 |  |  |  
 | 
      
         | 412 |  |  |       uip_ipaddr_copy(BUF->dipaddr, ipaddr);
 | 
      
         | 413 |  |  |       uip_ipaddr_copy(BUF->sipaddr, uip_hostaddr);
 | 
      
         | 414 |  |  |       BUF->opcode = HTONS(ARP_REQUEST); /* ARP request. */
 | 
      
         | 415 |  |  |       BUF->hwtype = HTONS(ARP_HWTYPE_ETH);
 | 
      
         | 416 |  |  |       BUF->protocol = HTONS(UIP_ETHTYPE_IP);
 | 
      
         | 417 |  |  |       BUF->hwlen = 6;
 | 
      
         | 418 |  |  |       BUF->protolen = 4;
 | 
      
         | 419 |  |  |       BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP);
 | 
      
         | 420 |  |  |  
 | 
      
         | 421 |  |  |       uip_appdata = &uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN];
 | 
      
         | 422 |  |  |  
 | 
      
         | 423 |  |  |       uip_len = sizeof(struct arp_hdr);
 | 
      
         | 424 |  |  |       return;
 | 
      
         | 425 |  |  |     }
 | 
      
         | 426 |  |  |  
 | 
      
         | 427 |  |  |     /* Build an ethernet header. */
 | 
      
         | 428 |  |  |     memcpy(IPBUF->ethhdr.dest.addr, tabptr->ethaddr.addr, 6);
 | 
      
         | 429 |  |  |   }
 | 
      
         | 430 |  |  |   memcpy(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
 | 
      
         | 431 |  |  |  
 | 
      
         | 432 |  |  |   IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP);
 | 
      
         | 433 |  |  |  
 | 
      
         | 434 |  |  |   uip_len += sizeof(struct uip_eth_hdr);
 | 
      
         | 435 |  |  | }
 | 
      
         | 436 |  |  | /*-----------------------------------------------------------------------------------*/
 | 
      
         | 437 |  |  |  
 | 
      
         | 438 |  |  | /** @} */
 | 
      
         | 439 |  |  | /** @} */
 |