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