blob: a4573bccd6da7b6763016d4f07d3032d44483d99 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * NET3 IP device support routines.
3 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 * Derived from the IP parts of dev.c 1.0.19
Jesper Juhl02c30a82005-05-05 16:16:16 -070010 * Authors: Ross Biro
Linus Torvalds1da177e2005-04-16 15:20:36 -070011 * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
12 * Mark Evans, <evansmp@uhura.aston.ac.uk>
13 *
14 * Additional Authors:
15 * Alan Cox, <gw4pts@gw4pts.ampr.org>
16 * Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
17 *
18 * Changes:
19 * Alexey Kuznetsov: pa_* fields are replaced with ifaddr
20 * lists.
21 * Cyrus Durgin: updated for kmod
22 * Matthias Andree: in devinet_ioctl, compare label and
23 * address (4.4BSD alias style support),
24 * fall back to comparing just the label
25 * if no match found.
26 */
27
Linus Torvalds1da177e2005-04-16 15:20:36 -070028
Linus Torvalds7c0f6ba2016-12-24 11:46:01 -080029#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <linux/bitops.h>
Randy Dunlap4fc268d2006-01-11 12:17:47 -080031#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include <linux/module.h>
33#include <linux/types.h>
34#include <linux/kernel.h>
Ingo Molnar174cd4b2017-02-02 19:15:33 +010035#include <linux/sched/signal.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#include <linux/string.h>
37#include <linux/mm.h>
38#include <linux/socket.h>
39#include <linux/sockios.h>
40#include <linux/in.h>
41#include <linux/errno.h>
42#include <linux/interrupt.h>
Thomas Graf18237302006-08-04 23:04:54 -070043#include <linux/if_addr.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070044#include <linux/if_ether.h>
45#include <linux/inet.h>
46#include <linux/netdevice.h>
47#include <linux/etherdevice.h>
48#include <linux/skbuff.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <linux/init.h>
50#include <linux/notifier.h>
51#include <linux/inetdevice.h>
52#include <linux/igmp.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090053#include <linux/slab.h>
David S. Millerfd23c3b2011-02-18 12:42:28 -080054#include <linux/hash.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070055#ifdef CONFIG_SYSCTL
56#include <linux/sysctl.h>
57#endif
58#include <linux/kmod.h>
Nicolas Dichteledc9e742012-10-25 22:28:52 +000059#include <linux/netconf.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070060
Arnaldo Carvalho de Melo14c85022005-12-27 02:43:12 -020061#include <net/arp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070062#include <net/ip.h>
63#include <net/route.h>
64#include <net/ip_fib.h>
Thomas Graf63f34442007-03-22 11:55:17 -070065#include <net/rtnetlink.h>
Pavel Emelyanov752d14d2007-12-16 13:31:47 -080066#include <net/net_namespace.h>
Jiri Pirko5c766d62013-01-24 09:41:41 +000067#include <net/addrconf.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070068
Adrian Bunk0027ba82008-01-31 17:17:31 -080069static struct ipv4_devconf ipv4_devconf = {
Herbert Xu42f811b2007-06-04 23:34:44 -070070 .data = {
Eric W. Biederman02291682010-02-14 03:25:51 +000071 [IPV4_DEVCONF_ACCEPT_REDIRECTS - 1] = 1,
72 [IPV4_DEVCONF_SEND_REDIRECTS - 1] = 1,
73 [IPV4_DEVCONF_SECURE_REDIRECTS - 1] = 1,
74 [IPV4_DEVCONF_SHARED_MEDIA - 1] = 1,
William Manley26900482013-08-06 19:03:15 +010075 [IPV4_DEVCONF_IGMPV2_UNSOLICITED_REPORT_INTERVAL - 1] = 10000 /*ms*/,
76 [IPV4_DEVCONF_IGMPV3_UNSOLICITED_REPORT_INTERVAL - 1] = 1000 /*ms*/,
Herbert Xu42f811b2007-06-04 23:34:44 -070077 },
Linus Torvalds1da177e2005-04-16 15:20:36 -070078};
79
80static struct ipv4_devconf ipv4_devconf_dflt = {
Herbert Xu42f811b2007-06-04 23:34:44 -070081 .data = {
Eric W. Biederman02291682010-02-14 03:25:51 +000082 [IPV4_DEVCONF_ACCEPT_REDIRECTS - 1] = 1,
83 [IPV4_DEVCONF_SEND_REDIRECTS - 1] = 1,
84 [IPV4_DEVCONF_SECURE_REDIRECTS - 1] = 1,
85 [IPV4_DEVCONF_SHARED_MEDIA - 1] = 1,
86 [IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE - 1] = 1,
William Manley26900482013-08-06 19:03:15 +010087 [IPV4_DEVCONF_IGMPV2_UNSOLICITED_REPORT_INTERVAL - 1] = 10000 /*ms*/,
88 [IPV4_DEVCONF_IGMPV3_UNSOLICITED_REPORT_INTERVAL - 1] = 1000 /*ms*/,
Herbert Xu42f811b2007-06-04 23:34:44 -070089 },
Linus Torvalds1da177e2005-04-16 15:20:36 -070090};
91
Pavel Emelyanov9355bbd2007-12-16 13:32:16 -080092#define IPV4_DEVCONF_DFLT(net, attr) \
93 IPV4_DEVCONF((*net->ipv4.devconf_dflt), attr)
Herbert Xu42f811b2007-06-04 23:34:44 -070094
Patrick McHardyef7c79e2007-06-05 12:38:30 -070095static const struct nla_policy ifa_ipv4_policy[IFA_MAX+1] = {
Thomas Graf5c753972006-08-04 23:03:53 -070096 [IFA_LOCAL] = { .type = NLA_U32 },
97 [IFA_ADDRESS] = { .type = NLA_U32 },
98 [IFA_BROADCAST] = { .type = NLA_U32 },
Thomas Graf5176f912006-08-26 20:13:18 -070099 [IFA_LABEL] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 },
Jiri Pirko5c766d62013-01-24 09:41:41 +0000100 [IFA_CACHEINFO] = { .len = sizeof(struct ifa_cacheinfo) },
Jiri Pirkoad6c8132013-12-08 12:16:10 +0100101 [IFA_FLAGS] = { .type = NLA_U32 },
Thomas Graf5c753972006-08-04 23:03:53 -0700102};
103
Eric Dumazet40384992012-08-03 21:06:50 +0000104#define IN4_ADDR_HSIZE_SHIFT 8
105#define IN4_ADDR_HSIZE (1U << IN4_ADDR_HSIZE_SHIFT)
106
David S. Millerfd23c3b2011-02-18 12:42:28 -0800107static struct hlist_head inet_addr_lst[IN4_ADDR_HSIZE];
David S. Millerfd23c3b2011-02-18 12:42:28 -0800108
Eric Dumazet6eada012015-03-18 14:05:33 -0700109static u32 inet_addr_hash(const struct net *net, __be32 addr)
David S. Millerfd23c3b2011-02-18 12:42:28 -0800110{
Eric Dumazet40384992012-08-03 21:06:50 +0000111 u32 val = (__force u32) addr ^ net_hash_mix(net);
David S. Millerfd23c3b2011-02-18 12:42:28 -0800112
Eric Dumazet40384992012-08-03 21:06:50 +0000113 return hash_32(val, IN4_ADDR_HSIZE_SHIFT);
David S. Millerfd23c3b2011-02-18 12:42:28 -0800114}
115
116static void inet_hash_insert(struct net *net, struct in_ifaddr *ifa)
117{
Eric Dumazet40384992012-08-03 21:06:50 +0000118 u32 hash = inet_addr_hash(net, ifa->ifa_local);
David S. Millerfd23c3b2011-02-18 12:42:28 -0800119
WANG Cong32a4be42014-05-06 11:15:56 -0700120 ASSERT_RTNL();
David S. Millerfd23c3b2011-02-18 12:42:28 -0800121 hlist_add_head_rcu(&ifa->hash, &inet_addr_lst[hash]);
David S. Millerfd23c3b2011-02-18 12:42:28 -0800122}
123
124static void inet_hash_remove(struct in_ifaddr *ifa)
125{
WANG Cong32a4be42014-05-06 11:15:56 -0700126 ASSERT_RTNL();
David S. Millerfd23c3b2011-02-18 12:42:28 -0800127 hlist_del_init_rcu(&ifa->hash);
David S. Millerfd23c3b2011-02-18 12:42:28 -0800128}
129
David S. Miller9435eb12011-02-18 12:43:09 -0800130/**
131 * __ip_dev_find - find the first device with a given source address.
132 * @net: the net namespace
133 * @addr: the source address
134 * @devref: if true, take a reference on the found device
135 *
136 * If a caller uses devref=false, it should be protected by RCU, or RTNL
137 */
138struct net_device *__ip_dev_find(struct net *net, __be32 addr, bool devref)
139{
David S. Miller9435eb12011-02-18 12:43:09 -0800140 struct net_device *result = NULL;
141 struct in_ifaddr *ifa;
David S. Miller9435eb12011-02-18 12:43:09 -0800142
143 rcu_read_lock();
Paolo Abeni6e617de2017-09-20 18:26:53 +0200144 ifa = inet_lookup_ifaddr_rcu(net, addr);
145 if (!ifa) {
David S. Miller406b6f92011-03-22 21:56:23 -0700146 struct flowi4 fl4 = { .daddr = addr };
147 struct fib_result res = { 0 };
148 struct fib_table *local;
149
150 /* Fallback to FIB local table so that communication
151 * over loopback subnets work.
152 */
153 local = fib_get_table(net, RT_TABLE_LOCAL);
154 if (local &&
155 !fib_table_lookup(local, &fl4, &res, FIB_LOOKUP_NOREF) &&
156 res.type == RTN_LOCAL)
157 result = FIB_RES_DEV(res);
Paolo Abeni6e617de2017-09-20 18:26:53 +0200158 } else {
159 result = ifa->ifa_dev->dev;
David S. Miller406b6f92011-03-22 21:56:23 -0700160 }
David S. Miller9435eb12011-02-18 12:43:09 -0800161 if (result && devref)
162 dev_hold(result);
163 rcu_read_unlock();
164 return result;
165}
166EXPORT_SYMBOL(__ip_dev_find);
167
Paolo Abeni6e617de2017-09-20 18:26:53 +0200168/* called under RCU lock */
169struct in_ifaddr *inet_lookup_ifaddr_rcu(struct net *net, __be32 addr)
170{
171 u32 hash = inet_addr_hash(net, addr);
172 struct in_ifaddr *ifa;
173
174 hlist_for_each_entry_rcu(ifa, &inet_addr_lst[hash], hash)
175 if (ifa->ifa_local == addr &&
176 net_eq(dev_net(ifa->ifa_dev->dev), net))
177 return ifa;
178
179 return NULL;
180}
181
Thomas Grafd6062cb2006-08-15 00:33:59 -0700182static void rtmsg_ifa(int event, struct in_ifaddr *, struct nlmsghdr *, u32);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183
Alan Sterne041c682006-03-27 01:16:30 -0800184static BLOCKING_NOTIFIER_HEAD(inetaddr_chain);
Krister Johansen3ad7d242017-06-08 13:12:14 -0700185static BLOCKING_NOTIFIER_HEAD(inetaddr_validator_chain);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
187 int destroy);
188#ifdef CONFIG_SYSCTL
WANG Cong20e61da2014-07-25 15:25:08 -0700189static int devinet_sysctl_register(struct in_device *idev);
Pavel Emelyanov51602b22007-12-11 02:17:40 -0800190static void devinet_sysctl_unregister(struct in_device *idev);
191#else
WANG Cong20e61da2014-07-25 15:25:08 -0700192static int devinet_sysctl_register(struct in_device *idev)
Pavel Emelyanov51602b22007-12-11 02:17:40 -0800193{
WANG Cong20e61da2014-07-25 15:25:08 -0700194 return 0;
Pavel Emelyanov51602b22007-12-11 02:17:40 -0800195}
Eric Dumazet40384992012-08-03 21:06:50 +0000196static void devinet_sysctl_unregister(struct in_device *idev)
Pavel Emelyanov51602b22007-12-11 02:17:40 -0800197{
198}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199#endif
200
201/* Locks all the inet devices. */
202
203static struct in_ifaddr *inet_alloc_ifa(void)
204{
Alexey Dobriyan93adcc82008-10-28 13:25:09 -0700205 return kzalloc(sizeof(struct in_ifaddr), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206}
207
208static void inet_rcu_free_ifa(struct rcu_head *head)
209{
210 struct in_ifaddr *ifa = container_of(head, struct in_ifaddr, rcu_head);
211 if (ifa->ifa_dev)
212 in_dev_put(ifa->ifa_dev);
213 kfree(ifa);
214}
215
Eric Dumazet40384992012-08-03 21:06:50 +0000216static void inet_free_ifa(struct in_ifaddr *ifa)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217{
218 call_rcu(&ifa->rcu_head, inet_rcu_free_ifa);
219}
220
221void in_dev_finish_destroy(struct in_device *idev)
222{
223 struct net_device *dev = idev->dev;
224
Ilpo Järvinen547b7922008-07-25 21:43:18 -0700225 WARN_ON(idev->ifa_list);
226 WARN_ON(idev->mc_list);
Eric Dumazete9897072013-06-07 08:48:57 -0700227 kfree(rcu_dereference_protected(idev->mc_hash, 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228#ifdef NET_REFCNT_DEBUG
Joe Perches91df42b2012-05-15 14:11:54 +0000229 pr_debug("%s: %p=%s\n", __func__, idev, dev ? dev->name : "NIL");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230#endif
231 dev_put(dev);
232 if (!idev->dead)
Eric Dumazet9f9354b2009-11-04 22:05:10 -0800233 pr_err("Freeing alive in_device %p\n", idev);
234 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 kfree(idev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236}
Eric Dumazet9f9354b2009-11-04 22:05:10 -0800237EXPORT_SYMBOL(in_dev_finish_destroy);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238
Herbert Xu71e27da2007-06-04 23:36:06 -0700239static struct in_device *inetdev_init(struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240{
241 struct in_device *in_dev;
WANG Cong20e61da2014-07-25 15:25:08 -0700242 int err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243
244 ASSERT_RTNL();
245
Panagiotis Issaris0da974f2006-07-21 14:51:30 -0700246 in_dev = kzalloc(sizeof(*in_dev), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247 if (!in_dev)
248 goto out;
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +0900249 memcpy(&in_dev->cnf, dev_net(dev)->ipv4.devconf_dflt,
Pavel Emelyanov9355bbd2007-12-16 13:32:16 -0800250 sizeof(in_dev->cnf));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 in_dev->cnf.sysctl = NULL;
252 in_dev->dev = dev;
Eric Dumazet9f9354b2009-11-04 22:05:10 -0800253 in_dev->arp_parms = neigh_parms_alloc(dev, &arp_tbl);
254 if (!in_dev->arp_parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 goto out_kfree;
Ben Hutchings0187bdf2008-06-19 16:15:47 -0700256 if (IPV4_DEVCONF(in_dev->cnf, FORWARDING))
257 dev_disable_lro(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258 /* Reference in_dev->dev */
259 dev_hold(dev);
David L Stevens30c4cf52007-01-04 12:31:14 -0800260 /* Account for reference dev->ip_ptr (below) */
Reshetova, Elena7658b362017-06-30 13:08:03 +0300261 refcount_set(&in_dev->refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262
WANG Cong20e61da2014-07-25 15:25:08 -0700263 err = devinet_sysctl_register(in_dev);
264 if (err) {
265 in_dev->dead = 1;
266 in_dev_put(in_dev);
267 in_dev = NULL;
268 goto out;
269 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270 ip_mc_init_dev(in_dev);
271 if (dev->flags & IFF_UP)
272 ip_mc_up(in_dev);
Jarek Poplawski483479e2007-01-09 14:38:31 -0800273
David L Stevens30c4cf52007-01-04 12:31:14 -0800274 /* we can receive as soon as ip_ptr is set -- do this last */
Eric Dumazetcf778b02012-01-12 04:41:32 +0000275 rcu_assign_pointer(dev->ip_ptr, in_dev);
Jarek Poplawski483479e2007-01-09 14:38:31 -0800276out:
WANG Cong20e61da2014-07-25 15:25:08 -0700277 return in_dev ?: ERR_PTR(err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278out_kfree:
279 kfree(in_dev);
280 in_dev = NULL;
281 goto out;
282}
283
284static void in_dev_rcu_put(struct rcu_head *head)
285{
286 struct in_device *idev = container_of(head, struct in_device, rcu_head);
287 in_dev_put(idev);
288}
289
290static void inetdev_destroy(struct in_device *in_dev)
291{
292 struct in_ifaddr *ifa;
293 struct net_device *dev;
294
295 ASSERT_RTNL();
296
297 dev = in_dev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298
299 in_dev->dead = 1;
300
301 ip_mc_destroy_dev(in_dev);
302
303 while ((ifa = in_dev->ifa_list) != NULL) {
304 inet_del_ifa(in_dev, &in_dev->ifa_list, 0);
305 inet_free_ifa(ifa);
306 }
307
Stephen Hemmingera9b3cd72011-08-01 16:19:00 +0000308 RCU_INIT_POINTER(dev->ip_ptr, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309
Pavel Emelyanov51602b22007-12-11 02:17:40 -0800310 devinet_sysctl_unregister(in_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311 neigh_parms_release(&arp_tbl, in_dev->arp_parms);
312 arp_ifdown(dev);
313
314 call_rcu(&in_dev->rcu_head, in_dev_rcu_put);
315}
316
Al Viroff428d72006-09-26 22:13:35 -0700317int inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318{
319 rcu_read_lock();
320 for_primary_ifa(in_dev) {
321 if (inet_ifa_match(a, ifa)) {
322 if (!b || inet_ifa_match(b, ifa)) {
323 rcu_read_unlock();
324 return 1;
325 }
326 }
327 } endfor_ifa(in_dev);
328 rcu_read_unlock();
329 return 0;
330}
331
Thomas Grafd6062cb2006-08-15 00:33:59 -0700332static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
Eric W. Biederman15e47302012-09-07 20:12:54 +0000333 int destroy, struct nlmsghdr *nlh, u32 portid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334{
Harald Welte8f937c62005-05-29 20:23:46 -0700335 struct in_ifaddr *promote = NULL;
Jamal Hadi Salim0ff60a42005-11-22 14:47:37 -0800336 struct in_ifaddr *ifa, *ifa1 = *ifap;
337 struct in_ifaddr *last_prim = in_dev->ifa_list;
338 struct in_ifaddr *prev_prom = NULL;
339 int do_promote = IN_DEV_PROMOTE_SECONDARIES(in_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340
341 ASSERT_RTNL();
342
David S. Millerfbd40ea2016-03-13 23:28:00 -0400343 if (in_dev->dead)
344 goto no_promotions;
345
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900346 /* 1. Deleting primary ifaddr forces deletion all secondaries
Harald Welte8f937c62005-05-29 20:23:46 -0700347 * unless alias promotion is set
348 **/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349
350 if (!(ifa1->ifa_flags & IFA_F_SECONDARY)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 struct in_ifaddr **ifap1 = &ifa1->ifa_next;
352
353 while ((ifa = *ifap1) != NULL) {
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900354 if (!(ifa->ifa_flags & IFA_F_SECONDARY) &&
Jamal Hadi Salim0ff60a42005-11-22 14:47:37 -0800355 ifa1->ifa_scope <= ifa->ifa_scope)
356 last_prim = ifa;
357
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358 if (!(ifa->ifa_flags & IFA_F_SECONDARY) ||
359 ifa1->ifa_mask != ifa->ifa_mask ||
360 !inet_ifa_match(ifa1->ifa_address, ifa)) {
361 ifap1 = &ifa->ifa_next;
Jamal Hadi Salim0ff60a42005-11-22 14:47:37 -0800362 prev_prom = ifa;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363 continue;
364 }
365
Jamal Hadi Salim0ff60a42005-11-22 14:47:37 -0800366 if (!do_promote) {
David S. Millerfd23c3b2011-02-18 12:42:28 -0800367 inet_hash_remove(ifa);
Harald Welte8f937c62005-05-29 20:23:46 -0700368 *ifap1 = ifa->ifa_next;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369
Eric W. Biederman15e47302012-09-07 20:12:54 +0000370 rtmsg_ifa(RTM_DELADDR, ifa, nlh, portid);
Alan Sterne041c682006-03-27 01:16:30 -0800371 blocking_notifier_call_chain(&inetaddr_chain,
372 NETDEV_DOWN, ifa);
Harald Welte8f937c62005-05-29 20:23:46 -0700373 inet_free_ifa(ifa);
374 } else {
375 promote = ifa;
376 break;
377 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 }
379 }
380
Julian Anastasov2d230e22011-03-19 12:13:52 +0000381 /* On promotion all secondaries from subnet are changing
382 * the primary IP, we must remove all their routes silently
383 * and later to add them back with new prefsrc. Do this
384 * while all addresses are on the device list.
385 */
386 for (ifa = promote; ifa; ifa = ifa->ifa_next) {
387 if (ifa1->ifa_mask == ifa->ifa_mask &&
388 inet_ifa_match(ifa1->ifa_address, ifa))
389 fib_del_ifaddr(ifa, ifa1);
390 }
391
David S. Millerfbd40ea2016-03-13 23:28:00 -0400392no_promotions:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 /* 2. Unlink it */
394
395 *ifap = ifa1->ifa_next;
David S. Millerfd23c3b2011-02-18 12:42:28 -0800396 inet_hash_remove(ifa1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397
398 /* 3. Announce address deletion */
399
400 /* Send message first, then call notifier.
401 At first sight, FIB update triggered by notifier
402 will refer to already deleted ifaddr, that could confuse
403 netlink listeners. It is not true: look, gated sees
404 that route deleted and if it still thinks that ifaddr
405 is valid, it will try to restore deleted routes... Grr.
406 So that, this order is correct.
407 */
Eric W. Biederman15e47302012-09-07 20:12:54 +0000408 rtmsg_ifa(RTM_DELADDR, ifa1, nlh, portid);
Alan Sterne041c682006-03-27 01:16:30 -0800409 blocking_notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1);
Jamal Hadi Salim0ff60a42005-11-22 14:47:37 -0800410
411 if (promote) {
Julian Anastasov04024b92011-03-19 12:13:54 +0000412 struct in_ifaddr *next_sec = promote->ifa_next;
Jamal Hadi Salim0ff60a42005-11-22 14:47:37 -0800413
414 if (prev_prom) {
415 prev_prom->ifa_next = promote->ifa_next;
416 promote->ifa_next = last_prim->ifa_next;
417 last_prim->ifa_next = promote;
418 }
419
420 promote->ifa_flags &= ~IFA_F_SECONDARY;
Eric W. Biederman15e47302012-09-07 20:12:54 +0000421 rtmsg_ifa(RTM_NEWADDR, promote, nlh, portid);
Alan Sterne041c682006-03-27 01:16:30 -0800422 blocking_notifier_call_chain(&inetaddr_chain,
423 NETDEV_UP, promote);
Julian Anastasov04024b92011-03-19 12:13:54 +0000424 for (ifa = next_sec; ifa; ifa = ifa->ifa_next) {
Jamal Hadi Salim0ff60a42005-11-22 14:47:37 -0800425 if (ifa1->ifa_mask != ifa->ifa_mask ||
426 !inet_ifa_match(ifa1->ifa_address, ifa))
427 continue;
428 fib_add_ifaddr(ifa);
429 }
430
431 }
Herbert Xu63630972007-06-07 18:35:38 -0700432 if (destroy)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433 inet_free_ifa(ifa1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434}
435
Thomas Grafd6062cb2006-08-15 00:33:59 -0700436static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
437 int destroy)
438{
439 __inet_del_ifa(in_dev, ifap, destroy, NULL, 0);
440}
441
Jiri Pirko5c766d62013-01-24 09:41:41 +0000442static void check_lifetime(struct work_struct *work);
443
444static DECLARE_DELAYED_WORK(check_lifetime_work, check_lifetime);
445
Thomas Grafd6062cb2006-08-15 00:33:59 -0700446static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh,
David Ahernde95e042017-10-18 09:56:54 -0700447 u32 portid, struct netlink_ext_ack *extack)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448{
449 struct in_device *in_dev = ifa->ifa_dev;
450 struct in_ifaddr *ifa1, **ifap, **last_primary;
Krister Johansen3ad7d242017-06-08 13:12:14 -0700451 struct in_validator_info ivi;
452 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453
454 ASSERT_RTNL();
455
456 if (!ifa->ifa_local) {
457 inet_free_ifa(ifa);
458 return 0;
459 }
460
461 ifa->ifa_flags &= ~IFA_F_SECONDARY;
462 last_primary = &in_dev->ifa_list;
463
464 for (ifap = &in_dev->ifa_list; (ifa1 = *ifap) != NULL;
465 ifap = &ifa1->ifa_next) {
466 if (!(ifa1->ifa_flags & IFA_F_SECONDARY) &&
467 ifa->ifa_scope <= ifa1->ifa_scope)
468 last_primary = &ifa1->ifa_next;
469 if (ifa1->ifa_mask == ifa->ifa_mask &&
470 inet_ifa_match(ifa1->ifa_address, ifa)) {
471 if (ifa1->ifa_local == ifa->ifa_local) {
472 inet_free_ifa(ifa);
473 return -EEXIST;
474 }
475 if (ifa1->ifa_scope != ifa->ifa_scope) {
476 inet_free_ifa(ifa);
477 return -EINVAL;
478 }
479 ifa->ifa_flags |= IFA_F_SECONDARY;
480 }
481 }
482
Krister Johansen3ad7d242017-06-08 13:12:14 -0700483 /* Allow any devices that wish to register ifaddr validtors to weigh
484 * in now, before changes are committed. The rntl lock is serializing
485 * access here, so the state should not change between a validator call
486 * and a final notify on commit. This isn't invoked on promotion under
487 * the assumption that validators are checking the address itself, and
488 * not the flags.
489 */
490 ivi.ivi_addr = ifa->ifa_address;
491 ivi.ivi_dev = ifa->ifa_dev;
David Ahernde95e042017-10-18 09:56:54 -0700492 ivi.extack = extack;
Krister Johansen3ad7d242017-06-08 13:12:14 -0700493 ret = blocking_notifier_call_chain(&inetaddr_validator_chain,
494 NETDEV_UP, &ivi);
495 ret = notifier_to_errno(ret);
496 if (ret) {
497 inet_free_ifa(ifa);
498 return ret;
499 }
500
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 if (!(ifa->ifa_flags & IFA_F_SECONDARY)) {
Aruna-Hewapathirane63862b52014-01-11 07:15:59 -0500502 prandom_seed((__force u32) ifa->ifa_local);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 ifap = last_primary;
504 }
505
506 ifa->ifa_next = *ifap;
507 *ifap = ifa;
508
David S. Millerfd23c3b2011-02-18 12:42:28 -0800509 inet_hash_insert(dev_net(in_dev->dev), ifa);
510
Jiri Pirko5c766d62013-01-24 09:41:41 +0000511 cancel_delayed_work(&check_lifetime_work);
viresh kumar906e0732014-01-22 12:23:32 +0530512 queue_delayed_work(system_power_efficient_wq, &check_lifetime_work, 0);
Jiri Pirko5c766d62013-01-24 09:41:41 +0000513
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514 /* Send message first, then call notifier.
515 Notifier will trigger FIB update, so that
516 listeners of netlink will know about new ifaddr */
Eric W. Biederman15e47302012-09-07 20:12:54 +0000517 rtmsg_ifa(RTM_NEWADDR, ifa, nlh, portid);
Alan Sterne041c682006-03-27 01:16:30 -0800518 blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519
520 return 0;
521}
522
Thomas Grafd6062cb2006-08-15 00:33:59 -0700523static int inet_insert_ifa(struct in_ifaddr *ifa)
524{
David Ahernde95e042017-10-18 09:56:54 -0700525 return __inet_insert_ifa(ifa, NULL, 0, NULL);
Thomas Grafd6062cb2006-08-15 00:33:59 -0700526}
527
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528static int inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa)
529{
Herbert Xue5ed6392005-10-03 14:35:55 -0700530 struct in_device *in_dev = __in_dev_get_rtnl(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531
532 ASSERT_RTNL();
533
534 if (!in_dev) {
Herbert Xu71e27da2007-06-04 23:36:06 -0700535 inet_free_ifa(ifa);
536 return -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 }
Herbert Xu71e27da2007-06-04 23:36:06 -0700538 ipv4_devconf_setall(in_dev);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +0100539 neigh_parms_data_state_setall(in_dev->arp_parms);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 if (ifa->ifa_dev != in_dev) {
Ilpo Järvinen547b7922008-07-25 21:43:18 -0700541 WARN_ON(ifa->ifa_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542 in_dev_hold(in_dev);
543 ifa->ifa_dev = in_dev;
544 }
Joe Perchesf97c1e02007-12-16 13:45:43 -0800545 if (ipv4_is_loopback(ifa->ifa_local))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 ifa->ifa_scope = RT_SCOPE_HOST;
547 return inet_insert_ifa(ifa);
548}
549
Eric Dumazet8723e1b2010-10-19 00:39:26 +0000550/* Caller must hold RCU or RTNL :
551 * We dont take a reference on found in_device
552 */
Denis V. Lunev7fee0ca2008-01-21 17:32:38 -0800553struct in_device *inetdev_by_index(struct net *net, int ifindex)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554{
555 struct net_device *dev;
556 struct in_device *in_dev = NULL;
Eric Dumazetc148fc22009-11-01 19:23:04 +0000557
558 rcu_read_lock();
559 dev = dev_get_by_index_rcu(net, ifindex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 if (dev)
Eric Dumazet8723e1b2010-10-19 00:39:26 +0000561 in_dev = rcu_dereference_rtnl(dev->ip_ptr);
Eric Dumazetc148fc22009-11-01 19:23:04 +0000562 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563 return in_dev;
564}
Eric Dumazet9f9354b2009-11-04 22:05:10 -0800565EXPORT_SYMBOL(inetdev_by_index);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566
567/* Called only from RTNL semaphored context. No locks. */
568
Al Viro60cad5d2006-09-26 22:17:09 -0700569struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, __be32 prefix,
570 __be32 mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571{
572 ASSERT_RTNL();
573
574 for_primary_ifa(in_dev) {
575 if (ifa->ifa_mask == mask && inet_ifa_match(prefix, ifa))
576 return ifa;
577 } endfor_ifa(in_dev);
578 return NULL;
579}
580
Madhu Challa93a714d2015-02-25 09:58:35 -0800581static int ip_mc_config(struct sock *sk, bool join, const struct in_ifaddr *ifa)
582{
583 struct ip_mreqn mreq = {
584 .imr_multiaddr.s_addr = ifa->ifa_address,
585 .imr_ifindex = ifa->ifa_dev->dev->ifindex,
586 };
587 int ret;
588
589 ASSERT_RTNL();
590
591 lock_sock(sk);
592 if (join)
Marcelo Ricardo Leitner54ff9ef2015-03-18 14:50:43 -0300593 ret = ip_mc_join_group(sk, &mreq);
Madhu Challa93a714d2015-02-25 09:58:35 -0800594 else
Marcelo Ricardo Leitner54ff9ef2015-03-18 14:50:43 -0300595 ret = ip_mc_leave_group(sk, &mreq);
Madhu Challa93a714d2015-02-25 09:58:35 -0800596 release_sock(sk);
597
598 return ret;
599}
600
David Ahernc21ef3e2017-04-16 09:48:24 -0700601static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh,
602 struct netlink_ext_ack *extack)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +0900604 struct net *net = sock_net(skb->sk);
Thomas Grafdfdd5fd2006-08-04 23:04:17 -0700605 struct nlattr *tb[IFA_MAX+1];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 struct in_device *in_dev;
Thomas Grafdfdd5fd2006-08-04 23:04:17 -0700607 struct ifaddrmsg *ifm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608 struct in_ifaddr *ifa, **ifap;
Thomas Grafdfdd5fd2006-08-04 23:04:17 -0700609 int err = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610
611 ASSERT_RTNL();
612
Johannes Bergfceb6432017-04-12 14:34:07 +0200613 err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv4_policy,
David Ahernc21ef3e2017-04-16 09:48:24 -0700614 extack);
Thomas Grafdfdd5fd2006-08-04 23:04:17 -0700615 if (err < 0)
616 goto errout;
617
618 ifm = nlmsg_data(nlh);
Denis V. Lunev7fee0ca2008-01-21 17:32:38 -0800619 in_dev = inetdev_by_index(net, ifm->ifa_index);
Ian Morris51456b22015-04-03 09:17:26 +0100620 if (!in_dev) {
Thomas Grafdfdd5fd2006-08-04 23:04:17 -0700621 err = -ENODEV;
622 goto errout;
623 }
624
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
626 ifap = &ifa->ifa_next) {
Thomas Grafdfdd5fd2006-08-04 23:04:17 -0700627 if (tb[IFA_LOCAL] &&
Jiri Benc67b61f62015-03-29 16:59:26 +0200628 ifa->ifa_local != nla_get_in_addr(tb[IFA_LOCAL]))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629 continue;
Thomas Grafdfdd5fd2006-08-04 23:04:17 -0700630
631 if (tb[IFA_LABEL] && nla_strcmp(tb[IFA_LABEL], ifa->ifa_label))
632 continue;
633
634 if (tb[IFA_ADDRESS] &&
635 (ifm->ifa_prefixlen != ifa->ifa_prefixlen ||
Jiri Benc67b61f62015-03-29 16:59:26 +0200636 !inet_ifa_match(nla_get_in_addr(tb[IFA_ADDRESS]), ifa)))
Thomas Grafdfdd5fd2006-08-04 23:04:17 -0700637 continue;
638
Madhu Challa93a714d2015-02-25 09:58:35 -0800639 if (ipv4_is_multicast(ifa->ifa_address))
640 ip_mc_config(net->ipv4.mc_autojoin_sk, false, ifa);
Eric W. Biederman15e47302012-09-07 20:12:54 +0000641 __inet_del_ifa(in_dev, ifap, 1, nlh, NETLINK_CB(skb).portid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642 return 0;
643 }
Thomas Grafdfdd5fd2006-08-04 23:04:17 -0700644
645 err = -EADDRNOTAVAIL;
646errout:
647 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648}
649
Jiri Pirko5c766d62013-01-24 09:41:41 +0000650#define INFINITY_LIFE_TIME 0xFFFFFFFF
651
652static void check_lifetime(struct work_struct *work)
653{
654 unsigned long now, next, next_sec, next_sched;
655 struct in_ifaddr *ifa;
Jiri Pirkoc988d1e2013-04-04 23:39:39 +0000656 struct hlist_node *n;
Jiri Pirko5c766d62013-01-24 09:41:41 +0000657 int i;
658
659 now = jiffies;
660 next = round_jiffies_up(now + ADDR_CHECK_FREQUENCY);
661
Jiri Pirko5c766d62013-01-24 09:41:41 +0000662 for (i = 0; i < IN4_ADDR_HSIZE; i++) {
Jiri Pirkoc988d1e2013-04-04 23:39:39 +0000663 bool change_needed = false;
664
665 rcu_read_lock();
Sasha Levinb67bfe02013-02-27 17:06:00 -0800666 hlist_for_each_entry_rcu(ifa, &inet_addr_lst[i], hash) {
Jiri Pirko5c766d62013-01-24 09:41:41 +0000667 unsigned long age;
668
669 if (ifa->ifa_flags & IFA_F_PERMANENT)
670 continue;
671
672 /* We try to batch several events at once. */
673 age = (now - ifa->ifa_tstamp +
674 ADDRCONF_TIMER_FUZZ_MINUS) / HZ;
675
676 if (ifa->ifa_valid_lft != INFINITY_LIFE_TIME &&
677 age >= ifa->ifa_valid_lft) {
Jiri Pirkoc988d1e2013-04-04 23:39:39 +0000678 change_needed = true;
Jiri Pirko5c766d62013-01-24 09:41:41 +0000679 } else if (ifa->ifa_preferred_lft ==
680 INFINITY_LIFE_TIME) {
681 continue;
682 } else if (age >= ifa->ifa_preferred_lft) {
683 if (time_before(ifa->ifa_tstamp +
684 ifa->ifa_valid_lft * HZ, next))
685 next = ifa->ifa_tstamp +
686 ifa->ifa_valid_lft * HZ;
687
Jiri Pirkoc988d1e2013-04-04 23:39:39 +0000688 if (!(ifa->ifa_flags & IFA_F_DEPRECATED))
689 change_needed = true;
Jiri Pirko5c766d62013-01-24 09:41:41 +0000690 } else if (time_before(ifa->ifa_tstamp +
691 ifa->ifa_preferred_lft * HZ,
692 next)) {
693 next = ifa->ifa_tstamp +
694 ifa->ifa_preferred_lft * HZ;
695 }
696 }
Jiri Pirkoc988d1e2013-04-04 23:39:39 +0000697 rcu_read_unlock();
698 if (!change_needed)
699 continue;
700 rtnl_lock();
701 hlist_for_each_entry_safe(ifa, n, &inet_addr_lst[i], hash) {
702 unsigned long age;
703
704 if (ifa->ifa_flags & IFA_F_PERMANENT)
705 continue;
706
707 /* We try to batch several events at once. */
708 age = (now - ifa->ifa_tstamp +
709 ADDRCONF_TIMER_FUZZ_MINUS) / HZ;
710
711 if (ifa->ifa_valid_lft != INFINITY_LIFE_TIME &&
712 age >= ifa->ifa_valid_lft) {
713 struct in_ifaddr **ifap;
714
715 for (ifap = &ifa->ifa_dev->ifa_list;
716 *ifap != NULL; ifap = &(*ifap)->ifa_next) {
717 if (*ifap == ifa) {
718 inet_del_ifa(ifa->ifa_dev,
719 ifap, 1);
720 break;
721 }
722 }
723 } else if (ifa->ifa_preferred_lft !=
724 INFINITY_LIFE_TIME &&
725 age >= ifa->ifa_preferred_lft &&
726 !(ifa->ifa_flags & IFA_F_DEPRECATED)) {
727 ifa->ifa_flags |= IFA_F_DEPRECATED;
728 rtmsg_ifa(RTM_NEWADDR, ifa, NULL, 0);
729 }
730 }
731 rtnl_unlock();
Jiri Pirko5c766d62013-01-24 09:41:41 +0000732 }
Jiri Pirko5c766d62013-01-24 09:41:41 +0000733
734 next_sec = round_jiffies_up(next);
735 next_sched = next;
736
737 /* If rounded timeout is accurate enough, accept it. */
738 if (time_before(next_sec, next + ADDRCONF_TIMER_FUZZ))
739 next_sched = next_sec;
740
741 now = jiffies;
742 /* And minimum interval is ADDRCONF_TIMER_FUZZ_MAX. */
743 if (time_before(next_sched, now + ADDRCONF_TIMER_FUZZ_MAX))
744 next_sched = now + ADDRCONF_TIMER_FUZZ_MAX;
745
viresh kumar906e0732014-01-22 12:23:32 +0530746 queue_delayed_work(system_power_efficient_wq, &check_lifetime_work,
747 next_sched - now);
Jiri Pirko5c766d62013-01-24 09:41:41 +0000748}
749
750static void set_ifa_lifetime(struct in_ifaddr *ifa, __u32 valid_lft,
751 __u32 prefered_lft)
752{
753 unsigned long timeout;
754
755 ifa->ifa_flags &= ~(IFA_F_PERMANENT | IFA_F_DEPRECATED);
756
757 timeout = addrconf_timeout_fixup(valid_lft, HZ);
758 if (addrconf_finite_timeout(timeout))
759 ifa->ifa_valid_lft = timeout;
760 else
761 ifa->ifa_flags |= IFA_F_PERMANENT;
762
763 timeout = addrconf_timeout_fixup(prefered_lft, HZ);
764 if (addrconf_finite_timeout(timeout)) {
765 if (timeout == 0)
766 ifa->ifa_flags |= IFA_F_DEPRECATED;
767 ifa->ifa_preferred_lft = timeout;
768 }
769 ifa->ifa_tstamp = jiffies;
770 if (!ifa->ifa_cstamp)
771 ifa->ifa_cstamp = ifa->ifa_tstamp;
772}
773
774static struct in_ifaddr *rtm_to_ifaddr(struct net *net, struct nlmsghdr *nlh,
775 __u32 *pvalid_lft, __u32 *pprefered_lft)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776{
Thomas Graf5c753972006-08-04 23:03:53 -0700777 struct nlattr *tb[IFA_MAX+1];
778 struct in_ifaddr *ifa;
779 struct ifaddrmsg *ifm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 struct net_device *dev;
781 struct in_device *in_dev;
Denis V. Lunev7b218572008-01-31 18:47:00 -0800782 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783
Johannes Bergfceb6432017-04-12 14:34:07 +0200784 err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv4_policy,
785 NULL);
Thomas Graf5c753972006-08-04 23:03:53 -0700786 if (err < 0)
787 goto errout;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788
Thomas Graf5c753972006-08-04 23:03:53 -0700789 ifm = nlmsg_data(nlh);
Denis V. Lunev7b218572008-01-31 18:47:00 -0800790 err = -EINVAL;
Ian Morris51456b22015-04-03 09:17:26 +0100791 if (ifm->ifa_prefixlen > 32 || !tb[IFA_LOCAL])
Thomas Graf5c753972006-08-04 23:03:53 -0700792 goto errout;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793
Denis V. Lunev4b8aa9a2008-01-31 18:47:40 -0800794 dev = __dev_get_by_index(net, ifm->ifa_index);
Denis V. Lunev7b218572008-01-31 18:47:00 -0800795 err = -ENODEV;
Ian Morris51456b22015-04-03 09:17:26 +0100796 if (!dev)
Thomas Graf5c753972006-08-04 23:03:53 -0700797 goto errout;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798
Thomas Graf5c753972006-08-04 23:03:53 -0700799 in_dev = __in_dev_get_rtnl(dev);
Denis V. Lunev7b218572008-01-31 18:47:00 -0800800 err = -ENOBUFS;
Ian Morris51456b22015-04-03 09:17:26 +0100801 if (!in_dev)
Herbert Xu71e27da2007-06-04 23:36:06 -0700802 goto errout;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803
Thomas Graf5c753972006-08-04 23:03:53 -0700804 ifa = inet_alloc_ifa();
Ian Morris51456b22015-04-03 09:17:26 +0100805 if (!ifa)
Thomas Graf5c753972006-08-04 23:03:53 -0700806 /*
807 * A potential indev allocation can be left alive, it stays
808 * assigned to its device and is destroy with it.
809 */
Thomas Graf5c753972006-08-04 23:03:53 -0700810 goto errout;
Thomas Graf5c753972006-08-04 23:03:53 -0700811
Pavel Emelyanova4e65d32007-12-07 23:55:43 -0800812 ipv4_devconf_setall(in_dev);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +0100813 neigh_parms_data_state_setall(in_dev->arp_parms);
Thomas Graf5c753972006-08-04 23:03:53 -0700814 in_dev_hold(in_dev);
815
Ian Morris51456b22015-04-03 09:17:26 +0100816 if (!tb[IFA_ADDRESS])
Thomas Graf5c753972006-08-04 23:03:53 -0700817 tb[IFA_ADDRESS] = tb[IFA_LOCAL];
818
David S. Millerfd23c3b2011-02-18 12:42:28 -0800819 INIT_HLIST_NODE(&ifa->hash);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820 ifa->ifa_prefixlen = ifm->ifa_prefixlen;
821 ifa->ifa_mask = inet_make_mask(ifm->ifa_prefixlen);
Jiri Pirkoad6c8132013-12-08 12:16:10 +0100822 ifa->ifa_flags = tb[IFA_FLAGS] ? nla_get_u32(tb[IFA_FLAGS]) :
823 ifm->ifa_flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 ifa->ifa_scope = ifm->ifa_scope;
Thomas Graf5c753972006-08-04 23:03:53 -0700825 ifa->ifa_dev = in_dev;
826
Jiri Benc67b61f62015-03-29 16:59:26 +0200827 ifa->ifa_local = nla_get_in_addr(tb[IFA_LOCAL]);
828 ifa->ifa_address = nla_get_in_addr(tb[IFA_ADDRESS]);
Thomas Graf5c753972006-08-04 23:03:53 -0700829
830 if (tb[IFA_BROADCAST])
Jiri Benc67b61f62015-03-29 16:59:26 +0200831 ifa->ifa_broadcast = nla_get_in_addr(tb[IFA_BROADCAST]);
Thomas Graf5c753972006-08-04 23:03:53 -0700832
Thomas Graf5c753972006-08-04 23:03:53 -0700833 if (tb[IFA_LABEL])
834 nla_strlcpy(ifa->ifa_label, tb[IFA_LABEL], IFNAMSIZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 else
836 memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
837
Jiri Pirko5c766d62013-01-24 09:41:41 +0000838 if (tb[IFA_CACHEINFO]) {
839 struct ifa_cacheinfo *ci;
840
841 ci = nla_data(tb[IFA_CACHEINFO]);
842 if (!ci->ifa_valid || ci->ifa_prefered > ci->ifa_valid) {
843 err = -EINVAL;
Daniel Borkmann446266b2013-08-02 11:32:43 +0200844 goto errout_free;
Jiri Pirko5c766d62013-01-24 09:41:41 +0000845 }
846 *pvalid_lft = ci->ifa_valid;
847 *pprefered_lft = ci->ifa_prefered;
848 }
849
Thomas Graf5c753972006-08-04 23:03:53 -0700850 return ifa;
851
Daniel Borkmann446266b2013-08-02 11:32:43 +0200852errout_free:
853 inet_free_ifa(ifa);
Thomas Graf5c753972006-08-04 23:03:53 -0700854errout:
855 return ERR_PTR(err);
856}
857
Jiri Pirko5c766d62013-01-24 09:41:41 +0000858static struct in_ifaddr *find_matching_ifa(struct in_ifaddr *ifa)
859{
860 struct in_device *in_dev = ifa->ifa_dev;
861 struct in_ifaddr *ifa1, **ifap;
862
863 if (!ifa->ifa_local)
864 return NULL;
865
866 for (ifap = &in_dev->ifa_list; (ifa1 = *ifap) != NULL;
867 ifap = &ifa1->ifa_next) {
868 if (ifa1->ifa_mask == ifa->ifa_mask &&
869 inet_ifa_match(ifa1->ifa_address, ifa) &&
870 ifa1->ifa_local == ifa->ifa_local)
871 return ifa1;
872 }
873 return NULL;
874}
875
David Ahernc21ef3e2017-04-16 09:48:24 -0700876static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
877 struct netlink_ext_ack *extack)
Thomas Graf5c753972006-08-04 23:03:53 -0700878{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +0900879 struct net *net = sock_net(skb->sk);
Thomas Graf5c753972006-08-04 23:03:53 -0700880 struct in_ifaddr *ifa;
Jiri Pirko5c766d62013-01-24 09:41:41 +0000881 struct in_ifaddr *ifa_existing;
882 __u32 valid_lft = INFINITY_LIFE_TIME;
883 __u32 prefered_lft = INFINITY_LIFE_TIME;
Thomas Graf5c753972006-08-04 23:03:53 -0700884
885 ASSERT_RTNL();
886
Jiri Pirko5c766d62013-01-24 09:41:41 +0000887 ifa = rtm_to_ifaddr(net, nlh, &valid_lft, &prefered_lft);
Thomas Graf5c753972006-08-04 23:03:53 -0700888 if (IS_ERR(ifa))
889 return PTR_ERR(ifa);
890
Jiri Pirko5c766d62013-01-24 09:41:41 +0000891 ifa_existing = find_matching_ifa(ifa);
892 if (!ifa_existing) {
893 /* It would be best to check for !NLM_F_CREATE here but
stephen hemminger614d0562014-05-16 20:46:58 -0700894 * userspace already relies on not having to provide this.
Jiri Pirko5c766d62013-01-24 09:41:41 +0000895 */
896 set_ifa_lifetime(ifa, valid_lft, prefered_lft);
Madhu Challa93a714d2015-02-25 09:58:35 -0800897 if (ifa->ifa_flags & IFA_F_MCAUTOJOIN) {
898 int ret = ip_mc_config(net->ipv4.mc_autojoin_sk,
899 true, ifa);
900
901 if (ret < 0) {
902 inet_free_ifa(ifa);
903 return ret;
904 }
905 }
David Ahernde95e042017-10-18 09:56:54 -0700906 return __inet_insert_ifa(ifa, nlh, NETLINK_CB(skb).portid,
907 extack);
Jiri Pirko5c766d62013-01-24 09:41:41 +0000908 } else {
909 inet_free_ifa(ifa);
910
911 if (nlh->nlmsg_flags & NLM_F_EXCL ||
912 !(nlh->nlmsg_flags & NLM_F_REPLACE))
913 return -EEXIST;
Jiri Pirko34e2ed32013-04-04 08:33:00 +0000914 ifa = ifa_existing;
915 set_ifa_lifetime(ifa, valid_lft, prefered_lft);
Jiri Pirko05a324b2013-04-04 23:39:38 +0000916 cancel_delayed_work(&check_lifetime_work);
viresh kumar906e0732014-01-22 12:23:32 +0530917 queue_delayed_work(system_power_efficient_wq,
918 &check_lifetime_work, 0);
Jiri Pirko34e2ed32013-04-04 08:33:00 +0000919 rtmsg_ifa(RTM_NEWADDR, ifa, nlh, NETLINK_CB(skb).portid);
Jiri Pirko5c766d62013-01-24 09:41:41 +0000920 }
921 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922}
923
924/*
925 * Determine a default network mask, based on the IP address.
926 */
927
Eric Dumazet40384992012-08-03 21:06:50 +0000928static int inet_abc_len(__be32 addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929{
930 int rc = -1; /* Something else, probably a multicast. */
931
Joe Perchesf97c1e02007-12-16 13:45:43 -0800932 if (ipv4_is_zeronet(addr))
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900933 rc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934 else {
Al Viro714e85b2006-11-14 20:51:49 -0800935 __u32 haddr = ntohl(addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936
Al Viro714e85b2006-11-14 20:51:49 -0800937 if (IN_CLASSA(haddr))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 rc = 8;
Al Viro714e85b2006-11-14 20:51:49 -0800939 else if (IN_CLASSB(haddr))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 rc = 16;
Al Viro714e85b2006-11-14 20:51:49 -0800941 else if (IN_CLASSC(haddr))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 rc = 24;
943 }
944
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900945 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946}
947
948
Denis V. Luneve5b13cb2008-02-28 20:51:43 -0800949int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950{
951 struct ifreq ifr;
952 struct sockaddr_in sin_orig;
953 struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr;
954 struct in_device *in_dev;
955 struct in_ifaddr **ifap = NULL;
956 struct in_ifaddr *ifa = NULL;
957 struct net_device *dev;
958 char *colon;
959 int ret = -EFAULT;
960 int tryaddrmatch = 0;
961
962 /*
963 * Fetch the caller's info block into kernel space
964 */
965
966 if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
967 goto out;
968 ifr.ifr_name[IFNAMSIZ - 1] = 0;
969
970 /* save original address for comparison */
971 memcpy(&sin_orig, sin, sizeof(*sin));
972
973 colon = strchr(ifr.ifr_name, ':');
974 if (colon)
975 *colon = 0;
976
Denis V. Luneve5b13cb2008-02-28 20:51:43 -0800977 dev_load(net, ifr.ifr_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978
Stephen Hemminger132adf52007-03-08 20:44:43 -0800979 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980 case SIOCGIFADDR: /* Get interface address */
981 case SIOCGIFBRDADDR: /* Get the broadcast address */
982 case SIOCGIFDSTADDR: /* Get the destination address */
983 case SIOCGIFNETMASK: /* Get the netmask for the interface */
984 /* Note that these ioctls will not sleep,
985 so that we do not impose a lock.
986 One day we will be forced to put shlock here (I mean SMP)
987 */
988 tryaddrmatch = (sin_orig.sin_family == AF_INET);
989 memset(sin, 0, sizeof(*sin));
990 sin->sin_family = AF_INET;
991 break;
992
993 case SIOCSIFFLAGS:
Zhao Hongjiangbf5b30b2012-09-20 22:37:25 +0000994 ret = -EPERM;
Eric W. Biederman52e804c2012-11-16 03:03:05 +0000995 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996 goto out;
997 break;
998 case SIOCSIFADDR: /* Set interface address (and family) */
999 case SIOCSIFBRDADDR: /* Set the broadcast address */
1000 case SIOCSIFDSTADDR: /* Set the destination address */
1001 case SIOCSIFNETMASK: /* Set the netmask for the interface */
Zhao Hongjiangbf5b30b2012-09-20 22:37:25 +00001002 ret = -EPERM;
Eric W. Biederman52e804c2012-11-16 03:03:05 +00001003 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 goto out;
1005 ret = -EINVAL;
1006 if (sin->sin_family != AF_INET)
1007 goto out;
1008 break;
1009 default:
1010 ret = -EINVAL;
1011 goto out;
1012 }
1013
1014 rtnl_lock();
1015
1016 ret = -ENODEV;
Eric Dumazet9f9354b2009-11-04 22:05:10 -08001017 dev = __dev_get_by_name(net, ifr.ifr_name);
1018 if (!dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 goto done;
1020
1021 if (colon)
1022 *colon = ':';
1023
Eric Dumazet9f9354b2009-11-04 22:05:10 -08001024 in_dev = __in_dev_get_rtnl(dev);
1025 if (in_dev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 if (tryaddrmatch) {
1027 /* Matthias Andree */
1028 /* compare label and address (4.4BSD style) */
1029 /* note: we only do this for a limited set of ioctls
1030 and only if the original address family was AF_INET.
1031 This is checked above. */
1032 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
1033 ifap = &ifa->ifa_next) {
1034 if (!strcmp(ifr.ifr_name, ifa->ifa_label) &&
1035 sin_orig.sin_addr.s_addr ==
David S. Miller6c91afe2011-03-09 13:27:16 -08001036 ifa->ifa_local) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 break; /* found */
1038 }
1039 }
1040 }
1041 /* we didn't get a match, maybe the application is
1042 4.3BSD-style and passed in junk so we fall back to
1043 comparing just the label */
1044 if (!ifa) {
1045 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
1046 ifap = &ifa->ifa_next)
1047 if (!strcmp(ifr.ifr_name, ifa->ifa_label))
1048 break;
1049 }
1050 }
1051
1052 ret = -EADDRNOTAVAIL;
1053 if (!ifa && cmd != SIOCSIFADDR && cmd != SIOCSIFFLAGS)
1054 goto done;
1055
Stephen Hemminger132adf52007-03-08 20:44:43 -08001056 switch (cmd) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 case SIOCGIFADDR: /* Get interface address */
1058 sin->sin_addr.s_addr = ifa->ifa_local;
1059 goto rarok;
1060
1061 case SIOCGIFBRDADDR: /* Get the broadcast address */
1062 sin->sin_addr.s_addr = ifa->ifa_broadcast;
1063 goto rarok;
1064
1065 case SIOCGIFDSTADDR: /* Get the destination address */
1066 sin->sin_addr.s_addr = ifa->ifa_address;
1067 goto rarok;
1068
1069 case SIOCGIFNETMASK: /* Get the netmask for the interface */
1070 sin->sin_addr.s_addr = ifa->ifa_mask;
1071 goto rarok;
1072
1073 case SIOCSIFFLAGS:
1074 if (colon) {
1075 ret = -EADDRNOTAVAIL;
1076 if (!ifa)
1077 break;
1078 ret = 0;
1079 if (!(ifr.ifr_flags & IFF_UP))
1080 inet_del_ifa(in_dev, ifap, 1);
1081 break;
1082 }
1083 ret = dev_change_flags(dev, ifr.ifr_flags);
1084 break;
1085
1086 case SIOCSIFADDR: /* Set interface address (and family) */
1087 ret = -EINVAL;
1088 if (inet_abc_len(sin->sin_addr.s_addr) < 0)
1089 break;
1090
1091 if (!ifa) {
1092 ret = -ENOBUFS;
Eric Dumazet9f9354b2009-11-04 22:05:10 -08001093 ifa = inet_alloc_ifa();
1094 if (!ifa)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095 break;
Xi Wangc7e2e1d2013-01-05 11:19:24 +00001096 INIT_HLIST_NODE(&ifa->hash);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 if (colon)
1098 memcpy(ifa->ifa_label, ifr.ifr_name, IFNAMSIZ);
1099 else
1100 memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
1101 } else {
1102 ret = 0;
1103 if (ifa->ifa_local == sin->sin_addr.s_addr)
1104 break;
1105 inet_del_ifa(in_dev, ifap, 0);
1106 ifa->ifa_broadcast = 0;
Bjorn Mork148f9722008-02-26 18:17:53 -08001107 ifa->ifa_scope = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108 }
1109
1110 ifa->ifa_address = ifa->ifa_local = sin->sin_addr.s_addr;
1111
1112 if (!(dev->flags & IFF_POINTOPOINT)) {
1113 ifa->ifa_prefixlen = inet_abc_len(ifa->ifa_address);
1114 ifa->ifa_mask = inet_make_mask(ifa->ifa_prefixlen);
1115 if ((dev->flags & IFF_BROADCAST) &&
1116 ifa->ifa_prefixlen < 31)
1117 ifa->ifa_broadcast = ifa->ifa_address |
1118 ~ifa->ifa_mask;
1119 } else {
1120 ifa->ifa_prefixlen = 32;
1121 ifa->ifa_mask = inet_make_mask(32);
1122 }
Jiri Pirko5c766d62013-01-24 09:41:41 +00001123 set_ifa_lifetime(ifa, INFINITY_LIFE_TIME, INFINITY_LIFE_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 ret = inet_set_ifa(dev, ifa);
1125 break;
1126
1127 case SIOCSIFBRDADDR: /* Set the broadcast address */
1128 ret = 0;
1129 if (ifa->ifa_broadcast != sin->sin_addr.s_addr) {
1130 inet_del_ifa(in_dev, ifap, 0);
1131 ifa->ifa_broadcast = sin->sin_addr.s_addr;
1132 inet_insert_ifa(ifa);
1133 }
1134 break;
1135
1136 case SIOCSIFDSTADDR: /* Set the destination address */
1137 ret = 0;
1138 if (ifa->ifa_address == sin->sin_addr.s_addr)
1139 break;
1140 ret = -EINVAL;
1141 if (inet_abc_len(sin->sin_addr.s_addr) < 0)
1142 break;
1143 ret = 0;
1144 inet_del_ifa(in_dev, ifap, 0);
1145 ifa->ifa_address = sin->sin_addr.s_addr;
1146 inet_insert_ifa(ifa);
1147 break;
1148
1149 case SIOCSIFNETMASK: /* Set the netmask for the interface */
1150
1151 /*
1152 * The mask we set must be legal.
1153 */
1154 ret = -EINVAL;
1155 if (bad_mask(sin->sin_addr.s_addr, 0))
1156 break;
1157 ret = 0;
1158 if (ifa->ifa_mask != sin->sin_addr.s_addr) {
Al Viroa144ea42006-09-28 18:00:55 -07001159 __be32 old_mask = ifa->ifa_mask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 inet_del_ifa(in_dev, ifap, 0);
1161 ifa->ifa_mask = sin->sin_addr.s_addr;
1162 ifa->ifa_prefixlen = inet_mask_len(ifa->ifa_mask);
1163
1164 /* See if current broadcast address matches
1165 * with current netmask, then recalculate
1166 * the broadcast address. Otherwise it's a
1167 * funny address, so don't touch it since
1168 * the user seems to know what (s)he's doing...
1169 */
1170 if ((dev->flags & IFF_BROADCAST) &&
1171 (ifa->ifa_prefixlen < 31) &&
1172 (ifa->ifa_broadcast ==
David Engeldcab5e12005-10-21 22:09:16 -05001173 (ifa->ifa_local|~old_mask))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174 ifa->ifa_broadcast = (ifa->ifa_local |
1175 ~sin->sin_addr.s_addr);
1176 }
1177 inet_insert_ifa(ifa);
1178 }
1179 break;
1180 }
1181done:
1182 rtnl_unlock();
1183out:
1184 return ret;
1185rarok:
1186 rtnl_unlock();
1187 ret = copy_to_user(arg, &ifr, sizeof(struct ifreq)) ? -EFAULT : 0;
1188 goto out;
1189}
1190
1191static int inet_gifconf(struct net_device *dev, char __user *buf, int len)
1192{
Herbert Xue5ed6392005-10-03 14:35:55 -07001193 struct in_device *in_dev = __in_dev_get_rtnl(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194 struct in_ifaddr *ifa;
1195 struct ifreq ifr;
1196 int done = 0;
1197
Eric Dumazet9f9354b2009-11-04 22:05:10 -08001198 if (!in_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199 goto out;
1200
Eric Dumazet9f9354b2009-11-04 22:05:10 -08001201 for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202 if (!buf) {
1203 done += sizeof(ifr);
1204 continue;
1205 }
1206 if (len < (int) sizeof(ifr))
1207 break;
1208 memset(&ifr, 0, sizeof(struct ifreq));
Dan Carpenter4299c8a2013-07-29 22:15:19 +03001209 strcpy(ifr.ifr_name, ifa->ifa_label);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210
1211 (*(struct sockaddr_in *)&ifr.ifr_addr).sin_family = AF_INET;
1212 (*(struct sockaddr_in *)&ifr.ifr_addr).sin_addr.s_addr =
1213 ifa->ifa_local;
1214
1215 if (copy_to_user(buf, &ifr, sizeof(struct ifreq))) {
1216 done = -EFAULT;
1217 break;
1218 }
1219 buf += sizeof(struct ifreq);
1220 len -= sizeof(struct ifreq);
1221 done += sizeof(struct ifreq);
1222 }
1223out:
1224 return done;
1225}
1226
Gao Feng8b57fd12017-03-10 12:38:47 +08001227static __be32 in_dev_select_addr(const struct in_device *in_dev,
1228 int scope)
1229{
1230 for_primary_ifa(in_dev) {
1231 if (ifa->ifa_scope != RT_SCOPE_LINK &&
1232 ifa->ifa_scope <= scope)
1233 return ifa->ifa_local;
1234 } endfor_ifa(in_dev);
1235
1236 return 0;
1237}
1238
Al Viroa61ced52006-09-26 21:27:54 -07001239__be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240{
Al Viroa61ced52006-09-26 21:27:54 -07001241 __be32 addr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242 struct in_device *in_dev;
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09001243 struct net *net = dev_net(dev);
David Ahern3f2fb9a2016-02-24 11:47:02 -08001244 int master_idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245
1246 rcu_read_lock();
Herbert Xue5ed6392005-10-03 14:35:55 -07001247 in_dev = __in_dev_get_rcu(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248 if (!in_dev)
1249 goto no_in_dev;
1250
1251 for_primary_ifa(in_dev) {
1252 if (ifa->ifa_scope > scope)
1253 continue;
1254 if (!dst || inet_ifa_match(dst, ifa)) {
1255 addr = ifa->ifa_local;
1256 break;
1257 }
1258 if (!addr)
1259 addr = ifa->ifa_local;
1260 } endfor_ifa(in_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261
1262 if (addr)
Eric Dumazetc6d14c82009-11-04 05:43:23 -08001263 goto out_unlock;
Eric Dumazet9f9354b2009-11-04 22:05:10 -08001264no_in_dev:
David Ahern3f2fb9a2016-02-24 11:47:02 -08001265 master_idx = l3mdev_master_ifindex_rcu(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266
David Lamparter17b693c2016-02-24 11:47:03 -08001267 /* For VRFs, the VRF device takes the place of the loopback device,
1268 * with addresses on it being preferred. Note in such cases the
1269 * loopback device will be among the devices that fail the master_idx
1270 * equality check in the loop below.
1271 */
1272 if (master_idx &&
1273 (dev = dev_get_by_index_rcu(net, master_idx)) &&
1274 (in_dev = __in_dev_get_rcu(dev))) {
Gao Feng8b57fd12017-03-10 12:38:47 +08001275 addr = in_dev_select_addr(in_dev, scope);
1276 if (addr)
1277 goto out_unlock;
David Lamparter17b693c2016-02-24 11:47:03 -08001278 }
1279
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 /* Not loopback addresses on loopback should be preferred
Stephen Hemmingerca9f1fd2015-02-14 13:47:54 -05001281 in this case. It is important that lo is the first interface
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282 in dev_base list.
1283 */
Eric Dumazetc6d14c82009-11-04 05:43:23 -08001284 for_each_netdev_rcu(net, dev) {
David Ahern3f2fb9a2016-02-24 11:47:02 -08001285 if (l3mdev_master_ifindex_rcu(dev) != master_idx)
1286 continue;
1287
Eric Dumazet9f9354b2009-11-04 22:05:10 -08001288 in_dev = __in_dev_get_rcu(dev);
1289 if (!in_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290 continue;
1291
Gao Feng8b57fd12017-03-10 12:38:47 +08001292 addr = in_dev_select_addr(in_dev, scope);
1293 if (addr)
1294 goto out_unlock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295 }
Eric Dumazetc6d14c82009-11-04 05:43:23 -08001296out_unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298 return addr;
1299}
Eric Dumazet9f9354b2009-11-04 22:05:10 -08001300EXPORT_SYMBOL(inet_select_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301
Al Viro60cad5d2006-09-26 22:17:09 -07001302static __be32 confirm_addr_indev(struct in_device *in_dev, __be32 dst,
1303 __be32 local, int scope)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304{
1305 int same = 0;
Al Viroa144ea42006-09-28 18:00:55 -07001306 __be32 addr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307
1308 for_ifa(in_dev) {
1309 if (!addr &&
1310 (local == ifa->ifa_local || !local) &&
1311 ifa->ifa_scope <= scope) {
1312 addr = ifa->ifa_local;
1313 if (same)
1314 break;
1315 }
1316 if (!same) {
1317 same = (!local || inet_ifa_match(local, ifa)) &&
1318 (!dst || inet_ifa_match(dst, ifa));
1319 if (same && addr) {
1320 if (local || !dst)
1321 break;
1322 /* Is the selected addr into dst subnet? */
1323 if (inet_ifa_match(addr, ifa))
1324 break;
1325 /* No, then can we use new local src? */
1326 if (ifa->ifa_scope <= scope) {
1327 addr = ifa->ifa_local;
1328 break;
1329 }
1330 /* search for large dst subnet for addr */
1331 same = 0;
1332 }
1333 }
1334 } endfor_ifa(in_dev);
1335
Eric Dumazet9f9354b2009-11-04 22:05:10 -08001336 return same ? addr : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337}
1338
1339/*
1340 * Confirm that local IP address exists using wildcards:
Nicolas Dichtelb601fa192013-12-10 15:02:40 +01001341 * - net: netns to check, cannot be NULL
1342 * - in_dev: only on this interface, NULL=any interface
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343 * - dst: only in the same subnet as dst, 0=any dst
1344 * - local: address, 0=autoselect the local address
1345 * - scope: maximum allowed scope value for the local address
1346 */
Nicolas Dichtelb601fa192013-12-10 15:02:40 +01001347__be32 inet_confirm_addr(struct net *net, struct in_device *in_dev,
Denis V. Lunev9bd85e32008-01-14 23:05:55 -08001348 __be32 dst, __be32 local, int scope)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349{
Al Viro60cad5d2006-09-26 22:17:09 -07001350 __be32 addr = 0;
Denis V. Lunev9bd85e32008-01-14 23:05:55 -08001351 struct net_device *dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352
Ian Morris00db4122015-04-03 09:17:27 +01001353 if (in_dev)
Denis V. Lunev9bd85e32008-01-14 23:05:55 -08001354 return confirm_addr_indev(in_dev, dst, local, scope);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356 rcu_read_lock();
Eric Dumazetc6d14c82009-11-04 05:43:23 -08001357 for_each_netdev_rcu(net, dev) {
Eric Dumazet9f9354b2009-11-04 22:05:10 -08001358 in_dev = __in_dev_get_rcu(dev);
1359 if (in_dev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360 addr = confirm_addr_indev(in_dev, dst, local, scope);
1361 if (addr)
1362 break;
1363 }
1364 }
1365 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366
1367 return addr;
1368}
Andy Gospodarekeaddcd72012-03-22 16:14:29 +00001369EXPORT_SYMBOL(inet_confirm_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370
1371/*
1372 * Device notifier
1373 */
1374
1375int register_inetaddr_notifier(struct notifier_block *nb)
1376{
Alan Sterne041c682006-03-27 01:16:30 -08001377 return blocking_notifier_chain_register(&inetaddr_chain, nb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378}
Eric Dumazet9f9354b2009-11-04 22:05:10 -08001379EXPORT_SYMBOL(register_inetaddr_notifier);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380
1381int unregister_inetaddr_notifier(struct notifier_block *nb)
1382{
Alan Sterne041c682006-03-27 01:16:30 -08001383 return blocking_notifier_chain_unregister(&inetaddr_chain, nb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384}
Eric Dumazet9f9354b2009-11-04 22:05:10 -08001385EXPORT_SYMBOL(unregister_inetaddr_notifier);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386
Krister Johansen3ad7d242017-06-08 13:12:14 -07001387int register_inetaddr_validator_notifier(struct notifier_block *nb)
1388{
1389 return blocking_notifier_chain_register(&inetaddr_validator_chain, nb);
1390}
1391EXPORT_SYMBOL(register_inetaddr_validator_notifier);
1392
1393int unregister_inetaddr_validator_notifier(struct notifier_block *nb)
1394{
1395 return blocking_notifier_chain_unregister(&inetaddr_validator_chain,
1396 nb);
1397}
1398EXPORT_SYMBOL(unregister_inetaddr_validator_notifier);
1399
Eric Dumazet9f9354b2009-11-04 22:05:10 -08001400/* Rename ifa_labels for a device name change. Make some effort to preserve
1401 * existing alias numbering and to create unique labels if possible.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402*/
1403static void inetdev_changename(struct net_device *dev, struct in_device *in_dev)
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +09001404{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405 struct in_ifaddr *ifa;
1406 int named = 0;
1407
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +09001408 for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
1409 char old[IFNAMSIZ], *dot;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410
1411 memcpy(old, ifa->ifa_label, IFNAMSIZ);
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +09001412 memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 if (named++ == 0)
Thomas Graf573bf472008-06-10 15:40:04 -07001414 goto skip;
Mark McLoughlin44344b22008-01-04 00:56:25 -08001415 dot = strchr(old, ':');
Ian Morris51456b22015-04-03 09:17:26 +01001416 if (!dot) {
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +09001417 sprintf(old, ":%d", named);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418 dot = old;
1419 }
Eric Dumazet9f9354b2009-11-04 22:05:10 -08001420 if (strlen(dot) + strlen(dev->name) < IFNAMSIZ)
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +09001421 strcat(ifa->ifa_label, dot);
Eric Dumazet9f9354b2009-11-04 22:05:10 -08001422 else
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +09001423 strcpy(ifa->ifa_label + (IFNAMSIZ - strlen(dot) - 1), dot);
Thomas Graf573bf472008-06-10 15:40:04 -07001424skip:
1425 rtmsg_ifa(RTM_NEWADDR, ifa, NULL, 0);
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +09001426 }
1427}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428
Eric Dumazet40384992012-08-03 21:06:50 +00001429static bool inetdev_valid_mtu(unsigned int mtu)
Breno Leitao06770842008-09-02 17:28:58 -07001430{
1431 return mtu >= 68;
1432}
1433
Ian Campbelld11327ad2011-02-11 07:44:16 +00001434static void inetdev_send_gratuitous_arp(struct net_device *dev,
1435 struct in_device *in_dev)
1436
1437{
Zoltan Kissb76d0782011-07-24 13:09:30 +00001438 struct in_ifaddr *ifa;
Ian Campbelld11327ad2011-02-11 07:44:16 +00001439
Zoltan Kissb76d0782011-07-24 13:09:30 +00001440 for (ifa = in_dev->ifa_list; ifa;
1441 ifa = ifa->ifa_next) {
1442 arp_send(ARPOP_REQUEST, ETH_P_ARP,
1443 ifa->ifa_local, dev,
1444 ifa->ifa_local, NULL,
1445 dev->dev_addr, NULL);
1446 }
Ian Campbelld11327ad2011-02-11 07:44:16 +00001447}
1448
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449/* Called only under RTNL semaphore */
1450
1451static int inetdev_event(struct notifier_block *this, unsigned long event,
1452 void *ptr)
1453{
Jiri Pirko351638e2013-05-28 01:30:21 +00001454 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
Eric Dumazet748e2d92012-08-22 21:50:59 +00001455 struct in_device *in_dev = __in_dev_get_rtnl(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456
1457 ASSERT_RTNL();
1458
1459 if (!in_dev) {
Herbert Xu8030f542007-02-22 01:53:47 +09001460 if (event == NETDEV_REGISTER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461 in_dev = inetdev_init(dev);
WANG Cong20e61da2014-07-25 15:25:08 -07001462 if (IS_ERR(in_dev))
1463 return notifier_from_errno(PTR_ERR(in_dev));
Eric W. Biederman0cc217e2007-09-26 22:10:06 -07001464 if (dev->flags & IFF_LOOPBACK) {
Herbert Xu42f811b2007-06-04 23:34:44 -07001465 IN_DEV_CONF_SET(in_dev, NOXFRM, 1);
1466 IN_DEV_CONF_SET(in_dev, NOPOLICY, 1);
Herbert Xu8030f542007-02-22 01:53:47 +09001467 }
Breno Leitao06770842008-09-02 17:28:58 -07001468 } else if (event == NETDEV_CHANGEMTU) {
1469 /* Re-enabling IP */
1470 if (inetdev_valid_mtu(dev->mtu))
1471 in_dev = inetdev_init(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472 }
1473 goto out;
1474 }
1475
1476 switch (event) {
1477 case NETDEV_REGISTER:
Joe Perches91df42b2012-05-15 14:11:54 +00001478 pr_debug("%s: bug\n", __func__);
Stephen Hemmingera9b3cd72011-08-01 16:19:00 +00001479 RCU_INIT_POINTER(dev->ip_ptr, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480 break;
1481 case NETDEV_UP:
Breno Leitao06770842008-09-02 17:28:58 -07001482 if (!inetdev_valid_mtu(dev->mtu))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483 break;
Eric W. Biederman0cc217e2007-09-26 22:10:06 -07001484 if (dev->flags & IFF_LOOPBACK) {
Eric Dumazet9f9354b2009-11-04 22:05:10 -08001485 struct in_ifaddr *ifa = inet_alloc_ifa();
1486
1487 if (ifa) {
David S. Millerfd23c3b2011-02-18 12:42:28 -08001488 INIT_HLIST_NODE(&ifa->hash);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489 ifa->ifa_local =
1490 ifa->ifa_address = htonl(INADDR_LOOPBACK);
1491 ifa->ifa_prefixlen = 8;
1492 ifa->ifa_mask = inet_make_mask(8);
1493 in_dev_hold(in_dev);
1494 ifa->ifa_dev = in_dev;
1495 ifa->ifa_scope = RT_SCOPE_HOST;
1496 memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
Jiri Pirko5c766d62013-01-24 09:41:41 +00001497 set_ifa_lifetime(ifa, INFINITY_LIFE_TIME,
1498 INFINITY_LIFE_TIME);
Jiri Pirkodfd15822014-01-07 15:55:45 +01001499 ipv4_devconf_setall(in_dev);
1500 neigh_parms_data_state_setall(in_dev->arp_parms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501 inet_insert_ifa(ifa);
1502 }
1503 }
1504 ip_mc_up(in_dev);
Stephen Hemmingereefef1c2009-02-01 01:04:33 -08001505 /* fall through */
1506 case NETDEV_CHANGEADDR:
Ian Campbelld11327ad2011-02-11 07:44:16 +00001507 if (!IN_DEV_ARP_NOTIFY(in_dev))
1508 break;
1509 /* fall through */
1510 case NETDEV_NOTIFY_PEERS:
Stephen Hemmingera21090c2009-10-07 03:18:17 -07001511 /* Send gratuitous ARP to notify of link change */
Ian Campbelld11327ad2011-02-11 07:44:16 +00001512 inetdev_send_gratuitous_arp(dev, in_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513 break;
1514 case NETDEV_DOWN:
1515 ip_mc_down(in_dev);
1516 break;
Jiri Pirko93d9b7d2010-03-10 10:28:56 +00001517 case NETDEV_PRE_TYPE_CHANGE:
Moni Shoua75c78502009-09-15 02:37:40 -07001518 ip_mc_unmap(in_dev);
1519 break;
Jiri Pirko93d9b7d2010-03-10 10:28:56 +00001520 case NETDEV_POST_TYPE_CHANGE:
Moni Shoua75c78502009-09-15 02:37:40 -07001521 ip_mc_remap(in_dev);
1522 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523 case NETDEV_CHANGEMTU:
Breno Leitao06770842008-09-02 17:28:58 -07001524 if (inetdev_valid_mtu(dev->mtu))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525 break;
Breno Leitao06770842008-09-02 17:28:58 -07001526 /* disable IP when MTU is not enough */
Gustavo A. R. Silvafcfd6df2017-10-16 15:48:55 -05001527 /* fall through */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528 case NETDEV_UNREGISTER:
1529 inetdev_destroy(in_dev);
1530 break;
1531 case NETDEV_CHANGENAME:
1532 /* Do not notify about label change, this event is
1533 * not interesting to applications using netlink.
1534 */
1535 inetdev_changename(dev, in_dev);
1536
Pavel Emelyanov51602b22007-12-11 02:17:40 -08001537 devinet_sysctl_unregister(in_dev);
Pavel Emelyanov66f27a52007-12-02 00:55:54 +11001538 devinet_sysctl_register(in_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539 break;
1540 }
1541out:
1542 return NOTIFY_DONE;
1543}
1544
1545static struct notifier_block ip_netdev_notifier = {
Jianjun Kong539afed2008-11-03 02:48:48 -08001546 .notifier_call = inetdev_event,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547};
1548
Eric Dumazet40384992012-08-03 21:06:50 +00001549static size_t inet_nlmsg_size(void)
Thomas Graf339bf982006-11-10 14:10:15 -08001550{
1551 return NLMSG_ALIGN(sizeof(struct ifaddrmsg))
1552 + nla_total_size(4) /* IFA_ADDRESS */
1553 + nla_total_size(4) /* IFA_LOCAL */
1554 + nla_total_size(4) /* IFA_BROADCAST */
Jiri Pirkoad6c8132013-12-08 12:16:10 +01001555 + nla_total_size(IFNAMSIZ) /* IFA_LABEL */
Geert Uytterhoeven63b5f152014-02-05 08:38:25 +01001556 + nla_total_size(4) /* IFA_FLAGS */
1557 + nla_total_size(sizeof(struct ifa_cacheinfo)); /* IFA_CACHEINFO */
Thomas Graf339bf982006-11-10 14:10:15 -08001558}
1559
Jiri Pirko5c766d62013-01-24 09:41:41 +00001560static inline u32 cstamp_delta(unsigned long cstamp)
1561{
1562 return (cstamp - INITIAL_JIFFIES) * 100UL / HZ;
1563}
1564
1565static int put_cacheinfo(struct sk_buff *skb, unsigned long cstamp,
1566 unsigned long tstamp, u32 preferred, u32 valid)
1567{
1568 struct ifa_cacheinfo ci;
1569
1570 ci.cstamp = cstamp_delta(cstamp);
1571 ci.tstamp = cstamp_delta(tstamp);
1572 ci.ifa_prefered = preferred;
1573 ci.ifa_valid = valid;
1574
1575 return nla_put(skb, IFA_CACHEINFO, sizeof(ci), &ci);
1576}
1577
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,
Eric W. Biederman15e47302012-09-07 20:12:54 +00001579 u32 portid, u32 seq, int event, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580{
1581 struct ifaddrmsg *ifm;
1582 struct nlmsghdr *nlh;
Jiri Pirko5c766d62013-01-24 09:41:41 +00001583 u32 preferred, valid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584
Eric W. Biederman15e47302012-09-07 20:12:54 +00001585 nlh = nlmsg_put(skb, portid, seq, event, sizeof(*ifm), flags);
Ian Morris51456b22015-04-03 09:17:26 +01001586 if (!nlh)
Patrick McHardy26932562007-01-31 23:16:40 -08001587 return -EMSGSIZE;
Thomas Graf47f68512006-08-04 23:04:36 -07001588
1589 ifm = nlmsg_data(nlh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001590 ifm->ifa_family = AF_INET;
1591 ifm->ifa_prefixlen = ifa->ifa_prefixlen;
Jiri Pirko5c766d62013-01-24 09:41:41 +00001592 ifm->ifa_flags = ifa->ifa_flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001593 ifm->ifa_scope = ifa->ifa_scope;
1594 ifm->ifa_index = ifa->ifa_dev->dev->ifindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001595
Jiri Pirko5c766d62013-01-24 09:41:41 +00001596 if (!(ifm->ifa_flags & IFA_F_PERMANENT)) {
1597 preferred = ifa->ifa_preferred_lft;
1598 valid = ifa->ifa_valid_lft;
1599 if (preferred != INFINITY_LIFE_TIME) {
1600 long tval = (jiffies - ifa->ifa_tstamp) / HZ;
1601
1602 if (preferred > tval)
1603 preferred -= tval;
1604 else
1605 preferred = 0;
1606 if (valid != INFINITY_LIFE_TIME) {
1607 if (valid > tval)
1608 valid -= tval;
1609 else
1610 valid = 0;
1611 }
1612 }
1613 } else {
1614 preferred = INFINITY_LIFE_TIME;
1615 valid = INFINITY_LIFE_TIME;
1616 }
David S. Millerf3756b72012-04-01 20:39:02 -04001617 if ((ifa->ifa_address &&
Jiri Benc930345e2015-03-29 16:59:25 +02001618 nla_put_in_addr(skb, IFA_ADDRESS, ifa->ifa_address)) ||
David S. Millerf3756b72012-04-01 20:39:02 -04001619 (ifa->ifa_local &&
Jiri Benc930345e2015-03-29 16:59:25 +02001620 nla_put_in_addr(skb, IFA_LOCAL, ifa->ifa_local)) ||
David S. Millerf3756b72012-04-01 20:39:02 -04001621 (ifa->ifa_broadcast &&
Jiri Benc930345e2015-03-29 16:59:25 +02001622 nla_put_in_addr(skb, IFA_BROADCAST, ifa->ifa_broadcast)) ||
David S. Millerf3756b72012-04-01 20:39:02 -04001623 (ifa->ifa_label[0] &&
Jiri Pirko5c766d62013-01-24 09:41:41 +00001624 nla_put_string(skb, IFA_LABEL, ifa->ifa_label)) ||
Jiri Pirkoad6c8132013-12-08 12:16:10 +01001625 nla_put_u32(skb, IFA_FLAGS, ifa->ifa_flags) ||
Jiri Pirko5c766d62013-01-24 09:41:41 +00001626 put_cacheinfo(skb, ifa->ifa_cstamp, ifa->ifa_tstamp,
1627 preferred, valid))
David S. Millerf3756b72012-04-01 20:39:02 -04001628 goto nla_put_failure;
Thomas Graf47f68512006-08-04 23:04:36 -07001629
Johannes Berg053c0952015-01-16 22:09:00 +01001630 nlmsg_end(skb, nlh);
1631 return 0;
Thomas Graf47f68512006-08-04 23:04:36 -07001632
1633nla_put_failure:
Patrick McHardy26932562007-01-31 23:16:40 -08001634 nlmsg_cancel(skb, nlh);
1635 return -EMSGSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001636}
1637
1638static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
1639{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001640 struct net *net = sock_net(skb->sk);
Eric Dumazeteec4df92009-11-12 07:44:25 +00001641 int h, s_h;
1642 int idx, s_idx;
1643 int ip_idx, s_ip_idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644 struct net_device *dev;
1645 struct in_device *in_dev;
1646 struct in_ifaddr *ifa;
Eric Dumazeteec4df92009-11-12 07:44:25 +00001647 struct hlist_head *head;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648
Eric Dumazeteec4df92009-11-12 07:44:25 +00001649 s_h = cb->args[0];
1650 s_idx = idx = cb->args[1];
1651 s_ip_idx = ip_idx = cb->args[2];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652
Eric Dumazeteec4df92009-11-12 07:44:25 +00001653 for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
1654 idx = 0;
1655 head = &net->dev_index_head[h];
1656 rcu_read_lock();
Nicolas Dichtel04652772013-03-22 06:28:42 +00001657 cb->seq = atomic_read(&net->ipv4.dev_addr_genid) ^
1658 net->dev_base_seq;
Sasha Levinb67bfe02013-02-27 17:06:00 -08001659 hlist_for_each_entry_rcu(dev, head, index_hlist) {
Eric Dumazeteec4df92009-11-12 07:44:25 +00001660 if (idx < s_idx)
1661 goto cont;
Patrick McHardy4b97efd2010-03-26 20:27:49 -07001662 if (h > s_h || idx > s_idx)
Eric Dumazeteec4df92009-11-12 07:44:25 +00001663 s_ip_idx = 0;
1664 in_dev = __in_dev_get_rcu(dev);
1665 if (!in_dev)
1666 goto cont;
1667
1668 for (ifa = in_dev->ifa_list, ip_idx = 0; ifa;
1669 ifa = ifa->ifa_next, ip_idx++) {
1670 if (ip_idx < s_ip_idx)
1671 continue;
1672 if (inet_fill_ifaddr(skb, ifa,
Eric W. Biederman15e47302012-09-07 20:12:54 +00001673 NETLINK_CB(cb->skb).portid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674 cb->nlh->nlmsg_seq,
Johannes Berg053c0952015-01-16 22:09:00 +01001675 RTM_NEWADDR, NLM_F_MULTI) < 0) {
Eric Dumazeteec4df92009-11-12 07:44:25 +00001676 rcu_read_unlock();
1677 goto done;
1678 }
Nicolas Dichtel04652772013-03-22 06:28:42 +00001679 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
Eric Dumazeteec4df92009-11-12 07:44:25 +00001680 }
Pavel Emelianov7562f872007-05-03 15:13:45 -07001681cont:
Eric Dumazeteec4df92009-11-12 07:44:25 +00001682 idx++;
1683 }
1684 rcu_read_unlock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685 }
1686
1687done:
Eric Dumazeteec4df92009-11-12 07:44:25 +00001688 cb->args[0] = h;
1689 cb->args[1] = idx;
1690 cb->args[2] = ip_idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691
1692 return skb->len;
1693}
1694
Jianjun Kong539afed2008-11-03 02:48:48 -08001695static void rtmsg_ifa(int event, struct in_ifaddr *ifa, struct nlmsghdr *nlh,
Eric W. Biederman15e47302012-09-07 20:12:54 +00001696 u32 portid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697{
Thomas Graf47f68512006-08-04 23:04:36 -07001698 struct sk_buff *skb;
Thomas Grafd6062cb2006-08-15 00:33:59 -07001699 u32 seq = nlh ? nlh->nlmsg_seq : 0;
1700 int err = -ENOBUFS;
Denis V. Lunev4b8aa9a2008-01-31 18:47:40 -08001701 struct net *net;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09001703 net = dev_net(ifa->ifa_dev->dev);
Thomas Graf339bf982006-11-10 14:10:15 -08001704 skb = nlmsg_new(inet_nlmsg_size(), GFP_KERNEL);
Ian Morris51456b22015-04-03 09:17:26 +01001705 if (!skb)
Thomas Grafd6062cb2006-08-15 00:33:59 -07001706 goto errout;
1707
Eric W. Biederman15e47302012-09-07 20:12:54 +00001708 err = inet_fill_ifaddr(skb, ifa, portid, seq, event, 0);
Patrick McHardy26932562007-01-31 23:16:40 -08001709 if (err < 0) {
1710 /* -EMSGSIZE implies BUG in inet_nlmsg_size() */
1711 WARN_ON(err == -EMSGSIZE);
1712 kfree_skb(skb);
1713 goto errout;
1714 }
Eric W. Biederman15e47302012-09-07 20:12:54 +00001715 rtnl_notify(skb, net, portid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL);
Pablo Neira Ayuso1ce85fe2009-02-24 23:18:28 -08001716 return;
Thomas Grafd6062cb2006-08-15 00:33:59 -07001717errout:
1718 if (err < 0)
Denis V. Lunev4b8aa9a2008-01-31 18:47:40 -08001719 rtnl_set_sk_err(net, RTNLGRP_IPV4_IFADDR, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720}
1721
Arad, Ronenb1974ed2015-10-19 09:23:28 -07001722static size_t inet_get_link_af_size(const struct net_device *dev,
1723 u32 ext_filter_mask)
Thomas Graf9f0f7272010-11-16 04:32:48 +00001724{
Eric Dumazet1fc19af2011-05-09 20:55:03 -07001725 struct in_device *in_dev = rcu_dereference_rtnl(dev->ip_ptr);
Thomas Graf9f0f7272010-11-16 04:32:48 +00001726
1727 if (!in_dev)
1728 return 0;
1729
1730 return nla_total_size(IPV4_DEVCONF_MAX * 4); /* IFLA_INET_CONF */
1731}
1732
Sowmini Varadhand5566fd2015-09-11 16:48:48 -04001733static int inet_fill_link_af(struct sk_buff *skb, const struct net_device *dev,
1734 u32 ext_filter_mask)
Thomas Graf9f0f7272010-11-16 04:32:48 +00001735{
Eric Dumazet1fc19af2011-05-09 20:55:03 -07001736 struct in_device *in_dev = rcu_dereference_rtnl(dev->ip_ptr);
Thomas Graf9f0f7272010-11-16 04:32:48 +00001737 struct nlattr *nla;
1738 int i;
1739
1740 if (!in_dev)
1741 return -ENODATA;
1742
1743 nla = nla_reserve(skb, IFLA_INET_CONF, IPV4_DEVCONF_MAX * 4);
Ian Morris51456b22015-04-03 09:17:26 +01001744 if (!nla)
Thomas Graf9f0f7272010-11-16 04:32:48 +00001745 return -EMSGSIZE;
1746
1747 for (i = 0; i < IPV4_DEVCONF_MAX; i++)
1748 ((u32 *) nla_data(nla))[i] = in_dev->cnf.data[i];
1749
1750 return 0;
1751}
1752
1753static const struct nla_policy inet_af_policy[IFLA_INET_MAX+1] = {
1754 [IFLA_INET_CONF] = { .type = NLA_NESTED },
1755};
1756
Thomas Grafcf7afbf2010-11-22 01:31:54 +00001757static int inet_validate_link_af(const struct net_device *dev,
1758 const struct nlattr *nla)
Thomas Graf9f0f7272010-11-16 04:32:48 +00001759{
Thomas Graf9f0f7272010-11-16 04:32:48 +00001760 struct nlattr *a, *tb[IFLA_INET_MAX+1];
1761 int err, rem;
1762
Florian Westphal5fa85a02017-10-16 15:44:36 +02001763 if (dev && !__in_dev_get_rcu(dev))
Thomas Grafcf7afbf2010-11-22 01:31:54 +00001764 return -EAFNOSUPPORT;
Thomas Graf9f0f7272010-11-16 04:32:48 +00001765
Johannes Bergfceb6432017-04-12 14:34:07 +02001766 err = nla_parse_nested(tb, IFLA_INET_MAX, nla, inet_af_policy, NULL);
Thomas Graf9f0f7272010-11-16 04:32:48 +00001767 if (err < 0)
1768 return err;
1769
1770 if (tb[IFLA_INET_CONF]) {
1771 nla_for_each_nested(a, tb[IFLA_INET_CONF], rem) {
1772 int cfgid = nla_type(a);
1773
1774 if (nla_len(a) < 4)
1775 return -EINVAL;
1776
1777 if (cfgid <= 0 || cfgid > IPV4_DEVCONF_MAX)
1778 return -EINVAL;
1779 }
1780 }
1781
Thomas Grafcf7afbf2010-11-22 01:31:54 +00001782 return 0;
1783}
1784
1785static int inet_set_link_af(struct net_device *dev, const struct nlattr *nla)
1786{
Florian Westphal5fa85a02017-10-16 15:44:36 +02001787 struct in_device *in_dev = __in_dev_get_rcu(dev);
Thomas Grafcf7afbf2010-11-22 01:31:54 +00001788 struct nlattr *a, *tb[IFLA_INET_MAX+1];
1789 int rem;
1790
1791 if (!in_dev)
1792 return -EAFNOSUPPORT;
1793
Johannes Bergfceb6432017-04-12 14:34:07 +02001794 if (nla_parse_nested(tb, IFLA_INET_MAX, nla, NULL, NULL) < 0)
Thomas Grafcf7afbf2010-11-22 01:31:54 +00001795 BUG();
1796
Thomas Graf9f0f7272010-11-16 04:32:48 +00001797 if (tb[IFLA_INET_CONF]) {
1798 nla_for_each_nested(a, tb[IFLA_INET_CONF], rem)
1799 ipv4_devconf_set(in_dev, nla_type(a), nla_get_u32(a));
1800 }
1801
1802 return 0;
1803}
1804
Nicolas Dichteledc9e742012-10-25 22:28:52 +00001805static int inet_netconf_msgsize_devconf(int type)
1806{
1807 int size = NLMSG_ALIGN(sizeof(struct netconfmsg))
1808 + nla_total_size(4); /* NETCONFA_IFINDEX */
Zhang Shengju136ba622016-03-10 08:55:50 +00001809 bool all = false;
Nicolas Dichteledc9e742012-10-25 22:28:52 +00001810
Zhang Shengju136ba622016-03-10 08:55:50 +00001811 if (type == NETCONFA_ALL)
1812 all = true;
1813
1814 if (all || type == NETCONFA_FORWARDING)
Nicolas Dichteledc9e742012-10-25 22:28:52 +00001815 size += nla_total_size(4);
Zhang Shengju136ba622016-03-10 08:55:50 +00001816 if (all || type == NETCONFA_RP_FILTER)
Nicolas Dichtelcc535df2012-10-29 04:53:27 +00001817 size += nla_total_size(4);
Zhang Shengju136ba622016-03-10 08:55:50 +00001818 if (all || type == NETCONFA_MC_FORWARDING)
Nicolas Dichteld67b8c62012-12-04 01:13:35 +00001819 size += nla_total_size(4);
Zhang Shengju136ba622016-03-10 08:55:50 +00001820 if (all || type == NETCONFA_PROXY_NEIGH)
stephen hemmingerf085ff12013-12-12 13:06:50 -08001821 size += nla_total_size(4);
Zhang Shengju136ba622016-03-10 08:55:50 +00001822 if (all || type == NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN)
Andy Gospodarek974d7af2015-07-07 13:56:57 -04001823 size += nla_total_size(4);
Nicolas Dichteledc9e742012-10-25 22:28:52 +00001824
1825 return size;
1826}
1827
1828static int inet_netconf_fill_devconf(struct sk_buff *skb, int ifindex,
1829 struct ipv4_devconf *devconf, u32 portid,
1830 u32 seq, int event, unsigned int flags,
1831 int type)
1832{
1833 struct nlmsghdr *nlh;
1834 struct netconfmsg *ncm;
Zhang Shengju136ba622016-03-10 08:55:50 +00001835 bool all = false;
Nicolas Dichteledc9e742012-10-25 22:28:52 +00001836
1837 nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct netconfmsg),
1838 flags);
Ian Morris51456b22015-04-03 09:17:26 +01001839 if (!nlh)
Nicolas Dichteledc9e742012-10-25 22:28:52 +00001840 return -EMSGSIZE;
1841
Zhang Shengju136ba622016-03-10 08:55:50 +00001842 if (type == NETCONFA_ALL)
1843 all = true;
1844
Nicolas Dichteledc9e742012-10-25 22:28:52 +00001845 ncm = nlmsg_data(nlh);
1846 ncm->ncm_family = AF_INET;
1847
1848 if (nla_put_s32(skb, NETCONFA_IFINDEX, ifindex) < 0)
1849 goto nla_put_failure;
1850
David Ahernb5c96412017-03-28 14:28:03 -07001851 if (!devconf)
1852 goto out;
1853
Zhang Shengju136ba622016-03-10 08:55:50 +00001854 if ((all || type == NETCONFA_FORWARDING) &&
Nicolas Dichteledc9e742012-10-25 22:28:52 +00001855 nla_put_s32(skb, NETCONFA_FORWARDING,
1856 IPV4_DEVCONF(*devconf, FORWARDING)) < 0)
1857 goto nla_put_failure;
Zhang Shengju136ba622016-03-10 08:55:50 +00001858 if ((all || type == NETCONFA_RP_FILTER) &&
Nicolas Dichtelcc535df2012-10-29 04:53:27 +00001859 nla_put_s32(skb, NETCONFA_RP_FILTER,
1860 IPV4_DEVCONF(*devconf, RP_FILTER)) < 0)
1861 goto nla_put_failure;
Zhang Shengju136ba622016-03-10 08:55:50 +00001862 if ((all || type == NETCONFA_MC_FORWARDING) &&
Nicolas Dichteld67b8c62012-12-04 01:13:35 +00001863 nla_put_s32(skb, NETCONFA_MC_FORWARDING,
1864 IPV4_DEVCONF(*devconf, MC_FORWARDING)) < 0)
1865 goto nla_put_failure;
Zhang Shengju136ba622016-03-10 08:55:50 +00001866 if ((all || type == NETCONFA_PROXY_NEIGH) &&
stephen hemminger09aea5d2013-12-17 22:35:52 -08001867 nla_put_s32(skb, NETCONFA_PROXY_NEIGH,
stephen hemmingerf085ff12013-12-12 13:06:50 -08001868 IPV4_DEVCONF(*devconf, PROXY_ARP)) < 0)
1869 goto nla_put_failure;
Zhang Shengju136ba622016-03-10 08:55:50 +00001870 if ((all || type == NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN) &&
Andy Gospodarek974d7af2015-07-07 13:56:57 -04001871 nla_put_s32(skb, NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN,
1872 IPV4_DEVCONF(*devconf, IGNORE_ROUTES_WITH_LINKDOWN)) < 0)
1873 goto nla_put_failure;
Nicolas Dichteledc9e742012-10-25 22:28:52 +00001874
David Ahernb5c96412017-03-28 14:28:03 -07001875out:
Johannes Berg053c0952015-01-16 22:09:00 +01001876 nlmsg_end(skb, nlh);
1877 return 0;
Nicolas Dichteledc9e742012-10-25 22:28:52 +00001878
1879nla_put_failure:
1880 nlmsg_cancel(skb, nlh);
1881 return -EMSGSIZE;
1882}
1883
David Ahern3b022862017-03-28 14:28:02 -07001884void inet_netconf_notify_devconf(struct net *net, int event, int type,
1885 int ifindex, struct ipv4_devconf *devconf)
Nicolas Dichteledc9e742012-10-25 22:28:52 +00001886{
1887 struct sk_buff *skb;
1888 int err = -ENOBUFS;
1889
Eric Dumazetfa178062016-07-08 05:18:24 +02001890 skb = nlmsg_new(inet_netconf_msgsize_devconf(type), GFP_KERNEL);
Ian Morris51456b22015-04-03 09:17:26 +01001891 if (!skb)
Nicolas Dichteledc9e742012-10-25 22:28:52 +00001892 goto errout;
1893
1894 err = inet_netconf_fill_devconf(skb, ifindex, devconf, 0, 0,
David Ahern3b022862017-03-28 14:28:02 -07001895 event, 0, type);
Nicolas Dichteledc9e742012-10-25 22:28:52 +00001896 if (err < 0) {
1897 /* -EMSGSIZE implies BUG in inet_netconf_msgsize_devconf() */
1898 WARN_ON(err == -EMSGSIZE);
1899 kfree_skb(skb);
1900 goto errout;
1901 }
Eric Dumazetfa178062016-07-08 05:18:24 +02001902 rtnl_notify(skb, net, 0, RTNLGRP_IPV4_NETCONF, NULL, GFP_KERNEL);
Nicolas Dichteledc9e742012-10-25 22:28:52 +00001903 return;
1904errout:
1905 if (err < 0)
1906 rtnl_set_sk_err(net, RTNLGRP_IPV4_NETCONF, err);
1907}
1908
Nicolas Dichtel9e551112012-10-25 22:28:53 +00001909static const struct nla_policy devconf_ipv4_policy[NETCONFA_MAX+1] = {
1910 [NETCONFA_IFINDEX] = { .len = sizeof(int) },
1911 [NETCONFA_FORWARDING] = { .len = sizeof(int) },
Nicolas Dichtelcc535df2012-10-29 04:53:27 +00001912 [NETCONFA_RP_FILTER] = { .len = sizeof(int) },
stephen hemminger09aea5d2013-12-17 22:35:52 -08001913 [NETCONFA_PROXY_NEIGH] = { .len = sizeof(int) },
Andy Gospodarek974d7af2015-07-07 13:56:57 -04001914 [NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN] = { .len = sizeof(int) },
Nicolas Dichtel9e551112012-10-25 22:28:53 +00001915};
1916
1917static int inet_netconf_get_devconf(struct sk_buff *in_skb,
David Ahernc21ef3e2017-04-16 09:48:24 -07001918 struct nlmsghdr *nlh,
1919 struct netlink_ext_ack *extack)
Nicolas Dichtel9e551112012-10-25 22:28:53 +00001920{
1921 struct net *net = sock_net(in_skb->sk);
1922 struct nlattr *tb[NETCONFA_MAX+1];
1923 struct netconfmsg *ncm;
1924 struct sk_buff *skb;
1925 struct ipv4_devconf *devconf;
1926 struct in_device *in_dev;
1927 struct net_device *dev;
1928 int ifindex;
1929 int err;
1930
1931 err = nlmsg_parse(nlh, sizeof(*ncm), tb, NETCONFA_MAX,
David Ahernc21ef3e2017-04-16 09:48:24 -07001932 devconf_ipv4_policy, extack);
Nicolas Dichtel9e551112012-10-25 22:28:53 +00001933 if (err < 0)
1934 goto errout;
1935
Anton Protopopova97eb332016-02-16 21:43:16 -05001936 err = -EINVAL;
Nicolas Dichtel9e551112012-10-25 22:28:53 +00001937 if (!tb[NETCONFA_IFINDEX])
1938 goto errout;
1939
1940 ifindex = nla_get_s32(tb[NETCONFA_IFINDEX]);
1941 switch (ifindex) {
1942 case NETCONFA_IFINDEX_ALL:
1943 devconf = net->ipv4.devconf_all;
1944 break;
1945 case NETCONFA_IFINDEX_DEFAULT:
1946 devconf = net->ipv4.devconf_dflt;
1947 break;
1948 default:
1949 dev = __dev_get_by_index(net, ifindex);
Ian Morris51456b22015-04-03 09:17:26 +01001950 if (!dev)
Nicolas Dichtel9e551112012-10-25 22:28:53 +00001951 goto errout;
1952 in_dev = __in_dev_get_rtnl(dev);
Ian Morris51456b22015-04-03 09:17:26 +01001953 if (!in_dev)
Nicolas Dichtel9e551112012-10-25 22:28:53 +00001954 goto errout;
1955 devconf = &in_dev->cnf;
1956 break;
1957 }
1958
1959 err = -ENOBUFS;
Eric Dumazetfa178062016-07-08 05:18:24 +02001960 skb = nlmsg_new(inet_netconf_msgsize_devconf(NETCONFA_ALL), GFP_KERNEL);
Ian Morris51456b22015-04-03 09:17:26 +01001961 if (!skb)
Nicolas Dichtel9e551112012-10-25 22:28:53 +00001962 goto errout;
1963
1964 err = inet_netconf_fill_devconf(skb, ifindex, devconf,
1965 NETLINK_CB(in_skb).portid,
1966 nlh->nlmsg_seq, RTM_NEWNETCONF, 0,
Zhang Shengju136ba622016-03-10 08:55:50 +00001967 NETCONFA_ALL);
Nicolas Dichtel9e551112012-10-25 22:28:53 +00001968 if (err < 0) {
1969 /* -EMSGSIZE implies BUG in inet_netconf_msgsize_devconf() */
1970 WARN_ON(err == -EMSGSIZE);
1971 kfree_skb(skb);
1972 goto errout;
1973 }
1974 err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid);
1975errout:
1976 return err;
1977}
1978
Nicolas Dichtel7a674202013-03-05 23:42:06 +00001979static int inet_netconf_dump_devconf(struct sk_buff *skb,
1980 struct netlink_callback *cb)
1981{
1982 struct net *net = sock_net(skb->sk);
1983 int h, s_h;
1984 int idx, s_idx;
1985 struct net_device *dev;
1986 struct in_device *in_dev;
1987 struct hlist_head *head;
1988
1989 s_h = cb->args[0];
1990 s_idx = idx = cb->args[1];
1991
1992 for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
1993 idx = 0;
1994 head = &net->dev_index_head[h];
1995 rcu_read_lock();
Nicolas Dichtel04652772013-03-22 06:28:42 +00001996 cb->seq = atomic_read(&net->ipv4.dev_addr_genid) ^
1997 net->dev_base_seq;
Nicolas Dichtel7a674202013-03-05 23:42:06 +00001998 hlist_for_each_entry_rcu(dev, head, index_hlist) {
1999 if (idx < s_idx)
2000 goto cont;
2001 in_dev = __in_dev_get_rcu(dev);
2002 if (!in_dev)
2003 goto cont;
2004
2005 if (inet_netconf_fill_devconf(skb, dev->ifindex,
2006 &in_dev->cnf,
2007 NETLINK_CB(cb->skb).portid,
2008 cb->nlh->nlmsg_seq,
2009 RTM_NEWNETCONF,
2010 NLM_F_MULTI,
Zhang Shengju136ba622016-03-10 08:55:50 +00002011 NETCONFA_ALL) < 0) {
Nicolas Dichtel7a674202013-03-05 23:42:06 +00002012 rcu_read_unlock();
2013 goto done;
2014 }
Nicolas Dichtel04652772013-03-22 06:28:42 +00002015 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
Nicolas Dichtel7a674202013-03-05 23:42:06 +00002016cont:
2017 idx++;
2018 }
2019 rcu_read_unlock();
2020 }
2021 if (h == NETDEV_HASHENTRIES) {
2022 if (inet_netconf_fill_devconf(skb, NETCONFA_IFINDEX_ALL,
2023 net->ipv4.devconf_all,
2024 NETLINK_CB(cb->skb).portid,
2025 cb->nlh->nlmsg_seq,
2026 RTM_NEWNETCONF, NLM_F_MULTI,
Zhang Shengju136ba622016-03-10 08:55:50 +00002027 NETCONFA_ALL) < 0)
Nicolas Dichtel7a674202013-03-05 23:42:06 +00002028 goto done;
2029 else
2030 h++;
2031 }
2032 if (h == NETDEV_HASHENTRIES + 1) {
2033 if (inet_netconf_fill_devconf(skb, NETCONFA_IFINDEX_DEFAULT,
2034 net->ipv4.devconf_dflt,
2035 NETLINK_CB(cb->skb).portid,
2036 cb->nlh->nlmsg_seq,
2037 RTM_NEWNETCONF, NLM_F_MULTI,
Zhang Shengju136ba622016-03-10 08:55:50 +00002038 NETCONFA_ALL) < 0)
Nicolas Dichtel7a674202013-03-05 23:42:06 +00002039 goto done;
2040 else
2041 h++;
2042 }
2043done:
2044 cb->args[0] = h;
2045 cb->args[1] = idx;
2046
2047 return skb->len;
2048}
2049
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050#ifdef CONFIG_SYSCTL
2051
Pavel Emelyanovc0ce9fb2007-12-16 13:31:14 -08002052static void devinet_copy_dflt_conf(struct net *net, int i)
Herbert Xu31be3082007-06-04 23:35:37 -07002053{
2054 struct net_device *dev;
2055
Eric Dumazetc6d14c82009-11-04 05:43:23 -08002056 rcu_read_lock();
2057 for_each_netdev_rcu(net, dev) {
Herbert Xu31be3082007-06-04 23:35:37 -07002058 struct in_device *in_dev;
Eric Dumazetc6d14c82009-11-04 05:43:23 -08002059
Herbert Xu31be3082007-06-04 23:35:37 -07002060 in_dev = __in_dev_get_rcu(dev);
2061 if (in_dev && !test_bit(i, in_dev->cnf.state))
Pavel Emelyanov9355bbd2007-12-16 13:32:16 -08002062 in_dev->cnf.data[i] = net->ipv4.devconf_dflt->data[i];
Herbert Xu31be3082007-06-04 23:35:37 -07002063 }
Eric Dumazetc6d14c82009-11-04 05:43:23 -08002064 rcu_read_unlock();
Herbert Xu31be3082007-06-04 23:35:37 -07002065}
2066
Eric Dumazetc6d14c82009-11-04 05:43:23 -08002067/* called with RTNL locked */
Pavel Emelyanovc0ce9fb2007-12-16 13:31:14 -08002068static void inet_forward_change(struct net *net)
Pavel Emelyanov68dd2992007-12-05 01:44:58 -08002069{
2070 struct net_device *dev;
Pavel Emelyanov586f1212007-12-16 13:32:48 -08002071 int on = IPV4_DEVCONF_ALL(net, FORWARDING);
Pavel Emelyanov68dd2992007-12-05 01:44:58 -08002072
Pavel Emelyanov586f1212007-12-16 13:32:48 -08002073 IPV4_DEVCONF_ALL(net, ACCEPT_REDIRECTS) = !on;
Pavel Emelyanov9355bbd2007-12-16 13:32:16 -08002074 IPV4_DEVCONF_DFLT(net, FORWARDING) = on;
David Ahern3b022862017-03-28 14:28:02 -07002075 inet_netconf_notify_devconf(net, RTM_NEWNETCONF,
2076 NETCONFA_FORWARDING,
Nicolas Dichteledc9e742012-10-25 22:28:52 +00002077 NETCONFA_IFINDEX_ALL,
2078 net->ipv4.devconf_all);
David Ahern3b022862017-03-28 14:28:02 -07002079 inet_netconf_notify_devconf(net, RTM_NEWNETCONF,
2080 NETCONFA_FORWARDING,
Nicolas Dichteledc9e742012-10-25 22:28:52 +00002081 NETCONFA_IFINDEX_DEFAULT,
2082 net->ipv4.devconf_dflt);
Pavel Emelyanov68dd2992007-12-05 01:44:58 -08002083
Pavel Emelyanovc0ce9fb2007-12-16 13:31:14 -08002084 for_each_netdev(net, dev) {
Pavel Emelyanov68dd2992007-12-05 01:44:58 -08002085 struct in_device *in_dev;
Eric Dumazetfa178062016-07-08 05:18:24 +02002086
Ben Hutchings0187bdf2008-06-19 16:15:47 -07002087 if (on)
2088 dev_disable_lro(dev);
Eric Dumazetfa178062016-07-08 05:18:24 +02002089
2090 in_dev = __in_dev_get_rtnl(dev);
Nicolas Dichteledc9e742012-10-25 22:28:52 +00002091 if (in_dev) {
Pavel Emelyanov68dd2992007-12-05 01:44:58 -08002092 IN_DEV_CONF_SET(in_dev, FORWARDING, on);
David Ahern3b022862017-03-28 14:28:02 -07002093 inet_netconf_notify_devconf(net, RTM_NEWNETCONF,
2094 NETCONFA_FORWARDING,
Nicolas Dichteledc9e742012-10-25 22:28:52 +00002095 dev->ifindex, &in_dev->cnf);
2096 }
Pavel Emelyanov68dd2992007-12-05 01:44:58 -08002097 }
Pavel Emelyanov68dd2992007-12-05 01:44:58 -08002098}
2099
stephen hemmingerf085ff12013-12-12 13:06:50 -08002100static int devinet_conf_ifindex(struct net *net, struct ipv4_devconf *cnf)
2101{
2102 if (cnf == net->ipv4.devconf_dflt)
2103 return NETCONFA_IFINDEX_DEFAULT;
2104 else if (cnf == net->ipv4.devconf_all)
2105 return NETCONFA_IFINDEX_ALL;
2106 else {
2107 struct in_device *idev
2108 = container_of(cnf, struct in_device, cnf);
2109 return idev->dev->ifindex;
2110 }
2111}
2112
Joe Perchesfe2c6332013-06-11 23:04:25 -07002113static int devinet_conf_proc(struct ctl_table *ctl, int write,
Alexey Dobriyan8d65af72009-09-23 15:57:19 -07002114 void __user *buffer,
Herbert Xu31be3082007-06-04 23:35:37 -07002115 size_t *lenp, loff_t *ppos)
2116{
Peter Pan(潘卫平)d01ff0a2011-12-01 15:47:06 +00002117 int old_value = *(int *)ctl->data;
Alexey Dobriyan8d65af72009-09-23 15:57:19 -07002118 int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
Peter Pan(潘卫平)d01ff0a2011-12-01 15:47:06 +00002119 int new_value = *(int *)ctl->data;
Herbert Xu31be3082007-06-04 23:35:37 -07002120
2121 if (write) {
2122 struct ipv4_devconf *cnf = ctl->extra1;
Pavel Emelyanovc0ce9fb2007-12-16 13:31:14 -08002123 struct net *net = ctl->extra2;
Herbert Xu31be3082007-06-04 23:35:37 -07002124 int i = (int *)ctl->data - cnf->data;
stephen hemmingerf085ff12013-12-12 13:06:50 -08002125 int ifindex;
Herbert Xu31be3082007-06-04 23:35:37 -07002126
2127 set_bit(i, cnf->state);
2128
Pavel Emelyanov9355bbd2007-12-16 13:32:16 -08002129 if (cnf == net->ipv4.devconf_dflt)
Pavel Emelyanovc0ce9fb2007-12-16 13:31:14 -08002130 devinet_copy_dflt_conf(net, i);
Thomas Grafd0daebc32012-06-12 00:44:01 +00002131 if (i == IPV4_DEVCONF_ACCEPT_LOCAL - 1 ||
2132 i == IPV4_DEVCONF_ROUTE_LOCALNET - 1)
Peter Pan(潘卫平)d01ff0a2011-12-01 15:47:06 +00002133 if ((new_value == 0) && (old_value != 0))
Nicolas Dichtel4ccfe6d2012-09-07 00:45:29 +00002134 rt_cache_flush(net);
stephen hemmingerf085ff12013-12-12 13:06:50 -08002135
Nicolas Dichtelcc535df2012-10-29 04:53:27 +00002136 if (i == IPV4_DEVCONF_RP_FILTER - 1 &&
2137 new_value != old_value) {
stephen hemmingerf085ff12013-12-12 13:06:50 -08002138 ifindex = devinet_conf_ifindex(net, cnf);
David Ahern3b022862017-03-28 14:28:02 -07002139 inet_netconf_notify_devconf(net, RTM_NEWNETCONF,
2140 NETCONFA_RP_FILTER,
Nicolas Dichtelcc535df2012-10-29 04:53:27 +00002141 ifindex, cnf);
2142 }
stephen hemmingerf085ff12013-12-12 13:06:50 -08002143 if (i == IPV4_DEVCONF_PROXY_ARP - 1 &&
2144 new_value != old_value) {
2145 ifindex = devinet_conf_ifindex(net, cnf);
David Ahern3b022862017-03-28 14:28:02 -07002146 inet_netconf_notify_devconf(net, RTM_NEWNETCONF,
2147 NETCONFA_PROXY_NEIGH,
stephen hemmingerf085ff12013-12-12 13:06:50 -08002148 ifindex, cnf);
2149 }
Andy Gospodarek974d7af2015-07-07 13:56:57 -04002150 if (i == IPV4_DEVCONF_IGNORE_ROUTES_WITH_LINKDOWN - 1 &&
2151 new_value != old_value) {
2152 ifindex = devinet_conf_ifindex(net, cnf);
David Ahern3b022862017-03-28 14:28:02 -07002153 inet_netconf_notify_devconf(net, RTM_NEWNETCONF,
2154 NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN,
Andy Gospodarek974d7af2015-07-07 13:56:57 -04002155 ifindex, cnf);
2156 }
Herbert Xu31be3082007-06-04 23:35:37 -07002157 }
2158
2159 return ret;
2160}
2161
Joe Perchesfe2c6332013-06-11 23:04:25 -07002162static int devinet_sysctl_forward(struct ctl_table *ctl, int write,
Alexey Dobriyan8d65af72009-09-23 15:57:19 -07002163 void __user *buffer,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164 size_t *lenp, loff_t *ppos)
2165{
2166 int *valp = ctl->data;
2167 int val = *valp;
Eric W. Biederman88af1822010-02-19 13:22:59 +00002168 loff_t pos = *ppos;
Alexey Dobriyan8d65af72009-09-23 15:57:19 -07002169 int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002170
2171 if (write && *valp != val) {
Pavel Emelyanovc0ce9fb2007-12-16 13:31:14 -08002172 struct net *net = ctl->extra2;
2173
Ben Hutchings0187bdf2008-06-19 16:15:47 -07002174 if (valp != &IPV4_DEVCONF_DFLT(net, FORWARDING)) {
Eric W. Biederman88af1822010-02-19 13:22:59 +00002175 if (!rtnl_trylock()) {
2176 /* Restore the original values before restarting */
2177 *valp = val;
2178 *ppos = pos;
Eric W. Biederman9b8adb52009-05-13 16:59:21 +00002179 return restart_syscall();
Eric W. Biederman88af1822010-02-19 13:22:59 +00002180 }
Ben Hutchings0187bdf2008-06-19 16:15:47 -07002181 if (valp == &IPV4_DEVCONF_ALL(net, FORWARDING)) {
2182 inet_forward_change(net);
Nicolas Dichteledc9e742012-10-25 22:28:52 +00002183 } else {
Ben Hutchings0187bdf2008-06-19 16:15:47 -07002184 struct ipv4_devconf *cnf = ctl->extra1;
2185 struct in_device *idev =
2186 container_of(cnf, struct in_device, cnf);
Nicolas Dichteledc9e742012-10-25 22:28:52 +00002187 if (*valp)
2188 dev_disable_lro(idev->dev);
David Ahern3b022862017-03-28 14:28:02 -07002189 inet_netconf_notify_devconf(net, RTM_NEWNETCONF,
Nicolas Dichteledc9e742012-10-25 22:28:52 +00002190 NETCONFA_FORWARDING,
2191 idev->dev->ifindex,
2192 cnf);
Ben Hutchings0187bdf2008-06-19 16:15:47 -07002193 }
2194 rtnl_unlock();
Nicolas Dichtel4ccfe6d2012-09-07 00:45:29 +00002195 rt_cache_flush(net);
Nicolas Dichteledc9e742012-10-25 22:28:52 +00002196 } else
David Ahern3b022862017-03-28 14:28:02 -07002197 inet_netconf_notify_devconf(net, RTM_NEWNETCONF,
2198 NETCONFA_FORWARDING,
Nicolas Dichteledc9e742012-10-25 22:28:52 +00002199 NETCONFA_IFINDEX_DEFAULT,
2200 net->ipv4.devconf_dflt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002201 }
2202
2203 return ret;
2204}
2205
Joe Perchesfe2c6332013-06-11 23:04:25 -07002206static int ipv4_doint_and_flush(struct ctl_table *ctl, int write,
David S. Miller323e1262010-12-12 21:55:08 -08002207 void __user *buffer,
2208 size_t *lenp, loff_t *ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209{
2210 int *valp = ctl->data;
2211 int val = *valp;
Alexey Dobriyan8d65af72009-09-23 15:57:19 -07002212 int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
Denis V. Lunev76e6ebf2008-07-05 19:00:44 -07002213 struct net *net = ctl->extra2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214
2215 if (write && *valp != val)
Nicolas Dichtel4ccfe6d2012-09-07 00:45:29 +00002216 rt_cache_flush(net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217
2218 return ret;
2219}
2220
Eric W. Biedermanf8572d82009-11-05 13:32:03 -08002221#define DEVINET_SYSCTL_ENTRY(attr, name, mval, proc) \
Herbert Xu42f811b2007-06-04 23:34:44 -07002222 { \
Herbert Xu42f811b2007-06-04 23:34:44 -07002223 .procname = name, \
2224 .data = ipv4_devconf.data + \
Eric W. Biederman02291682010-02-14 03:25:51 +00002225 IPV4_DEVCONF_ ## attr - 1, \
Herbert Xu42f811b2007-06-04 23:34:44 -07002226 .maxlen = sizeof(int), \
2227 .mode = mval, \
2228 .proc_handler = proc, \
Herbert Xu31be3082007-06-04 23:35:37 -07002229 .extra1 = &ipv4_devconf, \
Herbert Xu42f811b2007-06-04 23:34:44 -07002230 }
2231
2232#define DEVINET_SYSCTL_RW_ENTRY(attr, name) \
Eric W. Biedermanf8572d82009-11-05 13:32:03 -08002233 DEVINET_SYSCTL_ENTRY(attr, name, 0644, devinet_conf_proc)
Herbert Xu42f811b2007-06-04 23:34:44 -07002234
2235#define DEVINET_SYSCTL_RO_ENTRY(attr, name) \
Eric W. Biedermanf8572d82009-11-05 13:32:03 -08002236 DEVINET_SYSCTL_ENTRY(attr, name, 0444, devinet_conf_proc)
Herbert Xu42f811b2007-06-04 23:34:44 -07002237
Eric W. Biedermanf8572d82009-11-05 13:32:03 -08002238#define DEVINET_SYSCTL_COMPLEX_ENTRY(attr, name, proc) \
2239 DEVINET_SYSCTL_ENTRY(attr, name, 0644, proc)
Herbert Xu42f811b2007-06-04 23:34:44 -07002240
2241#define DEVINET_SYSCTL_FLUSHING_ENTRY(attr, name) \
Eric W. Biedermanf8572d82009-11-05 13:32:03 -08002242 DEVINET_SYSCTL_COMPLEX_ENTRY(attr, name, ipv4_doint_and_flush)
Herbert Xu42f811b2007-06-04 23:34:44 -07002243
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244static struct devinet_sysctl_table {
2245 struct ctl_table_header *sysctl_header;
Eric W. Biederman02291682010-02-14 03:25:51 +00002246 struct ctl_table devinet_vars[__IPV4_DEVCONF_MAX];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247} devinet_sysctl = {
2248 .devinet_vars = {
Herbert Xu42f811b2007-06-04 23:34:44 -07002249 DEVINET_SYSCTL_COMPLEX_ENTRY(FORWARDING, "forwarding",
Eric W. Biedermanf8572d82009-11-05 13:32:03 -08002250 devinet_sysctl_forward),
Herbert Xu42f811b2007-06-04 23:34:44 -07002251 DEVINET_SYSCTL_RO_ENTRY(MC_FORWARDING, "mc_forwarding"),
2252
2253 DEVINET_SYSCTL_RW_ENTRY(ACCEPT_REDIRECTS, "accept_redirects"),
2254 DEVINET_SYSCTL_RW_ENTRY(SECURE_REDIRECTS, "secure_redirects"),
2255 DEVINET_SYSCTL_RW_ENTRY(SHARED_MEDIA, "shared_media"),
2256 DEVINET_SYSCTL_RW_ENTRY(RP_FILTER, "rp_filter"),
2257 DEVINET_SYSCTL_RW_ENTRY(SEND_REDIRECTS, "send_redirects"),
2258 DEVINET_SYSCTL_RW_ENTRY(ACCEPT_SOURCE_ROUTE,
2259 "accept_source_route"),
Patrick McHardy8153a102009-12-03 01:25:58 +00002260 DEVINET_SYSCTL_RW_ENTRY(ACCEPT_LOCAL, "accept_local"),
Jamal Hadi Salim28f6aee2009-12-25 17:30:22 -08002261 DEVINET_SYSCTL_RW_ENTRY(SRC_VMARK, "src_valid_mark"),
Herbert Xu42f811b2007-06-04 23:34:44 -07002262 DEVINET_SYSCTL_RW_ENTRY(PROXY_ARP, "proxy_arp"),
2263 DEVINET_SYSCTL_RW_ENTRY(MEDIUM_ID, "medium_id"),
2264 DEVINET_SYSCTL_RW_ENTRY(BOOTP_RELAY, "bootp_relay"),
2265 DEVINET_SYSCTL_RW_ENTRY(LOG_MARTIANS, "log_martians"),
2266 DEVINET_SYSCTL_RW_ENTRY(TAG, "tag"),
2267 DEVINET_SYSCTL_RW_ENTRY(ARPFILTER, "arp_filter"),
2268 DEVINET_SYSCTL_RW_ENTRY(ARP_ANNOUNCE, "arp_announce"),
2269 DEVINET_SYSCTL_RW_ENTRY(ARP_IGNORE, "arp_ignore"),
2270 DEVINET_SYSCTL_RW_ENTRY(ARP_ACCEPT, "arp_accept"),
Stephen Hemmingereefef1c2009-02-01 01:04:33 -08002271 DEVINET_SYSCTL_RW_ENTRY(ARP_NOTIFY, "arp_notify"),
Jesper Dangaard Brouer65324142010-01-05 05:50:47 +00002272 DEVINET_SYSCTL_RW_ENTRY(PROXY_ARP_PVLAN, "proxy_arp_pvlan"),
William Manley5c6fe012013-08-06 19:03:14 +01002273 DEVINET_SYSCTL_RW_ENTRY(FORCE_IGMP_VERSION,
2274 "force_igmp_version"),
William Manley26900482013-08-06 19:03:15 +01002275 DEVINET_SYSCTL_RW_ENTRY(IGMPV2_UNSOLICITED_REPORT_INTERVAL,
2276 "igmpv2_unsolicited_report_interval"),
2277 DEVINET_SYSCTL_RW_ENTRY(IGMPV3_UNSOLICITED_REPORT_INTERVAL,
2278 "igmpv3_unsolicited_report_interval"),
Andy Gospodarek0eeb0752015-06-23 13:45:37 -04002279 DEVINET_SYSCTL_RW_ENTRY(IGNORE_ROUTES_WITH_LINKDOWN,
2280 "ignore_routes_with_linkdown"),
Johannes Berg97daf332016-02-04 13:31:18 +01002281 DEVINET_SYSCTL_RW_ENTRY(DROP_GRATUITOUS_ARP,
2282 "drop_gratuitous_arp"),
Herbert Xu42f811b2007-06-04 23:34:44 -07002283
2284 DEVINET_SYSCTL_FLUSHING_ENTRY(NOXFRM, "disable_xfrm"),
2285 DEVINET_SYSCTL_FLUSHING_ENTRY(NOPOLICY, "disable_policy"),
Herbert Xu42f811b2007-06-04 23:34:44 -07002286 DEVINET_SYSCTL_FLUSHING_ENTRY(PROMOTE_SECONDARIES,
2287 "promote_secondaries"),
Thomas Grafd0daebc32012-06-12 00:44:01 +00002288 DEVINET_SYSCTL_FLUSHING_ENTRY(ROUTE_LOCALNET,
2289 "route_localnet"),
Johannes Berg12b74df2016-02-04 13:31:17 +01002290 DEVINET_SYSCTL_FLUSHING_ENTRY(DROP_UNICAST_IN_L2_MULTICAST,
2291 "drop_unicast_in_l2_multicast"),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002292 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07002293};
2294
Pavel Emelyanovea40b322007-12-16 13:30:07 -08002295static int __devinet_sysctl_register(struct net *net, char *dev_name,
Nicolas Dichtel29c994e2016-08-30 10:09:22 +02002296 int ifindex, struct ipv4_devconf *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002297{
2298 int i;
Pavel Emelyanov9fa89642007-12-02 00:17:46 +11002299 struct devinet_sysctl_table *t;
Eric W. Biederman8607ddb2012-04-19 13:42:09 +00002300 char path[sizeof("net/ipv4/conf/") + IFNAMSIZ];
Pavel Emelyanovbfada692007-12-02 00:57:08 +11002301
Pavel Emelyanov9fa89642007-12-02 00:17:46 +11002302 t = kmemdup(&devinet_sysctl, sizeof(*t), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303 if (!t)
Pavel Emelyanov9fa89642007-12-02 00:17:46 +11002304 goto out;
2305
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306 for (i = 0; i < ARRAY_SIZE(t->devinet_vars) - 1; i++) {
2307 t->devinet_vars[i].data += (char *)p - (char *)&ipv4_devconf;
Herbert Xu31be3082007-06-04 23:35:37 -07002308 t->devinet_vars[i].extra1 = p;
Pavel Emelyanovc0ce9fb2007-12-16 13:31:14 -08002309 t->devinet_vars[i].extra2 = net;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310 }
2311
Eric W. Biederman8607ddb2012-04-19 13:42:09 +00002312 snprintf(path, sizeof(path), "net/ipv4/conf/%s", dev_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002313
Eric W. Biederman8607ddb2012-04-19 13:42:09 +00002314 t->sysctl_header = register_net_sysctl(net, path, t->devinet_vars);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315 if (!t->sysctl_header)
Eric W. Biederman8607ddb2012-04-19 13:42:09 +00002316 goto free;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317
2318 p->sysctl = t;
Nicolas Dichtel29c994e2016-08-30 10:09:22 +02002319
David Ahern3b022862017-03-28 14:28:02 -07002320 inet_netconf_notify_devconf(net, RTM_NEWNETCONF, NETCONFA_ALL,
2321 ifindex, p);
Pavel Emelyanovea40b322007-12-16 13:30:07 -08002322 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002323
Pavel Emelyanov9fa89642007-12-02 00:17:46 +11002324free:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002325 kfree(t);
Pavel Emelyanov9fa89642007-12-02 00:17:46 +11002326out:
Pavel Emelyanovea40b322007-12-16 13:30:07 -08002327 return -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328}
2329
David Ahernb5c96412017-03-28 14:28:03 -07002330static void __devinet_sysctl_unregister(struct net *net,
2331 struct ipv4_devconf *cnf, int ifindex)
Pavel Emelyanov51602b22007-12-11 02:17:40 -08002332{
2333 struct devinet_sysctl_table *t = cnf->sysctl;
2334
David Ahernb5c96412017-03-28 14:28:03 -07002335 if (t) {
2336 cnf->sysctl = NULL;
2337 unregister_net_sysctl_table(t->sysctl_header);
2338 kfree(t);
2339 }
Pavel Emelyanov51602b22007-12-11 02:17:40 -08002340
David Ahernb5c96412017-03-28 14:28:03 -07002341 inet_netconf_notify_devconf(net, RTM_DELNETCONF, 0, ifindex, NULL);
Pavel Emelyanov51602b22007-12-11 02:17:40 -08002342}
2343
WANG Cong20e61da2014-07-25 15:25:08 -07002344static int devinet_sysctl_register(struct in_device *idev)
Pavel Emelyanov66f27a52007-12-02 00:55:54 +11002345{
WANG Cong20e61da2014-07-25 15:25:08 -07002346 int err;
2347
2348 if (!sysctl_dev_name_is_allowed(idev->dev->name))
2349 return -EINVAL;
2350
2351 err = neigh_sysctl_register(idev->dev, idev->arp_parms, NULL);
2352 if (err)
2353 return err;
2354 err = __devinet_sysctl_register(dev_net(idev->dev), idev->dev->name,
Nicolas Dichtel29c994e2016-08-30 10:09:22 +02002355 idev->dev->ifindex, &idev->cnf);
WANG Cong20e61da2014-07-25 15:25:08 -07002356 if (err)
2357 neigh_sysctl_unregister(idev->arp_parms);
2358 return err;
Pavel Emelyanov66f27a52007-12-02 00:55:54 +11002359}
2360
Pavel Emelyanov51602b22007-12-11 02:17:40 -08002361static void devinet_sysctl_unregister(struct in_device *idev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362{
David Ahernb5c96412017-03-28 14:28:03 -07002363 struct net *net = dev_net(idev->dev);
2364
2365 __devinet_sysctl_unregister(net, &idev->cnf, idev->dev->ifindex);
Pavel Emelyanov51602b22007-12-11 02:17:40 -08002366 neigh_sysctl_unregister(idev->arp_parms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002368
Pavel Emelyanov68dd2992007-12-05 01:44:58 -08002369static struct ctl_table ctl_forward_entry[] = {
2370 {
Pavel Emelyanov68dd2992007-12-05 01:44:58 -08002371 .procname = "ip_forward",
2372 .data = &ipv4_devconf.data[
Eric W. Biederman02291682010-02-14 03:25:51 +00002373 IPV4_DEVCONF_FORWARDING - 1],
Pavel Emelyanov68dd2992007-12-05 01:44:58 -08002374 .maxlen = sizeof(int),
2375 .mode = 0644,
2376 .proc_handler = devinet_sysctl_forward,
Pavel Emelyanov68dd2992007-12-05 01:44:58 -08002377 .extra1 = &ipv4_devconf,
Pavel Emelyanovc0ce9fb2007-12-16 13:31:14 -08002378 .extra2 = &init_net,
Pavel Emelyanov68dd2992007-12-05 01:44:58 -08002379 },
2380 { },
2381};
Eric Dumazet2a75de02008-01-05 23:08:49 -08002382#endif
Pavel Emelyanov68dd2992007-12-05 01:44:58 -08002383
Pavel Emelyanov752d14d2007-12-16 13:31:47 -08002384static __net_init int devinet_init_net(struct net *net)
2385{
2386 int err;
Pavel Emelyanov752d14d2007-12-16 13:31:47 -08002387 struct ipv4_devconf *all, *dflt;
Eric Dumazet2a75de02008-01-05 23:08:49 -08002388#ifdef CONFIG_SYSCTL
2389 struct ctl_table *tbl = ctl_forward_entry;
Pavel Emelyanov752d14d2007-12-16 13:31:47 -08002390 struct ctl_table_header *forw_hdr;
Eric Dumazet2a75de02008-01-05 23:08:49 -08002391#endif
Pavel Emelyanov752d14d2007-12-16 13:31:47 -08002392
2393 err = -ENOMEM;
2394 all = &ipv4_devconf;
2395 dflt = &ipv4_devconf_dflt;
Pavel Emelyanov752d14d2007-12-16 13:31:47 -08002396
Octavian Purdila09ad9bc2009-11-25 15:14:13 -08002397 if (!net_eq(net, &init_net)) {
Pavel Emelyanov752d14d2007-12-16 13:31:47 -08002398 all = kmemdup(all, sizeof(ipv4_devconf), GFP_KERNEL);
Ian Morris51456b22015-04-03 09:17:26 +01002399 if (!all)
Pavel Emelyanov752d14d2007-12-16 13:31:47 -08002400 goto err_alloc_all;
2401
2402 dflt = kmemdup(dflt, sizeof(ipv4_devconf_dflt), GFP_KERNEL);
Ian Morris51456b22015-04-03 09:17:26 +01002403 if (!dflt)
Pavel Emelyanov752d14d2007-12-16 13:31:47 -08002404 goto err_alloc_dflt;
2405
Eric Dumazet2a75de02008-01-05 23:08:49 -08002406#ifdef CONFIG_SYSCTL
Pavel Emelyanov752d14d2007-12-16 13:31:47 -08002407 tbl = kmemdup(tbl, sizeof(ctl_forward_entry), GFP_KERNEL);
Ian Morris51456b22015-04-03 09:17:26 +01002408 if (!tbl)
Pavel Emelyanov752d14d2007-12-16 13:31:47 -08002409 goto err_alloc_ctl;
2410
Eric W. Biederman02291682010-02-14 03:25:51 +00002411 tbl[0].data = &all->data[IPV4_DEVCONF_FORWARDING - 1];
Pavel Emelyanov752d14d2007-12-16 13:31:47 -08002412 tbl[0].extra1 = all;
2413 tbl[0].extra2 = net;
Eric Dumazet2a75de02008-01-05 23:08:49 -08002414#endif
Pavel Emelyanov752d14d2007-12-16 13:31:47 -08002415 }
2416
2417#ifdef CONFIG_SYSCTL
Nicolas Dichtel29c994e2016-08-30 10:09:22 +02002418 err = __devinet_sysctl_register(net, "all", NETCONFA_IFINDEX_ALL, all);
Pavel Emelyanov752d14d2007-12-16 13:31:47 -08002419 if (err < 0)
2420 goto err_reg_all;
2421
Nicolas Dichtel29c994e2016-08-30 10:09:22 +02002422 err = __devinet_sysctl_register(net, "default",
2423 NETCONFA_IFINDEX_DEFAULT, dflt);
Pavel Emelyanov752d14d2007-12-16 13:31:47 -08002424 if (err < 0)
2425 goto err_reg_dflt;
2426
2427 err = -ENOMEM;
Eric W. Biederman8607ddb2012-04-19 13:42:09 +00002428 forw_hdr = register_net_sysctl(net, "net/ipv4", tbl);
Ian Morris51456b22015-04-03 09:17:26 +01002429 if (!forw_hdr)
Pavel Emelyanov752d14d2007-12-16 13:31:47 -08002430 goto err_reg_ctl;
Eric Dumazet2a75de02008-01-05 23:08:49 -08002431 net->ipv4.forw_hdr = forw_hdr;
Pavel Emelyanov752d14d2007-12-16 13:31:47 -08002432#endif
2433
Pavel Emelyanov752d14d2007-12-16 13:31:47 -08002434 net->ipv4.devconf_all = all;
2435 net->ipv4.devconf_dflt = dflt;
2436 return 0;
2437
2438#ifdef CONFIG_SYSCTL
2439err_reg_ctl:
David Ahernb5c96412017-03-28 14:28:03 -07002440 __devinet_sysctl_unregister(net, dflt, NETCONFA_IFINDEX_DEFAULT);
Pavel Emelyanov752d14d2007-12-16 13:31:47 -08002441err_reg_dflt:
David Ahernb5c96412017-03-28 14:28:03 -07002442 __devinet_sysctl_unregister(net, all, NETCONFA_IFINDEX_ALL);
Pavel Emelyanov752d14d2007-12-16 13:31:47 -08002443err_reg_all:
2444 if (tbl != ctl_forward_entry)
2445 kfree(tbl);
Pavel Emelyanov752d14d2007-12-16 13:31:47 -08002446err_alloc_ctl:
Eric Dumazet2a75de02008-01-05 23:08:49 -08002447#endif
Pavel Emelyanov752d14d2007-12-16 13:31:47 -08002448 if (dflt != &ipv4_devconf_dflt)
2449 kfree(dflt);
2450err_alloc_dflt:
2451 if (all != &ipv4_devconf)
2452 kfree(all);
2453err_alloc_all:
2454 return err;
2455}
2456
2457static __net_exit void devinet_exit_net(struct net *net)
2458{
Eric Dumazet2a75de02008-01-05 23:08:49 -08002459#ifdef CONFIG_SYSCTL
Pavel Emelyanov752d14d2007-12-16 13:31:47 -08002460 struct ctl_table *tbl;
2461
2462 tbl = net->ipv4.forw_hdr->ctl_table_arg;
Pavel Emelyanov752d14d2007-12-16 13:31:47 -08002463 unregister_net_sysctl_table(net->ipv4.forw_hdr);
David Ahernb5c96412017-03-28 14:28:03 -07002464 __devinet_sysctl_unregister(net, net->ipv4.devconf_dflt,
2465 NETCONFA_IFINDEX_DEFAULT);
2466 __devinet_sysctl_unregister(net, net->ipv4.devconf_all,
2467 NETCONFA_IFINDEX_ALL);
Pavel Emelyanov752d14d2007-12-16 13:31:47 -08002468 kfree(tbl);
Eric Dumazet2a75de02008-01-05 23:08:49 -08002469#endif
Pavel Emelyanov752d14d2007-12-16 13:31:47 -08002470 kfree(net->ipv4.devconf_dflt);
2471 kfree(net->ipv4.devconf_all);
2472}
2473
2474static __net_initdata struct pernet_operations devinet_ops = {
2475 .init = devinet_init_net,
2476 .exit = devinet_exit_net,
2477};
2478
Daniel Borkmann207895fd32015-01-29 12:15:03 +01002479static struct rtnl_af_ops inet_af_ops __read_mostly = {
Thomas Graf9f0f7272010-11-16 04:32:48 +00002480 .family = AF_INET,
2481 .fill_link_af = inet_fill_link_af,
2482 .get_link_af_size = inet_get_link_af_size,
Thomas Grafcf7afbf2010-11-22 01:31:54 +00002483 .validate_link_af = inet_validate_link_af,
2484 .set_link_af = inet_set_link_af,
Thomas Graf9f0f7272010-11-16 04:32:48 +00002485};
2486
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487void __init devinet_init(void)
2488{
David S. Millerfd23c3b2011-02-18 12:42:28 -08002489 int i;
2490
2491 for (i = 0; i < IN4_ADDR_HSIZE; i++)
2492 INIT_HLIST_HEAD(&inet_addr_lst[i]);
2493
Pavel Emelyanov752d14d2007-12-16 13:31:47 -08002494 register_pernet_subsys(&devinet_ops);
2495
Linus Torvalds1da177e2005-04-16 15:20:36 -07002496 register_gifconf(PF_INET, inet_gifconf);
2497 register_netdevice_notifier(&ip_netdev_notifier);
Thomas Graf63f34442007-03-22 11:55:17 -07002498
viresh kumar906e0732014-01-22 12:23:32 +05302499 queue_delayed_work(system_power_efficient_wq, &check_lifetime_work, 0);
Jiri Pirko5c766d62013-01-24 09:41:41 +00002500
Thomas Graf9f0f7272010-11-16 04:32:48 +00002501 rtnl_af_register(&inet_af_ops);
2502
Florian Westphalb97bac62017-08-09 20:41:48 +02002503 rtnl_register(PF_INET, RTM_NEWADDR, inet_rtm_newaddr, NULL, 0);
2504 rtnl_register(PF_INET, RTM_DELADDR, inet_rtm_deladdr, NULL, 0);
2505 rtnl_register(PF_INET, RTM_GETADDR, NULL, inet_dump_ifaddr, 0);
Nicolas Dichtel9e551112012-10-25 22:28:53 +00002506 rtnl_register(PF_INET, RTM_GETNETCONF, inet_netconf_get_devconf,
Florian Westphalb97bac62017-08-09 20:41:48 +02002507 inet_netconf_dump_devconf, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002508}