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