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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [net/] [ipv4/] [devinet.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
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
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
 
31
#include <asm/uaccess.h>
32
#include <asm/system.h>
33
#include <linux/bitops.h>
34
#include <linux/capability.h>
35
#include <linux/module.h>
36
#include <linux/types.h>
37
#include <linux/kernel.h>
38
#include <linux/string.h>
39
#include <linux/mm.h>
40
#include <linux/socket.h>
41
#include <linux/sockios.h>
42
#include <linux/in.h>
43
#include <linux/errno.h>
44
#include <linux/interrupt.h>
45
#include <linux/if_addr.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/init.h>
52
#include <linux/notifier.h>
53
#include <linux/inetdevice.h>
54
#include <linux/igmp.h>
55
#ifdef CONFIG_SYSCTL
56
#include <linux/sysctl.h>
57
#endif
58
#include <linux/kmod.h>
59
 
60
#include <net/arp.h>
61
#include <net/ip.h>
62
#include <net/route.h>
63
#include <net/ip_fib.h>
64
#include <net/rtnetlink.h>
65
 
66
struct ipv4_devconf ipv4_devconf = {
67
        .data = {
68
                [NET_IPV4_CONF_ACCEPT_REDIRECTS - 1] = 1,
69
                [NET_IPV4_CONF_SEND_REDIRECTS - 1] = 1,
70
                [NET_IPV4_CONF_SECURE_REDIRECTS - 1] = 1,
71
                [NET_IPV4_CONF_SHARED_MEDIA - 1] = 1,
72
        },
73
};
74
 
75
static struct ipv4_devconf ipv4_devconf_dflt = {
76
        .data = {
77
                [NET_IPV4_CONF_ACCEPT_REDIRECTS - 1] = 1,
78
                [NET_IPV4_CONF_SEND_REDIRECTS - 1] = 1,
79
                [NET_IPV4_CONF_SECURE_REDIRECTS - 1] = 1,
80
                [NET_IPV4_CONF_SHARED_MEDIA - 1] = 1,
81
                [NET_IPV4_CONF_ACCEPT_SOURCE_ROUTE - 1] = 1,
82
        },
83
};
84
 
85
#define IPV4_DEVCONF_DFLT(attr) IPV4_DEVCONF(ipv4_devconf_dflt, attr)
86
 
87
static const struct nla_policy ifa_ipv4_policy[IFA_MAX+1] = {
88
        [IFA_LOCAL]             = { .type = NLA_U32 },
89
        [IFA_ADDRESS]           = { .type = NLA_U32 },
90
        [IFA_BROADCAST]         = { .type = NLA_U32 },
91
        [IFA_ANYCAST]           = { .type = NLA_U32 },
92
        [IFA_LABEL]             = { .type = NLA_STRING, .len = IFNAMSIZ - 1 },
93
};
94
 
95
static void rtmsg_ifa(int event, struct in_ifaddr *, struct nlmsghdr *, u32);
96
 
97
static BLOCKING_NOTIFIER_HEAD(inetaddr_chain);
98
static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
99
                         int destroy);
100
#ifdef CONFIG_SYSCTL
101
static void devinet_sysctl_register(struct in_device *in_dev,
102
                                    struct ipv4_devconf *p);
103
static void devinet_sysctl_unregister(struct ipv4_devconf *p);
104
#endif
105
 
106
/* Locks all the inet devices. */
107
 
108
static struct in_ifaddr *inet_alloc_ifa(void)
109
{
110
        struct in_ifaddr *ifa = kzalloc(sizeof(*ifa), GFP_KERNEL);
111
 
112
        if (ifa) {
113
                INIT_RCU_HEAD(&ifa->rcu_head);
114
        }
115
 
116
        return ifa;
117
}
118
 
119
static void inet_rcu_free_ifa(struct rcu_head *head)
120
{
121
        struct in_ifaddr *ifa = container_of(head, struct in_ifaddr, rcu_head);
122
        if (ifa->ifa_dev)
123
                in_dev_put(ifa->ifa_dev);
124
        kfree(ifa);
125
}
126
 
127
static inline void inet_free_ifa(struct in_ifaddr *ifa)
128
{
129
        call_rcu(&ifa->rcu_head, inet_rcu_free_ifa);
130
}
131
 
132
void in_dev_finish_destroy(struct in_device *idev)
133
{
134
        struct net_device *dev = idev->dev;
135
 
136
        BUG_TRAP(!idev->ifa_list);
137
        BUG_TRAP(!idev->mc_list);
138
#ifdef NET_REFCNT_DEBUG
139
        printk(KERN_DEBUG "in_dev_finish_destroy: %p=%s\n",
140
               idev, dev ? dev->name : "NIL");
141
#endif
142
        dev_put(dev);
143
        if (!idev->dead)
144
                printk("Freeing alive in_device %p\n", idev);
145
        else {
146
                kfree(idev);
147
        }
148
}
149
 
150
static struct in_device *inetdev_init(struct net_device *dev)
151
{
152
        struct in_device *in_dev;
153
 
154
        ASSERT_RTNL();
155
 
156
        in_dev = kzalloc(sizeof(*in_dev), GFP_KERNEL);
157
        if (!in_dev)
158
                goto out;
159
        INIT_RCU_HEAD(&in_dev->rcu_head);
160
        memcpy(&in_dev->cnf, &ipv4_devconf_dflt, sizeof(in_dev->cnf));
161
        in_dev->cnf.sysctl = NULL;
162
        in_dev->dev = dev;
163
        if ((in_dev->arp_parms = neigh_parms_alloc(dev, &arp_tbl)) == NULL)
164
                goto out_kfree;
165
        /* Reference in_dev->dev */
166
        dev_hold(dev);
167
#ifdef CONFIG_SYSCTL
168
        neigh_sysctl_register(dev, in_dev->arp_parms, NET_IPV4,
169
                              NET_IPV4_NEIGH, "ipv4", NULL, NULL);
170
#endif
171
 
172
        /* Account for reference dev->ip_ptr (below) */
173
        in_dev_hold(in_dev);
174
 
175
#ifdef CONFIG_SYSCTL
176
        devinet_sysctl_register(in_dev, &in_dev->cnf);
177
#endif
178
        ip_mc_init_dev(in_dev);
179
        if (dev->flags & IFF_UP)
180
                ip_mc_up(in_dev);
181
 
182
        /* we can receive as soon as ip_ptr is set -- do this last */
183
        rcu_assign_pointer(dev->ip_ptr, in_dev);
184
out:
185
        return in_dev;
186
out_kfree:
187
        kfree(in_dev);
188
        in_dev = NULL;
189
        goto out;
190
}
191
 
192
static void in_dev_rcu_put(struct rcu_head *head)
193
{
194
        struct in_device *idev = container_of(head, struct in_device, rcu_head);
195
        in_dev_put(idev);
196
}
197
 
198
static void inetdev_destroy(struct in_device *in_dev)
199
{
200
        struct in_ifaddr *ifa;
201
        struct net_device *dev;
202
 
203
        ASSERT_RTNL();
204
 
205
        dev = in_dev->dev;
206
 
207
        in_dev->dead = 1;
208
 
209
        ip_mc_destroy_dev(in_dev);
210
 
211
        while ((ifa = in_dev->ifa_list) != NULL) {
212
                inet_del_ifa(in_dev, &in_dev->ifa_list, 0);
213
                inet_free_ifa(ifa);
214
        }
215
 
216
#ifdef CONFIG_SYSCTL
217
        devinet_sysctl_unregister(&in_dev->cnf);
218
#endif
219
 
220
        dev->ip_ptr = NULL;
221
 
222
#ifdef CONFIG_SYSCTL
223
        neigh_sysctl_unregister(in_dev->arp_parms);
224
#endif
225
        neigh_parms_release(&arp_tbl, in_dev->arp_parms);
226
        arp_ifdown(dev);
227
 
228
        call_rcu(&in_dev->rcu_head, in_dev_rcu_put);
229
}
230
 
231
int inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b)
232
{
233
        rcu_read_lock();
234
        for_primary_ifa(in_dev) {
235
                if (inet_ifa_match(a, ifa)) {
236
                        if (!b || inet_ifa_match(b, ifa)) {
237
                                rcu_read_unlock();
238
                                return 1;
239
                        }
240
                }
241
        } endfor_ifa(in_dev);
242
        rcu_read_unlock();
243
        return 0;
244
}
245
 
246
static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
247
                         int destroy, struct nlmsghdr *nlh, u32 pid)
248
{
249
        struct in_ifaddr *promote = NULL;
250
        struct in_ifaddr *ifa, *ifa1 = *ifap;
251
        struct in_ifaddr *last_prim = in_dev->ifa_list;
252
        struct in_ifaddr *prev_prom = NULL;
253
        int do_promote = IN_DEV_PROMOTE_SECONDARIES(in_dev);
254
 
255
        ASSERT_RTNL();
256
 
257
        /* 1. Deleting primary ifaddr forces deletion all secondaries
258
         * unless alias promotion is set
259
         **/
260
 
261
        if (!(ifa1->ifa_flags & IFA_F_SECONDARY)) {
262
                struct in_ifaddr **ifap1 = &ifa1->ifa_next;
263
 
264
                while ((ifa = *ifap1) != NULL) {
265
                        if (!(ifa->ifa_flags & IFA_F_SECONDARY) &&
266
                            ifa1->ifa_scope <= ifa->ifa_scope)
267
                                last_prim = ifa;
268
 
269
                        if (!(ifa->ifa_flags & IFA_F_SECONDARY) ||
270
                            ifa1->ifa_mask != ifa->ifa_mask ||
271
                            !inet_ifa_match(ifa1->ifa_address, ifa)) {
272
                                ifap1 = &ifa->ifa_next;
273
                                prev_prom = ifa;
274
                                continue;
275
                        }
276
 
277
                        if (!do_promote) {
278
                                *ifap1 = ifa->ifa_next;
279
 
280
                                rtmsg_ifa(RTM_DELADDR, ifa, nlh, pid);
281
                                blocking_notifier_call_chain(&inetaddr_chain,
282
                                                NETDEV_DOWN, ifa);
283
                                inet_free_ifa(ifa);
284
                        } else {
285
                                promote = ifa;
286
                                break;
287
                        }
288
                }
289
        }
290
 
291
        /* 2. Unlink it */
292
 
293
        *ifap = ifa1->ifa_next;
294
 
295
        /* 3. Announce address deletion */
296
 
297
        /* Send message first, then call notifier.
298
           At first sight, FIB update triggered by notifier
299
           will refer to already deleted ifaddr, that could confuse
300
           netlink listeners. It is not true: look, gated sees
301
           that route deleted and if it still thinks that ifaddr
302
           is valid, it will try to restore deleted routes... Grr.
303
           So that, this order is correct.
304
         */
305
        rtmsg_ifa(RTM_DELADDR, ifa1, nlh, pid);
306
        blocking_notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1);
307
 
308
        if (promote) {
309
 
310
                if (prev_prom) {
311
                        prev_prom->ifa_next = promote->ifa_next;
312
                        promote->ifa_next = last_prim->ifa_next;
313
                        last_prim->ifa_next = promote;
314
                }
315
 
316
                promote->ifa_flags &= ~IFA_F_SECONDARY;
317
                rtmsg_ifa(RTM_NEWADDR, promote, nlh, pid);
318
                blocking_notifier_call_chain(&inetaddr_chain,
319
                                NETDEV_UP, promote);
320
                for (ifa = promote->ifa_next; ifa; ifa = ifa->ifa_next) {
321
                        if (ifa1->ifa_mask != ifa->ifa_mask ||
322
                            !inet_ifa_match(ifa1->ifa_address, ifa))
323
                                        continue;
324
                        fib_add_ifaddr(ifa);
325
                }
326
 
327
        }
328
        if (destroy)
329
                inet_free_ifa(ifa1);
330
}
331
 
332
static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
333
                         int destroy)
334
{
335
        __inet_del_ifa(in_dev, ifap, destroy, NULL, 0);
336
}
337
 
338
static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh,
339
                             u32 pid)
340
{
341
        struct in_device *in_dev = ifa->ifa_dev;
342
        struct in_ifaddr *ifa1, **ifap, **last_primary;
343
 
344
        ASSERT_RTNL();
345
 
346
        if (!ifa->ifa_local) {
347
                inet_free_ifa(ifa);
348
                return 0;
349
        }
350
 
351
        ifa->ifa_flags &= ~IFA_F_SECONDARY;
352
        last_primary = &in_dev->ifa_list;
353
 
354
        for (ifap = &in_dev->ifa_list; (ifa1 = *ifap) != NULL;
355
             ifap = &ifa1->ifa_next) {
356
                if (!(ifa1->ifa_flags & IFA_F_SECONDARY) &&
357
                    ifa->ifa_scope <= ifa1->ifa_scope)
358
                        last_primary = &ifa1->ifa_next;
359
                if (ifa1->ifa_mask == ifa->ifa_mask &&
360
                    inet_ifa_match(ifa1->ifa_address, ifa)) {
361
                        if (ifa1->ifa_local == ifa->ifa_local) {
362
                                inet_free_ifa(ifa);
363
                                return -EEXIST;
364
                        }
365
                        if (ifa1->ifa_scope != ifa->ifa_scope) {
366
                                inet_free_ifa(ifa);
367
                                return -EINVAL;
368
                        }
369
                        ifa->ifa_flags |= IFA_F_SECONDARY;
370
                }
371
        }
372
 
373
        if (!(ifa->ifa_flags & IFA_F_SECONDARY)) {
374
                net_srandom(ifa->ifa_local);
375
                ifap = last_primary;
376
        }
377
 
378
        ifa->ifa_next = *ifap;
379
        *ifap = ifa;
380
 
381
        /* Send message first, then call notifier.
382
           Notifier will trigger FIB update, so that
383
           listeners of netlink will know about new ifaddr */
384
        rtmsg_ifa(RTM_NEWADDR, ifa, nlh, pid);
385
        blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa);
386
 
387
        return 0;
388
}
389
 
390
static int inet_insert_ifa(struct in_ifaddr *ifa)
391
{
392
        return __inet_insert_ifa(ifa, NULL, 0);
393
}
394
 
395
static int inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa)
396
{
397
        struct in_device *in_dev = __in_dev_get_rtnl(dev);
398
 
399
        ASSERT_RTNL();
400
 
401
        if (!in_dev) {
402
                inet_free_ifa(ifa);
403
                return -ENOBUFS;
404
        }
405
        ipv4_devconf_setall(in_dev);
406
        if (ifa->ifa_dev != in_dev) {
407
                BUG_TRAP(!ifa->ifa_dev);
408
                in_dev_hold(in_dev);
409
                ifa->ifa_dev = in_dev;
410
        }
411
        if (LOOPBACK(ifa->ifa_local))
412
                ifa->ifa_scope = RT_SCOPE_HOST;
413
        return inet_insert_ifa(ifa);
414
}
415
 
416
struct in_device *inetdev_by_index(int ifindex)
417
{
418
        struct net_device *dev;
419
        struct in_device *in_dev = NULL;
420
        read_lock(&dev_base_lock);
421
        dev = __dev_get_by_index(&init_net, ifindex);
422
        if (dev)
423
                in_dev = in_dev_get(dev);
424
        read_unlock(&dev_base_lock);
425
        return in_dev;
426
}
427
 
428
/* Called only from RTNL semaphored context. No locks. */
429
 
430
struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, __be32 prefix,
431
                                    __be32 mask)
432
{
433
        ASSERT_RTNL();
434
 
435
        for_primary_ifa(in_dev) {
436
                if (ifa->ifa_mask == mask && inet_ifa_match(prefix, ifa))
437
                        return ifa;
438
        } endfor_ifa(in_dev);
439
        return NULL;
440
}
441
 
442
static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
443
{
444
        struct nlattr *tb[IFA_MAX+1];
445
        struct in_device *in_dev;
446
        struct ifaddrmsg *ifm;
447
        struct in_ifaddr *ifa, **ifap;
448
        int err = -EINVAL;
449
 
450
        ASSERT_RTNL();
451
 
452
        err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv4_policy);
453
        if (err < 0)
454
                goto errout;
455
 
456
        ifm = nlmsg_data(nlh);
457
        in_dev = inetdev_by_index(ifm->ifa_index);
458
        if (in_dev == NULL) {
459
                err = -ENODEV;
460
                goto errout;
461
        }
462
 
463
        __in_dev_put(in_dev);
464
 
465
        for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
466
             ifap = &ifa->ifa_next) {
467
                if (tb[IFA_LOCAL] &&
468
                    ifa->ifa_local != nla_get_be32(tb[IFA_LOCAL]))
469
                        continue;
470
 
471
                if (tb[IFA_LABEL] && nla_strcmp(tb[IFA_LABEL], ifa->ifa_label))
472
                        continue;
473
 
474
                if (tb[IFA_ADDRESS] &&
475
                    (ifm->ifa_prefixlen != ifa->ifa_prefixlen ||
476
                    !inet_ifa_match(nla_get_be32(tb[IFA_ADDRESS]), ifa)))
477
                        continue;
478
 
479
                __inet_del_ifa(in_dev, ifap, 1, nlh, NETLINK_CB(skb).pid);
480
                return 0;
481
        }
482
 
483
        err = -EADDRNOTAVAIL;
484
errout:
485
        return err;
486
}
487
 
488
static struct in_ifaddr *rtm_to_ifaddr(struct nlmsghdr *nlh)
489
{
490
        struct nlattr *tb[IFA_MAX+1];
491
        struct in_ifaddr *ifa;
492
        struct ifaddrmsg *ifm;
493
        struct net_device *dev;
494
        struct in_device *in_dev;
495
        int err = -EINVAL;
496
 
497
        err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv4_policy);
498
        if (err < 0)
499
                goto errout;
500
 
501
        ifm = nlmsg_data(nlh);
502
        if (ifm->ifa_prefixlen > 32 || tb[IFA_LOCAL] == NULL) {
503
                err = -EINVAL;
504
                goto errout;
505
        }
506
 
507
        dev = __dev_get_by_index(&init_net, ifm->ifa_index);
508
        if (dev == NULL) {
509
                err = -ENODEV;
510
                goto errout;
511
        }
512
 
513
        in_dev = __in_dev_get_rtnl(dev);
514
        if (in_dev == NULL) {
515
                err = -ENOBUFS;
516
                goto errout;
517
        }
518
 
519
        ifa = inet_alloc_ifa();
520
        if (ifa == NULL) {
521
                /*
522
                 * A potential indev allocation can be left alive, it stays
523
                 * assigned to its device and is destroy with it.
524
                 */
525
                err = -ENOBUFS;
526
                goto errout;
527
        }
528
 
529
        ipv4_devconf_setall(in_dev);
530
        in_dev_hold(in_dev);
531
 
532
        if (tb[IFA_ADDRESS] == NULL)
533
                tb[IFA_ADDRESS] = tb[IFA_LOCAL];
534
 
535
        ifa->ifa_prefixlen = ifm->ifa_prefixlen;
536
        ifa->ifa_mask = inet_make_mask(ifm->ifa_prefixlen);
537
        ifa->ifa_flags = ifm->ifa_flags;
538
        ifa->ifa_scope = ifm->ifa_scope;
539
        ifa->ifa_dev = in_dev;
540
 
541
        ifa->ifa_local = nla_get_be32(tb[IFA_LOCAL]);
542
        ifa->ifa_address = nla_get_be32(tb[IFA_ADDRESS]);
543
 
544
        if (tb[IFA_BROADCAST])
545
                ifa->ifa_broadcast = nla_get_be32(tb[IFA_BROADCAST]);
546
 
547
        if (tb[IFA_ANYCAST])
548
                ifa->ifa_anycast = nla_get_be32(tb[IFA_ANYCAST]);
549
 
550
        if (tb[IFA_LABEL])
551
                nla_strlcpy(ifa->ifa_label, tb[IFA_LABEL], IFNAMSIZ);
552
        else
553
                memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
554
 
555
        return ifa;
556
 
557
errout:
558
        return ERR_PTR(err);
559
}
560
 
561
static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
562
{
563
        struct in_ifaddr *ifa;
564
 
565
        ASSERT_RTNL();
566
 
567
        ifa = rtm_to_ifaddr(nlh);
568
        if (IS_ERR(ifa))
569
                return PTR_ERR(ifa);
570
 
571
        return __inet_insert_ifa(ifa, nlh, NETLINK_CB(skb).pid);
572
}
573
 
574
/*
575
 *      Determine a default network mask, based on the IP address.
576
 */
577
 
578
static __inline__ int inet_abc_len(__be32 addr)
579
{
580
        int rc = -1;    /* Something else, probably a multicast. */
581
 
582
        if (ZERONET(addr))
583
                rc = 0;
584
        else {
585
                __u32 haddr = ntohl(addr);
586
 
587
                if (IN_CLASSA(haddr))
588
                        rc = 8;
589
                else if (IN_CLASSB(haddr))
590
                        rc = 16;
591
                else if (IN_CLASSC(haddr))
592
                        rc = 24;
593
        }
594
 
595
        return rc;
596
}
597
 
598
 
599
int devinet_ioctl(unsigned int cmd, void __user *arg)
600
{
601
        struct ifreq ifr;
602
        struct sockaddr_in sin_orig;
603
        struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr;
604
        struct in_device *in_dev;
605
        struct in_ifaddr **ifap = NULL;
606
        struct in_ifaddr *ifa = NULL;
607
        struct net_device *dev;
608
        char *colon;
609
        int ret = -EFAULT;
610
        int tryaddrmatch = 0;
611
 
612
        /*
613
         *      Fetch the caller's info block into kernel space
614
         */
615
 
616
        if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
617
                goto out;
618
        ifr.ifr_name[IFNAMSIZ - 1] = 0;
619
 
620
        /* save original address for comparison */
621
        memcpy(&sin_orig, sin, sizeof(*sin));
622
 
623
        colon = strchr(ifr.ifr_name, ':');
624
        if (colon)
625
                *colon = 0;
626
 
627
#ifdef CONFIG_KMOD
628
        dev_load(&init_net, ifr.ifr_name);
629
#endif
630
 
631
        switch (cmd) {
632
        case SIOCGIFADDR:       /* Get interface address */
633
        case SIOCGIFBRDADDR:    /* Get the broadcast address */
634
        case SIOCGIFDSTADDR:    /* Get the destination address */
635
        case SIOCGIFNETMASK:    /* Get the netmask for the interface */
636
                /* Note that these ioctls will not sleep,
637
                   so that we do not impose a lock.
638
                   One day we will be forced to put shlock here (I mean SMP)
639
                 */
640
                tryaddrmatch = (sin_orig.sin_family == AF_INET);
641
                memset(sin, 0, sizeof(*sin));
642
                sin->sin_family = AF_INET;
643
                break;
644
 
645
        case SIOCSIFFLAGS:
646
                ret = -EACCES;
647
                if (!capable(CAP_NET_ADMIN))
648
                        goto out;
649
                break;
650
        case SIOCSIFADDR:       /* Set interface address (and family) */
651
        case SIOCSIFBRDADDR:    /* Set the broadcast address */
652
        case SIOCSIFDSTADDR:    /* Set the destination address */
653
        case SIOCSIFNETMASK:    /* Set the netmask for the interface */
654
                ret = -EACCES;
655
                if (!capable(CAP_NET_ADMIN))
656
                        goto out;
657
                ret = -EINVAL;
658
                if (sin->sin_family != AF_INET)
659
                        goto out;
660
                break;
661
        default:
662
                ret = -EINVAL;
663
                goto out;
664
        }
665
 
666
        rtnl_lock();
667
 
668
        ret = -ENODEV;
669
        if ((dev = __dev_get_by_name(&init_net, ifr.ifr_name)) == NULL)
670
                goto done;
671
 
672
        if (colon)
673
                *colon = ':';
674
 
675
        if ((in_dev = __in_dev_get_rtnl(dev)) != NULL) {
676
                if (tryaddrmatch) {
677
                        /* Matthias Andree */
678
                        /* compare label and address (4.4BSD style) */
679
                        /* note: we only do this for a limited set of ioctls
680
                           and only if the original address family was AF_INET.
681
                           This is checked above. */
682
                        for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
683
                             ifap = &ifa->ifa_next) {
684
                                if (!strcmp(ifr.ifr_name, ifa->ifa_label) &&
685
                                    sin_orig.sin_addr.s_addr ==
686
                                                        ifa->ifa_address) {
687
                                        break; /* found */
688
                                }
689
                        }
690
                }
691
                /* we didn't get a match, maybe the application is
692
                   4.3BSD-style and passed in junk so we fall back to
693
                   comparing just the label */
694
                if (!ifa) {
695
                        for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
696
                             ifap = &ifa->ifa_next)
697
                                if (!strcmp(ifr.ifr_name, ifa->ifa_label))
698
                                        break;
699
                }
700
        }
701
 
702
        ret = -EADDRNOTAVAIL;
703
        if (!ifa && cmd != SIOCSIFADDR && cmd != SIOCSIFFLAGS)
704
                goto done;
705
 
706
        switch (cmd) {
707
        case SIOCGIFADDR:       /* Get interface address */
708
                sin->sin_addr.s_addr = ifa->ifa_local;
709
                goto rarok;
710
 
711
        case SIOCGIFBRDADDR:    /* Get the broadcast address */
712
                sin->sin_addr.s_addr = ifa->ifa_broadcast;
713
                goto rarok;
714
 
715
        case SIOCGIFDSTADDR:    /* Get the destination address */
716
                sin->sin_addr.s_addr = ifa->ifa_address;
717
                goto rarok;
718
 
719
        case SIOCGIFNETMASK:    /* Get the netmask for the interface */
720
                sin->sin_addr.s_addr = ifa->ifa_mask;
721
                goto rarok;
722
 
723
        case SIOCSIFFLAGS:
724
                if (colon) {
725
                        ret = -EADDRNOTAVAIL;
726
                        if (!ifa)
727
                                break;
728
                        ret = 0;
729
                        if (!(ifr.ifr_flags & IFF_UP))
730
                                inet_del_ifa(in_dev, ifap, 1);
731
                        break;
732
                }
733
                ret = dev_change_flags(dev, ifr.ifr_flags);
734
                break;
735
 
736
        case SIOCSIFADDR:       /* Set interface address (and family) */
737
                ret = -EINVAL;
738
                if (inet_abc_len(sin->sin_addr.s_addr) < 0)
739
                        break;
740
 
741
                if (!ifa) {
742
                        ret = -ENOBUFS;
743
                        if ((ifa = inet_alloc_ifa()) == NULL)
744
                                break;
745
                        if (colon)
746
                                memcpy(ifa->ifa_label, ifr.ifr_name, IFNAMSIZ);
747
                        else
748
                                memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
749
                } else {
750
                        ret = 0;
751
                        if (ifa->ifa_local == sin->sin_addr.s_addr)
752
                                break;
753
                        inet_del_ifa(in_dev, ifap, 0);
754
                        ifa->ifa_broadcast = 0;
755
                        ifa->ifa_anycast = 0;
756
                }
757
 
758
                ifa->ifa_address = ifa->ifa_local = sin->sin_addr.s_addr;
759
 
760
                if (!(dev->flags & IFF_POINTOPOINT)) {
761
                        ifa->ifa_prefixlen = inet_abc_len(ifa->ifa_address);
762
                        ifa->ifa_mask = inet_make_mask(ifa->ifa_prefixlen);
763
                        if ((dev->flags & IFF_BROADCAST) &&
764
                            ifa->ifa_prefixlen < 31)
765
                                ifa->ifa_broadcast = ifa->ifa_address |
766
                                                     ~ifa->ifa_mask;
767
                } else {
768
                        ifa->ifa_prefixlen = 32;
769
                        ifa->ifa_mask = inet_make_mask(32);
770
                }
771
                ret = inet_set_ifa(dev, ifa);
772
                break;
773
 
774
        case SIOCSIFBRDADDR:    /* Set the broadcast address */
775
                ret = 0;
776
                if (ifa->ifa_broadcast != sin->sin_addr.s_addr) {
777
                        inet_del_ifa(in_dev, ifap, 0);
778
                        ifa->ifa_broadcast = sin->sin_addr.s_addr;
779
                        inet_insert_ifa(ifa);
780
                }
781
                break;
782
 
783
        case SIOCSIFDSTADDR:    /* Set the destination address */
784
                ret = 0;
785
                if (ifa->ifa_address == sin->sin_addr.s_addr)
786
                        break;
787
                ret = -EINVAL;
788
                if (inet_abc_len(sin->sin_addr.s_addr) < 0)
789
                        break;
790
                ret = 0;
791
                inet_del_ifa(in_dev, ifap, 0);
792
                ifa->ifa_address = sin->sin_addr.s_addr;
793
                inet_insert_ifa(ifa);
794
                break;
795
 
796
        case SIOCSIFNETMASK:    /* Set the netmask for the interface */
797
 
798
                /*
799
                 *      The mask we set must be legal.
800
                 */
801
                ret = -EINVAL;
802
                if (bad_mask(sin->sin_addr.s_addr, 0))
803
                        break;
804
                ret = 0;
805
                if (ifa->ifa_mask != sin->sin_addr.s_addr) {
806
                        __be32 old_mask = ifa->ifa_mask;
807
                        inet_del_ifa(in_dev, ifap, 0);
808
                        ifa->ifa_mask = sin->sin_addr.s_addr;
809
                        ifa->ifa_prefixlen = inet_mask_len(ifa->ifa_mask);
810
 
811
                        /* See if current broadcast address matches
812
                         * with current netmask, then recalculate
813
                         * the broadcast address. Otherwise it's a
814
                         * funny address, so don't touch it since
815
                         * the user seems to know what (s)he's doing...
816
                         */
817
                        if ((dev->flags & IFF_BROADCAST) &&
818
                            (ifa->ifa_prefixlen < 31) &&
819
                            (ifa->ifa_broadcast ==
820
                             (ifa->ifa_local|~old_mask))) {
821
                                ifa->ifa_broadcast = (ifa->ifa_local |
822
                                                      ~sin->sin_addr.s_addr);
823
                        }
824
                        inet_insert_ifa(ifa);
825
                }
826
                break;
827
        }
828
done:
829
        rtnl_unlock();
830
out:
831
        return ret;
832
rarok:
833
        rtnl_unlock();
834
        ret = copy_to_user(arg, &ifr, sizeof(struct ifreq)) ? -EFAULT : 0;
835
        goto out;
836
}
837
 
838
static int inet_gifconf(struct net_device *dev, char __user *buf, int len)
839
{
840
        struct in_device *in_dev = __in_dev_get_rtnl(dev);
841
        struct in_ifaddr *ifa;
842
        struct ifreq ifr;
843
        int done = 0;
844
 
845
        if (!in_dev || (ifa = in_dev->ifa_list) == NULL)
846
                goto out;
847
 
848
        for (; ifa; ifa = ifa->ifa_next) {
849
                if (!buf) {
850
                        done += sizeof(ifr);
851
                        continue;
852
                }
853
                if (len < (int) sizeof(ifr))
854
                        break;
855
                memset(&ifr, 0, sizeof(struct ifreq));
856
                if (ifa->ifa_label)
857
                        strcpy(ifr.ifr_name, ifa->ifa_label);
858
                else
859
                        strcpy(ifr.ifr_name, dev->name);
860
 
861
                (*(struct sockaddr_in *)&ifr.ifr_addr).sin_family = AF_INET;
862
                (*(struct sockaddr_in *)&ifr.ifr_addr).sin_addr.s_addr =
863
                                                                ifa->ifa_local;
864
 
865
                if (copy_to_user(buf, &ifr, sizeof(struct ifreq))) {
866
                        done = -EFAULT;
867
                        break;
868
                }
869
                buf  += sizeof(struct ifreq);
870
                len  -= sizeof(struct ifreq);
871
                done += sizeof(struct ifreq);
872
        }
873
out:
874
        return done;
875
}
876
 
877
__be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope)
878
{
879
        __be32 addr = 0;
880
        struct in_device *in_dev;
881
 
882
        rcu_read_lock();
883
        in_dev = __in_dev_get_rcu(dev);
884
        if (!in_dev)
885
                goto no_in_dev;
886
 
887
        for_primary_ifa(in_dev) {
888
                if (ifa->ifa_scope > scope)
889
                        continue;
890
                if (!dst || inet_ifa_match(dst, ifa)) {
891
                        addr = ifa->ifa_local;
892
                        break;
893
                }
894
                if (!addr)
895
                        addr = ifa->ifa_local;
896
        } endfor_ifa(in_dev);
897
no_in_dev:
898
        rcu_read_unlock();
899
 
900
        if (addr)
901
                goto out;
902
 
903
        /* Not loopback addresses on loopback should be preferred
904
           in this case. It is importnat that lo is the first interface
905
           in dev_base list.
906
         */
907
        read_lock(&dev_base_lock);
908
        rcu_read_lock();
909
        for_each_netdev(&init_net, dev) {
910
                if ((in_dev = __in_dev_get_rcu(dev)) == NULL)
911
                        continue;
912
 
913
                for_primary_ifa(in_dev) {
914
                        if (ifa->ifa_scope != RT_SCOPE_LINK &&
915
                            ifa->ifa_scope <= scope) {
916
                                addr = ifa->ifa_local;
917
                                goto out_unlock_both;
918
                        }
919
                } endfor_ifa(in_dev);
920
        }
921
out_unlock_both:
922
        read_unlock(&dev_base_lock);
923
        rcu_read_unlock();
924
out:
925
        return addr;
926
}
927
 
928
static __be32 confirm_addr_indev(struct in_device *in_dev, __be32 dst,
929
                              __be32 local, int scope)
930
{
931
        int same = 0;
932
        __be32 addr = 0;
933
 
934
        for_ifa(in_dev) {
935
                if (!addr &&
936
                    (local == ifa->ifa_local || !local) &&
937
                    ifa->ifa_scope <= scope) {
938
                        addr = ifa->ifa_local;
939
                        if (same)
940
                                break;
941
                }
942
                if (!same) {
943
                        same = (!local || inet_ifa_match(local, ifa)) &&
944
                                (!dst || inet_ifa_match(dst, ifa));
945
                        if (same && addr) {
946
                                if (local || !dst)
947
                                        break;
948
                                /* Is the selected addr into dst subnet? */
949
                                if (inet_ifa_match(addr, ifa))
950
                                        break;
951
                                /* No, then can we use new local src? */
952
                                if (ifa->ifa_scope <= scope) {
953
                                        addr = ifa->ifa_local;
954
                                        break;
955
                                }
956
                                /* search for large dst subnet for addr */
957
                                same = 0;
958
                        }
959
                }
960
        } endfor_ifa(in_dev);
961
 
962
        return same? addr : 0;
963
}
964
 
965
/*
966
 * Confirm that local IP address exists using wildcards:
967
 * - dev: only on this interface, 0=any interface
968
 * - dst: only in the same subnet as dst, 0=any dst
969
 * - local: address, 0=autoselect the local address
970
 * - scope: maximum allowed scope value for the local address
971
 */
972
__be32 inet_confirm_addr(const struct net_device *dev, __be32 dst, __be32 local, int scope)
973
{
974
        __be32 addr = 0;
975
        struct in_device *in_dev;
976
 
977
        if (dev) {
978
                rcu_read_lock();
979
                if ((in_dev = __in_dev_get_rcu(dev)))
980
                        addr = confirm_addr_indev(in_dev, dst, local, scope);
981
                rcu_read_unlock();
982
 
983
                return addr;
984
        }
985
 
986
        read_lock(&dev_base_lock);
987
        rcu_read_lock();
988
        for_each_netdev(&init_net, dev) {
989
                if ((in_dev = __in_dev_get_rcu(dev))) {
990
                        addr = confirm_addr_indev(in_dev, dst, local, scope);
991
                        if (addr)
992
                                break;
993
                }
994
        }
995
        rcu_read_unlock();
996
        read_unlock(&dev_base_lock);
997
 
998
        return addr;
999
}
1000
 
1001
/*
1002
 *      Device notifier
1003
 */
1004
 
1005
int register_inetaddr_notifier(struct notifier_block *nb)
1006
{
1007
        return blocking_notifier_chain_register(&inetaddr_chain, nb);
1008
}
1009
 
1010
int unregister_inetaddr_notifier(struct notifier_block *nb)
1011
{
1012
        return blocking_notifier_chain_unregister(&inetaddr_chain, nb);
1013
}
1014
 
1015
/* Rename ifa_labels for a device name change. Make some effort to preserve existing
1016
 * alias numbering and to create unique labels if possible.
1017
*/
1018
static void inetdev_changename(struct net_device *dev, struct in_device *in_dev)
1019
{
1020
        struct in_ifaddr *ifa;
1021
        int named = 0;
1022
 
1023
        for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
1024
                char old[IFNAMSIZ], *dot;
1025
 
1026
                memcpy(old, ifa->ifa_label, IFNAMSIZ);
1027
                memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
1028
                if (named++ == 0)
1029
                        continue;
1030
                dot = strchr(old, ':');
1031
                if (dot == NULL) {
1032
                        sprintf(old, ":%d", named);
1033
                        dot = old;
1034
                }
1035
                if (strlen(dot) + strlen(dev->name) < IFNAMSIZ) {
1036
                        strcat(ifa->ifa_label, dot);
1037
                } else {
1038
                        strcpy(ifa->ifa_label + (IFNAMSIZ - strlen(dot) - 1), dot);
1039
                }
1040
        }
1041
}
1042
 
1043
/* Called only under RTNL semaphore */
1044
 
1045
static int inetdev_event(struct notifier_block *this, unsigned long event,
1046
                         void *ptr)
1047
{
1048
        struct net_device *dev = ptr;
1049
        struct in_device *in_dev = __in_dev_get_rtnl(dev);
1050
 
1051
        if (dev->nd_net != &init_net)
1052
                return NOTIFY_DONE;
1053
 
1054
        ASSERT_RTNL();
1055
 
1056
        if (!in_dev) {
1057
                if (event == NETDEV_REGISTER) {
1058
                        in_dev = inetdev_init(dev);
1059
                        if (!in_dev)
1060
                                return notifier_from_errno(-ENOMEM);
1061
                        if (dev->flags & IFF_LOOPBACK) {
1062
                                IN_DEV_CONF_SET(in_dev, NOXFRM, 1);
1063
                                IN_DEV_CONF_SET(in_dev, NOPOLICY, 1);
1064
                        }
1065
                }
1066
                goto out;
1067
        }
1068
 
1069
        switch (event) {
1070
        case NETDEV_REGISTER:
1071
                printk(KERN_DEBUG "inetdev_event: bug\n");
1072
                dev->ip_ptr = NULL;
1073
                break;
1074
        case NETDEV_UP:
1075
                if (dev->mtu < 68)
1076
                        break;
1077
                if (dev->flags & IFF_LOOPBACK) {
1078
                        struct in_ifaddr *ifa;
1079
                        if ((ifa = inet_alloc_ifa()) != NULL) {
1080
                                ifa->ifa_local =
1081
                                  ifa->ifa_address = htonl(INADDR_LOOPBACK);
1082
                                ifa->ifa_prefixlen = 8;
1083
                                ifa->ifa_mask = inet_make_mask(8);
1084
                                in_dev_hold(in_dev);
1085
                                ifa->ifa_dev = in_dev;
1086
                                ifa->ifa_scope = RT_SCOPE_HOST;
1087
                                memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
1088
                                inet_insert_ifa(ifa);
1089
                        }
1090
                }
1091
                ip_mc_up(in_dev);
1092
                break;
1093
        case NETDEV_DOWN:
1094
                ip_mc_down(in_dev);
1095
                break;
1096
        case NETDEV_CHANGEMTU:
1097
                if (dev->mtu >= 68)
1098
                        break;
1099
                /* MTU falled under 68, disable IP */
1100
        case NETDEV_UNREGISTER:
1101
                inetdev_destroy(in_dev);
1102
                break;
1103
        case NETDEV_CHANGENAME:
1104
                /* Do not notify about label change, this event is
1105
                 * not interesting to applications using netlink.
1106
                 */
1107
                inetdev_changename(dev, in_dev);
1108
 
1109
#ifdef CONFIG_SYSCTL
1110
                devinet_sysctl_unregister(&in_dev->cnf);
1111
                neigh_sysctl_unregister(in_dev->arp_parms);
1112
                neigh_sysctl_register(dev, in_dev->arp_parms, NET_IPV4,
1113
                                      NET_IPV4_NEIGH, "ipv4", NULL, NULL);
1114
                devinet_sysctl_register(in_dev, &in_dev->cnf);
1115
#endif
1116
                break;
1117
        }
1118
out:
1119
        return NOTIFY_DONE;
1120
}
1121
 
1122
static struct notifier_block ip_netdev_notifier = {
1123
        .notifier_call =inetdev_event,
1124
};
1125
 
1126
static inline size_t inet_nlmsg_size(void)
1127
{
1128
        return NLMSG_ALIGN(sizeof(struct ifaddrmsg))
1129
               + nla_total_size(4) /* IFA_ADDRESS */
1130
               + nla_total_size(4) /* IFA_LOCAL */
1131
               + nla_total_size(4) /* IFA_BROADCAST */
1132
               + nla_total_size(4) /* IFA_ANYCAST */
1133
               + nla_total_size(IFNAMSIZ); /* IFA_LABEL */
1134
}
1135
 
1136
static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,
1137
                            u32 pid, u32 seq, int event, unsigned int flags)
1138
{
1139
        struct ifaddrmsg *ifm;
1140
        struct nlmsghdr  *nlh;
1141
 
1142
        nlh = nlmsg_put(skb, pid, seq, event, sizeof(*ifm), flags);
1143
        if (nlh == NULL)
1144
                return -EMSGSIZE;
1145
 
1146
        ifm = nlmsg_data(nlh);
1147
        ifm->ifa_family = AF_INET;
1148
        ifm->ifa_prefixlen = ifa->ifa_prefixlen;
1149
        ifm->ifa_flags = ifa->ifa_flags|IFA_F_PERMANENT;
1150
        ifm->ifa_scope = ifa->ifa_scope;
1151
        ifm->ifa_index = ifa->ifa_dev->dev->ifindex;
1152
 
1153
        if (ifa->ifa_address)
1154
                NLA_PUT_BE32(skb, IFA_ADDRESS, ifa->ifa_address);
1155
 
1156
        if (ifa->ifa_local)
1157
                NLA_PUT_BE32(skb, IFA_LOCAL, ifa->ifa_local);
1158
 
1159
        if (ifa->ifa_broadcast)
1160
                NLA_PUT_BE32(skb, IFA_BROADCAST, ifa->ifa_broadcast);
1161
 
1162
        if (ifa->ifa_anycast)
1163
                NLA_PUT_BE32(skb, IFA_ANYCAST, ifa->ifa_anycast);
1164
 
1165
        if (ifa->ifa_label[0])
1166
                NLA_PUT_STRING(skb, IFA_LABEL, ifa->ifa_label);
1167
 
1168
        return nlmsg_end(skb, nlh);
1169
 
1170
nla_put_failure:
1171
        nlmsg_cancel(skb, nlh);
1172
        return -EMSGSIZE;
1173
}
1174
 
1175
static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
1176
{
1177
        int idx, ip_idx;
1178
        struct net_device *dev;
1179
        struct in_device *in_dev;
1180
        struct in_ifaddr *ifa;
1181
        int s_ip_idx, s_idx = cb->args[0];
1182
 
1183
        s_ip_idx = ip_idx = cb->args[1];
1184
        idx = 0;
1185
        for_each_netdev(&init_net, dev) {
1186
                if (idx < s_idx)
1187
                        goto cont;
1188
                if (idx > s_idx)
1189
                        s_ip_idx = 0;
1190
                if ((in_dev = __in_dev_get_rtnl(dev)) == NULL)
1191
                        goto cont;
1192
 
1193
                for (ifa = in_dev->ifa_list, ip_idx = 0; ifa;
1194
                     ifa = ifa->ifa_next, ip_idx++) {
1195
                        if (ip_idx < s_ip_idx)
1196
                                continue;
1197
                        if (inet_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid,
1198
                                             cb->nlh->nlmsg_seq,
1199
                                             RTM_NEWADDR, NLM_F_MULTI) <= 0)
1200
                                goto done;
1201
                }
1202
cont:
1203
                idx++;
1204
        }
1205
 
1206
done:
1207
        cb->args[0] = idx;
1208
        cb->args[1] = ip_idx;
1209
 
1210
        return skb->len;
1211
}
1212
 
1213
static void rtmsg_ifa(int event, struct in_ifaddr* ifa, struct nlmsghdr *nlh,
1214
                      u32 pid)
1215
{
1216
        struct sk_buff *skb;
1217
        u32 seq = nlh ? nlh->nlmsg_seq : 0;
1218
        int err = -ENOBUFS;
1219
 
1220
        skb = nlmsg_new(inet_nlmsg_size(), GFP_KERNEL);
1221
        if (skb == NULL)
1222
                goto errout;
1223
 
1224
        err = inet_fill_ifaddr(skb, ifa, pid, seq, event, 0);
1225
        if (err < 0) {
1226
                /* -EMSGSIZE implies BUG in inet_nlmsg_size() */
1227
                WARN_ON(err == -EMSGSIZE);
1228
                kfree_skb(skb);
1229
                goto errout;
1230
        }
1231
        err = rtnl_notify(skb, pid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL);
1232
errout:
1233
        if (err < 0)
1234
                rtnl_set_sk_err(RTNLGRP_IPV4_IFADDR, err);
1235
}
1236
 
1237
#ifdef CONFIG_SYSCTL
1238
 
1239
static void devinet_copy_dflt_conf(int i)
1240
{
1241
        struct net_device *dev;
1242
 
1243
        read_lock(&dev_base_lock);
1244
        for_each_netdev(&init_net, dev) {
1245
                struct in_device *in_dev;
1246
                rcu_read_lock();
1247
                in_dev = __in_dev_get_rcu(dev);
1248
                if (in_dev && !test_bit(i, in_dev->cnf.state))
1249
                        in_dev->cnf.data[i] = ipv4_devconf_dflt.data[i];
1250
                rcu_read_unlock();
1251
        }
1252
        read_unlock(&dev_base_lock);
1253
}
1254
 
1255
static int devinet_conf_proc(ctl_table *ctl, int write,
1256
                             struct file* filp, void __user *buffer,
1257
                             size_t *lenp, loff_t *ppos)
1258
{
1259
        int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
1260
 
1261
        if (write) {
1262
                struct ipv4_devconf *cnf = ctl->extra1;
1263
                int i = (int *)ctl->data - cnf->data;
1264
 
1265
                set_bit(i, cnf->state);
1266
 
1267
                if (cnf == &ipv4_devconf_dflt)
1268
                        devinet_copy_dflt_conf(i);
1269
        }
1270
 
1271
        return ret;
1272
}
1273
 
1274
static int devinet_conf_sysctl(ctl_table *table, int __user *name, int nlen,
1275
                               void __user *oldval, size_t __user *oldlenp,
1276
                               void __user *newval, size_t newlen)
1277
{
1278
        struct ipv4_devconf *cnf;
1279
        int *valp = table->data;
1280
        int new;
1281
        int i;
1282
 
1283
        if (!newval || !newlen)
1284
                return 0;
1285
 
1286
        if (newlen != sizeof(int))
1287
                return -EINVAL;
1288
 
1289
        if (get_user(new, (int __user *)newval))
1290
                return -EFAULT;
1291
 
1292
        if (new == *valp)
1293
                return 0;
1294
 
1295
        if (oldval && oldlenp) {
1296
                size_t len;
1297
 
1298
                if (get_user(len, oldlenp))
1299
                        return -EFAULT;
1300
 
1301
                if (len) {
1302
                        if (len > table->maxlen)
1303
                                len = table->maxlen;
1304
                        if (copy_to_user(oldval, valp, len))
1305
                                return -EFAULT;
1306
                        if (put_user(len, oldlenp))
1307
                                return -EFAULT;
1308
                }
1309
        }
1310
 
1311
        *valp = new;
1312
 
1313
        cnf = table->extra1;
1314
        i = (int *)table->data - cnf->data;
1315
 
1316
        set_bit(i, cnf->state);
1317
 
1318
        if (cnf == &ipv4_devconf_dflt)
1319
                devinet_copy_dflt_conf(i);
1320
 
1321
        return 1;
1322
}
1323
 
1324
void inet_forward_change(void)
1325
{
1326
        struct net_device *dev;
1327
        int on = IPV4_DEVCONF_ALL(FORWARDING);
1328
 
1329
        IPV4_DEVCONF_ALL(ACCEPT_REDIRECTS) = !on;
1330
        IPV4_DEVCONF_DFLT(FORWARDING) = on;
1331
 
1332
        read_lock(&dev_base_lock);
1333
        for_each_netdev(&init_net, dev) {
1334
                struct in_device *in_dev;
1335
                rcu_read_lock();
1336
                in_dev = __in_dev_get_rcu(dev);
1337
                if (in_dev)
1338
                        IN_DEV_CONF_SET(in_dev, FORWARDING, on);
1339
                rcu_read_unlock();
1340
        }
1341
        read_unlock(&dev_base_lock);
1342
 
1343
        rt_cache_flush(0);
1344
}
1345
 
1346
static int devinet_sysctl_forward(ctl_table *ctl, int write,
1347
                                  struct file* filp, void __user *buffer,
1348
                                  size_t *lenp, loff_t *ppos)
1349
{
1350
        int *valp = ctl->data;
1351
        int val = *valp;
1352
        int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
1353
 
1354
        if (write && *valp != val) {
1355
                if (valp == &IPV4_DEVCONF_ALL(FORWARDING))
1356
                        inet_forward_change();
1357
                else if (valp != &IPV4_DEVCONF_DFLT(FORWARDING))
1358
                        rt_cache_flush(0);
1359
        }
1360
 
1361
        return ret;
1362
}
1363
 
1364
int ipv4_doint_and_flush(ctl_table *ctl, int write,
1365
                         struct file* filp, void __user *buffer,
1366
                         size_t *lenp, loff_t *ppos)
1367
{
1368
        int *valp = ctl->data;
1369
        int val = *valp;
1370
        int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
1371
 
1372
        if (write && *valp != val)
1373
                rt_cache_flush(0);
1374
 
1375
        return ret;
1376
}
1377
 
1378
int ipv4_doint_and_flush_strategy(ctl_table *table, int __user *name, int nlen,
1379
                                  void __user *oldval, size_t __user *oldlenp,
1380
                                  void __user *newval, size_t newlen)
1381
{
1382
        int ret = devinet_conf_sysctl(table, name, nlen, oldval, oldlenp,
1383
                                      newval, newlen);
1384
 
1385
        if (ret == 1)
1386
                rt_cache_flush(0);
1387
 
1388
        return ret;
1389
}
1390
 
1391
 
1392
#define DEVINET_SYSCTL_ENTRY(attr, name, mval, proc, sysctl) \
1393
        { \
1394
                .ctl_name       = NET_IPV4_CONF_ ## attr, \
1395
                .procname       = name, \
1396
                .data           = ipv4_devconf.data + \
1397
                                  NET_IPV4_CONF_ ## attr - 1, \
1398
                .maxlen         = sizeof(int), \
1399
                .mode           = mval, \
1400
                .proc_handler   = proc, \
1401
                .strategy       = sysctl, \
1402
                .extra1         = &ipv4_devconf, \
1403
        }
1404
 
1405
#define DEVINET_SYSCTL_RW_ENTRY(attr, name) \
1406
        DEVINET_SYSCTL_ENTRY(attr, name, 0644, devinet_conf_proc, \
1407
                             devinet_conf_sysctl)
1408
 
1409
#define DEVINET_SYSCTL_RO_ENTRY(attr, name) \
1410
        DEVINET_SYSCTL_ENTRY(attr, name, 0444, devinet_conf_proc, \
1411
                             devinet_conf_sysctl)
1412
 
1413
#define DEVINET_SYSCTL_COMPLEX_ENTRY(attr, name, proc, sysctl) \
1414
        DEVINET_SYSCTL_ENTRY(attr, name, 0644, proc, sysctl)
1415
 
1416
#define DEVINET_SYSCTL_FLUSHING_ENTRY(attr, name) \
1417
        DEVINET_SYSCTL_COMPLEX_ENTRY(attr, name, ipv4_doint_and_flush, \
1418
                                     ipv4_doint_and_flush_strategy)
1419
 
1420
static struct devinet_sysctl_table {
1421
        struct ctl_table_header *sysctl_header;
1422
        ctl_table               devinet_vars[__NET_IPV4_CONF_MAX];
1423
        ctl_table               devinet_dev[2];
1424
        ctl_table               devinet_conf_dir[2];
1425
        ctl_table               devinet_proto_dir[2];
1426
        ctl_table               devinet_root_dir[2];
1427
} devinet_sysctl = {
1428
        .devinet_vars = {
1429
                DEVINET_SYSCTL_COMPLEX_ENTRY(FORWARDING, "forwarding",
1430
                                             devinet_sysctl_forward,
1431
                                             devinet_conf_sysctl),
1432
                DEVINET_SYSCTL_RO_ENTRY(MC_FORWARDING, "mc_forwarding"),
1433
 
1434
                DEVINET_SYSCTL_RW_ENTRY(ACCEPT_REDIRECTS, "accept_redirects"),
1435
                DEVINET_SYSCTL_RW_ENTRY(SECURE_REDIRECTS, "secure_redirects"),
1436
                DEVINET_SYSCTL_RW_ENTRY(SHARED_MEDIA, "shared_media"),
1437
                DEVINET_SYSCTL_RW_ENTRY(RP_FILTER, "rp_filter"),
1438
                DEVINET_SYSCTL_RW_ENTRY(SEND_REDIRECTS, "send_redirects"),
1439
                DEVINET_SYSCTL_RW_ENTRY(ACCEPT_SOURCE_ROUTE,
1440
                                        "accept_source_route"),
1441
                DEVINET_SYSCTL_RW_ENTRY(PROXY_ARP, "proxy_arp"),
1442
                DEVINET_SYSCTL_RW_ENTRY(MEDIUM_ID, "medium_id"),
1443
                DEVINET_SYSCTL_RW_ENTRY(BOOTP_RELAY, "bootp_relay"),
1444
                DEVINET_SYSCTL_RW_ENTRY(LOG_MARTIANS, "log_martians"),
1445
                DEVINET_SYSCTL_RW_ENTRY(TAG, "tag"),
1446
                DEVINET_SYSCTL_RW_ENTRY(ARPFILTER, "arp_filter"),
1447
                DEVINET_SYSCTL_RW_ENTRY(ARP_ANNOUNCE, "arp_announce"),
1448
                DEVINET_SYSCTL_RW_ENTRY(ARP_IGNORE, "arp_ignore"),
1449
                DEVINET_SYSCTL_RW_ENTRY(ARP_ACCEPT, "arp_accept"),
1450
 
1451
                DEVINET_SYSCTL_FLUSHING_ENTRY(NOXFRM, "disable_xfrm"),
1452
                DEVINET_SYSCTL_FLUSHING_ENTRY(NOPOLICY, "disable_policy"),
1453
                DEVINET_SYSCTL_FLUSHING_ENTRY(FORCE_IGMP_VERSION,
1454
                                              "force_igmp_version"),
1455
                DEVINET_SYSCTL_FLUSHING_ENTRY(PROMOTE_SECONDARIES,
1456
                                              "promote_secondaries"),
1457
        },
1458
        .devinet_dev = {
1459
                {
1460
                        .ctl_name       = NET_PROTO_CONF_ALL,
1461
                        .procname       = "all",
1462
                        .mode           = 0555,
1463
                        .child          = devinet_sysctl.devinet_vars,
1464
                },
1465
        },
1466
        .devinet_conf_dir = {
1467
                {
1468
                        .ctl_name       = NET_IPV4_CONF,
1469
                        .procname       = "conf",
1470
                        .mode           = 0555,
1471
                        .child          = devinet_sysctl.devinet_dev,
1472
                },
1473
        },
1474
        .devinet_proto_dir = {
1475
                {
1476
                        .ctl_name       = NET_IPV4,
1477
                        .procname       = "ipv4",
1478
                        .mode           = 0555,
1479
                        .child          = devinet_sysctl.devinet_conf_dir,
1480
                },
1481
        },
1482
        .devinet_root_dir = {
1483
                {
1484
                        .ctl_name       = CTL_NET,
1485
                        .procname       = "net",
1486
                        .mode           = 0555,
1487
                        .child          = devinet_sysctl.devinet_proto_dir,
1488
                },
1489
        },
1490
};
1491
 
1492
static void devinet_sysctl_register(struct in_device *in_dev,
1493
                                    struct ipv4_devconf *p)
1494
{
1495
        int i;
1496
        struct net_device *dev = in_dev ? in_dev->dev : NULL;
1497
        struct devinet_sysctl_table *t = kmemdup(&devinet_sysctl, sizeof(*t),
1498
                                                 GFP_KERNEL);
1499
        char *dev_name = NULL;
1500
 
1501
        if (!t)
1502
                return;
1503
        for (i = 0; i < ARRAY_SIZE(t->devinet_vars) - 1; i++) {
1504
                t->devinet_vars[i].data += (char *)p - (char *)&ipv4_devconf;
1505
                t->devinet_vars[i].extra1 = p;
1506
        }
1507
 
1508
        if (dev) {
1509
                dev_name = dev->name;
1510
                t->devinet_dev[0].ctl_name = dev->ifindex;
1511
        } else {
1512
                dev_name = "default";
1513
                t->devinet_dev[0].ctl_name = NET_PROTO_CONF_DEFAULT;
1514
        }
1515
 
1516
        /*
1517
         * Make a copy of dev_name, because '.procname' is regarded as const
1518
         * by sysctl and we wouldn't want anyone to change it under our feet
1519
         * (see SIOCSIFNAME).
1520
         */
1521
        dev_name = kstrdup(dev_name, GFP_KERNEL);
1522
        if (!dev_name)
1523
            goto free;
1524
 
1525
        t->devinet_dev[0].procname    = dev_name;
1526
        t->devinet_dev[0].child        = t->devinet_vars;
1527
        t->devinet_conf_dir[0].child  = t->devinet_dev;
1528
        t->devinet_proto_dir[0].child = t->devinet_conf_dir;
1529
        t->devinet_root_dir[0].child  = t->devinet_proto_dir;
1530
 
1531
        t->sysctl_header = register_sysctl_table(t->devinet_root_dir);
1532
        if (!t->sysctl_header)
1533
            goto free_procname;
1534
 
1535
        p->sysctl = t;
1536
        return;
1537
 
1538
        /* error path */
1539
 free_procname:
1540
        kfree(dev_name);
1541
 free:
1542
        kfree(t);
1543
        return;
1544
}
1545
 
1546
static void devinet_sysctl_unregister(struct ipv4_devconf *p)
1547
{
1548
        if (p->sysctl) {
1549
                struct devinet_sysctl_table *t = p->sysctl;
1550
                p->sysctl = NULL;
1551
                unregister_sysctl_table(t->sysctl_header);
1552
                kfree(t->devinet_dev[0].procname);
1553
                kfree(t);
1554
        }
1555
}
1556
#endif
1557
 
1558
void __init devinet_init(void)
1559
{
1560
        register_gifconf(PF_INET, inet_gifconf);
1561
        register_netdevice_notifier(&ip_netdev_notifier);
1562
 
1563
        rtnl_register(PF_INET, RTM_NEWADDR, inet_rtm_newaddr, NULL);
1564
        rtnl_register(PF_INET, RTM_DELADDR, inet_rtm_deladdr, NULL);
1565
        rtnl_register(PF_INET, RTM_GETADDR, NULL, inet_dump_ifaddr);
1566
#ifdef CONFIG_SYSCTL
1567
        devinet_sysctl.sysctl_header =
1568
                register_sysctl_table(devinet_sysctl.devinet_root_dir);
1569
        devinet_sysctl_register(NULL, &ipv4_devconf_dflt);
1570
#endif
1571
}
1572
 
1573
EXPORT_SYMBOL(in_dev_finish_destroy);
1574
EXPORT_SYMBOL(inet_select_addr);
1575
EXPORT_SYMBOL(inetdev_by_index);
1576
EXPORT_SYMBOL(register_inetaddr_notifier);
1577
EXPORT_SYMBOL(unregister_inetaddr_notifier);

powered by: WebSVN 2.1.0

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