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