ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/Linux/NetDriver/sheep_net.c
Revision: 1.11
Committed: 2004-01-12T15:54:46Z (20 years, 5 months ago) by cebix
Content type: text/plain
Branch: MAIN
CVS Tags: nigel-build-16, nigel-build-15
Changes since 1.10: +1 -1 lines
Log Message:
Happy New Year!

File Contents

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