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+1, 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 static int
255 arp_response(struct arphdr *arp1, struct device *dev, int addrtype)
256 {
257 struct arphdr *arp2;
258 struct sk_buff *skb;
259 unsigned long src, dst;
260 unsigned char *ptr1, *ptr2;
261 int hlen;
262 struct arp_table *apt = NULL;
263
264
265 ptr1 = ((unsigned char *) &arp1->ar_op) + sizeof(u_short);
266 src = *((unsigned long *) (ptr1 + arp1->ar_hln));
267 dst = *((unsigned long *) (ptr1 + (arp1->ar_hln * 2) + arp1->ar_pln));
268
269 if(addrtype!=IS_MYADDR)
270 {
271 apt=arp_lookup_proxy(dst);
272 if(apt==NULL)
273 return(1);
274 }
275
276
277 skb = alloc_skb(sizeof(struct sk_buff) +
278 sizeof(struct arphdr) +
279 (2 * arp1->ar_hln) + (2 * arp1->ar_pln) +
280 dev->hard_header_len, GFP_ATOMIC);
281 if (skb == NULL) {
282 printk("ARP: no memory available for ARP REPLY!\n");
283 return(1);
284 }
285
286 skb->mem_addr = skb;
287 skb->len = sizeof(struct arphdr) + (2 * arp1->ar_hln) +
288 (2 * arp1->ar_pln) + dev->hard_header_len;
289 skb->mem_len = sizeof(struct sk_buff) + skb->len;
290 hlen = dev->hard_header((unsigned char *)(skb+1), dev,
291 ETH_P_ARP, src, dst, skb->len);
292 if (hlen < 0) {
293 printk("ARP: cannot create HW frame header for REPLY !\n");
294 kfree_skb(skb, FREE_WRITE);
295 return(1);
296 }
297
298
299
300
301
302
303 arp2 = (struct arphdr *) ((unsigned char *) (skb+1) + hlen);
304 ptr2 = ((unsigned char *) &arp2->ar_op) + sizeof(u_short);
305 arp2->ar_hrd = arp1->ar_hrd;
306 arp2->ar_pro = arp1->ar_pro;
307 arp2->ar_hln = arp1->ar_hln;
308 arp2->ar_pln = arp1->ar_pln;
309 arp2->ar_op = htons(ARPOP_REPLY);
310 if(addrtype==IS_MYADDR)
311 memcpy(ptr2, dev->dev_addr, arp2->ar_hln);
312 else
313 memcpy(ptr2, apt->ha, arp2->ar_hln);
314 ptr2 += arp2->ar_hln;
315 memcpy(ptr2, ptr1 + (arp1->ar_hln * 2) + arp1->ar_pln, arp2->ar_pln);
316 ptr2 += arp2->ar_pln;
317 memcpy(ptr2, ptr1, arp2->ar_hln);
318 ptr2 += arp2->ar_hln;
319 memcpy(ptr2, ptr1 + arp1->ar_hln, arp2->ar_pln);
320
321 skb->free = 1;
322 skb->arp = 1;
323 skb->sk = NULL;
324 skb->next = NULL;
325
326 DPRINTF((DBG_ARP, ">>"));
327 arp_print(arp2);
328
329
330 dev->queue_xmit(skb, dev, 0);
331 return(0);
332 }
333
334
335
336 static struct arp_table *
337 arp_lookup(unsigned long paddr)
338 {
339 struct arp_table *apt;
340 unsigned long hash;
341
342 DPRINTF((DBG_ARP, "ARP: lookup(%s)\n", in_ntoa(paddr)));
343
344
345 if (chk_addr(paddr) == IS_MYADDR) {
346 printk("ARP: ARPing my own IP address %s !\n", in_ntoa(paddr));
347 return(NULL);
348 }
349
350
351 hash = htonl(paddr) & (ARP_TABLE_SIZE - 1);
352 cli();
353 apt = arp_tables[hash];
354 while(apt != NULL) {
355 if (apt->ip == paddr) {
356 sti();
357 return(apt);
358 }
359 apt = apt->next;
360 }
361 sti();
362 return(NULL);
363 }
364
365
366
367 static struct arp_table *arp_lookup_proxy(unsigned long paddr)
368 {
369 struct arp_table *apt;
370 unsigned long hash;
371
372 DPRINTF((DBG_ARP, "ARP: lookup proxy(%s)\n", in_ntoa(paddr)));
373
374
375 hash = htonl(paddr) & (ARP_TABLE_SIZE - 1);
376 cli();
377 apt = arp_tables[hash];
378 while(apt != NULL) {
379 if (apt->ip == paddr && (apt->flags & ATF_PUBL) ) {
380 sti();
381 return(apt);
382 }
383 apt = apt->next;
384 }
385 sti();
386 return(NULL);
387 }
388
389
390
391 void
392 arp_destructor(unsigned long paddr, int force)
393 {
394 struct arp_table *apt;
395 struct arp_table **lapt;
396 unsigned long hash;
397
398 DPRINTF((DBG_ARP, "ARP: destroy(%s)\n", in_ntoa(paddr)));
399
400
401 if (chk_addr(paddr) == IS_MYADDR) {
402 DPRINTF((DBG_ARP, "ARP: Destroying my own IP address %s !\n",
403 in_ntoa(paddr)));
404 return;
405 }
406 hash = htonl(paddr) & (ARP_TABLE_SIZE - 1);
407
408 cli();
409 lapt = &arp_tables[hash];
410 while ((apt = *lapt) != NULL) {
411 if (apt->ip == paddr) {
412 if((apt->flags&ATF_PERM) && !force)
413 return;
414 *lapt = apt->next;
415 if(apt->flags&ATF_PUBL)
416 arp_proxies--;
417 kfree_s(apt, sizeof(struct arp_table));
418 sti();
419 return;
420 }
421 lapt = &apt->next;
422 }
423 sti();
424 }
425
426
427
428
429
430 void arp_destroy(unsigned long paddr)
431 {
432 arp_destructor(paddr,1);
433 }
434
435
436
437
438
439 void arp_destroy_maybe(unsigned long paddr)
440 {
441 arp_destructor(paddr,0);
442 }
443
444
445 static struct arp_table *
446 arp_create(unsigned long paddr, unsigned char *addr, int hlen, int htype)
447 {
448 struct arp_table *apt;
449 unsigned long hash;
450
451 DPRINTF((DBG_ARP, "ARP: create(%s, ", in_ntoa(paddr)));
452 DPRINTF((DBG_ARP, "%s, ", eth_print(addr)));
453 DPRINTF((DBG_ARP, "%d, %d)\n", hlen, htype));
454
455 apt = (struct arp_table *) kmalloc(sizeof(struct arp_table), GFP_ATOMIC);
456 if (apt == NULL) {
457 printk("ARP: no memory available for new ARP entry!\n");
458 return(NULL);
459 }
460
461
462 hash = htonl(paddr) & (ARP_TABLE_SIZE - 1);
463 apt->ip = paddr;
464 apt->hlen = hlen;
465 apt->htype = htype;
466 apt->flags = (ATF_INUSE | ATF_COM);
467 memcpy(apt->ha, addr, hlen);
468 apt->last_used = jiffies;
469 cli();
470 apt->next = arp_tables[hash];
471 arp_tables[hash] = apt;
472 sti();
473 return(apt);
474 }
475
476
477
478
479
480
481
482
483
484
485
486 int
487 arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
488 {
489 struct arphdr *arp;
490 struct arp_table *tbl;
491 unsigned long src, dst;
492 unsigned char *ptr;
493 int ret;
494 int addr_hint;
495
496 DPRINTF((DBG_ARP, "<<\n"));
497 arp = skb->h.arp;
498 arp_print(arp);
499
500
501 if (arp->ar_hln != dev->addr_len || dev->type != NET16(arp->ar_hrd))
502 {
503 DPRINTF((DBG_ARP,"ARP: Bad packet received on device \"%s\" !\n", dev->name));
504 kfree_skb(skb, FREE_READ);
505 return(0);
506 }
507
508
509 if (((arp->ar_pro != NET16(0x00CC) && dev->type==3) || (arp->ar_pro != NET16(ETH_P_IP) && dev->type!=3) ) || arp->ar_pln != 4)
510 {
511 if (arp->ar_op != NET16(ARPOP_REQUEST))
512 DPRINTF((DBG_ARP,"ARP: Non-IP request on device \"%s\" !\n", dev->name));
513 kfree_skb(skb, FREE_READ);
514 return(0);
515 }
516
517
518
519
520
521
522 ptr = ((unsigned char *) &arp->ar_op) + sizeof(u_short);
523 memcpy(&src, ptr + arp->ar_hln, arp->ar_pln);
524 tbl = arp_lookup(src);
525 if (tbl != NULL) {
526 DPRINTF((DBG_ARP, "ARP: udating entry for %s\n", in_ntoa(src)));
527 memcpy(tbl->ha, ptr, arp->ar_hln);
528 tbl->hlen = arp->ar_hln;
529 tbl->flags |= ATF_COM;
530 tbl->last_used = jiffies;
531 } else {
532 memcpy(&dst, ptr + (arp->ar_hln * 2) + arp->ar_pln, arp->ar_pln);
533 if (chk_addr(dst) != IS_MYADDR) {
534 kfree_skb(skb, FREE_READ);
535 return(0);
536 } else {
537 tbl = arp_create(src, ptr, arp->ar_hln, arp->ar_hrd);
538 if (tbl == NULL) {
539 kfree_skb(skb, FREE_READ);
540 return(0);
541 }
542 }
543 }
544
545
546
547
548
549
550 arp_send_q();
551
552
553
554
555
556 if (arp->ar_op != NET16(ARPOP_REQUEST)) {
557 kfree_skb(skb, FREE_READ);
558 return(0);
559 }
560
561
562
563
564
565 if(chk_addr(dst)==IS_BROADCAST)
566 {
567 kfree_skb(skb, FREE_READ);
568 return 0;
569 }
570
571 memcpy(&dst, ptr + (arp->ar_hln * 2) + arp->ar_pln, arp->ar_pln);
572 if ((addr_hint=chk_addr(dst)) != IS_MYADDR && arp_proxies==0) {
573 DPRINTF((DBG_ARP, "ARP: request was not for me!\n"));
574 kfree_skb(skb, FREE_READ);
575 return(0);
576 }
577
578
579
580
581
582 ret = arp_response(arp, dev, addr_hint);
583 kfree_skb(skb, FREE_READ);
584 return(ret);
585 }
586
587
588
589 void
590 arp_send(unsigned long paddr, struct device *dev, unsigned long saddr)
591 {
592 struct sk_buff *skb;
593 struct arphdr *arp;
594 unsigned char *ptr;
595 int tmp;
596
597 DPRINTF((DBG_ARP, "ARP: send(paddr=%s, ", in_ntoa(paddr)));
598 DPRINTF((DBG_ARP, "dev=%s, ", dev->name));
599 DPRINTF((DBG_ARP, "saddr=%s)\n", in_ntoa(saddr)));
600
601 skb = alloc_skb(sizeof(struct sk_buff) +
602 sizeof(struct arphdr) + (2 * dev->addr_len) +
603 dev->hard_header_len +
604 (2 * 4 ), GFP_ATOMIC);
605 if (skb == NULL) {
606 printk("ARP: No memory available for REQUEST %s\n", in_ntoa(paddr));
607 return;
608 }
609
610
611 skb->sk = NULL;
612 skb->mem_addr = skb;
613 skb->len = sizeof(struct arphdr) +
614 dev->hard_header_len + (2 * dev->addr_len) + 8;
615 skb->mem_len = sizeof(struct sk_buff) + skb->len;
616 skb->arp = 1;
617 skb->dev = dev;
618 skb->next = NULL;
619 skb->free = 1;
620 tmp = dev->hard_header((unsigned char *)(skb+1), dev,
621 ETH_P_ARP, 0, saddr, skb->len);
622 if (tmp < 0) {
623 kfree_skb(skb,FREE_WRITE);
624 return;
625 }
626 arp = (struct arphdr *) ((unsigned char *) (skb+1) + tmp);
627 arp->ar_hrd = htons(dev->type);
628 if(dev->type!=3)
629 arp->ar_pro = htons(ETH_P_IP);
630 else
631 arp->ar_pro = htons(0xCC);
632 arp->ar_hln = dev->addr_len;
633 arp->ar_pln = 4;
634 arp->ar_op = htons(ARPOP_REQUEST);
635
636 ptr = ((unsigned char *) &arp->ar_op) + sizeof(u_short);
637 memcpy(ptr, dev->dev_addr, arp->ar_hln);
638 ptr += arp->ar_hln;
639 memcpy(ptr, &saddr, arp->ar_pln);
640 ptr += arp->ar_pln;
641
642 memset(ptr,0,arp->ar_hln);
643 ptr += arp->ar_hln;
644 memcpy(ptr, &paddr, arp->ar_pln);
645
646 DPRINTF((DBG_ARP, ">>\n"));
647 arp_print(arp);
648 dev->queue_xmit(skb, dev, 0);
649 }
650
651
652
653 int
654 arp_find(unsigned char *haddr, unsigned long paddr, struct device *dev,
655 unsigned long saddr)
656 {
657 struct arp_table *apt;
658
659 DPRINTF((DBG_ARP, "ARP: find(haddr=%s, ", eth_print(haddr)));
660 DPRINTF((DBG_ARP, "paddr=%s, ", in_ntoa(paddr)));
661 DPRINTF((DBG_ARP, "dev=%s, saddr=%s)\n", dev->name, in_ntoa(saddr)));
662
663 switch(chk_addr(paddr)) {
664 case IS_MYADDR:
665 memcpy(haddr, dev->dev_addr, dev->addr_len);
666 return(0);
667 case IS_BROADCAST:
668 memcpy(haddr, dev->broadcast, dev->addr_len);
669 return(0);
670 }
671
672 apt = arp_lookup(paddr);
673 if (apt != NULL) {
674
675
676
677
678
679 if ((apt->flags & ATF_PERM) ||
680 (apt->last_used < jiffies+ARP_TIMEOUT && apt->hlen != 0)) {
681 apt->last_used = jiffies;
682 memcpy(haddr, apt->ha, dev->addr_len);
683 return(0);
684 } else {
685 DPRINTF((DBG_ARP, "ARP: find: found expired entry for %s\n",
686 in_ntoa(apt->ip)));
687 }
688 }
689
690
691
692
693
694
695 *(unsigned long *)haddr = paddr;
696
697
698 arp_send(paddr, dev, saddr);
699
700 return(1);
701 }
702
703
704
705 void
706 arp_add(unsigned long addr, unsigned char *haddr, struct device *dev)
707 {
708 struct arp_table *apt;
709
710 DPRINTF((DBG_ARP, "ARP: add(%s, ", in_ntoa(addr)));
711 DPRINTF((DBG_ARP, "%s, ", eth_print(haddr)));
712 DPRINTF((DBG_ARP, "%d, %d)\n", dev->hard_header_len, dev->type));
713
714
715 if (addr == 0) {
716 printk("ARP: add: will not add entry for 0.0.0.0 !\n");
717 return;
718 }
719
720
721 apt = arp_lookup(addr);
722 if (apt != NULL) {
723 DPRINTF((DBG_ARP, "ARP: updating entry for %s\n", in_ntoa(addr)));
724 apt->last_used = jiffies;
725 memcpy(apt->ha, haddr , dev->addr_len);
726 return;
727 }
728 arp_create(addr, haddr, dev->addr_len, dev->type);
729 }
730
731
732
733 void
734 arp_add_broad(unsigned long addr, struct device *dev)
735 {
736 struct arp_table *apt;
737
738 arp_add(addr, dev->broadcast, dev);
739 apt = arp_lookup(addr);
740 if (apt != NULL) {
741 apt->flags |= ATF_PERM;
742 }
743 }
744
745
746
747 void
748 arp_queue(struct sk_buff *skb)
749 {
750 cli();
751 skb->tries = ARP_MAX_TRIES;
752
753 if (skb->next != NULL) {
754 sti();
755 printk("ARP: arp_queue skb already on queue magic=%X.\n", skb->magic);
756 return;
757 }
758 skb_queue_tail(&arp_q,skb);
759 skb->magic = ARP_QUEUE_MAGIC;
760 sti();
761 }
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779 int
780 arp_get_info(char *buffer)
781 {
782 struct arpreq *req;
783 struct arp_table *apt;
784 int i;
785 char *pos;
786
787
788 pos = buffer;
789 i = 0;
790 for (i = 0; i < ARP_TABLE_SIZE; i++) {
791 cli();
792 apt = arp_tables[i];
793 sti();
794 while (apt != NULL) {
795 if (pos < (buffer + 4000)) {
796 req = (struct arpreq *) pos;
797 memset((char *) req, 0, sizeof(struct arpreq));
798 req->arp_pa.sa_family = AF_INET;
799 memcpy((char *) req->arp_pa.sa_data, (char *) &apt->ip, 4);
800 req->arp_ha.sa_family = apt->htype;
801 memcpy((char *) req->arp_ha.sa_data,
802 (char *) &apt->ha, apt->hlen);
803 }
804 pos += sizeof(struct arpreq);
805 cli();
806 apt = apt->next;
807 sti();
808 }
809 }
810 return(pos - buffer);
811 }
812
813
814
815 static int
816 arp_req_set(struct arpreq *req)
817 {
818 struct arpreq r;
819 struct arp_table *apt;
820 struct sockaddr_in *si;
821 int htype, hlen;
822
823
824 memcpy_fromfs(&r, req, sizeof(r));
825 if (r.arp_pa.sa_family != AF_INET) return(-EPFNOSUPPORT);
826
827
828
829
830
831
832 si = (struct sockaddr_in *) &r.arp_pa;
833 switch(r.arp_ha.sa_family) {
834 case 0:
835 case ARPHRD_ETHER:
836 htype = ARPHRD_ETHER;
837 hlen = ETH_ALEN;
838 break;
839 case ARPHRD_AX25:
840 htype = ARPHRD_AX25;
841 hlen = 7;
842 break;
843
844 default:
845 return(-EPFNOSUPPORT);
846 }
847
848
849 if (si->sin_addr.s_addr == 0) {
850 printk("ARP: SETARP: requested PA is 0.0.0.0 !\n");
851 return(-EINVAL);
852 }
853 apt = arp_lookup(si->sin_addr.s_addr);
854 if (apt == NULL) {
855 apt = arp_create(si->sin_addr.s_addr,
856 (unsigned char *) r.arp_ha.sa_data, hlen, htype);
857 if (apt == NULL) return(-ENOMEM);
858 }
859
860
861 memcpy((char *) &apt->ha, (char *) &r.arp_ha.sa_data, hlen);
862 apt->last_used = jiffies;
863 apt->flags = r.arp_flags;
864 if(apt->flags&ATF_PUBL)
865 arp_proxies++;
866
867 return(0);
868 }
869
870
871
872 static int
873 arp_req_get(struct arpreq *req)
874 {
875 struct arpreq r;
876 struct arp_table *apt;
877 struct sockaddr_in *si;
878
879
880 memcpy_fromfs(&r, req, sizeof(r));
881 if (r.arp_pa.sa_family != AF_INET) return(-EPFNOSUPPORT);
882
883
884 si = (struct sockaddr_in *) &r.arp_pa;
885 apt = arp_lookup(si->sin_addr.s_addr);
886 if (apt == NULL) return(-ENXIO);
887
888
889 memcpy((char *) r.arp_ha.sa_data, (char *) &apt->ha, apt->hlen);
890 r.arp_ha.sa_family = apt->htype;
891
892
893 memcpy_tofs(req, &r, sizeof(r));
894 return(0);
895 }
896
897
898
899 static int
900 arp_req_del(struct arpreq *req)
901 {
902 struct arpreq r;
903 struct sockaddr_in *si;
904
905
906 memcpy_fromfs(&r, req, sizeof(r));
907 if (r.arp_pa.sa_family != AF_INET) return(-EPFNOSUPPORT);
908
909 si = (struct sockaddr_in *) &r.arp_pa;
910
911
912
913 if(chk_addr(si->sin_addr.s_addr)==IS_MYADDR)
914 return -EINVAL;
915
916 arp_destroy(si->sin_addr.s_addr);
917
918 return(0);
919 }
920
921
922
923 int
924 arp_ioctl(unsigned int cmd, void *arg)
925 {
926 int err;
927 switch(cmd) {
928 case DDIOCSDBG:
929 return(dbg_ioctl(arg, DBG_ARP));
930 case SIOCDARP:
931 if (!suser()) return(-EPERM);
932 err=verify_area(VERIFY_READ,arg,sizeof(struct arpreq));
933 if(err)
934 return err;
935 return(arp_req_del((struct arpreq *)arg));
936 case SIOCGARP:
937 err=verify_area(VERIFY_WRITE,arg,sizeof(struct arpreq));
938 if(err)
939 return err;
940 return(arp_req_get((struct arpreq *)arg));
941 case SIOCSARP:
942 if (!suser()) return(-EPERM);
943 err=verify_area(VERIFY_READ,arg,sizeof(struct arpreq));
944 if(err)
945 return err;
946 return(arp_req_set((struct arpreq *)arg));
947 default:
948 return(-EINVAL);
949 }
950
951 return(0);
952 }