Blame view

net/ipv6/ip6mr.c 59.4 KB
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  /*
   *	Linux IPv6 multicast routing support for BSD pim6sd
   *	Based on net/ipv4/ipmr.c.
   *
   *	(c) 2004 Mickael Hoerdt, <hoerdt@clarinet.u-strasbg.fr>
   *		LSIIT Laboratory, Strasbourg, France
   *	(c) 2004 Jean-Philippe Andriot, <jean-philippe.andriot@6WIND.com>
   *		6WIND, Paris, France
   *	Copyright (C)2007,2008 USAGI/WIDE Project
   *		YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
   *
   *	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.
   *
   */
7c0f6ba68   Linus Torvalds   Replace <asm/uacc...
18
  #include <linux/uaccess.h>
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
19
20
21
22
23
24
25
26
27
  #include <linux/types.h>
  #include <linux/sched.h>
  #include <linux/errno.h>
  #include <linux/timer.h>
  #include <linux/mm.h>
  #include <linux/kernel.h>
  #include <linux/fcntl.h>
  #include <linux/stat.h>
  #include <linux/socket.h>
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
28
29
30
  #include <linux/inet.h>
  #include <linux/netdevice.h>
  #include <linux/inetdevice.h>
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
31
32
  #include <linux/proc_fs.h>
  #include <linux/seq_file.h>
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
33
  #include <linux/init.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
34
  #include <linux/slab.h>
e2d57766e   David S. Miller   net: Provide comp...
35
  #include <linux/compat.h>
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
36
37
38
  #include <net/protocol.h>
  #include <linux/skbuff.h>
  #include <net/sock.h>
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
39
  #include <net/raw.h>
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
40
41
  #include <linux/notifier.h>
  #include <linux/if_arp.h>
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
42
43
  #include <net/checksum.h>
  #include <net/netlink.h>
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
44
  #include <net/fib_rules.h>
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
45
46
47
48
  
  #include <net/ipv6.h>
  #include <net/ip6_route.h>
  #include <linux/mroute6.h>
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
49
  #include <linux/pim.h>
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
50
51
  #include <net/addrconf.h>
  #include <linux/netfilter_ipv6.h>
bc3b2d7fb   Paul Gortmaker   net: Add export.h...
52
  #include <linux/export.h>
5d6e430d3   Dave Jones   ipv6: compile fix...
53
  #include <net/ip6_checksum.h>
d67b8c616   Nicolas Dichtel   netconf: advertis...
54
  #include <linux/netconf.h>
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
55

6bd521433   Patrick McHardy   ipv6: ip6mr: move...
56
  struct mr6_table {
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
57
  	struct list_head	list;
0c5c9fb55   Eric W. Biederman   net: Introduce po...
58
  	possible_net_t		net;
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
59
  	u32			id;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
60
61
62
63
64
65
66
  	struct sock		*mroute6_sk;
  	struct timer_list	ipmr_expire_timer;
  	struct list_head	mfc6_unres_queue;
  	struct list_head	mfc6_cache_array[MFC6_LINES];
  	struct mif_device	vif6_table[MAXMIFS];
  	int			maxvif;
  	atomic_t		cache_resolve_queue_len;
53d6841d2   Joe Perches   ipv4/ipmr and ipv...
67
68
  	bool			mroute_do_assert;
  	bool			mroute_do_pim;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
69
70
71
72
  #ifdef CONFIG_IPV6_PIMSM_V2
  	int			mroute_reg_vif_num;
  #endif
  };
18e260fd2   Gustavo A. R. Silva   ip6mr: Fix potent...
73
  #include <linux/nospec.h>
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
74
75
76
77
78
79
80
  struct ip6mr_rule {
  	struct fib_rule		common;
  };
  
  struct ip6mr_result {
  	struct mr6_table	*mrt;
  };
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
81
82
83
84
85
86
87
88
89
  /* Big lock, protecting vif table, mrt cache and mroute socket state.
     Note that the changes are semaphored via rtnl_lock.
   */
  
  static DEFINE_RWLOCK(mrt_lock);
  
  /*
   *	Multicast router control variables
   */
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
90
  #define MIF_EXISTS(_mrt, _idx) ((_mrt)->vif6_table[_idx].dev != NULL)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
91

7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
92
93
94
95
96
97
98
99
100
101
102
103
  /* Special spinlock for queue of unresolved entries */
  static DEFINE_SPINLOCK(mfc_unres_lock);
  
  /* We return to original Alan's scheme. Hash table of resolved
     entries is changed only in process context and protected
     with weak lock mrt_lock. Queue of unresolved entries is protected
     with strong spinlock mfc_unres_lock.
  
     In this case data path is free of exclusive locks at all.
   */
  
  static struct kmem_cache *mrt_cachep __read_mostly;
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
104
105
  static struct mr6_table *ip6mr_new_table(struct net *net, u32 id);
  static void ip6mr_free_table(struct mr6_table *mrt);
2b52c3ada   Rami Rosen   ip6mr: change the...
106
107
  static void ip6_mr_forward(struct net *net, struct mr6_table *mrt,
  			   struct sk_buff *skb, struct mfc6_cache *cache);
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
108
  static int ip6mr_cache_report(struct mr6_table *mrt, struct sk_buff *pkt,
8229efdae   Benjamin Thery   netns: ip6mr: ena...
109
  			      mifi_t mifi, int assert);
5b285cac3   Patrick McHardy   ipv6: ip6mr: add ...
110
111
  static int __ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb,
  			       struct mfc6_cache *c, struct rtmsg *rtm);
812e44dd1   Nicolas Dichtel   ip6mr: advertise ...
112
113
  static void mr6_netlink_event(struct mr6_table *mrt, struct mfc6_cache *mfc,
  			      int cmd);
dd12d15c9   Julien Gomes   ip6mr: add netlin...
114
  static void mrt6msg_netlink_event(struct mr6_table *mrt, struct sk_buff *pkt);
5b285cac3   Patrick McHardy   ipv6: ip6mr: add ...
115
116
  static int ip6mr_rtm_dumproute(struct sk_buff *skb,
  			       struct netlink_callback *cb);
4c6980462   Nikolay Aleksandrov   net: ip6mr: fix s...
117
  static void mroute_clean_tables(struct mr6_table *mrt, bool all);
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
118
119
120
  static void ipmr_expire_process(unsigned long arg);
  
  #ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
8ffb335e8   Eric Dumazet   ip6mr: fix a typo...
121
  #define ip6mr_for_each_table(mrt, net) \
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
122
123
124
125
126
127
128
129
130
131
132
133
  	list_for_each_entry_rcu(mrt, &net->ipv6.mr6_tables, list)
  
  static struct mr6_table *ip6mr_get_table(struct net *net, u32 id)
  {
  	struct mr6_table *mrt;
  
  	ip6mr_for_each_table(mrt, net) {
  		if (mrt->id == id)
  			return mrt;
  	}
  	return NULL;
  }
4c9483b2f   David S. Miller   ipv6: Convert to ...
134
  static int ip6mr_fib_lookup(struct net *net, struct flowi6 *flp6,
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
135
136
  			    struct mr6_table **mrt)
  {
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
137
  	int err;
95f4a45de   Hannes Frederic Sowa   net: avoid refere...
138
139
140
141
142
  	struct ip6mr_result res;
  	struct fib_lookup_arg arg = {
  		.result = &res,
  		.flags = FIB_LOOKUP_NOREF,
  	};
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
143

4c9483b2f   David S. Miller   ipv6: Convert to ...
144
145
  	err = fib_rules_lookup(net->ipv6.mr6_rules_ops,
  			       flowi6_to_flowi(flp6), 0, &arg);
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
  	if (err < 0)
  		return err;
  	*mrt = res.mrt;
  	return 0;
  }
  
  static int ip6mr_rule_action(struct fib_rule *rule, struct flowi *flp,
  			     int flags, struct fib_lookup_arg *arg)
  {
  	struct ip6mr_result *res = arg->result;
  	struct mr6_table *mrt;
  
  	switch (rule->action) {
  	case FR_ACT_TO_TBL:
  		break;
  	case FR_ACT_UNREACHABLE:
  		return -ENETUNREACH;
  	case FR_ACT_PROHIBIT:
  		return -EACCES;
  	case FR_ACT_BLACKHOLE:
  	default:
  		return -EINVAL;
  	}
  
  	mrt = ip6mr_get_table(rule->fr_net, rule->table);
63159f29b   Ian Morris   ipv6: coding styl...
171
  	if (!mrt)
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
  		return -EAGAIN;
  	res->mrt = mrt;
  	return 0;
  }
  
  static int ip6mr_rule_match(struct fib_rule *rule, struct flowi *flp, int flags)
  {
  	return 1;
  }
  
  static const struct nla_policy ip6mr_rule_policy[FRA_MAX + 1] = {
  	FRA_GENERIC_POLICY,
  };
  
  static int ip6mr_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
  				struct fib_rule_hdr *frh, struct nlattr **tb)
  {
  	return 0;
  }
  
  static int ip6mr_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
  			      struct nlattr **tb)
  {
  	return 1;
  }
  
  static int ip6mr_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
  			   struct fib_rule_hdr *frh)
  {
  	frh->dst_len = 0;
  	frh->src_len = 0;
  	frh->tos     = 0;
  	return 0;
  }
04a6f82cf   Andi Kleen   sections: fix sec...
206
  static const struct fib_rules_ops __net_initconst ip6mr_rules_ops_template = {
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
207
208
209
210
211
212
213
  	.family		= RTNL_FAMILY_IP6MR,
  	.rule_size	= sizeof(struct ip6mr_rule),
  	.addr_size	= sizeof(struct in6_addr),
  	.action		= ip6mr_rule_action,
  	.match		= ip6mr_rule_match,
  	.configure	= ip6mr_rule_configure,
  	.compare	= ip6mr_rule_compare,
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
  	.fill		= ip6mr_rule_fill,
  	.nlgroup	= RTNLGRP_IPV6_RULE,
  	.policy		= ip6mr_rule_policy,
  	.owner		= THIS_MODULE,
  };
  
  static int __net_init ip6mr_rules_init(struct net *net)
  {
  	struct fib_rules_ops *ops;
  	struct mr6_table *mrt;
  	int err;
  
  	ops = fib_rules_register(&ip6mr_rules_ops_template, net);
  	if (IS_ERR(ops))
  		return PTR_ERR(ops);
  
  	INIT_LIST_HEAD(&net->ipv6.mr6_tables);
  
  	mrt = ip6mr_new_table(net, RT6_TABLE_DFLT);
63159f29b   Ian Morris   ipv6: coding styl...
233
  	if (!mrt) {
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
234
235
236
237
238
239
240
241
242
243
244
245
  		err = -ENOMEM;
  		goto err1;
  	}
  
  	err = fib_default_rule_add(ops, 0x7fff, RT6_TABLE_DFLT, 0);
  	if (err < 0)
  		goto err2;
  
  	net->ipv6.mr6_rules_ops = ops;
  	return 0;
  
  err2:
f243e5a78   WANG Cong   ipmr,ip6mr: call ...
246
  	ip6mr_free_table(mrt);
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
247
248
249
250
251
252
253
254
  err1:
  	fib_rules_unregister(ops);
  	return err;
  }
  
  static void __net_exit ip6mr_rules_exit(struct net *net)
  {
  	struct mr6_table *mrt, *next;
905a6f96a   Hannes Frederic Sowa   ipv6: take rtnl_l...
255
  	rtnl_lock();
035320d54   Eric Dumazet   ipmr: dont corrup...
256
257
  	list_for_each_entry_safe(mrt, next, &net->ipv6.mr6_tables, list) {
  		list_del(&mrt->list);
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
258
  		ip6mr_free_table(mrt);
035320d54   Eric Dumazet   ipmr: dont corrup...
259
  	}
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
260
  	fib_rules_unregister(net->ipv6.mr6_rules_ops);
419df12fb   WANG Cong   net: move fib_rul...
261
  	rtnl_unlock();
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
262
263
264
265
266
267
268
269
270
  }
  #else
  #define ip6mr_for_each_table(mrt, net) \
  	for (mrt = net->ipv6.mrt6; mrt; mrt = NULL)
  
  static struct mr6_table *ip6mr_get_table(struct net *net, u32 id)
  {
  	return net->ipv6.mrt6;
  }
4c9483b2f   David S. Miller   ipv6: Convert to ...
271
  static int ip6mr_fib_lookup(struct net *net, struct flowi6 *flp6,
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
272
273
274
275
276
277
278
279
280
281
282
283
284
285
  			    struct mr6_table **mrt)
  {
  	*mrt = net->ipv6.mrt6;
  	return 0;
  }
  
  static int __net_init ip6mr_rules_init(struct net *net)
  {
  	net->ipv6.mrt6 = ip6mr_new_table(net, RT6_TABLE_DFLT);
  	return net->ipv6.mrt6 ? 0 : -ENOMEM;
  }
  
  static void __net_exit ip6mr_rules_exit(struct net *net)
  {
905a6f96a   Hannes Frederic Sowa   ipv6: take rtnl_l...
286
  	rtnl_lock();
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
287
  	ip6mr_free_table(net->ipv6.mrt6);
905a6f96a   Hannes Frederic Sowa   ipv6: take rtnl_l...
288
289
  	net->ipv6.mrt6 = NULL;
  	rtnl_unlock();
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
290
291
292
293
294
295
296
297
298
  }
  #endif
  
  static struct mr6_table *ip6mr_new_table(struct net *net, u32 id)
  {
  	struct mr6_table *mrt;
  	unsigned int i;
  
  	mrt = ip6mr_get_table(net, id);
53b24b8f9   Ian Morris   ipv6: coding styl...
299
  	if (mrt)
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
300
301
302
  		return mrt;
  
  	mrt = kzalloc(sizeof(*mrt), GFP_KERNEL);
63159f29b   Ian Morris   ipv6: coding styl...
303
  	if (!mrt)
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
  		return NULL;
  	mrt->id = id;
  	write_pnet(&mrt->net, net);
  
  	/* Forwarding cache */
  	for (i = 0; i < MFC6_LINES; i++)
  		INIT_LIST_HEAD(&mrt->mfc6_cache_array[i]);
  
  	INIT_LIST_HEAD(&mrt->mfc6_unres_queue);
  
  	setup_timer(&mrt->ipmr_expire_timer, ipmr_expire_process,
  		    (unsigned long)mrt);
  
  #ifdef CONFIG_IPV6_PIMSM_V2
  	mrt->mroute_reg_vif_num = -1;
  #endif
  #ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
  	list_add_tail_rcu(&mrt->list, &net->ipv6.mr6_tables);
  #endif
  	return mrt;
  }
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
325

d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
326
327
  static void ip6mr_free_table(struct mr6_table *mrt)
  {
7ba0c47c3   WANG Cong   ip6mr: call del_t...
328
  	del_timer_sync(&mrt->ipmr_expire_timer);
4c6980462   Nikolay Aleksandrov   net: ip6mr: fix s...
329
  	mroute_clean_tables(mrt, true);
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
330
331
  	kfree(mrt);
  }
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
332
333
334
335
  
  #ifdef CONFIG_PROC_FS
  
  struct ipmr_mfc_iter {
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
336
  	struct seq_net_private p;
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
337
  	struct mr6_table *mrt;
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
338
  	struct list_head *cache;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
339
340
  	int ct;
  };
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
341
342
  static struct mfc6_cache *ipmr_mfc_seq_idx(struct net *net,
  					   struct ipmr_mfc_iter *it, loff_t pos)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
343
  {
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
344
  	struct mr6_table *mrt = it->mrt;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
345
  	struct mfc6_cache *mfc;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
346
  	read_lock(&mrt_lock);
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
347
  	for (it->ct = 0; it->ct < MFC6_LINES; it->ct++) {
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
348
  		it->cache = &mrt->mfc6_cache_array[it->ct];
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
349
  		list_for_each_entry(mfc, it->cache, list)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
350
351
  			if (pos-- == 0)
  				return mfc;
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
352
  	}
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
353
  	read_unlock(&mrt_lock);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
354
  	spin_lock_bh(&mfc_unres_lock);
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
355
  	it->cache = &mrt->mfc6_unres_queue;
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
356
  	list_for_each_entry(mfc, it->cache, list)
c476efbcd   Patrick McHardy   ipv6: ip6mr: move...
357
  		if (pos-- == 0)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
358
359
360
361
362
363
  			return mfc;
  	spin_unlock_bh(&mfc_unres_lock);
  
  	it->cache = NULL;
  	return NULL;
  }
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
364
365
366
367
368
  /*
   *	The /proc interfaces to multicast routing /proc/ip6_mr_cache /proc/ip6_mr_vif
   */
  
  struct ipmr_vif_iter {
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
369
  	struct seq_net_private p;
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
370
  	struct mr6_table *mrt;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
371
372
  	int ct;
  };
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
373
374
  static struct mif_device *ip6mr_vif_seq_idx(struct net *net,
  					    struct ipmr_vif_iter *iter,
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
375
376
  					    loff_t pos)
  {
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
377
  	struct mr6_table *mrt = iter->mrt;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
378
379
380
  
  	for (iter->ct = 0; iter->ct < mrt->maxvif; ++iter->ct) {
  		if (!MIF_EXISTS(mrt, iter->ct))
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
381
382
  			continue;
  		if (pos-- == 0)
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
383
  			return &mrt->vif6_table[iter->ct];
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
384
385
386
387
388
389
390
  	}
  	return NULL;
  }
  
  static void *ip6mr_vif_seq_start(struct seq_file *seq, loff_t *pos)
  	__acquires(mrt_lock)
  {
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
391
  	struct ipmr_vif_iter *iter = seq->private;
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
392
  	struct net *net = seq_file_net(seq);
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
393
394
395
  	struct mr6_table *mrt;
  
  	mrt = ip6mr_get_table(net, RT6_TABLE_DFLT);
63159f29b   Ian Morris   ipv6: coding styl...
396
  	if (!mrt)
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
397
398
399
  		return ERR_PTR(-ENOENT);
  
  	iter->mrt = mrt;
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
400

7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
401
  	read_lock(&mrt_lock);
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
402
403
  	return *pos ? ip6mr_vif_seq_idx(net, seq->private, *pos - 1)
  		: SEQ_START_TOKEN;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
404
405
406
407
408
  }
  
  static void *ip6mr_vif_seq_next(struct seq_file *seq, void *v, loff_t *pos)
  {
  	struct ipmr_vif_iter *iter = seq->private;
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
409
  	struct net *net = seq_file_net(seq);
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
410
  	struct mr6_table *mrt = iter->mrt;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
411
412
413
  
  	++*pos;
  	if (v == SEQ_START_TOKEN)
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
414
  		return ip6mr_vif_seq_idx(net, iter, 0);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
415

6bd521433   Patrick McHardy   ipv6: ip6mr: move...
416
417
  	while (++iter->ct < mrt->maxvif) {
  		if (!MIF_EXISTS(mrt, iter->ct))
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
418
  			continue;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
419
  		return &mrt->vif6_table[iter->ct];
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
420
421
422
423
424
425
426
427
428
429
430
431
  	}
  	return NULL;
  }
  
  static void ip6mr_vif_seq_stop(struct seq_file *seq, void *v)
  	__releases(mrt_lock)
  {
  	read_unlock(&mrt_lock);
  }
  
  static int ip6mr_vif_seq_show(struct seq_file *seq, void *v)
  {
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
432
433
  	struct ipmr_vif_iter *iter = seq->private;
  	struct mr6_table *mrt = iter->mrt;
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
434

7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
435
436
437
438
439
440
441
442
443
  	if (v == SEQ_START_TOKEN) {
  		seq_puts(seq,
  			 "Interface      BytesIn  PktsIn  BytesOut PktsOut Flags
  ");
  	} else {
  		const struct mif_device *vif = v;
  		const char *name = vif->dev ? vif->dev->name : "none";
  
  		seq_printf(seq,
d430a227d   Al Viro   bogus format in i...
444
445
  			   "%2td %-10s %8ld %7ld  %8ld %7ld %05X
  ",
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
446
  			   vif - mrt->vif6_table,
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
447
448
449
450
451
452
  			   name, vif->bytes_in, vif->pkt_in,
  			   vif->bytes_out, vif->pkt_out,
  			   vif->flags);
  	}
  	return 0;
  }
98147d527   Stephen Hemminger   net: seq_operatio...
453
  static const struct seq_operations ip6mr_vif_seq_ops = {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
454
455
456
457
458
459
460
461
  	.start = ip6mr_vif_seq_start,
  	.next  = ip6mr_vif_seq_next,
  	.stop  = ip6mr_vif_seq_stop,
  	.show  = ip6mr_vif_seq_show,
  };
  
  static int ip6mr_vif_open(struct inode *inode, struct file *file)
  {
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
462
463
  	return seq_open_net(inode, file, &ip6mr_vif_seq_ops,
  			    sizeof(struct ipmr_vif_iter));
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
464
  }
5ca1b998d   Stephen Hemminger   net: file_operati...
465
  static const struct file_operations ip6mr_vif_fops = {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
466
467
468
469
  	.owner	 = THIS_MODULE,
  	.open    = ip6mr_vif_open,
  	.read    = seq_read,
  	.llseek  = seq_lseek,
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
470
  	.release = seq_release_net,
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
471
472
473
474
  };
  
  static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos)
  {
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
475
  	struct ipmr_mfc_iter *it = seq->private;
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
476
  	struct net *net = seq_file_net(seq);
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
477
  	struct mr6_table *mrt;
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
478

d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
479
  	mrt = ip6mr_get_table(net, RT6_TABLE_DFLT);
63159f29b   Ian Morris   ipv6: coding styl...
480
  	if (!mrt)
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
481
482
483
  		return ERR_PTR(-ENOENT);
  
  	it->mrt = mrt;
2726946df   Nikolay Aleksandrov   ip6mr: fix stale ...
484
  	it->cache = NULL;
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
485
486
  	return *pos ? ipmr_mfc_seq_idx(net, seq->private, *pos - 1)
  		: SEQ_START_TOKEN;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
487
488
489
490
491
492
  }
  
  static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
  {
  	struct mfc6_cache *mfc = v;
  	struct ipmr_mfc_iter *it = seq->private;
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
493
  	struct net *net = seq_file_net(seq);
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
494
  	struct mr6_table *mrt = it->mrt;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
495
496
497
498
  
  	++*pos;
  
  	if (v == SEQ_START_TOKEN)
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
499
  		return ipmr_mfc_seq_idx(net, seq->private, 0);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
500

f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
501
502
  	if (mfc->list.next != it->cache)
  		return list_entry(mfc->list.next, struct mfc6_cache, list);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
503

6bd521433   Patrick McHardy   ipv6: ip6mr: move...
504
  	if (it->cache == &mrt->mfc6_unres_queue)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
505
  		goto end_of_list;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
506
  	BUG_ON(it->cache != &mrt->mfc6_cache_array[it->ct]);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
507

4a6258a0e   Benjamin Thery   netns: ip6mr: dyn...
508
  	while (++it->ct < MFC6_LINES) {
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
509
  		it->cache = &mrt->mfc6_cache_array[it->ct];
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
510
511
512
  		if (list_empty(it->cache))
  			continue;
  		return list_first_entry(it->cache, struct mfc6_cache, list);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
513
514
515
516
  	}
  
  	/* exhausted cache_array, show unresolved */
  	read_unlock(&mrt_lock);
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
517
  	it->cache = &mrt->mfc6_unres_queue;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
518
519
520
  	it->ct = 0;
  
  	spin_lock_bh(&mfc_unres_lock);
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
521
522
  	if (!list_empty(it->cache))
  		return list_first_entry(it->cache, struct mfc6_cache, list);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
523
524
525
526
527
528
529
530
531
532
533
  
   end_of_list:
  	spin_unlock_bh(&mfc_unres_lock);
  	it->cache = NULL;
  
  	return NULL;
  }
  
  static void ipmr_mfc_seq_stop(struct seq_file *seq, void *v)
  {
  	struct ipmr_mfc_iter *it = seq->private;
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
534
  	struct mr6_table *mrt = it->mrt;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
535

6bd521433   Patrick McHardy   ipv6: ip6mr: move...
536
  	if (it->cache == &mrt->mfc6_unres_queue)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
537
  		spin_unlock_bh(&mfc_unres_lock);
25b4a44c1   Richard Laing   net/ipv6: Correct...
538
  	else if (it->cache == &mrt->mfc6_cache_array[it->ct])
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
  		read_unlock(&mrt_lock);
  }
  
  static int ipmr_mfc_seq_show(struct seq_file *seq, void *v)
  {
  	int n;
  
  	if (v == SEQ_START_TOKEN) {
  		seq_puts(seq,
  			 "Group                            "
  			 "Origin                           "
  			 "Iif      Pkts  Bytes     Wrong  Oifs
  ");
  	} else {
  		const struct mfc6_cache *mfc = v;
  		const struct ipmr_mfc_iter *it = seq->private;
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
555
  		struct mr6_table *mrt = it->mrt;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
556

999890b21   Benjamin Thery   net: /proc/net/ip...
557
  		seq_printf(seq, "%pI6 %pI6 %-3hd",
0c6ce78ab   Harvey Harrison   net: replace uses...
558
  			   &mfc->mf6c_mcastgrp, &mfc->mf6c_origin,
1ea472e2d   Benjamin Thery   net: fix /proc/ne...
559
  			   mfc->mf6c_parent);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
560

6bd521433   Patrick McHardy   ipv6: ip6mr: move...
561
  		if (it->cache != &mrt->mfc6_unres_queue) {
1ea472e2d   Benjamin Thery   net: fix /proc/ne...
562
563
564
565
  			seq_printf(seq, " %8lu %8lu %8lu",
  				   mfc->mfc_un.res.pkt,
  				   mfc->mfc_un.res.bytes,
  				   mfc->mfc_un.res.wrong_if);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
566
567
  			for (n = mfc->mfc_un.res.minvif;
  			     n < mfc->mfc_un.res.maxvif; n++) {
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
568
  				if (MIF_EXISTS(mrt, n) &&
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
569
570
571
572
573
  				    mfc->mfc_un.res.ttls[n] < 255)
  					seq_printf(seq,
  						   " %2d:%-3d",
  						   n, mfc->mfc_un.res.ttls[n]);
  			}
1ea472e2d   Benjamin Thery   net: fix /proc/ne...
574
575
576
577
578
  		} else {
  			/* unresolved mfc_caches don't contain
  			 * pkt, bytes and wrong_if values
  			 */
  			seq_printf(seq, " %8lu %8lu %8lu", 0ul, 0ul, 0ul);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
579
580
581
582
583
584
  		}
  		seq_putc(seq, '
  ');
  	}
  	return 0;
  }
88e9d34c7   James Morris   seq_file: constif...
585
  static const struct seq_operations ipmr_mfc_seq_ops = {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
586
587
588
589
590
591
592
593
  	.start = ipmr_mfc_seq_start,
  	.next  = ipmr_mfc_seq_next,
  	.stop  = ipmr_mfc_seq_stop,
  	.show  = ipmr_mfc_seq_show,
  };
  
  static int ipmr_mfc_open(struct inode *inode, struct file *file)
  {
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
594
595
  	return seq_open_net(inode, file, &ipmr_mfc_seq_ops,
  			    sizeof(struct ipmr_mfc_iter));
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
596
  }
5ca1b998d   Stephen Hemminger   net: file_operati...
597
  static const struct file_operations ip6mr_mfc_fops = {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
598
599
600
601
  	.owner	 = THIS_MODULE,
  	.open    = ipmr_mfc_open,
  	.read    = seq_read,
  	.llseek  = seq_lseek,
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
602
  	.release = seq_release_net,
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
603
604
  };
  #endif
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
605
  #ifdef CONFIG_IPV6_PIMSM_V2
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
606
607
608
609
610
611
  
  static int pim6_rcv(struct sk_buff *skb)
  {
  	struct pimreghdr *pim;
  	struct ipv6hdr   *encap;
  	struct net_device  *reg_dev = NULL;
8229efdae   Benjamin Thery   netns: ip6mr: ena...
612
  	struct net *net = dev_net(skb->dev);
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
613
  	struct mr6_table *mrt;
4c9483b2f   David S. Miller   ipv6: Convert to ...
614
615
616
  	struct flowi6 fl6 = {
  		.flowi6_iif	= skb->dev->ifindex,
  		.flowi6_mark	= skb->mark,
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
617
618
  	};
  	int reg_vif_num;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
619
620
621
622
623
  
  	if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(*encap)))
  		goto drop;
  
  	pim = (struct pimreghdr *)skb_transport_header(skb);
56245cae1   Nikolay Aleksandrov   net: pim: add all...
624
  	if (pim->type != ((PIM_VERSION << 4) | PIM_TYPE_REGISTER) ||
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
625
  	    (pim->flags & PIM_NULL_REGISTER) ||
1d6e55f19   Thomas Goff   IPv6: Fix multica...
626
627
628
  	    (csum_ipv6_magic(&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
  			     sizeof(*pim), IPPROTO_PIM,
  			     csum_partial((void *)pim, sizeof(*pim), 0)) &&
ec6b486fa   Al Viro   ipv6: result of c...
629
  	     csum_fold(skb_checksum(skb, 0, skb->len, 0))))
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
630
631
632
633
634
635
636
637
638
639
  		goto drop;
  
  	/* check if the inner packet is destined to mcast group */
  	encap = (struct ipv6hdr *)(skb_transport_header(skb) +
  				   sizeof(*pim));
  
  	if (!ipv6_addr_is_multicast(&encap->daddr) ||
  	    encap->payload_len == 0 ||
  	    ntohs(encap->payload_len) + sizeof(*pim) > skb->len)
  		goto drop;
4c9483b2f   David S. Miller   ipv6: Convert to ...
640
  	if (ip6mr_fib_lookup(net, &fl6, &mrt) < 0)
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
641
642
  		goto drop;
  	reg_vif_num = mrt->mroute_reg_vif_num;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
643
644
  	read_lock(&mrt_lock);
  	if (reg_vif_num >= 0)
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
645
  		reg_dev = mrt->vif6_table[reg_vif_num].dev;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
646
647
648
  	if (reg_dev)
  		dev_hold(reg_dev);
  	read_unlock(&mrt_lock);
63159f29b   Ian Morris   ipv6: coding styl...
649
  	if (!reg_dev)
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
650
651
652
653
654
  		goto drop;
  
  	skb->mac_header = skb->network_header;
  	skb_pull(skb, (u8 *)encap - skb->data);
  	skb_reset_network_header(skb);
1d6e55f19   Thomas Goff   IPv6: Fix multica...
655
  	skb->protocol = htons(ETH_P_IPV6);
3e49e6d52   Cesar Eduardo Barros   net: use CHECKSUM...
656
  	skb->ip_summed = CHECKSUM_NONE;
d19d56ddc   Eric Dumazet   net: Introduce sk...
657

ea23192e8   Nicolas Dichtel   tunnels: harmoniz...
658
  	skb_tunnel_rx(skb, reg_dev, dev_net(reg_dev));
d19d56ddc   Eric Dumazet   net: Introduce sk...
659

caf586e5f   Eric Dumazet   net: add a core n...
660
  	netif_rx(skb);
8990f468a   Eric Dumazet   net: rx_dropped a...
661

14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
662
663
664
665
666
667
  	dev_put(reg_dev);
  	return 0;
   drop:
  	kfree_skb(skb);
  	return 0;
  }
41135cc83   Alexey Dobriyan   net: constify str...
668
  static const struct inet6_protocol pim6_protocol = {
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
669
670
671
672
  	.handler	=	pim6_rcv,
  };
  
  /* Service routines creating virtual interfaces: PIMREG */
6fef4c0c8   Stephen Hemminger   netdev: convert p...
673
674
  static netdev_tx_t reg_vif_xmit(struct sk_buff *skb,
  				      struct net_device *dev)
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
675
  {
8229efdae   Benjamin Thery   netns: ip6mr: ena...
676
  	struct net *net = dev_net(dev);
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
677
  	struct mr6_table *mrt;
4c9483b2f   David S. Miller   ipv6: Convert to ...
678
679
  	struct flowi6 fl6 = {
  		.flowi6_oif	= dev->ifindex,
6a662719c   Cong Wang   ipv4, fib: pass L...
680
  		.flowi6_iif	= skb->skb_iif ? : LOOPBACK_IFINDEX,
4c9483b2f   David S. Miller   ipv6: Convert to ...
681
  		.flowi6_mark	= skb->mark,
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
682
683
  	};
  	int err;
4c9483b2f   David S. Miller   ipv6: Convert to ...
684
  	err = ip6mr_fib_lookup(net, &fl6, &mrt);
67928c404   Ben Greear   ipv6-multicast: F...
685
686
  	if (err < 0) {
  		kfree_skb(skb);
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
687
  		return err;
67928c404   Ben Greear   ipv6-multicast: F...
688
  	}
8229efdae   Benjamin Thery   netns: ip6mr: ena...
689

14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
690
  	read_lock(&mrt_lock);
dc58c78c0   Pavel Emelyanov   ip6mr: Use on-dev...
691
692
  	dev->stats.tx_bytes += skb->len;
  	dev->stats.tx_packets++;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
693
  	ip6mr_cache_report(mrt, skb, mrt->mroute_reg_vif_num, MRT6MSG_WHOLEPKT);
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
694
695
  	read_unlock(&mrt_lock);
  	kfree_skb(skb);
6ed106549   Patrick McHardy   net: use NETDEV_T...
696
  	return NETDEV_TX_OK;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
697
  }
ee9b9596a   Nicolas Dichtel   ipmr,ip6mr: imple...
698
699
700
701
  static int reg_vif_get_iflink(const struct net_device *dev)
  {
  	return 0;
  }
007c3838d   Stephen Hemminger   ipmr: convert ipm...
702
703
  static const struct net_device_ops reg_vif_netdev_ops = {
  	.ndo_start_xmit	= reg_vif_xmit,
ee9b9596a   Nicolas Dichtel   ipmr,ip6mr: imple...
704
  	.ndo_get_iflink = reg_vif_get_iflink,
007c3838d   Stephen Hemminger   ipmr: convert ipm...
705
  };
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
706
707
708
709
710
  static void reg_vif_setup(struct net_device *dev)
  {
  	dev->type		= ARPHRD_PIMREG;
  	dev->mtu		= 1500 - sizeof(struct ipv6hdr) - 8;
  	dev->flags		= IFF_NOARP;
007c3838d   Stephen Hemminger   ipmr: convert ipm...
711
  	dev->netdev_ops		= &reg_vif_netdev_ops;
cf124db56   David S. Miller   net: Fix inconsis...
712
  	dev->needs_free_netdev	= true;
403dbb97f   Tom Goff   PIM-SM: namespace...
713
  	dev->features		|= NETIF_F_NETNS_LOCAL;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
714
  }
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
715
  static struct net_device *ip6mr_reg_vif(struct net *net, struct mr6_table *mrt)
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
716
717
  {
  	struct net_device *dev;
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
718
719
720
721
722
723
  	char name[IFNAMSIZ];
  
  	if (mrt->id == RT6_TABLE_DFLT)
  		sprintf(name, "pim6reg");
  	else
  		sprintf(name, "pim6reg%u", mrt->id);
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
724

c835a6773   Tom Gundersen   net: set name_ass...
725
  	dev = alloc_netdev(0, name, NET_NAME_UNKNOWN, reg_vif_setup);
63159f29b   Ian Morris   ipv6: coding styl...
726
  	if (!dev)
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
727
  		return NULL;
8229efdae   Benjamin Thery   netns: ip6mr: ena...
728
  	dev_net_set(dev, net);
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
729
730
731
732
  	if (register_netdevice(dev)) {
  		free_netdev(dev);
  		return NULL;
  	}
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
733

14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
734
735
  	if (dev_open(dev))
  		goto failure;
7af3db78a   Wang Chen   ipv6: Fix using a...
736
  	dev_hold(dev);
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
737
738
739
  	return dev;
  
  failure:
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
740
741
742
743
  	unregister_netdevice(dev);
  	return NULL;
  }
  #endif
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
744
745
746
  /*
   *	Delete a VIF entry
   */
723b929ca   Nikolay Aleksandrov   ip6mr: fix notifi...
747
748
  static int mif6_delete(struct mr6_table *mrt, int vifi, int notify,
  		       struct list_head *head)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
749
750
751
  {
  	struct mif_device *v;
  	struct net_device *dev;
1d6e55f19   Thomas Goff   IPv6: Fix multica...
752
  	struct inet6_dev *in6_dev;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
753
754
  
  	if (vifi < 0 || vifi >= mrt->maxvif)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
755
  		return -EADDRNOTAVAIL;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
756
  	v = &mrt->vif6_table[vifi];
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
757
758
759
760
761
762
763
764
765
  
  	write_lock_bh(&mrt_lock);
  	dev = v->dev;
  	v->dev = NULL;
  
  	if (!dev) {
  		write_unlock_bh(&mrt_lock);
  		return -EADDRNOTAVAIL;
  	}
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
766
  #ifdef CONFIG_IPV6_PIMSM_V2
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
767
768
  	if (vifi == mrt->mroute_reg_vif_num)
  		mrt->mroute_reg_vif_num = -1;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
769
  #endif
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
770
  	if (vifi + 1 == mrt->maxvif) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
771
772
  		int tmp;
  		for (tmp = vifi - 1; tmp >= 0; tmp--) {
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
773
  			if (MIF_EXISTS(mrt, tmp))
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
774
775
  				break;
  		}
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
776
  		mrt->maxvif = tmp + 1;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
777
778
779
780
781
  	}
  
  	write_unlock_bh(&mrt_lock);
  
  	dev_set_allmulti(dev, -1);
1d6e55f19   Thomas Goff   IPv6: Fix multica...
782
  	in6_dev = __in6_dev_get(dev);
d67b8c616   Nicolas Dichtel   netconf: advertis...
783
  	if (in6_dev) {
1d6e55f19   Thomas Goff   IPv6: Fix multica...
784
  		in6_dev->cnf.mc_forwarding--;
85b3daada   David Ahern   net: ipv6: Refact...
785
  		inet6_netconf_notify_devconf(dev_net(dev), RTM_NEWNETCONF,
d67b8c616   Nicolas Dichtel   netconf: advertis...
786
787
788
  					     NETCONFA_MC_FORWARDING,
  					     dev->ifindex, &in6_dev->cnf);
  	}
1d6e55f19   Thomas Goff   IPv6: Fix multica...
789

723b929ca   Nikolay Aleksandrov   ip6mr: fix notifi...
790
  	if ((v->flags & MIFF_REGISTER) && !notify)
c871e664e   Eric Dumazet   ip6mr: Optimize m...
791
  		unregister_netdevice_queue(dev, head);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
792
793
794
795
  
  	dev_put(dev);
  	return 0;
  }
58701ad41   Benjamin Thery   netns: ip6mr: sto...
796
797
  static inline void ip6mr_cache_free(struct mfc6_cache *c)
  {
58701ad41   Benjamin Thery   netns: ip6mr: sto...
798
799
  	kmem_cache_free(mrt_cachep, c);
  }
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
800
801
802
  /* Destroy an unresolved cache entry, killing queued skbs
     and reporting error to netlink readers.
   */
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
803
  static void ip6mr_destroy_unres(struct mr6_table *mrt, struct mfc6_cache *c)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
804
  {
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
805
  	struct net *net = read_pnet(&mrt->net);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
806
  	struct sk_buff *skb;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
807
  	atomic_dec(&mrt->cache_resolve_queue_len);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
808

67ba4152e   Ian Morris   ipv6: White-space...
809
  	while ((skb = skb_dequeue(&c->mfc_un.unres.unresolved)) != NULL) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
810
  		if (ipv6_hdr(skb)->version == 0) {
af72868b9   Johannes Berg   networking: make ...
811
812
  			struct nlmsghdr *nlh = skb_pull(skb,
  							sizeof(struct ipv6hdr));
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
813
  			nlh->nlmsg_type = NLMSG_ERROR;
573ce260b   Hong zhi guo   net-next: replace...
814
  			nlh->nlmsg_len = nlmsg_msg_size(sizeof(struct nlmsgerr));
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
815
  			skb_trim(skb, nlh->nlmsg_len);
573ce260b   Hong zhi guo   net-next: replace...
816
  			((struct nlmsgerr *)nlmsg_data(nlh))->error = -ETIMEDOUT;
15e473046   Eric W. Biederman   netlink: Rename p...
817
  			rtnl_unicast(skb, net, NETLINK_CB(skb).portid);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
818
819
820
  		} else
  			kfree_skb(skb);
  	}
58701ad41   Benjamin Thery   netns: ip6mr: sto...
821
  	ip6mr_cache_free(c);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
822
  }
c476efbcd   Patrick McHardy   ipv6: ip6mr: move...
823
  /* Timer process for all the unresolved queue. */
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
824

6bd521433   Patrick McHardy   ipv6: ip6mr: move...
825
  static void ipmr_do_expire_process(struct mr6_table *mrt)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
826
827
828
  {
  	unsigned long now = jiffies;
  	unsigned long expires = 10 * HZ;
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
829
  	struct mfc6_cache *c, *next;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
830

6bd521433   Patrick McHardy   ipv6: ip6mr: move...
831
  	list_for_each_entry_safe(c, next, &mrt->mfc6_unres_queue, list) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
832
833
834
835
836
  		if (time_after(c->mfc_un.unres.expires, now)) {
  			/* not yet... */
  			unsigned long interval = c->mfc_un.unres.expires - now;
  			if (interval < expires)
  				expires = interval;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
837
838
  			continue;
  		}
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
839
  		list_del(&c->list);
812e44dd1   Nicolas Dichtel   ip6mr: advertise ...
840
  		mr6_netlink_event(mrt, c, RTM_DELROUTE);
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
841
  		ip6mr_destroy_unres(mrt, c);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
842
  	}
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
843
844
  	if (!list_empty(&mrt->mfc6_unres_queue))
  		mod_timer(&mrt->ipmr_expire_timer, jiffies + expires);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
845
  }
c476efbcd   Patrick McHardy   ipv6: ip6mr: move...
846
  static void ipmr_expire_process(unsigned long arg)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
847
  {
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
848
  	struct mr6_table *mrt = (struct mr6_table *)arg;
c476efbcd   Patrick McHardy   ipv6: ip6mr: move...
849

7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
850
  	if (!spin_trylock(&mfc_unres_lock)) {
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
851
  		mod_timer(&mrt->ipmr_expire_timer, jiffies + 1);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
852
853
  		return;
  	}
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
854
855
  	if (!list_empty(&mrt->mfc6_unres_queue))
  		ipmr_do_expire_process(mrt);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
856
857
858
859
860
  
  	spin_unlock(&mfc_unres_lock);
  }
  
  /* Fill oifs list. It is called under write locked mrt_lock. */
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
861
  static void ip6mr_update_thresholds(struct mr6_table *mrt, struct mfc6_cache *cache,
b5aa30b19   Patrick McHardy   ipv6: ip6mr: remo...
862
  				    unsigned char *ttls)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
863
864
  {
  	int vifi;
6ac7eb086   Rami Rosen   [IPV6] MROUTE: Ad...
865
  	cache->mfc_un.res.minvif = MAXMIFS;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
866
  	cache->mfc_un.res.maxvif = 0;
6ac7eb086   Rami Rosen   [IPV6] MROUTE: Ad...
867
  	memset(cache->mfc_un.res.ttls, 255, MAXMIFS);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
868

6bd521433   Patrick McHardy   ipv6: ip6mr: move...
869
870
  	for (vifi = 0; vifi < mrt->maxvif; vifi++) {
  		if (MIF_EXISTS(mrt, vifi) &&
4e16880cb   Benjamin Thery   netns: ip6mr: dyn...
871
  		    ttls[vifi] && ttls[vifi] < 255) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
872
873
874
875
876
877
878
  			cache->mfc_un.res.ttls[vifi] = ttls[vifi];
  			if (cache->mfc_un.res.minvif > vifi)
  				cache->mfc_un.res.minvif = vifi;
  			if (cache->mfc_un.res.maxvif <= vifi)
  				cache->mfc_un.res.maxvif = vifi + 1;
  		}
  	}
90b5ca176   Nikolay Aleksandrov   net: ipmr/ip6mr: ...
879
  	cache->mfc_un.res.lastuse = jiffies;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
880
  }
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
881
882
  static int mif6_add(struct net *net, struct mr6_table *mrt,
  		    struct mif6ctl *vifc, int mrtsock)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
883
884
  {
  	int vifi = vifc->mif6c_mifi;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
885
  	struct mif_device *v = &mrt->vif6_table[vifi];
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
886
  	struct net_device *dev;
1d6e55f19   Thomas Goff   IPv6: Fix multica...
887
  	struct inet6_dev *in6_dev;
5ae7b4441   Wang Chen   ipv6: Check retur...
888
  	int err;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
889
890
  
  	/* Is vif busy ? */
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
891
  	if (MIF_EXISTS(mrt, vifi))
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
892
893
894
  		return -EADDRINUSE;
  
  	switch (vifc->mif6c_flags) {
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
895
896
897
898
899
900
  #ifdef CONFIG_IPV6_PIMSM_V2
  	case MIFF_REGISTER:
  		/*
  		 * Special Purpose VIF in PIM
  		 * All the packets will be sent to the daemon
  		 */
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
901
  		if (mrt->mroute_reg_vif_num >= 0)
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
902
  			return -EADDRINUSE;
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
903
  		dev = ip6mr_reg_vif(net, mrt);
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
904
905
  		if (!dev)
  			return -ENOBUFS;
5ae7b4441   Wang Chen   ipv6: Check retur...
906
907
908
  		err = dev_set_allmulti(dev, 1);
  		if (err) {
  			unregister_netdevice(dev);
7af3db78a   Wang Chen   ipv6: Fix using a...
909
  			dev_put(dev);
5ae7b4441   Wang Chen   ipv6: Check retur...
910
911
  			return err;
  		}
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
912
913
  		break;
  #endif
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
914
  	case 0:
8229efdae   Benjamin Thery   netns: ip6mr: ena...
915
  		dev = dev_get_by_index(net, vifc->mif6c_pifi);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
916
917
  		if (!dev)
  			return -EADDRNOTAVAIL;
5ae7b4441   Wang Chen   ipv6: Check retur...
918
  		err = dev_set_allmulti(dev, 1);
7af3db78a   Wang Chen   ipv6: Fix using a...
919
920
  		if (err) {
  			dev_put(dev);
5ae7b4441   Wang Chen   ipv6: Check retur...
921
  			return err;
7af3db78a   Wang Chen   ipv6: Fix using a...
922
  		}
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
923
924
925
926
  		break;
  	default:
  		return -EINVAL;
  	}
1d6e55f19   Thomas Goff   IPv6: Fix multica...
927
  	in6_dev = __in6_dev_get(dev);
d67b8c616   Nicolas Dichtel   netconf: advertis...
928
  	if (in6_dev) {
1d6e55f19   Thomas Goff   IPv6: Fix multica...
929
  		in6_dev->cnf.mc_forwarding++;
85b3daada   David Ahern   net: ipv6: Refact...
930
  		inet6_netconf_notify_devconf(dev_net(dev), RTM_NEWNETCONF,
d67b8c616   Nicolas Dichtel   netconf: advertis...
931
932
933
  					     NETCONFA_MC_FORWARDING,
  					     dev->ifindex, &in6_dev->cnf);
  	}
1d6e55f19   Thomas Goff   IPv6: Fix multica...
934

7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
935
936
937
938
939
940
941
942
943
944
945
946
947
948
  	/*
  	 *	Fill in the VIF structures
  	 */
  	v->rate_limit = vifc->vifc_rate_limit;
  	v->flags = vifc->mif6c_flags;
  	if (!mrtsock)
  		v->flags |= VIFF_STATIC;
  	v->threshold = vifc->vifc_threshold;
  	v->bytes_in = 0;
  	v->bytes_out = 0;
  	v->pkt_in = 0;
  	v->pkt_out = 0;
  	v->link = dev->ifindex;
  	if (v->flags & MIFF_REGISTER)
a54acb3a6   Nicolas Dichtel   dev: introduce de...
949
  		v->link = dev_get_iflink(dev);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
950
951
952
  
  	/* And finish update writing critical data */
  	write_lock_bh(&mrt_lock);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
953
  	v->dev = dev;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
954
955
  #ifdef CONFIG_IPV6_PIMSM_V2
  	if (v->flags & MIFF_REGISTER)
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
956
  		mrt->mroute_reg_vif_num = vifi;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
957
  #endif
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
958
959
  	if (vifi + 1 > mrt->maxvif)
  		mrt->maxvif = vifi + 1;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
960
961
962
  	write_unlock_bh(&mrt_lock);
  	return 0;
  }
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
963
  static struct mfc6_cache *ip6mr_cache_find(struct mr6_table *mrt,
b71d1d426   Eric Dumazet   inet: constify ip...
964
965
  					   const struct in6_addr *origin,
  					   const struct in6_addr *mcastgrp)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
966
967
968
  {
  	int line = MFC6_HASH(mcastgrp, origin);
  	struct mfc6_cache *c;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
969
  	list_for_each_entry(c, &mrt->mfc6_cache_array[line], list) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
970
971
  		if (ipv6_addr_equal(&c->mf6c_origin, origin) &&
  		    ipv6_addr_equal(&c->mf6c_mcastgrp, mcastgrp))
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
972
  			return c;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
973
  	}
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
974
  	return NULL;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
975
  }
660b26dc1   Nicolas Dichtel   mcast: add multic...
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
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
  /* Look for a (*,*,oif) entry */
  static struct mfc6_cache *ip6mr_cache_find_any_parent(struct mr6_table *mrt,
  						      mifi_t mifi)
  {
  	int line = MFC6_HASH(&in6addr_any, &in6addr_any);
  	struct mfc6_cache *c;
  
  	list_for_each_entry(c, &mrt->mfc6_cache_array[line], list)
  		if (ipv6_addr_any(&c->mf6c_origin) &&
  		    ipv6_addr_any(&c->mf6c_mcastgrp) &&
  		    (c->mfc_un.res.ttls[mifi] < 255))
  			return c;
  
  	return NULL;
  }
  
  /* Look for a (*,G) entry */
  static struct mfc6_cache *ip6mr_cache_find_any(struct mr6_table *mrt,
  					       struct in6_addr *mcastgrp,
  					       mifi_t mifi)
  {
  	int line = MFC6_HASH(mcastgrp, &in6addr_any);
  	struct mfc6_cache *c, *proxy;
  
  	if (ipv6_addr_any(mcastgrp))
  		goto skip;
  
  	list_for_each_entry(c, &mrt->mfc6_cache_array[line], list)
  		if (ipv6_addr_any(&c->mf6c_origin) &&
  		    ipv6_addr_equal(&c->mf6c_mcastgrp, mcastgrp)) {
  			if (c->mfc_un.res.ttls[mifi] < 255)
  				return c;
  
  			/* It's ok if the mifi is part of the static tree */
  			proxy = ip6mr_cache_find_any_parent(mrt,
  							    c->mf6c_parent);
  			if (proxy && proxy->mfc_un.res.ttls[mifi] < 255)
  				return c;
  		}
  
  skip:
  	return ip6mr_cache_find_any_parent(mrt, mifi);
  }
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1019
1020
1021
  /*
   *	Allocate a multicast cache entry
   */
b5aa30b19   Patrick McHardy   ipv6: ip6mr: remo...
1022
  static struct mfc6_cache *ip6mr_cache_alloc(void)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1023
  {
36cbac590   Joe Perches   net/ipv6/ip6mr.c:...
1024
  	struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL);
63159f29b   Ian Morris   ipv6: coding styl...
1025
  	if (!c)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1026
  		return NULL;
70a0dec45   Tom Goff   ipmr/ip6mr: Initi...
1027
  	c->mfc_un.res.last_assert = jiffies - MFC_ASSERT_THRESH - 1;
6ac7eb086   Rami Rosen   [IPV6] MROUTE: Ad...
1028
  	c->mfc_un.res.minvif = MAXMIFS;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1029
1030
  	return c;
  }
b5aa30b19   Patrick McHardy   ipv6: ip6mr: remo...
1031
  static struct mfc6_cache *ip6mr_cache_alloc_unres(void)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1032
  {
36cbac590   Joe Perches   net/ipv6/ip6mr.c:...
1033
  	struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC);
63159f29b   Ian Morris   ipv6: coding styl...
1034
  	if (!c)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1035
  		return NULL;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1036
1037
1038
1039
1040
1041
1042
1043
  	skb_queue_head_init(&c->mfc_un.unres.unresolved);
  	c->mfc_un.unres.expires = jiffies + 10 * HZ;
  	return c;
  }
  
  /*
   *	A cache entry has gone into a resolved state from queued
   */
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1044
1045
  static void ip6mr_cache_resolve(struct net *net, struct mr6_table *mrt,
  				struct mfc6_cache *uc, struct mfc6_cache *c)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1046
1047
1048
1049
1050
1051
  {
  	struct sk_buff *skb;
  
  	/*
  	 *	Play the pending entries through our router
  	 */
67ba4152e   Ian Morris   ipv6: White-space...
1052
  	while ((skb = __skb_dequeue(&uc->mfc_un.unres.unresolved))) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1053
  		if (ipv6_hdr(skb)->version == 0) {
af72868b9   Johannes Berg   networking: make ...
1054
1055
  			struct nlmsghdr *nlh = skb_pull(skb,
  							sizeof(struct ipv6hdr));
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1056

573ce260b   Hong zhi guo   net-next: replace...
1057
  			if (__ip6mr_fill_mroute(mrt, skb, c, nlmsg_data(nlh)) > 0) {
549e028d0   YOSHIFUJI Hideaki   [IPV6] MROUTE: Us...
1058
  				nlh->nlmsg_len = skb_tail_pointer(skb) - (u8 *)nlh;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1059
1060
  			} else {
  				nlh->nlmsg_type = NLMSG_ERROR;
573ce260b   Hong zhi guo   net-next: replace...
1061
  				nlh->nlmsg_len = nlmsg_msg_size(sizeof(struct nlmsgerr));
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1062
  				skb_trim(skb, nlh->nlmsg_len);
573ce260b   Hong zhi guo   net-next: replace...
1063
  				((struct nlmsgerr *)nlmsg_data(nlh))->error = -EMSGSIZE;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1064
  			}
15e473046   Eric W. Biederman   netlink: Rename p...
1065
  			rtnl_unicast(skb, net, NETLINK_CB(skb).portid);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1066
  		} else
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1067
  			ip6_mr_forward(net, mrt, skb, c);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1068
1069
1070
1071
  	}
  }
  
  /*
dd12d15c9   Julien Gomes   ip6mr: add netlin...
1072
   *	Bounce a cache query up to pim6sd and netlink.
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1073
1074
1075
   *
   *	Called under mrt_lock.
   */
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1076
1077
  static int ip6mr_cache_report(struct mr6_table *mrt, struct sk_buff *pkt,
  			      mifi_t mifi, int assert)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1078
1079
1080
1081
  {
  	struct sk_buff *skb;
  	struct mrt6msg *msg;
  	int ret;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1082
1083
1084
1085
1086
1087
1088
  #ifdef CONFIG_IPV6_PIMSM_V2
  	if (assert == MRT6MSG_WHOLEPKT)
  		skb = skb_realloc_headroom(pkt, -skb_network_offset(pkt)
  						+sizeof(*msg));
  	else
  #endif
  		skb = alloc_skb(sizeof(struct ipv6hdr) + sizeof(*msg), GFP_ATOMIC);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1089
1090
1091
1092
1093
1094
1095
1096
  
  	if (!skb)
  		return -ENOBUFS;
  
  	/* I suppose that internal messages
  	 * do not require checksums */
  
  	skb->ip_summed = CHECKSUM_UNNECESSARY;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
  #ifdef CONFIG_IPV6_PIMSM_V2
  	if (assert == MRT6MSG_WHOLEPKT) {
  		/* Ugly, but we have no choice with this interface.
  		   Duplicate old header, fix length etc.
  		   And all this only to mangle msg->im6_msgtype and
  		   to set msg->im6_mbz to "mbz" :-)
  		 */
  		skb_push(skb, -skb_network_offset(pkt));
  
  		skb_push(skb, sizeof(*msg));
  		skb_reset_transport_header(skb);
  		msg = (struct mrt6msg *)skb_transport_header(skb);
  		msg->im6_mbz = 0;
  		msg->im6_msgtype = MRT6MSG_WHOLEPKT;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1111
  		msg->im6_mif = mrt->mroute_reg_vif_num;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1112
  		msg->im6_pad = 0;
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
1113
1114
  		msg->im6_src = ipv6_hdr(pkt)->saddr;
  		msg->im6_dst = ipv6_hdr(pkt)->daddr;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1115
1116
1117
1118
1119
  
  		skb->ip_summed = CHECKSUM_UNNECESSARY;
  	} else
  #endif
  	{
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
  	/*
  	 *	Copy the IP header
  	 */
  
  	skb_put(skb, sizeof(struct ipv6hdr));
  	skb_reset_network_header(skb);
  	skb_copy_to_linear_data(skb, ipv6_hdr(pkt), sizeof(struct ipv6hdr));
  
  	/*
  	 *	Add our header
  	 */
  	skb_put(skb, sizeof(*msg));
  	skb_reset_transport_header(skb);
  	msg = (struct mrt6msg *)skb_transport_header(skb);
  
  	msg->im6_mbz = 0;
  	msg->im6_msgtype = assert;
6ac7eb086   Rami Rosen   [IPV6] MROUTE: Ad...
1137
  	msg->im6_mif = mifi;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1138
  	msg->im6_pad = 0;
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
1139
1140
  	msg->im6_src = ipv6_hdr(pkt)->saddr;
  	msg->im6_dst = ipv6_hdr(pkt)->daddr;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1141

adf30907d   Eric Dumazet   net: skb->dst acc...
1142
  	skb_dst_set(skb, dst_clone(skb_dst(pkt)));
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1143
  	skb->ip_summed = CHECKSUM_UNNECESSARY;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1144
  	}
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1145

63159f29b   Ian Morris   ipv6: coding styl...
1146
  	if (!mrt->mroute6_sk) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1147
1148
1149
  		kfree_skb(skb);
  		return -EINVAL;
  	}
dd12d15c9   Julien Gomes   ip6mr: add netlin...
1150
  	mrt6msg_netlink_event(mrt, skb);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1151
1152
1153
  	/*
  	 *	Deliver to user space multicast routing algorithms
  	 */
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1154
  	ret = sock_queue_rcv_skb(mrt->mroute6_sk, skb);
bd91b8bf3   Benjamin Thery   netns: ip6mr: all...
1155
  	if (ret < 0) {
e87cc4728   Joe Perches   net: Convert net_...
1156
1157
  		net_warn_ratelimited("mroute6: pending queue full, dropping entries
  ");
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
  		kfree_skb(skb);
  	}
  
  	return ret;
  }
  
  /*
   *	Queue a packet for resolution. It gets locked cache entry!
   */
  
  static int
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1169
  ip6mr_cache_unresolved(struct mr6_table *mrt, mifi_t mifi, struct sk_buff *skb)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1170
  {
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1171
  	bool found = false;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1172
1173
1174
1175
  	int err;
  	struct mfc6_cache *c;
  
  	spin_lock_bh(&mfc_unres_lock);
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1176
  	list_for_each_entry(c, &mrt->mfc6_unres_queue, list) {
c476efbcd   Patrick McHardy   ipv6: ip6mr: move...
1177
  		if (ipv6_addr_equal(&c->mf6c_mcastgrp, &ipv6_hdr(skb)->daddr) &&
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1178
1179
  		    ipv6_addr_equal(&c->mf6c_origin, &ipv6_hdr(skb)->saddr)) {
  			found = true;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1180
  			break;
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1181
  		}
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1182
  	}
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1183
  	if (!found) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1184
1185
1186
  		/*
  		 *	Create a new entry if allowable
  		 */
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1187
  		if (atomic_read(&mrt->cache_resolve_queue_len) >= 10 ||
b5aa30b19   Patrick McHardy   ipv6: ip6mr: remo...
1188
  		    (c = ip6mr_cache_alloc_unres()) == NULL) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
  			spin_unlock_bh(&mfc_unres_lock);
  
  			kfree_skb(skb);
  			return -ENOBUFS;
  		}
  
  		/*
  		 *	Fill in the new cache entry
  		 */
  		c->mf6c_parent = -1;
  		c->mf6c_origin = ipv6_hdr(skb)->saddr;
  		c->mf6c_mcastgrp = ipv6_hdr(skb)->daddr;
  
  		/*
  		 *	Reflect first query at pim6sd
  		 */
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1205
  		err = ip6mr_cache_report(mrt, skb, mifi, MRT6MSG_NOCACHE);
8229efdae   Benjamin Thery   netns: ip6mr: ena...
1206
  		if (err < 0) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1207
1208
1209
1210
  			/* If the report failed throw the cache entry
  			   out - Brad Parker
  			 */
  			spin_unlock_bh(&mfc_unres_lock);
58701ad41   Benjamin Thery   netns: ip6mr: sto...
1211
  			ip6mr_cache_free(c);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1212
1213
1214
  			kfree_skb(skb);
  			return err;
  		}
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1215
1216
  		atomic_inc(&mrt->cache_resolve_queue_len);
  		list_add(&c->list, &mrt->mfc6_unres_queue);
812e44dd1   Nicolas Dichtel   ip6mr: advertise ...
1217
  		mr6_netlink_event(mrt, c, RTM_NEWROUTE);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1218

6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1219
  		ipmr_do_expire_process(mrt);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
  	}
  
  	/*
  	 *	See if we can append the packet
  	 */
  	if (c->mfc_un.unres.unresolved.qlen > 3) {
  		kfree_skb(skb);
  		err = -ENOBUFS;
  	} else {
  		skb_queue_tail(&c->mfc_un.unres.unresolved, skb);
  		err = 0;
  	}
  
  	spin_unlock_bh(&mfc_unres_lock);
  	return err;
  }
  
  /*
   *	MFC6 cache manipulation by user space
   */
660b26dc1   Nicolas Dichtel   mcast: add multic...
1240
1241
  static int ip6mr_mfc_delete(struct mr6_table *mrt, struct mf6cctl *mfc,
  			    int parent)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1242
1243
  {
  	int line;
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1244
  	struct mfc6_cache *c, *next;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1245
1246
  
  	line = MFC6_HASH(&mfc->mf6cc_mcastgrp.sin6_addr, &mfc->mf6cc_origin.sin6_addr);
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1247
  	list_for_each_entry_safe(c, next, &mrt->mfc6_cache_array[line], list) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1248
  		if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) &&
660b26dc1   Nicolas Dichtel   mcast: add multic...
1249
1250
1251
  		    ipv6_addr_equal(&c->mf6c_mcastgrp,
  				    &mfc->mf6cc_mcastgrp.sin6_addr) &&
  		    (parent == -1 || parent == c->mf6c_parent)) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1252
  			write_lock_bh(&mrt_lock);
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1253
  			list_del(&c->list);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1254
  			write_unlock_bh(&mrt_lock);
812e44dd1   Nicolas Dichtel   ip6mr: advertise ...
1255
  			mr6_netlink_event(mrt, c, RTM_DELROUTE);
58701ad41   Benjamin Thery   netns: ip6mr: sto...
1256
  			ip6mr_cache_free(c);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1257
1258
1259
1260
1261
1262
1263
1264
1265
  			return 0;
  		}
  	}
  	return -ENOENT;
  }
  
  static int ip6mr_device_event(struct notifier_block *this,
  			      unsigned long event, void *ptr)
  {
351638e7d   Jiri Pirko   net: pass info st...
1266
  	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
8229efdae   Benjamin Thery   netns: ip6mr: ena...
1267
  	struct net *net = dev_net(dev);
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1268
  	struct mr6_table *mrt;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1269
1270
  	struct mif_device *v;
  	int ct;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1271
1272
  	if (event != NETDEV_UNREGISTER)
  		return NOTIFY_DONE;
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1273
1274
1275
1276
  	ip6mr_for_each_table(mrt, net) {
  		v = &mrt->vif6_table[0];
  		for (ct = 0; ct < mrt->maxvif; ct++, v++) {
  			if (v->dev == dev)
723b929ca   Nikolay Aleksandrov   ip6mr: fix notifi...
1277
  				mif6_delete(mrt, ct, 1, NULL);
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1278
  		}
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1279
  	}
c871e664e   Eric Dumazet   ip6mr: Optimize m...
1280

7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
  	return NOTIFY_DONE;
  }
  
  static struct notifier_block ip6_mr_notifier = {
  	.notifier_call = ip6mr_device_event
  };
  
  /*
   *	Setup for IP multicast routing
   */
4e16880cb   Benjamin Thery   netns: ip6mr: dyn...
1291
1292
  static int __net_init ip6mr_net_init(struct net *net)
  {
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1293
  	int err;
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1294

d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1295
1296
  	err = ip6mr_rules_init(net);
  	if (err < 0)
4e16880cb   Benjamin Thery   netns: ip6mr: dyn...
1297
  		goto fail;
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
1298
1299
1300
  
  #ifdef CONFIG_PROC_FS
  	err = -ENOMEM;
d4beaa66a   Gao feng   net: proc: change...
1301
  	if (!proc_create("ip6_mr_vif", 0, net->proc_net, &ip6mr_vif_fops))
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
1302
  		goto proc_vif_fail;
d4beaa66a   Gao feng   net: proc: change...
1303
  	if (!proc_create("ip6_mr_cache", 0, net->proc_net, &ip6mr_mfc_fops))
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
1304
1305
  		goto proc_cache_fail;
  #endif
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1306

4a6258a0e   Benjamin Thery   netns: ip6mr: dyn...
1307
  	return 0;
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
1308
1309
  #ifdef CONFIG_PROC_FS
  proc_cache_fail:
ece31ffd5   Gao feng   net: proc: change...
1310
  	remove_proc_entry("ip6_mr_vif", net->proc_net);
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
1311
  proc_vif_fail:
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1312
  	ip6mr_rules_exit(net);
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
1313
  #endif
4e16880cb   Benjamin Thery   netns: ip6mr: dyn...
1314
1315
1316
1317
1318
1319
  fail:
  	return err;
  }
  
  static void __net_exit ip6mr_net_exit(struct net *net)
  {
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
1320
  #ifdef CONFIG_PROC_FS
ece31ffd5   Gao feng   net: proc: change...
1321
1322
  	remove_proc_entry("ip6_mr_cache", net->proc_net);
  	remove_proc_entry("ip6_mr_vif", net->proc_net);
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
1323
  #endif
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1324
  	ip6mr_rules_exit(net);
4e16880cb   Benjamin Thery   netns: ip6mr: dyn...
1325
1326
1327
1328
1329
1330
  }
  
  static struct pernet_operations ip6mr_net_ops = {
  	.init = ip6mr_net_init,
  	.exit = ip6mr_net_exit,
  };
623d1a1af   Wang Chen   ipv6: Do cleanup ...
1331
  int __init ip6_mr_init(void)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1332
  {
623d1a1af   Wang Chen   ipv6: Do cleanup ...
1333
  	int err;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1334
1335
1336
1337
1338
  	mrt_cachep = kmem_cache_create("ip6_mrt_cache",
  				       sizeof(struct mfc6_cache),
  				       0, SLAB_HWCACHE_ALIGN,
  				       NULL);
  	if (!mrt_cachep)
623d1a1af   Wang Chen   ipv6: Do cleanup ...
1339
  		return -ENOMEM;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1340

4e16880cb   Benjamin Thery   netns: ip6mr: dyn...
1341
1342
1343
  	err = register_pernet_subsys(&ip6mr_net_ops);
  	if (err)
  		goto reg_pernet_fail;
623d1a1af   Wang Chen   ipv6: Do cleanup ...
1344
1345
1346
  	err = register_netdevice_notifier(&ip6_mr_notifier);
  	if (err)
  		goto reg_notif_fail;
403dbb97f   Tom Goff   PIM-SM: namespace...
1347
1348
  #ifdef CONFIG_IPV6_PIMSM_V2
  	if (inet6_add_protocol(&pim6_protocol, IPPROTO_PIM) < 0) {
f32138319   Joe Perches   net: ipv6: Standa...
1349
1350
  		pr_err("%s: can't add PIM protocol
  ", __func__);
403dbb97f   Tom Goff   PIM-SM: namespace...
1351
1352
1353
1354
  		err = -EAGAIN;
  		goto add_proto_fail;
  	}
  #endif
c7ac8679b   Greg Rose   rtnetlink: Comput...
1355
  	rtnl_register(RTNL_FAMILY_IP6MR, RTM_GETROUTE, NULL,
b97bac64a   Florian Westphal   rtnetlink: make r...
1356
  		      ip6mr_rtm_dumproute, 0);
623d1a1af   Wang Chen   ipv6: Do cleanup ...
1357
  	return 0;
403dbb97f   Tom Goff   PIM-SM: namespace...
1358
1359
1360
1361
  #ifdef CONFIG_IPV6_PIMSM_V2
  add_proto_fail:
  	unregister_netdevice_notifier(&ip6_mr_notifier);
  #endif
87b30a653   Benjamin Thery   ipv6: fix ip6_mr_...
1362
  reg_notif_fail:
4e16880cb   Benjamin Thery   netns: ip6mr: dyn...
1363
1364
  	unregister_pernet_subsys(&ip6mr_net_ops);
  reg_pernet_fail:
87b30a653   Benjamin Thery   ipv6: fix ip6_mr_...
1365
  	kmem_cache_destroy(mrt_cachep);
623d1a1af   Wang Chen   ipv6: Do cleanup ...
1366
  	return err;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1367
  }
623d1a1af   Wang Chen   ipv6: Do cleanup ...
1368
1369
  void ip6_mr_cleanup(void)
  {
ffb1388a3   Duan Jiong   ipv6: delete prot...
1370
1371
1372
1373
  	rtnl_unregister(RTNL_FAMILY_IP6MR, RTM_GETROUTE);
  #ifdef CONFIG_IPV6_PIMSM_V2
  	inet6_del_protocol(&pim6_protocol, IPPROTO_PIM);
  #endif
623d1a1af   Wang Chen   ipv6: Do cleanup ...
1374
  	unregister_netdevice_notifier(&ip6_mr_notifier);
4e16880cb   Benjamin Thery   netns: ip6mr: dyn...
1375
  	unregister_pernet_subsys(&ip6mr_net_ops);
623d1a1af   Wang Chen   ipv6: Do cleanup ...
1376
1377
  	kmem_cache_destroy(mrt_cachep);
  }
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1378

6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1379
  static int ip6mr_mfc_add(struct net *net, struct mr6_table *mrt,
660b26dc1   Nicolas Dichtel   mcast: add multic...
1380
  			 struct mf6cctl *mfc, int mrtsock, int parent)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1381
  {
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1382
  	bool found = false;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1383
  	int line;
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1384
  	struct mfc6_cache *uc, *c;
6ac7eb086   Rami Rosen   [IPV6] MROUTE: Ad...
1385
  	unsigned char ttls[MAXMIFS];
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1386
  	int i;
a50436f2c   Patrick McHardy   net: ipmr/ip6mr: ...
1387
1388
  	if (mfc->mf6cc_parent >= MAXMIFS)
  		return -ENFILE;
6ac7eb086   Rami Rosen   [IPV6] MROUTE: Ad...
1389
1390
  	memset(ttls, 255, MAXMIFS);
  	for (i = 0; i < MAXMIFS; i++) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1391
1392
1393
1394
1395
1396
  		if (IF_ISSET(i, &mfc->mf6cc_ifset))
  			ttls[i] = 1;
  
  	}
  
  	line = MFC6_HASH(&mfc->mf6cc_mcastgrp.sin6_addr, &mfc->mf6cc_origin.sin6_addr);
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1397
  	list_for_each_entry(c, &mrt->mfc6_cache_array[line], list) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1398
  		if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) &&
660b26dc1   Nicolas Dichtel   mcast: add multic...
1399
1400
1401
  		    ipv6_addr_equal(&c->mf6c_mcastgrp,
  				    &mfc->mf6cc_mcastgrp.sin6_addr) &&
  		    (parent == -1 || parent == mfc->mf6cc_parent)) {
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1402
  			found = true;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1403
  			break;
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1404
  		}
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1405
  	}
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1406
  	if (found) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1407
1408
  		write_lock_bh(&mrt_lock);
  		c->mf6c_parent = mfc->mf6cc_parent;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1409
  		ip6mr_update_thresholds(mrt, c, ttls);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1410
1411
1412
  		if (!mrtsock)
  			c->mfc_flags |= MFC_STATIC;
  		write_unlock_bh(&mrt_lock);
812e44dd1   Nicolas Dichtel   ip6mr: advertise ...
1413
  		mr6_netlink_event(mrt, c, RTM_NEWROUTE);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1414
1415
  		return 0;
  	}
660b26dc1   Nicolas Dichtel   mcast: add multic...
1416
1417
  	if (!ipv6_addr_any(&mfc->mf6cc_mcastgrp.sin6_addr) &&
  	    !ipv6_addr_is_multicast(&mfc->mf6cc_mcastgrp.sin6_addr))
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1418
  		return -EINVAL;
b5aa30b19   Patrick McHardy   ipv6: ip6mr: remo...
1419
  	c = ip6mr_cache_alloc();
63159f29b   Ian Morris   ipv6: coding styl...
1420
  	if (!c)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1421
1422
1423
1424
1425
  		return -ENOMEM;
  
  	c->mf6c_origin = mfc->mf6cc_origin.sin6_addr;
  	c->mf6c_mcastgrp = mfc->mf6cc_mcastgrp.sin6_addr;
  	c->mf6c_parent = mfc->mf6cc_parent;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1426
  	ip6mr_update_thresholds(mrt, c, ttls);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1427
1428
1429
1430
  	if (!mrtsock)
  		c->mfc_flags |= MFC_STATIC;
  
  	write_lock_bh(&mrt_lock);
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1431
  	list_add(&c->list, &mrt->mfc6_cache_array[line]);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1432
1433
1434
1435
1436
1437
  	write_unlock_bh(&mrt_lock);
  
  	/*
  	 *	Check to see if we resolved a queued list. If so we
  	 *	need to send on the frames and tidy up.
  	 */
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1438
  	found = false;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1439
  	spin_lock_bh(&mfc_unres_lock);
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1440
  	list_for_each_entry(uc, &mrt->mfc6_unres_queue, list) {
c476efbcd   Patrick McHardy   ipv6: ip6mr: move...
1441
  		if (ipv6_addr_equal(&uc->mf6c_origin, &c->mf6c_origin) &&
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1442
  		    ipv6_addr_equal(&uc->mf6c_mcastgrp, &c->mf6c_mcastgrp)) {
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1443
  			list_del(&uc->list);
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1444
  			atomic_dec(&mrt->cache_resolve_queue_len);
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1445
  			found = true;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1446
1447
1448
  			break;
  		}
  	}
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1449
1450
  	if (list_empty(&mrt->mfc6_unres_queue))
  		del_timer(&mrt->ipmr_expire_timer);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1451
  	spin_unlock_bh(&mfc_unres_lock);
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1452
  	if (found) {
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1453
  		ip6mr_cache_resolve(net, mrt, uc, c);
58701ad41   Benjamin Thery   netns: ip6mr: sto...
1454
  		ip6mr_cache_free(uc);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1455
  	}
812e44dd1   Nicolas Dichtel   ip6mr: advertise ...
1456
  	mr6_netlink_event(mrt, c, RTM_NEWROUTE);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1457
1458
1459
1460
1461
1462
  	return 0;
  }
  
  /*
   *	Close the multicast socket, and clear the vif tables etc
   */
4c6980462   Nikolay Aleksandrov   net: ip6mr: fix s...
1463
  static void mroute_clean_tables(struct mr6_table *mrt, bool all)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1464
1465
  {
  	int i;
c871e664e   Eric Dumazet   ip6mr: Optimize m...
1466
  	LIST_HEAD(list);
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1467
  	struct mfc6_cache *c, *next;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1468
1469
1470
1471
  
  	/*
  	 *	Shut down all active vif entries
  	 */
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1472
  	for (i = 0; i < mrt->maxvif; i++) {
4c6980462   Nikolay Aleksandrov   net: ip6mr: fix s...
1473
1474
  		if (!all && (mrt->vif6_table[i].flags & VIFF_STATIC))
  			continue;
723b929ca   Nikolay Aleksandrov   ip6mr: fix notifi...
1475
  		mif6_delete(mrt, i, 0, &list);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1476
  	}
c871e664e   Eric Dumazet   ip6mr: Optimize m...
1477
  	unregister_netdevice_many(&list);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1478
1479
1480
1481
  
  	/*
  	 *	Wipe the cache
  	 */
4a6258a0e   Benjamin Thery   netns: ip6mr: dyn...
1482
  	for (i = 0; i < MFC6_LINES; i++) {
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1483
  		list_for_each_entry_safe(c, next, &mrt->mfc6_cache_array[i], list) {
4c6980462   Nikolay Aleksandrov   net: ip6mr: fix s...
1484
  			if (!all && (c->mfc_flags & MFC_STATIC))
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1485
  				continue;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1486
  			write_lock_bh(&mrt_lock);
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1487
  			list_del(&c->list);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1488
  			write_unlock_bh(&mrt_lock);
812e44dd1   Nicolas Dichtel   ip6mr: advertise ...
1489
  			mr6_netlink_event(mrt, c, RTM_DELROUTE);
58701ad41   Benjamin Thery   netns: ip6mr: sto...
1490
  			ip6mr_cache_free(c);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1491
1492
  		}
  	}
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1493
  	if (atomic_read(&mrt->cache_resolve_queue_len) != 0) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1494
  		spin_lock_bh(&mfc_unres_lock);
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1495
  		list_for_each_entry_safe(c, next, &mrt->mfc6_unres_queue, list) {
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1496
  			list_del(&c->list);
812e44dd1   Nicolas Dichtel   ip6mr: advertise ...
1497
  			mr6_netlink_event(mrt, c, RTM_DELROUTE);
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1498
  			ip6mr_destroy_unres(mrt, c);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1499
1500
1501
1502
  		}
  		spin_unlock_bh(&mfc_unres_lock);
  	}
  }
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1503
  static int ip6mr_sk_init(struct mr6_table *mrt, struct sock *sk)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1504
1505
  {
  	int err = 0;
8229efdae   Benjamin Thery   netns: ip6mr: ena...
1506
  	struct net *net = sock_net(sk);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1507
1508
1509
  
  	rtnl_lock();
  	write_lock_bh(&mrt_lock);
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1510
1511
  	if (likely(mrt->mroute6_sk == NULL)) {
  		mrt->mroute6_sk = sk;
1d6e55f19   Thomas Goff   IPv6: Fix multica...
1512
  		net->ipv6.devconf_all->mc_forwarding++;
927265bc6   Eric Dumazet   ipv6: do not abus...
1513
  	} else {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1514
  		err = -EADDRINUSE;
927265bc6   Eric Dumazet   ipv6: do not abus...
1515
  	}
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1516
  	write_unlock_bh(&mrt_lock);
927265bc6   Eric Dumazet   ipv6: do not abus...
1517
  	if (!err)
85b3daada   David Ahern   net: ipv6: Refact...
1518
1519
  		inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
  					     NETCONFA_MC_FORWARDING,
927265bc6   Eric Dumazet   ipv6: do not abus...
1520
1521
  					     NETCONFA_IFINDEX_ALL,
  					     net->ipv6.devconf_all);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1522
1523
1524
1525
1526
1527
1528
  	rtnl_unlock();
  
  	return err;
  }
  
  int ip6mr_sk_done(struct sock *sk)
  {
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1529
  	int err = -EACCES;
8229efdae   Benjamin Thery   netns: ip6mr: ena...
1530
  	struct net *net = sock_net(sk);
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1531
  	struct mr6_table *mrt;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1532
1533
  
  	rtnl_lock();
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1534
1535
1536
1537
1538
  	ip6mr_for_each_table(mrt, net) {
  		if (sk == mrt->mroute6_sk) {
  			write_lock_bh(&mrt_lock);
  			mrt->mroute6_sk = NULL;
  			net->ipv6.devconf_all->mc_forwarding--;
927265bc6   Eric Dumazet   ipv6: do not abus...
1539
  			write_unlock_bh(&mrt_lock);
85b3daada   David Ahern   net: ipv6: Refact...
1540
  			inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
d67b8c616   Nicolas Dichtel   netconf: advertis...
1541
1542
1543
  						     NETCONFA_MC_FORWARDING,
  						     NETCONFA_IFINDEX_ALL,
  						     net->ipv6.devconf_all);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1544

4c6980462   Nikolay Aleksandrov   net: ip6mr: fix s...
1545
  			mroute_clean_tables(mrt, false);
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1546
1547
1548
1549
  			err = 0;
  			break;
  		}
  	}
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1550
1551
1552
1553
  	rtnl_unlock();
  
  	return err;
  }
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1554
  struct sock *mroute6_socket(struct net *net, struct sk_buff *skb)
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1555
  {
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1556
  	struct mr6_table *mrt;
4c9483b2f   David S. Miller   ipv6: Convert to ...
1557
  	struct flowi6 fl6 = {
e374c618b   Julian Anastasov   net: ipv6: more p...
1558
  		.flowi6_iif	= skb->skb_iif ? : LOOPBACK_IFINDEX,
4c9483b2f   David S. Miller   ipv6: Convert to ...
1559
1560
  		.flowi6_oif	= skb->dev->ifindex,
  		.flowi6_mark	= skb->mark,
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1561
  	};
4c9483b2f   David S. Miller   ipv6: Convert to ...
1562
  	if (ip6mr_fib_lookup(net, &fl6, &mrt) < 0)
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1563
  		return NULL;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1564
1565
1566
  
  	return mrt->mroute6_sk;
  }
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1567
1568
1569
1570
1571
1572
  /*
   *	Socket options and virtual interface manipulation. The whole
   *	virtual interface system is a complete heap, but unfortunately
   *	that's how BSD mrouted happens to think. Maybe one day with a proper
   *	MOSPF/PIM router set up we can clean this up.
   */
b7058842c   David S. Miller   net: Make setsock...
1573
  int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsigned int optlen)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1574
  {
660b26dc1   Nicolas Dichtel   mcast: add multic...
1575
  	int ret, parent = 0;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1576
1577
1578
  	struct mif6ctl vif;
  	struct mf6cctl mfc;
  	mifi_t mifi;
8229efdae   Benjamin Thery   netns: ip6mr: ena...
1579
  	struct net *net = sock_net(sk);
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1580
  	struct mr6_table *mrt;
99253eb75   Xin Long   ipv6: check sk sk...
1581
1582
1583
  	if (sk->sk_type != SOCK_RAW ||
  	    inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
  		return -EOPNOTSUPP;
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1584
  	mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
63159f29b   Ian Morris   ipv6: coding styl...
1585
  	if (!mrt)
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1586
  		return -ENOENT;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1587
1588
  
  	if (optname != MRT6_INIT) {
af31f412c   Eric W. Biederman   net: Allow userns...
1589
  		if (sk != mrt->mroute6_sk && !ns_capable(net->user_ns, CAP_NET_ADMIN))
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1590
1591
1592
1593
1594
  			return -EACCES;
  	}
  
  	switch (optname) {
  	case MRT6_INIT:
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1595
1596
  		if (optlen < sizeof(int))
  			return -EINVAL;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1597
  		return ip6mr_sk_init(mrt, sk);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1598
1599
1600
1601
1602
1603
1604
1605
1606
  
  	case MRT6_DONE:
  		return ip6mr_sk_done(sk);
  
  	case MRT6_ADD_MIF:
  		if (optlen < sizeof(vif))
  			return -EINVAL;
  		if (copy_from_user(&vif, optval, sizeof(vif)))
  			return -EFAULT;
6ac7eb086   Rami Rosen   [IPV6] MROUTE: Ad...
1607
  		if (vif.mif6c_mifi >= MAXMIFS)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1608
1609
  			return -ENFILE;
  		rtnl_lock();
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1610
  		ret = mif6_add(net, mrt, &vif, sk == mrt->mroute6_sk);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1611
1612
1613
1614
1615
1616
1617
1618
1619
  		rtnl_unlock();
  		return ret;
  
  	case MRT6_DEL_MIF:
  		if (optlen < sizeof(mifi_t))
  			return -EINVAL;
  		if (copy_from_user(&mifi, optval, sizeof(mifi_t)))
  			return -EFAULT;
  		rtnl_lock();
723b929ca   Nikolay Aleksandrov   ip6mr: fix notifi...
1620
  		ret = mif6_delete(mrt, mifi, 0, NULL);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1621
1622
1623
1624
1625
1626
1627
1628
1629
  		rtnl_unlock();
  		return ret;
  
  	/*
  	 *	Manipulate the forwarding caches. These live
  	 *	in a sort of kernel/user symbiosis.
  	 */
  	case MRT6_ADD_MFC:
  	case MRT6_DEL_MFC:
660b26dc1   Nicolas Dichtel   mcast: add multic...
1630
1631
1632
  		parent = -1;
  	case MRT6_ADD_MFC_PROXY:
  	case MRT6_DEL_MFC_PROXY:
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1633
1634
1635
1636
  		if (optlen < sizeof(mfc))
  			return -EINVAL;
  		if (copy_from_user(&mfc, optval, sizeof(mfc)))
  			return -EFAULT;
660b26dc1   Nicolas Dichtel   mcast: add multic...
1637
1638
  		if (parent == 0)
  			parent = mfc.mf6cc_parent;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1639
  		rtnl_lock();
660b26dc1   Nicolas Dichtel   mcast: add multic...
1640
1641
  		if (optname == MRT6_DEL_MFC || optname == MRT6_DEL_MFC_PROXY)
  			ret = ip6mr_mfc_delete(mrt, &mfc, parent);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1642
  		else
660b26dc1   Nicolas Dichtel   mcast: add multic...
1643
1644
  			ret = ip6mr_mfc_add(net, mrt, &mfc,
  					    sk == mrt->mroute6_sk, parent);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1645
1646
1647
1648
  		rtnl_unlock();
  		return ret;
  
  	/*
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1649
1650
1651
1652
1653
  	 *	Control PIM assert (to activate pim will activate assert)
  	 */
  	case MRT6_ASSERT:
  	{
  		int v;
03f52a0a5   Joe Perches   ip6mr: Add sizeof...
1654
1655
1656
  
  		if (optlen != sizeof(v))
  			return -EINVAL;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1657
1658
  		if (get_user(v, (int __user *)optval))
  			return -EFAULT;
53d6841d2   Joe Perches   ipv4/ipmr and ipv...
1659
  		mrt->mroute_do_assert = v;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1660
1661
1662
1663
1664
1665
  		return 0;
  	}
  
  #ifdef CONFIG_IPV6_PIMSM_V2
  	case MRT6_PIM:
  	{
a9f83bf38   YOSHIFUJI Hideaki   [IPV6]: Sparse: R...
1666
  		int v;
03f52a0a5   Joe Perches   ip6mr: Add sizeof...
1667
1668
1669
  
  		if (optlen != sizeof(v))
  			return -EINVAL;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1670
1671
1672
1673
1674
  		if (get_user(v, (int __user *)optval))
  			return -EFAULT;
  		v = !!v;
  		rtnl_lock();
  		ret = 0;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1675
1676
1677
  		if (v != mrt->mroute_do_pim) {
  			mrt->mroute_do_pim = v;
  			mrt->mroute_do_assert = v;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1678
1679
1680
1681
1682
1683
  		}
  		rtnl_unlock();
  		return ret;
  	}
  
  #endif
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1684
1685
1686
1687
1688
1689
1690
1691
1692
  #ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
  	case MRT6_TABLE:
  	{
  		u32 v;
  
  		if (optlen != sizeof(u32))
  			return -EINVAL;
  		if (get_user(v, (u32 __user *)optval))
  			return -EFAULT;
75356a814   Dan Carpenter   ip6mr: limit IPv6...
1693
1694
1695
  		/* "pim6reg%u" should not exceed 16 bytes (IFNAMSIZ) */
  		if (v != RT_TABLE_DEFAULT && v >= 100000000)
  			return -EINVAL;
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1696
1697
1698
1699
1700
1701
1702
  		if (sk == mrt->mroute6_sk)
  			return -EBUSY;
  
  		rtnl_lock();
  		ret = 0;
  		if (!ip6mr_new_table(net, v))
  			ret = -ENOMEM;
989986db8   Sabrina Dubroca   ip6mr: only set i...
1703
1704
  		else
  			raw6_sk(sk)->ip6mr_table = v;
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1705
1706
1707
1708
  		rtnl_unlock();
  		return ret;
  	}
  #endif
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1709
  	/*
7d120c55d   Rami Rosen   ipv6 mroute: Use ...
1710
  	 *	Spurious command, or MRT6_VERSION which you cannot
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
  	 *	set.
  	 */
  	default:
  		return -ENOPROTOOPT;
  	}
  }
  
  /*
   *	Getsock opt support for the multicast routing system.
   */
  
  int ip6_mroute_getsockopt(struct sock *sk, int optname, char __user *optval,
  			  int __user *optlen)
  {
  	int olr;
  	int val;
8229efdae   Benjamin Thery   netns: ip6mr: ena...
1727
  	struct net *net = sock_net(sk);
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1728
  	struct mr6_table *mrt;
99253eb75   Xin Long   ipv6: check sk sk...
1729
1730
1731
  	if (sk->sk_type != SOCK_RAW ||
  	    inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
  		return -EOPNOTSUPP;
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1732
  	mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
63159f29b   Ian Morris   ipv6: coding styl...
1733
  	if (!mrt)
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1734
  		return -ENOENT;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1735
1736
1737
1738
1739
  
  	switch (optname) {
  	case MRT6_VERSION:
  		val = 0x0305;
  		break;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1740
1741
  #ifdef CONFIG_IPV6_PIMSM_V2
  	case MRT6_PIM:
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1742
  		val = mrt->mroute_do_pim;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1743
1744
1745
  		break;
  #endif
  	case MRT6_ASSERT:
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1746
  		val = mrt->mroute_do_assert;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1747
  		break;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
  	default:
  		return -ENOPROTOOPT;
  	}
  
  	if (get_user(olr, optlen))
  		return -EFAULT;
  
  	olr = min_t(int, olr, sizeof(int));
  	if (olr < 0)
  		return -EINVAL;
  
  	if (put_user(olr, optlen))
  		return -EFAULT;
  	if (copy_to_user(optval, &val, olr))
  		return -EFAULT;
  	return 0;
  }
  
  /*
   *	The IP multicast ioctl support routines.
   */
  
  int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg)
  {
  	struct sioc_sg_req6 sr;
  	struct sioc_mif_req6 vr;
  	struct mif_device *vif;
  	struct mfc6_cache *c;
8229efdae   Benjamin Thery   netns: ip6mr: ena...
1776
  	struct net *net = sock_net(sk);
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1777
1778
1779
  	struct mr6_table *mrt;
  
  	mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
63159f29b   Ian Morris   ipv6: coding styl...
1780
  	if (!mrt)
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1781
  		return -ENOENT;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1782
1783
1784
1785
1786
  
  	switch (cmd) {
  	case SIOCGETMIFCNT_IN6:
  		if (copy_from_user(&vr, arg, sizeof(vr)))
  			return -EFAULT;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1787
  		if (vr.mifi >= mrt->maxvif)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1788
  			return -EINVAL;
18e260fd2   Gustavo A. R. Silva   ip6mr: Fix potent...
1789
  		vr.mifi = array_index_nospec(vr.mifi, mrt->maxvif);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1790
  		read_lock(&mrt_lock);
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1791
1792
  		vif = &mrt->vif6_table[vr.mifi];
  		if (MIF_EXISTS(mrt, vr.mifi)) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
  			vr.icount = vif->pkt_in;
  			vr.ocount = vif->pkt_out;
  			vr.ibytes = vif->bytes_in;
  			vr.obytes = vif->bytes_out;
  			read_unlock(&mrt_lock);
  
  			if (copy_to_user(arg, &vr, sizeof(vr)))
  				return -EFAULT;
  			return 0;
  		}
  		read_unlock(&mrt_lock);
  		return -EADDRNOTAVAIL;
  	case SIOCGETSGCNT_IN6:
  		if (copy_from_user(&sr, arg, sizeof(sr)))
  			return -EFAULT;
  
  		read_lock(&mrt_lock);
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1810
  		c = ip6mr_cache_find(mrt, &sr.src.sin6_addr, &sr.grp.sin6_addr);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
  		if (c) {
  			sr.pktcnt = c->mfc_un.res.pkt;
  			sr.bytecnt = c->mfc_un.res.bytes;
  			sr.wrong_if = c->mfc_un.res.wrong_if;
  			read_unlock(&mrt_lock);
  
  			if (copy_to_user(arg, &sr, sizeof(sr)))
  				return -EFAULT;
  			return 0;
  		}
  		read_unlock(&mrt_lock);
  		return -EADDRNOTAVAIL;
  	default:
  		return -ENOIOCTLCMD;
  	}
  }
e2d57766e   David S. Miller   net: Provide comp...
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
  #ifdef CONFIG_COMPAT
  struct compat_sioc_sg_req6 {
  	struct sockaddr_in6 src;
  	struct sockaddr_in6 grp;
  	compat_ulong_t pktcnt;
  	compat_ulong_t bytecnt;
  	compat_ulong_t wrong_if;
  };
  
  struct compat_sioc_mif_req6 {
  	mifi_t	mifi;
  	compat_ulong_t icount;
  	compat_ulong_t ocount;
  	compat_ulong_t ibytes;
  	compat_ulong_t obytes;
  };
  
  int ip6mr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg)
  {
  	struct compat_sioc_sg_req6 sr;
  	struct compat_sioc_mif_req6 vr;
  	struct mif_device *vif;
  	struct mfc6_cache *c;
  	struct net *net = sock_net(sk);
  	struct mr6_table *mrt;
  
  	mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
63159f29b   Ian Morris   ipv6: coding styl...
1854
  	if (!mrt)
e2d57766e   David S. Miller   net: Provide comp...
1855
1856
1857
1858
1859
1860
1861
1862
  		return -ENOENT;
  
  	switch (cmd) {
  	case SIOCGETMIFCNT_IN6:
  		if (copy_from_user(&vr, arg, sizeof(vr)))
  			return -EFAULT;
  		if (vr.mifi >= mrt->maxvif)
  			return -EINVAL;
18e260fd2   Gustavo A. R. Silva   ip6mr: Fix potent...
1863
  		vr.mifi = array_index_nospec(vr.mifi, mrt->maxvif);
e2d57766e   David S. Miller   net: Provide comp...
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
  		read_lock(&mrt_lock);
  		vif = &mrt->vif6_table[vr.mifi];
  		if (MIF_EXISTS(mrt, vr.mifi)) {
  			vr.icount = vif->pkt_in;
  			vr.ocount = vif->pkt_out;
  			vr.ibytes = vif->bytes_in;
  			vr.obytes = vif->bytes_out;
  			read_unlock(&mrt_lock);
  
  			if (copy_to_user(arg, &vr, sizeof(vr)))
  				return -EFAULT;
  			return 0;
  		}
  		read_unlock(&mrt_lock);
  		return -EADDRNOTAVAIL;
  	case SIOCGETSGCNT_IN6:
  		if (copy_from_user(&sr, arg, sizeof(sr)))
  			return -EFAULT;
  
  		read_lock(&mrt_lock);
  		c = ip6mr_cache_find(mrt, &sr.src.sin6_addr, &sr.grp.sin6_addr);
  		if (c) {
  			sr.pktcnt = c->mfc_un.res.pkt;
  			sr.bytecnt = c->mfc_un.res.bytes;
  			sr.wrong_if = c->mfc_un.res.wrong_if;
  			read_unlock(&mrt_lock);
  
  			if (copy_to_user(arg, &sr, sizeof(sr)))
  				return -EFAULT;
  			return 0;
  		}
  		read_unlock(&mrt_lock);
  		return -EADDRNOTAVAIL;
  	default:
  		return -ENOIOCTLCMD;
  	}
  }
  #endif
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1902

0c4b51f00   Eric W. Biederman   netfilter: Pass n...
1903
  static inline int ip6mr_forward2_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1904
  {
1d0155035   Eric Dumazet   ipv6: rename IP6_...
1905
1906
1907
1908
  	__IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
  			IPSTATS_MIB_OUTFORWDATAGRAMS);
  	__IP6_ADD_STATS(net, ip6_dst_idev(skb_dst(skb)),
  			IPSTATS_MIB_OUTOCTETS, skb->len);
13206b6bf   Eric W. Biederman   net: Pass net int...
1909
  	return dst_output(net, sk, skb);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1910
1911
1912
1913
1914
  }
  
  /*
   *	Processing handlers for ip6mr_forward
   */
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1915
1916
  static int ip6mr_forward2(struct net *net, struct mr6_table *mrt,
  			  struct sk_buff *skb, struct mfc6_cache *c, int vifi)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1917
1918
  {
  	struct ipv6hdr *ipv6h;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1919
  	struct mif_device *vif = &mrt->vif6_table[vifi];
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1920
1921
  	struct net_device *dev;
  	struct dst_entry *dst;
4c9483b2f   David S. Miller   ipv6: Convert to ...
1922
  	struct flowi6 fl6;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1923

63159f29b   Ian Morris   ipv6: coding styl...
1924
  	if (!vif->dev)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1925
  		goto out_free;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1926
1927
1928
1929
  #ifdef CONFIG_IPV6_PIMSM_V2
  	if (vif->flags & MIFF_REGISTER) {
  		vif->pkt_out++;
  		vif->bytes_out += skb->len;
dc58c78c0   Pavel Emelyanov   ip6mr: Use on-dev...
1930
1931
  		vif->dev->stats.tx_bytes += skb->len;
  		vif->dev->stats.tx_packets++;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1932
  		ip6mr_cache_report(mrt, skb, vifi, MRT6MSG_WHOLEPKT);
8da73b73e   Ilpo Järvinen   ip6mr: use goto t...
1933
  		goto out_free;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1934
1935
  	}
  #endif
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1936
  	ipv6h = ipv6_hdr(skb);
4c9483b2f   David S. Miller   ipv6: Convert to ...
1937
1938
1939
  	fl6 = (struct flowi6) {
  		.flowi6_oif = vif->link,
  		.daddr = ipv6h->daddr,
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1940
  	};
4c9483b2f   David S. Miller   ipv6: Convert to ...
1941
  	dst = ip6_route_output(net, NULL, &fl6);
5095d64db   RongQing.Li   ipv6: ip6_route_o...
1942
1943
  	if (dst->error) {
  		dst_release(dst);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1944
  		goto out_free;
5095d64db   RongQing.Li   ipv6: ip6_route_o...
1945
  	}
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1946

adf30907d   Eric Dumazet   net: skb->dst acc...
1947
1948
  	skb_dst_drop(skb);
  	skb_dst_set(skb, dst);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
  
  	/*
  	 * RFC1584 teaches, that DVMRP/PIM router must deliver packets locally
  	 * not only before forwarding, but after forwarding on all output
  	 * interfaces. It is clear, if mrouter runs a multicasting
  	 * program, it should receive packets not depending to what interface
  	 * program is joined.
  	 * If we will not make it, the program will have to join on all
  	 * interfaces. On the other hand, multihoming host (or router, but
  	 * not mrouter) cannot join to more than one interface - it will
  	 * result in receiving multiple packets.
  	 */
  	dev = vif->dev;
  	skb->dev = dev;
  	vif->pkt_out++;
  	vif->bytes_out += skb->len;
  
  	/* We are about to write */
  	/* XXX: extension headers? */
  	if (skb_cow(skb, sizeof(*ipv6h) + LL_RESERVED_SPACE(dev)))
  		goto out_free;
  
  	ipv6h = ipv6_hdr(skb);
  	ipv6h->hop_limit--;
  
  	IP6CB(skb)->flags |= IP6SKB_FORWARDED;
29a26a568   Eric W. Biederman   netfilter: Pass s...
1975
1976
  	return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD,
  		       net, NULL, skb, skb->dev, dev,
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1977
1978
1979
1980
1981
1982
  		       ip6mr_forward2_finish);
  
  out_free:
  	kfree_skb(skb);
  	return 0;
  }
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1983
  static int ip6mr_find_vif(struct mr6_table *mrt, struct net_device *dev)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1984
1985
  {
  	int ct;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1986
1987
1988
  
  	for (ct = mrt->maxvif - 1; ct >= 0; ct--) {
  		if (mrt->vif6_table[ct].dev == dev)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1989
1990
1991
1992
  			break;
  	}
  	return ct;
  }
2b52c3ada   Rami Rosen   ip6mr: change the...
1993
1994
  static void ip6_mr_forward(struct net *net, struct mr6_table *mrt,
  			   struct sk_buff *skb, struct mfc6_cache *cache)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1995
1996
1997
  {
  	int psend = -1;
  	int vif, ct;
660b26dc1   Nicolas Dichtel   mcast: add multic...
1998
  	int true_vifi = ip6mr_find_vif(mrt, skb->dev);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1999
2000
2001
2002
  
  	vif = cache->mf6c_parent;
  	cache->mfc_un.res.pkt++;
  	cache->mfc_un.res.bytes += skb->len;
43b9e1274   Nikolay Aleksandrov   net: ipmr/ip6mr: ...
2003
  	cache->mfc_un.res.lastuse = jiffies;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2004

660b26dc1   Nicolas Dichtel   mcast: add multic...
2005
2006
  	if (ipv6_addr_any(&cache->mf6c_origin) && true_vifi >= 0) {
  		struct mfc6_cache *cache_proxy;
40dc2ca3c   Fabian Frederick   ipv6: spelling s/...
2007
  		/* For an (*,G) entry, we only check that the incoming
660b26dc1   Nicolas Dichtel   mcast: add multic...
2008
2009
2010
2011
2012
2013
2014
  		 * interface is part of the static tree.
  		 */
  		cache_proxy = ip6mr_cache_find_any_parent(mrt, vif);
  		if (cache_proxy &&
  		    cache_proxy->mfc_un.res.ttls[true_vifi] < 255)
  			goto forward;
  	}
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2015
2016
2017
  	/*
  	 * Wrong interface: drop packet and (maybe) send PIM assert.
  	 */
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
2018
  	if (mrt->vif6_table[vif].dev != skb->dev) {
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2019
  		cache->mfc_un.res.wrong_if++;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2020

6bd521433   Patrick McHardy   ipv6: ip6mr: move...
2021
  		if (true_vifi >= 0 && mrt->mroute_do_assert &&
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2022
2023
2024
2025
2026
  		    /* pimsm uses asserts, when switching from RPT to SPT,
  		       so that we cannot check that packet arrived on an oif.
  		       It is bad, but otherwise we would need to move pretty
  		       large chunk of pimd to kernel. Ough... --ANK
  		     */
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
2027
  		    (mrt->mroute_do_pim ||
a21f3f997   Benjamin Thery   netns: ip6mr: dec...
2028
  		     cache->mfc_un.res.ttls[true_vifi] < 255) &&
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2029
2030
2031
  		    time_after(jiffies,
  			       cache->mfc_un.res.last_assert + MFC_ASSERT_THRESH)) {
  			cache->mfc_un.res.last_assert = jiffies;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
2032
  			ip6mr_cache_report(mrt, skb, true_vifi, MRT6MSG_WRONGMIF);
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2033
2034
2035
  		}
  		goto dont_forward;
  	}
660b26dc1   Nicolas Dichtel   mcast: add multic...
2036
  forward:
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
2037
2038
  	mrt->vif6_table[vif].pkt_in++;
  	mrt->vif6_table[vif].bytes_in += skb->len;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2039
2040
2041
2042
  
  	/*
  	 *	Forward the frame
  	 */
660b26dc1   Nicolas Dichtel   mcast: add multic...
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
  	if (ipv6_addr_any(&cache->mf6c_origin) &&
  	    ipv6_addr_any(&cache->mf6c_mcastgrp)) {
  		if (true_vifi >= 0 &&
  		    true_vifi != cache->mf6c_parent &&
  		    ipv6_hdr(skb)->hop_limit >
  				cache->mfc_un.res.ttls[cache->mf6c_parent]) {
  			/* It's an (*,*) entry and the packet is not coming from
  			 * the upstream: forward the packet to the upstream
  			 * only.
  			 */
  			psend = cache->mf6c_parent;
  			goto last_forward;
  		}
  		goto dont_forward;
  	}
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2058
  	for (ct = cache->mfc_un.res.maxvif - 1; ct >= cache->mfc_un.res.minvif; ct--) {
660b26dc1   Nicolas Dichtel   mcast: add multic...
2059
2060
2061
  		/* For (*,G) entry, don't forward to the incoming interface */
  		if ((!ipv6_addr_any(&cache->mf6c_origin) || ct != true_vifi) &&
  		    ipv6_hdr(skb)->hop_limit > cache->mfc_un.res.ttls[ct]) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2062
2063
2064
  			if (psend != -1) {
  				struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
  				if (skb2)
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
2065
  					ip6mr_forward2(net, mrt, skb2, cache, psend);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2066
2067
2068
2069
  			}
  			psend = ct;
  		}
  	}
660b26dc1   Nicolas Dichtel   mcast: add multic...
2070
  last_forward:
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2071
  	if (psend != -1) {
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
2072
  		ip6mr_forward2(net, mrt, skb, cache, psend);
2b52c3ada   Rami Rosen   ip6mr: change the...
2073
  		return;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2074
  	}
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2075
  dont_forward:
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2076
  	kfree_skb(skb);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
  }
  
  
  /*
   *	Multicast packets for forwarding arrive here
   */
  
  int ip6_mr_input(struct sk_buff *skb)
  {
  	struct mfc6_cache *cache;
8229efdae   Benjamin Thery   netns: ip6mr: ena...
2087
  	struct net *net = dev_net(skb->dev);
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
2088
  	struct mr6_table *mrt;
4c9483b2f   David S. Miller   ipv6: Convert to ...
2089
2090
2091
  	struct flowi6 fl6 = {
  		.flowi6_iif	= skb->dev->ifindex,
  		.flowi6_mark	= skb->mark,
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
2092
2093
  	};
  	int err;
4c9483b2f   David S. Miller   ipv6: Convert to ...
2094
  	err = ip6mr_fib_lookup(net, &fl6, &mrt);
2015de5fe   Ben Greear   ipv6-multicast: F...
2095
2096
  	if (err < 0) {
  		kfree_skb(skb);
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
2097
  		return err;
2015de5fe   Ben Greear   ipv6-multicast: F...
2098
  	}
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2099
2100
  
  	read_lock(&mrt_lock);
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
2101
  	cache = ip6mr_cache_find(mrt,
8229efdae   Benjamin Thery   netns: ip6mr: ena...
2102
  				 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr);
63159f29b   Ian Morris   ipv6: coding styl...
2103
  	if (!cache) {
660b26dc1   Nicolas Dichtel   mcast: add multic...
2104
2105
2106
2107
2108
2109
2110
  		int vif = ip6mr_find_vif(mrt, skb->dev);
  
  		if (vif >= 0)
  			cache = ip6mr_cache_find_any(mrt,
  						     &ipv6_hdr(skb)->daddr,
  						     vif);
  	}
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2111
2112
2113
2114
  
  	/*
  	 *	No usable cache entry
  	 */
63159f29b   Ian Morris   ipv6: coding styl...
2115
  	if (!cache) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2116
  		int vif;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
2117
  		vif = ip6mr_find_vif(mrt, skb->dev);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2118
  		if (vif >= 0) {
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
2119
  			int err = ip6mr_cache_unresolved(mrt, vif, skb);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2120
2121
2122
2123
2124
2125
2126
2127
  			read_unlock(&mrt_lock);
  
  			return err;
  		}
  		read_unlock(&mrt_lock);
  		kfree_skb(skb);
  		return -ENODEV;
  	}
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
2128
  	ip6_mr_forward(net, mrt, skb, cache);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2129
2130
2131
2132
2133
  
  	read_unlock(&mrt_lock);
  
  	return 0;
  }
5b285cac3   Patrick McHardy   ipv6: ip6mr: add ...
2134
2135
  static int __ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb,
  			       struct mfc6_cache *c, struct rtmsg *rtm)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2136
  {
adfa85e45   Nicolas Dichtel   ipmr/ip6mr: adver...
2137
  	struct rta_mfc_stats mfcs;
43b9e1274   Nikolay Aleksandrov   net: ipmr/ip6mr: ...
2138
2139
  	struct nlattr *mp_attr;
  	struct rtnexthop *nhp;
b5036cd4e   Nikolay Aleksandrov   ipmr, ip6mr: retu...
2140
  	unsigned long lastuse;
43b9e1274   Nikolay Aleksandrov   net: ipmr/ip6mr: ...
2141
  	int ct;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2142

7438189ba   Nicolas Dichtel   net: ipmr/ip6mr: ...
2143
  	/* If cache is unresolved, don't try to parse IIF and OIF */
1708ebc96   Nikolay Aleksandrov   ipmr, ip6mr: add ...
2144
2145
  	if (c->mf6c_parent >= MAXMIFS) {
  		rtm->rtm_flags |= RTNH_F_UNRESOLVED;
7438189ba   Nicolas Dichtel   net: ipmr/ip6mr: ...
2146
  		return -ENOENT;
1708ebc96   Nikolay Aleksandrov   ipmr, ip6mr: add ...
2147
  	}
7438189ba   Nicolas Dichtel   net: ipmr/ip6mr: ...
2148

74a0bd7d0   Thomas Graf   ip6mr: Do not use...
2149
2150
2151
  	if (MIF_EXISTS(mrt, c->mf6c_parent) &&
  	    nla_put_u32(skb, RTA_IIF, mrt->vif6_table[c->mf6c_parent].dev->ifindex) < 0)
  		return -EMSGSIZE;
70b386a0c   Nicolas Dichtel   ip6mr: use nla_ne...
2152
  	mp_attr = nla_nest_start(skb, RTA_MULTIPATH);
63159f29b   Ian Morris   ipv6: coding styl...
2153
  	if (!mp_attr)
70b386a0c   Nicolas Dichtel   ip6mr: use nla_ne...
2154
  		return -EMSGSIZE;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2155
2156
  
  	for (ct = c->mfc_un.res.minvif; ct < c->mfc_un.res.maxvif; ct++) {
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
2157
  		if (MIF_EXISTS(mrt, ct) && c->mfc_un.res.ttls[ct] < 255) {
70b386a0c   Nicolas Dichtel   ip6mr: use nla_ne...
2158
  			nhp = nla_reserve_nohdr(skb, sizeof(*nhp));
63159f29b   Ian Morris   ipv6: coding styl...
2159
  			if (!nhp) {
70b386a0c   Nicolas Dichtel   ip6mr: use nla_ne...
2160
2161
2162
  				nla_nest_cancel(skb, mp_attr);
  				return -EMSGSIZE;
  			}
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2163
2164
  			nhp->rtnh_flags = 0;
  			nhp->rtnh_hops = c->mfc_un.res.ttls[ct];
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
2165
  			nhp->rtnh_ifindex = mrt->vif6_table[ct].dev->ifindex;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2166
2167
2168
  			nhp->rtnh_len = sizeof(*nhp);
  		}
  	}
70b386a0c   Nicolas Dichtel   ip6mr: use nla_ne...
2169
2170
  
  	nla_nest_end(skb, mp_attr);
b5036cd4e   Nikolay Aleksandrov   ipmr, ip6mr: retu...
2171
2172
  	lastuse = READ_ONCE(c->mfc_un.res.lastuse);
  	lastuse = time_after_eq(jiffies, lastuse) ? jiffies - lastuse : 0;
adfa85e45   Nicolas Dichtel   ipmr/ip6mr: adver...
2173
2174
2175
  	mfcs.mfcs_packets = c->mfc_un.res.pkt;
  	mfcs.mfcs_bytes = c->mfc_un.res.bytes;
  	mfcs.mfcs_wrong_if = c->mfc_un.res.wrong_if;
43b9e1274   Nikolay Aleksandrov   net: ipmr/ip6mr: ...
2176
  	if (nla_put_64bit(skb, RTA_MFC_STATS, sizeof(mfcs), &mfcs, RTA_PAD) ||
b5036cd4e   Nikolay Aleksandrov   ipmr, ip6mr: retu...
2177
  	    nla_put_u64_64bit(skb, RTA_EXPIRES, jiffies_to_clock_t(lastuse),
43b9e1274   Nikolay Aleksandrov   net: ipmr/ip6mr: ...
2178
  			      RTA_PAD))
adfa85e45   Nicolas Dichtel   ipmr/ip6mr: adver...
2179
  		return -EMSGSIZE;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2180
2181
  	rtm->rtm_type = RTN_MULTICAST;
  	return 1;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2182
  }
2cf750704   Nikolay Aleksandrov   ipmr, ip6mr: fix ...
2183
  int ip6mr_get_route(struct net *net, struct sk_buff *skb, struct rtmsg *rtm,
fd61c6ba3   David Ahern   net: ipv6: remove...
2184
  		    u32 portid)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2185
2186
  {
  	int err;
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
2187
  	struct mr6_table *mrt;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2188
  	struct mfc6_cache *cache;
adf30907d   Eric Dumazet   net: skb->dst acc...
2189
  	struct rt6_info *rt = (struct rt6_info *)skb_dst(skb);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2190

d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
2191
  	mrt = ip6mr_get_table(net, RT6_TABLE_DFLT);
63159f29b   Ian Morris   ipv6: coding styl...
2192
  	if (!mrt)
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
2193
  		return -ENOENT;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2194
  	read_lock(&mrt_lock);
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
2195
  	cache = ip6mr_cache_find(mrt, &rt->rt6i_src.addr, &rt->rt6i_dst.addr);
660b26dc1   Nicolas Dichtel   mcast: add multic...
2196
2197
2198
2199
2200
2201
2202
  	if (!cache && skb->dev) {
  		int vif = ip6mr_find_vif(mrt, skb->dev);
  
  		if (vif >= 0)
  			cache = ip6mr_cache_find_any(mrt, &rt->rt6i_dst.addr,
  						     vif);
  	}
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2203
2204
2205
2206
2207
2208
  
  	if (!cache) {
  		struct sk_buff *skb2;
  		struct ipv6hdr *iph;
  		struct net_device *dev;
  		int vif;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2209
  		dev = skb->dev;
63159f29b   Ian Morris   ipv6: coding styl...
2210
  		if (!dev || (vif = ip6mr_find_vif(mrt, dev)) < 0) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
  			read_unlock(&mrt_lock);
  			return -ENODEV;
  		}
  
  		/* really correct? */
  		skb2 = alloc_skb(sizeof(struct ipv6hdr), GFP_ATOMIC);
  		if (!skb2) {
  			read_unlock(&mrt_lock);
  			return -ENOMEM;
  		}
2cf750704   Nikolay Aleksandrov   ipmr, ip6mr: fix ...
2221
  		NETLINK_CB(skb2).portid = portid;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
  		skb_reset_transport_header(skb2);
  
  		skb_put(skb2, sizeof(struct ipv6hdr));
  		skb_reset_network_header(skb2);
  
  		iph = ipv6_hdr(skb2);
  		iph->version = 0;
  		iph->priority = 0;
  		iph->flow_lbl[0] = 0;
  		iph->flow_lbl[1] = 0;
  		iph->flow_lbl[2] = 0;
  		iph->payload_len = 0;
  		iph->nexthdr = IPPROTO_NONE;
  		iph->hop_limit = 0;
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
2236
2237
  		iph->saddr = rt->rt6i_src.addr;
  		iph->daddr = rt->rt6i_dst.addr;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2238

6bd521433   Patrick McHardy   ipv6: ip6mr: move...
2239
  		err = ip6mr_cache_unresolved(mrt, vif, skb2);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2240
2241
2242
2243
  		read_unlock(&mrt_lock);
  
  		return err;
  	}
fd61c6ba3   David Ahern   net: ipv6: remove...
2244
  	if (rtm->rtm_flags & RTM_F_NOTIFY)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2245
  		cache->mfc_flags |= MFC_NOTIFY;
5b285cac3   Patrick McHardy   ipv6: ip6mr: add ...
2246
  	err = __ip6mr_fill_mroute(mrt, skb, cache, rtm);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2247
2248
2249
  	read_unlock(&mrt_lock);
  	return err;
  }
5b285cac3   Patrick McHardy   ipv6: ip6mr: add ...
2250
  static int ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb,
f518338b1   Nicolas Dichtel   ip6mr: fix mfc no...
2251
2252
  			     u32 portid, u32 seq, struct mfc6_cache *c, int cmd,
  			     int flags)
5b285cac3   Patrick McHardy   ipv6: ip6mr: add ...
2253
2254
2255
  {
  	struct nlmsghdr *nlh;
  	struct rtmsg *rtm;
1eb99af52   Nicolas Dichtel   ipmr/ip6mr: allow...
2256
  	int err;
5b285cac3   Patrick McHardy   ipv6: ip6mr: add ...
2257

f518338b1   Nicolas Dichtel   ip6mr: fix mfc no...
2258
  	nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rtm), flags);
63159f29b   Ian Morris   ipv6: coding styl...
2259
  	if (!nlh)
5b285cac3   Patrick McHardy   ipv6: ip6mr: add ...
2260
2261
2262
  		return -EMSGSIZE;
  
  	rtm = nlmsg_data(nlh);
193c1e478   Nicolas Dichtel   ip6mr: fix rtm_fa...
2263
  	rtm->rtm_family   = RTNL_FAMILY_IP6MR;
5b285cac3   Patrick McHardy   ipv6: ip6mr: add ...
2264
2265
2266
2267
  	rtm->rtm_dst_len  = 128;
  	rtm->rtm_src_len  = 128;
  	rtm->rtm_tos      = 0;
  	rtm->rtm_table    = mrt->id;
c78679e8f   David S. Miller   ipv6: Stop using ...
2268
2269
  	if (nla_put_u32(skb, RTA_TABLE, mrt->id))
  		goto nla_put_failure;
1eb99af52   Nicolas Dichtel   ipmr/ip6mr: allow...
2270
  	rtm->rtm_type = RTN_MULTICAST;
5b285cac3   Patrick McHardy   ipv6: ip6mr: add ...
2271
  	rtm->rtm_scope    = RT_SCOPE_UNIVERSE;
9a68ac72a   Nicolas Dichtel   ipmr/ip6mr: repor...
2272
2273
2274
2275
  	if (c->mfc_flags & MFC_STATIC)
  		rtm->rtm_protocol = RTPROT_STATIC;
  	else
  		rtm->rtm_protocol = RTPROT_MROUTED;
5b285cac3   Patrick McHardy   ipv6: ip6mr: add ...
2276
  	rtm->rtm_flags    = 0;
930345ea6   Jiri Benc   netlink: implemen...
2277
2278
  	if (nla_put_in6_addr(skb, RTA_SRC, &c->mf6c_origin) ||
  	    nla_put_in6_addr(skb, RTA_DST, &c->mf6c_mcastgrp))
c78679e8f   David S. Miller   ipv6: Stop using ...
2279
  		goto nla_put_failure;
1eb99af52   Nicolas Dichtel   ipmr/ip6mr: allow...
2280
2281
2282
  	err = __ip6mr_fill_mroute(mrt, skb, c, rtm);
  	/* do not break the dump if cache is unresolved */
  	if (err < 0 && err != -ENOENT)
5b285cac3   Patrick McHardy   ipv6: ip6mr: add ...
2283
  		goto nla_put_failure;
053c095a8   Johannes Berg   netlink: make nlm...
2284
2285
  	nlmsg_end(skb, nlh);
  	return 0;
5b285cac3   Patrick McHardy   ipv6: ip6mr: add ...
2286
2287
2288
2289
2290
  
  nla_put_failure:
  	nlmsg_cancel(skb, nlh);
  	return -EMSGSIZE;
  }
812e44dd1   Nicolas Dichtel   ip6mr: advertise ...
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
  static int mr6_msgsize(bool unresolved, int maxvif)
  {
  	size_t len =
  		NLMSG_ALIGN(sizeof(struct rtmsg))
  		+ nla_total_size(4)	/* RTA_TABLE */
  		+ nla_total_size(sizeof(struct in6_addr))	/* RTA_SRC */
  		+ nla_total_size(sizeof(struct in6_addr))	/* RTA_DST */
  		;
  
  	if (!unresolved)
  		len = len
  		      + nla_total_size(4)	/* RTA_IIF */
  		      + nla_total_size(0)	/* RTA_MULTIPATH */
  		      + maxvif * NLA_ALIGN(sizeof(struct rtnexthop))
  						/* RTA_MFC_STATS */
3d6b66c1d   Nicolas Dichtel   ip6mr: align RTA_...
2306
  		      + nla_total_size_64bit(sizeof(struct rta_mfc_stats))
812e44dd1   Nicolas Dichtel   ip6mr: advertise ...
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
  		;
  
  	return len;
  }
  
  static void mr6_netlink_event(struct mr6_table *mrt, struct mfc6_cache *mfc,
  			      int cmd)
  {
  	struct net *net = read_pnet(&mrt->net);
  	struct sk_buff *skb;
  	int err = -ENOBUFS;
  
  	skb = nlmsg_new(mr6_msgsize(mfc->mf6c_parent >= MAXMIFS, mrt->maxvif),
  			GFP_ATOMIC);
63159f29b   Ian Morris   ipv6: coding styl...
2321
  	if (!skb)
812e44dd1   Nicolas Dichtel   ip6mr: advertise ...
2322
  		goto errout;
f518338b1   Nicolas Dichtel   ip6mr: fix mfc no...
2323
  	err = ip6mr_fill_mroute(mrt, skb, 0, 0, mfc, cmd, 0);
812e44dd1   Nicolas Dichtel   ip6mr: advertise ...
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
  	if (err < 0)
  		goto errout;
  
  	rtnl_notify(skb, net, 0, RTNLGRP_IPV6_MROUTE, NULL, GFP_ATOMIC);
  	return;
  
  errout:
  	kfree_skb(skb);
  	if (err < 0)
  		rtnl_set_sk_err(net, RTNLGRP_IPV6_MROUTE, err);
  }
dd12d15c9   Julien Gomes   ip6mr: add netlin...
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
  static size_t mrt6msg_netlink_msgsize(size_t payloadlen)
  {
  	size_t len =
  		NLMSG_ALIGN(sizeof(struct rtgenmsg))
  		+ nla_total_size(1)	/* IP6MRA_CREPORT_MSGTYPE */
  		+ nla_total_size(4)	/* IP6MRA_CREPORT_MIF_ID */
  					/* IP6MRA_CREPORT_SRC_ADDR */
  		+ nla_total_size(sizeof(struct in6_addr))
  					/* IP6MRA_CREPORT_DST_ADDR */
  		+ nla_total_size(sizeof(struct in6_addr))
  					/* IP6MRA_CREPORT_PKT */
  		+ nla_total_size(payloadlen)
  		;
  
  	return len;
  }
  
  static void mrt6msg_netlink_event(struct mr6_table *mrt, struct sk_buff *pkt)
  {
  	struct net *net = read_pnet(&mrt->net);
  	struct nlmsghdr *nlh;
  	struct rtgenmsg *rtgenm;
  	struct mrt6msg *msg;
  	struct sk_buff *skb;
  	struct nlattr *nla;
  	int payloadlen;
  
  	payloadlen = pkt->len - sizeof(struct mrt6msg);
  	msg = (struct mrt6msg *)skb_transport_header(pkt);
  
  	skb = nlmsg_new(mrt6msg_netlink_msgsize(payloadlen), GFP_ATOMIC);
  	if (!skb)
  		goto errout;
  
  	nlh = nlmsg_put(skb, 0, 0, RTM_NEWCACHEREPORT,
  			sizeof(struct rtgenmsg), 0);
  	if (!nlh)
  		goto errout;
  	rtgenm = nlmsg_data(nlh);
  	rtgenm->rtgen_family = RTNL_FAMILY_IP6MR;
  	if (nla_put_u8(skb, IP6MRA_CREPORT_MSGTYPE, msg->im6_msgtype) ||
  	    nla_put_u32(skb, IP6MRA_CREPORT_MIF_ID, msg->im6_mif) ||
  	    nla_put_in6_addr(skb, IP6MRA_CREPORT_SRC_ADDR,
  			     &msg->im6_src) ||
  	    nla_put_in6_addr(skb, IP6MRA_CREPORT_DST_ADDR,
  			     &msg->im6_dst))
  		goto nla_put_failure;
  
  	nla = nla_reserve(skb, IP6MRA_CREPORT_PKT, payloadlen);
  	if (!nla || skb_copy_bits(pkt, sizeof(struct mrt6msg),
  				  nla_data(nla), payloadlen))
  		goto nla_put_failure;
  
  	nlmsg_end(skb, nlh);
  
  	rtnl_notify(skb, net, 0, RTNLGRP_IPV6_MROUTE_R, NULL, GFP_ATOMIC);
  	return;
  
  nla_put_failure:
  	nlmsg_cancel(skb, nlh);
  errout:
  	kfree_skb(skb);
  	rtnl_set_sk_err(net, RTNLGRP_IPV6_MROUTE_R, -ENOBUFS);
  }
5b285cac3   Patrick McHardy   ipv6: ip6mr: add ...
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
  static int ip6mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
  {
  	struct net *net = sock_net(skb->sk);
  	struct mr6_table *mrt;
  	struct mfc6_cache *mfc;
  	unsigned int t = 0, s_t;
  	unsigned int h = 0, s_h;
  	unsigned int e = 0, s_e;
  
  	s_t = cb->args[0];
  	s_h = cb->args[1];
  	s_e = cb->args[2];
  
  	read_lock(&mrt_lock);
  	ip6mr_for_each_table(mrt, net) {
  		if (t < s_t)
  			goto next_table;
  		if (t > s_t)
  			s_h = 0;
  		for (h = s_h; h < MFC6_LINES; h++) {
  			list_for_each_entry(mfc, &mrt->mfc6_cache_array[h], list) {
  				if (e < s_e)
  					goto next_entry;
  				if (ip6mr_fill_mroute(mrt, skb,
15e473046   Eric W. Biederman   netlink: Rename p...
2423
  						      NETLINK_CB(cb->skb).portid,
5b285cac3   Patrick McHardy   ipv6: ip6mr: add ...
2424
  						      cb->nlh->nlmsg_seq,
f518338b1   Nicolas Dichtel   ip6mr: fix mfc no...
2425
2426
  						      mfc, RTM_NEWROUTE,
  						      NLM_F_MULTI) < 0)
5b285cac3   Patrick McHardy   ipv6: ip6mr: add ...
2427
2428
2429
2430
2431
2432
  					goto done;
  next_entry:
  				e++;
  			}
  			e = s_e = 0;
  		}
1eb99af52   Nicolas Dichtel   ipmr/ip6mr: allow...
2433
2434
2435
2436
2437
2438
2439
  		spin_lock_bh(&mfc_unres_lock);
  		list_for_each_entry(mfc, &mrt->mfc6_unres_queue, list) {
  			if (e < s_e)
  				goto next_entry2;
  			if (ip6mr_fill_mroute(mrt, skb,
  					      NETLINK_CB(cb->skb).portid,
  					      cb->nlh->nlmsg_seq,
f518338b1   Nicolas Dichtel   ip6mr: fix mfc no...
2440
2441
  					      mfc, RTM_NEWROUTE,
  					      NLM_F_MULTI) < 0) {
1eb99af52   Nicolas Dichtel   ipmr/ip6mr: allow...
2442
2443
2444
2445
2446
2447
2448
2449
  				spin_unlock_bh(&mfc_unres_lock);
  				goto done;
  			}
  next_entry2:
  			e++;
  		}
  		spin_unlock_bh(&mfc_unres_lock);
  		e = s_e = 0;
5b285cac3   Patrick McHardy   ipv6: ip6mr: add ...
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
  		s_h = 0;
  next_table:
  		t++;
  	}
  done:
  	read_unlock(&mrt_lock);
  
  	cb->args[2] = e;
  	cb->args[1] = h;
  	cb->args[0] = t;
  
  	return skb->len;
  }