linux-bk/net/ipv4/devinet.c
<<
>>
Prefs
   1/*
   2 *      NET3    IP device support routines.
   3 *
   4 *      Version: $Id: devinet.c,v 1.44 2001/10/31 21:55:54 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
  22 *                                      lists.
  23 *              Cyrus Durgin:           updated for kmod
  24 *              Matthias Andree:        in devinet_ioctl, compare label and
  25 *                                      address (4.4BSD alias style support),
  26 *                                      fall back to comparing just the label
  27 *                                      if no match found.
  28 */
  29
  30#include <linux/config.h>
  31
  32#include <asm/uaccess.h>
  33#include <asm/system.h>
  34#include <asm/bitops.h>
  35#include <linux/module.h>
  36#include <linux/types.h>
  37#include <linux/kernel.h>
  38#include <linux/sched.h>
  39#include <linux/string.h>
  40#include <linux/mm.h>
  41#include <linux/socket.h>
  42#include <linux/sockios.h>
  43#include <linux/in.h>
  44#include <linux/errno.h>
  45#include <linux/interrupt.h>
  46#include <linux/if_ether.h>
  47#include <linux/inet.h>
  48#include <linux/netdevice.h>
  49#include <linux/etherdevice.h>
  50#include <linux/skbuff.h>
  51#include <linux/rtnetlink.h>
  52#include <linux/init.h>
  53#include <linux/notifier.h>
  54#include <linux/inetdevice.h>
  55#include <linux/igmp.h>
  56#ifdef CONFIG_SYSCTL
  57#include <linux/sysctl.h>
  58#endif
  59#include <linux/kmod.h>
  60
  61#include <net/ip.h>
  62#include <net/route.h>
  63#include <net/ip_fib.h>
  64
  65struct ipv4_devconf ipv4_devconf = {
  66        .accept_redirects = 1,
  67        .send_redirects =  1,
  68        .secure_redirects = 1,
  69        .shared_media =   1,
  70};
  71
  72static struct ipv4_devconf ipv4_devconf_dflt = {
  73        .accept_redirects =  1,
  74        .send_redirects =    1,
  75        .secure_redirects =  1,
  76        .shared_media =      1,
  77        .accept_source_route = 1,
  78};
  79
  80static void rtmsg_ifa(int event, struct in_ifaddr *);
  81
  82static struct notifier_block *inetaddr_chain;
  83static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
  84                         int destroy);
  85#ifdef CONFIG_SYSCTL
  86static void devinet_sysctl_register(struct in_device *in_dev,
  87                                    struct ipv4_devconf *p);
  88static void devinet_sysctl_unregister(struct ipv4_devconf *p);
  89#endif
  90
  91int inet_ifa_count;
  92int inet_dev_count;
  93
  94/* Locks all the inet devices. */
  95
  96rwlock_t inetdev_lock = RW_LOCK_UNLOCKED;
  97
  98static struct in_ifaddr *inet_alloc_ifa(void)
  99{
 100        struct in_ifaddr *ifa = kmalloc(sizeof(*ifa), GFP_KERNEL);
 101
 102        if (ifa) {
 103                memset(ifa, 0, sizeof(*ifa));
 104                inet_ifa_count++;
 105        }
 106
 107        return ifa;
 108}
 109
 110static __inline__ void inet_free_ifa(struct in_ifaddr *ifa)
 111{
 112        if (ifa->ifa_dev)
 113                __in_dev_put(ifa->ifa_dev);
 114        kfree(ifa);
 115        inet_ifa_count--;
 116}
 117
 118void in_dev_finish_destroy(struct in_device *idev)
 119{
 120        struct net_device *dev = idev->dev;
 121
 122        BUG_TRAP(!idev->ifa_list);
 123        BUG_TRAP(!idev->mc_list);
 124#ifdef NET_REFCNT_DEBUG
 125        printk(KERN_DEBUG "in_dev_finish_destroy: %p=%s\n",
 126               idev, dev ? dev->name : "NIL");
 127#endif
 128        dev_put(dev);
 129        if (!idev->dead)
 130                printk("Freeing alive in_device %p\n", idev);
 131        else {
 132                inet_dev_count--;
 133                kfree(idev);
 134        }
 135}
 136
 137struct in_device *inetdev_init(struct net_device *dev)
 138{
 139        struct in_device *in_dev;
 140
 141        ASSERT_RTNL();
 142
 143        in_dev = kmalloc(sizeof(*in_dev), GFP_KERNEL);
 144        if (!in_dev)
 145                goto out;
 146        memset(in_dev, 0, sizeof(*in_dev));
 147        in_dev->lock = RW_LOCK_UNLOCKED;
 148        memcpy(&in_dev->cnf, &ipv4_devconf_dflt, sizeof(in_dev->cnf));
 149        in_dev->cnf.sysctl = NULL;
 150        in_dev->dev = dev;
 151        if ((in_dev->arp_parms = neigh_parms_alloc(dev, &arp_tbl)) == NULL)
 152                goto out_kfree;
 153        inet_dev_count++;
 154        /* Reference in_dev->dev */
 155        dev_hold(dev);
 156#ifdef CONFIG_SYSCTL
 157        neigh_sysctl_register(dev, in_dev->arp_parms, NET_IPV4,
 158                              NET_IPV4_NEIGH, "ipv4");
 159#endif
 160        write_lock_bh(&inetdev_lock);
 161        dev->ip_ptr = in_dev;
 162        /* Account for reference dev->ip_ptr */
 163        in_dev_hold(in_dev);
 164        write_unlock_bh(&inetdev_lock);
 165#ifdef CONFIG_SYSCTL
 166        devinet_sysctl_register(in_dev, &in_dev->cnf);
 167#endif
 168        if (dev->flags & IFF_UP)
 169                ip_mc_up(in_dev);
 170out:
 171        return in_dev;
 172out_kfree:
 173        kfree(in_dev);
 174        in_dev = NULL;
 175        goto out;
 176}
 177
 178static void inetdev_destroy(struct in_device *in_dev)
 179{
 180        struct in_ifaddr *ifa;
 181
 182        ASSERT_RTNL();
 183
 184        in_dev->dead = 1;
 185
 186        ip_mc_destroy_dev(in_dev);
 187
 188        while ((ifa = in_dev->ifa_list) != NULL) {
 189                inet_del_ifa(in_dev, &in_dev->ifa_list, 0);
 190                inet_free_ifa(ifa);
 191        }
 192
 193#ifdef CONFIG_SYSCTL
 194        devinet_sysctl_unregister(&in_dev->cnf);
 195#endif
 196        write_lock_bh(&inetdev_lock);
 197        in_dev->dev->ip_ptr = NULL;
 198        /* in_dev_put following below will kill the in_device */
 199        write_unlock_bh(&inetdev_lock);
 200
 201#ifdef CONFIG_SYSCTL
 202        neigh_sysctl_unregister(in_dev->arp_parms);
 203#endif
 204        neigh_parms_release(&arp_tbl, in_dev->arp_parms);
 205        in_dev_put(in_dev);
 206}
 207
 208int inet_addr_onlink(struct in_device *in_dev, u32 a, u32 b)
 209{
 210        read_lock(&in_dev->lock);
 211        for_primary_ifa(in_dev) {
 212                if (inet_ifa_match(a, ifa)) {
 213                        if (!b || inet_ifa_match(b, ifa)) {
 214                                read_unlock(&in_dev->lock);
 215                                return 1;
 216                        }
 217                }
 218        } endfor_ifa(in_dev);
 219        read_unlock(&in_dev->lock);
 220        return 0;
 221}
 222
 223static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
 224                         int destroy)
 225{
 226        struct in_ifaddr *ifa1 = *ifap;
 227
 228        ASSERT_RTNL();
 229
 230        /* 1. Deleting primary ifaddr forces deletion all secondaries */
 231
 232        if (!(ifa1->ifa_flags & IFA_F_SECONDARY)) {
 233                struct in_ifaddr *ifa;
 234                struct in_ifaddr **ifap1 = &ifa1->ifa_next;
 235
 236                while ((ifa = *ifap1) != NULL) {
 237                        if (!(ifa->ifa_flags & IFA_F_SECONDARY) ||
 238                            ifa1->ifa_mask != ifa->ifa_mask ||
 239                            !inet_ifa_match(ifa1->ifa_address, ifa)) {
 240                                ifap1 = &ifa->ifa_next;
 241                                continue;
 242                        }
 243                        write_lock_bh(&in_dev->lock);
 244                        *ifap1 = ifa->ifa_next;
 245                        write_unlock_bh(&in_dev->lock);
 246
 247                        rtmsg_ifa(RTM_DELADDR, ifa);
 248                        notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa);
 249                        inet_free_ifa(ifa);
 250                }
 251        }
 252
 253        /* 2. Unlink it */
 254
 255        write_lock_bh(&in_dev->lock);
 256        *ifap = ifa1->ifa_next;
 257        write_unlock_bh(&in_dev->lock);
 258
 259        /* 3. Announce address deletion */
 260
 261        /* Send message first, then call notifier.
 262           At first sight, FIB update triggered by notifier
 263           will refer to already deleted ifaddr, that could confuse
 264           netlink listeners. It is not true: look, gated sees
 265           that route deleted and if it still thinks that ifaddr
 266           is valid, it will try to restore deleted routes... Grr.
 267           So that, this order is correct.
 268         */
 269        rtmsg_ifa(RTM_DELADDR, ifa1);
 270        notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1);
 271        if (destroy) {
 272                inet_free_ifa(ifa1);
 273
 274                if (!in_dev->ifa_list)
 275                        inetdev_destroy(in_dev);
 276        }
 277}
 278
 279static int inet_insert_ifa(struct in_ifaddr *ifa)
 280{
 281        struct in_device *in_dev = ifa->ifa_dev;
 282        struct in_ifaddr *ifa1, **ifap, **last_primary;
 283
 284        ASSERT_RTNL();
 285
 286        if (!ifa->ifa_local) {
 287                inet_free_ifa(ifa);
 288                return 0;
 289        }
 290
 291        ifa->ifa_flags &= ~IFA_F_SECONDARY;
 292        last_primary = &in_dev->ifa_list;
 293
 294        for (ifap = &in_dev->ifa_list; (ifa1 = *ifap) != NULL;
 295             ifap = &ifa1->ifa_next) {
 296                if (!(ifa1->ifa_flags & IFA_F_SECONDARY) &&
 297                    ifa->ifa_scope <= ifa1->ifa_scope)
 298                        last_primary = &ifa1->ifa_next;
 299                if (ifa1->ifa_mask == ifa->ifa_mask &&
 300                    inet_ifa_match(ifa1->ifa_address, ifa)) {
 301                        if (ifa1->ifa_local == ifa->ifa_local) {
 302                                inet_free_ifa(ifa);
 303                                return -EEXIST;
 304                        }
 305                        if (ifa1->ifa_scope != ifa->ifa_scope) {
 306                                inet_free_ifa(ifa);
 307                                return -EINVAL;
 308                        }
 309                        ifa->ifa_flags |= IFA_F_SECONDARY;
 310                }
 311        }
 312
 313        if (!(ifa->ifa_flags & IFA_F_SECONDARY)) {
 314                net_srandom(ifa->ifa_local);
 315                ifap = last_primary;
 316        }
 317
 318        ifa->ifa_next = *ifap;
 319        write_lock_bh(&in_dev->lock);
 320        *ifap = ifa;
 321        write_unlock_bh(&in_dev->lock);
 322
 323        /* Send message first, then call notifier.
 324           Notifier will trigger FIB update, so that
 325           listeners of netlink will know about new ifaddr */
 326        rtmsg_ifa(RTM_NEWADDR, ifa);
 327        notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa);
 328
 329        return 0;
 330}
 331
 332static int inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa)
 333{
 334        struct in_device *in_dev = __in_dev_get(dev);
 335
 336        ASSERT_RTNL();
 337
 338        if (!in_dev) {
 339                in_dev = inetdev_init(dev);
 340                if (!in_dev) {
 341                        inet_free_ifa(ifa);
 342                        return -ENOBUFS;
 343                }
 344        }
 345        if (ifa->ifa_dev != in_dev) {
 346                BUG_TRAP(!ifa->ifa_dev);
 347                in_dev_hold(in_dev);
 348                ifa->ifa_dev = in_dev;
 349        }
 350        if (LOOPBACK(ifa->ifa_local))
 351                ifa->ifa_scope = RT_SCOPE_HOST;
 352        return inet_insert_ifa(ifa);
 353}
 354
 355struct in_device *inetdev_by_index(int ifindex)
 356{
 357        struct net_device *dev;
 358        struct in_device *in_dev = NULL;
 359        read_lock(&dev_base_lock);
 360        dev = __dev_get_by_index(ifindex);
 361        if (dev)
 362                in_dev = in_dev_get(dev);
 363        read_unlock(&dev_base_lock);
 364        return in_dev;
 365}
 366
 367/* Called only from RTNL semaphored context. No locks. */
 368
 369struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, u32 prefix,
 370                                    u32 mask)
 371{
 372        ASSERT_RTNL();
 373
 374        for_primary_ifa(in_dev) {
 375                if (ifa->ifa_mask == mask && inet_ifa_match(prefix, ifa))
 376                        return ifa;
 377        } endfor_ifa(in_dev);
 378        return NULL;
 379}
 380
 381int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 382{
 383        struct rtattr **rta = arg;
 384        struct in_device *in_dev;
 385        struct ifaddrmsg *ifm = NLMSG_DATA(nlh);
 386        struct in_ifaddr *ifa, **ifap;
 387
 388        ASSERT_RTNL();
 389
 390        if ((in_dev = inetdev_by_index(ifm->ifa_index)) == NULL)
 391                goto out;
 392        __in_dev_put(in_dev);
 393
 394        for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
 395             ifap = &ifa->ifa_next) {
 396                if ((rta[IFA_LOCAL - 1] &&
 397                     memcmp(RTA_DATA(rta[IFA_LOCAL - 1]),
 398                            &ifa->ifa_local, 4)) ||
 399                    (rta[IFA_LABEL - 1] &&
 400                     strcmp(RTA_DATA(rta[IFA_LABEL - 1]), ifa->ifa_label)) ||
 401                    (rta[IFA_ADDRESS - 1] &&
 402                     (ifm->ifa_prefixlen != ifa->ifa_prefixlen ||
 403                      !inet_ifa_match(*(u32*)RTA_DATA(rta[IFA_ADDRESS - 1]),
 404                                      ifa))))
 405                        continue;
 406                inet_del_ifa(in_dev, ifap, 1);
 407                return 0;
 408        }
 409out:
 410        return -EADDRNOTAVAIL;
 411}
 412
 413int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 414{
 415        struct rtattr **rta = arg;
 416        struct net_device *dev;
 417        struct in_device *in_dev;
 418        struct ifaddrmsg *ifm = NLMSG_DATA(nlh);
 419        struct in_ifaddr *ifa;
 420        int rc = -EINVAL;
 421
 422        ASSERT_RTNL();
 423
 424        if (ifm->ifa_prefixlen > 32 || !rta[IFA_LOCAL - 1])
 425                goto out;
 426
 427        rc = -ENODEV;
 428        if ((dev = __dev_get_by_index(ifm->ifa_index)) == NULL)
 429                goto out;
 430
 431        rc = -ENOBUFS;
 432        if ((in_dev = __in_dev_get(dev)) == NULL) {
 433                in_dev = inetdev_init(dev);
 434                if (!in_dev)
 435                        goto out;
 436        }
 437
 438        if ((ifa = inet_alloc_ifa()) == NULL)
 439                goto out;
 440
 441        if (!rta[IFA_ADDRESS - 1])
 442                rta[IFA_ADDRESS - 1] = rta[IFA_LOCAL - 1];
 443        memcpy(&ifa->ifa_local, RTA_DATA(rta[IFA_LOCAL - 1]), 4);
 444        memcpy(&ifa->ifa_address, RTA_DATA(rta[IFA_ADDRESS - 1]), 4);
 445        ifa->ifa_prefixlen = ifm->ifa_prefixlen;
 446        ifa->ifa_mask = inet_make_mask(ifm->ifa_prefixlen);
 447        if (rta[IFA_BROADCAST - 1])
 448                memcpy(&ifa->ifa_broadcast,
 449                       RTA_DATA(rta[IFA_BROADCAST - 1]), 4);
 450        if (rta[IFA_ANYCAST - 1])
 451                memcpy(&ifa->ifa_anycast, RTA_DATA(rta[IFA_ANYCAST - 1]), 4);
 452        ifa->ifa_flags = ifm->ifa_flags;
 453        ifa->ifa_scope = ifm->ifa_scope;
 454        in_dev_hold(in_dev);
 455        ifa->ifa_dev   = in_dev;
 456        if (rta[IFA_LABEL - 1])
 457                memcpy(ifa->ifa_label, RTA_DATA(rta[IFA_LABEL - 1]), IFNAMSIZ);
 458        else
 459                memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
 460
 461        rc = inet_insert_ifa(ifa);
 462out:
 463        return rc;
 464}
 465
 466/*
 467 *      Determine a default network mask, based on the IP address.
 468 */
 469
 470static __inline__ int inet_abc_len(u32 addr)
 471{
 472        int rc = -1;    /* Something else, probably a multicast. */
 473
 474        if (ZERONET(addr))
 475                rc = 0;
 476        else {
 477                addr = ntohl(addr);
 478
 479                if (IN_CLASSA(addr))
 480                        rc = 8;
 481                else if (IN_CLASSB(addr))
 482                        rc = 16;
 483                else if (IN_CLASSC(addr))
 484                        rc = 24;
 485        }
 486
 487        return rc;
 488}
 489
 490
 491int devinet_ioctl(unsigned int cmd, void *arg)
 492{
 493        struct ifreq ifr;
 494        struct sockaddr_in sin_orig;
 495        struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr;
 496        struct in_device *in_dev;
 497        struct in_ifaddr **ifap = NULL;
 498        struct in_ifaddr *ifa = NULL;
 499        struct net_device *dev;
 500        char *colon;
 501        int ret = -EFAULT;
 502        int tryaddrmatch = 0;
 503
 504        /*
 505         *      Fetch the caller's info block into kernel space
 506         */
 507
 508        if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
 509                goto out;
 510        ifr.ifr_name[IFNAMSIZ - 1] = 0;
 511
 512        /* save original address for comparison */
 513        memcpy(&sin_orig, sin, sizeof(*sin));
 514
 515        colon = strchr(ifr.ifr_name, ':');
 516        if (colon)
 517                *colon = 0;
 518
 519#ifdef CONFIG_KMOD
 520        dev_load(ifr.ifr_name);
 521#endif
 522
 523        switch(cmd) {
 524        case SIOCGIFADDR:       /* Get interface address */
 525        case SIOCGIFBRDADDR:    /* Get the broadcast address */
 526        case SIOCGIFDSTADDR:    /* Get the destination address */
 527        case SIOCGIFNETMASK:    /* Get the netmask for the interface */
 528                /* Note that these ioctls will not sleep,
 529                   so that we do not impose a lock.
 530                   One day we will be forced to put shlock here (I mean SMP)
 531                 */
 532                tryaddrmatch = (sin_orig.sin_family == AF_INET);
 533                memset(sin, 0, sizeof(*sin));
 534                sin->sin_family = AF_INET;
 535                break;
 536
 537        case SIOCSIFFLAGS:
 538                ret = -EACCES;
 539                if (!capable(CAP_NET_ADMIN))
 540                        goto out;
 541                break;
 542        case SIOCSIFADDR:       /* Set interface address (and family) */
 543        case SIOCSIFBRDADDR:    /* Set the broadcast address */
 544        case SIOCSIFDSTADDR:    /* Set the destination address */
 545        case SIOCSIFNETMASK:    /* Set the netmask for the interface */
 546                ret = -EACCES;
 547                if (!capable(CAP_NET_ADMIN))
 548                        goto out;
 549                ret = -EINVAL;
 550                if (sin->sin_family != AF_INET)
 551                        goto out;
 552                break;
 553        default:
 554                ret = -EINVAL;
 555                goto out;
 556        }
 557
 558        rtnl_lock();
 559
 560        ret = -ENODEV;
 561        if ((dev = __dev_get_by_name(ifr.ifr_name)) == NULL)
 562                goto done;
 563
 564        if (colon)
 565                *colon = ':';
 566
 567        if ((in_dev = __in_dev_get(dev)) != NULL) {
 568                if (tryaddrmatch) {
 569                        /* Matthias Andree */
 570                        /* compare label and address (4.4BSD style) */
 571                        /* note: we only do this for a limited set of ioctls
 572                           and only if the original address family was AF_INET.
 573                           This is checked above. */
 574                        for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
 575                             ifap = &ifa->ifa_next) {
 576                                if (!strcmp(ifr.ifr_name, ifa->ifa_label) &&
 577                                    sin_orig.sin_addr.s_addr ==
 578                                                        ifa->ifa_address) {
 579                                        break; /* found */
 580                                }
 581                        }
 582                }
 583                /* we didn't get a match, maybe the application is
 584                   4.3BSD-style and passed in junk so we fall back to
 585                   comparing just the label */
 586                if (!ifa) {
 587                        for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
 588                             ifap = &ifa->ifa_next)
 589                                if (!strcmp(ifr.ifr_name, ifa->ifa_label))
 590                                        break;
 591                }
 592        }
 593
 594        ret = -EADDRNOTAVAIL;
 595        if (!ifa && cmd != SIOCSIFADDR && cmd != SIOCSIFFLAGS)
 596                goto done;
 597
 598        switch(cmd) {
 599        case SIOCGIFADDR:       /* Get interface address */
 600                sin->sin_addr.s_addr = ifa->ifa_local;
 601                goto rarok;
 602
 603        case SIOCGIFBRDADDR:    /* Get the broadcast address */
 604                sin->sin_addr.s_addr = ifa->ifa_broadcast;
 605                goto rarok;
 606
 607        case SIOCGIFDSTADDR:    /* Get the destination address */
 608                sin->sin_addr.s_addr = ifa->ifa_address;
 609                goto rarok;
 610
 611        case SIOCGIFNETMASK:    /* Get the netmask for the interface */
 612                sin->sin_addr.s_addr = ifa->ifa_mask;
 613                goto rarok;
 614
 615        case SIOCSIFFLAGS:
 616                if (colon) {
 617                        ret = -EADDRNOTAVAIL;
 618                        if (!ifa)
 619                                break;
 620                        ret = 0;
 621                        if (!(ifr.ifr_flags & IFF_UP))
 622                                inet_del_ifa(in_dev, ifap, 1);
 623                        break;
 624                }
 625                ret = dev_change_flags(dev, ifr.ifr_flags);
 626                break;
 627
 628        case SIOCSIFADDR:       /* Set interface address (and family) */
 629                ret = -EINVAL;
 630                if (inet_abc_len(sin->sin_addr.s_addr) < 0)
 631                        break;
 632
 633                if (!ifa) {
 634                        ret = -ENOBUFS;
 635                        if ((ifa = inet_alloc_ifa()) == NULL)
 636                                break;
 637                        if (colon)
 638                                memcpy(ifa->ifa_label, ifr.ifr_name, IFNAMSIZ);
 639                        else
 640                                memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
 641                } else {
 642                        ret = 0;
 643                        if (ifa->ifa_local == sin->sin_addr.s_addr)
 644                                break;
 645                        inet_del_ifa(in_dev, ifap, 0);
 646                        ifa->ifa_broadcast = 0;
 647                        ifa->ifa_anycast = 0;
 648                }
 649
 650                ifa->ifa_address = ifa->ifa_local = sin->sin_addr.s_addr;
 651
 652                if (!(dev->flags & IFF_POINTOPOINT)) {
 653                        ifa->ifa_prefixlen = inet_abc_len(ifa->ifa_address);
 654                        ifa->ifa_mask = inet_make_mask(ifa->ifa_prefixlen);
 655                        if ((dev->flags & IFF_BROADCAST) &&
 656                            ifa->ifa_prefixlen < 31)
 657                                ifa->ifa_broadcast = ifa->ifa_address |
 658                                                     ~ifa->ifa_mask;
 659                } else {
 660                        ifa->ifa_prefixlen = 32;
 661                        ifa->ifa_mask = inet_make_mask(32);
 662                }
 663                ret = inet_set_ifa(dev, ifa);
 664                break;
 665
 666        case SIOCSIFBRDADDR:    /* Set the broadcast address */
 667                ret = 0;
 668                if (ifa->ifa_broadcast != sin->sin_addr.s_addr) {
 669                        inet_del_ifa(in_dev, ifap, 0);
 670                        ifa->ifa_broadcast = sin->sin_addr.s_addr;
 671                        inet_insert_ifa(ifa);
 672                }
 673                break;
 674
 675        case SIOCSIFDSTADDR:    /* Set the destination address */
 676                ret = 0;
 677                if (ifa->ifa_address == sin->sin_addr.s_addr)
 678                        break;
 679                ret = -EINVAL;
 680                if (inet_abc_len(sin->sin_addr.s_addr) < 0)
 681                        break;
 682                ret = 0;
 683                inet_del_ifa(in_dev, ifap, 0);
 684                ifa->ifa_address = sin->sin_addr.s_addr;
 685                inet_insert_ifa(ifa);
 686                break;
 687
 688        case SIOCSIFNETMASK:    /* Set the netmask for the interface */
 689
 690                /*
 691                 *      The mask we set must be legal.
 692                 */
 693                ret = -EINVAL;
 694                if (bad_mask(sin->sin_addr.s_addr, 0))
 695                        break;
 696                ret = 0;
 697                if (ifa->ifa_mask != sin->sin_addr.s_addr) {
 698                        inet_del_ifa(in_dev, ifap, 0);
 699                        ifa->ifa_mask = sin->sin_addr.s_addr;
 700                        ifa->ifa_prefixlen = inet_mask_len(ifa->ifa_mask);
 701                        inet_insert_ifa(ifa);
 702                }
 703                break;
 704        }
 705done:
 706        rtnl_unlock();
 707out:
 708        return ret;
 709rarok:
 710        rtnl_unlock();
 711        ret = copy_to_user(arg, &ifr, sizeof(struct ifreq)) ? -EFAULT : 0;
 712        goto out;
 713}
 714
 715static int inet_gifconf(struct net_device *dev, char *buf, int len)
 716{
 717        struct in_device *in_dev = __in_dev_get(dev);
 718        struct in_ifaddr *ifa;
 719        struct ifreq ifr;
 720        int done = 0;
 721
 722        if (!in_dev || (ifa = in_dev->ifa_list) == NULL)
 723                goto out;
 724
 725        for (; ifa; ifa = ifa->ifa_next) {
 726                if (!buf) {
 727                        done += sizeof(ifr);
 728                        continue;
 729                }
 730                if (len < (int) sizeof(ifr))
 731                        break;
 732                memset(&ifr, 0, sizeof(struct ifreq));
 733                if (ifa->ifa_label)
 734                        strcpy(ifr.ifr_name, ifa->ifa_label);
 735                else
 736                        strcpy(ifr.ifr_name, dev->name);
 737
 738                (*(struct sockaddr_in *)&ifr.ifr_addr).sin_family = AF_INET;
 739                (*(struct sockaddr_in *)&ifr.ifr_addr).sin_addr.s_addr =
 740                                                                ifa->ifa_local;
 741
 742                if (copy_to_user(buf, &ifr, sizeof(struct ifreq))) {
 743                        done = -EFAULT;
 744                        break;
 745                }
 746                buf  += sizeof(struct ifreq);
 747                len  -= sizeof(struct ifreq);
 748                done += sizeof(struct ifreq);
 749        }
 750out:
 751        return done;
 752}
 753
 754u32 inet_select_addr(const struct net_device *dev, u32 dst, int scope)
 755{
 756        u32 addr = 0;
 757        struct in_device *in_dev;
 758
 759        read_lock(&inetdev_lock);
 760        in_dev = __in_dev_get(dev);
 761        if (!in_dev)
 762                goto out_unlock_inetdev;
 763
 764        read_lock(&in_dev->lock);
 765        for_primary_ifa(in_dev) {
 766                if (ifa->ifa_scope > scope)
 767                        continue;
 768                if (!dst || inet_ifa_match(dst, ifa)) {
 769                        addr = ifa->ifa_local;
 770                        break;
 771                }
 772                if (!addr)
 773                        addr = ifa->ifa_local;
 774        } endfor_ifa(in_dev);
 775        read_unlock(&in_dev->lock);
 776        read_unlock(&inetdev_lock);
 777
 778        if (addr)
 779                goto out;
 780
 781        /* Not loopback addresses on loopback should be preferred
 782           in this case. It is importnat that lo is the first interface
 783           in dev_base list.
 784         */
 785        read_lock(&dev_base_lock);
 786        read_lock(&inetdev_lock);
 787        for (dev = dev_base; dev; dev = dev->next) {
 788                if ((in_dev = __in_dev_get(dev)) == NULL)
 789                        continue;
 790
 791                read_lock(&in_dev->lock);
 792                for_primary_ifa(in_dev) {
 793                        if (ifa->ifa_scope != RT_SCOPE_LINK &&
 794                            ifa->ifa_scope <= scope) {
 795                                read_unlock(&in_dev->lock);
 796                                addr = ifa->ifa_local;
 797                                goto out_unlock_both;
 798                        }
 799                } endfor_ifa(in_dev);
 800                read_unlock(&in_dev->lock);
 801        }
 802out_unlock_both:
 803        read_unlock(&inetdev_lock);
 804        read_unlock(&dev_base_lock);
 805out:
 806        return addr;
 807out_unlock_inetdev:
 808        read_unlock(&inetdev_lock);
 809        goto out;
 810}
 811
 812/*
 813 *      Device notifier
 814 */
 815
 816int register_inetaddr_notifier(struct notifier_block *nb)
 817{
 818        return notifier_chain_register(&inetaddr_chain, nb);
 819}
 820
 821int unregister_inetaddr_notifier(struct notifier_block *nb)
 822{
 823        return notifier_chain_unregister(&inetaddr_chain, nb);
 824}
 825
 826/* Rename ifa_labels for a device name change. Make some effort to preserve existing
 827 * alias numbering and to create unique labels if possible.
 828*/
 829static void inetdev_changename(struct net_device *dev, struct in_device *in_dev)
 830{ 
 831        struct in_ifaddr *ifa;
 832        int named = 0;
 833
 834        for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) { 
 835                char old[IFNAMSIZ], *dot; 
 836
 837                memcpy(old, ifa->ifa_label, IFNAMSIZ);
 838                memcpy(ifa->ifa_label, dev->name, IFNAMSIZ); 
 839                if (named++ == 0)
 840                        continue;
 841                dot = strchr(ifa->ifa_label, ':');
 842                if (dot == NULL) { 
 843                        sprintf(old, ":%d", named); 
 844                        dot = old;
 845                }
 846                if (strlen(dot) + strlen(dev->name) < IFNAMSIZ) { 
 847                        strcat(ifa->ifa_label, dot); 
 848                } else { 
 849                        strcpy(ifa->ifa_label + (IFNAMSIZ - strlen(dot) - 1), dot); 
 850                } 
 851        }       
 852} 
 853
 854/* Called only under RTNL semaphore */
 855
 856static int inetdev_event(struct notifier_block *this, unsigned long event,
 857                         void *ptr)
 858{
 859        struct net_device *dev = ptr;
 860        struct in_device *in_dev = __in_dev_get(dev);
 861
 862        ASSERT_RTNL();
 863
 864        if (!in_dev)
 865                goto out;
 866
 867        switch (event) {
 868        case NETDEV_REGISTER:
 869                printk(KERN_DEBUG "inetdev_event: bug\n");
 870                dev->ip_ptr = NULL;
 871                break;
 872        case NETDEV_UP:
 873                if (dev->mtu < 68)
 874                        break;
 875                if (dev == &loopback_dev) {
 876                        struct in_ifaddr *ifa;
 877                        if ((ifa = inet_alloc_ifa()) != NULL) {
 878                                ifa->ifa_local =
 879                                  ifa->ifa_address = htonl(INADDR_LOOPBACK);
 880                                ifa->ifa_prefixlen = 8;
 881                                ifa->ifa_mask = inet_make_mask(8);
 882                                in_dev_hold(in_dev);
 883                                ifa->ifa_dev = in_dev;
 884                                ifa->ifa_scope = RT_SCOPE_HOST;
 885                                memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
 886                                inet_insert_ifa(ifa);
 887                        }
 888                        in_dev->cnf.no_xfrm = 1;
 889                        in_dev->cnf.no_policy = 1;
 890                }
 891                ip_mc_up(in_dev);
 892                break;
 893        case NETDEV_DOWN:
 894                ip_mc_down(in_dev);
 895                break;
 896        case NETDEV_CHANGEMTU:
 897                if (dev->mtu >= 68)
 898                        break;
 899                /* MTU falled under 68, disable IP */
 900        case NETDEV_UNREGISTER:
 901                inetdev_destroy(in_dev);
 902                break;
 903        case NETDEV_CHANGENAME:
 904                /* Do not notify about label change, this event is
 905                 * not interesting to applications using netlink.
 906                 */
 907                inetdev_changename(dev, in_dev);
 908
 909#ifdef CONFIG_SYSCTL
 910                devinet_sysctl_unregister(&in_dev->cnf);
 911                neigh_sysctl_unregister(in_dev->arp_parms);
 912                neigh_sysctl_register(dev, in_dev->arp_parms, NET_IPV4,
 913                                      NET_IPV4_NEIGH, "ipv4");
 914                devinet_sysctl_register(in_dev, &in_dev->cnf);
 915#endif
 916                break;
 917        }
 918out:
 919        return NOTIFY_DONE;
 920}
 921
 922struct notifier_block ip_netdev_notifier = {
 923        .notifier_call =inetdev_event,
 924};
 925
 926static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,
 927                            u32 pid, u32 seq, int event)
 928{
 929        struct ifaddrmsg *ifm;
 930        struct nlmsghdr  *nlh;
 931        unsigned char    *b = skb->tail;
 932
 933        nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*ifm));
 934        if (pid) nlh->nlmsg_flags |= NLM_F_MULTI;
 935        ifm = NLMSG_DATA(nlh);
 936        ifm->ifa_family = AF_INET;
 937        ifm->ifa_prefixlen = ifa->ifa_prefixlen;
 938        ifm->ifa_flags = ifa->ifa_flags|IFA_F_PERMANENT;
 939        ifm->ifa_scope = ifa->ifa_scope;
 940        ifm->ifa_index = ifa->ifa_dev->dev->ifindex;
 941        if (ifa->ifa_address)
 942                RTA_PUT(skb, IFA_ADDRESS, 4, &ifa->ifa_address);
 943        if (ifa->ifa_local)
 944                RTA_PUT(skb, IFA_LOCAL, 4, &ifa->ifa_local);
 945        if (ifa->ifa_broadcast)
 946                RTA_PUT(skb, IFA_BROADCAST, 4, &ifa->ifa_broadcast);
 947        if (ifa->ifa_anycast)
 948                RTA_PUT(skb, IFA_ANYCAST, 4, &ifa->ifa_anycast);
 949        if (ifa->ifa_label[0])
 950                RTA_PUT(skb, IFA_LABEL, IFNAMSIZ, &ifa->ifa_label);
 951        nlh->nlmsg_len = skb->tail - b;
 952        return skb->len;
 953
 954nlmsg_failure:
 955rtattr_failure:
 956        skb_trim(skb, b - skb->data);
 957        return -1;
 958}
 959
 960static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
 961{
 962        int idx, ip_idx;
 963        struct net_device *dev;
 964        struct in_device *in_dev;
 965        struct in_ifaddr *ifa;
 966        int s_ip_idx, s_idx = cb->args[0];
 967
 968        s_ip_idx = ip_idx = cb->args[1];
 969        read_lock(&dev_base_lock);
 970        for (dev = dev_base, idx = 0; dev; dev = dev->next, idx++) {
 971                if (idx < s_idx)
 972                        continue;
 973                if (idx > s_idx)
 974                        s_ip_idx = 0;
 975                read_lock(&inetdev_lock);
 976                if ((in_dev = __in_dev_get(dev)) == NULL) {
 977                        read_unlock(&inetdev_lock);
 978                        continue;
 979                }
 980                read_lock(&in_dev->lock);
 981                for (ifa = in_dev->ifa_list, ip_idx = 0; ifa;
 982                     ifa = ifa->ifa_next, ip_idx++) {
 983                        if (ip_idx < s_ip_idx)
 984                                continue;
 985                        if (inet_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid,
 986                                             cb->nlh->nlmsg_seq,
 987                                             RTM_NEWADDR) <= 0) {
 988                                read_unlock(&in_dev->lock);
 989                                read_unlock(&inetdev_lock);
 990                                goto done;
 991                        }
 992                }
 993                read_unlock(&in_dev->lock);
 994                read_unlock(&inetdev_lock);
 995        }
 996
 997done:
 998        read_unlock(&dev_base_lock);
 999        cb->args[0] = idx;
1000        cb->args[1] = ip_idx;
1001
1002        return skb->len;
1003}
1004
1005static void rtmsg_ifa(int event, struct in_ifaddr* ifa)
1006{
1007        int size = NLMSG_SPACE(sizeof(struct ifaddrmsg) + 128);
1008        struct sk_buff *skb = alloc_skb(size, GFP_KERNEL);
1009
1010        if (!skb)
1011                netlink_set_err(rtnl, 0, RTMGRP_IPV4_IFADDR, ENOBUFS);
1012        else if (inet_fill_ifaddr(skb, ifa, 0, 0, event) < 0) {
1013                kfree_skb(skb);
1014                netlink_set_err(rtnl, 0, RTMGRP_IPV4_IFADDR, EINVAL);
1015        } else {
1016                NETLINK_CB(skb).dst_groups = RTMGRP_IPV4_IFADDR;
1017                netlink_broadcast(rtnl, skb, 0, RTMGRP_IPV4_IFADDR, GFP_KERNEL);
1018        }
1019}
1020
1021static struct rtnetlink_link inet_rtnetlink_table[RTM_MAX - RTM_BASE + 1] = {
1022         [4] = { .doit   = inet_rtm_newaddr,  },
1023         [5] = { .doit   = inet_rtm_deladdr,  },
1024         [6] = { .dumpit = inet_dump_ifaddr,  },
1025         [8] = { .doit   = inet_rtm_newroute, },
1026         [9] = { .doit   = inet_rtm_delroute, },
1027        [10] = { .doit   = inet_rtm_getroute, .dumpit = inet_dump_fib, },
1028#ifdef CONFIG_IP_MULTIPLE_TABLES
1029        [16] = { .doit   = inet_rtm_newrule, },
1030        [17] = { .doit   = inet_rtm_delrule, },
1031        [18] = { .dumpit = inet_dump_rules,  },
1032#endif
1033};
1034
1035#ifdef CONFIG_SYSCTL
1036
1037void inet_forward_change(void)
1038{
1039        struct net_device *dev;
1040        int on = ipv4_devconf.forwarding;
1041
1042        ipv4_devconf.accept_redirects = !on;
1043        ipv4_devconf_dflt.forwarding = on;
1044
1045        read_lock(&dev_base_lock);
1046        for (dev = dev_base; dev; dev = dev->next) {
1047                struct in_device *in_dev;
1048                read_lock(&inetdev_lock);
1049                in_dev = __in_dev_get(dev);
1050                if (in_dev)
1051                        in_dev->cnf.forwarding = on;
1052                read_unlock(&inetdev_lock);
1053        }
1054        read_unlock(&dev_base_lock);
1055
1056        rt_cache_flush(0);
1057}
1058
1059static int devinet_sysctl_forward(ctl_table *ctl, int write,
1060                                  struct file* filp, void *buffer,
1061                                  size_t *lenp)
1062{
1063        int *valp = ctl->data;
1064        int val = *valp;
1065        int ret = proc_dointvec(ctl, write, filp, buffer, lenp);
1066
1067        if (write && *valp != val) {
1068                if (valp == &ipv4_devconf.forwarding)
1069                        inet_forward_change();
1070                else if (valp != &ipv4_devconf_dflt.forwarding)
1071                        rt_cache_flush(0);
1072        }
1073
1074        return ret;
1075}
1076
1077int ipv4_doint_and_flush(ctl_table *ctl, int write,
1078                         struct file* filp, void *buffer,
1079                         size_t *lenp)
1080{
1081        int *valp = ctl->data;
1082        int val = *valp;
1083        int ret = proc_dointvec(ctl, write, filp, buffer, lenp);
1084
1085        if (write && *valp != val)
1086                rt_cache_flush(0);
1087
1088        return ret;
1089}
1090
1091int ipv4_doint_and_flush_strategy(ctl_table *table, int *name, int nlen,
1092                                  void *oldval, size_t *oldlenp,
1093                                  void *newval, size_t newlen, 
1094                                  void **context)
1095{
1096        int *valp = table->data;
1097        int new;
1098
1099        if (!newval || !newlen)
1100                return 0;
1101
1102        if (newlen != sizeof(int))
1103                return -EINVAL;
1104
1105        if (get_user(new, (int *)newval))
1106                return -EFAULT;
1107
1108        if (new == *valp)
1109                return 0;
1110
1111        if (oldval && oldlenp) {
1112                size_t len;
1113
1114                if (get_user(len, oldlenp))
1115                        return -EFAULT;
1116
1117                if (len) {
1118                        if (len > table->maxlen)
1119                                len = table->maxlen;
1120                        if (copy_to_user(oldval, valp, len))
1121                                return -EFAULT;
1122                        if (put_user(len, oldlenp))
1123                                return -EFAULT;
1124                }
1125        }
1126
1127        *valp = new;
1128        rt_cache_flush(0);
1129        return 1;
1130}
1131
1132
1133static struct devinet_sysctl_table {
1134        struct ctl_table_header *sysctl_header;
1135        ctl_table               devinet_vars[17];
1136        ctl_table               devinet_dev[2];
1137        ctl_table               devinet_conf_dir[2];
1138        ctl_table               devinet_proto_dir[2];
1139        ctl_table               devinet_root_dir[2];
1140} devinet_sysctl = {
1141        .devinet_vars = {
1142                {
1143                        .ctl_name       = NET_IPV4_CONF_FORWARDING,
1144                        .procname       = "forwarding",
1145                        .data           = &ipv4_devconf.forwarding,
1146                        .maxlen         = sizeof(int),
1147                        .mode           = 0644,
1148                        .proc_handler   = &devinet_sysctl_forward,
1149                },
1150                {
1151                        .ctl_name       = NET_IPV4_CONF_MC_FORWARDING,
1152                        .procname       = "mc_forwarding",
1153                        .data           = &ipv4_devconf.mc_forwarding,
1154                        .maxlen         = sizeof(int),
1155                        .mode           = 0444,
1156                        .proc_handler   = &proc_dointvec,
1157                },
1158                {
1159                        .ctl_name       = NET_IPV4_CONF_ACCEPT_REDIRECTS,
1160                        .procname       = "accept_redirects",
1161                        .data           = &ipv4_devconf.accept_redirects,
1162                        .maxlen         = sizeof(int),
1163                        .mode           = 0644,
1164                        .proc_handler   = &proc_dointvec,
1165                },
1166                {
1167                        .ctl_name       = NET_IPV4_CONF_SECURE_REDIRECTS,
1168                        .procname       = "secure_redirects",
1169                        .data           = &ipv4_devconf.secure_redirects,
1170                        .maxlen         = sizeof(int),
1171                        .mode           = 0644,
1172                        .proc_handler   = &proc_dointvec,
1173                },
1174                {
1175                        .ctl_name       = NET_IPV4_CONF_SHARED_MEDIA,
1176                        .procname       = "shared_media",
1177                        .data           = &ipv4_devconf.shared_media,
1178                        .maxlen         = sizeof(int),
1179                        .mode           = 0644,
1180                        .proc_handler   = &proc_dointvec,
1181                },
1182                {
1183                        .ctl_name       = NET_IPV4_CONF_RP_FILTER,
1184                        .procname       = "rp_filter",
1185                        .data           = &ipv4_devconf.rp_filter,
1186                        .maxlen         = sizeof(int),
1187                        .mode           = 0644,
1188                        .proc_handler   = &proc_dointvec,
1189                },
1190                {
1191                        .ctl_name       = NET_IPV4_CONF_SEND_REDIRECTS,
1192                        .procname       = "send_redirects",
1193                        .data           = &ipv4_devconf.send_redirects,
1194                        .maxlen         = sizeof(int),
1195                        .mode           = 0644,
1196                        .proc_handler   = &proc_dointvec,
1197                },
1198                {
1199                        .ctl_name       = NET_IPV4_CONF_ACCEPT_SOURCE_ROUTE,
1200                        .procname       = "accept_source_route",
1201                        .data           = &ipv4_devconf.accept_source_route,
1202                        .maxlen         = sizeof(int),
1203                        .mode           = 0644,
1204                        .proc_handler   = &proc_dointvec,
1205                },
1206                {
1207                        .ctl_name       = NET_IPV4_CONF_PROXY_ARP,
1208                        .procname       = "proxy_arp",
1209                        .data           = &ipv4_devconf.proxy_arp,
1210                        .maxlen         = sizeof(int),
1211                        .mode           = 0644,
1212                        .proc_handler   = &proc_dointvec,
1213                },
1214                {
1215                        .ctl_name       = NET_IPV4_CONF_MEDIUM_ID,
1216                        .procname       = "medium_id",
1217                        .data           = &ipv4_devconf.medium_id,
1218                        .maxlen         = sizeof(int),
1219                        .mode           = 0644,
1220                        .proc_handler   = &proc_dointvec,
1221                },
1222                {
1223                        .ctl_name       = NET_IPV4_CONF_BOOTP_RELAY,
1224                        .procname       = "bootp_relay",
1225                        .data           = &ipv4_devconf.bootp_relay,
1226                        .maxlen         = sizeof(int),
1227                        .mode           = 0644,
1228                        .proc_handler   = &proc_dointvec,
1229                },
1230                {
1231                        .ctl_name       = NET_IPV4_CONF_LOG_MARTIANS,
1232                        .procname       = "log_martians",
1233                        .data           = &ipv4_devconf.log_martians,
1234                        .maxlen         = sizeof(int),
1235                        .mode           = 0644,
1236                        .proc_handler   = &proc_dointvec,
1237                },
1238                {
1239                        .ctl_name       = NET_IPV4_CONF_TAG,
1240                        .procname       = "tag",
1241                        .data           = &ipv4_devconf.tag,
1242                        .maxlen         = sizeof(int),
1243                        .mode           = 0644,
1244                        .proc_handler   = &proc_dointvec,
1245                },
1246                {
1247                        .ctl_name       = NET_IPV4_CONF_ARPFILTER,
1248                        .procname       = "arp_filter",
1249                        .data           = &ipv4_devconf.arp_filter,
1250                        .maxlen         = sizeof(int),
1251                        .mode           = 0644,
1252                        .proc_handler   = &proc_dointvec,
1253                },
1254                {
1255                        .ctl_name       = NET_IPV4_CONF_NOXFRM,
1256                        .procname       = "disable_xfrm",
1257                        .data           = &ipv4_devconf.no_xfrm,
1258                        .maxlen         = sizeof(int),
1259                        .mode           = 0644,
1260                        .proc_handler   = &ipv4_doint_and_flush,
1261                        .strategy       = &ipv4_doint_and_flush_strategy,
1262                },
1263                {
1264                        .ctl_name       = NET_IPV4_CONF_NOPOLICY,
1265                        .procname       = "disable_policy",
1266                        .data           = &ipv4_devconf.no_policy,
1267                        .maxlen         = sizeof(int),
1268                        .mode           = 0644,
1269                        .proc_handler   = &ipv4_doint_and_flush,
1270                        .strategy       = &ipv4_doint_and_flush_strategy,
1271                },
1272        },
1273        .devinet_dev = {
1274                {
1275                        .ctl_name       = NET_PROTO_CONF_ALL,
1276                        .procname       = "all",
1277                        .mode           = 0555,
1278                        .child          = devinet_sysctl.devinet_vars,
1279                },
1280        },
1281        .devinet_conf_dir = {
1282                {
1283                        .ctl_name       = NET_IPV4_CONF,
1284                        .procname       = "conf",
1285                        .mode           = 0555,
1286                        .child          = devinet_sysctl.devinet_dev,
1287                },
1288        },
1289        .devinet_proto_dir = {
1290                {
1291                        .ctl_name       = NET_IPV4,
1292                        .procname       = "ipv4",
1293                        .mode           = 0555,
1294                        .child          = devinet_sysctl.devinet_conf_dir,
1295                },
1296        },
1297        .devinet_root_dir = {
1298                {
1299                        .ctl_name       = CTL_NET,
1300                        .procname       = "net",
1301                        .mode           = 0555,
1302                        .child          = devinet_sysctl.devinet_proto_dir,
1303                },
1304        },
1305};
1306
1307static void devinet_sysctl_register(struct in_device *in_dev,
1308                                    struct ipv4_devconf *p)
1309{
1310        int i;
1311        struct net_device *dev = in_dev ? in_dev->dev : NULL;
1312        struct devinet_sysctl_table *t = kmalloc(sizeof(*t), GFP_KERNEL);
1313        char *dev_name = NULL;
1314
1315        if (!t)
1316                return;
1317        memcpy(t, &devinet_sysctl, sizeof(*t));
1318        for (i = 0; i < ARRAY_SIZE(t->devinet_vars) - 1; i++) {
1319                t->devinet_vars[i].data += (char *)p - (char *)&ipv4_devconf;
1320                t->devinet_vars[i].de = NULL;
1321        }
1322
1323        if (dev) {
1324                dev_name = dev->name; 
1325                t->devinet_dev[0].ctl_name = dev->ifindex;
1326        } else {
1327                dev_name = "default";
1328                t->devinet_dev[0].ctl_name = NET_PROTO_CONF_DEFAULT;
1329        }
1330
1331        /* 
1332         * Make a copy of dev_name, because '.procname' is regarded as const 
1333         * by sysctl and we wouldn't want anyone to change it under our feet
1334         * (see SIOCSIFNAME).
1335         */     
1336        dev_name = net_sysctl_strdup(dev_name);
1337        if (!dev_name)
1338            goto free;
1339
1340        t->devinet_dev[0].procname    = dev_name;
1341        t->devinet_dev[0].child       = t->devinet_vars;
1342        t->devinet_dev[0].de          = NULL;
1343        t->devinet_conf_dir[0].child  = t->devinet_dev;
1344        t->devinet_conf_dir[0].de     = NULL;
1345        t->devinet_proto_dir[0].child = t->devinet_conf_dir;
1346        t->devinet_proto_dir[0].de    = NULL;
1347        t->devinet_root_dir[0].child  = t->devinet_proto_dir;
1348        t->devinet_root_dir[0].de     = NULL;
1349
1350        t->sysctl_header = register_sysctl_table(t->devinet_root_dir, 0);
1351        if (!t->sysctl_header)
1352            goto free_procname;
1353
1354        p->sysctl = t;
1355        return;
1356
1357        /* error path */
1358 free_procname:
1359        kfree(dev_name);
1360 free:
1361        kfree(t);
1362        return;
1363}
1364
1365static void devinet_sysctl_unregister(struct ipv4_devconf *p)
1366{
1367        if (p->sysctl) {
1368                struct devinet_sysctl_table *t = p->sysctl;
1369                p->sysctl = NULL;
1370                unregister_sysctl_table(t->sysctl_header);
1371                kfree(t->devinet_dev[0].procname);
1372                kfree(t);
1373        }
1374}
1375#endif
1376
1377void __init devinet_init(void)
1378{
1379        register_gifconf(PF_INET, inet_gifconf);
1380        register_netdevice_notifier(&ip_netdev_notifier);
1381        rtnetlink_links[PF_INET] = inet_rtnetlink_table;
1382#ifdef CONFIG_SYSCTL
1383        devinet_sysctl.sysctl_header =
1384                register_sysctl_table(devinet_sysctl.devinet_root_dir, 0);
1385        devinet_sysctl_register(NULL, &ipv4_devconf_dflt);
1386#endif
1387}
1388
1389EXPORT_SYMBOL(devinet_ioctl);
1390EXPORT_SYMBOL(in_dev_finish_destroy);
1391EXPORT_SYMBOL(inet_select_addr);
1392EXPORT_SYMBOL(inetdev_by_index);
1393EXPORT_SYMBOL(inetdev_lock);
1394EXPORT_SYMBOL(register_inetaddr_notifier);
1395EXPORT_SYMBOL(unregister_inetaddr_notifier);
1396
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.