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 "dev.h"
43 #include "eth.h"
44 #include "ip.h"
45 #include "route.h"
46 #include "protocol.h"
47 #include "tcp.h"
48 #include "skbuff.h"
49 #include "sock.h"
50 #include "arp.h"
51
52
53 #define ARP_MAX_TRIES 3
54
55
56 static char *unk_print(unsigned char *, int);
57 static char *eth_aprint(unsigned char *, int);
58
59
60 static char *arp_cmds[] = {
61 "0x%04X",
62 "REQUEST",
63 "REPLY",
64 "REVERSE REQUEST",
65 "REVERSE REPLY",
66 NULL
67 };
68 #define ARP_MAX_CMDS (sizeof(arp_cmds) / sizeof(arp_cmds[0]))
69
70 static struct {
71 char *name;
72 char *(*print)(unsigned char *ptr, int len);
73 } arp_types[] = {
74 { "0x%04X", unk_print },
75 { "10 Mbps Ethernet", eth_aprint },
76 { "3 Mbps Ethernet", eth_aprint },
77 { "AX.25", unk_print },
78 { "Pronet", unk_print },
79 { "Chaos", unk_print },
80 { "IEEE 802.2 Ethernet (?)", eth_aprint },
81 { "Arcnet", unk_print },
82 { "AppleTalk", unk_print },
83 { NULL, NULL }
84 };
85 #define ARP_MAX_TYPE (sizeof(arp_types) / sizeof(arp_types[0]))
86
87
88 struct arp_table *arp_tables[ARP_TABLE_SIZE] = {
89 NULL,
90 };
91 struct sk_buff *arp_q = NULL;
92
93
94
95 static char *
96 unk_print(unsigned char *ptr, int len)
97 {
98 static char buff[32];
99 char *bufp = buff;
100 int i;
101
102 for (i = 0; i < len; i++)
103 bufp += sprintf(bufp, "%02X ", (*ptr++ & 0377));
104 return(buff);
105 }
106
107
108
109 static char *
110 eth_aprint(unsigned char *ptr, int len)
111 {
112 if (len != ETH_ALEN) return("");
113 return(eth_print(ptr));
114 }
115
116
117
118 static void
119 arp_print(struct arphdr *arp)
120 {
121 int len, idx;
122 unsigned char *ptr;
123
124 if (inet_debug != DBG_ARP) return;
125
126 printk("ARP: ");
127 if (arp == NULL) {
128 printk("(null)\n");
129 return;
130 }
131
132
133 len = htons(arp->ar_op);
134 if (len < ARP_MAX_CMDS) idx = len;
135 else idx = 0;
136 printk("op ");
137 printk(arp_cmds[idx], len);
138
139
140 len = htons(arp->ar_hrd);
141 if (len < ARP_MAX_TYPE) idx = len;
142 else idx = 0;
143 printk(" hrd = "); printk(arp_types[idx].name, len);
144 printk(" pro = 0x%04X\n", htons(arp->ar_pro));
145 printk(" hlen = %d plen = %d\n", arp->ar_hln, arp->ar_pln);
146
147
148
149
150
151
152
153 ptr = ((unsigned char *) &arp->ar_op) + sizeof(u_short);
154 printk(" sender HA = %s ", arp_types[idx].print(ptr, arp->ar_hln));
155 ptr += arp->ar_hln;
156 printk(" PA = %s\n", in_ntoa(*(unsigned long *) ptr));
157 ptr += arp->ar_pln;
158 printk(" target HA = %s ", arp_types[idx].print(ptr, arp->ar_hln));
159 ptr += arp->ar_hln;
160 printk(" PA = %s\n", in_ntoa(*(unsigned long *) ptr));
161 }
162
163
164
165 static void
166 arp_send_q(void)
167 {
168 struct sk_buff *skb;
169 struct sk_buff *next;
170
171 cli();
172 next = arp_q;
173 arp_q = NULL;
174 sti();
175 while ((skb = next) != NULL) {
176 if (skb->magic != ARP_QUEUE_MAGIC) {
177 printk("ARP: *** Bug: skb with bad magic %X: squashing queue\n",
178 skb->magic);
179 return;
180 }
181
182
183 if (skb->next == NULL
184 #ifdef CONFIG_MAX_16M
185 || ((unsigned long)(skb->next) > 16*1024*1024)
186 #endif
187 ) {
188 printk("ARP: *** Bug: bad skb->next, squashing queue\n");
189 return;
190 }
191
192
193 next = skb->next;
194 if (next != skb) {
195 skb->prev->next = next;
196 next->prev = skb->prev;
197 } else {
198 next = NULL;
199 }
200
201 skb->magic = 0;
202 skb->next = NULL;
203 skb->prev = NULL;
204
205
206 cli();
207 skb->tries--;
208 if (skb->tries == 0) {
209
210
211
212
213
214
215
216
217
218 skb->sk = NULL;
219 kfree_skb(skb, FREE_WRITE);
220
221 sti();
222 continue;
223 }
224
225
226 sti();
227 if (!skb->dev->rebuild_header(skb+1, skb->dev)) {
228
229 skb->next = NULL;
230 skb->prev = NULL;
231 skb->arp = 1;
232 skb->dev->queue_xmit(skb, skb->dev, 0);
233 } else {
234
235 cli();
236 skb->magic = ARP_QUEUE_MAGIC;
237 if (arp_q == NULL) {
238 skb->next = skb;
239 skb->prev = skb;
240 arp_q = skb;
241 } else {
242 skb->next = arp_q;
243 skb->prev = arp_q->prev;
244 arp_q->prev->next = skb;
245 arp_q->prev = skb;
246 }
247 sti();
248 }
249 }
250 }
251
252
253
254 static int
255 arp_response(struct arphdr *arp1, struct device *dev)
256 {
257 struct arphdr *arp2;
258 struct sk_buff *skb;
259 unsigned long src, dst;
260 unsigned char *ptr1, *ptr2;
261 int hlen;
262
263
264 skb = (struct sk_buff *) kmalloc(sizeof(struct sk_buff) +
265 sizeof(struct arphdr) +
266 (2 * arp1->ar_hln) + (2 * arp1->ar_pln) +
267 dev->hard_header_len, GFP_ATOMIC);
268 if (skb == NULL) {
269 printk("ARP: no memory available for ARP REPLY!\n");
270 return(1);
271 }
272
273
274 ptr1 = ((unsigned char *) &arp1->ar_op) + sizeof(u_short);
275 src = *((unsigned long *) (ptr1 + arp1->ar_hln));
276 dst = *((unsigned long *) (ptr1 + (arp1->ar_hln * 2) + arp1->ar_pln));
277
278 skb->lock = 0;
279 skb->mem_addr = skb;
280 skb->len = sizeof(struct arphdr) + (2 * arp1->ar_hln) +
281 (2 * arp1->ar_pln) + dev->hard_header_len;
282 skb->mem_len = sizeof(struct sk_buff) + skb->len;
283 hlen = dev->hard_header((unsigned char *)(skb+1), dev,
284 ETH_P_ARP, src, dst, skb->len);
285 if (hlen < 0) {
286 printk("ARP: cannot create HW frame header for REPLY !\n");
287 return(1);
288 }
289
290
291
292
293
294
295 arp2 = (struct arphdr *) ((unsigned char *) (skb+1) + hlen);
296 ptr2 = ((unsigned char *) &arp2->ar_op) + sizeof(u_short);
297 arp2->ar_hrd = arp1->ar_hrd;
298 arp2->ar_pro = arp1->ar_pro;
299 arp2->ar_hln = arp1->ar_hln;
300 arp2->ar_pln = arp1->ar_pln;
301 arp2->ar_op = htons(ARPOP_REPLY);
302 memcpy(ptr2, dev->dev_addr, arp2->ar_hln);
303 ptr2 += arp2->ar_hln;
304 memcpy(ptr2, ptr1 + (arp1->ar_hln * 2) + arp1->ar_pln, arp2->ar_pln);
305 ptr2 += arp2->ar_pln;
306 memcpy(ptr2, ptr1, arp2->ar_hln);
307 ptr2 += arp2->ar_hln;
308 memcpy(ptr2, ptr1 + arp1->ar_hln, arp2->ar_pln);
309
310 skb->free = 1;
311 skb->arp = 1;
312 skb->sk = NULL;
313 skb->next = NULL;
314
315 DPRINTF((DBG_ARP, ">>"));
316 arp_print(arp2);
317
318
319 dev->queue_xmit(skb, dev, 0);
320 return(0);
321 }
322
323
324
325 static struct arp_table *
326 arp_lookup(unsigned long paddr)
327 {
328 struct arp_table *apt;
329 unsigned long hash;
330
331 DPRINTF((DBG_ARP, "ARP: lookup(%s)\n", in_ntoa(paddr)));
332
333
334 if (chk_addr(paddr) == IS_MYADDR) {
335 printk("ARP: ARPing my own IP address %s !\n", in_ntoa(paddr));
336 return(NULL);
337 }
338
339
340 hash = htonl(paddr) & (ARP_TABLE_SIZE - 1);
341 cli();
342 apt = arp_tables[hash];
343 while(apt != NULL) {
344 if (apt->ip == paddr) {
345 sti();
346 return(apt);
347 }
348 apt = apt->next;
349 }
350 sti();
351 return(NULL);
352 }
353
354
355
356 void
357 arp_destroy(unsigned long paddr)
358 {
359 struct arp_table *apt;
360 struct arp_table **lapt;
361 unsigned long hash;
362
363 DPRINTF((DBG_ARP, "ARP: destroy(%s)\n", in_ntoa(paddr)));
364
365
366 if (chk_addr(paddr) == IS_MYADDR) {
367 DPRINTF((DBG_ARP, "ARP: Destroying my own IP address %s !\n",
368 in_ntoa(paddr)));
369 return;
370 }
371 hash = htonl(paddr) & (ARP_TABLE_SIZE - 1);
372
373 cli();
374 lapt = &arp_tables[hash];
375 while ((apt = *lapt) != NULL) {
376 if (apt->ip == paddr) {
377 *lapt = apt->next;
378 kfree_s(apt, sizeof(struct arp_table));
379 sti();
380 return;
381 }
382 lapt = &apt->next;
383 }
384 sti();
385 }
386
387
388
389 static struct arp_table *
390 arp_create(unsigned long paddr, unsigned char *addr, int hlen, int htype)
391 {
392 struct arp_table *apt;
393 unsigned long hash;
394
395 DPRINTF((DBG_ARP, "ARP: create(%s, ", in_ntoa(paddr)));
396 DPRINTF((DBG_ARP, "%s, ", eth_print(addr)));
397 DPRINTF((DBG_ARP, "%d, %d)\n", hlen, htype));
398
399 apt = (struct arp_table *) kmalloc(sizeof(struct arp_table), GFP_ATOMIC);
400 if (apt == NULL) {
401 printk("ARP: no memory available for new ARP entry!\n");
402 return(NULL);
403 }
404
405
406 hash = htonl(paddr) & (ARP_TABLE_SIZE - 1);
407 apt->ip = paddr;
408 apt->hlen = hlen;
409 apt->htype = htype;
410 apt->flags = (ATF_INUSE | ATF_COM);
411 memcpy(apt->ha, addr, hlen);
412 apt->last_used = jiffies;
413 cli();
414 apt->next = arp_tables[hash];
415 arp_tables[hash] = apt;
416 sti();
417 return(apt);
418 }
419
420
421
422
423
424
425
426
427
428
429
430 int
431 arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
432 {
433 struct arphdr *arp;
434 struct arp_table *tbl;
435 unsigned long src, dst;
436 unsigned char *ptr;
437 int ret;
438
439 DPRINTF((DBG_ARP, "<<\n"));
440 arp = skb->h.arp;
441 arp_print(arp);
442
443
444 if (arp->ar_hln != dev->addr_len || dev->type != NET16(arp->ar_hrd)) {
445 printk("ARP: Bad packet received on device \"%s\" !\n", dev->name);
446 kfree_skb(skb, FREE_READ);
447 return(0);
448 }
449
450
451 if (arp->ar_pro != NET16(ETH_P_IP) || arp->ar_pln != 4) {
452 if (arp->ar_op != NET16(ARPOP_REQUEST))
453 printk("ARP: Non-IP request on device \"%s\" !\n", dev->name);
454 kfree_skb(skb, FREE_READ);
455 return(0);
456 }
457
458
459
460
461
462
463 ptr = ((unsigned char *) &arp->ar_op) + sizeof(u_short);
464 memcpy(&src, ptr + arp->ar_hln, arp->ar_pln);
465 tbl = arp_lookup(src);
466 if (tbl != NULL) {
467 DPRINTF((DBG_ARP, "ARP: udating entry for %s\n", in_ntoa(src)));
468 memcpy(tbl->ha, ptr, arp->ar_hln);
469 tbl->hlen = arp->ar_hln;
470 tbl->flags |= ATF_COM;
471 tbl->last_used = jiffies;
472 } else {
473 memcpy(&dst, ptr + (arp->ar_hln * 2) + arp->ar_pln, arp->ar_pln);
474 if (chk_addr(dst) != IS_MYADDR) {
475 kfree_skb(skb, FREE_READ);
476 return(0);
477 } else {
478 tbl = arp_create(src, ptr, arp->ar_hln, arp->ar_hrd);
479 if (tbl == NULL) {
480 kfree_skb(skb, FREE_READ);
481 return(0);
482 }
483 }
484 }
485
486
487
488
489
490
491 arp_send_q();
492
493
494
495
496
497 if (arp->ar_op != NET16(ARPOP_REQUEST)) {
498 kfree_skb(skb, FREE_READ);
499 return(0);
500 }
501 memcpy(&dst, ptr + (arp->ar_hln * 2) + arp->ar_pln, arp->ar_pln);
502 if (chk_addr(dst) != IS_MYADDR) {
503 DPRINTF((DBG_ARP, "ARP: request was not for me!\n"));
504 kfree_skb(skb, FREE_READ);
505 return(0);
506 }
507
508
509
510
511
512 ret = arp_response(arp, dev);
513 kfree_skb(skb, FREE_READ);
514 return(ret);
515 }
516
517
518
519 void
520 arp_send(unsigned long paddr, struct device *dev, unsigned long saddr)
521 {
522 struct sk_buff *skb;
523 struct arphdr *arp;
524 unsigned char *ptr;
525 int tmp;
526
527 DPRINTF((DBG_ARP, "ARP: send(paddr=%s, ", in_ntoa(paddr)));
528 DPRINTF((DBG_ARP, "dev=%s, ", dev->name));
529 DPRINTF((DBG_ARP, "saddr=%s)\n", in_ntoa(saddr)));
530
531 skb = (struct sk_buff *) kmalloc(sizeof(struct sk_buff) +
532 sizeof(struct arphdr) + (2 * dev->addr_len) +
533 dev->hard_header_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, jiffies+ARP_TIMEOUT) && apt->hlen != 0)) {
607 apt->last_used = jiffies;
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 = jiffies;
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 = jiffies;
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 }