blob: 4e69847ed5bef4438499a800546e22fbed2962a7 [file] [log] [blame]
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001/*
2 * Linux IPv6 multicast routing support for BSD pim6sd
3 * Based on net/ipv4/ipmr.c.
4 *
5 * (c) 2004 Mickael Hoerdt, <hoerdt@clarinet.u-strasbg.fr>
6 * LSIIT Laboratory, Strasbourg, France
7 * (c) 2004 Jean-Philippe Andriot, <jean-philippe.andriot@6WIND.com>
8 * 6WIND, Paris, France
9 * Copyright (C)2007,2008 USAGI/WIDE Project
10 * YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 *
17 */
18
Linus Torvalds7c0f6ba2016-12-24 11:46:01 -080019#include <linux/uaccess.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090020#include <linux/types.h>
21#include <linux/sched.h>
22#include <linux/errno.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090023#include <linux/mm.h>
24#include <linux/kernel.h>
25#include <linux/fcntl.h>
26#include <linux/stat.h>
27#include <linux/socket.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090028#include <linux/inet.h>
29#include <linux/netdevice.h>
30#include <linux/inetdevice.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090031#include <linux/proc_fs.h>
32#include <linux/seq_file.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090033#include <linux/init.h>
David S. Millere2d57762011-02-03 17:59:32 -080034#include <linux/compat.h>
NeilBrown0eb71a92018-06-18 12:52:50 +100035#include <linux/rhashtable.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090036#include <net/protocol.h>
37#include <linux/skbuff.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090038#include <net/raw.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090039#include <linux/notifier.h>
40#include <linux/if_arp.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090041#include <net/checksum.h>
42#include <net/netlink.h>
Patrick McHardyd1db2752010-05-11 14:40:55 +020043#include <net/fib_rules.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090044
45#include <net/ipv6.h>
46#include <net/ip6_route.h>
47#include <linux/mroute6.h>
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +090048#include <linux/pim.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090049#include <net/addrconf.h>
50#include <linux/netfilter_ipv6.h>
Paul Gortmakerbc3b2d72011-07-15 11:47:34 -040051#include <linux/export.h>
Dave Jones5d6e4302009-01-31 00:51:49 -080052#include <net/ip6_checksum.h>
Nicolas Dichteld67b8c62012-12-04 01:13:35 +000053#include <linux/netconf.h>
Willem de Bruijncb9f1b72018-12-30 17:24:36 -050054#include <net/ip_tunnels.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090055
Gustavo A. R. Silva69d2c862018-12-11 14:10:08 -060056#include <linux/nospec.h>
57
Patrick McHardyd1db2752010-05-11 14:40:55 +020058struct ip6mr_rule {
59 struct fib_rule common;
60};
61
62struct ip6mr_result {
Yuval Mintzb70432f2018-02-28 23:29:32 +020063 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +020064};
65
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090066/* Big lock, protecting vif table, mrt cache and mroute socket state.
67 Note that the changes are semaphored via rtnl_lock.
68 */
69
70static DEFINE_RWLOCK(mrt_lock);
71
Yuval Mintzb70432f2018-02-28 23:29:32 +020072/* Multicast router control variables */
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090073
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090074/* Special spinlock for queue of unresolved entries */
75static DEFINE_SPINLOCK(mfc_unres_lock);
76
77/* We return to original Alan's scheme. Hash table of resolved
78 entries is changed only in process context and protected
79 with weak lock mrt_lock. Queue of unresolved entries is protected
80 with strong spinlock mfc_unres_lock.
81
82 In this case data path is free of exclusive locks at all.
83 */
84
85static struct kmem_cache *mrt_cachep __read_mostly;
86
Yuval Mintzb70432f2018-02-28 23:29:32 +020087static struct mr_table *ip6mr_new_table(struct net *net, u32 id);
88static void ip6mr_free_table(struct mr_table *mrt);
Patrick McHardyd1db2752010-05-11 14:40:55 +020089
Yuval Mintzb70432f2018-02-28 23:29:32 +020090static void ip6_mr_forward(struct net *net, struct mr_table *mrt,
Patrick Ruddye4a38c02018-10-01 09:41:27 +010091 struct net_device *dev, struct sk_buff *skb,
92 struct mfc6_cache *cache);
Yuval Mintzb70432f2018-02-28 23:29:32 +020093static int ip6mr_cache_report(struct mr_table *mrt, struct sk_buff *pkt,
Benjamin Thery8229efd2008-12-10 16:30:15 -080094 mifi_t mifi, int assert);
Yuval Mintzb70432f2018-02-28 23:29:32 +020095static void mr6_netlink_event(struct mr_table *mrt, struct mfc6_cache *mfc,
Nicolas Dichtel812e44d2012-12-04 01:13:41 +000096 int cmd);
Yuval Mintzb70432f2018-02-28 23:29:32 +020097static void mrt6msg_netlink_event(struct mr_table *mrt, struct sk_buff *pkt);
Patrick McHardy5b285ca2010-05-11 14:40:56 +020098static int ip6mr_rtm_dumproute(struct sk_buff *skb,
99 struct netlink_callback *cb);
Callum Sinclairca8d4792019-02-18 10:07:52 +1300100static void mroute_clean_tables(struct mr_table *mrt, int flags);
Kees Cooke99e88a2017-10-16 14:43:17 -0700101static void ipmr_expire_process(struct timer_list *t);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900102
Patrick McHardyd1db2752010-05-11 14:40:55 +0200103#ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
Eric Dumazet8ffb3352010-06-06 15:34:40 -0700104#define ip6mr_for_each_table(mrt, net) \
Patrick McHardyd1db2752010-05-11 14:40:55 +0200105 list_for_each_entry_rcu(mrt, &net->ipv6.mr6_tables, list)
106
Yuval Mintz7b0db852018-02-28 23:29:39 +0200107static struct mr_table *ip6mr_mr_table_iter(struct net *net,
108 struct mr_table *mrt)
109{
110 struct mr_table *ret;
111
112 if (!mrt)
113 ret = list_entry_rcu(net->ipv6.mr6_tables.next,
114 struct mr_table, list);
115 else
116 ret = list_entry_rcu(mrt->list.next,
117 struct mr_table, list);
118
119 if (&ret->list == &net->ipv6.mr6_tables)
120 return NULL;
121 return ret;
122}
123
Yuval Mintzb70432f2018-02-28 23:29:32 +0200124static struct mr_table *ip6mr_get_table(struct net *net, u32 id)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200125{
Yuval Mintzb70432f2018-02-28 23:29:32 +0200126 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200127
128 ip6mr_for_each_table(mrt, net) {
129 if (mrt->id == id)
130 return mrt;
131 }
132 return NULL;
133}
134
David S. Miller4c9483b2011-03-12 16:22:43 -0500135static int ip6mr_fib_lookup(struct net *net, struct flowi6 *flp6,
Yuval Mintzb70432f2018-02-28 23:29:32 +0200136 struct mr_table **mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200137{
Patrick McHardyd1db2752010-05-11 14:40:55 +0200138 int err;
Hannes Frederic Sowa95f4a452014-01-13 02:45:22 +0100139 struct ip6mr_result res;
140 struct fib_lookup_arg arg = {
141 .result = &res,
142 .flags = FIB_LOOKUP_NOREF,
143 };
Patrick McHardyd1db2752010-05-11 14:40:55 +0200144
Patrick Ruddye4a38c02018-10-01 09:41:27 +0100145 /* update flow if oif or iif point to device enslaved to l3mdev */
146 l3mdev_update_flow(net, flowi6_to_flowi(flp6));
147
David S. Miller4c9483b2011-03-12 16:22:43 -0500148 err = fib_rules_lookup(net->ipv6.mr6_rules_ops,
149 flowi6_to_flowi(flp6), 0, &arg);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200150 if (err < 0)
151 return err;
152 *mrt = res.mrt;
153 return 0;
154}
155
156static int ip6mr_rule_action(struct fib_rule *rule, struct flowi *flp,
157 int flags, struct fib_lookup_arg *arg)
158{
159 struct ip6mr_result *res = arg->result;
Yuval Mintzb70432f2018-02-28 23:29:32 +0200160 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200161
162 switch (rule->action) {
163 case FR_ACT_TO_TBL:
164 break;
165 case FR_ACT_UNREACHABLE:
166 return -ENETUNREACH;
167 case FR_ACT_PROHIBIT:
168 return -EACCES;
169 case FR_ACT_BLACKHOLE:
170 default:
171 return -EINVAL;
172 }
173
Patrick Ruddye4a38c02018-10-01 09:41:27 +0100174 arg->table = fib_rule_get_table(rule, arg);
175
176 mrt = ip6mr_get_table(rule->fr_net, arg->table);
Ian Morris63159f22015-03-29 14:00:04 +0100177 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200178 return -EAGAIN;
179 res->mrt = mrt;
180 return 0;
181}
182
183static int ip6mr_rule_match(struct fib_rule *rule, struct flowi *flp, int flags)
184{
185 return 1;
186}
187
188static const struct nla_policy ip6mr_rule_policy[FRA_MAX + 1] = {
189 FRA_GENERIC_POLICY,
190};
191
192static int ip6mr_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
Roopa Prabhub16fb412018-04-21 09:41:31 -0700193 struct fib_rule_hdr *frh, struct nlattr **tb,
194 struct netlink_ext_ack *extack)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200195{
196 return 0;
197}
198
199static int ip6mr_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
200 struct nlattr **tb)
201{
202 return 1;
203}
204
205static int ip6mr_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
206 struct fib_rule_hdr *frh)
207{
208 frh->dst_len = 0;
209 frh->src_len = 0;
210 frh->tos = 0;
211 return 0;
212}
213
Andi Kleen04a6f822012-10-04 17:12:11 -0700214static const struct fib_rules_ops __net_initconst ip6mr_rules_ops_template = {
Patrick McHardyd1db2752010-05-11 14:40:55 +0200215 .family = RTNL_FAMILY_IP6MR,
216 .rule_size = sizeof(struct ip6mr_rule),
217 .addr_size = sizeof(struct in6_addr),
218 .action = ip6mr_rule_action,
219 .match = ip6mr_rule_match,
220 .configure = ip6mr_rule_configure,
221 .compare = ip6mr_rule_compare,
Patrick McHardyd1db2752010-05-11 14:40:55 +0200222 .fill = ip6mr_rule_fill,
223 .nlgroup = RTNLGRP_IPV6_RULE,
224 .policy = ip6mr_rule_policy,
225 .owner = THIS_MODULE,
226};
227
228static int __net_init ip6mr_rules_init(struct net *net)
229{
230 struct fib_rules_ops *ops;
Yuval Mintzb70432f2018-02-28 23:29:32 +0200231 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200232 int err;
233
234 ops = fib_rules_register(&ip6mr_rules_ops_template, net);
235 if (IS_ERR(ops))
236 return PTR_ERR(ops);
237
238 INIT_LIST_HEAD(&net->ipv6.mr6_tables);
239
240 mrt = ip6mr_new_table(net, RT6_TABLE_DFLT);
Sabrina Dubrocae783bb02018-06-05 15:02:00 +0200241 if (IS_ERR(mrt)) {
242 err = PTR_ERR(mrt);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200243 goto err1;
244 }
245
246 err = fib_default_rule_add(ops, 0x7fff, RT6_TABLE_DFLT, 0);
247 if (err < 0)
248 goto err2;
249
250 net->ipv6.mr6_rules_ops = ops;
251 return 0;
252
253err2:
WANG Congf243e5a2015-03-25 14:45:03 -0700254 ip6mr_free_table(mrt);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200255err1:
256 fib_rules_unregister(ops);
257 return err;
258}
259
260static void __net_exit ip6mr_rules_exit(struct net *net)
261{
Yuval Mintzb70432f2018-02-28 23:29:32 +0200262 struct mr_table *mrt, *next;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200263
Hannes Frederic Sowa905a6f92013-07-22 23:45:53 +0200264 rtnl_lock();
Eric Dumazet035320d2010-06-06 23:48:40 +0000265 list_for_each_entry_safe(mrt, next, &net->ipv6.mr6_tables, list) {
266 list_del(&mrt->list);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200267 ip6mr_free_table(mrt);
Eric Dumazet035320d2010-06-06 23:48:40 +0000268 }
Patrick McHardyd1db2752010-05-11 14:40:55 +0200269 fib_rules_unregister(net->ipv6.mr6_rules_ops);
WANG Cong419df122015-03-31 11:01:46 -0700270 rtnl_unlock();
Patrick McHardyd1db2752010-05-11 14:40:55 +0200271}
Yuval Mintz088aa3e2018-03-26 15:01:34 +0300272
273static int ip6mr_rules_dump(struct net *net, struct notifier_block *nb)
274{
275 return fib_rules_dump(net, nb, RTNL_FAMILY_IP6MR);
276}
277
278static unsigned int ip6mr_rules_seq_read(struct net *net)
279{
280 return fib_rules_seq_read(net, RTNL_FAMILY_IP6MR);
281}
Yuval Mintzd3c07e52018-03-26 15:01:35 +0300282
283bool ip6mr_rule_default(const struct fib_rule *rule)
284{
285 return fib_rule_matchall(rule) && rule->action == FR_ACT_TO_TBL &&
286 rule->table == RT6_TABLE_DFLT && !rule->l3mdev;
287}
288EXPORT_SYMBOL(ip6mr_rule_default);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200289#else
290#define ip6mr_for_each_table(mrt, net) \
291 for (mrt = net->ipv6.mrt6; mrt; mrt = NULL)
292
Yuval Mintz7b0db852018-02-28 23:29:39 +0200293static struct mr_table *ip6mr_mr_table_iter(struct net *net,
294 struct mr_table *mrt)
295{
296 if (!mrt)
297 return net->ipv6.mrt6;
298 return NULL;
299}
300
Yuval Mintzb70432f2018-02-28 23:29:32 +0200301static struct mr_table *ip6mr_get_table(struct net *net, u32 id)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200302{
303 return net->ipv6.mrt6;
304}
305
David S. Miller4c9483b2011-03-12 16:22:43 -0500306static int ip6mr_fib_lookup(struct net *net, struct flowi6 *flp6,
Yuval Mintzb70432f2018-02-28 23:29:32 +0200307 struct mr_table **mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200308{
309 *mrt = net->ipv6.mrt6;
310 return 0;
311}
312
313static int __net_init ip6mr_rules_init(struct net *net)
314{
Sabrina Dubrocae783bb02018-06-05 15:02:00 +0200315 struct mr_table *mrt;
316
317 mrt = ip6mr_new_table(net, RT6_TABLE_DFLT);
318 if (IS_ERR(mrt))
319 return PTR_ERR(mrt);
320 net->ipv6.mrt6 = mrt;
321 return 0;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200322}
323
324static void __net_exit ip6mr_rules_exit(struct net *net)
325{
Hannes Frederic Sowa905a6f92013-07-22 23:45:53 +0200326 rtnl_lock();
Patrick McHardyd1db2752010-05-11 14:40:55 +0200327 ip6mr_free_table(net->ipv6.mrt6);
Hannes Frederic Sowa905a6f92013-07-22 23:45:53 +0200328 net->ipv6.mrt6 = NULL;
329 rtnl_unlock();
Patrick McHardyd1db2752010-05-11 14:40:55 +0200330}
Yuval Mintz088aa3e2018-03-26 15:01:34 +0300331
332static int ip6mr_rules_dump(struct net *net, struct notifier_block *nb)
333{
334 return 0;
335}
336
337static unsigned int ip6mr_rules_seq_read(struct net *net)
338{
339 return 0;
340}
Patrick McHardyd1db2752010-05-11 14:40:55 +0200341#endif
342
Yuval Mintz87c418b2018-02-28 23:29:31 +0200343static int ip6mr_hash_cmp(struct rhashtable_compare_arg *arg,
344 const void *ptr)
345{
346 const struct mfc6_cache_cmp_arg *cmparg = arg->key;
347 struct mfc6_cache *c = (struct mfc6_cache *)ptr;
348
349 return !ipv6_addr_equal(&c->mf6c_mcastgrp, &cmparg->mf6c_mcastgrp) ||
350 !ipv6_addr_equal(&c->mf6c_origin, &cmparg->mf6c_origin);
351}
352
353static const struct rhashtable_params ip6mr_rht_params = {
Yuval Mintz494fff52018-02-28 23:29:34 +0200354 .head_offset = offsetof(struct mr_mfc, mnode),
Yuval Mintz87c418b2018-02-28 23:29:31 +0200355 .key_offset = offsetof(struct mfc6_cache, cmparg),
356 .key_len = sizeof(struct mfc6_cache_cmp_arg),
357 .nelem_hint = 3,
Yuval Mintz87c418b2018-02-28 23:29:31 +0200358 .obj_cmpfn = ip6mr_hash_cmp,
359 .automatic_shrinking = true,
360};
361
Yuval Mintz0bbbf0e2018-02-28 23:29:33 +0200362static void ip6mr_new_table_set(struct mr_table *mrt,
363 struct net *net)
364{
365#ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
366 list_add_tail_rcu(&mrt->list, &net->ipv6.mr6_tables);
367#endif
368}
369
Yuval Mintz845c9a72018-02-28 23:29:35 +0200370static struct mfc6_cache_cmp_arg ip6mr_mr_table_ops_cmparg_any = {
371 .mf6c_origin = IN6ADDR_ANY_INIT,
372 .mf6c_mcastgrp = IN6ADDR_ANY_INIT,
373};
374
375static struct mr_table_ops ip6mr_mr_table_ops = {
376 .rht_params = &ip6mr_rht_params,
377 .cmparg_any = &ip6mr_mr_table_ops_cmparg_any,
378};
379
Yuval Mintzb70432f2018-02-28 23:29:32 +0200380static struct mr_table *ip6mr_new_table(struct net *net, u32 id)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200381{
Yuval Mintzb70432f2018-02-28 23:29:32 +0200382 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200383
384 mrt = ip6mr_get_table(net, id);
Ian Morris53b24b82015-03-29 14:00:05 +0100385 if (mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200386 return mrt;
387
Yuval Mintz845c9a72018-02-28 23:29:35 +0200388 return mr_table_alloc(net, id, &ip6mr_mr_table_ops,
Yuval Mintz0bbbf0e2018-02-28 23:29:33 +0200389 ipmr_expire_process, ip6mr_new_table_set);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200390}
391
Yuval Mintzb70432f2018-02-28 23:29:32 +0200392static void ip6mr_free_table(struct mr_table *mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200393{
WANG Cong7ba0c472015-03-31 11:01:47 -0700394 del_timer_sync(&mrt->ipmr_expire_timer);
Callum Sinclairca8d4792019-02-18 10:07:52 +1300395 mroute_clean_tables(mrt, MRT6_FLUSH_MIFS | MRT6_FLUSH_MIFS_STATIC |
396 MRT6_FLUSH_MFC | MRT6_FLUSH_MFC_STATIC);
Yuval Mintzb70432f2018-02-28 23:29:32 +0200397 rhltable_destroy(&mrt->mfc_hash);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200398 kfree(mrt);
399}
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900400
401#ifdef CONFIG_PROC_FS
Yuval Mintzc8d61962018-02-28 23:29:36 +0200402/* The /proc interfaces to multicast routing
403 * /proc/ip6_mr_cache /proc/ip6_mr_vif
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900404 */
405
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900406static void *ip6mr_vif_seq_start(struct seq_file *seq, loff_t *pos)
407 __acquires(mrt_lock)
408{
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200409 struct mr_vif_iter *iter = seq->private;
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800410 struct net *net = seq_file_net(seq);
Yuval Mintzb70432f2018-02-28 23:29:32 +0200411 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200412
413 mrt = ip6mr_get_table(net, RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +0100414 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200415 return ERR_PTR(-ENOENT);
416
417 iter->mrt = mrt;
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800418
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900419 read_lock(&mrt_lock);
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200420 return mr_vif_seq_start(seq, pos);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900421}
422
423static void ip6mr_vif_seq_stop(struct seq_file *seq, void *v)
424 __releases(mrt_lock)
425{
426 read_unlock(&mrt_lock);
427}
428
429static int ip6mr_vif_seq_show(struct seq_file *seq, void *v)
430{
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200431 struct mr_vif_iter *iter = seq->private;
Yuval Mintzb70432f2018-02-28 23:29:32 +0200432 struct mr_table *mrt = iter->mrt;
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800433
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900434 if (v == SEQ_START_TOKEN) {
435 seq_puts(seq,
436 "Interface BytesIn PktsIn BytesOut PktsOut Flags\n");
437 } else {
Yuval Mintz6853f212018-02-28 23:29:29 +0200438 const struct vif_device *vif = v;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900439 const char *name = vif->dev ? vif->dev->name : "none";
440
441 seq_printf(seq,
Al Virod430a222008-06-02 10:59:02 +0100442 "%2td %-10s %8ld %7ld %8ld %7ld %05X\n",
Yuval Mintzb70432f2018-02-28 23:29:32 +0200443 vif - mrt->vif_table,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900444 name, vif->bytes_in, vif->pkt_in,
445 vif->bytes_out, vif->pkt_out,
446 vif->flags);
447 }
448 return 0;
449}
450
Stephen Hemminger98147d52009-09-01 19:25:02 +0000451static const struct seq_operations ip6mr_vif_seq_ops = {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900452 .start = ip6mr_vif_seq_start,
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200453 .next = mr_vif_seq_next,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900454 .stop = ip6mr_vif_seq_stop,
455 .show = ip6mr_vif_seq_show,
456};
457
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900458static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos)
459{
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800460 struct net *net = seq_file_net(seq);
Yuval Mintzb70432f2018-02-28 23:29:32 +0200461 struct mr_table *mrt;
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800462
Patrick McHardyd1db2752010-05-11 14:40:55 +0200463 mrt = ip6mr_get_table(net, RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +0100464 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200465 return ERR_PTR(-ENOENT);
466
Yuval Mintzc8d61962018-02-28 23:29:36 +0200467 return mr_mfc_seq_start(seq, pos, mrt, &mfc_unres_lock);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900468}
469
470static int ipmr_mfc_seq_show(struct seq_file *seq, void *v)
471{
472 int n;
473
474 if (v == SEQ_START_TOKEN) {
475 seq_puts(seq,
476 "Group "
477 "Origin "
478 "Iif Pkts Bytes Wrong Oifs\n");
479 } else {
480 const struct mfc6_cache *mfc = v;
Yuval Mintzc8d61962018-02-28 23:29:36 +0200481 const struct mr_mfc_iter *it = seq->private;
Yuval Mintzb70432f2018-02-28 23:29:32 +0200482 struct mr_table *mrt = it->mrt;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900483
Benjamin Thery999890b2008-12-03 22:22:16 -0800484 seq_printf(seq, "%pI6 %pI6 %-3hd",
Harvey Harrison0c6ce782008-10-28 16:09:23 -0700485 &mfc->mf6c_mcastgrp, &mfc->mf6c_origin,
Yuval Mintz494fff52018-02-28 23:29:34 +0200486 mfc->_c.mfc_parent);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900487
Yuval Mintzb70432f2018-02-28 23:29:32 +0200488 if (it->cache != &mrt->mfc_unres_queue) {
Benjamin Thery1ea472e2008-12-03 22:21:47 -0800489 seq_printf(seq, " %8lu %8lu %8lu",
Yuval Mintz494fff52018-02-28 23:29:34 +0200490 mfc->_c.mfc_un.res.pkt,
491 mfc->_c.mfc_un.res.bytes,
492 mfc->_c.mfc_un.res.wrong_if);
493 for (n = mfc->_c.mfc_un.res.minvif;
494 n < mfc->_c.mfc_un.res.maxvif; n++) {
Yuval Mintzb70432f2018-02-28 23:29:32 +0200495 if (VIF_EXISTS(mrt, n) &&
Yuval Mintz494fff52018-02-28 23:29:34 +0200496 mfc->_c.mfc_un.res.ttls[n] < 255)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900497 seq_printf(seq,
Yuval Mintz494fff52018-02-28 23:29:34 +0200498 " %2d:%-3d", n,
499 mfc->_c.mfc_un.res.ttls[n]);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900500 }
Benjamin Thery1ea472e2008-12-03 22:21:47 -0800501 } else {
502 /* unresolved mfc_caches don't contain
503 * pkt, bytes and wrong_if values
504 */
505 seq_printf(seq, " %8lu %8lu %8lu", 0ul, 0ul, 0ul);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900506 }
507 seq_putc(seq, '\n');
508 }
509 return 0;
510}
511
James Morris88e9d342009-09-22 16:43:43 -0700512static const struct seq_operations ipmr_mfc_seq_ops = {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900513 .start = ipmr_mfc_seq_start,
Yuval Mintzc8d61962018-02-28 23:29:36 +0200514 .next = mr_mfc_seq_next,
515 .stop = mr_mfc_seq_stop,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900516 .show = ipmr_mfc_seq_show,
517};
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900518#endif
519
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900520#ifdef CONFIG_IPV6_PIMSM_V2
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900521
522static int pim6_rcv(struct sk_buff *skb)
523{
524 struct pimreghdr *pim;
525 struct ipv6hdr *encap;
526 struct net_device *reg_dev = NULL;
Benjamin Thery8229efd2008-12-10 16:30:15 -0800527 struct net *net = dev_net(skb->dev);
Yuval Mintzb70432f2018-02-28 23:29:32 +0200528 struct mr_table *mrt;
David S. Miller4c9483b2011-03-12 16:22:43 -0500529 struct flowi6 fl6 = {
530 .flowi6_iif = skb->dev->ifindex,
531 .flowi6_mark = skb->mark,
Patrick McHardyd1db2752010-05-11 14:40:55 +0200532 };
533 int reg_vif_num;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900534
535 if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(*encap)))
536 goto drop;
537
538 pim = (struct pimreghdr *)skb_transport_header(skb);
Nikolay Aleksandrov56245ca2016-10-31 13:21:04 +0100539 if (pim->type != ((PIM_VERSION << 4) | PIM_TYPE_REGISTER) ||
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900540 (pim->flags & PIM_NULL_REGISTER) ||
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800541 (csum_ipv6_magic(&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
542 sizeof(*pim), IPPROTO_PIM,
543 csum_partial((void *)pim, sizeof(*pim), 0)) &&
Al Viroec6b4862008-04-26 22:28:58 -0700544 csum_fold(skb_checksum(skb, 0, skb->len, 0))))
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900545 goto drop;
546
547 /* check if the inner packet is destined to mcast group */
548 encap = (struct ipv6hdr *)(skb_transport_header(skb) +
549 sizeof(*pim));
550
551 if (!ipv6_addr_is_multicast(&encap->daddr) ||
552 encap->payload_len == 0 ||
553 ntohs(encap->payload_len) + sizeof(*pim) > skb->len)
554 goto drop;
555
David S. Miller4c9483b2011-03-12 16:22:43 -0500556 if (ip6mr_fib_lookup(net, &fl6, &mrt) < 0)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200557 goto drop;
558 reg_vif_num = mrt->mroute_reg_vif_num;
559
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900560 read_lock(&mrt_lock);
561 if (reg_vif_num >= 0)
Yuval Mintzb70432f2018-02-28 23:29:32 +0200562 reg_dev = mrt->vif_table[reg_vif_num].dev;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900563 if (reg_dev)
564 dev_hold(reg_dev);
565 read_unlock(&mrt_lock);
566
Ian Morris63159f22015-03-29 14:00:04 +0100567 if (!reg_dev)
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900568 goto drop;
569
570 skb->mac_header = skb->network_header;
571 skb_pull(skb, (u8 *)encap - skb->data);
572 skb_reset_network_header(skb);
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800573 skb->protocol = htons(ETH_P_IPV6);
Cesar Eduardo Barros3e49e6d2011-03-26 05:10:30 +0000574 skb->ip_summed = CHECKSUM_NONE;
Eric Dumazetd19d56d2010-05-17 22:36:55 -0700575
Nicolas Dichtelea231922013-09-02 15:34:58 +0200576 skb_tunnel_rx(skb, reg_dev, dev_net(reg_dev));
Eric Dumazetd19d56d2010-05-17 22:36:55 -0700577
Eric Dumazetcaf586e2010-09-30 21:06:55 +0000578 netif_rx(skb);
Eric Dumazet8990f462010-09-20 00:12:11 +0000579
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900580 dev_put(reg_dev);
581 return 0;
582 drop:
583 kfree_skb(skb);
584 return 0;
585}
586
Alexey Dobriyan41135cc2009-09-14 12:22:28 +0000587static const struct inet6_protocol pim6_protocol = {
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900588 .handler = pim6_rcv,
589};
590
591/* Service routines creating virtual interfaces: PIMREG */
592
Stephen Hemminger6fef4c02009-08-31 19:50:41 +0000593static netdev_tx_t reg_vif_xmit(struct sk_buff *skb,
594 struct net_device *dev)
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900595{
Benjamin Thery8229efd2008-12-10 16:30:15 -0800596 struct net *net = dev_net(dev);
Yuval Mintzb70432f2018-02-28 23:29:32 +0200597 struct mr_table *mrt;
David S. Miller4c9483b2011-03-12 16:22:43 -0500598 struct flowi6 fl6 = {
599 .flowi6_oif = dev->ifindex,
Cong Wang6a662712014-04-15 16:25:34 -0700600 .flowi6_iif = skb->skb_iif ? : LOOPBACK_IFINDEX,
David S. Miller4c9483b2011-03-12 16:22:43 -0500601 .flowi6_mark = skb->mark,
Patrick McHardyd1db2752010-05-11 14:40:55 +0200602 };
Patrick McHardyd1db2752010-05-11 14:40:55 +0200603
Willem de Bruijncb9f1b72018-12-30 17:24:36 -0500604 if (!pskb_inet_may_pull(skb))
605 goto tx_err;
606
607 if (ip6mr_fib_lookup(net, &fl6, &mrt) < 0)
608 goto tx_err;
Benjamin Thery8229efd2008-12-10 16:30:15 -0800609
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900610 read_lock(&mrt_lock);
Pavel Emelyanovdc58c782008-05-21 14:17:54 -0700611 dev->stats.tx_bytes += skb->len;
612 dev->stats.tx_packets++;
Patrick McHardy6bd52142010-05-11 14:40:53 +0200613 ip6mr_cache_report(mrt, skb, mrt->mroute_reg_vif_num, MRT6MSG_WHOLEPKT);
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900614 read_unlock(&mrt_lock);
615 kfree_skb(skb);
Patrick McHardy6ed10652009-06-23 06:03:08 +0000616 return NETDEV_TX_OK;
Willem de Bruijncb9f1b72018-12-30 17:24:36 -0500617
618tx_err:
619 dev->stats.tx_errors++;
620 kfree_skb(skb);
621 return NETDEV_TX_OK;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900622}
623
Nicolas Dichtelee9b9592015-04-02 17:07:03 +0200624static int reg_vif_get_iflink(const struct net_device *dev)
625{
626 return 0;
627}
628
Stephen Hemminger007c3832008-11-20 20:28:35 -0800629static const struct net_device_ops reg_vif_netdev_ops = {
630 .ndo_start_xmit = reg_vif_xmit,
Nicolas Dichtelee9b9592015-04-02 17:07:03 +0200631 .ndo_get_iflink = reg_vif_get_iflink,
Stephen Hemminger007c3832008-11-20 20:28:35 -0800632};
633
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900634static void reg_vif_setup(struct net_device *dev)
635{
636 dev->type = ARPHRD_PIMREG;
637 dev->mtu = 1500 - sizeof(struct ipv6hdr) - 8;
638 dev->flags = IFF_NOARP;
Stephen Hemminger007c3832008-11-20 20:28:35 -0800639 dev->netdev_ops = &reg_vif_netdev_ops;
David S. Millercf124db2017-05-08 12:52:56 -0400640 dev->needs_free_netdev = true;
Tom Goff403dbb972009-06-14 03:16:13 -0700641 dev->features |= NETIF_F_NETNS_LOCAL;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900642}
643
Yuval Mintzb70432f2018-02-28 23:29:32 +0200644static struct net_device *ip6mr_reg_vif(struct net *net, struct mr_table *mrt)
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900645{
646 struct net_device *dev;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200647 char name[IFNAMSIZ];
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900648
Patrick McHardyd1db2752010-05-11 14:40:55 +0200649 if (mrt->id == RT6_TABLE_DFLT)
650 sprintf(name, "pim6reg");
651 else
652 sprintf(name, "pim6reg%u", mrt->id);
653
Tom Gundersenc835a672014-07-14 16:37:24 +0200654 dev = alloc_netdev(0, name, NET_NAME_UNKNOWN, reg_vif_setup);
Ian Morris63159f22015-03-29 14:00:04 +0100655 if (!dev)
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900656 return NULL;
657
Benjamin Thery8229efd2008-12-10 16:30:15 -0800658 dev_net_set(dev, net);
659
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900660 if (register_netdevice(dev)) {
661 free_netdev(dev);
662 return NULL;
663 }
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900664
Petr Machata00f54e62018-12-06 17:05:36 +0000665 if (dev_open(dev, NULL))
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900666 goto failure;
667
Wang Chen7af3db72008-07-14 20:54:54 -0700668 dev_hold(dev);
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900669 return dev;
670
671failure:
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900672 unregister_netdevice(dev);
673 return NULL;
674}
675#endif
676
Yuval Mintz088aa3e2018-03-26 15:01:34 +0300677static int call_ip6mr_vif_entry_notifiers(struct net *net,
678 enum fib_event_type event_type,
679 struct vif_device *vif,
680 mifi_t vif_index, u32 tb_id)
681{
682 return mr_call_vif_notifiers(net, RTNL_FAMILY_IP6MR, event_type,
683 vif, vif_index, tb_id,
684 &net->ipv6.ipmr_seq);
685}
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900686
Yuval Mintz088aa3e2018-03-26 15:01:34 +0300687static int call_ip6mr_mfc_entry_notifiers(struct net *net,
688 enum fib_event_type event_type,
689 struct mfc6_cache *mfc, u32 tb_id)
690{
691 return mr_call_mfc_notifiers(net, RTNL_FAMILY_IP6MR, event_type,
692 &mfc->_c, tb_id, &net->ipv6.ipmr_seq);
693}
694
695/* Delete a VIF entry */
Yuval Mintzb70432f2018-02-28 23:29:32 +0200696static int mif6_delete(struct mr_table *mrt, int vifi, int notify,
Nikolay Aleksandrov723b9292017-04-21 20:42:16 +0300697 struct list_head *head)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900698{
Yuval Mintz6853f212018-02-28 23:29:29 +0200699 struct vif_device *v;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900700 struct net_device *dev;
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800701 struct inet6_dev *in6_dev;
Patrick McHardy6bd52142010-05-11 14:40:53 +0200702
703 if (vifi < 0 || vifi >= mrt->maxvif)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900704 return -EADDRNOTAVAIL;
705
Yuval Mintzb70432f2018-02-28 23:29:32 +0200706 v = &mrt->vif_table[vifi];
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900707
Yuval Mintz088aa3e2018-03-26 15:01:34 +0300708 if (VIF_EXISTS(mrt, vifi))
709 call_ip6mr_vif_entry_notifiers(read_pnet(&mrt->net),
710 FIB_EVENT_VIF_DEL, v, vifi,
711 mrt->id);
712
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900713 write_lock_bh(&mrt_lock);
714 dev = v->dev;
715 v->dev = NULL;
716
717 if (!dev) {
718 write_unlock_bh(&mrt_lock);
719 return -EADDRNOTAVAIL;
720 }
721
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900722#ifdef CONFIG_IPV6_PIMSM_V2
Patrick McHardy6bd52142010-05-11 14:40:53 +0200723 if (vifi == mrt->mroute_reg_vif_num)
724 mrt->mroute_reg_vif_num = -1;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900725#endif
726
Patrick McHardy6bd52142010-05-11 14:40:53 +0200727 if (vifi + 1 == mrt->maxvif) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900728 int tmp;
729 for (tmp = vifi - 1; tmp >= 0; tmp--) {
Yuval Mintzb70432f2018-02-28 23:29:32 +0200730 if (VIF_EXISTS(mrt, tmp))
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900731 break;
732 }
Patrick McHardy6bd52142010-05-11 14:40:53 +0200733 mrt->maxvif = tmp + 1;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900734 }
735
736 write_unlock_bh(&mrt_lock);
737
738 dev_set_allmulti(dev, -1);
739
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800740 in6_dev = __in6_dev_get(dev);
Nicolas Dichteld67b8c62012-12-04 01:13:35 +0000741 if (in6_dev) {
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800742 in6_dev->cnf.mc_forwarding--;
David Ahern85b3daa2017-03-28 14:28:04 -0700743 inet6_netconf_notify_devconf(dev_net(dev), RTM_NEWNETCONF,
Nicolas Dichteld67b8c62012-12-04 01:13:35 +0000744 NETCONFA_MC_FORWARDING,
745 dev->ifindex, &in6_dev->cnf);
746 }
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800747
Nikolay Aleksandrov723b9292017-04-21 20:42:16 +0300748 if ((v->flags & MIFF_REGISTER) && !notify)
Eric Dumazetc871e662009-10-28 04:48:11 +0000749 unregister_netdevice_queue(dev, head);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900750
751 dev_put(dev);
752 return 0;
753}
754
Yuval Mintz87c418b2018-02-28 23:29:31 +0200755static inline void ip6mr_cache_free_rcu(struct rcu_head *head)
756{
Yuval Mintz494fff52018-02-28 23:29:34 +0200757 struct mr_mfc *c = container_of(head, struct mr_mfc, rcu);
Yuval Mintz87c418b2018-02-28 23:29:31 +0200758
Yuval Mintz494fff52018-02-28 23:29:34 +0200759 kmem_cache_free(mrt_cachep, (struct mfc6_cache *)c);
Yuval Mintz87c418b2018-02-28 23:29:31 +0200760}
761
Benjamin Thery58701ad2008-12-10 16:22:34 -0800762static inline void ip6mr_cache_free(struct mfc6_cache *c)
763{
Yuval Mintz494fff52018-02-28 23:29:34 +0200764 call_rcu(&c->_c.rcu, ip6mr_cache_free_rcu);
Benjamin Thery58701ad2008-12-10 16:22:34 -0800765}
766
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900767/* Destroy an unresolved cache entry, killing queued skbs
768 and reporting error to netlink readers.
769 */
770
Yuval Mintzb70432f2018-02-28 23:29:32 +0200771static void ip6mr_destroy_unres(struct mr_table *mrt, struct mfc6_cache *c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900772{
Patrick McHardy6bd52142010-05-11 14:40:53 +0200773 struct net *net = read_pnet(&mrt->net);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900774 struct sk_buff *skb;
775
Patrick McHardy6bd52142010-05-11 14:40:53 +0200776 atomic_dec(&mrt->cache_resolve_queue_len);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900777
Yuval Mintz494fff52018-02-28 23:29:34 +0200778 while ((skb = skb_dequeue(&c->_c.mfc_un.unres.unresolved)) != NULL) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900779 if (ipv6_hdr(skb)->version == 0) {
Johannes Bergaf728682017-06-16 14:29:22 +0200780 struct nlmsghdr *nlh = skb_pull(skb,
781 sizeof(struct ipv6hdr));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900782 nlh->nlmsg_type = NLMSG_ERROR;
Hong zhi guo573ce262013-03-27 06:47:04 +0000783 nlh->nlmsg_len = nlmsg_msg_size(sizeof(struct nlmsgerr));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900784 skb_trim(skb, nlh->nlmsg_len);
Hong zhi guo573ce262013-03-27 06:47:04 +0000785 ((struct nlmsgerr *)nlmsg_data(nlh))->error = -ETIMEDOUT;
Eric W. Biederman15e47302012-09-07 20:12:54 +0000786 rtnl_unicast(skb, net, NETLINK_CB(skb).portid);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900787 } else
788 kfree_skb(skb);
789 }
790
Benjamin Thery58701ad2008-12-10 16:22:34 -0800791 ip6mr_cache_free(c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900792}
793
794
Patrick McHardyc476efb2010-05-11 14:40:48 +0200795/* Timer process for all the unresolved queue. */
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900796
Yuval Mintzb70432f2018-02-28 23:29:32 +0200797static void ipmr_do_expire_process(struct mr_table *mrt)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900798{
799 unsigned long now = jiffies;
800 unsigned long expires = 10 * HZ;
Yuval Mintz494fff52018-02-28 23:29:34 +0200801 struct mr_mfc *c, *next;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900802
Yuval Mintzb70432f2018-02-28 23:29:32 +0200803 list_for_each_entry_safe(c, next, &mrt->mfc_unres_queue, list) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900804 if (time_after(c->mfc_un.unres.expires, now)) {
805 /* not yet... */
806 unsigned long interval = c->mfc_un.unres.expires - now;
807 if (interval < expires)
808 expires = interval;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900809 continue;
810 }
811
Patrick McHardyf30a77842010-05-11 14:40:51 +0200812 list_del(&c->list);
Yuval Mintz494fff52018-02-28 23:29:34 +0200813 mr6_netlink_event(mrt, (struct mfc6_cache *)c, RTM_DELROUTE);
814 ip6mr_destroy_unres(mrt, (struct mfc6_cache *)c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900815 }
816
Yuval Mintzb70432f2018-02-28 23:29:32 +0200817 if (!list_empty(&mrt->mfc_unres_queue))
Patrick McHardy6bd52142010-05-11 14:40:53 +0200818 mod_timer(&mrt->ipmr_expire_timer, jiffies + expires);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900819}
820
Kees Cooke99e88a2017-10-16 14:43:17 -0700821static void ipmr_expire_process(struct timer_list *t)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900822{
Yuval Mintzb70432f2018-02-28 23:29:32 +0200823 struct mr_table *mrt = from_timer(mrt, t, ipmr_expire_timer);
Patrick McHardyc476efb2010-05-11 14:40:48 +0200824
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900825 if (!spin_trylock(&mfc_unres_lock)) {
Patrick McHardy6bd52142010-05-11 14:40:53 +0200826 mod_timer(&mrt->ipmr_expire_timer, jiffies + 1);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900827 return;
828 }
829
Yuval Mintzb70432f2018-02-28 23:29:32 +0200830 if (!list_empty(&mrt->mfc_unres_queue))
Patrick McHardy6bd52142010-05-11 14:40:53 +0200831 ipmr_do_expire_process(mrt);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900832
833 spin_unlock(&mfc_unres_lock);
834}
835
836/* Fill oifs list. It is called under write locked mrt_lock. */
837
Yuval Mintzb70432f2018-02-28 23:29:32 +0200838static void ip6mr_update_thresholds(struct mr_table *mrt,
Yuval Mintz494fff52018-02-28 23:29:34 +0200839 struct mr_mfc *cache,
Patrick McHardyb5aa30b2010-05-11 14:40:50 +0200840 unsigned char *ttls)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900841{
842 int vifi;
843
Rami Rosen6ac7eb02008-04-10 12:40:10 +0300844 cache->mfc_un.res.minvif = MAXMIFS;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900845 cache->mfc_un.res.maxvif = 0;
Rami Rosen6ac7eb02008-04-10 12:40:10 +0300846 memset(cache->mfc_un.res.ttls, 255, MAXMIFS);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900847
Patrick McHardy6bd52142010-05-11 14:40:53 +0200848 for (vifi = 0; vifi < mrt->maxvif; vifi++) {
Yuval Mintzb70432f2018-02-28 23:29:32 +0200849 if (VIF_EXISTS(mrt, vifi) &&
Benjamin Thery4e168802008-12-10 16:15:08 -0800850 ttls[vifi] && ttls[vifi] < 255) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900851 cache->mfc_un.res.ttls[vifi] = ttls[vifi];
852 if (cache->mfc_un.res.minvif > vifi)
853 cache->mfc_un.res.minvif = vifi;
854 if (cache->mfc_un.res.maxvif <= vifi)
855 cache->mfc_un.res.maxvif = vifi + 1;
856 }
857 }
Nikolay Aleksandrov90b5ca12016-07-26 18:54:52 +0200858 cache->mfc_un.res.lastuse = jiffies;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900859}
860
Yuval Mintzb70432f2018-02-28 23:29:32 +0200861static int mif6_add(struct net *net, struct mr_table *mrt,
Patrick McHardy6bd52142010-05-11 14:40:53 +0200862 struct mif6ctl *vifc, int mrtsock)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900863{
864 int vifi = vifc->mif6c_mifi;
Yuval Mintzb70432f2018-02-28 23:29:32 +0200865 struct vif_device *v = &mrt->vif_table[vifi];
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900866 struct net_device *dev;
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800867 struct inet6_dev *in6_dev;
Wang Chen5ae7b442008-07-14 20:54:23 -0700868 int err;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900869
870 /* Is vif busy ? */
Yuval Mintzb70432f2018-02-28 23:29:32 +0200871 if (VIF_EXISTS(mrt, vifi))
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900872 return -EADDRINUSE;
873
874 switch (vifc->mif6c_flags) {
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900875#ifdef CONFIG_IPV6_PIMSM_V2
876 case MIFF_REGISTER:
877 /*
878 * Special Purpose VIF in PIM
879 * All the packets will be sent to the daemon
880 */
Patrick McHardy6bd52142010-05-11 14:40:53 +0200881 if (mrt->mroute_reg_vif_num >= 0)
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900882 return -EADDRINUSE;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200883 dev = ip6mr_reg_vif(net, mrt);
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900884 if (!dev)
885 return -ENOBUFS;
Wang Chen5ae7b442008-07-14 20:54:23 -0700886 err = dev_set_allmulti(dev, 1);
887 if (err) {
888 unregister_netdevice(dev);
Wang Chen7af3db72008-07-14 20:54:54 -0700889 dev_put(dev);
Wang Chen5ae7b442008-07-14 20:54:23 -0700890 return err;
891 }
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900892 break;
893#endif
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900894 case 0:
Benjamin Thery8229efd2008-12-10 16:30:15 -0800895 dev = dev_get_by_index(net, vifc->mif6c_pifi);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900896 if (!dev)
897 return -EADDRNOTAVAIL;
Wang Chen5ae7b442008-07-14 20:54:23 -0700898 err = dev_set_allmulti(dev, 1);
Wang Chen7af3db72008-07-14 20:54:54 -0700899 if (err) {
900 dev_put(dev);
Wang Chen5ae7b442008-07-14 20:54:23 -0700901 return err;
Wang Chen7af3db72008-07-14 20:54:54 -0700902 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900903 break;
904 default:
905 return -EINVAL;
906 }
907
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800908 in6_dev = __in6_dev_get(dev);
Nicolas Dichteld67b8c62012-12-04 01:13:35 +0000909 if (in6_dev) {
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800910 in6_dev->cnf.mc_forwarding++;
David Ahern85b3daa2017-03-28 14:28:04 -0700911 inet6_netconf_notify_devconf(dev_net(dev), RTM_NEWNETCONF,
Nicolas Dichteld67b8c62012-12-04 01:13:35 +0000912 NETCONFA_MC_FORWARDING,
913 dev->ifindex, &in6_dev->cnf);
914 }
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800915
Yuval Mintz6853f212018-02-28 23:29:29 +0200916 /* Fill in the VIF structures */
917 vif_device_init(v, dev, vifc->vifc_rate_limit, vifc->vifc_threshold,
918 vifc->mif6c_flags | (!mrtsock ? VIFF_STATIC : 0),
919 MIFF_REGISTER);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900920
921 /* And finish update writing critical data */
922 write_lock_bh(&mrt_lock);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900923 v->dev = dev;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900924#ifdef CONFIG_IPV6_PIMSM_V2
925 if (v->flags & MIFF_REGISTER)
Patrick McHardy6bd52142010-05-11 14:40:53 +0200926 mrt->mroute_reg_vif_num = vifi;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900927#endif
Patrick McHardy6bd52142010-05-11 14:40:53 +0200928 if (vifi + 1 > mrt->maxvif)
929 mrt->maxvif = vifi + 1;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900930 write_unlock_bh(&mrt_lock);
Yuval Mintz088aa3e2018-03-26 15:01:34 +0300931 call_ip6mr_vif_entry_notifiers(net, FIB_EVENT_VIF_ADD,
932 v, vifi, mrt->id);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900933 return 0;
934}
935
Yuval Mintzb70432f2018-02-28 23:29:32 +0200936static struct mfc6_cache *ip6mr_cache_find(struct mr_table *mrt,
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000937 const struct in6_addr *origin,
938 const struct in6_addr *mcastgrp)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900939{
Yuval Mintz87c418b2018-02-28 23:29:31 +0200940 struct mfc6_cache_cmp_arg arg = {
941 .mf6c_origin = *origin,
942 .mf6c_mcastgrp = *mcastgrp,
943 };
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900944
Yuval Mintz845c9a72018-02-28 23:29:35 +0200945 return mr_mfc_find(mrt, &arg);
Nicolas Dichtel660b26d2013-01-21 06:00:26 +0000946}
947
948/* Look for a (*,G) entry */
Yuval Mintzb70432f2018-02-28 23:29:32 +0200949static struct mfc6_cache *ip6mr_cache_find_any(struct mr_table *mrt,
Nicolas Dichtel660b26d2013-01-21 06:00:26 +0000950 struct in6_addr *mcastgrp,
951 mifi_t mifi)
952{
Yuval Mintz87c418b2018-02-28 23:29:31 +0200953 struct mfc6_cache_cmp_arg arg = {
954 .mf6c_origin = in6addr_any,
955 .mf6c_mcastgrp = *mcastgrp,
956 };
Nicolas Dichtel660b26d2013-01-21 06:00:26 +0000957
958 if (ipv6_addr_any(mcastgrp))
Yuval Mintz845c9a72018-02-28 23:29:35 +0200959 return mr_mfc_find_any_parent(mrt, mifi);
960 return mr_mfc_find_any(mrt, mifi, &arg);
Nicolas Dichtel660b26d2013-01-21 06:00:26 +0000961}
962
Yuval Mintz87c418b2018-02-28 23:29:31 +0200963/* Look for a (S,G,iif) entry if parent != -1 */
964static struct mfc6_cache *
Yuval Mintzb70432f2018-02-28 23:29:32 +0200965ip6mr_cache_find_parent(struct mr_table *mrt,
Yuval Mintz87c418b2018-02-28 23:29:31 +0200966 const struct in6_addr *origin,
967 const struct in6_addr *mcastgrp,
968 int parent)
969{
970 struct mfc6_cache_cmp_arg arg = {
971 .mf6c_origin = *origin,
972 .mf6c_mcastgrp = *mcastgrp,
973 };
Yuval Mintz87c418b2018-02-28 23:29:31 +0200974
Yuval Mintz845c9a72018-02-28 23:29:35 +0200975 return mr_mfc_find_parent(mrt, &arg, parent);
Yuval Mintz87c418b2018-02-28 23:29:31 +0200976}
977
Yuval Mintz845c9a72018-02-28 23:29:35 +0200978/* Allocate a multicast cache entry */
Patrick McHardyb5aa30b2010-05-11 14:40:50 +0200979static struct mfc6_cache *ip6mr_cache_alloc(void)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900980{
Joe Perches36cbac52008-12-03 22:27:25 -0800981 struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL);
Ian Morris63159f22015-03-29 14:00:04 +0100982 if (!c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900983 return NULL;
Yuval Mintz494fff52018-02-28 23:29:34 +0200984 c->_c.mfc_un.res.last_assert = jiffies - MFC_ASSERT_THRESH - 1;
985 c->_c.mfc_un.res.minvif = MAXMIFS;
Yuval Mintz8c13af22018-03-26 15:01:36 +0300986 c->_c.free = ip6mr_cache_free_rcu;
987 refcount_set(&c->_c.mfc_un.res.refcount, 1);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900988 return c;
989}
990
Patrick McHardyb5aa30b2010-05-11 14:40:50 +0200991static struct mfc6_cache *ip6mr_cache_alloc_unres(void)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900992{
Joe Perches36cbac52008-12-03 22:27:25 -0800993 struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC);
Ian Morris63159f22015-03-29 14:00:04 +0100994 if (!c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900995 return NULL;
Yuval Mintz494fff52018-02-28 23:29:34 +0200996 skb_queue_head_init(&c->_c.mfc_un.unres.unresolved);
997 c->_c.mfc_un.unres.expires = jiffies + 10 * HZ;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900998 return c;
999}
1000
1001/*
1002 * A cache entry has gone into a resolved state from queued
1003 */
1004
Yuval Mintzb70432f2018-02-28 23:29:32 +02001005static void ip6mr_cache_resolve(struct net *net, struct mr_table *mrt,
Patrick McHardy6bd52142010-05-11 14:40:53 +02001006 struct mfc6_cache *uc, struct mfc6_cache *c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001007{
1008 struct sk_buff *skb;
1009
1010 /*
1011 * Play the pending entries through our router
1012 */
1013
Yuval Mintz494fff52018-02-28 23:29:34 +02001014 while ((skb = __skb_dequeue(&uc->_c.mfc_un.unres.unresolved))) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001015 if (ipv6_hdr(skb)->version == 0) {
Johannes Bergaf728682017-06-16 14:29:22 +02001016 struct nlmsghdr *nlh = skb_pull(skb,
1017 sizeof(struct ipv6hdr));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001018
Yuval Mintz7b0db852018-02-28 23:29:39 +02001019 if (mr_fill_mroute(mrt, skb, &c->_c,
1020 nlmsg_data(nlh)) > 0) {
YOSHIFUJI Hideaki549e0282008-04-05 22:17:39 +09001021 nlh->nlmsg_len = skb_tail_pointer(skb) - (u8 *)nlh;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001022 } else {
1023 nlh->nlmsg_type = NLMSG_ERROR;
Hong zhi guo573ce262013-03-27 06:47:04 +00001024 nlh->nlmsg_len = nlmsg_msg_size(sizeof(struct nlmsgerr));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001025 skb_trim(skb, nlh->nlmsg_len);
Hong zhi guo573ce262013-03-27 06:47:04 +00001026 ((struct nlmsgerr *)nlmsg_data(nlh))->error = -EMSGSIZE;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001027 }
Eric W. Biederman15e47302012-09-07 20:12:54 +00001028 rtnl_unicast(skb, net, NETLINK_CB(skb).portid);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001029 } else
Patrick Ruddye4a38c02018-10-01 09:41:27 +01001030 ip6_mr_forward(net, mrt, skb->dev, skb, c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001031 }
1032}
1033
1034/*
Julien Gomesdd12d15c2017-06-20 13:54:18 -07001035 * Bounce a cache query up to pim6sd and netlink.
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001036 *
1037 * Called under mrt_lock.
1038 */
1039
Yuval Mintzb70432f2018-02-28 23:29:32 +02001040static int ip6mr_cache_report(struct mr_table *mrt, struct sk_buff *pkt,
Patrick McHardy6bd52142010-05-11 14:40:53 +02001041 mifi_t mifi, int assert)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001042{
Yuval Mintz8571ab42018-02-28 23:29:30 +02001043 struct sock *mroute6_sk;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001044 struct sk_buff *skb;
1045 struct mrt6msg *msg;
1046 int ret;
1047
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001048#ifdef CONFIG_IPV6_PIMSM_V2
1049 if (assert == MRT6MSG_WHOLEPKT)
1050 skb = skb_realloc_headroom(pkt, -skb_network_offset(pkt)
1051 +sizeof(*msg));
1052 else
1053#endif
1054 skb = alloc_skb(sizeof(struct ipv6hdr) + sizeof(*msg), GFP_ATOMIC);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001055
1056 if (!skb)
1057 return -ENOBUFS;
1058
1059 /* I suppose that internal messages
1060 * do not require checksums */
1061
1062 skb->ip_summed = CHECKSUM_UNNECESSARY;
1063
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001064#ifdef CONFIG_IPV6_PIMSM_V2
1065 if (assert == MRT6MSG_WHOLEPKT) {
1066 /* Ugly, but we have no choice with this interface.
1067 Duplicate old header, fix length etc.
1068 And all this only to mangle msg->im6_msgtype and
1069 to set msg->im6_mbz to "mbz" :-)
1070 */
1071 skb_push(skb, -skb_network_offset(pkt));
1072
1073 skb_push(skb, sizeof(*msg));
1074 skb_reset_transport_header(skb);
1075 msg = (struct mrt6msg *)skb_transport_header(skb);
1076 msg->im6_mbz = 0;
1077 msg->im6_msgtype = MRT6MSG_WHOLEPKT;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001078 msg->im6_mif = mrt->mroute_reg_vif_num;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001079 msg->im6_pad = 0;
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +00001080 msg->im6_src = ipv6_hdr(pkt)->saddr;
1081 msg->im6_dst = ipv6_hdr(pkt)->daddr;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001082
1083 skb->ip_summed = CHECKSUM_UNNECESSARY;
1084 } else
1085#endif
1086 {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001087 /*
1088 * Copy the IP header
1089 */
1090
1091 skb_put(skb, sizeof(struct ipv6hdr));
1092 skb_reset_network_header(skb);
1093 skb_copy_to_linear_data(skb, ipv6_hdr(pkt), sizeof(struct ipv6hdr));
1094
1095 /*
1096 * Add our header
1097 */
1098 skb_put(skb, sizeof(*msg));
1099 skb_reset_transport_header(skb);
1100 msg = (struct mrt6msg *)skb_transport_header(skb);
1101
1102 msg->im6_mbz = 0;
1103 msg->im6_msgtype = assert;
Rami Rosen6ac7eb02008-04-10 12:40:10 +03001104 msg->im6_mif = mifi;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001105 msg->im6_pad = 0;
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +00001106 msg->im6_src = ipv6_hdr(pkt)->saddr;
1107 msg->im6_dst = ipv6_hdr(pkt)->daddr;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001108
Eric Dumazetadf30902009-06-02 05:19:30 +00001109 skb_dst_set(skb, dst_clone(skb_dst(pkt)));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001110 skb->ip_summed = CHECKSUM_UNNECESSARY;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001111 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001112
Yuval Mintz8571ab42018-02-28 23:29:30 +02001113 rcu_read_lock();
Yuval Mintzb70432f2018-02-28 23:29:32 +02001114 mroute6_sk = rcu_dereference(mrt->mroute_sk);
Yuval Mintz8571ab42018-02-28 23:29:30 +02001115 if (!mroute6_sk) {
1116 rcu_read_unlock();
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001117 kfree_skb(skb);
1118 return -EINVAL;
1119 }
1120
Julien Gomesdd12d15c2017-06-20 13:54:18 -07001121 mrt6msg_netlink_event(mrt, skb);
1122
Yuval Mintz8571ab42018-02-28 23:29:30 +02001123 /* Deliver to user space multicast routing algorithms */
1124 ret = sock_queue_rcv_skb(mroute6_sk, skb);
1125 rcu_read_unlock();
Benjamin Therybd91b8b2008-12-10 16:07:08 -08001126 if (ret < 0) {
Joe Perchese87cc472012-05-13 21:56:26 +00001127 net_warn_ratelimited("mroute6: pending queue full, dropping entries\n");
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001128 kfree_skb(skb);
1129 }
1130
1131 return ret;
1132}
1133
Yuval Mintz494fff52018-02-28 23:29:34 +02001134/* Queue a packet for resolution. It gets locked cache entry! */
1135static int ip6mr_cache_unresolved(struct mr_table *mrt, mifi_t mifi,
Patrick Ruddye4a38c02018-10-01 09:41:27 +01001136 struct sk_buff *skb, struct net_device *dev)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001137{
Yuval Mintz494fff52018-02-28 23:29:34 +02001138 struct mfc6_cache *c;
Patrick McHardyf30a77842010-05-11 14:40:51 +02001139 bool found = false;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001140 int err;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001141
1142 spin_lock_bh(&mfc_unres_lock);
Yuval Mintz494fff52018-02-28 23:29:34 +02001143 list_for_each_entry(c, &mrt->mfc_unres_queue, _c.list) {
Patrick McHardyc476efb2010-05-11 14:40:48 +02001144 if (ipv6_addr_equal(&c->mf6c_mcastgrp, &ipv6_hdr(skb)->daddr) &&
Patrick McHardyf30a77842010-05-11 14:40:51 +02001145 ipv6_addr_equal(&c->mf6c_origin, &ipv6_hdr(skb)->saddr)) {
1146 found = true;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001147 break;
Patrick McHardyf30a77842010-05-11 14:40:51 +02001148 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001149 }
1150
Patrick McHardyf30a77842010-05-11 14:40:51 +02001151 if (!found) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001152 /*
1153 * Create a new entry if allowable
1154 */
1155
Patrick McHardy6bd52142010-05-11 14:40:53 +02001156 if (atomic_read(&mrt->cache_resolve_queue_len) >= 10 ||
Patrick McHardyb5aa30b2010-05-11 14:40:50 +02001157 (c = ip6mr_cache_alloc_unres()) == NULL) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001158 spin_unlock_bh(&mfc_unres_lock);
1159
1160 kfree_skb(skb);
1161 return -ENOBUFS;
1162 }
1163
Yuval Mintz494fff52018-02-28 23:29:34 +02001164 /* Fill in the new cache entry */
1165 c->_c.mfc_parent = -1;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001166 c->mf6c_origin = ipv6_hdr(skb)->saddr;
1167 c->mf6c_mcastgrp = ipv6_hdr(skb)->daddr;
1168
1169 /*
1170 * Reflect first query at pim6sd
1171 */
Patrick McHardy6bd52142010-05-11 14:40:53 +02001172 err = ip6mr_cache_report(mrt, skb, mifi, MRT6MSG_NOCACHE);
Benjamin Thery8229efd2008-12-10 16:30:15 -08001173 if (err < 0) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001174 /* If the report failed throw the cache entry
1175 out - Brad Parker
1176 */
1177 spin_unlock_bh(&mfc_unres_lock);
1178
Benjamin Thery58701ad2008-12-10 16:22:34 -08001179 ip6mr_cache_free(c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001180 kfree_skb(skb);
1181 return err;
1182 }
1183
Patrick McHardy6bd52142010-05-11 14:40:53 +02001184 atomic_inc(&mrt->cache_resolve_queue_len);
Yuval Mintz494fff52018-02-28 23:29:34 +02001185 list_add(&c->_c.list, &mrt->mfc_unres_queue);
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00001186 mr6_netlink_event(mrt, c, RTM_NEWROUTE);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001187
Patrick McHardy6bd52142010-05-11 14:40:53 +02001188 ipmr_do_expire_process(mrt);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001189 }
1190
Yuval Mintz494fff52018-02-28 23:29:34 +02001191 /* See if we can append the packet */
1192 if (c->_c.mfc_un.unres.unresolved.qlen > 3) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001193 kfree_skb(skb);
1194 err = -ENOBUFS;
1195 } else {
Patrick Ruddye4a38c02018-10-01 09:41:27 +01001196 if (dev) {
1197 skb->dev = dev;
1198 skb->skb_iif = dev->ifindex;
1199 }
Yuval Mintz494fff52018-02-28 23:29:34 +02001200 skb_queue_tail(&c->_c.mfc_un.unres.unresolved, skb);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001201 err = 0;
1202 }
1203
1204 spin_unlock_bh(&mfc_unres_lock);
1205 return err;
1206}
1207
1208/*
1209 * MFC6 cache manipulation by user space
1210 */
1211
Yuval Mintzb70432f2018-02-28 23:29:32 +02001212static int ip6mr_mfc_delete(struct mr_table *mrt, struct mf6cctl *mfc,
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001213 int parent)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001214{
Yuval Mintz87c418b2018-02-28 23:29:31 +02001215 struct mfc6_cache *c;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001216
Yuval Mintz87c418b2018-02-28 23:29:31 +02001217 /* The entries are added/deleted only under RTNL */
1218 rcu_read_lock();
1219 c = ip6mr_cache_find_parent(mrt, &mfc->mf6cc_origin.sin6_addr,
1220 &mfc->mf6cc_mcastgrp.sin6_addr, parent);
1221 rcu_read_unlock();
1222 if (!c)
1223 return -ENOENT;
Yuval Mintz494fff52018-02-28 23:29:34 +02001224 rhltable_remove(&mrt->mfc_hash, &c->_c.mnode, ip6mr_rht_params);
1225 list_del_rcu(&c->_c.list);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001226
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001227 call_ip6mr_mfc_entry_notifiers(read_pnet(&mrt->net),
1228 FIB_EVENT_ENTRY_DEL, c, mrt->id);
Yuval Mintz87c418b2018-02-28 23:29:31 +02001229 mr6_netlink_event(mrt, c, RTM_DELROUTE);
Yuval Mintz8c13af22018-03-26 15:01:36 +03001230 mr_cache_put(&c->_c);
Yuval Mintz87c418b2018-02-28 23:29:31 +02001231 return 0;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001232}
1233
1234static int ip6mr_device_event(struct notifier_block *this,
1235 unsigned long event, void *ptr)
1236{
Jiri Pirko351638e2013-05-28 01:30:21 +00001237 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
Benjamin Thery8229efd2008-12-10 16:30:15 -08001238 struct net *net = dev_net(dev);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001239 struct mr_table *mrt;
Yuval Mintz6853f212018-02-28 23:29:29 +02001240 struct vif_device *v;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001241 int ct;
1242
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001243 if (event != NETDEV_UNREGISTER)
1244 return NOTIFY_DONE;
1245
Patrick McHardyd1db2752010-05-11 14:40:55 +02001246 ip6mr_for_each_table(mrt, net) {
Yuval Mintzb70432f2018-02-28 23:29:32 +02001247 v = &mrt->vif_table[0];
Patrick McHardyd1db2752010-05-11 14:40:55 +02001248 for (ct = 0; ct < mrt->maxvif; ct++, v++) {
1249 if (v->dev == dev)
Nikolay Aleksandrov723b9292017-04-21 20:42:16 +03001250 mif6_delete(mrt, ct, 1, NULL);
Patrick McHardyd1db2752010-05-11 14:40:55 +02001251 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001252 }
Eric Dumazetc871e662009-10-28 04:48:11 +00001253
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001254 return NOTIFY_DONE;
1255}
1256
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001257static unsigned int ip6mr_seq_read(struct net *net)
1258{
1259 ASSERT_RTNL();
1260
1261 return net->ipv6.ipmr_seq + ip6mr_rules_seq_read(net);
1262}
1263
1264static int ip6mr_dump(struct net *net, struct notifier_block *nb)
1265{
1266 return mr_dump(net, nb, RTNL_FAMILY_IP6MR, ip6mr_rules_dump,
1267 ip6mr_mr_table_iter, &mrt_lock);
1268}
1269
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001270static struct notifier_block ip6_mr_notifier = {
1271 .notifier_call = ip6mr_device_event
1272};
1273
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001274static const struct fib_notifier_ops ip6mr_notifier_ops_template = {
1275 .family = RTNL_FAMILY_IP6MR,
1276 .fib_seq_read = ip6mr_seq_read,
1277 .fib_dump = ip6mr_dump,
1278 .owner = THIS_MODULE,
1279};
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001280
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001281static int __net_init ip6mr_notifier_init(struct net *net)
1282{
1283 struct fib_notifier_ops *ops;
1284
1285 net->ipv6.ipmr_seq = 0;
1286
1287 ops = fib_notifier_ops_register(&ip6mr_notifier_ops_template, net);
1288 if (IS_ERR(ops))
1289 return PTR_ERR(ops);
1290
1291 net->ipv6.ip6mr_notifier_ops = ops;
1292
1293 return 0;
1294}
1295
1296static void __net_exit ip6mr_notifier_exit(struct net *net)
1297{
1298 fib_notifier_ops_unregister(net->ipv6.ip6mr_notifier_ops);
1299 net->ipv6.ip6mr_notifier_ops = NULL;
1300}
1301
1302/* Setup for IP multicast routing */
Benjamin Thery4e168802008-12-10 16:15:08 -08001303static int __net_init ip6mr_net_init(struct net *net)
1304{
Patrick McHardyd1db2752010-05-11 14:40:55 +02001305 int err;
Patrick McHardyf30a77842010-05-11 14:40:51 +02001306
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001307 err = ip6mr_notifier_init(net);
1308 if (err)
1309 return err;
1310
Patrick McHardyd1db2752010-05-11 14:40:55 +02001311 err = ip6mr_rules_init(net);
1312 if (err < 0)
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001313 goto ip6mr_rules_fail;
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001314
1315#ifdef CONFIG_PROC_FS
1316 err = -ENOMEM;
Christoph Hellwigc3506372018-04-10 19:42:55 +02001317 if (!proc_create_net("ip6_mr_vif", 0, net->proc_net, &ip6mr_vif_seq_ops,
1318 sizeof(struct mr_vif_iter)))
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001319 goto proc_vif_fail;
Christoph Hellwigc3506372018-04-10 19:42:55 +02001320 if (!proc_create_net("ip6_mr_cache", 0, net->proc_net, &ipmr_mfc_seq_ops,
1321 sizeof(struct mr_mfc_iter)))
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001322 goto proc_cache_fail;
1323#endif
Patrick McHardy6bd52142010-05-11 14:40:53 +02001324
Benjamin Thery4a6258a2008-12-10 16:24:07 -08001325 return 0;
1326
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001327#ifdef CONFIG_PROC_FS
1328proc_cache_fail:
Gao fengece31ff2013-02-18 01:34:56 +00001329 remove_proc_entry("ip6_mr_vif", net->proc_net);
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001330proc_vif_fail:
Patrick McHardyd1db2752010-05-11 14:40:55 +02001331 ip6mr_rules_exit(net);
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001332#endif
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001333ip6mr_rules_fail:
1334 ip6mr_notifier_exit(net);
Benjamin Thery4e168802008-12-10 16:15:08 -08001335 return err;
1336}
1337
1338static void __net_exit ip6mr_net_exit(struct net *net)
1339{
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001340#ifdef CONFIG_PROC_FS
Gao fengece31ff2013-02-18 01:34:56 +00001341 remove_proc_entry("ip6_mr_cache", net->proc_net);
1342 remove_proc_entry("ip6_mr_vif", net->proc_net);
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001343#endif
Patrick McHardyd1db2752010-05-11 14:40:55 +02001344 ip6mr_rules_exit(net);
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001345 ip6mr_notifier_exit(net);
Benjamin Thery4e168802008-12-10 16:15:08 -08001346}
1347
1348static struct pernet_operations ip6mr_net_ops = {
1349 .init = ip6mr_net_init,
1350 .exit = ip6mr_net_exit,
1351};
1352
Wang Chen623d1a12008-07-03 12:13:30 +08001353int __init ip6_mr_init(void)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001354{
Wang Chen623d1a12008-07-03 12:13:30 +08001355 int err;
1356
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001357 mrt_cachep = kmem_cache_create("ip6_mrt_cache",
1358 sizeof(struct mfc6_cache),
1359 0, SLAB_HWCACHE_ALIGN,
1360 NULL);
1361 if (!mrt_cachep)
Wang Chen623d1a12008-07-03 12:13:30 +08001362 return -ENOMEM;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001363
Benjamin Thery4e168802008-12-10 16:15:08 -08001364 err = register_pernet_subsys(&ip6mr_net_ops);
1365 if (err)
1366 goto reg_pernet_fail;
1367
Wang Chen623d1a12008-07-03 12:13:30 +08001368 err = register_netdevice_notifier(&ip6_mr_notifier);
1369 if (err)
1370 goto reg_notif_fail;
Tom Goff403dbb972009-06-14 03:16:13 -07001371#ifdef CONFIG_IPV6_PIMSM_V2
1372 if (inet6_add_protocol(&pim6_protocol, IPPROTO_PIM) < 0) {
Joe Perchesf3213832012-05-15 14:11:53 +00001373 pr_err("%s: can't add PIM protocol\n", __func__);
Tom Goff403dbb972009-06-14 03:16:13 -07001374 err = -EAGAIN;
1375 goto add_proto_fail;
1376 }
1377#endif
Florian Westphala3fde2a2017-12-04 19:19:18 +01001378 err = rtnl_register_module(THIS_MODULE, RTNL_FAMILY_IP6MR, RTM_GETROUTE,
1379 NULL, ip6mr_rtm_dumproute, 0);
1380 if (err == 0)
1381 return 0;
1382
Tom Goff403dbb972009-06-14 03:16:13 -07001383#ifdef CONFIG_IPV6_PIMSM_V2
Florian Westphala3fde2a2017-12-04 19:19:18 +01001384 inet6_del_protocol(&pim6_protocol, IPPROTO_PIM);
Tom Goff403dbb972009-06-14 03:16:13 -07001385add_proto_fail:
1386 unregister_netdevice_notifier(&ip6_mr_notifier);
1387#endif
Benjamin Thery87b30a62008-11-10 16:34:11 -08001388reg_notif_fail:
Benjamin Thery4e168802008-12-10 16:15:08 -08001389 unregister_pernet_subsys(&ip6mr_net_ops);
1390reg_pernet_fail:
Benjamin Thery87b30a62008-11-10 16:34:11 -08001391 kmem_cache_destroy(mrt_cachep);
Wang Chen623d1a12008-07-03 12:13:30 +08001392 return err;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001393}
1394
Wang Chen623d1a12008-07-03 12:13:30 +08001395void ip6_mr_cleanup(void)
1396{
Duan Jiongffb13882014-11-19 09:35:39 +08001397 rtnl_unregister(RTNL_FAMILY_IP6MR, RTM_GETROUTE);
1398#ifdef CONFIG_IPV6_PIMSM_V2
1399 inet6_del_protocol(&pim6_protocol, IPPROTO_PIM);
1400#endif
Wang Chen623d1a12008-07-03 12:13:30 +08001401 unregister_netdevice_notifier(&ip6_mr_notifier);
Benjamin Thery4e168802008-12-10 16:15:08 -08001402 unregister_pernet_subsys(&ip6mr_net_ops);
Wang Chen623d1a12008-07-03 12:13:30 +08001403 kmem_cache_destroy(mrt_cachep);
1404}
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001405
Yuval Mintzb70432f2018-02-28 23:29:32 +02001406static int ip6mr_mfc_add(struct net *net, struct mr_table *mrt,
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001407 struct mf6cctl *mfc, int mrtsock, int parent)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001408{
Rami Rosen6ac7eb02008-04-10 12:40:10 +03001409 unsigned char ttls[MAXMIFS];
Yuval Mintz87c418b2018-02-28 23:29:31 +02001410 struct mfc6_cache *uc, *c;
Yuval Mintz494fff52018-02-28 23:29:34 +02001411 struct mr_mfc *_uc;
Yuval Mintz87c418b2018-02-28 23:29:31 +02001412 bool found;
1413 int i, err;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001414
Patrick McHardya50436f22010-03-17 06:04:14 +00001415 if (mfc->mf6cc_parent >= MAXMIFS)
1416 return -ENFILE;
1417
Rami Rosen6ac7eb02008-04-10 12:40:10 +03001418 memset(ttls, 255, MAXMIFS);
1419 for (i = 0; i < MAXMIFS; i++) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001420 if (IF_ISSET(i, &mfc->mf6cc_ifset))
1421 ttls[i] = 1;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001422 }
1423
Yuval Mintz87c418b2018-02-28 23:29:31 +02001424 /* The entries are added/deleted only under RTNL */
1425 rcu_read_lock();
1426 c = ip6mr_cache_find_parent(mrt, &mfc->mf6cc_origin.sin6_addr,
1427 &mfc->mf6cc_mcastgrp.sin6_addr, parent);
1428 rcu_read_unlock();
1429 if (c) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001430 write_lock_bh(&mrt_lock);
Yuval Mintz494fff52018-02-28 23:29:34 +02001431 c->_c.mfc_parent = mfc->mf6cc_parent;
1432 ip6mr_update_thresholds(mrt, &c->_c, ttls);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001433 if (!mrtsock)
Yuval Mintz494fff52018-02-28 23:29:34 +02001434 c->_c.mfc_flags |= MFC_STATIC;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001435 write_unlock_bh(&mrt_lock);
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001436 call_ip6mr_mfc_entry_notifiers(net, FIB_EVENT_ENTRY_REPLACE,
1437 c, mrt->id);
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00001438 mr6_netlink_event(mrt, c, RTM_NEWROUTE);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001439 return 0;
1440 }
1441
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001442 if (!ipv6_addr_any(&mfc->mf6cc_mcastgrp.sin6_addr) &&
1443 !ipv6_addr_is_multicast(&mfc->mf6cc_mcastgrp.sin6_addr))
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001444 return -EINVAL;
1445
Patrick McHardyb5aa30b2010-05-11 14:40:50 +02001446 c = ip6mr_cache_alloc();
Ian Morris63159f22015-03-29 14:00:04 +01001447 if (!c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001448 return -ENOMEM;
1449
1450 c->mf6c_origin = mfc->mf6cc_origin.sin6_addr;
1451 c->mf6c_mcastgrp = mfc->mf6cc_mcastgrp.sin6_addr;
Yuval Mintz494fff52018-02-28 23:29:34 +02001452 c->_c.mfc_parent = mfc->mf6cc_parent;
1453 ip6mr_update_thresholds(mrt, &c->_c, ttls);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001454 if (!mrtsock)
Yuval Mintz494fff52018-02-28 23:29:34 +02001455 c->_c.mfc_flags |= MFC_STATIC;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001456
Yuval Mintz494fff52018-02-28 23:29:34 +02001457 err = rhltable_insert_key(&mrt->mfc_hash, &c->cmparg, &c->_c.mnode,
Yuval Mintz87c418b2018-02-28 23:29:31 +02001458 ip6mr_rht_params);
1459 if (err) {
1460 pr_err("ip6mr: rhtable insert error %d\n", err);
1461 ip6mr_cache_free(c);
1462 return err;
1463 }
Yuval Mintz494fff52018-02-28 23:29:34 +02001464 list_add_tail_rcu(&c->_c.list, &mrt->mfc_cache_list);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001465
Yuval Mintz87c418b2018-02-28 23:29:31 +02001466 /* Check to see if we resolved a queued list. If so we
1467 * need to send on the frames and tidy up.
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001468 */
Patrick McHardyf30a77842010-05-11 14:40:51 +02001469 found = false;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001470 spin_lock_bh(&mfc_unres_lock);
Yuval Mintz494fff52018-02-28 23:29:34 +02001471 list_for_each_entry(_uc, &mrt->mfc_unres_queue, list) {
1472 uc = (struct mfc6_cache *)_uc;
Patrick McHardyc476efb2010-05-11 14:40:48 +02001473 if (ipv6_addr_equal(&uc->mf6c_origin, &c->mf6c_origin) &&
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001474 ipv6_addr_equal(&uc->mf6c_mcastgrp, &c->mf6c_mcastgrp)) {
Yuval Mintz494fff52018-02-28 23:29:34 +02001475 list_del(&_uc->list);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001476 atomic_dec(&mrt->cache_resolve_queue_len);
Patrick McHardyf30a77842010-05-11 14:40:51 +02001477 found = true;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001478 break;
1479 }
1480 }
Yuval Mintzb70432f2018-02-28 23:29:32 +02001481 if (list_empty(&mrt->mfc_unres_queue))
Patrick McHardy6bd52142010-05-11 14:40:53 +02001482 del_timer(&mrt->ipmr_expire_timer);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001483 spin_unlock_bh(&mfc_unres_lock);
1484
Patrick McHardyf30a77842010-05-11 14:40:51 +02001485 if (found) {
Patrick McHardy6bd52142010-05-11 14:40:53 +02001486 ip6mr_cache_resolve(net, mrt, uc, c);
Benjamin Thery58701ad2008-12-10 16:22:34 -08001487 ip6mr_cache_free(uc);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001488 }
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001489 call_ip6mr_mfc_entry_notifiers(net, FIB_EVENT_ENTRY_ADD,
1490 c, mrt->id);
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00001491 mr6_netlink_event(mrt, c, RTM_NEWROUTE);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001492 return 0;
1493}
1494
1495/*
1496 * Close the multicast socket, and clear the vif tables etc
1497 */
1498
Callum Sinclairca8d4792019-02-18 10:07:52 +13001499static void mroute_clean_tables(struct mr_table *mrt, int flags)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001500{
Yuval Mintz494fff52018-02-28 23:29:34 +02001501 struct mr_mfc *c, *tmp;
Eric Dumazetc871e662009-10-28 04:48:11 +00001502 LIST_HEAD(list);
Yuval Mintz87c418b2018-02-28 23:29:31 +02001503 int i;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001504
Yuval Mintz87c418b2018-02-28 23:29:31 +02001505 /* Shut down all active vif entries */
Callum Sinclairca8d4792019-02-18 10:07:52 +13001506 if (flags & (MRT6_FLUSH_MIFS | MRT6_FLUSH_MIFS_STATIC)) {
1507 for (i = 0; i < mrt->maxvif; i++) {
1508 if (((mrt->vif_table[i].flags & VIFF_STATIC) &&
1509 !(flags & MRT6_FLUSH_MIFS_STATIC)) ||
1510 (!(mrt->vif_table[i].flags & VIFF_STATIC) && !(flags & MRT6_FLUSH_MIFS)))
1511 continue;
1512 mif6_delete(mrt, i, 0, &list);
1513 }
1514 unregister_netdevice_many(&list);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001515 }
1516
Yuval Mintz87c418b2018-02-28 23:29:31 +02001517 /* Wipe the cache */
Callum Sinclairca8d4792019-02-18 10:07:52 +13001518 if (flags & (MRT6_FLUSH_MFC | MRT6_FLUSH_MFC_STATIC)) {
1519 list_for_each_entry_safe(c, tmp, &mrt->mfc_cache_list, list) {
1520 if (((c->mfc_flags & MFC_STATIC) && !(flags & MRT6_FLUSH_MFC_STATIC)) ||
1521 (!(c->mfc_flags & MFC_STATIC) && !(flags & MRT6_FLUSH_MFC)))
1522 continue;
1523 rhltable_remove(&mrt->mfc_hash, &c->mnode, ip6mr_rht_params);
1524 list_del_rcu(&c->list);
1525 call_ip6mr_mfc_entry_notifiers(read_pnet(&mrt->net),
1526 FIB_EVENT_ENTRY_DEL,
1527 (struct mfc6_cache *)c, mrt->id);
1528 mr6_netlink_event(mrt, (struct mfc6_cache *)c, RTM_DELROUTE);
1529 mr_cache_put(c);
1530 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001531 }
1532
Callum Sinclairca8d4792019-02-18 10:07:52 +13001533 if (flags & MRT6_FLUSH_MFC) {
1534 if (atomic_read(&mrt->cache_resolve_queue_len) != 0) {
1535 spin_lock_bh(&mfc_unres_lock);
1536 list_for_each_entry_safe(c, tmp, &mrt->mfc_unres_queue, list) {
1537 list_del(&c->list);
1538 mr6_netlink_event(mrt, (struct mfc6_cache *)c,
1539 RTM_DELROUTE);
1540 ip6mr_destroy_unres(mrt, (struct mfc6_cache *)c);
1541 }
1542 spin_unlock_bh(&mfc_unres_lock);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001543 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001544 }
1545}
1546
Yuval Mintzb70432f2018-02-28 23:29:32 +02001547static int ip6mr_sk_init(struct mr_table *mrt, struct sock *sk)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001548{
1549 int err = 0;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001550 struct net *net = sock_net(sk);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001551
1552 rtnl_lock();
1553 write_lock_bh(&mrt_lock);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001554 if (rtnl_dereference(mrt->mroute_sk)) {
Eric Dumazet927265b2016-07-08 05:46:04 +02001555 err = -EADDRINUSE;
Yuval Mintz8571ab42018-02-28 23:29:30 +02001556 } else {
Yuval Mintzb70432f2018-02-28 23:29:32 +02001557 rcu_assign_pointer(mrt->mroute_sk, sk);
Eric Dumazeta366e302018-03-07 08:43:19 -08001558 sock_set_flag(sk, SOCK_RCU_FREE);
Yuval Mintz8571ab42018-02-28 23:29:30 +02001559 net->ipv6.devconf_all->mc_forwarding++;
Eric Dumazet927265b2016-07-08 05:46:04 +02001560 }
1561 write_unlock_bh(&mrt_lock);
1562
1563 if (!err)
David Ahern85b3daa2017-03-28 14:28:04 -07001564 inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
1565 NETCONFA_MC_FORWARDING,
Nicolas Dichteld67b8c62012-12-04 01:13:35 +00001566 NETCONFA_IFINDEX_ALL,
1567 net->ipv6.devconf_all);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001568 rtnl_unlock();
1569
1570 return err;
1571}
1572
1573int ip6mr_sk_done(struct sock *sk)
1574{
Patrick McHardyd1db2752010-05-11 14:40:55 +02001575 int err = -EACCES;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001576 struct net *net = sock_net(sk);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001577 struct mr_table *mrt;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001578
Francesco Ruggeri338d1822017-11-08 11:23:46 -08001579 if (sk->sk_type != SOCK_RAW ||
1580 inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
1581 return err;
1582
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001583 rtnl_lock();
Patrick McHardyd1db2752010-05-11 14:40:55 +02001584 ip6mr_for_each_table(mrt, net) {
Yuval Mintzb70432f2018-02-28 23:29:32 +02001585 if (sk == rtnl_dereference(mrt->mroute_sk)) {
Patrick McHardyd1db2752010-05-11 14:40:55 +02001586 write_lock_bh(&mrt_lock);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001587 RCU_INIT_POINTER(mrt->mroute_sk, NULL);
Eric Dumazeta366e302018-03-07 08:43:19 -08001588 /* Note that mroute_sk had SOCK_RCU_FREE set,
1589 * so the RCU grace period before sk freeing
1590 * is guaranteed by sk_destruct()
1591 */
Patrick McHardyd1db2752010-05-11 14:40:55 +02001592 net->ipv6.devconf_all->mc_forwarding--;
Eric Dumazet927265b2016-07-08 05:46:04 +02001593 write_unlock_bh(&mrt_lock);
David Ahern85b3daa2017-03-28 14:28:04 -07001594 inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
Nicolas Dichteld67b8c62012-12-04 01:13:35 +00001595 NETCONFA_MC_FORWARDING,
1596 NETCONFA_IFINDEX_ALL,
1597 net->ipv6.devconf_all);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001598
Callum Sinclairca8d4792019-02-18 10:07:52 +13001599 mroute_clean_tables(mrt, MRT6_FLUSH_MIFS | MRT6_FLUSH_MFC);
Patrick McHardyd1db2752010-05-11 14:40:55 +02001600 err = 0;
1601 break;
1602 }
1603 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001604 rtnl_unlock();
1605
1606 return err;
1607}
1608
Yuval Mintz8571ab42018-02-28 23:29:30 +02001609bool mroute6_is_socket(struct net *net, struct sk_buff *skb)
Patrick McHardy6bd52142010-05-11 14:40:53 +02001610{
Yuval Mintzb70432f2018-02-28 23:29:32 +02001611 struct mr_table *mrt;
David S. Miller4c9483b2011-03-12 16:22:43 -05001612 struct flowi6 fl6 = {
Julian Anastasove374c612014-04-28 10:51:56 +03001613 .flowi6_iif = skb->skb_iif ? : LOOPBACK_IFINDEX,
David S. Miller4c9483b2011-03-12 16:22:43 -05001614 .flowi6_oif = skb->dev->ifindex,
1615 .flowi6_mark = skb->mark,
Patrick McHardyd1db2752010-05-11 14:40:55 +02001616 };
1617
David S. Miller4c9483b2011-03-12 16:22:43 -05001618 if (ip6mr_fib_lookup(net, &fl6, &mrt) < 0)
Patrick McHardyd1db2752010-05-11 14:40:55 +02001619 return NULL;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001620
Yuval Mintzb70432f2018-02-28 23:29:32 +02001621 return rcu_access_pointer(mrt->mroute_sk);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001622}
Yuval Mintz8571ab42018-02-28 23:29:30 +02001623EXPORT_SYMBOL(mroute6_is_socket);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001624
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001625/*
1626 * Socket options and virtual interface manipulation. The whole
1627 * virtual interface system is a complete heap, but unfortunately
1628 * that's how BSD mrouted happens to think. Maybe one day with a proper
1629 * MOSPF/PIM router set up we can clean this up.
1630 */
1631
David S. Millerb7058842009-09-30 16:12:20 -07001632int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsigned int optlen)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001633{
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001634 int ret, parent = 0;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001635 struct mif6ctl vif;
1636 struct mf6cctl mfc;
1637 mifi_t mifi;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001638 struct net *net = sock_net(sk);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001639 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +02001640
Xin Long99253eb2017-02-24 16:29:06 +08001641 if (sk->sk_type != SOCK_RAW ||
1642 inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
1643 return -EOPNOTSUPP;
1644
Patrick McHardyd1db2752010-05-11 14:40:55 +02001645 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +01001646 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +02001647 return -ENOENT;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001648
1649 if (optname != MRT6_INIT) {
Yuval Mintzb70432f2018-02-28 23:29:32 +02001650 if (sk != rcu_access_pointer(mrt->mroute_sk) &&
Yuval Mintz8571ab42018-02-28 23:29:30 +02001651 !ns_capable(net->user_ns, CAP_NET_ADMIN))
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001652 return -EACCES;
1653 }
1654
1655 switch (optname) {
1656 case MRT6_INIT:
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001657 if (optlen < sizeof(int))
1658 return -EINVAL;
1659
Patrick McHardy6bd52142010-05-11 14:40:53 +02001660 return ip6mr_sk_init(mrt, sk);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001661
1662 case MRT6_DONE:
1663 return ip6mr_sk_done(sk);
1664
1665 case MRT6_ADD_MIF:
1666 if (optlen < sizeof(vif))
1667 return -EINVAL;
1668 if (copy_from_user(&vif, optval, sizeof(vif)))
1669 return -EFAULT;
Rami Rosen6ac7eb02008-04-10 12:40:10 +03001670 if (vif.mif6c_mifi >= MAXMIFS)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001671 return -ENFILE;
1672 rtnl_lock();
Yuval Mintz8571ab42018-02-28 23:29:30 +02001673 ret = mif6_add(net, mrt, &vif,
Yuval Mintzb70432f2018-02-28 23:29:32 +02001674 sk == rtnl_dereference(mrt->mroute_sk));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001675 rtnl_unlock();
1676 return ret;
1677
1678 case MRT6_DEL_MIF:
1679 if (optlen < sizeof(mifi_t))
1680 return -EINVAL;
1681 if (copy_from_user(&mifi, optval, sizeof(mifi_t)))
1682 return -EFAULT;
1683 rtnl_lock();
Nikolay Aleksandrov723b9292017-04-21 20:42:16 +03001684 ret = mif6_delete(mrt, mifi, 0, NULL);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001685 rtnl_unlock();
1686 return ret;
1687
1688 /*
1689 * Manipulate the forwarding caches. These live
1690 * in a sort of kernel/user symbiosis.
1691 */
1692 case MRT6_ADD_MFC:
1693 case MRT6_DEL_MFC:
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001694 parent = -1;
Gustavo A. R. Silva275757e62017-10-16 16:36:52 -05001695 /* fall through */
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001696 case MRT6_ADD_MFC_PROXY:
1697 case MRT6_DEL_MFC_PROXY:
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001698 if (optlen < sizeof(mfc))
1699 return -EINVAL;
1700 if (copy_from_user(&mfc, optval, sizeof(mfc)))
1701 return -EFAULT;
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001702 if (parent == 0)
1703 parent = mfc.mf6cc_parent;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001704 rtnl_lock();
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001705 if (optname == MRT6_DEL_MFC || optname == MRT6_DEL_MFC_PROXY)
1706 ret = ip6mr_mfc_delete(mrt, &mfc, parent);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001707 else
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001708 ret = ip6mr_mfc_add(net, mrt, &mfc,
Yuval Mintz8571ab42018-02-28 23:29:30 +02001709 sk ==
Yuval Mintzb70432f2018-02-28 23:29:32 +02001710 rtnl_dereference(mrt->mroute_sk),
Yuval Mintz8571ab42018-02-28 23:29:30 +02001711 parent);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001712 rtnl_unlock();
1713 return ret;
1714
Callum Sinclairca8d4792019-02-18 10:07:52 +13001715 case MRT6_FLUSH:
1716 {
1717 int flags;
1718
1719 if (optlen != sizeof(flags))
1720 return -EINVAL;
1721 if (get_user(flags, (int __user *)optval))
1722 return -EFAULT;
1723 rtnl_lock();
1724 mroute_clean_tables(mrt, flags);
1725 rtnl_unlock();
1726 return 0;
1727 }
1728
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001729 /*
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001730 * Control PIM assert (to activate pim will activate assert)
1731 */
1732 case MRT6_ASSERT:
1733 {
1734 int v;
Joe Perches03f52a02012-11-25 18:26:34 +00001735
1736 if (optlen != sizeof(v))
1737 return -EINVAL;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001738 if (get_user(v, (int __user *)optval))
1739 return -EFAULT;
Joe Perches53d68412012-11-25 09:35:30 +00001740 mrt->mroute_do_assert = v;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001741 return 0;
1742 }
1743
1744#ifdef CONFIG_IPV6_PIMSM_V2
1745 case MRT6_PIM:
1746 {
YOSHIFUJI Hideakia9f83bf2008-04-10 15:41:28 +09001747 int v;
Joe Perches03f52a02012-11-25 18:26:34 +00001748
1749 if (optlen != sizeof(v))
1750 return -EINVAL;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001751 if (get_user(v, (int __user *)optval))
1752 return -EFAULT;
1753 v = !!v;
1754 rtnl_lock();
1755 ret = 0;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001756 if (v != mrt->mroute_do_pim) {
1757 mrt->mroute_do_pim = v;
1758 mrt->mroute_do_assert = v;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001759 }
1760 rtnl_unlock();
1761 return ret;
1762 }
1763
1764#endif
Patrick McHardyd1db2752010-05-11 14:40:55 +02001765#ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
1766 case MRT6_TABLE:
1767 {
1768 u32 v;
1769
1770 if (optlen != sizeof(u32))
1771 return -EINVAL;
1772 if (get_user(v, (u32 __user *)optval))
1773 return -EFAULT;
Dan Carpenter75356a82013-01-23 20:38:34 +00001774 /* "pim6reg%u" should not exceed 16 bytes (IFNAMSIZ) */
1775 if (v != RT_TABLE_DEFAULT && v >= 100000000)
1776 return -EINVAL;
Yuval Mintzb70432f2018-02-28 23:29:32 +02001777 if (sk == rcu_access_pointer(mrt->mroute_sk))
Patrick McHardyd1db2752010-05-11 14:40:55 +02001778 return -EBUSY;
1779
1780 rtnl_lock();
1781 ret = 0;
Sabrina Dubrocae783bb02018-06-05 15:02:00 +02001782 mrt = ip6mr_new_table(net, v);
1783 if (IS_ERR(mrt))
1784 ret = PTR_ERR(mrt);
Sabrina Dubroca848235e2018-06-05 15:01:59 +02001785 else
1786 raw6_sk(sk)->ip6mr_table = v;
Patrick McHardyd1db2752010-05-11 14:40:55 +02001787 rtnl_unlock();
1788 return ret;
1789 }
1790#endif
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001791 /*
Rami Rosen7d120c52008-04-23 14:35:13 +03001792 * Spurious command, or MRT6_VERSION which you cannot
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001793 * set.
1794 */
1795 default:
1796 return -ENOPROTOOPT;
1797 }
1798}
1799
1800/*
1801 * Getsock opt support for the multicast routing system.
1802 */
1803
1804int ip6_mroute_getsockopt(struct sock *sk, int optname, char __user *optval,
1805 int __user *optlen)
1806{
1807 int olr;
1808 int val;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001809 struct net *net = sock_net(sk);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001810 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +02001811
Xin Long99253eb2017-02-24 16:29:06 +08001812 if (sk->sk_type != SOCK_RAW ||
1813 inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
1814 return -EOPNOTSUPP;
1815
Patrick McHardyd1db2752010-05-11 14:40:55 +02001816 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +01001817 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +02001818 return -ENOENT;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001819
1820 switch (optname) {
1821 case MRT6_VERSION:
1822 val = 0x0305;
1823 break;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001824#ifdef CONFIG_IPV6_PIMSM_V2
1825 case MRT6_PIM:
Patrick McHardy6bd52142010-05-11 14:40:53 +02001826 val = mrt->mroute_do_pim;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001827 break;
1828#endif
1829 case MRT6_ASSERT:
Patrick McHardy6bd52142010-05-11 14:40:53 +02001830 val = mrt->mroute_do_assert;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001831 break;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001832 default:
1833 return -ENOPROTOOPT;
1834 }
1835
1836 if (get_user(olr, optlen))
1837 return -EFAULT;
1838
1839 olr = min_t(int, olr, sizeof(int));
1840 if (olr < 0)
1841 return -EINVAL;
1842
1843 if (put_user(olr, optlen))
1844 return -EFAULT;
1845 if (copy_to_user(optval, &val, olr))
1846 return -EFAULT;
1847 return 0;
1848}
1849
1850/*
1851 * The IP multicast ioctl support routines.
1852 */
1853
1854int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg)
1855{
1856 struct sioc_sg_req6 sr;
1857 struct sioc_mif_req6 vr;
Yuval Mintz6853f212018-02-28 23:29:29 +02001858 struct vif_device *vif;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001859 struct mfc6_cache *c;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001860 struct net *net = sock_net(sk);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001861 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +02001862
1863 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +01001864 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +02001865 return -ENOENT;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001866
1867 switch (cmd) {
1868 case SIOCGETMIFCNT_IN6:
1869 if (copy_from_user(&vr, arg, sizeof(vr)))
1870 return -EFAULT;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001871 if (vr.mifi >= mrt->maxvif)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001872 return -EINVAL;
Gustavo A. R. Silva69d2c862018-12-11 14:10:08 -06001873 vr.mifi = array_index_nospec(vr.mifi, mrt->maxvif);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001874 read_lock(&mrt_lock);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001875 vif = &mrt->vif_table[vr.mifi];
1876 if (VIF_EXISTS(mrt, vr.mifi)) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001877 vr.icount = vif->pkt_in;
1878 vr.ocount = vif->pkt_out;
1879 vr.ibytes = vif->bytes_in;
1880 vr.obytes = vif->bytes_out;
1881 read_unlock(&mrt_lock);
1882
1883 if (copy_to_user(arg, &vr, sizeof(vr)))
1884 return -EFAULT;
1885 return 0;
1886 }
1887 read_unlock(&mrt_lock);
1888 return -EADDRNOTAVAIL;
1889 case SIOCGETSGCNT_IN6:
1890 if (copy_from_user(&sr, arg, sizeof(sr)))
1891 return -EFAULT;
1892
Yuval Mintz87c418b2018-02-28 23:29:31 +02001893 rcu_read_lock();
Patrick McHardy6bd52142010-05-11 14:40:53 +02001894 c = ip6mr_cache_find(mrt, &sr.src.sin6_addr, &sr.grp.sin6_addr);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001895 if (c) {
Yuval Mintz494fff52018-02-28 23:29:34 +02001896 sr.pktcnt = c->_c.mfc_un.res.pkt;
1897 sr.bytecnt = c->_c.mfc_un.res.bytes;
1898 sr.wrong_if = c->_c.mfc_un.res.wrong_if;
Yuval Mintz87c418b2018-02-28 23:29:31 +02001899 rcu_read_unlock();
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001900
1901 if (copy_to_user(arg, &sr, sizeof(sr)))
1902 return -EFAULT;
1903 return 0;
1904 }
Yuval Mintz87c418b2018-02-28 23:29:31 +02001905 rcu_read_unlock();
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001906 return -EADDRNOTAVAIL;
1907 default:
1908 return -ENOIOCTLCMD;
1909 }
1910}
1911
David S. Millere2d57762011-02-03 17:59:32 -08001912#ifdef CONFIG_COMPAT
1913struct compat_sioc_sg_req6 {
1914 struct sockaddr_in6 src;
1915 struct sockaddr_in6 grp;
1916 compat_ulong_t pktcnt;
1917 compat_ulong_t bytecnt;
1918 compat_ulong_t wrong_if;
1919};
1920
1921struct compat_sioc_mif_req6 {
1922 mifi_t mifi;
1923 compat_ulong_t icount;
1924 compat_ulong_t ocount;
1925 compat_ulong_t ibytes;
1926 compat_ulong_t obytes;
1927};
1928
1929int ip6mr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg)
1930{
1931 struct compat_sioc_sg_req6 sr;
1932 struct compat_sioc_mif_req6 vr;
Yuval Mintz6853f212018-02-28 23:29:29 +02001933 struct vif_device *vif;
David S. Millere2d57762011-02-03 17:59:32 -08001934 struct mfc6_cache *c;
1935 struct net *net = sock_net(sk);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001936 struct mr_table *mrt;
David S. Millere2d57762011-02-03 17:59:32 -08001937
1938 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +01001939 if (!mrt)
David S. Millere2d57762011-02-03 17:59:32 -08001940 return -ENOENT;
1941
1942 switch (cmd) {
1943 case SIOCGETMIFCNT_IN6:
1944 if (copy_from_user(&vr, arg, sizeof(vr)))
1945 return -EFAULT;
1946 if (vr.mifi >= mrt->maxvif)
1947 return -EINVAL;
Gustavo A. R. Silva69d2c862018-12-11 14:10:08 -06001948 vr.mifi = array_index_nospec(vr.mifi, mrt->maxvif);
David S. Millere2d57762011-02-03 17:59:32 -08001949 read_lock(&mrt_lock);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001950 vif = &mrt->vif_table[vr.mifi];
1951 if (VIF_EXISTS(mrt, vr.mifi)) {
David S. Millere2d57762011-02-03 17:59:32 -08001952 vr.icount = vif->pkt_in;
1953 vr.ocount = vif->pkt_out;
1954 vr.ibytes = vif->bytes_in;
1955 vr.obytes = vif->bytes_out;
1956 read_unlock(&mrt_lock);
1957
1958 if (copy_to_user(arg, &vr, sizeof(vr)))
1959 return -EFAULT;
1960 return 0;
1961 }
1962 read_unlock(&mrt_lock);
1963 return -EADDRNOTAVAIL;
1964 case SIOCGETSGCNT_IN6:
1965 if (copy_from_user(&sr, arg, sizeof(sr)))
1966 return -EFAULT;
1967
Yuval Mintz87c418b2018-02-28 23:29:31 +02001968 rcu_read_lock();
David S. Millere2d57762011-02-03 17:59:32 -08001969 c = ip6mr_cache_find(mrt, &sr.src.sin6_addr, &sr.grp.sin6_addr);
1970 if (c) {
Yuval Mintz494fff52018-02-28 23:29:34 +02001971 sr.pktcnt = c->_c.mfc_un.res.pkt;
1972 sr.bytecnt = c->_c.mfc_un.res.bytes;
1973 sr.wrong_if = c->_c.mfc_un.res.wrong_if;
Yuval Mintz87c418b2018-02-28 23:29:31 +02001974 rcu_read_unlock();
David S. Millere2d57762011-02-03 17:59:32 -08001975
1976 if (copy_to_user(arg, &sr, sizeof(sr)))
1977 return -EFAULT;
1978 return 0;
1979 }
Yuval Mintz87c418b2018-02-28 23:29:31 +02001980 rcu_read_unlock();
David S. Millere2d57762011-02-03 17:59:32 -08001981 return -EADDRNOTAVAIL;
1982 default:
1983 return -ENOIOCTLCMD;
1984 }
1985}
1986#endif
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001987
Eric W. Biederman0c4b51f2015-09-15 20:04:18 -05001988static inline int ip6mr_forward2_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001989{
Ido Schimmel87c11f12019-03-03 07:34:57 +00001990 IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
1991 IPSTATS_MIB_OUTFORWDATAGRAMS);
1992 IP6_ADD_STATS(net, ip6_dst_idev(skb_dst(skb)),
1993 IPSTATS_MIB_OUTOCTETS, skb->len);
Eric W. Biederman13206b62015-10-07 16:48:35 -05001994 return dst_output(net, sk, skb);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001995}
1996
1997/*
1998 * Processing handlers for ip6mr_forward
1999 */
2000
Yuval Mintzb70432f2018-02-28 23:29:32 +02002001static int ip6mr_forward2(struct net *net, struct mr_table *mrt,
David Ahernf5c6dfd2018-12-17 15:36:11 -08002002 struct sk_buff *skb, int vifi)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002003{
2004 struct ipv6hdr *ipv6h;
Yuval Mintzb70432f2018-02-28 23:29:32 +02002005 struct vif_device *vif = &mrt->vif_table[vifi];
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002006 struct net_device *dev;
2007 struct dst_entry *dst;
David S. Miller4c9483b2011-03-12 16:22:43 -05002008 struct flowi6 fl6;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002009
Ian Morris63159f22015-03-29 14:00:04 +01002010 if (!vif->dev)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002011 goto out_free;
2012
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002013#ifdef CONFIG_IPV6_PIMSM_V2
2014 if (vif->flags & MIFF_REGISTER) {
2015 vif->pkt_out++;
2016 vif->bytes_out += skb->len;
Pavel Emelyanovdc58c782008-05-21 14:17:54 -07002017 vif->dev->stats.tx_bytes += skb->len;
2018 vif->dev->stats.tx_packets++;
Patrick McHardy6bd52142010-05-11 14:40:53 +02002019 ip6mr_cache_report(mrt, skb, vifi, MRT6MSG_WHOLEPKT);
Ilpo Järvinen8da73b72008-12-14 23:15:49 -08002020 goto out_free;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002021 }
2022#endif
2023
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002024 ipv6h = ipv6_hdr(skb);
2025
David S. Miller4c9483b2011-03-12 16:22:43 -05002026 fl6 = (struct flowi6) {
2027 .flowi6_oif = vif->link,
2028 .daddr = ipv6h->daddr,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002029 };
2030
David S. Miller4c9483b2011-03-12 16:22:43 -05002031 dst = ip6_route_output(net, NULL, &fl6);
RongQing.Li5095d642012-02-21 22:10:49 +00002032 if (dst->error) {
2033 dst_release(dst);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002034 goto out_free;
RongQing.Li5095d642012-02-21 22:10:49 +00002035 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002036
Eric Dumazetadf30902009-06-02 05:19:30 +00002037 skb_dst_drop(skb);
2038 skb_dst_set(skb, dst);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002039
2040 /*
2041 * RFC1584 teaches, that DVMRP/PIM router must deliver packets locally
2042 * not only before forwarding, but after forwarding on all output
2043 * interfaces. It is clear, if mrouter runs a multicasting
2044 * program, it should receive packets not depending to what interface
2045 * program is joined.
2046 * If we will not make it, the program will have to join on all
2047 * interfaces. On the other hand, multihoming host (or router, but
2048 * not mrouter) cannot join to more than one interface - it will
2049 * result in receiving multiple packets.
2050 */
2051 dev = vif->dev;
2052 skb->dev = dev;
2053 vif->pkt_out++;
2054 vif->bytes_out += skb->len;
2055
2056 /* We are about to write */
2057 /* XXX: extension headers? */
2058 if (skb_cow(skb, sizeof(*ipv6h) + LL_RESERVED_SPACE(dev)))
2059 goto out_free;
2060
2061 ipv6h = ipv6_hdr(skb);
2062 ipv6h->hop_limit--;
2063
2064 IP6CB(skb)->flags |= IP6SKB_FORWARDED;
2065
Eric W. Biederman29a26a52015-09-15 20:04:16 -05002066 return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD,
2067 net, NULL, skb, skb->dev, dev,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002068 ip6mr_forward2_finish);
2069
2070out_free:
2071 kfree_skb(skb);
2072 return 0;
2073}
2074
Yuval Mintzb70432f2018-02-28 23:29:32 +02002075static int ip6mr_find_vif(struct mr_table *mrt, struct net_device *dev)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002076{
2077 int ct;
Patrick McHardy6bd52142010-05-11 14:40:53 +02002078
2079 for (ct = mrt->maxvif - 1; ct >= 0; ct--) {
Yuval Mintzb70432f2018-02-28 23:29:32 +02002080 if (mrt->vif_table[ct].dev == dev)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002081 break;
2082 }
2083 return ct;
2084}
2085
Yuval Mintzb70432f2018-02-28 23:29:32 +02002086static void ip6_mr_forward(struct net *net, struct mr_table *mrt,
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002087 struct net_device *dev, struct sk_buff *skb,
2088 struct mfc6_cache *c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002089{
2090 int psend = -1;
2091 int vif, ct;
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002092 int true_vifi = ip6mr_find_vif(mrt, dev);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002093
Yuval Mintz494fff52018-02-28 23:29:34 +02002094 vif = c->_c.mfc_parent;
2095 c->_c.mfc_un.res.pkt++;
2096 c->_c.mfc_un.res.bytes += skb->len;
2097 c->_c.mfc_un.res.lastuse = jiffies;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002098
Yuval Mintz494fff52018-02-28 23:29:34 +02002099 if (ipv6_addr_any(&c->mf6c_origin) && true_vifi >= 0) {
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002100 struct mfc6_cache *cache_proxy;
2101
Fabian Frederick40dc2ca2014-10-29 10:00:26 +01002102 /* For an (*,G) entry, we only check that the incoming
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002103 * interface is part of the static tree.
2104 */
Yuval Mintz87c418b2018-02-28 23:29:31 +02002105 rcu_read_lock();
Yuval Mintz845c9a72018-02-28 23:29:35 +02002106 cache_proxy = mr_mfc_find_any_parent(mrt, vif);
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002107 if (cache_proxy &&
Yuval Mintz494fff52018-02-28 23:29:34 +02002108 cache_proxy->_c.mfc_un.res.ttls[true_vifi] < 255) {
Yuval Mintz87c418b2018-02-28 23:29:31 +02002109 rcu_read_unlock();
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002110 goto forward;
Yuval Mintz87c418b2018-02-28 23:29:31 +02002111 }
2112 rcu_read_unlock();
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002113 }
2114
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002115 /*
2116 * Wrong interface: drop packet and (maybe) send PIM assert.
2117 */
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002118 if (mrt->vif_table[vif].dev != dev) {
Yuval Mintz494fff52018-02-28 23:29:34 +02002119 c->_c.mfc_un.res.wrong_if++;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002120
Patrick McHardy6bd52142010-05-11 14:40:53 +02002121 if (true_vifi >= 0 && mrt->mroute_do_assert &&
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002122 /* pimsm uses asserts, when switching from RPT to SPT,
2123 so that we cannot check that packet arrived on an oif.
2124 It is bad, but otherwise we would need to move pretty
2125 large chunk of pimd to kernel. Ough... --ANK
2126 */
Patrick McHardy6bd52142010-05-11 14:40:53 +02002127 (mrt->mroute_do_pim ||
Yuval Mintz494fff52018-02-28 23:29:34 +02002128 c->_c.mfc_un.res.ttls[true_vifi] < 255) &&
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002129 time_after(jiffies,
Yuval Mintz494fff52018-02-28 23:29:34 +02002130 c->_c.mfc_un.res.last_assert +
2131 MFC_ASSERT_THRESH)) {
2132 c->_c.mfc_un.res.last_assert = jiffies;
Patrick McHardy6bd52142010-05-11 14:40:53 +02002133 ip6mr_cache_report(mrt, skb, true_vifi, MRT6MSG_WRONGMIF);
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002134 }
2135 goto dont_forward;
2136 }
2137
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002138forward:
Yuval Mintzb70432f2018-02-28 23:29:32 +02002139 mrt->vif_table[vif].pkt_in++;
2140 mrt->vif_table[vif].bytes_in += skb->len;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002141
2142 /*
2143 * Forward the frame
2144 */
Yuval Mintz494fff52018-02-28 23:29:34 +02002145 if (ipv6_addr_any(&c->mf6c_origin) &&
2146 ipv6_addr_any(&c->mf6c_mcastgrp)) {
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002147 if (true_vifi >= 0 &&
Yuval Mintz494fff52018-02-28 23:29:34 +02002148 true_vifi != c->_c.mfc_parent &&
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002149 ipv6_hdr(skb)->hop_limit >
Yuval Mintz494fff52018-02-28 23:29:34 +02002150 c->_c.mfc_un.res.ttls[c->_c.mfc_parent]) {
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002151 /* It's an (*,*) entry and the packet is not coming from
2152 * the upstream: forward the packet to the upstream
2153 * only.
2154 */
Yuval Mintz494fff52018-02-28 23:29:34 +02002155 psend = c->_c.mfc_parent;
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002156 goto last_forward;
2157 }
2158 goto dont_forward;
2159 }
Yuval Mintz494fff52018-02-28 23:29:34 +02002160 for (ct = c->_c.mfc_un.res.maxvif - 1;
2161 ct >= c->_c.mfc_un.res.minvif; ct--) {
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002162 /* For (*,G) entry, don't forward to the incoming interface */
Yuval Mintz494fff52018-02-28 23:29:34 +02002163 if ((!ipv6_addr_any(&c->mf6c_origin) || ct != true_vifi) &&
2164 ipv6_hdr(skb)->hop_limit > c->_c.mfc_un.res.ttls[ct]) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002165 if (psend != -1) {
2166 struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
2167 if (skb2)
David Ahernf5c6dfd2018-12-17 15:36:11 -08002168 ip6mr_forward2(net, mrt, skb2, psend);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002169 }
2170 psend = ct;
2171 }
2172 }
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002173last_forward:
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002174 if (psend != -1) {
David Ahernf5c6dfd2018-12-17 15:36:11 -08002175 ip6mr_forward2(net, mrt, skb, psend);
Rami Rosen2b52c3a2013-07-21 03:00:31 +03002176 return;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002177 }
2178
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002179dont_forward:
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002180 kfree_skb(skb);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002181}
2182
2183
2184/*
2185 * Multicast packets for forwarding arrive here
2186 */
2187
2188int ip6_mr_input(struct sk_buff *skb)
2189{
2190 struct mfc6_cache *cache;
Benjamin Thery8229efd2008-12-10 16:30:15 -08002191 struct net *net = dev_net(skb->dev);
Yuval Mintzb70432f2018-02-28 23:29:32 +02002192 struct mr_table *mrt;
David S. Miller4c9483b2011-03-12 16:22:43 -05002193 struct flowi6 fl6 = {
2194 .flowi6_iif = skb->dev->ifindex,
2195 .flowi6_mark = skb->mark,
Patrick McHardyd1db2752010-05-11 14:40:55 +02002196 };
2197 int err;
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002198 struct net_device *dev;
2199
2200 /* skb->dev passed in is the master dev for vrfs.
2201 * Get the proper interface that does have a vif associated with it.
2202 */
2203 dev = skb->dev;
2204 if (netif_is_l3_master(skb->dev)) {
2205 dev = dev_get_by_index_rcu(net, IPCB(skb)->iif);
2206 if (!dev) {
2207 kfree_skb(skb);
2208 return -ENODEV;
2209 }
2210 }
Patrick McHardyd1db2752010-05-11 14:40:55 +02002211
David S. Miller4c9483b2011-03-12 16:22:43 -05002212 err = ip6mr_fib_lookup(net, &fl6, &mrt);
Ben Greear2015de52011-09-27 15:16:08 -04002213 if (err < 0) {
2214 kfree_skb(skb);
Patrick McHardyd1db2752010-05-11 14:40:55 +02002215 return err;
Ben Greear2015de52011-09-27 15:16:08 -04002216 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002217
2218 read_lock(&mrt_lock);
Patrick McHardy6bd52142010-05-11 14:40:53 +02002219 cache = ip6mr_cache_find(mrt,
Benjamin Thery8229efd2008-12-10 16:30:15 -08002220 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr);
Ian Morris63159f22015-03-29 14:00:04 +01002221 if (!cache) {
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002222 int vif = ip6mr_find_vif(mrt, dev);
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002223
2224 if (vif >= 0)
2225 cache = ip6mr_cache_find_any(mrt,
2226 &ipv6_hdr(skb)->daddr,
2227 vif);
2228 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002229
2230 /*
2231 * No usable cache entry
2232 */
Ian Morris63159f22015-03-29 14:00:04 +01002233 if (!cache) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002234 int vif;
2235
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002236 vif = ip6mr_find_vif(mrt, dev);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002237 if (vif >= 0) {
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002238 int err = ip6mr_cache_unresolved(mrt, vif, skb, dev);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002239 read_unlock(&mrt_lock);
2240
2241 return err;
2242 }
2243 read_unlock(&mrt_lock);
2244 kfree_skb(skb);
2245 return -ENODEV;
2246 }
2247
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002248 ip6_mr_forward(net, mrt, dev, skb, cache);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002249
2250 read_unlock(&mrt_lock);
2251
2252 return 0;
2253}
2254
Nikolay Aleksandrov2cf75072016-09-25 23:08:31 +02002255int ip6mr_get_route(struct net *net, struct sk_buff *skb, struct rtmsg *rtm,
David Ahernfd61c6b2017-01-17 15:51:07 -08002256 u32 portid)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002257{
2258 int err;
Yuval Mintzb70432f2018-02-28 23:29:32 +02002259 struct mr_table *mrt;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002260 struct mfc6_cache *cache;
Eric Dumazetadf30902009-06-02 05:19:30 +00002261 struct rt6_info *rt = (struct rt6_info *)skb_dst(skb);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002262
Patrick McHardyd1db2752010-05-11 14:40:55 +02002263 mrt = ip6mr_get_table(net, RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +01002264 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +02002265 return -ENOENT;
2266
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002267 read_lock(&mrt_lock);
Patrick McHardy6bd52142010-05-11 14:40:53 +02002268 cache = ip6mr_cache_find(mrt, &rt->rt6i_src.addr, &rt->rt6i_dst.addr);
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002269 if (!cache && skb->dev) {
2270 int vif = ip6mr_find_vif(mrt, skb->dev);
2271
2272 if (vif >= 0)
2273 cache = ip6mr_cache_find_any(mrt, &rt->rt6i_dst.addr,
2274 vif);
2275 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002276
2277 if (!cache) {
2278 struct sk_buff *skb2;
2279 struct ipv6hdr *iph;
2280 struct net_device *dev;
2281 int vif;
2282
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002283 dev = skb->dev;
Ian Morris63159f22015-03-29 14:00:04 +01002284 if (!dev || (vif = ip6mr_find_vif(mrt, dev)) < 0) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002285 read_unlock(&mrt_lock);
2286 return -ENODEV;
2287 }
2288
2289 /* really correct? */
2290 skb2 = alloc_skb(sizeof(struct ipv6hdr), GFP_ATOMIC);
2291 if (!skb2) {
2292 read_unlock(&mrt_lock);
2293 return -ENOMEM;
2294 }
2295
Nikolay Aleksandrov2cf75072016-09-25 23:08:31 +02002296 NETLINK_CB(skb2).portid = portid;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002297 skb_reset_transport_header(skb2);
2298
2299 skb_put(skb2, sizeof(struct ipv6hdr));
2300 skb_reset_network_header(skb2);
2301
2302 iph = ipv6_hdr(skb2);
2303 iph->version = 0;
2304 iph->priority = 0;
2305 iph->flow_lbl[0] = 0;
2306 iph->flow_lbl[1] = 0;
2307 iph->flow_lbl[2] = 0;
2308 iph->payload_len = 0;
2309 iph->nexthdr = IPPROTO_NONE;
2310 iph->hop_limit = 0;
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +00002311 iph->saddr = rt->rt6i_src.addr;
2312 iph->daddr = rt->rt6i_dst.addr;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002313
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002314 err = ip6mr_cache_unresolved(mrt, vif, skb2, dev);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002315 read_unlock(&mrt_lock);
2316
2317 return err;
2318 }
2319
Yuval Mintz7b0db852018-02-28 23:29:39 +02002320 err = mr_fill_mroute(mrt, skb, &cache->_c, rtm);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002321 read_unlock(&mrt_lock);
2322 return err;
2323}
2324
Yuval Mintzb70432f2018-02-28 23:29:32 +02002325static int ip6mr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
Nicolas Dichtelf5183382014-03-19 17:47:51 +01002326 u32 portid, u32 seq, struct mfc6_cache *c, int cmd,
2327 int flags)
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002328{
2329 struct nlmsghdr *nlh;
2330 struct rtmsg *rtm;
Nicolas Dichtel1eb99af2012-12-04 01:13:39 +00002331 int err;
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002332
Nicolas Dichtelf5183382014-03-19 17:47:51 +01002333 nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rtm), flags);
Ian Morris63159f22015-03-29 14:00:04 +01002334 if (!nlh)
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002335 return -EMSGSIZE;
2336
2337 rtm = nlmsg_data(nlh);
Nicolas Dichtel193c1e42012-12-04 01:01:49 +00002338 rtm->rtm_family = RTNL_FAMILY_IP6MR;
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002339 rtm->rtm_dst_len = 128;
2340 rtm->rtm_src_len = 128;
2341 rtm->rtm_tos = 0;
2342 rtm->rtm_table = mrt->id;
David S. Millerc78679e2012-04-01 20:27:33 -04002343 if (nla_put_u32(skb, RTA_TABLE, mrt->id))
2344 goto nla_put_failure;
Nicolas Dichtel1eb99af2012-12-04 01:13:39 +00002345 rtm->rtm_type = RTN_MULTICAST;
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002346 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
Yuval Mintz494fff52018-02-28 23:29:34 +02002347 if (c->_c.mfc_flags & MFC_STATIC)
Nicolas Dichtel9a68ac72012-12-04 01:13:38 +00002348 rtm->rtm_protocol = RTPROT_STATIC;
2349 else
2350 rtm->rtm_protocol = RTPROT_MROUTED;
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002351 rtm->rtm_flags = 0;
2352
Jiri Benc930345e2015-03-29 16:59:25 +02002353 if (nla_put_in6_addr(skb, RTA_SRC, &c->mf6c_origin) ||
2354 nla_put_in6_addr(skb, RTA_DST, &c->mf6c_mcastgrp))
David S. Millerc78679e2012-04-01 20:27:33 -04002355 goto nla_put_failure;
Yuval Mintz7b0db852018-02-28 23:29:39 +02002356 err = mr_fill_mroute(mrt, skb, &c->_c, rtm);
Nicolas Dichtel1eb99af2012-12-04 01:13:39 +00002357 /* do not break the dump if cache is unresolved */
2358 if (err < 0 && err != -ENOENT)
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002359 goto nla_put_failure;
2360
Johannes Berg053c0952015-01-16 22:09:00 +01002361 nlmsg_end(skb, nlh);
2362 return 0;
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002363
2364nla_put_failure:
2365 nlmsg_cancel(skb, nlh);
2366 return -EMSGSIZE;
2367}
2368
Yuval Mintz7b0db852018-02-28 23:29:39 +02002369static int _ip6mr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
2370 u32 portid, u32 seq, struct mr_mfc *c,
2371 int cmd, int flags)
2372{
2373 return ip6mr_fill_mroute(mrt, skb, portid, seq, (struct mfc6_cache *)c,
2374 cmd, flags);
2375}
2376
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002377static int mr6_msgsize(bool unresolved, int maxvif)
2378{
2379 size_t len =
2380 NLMSG_ALIGN(sizeof(struct rtmsg))
2381 + nla_total_size(4) /* RTA_TABLE */
2382 + nla_total_size(sizeof(struct in6_addr)) /* RTA_SRC */
2383 + nla_total_size(sizeof(struct in6_addr)) /* RTA_DST */
2384 ;
2385
2386 if (!unresolved)
2387 len = len
2388 + nla_total_size(4) /* RTA_IIF */
2389 + nla_total_size(0) /* RTA_MULTIPATH */
2390 + maxvif * NLA_ALIGN(sizeof(struct rtnexthop))
2391 /* RTA_MFC_STATS */
Nicolas Dichtel3d6b66c2016-04-21 18:58:27 +02002392 + nla_total_size_64bit(sizeof(struct rta_mfc_stats))
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002393 ;
2394
2395 return len;
2396}
2397
Yuval Mintzb70432f2018-02-28 23:29:32 +02002398static void mr6_netlink_event(struct mr_table *mrt, struct mfc6_cache *mfc,
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002399 int cmd)
2400{
2401 struct net *net = read_pnet(&mrt->net);
2402 struct sk_buff *skb;
2403 int err = -ENOBUFS;
2404
Yuval Mintz494fff52018-02-28 23:29:34 +02002405 skb = nlmsg_new(mr6_msgsize(mfc->_c.mfc_parent >= MAXMIFS, mrt->maxvif),
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002406 GFP_ATOMIC);
Ian Morris63159f22015-03-29 14:00:04 +01002407 if (!skb)
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002408 goto errout;
2409
Nicolas Dichtelf5183382014-03-19 17:47:51 +01002410 err = ip6mr_fill_mroute(mrt, skb, 0, 0, mfc, cmd, 0);
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002411 if (err < 0)
2412 goto errout;
2413
2414 rtnl_notify(skb, net, 0, RTNLGRP_IPV6_MROUTE, NULL, GFP_ATOMIC);
2415 return;
2416
2417errout:
2418 kfree_skb(skb);
2419 if (err < 0)
2420 rtnl_set_sk_err(net, RTNLGRP_IPV6_MROUTE, err);
2421}
2422
Julien Gomesdd12d15c2017-06-20 13:54:18 -07002423static size_t mrt6msg_netlink_msgsize(size_t payloadlen)
2424{
2425 size_t len =
2426 NLMSG_ALIGN(sizeof(struct rtgenmsg))
2427 + nla_total_size(1) /* IP6MRA_CREPORT_MSGTYPE */
2428 + nla_total_size(4) /* IP6MRA_CREPORT_MIF_ID */
2429 /* IP6MRA_CREPORT_SRC_ADDR */
2430 + nla_total_size(sizeof(struct in6_addr))
2431 /* IP6MRA_CREPORT_DST_ADDR */
2432 + nla_total_size(sizeof(struct in6_addr))
2433 /* IP6MRA_CREPORT_PKT */
2434 + nla_total_size(payloadlen)
2435 ;
2436
2437 return len;
2438}
2439
Yuval Mintzb70432f2018-02-28 23:29:32 +02002440static void mrt6msg_netlink_event(struct mr_table *mrt, struct sk_buff *pkt)
Julien Gomesdd12d15c2017-06-20 13:54:18 -07002441{
2442 struct net *net = read_pnet(&mrt->net);
2443 struct nlmsghdr *nlh;
2444 struct rtgenmsg *rtgenm;
2445 struct mrt6msg *msg;
2446 struct sk_buff *skb;
2447 struct nlattr *nla;
2448 int payloadlen;
2449
2450 payloadlen = pkt->len - sizeof(struct mrt6msg);
2451 msg = (struct mrt6msg *)skb_transport_header(pkt);
2452
2453 skb = nlmsg_new(mrt6msg_netlink_msgsize(payloadlen), GFP_ATOMIC);
2454 if (!skb)
2455 goto errout;
2456
2457 nlh = nlmsg_put(skb, 0, 0, RTM_NEWCACHEREPORT,
2458 sizeof(struct rtgenmsg), 0);
2459 if (!nlh)
2460 goto errout;
2461 rtgenm = nlmsg_data(nlh);
2462 rtgenm->rtgen_family = RTNL_FAMILY_IP6MR;
2463 if (nla_put_u8(skb, IP6MRA_CREPORT_MSGTYPE, msg->im6_msgtype) ||
2464 nla_put_u32(skb, IP6MRA_CREPORT_MIF_ID, msg->im6_mif) ||
2465 nla_put_in6_addr(skb, IP6MRA_CREPORT_SRC_ADDR,
2466 &msg->im6_src) ||
2467 nla_put_in6_addr(skb, IP6MRA_CREPORT_DST_ADDR,
2468 &msg->im6_dst))
2469 goto nla_put_failure;
2470
2471 nla = nla_reserve(skb, IP6MRA_CREPORT_PKT, payloadlen);
2472 if (!nla || skb_copy_bits(pkt, sizeof(struct mrt6msg),
2473 nla_data(nla), payloadlen))
2474 goto nla_put_failure;
2475
2476 nlmsg_end(skb, nlh);
2477
2478 rtnl_notify(skb, net, 0, RTNLGRP_IPV6_MROUTE_R, NULL, GFP_ATOMIC);
2479 return;
2480
2481nla_put_failure:
2482 nlmsg_cancel(skb, nlh);
2483errout:
2484 kfree_skb(skb);
2485 rtnl_set_sk_err(net, RTNLGRP_IPV6_MROUTE_R, -ENOBUFS);
2486}
2487
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002488static int ip6mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
2489{
David Aherne8ba3302018-10-07 20:16:35 -07002490 const struct nlmsghdr *nlh = cb->nlh;
David Ahern47246762018-10-15 18:56:42 -07002491 struct fib_dump_filter filter = {};
David Aherncb167892018-10-15 18:56:47 -07002492 int err;
David Aherne8ba3302018-10-07 20:16:35 -07002493
2494 if (cb->strict_check) {
David Ahern47246762018-10-15 18:56:42 -07002495 err = ip_valid_fib_dump_req(sock_net(skb->sk), nlh,
David Aherneffe6792018-10-15 18:56:48 -07002496 &filter, cb);
David Aherne8ba3302018-10-07 20:16:35 -07002497 if (err < 0)
2498 return err;
2499 }
2500
David Aherncb167892018-10-15 18:56:47 -07002501 if (filter.table_id) {
2502 struct mr_table *mrt;
2503
2504 mrt = ip6mr_get_table(sock_net(skb->sk), filter.table_id);
2505 if (!mrt) {
David Ahernae677bb2018-10-24 12:59:01 -07002506 if (filter.dump_all_families)
2507 return skb->len;
2508
David Aherncb167892018-10-15 18:56:47 -07002509 NL_SET_ERR_MSG_MOD(cb->extack, "MR table does not exist");
2510 return -ENOENT;
2511 }
2512 err = mr_table_dump(mrt, skb, cb, _ip6mr_fill_mroute,
2513 &mfc_unres_lock, &filter);
2514 return skb->len ? : err;
2515 }
2516
Yuval Mintz7b0db852018-02-28 23:29:39 +02002517 return mr_rtm_dumproute(skb, cb, ip6mr_mr_table_iter,
David Aherncb167892018-10-15 18:56:47 -07002518 _ip6mr_fill_mroute, &mfc_unres_lock, &filter);
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002519}