This source file includes following definitions.
- send_arp_q
- print_arp
- arp_sourceh
- arp_targeth
- arp_sourcep
- arp_targetp
- arp_free
- arp_malloc
- arp_response
- arp_lookup
- arp_destroy
- create_arp
- arp_rcv
- arp_snd
- arp_find
- arp_add
- arp_add_broad
- arp_queue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 #include <linux/types.h>
24 #include <linux/string.h>
25 #include <linux/kernel.h>
26 #include <linux/sched.h>
27
28 #include <linux/socket.h>
29 #include <netinet/in.h>
30 #include <asm/system.h>
31
32 #include "timer.h"
33 #include "ip.h"
34 #include "tcp.h"
35 #include "sock.h"
36 #include "arp.h"
37
38 #undef ARP_DEBUG
39 #ifdef ARP_DEBUG
40 #define PRINTK printk
41 #else
42 #define PRINTK dummy_routine
43 #endif
44
45 static struct arp_table *arp_table[ARP_TABLE_SIZE] ={NULL, };
46 static struct sk_buff *arp_q=NULL;
47
48
49 static void
50 send_arp_q(void)
51 {
52 struct sk_buff *skb;
53 if (arp_q == NULL) return;
54
55 skb = arp_q;
56 do {
57 if (!skb->dev->rebuild_header (skb+1, skb->dev))
58 {
59 if (skb->next == skb)
60 {
61 arp_q = NULL;
62 }
63 else
64 {
65 skb->next->prev = skb->prev;
66 skb->prev->next = skb->next;
67 arp_q = skb->next;
68 }
69 skb->next = NULL;
70 skb->prev = NULL;
71 skb->arp = 1;
72 skb->dev->queue_xmit (skb, skb->dev, 0);
73 if (arp_q == NULL) break;
74 skb = arp_q;
75 continue;
76 }
77 skb=skb->next;
78 } while (skb != arp_q);
79
80 }
81
82 static void
83 print_arp(struct arp *arp)
84 {
85 int i;
86 unsigned long *lptr;
87 unsigned char *ptr;
88 PRINTK ("arp: \n");
89 PRINTK (" hrd = %d\n",net16(arp->hrd));
90 PRINTK (" pro = %d\n",net16(arp->pro));
91 PRINTK (" hlen = %d plen = %d\n",arp->hlen, arp->plen);
92 PRINTK (" op = %d\n", net16(arp->op));
93 ptr = (unsigned char *)(arp+1);
94 PRINTK (" sender haddr = ");
95 for (i = 0; i < arp->hlen; i++)
96 {
97 PRINTK ("0x%02X ",*ptr++);
98 }
99 lptr = (void *)ptr;
100 PRINTK (" send paddr = %X\n",*lptr);
101 lptr ++;
102 ptr = (void *)lptr;
103 PRINTK (" destination haddr = ");
104 for (i = 0; i < arp->hlen; i++)
105 {
106 PRINTK ("0x%02X ",*ptr++);
107 }
108 lptr = (void *)ptr;
109 PRINTK (" destination paddr = %X\n",*lptr);
110 }
111
112 static unsigned char *
113 arp_sourceh(struct arp *arp)
114 {
115 unsigned char *ptr;
116 ptr = (unsigned char *)(arp + 1);
117 return (ptr);
118 }
119
120 static unsigned char *
121 arp_targeth(struct arp *arp)
122 {
123 unsigned char *ptr;
124 ptr = (unsigned char *)(arp + 1);
125 ptr += arp->hlen+4;
126 return (ptr);
127 }
128
129 static unsigned long *
130 arp_sourcep(struct arp *arp)
131 {
132 unsigned long *lptr;
133 unsigned char *ptr;
134 ptr = (unsigned char *)(arp + 1);
135 ptr += arp->hlen;
136 lptr = (unsigned long *)ptr;
137 return (lptr);
138 }
139
140
141 static unsigned long *
142 arp_targetp(struct arp *arp)
143 {
144 unsigned long *lptr;
145 unsigned char *ptr;
146 ptr = (unsigned char *)(arp + 1);
147 ptr += 2*arp->hlen+4;
148 lptr = (unsigned long *)ptr;
149 return (lptr);
150 }
151
152 static void
153 arp_free (void *ptr, unsigned long len)
154 {
155 free_s(ptr, len);
156 }
157
158 static void *
159 arp_malloc (unsigned long amount)
160 {
161 return (malloc (amount));
162 }
163
164 static int
165 arp_response (struct arp *arp1, struct device *dev)
166 {
167 struct arp *arp2;
168 struct sk_buff *skb;
169 int tmp;
170
171
172 skb = arp_malloc (sizeof (*skb) + sizeof (*arp2) +
173 2*arp1->hlen + 2*arp1->plen + dev->hard_header_len);
174 if (skb == NULL) return (1);
175
176 skb->mem_addr = skb;
177 skb->mem_len = sizeof (*skb) + sizeof (*arp2) + 2*arp1->hlen +
178 2*arp1->plen + dev->hard_header_len;
179 skb->len = sizeof (*arp2) + 2*arp1->hlen +
180 2*arp1->plen + dev->hard_header_len;
181
182 tmp = dev->hard_header((unsigned char *)(skb+1), dev,
183 ETHERTYPE_ARP, *arp_sourcep(arp1),
184 *arp_targetp(arp1),skb->len);
185
186 if (tmp < 0) return (1);
187
188 arp2 =(struct arp *) ((unsigned char *)skb+sizeof (*skb) + tmp );
189 memcpy (arp2, arp1, sizeof (*arp2));
190
191
192 *arp_sourcep(arp2) = *arp_targetp(arp1);
193 memcpy(arp_sourceh(arp2), dev->dev_addr, arp1->hlen);
194
195 *arp_targetp(arp2) = *arp_sourcep(arp1);
196 memcpy(arp_targeth(arp2), arp_sourceh(arp1), arp1->hlen);
197
198 arp2->op = NET16(ARP_REPLY);
199 skb->free = 1;
200 skb->arp = 1;
201 skb->sk = NULL;
202 skb->next = NULL;
203 PRINTK (">>");
204 print_arp(arp2);
205
206 dev->queue_xmit (skb, dev, 0);
207 return (0);
208 }
209
210
211
212 static struct arp_table *
213 arp_lookup (unsigned long paddr)
214 {
215 unsigned long hash;
216 struct arp_table *apt;
217 PRINTK ("arp_lookup(paddr=%X)\n", paddr);
218
219 if (my_ip_addr(paddr)) return (NULL);
220 hash = net32(paddr) & (ARP_TABLE_SIZE - 1);
221 cli();
222 for (apt = arp_table[hash]; apt != NULL; apt = apt->next)
223 {
224 if (apt->ip == paddr)
225 {
226 sti();
227 return (apt);
228 }
229 }
230 sti();
231 return (NULL);
232 }
233
234 void
235 arp_destroy(unsigned long paddr)
236 {
237 unsigned long hash;
238 struct arp_table *apt;
239 struct arp_table *lapt;
240 PRINTK ("arp_destroy (paddr=%X)\n",paddr);
241
242 if (my_ip_addr(paddr)) return;
243 hash = net32(paddr) & (ARP_TABLE_SIZE - 1);
244
245 cli();
246
247 if (arp_table[hash] == NULL) return;
248
249
250 if (arp_table[hash]->ip == paddr)
251 {
252 apt = arp_table[hash];
253 arp_table[hash] = arp_table[hash]->next;
254 arp_free (apt, sizeof (*apt));
255 sti();
256 return;
257 }
258
259
260 lapt = arp_table[hash];
261 for (apt = arp_table[hash]->next; apt != NULL; apt = apt->next)
262 {
263 if (apt->ip == paddr)
264 {
265 lapt->next = apt->next;
266 arp_free (apt, sizeof (*apt));
267 sti();
268 return;
269 }
270 }
271 sti();
272 }
273
274
275
276 static struct arp_table *
277 create_arp (unsigned long paddr, unsigned char *addr, int hlen)
278 {
279 struct arp_table *apt;
280 unsigned long hash;
281 apt = arp_malloc (sizeof (*apt));
282 if (apt == NULL) return (NULL);
283
284 hash = net32(paddr) & (ARP_TABLE_SIZE - 1);
285 apt->ip = paddr;
286 apt->hlen =hlen;
287 memcpy (apt->hard, addr, hlen);
288 apt->last_used=timer_seq;
289 cli();
290 apt->next = arp_table[hash];
291 arp_table[hash] = apt;
292 sti();
293 return (apt);
294 }
295
296 int
297 arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
298 {
299 struct arp *arp;
300 struct arp_table *tbl;
301 int ret;
302
303 PRINTK ("<<\n");
304 arp = skb->h.arp;
305 print_arp(arp);
306
307
308 if (arp->hlen != dev->addr_len || dev->type !=NET16( arp->hrd))
309 {
310 free_skb(skb, FREE_READ);
311 return (0);
312 }
313
314
315 if (arp->pro != NET16(ARP_IP_PROT) || arp->plen != 4)
316 {
317 free_skb (skb, FREE_READ);
318 return (0);
319 }
320
321
322 tbl = arp_lookup (*arp_sourcep(arp));
323 if (tbl != NULL)
324 {
325 memcpy (tbl->hard, arp+1, arp->hlen);
326 tbl->hlen = arp->hlen;
327 tbl->last_used = timer_seq;
328 }
329
330 if (!my_ip_addr(*arp_targetp(arp)))
331 {
332 free_skb (skb, FREE_READ);
333 return (0);
334 }
335
336 if (tbl == NULL)
337 create_arp (*arp_sourcep(arp), arp_sourceh(arp), arp->hlen);
338
339
340 send_arp_q();
341
342 if (arp->op != NET16(ARP_REQUEST))
343 {
344 free_skb (skb, FREE_READ);
345 return (0);
346 }
347
348
349 ret = arp_response(arp, dev);
350 free_skb (skb, FREE_READ);
351 return (ret);
352 }
353
354 void
355 arp_snd (unsigned long paddr, struct device *dev, unsigned long saddr)
356 {
357 struct sk_buff *skb;
358 struct arp *arp;
359 struct arp_table *apt;
360 int tmp;
361 PRINTK ("arp_snd (paddr=%X, dev=%X, saddr=%X)\n",paddr, dev, saddr);
362
363
364 apt = create_arp (paddr, NULL, 0);
365 if (apt == NULL) return;
366
367 skb = arp_malloc (sizeof (*arp) + sizeof (*skb) + dev->hard_header_len +
368 2*dev->addr_len+8);
369 if (skb == NULL) return;
370
371 skb->sk = NULL;
372 skb->mem_addr = skb;
373 skb->mem_len = sizeof (*arp) + sizeof (*skb) + dev->hard_header_len +
374 2*dev->addr_len+8;
375 skb->arp = 1;
376 skb->dev = dev;
377 skb->len = sizeof (*arp) + dev->hard_header_len + 2*dev->addr_len+8;
378 skb->next = NULL;
379
380 tmp = dev->hard_header ((unsigned char *)(skb+1), dev,
381 ETHERTYPE_ARP, 0, saddr, skb->len);
382 if (tmp < 0)
383 {
384 arp_free (skb->mem_addr, skb->mem_len);
385 return;
386 }
387
388 arp =(struct arp *) ((unsigned char *)skb+sizeof (*skb) + tmp );
389 arp->hrd = net16(dev->type);
390 arp->pro = NET16(ARP_IP_PROT);
391 arp->hlen = dev->addr_len;
392 arp->plen = 4;
393 arp->op = NET16(ARP_REQUEST);
394 *arp_sourcep(arp) = saddr;
395 *arp_targetp(arp) = paddr;
396 memcpy (arp_sourceh(arp), dev->dev_addr, dev->addr_len);
397 memcpy (arp_targeth(arp), dev->broadcast, dev->addr_len);
398 PRINTK(">>\n");
399 print_arp(arp);
400 dev->queue_xmit (skb, dev, 0);
401 }
402
403 int
404 arp_find(unsigned char *haddr, unsigned long paddr, struct device *dev,
405 unsigned long saddr)
406 {
407 struct arp_table *apt;
408 PRINTK ("arp_find(haddr=%X, paddr=%X, dev=%X, saddr=%X)\n",
409 haddr, paddr, dev, saddr);
410 if (my_ip_addr (paddr))
411 {
412 memcpy (haddr, dev->dev_addr, dev->addr_len);
413 return (0);
414 }
415 apt = arp_lookup (paddr);
416 if (apt != NULL)
417 {
418
419
420
421 if (!before (apt->last_used, timer_seq+ARP_TIMEOUT) &&
422 apt->hlen != 0)
423 {
424 apt->last_used=timer_seq;
425 memcpy (haddr, apt->hard, dev->addr_len);
426 return (0);
427 }
428 }
429
430
431
432 if (apt == NULL || after (timer_seq, apt->last_used+ARP_RES_TIME))
433 arp_snd(paddr,dev,saddr);
434
435
436
437
438 *(unsigned long *)haddr = paddr;
439 return (1);
440 }
441
442 void
443 arp_add (unsigned long addr, unsigned char *haddr, struct device *dev)
444 {
445 struct arp_table *apt;
446
447 apt = arp_lookup (addr);
448 if (apt != NULL)
449 {
450 apt->last_used = timer_seq;
451 memcpy (apt->hard, haddr , dev->addr_len);
452 return;
453 }
454 create_arp (addr, haddr, dev->addr_len);
455 }
456
457 void
458 arp_add_broad (unsigned long addr, struct device *dev)
459 {
460 arp_add (addr, dev->broadcast , dev);
461 }
462
463 void
464 arp_queue(struct sk_buff *skb)
465 {
466 cli();
467 if (arp_q == NULL)
468 {
469 arp_q = skb;
470 skb->next = skb;
471 skb->prev = skb;
472 }
473 else
474 {
475 skb->next = arp_q;
476 skb->prev = arp_q->prev;
477 skb->next->prev = skb;
478 skb->prev->next = skb;
479 }
480 sti();
481 }