linux-old/net/ipv4/devinet.c
<<
>>
Prefs
   1/*
   2 *      NET3    IP device support routines.
   3 *
   4 *      Version: $Id: devinet.c,v 1.27 1999/03/25 10:04:06 davem Exp $
   5 *
   6 *              This program is free software; you can redistribute it and/or
   7 *              modify it under the terms of the GNU General Public License
   8 *              as published by the Free Software Foundation; either version
   9 *              2 of the License, or (at your option) any later version.
  10 *
  11 *      Derived from the IP parts of dev.c 1.0.19
  12 *              Authors:        Ross Biro, <bir7@leland.Stanford.Edu>
  13 *                              Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  14 *                              Mark Evans, <evansmp@uhura.aston.ac.uk>
  15 *
  16 *      Additional Authors:
  17 *              Alan Cox, <gw4pts@gw4pts.ampr.org>
  18 *              Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
  19 *
  20 *      Changes:
  21 *              Alexey Kuznetsov:       pa_* fields are replaced with ifaddr lists.
  22 *              Cyrus Durgin:           updated for kmod
  23 */
  24
  25#include <linux/config.h>
  26 
  27#include <asm/uaccess.h>
  28#include <asm/system.h>
  29#include <asm/bitops.h>
  30#include <linux/types.h>
  31#include <linux/kernel.h>
  32#include <linux/sched.h>
  33#include <linux/string.h>
  34#include <linux/mm.h>
  35#include <linux/socket.h>
  36#include <linux/sockios.h>
  37#include <linux/in.h>
  38#include <linux/errno.h>
  39#include <linux/interrupt.h>
  40#include <linux/if_ether.h>
  41#include <linux/inet.h>
  42#include <linux/netdevice.h>
  43#include <linux/etherdevice.h>
  44#include <linux/skbuff.h>
  45#include <linux/rtnetlink.h>
  46#include <linux/init.h>
  47#include <linux/notifier.h>
  48#include <linux/inetdevice.h>
  49#include <linux/igmp.h>
  50#ifdef CONFIG_SYSCTL
  51#include <linux/sysctl.h>
  52#endif
  53#ifdef CONFIG_KMOD
  54#include <linux/kmod.h>
  55#endif
  56
  57#include <net/ip.h>
  58#include <net/route.h>
  59#include <net/ip_fib.h>
  60
  61struct ipv4_devconf ipv4_devconf = { 1, 1, 1, 1, 0, };
  62static struct ipv4_devconf ipv4_devconf_dflt = { 1, 1, 1, 1, 1, };
  63
  64#ifdef CONFIG_RTNETLINK
  65static void rtmsg_ifa(int event, struct in_ifaddr *);
  66#else
  67#define rtmsg_ifa(a,b)  do { } while(0)
  68#endif
  69
  70static struct notifier_block *inetaddr_chain;
  71static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, int destroy);
  72#ifdef CONFIG_SYSCTL
  73static void devinet_sysctl_register(struct in_device *in_dev, struct ipv4_devconf *p);
  74static void devinet_sysctl_unregister(struct ipv4_devconf *p);
  75#endif
  76
  77int inet_ifa_count;
  78int inet_dev_count;
  79
  80static struct in_ifaddr * inet_alloc_ifa(void)
  81{
  82        struct in_ifaddr *ifa;
  83
  84        ifa = kmalloc(sizeof(*ifa), GFP_KERNEL);
  85        if (ifa) {
  86                memset(ifa, 0, sizeof(*ifa));
  87                inet_ifa_count++;
  88        }
  89
  90        return ifa;
  91}
  92
  93static __inline__ void inet_free_ifa(struct in_ifaddr *ifa)
  94{
  95        kfree_s(ifa, sizeof(*ifa));
  96        inet_ifa_count--;
  97}
  98
  99struct in_device *inetdev_init(struct device *dev)
 100{
 101        struct in_device *in_dev;
 102
 103        in_dev = kmalloc(sizeof(*in_dev), GFP_KERNEL);
 104        if (!in_dev)
 105                return NULL;
 106        inet_dev_count++;
 107        memset(in_dev, 0, sizeof(*in_dev));
 108        memcpy(&in_dev->cnf, &ipv4_devconf_dflt, sizeof(in_dev->cnf));
 109        in_dev->cnf.sysctl = NULL;
 110        in_dev->dev = dev;
 111        if ((in_dev->arp_parms = neigh_parms_alloc(dev, &arp_tbl)) == NULL) {
 112                kfree(in_dev);
 113                return NULL;
 114        }
 115#ifdef CONFIG_SYSCTL
 116        neigh_sysctl_register(dev, in_dev->arp_parms, NET_IPV4, NET_IPV4_NEIGH, "ipv4");
 117#endif
 118        dev->ip_ptr = in_dev;
 119#ifdef CONFIG_SYSCTL
 120        devinet_sysctl_register(in_dev, &in_dev->cnf);
 121#endif
 122        if (dev->flags&IFF_UP)
 123                ip_mc_up(in_dev);
 124        return in_dev;
 125}
 126
 127static void inetdev_destroy(struct in_device *in_dev)
 128{
 129        struct in_ifaddr *ifa;
 130
 131        ip_mc_destroy_dev(in_dev);
 132
 133        while ((ifa = in_dev->ifa_list) != NULL) {
 134                inet_del_ifa(in_dev, &in_dev->ifa_list, 0);
 135                inet_free_ifa(ifa);
 136        }
 137
 138#ifdef CONFIG_SYSCTL
 139        devinet_sysctl_unregister(&in_dev->cnf);
 140#endif
 141        in_dev->dev->ip_ptr = NULL;
 142        synchronize_bh();
 143        neigh_parms_release(&arp_tbl, in_dev->arp_parms);
 144        kfree(in_dev);
 145}
 146
 147struct in_ifaddr * inet_addr_onlink(struct in_device *in_dev, u32 a, u32 b)
 148{
 149        for_primary_ifa(in_dev) {
 150                if (inet_ifa_match(a, ifa)) {
 151                        if (!b || inet_ifa_match(b, ifa))
 152                                return ifa;
 153                }
 154        } endfor_ifa(in_dev);
 155        return NULL;
 156}
 157
 158static void
 159inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, int destroy)
 160{
 161        struct in_ifaddr *ifa1 = *ifap;
 162
 163        /* 1. Deleting primary ifaddr forces deletion all secondaries */
 164
 165        if (!(ifa1->ifa_flags&IFA_F_SECONDARY)) {
 166                struct in_ifaddr *ifa;
 167                struct in_ifaddr **ifap1 = &ifa1->ifa_next;
 168
 169                while ((ifa=*ifap1) != NULL) {
 170                        if (!(ifa->ifa_flags&IFA_F_SECONDARY) ||
 171                            ifa1->ifa_mask != ifa->ifa_mask ||
 172                            !inet_ifa_match(ifa1->ifa_address, ifa)) {
 173                                ifap1 = &ifa->ifa_next;
 174                                continue;
 175                        }
 176                        *ifap1 = ifa->ifa_next;
 177                        synchronize_bh();
 178
 179                        rtmsg_ifa(RTM_DELADDR, ifa);
 180                        notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa);
 181                        inet_free_ifa(ifa);
 182                }
 183        }
 184
 185        /* 2. Unlink it */
 186
 187        *ifap = ifa1->ifa_next;
 188        synchronize_bh();
 189
 190        /* 3. Announce address deletion */
 191
 192        /* Send message first, then call notifier.
 193           At first sight, FIB update triggered by notifier
 194           will refer to already deleted ifaddr, that could confuse
 195           netlink listeners. It is not true: look, gated sees
 196           that route deleted and if it still thinks that ifaddr
 197           is valid, it will try to restore deleted routes... Grr.
 198           So that, this order is correct.
 199         */
 200        rtmsg_ifa(RTM_DELADDR, ifa1);
 201        notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1);
 202        if (destroy) {
 203                inet_free_ifa(ifa1);
 204                if (in_dev->ifa_list == NULL)
 205                        inetdev_destroy(in_dev);
 206        }
 207}
 208
 209static int
 210inet_insert_ifa(struct in_device *in_dev, struct in_ifaddr *ifa)
 211{
 212        struct in_ifaddr *ifa1, **ifap, **last_primary;
 213
 214        if (ifa->ifa_local == 0) {
 215                inet_free_ifa(ifa);
 216                return 0;
 217        }
 218
 219        ifa->ifa_flags &= ~IFA_F_SECONDARY;
 220        last_primary = &in_dev->ifa_list;
 221
 222        for (ifap=&in_dev->ifa_list; (ifa1=*ifap)!=NULL; ifap=&ifa1->ifa_next) {
 223                if (!(ifa1->ifa_flags&IFA_F_SECONDARY) && ifa->ifa_scope <= ifa1->ifa_scope)
 224                        last_primary = &ifa1->ifa_next;
 225                if (ifa1->ifa_mask == ifa->ifa_mask && inet_ifa_match(ifa1->ifa_address, ifa)) {
 226                        if (ifa1->ifa_local == ifa->ifa_local) {
 227                                inet_free_ifa(ifa);
 228                                return -EEXIST;
 229                        }
 230                        if (ifa1->ifa_scope != ifa->ifa_scope) {
 231                                inet_free_ifa(ifa);
 232                                return -EINVAL;
 233                        }
 234                        ifa->ifa_flags |= IFA_F_SECONDARY;
 235                }
 236        }
 237
 238        if (!(ifa->ifa_flags&IFA_F_SECONDARY)) {
 239                net_srandom(ifa->ifa_local);
 240                ifap = last_primary;
 241        }
 242
 243        ifa->ifa_next = *ifap;
 244        wmb();
 245        *ifap = ifa;
 246
 247        /* Send message first, then call notifier.
 248           Notifier will trigger FIB update, so that
 249           listeners of netlink will know about new ifaddr */
 250        rtmsg_ifa(RTM_NEWADDR, ifa);
 251        notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa);
 252
 253        return 0;
 254}
 255
 256static int
 257inet_set_ifa(struct device *dev, struct in_ifaddr *ifa)
 258{
 259        struct in_device *in_dev = dev->ip_ptr;
 260
 261        if (in_dev == NULL) {
 262                in_dev = inetdev_init(dev);
 263                if (in_dev == NULL) {
 264                        inet_free_ifa(ifa);
 265                        return -ENOBUFS;
 266                }
 267        }
 268        ifa->ifa_dev = in_dev;
 269        if (LOOPBACK(ifa->ifa_local))
 270                ifa->ifa_scope = RT_SCOPE_HOST;
 271        return inet_insert_ifa(in_dev, ifa);
 272}
 273
 274struct in_device *inetdev_by_index(int ifindex)
 275{
 276        struct device *dev;
 277        dev = dev_get_by_index(ifindex);
 278        if (dev)
 279                return dev->ip_ptr;
 280        return NULL;
 281}
 282
 283struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, u32 prefix, u32 mask)
 284{
 285        for_primary_ifa(in_dev) {
 286                if (ifa->ifa_mask == mask && inet_ifa_match(prefix, ifa))
 287                        return ifa;
 288        } endfor_ifa(in_dev);
 289        return NULL;
 290}
 291
 292#ifdef CONFIG_RTNETLINK
 293
 294/* rtm_{add|del} functions are not reenterable, so that
 295   this structure can be made static
 296 */
 297
 298int
 299inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 300{
 301        struct rtattr  **rta = arg;
 302        struct in_device *in_dev;
 303        struct ifaddrmsg *ifm = NLMSG_DATA(nlh);
 304        struct in_ifaddr *ifa, **ifap;
 305
 306        if ((in_dev = inetdev_by_index(ifm->ifa_index)) == NULL)
 307                return -EADDRNOTAVAIL;
 308
 309        for (ifap=&in_dev->ifa_list; (ifa=*ifap)!=NULL; ifap=&ifa->ifa_next) {
 310                if ((rta[IFA_LOCAL-1] && memcmp(RTA_DATA(rta[IFA_LOCAL-1]), &ifa->ifa_local, 4)) ||
 311                    (rta[IFA_LABEL-1] && strcmp(RTA_DATA(rta[IFA_LABEL-1]), ifa->ifa_label)) ||
 312                    (rta[IFA_ADDRESS-1] &&
 313                     (ifm->ifa_prefixlen != ifa->ifa_prefixlen ||
 314                      !inet_ifa_match(*(u32*)RTA_DATA(rta[IFA_ADDRESS-1]), ifa))))
 315                        continue;
 316                inet_del_ifa(in_dev, ifap, 1);
 317                return 0;
 318        }
 319
 320        return -EADDRNOTAVAIL;
 321}
 322
 323int
 324inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 325{
 326        struct rtattr **rta = arg;
 327        struct device *dev;
 328        struct in_device *in_dev;
 329        struct ifaddrmsg *ifm = NLMSG_DATA(nlh);
 330        struct in_ifaddr *ifa;
 331
 332        if (ifm->ifa_prefixlen > 32 || rta[IFA_LOCAL-1] == NULL)
 333                return -EINVAL;
 334
 335        if ((dev = dev_get_by_index(ifm->ifa_index)) == NULL)
 336                return -ENODEV;
 337
 338        if ((in_dev = dev->ip_ptr) == NULL) {
 339                in_dev = inetdev_init(dev);
 340                if (!in_dev)
 341                        return -ENOBUFS;
 342        }
 343
 344        if ((ifa = inet_alloc_ifa()) == NULL)
 345                return -ENOBUFS;
 346
 347        if (rta[IFA_ADDRESS-1] == NULL)
 348                rta[IFA_ADDRESS-1] = rta[IFA_LOCAL-1];
 349        memcpy(&ifa->ifa_local, RTA_DATA(rta[IFA_LOCAL-1]), 4);
 350        memcpy(&ifa->ifa_address, RTA_DATA(rta[IFA_ADDRESS-1]), 4);
 351        ifa->ifa_prefixlen = ifm->ifa_prefixlen;
 352        ifa->ifa_mask = inet_make_mask(ifm->ifa_prefixlen);
 353        if (rta[IFA_BROADCAST-1])
 354                memcpy(&ifa->ifa_broadcast, RTA_DATA(rta[IFA_BROADCAST-1]), 4);
 355        if (rta[IFA_ANYCAST-1])
 356                memcpy(&ifa->ifa_anycast, RTA_DATA(rta[IFA_ANYCAST-1]), 4);
 357        ifa->ifa_flags = ifm->ifa_flags;
 358        ifa->ifa_scope = ifm->ifa_scope;
 359        ifa->ifa_dev = in_dev;
 360        if (rta[IFA_LABEL-1])
 361                memcpy(ifa->ifa_label, RTA_DATA(rta[IFA_LABEL-1]), IFNAMSIZ);
 362        else
 363                memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
 364
 365        return inet_insert_ifa(in_dev, ifa);
 366}
 367
 368#endif
 369
 370/* 
 371 *      Determine a default network mask, based on the IP address. 
 372 */
 373
 374static __inline__ int inet_abc_len(u32 addr)
 375{
 376        if (ZERONET(addr))
 377                return 0;
 378
 379        addr = ntohl(addr);
 380        if (IN_CLASSA(addr)) 
 381                return 8;
 382        if (IN_CLASSB(addr)) 
 383                return 16;
 384        if (IN_CLASSC(addr)) 
 385                return 24;
 386
 387        /*
 388         *      Something else, probably a multicast. 
 389         */
 390         
 391        return -1;
 392}
 393
 394
 395int devinet_ioctl(unsigned int cmd, void *arg)
 396{
 397        struct ifreq ifr;
 398        struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr;
 399        struct in_device *in_dev;
 400        struct in_ifaddr **ifap = NULL;
 401        struct in_ifaddr *ifa = NULL;
 402        struct device *dev;
 403#ifdef CONFIG_IP_ALIAS
 404        char *colon;
 405#endif
 406        int exclusive = 0;
 407        int ret = 0;
 408
 409        /*
 410         *      Fetch the caller's info block into kernel space
 411         */
 412
 413        if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
 414                return -EFAULT;
 415        ifr.ifr_name[IFNAMSIZ-1] = 0;
 416
 417#ifdef CONFIG_IP_ALIAS
 418        colon = strchr(ifr.ifr_name, ':');
 419        if (colon)
 420                *colon = 0;
 421#endif
 422
 423#ifdef CONFIG_KMOD
 424        dev_load(ifr.ifr_name);
 425#endif
 426
 427        switch(cmd) {
 428        case SIOCGIFADDR:       /* Get interface address */
 429        case SIOCGIFBRDADDR:    /* Get the broadcast address */
 430        case SIOCGIFDSTADDR:    /* Get the destination address */
 431        case SIOCGIFNETMASK:    /* Get the netmask for the interface */
 432                /* Note that this ioctls will not sleep,
 433                   so that we do not impose a lock.
 434                   One day we will be forced to put shlock here (I mean SMP)
 435                 */
 436                memset(sin, 0, sizeof(*sin));
 437                sin->sin_family = AF_INET;
 438                break;
 439
 440        case SIOCSIFFLAGS:
 441                if (!capable(CAP_NET_ADMIN))
 442                        return -EACCES;
 443                rtnl_lock();
 444                exclusive = 1;
 445                break;
 446        case SIOCSIFADDR:       /* Set interface address (and family) */
 447        case SIOCSIFBRDADDR:    /* Set the broadcast address */
 448        case SIOCSIFDSTADDR:    /* Set the destination address */
 449        case SIOCSIFNETMASK:    /* Set the netmask for the interface */
 450                if (!capable(CAP_NET_ADMIN))
 451                        return -EACCES;
 452                if (sin->sin_family != AF_INET)
 453                        return -EINVAL;
 454                rtnl_lock();
 455                exclusive = 1;
 456                break;
 457        default:
 458                return -EINVAL;
 459        }
 460
 461
 462        if ((dev = dev_get(ifr.ifr_name)) == NULL) {
 463                ret = -ENODEV;
 464                goto done;
 465        }
 466
 467#ifdef CONFIG_IP_ALIAS
 468        if (colon)
 469                *colon = ':';
 470#endif
 471
 472        if ((in_dev=dev->ip_ptr) != NULL) {
 473                for (ifap=&in_dev->ifa_list; (ifa=*ifap) != NULL; ifap=&ifa->ifa_next)
 474                        if (strcmp(ifr.ifr_name, ifa->ifa_label) == 0)
 475                                break;
 476        }
 477
 478        if (ifa == NULL && cmd != SIOCSIFADDR && cmd != SIOCSIFFLAGS) {
 479                ret = -EADDRNOTAVAIL;
 480                goto done;
 481        }
 482
 483        switch(cmd) {
 484                case SIOCGIFADDR:       /* Get interface address */
 485                        sin->sin_addr.s_addr = ifa->ifa_local;
 486                        goto rarok;
 487
 488                case SIOCGIFBRDADDR:    /* Get the broadcast address */
 489                        sin->sin_addr.s_addr = ifa->ifa_broadcast;
 490                        goto rarok;
 491
 492                case SIOCGIFDSTADDR:    /* Get the destination address */
 493                        sin->sin_addr.s_addr = ifa->ifa_address;
 494                        goto rarok;
 495
 496                case SIOCGIFNETMASK:    /* Get the netmask for the interface */
 497                        sin->sin_addr.s_addr = ifa->ifa_mask;
 498                        goto rarok;
 499
 500                case SIOCSIFFLAGS:
 501#ifdef CONFIG_IP_ALIAS
 502                        if (colon) {
 503                                if (ifa == NULL) {
 504                                        ret = -EADDRNOTAVAIL;
 505                                        break;
 506                                }
 507                                if (!(ifr.ifr_flags&IFF_UP))
 508                                        inet_del_ifa(in_dev, ifap, 1);
 509                                break;
 510                        }
 511#endif
 512                        ret = dev_change_flags(dev, ifr.ifr_flags);
 513                        break;
 514        
 515                case SIOCSIFADDR:       /* Set interface address (and family) */
 516                        if (inet_abc_len(sin->sin_addr.s_addr) < 0) {
 517                                ret = -EINVAL;
 518                                break;
 519                        }
 520
 521                        if (!ifa) {
 522                                if ((ifa = inet_alloc_ifa()) == NULL) {
 523                                        ret = -ENOBUFS;
 524                                        break;
 525                                }
 526#ifdef CONFIG_IP_ALIAS
 527                                if (colon)
 528                                        memcpy(ifa->ifa_label, ifr.ifr_name, IFNAMSIZ);
 529                                else
 530#endif
 531                                memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
 532                        } else {
 533                                ret = 0;
 534                                if (ifa->ifa_local == sin->sin_addr.s_addr)
 535                                        break;
 536                                inet_del_ifa(in_dev, ifap, 0);
 537                                ifa->ifa_broadcast = 0;
 538                                ifa->ifa_anycast = 0;
 539                        }
 540
 541                        ifa->ifa_address =
 542                        ifa->ifa_local = sin->sin_addr.s_addr;
 543
 544                        if (!(dev->flags&IFF_POINTOPOINT)) {
 545                                ifa->ifa_prefixlen = inet_abc_len(ifa->ifa_address);
 546                                ifa->ifa_mask = inet_make_mask(ifa->ifa_prefixlen);
 547                                if ((dev->flags&IFF_BROADCAST) && ifa->ifa_prefixlen < 31)
 548                                        ifa->ifa_broadcast = ifa->ifa_address|~ifa->ifa_mask;
 549                        } else {
 550                                ifa->ifa_prefixlen = 32;
 551                                ifa->ifa_mask = inet_make_mask(32);
 552                        }
 553                        ret = inet_set_ifa(dev, ifa);
 554                        break;
 555
 556                case SIOCSIFBRDADDR:    /* Set the broadcast address */
 557                        if (ifa->ifa_broadcast != sin->sin_addr.s_addr) {
 558                                inet_del_ifa(in_dev, ifap, 0);
 559                                ifa->ifa_broadcast = sin->sin_addr.s_addr;
 560                                inet_insert_ifa(in_dev, ifa);
 561                        }
 562                        break;
 563        
 564                case SIOCSIFDSTADDR:    /* Set the destination address */
 565                        if (ifa->ifa_address != sin->sin_addr.s_addr) {
 566                                if (inet_abc_len(sin->sin_addr.s_addr) < 0) {
 567                                        ret = -EINVAL;
 568                                        break;
 569                                }
 570                                inet_del_ifa(in_dev, ifap, 0);
 571                                ifa->ifa_address = sin->sin_addr.s_addr;
 572                                inet_insert_ifa(in_dev, ifa);
 573                        }
 574                        break;
 575
 576                case SIOCSIFNETMASK:    /* Set the netmask for the interface */
 577
 578                        /*
 579                         *      The mask we set must be legal.
 580                         */
 581                        if (bad_mask(sin->sin_addr.s_addr, 0)) {
 582                                ret = -EINVAL;
 583                                break;
 584                        }
 585
 586                        if (ifa->ifa_mask != sin->sin_addr.s_addr) {
 587                                inet_del_ifa(in_dev, ifap, 0);
 588                                ifa->ifa_mask = sin->sin_addr.s_addr;
 589                                ifa->ifa_prefixlen = inet_mask_len(ifa->ifa_mask);
 590                                inet_set_ifa(dev, ifa);
 591                        }
 592                        break;
 593        }
 594done:
 595        if (exclusive)
 596                rtnl_unlock();
 597        return ret;
 598
 599rarok:
 600        if (copy_to_user(arg, &ifr, sizeof(struct ifreq)))
 601                return -EFAULT;
 602        return 0;
 603}
 604
 605static int
 606inet_gifconf(struct device *dev, char *buf, int len)
 607{
 608        struct in_device *in_dev = dev->ip_ptr;
 609        struct in_ifaddr *ifa;
 610        struct ifreq ifr;
 611        int done=0;
 612
 613        if (in_dev==NULL || (ifa=in_dev->ifa_list)==NULL)
 614                return 0;
 615
 616        for ( ; ifa; ifa = ifa->ifa_next) {
 617                if (!buf) {
 618                        done += sizeof(ifr);
 619                        continue;
 620                }
 621                if (len < (int) sizeof(ifr))
 622                        return done;
 623                memset(&ifr, 0, sizeof(struct ifreq));
 624                if (ifa->ifa_label)
 625                        strcpy(ifr.ifr_name, ifa->ifa_label);
 626                else
 627                        strcpy(ifr.ifr_name, dev->name);
 628
 629                (*(struct sockaddr_in *) &ifr.ifr_addr).sin_family = AF_INET;
 630                (*(struct sockaddr_in *) &ifr.ifr_addr).sin_addr.s_addr = ifa->ifa_local;
 631
 632                if (copy_to_user(buf, &ifr, sizeof(struct ifreq)))
 633                        return -EFAULT;
 634                buf += sizeof(struct ifreq);
 635                len -= sizeof(struct ifreq);
 636                done += sizeof(struct ifreq);
 637        }
 638        return done;
 639}
 640
 641u32 inet_select_addr(struct device *dev, u32 dst, int scope)
 642{
 643        u32 addr = 0;
 644        struct in_device *in_dev = dev->ip_ptr;
 645
 646        if (in_dev == NULL)
 647                return 0;
 648
 649        for_primary_ifa(in_dev) {
 650                if (ifa->ifa_scope > scope)
 651                        continue;
 652                addr = ifa->ifa_local;
 653                if (!dst || inet_ifa_match(dst, ifa))
 654                        return addr;
 655        } endfor_ifa(in_dev);
 656        
 657        if (addr || scope >= RT_SCOPE_LINK)
 658                return addr;
 659
 660        /* Not loopback addresses on loopback should be preferred
 661           in this case. It is importnat that lo is the first interface
 662           in dev_base list.
 663         */
 664        for (dev=dev_base; dev; dev=dev->next) {
 665                if ((in_dev=dev->ip_ptr) == NULL)
 666                        continue;
 667
 668                for_primary_ifa(in_dev) {
 669                        if (ifa->ifa_scope <= scope)
 670                                return ifa->ifa_local;
 671                } endfor_ifa(in_dev);
 672        }
 673
 674        return 0;
 675}
 676
 677/*
 678 *      Device notifier
 679 */
 680
 681int register_inetaddr_notifier(struct notifier_block *nb)
 682{
 683        return notifier_chain_register(&inetaddr_chain, nb);
 684}
 685
 686int unregister_inetaddr_notifier(struct notifier_block *nb)
 687{
 688        return notifier_chain_unregister(&inetaddr_chain,nb);
 689}
 690 
 691static int inetdev_event(struct notifier_block *this, unsigned long event, void *ptr)
 692{
 693        struct device *dev = ptr;
 694        struct in_device *in_dev = dev->ip_ptr;
 695
 696        if (in_dev == NULL)
 697                return NOTIFY_DONE;
 698
 699        switch (event) {
 700        case NETDEV_REGISTER:
 701                if (in_dev)
 702                        printk(KERN_DEBUG "inetdev_event: bug\n");
 703                dev->ip_ptr = NULL;
 704                break;
 705        case NETDEV_UP:
 706                if (dev == &loopback_dev) {
 707                        struct in_ifaddr *ifa;
 708                        if ((ifa = inet_alloc_ifa()) != NULL) {
 709                                ifa->ifa_local =
 710                                ifa->ifa_address = htonl(INADDR_LOOPBACK);
 711                                ifa->ifa_prefixlen = 8;
 712                                ifa->ifa_mask = inet_make_mask(8);
 713                                ifa->ifa_dev = in_dev;
 714                                ifa->ifa_scope = RT_SCOPE_HOST;
 715                                inet_insert_ifa(in_dev, ifa);
 716                        }
 717                }
 718                ip_mc_up(in_dev);
 719                break;
 720        case NETDEV_DOWN:
 721                ip_mc_down(in_dev);
 722                break;
 723        case NETDEV_UNREGISTER:
 724                inetdev_destroy(in_dev);
 725                break;
 726        case NETDEV_CHANGENAME:
 727                if (in_dev->ifa_list) {
 728                        struct in_ifaddr *ifa;
 729                        for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next)
 730                                memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
 731                        /* Do not notify about label change, this event is
 732                           not interesting to applications using netlink.
 733                         */
 734                }
 735                break;
 736        }
 737
 738        return NOTIFY_DONE;
 739}
 740
 741struct notifier_block ip_netdev_notifier={
 742        inetdev_event,
 743        NULL,
 744        0
 745};
 746
 747#ifdef CONFIG_RTNETLINK
 748
 749static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,
 750                            u32 pid, u32 seq, int event)
 751{
 752        struct ifaddrmsg *ifm;
 753        struct nlmsghdr  *nlh;
 754        unsigned char    *b = skb->tail;
 755
 756        nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*ifm));
 757        ifm = NLMSG_DATA(nlh);
 758        ifm->ifa_family = AF_INET;
 759        ifm->ifa_prefixlen = ifa->ifa_prefixlen;
 760        ifm->ifa_flags = ifa->ifa_flags|IFA_F_PERMANENT;
 761        ifm->ifa_scope = ifa->ifa_scope;
 762        ifm->ifa_index = ifa->ifa_dev->dev->ifindex;
 763        if (ifa->ifa_address)
 764                RTA_PUT(skb, IFA_ADDRESS, 4, &ifa->ifa_address);
 765        if (ifa->ifa_local)
 766                RTA_PUT(skb, IFA_LOCAL, 4, &ifa->ifa_local);
 767        if (ifa->ifa_broadcast)
 768                RTA_PUT(skb, IFA_BROADCAST, 4, &ifa->ifa_broadcast);
 769        if (ifa->ifa_anycast)
 770                RTA_PUT(skb, IFA_ANYCAST, 4, &ifa->ifa_anycast);
 771        if (ifa->ifa_label[0])
 772                RTA_PUT(skb, IFA_LABEL, IFNAMSIZ, &ifa->ifa_label);
 773        nlh->nlmsg_len = skb->tail - b;
 774        return skb->len;
 775
 776nlmsg_failure:
 777rtattr_failure:
 778        skb_trim(skb, b - skb->data);
 779        return -1;
 780}
 781
 782static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
 783{
 784        int idx, ip_idx;
 785        int s_idx, s_ip_idx;
 786        struct device *dev;
 787        struct in_device *in_dev;
 788        struct in_ifaddr *ifa;
 789
 790        s_idx = cb->args[0];
 791        s_ip_idx = ip_idx = cb->args[1];
 792        for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
 793                if (idx < s_idx)
 794                        continue;
 795                if (idx > s_idx)
 796                        s_ip_idx = 0;
 797                if ((in_dev = dev->ip_ptr) == NULL)
 798                        continue;
 799                for (ifa = in_dev->ifa_list, ip_idx = 0; ifa;
 800                     ifa = ifa->ifa_next, ip_idx++) {
 801                        if (ip_idx < s_ip_idx)
 802                                continue;
 803                        if (inet_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid,
 804                                             cb->nlh->nlmsg_seq, RTM_NEWADDR) <= 0)
 805                                goto done;
 806                }
 807        }
 808done:
 809        cb->args[0] = idx;
 810        cb->args[1] = ip_idx;
 811
 812        return skb->len;
 813}
 814
 815static void rtmsg_ifa(int event, struct in_ifaddr * ifa)
 816{
 817        struct sk_buff *skb;
 818        int size = NLMSG_SPACE(sizeof(struct ifaddrmsg)+128);
 819
 820        skb = alloc_skb(size, GFP_KERNEL);
 821        if (!skb) {
 822                netlink_set_err(rtnl, 0, RTMGRP_IPV4_IFADDR, ENOBUFS);
 823                return;
 824        }
 825        if (inet_fill_ifaddr(skb, ifa, 0, 0, event) < 0) {
 826                kfree_skb(skb);
 827                netlink_set_err(rtnl, 0, RTMGRP_IPV4_IFADDR, EINVAL);
 828                return;
 829        }
 830        NETLINK_CB(skb).dst_groups = RTMGRP_IPV4_IFADDR;
 831        netlink_broadcast(rtnl, skb, 0, RTMGRP_IPV4_IFADDR, GFP_KERNEL);
 832}
 833
 834
 835static struct rtnetlink_link inet_rtnetlink_table[RTM_MAX-RTM_BASE+1] =
 836{
 837        { NULL,                 NULL,                   },
 838        { NULL,                 NULL,                   },
 839        { NULL,                 NULL,                   },
 840        { NULL,                 NULL,                   },
 841
 842        { inet_rtm_newaddr,     NULL,                   },
 843        { inet_rtm_deladdr,     NULL,                   },
 844        { NULL,                 inet_dump_ifaddr,       },
 845        { NULL,                 NULL,                   },
 846
 847        { inet_rtm_newroute,    NULL,                   },
 848        { inet_rtm_delroute,    NULL,                   },
 849        { inet_rtm_getroute,    inet_dump_fib,          },
 850        { NULL,                 NULL,                   },
 851
 852        { NULL,                 NULL,                   },
 853        { NULL,                 NULL,                   },
 854        { NULL,                 NULL,                   },
 855        { NULL,                 NULL,                   },
 856
 857#ifdef CONFIG_IP_MULTIPLE_TABLES
 858        { inet_rtm_newrule,     NULL,                   },
 859        { inet_rtm_delrule,     NULL,                   },
 860        { NULL,                 inet_dump_rules,        },
 861        { NULL,                 NULL,                   },
 862#else
 863        { NULL,                 NULL,                   },
 864        { NULL,                 NULL,                   },
 865        { NULL,                 NULL,                   },
 866        { NULL,                 NULL,                   },
 867#endif
 868};
 869
 870#endif /* CONFIG_RTNETLINK */
 871
 872
 873#ifdef CONFIG_SYSCTL
 874
 875void inet_forward_change()
 876{
 877        struct device *dev;
 878        int on = ipv4_devconf.forwarding;
 879
 880        ipv4_devconf.accept_redirects = !on;
 881        ipv4_devconf_dflt.forwarding = on;
 882
 883        for (dev = dev_base; dev; dev = dev->next) {
 884                struct in_device *in_dev = dev->ip_ptr;
 885                if (in_dev)
 886                        in_dev->cnf.forwarding = on;
 887        }
 888
 889        rt_cache_flush(0);
 890
 891        ip_statistics.IpForwarding = on ? 1 : 2;
 892}
 893
 894static
 895int devinet_sysctl_forward(ctl_table *ctl, int write, struct file * filp,
 896                           void *buffer, size_t *lenp)
 897{
 898        int *valp = ctl->data;
 899        int val = *valp;
 900        int ret;
 901
 902        ret = proc_dointvec(ctl, write, filp, buffer, lenp);
 903
 904        if (write && *valp != val) {
 905                if (valp == &ipv4_devconf.forwarding)
 906                        inet_forward_change();
 907                else if (valp != &ipv4_devconf_dflt.forwarding)
 908                        rt_cache_flush(0);
 909        }
 910
 911        return ret;
 912}
 913
 914static struct devinet_sysctl_table
 915{
 916        struct ctl_table_header *sysctl_header;
 917        ctl_table devinet_vars[12];
 918        ctl_table devinet_dev[2];
 919        ctl_table devinet_conf_dir[2];
 920        ctl_table devinet_proto_dir[2];
 921        ctl_table devinet_root_dir[2];
 922} devinet_sysctl = {
 923        NULL,
 924        {{NET_IPV4_CONF_FORWARDING, "forwarding",
 925         &ipv4_devconf.forwarding, sizeof(int), 0644, NULL,
 926         &devinet_sysctl_forward},
 927        {NET_IPV4_CONF_MC_FORWARDING, "mc_forwarding",
 928         &ipv4_devconf.mc_forwarding, sizeof(int), 0444, NULL,
 929         &proc_dointvec},
 930        {NET_IPV4_CONF_ACCEPT_REDIRECTS, "accept_redirects",
 931         &ipv4_devconf.accept_redirects, sizeof(int), 0644, NULL,
 932         &proc_dointvec},
 933        {NET_IPV4_CONF_SECURE_REDIRECTS, "secure_redirects",
 934         &ipv4_devconf.secure_redirects, sizeof(int), 0644, NULL,
 935         &proc_dointvec},
 936        {NET_IPV4_CONF_SHARED_MEDIA, "shared_media",
 937         &ipv4_devconf.shared_media, sizeof(int), 0644, NULL,
 938         &proc_dointvec},
 939        {NET_IPV4_CONF_RP_FILTER, "rp_filter",
 940         &ipv4_devconf.rp_filter, sizeof(int), 0644, NULL,
 941         &proc_dointvec},
 942        {NET_IPV4_CONF_SEND_REDIRECTS, "send_redirects",
 943         &ipv4_devconf.send_redirects, sizeof(int), 0644, NULL,
 944         &proc_dointvec},
 945        {NET_IPV4_CONF_ACCEPT_SOURCE_ROUTE, "accept_source_route",
 946         &ipv4_devconf.accept_source_route, sizeof(int), 0644, NULL,
 947         &proc_dointvec},
 948        {NET_IPV4_CONF_PROXY_ARP, "proxy_arp",
 949         &ipv4_devconf.proxy_arp, sizeof(int), 0644, NULL,
 950         &proc_dointvec},
 951        {NET_IPV4_CONF_BOOTP_RELAY, "bootp_relay",
 952         &ipv4_devconf.bootp_relay, sizeof(int), 0644, NULL,
 953         &proc_dointvec},
 954        {NET_IPV4_CONF_LOG_MARTIANS, "log_martians",
 955         &ipv4_devconf.log_martians, sizeof(int), 0644, NULL,
 956         &proc_dointvec},
 957         {0}},
 958
 959        {{NET_PROTO_CONF_ALL, "all", NULL, 0, 0555, devinet_sysctl.devinet_vars},{0}},
 960        {{NET_IPV4_CONF, "conf", NULL, 0, 0555, devinet_sysctl.devinet_dev},{0}},
 961        {{NET_IPV4, "ipv4", NULL, 0, 0555, devinet_sysctl.devinet_conf_dir},{0}},
 962        {{CTL_NET, "net", NULL, 0, 0555, devinet_sysctl.devinet_proto_dir},{0}}
 963};
 964
 965static void devinet_sysctl_register(struct in_device *in_dev, struct ipv4_devconf *p)
 966{
 967        int i;
 968        struct device *dev = in_dev ? in_dev->dev : NULL;
 969        struct devinet_sysctl_table *t;
 970
 971        t = kmalloc(sizeof(*t), GFP_KERNEL);
 972        if (t == NULL)
 973                return;
 974        memcpy(t, &devinet_sysctl, sizeof(*t));
 975        for (i=0; i<sizeof(t->devinet_vars)/sizeof(t->devinet_vars[0])-1; i++) {
 976                t->devinet_vars[i].data += (char*)p - (char*)&ipv4_devconf;
 977                t->devinet_vars[i].de = NULL;
 978        }
 979        if (dev) {
 980                t->devinet_dev[0].procname = dev->name;
 981                t->devinet_dev[0].ctl_name = dev->ifindex;
 982        } else {
 983                t->devinet_dev[0].procname = "default";
 984                t->devinet_dev[0].ctl_name = NET_PROTO_CONF_DEFAULT;
 985        }
 986        t->devinet_dev[0].child = t->devinet_vars;
 987        t->devinet_dev[0].de = NULL;
 988        t->devinet_conf_dir[0].child = t->devinet_dev;
 989        t->devinet_conf_dir[0].de = NULL;
 990        t->devinet_proto_dir[0].child = t->devinet_conf_dir;
 991        t->devinet_proto_dir[0].de = NULL;
 992        t->devinet_root_dir[0].child = t->devinet_proto_dir;
 993        t->devinet_root_dir[0].de = NULL;
 994
 995        t->sysctl_header = register_sysctl_table(t->devinet_root_dir, 0);
 996        if (t->sysctl_header == NULL)
 997                kfree(t);
 998        else
 999                p->sysctl = t;
1000}
1001
1002static void devinet_sysctl_unregister(struct ipv4_devconf *p)
1003{
1004        if (p->sysctl) {
1005                struct devinet_sysctl_table *t = p->sysctl;
1006                p->sysctl = NULL;
1007                unregister_sysctl_table(t->sysctl_header);
1008                kfree(t);
1009        }
1010}
1011#endif
1012
1013__initfunc(void devinet_init(void))
1014{
1015        register_gifconf(PF_INET, inet_gifconf);
1016        register_netdevice_notifier(&ip_netdev_notifier);
1017#ifdef CONFIG_RTNETLINK
1018        rtnetlink_links[PF_INET] = inet_rtnetlink_table;
1019#endif
1020#ifdef CONFIG_SYSCTL
1021        devinet_sysctl.sysctl_header =
1022                register_sysctl_table(devinet_sysctl.devinet_root_dir, 0);
1023        devinet_sysctl_register(NULL, &ipv4_devconf_dflt);
1024#endif
1025}
1026
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.