blob: 6f07b838042500832b718433c5091ca4cdc5cd0c [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>
NeilBrown0eb71a92018-06-18 12:52:50 +100035#include <linux/rhashtable.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090036#include <net/protocol.h>
37#include <linux/skbuff.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090038#include <net/raw.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090039#include <linux/notifier.h>
40#include <linux/if_arp.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090041#include <net/checksum.h>
42#include <net/netlink.h>
Patrick McHardyd1db2752010-05-11 14:40:55 +020043#include <net/fib_rules.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090044
45#include <net/ipv6.h>
46#include <net/ip6_route.h>
47#include <linux/mroute6.h>
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +090048#include <linux/pim.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090049#include <net/addrconf.h>
50#include <linux/netfilter_ipv6.h>
Paul Gortmakerbc3b2d72011-07-15 11:47:34 -040051#include <linux/export.h>
Dave Jones5d6e4302009-01-31 00:51:49 -080052#include <net/ip6_checksum.h>
Nicolas Dichteld67b8c62012-12-04 01:13:35 +000053#include <linux/netconf.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090054
Patrick McHardyd1db2752010-05-11 14:40:55 +020055struct ip6mr_rule {
56 struct fib_rule common;
57};
58
59struct ip6mr_result {
Yuval Mintzb70432f2018-02-28 23:29:32 +020060 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +020061};
62
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090063/* Big lock, protecting vif table, mrt cache and mroute socket state.
64 Note that the changes are semaphored via rtnl_lock.
65 */
66
67static DEFINE_RWLOCK(mrt_lock);
68
Yuval Mintzb70432f2018-02-28 23:29:32 +020069/* Multicast router control variables */
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090070
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090071/* Special spinlock for queue of unresolved entries */
72static DEFINE_SPINLOCK(mfc_unres_lock);
73
74/* We return to original Alan's scheme. Hash table of resolved
75 entries is changed only in process context and protected
76 with weak lock mrt_lock. Queue of unresolved entries is protected
77 with strong spinlock mfc_unres_lock.
78
79 In this case data path is free of exclusive locks at all.
80 */
81
82static struct kmem_cache *mrt_cachep __read_mostly;
83
Yuval Mintzb70432f2018-02-28 23:29:32 +020084static struct mr_table *ip6mr_new_table(struct net *net, u32 id);
85static void ip6mr_free_table(struct mr_table *mrt);
Patrick McHardyd1db2752010-05-11 14:40:55 +020086
Yuval Mintzb70432f2018-02-28 23:29:32 +020087static void ip6_mr_forward(struct net *net, struct mr_table *mrt,
Patrick Ruddye4a38c02018-10-01 09:41:27 +010088 struct net_device *dev, struct sk_buff *skb,
89 struct mfc6_cache *cache);
Yuval Mintzb70432f2018-02-28 23:29:32 +020090static int ip6mr_cache_report(struct mr_table *mrt, struct sk_buff *pkt,
Benjamin Thery8229efd2008-12-10 16:30:15 -080091 mifi_t mifi, int assert);
Yuval Mintzb70432f2018-02-28 23:29:32 +020092static void mr6_netlink_event(struct mr_table *mrt, struct mfc6_cache *mfc,
Nicolas Dichtel812e44d2012-12-04 01:13:41 +000093 int cmd);
Yuval Mintzb70432f2018-02-28 23:29:32 +020094static void mrt6msg_netlink_event(struct mr_table *mrt, struct sk_buff *pkt);
Patrick McHardy5b285ca2010-05-11 14:40:56 +020095static int ip6mr_rtm_dumproute(struct sk_buff *skb,
96 struct netlink_callback *cb);
Yuval Mintzb70432f2018-02-28 23:29:32 +020097static void mroute_clean_tables(struct mr_table *mrt, bool all);
Kees Cooke99e88a2017-10-16 14:43:17 -070098static void ipmr_expire_process(struct timer_list *t);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090099
Patrick McHardyd1db2752010-05-11 14:40:55 +0200100#ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
Eric Dumazet8ffb3352010-06-06 15:34:40 -0700101#define ip6mr_for_each_table(mrt, net) \
Patrick McHardyd1db2752010-05-11 14:40:55 +0200102 list_for_each_entry_rcu(mrt, &net->ipv6.mr6_tables, list)
103
Yuval Mintz7b0db852018-02-28 23:29:39 +0200104static struct mr_table *ip6mr_mr_table_iter(struct net *net,
105 struct mr_table *mrt)
106{
107 struct mr_table *ret;
108
109 if (!mrt)
110 ret = list_entry_rcu(net->ipv6.mr6_tables.next,
111 struct mr_table, list);
112 else
113 ret = list_entry_rcu(mrt->list.next,
114 struct mr_table, list);
115
116 if (&ret->list == &net->ipv6.mr6_tables)
117 return NULL;
118 return ret;
119}
120
Yuval Mintzb70432f2018-02-28 23:29:32 +0200121static struct mr_table *ip6mr_get_table(struct net *net, u32 id)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200122{
Yuval Mintzb70432f2018-02-28 23:29:32 +0200123 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200124
125 ip6mr_for_each_table(mrt, net) {
126 if (mrt->id == id)
127 return mrt;
128 }
129 return NULL;
130}
131
David S. Miller4c9483b2011-03-12 16:22:43 -0500132static int ip6mr_fib_lookup(struct net *net, struct flowi6 *flp6,
Yuval Mintzb70432f2018-02-28 23:29:32 +0200133 struct mr_table **mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200134{
Patrick McHardyd1db2752010-05-11 14:40:55 +0200135 int err;
Hannes Frederic Sowa95f4a452014-01-13 02:45:22 +0100136 struct ip6mr_result res;
137 struct fib_lookup_arg arg = {
138 .result = &res,
139 .flags = FIB_LOOKUP_NOREF,
140 };
Patrick McHardyd1db2752010-05-11 14:40:55 +0200141
Patrick Ruddye4a38c02018-10-01 09:41:27 +0100142 /* update flow if oif or iif point to device enslaved to l3mdev */
143 l3mdev_update_flow(net, flowi6_to_flowi(flp6));
144
David S. Miller4c9483b2011-03-12 16:22:43 -0500145 err = fib_rules_lookup(net->ipv6.mr6_rules_ops,
146 flowi6_to_flowi(flp6), 0, &arg);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200147 if (err < 0)
148 return err;
149 *mrt = res.mrt;
150 return 0;
151}
152
153static int ip6mr_rule_action(struct fib_rule *rule, struct flowi *flp,
154 int flags, struct fib_lookup_arg *arg)
155{
156 struct ip6mr_result *res = arg->result;
Yuval Mintzb70432f2018-02-28 23:29:32 +0200157 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200158
159 switch (rule->action) {
160 case FR_ACT_TO_TBL:
161 break;
162 case FR_ACT_UNREACHABLE:
163 return -ENETUNREACH;
164 case FR_ACT_PROHIBIT:
165 return -EACCES;
166 case FR_ACT_BLACKHOLE:
167 default:
168 return -EINVAL;
169 }
170
Patrick Ruddye4a38c02018-10-01 09:41:27 +0100171 arg->table = fib_rule_get_table(rule, arg);
172
173 mrt = ip6mr_get_table(rule->fr_net, arg->table);
Ian Morris63159f22015-03-29 14:00:04 +0100174 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200175 return -EAGAIN;
176 res->mrt = mrt;
177 return 0;
178}
179
180static int ip6mr_rule_match(struct fib_rule *rule, struct flowi *flp, int flags)
181{
182 return 1;
183}
184
185static const struct nla_policy ip6mr_rule_policy[FRA_MAX + 1] = {
186 FRA_GENERIC_POLICY,
187};
188
189static int ip6mr_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
Roopa Prabhub16fb412018-04-21 09:41:31 -0700190 struct fib_rule_hdr *frh, struct nlattr **tb,
191 struct netlink_ext_ack *extack)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200192{
193 return 0;
194}
195
196static int ip6mr_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
197 struct nlattr **tb)
198{
199 return 1;
200}
201
202static int ip6mr_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
203 struct fib_rule_hdr *frh)
204{
205 frh->dst_len = 0;
206 frh->src_len = 0;
207 frh->tos = 0;
208 return 0;
209}
210
Andi Kleen04a6f822012-10-04 17:12:11 -0700211static const struct fib_rules_ops __net_initconst ip6mr_rules_ops_template = {
Patrick McHardyd1db2752010-05-11 14:40:55 +0200212 .family = RTNL_FAMILY_IP6MR,
213 .rule_size = sizeof(struct ip6mr_rule),
214 .addr_size = sizeof(struct in6_addr),
215 .action = ip6mr_rule_action,
216 .match = ip6mr_rule_match,
217 .configure = ip6mr_rule_configure,
218 .compare = ip6mr_rule_compare,
Patrick McHardyd1db2752010-05-11 14:40:55 +0200219 .fill = ip6mr_rule_fill,
220 .nlgroup = RTNLGRP_IPV6_RULE,
221 .policy = ip6mr_rule_policy,
222 .owner = THIS_MODULE,
223};
224
225static int __net_init ip6mr_rules_init(struct net *net)
226{
227 struct fib_rules_ops *ops;
Yuval Mintzb70432f2018-02-28 23:29:32 +0200228 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200229 int err;
230
231 ops = fib_rules_register(&ip6mr_rules_ops_template, net);
232 if (IS_ERR(ops))
233 return PTR_ERR(ops);
234
235 INIT_LIST_HEAD(&net->ipv6.mr6_tables);
236
237 mrt = ip6mr_new_table(net, RT6_TABLE_DFLT);
Sabrina Dubrocae783bb02018-06-05 15:02:00 +0200238 if (IS_ERR(mrt)) {
239 err = PTR_ERR(mrt);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200240 goto err1;
241 }
242
243 err = fib_default_rule_add(ops, 0x7fff, RT6_TABLE_DFLT, 0);
244 if (err < 0)
245 goto err2;
246
247 net->ipv6.mr6_rules_ops = ops;
248 return 0;
249
250err2:
WANG Congf243e5a2015-03-25 14:45:03 -0700251 ip6mr_free_table(mrt);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200252err1:
253 fib_rules_unregister(ops);
254 return err;
255}
256
257static void __net_exit ip6mr_rules_exit(struct net *net)
258{
Yuval Mintzb70432f2018-02-28 23:29:32 +0200259 struct mr_table *mrt, *next;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200260
Hannes Frederic Sowa905a6f92013-07-22 23:45:53 +0200261 rtnl_lock();
Eric Dumazet035320d2010-06-06 23:48:40 +0000262 list_for_each_entry_safe(mrt, next, &net->ipv6.mr6_tables, list) {
263 list_del(&mrt->list);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200264 ip6mr_free_table(mrt);
Eric Dumazet035320d2010-06-06 23:48:40 +0000265 }
Patrick McHardyd1db2752010-05-11 14:40:55 +0200266 fib_rules_unregister(net->ipv6.mr6_rules_ops);
WANG Cong419df122015-03-31 11:01:46 -0700267 rtnl_unlock();
Patrick McHardyd1db2752010-05-11 14:40:55 +0200268}
Yuval Mintz088aa3e2018-03-26 15:01:34 +0300269
270static int ip6mr_rules_dump(struct net *net, struct notifier_block *nb)
271{
272 return fib_rules_dump(net, nb, RTNL_FAMILY_IP6MR);
273}
274
275static unsigned int ip6mr_rules_seq_read(struct net *net)
276{
277 return fib_rules_seq_read(net, RTNL_FAMILY_IP6MR);
278}
Yuval Mintzd3c07e52018-03-26 15:01:35 +0300279
280bool ip6mr_rule_default(const struct fib_rule *rule)
281{
282 return fib_rule_matchall(rule) && rule->action == FR_ACT_TO_TBL &&
283 rule->table == RT6_TABLE_DFLT && !rule->l3mdev;
284}
285EXPORT_SYMBOL(ip6mr_rule_default);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200286#else
287#define ip6mr_for_each_table(mrt, net) \
288 for (mrt = net->ipv6.mrt6; mrt; mrt = NULL)
289
Yuval Mintz7b0db852018-02-28 23:29:39 +0200290static struct mr_table *ip6mr_mr_table_iter(struct net *net,
291 struct mr_table *mrt)
292{
293 if (!mrt)
294 return net->ipv6.mrt6;
295 return NULL;
296}
297
Yuval Mintzb70432f2018-02-28 23:29:32 +0200298static struct mr_table *ip6mr_get_table(struct net *net, u32 id)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200299{
300 return net->ipv6.mrt6;
301}
302
David S. Miller4c9483b2011-03-12 16:22:43 -0500303static int ip6mr_fib_lookup(struct net *net, struct flowi6 *flp6,
Yuval Mintzb70432f2018-02-28 23:29:32 +0200304 struct mr_table **mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200305{
306 *mrt = net->ipv6.mrt6;
307 return 0;
308}
309
310static int __net_init ip6mr_rules_init(struct net *net)
311{
Sabrina Dubrocae783bb02018-06-05 15:02:00 +0200312 struct mr_table *mrt;
313
314 mrt = ip6mr_new_table(net, RT6_TABLE_DFLT);
315 if (IS_ERR(mrt))
316 return PTR_ERR(mrt);
317 net->ipv6.mrt6 = mrt;
318 return 0;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200319}
320
321static void __net_exit ip6mr_rules_exit(struct net *net)
322{
Hannes Frederic Sowa905a6f92013-07-22 23:45:53 +0200323 rtnl_lock();
Patrick McHardyd1db2752010-05-11 14:40:55 +0200324 ip6mr_free_table(net->ipv6.mrt6);
Hannes Frederic Sowa905a6f92013-07-22 23:45:53 +0200325 net->ipv6.mrt6 = NULL;
326 rtnl_unlock();
Patrick McHardyd1db2752010-05-11 14:40:55 +0200327}
Yuval Mintz088aa3e2018-03-26 15:01:34 +0300328
329static int ip6mr_rules_dump(struct net *net, struct notifier_block *nb)
330{
331 return 0;
332}
333
334static unsigned int ip6mr_rules_seq_read(struct net *net)
335{
336 return 0;
337}
Patrick McHardyd1db2752010-05-11 14:40:55 +0200338#endif
339
Yuval Mintz87c418b2018-02-28 23:29:31 +0200340static int ip6mr_hash_cmp(struct rhashtable_compare_arg *arg,
341 const void *ptr)
342{
343 const struct mfc6_cache_cmp_arg *cmparg = arg->key;
344 struct mfc6_cache *c = (struct mfc6_cache *)ptr;
345
346 return !ipv6_addr_equal(&c->mf6c_mcastgrp, &cmparg->mf6c_mcastgrp) ||
347 !ipv6_addr_equal(&c->mf6c_origin, &cmparg->mf6c_origin);
348}
349
350static const struct rhashtable_params ip6mr_rht_params = {
Yuval Mintz494fff52018-02-28 23:29:34 +0200351 .head_offset = offsetof(struct mr_mfc, mnode),
Yuval Mintz87c418b2018-02-28 23:29:31 +0200352 .key_offset = offsetof(struct mfc6_cache, cmparg),
353 .key_len = sizeof(struct mfc6_cache_cmp_arg),
354 .nelem_hint = 3,
355 .locks_mul = 1,
356 .obj_cmpfn = ip6mr_hash_cmp,
357 .automatic_shrinking = true,
358};
359
Yuval Mintz0bbbf0e2018-02-28 23:29:33 +0200360static void ip6mr_new_table_set(struct mr_table *mrt,
361 struct net *net)
362{
363#ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
364 list_add_tail_rcu(&mrt->list, &net->ipv6.mr6_tables);
365#endif
366}
367
Yuval Mintz845c9a72018-02-28 23:29:35 +0200368static struct mfc6_cache_cmp_arg ip6mr_mr_table_ops_cmparg_any = {
369 .mf6c_origin = IN6ADDR_ANY_INIT,
370 .mf6c_mcastgrp = IN6ADDR_ANY_INIT,
371};
372
373static struct mr_table_ops ip6mr_mr_table_ops = {
374 .rht_params = &ip6mr_rht_params,
375 .cmparg_any = &ip6mr_mr_table_ops_cmparg_any,
376};
377
Yuval Mintzb70432f2018-02-28 23:29:32 +0200378static struct mr_table *ip6mr_new_table(struct net *net, u32 id)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200379{
Yuval Mintzb70432f2018-02-28 23:29:32 +0200380 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200381
382 mrt = ip6mr_get_table(net, id);
Ian Morris53b24b82015-03-29 14:00:05 +0100383 if (mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200384 return mrt;
385
Yuval Mintz845c9a72018-02-28 23:29:35 +0200386 return mr_table_alloc(net, id, &ip6mr_mr_table_ops,
Yuval Mintz0bbbf0e2018-02-28 23:29:33 +0200387 ipmr_expire_process, ip6mr_new_table_set);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200388}
389
Yuval Mintzb70432f2018-02-28 23:29:32 +0200390static void ip6mr_free_table(struct mr_table *mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200391{
WANG Cong7ba0c472015-03-31 11:01:47 -0700392 del_timer_sync(&mrt->ipmr_expire_timer);
Nikolay Aleksandrov4c698042015-11-20 13:54:20 +0100393 mroute_clean_tables(mrt, true);
Yuval Mintzb70432f2018-02-28 23:29:32 +0200394 rhltable_destroy(&mrt->mfc_hash);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200395 kfree(mrt);
396}
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900397
398#ifdef CONFIG_PROC_FS
Yuval Mintzc8d61962018-02-28 23:29:36 +0200399/* The /proc interfaces to multicast routing
400 * /proc/ip6_mr_cache /proc/ip6_mr_vif
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900401 */
402
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900403static void *ip6mr_vif_seq_start(struct seq_file *seq, loff_t *pos)
404 __acquires(mrt_lock)
405{
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200406 struct mr_vif_iter *iter = seq->private;
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800407 struct net *net = seq_file_net(seq);
Yuval Mintzb70432f2018-02-28 23:29:32 +0200408 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200409
410 mrt = ip6mr_get_table(net, RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +0100411 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200412 return ERR_PTR(-ENOENT);
413
414 iter->mrt = mrt;
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800415
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900416 read_lock(&mrt_lock);
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200417 return mr_vif_seq_start(seq, pos);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900418}
419
420static void ip6mr_vif_seq_stop(struct seq_file *seq, void *v)
421 __releases(mrt_lock)
422{
423 read_unlock(&mrt_lock);
424}
425
426static int ip6mr_vif_seq_show(struct seq_file *seq, void *v)
427{
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200428 struct mr_vif_iter *iter = seq->private;
Yuval Mintzb70432f2018-02-28 23:29:32 +0200429 struct mr_table *mrt = iter->mrt;
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800430
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900431 if (v == SEQ_START_TOKEN) {
432 seq_puts(seq,
433 "Interface BytesIn PktsIn BytesOut PktsOut Flags\n");
434 } else {
Yuval Mintz6853f212018-02-28 23:29:29 +0200435 const struct vif_device *vif = v;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900436 const char *name = vif->dev ? vif->dev->name : "none";
437
438 seq_printf(seq,
Al Virod430a222008-06-02 10:59:02 +0100439 "%2td %-10s %8ld %7ld %8ld %7ld %05X\n",
Yuval Mintzb70432f2018-02-28 23:29:32 +0200440 vif - mrt->vif_table,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900441 name, vif->bytes_in, vif->pkt_in,
442 vif->bytes_out, vif->pkt_out,
443 vif->flags);
444 }
445 return 0;
446}
447
Stephen Hemminger98147d52009-09-01 19:25:02 +0000448static const struct seq_operations ip6mr_vif_seq_ops = {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900449 .start = ip6mr_vif_seq_start,
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200450 .next = mr_vif_seq_next,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900451 .stop = ip6mr_vif_seq_stop,
452 .show = ip6mr_vif_seq_show,
453};
454
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900455static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos)
456{
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800457 struct net *net = seq_file_net(seq);
Yuval Mintzb70432f2018-02-28 23:29:32 +0200458 struct mr_table *mrt;
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800459
Patrick McHardyd1db2752010-05-11 14:40:55 +0200460 mrt = ip6mr_get_table(net, RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +0100461 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200462 return ERR_PTR(-ENOENT);
463
Yuval Mintzc8d61962018-02-28 23:29:36 +0200464 return mr_mfc_seq_start(seq, pos, mrt, &mfc_unres_lock);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900465}
466
467static int ipmr_mfc_seq_show(struct seq_file *seq, void *v)
468{
469 int n;
470
471 if (v == SEQ_START_TOKEN) {
472 seq_puts(seq,
473 "Group "
474 "Origin "
475 "Iif Pkts Bytes Wrong Oifs\n");
476 } else {
477 const struct mfc6_cache *mfc = v;
Yuval Mintzc8d61962018-02-28 23:29:36 +0200478 const struct mr_mfc_iter *it = seq->private;
Yuval Mintzb70432f2018-02-28 23:29:32 +0200479 struct mr_table *mrt = it->mrt;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900480
Benjamin Thery999890b2008-12-03 22:22:16 -0800481 seq_printf(seq, "%pI6 %pI6 %-3hd",
Harvey Harrison0c6ce782008-10-28 16:09:23 -0700482 &mfc->mf6c_mcastgrp, &mfc->mf6c_origin,
Yuval Mintz494fff52018-02-28 23:29:34 +0200483 mfc->_c.mfc_parent);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900484
Yuval Mintzb70432f2018-02-28 23:29:32 +0200485 if (it->cache != &mrt->mfc_unres_queue) {
Benjamin Thery1ea472e2008-12-03 22:21:47 -0800486 seq_printf(seq, " %8lu %8lu %8lu",
Yuval Mintz494fff52018-02-28 23:29:34 +0200487 mfc->_c.mfc_un.res.pkt,
488 mfc->_c.mfc_un.res.bytes,
489 mfc->_c.mfc_un.res.wrong_if);
490 for (n = mfc->_c.mfc_un.res.minvif;
491 n < mfc->_c.mfc_un.res.maxvif; n++) {
Yuval Mintzb70432f2018-02-28 23:29:32 +0200492 if (VIF_EXISTS(mrt, n) &&
Yuval Mintz494fff52018-02-28 23:29:34 +0200493 mfc->_c.mfc_un.res.ttls[n] < 255)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900494 seq_printf(seq,
Yuval Mintz494fff52018-02-28 23:29:34 +0200495 " %2d:%-3d", n,
496 mfc->_c.mfc_un.res.ttls[n]);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900497 }
Benjamin Thery1ea472e2008-12-03 22:21:47 -0800498 } else {
499 /* unresolved mfc_caches don't contain
500 * pkt, bytes and wrong_if values
501 */
502 seq_printf(seq, " %8lu %8lu %8lu", 0ul, 0ul, 0ul);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900503 }
504 seq_putc(seq, '\n');
505 }
506 return 0;
507}
508
James Morris88e9d342009-09-22 16:43:43 -0700509static const struct seq_operations ipmr_mfc_seq_ops = {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900510 .start = ipmr_mfc_seq_start,
Yuval Mintzc8d61962018-02-28 23:29:36 +0200511 .next = mr_mfc_seq_next,
512 .stop = mr_mfc_seq_stop,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900513 .show = ipmr_mfc_seq_show,
514};
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900515#endif
516
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900517#ifdef CONFIG_IPV6_PIMSM_V2
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900518
519static int pim6_rcv(struct sk_buff *skb)
520{
521 struct pimreghdr *pim;
522 struct ipv6hdr *encap;
523 struct net_device *reg_dev = NULL;
Benjamin Thery8229efd2008-12-10 16:30:15 -0800524 struct net *net = dev_net(skb->dev);
Yuval Mintzb70432f2018-02-28 23:29:32 +0200525 struct mr_table *mrt;
David S. Miller4c9483b2011-03-12 16:22:43 -0500526 struct flowi6 fl6 = {
527 .flowi6_iif = skb->dev->ifindex,
528 .flowi6_mark = skb->mark,
Patrick McHardyd1db2752010-05-11 14:40:55 +0200529 };
530 int reg_vif_num;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900531
532 if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(*encap)))
533 goto drop;
534
535 pim = (struct pimreghdr *)skb_transport_header(skb);
Nikolay Aleksandrov56245ca2016-10-31 13:21:04 +0100536 if (pim->type != ((PIM_VERSION << 4) | PIM_TYPE_REGISTER) ||
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900537 (pim->flags & PIM_NULL_REGISTER) ||
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800538 (csum_ipv6_magic(&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
539 sizeof(*pim), IPPROTO_PIM,
540 csum_partial((void *)pim, sizeof(*pim), 0)) &&
Al Viroec6b4862008-04-26 22:28:58 -0700541 csum_fold(skb_checksum(skb, 0, skb->len, 0))))
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900542 goto drop;
543
544 /* check if the inner packet is destined to mcast group */
545 encap = (struct ipv6hdr *)(skb_transport_header(skb) +
546 sizeof(*pim));
547
548 if (!ipv6_addr_is_multicast(&encap->daddr) ||
549 encap->payload_len == 0 ||
550 ntohs(encap->payload_len) + sizeof(*pim) > skb->len)
551 goto drop;
552
David S. Miller4c9483b2011-03-12 16:22:43 -0500553 if (ip6mr_fib_lookup(net, &fl6, &mrt) < 0)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200554 goto drop;
555 reg_vif_num = mrt->mroute_reg_vif_num;
556
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900557 read_lock(&mrt_lock);
558 if (reg_vif_num >= 0)
Yuval Mintzb70432f2018-02-28 23:29:32 +0200559 reg_dev = mrt->vif_table[reg_vif_num].dev;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900560 if (reg_dev)
561 dev_hold(reg_dev);
562 read_unlock(&mrt_lock);
563
Ian Morris63159f22015-03-29 14:00:04 +0100564 if (!reg_dev)
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900565 goto drop;
566
567 skb->mac_header = skb->network_header;
568 skb_pull(skb, (u8 *)encap - skb->data);
569 skb_reset_network_header(skb);
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800570 skb->protocol = htons(ETH_P_IPV6);
Cesar Eduardo Barros3e49e6d2011-03-26 05:10:30 +0000571 skb->ip_summed = CHECKSUM_NONE;
Eric Dumazetd19d56d2010-05-17 22:36:55 -0700572
Nicolas Dichtelea231922013-09-02 15:34:58 +0200573 skb_tunnel_rx(skb, reg_dev, dev_net(reg_dev));
Eric Dumazetd19d56d2010-05-17 22:36:55 -0700574
Eric Dumazetcaf586e2010-09-30 21:06:55 +0000575 netif_rx(skb);
Eric Dumazet8990f462010-09-20 00:12:11 +0000576
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900577 dev_put(reg_dev);
578 return 0;
579 drop:
580 kfree_skb(skb);
581 return 0;
582}
583
Alexey Dobriyan41135cc2009-09-14 12:22:28 +0000584static const struct inet6_protocol pim6_protocol = {
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900585 .handler = pim6_rcv,
586};
587
588/* Service routines creating virtual interfaces: PIMREG */
589
Stephen Hemminger6fef4c02009-08-31 19:50:41 +0000590static netdev_tx_t reg_vif_xmit(struct sk_buff *skb,
591 struct net_device *dev)
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900592{
Benjamin Thery8229efd2008-12-10 16:30:15 -0800593 struct net *net = dev_net(dev);
Yuval Mintzb70432f2018-02-28 23:29:32 +0200594 struct mr_table *mrt;
David S. Miller4c9483b2011-03-12 16:22:43 -0500595 struct flowi6 fl6 = {
596 .flowi6_oif = dev->ifindex,
Cong Wang6a662712014-04-15 16:25:34 -0700597 .flowi6_iif = skb->skb_iif ? : LOOPBACK_IFINDEX,
David S. Miller4c9483b2011-03-12 16:22:43 -0500598 .flowi6_mark = skb->mark,
Patrick McHardyd1db2752010-05-11 14:40:55 +0200599 };
600 int err;
601
David S. Miller4c9483b2011-03-12 16:22:43 -0500602 err = ip6mr_fib_lookup(net, &fl6, &mrt);
Ben Greear67928c42011-09-23 13:11:01 +0000603 if (err < 0) {
604 kfree_skb(skb);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200605 return err;
Ben Greear67928c42011-09-23 13:11:01 +0000606 }
Benjamin Thery8229efd2008-12-10 16:30:15 -0800607
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900608 read_lock(&mrt_lock);
Pavel Emelyanovdc58c782008-05-21 14:17:54 -0700609 dev->stats.tx_bytes += skb->len;
610 dev->stats.tx_packets++;
Patrick McHardy6bd52142010-05-11 14:40:53 +0200611 ip6mr_cache_report(mrt, skb, mrt->mroute_reg_vif_num, MRT6MSG_WHOLEPKT);
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900612 read_unlock(&mrt_lock);
613 kfree_skb(skb);
Patrick McHardy6ed10652009-06-23 06:03:08 +0000614 return NETDEV_TX_OK;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900615}
616
Nicolas Dichtelee9b9592015-04-02 17:07:03 +0200617static int reg_vif_get_iflink(const struct net_device *dev)
618{
619 return 0;
620}
621
Stephen Hemminger007c3832008-11-20 20:28:35 -0800622static const struct net_device_ops reg_vif_netdev_ops = {
623 .ndo_start_xmit = reg_vif_xmit,
Nicolas Dichtelee9b9592015-04-02 17:07:03 +0200624 .ndo_get_iflink = reg_vif_get_iflink,
Stephen Hemminger007c3832008-11-20 20:28:35 -0800625};
626
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900627static void reg_vif_setup(struct net_device *dev)
628{
629 dev->type = ARPHRD_PIMREG;
630 dev->mtu = 1500 - sizeof(struct ipv6hdr) - 8;
631 dev->flags = IFF_NOARP;
Stephen Hemminger007c3832008-11-20 20:28:35 -0800632 dev->netdev_ops = &reg_vif_netdev_ops;
David S. Millercf124db2017-05-08 12:52:56 -0400633 dev->needs_free_netdev = true;
Tom Goff403dbb92009-06-14 03:16:13 -0700634 dev->features |= NETIF_F_NETNS_LOCAL;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900635}
636
Yuval Mintzb70432f2018-02-28 23:29:32 +0200637static struct net_device *ip6mr_reg_vif(struct net *net, struct mr_table *mrt)
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900638{
639 struct net_device *dev;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200640 char name[IFNAMSIZ];
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900641
Patrick McHardyd1db2752010-05-11 14:40:55 +0200642 if (mrt->id == RT6_TABLE_DFLT)
643 sprintf(name, "pim6reg");
644 else
645 sprintf(name, "pim6reg%u", mrt->id);
646
Tom Gundersenc835a672014-07-14 16:37:24 +0200647 dev = alloc_netdev(0, name, NET_NAME_UNKNOWN, reg_vif_setup);
Ian Morris63159f22015-03-29 14:00:04 +0100648 if (!dev)
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900649 return NULL;
650
Benjamin Thery8229efd2008-12-10 16:30:15 -0800651 dev_net_set(dev, net);
652
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900653 if (register_netdevice(dev)) {
654 free_netdev(dev);
655 return NULL;
656 }
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900657
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900658 if (dev_open(dev))
659 goto failure;
660
Wang Chen7af3db72008-07-14 20:54:54 -0700661 dev_hold(dev);
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900662 return dev;
663
664failure:
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900665 unregister_netdevice(dev);
666 return NULL;
667}
668#endif
669
Yuval Mintz088aa3e2018-03-26 15:01:34 +0300670static int call_ip6mr_vif_entry_notifiers(struct net *net,
671 enum fib_event_type event_type,
672 struct vif_device *vif,
673 mifi_t vif_index, u32 tb_id)
674{
675 return mr_call_vif_notifiers(net, RTNL_FAMILY_IP6MR, event_type,
676 vif, vif_index, tb_id,
677 &net->ipv6.ipmr_seq);
678}
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900679
Yuval Mintz088aa3e2018-03-26 15:01:34 +0300680static int call_ip6mr_mfc_entry_notifiers(struct net *net,
681 enum fib_event_type event_type,
682 struct mfc6_cache *mfc, u32 tb_id)
683{
684 return mr_call_mfc_notifiers(net, RTNL_FAMILY_IP6MR, event_type,
685 &mfc->_c, tb_id, &net->ipv6.ipmr_seq);
686}
687
688/* Delete a VIF entry */
Yuval Mintzb70432f2018-02-28 23:29:32 +0200689static int mif6_delete(struct mr_table *mrt, int vifi, int notify,
Nikolay Aleksandrov723b9292017-04-21 20:42:16 +0300690 struct list_head *head)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900691{
Yuval Mintz6853f212018-02-28 23:29:29 +0200692 struct vif_device *v;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900693 struct net_device *dev;
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800694 struct inet6_dev *in6_dev;
Patrick McHardy6bd52142010-05-11 14:40:53 +0200695
696 if (vifi < 0 || vifi >= mrt->maxvif)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900697 return -EADDRNOTAVAIL;
698
Yuval Mintzb70432f2018-02-28 23:29:32 +0200699 v = &mrt->vif_table[vifi];
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900700
Yuval Mintz088aa3e2018-03-26 15:01:34 +0300701 if (VIF_EXISTS(mrt, vifi))
702 call_ip6mr_vif_entry_notifiers(read_pnet(&mrt->net),
703 FIB_EVENT_VIF_DEL, v, vifi,
704 mrt->id);
705
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900706 write_lock_bh(&mrt_lock);
707 dev = v->dev;
708 v->dev = NULL;
709
710 if (!dev) {
711 write_unlock_bh(&mrt_lock);
712 return -EADDRNOTAVAIL;
713 }
714
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900715#ifdef CONFIG_IPV6_PIMSM_V2
Patrick McHardy6bd52142010-05-11 14:40:53 +0200716 if (vifi == mrt->mroute_reg_vif_num)
717 mrt->mroute_reg_vif_num = -1;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900718#endif
719
Patrick McHardy6bd52142010-05-11 14:40:53 +0200720 if (vifi + 1 == mrt->maxvif) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900721 int tmp;
722 for (tmp = vifi - 1; tmp >= 0; tmp--) {
Yuval Mintzb70432f2018-02-28 23:29:32 +0200723 if (VIF_EXISTS(mrt, tmp))
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900724 break;
725 }
Patrick McHardy6bd52142010-05-11 14:40:53 +0200726 mrt->maxvif = tmp + 1;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900727 }
728
729 write_unlock_bh(&mrt_lock);
730
731 dev_set_allmulti(dev, -1);
732
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800733 in6_dev = __in6_dev_get(dev);
Nicolas Dichteld67b8c62012-12-04 01:13:35 +0000734 if (in6_dev) {
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800735 in6_dev->cnf.mc_forwarding--;
David Ahern85b3daa2017-03-28 14:28:04 -0700736 inet6_netconf_notify_devconf(dev_net(dev), RTM_NEWNETCONF,
Nicolas Dichteld67b8c62012-12-04 01:13:35 +0000737 NETCONFA_MC_FORWARDING,
738 dev->ifindex, &in6_dev->cnf);
739 }
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800740
Nikolay Aleksandrov723b9292017-04-21 20:42:16 +0300741 if ((v->flags & MIFF_REGISTER) && !notify)
Eric Dumazetc871e662009-10-28 04:48:11 +0000742 unregister_netdevice_queue(dev, head);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900743
744 dev_put(dev);
745 return 0;
746}
747
Yuval Mintz87c418b2018-02-28 23:29:31 +0200748static inline void ip6mr_cache_free_rcu(struct rcu_head *head)
749{
Yuval Mintz494fff52018-02-28 23:29:34 +0200750 struct mr_mfc *c = container_of(head, struct mr_mfc, rcu);
Yuval Mintz87c418b2018-02-28 23:29:31 +0200751
Yuval Mintz494fff52018-02-28 23:29:34 +0200752 kmem_cache_free(mrt_cachep, (struct mfc6_cache *)c);
Yuval Mintz87c418b2018-02-28 23:29:31 +0200753}
754
Benjamin Thery58701ad2008-12-10 16:22:34 -0800755static inline void ip6mr_cache_free(struct mfc6_cache *c)
756{
Yuval Mintz494fff52018-02-28 23:29:34 +0200757 call_rcu(&c->_c.rcu, ip6mr_cache_free_rcu);
Benjamin Thery58701ad2008-12-10 16:22:34 -0800758}
759
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900760/* Destroy an unresolved cache entry, killing queued skbs
761 and reporting error to netlink readers.
762 */
763
Yuval Mintzb70432f2018-02-28 23:29:32 +0200764static void ip6mr_destroy_unres(struct mr_table *mrt, struct mfc6_cache *c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900765{
Patrick McHardy6bd52142010-05-11 14:40:53 +0200766 struct net *net = read_pnet(&mrt->net);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900767 struct sk_buff *skb;
768
Patrick McHardy6bd52142010-05-11 14:40:53 +0200769 atomic_dec(&mrt->cache_resolve_queue_len);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900770
Yuval Mintz494fff52018-02-28 23:29:34 +0200771 while ((skb = skb_dequeue(&c->_c.mfc_un.unres.unresolved)) != NULL) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900772 if (ipv6_hdr(skb)->version == 0) {
Johannes Bergaf728682017-06-16 14:29:22 +0200773 struct nlmsghdr *nlh = skb_pull(skb,
774 sizeof(struct ipv6hdr));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900775 nlh->nlmsg_type = NLMSG_ERROR;
Hong zhi guo573ce262013-03-27 06:47:04 +0000776 nlh->nlmsg_len = nlmsg_msg_size(sizeof(struct nlmsgerr));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900777 skb_trim(skb, nlh->nlmsg_len);
Hong zhi guo573ce262013-03-27 06:47:04 +0000778 ((struct nlmsgerr *)nlmsg_data(nlh))->error = -ETIMEDOUT;
Eric W. Biederman15e47302012-09-07 20:12:54 +0000779 rtnl_unicast(skb, net, NETLINK_CB(skb).portid);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900780 } else
781 kfree_skb(skb);
782 }
783
Benjamin Thery58701ad2008-12-10 16:22:34 -0800784 ip6mr_cache_free(c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900785}
786
787
Patrick McHardyc476efb2010-05-11 14:40:48 +0200788/* Timer process for all the unresolved queue. */
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900789
Yuval Mintzb70432f2018-02-28 23:29:32 +0200790static void ipmr_do_expire_process(struct mr_table *mrt)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900791{
792 unsigned long now = jiffies;
793 unsigned long expires = 10 * HZ;
Yuval Mintz494fff52018-02-28 23:29:34 +0200794 struct mr_mfc *c, *next;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900795
Yuval Mintzb70432f2018-02-28 23:29:32 +0200796 list_for_each_entry_safe(c, next, &mrt->mfc_unres_queue, list) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900797 if (time_after(c->mfc_un.unres.expires, now)) {
798 /* not yet... */
799 unsigned long interval = c->mfc_un.unres.expires - now;
800 if (interval < expires)
801 expires = interval;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900802 continue;
803 }
804
Patrick McHardyf30a77842010-05-11 14:40:51 +0200805 list_del(&c->list);
Yuval Mintz494fff52018-02-28 23:29:34 +0200806 mr6_netlink_event(mrt, (struct mfc6_cache *)c, RTM_DELROUTE);
807 ip6mr_destroy_unres(mrt, (struct mfc6_cache *)c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900808 }
809
Yuval Mintzb70432f2018-02-28 23:29:32 +0200810 if (!list_empty(&mrt->mfc_unres_queue))
Patrick McHardy6bd52142010-05-11 14:40:53 +0200811 mod_timer(&mrt->ipmr_expire_timer, jiffies + expires);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900812}
813
Kees Cooke99e88a2017-10-16 14:43:17 -0700814static void ipmr_expire_process(struct timer_list *t)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900815{
Yuval Mintzb70432f2018-02-28 23:29:32 +0200816 struct mr_table *mrt = from_timer(mrt, t, ipmr_expire_timer);
Patrick McHardyc476efb2010-05-11 14:40:48 +0200817
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900818 if (!spin_trylock(&mfc_unres_lock)) {
Patrick McHardy6bd52142010-05-11 14:40:53 +0200819 mod_timer(&mrt->ipmr_expire_timer, jiffies + 1);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900820 return;
821 }
822
Yuval Mintzb70432f2018-02-28 23:29:32 +0200823 if (!list_empty(&mrt->mfc_unres_queue))
Patrick McHardy6bd52142010-05-11 14:40:53 +0200824 ipmr_do_expire_process(mrt);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900825
826 spin_unlock(&mfc_unres_lock);
827}
828
829/* Fill oifs list. It is called under write locked mrt_lock. */
830
Yuval Mintzb70432f2018-02-28 23:29:32 +0200831static void ip6mr_update_thresholds(struct mr_table *mrt,
Yuval Mintz494fff52018-02-28 23:29:34 +0200832 struct mr_mfc *cache,
Patrick McHardyb5aa30b2010-05-11 14:40:50 +0200833 unsigned char *ttls)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900834{
835 int vifi;
836
Rami Rosen6ac7eb02008-04-10 12:40:10 +0300837 cache->mfc_un.res.minvif = MAXMIFS;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900838 cache->mfc_un.res.maxvif = 0;
Rami Rosen6ac7eb02008-04-10 12:40:10 +0300839 memset(cache->mfc_un.res.ttls, 255, MAXMIFS);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900840
Patrick McHardy6bd52142010-05-11 14:40:53 +0200841 for (vifi = 0; vifi < mrt->maxvif; vifi++) {
Yuval Mintzb70432f2018-02-28 23:29:32 +0200842 if (VIF_EXISTS(mrt, vifi) &&
Benjamin Thery4e168802008-12-10 16:15:08 -0800843 ttls[vifi] && ttls[vifi] < 255) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900844 cache->mfc_un.res.ttls[vifi] = ttls[vifi];
845 if (cache->mfc_un.res.minvif > vifi)
846 cache->mfc_un.res.minvif = vifi;
847 if (cache->mfc_un.res.maxvif <= vifi)
848 cache->mfc_un.res.maxvif = vifi + 1;
849 }
850 }
Nikolay Aleksandrov90b5ca12016-07-26 18:54:52 +0200851 cache->mfc_un.res.lastuse = jiffies;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900852}
853
Yuval Mintzb70432f2018-02-28 23:29:32 +0200854static int mif6_add(struct net *net, struct mr_table *mrt,
Patrick McHardy6bd52142010-05-11 14:40:53 +0200855 struct mif6ctl *vifc, int mrtsock)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900856{
857 int vifi = vifc->mif6c_mifi;
Yuval Mintzb70432f2018-02-28 23:29:32 +0200858 struct vif_device *v = &mrt->vif_table[vifi];
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900859 struct net_device *dev;
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800860 struct inet6_dev *in6_dev;
Wang Chen5ae7b442008-07-14 20:54:23 -0700861 int err;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900862
863 /* Is vif busy ? */
Yuval Mintzb70432f2018-02-28 23:29:32 +0200864 if (VIF_EXISTS(mrt, vifi))
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900865 return -EADDRINUSE;
866
867 switch (vifc->mif6c_flags) {
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900868#ifdef CONFIG_IPV6_PIMSM_V2
869 case MIFF_REGISTER:
870 /*
871 * Special Purpose VIF in PIM
872 * All the packets will be sent to the daemon
873 */
Patrick McHardy6bd52142010-05-11 14:40:53 +0200874 if (mrt->mroute_reg_vif_num >= 0)
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900875 return -EADDRINUSE;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200876 dev = ip6mr_reg_vif(net, mrt);
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900877 if (!dev)
878 return -ENOBUFS;
Wang Chen5ae7b442008-07-14 20:54:23 -0700879 err = dev_set_allmulti(dev, 1);
880 if (err) {
881 unregister_netdevice(dev);
Wang Chen7af3db72008-07-14 20:54:54 -0700882 dev_put(dev);
Wang Chen5ae7b442008-07-14 20:54:23 -0700883 return err;
884 }
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900885 break;
886#endif
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900887 case 0:
Benjamin Thery8229efd2008-12-10 16:30:15 -0800888 dev = dev_get_by_index(net, vifc->mif6c_pifi);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900889 if (!dev)
890 return -EADDRNOTAVAIL;
Wang Chen5ae7b442008-07-14 20:54:23 -0700891 err = dev_set_allmulti(dev, 1);
Wang Chen7af3db72008-07-14 20:54:54 -0700892 if (err) {
893 dev_put(dev);
Wang Chen5ae7b442008-07-14 20:54:23 -0700894 return err;
Wang Chen7af3db72008-07-14 20:54:54 -0700895 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900896 break;
897 default:
898 return -EINVAL;
899 }
900
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800901 in6_dev = __in6_dev_get(dev);
Nicolas Dichteld67b8c62012-12-04 01:13:35 +0000902 if (in6_dev) {
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800903 in6_dev->cnf.mc_forwarding++;
David Ahern85b3daa2017-03-28 14:28:04 -0700904 inet6_netconf_notify_devconf(dev_net(dev), RTM_NEWNETCONF,
Nicolas Dichteld67b8c62012-12-04 01:13:35 +0000905 NETCONFA_MC_FORWARDING,
906 dev->ifindex, &in6_dev->cnf);
907 }
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800908
Yuval Mintz6853f212018-02-28 23:29:29 +0200909 /* Fill in the VIF structures */
910 vif_device_init(v, dev, vifc->vifc_rate_limit, vifc->vifc_threshold,
911 vifc->mif6c_flags | (!mrtsock ? VIFF_STATIC : 0),
912 MIFF_REGISTER);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900913
914 /* And finish update writing critical data */
915 write_lock_bh(&mrt_lock);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900916 v->dev = dev;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900917#ifdef CONFIG_IPV6_PIMSM_V2
918 if (v->flags & MIFF_REGISTER)
Patrick McHardy6bd52142010-05-11 14:40:53 +0200919 mrt->mroute_reg_vif_num = vifi;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900920#endif
Patrick McHardy6bd52142010-05-11 14:40:53 +0200921 if (vifi + 1 > mrt->maxvif)
922 mrt->maxvif = vifi + 1;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900923 write_unlock_bh(&mrt_lock);
Yuval Mintz088aa3e2018-03-26 15:01:34 +0300924 call_ip6mr_vif_entry_notifiers(net, FIB_EVENT_VIF_ADD,
925 v, vifi, mrt->id);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900926 return 0;
927}
928
Yuval Mintzb70432f2018-02-28 23:29:32 +0200929static struct mfc6_cache *ip6mr_cache_find(struct mr_table *mrt,
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000930 const struct in6_addr *origin,
931 const struct in6_addr *mcastgrp)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900932{
Yuval Mintz87c418b2018-02-28 23:29:31 +0200933 struct mfc6_cache_cmp_arg arg = {
934 .mf6c_origin = *origin,
935 .mf6c_mcastgrp = *mcastgrp,
936 };
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900937
Yuval Mintz845c9a72018-02-28 23:29:35 +0200938 return mr_mfc_find(mrt, &arg);
Nicolas Dichtel660b26d2013-01-21 06:00:26 +0000939}
940
941/* Look for a (*,G) entry */
Yuval Mintzb70432f2018-02-28 23:29:32 +0200942static struct mfc6_cache *ip6mr_cache_find_any(struct mr_table *mrt,
Nicolas Dichtel660b26d2013-01-21 06:00:26 +0000943 struct in6_addr *mcastgrp,
944 mifi_t mifi)
945{
Yuval Mintz87c418b2018-02-28 23:29:31 +0200946 struct mfc6_cache_cmp_arg arg = {
947 .mf6c_origin = in6addr_any,
948 .mf6c_mcastgrp = *mcastgrp,
949 };
Nicolas Dichtel660b26d2013-01-21 06:00:26 +0000950
951 if (ipv6_addr_any(mcastgrp))
Yuval Mintz845c9a72018-02-28 23:29:35 +0200952 return mr_mfc_find_any_parent(mrt, mifi);
953 return mr_mfc_find_any(mrt, mifi, &arg);
Nicolas Dichtel660b26d2013-01-21 06:00:26 +0000954}
955
Yuval Mintz87c418b2018-02-28 23:29:31 +0200956/* Look for a (S,G,iif) entry if parent != -1 */
957static struct mfc6_cache *
Yuval Mintzb70432f2018-02-28 23:29:32 +0200958ip6mr_cache_find_parent(struct mr_table *mrt,
Yuval Mintz87c418b2018-02-28 23:29:31 +0200959 const struct in6_addr *origin,
960 const struct in6_addr *mcastgrp,
961 int parent)
962{
963 struct mfc6_cache_cmp_arg arg = {
964 .mf6c_origin = *origin,
965 .mf6c_mcastgrp = *mcastgrp,
966 };
Yuval Mintz87c418b2018-02-28 23:29:31 +0200967
Yuval Mintz845c9a72018-02-28 23:29:35 +0200968 return mr_mfc_find_parent(mrt, &arg, parent);
Yuval Mintz87c418b2018-02-28 23:29:31 +0200969}
970
Yuval Mintz845c9a72018-02-28 23:29:35 +0200971/* Allocate a multicast cache entry */
Patrick McHardyb5aa30b2010-05-11 14:40:50 +0200972static struct mfc6_cache *ip6mr_cache_alloc(void)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900973{
Joe Perches36cbac52008-12-03 22:27:25 -0800974 struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL);
Ian Morris63159f22015-03-29 14:00:04 +0100975 if (!c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900976 return NULL;
Yuval Mintz494fff52018-02-28 23:29:34 +0200977 c->_c.mfc_un.res.last_assert = jiffies - MFC_ASSERT_THRESH - 1;
978 c->_c.mfc_un.res.minvif = MAXMIFS;
Yuval Mintz8c13af22018-03-26 15:01:36 +0300979 c->_c.free = ip6mr_cache_free_rcu;
980 refcount_set(&c->_c.mfc_un.res.refcount, 1);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900981 return c;
982}
983
Patrick McHardyb5aa30b2010-05-11 14:40:50 +0200984static struct mfc6_cache *ip6mr_cache_alloc_unres(void)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900985{
Joe Perches36cbac52008-12-03 22:27:25 -0800986 struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC);
Ian Morris63159f22015-03-29 14:00:04 +0100987 if (!c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900988 return NULL;
Yuval Mintz494fff52018-02-28 23:29:34 +0200989 skb_queue_head_init(&c->_c.mfc_un.unres.unresolved);
990 c->_c.mfc_un.unres.expires = jiffies + 10 * HZ;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900991 return c;
992}
993
994/*
995 * A cache entry has gone into a resolved state from queued
996 */
997
Yuval Mintzb70432f2018-02-28 23:29:32 +0200998static void ip6mr_cache_resolve(struct net *net, struct mr_table *mrt,
Patrick McHardy6bd52142010-05-11 14:40:53 +0200999 struct mfc6_cache *uc, struct mfc6_cache *c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001000{
1001 struct sk_buff *skb;
1002
1003 /*
1004 * Play the pending entries through our router
1005 */
1006
Yuval Mintz494fff52018-02-28 23:29:34 +02001007 while ((skb = __skb_dequeue(&uc->_c.mfc_un.unres.unresolved))) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001008 if (ipv6_hdr(skb)->version == 0) {
Johannes Bergaf728682017-06-16 14:29:22 +02001009 struct nlmsghdr *nlh = skb_pull(skb,
1010 sizeof(struct ipv6hdr));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001011
Yuval Mintz7b0db852018-02-28 23:29:39 +02001012 if (mr_fill_mroute(mrt, skb, &c->_c,
1013 nlmsg_data(nlh)) > 0) {
YOSHIFUJI Hideaki549e0282008-04-05 22:17:39 +09001014 nlh->nlmsg_len = skb_tail_pointer(skb) - (u8 *)nlh;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001015 } else {
1016 nlh->nlmsg_type = NLMSG_ERROR;
Hong zhi guo573ce262013-03-27 06:47:04 +00001017 nlh->nlmsg_len = nlmsg_msg_size(sizeof(struct nlmsgerr));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001018 skb_trim(skb, nlh->nlmsg_len);
Hong zhi guo573ce262013-03-27 06:47:04 +00001019 ((struct nlmsgerr *)nlmsg_data(nlh))->error = -EMSGSIZE;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001020 }
Eric W. Biederman15e47302012-09-07 20:12:54 +00001021 rtnl_unicast(skb, net, NETLINK_CB(skb).portid);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001022 } else
Patrick Ruddye4a38c02018-10-01 09:41:27 +01001023 ip6_mr_forward(net, mrt, skb->dev, skb, c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001024 }
1025}
1026
1027/*
Julien Gomesdd12d15c2017-06-20 13:54:18 -07001028 * Bounce a cache query up to pim6sd and netlink.
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001029 *
1030 * Called under mrt_lock.
1031 */
1032
Yuval Mintzb70432f2018-02-28 23:29:32 +02001033static int ip6mr_cache_report(struct mr_table *mrt, struct sk_buff *pkt,
Patrick McHardy6bd52142010-05-11 14:40:53 +02001034 mifi_t mifi, int assert)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001035{
Yuval Mintz8571ab42018-02-28 23:29:30 +02001036 struct sock *mroute6_sk;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001037 struct sk_buff *skb;
1038 struct mrt6msg *msg;
1039 int ret;
1040
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001041#ifdef CONFIG_IPV6_PIMSM_V2
1042 if (assert == MRT6MSG_WHOLEPKT)
1043 skb = skb_realloc_headroom(pkt, -skb_network_offset(pkt)
1044 +sizeof(*msg));
1045 else
1046#endif
1047 skb = alloc_skb(sizeof(struct ipv6hdr) + sizeof(*msg), GFP_ATOMIC);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001048
1049 if (!skb)
1050 return -ENOBUFS;
1051
1052 /* I suppose that internal messages
1053 * do not require checksums */
1054
1055 skb->ip_summed = CHECKSUM_UNNECESSARY;
1056
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001057#ifdef CONFIG_IPV6_PIMSM_V2
1058 if (assert == MRT6MSG_WHOLEPKT) {
1059 /* Ugly, but we have no choice with this interface.
1060 Duplicate old header, fix length etc.
1061 And all this only to mangle msg->im6_msgtype and
1062 to set msg->im6_mbz to "mbz" :-)
1063 */
1064 skb_push(skb, -skb_network_offset(pkt));
1065
1066 skb_push(skb, sizeof(*msg));
1067 skb_reset_transport_header(skb);
1068 msg = (struct mrt6msg *)skb_transport_header(skb);
1069 msg->im6_mbz = 0;
1070 msg->im6_msgtype = MRT6MSG_WHOLEPKT;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001071 msg->im6_mif = mrt->mroute_reg_vif_num;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001072 msg->im6_pad = 0;
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +00001073 msg->im6_src = ipv6_hdr(pkt)->saddr;
1074 msg->im6_dst = ipv6_hdr(pkt)->daddr;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001075
1076 skb->ip_summed = CHECKSUM_UNNECESSARY;
1077 } else
1078#endif
1079 {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001080 /*
1081 * Copy the IP header
1082 */
1083
1084 skb_put(skb, sizeof(struct ipv6hdr));
1085 skb_reset_network_header(skb);
1086 skb_copy_to_linear_data(skb, ipv6_hdr(pkt), sizeof(struct ipv6hdr));
1087
1088 /*
1089 * Add our header
1090 */
1091 skb_put(skb, sizeof(*msg));
1092 skb_reset_transport_header(skb);
1093 msg = (struct mrt6msg *)skb_transport_header(skb);
1094
1095 msg->im6_mbz = 0;
1096 msg->im6_msgtype = assert;
Rami Rosen6ac7eb02008-04-10 12:40:10 +03001097 msg->im6_mif = mifi;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001098 msg->im6_pad = 0;
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +00001099 msg->im6_src = ipv6_hdr(pkt)->saddr;
1100 msg->im6_dst = ipv6_hdr(pkt)->daddr;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001101
Eric Dumazetadf30902009-06-02 05:19:30 +00001102 skb_dst_set(skb, dst_clone(skb_dst(pkt)));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001103 skb->ip_summed = CHECKSUM_UNNECESSARY;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001104 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001105
Yuval Mintz8571ab42018-02-28 23:29:30 +02001106 rcu_read_lock();
Yuval Mintzb70432f2018-02-28 23:29:32 +02001107 mroute6_sk = rcu_dereference(mrt->mroute_sk);
Yuval Mintz8571ab42018-02-28 23:29:30 +02001108 if (!mroute6_sk) {
1109 rcu_read_unlock();
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001110 kfree_skb(skb);
1111 return -EINVAL;
1112 }
1113
Julien Gomesdd12d15c2017-06-20 13:54:18 -07001114 mrt6msg_netlink_event(mrt, skb);
1115
Yuval Mintz8571ab42018-02-28 23:29:30 +02001116 /* Deliver to user space multicast routing algorithms */
1117 ret = sock_queue_rcv_skb(mroute6_sk, skb);
1118 rcu_read_unlock();
Benjamin Therybd91b8b2008-12-10 16:07:08 -08001119 if (ret < 0) {
Joe Perchese87cc472012-05-13 21:56:26 +00001120 net_warn_ratelimited("mroute6: pending queue full, dropping entries\n");
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001121 kfree_skb(skb);
1122 }
1123
1124 return ret;
1125}
1126
Yuval Mintz494fff52018-02-28 23:29:34 +02001127/* Queue a packet for resolution. It gets locked cache entry! */
1128static int ip6mr_cache_unresolved(struct mr_table *mrt, mifi_t mifi,
Patrick Ruddye4a38c02018-10-01 09:41:27 +01001129 struct sk_buff *skb, struct net_device *dev)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001130{
Yuval Mintz494fff52018-02-28 23:29:34 +02001131 struct mfc6_cache *c;
Patrick McHardyf30a77842010-05-11 14:40:51 +02001132 bool found = false;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001133 int err;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001134
1135 spin_lock_bh(&mfc_unres_lock);
Yuval Mintz494fff52018-02-28 23:29:34 +02001136 list_for_each_entry(c, &mrt->mfc_unres_queue, _c.list) {
Patrick McHardyc476efb2010-05-11 14:40:48 +02001137 if (ipv6_addr_equal(&c->mf6c_mcastgrp, &ipv6_hdr(skb)->daddr) &&
Patrick McHardyf30a77842010-05-11 14:40:51 +02001138 ipv6_addr_equal(&c->mf6c_origin, &ipv6_hdr(skb)->saddr)) {
1139 found = true;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001140 break;
Patrick McHardyf30a77842010-05-11 14:40:51 +02001141 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001142 }
1143
Patrick McHardyf30a77842010-05-11 14:40:51 +02001144 if (!found) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001145 /*
1146 * Create a new entry if allowable
1147 */
1148
Patrick McHardy6bd52142010-05-11 14:40:53 +02001149 if (atomic_read(&mrt->cache_resolve_queue_len) >= 10 ||
Patrick McHardyb5aa30b2010-05-11 14:40:50 +02001150 (c = ip6mr_cache_alloc_unres()) == NULL) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001151 spin_unlock_bh(&mfc_unres_lock);
1152
1153 kfree_skb(skb);
1154 return -ENOBUFS;
1155 }
1156
Yuval Mintz494fff52018-02-28 23:29:34 +02001157 /* Fill in the new cache entry */
1158 c->_c.mfc_parent = -1;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001159 c->mf6c_origin = ipv6_hdr(skb)->saddr;
1160 c->mf6c_mcastgrp = ipv6_hdr(skb)->daddr;
1161
1162 /*
1163 * Reflect first query at pim6sd
1164 */
Patrick McHardy6bd52142010-05-11 14:40:53 +02001165 err = ip6mr_cache_report(mrt, skb, mifi, MRT6MSG_NOCACHE);
Benjamin Thery8229efd2008-12-10 16:30:15 -08001166 if (err < 0) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001167 /* If the report failed throw the cache entry
1168 out - Brad Parker
1169 */
1170 spin_unlock_bh(&mfc_unres_lock);
1171
Benjamin Thery58701ad2008-12-10 16:22:34 -08001172 ip6mr_cache_free(c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001173 kfree_skb(skb);
1174 return err;
1175 }
1176
Patrick McHardy6bd52142010-05-11 14:40:53 +02001177 atomic_inc(&mrt->cache_resolve_queue_len);
Yuval Mintz494fff52018-02-28 23:29:34 +02001178 list_add(&c->_c.list, &mrt->mfc_unres_queue);
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00001179 mr6_netlink_event(mrt, c, RTM_NEWROUTE);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001180
Patrick McHardy6bd52142010-05-11 14:40:53 +02001181 ipmr_do_expire_process(mrt);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001182 }
1183
Yuval Mintz494fff52018-02-28 23:29:34 +02001184 /* See if we can append the packet */
1185 if (c->_c.mfc_un.unres.unresolved.qlen > 3) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001186 kfree_skb(skb);
1187 err = -ENOBUFS;
1188 } else {
Patrick Ruddye4a38c02018-10-01 09:41:27 +01001189 if (dev) {
1190 skb->dev = dev;
1191 skb->skb_iif = dev->ifindex;
1192 }
Yuval Mintz494fff52018-02-28 23:29:34 +02001193 skb_queue_tail(&c->_c.mfc_un.unres.unresolved, skb);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001194 err = 0;
1195 }
1196
1197 spin_unlock_bh(&mfc_unres_lock);
1198 return err;
1199}
1200
1201/*
1202 * MFC6 cache manipulation by user space
1203 */
1204
Yuval Mintzb70432f2018-02-28 23:29:32 +02001205static int ip6mr_mfc_delete(struct mr_table *mrt, struct mf6cctl *mfc,
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001206 int parent)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001207{
Yuval Mintz87c418b2018-02-28 23:29:31 +02001208 struct mfc6_cache *c;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001209
Yuval Mintz87c418b2018-02-28 23:29:31 +02001210 /* The entries are added/deleted only under RTNL */
1211 rcu_read_lock();
1212 c = ip6mr_cache_find_parent(mrt, &mfc->mf6cc_origin.sin6_addr,
1213 &mfc->mf6cc_mcastgrp.sin6_addr, parent);
1214 rcu_read_unlock();
1215 if (!c)
1216 return -ENOENT;
Yuval Mintz494fff52018-02-28 23:29:34 +02001217 rhltable_remove(&mrt->mfc_hash, &c->_c.mnode, ip6mr_rht_params);
1218 list_del_rcu(&c->_c.list);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001219
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001220 call_ip6mr_mfc_entry_notifiers(read_pnet(&mrt->net),
1221 FIB_EVENT_ENTRY_DEL, c, mrt->id);
Yuval Mintz87c418b2018-02-28 23:29:31 +02001222 mr6_netlink_event(mrt, c, RTM_DELROUTE);
Yuval Mintz8c13af22018-03-26 15:01:36 +03001223 mr_cache_put(&c->_c);
Yuval Mintz87c418b2018-02-28 23:29:31 +02001224 return 0;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001225}
1226
1227static int ip6mr_device_event(struct notifier_block *this,
1228 unsigned long event, void *ptr)
1229{
Jiri Pirko351638e2013-05-28 01:30:21 +00001230 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
Benjamin Thery8229efd2008-12-10 16:30:15 -08001231 struct net *net = dev_net(dev);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001232 struct mr_table *mrt;
Yuval Mintz6853f212018-02-28 23:29:29 +02001233 struct vif_device *v;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001234 int ct;
1235
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001236 if (event != NETDEV_UNREGISTER)
1237 return NOTIFY_DONE;
1238
Patrick McHardyd1db2752010-05-11 14:40:55 +02001239 ip6mr_for_each_table(mrt, net) {
Yuval Mintzb70432f2018-02-28 23:29:32 +02001240 v = &mrt->vif_table[0];
Patrick McHardyd1db2752010-05-11 14:40:55 +02001241 for (ct = 0; ct < mrt->maxvif; ct++, v++) {
1242 if (v->dev == dev)
Nikolay Aleksandrov723b9292017-04-21 20:42:16 +03001243 mif6_delete(mrt, ct, 1, NULL);
Patrick McHardyd1db2752010-05-11 14:40:55 +02001244 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001245 }
Eric Dumazetc871e662009-10-28 04:48:11 +00001246
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001247 return NOTIFY_DONE;
1248}
1249
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001250static unsigned int ip6mr_seq_read(struct net *net)
1251{
1252 ASSERT_RTNL();
1253
1254 return net->ipv6.ipmr_seq + ip6mr_rules_seq_read(net);
1255}
1256
1257static int ip6mr_dump(struct net *net, struct notifier_block *nb)
1258{
1259 return mr_dump(net, nb, RTNL_FAMILY_IP6MR, ip6mr_rules_dump,
1260 ip6mr_mr_table_iter, &mrt_lock);
1261}
1262
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001263static struct notifier_block ip6_mr_notifier = {
1264 .notifier_call = ip6mr_device_event
1265};
1266
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001267static const struct fib_notifier_ops ip6mr_notifier_ops_template = {
1268 .family = RTNL_FAMILY_IP6MR,
1269 .fib_seq_read = ip6mr_seq_read,
1270 .fib_dump = ip6mr_dump,
1271 .owner = THIS_MODULE,
1272};
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001273
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001274static int __net_init ip6mr_notifier_init(struct net *net)
1275{
1276 struct fib_notifier_ops *ops;
1277
1278 net->ipv6.ipmr_seq = 0;
1279
1280 ops = fib_notifier_ops_register(&ip6mr_notifier_ops_template, net);
1281 if (IS_ERR(ops))
1282 return PTR_ERR(ops);
1283
1284 net->ipv6.ip6mr_notifier_ops = ops;
1285
1286 return 0;
1287}
1288
1289static void __net_exit ip6mr_notifier_exit(struct net *net)
1290{
1291 fib_notifier_ops_unregister(net->ipv6.ip6mr_notifier_ops);
1292 net->ipv6.ip6mr_notifier_ops = NULL;
1293}
1294
1295/* Setup for IP multicast routing */
Benjamin Thery4e168802008-12-10 16:15:08 -08001296static int __net_init ip6mr_net_init(struct net *net)
1297{
Patrick McHardyd1db2752010-05-11 14:40:55 +02001298 int err;
Patrick McHardyf30a77842010-05-11 14:40:51 +02001299
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001300 err = ip6mr_notifier_init(net);
1301 if (err)
1302 return err;
1303
Patrick McHardyd1db2752010-05-11 14:40:55 +02001304 err = ip6mr_rules_init(net);
1305 if (err < 0)
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001306 goto ip6mr_rules_fail;
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001307
1308#ifdef CONFIG_PROC_FS
1309 err = -ENOMEM;
Christoph Hellwigc3506372018-04-10 19:42:55 +02001310 if (!proc_create_net("ip6_mr_vif", 0, net->proc_net, &ip6mr_vif_seq_ops,
1311 sizeof(struct mr_vif_iter)))
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001312 goto proc_vif_fail;
Christoph Hellwigc3506372018-04-10 19:42:55 +02001313 if (!proc_create_net("ip6_mr_cache", 0, net->proc_net, &ipmr_mfc_seq_ops,
1314 sizeof(struct mr_mfc_iter)))
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001315 goto proc_cache_fail;
1316#endif
Patrick McHardy6bd52142010-05-11 14:40:53 +02001317
Benjamin Thery4a6258a2008-12-10 16:24:07 -08001318 return 0;
1319
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001320#ifdef CONFIG_PROC_FS
1321proc_cache_fail:
Gao fengece31ff2013-02-18 01:34:56 +00001322 remove_proc_entry("ip6_mr_vif", net->proc_net);
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001323proc_vif_fail:
Patrick McHardyd1db2752010-05-11 14:40:55 +02001324 ip6mr_rules_exit(net);
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001325#endif
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001326ip6mr_rules_fail:
1327 ip6mr_notifier_exit(net);
Benjamin Thery4e168802008-12-10 16:15:08 -08001328 return err;
1329}
1330
1331static void __net_exit ip6mr_net_exit(struct net *net)
1332{
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001333#ifdef CONFIG_PROC_FS
Gao fengece31ff2013-02-18 01:34:56 +00001334 remove_proc_entry("ip6_mr_cache", net->proc_net);
1335 remove_proc_entry("ip6_mr_vif", net->proc_net);
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001336#endif
Patrick McHardyd1db2752010-05-11 14:40:55 +02001337 ip6mr_rules_exit(net);
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001338 ip6mr_notifier_exit(net);
Benjamin Thery4e168802008-12-10 16:15:08 -08001339}
1340
1341static struct pernet_operations ip6mr_net_ops = {
1342 .init = ip6mr_net_init,
1343 .exit = ip6mr_net_exit,
1344};
1345
Wang Chen623d1a12008-07-03 12:13:30 +08001346int __init ip6_mr_init(void)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001347{
Wang Chen623d1a12008-07-03 12:13:30 +08001348 int err;
1349
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001350 mrt_cachep = kmem_cache_create("ip6_mrt_cache",
1351 sizeof(struct mfc6_cache),
1352 0, SLAB_HWCACHE_ALIGN,
1353 NULL);
1354 if (!mrt_cachep)
Wang Chen623d1a12008-07-03 12:13:30 +08001355 return -ENOMEM;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001356
Benjamin Thery4e168802008-12-10 16:15:08 -08001357 err = register_pernet_subsys(&ip6mr_net_ops);
1358 if (err)
1359 goto reg_pernet_fail;
1360
Wang Chen623d1a12008-07-03 12:13:30 +08001361 err = register_netdevice_notifier(&ip6_mr_notifier);
1362 if (err)
1363 goto reg_notif_fail;
Tom Goff403dbb92009-06-14 03:16:13 -07001364#ifdef CONFIG_IPV6_PIMSM_V2
1365 if (inet6_add_protocol(&pim6_protocol, IPPROTO_PIM) < 0) {
Joe Perchesf3213832012-05-15 14:11:53 +00001366 pr_err("%s: can't add PIM protocol\n", __func__);
Tom Goff403dbb92009-06-14 03:16:13 -07001367 err = -EAGAIN;
1368 goto add_proto_fail;
1369 }
1370#endif
Florian Westphala3fde2a2017-12-04 19:19:18 +01001371 err = rtnl_register_module(THIS_MODULE, RTNL_FAMILY_IP6MR, RTM_GETROUTE,
1372 NULL, ip6mr_rtm_dumproute, 0);
1373 if (err == 0)
1374 return 0;
1375
Tom Goff403dbb92009-06-14 03:16:13 -07001376#ifdef CONFIG_IPV6_PIMSM_V2
Florian Westphala3fde2a2017-12-04 19:19:18 +01001377 inet6_del_protocol(&pim6_protocol, IPPROTO_PIM);
Tom Goff403dbb92009-06-14 03:16:13 -07001378add_proto_fail:
1379 unregister_netdevice_notifier(&ip6_mr_notifier);
1380#endif
Benjamin Thery87b30a62008-11-10 16:34:11 -08001381reg_notif_fail:
Benjamin Thery4e168802008-12-10 16:15:08 -08001382 unregister_pernet_subsys(&ip6mr_net_ops);
1383reg_pernet_fail:
Benjamin Thery87b30a62008-11-10 16:34:11 -08001384 kmem_cache_destroy(mrt_cachep);
Wang Chen623d1a12008-07-03 12:13:30 +08001385 return err;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001386}
1387
Wang Chen623d1a12008-07-03 12:13:30 +08001388void ip6_mr_cleanup(void)
1389{
Duan Jiongffb13882014-11-19 09:35:39 +08001390 rtnl_unregister(RTNL_FAMILY_IP6MR, RTM_GETROUTE);
1391#ifdef CONFIG_IPV6_PIMSM_V2
1392 inet6_del_protocol(&pim6_protocol, IPPROTO_PIM);
1393#endif
Wang Chen623d1a12008-07-03 12:13:30 +08001394 unregister_netdevice_notifier(&ip6_mr_notifier);
Benjamin Thery4e168802008-12-10 16:15:08 -08001395 unregister_pernet_subsys(&ip6mr_net_ops);
Wang Chen623d1a12008-07-03 12:13:30 +08001396 kmem_cache_destroy(mrt_cachep);
1397}
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001398
Yuval Mintzb70432f2018-02-28 23:29:32 +02001399static int ip6mr_mfc_add(struct net *net, struct mr_table *mrt,
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001400 struct mf6cctl *mfc, int mrtsock, int parent)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001401{
Rami Rosen6ac7eb02008-04-10 12:40:10 +03001402 unsigned char ttls[MAXMIFS];
Yuval Mintz87c418b2018-02-28 23:29:31 +02001403 struct mfc6_cache *uc, *c;
Yuval Mintz494fff52018-02-28 23:29:34 +02001404 struct mr_mfc *_uc;
Yuval Mintz87c418b2018-02-28 23:29:31 +02001405 bool found;
1406 int i, err;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001407
Patrick McHardya50436f22010-03-17 06:04:14 +00001408 if (mfc->mf6cc_parent >= MAXMIFS)
1409 return -ENFILE;
1410
Rami Rosen6ac7eb02008-04-10 12:40:10 +03001411 memset(ttls, 255, MAXMIFS);
1412 for (i = 0; i < MAXMIFS; i++) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001413 if (IF_ISSET(i, &mfc->mf6cc_ifset))
1414 ttls[i] = 1;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001415 }
1416
Yuval Mintz87c418b2018-02-28 23:29:31 +02001417 /* The entries are added/deleted only under RTNL */
1418 rcu_read_lock();
1419 c = ip6mr_cache_find_parent(mrt, &mfc->mf6cc_origin.sin6_addr,
1420 &mfc->mf6cc_mcastgrp.sin6_addr, parent);
1421 rcu_read_unlock();
1422 if (c) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001423 write_lock_bh(&mrt_lock);
Yuval Mintz494fff52018-02-28 23:29:34 +02001424 c->_c.mfc_parent = mfc->mf6cc_parent;
1425 ip6mr_update_thresholds(mrt, &c->_c, ttls);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001426 if (!mrtsock)
Yuval Mintz494fff52018-02-28 23:29:34 +02001427 c->_c.mfc_flags |= MFC_STATIC;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001428 write_unlock_bh(&mrt_lock);
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001429 call_ip6mr_mfc_entry_notifiers(net, FIB_EVENT_ENTRY_REPLACE,
1430 c, mrt->id);
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00001431 mr6_netlink_event(mrt, c, RTM_NEWROUTE);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001432 return 0;
1433 }
1434
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001435 if (!ipv6_addr_any(&mfc->mf6cc_mcastgrp.sin6_addr) &&
1436 !ipv6_addr_is_multicast(&mfc->mf6cc_mcastgrp.sin6_addr))
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001437 return -EINVAL;
1438
Patrick McHardyb5aa30b2010-05-11 14:40:50 +02001439 c = ip6mr_cache_alloc();
Ian Morris63159f22015-03-29 14:00:04 +01001440 if (!c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001441 return -ENOMEM;
1442
1443 c->mf6c_origin = mfc->mf6cc_origin.sin6_addr;
1444 c->mf6c_mcastgrp = mfc->mf6cc_mcastgrp.sin6_addr;
Yuval Mintz494fff52018-02-28 23:29:34 +02001445 c->_c.mfc_parent = mfc->mf6cc_parent;
1446 ip6mr_update_thresholds(mrt, &c->_c, ttls);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001447 if (!mrtsock)
Yuval Mintz494fff52018-02-28 23:29:34 +02001448 c->_c.mfc_flags |= MFC_STATIC;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001449
Yuval Mintz494fff52018-02-28 23:29:34 +02001450 err = rhltable_insert_key(&mrt->mfc_hash, &c->cmparg, &c->_c.mnode,
Yuval Mintz87c418b2018-02-28 23:29:31 +02001451 ip6mr_rht_params);
1452 if (err) {
1453 pr_err("ip6mr: rhtable insert error %d\n", err);
1454 ip6mr_cache_free(c);
1455 return err;
1456 }
Yuval Mintz494fff52018-02-28 23:29:34 +02001457 list_add_tail_rcu(&c->_c.list, &mrt->mfc_cache_list);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001458
Yuval Mintz87c418b2018-02-28 23:29:31 +02001459 /* Check to see if we resolved a queued list. If so we
1460 * need to send on the frames and tidy up.
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001461 */
Patrick McHardyf30a77842010-05-11 14:40:51 +02001462 found = false;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001463 spin_lock_bh(&mfc_unres_lock);
Yuval Mintz494fff52018-02-28 23:29:34 +02001464 list_for_each_entry(_uc, &mrt->mfc_unres_queue, list) {
1465 uc = (struct mfc6_cache *)_uc;
Patrick McHardyc476efb2010-05-11 14:40:48 +02001466 if (ipv6_addr_equal(&uc->mf6c_origin, &c->mf6c_origin) &&
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001467 ipv6_addr_equal(&uc->mf6c_mcastgrp, &c->mf6c_mcastgrp)) {
Yuval Mintz494fff52018-02-28 23:29:34 +02001468 list_del(&_uc->list);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001469 atomic_dec(&mrt->cache_resolve_queue_len);
Patrick McHardyf30a77842010-05-11 14:40:51 +02001470 found = true;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001471 break;
1472 }
1473 }
Yuval Mintzb70432f2018-02-28 23:29:32 +02001474 if (list_empty(&mrt->mfc_unres_queue))
Patrick McHardy6bd52142010-05-11 14:40:53 +02001475 del_timer(&mrt->ipmr_expire_timer);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001476 spin_unlock_bh(&mfc_unres_lock);
1477
Patrick McHardyf30a77842010-05-11 14:40:51 +02001478 if (found) {
Patrick McHardy6bd52142010-05-11 14:40:53 +02001479 ip6mr_cache_resolve(net, mrt, uc, c);
Benjamin Thery58701ad2008-12-10 16:22:34 -08001480 ip6mr_cache_free(uc);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001481 }
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001482 call_ip6mr_mfc_entry_notifiers(net, FIB_EVENT_ENTRY_ADD,
1483 c, mrt->id);
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00001484 mr6_netlink_event(mrt, c, RTM_NEWROUTE);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001485 return 0;
1486}
1487
1488/*
1489 * Close the multicast socket, and clear the vif tables etc
1490 */
1491
Yuval Mintzb70432f2018-02-28 23:29:32 +02001492static void mroute_clean_tables(struct mr_table *mrt, bool all)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001493{
Yuval Mintz494fff52018-02-28 23:29:34 +02001494 struct mr_mfc *c, *tmp;
Eric Dumazetc871e662009-10-28 04:48:11 +00001495 LIST_HEAD(list);
Yuval Mintz87c418b2018-02-28 23:29:31 +02001496 int i;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001497
Yuval Mintz87c418b2018-02-28 23:29:31 +02001498 /* Shut down all active vif entries */
Patrick McHardy6bd52142010-05-11 14:40:53 +02001499 for (i = 0; i < mrt->maxvif; i++) {
Yuval Mintzb70432f2018-02-28 23:29:32 +02001500 if (!all && (mrt->vif_table[i].flags & VIFF_STATIC))
Nikolay Aleksandrov4c698042015-11-20 13:54:20 +01001501 continue;
Nikolay Aleksandrov723b9292017-04-21 20:42:16 +03001502 mif6_delete(mrt, i, 0, &list);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001503 }
Eric Dumazetc871e662009-10-28 04:48:11 +00001504 unregister_netdevice_many(&list);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001505
Yuval Mintz87c418b2018-02-28 23:29:31 +02001506 /* Wipe the cache */
Yuval Mintzb70432f2018-02-28 23:29:32 +02001507 list_for_each_entry_safe(c, tmp, &mrt->mfc_cache_list, list) {
Yuval Mintz87c418b2018-02-28 23:29:31 +02001508 if (!all && (c->mfc_flags & MFC_STATIC))
1509 continue;
Yuval Mintzb70432f2018-02-28 23:29:32 +02001510 rhltable_remove(&mrt->mfc_hash, &c->mnode, ip6mr_rht_params);
Yuval Mintz87c418b2018-02-28 23:29:31 +02001511 list_del_rcu(&c->list);
Yuval Mintz494fff52018-02-28 23:29:34 +02001512 mr6_netlink_event(mrt, (struct mfc6_cache *)c, RTM_DELROUTE);
Yuval Mintz8c13af22018-03-26 15:01:36 +03001513 mr_cache_put(c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001514 }
1515
Patrick McHardy6bd52142010-05-11 14:40:53 +02001516 if (atomic_read(&mrt->cache_resolve_queue_len) != 0) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001517 spin_lock_bh(&mfc_unres_lock);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001518 list_for_each_entry_safe(c, tmp, &mrt->mfc_unres_queue, list) {
Patrick McHardyf30a77842010-05-11 14:40:51 +02001519 list_del(&c->list);
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001520 call_ip6mr_mfc_entry_notifiers(read_pnet(&mrt->net),
1521 FIB_EVENT_ENTRY_DEL,
1522 (struct mfc6_cache *)c,
1523 mrt->id);
Yuval Mintz494fff52018-02-28 23:29:34 +02001524 mr6_netlink_event(mrt, (struct mfc6_cache *)c,
1525 RTM_DELROUTE);
1526 ip6mr_destroy_unres(mrt, (struct mfc6_cache *)c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001527 }
1528 spin_unlock_bh(&mfc_unres_lock);
1529 }
1530}
1531
Yuval Mintzb70432f2018-02-28 23:29:32 +02001532static int ip6mr_sk_init(struct mr_table *mrt, struct sock *sk)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001533{
1534 int err = 0;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001535 struct net *net = sock_net(sk);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001536
1537 rtnl_lock();
1538 write_lock_bh(&mrt_lock);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001539 if (rtnl_dereference(mrt->mroute_sk)) {
Eric Dumazet927265b2016-07-08 05:46:04 +02001540 err = -EADDRINUSE;
Yuval Mintz8571ab42018-02-28 23:29:30 +02001541 } else {
Yuval Mintzb70432f2018-02-28 23:29:32 +02001542 rcu_assign_pointer(mrt->mroute_sk, sk);
Eric Dumazeta366e302018-03-07 08:43:19 -08001543 sock_set_flag(sk, SOCK_RCU_FREE);
Yuval Mintz8571ab42018-02-28 23:29:30 +02001544 net->ipv6.devconf_all->mc_forwarding++;
Eric Dumazet927265b2016-07-08 05:46:04 +02001545 }
1546 write_unlock_bh(&mrt_lock);
1547
1548 if (!err)
David Ahern85b3daa2017-03-28 14:28:04 -07001549 inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
1550 NETCONFA_MC_FORWARDING,
Nicolas Dichteld67b8c62012-12-04 01:13:35 +00001551 NETCONFA_IFINDEX_ALL,
1552 net->ipv6.devconf_all);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001553 rtnl_unlock();
1554
1555 return err;
1556}
1557
1558int ip6mr_sk_done(struct sock *sk)
1559{
Patrick McHardyd1db2752010-05-11 14:40:55 +02001560 int err = -EACCES;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001561 struct net *net = sock_net(sk);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001562 struct mr_table *mrt;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001563
Francesco Ruggeri338d1822017-11-08 11:23:46 -08001564 if (sk->sk_type != SOCK_RAW ||
1565 inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
1566 return err;
1567
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001568 rtnl_lock();
Patrick McHardyd1db2752010-05-11 14:40:55 +02001569 ip6mr_for_each_table(mrt, net) {
Yuval Mintzb70432f2018-02-28 23:29:32 +02001570 if (sk == rtnl_dereference(mrt->mroute_sk)) {
Patrick McHardyd1db2752010-05-11 14:40:55 +02001571 write_lock_bh(&mrt_lock);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001572 RCU_INIT_POINTER(mrt->mroute_sk, NULL);
Eric Dumazeta366e302018-03-07 08:43:19 -08001573 /* Note that mroute_sk had SOCK_RCU_FREE set,
1574 * so the RCU grace period before sk freeing
1575 * is guaranteed by sk_destruct()
1576 */
Patrick McHardyd1db2752010-05-11 14:40:55 +02001577 net->ipv6.devconf_all->mc_forwarding--;
Eric Dumazet927265b2016-07-08 05:46:04 +02001578 write_unlock_bh(&mrt_lock);
David Ahern85b3daa2017-03-28 14:28:04 -07001579 inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
Nicolas Dichteld67b8c62012-12-04 01:13:35 +00001580 NETCONFA_MC_FORWARDING,
1581 NETCONFA_IFINDEX_ALL,
1582 net->ipv6.devconf_all);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001583
Nikolay Aleksandrov4c698042015-11-20 13:54:20 +01001584 mroute_clean_tables(mrt, false);
Patrick McHardyd1db2752010-05-11 14:40:55 +02001585 err = 0;
1586 break;
1587 }
1588 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001589 rtnl_unlock();
1590
1591 return err;
1592}
1593
Yuval Mintz8571ab42018-02-28 23:29:30 +02001594bool mroute6_is_socket(struct net *net, struct sk_buff *skb)
Patrick McHardy6bd52142010-05-11 14:40:53 +02001595{
Yuval Mintzb70432f2018-02-28 23:29:32 +02001596 struct mr_table *mrt;
David S. Miller4c9483b2011-03-12 16:22:43 -05001597 struct flowi6 fl6 = {
Julian Anastasove374c612014-04-28 10:51:56 +03001598 .flowi6_iif = skb->skb_iif ? : LOOPBACK_IFINDEX,
David S. Miller4c9483b2011-03-12 16:22:43 -05001599 .flowi6_oif = skb->dev->ifindex,
1600 .flowi6_mark = skb->mark,
Patrick McHardyd1db2752010-05-11 14:40:55 +02001601 };
1602
David S. Miller4c9483b2011-03-12 16:22:43 -05001603 if (ip6mr_fib_lookup(net, &fl6, &mrt) < 0)
Patrick McHardyd1db2752010-05-11 14:40:55 +02001604 return NULL;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001605
Yuval Mintzb70432f2018-02-28 23:29:32 +02001606 return rcu_access_pointer(mrt->mroute_sk);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001607}
Yuval Mintz8571ab42018-02-28 23:29:30 +02001608EXPORT_SYMBOL(mroute6_is_socket);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001609
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001610/*
1611 * Socket options and virtual interface manipulation. The whole
1612 * virtual interface system is a complete heap, but unfortunately
1613 * that's how BSD mrouted happens to think. Maybe one day with a proper
1614 * MOSPF/PIM router set up we can clean this up.
1615 */
1616
David S. Millerb7058842009-09-30 16:12:20 -07001617int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsigned int optlen)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001618{
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001619 int ret, parent = 0;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001620 struct mif6ctl vif;
1621 struct mf6cctl mfc;
1622 mifi_t mifi;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001623 struct net *net = sock_net(sk);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001624 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +02001625
Xin Long99253eb2017-02-24 16:29:06 +08001626 if (sk->sk_type != SOCK_RAW ||
1627 inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
1628 return -EOPNOTSUPP;
1629
Patrick McHardyd1db2752010-05-11 14:40:55 +02001630 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +01001631 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +02001632 return -ENOENT;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001633
1634 if (optname != MRT6_INIT) {
Yuval Mintzb70432f2018-02-28 23:29:32 +02001635 if (sk != rcu_access_pointer(mrt->mroute_sk) &&
Yuval Mintz8571ab42018-02-28 23:29:30 +02001636 !ns_capable(net->user_ns, CAP_NET_ADMIN))
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001637 return -EACCES;
1638 }
1639
1640 switch (optname) {
1641 case MRT6_INIT:
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001642 if (optlen < sizeof(int))
1643 return -EINVAL;
1644
Patrick McHardy6bd52142010-05-11 14:40:53 +02001645 return ip6mr_sk_init(mrt, sk);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001646
1647 case MRT6_DONE:
1648 return ip6mr_sk_done(sk);
1649
1650 case MRT6_ADD_MIF:
1651 if (optlen < sizeof(vif))
1652 return -EINVAL;
1653 if (copy_from_user(&vif, optval, sizeof(vif)))
1654 return -EFAULT;
Rami Rosen6ac7eb02008-04-10 12:40:10 +03001655 if (vif.mif6c_mifi >= MAXMIFS)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001656 return -ENFILE;
1657 rtnl_lock();
Yuval Mintz8571ab42018-02-28 23:29:30 +02001658 ret = mif6_add(net, mrt, &vif,
Yuval Mintzb70432f2018-02-28 23:29:32 +02001659 sk == rtnl_dereference(mrt->mroute_sk));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001660 rtnl_unlock();
1661 return ret;
1662
1663 case MRT6_DEL_MIF:
1664 if (optlen < sizeof(mifi_t))
1665 return -EINVAL;
1666 if (copy_from_user(&mifi, optval, sizeof(mifi_t)))
1667 return -EFAULT;
1668 rtnl_lock();
Nikolay Aleksandrov723b9292017-04-21 20:42:16 +03001669 ret = mif6_delete(mrt, mifi, 0, NULL);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001670 rtnl_unlock();
1671 return ret;
1672
1673 /*
1674 * Manipulate the forwarding caches. These live
1675 * in a sort of kernel/user symbiosis.
1676 */
1677 case MRT6_ADD_MFC:
1678 case MRT6_DEL_MFC:
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001679 parent = -1;
Gustavo A. R. Silva275757e62017-10-16 16:36:52 -05001680 /* fall through */
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001681 case MRT6_ADD_MFC_PROXY:
1682 case MRT6_DEL_MFC_PROXY:
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001683 if (optlen < sizeof(mfc))
1684 return -EINVAL;
1685 if (copy_from_user(&mfc, optval, sizeof(mfc)))
1686 return -EFAULT;
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001687 if (parent == 0)
1688 parent = mfc.mf6cc_parent;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001689 rtnl_lock();
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001690 if (optname == MRT6_DEL_MFC || optname == MRT6_DEL_MFC_PROXY)
1691 ret = ip6mr_mfc_delete(mrt, &mfc, parent);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001692 else
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001693 ret = ip6mr_mfc_add(net, mrt, &mfc,
Yuval Mintz8571ab42018-02-28 23:29:30 +02001694 sk ==
Yuval Mintzb70432f2018-02-28 23:29:32 +02001695 rtnl_dereference(mrt->mroute_sk),
Yuval Mintz8571ab42018-02-28 23:29:30 +02001696 parent);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001697 rtnl_unlock();
1698 return ret;
1699
1700 /*
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001701 * Control PIM assert (to activate pim will activate assert)
1702 */
1703 case MRT6_ASSERT:
1704 {
1705 int v;
Joe Perches03f52a02012-11-25 18:26:34 +00001706
1707 if (optlen != sizeof(v))
1708 return -EINVAL;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001709 if (get_user(v, (int __user *)optval))
1710 return -EFAULT;
Joe Perches53d68412012-11-25 09:35:30 +00001711 mrt->mroute_do_assert = v;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001712 return 0;
1713 }
1714
1715#ifdef CONFIG_IPV6_PIMSM_V2
1716 case MRT6_PIM:
1717 {
YOSHIFUJI Hideakia9f83bf2008-04-10 15:41:28 +09001718 int v;
Joe Perches03f52a02012-11-25 18:26:34 +00001719
1720 if (optlen != sizeof(v))
1721 return -EINVAL;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001722 if (get_user(v, (int __user *)optval))
1723 return -EFAULT;
1724 v = !!v;
1725 rtnl_lock();
1726 ret = 0;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001727 if (v != mrt->mroute_do_pim) {
1728 mrt->mroute_do_pim = v;
1729 mrt->mroute_do_assert = v;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001730 }
1731 rtnl_unlock();
1732 return ret;
1733 }
1734
1735#endif
Patrick McHardyd1db2752010-05-11 14:40:55 +02001736#ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
1737 case MRT6_TABLE:
1738 {
1739 u32 v;
1740
1741 if (optlen != sizeof(u32))
1742 return -EINVAL;
1743 if (get_user(v, (u32 __user *)optval))
1744 return -EFAULT;
Dan Carpenter75356a82013-01-23 20:38:34 +00001745 /* "pim6reg%u" should not exceed 16 bytes (IFNAMSIZ) */
1746 if (v != RT_TABLE_DEFAULT && v >= 100000000)
1747 return -EINVAL;
Yuval Mintzb70432f2018-02-28 23:29:32 +02001748 if (sk == rcu_access_pointer(mrt->mroute_sk))
Patrick McHardyd1db2752010-05-11 14:40:55 +02001749 return -EBUSY;
1750
1751 rtnl_lock();
1752 ret = 0;
Sabrina Dubrocae783bb02018-06-05 15:02:00 +02001753 mrt = ip6mr_new_table(net, v);
1754 if (IS_ERR(mrt))
1755 ret = PTR_ERR(mrt);
Sabrina Dubroca848235e2018-06-05 15:01:59 +02001756 else
1757 raw6_sk(sk)->ip6mr_table = v;
Patrick McHardyd1db2752010-05-11 14:40:55 +02001758 rtnl_unlock();
1759 return ret;
1760 }
1761#endif
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001762 /*
Rami Rosen7d120c52008-04-23 14:35:13 +03001763 * Spurious command, or MRT6_VERSION which you cannot
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001764 * set.
1765 */
1766 default:
1767 return -ENOPROTOOPT;
1768 }
1769}
1770
1771/*
1772 * Getsock opt support for the multicast routing system.
1773 */
1774
1775int ip6_mroute_getsockopt(struct sock *sk, int optname, char __user *optval,
1776 int __user *optlen)
1777{
1778 int olr;
1779 int val;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001780 struct net *net = sock_net(sk);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001781 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +02001782
Xin Long99253eb2017-02-24 16:29:06 +08001783 if (sk->sk_type != SOCK_RAW ||
1784 inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
1785 return -EOPNOTSUPP;
1786
Patrick McHardyd1db2752010-05-11 14:40:55 +02001787 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +01001788 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +02001789 return -ENOENT;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001790
1791 switch (optname) {
1792 case MRT6_VERSION:
1793 val = 0x0305;
1794 break;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001795#ifdef CONFIG_IPV6_PIMSM_V2
1796 case MRT6_PIM:
Patrick McHardy6bd52142010-05-11 14:40:53 +02001797 val = mrt->mroute_do_pim;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001798 break;
1799#endif
1800 case MRT6_ASSERT:
Patrick McHardy6bd52142010-05-11 14:40:53 +02001801 val = mrt->mroute_do_assert;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001802 break;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001803 default:
1804 return -ENOPROTOOPT;
1805 }
1806
1807 if (get_user(olr, optlen))
1808 return -EFAULT;
1809
1810 olr = min_t(int, olr, sizeof(int));
1811 if (olr < 0)
1812 return -EINVAL;
1813
1814 if (put_user(olr, optlen))
1815 return -EFAULT;
1816 if (copy_to_user(optval, &val, olr))
1817 return -EFAULT;
1818 return 0;
1819}
1820
1821/*
1822 * The IP multicast ioctl support routines.
1823 */
1824
1825int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg)
1826{
1827 struct sioc_sg_req6 sr;
1828 struct sioc_mif_req6 vr;
Yuval Mintz6853f212018-02-28 23:29:29 +02001829 struct vif_device *vif;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001830 struct mfc6_cache *c;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001831 struct net *net = sock_net(sk);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001832 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +02001833
1834 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +01001835 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +02001836 return -ENOENT;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001837
1838 switch (cmd) {
1839 case SIOCGETMIFCNT_IN6:
1840 if (copy_from_user(&vr, arg, sizeof(vr)))
1841 return -EFAULT;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001842 if (vr.mifi >= mrt->maxvif)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001843 return -EINVAL;
1844 read_lock(&mrt_lock);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001845 vif = &mrt->vif_table[vr.mifi];
1846 if (VIF_EXISTS(mrt, vr.mifi)) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001847 vr.icount = vif->pkt_in;
1848 vr.ocount = vif->pkt_out;
1849 vr.ibytes = vif->bytes_in;
1850 vr.obytes = vif->bytes_out;
1851 read_unlock(&mrt_lock);
1852
1853 if (copy_to_user(arg, &vr, sizeof(vr)))
1854 return -EFAULT;
1855 return 0;
1856 }
1857 read_unlock(&mrt_lock);
1858 return -EADDRNOTAVAIL;
1859 case SIOCGETSGCNT_IN6:
1860 if (copy_from_user(&sr, arg, sizeof(sr)))
1861 return -EFAULT;
1862
Yuval Mintz87c418b2018-02-28 23:29:31 +02001863 rcu_read_lock();
Patrick McHardy6bd52142010-05-11 14:40:53 +02001864 c = ip6mr_cache_find(mrt, &sr.src.sin6_addr, &sr.grp.sin6_addr);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001865 if (c) {
Yuval Mintz494fff52018-02-28 23:29:34 +02001866 sr.pktcnt = c->_c.mfc_un.res.pkt;
1867 sr.bytecnt = c->_c.mfc_un.res.bytes;
1868 sr.wrong_if = c->_c.mfc_un.res.wrong_if;
Yuval Mintz87c418b2018-02-28 23:29:31 +02001869 rcu_read_unlock();
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001870
1871 if (copy_to_user(arg, &sr, sizeof(sr)))
1872 return -EFAULT;
1873 return 0;
1874 }
Yuval Mintz87c418b2018-02-28 23:29:31 +02001875 rcu_read_unlock();
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001876 return -EADDRNOTAVAIL;
1877 default:
1878 return -ENOIOCTLCMD;
1879 }
1880}
1881
David S. Millere2d57762011-02-03 17:59:32 -08001882#ifdef CONFIG_COMPAT
1883struct compat_sioc_sg_req6 {
1884 struct sockaddr_in6 src;
1885 struct sockaddr_in6 grp;
1886 compat_ulong_t pktcnt;
1887 compat_ulong_t bytecnt;
1888 compat_ulong_t wrong_if;
1889};
1890
1891struct compat_sioc_mif_req6 {
1892 mifi_t mifi;
1893 compat_ulong_t icount;
1894 compat_ulong_t ocount;
1895 compat_ulong_t ibytes;
1896 compat_ulong_t obytes;
1897};
1898
1899int ip6mr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg)
1900{
1901 struct compat_sioc_sg_req6 sr;
1902 struct compat_sioc_mif_req6 vr;
Yuval Mintz6853f212018-02-28 23:29:29 +02001903 struct vif_device *vif;
David S. Millere2d57762011-02-03 17:59:32 -08001904 struct mfc6_cache *c;
1905 struct net *net = sock_net(sk);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001906 struct mr_table *mrt;
David S. Millere2d57762011-02-03 17:59:32 -08001907
1908 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +01001909 if (!mrt)
David S. Millere2d57762011-02-03 17:59:32 -08001910 return -ENOENT;
1911
1912 switch (cmd) {
1913 case SIOCGETMIFCNT_IN6:
1914 if (copy_from_user(&vr, arg, sizeof(vr)))
1915 return -EFAULT;
1916 if (vr.mifi >= mrt->maxvif)
1917 return -EINVAL;
1918 read_lock(&mrt_lock);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001919 vif = &mrt->vif_table[vr.mifi];
1920 if (VIF_EXISTS(mrt, vr.mifi)) {
David S. Millere2d57762011-02-03 17:59:32 -08001921 vr.icount = vif->pkt_in;
1922 vr.ocount = vif->pkt_out;
1923 vr.ibytes = vif->bytes_in;
1924 vr.obytes = vif->bytes_out;
1925 read_unlock(&mrt_lock);
1926
1927 if (copy_to_user(arg, &vr, sizeof(vr)))
1928 return -EFAULT;
1929 return 0;
1930 }
1931 read_unlock(&mrt_lock);
1932 return -EADDRNOTAVAIL;
1933 case SIOCGETSGCNT_IN6:
1934 if (copy_from_user(&sr, arg, sizeof(sr)))
1935 return -EFAULT;
1936
Yuval Mintz87c418b2018-02-28 23:29:31 +02001937 rcu_read_lock();
David S. Millere2d57762011-02-03 17:59:32 -08001938 c = ip6mr_cache_find(mrt, &sr.src.sin6_addr, &sr.grp.sin6_addr);
1939 if (c) {
Yuval Mintz494fff52018-02-28 23:29:34 +02001940 sr.pktcnt = c->_c.mfc_un.res.pkt;
1941 sr.bytecnt = c->_c.mfc_un.res.bytes;
1942 sr.wrong_if = c->_c.mfc_un.res.wrong_if;
Yuval Mintz87c418b2018-02-28 23:29:31 +02001943 rcu_read_unlock();
David S. Millere2d57762011-02-03 17:59:32 -08001944
1945 if (copy_to_user(arg, &sr, sizeof(sr)))
1946 return -EFAULT;
1947 return 0;
1948 }
Yuval Mintz87c418b2018-02-28 23:29:31 +02001949 rcu_read_unlock();
David S. Millere2d57762011-02-03 17:59:32 -08001950 return -EADDRNOTAVAIL;
1951 default:
1952 return -ENOIOCTLCMD;
1953 }
1954}
1955#endif
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001956
Eric W. Biederman0c4b51f2015-09-15 20:04:18 -05001957static inline int ip6mr_forward2_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001958{
Eric Dumazet1d015502016-04-27 16:44:40 -07001959 __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
1960 IPSTATS_MIB_OUTFORWDATAGRAMS);
1961 __IP6_ADD_STATS(net, ip6_dst_idev(skb_dst(skb)),
1962 IPSTATS_MIB_OUTOCTETS, skb->len);
Eric W. Biederman13206b62015-10-07 16:48:35 -05001963 return dst_output(net, sk, skb);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001964}
1965
1966/*
1967 * Processing handlers for ip6mr_forward
1968 */
1969
Yuval Mintzb70432f2018-02-28 23:29:32 +02001970static int ip6mr_forward2(struct net *net, struct mr_table *mrt,
Patrick McHardy6bd52142010-05-11 14:40:53 +02001971 struct sk_buff *skb, struct mfc6_cache *c, int vifi)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001972{
1973 struct ipv6hdr *ipv6h;
Yuval Mintzb70432f2018-02-28 23:29:32 +02001974 struct vif_device *vif = &mrt->vif_table[vifi];
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001975 struct net_device *dev;
1976 struct dst_entry *dst;
David S. Miller4c9483b2011-03-12 16:22:43 -05001977 struct flowi6 fl6;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001978
Ian Morris63159f22015-03-29 14:00:04 +01001979 if (!vif->dev)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001980 goto out_free;
1981
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001982#ifdef CONFIG_IPV6_PIMSM_V2
1983 if (vif->flags & MIFF_REGISTER) {
1984 vif->pkt_out++;
1985 vif->bytes_out += skb->len;
Pavel Emelyanovdc58c782008-05-21 14:17:54 -07001986 vif->dev->stats.tx_bytes += skb->len;
1987 vif->dev->stats.tx_packets++;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001988 ip6mr_cache_report(mrt, skb, vifi, MRT6MSG_WHOLEPKT);
Ilpo Järvinen8da73b72008-12-14 23:15:49 -08001989 goto out_free;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001990 }
1991#endif
1992
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001993 ipv6h = ipv6_hdr(skb);
1994
David S. Miller4c9483b2011-03-12 16:22:43 -05001995 fl6 = (struct flowi6) {
1996 .flowi6_oif = vif->link,
1997 .daddr = ipv6h->daddr,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001998 };
1999
David S. Miller4c9483b2011-03-12 16:22:43 -05002000 dst = ip6_route_output(net, NULL, &fl6);
RongQing.Li5095d642012-02-21 22:10:49 +00002001 if (dst->error) {
2002 dst_release(dst);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002003 goto out_free;
RongQing.Li5095d642012-02-21 22:10:49 +00002004 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002005
Eric Dumazetadf30902009-06-02 05:19:30 +00002006 skb_dst_drop(skb);
2007 skb_dst_set(skb, dst);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002008
2009 /*
2010 * RFC1584 teaches, that DVMRP/PIM router must deliver packets locally
2011 * not only before forwarding, but after forwarding on all output
2012 * interfaces. It is clear, if mrouter runs a multicasting
2013 * program, it should receive packets not depending to what interface
2014 * program is joined.
2015 * If we will not make it, the program will have to join on all
2016 * interfaces. On the other hand, multihoming host (or router, but
2017 * not mrouter) cannot join to more than one interface - it will
2018 * result in receiving multiple packets.
2019 */
2020 dev = vif->dev;
2021 skb->dev = dev;
2022 vif->pkt_out++;
2023 vif->bytes_out += skb->len;
2024
2025 /* We are about to write */
2026 /* XXX: extension headers? */
2027 if (skb_cow(skb, sizeof(*ipv6h) + LL_RESERVED_SPACE(dev)))
2028 goto out_free;
2029
2030 ipv6h = ipv6_hdr(skb);
2031 ipv6h->hop_limit--;
2032
2033 IP6CB(skb)->flags |= IP6SKB_FORWARDED;
2034
Eric W. Biederman29a26a52015-09-15 20:04:16 -05002035 return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD,
2036 net, NULL, skb, skb->dev, dev,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002037 ip6mr_forward2_finish);
2038
2039out_free:
2040 kfree_skb(skb);
2041 return 0;
2042}
2043
Yuval Mintzb70432f2018-02-28 23:29:32 +02002044static int ip6mr_find_vif(struct mr_table *mrt, struct net_device *dev)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002045{
2046 int ct;
Patrick McHardy6bd52142010-05-11 14:40:53 +02002047
2048 for (ct = mrt->maxvif - 1; ct >= 0; ct--) {
Yuval Mintzb70432f2018-02-28 23:29:32 +02002049 if (mrt->vif_table[ct].dev == dev)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002050 break;
2051 }
2052 return ct;
2053}
2054
Yuval Mintzb70432f2018-02-28 23:29:32 +02002055static void ip6_mr_forward(struct net *net, struct mr_table *mrt,
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002056 struct net_device *dev, struct sk_buff *skb,
2057 struct mfc6_cache *c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002058{
2059 int psend = -1;
2060 int vif, ct;
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002061 int true_vifi = ip6mr_find_vif(mrt, dev);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002062
Yuval Mintz494fff52018-02-28 23:29:34 +02002063 vif = c->_c.mfc_parent;
2064 c->_c.mfc_un.res.pkt++;
2065 c->_c.mfc_un.res.bytes += skb->len;
2066 c->_c.mfc_un.res.lastuse = jiffies;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002067
Yuval Mintz494fff52018-02-28 23:29:34 +02002068 if (ipv6_addr_any(&c->mf6c_origin) && true_vifi >= 0) {
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002069 struct mfc6_cache *cache_proxy;
2070
Fabian Frederick40dc2ca2014-10-29 10:00:26 +01002071 /* For an (*,G) entry, we only check that the incoming
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002072 * interface is part of the static tree.
2073 */
Yuval Mintz87c418b2018-02-28 23:29:31 +02002074 rcu_read_lock();
Yuval Mintz845c9a72018-02-28 23:29:35 +02002075 cache_proxy = mr_mfc_find_any_parent(mrt, vif);
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002076 if (cache_proxy &&
Yuval Mintz494fff52018-02-28 23:29:34 +02002077 cache_proxy->_c.mfc_un.res.ttls[true_vifi] < 255) {
Yuval Mintz87c418b2018-02-28 23:29:31 +02002078 rcu_read_unlock();
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002079 goto forward;
Yuval Mintz87c418b2018-02-28 23:29:31 +02002080 }
2081 rcu_read_unlock();
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002082 }
2083
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002084 /*
2085 * Wrong interface: drop packet and (maybe) send PIM assert.
2086 */
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002087 if (mrt->vif_table[vif].dev != dev) {
Yuval Mintz494fff52018-02-28 23:29:34 +02002088 c->_c.mfc_un.res.wrong_if++;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002089
Patrick McHardy6bd52142010-05-11 14:40:53 +02002090 if (true_vifi >= 0 && mrt->mroute_do_assert &&
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002091 /* pimsm uses asserts, when switching from RPT to SPT,
2092 so that we cannot check that packet arrived on an oif.
2093 It is bad, but otherwise we would need to move pretty
2094 large chunk of pimd to kernel. Ough... --ANK
2095 */
Patrick McHardy6bd52142010-05-11 14:40:53 +02002096 (mrt->mroute_do_pim ||
Yuval Mintz494fff52018-02-28 23:29:34 +02002097 c->_c.mfc_un.res.ttls[true_vifi] < 255) &&
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002098 time_after(jiffies,
Yuval Mintz494fff52018-02-28 23:29:34 +02002099 c->_c.mfc_un.res.last_assert +
2100 MFC_ASSERT_THRESH)) {
2101 c->_c.mfc_un.res.last_assert = jiffies;
Patrick McHardy6bd52142010-05-11 14:40:53 +02002102 ip6mr_cache_report(mrt, skb, true_vifi, MRT6MSG_WRONGMIF);
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002103 }
2104 goto dont_forward;
2105 }
2106
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002107forward:
Yuval Mintzb70432f2018-02-28 23:29:32 +02002108 mrt->vif_table[vif].pkt_in++;
2109 mrt->vif_table[vif].bytes_in += skb->len;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002110
2111 /*
2112 * Forward the frame
2113 */
Yuval Mintz494fff52018-02-28 23:29:34 +02002114 if (ipv6_addr_any(&c->mf6c_origin) &&
2115 ipv6_addr_any(&c->mf6c_mcastgrp)) {
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002116 if (true_vifi >= 0 &&
Yuval Mintz494fff52018-02-28 23:29:34 +02002117 true_vifi != c->_c.mfc_parent &&
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002118 ipv6_hdr(skb)->hop_limit >
Yuval Mintz494fff52018-02-28 23:29:34 +02002119 c->_c.mfc_un.res.ttls[c->_c.mfc_parent]) {
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002120 /* It's an (*,*) entry and the packet is not coming from
2121 * the upstream: forward the packet to the upstream
2122 * only.
2123 */
Yuval Mintz494fff52018-02-28 23:29:34 +02002124 psend = c->_c.mfc_parent;
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002125 goto last_forward;
2126 }
2127 goto dont_forward;
2128 }
Yuval Mintz494fff52018-02-28 23:29:34 +02002129 for (ct = c->_c.mfc_un.res.maxvif - 1;
2130 ct >= c->_c.mfc_un.res.minvif; ct--) {
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002131 /* For (*,G) entry, don't forward to the incoming interface */
Yuval Mintz494fff52018-02-28 23:29:34 +02002132 if ((!ipv6_addr_any(&c->mf6c_origin) || ct != true_vifi) &&
2133 ipv6_hdr(skb)->hop_limit > c->_c.mfc_un.res.ttls[ct]) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002134 if (psend != -1) {
2135 struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
2136 if (skb2)
Yuval Mintz494fff52018-02-28 23:29:34 +02002137 ip6mr_forward2(net, mrt, skb2,
2138 c, psend);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002139 }
2140 psend = ct;
2141 }
2142 }
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002143last_forward:
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002144 if (psend != -1) {
Yuval Mintz494fff52018-02-28 23:29:34 +02002145 ip6mr_forward2(net, mrt, skb, c, psend);
Rami Rosen2b52c3a2013-07-21 03:00:31 +03002146 return;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002147 }
2148
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002149dont_forward:
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002150 kfree_skb(skb);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002151}
2152
2153
2154/*
2155 * Multicast packets for forwarding arrive here
2156 */
2157
2158int ip6_mr_input(struct sk_buff *skb)
2159{
2160 struct mfc6_cache *cache;
Benjamin Thery8229efd2008-12-10 16:30:15 -08002161 struct net *net = dev_net(skb->dev);
Yuval Mintzb70432f2018-02-28 23:29:32 +02002162 struct mr_table *mrt;
David S. Miller4c9483b2011-03-12 16:22:43 -05002163 struct flowi6 fl6 = {
2164 .flowi6_iif = skb->dev->ifindex,
2165 .flowi6_mark = skb->mark,
Patrick McHardyd1db2752010-05-11 14:40:55 +02002166 };
2167 int err;
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002168 struct net_device *dev;
2169
2170 /* skb->dev passed in is the master dev for vrfs.
2171 * Get the proper interface that does have a vif associated with it.
2172 */
2173 dev = skb->dev;
2174 if (netif_is_l3_master(skb->dev)) {
2175 dev = dev_get_by_index_rcu(net, IPCB(skb)->iif);
2176 if (!dev) {
2177 kfree_skb(skb);
2178 return -ENODEV;
2179 }
2180 }
Patrick McHardyd1db2752010-05-11 14:40:55 +02002181
David S. Miller4c9483b2011-03-12 16:22:43 -05002182 err = ip6mr_fib_lookup(net, &fl6, &mrt);
Ben Greear2015de52011-09-27 15:16:08 -04002183 if (err < 0) {
2184 kfree_skb(skb);
Patrick McHardyd1db2752010-05-11 14:40:55 +02002185 return err;
Ben Greear2015de52011-09-27 15:16:08 -04002186 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002187
2188 read_lock(&mrt_lock);
Patrick McHardy6bd52142010-05-11 14:40:53 +02002189 cache = ip6mr_cache_find(mrt,
Benjamin Thery8229efd2008-12-10 16:30:15 -08002190 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr);
Ian Morris63159f22015-03-29 14:00:04 +01002191 if (!cache) {
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002192 int vif = ip6mr_find_vif(mrt, dev);
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002193
2194 if (vif >= 0)
2195 cache = ip6mr_cache_find_any(mrt,
2196 &ipv6_hdr(skb)->daddr,
2197 vif);
2198 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002199
2200 /*
2201 * No usable cache entry
2202 */
Ian Morris63159f22015-03-29 14:00:04 +01002203 if (!cache) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002204 int vif;
2205
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002206 vif = ip6mr_find_vif(mrt, dev);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002207 if (vif >= 0) {
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002208 int err = ip6mr_cache_unresolved(mrt, vif, skb, dev);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002209 read_unlock(&mrt_lock);
2210
2211 return err;
2212 }
2213 read_unlock(&mrt_lock);
2214 kfree_skb(skb);
2215 return -ENODEV;
2216 }
2217
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002218 ip6_mr_forward(net, mrt, dev, skb, cache);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002219
2220 read_unlock(&mrt_lock);
2221
2222 return 0;
2223}
2224
Nikolay Aleksandrov2cf75072016-09-25 23:08:31 +02002225int ip6mr_get_route(struct net *net, struct sk_buff *skb, struct rtmsg *rtm,
David Ahernfd61c6b2017-01-17 15:51:07 -08002226 u32 portid)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002227{
2228 int err;
Yuval Mintzb70432f2018-02-28 23:29:32 +02002229 struct mr_table *mrt;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002230 struct mfc6_cache *cache;
Eric Dumazetadf30902009-06-02 05:19:30 +00002231 struct rt6_info *rt = (struct rt6_info *)skb_dst(skb);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002232
Patrick McHardyd1db2752010-05-11 14:40:55 +02002233 mrt = ip6mr_get_table(net, RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +01002234 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +02002235 return -ENOENT;
2236
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002237 read_lock(&mrt_lock);
Patrick McHardy6bd52142010-05-11 14:40:53 +02002238 cache = ip6mr_cache_find(mrt, &rt->rt6i_src.addr, &rt->rt6i_dst.addr);
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002239 if (!cache && skb->dev) {
2240 int vif = ip6mr_find_vif(mrt, skb->dev);
2241
2242 if (vif >= 0)
2243 cache = ip6mr_cache_find_any(mrt, &rt->rt6i_dst.addr,
2244 vif);
2245 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002246
2247 if (!cache) {
2248 struct sk_buff *skb2;
2249 struct ipv6hdr *iph;
2250 struct net_device *dev;
2251 int vif;
2252
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002253 dev = skb->dev;
Ian Morris63159f22015-03-29 14:00:04 +01002254 if (!dev || (vif = ip6mr_find_vif(mrt, dev)) < 0) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002255 read_unlock(&mrt_lock);
2256 return -ENODEV;
2257 }
2258
2259 /* really correct? */
2260 skb2 = alloc_skb(sizeof(struct ipv6hdr), GFP_ATOMIC);
2261 if (!skb2) {
2262 read_unlock(&mrt_lock);
2263 return -ENOMEM;
2264 }
2265
Nikolay Aleksandrov2cf75072016-09-25 23:08:31 +02002266 NETLINK_CB(skb2).portid = portid;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002267 skb_reset_transport_header(skb2);
2268
2269 skb_put(skb2, sizeof(struct ipv6hdr));
2270 skb_reset_network_header(skb2);
2271
2272 iph = ipv6_hdr(skb2);
2273 iph->version = 0;
2274 iph->priority = 0;
2275 iph->flow_lbl[0] = 0;
2276 iph->flow_lbl[1] = 0;
2277 iph->flow_lbl[2] = 0;
2278 iph->payload_len = 0;
2279 iph->nexthdr = IPPROTO_NONE;
2280 iph->hop_limit = 0;
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +00002281 iph->saddr = rt->rt6i_src.addr;
2282 iph->daddr = rt->rt6i_dst.addr;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002283
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002284 err = ip6mr_cache_unresolved(mrt, vif, skb2, dev);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002285 read_unlock(&mrt_lock);
2286
2287 return err;
2288 }
2289
Yuval Mintz7b0db852018-02-28 23:29:39 +02002290 err = mr_fill_mroute(mrt, skb, &cache->_c, rtm);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002291 read_unlock(&mrt_lock);
2292 return err;
2293}
2294
Yuval Mintzb70432f2018-02-28 23:29:32 +02002295static int ip6mr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
Nicolas Dichtelf5183382014-03-19 17:47:51 +01002296 u32 portid, u32 seq, struct mfc6_cache *c, int cmd,
2297 int flags)
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002298{
2299 struct nlmsghdr *nlh;
2300 struct rtmsg *rtm;
Nicolas Dichtel1eb99af2012-12-04 01:13:39 +00002301 int err;
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002302
Nicolas Dichtelf5183382014-03-19 17:47:51 +01002303 nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rtm), flags);
Ian Morris63159f22015-03-29 14:00:04 +01002304 if (!nlh)
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002305 return -EMSGSIZE;
2306
2307 rtm = nlmsg_data(nlh);
Nicolas Dichtel193c1e42012-12-04 01:01:49 +00002308 rtm->rtm_family = RTNL_FAMILY_IP6MR;
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002309 rtm->rtm_dst_len = 128;
2310 rtm->rtm_src_len = 128;
2311 rtm->rtm_tos = 0;
2312 rtm->rtm_table = mrt->id;
David S. Millerc78679e2012-04-01 20:27:33 -04002313 if (nla_put_u32(skb, RTA_TABLE, mrt->id))
2314 goto nla_put_failure;
Nicolas Dichtel1eb99af2012-12-04 01:13:39 +00002315 rtm->rtm_type = RTN_MULTICAST;
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002316 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
Yuval Mintz494fff52018-02-28 23:29:34 +02002317 if (c->_c.mfc_flags & MFC_STATIC)
Nicolas Dichtel9a68ac72012-12-04 01:13:38 +00002318 rtm->rtm_protocol = RTPROT_STATIC;
2319 else
2320 rtm->rtm_protocol = RTPROT_MROUTED;
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002321 rtm->rtm_flags = 0;
2322
Jiri Benc930345e2015-03-29 16:59:25 +02002323 if (nla_put_in6_addr(skb, RTA_SRC, &c->mf6c_origin) ||
2324 nla_put_in6_addr(skb, RTA_DST, &c->mf6c_mcastgrp))
David S. Millerc78679e2012-04-01 20:27:33 -04002325 goto nla_put_failure;
Yuval Mintz7b0db852018-02-28 23:29:39 +02002326 err = mr_fill_mroute(mrt, skb, &c->_c, rtm);
Nicolas Dichtel1eb99af2012-12-04 01:13:39 +00002327 /* do not break the dump if cache is unresolved */
2328 if (err < 0 && err != -ENOENT)
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002329 goto nla_put_failure;
2330
Johannes Berg053c0952015-01-16 22:09:00 +01002331 nlmsg_end(skb, nlh);
2332 return 0;
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002333
2334nla_put_failure:
2335 nlmsg_cancel(skb, nlh);
2336 return -EMSGSIZE;
2337}
2338
Yuval Mintz7b0db852018-02-28 23:29:39 +02002339static int _ip6mr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
2340 u32 portid, u32 seq, struct mr_mfc *c,
2341 int cmd, int flags)
2342{
2343 return ip6mr_fill_mroute(mrt, skb, portid, seq, (struct mfc6_cache *)c,
2344 cmd, flags);
2345}
2346
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002347static int mr6_msgsize(bool unresolved, int maxvif)
2348{
2349 size_t len =
2350 NLMSG_ALIGN(sizeof(struct rtmsg))
2351 + nla_total_size(4) /* RTA_TABLE */
2352 + nla_total_size(sizeof(struct in6_addr)) /* RTA_SRC */
2353 + nla_total_size(sizeof(struct in6_addr)) /* RTA_DST */
2354 ;
2355
2356 if (!unresolved)
2357 len = len
2358 + nla_total_size(4) /* RTA_IIF */
2359 + nla_total_size(0) /* RTA_MULTIPATH */
2360 + maxvif * NLA_ALIGN(sizeof(struct rtnexthop))
2361 /* RTA_MFC_STATS */
Nicolas Dichtel3d6b66c2016-04-21 18:58:27 +02002362 + nla_total_size_64bit(sizeof(struct rta_mfc_stats))
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002363 ;
2364
2365 return len;
2366}
2367
Yuval Mintzb70432f2018-02-28 23:29:32 +02002368static void mr6_netlink_event(struct mr_table *mrt, struct mfc6_cache *mfc,
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002369 int cmd)
2370{
2371 struct net *net = read_pnet(&mrt->net);
2372 struct sk_buff *skb;
2373 int err = -ENOBUFS;
2374
Yuval Mintz494fff52018-02-28 23:29:34 +02002375 skb = nlmsg_new(mr6_msgsize(mfc->_c.mfc_parent >= MAXMIFS, mrt->maxvif),
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002376 GFP_ATOMIC);
Ian Morris63159f22015-03-29 14:00:04 +01002377 if (!skb)
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002378 goto errout;
2379
Nicolas Dichtelf5183382014-03-19 17:47:51 +01002380 err = ip6mr_fill_mroute(mrt, skb, 0, 0, mfc, cmd, 0);
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002381 if (err < 0)
2382 goto errout;
2383
2384 rtnl_notify(skb, net, 0, RTNLGRP_IPV6_MROUTE, NULL, GFP_ATOMIC);
2385 return;
2386
2387errout:
2388 kfree_skb(skb);
2389 if (err < 0)
2390 rtnl_set_sk_err(net, RTNLGRP_IPV6_MROUTE, err);
2391}
2392
Julien Gomesdd12d15c2017-06-20 13:54:18 -07002393static size_t mrt6msg_netlink_msgsize(size_t payloadlen)
2394{
2395 size_t len =
2396 NLMSG_ALIGN(sizeof(struct rtgenmsg))
2397 + nla_total_size(1) /* IP6MRA_CREPORT_MSGTYPE */
2398 + nla_total_size(4) /* IP6MRA_CREPORT_MIF_ID */
2399 /* IP6MRA_CREPORT_SRC_ADDR */
2400 + nla_total_size(sizeof(struct in6_addr))
2401 /* IP6MRA_CREPORT_DST_ADDR */
2402 + nla_total_size(sizeof(struct in6_addr))
2403 /* IP6MRA_CREPORT_PKT */
2404 + nla_total_size(payloadlen)
2405 ;
2406
2407 return len;
2408}
2409
Yuval Mintzb70432f2018-02-28 23:29:32 +02002410static void mrt6msg_netlink_event(struct mr_table *mrt, struct sk_buff *pkt)
Julien Gomesdd12d15c2017-06-20 13:54:18 -07002411{
2412 struct net *net = read_pnet(&mrt->net);
2413 struct nlmsghdr *nlh;
2414 struct rtgenmsg *rtgenm;
2415 struct mrt6msg *msg;
2416 struct sk_buff *skb;
2417 struct nlattr *nla;
2418 int payloadlen;
2419
2420 payloadlen = pkt->len - sizeof(struct mrt6msg);
2421 msg = (struct mrt6msg *)skb_transport_header(pkt);
2422
2423 skb = nlmsg_new(mrt6msg_netlink_msgsize(payloadlen), GFP_ATOMIC);
2424 if (!skb)
2425 goto errout;
2426
2427 nlh = nlmsg_put(skb, 0, 0, RTM_NEWCACHEREPORT,
2428 sizeof(struct rtgenmsg), 0);
2429 if (!nlh)
2430 goto errout;
2431 rtgenm = nlmsg_data(nlh);
2432 rtgenm->rtgen_family = RTNL_FAMILY_IP6MR;
2433 if (nla_put_u8(skb, IP6MRA_CREPORT_MSGTYPE, msg->im6_msgtype) ||
2434 nla_put_u32(skb, IP6MRA_CREPORT_MIF_ID, msg->im6_mif) ||
2435 nla_put_in6_addr(skb, IP6MRA_CREPORT_SRC_ADDR,
2436 &msg->im6_src) ||
2437 nla_put_in6_addr(skb, IP6MRA_CREPORT_DST_ADDR,
2438 &msg->im6_dst))
2439 goto nla_put_failure;
2440
2441 nla = nla_reserve(skb, IP6MRA_CREPORT_PKT, payloadlen);
2442 if (!nla || skb_copy_bits(pkt, sizeof(struct mrt6msg),
2443 nla_data(nla), payloadlen))
2444 goto nla_put_failure;
2445
2446 nlmsg_end(skb, nlh);
2447
2448 rtnl_notify(skb, net, 0, RTNLGRP_IPV6_MROUTE_R, NULL, GFP_ATOMIC);
2449 return;
2450
2451nla_put_failure:
2452 nlmsg_cancel(skb, nlh);
2453errout:
2454 kfree_skb(skb);
2455 rtnl_set_sk_err(net, RTNLGRP_IPV6_MROUTE_R, -ENOBUFS);
2456}
2457
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002458static int ip6mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
2459{
Yuval Mintz7b0db852018-02-28 23:29:39 +02002460 return mr_rtm_dumproute(skb, cb, ip6mr_mr_table_iter,
2461 _ip6mr_fill_mroute, &mfc_unres_lock);
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002462}