blob: 9419fceeed411d49d804c8cc6004587db79ab23c [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
19#include <asm/system.h>
20#include <asm/uaccess.h>
21#include <linux/types.h>
22#include <linux/sched.h>
23#include <linux/errno.h>
24#include <linux/timer.h>
25#include <linux/mm.h>
26#include <linux/kernel.h>
27#include <linux/fcntl.h>
28#include <linux/stat.h>
29#include <linux/socket.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090030#include <linux/inet.h>
31#include <linux/netdevice.h>
32#include <linux/inetdevice.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090033#include <linux/proc_fs.h>
34#include <linux/seq_file.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090035#include <linux/init.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090036#include <linux/slab.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090037#include <net/protocol.h>
38#include <linux/skbuff.h>
39#include <net/sock.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090040#include <net/raw.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090041#include <linux/notifier.h>
42#include <linux/if_arp.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090043#include <net/checksum.h>
44#include <net/netlink.h>
45
46#include <net/ipv6.h>
47#include <net/ip6_route.h>
48#include <linux/mroute6.h>
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +090049#include <linux/pim.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090050#include <net/addrconf.h>
51#include <linux/netfilter_ipv6.h>
Dave Jones5d6e4302009-01-31 00:51:49 -080052#include <net/ip6_checksum.h>
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090053
Patrick McHardy6bd52142010-05-11 14:40:53 +020054struct mr6_table {
55#ifdef CONFIG_NET_NS
56 struct net *net;
57#endif
58 struct sock *mroute6_sk;
59 struct timer_list ipmr_expire_timer;
60 struct list_head mfc6_unres_queue;
61 struct list_head mfc6_cache_array[MFC6_LINES];
62 struct mif_device vif6_table[MAXMIFS];
63 int maxvif;
64 atomic_t cache_resolve_queue_len;
65 int mroute_do_assert;
66 int mroute_do_pim;
67#ifdef CONFIG_IPV6_PIMSM_V2
68 int mroute_reg_vif_num;
69#endif
70};
71
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090072/* Big lock, protecting vif table, mrt cache and mroute socket state.
73 Note that the changes are semaphored via rtnl_lock.
74 */
75
76static DEFINE_RWLOCK(mrt_lock);
77
78/*
79 * Multicast router control variables
80 */
81
Patrick McHardy6bd52142010-05-11 14:40:53 +020082#define MIF_EXISTS(_mrt, _idx) ((_mrt)->vif6_table[_idx].dev != NULL)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090083
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +090084/* Special spinlock for queue of unresolved entries */
85static DEFINE_SPINLOCK(mfc_unres_lock);
86
87/* We return to original Alan's scheme. Hash table of resolved
88 entries is changed only in process context and protected
89 with weak lock mrt_lock. Queue of unresolved entries is protected
90 with strong spinlock mfc_unres_lock.
91
92 In this case data path is free of exclusive locks at all.
93 */
94
95static struct kmem_cache *mrt_cachep __read_mostly;
96
Patrick McHardy6bd52142010-05-11 14:40:53 +020097static int ip6_mr_forward(struct net *net, struct mr6_table *mrt,
98 struct sk_buff *skb, struct mfc6_cache *cache);
99static int ip6mr_cache_report(struct mr6_table *mrt, struct sk_buff *pkt,
Benjamin Thery8229efd2008-12-10 16:30:15 -0800100 mifi_t mifi, int assert);
Patrick McHardy6bd52142010-05-11 14:40:53 +0200101static int ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb,
Patrick McHardyb5aa30b2010-05-11 14:40:50 +0200102 struct mfc6_cache *c, struct rtmsg *rtm);
Patrick McHardy6bd52142010-05-11 14:40:53 +0200103static void mroute_clean_tables(struct mr6_table *mrt);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900104
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900105
106#ifdef CONFIG_PROC_FS
107
108struct ipmr_mfc_iter {
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800109 struct seq_net_private p;
Patrick McHardyf30a77842010-05-11 14:40:51 +0200110 struct list_head *cache;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900111 int ct;
112};
113
114
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800115static struct mfc6_cache *ipmr_mfc_seq_idx(struct net *net,
116 struct ipmr_mfc_iter *it, loff_t pos)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900117{
Patrick McHardy6bd52142010-05-11 14:40:53 +0200118 struct mr6_table *mrt = net->ipv6.mrt6;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900119 struct mfc6_cache *mfc;
120
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900121 read_lock(&mrt_lock);
Patrick McHardyf30a77842010-05-11 14:40:51 +0200122 for (it->ct = 0; it->ct < MFC6_LINES; it->ct++) {
Patrick McHardy6bd52142010-05-11 14:40:53 +0200123 it->cache = &mrt->mfc6_cache_array[it->ct];
Patrick McHardyf30a77842010-05-11 14:40:51 +0200124 list_for_each_entry(mfc, it->cache, list)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900125 if (pos-- == 0)
126 return mfc;
Patrick McHardyf30a77842010-05-11 14:40:51 +0200127 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900128 read_unlock(&mrt_lock);
129
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900130 spin_lock_bh(&mfc_unres_lock);
Patrick McHardy6bd52142010-05-11 14:40:53 +0200131 it->cache = &mrt->mfc6_unres_queue;
Patrick McHardyf30a77842010-05-11 14:40:51 +0200132 list_for_each_entry(mfc, it->cache, list)
Patrick McHardyc476efb2010-05-11 14:40:48 +0200133 if (pos-- == 0)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900134 return mfc;
135 spin_unlock_bh(&mfc_unres_lock);
136
137 it->cache = NULL;
138 return NULL;
139}
140
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900141/*
142 * The /proc interfaces to multicast routing /proc/ip6_mr_cache /proc/ip6_mr_vif
143 */
144
145struct ipmr_vif_iter {
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800146 struct seq_net_private p;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900147 int ct;
148};
149
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800150static struct mif_device *ip6mr_vif_seq_idx(struct net *net,
151 struct ipmr_vif_iter *iter,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900152 loff_t pos)
153{
Patrick McHardy6bd52142010-05-11 14:40:53 +0200154 struct mr6_table *mrt = net->ipv6.mrt6;
155
156 for (iter->ct = 0; iter->ct < mrt->maxvif; ++iter->ct) {
157 if (!MIF_EXISTS(mrt, iter->ct))
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900158 continue;
159 if (pos-- == 0)
Patrick McHardy6bd52142010-05-11 14:40:53 +0200160 return &mrt->vif6_table[iter->ct];
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900161 }
162 return NULL;
163}
164
165static void *ip6mr_vif_seq_start(struct seq_file *seq, loff_t *pos)
166 __acquires(mrt_lock)
167{
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800168 struct net *net = seq_file_net(seq);
169
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900170 read_lock(&mrt_lock);
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800171 return *pos ? ip6mr_vif_seq_idx(net, seq->private, *pos - 1)
172 : SEQ_START_TOKEN;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900173}
174
175static void *ip6mr_vif_seq_next(struct seq_file *seq, void *v, loff_t *pos)
176{
177 struct ipmr_vif_iter *iter = seq->private;
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800178 struct net *net = seq_file_net(seq);
Patrick McHardy6bd52142010-05-11 14:40:53 +0200179 struct mr6_table *mrt = net->ipv6.mrt6;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900180
181 ++*pos;
182 if (v == SEQ_START_TOKEN)
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800183 return ip6mr_vif_seq_idx(net, iter, 0);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900184
Patrick McHardy6bd52142010-05-11 14:40:53 +0200185 while (++iter->ct < mrt->maxvif) {
186 if (!MIF_EXISTS(mrt, iter->ct))
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900187 continue;
Patrick McHardy6bd52142010-05-11 14:40:53 +0200188 return &mrt->vif6_table[iter->ct];
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900189 }
190 return NULL;
191}
192
193static void ip6mr_vif_seq_stop(struct seq_file *seq, void *v)
194 __releases(mrt_lock)
195{
196 read_unlock(&mrt_lock);
197}
198
199static int ip6mr_vif_seq_show(struct seq_file *seq, void *v)
200{
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800201 struct net *net = seq_file_net(seq);
Patrick McHardy6bd52142010-05-11 14:40:53 +0200202 struct mr6_table *mrt = net->ipv6.mrt6;
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800203
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900204 if (v == SEQ_START_TOKEN) {
205 seq_puts(seq,
206 "Interface BytesIn PktsIn BytesOut PktsOut Flags\n");
207 } else {
208 const struct mif_device *vif = v;
209 const char *name = vif->dev ? vif->dev->name : "none";
210
211 seq_printf(seq,
Al Virod430a222008-06-02 10:59:02 +0100212 "%2td %-10s %8ld %7ld %8ld %7ld %05X\n",
Patrick McHardy6bd52142010-05-11 14:40:53 +0200213 vif - mrt->vif6_table,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900214 name, vif->bytes_in, vif->pkt_in,
215 vif->bytes_out, vif->pkt_out,
216 vif->flags);
217 }
218 return 0;
219}
220
Stephen Hemminger98147d52009-09-01 19:25:02 +0000221static const struct seq_operations ip6mr_vif_seq_ops = {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900222 .start = ip6mr_vif_seq_start,
223 .next = ip6mr_vif_seq_next,
224 .stop = ip6mr_vif_seq_stop,
225 .show = ip6mr_vif_seq_show,
226};
227
228static int ip6mr_vif_open(struct inode *inode, struct file *file)
229{
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800230 return seq_open_net(inode, file, &ip6mr_vif_seq_ops,
231 sizeof(struct ipmr_vif_iter));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900232}
233
Stephen Hemminger5ca1b992009-09-01 19:25:05 +0000234static const struct file_operations ip6mr_vif_fops = {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900235 .owner = THIS_MODULE,
236 .open = ip6mr_vif_open,
237 .read = seq_read,
238 .llseek = seq_lseek,
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800239 .release = seq_release_net,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900240};
241
242static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos)
243{
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800244 struct net *net = seq_file_net(seq);
245
246 return *pos ? ipmr_mfc_seq_idx(net, seq->private, *pos - 1)
247 : SEQ_START_TOKEN;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900248}
249
250static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
251{
252 struct mfc6_cache *mfc = v;
253 struct ipmr_mfc_iter *it = seq->private;
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800254 struct net *net = seq_file_net(seq);
Patrick McHardy6bd52142010-05-11 14:40:53 +0200255 struct mr6_table *mrt = net->ipv6.mrt6;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900256
257 ++*pos;
258
259 if (v == SEQ_START_TOKEN)
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800260 return ipmr_mfc_seq_idx(net, seq->private, 0);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900261
Patrick McHardyf30a77842010-05-11 14:40:51 +0200262 if (mfc->list.next != it->cache)
263 return list_entry(mfc->list.next, struct mfc6_cache, list);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900264
Patrick McHardy6bd52142010-05-11 14:40:53 +0200265 if (it->cache == &mrt->mfc6_unres_queue)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900266 goto end_of_list;
267
Patrick McHardy6bd52142010-05-11 14:40:53 +0200268 BUG_ON(it->cache != &mrt->mfc6_cache_array[it->ct]);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900269
Benjamin Thery4a6258a2008-12-10 16:24:07 -0800270 while (++it->ct < MFC6_LINES) {
Patrick McHardy6bd52142010-05-11 14:40:53 +0200271 it->cache = &mrt->mfc6_cache_array[it->ct];
Patrick McHardyf30a77842010-05-11 14:40:51 +0200272 if (list_empty(it->cache))
273 continue;
274 return list_first_entry(it->cache, struct mfc6_cache, list);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900275 }
276
277 /* exhausted cache_array, show unresolved */
278 read_unlock(&mrt_lock);
Patrick McHardy6bd52142010-05-11 14:40:53 +0200279 it->cache = &mrt->mfc6_unres_queue;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900280 it->ct = 0;
281
282 spin_lock_bh(&mfc_unres_lock);
Patrick McHardyf30a77842010-05-11 14:40:51 +0200283 if (!list_empty(it->cache))
284 return list_first_entry(it->cache, struct mfc6_cache, list);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900285
286 end_of_list:
287 spin_unlock_bh(&mfc_unres_lock);
288 it->cache = NULL;
289
290 return NULL;
291}
292
293static void ipmr_mfc_seq_stop(struct seq_file *seq, void *v)
294{
295 struct ipmr_mfc_iter *it = seq->private;
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800296 struct net *net = seq_file_net(seq);
Patrick McHardy6bd52142010-05-11 14:40:53 +0200297 struct mr6_table *mrt = net->ipv6.mrt6;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900298
Patrick McHardy6bd52142010-05-11 14:40:53 +0200299 if (it->cache == &mrt->mfc6_unres_queue)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900300 spin_unlock_bh(&mfc_unres_lock);
Patrick McHardy6bd52142010-05-11 14:40:53 +0200301 else if (it->cache == mrt->mfc6_cache_array)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900302 read_unlock(&mrt_lock);
303}
304
305static int ipmr_mfc_seq_show(struct seq_file *seq, void *v)
306{
307 int n;
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800308 struct net *net = seq_file_net(seq);
Patrick McHardy6bd52142010-05-11 14:40:53 +0200309 struct mr6_table *mrt = net->ipv6.mrt6;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900310
311 if (v == SEQ_START_TOKEN) {
312 seq_puts(seq,
313 "Group "
314 "Origin "
315 "Iif Pkts Bytes Wrong Oifs\n");
316 } else {
317 const struct mfc6_cache *mfc = v;
318 const struct ipmr_mfc_iter *it = seq->private;
319
Benjamin Thery999890b2008-12-03 22:22:16 -0800320 seq_printf(seq, "%pI6 %pI6 %-3hd",
Harvey Harrison0c6ce782008-10-28 16:09:23 -0700321 &mfc->mf6c_mcastgrp, &mfc->mf6c_origin,
Benjamin Thery1ea472e2008-12-03 22:21:47 -0800322 mfc->mf6c_parent);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900323
Patrick McHardy6bd52142010-05-11 14:40:53 +0200324 if (it->cache != &mrt->mfc6_unres_queue) {
Benjamin Thery1ea472e2008-12-03 22:21:47 -0800325 seq_printf(seq, " %8lu %8lu %8lu",
326 mfc->mfc_un.res.pkt,
327 mfc->mfc_un.res.bytes,
328 mfc->mfc_un.res.wrong_if);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900329 for (n = mfc->mfc_un.res.minvif;
330 n < mfc->mfc_un.res.maxvif; n++) {
Patrick McHardy6bd52142010-05-11 14:40:53 +0200331 if (MIF_EXISTS(mrt, n) &&
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900332 mfc->mfc_un.res.ttls[n] < 255)
333 seq_printf(seq,
334 " %2d:%-3d",
335 n, mfc->mfc_un.res.ttls[n]);
336 }
Benjamin Thery1ea472e2008-12-03 22:21:47 -0800337 } else {
338 /* unresolved mfc_caches don't contain
339 * pkt, bytes and wrong_if values
340 */
341 seq_printf(seq, " %8lu %8lu %8lu", 0ul, 0ul, 0ul);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900342 }
343 seq_putc(seq, '\n');
344 }
345 return 0;
346}
347
James Morris88e9d342009-09-22 16:43:43 -0700348static const struct seq_operations ipmr_mfc_seq_ops = {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900349 .start = ipmr_mfc_seq_start,
350 .next = ipmr_mfc_seq_next,
351 .stop = ipmr_mfc_seq_stop,
352 .show = ipmr_mfc_seq_show,
353};
354
355static int ipmr_mfc_open(struct inode *inode, struct file *file)
356{
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800357 return seq_open_net(inode, file, &ipmr_mfc_seq_ops,
358 sizeof(struct ipmr_mfc_iter));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900359}
360
Stephen Hemminger5ca1b992009-09-01 19:25:05 +0000361static const struct file_operations ip6mr_mfc_fops = {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900362 .owner = THIS_MODULE,
363 .open = ipmr_mfc_open,
364 .read = seq_read,
365 .llseek = seq_lseek,
Benjamin Thery8b90fc72008-12-10 16:29:48 -0800366 .release = seq_release_net,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900367};
368#endif
369
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900370#ifdef CONFIG_IPV6_PIMSM_V2
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900371
372static int pim6_rcv(struct sk_buff *skb)
373{
374 struct pimreghdr *pim;
375 struct ipv6hdr *encap;
376 struct net_device *reg_dev = NULL;
Benjamin Thery8229efd2008-12-10 16:30:15 -0800377 struct net *net = dev_net(skb->dev);
Patrick McHardy6bd52142010-05-11 14:40:53 +0200378 struct mr6_table *mrt = net->ipv6.mrt6;
379 int reg_vif_num = mrt->mroute_reg_vif_num;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900380
381 if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(*encap)))
382 goto drop;
383
384 pim = (struct pimreghdr *)skb_transport_header(skb);
385 if (pim->type != ((PIM_VERSION << 4) | PIM_REGISTER) ||
386 (pim->flags & PIM_NULL_REGISTER) ||
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800387 (csum_ipv6_magic(&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
388 sizeof(*pim), IPPROTO_PIM,
389 csum_partial((void *)pim, sizeof(*pim), 0)) &&
Al Viroec6b4862008-04-26 22:28:58 -0700390 csum_fold(skb_checksum(skb, 0, skb->len, 0))))
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900391 goto drop;
392
393 /* check if the inner packet is destined to mcast group */
394 encap = (struct ipv6hdr *)(skb_transport_header(skb) +
395 sizeof(*pim));
396
397 if (!ipv6_addr_is_multicast(&encap->daddr) ||
398 encap->payload_len == 0 ||
399 ntohs(encap->payload_len) + sizeof(*pim) > skb->len)
400 goto drop;
401
402 read_lock(&mrt_lock);
403 if (reg_vif_num >= 0)
Patrick McHardy6bd52142010-05-11 14:40:53 +0200404 reg_dev = mrt->vif6_table[reg_vif_num].dev;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900405 if (reg_dev)
406 dev_hold(reg_dev);
407 read_unlock(&mrt_lock);
408
409 if (reg_dev == NULL)
410 goto drop;
411
412 skb->mac_header = skb->network_header;
413 skb_pull(skb, (u8 *)encap - skb->data);
414 skb_reset_network_header(skb);
415 skb->dev = reg_dev;
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800416 skb->protocol = htons(ETH_P_IPV6);
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900417 skb->ip_summed = 0;
418 skb->pkt_type = PACKET_HOST;
Eric Dumazetadf30902009-06-02 05:19:30 +0000419 skb_dst_drop(skb);
Pavel Emelyanovdc58c782008-05-21 14:17:54 -0700420 reg_dev->stats.rx_bytes += skb->len;
421 reg_dev->stats.rx_packets++;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900422 nf_reset(skb);
423 netif_rx(skb);
424 dev_put(reg_dev);
425 return 0;
426 drop:
427 kfree_skb(skb);
428 return 0;
429}
430
Alexey Dobriyan41135cc2009-09-14 12:22:28 +0000431static const struct inet6_protocol pim6_protocol = {
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900432 .handler = pim6_rcv,
433};
434
435/* Service routines creating virtual interfaces: PIMREG */
436
Stephen Hemminger6fef4c02009-08-31 19:50:41 +0000437static netdev_tx_t reg_vif_xmit(struct sk_buff *skb,
438 struct net_device *dev)
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900439{
Benjamin Thery8229efd2008-12-10 16:30:15 -0800440 struct net *net = dev_net(dev);
Patrick McHardy6bd52142010-05-11 14:40:53 +0200441 struct mr6_table *mrt = net->ipv6.mrt6;
Benjamin Thery8229efd2008-12-10 16:30:15 -0800442
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900443 read_lock(&mrt_lock);
Pavel Emelyanovdc58c782008-05-21 14:17:54 -0700444 dev->stats.tx_bytes += skb->len;
445 dev->stats.tx_packets++;
Patrick McHardy6bd52142010-05-11 14:40:53 +0200446 ip6mr_cache_report(mrt, skb, mrt->mroute_reg_vif_num, MRT6MSG_WHOLEPKT);
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900447 read_unlock(&mrt_lock);
448 kfree_skb(skb);
Patrick McHardy6ed10652009-06-23 06:03:08 +0000449 return NETDEV_TX_OK;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900450}
451
Stephen Hemminger007c3832008-11-20 20:28:35 -0800452static const struct net_device_ops reg_vif_netdev_ops = {
453 .ndo_start_xmit = reg_vif_xmit,
454};
455
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900456static void reg_vif_setup(struct net_device *dev)
457{
458 dev->type = ARPHRD_PIMREG;
459 dev->mtu = 1500 - sizeof(struct ipv6hdr) - 8;
460 dev->flags = IFF_NOARP;
Stephen Hemminger007c3832008-11-20 20:28:35 -0800461 dev->netdev_ops = &reg_vif_netdev_ops;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900462 dev->destructor = free_netdev;
Tom Goff403dbb92009-06-14 03:16:13 -0700463 dev->features |= NETIF_F_NETNS_LOCAL;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900464}
465
Benjamin Thery8229efd2008-12-10 16:30:15 -0800466static struct net_device *ip6mr_reg_vif(struct net *net)
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900467{
468 struct net_device *dev;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900469
Pavel Emelyanovdc58c782008-05-21 14:17:54 -0700470 dev = alloc_netdev(0, "pim6reg", reg_vif_setup);
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900471 if (dev == NULL)
472 return NULL;
473
Benjamin Thery8229efd2008-12-10 16:30:15 -0800474 dev_net_set(dev, net);
475
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900476 if (register_netdevice(dev)) {
477 free_netdev(dev);
478 return NULL;
479 }
480 dev->iflink = 0;
481
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900482 if (dev_open(dev))
483 goto failure;
484
Wang Chen7af3db72008-07-14 20:54:54 -0700485 dev_hold(dev);
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900486 return dev;
487
488failure:
489 /* allow the register to be completed before unregistering. */
490 rtnl_unlock();
491 rtnl_lock();
492
493 unregister_netdevice(dev);
494 return NULL;
495}
496#endif
497
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900498/*
499 * Delete a VIF entry
500 */
501
Patrick McHardy6bd52142010-05-11 14:40:53 +0200502static int mif6_delete(struct mr6_table *mrt, int vifi, struct list_head *head)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900503{
504 struct mif_device *v;
505 struct net_device *dev;
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800506 struct inet6_dev *in6_dev;
Patrick McHardy6bd52142010-05-11 14:40:53 +0200507
508 if (vifi < 0 || vifi >= mrt->maxvif)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900509 return -EADDRNOTAVAIL;
510
Patrick McHardy6bd52142010-05-11 14:40:53 +0200511 v = &mrt->vif6_table[vifi];
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900512
513 write_lock_bh(&mrt_lock);
514 dev = v->dev;
515 v->dev = NULL;
516
517 if (!dev) {
518 write_unlock_bh(&mrt_lock);
519 return -EADDRNOTAVAIL;
520 }
521
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900522#ifdef CONFIG_IPV6_PIMSM_V2
Patrick McHardy6bd52142010-05-11 14:40:53 +0200523 if (vifi == mrt->mroute_reg_vif_num)
524 mrt->mroute_reg_vif_num = -1;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900525#endif
526
Patrick McHardy6bd52142010-05-11 14:40:53 +0200527 if (vifi + 1 == mrt->maxvif) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900528 int tmp;
529 for (tmp = vifi - 1; tmp >= 0; tmp--) {
Patrick McHardy6bd52142010-05-11 14:40:53 +0200530 if (MIF_EXISTS(mrt, tmp))
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900531 break;
532 }
Patrick McHardy6bd52142010-05-11 14:40:53 +0200533 mrt->maxvif = tmp + 1;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900534 }
535
536 write_unlock_bh(&mrt_lock);
537
538 dev_set_allmulti(dev, -1);
539
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800540 in6_dev = __in6_dev_get(dev);
541 if (in6_dev)
542 in6_dev->cnf.mc_forwarding--;
543
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900544 if (v->flags & MIFF_REGISTER)
Eric Dumazetc871e662009-10-28 04:48:11 +0000545 unregister_netdevice_queue(dev, head);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900546
547 dev_put(dev);
548 return 0;
549}
550
Benjamin Thery58701ad2008-12-10 16:22:34 -0800551static inline void ip6mr_cache_free(struct mfc6_cache *c)
552{
Benjamin Thery58701ad2008-12-10 16:22:34 -0800553 kmem_cache_free(mrt_cachep, c);
554}
555
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900556/* Destroy an unresolved cache entry, killing queued skbs
557 and reporting error to netlink readers.
558 */
559
Patrick McHardy6bd52142010-05-11 14:40:53 +0200560static void ip6mr_destroy_unres(struct mr6_table *mrt, struct mfc6_cache *c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900561{
Patrick McHardy6bd52142010-05-11 14:40:53 +0200562 struct net *net = read_pnet(&mrt->net);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900563 struct sk_buff *skb;
564
Patrick McHardy6bd52142010-05-11 14:40:53 +0200565 atomic_dec(&mrt->cache_resolve_queue_len);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900566
567 while((skb = skb_dequeue(&c->mfc_un.unres.unresolved)) != NULL) {
568 if (ipv6_hdr(skb)->version == 0) {
569 struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct ipv6hdr));
570 nlh->nlmsg_type = NLMSG_ERROR;
571 nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct nlmsgerr));
572 skb_trim(skb, nlh->nlmsg_len);
573 ((struct nlmsgerr *)NLMSG_DATA(nlh))->error = -ETIMEDOUT;
Benjamin Thery8229efd2008-12-10 16:30:15 -0800574 rtnl_unicast(skb, net, NETLINK_CB(skb).pid);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900575 } else
576 kfree_skb(skb);
577 }
578
Benjamin Thery58701ad2008-12-10 16:22:34 -0800579 ip6mr_cache_free(c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900580}
581
582
Patrick McHardyc476efb2010-05-11 14:40:48 +0200583/* Timer process for all the unresolved queue. */
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900584
Patrick McHardy6bd52142010-05-11 14:40:53 +0200585static void ipmr_do_expire_process(struct mr6_table *mrt)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900586{
587 unsigned long now = jiffies;
588 unsigned long expires = 10 * HZ;
Patrick McHardyf30a77842010-05-11 14:40:51 +0200589 struct mfc6_cache *c, *next;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900590
Patrick McHardy6bd52142010-05-11 14:40:53 +0200591 list_for_each_entry_safe(c, next, &mrt->mfc6_unres_queue, list) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900592 if (time_after(c->mfc_un.unres.expires, now)) {
593 /* not yet... */
594 unsigned long interval = c->mfc_un.unres.expires - now;
595 if (interval < expires)
596 expires = interval;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900597 continue;
598 }
599
Patrick McHardyf30a77842010-05-11 14:40:51 +0200600 list_del(&c->list);
Patrick McHardy6bd52142010-05-11 14:40:53 +0200601 ip6mr_destroy_unres(mrt, c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900602 }
603
Patrick McHardy6bd52142010-05-11 14:40:53 +0200604 if (!list_empty(&mrt->mfc6_unres_queue))
605 mod_timer(&mrt->ipmr_expire_timer, jiffies + expires);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900606}
607
Patrick McHardyc476efb2010-05-11 14:40:48 +0200608static void ipmr_expire_process(unsigned long arg)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900609{
Patrick McHardy6bd52142010-05-11 14:40:53 +0200610 struct mr6_table *mrt = (struct mr6_table *)arg;
Patrick McHardyc476efb2010-05-11 14:40:48 +0200611
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900612 if (!spin_trylock(&mfc_unres_lock)) {
Patrick McHardy6bd52142010-05-11 14:40:53 +0200613 mod_timer(&mrt->ipmr_expire_timer, jiffies + 1);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900614 return;
615 }
616
Patrick McHardy6bd52142010-05-11 14:40:53 +0200617 if (!list_empty(&mrt->mfc6_unres_queue))
618 ipmr_do_expire_process(mrt);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900619
620 spin_unlock(&mfc_unres_lock);
621}
622
623/* Fill oifs list. It is called under write locked mrt_lock. */
624
Patrick McHardy6bd52142010-05-11 14:40:53 +0200625static void ip6mr_update_thresholds(struct mr6_table *mrt, struct mfc6_cache *cache,
Patrick McHardyb5aa30b2010-05-11 14:40:50 +0200626 unsigned char *ttls)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900627{
628 int vifi;
629
Rami Rosen6ac7eb02008-04-10 12:40:10 +0300630 cache->mfc_un.res.minvif = MAXMIFS;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900631 cache->mfc_un.res.maxvif = 0;
Rami Rosen6ac7eb02008-04-10 12:40:10 +0300632 memset(cache->mfc_un.res.ttls, 255, MAXMIFS);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900633
Patrick McHardy6bd52142010-05-11 14:40:53 +0200634 for (vifi = 0; vifi < mrt->maxvif; vifi++) {
635 if (MIF_EXISTS(mrt, vifi) &&
Benjamin Thery4e168802008-12-10 16:15:08 -0800636 ttls[vifi] && ttls[vifi] < 255) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900637 cache->mfc_un.res.ttls[vifi] = ttls[vifi];
638 if (cache->mfc_un.res.minvif > vifi)
639 cache->mfc_un.res.minvif = vifi;
640 if (cache->mfc_un.res.maxvif <= vifi)
641 cache->mfc_un.res.maxvif = vifi + 1;
642 }
643 }
644}
645
Patrick McHardy6bd52142010-05-11 14:40:53 +0200646static int mif6_add(struct net *net, struct mr6_table *mrt,
647 struct mif6ctl *vifc, int mrtsock)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900648{
649 int vifi = vifc->mif6c_mifi;
Patrick McHardy6bd52142010-05-11 14:40:53 +0200650 struct mif_device *v = &mrt->vif6_table[vifi];
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900651 struct net_device *dev;
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800652 struct inet6_dev *in6_dev;
Wang Chen5ae7b442008-07-14 20:54:23 -0700653 int err;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900654
655 /* Is vif busy ? */
Patrick McHardy6bd52142010-05-11 14:40:53 +0200656 if (MIF_EXISTS(mrt, vifi))
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900657 return -EADDRINUSE;
658
659 switch (vifc->mif6c_flags) {
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900660#ifdef CONFIG_IPV6_PIMSM_V2
661 case MIFF_REGISTER:
662 /*
663 * Special Purpose VIF in PIM
664 * All the packets will be sent to the daemon
665 */
Patrick McHardy6bd52142010-05-11 14:40:53 +0200666 if (mrt->mroute_reg_vif_num >= 0)
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900667 return -EADDRINUSE;
Benjamin Thery8229efd2008-12-10 16:30:15 -0800668 dev = ip6mr_reg_vif(net);
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900669 if (!dev)
670 return -ENOBUFS;
Wang Chen5ae7b442008-07-14 20:54:23 -0700671 err = dev_set_allmulti(dev, 1);
672 if (err) {
673 unregister_netdevice(dev);
Wang Chen7af3db72008-07-14 20:54:54 -0700674 dev_put(dev);
Wang Chen5ae7b442008-07-14 20:54:23 -0700675 return err;
676 }
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900677 break;
678#endif
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900679 case 0:
Benjamin Thery8229efd2008-12-10 16:30:15 -0800680 dev = dev_get_by_index(net, vifc->mif6c_pifi);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900681 if (!dev)
682 return -EADDRNOTAVAIL;
Wang Chen5ae7b442008-07-14 20:54:23 -0700683 err = dev_set_allmulti(dev, 1);
Wang Chen7af3db72008-07-14 20:54:54 -0700684 if (err) {
685 dev_put(dev);
Wang Chen5ae7b442008-07-14 20:54:23 -0700686 return err;
Wang Chen7af3db72008-07-14 20:54:54 -0700687 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900688 break;
689 default:
690 return -EINVAL;
691 }
692
Thomas Goff1d6e55f2009-01-27 22:39:59 -0800693 in6_dev = __in6_dev_get(dev);
694 if (in6_dev)
695 in6_dev->cnf.mc_forwarding++;
696
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900697 /*
698 * Fill in the VIF structures
699 */
700 v->rate_limit = vifc->vifc_rate_limit;
701 v->flags = vifc->mif6c_flags;
702 if (!mrtsock)
703 v->flags |= VIFF_STATIC;
704 v->threshold = vifc->vifc_threshold;
705 v->bytes_in = 0;
706 v->bytes_out = 0;
707 v->pkt_in = 0;
708 v->pkt_out = 0;
709 v->link = dev->ifindex;
710 if (v->flags & MIFF_REGISTER)
711 v->link = dev->iflink;
712
713 /* And finish update writing critical data */
714 write_lock_bh(&mrt_lock);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900715 v->dev = dev;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900716#ifdef CONFIG_IPV6_PIMSM_V2
717 if (v->flags & MIFF_REGISTER)
Patrick McHardy6bd52142010-05-11 14:40:53 +0200718 mrt->mroute_reg_vif_num = vifi;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900719#endif
Patrick McHardy6bd52142010-05-11 14:40:53 +0200720 if (vifi + 1 > mrt->maxvif)
721 mrt->maxvif = vifi + 1;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900722 write_unlock_bh(&mrt_lock);
723 return 0;
724}
725
Patrick McHardy6bd52142010-05-11 14:40:53 +0200726static struct mfc6_cache *ip6mr_cache_find(struct mr6_table *mrt,
Benjamin Thery8229efd2008-12-10 16:30:15 -0800727 struct in6_addr *origin,
728 struct in6_addr *mcastgrp)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900729{
730 int line = MFC6_HASH(mcastgrp, origin);
731 struct mfc6_cache *c;
732
Patrick McHardy6bd52142010-05-11 14:40:53 +0200733 list_for_each_entry(c, &mrt->mfc6_cache_array[line], list) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900734 if (ipv6_addr_equal(&c->mf6c_origin, origin) &&
735 ipv6_addr_equal(&c->mf6c_mcastgrp, mcastgrp))
Patrick McHardyf30a77842010-05-11 14:40:51 +0200736 return c;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900737 }
Patrick McHardyf30a77842010-05-11 14:40:51 +0200738 return NULL;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900739}
740
741/*
742 * Allocate a multicast cache entry
743 */
Patrick McHardyb5aa30b2010-05-11 14:40:50 +0200744static struct mfc6_cache *ip6mr_cache_alloc(void)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900745{
Joe Perches36cbac52008-12-03 22:27:25 -0800746 struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900747 if (c == NULL)
748 return NULL;
Rami Rosen6ac7eb02008-04-10 12:40:10 +0300749 c->mfc_un.res.minvif = MAXMIFS;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900750 return c;
751}
752
Patrick McHardyb5aa30b2010-05-11 14:40:50 +0200753static struct mfc6_cache *ip6mr_cache_alloc_unres(void)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900754{
Joe Perches36cbac52008-12-03 22:27:25 -0800755 struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900756 if (c == NULL)
757 return NULL;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900758 skb_queue_head_init(&c->mfc_un.unres.unresolved);
759 c->mfc_un.unres.expires = jiffies + 10 * HZ;
760 return c;
761}
762
763/*
764 * A cache entry has gone into a resolved state from queued
765 */
766
Patrick McHardy6bd52142010-05-11 14:40:53 +0200767static void ip6mr_cache_resolve(struct net *net, struct mr6_table *mrt,
768 struct mfc6_cache *uc, struct mfc6_cache *c)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900769{
770 struct sk_buff *skb;
771
772 /*
773 * Play the pending entries through our router
774 */
775
776 while((skb = __skb_dequeue(&uc->mfc_un.unres.unresolved))) {
777 if (ipv6_hdr(skb)->version == 0) {
778 int err;
779 struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct ipv6hdr));
780
Patrick McHardy6bd52142010-05-11 14:40:53 +0200781 if (ip6mr_fill_mroute(mrt, skb, c, NLMSG_DATA(nlh)) > 0) {
YOSHIFUJI Hideaki549e0282008-04-05 22:17:39 +0900782 nlh->nlmsg_len = skb_tail_pointer(skb) - (u8 *)nlh;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900783 } else {
784 nlh->nlmsg_type = NLMSG_ERROR;
785 nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct nlmsgerr));
786 skb_trim(skb, nlh->nlmsg_len);
787 ((struct nlmsgerr *)NLMSG_DATA(nlh))->error = -EMSGSIZE;
788 }
Patrick McHardyb5aa30b2010-05-11 14:40:50 +0200789 err = rtnl_unicast(skb, net, NETLINK_CB(skb).pid);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900790 } else
Patrick McHardy6bd52142010-05-11 14:40:53 +0200791 ip6_mr_forward(net, mrt, skb, c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900792 }
793}
794
795/*
796 * Bounce a cache query up to pim6sd. We could use netlink for this but pim6sd
797 * expects the following bizarre scheme.
798 *
799 * Called under mrt_lock.
800 */
801
Patrick McHardy6bd52142010-05-11 14:40:53 +0200802static int ip6mr_cache_report(struct mr6_table *mrt, struct sk_buff *pkt,
803 mifi_t mifi, int assert)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900804{
805 struct sk_buff *skb;
806 struct mrt6msg *msg;
807 int ret;
808
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900809#ifdef CONFIG_IPV6_PIMSM_V2
810 if (assert == MRT6MSG_WHOLEPKT)
811 skb = skb_realloc_headroom(pkt, -skb_network_offset(pkt)
812 +sizeof(*msg));
813 else
814#endif
815 skb = alloc_skb(sizeof(struct ipv6hdr) + sizeof(*msg), GFP_ATOMIC);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900816
817 if (!skb)
818 return -ENOBUFS;
819
820 /* I suppose that internal messages
821 * do not require checksums */
822
823 skb->ip_summed = CHECKSUM_UNNECESSARY;
824
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900825#ifdef CONFIG_IPV6_PIMSM_V2
826 if (assert == MRT6MSG_WHOLEPKT) {
827 /* Ugly, but we have no choice with this interface.
828 Duplicate old header, fix length etc.
829 And all this only to mangle msg->im6_msgtype and
830 to set msg->im6_mbz to "mbz" :-)
831 */
832 skb_push(skb, -skb_network_offset(pkt));
833
834 skb_push(skb, sizeof(*msg));
835 skb_reset_transport_header(skb);
836 msg = (struct mrt6msg *)skb_transport_header(skb);
837 msg->im6_mbz = 0;
838 msg->im6_msgtype = MRT6MSG_WHOLEPKT;
Patrick McHardy6bd52142010-05-11 14:40:53 +0200839 msg->im6_mif = mrt->mroute_reg_vif_num;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900840 msg->im6_pad = 0;
841 ipv6_addr_copy(&msg->im6_src, &ipv6_hdr(pkt)->saddr);
842 ipv6_addr_copy(&msg->im6_dst, &ipv6_hdr(pkt)->daddr);
843
844 skb->ip_summed = CHECKSUM_UNNECESSARY;
845 } else
846#endif
847 {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900848 /*
849 * Copy the IP header
850 */
851
852 skb_put(skb, sizeof(struct ipv6hdr));
853 skb_reset_network_header(skb);
854 skb_copy_to_linear_data(skb, ipv6_hdr(pkt), sizeof(struct ipv6hdr));
855
856 /*
857 * Add our header
858 */
859 skb_put(skb, sizeof(*msg));
860 skb_reset_transport_header(skb);
861 msg = (struct mrt6msg *)skb_transport_header(skb);
862
863 msg->im6_mbz = 0;
864 msg->im6_msgtype = assert;
Rami Rosen6ac7eb02008-04-10 12:40:10 +0300865 msg->im6_mif = mifi;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900866 msg->im6_pad = 0;
867 ipv6_addr_copy(&msg->im6_src, &ipv6_hdr(pkt)->saddr);
868 ipv6_addr_copy(&msg->im6_dst, &ipv6_hdr(pkt)->daddr);
869
Eric Dumazetadf30902009-06-02 05:19:30 +0000870 skb_dst_set(skb, dst_clone(skb_dst(pkt)));
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900871 skb->ip_summed = CHECKSUM_UNNECESSARY;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +0900872 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900873
Patrick McHardy6bd52142010-05-11 14:40:53 +0200874 if (mrt->mroute6_sk == NULL) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900875 kfree_skb(skb);
876 return -EINVAL;
877 }
878
879 /*
880 * Deliver to user space multicast routing algorithms
881 */
Patrick McHardy6bd52142010-05-11 14:40:53 +0200882 ret = sock_queue_rcv_skb(mrt->mroute6_sk, skb);
Benjamin Therybd91b8b2008-12-10 16:07:08 -0800883 if (ret < 0) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900884 if (net_ratelimit())
885 printk(KERN_WARNING "mroute6: pending queue full, dropping entries.\n");
886 kfree_skb(skb);
887 }
888
889 return ret;
890}
891
892/*
893 * Queue a packet for resolution. It gets locked cache entry!
894 */
895
896static int
Patrick McHardy6bd52142010-05-11 14:40:53 +0200897ip6mr_cache_unresolved(struct mr6_table *mrt, mifi_t mifi, struct sk_buff *skb)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900898{
Patrick McHardyf30a77842010-05-11 14:40:51 +0200899 bool found = false;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900900 int err;
901 struct mfc6_cache *c;
902
903 spin_lock_bh(&mfc_unres_lock);
Patrick McHardy6bd52142010-05-11 14:40:53 +0200904 list_for_each_entry(c, &mrt->mfc6_unres_queue, list) {
Patrick McHardyc476efb2010-05-11 14:40:48 +0200905 if (ipv6_addr_equal(&c->mf6c_mcastgrp, &ipv6_hdr(skb)->daddr) &&
Patrick McHardyf30a77842010-05-11 14:40:51 +0200906 ipv6_addr_equal(&c->mf6c_origin, &ipv6_hdr(skb)->saddr)) {
907 found = true;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900908 break;
Patrick McHardyf30a77842010-05-11 14:40:51 +0200909 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900910 }
911
Patrick McHardyf30a77842010-05-11 14:40:51 +0200912 if (!found) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900913 /*
914 * Create a new entry if allowable
915 */
916
Patrick McHardy6bd52142010-05-11 14:40:53 +0200917 if (atomic_read(&mrt->cache_resolve_queue_len) >= 10 ||
Patrick McHardyb5aa30b2010-05-11 14:40:50 +0200918 (c = ip6mr_cache_alloc_unres()) == NULL) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900919 spin_unlock_bh(&mfc_unres_lock);
920
921 kfree_skb(skb);
922 return -ENOBUFS;
923 }
924
925 /*
926 * Fill in the new cache entry
927 */
928 c->mf6c_parent = -1;
929 c->mf6c_origin = ipv6_hdr(skb)->saddr;
930 c->mf6c_mcastgrp = ipv6_hdr(skb)->daddr;
931
932 /*
933 * Reflect first query at pim6sd
934 */
Patrick McHardy6bd52142010-05-11 14:40:53 +0200935 err = ip6mr_cache_report(mrt, skb, mifi, MRT6MSG_NOCACHE);
Benjamin Thery8229efd2008-12-10 16:30:15 -0800936 if (err < 0) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900937 /* If the report failed throw the cache entry
938 out - Brad Parker
939 */
940 spin_unlock_bh(&mfc_unres_lock);
941
Benjamin Thery58701ad2008-12-10 16:22:34 -0800942 ip6mr_cache_free(c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900943 kfree_skb(skb);
944 return err;
945 }
946
Patrick McHardy6bd52142010-05-11 14:40:53 +0200947 atomic_inc(&mrt->cache_resolve_queue_len);
948 list_add(&c->list, &mrt->mfc6_unres_queue);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900949
Patrick McHardy6bd52142010-05-11 14:40:53 +0200950 ipmr_do_expire_process(mrt);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900951 }
952
953 /*
954 * See if we can append the packet
955 */
956 if (c->mfc_un.unres.unresolved.qlen > 3) {
957 kfree_skb(skb);
958 err = -ENOBUFS;
959 } else {
960 skb_queue_tail(&c->mfc_un.unres.unresolved, skb);
961 err = 0;
962 }
963
964 spin_unlock_bh(&mfc_unres_lock);
965 return err;
966}
967
968/*
969 * MFC6 cache manipulation by user space
970 */
971
Patrick McHardy6bd52142010-05-11 14:40:53 +0200972static int ip6mr_mfc_delete(struct mr6_table *mrt, struct mf6cctl *mfc)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900973{
974 int line;
Patrick McHardyf30a77842010-05-11 14:40:51 +0200975 struct mfc6_cache *c, *next;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900976
977 line = MFC6_HASH(&mfc->mf6cc_mcastgrp.sin6_addr, &mfc->mf6cc_origin.sin6_addr);
978
Patrick McHardy6bd52142010-05-11 14:40:53 +0200979 list_for_each_entry_safe(c, next, &mrt->mfc6_cache_array[line], list) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900980 if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) &&
981 ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr)) {
982 write_lock_bh(&mrt_lock);
Patrick McHardyf30a77842010-05-11 14:40:51 +0200983 list_del(&c->list);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900984 write_unlock_bh(&mrt_lock);
985
Benjamin Thery58701ad2008-12-10 16:22:34 -0800986 ip6mr_cache_free(c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900987 return 0;
988 }
989 }
990 return -ENOENT;
991}
992
993static int ip6mr_device_event(struct notifier_block *this,
994 unsigned long event, void *ptr)
995{
996 struct net_device *dev = ptr;
Benjamin Thery8229efd2008-12-10 16:30:15 -0800997 struct net *net = dev_net(dev);
Patrick McHardy6bd52142010-05-11 14:40:53 +0200998 struct mr6_table *mrt = net->ipv6.mrt6;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +0900999 struct mif_device *v;
1000 int ct;
Eric Dumazetc871e662009-10-28 04:48:11 +00001001 LIST_HEAD(list);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001002
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001003 if (event != NETDEV_UNREGISTER)
1004 return NOTIFY_DONE;
1005
Patrick McHardy6bd52142010-05-11 14:40:53 +02001006 v = &mrt->vif6_table[0];
1007 for (ct = 0; ct < mrt->maxvif; ct++, v++) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001008 if (v->dev == dev)
Patrick McHardy6bd52142010-05-11 14:40:53 +02001009 mif6_delete(mrt, ct, &list);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001010 }
Eric Dumazetc871e662009-10-28 04:48:11 +00001011 unregister_netdevice_many(&list);
1012
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001013 return NOTIFY_DONE;
1014}
1015
1016static struct notifier_block ip6_mr_notifier = {
1017 .notifier_call = ip6mr_device_event
1018};
1019
1020/*
1021 * Setup for IP multicast routing
1022 */
1023
Benjamin Thery4e168802008-12-10 16:15:08 -08001024static int __net_init ip6mr_net_init(struct net *net)
1025{
Patrick McHardy6bd52142010-05-11 14:40:53 +02001026 struct mr6_table *mrt;
Patrick McHardyf30a77842010-05-11 14:40:51 +02001027 unsigned int i;
Benjamin Thery4e168802008-12-10 16:15:08 -08001028 int err = 0;
Patrick McHardyf30a77842010-05-11 14:40:51 +02001029
Patrick McHardy6bd52142010-05-11 14:40:53 +02001030 mrt = kzalloc(sizeof(*mrt), GFP_KERNEL);
1031 if (mrt == NULL) {
Benjamin Thery4e168802008-12-10 16:15:08 -08001032 err = -ENOMEM;
1033 goto fail;
1034 }
Benjamin Thery4a6258a2008-12-10 16:24:07 -08001035
Patrick McHardy6bd52142010-05-11 14:40:53 +02001036 write_pnet(&mrt->net, net);
Benjamin Thery950d5702008-12-10 16:29:24 -08001037
Patrick McHardyf30a77842010-05-11 14:40:51 +02001038 for (i = 0; i < MFC6_LINES; i++)
Patrick McHardy6bd52142010-05-11 14:40:53 +02001039 INIT_LIST_HEAD(&mrt->mfc6_cache_array[i]);
Patrick McHardyf30a77842010-05-11 14:40:51 +02001040
Patrick McHardy6bd52142010-05-11 14:40:53 +02001041 INIT_LIST_HEAD(&mrt->mfc6_unres_queue);
Patrick McHardyf30a77842010-05-11 14:40:51 +02001042
Patrick McHardy6bd52142010-05-11 14:40:53 +02001043 setup_timer(&mrt->ipmr_expire_timer, ipmr_expire_process,
1044 (unsigned long)mrt);
Patrick McHardyc476efb2010-05-11 14:40:48 +02001045
Benjamin Thery950d5702008-12-10 16:29:24 -08001046#ifdef CONFIG_IPV6_PIMSM_V2
Patrick McHardy6bd52142010-05-11 14:40:53 +02001047 mrt->mroute_reg_vif_num = -1;
Benjamin Thery950d5702008-12-10 16:29:24 -08001048#endif
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001049
1050#ifdef CONFIG_PROC_FS
1051 err = -ENOMEM;
1052 if (!proc_net_fops_create(net, "ip6_mr_vif", 0, &ip6mr_vif_fops))
1053 goto proc_vif_fail;
1054 if (!proc_net_fops_create(net, "ip6_mr_cache", 0, &ip6mr_mfc_fops))
1055 goto proc_cache_fail;
1056#endif
Patrick McHardy6bd52142010-05-11 14:40:53 +02001057
1058 net->ipv6.mrt6 = mrt;
Benjamin Thery4a6258a2008-12-10 16:24:07 -08001059 return 0;
1060
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001061#ifdef CONFIG_PROC_FS
1062proc_cache_fail:
1063 proc_net_remove(net, "ip6_mr_vif");
1064proc_vif_fail:
Patrick McHardy6bd52142010-05-11 14:40:53 +02001065 kfree(mrt);
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001066#endif
Benjamin Thery4e168802008-12-10 16:15:08 -08001067fail:
1068 return err;
1069}
1070
1071static void __net_exit ip6mr_net_exit(struct net *net)
1072{
Patrick McHardy6bd52142010-05-11 14:40:53 +02001073 struct mr6_table *mrt = net->ipv6.mrt6;
1074
Benjamin Thery8b90fc72008-12-10 16:29:48 -08001075#ifdef CONFIG_PROC_FS
1076 proc_net_remove(net, "ip6_mr_cache");
1077 proc_net_remove(net, "ip6_mr_vif");
1078#endif
Patrick McHardy6bd52142010-05-11 14:40:53 +02001079 del_timer(&mrt->ipmr_expire_timer);
1080 mroute_clean_tables(mrt);
1081 kfree(mrt);
Benjamin Thery4e168802008-12-10 16:15:08 -08001082}
1083
1084static struct pernet_operations ip6mr_net_ops = {
1085 .init = ip6mr_net_init,
1086 .exit = ip6mr_net_exit,
1087};
1088
Wang Chen623d1a12008-07-03 12:13:30 +08001089int __init ip6_mr_init(void)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001090{
Wang Chen623d1a12008-07-03 12:13:30 +08001091 int err;
1092
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001093 mrt_cachep = kmem_cache_create("ip6_mrt_cache",
1094 sizeof(struct mfc6_cache),
1095 0, SLAB_HWCACHE_ALIGN,
1096 NULL);
1097 if (!mrt_cachep)
Wang Chen623d1a12008-07-03 12:13:30 +08001098 return -ENOMEM;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001099
Benjamin Thery4e168802008-12-10 16:15:08 -08001100 err = register_pernet_subsys(&ip6mr_net_ops);
1101 if (err)
1102 goto reg_pernet_fail;
1103
Wang Chen623d1a12008-07-03 12:13:30 +08001104 err = register_netdevice_notifier(&ip6_mr_notifier);
1105 if (err)
1106 goto reg_notif_fail;
Tom Goff403dbb92009-06-14 03:16:13 -07001107#ifdef CONFIG_IPV6_PIMSM_V2
1108 if (inet6_add_protocol(&pim6_protocol, IPPROTO_PIM) < 0) {
1109 printk(KERN_ERR "ip6_mr_init: can't add PIM protocol\n");
1110 err = -EAGAIN;
1111 goto add_proto_fail;
1112 }
1113#endif
Wang Chen623d1a12008-07-03 12:13:30 +08001114 return 0;
Tom Goff403dbb92009-06-14 03:16:13 -07001115#ifdef CONFIG_IPV6_PIMSM_V2
1116add_proto_fail:
1117 unregister_netdevice_notifier(&ip6_mr_notifier);
1118#endif
Benjamin Thery87b30a62008-11-10 16:34:11 -08001119reg_notif_fail:
Benjamin Thery4e168802008-12-10 16:15:08 -08001120 unregister_pernet_subsys(&ip6mr_net_ops);
1121reg_pernet_fail:
Benjamin Thery87b30a62008-11-10 16:34:11 -08001122 kmem_cache_destroy(mrt_cachep);
Wang Chen623d1a12008-07-03 12:13:30 +08001123 return err;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001124}
1125
Wang Chen623d1a12008-07-03 12:13:30 +08001126void ip6_mr_cleanup(void)
1127{
Wang Chen623d1a12008-07-03 12:13:30 +08001128 unregister_netdevice_notifier(&ip6_mr_notifier);
Benjamin Thery4e168802008-12-10 16:15:08 -08001129 unregister_pernet_subsys(&ip6mr_net_ops);
Wang Chen623d1a12008-07-03 12:13:30 +08001130 kmem_cache_destroy(mrt_cachep);
1131}
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001132
Patrick McHardy6bd52142010-05-11 14:40:53 +02001133static int ip6mr_mfc_add(struct net *net, struct mr6_table *mrt,
1134 struct mf6cctl *mfc, int mrtsock)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001135{
Patrick McHardyf30a77842010-05-11 14:40:51 +02001136 bool found = false;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001137 int line;
Patrick McHardyf30a77842010-05-11 14:40:51 +02001138 struct mfc6_cache *uc, *c;
Rami Rosen6ac7eb02008-04-10 12:40:10 +03001139 unsigned char ttls[MAXMIFS];
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001140 int i;
1141
Patrick McHardya50436f2010-03-17 06:04:14 +00001142 if (mfc->mf6cc_parent >= MAXMIFS)
1143 return -ENFILE;
1144
Rami Rosen6ac7eb02008-04-10 12:40:10 +03001145 memset(ttls, 255, MAXMIFS);
1146 for (i = 0; i < MAXMIFS; i++) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001147 if (IF_ISSET(i, &mfc->mf6cc_ifset))
1148 ttls[i] = 1;
1149
1150 }
1151
1152 line = MFC6_HASH(&mfc->mf6cc_mcastgrp.sin6_addr, &mfc->mf6cc_origin.sin6_addr);
1153
Patrick McHardy6bd52142010-05-11 14:40:53 +02001154 list_for_each_entry(c, &mrt->mfc6_cache_array[line], list) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001155 if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) &&
Patrick McHardyf30a77842010-05-11 14:40:51 +02001156 ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr)) {
1157 found = true;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001158 break;
Patrick McHardyf30a77842010-05-11 14:40:51 +02001159 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001160 }
1161
Patrick McHardyf30a77842010-05-11 14:40:51 +02001162 if (found) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001163 write_lock_bh(&mrt_lock);
1164 c->mf6c_parent = mfc->mf6cc_parent;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001165 ip6mr_update_thresholds(mrt, c, ttls);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001166 if (!mrtsock)
1167 c->mfc_flags |= MFC_STATIC;
1168 write_unlock_bh(&mrt_lock);
1169 return 0;
1170 }
1171
1172 if (!ipv6_addr_is_multicast(&mfc->mf6cc_mcastgrp.sin6_addr))
1173 return -EINVAL;
1174
Patrick McHardyb5aa30b2010-05-11 14:40:50 +02001175 c = ip6mr_cache_alloc();
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001176 if (c == NULL)
1177 return -ENOMEM;
1178
1179 c->mf6c_origin = mfc->mf6cc_origin.sin6_addr;
1180 c->mf6c_mcastgrp = mfc->mf6cc_mcastgrp.sin6_addr;
1181 c->mf6c_parent = mfc->mf6cc_parent;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001182 ip6mr_update_thresholds(mrt, c, ttls);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001183 if (!mrtsock)
1184 c->mfc_flags |= MFC_STATIC;
1185
1186 write_lock_bh(&mrt_lock);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001187 list_add(&c->list, &mrt->mfc6_cache_array[line]);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001188 write_unlock_bh(&mrt_lock);
1189
1190 /*
1191 * Check to see if we resolved a queued list. If so we
1192 * need to send on the frames and tidy up.
1193 */
Patrick McHardyf30a77842010-05-11 14:40:51 +02001194 found = false;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001195 spin_lock_bh(&mfc_unres_lock);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001196 list_for_each_entry(uc, &mrt->mfc6_unres_queue, list) {
Patrick McHardyc476efb2010-05-11 14:40:48 +02001197 if (ipv6_addr_equal(&uc->mf6c_origin, &c->mf6c_origin) &&
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001198 ipv6_addr_equal(&uc->mf6c_mcastgrp, &c->mf6c_mcastgrp)) {
Patrick McHardyf30a77842010-05-11 14:40:51 +02001199 list_del(&uc->list);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001200 atomic_dec(&mrt->cache_resolve_queue_len);
Patrick McHardyf30a77842010-05-11 14:40:51 +02001201 found = true;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001202 break;
1203 }
1204 }
Patrick McHardy6bd52142010-05-11 14:40:53 +02001205 if (list_empty(&mrt->mfc6_unres_queue))
1206 del_timer(&mrt->ipmr_expire_timer);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001207 spin_unlock_bh(&mfc_unres_lock);
1208
Patrick McHardyf30a77842010-05-11 14:40:51 +02001209 if (found) {
Patrick McHardy6bd52142010-05-11 14:40:53 +02001210 ip6mr_cache_resolve(net, mrt, uc, c);
Benjamin Thery58701ad2008-12-10 16:22:34 -08001211 ip6mr_cache_free(uc);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001212 }
1213 return 0;
1214}
1215
1216/*
1217 * Close the multicast socket, and clear the vif tables etc
1218 */
1219
Patrick McHardy6bd52142010-05-11 14:40:53 +02001220static void mroute_clean_tables(struct mr6_table *mrt)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001221{
1222 int i;
Eric Dumazetc871e662009-10-28 04:48:11 +00001223 LIST_HEAD(list);
Patrick McHardyf30a77842010-05-11 14:40:51 +02001224 struct mfc6_cache *c, *next;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001225
1226 /*
1227 * Shut down all active vif entries
1228 */
Patrick McHardy6bd52142010-05-11 14:40:53 +02001229 for (i = 0; i < mrt->maxvif; i++) {
1230 if (!(mrt->vif6_table[i].flags & VIFF_STATIC))
1231 mif6_delete(mrt, i, &list);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001232 }
Eric Dumazetc871e662009-10-28 04:48:11 +00001233 unregister_netdevice_many(&list);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001234
1235 /*
1236 * Wipe the cache
1237 */
Benjamin Thery4a6258a2008-12-10 16:24:07 -08001238 for (i = 0; i < MFC6_LINES; i++) {
Patrick McHardy6bd52142010-05-11 14:40:53 +02001239 list_for_each_entry_safe(c, next, &mrt->mfc6_cache_array[i], list) {
Patrick McHardyf30a77842010-05-11 14:40:51 +02001240 if (c->mfc_flags & MFC_STATIC)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001241 continue;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001242 write_lock_bh(&mrt_lock);
Patrick McHardyf30a77842010-05-11 14:40:51 +02001243 list_del(&c->list);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001244 write_unlock_bh(&mrt_lock);
1245
Benjamin Thery58701ad2008-12-10 16:22:34 -08001246 ip6mr_cache_free(c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001247 }
1248 }
1249
Patrick McHardy6bd52142010-05-11 14:40:53 +02001250 if (atomic_read(&mrt->cache_resolve_queue_len) != 0) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001251 spin_lock_bh(&mfc_unres_lock);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001252 list_for_each_entry_safe(c, next, &mrt->mfc6_unres_queue, list) {
Patrick McHardyf30a77842010-05-11 14:40:51 +02001253 list_del(&c->list);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001254 ip6mr_destroy_unres(mrt, c);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001255 }
1256 spin_unlock_bh(&mfc_unres_lock);
1257 }
1258}
1259
Patrick McHardy6bd52142010-05-11 14:40:53 +02001260static int ip6mr_sk_init(struct mr6_table *mrt, struct sock *sk)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001261{
1262 int err = 0;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001263 struct net *net = sock_net(sk);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001264
1265 rtnl_lock();
1266 write_lock_bh(&mrt_lock);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001267 if (likely(mrt->mroute6_sk == NULL)) {
1268 mrt->mroute6_sk = sk;
Thomas Goff1d6e55f2009-01-27 22:39:59 -08001269 net->ipv6.devconf_all->mc_forwarding++;
1270 }
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001271 else
1272 err = -EADDRINUSE;
1273 write_unlock_bh(&mrt_lock);
1274
1275 rtnl_unlock();
1276
1277 return err;
1278}
1279
1280int ip6mr_sk_done(struct sock *sk)
1281{
1282 int err = 0;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001283 struct net *net = sock_net(sk);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001284 struct mr6_table *mrt = net->ipv6.mrt6;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001285
1286 rtnl_lock();
Patrick McHardy6bd52142010-05-11 14:40:53 +02001287 if (sk == mrt->mroute6_sk) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001288 write_lock_bh(&mrt_lock);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001289 mrt->mroute6_sk = NULL;
Thomas Goff1d6e55f2009-01-27 22:39:59 -08001290 net->ipv6.devconf_all->mc_forwarding--;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001291 write_unlock_bh(&mrt_lock);
1292
Patrick McHardy6bd52142010-05-11 14:40:53 +02001293 mroute_clean_tables(mrt);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001294 } else
1295 err = -EACCES;
1296 rtnl_unlock();
1297
1298 return err;
1299}
1300
Patrick McHardy6bd52142010-05-11 14:40:53 +02001301struct sock *mroute6_socket(struct net *net)
1302{
1303 struct mr6_table *mrt = net->ipv6.mrt6;
1304
1305 return mrt->mroute6_sk;
1306}
1307
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001308/*
1309 * Socket options and virtual interface manipulation. The whole
1310 * virtual interface system is a complete heap, but unfortunately
1311 * that's how BSD mrouted happens to think. Maybe one day with a proper
1312 * MOSPF/PIM router set up we can clean this up.
1313 */
1314
David S. Millerb7058842009-09-30 16:12:20 -07001315int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsigned int optlen)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001316{
1317 int ret;
1318 struct mif6ctl vif;
1319 struct mf6cctl mfc;
1320 mifi_t mifi;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001321 struct net *net = sock_net(sk);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001322 struct mr6_table *mrt = net->ipv6.mrt6;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001323
1324 if (optname != MRT6_INIT) {
Patrick McHardy6bd52142010-05-11 14:40:53 +02001325 if (sk != mrt->mroute6_sk && !capable(CAP_NET_ADMIN))
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001326 return -EACCES;
1327 }
1328
1329 switch (optname) {
1330 case MRT6_INIT:
1331 if (sk->sk_type != SOCK_RAW ||
Eric Dumazetc720c7e2009-10-15 06:30:45 +00001332 inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001333 return -EOPNOTSUPP;
1334 if (optlen < sizeof(int))
1335 return -EINVAL;
1336
Patrick McHardy6bd52142010-05-11 14:40:53 +02001337 return ip6mr_sk_init(mrt, sk);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001338
1339 case MRT6_DONE:
1340 return ip6mr_sk_done(sk);
1341
1342 case MRT6_ADD_MIF:
1343 if (optlen < sizeof(vif))
1344 return -EINVAL;
1345 if (copy_from_user(&vif, optval, sizeof(vif)))
1346 return -EFAULT;
Rami Rosen6ac7eb02008-04-10 12:40:10 +03001347 if (vif.mif6c_mifi >= MAXMIFS)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001348 return -ENFILE;
1349 rtnl_lock();
Patrick McHardy6bd52142010-05-11 14:40:53 +02001350 ret = mif6_add(net, mrt, &vif, sk == mrt->mroute6_sk);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001351 rtnl_unlock();
1352 return ret;
1353
1354 case MRT6_DEL_MIF:
1355 if (optlen < sizeof(mifi_t))
1356 return -EINVAL;
1357 if (copy_from_user(&mifi, optval, sizeof(mifi_t)))
1358 return -EFAULT;
1359 rtnl_lock();
Patrick McHardy6bd52142010-05-11 14:40:53 +02001360 ret = mif6_delete(mrt, mifi, NULL);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001361 rtnl_unlock();
1362 return ret;
1363
1364 /*
1365 * Manipulate the forwarding caches. These live
1366 * in a sort of kernel/user symbiosis.
1367 */
1368 case MRT6_ADD_MFC:
1369 case MRT6_DEL_MFC:
1370 if (optlen < sizeof(mfc))
1371 return -EINVAL;
1372 if (copy_from_user(&mfc, optval, sizeof(mfc)))
1373 return -EFAULT;
1374 rtnl_lock();
1375 if (optname == MRT6_DEL_MFC)
Patrick McHardy6bd52142010-05-11 14:40:53 +02001376 ret = ip6mr_mfc_delete(mrt, &mfc);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001377 else
Patrick McHardy6bd52142010-05-11 14:40:53 +02001378 ret = ip6mr_mfc_add(net, mrt, &mfc, sk == mrt->mroute6_sk);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001379 rtnl_unlock();
1380 return ret;
1381
1382 /*
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001383 * Control PIM assert (to activate pim will activate assert)
1384 */
1385 case MRT6_ASSERT:
1386 {
1387 int v;
1388 if (get_user(v, (int __user *)optval))
1389 return -EFAULT;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001390 mrt->mroute_do_assert = !!v;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001391 return 0;
1392 }
1393
1394#ifdef CONFIG_IPV6_PIMSM_V2
1395 case MRT6_PIM:
1396 {
YOSHIFUJI Hideakia9f83bf2008-04-10 15:41:28 +09001397 int v;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001398 if (get_user(v, (int __user *)optval))
1399 return -EFAULT;
1400 v = !!v;
1401 rtnl_lock();
1402 ret = 0;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001403 if (v != mrt->mroute_do_pim) {
1404 mrt->mroute_do_pim = v;
1405 mrt->mroute_do_assert = v;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001406 }
1407 rtnl_unlock();
1408 return ret;
1409 }
1410
1411#endif
1412 /*
Rami Rosen7d120c52008-04-23 14:35:13 +03001413 * Spurious command, or MRT6_VERSION which you cannot
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001414 * set.
1415 */
1416 default:
1417 return -ENOPROTOOPT;
1418 }
1419}
1420
1421/*
1422 * Getsock opt support for the multicast routing system.
1423 */
1424
1425int ip6_mroute_getsockopt(struct sock *sk, int optname, char __user *optval,
1426 int __user *optlen)
1427{
1428 int olr;
1429 int val;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001430 struct net *net = sock_net(sk);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001431 struct mr6_table *mrt = net->ipv6.mrt6;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001432
1433 switch (optname) {
1434 case MRT6_VERSION:
1435 val = 0x0305;
1436 break;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001437#ifdef CONFIG_IPV6_PIMSM_V2
1438 case MRT6_PIM:
Patrick McHardy6bd52142010-05-11 14:40:53 +02001439 val = mrt->mroute_do_pim;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001440 break;
1441#endif
1442 case MRT6_ASSERT:
Patrick McHardy6bd52142010-05-11 14:40:53 +02001443 val = mrt->mroute_do_assert;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001444 break;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001445 default:
1446 return -ENOPROTOOPT;
1447 }
1448
1449 if (get_user(olr, optlen))
1450 return -EFAULT;
1451
1452 olr = min_t(int, olr, sizeof(int));
1453 if (olr < 0)
1454 return -EINVAL;
1455
1456 if (put_user(olr, optlen))
1457 return -EFAULT;
1458 if (copy_to_user(optval, &val, olr))
1459 return -EFAULT;
1460 return 0;
1461}
1462
1463/*
1464 * The IP multicast ioctl support routines.
1465 */
1466
1467int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg)
1468{
1469 struct sioc_sg_req6 sr;
1470 struct sioc_mif_req6 vr;
1471 struct mif_device *vif;
1472 struct mfc6_cache *c;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001473 struct net *net = sock_net(sk);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001474 struct mr6_table *mrt = net->ipv6.mrt6;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001475
1476 switch (cmd) {
1477 case SIOCGETMIFCNT_IN6:
1478 if (copy_from_user(&vr, arg, sizeof(vr)))
1479 return -EFAULT;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001480 if (vr.mifi >= mrt->maxvif)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001481 return -EINVAL;
1482 read_lock(&mrt_lock);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001483 vif = &mrt->vif6_table[vr.mifi];
1484 if (MIF_EXISTS(mrt, vr.mifi)) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001485 vr.icount = vif->pkt_in;
1486 vr.ocount = vif->pkt_out;
1487 vr.ibytes = vif->bytes_in;
1488 vr.obytes = vif->bytes_out;
1489 read_unlock(&mrt_lock);
1490
1491 if (copy_to_user(arg, &vr, sizeof(vr)))
1492 return -EFAULT;
1493 return 0;
1494 }
1495 read_unlock(&mrt_lock);
1496 return -EADDRNOTAVAIL;
1497 case SIOCGETSGCNT_IN6:
1498 if (copy_from_user(&sr, arg, sizeof(sr)))
1499 return -EFAULT;
1500
1501 read_lock(&mrt_lock);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001502 c = ip6mr_cache_find(mrt, &sr.src.sin6_addr, &sr.grp.sin6_addr);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001503 if (c) {
1504 sr.pktcnt = c->mfc_un.res.pkt;
1505 sr.bytecnt = c->mfc_un.res.bytes;
1506 sr.wrong_if = c->mfc_un.res.wrong_if;
1507 read_unlock(&mrt_lock);
1508
1509 if (copy_to_user(arg, &sr, sizeof(sr)))
1510 return -EFAULT;
1511 return 0;
1512 }
1513 read_unlock(&mrt_lock);
1514 return -EADDRNOTAVAIL;
1515 default:
1516 return -ENOIOCTLCMD;
1517 }
1518}
1519
1520
1521static inline int ip6mr_forward2_finish(struct sk_buff *skb)
1522{
Eric Dumazetadf30902009-06-02 05:19:30 +00001523 IP6_INC_STATS_BH(dev_net(skb_dst(skb)->dev), ip6_dst_idev(skb_dst(skb)),
Denis V. Lunev483a47d2008-10-08 11:09:27 -07001524 IPSTATS_MIB_OUTFORWDATAGRAMS);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001525 return dst_output(skb);
1526}
1527
1528/*
1529 * Processing handlers for ip6mr_forward
1530 */
1531
Patrick McHardy6bd52142010-05-11 14:40:53 +02001532static int ip6mr_forward2(struct net *net, struct mr6_table *mrt,
1533 struct sk_buff *skb, struct mfc6_cache *c, int vifi)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001534{
1535 struct ipv6hdr *ipv6h;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001536 struct mif_device *vif = &mrt->vif6_table[vifi];
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001537 struct net_device *dev;
1538 struct dst_entry *dst;
1539 struct flowi fl;
1540
1541 if (vif->dev == NULL)
1542 goto out_free;
1543
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001544#ifdef CONFIG_IPV6_PIMSM_V2
1545 if (vif->flags & MIFF_REGISTER) {
1546 vif->pkt_out++;
1547 vif->bytes_out += skb->len;
Pavel Emelyanovdc58c782008-05-21 14:17:54 -07001548 vif->dev->stats.tx_bytes += skb->len;
1549 vif->dev->stats.tx_packets++;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001550 ip6mr_cache_report(mrt, skb, vifi, MRT6MSG_WHOLEPKT);
Ilpo Järvinen8da73b72008-12-14 23:15:49 -08001551 goto out_free;
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001552 }
1553#endif
1554
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001555 ipv6h = ipv6_hdr(skb);
1556
1557 fl = (struct flowi) {
1558 .oif = vif->link,
1559 .nl_u = { .ip6_u =
1560 { .daddr = ipv6h->daddr, }
1561 }
1562 };
1563
Benjamin Thery8229efd2008-12-10 16:30:15 -08001564 dst = ip6_route_output(net, NULL, &fl);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001565 if (!dst)
1566 goto out_free;
1567
Eric Dumazetadf30902009-06-02 05:19:30 +00001568 skb_dst_drop(skb);
1569 skb_dst_set(skb, dst);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001570
1571 /*
1572 * RFC1584 teaches, that DVMRP/PIM router must deliver packets locally
1573 * not only before forwarding, but after forwarding on all output
1574 * interfaces. It is clear, if mrouter runs a multicasting
1575 * program, it should receive packets not depending to what interface
1576 * program is joined.
1577 * If we will not make it, the program will have to join on all
1578 * interfaces. On the other hand, multihoming host (or router, but
1579 * not mrouter) cannot join to more than one interface - it will
1580 * result in receiving multiple packets.
1581 */
1582 dev = vif->dev;
1583 skb->dev = dev;
1584 vif->pkt_out++;
1585 vif->bytes_out += skb->len;
1586
1587 /* We are about to write */
1588 /* XXX: extension headers? */
1589 if (skb_cow(skb, sizeof(*ipv6h) + LL_RESERVED_SPACE(dev)))
1590 goto out_free;
1591
1592 ipv6h = ipv6_hdr(skb);
1593 ipv6h->hop_limit--;
1594
1595 IP6CB(skb)->flags |= IP6SKB_FORWARDED;
1596
Jan Engelhardtb2e0b382010-03-23 04:09:07 +01001597 return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD, skb, skb->dev, dev,
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001598 ip6mr_forward2_finish);
1599
1600out_free:
1601 kfree_skb(skb);
1602 return 0;
1603}
1604
Patrick McHardy6bd52142010-05-11 14:40:53 +02001605static int ip6mr_find_vif(struct mr6_table *mrt, struct net_device *dev)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001606{
1607 int ct;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001608
1609 for (ct = mrt->maxvif - 1; ct >= 0; ct--) {
1610 if (mrt->vif6_table[ct].dev == dev)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001611 break;
1612 }
1613 return ct;
1614}
1615
Patrick McHardy6bd52142010-05-11 14:40:53 +02001616static int ip6_mr_forward(struct net *net, struct mr6_table *mrt,
1617 struct sk_buff *skb, struct mfc6_cache *cache)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001618{
1619 int psend = -1;
1620 int vif, ct;
1621
1622 vif = cache->mf6c_parent;
1623 cache->mfc_un.res.pkt++;
1624 cache->mfc_un.res.bytes += skb->len;
1625
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001626 /*
1627 * Wrong interface: drop packet and (maybe) send PIM assert.
1628 */
Patrick McHardy6bd52142010-05-11 14:40:53 +02001629 if (mrt->vif6_table[vif].dev != skb->dev) {
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001630 int true_vifi;
1631
1632 cache->mfc_un.res.wrong_if++;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001633 true_vifi = ip6mr_find_vif(mrt, skb->dev);
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001634
Patrick McHardy6bd52142010-05-11 14:40:53 +02001635 if (true_vifi >= 0 && mrt->mroute_do_assert &&
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001636 /* pimsm uses asserts, when switching from RPT to SPT,
1637 so that we cannot check that packet arrived on an oif.
1638 It is bad, but otherwise we would need to move pretty
1639 large chunk of pimd to kernel. Ough... --ANK
1640 */
Patrick McHardy6bd52142010-05-11 14:40:53 +02001641 (mrt->mroute_do_pim ||
Benjamin Therya21f3f92008-12-10 16:28:44 -08001642 cache->mfc_un.res.ttls[true_vifi] < 255) &&
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001643 time_after(jiffies,
1644 cache->mfc_un.res.last_assert + MFC_ASSERT_THRESH)) {
1645 cache->mfc_un.res.last_assert = jiffies;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001646 ip6mr_cache_report(mrt, skb, true_vifi, MRT6MSG_WRONGMIF);
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001647 }
1648 goto dont_forward;
1649 }
1650
Patrick McHardy6bd52142010-05-11 14:40:53 +02001651 mrt->vif6_table[vif].pkt_in++;
1652 mrt->vif6_table[vif].bytes_in += skb->len;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001653
1654 /*
1655 * Forward the frame
1656 */
1657 for (ct = cache->mfc_un.res.maxvif - 1; ct >= cache->mfc_un.res.minvif; ct--) {
1658 if (ipv6_hdr(skb)->hop_limit > cache->mfc_un.res.ttls[ct]) {
1659 if (psend != -1) {
1660 struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
1661 if (skb2)
Patrick McHardy6bd52142010-05-11 14:40:53 +02001662 ip6mr_forward2(net, mrt, skb2, cache, psend);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001663 }
1664 psend = ct;
1665 }
1666 }
1667 if (psend != -1) {
Patrick McHardy6bd52142010-05-11 14:40:53 +02001668 ip6mr_forward2(net, mrt, skb, cache, psend);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001669 return 0;
1670 }
1671
YOSHIFUJI Hideaki14fb64e2008-04-03 09:22:54 +09001672dont_forward:
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001673 kfree_skb(skb);
1674 return 0;
1675}
1676
1677
1678/*
1679 * Multicast packets for forwarding arrive here
1680 */
1681
1682int ip6_mr_input(struct sk_buff *skb)
1683{
1684 struct mfc6_cache *cache;
Benjamin Thery8229efd2008-12-10 16:30:15 -08001685 struct net *net = dev_net(skb->dev);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001686 struct mr6_table *mrt = net->ipv6.mrt6;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001687
1688 read_lock(&mrt_lock);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001689 cache = ip6mr_cache_find(mrt,
Benjamin Thery8229efd2008-12-10 16:30:15 -08001690 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001691
1692 /*
1693 * No usable cache entry
1694 */
1695 if (cache == NULL) {
1696 int vif;
1697
Patrick McHardy6bd52142010-05-11 14:40:53 +02001698 vif = ip6mr_find_vif(mrt, skb->dev);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001699 if (vif >= 0) {
Patrick McHardy6bd52142010-05-11 14:40:53 +02001700 int err = ip6mr_cache_unresolved(mrt, vif, skb);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001701 read_unlock(&mrt_lock);
1702
1703 return err;
1704 }
1705 read_unlock(&mrt_lock);
1706 kfree_skb(skb);
1707 return -ENODEV;
1708 }
1709
Patrick McHardy6bd52142010-05-11 14:40:53 +02001710 ip6_mr_forward(net, mrt, skb, cache);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001711
1712 read_unlock(&mrt_lock);
1713
1714 return 0;
1715}
1716
1717
1718static int
Patrick McHardy6bd52142010-05-11 14:40:53 +02001719ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb,
1720 struct mfc6_cache *c, struct rtmsg *rtm)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001721{
1722 int ct;
1723 struct rtnexthop *nhp;
YOSHIFUJI Hideaki549e0282008-04-05 22:17:39 +09001724 u8 *b = skb_tail_pointer(skb);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001725 struct rtattr *mp_head;
1726
Nicolas Dichtel74381892010-03-25 23:45:35 +00001727 /* If cache is unresolved, don't try to parse IIF and OIF */
1728 if (c->mf6c_parent > MAXMIFS)
1729 return -ENOENT;
1730
Patrick McHardy6bd52142010-05-11 14:40:53 +02001731 if (MIF_EXISTS(mrt, c->mf6c_parent))
1732 RTA_PUT(skb, RTA_IIF, 4, &mrt->vif6_table[c->mf6c_parent].dev->ifindex);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001733
1734 mp_head = (struct rtattr *)skb_put(skb, RTA_LENGTH(0));
1735
1736 for (ct = c->mfc_un.res.minvif; ct < c->mfc_un.res.maxvif; ct++) {
Patrick McHardy6bd52142010-05-11 14:40:53 +02001737 if (MIF_EXISTS(mrt, ct) && c->mfc_un.res.ttls[ct] < 255) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001738 if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4))
1739 goto rtattr_failure;
1740 nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp)));
1741 nhp->rtnh_flags = 0;
1742 nhp->rtnh_hops = c->mfc_un.res.ttls[ct];
Patrick McHardy6bd52142010-05-11 14:40:53 +02001743 nhp->rtnh_ifindex = mrt->vif6_table[ct].dev->ifindex;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001744 nhp->rtnh_len = sizeof(*nhp);
1745 }
1746 }
1747 mp_head->rta_type = RTA_MULTIPATH;
YOSHIFUJI Hideaki549e0282008-04-05 22:17:39 +09001748 mp_head->rta_len = skb_tail_pointer(skb) - (u8 *)mp_head;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001749 rtm->rtm_type = RTN_MULTICAST;
1750 return 1;
1751
1752rtattr_failure:
1753 nlmsg_trim(skb, b);
1754 return -EMSGSIZE;
1755}
1756
Benjamin Thery8229efd2008-12-10 16:30:15 -08001757int ip6mr_get_route(struct net *net,
1758 struct sk_buff *skb, struct rtmsg *rtm, int nowait)
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001759{
1760 int err;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001761 struct mr6_table *mrt = net->ipv6.mrt6;
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001762 struct mfc6_cache *cache;
Eric Dumazetadf30902009-06-02 05:19:30 +00001763 struct rt6_info *rt = (struct rt6_info *)skb_dst(skb);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001764
1765 read_lock(&mrt_lock);
Patrick McHardy6bd52142010-05-11 14:40:53 +02001766 cache = ip6mr_cache_find(mrt, &rt->rt6i_src.addr, &rt->rt6i_dst.addr);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001767
1768 if (!cache) {
1769 struct sk_buff *skb2;
1770 struct ipv6hdr *iph;
1771 struct net_device *dev;
1772 int vif;
1773
1774 if (nowait) {
1775 read_unlock(&mrt_lock);
1776 return -EAGAIN;
1777 }
1778
1779 dev = skb->dev;
Patrick McHardy6bd52142010-05-11 14:40:53 +02001780 if (dev == NULL || (vif = ip6mr_find_vif(mrt, dev)) < 0) {
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001781 read_unlock(&mrt_lock);
1782 return -ENODEV;
1783 }
1784
1785 /* really correct? */
1786 skb2 = alloc_skb(sizeof(struct ipv6hdr), GFP_ATOMIC);
1787 if (!skb2) {
1788 read_unlock(&mrt_lock);
1789 return -ENOMEM;
1790 }
1791
1792 skb_reset_transport_header(skb2);
1793
1794 skb_put(skb2, sizeof(struct ipv6hdr));
1795 skb_reset_network_header(skb2);
1796
1797 iph = ipv6_hdr(skb2);
1798 iph->version = 0;
1799 iph->priority = 0;
1800 iph->flow_lbl[0] = 0;
1801 iph->flow_lbl[1] = 0;
1802 iph->flow_lbl[2] = 0;
1803 iph->payload_len = 0;
1804 iph->nexthdr = IPPROTO_NONE;
1805 iph->hop_limit = 0;
1806 ipv6_addr_copy(&iph->saddr, &rt->rt6i_src.addr);
1807 ipv6_addr_copy(&iph->daddr, &rt->rt6i_dst.addr);
1808
Patrick McHardy6bd52142010-05-11 14:40:53 +02001809 err = ip6mr_cache_unresolved(mrt, vif, skb2);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001810 read_unlock(&mrt_lock);
1811
1812 return err;
1813 }
1814
1815 if (!nowait && (rtm->rtm_flags&RTM_F_NOTIFY))
1816 cache->mfc_flags |= MFC_NOTIFY;
1817
Patrick McHardy6bd52142010-05-11 14:40:53 +02001818 err = ip6mr_fill_mroute(mrt, skb, cache, rtm);
YOSHIFUJI Hideaki7bc570c2008-04-03 09:22:53 +09001819 read_unlock(&mrt_lock);
1820 return err;
1821}
1822