Blame view

net/ipv4/fib_frontend.c 23.9 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
  /*
   * 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   Linus Torvalds   Linux-2.6.12-rc2
8
9
10
11
12
13
14
   * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
   *
   *		This program is free software; you can redistribute it and/or
   *		modify it under the terms of the GNU General Public License
   *		as published by the Free Software Foundation; either version
   *		2 of the License, or (at your option) any later version.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
16
17
18
  #include <linux/module.h>
  #include <asm/uaccess.h>
  #include <asm/system.h>
  #include <linux/bitops.h>
4fc268d24   Randy Dunlap   [PATCH] capable/c...
19
  #include <linux/capability.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
21
  #include <linux/types.h>
  #include <linux/kernel.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
23
24
25
26
27
28
  #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   Arnaldo Carvalho de Melo   [INET_SOCK]: Move...
29
  #include <linux/inetdevice.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
  #include <linux/netdevice.h>
1823730fb   Thomas Graf   [IPv4]: Move inte...
31
  #include <linux/if_addr.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
33
  #include <linux/if_arp.h>
  #include <linux/skbuff.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
  #include <linux/init.h>
1af5a8c4a   Patrick McHardy   [IPV4]: Increase ...
35
  #include <linux/list.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
36
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
38
39
40
41
42
  
  #include <net/ip.h>
  #include <net/protocol.h>
  #include <net/route.h>
  #include <net/tcp.h>
  #include <net/sock.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43
44
  #include <net/arp.h>
  #include <net/ip_fib.h>
63f3444fb   Thomas Graf   [IPv4]: Use rtnl ...
45
  #include <net/rtnetlink.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47
  #ifndef CONFIG_IP_MULTIPLE_TABLES
7b1a74fdb   Denis V. Lunev   [NETNS]: Refactor...
48
  static int __net_init fib4_rules_init(struct net *net)
c3e9a353d   Pavel Emelyanov   [IPV4]: Compact s...
49
  {
93456b6d7   Denis V. Lunev   [IPV4]: Unify acc...
50
  	struct fib_table *local_table, *main_table;
5348ba85a   David S. Miller   ipv4: Update some...
51
  	local_table = fib_trie_table(RT_TABLE_LOCAL);
93456b6d7   Denis V. Lunev   [IPV4]: Unify acc...
52
  	if (local_table == NULL)
dbb50165b   Denis V. Lunev   [IPV4]: Check fib...
53
  		return -ENOMEM;
5348ba85a   David S. Miller   ipv4: Update some...
54
  	main_table  = fib_trie_table(RT_TABLE_MAIN);
93456b6d7   Denis V. Lunev   [IPV4]: Unify acc...
55
  	if (main_table == NULL)
dbb50165b   Denis V. Lunev   [IPV4]: Check fib...
56
  		goto fail;
93456b6d7   Denis V. Lunev   [IPV4]: Unify acc...
57
  	hlist_add_head_rcu(&local_table->tb_hlist,
e4aef8aea   Denis V. Lunev   [NETNS]: Place fi...
58
  				&net->ipv4.fib_table_hash[TABLE_LOCAL_INDEX]);
93456b6d7   Denis V. Lunev   [IPV4]: Unify acc...
59
  	hlist_add_head_rcu(&main_table->tb_hlist,
e4aef8aea   Denis V. Lunev   [NETNS]: Place fi...
60
  				&net->ipv4.fib_table_hash[TABLE_MAIN_INDEX]);
dbb50165b   Denis V. Lunev   [IPV4]: Check fib...
61
62
63
  	return 0;
  
  fail:
93456b6d7   Denis V. Lunev   [IPV4]: Unify acc...
64
  	kfree(local_table);
dbb50165b   Denis V. Lunev   [IPV4]: Check fib...
65
  	return -ENOMEM;
c3e9a353d   Pavel Emelyanov   [IPV4]: Compact s...
66
  }
1af5a8c4a   Patrick McHardy   [IPV4]: Increase ...
67
  #else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68

8ad4942cd   Denis V. Lunev   [NETNS]: Add netn...
69
  struct fib_table *fib_new_table(struct net *net, u32 id)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
71
  {
  	struct fib_table *tb;
1af5a8c4a   Patrick McHardy   [IPV4]: Increase ...
72
  	unsigned int h;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73

1af5a8c4a   Patrick McHardy   [IPV4]: Increase ...
74
75
  	if (id == 0)
  		id = RT_TABLE_MAIN;
8ad4942cd   Denis V. Lunev   [NETNS]: Add netn...
76
  	tb = fib_get_table(net, id);
1af5a8c4a   Patrick McHardy   [IPV4]: Increase ...
77
78
  	if (tb)
  		return tb;
7f9b80529   Stephen Hemminger   [IPV4]: fib hash|...
79

5348ba85a   David S. Miller   ipv4: Update some...
80
  	tb = fib_trie_table(id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81
82
  	if (!tb)
  		return NULL;
1af5a8c4a   Patrick McHardy   [IPV4]: Increase ...
83
  	h = id & (FIB_TABLE_HASHSZ - 1);
e4aef8aea   Denis V. Lunev   [NETNS]: Place fi...
84
  	hlist_add_head_rcu(&tb->tb_hlist, &net->ipv4.fib_table_hash[h]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
86
  	return tb;
  }
8ad4942cd   Denis V. Lunev   [NETNS]: Add netn...
87
  struct fib_table *fib_get_table(struct net *net, u32 id)
1af5a8c4a   Patrick McHardy   [IPV4]: Increase ...
88
89
90
  {
  	struct fib_table *tb;
  	struct hlist_node *node;
e4aef8aea   Denis V. Lunev   [NETNS]: Place fi...
91
  	struct hlist_head *head;
1af5a8c4a   Patrick McHardy   [IPV4]: Increase ...
92
  	unsigned int h;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
93

1af5a8c4a   Patrick McHardy   [IPV4]: Increase ...
94
95
96
  	if (id == 0)
  		id = RT_TABLE_MAIN;
  	h = id & (FIB_TABLE_HASHSZ - 1);
e4aef8aea   Denis V. Lunev   [NETNS]: Place fi...
97

1af5a8c4a   Patrick McHardy   [IPV4]: Increase ...
98
  	rcu_read_lock();
e4aef8aea   Denis V. Lunev   [NETNS]: Place fi...
99
100
  	head = &net->ipv4.fib_table_hash[h];
  	hlist_for_each_entry_rcu(tb, node, head, tb_hlist) {
1af5a8c4a   Patrick McHardy   [IPV4]: Increase ...
101
102
103
104
105
106
107
108
  		if (tb->tb_id == id) {
  			rcu_read_unlock();
  			return tb;
  		}
  	}
  	rcu_read_unlock();
  	return NULL;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109
  #endif /* CONFIG_IP_MULTIPLE_TABLES */
e4aef8aea   Denis V. Lunev   [NETNS]: Place fi...
110
  static void fib_flush(struct net *net)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
112
  {
  	int flushed = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113
  	struct fib_table *tb;
1af5a8c4a   Patrick McHardy   [IPV4]: Increase ...
114
  	struct hlist_node *node;
e4aef8aea   Denis V. Lunev   [NETNS]: Place fi...
115
  	struct hlist_head *head;
1af5a8c4a   Patrick McHardy   [IPV4]: Increase ...
116
  	unsigned int h;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
117

1af5a8c4a   Patrick McHardy   [IPV4]: Increase ...
118
  	for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
e4aef8aea   Denis V. Lunev   [NETNS]: Place fi...
119
120
  		head = &net->ipv4.fib_table_hash[h];
  		hlist_for_each_entry(tb, node, head, tb_hlist)
16c6cf8bb   Stephen Hemminger   ipv4: fib table a...
121
  			flushed += fib_table_flush(tb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
123
124
  
  	if (flushed)
76e6ebfb4   Denis V. Lunev   netns: add namesp...
125
  		rt_cache_flush(net, -1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
  }
055381161   Laszlo Attila Toth   [IPV4]: Add inet_...
127
128
129
130
  /*
   * Find address type as if only "dev" was present in the system. If
   * on_dev is NULL then all interfaces are taken into consideration.
   */
6b175b26c   Eric W. Biederman   [NETNS]: Add netn...
131
132
  static inline unsigned __inet_dev_addr_type(struct net *net,
  					    const struct net_device *dev,
055381161   Laszlo Attila Toth   [IPV4]: Add inet_...
133
  					    __be32 addr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
  {
9ade22861   David S. Miller   ipv4: Use flowi4 ...
135
  	struct flowi4		fl4 = { .daddr = addr };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
137
  	struct fib_result	res;
  	unsigned ret = RTN_BROADCAST;
03cf786c4   Pavel Emelyanov   [IPV4]: Explicitl...
138
  	struct fib_table *local_table;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139

1e637c74b   Jan Engelhardt   [IPV4]: Enable us...
140
  	if (ipv4_is_zeronet(addr) || ipv4_is_lbcast(addr))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
  		return RTN_BROADCAST;
f97c1e0c6   Joe Perches   [IPV4] net/ipv4: ...
142
  	if (ipv4_is_multicast(addr))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143
144
145
146
147
  		return RTN_MULTICAST;
  
  #ifdef CONFIG_IP_MULTIPLE_TABLES
  	res.r = NULL;
  #endif
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
148

6b175b26c   Eric W. Biederman   [NETNS]: Add netn...
149
  	local_table = fib_get_table(net, RT_TABLE_LOCAL);
03cf786c4   Pavel Emelyanov   [IPV4]: Explicitl...
150
  	if (local_table) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151
  		ret = RTN_UNICAST;
ebc0ffae5   Eric Dumazet   fib: RCU conversi...
152
  		rcu_read_lock();
9ade22861   David S. Miller   ipv4: Use flowi4 ...
153
  		if (!fib_table_lookup(local_table, &fl4, &res, FIB_LOOKUP_NOREF)) {
055381161   Laszlo Attila Toth   [IPV4]: Add inet_...
154
155
  			if (!dev || dev == res.fi->fib_dev)
  				ret = res.type;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
156
  		}
ebc0ffae5   Eric Dumazet   fib: RCU conversi...
157
  		rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
159
160
  	}
  	return ret;
  }
6b175b26c   Eric W. Biederman   [NETNS]: Add netn...
161
  unsigned int inet_addr_type(struct net *net, __be32 addr)
055381161   Laszlo Attila Toth   [IPV4]: Add inet_...
162
  {
6b175b26c   Eric W. Biederman   [NETNS]: Add netn...
163
  	return __inet_dev_addr_type(net, NULL, addr);
055381161   Laszlo Attila Toth   [IPV4]: Add inet_...
164
  }
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
165
  EXPORT_SYMBOL(inet_addr_type);
055381161   Laszlo Attila Toth   [IPV4]: Add inet_...
166

6b175b26c   Eric W. Biederman   [NETNS]: Add netn...
167
168
  unsigned int inet_dev_addr_type(struct net *net, const struct net_device *dev,
  				__be32 addr)
055381161   Laszlo Attila Toth   [IPV4]: Add inet_...
169
  {
6a31d2a97   Eric Dumazet   fib: cleanups
170
  	return __inet_dev_addr_type(net, dev, addr);
055381161   Laszlo Attila Toth   [IPV4]: Add inet_...
171
  }
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
172
  EXPORT_SYMBOL(inet_dev_addr_type);
055381161   Laszlo Attila Toth   [IPV4]: Add inet_...
173

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
174
  /* Given (packet source, input interface) and optional (dst, oif, tos):
6a31d2a97   Eric Dumazet   fib: cleanups
175
176
177
178
179
   * - (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   Eric Dumazet   fib: RCU conversi...
180
   * called with rcu_read_lock()
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
181
   */
d9c9df8c9   Al Viro   [IPV4]: fib_valid...
182
  int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
b0c110ca8   jamal   net: Fix RPF to w...
183
184
  			struct net_device *dev, __be32 *spec_dst,
  			u32 *itag, u32 mark)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185
186
  {
  	struct in_device *in_dev;
9ade22861   David S. Miller   ipv4: Use flowi4 ...
187
  	struct flowi4 fl4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188
  	struct fib_result res;
8153a10c0   Patrick McHardy   ipv4 05/05: add s...
189
  	int no_addr, rpf, accept_local;
6f86b3251   David S. Miller   ipv4: Fix reverse...
190
  	bool dev_match;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
191
  	int ret;
5b707aaae   Denis V. Lunev   [NETNS]: Pass cor...
192
  	struct net *net;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193

9ade22861   David S. Miller   ipv4: Use flowi4 ...
194
195
196
197
198
199
200
  	fl4.flowi4_oif = 0;
  	fl4.flowi4_iif = oif;
  	fl4.flowi4_mark = mark;
  	fl4.daddr = src;
  	fl4.saddr = dst;
  	fl4.flowi4_tos = tos;
  	fl4.flowi4_scope = RT_SCOPE_UNIVERSE;
cc7e17ea0   David S. Miller   ipv4: Optimize fl...
201

8153a10c0   Patrick McHardy   ipv4 05/05: add s...
202
  	no_addr = rpf = accept_local = 0;
e5ed63991   Herbert Xu   [IPV4]: Replace _...
203
  	in_dev = __in_dev_get_rcu(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
204
205
206
  	if (in_dev) {
  		no_addr = in_dev->ifa_list == NULL;
  		rpf = IN_DEV_RPFILTER(in_dev);
8153a10c0   Patrick McHardy   ipv4 05/05: add s...
207
  		accept_local = IN_DEV_ACCEPT_LOCAL(in_dev);
28f6aeea3   Jamal Hadi Salim   net: restore ip s...
208
  		if (mark && !IN_DEV_SRC_VMARK(in_dev))
9ade22861   David S. Miller   ipv4: Use flowi4 ...
209
  			fl4.flowi4_mark = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
210
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211
212
213
  
  	if (in_dev == NULL)
  		goto e_inval;
c346dca10   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
214
  	net = dev_net(dev);
9ade22861   David S. Miller   ipv4: Use flowi4 ...
215
  	if (fib_lookup(net, &fl4, &res))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
216
  		goto last_resort;
8153a10c0   Patrick McHardy   ipv4 05/05: add s...
217
218
  	if (res.type != RTN_UNICAST) {
  		if (res.type != RTN_LOCAL || !accept_local)
ebc0ffae5   Eric Dumazet   fib: RCU conversi...
219
  			goto e_inval;
8153a10c0   Patrick McHardy   ipv4 05/05: add s...
220
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
222
  	*spec_dst = FIB_RES_PREFSRC(res);
  	fib_combine_itag(itag, &res);
6f86b3251   David S. Miller   ipv4: Fix reverse...
223
  	dev_match = false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224
  #ifdef CONFIG_IP_ROUTE_MULTIPATH
6f86b3251   David S. Miller   ipv4: Fix reverse...
225
226
227
228
229
230
231
232
  	for (ret = 0; ret < res.fi->fib_nhs; ret++) {
  		struct fib_nh *nh = &res.fi->fib_nh[ret];
  
  		if (nh->nh_dev == dev) {
  			dev_match = true;
  			break;
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
233
234
  #else
  	if (FIB_RES_DEV(res) == dev)
6f86b3251   David S. Miller   ipv4: Fix reverse...
235
  		dev_match = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
236
  #endif
6f86b3251   David S. Miller   ipv4: Fix reverse...
237
  	if (dev_match) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
  		ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
239
240
  		return ret;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
241
242
  	if (no_addr)
  		goto last_resort;
c1cf8422f   Stephen Hemminger   ip: add loose rev...
243
  	if (rpf == 1)
b5f7e7554   Eric Dumazet   ipv4: add LINUX_M...
244
  		goto e_rpf;
9ade22861   David S. Miller   ipv4: Use flowi4 ...
245
  	fl4.flowi4_oif = dev->ifindex;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
246
247
  
  	ret = 0;
9ade22861   David S. Miller   ipv4: Use flowi4 ...
248
  	if (fib_lookup(net, &fl4, &res) == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249
250
251
252
  		if (res.type == RTN_UNICAST) {
  			*spec_dst = FIB_RES_PREFSRC(res);
  			ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253
254
255
256
257
  	}
  	return ret;
  
  last_resort:
  	if (rpf)
b5f7e7554   Eric Dumazet   ipv4: add LINUX_M...
258
  		goto e_rpf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
259
260
261
  	*spec_dst = inet_select_addr(dev, 0, RT_SCOPE_UNIVERSE);
  	*itag = 0;
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
262
263
  e_inval:
  	return -EINVAL;
b5f7e7554   Eric Dumazet   ipv4: add LINUX_M...
264
265
  e_rpf:
  	return -EXDEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
266
  }
81f7bf6cb   Al Viro   [IPV4]: net/ipv4/...
267
  static inline __be32 sk_extract_addr(struct sockaddr *addr)
4e902c574   Thomas Graf   [IPv4]: FIB confi...
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
  {
  	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   Denis V. Lunev   [NETNS]: Correctl...
283
  static int rtentry_to_fib_config(struct net *net, int cmd, struct rtentry *rt,
4e902c574   Thomas Graf   [IPv4]: FIB confi...
284
285
  				 struct fib_config *cfg)
  {
6d85c10ab   Al Viro   [IPV4]: struct fi...
286
  	__be32 addr;
4e902c574   Thomas Graf   [IPv4]: FIB confi...
287
288
289
  	int plen;
  
  	memset(cfg, 0, sizeof(*cfg));
4b5d47d4d   Denis V. Lunev   [NETNS]: Correctl...
290
  	cfg->fc_nlinfo.nl_net = net;
4e902c574   Thomas Graf   [IPv4]: FIB confi...
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
  
  	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   Al Viro   [IPV4]: net/ipv4/...
306
  		__be32 mask = sk_extract_addr(&rt->rt_genmask);
4e902c574   Thomas Graf   [IPv4]: FIB confi...
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
  
  		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   Denis V. Lunev   [NETNS]: Correctl...
351
  		dev = __dev_get_by_name(net, devname);
4e902c574   Thomas Graf   [IPv4]: FIB confi...
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
  		if (!dev)
  			return -ENODEV;
  		cfg->fc_oif = dev->ifindex;
  		if (colon) {
  			struct in_ifaddr *ifa;
  			struct in_device *in_dev = __in_dev_get_rtnl(dev);
  			if (!in_dev)
  				return -ENODEV;
  			*colon = ':';
  			for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next)
  				if (strcmp(ifa->ifa_label, devname) == 0)
  					break;
  			if (ifa == NULL)
  				return -ENODEV;
  			cfg->fc_prefsrc = ifa->ifa_local;
  		}
  	}
  
  	addr = sk_extract_addr(&rt->rt_gateway);
  	if (rt->rt_gateway.sa_family == AF_INET && addr) {
  		cfg->fc_gw = addr;
  		if (rt->rt_flags & RTF_GATEWAY &&
4b5d47d4d   Denis V. Lunev   [NETNS]: Correctl...
374
  		    inet_addr_type(net, addr) == RTN_UNICAST)
4e902c574   Thomas Graf   [IPv4]: FIB confi...
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
  			cfg->fc_scope = RT_SCOPE_UNIVERSE;
  	}
  
  	if (cmd == SIOCDELRT)
  		return 0;
  
  	if (rt->rt_flags & RTF_GATEWAY && !cfg->fc_gw)
  		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;
  
  		mx = kzalloc(3 * nla_total_size(4), GFP_KERNEL);
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
392
  		if (mx == NULL)
4e902c574   Thomas Graf   [IPv4]: FIB confi...
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
  			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   Linus Torvalds   Linux-2.6.12-rc2
410
  /*
6a31d2a97   Eric Dumazet   fib: cleanups
411
412
   * Handle IP routing ioctl calls.
   * These are used to manipulate the routing tables
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
413
   */
1bad118a3   Denis V. Lunev   [NETNS]: Pass nam...
414
  int ip_rt_ioctl(struct net *net, unsigned int cmd, void __user *arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
415
  {
4e902c574   Thomas Graf   [IPv4]: FIB confi...
416
417
  	struct fib_config cfg;
  	struct rtentry rt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
418
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
419
420
421
422
423
424
  
  	switch (cmd) {
  	case SIOCADDRT:		/* Add a route */
  	case SIOCDELRT:		/* Delete a route */
  		if (!capable(CAP_NET_ADMIN))
  			return -EPERM;
4e902c574   Thomas Graf   [IPv4]: FIB confi...
425
426
  
  		if (copy_from_user(&rt, arg, sizeof(rt)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
427
  			return -EFAULT;
4e902c574   Thomas Graf   [IPv4]: FIB confi...
428

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
429
  		rtnl_lock();
1bad118a3   Denis V. Lunev   [NETNS]: Pass nam...
430
  		err = rtentry_to_fib_config(net, cmd, &rt, &cfg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
431
  		if (err == 0) {
4e902c574   Thomas Graf   [IPv4]: FIB confi...
432
  			struct fib_table *tb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
433
  			if (cmd == SIOCDELRT) {
1bad118a3   Denis V. Lunev   [NETNS]: Pass nam...
434
  				tb = fib_get_table(net, cfg.fc_table);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
435
  				if (tb)
16c6cf8bb   Stephen Hemminger   ipv4: fib table a...
436
  					err = fib_table_delete(tb, &cfg);
4e902c574   Thomas Graf   [IPv4]: FIB confi...
437
438
  				else
  					err = -ESRCH;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
439
  			} else {
1bad118a3   Denis V. Lunev   [NETNS]: Pass nam...
440
  				tb = fib_new_table(net, cfg.fc_table);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
441
  				if (tb)
16c6cf8bb   Stephen Hemminger   ipv4: fib table a...
442
  					err = fib_table_insert(tb, &cfg);
4e902c574   Thomas Graf   [IPv4]: FIB confi...
443
444
  				else
  					err = -ENOBUFS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
445
  			}
4e902c574   Thomas Graf   [IPv4]: FIB confi...
446
447
448
  
  			/* allocated by rtentry_to_fib_config() */
  			kfree(cfg.fc_mx);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
449
450
451
452
453
454
  		}
  		rtnl_unlock();
  		return err;
  	}
  	return -EINVAL;
  }
6a31d2a97   Eric Dumazet   fib: cleanups
455
  const struct nla_policy rtm_ipv4_policy[RTA_MAX + 1] = {
4e902c574   Thomas Graf   [IPv4]: FIB confi...
456
457
458
459
460
461
462
463
  	[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   Thomas Graf   [NETLINK]: Make u...
464
  	[RTA_MULTIPATH]		= { .len = sizeof(struct rtnexthop) },
4e902c574   Thomas Graf   [IPv4]: FIB confi...
465
  	[RTA_FLOW]		= { .type = NLA_U32 },
4e902c574   Thomas Graf   [IPv4]: FIB confi...
466
  };
4b5d47d4d   Denis V. Lunev   [NETNS]: Correctl...
467
  static int rtm_to_fib_config(struct net *net, struct sk_buff *skb,
6a31d2a97   Eric Dumazet   fib: cleanups
468
  			     struct nlmsghdr *nlh, struct fib_config *cfg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
469
  {
4e902c574   Thomas Graf   [IPv4]: FIB confi...
470
471
472
473
474
475
476
477
478
479
480
  	struct nlattr *attr;
  	int err, remaining;
  	struct rtmsg *rtm;
  
  	err = nlmsg_validate(nlh, sizeof(*rtm), RTA_MAX, rtm_ipv4_policy);
  	if (err < 0)
  		goto errout;
  
  	memset(cfg, 0, sizeof(*cfg));
  
  	rtm = nlmsg_data(nlh);
4e902c574   Thomas Graf   [IPv4]: FIB confi...
481
  	cfg->fc_dst_len = rtm->rtm_dst_len;
4e902c574   Thomas Graf   [IPv4]: FIB confi...
482
483
484
485
486
487
488
489
490
491
  	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;
  
  	cfg->fc_nlinfo.pid = NETLINK_CB(skb).pid;
  	cfg->fc_nlinfo.nlh = nlh;
4b5d47d4d   Denis V. Lunev   [NETNS]: Correctl...
492
  	cfg->fc_nlinfo.nl_net = net;
4e902c574   Thomas Graf   [IPv4]: FIB confi...
493

a0ee18b9b   Thomas Graf   [IPv4] fib: Fix o...
494
495
496
497
  	if (cfg->fc_type > RTN_MAX) {
  		err = -EINVAL;
  		goto errout;
  	}
4e902c574   Thomas Graf   [IPv4]: FIB confi...
498
  	nlmsg_for_each_attr(attr, nlh, sizeof(struct rtmsg), remaining) {
8f4c1f9b0   Thomas Graf   [NETLINK]: Introd...
499
  		switch (nla_type(attr)) {
4e902c574   Thomas Graf   [IPv4]: FIB confi...
500
  		case RTA_DST:
17fb2c643   Al Viro   [IPV4]: RTA_{DST,...
501
  			cfg->fc_dst = nla_get_be32(attr);
4e902c574   Thomas Graf   [IPv4]: FIB confi...
502
  			break;
4e902c574   Thomas Graf   [IPv4]: FIB confi...
503
504
505
506
  		case RTA_OIF:
  			cfg->fc_oif = nla_get_u32(attr);
  			break;
  		case RTA_GATEWAY:
17fb2c643   Al Viro   [IPV4]: RTA_{DST,...
507
  			cfg->fc_gw = nla_get_be32(attr);
4e902c574   Thomas Graf   [IPv4]: FIB confi...
508
509
510
511
512
  			break;
  		case RTA_PRIORITY:
  			cfg->fc_priority = nla_get_u32(attr);
  			break;
  		case RTA_PREFSRC:
17fb2c643   Al Viro   [IPV4]: RTA_{DST,...
513
  			cfg->fc_prefsrc = nla_get_be32(attr);
4e902c574   Thomas Graf   [IPv4]: FIB confi...
514
515
516
517
518
519
520
521
522
523
524
525
  			break;
  		case RTA_METRICS:
  			cfg->fc_mx = nla_data(attr);
  			cfg->fc_mx_len = nla_len(attr);
  			break;
  		case RTA_MULTIPATH:
  			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   Thomas Graf   [IPv4]: FIB confi...
526
527
528
  		case RTA_TABLE:
  			cfg->fc_table = nla_get_u32(attr);
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
529
530
  		}
  	}
4e902c574   Thomas Graf   [IPv4]: FIB confi...
531

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
532
  	return 0;
4e902c574   Thomas Graf   [IPv4]: FIB confi...
533
534
  errout:
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
535
  }
6ed2533e5   Jianjun Kong   net: clean up net...
536
  static int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
537
  {
3b1e0a655   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
538
  	struct net *net = sock_net(skb->sk);
4e902c574   Thomas Graf   [IPv4]: FIB confi...
539
540
541
  	struct fib_config cfg;
  	struct fib_table *tb;
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
542

4b5d47d4d   Denis V. Lunev   [NETNS]: Correctl...
543
  	err = rtm_to_fib_config(net, skb, nlh, &cfg);
4e902c574   Thomas Graf   [IPv4]: FIB confi...
544
545
  	if (err < 0)
  		goto errout;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
546

8ad4942cd   Denis V. Lunev   [NETNS]: Add netn...
547
  	tb = fib_get_table(net, cfg.fc_table);
4e902c574   Thomas Graf   [IPv4]: FIB confi...
548
549
550
551
  	if (tb == NULL) {
  		err = -ESRCH;
  		goto errout;
  	}
16c6cf8bb   Stephen Hemminger   ipv4: fib table a...
552
  	err = fib_table_delete(tb, &cfg);
4e902c574   Thomas Graf   [IPv4]: FIB confi...
553
554
  errout:
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
555
  }
6ed2533e5   Jianjun Kong   net: clean up net...
556
  static int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
557
  {
3b1e0a655   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
558
  	struct net *net = sock_net(skb->sk);
4e902c574   Thomas Graf   [IPv4]: FIB confi...
559
560
561
  	struct fib_config cfg;
  	struct fib_table *tb;
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
562

4b5d47d4d   Denis V. Lunev   [NETNS]: Correctl...
563
  	err = rtm_to_fib_config(net, skb, nlh, &cfg);
4e902c574   Thomas Graf   [IPv4]: FIB confi...
564
565
  	if (err < 0)
  		goto errout;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
566

226b0b4a5   Denis V. Lunev   [NETNS]: Replace ...
567
  	tb = fib_new_table(net, cfg.fc_table);
4e902c574   Thomas Graf   [IPv4]: FIB confi...
568
569
570
571
  	if (tb == NULL) {
  		err = -ENOBUFS;
  		goto errout;
  	}
16c6cf8bb   Stephen Hemminger   ipv4: fib table a...
572
  	err = fib_table_insert(tb, &cfg);
4e902c574   Thomas Graf   [IPv4]: FIB confi...
573
574
  errout:
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
575
  }
63f3444fb   Thomas Graf   [IPv4]: Use rtnl ...
576
  static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
577
  {
3b1e0a655   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
578
  	struct net *net = sock_net(skb->sk);
1af5a8c4a   Patrick McHardy   [IPV4]: Increase ...
579
580
  	unsigned int h, s_h;
  	unsigned int e = 0, s_e;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
581
  	struct fib_table *tb;
1af5a8c4a   Patrick McHardy   [IPV4]: Increase ...
582
  	struct hlist_node *node;
e4aef8aea   Denis V. Lunev   [NETNS]: Place fi...
583
  	struct hlist_head *head;
1af5a8c4a   Patrick McHardy   [IPV4]: Increase ...
584
  	int dumped = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
585

be403ea18   Thomas Graf   [IPv4]: Convert F...
586
587
  	if (nlmsg_len(cb->nlh) >= sizeof(struct rtmsg) &&
  	    ((struct rtmsg *) nlmsg_data(cb->nlh))->rtm_flags & RTM_F_CLONED)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
588
  		return ip_rt_dump(skb, cb);
1af5a8c4a   Patrick McHardy   [IPV4]: Increase ...
589
590
591
592
593
  	s_h = cb->args[0];
  	s_e = cb->args[1];
  
  	for (h = s_h; h < FIB_TABLE_HASHSZ; h++, s_e = 0) {
  		e = 0;
e4aef8aea   Denis V. Lunev   [NETNS]: Place fi...
594
595
  		head = &net->ipv4.fib_table_hash[h];
  		hlist_for_each_entry(tb, node, head, tb_hlist) {
1af5a8c4a   Patrick McHardy   [IPV4]: Increase ...
596
597
598
599
  			if (e < s_e)
  				goto next;
  			if (dumped)
  				memset(&cb->args[2], 0, sizeof(cb->args) -
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
600
  						 2 * sizeof(cb->args[0]));
16c6cf8bb   Stephen Hemminger   ipv4: fib table a...
601
  			if (fib_table_dump(tb, skb, cb) < 0)
1af5a8c4a   Patrick McHardy   [IPV4]: Increase ...
602
603
604
605
606
  				goto out;
  			dumped = 1;
  next:
  			e++;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
607
  	}
1af5a8c4a   Patrick McHardy   [IPV4]: Increase ...
608
609
610
  out:
  	cb->args[1] = e;
  	cb->args[0] = h;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
611
612
613
614
615
  
  	return skb->len;
  }
  
  /* Prepare and feed intra-kernel routing request.
6a31d2a97   Eric Dumazet   fib: cleanups
616
617
618
619
   * 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   Linus Torvalds   Linux-2.6.12-rc2
620
   */
81f7bf6cb   Al Viro   [IPV4]: net/ipv4/...
621
  static void fib_magic(int cmd, int type, __be32 dst, int dst_len, struct in_ifaddr *ifa)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
622
  {
c346dca10   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
623
  	struct net *net = dev_net(ifa->ifa_dev->dev);
4e902c574   Thomas Graf   [IPv4]: FIB confi...
624
625
626
627
628
629
630
631
632
  	struct fib_table *tb;
  	struct fib_config cfg = {
  		.fc_protocol = RTPROT_KERNEL,
  		.fc_type = type,
  		.fc_dst = dst,
  		.fc_dst_len = dst_len,
  		.fc_prefsrc = ifa->ifa_local,
  		.fc_oif = ifa->ifa_dev->dev->ifindex,
  		.fc_nlflags = NLM_F_CREATE | NLM_F_APPEND,
4d1169c1e   Denis V. Lunev   [NETNS]: Add netn...
633
  		.fc_nlinfo = {
4b5d47d4d   Denis V. Lunev   [NETNS]: Correctl...
634
  			.nl_net = net,
4d1169c1e   Denis V. Lunev   [NETNS]: Add netn...
635
  		},
4e902c574   Thomas Graf   [IPv4]: FIB confi...
636
  	};
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
637
638
  
  	if (type == RTN_UNICAST)
4b5d47d4d   Denis V. Lunev   [NETNS]: Correctl...
639
  		tb = fib_new_table(net, RT_TABLE_MAIN);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
640
  	else
4b5d47d4d   Denis V. Lunev   [NETNS]: Correctl...
641
  		tb = fib_new_table(net, RT_TABLE_LOCAL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
642
643
644
  
  	if (tb == NULL)
  		return;
4e902c574   Thomas Graf   [IPv4]: FIB confi...
645
  	cfg.fc_table = tb->tb_id;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
646

4e902c574   Thomas Graf   [IPv4]: FIB confi...
647
648
649
650
  	if (type != RTN_LOCAL)
  		cfg.fc_scope = RT_SCOPE_LINK;
  	else
  		cfg.fc_scope = RT_SCOPE_HOST;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
651
652
  
  	if (cmd == RTM_NEWROUTE)
16c6cf8bb   Stephen Hemminger   ipv4: fib table a...
653
  		fib_table_insert(tb, &cfg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
654
  	else
16c6cf8bb   Stephen Hemminger   ipv4: fib table a...
655
  		fib_table_delete(tb, &cfg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
656
  }
0ff60a456   Jamal Hadi Salim   [IPV4]: Fix secon...
657
  void fib_add_ifaddr(struct in_ifaddr *ifa)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
658
659
660
661
  {
  	struct in_device *in_dev = ifa->ifa_dev;
  	struct net_device *dev = in_dev->dev;
  	struct in_ifaddr *prim = ifa;
a144ea4b7   Al Viro   [IPV4]: annotate ...
662
663
  	__be32 mask = ifa->ifa_mask;
  	__be32 addr = ifa->ifa_local;
6a31d2a97   Eric Dumazet   fib: cleanups
664
  	__be32 prefix = ifa->ifa_address & mask;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
665

6a31d2a97   Eric Dumazet   fib: cleanups
666
  	if (ifa->ifa_flags & IFA_F_SECONDARY) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
667
668
  		prim = inet_ifa_byprefix(in_dev, prefix, mask);
  		if (prim == NULL) {
a6db90109   Stephen Hemminger   [IPV4] FIB: print...
669
670
  			printk(KERN_WARNING "fib_add_ifaddr: bug: prim == NULL
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
671
672
673
674
675
  			return;
  		}
  	}
  
  	fib_magic(RTM_NEWROUTE, RTN_LOCAL, addr, 32, prim);
6a31d2a97   Eric Dumazet   fib: cleanups
676
  	if (!(dev->flags & IFF_UP))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
677
678
679
  		return;
  
  	/* Add broadcast address, if it is explicitly assigned. */
a144ea4b7   Al Viro   [IPV4]: annotate ...
680
  	if (ifa->ifa_broadcast && ifa->ifa_broadcast != htonl(0xFFFFFFFF))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
681
  		fib_magic(RTM_NEWROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim);
6a31d2a97   Eric Dumazet   fib: cleanups
682
  	if (!ipv4_is_zeronet(prefix) && !(ifa->ifa_flags & IFA_F_SECONDARY) &&
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
683
  	    (prefix != addr || ifa->ifa_prefixlen < 32)) {
6a31d2a97   Eric Dumazet   fib: cleanups
684
685
686
  		fib_magic(RTM_NEWROUTE,
  			  dev->flags & IFF_LOOPBACK ? RTN_LOCAL : RTN_UNICAST,
  			  prefix, ifa->ifa_prefixlen, prim);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
687
688
689
690
  
  		/* Add network specific broadcasts, when it takes a sense */
  		if (ifa->ifa_prefixlen < 31) {
  			fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix, 32, prim);
6a31d2a97   Eric Dumazet   fib: cleanups
691
692
  			fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix | ~mask,
  				  32, prim);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
693
694
695
696
697
698
699
700
701
702
  		}
  	}
  }
  
  static void fib_del_ifaddr(struct in_ifaddr *ifa)
  {
  	struct in_device *in_dev = ifa->ifa_dev;
  	struct net_device *dev = in_dev->dev;
  	struct in_ifaddr *ifa1;
  	struct in_ifaddr *prim = ifa;
6a31d2a97   Eric Dumazet   fib: cleanups
703
704
  	__be32 brd = ifa->ifa_address | ~ifa->ifa_mask;
  	__be32 any = ifa->ifa_address & ifa->ifa_mask;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
705
706
707
708
709
  #define LOCAL_OK	1
  #define BRD_OK		2
  #define BRD0_OK		4
  #define BRD1_OK		8
  	unsigned ok = 0;
6a31d2a97   Eric Dumazet   fib: cleanups
710
711
712
713
  	if (!(ifa->ifa_flags & IFA_F_SECONDARY))
  		fib_magic(RTM_DELROUTE,
  			  dev->flags & IFF_LOOPBACK ? RTN_LOCAL : RTN_UNICAST,
  			  any, ifa->ifa_prefixlen, prim);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
714
715
716
  	else {
  		prim = inet_ifa_byprefix(in_dev, any, ifa->ifa_mask);
  		if (prim == NULL) {
a6db90109   Stephen Hemminger   [IPV4] FIB: print...
717
718
  			printk(KERN_WARNING "fib_del_ifaddr: bug: prim == NULL
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
719
720
721
722
723
  			return;
  		}
  	}
  
  	/* Deletion is more complicated than add.
6a31d2a97   Eric Dumazet   fib: cleanups
724
725
726
  	 * We should take care of not to delete too much :-)
  	 *
  	 * Scan address list to be sure that addresses are really gone.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
727
728
729
730
731
732
733
734
735
736
737
738
  	 */
  
  	for (ifa1 = in_dev->ifa_list; ifa1; ifa1 = ifa1->ifa_next) {
  		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;
  	}
6a31d2a97   Eric Dumazet   fib: cleanups
739
  	if (!(ok & BRD_OK))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
740
  		fib_magic(RTM_DELROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim);
6a31d2a97   Eric Dumazet   fib: cleanups
741
  	if (!(ok & BRD1_OK))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
742
  		fib_magic(RTM_DELROUTE, RTN_BROADCAST, brd, 32, prim);
6a31d2a97   Eric Dumazet   fib: cleanups
743
  	if (!(ok & BRD0_OK))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
744
  		fib_magic(RTM_DELROUTE, RTN_BROADCAST, any, 32, prim);
6a31d2a97   Eric Dumazet   fib: cleanups
745
  	if (!(ok & LOCAL_OK)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
746
747
748
  		fib_magic(RTM_DELROUTE, RTN_LOCAL, ifa->ifa_local, 32, prim);
  
  		/* Check, that this local address finally disappeared. */
c346dca10   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
749
  		if (inet_addr_type(dev_net(dev), ifa->ifa_local) != RTN_LOCAL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
750
  			/* And the last, but not the least thing.
6a31d2a97   Eric Dumazet   fib: cleanups
751
752
753
754
755
  			 * We must flush stray FIB entries.
  			 *
  			 * First of all, we scan fib_info list searching
  			 * for stray nexthop entries, then ignite fib_flush.
  			 */
c346dca10   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
756
757
  			if (fib_sync_down_addr(dev_net(dev), ifa->ifa_local))
  				fib_flush(dev_net(dev));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
758
759
760
761
762
763
764
  		}
  	}
  #undef LOCAL_OK
  #undef BRD_OK
  #undef BRD0_OK
  #undef BRD1_OK
  }
6a31d2a97   Eric Dumazet   fib: cleanups
765
  static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb)
246955fe4   Robert Olsson   [NETLINK]: fib_lo...
766
  {
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
767

246955fe4   Robert Olsson   [NETLINK]: fib_lo...
768
  	struct fib_result       res;
9ade22861   David S. Miller   ipv4: Use flowi4 ...
769
770
771
772
773
  	struct flowi4           fl4 = {
  		.flowi4_mark = frn->fl_mark,
  		.daddr = frn->fl_addr,
  		.flowi4_tos = frn->fl_tos,
  		.flowi4_scope = frn->fl_scope,
6a31d2a97   Eric Dumazet   fib: cleanups
774
  	};
1194ed0a3   Alexey Kuznetsov   [NETLINK]: Infini...
775

912a41a4a   Sergey Vlasov   [IPV4] nl_fib_loo...
776
777
778
  #ifdef CONFIG_IP_MULTIPLE_TABLES
  	res.r = NULL;
  #endif
1194ed0a3   Alexey Kuznetsov   [NETLINK]: Infini...
779
  	frn->err = -ENOENT;
246955fe4   Robert Olsson   [NETLINK]: fib_lo...
780
781
782
783
  	if (tb) {
  		local_bh_disable();
  
  		frn->tb_id = tb->tb_id;
ebc0ffae5   Eric Dumazet   fib: RCU conversi...
784
  		rcu_read_lock();
9ade22861   David S. Miller   ipv4: Use flowi4 ...
785
  		frn->err = fib_table_lookup(tb, &fl4, &res, FIB_LOOKUP_NOREF);
246955fe4   Robert Olsson   [NETLINK]: fib_lo...
786
787
788
789
790
791
792
  
  		if (!frn->err) {
  			frn->prefixlen = res.prefixlen;
  			frn->nh_sel = res.nh_sel;
  			frn->type = res.type;
  			frn->scope = res.scope;
  		}
ebc0ffae5   Eric Dumazet   fib: RCU conversi...
793
  		rcu_read_unlock();
246955fe4   Robert Olsson   [NETLINK]: fib_lo...
794
795
796
  		local_bh_enable();
  	}
  }
28f7b0360   David S. Miller   [NETLINK]: fib_fr...
797
  static void nl_fib_input(struct sk_buff *skb)
246955fe4   Robert Olsson   [NETLINK]: fib_lo...
798
  {
6bd48fcf7   Denis V. Lunev   [NETNS]: Provide ...
799
  	struct net *net;
246955fe4   Robert Olsson   [NETLINK]: fib_lo...
800
  	struct fib_result_nl *frn;
28f7b0360   David S. Miller   [NETLINK]: fib_fr...
801
  	struct nlmsghdr *nlh;
246955fe4   Robert Olsson   [NETLINK]: fib_lo...
802
  	struct fib_table *tb;
28f7b0360   David S. Miller   [NETLINK]: fib_fr...
803
  	u32 pid;
1194ed0a3   Alexey Kuznetsov   [NETLINK]: Infini...
804

3b1e0a655   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
805
  	net = sock_net(skb->sk);
b529ccf27   Arnaldo Carvalho de Melo   [NETLINK]: Introd...
806
  	nlh = nlmsg_hdr(skb);
ea86575ea   Thomas Graf   [NETLINK]: Fix pr...
807
  	if (skb->len < NLMSG_SPACE(0) || skb->len < nlh->nlmsg_len ||
d883a0367   Denis V. Lunev   [IPV4]: OOPS with...
808
  	    nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*frn)))
ea86575ea   Thomas Graf   [NETLINK]: Fix pr...
809
  		return;
d883a0367   Denis V. Lunev   [IPV4]: OOPS with...
810
811
812
813
814
  
  	skb = skb_clone(skb, GFP_KERNEL);
  	if (skb == NULL)
  		return;
  	nlh = nlmsg_hdr(skb);
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
815

246955fe4   Robert Olsson   [NETLINK]: fib_lo...
816
  	frn = (struct fib_result_nl *) NLMSG_DATA(nlh);
6bd48fcf7   Denis V. Lunev   [NETNS]: Provide ...
817
  	tb = fib_get_table(net, frn->tb_id_in);
246955fe4   Robert Olsson   [NETLINK]: fib_lo...
818
819
  
  	nl_fib_lookup(frn, tb);
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
820

6a31d2a97   Eric Dumazet   fib: cleanups
821
822
  	pid = NETLINK_CB(skb).pid;      /* pid of sending process */
  	NETLINK_CB(skb).pid = 0;        /* from kernel */
ac6d439d2   Patrick McHardy   [NETLINK]: Conver...
823
  	NETLINK_CB(skb).dst_group = 0;  /* unicast */
6bd48fcf7   Denis V. Lunev   [NETNS]: Provide ...
824
  	netlink_unicast(net->ipv4.fibnl, skb, pid, MSG_DONTWAIT);
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
825
  }
246955fe4   Robert Olsson   [NETLINK]: fib_lo...
826

2c8c1e729   Alexey Dobriyan   net: spread __net...
827
  static int __net_init nl_fib_lookup_init(struct net *net)
246955fe4   Robert Olsson   [NETLINK]: fib_lo...
828
  {
6bd48fcf7   Denis V. Lunev   [NETNS]: Provide ...
829
830
831
832
  	struct sock *sk;
  	sk = netlink_kernel_create(net, NETLINK_FIB_LOOKUP, 0,
  				   nl_fib_input, NULL, THIS_MODULE);
  	if (sk == NULL)
7b1a74fdb   Denis V. Lunev   [NETNS]: Refactor...
833
  		return -EAFNOSUPPORT;
6bd48fcf7   Denis V. Lunev   [NETNS]: Provide ...
834
  	net->ipv4.fibnl = sk;
7b1a74fdb   Denis V. Lunev   [NETNS]: Refactor...
835
836
837
838
839
  	return 0;
  }
  
  static void nl_fib_lookup_exit(struct net *net)
  {
b7c6ba6eb   Denis V. Lunev   [NETNS]: Consolid...
840
  	netlink_kernel_release(net->ipv4.fibnl);
775516bfa   Denis V. Lunev   [NETNS]: Namespac...
841
  	net->ipv4.fibnl = NULL;
246955fe4   Robert Olsson   [NETLINK]: fib_lo...
842
  }
e2ce14684   Octavian Purdila   ipv4: factorize c...
843
  static void fib_disable_ip(struct net_device *dev, int force, int delay)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
844
  {
85326fa54   Denis V. Lunev   [IPV4]: fib_sync_...
845
  	if (fib_sync_down_dev(dev, force))
c346dca10   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
846
  		fib_flush(dev_net(dev));
e2ce14684   Octavian Purdila   ipv4: factorize c...
847
  	rt_cache_flush(dev_net(dev), delay);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
848
849
850
851
852
  	arp_ifdown(dev);
  }
  
  static int fib_inetaddr_event(struct notifier_block *this, unsigned long event, void *ptr)
  {
6ed2533e5   Jianjun Kong   net: clean up net...
853
  	struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
76e6ebfb4   Denis V. Lunev   netns: add namesp...
854
  	struct net_device *dev = ifa->ifa_dev->dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
855
856
857
858
859
  
  	switch (event) {
  	case NETDEV_UP:
  		fib_add_ifaddr(ifa);
  #ifdef CONFIG_IP_ROUTE_MULTIPATH
76e6ebfb4   Denis V. Lunev   netns: add namesp...
860
  		fib_sync_up(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
861
  #endif
1fc050a13   David S. Miller   ipv4: Cache sourc...
862
  		fib_update_nh_saddrs(dev);
76e6ebfb4   Denis V. Lunev   netns: add namesp...
863
  		rt_cache_flush(dev_net(dev), -1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
864
865
866
  		break;
  	case NETDEV_DOWN:
  		fib_del_ifaddr(ifa);
1fc050a13   David S. Miller   ipv4: Cache sourc...
867
  		fib_update_nh_saddrs(dev);
9fcc2e8a7   Jayachandran C   [IPV4]: Fix issue...
868
  		if (ifa->ifa_dev->ifa_list == NULL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
869
  			/* Last address was deleted from this interface.
6a31d2a97   Eric Dumazet   fib: cleanups
870
  			 * Disable IP.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
871
  			 */
e2ce14684   Octavian Purdila   ipv4: factorize c...
872
  			fib_disable_ip(dev, 1, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
873
  		} else {
76e6ebfb4   Denis V. Lunev   netns: add namesp...
874
  			rt_cache_flush(dev_net(dev), -1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
875
876
877
878
879
880
881
882
883
  		}
  		break;
  	}
  	return NOTIFY_DONE;
  }
  
  static int fib_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
  {
  	struct net_device *dev = ptr;
e5ed63991   Herbert Xu   [IPV4]: Replace _...
884
  	struct in_device *in_dev = __in_dev_get_rtnl(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
885
886
  
  	if (event == NETDEV_UNREGISTER) {
e2ce14684   Octavian Purdila   ipv4: factorize c...
887
  		fib_disable_ip(dev, 2, -1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
888
889
890
891
892
893
894
895
896
897
898
899
900
901
  		return NOTIFY_DONE;
  	}
  
  	if (!in_dev)
  		return NOTIFY_DONE;
  
  	switch (event) {
  	case NETDEV_UP:
  		for_ifa(in_dev) {
  			fib_add_ifaddr(ifa);
  		} endfor_ifa(in_dev);
  #ifdef CONFIG_IP_ROUTE_MULTIPATH
  		fib_sync_up(dev);
  #endif
76e6ebfb4   Denis V. Lunev   netns: add namesp...
902
  		rt_cache_flush(dev_net(dev), -1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
903
904
  		break;
  	case NETDEV_DOWN:
e2ce14684   Octavian Purdila   ipv4: factorize c...
905
  		fib_disable_ip(dev, 0, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
906
907
908
  		break;
  	case NETDEV_CHANGEMTU:
  	case NETDEV_CHANGE:
76e6ebfb4   Denis V. Lunev   netns: add namesp...
909
  		rt_cache_flush(dev_net(dev), 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
910
  		break;
a5ee15513   Eric W. Biederman   net: NETDEV_UNREG...
911
  	case NETDEV_UNREGISTER_BATCH:
6561a3b12   David S. Miller   ipv4: Flush per-n...
912
913
914
915
916
  		/* The batch unregister is only called on the first
  		 * device in the list of devices being unregistered.
  		 * Therefore we should not pass dev_net(dev) in here.
  		 */
  		rt_cache_flush_batch(NULL);
a5ee15513   Eric W. Biederman   net: NETDEV_UNREG...
917
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
918
919
920
921
922
  	}
  	return NOTIFY_DONE;
  }
  
  static struct notifier_block fib_inetaddr_notifier = {
6ed2533e5   Jianjun Kong   net: clean up net...
923
  	.notifier_call = fib_inetaddr_event,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
924
925
926
  };
  
  static struct notifier_block fib_netdev_notifier = {
6ed2533e5   Jianjun Kong   net: clean up net...
927
  	.notifier_call = fib_netdev_event,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
928
  };
7b1a74fdb   Denis V. Lunev   [NETNS]: Refactor...
929
  static int __net_init ip_fib_net_init(struct net *net)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
930
  {
dce5cbeec   Denis V. Lunev   [IPV4]: Fix memor...
931
  	int err;
10da66f75   Eric Dumazet   fib: avoid false ...
932
933
934
935
  	size_t size = sizeof(struct hlist_head) * FIB_TABLE_HASHSZ;
  
  	/* Avoid false sharing : Use at least a full cache line */
  	size = max_t(size_t, size, L1_CACHE_BYTES);
1af5a8c4a   Patrick McHardy   [IPV4]: Increase ...
936

10da66f75   Eric Dumazet   fib: avoid false ...
937
  	net->ipv4.fib_table_hash = kzalloc(size, GFP_KERNEL);
e4aef8aea   Denis V. Lunev   [NETNS]: Place fi...
938
939
  	if (net->ipv4.fib_table_hash == NULL)
  		return -ENOMEM;
dce5cbeec   Denis V. Lunev   [IPV4]: Fix memor...
940
941
942
943
944
945
946
947
  	err = fib4_rules_init(net);
  	if (err < 0)
  		goto fail;
  	return 0;
  
  fail:
  	kfree(net->ipv4.fib_table_hash);
  	return err;
7b1a74fdb   Denis V. Lunev   [NETNS]: Refactor...
948
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
949

2c8c1e729   Alexey Dobriyan   net: spread __net...
950
  static void ip_fib_net_exit(struct net *net)
7b1a74fdb   Denis V. Lunev   [NETNS]: Refactor...
951
952
953
954
955
956
957
958
959
960
961
  {
  	unsigned int i;
  
  #ifdef CONFIG_IP_MULTIPLE_TABLES
  	fib4_rules_exit(net);
  #endif
  
  	for (i = 0; i < FIB_TABLE_HASHSZ; i++) {
  		struct fib_table *tb;
  		struct hlist_head *head;
  		struct hlist_node *node, *tmp;
63f3444fb   Thomas Graf   [IPv4]: Use rtnl ...
962

e4aef8aea   Denis V. Lunev   [NETNS]: Place fi...
963
  		head = &net->ipv4.fib_table_hash[i];
7b1a74fdb   Denis V. Lunev   [NETNS]: Refactor...
964
965
  		hlist_for_each_entry_safe(tb, node, tmp, head, tb_hlist) {
  			hlist_del(node);
16c6cf8bb   Stephen Hemminger   ipv4: fib table a...
966
  			fib_table_flush(tb);
4aa2c466a   Pavel Emelyanov   fib: Fix fib zone...
967
  			fib_free_table(tb);
7b1a74fdb   Denis V. Lunev   [NETNS]: Refactor...
968
969
  		}
  	}
e4aef8aea   Denis V. Lunev   [NETNS]: Place fi...
970
  	kfree(net->ipv4.fib_table_hash);
7b1a74fdb   Denis V. Lunev   [NETNS]: Refactor...
971
972
973
974
975
  }
  
  static int __net_init fib_net_init(struct net *net)
  {
  	int error;
7b1a74fdb   Denis V. Lunev   [NETNS]: Refactor...
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
  	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)
  {
63f3444fb   Thomas Graf   [IPv4]: Use rtnl ...
1009
1010
1011
  	rtnl_register(PF_INET, RTM_NEWROUTE, inet_rtm_newroute, NULL);
  	rtnl_register(PF_INET, RTM_DELROUTE, inet_rtm_delroute, NULL);
  	rtnl_register(PF_INET, RTM_GETROUTE, NULL, inet_dump_fib);
7b1a74fdb   Denis V. Lunev   [NETNS]: Refactor...
1012
1013
1014
1015
  
  	register_pernet_subsys(&fib_net_ops);
  	register_netdevice_notifier(&fib_netdev_notifier);
  	register_inetaddr_notifier(&fib_inetaddr_notifier);
7f9b80529   Stephen Hemminger   [IPV4]: fib hash|...
1016

5348ba85a   David S. Miller   ipv4: Update some...
1017
  	fib_trie_init();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1018
  }