Blame view
net/ipv4/devinet.c
68.6 KB
2874c5fd2 treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
1da177e4c Linux-2.6.12-rc2 |
2 3 4 |
/* * NET3 IP device support routines. * |
1da177e4c Linux-2.6.12-rc2 |
5 |
* Derived from the IP parts of dev.c 1.0.19 |
02c30a84e [PATCH] update Ro... |
6 |
* Authors: Ross Biro |
1da177e4c Linux-2.6.12-rc2 |
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> * Mark Evans, <evansmp@uhura.aston.ac.uk> * * Additional Authors: * Alan Cox, <gw4pts@gw4pts.ampr.org> * Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> * * Changes: * Alexey Kuznetsov: pa_* fields are replaced with ifaddr * lists. * Cyrus Durgin: updated for kmod * Matthias Andree: in devinet_ioctl, compare label and * address (4.4BSD alias style support), * fall back to comparing just the label * if no match found. */ |
1da177e4c Linux-2.6.12-rc2 |
23 |
|
7c0f6ba68 Replace <asm/uacc... |
24 |
#include <linux/uaccess.h> |
1da177e4c Linux-2.6.12-rc2 |
25 |
#include <linux/bitops.h> |
4fc268d24 [PATCH] capable/c... |
26 |
#include <linux/capability.h> |
1da177e4c Linux-2.6.12-rc2 |
27 28 29 |
#include <linux/module.h> #include <linux/types.h> #include <linux/kernel.h> |
174cd4b1e sched/headers: Pr... |
30 |
#include <linux/sched/signal.h> |
1da177e4c Linux-2.6.12-rc2 |
31 32 33 34 35 36 37 |
#include <linux/string.h> #include <linux/mm.h> #include <linux/socket.h> #include <linux/sockios.h> #include <linux/in.h> #include <linux/errno.h> #include <linux/interrupt.h> |
1823730fb [IPv4]: Move inte... |
38 |
#include <linux/if_addr.h> |
1da177e4c Linux-2.6.12-rc2 |
39 40 41 42 43 |
#include <linux/if_ether.h> #include <linux/inet.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/skbuff.h> |
1da177e4c Linux-2.6.12-rc2 |
44 45 46 47 |
#include <linux/init.h> #include <linux/notifier.h> #include <linux/inetdevice.h> #include <linux/igmp.h> |
5a0e3ad6a include cleanup: ... |
48 |
#include <linux/slab.h> |
fd23c3b31 ipv4: Add hash ta... |
49 |
#include <linux/hash.h> |
1da177e4c Linux-2.6.12-rc2 |
50 51 52 53 |
#ifdef CONFIG_SYSCTL #include <linux/sysctl.h> #endif #include <linux/kmod.h> |
edc9e7489 rtnl/ipv4: use ne... |
54 |
#include <linux/netconf.h> |
1da177e4c Linux-2.6.12-rc2 |
55 |
|
14c850212 [INET_SOCK]: Move... |
56 |
#include <net/arp.h> |
1da177e4c Linux-2.6.12-rc2 |
57 58 59 |
#include <net/ip.h> #include <net/route.h> #include <net/ip_fib.h> |
63f3444fb [IPv4]: Use rtnl ... |
60 |
#include <net/rtnetlink.h> |
752d14dc6 [IPV4]: Move the ... |
61 |
#include <net/net_namespace.h> |
5c766d642 ipv4: introduce a... |
62 |
#include <net/addrconf.h> |
1da177e4c Linux-2.6.12-rc2 |
63 |
|
2e6054636 ipv4: don't set I... |
64 65 66 67 |
#define IPV6ONLY_FLAGS \ (IFA_F_NODAD | IFA_F_OPTIMISTIC | IFA_F_DADFAILED | \ IFA_F_HOMEADDRESS | IFA_F_TENTATIVE | \ IFA_F_MANAGETEMPADDR | IFA_F_STABLE_PRIVACY) |
0027ba843 [IPV4]: Make stru... |
68 |
static struct ipv4_devconf ipv4_devconf = { |
42f811b8b [IPV4]: Convert I... |
69 |
.data = { |
02291680f net ipv4: Decoupl... |
70 71 72 73 |
[IPV4_DEVCONF_ACCEPT_REDIRECTS - 1] = 1, [IPV4_DEVCONF_SEND_REDIRECTS - 1] = 1, [IPV4_DEVCONF_SECURE_REDIRECTS - 1] = 1, [IPV4_DEVCONF_SHARED_MEDIA - 1] = 1, |
2690048c0 net: igmp: Allow ... |
74 75 |
[IPV4_DEVCONF_IGMPV2_UNSOLICITED_REPORT_INTERVAL - 1] = 10000 /*ms*/, [IPV4_DEVCONF_IGMPV3_UNSOLICITED_REPORT_INTERVAL - 1] = 1000 /*ms*/, |
42f811b8b [IPV4]: Convert I... |
76 |
}, |
1da177e4c Linux-2.6.12-rc2 |
77 78 79 |
}; static struct ipv4_devconf ipv4_devconf_dflt = { |
42f811b8b [IPV4]: Convert I... |
80 |
.data = { |
02291680f net ipv4: Decoupl... |
81 82 83 84 85 |
[IPV4_DEVCONF_ACCEPT_REDIRECTS - 1] = 1, [IPV4_DEVCONF_SEND_REDIRECTS - 1] = 1, [IPV4_DEVCONF_SECURE_REDIRECTS - 1] = 1, [IPV4_DEVCONF_SHARED_MEDIA - 1] = 1, [IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE - 1] = 1, |
2690048c0 net: igmp: Allow ... |
86 87 |
[IPV4_DEVCONF_IGMPV2_UNSOLICITED_REPORT_INTERVAL - 1] = 10000 /*ms*/, [IPV4_DEVCONF_IGMPV3_UNSOLICITED_REPORT_INTERVAL - 1] = 1000 /*ms*/, |
42f811b8b [IPV4]: Convert I... |
88 |
}, |
1da177e4c Linux-2.6.12-rc2 |
89 |
}; |
9355bbd68 [IPV4]: Switch us... |
90 91 |
#define IPV4_DEVCONF_DFLT(net, attr) \ IPV4_DEVCONF((*net->ipv4.devconf_dflt), attr) |
42f811b8b [IPV4]: Convert I... |
92 |
|
ef7c79ed6 [NETLINK]: Mark n... |
93 |
static const struct nla_policy ifa_ipv4_policy[IFA_MAX+1] = { |
5c7539781 [IPV4]: Convert a... |
94 95 96 |
[IFA_LOCAL] = { .type = NLA_U32 }, [IFA_ADDRESS] = { .type = NLA_U32 }, [IFA_BROADCAST] = { .type = NLA_U32 }, |
5176f91ea [NETLINK]: Make u... |
97 |
[IFA_LABEL] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, |
5c766d642 ipv4: introduce a... |
98 |
[IFA_CACHEINFO] = { .len = sizeof(struct ifa_cacheinfo) }, |
ad6c81359 ipv4: add support... |
99 |
[IFA_FLAGS] = { .type = NLA_U32 }, |
af4d768ad net/ipv4: Add sup... |
100 |
[IFA_RT_PRIORITY] = { .type = NLA_U32 }, |
d38071455 ipv4: enable IFA_... |
101 |
[IFA_TARGET_NETNSID] = { .type = NLA_S32 }, |
5c7539781 [IPV4]: Convert a... |
102 |
}; |
978a46fa6 ipv4: add inet_fi... |
103 104 105 106 107 108 |
struct inet_fill_args { u32 portid; u32 seq; int event; unsigned int flags; int netnsid; |
5fcd266a9 net/ipv4: Add sup... |
109 |
int ifindex; |
978a46fa6 ipv4: add inet_fi... |
110 |
}; |
40384999d ipv4: change inet... |
111 112 |
#define IN4_ADDR_HSIZE_SHIFT 8 #define IN4_ADDR_HSIZE (1U << IN4_ADDR_HSIZE_SHIFT) |
fd23c3b31 ipv4: Add hash ta... |
113 |
static struct hlist_head inet_addr_lst[IN4_ADDR_HSIZE]; |
fd23c3b31 ipv4: Add hash ta... |
114 |
|
6eada0110 netns: constify n... |
115 |
static u32 inet_addr_hash(const struct net *net, __be32 addr) |
fd23c3b31 ipv4: Add hash ta... |
116 |
{ |
40384999d ipv4: change inet... |
117 |
u32 val = (__force u32) addr ^ net_hash_mix(net); |
fd23c3b31 ipv4: Add hash ta... |
118 |
|
40384999d ipv4: change inet... |
119 |
return hash_32(val, IN4_ADDR_HSIZE_SHIFT); |
fd23c3b31 ipv4: Add hash ta... |
120 121 122 123 |
} static void inet_hash_insert(struct net *net, struct in_ifaddr *ifa) { |
40384999d ipv4: change inet... |
124 |
u32 hash = inet_addr_hash(net, ifa->ifa_local); |
fd23c3b31 ipv4: Add hash ta... |
125 |
|
32a4be489 ipv4: remove inet... |
126 |
ASSERT_RTNL(); |
fd23c3b31 ipv4: Add hash ta... |
127 |
hlist_add_head_rcu(&ifa->hash, &inet_addr_lst[hash]); |
fd23c3b31 ipv4: Add hash ta... |
128 129 130 131 |
} static void inet_hash_remove(struct in_ifaddr *ifa) { |
32a4be489 ipv4: remove inet... |
132 |
ASSERT_RTNL(); |
fd23c3b31 ipv4: Add hash ta... |
133 |
hlist_del_init_rcu(&ifa->hash); |
fd23c3b31 ipv4: Add hash ta... |
134 |
} |
9435eb1cf ipv4: Implement _... |
135 136 137 138 139 140 141 142 143 144 |
/** * __ip_dev_find - find the first device with a given source address. * @net: the net namespace * @addr: the source address * @devref: if true, take a reference on the found device * * If a caller uses devref=false, it should be protected by RCU, or RTNL */ struct net_device *__ip_dev_find(struct net *net, __be32 addr, bool devref) { |
9435eb1cf ipv4: Implement _... |
145 146 |
struct net_device *result = NULL; struct in_ifaddr *ifa; |
9435eb1cf ipv4: Implement _... |
147 148 |
rcu_read_lock(); |
6e617de84 net: avoid a full... |
149 150 |
ifa = inet_lookup_ifaddr_rcu(net, addr); if (!ifa) { |
406b6f974 ipv4: Fallback to... |
151 152 153 154 155 156 157 158 159 160 161 162 |
struct flowi4 fl4 = { .daddr = addr }; struct fib_result res = { 0 }; struct fib_table *local; /* Fallback to FIB local table so that communication * over loopback subnets work. */ local = fib_get_table(net, RT_TABLE_LOCAL); if (local && !fib_table_lookup(local, &fl4, &res, FIB_LOOKUP_NOREF) && res.type == RTN_LOCAL) result = FIB_RES_DEV(res); |
6e617de84 net: avoid a full... |
163 164 |
} else { result = ifa->ifa_dev->dev; |
406b6f974 ipv4: Fallback to... |
165 |
} |
9435eb1cf ipv4: Implement _... |
166 167 168 169 170 171 |
if (result && devref) dev_hold(result); rcu_read_unlock(); return result; } EXPORT_SYMBOL(__ip_dev_find); |
6e617de84 net: avoid a full... |
172 173 174 175 176 177 178 179 180 181 182 183 184 |
/* called under RCU lock */ struct in_ifaddr *inet_lookup_ifaddr_rcu(struct net *net, __be32 addr) { u32 hash = inet_addr_hash(net, addr); struct in_ifaddr *ifa; hlist_for_each_entry_rcu(ifa, &inet_addr_lst[hash], hash) if (ifa->ifa_local == addr && net_eq(dev_net(ifa->ifa_dev->dev), net)) return ifa; return NULL; } |
d6062cbbd [IPv4] address: C... |
185 |
static void rtmsg_ifa(int event, struct in_ifaddr *, struct nlmsghdr *, u32); |
1da177e4c Linux-2.6.12-rc2 |
186 |
|
e041c6834 [PATCH] Notifier ... |
187 |
static BLOCKING_NOTIFIER_HEAD(inetaddr_chain); |
3ad7d2468 Ipvlan should ret... |
188 |
static BLOCKING_NOTIFIER_HEAD(inetaddr_validator_chain); |
2638eb8b5 net: ipv4: provid... |
189 190 |
static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr __rcu **ifap, |
1da177e4c Linux-2.6.12-rc2 |
191 192 |
int destroy); #ifdef CONFIG_SYSCTL |
20e61da7f ipv4: fail early ... |
193 |
static int devinet_sysctl_register(struct in_device *idev); |
51602b2a5 [IPV4]: Cleanup s... |
194 195 |
static void devinet_sysctl_unregister(struct in_device *idev); #else |
20e61da7f ipv4: fail early ... |
196 |
static int devinet_sysctl_register(struct in_device *idev) |
51602b2a5 [IPV4]: Cleanup s... |
197 |
{ |
20e61da7f ipv4: fail early ... |
198 |
return 0; |
51602b2a5 [IPV4]: Cleanup s... |
199 |
} |
40384999d ipv4: change inet... |
200 |
static void devinet_sysctl_unregister(struct in_device *idev) |
51602b2a5 [IPV4]: Cleanup s... |
201 202 |
{ } |
1da177e4c Linux-2.6.12-rc2 |
203 204 205 206 207 208 |
#endif /* Locks all the inet devices. */ static struct in_ifaddr *inet_alloc_ifa(void) { |
93adcc80f net: don't use IN... |
209 |
return kzalloc(sizeof(struct in_ifaddr), GFP_KERNEL); |
1da177e4c Linux-2.6.12-rc2 |
210 211 212 213 214 215 216 217 218 |
} static void inet_rcu_free_ifa(struct rcu_head *head) { struct in_ifaddr *ifa = container_of(head, struct in_ifaddr, rcu_head); if (ifa->ifa_dev) in_dev_put(ifa->ifa_dev); kfree(ifa); } |
40384999d ipv4: change inet... |
219 |
static void inet_free_ifa(struct in_ifaddr *ifa) |
1da177e4c Linux-2.6.12-rc2 |
220 221 222 223 224 225 226 |
{ call_rcu(&ifa->rcu_head, inet_rcu_free_ifa); } void in_dev_finish_destroy(struct in_device *idev) { struct net_device *dev = idev->dev; |
547b792ca net: convert BUG_... |
227 228 |
WARN_ON(idev->ifa_list); WARN_ON(idev->mc_list); |
e98970713 igmp: hash a hash... |
229 |
kfree(rcu_dereference_protected(idev->mc_hash, 1)); |
1da177e4c Linux-2.6.12-rc2 |
230 |
#ifdef NET_REFCNT_DEBUG |
91df42bed net: ipv4 and ipv... |
231 232 |
pr_debug("%s: %p=%s ", __func__, idev, dev ? dev->name : "NIL"); |
1da177e4c Linux-2.6.12-rc2 |
233 234 235 |
#endif dev_put(dev); if (!idev->dead) |
9f9354b92 net: net/ipv4/dev... |
236 237 238 |
pr_err("Freeing alive in_device %p ", idev); else |
1da177e4c Linux-2.6.12-rc2 |
239 |
kfree(idev); |
1da177e4c Linux-2.6.12-rc2 |
240 |
} |
9f9354b92 net: net/ipv4/dev... |
241 |
EXPORT_SYMBOL(in_dev_finish_destroy); |
1da177e4c Linux-2.6.12-rc2 |
242 |
|
71e27da96 [IPV4]: Restore o... |
243 |
static struct in_device *inetdev_init(struct net_device *dev) |
1da177e4c Linux-2.6.12-rc2 |
244 245 |
{ struct in_device *in_dev; |
20e61da7f ipv4: fail early ... |
246 |
int err = -ENOMEM; |
1da177e4c Linux-2.6.12-rc2 |
247 248 |
ASSERT_RTNL(); |
0da974f4f [NET]: Conversion... |
249 |
in_dev = kzalloc(sizeof(*in_dev), GFP_KERNEL); |
1da177e4c Linux-2.6.12-rc2 |
250 251 |
if (!in_dev) goto out; |
c346dca10 [NET] NETNS: Omit... |
252 |
memcpy(&in_dev->cnf, dev_net(dev)->ipv4.devconf_dflt, |
9355bbd68 [IPV4]: Switch us... |
253 |
sizeof(in_dev->cnf)); |
1da177e4c Linux-2.6.12-rc2 |
254 255 |
in_dev->cnf.sysctl = NULL; in_dev->dev = dev; |
9f9354b92 net: net/ipv4/dev... |
256 257 |
in_dev->arp_parms = neigh_parms_alloc(dev, &arp_tbl); if (!in_dev->arp_parms) |
1da177e4c Linux-2.6.12-rc2 |
258 |
goto out_kfree; |
0187bdfb0 net: Disable LRO ... |
259 260 |
if (IPV4_DEVCONF(in_dev->cnf, FORWARDING)) dev_disable_lro(dev); |
1da177e4c Linux-2.6.12-rc2 |
261 262 |
/* Reference in_dev->dev */ dev_hold(dev); |
30c4cf577 [IPV4/IPV6]: Fix ... |
263 |
/* Account for reference dev->ip_ptr (below) */ |
7658b36f1 net: convert in_d... |
264 |
refcount_set(&in_dev->refcnt, 1); |
1da177e4c Linux-2.6.12-rc2 |
265 |
|
20e61da7f ipv4: fail early ... |
266 267 268 |
err = devinet_sysctl_register(in_dev); if (err) { in_dev->dead = 1; |
1b49cd71b devinet: fix meml... |
269 |
neigh_parms_release(&arp_tbl, in_dev->arp_parms); |
20e61da7f ipv4: fail early ... |
270 271 272 273 |
in_dev_put(in_dev); in_dev = NULL; goto out; } |
1da177e4c Linux-2.6.12-rc2 |
274 275 276 |
ip_mc_init_dev(in_dev); if (dev->flags & IFF_UP) ip_mc_up(in_dev); |
483479ecc [IPV4] devinet: i... |
277 |
|
30c4cf577 [IPV4/IPV6]: Fix ... |
278 |
/* we can receive as soon as ip_ptr is set -- do this last */ |
cf778b00e net: reintroduce ... |
279 |
rcu_assign_pointer(dev->ip_ptr, in_dev); |
483479ecc [IPV4] devinet: i... |
280 |
out: |
20e61da7f ipv4: fail early ... |
281 |
return in_dev ?: ERR_PTR(err); |
1da177e4c Linux-2.6.12-rc2 |
282 283 284 285 286 287 288 289 290 291 292 293 294 295 |
out_kfree: kfree(in_dev); in_dev = NULL; goto out; } static void in_dev_rcu_put(struct rcu_head *head) { struct in_device *idev = container_of(head, struct in_device, rcu_head); in_dev_put(idev); } static void inetdev_destroy(struct in_device *in_dev) { |
1da177e4c Linux-2.6.12-rc2 |
296 |
struct net_device *dev; |
2638eb8b5 net: ipv4: provid... |
297 |
struct in_ifaddr *ifa; |
1da177e4c Linux-2.6.12-rc2 |
298 299 300 301 |
ASSERT_RTNL(); dev = in_dev->dev; |
1da177e4c Linux-2.6.12-rc2 |
302 303 304 305 |
in_dev->dead = 1; ip_mc_destroy_dev(in_dev); |
2638eb8b5 net: ipv4: provid... |
306 |
while ((ifa = rtnl_dereference(in_dev->ifa_list)) != NULL) { |
1da177e4c Linux-2.6.12-rc2 |
307 308 309 |
inet_del_ifa(in_dev, &in_dev->ifa_list, 0); inet_free_ifa(ifa); } |
a9b3cd7f3 rcu: convert uses... |
310 |
RCU_INIT_POINTER(dev->ip_ptr, NULL); |
1da177e4c Linux-2.6.12-rc2 |
311 |
|
51602b2a5 [IPV4]: Cleanup s... |
312 |
devinet_sysctl_unregister(in_dev); |
1da177e4c Linux-2.6.12-rc2 |
313 314 315 316 317 |
neigh_parms_release(&arp_tbl, in_dev->arp_parms); arp_ifdown(dev); call_rcu(&in_dev->rcu_head, in_dev_rcu_put); } |
ff428d72c [IPV4]: inet_addr... |
318 |
int inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b) |
1da177e4c Linux-2.6.12-rc2 |
319 |
{ |
d519e8708 devinet: use in_d... |
320 |
const struct in_ifaddr *ifa; |
1da177e4c Linux-2.6.12-rc2 |
321 |
rcu_read_lock(); |
d519e8708 devinet: use in_d... |
322 |
in_dev_for_each_ifa_rcu(ifa, in_dev) { |
1da177e4c Linux-2.6.12-rc2 |
323 324 325 326 327 328 |
if (inet_ifa_match(a, ifa)) { if (!b || inet_ifa_match(b, ifa)) { rcu_read_unlock(); return 1; } } |
d519e8708 devinet: use in_d... |
329 |
} |
1da177e4c Linux-2.6.12-rc2 |
330 331 332 |
rcu_read_unlock(); return 0; } |
2638eb8b5 net: ipv4: provid... |
333 334 335 |
static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr __rcu **ifap, int destroy, struct nlmsghdr *nlh, u32 portid) |
1da177e4c Linux-2.6.12-rc2 |
336 |
{ |
8f937c609 [IPV4]: Primary a... |
337 |
struct in_ifaddr *promote = NULL; |
2638eb8b5 net: ipv4: provid... |
338 339 |
struct in_ifaddr *ifa, *ifa1; struct in_ifaddr *last_prim; |
0ff60a456 [IPV4]: Fix secon... |
340 341 |
struct in_ifaddr *prev_prom = NULL; int do_promote = IN_DEV_PROMOTE_SECONDARIES(in_dev); |
1da177e4c Linux-2.6.12-rc2 |
342 343 |
ASSERT_RTNL(); |
2638eb8b5 net: ipv4: provid... |
344 345 |
ifa1 = rtnl_dereference(*ifap); last_prim = rtnl_dereference(in_dev->ifa_list); |
fbd40ea01 ipv4: Don't do ex... |
346 347 |
if (in_dev->dead) goto no_promotions; |
e905a9eda [NET] IPV4: Fix w... |
348 |
/* 1. Deleting primary ifaddr forces deletion all secondaries |
8f937c609 [IPV4]: Primary a... |
349 350 |
* unless alias promotion is set **/ |
1da177e4c Linux-2.6.12-rc2 |
351 352 |
if (!(ifa1->ifa_flags & IFA_F_SECONDARY)) { |
2638eb8b5 net: ipv4: provid... |
353 |
struct in_ifaddr __rcu **ifap1 = &ifa1->ifa_next; |
1da177e4c Linux-2.6.12-rc2 |
354 |
|
2638eb8b5 net: ipv4: provid... |
355 |
while ((ifa = rtnl_dereference(*ifap1)) != NULL) { |
e905a9eda [NET] IPV4: Fix w... |
356 |
if (!(ifa->ifa_flags & IFA_F_SECONDARY) && |
0ff60a456 [IPV4]: Fix secon... |
357 358 |
ifa1->ifa_scope <= ifa->ifa_scope) last_prim = ifa; |
1da177e4c Linux-2.6.12-rc2 |
359 360 361 362 |
if (!(ifa->ifa_flags & IFA_F_SECONDARY) || ifa1->ifa_mask != ifa->ifa_mask || !inet_ifa_match(ifa1->ifa_address, ifa)) { ifap1 = &ifa->ifa_next; |
0ff60a456 [IPV4]: Fix secon... |
363 |
prev_prom = ifa; |
1da177e4c Linux-2.6.12-rc2 |
364 365 |
continue; } |
0ff60a456 [IPV4]: Fix secon... |
366 |
if (!do_promote) { |
fd23c3b31 ipv4: Add hash ta... |
367 |
inet_hash_remove(ifa); |
8f937c609 [IPV4]: Primary a... |
368 |
*ifap1 = ifa->ifa_next; |
1da177e4c Linux-2.6.12-rc2 |
369 |
|
15e473046 netlink: Rename p... |
370 |
rtmsg_ifa(RTM_DELADDR, ifa, nlh, portid); |
e041c6834 [PATCH] Notifier ... |
371 372 |
blocking_notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa); |
8f937c609 [IPV4]: Primary a... |
373 374 375 376 377 |
inet_free_ifa(ifa); } else { promote = ifa; break; } |
1da177e4c Linux-2.6.12-rc2 |
378 379 |
} } |
2d230e2b2 ipv4: remove the ... |
380 381 382 383 384 |
/* On promotion all secondaries from subnet are changing * the primary IP, we must remove all their routes silently * and later to add them back with new prefsrc. Do this * while all addresses are on the device list. */ |
2638eb8b5 net: ipv4: provid... |
385 |
for (ifa = promote; ifa; ifa = rtnl_dereference(ifa->ifa_next)) { |
2d230e2b2 ipv4: remove the ... |
386 387 388 389 |
if (ifa1->ifa_mask == ifa->ifa_mask && inet_ifa_match(ifa1->ifa_address, ifa)) fib_del_ifaddr(ifa, ifa1); } |
fbd40ea01 ipv4: Don't do ex... |
390 |
no_promotions: |
1da177e4c Linux-2.6.12-rc2 |
391 392 393 |
/* 2. Unlink it */ *ifap = ifa1->ifa_next; |
fd23c3b31 ipv4: Add hash ta... |
394 |
inet_hash_remove(ifa1); |
1da177e4c Linux-2.6.12-rc2 |
395 396 397 398 399 400 401 402 403 404 405 |
/* 3. Announce address deletion */ /* Send message first, then call notifier. At first sight, FIB update triggered by notifier will refer to already deleted ifaddr, that could confuse netlink listeners. It is not true: look, gated sees that route deleted and if it still thinks that ifaddr is valid, it will try to restore deleted routes... Grr. So that, this order is correct. */ |
15e473046 netlink: Rename p... |
406 |
rtmsg_ifa(RTM_DELADDR, ifa1, nlh, portid); |
e041c6834 [PATCH] Notifier ... |
407 |
blocking_notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1); |
1da177e4c Linux-2.6.12-rc2 |
408 |
|
0ff60a456 [IPV4]: Fix secon... |
409 |
if (promote) { |
2638eb8b5 net: ipv4: provid... |
410 |
struct in_ifaddr *next_sec; |
0ff60a456 [IPV4]: Fix secon... |
411 |
|
2638eb8b5 net: ipv4: provid... |
412 |
next_sec = rtnl_dereference(promote->ifa_next); |
0ff60a456 [IPV4]: Fix secon... |
413 |
if (prev_prom) { |
2638eb8b5 net: ipv4: provid... |
414 |
struct in_ifaddr *last_sec; |
2638eb8b5 net: ipv4: provid... |
415 |
rcu_assign_pointer(prev_prom->ifa_next, next_sec); |
6a9e9cea4 net: ipv4: fix in... |
416 417 |
last_sec = rtnl_dereference(last_prim->ifa_next); |
2638eb8b5 net: ipv4: provid... |
418 419 |
rcu_assign_pointer(promote->ifa_next, last_sec); rcu_assign_pointer(last_prim->ifa_next, promote); |
0ff60a456 [IPV4]: Fix secon... |
420 |
} |
8f937c609 [IPV4]: Primary a... |
421 |
|
8f937c609 [IPV4]: Primary a... |
422 |
promote->ifa_flags &= ~IFA_F_SECONDARY; |
15e473046 netlink: Rename p... |
423 |
rtmsg_ifa(RTM_NEWADDR, promote, nlh, portid); |
e041c6834 [PATCH] Notifier ... |
424 425 |
blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, promote); |
2638eb8b5 net: ipv4: provid... |
426 427 |
for (ifa = next_sec; ifa; ifa = rtnl_dereference(ifa->ifa_next)) { |
0ff60a456 [IPV4]: Fix secon... |
428 429 430 431 432 433 434 |
if (ifa1->ifa_mask != ifa->ifa_mask || !inet_ifa_match(ifa1->ifa_address, ifa)) continue; fib_add_ifaddr(ifa); } } |
6363097cc [IPV4]: Do not re... |
435 |
if (destroy) |
0ff60a456 [IPV4]: Fix secon... |
436 |
inet_free_ifa(ifa1); |
1da177e4c Linux-2.6.12-rc2 |
437 |
} |
2638eb8b5 net: ipv4: provid... |
438 439 |
static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr __rcu **ifap, |
d6062cbbd [IPv4] address: C... |
440 441 442 443 |
int destroy) { __inet_del_ifa(in_dev, ifap, destroy, NULL, 0); } |
5c766d642 ipv4: introduce a... |
444 445 446 |
static void check_lifetime(struct work_struct *work); static DECLARE_DELAYED_WORK(check_lifetime_work, check_lifetime); |
d6062cbbd [IPv4] address: C... |
447 |
static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh, |
de95e0479 net: Add extack t... |
448 |
u32 portid, struct netlink_ext_ack *extack) |
1da177e4c Linux-2.6.12-rc2 |
449 |
{ |
2638eb8b5 net: ipv4: provid... |
450 |
struct in_ifaddr __rcu **last_primary, **ifap; |
1da177e4c Linux-2.6.12-rc2 |
451 |
struct in_device *in_dev = ifa->ifa_dev; |
3ad7d2468 Ipvlan should ret... |
452 |
struct in_validator_info ivi; |
2638eb8b5 net: ipv4: provid... |
453 |
struct in_ifaddr *ifa1; |
3ad7d2468 Ipvlan should ret... |
454 |
int ret; |
1da177e4c Linux-2.6.12-rc2 |
455 456 457 458 459 460 461 462 463 464 |
ASSERT_RTNL(); if (!ifa->ifa_local) { inet_free_ifa(ifa); return 0; } ifa->ifa_flags &= ~IFA_F_SECONDARY; last_primary = &in_dev->ifa_list; |
2e6054636 ipv4: don't set I... |
465 466 |
/* Don't set IPv6 only flags to IPv4 addresses */ ifa->ifa_flags &= ~IPV6ONLY_FLAGS; |
2638eb8b5 net: ipv4: provid... |
467 468 469 470 |
ifap = &in_dev->ifa_list; ifa1 = rtnl_dereference(*ifap); while (ifa1) { |
1da177e4c Linux-2.6.12-rc2 |
471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 |
if (!(ifa1->ifa_flags & IFA_F_SECONDARY) && ifa->ifa_scope <= ifa1->ifa_scope) last_primary = &ifa1->ifa_next; if (ifa1->ifa_mask == ifa->ifa_mask && inet_ifa_match(ifa1->ifa_address, ifa)) { if (ifa1->ifa_local == ifa->ifa_local) { inet_free_ifa(ifa); return -EEXIST; } if (ifa1->ifa_scope != ifa->ifa_scope) { inet_free_ifa(ifa); return -EINVAL; } ifa->ifa_flags |= IFA_F_SECONDARY; } |
2638eb8b5 net: ipv4: provid... |
486 487 488 |
ifap = &ifa1->ifa_next; ifa1 = rtnl_dereference(*ifap); |
1da177e4c Linux-2.6.12-rc2 |
489 |
} |
3ad7d2468 Ipvlan should ret... |
490 491 492 493 494 495 496 497 498 |
/* Allow any devices that wish to register ifaddr validtors to weigh * in now, before changes are committed. The rntl lock is serializing * access here, so the state should not change between a validator call * and a final notify on commit. This isn't invoked on promotion under * the assumption that validators are checking the address itself, and * not the flags. */ ivi.ivi_addr = ifa->ifa_address; ivi.ivi_dev = ifa->ifa_dev; |
de95e0479 net: Add extack t... |
499 |
ivi.extack = extack; |
3ad7d2468 Ipvlan should ret... |
500 501 502 503 504 505 506 |
ret = blocking_notifier_call_chain(&inetaddr_validator_chain, NETDEV_UP, &ivi); ret = notifier_to_errno(ret); if (ret) { inet_free_ifa(ifa); return ret; } |
1da177e4c Linux-2.6.12-rc2 |
507 |
if (!(ifa->ifa_flags & IFA_F_SECONDARY)) { |
63862b5be net: replace macr... |
508 |
prandom_seed((__force u32) ifa->ifa_local); |
1da177e4c Linux-2.6.12-rc2 |
509 510 |
ifap = last_primary; } |
2638eb8b5 net: ipv4: provid... |
511 512 |
rcu_assign_pointer(ifa->ifa_next, *ifap); rcu_assign_pointer(*ifap, ifa); |
1da177e4c Linux-2.6.12-rc2 |
513 |
|
fd23c3b31 ipv4: Add hash ta... |
514 |
inet_hash_insert(dev_net(in_dev->dev), ifa); |
5c766d642 ipv4: introduce a... |
515 |
cancel_delayed_work(&check_lifetime_work); |
906e073f3 net/ipv4: queue w... |
516 |
queue_delayed_work(system_power_efficient_wq, &check_lifetime_work, 0); |
5c766d642 ipv4: introduce a... |
517 |
|
1da177e4c Linux-2.6.12-rc2 |
518 519 520 |
/* Send message first, then call notifier. Notifier will trigger FIB update, so that listeners of netlink will know about new ifaddr */ |
15e473046 netlink: Rename p... |
521 |
rtmsg_ifa(RTM_NEWADDR, ifa, nlh, portid); |
e041c6834 [PATCH] Notifier ... |
522 |
blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa); |
1da177e4c Linux-2.6.12-rc2 |
523 524 525 |
return 0; } |
d6062cbbd [IPv4] address: C... |
526 527 |
static int inet_insert_ifa(struct in_ifaddr *ifa) { |
de95e0479 net: Add extack t... |
528 |
return __inet_insert_ifa(ifa, NULL, 0, NULL); |
d6062cbbd [IPv4] address: C... |
529 |
} |
1da177e4c Linux-2.6.12-rc2 |
530 531 |
static int inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa) { |
e5ed63991 [IPV4]: Replace _... |
532 |
struct in_device *in_dev = __in_dev_get_rtnl(dev); |
1da177e4c Linux-2.6.12-rc2 |
533 534 535 536 |
ASSERT_RTNL(); if (!in_dev) { |
71e27da96 [IPV4]: Restore o... |
537 538 |
inet_free_ifa(ifa); return -ENOBUFS; |
1da177e4c Linux-2.6.12-rc2 |
539 |
} |
71e27da96 [IPV4]: Restore o... |
540 |
ipv4_devconf_setall(in_dev); |
1d4c8c298 neigh: restore ol... |
541 |
neigh_parms_data_state_setall(in_dev->arp_parms); |
1da177e4c Linux-2.6.12-rc2 |
542 |
if (ifa->ifa_dev != in_dev) { |
547b792ca net: convert BUG_... |
543 |
WARN_ON(ifa->ifa_dev); |
1da177e4c Linux-2.6.12-rc2 |
544 545 546 |
in_dev_hold(in_dev); ifa->ifa_dev = in_dev; } |
f97c1e0c6 [IPV4] net/ipv4: ... |
547 |
if (ipv4_is_loopback(ifa->ifa_local)) |
1da177e4c Linux-2.6.12-rc2 |
548 549 550 |
ifa->ifa_scope = RT_SCOPE_HOST; return inet_insert_ifa(ifa); } |
8723e1b4a inet: RCU changes... |
551 552 553 |
/* Caller must hold RCU or RTNL : * We dont take a reference on found in_device */ |
7fee0ca23 [NETNS]: Add netn... |
554 |
struct in_device *inetdev_by_index(struct net *net, int ifindex) |
1da177e4c Linux-2.6.12-rc2 |
555 556 557 |
{ struct net_device *dev; struct in_device *in_dev = NULL; |
c148fc2e3 ipv4: inetdev_by_... |
558 559 560 |
rcu_read_lock(); dev = dev_get_by_index_rcu(net, ifindex); |
1da177e4c Linux-2.6.12-rc2 |
561 |
if (dev) |
8723e1b4a inet: RCU changes... |
562 |
in_dev = rcu_dereference_rtnl(dev->ip_ptr); |
c148fc2e3 ipv4: inetdev_by_... |
563 |
rcu_read_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
564 565 |
return in_dev; } |
9f9354b92 net: net/ipv4/dev... |
566 |
EXPORT_SYMBOL(inetdev_by_index); |
1da177e4c Linux-2.6.12-rc2 |
567 568 |
/* Called only from RTNL semaphored context. No locks. */ |
60cad5da5 [IPV4]: annotate ... |
569 570 |
struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, __be32 prefix, __be32 mask) |
1da177e4c Linux-2.6.12-rc2 |
571 |
{ |
d519e8708 devinet: use in_d... |
572 |
struct in_ifaddr *ifa; |
1da177e4c Linux-2.6.12-rc2 |
573 |
ASSERT_RTNL(); |
d519e8708 devinet: use in_d... |
574 |
in_dev_for_each_ifa_rtnl(ifa, in_dev) { |
1da177e4c Linux-2.6.12-rc2 |
575 576 |
if (ifa->ifa_mask == mask && inet_ifa_match(prefix, ifa)) return ifa; |
d519e8708 devinet: use in_d... |
577 |
} |
1da177e4c Linux-2.6.12-rc2 |
578 579 |
return NULL; } |
690cc8632 net: ipv4: devine... |
580 581 |
static int ip_mc_autojoin_config(struct net *net, bool join, const struct in_ifaddr *ifa) |
93a714d6b multicast: Extend... |
582 |
{ |
690cc8632 net: ipv4: devine... |
583 |
#if defined(CONFIG_IP_MULTICAST) |
93a714d6b multicast: Extend... |
584 585 586 587 |
struct ip_mreqn mreq = { .imr_multiaddr.s_addr = ifa->ifa_address, .imr_ifindex = ifa->ifa_dev->dev->ifindex, }; |
690cc8632 net: ipv4: devine... |
588 |
struct sock *sk = net->ipv4.mc_autojoin_sk; |
93a714d6b multicast: Extend... |
589 590 591 592 593 594 |
int ret; ASSERT_RTNL(); lock_sock(sk); if (join) |
54ff9ef36 ipv4, ipv6: kill ... |
595 |
ret = ip_mc_join_group(sk, &mreq); |
93a714d6b multicast: Extend... |
596 |
else |
54ff9ef36 ipv4, ipv6: kill ... |
597 |
ret = ip_mc_leave_group(sk, &mreq); |
93a714d6b multicast: Extend... |
598 599 600 |
release_sock(sk); return ret; |
690cc8632 net: ipv4: devine... |
601 602 603 |
#else return -EOPNOTSUPP; #endif |
93a714d6b multicast: Extend... |
604 |
} |
c21ef3e34 net: rtnetlink: p... |
605 606 |
static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, struct netlink_ext_ack *extack) |
1da177e4c Linux-2.6.12-rc2 |
607 |
{ |
3b1e0a655 [NET] NETNS: Omit... |
608 |
struct net *net = sock_net(skb->sk); |
2638eb8b5 net: ipv4: provid... |
609 |
struct in_ifaddr __rcu **ifap; |
dfdd5fd4e [IPV4]: Convert a... |
610 |
struct nlattr *tb[IFA_MAX+1]; |
1da177e4c Linux-2.6.12-rc2 |
611 |
struct in_device *in_dev; |
dfdd5fd4e [IPV4]: Convert a... |
612 |
struct ifaddrmsg *ifm; |
2638eb8b5 net: ipv4: provid... |
613 |
struct in_ifaddr *ifa; |
dfdd5fd4e [IPV4]: Convert a... |
614 |
int err = -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
615 616 |
ASSERT_RTNL(); |
8cb081746 netlink: make val... |
617 618 |
err = nlmsg_parse_deprecated(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv4_policy, extack); |
dfdd5fd4e [IPV4]: Convert a... |
619 620 621 622 |
if (err < 0) goto errout; ifm = nlmsg_data(nlh); |
7fee0ca23 [NETNS]: Add netn... |
623 |
in_dev = inetdev_by_index(net, ifm->ifa_index); |
51456b291 ipv4: coding styl... |
624 |
if (!in_dev) { |
dfdd5fd4e [IPV4]: Convert a... |
625 626 627 |
err = -ENODEV; goto errout; } |
2638eb8b5 net: ipv4: provid... |
628 |
for (ifap = &in_dev->ifa_list; (ifa = rtnl_dereference(*ifap)) != NULL; |
1da177e4c Linux-2.6.12-rc2 |
629 |
ifap = &ifa->ifa_next) { |
dfdd5fd4e [IPV4]: Convert a... |
630 |
if (tb[IFA_LOCAL] && |
67b61f6c1 netlink: implemen... |
631 |
ifa->ifa_local != nla_get_in_addr(tb[IFA_LOCAL])) |
dfdd5fd4e [IPV4]: Convert a... |
632 633 634 |
continue; if (tb[IFA_LABEL] && nla_strcmp(tb[IFA_LABEL], ifa->ifa_label)) |
1da177e4c Linux-2.6.12-rc2 |
635 |
continue; |
dfdd5fd4e [IPV4]: Convert a... |
636 637 638 |
if (tb[IFA_ADDRESS] && (ifm->ifa_prefixlen != ifa->ifa_prefixlen || |
67b61f6c1 netlink: implemen... |
639 |
!inet_ifa_match(nla_get_in_addr(tb[IFA_ADDRESS]), ifa))) |
dfdd5fd4e [IPV4]: Convert a... |
640 |
continue; |
93a714d6b multicast: Extend... |
641 |
if (ipv4_is_multicast(ifa->ifa_address)) |
690cc8632 net: ipv4: devine... |
642 |
ip_mc_autojoin_config(net, false, ifa); |
15e473046 netlink: Rename p... |
643 |
__inet_del_ifa(in_dev, ifap, 1, nlh, NETLINK_CB(skb).portid); |
1da177e4c Linux-2.6.12-rc2 |
644 645 |
return 0; } |
dfdd5fd4e [IPV4]: Convert a... |
646 647 648 649 |
err = -EADDRNOTAVAIL; errout: return err; |
1da177e4c Linux-2.6.12-rc2 |
650 |
} |
5c766d642 ipv4: introduce a... |
651 652 653 654 655 656 |
#define INFINITY_LIFE_TIME 0xFFFFFFFF static void check_lifetime(struct work_struct *work) { unsigned long now, next, next_sec, next_sched; struct in_ifaddr *ifa; |
c988d1e8c net: ipv4: fix sc... |
657 |
struct hlist_node *n; |
5c766d642 ipv4: introduce a... |
658 659 660 661 |
int i; now = jiffies; next = round_jiffies_up(now + ADDR_CHECK_FREQUENCY); |
5c766d642 ipv4: introduce a... |
662 |
for (i = 0; i < IN4_ADDR_HSIZE; i++) { |
c988d1e8c net: ipv4: fix sc... |
663 664 665 |
bool change_needed = false; rcu_read_lock(); |
b67bfe0d4 hlist: drop the n... |
666 |
hlist_for_each_entry_rcu(ifa, &inet_addr_lst[i], hash) { |
5c766d642 ipv4: introduce a... |
667 668 669 670 671 672 673 674 675 676 677 |
unsigned long age; if (ifa->ifa_flags & IFA_F_PERMANENT) continue; /* We try to batch several events at once. */ age = (now - ifa->ifa_tstamp + ADDRCONF_TIMER_FUZZ_MINUS) / HZ; if (ifa->ifa_valid_lft != INFINITY_LIFE_TIME && age >= ifa->ifa_valid_lft) { |
c988d1e8c net: ipv4: fix sc... |
678 |
change_needed = true; |
5c766d642 ipv4: introduce a... |
679 680 681 682 683 684 685 686 |
} else if (ifa->ifa_preferred_lft == INFINITY_LIFE_TIME) { continue; } else if (age >= ifa->ifa_preferred_lft) { if (time_before(ifa->ifa_tstamp + ifa->ifa_valid_lft * HZ, next)) next = ifa->ifa_tstamp + ifa->ifa_valid_lft * HZ; |
c988d1e8c net: ipv4: fix sc... |
687 688 |
if (!(ifa->ifa_flags & IFA_F_DEPRECATED)) change_needed = true; |
5c766d642 ipv4: introduce a... |
689 690 691 692 693 694 695 |
} else if (time_before(ifa->ifa_tstamp + ifa->ifa_preferred_lft * HZ, next)) { next = ifa->ifa_tstamp + ifa->ifa_preferred_lft * HZ; } } |
c988d1e8c net: ipv4: fix sc... |
696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 |
rcu_read_unlock(); if (!change_needed) continue; rtnl_lock(); hlist_for_each_entry_safe(ifa, n, &inet_addr_lst[i], hash) { unsigned long age; if (ifa->ifa_flags & IFA_F_PERMANENT) continue; /* We try to batch several events at once. */ age = (now - ifa->ifa_tstamp + ADDRCONF_TIMER_FUZZ_MINUS) / HZ; if (ifa->ifa_valid_lft != INFINITY_LIFE_TIME && age >= ifa->ifa_valid_lft) { |
2638eb8b5 net: ipv4: provid... |
712 713 714 715 716 717 |
struct in_ifaddr __rcu **ifap; struct in_ifaddr *tmp; ifap = &ifa->ifa_dev->ifa_list; tmp = rtnl_dereference(*ifap); while (tmp) { |
40008e921 net: ipv4: remove... |
718 |
if (tmp == ifa) { |
c988d1e8c net: ipv4: fix sc... |
719 720 721 722 |
inet_del_ifa(ifa->ifa_dev, ifap, 1); break; } |
2638eb8b5 net: ipv4: provid... |
723 724 |
ifap = &tmp->ifa_next; tmp = rtnl_dereference(*ifap); |
c988d1e8c net: ipv4: fix sc... |
725 726 727 728 729 730 731 732 733 734 |
} } else if (ifa->ifa_preferred_lft != INFINITY_LIFE_TIME && age >= ifa->ifa_preferred_lft && !(ifa->ifa_flags & IFA_F_DEPRECATED)) { ifa->ifa_flags |= IFA_F_DEPRECATED; rtmsg_ifa(RTM_NEWADDR, ifa, NULL, 0); } } rtnl_unlock(); |
5c766d642 ipv4: introduce a... |
735 |
} |
5c766d642 ipv4: introduce a... |
736 737 738 739 740 741 742 743 744 745 746 747 |
next_sec = round_jiffies_up(next); next_sched = next; /* If rounded timeout is accurate enough, accept it. */ if (time_before(next_sec, next + ADDRCONF_TIMER_FUZZ)) next_sched = next_sec; now = jiffies; /* And minimum interval is ADDRCONF_TIMER_FUZZ_MAX. */ if (time_before(next_sched, now + ADDRCONF_TIMER_FUZZ_MAX)) next_sched = now + ADDRCONF_TIMER_FUZZ_MAX; |
906e073f3 net/ipv4: queue w... |
748 749 |
queue_delayed_work(system_power_efficient_wq, &check_lifetime_work, next_sched - now); |
5c766d642 ipv4: introduce a... |
750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 |
} static void set_ifa_lifetime(struct in_ifaddr *ifa, __u32 valid_lft, __u32 prefered_lft) { unsigned long timeout; ifa->ifa_flags &= ~(IFA_F_PERMANENT | IFA_F_DEPRECATED); timeout = addrconf_timeout_fixup(valid_lft, HZ); if (addrconf_finite_timeout(timeout)) ifa->ifa_valid_lft = timeout; else ifa->ifa_flags |= IFA_F_PERMANENT; timeout = addrconf_timeout_fixup(prefered_lft, HZ); if (addrconf_finite_timeout(timeout)) { if (timeout == 0) ifa->ifa_flags |= IFA_F_DEPRECATED; ifa->ifa_preferred_lft = timeout; } ifa->ifa_tstamp = jiffies; if (!ifa->ifa_cstamp) ifa->ifa_cstamp = ifa->ifa_tstamp; } static struct in_ifaddr *rtm_to_ifaddr(struct net *net, struct nlmsghdr *nlh, |
dac9c9790 net: Add extack t... |
777 778 |
__u32 *pvalid_lft, __u32 *pprefered_lft, struct netlink_ext_ack *extack) |
1da177e4c Linux-2.6.12-rc2 |
779 |
{ |
5c7539781 [IPV4]: Convert a... |
780 781 782 |
struct nlattr *tb[IFA_MAX+1]; struct in_ifaddr *ifa; struct ifaddrmsg *ifm; |
1da177e4c Linux-2.6.12-rc2 |
783 784 |
struct net_device *dev; struct in_device *in_dev; |
7b2185747 [IPV4]: Small sty... |
785 |
int err; |
1da177e4c Linux-2.6.12-rc2 |
786 |
|
8cb081746 netlink: make val... |
787 788 |
err = nlmsg_parse_deprecated(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv4_policy, extack); |
5c7539781 [IPV4]: Convert a... |
789 790 |
if (err < 0) goto errout; |
1da177e4c Linux-2.6.12-rc2 |
791 |
|
5c7539781 [IPV4]: Convert a... |
792 |
ifm = nlmsg_data(nlh); |
7b2185747 [IPV4]: Small sty... |
793 |
err = -EINVAL; |
51456b291 ipv4: coding styl... |
794 |
if (ifm->ifa_prefixlen > 32 || !tb[IFA_LOCAL]) |
5c7539781 [IPV4]: Convert a... |
795 |
goto errout; |
1da177e4c Linux-2.6.12-rc2 |
796 |
|
4b8aa9abe [NETNS]: Process ... |
797 |
dev = __dev_get_by_index(net, ifm->ifa_index); |
7b2185747 [IPV4]: Small sty... |
798 |
err = -ENODEV; |
51456b291 ipv4: coding styl... |
799 |
if (!dev) |
5c7539781 [IPV4]: Convert a... |
800 |
goto errout; |
1da177e4c Linux-2.6.12-rc2 |
801 |
|
5c7539781 [IPV4]: Convert a... |
802 |
in_dev = __in_dev_get_rtnl(dev); |
7b2185747 [IPV4]: Small sty... |
803 |
err = -ENOBUFS; |
51456b291 ipv4: coding styl... |
804 |
if (!in_dev) |
71e27da96 [IPV4]: Restore o... |
805 |
goto errout; |
1da177e4c Linux-2.6.12-rc2 |
806 |
|
5c7539781 [IPV4]: Convert a... |
807 |
ifa = inet_alloc_ifa(); |
51456b291 ipv4: coding styl... |
808 |
if (!ifa) |
5c7539781 [IPV4]: Convert a... |
809 810 811 812 |
/* * A potential indev allocation can be left alive, it stays * assigned to its device and is destroy with it. */ |
5c7539781 [IPV4]: Convert a... |
813 |
goto errout; |
5c7539781 [IPV4]: Convert a... |
814 |
|
a4e65d36a [IPV4]: Swap the ... |
815 |
ipv4_devconf_setall(in_dev); |
1d4c8c298 neigh: restore ol... |
816 |
neigh_parms_data_state_setall(in_dev->arp_parms); |
5c7539781 [IPV4]: Convert a... |
817 |
in_dev_hold(in_dev); |
51456b291 ipv4: coding styl... |
818 |
if (!tb[IFA_ADDRESS]) |
5c7539781 [IPV4]: Convert a... |
819 |
tb[IFA_ADDRESS] = tb[IFA_LOCAL]; |
1da177e4c Linux-2.6.12-rc2 |
820 |
|
fd23c3b31 ipv4: Add hash ta... |
821 |
INIT_HLIST_NODE(&ifa->hash); |
1da177e4c Linux-2.6.12-rc2 |
822 823 |
ifa->ifa_prefixlen = ifm->ifa_prefixlen; ifa->ifa_mask = inet_make_mask(ifm->ifa_prefixlen); |
ad6c81359 ipv4: add support... |
824 825 |
ifa->ifa_flags = tb[IFA_FLAGS] ? nla_get_u32(tb[IFA_FLAGS]) : ifm->ifa_flags; |
1da177e4c Linux-2.6.12-rc2 |
826 |
ifa->ifa_scope = ifm->ifa_scope; |
5c7539781 [IPV4]: Convert a... |
827 |
ifa->ifa_dev = in_dev; |
67b61f6c1 netlink: implemen... |
828 829 |
ifa->ifa_local = nla_get_in_addr(tb[IFA_LOCAL]); ifa->ifa_address = nla_get_in_addr(tb[IFA_ADDRESS]); |
5c7539781 [IPV4]: Convert a... |
830 831 |
if (tb[IFA_BROADCAST]) |
67b61f6c1 netlink: implemen... |
832 |
ifa->ifa_broadcast = nla_get_in_addr(tb[IFA_BROADCAST]); |
5c7539781 [IPV4]: Convert a... |
833 |
|
5c7539781 [IPV4]: Convert a... |
834 835 |
if (tb[IFA_LABEL]) nla_strlcpy(ifa->ifa_label, tb[IFA_LABEL], IFNAMSIZ); |
1da177e4c Linux-2.6.12-rc2 |
836 837 |
else memcpy(ifa->ifa_label, dev->name, IFNAMSIZ); |
af4d768ad net/ipv4: Add sup... |
838 839 |
if (tb[IFA_RT_PRIORITY]) ifa->ifa_rt_priority = nla_get_u32(tb[IFA_RT_PRIORITY]); |
5c766d642 ipv4: introduce a... |
840 841 842 843 844 845 |
if (tb[IFA_CACHEINFO]) { struct ifa_cacheinfo *ci; ci = nla_data(tb[IFA_CACHEINFO]); if (!ci->ifa_valid || ci->ifa_prefered > ci->ifa_valid) { err = -EINVAL; |
446266b0c net: rtm_to_ifadd... |
846 |
goto errout_free; |
5c766d642 ipv4: introduce a... |
847 848 849 850 |
} *pvalid_lft = ci->ifa_valid; *pprefered_lft = ci->ifa_prefered; } |
5c7539781 [IPV4]: Convert a... |
851 |
return ifa; |
446266b0c net: rtm_to_ifadd... |
852 853 |
errout_free: inet_free_ifa(ifa); |
5c7539781 [IPV4]: Convert a... |
854 855 856 |
errout: return ERR_PTR(err); } |
5c766d642 ipv4: introduce a... |
857 858 859 |
static struct in_ifaddr *find_matching_ifa(struct in_ifaddr *ifa) { struct in_device *in_dev = ifa->ifa_dev; |
ef11db331 net: inetdevice: ... |
860 |
struct in_ifaddr *ifa1; |
5c766d642 ipv4: introduce a... |
861 862 863 |
if (!ifa->ifa_local) return NULL; |
ef11db331 net: inetdevice: ... |
864 |
in_dev_for_each_ifa_rtnl(ifa1, in_dev) { |
5c766d642 ipv4: introduce a... |
865 866 867 868 869 870 871 |
if (ifa1->ifa_mask == ifa->ifa_mask && inet_ifa_match(ifa1->ifa_address, ifa) && ifa1->ifa_local == ifa->ifa_local) return ifa1; } return NULL; } |
c21ef3e34 net: rtnetlink: p... |
872 873 |
static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, struct netlink_ext_ack *extack) |
5c7539781 [IPV4]: Convert a... |
874 |
{ |
3b1e0a655 [NET] NETNS: Omit... |
875 |
struct net *net = sock_net(skb->sk); |
5c7539781 [IPV4]: Convert a... |
876 |
struct in_ifaddr *ifa; |
5c766d642 ipv4: introduce a... |
877 878 879 |
struct in_ifaddr *ifa_existing; __u32 valid_lft = INFINITY_LIFE_TIME; __u32 prefered_lft = INFINITY_LIFE_TIME; |
5c7539781 [IPV4]: Convert a... |
880 881 |
ASSERT_RTNL(); |
dac9c9790 net: Add extack t... |
882 |
ifa = rtm_to_ifaddr(net, nlh, &valid_lft, &prefered_lft, extack); |
5c7539781 [IPV4]: Convert a... |
883 884 |
if (IS_ERR(ifa)) return PTR_ERR(ifa); |
5c766d642 ipv4: introduce a... |
885 886 887 |
ifa_existing = find_matching_ifa(ifa); if (!ifa_existing) { /* It would be best to check for !NLM_F_CREATE here but |
614d056c8 ipv4: minor spell... |
888 |
* userspace already relies on not having to provide this. |
5c766d642 ipv4: introduce a... |
889 890 |
*/ set_ifa_lifetime(ifa, valid_lft, prefered_lft); |
93a714d6b multicast: Extend... |
891 |
if (ifa->ifa_flags & IFA_F_MCAUTOJOIN) { |
690cc8632 net: ipv4: devine... |
892 |
int ret = ip_mc_autojoin_config(net, true, ifa); |
93a714d6b multicast: Extend... |
893 894 895 896 897 898 |
if (ret < 0) { inet_free_ifa(ifa); return ret; } } |
de95e0479 net: Add extack t... |
899 900 |
return __inet_insert_ifa(ifa, nlh, NETLINK_CB(skb).portid, extack); |
5c766d642 ipv4: introduce a... |
901 |
} else { |
af4d768ad net/ipv4: Add sup... |
902 |
u32 new_metric = ifa->ifa_rt_priority; |
5c766d642 ipv4: introduce a... |
903 904 905 906 907 |
inet_free_ifa(ifa); if (nlh->nlmsg_flags & NLM_F_EXCL || !(nlh->nlmsg_flags & NLM_F_REPLACE)) return -EEXIST; |
34e2ed34a net: ipv4: notify... |
908 |
ifa = ifa_existing; |
af4d768ad net/ipv4: Add sup... |
909 910 911 912 913 |
if (ifa->ifa_rt_priority != new_metric) { fib_modify_prefix_metric(ifa, new_metric); ifa->ifa_rt_priority = new_metric; } |
34e2ed34a net: ipv4: notify... |
914 |
set_ifa_lifetime(ifa, valid_lft, prefered_lft); |
05a324b9c net: ipv4: reset ... |
915 |
cancel_delayed_work(&check_lifetime_work); |
906e073f3 net/ipv4: queue w... |
916 917 |
queue_delayed_work(system_power_efficient_wq, &check_lifetime_work, 0); |
34e2ed34a net: ipv4: notify... |
918 |
rtmsg_ifa(RTM_NEWADDR, ifa, nlh, NETLINK_CB(skb).portid); |
5c766d642 ipv4: introduce a... |
919 920 |
} return 0; |
1da177e4c Linux-2.6.12-rc2 |
921 922 923 924 925 |
} /* * Determine a default network mask, based on the IP address. */ |
40384999d ipv4: change inet... |
926 |
static int inet_abc_len(__be32 addr) |
1da177e4c Linux-2.6.12-rc2 |
927 928 |
{ int rc = -1; /* Something else, probably a multicast. */ |
65cab850f net: Allow class-... |
929 |
if (ipv4_is_zeronet(addr) || ipv4_is_lbcast(addr)) |
e905a9eda [NET] IPV4: Fix w... |
930 |
rc = 0; |
1da177e4c Linux-2.6.12-rc2 |
931 |
else { |
714e85be3 [IPV6]: Assorted ... |
932 |
__u32 haddr = ntohl(addr); |
714e85be3 [IPV6]: Assorted ... |
933 |
if (IN_CLASSA(haddr)) |
1da177e4c Linux-2.6.12-rc2 |
934 |
rc = 8; |
714e85be3 [IPV6]: Assorted ... |
935 |
else if (IN_CLASSB(haddr)) |
1da177e4c Linux-2.6.12-rc2 |
936 |
rc = 16; |
714e85be3 [IPV6]: Assorted ... |
937 |
else if (IN_CLASSC(haddr)) |
1da177e4c Linux-2.6.12-rc2 |
938 |
rc = 24; |
65cab850f net: Allow class-... |
939 940 |
else if (IN_CLASSE(haddr)) rc = 32; |
1da177e4c Linux-2.6.12-rc2 |
941 |
} |
e905a9eda [NET] IPV4: Fix w... |
942 |
return rc; |
1da177e4c Linux-2.6.12-rc2 |
943 |
} |
03aef17bb devinet_ioctl(): ... |
944 |
int devinet_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr) |
1da177e4c Linux-2.6.12-rc2 |
945 |
{ |
1da177e4c Linux-2.6.12-rc2 |
946 |
struct sockaddr_in sin_orig; |
03aef17bb devinet_ioctl(): ... |
947 |
struct sockaddr_in *sin = (struct sockaddr_in *)&ifr->ifr_addr; |
2638eb8b5 net: ipv4: provid... |
948 |
struct in_ifaddr __rcu **ifap = NULL; |
1da177e4c Linux-2.6.12-rc2 |
949 |
struct in_device *in_dev; |
1da177e4c Linux-2.6.12-rc2 |
950 951 952 953 954 |
struct in_ifaddr *ifa = NULL; struct net_device *dev; char *colon; int ret = -EFAULT; int tryaddrmatch = 0; |
03aef17bb devinet_ioctl(): ... |
955 |
ifr->ifr_name[IFNAMSIZ - 1] = 0; |
1da177e4c Linux-2.6.12-rc2 |
956 957 958 |
/* save original address for comparison */ memcpy(&sin_orig, sin, sizeof(*sin)); |
03aef17bb devinet_ioctl(): ... |
959 |
colon = strchr(ifr->ifr_name, ':'); |
1da177e4c Linux-2.6.12-rc2 |
960 961 |
if (colon) *colon = 0; |
03aef17bb devinet_ioctl(): ... |
962 |
dev_load(net, ifr->ifr_name); |
1da177e4c Linux-2.6.12-rc2 |
963 |
|
132adf546 [IPV4]: cleanup |
964 |
switch (cmd) { |
1da177e4c Linux-2.6.12-rc2 |
965 966 967 968 969 970 971 972 973 974 975 976 977 978 |
case SIOCGIFADDR: /* Get interface address */ case SIOCGIFBRDADDR: /* Get the broadcast address */ case SIOCGIFDSTADDR: /* Get the destination address */ case SIOCGIFNETMASK: /* Get the netmask for the interface */ /* Note that these ioctls will not sleep, so that we do not impose a lock. One day we will be forced to put shlock here (I mean SMP) */ tryaddrmatch = (sin_orig.sin_family == AF_INET); memset(sin, 0, sizeof(*sin)); sin->sin_family = AF_INET; break; case SIOCSIFFLAGS: |
bf5b30b8a net: change retur... |
979 |
ret = -EPERM; |
52e804c6d net: Allow userns... |
980 |
if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) |
1da177e4c Linux-2.6.12-rc2 |
981 982 983 984 985 986 |
goto out; break; case SIOCSIFADDR: /* Set interface address (and family) */ case SIOCSIFBRDADDR: /* Set the broadcast address */ case SIOCSIFDSTADDR: /* Set the destination address */ case SIOCSIFNETMASK: /* Set the netmask for the interface */ |
bf5b30b8a net: change retur... |
987 |
ret = -EPERM; |
52e804c6d net: Allow userns... |
988 |
if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) |
1da177e4c Linux-2.6.12-rc2 |
989 990 991 992 993 994 995 996 997 998 999 1000 1001 |
goto out; ret = -EINVAL; if (sin->sin_family != AF_INET) goto out; break; default: ret = -EINVAL; goto out; } rtnl_lock(); ret = -ENODEV; |
03aef17bb devinet_ioctl(): ... |
1002 |
dev = __dev_get_by_name(net, ifr->ifr_name); |
9f9354b92 net: net/ipv4/dev... |
1003 |
if (!dev) |
1da177e4c Linux-2.6.12-rc2 |
1004 1005 1006 1007 |
goto done; if (colon) *colon = ':'; |
9f9354b92 net: net/ipv4/dev... |
1008 1009 |
in_dev = __in_dev_get_rtnl(dev); if (in_dev) { |
1da177e4c Linux-2.6.12-rc2 |
1010 1011 1012 1013 1014 1015 |
if (tryaddrmatch) { /* Matthias Andree */ /* compare label and address (4.4BSD style) */ /* note: we only do this for a limited set of ioctls and only if the original address family was AF_INET. This is checked above. */ |
2638eb8b5 net: ipv4: provid... |
1016 1017 1018 |
for (ifap = &in_dev->ifa_list; (ifa = rtnl_dereference(*ifap)) != NULL; |
1da177e4c Linux-2.6.12-rc2 |
1019 |
ifap = &ifa->ifa_next) { |
03aef17bb devinet_ioctl(): ... |
1020 |
if (!strcmp(ifr->ifr_name, ifa->ifa_label) && |
1da177e4c Linux-2.6.12-rc2 |
1021 |
sin_orig.sin_addr.s_addr == |
6c91afe1a ipv4: Fix erroneo... |
1022 |
ifa->ifa_local) { |
1da177e4c Linux-2.6.12-rc2 |
1023 1024 1025 1026 1027 1028 1029 1030 |
break; /* found */ } } } /* we didn't get a match, maybe the application is 4.3BSD-style and passed in junk so we fall back to comparing just the label */ if (!ifa) { |
2638eb8b5 net: ipv4: provid... |
1031 1032 |
for (ifap = &in_dev->ifa_list; (ifa = rtnl_dereference(*ifap)) != NULL; |
1da177e4c Linux-2.6.12-rc2 |
1033 |
ifap = &ifa->ifa_next) |
03aef17bb devinet_ioctl(): ... |
1034 |
if (!strcmp(ifr->ifr_name, ifa->ifa_label)) |
1da177e4c Linux-2.6.12-rc2 |
1035 1036 1037 1038 1039 1040 1041 |
break; } } ret = -EADDRNOTAVAIL; if (!ifa && cmd != SIOCSIFADDR && cmd != SIOCSIFFLAGS) goto done; |
132adf546 [IPV4]: cleanup |
1042 |
switch (cmd) { |
1da177e4c Linux-2.6.12-rc2 |
1043 |
case SIOCGIFADDR: /* Get interface address */ |
30e948a37 ipv4: Get the add... |
1044 |
ret = 0; |
1da177e4c Linux-2.6.12-rc2 |
1045 |
sin->sin_addr.s_addr = ifa->ifa_local; |
03aef17bb devinet_ioctl(): ... |
1046 |
break; |
1da177e4c Linux-2.6.12-rc2 |
1047 1048 |
case SIOCGIFBRDADDR: /* Get the broadcast address */ |
30e948a37 ipv4: Get the add... |
1049 |
ret = 0; |
1da177e4c Linux-2.6.12-rc2 |
1050 |
sin->sin_addr.s_addr = ifa->ifa_broadcast; |
03aef17bb devinet_ioctl(): ... |
1051 |
break; |
1da177e4c Linux-2.6.12-rc2 |
1052 1053 |
case SIOCGIFDSTADDR: /* Get the destination address */ |
30e948a37 ipv4: Get the add... |
1054 |
ret = 0; |
1da177e4c Linux-2.6.12-rc2 |
1055 |
sin->sin_addr.s_addr = ifa->ifa_address; |
03aef17bb devinet_ioctl(): ... |
1056 |
break; |
1da177e4c Linux-2.6.12-rc2 |
1057 1058 |
case SIOCGIFNETMASK: /* Get the netmask for the interface */ |
30e948a37 ipv4: Get the add... |
1059 |
ret = 0; |
1da177e4c Linux-2.6.12-rc2 |
1060 |
sin->sin_addr.s_addr = ifa->ifa_mask; |
03aef17bb devinet_ioctl(): ... |
1061 |
break; |
1da177e4c Linux-2.6.12-rc2 |
1062 1063 1064 1065 1066 1067 1068 |
case SIOCSIFFLAGS: if (colon) { ret = -EADDRNOTAVAIL; if (!ifa) break; ret = 0; |
03aef17bb devinet_ioctl(): ... |
1069 |
if (!(ifr->ifr_flags & IFF_UP)) |
1da177e4c Linux-2.6.12-rc2 |
1070 1071 1072 |
inet_del_ifa(in_dev, ifap, 1); break; } |
567c5e13b net: core: dev: A... |
1073 |
ret = dev_change_flags(dev, ifr->ifr_flags, NULL); |
1da177e4c Linux-2.6.12-rc2 |
1074 1075 1076 1077 1078 1079 1080 1081 1082 |
break; case SIOCSIFADDR: /* Set interface address (and family) */ ret = -EINVAL; if (inet_abc_len(sin->sin_addr.s_addr) < 0) break; if (!ifa) { ret = -ENOBUFS; |
9f9354b92 net: net/ipv4/dev... |
1083 1084 |
ifa = inet_alloc_ifa(); if (!ifa) |
1da177e4c Linux-2.6.12-rc2 |
1085 |
break; |
c7e2e1d72 ipv4: fix NULL ch... |
1086 |
INIT_HLIST_NODE(&ifa->hash); |
1da177e4c Linux-2.6.12-rc2 |
1087 |
if (colon) |
03aef17bb devinet_ioctl(): ... |
1088 |
memcpy(ifa->ifa_label, ifr->ifr_name, IFNAMSIZ); |
1da177e4c Linux-2.6.12-rc2 |
1089 1090 1091 1092 1093 1094 1095 1096 |
else memcpy(ifa->ifa_label, dev->name, IFNAMSIZ); } else { ret = 0; if (ifa->ifa_local == sin->sin_addr.s_addr) break; inet_del_ifa(in_dev, ifap, 0); ifa->ifa_broadcast = 0; |
148f97292 [IPV4]: Reset sco... |
1097 |
ifa->ifa_scope = 0; |
1da177e4c Linux-2.6.12-rc2 |
1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 |
} ifa->ifa_address = ifa->ifa_local = sin->sin_addr.s_addr; if (!(dev->flags & IFF_POINTOPOINT)) { ifa->ifa_prefixlen = inet_abc_len(ifa->ifa_address); ifa->ifa_mask = inet_make_mask(ifa->ifa_prefixlen); if ((dev->flags & IFF_BROADCAST) && ifa->ifa_prefixlen < 31) ifa->ifa_broadcast = ifa->ifa_address | ~ifa->ifa_mask; } else { ifa->ifa_prefixlen = 32; ifa->ifa_mask = inet_make_mask(32); } |
5c766d642 ipv4: introduce a... |
1113 |
set_ifa_lifetime(ifa, INFINITY_LIFE_TIME, INFINITY_LIFE_TIME); |
1da177e4c Linux-2.6.12-rc2 |
1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 |
ret = inet_set_ifa(dev, ifa); break; case SIOCSIFBRDADDR: /* Set the broadcast address */ ret = 0; if (ifa->ifa_broadcast != sin->sin_addr.s_addr) { inet_del_ifa(in_dev, ifap, 0); ifa->ifa_broadcast = sin->sin_addr.s_addr; inet_insert_ifa(ifa); } break; case SIOCSIFDSTADDR: /* Set the destination address */ ret = 0; if (ifa->ifa_address == sin->sin_addr.s_addr) break; ret = -EINVAL; if (inet_abc_len(sin->sin_addr.s_addr) < 0) break; ret = 0; inet_del_ifa(in_dev, ifap, 0); ifa->ifa_address = sin->sin_addr.s_addr; inet_insert_ifa(ifa); break; case SIOCSIFNETMASK: /* Set the netmask for the interface */ /* * The mask we set must be legal. */ ret = -EINVAL; if (bad_mask(sin->sin_addr.s_addr, 0)) break; ret = 0; if (ifa->ifa_mask != sin->sin_addr.s_addr) { |
a144ea4b7 [IPV4]: annotate ... |
1149 |
__be32 old_mask = ifa->ifa_mask; |
1da177e4c Linux-2.6.12-rc2 |
1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 |
inet_del_ifa(in_dev, ifap, 0); ifa->ifa_mask = sin->sin_addr.s_addr; ifa->ifa_prefixlen = inet_mask_len(ifa->ifa_mask); /* See if current broadcast address matches * with current netmask, then recalculate * the broadcast address. Otherwise it's a * funny address, so don't touch it since * the user seems to know what (s)he's doing... */ if ((dev->flags & IFF_BROADCAST) && (ifa->ifa_prefixlen < 31) && (ifa->ifa_broadcast == |
dcab5e1ee [IPV4]: Fix setti... |
1163 |
(ifa->ifa_local|~old_mask))) { |
1da177e4c Linux-2.6.12-rc2 |
1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 |
ifa->ifa_broadcast = (ifa->ifa_local | ~sin->sin_addr.s_addr); } inet_insert_ifa(ifa); } break; } done: rtnl_unlock(); out: return ret; |
1da177e4c Linux-2.6.12-rc2 |
1175 |
} |
36fd633ec net: separate SIO... |
1176 |
static int inet_gifconf(struct net_device *dev, char __user *buf, int len, int size) |
1da177e4c Linux-2.6.12-rc2 |
1177 |
{ |
e5ed63991 [IPV4]: Replace _... |
1178 |
struct in_device *in_dev = __in_dev_get_rtnl(dev); |
ef11db331 net: inetdevice: ... |
1179 |
const struct in_ifaddr *ifa; |
1da177e4c Linux-2.6.12-rc2 |
1180 1181 |
struct ifreq ifr; int done = 0; |
36fd633ec net: separate SIO... |
1182 1183 |
if (WARN_ON(size > sizeof(struct ifreq))) goto out; |
9f9354b92 net: net/ipv4/dev... |
1184 |
if (!in_dev) |
1da177e4c Linux-2.6.12-rc2 |
1185 |
goto out; |
ef11db331 net: inetdevice: ... |
1186 |
in_dev_for_each_ifa_rtnl(ifa, in_dev) { |
1da177e4c Linux-2.6.12-rc2 |
1187 |
if (!buf) { |
36fd633ec net: separate SIO... |
1188 |
done += size; |
1da177e4c Linux-2.6.12-rc2 |
1189 1190 |
continue; } |
36fd633ec net: separate SIO... |
1191 |
if (len < size) |
1da177e4c Linux-2.6.12-rc2 |
1192 1193 |
break; memset(&ifr, 0, sizeof(struct ifreq)); |
4299c8a94 net: remove an un... |
1194 |
strcpy(ifr.ifr_name, ifa->ifa_label); |
1da177e4c Linux-2.6.12-rc2 |
1195 1196 1197 1198 |
(*(struct sockaddr_in *)&ifr.ifr_addr).sin_family = AF_INET; (*(struct sockaddr_in *)&ifr.ifr_addr).sin_addr.s_addr = ifa->ifa_local; |
36fd633ec net: separate SIO... |
1199 |
if (copy_to_user(buf + done, &ifr, size)) { |
1da177e4c Linux-2.6.12-rc2 |
1200 1201 1202 |
done = -EFAULT; break; } |
36fd633ec net: separate SIO... |
1203 1204 |
len -= size; done += size; |
1da177e4c Linux-2.6.12-rc2 |
1205 1206 1207 1208 |
} out: return done; } |
8b57fd1ec net: Eliminate du... |
1209 1210 1211 |
static __be32 in_dev_select_addr(const struct in_device *in_dev, int scope) { |
d519e8708 devinet: use in_d... |
1212 1213 1214 1215 1216 |
const struct in_ifaddr *ifa; in_dev_for_each_ifa_rcu(ifa, in_dev) { if (ifa->ifa_flags & IFA_F_SECONDARY) continue; |
8b57fd1ec net: Eliminate du... |
1217 1218 1219 |
if (ifa->ifa_scope != RT_SCOPE_LINK && ifa->ifa_scope <= scope) return ifa->ifa_local; |
d519e8708 devinet: use in_d... |
1220 |
} |
8b57fd1ec net: Eliminate du... |
1221 1222 1223 |
return 0; } |
a61ced5d1 [IPV4]: inet_sele... |
1224 |
__be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope) |
1da177e4c Linux-2.6.12-rc2 |
1225 |
{ |
d519e8708 devinet: use in_d... |
1226 |
const struct in_ifaddr *ifa; |
a61ced5d1 [IPV4]: inet_sele... |
1227 |
__be32 addr = 0; |
d8c444d54 ipv4: fix inet_se... |
1228 |
unsigned char localnet_scope = RT_SCOPE_HOST; |
1da177e4c Linux-2.6.12-rc2 |
1229 |
struct in_device *in_dev; |
c346dca10 [NET] NETNS: Omit... |
1230 |
struct net *net = dev_net(dev); |
3f2fb9a83 net: l3mdev: addr... |
1231 |
int master_idx; |
1da177e4c Linux-2.6.12-rc2 |
1232 1233 |
rcu_read_lock(); |
e5ed63991 [IPV4]: Replace _... |
1234 |
in_dev = __in_dev_get_rcu(dev); |
1da177e4c Linux-2.6.12-rc2 |
1235 1236 |
if (!in_dev) goto no_in_dev; |
d8c444d54 ipv4: fix inet_se... |
1237 1238 |
if (unlikely(IN_DEV_ROUTE_LOCALNET(in_dev))) localnet_scope = RT_SCOPE_LINK; |
d519e8708 devinet: use in_d... |
1239 1240 1241 |
in_dev_for_each_ifa_rcu(ifa, in_dev) { if (ifa->ifa_flags & IFA_F_SECONDARY) continue; |
d8c444d54 ipv4: fix inet_se... |
1242 |
if (min(ifa->ifa_scope, localnet_scope) > scope) |
1da177e4c Linux-2.6.12-rc2 |
1243 1244 1245 1246 1247 1248 1249 |
continue; if (!dst || inet_ifa_match(dst, ifa)) { addr = ifa->ifa_local; break; } if (!addr) addr = ifa->ifa_local; |
d519e8708 devinet: use in_d... |
1250 |
} |
1da177e4c Linux-2.6.12-rc2 |
1251 1252 |
if (addr) |
c6d14c845 net: Introduce fo... |
1253 |
goto out_unlock; |
9f9354b92 net: net/ipv4/dev... |
1254 |
no_in_dev: |
3f2fb9a83 net: l3mdev: addr... |
1255 |
master_idx = l3mdev_master_ifindex_rcu(dev); |
1da177e4c Linux-2.6.12-rc2 |
1256 |
|
17b693cdd net: l3mdev: pref... |
1257 1258 1259 1260 1261 1262 1263 1264 |
/* For VRFs, the VRF device takes the place of the loopback device, * with addresses on it being preferred. Note in such cases the * loopback device will be among the devices that fail the master_idx * equality check in the loop below. */ if (master_idx && (dev = dev_get_by_index_rcu(net, master_idx)) && (in_dev = __in_dev_get_rcu(dev))) { |
8b57fd1ec net: Eliminate du... |
1265 1266 1267 |
addr = in_dev_select_addr(in_dev, scope); if (addr) goto out_unlock; |
17b693cdd net: l3mdev: pref... |
1268 |
} |
1da177e4c Linux-2.6.12-rc2 |
1269 |
/* Not loopback addresses on loopback should be preferred |
ca9f1fd26 net: spelling fixes |
1270 |
in this case. It is important that lo is the first interface |
1da177e4c Linux-2.6.12-rc2 |
1271 1272 |
in dev_base list. */ |
c6d14c845 net: Introduce fo... |
1273 |
for_each_netdev_rcu(net, dev) { |
3f2fb9a83 net: l3mdev: addr... |
1274 1275 |
if (l3mdev_master_ifindex_rcu(dev) != master_idx) continue; |
9f9354b92 net: net/ipv4/dev... |
1276 1277 |
in_dev = __in_dev_get_rcu(dev); if (!in_dev) |
1da177e4c Linux-2.6.12-rc2 |
1278 |
continue; |
8b57fd1ec net: Eliminate du... |
1279 1280 1281 |
addr = in_dev_select_addr(in_dev, scope); if (addr) goto out_unlock; |
1da177e4c Linux-2.6.12-rc2 |
1282 |
} |
c6d14c845 net: Introduce fo... |
1283 |
out_unlock: |
1da177e4c Linux-2.6.12-rc2 |
1284 |
rcu_read_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
1285 1286 |
return addr; } |
9f9354b92 net: net/ipv4/dev... |
1287 |
EXPORT_SYMBOL(inet_select_addr); |
1da177e4c Linux-2.6.12-rc2 |
1288 |
|
60cad5da5 [IPV4]: annotate ... |
1289 1290 |
static __be32 confirm_addr_indev(struct in_device *in_dev, __be32 dst, __be32 local, int scope) |
1da177e4c Linux-2.6.12-rc2 |
1291 |
{ |
650638a7c ipv4: fix confirm... |
1292 |
unsigned char localnet_scope = RT_SCOPE_HOST; |
ef11db331 net: inetdevice: ... |
1293 |
const struct in_ifaddr *ifa; |
a144ea4b7 [IPV4]: annotate ... |
1294 |
__be32 addr = 0; |
ef11db331 net: inetdevice: ... |
1295 |
int same = 0; |
1da177e4c Linux-2.6.12-rc2 |
1296 |
|
650638a7c ipv4: fix confirm... |
1297 1298 |
if (unlikely(IN_DEV_ROUTE_LOCALNET(in_dev))) localnet_scope = RT_SCOPE_LINK; |
ef11db331 net: inetdevice: ... |
1299 |
in_dev_for_each_ifa_rcu(ifa, in_dev) { |
650638a7c ipv4: fix confirm... |
1300 |
unsigned char min_scope = min(ifa->ifa_scope, localnet_scope); |
1da177e4c Linux-2.6.12-rc2 |
1301 1302 |
if (!addr && (local == ifa->ifa_local || !local) && |
650638a7c ipv4: fix confirm... |
1303 |
min_scope <= scope) { |
1da177e4c Linux-2.6.12-rc2 |
1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 |
addr = ifa->ifa_local; if (same) break; } if (!same) { same = (!local || inet_ifa_match(local, ifa)) && (!dst || inet_ifa_match(dst, ifa)); if (same && addr) { if (local || !dst) break; /* Is the selected addr into dst subnet? */ if (inet_ifa_match(addr, ifa)) break; /* No, then can we use new local src? */ |
650638a7c ipv4: fix confirm... |
1318 |
if (min_scope <= scope) { |
1da177e4c Linux-2.6.12-rc2 |
1319 1320 1321 1322 1323 1324 1325 |
addr = ifa->ifa_local; break; } /* search for large dst subnet for addr */ same = 0; } } |
ef11db331 net: inetdevice: ... |
1326 |
} |
1da177e4c Linux-2.6.12-rc2 |
1327 |
|
9f9354b92 net: net/ipv4/dev... |
1328 |
return same ? addr : 0; |
1da177e4c Linux-2.6.12-rc2 |
1329 1330 1331 1332 |
} /* * Confirm that local IP address exists using wildcards: |
b601fa197 ipv4: fix wildcar... |
1333 1334 |
* - net: netns to check, cannot be NULL * - in_dev: only on this interface, NULL=any interface |
1da177e4c Linux-2.6.12-rc2 |
1335 1336 1337 1338 |
* - dst: only in the same subnet as dst, 0=any dst * - local: address, 0=autoselect the local address * - scope: maximum allowed scope value for the local address */ |
b601fa197 ipv4: fix wildcar... |
1339 |
__be32 inet_confirm_addr(struct net *net, struct in_device *in_dev, |
9bd85e326 [IPV4]: Remove ex... |
1340 |
__be32 dst, __be32 local, int scope) |
1da177e4c Linux-2.6.12-rc2 |
1341 |
{ |
60cad5da5 [IPV4]: annotate ... |
1342 |
__be32 addr = 0; |
9bd85e326 [IPV4]: Remove ex... |
1343 |
struct net_device *dev; |
1da177e4c Linux-2.6.12-rc2 |
1344 |
|
00db41243 ipv4: coding styl... |
1345 |
if (in_dev) |
9bd85e326 [IPV4]: Remove ex... |
1346 |
return confirm_addr_indev(in_dev, dst, local, scope); |
1da177e4c Linux-2.6.12-rc2 |
1347 |
|
1da177e4c Linux-2.6.12-rc2 |
1348 |
rcu_read_lock(); |
c6d14c845 net: Introduce fo... |
1349 |
for_each_netdev_rcu(net, dev) { |
9f9354b92 net: net/ipv4/dev... |
1350 1351 |
in_dev = __in_dev_get_rcu(dev); if (in_dev) { |
1da177e4c Linux-2.6.12-rc2 |
1352 1353 1354 1355 1356 1357 |
addr = confirm_addr_indev(in_dev, dst, local, scope); if (addr) break; } } rcu_read_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
1358 1359 1360 |
return addr; } |
eaddcd769 bonding: remove e... |
1361 |
EXPORT_SYMBOL(inet_confirm_addr); |
1da177e4c Linux-2.6.12-rc2 |
1362 1363 1364 1365 1366 1367 1368 |
/* * Device notifier */ int register_inetaddr_notifier(struct notifier_block *nb) { |
e041c6834 [PATCH] Notifier ... |
1369 |
return blocking_notifier_chain_register(&inetaddr_chain, nb); |
1da177e4c Linux-2.6.12-rc2 |
1370 |
} |
9f9354b92 net: net/ipv4/dev... |
1371 |
EXPORT_SYMBOL(register_inetaddr_notifier); |
1da177e4c Linux-2.6.12-rc2 |
1372 1373 1374 |
int unregister_inetaddr_notifier(struct notifier_block *nb) { |
e041c6834 [PATCH] Notifier ... |
1375 |
return blocking_notifier_chain_unregister(&inetaddr_chain, nb); |
1da177e4c Linux-2.6.12-rc2 |
1376 |
} |
9f9354b92 net: net/ipv4/dev... |
1377 |
EXPORT_SYMBOL(unregister_inetaddr_notifier); |
1da177e4c Linux-2.6.12-rc2 |
1378 |
|
3ad7d2468 Ipvlan should ret... |
1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 |
int register_inetaddr_validator_notifier(struct notifier_block *nb) { return blocking_notifier_chain_register(&inetaddr_validator_chain, nb); } EXPORT_SYMBOL(register_inetaddr_validator_notifier); int unregister_inetaddr_validator_notifier(struct notifier_block *nb) { return blocking_notifier_chain_unregister(&inetaddr_validator_chain, nb); } EXPORT_SYMBOL(unregister_inetaddr_validator_notifier); |
9f9354b92 net: net/ipv4/dev... |
1391 1392 |
/* Rename ifa_labels for a device name change. Make some effort to preserve * existing alias numbering and to create unique labels if possible. |
1da177e4c Linux-2.6.12-rc2 |
1393 1394 |
*/ static void inetdev_changename(struct net_device *dev, struct in_device *in_dev) |
e905a9eda [NET] IPV4: Fix w... |
1395 |
{ |
1da177e4c Linux-2.6.12-rc2 |
1396 1397 |
struct in_ifaddr *ifa; int named = 0; |
ef11db331 net: inetdevice: ... |
1398 |
in_dev_for_each_ifa_rtnl(ifa, in_dev) { |
e905a9eda [NET] IPV4: Fix w... |
1399 |
char old[IFNAMSIZ], *dot; |
1da177e4c Linux-2.6.12-rc2 |
1400 1401 |
memcpy(old, ifa->ifa_label, IFNAMSIZ); |
e905a9eda [NET] IPV4: Fix w... |
1402 |
memcpy(ifa->ifa_label, dev->name, IFNAMSIZ); |
1da177e4c Linux-2.6.12-rc2 |
1403 |
if (named++ == 0) |
573bf470e ipv4 addr: Send n... |
1404 |
goto skip; |
44344b2a8 [INET]: Fix netde... |
1405 |
dot = strchr(old, ':'); |
51456b291 ipv4: coding styl... |
1406 |
if (!dot) { |
e905a9eda [NET] IPV4: Fix w... |
1407 |
sprintf(old, ":%d", named); |
1da177e4c Linux-2.6.12-rc2 |
1408 1409 |
dot = old; } |
9f9354b92 net: net/ipv4/dev... |
1410 |
if (strlen(dot) + strlen(dev->name) < IFNAMSIZ) |
e905a9eda [NET] IPV4: Fix w... |
1411 |
strcat(ifa->ifa_label, dot); |
9f9354b92 net: net/ipv4/dev... |
1412 |
else |
e905a9eda [NET] IPV4: Fix w... |
1413 |
strcpy(ifa->ifa_label + (IFNAMSIZ - strlen(dot) - 1), dot); |
573bf470e ipv4 addr: Send n... |
1414 1415 |
skip: rtmsg_ifa(RTM_NEWADDR, ifa, NULL, 0); |
e905a9eda [NET] IPV4: Fix w... |
1416 1417 |
} } |
1da177e4c Linux-2.6.12-rc2 |
1418 |
|
d11327ad6 arp_notify: uncon... |
1419 1420 1421 1422 |
static void inetdev_send_gratuitous_arp(struct net_device *dev, struct in_device *in_dev) { |
ef11db331 net: inetdevice: ... |
1423 |
const struct in_ifaddr *ifa; |
d11327ad6 arp_notify: uncon... |
1424 |
|
ef11db331 net: inetdevice: ... |
1425 |
in_dev_for_each_ifa_rtnl(ifa, in_dev) { |
b76d0789c IPv4: Send gratui... |
1426 1427 1428 1429 1430 |
arp_send(ARPOP_REQUEST, ETH_P_ARP, ifa->ifa_local, dev, ifa->ifa_local, NULL, dev->dev_addr, NULL); } |
d11327ad6 arp_notify: uncon... |
1431 |
} |
1da177e4c Linux-2.6.12-rc2 |
1432 1433 1434 1435 1436 |
/* Called only under RTNL semaphore */ static int inetdev_event(struct notifier_block *this, unsigned long event, void *ptr) { |
351638e7d net: pass info st... |
1437 |
struct net_device *dev = netdev_notifier_info_to_dev(ptr); |
748e2d939 net: reinstate rt... |
1438 |
struct in_device *in_dev = __in_dev_get_rtnl(dev); |
0115e8e30 net: remove delay... |
1439 |
|
1da177e4c Linux-2.6.12-rc2 |
1440 1441 1442 |
ASSERT_RTNL(); if (!in_dev) { |
8030f5449 [IPV4] devinet: R... |
1443 |
if (event == NETDEV_REGISTER) { |
1da177e4c Linux-2.6.12-rc2 |
1444 |
in_dev = inetdev_init(dev); |
20e61da7f ipv4: fail early ... |
1445 1446 |
if (IS_ERR(in_dev)) return notifier_from_errno(PTR_ERR(in_dev)); |
0cc217e16 [IPV4]: When poss... |
1447 |
if (dev->flags & IFF_LOOPBACK) { |
42f811b8b [IPV4]: Convert I... |
1448 1449 |
IN_DEV_CONF_SET(in_dev, NOXFRM, 1); IN_DEV_CONF_SET(in_dev, NOPOLICY, 1); |
8030f5449 [IPV4] devinet: R... |
1450 |
} |
06770843c ipv: Re-enable IP... |
1451 1452 1453 1454 |
} else if (event == NETDEV_CHANGEMTU) { /* Re-enabling IP */ if (inetdev_valid_mtu(dev->mtu)) in_dev = inetdev_init(dev); |
1da177e4c Linux-2.6.12-rc2 |
1455 1456 1457 1458 1459 1460 |
} goto out; } switch (event) { case NETDEV_REGISTER: |
91df42bed net: ipv4 and ipv... |
1461 1462 |
pr_debug("%s: bug ", __func__); |
a9b3cd7f3 rcu: convert uses... |
1463 |
RCU_INIT_POINTER(dev->ip_ptr, NULL); |
1da177e4c Linux-2.6.12-rc2 |
1464 1465 |
break; case NETDEV_UP: |
06770843c ipv: Re-enable IP... |
1466 |
if (!inetdev_valid_mtu(dev->mtu)) |
1da177e4c Linux-2.6.12-rc2 |
1467 |
break; |
0cc217e16 [IPV4]: When poss... |
1468 |
if (dev->flags & IFF_LOOPBACK) { |
9f9354b92 net: net/ipv4/dev... |
1469 1470 1471 |
struct in_ifaddr *ifa = inet_alloc_ifa(); if (ifa) { |
fd23c3b31 ipv4: Add hash ta... |
1472 |
INIT_HLIST_NODE(&ifa->hash); |
1da177e4c Linux-2.6.12-rc2 |
1473 1474 1475 1476 1477 1478 1479 1480 |
ifa->ifa_local = ifa->ifa_address = htonl(INADDR_LOOPBACK); ifa->ifa_prefixlen = 8; ifa->ifa_mask = inet_make_mask(8); in_dev_hold(in_dev); ifa->ifa_dev = in_dev; ifa->ifa_scope = RT_SCOPE_HOST; memcpy(ifa->ifa_label, dev->name, IFNAMSIZ); |
5c766d642 ipv4: introduce a... |
1481 1482 |
set_ifa_lifetime(ifa, INFINITY_LIFE_TIME, INFINITY_LIFE_TIME); |
dfd1582d1 ipv4: loopback de... |
1483 1484 |
ipv4_devconf_setall(in_dev); neigh_parms_data_state_setall(in_dev->arp_parms); |
1da177e4c Linux-2.6.12-rc2 |
1485 1486 1487 1488 |
inet_insert_ifa(ifa); } } ip_mc_up(in_dev); |
a8eceea84 inet: Use fallthr... |
1489 |
fallthrough; |
eefef1cf7 net: add ARP noti... |
1490 |
case NETDEV_CHANGEADDR: |
d11327ad6 arp_notify: uncon... |
1491 1492 |
if (!IN_DEV_ARP_NOTIFY(in_dev)) break; |
a8eceea84 inet: Use fallthr... |
1493 |
fallthrough; |
d11327ad6 arp_notify: uncon... |
1494 |
case NETDEV_NOTIFY_PEERS: |
a21090cff ipv4: arp_notify ... |
1495 |
/* Send gratuitous ARP to notify of link change */ |
d11327ad6 arp_notify: uncon... |
1496 |
inetdev_send_gratuitous_arp(dev, in_dev); |
1da177e4c Linux-2.6.12-rc2 |
1497 1498 1499 1500 |
break; case NETDEV_DOWN: ip_mc_down(in_dev); break; |
93d9b7d7a net: rename notif... |
1501 |
case NETDEV_PRE_TYPE_CHANGE: |
75c78500d bonding: remap mu... |
1502 1503 |
ip_mc_unmap(in_dev); break; |
93d9b7d7a net: rename notif... |
1504 |
case NETDEV_POST_TYPE_CHANGE: |
75c78500d bonding: remap mu... |
1505 1506 |
ip_mc_remap(in_dev); break; |
1da177e4c Linux-2.6.12-rc2 |
1507 |
case NETDEV_CHANGEMTU: |
06770843c ipv: Re-enable IP... |
1508 |
if (inetdev_valid_mtu(dev->mtu)) |
1da177e4c Linux-2.6.12-rc2 |
1509 |
break; |
06770843c ipv: Re-enable IP... |
1510 |
/* disable IP when MTU is not enough */ |
a8eceea84 inet: Use fallthr... |
1511 |
fallthrough; |
1da177e4c Linux-2.6.12-rc2 |
1512 1513 1514 1515 1516 1517 1518 1519 |
case NETDEV_UNREGISTER: inetdev_destroy(in_dev); break; case NETDEV_CHANGENAME: /* Do not notify about label change, this event is * not interesting to applications using netlink. */ inetdev_changename(dev, in_dev); |
51602b2a5 [IPV4]: Cleanup s... |
1520 |
devinet_sysctl_unregister(in_dev); |
66f27a520 [IPV4]: Unify and... |
1521 |
devinet_sysctl_register(in_dev); |
1da177e4c Linux-2.6.12-rc2 |
1522 1523 1524 1525 1526 1527 1528 |
break; } out: return NOTIFY_DONE; } static struct notifier_block ip_netdev_notifier = { |
539afedfc net: clean up net... |
1529 |
.notifier_call = inetdev_event, |
1da177e4c Linux-2.6.12-rc2 |
1530 |
}; |
40384999d ipv4: change inet... |
1531 |
static size_t inet_nlmsg_size(void) |
339bf98ff [NETLINK]: Do pre... |
1532 1533 1534 1535 1536 |
{ return NLMSG_ALIGN(sizeof(struct ifaddrmsg)) + nla_total_size(4) /* IFA_ADDRESS */ + nla_total_size(4) /* IFA_LOCAL */ + nla_total_size(4) /* IFA_BROADCAST */ |
ad6c81359 ipv4: add support... |
1537 |
+ nla_total_size(IFNAMSIZ) /* IFA_LABEL */ |
63b5f152e ipv4: Fix runtime... |
1538 |
+ nla_total_size(4) /* IFA_FLAGS */ |
af4d768ad net/ipv4: Add sup... |
1539 |
+ nla_total_size(4) /* IFA_RT_PRIORITY */ |
63b5f152e ipv4: Fix runtime... |
1540 |
+ nla_total_size(sizeof(struct ifa_cacheinfo)); /* IFA_CACHEINFO */ |
339bf98ff [NETLINK]: Do pre... |
1541 |
} |
5c766d642 ipv4: introduce a... |
1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 |
static inline u32 cstamp_delta(unsigned long cstamp) { return (cstamp - INITIAL_JIFFIES) * 100UL / HZ; } static int put_cacheinfo(struct sk_buff *skb, unsigned long cstamp, unsigned long tstamp, u32 preferred, u32 valid) { struct ifa_cacheinfo ci; ci.cstamp = cstamp_delta(cstamp); ci.tstamp = cstamp_delta(tstamp); ci.ifa_prefered = preferred; ci.ifa_valid = valid; return nla_put(skb, IFA_CACHEINFO, sizeof(ci), &ci); } |
1da177e4c Linux-2.6.12-rc2 |
1559 |
static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa, |
978a46fa6 ipv4: add inet_fi... |
1560 |
struct inet_fill_args *args) |
1da177e4c Linux-2.6.12-rc2 |
1561 1562 1563 |
{ struct ifaddrmsg *ifm; struct nlmsghdr *nlh; |
5c766d642 ipv4: introduce a... |
1564 |
u32 preferred, valid; |
1da177e4c Linux-2.6.12-rc2 |
1565 |
|
978a46fa6 ipv4: add inet_fi... |
1566 1567 |
nlh = nlmsg_put(skb, args->portid, args->seq, args->event, sizeof(*ifm), args->flags); |
51456b291 ipv4: coding styl... |
1568 |
if (!nlh) |
26932566a [NETLINK]: Don't ... |
1569 |
return -EMSGSIZE; |
47f68512d [IPV4]: Convert a... |
1570 1571 |
ifm = nlmsg_data(nlh); |
1da177e4c Linux-2.6.12-rc2 |
1572 1573 |
ifm->ifa_family = AF_INET; ifm->ifa_prefixlen = ifa->ifa_prefixlen; |
5c766d642 ipv4: introduce a... |
1574 |
ifm->ifa_flags = ifa->ifa_flags; |
1da177e4c Linux-2.6.12-rc2 |
1575 1576 |
ifm->ifa_scope = ifa->ifa_scope; ifm->ifa_index = ifa->ifa_dev->dev->ifindex; |
47f68512d [IPV4]: Convert a... |
1577 |
|
978a46fa6 ipv4: add inet_fi... |
1578 1579 |
if (args->netnsid >= 0 && nla_put_s32(skb, IFA_TARGET_NETNSID, args->netnsid)) |
d38071455 ipv4: enable IFA_... |
1580 |
goto nla_put_failure; |
5c766d642 ipv4: introduce a... |
1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 |
if (!(ifm->ifa_flags & IFA_F_PERMANENT)) { preferred = ifa->ifa_preferred_lft; valid = ifa->ifa_valid_lft; if (preferred != INFINITY_LIFE_TIME) { long tval = (jiffies - ifa->ifa_tstamp) / HZ; if (preferred > tval) preferred -= tval; else preferred = 0; if (valid != INFINITY_LIFE_TIME) { if (valid > tval) valid -= tval; else valid = 0; } } } else { preferred = INFINITY_LIFE_TIME; valid = INFINITY_LIFE_TIME; } |
f3756b79e ipv4: Stop using ... |
1602 |
if ((ifa->ifa_address && |
930345ea6 netlink: implemen... |
1603 |
nla_put_in_addr(skb, IFA_ADDRESS, ifa->ifa_address)) || |
f3756b79e ipv4: Stop using ... |
1604 |
(ifa->ifa_local && |
930345ea6 netlink: implemen... |
1605 |
nla_put_in_addr(skb, IFA_LOCAL, ifa->ifa_local)) || |
f3756b79e ipv4: Stop using ... |
1606 |
(ifa->ifa_broadcast && |
930345ea6 netlink: implemen... |
1607 |
nla_put_in_addr(skb, IFA_BROADCAST, ifa->ifa_broadcast)) || |
f3756b79e ipv4: Stop using ... |
1608 |
(ifa->ifa_label[0] && |
5c766d642 ipv4: introduce a... |
1609 |
nla_put_string(skb, IFA_LABEL, ifa->ifa_label)) || |
ad6c81359 ipv4: add support... |
1610 |
nla_put_u32(skb, IFA_FLAGS, ifa->ifa_flags) || |
af4d768ad net/ipv4: Add sup... |
1611 1612 |
(ifa->ifa_rt_priority && nla_put_u32(skb, IFA_RT_PRIORITY, ifa->ifa_rt_priority)) || |
5c766d642 ipv4: introduce a... |
1613 1614 |
put_cacheinfo(skb, ifa->ifa_cstamp, ifa->ifa_tstamp, preferred, valid)) |
f3756b79e ipv4: Stop using ... |
1615 |
goto nla_put_failure; |
1da177e4c Linux-2.6.12-rc2 |
1616 |
|
053c095a8 netlink: make nlm... |
1617 1618 |
nlmsg_end(skb, nlh); return 0; |
47f68512d [IPV4]: Convert a... |
1619 1620 |
nla_put_failure: |
26932566a [NETLINK]: Don't ... |
1621 1622 |
nlmsg_cancel(skb, nlh); return -EMSGSIZE; |
1da177e4c Linux-2.6.12-rc2 |
1623 |
} |
c33078e3d net/ipv4: Update ... |
1624 1625 1626 |
static int inet_valid_dump_ifaddr_req(const struct nlmsghdr *nlh, struct inet_fill_args *fillargs, struct net **tgt_net, struct sock *sk, |
5fcd266a9 net/ipv4: Add sup... |
1627 |
struct netlink_callback *cb) |
c33078e3d net/ipv4: Update ... |
1628 |
{ |
5fcd266a9 net/ipv4: Add sup... |
1629 |
struct netlink_ext_ack *extack = cb->extack; |
c33078e3d net/ipv4: Update ... |
1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 |
struct nlattr *tb[IFA_MAX+1]; struct ifaddrmsg *ifm; int err, i; if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ifm))) { NL_SET_ERR_MSG(extack, "ipv4: Invalid header for address dump request"); return -EINVAL; } ifm = nlmsg_data(nlh); if (ifm->ifa_prefixlen || ifm->ifa_flags || ifm->ifa_scope) { NL_SET_ERR_MSG(extack, "ipv4: Invalid values in header for address dump request"); return -EINVAL; } |
5fcd266a9 net/ipv4: Add sup... |
1644 1645 1646 1647 1648 |
fillargs->ifindex = ifm->ifa_index; if (fillargs->ifindex) { cb->answer_flags |= NLM_F_DUMP_FILTERED; fillargs->flags |= NLM_F_DUMP_FILTERED; |
c33078e3d net/ipv4: Update ... |
1649 |
} |
8cb081746 netlink: make val... |
1650 1651 |
err = nlmsg_parse_deprecated_strict(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv4_policy, extack); |
c33078e3d net/ipv4: Update ... |
1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 |
if (err < 0) return err; for (i = 0; i <= IFA_MAX; ++i) { if (!tb[i]) continue; if (i == IFA_TARGET_NETNSID) { struct net *net; fillargs->netnsid = nla_get_s32(tb[i]); net = rtnl_get_net_ns_capable(sk, fillargs->netnsid); if (IS_ERR(net)) { |
bf4cc40e9 net/{ipv4,ipv6}: ... |
1666 |
fillargs->netnsid = -1; |
c33078e3d net/ipv4: Update ... |
1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 |
NL_SET_ERR_MSG(extack, "ipv4: Invalid target network namespace id"); return PTR_ERR(net); } *tgt_net = net; } else { NL_SET_ERR_MSG(extack, "ipv4: Unsupported attribute in dump request"); return -EINVAL; } } return 0; } |
1c98eca41 net/ipv4: Move lo... |
1679 1680 1681 1682 1683 1684 1685 |
static int in_dev_dump_addr(struct in_device *in_dev, struct sk_buff *skb, struct netlink_callback *cb, int s_ip_idx, struct inet_fill_args *fillargs) { struct in_ifaddr *ifa; int ip_idx = 0; int err; |
d3e6e285f net: ipv4: fix rc... |
1686 |
in_dev_for_each_ifa_rtnl(ifa, in_dev) { |
ef11db331 net: inetdevice: ... |
1687 1688 |
if (ip_idx < s_ip_idx) { ip_idx++; |
1c98eca41 net/ipv4: Move lo... |
1689 |
continue; |
ef11db331 net: inetdevice: ... |
1690 |
} |
1c98eca41 net/ipv4: Move lo... |
1691 1692 1693 1694 1695 |
err = inet_fill_ifaddr(skb, ifa, fillargs); if (err < 0) goto done; nl_dump_check_consistent(cb, nlmsg_hdr(skb)); |
ef11db331 net: inetdevice: ... |
1696 |
ip_idx++; |
1c98eca41 net/ipv4: Move lo... |
1697 1698 1699 1700 1701 1702 1703 1704 |
} err = 0; done: cb->args[2] = ip_idx; return err; } |
1da177e4c Linux-2.6.12-rc2 |
1705 1706 |
static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) { |
c33078e3d net/ipv4: Update ... |
1707 |
const struct nlmsghdr *nlh = cb->nlh; |
978a46fa6 ipv4: add inet_fi... |
1708 1709 |
struct inet_fill_args fillargs = { .portid = NETLINK_CB(cb->skb).portid, |
c33078e3d net/ipv4: Update ... |
1710 |
.seq = nlh->nlmsg_seq, |
978a46fa6 ipv4: add inet_fi... |
1711 1712 1713 1714 |
.event = RTM_NEWADDR, .flags = NLM_F_MULTI, .netnsid = -1, }; |
3b1e0a655 [NET] NETNS: Omit... |
1715 |
struct net *net = sock_net(skb->sk); |
d38071455 ipv4: enable IFA_... |
1716 |
struct net *tgt_net = net; |
eec4df988 ipv4: speedup ine... |
1717 1718 |
int h, s_h; int idx, s_idx; |
1c98eca41 net/ipv4: Move lo... |
1719 |
int s_ip_idx; |
1da177e4c Linux-2.6.12-rc2 |
1720 1721 |
struct net_device *dev; struct in_device *in_dev; |
eec4df988 ipv4: speedup ine... |
1722 |
struct hlist_head *head; |
d7e38611b net/ipv4: Put tar... |
1723 |
int err = 0; |
1da177e4c Linux-2.6.12-rc2 |
1724 |
|
eec4df988 ipv4: speedup ine... |
1725 1726 |
s_h = cb->args[0]; s_idx = idx = cb->args[1]; |
1c98eca41 net/ipv4: Move lo... |
1727 |
s_ip_idx = cb->args[2]; |
eec4df988 ipv4: speedup ine... |
1728 |
|
c33078e3d net/ipv4: Update ... |
1729 |
if (cb->strict_check) { |
c33078e3d net/ipv4: Update ... |
1730 |
err = inet_valid_dump_ifaddr_req(nlh, &fillargs, &tgt_net, |
5fcd266a9 net/ipv4: Add sup... |
1731 |
skb->sk, cb); |
c33078e3d net/ipv4: Update ... |
1732 |
if (err < 0) |
d7e38611b net/ipv4: Put tar... |
1733 |
goto put_tgt_net; |
5fcd266a9 net/ipv4: Add sup... |
1734 |
|
d7e38611b net/ipv4: Put tar... |
1735 |
err = 0; |
5fcd266a9 net/ipv4: Add sup... |
1736 1737 |
if (fillargs.ifindex) { dev = __dev_get_by_index(tgt_net, fillargs.ifindex); |
d7e38611b net/ipv4: Put tar... |
1738 1739 1740 1741 |
if (!dev) { err = -ENODEV; goto put_tgt_net; } |
5fcd266a9 net/ipv4: Add sup... |
1742 1743 1744 1745 1746 1747 1748 1749 |
in_dev = __in_dev_get_rtnl(dev); if (in_dev) { err = in_dev_dump_addr(in_dev, skb, cb, s_ip_idx, &fillargs); } goto put_tgt_net; } |
d38071455 ipv4: enable IFA_... |
1750 |
} |
eec4df988 ipv4: speedup ine... |
1751 1752 |
for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { idx = 0; |
d38071455 ipv4: enable IFA_... |
1753 |
head = &tgt_net->dev_index_head[h]; |
eec4df988 ipv4: speedup ine... |
1754 |
rcu_read_lock(); |
d38071455 ipv4: enable IFA_... |
1755 1756 |
cb->seq = atomic_read(&tgt_net->ipv4.dev_addr_genid) ^ tgt_net->dev_base_seq; |
b67bfe0d4 hlist: drop the n... |
1757 |
hlist_for_each_entry_rcu(dev, head, index_hlist) { |
eec4df988 ipv4: speedup ine... |
1758 1759 |
if (idx < s_idx) goto cont; |
4b97efdf3 net: fix netlink ... |
1760 |
if (h > s_h || idx > s_idx) |
eec4df988 ipv4: speedup ine... |
1761 1762 1763 1764 |
s_ip_idx = 0; in_dev = __in_dev_get_rcu(dev); if (!in_dev) goto cont; |
1da177e4c Linux-2.6.12-rc2 |
1765 |
|
1c98eca41 net/ipv4: Move lo... |
1766 1767 1768 1769 1770 |
err = in_dev_dump_addr(in_dev, skb, cb, s_ip_idx, &fillargs); if (err < 0) { rcu_read_unlock(); goto done; |
eec4df988 ipv4: speedup ine... |
1771 |
} |
7562f876c [NET]: Rework dev... |
1772 |
cont: |
eec4df988 ipv4: speedup ine... |
1773 1774 1775 |
idx++; } rcu_read_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
1776 1777 1778 |
} done: |
eec4df988 ipv4: speedup ine... |
1779 1780 |
cb->args[0] = h; cb->args[1] = idx; |
5fcd266a9 net/ipv4: Add sup... |
1781 |
put_tgt_net: |
978a46fa6 ipv4: add inet_fi... |
1782 |
if (fillargs.netnsid >= 0) |
d38071455 ipv4: enable IFA_... |
1783 |
put_net(tgt_net); |
1da177e4c Linux-2.6.12-rc2 |
1784 |
|
7c1e8a381 netlink: fixup re... |
1785 |
return skb->len ? : err; |
1da177e4c Linux-2.6.12-rc2 |
1786 |
} |
539afedfc net: clean up net... |
1787 |
static void rtmsg_ifa(int event, struct in_ifaddr *ifa, struct nlmsghdr *nlh, |
15e473046 netlink: Rename p... |
1788 |
u32 portid) |
1da177e4c Linux-2.6.12-rc2 |
1789 |
{ |
978a46fa6 ipv4: add inet_fi... |
1790 1791 1792 1793 1794 1795 1796 |
struct inet_fill_args fillargs = { .portid = portid, .seq = nlh ? nlh->nlmsg_seq : 0, .event = event, .flags = 0, .netnsid = -1, }; |
47f68512d [IPV4]: Convert a... |
1797 |
struct sk_buff *skb; |
d6062cbbd [IPv4] address: C... |
1798 |
int err = -ENOBUFS; |
4b8aa9abe [NETNS]: Process ... |
1799 |
struct net *net; |
1da177e4c Linux-2.6.12-rc2 |
1800 |
|
c346dca10 [NET] NETNS: Omit... |
1801 |
net = dev_net(ifa->ifa_dev->dev); |
339bf98ff [NETLINK]: Do pre... |
1802 |
skb = nlmsg_new(inet_nlmsg_size(), GFP_KERNEL); |
51456b291 ipv4: coding styl... |
1803 |
if (!skb) |
d6062cbbd [IPv4] address: C... |
1804 |
goto errout; |
978a46fa6 ipv4: add inet_fi... |
1805 |
err = inet_fill_ifaddr(skb, ifa, &fillargs); |
26932566a [NETLINK]: Don't ... |
1806 1807 1808 1809 1810 1811 |
if (err < 0) { /* -EMSGSIZE implies BUG in inet_nlmsg_size() */ WARN_ON(err == -EMSGSIZE); kfree_skb(skb); goto errout; } |
15e473046 netlink: Rename p... |
1812 |
rtnl_notify(skb, net, portid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL); |
1ce85fe40 netlink: change n... |
1813 |
return; |
d6062cbbd [IPv4] address: C... |
1814 1815 |
errout: if (err < 0) |
4b8aa9abe [NETNS]: Process ... |
1816 |
rtnl_set_sk_err(net, RTNLGRP_IPV4_IFADDR, err); |
1da177e4c Linux-2.6.12-rc2 |
1817 |
} |
b1974ed05 netlink: Rightsiz... |
1818 1819 |
static size_t inet_get_link_af_size(const struct net_device *dev, u32 ext_filter_mask) |
9f0f7272a ipv4: AF_INET lin... |
1820 |
{ |
1fc19aff8 net: fix two lock... |
1821 |
struct in_device *in_dev = rcu_dereference_rtnl(dev->ip_ptr); |
9f0f7272a ipv4: AF_INET lin... |
1822 1823 1824 1825 1826 1827 |
if (!in_dev) return 0; return nla_total_size(IPV4_DEVCONF_MAX * 4); /* IFLA_INET_CONF */ } |
d5566fd72 rtnetlink: RTEXT_... |
1828 1829 |
static int inet_fill_link_af(struct sk_buff *skb, const struct net_device *dev, u32 ext_filter_mask) |
9f0f7272a ipv4: AF_INET lin... |
1830 |
{ |
1fc19aff8 net: fix two lock... |
1831 |
struct in_device *in_dev = rcu_dereference_rtnl(dev->ip_ptr); |
9f0f7272a ipv4: AF_INET lin... |
1832 1833 1834 1835 1836 1837 1838 |
struct nlattr *nla; int i; if (!in_dev) return -ENODATA; nla = nla_reserve(skb, IFLA_INET_CONF, IPV4_DEVCONF_MAX * 4); |
51456b291 ipv4: coding styl... |
1839 |
if (!nla) |
9f0f7272a ipv4: AF_INET lin... |
1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 |
return -EMSGSIZE; for (i = 0; i < IPV4_DEVCONF_MAX; i++) ((u32 *) nla_data(nla))[i] = in_dev->cnf.data[i]; return 0; } static const struct nla_policy inet_af_policy[IFLA_INET_MAX+1] = { [IFLA_INET_CONF] = { .type = NLA_NESTED }, }; |
cf7afbfeb rtnl: make link a... |
1851 1852 |
static int inet_validate_link_af(const struct net_device *dev, const struct nlattr *nla) |
9f0f7272a ipv4: AF_INET lin... |
1853 |
{ |
9f0f7272a ipv4: AF_INET lin... |
1854 1855 |
struct nlattr *a, *tb[IFLA_INET_MAX+1]; int err, rem; |
5fa85a093 net: core: rcu-if... |
1856 |
if (dev && !__in_dev_get_rcu(dev)) |
cf7afbfeb rtnl: make link a... |
1857 |
return -EAFNOSUPPORT; |
9f0f7272a ipv4: AF_INET lin... |
1858 |
|
8cb081746 netlink: make val... |
1859 1860 |
err = nla_parse_nested_deprecated(tb, IFLA_INET_MAX, nla, inet_af_policy, NULL); |
9f0f7272a ipv4: AF_INET lin... |
1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 |
if (err < 0) return err; if (tb[IFLA_INET_CONF]) { nla_for_each_nested(a, tb[IFLA_INET_CONF], rem) { int cfgid = nla_type(a); if (nla_len(a) < 4) return -EINVAL; if (cfgid <= 0 || cfgid > IPV4_DEVCONF_MAX) return -EINVAL; } } |
cf7afbfeb rtnl: make link a... |
1875 1876 1877 1878 1879 |
return 0; } static int inet_set_link_af(struct net_device *dev, const struct nlattr *nla) { |
5fa85a093 net: core: rcu-if... |
1880 |
struct in_device *in_dev = __in_dev_get_rcu(dev); |
cf7afbfeb rtnl: make link a... |
1881 1882 1883 1884 1885 |
struct nlattr *a, *tb[IFLA_INET_MAX+1]; int rem; if (!in_dev) return -EAFNOSUPPORT; |
8cb081746 netlink: make val... |
1886 |
if (nla_parse_nested_deprecated(tb, IFLA_INET_MAX, nla, NULL, NULL) < 0) |
cf7afbfeb rtnl: make link a... |
1887 |
BUG(); |
9f0f7272a ipv4: AF_INET lin... |
1888 1889 1890 1891 1892 1893 1894 |
if (tb[IFLA_INET_CONF]) { nla_for_each_nested(a, tb[IFLA_INET_CONF], rem) ipv4_devconf_set(in_dev, nla_type(a), nla_get_u32(a)); } return 0; } |
edc9e7489 rtnl/ipv4: use ne... |
1895 1896 1897 1898 |
static int inet_netconf_msgsize_devconf(int type) { int size = NLMSG_ALIGN(sizeof(struct netconfmsg)) + nla_total_size(4); /* NETCONFA_IFINDEX */ |
136ba622d netconf: add macr... |
1899 |
bool all = false; |
edc9e7489 rtnl/ipv4: use ne... |
1900 |
|
136ba622d netconf: add macr... |
1901 1902 1903 1904 |
if (type == NETCONFA_ALL) all = true; if (all || type == NETCONFA_FORWARDING) |
edc9e7489 rtnl/ipv4: use ne... |
1905 |
size += nla_total_size(4); |
136ba622d netconf: add macr... |
1906 |
if (all || type == NETCONFA_RP_FILTER) |
cc535dfb6 rtnl/ipv4: use ne... |
1907 |
size += nla_total_size(4); |
136ba622d netconf: add macr... |
1908 |
if (all || type == NETCONFA_MC_FORWARDING) |
d67b8c616 netconf: advertis... |
1909 |
size += nla_total_size(4); |
5cbf777cf route: add suppor... |
1910 1911 |
if (all || type == NETCONFA_BC_FORWARDING) size += nla_total_size(4); |
136ba622d netconf: add macr... |
1912 |
if (all || type == NETCONFA_PROXY_NEIGH) |
f085ff1c1 netconf: add prox... |
1913 |
size += nla_total_size(4); |
136ba622d netconf: add macr... |
1914 |
if (all || type == NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN) |
974d7af5f ipv4: add support... |
1915 |
size += nla_total_size(4); |
edc9e7489 rtnl/ipv4: use ne... |
1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 |
return size; } static int inet_netconf_fill_devconf(struct sk_buff *skb, int ifindex, struct ipv4_devconf *devconf, u32 portid, u32 seq, int event, unsigned int flags, int type) { struct nlmsghdr *nlh; struct netconfmsg *ncm; |
136ba622d netconf: add macr... |
1927 |
bool all = false; |
edc9e7489 rtnl/ipv4: use ne... |
1928 1929 1930 |
nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct netconfmsg), flags); |
51456b291 ipv4: coding styl... |
1931 |
if (!nlh) |
edc9e7489 rtnl/ipv4: use ne... |
1932 |
return -EMSGSIZE; |
136ba622d netconf: add macr... |
1933 1934 |
if (type == NETCONFA_ALL) all = true; |
edc9e7489 rtnl/ipv4: use ne... |
1935 1936 1937 1938 1939 |
ncm = nlmsg_data(nlh); ncm->ncm_family = AF_INET; if (nla_put_s32(skb, NETCONFA_IFINDEX, ifindex) < 0) goto nla_put_failure; |
b5c9641d3 net: devinet: Add... |
1940 1941 |
if (!devconf) goto out; |
136ba622d netconf: add macr... |
1942 |
if ((all || type == NETCONFA_FORWARDING) && |
edc9e7489 rtnl/ipv4: use ne... |
1943 1944 1945 |
nla_put_s32(skb, NETCONFA_FORWARDING, IPV4_DEVCONF(*devconf, FORWARDING)) < 0) goto nla_put_failure; |
136ba622d netconf: add macr... |
1946 |
if ((all || type == NETCONFA_RP_FILTER) && |
cc535dfb6 rtnl/ipv4: use ne... |
1947 1948 1949 |
nla_put_s32(skb, NETCONFA_RP_FILTER, IPV4_DEVCONF(*devconf, RP_FILTER)) < 0) goto nla_put_failure; |
136ba622d netconf: add macr... |
1950 |
if ((all || type == NETCONFA_MC_FORWARDING) && |
d67b8c616 netconf: advertis... |
1951 1952 1953 |
nla_put_s32(skb, NETCONFA_MC_FORWARDING, IPV4_DEVCONF(*devconf, MC_FORWARDING)) < 0) goto nla_put_failure; |
5cbf777cf route: add suppor... |
1954 1955 1956 1957 |
if ((all || type == NETCONFA_BC_FORWARDING) && nla_put_s32(skb, NETCONFA_BC_FORWARDING, IPV4_DEVCONF(*devconf, BC_FORWARDING)) < 0) goto nla_put_failure; |
136ba622d netconf: add macr... |
1958 |
if ((all || type == NETCONFA_PROXY_NEIGH) && |
09aea5df7 netconf: rename P... |
1959 |
nla_put_s32(skb, NETCONFA_PROXY_NEIGH, |
f085ff1c1 netconf: add prox... |
1960 1961 |
IPV4_DEVCONF(*devconf, PROXY_ARP)) < 0) goto nla_put_failure; |
136ba622d netconf: add macr... |
1962 |
if ((all || type == NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN) && |
974d7af5f ipv4: add support... |
1963 1964 1965 |
nla_put_s32(skb, NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN, IPV4_DEVCONF(*devconf, IGNORE_ROUTES_WITH_LINKDOWN)) < 0) goto nla_put_failure; |
edc9e7489 rtnl/ipv4: use ne... |
1966 |
|
b5c9641d3 net: devinet: Add... |
1967 |
out: |
053c095a8 netlink: make nlm... |
1968 1969 |
nlmsg_end(skb, nlh); return 0; |
edc9e7489 rtnl/ipv4: use ne... |
1970 1971 1972 1973 1974 |
nla_put_failure: nlmsg_cancel(skb, nlh); return -EMSGSIZE; } |
3b0228656 net: devinet: Ref... |
1975 1976 |
void inet_netconf_notify_devconf(struct net *net, int event, int type, int ifindex, struct ipv4_devconf *devconf) |
edc9e7489 rtnl/ipv4: use ne... |
1977 1978 1979 |
{ struct sk_buff *skb; int err = -ENOBUFS; |
fa17806cd ipv4: do not abus... |
1980 |
skb = nlmsg_new(inet_netconf_msgsize_devconf(type), GFP_KERNEL); |
51456b291 ipv4: coding styl... |
1981 |
if (!skb) |
edc9e7489 rtnl/ipv4: use ne... |
1982 1983 1984 |
goto errout; err = inet_netconf_fill_devconf(skb, ifindex, devconf, 0, 0, |
3b0228656 net: devinet: Ref... |
1985 |
event, 0, type); |
edc9e7489 rtnl/ipv4: use ne... |
1986 1987 1988 1989 1990 1991 |
if (err < 0) { /* -EMSGSIZE implies BUG in inet_netconf_msgsize_devconf() */ WARN_ON(err == -EMSGSIZE); kfree_skb(skb); goto errout; } |
fa17806cd ipv4: do not abus... |
1992 |
rtnl_notify(skb, net, 0, RTNLGRP_IPV4_NETCONF, NULL, GFP_KERNEL); |
edc9e7489 rtnl/ipv4: use ne... |
1993 1994 1995 1996 1997 |
return; errout: if (err < 0) rtnl_set_sk_err(net, RTNLGRP_IPV4_NETCONF, err); } |
9e5511106 rtnl/ipv4: add su... |
1998 1999 2000 |
static const struct nla_policy devconf_ipv4_policy[NETCONFA_MAX+1] = { [NETCONFA_IFINDEX] = { .len = sizeof(int) }, [NETCONFA_FORWARDING] = { .len = sizeof(int) }, |
cc535dfb6 rtnl/ipv4: use ne... |
2001 |
[NETCONFA_RP_FILTER] = { .len = sizeof(int) }, |
09aea5df7 netconf: rename P... |
2002 |
[NETCONFA_PROXY_NEIGH] = { .len = sizeof(int) }, |
974d7af5f ipv4: add support... |
2003 |
[NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN] = { .len = sizeof(int) }, |
9e5511106 rtnl/ipv4: add su... |
2004 |
}; |
eede370d6 net: ipv4: netcon... |
2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 |
static int inet_netconf_valid_get_req(struct sk_buff *skb, const struct nlmsghdr *nlh, struct nlattr **tb, struct netlink_ext_ack *extack) { int i, err; if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(struct netconfmsg))) { NL_SET_ERR_MSG(extack, "ipv4: Invalid header for netconf get request"); return -EINVAL; } if (!netlink_strict_get_check(skb)) |
8cb081746 netlink: make val... |
2018 2019 2020 |
return nlmsg_parse_deprecated(nlh, sizeof(struct netconfmsg), tb, NETCONFA_MAX, devconf_ipv4_policy, extack); |
eede370d6 net: ipv4: netcon... |
2021 |
|
8cb081746 netlink: make val... |
2022 2023 2024 |
err = nlmsg_parse_deprecated_strict(nlh, sizeof(struct netconfmsg), tb, NETCONFA_MAX, devconf_ipv4_policy, extack); |
eede370d6 net: ipv4: netcon... |
2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 |
if (err) return err; for (i = 0; i <= NETCONFA_MAX; i++) { if (!tb[i]) continue; switch (i) { case NETCONFA_IFINDEX: break; default: NL_SET_ERR_MSG(extack, "ipv4: Unsupported attribute in netconf get request"); return -EINVAL; } } return 0; } |
9e5511106 rtnl/ipv4: add su... |
2043 |
static int inet_netconf_get_devconf(struct sk_buff *in_skb, |
c21ef3e34 net: rtnetlink: p... |
2044 2045 |
struct nlmsghdr *nlh, struct netlink_ext_ack *extack) |
9e5511106 rtnl/ipv4: add su... |
2046 2047 2048 |
{ struct net *net = sock_net(in_skb->sk); struct nlattr *tb[NETCONFA_MAX+1]; |
9e5511106 rtnl/ipv4: add su... |
2049 2050 2051 2052 2053 2054 |
struct sk_buff *skb; struct ipv4_devconf *devconf; struct in_device *in_dev; struct net_device *dev; int ifindex; int err; |
eede370d6 net: ipv4: netcon... |
2055 2056 |
err = inet_netconf_valid_get_req(in_skb, nlh, tb, extack); if (err) |
9e5511106 rtnl/ipv4: add su... |
2057 |
goto errout; |
a97eb33ff rtnl: RTM_GETNETC... |
2058 |
err = -EINVAL; |
9e5511106 rtnl/ipv4: add su... |
2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 |
if (!tb[NETCONFA_IFINDEX]) goto errout; ifindex = nla_get_s32(tb[NETCONFA_IFINDEX]); switch (ifindex) { case NETCONFA_IFINDEX_ALL: devconf = net->ipv4.devconf_all; break; case NETCONFA_IFINDEX_DEFAULT: devconf = net->ipv4.devconf_dflt; break; default: dev = __dev_get_by_index(net, ifindex); |
51456b291 ipv4: coding styl... |
2072 |
if (!dev) |
9e5511106 rtnl/ipv4: add su... |
2073 2074 |
goto errout; in_dev = __in_dev_get_rtnl(dev); |
51456b291 ipv4: coding styl... |
2075 |
if (!in_dev) |
9e5511106 rtnl/ipv4: add su... |
2076 2077 2078 2079 2080 2081 |
goto errout; devconf = &in_dev->cnf; break; } err = -ENOBUFS; |
fa17806cd ipv4: do not abus... |
2082 |
skb = nlmsg_new(inet_netconf_msgsize_devconf(NETCONFA_ALL), GFP_KERNEL); |
51456b291 ipv4: coding styl... |
2083 |
if (!skb) |
9e5511106 rtnl/ipv4: add su... |
2084 2085 2086 2087 2088 |
goto errout; err = inet_netconf_fill_devconf(skb, ifindex, devconf, NETLINK_CB(in_skb).portid, nlh->nlmsg_seq, RTM_NEWNETCONF, 0, |
136ba622d netconf: add macr... |
2089 |
NETCONFA_ALL); |
9e5511106 rtnl/ipv4: add su... |
2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 |
if (err < 0) { /* -EMSGSIZE implies BUG in inet_netconf_msgsize_devconf() */ WARN_ON(err == -EMSGSIZE); kfree_skb(skb); goto errout; } err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid); errout: return err; } |
7a6742003 netconf: add the ... |
2100 2101 2102 |
static int inet_netconf_dump_devconf(struct sk_buff *skb, struct netlink_callback *cb) { |
addd383f5 net: Update netco... |
2103 |
const struct nlmsghdr *nlh = cb->nlh; |
7a6742003 netconf: add the ... |
2104 2105 2106 2107 2108 2109 |
struct net *net = sock_net(skb->sk); int h, s_h; int idx, s_idx; struct net_device *dev; struct in_device *in_dev; struct hlist_head *head; |
addd383f5 net: Update netco... |
2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 |
if (cb->strict_check) { struct netlink_ext_ack *extack = cb->extack; struct netconfmsg *ncm; if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ncm))) { NL_SET_ERR_MSG(extack, "ipv4: Invalid header for netconf dump request"); return -EINVAL; } if (nlmsg_attrlen(nlh, sizeof(*ncm))) { NL_SET_ERR_MSG(extack, "ipv4: Invalid data after header in netconf dump request"); return -EINVAL; } } |
7a6742003 netconf: add the ... |
2124 2125 2126 2127 2128 2129 2130 |
s_h = cb->args[0]; s_idx = idx = cb->args[1]; for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { idx = 0; head = &net->dev_index_head[h]; rcu_read_lock(); |
0465277f6 ipv4: provide add... |
2131 2132 |
cb->seq = atomic_read(&net->ipv4.dev_addr_genid) ^ net->dev_base_seq; |
7a6742003 netconf: add the ... |
2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 |
hlist_for_each_entry_rcu(dev, head, index_hlist) { if (idx < s_idx) goto cont; in_dev = __in_dev_get_rcu(dev); if (!in_dev) goto cont; if (inet_netconf_fill_devconf(skb, dev->ifindex, &in_dev->cnf, NETLINK_CB(cb->skb).portid, |
addd383f5 net: Update netco... |
2143 |
nlh->nlmsg_seq, |
7a6742003 netconf: add the ... |
2144 2145 |
RTM_NEWNETCONF, NLM_F_MULTI, |
136ba622d netconf: add macr... |
2146 |
NETCONFA_ALL) < 0) { |
7a6742003 netconf: add the ... |
2147 2148 2149 |
rcu_read_unlock(); goto done; } |
0465277f6 ipv4: provide add... |
2150 |
nl_dump_check_consistent(cb, nlmsg_hdr(skb)); |
7a6742003 netconf: add the ... |
2151 2152 2153 2154 2155 2156 2157 2158 2159 |
cont: idx++; } rcu_read_unlock(); } if (h == NETDEV_HASHENTRIES) { if (inet_netconf_fill_devconf(skb, NETCONFA_IFINDEX_ALL, net->ipv4.devconf_all, NETLINK_CB(cb->skb).portid, |
addd383f5 net: Update netco... |
2160 |
nlh->nlmsg_seq, |
7a6742003 netconf: add the ... |
2161 |
RTM_NEWNETCONF, NLM_F_MULTI, |
136ba622d netconf: add macr... |
2162 |
NETCONFA_ALL) < 0) |
7a6742003 netconf: add the ... |
2163 2164 2165 2166 2167 2168 2169 2170 |
goto done; else h++; } if (h == NETDEV_HASHENTRIES + 1) { if (inet_netconf_fill_devconf(skb, NETCONFA_IFINDEX_DEFAULT, net->ipv4.devconf_dflt, NETLINK_CB(cb->skb).portid, |
addd383f5 net: Update netco... |
2171 |
nlh->nlmsg_seq, |
7a6742003 netconf: add the ... |
2172 |
RTM_NEWNETCONF, NLM_F_MULTI, |
136ba622d netconf: add macr... |
2173 |
NETCONFA_ALL) < 0) |
7a6742003 netconf: add the ... |
2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 |
goto done; else h++; } done: cb->args[0] = h; cb->args[1] = idx; return skb->len; } |
1da177e4c Linux-2.6.12-rc2 |
2184 |
#ifdef CONFIG_SYSCTL |
c0ce9fb30 [IPV4]: Store the... |
2185 |
static void devinet_copy_dflt_conf(struct net *net, int i) |
31be30854 [IPV4]: Add defau... |
2186 2187 |
{ struct net_device *dev; |
c6d14c845 net: Introduce fo... |
2188 2189 |
rcu_read_lock(); for_each_netdev_rcu(net, dev) { |
31be30854 [IPV4]: Add defau... |
2190 |
struct in_device *in_dev; |
c6d14c845 net: Introduce fo... |
2191 |
|
31be30854 [IPV4]: Add defau... |
2192 2193 |
in_dev = __in_dev_get_rcu(dev); if (in_dev && !test_bit(i, in_dev->cnf.state)) |
9355bbd68 [IPV4]: Switch us... |
2194 |
in_dev->cnf.data[i] = net->ipv4.devconf_dflt->data[i]; |
31be30854 [IPV4]: Add defau... |
2195 |
} |
c6d14c845 net: Introduce fo... |
2196 |
rcu_read_unlock(); |
31be30854 [IPV4]: Add defau... |
2197 |
} |
c6d14c845 net: Introduce fo... |
2198 |
/* called with RTNL locked */ |
c0ce9fb30 [IPV4]: Store the... |
2199 |
static void inet_forward_change(struct net *net) |
68dd299bc [INET]: Merge sys... |
2200 2201 |
{ struct net_device *dev; |
586f12115 [IPV4]: Switch us... |
2202 |
int on = IPV4_DEVCONF_ALL(net, FORWARDING); |
68dd299bc [INET]: Merge sys... |
2203 |
|
586f12115 [IPV4]: Switch us... |
2204 |
IPV4_DEVCONF_ALL(net, ACCEPT_REDIRECTS) = !on; |
9355bbd68 [IPV4]: Switch us... |
2205 |
IPV4_DEVCONF_DFLT(net, FORWARDING) = on; |
3b0228656 net: devinet: Ref... |
2206 2207 |
inet_netconf_notify_devconf(net, RTM_NEWNETCONF, NETCONFA_FORWARDING, |
edc9e7489 rtnl/ipv4: use ne... |
2208 2209 |
NETCONFA_IFINDEX_ALL, net->ipv4.devconf_all); |
3b0228656 net: devinet: Ref... |
2210 2211 |
inet_netconf_notify_devconf(net, RTM_NEWNETCONF, NETCONFA_FORWARDING, |
edc9e7489 rtnl/ipv4: use ne... |
2212 2213 |
NETCONFA_IFINDEX_DEFAULT, net->ipv4.devconf_dflt); |
68dd299bc [INET]: Merge sys... |
2214 |
|
c0ce9fb30 [IPV4]: Store the... |
2215 |
for_each_netdev(net, dev) { |
68dd299bc [INET]: Merge sys... |
2216 |
struct in_device *in_dev; |
fa17806cd ipv4: do not abus... |
2217 |
|
0187bdfb0 net: Disable LRO ... |
2218 2219 |
if (on) dev_disable_lro(dev); |
fa17806cd ipv4: do not abus... |
2220 2221 |
in_dev = __in_dev_get_rtnl(dev); |
edc9e7489 rtnl/ipv4: use ne... |
2222 |
if (in_dev) { |
68dd299bc [INET]: Merge sys... |
2223 |
IN_DEV_CONF_SET(in_dev, FORWARDING, on); |
3b0228656 net: devinet: Ref... |
2224 2225 |
inet_netconf_notify_devconf(net, RTM_NEWNETCONF, NETCONFA_FORWARDING, |
edc9e7489 rtnl/ipv4: use ne... |
2226 2227 |
dev->ifindex, &in_dev->cnf); } |
68dd299bc [INET]: Merge sys... |
2228 |
} |
68dd299bc [INET]: Merge sys... |
2229 |
} |
f085ff1c1 netconf: add prox... |
2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 |
static int devinet_conf_ifindex(struct net *net, struct ipv4_devconf *cnf) { if (cnf == net->ipv4.devconf_dflt) return NETCONFA_IFINDEX_DEFAULT; else if (cnf == net->ipv4.devconf_all) return NETCONFA_IFINDEX_ALL; else { struct in_device *idev = container_of(cnf, struct in_device, cnf); return idev->dev->ifindex; } } |
fe2c6338f net: Convert uses... |
2242 |
static int devinet_conf_proc(struct ctl_table *ctl, int write, |
32927393d sysctl: pass kern... |
2243 |
void *buffer, size_t *lenp, loff_t *ppos) |
31be30854 [IPV4]: Add defau... |
2244 |
{ |
d01ff0a04 ipv4: flush route... |
2245 |
int old_value = *(int *)ctl->data; |
8d65af789 sysctl: remove "s... |
2246 |
int ret = proc_dointvec(ctl, write, buffer, lenp, ppos); |
d01ff0a04 ipv4: flush route... |
2247 |
int new_value = *(int *)ctl->data; |
31be30854 [IPV4]: Add defau... |
2248 2249 2250 |
if (write) { struct ipv4_devconf *cnf = ctl->extra1; |
c0ce9fb30 [IPV4]: Store the... |
2251 |
struct net *net = ctl->extra2; |
31be30854 [IPV4]: Add defau... |
2252 |
int i = (int *)ctl->data - cnf->data; |
f085ff1c1 netconf: add prox... |
2253 |
int ifindex; |
31be30854 [IPV4]: Add defau... |
2254 2255 |
set_bit(i, cnf->state); |
9355bbd68 [IPV4]: Switch us... |
2256 |
if (cnf == net->ipv4.devconf_dflt) |
c0ce9fb30 [IPV4]: Store the... |
2257 |
devinet_copy_dflt_conf(net, i); |
d0daebc3d ipv4: Add interfa... |
2258 2259 |
if (i == IPV4_DEVCONF_ACCEPT_LOCAL - 1 || i == IPV4_DEVCONF_ROUTE_LOCALNET - 1) |
d01ff0a04 ipv4: flush route... |
2260 |
if ((new_value == 0) && (old_value != 0)) |
4ccfe6d41 ipv4/route: arg d... |
2261 |
rt_cache_flush(net); |
f085ff1c1 netconf: add prox... |
2262 |
|
5cbf777cf route: add suppor... |
2263 2264 2265 |
if (i == IPV4_DEVCONF_BC_FORWARDING - 1 && new_value != old_value) rt_cache_flush(net); |
cc535dfb6 rtnl/ipv4: use ne... |
2266 2267 |
if (i == IPV4_DEVCONF_RP_FILTER - 1 && new_value != old_value) { |
f085ff1c1 netconf: add prox... |
2268 |
ifindex = devinet_conf_ifindex(net, cnf); |
3b0228656 net: devinet: Ref... |
2269 2270 |
inet_netconf_notify_devconf(net, RTM_NEWNETCONF, NETCONFA_RP_FILTER, |
cc535dfb6 rtnl/ipv4: use ne... |
2271 2272 |
ifindex, cnf); } |
f085ff1c1 netconf: add prox... |
2273 2274 2275 |
if (i == IPV4_DEVCONF_PROXY_ARP - 1 && new_value != old_value) { ifindex = devinet_conf_ifindex(net, cnf); |
3b0228656 net: devinet: Ref... |
2276 2277 |
inet_netconf_notify_devconf(net, RTM_NEWNETCONF, NETCONFA_PROXY_NEIGH, |
f085ff1c1 netconf: add prox... |
2278 2279 |
ifindex, cnf); } |
974d7af5f ipv4: add support... |
2280 2281 2282 |
if (i == IPV4_DEVCONF_IGNORE_ROUTES_WITH_LINKDOWN - 1 && new_value != old_value) { ifindex = devinet_conf_ifindex(net, cnf); |
3b0228656 net: devinet: Ref... |
2283 2284 |
inet_netconf_notify_devconf(net, RTM_NEWNETCONF, NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN, |
974d7af5f ipv4: add support... |
2285 2286 |
ifindex, cnf); } |
31be30854 [IPV4]: Add defau... |
2287 2288 2289 2290 |
} return ret; } |
fe2c6338f net: Convert uses... |
2291 |
static int devinet_sysctl_forward(struct ctl_table *ctl, int write, |
32927393d sysctl: pass kern... |
2292 |
void *buffer, size_t *lenp, loff_t *ppos) |
1da177e4c Linux-2.6.12-rc2 |
2293 2294 2295 |
{ int *valp = ctl->data; int val = *valp; |
88af182e3 net: Fix sysctl r... |
2296 |
loff_t pos = *ppos; |
8d65af789 sysctl: remove "s... |
2297 |
int ret = proc_dointvec(ctl, write, buffer, lenp, ppos); |
1da177e4c Linux-2.6.12-rc2 |
2298 2299 |
if (write && *valp != val) { |
c0ce9fb30 [IPV4]: Store the... |
2300 |
struct net *net = ctl->extra2; |
0187bdfb0 net: Disable LRO ... |
2301 |
if (valp != &IPV4_DEVCONF_DFLT(net, FORWARDING)) { |
88af182e3 net: Fix sysctl r... |
2302 2303 2304 2305 |
if (!rtnl_trylock()) { /* Restore the original values before restarting */ *valp = val; *ppos = pos; |
9b8adb5ea net: Fix devinet_... |
2306 |
return restart_syscall(); |
88af182e3 net: Fix sysctl r... |
2307 |
} |
0187bdfb0 net: Disable LRO ... |
2308 2309 |
if (valp == &IPV4_DEVCONF_ALL(net, FORWARDING)) { inet_forward_change(net); |
edc9e7489 rtnl/ipv4: use ne... |
2310 |
} else { |
0187bdfb0 net: Disable LRO ... |
2311 2312 2313 |
struct ipv4_devconf *cnf = ctl->extra1; struct in_device *idev = container_of(cnf, struct in_device, cnf); |
edc9e7489 rtnl/ipv4: use ne... |
2314 2315 |
if (*valp) dev_disable_lro(idev->dev); |
3b0228656 net: devinet: Ref... |
2316 |
inet_netconf_notify_devconf(net, RTM_NEWNETCONF, |
edc9e7489 rtnl/ipv4: use ne... |
2317 2318 2319 |
NETCONFA_FORWARDING, idev->dev->ifindex, cnf); |
0187bdfb0 net: Disable LRO ... |
2320 2321 |
} rtnl_unlock(); |
4ccfe6d41 ipv4/route: arg d... |
2322 |
rt_cache_flush(net); |
edc9e7489 rtnl/ipv4: use ne... |
2323 |
} else |
3b0228656 net: devinet: Ref... |
2324 2325 |
inet_netconf_notify_devconf(net, RTM_NEWNETCONF, NETCONFA_FORWARDING, |
edc9e7489 rtnl/ipv4: use ne... |
2326 2327 |
NETCONFA_IFINDEX_DEFAULT, net->ipv4.devconf_dflt); |
1da177e4c Linux-2.6.12-rc2 |
2328 2329 2330 2331 |
} return ret; } |
fe2c6338f net: Convert uses... |
2332 |
static int ipv4_doint_and_flush(struct ctl_table *ctl, int write, |
32927393d sysctl: pass kern... |
2333 |
void *buffer, size_t *lenp, loff_t *ppos) |
1da177e4c Linux-2.6.12-rc2 |
2334 2335 2336 |
{ int *valp = ctl->data; int val = *valp; |
8d65af789 sysctl: remove "s... |
2337 |
int ret = proc_dointvec(ctl, write, buffer, lenp, ppos); |
76e6ebfb4 netns: add namesp... |
2338 |
struct net *net = ctl->extra2; |
1da177e4c Linux-2.6.12-rc2 |
2339 2340 |
if (write && *valp != val) |
4ccfe6d41 ipv4/route: arg d... |
2341 |
rt_cache_flush(net); |
1da177e4c Linux-2.6.12-rc2 |
2342 2343 2344 |
return ret; } |
f8572d8f2 sysctl net: Remov... |
2345 |
#define DEVINET_SYSCTL_ENTRY(attr, name, mval, proc) \ |
42f811b8b [IPV4]: Convert I... |
2346 |
{ \ |
42f811b8b [IPV4]: Convert I... |
2347 2348 |
.procname = name, \ .data = ipv4_devconf.data + \ |
02291680f net ipv4: Decoupl... |
2349 |
IPV4_DEVCONF_ ## attr - 1, \ |
42f811b8b [IPV4]: Convert I... |
2350 2351 2352 |
.maxlen = sizeof(int), \ .mode = mval, \ .proc_handler = proc, \ |
31be30854 [IPV4]: Add defau... |
2353 |
.extra1 = &ipv4_devconf, \ |
42f811b8b [IPV4]: Convert I... |
2354 2355 2356 |
} #define DEVINET_SYSCTL_RW_ENTRY(attr, name) \ |
f8572d8f2 sysctl net: Remov... |
2357 |
DEVINET_SYSCTL_ENTRY(attr, name, 0644, devinet_conf_proc) |
42f811b8b [IPV4]: Convert I... |
2358 2359 |
#define DEVINET_SYSCTL_RO_ENTRY(attr, name) \ |
f8572d8f2 sysctl net: Remov... |
2360 |
DEVINET_SYSCTL_ENTRY(attr, name, 0444, devinet_conf_proc) |
42f811b8b [IPV4]: Convert I... |
2361 |
|
f8572d8f2 sysctl net: Remov... |
2362 2363 |
#define DEVINET_SYSCTL_COMPLEX_ENTRY(attr, name, proc) \ DEVINET_SYSCTL_ENTRY(attr, name, 0644, proc) |
42f811b8b [IPV4]: Convert I... |
2364 2365 |
#define DEVINET_SYSCTL_FLUSHING_ENTRY(attr, name) \ |
f8572d8f2 sysctl net: Remov... |
2366 |
DEVINET_SYSCTL_COMPLEX_ENTRY(attr, name, ipv4_doint_and_flush) |
42f811b8b [IPV4]: Convert I... |
2367 |
|
1da177e4c Linux-2.6.12-rc2 |
2368 2369 |
static struct devinet_sysctl_table { struct ctl_table_header *sysctl_header; |
02291680f net ipv4: Decoupl... |
2370 |
struct ctl_table devinet_vars[__IPV4_DEVCONF_MAX]; |
1da177e4c Linux-2.6.12-rc2 |
2371 2372 |
} devinet_sysctl = { .devinet_vars = { |
42f811b8b [IPV4]: Convert I... |
2373 |
DEVINET_SYSCTL_COMPLEX_ENTRY(FORWARDING, "forwarding", |
f8572d8f2 sysctl net: Remov... |
2374 |
devinet_sysctl_forward), |
42f811b8b [IPV4]: Convert I... |
2375 |
DEVINET_SYSCTL_RO_ENTRY(MC_FORWARDING, "mc_forwarding"), |
5cbf777cf route: add suppor... |
2376 |
DEVINET_SYSCTL_RW_ENTRY(BC_FORWARDING, "bc_forwarding"), |
42f811b8b [IPV4]: Convert I... |
2377 2378 2379 2380 2381 2382 2383 2384 |
DEVINET_SYSCTL_RW_ENTRY(ACCEPT_REDIRECTS, "accept_redirects"), DEVINET_SYSCTL_RW_ENTRY(SECURE_REDIRECTS, "secure_redirects"), DEVINET_SYSCTL_RW_ENTRY(SHARED_MEDIA, "shared_media"), DEVINET_SYSCTL_RW_ENTRY(RP_FILTER, "rp_filter"), DEVINET_SYSCTL_RW_ENTRY(SEND_REDIRECTS, "send_redirects"), DEVINET_SYSCTL_RW_ENTRY(ACCEPT_SOURCE_ROUTE, "accept_source_route"), |
8153a10c0 ipv4 05/05: add s... |
2385 |
DEVINET_SYSCTL_RW_ENTRY(ACCEPT_LOCAL, "accept_local"), |
28f6aeea3 net: restore ip s... |
2386 |
DEVINET_SYSCTL_RW_ENTRY(SRC_VMARK, "src_valid_mark"), |
42f811b8b [IPV4]: Convert I... |
2387 2388 2389 2390 2391 2392 2393 2394 2395 |
DEVINET_SYSCTL_RW_ENTRY(PROXY_ARP, "proxy_arp"), DEVINET_SYSCTL_RW_ENTRY(MEDIUM_ID, "medium_id"), DEVINET_SYSCTL_RW_ENTRY(BOOTP_RELAY, "bootp_relay"), DEVINET_SYSCTL_RW_ENTRY(LOG_MARTIANS, "log_martians"), DEVINET_SYSCTL_RW_ENTRY(TAG, "tag"), DEVINET_SYSCTL_RW_ENTRY(ARPFILTER, "arp_filter"), DEVINET_SYSCTL_RW_ENTRY(ARP_ANNOUNCE, "arp_announce"), DEVINET_SYSCTL_RW_ENTRY(ARP_IGNORE, "arp_ignore"), DEVINET_SYSCTL_RW_ENTRY(ARP_ACCEPT, "arp_accept"), |
eefef1cf7 net: add ARP noti... |
2396 |
DEVINET_SYSCTL_RW_ENTRY(ARP_NOTIFY, "arp_notify"), |
65324144b net: RFC3069, pri... |
2397 |
DEVINET_SYSCTL_RW_ENTRY(PROXY_ARP_PVLAN, "proxy_arp_pvlan"), |
5c6fe01c1 net: igmp: Don't ... |
2398 2399 |
DEVINET_SYSCTL_RW_ENTRY(FORCE_IGMP_VERSION, "force_igmp_version"), |
2690048c0 net: igmp: Allow ... |
2400 2401 2402 2403 |
DEVINET_SYSCTL_RW_ENTRY(IGMPV2_UNSOLICITED_REPORT_INTERVAL, "igmpv2_unsolicited_report_interval"), DEVINET_SYSCTL_RW_ENTRY(IGMPV3_UNSOLICITED_REPORT_INTERVAL, "igmpv3_unsolicited_report_interval"), |
0eeb075fa net: ipv4 sysctl ... |
2404 2405 |
DEVINET_SYSCTL_RW_ENTRY(IGNORE_ROUTES_WITH_LINKDOWN, "ignore_routes_with_linkdown"), |
97daf3314 ipv4: add option ... |
2406 2407 |
DEVINET_SYSCTL_RW_ENTRY(DROP_GRATUITOUS_ARP, "drop_gratuitous_arp"), |
42f811b8b [IPV4]: Convert I... |
2408 2409 2410 |
DEVINET_SYSCTL_FLUSHING_ENTRY(NOXFRM, "disable_xfrm"), DEVINET_SYSCTL_FLUSHING_ENTRY(NOPOLICY, "disable_policy"), |
42f811b8b [IPV4]: Convert I... |
2411 2412 |
DEVINET_SYSCTL_FLUSHING_ENTRY(PROMOTE_SECONDARIES, "promote_secondaries"), |
d0daebc3d ipv4: Add interfa... |
2413 2414 |
DEVINET_SYSCTL_FLUSHING_ENTRY(ROUTE_LOCALNET, "route_localnet"), |
12b74dfad ipv4: add option ... |
2415 2416 |
DEVINET_SYSCTL_FLUSHING_ENTRY(DROP_UNICAST_IN_L2_MULTICAST, "drop_unicast_in_l2_multicast"), |
1da177e4c Linux-2.6.12-rc2 |
2417 |
}, |
1da177e4c Linux-2.6.12-rc2 |
2418 |
}; |
ea40b324d [IPV4]: Make __de... |
2419 |
static int __devinet_sysctl_register(struct net *net, char *dev_name, |
29c994e36 netconf: add a no... |
2420 |
int ifindex, struct ipv4_devconf *p) |
1da177e4c Linux-2.6.12-rc2 |
2421 2422 |
{ int i; |
9fa896429 [IPV4]: Cleanup t... |
2423 |
struct devinet_sysctl_table *t; |
8607ddb86 net ipv4: Convert... |
2424 |
char path[sizeof("net/ipv4/conf/") + IFNAMSIZ]; |
bfada697b [IPV4]: Use ctl p... |
2425 |
|
9fa896429 [IPV4]: Cleanup t... |
2426 |
t = kmemdup(&devinet_sysctl, sizeof(*t), GFP_KERNEL); |
1da177e4c Linux-2.6.12-rc2 |
2427 |
if (!t) |
9fa896429 [IPV4]: Cleanup t... |
2428 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
2429 2430 |
for (i = 0; i < ARRAY_SIZE(t->devinet_vars) - 1; i++) { t->devinet_vars[i].data += (char *)p - (char *)&ipv4_devconf; |
31be30854 [IPV4]: Add defau... |
2431 |
t->devinet_vars[i].extra1 = p; |
c0ce9fb30 [IPV4]: Store the... |
2432 |
t->devinet_vars[i].extra2 = net; |
1da177e4c Linux-2.6.12-rc2 |
2433 |
} |
8607ddb86 net ipv4: Convert... |
2434 |
snprintf(path, sizeof(path), "net/ipv4/conf/%s", dev_name); |
1da177e4c Linux-2.6.12-rc2 |
2435 |
|
8607ddb86 net ipv4: Convert... |
2436 |
t->sysctl_header = register_net_sysctl(net, path, t->devinet_vars); |
1da177e4c Linux-2.6.12-rc2 |
2437 |
if (!t->sysctl_header) |
8607ddb86 net ipv4: Convert... |
2438 |
goto free; |
1da177e4c Linux-2.6.12-rc2 |
2439 2440 |
p->sysctl = t; |
29c994e36 netconf: add a no... |
2441 |
|
3b0228656 net: devinet: Ref... |
2442 2443 |
inet_netconf_notify_devconf(net, RTM_NEWNETCONF, NETCONFA_ALL, ifindex, p); |
ea40b324d [IPV4]: Make __de... |
2444 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
2445 |
|
9fa896429 [IPV4]: Cleanup t... |
2446 |
free: |
1da177e4c Linux-2.6.12-rc2 |
2447 |
kfree(t); |
9fa896429 [IPV4]: Cleanup t... |
2448 |
out: |
ea40b324d [IPV4]: Make __de... |
2449 |
return -ENOBUFS; |
1da177e4c Linux-2.6.12-rc2 |
2450 |
} |
b5c9641d3 net: devinet: Add... |
2451 2452 |
static void __devinet_sysctl_unregister(struct net *net, struct ipv4_devconf *cnf, int ifindex) |
51602b2a5 [IPV4]: Cleanup s... |
2453 2454 |
{ struct devinet_sysctl_table *t = cnf->sysctl; |
b5c9641d3 net: devinet: Add... |
2455 2456 2457 2458 2459 |
if (t) { cnf->sysctl = NULL; unregister_net_sysctl_table(t->sysctl_header); kfree(t); } |
51602b2a5 [IPV4]: Cleanup s... |
2460 |
|
b5c9641d3 net: devinet: Add... |
2461 |
inet_netconf_notify_devconf(net, RTM_DELNETCONF, 0, ifindex, NULL); |
51602b2a5 [IPV4]: Cleanup s... |
2462 |
} |
20e61da7f ipv4: fail early ... |
2463 |
static int devinet_sysctl_register(struct in_device *idev) |
66f27a520 [IPV4]: Unify and... |
2464 |
{ |
20e61da7f ipv4: fail early ... |
2465 2466 2467 2468 2469 2470 2471 2472 2473 |
int err; if (!sysctl_dev_name_is_allowed(idev->dev->name)) return -EINVAL; err = neigh_sysctl_register(idev->dev, idev->arp_parms, NULL); if (err) return err; err = __devinet_sysctl_register(dev_net(idev->dev), idev->dev->name, |
29c994e36 netconf: add a no... |
2474 |
idev->dev->ifindex, &idev->cnf); |
20e61da7f ipv4: fail early ... |
2475 2476 2477 |
if (err) neigh_sysctl_unregister(idev->arp_parms); return err; |
66f27a520 [IPV4]: Unify and... |
2478 |
} |
51602b2a5 [IPV4]: Cleanup s... |
2479 |
static void devinet_sysctl_unregister(struct in_device *idev) |
1da177e4c Linux-2.6.12-rc2 |
2480 |
{ |
b5c9641d3 net: devinet: Add... |
2481 2482 2483 |
struct net *net = dev_net(idev->dev); __devinet_sysctl_unregister(net, &idev->cnf, idev->dev->ifindex); |
51602b2a5 [IPV4]: Cleanup s... |
2484 |
neigh_sysctl_unregister(idev->arp_parms); |
1da177e4c Linux-2.6.12-rc2 |
2485 |
} |
1da177e4c Linux-2.6.12-rc2 |
2486 |
|
68dd299bc [INET]: Merge sys... |
2487 2488 |
static struct ctl_table ctl_forward_entry[] = { { |
68dd299bc [INET]: Merge sys... |
2489 2490 |
.procname = "ip_forward", .data = &ipv4_devconf.data[ |
02291680f net ipv4: Decoupl... |
2491 |
IPV4_DEVCONF_FORWARDING - 1], |
68dd299bc [INET]: Merge sys... |
2492 2493 2494 |
.maxlen = sizeof(int), .mode = 0644, .proc_handler = devinet_sysctl_forward, |
68dd299bc [INET]: Merge sys... |
2495 |
.extra1 = &ipv4_devconf, |
c0ce9fb30 [IPV4]: Store the... |
2496 |
.extra2 = &init_net, |
68dd299bc [INET]: Merge sys... |
2497 2498 2499 |
}, { }, }; |
2a75de0c1 [NETNS]: Should b... |
2500 |
#endif |
68dd299bc [INET]: Merge sys... |
2501 |
|
752d14dc6 [IPV4]: Move the ... |
2502 2503 2504 |
static __net_init int devinet_init_net(struct net *net) { int err; |
752d14dc6 [IPV4]: Move the ... |
2505 |
struct ipv4_devconf *all, *dflt; |
2a75de0c1 [NETNS]: Should b... |
2506 |
#ifdef CONFIG_SYSCTL |
856c395cf net: introduce a ... |
2507 |
struct ctl_table *tbl; |
752d14dc6 [IPV4]: Move the ... |
2508 |
struct ctl_table_header *forw_hdr; |
2a75de0c1 [NETNS]: Should b... |
2509 |
#endif |
752d14dc6 [IPV4]: Move the ... |
2510 2511 |
err = -ENOMEM; |
856c395cf net: introduce a ... |
2512 2513 2514 |
all = kmemdup(&ipv4_devconf, sizeof(ipv4_devconf), GFP_KERNEL); if (!all) goto err_alloc_all; |
752d14dc6 [IPV4]: Move the ... |
2515 |
|
856c395cf net: introduce a ... |
2516 2517 2518 |
dflt = kmemdup(&ipv4_devconf_dflt, sizeof(ipv4_devconf_dflt), GFP_KERNEL); if (!dflt) goto err_alloc_dflt; |
752d14dc6 [IPV4]: Move the ... |
2519 |
|
2a75de0c1 [NETNS]: Should b... |
2520 |
#ifdef CONFIG_SYSCTL |
856c395cf net: introduce a ... |
2521 2522 2523 |
tbl = kmemdup(ctl_forward_entry, sizeof(ctl_forward_entry), GFP_KERNEL); if (!tbl) goto err_alloc_ctl; |
752d14dc6 [IPV4]: Move the ... |
2524 |
|
856c395cf net: introduce a ... |
2525 2526 2527 |
tbl[0].data = &all->data[IPV4_DEVCONF_FORWARDING - 1]; tbl[0].extra1 = all; tbl[0].extra2 = net; |
2a75de0c1 [NETNS]: Should b... |
2528 |
#endif |
856c395cf net: introduce a ... |
2529 |
|
9efd6a3ce netns: enable to ... |
2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 |
if (!net_eq(net, &init_net)) { if (IS_ENABLED(CONFIG_SYSCTL) && sysctl_devconf_inherit_init_net == 3) { /* copy from the current netns */ memcpy(all, current->nsproxy->net_ns->ipv4.devconf_all, sizeof(ipv4_devconf)); memcpy(dflt, current->nsproxy->net_ns->ipv4.devconf_dflt, sizeof(ipv4_devconf_dflt)); } else if (!IS_ENABLED(CONFIG_SYSCTL) || sysctl_devconf_inherit_init_net != 2) { /* inherit == 0 or 1: copy from init_net */ memcpy(all, init_net.ipv4.devconf_all, sizeof(ipv4_devconf)); memcpy(dflt, init_net.ipv4.devconf_dflt, sizeof(ipv4_devconf_dflt)); } /* else inherit == 2: use compiled values */ |
752d14dc6 [IPV4]: Move the ... |
2548 2549 2550 |
} #ifdef CONFIG_SYSCTL |
29c994e36 netconf: add a no... |
2551 |
err = __devinet_sysctl_register(net, "all", NETCONFA_IFINDEX_ALL, all); |
752d14dc6 [IPV4]: Move the ... |
2552 2553 |
if (err < 0) goto err_reg_all; |
29c994e36 netconf: add a no... |
2554 2555 |
err = __devinet_sysctl_register(net, "default", NETCONFA_IFINDEX_DEFAULT, dflt); |
752d14dc6 [IPV4]: Move the ... |
2556 2557 2558 2559 |
if (err < 0) goto err_reg_dflt; err = -ENOMEM; |
8607ddb86 net ipv4: Convert... |
2560 |
forw_hdr = register_net_sysctl(net, "net/ipv4", tbl); |
51456b291 ipv4: coding styl... |
2561 |
if (!forw_hdr) |
752d14dc6 [IPV4]: Move the ... |
2562 |
goto err_reg_ctl; |
2a75de0c1 [NETNS]: Should b... |
2563 |
net->ipv4.forw_hdr = forw_hdr; |
752d14dc6 [IPV4]: Move the ... |
2564 |
#endif |
752d14dc6 [IPV4]: Move the ... |
2565 2566 2567 2568 2569 2570 |
net->ipv4.devconf_all = all; net->ipv4.devconf_dflt = dflt; return 0; #ifdef CONFIG_SYSCTL err_reg_ctl: |
b5c9641d3 net: devinet: Add... |
2571 |
__devinet_sysctl_unregister(net, dflt, NETCONFA_IFINDEX_DEFAULT); |
752d14dc6 [IPV4]: Move the ... |
2572 |
err_reg_dflt: |
b5c9641d3 net: devinet: Add... |
2573 |
__devinet_sysctl_unregister(net, all, NETCONFA_IFINDEX_ALL); |
752d14dc6 [IPV4]: Move the ... |
2574 |
err_reg_all: |
856c395cf net: introduce a ... |
2575 |
kfree(tbl); |
752d14dc6 [IPV4]: Move the ... |
2576 |
err_alloc_ctl: |
2a75de0c1 [NETNS]: Should b... |
2577 |
#endif |
856c395cf net: introduce a ... |
2578 |
kfree(dflt); |
752d14dc6 [IPV4]: Move the ... |
2579 |
err_alloc_dflt: |
856c395cf net: introduce a ... |
2580 |
kfree(all); |
752d14dc6 [IPV4]: Move the ... |
2581 2582 2583 2584 2585 2586 |
err_alloc_all: return err; } static __net_exit void devinet_exit_net(struct net *net) { |
2a75de0c1 [NETNS]: Should b... |
2587 |
#ifdef CONFIG_SYSCTL |
752d14dc6 [IPV4]: Move the ... |
2588 2589 2590 |
struct ctl_table *tbl; tbl = net->ipv4.forw_hdr->ctl_table_arg; |
752d14dc6 [IPV4]: Move the ... |
2591 |
unregister_net_sysctl_table(net->ipv4.forw_hdr); |
b5c9641d3 net: devinet: Add... |
2592 2593 2594 2595 |
__devinet_sysctl_unregister(net, net->ipv4.devconf_dflt, NETCONFA_IFINDEX_DEFAULT); __devinet_sysctl_unregister(net, net->ipv4.devconf_all, NETCONFA_IFINDEX_ALL); |
752d14dc6 [IPV4]: Move the ... |
2596 |
kfree(tbl); |
2a75de0c1 [NETNS]: Should b... |
2597 |
#endif |
752d14dc6 [IPV4]: Move the ... |
2598 2599 2600 2601 2602 2603 2604 2605 |
kfree(net->ipv4.devconf_dflt); kfree(net->ipv4.devconf_all); } static __net_initdata struct pernet_operations devinet_ops = { .init = devinet_init_net, .exit = devinet_exit_net, }; |
207895fd3 net: mark some po... |
2606 |
static struct rtnl_af_ops inet_af_ops __read_mostly = { |
9f0f7272a ipv4: AF_INET lin... |
2607 2608 2609 |
.family = AF_INET, .fill_link_af = inet_fill_link_af, .get_link_af_size = inet_get_link_af_size, |
cf7afbfeb rtnl: make link a... |
2610 2611 |
.validate_link_af = inet_validate_link_af, .set_link_af = inet_set_link_af, |
9f0f7272a ipv4: AF_INET lin... |
2612 |
}; |
1da177e4c Linux-2.6.12-rc2 |
2613 2614 |
void __init devinet_init(void) { |
fd23c3b31 ipv4: Add hash ta... |
2615 2616 2617 2618 |
int i; for (i = 0; i < IN4_ADDR_HSIZE; i++) INIT_HLIST_HEAD(&inet_addr_lst[i]); |
752d14dc6 [IPV4]: Move the ... |
2619 |
register_pernet_subsys(&devinet_ops); |
1da177e4c Linux-2.6.12-rc2 |
2620 2621 |
register_gifconf(PF_INET, inet_gifconf); register_netdevice_notifier(&ip_netdev_notifier); |
63f3444fb [IPv4]: Use rtnl ... |
2622 |
|
906e073f3 net/ipv4: queue w... |
2623 |
queue_delayed_work(system_power_efficient_wq, &check_lifetime_work, 0); |
5c766d642 ipv4: introduce a... |
2624 |
|
9f0f7272a ipv4: AF_INET lin... |
2625 |
rtnl_af_register(&inet_af_ops); |
b97bac64a rtnetlink: make r... |
2626 2627 2628 |
rtnl_register(PF_INET, RTM_NEWADDR, inet_rtm_newaddr, NULL, 0); rtnl_register(PF_INET, RTM_DELADDR, inet_rtm_deladdr, NULL, 0); rtnl_register(PF_INET, RTM_GETADDR, NULL, inet_dump_ifaddr, 0); |
9e5511106 rtnl/ipv4: add su... |
2629 |
rtnl_register(PF_INET, RTM_GETNETCONF, inet_netconf_get_devconf, |
b97bac64a rtnetlink: make r... |
2630 |
inet_netconf_dump_devconf, 0); |
1da177e4c Linux-2.6.12-rc2 |
2631 |
} |