blob: e4dd57976737a81549861c8ff5d9e9dcb7793a8d [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,
358 .locks_mul = 1,
359 .obj_cmpfn = ip6mr_hash_cmp,
360 .automatic_shrinking = true,
361};
362
Yuval Mintz0bbbf0e2018-02-28 23:29:33 +0200363static void ip6mr_new_table_set(struct mr_table *mrt,
364 struct net *net)
365{
366#ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
367 list_add_tail_rcu(&mrt->list, &net->ipv6.mr6_tables);
368#endif
369}
370
Yuval Mintz845c9a72018-02-28 23:29:35 +0200371static struct mfc6_cache_cmp_arg ip6mr_mr_table_ops_cmparg_any = {
372 .mf6c_origin = IN6ADDR_ANY_INIT,
373 .mf6c_mcastgrp = IN6ADDR_ANY_INIT,
374};
375
376static struct mr_table_ops ip6mr_mr_table_ops = {
377 .rht_params = &ip6mr_rht_params,
378 .cmparg_any = &ip6mr_mr_table_ops_cmparg_any,
379};
380
Yuval Mintzb70432f2018-02-28 23:29:32 +0200381static struct mr_table *ip6mr_new_table(struct net *net, u32 id)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200382{
Yuval Mintzb70432f2018-02-28 23:29:32 +0200383 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200384
385 mrt = ip6mr_get_table(net, id);
Ian Morris53b24b82015-03-29 14:00:05 +0100386 if (mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200387 return mrt;
388
Yuval Mintz845c9a72018-02-28 23:29:35 +0200389 return mr_table_alloc(net, id, &ip6mr_mr_table_ops,
Yuval Mintz0bbbf0e2018-02-28 23:29:33 +0200390 ipmr_expire_process, ip6mr_new_table_set);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200391}
392
Yuval Mintzb70432f2018-02-28 23:29:32 +0200393static void ip6mr_free_table(struct mr_table *mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200394{
WANG Cong7ba0c472015-03-31 11:01:47 -0700395 del_timer_sync(&mrt->ipmr_expire_timer);
Callum Sinclairca8d4792019-02-18 10:07:52 +1300396 mroute_clean_tables(mrt, MRT6_FLUSH_MIFS | MRT6_FLUSH_MIFS_STATIC |
397 MRT6_FLUSH_MFC | MRT6_FLUSH_MFC_STATIC);
Yuval Mintzb70432f2018-02-28 23:29:32 +0200398 rhltable_destroy(&mrt->mfc_hash);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200399 kfree(mrt);
400}
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900401
402#ifdef CONFIG_PROC_FS
Yuval Mintzc8d61962018-02-28 23:29:36 +0200403/* The /proc interfaces to multicast routing
404 * /proc/ip6_mr_cache /proc/ip6_mr_vif
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900405 */
406
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900407static void *ip6mr_vif_seq_start(struct seq_file *seq, loff_t *pos)
408 __acquires(mrt_lock)
409{
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200410 struct mr_vif_iter *iter = seq->private;
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800411 struct net *net = seq_file_net(seq);
Yuval Mintzb70432f2018-02-28 23:29:32 +0200412 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200413
414 mrt = ip6mr_get_table(net, RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +0100415 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200416 return ERR_PTR(-ENOENT);
417
418 iter->mrt = mrt;
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800419
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900420 read_lock(&mrt_lock);
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200421 return mr_vif_seq_start(seq, pos);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900422}
423
424static void ip6mr_vif_seq_stop(struct seq_file *seq, void *v)
425 __releases(mrt_lock)
426{
427 read_unlock(&mrt_lock);
428}
429
430static int ip6mr_vif_seq_show(struct seq_file *seq, void *v)
431{
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200432 struct mr_vif_iter *iter = seq->private;
Yuval Mintzb70432f2018-02-28 23:29:32 +0200433 struct mr_table *mrt = iter->mrt;
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800434
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900435 if (v == SEQ_START_TOKEN) {
436 seq_puts(seq,
437 "Interface BytesIn PktsIn BytesOut PktsOut Flags\n");
438 } else {
Yuval Mintz6853f212018-02-28 23:29:29 +0200439 const struct vif_device *vif = v;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900440 const char *name = vif->dev ? vif->dev->name : "none";
441
442 seq_printf(seq,
Al Virod430a222008-06-02 10:59:02 +0100443 "%2td %-10s %8ld %7ld %8ld %7ld %05X\n",
Yuval Mintzb70432f2018-02-28 23:29:32 +0200444 vif - mrt->vif_table,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900445 name, vif->bytes_in, vif->pkt_in,
446 vif->bytes_out, vif->pkt_out,
447 vif->flags);
448 }
449 return 0;
450}
451
Stephen Hemminger98147d52009-09-01 19:25:02 +0000452static const struct seq_operations ip6mr_vif_seq_ops = {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900453 .start = ip6mr_vif_seq_start,
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200454 .next = mr_vif_seq_next,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900455 .stop = ip6mr_vif_seq_stop,
456 .show = ip6mr_vif_seq_show,
457};
458
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900459static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos)
460{
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800461 struct net *net = seq_file_net(seq);
Yuval Mintzb70432f2018-02-28 23:29:32 +0200462 struct mr_table *mrt;
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800463
Patrick McHardyd1db2752010-05-11 14:40:55 +0200464 mrt = ip6mr_get_table(net, RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +0100465 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200466 return ERR_PTR(-ENOENT);
467
Yuval Mintzc8d61962018-02-28 23:29:36 +0200468 return mr_mfc_seq_start(seq, pos, mrt, &mfc_unres_lock);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900469}
470
471static int ipmr_mfc_seq_show(struct seq_file *seq, void *v)
472{
473 int n;
474
475 if (v == SEQ_START_TOKEN) {
476 seq_puts(seq,
477 "Group "
478 "Origin "
479 "Iif Pkts Bytes Wrong Oifs\n");
480 } else {
481 const struct mfc6_cache *mfc = v;
Yuval Mintzc8d61962018-02-28 23:29:36 +0200482 const struct mr_mfc_iter *it = seq->private;
Yuval Mintzb70432f2018-02-28 23:29:32 +0200483 struct mr_table *mrt = it->mrt;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900484
Benjamin Thery999890b2008-12-03 22:22:16 -0800485 seq_printf(seq, "%pI6 %pI6 %-3hd",
Harvey Harrison0c6ce782008-10-28 16:09:23 -0700486 &mfc->mf6c_mcastgrp, &mfc->mf6c_origin,
Yuval Mintz494fff52018-02-28 23:29:34 +0200487 mfc->_c.mfc_parent);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900488
Yuval Mintzb70432f2018-02-28 23:29:32 +0200489 if (it->cache != &mrt->mfc_unres_queue) {
Benjamin Thery1ea472e2008-12-03 22:21:47 -0800490 seq_printf(seq, " %8lu %8lu %8lu",
Yuval Mintz494fff52018-02-28 23:29:34 +0200491 mfc->_c.mfc_un.res.pkt,
492 mfc->_c.mfc_un.res.bytes,
493 mfc->_c.mfc_un.res.wrong_if);
494 for (n = mfc->_c.mfc_un.res.minvif;
495 n < mfc->_c.mfc_un.res.maxvif; n++) {
Yuval Mintzb70432f2018-02-28 23:29:32 +0200496 if (VIF_EXISTS(mrt, n) &&
Yuval Mintz494fff52018-02-28 23:29:34 +0200497 mfc->_c.mfc_un.res.ttls[n] < 255)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900498 seq_printf(seq,
Yuval Mintz494fff52018-02-28 23:29:34 +0200499 " %2d:%-3d", n,
500 mfc->_c.mfc_un.res.ttls[n]);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900501 }
Benjamin Thery1ea472e2008-12-03 22:21:47 -0800502 } else {
503 /* unresolved mfc_caches don't contain
504 * pkt, bytes and wrong_if values
505 */
506 seq_printf(seq, " %8lu %8lu %8lu", 0ul, 0ul, 0ul);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900507 }
508 seq_putc(seq, '\n');
509 }
510 return 0;
511}
512
James Morris88e9d342009-09-22 16:43:43 -0700513static const struct seq_operations ipmr_mfc_seq_ops = {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900514 .start = ipmr_mfc_seq_start,
Yuval Mintzc8d61962018-02-28 23:29:36 +0200515 .next = mr_mfc_seq_next,
516 .stop = mr_mfc_seq_stop,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900517 .show = ipmr_mfc_seq_show,
518};
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900519#endif
520
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900521#ifdef CONFIG_IPV6_PIMSM_V2
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900522
523static int pim6_rcv(struct sk_buff *skb)
524{
525 struct pimreghdr *pim;
526 struct ipv6hdr *encap;
527 struct net_device *reg_dev = NULL;
Benjamin Thery8229efd2008-12-10 16:30:15 -0800528 struct net *net = dev_net(skb->dev);
Yuval Mintzb70432f2018-02-28 23:29:32 +0200529 struct mr_table *mrt;
David S. Miller4c9483b2011-03-12 16:22:43 -0500530 struct flowi6 fl6 = {
531 .flowi6_iif = skb->dev->ifindex,
532 .flowi6_mark = skb->mark,
Patrick McHardyd1db2752010-05-11 14:40:55 +0200533 };
534 int reg_vif_num;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900535
536 if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(*encap)))
537 goto drop;
538
539 pim = (struct pimreghdr *)skb_transport_header(skb);
Nikolay Aleksandrov56245ca2016-10-31 13:21:04 +0100540 if (pim->type != ((PIM_VERSION << 4) | PIM_TYPE_REGISTER) ||
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900541 (pim->flags & PIM_NULL_REGISTER) ||
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800542 (csum_ipv6_magic(&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
543 sizeof(*pim), IPPROTO_PIM,
544 csum_partial((void *)pim, sizeof(*pim), 0)) &&
Al Viroec6b4862008-04-26 22:28:58 -0700545 csum_fold(skb_checksum(skb, 0, skb->len, 0))))
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900546 goto drop;
547
548 /* check if the inner packet is destined to mcast group */
549 encap = (struct ipv6hdr *)(skb_transport_header(skb) +
550 sizeof(*pim));
551
552 if (!ipv6_addr_is_multicast(&encap->daddr) ||
553 encap->payload_len == 0 ||
554 ntohs(encap->payload_len) + sizeof(*pim) > skb->len)
555 goto drop;
556
David S. Miller4c9483b2011-03-12 16:22:43 -0500557 if (ip6mr_fib_lookup(net, &fl6, &mrt) < 0)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200558 goto drop;
559 reg_vif_num = mrt->mroute_reg_vif_num;
560
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900561 read_lock(&mrt_lock);
562 if (reg_vif_num >= 0)
Yuval Mintzb70432f2018-02-28 23:29:32 +0200563 reg_dev = mrt->vif_table[reg_vif_num].dev;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900564 if (reg_dev)
565 dev_hold(reg_dev);
566 read_unlock(&mrt_lock);
567
Ian Morris63159f22015-03-29 14:00:04 +0100568 if (!reg_dev)
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900569 goto drop;
570
571 skb->mac_header = skb->network_header;
572 skb_pull(skb, (u8 *)encap - skb->data);
573 skb_reset_network_header(skb);
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800574 skb->protocol = htons(ETH_P_IPV6);
Cesar Eduardo Barros3e49e6d2011-03-26 05:10:30 +0000575 skb->ip_summed = CHECKSUM_NONE;
Eric Dumazetd19d56d2010-05-17 22:36:55 -0700576
Nicolas Dichtelea231922013-09-02 15:34:58 +0200577 skb_tunnel_rx(skb, reg_dev, dev_net(reg_dev));
Eric Dumazetd19d56d2010-05-17 22:36:55 -0700578
Eric Dumazetcaf586e2010-09-30 21:06:55 +0000579 netif_rx(skb);
Eric Dumazet8990f462010-09-20 00:12:11 +0000580
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900581 dev_put(reg_dev);
582 return 0;
583 drop:
584 kfree_skb(skb);
585 return 0;
586}
587
Alexey Dobriyan41135cc2009-09-14 12:22:28 +0000588static const struct inet6_protocol pim6_protocol = {
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900589 .handler = pim6_rcv,
590};
591
592/* Service routines creating virtual interfaces: PIMREG */
593
Stephen Hemminger6fef4c02009-08-31 19:50:41 +0000594static netdev_tx_t reg_vif_xmit(struct sk_buff *skb,
595 struct net_device *dev)
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900596{
Benjamin Thery8229efd2008-12-10 16:30:15 -0800597 struct net *net = dev_net(dev);
Yuval Mintzb70432f2018-02-28 23:29:32 +0200598 struct mr_table *mrt;
David S. Miller4c9483b2011-03-12 16:22:43 -0500599 struct flowi6 fl6 = {
600 .flowi6_oif = dev->ifindex,
Cong Wang6a662712014-04-15 16:25:34 -0700601 .flowi6_iif = skb->skb_iif ? : LOOPBACK_IFINDEX,
David S. Miller4c9483b2011-03-12 16:22:43 -0500602 .flowi6_mark = skb->mark,
Patrick McHardyd1db2752010-05-11 14:40:55 +0200603 };
Patrick McHardyd1db2752010-05-11 14:40:55 +0200604
Willem de Bruijncb9f1b72018-12-30 17:24:36 -0500605 if (!pskb_inet_may_pull(skb))
606 goto tx_err;
607
608 if (ip6mr_fib_lookup(net, &fl6, &mrt) < 0)
609 goto tx_err;
Benjamin Thery8229efd2008-12-10 16:30:15 -0800610
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900611 read_lock(&mrt_lock);
Pavel Emelyanovdc58c782008-05-21 14:17:54 -0700612 dev->stats.tx_bytes += skb->len;
613 dev->stats.tx_packets++;
Patrick McHardy6bd52142010-05-11 14:40:53 +0200614 ip6mr_cache_report(mrt, skb, mrt->mroute_reg_vif_num, MRT6MSG_WHOLEPKT);
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900615 read_unlock(&mrt_lock);
616 kfree_skb(skb);
Patrick McHardy6ed10652009-06-23 06:03:08 +0000617 return NETDEV_TX_OK;
Willem de Bruijncb9f1b72018-12-30 17:24:36 -0500618
619tx_err:
620 dev->stats.tx_errors++;
621 kfree_skb(skb);
622 return NETDEV_TX_OK;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900623}
624
Nicolas Dichtelee9b9592015-04-02 17:07:03 +0200625static int reg_vif_get_iflink(const struct net_device *dev)
626{
627 return 0;
628}
629
Stephen Hemminger007c3832008-11-20 20:28:35 -0800630static const struct net_device_ops reg_vif_netdev_ops = {
631 .ndo_start_xmit = reg_vif_xmit,
Nicolas Dichtelee9b9592015-04-02 17:07:03 +0200632 .ndo_get_iflink = reg_vif_get_iflink,
Stephen Hemminger007c3832008-11-20 20:28:35 -0800633};
634
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900635static void reg_vif_setup(struct net_device *dev)
636{
637 dev->type = ARPHRD_PIMREG;
638 dev->mtu = 1500 - sizeof(struct ipv6hdr) - 8;
639 dev->flags = IFF_NOARP;
Stephen Hemminger007c3832008-11-20 20:28:35 -0800640 dev->netdev_ops = &reg_vif_netdev_ops;
David S. Millercf124db2017-05-08 12:52:56 -0400641 dev->needs_free_netdev = true;
Tom Goff403dbb92009-06-14 03:16:13 -0700642 dev->features |= NETIF_F_NETNS_LOCAL;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900643}
644
Yuval Mintzb70432f2018-02-28 23:29:32 +0200645static struct net_device *ip6mr_reg_vif(struct net *net, struct mr_table *mrt)
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900646{
647 struct net_device *dev;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200648 char name[IFNAMSIZ];
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900649
Patrick McHardyd1db2752010-05-11 14:40:55 +0200650 if (mrt->id == RT6_TABLE_DFLT)
651 sprintf(name, "pim6reg");
652 else
653 sprintf(name, "pim6reg%u", mrt->id);
654
Tom Gundersenc835a672014-07-14 16:37:24 +0200655 dev = alloc_netdev(0, name, NET_NAME_UNKNOWN, reg_vif_setup);
Ian Morris63159f22015-03-29 14:00:04 +0100656 if (!dev)
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900657 return NULL;
658
Benjamin Thery8229efd2008-12-10 16:30:15 -0800659 dev_net_set(dev, net);
660
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900661 if (register_netdevice(dev)) {
662 free_netdev(dev);
663 return NULL;
664 }
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900665
Petr Machata00f54e62018-12-06 17:05:36 +0000666 if (dev_open(dev, NULL))
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900667 goto failure;
668
Wang Chen7af3db72008-07-14 20:54:54 -0700669 dev_hold(dev);
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900670 return dev;
671
672failure:
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900673 unregister_netdevice(dev);
674 return NULL;
675}
676#endif
677
Yuval Mintz088aa3e2018-03-26 15:01:34 +0300678static int call_ip6mr_vif_entry_notifiers(struct net *net,
679 enum fib_event_type event_type,
680 struct vif_device *vif,
681 mifi_t vif_index, u32 tb_id)
682{
683 return mr_call_vif_notifiers(net, RTNL_FAMILY_IP6MR, event_type,
684 vif, vif_index, tb_id,
685 &net->ipv6.ipmr_seq);
686}
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900687
Yuval Mintz088aa3e2018-03-26 15:01:34 +0300688static int call_ip6mr_mfc_entry_notifiers(struct net *net,
689 enum fib_event_type event_type,
690 struct mfc6_cache *mfc, u32 tb_id)
691{
692 return mr_call_mfc_notifiers(net, RTNL_FAMILY_IP6MR, event_type,
693 &mfc->_c, tb_id, &net->ipv6.ipmr_seq);
694}
695
696/* Delete a VIF entry */
Yuval Mintzb70432f2018-02-28 23:29:32 +0200697static int mif6_delete(struct mr_table *mrt, int vifi, int notify,
Nikolay Aleksandrov723b9292017-04-21 20:42:16 +0300698 struct list_head *head)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900699{
Yuval Mintz6853f212018-02-28 23:29:29 +0200700 struct vif_device *v;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900701 struct net_device *dev;
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800702 struct inet6_dev *in6_dev;
Patrick McHardy6bd52142010-05-11 14:40:53 +0200703
704 if (vifi < 0 || vifi >= mrt->maxvif)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900705 return -EADDRNOTAVAIL;
706
Yuval Mintzb70432f2018-02-28 23:29:32 +0200707 v = &mrt->vif_table[vifi];
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900708
Yuval Mintz088aa3e2018-03-26 15:01:34 +0300709 if (VIF_EXISTS(mrt, vifi))
710 call_ip6mr_vif_entry_notifiers(read_pnet(&mrt->net),
711 FIB_EVENT_VIF_DEL, v, vifi,
712 mrt->id);
713
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900714 write_lock_bh(&mrt_lock);
715 dev = v->dev;
716 v->dev = NULL;
717
718 if (!dev) {
719 write_unlock_bh(&mrt_lock);
720 return -EADDRNOTAVAIL;
721 }
722
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900723#ifdef CONFIG_IPV6_PIMSM_V2
Patrick McHardy6bd52142010-05-11 14:40:53 +0200724 if (vifi == mrt->mroute_reg_vif_num)
725 mrt->mroute_reg_vif_num = -1;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900726#endif
727
Patrick McHardy6bd52142010-05-11 14:40:53 +0200728 if (vifi + 1 == mrt->maxvif) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900729 int tmp;
730 for (tmp = vifi - 1; tmp >= 0; tmp--) {
Yuval Mintzb70432f2018-02-28 23:29:32 +0200731 if (VIF_EXISTS(mrt, tmp))
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900732 break;
733 }
Patrick McHardy6bd52142010-05-11 14:40:53 +0200734 mrt->maxvif = tmp + 1;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900735 }
736
737 write_unlock_bh(&mrt_lock);
738
739 dev_set_allmulti(dev, -1);
740
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800741 in6_dev = __in6_dev_get(dev);
Nicolas Dichteld67b8c62012-12-04 01:13:35 +0000742 if (in6_dev) {
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800743 in6_dev->cnf.mc_forwarding--;
David Ahern85b3daa2017-03-28 14:28:04 -0700744 inet6_netconf_notify_devconf(dev_net(dev), RTM_NEWNETCONF,
Nicolas Dichteld67b8c62012-12-04 01:13:35 +0000745 NETCONFA_MC_FORWARDING,
746 dev->ifindex, &in6_dev->cnf);
747 }
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800748
Nikolay Aleksandrov723b9292017-04-21 20:42:16 +0300749 if ((v->flags & MIFF_REGISTER) && !notify)
Eric Dumazetc871e662009-10-28 04:48:11 +0000750 unregister_netdevice_queue(dev, head);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900751
752 dev_put(dev);
753 return 0;
754}
755
Yuval Mintz87c418b2018-02-28 23:29:31 +0200756static inline void ip6mr_cache_free_rcu(struct rcu_head *head)
757{
Yuval Mintz494fff52018-02-28 23:29:34 +0200758 struct mr_mfc *c = container_of(head, struct mr_mfc, rcu);
Yuval Mintz87c418b2018-02-28 23:29:31 +0200759
Yuval Mintz494fff52018-02-28 23:29:34 +0200760 kmem_cache_free(mrt_cachep, (struct mfc6_cache *)c);
Yuval Mintz87c418b2018-02-28 23:29:31 +0200761}
762
Benjamin Thery58701ad2008-12-10 16:22:34 -0800763static inline void ip6mr_cache_free(struct mfc6_cache *c)
764{
Yuval Mintz494fff52018-02-28 23:29:34 +0200765 call_rcu(&c->_c.rcu, ip6mr_cache_free_rcu);
Benjamin Thery58701ad2008-12-10 16:22:34 -0800766}
767
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900768/* Destroy an unresolved cache entry, killing queued skbs
769 and reporting error to netlink readers.
770 */
771
Yuval Mintzb70432f2018-02-28 23:29:32 +0200772static void ip6mr_destroy_unres(struct mr_table *mrt, struct mfc6_cache *c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900773{
Patrick McHardy6bd52142010-05-11 14:40:53 +0200774 struct net *net = read_pnet(&mrt->net);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900775 struct sk_buff *skb;
776
Patrick McHardy6bd52142010-05-11 14:40:53 +0200777 atomic_dec(&mrt->cache_resolve_queue_len);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900778
Yuval Mintz494fff52018-02-28 23:29:34 +0200779 while ((skb = skb_dequeue(&c->_c.mfc_un.unres.unresolved)) != NULL) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900780 if (ipv6_hdr(skb)->version == 0) {
Johannes Bergaf728682017-06-16 14:29:22 +0200781 struct nlmsghdr *nlh = skb_pull(skb,
782 sizeof(struct ipv6hdr));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900783 nlh->nlmsg_type = NLMSG_ERROR;
Hong zhi guo573ce262013-03-27 06:47:04 +0000784 nlh->nlmsg_len = nlmsg_msg_size(sizeof(struct nlmsgerr));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900785 skb_trim(skb, nlh->nlmsg_len);
Hong zhi guo573ce262013-03-27 06:47:04 +0000786 ((struct nlmsgerr *)nlmsg_data(nlh))->error = -ETIMEDOUT;
Eric W. Biederman15e47302012-09-07 20:12:54 +0000787 rtnl_unicast(skb, net, NETLINK_CB(skb).portid);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900788 } else
789 kfree_skb(skb);
790 }
791
Benjamin Thery58701ad2008-12-10 16:22:34 -0800792 ip6mr_cache_free(c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900793}
794
795
Patrick McHardyc476efb2010-05-11 14:40:48 +0200796/* Timer process for all the unresolved queue. */
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900797
Yuval Mintzb70432f2018-02-28 23:29:32 +0200798static void ipmr_do_expire_process(struct mr_table *mrt)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900799{
800 unsigned long now = jiffies;
801 unsigned long expires = 10 * HZ;
Yuval Mintz494fff52018-02-28 23:29:34 +0200802 struct mr_mfc *c, *next;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900803
Yuval Mintzb70432f2018-02-28 23:29:32 +0200804 list_for_each_entry_safe(c, next, &mrt->mfc_unres_queue, list) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900805 if (time_after(c->mfc_un.unres.expires, now)) {
806 /* not yet... */
807 unsigned long interval = c->mfc_un.unres.expires - now;
808 if (interval < expires)
809 expires = interval;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900810 continue;
811 }
812
Patrick McHardyf30a77842010-05-11 14:40:51 +0200813 list_del(&c->list);
Yuval Mintz494fff52018-02-28 23:29:34 +0200814 mr6_netlink_event(mrt, (struct mfc6_cache *)c, RTM_DELROUTE);
815 ip6mr_destroy_unres(mrt, (struct mfc6_cache *)c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900816 }
817
Yuval Mintzb70432f2018-02-28 23:29:32 +0200818 if (!list_empty(&mrt->mfc_unres_queue))
Patrick McHardy6bd52142010-05-11 14:40:53 +0200819 mod_timer(&mrt->ipmr_expire_timer, jiffies + expires);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900820}
821
Kees Cooke99e88a2017-10-16 14:43:17 -0700822static void ipmr_expire_process(struct timer_list *t)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900823{
Yuval Mintzb70432f2018-02-28 23:29:32 +0200824 struct mr_table *mrt = from_timer(mrt, t, ipmr_expire_timer);
Patrick McHardyc476efb2010-05-11 14:40:48 +0200825
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900826 if (!spin_trylock(&mfc_unres_lock)) {
Patrick McHardy6bd52142010-05-11 14:40:53 +0200827 mod_timer(&mrt->ipmr_expire_timer, jiffies + 1);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900828 return;
829 }
830
Yuval Mintzb70432f2018-02-28 23:29:32 +0200831 if (!list_empty(&mrt->mfc_unres_queue))
Patrick McHardy6bd52142010-05-11 14:40:53 +0200832 ipmr_do_expire_process(mrt);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900833
834 spin_unlock(&mfc_unres_lock);
835}
836
837/* Fill oifs list. It is called under write locked mrt_lock. */
838
Yuval Mintzb70432f2018-02-28 23:29:32 +0200839static void ip6mr_update_thresholds(struct mr_table *mrt,
Yuval Mintz494fff52018-02-28 23:29:34 +0200840 struct mr_mfc *cache,
Patrick McHardyb5aa30b2010-05-11 14:40:50 +0200841 unsigned char *ttls)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900842{
843 int vifi;
844
Rami Rosen6ac7eb02008-04-10 12:40:10 +0300845 cache->mfc_un.res.minvif = MAXMIFS;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900846 cache->mfc_un.res.maxvif = 0;
Rami Rosen6ac7eb02008-04-10 12:40:10 +0300847 memset(cache->mfc_un.res.ttls, 255, MAXMIFS);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900848
Patrick McHardy6bd52142010-05-11 14:40:53 +0200849 for (vifi = 0; vifi < mrt->maxvif; vifi++) {
Yuval Mintzb70432f2018-02-28 23:29:32 +0200850 if (VIF_EXISTS(mrt, vifi) &&
Benjamin Thery4e168802008-12-10 16:15:08 -0800851 ttls[vifi] && ttls[vifi] < 255) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900852 cache->mfc_un.res.ttls[vifi] = ttls[vifi];
853 if (cache->mfc_un.res.minvif > vifi)
854 cache->mfc_un.res.minvif = vifi;
855 if (cache->mfc_un.res.maxvif <= vifi)
856 cache->mfc_un.res.maxvif = vifi + 1;
857 }
858 }
Nikolay Aleksandrov90b5ca12016-07-26 18:54:52 +0200859 cache->mfc_un.res.lastuse = jiffies;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900860}
861
Yuval Mintzb70432f2018-02-28 23:29:32 +0200862static int mif6_add(struct net *net, struct mr_table *mrt,
Patrick McHardy6bd52142010-05-11 14:40:53 +0200863 struct mif6ctl *vifc, int mrtsock)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900864{
865 int vifi = vifc->mif6c_mifi;
Yuval Mintzb70432f2018-02-28 23:29:32 +0200866 struct vif_device *v = &mrt->vif_table[vifi];
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900867 struct net_device *dev;
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800868 struct inet6_dev *in6_dev;
Wang Chen5ae7b442008-07-14 20:54:23 -0700869 int err;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900870
871 /* Is vif busy ? */
Yuval Mintzb70432f2018-02-28 23:29:32 +0200872 if (VIF_EXISTS(mrt, vifi))
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900873 return -EADDRINUSE;
874
875 switch (vifc->mif6c_flags) {
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900876#ifdef CONFIG_IPV6_PIMSM_V2
877 case MIFF_REGISTER:
878 /*
879 * Special Purpose VIF in PIM
880 * All the packets will be sent to the daemon
881 */
Patrick McHardy6bd52142010-05-11 14:40:53 +0200882 if (mrt->mroute_reg_vif_num >= 0)
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900883 return -EADDRINUSE;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200884 dev = ip6mr_reg_vif(net, mrt);
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900885 if (!dev)
886 return -ENOBUFS;
Wang Chen5ae7b442008-07-14 20:54:23 -0700887 err = dev_set_allmulti(dev, 1);
888 if (err) {
889 unregister_netdevice(dev);
Wang Chen7af3db72008-07-14 20:54:54 -0700890 dev_put(dev);
Wang Chen5ae7b442008-07-14 20:54:23 -0700891 return err;
892 }
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900893 break;
894#endif
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900895 case 0:
Benjamin Thery8229efd2008-12-10 16:30:15 -0800896 dev = dev_get_by_index(net, vifc->mif6c_pifi);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900897 if (!dev)
898 return -EADDRNOTAVAIL;
Wang Chen5ae7b442008-07-14 20:54:23 -0700899 err = dev_set_allmulti(dev, 1);
Wang Chen7af3db72008-07-14 20:54:54 -0700900 if (err) {
901 dev_put(dev);
Wang Chen5ae7b442008-07-14 20:54:23 -0700902 return err;
Wang Chen7af3db72008-07-14 20:54:54 -0700903 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900904 break;
905 default:
906 return -EINVAL;
907 }
908
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800909 in6_dev = __in6_dev_get(dev);
Nicolas Dichteld67b8c62012-12-04 01:13:35 +0000910 if (in6_dev) {
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800911 in6_dev->cnf.mc_forwarding++;
David Ahern85b3daa2017-03-28 14:28:04 -0700912 inet6_netconf_notify_devconf(dev_net(dev), RTM_NEWNETCONF,
Nicolas Dichteld67b8c62012-12-04 01:13:35 +0000913 NETCONFA_MC_FORWARDING,
914 dev->ifindex, &in6_dev->cnf);
915 }
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800916
Yuval Mintz6853f212018-02-28 23:29:29 +0200917 /* Fill in the VIF structures */
918 vif_device_init(v, dev, vifc->vifc_rate_limit, vifc->vifc_threshold,
919 vifc->mif6c_flags | (!mrtsock ? VIFF_STATIC : 0),
920 MIFF_REGISTER);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900921
922 /* And finish update writing critical data */
923 write_lock_bh(&mrt_lock);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900924 v->dev = dev;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900925#ifdef CONFIG_IPV6_PIMSM_V2
926 if (v->flags & MIFF_REGISTER)
Patrick McHardy6bd52142010-05-11 14:40:53 +0200927 mrt->mroute_reg_vif_num = vifi;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900928#endif
Patrick McHardy6bd52142010-05-11 14:40:53 +0200929 if (vifi + 1 > mrt->maxvif)
930 mrt->maxvif = vifi + 1;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900931 write_unlock_bh(&mrt_lock);
Yuval Mintz088aa3e2018-03-26 15:01:34 +0300932 call_ip6mr_vif_entry_notifiers(net, FIB_EVENT_VIF_ADD,
933 v, vifi, mrt->id);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900934 return 0;
935}
936
Yuval Mintzb70432f2018-02-28 23:29:32 +0200937static struct mfc6_cache *ip6mr_cache_find(struct mr_table *mrt,
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000938 const struct in6_addr *origin,
939 const struct in6_addr *mcastgrp)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900940{
Yuval Mintz87c418b2018-02-28 23:29:31 +0200941 struct mfc6_cache_cmp_arg arg = {
942 .mf6c_origin = *origin,
943 .mf6c_mcastgrp = *mcastgrp,
944 };
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900945
Yuval Mintz845c9a72018-02-28 23:29:35 +0200946 return mr_mfc_find(mrt, &arg);
Nicolas Dichtel660b26d2013-01-21 06:00:26 +0000947}
948
949/* Look for a (*,G) entry */
Yuval Mintzb70432f2018-02-28 23:29:32 +0200950static struct mfc6_cache *ip6mr_cache_find_any(struct mr_table *mrt,
Nicolas Dichtel660b26d2013-01-21 06:00:26 +0000951 struct in6_addr *mcastgrp,
952 mifi_t mifi)
953{
Yuval Mintz87c418b2018-02-28 23:29:31 +0200954 struct mfc6_cache_cmp_arg arg = {
955 .mf6c_origin = in6addr_any,
956 .mf6c_mcastgrp = *mcastgrp,
957 };
Nicolas Dichtel660b26d2013-01-21 06:00:26 +0000958
959 if (ipv6_addr_any(mcastgrp))
Yuval Mintz845c9a72018-02-28 23:29:35 +0200960 return mr_mfc_find_any_parent(mrt, mifi);
961 return mr_mfc_find_any(mrt, mifi, &arg);
Nicolas Dichtel660b26d2013-01-21 06:00:26 +0000962}
963
Yuval Mintz87c418b2018-02-28 23:29:31 +0200964/* Look for a (S,G,iif) entry if parent != -1 */
965static struct mfc6_cache *
Yuval Mintzb70432f2018-02-28 23:29:32 +0200966ip6mr_cache_find_parent(struct mr_table *mrt,
Yuval Mintz87c418b2018-02-28 23:29:31 +0200967 const struct in6_addr *origin,
968 const struct in6_addr *mcastgrp,
969 int parent)
970{
971 struct mfc6_cache_cmp_arg arg = {
972 .mf6c_origin = *origin,
973 .mf6c_mcastgrp = *mcastgrp,
974 };
Yuval Mintz87c418b2018-02-28 23:29:31 +0200975
Yuval Mintz845c9a72018-02-28 23:29:35 +0200976 return mr_mfc_find_parent(mrt, &arg, parent);
Yuval Mintz87c418b2018-02-28 23:29:31 +0200977}
978
Yuval Mintz845c9a72018-02-28 23:29:35 +0200979/* Allocate a multicast cache entry */
Patrick McHardyb5aa30b2010-05-11 14:40:50 +0200980static struct mfc6_cache *ip6mr_cache_alloc(void)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900981{
Joe Perches36cbac52008-12-03 22:27:25 -0800982 struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL);
Ian Morris63159f22015-03-29 14:00:04 +0100983 if (!c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900984 return NULL;
Yuval Mintz494fff52018-02-28 23:29:34 +0200985 c->_c.mfc_un.res.last_assert = jiffies - MFC_ASSERT_THRESH - 1;
986 c->_c.mfc_un.res.minvif = MAXMIFS;
Yuval Mintz8c13af22018-03-26 15:01:36 +0300987 c->_c.free = ip6mr_cache_free_rcu;
988 refcount_set(&c->_c.mfc_un.res.refcount, 1);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900989 return c;
990}
991
Patrick McHardyb5aa30b2010-05-11 14:40:50 +0200992static struct mfc6_cache *ip6mr_cache_alloc_unres(void)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900993{
Joe Perches36cbac52008-12-03 22:27:25 -0800994 struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC);
Ian Morris63159f22015-03-29 14:00:04 +0100995 if (!c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900996 return NULL;
Yuval Mintz494fff52018-02-28 23:29:34 +0200997 skb_queue_head_init(&c->_c.mfc_un.unres.unresolved);
998 c->_c.mfc_un.unres.expires = jiffies + 10 * HZ;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900999 return c;
1000}
1001
1002/*
1003 * A cache entry has gone into a resolved state from queued
1004 */
1005
Yuval Mintzb70432f2018-02-28 23:29:32 +02001006static void ip6mr_cache_resolve(struct net *net, struct mr_table *mrt,
Patrick McHardy6bd52142010-05-11 14:40:53 +02001007 struct mfc6_cache *uc, struct mfc6_cache *c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001008{
1009 struct sk_buff *skb;
1010
1011 /*
1012 * Play the pending entries through our router
1013 */
1014
Yuval Mintz494fff52018-02-28 23:29:34 +02001015 while ((skb = __skb_dequeue(&uc->_c.mfc_un.unres.unresolved))) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001016 if (ipv6_hdr(skb)->version == 0) {
Johannes Bergaf728682017-06-16 14:29:22 +02001017 struct nlmsghdr *nlh = skb_pull(skb,
1018 sizeof(struct ipv6hdr));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001019
Yuval Mintz7b0db852018-02-28 23:29:39 +02001020 if (mr_fill_mroute(mrt, skb, &c->_c,
1021 nlmsg_data(nlh)) > 0) {
YOSHIFUJI Hideaki549e0282008-04-05 22:17:39 +09001022 nlh->nlmsg_len = skb_tail_pointer(skb) - (u8 *)nlh;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001023 } else {
1024 nlh->nlmsg_type = NLMSG_ERROR;
Hong zhi guo573ce262013-03-27 06:47:04 +00001025 nlh->nlmsg_len = nlmsg_msg_size(sizeof(struct nlmsgerr));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001026 skb_trim(skb, nlh->nlmsg_len);
Hong zhi guo573ce262013-03-27 06:47:04 +00001027 ((struct nlmsgerr *)nlmsg_data(nlh))->error = -EMSGSIZE;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001028 }
Eric W. Biederman15e47302012-09-07 20:12:54 +00001029 rtnl_unicast(skb, net, NETLINK_CB(skb).portid);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001030 } else
Patrick Ruddye4a38c02018-10-01 09:41:27 +01001031 ip6_mr_forward(net, mrt, skb->dev, skb, c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001032 }
1033}
1034
1035/*
Julien Gomesdd12d15c2017-06-20 13:54:18 -07001036 * Bounce a cache query up to pim6sd and netlink.
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001037 *
1038 * Called under mrt_lock.
1039 */
1040
Yuval Mintzb70432f2018-02-28 23:29:32 +02001041static int ip6mr_cache_report(struct mr_table *mrt, struct sk_buff *pkt,
Patrick McHardy6bd52142010-05-11 14:40:53 +02001042 mifi_t mifi, int assert)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001043{
Yuval Mintz8571ab42018-02-28 23:29:30 +02001044 struct sock *mroute6_sk;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001045 struct sk_buff *skb;
1046 struct mrt6msg *msg;
1047 int ret;
1048
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001049#ifdef CONFIG_IPV6_PIMSM_V2
1050 if (assert == MRT6MSG_WHOLEPKT)
1051 skb = skb_realloc_headroom(pkt, -skb_network_offset(pkt)
1052 +sizeof(*msg));
1053 else
1054#endif
1055 skb = alloc_skb(sizeof(struct ipv6hdr) + sizeof(*msg), GFP_ATOMIC);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001056
1057 if (!skb)
1058 return -ENOBUFS;
1059
1060 /* I suppose that internal messages
1061 * do not require checksums */
1062
1063 skb->ip_summed = CHECKSUM_UNNECESSARY;
1064
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001065#ifdef CONFIG_IPV6_PIMSM_V2
1066 if (assert == MRT6MSG_WHOLEPKT) {
1067 /* Ugly, but we have no choice with this interface.
1068 Duplicate old header, fix length etc.
1069 And all this only to mangle msg->im6_msgtype and
1070 to set msg->im6_mbz to "mbz" :-)
1071 */
1072 skb_push(skb, -skb_network_offset(pkt));
1073
1074 skb_push(skb, sizeof(*msg));
1075 skb_reset_transport_header(skb);
1076 msg = (struct mrt6msg *)skb_transport_header(skb);
1077 msg->im6_mbz = 0;
1078 msg->im6_msgtype = MRT6MSG_WHOLEPKT;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001079 msg->im6_mif = mrt->mroute_reg_vif_num;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001080 msg->im6_pad = 0;
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +00001081 msg->im6_src = ipv6_hdr(pkt)->saddr;
1082 msg->im6_dst = ipv6_hdr(pkt)->daddr;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001083
1084 skb->ip_summed = CHECKSUM_UNNECESSARY;
1085 } else
1086#endif
1087 {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001088 /*
1089 * Copy the IP header
1090 */
1091
1092 skb_put(skb, sizeof(struct ipv6hdr));
1093 skb_reset_network_header(skb);
1094 skb_copy_to_linear_data(skb, ipv6_hdr(pkt), sizeof(struct ipv6hdr));
1095
1096 /*
1097 * Add our header
1098 */
1099 skb_put(skb, sizeof(*msg));
1100 skb_reset_transport_header(skb);
1101 msg = (struct mrt6msg *)skb_transport_header(skb);
1102
1103 msg->im6_mbz = 0;
1104 msg->im6_msgtype = assert;
Rami Rosen6ac7eb02008-04-10 12:40:10 +03001105 msg->im6_mif = mifi;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001106 msg->im6_pad = 0;
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +00001107 msg->im6_src = ipv6_hdr(pkt)->saddr;
1108 msg->im6_dst = ipv6_hdr(pkt)->daddr;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001109
Eric Dumazetadf30902009-06-02 05:19:30 +00001110 skb_dst_set(skb, dst_clone(skb_dst(pkt)));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001111 skb->ip_summed = CHECKSUM_UNNECESSARY;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001112 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001113
Yuval Mintz8571ab42018-02-28 23:29:30 +02001114 rcu_read_lock();
Yuval Mintzb70432f2018-02-28 23:29:32 +02001115 mroute6_sk = rcu_dereference(mrt->mroute_sk);
Yuval Mintz8571ab42018-02-28 23:29:30 +02001116 if (!mroute6_sk) {
1117 rcu_read_unlock();
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001118 kfree_skb(skb);
1119 return -EINVAL;
1120 }
1121
Julien Gomesdd12d15c2017-06-20 13:54:18 -07001122 mrt6msg_netlink_event(mrt, skb);
1123
Yuval Mintz8571ab42018-02-28 23:29:30 +02001124 /* Deliver to user space multicast routing algorithms */
1125 ret = sock_queue_rcv_skb(mroute6_sk, skb);
1126 rcu_read_unlock();
Benjamin Therybd91b8b2008-12-10 16:07:08 -08001127 if (ret < 0) {
Joe Perchese87cc472012-05-13 21:56:26 +00001128 net_warn_ratelimited("mroute6: pending queue full, dropping entries\n");
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001129 kfree_skb(skb);
1130 }
1131
1132 return ret;
1133}
1134
Yuval Mintz494fff52018-02-28 23:29:34 +02001135/* Queue a packet for resolution. It gets locked cache entry! */
1136static int ip6mr_cache_unresolved(struct mr_table *mrt, mifi_t mifi,
Patrick Ruddye4a38c02018-10-01 09:41:27 +01001137 struct sk_buff *skb, struct net_device *dev)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001138{
Yuval Mintz494fff52018-02-28 23:29:34 +02001139 struct mfc6_cache *c;
Patrick McHardyf30a77842010-05-11 14:40:51 +02001140 bool found = false;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001141 int err;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001142
1143 spin_lock_bh(&mfc_unres_lock);
Yuval Mintz494fff52018-02-28 23:29:34 +02001144 list_for_each_entry(c, &mrt->mfc_unres_queue, _c.list) {
Patrick McHardyc476efb2010-05-11 14:40:48 +02001145 if (ipv6_addr_equal(&c->mf6c_mcastgrp, &ipv6_hdr(skb)->daddr) &&
Patrick McHardyf30a77842010-05-11 14:40:51 +02001146 ipv6_addr_equal(&c->mf6c_origin, &ipv6_hdr(skb)->saddr)) {
1147 found = true;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001148 break;
Patrick McHardyf30a77842010-05-11 14:40:51 +02001149 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001150 }
1151
Patrick McHardyf30a77842010-05-11 14:40:51 +02001152 if (!found) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001153 /*
1154 * Create a new entry if allowable
1155 */
1156
Patrick McHardy6bd52142010-05-11 14:40:53 +02001157 if (atomic_read(&mrt->cache_resolve_queue_len) >= 10 ||
Patrick McHardyb5aa30b2010-05-11 14:40:50 +02001158 (c = ip6mr_cache_alloc_unres()) == NULL) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001159 spin_unlock_bh(&mfc_unres_lock);
1160
1161 kfree_skb(skb);
1162 return -ENOBUFS;
1163 }
1164
Yuval Mintz494fff52018-02-28 23:29:34 +02001165 /* Fill in the new cache entry */
1166 c->_c.mfc_parent = -1;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001167 c->mf6c_origin = ipv6_hdr(skb)->saddr;
1168 c->mf6c_mcastgrp = ipv6_hdr(skb)->daddr;
1169
1170 /*
1171 * Reflect first query at pim6sd
1172 */
Patrick McHardy6bd52142010-05-11 14:40:53 +02001173 err = ip6mr_cache_report(mrt, skb, mifi, MRT6MSG_NOCACHE);
Benjamin Thery8229efd2008-12-10 16:30:15 -08001174 if (err < 0) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001175 /* If the report failed throw the cache entry
1176 out - Brad Parker
1177 */
1178 spin_unlock_bh(&mfc_unres_lock);
1179
Benjamin Thery58701ad2008-12-10 16:22:34 -08001180 ip6mr_cache_free(c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001181 kfree_skb(skb);
1182 return err;
1183 }
1184
Patrick McHardy6bd52142010-05-11 14:40:53 +02001185 atomic_inc(&mrt->cache_resolve_queue_len);
Yuval Mintz494fff52018-02-28 23:29:34 +02001186 list_add(&c->_c.list, &mrt->mfc_unres_queue);
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00001187 mr6_netlink_event(mrt, c, RTM_NEWROUTE);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001188
Patrick McHardy6bd52142010-05-11 14:40:53 +02001189 ipmr_do_expire_process(mrt);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001190 }
1191
Yuval Mintz494fff52018-02-28 23:29:34 +02001192 /* See if we can append the packet */
1193 if (c->_c.mfc_un.unres.unresolved.qlen > 3) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001194 kfree_skb(skb);
1195 err = -ENOBUFS;
1196 } else {
Patrick Ruddye4a38c02018-10-01 09:41:27 +01001197 if (dev) {
1198 skb->dev = dev;
1199 skb->skb_iif = dev->ifindex;
1200 }
Yuval Mintz494fff52018-02-28 23:29:34 +02001201 skb_queue_tail(&c->_c.mfc_un.unres.unresolved, skb);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001202 err = 0;
1203 }
1204
1205 spin_unlock_bh(&mfc_unres_lock);
1206 return err;
1207}
1208
1209/*
1210 * MFC6 cache manipulation by user space
1211 */
1212
Yuval Mintzb70432f2018-02-28 23:29:32 +02001213static int ip6mr_mfc_delete(struct mr_table *mrt, struct mf6cctl *mfc,
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001214 int parent)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001215{
Yuval Mintz87c418b2018-02-28 23:29:31 +02001216 struct mfc6_cache *c;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001217
Yuval Mintz87c418b2018-02-28 23:29:31 +02001218 /* The entries are added/deleted only under RTNL */
1219 rcu_read_lock();
1220 c = ip6mr_cache_find_parent(mrt, &mfc->mf6cc_origin.sin6_addr,
1221 &mfc->mf6cc_mcastgrp.sin6_addr, parent);
1222 rcu_read_unlock();
1223 if (!c)
1224 return -ENOENT;
Yuval Mintz494fff52018-02-28 23:29:34 +02001225 rhltable_remove(&mrt->mfc_hash, &c->_c.mnode, ip6mr_rht_params);
1226 list_del_rcu(&c->_c.list);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001227
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001228 call_ip6mr_mfc_entry_notifiers(read_pnet(&mrt->net),
1229 FIB_EVENT_ENTRY_DEL, c, mrt->id);
Yuval Mintz87c418b2018-02-28 23:29:31 +02001230 mr6_netlink_event(mrt, c, RTM_DELROUTE);
Yuval Mintz8c13af22018-03-26 15:01:36 +03001231 mr_cache_put(&c->_c);
Yuval Mintz87c418b2018-02-28 23:29:31 +02001232 return 0;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001233}
1234
1235static int ip6mr_device_event(struct notifier_block *this,
1236 unsigned long event, void *ptr)
1237{
Jiri Pirko351638e2013-05-28 01:30:21 +00001238 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
Benjamin Thery8229efd2008-12-10 16:30:15 -08001239 struct net *net = dev_net(dev);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001240 struct mr_table *mrt;
Yuval Mintz6853f212018-02-28 23:29:29 +02001241 struct vif_device *v;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001242 int ct;
1243
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001244 if (event != NETDEV_UNREGISTER)
1245 return NOTIFY_DONE;
1246
Patrick McHardyd1db2752010-05-11 14:40:55 +02001247 ip6mr_for_each_table(mrt, net) {
Yuval Mintzb70432f2018-02-28 23:29:32 +02001248 v = &mrt->vif_table[0];
Patrick McHardyd1db2752010-05-11 14:40:55 +02001249 for (ct = 0; ct < mrt->maxvif; ct++, v++) {
1250 if (v->dev == dev)
Nikolay Aleksandrov723b9292017-04-21 20:42:16 +03001251 mif6_delete(mrt, ct, 1, NULL);
Patrick McHardyd1db2752010-05-11 14:40:55 +02001252 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001253 }
Eric Dumazetc871e662009-10-28 04:48:11 +00001254
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001255 return NOTIFY_DONE;
1256}
1257
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001258static unsigned int ip6mr_seq_read(struct net *net)
1259{
1260 ASSERT_RTNL();
1261
1262 return net->ipv6.ipmr_seq + ip6mr_rules_seq_read(net);
1263}
1264
1265static int ip6mr_dump(struct net *net, struct notifier_block *nb)
1266{
1267 return mr_dump(net, nb, RTNL_FAMILY_IP6MR, ip6mr_rules_dump,
1268 ip6mr_mr_table_iter, &mrt_lock);
1269}
1270
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001271static struct notifier_block ip6_mr_notifier = {
1272 .notifier_call = ip6mr_device_event
1273};
1274
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001275static const struct fib_notifier_ops ip6mr_notifier_ops_template = {
1276 .family = RTNL_FAMILY_IP6MR,
1277 .fib_seq_read = ip6mr_seq_read,
1278 .fib_dump = ip6mr_dump,
1279 .owner = THIS_MODULE,
1280};
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001281
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001282static int __net_init ip6mr_notifier_init(struct net *net)
1283{
1284 struct fib_notifier_ops *ops;
1285
1286 net->ipv6.ipmr_seq = 0;
1287
1288 ops = fib_notifier_ops_register(&ip6mr_notifier_ops_template, net);
1289 if (IS_ERR(ops))
1290 return PTR_ERR(ops);
1291
1292 net->ipv6.ip6mr_notifier_ops = ops;
1293
1294 return 0;
1295}
1296
1297static void __net_exit ip6mr_notifier_exit(struct net *net)
1298{
1299 fib_notifier_ops_unregister(net->ipv6.ip6mr_notifier_ops);
1300 net->ipv6.ip6mr_notifier_ops = NULL;
1301}
1302
1303/* Setup for IP multicast routing */
Benjamin Thery4e168802008-12-10 16:15:08 -08001304static int __net_init ip6mr_net_init(struct net *net)
1305{
Patrick McHardyd1db2752010-05-11 14:40:55 +02001306 int err;
Patrick McHardyf30a77842010-05-11 14:40:51 +02001307
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001308 err = ip6mr_notifier_init(net);
1309 if (err)
1310 return err;
1311
Patrick McHardyd1db2752010-05-11 14:40:55 +02001312 err = ip6mr_rules_init(net);
1313 if (err < 0)
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001314 goto ip6mr_rules_fail;
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001315
1316#ifdef CONFIG_PROC_FS
1317 err = -ENOMEM;
Christoph Hellwigc3506372018-04-10 19:42:55 +02001318 if (!proc_create_net("ip6_mr_vif", 0, net->proc_net, &ip6mr_vif_seq_ops,
1319 sizeof(struct mr_vif_iter)))
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001320 goto proc_vif_fail;
Christoph Hellwigc3506372018-04-10 19:42:55 +02001321 if (!proc_create_net("ip6_mr_cache", 0, net->proc_net, &ipmr_mfc_seq_ops,
1322 sizeof(struct mr_mfc_iter)))
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001323 goto proc_cache_fail;
1324#endif
Patrick McHardy6bd52142010-05-11 14:40:53 +02001325
Benjamin Thery4a6258a2008-12-10 16:24:07 -08001326 return 0;
1327
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001328#ifdef CONFIG_PROC_FS
1329proc_cache_fail:
Gao fengece31ff2013-02-18 01:34:56 +00001330 remove_proc_entry("ip6_mr_vif", net->proc_net);
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001331proc_vif_fail:
Patrick McHardyd1db2752010-05-11 14:40:55 +02001332 ip6mr_rules_exit(net);
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001333#endif
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001334ip6mr_rules_fail:
1335 ip6mr_notifier_exit(net);
Benjamin Thery4e168802008-12-10 16:15:08 -08001336 return err;
1337}
1338
1339static void __net_exit ip6mr_net_exit(struct net *net)
1340{
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001341#ifdef CONFIG_PROC_FS
Gao fengece31ff2013-02-18 01:34:56 +00001342 remove_proc_entry("ip6_mr_cache", net->proc_net);
1343 remove_proc_entry("ip6_mr_vif", net->proc_net);
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001344#endif
Patrick McHardyd1db2752010-05-11 14:40:55 +02001345 ip6mr_rules_exit(net);
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001346 ip6mr_notifier_exit(net);
Benjamin Thery4e168802008-12-10 16:15:08 -08001347}
1348
1349static struct pernet_operations ip6mr_net_ops = {
1350 .init = ip6mr_net_init,
1351 .exit = ip6mr_net_exit,
1352};
1353
Wang Chen623d1a12008-07-03 12:13:30 +08001354int __init ip6_mr_init(void)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001355{
Wang Chen623d1a12008-07-03 12:13:30 +08001356 int err;
1357
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001358 mrt_cachep = kmem_cache_create("ip6_mrt_cache",
1359 sizeof(struct mfc6_cache),
1360 0, SLAB_HWCACHE_ALIGN,
1361 NULL);
1362 if (!mrt_cachep)
Wang Chen623d1a12008-07-03 12:13:30 +08001363 return -ENOMEM;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001364
Benjamin Thery4e168802008-12-10 16:15:08 -08001365 err = register_pernet_subsys(&ip6mr_net_ops);
1366 if (err)
1367 goto reg_pernet_fail;
1368
Wang Chen623d1a12008-07-03 12:13:30 +08001369 err = register_netdevice_notifier(&ip6_mr_notifier);
1370 if (err)
1371 goto reg_notif_fail;
Tom Goff403dbb92009-06-14 03:16:13 -07001372#ifdef CONFIG_IPV6_PIMSM_V2
1373 if (inet6_add_protocol(&pim6_protocol, IPPROTO_PIM) < 0) {
Joe Perchesf3213832012-05-15 14:11:53 +00001374 pr_err("%s: can't add PIM protocol\n", __func__);
Tom Goff403dbb92009-06-14 03:16:13 -07001375 err = -EAGAIN;
1376 goto add_proto_fail;
1377 }
1378#endif
Florian Westphala3fde2a2017-12-04 19:19:18 +01001379 err = rtnl_register_module(THIS_MODULE, RTNL_FAMILY_IP6MR, RTM_GETROUTE,
1380 NULL, ip6mr_rtm_dumproute, 0);
1381 if (err == 0)
1382 return 0;
1383
Tom Goff403dbb92009-06-14 03:16:13 -07001384#ifdef CONFIG_IPV6_PIMSM_V2
Florian Westphala3fde2a2017-12-04 19:19:18 +01001385 inet6_del_protocol(&pim6_protocol, IPPROTO_PIM);
Tom Goff403dbb92009-06-14 03:16:13 -07001386add_proto_fail:
1387 unregister_netdevice_notifier(&ip6_mr_notifier);
1388#endif
Benjamin Thery87b30a62008-11-10 16:34:11 -08001389reg_notif_fail:
Benjamin Thery4e168802008-12-10 16:15:08 -08001390 unregister_pernet_subsys(&ip6mr_net_ops);
1391reg_pernet_fail:
Benjamin Thery87b30a62008-11-10 16:34:11 -08001392 kmem_cache_destroy(mrt_cachep);
Wang Chen623d1a12008-07-03 12:13:30 +08001393 return err;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001394}
1395
Wang Chen623d1a12008-07-03 12:13:30 +08001396void ip6_mr_cleanup(void)
1397{
Duan Jiongffb13882014-11-19 09:35:39 +08001398 rtnl_unregister(RTNL_FAMILY_IP6MR, RTM_GETROUTE);
1399#ifdef CONFIG_IPV6_PIMSM_V2
1400 inet6_del_protocol(&pim6_protocol, IPPROTO_PIM);
1401#endif
Wang Chen623d1a12008-07-03 12:13:30 +08001402 unregister_netdevice_notifier(&ip6_mr_notifier);
Benjamin Thery4e168802008-12-10 16:15:08 -08001403 unregister_pernet_subsys(&ip6mr_net_ops);
Wang Chen623d1a12008-07-03 12:13:30 +08001404 kmem_cache_destroy(mrt_cachep);
1405}
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001406
Yuval Mintzb70432f2018-02-28 23:29:32 +02001407static int ip6mr_mfc_add(struct net *net, struct mr_table *mrt,
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001408 struct mf6cctl *mfc, int mrtsock, int parent)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001409{
Rami Rosen6ac7eb02008-04-10 12:40:10 +03001410 unsigned char ttls[MAXMIFS];
Yuval Mintz87c418b2018-02-28 23:29:31 +02001411 struct mfc6_cache *uc, *c;
Yuval Mintz494fff52018-02-28 23:29:34 +02001412 struct mr_mfc *_uc;
Yuval Mintz87c418b2018-02-28 23:29:31 +02001413 bool found;
1414 int i, err;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001415
Patrick McHardya50436f22010-03-17 06:04:14 +00001416 if (mfc->mf6cc_parent >= MAXMIFS)
1417 return -ENFILE;
1418
Rami Rosen6ac7eb02008-04-10 12:40:10 +03001419 memset(ttls, 255, MAXMIFS);
1420 for (i = 0; i < MAXMIFS; i++) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001421 if (IF_ISSET(i, &mfc->mf6cc_ifset))
1422 ttls[i] = 1;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001423 }
1424
Yuval Mintz87c418b2018-02-28 23:29:31 +02001425 /* The entries are added/deleted only under RTNL */
1426 rcu_read_lock();
1427 c = ip6mr_cache_find_parent(mrt, &mfc->mf6cc_origin.sin6_addr,
1428 &mfc->mf6cc_mcastgrp.sin6_addr, parent);
1429 rcu_read_unlock();
1430 if (c) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001431 write_lock_bh(&mrt_lock);
Yuval Mintz494fff52018-02-28 23:29:34 +02001432 c->_c.mfc_parent = mfc->mf6cc_parent;
1433 ip6mr_update_thresholds(mrt, &c->_c, ttls);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001434 if (!mrtsock)
Yuval Mintz494fff52018-02-28 23:29:34 +02001435 c->_c.mfc_flags |= MFC_STATIC;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001436 write_unlock_bh(&mrt_lock);
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001437 call_ip6mr_mfc_entry_notifiers(net, FIB_EVENT_ENTRY_REPLACE,
1438 c, mrt->id);
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00001439 mr6_netlink_event(mrt, c, RTM_NEWROUTE);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001440 return 0;
1441 }
1442
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001443 if (!ipv6_addr_any(&mfc->mf6cc_mcastgrp.sin6_addr) &&
1444 !ipv6_addr_is_multicast(&mfc->mf6cc_mcastgrp.sin6_addr))
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001445 return -EINVAL;
1446
Patrick McHardyb5aa30b2010-05-11 14:40:50 +02001447 c = ip6mr_cache_alloc();
Ian Morris63159f22015-03-29 14:00:04 +01001448 if (!c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001449 return -ENOMEM;
1450
1451 c->mf6c_origin = mfc->mf6cc_origin.sin6_addr;
1452 c->mf6c_mcastgrp = mfc->mf6cc_mcastgrp.sin6_addr;
Yuval Mintz494fff52018-02-28 23:29:34 +02001453 c->_c.mfc_parent = mfc->mf6cc_parent;
1454 ip6mr_update_thresholds(mrt, &c->_c, ttls);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001455 if (!mrtsock)
Yuval Mintz494fff52018-02-28 23:29:34 +02001456 c->_c.mfc_flags |= MFC_STATIC;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001457
Yuval Mintz494fff52018-02-28 23:29:34 +02001458 err = rhltable_insert_key(&mrt->mfc_hash, &c->cmparg, &c->_c.mnode,
Yuval Mintz87c418b2018-02-28 23:29:31 +02001459 ip6mr_rht_params);
1460 if (err) {
1461 pr_err("ip6mr: rhtable insert error %d\n", err);
1462 ip6mr_cache_free(c);
1463 return err;
1464 }
Yuval Mintz494fff52018-02-28 23:29:34 +02001465 list_add_tail_rcu(&c->_c.list, &mrt->mfc_cache_list);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001466
Yuval Mintz87c418b2018-02-28 23:29:31 +02001467 /* Check to see if we resolved a queued list. If so we
1468 * need to send on the frames and tidy up.
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001469 */
Patrick McHardyf30a77842010-05-11 14:40:51 +02001470 found = false;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001471 spin_lock_bh(&mfc_unres_lock);
Yuval Mintz494fff52018-02-28 23:29:34 +02001472 list_for_each_entry(_uc, &mrt->mfc_unres_queue, list) {
1473 uc = (struct mfc6_cache *)_uc;
Patrick McHardyc476efb2010-05-11 14:40:48 +02001474 if (ipv6_addr_equal(&uc->mf6c_origin, &c->mf6c_origin) &&
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001475 ipv6_addr_equal(&uc->mf6c_mcastgrp, &c->mf6c_mcastgrp)) {
Yuval Mintz494fff52018-02-28 23:29:34 +02001476 list_del(&_uc->list);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001477 atomic_dec(&mrt->cache_resolve_queue_len);
Patrick McHardyf30a77842010-05-11 14:40:51 +02001478 found = true;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001479 break;
1480 }
1481 }
Yuval Mintzb70432f2018-02-28 23:29:32 +02001482 if (list_empty(&mrt->mfc_unres_queue))
Patrick McHardy6bd52142010-05-11 14:40:53 +02001483 del_timer(&mrt->ipmr_expire_timer);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001484 spin_unlock_bh(&mfc_unres_lock);
1485
Patrick McHardyf30a77842010-05-11 14:40:51 +02001486 if (found) {
Patrick McHardy6bd52142010-05-11 14:40:53 +02001487 ip6mr_cache_resolve(net, mrt, uc, c);
Benjamin Thery58701ad2008-12-10 16:22:34 -08001488 ip6mr_cache_free(uc);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001489 }
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001490 call_ip6mr_mfc_entry_notifiers(net, FIB_EVENT_ENTRY_ADD,
1491 c, mrt->id);
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00001492 mr6_netlink_event(mrt, c, RTM_NEWROUTE);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001493 return 0;
1494}
1495
1496/*
1497 * Close the multicast socket, and clear the vif tables etc
1498 */
1499
Callum Sinclairca8d4792019-02-18 10:07:52 +13001500static void mroute_clean_tables(struct mr_table *mrt, int flags)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001501{
Yuval Mintz494fff52018-02-28 23:29:34 +02001502 struct mr_mfc *c, *tmp;
Eric Dumazetc871e662009-10-28 04:48:11 +00001503 LIST_HEAD(list);
Yuval Mintz87c418b2018-02-28 23:29:31 +02001504 int i;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001505
Yuval Mintz87c418b2018-02-28 23:29:31 +02001506 /* Shut down all active vif entries */
Callum Sinclairca8d4792019-02-18 10:07:52 +13001507 if (flags & (MRT6_FLUSH_MIFS | MRT6_FLUSH_MIFS_STATIC)) {
1508 for (i = 0; i < mrt->maxvif; i++) {
1509 if (((mrt->vif_table[i].flags & VIFF_STATIC) &&
1510 !(flags & MRT6_FLUSH_MIFS_STATIC)) ||
1511 (!(mrt->vif_table[i].flags & VIFF_STATIC) && !(flags & MRT6_FLUSH_MIFS)))
1512 continue;
1513 mif6_delete(mrt, i, 0, &list);
1514 }
1515 unregister_netdevice_many(&list);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001516 }
1517
Yuval Mintz87c418b2018-02-28 23:29:31 +02001518 /* Wipe the cache */
Callum Sinclairca8d4792019-02-18 10:07:52 +13001519 if (flags & (MRT6_FLUSH_MFC | MRT6_FLUSH_MFC_STATIC)) {
1520 list_for_each_entry_safe(c, tmp, &mrt->mfc_cache_list, list) {
1521 if (((c->mfc_flags & MFC_STATIC) && !(flags & MRT6_FLUSH_MFC_STATIC)) ||
1522 (!(c->mfc_flags & MFC_STATIC) && !(flags & MRT6_FLUSH_MFC)))
1523 continue;
1524 rhltable_remove(&mrt->mfc_hash, &c->mnode, ip6mr_rht_params);
1525 list_del_rcu(&c->list);
1526 call_ip6mr_mfc_entry_notifiers(read_pnet(&mrt->net),
1527 FIB_EVENT_ENTRY_DEL,
1528 (struct mfc6_cache *)c, mrt->id);
1529 mr6_netlink_event(mrt, (struct mfc6_cache *)c, RTM_DELROUTE);
1530 mr_cache_put(c);
1531 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001532 }
1533
Callum Sinclairca8d4792019-02-18 10:07:52 +13001534 if (flags & MRT6_FLUSH_MFC) {
1535 if (atomic_read(&mrt->cache_resolve_queue_len) != 0) {
1536 spin_lock_bh(&mfc_unres_lock);
1537 list_for_each_entry_safe(c, tmp, &mrt->mfc_unres_queue, list) {
1538 list_del(&c->list);
1539 mr6_netlink_event(mrt, (struct mfc6_cache *)c,
1540 RTM_DELROUTE);
1541 ip6mr_destroy_unres(mrt, (struct mfc6_cache *)c);
1542 }
1543 spin_unlock_bh(&mfc_unres_lock);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001544 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001545 }
1546}
1547
Yuval Mintzb70432f2018-02-28 23:29:32 +02001548static int ip6mr_sk_init(struct mr_table *mrt, struct sock *sk)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001549{
1550 int err = 0;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001551 struct net *net = sock_net(sk);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001552
1553 rtnl_lock();
1554 write_lock_bh(&mrt_lock);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001555 if (rtnl_dereference(mrt->mroute_sk)) {
Eric Dumazet927265b2016-07-08 05:46:04 +02001556 err = -EADDRINUSE;
Yuval Mintz8571ab42018-02-28 23:29:30 +02001557 } else {
Yuval Mintzb70432f2018-02-28 23:29:32 +02001558 rcu_assign_pointer(mrt->mroute_sk, sk);
Eric Dumazeta366e302018-03-07 08:43:19 -08001559 sock_set_flag(sk, SOCK_RCU_FREE);
Yuval Mintz8571ab42018-02-28 23:29:30 +02001560 net->ipv6.devconf_all->mc_forwarding++;
Eric Dumazet927265b2016-07-08 05:46:04 +02001561 }
1562 write_unlock_bh(&mrt_lock);
1563
1564 if (!err)
David Ahern85b3daa2017-03-28 14:28:04 -07001565 inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
1566 NETCONFA_MC_FORWARDING,
Nicolas Dichteld67b8c62012-12-04 01:13:35 +00001567 NETCONFA_IFINDEX_ALL,
1568 net->ipv6.devconf_all);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001569 rtnl_unlock();
1570
1571 return err;
1572}
1573
1574int ip6mr_sk_done(struct sock *sk)
1575{
Patrick McHardyd1db2752010-05-11 14:40:55 +02001576 int err = -EACCES;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001577 struct net *net = sock_net(sk);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001578 struct mr_table *mrt;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001579
Francesco Ruggeri338d1822017-11-08 11:23:46 -08001580 if (sk->sk_type != SOCK_RAW ||
1581 inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
1582 return err;
1583
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001584 rtnl_lock();
Patrick McHardyd1db2752010-05-11 14:40:55 +02001585 ip6mr_for_each_table(mrt, net) {
Yuval Mintzb70432f2018-02-28 23:29:32 +02001586 if (sk == rtnl_dereference(mrt->mroute_sk)) {
Patrick McHardyd1db2752010-05-11 14:40:55 +02001587 write_lock_bh(&mrt_lock);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001588 RCU_INIT_POINTER(mrt->mroute_sk, NULL);
Eric Dumazeta366e302018-03-07 08:43:19 -08001589 /* Note that mroute_sk had SOCK_RCU_FREE set,
1590 * so the RCU grace period before sk freeing
1591 * is guaranteed by sk_destruct()
1592 */
Patrick McHardyd1db2752010-05-11 14:40:55 +02001593 net->ipv6.devconf_all->mc_forwarding--;
Eric Dumazet927265b2016-07-08 05:46:04 +02001594 write_unlock_bh(&mrt_lock);
David Ahern85b3daa2017-03-28 14:28:04 -07001595 inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
Nicolas Dichteld67b8c62012-12-04 01:13:35 +00001596 NETCONFA_MC_FORWARDING,
1597 NETCONFA_IFINDEX_ALL,
1598 net->ipv6.devconf_all);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001599
Callum Sinclairca8d4792019-02-18 10:07:52 +13001600 mroute_clean_tables(mrt, MRT6_FLUSH_MIFS | MRT6_FLUSH_MFC);
Patrick McHardyd1db2752010-05-11 14:40:55 +02001601 err = 0;
1602 break;
1603 }
1604 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001605 rtnl_unlock();
1606
1607 return err;
1608}
1609
Yuval Mintz8571ab42018-02-28 23:29:30 +02001610bool mroute6_is_socket(struct net *net, struct sk_buff *skb)
Patrick McHardy6bd52142010-05-11 14:40:53 +02001611{
Yuval Mintzb70432f2018-02-28 23:29:32 +02001612 struct mr_table *mrt;
David S. Miller4c9483b2011-03-12 16:22:43 -05001613 struct flowi6 fl6 = {
Julian Anastasove374c612014-04-28 10:51:56 +03001614 .flowi6_iif = skb->skb_iif ? : LOOPBACK_IFINDEX,
David S. Miller4c9483b2011-03-12 16:22:43 -05001615 .flowi6_oif = skb->dev->ifindex,
1616 .flowi6_mark = skb->mark,
Patrick McHardyd1db2752010-05-11 14:40:55 +02001617 };
1618
David S. Miller4c9483b2011-03-12 16:22:43 -05001619 if (ip6mr_fib_lookup(net, &fl6, &mrt) < 0)
Patrick McHardyd1db2752010-05-11 14:40:55 +02001620 return NULL;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001621
Yuval Mintzb70432f2018-02-28 23:29:32 +02001622 return rcu_access_pointer(mrt->mroute_sk);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001623}
Yuval Mintz8571ab42018-02-28 23:29:30 +02001624EXPORT_SYMBOL(mroute6_is_socket);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001625
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001626/*
1627 * Socket options and virtual interface manipulation. The whole
1628 * virtual interface system is a complete heap, but unfortunately
1629 * that's how BSD mrouted happens to think. Maybe one day with a proper
1630 * MOSPF/PIM router set up we can clean this up.
1631 */
1632
David S. Millerb7058842009-09-30 16:12:20 -07001633int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsigned int optlen)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001634{
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001635 int ret, parent = 0;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001636 struct mif6ctl vif;
1637 struct mf6cctl mfc;
1638 mifi_t mifi;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001639 struct net *net = sock_net(sk);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001640 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +02001641
Xin Long99253eb2017-02-24 16:29:06 +08001642 if (sk->sk_type != SOCK_RAW ||
1643 inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
1644 return -EOPNOTSUPP;
1645
Patrick McHardyd1db2752010-05-11 14:40:55 +02001646 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +01001647 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +02001648 return -ENOENT;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001649
1650 if (optname != MRT6_INIT) {
Yuval Mintzb70432f2018-02-28 23:29:32 +02001651 if (sk != rcu_access_pointer(mrt->mroute_sk) &&
Yuval Mintz8571ab42018-02-28 23:29:30 +02001652 !ns_capable(net->user_ns, CAP_NET_ADMIN))
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001653 return -EACCES;
1654 }
1655
1656 switch (optname) {
1657 case MRT6_INIT:
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001658 if (optlen < sizeof(int))
1659 return -EINVAL;
1660
Patrick McHardy6bd52142010-05-11 14:40:53 +02001661 return ip6mr_sk_init(mrt, sk);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001662
1663 case MRT6_DONE:
1664 return ip6mr_sk_done(sk);
1665
1666 case MRT6_ADD_MIF:
1667 if (optlen < sizeof(vif))
1668 return -EINVAL;
1669 if (copy_from_user(&vif, optval, sizeof(vif)))
1670 return -EFAULT;
Rami Rosen6ac7eb02008-04-10 12:40:10 +03001671 if (vif.mif6c_mifi >= MAXMIFS)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001672 return -ENFILE;
1673 rtnl_lock();
Yuval Mintz8571ab42018-02-28 23:29:30 +02001674 ret = mif6_add(net, mrt, &vif,
Yuval Mintzb70432f2018-02-28 23:29:32 +02001675 sk == rtnl_dereference(mrt->mroute_sk));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001676 rtnl_unlock();
1677 return ret;
1678
1679 case MRT6_DEL_MIF:
1680 if (optlen < sizeof(mifi_t))
1681 return -EINVAL;
1682 if (copy_from_user(&mifi, optval, sizeof(mifi_t)))
1683 return -EFAULT;
1684 rtnl_lock();
Nikolay Aleksandrov723b9292017-04-21 20:42:16 +03001685 ret = mif6_delete(mrt, mifi, 0, NULL);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001686 rtnl_unlock();
1687 return ret;
1688
1689 /*
1690 * Manipulate the forwarding caches. These live
1691 * in a sort of kernel/user symbiosis.
1692 */
1693 case MRT6_ADD_MFC:
1694 case MRT6_DEL_MFC:
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001695 parent = -1;
Gustavo A. R. Silva275757e62017-10-16 16:36:52 -05001696 /* fall through */
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001697 case MRT6_ADD_MFC_PROXY:
1698 case MRT6_DEL_MFC_PROXY:
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001699 if (optlen < sizeof(mfc))
1700 return -EINVAL;
1701 if (copy_from_user(&mfc, optval, sizeof(mfc)))
1702 return -EFAULT;
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001703 if (parent == 0)
1704 parent = mfc.mf6cc_parent;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001705 rtnl_lock();
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001706 if (optname == MRT6_DEL_MFC || optname == MRT6_DEL_MFC_PROXY)
1707 ret = ip6mr_mfc_delete(mrt, &mfc, parent);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001708 else
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001709 ret = ip6mr_mfc_add(net, mrt, &mfc,
Yuval Mintz8571ab42018-02-28 23:29:30 +02001710 sk ==
Yuval Mintzb70432f2018-02-28 23:29:32 +02001711 rtnl_dereference(mrt->mroute_sk),
Yuval Mintz8571ab42018-02-28 23:29:30 +02001712 parent);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001713 rtnl_unlock();
1714 return ret;
1715
Callum Sinclairca8d4792019-02-18 10:07:52 +13001716 case MRT6_FLUSH:
1717 {
1718 int flags;
1719
1720 if (optlen != sizeof(flags))
1721 return -EINVAL;
1722 if (get_user(flags, (int __user *)optval))
1723 return -EFAULT;
1724 rtnl_lock();
1725 mroute_clean_tables(mrt, flags);
1726 rtnl_unlock();
1727 return 0;
1728 }
1729
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001730 /*
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001731 * Control PIM assert (to activate pim will activate assert)
1732 */
1733 case MRT6_ASSERT:
1734 {
1735 int v;
Joe Perches03f52a02012-11-25 18:26:34 +00001736
1737 if (optlen != sizeof(v))
1738 return -EINVAL;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001739 if (get_user(v, (int __user *)optval))
1740 return -EFAULT;
Joe Perches53d68412012-11-25 09:35:30 +00001741 mrt->mroute_do_assert = v;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001742 return 0;
1743 }
1744
1745#ifdef CONFIG_IPV6_PIMSM_V2
1746 case MRT6_PIM:
1747 {
YOSHIFUJI Hideakia9f83bf2008-04-10 15:41:28 +09001748 int v;
Joe Perches03f52a02012-11-25 18:26:34 +00001749
1750 if (optlen != sizeof(v))
1751 return -EINVAL;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001752 if (get_user(v, (int __user *)optval))
1753 return -EFAULT;
1754 v = !!v;
1755 rtnl_lock();
1756 ret = 0;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001757 if (v != mrt->mroute_do_pim) {
1758 mrt->mroute_do_pim = v;
1759 mrt->mroute_do_assert = v;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001760 }
1761 rtnl_unlock();
1762 return ret;
1763 }
1764
1765#endif
Patrick McHardyd1db2752010-05-11 14:40:55 +02001766#ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
1767 case MRT6_TABLE:
1768 {
1769 u32 v;
1770
1771 if (optlen != sizeof(u32))
1772 return -EINVAL;
1773 if (get_user(v, (u32 __user *)optval))
1774 return -EFAULT;
Dan Carpenter75356a82013-01-23 20:38:34 +00001775 /* "pim6reg%u" should not exceed 16 bytes (IFNAMSIZ) */
1776 if (v != RT_TABLE_DEFAULT && v >= 100000000)
1777 return -EINVAL;
Yuval Mintzb70432f2018-02-28 23:29:32 +02001778 if (sk == rcu_access_pointer(mrt->mroute_sk))
Patrick McHardyd1db2752010-05-11 14:40:55 +02001779 return -EBUSY;
1780
1781 rtnl_lock();
1782 ret = 0;
Sabrina Dubrocae783bb02018-06-05 15:02:00 +02001783 mrt = ip6mr_new_table(net, v);
1784 if (IS_ERR(mrt))
1785 ret = PTR_ERR(mrt);
Sabrina Dubroca848235e2018-06-05 15:01:59 +02001786 else
1787 raw6_sk(sk)->ip6mr_table = v;
Patrick McHardyd1db2752010-05-11 14:40:55 +02001788 rtnl_unlock();
1789 return ret;
1790 }
1791#endif
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001792 /*
Rami Rosen7d120c52008-04-23 14:35:13 +03001793 * Spurious command, or MRT6_VERSION which you cannot
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001794 * set.
1795 */
1796 default:
1797 return -ENOPROTOOPT;
1798 }
1799}
1800
1801/*
1802 * Getsock opt support for the multicast routing system.
1803 */
1804
1805int ip6_mroute_getsockopt(struct sock *sk, int optname, char __user *optval,
1806 int __user *optlen)
1807{
1808 int olr;
1809 int val;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001810 struct net *net = sock_net(sk);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001811 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +02001812
Xin Long99253eb2017-02-24 16:29:06 +08001813 if (sk->sk_type != SOCK_RAW ||
1814 inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
1815 return -EOPNOTSUPP;
1816
Patrick McHardyd1db2752010-05-11 14:40:55 +02001817 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +01001818 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +02001819 return -ENOENT;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001820
1821 switch (optname) {
1822 case MRT6_VERSION:
1823 val = 0x0305;
1824 break;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001825#ifdef CONFIG_IPV6_PIMSM_V2
1826 case MRT6_PIM:
Patrick McHardy6bd52142010-05-11 14:40:53 +02001827 val = mrt->mroute_do_pim;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001828 break;
1829#endif
1830 case MRT6_ASSERT:
Patrick McHardy6bd52142010-05-11 14:40:53 +02001831 val = mrt->mroute_do_assert;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001832 break;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001833 default:
1834 return -ENOPROTOOPT;
1835 }
1836
1837 if (get_user(olr, optlen))
1838 return -EFAULT;
1839
1840 olr = min_t(int, olr, sizeof(int));
1841 if (olr < 0)
1842 return -EINVAL;
1843
1844 if (put_user(olr, optlen))
1845 return -EFAULT;
1846 if (copy_to_user(optval, &val, olr))
1847 return -EFAULT;
1848 return 0;
1849}
1850
1851/*
1852 * The IP multicast ioctl support routines.
1853 */
1854
1855int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg)
1856{
1857 struct sioc_sg_req6 sr;
1858 struct sioc_mif_req6 vr;
Yuval Mintz6853f212018-02-28 23:29:29 +02001859 struct vif_device *vif;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001860 struct mfc6_cache *c;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001861 struct net *net = sock_net(sk);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001862 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +02001863
1864 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +01001865 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +02001866 return -ENOENT;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001867
1868 switch (cmd) {
1869 case SIOCGETMIFCNT_IN6:
1870 if (copy_from_user(&vr, arg, sizeof(vr)))
1871 return -EFAULT;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001872 if (vr.mifi >= mrt->maxvif)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001873 return -EINVAL;
Gustavo A. R. Silva69d2c862018-12-11 14:10:08 -06001874 vr.mifi = array_index_nospec(vr.mifi, mrt->maxvif);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001875 read_lock(&mrt_lock);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001876 vif = &mrt->vif_table[vr.mifi];
1877 if (VIF_EXISTS(mrt, vr.mifi)) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001878 vr.icount = vif->pkt_in;
1879 vr.ocount = vif->pkt_out;
1880 vr.ibytes = vif->bytes_in;
1881 vr.obytes = vif->bytes_out;
1882 read_unlock(&mrt_lock);
1883
1884 if (copy_to_user(arg, &vr, sizeof(vr)))
1885 return -EFAULT;
1886 return 0;
1887 }
1888 read_unlock(&mrt_lock);
1889 return -EADDRNOTAVAIL;
1890 case SIOCGETSGCNT_IN6:
1891 if (copy_from_user(&sr, arg, sizeof(sr)))
1892 return -EFAULT;
1893
Yuval Mintz87c418b2018-02-28 23:29:31 +02001894 rcu_read_lock();
Patrick McHardy6bd52142010-05-11 14:40:53 +02001895 c = ip6mr_cache_find(mrt, &sr.src.sin6_addr, &sr.grp.sin6_addr);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001896 if (c) {
Yuval Mintz494fff52018-02-28 23:29:34 +02001897 sr.pktcnt = c->_c.mfc_un.res.pkt;
1898 sr.bytecnt = c->_c.mfc_un.res.bytes;
1899 sr.wrong_if = c->_c.mfc_un.res.wrong_if;
Yuval Mintz87c418b2018-02-28 23:29:31 +02001900 rcu_read_unlock();
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001901
1902 if (copy_to_user(arg, &sr, sizeof(sr)))
1903 return -EFAULT;
1904 return 0;
1905 }
Yuval Mintz87c418b2018-02-28 23:29:31 +02001906 rcu_read_unlock();
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001907 return -EADDRNOTAVAIL;
1908 default:
1909 return -ENOIOCTLCMD;
1910 }
1911}
1912
David S. Millere2d57762011-02-03 17:59:32 -08001913#ifdef CONFIG_COMPAT
1914struct compat_sioc_sg_req6 {
1915 struct sockaddr_in6 src;
1916 struct sockaddr_in6 grp;
1917 compat_ulong_t pktcnt;
1918 compat_ulong_t bytecnt;
1919 compat_ulong_t wrong_if;
1920};
1921
1922struct compat_sioc_mif_req6 {
1923 mifi_t mifi;
1924 compat_ulong_t icount;
1925 compat_ulong_t ocount;
1926 compat_ulong_t ibytes;
1927 compat_ulong_t obytes;
1928};
1929
1930int ip6mr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg)
1931{
1932 struct compat_sioc_sg_req6 sr;
1933 struct compat_sioc_mif_req6 vr;
Yuval Mintz6853f212018-02-28 23:29:29 +02001934 struct vif_device *vif;
David S. Millere2d57762011-02-03 17:59:32 -08001935 struct mfc6_cache *c;
1936 struct net *net = sock_net(sk);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001937 struct mr_table *mrt;
David S. Millere2d57762011-02-03 17:59:32 -08001938
1939 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +01001940 if (!mrt)
David S. Millere2d57762011-02-03 17:59:32 -08001941 return -ENOENT;
1942
1943 switch (cmd) {
1944 case SIOCGETMIFCNT_IN6:
1945 if (copy_from_user(&vr, arg, sizeof(vr)))
1946 return -EFAULT;
1947 if (vr.mifi >= mrt->maxvif)
1948 return -EINVAL;
Gustavo A. R. Silva69d2c862018-12-11 14:10:08 -06001949 vr.mifi = array_index_nospec(vr.mifi, mrt->maxvif);
David S. Millere2d57762011-02-03 17:59:32 -08001950 read_lock(&mrt_lock);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001951 vif = &mrt->vif_table[vr.mifi];
1952 if (VIF_EXISTS(mrt, vr.mifi)) {
David S. Millere2d57762011-02-03 17:59:32 -08001953 vr.icount = vif->pkt_in;
1954 vr.ocount = vif->pkt_out;
1955 vr.ibytes = vif->bytes_in;
1956 vr.obytes = vif->bytes_out;
1957 read_unlock(&mrt_lock);
1958
1959 if (copy_to_user(arg, &vr, sizeof(vr)))
1960 return -EFAULT;
1961 return 0;
1962 }
1963 read_unlock(&mrt_lock);
1964 return -EADDRNOTAVAIL;
1965 case SIOCGETSGCNT_IN6:
1966 if (copy_from_user(&sr, arg, sizeof(sr)))
1967 return -EFAULT;
1968
Yuval Mintz87c418b2018-02-28 23:29:31 +02001969 rcu_read_lock();
David S. Millere2d57762011-02-03 17:59:32 -08001970 c = ip6mr_cache_find(mrt, &sr.src.sin6_addr, &sr.grp.sin6_addr);
1971 if (c) {
Yuval Mintz494fff52018-02-28 23:29:34 +02001972 sr.pktcnt = c->_c.mfc_un.res.pkt;
1973 sr.bytecnt = c->_c.mfc_un.res.bytes;
1974 sr.wrong_if = c->_c.mfc_un.res.wrong_if;
Yuval Mintz87c418b2018-02-28 23:29:31 +02001975 rcu_read_unlock();
David S. Millere2d57762011-02-03 17:59:32 -08001976
1977 if (copy_to_user(arg, &sr, sizeof(sr)))
1978 return -EFAULT;
1979 return 0;
1980 }
Yuval Mintz87c418b2018-02-28 23:29:31 +02001981 rcu_read_unlock();
David S. Millere2d57762011-02-03 17:59:32 -08001982 return -EADDRNOTAVAIL;
1983 default:
1984 return -ENOIOCTLCMD;
1985 }
1986}
1987#endif
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001988
Eric W. Biederman0c4b51f2015-09-15 20:04:18 -05001989static inline int ip6mr_forward2_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001990{
Ido Schimmel87c11f12019-03-03 07:34:57 +00001991 IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
1992 IPSTATS_MIB_OUTFORWDATAGRAMS);
1993 IP6_ADD_STATS(net, ip6_dst_idev(skb_dst(skb)),
1994 IPSTATS_MIB_OUTOCTETS, skb->len);
Eric W. Biederman13206b62015-10-07 16:48:35 -05001995 return dst_output(net, sk, skb);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001996}
1997
1998/*
1999 * Processing handlers for ip6mr_forward
2000 */
2001
Yuval Mintzb70432f2018-02-28 23:29:32 +02002002static int ip6mr_forward2(struct net *net, struct mr_table *mrt,
David Ahernf5c6dfd2018-12-17 15:36:11 -08002003 struct sk_buff *skb, int vifi)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002004{
2005 struct ipv6hdr *ipv6h;
Yuval Mintzb70432f2018-02-28 23:29:32 +02002006 struct vif_device *vif = &mrt->vif_table[vifi];
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002007 struct net_device *dev;
2008 struct dst_entry *dst;
David S. Miller4c9483b2011-03-12 16:22:43 -05002009 struct flowi6 fl6;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002010
Ian Morris63159f22015-03-29 14:00:04 +01002011 if (!vif->dev)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002012 goto out_free;
2013
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002014#ifdef CONFIG_IPV6_PIMSM_V2
2015 if (vif->flags & MIFF_REGISTER) {
2016 vif->pkt_out++;
2017 vif->bytes_out += skb->len;
Pavel Emelyanovdc58c782008-05-21 14:17:54 -07002018 vif->dev->stats.tx_bytes += skb->len;
2019 vif->dev->stats.tx_packets++;
Patrick McHardy6bd52142010-05-11 14:40:53 +02002020 ip6mr_cache_report(mrt, skb, vifi, MRT6MSG_WHOLEPKT);
Ilpo Järvinen8da73b72008-12-14 23:15:49 -08002021 goto out_free;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002022 }
2023#endif
2024
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002025 ipv6h = ipv6_hdr(skb);
2026
David S. Miller4c9483b2011-03-12 16:22:43 -05002027 fl6 = (struct flowi6) {
2028 .flowi6_oif = vif->link,
2029 .daddr = ipv6h->daddr,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002030 };
2031
David S. Miller4c9483b2011-03-12 16:22:43 -05002032 dst = ip6_route_output(net, NULL, &fl6);
RongQing.Li5095d642012-02-21 22:10:49 +00002033 if (dst->error) {
2034 dst_release(dst);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002035 goto out_free;
RongQing.Li5095d642012-02-21 22:10:49 +00002036 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002037
Eric Dumazetadf30902009-06-02 05:19:30 +00002038 skb_dst_drop(skb);
2039 skb_dst_set(skb, dst);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002040
2041 /*
2042 * RFC1584 teaches, that DVMRP/PIM router must deliver packets locally
2043 * not only before forwarding, but after forwarding on all output
2044 * interfaces. It is clear, if mrouter runs a multicasting
2045 * program, it should receive packets not depending to what interface
2046 * program is joined.
2047 * If we will not make it, the program will have to join on all
2048 * interfaces. On the other hand, multihoming host (or router, but
2049 * not mrouter) cannot join to more than one interface - it will
2050 * result in receiving multiple packets.
2051 */
2052 dev = vif->dev;
2053 skb->dev = dev;
2054 vif->pkt_out++;
2055 vif->bytes_out += skb->len;
2056
2057 /* We are about to write */
2058 /* XXX: extension headers? */
2059 if (skb_cow(skb, sizeof(*ipv6h) + LL_RESERVED_SPACE(dev)))
2060 goto out_free;
2061
2062 ipv6h = ipv6_hdr(skb);
2063 ipv6h->hop_limit--;
2064
2065 IP6CB(skb)->flags |= IP6SKB_FORWARDED;
2066
Eric W. Biederman29a26a52015-09-15 20:04:16 -05002067 return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD,
2068 net, NULL, skb, skb->dev, dev,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002069 ip6mr_forward2_finish);
2070
2071out_free:
2072 kfree_skb(skb);
2073 return 0;
2074}
2075
Yuval Mintzb70432f2018-02-28 23:29:32 +02002076static int ip6mr_find_vif(struct mr_table *mrt, struct net_device *dev)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002077{
2078 int ct;
Patrick McHardy6bd52142010-05-11 14:40:53 +02002079
2080 for (ct = mrt->maxvif - 1; ct >= 0; ct--) {
Yuval Mintzb70432f2018-02-28 23:29:32 +02002081 if (mrt->vif_table[ct].dev == dev)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002082 break;
2083 }
2084 return ct;
2085}
2086
Yuval Mintzb70432f2018-02-28 23:29:32 +02002087static void ip6_mr_forward(struct net *net, struct mr_table *mrt,
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002088 struct net_device *dev, struct sk_buff *skb,
2089 struct mfc6_cache *c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002090{
2091 int psend = -1;
2092 int vif, ct;
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002093 int true_vifi = ip6mr_find_vif(mrt, dev);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002094
Yuval Mintz494fff52018-02-28 23:29:34 +02002095 vif = c->_c.mfc_parent;
2096 c->_c.mfc_un.res.pkt++;
2097 c->_c.mfc_un.res.bytes += skb->len;
2098 c->_c.mfc_un.res.lastuse = jiffies;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002099
Yuval Mintz494fff52018-02-28 23:29:34 +02002100 if (ipv6_addr_any(&c->mf6c_origin) && true_vifi >= 0) {
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002101 struct mfc6_cache *cache_proxy;
2102
Fabian Frederick40dc2ca2014-10-29 10:00:26 +01002103 /* For an (*,G) entry, we only check that the incoming
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002104 * interface is part of the static tree.
2105 */
Yuval Mintz87c418b2018-02-28 23:29:31 +02002106 rcu_read_lock();
Yuval Mintz845c9a72018-02-28 23:29:35 +02002107 cache_proxy = mr_mfc_find_any_parent(mrt, vif);
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002108 if (cache_proxy &&
Yuval Mintz494fff52018-02-28 23:29:34 +02002109 cache_proxy->_c.mfc_un.res.ttls[true_vifi] < 255) {
Yuval Mintz87c418b2018-02-28 23:29:31 +02002110 rcu_read_unlock();
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002111 goto forward;
Yuval Mintz87c418b2018-02-28 23:29:31 +02002112 }
2113 rcu_read_unlock();
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002114 }
2115
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002116 /*
2117 * Wrong interface: drop packet and (maybe) send PIM assert.
2118 */
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002119 if (mrt->vif_table[vif].dev != dev) {
Yuval Mintz494fff52018-02-28 23:29:34 +02002120 c->_c.mfc_un.res.wrong_if++;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002121
Patrick McHardy6bd52142010-05-11 14:40:53 +02002122 if (true_vifi >= 0 && mrt->mroute_do_assert &&
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002123 /* pimsm uses asserts, when switching from RPT to SPT,
2124 so that we cannot check that packet arrived on an oif.
2125 It is bad, but otherwise we would need to move pretty
2126 large chunk of pimd to kernel. Ough... --ANK
2127 */
Patrick McHardy6bd52142010-05-11 14:40:53 +02002128 (mrt->mroute_do_pim ||
Yuval Mintz494fff52018-02-28 23:29:34 +02002129 c->_c.mfc_un.res.ttls[true_vifi] < 255) &&
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002130 time_after(jiffies,
Yuval Mintz494fff52018-02-28 23:29:34 +02002131 c->_c.mfc_un.res.last_assert +
2132 MFC_ASSERT_THRESH)) {
2133 c->_c.mfc_un.res.last_assert = jiffies;
Patrick McHardy6bd52142010-05-11 14:40:53 +02002134 ip6mr_cache_report(mrt, skb, true_vifi, MRT6MSG_WRONGMIF);
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002135 }
2136 goto dont_forward;
2137 }
2138
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002139forward:
Yuval Mintzb70432f2018-02-28 23:29:32 +02002140 mrt->vif_table[vif].pkt_in++;
2141 mrt->vif_table[vif].bytes_in += skb->len;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002142
2143 /*
2144 * Forward the frame
2145 */
Yuval Mintz494fff52018-02-28 23:29:34 +02002146 if (ipv6_addr_any(&c->mf6c_origin) &&
2147 ipv6_addr_any(&c->mf6c_mcastgrp)) {
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002148 if (true_vifi >= 0 &&
Yuval Mintz494fff52018-02-28 23:29:34 +02002149 true_vifi != c->_c.mfc_parent &&
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002150 ipv6_hdr(skb)->hop_limit >
Yuval Mintz494fff52018-02-28 23:29:34 +02002151 c->_c.mfc_un.res.ttls[c->_c.mfc_parent]) {
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002152 /* It's an (*,*) entry and the packet is not coming from
2153 * the upstream: forward the packet to the upstream
2154 * only.
2155 */
Yuval Mintz494fff52018-02-28 23:29:34 +02002156 psend = c->_c.mfc_parent;
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002157 goto last_forward;
2158 }
2159 goto dont_forward;
2160 }
Yuval Mintz494fff52018-02-28 23:29:34 +02002161 for (ct = c->_c.mfc_un.res.maxvif - 1;
2162 ct >= c->_c.mfc_un.res.minvif; ct--) {
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002163 /* For (*,G) entry, don't forward to the incoming interface */
Yuval Mintz494fff52018-02-28 23:29:34 +02002164 if ((!ipv6_addr_any(&c->mf6c_origin) || ct != true_vifi) &&
2165 ipv6_hdr(skb)->hop_limit > c->_c.mfc_un.res.ttls[ct]) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002166 if (psend != -1) {
2167 struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
2168 if (skb2)
David Ahernf5c6dfd2018-12-17 15:36:11 -08002169 ip6mr_forward2(net, mrt, skb2, psend);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002170 }
2171 psend = ct;
2172 }
2173 }
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002174last_forward:
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002175 if (psend != -1) {
David Ahernf5c6dfd2018-12-17 15:36:11 -08002176 ip6mr_forward2(net, mrt, skb, psend);
Rami Rosen2b52c3a2013-07-21 03:00:31 +03002177 return;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002178 }
2179
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002180dont_forward:
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002181 kfree_skb(skb);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002182}
2183
2184
2185/*
2186 * Multicast packets for forwarding arrive here
2187 */
2188
2189int ip6_mr_input(struct sk_buff *skb)
2190{
2191 struct mfc6_cache *cache;
Benjamin Thery8229efd2008-12-10 16:30:15 -08002192 struct net *net = dev_net(skb->dev);
Yuval Mintzb70432f2018-02-28 23:29:32 +02002193 struct mr_table *mrt;
David S. Miller4c9483b2011-03-12 16:22:43 -05002194 struct flowi6 fl6 = {
2195 .flowi6_iif = skb->dev->ifindex,
2196 .flowi6_mark = skb->mark,
Patrick McHardyd1db2752010-05-11 14:40:55 +02002197 };
2198 int err;
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002199 struct net_device *dev;
2200
2201 /* skb->dev passed in is the master dev for vrfs.
2202 * Get the proper interface that does have a vif associated with it.
2203 */
2204 dev = skb->dev;
2205 if (netif_is_l3_master(skb->dev)) {
2206 dev = dev_get_by_index_rcu(net, IPCB(skb)->iif);
2207 if (!dev) {
2208 kfree_skb(skb);
2209 return -ENODEV;
2210 }
2211 }
Patrick McHardyd1db2752010-05-11 14:40:55 +02002212
David S. Miller4c9483b2011-03-12 16:22:43 -05002213 err = ip6mr_fib_lookup(net, &fl6, &mrt);
Ben Greear2015de52011-09-27 15:16:08 -04002214 if (err < 0) {
2215 kfree_skb(skb);
Patrick McHardyd1db2752010-05-11 14:40:55 +02002216 return err;
Ben Greear2015de52011-09-27 15:16:08 -04002217 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002218
2219 read_lock(&mrt_lock);
Patrick McHardy6bd52142010-05-11 14:40:53 +02002220 cache = ip6mr_cache_find(mrt,
Benjamin Thery8229efd2008-12-10 16:30:15 -08002221 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr);
Ian Morris63159f22015-03-29 14:00:04 +01002222 if (!cache) {
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002223 int vif = ip6mr_find_vif(mrt, dev);
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002224
2225 if (vif >= 0)
2226 cache = ip6mr_cache_find_any(mrt,
2227 &ipv6_hdr(skb)->daddr,
2228 vif);
2229 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002230
2231 /*
2232 * No usable cache entry
2233 */
Ian Morris63159f22015-03-29 14:00:04 +01002234 if (!cache) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002235 int vif;
2236
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002237 vif = ip6mr_find_vif(mrt, dev);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002238 if (vif >= 0) {
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002239 int err = ip6mr_cache_unresolved(mrt, vif, skb, dev);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002240 read_unlock(&mrt_lock);
2241
2242 return err;
2243 }
2244 read_unlock(&mrt_lock);
2245 kfree_skb(skb);
2246 return -ENODEV;
2247 }
2248
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002249 ip6_mr_forward(net, mrt, dev, skb, cache);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002250
2251 read_unlock(&mrt_lock);
2252
2253 return 0;
2254}
2255
Nikolay Aleksandrov2cf75072016-09-25 23:08:31 +02002256int ip6mr_get_route(struct net *net, struct sk_buff *skb, struct rtmsg *rtm,
David Ahernfd61c6b2017-01-17 15:51:07 -08002257 u32 portid)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002258{
2259 int err;
Yuval Mintzb70432f2018-02-28 23:29:32 +02002260 struct mr_table *mrt;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002261 struct mfc6_cache *cache;
Eric Dumazetadf30902009-06-02 05:19:30 +00002262 struct rt6_info *rt = (struct rt6_info *)skb_dst(skb);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002263
Patrick McHardyd1db2752010-05-11 14:40:55 +02002264 mrt = ip6mr_get_table(net, RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +01002265 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +02002266 return -ENOENT;
2267
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002268 read_lock(&mrt_lock);
Patrick McHardy6bd52142010-05-11 14:40:53 +02002269 cache = ip6mr_cache_find(mrt, &rt->rt6i_src.addr, &rt->rt6i_dst.addr);
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002270 if (!cache && skb->dev) {
2271 int vif = ip6mr_find_vif(mrt, skb->dev);
2272
2273 if (vif >= 0)
2274 cache = ip6mr_cache_find_any(mrt, &rt->rt6i_dst.addr,
2275 vif);
2276 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002277
2278 if (!cache) {
2279 struct sk_buff *skb2;
2280 struct ipv6hdr *iph;
2281 struct net_device *dev;
2282 int vif;
2283
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002284 dev = skb->dev;
Ian Morris63159f22015-03-29 14:00:04 +01002285 if (!dev || (vif = ip6mr_find_vif(mrt, dev)) < 0) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002286 read_unlock(&mrt_lock);
2287 return -ENODEV;
2288 }
2289
2290 /* really correct? */
2291 skb2 = alloc_skb(sizeof(struct ipv6hdr), GFP_ATOMIC);
2292 if (!skb2) {
2293 read_unlock(&mrt_lock);
2294 return -ENOMEM;
2295 }
2296
Nikolay Aleksandrov2cf75072016-09-25 23:08:31 +02002297 NETLINK_CB(skb2).portid = portid;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002298 skb_reset_transport_header(skb2);
2299
2300 skb_put(skb2, sizeof(struct ipv6hdr));
2301 skb_reset_network_header(skb2);
2302
2303 iph = ipv6_hdr(skb2);
2304 iph->version = 0;
2305 iph->priority = 0;
2306 iph->flow_lbl[0] = 0;
2307 iph->flow_lbl[1] = 0;
2308 iph->flow_lbl[2] = 0;
2309 iph->payload_len = 0;
2310 iph->nexthdr = IPPROTO_NONE;
2311 iph->hop_limit = 0;
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +00002312 iph->saddr = rt->rt6i_src.addr;
2313 iph->daddr = rt->rt6i_dst.addr;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002314
Patrick Ruddye4a38c02018-10-01 09:41:27 +01002315 err = ip6mr_cache_unresolved(mrt, vif, skb2, dev);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002316 read_unlock(&mrt_lock);
2317
2318 return err;
2319 }
2320
Yuval Mintz7b0db852018-02-28 23:29:39 +02002321 err = mr_fill_mroute(mrt, skb, &cache->_c, rtm);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002322 read_unlock(&mrt_lock);
2323 return err;
2324}
2325
Yuval Mintzb70432f2018-02-28 23:29:32 +02002326static int ip6mr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
Nicolas Dichtelf5183382014-03-19 17:47:51 +01002327 u32 portid, u32 seq, struct mfc6_cache *c, int cmd,
2328 int flags)
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002329{
2330 struct nlmsghdr *nlh;
2331 struct rtmsg *rtm;
Nicolas Dichtel1eb99af2012-12-04 01:13:39 +00002332 int err;
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002333
Nicolas Dichtelf5183382014-03-19 17:47:51 +01002334 nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rtm), flags);
Ian Morris63159f22015-03-29 14:00:04 +01002335 if (!nlh)
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002336 return -EMSGSIZE;
2337
2338 rtm = nlmsg_data(nlh);
Nicolas Dichtel193c1e42012-12-04 01:01:49 +00002339 rtm->rtm_family = RTNL_FAMILY_IP6MR;
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002340 rtm->rtm_dst_len = 128;
2341 rtm->rtm_src_len = 128;
2342 rtm->rtm_tos = 0;
2343 rtm->rtm_table = mrt->id;
David S. Millerc78679e2012-04-01 20:27:33 -04002344 if (nla_put_u32(skb, RTA_TABLE, mrt->id))
2345 goto nla_put_failure;
Nicolas Dichtel1eb99af2012-12-04 01:13:39 +00002346 rtm->rtm_type = RTN_MULTICAST;
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002347 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
Yuval Mintz494fff52018-02-28 23:29:34 +02002348 if (c->_c.mfc_flags & MFC_STATIC)
Nicolas Dichtel9a68ac72012-12-04 01:13:38 +00002349 rtm->rtm_protocol = RTPROT_STATIC;
2350 else
2351 rtm->rtm_protocol = RTPROT_MROUTED;
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002352 rtm->rtm_flags = 0;
2353
Jiri Benc930345e2015-03-29 16:59:25 +02002354 if (nla_put_in6_addr(skb, RTA_SRC, &c->mf6c_origin) ||
2355 nla_put_in6_addr(skb, RTA_DST, &c->mf6c_mcastgrp))
David S. Millerc78679e2012-04-01 20:27:33 -04002356 goto nla_put_failure;
Yuval Mintz7b0db852018-02-28 23:29:39 +02002357 err = mr_fill_mroute(mrt, skb, &c->_c, rtm);
Nicolas Dichtel1eb99af2012-12-04 01:13:39 +00002358 /* do not break the dump if cache is unresolved */
2359 if (err < 0 && err != -ENOENT)
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002360 goto nla_put_failure;
2361
Johannes Berg053c0952015-01-16 22:09:00 +01002362 nlmsg_end(skb, nlh);
2363 return 0;
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002364
2365nla_put_failure:
2366 nlmsg_cancel(skb, nlh);
2367 return -EMSGSIZE;
2368}
2369
Yuval Mintz7b0db852018-02-28 23:29:39 +02002370static int _ip6mr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
2371 u32 portid, u32 seq, struct mr_mfc *c,
2372 int cmd, int flags)
2373{
2374 return ip6mr_fill_mroute(mrt, skb, portid, seq, (struct mfc6_cache *)c,
2375 cmd, flags);
2376}
2377
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002378static int mr6_msgsize(bool unresolved, int maxvif)
2379{
2380 size_t len =
2381 NLMSG_ALIGN(sizeof(struct rtmsg))
2382 + nla_total_size(4) /* RTA_TABLE */
2383 + nla_total_size(sizeof(struct in6_addr)) /* RTA_SRC */
2384 + nla_total_size(sizeof(struct in6_addr)) /* RTA_DST */
2385 ;
2386
2387 if (!unresolved)
2388 len = len
2389 + nla_total_size(4) /* RTA_IIF */
2390 + nla_total_size(0) /* RTA_MULTIPATH */
2391 + maxvif * NLA_ALIGN(sizeof(struct rtnexthop))
2392 /* RTA_MFC_STATS */
Nicolas Dichtel3d6b66c2016-04-21 18:58:27 +02002393 + nla_total_size_64bit(sizeof(struct rta_mfc_stats))
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002394 ;
2395
2396 return len;
2397}
2398
Yuval Mintzb70432f2018-02-28 23:29:32 +02002399static void mr6_netlink_event(struct mr_table *mrt, struct mfc6_cache *mfc,
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002400 int cmd)
2401{
2402 struct net *net = read_pnet(&mrt->net);
2403 struct sk_buff *skb;
2404 int err = -ENOBUFS;
2405
Yuval Mintz494fff52018-02-28 23:29:34 +02002406 skb = nlmsg_new(mr6_msgsize(mfc->_c.mfc_parent >= MAXMIFS, mrt->maxvif),
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002407 GFP_ATOMIC);
Ian Morris63159f22015-03-29 14:00:04 +01002408 if (!skb)
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002409 goto errout;
2410
Nicolas Dichtelf5183382014-03-19 17:47:51 +01002411 err = ip6mr_fill_mroute(mrt, skb, 0, 0, mfc, cmd, 0);
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002412 if (err < 0)
2413 goto errout;
2414
2415 rtnl_notify(skb, net, 0, RTNLGRP_IPV6_MROUTE, NULL, GFP_ATOMIC);
2416 return;
2417
2418errout:
2419 kfree_skb(skb);
2420 if (err < 0)
2421 rtnl_set_sk_err(net, RTNLGRP_IPV6_MROUTE, err);
2422}
2423
Julien Gomesdd12d15c2017-06-20 13:54:18 -07002424static size_t mrt6msg_netlink_msgsize(size_t payloadlen)
2425{
2426 size_t len =
2427 NLMSG_ALIGN(sizeof(struct rtgenmsg))
2428 + nla_total_size(1) /* IP6MRA_CREPORT_MSGTYPE */
2429 + nla_total_size(4) /* IP6MRA_CREPORT_MIF_ID */
2430 /* IP6MRA_CREPORT_SRC_ADDR */
2431 + nla_total_size(sizeof(struct in6_addr))
2432 /* IP6MRA_CREPORT_DST_ADDR */
2433 + nla_total_size(sizeof(struct in6_addr))
2434 /* IP6MRA_CREPORT_PKT */
2435 + nla_total_size(payloadlen)
2436 ;
2437
2438 return len;
2439}
2440
Yuval Mintzb70432f2018-02-28 23:29:32 +02002441static void mrt6msg_netlink_event(struct mr_table *mrt, struct sk_buff *pkt)
Julien Gomesdd12d15c2017-06-20 13:54:18 -07002442{
2443 struct net *net = read_pnet(&mrt->net);
2444 struct nlmsghdr *nlh;
2445 struct rtgenmsg *rtgenm;
2446 struct mrt6msg *msg;
2447 struct sk_buff *skb;
2448 struct nlattr *nla;
2449 int payloadlen;
2450
2451 payloadlen = pkt->len - sizeof(struct mrt6msg);
2452 msg = (struct mrt6msg *)skb_transport_header(pkt);
2453
2454 skb = nlmsg_new(mrt6msg_netlink_msgsize(payloadlen), GFP_ATOMIC);
2455 if (!skb)
2456 goto errout;
2457
2458 nlh = nlmsg_put(skb, 0, 0, RTM_NEWCACHEREPORT,
2459 sizeof(struct rtgenmsg), 0);
2460 if (!nlh)
2461 goto errout;
2462 rtgenm = nlmsg_data(nlh);
2463 rtgenm->rtgen_family = RTNL_FAMILY_IP6MR;
2464 if (nla_put_u8(skb, IP6MRA_CREPORT_MSGTYPE, msg->im6_msgtype) ||
2465 nla_put_u32(skb, IP6MRA_CREPORT_MIF_ID, msg->im6_mif) ||
2466 nla_put_in6_addr(skb, IP6MRA_CREPORT_SRC_ADDR,
2467 &msg->im6_src) ||
2468 nla_put_in6_addr(skb, IP6MRA_CREPORT_DST_ADDR,
2469 &msg->im6_dst))
2470 goto nla_put_failure;
2471
2472 nla = nla_reserve(skb, IP6MRA_CREPORT_PKT, payloadlen);
2473 if (!nla || skb_copy_bits(pkt, sizeof(struct mrt6msg),
2474 nla_data(nla), payloadlen))
2475 goto nla_put_failure;
2476
2477 nlmsg_end(skb, nlh);
2478
2479 rtnl_notify(skb, net, 0, RTNLGRP_IPV6_MROUTE_R, NULL, GFP_ATOMIC);
2480 return;
2481
2482nla_put_failure:
2483 nlmsg_cancel(skb, nlh);
2484errout:
2485 kfree_skb(skb);
2486 rtnl_set_sk_err(net, RTNLGRP_IPV6_MROUTE_R, -ENOBUFS);
2487}
2488
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002489static int ip6mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
2490{
David Aherne8ba3302018-10-07 20:16:35 -07002491 const struct nlmsghdr *nlh = cb->nlh;
David Ahern47246762018-10-15 18:56:42 -07002492 struct fib_dump_filter filter = {};
David Aherncb167892018-10-15 18:56:47 -07002493 int err;
David Aherne8ba3302018-10-07 20:16:35 -07002494
2495 if (cb->strict_check) {
David Ahern47246762018-10-15 18:56:42 -07002496 err = ip_valid_fib_dump_req(sock_net(skb->sk), nlh,
David Aherneffe6792018-10-15 18:56:48 -07002497 &filter, cb);
David Aherne8ba3302018-10-07 20:16:35 -07002498 if (err < 0)
2499 return err;
2500 }
2501
David Aherncb167892018-10-15 18:56:47 -07002502 if (filter.table_id) {
2503 struct mr_table *mrt;
2504
2505 mrt = ip6mr_get_table(sock_net(skb->sk), filter.table_id);
2506 if (!mrt) {
David Ahernae677bb2018-10-24 12:59:01 -07002507 if (filter.dump_all_families)
2508 return skb->len;
2509
David Aherncb167892018-10-15 18:56:47 -07002510 NL_SET_ERR_MSG_MOD(cb->extack, "MR table does not exist");
2511 return -ENOENT;
2512 }
2513 err = mr_table_dump(mrt, skb, cb, _ip6mr_fill_mroute,
2514 &mfc_unres_lock, &filter);
2515 return skb->len ? : err;
2516 }
2517
Yuval Mintz7b0db852018-02-28 23:29:39 +02002518 return mr_rtm_dumproute(skb, cb, ip6mr_mr_table_iter,
David Aherncb167892018-10-15 18:56:47 -07002519 _ip6mr_fill_mroute, &mfc_unres_lock, &filter);
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002520}