UbixOS V2  2.0
arp.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2001, Swedish Institute of Computer Science.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the lwIP TCP/IP stack.
30  *
31  * Author: Adam Dunkels <adam@sics.se>
32  *
33  * $Id: arp.c 54 2016-01-11 01:29:55Z reddawg $
34  *
35  */
36 
37 #include <sys/types.h>
38 #include <lib/kprintf.h>
39 
40 #include "net/debug.h"
41 #include "net/ipv4/inet.h"
42 #include "netif/arp.h"
43 #include "net/ipv4/ip.h"
44 
45 
46 #define ARP_MAXAGE 2 /* 120 * 10 seconds = 20 minutes. */
47 
48 #define HWTYPE_ETHERNET 1
49 
50 #define ARP_REQUEST 1
51 #define ARP_REPLY 2
52 
53 /* MUST be compiled with "pack structs" or equivalent! */
55 struct arp_hdr {
56  PACK_STRUCT_FIELD(struct eth_hdr ethhdr);
57  PACK_STRUCT_FIELD(uInt16 hwtype);
59  PACK_STRUCT_FIELD(uInt16 _hwlen_protolen);
60  PACK_STRUCT_FIELD(uInt16 opcode);
61  PACK_STRUCT_FIELD(struct eth_addr shwaddr);
62  PACK_STRUCT_FIELD(struct ip_addr sipaddr);
63  PACK_STRUCT_FIELD(struct eth_addr dhwaddr);
64  PACK_STRUCT_FIELD(struct ip_addr dipaddr);
67 
68 #define ARPH_HWLEN(hdr) (NTOHS((hdr)->_hwlen_protolen) >> 8)
69 #define ARPH_PROTOLEN(hdr) (NTOHS((hdr)->_hwlen_protolen) & 0xff)
70 
71 
72 #define ARPH_HWLEN_SET(hdr, len) (hdr)->_hwlen_protolen = HTONS(ARPH_PROTOLEN(hdr) | ((len) << 8))
73 #define ARPH_PROTOLEN_SET(hdr, len) (hdr)->_hwlen_protolen = HTONS((len) | (ARPH_HWLEN(hdr) << 8))
74 
76 struct ethip_hdr {
77  PACK_STRUCT_FIELD(struct eth_hdr eth);
78  PACK_STRUCT_FIELD(struct ip_hdr ip);
79 };
81 
82 struct arp_entry {
83  struct ip_addr ipaddr;
84  struct eth_addr ethaddr;
86 };
87 
88 static struct arp_entry arp_table[ARP_TABLE_SIZE];
89 static uInt8 ctime;
90 
91 /*-----------------------------------------------------------------------------------*/
92 void
93 arp_init(void)
94 {
95  uInt8 i;
96 
97  for(i = 0; i < ARP_TABLE_SIZE; ++i) {
98  ip_addr_set(&(arp_table[i].ipaddr),
99  IP_ADDR_ANY);
100  }
101 }
102 /*-----------------------------------------------------------------------------------*/
103 void
104 arp_tmr(void)
105 {
106  uInt8 i;
107 
108  ++ctime;
109  for(i = 0; i < ARP_TABLE_SIZE; ++i) {
110  if(!ip_addr_isany(&arp_table[i].ipaddr) &&
111  ctime - arp_table[i].ctime >= ARP_MAXAGE) {
112  DEBUGF(ARP_DEBUG, ("arp_timer: expired entry %d.\n", i));
113  ip_addr_set(&(arp_table[i].ipaddr),
114  IP_ADDR_ANY);
115  }
116  }
117 }
118 /*-----------------------------------------------------------------------------------*/
119 static void
120 add_arp_entry(struct ip_addr *ipaddr, struct eth_addr *ethaddr)
121 {
122  uInt8 i, j, k;
123  uInt8 maxtime;
124 
125  /* Walk through the ARP mapping table and try to find an entry to
126  update. If none is found, the IP -> MAC address mapping is
127  inserted in the ARP table. */
128  for(i = 0; i < ARP_TABLE_SIZE; ++i) {
129 
130  /* Only check those entries that are actually in use. */
131  if(!ip_addr_isany(&arp_table[i].ipaddr)) {
132  /* Check if the source IP address of the incoming packet matches
133  the IP address in this ARP table entry. */
134  if(ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
135  /* An old entry found, update this and return. */
136  for(k = 0; k < 6; ++k) {
137  arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
138  }
139  arp_table[i].ctime = ctime;
140  return;
141  }
142  }
143  }
144 
145  /* If we get here, no existing ARP table entry was found, so we
146  create one. */
147 
148  /* First, we try to find an unused entry in the ARP table. */
149  for(i = 0; i < ARP_TABLE_SIZE; ++i) {
150  if(ip_addr_isany(&arp_table[i].ipaddr)) {
151  break;
152  }
153  }
154 
155  /* If no unused entry is found, we try to find the oldest entry and
156  throw it away. */
157  if(i == ARP_TABLE_SIZE) {
158  maxtime = 0;
159  j = 0;
160  for(i = 0; i < ARP_TABLE_SIZE; ++i) {
161  if(ctime - arp_table[i].ctime > maxtime) {
162  maxtime = ctime - arp_table[i].ctime;
163  j = i;
164  }
165  }
166  i = j;
167  }
168 
169  /* Now, i is the ARP table entry which we will fill with the new
170  information. */
171  ip_addr_set(&arp_table[i].ipaddr, ipaddr);
172  for(k = 0; k < 6; ++k) {
173  arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
174  }
175  arp_table[i].ctime = ctime;
176  return;
177 
178 }
179 /*-----------------------------------------------------------------------------------*/
180 void
181 arp_ip_input(struct netif *netif, struct pbuf *p)
182 {
183  struct ethip_hdr *hdr;
184 
185  hdr = p->payload;
186 
187  /* Only insert/update an entry if the source IP address of the
188  incoming IP packet comes from a host on the local network. */
189  if(!ip_addr_maskcmp(&(hdr->ip.src), &(netif->ip_addr), &(netif->netmask))) {
190  return;
191  }
192  DEBUGF(ARP_DEBUG, ("arp_ip_input: updating ARP table.\n"));
193  add_arp_entry(&(hdr->ip.src), &(hdr->eth.src));
194 }
195 /*-----------------------------------------------------------------------------------*/
196 struct pbuf *
197 arp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
198 {
199  struct arp_hdr *hdr;
200  uInt8 i;
201 
202  if(p->tot_len < sizeof(struct arp_hdr)) {
203  kprintf("arp_arp_input: packet too short (%d/%d)\n", p->tot_len, sizeof(struct arp_hdr));
204  pbuf_free(p);
205  return NULL;
206  }
207 
208  hdr = p->payload;
209 
210  //kprintf("HDR->OPCODE: [0x%X]\n", hdr->opcode);
211 
212  switch(htons(hdr->opcode)) {
213  case ARP_REQUEST:
214  // kprintf("ARP_REQUEST");
215 //ip_addr_debug_print(&hdr->dipaddr);
216 //ip_addr_debug_print(&netif->ip_addr);
217  /* ARP request. If it asked for our address, we send out a
218  reply. */
219  if(ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr))) {
220 //kprintf("MATCHED!\n");
221  hdr->opcode = htons(ARP_REPLY);
222 
223  ip_addr_set(&(hdr->dipaddr), &(hdr->sipaddr));
224  ip_addr_set(&(hdr->sipaddr), &(netif->ip_addr));
225 
226  for(i = 0; i < 6; ++i) {
227  hdr->dhwaddr.addr[i] = hdr->shwaddr.addr[i];
228  hdr->shwaddr.addr[i] = ethaddr->addr[i];
229  hdr->ethhdr.dest.addr[i] = hdr->dhwaddr.addr[i];
230  hdr->ethhdr.src.addr[i] = ethaddr->addr[i];
231  }
232 
233  hdr->hwtype = htons(HWTYPE_ETHERNET);
234  ARPH_HWLEN_SET(hdr, 6);
235 
236  hdr->proto = htons(ETHTYPE_IP);
237  ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));
238 
239  hdr->ethhdr.type = htons(ETHTYPE_ARP);
240  return p;
241  }
242  break;
243  case ARP_REPLY:
244  kprintf("ARP_RREPLY");
245  /* ARP reply. We insert or update the ARP table. */
246  if(ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr))) {
247  add_arp_entry(&(hdr->sipaddr), &(hdr->shwaddr));
248  }
249  break;
250  default:
251  kprintf("arp_arp_input: unknown type %d\n", htons(hdr->opcode));
252  break;
253  }
254 
255  pbuf_free(p);
256  return NULL;
257 }
258 /*-----------------------------------------------------------------------------------*/
259 struct eth_addr *
260 arp_lookup(struct ip_addr *ipaddr)
261 {
262  uInt8 i;
263 
264  for(i = 0; i < ARP_TABLE_SIZE; ++i) {
265  if(ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
266  return &arp_table[i].ethaddr;
267  }
268  }
269  return NULL;
270 }
271 /*-----------------------------------------------------------------------------------*/
272 struct pbuf *
273 arp_query(struct netif *netif, struct eth_addr *ethaddr, struct ip_addr *ipaddr)
274 {
275  struct arp_hdr *hdr;
276  struct pbuf *p;
277  uInt8 i;
278 
279  p = pbuf_alloc(PBUF_LINK, sizeof(struct arp_hdr), PBUF_RAM);
280  if(p == NULL) {
281  return NULL;
282  }
283 
284  hdr = p->payload;
285 
286  hdr->opcode = htons(ARP_REQUEST);
287 
288  for(i = 0; i < 6; ++i) {
289  hdr->dhwaddr.addr[i] = 0x00;
290  hdr->shwaddr.addr[i] = ethaddr->addr[i];
291  }
292 
293  ip_addr_set(&(hdr->dipaddr), ipaddr);
294  ip_addr_set(&(hdr->sipaddr), &(netif->ip_addr));
295 
296  hdr->hwtype = htons(HWTYPE_ETHERNET);
297  ARPH_HWLEN_SET(hdr, 6);
298 
299  hdr->proto = htons(ETHTYPE_IP);
300  ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));
301 
302  for(i = 0; i < 6; ++i) {
303  hdr->ethhdr.dest.addr[i] = 0xff;
304  hdr->ethhdr.src.addr[i] = ethaddr->addr[i];
305  }
306 
307  hdr->ethhdr.type = htons(ETHTYPE_ARP);
308  return p;
309 }
310 /*-----------------------------------------------------------------------------------*/
311 
312 
313 
314 
ip_addr_cmp
#define ip_addr_cmp(addr1, addr2)
Definition: ip_addr.h:316
PBUF_LINK
Definition: pbuf.h:85
htons
#define htons(x)
Definition: def.h:108
arp_hdr::PACK_STRUCT_FIELD
PACK_STRUCT_FIELD(struct eth_hdr ethhdr)
uInt16
unsigned short int uInt16
Definition: objgfx30.h:48
ip_addr_set
#define ip_addr_set(dest, src)
Definition: ip_addr.h:307
arp_tmr
void arp_tmr(void)
Definition: arp.c:104
ip_addr_isany
#define ip_addr_isany(ipaddr)
Definition: ip_addr.h:317
pbuf::tot_len
u16_t tot_len
Definition: pbuf.h:156
ARP_REQUEST
#define ARP_REQUEST
Definition: arp.c:50
ARPH_PROTOLEN_SET
#define ARPH_PROTOLEN_SET(hdr, len)
Definition: arp.c:73
ARP_MAXAGE
#define ARP_MAXAGE
Definition: arp.c:46
pbuf_free
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:715
types.h
arp_entry::ipaddr
struct ip_addr ipaddr
Definition: arp.c:83
ARPH_HWLEN_SET
#define ARPH_HWLEN_SET(hdr, len)
Definition: arp.c:72
ip_hdr
Definition: ip4.h:71
pbuf_alloc
struct pbuf * pbuf_alloc(pbuf_layer l, u16_t length, pbuf_type type)
Definition: pbuf.c:248
kprintf.h
uInt8
unsigned char uInt8
Definition: objgfx30.h:47
PACK_STRUCT_BEGIN
#define PACK_STRUCT_BEGIN
Definition: cc.h:8
eth_hdr
Definition: ethernet.h:71
netif
Definition: netif.h:233
arp_entry::ethaddr
struct eth_addr ethaddr
Definition: arp.c:84
arp_lookup
struct eth_addr * arp_lookup(struct ip_addr *ipaddr)
Definition: arp.c:260
arp_entry
Definition: arp.c:82
HWTYPE_ETHERNET
#define HWTYPE_ETHERNET
Definition: arp.c:48
PBUF_RAM
Definition: pbuf.h:108
ethip_hdr
Definition: arp.c:76
ARP_REPLY
#define ARP_REPLY
Definition: arp.c:51
eth_addr
Definition: ethernet.h:58
arp_query
struct pbuf * arp_query(struct netif *netif, struct eth_addr *ethaddr, struct ip_addr *ipaddr)
Definition: arp.c:273
ethip_hdr::PACK_STRUCT_FIELD
PACK_STRUCT_FIELD(struct eth_hdr eth)
arp_init
void arp_init(void)
Definition: arp.c:93
ETHTYPE_IP
Definition: ethernet.h:110
ARP_TABLE_SIZE
#define ARP_TABLE_SIZE
Definition: lwipopts.h:91
arp_arp_input
struct pbuf * arp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
Definition: arp.c:197
arp_ip_input
void arp_ip_input(struct netif *netif, struct pbuf *p)
Definition: arp.c:181
arp_entry::ctime
uInt8 ctime
Definition: arp.c:85
kprintf
int kprintf(const char *,...)
Definition: kprintf.c:259
pbuf
Definition: pbuf.h:142
ETHTYPE_ARP
Definition: ethernet.h:112
arp_hdr
Definition: arp.c:55
PACK_STRUCT_STRUCT
PACK_STRUCT_BEGIN struct arp_hdr PACK_STRUCT_STRUCT
debug.h
pbuf::payload
void * payload
Definition: pbuf.h:147
PACK_STRUCT_END
#define PACK_STRUCT_END
Definition: cc.h:9
NULL
#define NULL
Definition: fat_string.h:17