blob: e80d36c5073defc19565e53dddacf4856726f242 [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) \
Patrick McHardyd1db2752010-05-11 14:40:55 +0200100 list_for_each_entry_rcu(mrt, &net->ipv6.mr6_tables, list)
101
Yuval Mintz7b0db852018-02-28 23:29:39 +0200102static struct mr_table *ip6mr_mr_table_iter(struct net *net,
103 struct mr_table *mrt)
104{
105 struct mr_table *ret;
106
107 if (!mrt)
108 ret = list_entry_rcu(net->ipv6.mr6_tables.next,
109 struct mr_table, list);
110 else
111 ret = list_entry_rcu(mrt->list.next,
112 struct mr_table, list);
113
114 if (&ret->list == &net->ipv6.mr6_tables)
115 return NULL;
116 return ret;
117}
118
Yuval Mintzb70432f2018-02-28 23:29:32 +0200119static struct mr_table *ip6mr_get_table(struct net *net, u32 id)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200120{
Yuval Mintzb70432f2018-02-28 23:29:32 +0200121 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200122
123 ip6mr_for_each_table(mrt, net) {
124 if (mrt->id == id)
125 return mrt;
126 }
127 return NULL;
128}
129
David S. Miller4c9483b2011-03-12 16:22:43 -0500130static int ip6mr_fib_lookup(struct net *net, struct flowi6 *flp6,
Yuval Mintzb70432f2018-02-28 23:29:32 +0200131 struct mr_table **mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200132{
Patrick McHardyd1db2752010-05-11 14:40:55 +0200133 int err;
Hannes Frederic Sowa95f4a452014-01-13 02:45:22 +0100134 struct ip6mr_result res;
135 struct fib_lookup_arg arg = {
136 .result = &res,
137 .flags = FIB_LOOKUP_NOREF,
138 };
Patrick McHardyd1db2752010-05-11 14:40:55 +0200139
Patrick Ruddye4a38c02018-10-01 09:41:27 +0100140 /* update flow if oif or iif point to device enslaved to l3mdev */
141 l3mdev_update_flow(net, flowi6_to_flowi(flp6));
142
David S. Miller4c9483b2011-03-12 16:22:43 -0500143 err = fib_rules_lookup(net->ipv6.mr6_rules_ops,
144 flowi6_to_flowi(flp6), 0, &arg);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200145 if (err < 0)
146 return err;
147 *mrt = res.mrt;
148 return 0;
149}
150
151static int ip6mr_rule_action(struct fib_rule *rule, struct flowi *flp,
152 int flags, struct fib_lookup_arg *arg)
153{
154 struct ip6mr_result *res = arg->result;
Yuval Mintzb70432f2018-02-28 23:29:32 +0200155 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200156
157 switch (rule->action) {
158 case FR_ACT_TO_TBL:
159 break;
160 case FR_ACT_UNREACHABLE:
161 return -ENETUNREACH;
162 case FR_ACT_PROHIBIT:
163 return -EACCES;
164 case FR_ACT_BLACKHOLE:
165 default:
166 return -EINVAL;
167 }
168
Patrick Ruddye4a38c02018-10-01 09:41:27 +0100169 arg->table = fib_rule_get_table(rule, arg);
170
171 mrt = ip6mr_get_table(rule->fr_net, arg->table);
Ian Morris63159f22015-03-29 14:00:04 +0100172 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200173 return -EAGAIN;
174 res->mrt = mrt;
175 return 0;
176}
177
178static int ip6mr_rule_match(struct fib_rule *rule, struct flowi *flp, int flags)
179{
180 return 1;
181}
182
183static const struct nla_policy ip6mr_rule_policy[FRA_MAX + 1] = {
184 FRA_GENERIC_POLICY,
185};
186
187static int ip6mr_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
Roopa Prabhub16fb412018-04-21 09:41:31 -0700188 struct fib_rule_hdr *frh, struct nlattr **tb,
189 struct netlink_ext_ack *extack)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200190{
191 return 0;
192}
193
194static int ip6mr_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
195 struct nlattr **tb)
196{
197 return 1;
198}
199
200static int ip6mr_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
201 struct fib_rule_hdr *frh)
202{
203 frh->dst_len = 0;
204 frh->src_len = 0;
205 frh->tos = 0;
206 return 0;
207}
208
Andi Kleen04a6f822012-10-04 17:12:11 -0700209static const struct fib_rules_ops __net_initconst ip6mr_rules_ops_template = {
Patrick McHardyd1db2752010-05-11 14:40:55 +0200210 .family = RTNL_FAMILY_IP6MR,
211 .rule_size = sizeof(struct ip6mr_rule),
212 .addr_size = sizeof(struct in6_addr),
213 .action = ip6mr_rule_action,
214 .match = ip6mr_rule_match,
215 .configure = ip6mr_rule_configure,
216 .compare = ip6mr_rule_compare,
Patrick McHardyd1db2752010-05-11 14:40:55 +0200217 .fill = ip6mr_rule_fill,
218 .nlgroup = RTNLGRP_IPV6_RULE,
219 .policy = ip6mr_rule_policy,
220 .owner = THIS_MODULE,
221};
222
223static int __net_init ip6mr_rules_init(struct net *net)
224{
225 struct fib_rules_ops *ops;
Yuval Mintzb70432f2018-02-28 23:29:32 +0200226 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200227 int err;
228
229 ops = fib_rules_register(&ip6mr_rules_ops_template, net);
230 if (IS_ERR(ops))
231 return PTR_ERR(ops);
232
233 INIT_LIST_HEAD(&net->ipv6.mr6_tables);
234
235 mrt = ip6mr_new_table(net, RT6_TABLE_DFLT);
Sabrina Dubrocae783bb02018-06-05 15:02:00 +0200236 if (IS_ERR(mrt)) {
237 err = PTR_ERR(mrt);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200238 goto err1;
239 }
240
241 err = fib_default_rule_add(ops, 0x7fff, RT6_TABLE_DFLT, 0);
242 if (err < 0)
243 goto err2;
244
245 net->ipv6.mr6_rules_ops = ops;
246 return 0;
247
248err2:
WANG Congf243e5a2015-03-25 14:45:03 -0700249 ip6mr_free_table(mrt);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200250err1:
251 fib_rules_unregister(ops);
252 return err;
253}
254
255static void __net_exit ip6mr_rules_exit(struct net *net)
256{
Yuval Mintzb70432f2018-02-28 23:29:32 +0200257 struct mr_table *mrt, *next;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200258
Hannes Frederic Sowa905a6f92013-07-22 23:45:53 +0200259 rtnl_lock();
Eric Dumazet035320d2010-06-06 23:48:40 +0000260 list_for_each_entry_safe(mrt, next, &net->ipv6.mr6_tables, list) {
261 list_del(&mrt->list);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200262 ip6mr_free_table(mrt);
Eric Dumazet035320d2010-06-06 23:48:40 +0000263 }
Patrick McHardyd1db2752010-05-11 14:40:55 +0200264 fib_rules_unregister(net->ipv6.mr6_rules_ops);
WANG Cong419df122015-03-31 11:01:46 -0700265 rtnl_unlock();
Patrick McHardyd1db2752010-05-11 14:40:55 +0200266}
Yuval Mintz088aa3e2018-03-26 15:01:34 +0300267
268static int ip6mr_rules_dump(struct net *net, struct notifier_block *nb)
269{
270 return fib_rules_dump(net, nb, RTNL_FAMILY_IP6MR);
271}
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
327static int ip6mr_rules_dump(struct net *net, struct notifier_block *nb)
328{
329 return 0;
330}
331
332static unsigned int ip6mr_rules_seq_read(struct net *net)
333{
334 return 0;
335}
Patrick McHardyd1db2752010-05-11 14:40:55 +0200336#endif
337
Yuval Mintz87c418b2018-02-28 23:29:31 +0200338static int ip6mr_hash_cmp(struct rhashtable_compare_arg *arg,
339 const void *ptr)
340{
341 const struct mfc6_cache_cmp_arg *cmparg = arg->key;
342 struct mfc6_cache *c = (struct mfc6_cache *)ptr;
343
344 return !ipv6_addr_equal(&c->mf6c_mcastgrp, &cmparg->mf6c_mcastgrp) ||
345 !ipv6_addr_equal(&c->mf6c_origin, &cmparg->mf6c_origin);
346}
347
348static const struct rhashtable_params ip6mr_rht_params = {
Yuval Mintz494fff52018-02-28 23:29:34 +0200349 .head_offset = offsetof(struct mr_mfc, mnode),
Yuval Mintz87c418b2018-02-28 23:29:31 +0200350 .key_offset = offsetof(struct mfc6_cache, cmparg),
351 .key_len = sizeof(struct mfc6_cache_cmp_arg),
352 .nelem_hint = 3,
Yuval Mintz87c418b2018-02-28 23:29:31 +0200353 .obj_cmpfn = ip6mr_hash_cmp,
354 .automatic_shrinking = true,
355};
356
Yuval Mintz0bbbf0e2018-02-28 23:29:33 +0200357static void ip6mr_new_table_set(struct mr_table *mrt,
358 struct net *net)
359{
360#ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
361 list_add_tail_rcu(&mrt->list, &net->ipv6.mr6_tables);
362#endif
363}
364
Yuval Mintz845c9a72018-02-28 23:29:35 +0200365static struct mfc6_cache_cmp_arg ip6mr_mr_table_ops_cmparg_any = {
366 .mf6c_origin = IN6ADDR_ANY_INIT,
367 .mf6c_mcastgrp = IN6ADDR_ANY_INIT,
368};
369
370static struct mr_table_ops ip6mr_mr_table_ops = {
371 .rht_params = &ip6mr_rht_params,
372 .cmparg_any = &ip6mr_mr_table_ops_cmparg_any,
373};
374
Yuval Mintzb70432f2018-02-28 23:29:32 +0200375static struct mr_table *ip6mr_new_table(struct net *net, u32 id)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200376{
Yuval Mintzb70432f2018-02-28 23:29:32 +0200377 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200378
379 mrt = ip6mr_get_table(net, id);
Ian Morris53b24b82015-03-29 14:00:05 +0100380 if (mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200381 return mrt;
382
Yuval Mintz845c9a72018-02-28 23:29:35 +0200383 return mr_table_alloc(net, id, &ip6mr_mr_table_ops,
Yuval Mintz0bbbf0e2018-02-28 23:29:33 +0200384 ipmr_expire_process, ip6mr_new_table_set);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200385}
386
Yuval Mintzb70432f2018-02-28 23:29:32 +0200387static void ip6mr_free_table(struct mr_table *mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200388{
WANG Cong7ba0c472015-03-31 11:01:47 -0700389 del_timer_sync(&mrt->ipmr_expire_timer);
Callum Sinclairca8d4792019-02-18 10:07:52 +1300390 mroute_clean_tables(mrt, MRT6_FLUSH_MIFS | MRT6_FLUSH_MIFS_STATIC |
391 MRT6_FLUSH_MFC | MRT6_FLUSH_MFC_STATIC);
Yuval Mintzb70432f2018-02-28 23:29:32 +0200392 rhltable_destroy(&mrt->mfc_hash);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200393 kfree(mrt);
394}
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900395
396#ifdef CONFIG_PROC_FS
Yuval Mintzc8d61962018-02-28 23:29:36 +0200397/* The /proc interfaces to multicast routing
398 * /proc/ip6_mr_cache /proc/ip6_mr_vif
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900399 */
400
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900401static void *ip6mr_vif_seq_start(struct seq_file *seq, loff_t *pos)
402 __acquires(mrt_lock)
403{
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200404 struct mr_vif_iter *iter = seq->private;
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800405 struct net *net = seq_file_net(seq);
Yuval Mintzb70432f2018-02-28 23:29:32 +0200406 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200407
408 mrt = ip6mr_get_table(net, RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +0100409 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200410 return ERR_PTR(-ENOENT);
411
412 iter->mrt = mrt;
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800413
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900414 read_lock(&mrt_lock);
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200415 return mr_vif_seq_start(seq, pos);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900416}
417
418static void ip6mr_vif_seq_stop(struct seq_file *seq, void *v)
419 __releases(mrt_lock)
420{
421 read_unlock(&mrt_lock);
422}
423
424static int ip6mr_vif_seq_show(struct seq_file *seq, void *v)
425{
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200426 struct mr_vif_iter *iter = seq->private;
Yuval Mintzb70432f2018-02-28 23:29:32 +0200427 struct mr_table *mrt = iter->mrt;
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800428
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900429 if (v == SEQ_START_TOKEN) {
430 seq_puts(seq,
431 "Interface BytesIn PktsIn BytesOut PktsOut Flags\n");
432 } else {
Yuval Mintz6853f212018-02-28 23:29:29 +0200433 const struct vif_device *vif = v;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900434 const char *name = vif->dev ? vif->dev->name : "none";
435
436 seq_printf(seq,
Al Virod430a222008-06-02 10:59:02 +0100437 "%2td %-10s %8ld %7ld %8ld %7ld %05X\n",
Yuval Mintzb70432f2018-02-28 23:29:32 +0200438 vif - mrt->vif_table,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900439 name, vif->bytes_in, vif->pkt_in,
440 vif->bytes_out, vif->pkt_out,
441 vif->flags);
442 }
443 return 0;
444}
445
Stephen Hemminger98147d52009-09-01 19:25:02 +0000446static const struct seq_operations ip6mr_vif_seq_ops = {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900447 .start = ip6mr_vif_seq_start,
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200448 .next = mr_vif_seq_next,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900449 .stop = ip6mr_vif_seq_stop,
450 .show = ip6mr_vif_seq_show,
451};
452
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900453static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos)
454{
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800455 struct net *net = seq_file_net(seq);
Yuval Mintzb70432f2018-02-28 23:29:32 +0200456 struct mr_table *mrt;
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800457
Patrick McHardyd1db2752010-05-11 14:40:55 +0200458 mrt = ip6mr_get_table(net, RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +0100459 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200460 return ERR_PTR(-ENOENT);
461
Yuval Mintzc8d61962018-02-28 23:29:36 +0200462 return mr_mfc_seq_start(seq, pos, mrt, &mfc_unres_lock);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900463}
464
465static int ipmr_mfc_seq_show(struct seq_file *seq, void *v)
466{
467 int n;
468
469 if (v == SEQ_START_TOKEN) {
470 seq_puts(seq,
471 "Group "
472 "Origin "
473 "Iif Pkts Bytes Wrong Oifs\n");
474 } else {
475 const struct mfc6_cache *mfc = v;
Yuval Mintzc8d61962018-02-28 23:29:36 +0200476 const struct mr_mfc_iter *it = seq->private;
Yuval Mintzb70432f2018-02-28 23:29:32 +0200477 struct mr_table *mrt = it->mrt;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900478
Benjamin Thery999890b22008-12-03 22:22:16 -0800479 seq_printf(seq, "%pI6 %pI6 %-3hd",
Harvey Harrison0c6ce782008-10-28 16:09:23 -0700480 &mfc->mf6c_mcastgrp, &mfc->mf6c_origin,
Yuval Mintz494fff52018-02-28 23:29:34 +0200481 mfc->_c.mfc_parent);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900482
Yuval Mintzb70432f2018-02-28 23:29:32 +0200483 if (it->cache != &mrt->mfc_unres_queue) {
Benjamin Thery1ea472e2008-12-03 22:21:47 -0800484 seq_printf(seq, " %8lu %8lu %8lu",
Yuval Mintz494fff52018-02-28 23:29:34 +0200485 mfc->_c.mfc_un.res.pkt,
486 mfc->_c.mfc_un.res.bytes,
487 mfc->_c.mfc_un.res.wrong_if);
488 for (n = mfc->_c.mfc_un.res.minvif;
489 n < mfc->_c.mfc_un.res.maxvif; n++) {
Yuval Mintzb70432f2018-02-28 23:29:32 +0200490 if (VIF_EXISTS(mrt, n) &&
Yuval Mintz494fff52018-02-28 23:29:34 +0200491 mfc->_c.mfc_un.res.ttls[n] < 255)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900492 seq_printf(seq,
Yuval Mintz494fff52018-02-28 23:29:34 +0200493 " %2d:%-3d", n,
494 mfc->_c.mfc_un.res.ttls[n]);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900495 }
Benjamin Thery1ea472e2008-12-03 22:21:47 -0800496 } else {
497 /* unresolved mfc_caches don't contain
498 * pkt, bytes and wrong_if values
499 */
500 seq_printf(seq, " %8lu %8lu %8lu", 0ul, 0ul, 0ul);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900501 }
502 seq_putc(seq, '\n');
503 }
504 return 0;
505}
506
James Morris88e9d342009-09-22 16:43:43 -0700507static const struct seq_operations ipmr_mfc_seq_ops = {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900508 .start = ipmr_mfc_seq_start,
Yuval Mintzc8d61962018-02-28 23:29:36 +0200509 .next = mr_mfc_seq_next,
510 .stop = mr_mfc_seq_stop,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900511 .show = ipmr_mfc_seq_show,
512};
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900513#endif
514
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900515#ifdef CONFIG_IPV6_PIMSM_V2
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900516
517static int pim6_rcv(struct sk_buff *skb)
518{
519 struct pimreghdr *pim;
520 struct ipv6hdr *encap;
521 struct net_device *reg_dev = NULL;
Benjamin Thery8229efd2008-12-10 16:30:15 -0800522 struct net *net = dev_net(skb->dev);
Yuval Mintzb70432f2018-02-28 23:29:32 +0200523 struct mr_table *mrt;
David S. Miller4c9483b2011-03-12 16:22:43 -0500524 struct flowi6 fl6 = {
525 .flowi6_iif = skb->dev->ifindex,
526 .flowi6_mark = skb->mark,
Patrick McHardyd1db2752010-05-11 14:40:55 +0200527 };
528 int reg_vif_num;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900529
530 if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(*encap)))
531 goto drop;
532
533 pim = (struct pimreghdr *)skb_transport_header(skb);
Nikolay Aleksandrov56245ca2016-10-31 13:21:04 +0100534 if (pim->type != ((PIM_VERSION << 4) | PIM_TYPE_REGISTER) ||
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900535 (pim->flags & PIM_NULL_REGISTER) ||
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800536 (csum_ipv6_magic(&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
537 sizeof(*pim), IPPROTO_PIM,
538 csum_partial((void *)pim, sizeof(*pim), 0)) &&
Al Viroec6b4862008-04-26 22:28:58 -0700539 csum_fold(skb_checksum(skb, 0, skb->len, 0))))
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900540 goto drop;
541
542 /* check if the inner packet is destined to mcast group */
543 encap = (struct ipv6hdr *)(skb_transport_header(skb) +
544 sizeof(*pim));
545
546 if (!ipv6_addr_is_multicast(&encap->daddr) ||
547 encap->payload_len == 0 ||
548 ntohs(encap->payload_len) + sizeof(*pim) > skb->len)
549 goto drop;
550
David S. Miller4c9483b2011-03-12 16:22:43 -0500551 if (ip6mr_fib_lookup(net, &fl6, &mrt) < 0)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200552 goto drop;
553 reg_vif_num = mrt->mroute_reg_vif_num;
554
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900555 read_lock(&mrt_lock);
556 if (reg_vif_num >= 0)
Yuval Mintzb70432f2018-02-28 23:29:32 +0200557 reg_dev = mrt->vif_table[reg_vif_num].dev;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900558 if (reg_dev)
559 dev_hold(reg_dev);
560 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
746 dev_put(dev);
747 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;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900919#ifdef CONFIG_IPV6_PIMSM_V2
920 if (v->flags & MIFF_REGISTER)
Patrick McHardy6bd52142010-05-11 14:40:53 +0200921 mrt->mroute_reg_vif_num = vifi;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900922#endif
Patrick McHardy6bd52142010-05-11 14:40:53 +0200923 if (vifi + 1 > mrt->maxvif)
924 mrt->maxvif = vifi + 1;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900925 write_unlock_bh(&mrt_lock);
Yuval Mintz088aa3e2018-03-26 15:01:34 +0300926 call_ip6mr_vif_entry_notifiers(net, FIB_EVENT_VIF_ADD,
927 v, vifi, mrt->id);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900928 return 0;
929}
930
Yuval Mintzb70432f2018-02-28 23:29:32 +0200931static struct mfc6_cache *ip6mr_cache_find(struct mr_table *mrt,
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000932 const struct in6_addr *origin,
933 const struct in6_addr *mcastgrp)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900934{
Yuval Mintz87c418b2018-02-28 23:29:31 +0200935 struct mfc6_cache_cmp_arg arg = {
936 .mf6c_origin = *origin,
937 .mf6c_mcastgrp = *mcastgrp,
938 };
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900939
Yuval Mintz845c9a72018-02-28 23:29:35 +0200940 return mr_mfc_find(mrt, &arg);
Nicolas Dichtel660b26d2013-01-21 06:00:26 +0000941}
942
943/* Look for a (*,G) entry */
Yuval Mintzb70432f2018-02-28 23:29:32 +0200944static struct mfc6_cache *ip6mr_cache_find_any(struct mr_table *mrt,
Nicolas Dichtel660b26d2013-01-21 06:00:26 +0000945 struct in6_addr *mcastgrp,
946 mifi_t mifi)
947{
Yuval Mintz87c418b2018-02-28 23:29:31 +0200948 struct mfc6_cache_cmp_arg arg = {
949 .mf6c_origin = in6addr_any,
950 .mf6c_mcastgrp = *mcastgrp,
951 };
Nicolas Dichtel660b26d2013-01-21 06:00:26 +0000952
953 if (ipv6_addr_any(mcastgrp))
Yuval Mintz845c9a72018-02-28 23:29:35 +0200954 return mr_mfc_find_any_parent(mrt, mifi);
955 return mr_mfc_find_any(mrt, mifi, &arg);
Nicolas Dichtel660b26d2013-01-21 06:00:26 +0000956}
957
Yuval Mintz87c418b2018-02-28 23:29:31 +0200958/* Look for a (S,G,iif) entry if parent != -1 */
959static struct mfc6_cache *
Yuval Mintzb70432f2018-02-28 23:29:32 +0200960ip6mr_cache_find_parent(struct mr_table *mrt,
Yuval Mintz87c418b2018-02-28 23:29:31 +0200961 const struct in6_addr *origin,
962 const struct in6_addr *mcastgrp,
963 int parent)
964{
965 struct mfc6_cache_cmp_arg arg = {
966 .mf6c_origin = *origin,
967 .mf6c_mcastgrp = *mcastgrp,
968 };
Yuval Mintz87c418b2018-02-28 23:29:31 +0200969
Yuval Mintz845c9a72018-02-28 23:29:35 +0200970 return mr_mfc_find_parent(mrt, &arg, parent);
Yuval Mintz87c418b2018-02-28 23:29:31 +0200971}
972
Yuval Mintz845c9a72018-02-28 23:29:35 +0200973/* Allocate a multicast cache entry */
Patrick McHardyb5aa30b2010-05-11 14:40:50 +0200974static struct mfc6_cache *ip6mr_cache_alloc(void)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900975{
Joe Perches36cbac52008-12-03 22:27:25 -0800976 struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL);
Ian Morris63159f22015-03-29 14:00:04 +0100977 if (!c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900978 return NULL;
Yuval Mintz494fff52018-02-28 23:29:34 +0200979 c->_c.mfc_un.res.last_assert = jiffies - MFC_ASSERT_THRESH - 1;
980 c->_c.mfc_un.res.minvif = MAXMIFS;
Yuval Mintz8c13af22018-03-26 15:01:36 +0300981 c->_c.free = ip6mr_cache_free_rcu;
982 refcount_set(&c->_c.mfc_un.res.refcount, 1);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900983 return c;
984}
985
Patrick McHardyb5aa30b2010-05-11 14:40:50 +0200986static struct mfc6_cache *ip6mr_cache_alloc_unres(void)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900987{
Joe Perches36cbac52008-12-03 22:27:25 -0800988 struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC);
Ian Morris63159f22015-03-29 14:00:04 +0100989 if (!c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900990 return NULL;
Yuval Mintz494fff52018-02-28 23:29:34 +0200991 skb_queue_head_init(&c->_c.mfc_un.unres.unresolved);
992 c->_c.mfc_un.unres.expires = jiffies + 10 * HZ;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900993 return c;
994}
995
996/*
997 * A cache entry has gone into a resolved state from queued
998 */
999
Yuval Mintzb70432f2018-02-28 23:29:32 +02001000static void ip6mr_cache_resolve(struct net *net, struct mr_table *mrt,
Patrick McHardy6bd52142010-05-11 14:40:53 +02001001 struct mfc6_cache *uc, struct mfc6_cache *c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001002{
1003 struct sk_buff *skb;
1004
1005 /*
1006 * Play the pending entries through our router
1007 */
1008
Yuval Mintz494fff52018-02-28 23:29:34 +02001009 while ((skb = __skb_dequeue(&uc->_c.mfc_un.unres.unresolved))) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001010 if (ipv6_hdr(skb)->version == 0) {
Johannes Bergaf728682017-06-16 14:29:22 +02001011 struct nlmsghdr *nlh = skb_pull(skb,
1012 sizeof(struct ipv6hdr));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001013
Yuval Mintz7b0db852018-02-28 23:29:39 +02001014 if (mr_fill_mroute(mrt, skb, &c->_c,
1015 nlmsg_data(nlh)) > 0) {
YOSHIFUJI Hideaki549e0282008-04-05 22:17:39 +09001016 nlh->nlmsg_len = skb_tail_pointer(skb) - (u8 *)nlh;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001017 } else {
1018 nlh->nlmsg_type = NLMSG_ERROR;
Hong zhi guo573ce262013-03-27 06:47:04 +00001019 nlh->nlmsg_len = nlmsg_msg_size(sizeof(struct nlmsgerr));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001020 skb_trim(skb, nlh->nlmsg_len);
Hong zhi guo573ce262013-03-27 06:47:04 +00001021 ((struct nlmsgerr *)nlmsg_data(nlh))->error = -EMSGSIZE;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001022 }
Eric W. Biederman15e47302012-09-07 20:12:54 +00001023 rtnl_unicast(skb, net, NETLINK_CB(skb).portid);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001024 } else
Patrick Ruddye4a38c02018-10-01 09:41:27 +01001025 ip6_mr_forward(net, mrt, skb->dev, skb, c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001026 }
1027}
1028
1029/*
Julien Gomesdd12d15c2017-06-20 13:54:18 -07001030 * Bounce a cache query up to pim6sd and netlink.
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001031 *
1032 * Called under mrt_lock.
1033 */
1034
Yuval Mintzb70432f2018-02-28 23:29:32 +02001035static int ip6mr_cache_report(struct mr_table *mrt, struct sk_buff *pkt,
Patrick McHardy6bd52142010-05-11 14:40:53 +02001036 mifi_t mifi, int assert)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001037{
Yuval Mintz8571ab42018-02-28 23:29:30 +02001038 struct sock *mroute6_sk;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001039 struct sk_buff *skb;
1040 struct mrt6msg *msg;
1041 int ret;
1042
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001043#ifdef CONFIG_IPV6_PIMSM_V2
1044 if (assert == MRT6MSG_WHOLEPKT)
1045 skb = skb_realloc_headroom(pkt, -skb_network_offset(pkt)
1046 +sizeof(*msg));
1047 else
1048#endif
1049 skb = alloc_skb(sizeof(struct ipv6hdr) + sizeof(*msg), GFP_ATOMIC);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001050
1051 if (!skb)
1052 return -ENOBUFS;
1053
1054 /* I suppose that internal messages
1055 * do not require checksums */
1056
1057 skb->ip_summed = CHECKSUM_UNNECESSARY;
1058
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001059#ifdef CONFIG_IPV6_PIMSM_V2
1060 if (assert == MRT6MSG_WHOLEPKT) {
1061 /* Ugly, but we have no choice with this interface.
1062 Duplicate old header, fix length etc.
1063 And all this only to mangle msg->im6_msgtype and
1064 to set msg->im6_mbz to "mbz" :-)
1065 */
1066 skb_push(skb, -skb_network_offset(pkt));
1067
1068 skb_push(skb, sizeof(*msg));
1069 skb_reset_transport_header(skb);
1070 msg = (struct mrt6msg *)skb_transport_header(skb);
1071 msg->im6_mbz = 0;
1072 msg->im6_msgtype = MRT6MSG_WHOLEPKT;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001073 msg->im6_mif = mrt->mroute_reg_vif_num;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001074 msg->im6_pad = 0;
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +00001075 msg->im6_src = ipv6_hdr(pkt)->saddr;
1076 msg->im6_dst = ipv6_hdr(pkt)->daddr;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001077
1078 skb->ip_summed = CHECKSUM_UNNECESSARY;
1079 } else
1080#endif
1081 {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001082 /*
1083 * Copy the IP header
1084 */
1085
1086 skb_put(skb, sizeof(struct ipv6hdr));
1087 skb_reset_network_header(skb);
1088 skb_copy_to_linear_data(skb, ipv6_hdr(pkt), sizeof(struct ipv6hdr));
1089
1090 /*
1091 * Add our header
1092 */
1093 skb_put(skb, sizeof(*msg));
1094 skb_reset_transport_header(skb);
1095 msg = (struct mrt6msg *)skb_transport_header(skb);
1096
1097 msg->im6_mbz = 0;
1098 msg->im6_msgtype = assert;
Rami Rosen6ac7eb02008-04-10 12:40:10 +03001099 msg->im6_mif = mifi;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001100 msg->im6_pad = 0;
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +00001101 msg->im6_src = ipv6_hdr(pkt)->saddr;
1102 msg->im6_dst = ipv6_hdr(pkt)->daddr;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001103
Eric Dumazetadf30902009-06-02 05:19:30 +00001104 skb_dst_set(skb, dst_clone(skb_dst(pkt)));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001105 skb->ip_summed = CHECKSUM_UNNECESSARY;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001106 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001107
Yuval Mintz8571ab42018-02-28 23:29:30 +02001108 rcu_read_lock();
Yuval Mintzb70432f2018-02-28 23:29:32 +02001109 mroute6_sk = rcu_dereference(mrt->mroute_sk);
Yuval Mintz8571ab42018-02-28 23:29:30 +02001110 if (!mroute6_sk) {
1111 rcu_read_unlock();
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001112 kfree_skb(skb);
1113 return -EINVAL;
1114 }
1115
Julien Gomesdd12d15c2017-06-20 13:54:18 -07001116 mrt6msg_netlink_event(mrt, skb);
1117
Yuval Mintz8571ab42018-02-28 23:29:30 +02001118 /* Deliver to user space multicast routing algorithms */
1119 ret = sock_queue_rcv_skb(mroute6_sk, skb);
1120 rcu_read_unlock();
Benjamin Therybd91b8b2008-12-10 16:07:08 -08001121 if (ret < 0) {
Joe Perchese87cc472012-05-13 21:56:26 +00001122 net_warn_ratelimited("mroute6: pending queue full, dropping entries\n");
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001123 kfree_skb(skb);
1124 }
1125
1126 return ret;
1127}
1128
Yuval Mintz494fff52018-02-28 23:29:34 +02001129/* Queue a packet for resolution. It gets locked cache entry! */
1130static int ip6mr_cache_unresolved(struct mr_table *mrt, mifi_t mifi,
Patrick Ruddye4a38c02018-10-01 09:41:27 +01001131 struct sk_buff *skb, struct net_device *dev)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001132{
Yuval Mintz494fff52018-02-28 23:29:34 +02001133 struct mfc6_cache *c;
Patrick McHardyf30a77842010-05-11 14:40:51 +02001134 bool found = false;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001135 int err;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001136
1137 spin_lock_bh(&mfc_unres_lock);
Yuval Mintz494fff52018-02-28 23:29:34 +02001138 list_for_each_entry(c, &mrt->mfc_unres_queue, _c.list) {
Patrick McHardyc476efb2010-05-11 14:40:48 +02001139 if (ipv6_addr_equal(&c->mf6c_mcastgrp, &ipv6_hdr(skb)->daddr) &&
Patrick McHardyf30a77842010-05-11 14:40:51 +02001140 ipv6_addr_equal(&c->mf6c_origin, &ipv6_hdr(skb)->saddr)) {
1141 found = true;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001142 break;
Patrick McHardyf30a77842010-05-11 14:40:51 +02001143 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001144 }
1145
Patrick McHardyf30a77842010-05-11 14:40:51 +02001146 if (!found) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001147 /*
1148 * Create a new entry if allowable
1149 */
1150
Patrick McHardy6bd52142010-05-11 14:40:53 +02001151 if (atomic_read(&mrt->cache_resolve_queue_len) >= 10 ||
Patrick McHardyb5aa30b2010-05-11 14:40:50 +02001152 (c = ip6mr_cache_alloc_unres()) == NULL) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001153 spin_unlock_bh(&mfc_unres_lock);
1154
1155 kfree_skb(skb);
1156 return -ENOBUFS;
1157 }
1158
Yuval Mintz494fff52018-02-28 23:29:34 +02001159 /* Fill in the new cache entry */
1160 c->_c.mfc_parent = -1;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001161 c->mf6c_origin = ipv6_hdr(skb)->saddr;
1162 c->mf6c_mcastgrp = ipv6_hdr(skb)->daddr;
1163
1164 /*
1165 * Reflect first query at pim6sd
1166 */
Patrick McHardy6bd52142010-05-11 14:40:53 +02001167 err = ip6mr_cache_report(mrt, skb, mifi, MRT6MSG_NOCACHE);
Benjamin Thery8229efd2008-12-10 16:30:15 -08001168 if (err < 0) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001169 /* If the report failed throw the cache entry
1170 out - Brad Parker
1171 */
1172 spin_unlock_bh(&mfc_unres_lock);
1173
Benjamin Thery58701ad2008-12-10 16:22:34 -08001174 ip6mr_cache_free(c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001175 kfree_skb(skb);
1176 return err;
1177 }
1178
Patrick McHardy6bd52142010-05-11 14:40:53 +02001179 atomic_inc(&mrt->cache_resolve_queue_len);
Yuval Mintz494fff52018-02-28 23:29:34 +02001180 list_add(&c->_c.list, &mrt->mfc_unres_queue);
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00001181 mr6_netlink_event(mrt, c, RTM_NEWROUTE);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001182
Patrick McHardy6bd52142010-05-11 14:40:53 +02001183 ipmr_do_expire_process(mrt);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001184 }
1185
Yuval Mintz494fff52018-02-28 23:29:34 +02001186 /* See if we can append the packet */
1187 if (c->_c.mfc_un.unres.unresolved.qlen > 3) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001188 kfree_skb(skb);
1189 err = -ENOBUFS;
1190 } else {
Patrick Ruddye4a38c02018-10-01 09:41:27 +01001191 if (dev) {
1192 skb->dev = dev;
1193 skb->skb_iif = dev->ifindex;
1194 }
Yuval Mintz494fff52018-02-28 23:29:34 +02001195 skb_queue_tail(&c->_c.mfc_un.unres.unresolved, skb);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001196 err = 0;
1197 }
1198
1199 spin_unlock_bh(&mfc_unres_lock);
1200 return err;
1201}
1202
1203/*
1204 * MFC6 cache manipulation by user space
1205 */
1206
Yuval Mintzb70432f2018-02-28 23:29:32 +02001207static int ip6mr_mfc_delete(struct mr_table *mrt, struct mf6cctl *mfc,
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001208 int parent)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001209{
Yuval Mintz87c418b2018-02-28 23:29:31 +02001210 struct mfc6_cache *c;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001211
Yuval Mintz87c418b2018-02-28 23:29:31 +02001212 /* The entries are added/deleted only under RTNL */
1213 rcu_read_lock();
1214 c = ip6mr_cache_find_parent(mrt, &mfc->mf6cc_origin.sin6_addr,
1215 &mfc->mf6cc_mcastgrp.sin6_addr, parent);
1216 rcu_read_unlock();
1217 if (!c)
1218 return -ENOENT;
Yuval Mintz494fff52018-02-28 23:29:34 +02001219 rhltable_remove(&mrt->mfc_hash, &c->_c.mnode, ip6mr_rht_params);
1220 list_del_rcu(&c->_c.list);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001221
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001222 call_ip6mr_mfc_entry_notifiers(read_pnet(&mrt->net),
1223 FIB_EVENT_ENTRY_DEL, c, mrt->id);
Yuval Mintz87c418b2018-02-28 23:29:31 +02001224 mr6_netlink_event(mrt, c, RTM_DELROUTE);
Yuval Mintz8c13af22018-03-26 15:01:36 +03001225 mr_cache_put(&c->_c);
Yuval Mintz87c418b2018-02-28 23:29:31 +02001226 return 0;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001227}
1228
1229static int ip6mr_device_event(struct notifier_block *this,
1230 unsigned long event, void *ptr)
1231{
Jiri Pirko351638e2013-05-28 01:30:21 +00001232 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
Benjamin Thery8229efd2008-12-10 16:30:15 -08001233 struct net *net = dev_net(dev);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001234 struct mr_table *mrt;
Yuval Mintz6853f212018-02-28 23:29:29 +02001235 struct vif_device *v;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001236 int ct;
1237
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001238 if (event != NETDEV_UNREGISTER)
1239 return NOTIFY_DONE;
1240
Patrick McHardyd1db2752010-05-11 14:40:55 +02001241 ip6mr_for_each_table(mrt, net) {
Yuval Mintzb70432f2018-02-28 23:29:32 +02001242 v = &mrt->vif_table[0];
Patrick McHardyd1db2752010-05-11 14:40:55 +02001243 for (ct = 0; ct < mrt->maxvif; ct++, v++) {
1244 if (v->dev == dev)
Nikolay Aleksandrov723b9292017-04-21 20:42:16 +03001245 mif6_delete(mrt, ct, 1, NULL);
Patrick McHardyd1db2752010-05-11 14:40:55 +02001246 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001247 }
Eric Dumazetc871e662009-10-28 04:48:11 +00001248
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001249 return NOTIFY_DONE;
1250}
1251
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001252static unsigned int ip6mr_seq_read(struct net *net)
1253{
1254 ASSERT_RTNL();
1255
1256 return net->ipv6.ipmr_seq + ip6mr_rules_seq_read(net);
1257}
1258
1259static int ip6mr_dump(struct net *net, struct notifier_block *nb)
1260{
1261 return mr_dump(net, nb, RTNL_FAMILY_IP6MR, ip6mr_rules_dump,
1262 ip6mr_mr_table_iter, &mrt_lock);
1263}
1264
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001265static struct notifier_block ip6_mr_notifier = {
1266 .notifier_call = ip6mr_device_event
1267};
1268
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001269static const struct fib_notifier_ops ip6mr_notifier_ops_template = {
1270 .family = RTNL_FAMILY_IP6MR,
1271 .fib_seq_read = ip6mr_seq_read,
1272 .fib_dump = ip6mr_dump,
1273 .owner = THIS_MODULE,
1274};
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001275
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001276static int __net_init ip6mr_notifier_init(struct net *net)
1277{
1278 struct fib_notifier_ops *ops;
1279
1280 net->ipv6.ipmr_seq = 0;
1281
1282 ops = fib_notifier_ops_register(&ip6mr_notifier_ops_template, net);
1283 if (IS_ERR(ops))
1284 return PTR_ERR(ops);
1285
1286 net->ipv6.ip6mr_notifier_ops = ops;
1287
1288 return 0;
1289}
1290
1291static void __net_exit ip6mr_notifier_exit(struct net *net)
1292{
1293 fib_notifier_ops_unregister(net->ipv6.ip6mr_notifier_ops);
1294 net->ipv6.ip6mr_notifier_ops = NULL;
1295}
1296
1297/* Setup for IP multicast routing */
Benjamin Thery4e168802008-12-10 16:15:08 -08001298static int __net_init ip6mr_net_init(struct net *net)
1299{
Patrick McHardyd1db2752010-05-11 14:40:55 +02001300 int err;
Patrick McHardyf30a77842010-05-11 14:40:51 +02001301
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001302 err = ip6mr_notifier_init(net);
1303 if (err)
1304 return err;
1305
Patrick McHardyd1db2752010-05-11 14:40:55 +02001306 err = ip6mr_rules_init(net);
1307 if (err < 0)
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001308 goto ip6mr_rules_fail;
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001309
1310#ifdef CONFIG_PROC_FS
1311 err = -ENOMEM;
Christoph Hellwigc3506372018-04-10 19:42:55 +02001312 if (!proc_create_net("ip6_mr_vif", 0, net->proc_net, &ip6mr_vif_seq_ops,
1313 sizeof(struct mr_vif_iter)))
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001314 goto proc_vif_fail;
Christoph Hellwigc3506372018-04-10 19:42:55 +02001315 if (!proc_create_net("ip6_mr_cache", 0, net->proc_net, &ipmr_mfc_seq_ops,
1316 sizeof(struct mr_mfc_iter)))
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001317 goto proc_cache_fail;
1318#endif
Patrick McHardy6bd52142010-05-11 14:40:53 +02001319
Benjamin Thery4a6258a2008-12-10 16:24:07 -08001320 return 0;
1321
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001322#ifdef CONFIG_PROC_FS
1323proc_cache_fail:
Gao fengece31ff2013-02-18 01:34:56 +00001324 remove_proc_entry("ip6_mr_vif", net->proc_net);
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001325proc_vif_fail:
Patrick McHardyd1db2752010-05-11 14:40:55 +02001326 ip6mr_rules_exit(net);
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001327#endif
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001328ip6mr_rules_fail:
1329 ip6mr_notifier_exit(net);
Benjamin Thery4e168802008-12-10 16:15:08 -08001330 return err;
1331}
1332
1333static void __net_exit ip6mr_net_exit(struct net *net)
1334{
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001335#ifdef CONFIG_PROC_FS
Gao fengece31ff2013-02-18 01:34:56 +00001336 remove_proc_entry("ip6_mr_cache", net->proc_net);
1337 remove_proc_entry("ip6_mr_vif", net->proc_net);
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001338#endif
Patrick McHardyd1db2752010-05-11 14:40:55 +02001339 ip6mr_rules_exit(net);
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001340 ip6mr_notifier_exit(net);
Benjamin Thery4e168802008-12-10 16:15:08 -08001341}
1342
1343static struct pernet_operations ip6mr_net_ops = {
1344 .init = ip6mr_net_init,
1345 .exit = ip6mr_net_exit,
1346};
1347
Wang Chen623d1a12008-07-03 12:13:30 +08001348int __init ip6_mr_init(void)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001349{
Wang Chen623d1a12008-07-03 12:13:30 +08001350 int err;
1351
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001352 mrt_cachep = kmem_cache_create("ip6_mrt_cache",
1353 sizeof(struct mfc6_cache),
1354 0, SLAB_HWCACHE_ALIGN,
1355 NULL);
1356 if (!mrt_cachep)
Wang Chen623d1a12008-07-03 12:13:30 +08001357 return -ENOMEM;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001358
Benjamin Thery4e168802008-12-10 16:15:08 -08001359 err = register_pernet_subsys(&ip6mr_net_ops);
1360 if (err)
1361 goto reg_pernet_fail;
1362
Wang Chen623d1a12008-07-03 12:13:30 +08001363 err = register_netdevice_notifier(&ip6_mr_notifier);
1364 if (err)
1365 goto reg_notif_fail;
Tom Goff403dbb92009-06-14 03:16:13 -07001366#ifdef CONFIG_IPV6_PIMSM_V2
1367 if (inet6_add_protocol(&pim6_protocol, IPPROTO_PIM) < 0) {
Joe Perchesf3213832012-05-15 14:11:53 +00001368 pr_err("%s: can't add PIM protocol\n", __func__);
Tom Goff403dbb92009-06-14 03:16:13 -07001369 err = -EAGAIN;
1370 goto add_proto_fail;
1371 }
1372#endif
Florian Westphala3fde2a2017-12-04 19:19:18 +01001373 err = rtnl_register_module(THIS_MODULE, RTNL_FAMILY_IP6MR, RTM_GETROUTE,
1374 NULL, ip6mr_rtm_dumproute, 0);
1375 if (err == 0)
1376 return 0;
1377
Tom Goff403dbb92009-06-14 03:16:13 -07001378#ifdef CONFIG_IPV6_PIMSM_V2
Florian Westphala3fde2a2017-12-04 19:19:18 +01001379 inet6_del_protocol(&pim6_protocol, IPPROTO_PIM);
Tom Goff403dbb92009-06-14 03:16:13 -07001380add_proto_fail:
1381 unregister_netdevice_notifier(&ip6_mr_notifier);
1382#endif
Benjamin Thery87b30a62008-11-10 16:34:11 -08001383reg_notif_fail:
Benjamin Thery4e168802008-12-10 16:15:08 -08001384 unregister_pernet_subsys(&ip6mr_net_ops);
1385reg_pernet_fail:
Benjamin Thery87b30a62008-11-10 16:34:11 -08001386 kmem_cache_destroy(mrt_cachep);
Wang Chen623d1a12008-07-03 12:13:30 +08001387 return err;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001388}
1389
Wang Chen623d1a12008-07-03 12:13:30 +08001390void ip6_mr_cleanup(void)
1391{
Duan Jiongffb13882014-11-19 09:35:39 +08001392 rtnl_unregister(RTNL_FAMILY_IP6MR, RTM_GETROUTE);
1393#ifdef CONFIG_IPV6_PIMSM_V2
1394 inet6_del_protocol(&pim6_protocol, IPPROTO_PIM);
1395#endif
Wang Chen623d1a12008-07-03 12:13:30 +08001396 unregister_netdevice_notifier(&ip6_mr_notifier);
Benjamin Thery4e168802008-12-10 16:15:08 -08001397 unregister_pernet_subsys(&ip6mr_net_ops);
Wang Chen623d1a12008-07-03 12:13:30 +08001398 kmem_cache_destroy(mrt_cachep);
1399}
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001400
Yuval Mintzb70432f2018-02-28 23:29:32 +02001401static int ip6mr_mfc_add(struct net *net, struct mr_table *mrt,
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001402 struct mf6cctl *mfc, int mrtsock, int parent)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001403{
Rami Rosen6ac7eb02008-04-10 12:40:10 +03001404 unsigned char ttls[MAXMIFS];
Yuval Mintz87c418b2018-02-28 23:29:31 +02001405 struct mfc6_cache *uc, *c;
Yuval Mintz494fff52018-02-28 23:29:34 +02001406 struct mr_mfc *_uc;
Yuval Mintz87c418b2018-02-28 23:29:31 +02001407 bool found;
1408 int i, err;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001409
Patrick McHardya50436f22010-03-17 06:04:14 +00001410 if (mfc->mf6cc_parent >= MAXMIFS)
1411 return -ENFILE;
1412
Rami Rosen6ac7eb02008-04-10 12:40:10 +03001413 memset(ttls, 255, MAXMIFS);
1414 for (i = 0; i < MAXMIFS; i++) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001415 if (IF_ISSET(i, &mfc->mf6cc_ifset))
1416 ttls[i] = 1;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001417 }
1418
Yuval Mintz87c418b2018-02-28 23:29:31 +02001419 /* The entries are added/deleted only under RTNL */
1420 rcu_read_lock();
1421 c = ip6mr_cache_find_parent(mrt, &mfc->mf6cc_origin.sin6_addr,
1422 &mfc->mf6cc_mcastgrp.sin6_addr, parent);
1423 rcu_read_unlock();
1424 if (c) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001425 write_lock_bh(&mrt_lock);
Yuval Mintz494fff52018-02-28 23:29:34 +02001426 c->_c.mfc_parent = mfc->mf6cc_parent;
1427 ip6mr_update_thresholds(mrt, &c->_c, ttls);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001428 if (!mrtsock)
Yuval Mintz494fff52018-02-28 23:29:34 +02001429 c->_c.mfc_flags |= MFC_STATIC;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001430 write_unlock_bh(&mrt_lock);
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001431 call_ip6mr_mfc_entry_notifiers(net, FIB_EVENT_ENTRY_REPLACE,
1432 c, mrt->id);
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00001433 mr6_netlink_event(mrt, c, RTM_NEWROUTE);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001434 return 0;
1435 }
1436
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001437 if (!ipv6_addr_any(&mfc->mf6cc_mcastgrp.sin6_addr) &&
1438 !ipv6_addr_is_multicast(&mfc->mf6cc_mcastgrp.sin6_addr))
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001439 return -EINVAL;
1440
Patrick McHardyb5aa30b2010-05-11 14:40:50 +02001441 c = ip6mr_cache_alloc();
Ian Morris63159f22015-03-29 14:00:04 +01001442 if (!c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001443 return -ENOMEM;
1444
1445 c->mf6c_origin = mfc->mf6cc_origin.sin6_addr;
1446 c->mf6c_mcastgrp = mfc->mf6cc_mcastgrp.sin6_addr;
Yuval Mintz494fff52018-02-28 23:29:34 +02001447 c->_c.mfc_parent = mfc->mf6cc_parent;
1448 ip6mr_update_thresholds(mrt, &c->_c, ttls);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001449 if (!mrtsock)
Yuval Mintz494fff52018-02-28 23:29:34 +02001450 c->_c.mfc_flags |= MFC_STATIC;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001451
Yuval Mintz494fff52018-02-28 23:29:34 +02001452 err = rhltable_insert_key(&mrt->mfc_hash, &c->cmparg, &c->_c.mnode,
Yuval Mintz87c418b2018-02-28 23:29:31 +02001453 ip6mr_rht_params);
1454 if (err) {
1455 pr_err("ip6mr: rhtable insert error %d\n", err);
1456 ip6mr_cache_free(c);
1457 return err;
1458 }
Yuval Mintz494fff52018-02-28 23:29:34 +02001459 list_add_tail_rcu(&c->_c.list, &mrt->mfc_cache_list);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001460
Yuval Mintz87c418b2018-02-28 23:29:31 +02001461 /* Check to see if we resolved a queued list. If so we
1462 * need to send on the frames and tidy up.
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001463 */
Patrick McHardyf30a77842010-05-11 14:40:51 +02001464 found = false;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001465 spin_lock_bh(&mfc_unres_lock);
Yuval Mintz494fff52018-02-28 23:29:34 +02001466 list_for_each_entry(_uc, &mrt->mfc_unres_queue, list) {
1467 uc = (struct mfc6_cache *)_uc;
Patrick McHardyc476efb2010-05-11 14:40:48 +02001468 if (ipv6_addr_equal(&uc->mf6c_origin, &c->mf6c_origin) &&
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001469 ipv6_addr_equal(&uc->mf6c_mcastgrp, &c->mf6c_mcastgrp)) {
Yuval Mintz494fff52018-02-28 23:29:34 +02001470 list_del(&_uc->list);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001471 atomic_dec(&mrt->cache_resolve_queue_len);
Patrick McHardyf30a77842010-05-11 14:40:51 +02001472 found = true;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001473 break;
1474 }
1475 }
Yuval Mintzb70432f2018-02-28 23:29:32 +02001476 if (list_empty(&mrt->mfc_unres_queue))
Patrick McHardy6bd52142010-05-11 14:40:53 +02001477 del_timer(&mrt->ipmr_expire_timer);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001478 spin_unlock_bh(&mfc_unres_lock);
1479
Patrick McHardyf30a77842010-05-11 14:40:51 +02001480 if (found) {
Patrick McHardy6bd52142010-05-11 14:40:53 +02001481 ip6mr_cache_resolve(net, mrt, uc, c);
Benjamin Thery58701ad2008-12-10 16:22:34 -08001482 ip6mr_cache_free(uc);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001483 }
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001484 call_ip6mr_mfc_entry_notifiers(net, FIB_EVENT_ENTRY_ADD,
1485 c, mrt->id);
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00001486 mr6_netlink_event(mrt, c, RTM_NEWROUTE);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001487 return 0;
1488}
1489
1490/*
1491 * Close the multicast socket, and clear the vif tables etc
1492 */
1493
Callum Sinclairca8d4792019-02-18 10:07:52 +13001494static void mroute_clean_tables(struct mr_table *mrt, int flags)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001495{
Yuval Mintz494fff52018-02-28 23:29:34 +02001496 struct mr_mfc *c, *tmp;
Eric Dumazetc871e662009-10-28 04:48:11 +00001497 LIST_HEAD(list);
Yuval Mintz87c418b2018-02-28 23:29:31 +02001498 int i;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001499
Yuval Mintz87c418b2018-02-28 23:29:31 +02001500 /* Shut down all active vif entries */
Callum Sinclairca8d4792019-02-18 10:07:52 +13001501 if (flags & (MRT6_FLUSH_MIFS | MRT6_FLUSH_MIFS_STATIC)) {
1502 for (i = 0; i < mrt->maxvif; i++) {
1503 if (((mrt->vif_table[i].flags & VIFF_STATIC) &&
1504 !(flags & MRT6_FLUSH_MIFS_STATIC)) ||
1505 (!(mrt->vif_table[i].flags & VIFF_STATIC) && !(flags & MRT6_FLUSH_MIFS)))
1506 continue;
1507 mif6_delete(mrt, i, 0, &list);
1508 }
1509 unregister_netdevice_many(&list);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001510 }
1511
Yuval Mintz87c418b2018-02-28 23:29:31 +02001512 /* Wipe the cache */
Callum Sinclairca8d4792019-02-18 10:07:52 +13001513 if (flags & (MRT6_FLUSH_MFC | MRT6_FLUSH_MFC_STATIC)) {
1514 list_for_each_entry_safe(c, tmp, &mrt->mfc_cache_list, list) {
1515 if (((c->mfc_flags & MFC_STATIC) && !(flags & MRT6_FLUSH_MFC_STATIC)) ||
1516 (!(c->mfc_flags & MFC_STATIC) && !(flags & MRT6_FLUSH_MFC)))
1517 continue;
1518 rhltable_remove(&mrt->mfc_hash, &c->mnode, ip6mr_rht_params);
1519 list_del_rcu(&c->list);
1520 call_ip6mr_mfc_entry_notifiers(read_pnet(&mrt->net),
1521 FIB_EVENT_ENTRY_DEL,
1522 (struct mfc6_cache *)c, mrt->id);
1523 mr6_netlink_event(mrt, (struct mfc6_cache *)c, RTM_DELROUTE);
1524 mr_cache_put(c);
1525 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001526 }
1527
Callum Sinclairca8d4792019-02-18 10:07:52 +13001528 if (flags & MRT6_FLUSH_MFC) {
1529 if (atomic_read(&mrt->cache_resolve_queue_len) != 0) {
1530 spin_lock_bh(&mfc_unres_lock);
1531 list_for_each_entry_safe(c, tmp, &mrt->mfc_unres_queue, list) {
1532 list_del(&c->list);
1533 mr6_netlink_event(mrt, (struct mfc6_cache *)c,
1534 RTM_DELROUTE);
1535 ip6mr_destroy_unres(mrt, (struct mfc6_cache *)c);
1536 }
1537 spin_unlock_bh(&mfc_unres_lock);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001538 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001539 }
1540}
1541
Yuval Mintzb70432f2018-02-28 23:29:32 +02001542static int ip6mr_sk_init(struct mr_table *mrt, struct sock *sk)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001543{
1544 int err = 0;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001545 struct net *net = sock_net(sk);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001546
1547 rtnl_lock();
1548 write_lock_bh(&mrt_lock);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001549 if (rtnl_dereference(mrt->mroute_sk)) {
Eric Dumazet927265b2016-07-08 05:46:04 +02001550 err = -EADDRINUSE;
Yuval Mintz8571ab42018-02-28 23:29:30 +02001551 } else {
Yuval Mintzb70432f2018-02-28 23:29:32 +02001552 rcu_assign_pointer(mrt->mroute_sk, sk);
Eric Dumazeta366e302018-03-07 08:43:19 -08001553 sock_set_flag(sk, SOCK_RCU_FREE);
Yuval Mintz8571ab42018-02-28 23:29:30 +02001554 net->ipv6.devconf_all->mc_forwarding++;
Eric Dumazet927265b2016-07-08 05:46:04 +02001555 }
1556 write_unlock_bh(&mrt_lock);
1557
1558 if (!err)
David Ahern85b3daa2017-03-28 14:28:04 -07001559 inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
1560 NETCONFA_MC_FORWARDING,
Nicolas Dichteld67b8c62012-12-04 01:13:35 +00001561 NETCONFA_IFINDEX_ALL,
1562 net->ipv6.devconf_all);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001563 rtnl_unlock();
1564
1565 return err;
1566}
1567
1568int ip6mr_sk_done(struct sock *sk)
1569{
Patrick McHardyd1db2752010-05-11 14:40:55 +02001570 int err = -EACCES;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001571 struct net *net = sock_net(sk);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001572 struct mr_table *mrt;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001573
Francesco Ruggeri338d1822017-11-08 11:23:46 -08001574 if (sk->sk_type != SOCK_RAW ||
1575 inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
1576 return err;
1577
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001578 rtnl_lock();
Patrick McHardyd1db2752010-05-11 14:40:55 +02001579 ip6mr_for_each_table(mrt, net) {
Yuval Mintzb70432f2018-02-28 23:29:32 +02001580 if (sk == rtnl_dereference(mrt->mroute_sk)) {
Patrick McHardyd1db2752010-05-11 14:40:55 +02001581 write_lock_bh(&mrt_lock);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001582 RCU_INIT_POINTER(mrt->mroute_sk, NULL);
Eric Dumazeta366e302018-03-07 08:43:19 -08001583 /* Note that mroute_sk had SOCK_RCU_FREE set,
1584 * so the RCU grace period before sk freeing
1585 * is guaranteed by sk_destruct()
1586 */
Patrick McHardyd1db2752010-05-11 14:40:55 +02001587 net->ipv6.devconf_all->mc_forwarding--;
Eric Dumazet927265b2016-07-08 05:46:04 +02001588 write_unlock_bh(&mrt_lock);
David Ahern85b3daa2017-03-28 14:28:04 -07001589 inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
Nicolas Dichteld67b8c62012-12-04 01:13:35 +00001590 NETCONFA_MC_FORWARDING,
1591 NETCONFA_IFINDEX_ALL,
1592 net->ipv6.devconf_all);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001593
Callum Sinclairca8d4792019-02-18 10:07:52 +13001594 mroute_clean_tables(mrt, MRT6_FLUSH_MIFS | MRT6_FLUSH_MFC);
Patrick McHardyd1db2752010-05-11 14:40:55 +02001595 err = 0;
1596 break;
1597 }
1598 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001599 rtnl_unlock();
1600
1601 return err;
1602}
1603
Yuval Mintz8571ab42018-02-28 23:29:30 +02001604bool mroute6_is_socket(struct net *net, struct sk_buff *skb)
Patrick McHardy6bd52142010-05-11 14:40:53 +02001605{
Yuval Mintzb70432f2018-02-28 23:29:32 +02001606 struct mr_table *mrt;
David S. Miller4c9483b2011-03-12 16:22:43 -05001607 struct flowi6 fl6 = {
Julian Anastasove374c612014-04-28 10:51:56 +03001608 .flowi6_iif = skb->skb_iif ? : LOOPBACK_IFINDEX,
David S. Miller4c9483b2011-03-12 16:22:43 -05001609 .flowi6_oif = skb->dev->ifindex,
1610 .flowi6_mark = skb->mark,
Patrick McHardyd1db2752010-05-11 14:40:55 +02001611 };
1612
David S. Miller4c9483b2011-03-12 16:22:43 -05001613 if (ip6mr_fib_lookup(net, &fl6, &mrt) < 0)
Patrick McHardyd1db2752010-05-11 14:40:55 +02001614 return NULL;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001615
Yuval Mintzb70432f2018-02-28 23:29:32 +02001616 return rcu_access_pointer(mrt->mroute_sk);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001617}
Yuval Mintz8571ab42018-02-28 23:29:30 +02001618EXPORT_SYMBOL(mroute6_is_socket);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001619
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001620/*
1621 * Socket options and virtual interface manipulation. The whole
1622 * virtual interface system is a complete heap, but unfortunately
1623 * that's how BSD mrouted happens to think. Maybe one day with a proper
1624 * MOSPF/PIM router set up we can clean this up.
1625 */
1626
David S. Millerb7058842009-09-30 16:12:20 -07001627int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsigned int optlen)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001628{
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001629 int ret, parent = 0;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001630 struct mif6ctl vif;
1631 struct mf6cctl mfc;
1632 mifi_t mifi;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001633 struct net *net = sock_net(sk);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001634 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +02001635
Xin Long99253eb2017-02-24 16:29:06 +08001636 if (sk->sk_type != SOCK_RAW ||
1637 inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
1638 return -EOPNOTSUPP;
1639
Patrick McHardyd1db2752010-05-11 14:40:55 +02001640 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +01001641 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +02001642 return -ENOENT;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001643
1644 if (optname != MRT6_INIT) {
Yuval Mintzb70432f2018-02-28 23:29:32 +02001645 if (sk != rcu_access_pointer(mrt->mroute_sk) &&
Yuval Mintz8571ab42018-02-28 23:29:30 +02001646 !ns_capable(net->user_ns, CAP_NET_ADMIN))
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001647 return -EACCES;
1648 }
1649
1650 switch (optname) {
1651 case MRT6_INIT:
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001652 if (optlen < sizeof(int))
1653 return -EINVAL;
1654
Patrick McHardy6bd52142010-05-11 14:40:53 +02001655 return ip6mr_sk_init(mrt, sk);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001656
1657 case MRT6_DONE:
1658 return ip6mr_sk_done(sk);
1659
1660 case MRT6_ADD_MIF:
1661 if (optlen < sizeof(vif))
1662 return -EINVAL;
1663 if (copy_from_user(&vif, optval, sizeof(vif)))
1664 return -EFAULT;
Rami Rosen6ac7eb02008-04-10 12:40:10 +03001665 if (vif.mif6c_mifi >= MAXMIFS)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001666 return -ENFILE;
1667 rtnl_lock();
Yuval Mintz8571ab42018-02-28 23:29:30 +02001668 ret = mif6_add(net, mrt, &vif,
Yuval Mintzb70432f2018-02-28 23:29:32 +02001669 sk == rtnl_dereference(mrt->mroute_sk));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001670 rtnl_unlock();
1671 return ret;
1672
1673 case MRT6_DEL_MIF:
1674 if (optlen < sizeof(mifi_t))
1675 return -EINVAL;
1676 if (copy_from_user(&mifi, optval, sizeof(mifi_t)))
1677 return -EFAULT;
1678 rtnl_lock();
Nikolay Aleksandrov723b9292017-04-21 20:42:16 +03001679 ret = mif6_delete(mrt, mifi, 0, NULL);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001680 rtnl_unlock();
1681 return ret;
1682
1683 /*
1684 * Manipulate the forwarding caches. These live
1685 * in a sort of kernel/user symbiosis.
1686 */
1687 case MRT6_ADD_MFC:
1688 case MRT6_DEL_MFC:
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001689 parent = -1;
Gustavo A. R. Silva275757e62017-10-16 16:36:52 -05001690 /* fall through */
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001691 case MRT6_ADD_MFC_PROXY:
1692 case MRT6_DEL_MFC_PROXY:
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001693 if (optlen < sizeof(mfc))
1694 return -EINVAL;
1695 if (copy_from_user(&mfc, optval, sizeof(mfc)))
1696 return -EFAULT;
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001697 if (parent == 0)
1698 parent = mfc.mf6cc_parent;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001699 rtnl_lock();
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001700 if (optname == MRT6_DEL_MFC || optname == MRT6_DEL_MFC_PROXY)
1701 ret = ip6mr_mfc_delete(mrt, &mfc, parent);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001702 else
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001703 ret = ip6mr_mfc_add(net, mrt, &mfc,
Yuval Mintz8571ab42018-02-28 23:29:30 +02001704 sk ==
Yuval Mintzb70432f2018-02-28 23:29:32 +02001705 rtnl_dereference(mrt->mroute_sk),
Yuval Mintz8571ab42018-02-28 23:29:30 +02001706 parent);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001707 rtnl_unlock();
1708 return ret;
1709
Callum Sinclairca8d4792019-02-18 10:07:52 +13001710 case MRT6_FLUSH:
1711 {
1712 int flags;
1713
1714 if (optlen != sizeof(flags))
1715 return -EINVAL;
1716 if (get_user(flags, (int __user *)optval))
1717 return -EFAULT;
1718 rtnl_lock();
1719 mroute_clean_tables(mrt, flags);
1720 rtnl_unlock();
1721 return 0;
1722 }
1723
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001724 /*
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001725 * Control PIM assert (to activate pim will activate assert)
1726 */
1727 case MRT6_ASSERT:
1728 {
1729 int v;
Joe Perches03f52a02012-11-25 18:26:34 +00001730
1731 if (optlen != sizeof(v))
1732 return -EINVAL;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001733 if (get_user(v, (int __user *)optval))
1734 return -EFAULT;
Joe Perches53d68412012-11-25 09:35:30 +00001735 mrt->mroute_do_assert = v;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001736 return 0;
1737 }
1738
1739#ifdef CONFIG_IPV6_PIMSM_V2
1740 case MRT6_PIM:
1741 {
YOSHIFUJI Hideakia9f83bf2008-04-10 15:41:28 +09001742 int v;
Joe Perches03f52a02012-11-25 18:26:34 +00001743
1744 if (optlen != sizeof(v))
1745 return -EINVAL;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001746 if (get_user(v, (int __user *)optval))
1747 return -EFAULT;
1748 v = !!v;
1749 rtnl_lock();
1750 ret = 0;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001751 if (v != mrt->mroute_do_pim) {
1752 mrt->mroute_do_pim = v;
1753 mrt->mroute_do_assert = v;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001754 }
1755 rtnl_unlock();
1756 return ret;
1757 }
1758
1759#endif
Patrick McHardyd1db2752010-05-11 14:40:55 +02001760#ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
1761 case MRT6_TABLE:
1762 {
1763 u32 v;
1764
1765 if (optlen != sizeof(u32))
1766 return -EINVAL;
1767 if (get_user(v, (u32 __user *)optval))
1768 return -EFAULT;
Dan Carpenter75356a82013-01-23 20:38:34 +00001769 /* "pim6reg%u" should not exceed 16 bytes (IFNAMSIZ) */
1770 if (v != RT_TABLE_DEFAULT && v >= 100000000)
1771 return -EINVAL;
Yuval Mintzb70432f2018-02-28 23:29:32 +02001772 if (sk == rcu_access_pointer(mrt->mroute_sk))
Patrick McHardyd1db2752010-05-11 14:40:55 +02001773 return -EBUSY;
1774
1775 rtnl_lock();
1776 ret = 0;
Sabrina Dubrocae783bb02018-06-05 15:02:00 +02001777 mrt = ip6mr_new_table(net, v);
1778 if (IS_ERR(mrt))
1779 ret = PTR_ERR(mrt);
Sabrina Dubroca848235e2018-06-05 15:01:59 +02001780 else
1781 raw6_sk(sk)->ip6mr_table = v;
Patrick McHardyd1db2752010-05-11 14:40:55 +02001782 rtnl_unlock();
1783 return ret;
1784 }
1785#endif
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001786 /*
Rami Rosen7d120c52008-04-23 14:35:13 +03001787 * Spurious command, or MRT6_VERSION which you cannot
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001788 * set.
1789 */
1790 default:
1791 return -ENOPROTOOPT;
1792 }
1793}
1794
1795/*
1796 * Getsock opt support for the multicast routing system.
1797 */
1798
1799int ip6_mroute_getsockopt(struct sock *sk, int optname, char __user *optval,
1800 int __user *optlen)
1801{
1802 int olr;
1803 int val;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001804 struct net *net = sock_net(sk);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001805 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +02001806
Xin Long99253eb2017-02-24 16:29:06 +08001807 if (sk->sk_type != SOCK_RAW ||
1808 inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
1809 return -EOPNOTSUPP;
1810
Patrick McHardyd1db2752010-05-11 14:40:55 +02001811 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +01001812 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +02001813 return -ENOENT;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001814
1815 switch (optname) {
1816 case MRT6_VERSION:
1817 val = 0x0305;
1818 break;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001819#ifdef CONFIG_IPV6_PIMSM_V2
1820 case MRT6_PIM:
Patrick McHardy6bd52142010-05-11 14:40:53 +02001821 val = mrt->mroute_do_pim;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001822 break;
1823#endif
1824 case MRT6_ASSERT:
Patrick McHardy6bd52142010-05-11 14:40:53 +02001825 val = mrt->mroute_do_assert;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001826 break;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001827 default:
1828 return -ENOPROTOOPT;
1829 }
1830
1831 if (get_user(olr, optlen))
1832 return -EFAULT;
1833
1834 olr = min_t(int, olr, sizeof(int));
1835 if (olr < 0)
1836 return -EINVAL;
1837
1838 if (put_user(olr, optlen))
1839 return -EFAULT;
1840 if (copy_to_user(optval, &val, olr))
1841 return -EFAULT;
1842 return 0;
1843}
1844
1845/*
1846 * The IP multicast ioctl support routines.
1847 */
1848
1849int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg)
1850{
1851 struct sioc_sg_req6 sr;
1852 struct sioc_mif_req6 vr;
Yuval Mintz6853f212018-02-28 23:29:29 +02001853 struct vif_device *vif;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001854 struct mfc6_cache *c;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001855 struct net *net = sock_net(sk);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001856 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +02001857
1858 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +01001859 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +02001860 return -ENOENT;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001861
1862 switch (cmd) {
1863 case SIOCGETMIFCNT_IN6:
1864 if (copy_from_user(&vr, arg, sizeof(vr)))
1865 return -EFAULT;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001866 if (vr.mifi >= mrt->maxvif)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001867 return -EINVAL;
Gustavo A. R. Silva69d2c862018-12-11 14:10:08 -06001868 vr.mifi = array_index_nospec(vr.mifi, mrt->maxvif);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001869 read_lock(&mrt_lock);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001870 vif = &mrt->vif_table[vr.mifi];
1871 if (VIF_EXISTS(mrt, vr.mifi)) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001872 vr.icount = vif->pkt_in;
1873 vr.ocount = vif->pkt_out;
1874 vr.ibytes = vif->bytes_in;
1875 vr.obytes = vif->bytes_out;
1876 read_unlock(&mrt_lock);
1877
1878 if (copy_to_user(arg, &vr, sizeof(vr)))
1879 return -EFAULT;
1880 return 0;
1881 }
1882 read_unlock(&mrt_lock);
1883 return -EADDRNOTAVAIL;
1884 case SIOCGETSGCNT_IN6:
1885 if (copy_from_user(&sr, arg, sizeof(sr)))
1886 return -EFAULT;
1887
Yuval Mintz87c418b2018-02-28 23:29:31 +02001888 rcu_read_lock();
Patrick McHardy6bd52142010-05-11 14:40:53 +02001889 c = ip6mr_cache_find(mrt, &sr.src.sin6_addr, &sr.grp.sin6_addr);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001890 if (c) {
Yuval Mintz494fff52018-02-28 23:29:34 +02001891 sr.pktcnt = c->_c.mfc_un.res.pkt;
1892 sr.bytecnt = c->_c.mfc_un.res.bytes;
1893 sr.wrong_if = c->_c.mfc_un.res.wrong_if;
Yuval Mintz87c418b2018-02-28 23:29:31 +02001894 rcu_read_unlock();
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001895
1896 if (copy_to_user(arg, &sr, sizeof(sr)))
1897 return -EFAULT;
1898 return 0;
1899 }
Yuval Mintz87c418b2018-02-28 23:29:31 +02001900 rcu_read_unlock();
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001901 return -EADDRNOTAVAIL;
1902 default:
1903 return -ENOIOCTLCMD;
1904 }
1905}
1906
David S. Millere2d57762011-02-03 17:59:32 -08001907#ifdef CONFIG_COMPAT
1908struct compat_sioc_sg_req6 {
1909 struct sockaddr_in6 src;
1910 struct sockaddr_in6 grp;
1911 compat_ulong_t pktcnt;
1912 compat_ulong_t bytecnt;
1913 compat_ulong_t wrong_if;
1914};
1915
1916struct compat_sioc_mif_req6 {
1917 mifi_t mifi;
1918 compat_ulong_t icount;
1919 compat_ulong_t ocount;
1920 compat_ulong_t ibytes;
1921 compat_ulong_t obytes;
1922};
1923
1924int ip6mr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg)
1925{
1926 struct compat_sioc_sg_req6 sr;
1927 struct compat_sioc_mif_req6 vr;
Yuval Mintz6853f212018-02-28 23:29:29 +02001928 struct vif_device *vif;
David S. Millere2d57762011-02-03 17:59:32 -08001929 struct mfc6_cache *c;
1930 struct net *net = sock_net(sk);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001931 struct mr_table *mrt;
David S. Millere2d57762011-02-03 17:59:32 -08001932
1933 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +01001934 if (!mrt)
David S. Millere2d57762011-02-03 17:59:32 -08001935 return -ENOENT;
1936
1937 switch (cmd) {
1938 case SIOCGETMIFCNT_IN6:
1939 if (copy_from_user(&vr, arg, sizeof(vr)))
1940 return -EFAULT;
1941 if (vr.mifi >= mrt->maxvif)
1942 return -EINVAL;
Gustavo A. R. Silva69d2c862018-12-11 14:10:08 -06001943 vr.mifi = array_index_nospec(vr.mifi, mrt->maxvif);
David S. Millere2d57762011-02-03 17:59:32 -08001944 read_lock(&mrt_lock);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001945 vif = &mrt->vif_table[vr.mifi];
1946 if (VIF_EXISTS(mrt, vr.mifi)) {
David S. Millere2d57762011-02-03 17:59:32 -08001947 vr.icount = vif->pkt_in;
1948 vr.ocount = vif->pkt_out;
1949 vr.ibytes = vif->bytes_in;
1950 vr.obytes = vif->bytes_out;
1951 read_unlock(&mrt_lock);
1952
1953 if (copy_to_user(arg, &vr, sizeof(vr)))
1954 return -EFAULT;
1955 return 0;
1956 }
1957 read_unlock(&mrt_lock);
1958 return -EADDRNOTAVAIL;
1959 case SIOCGETSGCNT_IN6:
1960 if (copy_from_user(&sr, arg, sizeof(sr)))
1961 return -EFAULT;
1962
Yuval Mintz87c418b2018-02-28 23:29:31 +02001963 rcu_read_lock();
David S. Millere2d57762011-02-03 17:59:32 -08001964 c = ip6mr_cache_find(mrt, &sr.src.sin6_addr, &sr.grp.sin6_addr);
1965 if (c) {
Yuval Mintz494fff52018-02-28 23:29:34 +02001966 sr.pktcnt = c->_c.mfc_un.res.pkt;
1967 sr.bytecnt = c->_c.mfc_un.res.bytes;
1968 sr.wrong_if = c->_c.mfc_un.res.wrong_if;
Yuval Mintz87c418b2018-02-28 23:29:31 +02001969 rcu_read_unlock();
David S. Millere2d57762011-02-03 17:59:32 -08001970
1971 if (copy_to_user(arg, &sr, sizeof(sr)))
1972 return -EFAULT;
1973 return 0;
1974 }
Yuval Mintz87c418b2018-02-28 23:29:31 +02001975 rcu_read_unlock();
David S. Millere2d57762011-02-03 17:59:32 -08001976 return -EADDRNOTAVAIL;
1977 default:
1978 return -ENOIOCTLCMD;
1979 }
1980}
1981#endif
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001982
Eric W. Biederman0c4b51f2015-09-15 20:04:18 -05001983static inline int ip6mr_forward2_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001984{
Ido Schimmel87c11f12019-03-03 07:34:57 +00001985 IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
1986 IPSTATS_MIB_OUTFORWDATAGRAMS);
1987 IP6_ADD_STATS(net, ip6_dst_idev(skb_dst(skb)),
1988 IPSTATS_MIB_OUTOCTETS, skb->len);
Eric W. Biederman13206b62015-10-07 16:48:35 -05001989 return dst_output(net, sk, skb);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001990}
1991
1992/*
1993 * Processing handlers for ip6mr_forward
1994 */
1995
Yuval Mintzb70432f2018-02-28 23:29:32 +02001996static int ip6mr_forward2(struct net *net, struct mr_table *mrt,
David Ahernf5c6dfd2018-12-17 15:36:11 -08001997 struct sk_buff *skb, int vifi)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001998{
1999 struct ipv6hdr *ipv6h;
Yuval Mintzb70432f2018-02-28 23:29:32 +02002000 struct vif_device *vif = &mrt->vif_table[vifi];
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002001 struct net_device *dev;
2002 struct dst_entry *dst;
David S. Miller4c9483b2011-03-12 16:22:43 -05002003 struct flowi6 fl6;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002004
Ian Morris63159f22015-03-29 14:00:04 +01002005 if (!vif->dev)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002006 goto out_free;
2007
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002008#ifdef CONFIG_IPV6_PIMSM_V2
2009 if (vif->flags & MIFF_REGISTER) {
2010 vif->pkt_out++;
2011 vif->bytes_out += skb->len;
Pavel Emelyanovdc58c782008-05-21 14:17:54 -07002012 vif->dev->stats.tx_bytes += skb->len;
2013 vif->dev->stats.tx_packets++;
Patrick McHardy6bd52142010-05-11 14:40:53 +02002014 ip6mr_cache_report(mrt, skb, vifi, MRT6MSG_WHOLEPKT);
Ilpo Järvinen8da73b72008-12-14 23:15:49 -08002015 goto out_free;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002016 }
2017#endif
2018
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002019 ipv6h = ipv6_hdr(skb);
2020
David S. Miller4c9483b2011-03-12 16:22:43 -05002021 fl6 = (struct flowi6) {
2022 .flowi6_oif = vif->link,
2023 .daddr = ipv6h->daddr,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002024 };
2025
David S. Miller4c9483b2011-03-12 16:22:43 -05002026 dst = ip6_route_output(net, NULL, &fl6);
RongQing.Li5095d642012-02-21 22:10:49 +00002027 if (dst->error) {
2028 dst_release(dst);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002029 goto out_free;
RongQing.Li5095d642012-02-21 22:10:49 +00002030 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002031
Eric Dumazetadf30902009-06-02 05:19:30 +00002032 skb_dst_drop(skb);
2033 skb_dst_set(skb, dst);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002034
2035 /*
2036 * RFC1584 teaches, that DVMRP/PIM router must deliver packets locally
2037 * not only before forwarding, but after forwarding on all output
2038 * interfaces. It is clear, if mrouter runs a multicasting
2039 * program, it should receive packets not depending to what interface
2040 * program is joined.
2041 * If we will not make it, the program will have to join on all
2042 * interfaces. On the other hand, multihoming host (or router, but
2043 * not mrouter) cannot join to more than one interface - it will
2044 * result in receiving multiple packets.
2045 */
2046 dev = vif->dev;
2047 skb->dev = dev;
2048 vif->pkt_out++;
2049 vif->bytes_out += skb->len;
2050
2051 /* We are about to write */
2052 /* XXX: extension headers? */
2053 if (skb_cow(skb, sizeof(*ipv6h) + LL_RESERVED_SPACE(dev)))
2054 goto out_free;
2055
2056 ipv6h = ipv6_hdr(skb);
2057 ipv6h->hop_limit--;
2058
2059 IP6CB(skb)->flags |= IP6SKB_FORWARDED;
2060
Eric W. Biederman29a26a52015-09-15 20:04:16 -05002061 return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD,
2062 net, NULL, skb, skb->dev, dev,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002063 ip6mr_forward2_finish);
2064
2065out_free:
2066 kfree_skb(skb);
2067 return 0;
2068}
2069
Yuval Mintzb70432f2018-02-28 23:29:32 +02002070static int ip6mr_find_vif(struct mr_table *mrt, struct net_device *dev)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002071{
2072 int ct;
Patrick McHardy6bd52142010-05-11 14:40:53 +02002073
2074 for (ct = mrt->maxvif - 1; ct >= 0; ct--) {
Yuval Mintzb70432f2018-02-28 23:29:32 +02002075 if (mrt->vif_table[ct].dev == dev)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002076 break;
2077 }
2078 return ct;
2079}
2080
Yuval Mintzb70432f2018-02-28 23:29:32 +02002081static void ip6_mr_forward(struct net *net, struct mr_table *mrt,
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002082 struct net_device *dev, struct sk_buff *skb,
2083 struct mfc6_cache *c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002084{
2085 int psend = -1;
2086 int vif, ct;
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002087 int true_vifi = ip6mr_find_vif(mrt, dev);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002088
Yuval Mintz494fff52018-02-28 23:29:34 +02002089 vif = c->_c.mfc_parent;
2090 c->_c.mfc_un.res.pkt++;
2091 c->_c.mfc_un.res.bytes += skb->len;
2092 c->_c.mfc_un.res.lastuse = jiffies;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002093
Yuval Mintz494fff52018-02-28 23:29:34 +02002094 if (ipv6_addr_any(&c->mf6c_origin) && true_vifi >= 0) {
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002095 struct mfc6_cache *cache_proxy;
2096
Fabian Frederick40dc2ca2014-10-29 10:00:26 +01002097 /* For an (*,G) entry, we only check that the incoming
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002098 * interface is part of the static tree.
2099 */
Yuval Mintz87c418b2018-02-28 23:29:31 +02002100 rcu_read_lock();
Yuval Mintz845c9a72018-02-28 23:29:35 +02002101 cache_proxy = mr_mfc_find_any_parent(mrt, vif);
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002102 if (cache_proxy &&
Yuval Mintz494fff52018-02-28 23:29:34 +02002103 cache_proxy->_c.mfc_un.res.ttls[true_vifi] < 255) {
Yuval Mintz87c418b2018-02-28 23:29:31 +02002104 rcu_read_unlock();
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002105 goto forward;
Yuval Mintz87c418b2018-02-28 23:29:31 +02002106 }
2107 rcu_read_unlock();
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002108 }
2109
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002110 /*
2111 * Wrong interface: drop packet and (maybe) send PIM assert.
2112 */
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002113 if (mrt->vif_table[vif].dev != dev) {
Yuval Mintz494fff52018-02-28 23:29:34 +02002114 c->_c.mfc_un.res.wrong_if++;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002115
Patrick McHardy6bd52142010-05-11 14:40:53 +02002116 if (true_vifi >= 0 && mrt->mroute_do_assert &&
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002117 /* pimsm uses asserts, when switching from RPT to SPT,
2118 so that we cannot check that packet arrived on an oif.
2119 It is bad, but otherwise we would need to move pretty
2120 large chunk of pimd to kernel. Ough... --ANK
2121 */
Patrick McHardy6bd52142010-05-11 14:40:53 +02002122 (mrt->mroute_do_pim ||
Yuval Mintz494fff52018-02-28 23:29:34 +02002123 c->_c.mfc_un.res.ttls[true_vifi] < 255) &&
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002124 time_after(jiffies,
Yuval Mintz494fff52018-02-28 23:29:34 +02002125 c->_c.mfc_un.res.last_assert +
2126 MFC_ASSERT_THRESH)) {
2127 c->_c.mfc_un.res.last_assert = jiffies;
Patrick McHardy6bd52142010-05-11 14:40:53 +02002128 ip6mr_cache_report(mrt, skb, true_vifi, MRT6MSG_WRONGMIF);
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002129 }
2130 goto dont_forward;
2131 }
2132
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002133forward:
Yuval Mintzb70432f2018-02-28 23:29:32 +02002134 mrt->vif_table[vif].pkt_in++;
2135 mrt->vif_table[vif].bytes_in += skb->len;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002136
2137 /*
2138 * Forward the frame
2139 */
Yuval Mintz494fff52018-02-28 23:29:34 +02002140 if (ipv6_addr_any(&c->mf6c_origin) &&
2141 ipv6_addr_any(&c->mf6c_mcastgrp)) {
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002142 if (true_vifi >= 0 &&
Yuval Mintz494fff52018-02-28 23:29:34 +02002143 true_vifi != c->_c.mfc_parent &&
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002144 ipv6_hdr(skb)->hop_limit >
Yuval Mintz494fff52018-02-28 23:29:34 +02002145 c->_c.mfc_un.res.ttls[c->_c.mfc_parent]) {
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002146 /* It's an (*,*) entry and the packet is not coming from
2147 * the upstream: forward the packet to the upstream
2148 * only.
2149 */
Yuval Mintz494fff52018-02-28 23:29:34 +02002150 psend = c->_c.mfc_parent;
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002151 goto last_forward;
2152 }
2153 goto dont_forward;
2154 }
Yuval Mintz494fff52018-02-28 23:29:34 +02002155 for (ct = c->_c.mfc_un.res.maxvif - 1;
2156 ct >= c->_c.mfc_un.res.minvif; ct--) {
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002157 /* For (*,G) entry, don't forward to the incoming interface */
Yuval Mintz494fff52018-02-28 23:29:34 +02002158 if ((!ipv6_addr_any(&c->mf6c_origin) || ct != true_vifi) &&
2159 ipv6_hdr(skb)->hop_limit > c->_c.mfc_un.res.ttls[ct]) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002160 if (psend != -1) {
2161 struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
2162 if (skb2)
David Ahernf5c6dfd2018-12-17 15:36:11 -08002163 ip6mr_forward2(net, mrt, skb2, psend);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002164 }
2165 psend = ct;
2166 }
2167 }
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002168last_forward:
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002169 if (psend != -1) {
David Ahernf5c6dfd2018-12-17 15:36:11 -08002170 ip6mr_forward2(net, mrt, skb, psend);
Rami Rosen2b52c3a2013-07-21 03:00:31 +03002171 return;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002172 }
2173
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002174dont_forward:
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002175 kfree_skb(skb);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002176}
2177
2178
2179/*
2180 * Multicast packets for forwarding arrive here
2181 */
2182
2183int ip6_mr_input(struct sk_buff *skb)
2184{
2185 struct mfc6_cache *cache;
Benjamin Thery8229efd2008-12-10 16:30:15 -08002186 struct net *net = dev_net(skb->dev);
Yuval Mintzb70432f2018-02-28 23:29:32 +02002187 struct mr_table *mrt;
David S. Miller4c9483b2011-03-12 16:22:43 -05002188 struct flowi6 fl6 = {
2189 .flowi6_iif = skb->dev->ifindex,
2190 .flowi6_mark = skb->mark,
Patrick McHardyd1db2752010-05-11 14:40:55 +02002191 };
2192 int err;
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002193 struct net_device *dev;
2194
2195 /* skb->dev passed in is the master dev for vrfs.
2196 * Get the proper interface that does have a vif associated with it.
2197 */
2198 dev = skb->dev;
2199 if (netif_is_l3_master(skb->dev)) {
2200 dev = dev_get_by_index_rcu(net, IPCB(skb)->iif);
2201 if (!dev) {
2202 kfree_skb(skb);
2203 return -ENODEV;
2204 }
2205 }
Patrick McHardyd1db2752010-05-11 14:40:55 +02002206
David S. Miller4c9483b2011-03-12 16:22:43 -05002207 err = ip6mr_fib_lookup(net, &fl6, &mrt);
Ben Greear2015de52011-09-27 15:16:08 -04002208 if (err < 0) {
2209 kfree_skb(skb);
Patrick McHardyd1db2752010-05-11 14:40:55 +02002210 return err;
Ben Greear2015de52011-09-27 15:16:08 -04002211 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002212
2213 read_lock(&mrt_lock);
Patrick McHardy6bd52142010-05-11 14:40:53 +02002214 cache = ip6mr_cache_find(mrt,
Benjamin Thery8229efd2008-12-10 16:30:15 -08002215 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr);
Ian Morris63159f22015-03-29 14:00:04 +01002216 if (!cache) {
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002217 int vif = ip6mr_find_vif(mrt, dev);
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002218
2219 if (vif >= 0)
2220 cache = ip6mr_cache_find_any(mrt,
2221 &ipv6_hdr(skb)->daddr,
2222 vif);
2223 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002224
2225 /*
2226 * No usable cache entry
2227 */
Ian Morris63159f22015-03-29 14:00:04 +01002228 if (!cache) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002229 int vif;
2230
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002231 vif = ip6mr_find_vif(mrt, dev);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002232 if (vif >= 0) {
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002233 int err = ip6mr_cache_unresolved(mrt, vif, skb, dev);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002234 read_unlock(&mrt_lock);
2235
2236 return err;
2237 }
2238 read_unlock(&mrt_lock);
2239 kfree_skb(skb);
2240 return -ENODEV;
2241 }
2242
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002243 ip6_mr_forward(net, mrt, dev, skb, cache);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002244
2245 read_unlock(&mrt_lock);
2246
2247 return 0;
2248}
2249
Nikolay Aleksandrov2cf75072016-09-25 23:08:31 +02002250int ip6mr_get_route(struct net *net, struct sk_buff *skb, struct rtmsg *rtm,
David Ahernfd61c6b2017-01-17 15:51:07 -08002251 u32 portid)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002252{
2253 int err;
Yuval Mintzb70432f2018-02-28 23:29:32 +02002254 struct mr_table *mrt;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002255 struct mfc6_cache *cache;
Eric Dumazetadf30902009-06-02 05:19:30 +00002256 struct rt6_info *rt = (struct rt6_info *)skb_dst(skb);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002257
Patrick McHardyd1db2752010-05-11 14:40:55 +02002258 mrt = ip6mr_get_table(net, RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +01002259 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +02002260 return -ENOENT;
2261
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002262 read_lock(&mrt_lock);
Patrick McHardy6bd52142010-05-11 14:40:53 +02002263 cache = ip6mr_cache_find(mrt, &rt->rt6i_src.addr, &rt->rt6i_dst.addr);
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002264 if (!cache && skb->dev) {
2265 int vif = ip6mr_find_vif(mrt, skb->dev);
2266
2267 if (vif >= 0)
2268 cache = ip6mr_cache_find_any(mrt, &rt->rt6i_dst.addr,
2269 vif);
2270 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002271
2272 if (!cache) {
2273 struct sk_buff *skb2;
2274 struct ipv6hdr *iph;
2275 struct net_device *dev;
2276 int vif;
2277
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002278 dev = skb->dev;
Ian Morris63159f22015-03-29 14:00:04 +01002279 if (!dev || (vif = ip6mr_find_vif(mrt, dev)) < 0) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002280 read_unlock(&mrt_lock);
2281 return -ENODEV;
2282 }
2283
2284 /* really correct? */
2285 skb2 = alloc_skb(sizeof(struct ipv6hdr), GFP_ATOMIC);
2286 if (!skb2) {
2287 read_unlock(&mrt_lock);
2288 return -ENOMEM;
2289 }
2290
Nikolay Aleksandrov2cf75072016-09-25 23:08:31 +02002291 NETLINK_CB(skb2).portid = portid;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002292 skb_reset_transport_header(skb2);
2293
2294 skb_put(skb2, sizeof(struct ipv6hdr));
2295 skb_reset_network_header(skb2);
2296
2297 iph = ipv6_hdr(skb2);
2298 iph->version = 0;
2299 iph->priority = 0;
2300 iph->flow_lbl[0] = 0;
2301 iph->flow_lbl[1] = 0;
2302 iph->flow_lbl[2] = 0;
2303 iph->payload_len = 0;
2304 iph->nexthdr = IPPROTO_NONE;
2305 iph->hop_limit = 0;
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +00002306 iph->saddr = rt->rt6i_src.addr;
2307 iph->daddr = rt->rt6i_dst.addr;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002308
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002309 err = ip6mr_cache_unresolved(mrt, vif, skb2, dev);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002310 read_unlock(&mrt_lock);
2311
2312 return err;
2313 }
2314
Yuval Mintz7b0db852018-02-28 23:29:39 +02002315 err = mr_fill_mroute(mrt, skb, &cache->_c, rtm);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002316 read_unlock(&mrt_lock);
2317 return err;
2318}
2319
Yuval Mintzb70432f2018-02-28 23:29:32 +02002320static int ip6mr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
Nicolas Dichtelf5183382014-03-19 17:47:51 +01002321 u32 portid, u32 seq, struct mfc6_cache *c, int cmd,
2322 int flags)
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002323{
2324 struct nlmsghdr *nlh;
2325 struct rtmsg *rtm;
Nicolas Dichtel1eb99af52012-12-04 01:13:39 +00002326 int err;
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002327
Nicolas Dichtelf5183382014-03-19 17:47:51 +01002328 nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rtm), flags);
Ian Morris63159f22015-03-29 14:00:04 +01002329 if (!nlh)
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002330 return -EMSGSIZE;
2331
2332 rtm = nlmsg_data(nlh);
Nicolas Dichtel193c1e42012-12-04 01:01:49 +00002333 rtm->rtm_family = RTNL_FAMILY_IP6MR;
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002334 rtm->rtm_dst_len = 128;
2335 rtm->rtm_src_len = 128;
2336 rtm->rtm_tos = 0;
2337 rtm->rtm_table = mrt->id;
David S. Millerc78679e2012-04-01 20:27:33 -04002338 if (nla_put_u32(skb, RTA_TABLE, mrt->id))
2339 goto nla_put_failure;
Nicolas Dichtel1eb99af52012-12-04 01:13:39 +00002340 rtm->rtm_type = RTN_MULTICAST;
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002341 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
Yuval Mintz494fff52018-02-28 23:29:34 +02002342 if (c->_c.mfc_flags & MFC_STATIC)
Nicolas Dichtel9a68ac72012-12-04 01:13:38 +00002343 rtm->rtm_protocol = RTPROT_STATIC;
2344 else
2345 rtm->rtm_protocol = RTPROT_MROUTED;
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002346 rtm->rtm_flags = 0;
2347
Jiri Benc930345e2015-03-29 16:59:25 +02002348 if (nla_put_in6_addr(skb, RTA_SRC, &c->mf6c_origin) ||
2349 nla_put_in6_addr(skb, RTA_DST, &c->mf6c_mcastgrp))
David S. Millerc78679e2012-04-01 20:27:33 -04002350 goto nla_put_failure;
Yuval Mintz7b0db852018-02-28 23:29:39 +02002351 err = mr_fill_mroute(mrt, skb, &c->_c, rtm);
Nicolas Dichtel1eb99af52012-12-04 01:13:39 +00002352 /* do not break the dump if cache is unresolved */
2353 if (err < 0 && err != -ENOENT)
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002354 goto nla_put_failure;
2355
Johannes Berg053c0952015-01-16 22:09:00 +01002356 nlmsg_end(skb, nlh);
2357 return 0;
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002358
2359nla_put_failure:
2360 nlmsg_cancel(skb, nlh);
2361 return -EMSGSIZE;
2362}
2363
Yuval Mintz7b0db852018-02-28 23:29:39 +02002364static int _ip6mr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
2365 u32 portid, u32 seq, struct mr_mfc *c,
2366 int cmd, int flags)
2367{
2368 return ip6mr_fill_mroute(mrt, skb, portid, seq, (struct mfc6_cache *)c,
2369 cmd, flags);
2370}
2371
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002372static int mr6_msgsize(bool unresolved, int maxvif)
2373{
2374 size_t len =
2375 NLMSG_ALIGN(sizeof(struct rtmsg))
2376 + nla_total_size(4) /* RTA_TABLE */
2377 + nla_total_size(sizeof(struct in6_addr)) /* RTA_SRC */
2378 + nla_total_size(sizeof(struct in6_addr)) /* RTA_DST */
2379 ;
2380
2381 if (!unresolved)
2382 len = len
2383 + nla_total_size(4) /* RTA_IIF */
2384 + nla_total_size(0) /* RTA_MULTIPATH */
2385 + maxvif * NLA_ALIGN(sizeof(struct rtnexthop))
2386 /* RTA_MFC_STATS */
Nicolas Dichtel3d6b66c2016-04-21 18:58:27 +02002387 + nla_total_size_64bit(sizeof(struct rta_mfc_stats))
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002388 ;
2389
2390 return len;
2391}
2392
Yuval Mintzb70432f2018-02-28 23:29:32 +02002393static void mr6_netlink_event(struct mr_table *mrt, struct mfc6_cache *mfc,
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002394 int cmd)
2395{
2396 struct net *net = read_pnet(&mrt->net);
2397 struct sk_buff *skb;
2398 int err = -ENOBUFS;
2399
Yuval Mintz494fff52018-02-28 23:29:34 +02002400 skb = nlmsg_new(mr6_msgsize(mfc->_c.mfc_parent >= MAXMIFS, mrt->maxvif),
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002401 GFP_ATOMIC);
Ian Morris63159f22015-03-29 14:00:04 +01002402 if (!skb)
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002403 goto errout;
2404
Nicolas Dichtelf5183382014-03-19 17:47:51 +01002405 err = ip6mr_fill_mroute(mrt, skb, 0, 0, mfc, cmd, 0);
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002406 if (err < 0)
2407 goto errout;
2408
2409 rtnl_notify(skb, net, 0, RTNLGRP_IPV6_MROUTE, NULL, GFP_ATOMIC);
2410 return;
2411
2412errout:
2413 kfree_skb(skb);
2414 if (err < 0)
2415 rtnl_set_sk_err(net, RTNLGRP_IPV6_MROUTE, err);
2416}
2417
Julien Gomesdd12d15c2017-06-20 13:54:18 -07002418static size_t mrt6msg_netlink_msgsize(size_t payloadlen)
2419{
2420 size_t len =
2421 NLMSG_ALIGN(sizeof(struct rtgenmsg))
2422 + nla_total_size(1) /* IP6MRA_CREPORT_MSGTYPE */
2423 + nla_total_size(4) /* IP6MRA_CREPORT_MIF_ID */
2424 /* IP6MRA_CREPORT_SRC_ADDR */
2425 + nla_total_size(sizeof(struct in6_addr))
2426 /* IP6MRA_CREPORT_DST_ADDR */
2427 + nla_total_size(sizeof(struct in6_addr))
2428 /* IP6MRA_CREPORT_PKT */
2429 + nla_total_size(payloadlen)
2430 ;
2431
2432 return len;
2433}
2434
Yuval Mintzb70432f2018-02-28 23:29:32 +02002435static void mrt6msg_netlink_event(struct mr_table *mrt, struct sk_buff *pkt)
Julien Gomesdd12d15c2017-06-20 13:54:18 -07002436{
2437 struct net *net = read_pnet(&mrt->net);
2438 struct nlmsghdr *nlh;
2439 struct rtgenmsg *rtgenm;
2440 struct mrt6msg *msg;
2441 struct sk_buff *skb;
2442 struct nlattr *nla;
2443 int payloadlen;
2444
2445 payloadlen = pkt->len - sizeof(struct mrt6msg);
2446 msg = (struct mrt6msg *)skb_transport_header(pkt);
2447
2448 skb = nlmsg_new(mrt6msg_netlink_msgsize(payloadlen), GFP_ATOMIC);
2449 if (!skb)
2450 goto errout;
2451
2452 nlh = nlmsg_put(skb, 0, 0, RTM_NEWCACHEREPORT,
2453 sizeof(struct rtgenmsg), 0);
2454 if (!nlh)
2455 goto errout;
2456 rtgenm = nlmsg_data(nlh);
2457 rtgenm->rtgen_family = RTNL_FAMILY_IP6MR;
2458 if (nla_put_u8(skb, IP6MRA_CREPORT_MSGTYPE, msg->im6_msgtype) ||
2459 nla_put_u32(skb, IP6MRA_CREPORT_MIF_ID, msg->im6_mif) ||
2460 nla_put_in6_addr(skb, IP6MRA_CREPORT_SRC_ADDR,
2461 &msg->im6_src) ||
2462 nla_put_in6_addr(skb, IP6MRA_CREPORT_DST_ADDR,
2463 &msg->im6_dst))
2464 goto nla_put_failure;
2465
2466 nla = nla_reserve(skb, IP6MRA_CREPORT_PKT, payloadlen);
2467 if (!nla || skb_copy_bits(pkt, sizeof(struct mrt6msg),
2468 nla_data(nla), payloadlen))
2469 goto nla_put_failure;
2470
2471 nlmsg_end(skb, nlh);
2472
2473 rtnl_notify(skb, net, 0, RTNLGRP_IPV6_MROUTE_R, NULL, GFP_ATOMIC);
2474 return;
2475
2476nla_put_failure:
2477 nlmsg_cancel(skb, nlh);
2478errout:
2479 kfree_skb(skb);
2480 rtnl_set_sk_err(net, RTNLGRP_IPV6_MROUTE_R, -ENOBUFS);
2481}
2482
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002483static int ip6mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
2484{
David Aherne8ba3302018-10-07 20:16:35 -07002485 const struct nlmsghdr *nlh = cb->nlh;
David Ahern47246762018-10-15 18:56:42 -07002486 struct fib_dump_filter filter = {};
David Aherncb167892018-10-15 18:56:47 -07002487 int err;
David Aherne8ba3302018-10-07 20:16:35 -07002488
2489 if (cb->strict_check) {
David Ahern47246762018-10-15 18:56:42 -07002490 err = ip_valid_fib_dump_req(sock_net(skb->sk), nlh,
David Aherneffe6792018-10-15 18:56:48 -07002491 &filter, cb);
David Aherne8ba3302018-10-07 20:16:35 -07002492 if (err < 0)
2493 return err;
2494 }
2495
David Aherncb167892018-10-15 18:56:47 -07002496 if (filter.table_id) {
2497 struct mr_table *mrt;
2498
2499 mrt = ip6mr_get_table(sock_net(skb->sk), filter.table_id);
2500 if (!mrt) {
David Ahernae677bb2018-10-24 12:59:01 -07002501 if (filter.dump_all_families)
2502 return skb->len;
2503
David Aherncb167892018-10-15 18:56:47 -07002504 NL_SET_ERR_MSG_MOD(cb->extack, "MR table does not exist");
2505 return -ENOENT;
2506 }
2507 err = mr_table_dump(mrt, skb, cb, _ip6mr_fill_mroute,
2508 &mfc_unres_lock, &filter);
2509 return skb->len ? : err;
2510 }
2511
Yuval Mintz7b0db852018-02-28 23:29:39 +02002512 return mr_rtm_dumproute(skb, cb, ip6mr_mr_table_iter,
David Aherncb167892018-10-15 18:56:47 -07002513 _ip6mr_fill_mroute, &mfc_unres_lock, &filter);
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002514}