blob: 298fd8b6ed17fa1ce95c6a1b2b831bf68201671a [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>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090035#include <net/protocol.h>
36#include <linux/skbuff.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090037#include <net/raw.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090038#include <linux/notifier.h>
39#include <linux/if_arp.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090040#include <net/checksum.h>
41#include <net/netlink.h>
Patrick McHardyd1db2752010-05-11 14:40:55 +020042#include <net/fib_rules.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090043
44#include <net/ipv6.h>
45#include <net/ip6_route.h>
46#include <linux/mroute6.h>
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +090047#include <linux/pim.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090048#include <net/addrconf.h>
49#include <linux/netfilter_ipv6.h>
Paul Gortmakerbc3b2d72011-07-15 11:47:34 -040050#include <linux/export.h>
Dave Jones5d6e4302009-01-31 00:51:49 -080051#include <net/ip6_checksum.h>
Nicolas Dichteld67b8c62012-12-04 01:13:35 +000052#include <linux/netconf.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090053
Patrick McHardyd1db2752010-05-11 14:40:55 +020054struct ip6mr_rule {
55 struct fib_rule common;
56};
57
58struct ip6mr_result {
Yuval Mintzb70432f2018-02-28 23:29:32 +020059 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +020060};
61
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090062/* Big lock, protecting vif table, mrt cache and mroute socket state.
63 Note that the changes are semaphored via rtnl_lock.
64 */
65
66static DEFINE_RWLOCK(mrt_lock);
67
Yuval Mintzb70432f2018-02-28 23:29:32 +020068/* Multicast router control variables */
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090069
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090070/* Special spinlock for queue of unresolved entries */
71static DEFINE_SPINLOCK(mfc_unres_lock);
72
73/* We return to original Alan's scheme. Hash table of resolved
74 entries is changed only in process context and protected
75 with weak lock mrt_lock. Queue of unresolved entries is protected
76 with strong spinlock mfc_unres_lock.
77
78 In this case data path is free of exclusive locks at all.
79 */
80
81static struct kmem_cache *mrt_cachep __read_mostly;
82
Yuval Mintzb70432f2018-02-28 23:29:32 +020083static struct mr_table *ip6mr_new_table(struct net *net, u32 id);
84static void ip6mr_free_table(struct mr_table *mrt);
Patrick McHardyd1db2752010-05-11 14:40:55 +020085
Yuval Mintzb70432f2018-02-28 23:29:32 +020086static void ip6_mr_forward(struct net *net, struct mr_table *mrt,
Rami Rosen2b52c3a2013-07-21 03:00:31 +030087 struct sk_buff *skb, struct mfc6_cache *cache);
Yuval Mintzb70432f2018-02-28 23:29:32 +020088static int ip6mr_cache_report(struct mr_table *mrt, struct sk_buff *pkt,
Benjamin Thery8229efd2008-12-10 16:30:15 -080089 mifi_t mifi, int assert);
Yuval Mintzb70432f2018-02-28 23:29:32 +020090static void mr6_netlink_event(struct mr_table *mrt, struct mfc6_cache *mfc,
Nicolas Dichtel812e44d2012-12-04 01:13:41 +000091 int cmd);
Yuval Mintzb70432f2018-02-28 23:29:32 +020092static void mrt6msg_netlink_event(struct mr_table *mrt, struct sk_buff *pkt);
Patrick McHardy5b285ca2010-05-11 14:40:56 +020093static int ip6mr_rtm_dumproute(struct sk_buff *skb,
94 struct netlink_callback *cb);
Yuval Mintzb70432f2018-02-28 23:29:32 +020095static void mroute_clean_tables(struct mr_table *mrt, bool all);
Kees Cooke99e88a2017-10-16 14:43:17 -070096static void ipmr_expire_process(struct timer_list *t);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090097
Patrick McHardyd1db2752010-05-11 14:40:55 +020098#ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
Eric Dumazet8ffb3352010-06-06 15:34:40 -070099#define ip6mr_for_each_table(mrt, net) \
Patrick McHardyd1db2752010-05-11 14:40:55 +0200100 list_for_each_entry_rcu(mrt, &net->ipv6.mr6_tables, list)
101
Yuval Mintz7b0db852018-02-28 23:29:39 +0200102static struct mr_table *ip6mr_mr_table_iter(struct net *net,
103 struct mr_table *mrt)
104{
105 struct mr_table *ret;
106
107 if (!mrt)
108 ret = list_entry_rcu(net->ipv6.mr6_tables.next,
109 struct mr_table, list);
110 else
111 ret = list_entry_rcu(mrt->list.next,
112 struct mr_table, list);
113
114 if (&ret->list == &net->ipv6.mr6_tables)
115 return NULL;
116 return ret;
117}
118
Yuval Mintzb70432f2018-02-28 23:29:32 +0200119static struct mr_table *ip6mr_get_table(struct net *net, u32 id)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200120{
Yuval Mintzb70432f2018-02-28 23:29:32 +0200121 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200122
123 ip6mr_for_each_table(mrt, net) {
124 if (mrt->id == id)
125 return mrt;
126 }
127 return NULL;
128}
129
David S. Miller4c9483b2011-03-12 16:22:43 -0500130static int ip6mr_fib_lookup(struct net *net, struct flowi6 *flp6,
Yuval Mintzb70432f2018-02-28 23:29:32 +0200131 struct mr_table **mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200132{
Patrick McHardyd1db2752010-05-11 14:40:55 +0200133 int err;
Hannes Frederic Sowa95f4a452014-01-13 02:45:22 +0100134 struct ip6mr_result res;
135 struct fib_lookup_arg arg = {
136 .result = &res,
137 .flags = FIB_LOOKUP_NOREF,
138 };
Patrick McHardyd1db2752010-05-11 14:40:55 +0200139
David S. Miller4c9483b2011-03-12 16:22:43 -0500140 err = fib_rules_lookup(net->ipv6.mr6_rules_ops,
141 flowi6_to_flowi(flp6), 0, &arg);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200142 if (err < 0)
143 return err;
144 *mrt = res.mrt;
145 return 0;
146}
147
148static int ip6mr_rule_action(struct fib_rule *rule, struct flowi *flp,
149 int flags, struct fib_lookup_arg *arg)
150{
151 struct ip6mr_result *res = arg->result;
Yuval Mintzb70432f2018-02-28 23:29:32 +0200152 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200153
154 switch (rule->action) {
155 case FR_ACT_TO_TBL:
156 break;
157 case FR_ACT_UNREACHABLE:
158 return -ENETUNREACH;
159 case FR_ACT_PROHIBIT:
160 return -EACCES;
161 case FR_ACT_BLACKHOLE:
162 default:
163 return -EINVAL;
164 }
165
166 mrt = ip6mr_get_table(rule->fr_net, rule->table);
Ian Morris63159f22015-03-29 14:00:04 +0100167 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200168 return -EAGAIN;
169 res->mrt = mrt;
170 return 0;
171}
172
173static int ip6mr_rule_match(struct fib_rule *rule, struct flowi *flp, int flags)
174{
175 return 1;
176}
177
178static const struct nla_policy ip6mr_rule_policy[FRA_MAX + 1] = {
179 FRA_GENERIC_POLICY,
180};
181
182static int ip6mr_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
183 struct fib_rule_hdr *frh, struct nlattr **tb)
184{
185 return 0;
186}
187
188static int ip6mr_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
189 struct nlattr **tb)
190{
191 return 1;
192}
193
194static int ip6mr_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
195 struct fib_rule_hdr *frh)
196{
197 frh->dst_len = 0;
198 frh->src_len = 0;
199 frh->tos = 0;
200 return 0;
201}
202
Andi Kleen04a6f822012-10-04 17:12:11 -0700203static const struct fib_rules_ops __net_initconst ip6mr_rules_ops_template = {
Patrick McHardyd1db2752010-05-11 14:40:55 +0200204 .family = RTNL_FAMILY_IP6MR,
205 .rule_size = sizeof(struct ip6mr_rule),
206 .addr_size = sizeof(struct in6_addr),
207 .action = ip6mr_rule_action,
208 .match = ip6mr_rule_match,
209 .configure = ip6mr_rule_configure,
210 .compare = ip6mr_rule_compare,
Patrick McHardyd1db2752010-05-11 14:40:55 +0200211 .fill = ip6mr_rule_fill,
212 .nlgroup = RTNLGRP_IPV6_RULE,
213 .policy = ip6mr_rule_policy,
214 .owner = THIS_MODULE,
215};
216
217static int __net_init ip6mr_rules_init(struct net *net)
218{
219 struct fib_rules_ops *ops;
Yuval Mintzb70432f2018-02-28 23:29:32 +0200220 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200221 int err;
222
223 ops = fib_rules_register(&ip6mr_rules_ops_template, net);
224 if (IS_ERR(ops))
225 return PTR_ERR(ops);
226
227 INIT_LIST_HEAD(&net->ipv6.mr6_tables);
228
229 mrt = ip6mr_new_table(net, RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +0100230 if (!mrt) {
Patrick McHardyd1db2752010-05-11 14:40:55 +0200231 err = -ENOMEM;
232 goto err1;
233 }
234
235 err = fib_default_rule_add(ops, 0x7fff, RT6_TABLE_DFLT, 0);
236 if (err < 0)
237 goto err2;
238
239 net->ipv6.mr6_rules_ops = ops;
240 return 0;
241
242err2:
WANG Congf243e5a2015-03-25 14:45:03 -0700243 ip6mr_free_table(mrt);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200244err1:
245 fib_rules_unregister(ops);
246 return err;
247}
248
249static void __net_exit ip6mr_rules_exit(struct net *net)
250{
Yuval Mintzb70432f2018-02-28 23:29:32 +0200251 struct mr_table *mrt, *next;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200252
Hannes Frederic Sowa905a6f92013-07-22 23:45:53 +0200253 rtnl_lock();
Eric Dumazet035320d2010-06-06 23:48:40 +0000254 list_for_each_entry_safe(mrt, next, &net->ipv6.mr6_tables, list) {
255 list_del(&mrt->list);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200256 ip6mr_free_table(mrt);
Eric Dumazet035320d2010-06-06 23:48:40 +0000257 }
Patrick McHardyd1db2752010-05-11 14:40:55 +0200258 fib_rules_unregister(net->ipv6.mr6_rules_ops);
WANG Cong419df122015-03-31 11:01:46 -0700259 rtnl_unlock();
Patrick McHardyd1db2752010-05-11 14:40:55 +0200260}
Yuval Mintz088aa3e2018-03-26 15:01:34 +0300261
262static int ip6mr_rules_dump(struct net *net, struct notifier_block *nb)
263{
264 return fib_rules_dump(net, nb, RTNL_FAMILY_IP6MR);
265}
266
267static unsigned int ip6mr_rules_seq_read(struct net *net)
268{
269 return fib_rules_seq_read(net, RTNL_FAMILY_IP6MR);
270}
Yuval Mintzd3c07e52018-03-26 15:01:35 +0300271
272bool ip6mr_rule_default(const struct fib_rule *rule)
273{
274 return fib_rule_matchall(rule) && rule->action == FR_ACT_TO_TBL &&
275 rule->table == RT6_TABLE_DFLT && !rule->l3mdev;
276}
277EXPORT_SYMBOL(ip6mr_rule_default);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200278#else
279#define ip6mr_for_each_table(mrt, net) \
280 for (mrt = net->ipv6.mrt6; mrt; mrt = NULL)
281
Yuval Mintz7b0db852018-02-28 23:29:39 +0200282static struct mr_table *ip6mr_mr_table_iter(struct net *net,
283 struct mr_table *mrt)
284{
285 if (!mrt)
286 return net->ipv6.mrt6;
287 return NULL;
288}
289
Yuval Mintzb70432f2018-02-28 23:29:32 +0200290static struct mr_table *ip6mr_get_table(struct net *net, u32 id)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200291{
292 return net->ipv6.mrt6;
293}
294
David S. Miller4c9483b2011-03-12 16:22:43 -0500295static int ip6mr_fib_lookup(struct net *net, struct flowi6 *flp6,
Yuval Mintzb70432f2018-02-28 23:29:32 +0200296 struct mr_table **mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200297{
298 *mrt = net->ipv6.mrt6;
299 return 0;
300}
301
302static int __net_init ip6mr_rules_init(struct net *net)
303{
304 net->ipv6.mrt6 = ip6mr_new_table(net, RT6_TABLE_DFLT);
305 return net->ipv6.mrt6 ? 0 : -ENOMEM;
306}
307
308static void __net_exit ip6mr_rules_exit(struct net *net)
309{
Hannes Frederic Sowa905a6f92013-07-22 23:45:53 +0200310 rtnl_lock();
Patrick McHardyd1db2752010-05-11 14:40:55 +0200311 ip6mr_free_table(net->ipv6.mrt6);
Hannes Frederic Sowa905a6f92013-07-22 23:45:53 +0200312 net->ipv6.mrt6 = NULL;
313 rtnl_unlock();
Patrick McHardyd1db2752010-05-11 14:40:55 +0200314}
Yuval Mintz088aa3e2018-03-26 15:01:34 +0300315
316static int ip6mr_rules_dump(struct net *net, struct notifier_block *nb)
317{
318 return 0;
319}
320
321static unsigned int ip6mr_rules_seq_read(struct net *net)
322{
323 return 0;
324}
Patrick McHardyd1db2752010-05-11 14:40:55 +0200325#endif
326
Yuval Mintz87c418b2018-02-28 23:29:31 +0200327static int ip6mr_hash_cmp(struct rhashtable_compare_arg *arg,
328 const void *ptr)
329{
330 const struct mfc6_cache_cmp_arg *cmparg = arg->key;
331 struct mfc6_cache *c = (struct mfc6_cache *)ptr;
332
333 return !ipv6_addr_equal(&c->mf6c_mcastgrp, &cmparg->mf6c_mcastgrp) ||
334 !ipv6_addr_equal(&c->mf6c_origin, &cmparg->mf6c_origin);
335}
336
337static const struct rhashtable_params ip6mr_rht_params = {
Yuval Mintz494fff52018-02-28 23:29:34 +0200338 .head_offset = offsetof(struct mr_mfc, mnode),
Yuval Mintz87c418b2018-02-28 23:29:31 +0200339 .key_offset = offsetof(struct mfc6_cache, cmparg),
340 .key_len = sizeof(struct mfc6_cache_cmp_arg),
341 .nelem_hint = 3,
342 .locks_mul = 1,
343 .obj_cmpfn = ip6mr_hash_cmp,
344 .automatic_shrinking = true,
345};
346
Yuval Mintz0bbbf0e2018-02-28 23:29:33 +0200347static void ip6mr_new_table_set(struct mr_table *mrt,
348 struct net *net)
349{
350#ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
351 list_add_tail_rcu(&mrt->list, &net->ipv6.mr6_tables);
352#endif
353}
354
Yuval Mintz845c9a72018-02-28 23:29:35 +0200355static struct mfc6_cache_cmp_arg ip6mr_mr_table_ops_cmparg_any = {
356 .mf6c_origin = IN6ADDR_ANY_INIT,
357 .mf6c_mcastgrp = IN6ADDR_ANY_INIT,
358};
359
360static struct mr_table_ops ip6mr_mr_table_ops = {
361 .rht_params = &ip6mr_rht_params,
362 .cmparg_any = &ip6mr_mr_table_ops_cmparg_any,
363};
364
Yuval Mintzb70432f2018-02-28 23:29:32 +0200365static struct mr_table *ip6mr_new_table(struct net *net, u32 id)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200366{
Yuval Mintzb70432f2018-02-28 23:29:32 +0200367 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200368
369 mrt = ip6mr_get_table(net, id);
Ian Morris53b24b82015-03-29 14:00:05 +0100370 if (mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200371 return mrt;
372
Yuval Mintz845c9a72018-02-28 23:29:35 +0200373 return mr_table_alloc(net, id, &ip6mr_mr_table_ops,
Yuval Mintz0bbbf0e2018-02-28 23:29:33 +0200374 ipmr_expire_process, ip6mr_new_table_set);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200375}
376
Yuval Mintzb70432f2018-02-28 23:29:32 +0200377static void ip6mr_free_table(struct mr_table *mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200378{
WANG Cong7ba0c472015-03-31 11:01:47 -0700379 del_timer_sync(&mrt->ipmr_expire_timer);
Nikolay Aleksandrov4c698042015-11-20 13:54:20 +0100380 mroute_clean_tables(mrt, true);
Yuval Mintzb70432f2018-02-28 23:29:32 +0200381 rhltable_destroy(&mrt->mfc_hash);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200382 kfree(mrt);
383}
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900384
385#ifdef CONFIG_PROC_FS
Yuval Mintzc8d61962018-02-28 23:29:36 +0200386/* The /proc interfaces to multicast routing
387 * /proc/ip6_mr_cache /proc/ip6_mr_vif
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900388 */
389
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900390static void *ip6mr_vif_seq_start(struct seq_file *seq, loff_t *pos)
391 __acquires(mrt_lock)
392{
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200393 struct mr_vif_iter *iter = seq->private;
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800394 struct net *net = seq_file_net(seq);
Yuval Mintzb70432f2018-02-28 23:29:32 +0200395 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200396
397 mrt = ip6mr_get_table(net, RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +0100398 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200399 return ERR_PTR(-ENOENT);
400
401 iter->mrt = mrt;
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800402
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900403 read_lock(&mrt_lock);
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200404 return mr_vif_seq_start(seq, pos);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900405}
406
407static void ip6mr_vif_seq_stop(struct seq_file *seq, void *v)
408 __releases(mrt_lock)
409{
410 read_unlock(&mrt_lock);
411}
412
413static int ip6mr_vif_seq_show(struct seq_file *seq, void *v)
414{
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200415 struct mr_vif_iter *iter = seq->private;
Yuval Mintzb70432f2018-02-28 23:29:32 +0200416 struct mr_table *mrt = iter->mrt;
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800417
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900418 if (v == SEQ_START_TOKEN) {
419 seq_puts(seq,
420 "Interface BytesIn PktsIn BytesOut PktsOut Flags\n");
421 } else {
Yuval Mintz6853f212018-02-28 23:29:29 +0200422 const struct vif_device *vif = v;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900423 const char *name = vif->dev ? vif->dev->name : "none";
424
425 seq_printf(seq,
Al Virod430a222008-06-02 10:59:02 +0100426 "%2td %-10s %8ld %7ld %8ld %7ld %05X\n",
Yuval Mintzb70432f2018-02-28 23:29:32 +0200427 vif - mrt->vif_table,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900428 name, vif->bytes_in, vif->pkt_in,
429 vif->bytes_out, vif->pkt_out,
430 vif->flags);
431 }
432 return 0;
433}
434
Stephen Hemminger98147d52009-09-01 19:25:02 +0000435static const struct seq_operations ip6mr_vif_seq_ops = {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900436 .start = ip6mr_vif_seq_start,
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200437 .next = mr_vif_seq_next,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900438 .stop = ip6mr_vif_seq_stop,
439 .show = ip6mr_vif_seq_show,
440};
441
442static int ip6mr_vif_open(struct inode *inode, struct file *file)
443{
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800444 return seq_open_net(inode, file, &ip6mr_vif_seq_ops,
Yuval Mintz3feda6b2018-02-28 23:29:37 +0200445 sizeof(struct mr_vif_iter));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900446}
447
Stephen Hemminger5ca1b992009-09-01 19:25:05 +0000448static const struct file_operations ip6mr_vif_fops = {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900449 .open = ip6mr_vif_open,
450 .read = seq_read,
451 .llseek = seq_lseek,
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800452 .release = seq_release_net,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900453};
454
455static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos)
456{
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800457 struct net *net = seq_file_net(seq);
Yuval Mintzb70432f2018-02-28 23:29:32 +0200458 struct mr_table *mrt;
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800459
Patrick McHardyd1db2752010-05-11 14:40:55 +0200460 mrt = ip6mr_get_table(net, RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +0100461 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200462 return ERR_PTR(-ENOENT);
463
Yuval Mintzc8d61962018-02-28 23:29:36 +0200464 return mr_mfc_seq_start(seq, pos, mrt, &mfc_unres_lock);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900465}
466
467static int ipmr_mfc_seq_show(struct seq_file *seq, void *v)
468{
469 int n;
470
471 if (v == SEQ_START_TOKEN) {
472 seq_puts(seq,
473 "Group "
474 "Origin "
475 "Iif Pkts Bytes Wrong Oifs\n");
476 } else {
477 const struct mfc6_cache *mfc = v;
Yuval Mintzc8d61962018-02-28 23:29:36 +0200478 const struct mr_mfc_iter *it = seq->private;
Yuval Mintzb70432f2018-02-28 23:29:32 +0200479 struct mr_table *mrt = it->mrt;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900480
Benjamin Thery999890b2008-12-03 22:22:16 -0800481 seq_printf(seq, "%pI6 %pI6 %-3hd",
Harvey Harrison0c6ce782008-10-28 16:09:23 -0700482 &mfc->mf6c_mcastgrp, &mfc->mf6c_origin,
Yuval Mintz494fff52018-02-28 23:29:34 +0200483 mfc->_c.mfc_parent);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900484
Yuval Mintzb70432f2018-02-28 23:29:32 +0200485 if (it->cache != &mrt->mfc_unres_queue) {
Benjamin Thery1ea472e2008-12-03 22:21:47 -0800486 seq_printf(seq, " %8lu %8lu %8lu",
Yuval Mintz494fff52018-02-28 23:29:34 +0200487 mfc->_c.mfc_un.res.pkt,
488 mfc->_c.mfc_un.res.bytes,
489 mfc->_c.mfc_un.res.wrong_if);
490 for (n = mfc->_c.mfc_un.res.minvif;
491 n < mfc->_c.mfc_un.res.maxvif; n++) {
Yuval Mintzb70432f2018-02-28 23:29:32 +0200492 if (VIF_EXISTS(mrt, n) &&
Yuval Mintz494fff52018-02-28 23:29:34 +0200493 mfc->_c.mfc_un.res.ttls[n] < 255)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900494 seq_printf(seq,
Yuval Mintz494fff52018-02-28 23:29:34 +0200495 " %2d:%-3d", n,
496 mfc->_c.mfc_un.res.ttls[n]);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900497 }
Benjamin Thery1ea472e2008-12-03 22:21:47 -0800498 } else {
499 /* unresolved mfc_caches don't contain
500 * pkt, bytes and wrong_if values
501 */
502 seq_printf(seq, " %8lu %8lu %8lu", 0ul, 0ul, 0ul);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900503 }
504 seq_putc(seq, '\n');
505 }
506 return 0;
507}
508
James Morris88e9d342009-09-22 16:43:43 -0700509static const struct seq_operations ipmr_mfc_seq_ops = {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900510 .start = ipmr_mfc_seq_start,
Yuval Mintzc8d61962018-02-28 23:29:36 +0200511 .next = mr_mfc_seq_next,
512 .stop = mr_mfc_seq_stop,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900513 .show = ipmr_mfc_seq_show,
514};
515
516static int ipmr_mfc_open(struct inode *inode, struct file *file)
517{
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800518 return seq_open_net(inode, file, &ipmr_mfc_seq_ops,
Yuval Mintzc8d61962018-02-28 23:29:36 +0200519 sizeof(struct mr_mfc_iter));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900520}
521
Stephen Hemminger5ca1b992009-09-01 19:25:05 +0000522static const struct file_operations ip6mr_mfc_fops = {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900523 .open = ipmr_mfc_open,
524 .read = seq_read,
525 .llseek = seq_lseek,
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800526 .release = seq_release_net,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900527};
528#endif
529
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900530#ifdef CONFIG_IPV6_PIMSM_V2
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900531
532static int pim6_rcv(struct sk_buff *skb)
533{
534 struct pimreghdr *pim;
535 struct ipv6hdr *encap;
536 struct net_device *reg_dev = NULL;
Benjamin Thery8229efd2008-12-10 16:30:15 -0800537 struct net *net = dev_net(skb->dev);
Yuval Mintzb70432f2018-02-28 23:29:32 +0200538 struct mr_table *mrt;
David S. Miller4c9483b2011-03-12 16:22:43 -0500539 struct flowi6 fl6 = {
540 .flowi6_iif = skb->dev->ifindex,
541 .flowi6_mark = skb->mark,
Patrick McHardyd1db2752010-05-11 14:40:55 +0200542 };
543 int reg_vif_num;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900544
545 if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(*encap)))
546 goto drop;
547
548 pim = (struct pimreghdr *)skb_transport_header(skb);
Nikolay Aleksandrov56245ca2016-10-31 13:21:04 +0100549 if (pim->type != ((PIM_VERSION << 4) | PIM_TYPE_REGISTER) ||
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900550 (pim->flags & PIM_NULL_REGISTER) ||
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800551 (csum_ipv6_magic(&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
552 sizeof(*pim), IPPROTO_PIM,
553 csum_partial((void *)pim, sizeof(*pim), 0)) &&
Al Viroec6b4862008-04-26 22:28:58 -0700554 csum_fold(skb_checksum(skb, 0, skb->len, 0))))
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900555 goto drop;
556
557 /* check if the inner packet is destined to mcast group */
558 encap = (struct ipv6hdr *)(skb_transport_header(skb) +
559 sizeof(*pim));
560
561 if (!ipv6_addr_is_multicast(&encap->daddr) ||
562 encap->payload_len == 0 ||
563 ntohs(encap->payload_len) + sizeof(*pim) > skb->len)
564 goto drop;
565
David S. Miller4c9483b2011-03-12 16:22:43 -0500566 if (ip6mr_fib_lookup(net, &fl6, &mrt) < 0)
Patrick McHardyd1db2752010-05-11 14:40:55 +0200567 goto drop;
568 reg_vif_num = mrt->mroute_reg_vif_num;
569
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900570 read_lock(&mrt_lock);
571 if (reg_vif_num >= 0)
Yuval Mintzb70432f2018-02-28 23:29:32 +0200572 reg_dev = mrt->vif_table[reg_vif_num].dev;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900573 if (reg_dev)
574 dev_hold(reg_dev);
575 read_unlock(&mrt_lock);
576
Ian Morris63159f22015-03-29 14:00:04 +0100577 if (!reg_dev)
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900578 goto drop;
579
580 skb->mac_header = skb->network_header;
581 skb_pull(skb, (u8 *)encap - skb->data);
582 skb_reset_network_header(skb);
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800583 skb->protocol = htons(ETH_P_IPV6);
Cesar Eduardo Barros3e49e6d2011-03-26 05:10:30 +0000584 skb->ip_summed = CHECKSUM_NONE;
Eric Dumazetd19d56d2010-05-17 22:36:55 -0700585
Nicolas Dichtelea231922013-09-02 15:34:58 +0200586 skb_tunnel_rx(skb, reg_dev, dev_net(reg_dev));
Eric Dumazetd19d56d2010-05-17 22:36:55 -0700587
Eric Dumazetcaf586e2010-09-30 21:06:55 +0000588 netif_rx(skb);
Eric Dumazet8990f462010-09-20 00:12:11 +0000589
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900590 dev_put(reg_dev);
591 return 0;
592 drop:
593 kfree_skb(skb);
594 return 0;
595}
596
Alexey Dobriyan41135cc2009-09-14 12:22:28 +0000597static const struct inet6_protocol pim6_protocol = {
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900598 .handler = pim6_rcv,
599};
600
601/* Service routines creating virtual interfaces: PIMREG */
602
Stephen Hemminger6fef4c02009-08-31 19:50:41 +0000603static netdev_tx_t reg_vif_xmit(struct sk_buff *skb,
604 struct net_device *dev)
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900605{
Benjamin Thery8229efd2008-12-10 16:30:15 -0800606 struct net *net = dev_net(dev);
Yuval Mintzb70432f2018-02-28 23:29:32 +0200607 struct mr_table *mrt;
David S. Miller4c9483b2011-03-12 16:22:43 -0500608 struct flowi6 fl6 = {
609 .flowi6_oif = dev->ifindex,
Cong Wang6a662712014-04-15 16:25:34 -0700610 .flowi6_iif = skb->skb_iif ? : LOOPBACK_IFINDEX,
David S. Miller4c9483b2011-03-12 16:22:43 -0500611 .flowi6_mark = skb->mark,
Patrick McHardyd1db2752010-05-11 14:40:55 +0200612 };
613 int err;
614
David S. Miller4c9483b2011-03-12 16:22:43 -0500615 err = ip6mr_fib_lookup(net, &fl6, &mrt);
Ben Greear67928c42011-09-23 13:11:01 +0000616 if (err < 0) {
617 kfree_skb(skb);
Patrick McHardyd1db2752010-05-11 14:40:55 +0200618 return err;
Ben Greear67928c42011-09-23 13:11:01 +0000619 }
Benjamin Thery8229efd2008-12-10 16:30:15 -0800620
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900621 read_lock(&mrt_lock);
Pavel Emelyanovdc58c782008-05-21 14:17:54 -0700622 dev->stats.tx_bytes += skb->len;
623 dev->stats.tx_packets++;
Patrick McHardy6bd52142010-05-11 14:40:53 +0200624 ip6mr_cache_report(mrt, skb, mrt->mroute_reg_vif_num, MRT6MSG_WHOLEPKT);
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900625 read_unlock(&mrt_lock);
626 kfree_skb(skb);
Patrick McHardy6ed10652009-06-23 06:03:08 +0000627 return NETDEV_TX_OK;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900628}
629
Nicolas Dichtelee9b9592015-04-02 17:07:03 +0200630static int reg_vif_get_iflink(const struct net_device *dev)
631{
632 return 0;
633}
634
Stephen Hemminger007c3832008-11-20 20:28:35 -0800635static const struct net_device_ops reg_vif_netdev_ops = {
636 .ndo_start_xmit = reg_vif_xmit,
Nicolas Dichtelee9b9592015-04-02 17:07:03 +0200637 .ndo_get_iflink = reg_vif_get_iflink,
Stephen Hemminger007c3832008-11-20 20:28:35 -0800638};
639
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900640static void reg_vif_setup(struct net_device *dev)
641{
642 dev->type = ARPHRD_PIMREG;
643 dev->mtu = 1500 - sizeof(struct ipv6hdr) - 8;
644 dev->flags = IFF_NOARP;
Stephen Hemminger007c3832008-11-20 20:28:35 -0800645 dev->netdev_ops = &reg_vif_netdev_ops;
David S. Millercf124db2017-05-08 12:52:56 -0400646 dev->needs_free_netdev = true;
Tom Goff403dbb92009-06-14 03:16:13 -0700647 dev->features |= NETIF_F_NETNS_LOCAL;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900648}
649
Yuval Mintzb70432f2018-02-28 23:29:32 +0200650static struct net_device *ip6mr_reg_vif(struct net *net, struct mr_table *mrt)
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900651{
652 struct net_device *dev;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200653 char name[IFNAMSIZ];
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900654
Patrick McHardyd1db2752010-05-11 14:40:55 +0200655 if (mrt->id == RT6_TABLE_DFLT)
656 sprintf(name, "pim6reg");
657 else
658 sprintf(name, "pim6reg%u", mrt->id);
659
Tom Gundersenc835a672014-07-14 16:37:24 +0200660 dev = alloc_netdev(0, name, NET_NAME_UNKNOWN, reg_vif_setup);
Ian Morris63159f22015-03-29 14:00:04 +0100661 if (!dev)
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900662 return NULL;
663
Benjamin Thery8229efd2008-12-10 16:30:15 -0800664 dev_net_set(dev, net);
665
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900666 if (register_netdevice(dev)) {
667 free_netdev(dev);
668 return NULL;
669 }
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900670
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900671 if (dev_open(dev))
672 goto failure;
673
Wang Chen7af3db72008-07-14 20:54:54 -0700674 dev_hold(dev);
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900675 return dev;
676
677failure:
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900678 unregister_netdevice(dev);
679 return NULL;
680}
681#endif
682
Yuval Mintz088aa3e2018-03-26 15:01:34 +0300683static int call_ip6mr_vif_entry_notifiers(struct net *net,
684 enum fib_event_type event_type,
685 struct vif_device *vif,
686 mifi_t vif_index, u32 tb_id)
687{
688 return mr_call_vif_notifiers(net, RTNL_FAMILY_IP6MR, event_type,
689 vif, vif_index, tb_id,
690 &net->ipv6.ipmr_seq);
691}
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900692
Yuval Mintz088aa3e2018-03-26 15:01:34 +0300693static int call_ip6mr_mfc_entry_notifiers(struct net *net,
694 enum fib_event_type event_type,
695 struct mfc6_cache *mfc, u32 tb_id)
696{
697 return mr_call_mfc_notifiers(net, RTNL_FAMILY_IP6MR, event_type,
698 &mfc->_c, tb_id, &net->ipv6.ipmr_seq);
699}
700
701/* Delete a VIF entry */
Yuval Mintzb70432f2018-02-28 23:29:32 +0200702static int mif6_delete(struct mr_table *mrt, int vifi, int notify,
Nikolay Aleksandrov723b9292017-04-21 20:42:16 +0300703 struct list_head *head)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900704{
Yuval Mintz6853f212018-02-28 23:29:29 +0200705 struct vif_device *v;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900706 struct net_device *dev;
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800707 struct inet6_dev *in6_dev;
Patrick McHardy6bd52142010-05-11 14:40:53 +0200708
709 if (vifi < 0 || vifi >= mrt->maxvif)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900710 return -EADDRNOTAVAIL;
711
Yuval Mintzb70432f2018-02-28 23:29:32 +0200712 v = &mrt->vif_table[vifi];
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900713
Yuval Mintz088aa3e2018-03-26 15:01:34 +0300714 if (VIF_EXISTS(mrt, vifi))
715 call_ip6mr_vif_entry_notifiers(read_pnet(&mrt->net),
716 FIB_EVENT_VIF_DEL, v, vifi,
717 mrt->id);
718
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900719 write_lock_bh(&mrt_lock);
720 dev = v->dev;
721 v->dev = NULL;
722
723 if (!dev) {
724 write_unlock_bh(&mrt_lock);
725 return -EADDRNOTAVAIL;
726 }
727
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900728#ifdef CONFIG_IPV6_PIMSM_V2
Patrick McHardy6bd52142010-05-11 14:40:53 +0200729 if (vifi == mrt->mroute_reg_vif_num)
730 mrt->mroute_reg_vif_num = -1;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900731#endif
732
Patrick McHardy6bd52142010-05-11 14:40:53 +0200733 if (vifi + 1 == mrt->maxvif) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900734 int tmp;
735 for (tmp = vifi - 1; tmp >= 0; tmp--) {
Yuval Mintzb70432f2018-02-28 23:29:32 +0200736 if (VIF_EXISTS(mrt, tmp))
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900737 break;
738 }
Patrick McHardy6bd52142010-05-11 14:40:53 +0200739 mrt->maxvif = tmp + 1;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900740 }
741
742 write_unlock_bh(&mrt_lock);
743
744 dev_set_allmulti(dev, -1);
745
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800746 in6_dev = __in6_dev_get(dev);
Nicolas Dichteld67b8c62012-12-04 01:13:35 +0000747 if (in6_dev) {
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800748 in6_dev->cnf.mc_forwarding--;
David Ahern85b3daa2017-03-28 14:28:04 -0700749 inet6_netconf_notify_devconf(dev_net(dev), RTM_NEWNETCONF,
Nicolas Dichteld67b8c62012-12-04 01:13:35 +0000750 NETCONFA_MC_FORWARDING,
751 dev->ifindex, &in6_dev->cnf);
752 }
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800753
Nikolay Aleksandrov723b9292017-04-21 20:42:16 +0300754 if ((v->flags & MIFF_REGISTER) && !notify)
Eric Dumazetc871e662009-10-28 04:48:11 +0000755 unregister_netdevice_queue(dev, head);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900756
757 dev_put(dev);
758 return 0;
759}
760
Yuval Mintz87c418b2018-02-28 23:29:31 +0200761static inline void ip6mr_cache_free_rcu(struct rcu_head *head)
762{
Yuval Mintz494fff52018-02-28 23:29:34 +0200763 struct mr_mfc *c = container_of(head, struct mr_mfc, rcu);
Yuval Mintz87c418b2018-02-28 23:29:31 +0200764
Yuval Mintz494fff52018-02-28 23:29:34 +0200765 kmem_cache_free(mrt_cachep, (struct mfc6_cache *)c);
Yuval Mintz87c418b2018-02-28 23:29:31 +0200766}
767
Benjamin Thery58701ad2008-12-10 16:22:34 -0800768static inline void ip6mr_cache_free(struct mfc6_cache *c)
769{
Yuval Mintz494fff52018-02-28 23:29:34 +0200770 call_rcu(&c->_c.rcu, ip6mr_cache_free_rcu);
Benjamin Thery58701ad2008-12-10 16:22:34 -0800771}
772
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900773/* Destroy an unresolved cache entry, killing queued skbs
774 and reporting error to netlink readers.
775 */
776
Yuval Mintzb70432f2018-02-28 23:29:32 +0200777static void ip6mr_destroy_unres(struct mr_table *mrt, struct mfc6_cache *c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900778{
Patrick McHardy6bd52142010-05-11 14:40:53 +0200779 struct net *net = read_pnet(&mrt->net);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900780 struct sk_buff *skb;
781
Patrick McHardy6bd52142010-05-11 14:40:53 +0200782 atomic_dec(&mrt->cache_resolve_queue_len);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900783
Yuval Mintz494fff52018-02-28 23:29:34 +0200784 while ((skb = skb_dequeue(&c->_c.mfc_un.unres.unresolved)) != NULL) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900785 if (ipv6_hdr(skb)->version == 0) {
Johannes Bergaf728682017-06-16 14:29:22 +0200786 struct nlmsghdr *nlh = skb_pull(skb,
787 sizeof(struct ipv6hdr));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900788 nlh->nlmsg_type = NLMSG_ERROR;
Hong zhi guo573ce262013-03-27 06:47:04 +0000789 nlh->nlmsg_len = nlmsg_msg_size(sizeof(struct nlmsgerr));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900790 skb_trim(skb, nlh->nlmsg_len);
Hong zhi guo573ce262013-03-27 06:47:04 +0000791 ((struct nlmsgerr *)nlmsg_data(nlh))->error = -ETIMEDOUT;
Eric W. Biederman15e47302012-09-07 20:12:54 +0000792 rtnl_unicast(skb, net, NETLINK_CB(skb).portid);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900793 } else
794 kfree_skb(skb);
795 }
796
Benjamin Thery58701ad2008-12-10 16:22:34 -0800797 ip6mr_cache_free(c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900798}
799
800
Patrick McHardyc476efb2010-05-11 14:40:48 +0200801/* Timer process for all the unresolved queue. */
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900802
Yuval Mintzb70432f2018-02-28 23:29:32 +0200803static void ipmr_do_expire_process(struct mr_table *mrt)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900804{
805 unsigned long now = jiffies;
806 unsigned long expires = 10 * HZ;
Yuval Mintz494fff52018-02-28 23:29:34 +0200807 struct mr_mfc *c, *next;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900808
Yuval Mintzb70432f2018-02-28 23:29:32 +0200809 list_for_each_entry_safe(c, next, &mrt->mfc_unres_queue, list) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900810 if (time_after(c->mfc_un.unres.expires, now)) {
811 /* not yet... */
812 unsigned long interval = c->mfc_un.unres.expires - now;
813 if (interval < expires)
814 expires = interval;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900815 continue;
816 }
817
Patrick McHardyf30a77842010-05-11 14:40:51 +0200818 list_del(&c->list);
Yuval Mintz494fff52018-02-28 23:29:34 +0200819 mr6_netlink_event(mrt, (struct mfc6_cache *)c, RTM_DELROUTE);
820 ip6mr_destroy_unres(mrt, (struct mfc6_cache *)c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900821 }
822
Yuval Mintzb70432f2018-02-28 23:29:32 +0200823 if (!list_empty(&mrt->mfc_unres_queue))
Patrick McHardy6bd52142010-05-11 14:40:53 +0200824 mod_timer(&mrt->ipmr_expire_timer, jiffies + expires);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900825}
826
Kees Cooke99e88a2017-10-16 14:43:17 -0700827static void ipmr_expire_process(struct timer_list *t)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900828{
Yuval Mintzb70432f2018-02-28 23:29:32 +0200829 struct mr_table *mrt = from_timer(mrt, t, ipmr_expire_timer);
Patrick McHardyc476efb2010-05-11 14:40:48 +0200830
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900831 if (!spin_trylock(&mfc_unres_lock)) {
Patrick McHardy6bd52142010-05-11 14:40:53 +0200832 mod_timer(&mrt->ipmr_expire_timer, jiffies + 1);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900833 return;
834 }
835
Yuval Mintzb70432f2018-02-28 23:29:32 +0200836 if (!list_empty(&mrt->mfc_unres_queue))
Patrick McHardy6bd52142010-05-11 14:40:53 +0200837 ipmr_do_expire_process(mrt);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900838
839 spin_unlock(&mfc_unres_lock);
840}
841
842/* Fill oifs list. It is called under write locked mrt_lock. */
843
Yuval Mintzb70432f2018-02-28 23:29:32 +0200844static void ip6mr_update_thresholds(struct mr_table *mrt,
Yuval Mintz494fff52018-02-28 23:29:34 +0200845 struct mr_mfc *cache,
Patrick McHardyb5aa30b2010-05-11 14:40:50 +0200846 unsigned char *ttls)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900847{
848 int vifi;
849
Rami Rosen6ac7eb02008-04-10 12:40:10 +0300850 cache->mfc_un.res.minvif = MAXMIFS;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900851 cache->mfc_un.res.maxvif = 0;
Rami Rosen6ac7eb02008-04-10 12:40:10 +0300852 memset(cache->mfc_un.res.ttls, 255, MAXMIFS);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900853
Patrick McHardy6bd52142010-05-11 14:40:53 +0200854 for (vifi = 0; vifi < mrt->maxvif; vifi++) {
Yuval Mintzb70432f2018-02-28 23:29:32 +0200855 if (VIF_EXISTS(mrt, vifi) &&
Benjamin Thery4e168802008-12-10 16:15:08 -0800856 ttls[vifi] && ttls[vifi] < 255) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900857 cache->mfc_un.res.ttls[vifi] = ttls[vifi];
858 if (cache->mfc_un.res.minvif > vifi)
859 cache->mfc_un.res.minvif = vifi;
860 if (cache->mfc_un.res.maxvif <= vifi)
861 cache->mfc_un.res.maxvif = vifi + 1;
862 }
863 }
Nikolay Aleksandrov90b5ca12016-07-26 18:54:52 +0200864 cache->mfc_un.res.lastuse = jiffies;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900865}
866
Yuval Mintzb70432f2018-02-28 23:29:32 +0200867static int mif6_add(struct net *net, struct mr_table *mrt,
Patrick McHardy6bd52142010-05-11 14:40:53 +0200868 struct mif6ctl *vifc, int mrtsock)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900869{
870 int vifi = vifc->mif6c_mifi;
Yuval Mintzb70432f2018-02-28 23:29:32 +0200871 struct vif_device *v = &mrt->vif_table[vifi];
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900872 struct net_device *dev;
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800873 struct inet6_dev *in6_dev;
Wang Chen5ae7b442008-07-14 20:54:23 -0700874 int err;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900875
876 /* Is vif busy ? */
Yuval Mintzb70432f2018-02-28 23:29:32 +0200877 if (VIF_EXISTS(mrt, vifi))
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900878 return -EADDRINUSE;
879
880 switch (vifc->mif6c_flags) {
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900881#ifdef CONFIG_IPV6_PIMSM_V2
882 case MIFF_REGISTER:
883 /*
884 * Special Purpose VIF in PIM
885 * All the packets will be sent to the daemon
886 */
Patrick McHardy6bd52142010-05-11 14:40:53 +0200887 if (mrt->mroute_reg_vif_num >= 0)
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900888 return -EADDRINUSE;
Patrick McHardyd1db2752010-05-11 14:40:55 +0200889 dev = ip6mr_reg_vif(net, mrt);
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900890 if (!dev)
891 return -ENOBUFS;
Wang Chen5ae7b442008-07-14 20:54:23 -0700892 err = dev_set_allmulti(dev, 1);
893 if (err) {
894 unregister_netdevice(dev);
Wang Chen7af3db72008-07-14 20:54:54 -0700895 dev_put(dev);
Wang Chen5ae7b442008-07-14 20:54:23 -0700896 return err;
897 }
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900898 break;
899#endif
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900900 case 0:
Benjamin Thery8229efd2008-12-10 16:30:15 -0800901 dev = dev_get_by_index(net, vifc->mif6c_pifi);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900902 if (!dev)
903 return -EADDRNOTAVAIL;
Wang Chen5ae7b442008-07-14 20:54:23 -0700904 err = dev_set_allmulti(dev, 1);
Wang Chen7af3db72008-07-14 20:54:54 -0700905 if (err) {
906 dev_put(dev);
Wang Chen5ae7b442008-07-14 20:54:23 -0700907 return err;
Wang Chen7af3db72008-07-14 20:54:54 -0700908 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900909 break;
910 default:
911 return -EINVAL;
912 }
913
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800914 in6_dev = __in6_dev_get(dev);
Nicolas Dichteld67b8c62012-12-04 01:13:35 +0000915 if (in6_dev) {
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800916 in6_dev->cnf.mc_forwarding++;
David Ahern85b3daa2017-03-28 14:28:04 -0700917 inet6_netconf_notify_devconf(dev_net(dev), RTM_NEWNETCONF,
Nicolas Dichteld67b8c62012-12-04 01:13:35 +0000918 NETCONFA_MC_FORWARDING,
919 dev->ifindex, &in6_dev->cnf);
920 }
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800921
Yuval Mintz6853f212018-02-28 23:29:29 +0200922 /* Fill in the VIF structures */
923 vif_device_init(v, dev, vifc->vifc_rate_limit, vifc->vifc_threshold,
924 vifc->mif6c_flags | (!mrtsock ? VIFF_STATIC : 0),
925 MIFF_REGISTER);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900926
927 /* And finish update writing critical data */
928 write_lock_bh(&mrt_lock);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900929 v->dev = dev;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900930#ifdef CONFIG_IPV6_PIMSM_V2
931 if (v->flags & MIFF_REGISTER)
Patrick McHardy6bd52142010-05-11 14:40:53 +0200932 mrt->mroute_reg_vif_num = vifi;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900933#endif
Patrick McHardy6bd52142010-05-11 14:40:53 +0200934 if (vifi + 1 > mrt->maxvif)
935 mrt->maxvif = vifi + 1;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900936 write_unlock_bh(&mrt_lock);
Yuval Mintz088aa3e2018-03-26 15:01:34 +0300937 call_ip6mr_vif_entry_notifiers(net, FIB_EVENT_VIF_ADD,
938 v, vifi, mrt->id);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900939 return 0;
940}
941
Yuval Mintzb70432f2018-02-28 23:29:32 +0200942static struct mfc6_cache *ip6mr_cache_find(struct mr_table *mrt,
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000943 const struct in6_addr *origin,
944 const struct in6_addr *mcastgrp)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900945{
Yuval Mintz87c418b2018-02-28 23:29:31 +0200946 struct mfc6_cache_cmp_arg arg = {
947 .mf6c_origin = *origin,
948 .mf6c_mcastgrp = *mcastgrp,
949 };
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900950
Yuval Mintz845c9a72018-02-28 23:29:35 +0200951 return mr_mfc_find(mrt, &arg);
Nicolas Dichtel660b26d2013-01-21 06:00:26 +0000952}
953
954/* Look for a (*,G) entry */
Yuval Mintzb70432f2018-02-28 23:29:32 +0200955static struct mfc6_cache *ip6mr_cache_find_any(struct mr_table *mrt,
Nicolas Dichtel660b26d2013-01-21 06:00:26 +0000956 struct in6_addr *mcastgrp,
957 mifi_t mifi)
958{
Yuval Mintz87c418b2018-02-28 23:29:31 +0200959 struct mfc6_cache_cmp_arg arg = {
960 .mf6c_origin = in6addr_any,
961 .mf6c_mcastgrp = *mcastgrp,
962 };
Nicolas Dichtel660b26d2013-01-21 06:00:26 +0000963
964 if (ipv6_addr_any(mcastgrp))
Yuval Mintz845c9a72018-02-28 23:29:35 +0200965 return mr_mfc_find_any_parent(mrt, mifi);
966 return mr_mfc_find_any(mrt, mifi, &arg);
Nicolas Dichtel660b26d2013-01-21 06:00:26 +0000967}
968
Yuval Mintz87c418b2018-02-28 23:29:31 +0200969/* Look for a (S,G,iif) entry if parent != -1 */
970static struct mfc6_cache *
Yuval Mintzb70432f2018-02-28 23:29:32 +0200971ip6mr_cache_find_parent(struct mr_table *mrt,
Yuval Mintz87c418b2018-02-28 23:29:31 +0200972 const struct in6_addr *origin,
973 const struct in6_addr *mcastgrp,
974 int parent)
975{
976 struct mfc6_cache_cmp_arg arg = {
977 .mf6c_origin = *origin,
978 .mf6c_mcastgrp = *mcastgrp,
979 };
Yuval Mintz87c418b2018-02-28 23:29:31 +0200980
Yuval Mintz845c9a72018-02-28 23:29:35 +0200981 return mr_mfc_find_parent(mrt, &arg, parent);
Yuval Mintz87c418b2018-02-28 23:29:31 +0200982}
983
Yuval Mintz845c9a72018-02-28 23:29:35 +0200984/* Allocate a multicast cache entry */
Patrick McHardyb5aa30b2010-05-11 14:40:50 +0200985static struct mfc6_cache *ip6mr_cache_alloc(void)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900986{
Joe Perches36cbac52008-12-03 22:27:25 -0800987 struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL);
Ian Morris63159f22015-03-29 14:00:04 +0100988 if (!c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900989 return NULL;
Yuval Mintz494fff52018-02-28 23:29:34 +0200990 c->_c.mfc_un.res.last_assert = jiffies - MFC_ASSERT_THRESH - 1;
991 c->_c.mfc_un.res.minvif = MAXMIFS;
Yuval Mintz8c13af22018-03-26 15:01:36 +0300992 c->_c.free = ip6mr_cache_free_rcu;
993 refcount_set(&c->_c.mfc_un.res.refcount, 1);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900994 return c;
995}
996
Patrick McHardyb5aa30b2010-05-11 14:40:50 +0200997static struct mfc6_cache *ip6mr_cache_alloc_unres(void)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900998{
Joe Perches36cbac52008-12-03 22:27:25 -0800999 struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC);
Ian Morris63159f22015-03-29 14:00:04 +01001000 if (!c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001001 return NULL;
Yuval Mintz494fff52018-02-28 23:29:34 +02001002 skb_queue_head_init(&c->_c.mfc_un.unres.unresolved);
1003 c->_c.mfc_un.unres.expires = jiffies + 10 * HZ;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001004 return c;
1005}
1006
1007/*
1008 * A cache entry has gone into a resolved state from queued
1009 */
1010
Yuval Mintzb70432f2018-02-28 23:29:32 +02001011static void ip6mr_cache_resolve(struct net *net, struct mr_table *mrt,
Patrick McHardy6bd52142010-05-11 14:40:53 +02001012 struct mfc6_cache *uc, struct mfc6_cache *c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001013{
1014 struct sk_buff *skb;
1015
1016 /*
1017 * Play the pending entries through our router
1018 */
1019
Yuval Mintz494fff52018-02-28 23:29:34 +02001020 while ((skb = __skb_dequeue(&uc->_c.mfc_un.unres.unresolved))) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001021 if (ipv6_hdr(skb)->version == 0) {
Johannes Bergaf728682017-06-16 14:29:22 +02001022 struct nlmsghdr *nlh = skb_pull(skb,
1023 sizeof(struct ipv6hdr));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001024
Yuval Mintz7b0db852018-02-28 23:29:39 +02001025 if (mr_fill_mroute(mrt, skb, &c->_c,
1026 nlmsg_data(nlh)) > 0) {
YOSHIFUJI Hideaki549e0282008-04-05 22:17:39 +09001027 nlh->nlmsg_len = skb_tail_pointer(skb) - (u8 *)nlh;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001028 } else {
1029 nlh->nlmsg_type = NLMSG_ERROR;
Hong zhi guo573ce262013-03-27 06:47:04 +00001030 nlh->nlmsg_len = nlmsg_msg_size(sizeof(struct nlmsgerr));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001031 skb_trim(skb, nlh->nlmsg_len);
Hong zhi guo573ce262013-03-27 06:47:04 +00001032 ((struct nlmsgerr *)nlmsg_data(nlh))->error = -EMSGSIZE;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001033 }
Eric W. Biederman15e47302012-09-07 20:12:54 +00001034 rtnl_unicast(skb, net, NETLINK_CB(skb).portid);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001035 } else
Patrick McHardy6bd52142010-05-11 14:40:53 +02001036 ip6_mr_forward(net, mrt, skb, c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001037 }
1038}
1039
1040/*
Julien Gomesdd12d15c2017-06-20 13:54:18 -07001041 * Bounce a cache query up to pim6sd and netlink.
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001042 *
1043 * Called under mrt_lock.
1044 */
1045
Yuval Mintzb70432f2018-02-28 23:29:32 +02001046static int ip6mr_cache_report(struct mr_table *mrt, struct sk_buff *pkt,
Patrick McHardy6bd52142010-05-11 14:40:53 +02001047 mifi_t mifi, int assert)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001048{
Yuval Mintz8571ab42018-02-28 23:29:30 +02001049 struct sock *mroute6_sk;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001050 struct sk_buff *skb;
1051 struct mrt6msg *msg;
1052 int ret;
1053
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001054#ifdef CONFIG_IPV6_PIMSM_V2
1055 if (assert == MRT6MSG_WHOLEPKT)
1056 skb = skb_realloc_headroom(pkt, -skb_network_offset(pkt)
1057 +sizeof(*msg));
1058 else
1059#endif
1060 skb = alloc_skb(sizeof(struct ipv6hdr) + sizeof(*msg), GFP_ATOMIC);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001061
1062 if (!skb)
1063 return -ENOBUFS;
1064
1065 /* I suppose that internal messages
1066 * do not require checksums */
1067
1068 skb->ip_summed = CHECKSUM_UNNECESSARY;
1069
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001070#ifdef CONFIG_IPV6_PIMSM_V2
1071 if (assert == MRT6MSG_WHOLEPKT) {
1072 /* Ugly, but we have no choice with this interface.
1073 Duplicate old header, fix length etc.
1074 And all this only to mangle msg->im6_msgtype and
1075 to set msg->im6_mbz to "mbz" :-)
1076 */
1077 skb_push(skb, -skb_network_offset(pkt));
1078
1079 skb_push(skb, sizeof(*msg));
1080 skb_reset_transport_header(skb);
1081 msg = (struct mrt6msg *)skb_transport_header(skb);
1082 msg->im6_mbz = 0;
1083 msg->im6_msgtype = MRT6MSG_WHOLEPKT;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001084 msg->im6_mif = mrt->mroute_reg_vif_num;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001085 msg->im6_pad = 0;
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +00001086 msg->im6_src = ipv6_hdr(pkt)->saddr;
1087 msg->im6_dst = ipv6_hdr(pkt)->daddr;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001088
1089 skb->ip_summed = CHECKSUM_UNNECESSARY;
1090 } else
1091#endif
1092 {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001093 /*
1094 * Copy the IP header
1095 */
1096
1097 skb_put(skb, sizeof(struct ipv6hdr));
1098 skb_reset_network_header(skb);
1099 skb_copy_to_linear_data(skb, ipv6_hdr(pkt), sizeof(struct ipv6hdr));
1100
1101 /*
1102 * Add our header
1103 */
1104 skb_put(skb, sizeof(*msg));
1105 skb_reset_transport_header(skb);
1106 msg = (struct mrt6msg *)skb_transport_header(skb);
1107
1108 msg->im6_mbz = 0;
1109 msg->im6_msgtype = assert;
Rami Rosen6ac7eb02008-04-10 12:40:10 +03001110 msg->im6_mif = mifi;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001111 msg->im6_pad = 0;
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +00001112 msg->im6_src = ipv6_hdr(pkt)->saddr;
1113 msg->im6_dst = ipv6_hdr(pkt)->daddr;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001114
Eric Dumazetadf30902009-06-02 05:19:30 +00001115 skb_dst_set(skb, dst_clone(skb_dst(pkt)));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001116 skb->ip_summed = CHECKSUM_UNNECESSARY;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001117 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001118
Yuval Mintz8571ab42018-02-28 23:29:30 +02001119 rcu_read_lock();
Yuval Mintzb70432f2018-02-28 23:29:32 +02001120 mroute6_sk = rcu_dereference(mrt->mroute_sk);
Yuval Mintz8571ab42018-02-28 23:29:30 +02001121 if (!mroute6_sk) {
1122 rcu_read_unlock();
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001123 kfree_skb(skb);
1124 return -EINVAL;
1125 }
1126
Julien Gomesdd12d15c2017-06-20 13:54:18 -07001127 mrt6msg_netlink_event(mrt, skb);
1128
Yuval Mintz8571ab42018-02-28 23:29:30 +02001129 /* Deliver to user space multicast routing algorithms */
1130 ret = sock_queue_rcv_skb(mroute6_sk, skb);
1131 rcu_read_unlock();
Benjamin Therybd91b8b2008-12-10 16:07:08 -08001132 if (ret < 0) {
Joe Perchese87cc472012-05-13 21:56:26 +00001133 net_warn_ratelimited("mroute6: pending queue full, dropping entries\n");
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001134 kfree_skb(skb);
1135 }
1136
1137 return ret;
1138}
1139
Yuval Mintz494fff52018-02-28 23:29:34 +02001140/* Queue a packet for resolution. It gets locked cache entry! */
1141static int ip6mr_cache_unresolved(struct mr_table *mrt, mifi_t mifi,
1142 struct sk_buff *skb)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001143{
Yuval Mintz494fff52018-02-28 23:29:34 +02001144 struct mfc6_cache *c;
Patrick McHardyf30a77842010-05-11 14:40:51 +02001145 bool found = false;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001146 int err;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001147
1148 spin_lock_bh(&mfc_unres_lock);
Yuval Mintz494fff52018-02-28 23:29:34 +02001149 list_for_each_entry(c, &mrt->mfc_unres_queue, _c.list) {
Patrick McHardyc476efb2010-05-11 14:40:48 +02001150 if (ipv6_addr_equal(&c->mf6c_mcastgrp, &ipv6_hdr(skb)->daddr) &&
Patrick McHardyf30a77842010-05-11 14:40:51 +02001151 ipv6_addr_equal(&c->mf6c_origin, &ipv6_hdr(skb)->saddr)) {
1152 found = true;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001153 break;
Patrick McHardyf30a77842010-05-11 14:40:51 +02001154 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001155 }
1156
Patrick McHardyf30a77842010-05-11 14:40:51 +02001157 if (!found) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001158 /*
1159 * Create a new entry if allowable
1160 */
1161
Patrick McHardy6bd52142010-05-11 14:40:53 +02001162 if (atomic_read(&mrt->cache_resolve_queue_len) >= 10 ||
Patrick McHardyb5aa30b2010-05-11 14:40:50 +02001163 (c = ip6mr_cache_alloc_unres()) == NULL) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001164 spin_unlock_bh(&mfc_unres_lock);
1165
1166 kfree_skb(skb);
1167 return -ENOBUFS;
1168 }
1169
Yuval Mintz494fff52018-02-28 23:29:34 +02001170 /* Fill in the new cache entry */
1171 c->_c.mfc_parent = -1;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001172 c->mf6c_origin = ipv6_hdr(skb)->saddr;
1173 c->mf6c_mcastgrp = ipv6_hdr(skb)->daddr;
1174
1175 /*
1176 * Reflect first query at pim6sd
1177 */
Patrick McHardy6bd52142010-05-11 14:40:53 +02001178 err = ip6mr_cache_report(mrt, skb, mifi, MRT6MSG_NOCACHE);
Benjamin Thery8229efd2008-12-10 16:30:15 -08001179 if (err < 0) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001180 /* If the report failed throw the cache entry
1181 out - Brad Parker
1182 */
1183 spin_unlock_bh(&mfc_unres_lock);
1184
Benjamin Thery58701ad2008-12-10 16:22:34 -08001185 ip6mr_cache_free(c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001186 kfree_skb(skb);
1187 return err;
1188 }
1189
Patrick McHardy6bd52142010-05-11 14:40:53 +02001190 atomic_inc(&mrt->cache_resolve_queue_len);
Yuval Mintz494fff52018-02-28 23:29:34 +02001191 list_add(&c->_c.list, &mrt->mfc_unres_queue);
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00001192 mr6_netlink_event(mrt, c, RTM_NEWROUTE);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001193
Patrick McHardy6bd52142010-05-11 14:40:53 +02001194 ipmr_do_expire_process(mrt);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001195 }
1196
Yuval Mintz494fff52018-02-28 23:29:34 +02001197 /* See if we can append the packet */
1198 if (c->_c.mfc_un.unres.unresolved.qlen > 3) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001199 kfree_skb(skb);
1200 err = -ENOBUFS;
1201 } else {
Yuval Mintz494fff52018-02-28 23:29:34 +02001202 skb_queue_tail(&c->_c.mfc_un.unres.unresolved, skb);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001203 err = 0;
1204 }
1205
1206 spin_unlock_bh(&mfc_unres_lock);
1207 return err;
1208}
1209
1210/*
1211 * MFC6 cache manipulation by user space
1212 */
1213
Yuval Mintzb70432f2018-02-28 23:29:32 +02001214static int ip6mr_mfc_delete(struct mr_table *mrt, struct mf6cctl *mfc,
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001215 int parent)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001216{
Yuval Mintz87c418b2018-02-28 23:29:31 +02001217 struct mfc6_cache *c;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001218
Yuval Mintz87c418b2018-02-28 23:29:31 +02001219 /* The entries are added/deleted only under RTNL */
1220 rcu_read_lock();
1221 c = ip6mr_cache_find_parent(mrt, &mfc->mf6cc_origin.sin6_addr,
1222 &mfc->mf6cc_mcastgrp.sin6_addr, parent);
1223 rcu_read_unlock();
1224 if (!c)
1225 return -ENOENT;
Yuval Mintz494fff52018-02-28 23:29:34 +02001226 rhltable_remove(&mrt->mfc_hash, &c->_c.mnode, ip6mr_rht_params);
1227 list_del_rcu(&c->_c.list);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001228
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001229 call_ip6mr_mfc_entry_notifiers(read_pnet(&mrt->net),
1230 FIB_EVENT_ENTRY_DEL, c, mrt->id);
Yuval Mintz87c418b2018-02-28 23:29:31 +02001231 mr6_netlink_event(mrt, c, RTM_DELROUTE);
Yuval Mintz8c13af22018-03-26 15:01:36 +03001232 mr_cache_put(&c->_c);
Yuval Mintz87c418b2018-02-28 23:29:31 +02001233 return 0;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001234}
1235
1236static int ip6mr_device_event(struct notifier_block *this,
1237 unsigned long event, void *ptr)
1238{
Jiri Pirko351638e2013-05-28 01:30:21 +00001239 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
Benjamin Thery8229efd2008-12-10 16:30:15 -08001240 struct net *net = dev_net(dev);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001241 struct mr_table *mrt;
Yuval Mintz6853f212018-02-28 23:29:29 +02001242 struct vif_device *v;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001243 int ct;
1244
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001245 if (event != NETDEV_UNREGISTER)
1246 return NOTIFY_DONE;
1247
Patrick McHardyd1db2752010-05-11 14:40:55 +02001248 ip6mr_for_each_table(mrt, net) {
Yuval Mintzb70432f2018-02-28 23:29:32 +02001249 v = &mrt->vif_table[0];
Patrick McHardyd1db2752010-05-11 14:40:55 +02001250 for (ct = 0; ct < mrt->maxvif; ct++, v++) {
1251 if (v->dev == dev)
Nikolay Aleksandrov723b9292017-04-21 20:42:16 +03001252 mif6_delete(mrt, ct, 1, NULL);
Patrick McHardyd1db2752010-05-11 14:40:55 +02001253 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001254 }
Eric Dumazetc871e662009-10-28 04:48:11 +00001255
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001256 return NOTIFY_DONE;
1257}
1258
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001259static unsigned int ip6mr_seq_read(struct net *net)
1260{
1261 ASSERT_RTNL();
1262
1263 return net->ipv6.ipmr_seq + ip6mr_rules_seq_read(net);
1264}
1265
1266static int ip6mr_dump(struct net *net, struct notifier_block *nb)
1267{
1268 return mr_dump(net, nb, RTNL_FAMILY_IP6MR, ip6mr_rules_dump,
1269 ip6mr_mr_table_iter, &mrt_lock);
1270}
1271
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001272static struct notifier_block ip6_mr_notifier = {
1273 .notifier_call = ip6mr_device_event
1274};
1275
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001276static const struct fib_notifier_ops ip6mr_notifier_ops_template = {
1277 .family = RTNL_FAMILY_IP6MR,
1278 .fib_seq_read = ip6mr_seq_read,
1279 .fib_dump = ip6mr_dump,
1280 .owner = THIS_MODULE,
1281};
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001282
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001283static int __net_init ip6mr_notifier_init(struct net *net)
1284{
1285 struct fib_notifier_ops *ops;
1286
1287 net->ipv6.ipmr_seq = 0;
1288
1289 ops = fib_notifier_ops_register(&ip6mr_notifier_ops_template, net);
1290 if (IS_ERR(ops))
1291 return PTR_ERR(ops);
1292
1293 net->ipv6.ip6mr_notifier_ops = ops;
1294
1295 return 0;
1296}
1297
1298static void __net_exit ip6mr_notifier_exit(struct net *net)
1299{
1300 fib_notifier_ops_unregister(net->ipv6.ip6mr_notifier_ops);
1301 net->ipv6.ip6mr_notifier_ops = NULL;
1302}
1303
1304/* Setup for IP multicast routing */
Benjamin Thery4e168802008-12-10 16:15:08 -08001305static int __net_init ip6mr_net_init(struct net *net)
1306{
Patrick McHardyd1db2752010-05-11 14:40:55 +02001307 int err;
Patrick McHardyf30a77842010-05-11 14:40:51 +02001308
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001309 err = ip6mr_notifier_init(net);
1310 if (err)
1311 return err;
1312
Patrick McHardyd1db2752010-05-11 14:40:55 +02001313 err = ip6mr_rules_init(net);
1314 if (err < 0)
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001315 goto ip6mr_rules_fail;
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001316
1317#ifdef CONFIG_PROC_FS
1318 err = -ENOMEM;
Gao fengd4beaa62013-02-18 01:34:54 +00001319 if (!proc_create("ip6_mr_vif", 0, net->proc_net, &ip6mr_vif_fops))
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001320 goto proc_vif_fail;
Gao fengd4beaa62013-02-18 01:34:54 +00001321 if (!proc_create("ip6_mr_cache", 0, net->proc_net, &ip6mr_mfc_fops))
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001322 goto proc_cache_fail;
1323#endif
Patrick McHardy6bd52142010-05-11 14:40:53 +02001324
Benjamin Thery4a6258a2008-12-10 16:24:07 -08001325 return 0;
1326
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001327#ifdef CONFIG_PROC_FS
1328proc_cache_fail:
Gao fengece31ff2013-02-18 01:34:56 +00001329 remove_proc_entry("ip6_mr_vif", net->proc_net);
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001330proc_vif_fail:
Patrick McHardyd1db2752010-05-11 14:40:55 +02001331 ip6mr_rules_exit(net);
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001332#endif
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001333ip6mr_rules_fail:
1334 ip6mr_notifier_exit(net);
Benjamin Thery4e168802008-12-10 16:15:08 -08001335 return err;
1336}
1337
1338static void __net_exit ip6mr_net_exit(struct net *net)
1339{
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001340#ifdef CONFIG_PROC_FS
Gao fengece31ff2013-02-18 01:34:56 +00001341 remove_proc_entry("ip6_mr_cache", net->proc_net);
1342 remove_proc_entry("ip6_mr_vif", net->proc_net);
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001343#endif
Patrick McHardyd1db2752010-05-11 14:40:55 +02001344 ip6mr_rules_exit(net);
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001345 ip6mr_notifier_exit(net);
Benjamin Thery4e168802008-12-10 16:15:08 -08001346}
1347
1348static struct pernet_operations ip6mr_net_ops = {
1349 .init = ip6mr_net_init,
1350 .exit = ip6mr_net_exit,
1351};
1352
Wang Chen623d1a12008-07-03 12:13:30 +08001353int __init ip6_mr_init(void)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001354{
Wang Chen623d1a12008-07-03 12:13:30 +08001355 int err;
1356
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001357 mrt_cachep = kmem_cache_create("ip6_mrt_cache",
1358 sizeof(struct mfc6_cache),
1359 0, SLAB_HWCACHE_ALIGN,
1360 NULL);
1361 if (!mrt_cachep)
Wang Chen623d1a12008-07-03 12:13:30 +08001362 return -ENOMEM;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001363
Benjamin Thery4e168802008-12-10 16:15:08 -08001364 err = register_pernet_subsys(&ip6mr_net_ops);
1365 if (err)
1366 goto reg_pernet_fail;
1367
Wang Chen623d1a12008-07-03 12:13:30 +08001368 err = register_netdevice_notifier(&ip6_mr_notifier);
1369 if (err)
1370 goto reg_notif_fail;
Tom Goff403dbb92009-06-14 03:16:13 -07001371#ifdef CONFIG_IPV6_PIMSM_V2
1372 if (inet6_add_protocol(&pim6_protocol, IPPROTO_PIM) < 0) {
Joe Perchesf3213832012-05-15 14:11:53 +00001373 pr_err("%s: can't add PIM protocol\n", __func__);
Tom Goff403dbb92009-06-14 03:16:13 -07001374 err = -EAGAIN;
1375 goto add_proto_fail;
1376 }
1377#endif
Florian Westphala3fde2a2017-12-04 19:19:18 +01001378 err = rtnl_register_module(THIS_MODULE, RTNL_FAMILY_IP6MR, RTM_GETROUTE,
1379 NULL, ip6mr_rtm_dumproute, 0);
1380 if (err == 0)
1381 return 0;
1382
Tom Goff403dbb92009-06-14 03:16:13 -07001383#ifdef CONFIG_IPV6_PIMSM_V2
Florian Westphala3fde2a2017-12-04 19:19:18 +01001384 inet6_del_protocol(&pim6_protocol, IPPROTO_PIM);
Tom Goff403dbb92009-06-14 03:16:13 -07001385add_proto_fail:
1386 unregister_netdevice_notifier(&ip6_mr_notifier);
1387#endif
Benjamin Thery87b30a62008-11-10 16:34:11 -08001388reg_notif_fail:
Benjamin Thery4e168802008-12-10 16:15:08 -08001389 unregister_pernet_subsys(&ip6mr_net_ops);
1390reg_pernet_fail:
Benjamin Thery87b30a62008-11-10 16:34:11 -08001391 kmem_cache_destroy(mrt_cachep);
Wang Chen623d1a12008-07-03 12:13:30 +08001392 return err;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001393}
1394
Wang Chen623d1a12008-07-03 12:13:30 +08001395void ip6_mr_cleanup(void)
1396{
Duan Jiongffb13882014-11-19 09:35:39 +08001397 rtnl_unregister(RTNL_FAMILY_IP6MR, RTM_GETROUTE);
1398#ifdef CONFIG_IPV6_PIMSM_V2
1399 inet6_del_protocol(&pim6_protocol, IPPROTO_PIM);
1400#endif
Wang Chen623d1a12008-07-03 12:13:30 +08001401 unregister_netdevice_notifier(&ip6_mr_notifier);
Benjamin Thery4e168802008-12-10 16:15:08 -08001402 unregister_pernet_subsys(&ip6mr_net_ops);
Wang Chen623d1a12008-07-03 12:13:30 +08001403 kmem_cache_destroy(mrt_cachep);
1404}
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001405
Yuval Mintzb70432f2018-02-28 23:29:32 +02001406static int ip6mr_mfc_add(struct net *net, struct mr_table *mrt,
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001407 struct mf6cctl *mfc, int mrtsock, int parent)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001408{
Rami Rosen6ac7eb02008-04-10 12:40:10 +03001409 unsigned char ttls[MAXMIFS];
Yuval Mintz87c418b2018-02-28 23:29:31 +02001410 struct mfc6_cache *uc, *c;
Yuval Mintz494fff52018-02-28 23:29:34 +02001411 struct mr_mfc *_uc;
Yuval Mintz87c418b2018-02-28 23:29:31 +02001412 bool found;
1413 int i, err;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001414
Patrick McHardya50436f22010-03-17 06:04:14 +00001415 if (mfc->mf6cc_parent >= MAXMIFS)
1416 return -ENFILE;
1417
Rami Rosen6ac7eb02008-04-10 12:40:10 +03001418 memset(ttls, 255, MAXMIFS);
1419 for (i = 0; i < MAXMIFS; i++) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001420 if (IF_ISSET(i, &mfc->mf6cc_ifset))
1421 ttls[i] = 1;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001422 }
1423
Yuval Mintz87c418b2018-02-28 23:29:31 +02001424 /* The entries are added/deleted only under RTNL */
1425 rcu_read_lock();
1426 c = ip6mr_cache_find_parent(mrt, &mfc->mf6cc_origin.sin6_addr,
1427 &mfc->mf6cc_mcastgrp.sin6_addr, parent);
1428 rcu_read_unlock();
1429 if (c) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001430 write_lock_bh(&mrt_lock);
Yuval Mintz494fff52018-02-28 23:29:34 +02001431 c->_c.mfc_parent = mfc->mf6cc_parent;
1432 ip6mr_update_thresholds(mrt, &c->_c, ttls);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001433 if (!mrtsock)
Yuval Mintz494fff52018-02-28 23:29:34 +02001434 c->_c.mfc_flags |= MFC_STATIC;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001435 write_unlock_bh(&mrt_lock);
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001436 call_ip6mr_mfc_entry_notifiers(net, FIB_EVENT_ENTRY_REPLACE,
1437 c, mrt->id);
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00001438 mr6_netlink_event(mrt, c, RTM_NEWROUTE);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001439 return 0;
1440 }
1441
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001442 if (!ipv6_addr_any(&mfc->mf6cc_mcastgrp.sin6_addr) &&
1443 !ipv6_addr_is_multicast(&mfc->mf6cc_mcastgrp.sin6_addr))
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001444 return -EINVAL;
1445
Patrick McHardyb5aa30b2010-05-11 14:40:50 +02001446 c = ip6mr_cache_alloc();
Ian Morris63159f22015-03-29 14:00:04 +01001447 if (!c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001448 return -ENOMEM;
1449
1450 c->mf6c_origin = mfc->mf6cc_origin.sin6_addr;
1451 c->mf6c_mcastgrp = mfc->mf6cc_mcastgrp.sin6_addr;
Yuval Mintz494fff52018-02-28 23:29:34 +02001452 c->_c.mfc_parent = mfc->mf6cc_parent;
1453 ip6mr_update_thresholds(mrt, &c->_c, ttls);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001454 if (!mrtsock)
Yuval Mintz494fff52018-02-28 23:29:34 +02001455 c->_c.mfc_flags |= MFC_STATIC;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001456
Yuval Mintz494fff52018-02-28 23:29:34 +02001457 err = rhltable_insert_key(&mrt->mfc_hash, &c->cmparg, &c->_c.mnode,
Yuval Mintz87c418b2018-02-28 23:29:31 +02001458 ip6mr_rht_params);
1459 if (err) {
1460 pr_err("ip6mr: rhtable insert error %d\n", err);
1461 ip6mr_cache_free(c);
1462 return err;
1463 }
Yuval Mintz494fff52018-02-28 23:29:34 +02001464 list_add_tail_rcu(&c->_c.list, &mrt->mfc_cache_list);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001465
Yuval Mintz87c418b2018-02-28 23:29:31 +02001466 /* Check to see if we resolved a queued list. If so we
1467 * need to send on the frames and tidy up.
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001468 */
Patrick McHardyf30a77842010-05-11 14:40:51 +02001469 found = false;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001470 spin_lock_bh(&mfc_unres_lock);
Yuval Mintz494fff52018-02-28 23:29:34 +02001471 list_for_each_entry(_uc, &mrt->mfc_unres_queue, list) {
1472 uc = (struct mfc6_cache *)_uc;
Patrick McHardyc476efb2010-05-11 14:40:48 +02001473 if (ipv6_addr_equal(&uc->mf6c_origin, &c->mf6c_origin) &&
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001474 ipv6_addr_equal(&uc->mf6c_mcastgrp, &c->mf6c_mcastgrp)) {
Yuval Mintz494fff52018-02-28 23:29:34 +02001475 list_del(&_uc->list);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001476 atomic_dec(&mrt->cache_resolve_queue_len);
Patrick McHardyf30a77842010-05-11 14:40:51 +02001477 found = true;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001478 break;
1479 }
1480 }
Yuval Mintzb70432f2018-02-28 23:29:32 +02001481 if (list_empty(&mrt->mfc_unres_queue))
Patrick McHardy6bd52142010-05-11 14:40:53 +02001482 del_timer(&mrt->ipmr_expire_timer);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001483 spin_unlock_bh(&mfc_unres_lock);
1484
Patrick McHardyf30a77842010-05-11 14:40:51 +02001485 if (found) {
Patrick McHardy6bd52142010-05-11 14:40:53 +02001486 ip6mr_cache_resolve(net, mrt, uc, c);
Benjamin Thery58701ad2008-12-10 16:22:34 -08001487 ip6mr_cache_free(uc);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001488 }
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001489 call_ip6mr_mfc_entry_notifiers(net, FIB_EVENT_ENTRY_ADD,
1490 c, mrt->id);
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00001491 mr6_netlink_event(mrt, c, RTM_NEWROUTE);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001492 return 0;
1493}
1494
1495/*
1496 * Close the multicast socket, and clear the vif tables etc
1497 */
1498
Yuval Mintzb70432f2018-02-28 23:29:32 +02001499static void mroute_clean_tables(struct mr_table *mrt, bool all)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001500{
Yuval Mintz494fff52018-02-28 23:29:34 +02001501 struct mr_mfc *c, *tmp;
Eric Dumazetc871e662009-10-28 04:48:11 +00001502 LIST_HEAD(list);
Yuval Mintz87c418b2018-02-28 23:29:31 +02001503 int i;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001504
Yuval Mintz87c418b2018-02-28 23:29:31 +02001505 /* Shut down all active vif entries */
Patrick McHardy6bd52142010-05-11 14:40:53 +02001506 for (i = 0; i < mrt->maxvif; i++) {
Yuval Mintzb70432f2018-02-28 23:29:32 +02001507 if (!all && (mrt->vif_table[i].flags & VIFF_STATIC))
Nikolay Aleksandrov4c698042015-11-20 13:54:20 +01001508 continue;
Nikolay Aleksandrov723b9292017-04-21 20:42:16 +03001509 mif6_delete(mrt, i, 0, &list);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001510 }
Eric Dumazetc871e662009-10-28 04:48:11 +00001511 unregister_netdevice_many(&list);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001512
Yuval Mintz87c418b2018-02-28 23:29:31 +02001513 /* Wipe the cache */
Yuval Mintzb70432f2018-02-28 23:29:32 +02001514 list_for_each_entry_safe(c, tmp, &mrt->mfc_cache_list, list) {
Yuval Mintz87c418b2018-02-28 23:29:31 +02001515 if (!all && (c->mfc_flags & MFC_STATIC))
1516 continue;
Yuval Mintzb70432f2018-02-28 23:29:32 +02001517 rhltable_remove(&mrt->mfc_hash, &c->mnode, ip6mr_rht_params);
Yuval Mintz87c418b2018-02-28 23:29:31 +02001518 list_del_rcu(&c->list);
Yuval Mintz494fff52018-02-28 23:29:34 +02001519 mr6_netlink_event(mrt, (struct mfc6_cache *)c, RTM_DELROUTE);
Yuval Mintz8c13af22018-03-26 15:01:36 +03001520 mr_cache_put(c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001521 }
1522
Patrick McHardy6bd52142010-05-11 14:40:53 +02001523 if (atomic_read(&mrt->cache_resolve_queue_len) != 0) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001524 spin_lock_bh(&mfc_unres_lock);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001525 list_for_each_entry_safe(c, tmp, &mrt->mfc_unres_queue, list) {
Patrick McHardyf30a77842010-05-11 14:40:51 +02001526 list_del(&c->list);
Yuval Mintz088aa3e2018-03-26 15:01:34 +03001527 call_ip6mr_mfc_entry_notifiers(read_pnet(&mrt->net),
1528 FIB_EVENT_ENTRY_DEL,
1529 (struct mfc6_cache *)c,
1530 mrt->id);
Yuval Mintz494fff52018-02-28 23:29:34 +02001531 mr6_netlink_event(mrt, (struct mfc6_cache *)c,
1532 RTM_DELROUTE);
1533 ip6mr_destroy_unres(mrt, (struct mfc6_cache *)c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001534 }
1535 spin_unlock_bh(&mfc_unres_lock);
1536 }
1537}
1538
Yuval Mintzb70432f2018-02-28 23:29:32 +02001539static int ip6mr_sk_init(struct mr_table *mrt, struct sock *sk)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001540{
1541 int err = 0;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001542 struct net *net = sock_net(sk);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001543
1544 rtnl_lock();
1545 write_lock_bh(&mrt_lock);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001546 if (rtnl_dereference(mrt->mroute_sk)) {
Eric Dumazet927265b2016-07-08 05:46:04 +02001547 err = -EADDRINUSE;
Yuval Mintz8571ab42018-02-28 23:29:30 +02001548 } else {
Yuval Mintzb70432f2018-02-28 23:29:32 +02001549 rcu_assign_pointer(mrt->mroute_sk, sk);
Eric Dumazeta366e302018-03-07 08:43:19 -08001550 sock_set_flag(sk, SOCK_RCU_FREE);
Yuval Mintz8571ab42018-02-28 23:29:30 +02001551 net->ipv6.devconf_all->mc_forwarding++;
Eric Dumazet927265b2016-07-08 05:46:04 +02001552 }
1553 write_unlock_bh(&mrt_lock);
1554
1555 if (!err)
David Ahern85b3daa2017-03-28 14:28:04 -07001556 inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
1557 NETCONFA_MC_FORWARDING,
Nicolas Dichteld67b8c62012-12-04 01:13:35 +00001558 NETCONFA_IFINDEX_ALL,
1559 net->ipv6.devconf_all);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001560 rtnl_unlock();
1561
1562 return err;
1563}
1564
1565int ip6mr_sk_done(struct sock *sk)
1566{
Patrick McHardyd1db2752010-05-11 14:40:55 +02001567 int err = -EACCES;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001568 struct net *net = sock_net(sk);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001569 struct mr_table *mrt;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001570
Francesco Ruggeri338d1822017-11-08 11:23:46 -08001571 if (sk->sk_type != SOCK_RAW ||
1572 inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
1573 return err;
1574
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001575 rtnl_lock();
Patrick McHardyd1db2752010-05-11 14:40:55 +02001576 ip6mr_for_each_table(mrt, net) {
Yuval Mintzb70432f2018-02-28 23:29:32 +02001577 if (sk == rtnl_dereference(mrt->mroute_sk)) {
Patrick McHardyd1db2752010-05-11 14:40:55 +02001578 write_lock_bh(&mrt_lock);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001579 RCU_INIT_POINTER(mrt->mroute_sk, NULL);
Eric Dumazeta366e302018-03-07 08:43:19 -08001580 /* Note that mroute_sk had SOCK_RCU_FREE set,
1581 * so the RCU grace period before sk freeing
1582 * is guaranteed by sk_destruct()
1583 */
Patrick McHardyd1db2752010-05-11 14:40:55 +02001584 net->ipv6.devconf_all->mc_forwarding--;
Eric Dumazet927265b2016-07-08 05:46:04 +02001585 write_unlock_bh(&mrt_lock);
David Ahern85b3daa2017-03-28 14:28:04 -07001586 inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
Nicolas Dichteld67b8c62012-12-04 01:13:35 +00001587 NETCONFA_MC_FORWARDING,
1588 NETCONFA_IFINDEX_ALL,
1589 net->ipv6.devconf_all);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001590
Nikolay Aleksandrov4c698042015-11-20 13:54:20 +01001591 mroute_clean_tables(mrt, false);
Patrick McHardyd1db2752010-05-11 14:40:55 +02001592 err = 0;
1593 break;
1594 }
1595 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001596 rtnl_unlock();
1597
1598 return err;
1599}
1600
Yuval Mintz8571ab42018-02-28 23:29:30 +02001601bool mroute6_is_socket(struct net *net, struct sk_buff *skb)
Patrick McHardy6bd52142010-05-11 14:40:53 +02001602{
Yuval Mintzb70432f2018-02-28 23:29:32 +02001603 struct mr_table *mrt;
David S. Miller4c9483b2011-03-12 16:22:43 -05001604 struct flowi6 fl6 = {
Julian Anastasove374c612014-04-28 10:51:56 +03001605 .flowi6_iif = skb->skb_iif ? : LOOPBACK_IFINDEX,
David S. Miller4c9483b2011-03-12 16:22:43 -05001606 .flowi6_oif = skb->dev->ifindex,
1607 .flowi6_mark = skb->mark,
Patrick McHardyd1db2752010-05-11 14:40:55 +02001608 };
1609
David S. Miller4c9483b2011-03-12 16:22:43 -05001610 if (ip6mr_fib_lookup(net, &fl6, &mrt) < 0)
Patrick McHardyd1db2752010-05-11 14:40:55 +02001611 return NULL;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001612
Yuval Mintzb70432f2018-02-28 23:29:32 +02001613 return rcu_access_pointer(mrt->mroute_sk);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001614}
Yuval Mintz8571ab42018-02-28 23:29:30 +02001615EXPORT_SYMBOL(mroute6_is_socket);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001616
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001617/*
1618 * Socket options and virtual interface manipulation. The whole
1619 * virtual interface system is a complete heap, but unfortunately
1620 * that's how BSD mrouted happens to think. Maybe one day with a proper
1621 * MOSPF/PIM router set up we can clean this up.
1622 */
1623
David S. Millerb7058842009-09-30 16:12:20 -07001624int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsigned int optlen)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001625{
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001626 int ret, parent = 0;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001627 struct mif6ctl vif;
1628 struct mf6cctl mfc;
1629 mifi_t mifi;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001630 struct net *net = sock_net(sk);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001631 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +02001632
Xin Long99253eb2017-02-24 16:29:06 +08001633 if (sk->sk_type != SOCK_RAW ||
1634 inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
1635 return -EOPNOTSUPP;
1636
Patrick McHardyd1db2752010-05-11 14:40:55 +02001637 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +01001638 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +02001639 return -ENOENT;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001640
1641 if (optname != MRT6_INIT) {
Yuval Mintzb70432f2018-02-28 23:29:32 +02001642 if (sk != rcu_access_pointer(mrt->mroute_sk) &&
Yuval Mintz8571ab42018-02-28 23:29:30 +02001643 !ns_capable(net->user_ns, CAP_NET_ADMIN))
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001644 return -EACCES;
1645 }
1646
1647 switch (optname) {
1648 case MRT6_INIT:
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001649 if (optlen < sizeof(int))
1650 return -EINVAL;
1651
Patrick McHardy6bd52142010-05-11 14:40:53 +02001652 return ip6mr_sk_init(mrt, sk);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001653
1654 case MRT6_DONE:
1655 return ip6mr_sk_done(sk);
1656
1657 case MRT6_ADD_MIF:
1658 if (optlen < sizeof(vif))
1659 return -EINVAL;
1660 if (copy_from_user(&vif, optval, sizeof(vif)))
1661 return -EFAULT;
Rami Rosen6ac7eb02008-04-10 12:40:10 +03001662 if (vif.mif6c_mifi >= MAXMIFS)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001663 return -ENFILE;
1664 rtnl_lock();
Yuval Mintz8571ab42018-02-28 23:29:30 +02001665 ret = mif6_add(net, mrt, &vif,
Yuval Mintzb70432f2018-02-28 23:29:32 +02001666 sk == rtnl_dereference(mrt->mroute_sk));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001667 rtnl_unlock();
1668 return ret;
1669
1670 case MRT6_DEL_MIF:
1671 if (optlen < sizeof(mifi_t))
1672 return -EINVAL;
1673 if (copy_from_user(&mifi, optval, sizeof(mifi_t)))
1674 return -EFAULT;
1675 rtnl_lock();
Nikolay Aleksandrov723b9292017-04-21 20:42:16 +03001676 ret = mif6_delete(mrt, mifi, 0, NULL);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001677 rtnl_unlock();
1678 return ret;
1679
1680 /*
1681 * Manipulate the forwarding caches. These live
1682 * in a sort of kernel/user symbiosis.
1683 */
1684 case MRT6_ADD_MFC:
1685 case MRT6_DEL_MFC:
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001686 parent = -1;
Gustavo A. R. Silva275757e62017-10-16 16:36:52 -05001687 /* fall through */
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001688 case MRT6_ADD_MFC_PROXY:
1689 case MRT6_DEL_MFC_PROXY:
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001690 if (optlen < sizeof(mfc))
1691 return -EINVAL;
1692 if (copy_from_user(&mfc, optval, sizeof(mfc)))
1693 return -EFAULT;
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001694 if (parent == 0)
1695 parent = mfc.mf6cc_parent;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001696 rtnl_lock();
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001697 if (optname == MRT6_DEL_MFC || optname == MRT6_DEL_MFC_PROXY)
1698 ret = ip6mr_mfc_delete(mrt, &mfc, parent);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001699 else
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00001700 ret = ip6mr_mfc_add(net, mrt, &mfc,
Yuval Mintz8571ab42018-02-28 23:29:30 +02001701 sk ==
Yuval Mintzb70432f2018-02-28 23:29:32 +02001702 rtnl_dereference(mrt->mroute_sk),
Yuval Mintz8571ab42018-02-28 23:29:30 +02001703 parent);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001704 rtnl_unlock();
1705 return ret;
1706
1707 /*
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001708 * Control PIM assert (to activate pim will activate assert)
1709 */
1710 case MRT6_ASSERT:
1711 {
1712 int v;
Joe Perches03f52a02012-11-25 18:26:34 +00001713
1714 if (optlen != sizeof(v))
1715 return -EINVAL;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001716 if (get_user(v, (int __user *)optval))
1717 return -EFAULT;
Joe Perches53d68412012-11-25 09:35:30 +00001718 mrt->mroute_do_assert = v;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001719 return 0;
1720 }
1721
1722#ifdef CONFIG_IPV6_PIMSM_V2
1723 case MRT6_PIM:
1724 {
YOSHIFUJI Hideakia9f83bf2008-04-10 15:41:28 +09001725 int v;
Joe Perches03f52a02012-11-25 18:26:34 +00001726
1727 if (optlen != sizeof(v))
1728 return -EINVAL;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001729 if (get_user(v, (int __user *)optval))
1730 return -EFAULT;
1731 v = !!v;
1732 rtnl_lock();
1733 ret = 0;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001734 if (v != mrt->mroute_do_pim) {
1735 mrt->mroute_do_pim = v;
1736 mrt->mroute_do_assert = v;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001737 }
1738 rtnl_unlock();
1739 return ret;
1740 }
1741
1742#endif
Patrick McHardyd1db2752010-05-11 14:40:55 +02001743#ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
1744 case MRT6_TABLE:
1745 {
1746 u32 v;
1747
1748 if (optlen != sizeof(u32))
1749 return -EINVAL;
1750 if (get_user(v, (u32 __user *)optval))
1751 return -EFAULT;
Dan Carpenter75356a82013-01-23 20:38:34 +00001752 /* "pim6reg%u" should not exceed 16 bytes (IFNAMSIZ) */
1753 if (v != RT_TABLE_DEFAULT && v >= 100000000)
1754 return -EINVAL;
Yuval Mintzb70432f2018-02-28 23:29:32 +02001755 if (sk == rcu_access_pointer(mrt->mroute_sk))
Patrick McHardyd1db2752010-05-11 14:40:55 +02001756 return -EBUSY;
1757
1758 rtnl_lock();
1759 ret = 0;
1760 if (!ip6mr_new_table(net, v))
1761 ret = -ENOMEM;
1762 raw6_sk(sk)->ip6mr_table = v;
1763 rtnl_unlock();
1764 return ret;
1765 }
1766#endif
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001767 /*
Rami Rosen7d120c52008-04-23 14:35:13 +03001768 * Spurious command, or MRT6_VERSION which you cannot
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001769 * set.
1770 */
1771 default:
1772 return -ENOPROTOOPT;
1773 }
1774}
1775
1776/*
1777 * Getsock opt support for the multicast routing system.
1778 */
1779
1780int ip6_mroute_getsockopt(struct sock *sk, int optname, char __user *optval,
1781 int __user *optlen)
1782{
1783 int olr;
1784 int val;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001785 struct net *net = sock_net(sk);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001786 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +02001787
Xin Long99253eb2017-02-24 16:29:06 +08001788 if (sk->sk_type != SOCK_RAW ||
1789 inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
1790 return -EOPNOTSUPP;
1791
Patrick McHardyd1db2752010-05-11 14:40:55 +02001792 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +01001793 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +02001794 return -ENOENT;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001795
1796 switch (optname) {
1797 case MRT6_VERSION:
1798 val = 0x0305;
1799 break;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001800#ifdef CONFIG_IPV6_PIMSM_V2
1801 case MRT6_PIM:
Patrick McHardy6bd52142010-05-11 14:40:53 +02001802 val = mrt->mroute_do_pim;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001803 break;
1804#endif
1805 case MRT6_ASSERT:
Patrick McHardy6bd52142010-05-11 14:40:53 +02001806 val = mrt->mroute_do_assert;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001807 break;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001808 default:
1809 return -ENOPROTOOPT;
1810 }
1811
1812 if (get_user(olr, optlen))
1813 return -EFAULT;
1814
1815 olr = min_t(int, olr, sizeof(int));
1816 if (olr < 0)
1817 return -EINVAL;
1818
1819 if (put_user(olr, optlen))
1820 return -EFAULT;
1821 if (copy_to_user(optval, &val, olr))
1822 return -EFAULT;
1823 return 0;
1824}
1825
1826/*
1827 * The IP multicast ioctl support routines.
1828 */
1829
1830int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg)
1831{
1832 struct sioc_sg_req6 sr;
1833 struct sioc_mif_req6 vr;
Yuval Mintz6853f212018-02-28 23:29:29 +02001834 struct vif_device *vif;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001835 struct mfc6_cache *c;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001836 struct net *net = sock_net(sk);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001837 struct mr_table *mrt;
Patrick McHardyd1db2752010-05-11 14:40:55 +02001838
1839 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +01001840 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +02001841 return -ENOENT;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001842
1843 switch (cmd) {
1844 case SIOCGETMIFCNT_IN6:
1845 if (copy_from_user(&vr, arg, sizeof(vr)))
1846 return -EFAULT;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001847 if (vr.mifi >= mrt->maxvif)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001848 return -EINVAL;
1849 read_lock(&mrt_lock);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001850 vif = &mrt->vif_table[vr.mifi];
1851 if (VIF_EXISTS(mrt, vr.mifi)) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001852 vr.icount = vif->pkt_in;
1853 vr.ocount = vif->pkt_out;
1854 vr.ibytes = vif->bytes_in;
1855 vr.obytes = vif->bytes_out;
1856 read_unlock(&mrt_lock);
1857
1858 if (copy_to_user(arg, &vr, sizeof(vr)))
1859 return -EFAULT;
1860 return 0;
1861 }
1862 read_unlock(&mrt_lock);
1863 return -EADDRNOTAVAIL;
1864 case SIOCGETSGCNT_IN6:
1865 if (copy_from_user(&sr, arg, sizeof(sr)))
1866 return -EFAULT;
1867
Yuval Mintz87c418b2018-02-28 23:29:31 +02001868 rcu_read_lock();
Patrick McHardy6bd52142010-05-11 14:40:53 +02001869 c = ip6mr_cache_find(mrt, &sr.src.sin6_addr, &sr.grp.sin6_addr);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001870 if (c) {
Yuval Mintz494fff52018-02-28 23:29:34 +02001871 sr.pktcnt = c->_c.mfc_un.res.pkt;
1872 sr.bytecnt = c->_c.mfc_un.res.bytes;
1873 sr.wrong_if = c->_c.mfc_un.res.wrong_if;
Yuval Mintz87c418b2018-02-28 23:29:31 +02001874 rcu_read_unlock();
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001875
1876 if (copy_to_user(arg, &sr, sizeof(sr)))
1877 return -EFAULT;
1878 return 0;
1879 }
Yuval Mintz87c418b2018-02-28 23:29:31 +02001880 rcu_read_unlock();
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001881 return -EADDRNOTAVAIL;
1882 default:
1883 return -ENOIOCTLCMD;
1884 }
1885}
1886
David S. Millere2d57762011-02-03 17:59:32 -08001887#ifdef CONFIG_COMPAT
1888struct compat_sioc_sg_req6 {
1889 struct sockaddr_in6 src;
1890 struct sockaddr_in6 grp;
1891 compat_ulong_t pktcnt;
1892 compat_ulong_t bytecnt;
1893 compat_ulong_t wrong_if;
1894};
1895
1896struct compat_sioc_mif_req6 {
1897 mifi_t mifi;
1898 compat_ulong_t icount;
1899 compat_ulong_t ocount;
1900 compat_ulong_t ibytes;
1901 compat_ulong_t obytes;
1902};
1903
1904int ip6mr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg)
1905{
1906 struct compat_sioc_sg_req6 sr;
1907 struct compat_sioc_mif_req6 vr;
Yuval Mintz6853f212018-02-28 23:29:29 +02001908 struct vif_device *vif;
David S. Millere2d57762011-02-03 17:59:32 -08001909 struct mfc6_cache *c;
1910 struct net *net = sock_net(sk);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001911 struct mr_table *mrt;
David S. Millere2d57762011-02-03 17:59:32 -08001912
1913 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +01001914 if (!mrt)
David S. Millere2d57762011-02-03 17:59:32 -08001915 return -ENOENT;
1916
1917 switch (cmd) {
1918 case SIOCGETMIFCNT_IN6:
1919 if (copy_from_user(&vr, arg, sizeof(vr)))
1920 return -EFAULT;
1921 if (vr.mifi >= mrt->maxvif)
1922 return -EINVAL;
1923 read_lock(&mrt_lock);
Yuval Mintzb70432f2018-02-28 23:29:32 +02001924 vif = &mrt->vif_table[vr.mifi];
1925 if (VIF_EXISTS(mrt, vr.mifi)) {
David S. Millere2d57762011-02-03 17:59:32 -08001926 vr.icount = vif->pkt_in;
1927 vr.ocount = vif->pkt_out;
1928 vr.ibytes = vif->bytes_in;
1929 vr.obytes = vif->bytes_out;
1930 read_unlock(&mrt_lock);
1931
1932 if (copy_to_user(arg, &vr, sizeof(vr)))
1933 return -EFAULT;
1934 return 0;
1935 }
1936 read_unlock(&mrt_lock);
1937 return -EADDRNOTAVAIL;
1938 case SIOCGETSGCNT_IN6:
1939 if (copy_from_user(&sr, arg, sizeof(sr)))
1940 return -EFAULT;
1941
Yuval Mintz87c418b2018-02-28 23:29:31 +02001942 rcu_read_lock();
David S. Millere2d57762011-02-03 17:59:32 -08001943 c = ip6mr_cache_find(mrt, &sr.src.sin6_addr, &sr.grp.sin6_addr);
1944 if (c) {
Yuval Mintz494fff52018-02-28 23:29:34 +02001945 sr.pktcnt = c->_c.mfc_un.res.pkt;
1946 sr.bytecnt = c->_c.mfc_un.res.bytes;
1947 sr.wrong_if = c->_c.mfc_un.res.wrong_if;
Yuval Mintz87c418b2018-02-28 23:29:31 +02001948 rcu_read_unlock();
David S. Millere2d57762011-02-03 17:59:32 -08001949
1950 if (copy_to_user(arg, &sr, sizeof(sr)))
1951 return -EFAULT;
1952 return 0;
1953 }
Yuval Mintz87c418b2018-02-28 23:29:31 +02001954 rcu_read_unlock();
David S. Millere2d57762011-02-03 17:59:32 -08001955 return -EADDRNOTAVAIL;
1956 default:
1957 return -ENOIOCTLCMD;
1958 }
1959}
1960#endif
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001961
Eric W. Biederman0c4b51f2015-09-15 20:04:18 -05001962static inline int ip6mr_forward2_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001963{
Eric Dumazet1d015502016-04-27 16:44:40 -07001964 __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
1965 IPSTATS_MIB_OUTFORWDATAGRAMS);
1966 __IP6_ADD_STATS(net, ip6_dst_idev(skb_dst(skb)),
1967 IPSTATS_MIB_OUTOCTETS, skb->len);
Eric W. Biederman13206b62015-10-07 16:48:35 -05001968 return dst_output(net, sk, skb);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001969}
1970
1971/*
1972 * Processing handlers for ip6mr_forward
1973 */
1974
Yuval Mintzb70432f2018-02-28 23:29:32 +02001975static int ip6mr_forward2(struct net *net, struct mr_table *mrt,
Patrick McHardy6bd52142010-05-11 14:40:53 +02001976 struct sk_buff *skb, struct mfc6_cache *c, int vifi)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001977{
1978 struct ipv6hdr *ipv6h;
Yuval Mintzb70432f2018-02-28 23:29:32 +02001979 struct vif_device *vif = &mrt->vif_table[vifi];
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001980 struct net_device *dev;
1981 struct dst_entry *dst;
David S. Miller4c9483b2011-03-12 16:22:43 -05001982 struct flowi6 fl6;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001983
Ian Morris63159f22015-03-29 14:00:04 +01001984 if (!vif->dev)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001985 goto out_free;
1986
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001987#ifdef CONFIG_IPV6_PIMSM_V2
1988 if (vif->flags & MIFF_REGISTER) {
1989 vif->pkt_out++;
1990 vif->bytes_out += skb->len;
Pavel Emelyanovdc58c782008-05-21 14:17:54 -07001991 vif->dev->stats.tx_bytes += skb->len;
1992 vif->dev->stats.tx_packets++;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001993 ip6mr_cache_report(mrt, skb, vifi, MRT6MSG_WHOLEPKT);
Ilpo Järvinen8da73b72008-12-14 23:15:49 -08001994 goto out_free;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001995 }
1996#endif
1997
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001998 ipv6h = ipv6_hdr(skb);
1999
David S. Miller4c9483b2011-03-12 16:22:43 -05002000 fl6 = (struct flowi6) {
2001 .flowi6_oif = vif->link,
2002 .daddr = ipv6h->daddr,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002003 };
2004
David S. Miller4c9483b2011-03-12 16:22:43 -05002005 dst = ip6_route_output(net, NULL, &fl6);
RongQing.Li5095d642012-02-21 22:10:49 +00002006 if (dst->error) {
2007 dst_release(dst);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002008 goto out_free;
RongQing.Li5095d642012-02-21 22:10:49 +00002009 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002010
Eric Dumazetadf30902009-06-02 05:19:30 +00002011 skb_dst_drop(skb);
2012 skb_dst_set(skb, dst);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002013
2014 /*
2015 * RFC1584 teaches, that DVMRP/PIM router must deliver packets locally
2016 * not only before forwarding, but after forwarding on all output
2017 * interfaces. It is clear, if mrouter runs a multicasting
2018 * program, it should receive packets not depending to what interface
2019 * program is joined.
2020 * If we will not make it, the program will have to join on all
2021 * interfaces. On the other hand, multihoming host (or router, but
2022 * not mrouter) cannot join to more than one interface - it will
2023 * result in receiving multiple packets.
2024 */
2025 dev = vif->dev;
2026 skb->dev = dev;
2027 vif->pkt_out++;
2028 vif->bytes_out += skb->len;
2029
2030 /* We are about to write */
2031 /* XXX: extension headers? */
2032 if (skb_cow(skb, sizeof(*ipv6h) + LL_RESERVED_SPACE(dev)))
2033 goto out_free;
2034
2035 ipv6h = ipv6_hdr(skb);
2036 ipv6h->hop_limit--;
2037
2038 IP6CB(skb)->flags |= IP6SKB_FORWARDED;
2039
Eric W. Biederman29a26a52015-09-15 20:04:16 -05002040 return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD,
2041 net, NULL, skb, skb->dev, dev,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002042 ip6mr_forward2_finish);
2043
2044out_free:
2045 kfree_skb(skb);
2046 return 0;
2047}
2048
Yuval Mintzb70432f2018-02-28 23:29:32 +02002049static int ip6mr_find_vif(struct mr_table *mrt, struct net_device *dev)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002050{
2051 int ct;
Patrick McHardy6bd52142010-05-11 14:40:53 +02002052
2053 for (ct = mrt->maxvif - 1; ct >= 0; ct--) {
Yuval Mintzb70432f2018-02-28 23:29:32 +02002054 if (mrt->vif_table[ct].dev == dev)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002055 break;
2056 }
2057 return ct;
2058}
2059
Yuval Mintzb70432f2018-02-28 23:29:32 +02002060static void ip6_mr_forward(struct net *net, struct mr_table *mrt,
Yuval Mintz494fff52018-02-28 23:29:34 +02002061 struct sk_buff *skb, struct mfc6_cache *c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002062{
2063 int psend = -1;
2064 int vif, ct;
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002065 int true_vifi = ip6mr_find_vif(mrt, skb->dev);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002066
Yuval Mintz494fff52018-02-28 23:29:34 +02002067 vif = c->_c.mfc_parent;
2068 c->_c.mfc_un.res.pkt++;
2069 c->_c.mfc_un.res.bytes += skb->len;
2070 c->_c.mfc_un.res.lastuse = jiffies;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002071
Yuval Mintz494fff52018-02-28 23:29:34 +02002072 if (ipv6_addr_any(&c->mf6c_origin) && true_vifi >= 0) {
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002073 struct mfc6_cache *cache_proxy;
2074
Fabian Frederick40dc2ca2014-10-29 10:00:26 +01002075 /* For an (*,G) entry, we only check that the incoming
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002076 * interface is part of the static tree.
2077 */
Yuval Mintz87c418b2018-02-28 23:29:31 +02002078 rcu_read_lock();
Yuval Mintz845c9a72018-02-28 23:29:35 +02002079 cache_proxy = mr_mfc_find_any_parent(mrt, vif);
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002080 if (cache_proxy &&
Yuval Mintz494fff52018-02-28 23:29:34 +02002081 cache_proxy->_c.mfc_un.res.ttls[true_vifi] < 255) {
Yuval Mintz87c418b2018-02-28 23:29:31 +02002082 rcu_read_unlock();
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002083 goto forward;
Yuval Mintz87c418b2018-02-28 23:29:31 +02002084 }
2085 rcu_read_unlock();
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002086 }
2087
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002088 /*
2089 * Wrong interface: drop packet and (maybe) send PIM assert.
2090 */
Yuval Mintzb70432f2018-02-28 23:29:32 +02002091 if (mrt->vif_table[vif].dev != skb->dev) {
Yuval Mintz494fff52018-02-28 23:29:34 +02002092 c->_c.mfc_un.res.wrong_if++;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002093
Patrick McHardy6bd52142010-05-11 14:40:53 +02002094 if (true_vifi >= 0 && mrt->mroute_do_assert &&
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002095 /* pimsm uses asserts, when switching from RPT to SPT,
2096 so that we cannot check that packet arrived on an oif.
2097 It is bad, but otherwise we would need to move pretty
2098 large chunk of pimd to kernel. Ough... --ANK
2099 */
Patrick McHardy6bd52142010-05-11 14:40:53 +02002100 (mrt->mroute_do_pim ||
Yuval Mintz494fff52018-02-28 23:29:34 +02002101 c->_c.mfc_un.res.ttls[true_vifi] < 255) &&
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002102 time_after(jiffies,
Yuval Mintz494fff52018-02-28 23:29:34 +02002103 c->_c.mfc_un.res.last_assert +
2104 MFC_ASSERT_THRESH)) {
2105 c->_c.mfc_un.res.last_assert = jiffies;
Patrick McHardy6bd52142010-05-11 14:40:53 +02002106 ip6mr_cache_report(mrt, skb, true_vifi, MRT6MSG_WRONGMIF);
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002107 }
2108 goto dont_forward;
2109 }
2110
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002111forward:
Yuval Mintzb70432f2018-02-28 23:29:32 +02002112 mrt->vif_table[vif].pkt_in++;
2113 mrt->vif_table[vif].bytes_in += skb->len;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002114
2115 /*
2116 * Forward the frame
2117 */
Yuval Mintz494fff52018-02-28 23:29:34 +02002118 if (ipv6_addr_any(&c->mf6c_origin) &&
2119 ipv6_addr_any(&c->mf6c_mcastgrp)) {
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002120 if (true_vifi >= 0 &&
Yuval Mintz494fff52018-02-28 23:29:34 +02002121 true_vifi != c->_c.mfc_parent &&
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002122 ipv6_hdr(skb)->hop_limit >
Yuval Mintz494fff52018-02-28 23:29:34 +02002123 c->_c.mfc_un.res.ttls[c->_c.mfc_parent]) {
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002124 /* It's an (*,*) entry and the packet is not coming from
2125 * the upstream: forward the packet to the upstream
2126 * only.
2127 */
Yuval Mintz494fff52018-02-28 23:29:34 +02002128 psend = c->_c.mfc_parent;
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002129 goto last_forward;
2130 }
2131 goto dont_forward;
2132 }
Yuval Mintz494fff52018-02-28 23:29:34 +02002133 for (ct = c->_c.mfc_un.res.maxvif - 1;
2134 ct >= c->_c.mfc_un.res.minvif; ct--) {
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002135 /* For (*,G) entry, don't forward to the incoming interface */
Yuval Mintz494fff52018-02-28 23:29:34 +02002136 if ((!ipv6_addr_any(&c->mf6c_origin) || ct != true_vifi) &&
2137 ipv6_hdr(skb)->hop_limit > c->_c.mfc_un.res.ttls[ct]) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002138 if (psend != -1) {
2139 struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
2140 if (skb2)
Yuval Mintz494fff52018-02-28 23:29:34 +02002141 ip6mr_forward2(net, mrt, skb2,
2142 c, psend);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002143 }
2144 psend = ct;
2145 }
2146 }
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002147last_forward:
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002148 if (psend != -1) {
Yuval Mintz494fff52018-02-28 23:29:34 +02002149 ip6mr_forward2(net, mrt, skb, c, psend);
Rami Rosen2b52c3a2013-07-21 03:00:31 +03002150 return;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002151 }
2152
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09002153dont_forward:
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002154 kfree_skb(skb);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002155}
2156
2157
2158/*
2159 * Multicast packets for forwarding arrive here
2160 */
2161
2162int ip6_mr_input(struct sk_buff *skb)
2163{
2164 struct mfc6_cache *cache;
Benjamin Thery8229efd2008-12-10 16:30:15 -08002165 struct net *net = dev_net(skb->dev);
Yuval Mintzb70432f2018-02-28 23:29:32 +02002166 struct mr_table *mrt;
David S. Miller4c9483b2011-03-12 16:22:43 -05002167 struct flowi6 fl6 = {
2168 .flowi6_iif = skb->dev->ifindex,
2169 .flowi6_mark = skb->mark,
Patrick McHardyd1db2752010-05-11 14:40:55 +02002170 };
2171 int err;
2172
David S. Miller4c9483b2011-03-12 16:22:43 -05002173 err = ip6mr_fib_lookup(net, &fl6, &mrt);
Ben Greear2015de52011-09-27 15:16:08 -04002174 if (err < 0) {
2175 kfree_skb(skb);
Patrick McHardyd1db2752010-05-11 14:40:55 +02002176 return err;
Ben Greear2015de52011-09-27 15:16:08 -04002177 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002178
2179 read_lock(&mrt_lock);
Patrick McHardy6bd52142010-05-11 14:40:53 +02002180 cache = ip6mr_cache_find(mrt,
Benjamin Thery8229efd2008-12-10 16:30:15 -08002181 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr);
Ian Morris63159f22015-03-29 14:00:04 +01002182 if (!cache) {
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002183 int vif = ip6mr_find_vif(mrt, skb->dev);
2184
2185 if (vif >= 0)
2186 cache = ip6mr_cache_find_any(mrt,
2187 &ipv6_hdr(skb)->daddr,
2188 vif);
2189 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002190
2191 /*
2192 * No usable cache entry
2193 */
Ian Morris63159f22015-03-29 14:00:04 +01002194 if (!cache) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002195 int vif;
2196
Patrick McHardy6bd52142010-05-11 14:40:53 +02002197 vif = ip6mr_find_vif(mrt, skb->dev);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002198 if (vif >= 0) {
Patrick McHardy6bd52142010-05-11 14:40:53 +02002199 int err = ip6mr_cache_unresolved(mrt, vif, skb);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002200 read_unlock(&mrt_lock);
2201
2202 return err;
2203 }
2204 read_unlock(&mrt_lock);
2205 kfree_skb(skb);
2206 return -ENODEV;
2207 }
2208
Patrick McHardy6bd52142010-05-11 14:40:53 +02002209 ip6_mr_forward(net, mrt, skb, cache);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002210
2211 read_unlock(&mrt_lock);
2212
2213 return 0;
2214}
2215
Nikolay Aleksandrov2cf75072016-09-25 23:08:31 +02002216int ip6mr_get_route(struct net *net, struct sk_buff *skb, struct rtmsg *rtm,
David Ahernfd61c6b2017-01-17 15:51:07 -08002217 u32 portid)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002218{
2219 int err;
Yuval Mintzb70432f2018-02-28 23:29:32 +02002220 struct mr_table *mrt;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002221 struct mfc6_cache *cache;
Eric Dumazetadf30902009-06-02 05:19:30 +00002222 struct rt6_info *rt = (struct rt6_info *)skb_dst(skb);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002223
Patrick McHardyd1db2752010-05-11 14:40:55 +02002224 mrt = ip6mr_get_table(net, RT6_TABLE_DFLT);
Ian Morris63159f22015-03-29 14:00:04 +01002225 if (!mrt)
Patrick McHardyd1db2752010-05-11 14:40:55 +02002226 return -ENOENT;
2227
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002228 read_lock(&mrt_lock);
Patrick McHardy6bd52142010-05-11 14:40:53 +02002229 cache = ip6mr_cache_find(mrt, &rt->rt6i_src.addr, &rt->rt6i_dst.addr);
Nicolas Dichtel660b26d2013-01-21 06:00:26 +00002230 if (!cache && skb->dev) {
2231 int vif = ip6mr_find_vif(mrt, skb->dev);
2232
2233 if (vif >= 0)
2234 cache = ip6mr_cache_find_any(mrt, &rt->rt6i_dst.addr,
2235 vif);
2236 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002237
2238 if (!cache) {
2239 struct sk_buff *skb2;
2240 struct ipv6hdr *iph;
2241 struct net_device *dev;
2242 int vif;
2243
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002244 dev = skb->dev;
Ian Morris63159f22015-03-29 14:00:04 +01002245 if (!dev || (vif = ip6mr_find_vif(mrt, dev)) < 0) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002246 read_unlock(&mrt_lock);
2247 return -ENODEV;
2248 }
2249
2250 /* really correct? */
2251 skb2 = alloc_skb(sizeof(struct ipv6hdr), GFP_ATOMIC);
2252 if (!skb2) {
2253 read_unlock(&mrt_lock);
2254 return -ENOMEM;
2255 }
2256
Nikolay Aleksandrov2cf75072016-09-25 23:08:31 +02002257 NETLINK_CB(skb2).portid = portid;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002258 skb_reset_transport_header(skb2);
2259
2260 skb_put(skb2, sizeof(struct ipv6hdr));
2261 skb_reset_network_header(skb2);
2262
2263 iph = ipv6_hdr(skb2);
2264 iph->version = 0;
2265 iph->priority = 0;
2266 iph->flow_lbl[0] = 0;
2267 iph->flow_lbl[1] = 0;
2268 iph->flow_lbl[2] = 0;
2269 iph->payload_len = 0;
2270 iph->nexthdr = IPPROTO_NONE;
2271 iph->hop_limit = 0;
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +00002272 iph->saddr = rt->rt6i_src.addr;
2273 iph->daddr = rt->rt6i_dst.addr;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002274
Patrick McHardy6bd52142010-05-11 14:40:53 +02002275 err = ip6mr_cache_unresolved(mrt, vif, skb2);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002276 read_unlock(&mrt_lock);
2277
2278 return err;
2279 }
2280
Yuval Mintz7b0db852018-02-28 23:29:39 +02002281 err = mr_fill_mroute(mrt, skb, &cache->_c, rtm);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09002282 read_unlock(&mrt_lock);
2283 return err;
2284}
2285
Yuval Mintzb70432f2018-02-28 23:29:32 +02002286static int ip6mr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
Nicolas Dichtelf5183382014-03-19 17:47:51 +01002287 u32 portid, u32 seq, struct mfc6_cache *c, int cmd,
2288 int flags)
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002289{
2290 struct nlmsghdr *nlh;
2291 struct rtmsg *rtm;
Nicolas Dichtel1eb99af2012-12-04 01:13:39 +00002292 int err;
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002293
Nicolas Dichtelf5183382014-03-19 17:47:51 +01002294 nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rtm), flags);
Ian Morris63159f22015-03-29 14:00:04 +01002295 if (!nlh)
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002296 return -EMSGSIZE;
2297
2298 rtm = nlmsg_data(nlh);
Nicolas Dichtel193c1e42012-12-04 01:01:49 +00002299 rtm->rtm_family = RTNL_FAMILY_IP6MR;
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002300 rtm->rtm_dst_len = 128;
2301 rtm->rtm_src_len = 128;
2302 rtm->rtm_tos = 0;
2303 rtm->rtm_table = mrt->id;
David S. Millerc78679e2012-04-01 20:27:33 -04002304 if (nla_put_u32(skb, RTA_TABLE, mrt->id))
2305 goto nla_put_failure;
Nicolas Dichtel1eb99af2012-12-04 01:13:39 +00002306 rtm->rtm_type = RTN_MULTICAST;
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002307 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
Yuval Mintz494fff52018-02-28 23:29:34 +02002308 if (c->_c.mfc_flags & MFC_STATIC)
Nicolas Dichtel9a68ac72012-12-04 01:13:38 +00002309 rtm->rtm_protocol = RTPROT_STATIC;
2310 else
2311 rtm->rtm_protocol = RTPROT_MROUTED;
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002312 rtm->rtm_flags = 0;
2313
Jiri Benc930345e2015-03-29 16:59:25 +02002314 if (nla_put_in6_addr(skb, RTA_SRC, &c->mf6c_origin) ||
2315 nla_put_in6_addr(skb, RTA_DST, &c->mf6c_mcastgrp))
David S. Millerc78679e2012-04-01 20:27:33 -04002316 goto nla_put_failure;
Yuval Mintz7b0db852018-02-28 23:29:39 +02002317 err = mr_fill_mroute(mrt, skb, &c->_c, rtm);
Nicolas Dichtel1eb99af2012-12-04 01:13:39 +00002318 /* do not break the dump if cache is unresolved */
2319 if (err < 0 && err != -ENOENT)
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002320 goto nla_put_failure;
2321
Johannes Berg053c0952015-01-16 22:09:00 +01002322 nlmsg_end(skb, nlh);
2323 return 0;
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002324
2325nla_put_failure:
2326 nlmsg_cancel(skb, nlh);
2327 return -EMSGSIZE;
2328}
2329
Yuval Mintz7b0db852018-02-28 23:29:39 +02002330static int _ip6mr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
2331 u32 portid, u32 seq, struct mr_mfc *c,
2332 int cmd, int flags)
2333{
2334 return ip6mr_fill_mroute(mrt, skb, portid, seq, (struct mfc6_cache *)c,
2335 cmd, flags);
2336}
2337
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002338static int mr6_msgsize(bool unresolved, int maxvif)
2339{
2340 size_t len =
2341 NLMSG_ALIGN(sizeof(struct rtmsg))
2342 + nla_total_size(4) /* RTA_TABLE */
2343 + nla_total_size(sizeof(struct in6_addr)) /* RTA_SRC */
2344 + nla_total_size(sizeof(struct in6_addr)) /* RTA_DST */
2345 ;
2346
2347 if (!unresolved)
2348 len = len
2349 + nla_total_size(4) /* RTA_IIF */
2350 + nla_total_size(0) /* RTA_MULTIPATH */
2351 + maxvif * NLA_ALIGN(sizeof(struct rtnexthop))
2352 /* RTA_MFC_STATS */
Nicolas Dichtel3d6b66c2016-04-21 18:58:27 +02002353 + nla_total_size_64bit(sizeof(struct rta_mfc_stats))
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002354 ;
2355
2356 return len;
2357}
2358
Yuval Mintzb70432f2018-02-28 23:29:32 +02002359static void mr6_netlink_event(struct mr_table *mrt, struct mfc6_cache *mfc,
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002360 int cmd)
2361{
2362 struct net *net = read_pnet(&mrt->net);
2363 struct sk_buff *skb;
2364 int err = -ENOBUFS;
2365
Yuval Mintz494fff52018-02-28 23:29:34 +02002366 skb = nlmsg_new(mr6_msgsize(mfc->_c.mfc_parent >= MAXMIFS, mrt->maxvif),
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002367 GFP_ATOMIC);
Ian Morris63159f22015-03-29 14:00:04 +01002368 if (!skb)
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002369 goto errout;
2370
Nicolas Dichtelf5183382014-03-19 17:47:51 +01002371 err = ip6mr_fill_mroute(mrt, skb, 0, 0, mfc, cmd, 0);
Nicolas Dichtel812e44d2012-12-04 01:13:41 +00002372 if (err < 0)
2373 goto errout;
2374
2375 rtnl_notify(skb, net, 0, RTNLGRP_IPV6_MROUTE, NULL, GFP_ATOMIC);
2376 return;
2377
2378errout:
2379 kfree_skb(skb);
2380 if (err < 0)
2381 rtnl_set_sk_err(net, RTNLGRP_IPV6_MROUTE, err);
2382}
2383
Julien Gomesdd12d15c2017-06-20 13:54:18 -07002384static size_t mrt6msg_netlink_msgsize(size_t payloadlen)
2385{
2386 size_t len =
2387 NLMSG_ALIGN(sizeof(struct rtgenmsg))
2388 + nla_total_size(1) /* IP6MRA_CREPORT_MSGTYPE */
2389 + nla_total_size(4) /* IP6MRA_CREPORT_MIF_ID */
2390 /* IP6MRA_CREPORT_SRC_ADDR */
2391 + nla_total_size(sizeof(struct in6_addr))
2392 /* IP6MRA_CREPORT_DST_ADDR */
2393 + nla_total_size(sizeof(struct in6_addr))
2394 /* IP6MRA_CREPORT_PKT */
2395 + nla_total_size(payloadlen)
2396 ;
2397
2398 return len;
2399}
2400
Yuval Mintzb70432f2018-02-28 23:29:32 +02002401static void mrt6msg_netlink_event(struct mr_table *mrt, struct sk_buff *pkt)
Julien Gomesdd12d15c2017-06-20 13:54:18 -07002402{
2403 struct net *net = read_pnet(&mrt->net);
2404 struct nlmsghdr *nlh;
2405 struct rtgenmsg *rtgenm;
2406 struct mrt6msg *msg;
2407 struct sk_buff *skb;
2408 struct nlattr *nla;
2409 int payloadlen;
2410
2411 payloadlen = pkt->len - sizeof(struct mrt6msg);
2412 msg = (struct mrt6msg *)skb_transport_header(pkt);
2413
2414 skb = nlmsg_new(mrt6msg_netlink_msgsize(payloadlen), GFP_ATOMIC);
2415 if (!skb)
2416 goto errout;
2417
2418 nlh = nlmsg_put(skb, 0, 0, RTM_NEWCACHEREPORT,
2419 sizeof(struct rtgenmsg), 0);
2420 if (!nlh)
2421 goto errout;
2422 rtgenm = nlmsg_data(nlh);
2423 rtgenm->rtgen_family = RTNL_FAMILY_IP6MR;
2424 if (nla_put_u8(skb, IP6MRA_CREPORT_MSGTYPE, msg->im6_msgtype) ||
2425 nla_put_u32(skb, IP6MRA_CREPORT_MIF_ID, msg->im6_mif) ||
2426 nla_put_in6_addr(skb, IP6MRA_CREPORT_SRC_ADDR,
2427 &msg->im6_src) ||
2428 nla_put_in6_addr(skb, IP6MRA_CREPORT_DST_ADDR,
2429 &msg->im6_dst))
2430 goto nla_put_failure;
2431
2432 nla = nla_reserve(skb, IP6MRA_CREPORT_PKT, payloadlen);
2433 if (!nla || skb_copy_bits(pkt, sizeof(struct mrt6msg),
2434 nla_data(nla), payloadlen))
2435 goto nla_put_failure;
2436
2437 nlmsg_end(skb, nlh);
2438
2439 rtnl_notify(skb, net, 0, RTNLGRP_IPV6_MROUTE_R, NULL, GFP_ATOMIC);
2440 return;
2441
2442nla_put_failure:
2443 nlmsg_cancel(skb, nlh);
2444errout:
2445 kfree_skb(skb);
2446 rtnl_set_sk_err(net, RTNLGRP_IPV6_MROUTE_R, -ENOBUFS);
2447}
2448
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002449static int ip6mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
2450{
Yuval Mintz7b0db852018-02-28 23:29:39 +02002451 return mr_rtm_dumproute(skb, cb, ip6mr_mr_table_iter,
2452 _ip6mr_fill_mroute, &mfc_unres_lock);
Patrick McHardy5b285ca2010-05-11 14:40:56 +02002453}