ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/Linux/NetDriver/sheep_net.c
(Generate patch)

Comparing BasiliskII/src/Unix/Linux/NetDriver/sheep_net.c (file contents):
Revision 1.3 by cebix, 2001-02-02T20:52:58Z vs.
Revision 1.4 by cebix, 2001-03-18T15:41:17Z

# Line 29 | Line 29
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
# Line 42 | Line 55
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
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 < // Prototypes
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 device *dev, struct packet_type *pt);
75 > static int sheep_net_receiver(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt);
76  
77  
78   /*
# Line 62 | Line 80 | static int sheep_net_receiver(struct sk_
80   */
81  
82   struct SheepVars {
83 <        struct 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 <        struct wait_queue *wait;        // Wait queue for blocking read operations
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  
# Line 76 | Line 97 | struct SheepVars {
97   */
98  
99   static struct file_operations sheep_net_fops = {
100 <        NULL,   // llseek
101 <        sheep_net_read,
102 <        sheep_net_write,
103 <        NULL,   // readdir
104 <        sheep_net_poll,
105 <        sheep_net_ioctl,
85 <        NULL,   // mmap
86 <        sheep_net_open,
87 <        NULL,   // flush
88 <        sheep_net_release,
89 <        NULL,   // fsync
90 <        NULL,   // fasync
91 <        NULL,   // check_media_change
92 <        NULL,   // revalidate
93 <        NULL    // lock
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  
# Line 99 | Line 111 | static struct file_operations sheep_net_
111   */
112  
113   static struct miscdevice sheep_net_device = {
114 <        SHEEP_NET_MINOR,        // minor number
115 <        "sheep_net",            // name
114 >        SHEEP_NET_MINOR,        /* minor number */
115 >        "sheep_net",            /* name */
116          &sheep_net_fops,
117          NULL,
118          NULL
# Line 115 | Line 127 | int init_module(void)
127   {
128          int ret;
129  
130 <        // Register driver
130 >        /* Register driver */
131          ret = misc_register(&sheep_net_device);
132          D(bug("Sheep net driver installed\n"));
133          return ret;
# Line 130 | Line 142 | int cleanup_module(void)
142   {
143          int ret;
144  
145 <        // Unregister driver
145 >        /* Unregister driver */
146          ret = misc_deregister(&sheep_net_device);
147          D(bug("Sheep net driver removed\n"));
148          return ret;
# Line 146 | Line 158 | static int sheep_net_open(struct inode *
158          struct SheepVars *v;
159          D(bug("sheep_net: open\n"));
160  
161 <        // Must be opened with read permissions
161 >        /* Must be opened with read permissions */
162          if ((f->f_flags & O_ACCMODE) == O_WRONLY)
163                  return -EPERM;
164  
165 <        // Allocate private variables
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
179 >        /* Yes, we're open */
180          MOD_INC_USE_COUNT;
181          return 0;
182   }
# Line 173 | Line 192 | static int sheep_net_release(struct inod
192          struct sk_buff *skb;
193          D(bug("sheep_net: close\n"));
194  
195 <        // Detach from Ethernet card
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
206 >        /* Empty packet queue */
207          while ((skb = skb_dequeue(&v->queue)) != NULL)
208                  dev_kfree_skb(skb);
209  
210 <        // Free private variables
210 >        /* Free private variables */
211          kfree(v);
212  
213 <        // Sorry, we're closed
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  
# Line 202 | Line 290 | static ssize_t sheep_net_read(struct fil
290   {
291          struct SheepVars *v = (struct SheepVars *)f->private_data;
292          struct sk_buff *skb;
293 <        sigset_t sigs;
206 <        int i;
293 >
294          D(bug("sheep_net: read\n"));
295  
296          for (;;) {
297  
298 <                // Get next packet from queue
212 <                start_bh_atomic();
298 >                /* Get next packet from queue */
299                  skb = skb_dequeue(&v->queue);
214                end_bh_atomic();
300                  if (skb != NULL || (f->f_flags & O_NONBLOCK))
301                          break;
302  
303 <                // No packet in queue and in blocking mode, so block
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 <                signandsets(&sigs, &current->signal, &current->blocked);
308 <                for (i=0; i<_NSIG_WORDS; i++) {
224 <                        if (sigs.sig[i])
225 <                                return -EINTR;
226 <                }
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
313 >        /* Pass packet to caller */
314          if (count > skb->len)
315                  count = skb->len;
316          if (copy_to_user(buf, skb->data, count))
# Line 249 | Line 331 | static ssize_t sheep_net_write(struct fi
331          char *p;
332          D(bug("sheep_net: write\n"));
333  
334 <        // Check packet size
334 >        /* Check packet size */
335          if (count < sizeof(struct ethhdr))
336                  return -EINVAL;
337          if (count > 1514)
338                  count = 1514;
339  
340 <        // Interface active?
340 >        /* Interface active? */
341          if (v->ether == NULL)
342                  return count;
343  
344 <        // Allocate buffer for packet
344 >        /* Allocate buffer for packet */
345          skb = dev_alloc_skb(count);
346          if (skb == NULL)
347                  return -ENOBUFS;
348  
349 <        // Stuff packet in buffer
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
275 <        dev_lock_list();
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;
280        skb->protocol = PROT_MAGIC;     // "Magic" protocol value to recognize our packets in sheep_net_receiver()
361          skb->nh.raw = skb->h.raw = skb->data + v->ether->hard_header_len;
362 <        dev_unlock_list();
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   }
# Line 294 | Line 404 | static unsigned int sheep_net_poll(struc
404          struct SheepVars *v = (struct SheepVars *)f->private_data;
405          D(bug("sheep_net: poll\n"));
406  
407 <        // Packets in queue? Then return
408 <        start_bh_atomic();
299 <        if (!skb_queue_empty(&v->queue)) {
300 <                end_bh_atomic();
407 >        /* Packets in queue? Then return */
408 >        if (!skb_queue_empty(&v->queue))
409                  return POLLIN | POLLRDNORM;
302        }
410  
411 <        // Otherwise wait for packet
411 >        /* Otherwise wait for packet */
412          poll_wait(f, &v->wait, wait);
413 <        if (!skb_queue_empty(&v->queue)) {
307 <                end_bh_atomic();
413 >        if (!skb_queue_empty(&v->queue))
414                  return POLLIN | POLLRDNORM;
415 <        } else {
310 <                end_bh_atomic();
415 >        else
416                  return 0;
312        }
417   }
418  
419  
# Line 324 | Line 428 | static int sheep_net_ioctl(struct inode
428  
429          switch (code) {
430  
431 <                // Attach to Ethernet card
432 <                // arg: pointer to name of Ethernet device (char[8])
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?
437 >                        /* Already attached? */
438                          if (v->ether)
439                                  return -EBUSY;
440  
441 <                        // Get Ethernet card name
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
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 <                                dev_unlock_list();
455 <                                return -ENODEV;
454 >                                err = -ENODEV;
455 >                                goto error;
456                          }
457  
458 <                        // Is it Ethernet?
458 >                        /* Is it Ethernet? */
459                          if (v->ether->type != ARPHRD_ETHER) {
460 <                                v->ether = NULL;
461 <                                dev_unlock_list();
353 <                                return -EINVAL;
460 >                                err = -EINVAL;
461 >                                goto error;
462                          }
463  
464 <                        // Allocate socket
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 <                                v->ether = NULL;
471 <                                dev_unlock_list();
361 <                                return -ENOMEM;
470 >                                err = -ENOMEM;
471 >                                goto error;
472                          }
473                          v->skt->dead = 1;
474  
475 <                        // Attach packet handler
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 Ethernet card
498 <                // arg: pointer to buffer (6 bytes) to store address
497 >                /* Get hardware address of the sheep_net module
498 >                   arg: pointer to buffer (6 bytes) to store address */
499                  case SIOCGIFADDR:
500 <                        if (v->ether == NULL)
501 <                                return -ENODEV;
502 <                        if (copy_to_user((void *)arg, v->ether->dev_addr, 6))
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)
511 >                /* Add multicast address
512 >                   arg: pointer to address (6 bytes) */
513                  case SIOCADDMULTI: {
514                          char addr[6];
515                          if (v->ether == NULL)
# Line 392 | Line 519 | static int sheep_net_ioctl(struct inode
519                          return dev_mc_add(v->ether, addr, 6, 0);
520                  }
521  
522 <                // Remove multicast address
523 <                // arg: pointer to address (6 bytes)
522 >                /* Remove multicast address
523 >                   arg: pointer to address (6 bytes) */
524                  case SIOCDELMULTI: {
525                          char addr[6];
526                          if (v->ether == NULL)
# Line 403 | Line 530 | static int sheep_net_ioctl(struct inode
530                          return dev_mc_delete(v->ether, addr, 6, 0);
531                  }
532  
533 <                // Return size of first packet in queue
533 >                /* Return size of first packet in queue */
534                  case FIONREAD: {
535                          int count = 0;
536                          struct sk_buff *skb;
537 <                        start_bh_atomic();
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 <                        end_bh_atomic();
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          }
# Line 425 | Line 568 | static int sheep_net_ioctl(struct inode
568   *  Packet receiver function
569   */
570  
571 < static int sheep_net_receiver(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
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 <        // Packet sent by us? Then discard
580 <        if (skb->protocol == PROT_MAGIC) {
435 <                kfree_skb(skb);
436 <                return 0;
437 <        }
579 >        multicast = (skb->mac.ethernet->h_dest[0] & ETH_ADDR_MULTICAST);
580 >        fake = is_fake_addr(v, &skb->mac.ethernet->h_dest);
581  
582 <        // Discard packets if queue gets too full
583 <        if (skb_queue_len(&v->queue) > MAX_QUEUE) {
584 <                kfree_skb(skb);
585 <                return 0;
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 <        // We also want the Ethernet header
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
449 <        start_bh_atomic();
612 >        /* Enqueue packet */
613          skb_queue_tail(&v->queue, skb);
451        end_bh_atomic();
614  
615 <        // Unblock blocked read
615 >        /* Unblock blocked read */
616          wake_up(&v->wait);
617          return 0;
618 +
619 + drop:
620 +        kfree_skb(skb);
621 +        return 0;
622   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines