Blame view

net/ipv6/ip6mr.c 50.8 KB
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  /*
   *	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.
   *
   */
  
  #include <asm/system.h>
  #include <asm/uaccess.h>
  #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...
30
31
32
  #include <linux/inet.h>
  #include <linux/netdevice.h>
  #include <linux/inetdevice.h>
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
33
34
  #include <linux/proc_fs.h>
  #include <linux/seq_file.h>
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
35
  #include <linux/init.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
36
  #include <linux/slab.h>
e2d57766e   David S. Miller   net: Provide comp...
37
  #include <linux/compat.h>
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
38
39
40
  #include <net/protocol.h>
  #include <linux/skbuff.h>
  #include <net/sock.h>
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
41
  #include <net/raw.h>
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
42
43
  #include <linux/notifier.h>
  #include <linux/if_arp.h>
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
44
45
  #include <net/checksum.h>
  #include <net/netlink.h>
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
46
  #include <net/fib_rules.h>
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
47
48
49
50
  
  #include <net/ipv6.h>
  #include <net/ip6_route.h>
  #include <linux/mroute6.h>
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
51
  #include <linux/pim.h>
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
52
53
  #include <net/addrconf.h>
  #include <linux/netfilter_ipv6.h>
bc3b2d7fb   Paul Gortmaker   net: Add export.h...
54
  #include <linux/export.h>
5d6e430d3   Dave Jones   ipv6: compile fix...
55
  #include <net/ip6_checksum.h>
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
56

6bd521433   Patrick McHardy   ipv6: ip6mr: move...
57
  struct mr6_table {
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
58
  	struct list_head	list;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
59
60
61
  #ifdef CONFIG_NET_NS
  	struct net		*net;
  #endif
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
62
  	u32			id;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
63
64
65
66
67
68
69
70
71
72
73
74
75
  	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;
  	int			mroute_do_assert;
  	int			mroute_do_pim;
  #ifdef CONFIG_IPV6_PIMSM_V2
  	int			mroute_reg_vif_num;
  #endif
  };
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
76
77
78
79
80
81
82
  struct ip6mr_rule {
  	struct fib_rule		common;
  };
  
  struct ip6mr_result {
  	struct mr6_table	*mrt;
  };
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
83
84
85
86
87
88
89
90
91
  /* 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...
92
  #define MIF_EXISTS(_mrt, _idx) ((_mrt)->vif6_table[_idx].dev != NULL)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
93

7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
94
95
96
97
98
99
100
101
102
103
104
105
  /* 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...
106
107
  static struct mr6_table *ip6mr_new_table(struct net *net, u32 id);
  static void ip6mr_free_table(struct mr6_table *mrt);
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
108
109
110
  static int ip6_mr_forward(struct net *net, struct mr6_table *mrt,
  			  struct sk_buff *skb, struct mfc6_cache *cache);
  static int ip6mr_cache_report(struct mr6_table *mrt, struct sk_buff *pkt,
8229efdae   Benjamin Thery   netns: ip6mr: ena...
111
  			      mifi_t mifi, int assert);
5b285cac3   Patrick McHardy   ipv6: ip6mr: add ...
112
113
114
115
  static int __ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb,
  			       struct mfc6_cache *c, struct rtmsg *rtm);
  static int ip6mr_rtm_dumproute(struct sk_buff *skb,
  			       struct netlink_callback *cb);
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
116
  static void mroute_clean_tables(struct mr6_table *mrt);
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
117
118
119
  static void ipmr_expire_process(unsigned long arg);
  
  #ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
8ffb335e8   Eric Dumazet   ip6mr: fix a typo...
120
  #define ip6mr_for_each_table(mrt, net) \
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
121
122
123
124
125
126
127
128
129
130
131
132
  	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 ...
133
  static int ip6mr_fib_lookup(struct net *net, struct flowi6 *flp6,
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
134
135
136
137
138
  			    struct mr6_table **mrt)
  {
  	struct ip6mr_result res;
  	struct fib_lookup_arg arg = { .result = &res, };
  	int err;
4c9483b2f   David S. Miller   ipv6: Convert to ...
139
140
  	err = fib_rules_lookup(net->ipv6.mr6_rules_ops,
  			       flowi6_to_flowi(flp6), 0, &arg);
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
141
142
143
144
145
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
171
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
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
  	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);
  	if (mrt == NULL)
  		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;
  }
  
  static const struct fib_rules_ops __net_initdata ip6mr_rules_ops_template = {
  	.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,
  	.default_pref	= fib_default_rule_pref,
  	.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);
  	if (mrt == NULL) {
  		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:
  	kfree(mrt);
  err1:
  	fib_rules_unregister(ops);
  	return err;
  }
  
  static void __net_exit ip6mr_rules_exit(struct net *net)
  {
  	struct mr6_table *mrt, *next;
035320d54   Eric Dumazet   ipmr: dont corrup...
252
253
  	list_for_each_entry_safe(mrt, next, &net->ipv6.mr6_tables, list) {
  		list_del(&mrt->list);
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
254
  		ip6mr_free_table(mrt);
035320d54   Eric Dumazet   ipmr: dont corrup...
255
  	}
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
256
257
258
259
260
261
262
263
264
265
  	fib_rules_unregister(net->ipv6.mr6_rules_ops);
  }
  #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 ...
266
  static int ip6mr_fib_lookup(struct net *net, struct flowi6 *flp6,
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
  			    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)
  {
  	ip6mr_free_table(net->ipv6.mrt6);
  }
  #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);
  	if (mrt != NULL)
  		return mrt;
  
  	mrt = kzalloc(sizeof(*mrt), GFP_KERNEL);
  	if (mrt == NULL)
  		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...
317

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

7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
393
  	read_lock(&mrt_lock);
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
394
395
  	return *pos ? ip6mr_vif_seq_idx(net, seq->private, *pos - 1)
  		: SEQ_START_TOKEN;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
396
397
398
399
400
  }
  
  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...
401
  	struct net *net = seq_file_net(seq);
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
402
  	struct mr6_table *mrt = iter->mrt;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
403
404
405
  
  	++*pos;
  	if (v == SEQ_START_TOKEN)
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
406
  		return ip6mr_vif_seq_idx(net, iter, 0);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
407

6bd521433   Patrick McHardy   ipv6: ip6mr: move...
408
409
  	while (++iter->ct < mrt->maxvif) {
  		if (!MIF_EXISTS(mrt, iter->ct))
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
410
  			continue;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
411
  		return &mrt->vif6_table[iter->ct];
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
412
413
414
415
416
417
418
419
420
421
422
423
  	}
  	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...
424
425
  	struct ipmr_vif_iter *iter = seq->private;
  	struct mr6_table *mrt = iter->mrt;
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
426

7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
427
428
429
430
431
432
433
434
435
  	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...
436
437
  			   "%2td %-10s %8ld %7ld  %8ld %7ld %05X
  ",
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
438
  			   vif - mrt->vif6_table,
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
439
440
441
442
443
444
  			   name, vif->bytes_in, vif->pkt_in,
  			   vif->bytes_out, vif->pkt_out,
  			   vif->flags);
  	}
  	return 0;
  }
98147d527   Stephen Hemminger   net: seq_operatio...
445
  static const struct seq_operations ip6mr_vif_seq_ops = {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
446
447
448
449
450
451
452
453
  	.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...
454
455
  	return seq_open_net(inode, file, &ip6mr_vif_seq_ops,
  			    sizeof(struct ipmr_vif_iter));
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
456
  }
5ca1b998d   Stephen Hemminger   net: file_operati...
457
  static const struct file_operations ip6mr_vif_fops = {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
458
459
460
461
  	.owner	 = THIS_MODULE,
  	.open    = ip6mr_vif_open,
  	.read    = seq_read,
  	.llseek  = seq_lseek,
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
462
  	.release = seq_release_net,
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
463
464
465
466
  };
  
  static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos)
  {
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
467
  	struct ipmr_mfc_iter *it = seq->private;
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
468
  	struct net *net = seq_file_net(seq);
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
469
  	struct mr6_table *mrt;
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
470

d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
471
472
473
474
475
  	mrt = ip6mr_get_table(net, RT6_TABLE_DFLT);
  	if (mrt == NULL)
  		return ERR_PTR(-ENOENT);
  
  	it->mrt = mrt;
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
476
477
  	return *pos ? ipmr_mfc_seq_idx(net, seq->private, *pos - 1)
  		: SEQ_START_TOKEN;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
478
479
480
481
482
483
  }
  
  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...
484
  	struct net *net = seq_file_net(seq);
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
485
  	struct mr6_table *mrt = it->mrt;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
486
487
488
489
  
  	++*pos;
  
  	if (v == SEQ_START_TOKEN)
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
490
  		return ipmr_mfc_seq_idx(net, seq->private, 0);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
491

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

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

4a6258a0e   Benjamin Thery   netns: ip6mr: dyn...
499
  	while (++it->ct < MFC6_LINES) {
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
500
  		it->cache = &mrt->mfc6_cache_array[it->ct];
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
501
502
503
  		if (list_empty(it->cache))
  			continue;
  		return list_first_entry(it->cache, struct mfc6_cache, list);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
504
505
506
507
  	}
  
  	/* exhausted cache_array, show unresolved */
  	read_unlock(&mrt_lock);
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
508
  	it->cache = &mrt->mfc6_unres_queue;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
509
510
511
  	it->ct = 0;
  
  	spin_lock_bh(&mfc_unres_lock);
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
512
513
  	if (!list_empty(it->cache))
  		return list_first_entry(it->cache, struct mfc6_cache, list);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
514
515
516
517
518
519
520
521
522
523
524
  
   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...
525
  	struct mr6_table *mrt = it->mrt;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
526

6bd521433   Patrick McHardy   ipv6: ip6mr: move...
527
  	if (it->cache == &mrt->mfc6_unres_queue)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
528
  		spin_unlock_bh(&mfc_unres_lock);
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
529
  	else if (it->cache == mrt->mfc6_cache_array)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
  		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...
546
  		struct mr6_table *mrt = it->mrt;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
547

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

6bd521433   Patrick McHardy   ipv6: ip6mr: move...
552
  		if (it->cache != &mrt->mfc6_unres_queue) {
1ea472e2d   Benjamin Thery   net: fix /proc/ne...
553
554
555
556
  			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...
557
558
  			for (n = mfc->mfc_un.res.minvif;
  			     n < mfc->mfc_un.res.maxvif; n++) {
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
559
  				if (MIF_EXISTS(mrt, n) &&
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
560
561
562
563
564
  				    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...
565
566
567
568
569
  		} 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...
570
571
572
573
574
575
  		}
  		seq_putc(seq, '
  ');
  	}
  	return 0;
  }
88e9d34c7   James Morris   seq_file: constif...
576
  static const struct seq_operations ipmr_mfc_seq_ops = {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
577
578
579
580
581
582
583
584
  	.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...
585
586
  	return seq_open_net(inode, file, &ipmr_mfc_seq_ops,
  			    sizeof(struct ipmr_mfc_iter));
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
587
  }
5ca1b998d   Stephen Hemminger   net: file_operati...
588
  static const struct file_operations ip6mr_mfc_fops = {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
589
590
591
592
  	.owner	 = THIS_MODULE,
  	.open    = ipmr_mfc_open,
  	.read    = seq_read,
  	.llseek  = seq_lseek,
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
593
  	.release = seq_release_net,
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
594
595
  };
  #endif
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
596
  #ifdef CONFIG_IPV6_PIMSM_V2
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
597
598
599
600
601
602
  
  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...
603
  	struct net *net = dev_net(skb->dev);
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
604
  	struct mr6_table *mrt;
4c9483b2f   David S. Miller   ipv6: Convert to ...
605
606
607
  	struct flowi6 fl6 = {
  		.flowi6_iif	= skb->dev->ifindex,
  		.flowi6_mark	= skb->mark,
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
608
609
  	};
  	int reg_vif_num;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
610
611
612
613
614
615
616
  
  	if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(*encap)))
  		goto drop;
  
  	pim = (struct pimreghdr *)skb_transport_header(skb);
  	if (pim->type != ((PIM_VERSION << 4) | PIM_REGISTER) ||
  	    (pim->flags & PIM_NULL_REGISTER) ||
1d6e55f19   Thomas Goff   IPv6: Fix multica...
617
618
619
  	    (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...
620
  	     csum_fold(skb_checksum(skb, 0, skb->len, 0))))
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
621
622
623
624
625
626
627
628
629
630
  		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 ...
631
  	if (ip6mr_fib_lookup(net, &fl6, &mrt) < 0)
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
632
633
  		goto drop;
  	reg_vif_num = mrt->mroute_reg_vif_num;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
634
635
  	read_lock(&mrt_lock);
  	if (reg_vif_num >= 0)
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
636
  		reg_dev = mrt->vif6_table[reg_vif_num].dev;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
637
638
639
640
641
642
643
644
645
646
  	if (reg_dev)
  		dev_hold(reg_dev);
  	read_unlock(&mrt_lock);
  
  	if (reg_dev == NULL)
  		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...
647
  	skb->protocol = htons(ETH_P_IPV6);
3e49e6d52   Cesar Eduardo Barros   net: use CHECKSUM...
648
  	skb->ip_summed = CHECKSUM_NONE;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
649
  	skb->pkt_type = PACKET_HOST;
d19d56ddc   Eric Dumazet   net: Introduce sk...
650
651
  
  	skb_tunnel_rx(skb, reg_dev);
caf586e5f   Eric Dumazet   net: add a core n...
652
  	netif_rx(skb);
8990f468a   Eric Dumazet   net: rx_dropped a...
653

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

14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
682
  	read_lock(&mrt_lock);
dc58c78c0   Pavel Emelyanov   ip6mr: Use on-dev...
683
684
  	dev->stats.tx_bytes += skb->len;
  	dev->stats.tx_packets++;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
685
  	ip6mr_cache_report(mrt, skb, mrt->mroute_reg_vif_num, MRT6MSG_WHOLEPKT);
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
686
687
  	read_unlock(&mrt_lock);
  	kfree_skb(skb);
6ed106549   Patrick McHardy   net: use NETDEV_T...
688
  	return NETDEV_TX_OK;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
689
  }
007c3838d   Stephen Hemminger   ipmr: convert ipm...
690
691
692
  static const struct net_device_ops reg_vif_netdev_ops = {
  	.ndo_start_xmit	= reg_vif_xmit,
  };
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
693
694
695
696
697
  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...
698
  	dev->netdev_ops		= &reg_vif_netdev_ops;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
699
  	dev->destructor		= free_netdev;
403dbb97f   Tom Goff   PIM-SM: namespace...
700
  	dev->features		|= NETIF_F_NETNS_LOCAL;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
701
  }
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
702
  static struct net_device *ip6mr_reg_vif(struct net *net, struct mr6_table *mrt)
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
703
704
  {
  	struct net_device *dev;
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
705
706
707
708
709
710
  	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...
711

d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
712
  	dev = alloc_netdev(0, name, reg_vif_setup);
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
713
714
  	if (dev == NULL)
  		return NULL;
8229efdae   Benjamin Thery   netns: ip6mr: ena...
715
  	dev_net_set(dev, net);
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
716
717
718
719
720
  	if (register_netdevice(dev)) {
  		free_netdev(dev);
  		return NULL;
  	}
  	dev->iflink = 0;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
721
722
  	if (dev_open(dev))
  		goto failure;
7af3db78a   Wang Chen   ipv6: Fix using a...
723
  	dev_hold(dev);
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
724
725
726
727
728
729
730
731
732
733
734
  	return dev;
  
  failure:
  	/* allow the register to be completed before unregistering. */
  	rtnl_unlock();
  	rtnl_lock();
  
  	unregister_netdevice(dev);
  	return NULL;
  }
  #endif
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
735
736
737
  /*
   *	Delete a VIF entry
   */
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
738
  static int mif6_delete(struct mr6_table *mrt, int vifi, struct list_head *head)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
739
740
741
  {
  	struct mif_device *v;
  	struct net_device *dev;
1d6e55f19   Thomas Goff   IPv6: Fix multica...
742
  	struct inet6_dev *in6_dev;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
743
744
  
  	if (vifi < 0 || vifi >= mrt->maxvif)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
745
  		return -EADDRNOTAVAIL;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
746
  	v = &mrt->vif6_table[vifi];
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
747
748
749
750
751
752
753
754
755
  
  	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...
756
  #ifdef CONFIG_IPV6_PIMSM_V2
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
757
758
  	if (vifi == mrt->mroute_reg_vif_num)
  		mrt->mroute_reg_vif_num = -1;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
759
  #endif
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
760
  	if (vifi + 1 == mrt->maxvif) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
761
762
  		int tmp;
  		for (tmp = vifi - 1; tmp >= 0; tmp--) {
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
763
  			if (MIF_EXISTS(mrt, tmp))
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
764
765
  				break;
  		}
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
766
  		mrt->maxvif = tmp + 1;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
767
768
769
770
771
  	}
  
  	write_unlock_bh(&mrt_lock);
  
  	dev_set_allmulti(dev, -1);
1d6e55f19   Thomas Goff   IPv6: Fix multica...
772
773
774
  	in6_dev = __in6_dev_get(dev);
  	if (in6_dev)
  		in6_dev->cnf.mc_forwarding--;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
775
  	if (v->flags & MIFF_REGISTER)
c871e664e   Eric Dumazet   ip6mr: Optimize m...
776
  		unregister_netdevice_queue(dev, head);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
777
778
779
780
  
  	dev_put(dev);
  	return 0;
  }
58701ad41   Benjamin Thery   netns: ip6mr: sto...
781
782
  static inline void ip6mr_cache_free(struct mfc6_cache *c)
  {
58701ad41   Benjamin Thery   netns: ip6mr: sto...
783
784
  	kmem_cache_free(mrt_cachep, c);
  }
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
785
786
787
  /* Destroy an unresolved cache entry, killing queued skbs
     and reporting error to netlink readers.
   */
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
788
  static void ip6mr_destroy_unres(struct mr6_table *mrt, struct mfc6_cache *c)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
789
  {
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
790
  	struct net *net = read_pnet(&mrt->net);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
791
  	struct sk_buff *skb;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
792
  	atomic_dec(&mrt->cache_resolve_queue_len);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
793
794
795
796
797
798
799
800
  
  	while((skb = skb_dequeue(&c->mfc_un.unres.unresolved)) != NULL) {
  		if (ipv6_hdr(skb)->version == 0) {
  			struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct ipv6hdr));
  			nlh->nlmsg_type = NLMSG_ERROR;
  			nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct nlmsgerr));
  			skb_trim(skb, nlh->nlmsg_len);
  			((struct nlmsgerr *)NLMSG_DATA(nlh))->error = -ETIMEDOUT;
8229efdae   Benjamin Thery   netns: ip6mr: ena...
801
  			rtnl_unicast(skb, net, NETLINK_CB(skb).pid);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
802
803
804
  		} else
  			kfree_skb(skb);
  	}
58701ad41   Benjamin Thery   netns: ip6mr: sto...
805
  	ip6mr_cache_free(c);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
806
  }
c476efbcd   Patrick McHardy   ipv6: ip6mr: move...
807
  /* Timer process for all the unresolved queue. */
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
808

6bd521433   Patrick McHardy   ipv6: ip6mr: move...
809
  static void ipmr_do_expire_process(struct mr6_table *mrt)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
810
811
812
  {
  	unsigned long now = jiffies;
  	unsigned long expires = 10 * HZ;
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
813
  	struct mfc6_cache *c, *next;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
814

6bd521433   Patrick McHardy   ipv6: ip6mr: move...
815
  	list_for_each_entry_safe(c, next, &mrt->mfc6_unres_queue, list) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
816
817
818
819
820
  		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...
821
822
  			continue;
  		}
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
823
  		list_del(&c->list);
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
824
  		ip6mr_destroy_unres(mrt, c);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
825
  	}
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
826
827
  	if (!list_empty(&mrt->mfc6_unres_queue))
  		mod_timer(&mrt->ipmr_expire_timer, jiffies + expires);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
828
  }
c476efbcd   Patrick McHardy   ipv6: ip6mr: move...
829
  static void ipmr_expire_process(unsigned long arg)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
830
  {
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
831
  	struct mr6_table *mrt = (struct mr6_table *)arg;
c476efbcd   Patrick McHardy   ipv6: ip6mr: move...
832

7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
833
  	if (!spin_trylock(&mfc_unres_lock)) {
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
834
  		mod_timer(&mrt->ipmr_expire_timer, jiffies + 1);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
835
836
  		return;
  	}
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
837
838
  	if (!list_empty(&mrt->mfc6_unres_queue))
  		ipmr_do_expire_process(mrt);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
839
840
841
842
843
  
  	spin_unlock(&mfc_unres_lock);
  }
  
  /* Fill oifs list. It is called under write locked mrt_lock. */
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
844
  static void ip6mr_update_thresholds(struct mr6_table *mrt, struct mfc6_cache *cache,
b5aa30b19   Patrick McHardy   ipv6: ip6mr: remo...
845
  				    unsigned char *ttls)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
846
847
  {
  	int vifi;
6ac7eb086   Rami Rosen   [IPV6] MROUTE: Ad...
848
  	cache->mfc_un.res.minvif = MAXMIFS;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
849
  	cache->mfc_un.res.maxvif = 0;
6ac7eb086   Rami Rosen   [IPV6] MROUTE: Ad...
850
  	memset(cache->mfc_un.res.ttls, 255, MAXMIFS);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
851

6bd521433   Patrick McHardy   ipv6: ip6mr: move...
852
853
  	for (vifi = 0; vifi < mrt->maxvif; vifi++) {
  		if (MIF_EXISTS(mrt, vifi) &&
4e16880cb   Benjamin Thery   netns: ip6mr: dyn...
854
  		    ttls[vifi] && ttls[vifi] < 255) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
855
856
857
858
859
860
861
862
  			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;
  		}
  	}
  }
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
863
864
  static int mif6_add(struct net *net, struct mr6_table *mrt,
  		    struct mif6ctl *vifc, int mrtsock)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
865
866
  {
  	int vifi = vifc->mif6c_mifi;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
867
  	struct mif_device *v = &mrt->vif6_table[vifi];
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
868
  	struct net_device *dev;
1d6e55f19   Thomas Goff   IPv6: Fix multica...
869
  	struct inet6_dev *in6_dev;
5ae7b4441   Wang Chen   ipv6: Check retur...
870
  	int err;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
871
872
  
  	/* Is vif busy ? */
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
873
  	if (MIF_EXISTS(mrt, vifi))
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
874
875
876
  		return -EADDRINUSE;
  
  	switch (vifc->mif6c_flags) {
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
877
878
879
880
881
882
  #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...
883
  		if (mrt->mroute_reg_vif_num >= 0)
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
884
  			return -EADDRINUSE;
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
885
  		dev = ip6mr_reg_vif(net, mrt);
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
886
887
  		if (!dev)
  			return -ENOBUFS;
5ae7b4441   Wang Chen   ipv6: Check retur...
888
889
890
  		err = dev_set_allmulti(dev, 1);
  		if (err) {
  			unregister_netdevice(dev);
7af3db78a   Wang Chen   ipv6: Fix using a...
891
  			dev_put(dev);
5ae7b4441   Wang Chen   ipv6: Check retur...
892
893
  			return err;
  		}
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
894
895
  		break;
  #endif
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
896
  	case 0:
8229efdae   Benjamin Thery   netns: ip6mr: ena...
897
  		dev = dev_get_by_index(net, vifc->mif6c_pifi);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
898
899
  		if (!dev)
  			return -EADDRNOTAVAIL;
5ae7b4441   Wang Chen   ipv6: Check retur...
900
  		err = dev_set_allmulti(dev, 1);
7af3db78a   Wang Chen   ipv6: Fix using a...
901
902
  		if (err) {
  			dev_put(dev);
5ae7b4441   Wang Chen   ipv6: Check retur...
903
  			return err;
7af3db78a   Wang Chen   ipv6: Fix using a...
904
  		}
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
905
906
907
908
  		break;
  	default:
  		return -EINVAL;
  	}
1d6e55f19   Thomas Goff   IPv6: Fix multica...
909
910
911
  	in6_dev = __in6_dev_get(dev);
  	if (in6_dev)
  		in6_dev->cnf.mc_forwarding++;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
  	/*
  	 *	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)
  		v->link = dev->iflink;
  
  	/* And finish update writing critical data */
  	write_lock_bh(&mrt_lock);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
930
  	v->dev = dev;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
931
932
  #ifdef CONFIG_IPV6_PIMSM_V2
  	if (v->flags & MIFF_REGISTER)
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
933
  		mrt->mroute_reg_vif_num = vifi;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
934
  #endif
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
935
936
  	if (vifi + 1 > mrt->maxvif)
  		mrt->maxvif = vifi + 1;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
937
938
939
  	write_unlock_bh(&mrt_lock);
  	return 0;
  }
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
940
  static struct mfc6_cache *ip6mr_cache_find(struct mr6_table *mrt,
b71d1d426   Eric Dumazet   inet: constify ip...
941
942
  					   const struct in6_addr *origin,
  					   const struct in6_addr *mcastgrp)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
943
944
945
  {
  	int line = MFC6_HASH(mcastgrp, origin);
  	struct mfc6_cache *c;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
946
  	list_for_each_entry(c, &mrt->mfc6_cache_array[line], list) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
947
948
  		if (ipv6_addr_equal(&c->mf6c_origin, origin) &&
  		    ipv6_addr_equal(&c->mf6c_mcastgrp, mcastgrp))
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
949
  			return c;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
950
  	}
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
951
  	return NULL;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
952
953
954
955
956
  }
  
  /*
   *	Allocate a multicast cache entry
   */
b5aa30b19   Patrick McHardy   ipv6: ip6mr: remo...
957
  static struct mfc6_cache *ip6mr_cache_alloc(void)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
958
  {
36cbac590   Joe Perches   net/ipv6/ip6mr.c:...
959
  	struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
960
961
  	if (c == NULL)
  		return NULL;
6ac7eb086   Rami Rosen   [IPV6] MROUTE: Ad...
962
  	c->mfc_un.res.minvif = MAXMIFS;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
963
964
  	return c;
  }
b5aa30b19   Patrick McHardy   ipv6: ip6mr: remo...
965
  static struct mfc6_cache *ip6mr_cache_alloc_unres(void)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
966
  {
36cbac590   Joe Perches   net/ipv6/ip6mr.c:...
967
  	struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
968
969
  	if (c == NULL)
  		return NULL;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
970
971
972
973
974
975
976
977
  	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...
978
979
  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...
980
981
982
983
984
985
986
987
988
  {
  	struct sk_buff *skb;
  
  	/*
  	 *	Play the pending entries through our router
  	 */
  
  	while((skb = __skb_dequeue(&uc->mfc_un.unres.unresolved))) {
  		if (ipv6_hdr(skb)->version == 0) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
989
  			struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct ipv6hdr));
5b285cac3   Patrick McHardy   ipv6: ip6mr: add ...
990
  			if (__ip6mr_fill_mroute(mrt, skb, c, NLMSG_DATA(nlh)) > 0) {
549e028d0   YOSHIFUJI Hideaki   [IPV6] MROUTE: Us...
991
  				nlh->nlmsg_len = skb_tail_pointer(skb) - (u8 *)nlh;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
992
993
994
995
996
997
  			} else {
  				nlh->nlmsg_type = NLMSG_ERROR;
  				nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct nlmsgerr));
  				skb_trim(skb, nlh->nlmsg_len);
  				((struct nlmsgerr *)NLMSG_DATA(nlh))->error = -EMSGSIZE;
  			}
ddc3731fc   Hagen Paul Pfeifer   ipv6: ignore rtnl...
998
  			rtnl_unicast(skb, net, NETLINK_CB(skb).pid);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
999
  		} else
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1000
  			ip6_mr_forward(net, mrt, skb, c);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1001
1002
1003
1004
1005
1006
1007
1008
1009
  	}
  }
  
  /*
   *	Bounce a cache query up to pim6sd. We could use netlink for this but pim6sd
   *	expects the following bizarre scheme.
   *
   *	Called under mrt_lock.
   */
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1010
1011
  static int ip6mr_cache_report(struct mr6_table *mrt, struct sk_buff *pkt,
  			      mifi_t mifi, int assert)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1012
1013
1014
1015
  {
  	struct sk_buff *skb;
  	struct mrt6msg *msg;
  	int ret;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1016
1017
1018
1019
1020
1021
1022
  #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...
1023
1024
1025
1026
1027
1028
1029
1030
  
  	if (!skb)
  		return -ENOBUFS;
  
  	/* I suppose that internal messages
  	 * do not require checksums */
  
  	skb->ip_summed = CHECKSUM_UNNECESSARY;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
  #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...
1045
  		msg->im6_mif = mrt->mroute_reg_vif_num;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1046
  		msg->im6_pad = 0;
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
1047
1048
  		msg->im6_src = ipv6_hdr(pkt)->saddr;
  		msg->im6_dst = ipv6_hdr(pkt)->daddr;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1049
1050
1051
1052
1053
  
  		skb->ip_summed = CHECKSUM_UNNECESSARY;
  	} else
  #endif
  	{
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
  	/*
  	 *	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...
1071
  	msg->im6_mif = mifi;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1072
  	msg->im6_pad = 0;
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
1073
1074
  	msg->im6_src = ipv6_hdr(pkt)->saddr;
  	msg->im6_dst = ipv6_hdr(pkt)->daddr;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1075

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

6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1080
  	if (mrt->mroute6_sk == NULL) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1081
1082
1083
1084
1085
1086
1087
  		kfree_skb(skb);
  		return -EINVAL;
  	}
  
  	/*
  	 *	Deliver to user space multicast routing algorithms
  	 */
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1088
  	ret = sock_queue_rcv_skb(mrt->mroute6_sk, skb);
bd91b8bf3   Benjamin Thery   netns: ip6mr: all...
1089
  	if (ret < 0) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
  		if (net_ratelimit())
  			printk(KERN_WARNING "mroute6: pending queue full, dropping entries.
  ");
  		kfree_skb(skb);
  	}
  
  	return ret;
  }
  
  /*
   *	Queue a packet for resolution. It gets locked cache entry!
   */
  
  static int
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1104
  ip6mr_cache_unresolved(struct mr6_table *mrt, mifi_t mifi, struct sk_buff *skb)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1105
  {
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1106
  	bool found = false;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1107
1108
1109
1110
  	int err;
  	struct mfc6_cache *c;
  
  	spin_lock_bh(&mfc_unres_lock);
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1111
  	list_for_each_entry(c, &mrt->mfc6_unres_queue, list) {
c476efbcd   Patrick McHardy   ipv6: ip6mr: move...
1112
  		if (ipv6_addr_equal(&c->mf6c_mcastgrp, &ipv6_hdr(skb)->daddr) &&
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1113
1114
  		    ipv6_addr_equal(&c->mf6c_origin, &ipv6_hdr(skb)->saddr)) {
  			found = true;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1115
  			break;
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1116
  		}
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1117
  	}
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1118
  	if (!found) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1119
1120
1121
  		/*
  		 *	Create a new entry if allowable
  		 */
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1122
  		if (atomic_read(&mrt->cache_resolve_queue_len) >= 10 ||
b5aa30b19   Patrick McHardy   ipv6: ip6mr: remo...
1123
  		    (c = ip6mr_cache_alloc_unres()) == NULL) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
  			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...
1140
  		err = ip6mr_cache_report(mrt, skb, mifi, MRT6MSG_NOCACHE);
8229efdae   Benjamin Thery   netns: ip6mr: ena...
1141
  		if (err < 0) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1142
1143
1144
1145
  			/* If the report failed throw the cache entry
  			   out - Brad Parker
  			 */
  			spin_unlock_bh(&mfc_unres_lock);
58701ad41   Benjamin Thery   netns: ip6mr: sto...
1146
  			ip6mr_cache_free(c);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1147
1148
1149
  			kfree_skb(skb);
  			return err;
  		}
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1150
1151
  		atomic_inc(&mrt->cache_resolve_queue_len);
  		list_add(&c->list, &mrt->mfc6_unres_queue);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1152

6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1153
  		ipmr_do_expire_process(mrt);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
  	}
  
  	/*
  	 *	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
   */
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1174
  static int ip6mr_mfc_delete(struct mr6_table *mrt, struct mf6cctl *mfc)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1175
1176
  {
  	int line;
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1177
  	struct mfc6_cache *c, *next;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1178
1179
  
  	line = MFC6_HASH(&mfc->mf6cc_mcastgrp.sin6_addr, &mfc->mf6cc_origin.sin6_addr);
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1180
  	list_for_each_entry_safe(c, next, &mrt->mfc6_cache_array[line], list) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1181
1182
1183
  		if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) &&
  		    ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr)) {
  			write_lock_bh(&mrt_lock);
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1184
  			list_del(&c->list);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1185
  			write_unlock_bh(&mrt_lock);
58701ad41   Benjamin Thery   netns: ip6mr: sto...
1186
  			ip6mr_cache_free(c);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
  			return 0;
  		}
  	}
  	return -ENOENT;
  }
  
  static int ip6mr_device_event(struct notifier_block *this,
  			      unsigned long event, void *ptr)
  {
  	struct net_device *dev = ptr;
8229efdae   Benjamin Thery   netns: ip6mr: ena...
1197
  	struct net *net = dev_net(dev);
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1198
  	struct mr6_table *mrt;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1199
1200
  	struct mif_device *v;
  	int ct;
c871e664e   Eric Dumazet   ip6mr: Optimize m...
1201
  	LIST_HEAD(list);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1202

7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1203
1204
  	if (event != NETDEV_UNREGISTER)
  		return NOTIFY_DONE;
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1205
1206
1207
1208
1209
1210
  	ip6mr_for_each_table(mrt, net) {
  		v = &mrt->vif6_table[0];
  		for (ct = 0; ct < mrt->maxvif; ct++, v++) {
  			if (v->dev == dev)
  				mif6_delete(mrt, ct, &list);
  		}
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1211
  	}
c871e664e   Eric Dumazet   ip6mr: Optimize m...
1212
  	unregister_netdevice_many(&list);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
  	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...
1223
1224
  static int __net_init ip6mr_net_init(struct net *net)
  {
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1225
  	int err;
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1226

d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1227
1228
  	err = ip6mr_rules_init(net);
  	if (err < 0)
4e16880cb   Benjamin Thery   netns: ip6mr: dyn...
1229
  		goto fail;
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
1230
1231
1232
1233
1234
1235
1236
1237
  
  #ifdef CONFIG_PROC_FS
  	err = -ENOMEM;
  	if (!proc_net_fops_create(net, "ip6_mr_vif", 0, &ip6mr_vif_fops))
  		goto proc_vif_fail;
  	if (!proc_net_fops_create(net, "ip6_mr_cache", 0, &ip6mr_mfc_fops))
  		goto proc_cache_fail;
  #endif
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1238

4a6258a0e   Benjamin Thery   netns: ip6mr: dyn...
1239
  	return 0;
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
1240
1241
1242
1243
  #ifdef CONFIG_PROC_FS
  proc_cache_fail:
  	proc_net_remove(net, "ip6_mr_vif");
  proc_vif_fail:
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1244
  	ip6mr_rules_exit(net);
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
1245
  #endif
4e16880cb   Benjamin Thery   netns: ip6mr: dyn...
1246
1247
1248
1249
1250
1251
  fail:
  	return err;
  }
  
  static void __net_exit ip6mr_net_exit(struct net *net)
  {
8b90fc7e5   Benjamin Thery   netns: ip6mr: dec...
1252
1253
1254
1255
  #ifdef CONFIG_PROC_FS
  	proc_net_remove(net, "ip6_mr_cache");
  	proc_net_remove(net, "ip6_mr_vif");
  #endif
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1256
  	ip6mr_rules_exit(net);
4e16880cb   Benjamin Thery   netns: ip6mr: dyn...
1257
1258
1259
1260
1261
1262
  }
  
  static struct pernet_operations ip6mr_net_ops = {
  	.init = ip6mr_net_init,
  	.exit = ip6mr_net_exit,
  };
623d1a1af   Wang Chen   ipv6: Do cleanup ...
1263
  int __init ip6_mr_init(void)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1264
  {
623d1a1af   Wang Chen   ipv6: Do cleanup ...
1265
  	int err;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1266
1267
1268
1269
1270
  	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 ...
1271
  		return -ENOMEM;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1272

4e16880cb   Benjamin Thery   netns: ip6mr: dyn...
1273
1274
1275
  	err = register_pernet_subsys(&ip6mr_net_ops);
  	if (err)
  		goto reg_pernet_fail;
623d1a1af   Wang Chen   ipv6: Do cleanup ...
1276
1277
1278
  	err = register_netdevice_notifier(&ip6_mr_notifier);
  	if (err)
  		goto reg_notif_fail;
403dbb97f   Tom Goff   PIM-SM: namespace...
1279
1280
1281
1282
1283
1284
1285
1286
  #ifdef CONFIG_IPV6_PIMSM_V2
  	if (inet6_add_protocol(&pim6_protocol, IPPROTO_PIM) < 0) {
  		printk(KERN_ERR "ip6_mr_init: can't add PIM protocol
  ");
  		err = -EAGAIN;
  		goto add_proto_fail;
  	}
  #endif
c7ac8679b   Greg Rose   rtnetlink: Comput...
1287
1288
  	rtnl_register(RTNL_FAMILY_IP6MR, RTM_GETROUTE, NULL,
  		      ip6mr_rtm_dumproute, NULL);
623d1a1af   Wang Chen   ipv6: Do cleanup ...
1289
  	return 0;
403dbb97f   Tom Goff   PIM-SM: namespace...
1290
1291
1292
1293
  #ifdef CONFIG_IPV6_PIMSM_V2
  add_proto_fail:
  	unregister_netdevice_notifier(&ip6_mr_notifier);
  #endif
87b30a653   Benjamin Thery   ipv6: fix ip6_mr_...
1294
  reg_notif_fail:
4e16880cb   Benjamin Thery   netns: ip6mr: dyn...
1295
1296
  	unregister_pernet_subsys(&ip6mr_net_ops);
  reg_pernet_fail:
87b30a653   Benjamin Thery   ipv6: fix ip6_mr_...
1297
  	kmem_cache_destroy(mrt_cachep);
623d1a1af   Wang Chen   ipv6: Do cleanup ...
1298
  	return err;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1299
  }
623d1a1af   Wang Chen   ipv6: Do cleanup ...
1300
1301
  void ip6_mr_cleanup(void)
  {
623d1a1af   Wang Chen   ipv6: Do cleanup ...
1302
  	unregister_netdevice_notifier(&ip6_mr_notifier);
4e16880cb   Benjamin Thery   netns: ip6mr: dyn...
1303
  	unregister_pernet_subsys(&ip6mr_net_ops);
623d1a1af   Wang Chen   ipv6: Do cleanup ...
1304
1305
  	kmem_cache_destroy(mrt_cachep);
  }
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1306

6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1307
1308
  static int ip6mr_mfc_add(struct net *net, struct mr6_table *mrt,
  			 struct mf6cctl *mfc, int mrtsock)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1309
  {
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1310
  	bool found = false;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1311
  	int line;
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1312
  	struct mfc6_cache *uc, *c;
6ac7eb086   Rami Rosen   [IPV6] MROUTE: Ad...
1313
  	unsigned char ttls[MAXMIFS];
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1314
  	int i;
a50436f2c   Patrick McHardy   net: ipmr/ip6mr: ...
1315
1316
  	if (mfc->mf6cc_parent >= MAXMIFS)
  		return -ENFILE;
6ac7eb086   Rami Rosen   [IPV6] MROUTE: Ad...
1317
1318
  	memset(ttls, 255, MAXMIFS);
  	for (i = 0; i < MAXMIFS; i++) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1319
1320
1321
1322
1323
1324
  		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...
1325
  	list_for_each_entry(c, &mrt->mfc6_cache_array[line], list) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1326
  		if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) &&
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1327
1328
  		    ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr)) {
  			found = true;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1329
  			break;
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1330
  		}
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1331
  	}
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1332
  	if (found) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1333
1334
  		write_lock_bh(&mrt_lock);
  		c->mf6c_parent = mfc->mf6cc_parent;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1335
  		ip6mr_update_thresholds(mrt, c, ttls);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1336
1337
1338
1339
1340
1341
1342
1343
  		if (!mrtsock)
  			c->mfc_flags |= MFC_STATIC;
  		write_unlock_bh(&mrt_lock);
  		return 0;
  	}
  
  	if (!ipv6_addr_is_multicast(&mfc->mf6cc_mcastgrp.sin6_addr))
  		return -EINVAL;
b5aa30b19   Patrick McHardy   ipv6: ip6mr: remo...
1344
  	c = ip6mr_cache_alloc();
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1345
1346
1347
1348
1349
1350
  	if (c == NULL)
  		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...
1351
  	ip6mr_update_thresholds(mrt, c, ttls);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1352
1353
1354
1355
  	if (!mrtsock)
  		c->mfc_flags |= MFC_STATIC;
  
  	write_lock_bh(&mrt_lock);
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1356
  	list_add(&c->list, &mrt->mfc6_cache_array[line]);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1357
1358
1359
1360
1361
1362
  	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...
1363
  	found = false;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1364
  	spin_lock_bh(&mfc_unres_lock);
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1365
  	list_for_each_entry(uc, &mrt->mfc6_unres_queue, list) {
c476efbcd   Patrick McHardy   ipv6: ip6mr: move...
1366
  		if (ipv6_addr_equal(&uc->mf6c_origin, &c->mf6c_origin) &&
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1367
  		    ipv6_addr_equal(&uc->mf6c_mcastgrp, &c->mf6c_mcastgrp)) {
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1368
  			list_del(&uc->list);
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1369
  			atomic_dec(&mrt->cache_resolve_queue_len);
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1370
  			found = true;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1371
1372
1373
  			break;
  		}
  	}
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1374
1375
  	if (list_empty(&mrt->mfc6_unres_queue))
  		del_timer(&mrt->ipmr_expire_timer);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1376
  	spin_unlock_bh(&mfc_unres_lock);
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1377
  	if (found) {
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1378
  		ip6mr_cache_resolve(net, mrt, uc, c);
58701ad41   Benjamin Thery   netns: ip6mr: sto...
1379
  		ip6mr_cache_free(uc);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1380
1381
1382
1383
1384
1385
1386
  	}
  	return 0;
  }
  
  /*
   *	Close the multicast socket, and clear the vif tables etc
   */
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1387
  static void mroute_clean_tables(struct mr6_table *mrt)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1388
1389
  {
  	int i;
c871e664e   Eric Dumazet   ip6mr: Optimize m...
1390
  	LIST_HEAD(list);
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1391
  	struct mfc6_cache *c, *next;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1392
1393
1394
1395
  
  	/*
  	 *	Shut down all active vif entries
  	 */
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1396
1397
1398
  	for (i = 0; i < mrt->maxvif; i++) {
  		if (!(mrt->vif6_table[i].flags & VIFF_STATIC))
  			mif6_delete(mrt, i, &list);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1399
  	}
c871e664e   Eric Dumazet   ip6mr: Optimize m...
1400
  	unregister_netdevice_many(&list);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1401
1402
1403
1404
  
  	/*
  	 *	Wipe the cache
  	 */
4a6258a0e   Benjamin Thery   netns: ip6mr: dyn...
1405
  	for (i = 0; i < MFC6_LINES; i++) {
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1406
  		list_for_each_entry_safe(c, next, &mrt->mfc6_cache_array[i], list) {
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1407
  			if (c->mfc_flags & MFC_STATIC)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1408
  				continue;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1409
  			write_lock_bh(&mrt_lock);
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1410
  			list_del(&c->list);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1411
  			write_unlock_bh(&mrt_lock);
58701ad41   Benjamin Thery   netns: ip6mr: sto...
1412
  			ip6mr_cache_free(c);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1413
1414
  		}
  	}
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1415
  	if (atomic_read(&mrt->cache_resolve_queue_len) != 0) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1416
  		spin_lock_bh(&mfc_unres_lock);
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1417
  		list_for_each_entry_safe(c, next, &mrt->mfc6_unres_queue, list) {
f30a77842   Patrick McHardy   ipv6: ip6mr: conv...
1418
  			list_del(&c->list);
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1419
  			ip6mr_destroy_unres(mrt, c);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1420
1421
1422
1423
  		}
  		spin_unlock_bh(&mfc_unres_lock);
  	}
  }
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1424
  static int ip6mr_sk_init(struct mr6_table *mrt, struct sock *sk)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1425
1426
  {
  	int err = 0;
8229efdae   Benjamin Thery   netns: ip6mr: ena...
1427
  	struct net *net = sock_net(sk);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1428
1429
1430
  
  	rtnl_lock();
  	write_lock_bh(&mrt_lock);
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1431
1432
  	if (likely(mrt->mroute6_sk == NULL)) {
  		mrt->mroute6_sk = sk;
1d6e55f19   Thomas Goff   IPv6: Fix multica...
1433
1434
  		net->ipv6.devconf_all->mc_forwarding++;
  	}
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
  	else
  		err = -EADDRINUSE;
  	write_unlock_bh(&mrt_lock);
  
  	rtnl_unlock();
  
  	return err;
  }
  
  int ip6mr_sk_done(struct sock *sk)
  {
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1446
  	int err = -EACCES;
8229efdae   Benjamin Thery   netns: ip6mr: ena...
1447
  	struct net *net = sock_net(sk);
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1448
  	struct mr6_table *mrt;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1449
1450
  
  	rtnl_lock();
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1451
1452
1453
1454
1455
1456
  	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--;
  			write_unlock_bh(&mrt_lock);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1457

d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1458
1459
1460
1461
1462
  			mroute_clean_tables(mrt);
  			err = 0;
  			break;
  		}
  	}
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1463
1464
1465
1466
  	rtnl_unlock();
  
  	return err;
  }
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1467
  struct sock *mroute6_socket(struct net *net, struct sk_buff *skb)
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1468
  {
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1469
  	struct mr6_table *mrt;
4c9483b2f   David S. Miller   ipv6: Convert to ...
1470
1471
1472
1473
  	struct flowi6 fl6 = {
  		.flowi6_iif	= skb->skb_iif,
  		.flowi6_oif	= skb->dev->ifindex,
  		.flowi6_mark	= skb->mark,
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1474
  	};
4c9483b2f   David S. Miller   ipv6: Convert to ...
1475
  	if (ip6mr_fib_lookup(net, &fl6, &mrt) < 0)
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1476
  		return NULL;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1477
1478
1479
  
  	return mrt->mroute6_sk;
  }
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1480
1481
1482
1483
1484
1485
  /*
   *	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...
1486
  int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsigned int optlen)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1487
1488
1489
1490
1491
  {
  	int ret;
  	struct mif6ctl vif;
  	struct mf6cctl mfc;
  	mifi_t mifi;
8229efdae   Benjamin Thery   netns: ip6mr: ena...
1492
  	struct net *net = sock_net(sk);
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1493
1494
1495
1496
1497
  	struct mr6_table *mrt;
  
  	mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
  	if (mrt == NULL)
  		return -ENOENT;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1498
1499
  
  	if (optname != MRT6_INIT) {
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1500
  		if (sk != mrt->mroute6_sk && !capable(CAP_NET_ADMIN))
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1501
1502
1503
1504
1505
1506
  			return -EACCES;
  	}
  
  	switch (optname) {
  	case MRT6_INIT:
  		if (sk->sk_type != SOCK_RAW ||
c720c7e83   Eric Dumazet   inet: rename some...
1507
  		    inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1508
1509
1510
  			return -EOPNOTSUPP;
  		if (optlen < sizeof(int))
  			return -EINVAL;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1511
  		return ip6mr_sk_init(mrt, sk);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1512
1513
1514
1515
1516
1517
1518
1519
1520
  
  	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...
1521
  		if (vif.mif6c_mifi >= MAXMIFS)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1522
1523
  			return -ENFILE;
  		rtnl_lock();
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1524
  		ret = mif6_add(net, mrt, &vif, sk == mrt->mroute6_sk);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1525
1526
1527
1528
1529
1530
1531
1532
1533
  		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();
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1534
  		ret = mif6_delete(mrt, mifi, NULL);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
  		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:
  		if (optlen < sizeof(mfc))
  			return -EINVAL;
  		if (copy_from_user(&mfc, optval, sizeof(mfc)))
  			return -EFAULT;
  		rtnl_lock();
  		if (optname == MRT6_DEL_MFC)
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1550
  			ret = ip6mr_mfc_delete(mrt, &mfc);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1551
  		else
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1552
  			ret = ip6mr_mfc_add(net, mrt, &mfc, sk == mrt->mroute6_sk);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1553
1554
1555
1556
  		rtnl_unlock();
  		return ret;
  
  	/*
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1557
1558
1559
1560
1561
1562
1563
  	 *	Control PIM assert (to activate pim will activate assert)
  	 */
  	case MRT6_ASSERT:
  	{
  		int v;
  		if (get_user(v, (int __user *)optval))
  			return -EFAULT;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1564
  		mrt->mroute_do_assert = !!v;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1565
1566
1567
1568
1569
1570
  		return 0;
  	}
  
  #ifdef CONFIG_IPV6_PIMSM_V2
  	case MRT6_PIM:
  	{
a9f83bf38   YOSHIFUJI Hideaki   [IPV6]: Sparse: R...
1571
  		int v;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1572
1573
1574
1575
1576
  		if (get_user(v, (int __user *)optval))
  			return -EFAULT;
  		v = !!v;
  		rtnl_lock();
  		ret = 0;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1577
1578
1579
  		if (v != mrt->mroute_do_pim) {
  			mrt->mroute_do_pim = v;
  			mrt->mroute_do_assert = v;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1580
1581
1582
1583
1584
1585
  		}
  		rtnl_unlock();
  		return ret;
  	}
  
  #endif
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
  #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;
  		if (sk == mrt->mroute6_sk)
  			return -EBUSY;
  
  		rtnl_lock();
  		ret = 0;
  		if (!ip6mr_new_table(net, v))
  			ret = -ENOMEM;
  		raw6_sk(sk)->ip6mr_table = v;
  		rtnl_unlock();
  		return ret;
  	}
  #endif
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1607
  	/*
7d120c55d   Rami Rosen   ipv6 mroute: Use ...
1608
  	 *	Spurious command, or MRT6_VERSION which you cannot
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
  	 *	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...
1625
  	struct net *net = sock_net(sk);
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1626
1627
1628
1629
1630
  	struct mr6_table *mrt;
  
  	mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
  	if (mrt == NULL)
  		return -ENOENT;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1631
1632
1633
1634
1635
  
  	switch (optname) {
  	case MRT6_VERSION:
  		val = 0x0305;
  		break;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1636
1637
  #ifdef CONFIG_IPV6_PIMSM_V2
  	case MRT6_PIM:
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1638
  		val = mrt->mroute_do_pim;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1639
1640
1641
  		break;
  #endif
  	case MRT6_ASSERT:
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1642
  		val = mrt->mroute_do_assert;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1643
  		break;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
  	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...
1672
  	struct net *net = sock_net(sk);
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1673
1674
1675
1676
1677
  	struct mr6_table *mrt;
  
  	mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
  	if (mrt == NULL)
  		return -ENOENT;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1678
1679
1680
1681
1682
  
  	switch (cmd) {
  	case SIOCGETMIFCNT_IN6:
  		if (copy_from_user(&vr, arg, sizeof(vr)))
  			return -EFAULT;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1683
  		if (vr.mifi >= mrt->maxvif)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1684
1685
  			return -EINVAL;
  		read_lock(&mrt_lock);
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1686
1687
  		vif = &mrt->vif6_table[vr.mifi];
  		if (MIF_EXISTS(mrt, vr.mifi)) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
  			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...
1705
  		c = ip6mr_cache_find(mrt, &sr.src.sin6_addr, &sr.grp.sin6_addr);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
  		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...
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
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
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
  #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);
  	if (mrt == NULL)
  		return -ENOENT;
  
  	switch (cmd) {
  	case SIOCGETMIFCNT_IN6:
  		if (copy_from_user(&vr, arg, sizeof(vr)))
  			return -EFAULT;
  		if (vr.mifi >= mrt->maxvif)
  			return -EINVAL;
  		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...
1796
1797
1798
  
  static inline int ip6mr_forward2_finish(struct sk_buff *skb)
  {
adf30907d   Eric Dumazet   net: skb->dst acc...
1799
  	IP6_INC_STATS_BH(dev_net(skb_dst(skb)->dev), ip6_dst_idev(skb_dst(skb)),
483a47d2f   Denis V. Lunev   ipv6: added net a...
1800
  			 IPSTATS_MIB_OUTFORWDATAGRAMS);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1801
1802
1803
1804
1805
1806
  	return dst_output(skb);
  }
  
  /*
   *	Processing handlers for ip6mr_forward
   */
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1807
1808
  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...
1809
1810
  {
  	struct ipv6hdr *ipv6h;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1811
  	struct mif_device *vif = &mrt->vif6_table[vifi];
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1812
1813
  	struct net_device *dev;
  	struct dst_entry *dst;
4c9483b2f   David S. Miller   ipv6: Convert to ...
1814
  	struct flowi6 fl6;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1815
1816
1817
  
  	if (vif->dev == NULL)
  		goto out_free;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1818
1819
1820
1821
  #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...
1822
1823
  		vif->dev->stats.tx_bytes += skb->len;
  		vif->dev->stats.tx_packets++;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1824
  		ip6mr_cache_report(mrt, skb, vifi, MRT6MSG_WHOLEPKT);
8da73b73e   Ilpo Järvinen   ip6mr: use goto t...
1825
  		goto out_free;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1826
1827
  	}
  #endif
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1828
  	ipv6h = ipv6_hdr(skb);
4c9483b2f   David S. Miller   ipv6: Convert to ...
1829
1830
1831
  	fl6 = (struct flowi6) {
  		.flowi6_oif = vif->link,
  		.daddr = ipv6h->daddr,
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1832
  	};
4c9483b2f   David S. Miller   ipv6: Convert to ...
1833
  	dst = ip6_route_output(net, NULL, &fl6);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1834
1835
  	if (!dst)
  		goto out_free;
adf30907d   Eric Dumazet   net: skb->dst acc...
1836
1837
  	skb_dst_drop(skb);
  	skb_dst_set(skb, dst);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
  
  	/*
  	 * 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;
b2e0b385d   Jan Engelhardt   netfilter: ipv6: ...
1864
  	return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD, skb, skb->dev, dev,
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1865
1866
1867
1868
1869
1870
  		       ip6mr_forward2_finish);
  
  out_free:
  	kfree_skb(skb);
  	return 0;
  }
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1871
  static int ip6mr_find_vif(struct mr6_table *mrt, struct net_device *dev)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1872
1873
  {
  	int ct;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1874
1875
1876
  
  	for (ct = mrt->maxvif - 1; ct >= 0; ct--) {
  		if (mrt->vif6_table[ct].dev == dev)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1877
1878
1879
1880
  			break;
  	}
  	return ct;
  }
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1881
1882
  static int ip6_mr_forward(struct net *net, struct mr6_table *mrt,
  			  struct sk_buff *skb, struct mfc6_cache *cache)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1883
1884
1885
1886
1887
1888
1889
  {
  	int psend = -1;
  	int vif, ct;
  
  	vif = cache->mf6c_parent;
  	cache->mfc_un.res.pkt++;
  	cache->mfc_un.res.bytes += skb->len;
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1890
1891
1892
  	/*
  	 * Wrong interface: drop packet and (maybe) send PIM assert.
  	 */
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1893
  	if (mrt->vif6_table[vif].dev != skb->dev) {
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1894
1895
1896
  		int true_vifi;
  
  		cache->mfc_un.res.wrong_if++;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1897
  		true_vifi = ip6mr_find_vif(mrt, skb->dev);
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1898

6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1899
  		if (true_vifi >= 0 && mrt->mroute_do_assert &&
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1900
1901
1902
1903
1904
  		    /* 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...
1905
  		    (mrt->mroute_do_pim ||
a21f3f997   Benjamin Thery   netns: ip6mr: dec...
1906
  		     cache->mfc_un.res.ttls[true_vifi] < 255) &&
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1907
1908
1909
  		    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...
1910
  			ip6mr_cache_report(mrt, skb, true_vifi, MRT6MSG_WRONGMIF);
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1911
1912
1913
  		}
  		goto dont_forward;
  	}
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1914
1915
  	mrt->vif6_table[vif].pkt_in++;
  	mrt->vif6_table[vif].bytes_in += skb->len;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1916
1917
1918
1919
1920
1921
1922
1923
1924
  
  	/*
  	 *	Forward the frame
  	 */
  	for (ct = cache->mfc_un.res.maxvif - 1; ct >= cache->mfc_un.res.minvif; ct--) {
  		if (ipv6_hdr(skb)->hop_limit > cache->mfc_un.res.ttls[ct]) {
  			if (psend != -1) {
  				struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
  				if (skb2)
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1925
  					ip6mr_forward2(net, mrt, skb2, cache, psend);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1926
1927
1928
1929
1930
  			}
  			psend = ct;
  		}
  	}
  	if (psend != -1) {
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1931
  		ip6mr_forward2(net, mrt, skb, cache, psend);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1932
1933
  		return 0;
  	}
14fb64e1f   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1934
  dont_forward:
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
  	kfree_skb(skb);
  	return 0;
  }
  
  
  /*
   *	Multicast packets for forwarding arrive here
   */
  
  int ip6_mr_input(struct sk_buff *skb)
  {
  	struct mfc6_cache *cache;
8229efdae   Benjamin Thery   netns: ip6mr: ena...
1947
  	struct net *net = dev_net(skb->dev);
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1948
  	struct mr6_table *mrt;
4c9483b2f   David S. Miller   ipv6: Convert to ...
1949
1950
1951
  	struct flowi6 fl6 = {
  		.flowi6_iif	= skb->dev->ifindex,
  		.flowi6_mark	= skb->mark,
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1952
1953
  	};
  	int err;
4c9483b2f   David S. Miller   ipv6: Convert to ...
1954
  	err = ip6mr_fib_lookup(net, &fl6, &mrt);
2015de5fe   Ben Greear   ipv6-multicast: F...
1955
1956
  	if (err < 0) {
  		kfree_skb(skb);
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
1957
  		return err;
2015de5fe   Ben Greear   ipv6-multicast: F...
1958
  	}
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1959
1960
  
  	read_lock(&mrt_lock);
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1961
  	cache = ip6mr_cache_find(mrt,
8229efdae   Benjamin Thery   netns: ip6mr: ena...
1962
  				 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1963
1964
1965
1966
1967
1968
  
  	/*
  	 *	No usable cache entry
  	 */
  	if (cache == NULL) {
  		int vif;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1969
  		vif = ip6mr_find_vif(mrt, skb->dev);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1970
  		if (vif >= 0) {
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1971
  			int err = ip6mr_cache_unresolved(mrt, vif, skb);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1972
1973
1974
1975
1976
1977
1978
1979
  			read_unlock(&mrt_lock);
  
  			return err;
  		}
  		read_unlock(&mrt_lock);
  		kfree_skb(skb);
  		return -ENODEV;
  	}
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1980
  	ip6_mr_forward(net, mrt, skb, cache);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1981
1982
1983
1984
1985
  
  	read_unlock(&mrt_lock);
  
  	return 0;
  }
5b285cac3   Patrick McHardy   ipv6: ip6mr: add ...
1986
1987
  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...
1988
1989
1990
  {
  	int ct;
  	struct rtnexthop *nhp;
549e028d0   YOSHIFUJI Hideaki   [IPV6] MROUTE: Us...
1991
  	u8 *b = skb_tail_pointer(skb);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1992
  	struct rtattr *mp_head;
7438189ba   Nicolas Dichtel   net: ipmr/ip6mr: ...
1993
  	/* If cache is unresolved, don't try to parse IIF and OIF */
ed0f160ad   Dan Carpenter   ipmr: off by one ...
1994
  	if (c->mf6c_parent >= MAXMIFS)
7438189ba   Nicolas Dichtel   net: ipmr/ip6mr: ...
1995
  		return -ENOENT;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
1996
1997
  	if (MIF_EXISTS(mrt, c->mf6c_parent))
  		RTA_PUT(skb, RTA_IIF, 4, &mrt->vif6_table[c->mf6c_parent].dev->ifindex);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
1998
1999
2000
2001
  
  	mp_head = (struct rtattr *)skb_put(skb, RTA_LENGTH(0));
  
  	for (ct = c->mfc_un.res.minvif; ct < c->mfc_un.res.maxvif; ct++) {
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
2002
  		if (MIF_EXISTS(mrt, ct) && c->mfc_un.res.ttls[ct] < 255) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2003
2004
2005
2006
2007
  			if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4))
  				goto rtattr_failure;
  			nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp)));
  			nhp->rtnh_flags = 0;
  			nhp->rtnh_hops = c->mfc_un.res.ttls[ct];
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
2008
  			nhp->rtnh_ifindex = mrt->vif6_table[ct].dev->ifindex;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2009
2010
2011
2012
  			nhp->rtnh_len = sizeof(*nhp);
  		}
  	}
  	mp_head->rta_type = RTA_MULTIPATH;
549e028d0   YOSHIFUJI Hideaki   [IPV6] MROUTE: Us...
2013
  	mp_head->rta_len = skb_tail_pointer(skb) - (u8 *)mp_head;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2014
2015
2016
2017
2018
2019
2020
  	rtm->rtm_type = RTN_MULTICAST;
  	return 1;
  
  rtattr_failure:
  	nlmsg_trim(skb, b);
  	return -EMSGSIZE;
  }
8229efdae   Benjamin Thery   netns: ip6mr: ena...
2021
2022
  int ip6mr_get_route(struct net *net,
  		    struct sk_buff *skb, struct rtmsg *rtm, int nowait)
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2023
2024
  {
  	int err;
d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
2025
  	struct mr6_table *mrt;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2026
  	struct mfc6_cache *cache;
adf30907d   Eric Dumazet   net: skb->dst acc...
2027
  	struct rt6_info *rt = (struct rt6_info *)skb_dst(skb);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2028

d1db275dd   Patrick McHardy   ipv6: ip6mr: supp...
2029
2030
2031
  	mrt = ip6mr_get_table(net, RT6_TABLE_DFLT);
  	if (mrt == NULL)
  		return -ENOENT;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2032
  	read_lock(&mrt_lock);
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
2033
  	cache = ip6mr_cache_find(mrt, &rt->rt6i_src.addr, &rt->rt6i_dst.addr);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
  
  	if (!cache) {
  		struct sk_buff *skb2;
  		struct ipv6hdr *iph;
  		struct net_device *dev;
  		int vif;
  
  		if (nowait) {
  			read_unlock(&mrt_lock);
  			return -EAGAIN;
  		}
  
  		dev = skb->dev;
6bd521433   Patrick McHardy   ipv6: ip6mr: move...
2047
  		if (dev == NULL || (vif = ip6mr_find_vif(mrt, dev)) < 0) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
  			read_unlock(&mrt_lock);
  			return -ENODEV;
  		}
  
  		/* really correct? */
  		skb2 = alloc_skb(sizeof(struct ipv6hdr), GFP_ATOMIC);
  		if (!skb2) {
  			read_unlock(&mrt_lock);
  			return -ENOMEM;
  		}
  
  		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_...
2073
2074
  		iph->saddr = rt->rt6i_src.addr;
  		iph->daddr = rt->rt6i_dst.addr;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2075

6bd521433   Patrick McHardy   ipv6: ip6mr: move...
2076
  		err = ip6mr_cache_unresolved(mrt, vif, skb2);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2077
2078
2079
2080
2081
2082
2083
  		read_unlock(&mrt_lock);
  
  		return err;
  	}
  
  	if (!nowait && (rtm->rtm_flags&RTM_F_NOTIFY))
  		cache->mfc_flags |= MFC_NOTIFY;
5b285cac3   Patrick McHardy   ipv6: ip6mr: add ...
2084
  	err = __ip6mr_fill_mroute(mrt, skb, cache, rtm);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
2085
2086
2087
  	read_unlock(&mrt_lock);
  	return err;
  }
5b285cac3   Patrick McHardy   ipv6: ip6mr: add ...
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
  static int ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb,
  			     u32 pid, u32 seq, struct mfc6_cache *c)
  {
  	struct nlmsghdr *nlh;
  	struct rtmsg *rtm;
  
  	nlh = nlmsg_put(skb, pid, seq, RTM_NEWROUTE, sizeof(*rtm), NLM_F_MULTI);
  	if (nlh == NULL)
  		return -EMSGSIZE;
  
  	rtm = nlmsg_data(nlh);
  	rtm->rtm_family   = RTNL_FAMILY_IPMR;
  	rtm->rtm_dst_len  = 128;
  	rtm->rtm_src_len  = 128;
  	rtm->rtm_tos      = 0;
  	rtm->rtm_table    = mrt->id;
  	NLA_PUT_U32(skb, RTA_TABLE, mrt->id);
  	rtm->rtm_scope    = RT_SCOPE_UNIVERSE;
  	rtm->rtm_protocol = RTPROT_UNSPEC;
  	rtm->rtm_flags    = 0;
  
  	NLA_PUT(skb, RTA_SRC, 16, &c->mf6c_origin);
  	NLA_PUT(skb, RTA_DST, 16, &c->mf6c_mcastgrp);
  
  	if (__ip6mr_fill_mroute(mrt, skb, c, rtm) < 0)
  		goto nla_put_failure;
  
  	return nlmsg_end(skb, nlh);
  
  nla_put_failure:
  	nlmsg_cancel(skb, nlh);
  	return -EMSGSIZE;
  }
  
  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,
  						      NETLINK_CB(cb->skb).pid,
  						      cb->nlh->nlmsg_seq,
  						      mfc) < 0)
  					goto done;
  next_entry:
  				e++;
  			}
  			e = s_e = 0;
  		}
  		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;
  }