OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [net/] [ipv4/] [devinet.c] - Blame information for rev 1275

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.