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_table[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 = kmalloc(sizeof(struct sk_buff) + 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_table[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_table[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 = 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 = timer_seq;
413 cli();
414 apt->next = arp_table[hash];
415 arp_table[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 = timer_seq;
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 = kmalloc(sizeof(struct sk_buff) + sizeof(struct arphdr) +
532 (2 * dev->addr_len) + (2 * 4 ), GFP_ATOMIC);
533 if (skb == NULL) {
534 printk("ARP: No memory available for REQUEST %s\n", in_ntoa(paddr));
535 return;
536 }
537
538
539 skb->lock = 0;
540 skb->sk = NULL;
541 skb->mem_addr = skb;
542 skb->len = sizeof(struct arphdr) +
543 dev->hard_header_len + (2 * dev->addr_len) + 8;
544 skb->mem_len = sizeof(struct sk_buff) + skb->len;
545 skb->arp = 1;
546 skb->dev = dev;
547 skb->next = NULL;
548 tmp = dev->hard_header((unsigned char *)(skb+1), dev,
549 ETH_P_ARP, 0, saddr, skb->len);
550 if (tmp < 0) {
551 kfree_s(skb->mem_addr, skb->mem_len);
552 return;
553 }
554 arp = (struct arphdr *) ((unsigned char *) (skb+1) + tmp);
555 arp->ar_hrd = htons(dev->type);
556 arp->ar_pro = htons(ETH_P_IP);
557 arp->ar_hln = dev->addr_len;
558 arp->ar_pln = 4;
559 arp->ar_op = htons(ARPOP_REQUEST);
560
561 ptr = ((unsigned char *) &arp->ar_op) + sizeof(u_short);
562 memcpy(ptr, dev->dev_addr, arp->ar_hln);
563 ptr += arp->ar_hln;
564 memcpy(ptr, &saddr, arp->ar_pln);
565 ptr += arp->ar_pln;
566 memcpy(ptr, dev->broadcast, arp->ar_hln);
567 ptr += arp->ar_hln;
568 memcpy(ptr, &paddr, arp->ar_pln);
569
570 DPRINTF((DBG_ARP, ">>\n"));
571 arp_print(arp);
572 dev->queue_xmit(skb, dev, 0);
573 }
574
575
576
577 int
578 arp_find(unsigned char *haddr, unsigned long paddr, struct device *dev,
579 unsigned long saddr)
580 {
581 struct arp_table *apt;
582
583 DPRINTF((DBG_ARP, "ARP: find(haddr=%s, ", eth_print(haddr)));
584 DPRINTF((DBG_ARP, "paddr=%s, ", in_ntoa(paddr)));
585 DPRINTF((DBG_ARP, "dev=%s, saddr=%s)\n", dev->name, in_ntoa(saddr)));
586
587 switch(chk_addr(paddr)) {
588 case IS_MYADDR:
589 memcpy(haddr, dev->dev_addr, dev->addr_len);
590 return(0);
591 case IS_BROADCAST:
592 memcpy(haddr, dev->broadcast, dev->addr_len);
593 return(0);
594 }
595
596 apt = arp_lookup(paddr);
597 if (apt != NULL) {
598
599
600
601
602
603 if ((!(apt->flags & ATF_PERM)) ||
604 (!before(apt->last_used, timer_seq+ARP_TIMEOUT) && apt->hlen != 0)) {
605 apt->last_used = timer_seq;
606 memcpy(haddr, apt->ha, dev->addr_len);
607 return(0);
608 } else {
609 DPRINTF((DBG_ARP, "ARP: find: found expired entry for %s\n",
610 in_ntoa(apt->ip)));
611 }
612 }
613
614
615
616
617
618
619 *(unsigned long *)haddr = paddr;
620
621
622 arp_send(paddr, dev, saddr);
623
624 return(1);
625 }
626
627
628
629 void
630 arp_add(unsigned long addr, unsigned char *haddr, struct device *dev)
631 {
632 struct arp_table *apt;
633
634 DPRINTF((DBG_ARP, "ARP: add(%s, ", in_ntoa(addr)));
635 DPRINTF((DBG_ARP, "%s, ", eth_print(haddr)));
636 DPRINTF((DBG_ARP, "%d, %d)\n", dev->hard_header_len, dev->type));
637
638
639 if (addr == 0) {
640 printk("ARP: add: will not add entry for 0.0.0.0 !\n");
641 return;
642 }
643
644
645 apt = arp_lookup(addr);
646 if (apt != NULL) {
647 DPRINTF((DBG_ARP, "ARP: updating entry for %s\n", in_ntoa(addr)));
648 apt->last_used = timer_seq;
649 memcpy(apt->ha, haddr , dev->addr_len);
650 return;
651 }
652 arp_create(addr, haddr, dev->addr_len, dev->type);
653 }
654
655
656
657 void
658 arp_add_broad(unsigned long addr, struct device *dev)
659 {
660 struct arp_table *apt;
661
662 arp_add(addr, dev->broadcast, dev);
663 apt = arp_lookup(addr);
664 if (apt != NULL) {
665 apt->flags |= ATF_PERM;
666 }
667 }
668
669
670
671 void
672 arp_queue(struct sk_buff *skb)
673 {
674 cli();
675 skb->tries = ARP_MAX_TRIES;
676
677 if (skb->next != NULL) {
678 sti();
679 printk("ARP: arp_queue skb already on queue magic=%X.\n", skb->magic);
680 return;
681 }
682 if (arp_q == NULL) {
683 arp_q = skb;
684 skb->next = skb;
685 skb->prev = skb;
686 } else {
687 skb->next = arp_q;
688 skb->prev = arp_q->prev;
689 skb->next->prev = skb;
690 skb->prev->next = skb;
691 }
692 skb->magic = ARP_QUEUE_MAGIC;
693 sti();
694 }
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712 int
713 arp_get_info(char *buffer)
714 {
715 struct arpreq *req;
716 struct arp_table *apt;
717 int i;
718 char *pos;
719
720
721 pos = buffer;
722 i = 0;
723 for (i = 0; i < ARP_TABLE_SIZE; i++) {
724 cli();
725 apt = arp_table[i];
726 sti();
727 while (apt != NULL) {
728 if (pos < (buffer + 4000)) {
729 req = (struct arpreq *) pos;
730 memset((char *) req, 0, sizeof(struct arpreq));
731 req->arp_pa.sa_family = AF_INET;
732 memcpy((char *) req->arp_pa.sa_data, (char *) &apt->ip, 4);
733 req->arp_ha.sa_family = apt->htype;
734 memcpy((char *) req->arp_ha.sa_data,
735 (char *) &apt->ha, apt->hlen);
736 }
737 pos += sizeof(struct arpreq);
738 cli();
739 apt = apt->next;
740 sti();
741 }
742 }
743 return(pos - buffer);
744 }
745
746
747
748 static int
749 arp_req_set(struct arpreq *req)
750 {
751 struct arpreq r;
752 struct arp_table *apt;
753 struct sockaddr_in *si;
754 int htype, hlen;
755
756
757 memcpy_fromfs(&r, req, sizeof(r));
758 if (r.arp_pa.sa_family != AF_INET) return(-EPFNOSUPPORT);
759
760
761
762
763
764
765 si = (struct sockaddr_in *) &r.arp_pa;
766 switch(r.arp_ha.sa_family) {
767 case 0:
768 case ARPHRD_ETHER:
769 htype = ARPHRD_ETHER;
770 hlen = ETH_ALEN;
771 break;
772 default:
773 return(-EPFNOSUPPORT);
774 }
775
776
777 if (si->sin_addr.s_addr == 0) {
778 printk("ARP: SETARP: requested PA is 0.0.0.0 !\n");
779 return(-EINVAL);
780 }
781 apt = arp_lookup(si->sin_addr.s_addr);
782 if (apt == NULL) {
783 apt = arp_create(si->sin_addr.s_addr, r.arp_ha.sa_data, hlen, htype);
784 if (apt == NULL) return(-ENOMEM);
785 }
786
787
788 memcpy((char *) &apt->ha, (char *) &r.arp_ha.sa_data, hlen);
789 apt->last_used = timer_seq;
790 apt->flags = r.arp_flags;
791
792 return(0);
793 }
794
795
796
797 static int
798 arp_req_get(struct arpreq *req)
799 {
800 struct arpreq r;
801 struct arp_table *apt;
802 struct sockaddr_in *si;
803
804
805 memcpy_fromfs(&r, req, sizeof(r));
806 if (r.arp_pa.sa_family != AF_INET) return(-EPFNOSUPPORT);
807
808
809 si = (struct sockaddr_in *) &r.arp_pa;
810 apt = arp_lookup(si->sin_addr.s_addr);
811 if (apt == NULL) return(-ENXIO);
812
813
814 memcpy((char *) r.arp_ha.sa_data, (char *) &apt->ha, apt->hlen);
815 r.arp_ha.sa_family = apt->htype;
816
817
818 memcpy_tofs(req, &r, sizeof(r));
819 return(0);
820 }
821
822
823
824 static int
825 arp_req_del(struct arpreq *req)
826 {
827 struct arpreq r;
828 struct sockaddr_in *si;
829
830
831 memcpy_fromfs(&r, req, sizeof(r));
832 if (r.arp_pa.sa_family != AF_INET) return(-EPFNOSUPPORT);
833
834 si = (struct sockaddr_in *) &r.arp_pa;
835 arp_destroy(si->sin_addr.s_addr);
836
837 return(0);
838 }
839
840
841
842 int
843 arp_ioctl(unsigned int cmd, void *arg)
844 {
845 switch(cmd) {
846 case DDIOCSDBG:
847 return(dbg_ioctl(arg, DBG_ARP));
848 case SIOCDARP:
849 if (!suser()) return(-EPERM);
850 return(arp_req_del((struct arpreq *)arg));
851 case SIOCGARP:
852 return(arp_req_get((struct arpreq *)arg));
853 case SIOCSARP:
854 if (!suser()) return(-EPERM);
855 return(arp_req_set((struct arpreq *)arg));
856 default:
857 return(-EINVAL);
858 }
859
860 return(0);
861 }