|
|
1.1 root 1: /*
2: * Linux network driver support.
3: *
4: * Copyright (C) 1996 The University of Utah and the Computer Systems
5: * Laboratory at the University of Utah (CSL)
6: *
7: * This program is free software; you can redistribute it and/or modify
8: * it under the terms of the GNU General Public License as published by
9: * the Free Software Foundation; either version 2, or (at your option)
10: * any later version.
11: *
12: * This program is distributed in the hope that it will be useful,
13: * but WITHOUT ANY WARRANTY; without even the implied warranty of
14: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: * GNU General Public License for more details.
16: *
17: * You should have received a copy of the GNU General Public License
18: * along with this program; if not, write to the Free Software
19: * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20: *
21: * Author: Shantanu Goel, University of Utah CSL
22: */
23:
24: /*
25: * INET An implementation of the TCP/IP protocol suite for the LINUX
26: * operating system. INET is implemented using the BSD Socket
27: * interface as the means of communication with the user level.
28: *
29: * Ethernet-type device handling.
30: *
31: * Version: @(#)eth.c 1.0.7 05/25/93
32: *
33: * Authors: Ross Biro, <[email protected]>
34: * Fred N. van Kempen, <[email protected]>
35: * Mark Evans, <[email protected]>
36: * Florian La Roche, <[email protected]>
37: * Alan Cox, <[email protected]>
38: *
39: * Fixes:
40: * Mr Linux : Arp problems
41: * Alan Cox : Generic queue tidyup (very tiny here)
42: * Alan Cox : eth_header ntohs should be htons
43: * Alan Cox : eth_rebuild_header missing an htons and
44: * minor other things.
45: * Tegge : Arp bug fixes.
46: * Florian : Removed many unnecessary functions, code cleanup
47: * and changes for new arp and skbuff.
48: * Alan Cox : Redid header building to reflect new format.
49: * Alan Cox : ARP only when compiled with CONFIG_INET
50: * Greg Page : 802.2 and SNAP stuff.
51: * Alan Cox : MAC layer pointers/new format.
52: * Paul Gortmaker : eth_copy_and_sum shouldn't csum padding.
53: * Alan Cox : Protect against forwarding explosions with
54: * older network drivers and IFF_ALLMULTI
55: *
56: * This program is free software; you can redistribute it and/or
57: * modify it under the terms of the GNU General Public License
58: * as published by the Free Software Foundation; either version
59: * 2 of the License, or (at your option) any later version.
60: */
61:
62: #include <sys/types.h>
63: #include <machine/spl.h>
1.1.1.2 root 64: #include <machine/vm_param.h>
1.1 root 65:
66: #include <mach/mach_types.h>
67: #include <mach/kern_return.h>
68: #include <mach/mig_errors.h>
69: #include <mach/port.h>
70: #include <mach/vm_param.h>
71: #include <mach/notify.h>
72:
1.1.1.2 root 73: #include <kern/kalloc.h>
74: #include <kern/printf.h>
75:
1.1 root 76: #include <ipc/ipc_port.h>
77: #include <ipc/ipc_space.h>
78:
79: #include <vm/vm_map.h>
80: #include <vm/vm_kern.h>
81: #include <vm/vm_page.h>
82:
83: #include <device/device_types.h>
84: #include <device/device_port.h>
85: #include <device/if_hdr.h>
86: #include <device/if_ether.h>
87: #include <device/if_hdr.h>
88: #include <device/net_io.h>
1.1.1.2 root 89: #include <device/device_reply.user.h>
90: #include <device/device_emul.h>
91: #include <device/ds_routines.h>
1.1 root 92:
93: #define MACH_INCLUDE
94: #include <linux/kernel.h>
95: #include <linux/sched.h>
96: #include <linux/string.h>
97: #include <linux/errno.h>
98: #include <linux/delay.h>
99: #include <linux/interrupt.h>
100: #include <linux/malloc.h>
101: #include <linux/netdevice.h>
102: #include <linux/etherdevice.h>
1.1.1.2 root 103: #include <linux/wireless.h>
1.1 root 104:
1.1.1.2 root 105: #include <linux/dev/glue/glue.h>
1.1 root 106:
107: /* One of these is associated with each instance of a device. */
108: struct net_data
109: {
110: ipc_port_t port; /* device port */
111: struct ifnet ifnet; /* Mach ifnet structure (needed for filters) */
112: struct device device; /* generic device structure */
113: struct linux_device *dev; /* Linux network device structure */
114: };
115:
116: /* List of sk_buffs waiting to be freed. */
117: static struct sk_buff_head skb_done_list;
118:
119: /* Forward declarations. */
120:
121: extern struct device_emulation_ops linux_net_emulation_ops;
122:
123: static int print_packet_size = 0;
124:
125: /* Linux kernel network support routines. */
126:
127: /* Requeue packet SKB for transmission after the interface DEV
128: has timed out. The priority of the packet is PRI.
129: In Mach, we simply drop the packet like the native drivers. */
130: void
131: dev_queue_xmit (struct sk_buff *skb, struct linux_device *dev, int pri)
132: {
133: dev_kfree_skb (skb, FREE_WRITE);
134: }
135:
136: /* Close the device DEV. */
137: int
138: dev_close (struct linux_device *dev)
139: {
140: return 0;
141: }
142:
143: /* Network software interrupt handler. */
144: void
145: net_bh (void)
146: {
147: int len;
148: struct sk_buff *skb;
149: struct linux_device *dev;
150:
151: /* Start transmission on interfaces. */
152: for (dev = dev_base; dev; dev = dev->next)
153: {
154: if (dev->base_addr && dev->base_addr != 0xffe0)
155: while (1)
156: {
157: skb = skb_dequeue (&dev->buffs[0]);
158: if (skb)
159: {
160: len = skb->len;
161: if ((*dev->hard_start_xmit) (skb, dev))
162: {
163: skb_queue_head (&dev->buffs[0], skb);
164: mark_bh (NET_BH);
165: break;
166: }
167: else if (print_packet_size)
168: printf ("net_bh: length %d\n", len);
169: }
170: else
171: break;
172: }
173: }
174: }
175:
176: /* Free all sk_buffs on the done list.
177: This routine is called by the iodone thread in ds_routines.c. */
178: void
179: free_skbuffs ()
180: {
181: struct sk_buff *skb;
182:
183: while (1)
184: {
185: skb = skb_dequeue (&skb_done_list);
186: if (skb)
187: {
188: if (skb->copy)
189: {
190: vm_map_copy_discard (skb->copy);
191: skb->copy = NULL;
192: }
193: if (IP_VALID (skb->reply))
194: {
195: ds_device_write_reply (skb->reply, skb->reply_type, 0, skb->len);
196: skb->reply = IP_NULL;
197: }
198: dev_kfree_skb (skb, FREE_WRITE);
199: }
200: else
201: break;
202: }
203: }
204:
205: /* Allocate an sk_buff with SIZE bytes of data space. */
206: struct sk_buff *
207: alloc_skb (unsigned int size, int priority)
208: {
209: return dev_alloc_skb (size);
210: }
211:
212: /* Free SKB. */
213: void
214: kfree_skb (struct sk_buff *skb, int priority)
215: {
216: dev_kfree_skb (skb, priority);
217: }
218:
219: /* Allocate an sk_buff with SIZE bytes of data space. */
220: struct sk_buff *
221: dev_alloc_skb (unsigned int size)
222: {
223: struct sk_buff *skb;
224: unsigned char *bptr;
225: int len = size;
226:
227: size = (size + 15) & ~15;
228: size += sizeof (struct sk_buff);
229:
230: bptr = linux_kmalloc (size, GFP_KERNEL);
231: if (bptr == NULL)
232: return NULL;
233:
234: /* XXX: In Mach, a sk_buff is located at the head,
235: while it's located at the tail in Linux. */
236: skb = bptr;
237: skb->dev = NULL;
238: skb->reply = IP_NULL;
239: skb->copy = NULL;
240: skb->len = 0;
241: skb->prev = skb->next = NULL;
242: skb->list = NULL;
243: skb->data = bptr + sizeof (struct sk_buff);
244: skb->tail = skb->data;
245: skb->head = skb->data;
246: skb->end = skb->data + len;
247:
248: return skb;
249: }
250:
251: /* Free the sk_buff SKB. */
252: void
253: dev_kfree_skb (struct sk_buff *skb, int mode)
254: {
255: unsigned flags;
256:
257: /* Queue sk_buff on done list if there is a
258: page list attached or we need to send a reply.
259: Wakeup the iodone thread to process the list. */
260: if (skb->copy || IP_VALID (skb->reply))
261: {
262: skb_queue_tail (&skb_done_list, skb);
263: save_flags (flags);
264: thread_wakeup ((event_t) & io_done_list);
265: restore_flags (flags);
266: return;
267: }
268: linux_kfree (skb);
269: }
270:
271: /* Accept packet SKB received on an interface. */
272: void
273: netif_rx (struct sk_buff *skb)
274: {
275: ipc_kmsg_t kmsg;
276: struct ether_header *eh;
277: struct packet_header *ph;
278: struct linux_device *dev = skb->dev;
279:
280: assert (skb != NULL);
281:
282: if (print_packet_size)
283: printf ("netif_rx: length %ld\n", skb->len);
284:
285: /* Allocate a kernel message buffer. */
286: kmsg = net_kmsg_get ();
287: if (!kmsg)
288: {
289: dev_kfree_skb (skb, FREE_READ);
290: return;
291: }
292:
293: /* Copy packet into message buffer. */
294: eh = (struct ether_header *) (net_kmsg (kmsg)->header);
295: ph = (struct packet_header *) (net_kmsg (kmsg)->packet);
296: memcpy (eh, skb->data, sizeof (struct ether_header));
1.1.1.2 root 297:
298: /* packet is prefixed with a struct packet_header,
299: see include/device/net_status.h. */
1.1 root 300: memcpy (ph + 1, skb->data + sizeof (struct ether_header),
301: skb->len - sizeof (struct ether_header));
302: ph->type = eh->ether_type;
303: ph->length = (skb->len - sizeof (struct ether_header)
304: + sizeof (struct packet_header));
305:
306: dev_kfree_skb (skb, FREE_READ);
307:
1.1.1.2 root 308: net_kmsg(kmsg)->sent = FALSE; /* Mark packet as received. */
309:
1.1 root 310: /* Pass packet up to the microkernel. */
311: net_packet (&dev->net_data->ifnet, kmsg,
312: ph->length, ethernet_priority (kmsg));
313: }
314:
315: /* Mach device interface routines. */
316:
317: /* Return a send right associated with network device ND. */
318: static ipc_port_t
319: dev_to_port (void *nd)
320: {
321: return (nd
322: ? ipc_port_make_send (((struct net_data *) nd)->port)
323: : IP_NULL);
324: }
325:
326: static io_return_t
327: device_open (ipc_port_t reply_port, mach_msg_type_name_t reply_port_type,
328: dev_mode_t mode, char *name, device_t *devp)
329: {
330: io_return_t err = D_SUCCESS;
331: ipc_port_t notify;
332: struct ifnet *ifp;
333: struct linux_device *dev;
334: struct net_data *nd;
335:
336: /* Search for the device. */
337: for (dev = dev_base; dev; dev = dev->next)
338: if (dev->base_addr
339: && dev->base_addr != 0xffe0
340: && !strcmp (name, dev->name))
341: break;
342: if (!dev)
343: return D_NO_SUCH_DEVICE;
344:
345: /* Allocate and initialize device data if this is the first open. */
346: nd = dev->net_data;
347: if (!nd)
348: {
349: dev->net_data = nd = ((struct net_data *)
350: kalloc (sizeof (struct net_data)));
351: if (!nd)
352: {
353: err = D_NO_MEMORY;
354: goto out;
355: }
356: nd->dev = dev;
357: nd->device.emul_data = nd;
358: nd->device.emul_ops = &linux_net_emulation_ops;
359: nd->port = ipc_port_alloc_kernel ();
360: if (nd->port == IP_NULL)
361: {
362: err = KERN_RESOURCE_SHORTAGE;
363: goto out;
364: }
365: ipc_kobject_set (nd->port, (ipc_kobject_t) & nd->device, IKOT_DEVICE);
366: notify = ipc_port_make_sonce (nd->port);
367: ip_lock (nd->port);
368: ipc_port_nsrequest (nd->port, 1, notify, ¬ify);
369: assert (notify == IP_NULL);
370:
371: ifp = &nd->ifnet;
372: ifp->if_unit = dev->name[strlen (dev->name) - 1] - '0';
373: ifp->if_flags = IFF_UP | IFF_RUNNING;
374: ifp->if_mtu = dev->mtu;
375: ifp->if_header_size = dev->hard_header_len;
376: ifp->if_header_format = dev->type;
377: ifp->if_address_size = dev->addr_len;
378: ifp->if_address = dev->dev_addr;
379: if_init_queues (ifp);
380:
381: if (dev->open)
382: {
383: linux_intr_pri = SPL6;
384: if ((*dev->open) (dev))
385: err = D_NO_SUCH_DEVICE;
386: }
387:
388: out:
389: if (err)
390: {
391: if (nd)
392: {
393: if (nd->port != IP_NULL)
394: {
395: ipc_kobject_set (nd->port, IKO_NULL, IKOT_NONE);
396: ipc_port_dealloc_kernel (nd->port);
397: }
398: kfree ((vm_offset_t) nd, sizeof (struct net_data));
399: nd = NULL;
400: dev->net_data = NULL;
401: }
402: }
403: else
404: {
1.1.1.2 root 405: /* IPv6 heavily relies on multicasting (especially router and
406: neighbor solicits and advertisements), so enable reception of
407: those multicast packets by setting `LINUX_IFF_ALLMULTI'. */
408: dev->flags |= LINUX_IFF_UP | LINUX_IFF_RUNNING | LINUX_IFF_ALLMULTI;
1.1 root 409: skb_queue_head_init (&dev->buffs[0]);
1.1.1.2 root 410:
411: if (dev->set_multicast_list)
412: dev->set_multicast_list (dev);
1.1 root 413: }
414: if (IP_VALID (reply_port))
415: ds_device_open_reply (reply_port, reply_port_type,
416: err, dev_to_port (nd));
417: return MIG_NO_REPLY;
418: }
419:
420: *devp = &nd->device;
421: return D_SUCCESS;
422: }
423:
424: static io_return_t
425: device_write (void *d, ipc_port_t reply_port,
426: mach_msg_type_name_t reply_port_type, dev_mode_t mode,
427: recnum_t bn, io_buf_ptr_t data, unsigned int count,
428: int *bytes_written)
429: {
430: unsigned char *p;
1.1.1.3 ! root 431: int i, s;
1.1 root 432: vm_map_copy_t copy = (vm_map_copy_t) data;
1.1.1.3 ! root 433: char *map_data;
! 434: vm_offset_t map_addr;
! 435: vm_size_t map_size;
1.1 root 436: struct net_data *nd = d;
437: struct linux_device *dev = nd->dev;
438: struct sk_buff *skb;
1.1.1.3 ! root 439: kern_return_t kr;
1.1 root 440:
441: if (count == 0 || count > dev->mtu + dev->hard_header_len)
442: return D_INVALID_SIZE;
443:
444: /* Allocate a sk_buff. */
1.1.1.3 ! root 445: skb = dev_alloc_skb (count);
1.1 root 446: if (!skb)
447: return D_NO_MEMORY;
448:
1.1.1.3 ! root 449: /* Map user data. */
! 450: kr = kmem_io_map_copyout(device_io_map, (vm_offset_t *)&map_data,
! 451: &map_addr, &map_size, copy, count);
1.1 root 452:
1.1.1.3 ! root 453: if (kr) {
! 454: dev_kfree_skb (skb, FREE_WRITE);
! 455: return D_NO_MEMORY;
! 456: }
1.1 root 457:
1.1.1.3 ! root 458: /* XXX The underlying physical pages of the mapping could be highmem,
! 459: for which drivers require the use of a bounce buffer. */
! 460: memcpy (skb->data, map_data, count);
! 461: kmem_io_map_deallocate (device_io_map, map_addr, map_size);
! 462: vm_map_copy_discard (copy);
! 463:
! 464: skb->len = count;
! 465: skb->head = skb->data;
! 466: skb->tail = skb->data + skb->len;
! 467: skb->end = skb->tail;
1.1 root 468: skb->dev = dev;
469: skb->reply = reply_port;
470: skb->reply_type = reply_port_type;
471:
472: /* Queue packet for transmission and schedule a software interrupt. */
473: s = splimp ();
474: if (dev->buffs[0].next != (struct sk_buff *) &dev->buffs[0]
475: || (*dev->hard_start_xmit) (skb, dev))
476: {
477: __skb_queue_tail (&dev->buffs[0], skb);
478: mark_bh (NET_BH);
479: }
480: splx (s);
481:
1.1.1.2 root 482: /* Send packet to filters. */
483: {
484: struct packet_header *packet;
485: struct ether_header *header;
486: ipc_kmsg_t kmsg;
487:
488: kmsg = net_kmsg_get ();
489:
490: if (kmsg != IKM_NULL)
491: {
492: /* Suitable for Ethernet only. */
493: header = (struct ether_header *) (net_kmsg (kmsg)->header);
494: packet = (struct packet_header *) (net_kmsg (kmsg)->packet);
495: memcpy (header, skb->data, sizeof (struct ether_header));
496:
497: /* packet is prefixed with a struct packet_header,
498: see include/device/net_status.h. */
499: memcpy (packet + 1, skb->data + sizeof (struct ether_header),
500: skb->len - sizeof (struct ether_header));
501: packet->length = skb->len - sizeof (struct ether_header)
502: + sizeof (struct packet_header);
503: packet->type = header->ether_type;
504: net_kmsg (kmsg)->sent = TRUE; /* Mark packet as sent. */
505: s = splimp ();
506: net_packet (&dev->net_data->ifnet, kmsg, packet->length,
507: ethernet_priority (kmsg));
508: splx (s);
509: }
510: }
511:
1.1 root 512: return MIG_NO_REPLY;
513: }
514:
1.1.1.2 root 515:
1.1 root 516: static io_return_t
517: device_get_status (void *d, dev_flavor_t flavor, dev_status_t status,
518: mach_msg_type_number_t *count)
519: {
1.1.1.2 root 520: if (flavor == NET_FLAGS)
521: {
522: struct net_data *net = (struct net_data *) d;
523:
524: if (*count != 1)
525: return D_INVALID_SIZE;
526:
527: status[0] = net->dev->flags;
528: return D_SUCCESS;
529: }
530:
531: if(flavor >= SIOCIWFIRST && flavor <= SIOCIWLAST)
532: {
533: /* handle wireless ioctl */
534: if(! IW_IS_GET(flavor))
535: return D_INVALID_OPERATION;
536:
537: if(*count * sizeof(int) < sizeof(struct ifreq))
538: return D_INVALID_OPERATION;
539:
540: struct net_data *nd = d;
541: struct linux_device *dev = nd->dev;
542:
543: if(! dev->do_ioctl)
544: return D_INVALID_OPERATION;
545:
546: int result;
547:
548: if (flavor == SIOCGIWRANGE || flavor == SIOCGIWENCODE
549: || flavor == SIOCGIWESSID || flavor == SIOCGIWNICKN
550: || flavor == SIOCGIWSPY)
551: {
552: /*
553: * These ioctls require an `iw_point' as their argument (i.e.
554: * they want to return some data to userspace.
555: * Therefore supply some sane values and carry the data back
556: * to userspace right behind the `struct iwreq'.
557: */
558: struct iw_point *iwp = &((struct iwreq *) status)->u.data;
559: iwp->length = *count * sizeof (dev_status_t) - sizeof (struct ifreq);
560: iwp->pointer = (void *) status + sizeof (struct ifreq);
561:
562: result = dev->do_ioctl (dev, (struct ifreq *) status, flavor);
563:
564: *count = ((sizeof (struct ifreq) + iwp->length)
565: / sizeof (dev_status_t));
566: if (iwp->length % sizeof (dev_status_t))
567: (*count) ++;
568: }
569: else
570: {
571: *count = sizeof(struct ifreq) / sizeof(int);
572: result = dev->do_ioctl(dev, (struct ifreq *) status, flavor);
573: }
574:
575: return result ? D_IO_ERROR : D_SUCCESS;
576: }
577: else
578: {
579: /* common get_status request */
580: return net_getstat (&((struct net_data *) d)->ifnet, flavor,
581: status, count);
582: }
1.1 root 583: }
584:
1.1.1.2 root 585:
586: static io_return_t
587: device_set_status(void *d, dev_flavor_t flavor, dev_status_t status,
588: mach_msg_type_number_t count)
589: {
590: if (flavor == NET_FLAGS)
591: {
592: if (count != 1)
593: return D_INVALID_SIZE;
594:
595: short flags = status[0];
596: struct net_data *net = (struct net_data *) d;
597:
598: dev_change_flags (net->dev, flags);
599:
600: /* Change the flags of the Mach device, too. */
601: net->ifnet.if_flags = net->dev->flags;
602: return D_SUCCESS;
603: }
604:
605: if(flavor < SIOCIWFIRST || flavor > SIOCIWLAST)
606: return D_INVALID_OPERATION;
607:
608: if(! IW_IS_SET(flavor))
609: return D_INVALID_OPERATION;
610:
611: if(count * sizeof(int) < sizeof(struct ifreq))
612: return D_INVALID_OPERATION;
613:
614: struct net_data *nd = d;
615: struct linux_device *dev = nd->dev;
616:
617: if(! dev->do_ioctl)
618: return D_INVALID_OPERATION;
619:
620: if((flavor == SIOCSIWENCODE || flavor == SIOCSIWESSID
621: || flavor == SIOCSIWNICKN || flavor == SIOCSIWSPY)
622: && ((struct iwreq *) status)->u.data.pointer)
623: {
624: struct iw_point *iwp = &((struct iwreq *) status)->u.data;
625:
626: /* safety check whether the status array is long enough ... */
627: if(count * sizeof(int) < sizeof(struct ifreq) + iwp->length)
628: return D_INVALID_OPERATION;
629:
630: /* make sure, iwp->pointer points to the correct address */
631: if(iwp->pointer) iwp->pointer = (void *) status + sizeof(struct ifreq);
632: }
633:
634: int result = dev->do_ioctl(dev, (struct ifreq *) status, flavor);
635: return result ? D_IO_ERROR : D_SUCCESS;
636: }
637:
638:
1.1 root 639: static io_return_t
640: device_set_filter (void *d, ipc_port_t port, int priority,
641: filter_t * filter, unsigned filter_count)
642: {
643: return net_set_filter (&((struct net_data *) d)->ifnet,
644: port, priority, filter, filter_count);
645: }
646:
647: struct device_emulation_ops linux_net_emulation_ops =
648: {
649: NULL,
650: NULL,
651: dev_to_port,
652: device_open,
653: NULL,
654: device_write,
655: NULL,
656: NULL,
657: NULL,
1.1.1.2 root 658: device_set_status,
1.1 root 659: device_get_status,
660: device_set_filter,
661: NULL,
662: NULL,
663: NULL,
664: NULL
665: };
666:
667: /* Do any initialization required for network devices. */
668: void
669: linux_net_emulation_init ()
670: {
671: skb_queue_head_init (&skb_done_list);
672: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.