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

Committer:
frank26080115
Date:
Sun Mar 20 05:38:56 2011 +0000
Revision:
0:bf7b9fba3924

        

Who changed what in which revision?

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