linux-old/net/netlink.c
<<
>>
Prefs
   1/*
   2 * NETLINK      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/malloc.h>
  21#include <linux/ioport.h>
  22#include <linux/fcntl.h>
  23#include <linux/delay.h>
  24#include <linux/interrupt.h>
  25#include <linux/skbuff.h>
  26#include <linux/init.h>
  27
  28#include <net/netlink.h>
  29
  30#include <asm/poll.h>
  31#include <asm/io.h>
  32#include <asm/uaccess.h>
  33#include <asm/system.h>
  34
  35static int (*netlink_handler[MAX_LINKS])(int minor, struct sk_buff *skb);
  36static struct sk_buff_head skb_queue_rd[MAX_LINKS]; 
  37static int rdq_size[MAX_LINKS];
  38static struct wait_queue *read_space_wait[MAX_LINKS];
  39
  40static unsigned long active_map = 0;
  41static unsigned long open_map = 0;
  42
  43/*
  44 *      Device operations
  45 */
  46 
  47/*
  48 *      Default write handler.
  49 */
  50 
  51static int netlink_err(int minor, struct sk_buff *skb)
  52{
  53        kfree_skb(skb, FREE_READ);
  54        return -EUNATCH;
  55}
  56
  57/*
  58 *      Exported do nothing receiver for one way
  59 *      interfaces.
  60 */
  61  
  62int netlink_donothing(int minor, struct sk_buff *skb)
  63{
  64        kfree_skb(skb, FREE_READ);
  65        return -EINVAL;
  66}
  67
  68static unsigned int netlink_poll(struct file *file, poll_table * wait)
  69{
  70        unsigned int mask;
  71        unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
  72
  73        poll_wait(&read_space_wait[minor], wait);
  74        mask = POLLOUT | POLLWRNORM;
  75        if (skb_peek(&skb_queue_rd[minor]))
  76                mask |= POLLIN | POLLRDNORM;
  77        return mask;
  78}
  79
  80/*
  81 *      Write a message to the kernel side of a communication link
  82 */
  83 
  84static long netlink_write(struct inode * inode, struct file * file,
  85                          const char * buf, unsigned long count)
  86{
  87        int err; 
  88        unsigned int minor = MINOR(inode->i_rdev);
  89        struct sk_buff *skb;
  90        skb=alloc_skb(count, GFP_KERNEL);
  91        err = copy_from_user(skb_put(skb,count),buf, count);
  92        return err ? -EFAULT : (netlink_handler[minor])(minor,skb);
  93}
  94
  95/*
  96 *      Read a message from the kernel side of the communication link
  97 */
  98
  99static long netlink_read(struct inode * inode, struct file * file, char * buf,
 100                         unsigned long count)
 101{
 102        int err; 
 103        unsigned int minor = MINOR(inode->i_rdev);
 104        struct sk_buff *skb;
 105        cli();
 106        while((skb=skb_dequeue(&skb_queue_rd[minor]))==NULL)
 107        {
 108                if(file->f_flags&O_NONBLOCK)
 109                {
 110                        sti();
 111                        return -EAGAIN;
 112                }
 113                interruptible_sleep_on(&read_space_wait[minor]);
 114                if(current->signal & ~current->blocked)
 115                {
 116                        sti();
 117                        return -ERESTARTSYS;
 118                }
 119        }
 120        rdq_size[minor]-=skb->len;
 121        sti();
 122        if(skb->len<count)
 123                count=skb->len;
 124        err = copy_to_user(buf,skb->data,count);
 125        kfree_skb(skb, FREE_READ);
 126        return err ? -EFAULT : count;
 127}
 128
 129static long long netlink_lseek(struct file * file, long long offset, int origin)
 130{
 131        return -ESPIPE;
 132}
 133
 134static int netlink_open(struct inode * inode, struct file * file)
 135{
 136        unsigned int minor = MINOR(inode->i_rdev);
 137        
 138        if(minor>=MAX_LINKS)
 139                return -ENODEV;
 140        if(active_map&(1<<minor))
 141        {
 142                if (file->f_mode & FMODE_READ)
 143                {
 144                        if (open_map&(1<<minor))
 145                                return -EBUSY;
 146                        open_map|=(1<<minor);
 147                }
 148                MOD_INC_USE_COUNT;
 149                return 0;
 150        }
 151        return -EUNATCH;
 152}
 153
 154static int netlink_release(struct inode * inode, struct file * file)
 155{
 156        unsigned int minor = MINOR(inode->i_rdev);
 157        if (file->f_mode & FMODE_READ)
 158                open_map&=~(1<<minor);
 159        MOD_DEC_USE_COUNT;
 160        return 0;
 161}
 162
 163
 164static int netlink_ioctl(struct inode *inode, struct file *file,
 165                    unsigned int cmd, unsigned long arg)
 166{
 167        unsigned int minor = MINOR(inode->i_rdev);
 168        int retval = 0;
 169
 170        if (minor >= MAX_LINKS)
 171                return -ENODEV;
 172        switch ( cmd ) {
 173                default:
 174                        retval = -EINVAL;
 175        }
 176        return retval;
 177}
 178
 179
 180static struct file_operations netlink_fops = {
 181        netlink_lseek,
 182        netlink_read,
 183        netlink_write,
 184        NULL,           /* netlink_readdir */
 185        netlink_poll,
 186        netlink_ioctl,
 187        NULL,           /* netlink_mmap */
 188        netlink_open,
 189        netlink_release
 190};
 191
 192/*
 193 *      We export these functions to other modules. They provide a 
 194 *      complete set of kernel non-blocking support for message
 195 *      queueing.
 196 */
 197 
 198int netlink_attach(int unit, int (*function)(int minor, struct sk_buff *skb))
 199{
 200        if(unit>=MAX_LINKS)
 201                return -ENODEV;
 202        if(active_map&(1<<unit))
 203                return -EBUSY;
 204        active_map|=(1<<unit);
 205        netlink_handler[unit]=function;
 206        return 0;
 207}
 208
 209void netlink_detach(int unit)
 210{
 211        active_map&=~(1<<unit);
 212        netlink_handler[unit]=netlink_err;
 213}
 214
 215int netlink_post(int unit, struct sk_buff *skb)
 216{
 217        unsigned long flags;
 218        int ret=-EUNATCH;
 219        if(open_map&(1<<unit))
 220        {
 221                save_flags(flags);
 222                cli();
 223                if(rdq_size[unit]+skb->len>MAX_QBYTES)
 224                        ret=-EAGAIN;
 225                else
 226                {       
 227                        skb_queue_tail(&skb_queue_rd[unit], skb);
 228                        rdq_size[unit]+=skb->len;
 229                        ret=0;
 230                        wake_up_interruptible(&read_space_wait[unit]);
 231                }
 232                restore_flags(flags);
 233        }
 234        return ret;
 235}
 236
 237
 238/*
 239 *      "High" level netlink interface. (ANK)
 240 *      
 241 *      Features:
 242 *              - standard message format.
 243 *              - pseudo-reliable delivery. Messages can be still lost, but
 244 *                user level will know that they were lost and can
 245 *                recover (f.e. gated could reread FIB and device list)
 246 *              - messages are batched.
 247 *              - if user is not attached, we do not make useless work.
 248 *
 249 *      Examples:
 250 *              - netlink_post equivalent (but with pseudo-reliable delivery)
 251 *                      ctl.nlmsg_delay = 0;
 252 *                      ctl.nlmsg_maxsize = <one message size>;
 253 *                      ....
 254 *                      msg = nlmsg_send(&ctl, ...);
 255 *                      if (msg) {
 256 *                              ... make it ...
 257 *                              nlmsg_transmit(&ctl);
 258 *                      }
 259 *
 260 *              - batched messages.
 261 *                      if nlmsg_delay==0, messages are delivered only
 262 *                      by nlmsg_transmit, or when batch is completed,
 263 *                      otherwise nlmsg_transmit is noop (only starts
 264 *                      timer)
 265 *
 266 *                      ctl.nlmsg_delay = ...;
 267 *                      ctl.nlmsg_maxsize = <one batch size>;
 268 *                      ....
 269 *                      msg = nlmsg_send(&ctl, ...);
 270 *                      if (msg)
 271 *                              ... make it ...
 272 *                      ....
 273 *                      msg = nlmsg_send(&ctl, ...);
 274 *                      if (msg)
 275 *                              ... make it ...
 276 *                      ....
 277 *                      if (ctl.nlmsg_skb)
 278 *                              nlmsg_transmit(&ctl);
 279 *
 280 */
 281
 282/*
 283 *      Try to deliver queued messages.
 284 *      If the delivery fails (netlink is not attached or congested),
 285 *      do not free skb to avoid useless new message creation.
 286 *
 287 *      Notes:
 288 *              - timer should be already stopped.
 289 *              - NET SPL.
 290 */
 291
 292void nlmsg_flush(struct nlmsg_ctl *ctl)
 293{
 294        if (ctl->nlmsg_skb == NULL)
 295                return;
 296
 297        if (netlink_post(ctl->nlmsg_unit, ctl->nlmsg_skb) == 0)
 298        {
 299                ctl->nlmsg_skb = NULL;
 300                return;
 301        }
 302
 303        ctl->nlmsg_timer.expires = jiffies + NLMSG_RECOVERY_TIMEO;
 304        ctl->nlmsg_timer.data = (unsigned long)ctl;
 305        ctl->nlmsg_timer.function = (void (*)(unsigned long))nlmsg_flush;
 306        add_timer(&ctl->nlmsg_timer);
 307        return;
 308}
 309
 310
 311/*
 312 *      Allocate room for new message. If it is impossible,
 313 *      start "overrun" mode and return NULL.
 314 *
 315 *      Notes:
 316 *              - NET SPL.
 317 */
 318
 319void* nlmsg_send(struct nlmsg_ctl *ctl, unsigned long type, int len,
 320                 unsigned long seq, unsigned long pid)
 321{
 322        struct nlmsghdr *nlh;
 323        struct sk_buff *skb;
 324        int     rlen;
 325
 326        static __inline__ void nlmsg_lost(struct nlmsg_ctl *ctl,
 327                                          unsigned long seq)
 328        {
 329                if (!ctl->nlmsg_overrun)
 330                {
 331                        ctl->nlmsg_overrun_start = seq;
 332                        ctl->nlmsg_overrun_end = seq;
 333                        ctl->nlmsg_overrun = 1;
 334                        return;
 335                }
 336                if (!ctl->nlmsg_overrun_start)
 337                        ctl->nlmsg_overrun_start = seq;
 338                if (seq)
 339                        ctl->nlmsg_overrun_end = seq;
 340        }
 341
 342        if (!(open_map&(1<<ctl->nlmsg_unit)))
 343        {
 344                nlmsg_lost(ctl, seq);
 345                return NULL;
 346        }
 347
 348        rlen = NLMSG_ALIGN(len + sizeof(struct nlmsghdr));
 349
 350        if (rlen > ctl->nlmsg_maxsize)
 351        {
 352                printk(KERN_ERR "nlmsg_send: too big message\n");
 353                return NULL;
 354        }
 355
 356        if ((skb=ctl->nlmsg_skb) == NULL || skb_tailroom(skb) < rlen)
 357        {
 358                if (skb)
 359                {
 360                        ctl->nlmsg_force++;
 361                        nlmsg_flush(ctl);
 362                        ctl->nlmsg_force--;
 363                }
 364
 365                if (ctl->nlmsg_skb ||
 366                    (skb=alloc_skb(ctl->nlmsg_maxsize, GFP_ATOMIC)) == NULL)
 367                {
 368                        printk (KERN_WARNING "nlmsg at unit %d overrunned\n", ctl->nlmsg_unit);
 369                        nlmsg_lost(ctl, seq);
 370                        return NULL;
 371                }
 372
 373                ctl->nlmsg_skb = skb;
 374
 375                if (ctl->nlmsg_overrun)
 376                {
 377                        int *seqp;
 378                        nlh = (struct nlmsghdr*)skb_put(skb, sizeof(struct nlmsghdr) + 2*sizeof(unsigned long));
 379                        nlh->nlmsg_type = NLMSG_OVERRUN;
 380                        nlh->nlmsg_len = sizeof(struct nlmsghdr) + 2*sizeof(unsigned long);
 381                        nlh->nlmsg_seq = 0;
 382                        nlh->nlmsg_pid = 0;
 383                        seqp = (int*)nlh->nlmsg_data;
 384                        seqp[0] = ctl->nlmsg_overrun_start;
 385                        seqp[1] = ctl->nlmsg_overrun_end;
 386                        ctl->nlmsg_overrun = 0;
 387                }
 388                if (ctl->nlmsg_timer.function)
 389                {
 390                        del_timer(&ctl->nlmsg_timer);
 391                        ctl->nlmsg_timer.function = NULL;
 392                }
 393                if (ctl->nlmsg_delay)
 394                {
 395                        ctl->nlmsg_timer.expires = jiffies + ctl->nlmsg_delay;
 396                        ctl->nlmsg_timer.function = (void (*)(unsigned long))nlmsg_flush;
 397                        ctl->nlmsg_timer.data = (unsigned long)ctl;
 398                        add_timer(&ctl->nlmsg_timer);
 399                }
 400        }
 401
 402        nlh = (struct nlmsghdr*)skb_put(skb, rlen);
 403        nlh->nlmsg_type = type;
 404        nlh->nlmsg_len = sizeof(struct nlmsghdr) + len;
 405        nlh->nlmsg_seq = seq;
 406        nlh->nlmsg_pid = pid;
 407        return nlh->nlmsg_data;
 408}
 409
 410/*
 411 *      Kick message queue.
 412 *      Two modes:
 413 *              - synchronous (delay==0). Messages are delivered immediately.
 414 *              - delayed. Do not deliver, but start delivery timer.
 415 */
 416
 417void nlmsg_transmit(struct nlmsg_ctl *ctl)
 418{
 419        start_bh_atomic();
 420
 421        if (!ctl->nlmsg_delay)
 422        {
 423                if (ctl->nlmsg_timer.function)
 424                {
 425                        del_timer(&ctl->nlmsg_timer);
 426                        ctl->nlmsg_timer.function = NULL;
 427                }
 428                ctl->nlmsg_force++;
 429                nlmsg_flush(ctl);
 430                ctl->nlmsg_force--;
 431                end_bh_atomic();
 432                return;
 433        }
 434        if (!ctl->nlmsg_timer.function)
 435        {
 436                ctl->nlmsg_timer.expires = jiffies + ctl->nlmsg_delay;
 437                ctl->nlmsg_timer.function = (void (*)(unsigned long))nlmsg_flush;
 438                ctl->nlmsg_timer.data = (unsigned long)ctl;
 439                add_timer(&ctl->nlmsg_timer);
 440        }
 441
 442        end_bh_atomic();
 443}
 444
 445
 446__initfunc(int init_netlink(void))
 447{
 448        int ct;
 449
 450        if(register_chrdev(NETLINK_MAJOR,"netlink", &netlink_fops)) {
 451                printk(KERN_ERR "netlink: unable to get major %d\n", NETLINK_MAJOR);
 452                return -EIO;
 453        }
 454        for(ct=0;ct<MAX_LINKS;ct++)
 455        {
 456                skb_queue_head_init(&skb_queue_rd[ct]);
 457                netlink_handler[ct]=netlink_err;
 458        }
 459        return 0;
 460}
 461
 462#ifdef MODULE
 463
 464int init_module(void)
 465{
 466        printk(KERN_INFO "Network Kernel/User communications module 0.05\n");
 467        return init_netlink();
 468}
 469
 470void cleanup_module(void)
 471{
 472        unregister_chrdev(NET_MAJOR,"netlink");
 473}
 474
 475#endif
 476
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.