ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/Linux/NetDriver/sheep_net.c
Revision: 1.5
Committed: 2001-03-28T14:18:58Z (23 years, 8 months ago) by cebix
Content type: text/plain
Branch: MAIN
CVS Tags: snapshot-29052001, release-0_9-1
Changes since 1.4: +15 -6 lines
Log Message:
cleaned up a little

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