root/net/netlink.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. netlink_err
  2. netlink_write
  3. netlink_read
  4. netlink_lseek
  5. netlink_open
  6. netlink_release
  7. netlink_ioctl
  8. netlink_attach
  9. netlink_detach
  10. netlink_post
  11. init_module
  12. cleanup_module
  13. init_netlink

   1 /*
   2  * SKIPLINK     An implementation of a loadable kernel mode driver providing
   3  *              multiple kernel/user space bidirectional communications links.
   4  *
   5  *              Author:         Alan Cox <alan@cymru.net>
   6  *
   7  *              This program is free software; you can redistribute it and/or
   8  *              modify it under the terms of the GNU General Public License
   9  *              as published by the Free Software Foundation; either version
  10  *              2 of the License, or (at your option) any later version.
  11  * 
  12  */
  13 
  14 #include <linux/config.h>
  15 
  16 #if defined(CONFIG_NETLINK) || defined(MODULE)
  17 #ifdef MODULE
  18 #include <linux/module.h>
  19 #include <linux/version.h>
  20 #else
  21 #define MOD_INC_USE_COUNT
  22 #define MOD_DEC_USE_COUNT
  23 #endif
  24 
  25 #include <linux/errno.h>
  26 #include <linux/kernel.h>
  27 #include <linux/major.h>
  28 #include <linux/sched.h>
  29 #include <linux/lp.h>
  30 #include <linux/malloc.h>
  31 #include <linux/ioport.h>
  32 #include <linux/fcntl.h>
  33 #include <linux/delay.h>
  34 #include <linux/skbuff.h>
  35 
  36 #include <net/netlink.h>
  37 
  38 #include <asm/io.h>
  39 #include <asm/segment.h>
  40 #include <asm/system.h>
  41 
  42 static int (*netlink_handler[MAX_LINKS])(struct sk_buff *skb);
  43 static struct sk_buff_head skb_queue_rd[MAX_LINKS]; 
  44 static int rdq_size[MAX_LINKS];
  45 static struct wait_queue *read_space_wait[MAX_LINKS];
  46 
  47 static int active_map = 0;
  48 static int open_map = 0;
  49 
  50 /*
  51  *      Device operations
  52  */
  53  
  54 /*
  55  *      Default write handler.
  56  */
  57  
  58 static int netlink_err(struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
  59 {
  60         kfree_skb(skb, FREE_READ);
  61         return -EUNATCH;
  62 }
  63  
  64 /*
  65  *      Write a message to the kernel side of a communication link
  66  */
  67  
  68 static int netlink_write(struct inode * inode, struct file * file, const char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  69 {
  70         unsigned int minor = MINOR(inode->i_rdev);
  71         struct sk_buff *skb;
  72         skb=alloc_skb(count, GFP_KERNEL);
  73         memcpy_fromfs(skb_put(skb,count),buf, count);
  74         return (netlink_handler[minor])(skb);
  75 }
  76 
  77 /*
  78  *      Read a message from the kernel side of the communication link
  79  */
  80 
  81 static int netlink_read(struct inode * inode, struct file * file, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  82 {
  83         unsigned int minor = MINOR(inode->i_rdev);
  84         struct sk_buff *skb;
  85         cli();
  86         while((skb=skb_dequeue(&skb_queue_rd[minor]))==NULL)
  87         {
  88                 if(file->f_flags&O_NONBLOCK)
  89                 {
  90                         sti();
  91                         return -EWOULDBLOCK;
  92                 }
  93                 interruptible_sleep_on(&read_space_wait[minor]);
  94                 if(current->signal & ~current->blocked)
  95                 {
  96                         sti();
  97                         return -ERESTARTSYS;
  98                 }
  99         }
 100         rdq_size[minor]-=skb->len;
 101         sti();
 102         if(skb->len<count)
 103                 count=skb->len;
 104         memcpy_tofs(buf,skb->data,count);
 105         kfree_skb(skb, FREE_READ);
 106         return count;
 107 }
 108 
 109 static int netlink_lseek(struct inode * inode, struct file * file,
     /* [previous][next][first][last][top][bottom][index][help] */
 110                     off_t offset, int origin)
 111 {
 112         return -ESPIPE;
 113 }
 114 
 115 static int netlink_open(struct inode * inode, struct file * file)
     /* [previous][next][first][last][top][bottom][index][help] */
 116 {
 117         unsigned int minor = MINOR(inode->i_rdev);
 118         
 119         if(minor>=MAX_LINKS)
 120                 return -ENODEV;
 121         if(open_map&(1<<minor))
 122                 return -EBUSY;
 123         if(active_map&(1<<minor))
 124         {
 125                 open_map|=(1<<minor);
 126                 return 0;
 127         }
 128         return -EUNATCH;
 129 }
 130 
 131 static void netlink_release(struct inode * inode, struct file * file)
     /* [previous][next][first][last][top][bottom][index][help] */
 132 {
 133         unsigned int minor = MINOR(inode->i_rdev);
 134         open_map&=~(1<<minor);  
 135         MOD_DEC_USE_COUNT;
 136 }
 137 
 138 
 139 static int netlink_ioctl(struct inode *inode, struct file *file,
     /* [previous][next][first][last][top][bottom][index][help] */
 140                     unsigned int cmd, unsigned long arg)
 141 {
 142         unsigned int minor = MINOR(inode->i_rdev);
 143         int retval = 0;
 144 
 145         if (minor >= MAX_LINKS)
 146                 return -ENODEV;
 147         switch ( cmd ) {
 148                 default:
 149                         retval = -EINVAL;
 150         }
 151         return retval;
 152 }
 153 
 154 
 155 static struct file_operations netlink_fops = {
 156         netlink_lseek,
 157         netlink_read,
 158         netlink_write,
 159         NULL,           /* netlink_readdir */
 160         NULL,           /* netlink_select */
 161         netlink_ioctl,
 162         NULL,           /* netlink_mmap */
 163         netlink_open,
 164         netlink_release
 165 };
 166 
 167 /*
 168  *      We export these functions to other modules. They provide a 
 169  *      complete set of kernel non-blocking support for message
 170  *      queueing.
 171  */
 172  
 173 int netlink_attach(int unit, int (*function)(struct sk_buff *skb))
     /* [previous][next][first][last][top][bottom][index][help] */
 174 {
 175         if(unit>=MAX_LINKS)
 176                 return -ENODEV;
 177         if(active_map&(1<<unit))
 178                 return -EBUSY;
 179         active_map|=(1<<unit);
 180         netlink_handler[unit]=function;
 181         return 0;
 182 }
 183 
 184 void netlink_detach(int unit)
     /* [previous][next][first][last][top][bottom][index][help] */
 185 {
 186         active_map&=~(1<<unit);
 187         netlink_handler[unit]=netlink_err;
 188 }
 189 
 190 int netlink_post(int unit, struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
 191 {
 192         unsigned long flags;
 193         int ret;
 194         save_flags(flags);
 195         cli();
 196         if(rdq_size[unit]+skb->len>MAX_QBYTES)
 197                 ret=-EWOULDBLOCK;
 198         else
 199         {
 200                 skb_queue_tail(&skb_queue_rd[unit], skb);
 201                 rdq_size[unit]+=skb->len;
 202                 ret=0;
 203                 wake_up_interruptible(&read_space_wait[MAX_LINKS]);
 204         }
 205         restore_flags(flags);
 206         return ret;
 207 }
 208 
 209 
 210 #ifdef MODULE
 211 char kernel_version[]=UTS_RELEASE;
 212 
 213 int init_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 214 {
 215         int ct;
 216         printk("Network Kernel/User communications module 0.01 ALPHA\n");
 217         if (register_chrdev(NET_MAJOR,"netlink",&netlink_fops)) {
 218                 printk("netlink: unable to get major %d\n", NET_MAJOR);
 219                 return -EIO;
 220         }
 221         for(ct=0;ct<MAX_LINKS;ct++)
 222         {
 223                 skb_queue_head_init(&skb_queue_rd[ct]);
 224                 netlink_handler[ct]=netlink_err;
 225         }
 226         return 0;
 227 }
 228 
 229 void cleanup_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 230 {
 231         unregister_chrdev(NET_MAJOR,"netlink");
 232 }
 233 
 234 #else
 235 
 236 void init_netlink(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 237 {
 238         int ct;
 239         /* Keep quiet on booting, we don't want too many messages */
 240         if(register_chrdev(NET_MAJOR,"netlink", &netlink_fops))
 241                 printk("netlink: unable to get major %d\n", NET_MAJOR);
 242         for(ct=0;ct<MAX_LINKS;ct++)
 243         {
 244                 skb_queue_head_init(&skb_queue_rd[ct]);
 245                 netlink_handler[ct]=netlink_err;
 246         }
 247 }
 248 
 249 #endif
 250 #endif

/* [previous][next][first][last][top][bottom][index][help] */