root/net/netlink.c

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

DEFINITIONS

This source file includes following definitions.
  1. netlink_err
  2. netlink_donothing
  3. netlink_write
  4. netlink_read
  5. netlink_lseek
  6. netlink_open
  7. netlink_release
  8. netlink_ioctl
  9. netlink_attach
  10. netlink_detach
  11. netlink_post
  12. init_module
  13. cleanup_module
  14. 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  *      Exported do nothing receiver for one way
  66  *      interfaces.
  67  */
  68   
  69 int netlink_donothing(struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
  70 {
  71         kfree_skb(skb, FREE_READ);
  72         return -EINVAL;
  73 }
  74 
  75 /*
  76  *      Write a message to the kernel side of a communication link
  77  */
  78  
  79 static int netlink_write(struct inode * inode, struct file * file, const char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  80 {
  81         unsigned int minor = MINOR(inode->i_rdev);
  82         struct sk_buff *skb;
  83         skb=alloc_skb(count, GFP_KERNEL);
  84         memcpy_fromfs(skb_put(skb,count),buf, count);
  85         return (netlink_handler[minor])(skb);
  86 }
  87 
  88 /*
  89  *      Read a message from the kernel side of the communication link
  90  */
  91 
  92 static int netlink_read(struct inode * inode, struct file * file, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  93 {
  94         unsigned int minor = MINOR(inode->i_rdev);
  95         struct sk_buff *skb;
  96         cli();
  97         while((skb=skb_dequeue(&skb_queue_rd[minor]))==NULL)
  98         {
  99                 if(file->f_flags&O_NONBLOCK)
 100                 {
 101                         sti();
 102                         return -EWOULDBLOCK;
 103                 }
 104                 interruptible_sleep_on(&read_space_wait[minor]);
 105                 if(current->signal & ~current->blocked)
 106                 {
 107                         sti();
 108                         return -ERESTARTSYS;
 109                 }
 110         }
 111         rdq_size[minor]-=skb->len;
 112         sti();
 113         if(skb->len<count)
 114                 count=skb->len;
 115         memcpy_tofs(buf,skb->data,count);
 116         kfree_skb(skb, FREE_READ);
 117         return count;
 118 }
 119 
 120 static int netlink_lseek(struct inode * inode, struct file * file,
     /* [previous][next][first][last][top][bottom][index][help] */
 121                     off_t offset, int origin)
 122 {
 123         return -ESPIPE;
 124 }
 125 
 126 static int netlink_open(struct inode * inode, struct file * file)
     /* [previous][next][first][last][top][bottom][index][help] */
 127 {
 128         unsigned int minor = MINOR(inode->i_rdev);
 129         
 130         if(minor>=MAX_LINKS)
 131                 return -ENODEV;
 132         if(open_map&(1<<minor))
 133                 return -EBUSY;
 134         if(active_map&(1<<minor))
 135         {
 136                 open_map|=(1<<minor);
 137                 return 0;
 138         }
 139         return -EUNATCH;
 140 }
 141 
 142 static void netlink_release(struct inode * inode, struct file * file)
     /* [previous][next][first][last][top][bottom][index][help] */
 143 {
 144         unsigned int minor = MINOR(inode->i_rdev);
 145         open_map&=~(1<<minor);  
 146         MOD_DEC_USE_COUNT;
 147 }
 148 
 149 
 150 static int netlink_ioctl(struct inode *inode, struct file *file,
     /* [previous][next][first][last][top][bottom][index][help] */
 151                     unsigned int cmd, unsigned long arg)
 152 {
 153         unsigned int minor = MINOR(inode->i_rdev);
 154         int retval = 0;
 155 
 156         if (minor >= MAX_LINKS)
 157                 return -ENODEV;
 158         switch ( cmd ) {
 159                 default:
 160                         retval = -EINVAL;
 161         }
 162         return retval;
 163 }
 164 
 165 
 166 static struct file_operations netlink_fops = {
 167         netlink_lseek,
 168         netlink_read,
 169         netlink_write,
 170         NULL,           /* netlink_readdir */
 171         NULL,           /* netlink_select */
 172         netlink_ioctl,
 173         NULL,           /* netlink_mmap */
 174         netlink_open,
 175         netlink_release
 176 };
 177 
 178 /*
 179  *      We export these functions to other modules. They provide a 
 180  *      complete set of kernel non-blocking support for message
 181  *      queueing.
 182  */
 183  
 184 int netlink_attach(int unit, int (*function)(struct sk_buff *skb))
     /* [previous][next][first][last][top][bottom][index][help] */
 185 {
 186         if(unit>=MAX_LINKS)
 187                 return -ENODEV;
 188         if(active_map&(1<<unit))
 189                 return -EBUSY;
 190         active_map|=(1<<unit);
 191         netlink_handler[unit]=function;
 192         return 0;
 193 }
 194 
 195 void netlink_detach(int unit)
     /* [previous][next][first][last][top][bottom][index][help] */
 196 {
 197         active_map&=~(1<<unit);
 198         netlink_handler[unit]=netlink_err;
 199 }
 200 
 201 int netlink_post(int unit, struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
 202 {
 203         unsigned long flags;
 204         int ret=0;
 205         if(open_map&(1<<unit))
 206         {
 207                 save_flags(flags);
 208                 cli();
 209                 if(rdq_size[unit]+skb->len>MAX_QBYTES)
 210                         ret=-EWOULDBLOCK;
 211                 else
 212                 {       
 213                         skb_queue_tail(&skb_queue_rd[unit], skb);
 214                         rdq_size[unit]+=skb->len;
 215                         ret=0;
 216                         wake_up_interruptible(&read_space_wait[unit]);
 217                 }
 218                 restore_flags(flags);
 219         }
 220         return ret;
 221 }
 222 
 223 
 224 #ifdef MODULE
 225 char kernel_version[]=UTS_RELEASE;
 226 
 227 int init_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 228 {
 229         int ct;
 230         printk("Network Kernel/User communications module 0.03\n");
 231         if (register_chrdev(NET_MAJOR,"netlink",&netlink_fops)) {
 232                 printk("netlink: unable to get major %d\n", NET_MAJOR);
 233                 return -EIO;
 234         }
 235         for(ct=0;ct<MAX_LINKS;ct++)
 236         {
 237                 skb_queue_head_init(&skb_queue_rd[ct]);
 238                 netlink_handler[ct]=netlink_err;
 239         }
 240         return 0;
 241 }
 242 
 243 void cleanup_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 244 {
 245         unregister_chrdev(NET_MAJOR,"netlink");
 246 }
 247 
 248 #else
 249 
 250 void init_netlink(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 251 {
 252         int ct;
 253         /* Keep quiet on booting, we don't want too many messages */
 254         if(register_chrdev(NET_MAJOR,"netlink", &netlink_fops))
 255                 printk("netlink: unable to get major %d\n", NET_MAJOR);
 256         for(ct=0;ct<MAX_LINKS;ct++)
 257         {
 258                 skb_queue_head_init(&skb_queue_rd[ct]);
 259                 netlink_handler[ct]=netlink_err;
 260         }
 261 }
 262 
 263 #endif
 264 #endif

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