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

# Content
1 /*
2 * sheep_net.c - Linux driver for SheepShaver/Basilisk II networking (access to raw Ethernet packets)
3 *
4 * sheep_net (C) 1999-2001 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 #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 #include <linux/in.h>
33 #include <linux/wait.h>
34 #include <net/sock.h>
35 #include <net/arp.h>
36 #include <net/ip.h>
37 #include <asm/uaccess.h>
38
39 /* 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 #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 /* 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
63 #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 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 static int sheep_net_receiver(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt);
76
77
78 /*
79 * Driver private variables
80 */
81
82 struct SheepVars {
83 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 };
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 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 };
107
108
109 /*
110 * miscdevice structure for driver initialization
111 */
112
113 static struct miscdevice sheep_net_device = {
114 SHEEP_NET_MINOR, /* minor number */
115 "sheep_net", /* name */
116 &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 /* Register driver */
131 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 /* Unregister driver */
146 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 /* Must be opened with read permissions */
162 if ((f->f_flags & O_ACCMODE) == O_WRONLY)
163 return -EPERM;
164
165 /* Allocate private variables */
166 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 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
179 /* Yes, we're open */
180 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 /* Detach from Ethernet card */
196 if (v->ether) {
197 dev_remove_pack(&v->pt);
198 sk_free(v->skt);
199 v->skt = NULL;
200 #ifdef LINUX_24
201 dev_put( v->ether );
202 #endif
203 v->ether = NULL;
204 }
205
206 /* Empty packet queue */
207 while ((skb = skb_dequeue(&v->queue)) != NULL)
208 dev_kfree_skb(skb);
209
210 /* Free private variables */
211 kfree(v);
212
213 /* Sorry, we're closed */
214 MOD_DEC_USE_COUNT;
215 return 0;
216 }
217
218
219 /*
220 * 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 * 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
294 D(bug("sheep_net: read\n"));
295
296 for (;;) {
297
298 /* Get next packet from queue */
299 skb = skb_dequeue(&v->queue);
300 if (skb != NULL || (f->f_flags & O_NONBLOCK))
301 break;
302
303 /* No packet in queue and in blocking mode, so block */
304 interruptible_sleep_on(&v->wait);
305
306 /* Signal received? Then bail out */
307 if (signal_pending(current))
308 return -EINTR;
309 }
310 if (skb == NULL)
311 return -EAGAIN;
312
313 /* Pass packet to caller */
314 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 /* Check packet size */
335 if (count < sizeof(struct ethhdr))
336 return -EINVAL;
337 if (count > 1514)
338 count = 1514;
339
340 /* Interface active? */
341 if (v->ether == NULL)
342 return count;
343
344 /* Allocate buffer for packet */
345 skb = dev_alloc_skb(count);
346 if (skb == NULL)
347 return -ENOBUFS;
348
349 /* Stuff packet in buffer */
350 p = skb_put(skb, count);
351 if (copy_from_user(p, buf, count)) {
352 kfree_skb(skb);
353 return -EFAULT;
354 }
355
356 /* Transmit packet */
357 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 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 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 /* Packets in queue? Then return */
408 if (!skb_queue_empty(&v->queue))
409 return POLLIN | POLLRDNORM;
410
411 /* Otherwise wait for packet */
412 poll_wait(f, &v->wait, wait);
413 if (!skb_queue_empty(&v->queue))
414 return POLLIN | POLLRDNORM;
415 else
416 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 /* Attach to Ethernet card
432 arg: pointer to name of Ethernet device (char[8]) */
433 case SIOCSIFLINK: {
434 char name[8];
435 int err;
436
437 /* Already attached? */
438 if (v->ether)
439 return -EBUSY;
440
441 /* Get Ethernet card name */
442 if (copy_from_user(name, (void *)arg, 8))
443 return -EFAULT;
444 name[7] = 0;
445
446 /* Find card */
447 #ifdef LINUX_24
448 v->ether = dev_get_by_name(name);
449 #else
450 dev_lock_list();
451 v->ether = dev_get(name);
452 #endif
453 if (v->ether == NULL) {
454 err = -ENODEV;
455 goto error;
456 }
457
458 /* Is it Ethernet? */
459 if (v->ether->type != ARPHRD_ETHER) {
460 err = -EINVAL;
461 goto error;
462 }
463
464 /* Remember the card's hardware address */
465 memcpy(v->eth_addr, v->ether->dev_addr, 6);
466
467 /* Allocate socket */
468 v->skt = sk_alloc(0, GFP_USER, 1);
469 if (v->skt == NULL) {
470 err = -ENOMEM;
471 goto error;
472 }
473 v->skt->dead = 1;
474
475 /* Attach packet handler */
476 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 #ifndef LINUX_24
482 dev_unlock_list();
483 #endif
484 return 0;
485
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 }
496
497 /* Get hardware address of the sheep_net module
498 arg: pointer to buffer (6 bytes) to store address */
499 case SIOCGIFADDR:
500 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 return -EFAULT;
509 return 0;
510
511 /* Add multicast address
512 arg: pointer to address (6 bytes) */
513 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 /* Remove multicast address
523 arg: pointer to address (6 bytes) */
524 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 /* Return size of first packet in queue */
534 case FIONREAD: {
535 int count = 0;
536 struct sk_buff *skb;
537 #ifdef LINUX_24
538 long flags;
539 spin_lock_irqsave(&v->queue.lock, flags);
540 #else
541 cli();
542 #endif
543 skb = skb_peek(&v->queue);
544 if (skb)
545 count = skb->len;
546 #ifdef LINUX_24
547 spin_unlock_irqrestore(&v->queue.lock, flags);
548 #else
549 sti();
550 #endif
551 return put_user(count, (int *)arg);
552 }
553
554 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 default:
562 return -ENOIOCTLCMD;
563 }
564 }
565
566
567 /*
568 * Packet receiver function
569 */
570
571 static int sheep_net_receiver(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
572 {
573 struct SheepVars *v = (struct SheepVars *)pt->data;
574 struct sk_buff *skb2;
575 int fake;
576 int multicast;
577 D(bug("sheep_net: packet received\n"));
578
579 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 }
600
601 /* 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
609 /* We also want the Ethernet header */
610 skb_push(skb, skb->data - skb->mac.raw);
611
612 /* Enqueue packet */
613 skb_queue_tail(&v->queue, skb);
614
615 /* Unblock blocked read */
616 wake_up(&v->wait);
617 return 0;
618
619 drop:
620 kfree_skb(skb);
621 return 0;
622 }