This source file includes following definitions.
- unk_print
- eth_aprint
- arp_print
- arp_send_q
- arp_queue_kick
- arp_queue_ticker
- arp_response
- arp_lookup
- arp_lookup_proxy
- arp_destructor
- arp_destroy
- arp_destroy_maybe
- arp_create
- arp_rcv
- arp_send
- arp_find
- arp_add
- arp_add_broad
- arp_queue
- arp_get_info
- arp_req_set
- arp_req_get
- arp_req_del
- arp_ioctl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57 #include <linux/types.h>
58 #include <linux/string.h>
59 #include <linux/kernel.h>
60 #include <linux/sched.h>
61 #include <linux/config.h>
62 #include <linux/socket.h>
63 #include <linux/sockios.h>
64 #include <linux/timer.h>
65 #include <linux/errno.h>
66 #include <linux/if_arp.h>
67 #include <linux/in.h>
68 #include <asm/system.h>
69 #include <asm/segment.h>
70 #include <stdarg.h>
71 #include "inet.h"
72 #include "dev.h"
73 #include "eth.h"
74 #include "ip.h"
75 #include "route.h"
76 #include "protocol.h"
77 #include "tcp.h"
78 #include "skbuff.h"
79 #include "sock.h"
80 #include "arp.h"
81
82
83 #define ARP_MAX_TRIES 3
84
85
86 static char *unk_print(unsigned char *, int);
87 static char *eth_aprint(unsigned char *, int);
88
89
90 static char *arp_cmds[] = {
91 "0x%04X",
92 "REQUEST",
93 "REPLY",
94 "REVERSE REQUEST",
95 "REVERSE REPLY",
96 NULL
97 };
98 #define ARP_MAX_CMDS (sizeof(arp_cmds) / sizeof(arp_cmds[0]))
99
100 static struct {
101 char *name;
102 char *(*print)(unsigned char *ptr, int len);
103 } arp_types[] = {
104 { "0x%04X", unk_print },
105 { "10 Mbps Ethernet", eth_aprint },
106 { "3 Mbps Ethernet", eth_aprint },
107 { "AX.25", unk_print },
108 { "Pronet", unk_print },
109 { "Chaos", unk_print },
110 { "IEEE 802.2 Ethernet (?)", eth_aprint },
111 { "Arcnet", unk_print },
112 { "AppleTalk", unk_print },
113 { NULL, NULL }
114 };
115 #define ARP_MAX_TYPE (sizeof(arp_types) / sizeof(arp_types[0]))
116
117
118 struct arp_table *arp_tables[ARP_TABLE_SIZE] = {
119 NULL,
120 };
121
122 static int arp_proxies=0;
123
124
125
126 struct sk_buff * volatile arp_q = NULL;
127
128 static struct arp_table *arp_lookup(unsigned long addr);
129 static struct arp_table *arp_lookup_proxy(unsigned long addr);
130
131
132 static char *
133 unk_print(unsigned char *ptr, int len)
134 {
135 static char buff[32];
136 char *bufp = buff;
137 int i;
138
139 for (i = 0; i < len; i++)
140 bufp += sprintf(bufp, "%02X ", (*ptr++ & 0377));
141 return(buff);
142 }
143
144
145
146 static char *
147 eth_aprint(unsigned char *ptr, int len)
148 {
149 if (len != ETH_ALEN) return("");
150 return(eth_print(ptr));
151 }
152
153
154
155 static void
156 arp_print(struct arphdr *arp)
157 {
158 int len, idx;
159 unsigned char *ptr;
160
161 if (inet_debug != DBG_ARP) return;
162
163 printk("ARP: ");
164 if (arp == NULL) {
165 printk("(null)\n");
166 return;
167 }
168
169
170 len = htons(arp->ar_op);
171 if (len < ARP_MAX_CMDS) idx = len;
172 else idx = 0;
173 printk("op ");
174 printk(arp_cmds[idx], len);
175
176
177 len = htons(arp->ar_hrd);
178 if (len < ARP_MAX_TYPE) idx = len;
179 else idx = 0;
180 printk(" hrd = "); printk(arp_types[idx].name, len);
181 printk(" pro = 0x%04X\n", htons(arp->ar_pro));
182 printk(" hlen = %d plen = %d\n", arp->ar_hln, arp->ar_pln);
183
184
185
186
187
188
189
190 ptr = ((unsigned char *) &arp->ar_op) + sizeof(u_short);
191 printk(" sender HA = %s ", arp_types[idx].print(ptr, arp->ar_hln));
192 ptr += arp->ar_hln;
193 printk(" PA = %s\n", in_ntoa(*(unsigned long *) ptr));
194 ptr += arp->ar_pln;
195 printk(" target HA = %s ", arp_types[idx].print(ptr, arp->ar_hln));
196 ptr += arp->ar_hln;
197 printk(" PA = %s\n", in_ntoa(*(unsigned long *) ptr));
198 }
199
200
201
202 static void
203 arp_send_q(void)
204 {
205 struct sk_buff *skb;
206 struct sk_buff *volatile work_q;
207 cli();
208 work_q = arp_q;
209 skb_new_list_head(&work_q);
210 arp_q = NULL;
211 sti();
212 while((skb=skb_dequeue(&work_q))!=NULL)
213 {
214 IS_SKB(skb);
215 skb->magic = 0;
216 skb->next = NULL;
217 skb->prev = NULL;
218
219
220 cli();
221 skb->tries--;
222 if (skb->tries == 0) {
223
224
225
226
227
228
229
230
231
232 skb->sk = NULL;
233 if(skb->free)
234 kfree_skb(skb, FREE_WRITE);
235
236
237 sti();
238 continue;
239 }
240
241
242 sti();
243 if (skb->arp || !skb->dev->rebuild_header(skb->data, skb->dev)) {
244 skb->arp = 1;
245 skb->dev->queue_xmit(skb, skb->dev, 0);
246 } else {
247
248 skb->magic = ARP_QUEUE_MAGIC;
249 skb_queue_head(&arp_q,skb);
250 }
251 }
252 }
253
254
255 static struct timer_list arp_timer;
256
257 static void arp_queue_ticker(unsigned long data);
258
259 static void arp_queue_kick(void)
260 {
261 arp_timer.expires = 500;
262 arp_timer.data = 0;
263 arp_timer.function = arp_queue_ticker;
264 del_timer(&arp_timer);
265 add_timer(&arp_timer);
266 }
267
268 static void arp_queue_ticker(unsigned long data)
269 {
270 arp_send_q();
271 if (skb_peek(&arp_q))
272 arp_queue_kick();
273 }
274
275
276
277
278 static int
279 arp_response(struct arphdr *arp1, struct device *dev, int addrtype)
280 {
281 struct arphdr *arp2;
282 struct sk_buff *skb;
283 unsigned long src, dst;
284 unsigned char *ptr1, *ptr2;
285 int hlen;
286 struct arp_table *apt = NULL;
287
288
289 ptr1 = ((unsigned char *) &arp1->ar_op) + sizeof(u_short);
290 src = *((unsigned long *) (ptr1 + arp1->ar_hln));
291 dst = *((unsigned long *) (ptr1 + (arp1->ar_hln * 2) + arp1->ar_pln));
292
293 if(addrtype!=IS_MYADDR)
294 {
295 apt=arp_lookup_proxy(dst);
296 if(apt==NULL)
297 return(1);
298 }
299
300
301 skb = alloc_skb(sizeof(struct sk_buff) +
302 sizeof(struct arphdr) +
303 (2 * arp1->ar_hln) + (2 * arp1->ar_pln) +
304 dev->hard_header_len, GFP_ATOMIC);
305 if (skb == NULL) {
306 printk("ARP: no memory available for ARP REPLY!\n");
307 return(1);
308 }
309
310 skb->mem_addr = skb;
311 skb->len = sizeof(struct arphdr) + (2 * arp1->ar_hln) +
312 (2 * arp1->ar_pln) + dev->hard_header_len;
313 skb->mem_len = sizeof(struct sk_buff) + skb->len;
314 hlen = dev->hard_header(skb->data, dev, ETH_P_ARP, src, dst, skb->len);
315 if (hlen < 0) {
316 printk("ARP: cannot create HW frame header for REPLY !\n");
317 kfree_skb(skb, FREE_WRITE);
318 return(1);
319 }
320
321
322
323
324
325
326 arp2 = (struct arphdr *) (skb->data + hlen);
327 ptr2 = ((unsigned char *) &arp2->ar_op) + sizeof(u_short);
328 arp2->ar_hrd = arp1->ar_hrd;
329 arp2->ar_pro = arp1->ar_pro;
330 arp2->ar_hln = arp1->ar_hln;
331 arp2->ar_pln = arp1->ar_pln;
332 arp2->ar_op = htons(ARPOP_REPLY);
333 if(addrtype==IS_MYADDR)
334 memcpy(ptr2, dev->dev_addr, arp2->ar_hln);
335 else
336 memcpy(ptr2, apt->ha, arp2->ar_hln);
337 ptr2 += arp2->ar_hln;
338 memcpy(ptr2, ptr1 + (arp1->ar_hln * 2) + arp1->ar_pln, arp2->ar_pln);
339 ptr2 += arp2->ar_pln;
340 memcpy(ptr2, ptr1, arp2->ar_hln);
341 ptr2 += arp2->ar_hln;
342 memcpy(ptr2, ptr1 + arp1->ar_hln, arp2->ar_pln);
343
344 skb->free = 1;
345 skb->arp = 1;
346 skb->sk = NULL;
347 skb->next = NULL;
348
349 DPRINTF((DBG_ARP, ">>"));
350 arp_print(arp2);
351
352
353 dev->queue_xmit(skb, dev, 0);
354 return(0);
355 }
356
357
358
359 static struct arp_table *
360 arp_lookup(unsigned long paddr)
361 {
362 struct arp_table *apt;
363 unsigned long hash;
364
365 DPRINTF((DBG_ARP, "ARP: lookup(%s)\n", in_ntoa(paddr)));
366
367
368 if (chk_addr(paddr) == IS_MYADDR) {
369 printk("ARP: ARPing my own IP address %s !\n", in_ntoa(paddr));
370 return(NULL);
371 }
372
373
374 hash = htonl(paddr) & (ARP_TABLE_SIZE - 1);
375 cli();
376 apt = arp_tables[hash];
377 while(apt != NULL) {
378 if (apt->ip == paddr) {
379 sti();
380 return(apt);
381 }
382 apt = apt->next;
383 }
384 sti();
385 return(NULL);
386 }
387
388
389
390 static struct arp_table *arp_lookup_proxy(unsigned long paddr)
391 {
392 struct arp_table *apt;
393 unsigned long hash;
394
395 DPRINTF((DBG_ARP, "ARP: lookup proxy(%s)\n", in_ntoa(paddr)));
396
397
398 hash = htonl(paddr) & (ARP_TABLE_SIZE - 1);
399 cli();
400 apt = arp_tables[hash];
401 while(apt != NULL) {
402 if (apt->ip == paddr && (apt->flags & ATF_PUBL) ) {
403 sti();
404 return(apt);
405 }
406 apt = apt->next;
407 }
408 sti();
409 return(NULL);
410 }
411
412
413
414 void
415 arp_destructor(unsigned long paddr, int force)
416 {
417 struct arp_table *apt;
418 struct arp_table **lapt;
419 unsigned long hash;
420
421 DPRINTF((DBG_ARP, "ARP: destroy(%s)\n", in_ntoa(paddr)));
422
423
424 if (chk_addr(paddr) == IS_MYADDR) {
425 DPRINTF((DBG_ARP, "ARP: Destroying my own IP address %s !\n",
426 in_ntoa(paddr)));
427 return;
428 }
429 hash = htonl(paddr) & (ARP_TABLE_SIZE - 1);
430
431 cli();
432 lapt = &arp_tables[hash];
433 while ((apt = *lapt) != NULL) {
434 if (apt->ip == paddr) {
435 if((apt->flags&ATF_PERM) && !force)
436 return;
437 *lapt = apt->next;
438 if(apt->flags&ATF_PUBL)
439 arp_proxies--;
440 kfree_s(apt, sizeof(struct arp_table));
441 sti();
442 return;
443 }
444 lapt = &apt->next;
445 }
446 sti();
447 }
448
449
450
451
452
453 void arp_destroy(unsigned long paddr)
454 {
455 arp_destructor(paddr,1);
456 }
457
458
459
460
461
462 void arp_destroy_maybe(unsigned long paddr)
463 {
464 arp_destructor(paddr,0);
465 }
466
467
468 static struct arp_table *
469 arp_create(unsigned long paddr, unsigned char *addr, int hlen, int htype)
470 {
471 struct arp_table *apt;
472 unsigned long hash;
473
474 DPRINTF((DBG_ARP, "ARP: create(%s, ", in_ntoa(paddr)));
475 DPRINTF((DBG_ARP, "%s, ", eth_print(addr)));
476 DPRINTF((DBG_ARP, "%d, %d)\n", hlen, htype));
477
478 apt = (struct arp_table *) kmalloc(sizeof(struct arp_table), GFP_ATOMIC);
479 if (apt == NULL) {
480 printk("ARP: no memory available for new ARP entry!\n");
481 return(NULL);
482 }
483
484
485 hash = htonl(paddr) & (ARP_TABLE_SIZE - 1);
486 apt->ip = paddr;
487 apt->hlen = hlen;
488 apt->htype = htype;
489 apt->flags = (ATF_INUSE | ATF_COM);
490 memcpy(apt->ha, addr, hlen);
491 apt->last_used = jiffies;
492 cli();
493 apt->next = arp_tables[hash];
494 arp_tables[hash] = apt;
495 sti();
496 return(apt);
497 }
498
499
500
501
502
503
504
505
506
507
508
509 int
510 arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
511 {
512 struct arphdr *arp;
513 struct arp_table *tbl;
514 unsigned long src, dst;
515 unsigned char *ptr;
516 int ret;
517 int addr_hint;
518
519 DPRINTF((DBG_ARP, "<<\n"));
520 arp = skb->h.arp;
521 arp_print(arp);
522
523
524 if (arp->ar_hln != dev->addr_len || dev->type != NET16(arp->ar_hrd))
525 {
526 DPRINTF((DBG_ARP,"ARP: Bad packet received on device \"%s\" !\n", dev->name));
527 kfree_skb(skb, FREE_READ);
528 return(0);
529 }
530
531
532 if (((arp->ar_pro != NET16(0x00CC) && dev->type==3) || (arp->ar_pro != NET16(ETH_P_IP) && dev->type!=3) ) || arp->ar_pln != 4)
533 {
534 if (arp->ar_op != NET16(ARPOP_REQUEST))
535 DPRINTF((DBG_ARP,"ARP: Non-IP request on device \"%s\" !\n", dev->name));
536 kfree_skb(skb, FREE_READ);
537 return(0);
538 }
539
540
541
542
543
544
545 ptr = ((unsigned char *) &arp->ar_op) + sizeof(u_short);
546 memcpy(&src, ptr + arp->ar_hln, arp->ar_pln);
547 tbl = arp_lookup(src);
548 if (tbl != NULL) {
549 DPRINTF((DBG_ARP, "ARP: udating entry for %s\n", in_ntoa(src)));
550 memcpy(tbl->ha, ptr, arp->ar_hln);
551 tbl->hlen = arp->ar_hln;
552 tbl->flags |= ATF_COM;
553 tbl->last_used = jiffies;
554 } else {
555 memcpy(&dst, ptr + (arp->ar_hln * 2) + arp->ar_pln, arp->ar_pln);
556 if (chk_addr(dst) != IS_MYADDR && arp_proxies == 0) {
557 kfree_skb(skb, FREE_READ);
558 return(0);
559 } else {
560 tbl = arp_create(src, ptr, arp->ar_hln, arp->ar_hrd);
561 if (tbl == NULL) {
562 kfree_skb(skb, FREE_READ);
563 return(0);
564 }
565 }
566 }
567
568
569
570
571
572
573 arp_send_q();
574
575
576
577
578
579 if (arp->ar_op != NET16(ARPOP_REQUEST)) {
580 kfree_skb(skb, FREE_READ);
581 return(0);
582 }
583
584
585
586
587
588 if(chk_addr(dst)==IS_BROADCAST)
589 {
590 kfree_skb(skb, FREE_READ);
591 return 0;
592 }
593
594 memcpy(&dst, ptr + (arp->ar_hln * 2) + arp->ar_pln, arp->ar_pln);
595 if ((addr_hint=chk_addr(dst)) != IS_MYADDR && arp_proxies==0) {
596 DPRINTF((DBG_ARP, "ARP: request was not for me!\n"));
597 kfree_skb(skb, FREE_READ);
598 return(0);
599 }
600
601
602
603
604
605 ret = arp_response(arp, dev, addr_hint);
606 kfree_skb(skb, FREE_READ);
607 return(ret);
608 }
609
610
611
612 void
613 arp_send(unsigned long paddr, struct device *dev, unsigned long saddr)
614 {
615 struct sk_buff *skb;
616 struct arphdr *arp;
617 unsigned char *ptr;
618 int tmp;
619
620 DPRINTF((DBG_ARP, "ARP: send(paddr=%s, ", in_ntoa(paddr)));
621 DPRINTF((DBG_ARP, "dev=%s, ", dev->name));
622 DPRINTF((DBG_ARP, "saddr=%s)\n", in_ntoa(saddr)));
623
624 skb = alloc_skb(sizeof(struct sk_buff) +
625 sizeof(struct arphdr) + (2 * dev->addr_len) +
626 dev->hard_header_len +
627 (2 * 4 ), GFP_ATOMIC);
628 if (skb == NULL) {
629 printk("ARP: No memory available for REQUEST %s\n", in_ntoa(paddr));
630 return;
631 }
632
633
634 skb->sk = NULL;
635 skb->mem_addr = skb;
636 skb->len = sizeof(struct arphdr) +
637 dev->hard_header_len + (2 * dev->addr_len) + 8;
638 skb->mem_len = sizeof(struct sk_buff) + skb->len;
639 skb->arp = 1;
640 skb->dev = dev;
641 skb->next = NULL;
642 skb->free = 1;
643 tmp = dev->hard_header(skb->data, dev, ETH_P_ARP, 0, saddr, skb->len);
644 if (tmp < 0) {
645 kfree_skb(skb,FREE_WRITE);
646 return;
647 }
648 arp = (struct arphdr *) (skb->data + tmp);
649 arp->ar_hrd = htons(dev->type);
650 if(dev->type!=3)
651 arp->ar_pro = htons(ETH_P_IP);
652 else
653 arp->ar_pro = htons(0xCC);
654 arp->ar_hln = dev->addr_len;
655 arp->ar_pln = 4;
656 arp->ar_op = htons(ARPOP_REQUEST);
657
658 ptr = ((unsigned char *) &arp->ar_op) + sizeof(u_short);
659 memcpy(ptr, dev->dev_addr, arp->ar_hln);
660 ptr += arp->ar_hln;
661 memcpy(ptr, &saddr, arp->ar_pln);
662 ptr += arp->ar_pln;
663
664 memset(ptr,0,arp->ar_hln);
665 ptr += arp->ar_hln;
666 memcpy(ptr, &paddr, arp->ar_pln);
667
668 DPRINTF((DBG_ARP, ">>\n"));
669 arp_print(arp);
670 dev->queue_xmit(skb, dev, 0);
671 }
672
673
674
675 int
676 arp_find(unsigned char *haddr, unsigned long paddr, struct device *dev,
677 unsigned long saddr)
678 {
679 struct arp_table *apt;
680
681 DPRINTF((DBG_ARP, "ARP: find(haddr=%s, ", eth_print(haddr)));
682 DPRINTF((DBG_ARP, "paddr=%s, ", in_ntoa(paddr)));
683 DPRINTF((DBG_ARP, "dev=%s, saddr=%s)\n", dev->name, in_ntoa(saddr)));
684
685 switch(chk_addr(paddr)) {
686 case IS_MYADDR:
687 memcpy(haddr, dev->dev_addr, dev->addr_len);
688 return(0);
689 case IS_BROADCAST:
690 memcpy(haddr, dev->broadcast, dev->addr_len);
691 return(0);
692 }
693
694 apt = arp_lookup(paddr);
695 if (apt != NULL) {
696
697
698
699
700
701 if ((apt->flags & ATF_PERM) ||
702 (apt->last_used < jiffies+ARP_TIMEOUT && apt->hlen != 0)) {
703 apt->last_used = jiffies;
704 memcpy(haddr, apt->ha, dev->addr_len);
705 return(0);
706 } else {
707 DPRINTF((DBG_ARP, "ARP: find: found expired entry for %s\n",
708 in_ntoa(apt->ip)));
709 }
710 }
711
712
713
714
715
716
717 *(unsigned long *)haddr = paddr;
718
719
720 arp_send(paddr, dev, saddr);
721
722 return(1);
723 }
724
725
726
727 void
728 arp_add(unsigned long addr, unsigned char *haddr, struct device *dev)
729 {
730 struct arp_table *apt;
731
732 DPRINTF((DBG_ARP, "ARP: add(%s, ", in_ntoa(addr)));
733 DPRINTF((DBG_ARP, "%s, ", eth_print(haddr)));
734 DPRINTF((DBG_ARP, "%d, %d)\n", dev->hard_header_len, dev->type));
735
736
737 if (addr == 0) {
738 printk("ARP: add: will not add entry for 0.0.0.0 !\n");
739 return;
740 }
741
742
743 apt = arp_lookup(addr);
744 if (apt != NULL) {
745 DPRINTF((DBG_ARP, "ARP: updating entry for %s\n", in_ntoa(addr)));
746 apt->last_used = jiffies;
747 memcpy(apt->ha, haddr , dev->addr_len);
748 return;
749 }
750 arp_create(addr, haddr, dev->addr_len, dev->type);
751 }
752
753
754
755 void
756 arp_add_broad(unsigned long addr, struct device *dev)
757 {
758 struct arp_table *apt;
759
760 arp_add(addr, dev->broadcast, dev);
761 apt = arp_lookup(addr);
762 if (apt != NULL) {
763 apt->flags |= ATF_PERM;
764 }
765 }
766
767
768
769 void
770 arp_queue(struct sk_buff *skb)
771 {
772 cli();
773 skb->tries = ARP_MAX_TRIES;
774
775 if (skb->next != NULL) {
776 sti();
777 printk("ARP: arp_queue skb already on queue magic=%X.\n", skb->magic);
778 return;
779 }
780 if(arp_q==NULL)
781 arp_queue_kick();
782 skb_queue_tail(&arp_q,skb);
783 skb->magic = ARP_QUEUE_MAGIC;
784 sti();
785 }
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803 int
804 arp_get_info(char *buffer)
805 {
806 struct arpreq *req;
807 struct arp_table *apt;
808 int i;
809 char *pos;
810
811
812 pos = buffer;
813 i = 0;
814 for (i = 0; i < ARP_TABLE_SIZE; i++) {
815 cli();
816 apt = arp_tables[i];
817 sti();
818 while (apt != NULL) {
819 if (pos < (buffer + 4000)) {
820 req = (struct arpreq *) pos;
821 memset((char *) req, 0, sizeof(struct arpreq));
822 req->arp_pa.sa_family = AF_INET;
823 memcpy((char *) req->arp_pa.sa_data, (char *) &apt->ip, 4);
824 req->arp_ha.sa_family = apt->htype;
825 memcpy((char *) req->arp_ha.sa_data,
826 (char *) &apt->ha, apt->hlen);
827 req->arp_flags = apt->flags;
828 }
829 pos += sizeof(struct arpreq);
830 cli();
831 apt = apt->next;
832 sti();
833 }
834 }
835 return(pos - buffer);
836 }
837
838
839
840 static int
841 arp_req_set(struct arpreq *req)
842 {
843 struct arpreq r;
844 struct arp_table *apt;
845 struct sockaddr_in *si;
846 int htype, hlen;
847
848
849 memcpy_fromfs(&r, req, sizeof(r));
850 if (r.arp_pa.sa_family != AF_INET) return(-EPFNOSUPPORT);
851
852
853
854
855
856
857 si = (struct sockaddr_in *) &r.arp_pa;
858 switch(r.arp_ha.sa_family) {
859 case 0:
860 case ARPHRD_ETHER:
861 htype = ARPHRD_ETHER;
862 hlen = ETH_ALEN;
863 break;
864 case ARPHRD_AX25:
865 htype = ARPHRD_AX25;
866 hlen = 7;
867 break;
868
869 default:
870 return(-EPFNOSUPPORT);
871 }
872
873
874 if (si->sin_addr.s_addr == 0) {
875 printk("ARP: SETARP: requested PA is 0.0.0.0 !\n");
876 return(-EINVAL);
877 }
878 apt = arp_lookup(si->sin_addr.s_addr);
879 if (apt == NULL) {
880 apt = arp_create(si->sin_addr.s_addr,
881 (unsigned char *) r.arp_ha.sa_data, hlen, htype);
882 if (apt == NULL) return(-ENOMEM);
883 }
884
885
886 memcpy((char *) &apt->ha, (char *) &r.arp_ha.sa_data, hlen);
887 apt->last_used = jiffies;
888 apt->flags = r.arp_flags;
889 if(apt->flags&ATF_PUBL)
890 arp_proxies++;
891
892 return(0);
893 }
894
895
896
897 static int
898 arp_req_get(struct arpreq *req)
899 {
900 struct arpreq r;
901 struct arp_table *apt;
902 struct sockaddr_in *si;
903
904
905 memcpy_fromfs(&r, req, sizeof(r));
906 if (r.arp_pa.sa_family != AF_INET) return(-EPFNOSUPPORT);
907
908
909 si = (struct sockaddr_in *) &r.arp_pa;
910 apt = arp_lookup(si->sin_addr.s_addr);
911 if (apt == NULL) return(-ENXIO);
912
913
914 memcpy((char *) r.arp_ha.sa_data, (char *) &apt->ha, apt->hlen);
915 r.arp_ha.sa_family = apt->htype;
916
917
918 memcpy_tofs(req, &r, sizeof(r));
919 return(0);
920 }
921
922
923
924 static int
925 arp_req_del(struct arpreq *req)
926 {
927 struct arpreq r;
928 struct sockaddr_in *si;
929
930
931 memcpy_fromfs(&r, req, sizeof(r));
932 if (r.arp_pa.sa_family != AF_INET) return(-EPFNOSUPPORT);
933
934 si = (struct sockaddr_in *) &r.arp_pa;
935
936
937
938 if(chk_addr(si->sin_addr.s_addr)==IS_MYADDR)
939 return -EINVAL;
940
941 arp_destroy(si->sin_addr.s_addr);
942
943 return(0);
944 }
945
946
947
948 int
949 arp_ioctl(unsigned int cmd, void *arg)
950 {
951 int err;
952 switch(cmd) {
953 case DDIOCSDBG:
954 return(dbg_ioctl(arg, DBG_ARP));
955 case SIOCDARP:
956 if (!suser()) return(-EPERM);
957 err=verify_area(VERIFY_READ,arg,sizeof(struct arpreq));
958 if(err)
959 return err;
960 return(arp_req_del((struct arpreq *)arg));
961 case SIOCGARP:
962 err=verify_area(VERIFY_WRITE,arg,sizeof(struct arpreq));
963 if(err)
964 return err;
965 return(arp_req_get((struct arpreq *)arg));
966 case SIOCSARP:
967 if (!suser()) return(-EPERM);
968 err=verify_area(VERIFY_READ,arg,sizeof(struct arpreq));
969 if(err)
970 return err;
971 return(arp_req_set((struct arpreq *)arg));
972 default:
973 return(-EINVAL);
974 }
975
976 return(0);
977 }