Blame view
net/ipv4/fib_frontend.c
38.7 KB
2874c5fd2 treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
1da177e4c Linux-2.6.12-rc2 |
2 3 4 5 6 7 8 |
/* * INET An implementation of the TCP/IP protocol suite for the LINUX * operating system. INET is implemented using the BSD Socket * interface as the means of communication with the user level. * * IPv4 Forwarding Information Base: FIB frontend. * |
1da177e4c Linux-2.6.12-rc2 |
9 |
* Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> |
1da177e4c Linux-2.6.12-rc2 |
10 |
*/ |
1da177e4c Linux-2.6.12-rc2 |
11 |
#include <linux/module.h> |
7c0f6ba68 Replace <asm/uacc... |
12 |
#include <linux/uaccess.h> |
1da177e4c Linux-2.6.12-rc2 |
13 |
#include <linux/bitops.h> |
4fc268d24 [PATCH] capable/c... |
14 |
#include <linux/capability.h> |
1da177e4c Linux-2.6.12-rc2 |
15 16 |
#include <linux/types.h> #include <linux/kernel.h> |
1da177e4c Linux-2.6.12-rc2 |
17 18 19 20 21 22 23 |
#include <linux/mm.h> #include <linux/string.h> #include <linux/socket.h> #include <linux/sockios.h> #include <linux/errno.h> #include <linux/in.h> #include <linux/inet.h> |
14c850212 [INET_SOCK]: Move... |
24 |
#include <linux/inetdevice.h> |
1da177e4c Linux-2.6.12-rc2 |
25 |
#include <linux/netdevice.h> |
1823730fb [IPv4]: Move inte... |
26 |
#include <linux/if_addr.h> |
1da177e4c Linux-2.6.12-rc2 |
27 28 |
#include <linux/if_arp.h> #include <linux/skbuff.h> |
7a9bc9b81 ipv4: Elide fib_v... |
29 |
#include <linux/cache.h> |
1da177e4c Linux-2.6.12-rc2 |
30 |
#include <linux/init.h> |
1af5a8c4a [IPV4]: Increase ... |
31 |
#include <linux/list.h> |
5a0e3ad6a include cleanup: ... |
32 |
#include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
33 34 35 36 37 38 |
#include <net/ip.h> #include <net/protocol.h> #include <net/route.h> #include <net/tcp.h> #include <net/sock.h> |
1da177e4c Linux-2.6.12-rc2 |
39 40 |
#include <net/arp.h> #include <net/ip_fib.h> |
5481d73f8 ipv4: Use accesso... |
41 |
#include <net/nexthop.h> |
63f3444fb [IPv4]: Use rtnl ... |
42 |
#include <net/rtnetlink.h> |
990078afb Disable rp_filter... |
43 |
#include <net/xfrm.h> |
385add906 net: Replace vrf_... |
44 |
#include <net/l3mdev.h> |
9ed59592e lwtunnel: fix aut... |
45 |
#include <net/lwtunnel.h> |
f6d3c1927 net: FIB tracepoints |
46 |
#include <trace/events/fib.h> |
1da177e4c Linux-2.6.12-rc2 |
47 |
|
1da177e4c Linux-2.6.12-rc2 |
48 |
#ifndef CONFIG_IP_MULTIPLE_TABLES |
7b1a74fdb [NETNS]: Refactor... |
49 |
static int __net_init fib4_rules_init(struct net *net) |
c3e9a353d [IPV4]: Compact s... |
50 |
{ |
93456b6d7 [IPV4]: Unify acc... |
51 |
struct fib_table *local_table, *main_table; |
0ddcf43d5 ipv4: FIB Local/M... |
52 |
main_table = fib_trie_table(RT_TABLE_MAIN, NULL); |
51456b291 ipv4: coding styl... |
53 |
if (!main_table) |
61f0d861f fib_trie: Fix uni... |
54 |
return -ENOMEM; |
dbb50165b [IPV4]: Check fib... |
55 |
|
0ddcf43d5 ipv4: FIB Local/M... |
56 |
local_table = fib_trie_table(RT_TABLE_LOCAL, main_table); |
51456b291 ipv4: coding styl... |
57 |
if (!local_table) |
61f0d861f fib_trie: Fix uni... |
58 |
goto fail; |
0ddcf43d5 ipv4: FIB Local/M... |
59 |
|
93456b6d7 [IPV4]: Unify acc... |
60 |
hlist_add_head_rcu(&local_table->tb_hlist, |
e4aef8aea [NETNS]: Place fi... |
61 |
&net->ipv4.fib_table_hash[TABLE_LOCAL_INDEX]); |
93456b6d7 [IPV4]: Unify acc... |
62 |
hlist_add_head_rcu(&main_table->tb_hlist, |
e4aef8aea [NETNS]: Place fi... |
63 |
&net->ipv4.fib_table_hash[TABLE_MAIN_INDEX]); |
dbb50165b [IPV4]: Check fib... |
64 65 66 |
return 0; fail: |
61f0d861f fib_trie: Fix uni... |
67 |
fib_free_table(main_table); |
dbb50165b [IPV4]: Check fib... |
68 |
return -ENOMEM; |
c3e9a353d [IPV4]: Compact s... |
69 |
} |
032a48020 ipv4: fix validat... |
70 71 72 73 74 |
static bool fib4_has_custom_rules(struct net *net) { return false; } |
1af5a8c4a [IPV4]: Increase ... |
75 |
#else |
1da177e4c Linux-2.6.12-rc2 |
76 |
|
8ad4942cd [NETNS]: Add netn... |
77 |
struct fib_table *fib_new_table(struct net *net, u32 id) |
1da177e4c Linux-2.6.12-rc2 |
78 |
{ |
0ddcf43d5 ipv4: FIB Local/M... |
79 |
struct fib_table *tb, *alias = NULL; |
1af5a8c4a [IPV4]: Increase ... |
80 |
unsigned int h; |
1da177e4c Linux-2.6.12-rc2 |
81 |
|
1af5a8c4a [IPV4]: Increase ... |
82 83 |
if (id == 0) id = RT_TABLE_MAIN; |
8ad4942cd [NETNS]: Add netn... |
84 |
tb = fib_get_table(net, id); |
1af5a8c4a [IPV4]: Increase ... |
85 86 |
if (tb) return tb; |
7f9b80529 [IPV4]: fib hash|... |
87 |
|
5350d54f6 ipv4: Do not allo... |
88 |
if (id == RT_TABLE_LOCAL && !net->ipv4.fib_has_custom_rules) |
0ddcf43d5 ipv4: FIB Local/M... |
89 90 91 |
alias = fib_new_table(net, RT_TABLE_MAIN); tb = fib_trie_table(id, alias); |
1da177e4c Linux-2.6.12-rc2 |
92 93 |
if (!tb) return NULL; |
f4530fa57 ipv4: Avoid overh... |
94 95 |
switch (id) { |
f4530fa57 ipv4: Avoid overh... |
96 |
case RT_TABLE_MAIN: |
a7e535312 fib_trie: Make fi... |
97 |
rcu_assign_pointer(net->ipv4.fib_main, tb); |
f4530fa57 ipv4: Avoid overh... |
98 |
break; |
f4530fa57 ipv4: Avoid overh... |
99 |
case RT_TABLE_DEFAULT: |
a7e535312 fib_trie: Make fi... |
100 |
rcu_assign_pointer(net->ipv4.fib_default, tb); |
f4530fa57 ipv4: Avoid overh... |
101 |
break; |
f4530fa57 ipv4: Avoid overh... |
102 103 104 |
default: break; } |
1af5a8c4a [IPV4]: Increase ... |
105 |
h = id & (FIB_TABLE_HASHSZ - 1); |
e4aef8aea [NETNS]: Place fi... |
106 |
hlist_add_head_rcu(&tb->tb_hlist, &net->ipv4.fib_table_hash[h]); |
1da177e4c Linux-2.6.12-rc2 |
107 108 |
return tb; } |
b3b4663c9 net: vrf: Create ... |
109 |
EXPORT_SYMBOL_GPL(fib_new_table); |
1da177e4c Linux-2.6.12-rc2 |
110 |
|
345e9b542 fib_trie: Push rc... |
111 |
/* caller must hold either rtnl or rcu read lock */ |
8ad4942cd [NETNS]: Add netn... |
112 |
struct fib_table *fib_get_table(struct net *net, u32 id) |
1af5a8c4a [IPV4]: Increase ... |
113 114 |
{ struct fib_table *tb; |
e4aef8aea [NETNS]: Place fi... |
115 |
struct hlist_head *head; |
1af5a8c4a [IPV4]: Increase ... |
116 |
unsigned int h; |
1da177e4c Linux-2.6.12-rc2 |
117 |
|
1af5a8c4a [IPV4]: Increase ... |
118 119 120 |
if (id == 0) id = RT_TABLE_MAIN; h = id & (FIB_TABLE_HASHSZ - 1); |
e4aef8aea [NETNS]: Place fi... |
121 |
|
e4aef8aea [NETNS]: Place fi... |
122 |
head = &net->ipv4.fib_table_hash[h]; |
7fd69b0ba ipv4: Add lockdep... |
123 124 |
hlist_for_each_entry_rcu(tb, head, tb_hlist, lockdep_rtnl_is_held()) { |
345e9b542 fib_trie: Push rc... |
125 |
if (tb->tb_id == id) |
1af5a8c4a [IPV4]: Increase ... |
126 |
return tb; |
1af5a8c4a [IPV4]: Increase ... |
127 |
} |
1af5a8c4a [IPV4]: Increase ... |
128 129 |
return NULL; } |
032a48020 ipv4: fix validat... |
130 131 132 133 134 |
static bool fib4_has_custom_rules(struct net *net) { return net->ipv4.fib_has_custom_rules; } |
1da177e4c Linux-2.6.12-rc2 |
135 |
#endif /* CONFIG_IP_MULTIPLE_TABLES */ |
0ddcf43d5 ipv4: FIB Local/M... |
136 137 138 139 140 |
static void fib_replace_table(struct net *net, struct fib_table *old, struct fib_table *new) { #ifdef CONFIG_IP_MULTIPLE_TABLES switch (new->tb_id) { |
0ddcf43d5 ipv4: FIB Local/M... |
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
case RT_TABLE_MAIN: rcu_assign_pointer(net->ipv4.fib_main, new); break; case RT_TABLE_DEFAULT: rcu_assign_pointer(net->ipv4.fib_default, new); break; default: break; } #endif /* replace the old table in the hlist */ hlist_replace_rcu(&old->tb_hlist, &new->tb_hlist); } int fib_unmerge(struct net *net) { |
3b7093346 ipv4: Restore fib... |
158 |
struct fib_table *old, *new, *main_table; |
0ddcf43d5 ipv4: FIB Local/M... |
159 |
|
3c9e9f732 fib_trie: Avoid N... |
160 |
/* attempt to fetch local table if it has been allocated */ |
0ddcf43d5 ipv4: FIB Local/M... |
161 |
old = fib_get_table(net, RT_TABLE_LOCAL); |
3c9e9f732 fib_trie: Avoid N... |
162 163 |
if (!old) return 0; |
0ddcf43d5 ipv4: FIB Local/M... |
164 |
|
3c9e9f732 fib_trie: Avoid N... |
165 |
new = fib_trie_unmerge(old); |
0ddcf43d5 ipv4: FIB Local/M... |
166 167 |
if (!new) return -ENOMEM; |
3b7093346 ipv4: Restore fib... |
168 169 170 |
/* table is already unmerged */ if (new == old) return 0; |
0ddcf43d5 ipv4: FIB Local/M... |
171 |
/* replace merged table with clean table */ |
3b7093346 ipv4: Restore fib... |
172 173 174 175 176 177 178 179 180 181 |
fib_replace_table(net, old, new); fib_free_table(old); /* attempt to fetch main table if it has been allocated */ main_table = fib_get_table(net, RT_TABLE_MAIN); if (!main_table) return 0; /* flush local entries from main table */ fib_table_flush_external(main_table); |
0ddcf43d5 ipv4: FIB Local/M... |
182 183 184 |
return 0; } |
9bd836679 ipv4: export fib_... |
185 |
void fib_flush(struct net *net) |
1da177e4c Linux-2.6.12-rc2 |
186 187 |
{ int flushed = 0; |
1af5a8c4a [IPV4]: Increase ... |
188 |
unsigned int h; |
1da177e4c Linux-2.6.12-rc2 |
189 |
|
1af5a8c4a [IPV4]: Increase ... |
190 |
for (h = 0; h < FIB_TABLE_HASHSZ; h++) { |
a7e535312 fib_trie: Make fi... |
191 192 193 194 195 |
struct hlist_head *head = &net->ipv4.fib_table_hash[h]; struct hlist_node *tmp; struct fib_table *tb; hlist_for_each_entry_safe(tb, tmp, head, tb_hlist) |
f97f4dd8b net: ipv4: Fix me... |
196 |
flushed += fib_table_flush(net, tb, false); |
1da177e4c Linux-2.6.12-rc2 |
197 |
} |
1da177e4c Linux-2.6.12-rc2 |
198 199 |
if (flushed) |
4ccfe6d41 ipv4/route: arg d... |
200 |
rt_cache_flush(net); |
1da177e4c Linux-2.6.12-rc2 |
201 |
} |
055381161 [IPV4]: Add inet_... |
202 203 204 205 |
/* * Find address type as if only "dev" was present in the system. If * on_dev is NULL then all interfaces are taken into consideration. */ |
95c961747 net: cleanup unsi... |
206 207 |
static inline unsigned int __inet_dev_addr_type(struct net *net, const struct net_device *dev, |
9b8ff5182 net: Make table i... |
208 |
__be32 addr, u32 tb_id) |
1da177e4c Linux-2.6.12-rc2 |
209 |
{ |
9ade22861 ipv4: Use flowi4 ... |
210 |
struct flowi4 fl4 = { .daddr = addr }; |
1da177e4c Linux-2.6.12-rc2 |
211 |
struct fib_result res; |
95c961747 net: cleanup unsi... |
212 |
unsigned int ret = RTN_BROADCAST; |
15be405eb net: Add inet_add... |
213 |
struct fib_table *table; |
1da177e4c Linux-2.6.12-rc2 |
214 |
|
1e637c74b [IPV4]: Enable us... |
215 |
if (ipv4_is_zeronet(addr) || ipv4_is_lbcast(addr)) |
1da177e4c Linux-2.6.12-rc2 |
216 |
return RTN_BROADCAST; |
f97c1e0c6 [IPV4] net/ipv4: ... |
217 |
if (ipv4_is_multicast(addr)) |
1da177e4c Linux-2.6.12-rc2 |
218 |
return RTN_MULTICAST; |
345e9b542 fib_trie: Push rc... |
219 |
rcu_read_lock(); |
15be405eb net: Add inet_add... |
220 221 |
table = fib_get_table(net, tb_id); if (table) { |
1da177e4c Linux-2.6.12-rc2 |
222 |
ret = RTN_UNICAST; |
15be405eb net: Add inet_add... |
223 |
if (!fib_table_lookup(table, &fl4, &res, FIB_LOOKUP_NOREF)) { |
dcb1ecb50 ipv4: Prepare for... |
224 |
struct fib_nh_common *nhc = fib_info_nhc(res.fi, 0); |
5481d73f8 ipv4: Use accesso... |
225 |
|
dcb1ecb50 ipv4: Prepare for... |
226 |
if (!dev || dev == nhc->nhc_dev) |
055381161 [IPV4]: Add inet_... |
227 |
ret = res.type; |
1da177e4c Linux-2.6.12-rc2 |
228 229 |
} } |
345e9b542 fib_trie: Push rc... |
230 231 |
rcu_read_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
232 233 |
return ret; } |
9b8ff5182 net: Make table i... |
234 |
unsigned int inet_addr_type_table(struct net *net, __be32 addr, u32 tb_id) |
15be405eb net: Add inet_add... |
235 236 237 238 |
{ return __inet_dev_addr_type(net, NULL, addr, tb_id); } EXPORT_SYMBOL(inet_addr_type_table); |
6b175b26c [NETNS]: Add netn... |
239 |
unsigned int inet_addr_type(struct net *net, __be32 addr) |
055381161 [IPV4]: Add inet_... |
240 |
{ |
15be405eb net: Add inet_add... |
241 |
return __inet_dev_addr_type(net, NULL, addr, RT_TABLE_LOCAL); |
055381161 [IPV4]: Add inet_... |
242 |
} |
4bc2f18ba net/ipv4: EXPORT_... |
243 |
EXPORT_SYMBOL(inet_addr_type); |
055381161 [IPV4]: Add inet_... |
244 |
|
6b175b26c [NETNS]: Add netn... |
245 246 |
unsigned int inet_dev_addr_type(struct net *net, const struct net_device *dev, __be32 addr) |
055381161 [IPV4]: Add inet_... |
247 |
{ |
3236b0042 net: Replace vrf_... |
248 |
u32 rt_table = l3mdev_fib_table(dev) ? : RT_TABLE_LOCAL; |
15be405eb net: Add inet_add... |
249 250 |
return __inet_dev_addr_type(net, dev, addr, rt_table); |
055381161 [IPV4]: Add inet_... |
251 |
} |
4bc2f18ba net/ipv4: EXPORT_... |
252 |
EXPORT_SYMBOL(inet_dev_addr_type); |
055381161 [IPV4]: Add inet_... |
253 |
|
30bbaa195 net: Fix up inet_... |
254 255 256 257 258 259 260 |
/* inet_addr_type with dev == NULL but using the table from a dev * if one is associated */ unsigned int inet_addr_type_dev_table(struct net *net, const struct net_device *dev, __be32 addr) { |
3236b0042 net: Replace vrf_... |
261 |
u32 rt_table = l3mdev_fib_table(dev) ? : RT_TABLE_LOCAL; |
30bbaa195 net: Fix up inet_... |
262 263 264 265 |
return __inet_dev_addr_type(net, NULL, addr, rt_table); } EXPORT_SYMBOL(inet_addr_type_dev_table); |
35ebf65e8 ipv4: Create and ... |
266 267 268 269 270 |
__be32 fib_compute_spec_dst(struct sk_buff *skb) { struct net_device *dev = skb->dev; struct in_device *in_dev; struct fib_result res; |
a207a4b2e ipv4: Fix bugs in... |
271 |
struct rtable *rt; |
35ebf65e8 ipv4: Create and ... |
272 |
struct net *net; |
a207a4b2e ipv4: Fix bugs in... |
273 |
int scope; |
35ebf65e8 ipv4: Create and ... |
274 |
|
a207a4b2e ipv4: Fix bugs in... |
275 |
rt = skb_rtable(skb); |
0cc535a29 ipv4: fix address... |
276 277 |
if ((rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST | RTCF_LOCAL)) == RTCF_LOCAL) |
35ebf65e8 ipv4: Create and ... |
278 279 280 |
return ip_hdr(skb)->daddr; in_dev = __in_dev_get_rcu(dev); |
35ebf65e8 ipv4: Create and ... |
281 282 |
net = dev_net(dev); |
a207a4b2e ipv4: Fix bugs in... |
283 284 285 |
scope = RT_SCOPE_UNIVERSE; if (!ipv4_is_zeronet(ip_hdr(skb)->saddr)) { |
9fc12023d ipv4: remove BUG_... |
286 |
bool vmark = in_dev && IN_DEV_SRC_VMARK(in_dev); |
4cfc86f3d ipv4: initialize ... |
287 288 |
struct flowi4 fl4 = { .flowi4_iif = LOOPBACK_IFINDEX, |
e7372197e net/ipv4: Set oif... |
289 |
.flowi4_oif = l3mdev_master_ifindex_rcu(dev), |
4cfc86f3d ipv4: initialize ... |
290 291 292 |
.daddr = ip_hdr(skb)->saddr, .flowi4_tos = RT_TOS(ip_hdr(skb)->tos), .flowi4_scope = scope, |
9fc12023d ipv4: remove BUG_... |
293 |
.flowi4_mark = vmark ? skb->mark : 0, |
4cfc86f3d ipv4: initialize ... |
294 |
}; |
0eeb075fa net: ipv4 sysctl ... |
295 |
if (!fib_lookup(net, &fl4, &res, 0)) |
eba618aba ipv4: Add fib_nh_... |
296 |
return fib_result_prefsrc(net, &res); |
a207a4b2e ipv4: Fix bugs in... |
297 298 299 300 301 |
} else { scope = RT_SCOPE_LINK; } return inet_select_addr(dev, ip_hdr(skb)->saddr, scope); |
35ebf65e8 ipv4: Create and ... |
302 |
} |
78f2756c5 net/ipv4: Move de... |
303 304 305 |
bool fib_info_nh_uses_dev(struct fib_info *fi, const struct net_device *dev) { bool dev_match = false; |
075e264fa net/ipv4: avoid c... |
306 |
#ifdef CONFIG_IP_ROUTE_MULTIPATH |
78f2756c5 net/ipv4: Move de... |
307 |
int ret; |
5481d73f8 ipv4: Use accesso... |
308 |
for (ret = 0; ret < fib_info_num_path(fi); ret++) { |
dcb1ecb50 ipv4: Prepare for... |
309 |
const struct fib_nh_common *nhc = fib_info_nhc(fi, ret); |
78f2756c5 net/ipv4: Move de... |
310 |
|
dcb1ecb50 ipv4: Prepare for... |
311 |
if (nhc->nhc_dev == dev) { |
78f2756c5 net/ipv4: Move de... |
312 313 |
dev_match = true; break; |
dcb1ecb50 ipv4: Prepare for... |
314 |
} else if (l3mdev_master_ifindex_rcu(nhc->nhc_dev) == dev->ifindex) { |
78f2756c5 net/ipv4: Move de... |
315 316 317 318 319 |
dev_match = true; break; } } #else |
dcb1ecb50 ipv4: Prepare for... |
320 |
if (fib_info_nhc(fi, 0)->nhc_dev == dev) |
78f2756c5 net/ipv4: Move de... |
321 322 323 324 325 326 |
dev_match = true; #endif return dev_match; } EXPORT_SYMBOL_GPL(fib_info_nh_uses_dev); |
1da177e4c Linux-2.6.12-rc2 |
327 |
/* Given (packet source, input interface) and optional (dst, oif, tos): |
6a31d2a97 fib: cleanups |
328 329 330 331 332 |
* - (main) check, that source is valid i.e. not broadcast or our local * address. * - figure out what "logical" interface this packet arrived * and calculate "specific destination" address. * - check, that packet arrived from expected physical interface. |
ebc0ffae5 fib: RCU conversi... |
333 |
* called with rcu_read_lock() |
1da177e4c Linux-2.6.12-rc2 |
334 |
*/ |
7a9bc9b81 ipv4: Elide fib_v... |
335 336 337 |
static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst, u8 tos, int oif, struct net_device *dev, int rpf, struct in_device *idev, u32 *itag) |
1da177e4c Linux-2.6.12-rc2 |
338 |
{ |
5a847a6e1 net/ipv4: Initial... |
339 340 |
struct net *net = dev_net(dev); struct flow_keys flkeys; |
1dced6a85 ipv4: Restore acc... |
341 |
int ret, no_addr; |
1da177e4c Linux-2.6.12-rc2 |
342 |
struct fib_result res; |
9e56e3800 ipv4: Adjust in_d... |
343 |
struct flowi4 fl4; |
9e56e3800 ipv4: Adjust in_d... |
344 |
bool dev_match; |
1da177e4c Linux-2.6.12-rc2 |
345 |
|
9ade22861 ipv4: Use flowi4 ... |
346 |
fl4.flowi4_oif = 0; |
385add906 net: Replace vrf_... |
347 |
fl4.flowi4_iif = l3mdev_master_ifindex_rcu(dev); |
cd2fbe1b6 net: Use VRF devi... |
348 349 |
if (!fl4.flowi4_iif) fl4.flowi4_iif = oif ? : LOOPBACK_IFINDEX; |
9ade22861 ipv4: Use flowi4 ... |
350 351 352 353 |
fl4.daddr = src; fl4.saddr = dst; fl4.flowi4_tos = tos; fl4.flowi4_scope = RT_SCOPE_UNIVERSE; |
1b7179d3a route: Extend flo... |
354 |
fl4.flowi4_tun_key.tun_id = 0; |
b84f78782 net: Initialize f... |
355 |
fl4.flowi4_flags = 0; |
8bcfd0925 ipv4: add missing... |
356 |
fl4.flowi4_uid = sock_net_uid(net, NULL); |
cc7e17ea0 ipv4: Optimize fl... |
357 |
|
9e56e3800 ipv4: Adjust in_d... |
358 |
no_addr = idev->ifa_list == NULL; |
990078afb Disable rp_filter... |
359 |
|
9e56e3800 ipv4: Adjust in_d... |
360 |
fl4.flowi4_mark = IN_DEV_SRC_VMARK(idev) ? skb->mark : 0; |
5a847a6e1 net/ipv4: Initial... |
361 362 363 364 365 |
if (!fib4_rules_early_flow_dissect(net, skb, &fl4, &flkeys)) { fl4.flowi4_proto = 0; fl4.fl4_sport = 0; fl4.fl4_dport = 0; } |
1da177e4c Linux-2.6.12-rc2 |
366 |
|
0eeb075fa net: ipv4 sysctl ... |
367 |
if (fib_lookup(net, &fl4, &res, 0)) |
1da177e4c Linux-2.6.12-rc2 |
368 |
goto last_resort; |
1dced6a85 ipv4: Restore acc... |
369 370 371 |
if (res.type != RTN_UNICAST && (res.type != RTN_LOCAL || !IN_DEV_ACCEPT_LOCAL(idev))) goto e_inval; |
1da177e4c Linux-2.6.12-rc2 |
372 |
fib_combine_itag(itag, &res); |
6f86b3251 ipv4: Fix reverse... |
373 |
|
78f2756c5 net/ipv4: Move de... |
374 |
dev_match = fib_info_nh_uses_dev(res.fi, dev); |
66f820954 fib: relax source... |
375 376 377 378 379 |
/* This is not common, loopback packets retain skb_dst so normally they * would not even hit this slow path. */ dev_match = dev_match || (res.type == RTN_LOCAL && dev == net->loopback_dev); |
6f86b3251 ipv4: Fix reverse... |
380 |
if (dev_match) { |
eba618aba ipv4: Add fib_nh_... |
381 |
ret = FIB_RES_NHC(res)->nhc_scope >= RT_SCOPE_HOST; |
1da177e4c Linux-2.6.12-rc2 |
382 383 |
return ret; } |
1da177e4c Linux-2.6.12-rc2 |
384 385 |
if (no_addr) goto last_resort; |
c1cf8422f ip: add loose rev... |
386 |
if (rpf == 1) |
b5f7e7554 ipv4: add LINUX_M... |
387 |
goto e_rpf; |
9ade22861 ipv4: Use flowi4 ... |
388 |
fl4.flowi4_oif = dev->ifindex; |
1da177e4c Linux-2.6.12-rc2 |
389 390 |
ret = 0; |
0eeb075fa net: ipv4 sysctl ... |
391 |
if (fib_lookup(net, &fl4, &res, FIB_LOOKUP_IGNORE_LINKSTATE) == 0) { |
41347dcdd ipv4: Kill rt->rt... |
392 |
if (res.type == RTN_UNICAST) |
eba618aba ipv4: Add fib_nh_... |
393 |
ret = FIB_RES_NHC(res)->nhc_scope >= RT_SCOPE_HOST; |
1da177e4c Linux-2.6.12-rc2 |
394 395 396 397 398 |
} return ret; last_resort: if (rpf) |
b5f7e7554 ipv4: add LINUX_M... |
399 |
goto e_rpf; |
1da177e4c Linux-2.6.12-rc2 |
400 401 |
*itag = 0; return 0; |
1da177e4c Linux-2.6.12-rc2 |
402 403 |
e_inval: return -EINVAL; |
b5f7e7554 ipv4: add LINUX_M... |
404 405 |
e_rpf: return -EXDEV; |
1da177e4c Linux-2.6.12-rc2 |
406 |
} |
7a9bc9b81 ipv4: Elide fib_v... |
407 408 409 410 411 412 |
/* Ignore rp_filter for packets protected by IPsec. */ int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst, u8 tos, int oif, struct net_device *dev, struct in_device *idev, u32 *itag) { int r = secpath_exists(skb) ? 0 : IN_DEV_RPFILTER(idev); |
6e617de84 net: avoid a full... |
413 |
struct net *net = dev_net(dev); |
7a9bc9b81 ipv4: Elide fib_v... |
414 |
|
6e617de84 net: avoid a full... |
415 |
if (!r && !fib_num_tclassid_users(net) && |
e81da0e11 ipv4: fix sending... |
416 |
(dev->ifindex != oif || !IN_DEV_TX_REDIRECTS(idev))) { |
6e617de84 net: avoid a full... |
417 418 |
if (IN_DEV_ACCEPT_LOCAL(idev)) goto ok; |
032a48020 ipv4: fix validat... |
419 420 421 |
/* with custom local routes in place, checking local addresses * only will be too optimistic, with custom rules, checking * local addresses only can be too strict, e.g. due to vrf |
6e617de84 net: avoid a full... |
422 |
*/ |
032a48020 ipv4: fix validat... |
423 424 |
if (net->ipv4.fib_has_custom_local_routes || fib4_has_custom_rules(net)) |
6e617de84 net: avoid a full... |
425 426 427 428 429 |
goto full_check; if (inet_lookup_ifaddr_rcu(net, src)) return -EINVAL; ok: |
7a9bc9b81 ipv4: Elide fib_v... |
430 431 432 |
*itag = 0; return 0; } |
6e617de84 net: avoid a full... |
433 434 |
full_check: |
7a9bc9b81 ipv4: Elide fib_v... |
435 436 |
return __fib_validate_source(skb, src, dst, tos, oif, dev, r, idev, itag); } |
81f7bf6cb [IPV4]: net/ipv4/... |
437 |
static inline __be32 sk_extract_addr(struct sockaddr *addr) |
4e902c574 [IPv4]: FIB confi... |
438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 |
{ return ((struct sockaddr_in *) addr)->sin_addr.s_addr; } static int put_rtax(struct nlattr *mx, int len, int type, u32 value) { struct nlattr *nla; nla = (struct nlattr *) ((char *) mx + len); nla->nla_type = type; nla->nla_len = nla_attr_size(4); *(u32 *) nla_data(nla) = value; return len + nla_total_size(4); } |
4b5d47d4d [NETNS]: Correctl... |
453 |
static int rtentry_to_fib_config(struct net *net, int cmd, struct rtentry *rt, |
4e902c574 [IPv4]: FIB confi... |
454 455 |
struct fib_config *cfg) { |
6d85c10ab [IPV4]: struct fi... |
456 |
__be32 addr; |
4e902c574 [IPv4]: FIB confi... |
457 458 459 |
int plen; memset(cfg, 0, sizeof(*cfg)); |
4b5d47d4d [NETNS]: Correctl... |
460 |
cfg->fc_nlinfo.nl_net = net; |
4e902c574 [IPv4]: FIB confi... |
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 |
if (rt->rt_dst.sa_family != AF_INET) return -EAFNOSUPPORT; /* * Check mask for validity: * a) it must be contiguous. * b) destination must have all host bits clear. * c) if application forgot to set correct family (AF_INET), * reject request unless it is absolutely clear i.e. * both family and mask are zero. */ plen = 32; addr = sk_extract_addr(&rt->rt_dst); if (!(rt->rt_flags & RTF_HOST)) { |
81f7bf6cb [IPV4]: net/ipv4/... |
476 |
__be32 mask = sk_extract_addr(&rt->rt_genmask); |
4e902c574 [IPv4]: FIB confi... |
477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 |
if (rt->rt_genmask.sa_family != AF_INET) { if (mask || rt->rt_genmask.sa_family) return -EAFNOSUPPORT; } if (bad_mask(mask, addr)) return -EINVAL; plen = inet_mask_len(mask); } cfg->fc_dst_len = plen; cfg->fc_dst = addr; if (cmd != SIOCDELRT) { cfg->fc_nlflags = NLM_F_CREATE; cfg->fc_protocol = RTPROT_BOOT; } if (rt->rt_metric) cfg->fc_priority = rt->rt_metric - 1; if (rt->rt_flags & RTF_REJECT) { cfg->fc_scope = RT_SCOPE_HOST; cfg->fc_type = RTN_UNREACHABLE; return 0; } cfg->fc_scope = RT_SCOPE_NOWHERE; cfg->fc_type = RTN_UNICAST; if (rt->rt_dev) { char *colon; struct net_device *dev; char devname[IFNAMSIZ]; if (copy_from_user(devname, rt->rt_dev, IFNAMSIZ-1)) return -EFAULT; devname[IFNAMSIZ-1] = 0; colon = strchr(devname, ':'); if (colon) *colon = 0; |
4b5d47d4d [NETNS]: Correctl... |
521 |
dev = __dev_get_by_name(net, devname); |
4e902c574 [IPv4]: FIB confi... |
522 523 524 |
if (!dev) return -ENODEV; cfg->fc_oif = dev->ifindex; |
5a56a0b3a net: Don't delete... |
525 |
cfg->fc_table = l3mdev_fib_table(dev); |
4e902c574 [IPv4]: FIB confi... |
526 |
if (colon) { |
cd5a411db net: use new in_d... |
527 528 529 530 |
const struct in_ifaddr *ifa; struct in_device *in_dev; in_dev = __in_dev_get_rtnl(dev); |
4e902c574 [IPv4]: FIB confi... |
531 532 |
if (!in_dev) return -ENODEV; |
cd5a411db net: use new in_d... |
533 |
|
4e902c574 [IPv4]: FIB confi... |
534 |
*colon = ':'; |
cd5a411db net: use new in_d... |
535 536 537 |
rcu_read_lock(); in_dev_for_each_ifa_rcu(ifa, in_dev) { |
4e902c574 [IPv4]: FIB confi... |
538 539 |
if (strcmp(ifa->ifa_label, devname) == 0) break; |
cd5a411db net: use new in_d... |
540 541 |
} rcu_read_unlock(); |
51456b291 ipv4: coding styl... |
542 |
if (!ifa) |
4e902c574 [IPv4]: FIB confi... |
543 544 545 546 547 548 549 |
return -ENODEV; cfg->fc_prefsrc = ifa->ifa_local; } } addr = sk_extract_addr(&rt->rt_gateway); if (rt->rt_gateway.sa_family == AF_INET && addr) { |
30bbaa195 net: Fix up inet_... |
550 |
unsigned int addr_type; |
f35b794b3 ipv4: Prepare fib... |
551 552 |
cfg->fc_gw4 = addr; cfg->fc_gw_family = AF_INET; |
30bbaa195 net: Fix up inet_... |
553 |
addr_type = inet_addr_type_table(net, addr, cfg->fc_table); |
4e902c574 [IPv4]: FIB confi... |
554 |
if (rt->rt_flags & RTF_GATEWAY && |
30bbaa195 net: Fix up inet_... |
555 |
addr_type == RTN_UNICAST) |
4e902c574 [IPv4]: FIB confi... |
556 557 558 559 560 |
cfg->fc_scope = RT_SCOPE_UNIVERSE; } if (cmd == SIOCDELRT) return 0; |
f35b794b3 ipv4: Prepare fib... |
561 |
if (rt->rt_flags & RTF_GATEWAY && !cfg->fc_gw_family) |
4e902c574 [IPv4]: FIB confi... |
562 563 564 565 566 567 568 569 |
return -EINVAL; if (cfg->fc_scope == RT_SCOPE_NOWHERE) cfg->fc_scope = RT_SCOPE_LINK; if (rt->rt_flags & (RTF_MTU | RTF_WINDOW | RTF_IRTT)) { struct nlattr *mx; int len = 0; |
6396bb221 treewide: kzalloc... |
570 |
mx = kcalloc(3, nla_total_size(4), GFP_KERNEL); |
51456b291 ipv4: coding styl... |
571 |
if (!mx) |
4e902c574 [IPv4]: FIB confi... |
572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 |
return -ENOMEM; if (rt->rt_flags & RTF_MTU) len = put_rtax(mx, len, RTAX_ADVMSS, rt->rt_mtu - 40); if (rt->rt_flags & RTF_WINDOW) len = put_rtax(mx, len, RTAX_WINDOW, rt->rt_window); if (rt->rt_flags & RTF_IRTT) len = put_rtax(mx, len, RTAX_RTT, rt->rt_irtt << 3); cfg->fc_mx = mx; cfg->fc_mx_len = len; } return 0; } |
1da177e4c Linux-2.6.12-rc2 |
589 |
/* |
6a31d2a97 fib: cleanups |
590 591 |
* Handle IP routing ioctl calls. * These are used to manipulate the routing tables |
1da177e4c Linux-2.6.12-rc2 |
592 |
*/ |
ca25c3004 ip_rt_ioctl(): ta... |
593 |
int ip_rt_ioctl(struct net *net, unsigned int cmd, struct rtentry *rt) |
1da177e4c Linux-2.6.12-rc2 |
594 |
{ |
4e902c574 [IPv4]: FIB confi... |
595 |
struct fib_config cfg; |
1da177e4c Linux-2.6.12-rc2 |
596 |
int err; |
1da177e4c Linux-2.6.12-rc2 |
597 598 599 600 |
switch (cmd) { case SIOCADDRT: /* Add a route */ case SIOCDELRT: /* Delete a route */ |
52e804c6d net: Allow userns... |
601 |
if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) |
1da177e4c Linux-2.6.12-rc2 |
602 |
return -EPERM; |
4e902c574 [IPv4]: FIB confi... |
603 |
|
1da177e4c Linux-2.6.12-rc2 |
604 |
rtnl_lock(); |
ca25c3004 ip_rt_ioctl(): ta... |
605 |
err = rtentry_to_fib_config(net, cmd, rt, &cfg); |
1da177e4c Linux-2.6.12-rc2 |
606 |
if (err == 0) { |
4e902c574 [IPv4]: FIB confi... |
607 |
struct fib_table *tb; |
1da177e4c Linux-2.6.12-rc2 |
608 |
if (cmd == SIOCDELRT) { |
1bad118a3 [NETNS]: Pass nam... |
609 |
tb = fib_get_table(net, cfg.fc_table); |
1da177e4c Linux-2.6.12-rc2 |
610 |
if (tb) |
780559989 net: ipv4: Add ex... |
611 612 |
err = fib_table_delete(net, tb, &cfg, NULL); |
4e902c574 [IPv4]: FIB confi... |
613 614 |
else err = -ESRCH; |
1da177e4c Linux-2.6.12-rc2 |
615 |
} else { |
1bad118a3 [NETNS]: Pass nam... |
616 |
tb = fib_new_table(net, cfg.fc_table); |
1da177e4c Linux-2.6.12-rc2 |
617 |
if (tb) |
6d8422a17 net: ipv4: Plumb ... |
618 619 |
err = fib_table_insert(net, tb, &cfg, NULL); |
4e902c574 [IPv4]: FIB confi... |
620 621 |
else err = -ENOBUFS; |
1da177e4c Linux-2.6.12-rc2 |
622 |
} |
4e902c574 [IPv4]: FIB confi... |
623 624 625 |
/* allocated by rtentry_to_fib_config() */ kfree(cfg.fc_mx); |
1da177e4c Linux-2.6.12-rc2 |
626 627 628 629 630 631 |
} rtnl_unlock(); return err; } return -EINVAL; } |
6a31d2a97 fib: cleanups |
632 |
const struct nla_policy rtm_ipv4_policy[RTA_MAX + 1] = { |
75425657f net: Set strict_s... |
633 |
[RTA_UNSPEC] = { .strict_start_type = RTA_DPORT + 1 }, |
4e902c574 [IPv4]: FIB confi... |
634 635 636 637 638 639 640 641 |
[RTA_DST] = { .type = NLA_U32 }, [RTA_SRC] = { .type = NLA_U32 }, [RTA_IIF] = { .type = NLA_U32 }, [RTA_OIF] = { .type = NLA_U32 }, [RTA_GATEWAY] = { .type = NLA_U32 }, [RTA_PRIORITY] = { .type = NLA_U32 }, [RTA_PREFSRC] = { .type = NLA_U32 }, [RTA_METRICS] = { .type = NLA_NESTED }, |
5176f91ea [NETLINK]: Make u... |
642 |
[RTA_MULTIPATH] = { .len = sizeof(struct rtnexthop) }, |
4e902c574 [IPv4]: FIB confi... |
643 |
[RTA_FLOW] = { .type = NLA_U32 }, |
571e72267 ipv4: support for... |
644 645 |
[RTA_ENCAP_TYPE] = { .type = NLA_U16 }, [RTA_ENCAP] = { .type = NLA_NESTED }, |
622ec2c9d net: core: add UI... |
646 |
[RTA_UID] = { .type = NLA_U32 }, |
3b45a4106 net: route: add m... |
647 |
[RTA_MARK] = { .type = NLA_U32 }, |
2eabd764c net: ipv4: add mi... |
648 |
[RTA_TABLE] = { .type = NLA_U32 }, |
404eb77ea ipv4: support spo... |
649 650 651 |
[RTA_IP_PROTO] = { .type = NLA_U8 }, [RTA_SPORT] = { .type = NLA_U16 }, [RTA_DPORT] = { .type = NLA_U16 }, |
493ced1ac ipv4: Allow route... |
652 |
[RTA_NH_ID] = { .type = NLA_U32 }, |
4e902c574 [IPv4]: FIB confi... |
653 |
}; |
d15662682 ipv4: Allow ipv6 ... |
654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 |
int fib_gw_from_via(struct fib_config *cfg, struct nlattr *nla, struct netlink_ext_ack *extack) { struct rtvia *via; int alen; if (nla_len(nla) < offsetof(struct rtvia, rtvia_addr)) { NL_SET_ERR_MSG(extack, "Invalid attribute length for RTA_VIA"); return -EINVAL; } via = nla_data(nla); alen = nla_len(nla) - offsetof(struct rtvia, rtvia_addr); switch (via->rtvia_family) { case AF_INET: if (alen != sizeof(__be32)) { NL_SET_ERR_MSG(extack, "Invalid IPv4 address in RTA_VIA"); return -EINVAL; } cfg->fc_gw_family = AF_INET; cfg->fc_gw4 = *((__be32 *)via->rtvia_addr); break; case AF_INET6: #ifdef CONFIG_IPV6 if (alen != sizeof(struct in6_addr)) { NL_SET_ERR_MSG(extack, "Invalid IPv6 address in RTA_VIA"); return -EINVAL; } cfg->fc_gw_family = AF_INET6; cfg->fc_gw6 = *((struct in6_addr *)via->rtvia_addr); #else NL_SET_ERR_MSG(extack, "IPv6 support not enabled in kernel"); return -EINVAL; #endif break; default: NL_SET_ERR_MSG(extack, "Unsupported address family in RTA_VIA"); return -EINVAL; } return 0; } |
4b5d47d4d [NETNS]: Correctl... |
697 |
static int rtm_to_fib_config(struct net *net, struct sk_buff *skb, |
6d8422a17 net: ipv4: Plumb ... |
698 699 |
struct nlmsghdr *nlh, struct fib_config *cfg, struct netlink_ext_ack *extack) |
1da177e4c Linux-2.6.12-rc2 |
700 |
{ |
d15662682 ipv4: Allow ipv6 ... |
701 |
bool has_gw = false, has_via = false; |
4e902c574 [IPv4]: FIB confi... |
702 703 704 |
struct nlattr *attr; int err, remaining; struct rtmsg *rtm; |
8cb081746 netlink: make val... |
705 706 |
err = nlmsg_validate_deprecated(nlh, sizeof(*rtm), RTA_MAX, rtm_ipv4_policy, extack); |
4e902c574 [IPv4]: FIB confi... |
707 708 709 710 711 712 |
if (err < 0) goto errout; memset(cfg, 0, sizeof(*cfg)); rtm = nlmsg_data(nlh); |
4e902c574 [IPv4]: FIB confi... |
713 |
cfg->fc_dst_len = rtm->rtm_dst_len; |
4e902c574 [IPv4]: FIB confi... |
714 715 716 717 718 719 720 |
cfg->fc_tos = rtm->rtm_tos; cfg->fc_table = rtm->rtm_table; cfg->fc_protocol = rtm->rtm_protocol; cfg->fc_scope = rtm->rtm_scope; cfg->fc_type = rtm->rtm_type; cfg->fc_flags = rtm->rtm_flags; cfg->fc_nlflags = nlh->nlmsg_flags; |
15e473046 netlink: Rename p... |
721 |
cfg->fc_nlinfo.portid = NETLINK_CB(skb).portid; |
4e902c574 [IPv4]: FIB confi... |
722 |
cfg->fc_nlinfo.nlh = nlh; |
4b5d47d4d [NETNS]: Correctl... |
723 |
cfg->fc_nlinfo.nl_net = net; |
4e902c574 [IPv4]: FIB confi... |
724 |
|
a0ee18b9b [IPv4] fib: Fix o... |
725 |
if (cfg->fc_type > RTN_MAX) { |
c3ab2b4ec net: ipv4: Add ex... |
726 |
NL_SET_ERR_MSG(extack, "Invalid route type"); |
a0ee18b9b [IPv4] fib: Fix o... |
727 728 729 |
err = -EINVAL; goto errout; } |
4e902c574 [IPv4]: FIB confi... |
730 |
nlmsg_for_each_attr(attr, nlh, sizeof(struct rtmsg), remaining) { |
8f4c1f9b0 [NETLINK]: Introd... |
731 |
switch (nla_type(attr)) { |
4e902c574 [IPv4]: FIB confi... |
732 |
case RTA_DST: |
17fb2c643 [IPV4]: RTA_{DST,... |
733 |
cfg->fc_dst = nla_get_be32(attr); |
4e902c574 [IPv4]: FIB confi... |
734 |
break; |
4e902c574 [IPv4]: FIB confi... |
735 736 737 738 |
case RTA_OIF: cfg->fc_oif = nla_get_u32(attr); break; case RTA_GATEWAY: |
d15662682 ipv4: Allow ipv6 ... |
739 |
has_gw = true; |
f35b794b3 ipv4: Prepare fib... |
740 |
cfg->fc_gw4 = nla_get_be32(attr); |
d73f80f92 ipv4: Handle RTA_... |
741 742 |
if (cfg->fc_gw4) cfg->fc_gw_family = AF_INET; |
4e902c574 [IPv4]: FIB confi... |
743 |
break; |
b6e9e5df4 ipv4: Return erro... |
744 |
case RTA_VIA: |
d15662682 ipv4: Allow ipv6 ... |
745 746 747 748 749 |
has_via = true; err = fib_gw_from_via(cfg, attr, extack); if (err) goto errout; break; |
4e902c574 [IPv4]: FIB confi... |
750 751 752 753 |
case RTA_PRIORITY: cfg->fc_priority = nla_get_u32(attr); break; case RTA_PREFSRC: |
17fb2c643 [IPV4]: RTA_{DST,... |
754 |
cfg->fc_prefsrc = nla_get_be32(attr); |
4e902c574 [IPv4]: FIB confi... |
755 756 757 758 759 760 |
break; case RTA_METRICS: cfg->fc_mx = nla_data(attr); cfg->fc_mx_len = nla_len(attr); break; case RTA_MULTIPATH: |
9ed59592e lwtunnel: fix aut... |
761 |
err = lwtunnel_valid_encap_type_attr(nla_data(attr), |
c255bd681 net: lwtunnel: Ad... |
762 763 |
nla_len(attr), extack); |
9ed59592e lwtunnel: fix aut... |
764 765 |
if (err < 0) goto errout; |
4e902c574 [IPv4]: FIB confi... |
766 767 768 769 770 771 |
cfg->fc_mp = nla_data(attr); cfg->fc_mp_len = nla_len(attr); break; case RTA_FLOW: cfg->fc_flow = nla_get_u32(attr); break; |
4e902c574 [IPv4]: FIB confi... |
772 773 774 |
case RTA_TABLE: cfg->fc_table = nla_get_u32(attr); break; |
571e72267 ipv4: support for... |
775 776 777 778 779 |
case RTA_ENCAP: cfg->fc_encap = attr; break; case RTA_ENCAP_TYPE: cfg->fc_encap_type = nla_get_u16(attr); |
c255bd681 net: lwtunnel: Ad... |
780 781 |
err = lwtunnel_valid_encap_type(cfg->fc_encap_type, extack); |
9ed59592e lwtunnel: fix aut... |
782 783 |
if (err < 0) goto errout; |
571e72267 ipv4: support for... |
784 |
break; |
493ced1ac ipv4: Allow route... |
785 786 787 788 789 790 791 792 793 794 795 796 |
case RTA_NH_ID: cfg->fc_nh_id = nla_get_u32(attr); break; } } if (cfg->fc_nh_id) { if (cfg->fc_oif || cfg->fc_gw_family || cfg->fc_encap || cfg->fc_mp) { NL_SET_ERR_MSG(extack, "Nexthop specification and nexthop id are mutually exclusive"); return -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
797 798 |
} } |
4e902c574 [IPv4]: FIB confi... |
799 |
|
d15662682 ipv4: Allow ipv6 ... |
800 801 802 803 804 |
if (has_gw && has_via) { NL_SET_ERR_MSG(extack, "Nexthop configuration can not contain both GATEWAY and VIA"); goto errout; } |
1da177e4c Linux-2.6.12-rc2 |
805 |
return 0; |
4e902c574 [IPv4]: FIB confi... |
806 807 |
errout: return err; |
1da177e4c Linux-2.6.12-rc2 |
808 |
} |
c21ef3e34 net: rtnetlink: p... |
809 810 |
static int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh, struct netlink_ext_ack *extack) |
1da177e4c Linux-2.6.12-rc2 |
811 |
{ |
3b1e0a655 [NET] NETNS: Omit... |
812 |
struct net *net = sock_net(skb->sk); |
4e902c574 [IPv4]: FIB confi... |
813 814 815 |
struct fib_config cfg; struct fib_table *tb; int err; |
1da177e4c Linux-2.6.12-rc2 |
816 |
|
6d8422a17 net: ipv4: Plumb ... |
817 |
err = rtm_to_fib_config(net, skb, nlh, &cfg, extack); |
4e902c574 [IPv4]: FIB confi... |
818 819 |
if (err < 0) goto errout; |
1da177e4c Linux-2.6.12-rc2 |
820 |
|
493ced1ac ipv4: Allow route... |
821 822 823 824 825 |
if (cfg.fc_nh_id && !nexthop_find_by_id(net, cfg.fc_nh_id)) { NL_SET_ERR_MSG(extack, "Nexthop id does not exist"); err = -EINVAL; goto errout; } |
8ad4942cd [NETNS]: Add netn... |
826 |
tb = fib_get_table(net, cfg.fc_table); |
51456b291 ipv4: coding styl... |
827 |
if (!tb) { |
c3ab2b4ec net: ipv4: Add ex... |
828 |
NL_SET_ERR_MSG(extack, "FIB table does not exist"); |
4e902c574 [IPv4]: FIB confi... |
829 830 831 |
err = -ESRCH; goto errout; } |
780559989 net: ipv4: Add ex... |
832 |
err = fib_table_delete(net, tb, &cfg, extack); |
4e902c574 [IPv4]: FIB confi... |
833 834 |
errout: return err; |
1da177e4c Linux-2.6.12-rc2 |
835 |
} |
c21ef3e34 net: rtnetlink: p... |
836 837 |
static int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh, struct netlink_ext_ack *extack) |
1da177e4c Linux-2.6.12-rc2 |
838 |
{ |
3b1e0a655 [NET] NETNS: Omit... |
839 |
struct net *net = sock_net(skb->sk); |
4e902c574 [IPv4]: FIB confi... |
840 841 842 |
struct fib_config cfg; struct fib_table *tb; int err; |
1da177e4c Linux-2.6.12-rc2 |
843 |
|
6d8422a17 net: ipv4: Plumb ... |
844 |
err = rtm_to_fib_config(net, skb, nlh, &cfg, extack); |
4e902c574 [IPv4]: FIB confi... |
845 846 |
if (err < 0) goto errout; |
1da177e4c Linux-2.6.12-rc2 |
847 |
|
226b0b4a5 [NETNS]: Replace ... |
848 |
tb = fib_new_table(net, cfg.fc_table); |
51456b291 ipv4: coding styl... |
849 |
if (!tb) { |
4e902c574 [IPv4]: FIB confi... |
850 851 852 |
err = -ENOBUFS; goto errout; } |
6d8422a17 net: ipv4: Plumb ... |
853 |
err = fib_table_insert(net, tb, &cfg, extack); |
6e617de84 net: avoid a full... |
854 855 |
if (!err && cfg.fc_type == RTN_LOCAL) net->ipv4.fib_has_custom_local_routes = true; |
4e902c574 [IPv4]: FIB confi... |
856 857 |
errout: return err; |
1da177e4c Linux-2.6.12-rc2 |
858 |
} |
4724676d5 net: Add struct f... |
859 860 |
int ip_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh, struct fib_dump_filter *filter, |
effe67926 net: Enable kerne... |
861 |
struct netlink_callback *cb) |
e8ba330ac rtnetlink: Update... |
862 |
{ |
effe67926 net: Enable kerne... |
863 864 |
struct netlink_ext_ack *extack = cb->extack; struct nlattr *tb[RTA_MAX + 1]; |
e8ba330ac rtnetlink: Update... |
865 |
struct rtmsg *rtm; |
effe67926 net: Enable kerne... |
866 867 868 |
int err, i; ASSERT_RTNL(); |
e8ba330ac rtnetlink: Update... |
869 870 871 872 873 874 875 876 |
if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*rtm))) { NL_SET_ERR_MSG(extack, "Invalid header for FIB dump request"); return -EINVAL; } rtm = nlmsg_data(nlh); if (rtm->rtm_dst_len || rtm->rtm_src_len || rtm->rtm_tos || |
effe67926 net: Enable kerne... |
877 |
rtm->rtm_scope) { |
e8ba330ac rtnetlink: Update... |
878 879 880 |
NL_SET_ERR_MSG(extack, "Invalid values in header for FIB dump request"); return -EINVAL; } |
564c91f7e fib_frontend, ip6... |
881 |
|
e8ba330ac rtnetlink: Update... |
882 883 884 885 |
if (rtm->rtm_flags & ~(RTM_F_CLONED | RTM_F_PREFIX)) { NL_SET_ERR_MSG(extack, "Invalid flags for FIB dump request"); return -EINVAL; } |
564c91f7e fib_frontend, ip6... |
886 887 888 889 |
if (rtm->rtm_flags & RTM_F_CLONED) filter->dump_routes = false; else filter->dump_exceptions = false; |
e8ba330ac rtnetlink: Update... |
890 |
|
ae677bbb4 net: Don't return... |
891 |
filter->dump_all_families = (rtm->rtm_family == AF_UNSPEC); |
effe67926 net: Enable kerne... |
892 893 894 895 |
filter->flags = rtm->rtm_flags; filter->protocol = rtm->rtm_protocol; filter->rt_type = rtm->rtm_type; filter->table_id = rtm->rtm_table; |
8cb081746 netlink: make val... |
896 897 |
err = nlmsg_parse_deprecated_strict(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv4_policy, extack); |
effe67926 net: Enable kerne... |
898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 |
if (err < 0) return err; for (i = 0; i <= RTA_MAX; ++i) { int ifindex; if (!tb[i]) continue; switch (i) { case RTA_TABLE: filter->table_id = nla_get_u32(tb[i]); break; case RTA_OIF: ifindex = nla_get_u32(tb[i]); filter->dev = __dev_get_by_index(net, ifindex); if (!filter->dev) return -ENODEV; break; default: NL_SET_ERR_MSG(extack, "Unsupported attribute in dump request"); return -EINVAL; } } if (filter->flags || filter->protocol || filter->rt_type || filter->table_id || filter->dev) { filter->filter_set = 1; cb->answer_flags = NLM_F_DUMP_FILTERED; |
e8ba330ac rtnetlink: Update... |
927 928 929 930 931 |
} return 0; } EXPORT_SYMBOL_GPL(ip_valid_fib_dump_req); |
63f3444fb [IPv4]: Use rtnl ... |
932 |
static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) |
1da177e4c Linux-2.6.12-rc2 |
933 |
{ |
564c91f7e fib_frontend, ip6... |
934 935 |
struct fib_dump_filter filter = { .dump_routes = true, .dump_exceptions = true }; |
e8ba330ac rtnetlink: Update... |
936 |
const struct nlmsghdr *nlh = cb->nlh; |
3b1e0a655 [NET] NETNS: Omit... |
937 |
struct net *net = sock_net(skb->sk); |
1af5a8c4a [IPV4]: Increase ... |
938 939 |
unsigned int h, s_h; unsigned int e = 0, s_e; |
1da177e4c Linux-2.6.12-rc2 |
940 |
struct fib_table *tb; |
e4aef8aea [NETNS]: Place fi... |
941 |
struct hlist_head *head; |
f6c5775ff net: Improve hand... |
942 |
int dumped = 0, err; |
1da177e4c Linux-2.6.12-rc2 |
943 |
|
e8ba330ac rtnetlink: Update... |
944 |
if (cb->strict_check) { |
effe67926 net: Enable kerne... |
945 |
err = ip_valid_fib_dump_req(net, nlh, &filter, cb); |
e8ba330ac rtnetlink: Update... |
946 947 |
if (err < 0) return err; |
e4e92fb16 net/ipv4: Bail ea... |
948 949 950 951 |
} else if (nlmsg_len(nlh) >= sizeof(struct rtmsg)) { struct rtmsg *rtm = nlmsg_data(nlh); filter.flags = rtm->rtm_flags & (RTM_F_PREFIX | RTM_F_CLONED); |
e8ba330ac rtnetlink: Update... |
952 |
} |
b597ca6e8 ipv4/fib_frontend... |
953 954 |
/* ipv4 does not use prefix flag */ if (filter.flags & RTM_F_PREFIX) |
0b8c7f6f2 ipv4: remove ip_r... |
955 |
return skb->len; |
1da177e4c Linux-2.6.12-rc2 |
956 |
|
18a8021a7 net/ipv4: Plumb s... |
957 958 959 |
if (filter.table_id) { tb = fib_get_table(net, filter.table_id); if (!tb) { |
ae677bbb4 net: Don't return... |
960 961 |
if (filter.dump_all_families) return skb->len; |
18a8021a7 net/ipv4: Plumb s... |
962 963 964 965 966 967 968 |
NL_SET_ERR_MSG(cb->extack, "ipv4: FIB table does not exist"); return -ENOENT; } err = fib_table_dump(tb, skb, cb, &filter); return skb->len ? : err; } |
1af5a8c4a [IPV4]: Increase ... |
969 970 |
s_h = cb->args[0]; s_e = cb->args[1]; |
a7e535312 fib_trie: Make fi... |
971 |
rcu_read_lock(); |
1af5a8c4a [IPV4]: Increase ... |
972 973 |
for (h = s_h; h < FIB_TABLE_HASHSZ; h++, s_e = 0) { e = 0; |
e4aef8aea [NETNS]: Place fi... |
974 |
head = &net->ipv4.fib_table_hash[h]; |
a7e535312 fib_trie: Make fi... |
975 |
hlist_for_each_entry_rcu(tb, head, tb_hlist) { |
1af5a8c4a [IPV4]: Increase ... |
976 977 978 979 |
if (e < s_e) goto next; if (dumped) memset(&cb->args[2], 0, sizeof(cb->args) - |
e905a9eda [NET] IPV4: Fix w... |
980 |
2 * sizeof(cb->args[0])); |
18a8021a7 net/ipv4: Plumb s... |
981 |
err = fib_table_dump(tb, skb, cb, &filter); |
f6c5775ff net: Improve hand... |
982 983 984 985 986 987 |
if (err < 0) { if (likely(skb->len)) goto out; goto out_err; } |
1af5a8c4a [IPV4]: Increase ... |
988 989 990 991 |
dumped = 1; next: e++; } |
1da177e4c Linux-2.6.12-rc2 |
992 |
} |
1af5a8c4a [IPV4]: Increase ... |
993 |
out: |
f6c5775ff net: Improve hand... |
994 995 |
err = skb->len; out_err: |
a7e535312 fib_trie: Make fi... |
996 |
rcu_read_unlock(); |
1af5a8c4a [IPV4]: Increase ... |
997 998 |
cb->args[1] = e; cb->args[0] = h; |
1da177e4c Linux-2.6.12-rc2 |
999 |
|
f6c5775ff net: Improve hand... |
1000 |
return err; |
1da177e4c Linux-2.6.12-rc2 |
1001 1002 1003 |
} /* Prepare and feed intra-kernel routing request. |
6a31d2a97 fib: cleanups |
1004 1005 1006 1007 |
* Really, it should be netlink message, but :-( netlink * can be not configured, so that we feed it directly * to fib engine. It is legal, because all events occur * only when netlink is already locked. |
1da177e4c Linux-2.6.12-rc2 |
1008 |
*/ |
af4d768ad net/ipv4: Add sup... |
1009 1010 |
static void fib_magic(int cmd, int type, __be32 dst, int dst_len, struct in_ifaddr *ifa, u32 rt_priority) |
1da177e4c Linux-2.6.12-rc2 |
1011 |
{ |
c346dca10 [NET] NETNS: Omit... |
1012 |
struct net *net = dev_net(ifa->ifa_dev->dev); |
3236b0042 net: Replace vrf_... |
1013 |
u32 tb_id = l3mdev_fib_table(ifa->ifa_dev->dev); |
4e902c574 [IPv4]: FIB confi... |
1014 1015 1016 1017 1018 1019 |
struct fib_table *tb; struct fib_config cfg = { .fc_protocol = RTPROT_KERNEL, .fc_type = type, .fc_dst = dst, .fc_dst_len = dst_len, |
af4d768ad net/ipv4: Add sup... |
1020 |
.fc_priority = rt_priority, |
4e902c574 [IPv4]: FIB confi... |
1021 1022 1023 |
.fc_prefsrc = ifa->ifa_local, .fc_oif = ifa->ifa_dev->dev->ifindex, .fc_nlflags = NLM_F_CREATE | NLM_F_APPEND, |
4d1169c1e [NETNS]: Add netn... |
1024 |
.fc_nlinfo = { |
4b5d47d4d [NETNS]: Correctl... |
1025 |
.nl_net = net, |
4d1169c1e [NETNS]: Add netn... |
1026 |
}, |
4e902c574 [IPv4]: FIB confi... |
1027 |
}; |
1da177e4c Linux-2.6.12-rc2 |
1028 |
|
021dd3b8a net: Add routes t... |
1029 1030 |
if (!tb_id) tb_id = (type == RTN_UNICAST) ? RT_TABLE_MAIN : RT_TABLE_LOCAL; |
1da177e4c Linux-2.6.12-rc2 |
1031 |
|
021dd3b8a net: Add routes t... |
1032 |
tb = fib_new_table(net, tb_id); |
51456b291 ipv4: coding styl... |
1033 |
if (!tb) |
1da177e4c Linux-2.6.12-rc2 |
1034 |
return; |
4e902c574 [IPv4]: FIB confi... |
1035 |
cfg.fc_table = tb->tb_id; |
1da177e4c Linux-2.6.12-rc2 |
1036 |
|
4e902c574 [IPv4]: FIB confi... |
1037 1038 1039 1040 |
if (type != RTN_LOCAL) cfg.fc_scope = RT_SCOPE_LINK; else cfg.fc_scope = RT_SCOPE_HOST; |
1da177e4c Linux-2.6.12-rc2 |
1041 1042 |
if (cmd == RTM_NEWROUTE) |
6d8422a17 net: ipv4: Plumb ... |
1043 |
fib_table_insert(net, tb, &cfg, NULL); |
1da177e4c Linux-2.6.12-rc2 |
1044 |
else |
780559989 net: ipv4: Add ex... |
1045 |
fib_table_delete(net, tb, &cfg, NULL); |
1da177e4c Linux-2.6.12-rc2 |
1046 |
} |
0ff60a456 [IPV4]: Fix secon... |
1047 |
void fib_add_ifaddr(struct in_ifaddr *ifa) |
1da177e4c Linux-2.6.12-rc2 |
1048 1049 1050 1051 |
{ struct in_device *in_dev = ifa->ifa_dev; struct net_device *dev = in_dev->dev; struct in_ifaddr *prim = ifa; |
a144ea4b7 [IPV4]: annotate ... |
1052 1053 |
__be32 mask = ifa->ifa_mask; __be32 addr = ifa->ifa_local; |
6a31d2a97 fib: cleanups |
1054 |
__be32 prefix = ifa->ifa_address & mask; |
1da177e4c Linux-2.6.12-rc2 |
1055 |
|
6a31d2a97 fib: cleanups |
1056 |
if (ifa->ifa_flags & IFA_F_SECONDARY) { |
1da177e4c Linux-2.6.12-rc2 |
1057 |
prim = inet_ifa_byprefix(in_dev, prefix, mask); |
51456b291 ipv4: coding styl... |
1058 |
if (!prim) { |
058bd4d2a net: Convert prin... |
1059 1060 |
pr_warn("%s: bug: prim == NULL ", __func__); |
1da177e4c Linux-2.6.12-rc2 |
1061 1062 1063 |
return; } } |
af4d768ad net/ipv4: Add sup... |
1064 |
fib_magic(RTM_NEWROUTE, RTN_LOCAL, addr, 32, prim, 0); |
1da177e4c Linux-2.6.12-rc2 |
1065 |
|
6a31d2a97 fib: cleanups |
1066 |
if (!(dev->flags & IFF_UP)) |
1da177e4c Linux-2.6.12-rc2 |
1067 1068 1069 |
return; /* Add broadcast address, if it is explicitly assigned. */ |
a144ea4b7 [IPV4]: annotate ... |
1070 |
if (ifa->ifa_broadcast && ifa->ifa_broadcast != htonl(0xFFFFFFFF)) |
af4d768ad net/ipv4: Add sup... |
1071 1072 |
fib_magic(RTM_NEWROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim, 0); |
1da177e4c Linux-2.6.12-rc2 |
1073 |
|
6a31d2a97 fib: cleanups |
1074 |
if (!ipv4_is_zeronet(prefix) && !(ifa->ifa_flags & IFA_F_SECONDARY) && |
1da177e4c Linux-2.6.12-rc2 |
1075 |
(prefix != addr || ifa->ifa_prefixlen < 32)) { |
7b1311807 ipv4: implement s... |
1076 1077 1078 |
if (!(ifa->ifa_flags & IFA_F_NOPREFIXROUTE)) fib_magic(RTM_NEWROUTE, dev->flags & IFF_LOOPBACK ? RTN_LOCAL : RTN_UNICAST, |
af4d768ad net/ipv4: Add sup... |
1079 1080 |
prefix, ifa->ifa_prefixlen, prim, ifa->ifa_rt_priority); |
1da177e4c Linux-2.6.12-rc2 |
1081 1082 1083 |
/* Add network specific broadcasts, when it takes a sense */ if (ifa->ifa_prefixlen < 31) { |
af4d768ad net/ipv4: Add sup... |
1084 1085 |
fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix, 32, prim, 0); |
6a31d2a97 fib: cleanups |
1086 |
fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix | ~mask, |
af4d768ad net/ipv4: Add sup... |
1087 |
32, prim, 0); |
1da177e4c Linux-2.6.12-rc2 |
1088 1089 1090 |
} } } |
af4d768ad net/ipv4: Add sup... |
1091 1092 1093 1094 1095 1096 1097 1098 1099 |
void fib_modify_prefix_metric(struct in_ifaddr *ifa, u32 new_metric) { __be32 prefix = ifa->ifa_address & ifa->ifa_mask; struct in_device *in_dev = ifa->ifa_dev; struct net_device *dev = in_dev->dev; if (!(dev->flags & IFF_UP) || ifa->ifa_flags & (IFA_F_SECONDARY | IFA_F_NOPREFIXROUTE) || ipv4_is_zeronet(prefix) || |
0b834ba00 ipv4: fix route u... |
1100 |
(prefix == ifa->ifa_local && ifa->ifa_prefixlen == 32)) |
af4d768ad net/ipv4: Add sup... |
1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 |
return; /* add the new */ fib_magic(RTM_NEWROUTE, dev->flags & IFF_LOOPBACK ? RTN_LOCAL : RTN_UNICAST, prefix, ifa->ifa_prefixlen, ifa, new_metric); /* delete the old */ fib_magic(RTM_DELROUTE, dev->flags & IFF_LOOPBACK ? RTN_LOCAL : RTN_UNICAST, prefix, ifa->ifa_prefixlen, ifa, ifa->ifa_rt_priority); } |
e6abbaa27 ipv4: fix route d... |
1113 1114 1115 1116 1117 1118 |
/* Delete primary or secondary address. * Optionally, on secondary address promotion consider the addresses * from subnet iprim as deleted, even if they are in device list. * In this case the secondary ifa can be in device list. */ void fib_del_ifaddr(struct in_ifaddr *ifa, struct in_ifaddr *iprim) |
1da177e4c Linux-2.6.12-rc2 |
1119 1120 1121 1122 |
{ struct in_device *in_dev = ifa->ifa_dev; struct net_device *dev = in_dev->dev; struct in_ifaddr *ifa1; |
e6abbaa27 ipv4: fix route d... |
1123 |
struct in_ifaddr *prim = ifa, *prim1 = NULL; |
6a31d2a97 fib: cleanups |
1124 1125 |
__be32 brd = ifa->ifa_address | ~ifa->ifa_mask; __be32 any = ifa->ifa_address & ifa->ifa_mask; |
1da177e4c Linux-2.6.12-rc2 |
1126 1127 1128 1129 |
#define LOCAL_OK 1 #define BRD_OK 2 #define BRD0_OK 4 #define BRD1_OK 8 |
95c961747 net: cleanup unsi... |
1130 |
unsigned int ok = 0; |
e6abbaa27 ipv4: fix route d... |
1131 1132 1133 |
int subnet = 0; /* Primary network */ int gone = 1; /* Address is missing */ int same_prefsrc = 0; /* Another primary with same IP */ |
1da177e4c Linux-2.6.12-rc2 |
1134 |
|
e6abbaa27 ipv4: fix route d... |
1135 |
if (ifa->ifa_flags & IFA_F_SECONDARY) { |
1da177e4c Linux-2.6.12-rc2 |
1136 |
prim = inet_ifa_byprefix(in_dev, any, ifa->ifa_mask); |
51456b291 ipv4: coding styl... |
1137 |
if (!prim) { |
391a20333 ipv4/fib: don't w... |
1138 1139 1140 1141 1142 1143 |
/* if the device has been deleted, we don't perform * address promotion */ if (!in_dev->dead) pr_warn("%s: bug: prim == NULL ", __func__); |
1da177e4c Linux-2.6.12-rc2 |
1144 1145 |
return; } |
e6abbaa27 ipv4: fix route d... |
1146 |
if (iprim && iprim != prim) { |
058bd4d2a net: Convert prin... |
1147 1148 |
pr_warn("%s: bug: iprim != prim ", __func__); |
e6abbaa27 ipv4: fix route d... |
1149 1150 1151 1152 |
return; } } else if (!ipv4_is_zeronet(any) && (any != ifa->ifa_local || ifa->ifa_prefixlen < 32)) { |
7b1311807 ipv4: implement s... |
1153 1154 1155 |
if (!(ifa->ifa_flags & IFA_F_NOPREFIXROUTE)) fib_magic(RTM_DELROUTE, dev->flags & IFF_LOOPBACK ? RTN_LOCAL : RTN_UNICAST, |
af4d768ad net/ipv4: Add sup... |
1156 |
any, ifa->ifa_prefixlen, prim, 0); |
e6abbaa27 ipv4: fix route d... |
1157 |
subnet = 1; |
1da177e4c Linux-2.6.12-rc2 |
1158 |
} |
fbd40ea01 ipv4: Don't do ex... |
1159 1160 |
if (in_dev->dead) goto no_promotions; |
1da177e4c Linux-2.6.12-rc2 |
1161 |
/* Deletion is more complicated than add. |
6a31d2a97 fib: cleanups |
1162 1163 1164 |
* We should take care of not to delete too much :-) * * Scan address list to be sure that addresses are really gone. |
1da177e4c Linux-2.6.12-rc2 |
1165 |
*/ |
cd5a411db net: use new in_d... |
1166 1167 |
rcu_read_lock(); in_dev_for_each_ifa_rcu(ifa1, in_dev) { |
e6abbaa27 ipv4: fix route d... |
1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 |
if (ifa1 == ifa) { /* promotion, keep the IP */ gone = 0; continue; } /* Ignore IFAs from our subnet */ if (iprim && ifa1->ifa_mask == iprim->ifa_mask && inet_ifa_match(ifa1->ifa_address, iprim)) continue; /* Ignore ifa1 if it uses different primary IP (prefsrc) */ if (ifa1->ifa_flags & IFA_F_SECONDARY) { /* Another address from our subnet? */ if (ifa1->ifa_mask == prim->ifa_mask && inet_ifa_match(ifa1->ifa_address, prim)) prim1 = prim; else { /* We reached the secondaries, so * same_prefsrc should be determined. */ if (!same_prefsrc) continue; /* Search new prim1 if ifa1 is not * using the current prim1 */ if (!prim1 || ifa1->ifa_mask != prim1->ifa_mask || !inet_ifa_match(ifa1->ifa_address, prim1)) prim1 = inet_ifa_byprefix(in_dev, ifa1->ifa_address, ifa1->ifa_mask); if (!prim1) continue; if (prim1->ifa_local != prim->ifa_local) continue; } } else { if (prim->ifa_local != ifa1->ifa_local) continue; prim1 = ifa1; if (prim != prim1) same_prefsrc = 1; } |
1da177e4c Linux-2.6.12-rc2 |
1211 1212 1213 1214 1215 1216 1217 1218 |
if (ifa->ifa_local == ifa1->ifa_local) ok |= LOCAL_OK; if (ifa->ifa_broadcast == ifa1->ifa_broadcast) ok |= BRD_OK; if (brd == ifa1->ifa_broadcast) ok |= BRD1_OK; if (any == ifa1->ifa_broadcast) ok |= BRD0_OK; |
e6abbaa27 ipv4: fix route d... |
1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 |
/* primary has network specific broadcasts */ if (prim1 == ifa1 && ifa1->ifa_prefixlen < 31) { __be32 brd1 = ifa1->ifa_address | ~ifa1->ifa_mask; __be32 any1 = ifa1->ifa_address & ifa1->ifa_mask; if (!ipv4_is_zeronet(any1)) { if (ifa->ifa_broadcast == brd1 || ifa->ifa_broadcast == any1) ok |= BRD_OK; if (brd == brd1 || brd == any1) ok |= BRD1_OK; if (any == brd1 || any == any1) ok |= BRD0_OK; } } |
1da177e4c Linux-2.6.12-rc2 |
1234 |
} |
cd5a411db net: use new in_d... |
1235 |
rcu_read_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
1236 |
|
fbd40ea01 ipv4: Don't do ex... |
1237 |
no_promotions: |
6a31d2a97 fib: cleanups |
1238 |
if (!(ok & BRD_OK)) |
af4d768ad net/ipv4: Add sup... |
1239 1240 |
fib_magic(RTM_DELROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim, 0); |
e6abbaa27 ipv4: fix route d... |
1241 1242 |
if (subnet && ifa->ifa_prefixlen < 31) { if (!(ok & BRD1_OK)) |
af4d768ad net/ipv4: Add sup... |
1243 1244 |
fib_magic(RTM_DELROUTE, RTN_BROADCAST, brd, 32, prim, 0); |
e6abbaa27 ipv4: fix route d... |
1245 |
if (!(ok & BRD0_OK)) |
af4d768ad net/ipv4: Add sup... |
1246 1247 |
fib_magic(RTM_DELROUTE, RTN_BROADCAST, any, 32, prim, 0); |
e6abbaa27 ipv4: fix route d... |
1248 |
} |
6a31d2a97 fib: cleanups |
1249 |
if (!(ok & LOCAL_OK)) { |
30bbaa195 net: Fix up inet_... |
1250 |
unsigned int addr_type; |
af4d768ad net/ipv4: Add sup... |
1251 |
fib_magic(RTM_DELROUTE, RTN_LOCAL, ifa->ifa_local, 32, prim, 0); |
1da177e4c Linux-2.6.12-rc2 |
1252 1253 |
/* Check, that this local address finally disappeared. */ |
30bbaa195 net: Fix up inet_... |
1254 1255 1256 |
addr_type = inet_addr_type_dev_table(dev_net(dev), dev, ifa->ifa_local); if (gone && addr_type != RTN_LOCAL) { |
1da177e4c Linux-2.6.12-rc2 |
1257 |
/* And the last, but not the least thing. |
6a31d2a97 fib: cleanups |
1258 1259 1260 1261 1262 |
* We must flush stray FIB entries. * * First of all, we scan fib_info list searching * for stray nexthop entries, then ignite fib_flush. */ |
5a56a0b3a net: Don't delete... |
1263 |
if (fib_sync_down_addr(dev, ifa->ifa_local)) |
c346dca10 [NET] NETNS: Omit... |
1264 |
fib_flush(dev_net(dev)); |
1da177e4c Linux-2.6.12-rc2 |
1265 1266 1267 1268 1269 1270 1271 |
} } #undef LOCAL_OK #undef BRD_OK #undef BRD0_OK #undef BRD1_OK } |
345e9b542 fib_trie: Push rc... |
1272 |
static void nl_fib_lookup(struct net *net, struct fib_result_nl *frn) |
246955fe4 [NETLINK]: fib_lo... |
1273 |
{ |
e905a9eda [NET] IPV4: Fix w... |
1274 |
|
246955fe4 [NETLINK]: fib_lo... |
1275 |
struct fib_result res; |
9ade22861 ipv4: Use flowi4 ... |
1276 1277 1278 1279 1280 |
struct flowi4 fl4 = { .flowi4_mark = frn->fl_mark, .daddr = frn->fl_addr, .flowi4_tos = frn->fl_tos, .flowi4_scope = frn->fl_scope, |
6a31d2a97 fib: cleanups |
1281 |
}; |
345e9b542 fib_trie: Push rc... |
1282 1283 1284 1285 1286 |
struct fib_table *tb; rcu_read_lock(); tb = fib_get_table(net, frn->tb_id_in); |
1194ed0a3 [NETLINK]: Infini... |
1287 1288 |
frn->err = -ENOENT; |
246955fe4 [NETLINK]: fib_lo... |
1289 1290 1291 1292 |
if (tb) { local_bh_disable(); frn->tb_id = tb->tb_id; |
9ade22861 ipv4: Use flowi4 ... |
1293 |
frn->err = fib_table_lookup(tb, &fl4, &res, FIB_LOOKUP_NOREF); |
246955fe4 [NETLINK]: fib_lo... |
1294 1295 1296 1297 1298 1299 1300 1301 1302 |
if (!frn->err) { frn->prefixlen = res.prefixlen; frn->nh_sel = res.nh_sel; frn->type = res.type; frn->scope = res.scope; } local_bh_enable(); } |
345e9b542 fib_trie: Push rc... |
1303 1304 |
rcu_read_unlock(); |
246955fe4 [NETLINK]: fib_lo... |
1305 |
} |
28f7b0360 [NETLINK]: fib_fr... |
1306 |
static void nl_fib_input(struct sk_buff *skb) |
246955fe4 [NETLINK]: fib_lo... |
1307 |
{ |
6bd48fcf7 [NETNS]: Provide ... |
1308 |
struct net *net; |
246955fe4 [NETLINK]: fib_lo... |
1309 |
struct fib_result_nl *frn; |
28f7b0360 [NETLINK]: fib_fr... |
1310 |
struct nlmsghdr *nlh; |
15e473046 netlink: Rename p... |
1311 |
u32 portid; |
1194ed0a3 [NETLINK]: Infini... |
1312 |
|
3b1e0a655 [NET] NETNS: Omit... |
1313 |
net = sock_net(skb->sk); |
b529ccf27 [NETLINK]: Introd... |
1314 |
nlh = nlmsg_hdr(skb); |
c64c0b3ca ipv4: provide str... |
1315 1316 |
if (skb->len < nlmsg_total_size(sizeof(*frn)) || skb->len < nlh->nlmsg_len || |
573ce260b net-next: replace... |
1317 |
nlmsg_len(nlh) < sizeof(*frn)) |
ea86575ea [NETLINK]: Fix pr... |
1318 |
return; |
d883a0367 [IPV4]: OOPS with... |
1319 |
|
3a36515f7 netlink: fix spla... |
1320 |
skb = netlink_skb_clone(skb, GFP_KERNEL); |
51456b291 ipv4: coding styl... |
1321 |
if (!skb) |
d883a0367 [IPV4]: OOPS with... |
1322 1323 |
return; nlh = nlmsg_hdr(skb); |
e905a9eda [NET] IPV4: Fix w... |
1324 |
|
573ce260b net-next: replace... |
1325 |
frn = (struct fib_result_nl *) nlmsg_data(nlh); |
345e9b542 fib_trie: Push rc... |
1326 |
nl_fib_lookup(net, frn); |
e905a9eda [NET] IPV4: Fix w... |
1327 |
|
28a28283f ipv4: fib: fix a ... |
1328 |
portid = NETLINK_CB(skb).portid; /* netlink portid */ |
15e473046 netlink: Rename p... |
1329 |
NETLINK_CB(skb).portid = 0; /* from kernel */ |
ac6d439d2 [NETLINK]: Conver... |
1330 |
NETLINK_CB(skb).dst_group = 0; /* unicast */ |
15e473046 netlink: Rename p... |
1331 |
netlink_unicast(net->ipv4.fibnl, skb, portid, MSG_DONTWAIT); |
e905a9eda [NET] IPV4: Fix w... |
1332 |
} |
246955fe4 [NETLINK]: fib_lo... |
1333 |
|
2c8c1e729 net: spread __net... |
1334 |
static int __net_init nl_fib_lookup_init(struct net *net) |
246955fe4 [NETLINK]: fib_lo... |
1335 |
{ |
6bd48fcf7 [NETNS]: Provide ... |
1336 |
struct sock *sk; |
a31f2d17b netlink: add netl... |
1337 1338 1339 |
struct netlink_kernel_cfg cfg = { .input = nl_fib_input, }; |
9f00d9776 netlink: hide str... |
1340 |
sk = netlink_kernel_create(net, NETLINK_FIB_LOOKUP, &cfg); |
51456b291 ipv4: coding styl... |
1341 |
if (!sk) |
7b1a74fdb [NETNS]: Refactor... |
1342 |
return -EAFNOSUPPORT; |
6bd48fcf7 [NETNS]: Provide ... |
1343 |
net->ipv4.fibnl = sk; |
7b1a74fdb [NETNS]: Refactor... |
1344 1345 1346 1347 1348 |
return 0; } static void nl_fib_lookup_exit(struct net *net) { |
b7c6ba6eb [NETNS]: Consolid... |
1349 |
netlink_kernel_release(net->ipv4.fibnl); |
775516bfa [NETNS]: Namespac... |
1350 |
net->ipv4.fibnl = NULL; |
246955fe4 [NETLINK]: fib_lo... |
1351 |
} |
4f823defd ipv4: fix to not ... |
1352 1353 |
static void fib_disable_ip(struct net_device *dev, unsigned long event, bool force) |
1da177e4c Linux-2.6.12-rc2 |
1354 |
{ |
4f823defd ipv4: fix to not ... |
1355 |
if (fib_sync_down_dev(dev, event, force)) |
c346dca10 [NET] NETNS: Omit... |
1356 |
fib_flush(dev_net(dev)); |
06b4fc520 net: fib: Decreas... |
1357 1358 |
else rt_cache_flush(dev_net(dev)); |
1da177e4c Linux-2.6.12-rc2 |
1359 1360 1361 1362 1363 |
arp_ifdown(dev); } static int fib_inetaddr_event(struct notifier_block *this, unsigned long event, void *ptr) { |
6ed2533e5 net: clean up net... |
1364 |
struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; |
76e6ebfb4 netns: add namesp... |
1365 |
struct net_device *dev = ifa->ifa_dev->dev; |
436c3b66e ipv4: Invalidate ... |
1366 |
struct net *net = dev_net(dev); |
1da177e4c Linux-2.6.12-rc2 |
1367 1368 1369 1370 1371 |
switch (event) { case NETDEV_UP: fib_add_ifaddr(ifa); #ifdef CONFIG_IP_ROUTE_MULTIPATH |
8a3d03166 net: track link-s... |
1372 |
fib_sync_up(dev, RTNH_F_DEAD); |
1da177e4c Linux-2.6.12-rc2 |
1373 |
#endif |
436c3b66e ipv4: Invalidate ... |
1374 |
atomic_inc(&net->ipv4.dev_addr_genid); |
4ccfe6d41 ipv4/route: arg d... |
1375 |
rt_cache_flush(dev_net(dev)); |
1da177e4c Linux-2.6.12-rc2 |
1376 1377 |
break; case NETDEV_DOWN: |
e6abbaa27 ipv4: fix route d... |
1378 |
fib_del_ifaddr(ifa, NULL); |
436c3b66e ipv4: Invalidate ... |
1379 |
atomic_inc(&net->ipv4.dev_addr_genid); |
51456b291 ipv4: coding styl... |
1380 |
if (!ifa->ifa_dev->ifa_list) { |
1da177e4c Linux-2.6.12-rc2 |
1381 |
/* Last address was deleted from this interface. |
6a31d2a97 fib: cleanups |
1382 |
* Disable IP. |
1da177e4c Linux-2.6.12-rc2 |
1383 |
*/ |
4f823defd ipv4: fix to not ... |
1384 |
fib_disable_ip(dev, event, true); |
1da177e4c Linux-2.6.12-rc2 |
1385 |
} else { |
4ccfe6d41 ipv4/route: arg d... |
1386 |
rt_cache_flush(dev_net(dev)); |
1da177e4c Linux-2.6.12-rc2 |
1387 1388 1389 1390 1391 1392 1393 1394 |
} break; } return NOTIFY_DONE; } static int fib_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) { |
351638e7d net: pass info st... |
1395 |
struct net_device *dev = netdev_notifier_info_to_dev(ptr); |
af7d6cce5 net: ipv4: update... |
1396 1397 |
struct netdev_notifier_changeupper_info *upper_info = ptr; struct netdev_notifier_info_ext *info_ext = ptr; |
0115e8e30 net: remove delay... |
1398 |
struct in_device *in_dev; |
436c3b66e ipv4: Invalidate ... |
1399 |
struct net *net = dev_net(dev); |
cd5a411db net: use new in_d... |
1400 |
struct in_ifaddr *ifa; |
8a3d03166 net: track link-s... |
1401 |
unsigned int flags; |
1da177e4c Linux-2.6.12-rc2 |
1402 1403 |
if (event == NETDEV_UNREGISTER) { |
4f823defd ipv4: fix to not ... |
1404 |
fib_disable_ip(dev, event, true); |
caacf05e5 ipv4: Properly pu... |
1405 |
rt_flush_dev(dev); |
1da177e4c Linux-2.6.12-rc2 |
1406 1407 |
return NOTIFY_DONE; } |
0115e8e30 net: remove delay... |
1408 |
in_dev = __in_dev_get_rtnl(dev); |
a0065f266 fib_frontend: fix... |
1409 1410 |
if (!in_dev) return NOTIFY_DONE; |
0115e8e30 net: remove delay... |
1411 |
|
1da177e4c Linux-2.6.12-rc2 |
1412 1413 |
switch (event) { case NETDEV_UP: |
cd5a411db net: use new in_d... |
1414 |
in_dev_for_each_ifa_rtnl(ifa, in_dev) { |
1da177e4c Linux-2.6.12-rc2 |
1415 |
fib_add_ifaddr(ifa); |
cd5a411db net: use new in_d... |
1416 |
} |
1da177e4c Linux-2.6.12-rc2 |
1417 |
#ifdef CONFIG_IP_ROUTE_MULTIPATH |
8a3d03166 net: track link-s... |
1418 |
fib_sync_up(dev, RTNH_F_DEAD); |
1da177e4c Linux-2.6.12-rc2 |
1419 |
#endif |
436c3b66e ipv4: Invalidate ... |
1420 |
atomic_inc(&net->ipv4.dev_addr_genid); |
4ccfe6d41 ipv4/route: arg d... |
1421 |
rt_cache_flush(net); |
1da177e4c Linux-2.6.12-rc2 |
1422 1423 |
break; case NETDEV_DOWN: |
4f823defd ipv4: fix to not ... |
1424 |
fib_disable_ip(dev, event, false); |
1da177e4c Linux-2.6.12-rc2 |
1425 |
break; |
1da177e4c Linux-2.6.12-rc2 |
1426 |
case NETDEV_CHANGE: |
8a3d03166 net: track link-s... |
1427 1428 1429 1430 |
flags = dev_get_flags(dev); if (flags & (IFF_RUNNING | IFF_LOWER_UP)) fib_sync_up(dev, RTNH_F_LINKDOWN); else |
4f823defd ipv4: fix to not ... |
1431 |
fib_sync_down_dev(dev, event, false); |
af7d6cce5 net: ipv4: update... |
1432 1433 |
rt_cache_flush(net); break; |
8a3d03166 net: track link-s... |
1434 |
case NETDEV_CHANGEMTU: |
af7d6cce5 net: ipv4: update... |
1435 |
fib_sync_mtu(dev, info_ext->ext.mtu); |
4ccfe6d41 ipv4/route: arg d... |
1436 |
rt_cache_flush(net); |
1da177e4c Linux-2.6.12-rc2 |
1437 |
break; |
7f49e7a38 net: Flush local ... |
1438 |
case NETDEV_CHANGEUPPER: |
af7d6cce5 net: ipv4: update... |
1439 |
upper_info = ptr; |
7f49e7a38 net: Flush local ... |
1440 1441 1442 |
/* flush all routes if dev is linked to or unlinked from * an L3 master device (e.g., VRF) */ |
af7d6cce5 net: ipv4: update... |
1443 1444 |
if (upper_info->upper_dev && netif_is_l3_master(upper_info->upper_dev)) |
7f49e7a38 net: Flush local ... |
1445 1446 |
fib_disable_ip(dev, NETDEV_DOWN, true); break; |
1da177e4c Linux-2.6.12-rc2 |
1447 1448 1449 1450 1451 |
} return NOTIFY_DONE; } static struct notifier_block fib_inetaddr_notifier = { |
6ed2533e5 net: clean up net... |
1452 |
.notifier_call = fib_inetaddr_event, |
1da177e4c Linux-2.6.12-rc2 |
1453 1454 1455 |
}; static struct notifier_block fib_netdev_notifier = { |
6ed2533e5 net: clean up net... |
1456 |
.notifier_call = fib_netdev_event, |
1da177e4c Linux-2.6.12-rc2 |
1457 |
}; |
7b1a74fdb [NETNS]: Refactor... |
1458 |
static int __net_init ip_fib_net_init(struct net *net) |
1da177e4c Linux-2.6.12-rc2 |
1459 |
{ |
dce5cbeec [IPV4]: Fix memor... |
1460 |
int err; |
10da66f75 fib: avoid false ... |
1461 |
size_t size = sizeof(struct hlist_head) * FIB_TABLE_HASHSZ; |
04b1d4e50 net: core: Make t... |
1462 1463 1464 |
err = fib4_notifier_init(net); if (err) return err; |
cacaad11f ipv4: fib: Allow ... |
1465 |
|
10da66f75 fib: avoid false ... |
1466 1467 |
/* Avoid false sharing : Use at least a full cache line */ size = max_t(size_t, size, L1_CACHE_BYTES); |
1af5a8c4a [IPV4]: Increase ... |
1468 |
|
10da66f75 fib: avoid false ... |
1469 |
net->ipv4.fib_table_hash = kzalloc(size, GFP_KERNEL); |
04b1d4e50 net: core: Make t... |
1470 1471 1472 1473 |
if (!net->ipv4.fib_table_hash) { err = -ENOMEM; goto err_table_hash_alloc; } |
e4aef8aea [NETNS]: Place fi... |
1474 |
|
dce5cbeec [IPV4]: Fix memor... |
1475 1476 |
err = fib4_rules_init(net); if (err < 0) |
04b1d4e50 net: core: Make t... |
1477 |
goto err_rules_init; |
dce5cbeec [IPV4]: Fix memor... |
1478 |
return 0; |
04b1d4e50 net: core: Make t... |
1479 |
err_rules_init: |
dce5cbeec [IPV4]: Fix memor... |
1480 |
kfree(net->ipv4.fib_table_hash); |
04b1d4e50 net: core: Make t... |
1481 1482 |
err_table_hash_alloc: fib4_notifier_exit(net); |
dce5cbeec [IPV4]: Fix memor... |
1483 |
return err; |
7b1a74fdb [NETNS]: Refactor... |
1484 |
} |
1da177e4c Linux-2.6.12-rc2 |
1485 |
|
2c8c1e729 net: spread __net... |
1486 |
static void ip_fib_net_exit(struct net *net) |
7b1a74fdb [NETNS]: Refactor... |
1487 |
{ |
b4681c282 ipv4: Fix use-aft... |
1488 |
int i; |
7b1a74fdb [NETNS]: Refactor... |
1489 |
|
6dede75b7 fib_trie: call fi... |
1490 |
rtnl_lock(); |
6e47d6caf fib_trie: Cleanup... |
1491 |
#ifdef CONFIG_IP_MULTIPLE_TABLES |
6e47d6caf fib_trie: Cleanup... |
1492 1493 1494 |
RCU_INIT_POINTER(net->ipv4.fib_main, NULL); RCU_INIT_POINTER(net->ipv4.fib_default, NULL); #endif |
b4681c282 ipv4: Fix use-aft... |
1495 1496 1497 1498 1499 1500 |
/* Destroy the tables in reverse order to guarantee that the * local table, ID 255, is destroyed before the main table, ID * 254. This is necessary as the local table may contain * references to data contained in the main table. */ for (i = FIB_TABLE_HASHSZ - 1; i >= 0; i--) { |
a7e535312 fib_trie: Make fi... |
1501 |
struct hlist_head *head = &net->ipv4.fib_table_hash[i]; |
b67bfe0d4 hlist: drop the n... |
1502 |
struct hlist_node *tmp; |
a7e535312 fib_trie: Make fi... |
1503 |
struct fib_table *tb; |
b67bfe0d4 hlist: drop the n... |
1504 1505 |
hlist_for_each_entry_safe(tb, tmp, head, tb_hlist) { hlist_del(&tb->tb_hlist); |
f97f4dd8b net: ipv4: Fix me... |
1506 |
fib_table_flush(net, tb, true); |
4aa2c466a fib: Fix fib zone... |
1507 |
fib_free_table(tb); |
7b1a74fdb [NETNS]: Refactor... |
1508 1509 |
} } |
ad88d0513 fib_trie: Fix war... |
1510 1511 1512 1513 |
#ifdef CONFIG_IP_MULTIPLE_TABLES fib4_rules_exit(net); #endif |
e2666f849 fib: add rtnl loc... |
1514 |
rtnl_unlock(); |
e4aef8aea [NETNS]: Place fi... |
1515 |
kfree(net->ipv4.fib_table_hash); |
04b1d4e50 net: core: Make t... |
1516 |
fib4_notifier_exit(net); |
7b1a74fdb [NETNS]: Refactor... |
1517 1518 1519 1520 1521 |
} static int __net_init fib_net_init(struct net *net) { int error; |
f4530fa57 ipv4: Avoid overh... |
1522 1523 1524 |
#ifdef CONFIG_IP_ROUTE_CLASSID net->ipv4.fib_num_tclassid_users = 0; #endif |
7b1a74fdb [NETNS]: Refactor... |
1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 |
error = ip_fib_net_init(net); if (error < 0) goto out; error = nl_fib_lookup_init(net); if (error < 0) goto out_nlfl; error = fib_proc_init(net); if (error < 0) goto out_proc; out: return error; out_proc: nl_fib_lookup_exit(net); out_nlfl: ip_fib_net_exit(net); goto out; } static void __net_exit fib_net_exit(struct net *net) { fib_proc_exit(net); nl_fib_lookup_exit(net); ip_fib_net_exit(net); } static struct pernet_operations fib_net_ops = { .init = fib_net_init, .exit = fib_net_exit, }; void __init ip_fib_init(void) { |
8799a221f ipv4: initialize ... |
1558 |
fib_trie_init(); |
7b1a74fdb [NETNS]: Refactor... |
1559 1560 |
register_pernet_subsys(&fib_net_ops); |
8799a221f ipv4: initialize ... |
1561 |
|
7b1a74fdb [NETNS]: Refactor... |
1562 1563 |
register_netdevice_notifier(&fib_netdev_notifier); register_inetaddr_notifier(&fib_inetaddr_notifier); |
7f9b80529 [IPV4]: fib hash|... |
1564 |
|
b97bac64a rtnetlink: make r... |
1565 1566 1567 |
rtnl_register(PF_INET, RTM_NEWROUTE, inet_rtm_newroute, NULL, 0); rtnl_register(PF_INET, RTM_DELROUTE, inet_rtm_delroute, NULL, 0); rtnl_register(PF_INET, RTM_GETROUTE, NULL, inet_dump_fib, 0); |
1da177e4c Linux-2.6.12-rc2 |
1568 |
} |