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_netlink
  13. init_module
  14. cleanup_module

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

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