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