ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/Linux/NetDriver/sheep_net.c
Revision: 1.4
Committed: 2001-03-18T15:41:17Z (23 years, 3 months ago) by cebix
Content type: text/plain
Branch: MAIN
Changes since 1.3: +278 -112 lines
Log Message:
backported the changes from the Mac-On-Linux project:
 - now compiles under Linux 2.4 kernels
 - Ethernet hardware address is virtualized on the Mac side
 - automatically filters IP packets based on the IP address of the Mac side

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * sheep_net.c - Linux driver for SheepShaver/Basilisk II networking (access to raw Ethernet packets)
3     *
4 cebix 1.3 * sheep_net (C) 1999-2001 Mar"c" Hellwig and Christian Bauer
5 cebix 1.1 *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19     */
20    
21     #include <linux/kernel.h>
22     #include <linux/module.h>
23     #include <linux/version.h>
24     #include <linux/miscdevice.h>
25     #include <linux/netdevice.h>
26     #include <linux/etherdevice.h>
27     #include <linux/if_ether.h>
28     #include <linux/if_arp.h>
29     #include <linux/fs.h>
30     #include <linux/poll.h>
31     #include <linux/init.h>
32 cebix 1.4 #include <linux/in.h>
33     #include <linux/wait.h>
34 cebix 1.1 #include <net/sock.h>
35 cebix 1.4 #include <net/arp.h>
36     #include <net/ip.h>
37 cebix 1.1 #include <asm/uaccess.h>
38    
39 cebix 1.4 /* Compatibility glue */
40     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
41     #define LINUX_24
42     #else
43     #define net_device device
44     typedef struct wait_queue *wait_queue_head_t;
45     #define init_waitqueue_head(x) *(x)=NULL
46     #endif
47    
48 cebix 1.1 #define DEBUG 0
49    
50     #define bug printk
51     #if DEBUG
52     #define D(x) (x);
53     #else
54     #define D(x) ;
55     #endif
56    
57    
58 cebix 1.4 /* Constants */
59     #define SHEEP_NET_MINOR 198 /* Driver minor number */
60     #define MAX_QUEUE 32 /* Maximum number of packets in queue */
61     #define PROT_MAGIC 1520 /* Our "magic" protocol type */
62 cebix 1.1
63 cebix 1.4 #define ETH_ADDR_MULTICAST 0x1
64    
65     #define SIOC_MOL_GET_IPFILTER SIOCDEVPRIVATE
66     #define SIOC_MOL_SET_IPFILTER (SIOCDEVPRIVATE + 1)
67    
68     /* Prototypes */
69 cebix 1.1 static int sheep_net_open(struct inode *inode, struct file *f);
70     static int sheep_net_release(struct inode *inode, struct file *f);
71     static ssize_t sheep_net_read(struct file *f, char *buf, size_t count, loff_t *off);
72     static ssize_t sheep_net_write(struct file *f, const char *buf, size_t count, loff_t *off);
73     static unsigned int sheep_net_poll(struct file *f, struct poll_table_struct *wait);
74     static int sheep_net_ioctl(struct inode *inode, struct file *f, unsigned int code, unsigned long arg);
75 cebix 1.4 static int sheep_net_receiver(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt);
76 cebix 1.1
77    
78     /*
79     * Driver private variables
80     */
81    
82     struct SheepVars {
83 cebix 1.4 struct net_device *ether; /* The Ethernet device we're attached to */
84     struct sock *skt; /* Socket for communication with Ethernet card */
85     struct sk_buff_head queue; /* Receiver packet queue */
86     struct packet_type pt; /* Receiver packet type */
87     wait_queue_head_t wait; /* Wait queue for blocking read operations */
88     u32 ipfilter; /* Only receive IP packets destined for this address (host byte order) */
89     char eth_addr[6]; /* Hardware address of the Ethernet card */
90     char fake_addr[6]; /* Local faked hardware address (what SheepShaver sees) */
91 cebix 1.1 };
92    
93    
94     /*
95     * file_operations structure - has function pointers to the
96     * various entry points for device operations
97     */
98    
99     static struct file_operations sheep_net_fops = {
100 cebix 1.4 read: sheep_net_read,
101     write: sheep_net_write,
102     poll: sheep_net_poll,
103     ioctl: sheep_net_ioctl,
104     open: sheep_net_open,
105     release: sheep_net_release,
106 cebix 1.1 };
107    
108    
109     /*
110     * miscdevice structure for driver initialization
111     */
112    
113     static struct miscdevice sheep_net_device = {
114 cebix 1.4 SHEEP_NET_MINOR, /* minor number */
115     "sheep_net", /* name */
116 cebix 1.1 &sheep_net_fops,
117     NULL,
118     NULL
119     };
120    
121    
122     /*
123     * Initialize module
124     */
125    
126     int init_module(void)
127     {
128     int ret;
129    
130 cebix 1.4 /* Register driver */
131 cebix 1.1 ret = misc_register(&sheep_net_device);
132     D(bug("Sheep net driver installed\n"));
133     return ret;
134     }
135    
136    
137     /*
138     * Deinitialize module
139     */
140    
141     int cleanup_module(void)
142     {
143     int ret;
144    
145 cebix 1.4 /* Unregister driver */
146 cebix 1.1 ret = misc_deregister(&sheep_net_device);
147     D(bug("Sheep net driver removed\n"));
148     return ret;
149     }
150    
151    
152     /*
153     * Driver open() function
154     */
155    
156     static int sheep_net_open(struct inode *inode, struct file *f)
157     {
158     struct SheepVars *v;
159     D(bug("sheep_net: open\n"));
160    
161 cebix 1.4 /* Must be opened with read permissions */
162 cebix 1.1 if ((f->f_flags & O_ACCMODE) == O_WRONLY)
163     return -EPERM;
164    
165 cebix 1.4 /* Allocate private variables */
166 cebix 1.1 v = (struct SheepVars *)f->private_data = kmalloc(sizeof(struct SheepVars), GFP_USER);
167     if (v == NULL)
168     return -ENOMEM;
169     memset(v, 0, sizeof(struct SheepVars));
170     skb_queue_head_init(&v->queue);
171 cebix 1.4 init_waitqueue_head(&v->wait);
172     v->fake_addr[0] = 0xfe;
173     v->fake_addr[1] = 0xfd;
174     v->fake_addr[2] = 0xde;
175     v->fake_addr[3] = 0xad;
176     v->fake_addr[4] = 0xbe;
177     v->fake_addr[5] = 0xef;
178 cebix 1.1
179 cebix 1.4 /* Yes, we're open */
180 cebix 1.1 MOD_INC_USE_COUNT;
181     return 0;
182     }
183    
184    
185     /*
186     * Driver release() function
187     */
188    
189     static int sheep_net_release(struct inode *inode, struct file *f)
190     {
191     struct SheepVars *v = (struct SheepVars *)f->private_data;
192     struct sk_buff *skb;
193     D(bug("sheep_net: close\n"));
194    
195 cebix 1.4 /* Detach from Ethernet card */
196 cebix 1.1 if (v->ether) {
197     dev_remove_pack(&v->pt);
198     sk_free(v->skt);
199     v->skt = NULL;
200 cebix 1.4 #ifdef LINUX_24
201     dev_put( v->ether );
202     #endif
203 cebix 1.1 v->ether = NULL;
204     }
205    
206 cebix 1.4 /* Empty packet queue */
207 cebix 1.1 while ((skb = skb_dequeue(&v->queue)) != NULL)
208     dev_kfree_skb(skb);
209    
210 cebix 1.4 /* Free private variables */
211 cebix 1.1 kfree(v);
212    
213 cebix 1.4 /* Sorry, we're closed */
214 cebix 1.1 MOD_DEC_USE_COUNT;
215     return 0;
216     }
217    
218    
219     /*
220 cebix 1.4 * Check whether an Ethernet address is the local (attached) one or
221     * the fake one
222     */
223    
224     static inline int is_local_addr(struct SheepVars *v, void *a)
225     {
226     return memcmp(a, v->eth_addr, 6) == 0;
227     }
228    
229     static inline int is_fake_addr(struct SheepVars *v, void *a)
230     {
231     return memcmp(a, v->fake_addr, 6) == 0;
232     }
233    
234    
235     /*
236     * Outgoing packet. Replace the fake enet addr with the real local one.
237     */
238    
239     static inline void do_demasq(struct SheepVars *v, u8 *p)
240     {
241     memcpy(p, v->eth_addr, 6);
242     }
243    
244     static void demasquerade(struct SheepVars *v, struct sk_buff *skb)
245     {
246     u8 *p = skb->mac.raw;
247     int proto = (p[12] << 8) | p[13];
248    
249     do_demasq(v, p + 6); /* source address */
250    
251     /* Need to fix ARP packets */
252     if (proto == ETH_P_ARP) {
253     if (is_fake_addr(v, p + 14 + 8)) /* sender HW-addr */
254     do_demasq(v, p + 14 + 8);
255     }
256    
257     /* ...and AARPs (snap code: 0x00,0x00,0x00,0x80,0xF3) */
258     if (p[17] == 0 && p[18] == 0 && p[19] == 0 && p[20] == 0x80 && p[21] == 0xf3) {
259     /* XXX: we should perhaps look for the 802 frame too */
260     if (is_fake_addr(v, p + 30))
261     do_demasq(v, p + 30); /* sender HW-addr */
262     }
263     }
264    
265    
266     /*
267     * Incoming packet. Replace the local enet addr with the fake one.
268     */
269    
270     static inline void do_masq(struct SheepVars *v, u8 *p)
271     {
272     memcpy(p, v->fake_addr, 6);
273     }
274    
275     static void masquerade(struct SheepVars *v, struct sk_buff *skb)
276     {
277     u8 *p = skb->mac.raw;
278     if (!(p[0] & ETH_ADDR_MULTICAST))
279     do_masq(v, p); /* destination address */
280    
281     /* XXX: reverse ARP might need to be fixed */
282     }
283    
284    
285     /*
286 cebix 1.1 * Driver read() function
287     */
288    
289     static ssize_t sheep_net_read(struct file *f, char *buf, size_t count, loff_t *off)
290     {
291     struct SheepVars *v = (struct SheepVars *)f->private_data;
292     struct sk_buff *skb;
293 cebix 1.4
294 cebix 1.1 D(bug("sheep_net: read\n"));
295    
296     for (;;) {
297    
298 cebix 1.4 /* Get next packet from queue */
299 cebix 1.1 skb = skb_dequeue(&v->queue);
300     if (skb != NULL || (f->f_flags & O_NONBLOCK))
301     break;
302    
303 cebix 1.4 /* No packet in queue and in blocking mode, so block */
304 cebix 1.1 interruptible_sleep_on(&v->wait);
305    
306 cebix 1.4 /* Signal received? Then bail out */
307     if (signal_pending(current))
308     return -EINTR;
309 cebix 1.1 }
310     if (skb == NULL)
311     return -EAGAIN;
312    
313 cebix 1.4 /* Pass packet to caller */
314 cebix 1.1 if (count > skb->len)
315     count = skb->len;
316     if (copy_to_user(buf, skb->data, count))
317     count = -EFAULT;
318     dev_kfree_skb(skb);
319     return count;
320     }
321    
322    
323     /*
324     * Driver write() function
325     */
326    
327     static ssize_t sheep_net_write(struct file *f, const char *buf, size_t count, loff_t *off)
328     {
329     struct SheepVars *v = (struct SheepVars *)f->private_data;
330     struct sk_buff *skb;
331     char *p;
332     D(bug("sheep_net: write\n"));
333    
334 cebix 1.4 /* Check packet size */
335 cebix 1.1 if (count < sizeof(struct ethhdr))
336     return -EINVAL;
337     if (count > 1514)
338     count = 1514;
339    
340 cebix 1.4 /* Interface active? */
341 cebix 1.1 if (v->ether == NULL)
342     return count;
343    
344 cebix 1.4 /* Allocate buffer for packet */
345 cebix 1.1 skb = dev_alloc_skb(count);
346     if (skb == NULL)
347     return -ENOBUFS;
348    
349 cebix 1.4 /* Stuff packet in buffer */
350 cebix 1.1 p = skb_put(skb, count);
351     if (copy_from_user(p, buf, count)) {
352     kfree_skb(skb);
353     return -EFAULT;
354     }
355    
356 cebix 1.4 /* Transmit packet */
357 cebix 1.1 atomic_add(skb->truesize, &v->skt->wmem_alloc);
358     skb->sk = v->skt;
359     skb->dev = v->ether;
360     skb->priority = 0;
361     skb->nh.raw = skb->h.raw = skb->data + v->ether->hard_header_len;
362 cebix 1.4 skb->mac.raw = skb->data;
363    
364     /* Base the IP-filtering on the IP address in any outgoing ARP packets */
365     if (skb->mac.ethernet->h_proto == htons(ETH_P_ARP)) {
366     u8 *p = &skb->data[14+14]; /* source IP address */
367     u32 ip = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
368     if (ip != v->ipfilter) {
369     v->ipfilter = ip;
370     printk("sheep_net: ipfilter set to %d.%d.%d.%d\n", (ip >> 24) & 0xff, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff);
371     }
372     }
373    
374     /* Is this packet addressed solely to the local host? */
375     if (is_local_addr(v, skb->data) && !(skb->data[0] & ETH_ADDR_MULTICAST)) {
376     skb->protocol = eth_type_trans(skb, v->ether);
377     netif_rx(skb);
378     return count;
379     }
380     if (skb->data[0] & ETH_ADDR_MULTICAST) {
381     /* We can't clone the skb since we will manipulate the data below */
382     struct sk_buff *lskb = skb_copy(skb, GFP_ATOMIC);
383     if (lskb) {
384     lskb->protocol = eth_type_trans(lskb, v->ether);
385     netif_rx(lskb);
386     }
387     }
388    
389     /* Outgoing packet (will be on the net) */
390     demasquerade(v, skb);
391    
392     skb->protocol = PROT_MAGIC; /* Magic value (we can recognize the packet in sheep_net_receiver) */
393 cebix 1.1 dev_queue_xmit(skb);
394     return count;
395     }
396    
397    
398     /*
399     * Driver poll() function
400     */
401    
402     static unsigned int sheep_net_poll(struct file *f, struct poll_table_struct *wait)
403     {
404     struct SheepVars *v = (struct SheepVars *)f->private_data;
405     D(bug("sheep_net: poll\n"));
406    
407 cebix 1.4 /* Packets in queue? Then return */
408     if (!skb_queue_empty(&v->queue))
409 cebix 1.1 return POLLIN | POLLRDNORM;
410    
411 cebix 1.4 /* Otherwise wait for packet */
412 cebix 1.1 poll_wait(f, &v->wait, wait);
413 cebix 1.4 if (!skb_queue_empty(&v->queue))
414 cebix 1.1 return POLLIN | POLLRDNORM;
415 cebix 1.4 else
416 cebix 1.1 return 0;
417     }
418    
419    
420     /*
421     * Driver ioctl() function
422     */
423    
424     static int sheep_net_ioctl(struct inode *inode, struct file *f, unsigned int code, unsigned long arg)
425     {
426     struct SheepVars *v = (struct SheepVars *)f->private_data;
427     D(bug("sheep_net: ioctl %04x\n", code));
428    
429     switch (code) {
430    
431 cebix 1.4 /* Attach to Ethernet card
432     arg: pointer to name of Ethernet device (char[8]) */
433 cebix 1.1 case SIOCSIFLINK: {
434     char name[8];
435 cebix 1.4 int err;
436 cebix 1.1
437 cebix 1.4 /* Already attached? */
438 cebix 1.1 if (v->ether)
439     return -EBUSY;
440    
441 cebix 1.4 /* Get Ethernet card name */
442 cebix 1.1 if (copy_from_user(name, (void *)arg, 8))
443     return -EFAULT;
444     name[7] = 0;
445    
446 cebix 1.4 /* Find card */
447     #ifdef LINUX_24
448     v->ether = dev_get_by_name(name);
449     #else
450 cebix 1.1 dev_lock_list();
451     v->ether = dev_get(name);
452 cebix 1.4 #endif
453 cebix 1.1 if (v->ether == NULL) {
454 cebix 1.4 err = -ENODEV;
455     goto error;
456 cebix 1.1 }
457    
458 cebix 1.4 /* Is it Ethernet? */
459 cebix 1.1 if (v->ether->type != ARPHRD_ETHER) {
460 cebix 1.4 err = -EINVAL;
461     goto error;
462 cebix 1.1 }
463    
464 cebix 1.4 /* Remember the card's hardware address */
465     memcpy(v->eth_addr, v->ether->dev_addr, 6);
466    
467     /* Allocate socket */
468 cebix 1.1 v->skt = sk_alloc(0, GFP_USER, 1);
469     if (v->skt == NULL) {
470 cebix 1.4 err = -ENOMEM;
471     goto error;
472 cebix 1.1 }
473     v->skt->dead = 1;
474    
475 cebix 1.4 /* Attach packet handler */
476 cebix 1.1 v->pt.type = htons(ETH_P_ALL);
477     v->pt.dev = v->ether;
478     v->pt.func = sheep_net_receiver;
479     v->pt.data = v;
480     dev_add_pack(&v->pt);
481 cebix 1.4 #ifndef LINUX_24
482 cebix 1.1 dev_unlock_list();
483 cebix 1.4 #endif
484 cebix 1.1 return 0;
485 cebix 1.4
486     error:
487     #ifdef LINUX_24
488     if (v->ether)
489     dev_put(v->ether);
490     #else
491     dev_unlock_list();
492     #endif
493     v->ether = NULL;
494     return err;
495 cebix 1.1 }
496    
497 cebix 1.4 /* Get hardware address of the sheep_net module
498     arg: pointer to buffer (6 bytes) to store address */
499 cebix 1.1 case SIOCGIFADDR:
500 cebix 1.4 if (copy_to_user((void *)arg, v->fake_addr, 6))
501     return -EFAULT;
502     return 0;
503    
504     /* Set the hardware address of the sheep_net module
505     arg: pointer to new address (6 bytes) */
506     case SIOCSIFADDR:
507     if (copy_from_user(v->fake_addr, (void*)arg, 6))
508 cebix 1.1 return -EFAULT;
509     return 0;
510    
511 cebix 1.4 /* Add multicast address
512     arg: pointer to address (6 bytes) */
513 cebix 1.1 case SIOCADDMULTI: {
514     char addr[6];
515     if (v->ether == NULL)
516     return -ENODEV;
517     if (copy_from_user(addr, (void *)arg, 6))
518     return -EFAULT;
519     return dev_mc_add(v->ether, addr, 6, 0);
520     }
521    
522 cebix 1.4 /* Remove multicast address
523     arg: pointer to address (6 bytes) */
524 cebix 1.1 case SIOCDELMULTI: {
525     char addr[6];
526     if (v->ether == NULL)
527     return -ENODEV;
528     if (copy_from_user(addr, (void *)arg, 6))
529     return -EFAULT;
530     return dev_mc_delete(v->ether, addr, 6, 0);
531     }
532    
533 cebix 1.4 /* Return size of first packet in queue */
534 cebix 1.1 case FIONREAD: {
535     int count = 0;
536     struct sk_buff *skb;
537 cebix 1.4 #ifdef LINUX_24
538     long flags;
539     spin_lock_irqsave(&v->queue.lock, flags);
540     #else
541     cli();
542     #endif
543 cebix 1.1 skb = skb_peek(&v->queue);
544     if (skb)
545     count = skb->len;
546 cebix 1.4 #ifdef LINUX_24
547     spin_unlock_irqrestore(&v->queue.lock, flags);
548     #else
549     sti();
550     #endif
551 cebix 1.1 return put_user(count, (int *)arg);
552     }
553    
554 cebix 1.4 case SIOC_MOL_GET_IPFILTER:
555     return put_user(v->ipfilter, (int *)arg);
556    
557     case SIOC_MOL_SET_IPFILTER:
558     v->ipfilter = arg;
559     return 0;
560    
561 cebix 1.1 default:
562     return -ENOIOCTLCMD;
563     }
564     }
565    
566    
567     /*
568     * Packet receiver function
569     */
570    
571 cebix 1.4 static int sheep_net_receiver(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
572 cebix 1.1 {
573     struct SheepVars *v = (struct SheepVars *)pt->data;
574 cebix 1.4 struct sk_buff *skb2;
575     int fake;
576     int multicast;
577 cebix 1.1 D(bug("sheep_net: packet received\n"));
578    
579 cebix 1.4 multicast = (skb->mac.ethernet->h_dest[0] & ETH_ADDR_MULTICAST);
580     fake = is_fake_addr(v, &skb->mac.ethernet->h_dest);
581    
582     /* Packet sent by us? Then discard */
583     if (is_fake_addr(v, &skb->mac.ethernet->h_source) || skb->protocol == PROT_MAGIC)
584     goto drop;
585    
586     /* If the packet is not meant for this host, discard it */
587     if (!is_local_addr(v, &skb->mac.ethernet->h_dest) && !multicast && !fake)
588     goto drop;
589    
590     /* Discard packets if queue gets too full */
591     if (skb_queue_len(&v->queue) > MAX_QUEUE)
592     goto drop;
593    
594     /* Apply any filters here (if fake is true, then we *know* we want this packet) */
595     if (!fake) {
596     if ((skb->protocol == htons(ETH_P_IP))
597     && (!v->ipfilter || (ntohl(skb->h.ipiph->daddr) != v->ipfilter && !multicast)))
598     goto drop;
599 cebix 1.1 }
600    
601 cebix 1.4 /* Masquerade (we are typically a clone - best to make a real copy) */
602     skb2 = skb_copy(skb, GFP_ATOMIC);
603     if (!skb2)
604     goto drop;
605     kfree_skb(skb);
606     skb = skb2;
607     masquerade(v, skb);
608 cebix 1.1
609 cebix 1.4 /* We also want the Ethernet header */
610 cebix 1.1 skb_push(skb, skb->data - skb->mac.raw);
611    
612 cebix 1.4 /* Enqueue packet */
613 cebix 1.1 skb_queue_tail(&v->queue, skb);
614    
615 cebix 1.4 /* Unblock blocked read */
616 cebix 1.1 wake_up(&v->wait);
617 cebix 1.4 return 0;
618    
619     drop:
620     kfree_skb(skb);
621 cebix 1.1 return 0;
622     }