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

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