blob: 8a2db926b5eb6ab2e08691ad7244c504611540e6 [file] [log] [blame]
Thomas Gleixner2874c5f2019-05-27 08:55:01 +02001// SPDX-License-Identifier: GPL-2.0-or-later
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002/*
3 * Linux IPv6 multicast routing support for BSD pim6sd
4 * Based on net/ipv4/ipmr.c.
5 *
6 * (c) 2004 Mickael Hoerdt, <hoerdt@clarinet.u-strasbg.fr>
7 * LSIIT Laboratory, Strasbourg, France
8 * (c) 2004 Jean-Philippe Andriot, <jean-philippe.andriot@6WIND.com>
9 * 6WIND, Paris, France
10 * Copyright (C)2007,2008 USAGI/WIDE Project
11 * YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090012 */
13
Linus Torvalds7c0f6ba2016-12-24 11:46:01 -080014#include <linux/uaccess.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090015#include <linux/types.h>
16#include <linux/sched.h>
17#include <linux/errno.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090018#include <linux/mm.h>
19#include <linux/kernel.h>
20#include <linux/fcntl.h>
21#include <linux/stat.h>
22#include <linux/socket.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090023#include <linux/inet.h>
24#include <linux/netdevice.h>
25#include <linux/inetdevice.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090026#include <linux/proc_fs.h>
27#include <linux/seq_file.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090028#include <linux/init.h>
David S. Millere2d57762011-02-03 17:59:32 -080029#include <linux/compat.h>
NeilBrown0eb71a92018-06-18 12:52:50 +100030#include <linux/rhashtable.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090031#include <net/protocol.h>
32#include <linux/skbuff.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090033#include <net/raw.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090034#include <linux/notifier.h>
35#include <linux/if_arp.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090036#include <net/checksum.h>
37#include <net/netlink.h>
Patrick McHardyd1db2752010-05-11 14:40:55 +020038#include <net/fib_rules.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090039
40#include <net/ipv6.h>
41#include <net/ip6_route.h>
42#include <linux/mroute6.h>
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +090043#include <linux/pim.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090044#include <net/addrconf.h>
45#include <linux/netfilter_ipv6.h>
Paul Gortmakerbc3b2d72011-07-15 11:47:34 -040046#include <linux/export.h>
Dave Jones5d6e4302009-01-31 00:51:49 -080047#include <net/ip6_checksum.h>
Nicolas Dichteld67b8c62012-12-04 01:13:35 +000048#include <linux/netconf.h>
Willem de Bruijncb9f1b72018-12-30 17:24:36 -050049#include <net/ip_tunnels.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090050
Gustavo A. R. Silva69d2c862018-12-11 14:10:08 -060051#include <linux/nospec.h>
52
Patrick McHardyd1db2752010-05-11 14:40:55 +020053struct ip6mr_rule {
54 struct fib_rule common;
55};
56
57struct ip6mr_result {
Yuval Mintzb70432f2018-02-28 23:29:32 +020058 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +020059};
60
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090061/* Big lock, protecting vif table, mrt cache and mroute socket state.
62 Note that the changes are semaphored via rtnl_lock.
63 */
64
65static DEFINE_RWLOCK(mrt_lock);
66
Yuval Mintzb70432f2018-02-28 23:29:32 +020067/* Multicast router control variables */
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090068
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090069/* Special spinlock for queue of unresolved entries */
70static DEFINE_SPINLOCK(mfc_unres_lock);
71
72/* We return to original Alan's scheme. Hash table of resolved
73 entries is changed only in process context and protected
74 with weak lock mrt_lock. Queue of unresolved entries is protected
75 with strong spinlock mfc_unres_lock.
76
77 In this case data path is free of exclusive locks at all.
78 */
79
80static struct kmem_cache *mrt_cachep __read_mostly;
81
Yuval Mintzb70432f2018-02-28 23:29:32 +020082static struct mr_table *ip6mr_new_table(struct net *net, u32 id);
83static void ip6mr_free_table(struct mr_table *mrt);
Patrick McHardyd1db2752010-05-11 14:40:55 +020084
Yuval Mintzb70432f2018-02-28 23:29:32 +020085static void ip6_mr_forward(struct net *net, struct mr_table *mrt,
Patrick Ruddye4a38c02018-10-01 09:41:27 +010086 struct net_device *dev, struct sk_buff *skb,
87 struct mfc6_cache *cache);
Yuval Mintzb70432f2018-02-28 23:29:32 +020088static int ip6mr_cache_report(struct mr_table *mrt, struct sk_buff *pkt,
Benjamin Thery8229efd2008-12-10 16:30:15 -080089 mifi_t mifi, int assert);
Yuval Mintzb70432f2018-02-28 23:29:32 +020090static void mr6_netlink_event(struct mr_table *mrt, struct mfc6_cache *mfc,
Nicolas Dichtel812e44d2012-12-04 01:13:41 +000091 int cmd);
Yuval Mintzb70432f2018-02-28 23:29:32 +020092static void mrt6msg_netlink_event(struct mr_table *mrt, struct sk_buff *pkt);
Patrick McHardy5b285ca2010-05-11 14:40:56 +020093static int ip6mr_rtm_dumproute(struct sk_buff *skb,
94 struct netlink_callback *cb);
Callum Sinclairca8d4792019-02-18 10:07:52 +130095static void mroute_clean_tables(struct mr_table *mrt, int flags);
Kees Cooke99e88a2017-10-16 14:43:17 -070096static void ipmr_expire_process(struct timer_list *t);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090097
Patrick McHardyd1db2752010-05-11 14:40:55 +020098#ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
Eric Dumazet8ffb3352010-06-06 15:34:40 -070099#define ip6mr_for_each_table(mrt, net) \
Amol Grover28b380e2020-02-22 22:27:27 +0530100 list_for_each_entry_rcu(mrt, &net->ipv6.mr6_tables, list, \
Madhuparna Bhowmikb6dd5ac2020-05-16 13:15:15 +0530101 lockdep_rtnl_is_held() || \
102 list_empty(&net->ipv6.mr6_tables))
Patrick McHardyd1db2752010-05-11 14:40:55 +0200103
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
Patrick McHardyd1db2752010-05-11 14:40:55 +0200185static int ip6mr_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
Roopa Prabhub16fb412018-04-21 09:41:31 -0700186 struct fib_rule_hdr *frh, struct nlattr **tb,
187 struct netlink_ext_ack *extack)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200188{
189 return 0;
190}
191
192static int ip6mr_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
193 struct nlattr **tb)
194{
195 return 1;
196}
197
198static int ip6mr_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
199 struct fib_rule_hdr *frh)
200{
201 frh->dst_len = 0;
202 frh->src_len = 0;
203 frh->tos = 0;
204 return 0;
205}
206
Andi Kleen04a6f822012-10-04 17:12:11 -0700207static const struct fib_rules_ops __net_initconst ip6mr_rules_ops_template = {
Patrick McHardyd1db2752010-05-11 14:40:55 +0200208 .family = RTNL_FAMILY_IP6MR,
209 .rule_size = sizeof(struct ip6mr_rule),
210 .addr_size = sizeof(struct in6_addr),
211 .action = ip6mr_rule_action,
212 .match = ip6mr_rule_match,
213 .configure = ip6mr_rule_configure,
214 .compare = ip6mr_rule_compare,
Patrick McHardyd1db2752010-05-11 14:40:55 +0200215 .fill = ip6mr_rule_fill,
216 .nlgroup = RTNLGRP_IPV6_RULE,
Patrick McHardyd1db2752010-05-11 14:40:55 +0200217 .owner = THIS_MODULE,
218};
219
220static int __net_init ip6mr_rules_init(struct net *net)
221{
222 struct fib_rules_ops *ops;
Yuval Mintzb70432f2018-02-28 23:29:32 +0200223 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200224 int err;
225
226 ops = fib_rules_register(&ip6mr_rules_ops_template, net);
227 if (IS_ERR(ops))
228 return PTR_ERR(ops);
229
230 INIT_LIST_HEAD(&net->ipv6.mr6_tables);
231
232 mrt = ip6mr_new_table(net, RT6_TABLE_DFLT);
Sabrina Dubrocae783bb02018-06-05 15:02:00 +0200233 if (IS_ERR(mrt)) {
234 err = PTR_ERR(mrt);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200235 goto err1;
236 }
237
238 err = fib_default_rule_add(ops, 0x7fff, RT6_TABLE_DFLT, 0);
239 if (err < 0)
240 goto err2;
241
242 net->ipv6.mr6_rules_ops = ops;
243 return 0;
244
245err2:
Eric Dumazet5611a002022-02-07 21:34:51 -0800246 rtnl_lock();
WANG Congf243e5a2015-03-25 14:45:03 -0700247 ip6mr_free_table(mrt);
Eric Dumazet5611a002022-02-07 21:34:51 -0800248 rtnl_unlock();
Patrick McHardyd1db2752010-05-11 14:40:55 +0200249err1:
250 fib_rules_unregister(ops);
251 return err;
252}
253
254static void __net_exit ip6mr_rules_exit(struct net *net)
255{
Yuval Mintzb70432f2018-02-28 23:29:32 +0200256 struct mr_table *mrt, *next;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200257
Hannes Frederic Sowa905a6f92013-07-22 23:45:53 +0200258 rtnl_lock();
Eric Dumazet035320d2010-06-06 23:48:40 +0000259 list_for_each_entry_safe(mrt, next, &net->ipv6.mr6_tables, list) {
260 list_del(&mrt->list);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200261 ip6mr_free_table(mrt);
Eric Dumazet035320d2010-06-06 23:48:40 +0000262 }
Patrick McHardyd1db2752010-05-11 14:40:55 +0200263 fib_rules_unregister(net->ipv6.mr6_rules_ops);
WANG Cong419df122015-03-31 11:01:46 -0700264 rtnl_unlock();
Patrick McHardyd1db2752010-05-11 14:40:55 +0200265}
Yuval Mintz088aa3e2018-03-26 15:01:34 +0300266
Jiri Pirkob7a59552019-10-03 11:49:30 +0200267static int ip6mr_rules_dump(struct net *net, struct notifier_block *nb,
268 struct netlink_ext_ack *extack)
Yuval Mintz088aa3e2018-03-26 15:01:34 +0300269{
Jiri Pirkob7a59552019-10-03 11:49:30 +0200270 return fib_rules_dump(net, nb, RTNL_FAMILY_IP6MR, extack);
Yuval Mintz088aa3e2018-03-26 15:01:34 +0300271}
272
273static unsigned int ip6mr_rules_seq_read(struct net *net)
274{
275 return fib_rules_seq_read(net, RTNL_FAMILY_IP6MR);
276}
Yuval Mintzd3c07e52018-03-26 15:01:35 +0300277
278bool ip6mr_rule_default(const struct fib_rule *rule)
279{
280 return fib_rule_matchall(rule) && rule->action == FR_ACT_TO_TBL &&
281 rule->table == RT6_TABLE_DFLT && !rule->l3mdev;
282}
283EXPORT_SYMBOL(ip6mr_rule_default);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200284#else
285#define ip6mr_for_each_table(mrt, net) \
286 for (mrt = net->ipv6.mrt6; mrt; mrt = NULL)
287
Yuval Mintz7b0db852018-02-28 23:29:39 +0200288static struct mr_table *ip6mr_mr_table_iter(struct net *net,
289 struct mr_table *mrt)
290{
291 if (!mrt)
292 return net->ipv6.mrt6;
293 return NULL;
294}
295
Yuval Mintzb70432f2018-02-28 23:29:32 +0200296static struct mr_table *ip6mr_get_table(struct net *net, u32 id)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200297{
298 return net->ipv6.mrt6;
299}
300
David S. Miller4c9483b2011-03-12 16:22:43 -0500301static int ip6mr_fib_lookup(struct net *net, struct flowi6 *flp6,
Yuval Mintzb70432f2018-02-28 23:29:32 +0200302 struct mr_table **mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200303{
304 *mrt = net->ipv6.mrt6;
305 return 0;
306}
307
308static int __net_init ip6mr_rules_init(struct net *net)
309{
Sabrina Dubrocae783bb02018-06-05 15:02:00 +0200310 struct mr_table *mrt;
311
312 mrt = ip6mr_new_table(net, RT6_TABLE_DFLT);
313 if (IS_ERR(mrt))
314 return PTR_ERR(mrt);
315 net->ipv6.mrt6 = mrt;
316 return 0;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200317}
318
319static void __net_exit ip6mr_rules_exit(struct net *net)
320{
Hannes Frederic Sowa905a6f92013-07-22 23:45:53 +0200321 rtnl_lock();
Patrick McHardyd1db2752010-05-11 14:40:55 +0200322 ip6mr_free_table(net->ipv6.mrt6);
Hannes Frederic Sowa905a6f92013-07-22 23:45:53 +0200323 net->ipv6.mrt6 = NULL;
324 rtnl_unlock();
Patrick McHardyd1db2752010-05-11 14:40:55 +0200325}
Yuval Mintz088aa3e2018-03-26 15:01:34 +0300326
Jiri Pirkob7a59552019-10-03 11:49:30 +0200327static int ip6mr_rules_dump(struct net *net, struct notifier_block *nb,
328 struct netlink_ext_ack *extack)
Yuval Mintz088aa3e2018-03-26 15:01:34 +0300329{
330 return 0;
331}
332
333static unsigned int ip6mr_rules_seq_read(struct net *net)
334{
335 return 0;
336}
Patrick McHardyd1db2752010-05-11 14:40:55 +0200337#endif
338
Yuval Mintz87c418b2018-02-28 23:29:31 +0200339static int ip6mr_hash_cmp(struct rhashtable_compare_arg *arg,
340 const void *ptr)
341{
342 const struct mfc6_cache_cmp_arg *cmparg = arg->key;
343 struct mfc6_cache *c = (struct mfc6_cache *)ptr;
344
345 return !ipv6_addr_equal(&c->mf6c_mcastgrp, &cmparg->mf6c_mcastgrp) ||
346 !ipv6_addr_equal(&c->mf6c_origin, &cmparg->mf6c_origin);
347}
348
349static const struct rhashtable_params ip6mr_rht_params = {
Yuval Mintz494fff52018-02-28 23:29:34 +0200350 .head_offset = offsetof(struct mr_mfc, mnode),
Yuval Mintz87c418b2018-02-28 23:29:31 +0200351 .key_offset = offsetof(struct mfc6_cache, cmparg),
352 .key_len = sizeof(struct mfc6_cache_cmp_arg),
353 .nelem_hint = 3,
Yuval Mintz87c418b2018-02-28 23:29:31 +0200354 .obj_cmpfn = ip6mr_hash_cmp,
355 .automatic_shrinking = true,
356};
357
Yuval Mintz0bbbf0e2018-02-28 23:29:33 +0200358static void ip6mr_new_table_set(struct mr_table *mrt,
359 struct net *net)
360{
361#ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
362 list_add_tail_rcu(&mrt->list, &net->ipv6.mr6_tables);
363#endif
364}
365
Yuval Mintz845c9a72018-02-28 23:29:35 +0200366static struct mfc6_cache_cmp_arg ip6mr_mr_table_ops_cmparg_any = {
367 .mf6c_origin = IN6ADDR_ANY_INIT,
368 .mf6c_mcastgrp = IN6ADDR_ANY_INIT,
369};
370
371static struct mr_table_ops ip6mr_mr_table_ops = {
372 .rht_params = &ip6mr_rht_params,
373 .cmparg_any = &ip6mr_mr_table_ops_cmparg_any,
374};
375
Yuval Mintzb70432f2018-02-28 23:29:32 +0200376static struct mr_table *ip6mr_new_table(struct net *net, u32 id)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200377{
Yuval Mintzb70432f2018-02-28 23:29:32 +0200378 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200379
380 mrt = ip6mr_get_table(net, id);
Ian Morris53b24b82015-03-29 14:00:05 +0100381 if (mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200382 return mrt;
383
Yuval Mintz845c9a72018-02-28 23:29:35 +0200384 return mr_table_alloc(net, id, &ip6mr_mr_table_ops,
Yuval Mintz0bbbf0e2018-02-28 23:29:33 +0200385 ipmr_expire_process, ip6mr_new_table_set);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200386}
387
Yuval Mintzb70432f2018-02-28 23:29:32 +0200388static void ip6mr_free_table(struct mr_table *mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200389{
WANG Cong7ba0c472015-03-31 11:01:47 -0700390 del_timer_sync(&mrt->ipmr_expire_timer);
Callum Sinclairca8d4792019-02-18 10:07:52 +1300391 mroute_clean_tables(mrt, MRT6_FLUSH_MIFS | MRT6_FLUSH_MIFS_STATIC |
392 MRT6_FLUSH_MFC | MRT6_FLUSH_MFC_STATIC);
Yuval Mintzb70432f2018-02-28 23:29:32 +0200393 rhltable_destroy(&mrt->mfc_hash);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200394 kfree(mrt);
395}
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900396
397#ifdef CONFIG_PROC_FS
Yuval Mintzc8d61962018-02-28 23:29:36 +0200398/* The /proc interfaces to multicast routing
399 * /proc/ip6_mr_cache /proc/ip6_mr_vif
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900400 */
401
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900402static void *ip6mr_vif_seq_start(struct seq_file *seq, loff_t *pos)
403 __acquires(mrt_lock)
404{
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200405 struct mr_vif_iter *iter = seq->private;
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800406 struct net *net = seq_file_net(seq);
Yuval Mintzb70432f2018-02-28 23:29:32 +0200407 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200408
409 mrt = ip6mr_get_table(net, RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +0100410 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200411 return ERR_PTR(-ENOENT);
412
413 iter->mrt = mrt;
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800414
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900415 read_lock(&mrt_lock);
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200416 return mr_vif_seq_start(seq, pos);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900417}
418
419static void ip6mr_vif_seq_stop(struct seq_file *seq, void *v)
420 __releases(mrt_lock)
421{
422 read_unlock(&mrt_lock);
423}
424
425static int ip6mr_vif_seq_show(struct seq_file *seq, void *v)
426{
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200427 struct mr_vif_iter *iter = seq->private;
Yuval Mintzb70432f2018-02-28 23:29:32 +0200428 struct mr_table *mrt = iter->mrt;
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800429
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900430 if (v == SEQ_START_TOKEN) {
431 seq_puts(seq,
432 "Interface BytesIn PktsIn BytesOut PktsOut Flags\n");
433 } else {
Yuval Mintz6853f212018-02-28 23:29:29 +0200434 const struct vif_device *vif = v;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900435 const char *name = vif->dev ? vif->dev->name : "none";
436
437 seq_printf(seq,
Al Virod430a222008-06-02 10:59:02 +0100438 "%2td %-10s %8ld %7ld %8ld %7ld %05X\n",
Yuval Mintzb70432f2018-02-28 23:29:32 +0200439 vif - mrt->vif_table,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900440 name, vif->bytes_in, vif->pkt_in,
441 vif->bytes_out, vif->pkt_out,
442 vif->flags);
443 }
444 return 0;
445}
446
Stephen Hemminger98147d52009-09-01 19:25:02 +0000447static const struct seq_operations ip6mr_vif_seq_ops = {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900448 .start = ip6mr_vif_seq_start,
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200449 .next = mr_vif_seq_next,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900450 .stop = ip6mr_vif_seq_stop,
451 .show = ip6mr_vif_seq_show,
452};
453
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900454static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos)
455{
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800456 struct net *net = seq_file_net(seq);
Yuval Mintzb70432f2018-02-28 23:29:32 +0200457 struct mr_table *mrt;
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800458
Patrick McHardyd1db2752010-05-11 14:40:55 +0200459 mrt = ip6mr_get_table(net, RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +0100460 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200461 return ERR_PTR(-ENOENT);
462
Yuval Mintzc8d61962018-02-28 23:29:36 +0200463 return mr_mfc_seq_start(seq, pos, mrt, &mfc_unres_lock);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900464}
465
466static int ipmr_mfc_seq_show(struct seq_file *seq, void *v)
467{
468 int n;
469
470 if (v == SEQ_START_TOKEN) {
471 seq_puts(seq,
472 "Group "
473 "Origin "
474 "Iif Pkts Bytes Wrong Oifs\n");
475 } else {
476 const struct mfc6_cache *mfc = v;
Yuval Mintzc8d61962018-02-28 23:29:36 +0200477 const struct mr_mfc_iter *it = seq->private;
Yuval Mintzb70432f2018-02-28 23:29:32 +0200478 struct mr_table *mrt = it->mrt;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900479
Benjamin Thery999890b2008-12-03 22:22:16 -0800480 seq_printf(seq, "%pI6 %pI6 %-3hd",
Harvey Harrison0c6ce782008-10-28 16:09:23 -0700481 &mfc->mf6c_mcastgrp, &mfc->mf6c_origin,
Yuval Mintz494fff52018-02-28 23:29:34 +0200482 mfc->_c.mfc_parent);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900483
Yuval Mintzb70432f2018-02-28 23:29:32 +0200484 if (it->cache != &mrt->mfc_unres_queue) {
Benjamin Thery1ea472e2008-12-03 22:21:47 -0800485 seq_printf(seq, " %8lu %8lu %8lu",
Yuval Mintz494fff52018-02-28 23:29:34 +0200486 mfc->_c.mfc_un.res.pkt,
487 mfc->_c.mfc_un.res.bytes,
488 mfc->_c.mfc_un.res.wrong_if);
489 for (n = mfc->_c.mfc_un.res.minvif;
490 n < mfc->_c.mfc_un.res.maxvif; n++) {
Yuval Mintzb70432f2018-02-28 23:29:32 +0200491 if (VIF_EXISTS(mrt, n) &&
Yuval Mintz494fff52018-02-28 23:29:34 +0200492 mfc->_c.mfc_un.res.ttls[n] < 255)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900493 seq_printf(seq,
Yuval Mintz494fff52018-02-28 23:29:34 +0200494 " %2d:%-3d", n,
495 mfc->_c.mfc_un.res.ttls[n]);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900496 }
Benjamin Thery1ea472e2008-12-03 22:21:47 -0800497 } else {
498 /* unresolved mfc_caches don't contain
499 * pkt, bytes and wrong_if values
500 */
501 seq_printf(seq, " %8lu %8lu %8lu", 0ul, 0ul, 0ul);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900502 }
503 seq_putc(seq, '\n');
504 }
505 return 0;
506}
507
James Morris88e9d342009-09-22 16:43:43 -0700508static const struct seq_operations ipmr_mfc_seq_ops = {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900509 .start = ipmr_mfc_seq_start,
Yuval Mintzc8d61962018-02-28 23:29:36 +0200510 .next = mr_mfc_seq_next,
511 .stop = mr_mfc_seq_stop,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900512 .show = ipmr_mfc_seq_show,
513};
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900514#endif
515
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900516#ifdef CONFIG_IPV6_PIMSM_V2
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900517
518static int pim6_rcv(struct sk_buff *skb)
519{
520 struct pimreghdr *pim;
521 struct ipv6hdr *encap;
522 struct net_device *reg_dev = NULL;
Benjamin Thery8229efd2008-12-10 16:30:15 -0800523 struct net *net = dev_net(skb->dev);
Yuval Mintzb70432f2018-02-28 23:29:32 +0200524 struct mr_table *mrt;
David S. Miller4c9483b2011-03-12 16:22:43 -0500525 struct flowi6 fl6 = {
526 .flowi6_iif = skb->dev->ifindex,
527 .flowi6_mark = skb->mark,
Patrick McHardyd1db2752010-05-11 14:40:55 +0200528 };
529 int reg_vif_num;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900530
531 if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(*encap)))
532 goto drop;
533
534 pim = (struct pimreghdr *)skb_transport_header(skb);
Nikolay Aleksandrov56245ca2016-10-31 13:21:04 +0100535 if (pim->type != ((PIM_VERSION << 4) | PIM_TYPE_REGISTER) ||
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900536 (pim->flags & PIM_NULL_REGISTER) ||
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800537 (csum_ipv6_magic(&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
538 sizeof(*pim), IPPROTO_PIM,
539 csum_partial((void *)pim, sizeof(*pim), 0)) &&
Al Viroec6b4862008-04-26 22:28:58 -0700540 csum_fold(skb_checksum(skb, 0, skb->len, 0))))
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900541 goto drop;
542
543 /* check if the inner packet is destined to mcast group */
544 encap = (struct ipv6hdr *)(skb_transport_header(skb) +
545 sizeof(*pim));
546
547 if (!ipv6_addr_is_multicast(&encap->daddr) ||
548 encap->payload_len == 0 ||
549 ntohs(encap->payload_len) + sizeof(*pim) > skb->len)
550 goto drop;
551
David S. Miller4c9483b2011-03-12 16:22:43 -0500552 if (ip6mr_fib_lookup(net, &fl6, &mrt) < 0)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200553 goto drop;
554 reg_vif_num = mrt->mroute_reg_vif_num;
555
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900556 read_lock(&mrt_lock);
557 if (reg_vif_num >= 0)
Yuval Mintzb70432f2018-02-28 23:29:32 +0200558 reg_dev = mrt->vif_table[reg_vif_num].dev;
Yajun Deng1160dfa2021-08-05 19:55:27 +0800559 dev_hold(reg_dev);
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900560 read_unlock(&mrt_lock);
561
Ian Morris63159f22015-03-29 14:00:04 +0100562 if (!reg_dev)
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900563 goto drop;
564
565 skb->mac_header = skb->network_header;
566 skb_pull(skb, (u8 *)encap - skb->data);
567 skb_reset_network_header(skb);
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800568 skb->protocol = htons(ETH_P_IPV6);
Cesar Eduardo Barros3e49e6d2011-03-26 05:10:30 +0000569 skb->ip_summed = CHECKSUM_NONE;
Eric Dumazetd19d56d2010-05-17 22:36:55 -0700570
Nicolas Dichtelea231922013-09-02 15:34:58 +0200571 skb_tunnel_rx(skb, reg_dev, dev_net(reg_dev));
Eric Dumazetd19d56d2010-05-17 22:36:55 -0700572
Eric Dumazetcaf586e2010-09-30 21:06:55 +0000573 netif_rx(skb);
Eric Dumazet8990f462010-09-20 00:12:11 +0000574
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900575 dev_put(reg_dev);
576 return 0;
577 drop:
578 kfree_skb(skb);
579 return 0;
580}
581
Alexey Dobriyan41135cc2009-09-14 12:22:28 +0000582static const struct inet6_protocol pim6_protocol = {
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900583 .handler = pim6_rcv,
584};
585
586/* Service routines creating virtual interfaces: PIMREG */
587
Stephen Hemminger6fef4c02009-08-31 19:50:41 +0000588static netdev_tx_t reg_vif_xmit(struct sk_buff *skb,
589 struct net_device *dev)
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900590{
Benjamin Thery8229efd2008-12-10 16:30:15 -0800591 struct net *net = dev_net(dev);
Yuval Mintzb70432f2018-02-28 23:29:32 +0200592 struct mr_table *mrt;
David S. Miller4c9483b2011-03-12 16:22:43 -0500593 struct flowi6 fl6 = {
594 .flowi6_oif = dev->ifindex,
Cong Wang6a662712014-04-15 16:25:34 -0700595 .flowi6_iif = skb->skb_iif ? : LOOPBACK_IFINDEX,
David S. Miller4c9483b2011-03-12 16:22:43 -0500596 .flowi6_mark = skb->mark,
Patrick McHardyd1db2752010-05-11 14:40:55 +0200597 };
Patrick McHardyd1db2752010-05-11 14:40:55 +0200598
Willem de Bruijncb9f1b72018-12-30 17:24:36 -0500599 if (!pskb_inet_may_pull(skb))
600 goto tx_err;
601
602 if (ip6mr_fib_lookup(net, &fl6, &mrt) < 0)
603 goto tx_err;
Benjamin Thery8229efd2008-12-10 16:30:15 -0800604
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900605 read_lock(&mrt_lock);
Pavel Emelyanovdc58c782008-05-21 14:17:54 -0700606 dev->stats.tx_bytes += skb->len;
607 dev->stats.tx_packets++;
Patrick McHardy6bd52142010-05-11 14:40:53 +0200608 ip6mr_cache_report(mrt, skb, mrt->mroute_reg_vif_num, MRT6MSG_WHOLEPKT);
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900609 read_unlock(&mrt_lock);
610 kfree_skb(skb);
Patrick McHardy6ed10652009-06-23 06:03:08 +0000611 return NETDEV_TX_OK;
Willem de Bruijncb9f1b72018-12-30 17:24:36 -0500612
613tx_err:
614 dev->stats.tx_errors++;
615 kfree_skb(skb);
616 return NETDEV_TX_OK;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900617}
618
Nicolas Dichtelee9b9592015-04-02 17:07:03 +0200619static int reg_vif_get_iflink(const struct net_device *dev)
620{
621 return 0;
622}
623
Stephen Hemminger007c3832008-11-20 20:28:35 -0800624static const struct net_device_ops reg_vif_netdev_ops = {
625 .ndo_start_xmit = reg_vif_xmit,
Nicolas Dichtelee9b9592015-04-02 17:07:03 +0200626 .ndo_get_iflink = reg_vif_get_iflink,
Stephen Hemminger007c3832008-11-20 20:28:35 -0800627};
628
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900629static void reg_vif_setup(struct net_device *dev)
630{
631 dev->type = ARPHRD_PIMREG;
632 dev->mtu = 1500 - sizeof(struct ipv6hdr) - 8;
633 dev->flags = IFF_NOARP;
Stephen Hemminger007c3832008-11-20 20:28:35 -0800634 dev->netdev_ops = &reg_vif_netdev_ops;
David S. Millercf124db2017-05-08 12:52:56 -0400635 dev->needs_free_netdev = true;
Tom Goff403dbb92009-06-14 03:16:13 -0700636 dev->features |= NETIF_F_NETNS_LOCAL;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900637}
638
Yuval Mintzb70432f2018-02-28 23:29:32 +0200639static struct net_device *ip6mr_reg_vif(struct net *net, struct mr_table *mrt)
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900640{
641 struct net_device *dev;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200642 char name[IFNAMSIZ];
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900643
Patrick McHardyd1db2752010-05-11 14:40:55 +0200644 if (mrt->id == RT6_TABLE_DFLT)
645 sprintf(name, "pim6reg");
646 else
647 sprintf(name, "pim6reg%u", mrt->id);
648
Tom Gundersenc835a672014-07-14 16:37:24 +0200649 dev = alloc_netdev(0, name, NET_NAME_UNKNOWN, reg_vif_setup);
Ian Morris63159f22015-03-29 14:00:04 +0100650 if (!dev)
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900651 return NULL;
652
Benjamin Thery8229efd2008-12-10 16:30:15 -0800653 dev_net_set(dev, net);
654
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900655 if (register_netdevice(dev)) {
656 free_netdev(dev);
657 return NULL;
658 }
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900659
Petr Machata00f54e62018-12-06 17:05:36 +0000660 if (dev_open(dev, NULL))
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900661 goto failure;
662
Wang Chen7af3db72008-07-14 20:54:54 -0700663 dev_hold(dev);
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900664 return dev;
665
666failure:
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900667 unregister_netdevice(dev);
668 return NULL;
669}
670#endif
671
Yuval Mintz088aa3e2018-03-26 15:01:34 +0300672static int call_ip6mr_vif_entry_notifiers(struct net *net,
673 enum fib_event_type event_type,
674 struct vif_device *vif,
675 mifi_t vif_index, u32 tb_id)
676{
677 return mr_call_vif_notifiers(net, RTNL_FAMILY_IP6MR, event_type,
678 vif, vif_index, tb_id,
679 &net->ipv6.ipmr_seq);
680}
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900681
Yuval Mintz088aa3e2018-03-26 15:01:34 +0300682static int call_ip6mr_mfc_entry_notifiers(struct net *net,
683 enum fib_event_type event_type,
684 struct mfc6_cache *mfc, u32 tb_id)
685{
686 return mr_call_mfc_notifiers(net, RTNL_FAMILY_IP6MR, event_type,
687 &mfc->_c, tb_id, &net->ipv6.ipmr_seq);
688}
689
690/* Delete a VIF entry */
Yuval Mintzb70432f2018-02-28 23:29:32 +0200691static int mif6_delete(struct mr_table *mrt, int vifi, int notify,
Nikolay Aleksandrov723b9292017-04-21 20:42:16 +0300692 struct list_head *head)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900693{
Yuval Mintz6853f212018-02-28 23:29:29 +0200694 struct vif_device *v;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900695 struct net_device *dev;
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800696 struct inet6_dev *in6_dev;
Patrick McHardy6bd52142010-05-11 14:40:53 +0200697
698 if (vifi < 0 || vifi >= mrt->maxvif)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900699 return -EADDRNOTAVAIL;
700
Yuval Mintzb70432f2018-02-28 23:29:32 +0200701 v = &mrt->vif_table[vifi];
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900702
Yuval Mintz088aa3e2018-03-26 15:01:34 +0300703 if (VIF_EXISTS(mrt, vifi))
704 call_ip6mr_vif_entry_notifiers(read_pnet(&mrt->net),
705 FIB_EVENT_VIF_DEL, v, vifi,
706 mrt->id);
707
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900708 write_lock_bh(&mrt_lock);
709 dev = v->dev;
710 v->dev = NULL;
711
712 if (!dev) {
713 write_unlock_bh(&mrt_lock);
714 return -EADDRNOTAVAIL;
715 }
716
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900717#ifdef CONFIG_IPV6_PIMSM_V2
Patrick McHardy6bd52142010-05-11 14:40:53 +0200718 if (vifi == mrt->mroute_reg_vif_num)
719 mrt->mroute_reg_vif_num = -1;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900720#endif
721
Patrick McHardy6bd52142010-05-11 14:40:53 +0200722 if (vifi + 1 == mrt->maxvif) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900723 int tmp;
724 for (tmp = vifi - 1; tmp >= 0; tmp--) {
Yuval Mintzb70432f2018-02-28 23:29:32 +0200725 if (VIF_EXISTS(mrt, tmp))
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900726 break;
727 }
Patrick McHardy6bd52142010-05-11 14:40:53 +0200728 mrt->maxvif = tmp + 1;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900729 }
730
731 write_unlock_bh(&mrt_lock);
732
733 dev_set_allmulti(dev, -1);
734
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800735 in6_dev = __in6_dev_get(dev);
Nicolas Dichteld67b8c62012-12-04 01:13:35 +0000736 if (in6_dev) {
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800737 in6_dev->cnf.mc_forwarding--;
David Ahern85b3daa2017-03-28 14:28:04 -0700738 inet6_netconf_notify_devconf(dev_net(dev), RTM_NEWNETCONF,
Nicolas Dichteld67b8c62012-12-04 01:13:35 +0000739 NETCONFA_MC_FORWARDING,
740 dev->ifindex, &in6_dev->cnf);
741 }
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800742
Nikolay Aleksandrov723b9292017-04-21 20:42:16 +0300743 if ((v->flags & MIFF_REGISTER) && !notify)
Eric Dumazetc871e662009-10-28 04:48:11 +0000744 unregister_netdevice_queue(dev, head);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900745
Eric Dumazet42120a82021-12-04 20:22:16 -0800746 dev_put_track(dev, &v->dev_tracker);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900747 return 0;
748}
749
Yuval Mintz87c418b2018-02-28 23:29:31 +0200750static inline void ip6mr_cache_free_rcu(struct rcu_head *head)
751{
Yuval Mintz494fff52018-02-28 23:29:34 +0200752 struct mr_mfc *c = container_of(head, struct mr_mfc, rcu);
Yuval Mintz87c418b2018-02-28 23:29:31 +0200753
Yuval Mintz494fff52018-02-28 23:29:34 +0200754 kmem_cache_free(mrt_cachep, (struct mfc6_cache *)c);
Yuval Mintz87c418b2018-02-28 23:29:31 +0200755}
756
Benjamin Thery58701ad2008-12-10 16:22:34 -0800757static inline void ip6mr_cache_free(struct mfc6_cache *c)
758{
Yuval Mintz494fff52018-02-28 23:29:34 +0200759 call_rcu(&c->_c.rcu, ip6mr_cache_free_rcu);
Benjamin Thery58701ad2008-12-10 16:22:34 -0800760}
761
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900762/* Destroy an unresolved cache entry, killing queued skbs
763 and reporting error to netlink readers.
764 */
765
Yuval Mintzb70432f2018-02-28 23:29:32 +0200766static void ip6mr_destroy_unres(struct mr_table *mrt, struct mfc6_cache *c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900767{
Patrick McHardy6bd52142010-05-11 14:40:53 +0200768 struct net *net = read_pnet(&mrt->net);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900769 struct sk_buff *skb;
770
Patrick McHardy6bd52142010-05-11 14:40:53 +0200771 atomic_dec(&mrt->cache_resolve_queue_len);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900772
Yuval Mintz494fff52018-02-28 23:29:34 +0200773 while ((skb = skb_dequeue(&c->_c.mfc_un.unres.unresolved)) != NULL) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900774 if (ipv6_hdr(skb)->version == 0) {
Johannes Bergaf728682017-06-16 14:29:22 +0200775 struct nlmsghdr *nlh = skb_pull(skb,
776 sizeof(struct ipv6hdr));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900777 nlh->nlmsg_type = NLMSG_ERROR;
Hong zhi guo573ce262013-03-27 06:47:04 +0000778 nlh->nlmsg_len = nlmsg_msg_size(sizeof(struct nlmsgerr));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900779 skb_trim(skb, nlh->nlmsg_len);
Hong zhi guo573ce262013-03-27 06:47:04 +0000780 ((struct nlmsgerr *)nlmsg_data(nlh))->error = -ETIMEDOUT;
Eric W. Biederman15e47302012-09-07 20:12:54 +0000781 rtnl_unicast(skb, net, NETLINK_CB(skb).portid);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900782 } else
783 kfree_skb(skb);
784 }
785
Benjamin Thery58701ad2008-12-10 16:22:34 -0800786 ip6mr_cache_free(c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900787}
788
789
Patrick McHardyc476efb2010-05-11 14:40:48 +0200790/* Timer process for all the unresolved queue. */
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900791
Yuval Mintzb70432f2018-02-28 23:29:32 +0200792static void ipmr_do_expire_process(struct mr_table *mrt)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900793{
794 unsigned long now = jiffies;
795 unsigned long expires = 10 * HZ;
Yuval Mintz494fff52018-02-28 23:29:34 +0200796 struct mr_mfc *c, *next;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900797
Yuval Mintzb70432f2018-02-28 23:29:32 +0200798 list_for_each_entry_safe(c, next, &mrt->mfc_unres_queue, list) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900799 if (time_after(c->mfc_un.unres.expires, now)) {
800 /* not yet... */
801 unsigned long interval = c->mfc_un.unres.expires - now;
802 if (interval < expires)
803 expires = interval;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900804 continue;
805 }
806
Patrick McHardyf30a77842010-05-11 14:40:51 +0200807 list_del(&c->list);
Yuval Mintz494fff52018-02-28 23:29:34 +0200808 mr6_netlink_event(mrt, (struct mfc6_cache *)c, RTM_DELROUTE);
809 ip6mr_destroy_unres(mrt, (struct mfc6_cache *)c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900810 }
811
Yuval Mintzb70432f2018-02-28 23:29:32 +0200812 if (!list_empty(&mrt->mfc_unres_queue))
Patrick McHardy6bd52142010-05-11 14:40:53 +0200813 mod_timer(&mrt->ipmr_expire_timer, jiffies + expires);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900814}
815
Kees Cooke99e88a2017-10-16 14:43:17 -0700816static void ipmr_expire_process(struct timer_list *t)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900817{
Yuval Mintzb70432f2018-02-28 23:29:32 +0200818 struct mr_table *mrt = from_timer(mrt, t, ipmr_expire_timer);
Patrick McHardyc476efb2010-05-11 14:40:48 +0200819
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900820 if (!spin_trylock(&mfc_unres_lock)) {
Patrick McHardy6bd52142010-05-11 14:40:53 +0200821 mod_timer(&mrt->ipmr_expire_timer, jiffies + 1);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900822 return;
823 }
824
Yuval Mintzb70432f2018-02-28 23:29:32 +0200825 if (!list_empty(&mrt->mfc_unres_queue))
Patrick McHardy6bd52142010-05-11 14:40:53 +0200826 ipmr_do_expire_process(mrt);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900827
828 spin_unlock(&mfc_unres_lock);
829}
830
831/* Fill oifs list. It is called under write locked mrt_lock. */
832
Yuval Mintzb70432f2018-02-28 23:29:32 +0200833static void ip6mr_update_thresholds(struct mr_table *mrt,
Yuval Mintz494fff52018-02-28 23:29:34 +0200834 struct mr_mfc *cache,
Patrick McHardyb5aa30b2010-05-11 14:40:50 +0200835 unsigned char *ttls)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900836{
837 int vifi;
838
Rami Rosen6ac7eb02008-04-10 12:40:10 +0300839 cache->mfc_un.res.minvif = MAXMIFS;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900840 cache->mfc_un.res.maxvif = 0;
Rami Rosen6ac7eb02008-04-10 12:40:10 +0300841 memset(cache->mfc_un.res.ttls, 255, MAXMIFS);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900842
Patrick McHardy6bd52142010-05-11 14:40:53 +0200843 for (vifi = 0; vifi < mrt->maxvif; vifi++) {
Yuval Mintzb70432f2018-02-28 23:29:32 +0200844 if (VIF_EXISTS(mrt, vifi) &&
Benjamin Thery4e168802008-12-10 16:15:08 -0800845 ttls[vifi] && ttls[vifi] < 255) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900846 cache->mfc_un.res.ttls[vifi] = ttls[vifi];
847 if (cache->mfc_un.res.minvif > vifi)
848 cache->mfc_un.res.minvif = vifi;
849 if (cache->mfc_un.res.maxvif <= vifi)
850 cache->mfc_un.res.maxvif = vifi + 1;
851 }
852 }
Nikolay Aleksandrov90b5ca12016-07-26 18:54:52 +0200853 cache->mfc_un.res.lastuse = jiffies;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900854}
855
Yuval Mintzb70432f2018-02-28 23:29:32 +0200856static int mif6_add(struct net *net, struct mr_table *mrt,
Patrick McHardy6bd52142010-05-11 14:40:53 +0200857 struct mif6ctl *vifc, int mrtsock)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900858{
859 int vifi = vifc->mif6c_mifi;
Yuval Mintzb70432f2018-02-28 23:29:32 +0200860 struct vif_device *v = &mrt->vif_table[vifi];
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900861 struct net_device *dev;
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800862 struct inet6_dev *in6_dev;
Wang Chen5ae7b442008-07-14 20:54:23 -0700863 int err;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900864
865 /* Is vif busy ? */
Yuval Mintzb70432f2018-02-28 23:29:32 +0200866 if (VIF_EXISTS(mrt, vifi))
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900867 return -EADDRINUSE;
868
869 switch (vifc->mif6c_flags) {
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900870#ifdef CONFIG_IPV6_PIMSM_V2
871 case MIFF_REGISTER:
872 /*
873 * Special Purpose VIF in PIM
874 * All the packets will be sent to the daemon
875 */
Patrick McHardy6bd52142010-05-11 14:40:53 +0200876 if (mrt->mroute_reg_vif_num >= 0)
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900877 return -EADDRINUSE;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200878 dev = ip6mr_reg_vif(net, mrt);
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900879 if (!dev)
880 return -ENOBUFS;
Wang Chen5ae7b442008-07-14 20:54:23 -0700881 err = dev_set_allmulti(dev, 1);
882 if (err) {
883 unregister_netdevice(dev);
Wang Chen7af3db72008-07-14 20:54:54 -0700884 dev_put(dev);
Wang Chen5ae7b442008-07-14 20:54:23 -0700885 return err;
886 }
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900887 break;
888#endif
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900889 case 0:
Benjamin Thery8229efd2008-12-10 16:30:15 -0800890 dev = dev_get_by_index(net, vifc->mif6c_pifi);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900891 if (!dev)
892 return -EADDRNOTAVAIL;
Wang Chen5ae7b442008-07-14 20:54:23 -0700893 err = dev_set_allmulti(dev, 1);
Wang Chen7af3db72008-07-14 20:54:54 -0700894 if (err) {
895 dev_put(dev);
Wang Chen5ae7b442008-07-14 20:54:23 -0700896 return err;
Wang Chen7af3db72008-07-14 20:54:54 -0700897 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900898 break;
899 default:
900 return -EINVAL;
901 }
902
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800903 in6_dev = __in6_dev_get(dev);
Nicolas Dichteld67b8c62012-12-04 01:13:35 +0000904 if (in6_dev) {
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800905 in6_dev->cnf.mc_forwarding++;
David Ahern85b3daa2017-03-28 14:28:04 -0700906 inet6_netconf_notify_devconf(dev_net(dev), RTM_NEWNETCONF,
Nicolas Dichteld67b8c62012-12-04 01:13:35 +0000907 NETCONFA_MC_FORWARDING,
908 dev->ifindex, &in6_dev->cnf);
909 }
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800910
Yuval Mintz6853f212018-02-28 23:29:29 +0200911 /* Fill in the VIF structures */
912 vif_device_init(v, dev, vifc->vifc_rate_limit, vifc->vifc_threshold,
913 vifc->mif6c_flags | (!mrtsock ? VIFF_STATIC : 0),
914 MIFF_REGISTER);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900915
916 /* And finish update writing critical data */
917 write_lock_bh(&mrt_lock);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900918 v->dev = dev;
Eric Dumazet42120a82021-12-04 20:22:16 -0800919 netdev_tracker_alloc(dev, &v->dev_tracker, GFP_ATOMIC);
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900920#ifdef CONFIG_IPV6_PIMSM_V2
921 if (v->flags & MIFF_REGISTER)
Patrick McHardy6bd52142010-05-11 14:40:53 +0200922 mrt->mroute_reg_vif_num = vifi;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900923#endif
Patrick McHardy6bd52142010-05-11 14:40:53 +0200924 if (vifi + 1 > mrt->maxvif)
925 mrt->maxvif = vifi + 1;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900926 write_unlock_bh(&mrt_lock);
Yuval Mintz088aa3e2018-03-26 15:01:34 +0300927 call_ip6mr_vif_entry_notifiers(net, FIB_EVENT_VIF_ADD,
928 v, vifi, mrt->id);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900929 return 0;
930}
931
Yuval Mintzb70432f2018-02-28 23:29:32 +0200932static struct mfc6_cache *ip6mr_cache_find(struct mr_table *mrt,
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000933 const struct in6_addr *origin,
934 const struct in6_addr *mcastgrp)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900935{
Yuval Mintz87c418b2018-02-28 23:29:31 +0200936 struct mfc6_cache_cmp_arg arg = {
937 .mf6c_origin = *origin,
938 .mf6c_mcastgrp = *mcastgrp,
939 };
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900940
Yuval Mintz845c9a72018-02-28 23:29:35 +0200941 return mr_mfc_find(mrt, &arg);
Nicolas Dichtel660b26d2013-01-21 06:00:26 +0000942}
943
944/* Look for a (*,G) entry */
Yuval Mintzb70432f2018-02-28 23:29:32 +0200945static struct mfc6_cache *ip6mr_cache_find_any(struct mr_table *mrt,
Nicolas Dichtel660b26d2013-01-21 06:00:26 +0000946 struct in6_addr *mcastgrp,
947 mifi_t mifi)
948{
Yuval Mintz87c418b2018-02-28 23:29:31 +0200949 struct mfc6_cache_cmp_arg arg = {
950 .mf6c_origin = in6addr_any,
951 .mf6c_mcastgrp = *mcastgrp,
952 };
Nicolas Dichtel660b26d2013-01-21 06:00:26 +0000953
954 if (ipv6_addr_any(mcastgrp))
Yuval Mintz845c9a72018-02-28 23:29:35 +0200955 return mr_mfc_find_any_parent(mrt, mifi);
956 return mr_mfc_find_any(mrt, mifi, &arg);
Nicolas Dichtel660b26d2013-01-21 06:00:26 +0000957}
958
Yuval Mintz87c418b2018-02-28 23:29:31 +0200959/* Look for a (S,G,iif) entry if parent != -1 */
960static struct mfc6_cache *
Yuval Mintzb70432f2018-02-28 23:29:32 +0200961ip6mr_cache_find_parent(struct mr_table *mrt,
Yuval Mintz87c418b2018-02-28 23:29:31 +0200962 const struct in6_addr *origin,
963 const struct in6_addr *mcastgrp,
964 int parent)
965{
966 struct mfc6_cache_cmp_arg arg = {
967 .mf6c_origin = *origin,
968 .mf6c_mcastgrp = *mcastgrp,
969 };
Yuval Mintz87c418b2018-02-28 23:29:31 +0200970
Yuval Mintz845c9a72018-02-28 23:29:35 +0200971 return mr_mfc_find_parent(mrt, &arg, parent);
Yuval Mintz87c418b2018-02-28 23:29:31 +0200972}
973
Yuval Mintz845c9a72018-02-28 23:29:35 +0200974/* Allocate a multicast cache entry */
Patrick McHardyb5aa30b2010-05-11 14:40:50 +0200975static struct mfc6_cache *ip6mr_cache_alloc(void)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900976{
Joe Perches36cbac52008-12-03 22:27:25 -0800977 struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL);
Ian Morris63159f22015-03-29 14:00:04 +0100978 if (!c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900979 return NULL;
Yuval Mintz494fff52018-02-28 23:29:34 +0200980 c->_c.mfc_un.res.last_assert = jiffies - MFC_ASSERT_THRESH - 1;
981 c->_c.mfc_un.res.minvif = MAXMIFS;
Yuval Mintz8c13af22018-03-26 15:01:36 +0300982 c->_c.free = ip6mr_cache_free_rcu;
983 refcount_set(&c->_c.mfc_un.res.refcount, 1);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900984 return c;
985}
986
Patrick McHardyb5aa30b2010-05-11 14:40:50 +0200987static struct mfc6_cache *ip6mr_cache_alloc_unres(void)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900988{
Joe Perches36cbac52008-12-03 22:27:25 -0800989 struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC);
Ian Morris63159f22015-03-29 14:00:04 +0100990 if (!c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900991 return NULL;
Yuval Mintz494fff52018-02-28 23:29:34 +0200992 skb_queue_head_init(&c->_c.mfc_un.unres.unresolved);
993 c->_c.mfc_un.unres.expires = jiffies + 10 * HZ;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900994 return c;
995}
996
997/*
998 * A cache entry has gone into a resolved state from queued
999 */
1000
Yuval Mintzb70432f2018-02-28 23:29:32 +02001001static void ip6mr_cache_resolve(struct net *net, struct mr_table *mrt,
Patrick McHardy6bd52142010-05-11 14:40:53 +02001002 struct mfc6_cache *uc, struct mfc6_cache *c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001003{
1004 struct sk_buff *skb;
1005
1006 /*
1007 * Play the pending entries through our router
1008 */
1009
Yuval Mintz494fff52018-02-28 23:29:34 +02001010 while ((skb = __skb_dequeue(&uc->_c.mfc_un.unres.unresolved))) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001011 if (ipv6_hdr(skb)->version == 0) {
Johannes Bergaf728682017-06-16 14:29:22 +02001012 struct nlmsghdr *nlh = skb_pull(skb,
1013 sizeof(struct ipv6hdr));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001014
Yuval Mintz7b0db852018-02-28 23:29:39 +02001015 if (mr_fill_mroute(mrt, skb, &c->_c,
1016 nlmsg_data(nlh)) > 0) {
YOSHIFUJI Hideaki549e0282008-04-05 22:17:39 +09001017 nlh->nlmsg_len = skb_tail_pointer(skb) - (u8 *)nlh;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001018 } else {
1019 nlh->nlmsg_type = NLMSG_ERROR;
Hong zhi guo573ce262013-03-27 06:47:04 +00001020 nlh->nlmsg_len = nlmsg_msg_size(sizeof(struct nlmsgerr));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001021 skb_trim(skb, nlh->nlmsg_len);
Hong zhi guo573ce262013-03-27 06:47:04 +00001022 ((struct nlmsgerr *)nlmsg_data(nlh))->error = -EMSGSIZE;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001023 }
Eric W. Biederman15e47302012-09-07 20:12:54 +00001024 rtnl_unicast(skb, net, NETLINK_CB(skb).portid);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001025 } else
Patrick Ruddye4a38c02018-10-01 09:41:27 +01001026 ip6_mr_forward(net, mrt, skb->dev, skb, c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001027 }
1028}
1029
1030/*
Julien Gomesdd12d15c2017-06-20 13:54:18 -07001031 * Bounce a cache query up to pim6sd and netlink.
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001032 *
1033 * Called under mrt_lock.
1034 */
1035
Yuval Mintzb70432f2018-02-28 23:29:32 +02001036static int ip6mr_cache_report(struct mr_table *mrt, struct sk_buff *pkt,
Patrick McHardy6bd52142010-05-11 14:40:53 +02001037 mifi_t mifi, int assert)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001038{
Yuval Mintz8571ab42018-02-28 23:29:30 +02001039 struct sock *mroute6_sk;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001040 struct sk_buff *skb;
1041 struct mrt6msg *msg;
1042 int ret;
1043
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001044#ifdef CONFIG_IPV6_PIMSM_V2
1045 if (assert == MRT6MSG_WHOLEPKT)
1046 skb = skb_realloc_headroom(pkt, -skb_network_offset(pkt)
1047 +sizeof(*msg));
1048 else
1049#endif
1050 skb = alloc_skb(sizeof(struct ipv6hdr) + sizeof(*msg), GFP_ATOMIC);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001051
1052 if (!skb)
1053 return -ENOBUFS;
1054
1055 /* I suppose that internal messages
1056 * do not require checksums */
1057
1058 skb->ip_summed = CHECKSUM_UNNECESSARY;
1059
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001060#ifdef CONFIG_IPV6_PIMSM_V2
1061 if (assert == MRT6MSG_WHOLEPKT) {
1062 /* Ugly, but we have no choice with this interface.
1063 Duplicate old header, fix length etc.
1064 And all this only to mangle msg->im6_msgtype and
1065 to set msg->im6_mbz to "mbz" :-)
1066 */
1067 skb_push(skb, -skb_network_offset(pkt));
1068
1069 skb_push(skb, sizeof(*msg));
1070 skb_reset_transport_header(skb);
1071 msg = (struct mrt6msg *)skb_transport_header(skb);
1072 msg->im6_mbz = 0;
1073 msg->im6_msgtype = MRT6MSG_WHOLEPKT;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001074 msg->im6_mif = mrt->mroute_reg_vif_num;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001075 msg->im6_pad = 0;
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +00001076 msg->im6_src = ipv6_hdr(pkt)->saddr;
1077 msg->im6_dst = ipv6_hdr(pkt)->daddr;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001078
1079 skb->ip_summed = CHECKSUM_UNNECESSARY;
1080 } else
1081#endif
1082 {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001083 /*
1084 * Copy the IP header
1085 */
1086
1087 skb_put(skb, sizeof(struct ipv6hdr));
1088 skb_reset_network_header(skb);
1089 skb_copy_to_linear_data(skb, ipv6_hdr(pkt), sizeof(struct ipv6hdr));
1090
1091 /*
1092 * Add our header
1093 */
1094 skb_put(skb, sizeof(*msg));
1095 skb_reset_transport_header(skb);
1096 msg = (struct mrt6msg *)skb_transport_header(skb);
1097
1098 msg->im6_mbz = 0;
1099 msg->im6_msgtype = assert;
Rami Rosen6ac7eb02008-04-10 12:40:10 +03001100 msg->im6_mif = mifi;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001101 msg->im6_pad = 0;
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +00001102 msg->im6_src = ipv6_hdr(pkt)->saddr;
1103 msg->im6_dst = ipv6_hdr(pkt)->daddr;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001104
Eric Dumazetadf30902009-06-02 05:19:30 +00001105 skb_dst_set(skb, dst_clone(skb_dst(pkt)));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001106 skb->ip_summed = CHECKSUM_UNNECESSARY;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001107 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001108
Yuval Mintz8571ab42018-02-28 23:29:30 +02001109 rcu_read_lock();
Yuval Mintzb70432f2018-02-28 23:29:32 +02001110 mroute6_sk = rcu_dereference(mrt->mroute_sk);
Yuval Mintz8571ab42018-02-28 23:29:30 +02001111 if (!mroute6_sk) {
1112 rcu_read_unlock();
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001113 kfree_skb(skb);
1114 return -EINVAL;
1115 }
1116
Julien Gomesdd12d15c2017-06-20 13:54:18 -07001117 mrt6msg_netlink_event(mrt, skb);
1118
Yuval Mintz8571ab42018-02-28 23:29:30 +02001119 /* Deliver to user space multicast routing algorithms */
1120 ret = sock_queue_rcv_skb(mroute6_sk, skb);
1121 rcu_read_unlock();
Benjamin Therybd91b8b2008-12-10 16:07:08 -08001122 if (ret < 0) {
Joe Perchese87cc472012-05-13 21:56:26 +00001123 net_warn_ratelimited("mroute6: pending queue full, dropping entries\n");
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001124 kfree_skb(skb);
1125 }
1126
1127 return ret;
1128}
1129
Yuval Mintz494fff52018-02-28 23:29:34 +02001130/* Queue a packet for resolution. It gets locked cache entry! */
1131static int ip6mr_cache_unresolved(struct mr_table *mrt, mifi_t mifi,
Patrick Ruddye4a38c02018-10-01 09:41:27 +01001132 struct sk_buff *skb, struct net_device *dev)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001133{
Yuval Mintz494fff52018-02-28 23:29:34 +02001134 struct mfc6_cache *c;
Patrick McHardyf30a77842010-05-11 14:40:51 +02001135 bool found = false;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001136 int err;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001137
1138 spin_lock_bh(&mfc_unres_lock);
Yuval Mintz494fff52018-02-28 23:29:34 +02001139 list_for_each_entry(c, &mrt->mfc_unres_queue, _c.list) {
Patrick McHardyc476efb2010-05-11 14:40:48 +02001140 if (ipv6_addr_equal(&c->mf6c_mcastgrp, &ipv6_hdr(skb)->daddr) &&
Patrick McHardyf30a77842010-05-11 14:40:51 +02001141 ipv6_addr_equal(&c->mf6c_origin, &ipv6_hdr(skb)->saddr)) {
1142 found = true;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001143 break;
Patrick McHardyf30a77842010-05-11 14:40:51 +02001144 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001145 }
1146
Patrick McHardyf30a77842010-05-11 14:40:51 +02001147 if (!found) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001148 /*
1149 * Create a new entry if allowable
1150 */
1151
Hangbin Liu0079ad82019-09-06 15:36:01 +08001152 c = ip6mr_cache_alloc_unres();
1153 if (!c) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001154 spin_unlock_bh(&mfc_unres_lock);
1155
1156 kfree_skb(skb);
1157 return -ENOBUFS;
1158 }
1159
Yuval Mintz494fff52018-02-28 23:29:34 +02001160 /* Fill in the new cache entry */
1161 c->_c.mfc_parent = -1;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001162 c->mf6c_origin = ipv6_hdr(skb)->saddr;
1163 c->mf6c_mcastgrp = ipv6_hdr(skb)->daddr;
1164
1165 /*
1166 * Reflect first query at pim6sd
1167 */
Patrick McHardy6bd52142010-05-11 14:40:53 +02001168 err = ip6mr_cache_report(mrt, skb, mifi, MRT6MSG_NOCACHE);
Benjamin Thery8229efd2008-12-10 16:30:15 -08001169 if (err < 0) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001170 /* If the report failed throw the cache entry
1171 out - Brad Parker
1172 */
1173 spin_unlock_bh(&mfc_unres_lock);
1174
Benjamin Thery58701ad2008-12-10 16:22:34 -08001175 ip6mr_cache_free(c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001176 kfree_skb(skb);
1177 return err;
1178 }
1179
Patrick McHardy6bd52142010-05-11 14:40:53 +02001180 atomic_inc(&mrt->cache_resolve_queue_len);
Yuval Mintz494fff52018-02-28 23:29:34 +02001181 list_add(&c->_c.list, &mrt->mfc_unres_queue);
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00001182 mr6_netlink_event(mrt, c, RTM_NEWROUTE);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001183
Patrick McHardy6bd52142010-05-11 14:40:53 +02001184 ipmr_do_expire_process(mrt);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001185 }
1186
Yuval Mintz494fff52018-02-28 23:29:34 +02001187 /* See if we can append the packet */
1188 if (c->_c.mfc_un.unres.unresolved.qlen > 3) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001189 kfree_skb(skb);
1190 err = -ENOBUFS;
1191 } else {
Patrick Ruddye4a38c02018-10-01 09:41:27 +01001192 if (dev) {
1193 skb->dev = dev;
1194 skb->skb_iif = dev->ifindex;
1195 }
Yuval Mintz494fff52018-02-28 23:29:34 +02001196 skb_queue_tail(&c->_c.mfc_un.unres.unresolved, skb);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001197 err = 0;
1198 }
1199
1200 spin_unlock_bh(&mfc_unres_lock);
1201 return err;
1202}
1203
1204/*
1205 * MFC6 cache manipulation by user space
1206 */
1207
Yuval Mintzb70432f2018-02-28 23:29:32 +02001208static int ip6mr_mfc_delete(struct mr_table *mrt, struct mf6cctl *mfc,
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001209 int parent)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001210{
Yuval Mintz87c418b2018-02-28 23:29:31 +02001211 struct mfc6_cache *c;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001212
Yuval Mintz87c418b2018-02-28 23:29:31 +02001213 /* The entries are added/deleted only under RTNL */
1214 rcu_read_lock();
1215 c = ip6mr_cache_find_parent(mrt, &mfc->mf6cc_origin.sin6_addr,
1216 &mfc->mf6cc_mcastgrp.sin6_addr, parent);
1217 rcu_read_unlock();
1218 if (!c)
1219 return -ENOENT;
Yuval Mintz494fff52018-02-28 23:29:34 +02001220 rhltable_remove(&mrt->mfc_hash, &c->_c.mnode, ip6mr_rht_params);
1221 list_del_rcu(&c->_c.list);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001222
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001223 call_ip6mr_mfc_entry_notifiers(read_pnet(&mrt->net),
1224 FIB_EVENT_ENTRY_DEL, c, mrt->id);
Yuval Mintz87c418b2018-02-28 23:29:31 +02001225 mr6_netlink_event(mrt, c, RTM_DELROUTE);
Yuval Mintz8c13af22018-03-26 15:01:36 +03001226 mr_cache_put(&c->_c);
Yuval Mintz87c418b2018-02-28 23:29:31 +02001227 return 0;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001228}
1229
1230static int ip6mr_device_event(struct notifier_block *this,
1231 unsigned long event, void *ptr)
1232{
Jiri Pirko351638e2013-05-28 01:30:21 +00001233 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
Benjamin Thery8229efd2008-12-10 16:30:15 -08001234 struct net *net = dev_net(dev);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001235 struct mr_table *mrt;
Yuval Mintz6853f212018-02-28 23:29:29 +02001236 struct vif_device *v;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001237 int ct;
1238
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001239 if (event != NETDEV_UNREGISTER)
1240 return NOTIFY_DONE;
1241
Patrick McHardyd1db2752010-05-11 14:40:55 +02001242 ip6mr_for_each_table(mrt, net) {
Yuval Mintzb70432f2018-02-28 23:29:32 +02001243 v = &mrt->vif_table[0];
Patrick McHardyd1db2752010-05-11 14:40:55 +02001244 for (ct = 0; ct < mrt->maxvif; ct++, v++) {
1245 if (v->dev == dev)
Nikolay Aleksandrov723b9292017-04-21 20:42:16 +03001246 mif6_delete(mrt, ct, 1, NULL);
Patrick McHardyd1db2752010-05-11 14:40:55 +02001247 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001248 }
Eric Dumazetc871e662009-10-28 04:48:11 +00001249
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001250 return NOTIFY_DONE;
1251}
1252
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001253static unsigned int ip6mr_seq_read(struct net *net)
1254{
1255 ASSERT_RTNL();
1256
1257 return net->ipv6.ipmr_seq + ip6mr_rules_seq_read(net);
1258}
1259
Jiri Pirkob7a59552019-10-03 11:49:30 +02001260static int ip6mr_dump(struct net *net, struct notifier_block *nb,
1261 struct netlink_ext_ack *extack)
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001262{
1263 return mr_dump(net, nb, RTNL_FAMILY_IP6MR, ip6mr_rules_dump,
Jiri Pirkob7a59552019-10-03 11:49:30 +02001264 ip6mr_mr_table_iter, &mrt_lock, extack);
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001265}
1266
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001267static struct notifier_block ip6_mr_notifier = {
1268 .notifier_call = ip6mr_device_event
1269};
1270
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001271static const struct fib_notifier_ops ip6mr_notifier_ops_template = {
1272 .family = RTNL_FAMILY_IP6MR,
1273 .fib_seq_read = ip6mr_seq_read,
1274 .fib_dump = ip6mr_dump,
1275 .owner = THIS_MODULE,
1276};
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001277
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001278static int __net_init ip6mr_notifier_init(struct net *net)
1279{
1280 struct fib_notifier_ops *ops;
1281
1282 net->ipv6.ipmr_seq = 0;
1283
1284 ops = fib_notifier_ops_register(&ip6mr_notifier_ops_template, net);
1285 if (IS_ERR(ops))
1286 return PTR_ERR(ops);
1287
1288 net->ipv6.ip6mr_notifier_ops = ops;
1289
1290 return 0;
1291}
1292
1293static void __net_exit ip6mr_notifier_exit(struct net *net)
1294{
1295 fib_notifier_ops_unregister(net->ipv6.ip6mr_notifier_ops);
1296 net->ipv6.ip6mr_notifier_ops = NULL;
1297}
1298
1299/* Setup for IP multicast routing */
Benjamin Thery4e168802008-12-10 16:15:08 -08001300static int __net_init ip6mr_net_init(struct net *net)
1301{
Patrick McHardyd1db2752010-05-11 14:40:55 +02001302 int err;
Patrick McHardyf30a77842010-05-11 14:40:51 +02001303
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001304 err = ip6mr_notifier_init(net);
1305 if (err)
1306 return err;
1307
Patrick McHardyd1db2752010-05-11 14:40:55 +02001308 err = ip6mr_rules_init(net);
1309 if (err < 0)
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001310 goto ip6mr_rules_fail;
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001311
1312#ifdef CONFIG_PROC_FS
1313 err = -ENOMEM;
Christoph Hellwigc3506372018-04-10 19:42:55 +02001314 if (!proc_create_net("ip6_mr_vif", 0, net->proc_net, &ip6mr_vif_seq_ops,
1315 sizeof(struct mr_vif_iter)))
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001316 goto proc_vif_fail;
Christoph Hellwigc3506372018-04-10 19:42:55 +02001317 if (!proc_create_net("ip6_mr_cache", 0, net->proc_net, &ipmr_mfc_seq_ops,
1318 sizeof(struct mr_mfc_iter)))
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001319 goto proc_cache_fail;
1320#endif
Patrick McHardy6bd52142010-05-11 14:40:53 +02001321
Benjamin Thery4a6258a2008-12-10 16:24:07 -08001322 return 0;
1323
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001324#ifdef CONFIG_PROC_FS
1325proc_cache_fail:
Gao fengece31ff2013-02-18 01:34:56 +00001326 remove_proc_entry("ip6_mr_vif", net->proc_net);
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001327proc_vif_fail:
Patrick McHardyd1db2752010-05-11 14:40:55 +02001328 ip6mr_rules_exit(net);
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001329#endif
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001330ip6mr_rules_fail:
1331 ip6mr_notifier_exit(net);
Benjamin Thery4e168802008-12-10 16:15:08 -08001332 return err;
1333}
1334
1335static void __net_exit ip6mr_net_exit(struct net *net)
1336{
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001337#ifdef CONFIG_PROC_FS
Gao fengece31ff2013-02-18 01:34:56 +00001338 remove_proc_entry("ip6_mr_cache", net->proc_net);
1339 remove_proc_entry("ip6_mr_vif", net->proc_net);
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001340#endif
Patrick McHardyd1db2752010-05-11 14:40:55 +02001341 ip6mr_rules_exit(net);
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001342 ip6mr_notifier_exit(net);
Benjamin Thery4e168802008-12-10 16:15:08 -08001343}
1344
1345static struct pernet_operations ip6mr_net_ops = {
1346 .init = ip6mr_net_init,
1347 .exit = ip6mr_net_exit,
1348};
1349
Wang Chen623d1a12008-07-03 12:13:30 +08001350int __init ip6_mr_init(void)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001351{
Wang Chen623d1a12008-07-03 12:13:30 +08001352 int err;
1353
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001354 mrt_cachep = kmem_cache_create("ip6_mrt_cache",
1355 sizeof(struct mfc6_cache),
1356 0, SLAB_HWCACHE_ALIGN,
1357 NULL);
1358 if (!mrt_cachep)
Wang Chen623d1a12008-07-03 12:13:30 +08001359 return -ENOMEM;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001360
Benjamin Thery4e168802008-12-10 16:15:08 -08001361 err = register_pernet_subsys(&ip6mr_net_ops);
1362 if (err)
1363 goto reg_pernet_fail;
1364
Wang Chen623d1a12008-07-03 12:13:30 +08001365 err = register_netdevice_notifier(&ip6_mr_notifier);
1366 if (err)
1367 goto reg_notif_fail;
Tom Goff403dbb92009-06-14 03:16:13 -07001368#ifdef CONFIG_IPV6_PIMSM_V2
1369 if (inet6_add_protocol(&pim6_protocol, IPPROTO_PIM) < 0) {
Joe Perchesf3213832012-05-15 14:11:53 +00001370 pr_err("%s: can't add PIM protocol\n", __func__);
Tom Goff403dbb92009-06-14 03:16:13 -07001371 err = -EAGAIN;
1372 goto add_proto_fail;
1373 }
1374#endif
Florian Westphala3fde2a2017-12-04 19:19:18 +01001375 err = rtnl_register_module(THIS_MODULE, RTNL_FAMILY_IP6MR, RTM_GETROUTE,
1376 NULL, ip6mr_rtm_dumproute, 0);
1377 if (err == 0)
1378 return 0;
1379
Tom Goff403dbb92009-06-14 03:16:13 -07001380#ifdef CONFIG_IPV6_PIMSM_V2
Florian Westphala3fde2a2017-12-04 19:19:18 +01001381 inet6_del_protocol(&pim6_protocol, IPPROTO_PIM);
Tom Goff403dbb92009-06-14 03:16:13 -07001382add_proto_fail:
1383 unregister_netdevice_notifier(&ip6_mr_notifier);
1384#endif
Benjamin Thery87b30a62008-11-10 16:34:11 -08001385reg_notif_fail:
Benjamin Thery4e168802008-12-10 16:15:08 -08001386 unregister_pernet_subsys(&ip6mr_net_ops);
1387reg_pernet_fail:
Benjamin Thery87b30a62008-11-10 16:34:11 -08001388 kmem_cache_destroy(mrt_cachep);
Wang Chen623d1a12008-07-03 12:13:30 +08001389 return err;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001390}
1391
Wang Chen623d1a12008-07-03 12:13:30 +08001392void ip6_mr_cleanup(void)
1393{
Duan Jiongffb13882014-11-19 09:35:39 +08001394 rtnl_unregister(RTNL_FAMILY_IP6MR, RTM_GETROUTE);
1395#ifdef CONFIG_IPV6_PIMSM_V2
1396 inet6_del_protocol(&pim6_protocol, IPPROTO_PIM);
1397#endif
Wang Chen623d1a12008-07-03 12:13:30 +08001398 unregister_netdevice_notifier(&ip6_mr_notifier);
Benjamin Thery4e168802008-12-10 16:15:08 -08001399 unregister_pernet_subsys(&ip6mr_net_ops);
Wang Chen623d1a12008-07-03 12:13:30 +08001400 kmem_cache_destroy(mrt_cachep);
1401}
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001402
Yuval Mintzb70432f2018-02-28 23:29:32 +02001403static int ip6mr_mfc_add(struct net *net, struct mr_table *mrt,
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001404 struct mf6cctl *mfc, int mrtsock, int parent)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001405{
Rami Rosen6ac7eb02008-04-10 12:40:10 +03001406 unsigned char ttls[MAXMIFS];
Yuval Mintz87c418b2018-02-28 23:29:31 +02001407 struct mfc6_cache *uc, *c;
Yuval Mintz494fff52018-02-28 23:29:34 +02001408 struct mr_mfc *_uc;
Yuval Mintz87c418b2018-02-28 23:29:31 +02001409 bool found;
1410 int i, err;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001411
Patrick McHardya50436f22010-03-17 06:04:14 +00001412 if (mfc->mf6cc_parent >= MAXMIFS)
1413 return -ENFILE;
1414
Rami Rosen6ac7eb02008-04-10 12:40:10 +03001415 memset(ttls, 255, MAXMIFS);
1416 for (i = 0; i < MAXMIFS; i++) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001417 if (IF_ISSET(i, &mfc->mf6cc_ifset))
1418 ttls[i] = 1;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001419 }
1420
Yuval Mintz87c418b2018-02-28 23:29:31 +02001421 /* The entries are added/deleted only under RTNL */
1422 rcu_read_lock();
1423 c = ip6mr_cache_find_parent(mrt, &mfc->mf6cc_origin.sin6_addr,
1424 &mfc->mf6cc_mcastgrp.sin6_addr, parent);
1425 rcu_read_unlock();
1426 if (c) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001427 write_lock_bh(&mrt_lock);
Yuval Mintz494fff52018-02-28 23:29:34 +02001428 c->_c.mfc_parent = mfc->mf6cc_parent;
1429 ip6mr_update_thresholds(mrt, &c->_c, ttls);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001430 if (!mrtsock)
Yuval Mintz494fff52018-02-28 23:29:34 +02001431 c->_c.mfc_flags |= MFC_STATIC;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001432 write_unlock_bh(&mrt_lock);
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001433 call_ip6mr_mfc_entry_notifiers(net, FIB_EVENT_ENTRY_REPLACE,
1434 c, mrt->id);
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00001435 mr6_netlink_event(mrt, c, RTM_NEWROUTE);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001436 return 0;
1437 }
1438
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001439 if (!ipv6_addr_any(&mfc->mf6cc_mcastgrp.sin6_addr) &&
1440 !ipv6_addr_is_multicast(&mfc->mf6cc_mcastgrp.sin6_addr))
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001441 return -EINVAL;
1442
Patrick McHardyb5aa30b2010-05-11 14:40:50 +02001443 c = ip6mr_cache_alloc();
Ian Morris63159f22015-03-29 14:00:04 +01001444 if (!c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001445 return -ENOMEM;
1446
1447 c->mf6c_origin = mfc->mf6cc_origin.sin6_addr;
1448 c->mf6c_mcastgrp = mfc->mf6cc_mcastgrp.sin6_addr;
Yuval Mintz494fff52018-02-28 23:29:34 +02001449 c->_c.mfc_parent = mfc->mf6cc_parent;
1450 ip6mr_update_thresholds(mrt, &c->_c, ttls);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001451 if (!mrtsock)
Yuval Mintz494fff52018-02-28 23:29:34 +02001452 c->_c.mfc_flags |= MFC_STATIC;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001453
Yuval Mintz494fff52018-02-28 23:29:34 +02001454 err = rhltable_insert_key(&mrt->mfc_hash, &c->cmparg, &c->_c.mnode,
Yuval Mintz87c418b2018-02-28 23:29:31 +02001455 ip6mr_rht_params);
1456 if (err) {
1457 pr_err("ip6mr: rhtable insert error %d\n", err);
1458 ip6mr_cache_free(c);
1459 return err;
1460 }
Yuval Mintz494fff52018-02-28 23:29:34 +02001461 list_add_tail_rcu(&c->_c.list, &mrt->mfc_cache_list);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001462
Yuval Mintz87c418b2018-02-28 23:29:31 +02001463 /* Check to see if we resolved a queued list. If so we
1464 * need to send on the frames and tidy up.
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001465 */
Patrick McHardyf30a77842010-05-11 14:40:51 +02001466 found = false;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001467 spin_lock_bh(&mfc_unres_lock);
Yuval Mintz494fff52018-02-28 23:29:34 +02001468 list_for_each_entry(_uc, &mrt->mfc_unres_queue, list) {
1469 uc = (struct mfc6_cache *)_uc;
Patrick McHardyc476efb2010-05-11 14:40:48 +02001470 if (ipv6_addr_equal(&uc->mf6c_origin, &c->mf6c_origin) &&
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001471 ipv6_addr_equal(&uc->mf6c_mcastgrp, &c->mf6c_mcastgrp)) {
Yuval Mintz494fff52018-02-28 23:29:34 +02001472 list_del(&_uc->list);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001473 atomic_dec(&mrt->cache_resolve_queue_len);
Patrick McHardyf30a77842010-05-11 14:40:51 +02001474 found = true;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001475 break;
1476 }
1477 }
Yuval Mintzb70432f2018-02-28 23:29:32 +02001478 if (list_empty(&mrt->mfc_unres_queue))
Patrick McHardy6bd52142010-05-11 14:40:53 +02001479 del_timer(&mrt->ipmr_expire_timer);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001480 spin_unlock_bh(&mfc_unres_lock);
1481
Patrick McHardyf30a77842010-05-11 14:40:51 +02001482 if (found) {
Patrick McHardy6bd52142010-05-11 14:40:53 +02001483 ip6mr_cache_resolve(net, mrt, uc, c);
Benjamin Thery58701ad2008-12-10 16:22:34 -08001484 ip6mr_cache_free(uc);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001485 }
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001486 call_ip6mr_mfc_entry_notifiers(net, FIB_EVENT_ENTRY_ADD,
1487 c, mrt->id);
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00001488 mr6_netlink_event(mrt, c, RTM_NEWROUTE);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001489 return 0;
1490}
1491
1492/*
1493 * Close the multicast socket, and clear the vif tables etc
1494 */
1495
Callum Sinclairca8d4792019-02-18 10:07:52 +13001496static void mroute_clean_tables(struct mr_table *mrt, int flags)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001497{
Yuval Mintz494fff52018-02-28 23:29:34 +02001498 struct mr_mfc *c, *tmp;
Eric Dumazetc871e662009-10-28 04:48:11 +00001499 LIST_HEAD(list);
Yuval Mintz87c418b2018-02-28 23:29:31 +02001500 int i;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001501
Yuval Mintz87c418b2018-02-28 23:29:31 +02001502 /* Shut down all active vif entries */
Callum Sinclairca8d4792019-02-18 10:07:52 +13001503 if (flags & (MRT6_FLUSH_MIFS | MRT6_FLUSH_MIFS_STATIC)) {
1504 for (i = 0; i < mrt->maxvif; i++) {
1505 if (((mrt->vif_table[i].flags & VIFF_STATIC) &&
1506 !(flags & MRT6_FLUSH_MIFS_STATIC)) ||
1507 (!(mrt->vif_table[i].flags & VIFF_STATIC) && !(flags & MRT6_FLUSH_MIFS)))
1508 continue;
1509 mif6_delete(mrt, i, 0, &list);
1510 }
1511 unregister_netdevice_many(&list);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001512 }
1513
Yuval Mintz87c418b2018-02-28 23:29:31 +02001514 /* Wipe the cache */
Callum Sinclairca8d4792019-02-18 10:07:52 +13001515 if (flags & (MRT6_FLUSH_MFC | MRT6_FLUSH_MFC_STATIC)) {
1516 list_for_each_entry_safe(c, tmp, &mrt->mfc_cache_list, list) {
1517 if (((c->mfc_flags & MFC_STATIC) && !(flags & MRT6_FLUSH_MFC_STATIC)) ||
1518 (!(c->mfc_flags & MFC_STATIC) && !(flags & MRT6_FLUSH_MFC)))
1519 continue;
1520 rhltable_remove(&mrt->mfc_hash, &c->mnode, ip6mr_rht_params);
1521 list_del_rcu(&c->list);
1522 call_ip6mr_mfc_entry_notifiers(read_pnet(&mrt->net),
1523 FIB_EVENT_ENTRY_DEL,
1524 (struct mfc6_cache *)c, mrt->id);
1525 mr6_netlink_event(mrt, (struct mfc6_cache *)c, RTM_DELROUTE);
1526 mr_cache_put(c);
1527 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001528 }
1529
Callum Sinclairca8d4792019-02-18 10:07:52 +13001530 if (flags & MRT6_FLUSH_MFC) {
1531 if (atomic_read(&mrt->cache_resolve_queue_len) != 0) {
1532 spin_lock_bh(&mfc_unres_lock);
1533 list_for_each_entry_safe(c, tmp, &mrt->mfc_unres_queue, list) {
1534 list_del(&c->list);
1535 mr6_netlink_event(mrt, (struct mfc6_cache *)c,
1536 RTM_DELROUTE);
1537 ip6mr_destroy_unres(mrt, (struct mfc6_cache *)c);
1538 }
1539 spin_unlock_bh(&mfc_unres_lock);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001540 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001541 }
1542}
1543
Yuval Mintzb70432f2018-02-28 23:29:32 +02001544static int ip6mr_sk_init(struct mr_table *mrt, struct sock *sk)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001545{
1546 int err = 0;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001547 struct net *net = sock_net(sk);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001548
1549 rtnl_lock();
1550 write_lock_bh(&mrt_lock);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001551 if (rtnl_dereference(mrt->mroute_sk)) {
Eric Dumazet927265b2016-07-08 05:46:04 +02001552 err = -EADDRINUSE;
Yuval Mintz8571ab42018-02-28 23:29:30 +02001553 } else {
Yuval Mintzb70432f2018-02-28 23:29:32 +02001554 rcu_assign_pointer(mrt->mroute_sk, sk);
Eric Dumazeta366e302018-03-07 08:43:19 -08001555 sock_set_flag(sk, SOCK_RCU_FREE);
Yuval Mintz8571ab42018-02-28 23:29:30 +02001556 net->ipv6.devconf_all->mc_forwarding++;
Eric Dumazet927265b2016-07-08 05:46:04 +02001557 }
1558 write_unlock_bh(&mrt_lock);
1559
1560 if (!err)
David Ahern85b3daa2017-03-28 14:28:04 -07001561 inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
1562 NETCONFA_MC_FORWARDING,
Nicolas Dichteld67b8c62012-12-04 01:13:35 +00001563 NETCONFA_IFINDEX_ALL,
1564 net->ipv6.devconf_all);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001565 rtnl_unlock();
1566
1567 return err;
1568}
1569
1570int ip6mr_sk_done(struct sock *sk)
1571{
Patrick McHardyd1db2752010-05-11 14:40:55 +02001572 int err = -EACCES;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001573 struct net *net = sock_net(sk);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001574 struct mr_table *mrt;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001575
Francesco Ruggeri338d1822017-11-08 11:23:46 -08001576 if (sk->sk_type != SOCK_RAW ||
1577 inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
1578 return err;
1579
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001580 rtnl_lock();
Patrick McHardyd1db2752010-05-11 14:40:55 +02001581 ip6mr_for_each_table(mrt, net) {
Yuval Mintzb70432f2018-02-28 23:29:32 +02001582 if (sk == rtnl_dereference(mrt->mroute_sk)) {
Patrick McHardyd1db2752010-05-11 14:40:55 +02001583 write_lock_bh(&mrt_lock);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001584 RCU_INIT_POINTER(mrt->mroute_sk, NULL);
Eric Dumazeta366e302018-03-07 08:43:19 -08001585 /* Note that mroute_sk had SOCK_RCU_FREE set,
1586 * so the RCU grace period before sk freeing
1587 * is guaranteed by sk_destruct()
1588 */
Patrick McHardyd1db2752010-05-11 14:40:55 +02001589 net->ipv6.devconf_all->mc_forwarding--;
Eric Dumazet927265b2016-07-08 05:46:04 +02001590 write_unlock_bh(&mrt_lock);
David Ahern85b3daa2017-03-28 14:28:04 -07001591 inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
Nicolas Dichteld67b8c62012-12-04 01:13:35 +00001592 NETCONFA_MC_FORWARDING,
1593 NETCONFA_IFINDEX_ALL,
1594 net->ipv6.devconf_all);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001595
Callum Sinclairca8d4792019-02-18 10:07:52 +13001596 mroute_clean_tables(mrt, MRT6_FLUSH_MIFS | MRT6_FLUSH_MFC);
Patrick McHardyd1db2752010-05-11 14:40:55 +02001597 err = 0;
1598 break;
1599 }
1600 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001601 rtnl_unlock();
1602
1603 return err;
1604}
1605
Yuval Mintz8571ab42018-02-28 23:29:30 +02001606bool mroute6_is_socket(struct net *net, struct sk_buff *skb)
Patrick McHardy6bd52142010-05-11 14:40:53 +02001607{
Yuval Mintzb70432f2018-02-28 23:29:32 +02001608 struct mr_table *mrt;
David S. Miller4c9483b2011-03-12 16:22:43 -05001609 struct flowi6 fl6 = {
Julian Anastasove374c612014-04-28 10:51:56 +03001610 .flowi6_iif = skb->skb_iif ? : LOOPBACK_IFINDEX,
David S. Miller4c9483b2011-03-12 16:22:43 -05001611 .flowi6_oif = skb->dev->ifindex,
1612 .flowi6_mark = skb->mark,
Patrick McHardyd1db2752010-05-11 14:40:55 +02001613 };
1614
David S. Miller4c9483b2011-03-12 16:22:43 -05001615 if (ip6mr_fib_lookup(net, &fl6, &mrt) < 0)
Patrick McHardyd1db2752010-05-11 14:40:55 +02001616 return NULL;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001617
Yuval Mintzb70432f2018-02-28 23:29:32 +02001618 return rcu_access_pointer(mrt->mroute_sk);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001619}
Yuval Mintz8571ab42018-02-28 23:29:30 +02001620EXPORT_SYMBOL(mroute6_is_socket);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001621
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001622/*
1623 * Socket options and virtual interface manipulation. The whole
1624 * virtual interface system is a complete heap, but unfortunately
1625 * that's how BSD mrouted happens to think. Maybe one day with a proper
1626 * MOSPF/PIM router set up we can clean this up.
1627 */
1628
Christoph Hellwigb43c6152020-07-23 08:08:59 +02001629int ip6_mroute_setsockopt(struct sock *sk, int optname, sockptr_t optval,
1630 unsigned int optlen)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001631{
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001632 int ret, parent = 0;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001633 struct mif6ctl vif;
1634 struct mf6cctl mfc;
1635 mifi_t mifi;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001636 struct net *net = sock_net(sk);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001637 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +02001638
Xin Long99253eb2017-02-24 16:29:06 +08001639 if (sk->sk_type != SOCK_RAW ||
1640 inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
1641 return -EOPNOTSUPP;
1642
Patrick McHardyd1db2752010-05-11 14:40:55 +02001643 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +01001644 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +02001645 return -ENOENT;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001646
1647 if (optname != MRT6_INIT) {
Yuval Mintzb70432f2018-02-28 23:29:32 +02001648 if (sk != rcu_access_pointer(mrt->mroute_sk) &&
Yuval Mintz8571ab42018-02-28 23:29:30 +02001649 !ns_capable(net->user_ns, CAP_NET_ADMIN))
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001650 return -EACCES;
1651 }
1652
1653 switch (optname) {
1654 case MRT6_INIT:
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001655 if (optlen < sizeof(int))
1656 return -EINVAL;
1657
Patrick McHardy6bd52142010-05-11 14:40:53 +02001658 return ip6mr_sk_init(mrt, sk);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001659
1660 case MRT6_DONE:
1661 return ip6mr_sk_done(sk);
1662
1663 case MRT6_ADD_MIF:
1664 if (optlen < sizeof(vif))
1665 return -EINVAL;
Christoph Hellwigb43c6152020-07-23 08:08:59 +02001666 if (copy_from_sockptr(&vif, optval, sizeof(vif)))
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001667 return -EFAULT;
Rami Rosen6ac7eb02008-04-10 12:40:10 +03001668 if (vif.mif6c_mifi >= MAXMIFS)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001669 return -ENFILE;
1670 rtnl_lock();
Yuval Mintz8571ab42018-02-28 23:29:30 +02001671 ret = mif6_add(net, mrt, &vif,
Yuval Mintzb70432f2018-02-28 23:29:32 +02001672 sk == rtnl_dereference(mrt->mroute_sk));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001673 rtnl_unlock();
1674 return ret;
1675
1676 case MRT6_DEL_MIF:
1677 if (optlen < sizeof(mifi_t))
1678 return -EINVAL;
Christoph Hellwigb43c6152020-07-23 08:08:59 +02001679 if (copy_from_sockptr(&mifi, optval, sizeof(mifi_t)))
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001680 return -EFAULT;
1681 rtnl_lock();
Nikolay Aleksandrov723b9292017-04-21 20:42:16 +03001682 ret = mif6_delete(mrt, mifi, 0, NULL);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001683 rtnl_unlock();
1684 return ret;
1685
1686 /*
1687 * Manipulate the forwarding caches. These live
1688 * in a sort of kernel/user symbiosis.
1689 */
1690 case MRT6_ADD_MFC:
1691 case MRT6_DEL_MFC:
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001692 parent = -1;
Joe Perchesa8eceea2020-03-12 15:50:22 -07001693 fallthrough;
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001694 case MRT6_ADD_MFC_PROXY:
1695 case MRT6_DEL_MFC_PROXY:
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001696 if (optlen < sizeof(mfc))
1697 return -EINVAL;
Christoph Hellwigb43c6152020-07-23 08:08:59 +02001698 if (copy_from_sockptr(&mfc, optval, sizeof(mfc)))
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001699 return -EFAULT;
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001700 if (parent == 0)
1701 parent = mfc.mf6cc_parent;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001702 rtnl_lock();
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001703 if (optname == MRT6_DEL_MFC || optname == MRT6_DEL_MFC_PROXY)
1704 ret = ip6mr_mfc_delete(mrt, &mfc, parent);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001705 else
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001706 ret = ip6mr_mfc_add(net, mrt, &mfc,
Yuval Mintz8571ab42018-02-28 23:29:30 +02001707 sk ==
Yuval Mintzb70432f2018-02-28 23:29:32 +02001708 rtnl_dereference(mrt->mroute_sk),
Yuval Mintz8571ab42018-02-28 23:29:30 +02001709 parent);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001710 rtnl_unlock();
1711 return ret;
1712
Callum Sinclairca8d4792019-02-18 10:07:52 +13001713 case MRT6_FLUSH:
1714 {
1715 int flags;
1716
1717 if (optlen != sizeof(flags))
1718 return -EINVAL;
Christoph Hellwigb43c6152020-07-23 08:08:59 +02001719 if (copy_from_sockptr(&flags, optval, sizeof(flags)))
Callum Sinclairca8d4792019-02-18 10:07:52 +13001720 return -EFAULT;
1721 rtnl_lock();
1722 mroute_clean_tables(mrt, flags);
1723 rtnl_unlock();
1724 return 0;
1725 }
1726
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001727 /*
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001728 * Control PIM assert (to activate pim will activate assert)
1729 */
1730 case MRT6_ASSERT:
1731 {
1732 int v;
Joe Perches03f52a02012-11-25 18:26:34 +00001733
1734 if (optlen != sizeof(v))
1735 return -EINVAL;
Christoph Hellwigb43c6152020-07-23 08:08:59 +02001736 if (copy_from_sockptr(&v, optval, sizeof(v)))
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001737 return -EFAULT;
Joe Perches53d68412012-11-25 09:35:30 +00001738 mrt->mroute_do_assert = v;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001739 return 0;
1740 }
1741
1742#ifdef CONFIG_IPV6_PIMSM_V2
1743 case MRT6_PIM:
1744 {
YOSHIFUJI Hideakia9f83bf2008-04-10 15:41:28 +09001745 int v;
Joe Perches03f52a02012-11-25 18:26:34 +00001746
1747 if (optlen != sizeof(v))
1748 return -EINVAL;
Christoph Hellwigb43c6152020-07-23 08:08:59 +02001749 if (copy_from_sockptr(&v, optval, sizeof(v)))
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001750 return -EFAULT;
1751 v = !!v;
1752 rtnl_lock();
1753 ret = 0;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001754 if (v != mrt->mroute_do_pim) {
1755 mrt->mroute_do_pim = v;
1756 mrt->mroute_do_assert = v;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001757 }
1758 rtnl_unlock();
1759 return ret;
1760 }
1761
1762#endif
Patrick McHardyd1db2752010-05-11 14:40:55 +02001763#ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
1764 case MRT6_TABLE:
1765 {
1766 u32 v;
1767
1768 if (optlen != sizeof(u32))
1769 return -EINVAL;
Christoph Hellwigb43c6152020-07-23 08:08:59 +02001770 if (copy_from_sockptr(&v, optval, sizeof(v)))
Patrick McHardyd1db2752010-05-11 14:40:55 +02001771 return -EFAULT;
Dan Carpenter75356a82013-01-23 20:38:34 +00001772 /* "pim6reg%u" should not exceed 16 bytes (IFNAMSIZ) */
1773 if (v != RT_TABLE_DEFAULT && v >= 100000000)
1774 return -EINVAL;
Yuval Mintzb70432f2018-02-28 23:29:32 +02001775 if (sk == rcu_access_pointer(mrt->mroute_sk))
Patrick McHardyd1db2752010-05-11 14:40:55 +02001776 return -EBUSY;
1777
1778 rtnl_lock();
1779 ret = 0;
Sabrina Dubrocae783bb02018-06-05 15:02:00 +02001780 mrt = ip6mr_new_table(net, v);
1781 if (IS_ERR(mrt))
1782 ret = PTR_ERR(mrt);
Sabrina Dubroca848235e2018-06-05 15:01:59 +02001783 else
1784 raw6_sk(sk)->ip6mr_table = v;
Patrick McHardyd1db2752010-05-11 14:40:55 +02001785 rtnl_unlock();
1786 return ret;
1787 }
1788#endif
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001789 /*
Rami Rosen7d120c52008-04-23 14:35:13 +03001790 * Spurious command, or MRT6_VERSION which you cannot
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001791 * set.
1792 */
1793 default:
1794 return -ENOPROTOOPT;
1795 }
1796}
1797
1798/*
1799 * Getsock opt support for the multicast routing system.
1800 */
1801
1802int ip6_mroute_getsockopt(struct sock *sk, int optname, char __user *optval,
1803 int __user *optlen)
1804{
1805 int olr;
1806 int val;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001807 struct net *net = sock_net(sk);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001808 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +02001809
Xin Long99253eb2017-02-24 16:29:06 +08001810 if (sk->sk_type != SOCK_RAW ||
1811 inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
1812 return -EOPNOTSUPP;
1813
Patrick McHardyd1db2752010-05-11 14:40:55 +02001814 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +01001815 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +02001816 return -ENOENT;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001817
1818 switch (optname) {
1819 case MRT6_VERSION:
1820 val = 0x0305;
1821 break;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001822#ifdef CONFIG_IPV6_PIMSM_V2
1823 case MRT6_PIM:
Patrick McHardy6bd52142010-05-11 14:40:53 +02001824 val = mrt->mroute_do_pim;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001825 break;
1826#endif
1827 case MRT6_ASSERT:
Patrick McHardy6bd52142010-05-11 14:40:53 +02001828 val = mrt->mroute_do_assert;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001829 break;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001830 default:
1831 return -ENOPROTOOPT;
1832 }
1833
1834 if (get_user(olr, optlen))
1835 return -EFAULT;
1836
1837 olr = min_t(int, olr, sizeof(int));
1838 if (olr < 0)
1839 return -EINVAL;
1840
1841 if (put_user(olr, optlen))
1842 return -EFAULT;
1843 if (copy_to_user(optval, &val, olr))
1844 return -EFAULT;
1845 return 0;
1846}
1847
1848/*
1849 * The IP multicast ioctl support routines.
1850 */
1851
1852int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg)
1853{
1854 struct sioc_sg_req6 sr;
1855 struct sioc_mif_req6 vr;
Yuval Mintz6853f212018-02-28 23:29:29 +02001856 struct vif_device *vif;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001857 struct mfc6_cache *c;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001858 struct net *net = sock_net(sk);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001859 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +02001860
1861 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +01001862 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +02001863 return -ENOENT;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001864
1865 switch (cmd) {
1866 case SIOCGETMIFCNT_IN6:
1867 if (copy_from_user(&vr, arg, sizeof(vr)))
1868 return -EFAULT;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001869 if (vr.mifi >= mrt->maxvif)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001870 return -EINVAL;
Gustavo A. R. Silva69d2c862018-12-11 14:10:08 -06001871 vr.mifi = array_index_nospec(vr.mifi, mrt->maxvif);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001872 read_lock(&mrt_lock);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001873 vif = &mrt->vif_table[vr.mifi];
1874 if (VIF_EXISTS(mrt, vr.mifi)) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001875 vr.icount = vif->pkt_in;
1876 vr.ocount = vif->pkt_out;
1877 vr.ibytes = vif->bytes_in;
1878 vr.obytes = vif->bytes_out;
1879 read_unlock(&mrt_lock);
1880
1881 if (copy_to_user(arg, &vr, sizeof(vr)))
1882 return -EFAULT;
1883 return 0;
1884 }
1885 read_unlock(&mrt_lock);
1886 return -EADDRNOTAVAIL;
1887 case SIOCGETSGCNT_IN6:
1888 if (copy_from_user(&sr, arg, sizeof(sr)))
1889 return -EFAULT;
1890
Yuval Mintz87c418b2018-02-28 23:29:31 +02001891 rcu_read_lock();
Patrick McHardy6bd52142010-05-11 14:40:53 +02001892 c = ip6mr_cache_find(mrt, &sr.src.sin6_addr, &sr.grp.sin6_addr);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001893 if (c) {
Yuval Mintz494fff52018-02-28 23:29:34 +02001894 sr.pktcnt = c->_c.mfc_un.res.pkt;
1895 sr.bytecnt = c->_c.mfc_un.res.bytes;
1896 sr.wrong_if = c->_c.mfc_un.res.wrong_if;
Yuval Mintz87c418b2018-02-28 23:29:31 +02001897 rcu_read_unlock();
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001898
1899 if (copy_to_user(arg, &sr, sizeof(sr)))
1900 return -EFAULT;
1901 return 0;
1902 }
Yuval Mintz87c418b2018-02-28 23:29:31 +02001903 rcu_read_unlock();
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001904 return -EADDRNOTAVAIL;
1905 default:
1906 return -ENOIOCTLCMD;
1907 }
1908}
1909
David S. Millere2d57762011-02-03 17:59:32 -08001910#ifdef CONFIG_COMPAT
1911struct compat_sioc_sg_req6 {
1912 struct sockaddr_in6 src;
1913 struct sockaddr_in6 grp;
1914 compat_ulong_t pktcnt;
1915 compat_ulong_t bytecnt;
1916 compat_ulong_t wrong_if;
1917};
1918
1919struct compat_sioc_mif_req6 {
1920 mifi_t mifi;
1921 compat_ulong_t icount;
1922 compat_ulong_t ocount;
1923 compat_ulong_t ibytes;
1924 compat_ulong_t obytes;
1925};
1926
1927int ip6mr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg)
1928{
1929 struct compat_sioc_sg_req6 sr;
1930 struct compat_sioc_mif_req6 vr;
Yuval Mintz6853f212018-02-28 23:29:29 +02001931 struct vif_device *vif;
David S. Millere2d57762011-02-03 17:59:32 -08001932 struct mfc6_cache *c;
1933 struct net *net = sock_net(sk);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001934 struct mr_table *mrt;
David S. Millere2d57762011-02-03 17:59:32 -08001935
1936 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +01001937 if (!mrt)
David S. Millere2d57762011-02-03 17:59:32 -08001938 return -ENOENT;
1939
1940 switch (cmd) {
1941 case SIOCGETMIFCNT_IN6:
1942 if (copy_from_user(&vr, arg, sizeof(vr)))
1943 return -EFAULT;
1944 if (vr.mifi >= mrt->maxvif)
1945 return -EINVAL;
Gustavo A. R. Silva69d2c862018-12-11 14:10:08 -06001946 vr.mifi = array_index_nospec(vr.mifi, mrt->maxvif);
David S. Millere2d57762011-02-03 17:59:32 -08001947 read_lock(&mrt_lock);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001948 vif = &mrt->vif_table[vr.mifi];
1949 if (VIF_EXISTS(mrt, vr.mifi)) {
David S. Millere2d57762011-02-03 17:59:32 -08001950 vr.icount = vif->pkt_in;
1951 vr.ocount = vif->pkt_out;
1952 vr.ibytes = vif->bytes_in;
1953 vr.obytes = vif->bytes_out;
1954 read_unlock(&mrt_lock);
1955
1956 if (copy_to_user(arg, &vr, sizeof(vr)))
1957 return -EFAULT;
1958 return 0;
1959 }
1960 read_unlock(&mrt_lock);
1961 return -EADDRNOTAVAIL;
1962 case SIOCGETSGCNT_IN6:
1963 if (copy_from_user(&sr, arg, sizeof(sr)))
1964 return -EFAULT;
1965
Yuval Mintz87c418b2018-02-28 23:29:31 +02001966 rcu_read_lock();
David S. Millere2d57762011-02-03 17:59:32 -08001967 c = ip6mr_cache_find(mrt, &sr.src.sin6_addr, &sr.grp.sin6_addr);
1968 if (c) {
Yuval Mintz494fff52018-02-28 23:29:34 +02001969 sr.pktcnt = c->_c.mfc_un.res.pkt;
1970 sr.bytecnt = c->_c.mfc_un.res.bytes;
1971 sr.wrong_if = c->_c.mfc_un.res.wrong_if;
Yuval Mintz87c418b2018-02-28 23:29:31 +02001972 rcu_read_unlock();
David S. Millere2d57762011-02-03 17:59:32 -08001973
1974 if (copy_to_user(arg, &sr, sizeof(sr)))
1975 return -EFAULT;
1976 return 0;
1977 }
Yuval Mintz87c418b2018-02-28 23:29:31 +02001978 rcu_read_unlock();
David S. Millere2d57762011-02-03 17:59:32 -08001979 return -EADDRNOTAVAIL;
1980 default:
1981 return -ENOIOCTLCMD;
1982 }
1983}
1984#endif
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001985
Eric W. Biederman0c4b51f2015-09-15 20:04:18 -05001986static inline int ip6mr_forward2_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001987{
Ido Schimmel87c11f12019-03-03 07:34:57 +00001988 IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
1989 IPSTATS_MIB_OUTFORWDATAGRAMS);
1990 IP6_ADD_STATS(net, ip6_dst_idev(skb_dst(skb)),
1991 IPSTATS_MIB_OUTOCTETS, skb->len);
Eric W. Biederman13206b62015-10-07 16:48:35 -05001992 return dst_output(net, sk, skb);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001993}
1994
1995/*
1996 * Processing handlers for ip6mr_forward
1997 */
1998
Yuval Mintzb70432f2018-02-28 23:29:32 +02001999static int ip6mr_forward2(struct net *net, struct mr_table *mrt,
David Ahernf5c6dfd2018-12-17 15:36:11 -08002000 struct sk_buff *skb, int vifi)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002001{
2002 struct ipv6hdr *ipv6h;
Yuval Mintzb70432f2018-02-28 23:29:32 +02002003 struct vif_device *vif = &mrt->vif_table[vifi];
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002004 struct net_device *dev;
2005 struct dst_entry *dst;
David S. Miller4c9483b2011-03-12 16:22:43 -05002006 struct flowi6 fl6;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002007
Ian Morris63159f22015-03-29 14:00:04 +01002008 if (!vif->dev)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002009 goto out_free;
2010
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002011#ifdef CONFIG_IPV6_PIMSM_V2
2012 if (vif->flags & MIFF_REGISTER) {
2013 vif->pkt_out++;
2014 vif->bytes_out += skb->len;
Pavel Emelyanovdc58c782008-05-21 14:17:54 -07002015 vif->dev->stats.tx_bytes += skb->len;
2016 vif->dev->stats.tx_packets++;
Patrick McHardy6bd52142010-05-11 14:40:53 +02002017 ip6mr_cache_report(mrt, skb, vifi, MRT6MSG_WHOLEPKT);
Ilpo Järvinen8da73b72008-12-14 23:15:49 -08002018 goto out_free;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002019 }
2020#endif
2021
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002022 ipv6h = ipv6_hdr(skb);
2023
David S. Miller4c9483b2011-03-12 16:22:43 -05002024 fl6 = (struct flowi6) {
2025 .flowi6_oif = vif->link,
2026 .daddr = ipv6h->daddr,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002027 };
2028
David S. Miller4c9483b2011-03-12 16:22:43 -05002029 dst = ip6_route_output(net, NULL, &fl6);
RongQing.Li5095d642012-02-21 22:10:49 +00002030 if (dst->error) {
2031 dst_release(dst);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002032 goto out_free;
RongQing.Li5095d642012-02-21 22:10:49 +00002033 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002034
Eric Dumazetadf30902009-06-02 05:19:30 +00002035 skb_dst_drop(skb);
2036 skb_dst_set(skb, dst);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002037
2038 /*
2039 * RFC1584 teaches, that DVMRP/PIM router must deliver packets locally
2040 * not only before forwarding, but after forwarding on all output
2041 * interfaces. It is clear, if mrouter runs a multicasting
2042 * program, it should receive packets not depending to what interface
2043 * program is joined.
2044 * If we will not make it, the program will have to join on all
2045 * interfaces. On the other hand, multihoming host (or router, but
2046 * not mrouter) cannot join to more than one interface - it will
2047 * result in receiving multiple packets.
2048 */
2049 dev = vif->dev;
2050 skb->dev = dev;
2051 vif->pkt_out++;
2052 vif->bytes_out += skb->len;
2053
2054 /* We are about to write */
2055 /* XXX: extension headers? */
2056 if (skb_cow(skb, sizeof(*ipv6h) + LL_RESERVED_SPACE(dev)))
2057 goto out_free;
2058
2059 ipv6h = ipv6_hdr(skb);
2060 ipv6h->hop_limit--;
2061
2062 IP6CB(skb)->flags |= IP6SKB_FORWARDED;
2063
Eric W. Biederman29a26a52015-09-15 20:04:16 -05002064 return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD,
2065 net, NULL, skb, skb->dev, dev,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002066 ip6mr_forward2_finish);
2067
2068out_free:
2069 kfree_skb(skb);
2070 return 0;
2071}
2072
Yuval Mintzb70432f2018-02-28 23:29:32 +02002073static int ip6mr_find_vif(struct mr_table *mrt, struct net_device *dev)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002074{
2075 int ct;
Patrick McHardy6bd52142010-05-11 14:40:53 +02002076
2077 for (ct = mrt->maxvif - 1; ct >= 0; ct--) {
Yuval Mintzb70432f2018-02-28 23:29:32 +02002078 if (mrt->vif_table[ct].dev == dev)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002079 break;
2080 }
2081 return ct;
2082}
2083
Yuval Mintzb70432f2018-02-28 23:29:32 +02002084static void ip6_mr_forward(struct net *net, struct mr_table *mrt,
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002085 struct net_device *dev, struct sk_buff *skb,
2086 struct mfc6_cache *c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002087{
2088 int psend = -1;
2089 int vif, ct;
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002090 int true_vifi = ip6mr_find_vif(mrt, dev);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002091
Yuval Mintz494fff52018-02-28 23:29:34 +02002092 vif = c->_c.mfc_parent;
2093 c->_c.mfc_un.res.pkt++;
2094 c->_c.mfc_un.res.bytes += skb->len;
2095 c->_c.mfc_un.res.lastuse = jiffies;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002096
Yuval Mintz494fff52018-02-28 23:29:34 +02002097 if (ipv6_addr_any(&c->mf6c_origin) && true_vifi >= 0) {
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002098 struct mfc6_cache *cache_proxy;
2099
Fabian Frederick40dc2ca2014-10-29 10:00:26 +01002100 /* For an (*,G) entry, we only check that the incoming
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002101 * interface is part of the static tree.
2102 */
Yuval Mintz87c418b2018-02-28 23:29:31 +02002103 rcu_read_lock();
Yuval Mintz845c9a72018-02-28 23:29:35 +02002104 cache_proxy = mr_mfc_find_any_parent(mrt, vif);
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002105 if (cache_proxy &&
Yuval Mintz494fff52018-02-28 23:29:34 +02002106 cache_proxy->_c.mfc_un.res.ttls[true_vifi] < 255) {
Yuval Mintz87c418b2018-02-28 23:29:31 +02002107 rcu_read_unlock();
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002108 goto forward;
Yuval Mintz87c418b2018-02-28 23:29:31 +02002109 }
2110 rcu_read_unlock();
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002111 }
2112
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002113 /*
2114 * Wrong interface: drop packet and (maybe) send PIM assert.
2115 */
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002116 if (mrt->vif_table[vif].dev != dev) {
Yuval Mintz494fff52018-02-28 23:29:34 +02002117 c->_c.mfc_un.res.wrong_if++;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002118
Patrick McHardy6bd52142010-05-11 14:40:53 +02002119 if (true_vifi >= 0 && mrt->mroute_do_assert &&
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002120 /* pimsm uses asserts, when switching from RPT to SPT,
2121 so that we cannot check that packet arrived on an oif.
2122 It is bad, but otherwise we would need to move pretty
2123 large chunk of pimd to kernel. Ough... --ANK
2124 */
Patrick McHardy6bd52142010-05-11 14:40:53 +02002125 (mrt->mroute_do_pim ||
Yuval Mintz494fff52018-02-28 23:29:34 +02002126 c->_c.mfc_un.res.ttls[true_vifi] < 255) &&
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002127 time_after(jiffies,
Yuval Mintz494fff52018-02-28 23:29:34 +02002128 c->_c.mfc_un.res.last_assert +
2129 MFC_ASSERT_THRESH)) {
2130 c->_c.mfc_un.res.last_assert = jiffies;
Patrick McHardy6bd52142010-05-11 14:40:53 +02002131 ip6mr_cache_report(mrt, skb, true_vifi, MRT6MSG_WRONGMIF);
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002132 }
2133 goto dont_forward;
2134 }
2135
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002136forward:
Yuval Mintzb70432f2018-02-28 23:29:32 +02002137 mrt->vif_table[vif].pkt_in++;
2138 mrt->vif_table[vif].bytes_in += skb->len;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002139
2140 /*
2141 * Forward the frame
2142 */
Yuval Mintz494fff52018-02-28 23:29:34 +02002143 if (ipv6_addr_any(&c->mf6c_origin) &&
2144 ipv6_addr_any(&c->mf6c_mcastgrp)) {
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002145 if (true_vifi >= 0 &&
Yuval Mintz494fff52018-02-28 23:29:34 +02002146 true_vifi != c->_c.mfc_parent &&
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002147 ipv6_hdr(skb)->hop_limit >
Yuval Mintz494fff52018-02-28 23:29:34 +02002148 c->_c.mfc_un.res.ttls[c->_c.mfc_parent]) {
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002149 /* It's an (*,*) entry and the packet is not coming from
2150 * the upstream: forward the packet to the upstream
2151 * only.
2152 */
Yuval Mintz494fff52018-02-28 23:29:34 +02002153 psend = c->_c.mfc_parent;
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002154 goto last_forward;
2155 }
2156 goto dont_forward;
2157 }
Yuval Mintz494fff52018-02-28 23:29:34 +02002158 for (ct = c->_c.mfc_un.res.maxvif - 1;
2159 ct >= c->_c.mfc_un.res.minvif; ct--) {
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002160 /* For (*,G) entry, don't forward to the incoming interface */
Yuval Mintz494fff52018-02-28 23:29:34 +02002161 if ((!ipv6_addr_any(&c->mf6c_origin) || ct != true_vifi) &&
2162 ipv6_hdr(skb)->hop_limit > c->_c.mfc_un.res.ttls[ct]) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002163 if (psend != -1) {
2164 struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
2165 if (skb2)
David Ahernf5c6dfd2018-12-17 15:36:11 -08002166 ip6mr_forward2(net, mrt, skb2, psend);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002167 }
2168 psend = ct;
2169 }
2170 }
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002171last_forward:
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002172 if (psend != -1) {
David Ahernf5c6dfd2018-12-17 15:36:11 -08002173 ip6mr_forward2(net, mrt, skb, psend);
Rami Rosen2b52c3a2013-07-21 03:00:31 +03002174 return;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002175 }
2176
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002177dont_forward:
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002178 kfree_skb(skb);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002179}
2180
2181
2182/*
2183 * Multicast packets for forwarding arrive here
2184 */
2185
2186int ip6_mr_input(struct sk_buff *skb)
2187{
2188 struct mfc6_cache *cache;
Benjamin Thery8229efd2008-12-10 16:30:15 -08002189 struct net *net = dev_net(skb->dev);
Yuval Mintzb70432f2018-02-28 23:29:32 +02002190 struct mr_table *mrt;
David S. Miller4c9483b2011-03-12 16:22:43 -05002191 struct flowi6 fl6 = {
2192 .flowi6_iif = skb->dev->ifindex,
2193 .flowi6_mark = skb->mark,
Patrick McHardyd1db2752010-05-11 14:40:55 +02002194 };
2195 int err;
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002196 struct net_device *dev;
2197
2198 /* skb->dev passed in is the master dev for vrfs.
2199 * Get the proper interface that does have a vif associated with it.
2200 */
2201 dev = skb->dev;
2202 if (netif_is_l3_master(skb->dev)) {
2203 dev = dev_get_by_index_rcu(net, IPCB(skb)->iif);
2204 if (!dev) {
2205 kfree_skb(skb);
2206 return -ENODEV;
2207 }
2208 }
Patrick McHardyd1db2752010-05-11 14:40:55 +02002209
David S. Miller4c9483b2011-03-12 16:22:43 -05002210 err = ip6mr_fib_lookup(net, &fl6, &mrt);
Ben Greear2015de52011-09-27 15:16:08 -04002211 if (err < 0) {
2212 kfree_skb(skb);
Patrick McHardyd1db2752010-05-11 14:40:55 +02002213 return err;
Ben Greear2015de52011-09-27 15:16:08 -04002214 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002215
2216 read_lock(&mrt_lock);
Patrick McHardy6bd52142010-05-11 14:40:53 +02002217 cache = ip6mr_cache_find(mrt,
Benjamin Thery8229efd2008-12-10 16:30:15 -08002218 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr);
Ian Morris63159f22015-03-29 14:00:04 +01002219 if (!cache) {
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002220 int vif = ip6mr_find_vif(mrt, dev);
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002221
2222 if (vif >= 0)
2223 cache = ip6mr_cache_find_any(mrt,
2224 &ipv6_hdr(skb)->daddr,
2225 vif);
2226 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002227
2228 /*
2229 * No usable cache entry
2230 */
Ian Morris63159f22015-03-29 14:00:04 +01002231 if (!cache) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002232 int vif;
2233
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002234 vif = ip6mr_find_vif(mrt, dev);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002235 if (vif >= 0) {
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002236 int err = ip6mr_cache_unresolved(mrt, vif, skb, dev);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002237 read_unlock(&mrt_lock);
2238
2239 return err;
2240 }
2241 read_unlock(&mrt_lock);
2242 kfree_skb(skb);
2243 return -ENODEV;
2244 }
2245
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002246 ip6_mr_forward(net, mrt, dev, skb, cache);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002247
2248 read_unlock(&mrt_lock);
2249
2250 return 0;
2251}
2252
Nikolay Aleksandrov2cf75072016-09-25 23:08:31 +02002253int ip6mr_get_route(struct net *net, struct sk_buff *skb, struct rtmsg *rtm,
David Ahernfd61c6b2017-01-17 15:51:07 -08002254 u32 portid)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002255{
2256 int err;
Yuval Mintzb70432f2018-02-28 23:29:32 +02002257 struct mr_table *mrt;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002258 struct mfc6_cache *cache;
Eric Dumazetadf30902009-06-02 05:19:30 +00002259 struct rt6_info *rt = (struct rt6_info *)skb_dst(skb);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002260
Patrick McHardyd1db2752010-05-11 14:40:55 +02002261 mrt = ip6mr_get_table(net, RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +01002262 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +02002263 return -ENOENT;
2264
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002265 read_lock(&mrt_lock);
Patrick McHardy6bd52142010-05-11 14:40:53 +02002266 cache = ip6mr_cache_find(mrt, &rt->rt6i_src.addr, &rt->rt6i_dst.addr);
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002267 if (!cache && skb->dev) {
2268 int vif = ip6mr_find_vif(mrt, skb->dev);
2269
2270 if (vif >= 0)
2271 cache = ip6mr_cache_find_any(mrt, &rt->rt6i_dst.addr,
2272 vif);
2273 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002274
2275 if (!cache) {
2276 struct sk_buff *skb2;
2277 struct ipv6hdr *iph;
2278 struct net_device *dev;
2279 int vif;
2280
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002281 dev = skb->dev;
Ian Morris63159f22015-03-29 14:00:04 +01002282 if (!dev || (vif = ip6mr_find_vif(mrt, dev)) < 0) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002283 read_unlock(&mrt_lock);
2284 return -ENODEV;
2285 }
2286
2287 /* really correct? */
2288 skb2 = alloc_skb(sizeof(struct ipv6hdr), GFP_ATOMIC);
2289 if (!skb2) {
2290 read_unlock(&mrt_lock);
2291 return -ENOMEM;
2292 }
2293
Nikolay Aleksandrov2cf75072016-09-25 23:08:31 +02002294 NETLINK_CB(skb2).portid = portid;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002295 skb_reset_transport_header(skb2);
2296
2297 skb_put(skb2, sizeof(struct ipv6hdr));
2298 skb_reset_network_header(skb2);
2299
2300 iph = ipv6_hdr(skb2);
2301 iph->version = 0;
2302 iph->priority = 0;
2303 iph->flow_lbl[0] = 0;
2304 iph->flow_lbl[1] = 0;
2305 iph->flow_lbl[2] = 0;
2306 iph->payload_len = 0;
2307 iph->nexthdr = IPPROTO_NONE;
2308 iph->hop_limit = 0;
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +00002309 iph->saddr = rt->rt6i_src.addr;
2310 iph->daddr = rt->rt6i_dst.addr;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002311
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002312 err = ip6mr_cache_unresolved(mrt, vif, skb2, dev);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002313 read_unlock(&mrt_lock);
2314
2315 return err;
2316 }
2317
Yuval Mintz7b0db852018-02-28 23:29:39 +02002318 err = mr_fill_mroute(mrt, skb, &cache->_c, rtm);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002319 read_unlock(&mrt_lock);
2320 return err;
2321}
2322
Yuval Mintzb70432f2018-02-28 23:29:32 +02002323static int ip6mr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
Nicolas Dichtelf5183382014-03-19 17:47:51 +01002324 u32 portid, u32 seq, struct mfc6_cache *c, int cmd,
2325 int flags)
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002326{
2327 struct nlmsghdr *nlh;
2328 struct rtmsg *rtm;
Nicolas Dichtel1eb99af2012-12-04 01:13:39 +00002329 int err;
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002330
Nicolas Dichtelf5183382014-03-19 17:47:51 +01002331 nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rtm), flags);
Ian Morris63159f22015-03-29 14:00:04 +01002332 if (!nlh)
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002333 return -EMSGSIZE;
2334
2335 rtm = nlmsg_data(nlh);
Nicolas Dichtel193c1e42012-12-04 01:01:49 +00002336 rtm->rtm_family = RTNL_FAMILY_IP6MR;
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002337 rtm->rtm_dst_len = 128;
2338 rtm->rtm_src_len = 128;
2339 rtm->rtm_tos = 0;
2340 rtm->rtm_table = mrt->id;
David S. Millerc78679e2012-04-01 20:27:33 -04002341 if (nla_put_u32(skb, RTA_TABLE, mrt->id))
2342 goto nla_put_failure;
Nicolas Dichtel1eb99af2012-12-04 01:13:39 +00002343 rtm->rtm_type = RTN_MULTICAST;
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002344 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
Yuval Mintz494fff52018-02-28 23:29:34 +02002345 if (c->_c.mfc_flags & MFC_STATIC)
Nicolas Dichtel9a68ac72012-12-04 01:13:38 +00002346 rtm->rtm_protocol = RTPROT_STATIC;
2347 else
2348 rtm->rtm_protocol = RTPROT_MROUTED;
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002349 rtm->rtm_flags = 0;
2350
Jiri Benc930345e2015-03-29 16:59:25 +02002351 if (nla_put_in6_addr(skb, RTA_SRC, &c->mf6c_origin) ||
2352 nla_put_in6_addr(skb, RTA_DST, &c->mf6c_mcastgrp))
David S. Millerc78679e2012-04-01 20:27:33 -04002353 goto nla_put_failure;
Yuval Mintz7b0db852018-02-28 23:29:39 +02002354 err = mr_fill_mroute(mrt, skb, &c->_c, rtm);
Nicolas Dichtel1eb99af2012-12-04 01:13:39 +00002355 /* do not break the dump if cache is unresolved */
2356 if (err < 0 && err != -ENOENT)
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002357 goto nla_put_failure;
2358
Johannes Berg053c0952015-01-16 22:09:00 +01002359 nlmsg_end(skb, nlh);
2360 return 0;
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002361
2362nla_put_failure:
2363 nlmsg_cancel(skb, nlh);
2364 return -EMSGSIZE;
2365}
2366
Yuval Mintz7b0db852018-02-28 23:29:39 +02002367static int _ip6mr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
2368 u32 portid, u32 seq, struct mr_mfc *c,
2369 int cmd, int flags)
2370{
2371 return ip6mr_fill_mroute(mrt, skb, portid, seq, (struct mfc6_cache *)c,
2372 cmd, flags);
2373}
2374
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002375static int mr6_msgsize(bool unresolved, int maxvif)
2376{
2377 size_t len =
2378 NLMSG_ALIGN(sizeof(struct rtmsg))
2379 + nla_total_size(4) /* RTA_TABLE */
2380 + nla_total_size(sizeof(struct in6_addr)) /* RTA_SRC */
2381 + nla_total_size(sizeof(struct in6_addr)) /* RTA_DST */
2382 ;
2383
2384 if (!unresolved)
2385 len = len
2386 + nla_total_size(4) /* RTA_IIF */
2387 + nla_total_size(0) /* RTA_MULTIPATH */
2388 + maxvif * NLA_ALIGN(sizeof(struct rtnexthop))
2389 /* RTA_MFC_STATS */
Nicolas Dichtel3d6b66c2016-04-21 18:58:27 +02002390 + nla_total_size_64bit(sizeof(struct rta_mfc_stats))
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002391 ;
2392
2393 return len;
2394}
2395
Yuval Mintzb70432f2018-02-28 23:29:32 +02002396static void mr6_netlink_event(struct mr_table *mrt, struct mfc6_cache *mfc,
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002397 int cmd)
2398{
2399 struct net *net = read_pnet(&mrt->net);
2400 struct sk_buff *skb;
2401 int err = -ENOBUFS;
2402
Yuval Mintz494fff52018-02-28 23:29:34 +02002403 skb = nlmsg_new(mr6_msgsize(mfc->_c.mfc_parent >= MAXMIFS, mrt->maxvif),
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002404 GFP_ATOMIC);
Ian Morris63159f22015-03-29 14:00:04 +01002405 if (!skb)
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002406 goto errout;
2407
Nicolas Dichtelf5183382014-03-19 17:47:51 +01002408 err = ip6mr_fill_mroute(mrt, skb, 0, 0, mfc, cmd, 0);
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002409 if (err < 0)
2410 goto errout;
2411
2412 rtnl_notify(skb, net, 0, RTNLGRP_IPV6_MROUTE, NULL, GFP_ATOMIC);
2413 return;
2414
2415errout:
2416 kfree_skb(skb);
2417 if (err < 0)
2418 rtnl_set_sk_err(net, RTNLGRP_IPV6_MROUTE, err);
2419}
2420
Julien Gomesdd12d15c2017-06-20 13:54:18 -07002421static size_t mrt6msg_netlink_msgsize(size_t payloadlen)
2422{
2423 size_t len =
2424 NLMSG_ALIGN(sizeof(struct rtgenmsg))
2425 + nla_total_size(1) /* IP6MRA_CREPORT_MSGTYPE */
2426 + nla_total_size(4) /* IP6MRA_CREPORT_MIF_ID */
2427 /* IP6MRA_CREPORT_SRC_ADDR */
2428 + nla_total_size(sizeof(struct in6_addr))
2429 /* IP6MRA_CREPORT_DST_ADDR */
2430 + nla_total_size(sizeof(struct in6_addr))
2431 /* IP6MRA_CREPORT_PKT */
2432 + nla_total_size(payloadlen)
2433 ;
2434
2435 return len;
2436}
2437
Yuval Mintzb70432f2018-02-28 23:29:32 +02002438static void mrt6msg_netlink_event(struct mr_table *mrt, struct sk_buff *pkt)
Julien Gomesdd12d15c2017-06-20 13:54:18 -07002439{
2440 struct net *net = read_pnet(&mrt->net);
2441 struct nlmsghdr *nlh;
2442 struct rtgenmsg *rtgenm;
2443 struct mrt6msg *msg;
2444 struct sk_buff *skb;
2445 struct nlattr *nla;
2446 int payloadlen;
2447
2448 payloadlen = pkt->len - sizeof(struct mrt6msg);
2449 msg = (struct mrt6msg *)skb_transport_header(pkt);
2450
2451 skb = nlmsg_new(mrt6msg_netlink_msgsize(payloadlen), GFP_ATOMIC);
2452 if (!skb)
2453 goto errout;
2454
2455 nlh = nlmsg_put(skb, 0, 0, RTM_NEWCACHEREPORT,
2456 sizeof(struct rtgenmsg), 0);
2457 if (!nlh)
2458 goto errout;
2459 rtgenm = nlmsg_data(nlh);
2460 rtgenm->rtgen_family = RTNL_FAMILY_IP6MR;
2461 if (nla_put_u8(skb, IP6MRA_CREPORT_MSGTYPE, msg->im6_msgtype) ||
2462 nla_put_u32(skb, IP6MRA_CREPORT_MIF_ID, msg->im6_mif) ||
2463 nla_put_in6_addr(skb, IP6MRA_CREPORT_SRC_ADDR,
2464 &msg->im6_src) ||
2465 nla_put_in6_addr(skb, IP6MRA_CREPORT_DST_ADDR,
2466 &msg->im6_dst))
2467 goto nla_put_failure;
2468
2469 nla = nla_reserve(skb, IP6MRA_CREPORT_PKT, payloadlen);
2470 if (!nla || skb_copy_bits(pkt, sizeof(struct mrt6msg),
2471 nla_data(nla), payloadlen))
2472 goto nla_put_failure;
2473
2474 nlmsg_end(skb, nlh);
2475
2476 rtnl_notify(skb, net, 0, RTNLGRP_IPV6_MROUTE_R, NULL, GFP_ATOMIC);
2477 return;
2478
2479nla_put_failure:
2480 nlmsg_cancel(skb, nlh);
2481errout:
2482 kfree_skb(skb);
2483 rtnl_set_sk_err(net, RTNLGRP_IPV6_MROUTE_R, -ENOBUFS);
2484}
2485
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002486static int ip6mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
2487{
David Aherne8ba3302018-10-07 20:16:35 -07002488 const struct nlmsghdr *nlh = cb->nlh;
David Ahern47246762018-10-15 18:56:42 -07002489 struct fib_dump_filter filter = {};
David Aherncb167892018-10-15 18:56:47 -07002490 int err;
David Aherne8ba3302018-10-07 20:16:35 -07002491
2492 if (cb->strict_check) {
David Ahern47246762018-10-15 18:56:42 -07002493 err = ip_valid_fib_dump_req(sock_net(skb->sk), nlh,
David Aherneffe6792018-10-15 18:56:48 -07002494 &filter, cb);
David Aherne8ba3302018-10-07 20:16:35 -07002495 if (err < 0)
2496 return err;
2497 }
2498
David Aherncb167892018-10-15 18:56:47 -07002499 if (filter.table_id) {
2500 struct mr_table *mrt;
2501
2502 mrt = ip6mr_get_table(sock_net(skb->sk), filter.table_id);
2503 if (!mrt) {
Sabrina Dubroca41b4bd92020-05-20 11:15:46 +02002504 if (rtnl_msg_family(cb->nlh) != RTNL_FAMILY_IP6MR)
David Ahernae677bb2018-10-24 12:59:01 -07002505 return skb->len;
2506
David Aherncb167892018-10-15 18:56:47 -07002507 NL_SET_ERR_MSG_MOD(cb->extack, "MR table does not exist");
2508 return -ENOENT;
2509 }
2510 err = mr_table_dump(mrt, skb, cb, _ip6mr_fill_mroute,
2511 &mfc_unres_lock, &filter);
2512 return skb->len ? : err;
2513 }
2514
Yuval Mintz7b0db852018-02-28 23:29:39 +02002515 return mr_rtm_dumproute(skb, cb, ip6mr_mr_table_iter,
David Aherncb167892018-10-15 18:56:47 -07002516 _ip6mr_fill_mroute, &mfc_unres_lock, &filter);
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002517}