blob: 7345bd6c4b7dda39c0d73d542e9ca9a5366542ff [file] [log] [blame]
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001/*
2 * Linux IPv6 multicast routing support for BSD pim6sd
3 * Based on net/ipv4/ipmr.c.
4 *
5 * (c) 2004 Mickael Hoerdt, <hoerdt@clarinet.u-strasbg.fr>
6 * LSIIT Laboratory, Strasbourg, France
7 * (c) 2004 Jean-Philippe Andriot, <jean-philippe.andriot@6WIND.com>
8 * 6WIND, Paris, France
9 * Copyright (C)2007,2008 USAGI/WIDE Project
10 * YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 *
17 */
18
Linus Torvalds7c0f6ba2016-12-24 11:46:01 -080019#include <linux/uaccess.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090020#include <linux/types.h>
21#include <linux/sched.h>
22#include <linux/errno.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090023#include <linux/mm.h>
24#include <linux/kernel.h>
25#include <linux/fcntl.h>
26#include <linux/stat.h>
27#include <linux/socket.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090028#include <linux/inet.h>
29#include <linux/netdevice.h>
30#include <linux/inetdevice.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090031#include <linux/proc_fs.h>
32#include <linux/seq_file.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090033#include <linux/init.h>
David S. Millere2d57762011-02-03 17:59:32 -080034#include <linux/compat.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090035#include <net/protocol.h>
36#include <linux/skbuff.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090037#include <net/raw.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090038#include <linux/notifier.h>
39#include <linux/if_arp.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090040#include <net/checksum.h>
41#include <net/netlink.h>
Patrick McHardyd1db2752010-05-11 14:40:55 +020042#include <net/fib_rules.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090043
44#include <net/ipv6.h>
45#include <net/ip6_route.h>
46#include <linux/mroute6.h>
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +090047#include <linux/pim.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090048#include <net/addrconf.h>
49#include <linux/netfilter_ipv6.h>
Paul Gortmakerbc3b2d72011-07-15 11:47:34 -040050#include <linux/export.h>
Dave Jones5d6e4302009-01-31 00:51:49 -080051#include <net/ip6_checksum.h>
Nicolas Dichteld67b8c62012-12-04 01:13:35 +000052#include <linux/netconf.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090053
Patrick McHardyd1db2752010-05-11 14:40:55 +020054struct ip6mr_rule {
55 struct fib_rule common;
56};
57
58struct ip6mr_result {
Yuval Mintzb70432f2018-02-28 23:29:32 +020059 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +020060};
61
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090062/* Big lock, protecting vif table, mrt cache and mroute socket state.
63 Note that the changes are semaphored via rtnl_lock.
64 */
65
66static DEFINE_RWLOCK(mrt_lock);
67
Yuval Mintzb70432f2018-02-28 23:29:32 +020068/* Multicast router control variables */
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090069
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090070/* Special spinlock for queue of unresolved entries */
71static DEFINE_SPINLOCK(mfc_unres_lock);
72
73/* We return to original Alan's scheme. Hash table of resolved
74 entries is changed only in process context and protected
75 with weak lock mrt_lock. Queue of unresolved entries is protected
76 with strong spinlock mfc_unres_lock.
77
78 In this case data path is free of exclusive locks at all.
79 */
80
81static struct kmem_cache *mrt_cachep __read_mostly;
82
Yuval Mintzb70432f2018-02-28 23:29:32 +020083static struct mr_table *ip6mr_new_table(struct net *net, u32 id);
84static void ip6mr_free_table(struct mr_table *mrt);
Patrick McHardyd1db2752010-05-11 14:40:55 +020085
Yuval Mintzb70432f2018-02-28 23:29:32 +020086static void ip6_mr_forward(struct net *net, struct mr_table *mrt,
Rami Rosen2b52c3a2013-07-21 03:00:31 +030087 struct sk_buff *skb, struct mfc6_cache *cache);
Yuval Mintzb70432f2018-02-28 23:29:32 +020088static int ip6mr_cache_report(struct mr_table *mrt, struct sk_buff *pkt,
Benjamin Thery8229efd2008-12-10 16:30:15 -080089 mifi_t mifi, int assert);
Yuval Mintzb70432f2018-02-28 23:29:32 +020090static void mr6_netlink_event(struct mr_table *mrt, struct mfc6_cache *mfc,
Nicolas Dichtel812e44d2012-12-04 01:13:41 +000091 int cmd);
Yuval Mintzb70432f2018-02-28 23:29:32 +020092static void mrt6msg_netlink_event(struct mr_table *mrt, struct sk_buff *pkt);
Patrick McHardy5b285ca2010-05-11 14:40:56 +020093static int ip6mr_rtm_dumproute(struct sk_buff *skb,
94 struct netlink_callback *cb);
Yuval Mintzb70432f2018-02-28 23:29:32 +020095static void mroute_clean_tables(struct mr_table *mrt, bool all);
Kees Cooke99e88a2017-10-16 14:43:17 -070096static void ipmr_expire_process(struct timer_list *t);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090097
Patrick McHardyd1db2752010-05-11 14:40:55 +020098#ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
Eric Dumazet8ffb3352010-06-06 15:34:40 -070099#define ip6mr_for_each_table(mrt, net) \
Patrick McHardyd1db2752010-05-11 14:40:55 +0200100 list_for_each_entry_rcu(mrt, &net->ipv6.mr6_tables, list)
101
Yuval Mintz7b0db852018-02-28 23:29:39 +0200102static struct mr_table *ip6mr_mr_table_iter(struct net *net,
103 struct mr_table *mrt)
104{
105 struct mr_table *ret;
106
107 if (!mrt)
108 ret = list_entry_rcu(net->ipv6.mr6_tables.next,
109 struct mr_table, list);
110 else
111 ret = list_entry_rcu(mrt->list.next,
112 struct mr_table, list);
113
114 if (&ret->list == &net->ipv6.mr6_tables)
115 return NULL;
116 return ret;
117}
118
Yuval Mintzb70432f2018-02-28 23:29:32 +0200119static struct mr_table *ip6mr_get_table(struct net *net, u32 id)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200120{
Yuval Mintzb70432f2018-02-28 23:29:32 +0200121 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200122
123 ip6mr_for_each_table(mrt, net) {
124 if (mrt->id == id)
125 return mrt;
126 }
127 return NULL;
128}
129
David S. Miller4c9483b2011-03-12 16:22:43 -0500130static int ip6mr_fib_lookup(struct net *net, struct flowi6 *flp6,
Yuval Mintzb70432f2018-02-28 23:29:32 +0200131 struct mr_table **mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200132{
Patrick McHardyd1db2752010-05-11 14:40:55 +0200133 int err;
Hannes Frederic Sowa95f4a452014-01-13 02:45:22 +0100134 struct ip6mr_result res;
135 struct fib_lookup_arg arg = {
136 .result = &res,
137 .flags = FIB_LOOKUP_NOREF,
138 };
Patrick McHardyd1db2752010-05-11 14:40:55 +0200139
David S. Miller4c9483b2011-03-12 16:22:43 -0500140 err = fib_rules_lookup(net->ipv6.mr6_rules_ops,
141 flowi6_to_flowi(flp6), 0, &arg);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200142 if (err < 0)
143 return err;
144 *mrt = res.mrt;
145 return 0;
146}
147
148static int ip6mr_rule_action(struct fib_rule *rule, struct flowi *flp,
149 int flags, struct fib_lookup_arg *arg)
150{
151 struct ip6mr_result *res = arg->result;
Yuval Mintzb70432f2018-02-28 23:29:32 +0200152 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200153
154 switch (rule->action) {
155 case FR_ACT_TO_TBL:
156 break;
157 case FR_ACT_UNREACHABLE:
158 return -ENETUNREACH;
159 case FR_ACT_PROHIBIT:
160 return -EACCES;
161 case FR_ACT_BLACKHOLE:
162 default:
163 return -EINVAL;
164 }
165
166 mrt = ip6mr_get_table(rule->fr_net, rule->table);
Ian Morris63159f22015-03-29 14:00:04 +0100167 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200168 return -EAGAIN;
169 res->mrt = mrt;
170 return 0;
171}
172
173static int ip6mr_rule_match(struct fib_rule *rule, struct flowi *flp, int flags)
174{
175 return 1;
176}
177
178static const struct nla_policy ip6mr_rule_policy[FRA_MAX + 1] = {
179 FRA_GENERIC_POLICY,
180};
181
182static int ip6mr_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
183 struct fib_rule_hdr *frh, struct nlattr **tb)
184{
185 return 0;
186}
187
188static int ip6mr_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
189 struct nlattr **tb)
190{
191 return 1;
192}
193
194static int ip6mr_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
195 struct fib_rule_hdr *frh)
196{
197 frh->dst_len = 0;
198 frh->src_len = 0;
199 frh->tos = 0;
200 return 0;
201}
202
Andi Kleen04a6f822012-10-04 17:12:11 -0700203static const struct fib_rules_ops __net_initconst ip6mr_rules_ops_template = {
Patrick McHardyd1db2752010-05-11 14:40:55 +0200204 .family = RTNL_FAMILY_IP6MR,
205 .rule_size = sizeof(struct ip6mr_rule),
206 .addr_size = sizeof(struct in6_addr),
207 .action = ip6mr_rule_action,
208 .match = ip6mr_rule_match,
209 .configure = ip6mr_rule_configure,
210 .compare = ip6mr_rule_compare,
Patrick McHardyd1db2752010-05-11 14:40:55 +0200211 .fill = ip6mr_rule_fill,
212 .nlgroup = RTNLGRP_IPV6_RULE,
213 .policy = ip6mr_rule_policy,
214 .owner = THIS_MODULE,
215};
216
217static int __net_init ip6mr_rules_init(struct net *net)
218{
219 struct fib_rules_ops *ops;
Yuval Mintzb70432f2018-02-28 23:29:32 +0200220 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200221 int err;
222
223 ops = fib_rules_register(&ip6mr_rules_ops_template, net);
224 if (IS_ERR(ops))
225 return PTR_ERR(ops);
226
227 INIT_LIST_HEAD(&net->ipv6.mr6_tables);
228
229 mrt = ip6mr_new_table(net, RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +0100230 if (!mrt) {
Patrick McHardyd1db2752010-05-11 14:40:55 +0200231 err = -ENOMEM;
232 goto err1;
233 }
234
235 err = fib_default_rule_add(ops, 0x7fff, RT6_TABLE_DFLT, 0);
236 if (err < 0)
237 goto err2;
238
239 net->ipv6.mr6_rules_ops = ops;
240 return 0;
241
242err2:
WANG Congf243e5a2015-03-25 14:45:03 -0700243 ip6mr_free_table(mrt);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200244err1:
245 fib_rules_unregister(ops);
246 return err;
247}
248
249static void __net_exit ip6mr_rules_exit(struct net *net)
250{
Yuval Mintzb70432f2018-02-28 23:29:32 +0200251 struct mr_table *mrt, *next;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200252
Hannes Frederic Sowa905a6f92013-07-22 23:45:53 +0200253 rtnl_lock();
Eric Dumazet035320d2010-06-06 23:48:40 +0000254 list_for_each_entry_safe(mrt, next, &net->ipv6.mr6_tables, list) {
255 list_del(&mrt->list);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200256 ip6mr_free_table(mrt);
Eric Dumazet035320d2010-06-06 23:48:40 +0000257 }
Patrick McHardyd1db2752010-05-11 14:40:55 +0200258 fib_rules_unregister(net->ipv6.mr6_rules_ops);
WANG Cong419df122015-03-31 11:01:46 -0700259 rtnl_unlock();
Patrick McHardyd1db2752010-05-11 14:40:55 +0200260}
261#else
262#define ip6mr_for_each_table(mrt, net) \
263 for (mrt = net->ipv6.mrt6; mrt; mrt = NULL)
264
Yuval Mintz7b0db852018-02-28 23:29:39 +0200265static struct mr_table *ip6mr_mr_table_iter(struct net *net,
266 struct mr_table *mrt)
267{
268 if (!mrt)
269 return net->ipv6.mrt6;
270 return NULL;
271}
272
Yuval Mintzb70432f2018-02-28 23:29:32 +0200273static struct mr_table *ip6mr_get_table(struct net *net, u32 id)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200274{
275 return net->ipv6.mrt6;
276}
277
David S. Miller4c9483b2011-03-12 16:22:43 -0500278static int ip6mr_fib_lookup(struct net *net, struct flowi6 *flp6,
Yuval Mintzb70432f2018-02-28 23:29:32 +0200279 struct mr_table **mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200280{
281 *mrt = net->ipv6.mrt6;
282 return 0;
283}
284
285static int __net_init ip6mr_rules_init(struct net *net)
286{
287 net->ipv6.mrt6 = ip6mr_new_table(net, RT6_TABLE_DFLT);
288 return net->ipv6.mrt6 ? 0 : -ENOMEM;
289}
290
291static void __net_exit ip6mr_rules_exit(struct net *net)
292{
Hannes Frederic Sowa905a6f92013-07-22 23:45:53 +0200293 rtnl_lock();
Patrick McHardyd1db2752010-05-11 14:40:55 +0200294 ip6mr_free_table(net->ipv6.mrt6);
Hannes Frederic Sowa905a6f92013-07-22 23:45:53 +0200295 net->ipv6.mrt6 = NULL;
296 rtnl_unlock();
Patrick McHardyd1db2752010-05-11 14:40:55 +0200297}
298#endif
299
Yuval Mintz87c418b2018-02-28 23:29:31 +0200300static int ip6mr_hash_cmp(struct rhashtable_compare_arg *arg,
301 const void *ptr)
302{
303 const struct mfc6_cache_cmp_arg *cmparg = arg->key;
304 struct mfc6_cache *c = (struct mfc6_cache *)ptr;
305
306 return !ipv6_addr_equal(&c->mf6c_mcastgrp, &cmparg->mf6c_mcastgrp) ||
307 !ipv6_addr_equal(&c->mf6c_origin, &cmparg->mf6c_origin);
308}
309
310static const struct rhashtable_params ip6mr_rht_params = {
Yuval Mintz494fff52018-02-28 23:29:34 +0200311 .head_offset = offsetof(struct mr_mfc, mnode),
Yuval Mintz87c418b2018-02-28 23:29:31 +0200312 .key_offset = offsetof(struct mfc6_cache, cmparg),
313 .key_len = sizeof(struct mfc6_cache_cmp_arg),
314 .nelem_hint = 3,
315 .locks_mul = 1,
316 .obj_cmpfn = ip6mr_hash_cmp,
317 .automatic_shrinking = true,
318};
319
Yuval Mintz0bbbf0e2018-02-28 23:29:33 +0200320static void ip6mr_new_table_set(struct mr_table *mrt,
321 struct net *net)
322{
323#ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
324 list_add_tail_rcu(&mrt->list, &net->ipv6.mr6_tables);
325#endif
326}
327
Yuval Mintz845c9a72018-02-28 23:29:35 +0200328static struct mfc6_cache_cmp_arg ip6mr_mr_table_ops_cmparg_any = {
329 .mf6c_origin = IN6ADDR_ANY_INIT,
330 .mf6c_mcastgrp = IN6ADDR_ANY_INIT,
331};
332
333static struct mr_table_ops ip6mr_mr_table_ops = {
334 .rht_params = &ip6mr_rht_params,
335 .cmparg_any = &ip6mr_mr_table_ops_cmparg_any,
336};
337
Yuval Mintzb70432f2018-02-28 23:29:32 +0200338static struct mr_table *ip6mr_new_table(struct net *net, u32 id)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200339{
Yuval Mintzb70432f2018-02-28 23:29:32 +0200340 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200341
342 mrt = ip6mr_get_table(net, id);
Ian Morris53b24b82015-03-29 14:00:05 +0100343 if (mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200344 return mrt;
345
Yuval Mintz845c9a72018-02-28 23:29:35 +0200346 return mr_table_alloc(net, id, &ip6mr_mr_table_ops,
Yuval Mintz0bbbf0e2018-02-28 23:29:33 +0200347 ipmr_expire_process, ip6mr_new_table_set);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200348}
349
Yuval Mintzb70432f2018-02-28 23:29:32 +0200350static void ip6mr_free_table(struct mr_table *mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200351{
WANG Cong7ba0c472015-03-31 11:01:47 -0700352 del_timer_sync(&mrt->ipmr_expire_timer);
Nikolay Aleksandrov4c698042015-11-20 13:54:20 +0100353 mroute_clean_tables(mrt, true);
Yuval Mintzb70432f2018-02-28 23:29:32 +0200354 rhltable_destroy(&mrt->mfc_hash);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200355 kfree(mrt);
356}
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900357
358#ifdef CONFIG_PROC_FS
Yuval Mintzc8d61962018-02-28 23:29:36 +0200359/* The /proc interfaces to multicast routing
360 * /proc/ip6_mr_cache /proc/ip6_mr_vif
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900361 */
362
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900363static void *ip6mr_vif_seq_start(struct seq_file *seq, loff_t *pos)
364 __acquires(mrt_lock)
365{
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200366 struct mr_vif_iter *iter = seq->private;
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800367 struct net *net = seq_file_net(seq);
Yuval Mintzb70432f2018-02-28 23:29:32 +0200368 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200369
370 mrt = ip6mr_get_table(net, RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +0100371 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200372 return ERR_PTR(-ENOENT);
373
374 iter->mrt = mrt;
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800375
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900376 read_lock(&mrt_lock);
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200377 return mr_vif_seq_start(seq, pos);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900378}
379
380static void ip6mr_vif_seq_stop(struct seq_file *seq, void *v)
381 __releases(mrt_lock)
382{
383 read_unlock(&mrt_lock);
384}
385
386static int ip6mr_vif_seq_show(struct seq_file *seq, void *v)
387{
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200388 struct mr_vif_iter *iter = seq->private;
Yuval Mintzb70432f2018-02-28 23:29:32 +0200389 struct mr_table *mrt = iter->mrt;
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800390
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900391 if (v == SEQ_START_TOKEN) {
392 seq_puts(seq,
393 "Interface BytesIn PktsIn BytesOut PktsOut Flags\n");
394 } else {
Yuval Mintz6853f212018-02-28 23:29:29 +0200395 const struct vif_device *vif = v;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900396 const char *name = vif->dev ? vif->dev->name : "none";
397
398 seq_printf(seq,
Al Virod430a222008-06-02 10:59:02 +0100399 "%2td %-10s %8ld %7ld %8ld %7ld %05X\n",
Yuval Mintzb70432f2018-02-28 23:29:32 +0200400 vif - mrt->vif_table,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900401 name, vif->bytes_in, vif->pkt_in,
402 vif->bytes_out, vif->pkt_out,
403 vif->flags);
404 }
405 return 0;
406}
407
Stephen Hemminger98147d52009-09-01 19:25:02 +0000408static const struct seq_operations ip6mr_vif_seq_ops = {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900409 .start = ip6mr_vif_seq_start,
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200410 .next = mr_vif_seq_next,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900411 .stop = ip6mr_vif_seq_stop,
412 .show = ip6mr_vif_seq_show,
413};
414
415static int ip6mr_vif_open(struct inode *inode, struct file *file)
416{
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800417 return seq_open_net(inode, file, &ip6mr_vif_seq_ops,
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200418 sizeof(struct mr_vif_iter));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900419}
420
Stephen Hemminger5ca1b992009-09-01 19:25:05 +0000421static const struct file_operations ip6mr_vif_fops = {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900422 .open = ip6mr_vif_open,
423 .read = seq_read,
424 .llseek = seq_lseek,
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800425 .release = seq_release_net,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900426};
427
428static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos)
429{
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800430 struct net *net = seq_file_net(seq);
Yuval Mintzb70432f2018-02-28 23:29:32 +0200431 struct mr_table *mrt;
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800432
Patrick McHardyd1db2752010-05-11 14:40:55 +0200433 mrt = ip6mr_get_table(net, RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +0100434 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200435 return ERR_PTR(-ENOENT);
436
Yuval Mintzc8d61962018-02-28 23:29:36 +0200437 return mr_mfc_seq_start(seq, pos, mrt, &mfc_unres_lock);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900438}
439
440static int ipmr_mfc_seq_show(struct seq_file *seq, void *v)
441{
442 int n;
443
444 if (v == SEQ_START_TOKEN) {
445 seq_puts(seq,
446 "Group "
447 "Origin "
448 "Iif Pkts Bytes Wrong Oifs\n");
449 } else {
450 const struct mfc6_cache *mfc = v;
Yuval Mintzc8d61962018-02-28 23:29:36 +0200451 const struct mr_mfc_iter *it = seq->private;
Yuval Mintzb70432f2018-02-28 23:29:32 +0200452 struct mr_table *mrt = it->mrt;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900453
Benjamin Thery999890b2008-12-03 22:22:16 -0800454 seq_printf(seq, "%pI6 %pI6 %-3hd",
Harvey Harrison0c6ce782008-10-28 16:09:23 -0700455 &mfc->mf6c_mcastgrp, &mfc->mf6c_origin,
Yuval Mintz494fff52018-02-28 23:29:34 +0200456 mfc->_c.mfc_parent);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900457
Yuval Mintzb70432f2018-02-28 23:29:32 +0200458 if (it->cache != &mrt->mfc_unres_queue) {
Benjamin Thery1ea472e2008-12-03 22:21:47 -0800459 seq_printf(seq, " %8lu %8lu %8lu",
Yuval Mintz494fff52018-02-28 23:29:34 +0200460 mfc->_c.mfc_un.res.pkt,
461 mfc->_c.mfc_un.res.bytes,
462 mfc->_c.mfc_un.res.wrong_if);
463 for (n = mfc->_c.mfc_un.res.minvif;
464 n < mfc->_c.mfc_un.res.maxvif; n++) {
Yuval Mintzb70432f2018-02-28 23:29:32 +0200465 if (VIF_EXISTS(mrt, n) &&
Yuval Mintz494fff52018-02-28 23:29:34 +0200466 mfc->_c.mfc_un.res.ttls[n] < 255)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900467 seq_printf(seq,
Yuval Mintz494fff52018-02-28 23:29:34 +0200468 " %2d:%-3d", n,
469 mfc->_c.mfc_un.res.ttls[n]);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900470 }
Benjamin Thery1ea472e2008-12-03 22:21:47 -0800471 } else {
472 /* unresolved mfc_caches don't contain
473 * pkt, bytes and wrong_if values
474 */
475 seq_printf(seq, " %8lu %8lu %8lu", 0ul, 0ul, 0ul);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900476 }
477 seq_putc(seq, '\n');
478 }
479 return 0;
480}
481
James Morris88e9d342009-09-22 16:43:43 -0700482static const struct seq_operations ipmr_mfc_seq_ops = {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900483 .start = ipmr_mfc_seq_start,
Yuval Mintzc8d61962018-02-28 23:29:36 +0200484 .next = mr_mfc_seq_next,
485 .stop = mr_mfc_seq_stop,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900486 .show = ipmr_mfc_seq_show,
487};
488
489static int ipmr_mfc_open(struct inode *inode, struct file *file)
490{
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800491 return seq_open_net(inode, file, &ipmr_mfc_seq_ops,
Yuval Mintzc8d61962018-02-28 23:29:36 +0200492 sizeof(struct mr_mfc_iter));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900493}
494
Stephen Hemminger5ca1b992009-09-01 19:25:05 +0000495static const struct file_operations ip6mr_mfc_fops = {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900496 .open = ipmr_mfc_open,
497 .read = seq_read,
498 .llseek = seq_lseek,
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800499 .release = seq_release_net,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900500};
501#endif
502
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900503#ifdef CONFIG_IPV6_PIMSM_V2
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900504
505static int pim6_rcv(struct sk_buff *skb)
506{
507 struct pimreghdr *pim;
508 struct ipv6hdr *encap;
509 struct net_device *reg_dev = NULL;
Benjamin Thery8229efd2008-12-10 16:30:15 -0800510 struct net *net = dev_net(skb->dev);
Yuval Mintzb70432f2018-02-28 23:29:32 +0200511 struct mr_table *mrt;
David S. Miller4c9483b2011-03-12 16:22:43 -0500512 struct flowi6 fl6 = {
513 .flowi6_iif = skb->dev->ifindex,
514 .flowi6_mark = skb->mark,
Patrick McHardyd1db2752010-05-11 14:40:55 +0200515 };
516 int reg_vif_num;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900517
518 if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(*encap)))
519 goto drop;
520
521 pim = (struct pimreghdr *)skb_transport_header(skb);
Nikolay Aleksandrov56245ca2016-10-31 13:21:04 +0100522 if (pim->type != ((PIM_VERSION << 4) | PIM_TYPE_REGISTER) ||
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900523 (pim->flags & PIM_NULL_REGISTER) ||
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800524 (csum_ipv6_magic(&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
525 sizeof(*pim), IPPROTO_PIM,
526 csum_partial((void *)pim, sizeof(*pim), 0)) &&
Al Viroec6b4862008-04-26 22:28:58 -0700527 csum_fold(skb_checksum(skb, 0, skb->len, 0))))
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900528 goto drop;
529
530 /* check if the inner packet is destined to mcast group */
531 encap = (struct ipv6hdr *)(skb_transport_header(skb) +
532 sizeof(*pim));
533
534 if (!ipv6_addr_is_multicast(&encap->daddr) ||
535 encap->payload_len == 0 ||
536 ntohs(encap->payload_len) + sizeof(*pim) > skb->len)
537 goto drop;
538
David S. Miller4c9483b2011-03-12 16:22:43 -0500539 if (ip6mr_fib_lookup(net, &fl6, &mrt) < 0)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200540 goto drop;
541 reg_vif_num = mrt->mroute_reg_vif_num;
542
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900543 read_lock(&mrt_lock);
544 if (reg_vif_num >= 0)
Yuval Mintzb70432f2018-02-28 23:29:32 +0200545 reg_dev = mrt->vif_table[reg_vif_num].dev;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900546 if (reg_dev)
547 dev_hold(reg_dev);
548 read_unlock(&mrt_lock);
549
Ian Morris63159f22015-03-29 14:00:04 +0100550 if (!reg_dev)
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900551 goto drop;
552
553 skb->mac_header = skb->network_header;
554 skb_pull(skb, (u8 *)encap - skb->data);
555 skb_reset_network_header(skb);
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800556 skb->protocol = htons(ETH_P_IPV6);
Cesar Eduardo Barros3e49e6d2011-03-26 05:10:30 +0000557 skb->ip_summed = CHECKSUM_NONE;
Eric Dumazetd19d56d2010-05-17 22:36:55 -0700558
Nicolas Dichtelea231922013-09-02 15:34:58 +0200559 skb_tunnel_rx(skb, reg_dev, dev_net(reg_dev));
Eric Dumazetd19d56d2010-05-17 22:36:55 -0700560
Eric Dumazetcaf586e2010-09-30 21:06:55 +0000561 netif_rx(skb);
Eric Dumazet8990f462010-09-20 00:12:11 +0000562
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900563 dev_put(reg_dev);
564 return 0;
565 drop:
566 kfree_skb(skb);
567 return 0;
568}
569
Alexey Dobriyan41135cc2009-09-14 12:22:28 +0000570static const struct inet6_protocol pim6_protocol = {
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900571 .handler = pim6_rcv,
572};
573
574/* Service routines creating virtual interfaces: PIMREG */
575
Stephen Hemminger6fef4c02009-08-31 19:50:41 +0000576static netdev_tx_t reg_vif_xmit(struct sk_buff *skb,
577 struct net_device *dev)
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900578{
Benjamin Thery8229efd2008-12-10 16:30:15 -0800579 struct net *net = dev_net(dev);
Yuval Mintzb70432f2018-02-28 23:29:32 +0200580 struct mr_table *mrt;
David S. Miller4c9483b2011-03-12 16:22:43 -0500581 struct flowi6 fl6 = {
582 .flowi6_oif = dev->ifindex,
Cong Wang6a662712014-04-15 16:25:34 -0700583 .flowi6_iif = skb->skb_iif ? : LOOPBACK_IFINDEX,
David S. Miller4c9483b2011-03-12 16:22:43 -0500584 .flowi6_mark = skb->mark,
Patrick McHardyd1db2752010-05-11 14:40:55 +0200585 };
586 int err;
587
David S. Miller4c9483b2011-03-12 16:22:43 -0500588 err = ip6mr_fib_lookup(net, &fl6, &mrt);
Ben Greear67928c42011-09-23 13:11:01 +0000589 if (err < 0) {
590 kfree_skb(skb);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200591 return err;
Ben Greear67928c42011-09-23 13:11:01 +0000592 }
Benjamin Thery8229efd2008-12-10 16:30:15 -0800593
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900594 read_lock(&mrt_lock);
Pavel Emelyanovdc58c782008-05-21 14:17:54 -0700595 dev->stats.tx_bytes += skb->len;
596 dev->stats.tx_packets++;
Patrick McHardy6bd52142010-05-11 14:40:53 +0200597 ip6mr_cache_report(mrt, skb, mrt->mroute_reg_vif_num, MRT6MSG_WHOLEPKT);
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900598 read_unlock(&mrt_lock);
599 kfree_skb(skb);
Patrick McHardy6ed10652009-06-23 06:03:08 +0000600 return NETDEV_TX_OK;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900601}
602
Nicolas Dichtelee9b9592015-04-02 17:07:03 +0200603static int reg_vif_get_iflink(const struct net_device *dev)
604{
605 return 0;
606}
607
Stephen Hemminger007c3832008-11-20 20:28:35 -0800608static const struct net_device_ops reg_vif_netdev_ops = {
609 .ndo_start_xmit = reg_vif_xmit,
Nicolas Dichtelee9b9592015-04-02 17:07:03 +0200610 .ndo_get_iflink = reg_vif_get_iflink,
Stephen Hemminger007c3832008-11-20 20:28:35 -0800611};
612
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900613static void reg_vif_setup(struct net_device *dev)
614{
615 dev->type = ARPHRD_PIMREG;
616 dev->mtu = 1500 - sizeof(struct ipv6hdr) - 8;
617 dev->flags = IFF_NOARP;
Stephen Hemminger007c3832008-11-20 20:28:35 -0800618 dev->netdev_ops = &reg_vif_netdev_ops;
David S. Millercf124db2017-05-08 12:52:56 -0400619 dev->needs_free_netdev = true;
Tom Goff403dbb92009-06-14 03:16:13 -0700620 dev->features |= NETIF_F_NETNS_LOCAL;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900621}
622
Yuval Mintzb70432f2018-02-28 23:29:32 +0200623static struct net_device *ip6mr_reg_vif(struct net *net, struct mr_table *mrt)
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900624{
625 struct net_device *dev;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200626 char name[IFNAMSIZ];
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900627
Patrick McHardyd1db2752010-05-11 14:40:55 +0200628 if (mrt->id == RT6_TABLE_DFLT)
629 sprintf(name, "pim6reg");
630 else
631 sprintf(name, "pim6reg%u", mrt->id);
632
Tom Gundersenc835a672014-07-14 16:37:24 +0200633 dev = alloc_netdev(0, name, NET_NAME_UNKNOWN, reg_vif_setup);
Ian Morris63159f22015-03-29 14:00:04 +0100634 if (!dev)
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900635 return NULL;
636
Benjamin Thery8229efd2008-12-10 16:30:15 -0800637 dev_net_set(dev, net);
638
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900639 if (register_netdevice(dev)) {
640 free_netdev(dev);
641 return NULL;
642 }
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900643
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900644 if (dev_open(dev))
645 goto failure;
646
Wang Chen7af3db72008-07-14 20:54:54 -0700647 dev_hold(dev);
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900648 return dev;
649
650failure:
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900651 unregister_netdevice(dev);
652 return NULL;
653}
654#endif
655
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900656/*
657 * Delete a VIF entry
658 */
659
Yuval Mintzb70432f2018-02-28 23:29:32 +0200660static int mif6_delete(struct mr_table *mrt, int vifi, int notify,
Nikolay Aleksandrov723b9292017-04-21 20:42:16 +0300661 struct list_head *head)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900662{
Yuval Mintz6853f212018-02-28 23:29:29 +0200663 struct vif_device *v;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900664 struct net_device *dev;
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800665 struct inet6_dev *in6_dev;
Patrick McHardy6bd52142010-05-11 14:40:53 +0200666
667 if (vifi < 0 || vifi >= mrt->maxvif)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900668 return -EADDRNOTAVAIL;
669
Yuval Mintzb70432f2018-02-28 23:29:32 +0200670 v = &mrt->vif_table[vifi];
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900671
672 write_lock_bh(&mrt_lock);
673 dev = v->dev;
674 v->dev = NULL;
675
676 if (!dev) {
677 write_unlock_bh(&mrt_lock);
678 return -EADDRNOTAVAIL;
679 }
680
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900681#ifdef CONFIG_IPV6_PIMSM_V2
Patrick McHardy6bd52142010-05-11 14:40:53 +0200682 if (vifi == mrt->mroute_reg_vif_num)
683 mrt->mroute_reg_vif_num = -1;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900684#endif
685
Patrick McHardy6bd52142010-05-11 14:40:53 +0200686 if (vifi + 1 == mrt->maxvif) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900687 int tmp;
688 for (tmp = vifi - 1; tmp >= 0; tmp--) {
Yuval Mintzb70432f2018-02-28 23:29:32 +0200689 if (VIF_EXISTS(mrt, tmp))
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900690 break;
691 }
Patrick McHardy6bd52142010-05-11 14:40:53 +0200692 mrt->maxvif = tmp + 1;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900693 }
694
695 write_unlock_bh(&mrt_lock);
696
697 dev_set_allmulti(dev, -1);
698
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800699 in6_dev = __in6_dev_get(dev);
Nicolas Dichteld67b8c62012-12-04 01:13:35 +0000700 if (in6_dev) {
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800701 in6_dev->cnf.mc_forwarding--;
David Ahern85b3daa2017-03-28 14:28:04 -0700702 inet6_netconf_notify_devconf(dev_net(dev), RTM_NEWNETCONF,
Nicolas Dichteld67b8c62012-12-04 01:13:35 +0000703 NETCONFA_MC_FORWARDING,
704 dev->ifindex, &in6_dev->cnf);
705 }
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800706
Nikolay Aleksandrov723b9292017-04-21 20:42:16 +0300707 if ((v->flags & MIFF_REGISTER) && !notify)
Eric Dumazetc871e662009-10-28 04:48:11 +0000708 unregister_netdevice_queue(dev, head);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900709
710 dev_put(dev);
711 return 0;
712}
713
Yuval Mintz87c418b2018-02-28 23:29:31 +0200714static inline void ip6mr_cache_free_rcu(struct rcu_head *head)
715{
Yuval Mintz494fff52018-02-28 23:29:34 +0200716 struct mr_mfc *c = container_of(head, struct mr_mfc, rcu);
Yuval Mintz87c418b2018-02-28 23:29:31 +0200717
Yuval Mintz494fff52018-02-28 23:29:34 +0200718 kmem_cache_free(mrt_cachep, (struct mfc6_cache *)c);
Yuval Mintz87c418b2018-02-28 23:29:31 +0200719}
720
Benjamin Thery58701ad2008-12-10 16:22:34 -0800721static inline void ip6mr_cache_free(struct mfc6_cache *c)
722{
Yuval Mintz494fff52018-02-28 23:29:34 +0200723 call_rcu(&c->_c.rcu, ip6mr_cache_free_rcu);
Benjamin Thery58701ad2008-12-10 16:22:34 -0800724}
725
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900726/* Destroy an unresolved cache entry, killing queued skbs
727 and reporting error to netlink readers.
728 */
729
Yuval Mintzb70432f2018-02-28 23:29:32 +0200730static void ip6mr_destroy_unres(struct mr_table *mrt, struct mfc6_cache *c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900731{
Patrick McHardy6bd52142010-05-11 14:40:53 +0200732 struct net *net = read_pnet(&mrt->net);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900733 struct sk_buff *skb;
734
Patrick McHardy6bd52142010-05-11 14:40:53 +0200735 atomic_dec(&mrt->cache_resolve_queue_len);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900736
Yuval Mintz494fff52018-02-28 23:29:34 +0200737 while ((skb = skb_dequeue(&c->_c.mfc_un.unres.unresolved)) != NULL) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900738 if (ipv6_hdr(skb)->version == 0) {
Johannes Bergaf728682017-06-16 14:29:22 +0200739 struct nlmsghdr *nlh = skb_pull(skb,
740 sizeof(struct ipv6hdr));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900741 nlh->nlmsg_type = NLMSG_ERROR;
Hong zhi guo573ce262013-03-27 06:47:04 +0000742 nlh->nlmsg_len = nlmsg_msg_size(sizeof(struct nlmsgerr));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900743 skb_trim(skb, nlh->nlmsg_len);
Hong zhi guo573ce262013-03-27 06:47:04 +0000744 ((struct nlmsgerr *)nlmsg_data(nlh))->error = -ETIMEDOUT;
Eric W. Biederman15e47302012-09-07 20:12:54 +0000745 rtnl_unicast(skb, net, NETLINK_CB(skb).portid);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900746 } else
747 kfree_skb(skb);
748 }
749
Benjamin Thery58701ad2008-12-10 16:22:34 -0800750 ip6mr_cache_free(c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900751}
752
753
Patrick McHardyc476efb2010-05-11 14:40:48 +0200754/* Timer process for all the unresolved queue. */
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900755
Yuval Mintzb70432f2018-02-28 23:29:32 +0200756static void ipmr_do_expire_process(struct mr_table *mrt)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900757{
758 unsigned long now = jiffies;
759 unsigned long expires = 10 * HZ;
Yuval Mintz494fff52018-02-28 23:29:34 +0200760 struct mr_mfc *c, *next;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900761
Yuval Mintzb70432f2018-02-28 23:29:32 +0200762 list_for_each_entry_safe(c, next, &mrt->mfc_unres_queue, list) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900763 if (time_after(c->mfc_un.unres.expires, now)) {
764 /* not yet... */
765 unsigned long interval = c->mfc_un.unres.expires - now;
766 if (interval < expires)
767 expires = interval;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900768 continue;
769 }
770
Patrick McHardyf30a77842010-05-11 14:40:51 +0200771 list_del(&c->list);
Yuval Mintz494fff52018-02-28 23:29:34 +0200772 mr6_netlink_event(mrt, (struct mfc6_cache *)c, RTM_DELROUTE);
773 ip6mr_destroy_unres(mrt, (struct mfc6_cache *)c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900774 }
775
Yuval Mintzb70432f2018-02-28 23:29:32 +0200776 if (!list_empty(&mrt->mfc_unres_queue))
Patrick McHardy6bd52142010-05-11 14:40:53 +0200777 mod_timer(&mrt->ipmr_expire_timer, jiffies + expires);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900778}
779
Kees Cooke99e88a2017-10-16 14:43:17 -0700780static void ipmr_expire_process(struct timer_list *t)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900781{
Yuval Mintzb70432f2018-02-28 23:29:32 +0200782 struct mr_table *mrt = from_timer(mrt, t, ipmr_expire_timer);
Patrick McHardyc476efb2010-05-11 14:40:48 +0200783
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900784 if (!spin_trylock(&mfc_unres_lock)) {
Patrick McHardy6bd52142010-05-11 14:40:53 +0200785 mod_timer(&mrt->ipmr_expire_timer, jiffies + 1);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900786 return;
787 }
788
Yuval Mintzb70432f2018-02-28 23:29:32 +0200789 if (!list_empty(&mrt->mfc_unres_queue))
Patrick McHardy6bd52142010-05-11 14:40:53 +0200790 ipmr_do_expire_process(mrt);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900791
792 spin_unlock(&mfc_unres_lock);
793}
794
795/* Fill oifs list. It is called under write locked mrt_lock. */
796
Yuval Mintzb70432f2018-02-28 23:29:32 +0200797static void ip6mr_update_thresholds(struct mr_table *mrt,
Yuval Mintz494fff52018-02-28 23:29:34 +0200798 struct mr_mfc *cache,
Patrick McHardyb5aa30b2010-05-11 14:40:50 +0200799 unsigned char *ttls)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900800{
801 int vifi;
802
Rami Rosen6ac7eb02008-04-10 12:40:10 +0300803 cache->mfc_un.res.minvif = MAXMIFS;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900804 cache->mfc_un.res.maxvif = 0;
Rami Rosen6ac7eb02008-04-10 12:40:10 +0300805 memset(cache->mfc_un.res.ttls, 255, MAXMIFS);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900806
Patrick McHardy6bd52142010-05-11 14:40:53 +0200807 for (vifi = 0; vifi < mrt->maxvif; vifi++) {
Yuval Mintzb70432f2018-02-28 23:29:32 +0200808 if (VIF_EXISTS(mrt, vifi) &&
Benjamin Thery4e168802008-12-10 16:15:08 -0800809 ttls[vifi] && ttls[vifi] < 255) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900810 cache->mfc_un.res.ttls[vifi] = ttls[vifi];
811 if (cache->mfc_un.res.minvif > vifi)
812 cache->mfc_un.res.minvif = vifi;
813 if (cache->mfc_un.res.maxvif <= vifi)
814 cache->mfc_un.res.maxvif = vifi + 1;
815 }
816 }
Nikolay Aleksandrov90b5ca12016-07-26 18:54:52 +0200817 cache->mfc_un.res.lastuse = jiffies;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900818}
819
Yuval Mintzb70432f2018-02-28 23:29:32 +0200820static int mif6_add(struct net *net, struct mr_table *mrt,
Patrick McHardy6bd52142010-05-11 14:40:53 +0200821 struct mif6ctl *vifc, int mrtsock)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900822{
823 int vifi = vifc->mif6c_mifi;
Yuval Mintzb70432f2018-02-28 23:29:32 +0200824 struct vif_device *v = &mrt->vif_table[vifi];
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900825 struct net_device *dev;
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800826 struct inet6_dev *in6_dev;
Wang Chen5ae7b442008-07-14 20:54:23 -0700827 int err;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900828
829 /* Is vif busy ? */
Yuval Mintzb70432f2018-02-28 23:29:32 +0200830 if (VIF_EXISTS(mrt, vifi))
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900831 return -EADDRINUSE;
832
833 switch (vifc->mif6c_flags) {
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900834#ifdef CONFIG_IPV6_PIMSM_V2
835 case MIFF_REGISTER:
836 /*
837 * Special Purpose VIF in PIM
838 * All the packets will be sent to the daemon
839 */
Patrick McHardy6bd52142010-05-11 14:40:53 +0200840 if (mrt->mroute_reg_vif_num >= 0)
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900841 return -EADDRINUSE;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200842 dev = ip6mr_reg_vif(net, mrt);
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900843 if (!dev)
844 return -ENOBUFS;
Wang Chen5ae7b442008-07-14 20:54:23 -0700845 err = dev_set_allmulti(dev, 1);
846 if (err) {
847 unregister_netdevice(dev);
Wang Chen7af3db72008-07-14 20:54:54 -0700848 dev_put(dev);
Wang Chen5ae7b442008-07-14 20:54:23 -0700849 return err;
850 }
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900851 break;
852#endif
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900853 case 0:
Benjamin Thery8229efd2008-12-10 16:30:15 -0800854 dev = dev_get_by_index(net, vifc->mif6c_pifi);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900855 if (!dev)
856 return -EADDRNOTAVAIL;
Wang Chen5ae7b442008-07-14 20:54:23 -0700857 err = dev_set_allmulti(dev, 1);
Wang Chen7af3db72008-07-14 20:54:54 -0700858 if (err) {
859 dev_put(dev);
Wang Chen5ae7b442008-07-14 20:54:23 -0700860 return err;
Wang Chen7af3db72008-07-14 20:54:54 -0700861 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900862 break;
863 default:
864 return -EINVAL;
865 }
866
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800867 in6_dev = __in6_dev_get(dev);
Nicolas Dichteld67b8c62012-12-04 01:13:35 +0000868 if (in6_dev) {
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800869 in6_dev->cnf.mc_forwarding++;
David Ahern85b3daa2017-03-28 14:28:04 -0700870 inet6_netconf_notify_devconf(dev_net(dev), RTM_NEWNETCONF,
Nicolas Dichteld67b8c62012-12-04 01:13:35 +0000871 NETCONFA_MC_FORWARDING,
872 dev->ifindex, &in6_dev->cnf);
873 }
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800874
Yuval Mintz6853f212018-02-28 23:29:29 +0200875 /* Fill in the VIF structures */
876 vif_device_init(v, dev, vifc->vifc_rate_limit, vifc->vifc_threshold,
877 vifc->mif6c_flags | (!mrtsock ? VIFF_STATIC : 0),
878 MIFF_REGISTER);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900879
880 /* And finish update writing critical data */
881 write_lock_bh(&mrt_lock);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900882 v->dev = dev;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900883#ifdef CONFIG_IPV6_PIMSM_V2
884 if (v->flags & MIFF_REGISTER)
Patrick McHardy6bd52142010-05-11 14:40:53 +0200885 mrt->mroute_reg_vif_num = vifi;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900886#endif
Patrick McHardy6bd52142010-05-11 14:40:53 +0200887 if (vifi + 1 > mrt->maxvif)
888 mrt->maxvif = vifi + 1;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900889 write_unlock_bh(&mrt_lock);
890 return 0;
891}
892
Yuval Mintzb70432f2018-02-28 23:29:32 +0200893static struct mfc6_cache *ip6mr_cache_find(struct mr_table *mrt,
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000894 const struct in6_addr *origin,
895 const struct in6_addr *mcastgrp)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900896{
Yuval Mintz87c418b2018-02-28 23:29:31 +0200897 struct mfc6_cache_cmp_arg arg = {
898 .mf6c_origin = *origin,
899 .mf6c_mcastgrp = *mcastgrp,
900 };
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900901
Yuval Mintz845c9a72018-02-28 23:29:35 +0200902 return mr_mfc_find(mrt, &arg);
Nicolas Dichtel660b26d2013-01-21 06:00:26 +0000903}
904
905/* Look for a (*,G) entry */
Yuval Mintzb70432f2018-02-28 23:29:32 +0200906static struct mfc6_cache *ip6mr_cache_find_any(struct mr_table *mrt,
Nicolas Dichtel660b26d2013-01-21 06:00:26 +0000907 struct in6_addr *mcastgrp,
908 mifi_t mifi)
909{
Yuval Mintz87c418b2018-02-28 23:29:31 +0200910 struct mfc6_cache_cmp_arg arg = {
911 .mf6c_origin = in6addr_any,
912 .mf6c_mcastgrp = *mcastgrp,
913 };
Nicolas Dichtel660b26d2013-01-21 06:00:26 +0000914
915 if (ipv6_addr_any(mcastgrp))
Yuval Mintz845c9a72018-02-28 23:29:35 +0200916 return mr_mfc_find_any_parent(mrt, mifi);
917 return mr_mfc_find_any(mrt, mifi, &arg);
Nicolas Dichtel660b26d2013-01-21 06:00:26 +0000918}
919
Yuval Mintz87c418b2018-02-28 23:29:31 +0200920/* Look for a (S,G,iif) entry if parent != -1 */
921static struct mfc6_cache *
Yuval Mintzb70432f2018-02-28 23:29:32 +0200922ip6mr_cache_find_parent(struct mr_table *mrt,
Yuval Mintz87c418b2018-02-28 23:29:31 +0200923 const struct in6_addr *origin,
924 const struct in6_addr *mcastgrp,
925 int parent)
926{
927 struct mfc6_cache_cmp_arg arg = {
928 .mf6c_origin = *origin,
929 .mf6c_mcastgrp = *mcastgrp,
930 };
Yuval Mintz87c418b2018-02-28 23:29:31 +0200931
Yuval Mintz845c9a72018-02-28 23:29:35 +0200932 return mr_mfc_find_parent(mrt, &arg, parent);
Yuval Mintz87c418b2018-02-28 23:29:31 +0200933}
934
Yuval Mintz845c9a72018-02-28 23:29:35 +0200935/* Allocate a multicast cache entry */
Patrick McHardyb5aa30b2010-05-11 14:40:50 +0200936static struct mfc6_cache *ip6mr_cache_alloc(void)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900937{
Joe Perches36cbac52008-12-03 22:27:25 -0800938 struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL);
Ian Morris63159f22015-03-29 14:00:04 +0100939 if (!c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900940 return NULL;
Yuval Mintz494fff52018-02-28 23:29:34 +0200941 c->_c.mfc_un.res.last_assert = jiffies - MFC_ASSERT_THRESH - 1;
942 c->_c.mfc_un.res.minvif = MAXMIFS;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900943 return c;
944}
945
Patrick McHardyb5aa30b2010-05-11 14:40:50 +0200946static struct mfc6_cache *ip6mr_cache_alloc_unres(void)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900947{
Joe Perches36cbac52008-12-03 22:27:25 -0800948 struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC);
Ian Morris63159f22015-03-29 14:00:04 +0100949 if (!c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900950 return NULL;
Yuval Mintz494fff52018-02-28 23:29:34 +0200951 skb_queue_head_init(&c->_c.mfc_un.unres.unresolved);
952 c->_c.mfc_un.unres.expires = jiffies + 10 * HZ;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900953 return c;
954}
955
956/*
957 * A cache entry has gone into a resolved state from queued
958 */
959
Yuval Mintzb70432f2018-02-28 23:29:32 +0200960static void ip6mr_cache_resolve(struct net *net, struct mr_table *mrt,
Patrick McHardy6bd52142010-05-11 14:40:53 +0200961 struct mfc6_cache *uc, struct mfc6_cache *c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900962{
963 struct sk_buff *skb;
964
965 /*
966 * Play the pending entries through our router
967 */
968
Yuval Mintz494fff52018-02-28 23:29:34 +0200969 while ((skb = __skb_dequeue(&uc->_c.mfc_un.unres.unresolved))) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900970 if (ipv6_hdr(skb)->version == 0) {
Johannes Bergaf728682017-06-16 14:29:22 +0200971 struct nlmsghdr *nlh = skb_pull(skb,
972 sizeof(struct ipv6hdr));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900973
Yuval Mintz7b0db852018-02-28 23:29:39 +0200974 if (mr_fill_mroute(mrt, skb, &c->_c,
975 nlmsg_data(nlh)) > 0) {
YOSHIFUJI Hideaki549e0282008-04-05 22:17:39 +0900976 nlh->nlmsg_len = skb_tail_pointer(skb) - (u8 *)nlh;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900977 } else {
978 nlh->nlmsg_type = NLMSG_ERROR;
Hong zhi guo573ce262013-03-27 06:47:04 +0000979 nlh->nlmsg_len = nlmsg_msg_size(sizeof(struct nlmsgerr));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900980 skb_trim(skb, nlh->nlmsg_len);
Hong zhi guo573ce262013-03-27 06:47:04 +0000981 ((struct nlmsgerr *)nlmsg_data(nlh))->error = -EMSGSIZE;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900982 }
Eric W. Biederman15e47302012-09-07 20:12:54 +0000983 rtnl_unicast(skb, net, NETLINK_CB(skb).portid);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900984 } else
Patrick McHardy6bd52142010-05-11 14:40:53 +0200985 ip6_mr_forward(net, mrt, skb, c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900986 }
987}
988
989/*
Julien Gomesdd12d15c2017-06-20 13:54:18 -0700990 * Bounce a cache query up to pim6sd and netlink.
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900991 *
992 * Called under mrt_lock.
993 */
994
Yuval Mintzb70432f2018-02-28 23:29:32 +0200995static int ip6mr_cache_report(struct mr_table *mrt, struct sk_buff *pkt,
Patrick McHardy6bd52142010-05-11 14:40:53 +0200996 mifi_t mifi, int assert)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900997{
Yuval Mintz8571ab42018-02-28 23:29:30 +0200998 struct sock *mroute6_sk;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900999 struct sk_buff *skb;
1000 struct mrt6msg *msg;
1001 int ret;
1002
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001003#ifdef CONFIG_IPV6_PIMSM_V2
1004 if (assert == MRT6MSG_WHOLEPKT)
1005 skb = skb_realloc_headroom(pkt, -skb_network_offset(pkt)
1006 +sizeof(*msg));
1007 else
1008#endif
1009 skb = alloc_skb(sizeof(struct ipv6hdr) + sizeof(*msg), GFP_ATOMIC);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001010
1011 if (!skb)
1012 return -ENOBUFS;
1013
1014 /* I suppose that internal messages
1015 * do not require checksums */
1016
1017 skb->ip_summed = CHECKSUM_UNNECESSARY;
1018
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001019#ifdef CONFIG_IPV6_PIMSM_V2
1020 if (assert == MRT6MSG_WHOLEPKT) {
1021 /* Ugly, but we have no choice with this interface.
1022 Duplicate old header, fix length etc.
1023 And all this only to mangle msg->im6_msgtype and
1024 to set msg->im6_mbz to "mbz" :-)
1025 */
1026 skb_push(skb, -skb_network_offset(pkt));
1027
1028 skb_push(skb, sizeof(*msg));
1029 skb_reset_transport_header(skb);
1030 msg = (struct mrt6msg *)skb_transport_header(skb);
1031 msg->im6_mbz = 0;
1032 msg->im6_msgtype = MRT6MSG_WHOLEPKT;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001033 msg->im6_mif = mrt->mroute_reg_vif_num;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001034 msg->im6_pad = 0;
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +00001035 msg->im6_src = ipv6_hdr(pkt)->saddr;
1036 msg->im6_dst = ipv6_hdr(pkt)->daddr;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001037
1038 skb->ip_summed = CHECKSUM_UNNECESSARY;
1039 } else
1040#endif
1041 {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001042 /*
1043 * Copy the IP header
1044 */
1045
1046 skb_put(skb, sizeof(struct ipv6hdr));
1047 skb_reset_network_header(skb);
1048 skb_copy_to_linear_data(skb, ipv6_hdr(pkt), sizeof(struct ipv6hdr));
1049
1050 /*
1051 * Add our header
1052 */
1053 skb_put(skb, sizeof(*msg));
1054 skb_reset_transport_header(skb);
1055 msg = (struct mrt6msg *)skb_transport_header(skb);
1056
1057 msg->im6_mbz = 0;
1058 msg->im6_msgtype = assert;
Rami Rosen6ac7eb02008-04-10 12:40:10 +03001059 msg->im6_mif = mifi;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001060 msg->im6_pad = 0;
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +00001061 msg->im6_src = ipv6_hdr(pkt)->saddr;
1062 msg->im6_dst = ipv6_hdr(pkt)->daddr;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001063
Eric Dumazetadf30902009-06-02 05:19:30 +00001064 skb_dst_set(skb, dst_clone(skb_dst(pkt)));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001065 skb->ip_summed = CHECKSUM_UNNECESSARY;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001066 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001067
Yuval Mintz8571ab42018-02-28 23:29:30 +02001068 rcu_read_lock();
Yuval Mintzb70432f2018-02-28 23:29:32 +02001069 mroute6_sk = rcu_dereference(mrt->mroute_sk);
Yuval Mintz8571ab42018-02-28 23:29:30 +02001070 if (!mroute6_sk) {
1071 rcu_read_unlock();
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001072 kfree_skb(skb);
1073 return -EINVAL;
1074 }
1075
Julien Gomesdd12d15c2017-06-20 13:54:18 -07001076 mrt6msg_netlink_event(mrt, skb);
1077
Yuval Mintz8571ab42018-02-28 23:29:30 +02001078 /* Deliver to user space multicast routing algorithms */
1079 ret = sock_queue_rcv_skb(mroute6_sk, skb);
1080 rcu_read_unlock();
Benjamin Therybd91b8b2008-12-10 16:07:08 -08001081 if (ret < 0) {
Joe Perchese87cc472012-05-13 21:56:26 +00001082 net_warn_ratelimited("mroute6: pending queue full, dropping entries\n");
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001083 kfree_skb(skb);
1084 }
1085
1086 return ret;
1087}
1088
Yuval Mintz494fff52018-02-28 23:29:34 +02001089/* Queue a packet for resolution. It gets locked cache entry! */
1090static int ip6mr_cache_unresolved(struct mr_table *mrt, mifi_t mifi,
1091 struct sk_buff *skb)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001092{
Yuval Mintz494fff52018-02-28 23:29:34 +02001093 struct mfc6_cache *c;
Patrick McHardyf30a77842010-05-11 14:40:51 +02001094 bool found = false;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001095 int err;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001096
1097 spin_lock_bh(&mfc_unres_lock);
Yuval Mintz494fff52018-02-28 23:29:34 +02001098 list_for_each_entry(c, &mrt->mfc_unres_queue, _c.list) {
Patrick McHardyc476efb2010-05-11 14:40:48 +02001099 if (ipv6_addr_equal(&c->mf6c_mcastgrp, &ipv6_hdr(skb)->daddr) &&
Patrick McHardyf30a77842010-05-11 14:40:51 +02001100 ipv6_addr_equal(&c->mf6c_origin, &ipv6_hdr(skb)->saddr)) {
1101 found = true;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001102 break;
Patrick McHardyf30a77842010-05-11 14:40:51 +02001103 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001104 }
1105
Patrick McHardyf30a77842010-05-11 14:40:51 +02001106 if (!found) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001107 /*
1108 * Create a new entry if allowable
1109 */
1110
Patrick McHardy6bd52142010-05-11 14:40:53 +02001111 if (atomic_read(&mrt->cache_resolve_queue_len) >= 10 ||
Patrick McHardyb5aa30b2010-05-11 14:40:50 +02001112 (c = ip6mr_cache_alloc_unres()) == NULL) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001113 spin_unlock_bh(&mfc_unres_lock);
1114
1115 kfree_skb(skb);
1116 return -ENOBUFS;
1117 }
1118
Yuval Mintz494fff52018-02-28 23:29:34 +02001119 /* Fill in the new cache entry */
1120 c->_c.mfc_parent = -1;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001121 c->mf6c_origin = ipv6_hdr(skb)->saddr;
1122 c->mf6c_mcastgrp = ipv6_hdr(skb)->daddr;
1123
1124 /*
1125 * Reflect first query at pim6sd
1126 */
Patrick McHardy6bd52142010-05-11 14:40:53 +02001127 err = ip6mr_cache_report(mrt, skb, mifi, MRT6MSG_NOCACHE);
Benjamin Thery8229efd2008-12-10 16:30:15 -08001128 if (err < 0) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001129 /* If the report failed throw the cache entry
1130 out - Brad Parker
1131 */
1132 spin_unlock_bh(&mfc_unres_lock);
1133
Benjamin Thery58701ad2008-12-10 16:22:34 -08001134 ip6mr_cache_free(c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001135 kfree_skb(skb);
1136 return err;
1137 }
1138
Patrick McHardy6bd52142010-05-11 14:40:53 +02001139 atomic_inc(&mrt->cache_resolve_queue_len);
Yuval Mintz494fff52018-02-28 23:29:34 +02001140 list_add(&c->_c.list, &mrt->mfc_unres_queue);
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00001141 mr6_netlink_event(mrt, c, RTM_NEWROUTE);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001142
Patrick McHardy6bd52142010-05-11 14:40:53 +02001143 ipmr_do_expire_process(mrt);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001144 }
1145
Yuval Mintz494fff52018-02-28 23:29:34 +02001146 /* See if we can append the packet */
1147 if (c->_c.mfc_un.unres.unresolved.qlen > 3) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001148 kfree_skb(skb);
1149 err = -ENOBUFS;
1150 } else {
Yuval Mintz494fff52018-02-28 23:29:34 +02001151 skb_queue_tail(&c->_c.mfc_un.unres.unresolved, skb);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001152 err = 0;
1153 }
1154
1155 spin_unlock_bh(&mfc_unres_lock);
1156 return err;
1157}
1158
1159/*
1160 * MFC6 cache manipulation by user space
1161 */
1162
Yuval Mintzb70432f2018-02-28 23:29:32 +02001163static int ip6mr_mfc_delete(struct mr_table *mrt, struct mf6cctl *mfc,
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001164 int parent)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001165{
Yuval Mintz87c418b2018-02-28 23:29:31 +02001166 struct mfc6_cache *c;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001167
Yuval Mintz87c418b2018-02-28 23:29:31 +02001168 /* The entries are added/deleted only under RTNL */
1169 rcu_read_lock();
1170 c = ip6mr_cache_find_parent(mrt, &mfc->mf6cc_origin.sin6_addr,
1171 &mfc->mf6cc_mcastgrp.sin6_addr, parent);
1172 rcu_read_unlock();
1173 if (!c)
1174 return -ENOENT;
Yuval Mintz494fff52018-02-28 23:29:34 +02001175 rhltable_remove(&mrt->mfc_hash, &c->_c.mnode, ip6mr_rht_params);
1176 list_del_rcu(&c->_c.list);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001177
Yuval Mintz87c418b2018-02-28 23:29:31 +02001178 mr6_netlink_event(mrt, c, RTM_DELROUTE);
1179 ip6mr_cache_free(c);
1180 return 0;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001181}
1182
1183static int ip6mr_device_event(struct notifier_block *this,
1184 unsigned long event, void *ptr)
1185{
Jiri Pirko351638e2013-05-28 01:30:21 +00001186 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
Benjamin Thery8229efd2008-12-10 16:30:15 -08001187 struct net *net = dev_net(dev);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001188 struct mr_table *mrt;
Yuval Mintz6853f212018-02-28 23:29:29 +02001189 struct vif_device *v;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001190 int ct;
1191
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001192 if (event != NETDEV_UNREGISTER)
1193 return NOTIFY_DONE;
1194
Patrick McHardyd1db2752010-05-11 14:40:55 +02001195 ip6mr_for_each_table(mrt, net) {
Yuval Mintzb70432f2018-02-28 23:29:32 +02001196 v = &mrt->vif_table[0];
Patrick McHardyd1db2752010-05-11 14:40:55 +02001197 for (ct = 0; ct < mrt->maxvif; ct++, v++) {
1198 if (v->dev == dev)
Nikolay Aleksandrov723b9292017-04-21 20:42:16 +03001199 mif6_delete(mrt, ct, 1, NULL);
Patrick McHardyd1db2752010-05-11 14:40:55 +02001200 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001201 }
Eric Dumazetc871e662009-10-28 04:48:11 +00001202
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001203 return NOTIFY_DONE;
1204}
1205
1206static struct notifier_block ip6_mr_notifier = {
1207 .notifier_call = ip6mr_device_event
1208};
1209
1210/*
1211 * Setup for IP multicast routing
1212 */
1213
Benjamin Thery4e168802008-12-10 16:15:08 -08001214static int __net_init ip6mr_net_init(struct net *net)
1215{
Patrick McHardyd1db2752010-05-11 14:40:55 +02001216 int err;
Patrick McHardyf30a77842010-05-11 14:40:51 +02001217
Patrick McHardyd1db2752010-05-11 14:40:55 +02001218 err = ip6mr_rules_init(net);
1219 if (err < 0)
Benjamin Thery4e168802008-12-10 16:15:08 -08001220 goto fail;
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001221
1222#ifdef CONFIG_PROC_FS
1223 err = -ENOMEM;
Gao fengd4beaa62013-02-18 01:34:54 +00001224 if (!proc_create("ip6_mr_vif", 0, net->proc_net, &ip6mr_vif_fops))
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001225 goto proc_vif_fail;
Gao fengd4beaa62013-02-18 01:34:54 +00001226 if (!proc_create("ip6_mr_cache", 0, net->proc_net, &ip6mr_mfc_fops))
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001227 goto proc_cache_fail;
1228#endif
Patrick McHardy6bd52142010-05-11 14:40:53 +02001229
Benjamin Thery4a6258a2008-12-10 16:24:07 -08001230 return 0;
1231
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001232#ifdef CONFIG_PROC_FS
1233proc_cache_fail:
Gao fengece31ff2013-02-18 01:34:56 +00001234 remove_proc_entry("ip6_mr_vif", net->proc_net);
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001235proc_vif_fail:
Patrick McHardyd1db2752010-05-11 14:40:55 +02001236 ip6mr_rules_exit(net);
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001237#endif
Benjamin Thery4e168802008-12-10 16:15:08 -08001238fail:
1239 return err;
1240}
1241
1242static void __net_exit ip6mr_net_exit(struct net *net)
1243{
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001244#ifdef CONFIG_PROC_FS
Gao fengece31ff2013-02-18 01:34:56 +00001245 remove_proc_entry("ip6_mr_cache", net->proc_net);
1246 remove_proc_entry("ip6_mr_vif", net->proc_net);
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001247#endif
Patrick McHardyd1db2752010-05-11 14:40:55 +02001248 ip6mr_rules_exit(net);
Benjamin Thery4e168802008-12-10 16:15:08 -08001249}
1250
1251static struct pernet_operations ip6mr_net_ops = {
1252 .init = ip6mr_net_init,
1253 .exit = ip6mr_net_exit,
Kirill Tkhaib01a59a2018-02-19 11:48:37 +03001254 .async = true,
Benjamin Thery4e168802008-12-10 16:15:08 -08001255};
1256
Wang Chen623d1a12008-07-03 12:13:30 +08001257int __init ip6_mr_init(void)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001258{
Wang Chen623d1a12008-07-03 12:13:30 +08001259 int err;
1260
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001261 mrt_cachep = kmem_cache_create("ip6_mrt_cache",
1262 sizeof(struct mfc6_cache),
1263 0, SLAB_HWCACHE_ALIGN,
1264 NULL);
1265 if (!mrt_cachep)
Wang Chen623d1a12008-07-03 12:13:30 +08001266 return -ENOMEM;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001267
Benjamin Thery4e168802008-12-10 16:15:08 -08001268 err = register_pernet_subsys(&ip6mr_net_ops);
1269 if (err)
1270 goto reg_pernet_fail;
1271
Wang Chen623d1a12008-07-03 12:13:30 +08001272 err = register_netdevice_notifier(&ip6_mr_notifier);
1273 if (err)
1274 goto reg_notif_fail;
Tom Goff403dbb92009-06-14 03:16:13 -07001275#ifdef CONFIG_IPV6_PIMSM_V2
1276 if (inet6_add_protocol(&pim6_protocol, IPPROTO_PIM) < 0) {
Joe Perchesf3213832012-05-15 14:11:53 +00001277 pr_err("%s: can't add PIM protocol\n", __func__);
Tom Goff403dbb92009-06-14 03:16:13 -07001278 err = -EAGAIN;
1279 goto add_proto_fail;
1280 }
1281#endif
Florian Westphala3fde2a2017-12-04 19:19:18 +01001282 err = rtnl_register_module(THIS_MODULE, RTNL_FAMILY_IP6MR, RTM_GETROUTE,
1283 NULL, ip6mr_rtm_dumproute, 0);
1284 if (err == 0)
1285 return 0;
1286
Tom Goff403dbb92009-06-14 03:16:13 -07001287#ifdef CONFIG_IPV6_PIMSM_V2
Florian Westphala3fde2a2017-12-04 19:19:18 +01001288 inet6_del_protocol(&pim6_protocol, IPPROTO_PIM);
Tom Goff403dbb92009-06-14 03:16:13 -07001289add_proto_fail:
1290 unregister_netdevice_notifier(&ip6_mr_notifier);
1291#endif
Benjamin Thery87b30a62008-11-10 16:34:11 -08001292reg_notif_fail:
Benjamin Thery4e168802008-12-10 16:15:08 -08001293 unregister_pernet_subsys(&ip6mr_net_ops);
1294reg_pernet_fail:
Benjamin Thery87b30a62008-11-10 16:34:11 -08001295 kmem_cache_destroy(mrt_cachep);
Wang Chen623d1a12008-07-03 12:13:30 +08001296 return err;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001297}
1298
Wang Chen623d1a12008-07-03 12:13:30 +08001299void ip6_mr_cleanup(void)
1300{
Duan Jiongffb13882014-11-19 09:35:39 +08001301 rtnl_unregister(RTNL_FAMILY_IP6MR, RTM_GETROUTE);
1302#ifdef CONFIG_IPV6_PIMSM_V2
1303 inet6_del_protocol(&pim6_protocol, IPPROTO_PIM);
1304#endif
Wang Chen623d1a12008-07-03 12:13:30 +08001305 unregister_netdevice_notifier(&ip6_mr_notifier);
Benjamin Thery4e168802008-12-10 16:15:08 -08001306 unregister_pernet_subsys(&ip6mr_net_ops);
Wang Chen623d1a12008-07-03 12:13:30 +08001307 kmem_cache_destroy(mrt_cachep);
1308}
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001309
Yuval Mintzb70432f2018-02-28 23:29:32 +02001310static int ip6mr_mfc_add(struct net *net, struct mr_table *mrt,
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001311 struct mf6cctl *mfc, int mrtsock, int parent)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001312{
Rami Rosen6ac7eb02008-04-10 12:40:10 +03001313 unsigned char ttls[MAXMIFS];
Yuval Mintz87c418b2018-02-28 23:29:31 +02001314 struct mfc6_cache *uc, *c;
Yuval Mintz494fff52018-02-28 23:29:34 +02001315 struct mr_mfc *_uc;
Yuval Mintz87c418b2018-02-28 23:29:31 +02001316 bool found;
1317 int i, err;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001318
Patrick McHardya50436f22010-03-17 06:04:14 +00001319 if (mfc->mf6cc_parent >= MAXMIFS)
1320 return -ENFILE;
1321
Rami Rosen6ac7eb02008-04-10 12:40:10 +03001322 memset(ttls, 255, MAXMIFS);
1323 for (i = 0; i < MAXMIFS; i++) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001324 if (IF_ISSET(i, &mfc->mf6cc_ifset))
1325 ttls[i] = 1;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001326 }
1327
Yuval Mintz87c418b2018-02-28 23:29:31 +02001328 /* The entries are added/deleted only under RTNL */
1329 rcu_read_lock();
1330 c = ip6mr_cache_find_parent(mrt, &mfc->mf6cc_origin.sin6_addr,
1331 &mfc->mf6cc_mcastgrp.sin6_addr, parent);
1332 rcu_read_unlock();
1333 if (c) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001334 write_lock_bh(&mrt_lock);
Yuval Mintz494fff52018-02-28 23:29:34 +02001335 c->_c.mfc_parent = mfc->mf6cc_parent;
1336 ip6mr_update_thresholds(mrt, &c->_c, ttls);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001337 if (!mrtsock)
Yuval Mintz494fff52018-02-28 23:29:34 +02001338 c->_c.mfc_flags |= MFC_STATIC;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001339 write_unlock_bh(&mrt_lock);
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00001340 mr6_netlink_event(mrt, c, RTM_NEWROUTE);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001341 return 0;
1342 }
1343
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001344 if (!ipv6_addr_any(&mfc->mf6cc_mcastgrp.sin6_addr) &&
1345 !ipv6_addr_is_multicast(&mfc->mf6cc_mcastgrp.sin6_addr))
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001346 return -EINVAL;
1347
Patrick McHardyb5aa30b2010-05-11 14:40:50 +02001348 c = ip6mr_cache_alloc();
Ian Morris63159f22015-03-29 14:00:04 +01001349 if (!c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001350 return -ENOMEM;
1351
1352 c->mf6c_origin = mfc->mf6cc_origin.sin6_addr;
1353 c->mf6c_mcastgrp = mfc->mf6cc_mcastgrp.sin6_addr;
Yuval Mintz494fff52018-02-28 23:29:34 +02001354 c->_c.mfc_parent = mfc->mf6cc_parent;
1355 ip6mr_update_thresholds(mrt, &c->_c, ttls);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001356 if (!mrtsock)
Yuval Mintz494fff52018-02-28 23:29:34 +02001357 c->_c.mfc_flags |= MFC_STATIC;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001358
Yuval Mintz494fff52018-02-28 23:29:34 +02001359 err = rhltable_insert_key(&mrt->mfc_hash, &c->cmparg, &c->_c.mnode,
Yuval Mintz87c418b2018-02-28 23:29:31 +02001360 ip6mr_rht_params);
1361 if (err) {
1362 pr_err("ip6mr: rhtable insert error %d\n", err);
1363 ip6mr_cache_free(c);
1364 return err;
1365 }
Yuval Mintz494fff52018-02-28 23:29:34 +02001366 list_add_tail_rcu(&c->_c.list, &mrt->mfc_cache_list);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001367
Yuval Mintz87c418b2018-02-28 23:29:31 +02001368 /* Check to see if we resolved a queued list. If so we
1369 * need to send on the frames and tidy up.
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001370 */
Patrick McHardyf30a77842010-05-11 14:40:51 +02001371 found = false;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001372 spin_lock_bh(&mfc_unres_lock);
Yuval Mintz494fff52018-02-28 23:29:34 +02001373 list_for_each_entry(_uc, &mrt->mfc_unres_queue, list) {
1374 uc = (struct mfc6_cache *)_uc;
Patrick McHardyc476efb2010-05-11 14:40:48 +02001375 if (ipv6_addr_equal(&uc->mf6c_origin, &c->mf6c_origin) &&
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001376 ipv6_addr_equal(&uc->mf6c_mcastgrp, &c->mf6c_mcastgrp)) {
Yuval Mintz494fff52018-02-28 23:29:34 +02001377 list_del(&_uc->list);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001378 atomic_dec(&mrt->cache_resolve_queue_len);
Patrick McHardyf30a77842010-05-11 14:40:51 +02001379 found = true;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001380 break;
1381 }
1382 }
Yuval Mintzb70432f2018-02-28 23:29:32 +02001383 if (list_empty(&mrt->mfc_unres_queue))
Patrick McHardy6bd52142010-05-11 14:40:53 +02001384 del_timer(&mrt->ipmr_expire_timer);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001385 spin_unlock_bh(&mfc_unres_lock);
1386
Patrick McHardyf30a77842010-05-11 14:40:51 +02001387 if (found) {
Patrick McHardy6bd52142010-05-11 14:40:53 +02001388 ip6mr_cache_resolve(net, mrt, uc, c);
Benjamin Thery58701ad2008-12-10 16:22:34 -08001389 ip6mr_cache_free(uc);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001390 }
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00001391 mr6_netlink_event(mrt, c, RTM_NEWROUTE);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001392 return 0;
1393}
1394
1395/*
1396 * Close the multicast socket, and clear the vif tables etc
1397 */
1398
Yuval Mintzb70432f2018-02-28 23:29:32 +02001399static void mroute_clean_tables(struct mr_table *mrt, bool all)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001400{
Yuval Mintz494fff52018-02-28 23:29:34 +02001401 struct mr_mfc *c, *tmp;
Eric Dumazetc871e662009-10-28 04:48:11 +00001402 LIST_HEAD(list);
Yuval Mintz87c418b2018-02-28 23:29:31 +02001403 int i;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001404
Yuval Mintz87c418b2018-02-28 23:29:31 +02001405 /* Shut down all active vif entries */
Patrick McHardy6bd52142010-05-11 14:40:53 +02001406 for (i = 0; i < mrt->maxvif; i++) {
Yuval Mintzb70432f2018-02-28 23:29:32 +02001407 if (!all && (mrt->vif_table[i].flags & VIFF_STATIC))
Nikolay Aleksandrov4c698042015-11-20 13:54:20 +01001408 continue;
Nikolay Aleksandrov723b9292017-04-21 20:42:16 +03001409 mif6_delete(mrt, i, 0, &list);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001410 }
Eric Dumazetc871e662009-10-28 04:48:11 +00001411 unregister_netdevice_many(&list);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001412
Yuval Mintz87c418b2018-02-28 23:29:31 +02001413 /* Wipe the cache */
Yuval Mintzb70432f2018-02-28 23:29:32 +02001414 list_for_each_entry_safe(c, tmp, &mrt->mfc_cache_list, list) {
Yuval Mintz87c418b2018-02-28 23:29:31 +02001415 if (!all && (c->mfc_flags & MFC_STATIC))
1416 continue;
Yuval Mintzb70432f2018-02-28 23:29:32 +02001417 rhltable_remove(&mrt->mfc_hash, &c->mnode, ip6mr_rht_params);
Yuval Mintz87c418b2018-02-28 23:29:31 +02001418 list_del_rcu(&c->list);
Yuval Mintz494fff52018-02-28 23:29:34 +02001419 mr6_netlink_event(mrt, (struct mfc6_cache *)c, RTM_DELROUTE);
1420 ip6mr_cache_free((struct mfc6_cache *)c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001421 }
1422
Patrick McHardy6bd52142010-05-11 14:40:53 +02001423 if (atomic_read(&mrt->cache_resolve_queue_len) != 0) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001424 spin_lock_bh(&mfc_unres_lock);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001425 list_for_each_entry_safe(c, tmp, &mrt->mfc_unres_queue, list) {
Patrick McHardyf30a77842010-05-11 14:40:51 +02001426 list_del(&c->list);
Yuval Mintz494fff52018-02-28 23:29:34 +02001427 mr6_netlink_event(mrt, (struct mfc6_cache *)c,
1428 RTM_DELROUTE);
1429 ip6mr_destroy_unres(mrt, (struct mfc6_cache *)c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001430 }
1431 spin_unlock_bh(&mfc_unres_lock);
1432 }
1433}
1434
Yuval Mintzb70432f2018-02-28 23:29:32 +02001435static int ip6mr_sk_init(struct mr_table *mrt, struct sock *sk)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001436{
1437 int err = 0;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001438 struct net *net = sock_net(sk);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001439
1440 rtnl_lock();
1441 write_lock_bh(&mrt_lock);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001442 if (rtnl_dereference(mrt->mroute_sk)) {
Eric Dumazet927265b2016-07-08 05:46:04 +02001443 err = -EADDRINUSE;
Yuval Mintz8571ab42018-02-28 23:29:30 +02001444 } else {
Yuval Mintzb70432f2018-02-28 23:29:32 +02001445 rcu_assign_pointer(mrt->mroute_sk, sk);
Eric Dumazeta366e302018-03-07 08:43:19 -08001446 sock_set_flag(sk, SOCK_RCU_FREE);
Yuval Mintz8571ab42018-02-28 23:29:30 +02001447 net->ipv6.devconf_all->mc_forwarding++;
Eric Dumazet927265b2016-07-08 05:46:04 +02001448 }
1449 write_unlock_bh(&mrt_lock);
1450
1451 if (!err)
David Ahern85b3daa2017-03-28 14:28:04 -07001452 inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
1453 NETCONFA_MC_FORWARDING,
Nicolas Dichteld67b8c62012-12-04 01:13:35 +00001454 NETCONFA_IFINDEX_ALL,
1455 net->ipv6.devconf_all);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001456 rtnl_unlock();
1457
1458 return err;
1459}
1460
1461int ip6mr_sk_done(struct sock *sk)
1462{
Patrick McHardyd1db2752010-05-11 14:40:55 +02001463 int err = -EACCES;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001464 struct net *net = sock_net(sk);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001465 struct mr_table *mrt;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001466
Francesco Ruggeri338d1822017-11-08 11:23:46 -08001467 if (sk->sk_type != SOCK_RAW ||
1468 inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
1469 return err;
1470
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001471 rtnl_lock();
Patrick McHardyd1db2752010-05-11 14:40:55 +02001472 ip6mr_for_each_table(mrt, net) {
Yuval Mintzb70432f2018-02-28 23:29:32 +02001473 if (sk == rtnl_dereference(mrt->mroute_sk)) {
Patrick McHardyd1db2752010-05-11 14:40:55 +02001474 write_lock_bh(&mrt_lock);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001475 RCU_INIT_POINTER(mrt->mroute_sk, NULL);
Eric Dumazeta366e302018-03-07 08:43:19 -08001476 /* Note that mroute_sk had SOCK_RCU_FREE set,
1477 * so the RCU grace period before sk freeing
1478 * is guaranteed by sk_destruct()
1479 */
Patrick McHardyd1db2752010-05-11 14:40:55 +02001480 net->ipv6.devconf_all->mc_forwarding--;
Eric Dumazet927265b2016-07-08 05:46:04 +02001481 write_unlock_bh(&mrt_lock);
David Ahern85b3daa2017-03-28 14:28:04 -07001482 inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
Nicolas Dichteld67b8c62012-12-04 01:13:35 +00001483 NETCONFA_MC_FORWARDING,
1484 NETCONFA_IFINDEX_ALL,
1485 net->ipv6.devconf_all);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001486
Nikolay Aleksandrov4c698042015-11-20 13:54:20 +01001487 mroute_clean_tables(mrt, false);
Patrick McHardyd1db2752010-05-11 14:40:55 +02001488 err = 0;
1489 break;
1490 }
1491 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001492 rtnl_unlock();
1493
1494 return err;
1495}
1496
Yuval Mintz8571ab42018-02-28 23:29:30 +02001497bool mroute6_is_socket(struct net *net, struct sk_buff *skb)
Patrick McHardy6bd52142010-05-11 14:40:53 +02001498{
Yuval Mintzb70432f2018-02-28 23:29:32 +02001499 struct mr_table *mrt;
David S. Miller4c9483b2011-03-12 16:22:43 -05001500 struct flowi6 fl6 = {
Julian Anastasove374c612014-04-28 10:51:56 +03001501 .flowi6_iif = skb->skb_iif ? : LOOPBACK_IFINDEX,
David S. Miller4c9483b2011-03-12 16:22:43 -05001502 .flowi6_oif = skb->dev->ifindex,
1503 .flowi6_mark = skb->mark,
Patrick McHardyd1db2752010-05-11 14:40:55 +02001504 };
1505
David S. Miller4c9483b2011-03-12 16:22:43 -05001506 if (ip6mr_fib_lookup(net, &fl6, &mrt) < 0)
Patrick McHardyd1db2752010-05-11 14:40:55 +02001507 return NULL;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001508
Yuval Mintzb70432f2018-02-28 23:29:32 +02001509 return rcu_access_pointer(mrt->mroute_sk);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001510}
Yuval Mintz8571ab42018-02-28 23:29:30 +02001511EXPORT_SYMBOL(mroute6_is_socket);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001512
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001513/*
1514 * Socket options and virtual interface manipulation. The whole
1515 * virtual interface system is a complete heap, but unfortunately
1516 * that's how BSD mrouted happens to think. Maybe one day with a proper
1517 * MOSPF/PIM router set up we can clean this up.
1518 */
1519
David S. Millerb7058842009-09-30 16:12:20 -07001520int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsigned int optlen)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001521{
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001522 int ret, parent = 0;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001523 struct mif6ctl vif;
1524 struct mf6cctl mfc;
1525 mifi_t mifi;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001526 struct net *net = sock_net(sk);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001527 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +02001528
Xin Long99253eb2017-02-24 16:29:06 +08001529 if (sk->sk_type != SOCK_RAW ||
1530 inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
1531 return -EOPNOTSUPP;
1532
Patrick McHardyd1db2752010-05-11 14:40:55 +02001533 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +01001534 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +02001535 return -ENOENT;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001536
1537 if (optname != MRT6_INIT) {
Yuval Mintzb70432f2018-02-28 23:29:32 +02001538 if (sk != rcu_access_pointer(mrt->mroute_sk) &&
Yuval Mintz8571ab42018-02-28 23:29:30 +02001539 !ns_capable(net->user_ns, CAP_NET_ADMIN))
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001540 return -EACCES;
1541 }
1542
1543 switch (optname) {
1544 case MRT6_INIT:
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001545 if (optlen < sizeof(int))
1546 return -EINVAL;
1547
Patrick McHardy6bd52142010-05-11 14:40:53 +02001548 return ip6mr_sk_init(mrt, sk);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001549
1550 case MRT6_DONE:
1551 return ip6mr_sk_done(sk);
1552
1553 case MRT6_ADD_MIF:
1554 if (optlen < sizeof(vif))
1555 return -EINVAL;
1556 if (copy_from_user(&vif, optval, sizeof(vif)))
1557 return -EFAULT;
Rami Rosen6ac7eb02008-04-10 12:40:10 +03001558 if (vif.mif6c_mifi >= MAXMIFS)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001559 return -ENFILE;
1560 rtnl_lock();
Yuval Mintz8571ab42018-02-28 23:29:30 +02001561 ret = mif6_add(net, mrt, &vif,
Yuval Mintzb70432f2018-02-28 23:29:32 +02001562 sk == rtnl_dereference(mrt->mroute_sk));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001563 rtnl_unlock();
1564 return ret;
1565
1566 case MRT6_DEL_MIF:
1567 if (optlen < sizeof(mifi_t))
1568 return -EINVAL;
1569 if (copy_from_user(&mifi, optval, sizeof(mifi_t)))
1570 return -EFAULT;
1571 rtnl_lock();
Nikolay Aleksandrov723b9292017-04-21 20:42:16 +03001572 ret = mif6_delete(mrt, mifi, 0, NULL);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001573 rtnl_unlock();
1574 return ret;
1575
1576 /*
1577 * Manipulate the forwarding caches. These live
1578 * in a sort of kernel/user symbiosis.
1579 */
1580 case MRT6_ADD_MFC:
1581 case MRT6_DEL_MFC:
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001582 parent = -1;
Gustavo A. R. Silva275757e62017-10-16 16:36:52 -05001583 /* fall through */
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001584 case MRT6_ADD_MFC_PROXY:
1585 case MRT6_DEL_MFC_PROXY:
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001586 if (optlen < sizeof(mfc))
1587 return -EINVAL;
1588 if (copy_from_user(&mfc, optval, sizeof(mfc)))
1589 return -EFAULT;
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001590 if (parent == 0)
1591 parent = mfc.mf6cc_parent;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001592 rtnl_lock();
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001593 if (optname == MRT6_DEL_MFC || optname == MRT6_DEL_MFC_PROXY)
1594 ret = ip6mr_mfc_delete(mrt, &mfc, parent);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001595 else
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001596 ret = ip6mr_mfc_add(net, mrt, &mfc,
Yuval Mintz8571ab42018-02-28 23:29:30 +02001597 sk ==
Yuval Mintzb70432f2018-02-28 23:29:32 +02001598 rtnl_dereference(mrt->mroute_sk),
Yuval Mintz8571ab42018-02-28 23:29:30 +02001599 parent);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001600 rtnl_unlock();
1601 return ret;
1602
1603 /*
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001604 * Control PIM assert (to activate pim will activate assert)
1605 */
1606 case MRT6_ASSERT:
1607 {
1608 int v;
Joe Perches03f52a02012-11-25 18:26:34 +00001609
1610 if (optlen != sizeof(v))
1611 return -EINVAL;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001612 if (get_user(v, (int __user *)optval))
1613 return -EFAULT;
Joe Perches53d68412012-11-25 09:35:30 +00001614 mrt->mroute_do_assert = v;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001615 return 0;
1616 }
1617
1618#ifdef CONFIG_IPV6_PIMSM_V2
1619 case MRT6_PIM:
1620 {
YOSHIFUJI Hideakia9f83bf2008-04-10 15:41:28 +09001621 int v;
Joe Perches03f52a02012-11-25 18:26:34 +00001622
1623 if (optlen != sizeof(v))
1624 return -EINVAL;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001625 if (get_user(v, (int __user *)optval))
1626 return -EFAULT;
1627 v = !!v;
1628 rtnl_lock();
1629 ret = 0;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001630 if (v != mrt->mroute_do_pim) {
1631 mrt->mroute_do_pim = v;
1632 mrt->mroute_do_assert = v;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001633 }
1634 rtnl_unlock();
1635 return ret;
1636 }
1637
1638#endif
Patrick McHardyd1db2752010-05-11 14:40:55 +02001639#ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
1640 case MRT6_TABLE:
1641 {
1642 u32 v;
1643
1644 if (optlen != sizeof(u32))
1645 return -EINVAL;
1646 if (get_user(v, (u32 __user *)optval))
1647 return -EFAULT;
Dan Carpenter75356a82013-01-23 20:38:34 +00001648 /* "pim6reg%u" should not exceed 16 bytes (IFNAMSIZ) */
1649 if (v != RT_TABLE_DEFAULT && v >= 100000000)
1650 return -EINVAL;
Yuval Mintzb70432f2018-02-28 23:29:32 +02001651 if (sk == rcu_access_pointer(mrt->mroute_sk))
Patrick McHardyd1db2752010-05-11 14:40:55 +02001652 return -EBUSY;
1653
1654 rtnl_lock();
1655 ret = 0;
1656 if (!ip6mr_new_table(net, v))
1657 ret = -ENOMEM;
1658 raw6_sk(sk)->ip6mr_table = v;
1659 rtnl_unlock();
1660 return ret;
1661 }
1662#endif
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001663 /*
Rami Rosen7d120c52008-04-23 14:35:13 +03001664 * Spurious command, or MRT6_VERSION which you cannot
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001665 * set.
1666 */
1667 default:
1668 return -ENOPROTOOPT;
1669 }
1670}
1671
1672/*
1673 * Getsock opt support for the multicast routing system.
1674 */
1675
1676int ip6_mroute_getsockopt(struct sock *sk, int optname, char __user *optval,
1677 int __user *optlen)
1678{
1679 int olr;
1680 int val;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001681 struct net *net = sock_net(sk);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001682 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +02001683
Xin Long99253eb2017-02-24 16:29:06 +08001684 if (sk->sk_type != SOCK_RAW ||
1685 inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
1686 return -EOPNOTSUPP;
1687
Patrick McHardyd1db2752010-05-11 14:40:55 +02001688 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +01001689 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +02001690 return -ENOENT;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001691
1692 switch (optname) {
1693 case MRT6_VERSION:
1694 val = 0x0305;
1695 break;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001696#ifdef CONFIG_IPV6_PIMSM_V2
1697 case MRT6_PIM:
Patrick McHardy6bd52142010-05-11 14:40:53 +02001698 val = mrt->mroute_do_pim;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001699 break;
1700#endif
1701 case MRT6_ASSERT:
Patrick McHardy6bd52142010-05-11 14:40:53 +02001702 val = mrt->mroute_do_assert;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001703 break;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001704 default:
1705 return -ENOPROTOOPT;
1706 }
1707
1708 if (get_user(olr, optlen))
1709 return -EFAULT;
1710
1711 olr = min_t(int, olr, sizeof(int));
1712 if (olr < 0)
1713 return -EINVAL;
1714
1715 if (put_user(olr, optlen))
1716 return -EFAULT;
1717 if (copy_to_user(optval, &val, olr))
1718 return -EFAULT;
1719 return 0;
1720}
1721
1722/*
1723 * The IP multicast ioctl support routines.
1724 */
1725
1726int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg)
1727{
1728 struct sioc_sg_req6 sr;
1729 struct sioc_mif_req6 vr;
Yuval Mintz6853f212018-02-28 23:29:29 +02001730 struct vif_device *vif;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001731 struct mfc6_cache *c;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001732 struct net *net = sock_net(sk);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001733 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +02001734
1735 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +01001736 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +02001737 return -ENOENT;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001738
1739 switch (cmd) {
1740 case SIOCGETMIFCNT_IN6:
1741 if (copy_from_user(&vr, arg, sizeof(vr)))
1742 return -EFAULT;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001743 if (vr.mifi >= mrt->maxvif)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001744 return -EINVAL;
1745 read_lock(&mrt_lock);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001746 vif = &mrt->vif_table[vr.mifi];
1747 if (VIF_EXISTS(mrt, vr.mifi)) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001748 vr.icount = vif->pkt_in;
1749 vr.ocount = vif->pkt_out;
1750 vr.ibytes = vif->bytes_in;
1751 vr.obytes = vif->bytes_out;
1752 read_unlock(&mrt_lock);
1753
1754 if (copy_to_user(arg, &vr, sizeof(vr)))
1755 return -EFAULT;
1756 return 0;
1757 }
1758 read_unlock(&mrt_lock);
1759 return -EADDRNOTAVAIL;
1760 case SIOCGETSGCNT_IN6:
1761 if (copy_from_user(&sr, arg, sizeof(sr)))
1762 return -EFAULT;
1763
Yuval Mintz87c418b2018-02-28 23:29:31 +02001764 rcu_read_lock();
Patrick McHardy6bd52142010-05-11 14:40:53 +02001765 c = ip6mr_cache_find(mrt, &sr.src.sin6_addr, &sr.grp.sin6_addr);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001766 if (c) {
Yuval Mintz494fff52018-02-28 23:29:34 +02001767 sr.pktcnt = c->_c.mfc_un.res.pkt;
1768 sr.bytecnt = c->_c.mfc_un.res.bytes;
1769 sr.wrong_if = c->_c.mfc_un.res.wrong_if;
Yuval Mintz87c418b2018-02-28 23:29:31 +02001770 rcu_read_unlock();
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001771
1772 if (copy_to_user(arg, &sr, sizeof(sr)))
1773 return -EFAULT;
1774 return 0;
1775 }
Yuval Mintz87c418b2018-02-28 23:29:31 +02001776 rcu_read_unlock();
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001777 return -EADDRNOTAVAIL;
1778 default:
1779 return -ENOIOCTLCMD;
1780 }
1781}
1782
David S. Millere2d57762011-02-03 17:59:32 -08001783#ifdef CONFIG_COMPAT
1784struct compat_sioc_sg_req6 {
1785 struct sockaddr_in6 src;
1786 struct sockaddr_in6 grp;
1787 compat_ulong_t pktcnt;
1788 compat_ulong_t bytecnt;
1789 compat_ulong_t wrong_if;
1790};
1791
1792struct compat_sioc_mif_req6 {
1793 mifi_t mifi;
1794 compat_ulong_t icount;
1795 compat_ulong_t ocount;
1796 compat_ulong_t ibytes;
1797 compat_ulong_t obytes;
1798};
1799
1800int ip6mr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg)
1801{
1802 struct compat_sioc_sg_req6 sr;
1803 struct compat_sioc_mif_req6 vr;
Yuval Mintz6853f212018-02-28 23:29:29 +02001804 struct vif_device *vif;
David S. Millere2d57762011-02-03 17:59:32 -08001805 struct mfc6_cache *c;
1806 struct net *net = sock_net(sk);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001807 struct mr_table *mrt;
David S. Millere2d57762011-02-03 17:59:32 -08001808
1809 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +01001810 if (!mrt)
David S. Millere2d57762011-02-03 17:59:32 -08001811 return -ENOENT;
1812
1813 switch (cmd) {
1814 case SIOCGETMIFCNT_IN6:
1815 if (copy_from_user(&vr, arg, sizeof(vr)))
1816 return -EFAULT;
1817 if (vr.mifi >= mrt->maxvif)
1818 return -EINVAL;
1819 read_lock(&mrt_lock);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001820 vif = &mrt->vif_table[vr.mifi];
1821 if (VIF_EXISTS(mrt, vr.mifi)) {
David S. Millere2d57762011-02-03 17:59:32 -08001822 vr.icount = vif->pkt_in;
1823 vr.ocount = vif->pkt_out;
1824 vr.ibytes = vif->bytes_in;
1825 vr.obytes = vif->bytes_out;
1826 read_unlock(&mrt_lock);
1827
1828 if (copy_to_user(arg, &vr, sizeof(vr)))
1829 return -EFAULT;
1830 return 0;
1831 }
1832 read_unlock(&mrt_lock);
1833 return -EADDRNOTAVAIL;
1834 case SIOCGETSGCNT_IN6:
1835 if (copy_from_user(&sr, arg, sizeof(sr)))
1836 return -EFAULT;
1837
Yuval Mintz87c418b2018-02-28 23:29:31 +02001838 rcu_read_lock();
David S. Millere2d57762011-02-03 17:59:32 -08001839 c = ip6mr_cache_find(mrt, &sr.src.sin6_addr, &sr.grp.sin6_addr);
1840 if (c) {
Yuval Mintz494fff52018-02-28 23:29:34 +02001841 sr.pktcnt = c->_c.mfc_un.res.pkt;
1842 sr.bytecnt = c->_c.mfc_un.res.bytes;
1843 sr.wrong_if = c->_c.mfc_un.res.wrong_if;
Yuval Mintz87c418b2018-02-28 23:29:31 +02001844 rcu_read_unlock();
David S. Millere2d57762011-02-03 17:59:32 -08001845
1846 if (copy_to_user(arg, &sr, sizeof(sr)))
1847 return -EFAULT;
1848 return 0;
1849 }
Yuval Mintz87c418b2018-02-28 23:29:31 +02001850 rcu_read_unlock();
David S. Millere2d57762011-02-03 17:59:32 -08001851 return -EADDRNOTAVAIL;
1852 default:
1853 return -ENOIOCTLCMD;
1854 }
1855}
1856#endif
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001857
Eric W. Biederman0c4b51f2015-09-15 20:04:18 -05001858static inline int ip6mr_forward2_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001859{
Eric Dumazet1d015502016-04-27 16:44:40 -07001860 __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
1861 IPSTATS_MIB_OUTFORWDATAGRAMS);
1862 __IP6_ADD_STATS(net, ip6_dst_idev(skb_dst(skb)),
1863 IPSTATS_MIB_OUTOCTETS, skb->len);
Eric W. Biederman13206b62015-10-07 16:48:35 -05001864 return dst_output(net, sk, skb);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001865}
1866
1867/*
1868 * Processing handlers for ip6mr_forward
1869 */
1870
Yuval Mintzb70432f2018-02-28 23:29:32 +02001871static int ip6mr_forward2(struct net *net, struct mr_table *mrt,
Patrick McHardy6bd52142010-05-11 14:40:53 +02001872 struct sk_buff *skb, struct mfc6_cache *c, int vifi)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001873{
1874 struct ipv6hdr *ipv6h;
Yuval Mintzb70432f2018-02-28 23:29:32 +02001875 struct vif_device *vif = &mrt->vif_table[vifi];
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001876 struct net_device *dev;
1877 struct dst_entry *dst;
David S. Miller4c9483b2011-03-12 16:22:43 -05001878 struct flowi6 fl6;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001879
Ian Morris63159f22015-03-29 14:00:04 +01001880 if (!vif->dev)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001881 goto out_free;
1882
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001883#ifdef CONFIG_IPV6_PIMSM_V2
1884 if (vif->flags & MIFF_REGISTER) {
1885 vif->pkt_out++;
1886 vif->bytes_out += skb->len;
Pavel Emelyanovdc58c782008-05-21 14:17:54 -07001887 vif->dev->stats.tx_bytes += skb->len;
1888 vif->dev->stats.tx_packets++;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001889 ip6mr_cache_report(mrt, skb, vifi, MRT6MSG_WHOLEPKT);
Ilpo Järvinen8da73b72008-12-14 23:15:49 -08001890 goto out_free;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001891 }
1892#endif
1893
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001894 ipv6h = ipv6_hdr(skb);
1895
David S. Miller4c9483b2011-03-12 16:22:43 -05001896 fl6 = (struct flowi6) {
1897 .flowi6_oif = vif->link,
1898 .daddr = ipv6h->daddr,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001899 };
1900
David S. Miller4c9483b2011-03-12 16:22:43 -05001901 dst = ip6_route_output(net, NULL, &fl6);
RongQing.Li5095d642012-02-21 22:10:49 +00001902 if (dst->error) {
1903 dst_release(dst);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001904 goto out_free;
RongQing.Li5095d642012-02-21 22:10:49 +00001905 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001906
Eric Dumazetadf30902009-06-02 05:19:30 +00001907 skb_dst_drop(skb);
1908 skb_dst_set(skb, dst);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001909
1910 /*
1911 * RFC1584 teaches, that DVMRP/PIM router must deliver packets locally
1912 * not only before forwarding, but after forwarding on all output
1913 * interfaces. It is clear, if mrouter runs a multicasting
1914 * program, it should receive packets not depending to what interface
1915 * program is joined.
1916 * If we will not make it, the program will have to join on all
1917 * interfaces. On the other hand, multihoming host (or router, but
1918 * not mrouter) cannot join to more than one interface - it will
1919 * result in receiving multiple packets.
1920 */
1921 dev = vif->dev;
1922 skb->dev = dev;
1923 vif->pkt_out++;
1924 vif->bytes_out += skb->len;
1925
1926 /* We are about to write */
1927 /* XXX: extension headers? */
1928 if (skb_cow(skb, sizeof(*ipv6h) + LL_RESERVED_SPACE(dev)))
1929 goto out_free;
1930
1931 ipv6h = ipv6_hdr(skb);
1932 ipv6h->hop_limit--;
1933
1934 IP6CB(skb)->flags |= IP6SKB_FORWARDED;
1935
Eric W. Biederman29a26a52015-09-15 20:04:16 -05001936 return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD,
1937 net, NULL, skb, skb->dev, dev,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001938 ip6mr_forward2_finish);
1939
1940out_free:
1941 kfree_skb(skb);
1942 return 0;
1943}
1944
Yuval Mintzb70432f2018-02-28 23:29:32 +02001945static int ip6mr_find_vif(struct mr_table *mrt, struct net_device *dev)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001946{
1947 int ct;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001948
1949 for (ct = mrt->maxvif - 1; ct >= 0; ct--) {
Yuval Mintzb70432f2018-02-28 23:29:32 +02001950 if (mrt->vif_table[ct].dev == dev)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001951 break;
1952 }
1953 return ct;
1954}
1955
Yuval Mintzb70432f2018-02-28 23:29:32 +02001956static void ip6_mr_forward(struct net *net, struct mr_table *mrt,
Yuval Mintz494fff52018-02-28 23:29:34 +02001957 struct sk_buff *skb, struct mfc6_cache *c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001958{
1959 int psend = -1;
1960 int vif, ct;
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001961 int true_vifi = ip6mr_find_vif(mrt, skb->dev);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001962
Yuval Mintz494fff52018-02-28 23:29:34 +02001963 vif = c->_c.mfc_parent;
1964 c->_c.mfc_un.res.pkt++;
1965 c->_c.mfc_un.res.bytes += skb->len;
1966 c->_c.mfc_un.res.lastuse = jiffies;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001967
Yuval Mintz494fff52018-02-28 23:29:34 +02001968 if (ipv6_addr_any(&c->mf6c_origin) && true_vifi >= 0) {
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001969 struct mfc6_cache *cache_proxy;
1970
Fabian Frederick40dc2ca2014-10-29 10:00:26 +01001971 /* For an (*,G) entry, we only check that the incoming
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001972 * interface is part of the static tree.
1973 */
Yuval Mintz87c418b2018-02-28 23:29:31 +02001974 rcu_read_lock();
Yuval Mintz845c9a72018-02-28 23:29:35 +02001975 cache_proxy = mr_mfc_find_any_parent(mrt, vif);
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001976 if (cache_proxy &&
Yuval Mintz494fff52018-02-28 23:29:34 +02001977 cache_proxy->_c.mfc_un.res.ttls[true_vifi] < 255) {
Yuval Mintz87c418b2018-02-28 23:29:31 +02001978 rcu_read_unlock();
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001979 goto forward;
Yuval Mintz87c418b2018-02-28 23:29:31 +02001980 }
1981 rcu_read_unlock();
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001982 }
1983
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001984 /*
1985 * Wrong interface: drop packet and (maybe) send PIM assert.
1986 */
Yuval Mintzb70432f2018-02-28 23:29:32 +02001987 if (mrt->vif_table[vif].dev != skb->dev) {
Yuval Mintz494fff52018-02-28 23:29:34 +02001988 c->_c.mfc_un.res.wrong_if++;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001989
Patrick McHardy6bd52142010-05-11 14:40:53 +02001990 if (true_vifi >= 0 && mrt->mroute_do_assert &&
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001991 /* pimsm uses asserts, when switching from RPT to SPT,
1992 so that we cannot check that packet arrived on an oif.
1993 It is bad, but otherwise we would need to move pretty
1994 large chunk of pimd to kernel. Ough... --ANK
1995 */
Patrick McHardy6bd52142010-05-11 14:40:53 +02001996 (mrt->mroute_do_pim ||
Yuval Mintz494fff52018-02-28 23:29:34 +02001997 c->_c.mfc_un.res.ttls[true_vifi] < 255) &&
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001998 time_after(jiffies,
Yuval Mintz494fff52018-02-28 23:29:34 +02001999 c->_c.mfc_un.res.last_assert +
2000 MFC_ASSERT_THRESH)) {
2001 c->_c.mfc_un.res.last_assert = jiffies;
Patrick McHardy6bd52142010-05-11 14:40:53 +02002002 ip6mr_cache_report(mrt, skb, true_vifi, MRT6MSG_WRONGMIF);
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002003 }
2004 goto dont_forward;
2005 }
2006
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002007forward:
Yuval Mintzb70432f2018-02-28 23:29:32 +02002008 mrt->vif_table[vif].pkt_in++;
2009 mrt->vif_table[vif].bytes_in += skb->len;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002010
2011 /*
2012 * Forward the frame
2013 */
Yuval Mintz494fff52018-02-28 23:29:34 +02002014 if (ipv6_addr_any(&c->mf6c_origin) &&
2015 ipv6_addr_any(&c->mf6c_mcastgrp)) {
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002016 if (true_vifi >= 0 &&
Yuval Mintz494fff52018-02-28 23:29:34 +02002017 true_vifi != c->_c.mfc_parent &&
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002018 ipv6_hdr(skb)->hop_limit >
Yuval Mintz494fff52018-02-28 23:29:34 +02002019 c->_c.mfc_un.res.ttls[c->_c.mfc_parent]) {
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002020 /* It's an (*,*) entry and the packet is not coming from
2021 * the upstream: forward the packet to the upstream
2022 * only.
2023 */
Yuval Mintz494fff52018-02-28 23:29:34 +02002024 psend = c->_c.mfc_parent;
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002025 goto last_forward;
2026 }
2027 goto dont_forward;
2028 }
Yuval Mintz494fff52018-02-28 23:29:34 +02002029 for (ct = c->_c.mfc_un.res.maxvif - 1;
2030 ct >= c->_c.mfc_un.res.minvif; ct--) {
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002031 /* For (*,G) entry, don't forward to the incoming interface */
Yuval Mintz494fff52018-02-28 23:29:34 +02002032 if ((!ipv6_addr_any(&c->mf6c_origin) || ct != true_vifi) &&
2033 ipv6_hdr(skb)->hop_limit > c->_c.mfc_un.res.ttls[ct]) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002034 if (psend != -1) {
2035 struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
2036 if (skb2)
Yuval Mintz494fff52018-02-28 23:29:34 +02002037 ip6mr_forward2(net, mrt, skb2,
2038 c, psend);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002039 }
2040 psend = ct;
2041 }
2042 }
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002043last_forward:
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002044 if (psend != -1) {
Yuval Mintz494fff52018-02-28 23:29:34 +02002045 ip6mr_forward2(net, mrt, skb, c, psend);
Rami Rosen2b52c3a2013-07-21 03:00:31 +03002046 return;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002047 }
2048
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002049dont_forward:
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002050 kfree_skb(skb);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002051}
2052
2053
2054/*
2055 * Multicast packets for forwarding arrive here
2056 */
2057
2058int ip6_mr_input(struct sk_buff *skb)
2059{
2060 struct mfc6_cache *cache;
Benjamin Thery8229efd2008-12-10 16:30:15 -08002061 struct net *net = dev_net(skb->dev);
Yuval Mintzb70432f2018-02-28 23:29:32 +02002062 struct mr_table *mrt;
David S. Miller4c9483b2011-03-12 16:22:43 -05002063 struct flowi6 fl6 = {
2064 .flowi6_iif = skb->dev->ifindex,
2065 .flowi6_mark = skb->mark,
Patrick McHardyd1db2752010-05-11 14:40:55 +02002066 };
2067 int err;
2068
David S. Miller4c9483b2011-03-12 16:22:43 -05002069 err = ip6mr_fib_lookup(net, &fl6, &mrt);
Ben Greear2015de52011-09-27 15:16:08 -04002070 if (err < 0) {
2071 kfree_skb(skb);
Patrick McHardyd1db2752010-05-11 14:40:55 +02002072 return err;
Ben Greear2015de52011-09-27 15:16:08 -04002073 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002074
2075 read_lock(&mrt_lock);
Patrick McHardy6bd52142010-05-11 14:40:53 +02002076 cache = ip6mr_cache_find(mrt,
Benjamin Thery8229efd2008-12-10 16:30:15 -08002077 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr);
Ian Morris63159f22015-03-29 14:00:04 +01002078 if (!cache) {
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002079 int vif = ip6mr_find_vif(mrt, skb->dev);
2080
2081 if (vif >= 0)
2082 cache = ip6mr_cache_find_any(mrt,
2083 &ipv6_hdr(skb)->daddr,
2084 vif);
2085 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002086
2087 /*
2088 * No usable cache entry
2089 */
Ian Morris63159f22015-03-29 14:00:04 +01002090 if (!cache) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002091 int vif;
2092
Patrick McHardy6bd52142010-05-11 14:40:53 +02002093 vif = ip6mr_find_vif(mrt, skb->dev);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002094 if (vif >= 0) {
Patrick McHardy6bd52142010-05-11 14:40:53 +02002095 int err = ip6mr_cache_unresolved(mrt, vif, skb);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002096 read_unlock(&mrt_lock);
2097
2098 return err;
2099 }
2100 read_unlock(&mrt_lock);
2101 kfree_skb(skb);
2102 return -ENODEV;
2103 }
2104
Patrick McHardy6bd52142010-05-11 14:40:53 +02002105 ip6_mr_forward(net, mrt, skb, cache);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002106
2107 read_unlock(&mrt_lock);
2108
2109 return 0;
2110}
2111
Nikolay Aleksandrov2cf75072016-09-25 23:08:31 +02002112int ip6mr_get_route(struct net *net, struct sk_buff *skb, struct rtmsg *rtm,
David Ahernfd61c6b2017-01-17 15:51:07 -08002113 u32 portid)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002114{
2115 int err;
Yuval Mintzb70432f2018-02-28 23:29:32 +02002116 struct mr_table *mrt;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002117 struct mfc6_cache *cache;
Eric Dumazetadf30902009-06-02 05:19:30 +00002118 struct rt6_info *rt = (struct rt6_info *)skb_dst(skb);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002119
Patrick McHardyd1db2752010-05-11 14:40:55 +02002120 mrt = ip6mr_get_table(net, RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +01002121 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +02002122 return -ENOENT;
2123
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002124 read_lock(&mrt_lock);
Patrick McHardy6bd52142010-05-11 14:40:53 +02002125 cache = ip6mr_cache_find(mrt, &rt->rt6i_src.addr, &rt->rt6i_dst.addr);
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002126 if (!cache && skb->dev) {
2127 int vif = ip6mr_find_vif(mrt, skb->dev);
2128
2129 if (vif >= 0)
2130 cache = ip6mr_cache_find_any(mrt, &rt->rt6i_dst.addr,
2131 vif);
2132 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002133
2134 if (!cache) {
2135 struct sk_buff *skb2;
2136 struct ipv6hdr *iph;
2137 struct net_device *dev;
2138 int vif;
2139
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002140 dev = skb->dev;
Ian Morris63159f22015-03-29 14:00:04 +01002141 if (!dev || (vif = ip6mr_find_vif(mrt, dev)) < 0) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002142 read_unlock(&mrt_lock);
2143 return -ENODEV;
2144 }
2145
2146 /* really correct? */
2147 skb2 = alloc_skb(sizeof(struct ipv6hdr), GFP_ATOMIC);
2148 if (!skb2) {
2149 read_unlock(&mrt_lock);
2150 return -ENOMEM;
2151 }
2152
Nikolay Aleksandrov2cf75072016-09-25 23:08:31 +02002153 NETLINK_CB(skb2).portid = portid;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002154 skb_reset_transport_header(skb2);
2155
2156 skb_put(skb2, sizeof(struct ipv6hdr));
2157 skb_reset_network_header(skb2);
2158
2159 iph = ipv6_hdr(skb2);
2160 iph->version = 0;
2161 iph->priority = 0;
2162 iph->flow_lbl[0] = 0;
2163 iph->flow_lbl[1] = 0;
2164 iph->flow_lbl[2] = 0;
2165 iph->payload_len = 0;
2166 iph->nexthdr = IPPROTO_NONE;
2167 iph->hop_limit = 0;
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +00002168 iph->saddr = rt->rt6i_src.addr;
2169 iph->daddr = rt->rt6i_dst.addr;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002170
Patrick McHardy6bd52142010-05-11 14:40:53 +02002171 err = ip6mr_cache_unresolved(mrt, vif, skb2);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002172 read_unlock(&mrt_lock);
2173
2174 return err;
2175 }
2176
Yuval Mintz7b0db852018-02-28 23:29:39 +02002177 err = mr_fill_mroute(mrt, skb, &cache->_c, rtm);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002178 read_unlock(&mrt_lock);
2179 return err;
2180}
2181
Yuval Mintzb70432f2018-02-28 23:29:32 +02002182static int ip6mr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
Nicolas Dichtelf5183382014-03-19 17:47:51 +01002183 u32 portid, u32 seq, struct mfc6_cache *c, int cmd,
2184 int flags)
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002185{
2186 struct nlmsghdr *nlh;
2187 struct rtmsg *rtm;
Nicolas Dichtel1eb99af2012-12-04 01:13:39 +00002188 int err;
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002189
Nicolas Dichtelf5183382014-03-19 17:47:51 +01002190 nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rtm), flags);
Ian Morris63159f22015-03-29 14:00:04 +01002191 if (!nlh)
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002192 return -EMSGSIZE;
2193
2194 rtm = nlmsg_data(nlh);
Nicolas Dichtel193c1e42012-12-04 01:01:49 +00002195 rtm->rtm_family = RTNL_FAMILY_IP6MR;
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002196 rtm->rtm_dst_len = 128;
2197 rtm->rtm_src_len = 128;
2198 rtm->rtm_tos = 0;
2199 rtm->rtm_table = mrt->id;
David S. Millerc78679e2012-04-01 20:27:33 -04002200 if (nla_put_u32(skb, RTA_TABLE, mrt->id))
2201 goto nla_put_failure;
Nicolas Dichtel1eb99af2012-12-04 01:13:39 +00002202 rtm->rtm_type = RTN_MULTICAST;
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002203 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
Yuval Mintz494fff52018-02-28 23:29:34 +02002204 if (c->_c.mfc_flags & MFC_STATIC)
Nicolas Dichtel9a68ac72012-12-04 01:13:38 +00002205 rtm->rtm_protocol = RTPROT_STATIC;
2206 else
2207 rtm->rtm_protocol = RTPROT_MROUTED;
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002208 rtm->rtm_flags = 0;
2209
Jiri Benc930345e2015-03-29 16:59:25 +02002210 if (nla_put_in6_addr(skb, RTA_SRC, &c->mf6c_origin) ||
2211 nla_put_in6_addr(skb, RTA_DST, &c->mf6c_mcastgrp))
David S. Millerc78679e2012-04-01 20:27:33 -04002212 goto nla_put_failure;
Yuval Mintz7b0db852018-02-28 23:29:39 +02002213 err = mr_fill_mroute(mrt, skb, &c->_c, rtm);
Nicolas Dichtel1eb99af2012-12-04 01:13:39 +00002214 /* do not break the dump if cache is unresolved */
2215 if (err < 0 && err != -ENOENT)
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002216 goto nla_put_failure;
2217
Johannes Berg053c0952015-01-16 22:09:00 +01002218 nlmsg_end(skb, nlh);
2219 return 0;
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002220
2221nla_put_failure:
2222 nlmsg_cancel(skb, nlh);
2223 return -EMSGSIZE;
2224}
2225
Yuval Mintz7b0db852018-02-28 23:29:39 +02002226static int _ip6mr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
2227 u32 portid, u32 seq, struct mr_mfc *c,
2228 int cmd, int flags)
2229{
2230 return ip6mr_fill_mroute(mrt, skb, portid, seq, (struct mfc6_cache *)c,
2231 cmd, flags);
2232}
2233
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002234static int mr6_msgsize(bool unresolved, int maxvif)
2235{
2236 size_t len =
2237 NLMSG_ALIGN(sizeof(struct rtmsg))
2238 + nla_total_size(4) /* RTA_TABLE */
2239 + nla_total_size(sizeof(struct in6_addr)) /* RTA_SRC */
2240 + nla_total_size(sizeof(struct in6_addr)) /* RTA_DST */
2241 ;
2242
2243 if (!unresolved)
2244 len = len
2245 + nla_total_size(4) /* RTA_IIF */
2246 + nla_total_size(0) /* RTA_MULTIPATH */
2247 + maxvif * NLA_ALIGN(sizeof(struct rtnexthop))
2248 /* RTA_MFC_STATS */
Nicolas Dichtel3d6b66c2016-04-21 18:58:27 +02002249 + nla_total_size_64bit(sizeof(struct rta_mfc_stats))
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002250 ;
2251
2252 return len;
2253}
2254
Yuval Mintzb70432f2018-02-28 23:29:32 +02002255static void mr6_netlink_event(struct mr_table *mrt, struct mfc6_cache *mfc,
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002256 int cmd)
2257{
2258 struct net *net = read_pnet(&mrt->net);
2259 struct sk_buff *skb;
2260 int err = -ENOBUFS;
2261
Yuval Mintz494fff52018-02-28 23:29:34 +02002262 skb = nlmsg_new(mr6_msgsize(mfc->_c.mfc_parent >= MAXMIFS, mrt->maxvif),
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002263 GFP_ATOMIC);
Ian Morris63159f22015-03-29 14:00:04 +01002264 if (!skb)
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002265 goto errout;
2266
Nicolas Dichtelf5183382014-03-19 17:47:51 +01002267 err = ip6mr_fill_mroute(mrt, skb, 0, 0, mfc, cmd, 0);
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002268 if (err < 0)
2269 goto errout;
2270
2271 rtnl_notify(skb, net, 0, RTNLGRP_IPV6_MROUTE, NULL, GFP_ATOMIC);
2272 return;
2273
2274errout:
2275 kfree_skb(skb);
2276 if (err < 0)
2277 rtnl_set_sk_err(net, RTNLGRP_IPV6_MROUTE, err);
2278}
2279
Julien Gomesdd12d15c2017-06-20 13:54:18 -07002280static size_t mrt6msg_netlink_msgsize(size_t payloadlen)
2281{
2282 size_t len =
2283 NLMSG_ALIGN(sizeof(struct rtgenmsg))
2284 + nla_total_size(1) /* IP6MRA_CREPORT_MSGTYPE */
2285 + nla_total_size(4) /* IP6MRA_CREPORT_MIF_ID */
2286 /* IP6MRA_CREPORT_SRC_ADDR */
2287 + nla_total_size(sizeof(struct in6_addr))
2288 /* IP6MRA_CREPORT_DST_ADDR */
2289 + nla_total_size(sizeof(struct in6_addr))
2290 /* IP6MRA_CREPORT_PKT */
2291 + nla_total_size(payloadlen)
2292 ;
2293
2294 return len;
2295}
2296
Yuval Mintzb70432f2018-02-28 23:29:32 +02002297static void mrt6msg_netlink_event(struct mr_table *mrt, struct sk_buff *pkt)
Julien Gomesdd12d15c2017-06-20 13:54:18 -07002298{
2299 struct net *net = read_pnet(&mrt->net);
2300 struct nlmsghdr *nlh;
2301 struct rtgenmsg *rtgenm;
2302 struct mrt6msg *msg;
2303 struct sk_buff *skb;
2304 struct nlattr *nla;
2305 int payloadlen;
2306
2307 payloadlen = pkt->len - sizeof(struct mrt6msg);
2308 msg = (struct mrt6msg *)skb_transport_header(pkt);
2309
2310 skb = nlmsg_new(mrt6msg_netlink_msgsize(payloadlen), GFP_ATOMIC);
2311 if (!skb)
2312 goto errout;
2313
2314 nlh = nlmsg_put(skb, 0, 0, RTM_NEWCACHEREPORT,
2315 sizeof(struct rtgenmsg), 0);
2316 if (!nlh)
2317 goto errout;
2318 rtgenm = nlmsg_data(nlh);
2319 rtgenm->rtgen_family = RTNL_FAMILY_IP6MR;
2320 if (nla_put_u8(skb, IP6MRA_CREPORT_MSGTYPE, msg->im6_msgtype) ||
2321 nla_put_u32(skb, IP6MRA_CREPORT_MIF_ID, msg->im6_mif) ||
2322 nla_put_in6_addr(skb, IP6MRA_CREPORT_SRC_ADDR,
2323 &msg->im6_src) ||
2324 nla_put_in6_addr(skb, IP6MRA_CREPORT_DST_ADDR,
2325 &msg->im6_dst))
2326 goto nla_put_failure;
2327
2328 nla = nla_reserve(skb, IP6MRA_CREPORT_PKT, payloadlen);
2329 if (!nla || skb_copy_bits(pkt, sizeof(struct mrt6msg),
2330 nla_data(nla), payloadlen))
2331 goto nla_put_failure;
2332
2333 nlmsg_end(skb, nlh);
2334
2335 rtnl_notify(skb, net, 0, RTNLGRP_IPV6_MROUTE_R, NULL, GFP_ATOMIC);
2336 return;
2337
2338nla_put_failure:
2339 nlmsg_cancel(skb, nlh);
2340errout:
2341 kfree_skb(skb);
2342 rtnl_set_sk_err(net, RTNLGRP_IPV6_MROUTE_R, -ENOBUFS);
2343}
2344
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002345static int ip6mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
2346{
Yuval Mintz7b0db852018-02-28 23:29:39 +02002347 return mr_rtm_dumproute(skb, cb, ip6mr_mr_table_iter,
2348 _ip6mr_fill_mroute, &mfc_unres_lock);
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002349}