OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [Common/] [ethernet/] [uIP/] [uip-1.0/] [uip/] [uip_arp.c] - Blame information for rev 637

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
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
/** @} */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.