Deleted Added
full compact
ip6_mroute.c (254523) ip6_mroute.c (254889)
1/*-
2 * Copyright (C) 1998 WIDE Project.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the project nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $KAME: ip6_mroute.c,v 1.58 2001/12/18 02:36:31 itojun Exp $
30 */
31
32/*-
33 * Copyright (c) 1989 Stephen Deering
34 * Copyright (c) 1992, 1993
35 * The Regents of the University of California. All rights reserved.
36 *
37 * This code is derived from software contributed to Berkeley by
38 * Stephen Deering of Stanford University.
39 *
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
42 * are met:
43 * 1. Redistributions of source code must retain the above copyright
44 * notice, this list of conditions and the following disclaimer.
45 * 2. Redistributions in binary form must reproduce the above copyright
46 * notice, this list of conditions and the following disclaimer in the
47 * documentation and/or other materials provided with the distribution.
48 * 4. Neither the name of the University nor the names of its contributors
49 * may be used to endorse or promote products derived from this software
50 * without specific prior written permission.
51 *
52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * SUCH DAMAGE.
63 *
64 * @(#)ip_mroute.c 8.2 (Berkeley) 11/15/93
65 * BSDI ip_mroute.c,v 2.10 1996/11/14 00:29:52 jch Exp
66 */
67
68/*
69 * IP multicast forwarding procedures
70 *
71 * Written by David Waitzman, BBN Labs, August 1988.
72 * Modified by Steve Deering, Stanford, February 1989.
73 * Modified by Mark J. Steiglitz, Stanford, May, 1991
74 * Modified by Van Jacobson, LBL, January 1993
75 * Modified by Ajit Thyagarajan, PARC, August 1993
76 * Modified by Bill Fenner, PARC, April 1994
77 *
78 * MROUTING Revision: 3.5.1.2 + PIM-SMv2 (pimd) Support
79 */
80
81#include <sys/cdefs.h>
1/*-
2 * Copyright (C) 1998 WIDE Project.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the project nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $KAME: ip6_mroute.c,v 1.58 2001/12/18 02:36:31 itojun Exp $
30 */
31
32/*-
33 * Copyright (c) 1989 Stephen Deering
34 * Copyright (c) 1992, 1993
35 * The Regents of the University of California. All rights reserved.
36 *
37 * This code is derived from software contributed to Berkeley by
38 * Stephen Deering of Stanford University.
39 *
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
42 * are met:
43 * 1. Redistributions of source code must retain the above copyright
44 * notice, this list of conditions and the following disclaimer.
45 * 2. Redistributions in binary form must reproduce the above copyright
46 * notice, this list of conditions and the following disclaimer in the
47 * documentation and/or other materials provided with the distribution.
48 * 4. Neither the name of the University nor the names of its contributors
49 * may be used to endorse or promote products derived from this software
50 * without specific prior written permission.
51 *
52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * SUCH DAMAGE.
63 *
64 * @(#)ip_mroute.c 8.2 (Berkeley) 11/15/93
65 * BSDI ip_mroute.c,v 2.10 1996/11/14 00:29:52 jch Exp
66 */
67
68/*
69 * IP multicast forwarding procedures
70 *
71 * Written by David Waitzman, BBN Labs, August 1988.
72 * Modified by Steve Deering, Stanford, February 1989.
73 * Modified by Mark J. Steiglitz, Stanford, May, 1991
74 * Modified by Van Jacobson, LBL, January 1993
75 * Modified by Ajit Thyagarajan, PARC, August 1993
76 * Modified by Bill Fenner, PARC, April 1994
77 *
78 * MROUTING Revision: 3.5.1.2 + PIM-SMv2 (pimd) Support
79 */
80
81#include <sys/cdefs.h>
82__FBSDID("$FreeBSD: head/sys/netinet6/ip6_mroute.c 254523 2013-08-19 13:27:32Z andre $");
82__FBSDID("$FreeBSD: head/sys/netinet6/ip6_mroute.c 254889 2013-08-25 21:54:41Z markj $");
83
84#include "opt_inet6.h"
83
84#include "opt_inet6.h"
85#include "opt_kdtrace.h"
85
86#include <sys/param.h>
87#include <sys/callout.h>
88#include <sys/errno.h>
89#include <sys/kernel.h>
90#include <sys/lock.h>
91#include <sys/malloc.h>
92#include <sys/mbuf.h>
93#include <sys/module.h>
94#include <sys/domain.h>
95#include <sys/protosw.h>
86
87#include <sys/param.h>
88#include <sys/callout.h>
89#include <sys/errno.h>
90#include <sys/kernel.h>
91#include <sys/lock.h>
92#include <sys/malloc.h>
93#include <sys/mbuf.h>
94#include <sys/module.h>
95#include <sys/domain.h>
96#include <sys/protosw.h>
97#include <sys/sdt.h>
96#include <sys/signalvar.h>
97#include <sys/socket.h>
98#include <sys/socketvar.h>
99#include <sys/sockio.h>
100#include <sys/sx.h>
101#include <sys/sysctl.h>
102#include <sys/syslog.h>
103#include <sys/systm.h>
104#include <sys/time.h>
105
106#include <net/if.h>
107#include <net/if_types.h>
108#include <net/raw_cb.h>
109#include <net/vnet.h>
110
111#include <netinet/in.h>
112#include <netinet/in_var.h>
113#include <netinet/icmp6.h>
114#include <netinet/ip_encap.h>
115
116#include <netinet/ip6.h>
98#include <sys/signalvar.h>
99#include <sys/socket.h>
100#include <sys/socketvar.h>
101#include <sys/sockio.h>
102#include <sys/sx.h>
103#include <sys/sysctl.h>
104#include <sys/syslog.h>
105#include <sys/systm.h>
106#include <sys/time.h>
107
108#include <net/if.h>
109#include <net/if_types.h>
110#include <net/raw_cb.h>
111#include <net/vnet.h>
112
113#include <netinet/in.h>
114#include <netinet/in_var.h>
115#include <netinet/icmp6.h>
116#include <netinet/ip_encap.h>
117
118#include <netinet/ip6.h>
119#include <netinet/in_kdtrace.h>
117#include <netinet6/ip6_var.h>
118#include <netinet6/scope6_var.h>
119#include <netinet6/nd6.h>
120#include <netinet6/ip6_mroute.h>
121#include <netinet6/ip6protosw.h>
122#include <netinet6/pim6.h>
123#include <netinet6/pim6_var.h>
124
125static MALLOC_DEFINE(M_MRTABLE6, "mf6c", "multicast forwarding cache entry");
126
127/* XXX: this is a very common idiom; move to <sys/mbuf.h> ? */
128#define M_HASCL(m) ((m)->m_flags & M_EXT)
129
130static int ip6_mdq(struct mbuf *, struct ifnet *, struct mf6c *);
131static void phyint_send(struct ip6_hdr *, struct mif6 *, struct mbuf *);
132static int register_send(struct ip6_hdr *, struct mif6 *, struct mbuf *);
133static int set_pim6(int *);
134static int socket_send(struct socket *, struct mbuf *,
135 struct sockaddr_in6 *);
136
137extern int in6_mcast_loop;
138extern struct domain inet6domain;
139
140static const struct encaptab *pim6_encap_cookie;
141static const struct ip6protosw in6_pim_protosw = {
142 .pr_type = SOCK_RAW,
143 .pr_domain = &inet6domain,
144 .pr_protocol = IPPROTO_PIM,
145 .pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR,
146 .pr_input = pim6_input,
147 .pr_output = rip6_output,
148 .pr_ctloutput = rip6_ctloutput,
149 .pr_usrreqs = &rip6_usrreqs
150};
151static int pim6_encapcheck(const struct mbuf *, int, int, void *);
152
153static VNET_DEFINE(int, ip6_mrouter_ver) = 0;
154#define V_ip6_mrouter_ver VNET(ip6_mrouter_ver)
155
156SYSCTL_DECL(_net_inet6);
157SYSCTL_DECL(_net_inet6_ip6);
158static SYSCTL_NODE(_net_inet6, IPPROTO_PIM, pim, CTLFLAG_RW, 0, "PIM");
159
160static struct mrt6stat mrt6stat;
161SYSCTL_STRUCT(_net_inet6_ip6, OID_AUTO, mrt6stat, CTLFLAG_RW,
162 &mrt6stat, mrt6stat,
163 "Multicast Routing Statistics (struct mrt6stat, netinet6/ip6_mroute.h)");
164
165#define MRT6STAT_INC(name) mrt6stat.name += 1
166#define NO_RTE_FOUND 0x1
167#define RTE_FOUND 0x2
168
169static struct mtx mrouter6_mtx;
170#define MROUTER6_LOCK() mtx_lock(&mrouter6_mtx)
171#define MROUTER6_UNLOCK() mtx_unlock(&mrouter6_mtx)
172#define MROUTER6_LOCK_ASSERT() do { \
173 mtx_assert(&mrouter6_mtx, MA_OWNED); \
174 NET_ASSERT_GIANT(); \
175} while (0)
176#define MROUTER6_LOCK_INIT() \
177 mtx_init(&mrouter6_mtx, "IPv6 multicast forwarding", NULL, MTX_DEF)
178#define MROUTER6_LOCK_DESTROY() mtx_destroy(&mrouter6_mtx)
179
180static struct mf6c *mf6ctable[MF6CTBLSIZ];
181SYSCTL_OPAQUE(_net_inet6_ip6, OID_AUTO, mf6ctable, CTLFLAG_RD,
182 &mf6ctable, sizeof(mf6ctable), "S,*mf6ctable[MF6CTBLSIZ]",
183 "IPv6 Multicast Forwarding Table (struct *mf6ctable[MF6CTBLSIZ], "
184 "netinet6/ip6_mroute.h)");
185
186static struct mtx mfc6_mtx;
187#define MFC6_LOCK() mtx_lock(&mfc6_mtx)
188#define MFC6_UNLOCK() mtx_unlock(&mfc6_mtx)
189#define MFC6_LOCK_ASSERT() do { \
190 mtx_assert(&mfc6_mtx, MA_OWNED); \
191 NET_ASSERT_GIANT(); \
192} while (0)
193#define MFC6_LOCK_INIT() \
194 mtx_init(&mfc6_mtx, "IPv6 multicast forwarding cache", NULL, MTX_DEF)
195#define MFC6_LOCK_DESTROY() mtx_destroy(&mfc6_mtx)
196
197static u_char n6expire[MF6CTBLSIZ];
198
199static struct mif6 mif6table[MAXMIFS];
200SYSCTL_OPAQUE(_net_inet6_ip6, OID_AUTO, mif6table, CTLFLAG_RD,
201 &mif6table, sizeof(mif6table), "S,mif6[MAXMIFS]",
202 "IPv6 Multicast Interfaces (struct mif6[MAXMIFS], netinet6/ip6_mroute.h)");
203
204static struct mtx mif6_mtx;
205#define MIF6_LOCK() mtx_lock(&mif6_mtx)
206#define MIF6_UNLOCK() mtx_unlock(&mif6_mtx)
207#define MIF6_LOCK_ASSERT() mtx_assert(&mif6_mtx, MA_OWNED)
208#define MIF6_LOCK_INIT() \
209 mtx_init(&mif6_mtx, "IPv6 multicast interfaces", NULL, MTX_DEF)
210#define MIF6_LOCK_DESTROY() mtx_destroy(&mif6_mtx)
211
212#ifdef MRT6DEBUG
213static VNET_DEFINE(u_int, mrt6debug) = 0; /* debug level */
214#define V_mrt6debug VNET(mrt6debug)
215#define DEBUG_MFC 0x02
216#define DEBUG_FORWARD 0x04
217#define DEBUG_EXPIRE 0x08
218#define DEBUG_XMIT 0x10
219#define DEBUG_REG 0x20
220#define DEBUG_PIM 0x40
221#endif
222
223static void expire_upcalls(void *);
224#define EXPIRE_TIMEOUT (hz / 4) /* 4x / second */
225#define UPCALL_EXPIRE 6 /* number of timeouts */
226
227/*
228 * XXX TODO: maintain a count to if_allmulti() calls in struct ifnet.
229 */
230
231/*
232 * 'Interfaces' associated with decapsulator (so we can tell
233 * packets that went through it from ones that get reflected
234 * by a broken gateway). Different from IPv4 register_if,
235 * these interfaces are linked into the system ifnet list,
236 * because per-interface IPv6 statistics are maintained in
237 * ifp->if_afdata. But it does not have any routes point
238 * to them. I.e., packets can't be sent this way. They
239 * only exist as a placeholder for multicast source
240 * verification.
241 */
242static struct ifnet *multicast_register_if6;
243
244#define ENCAP_HOPS 64
245
246/*
247 * Private variables.
248 */
249static mifi_t nummifs = 0;
250static mifi_t reg_mif_num = (mifi_t)-1;
251
252static struct pim6stat pim6stat;
253SYSCTL_STRUCT(_net_inet6_pim, PIM6CTL_STATS, stats, CTLFLAG_RW,
254 &pim6stat, pim6stat,
255 "PIM Statistics (struct pim6stat, netinet6/pim6_var.h)");
256
257#define PIM6STAT_INC(name) pim6stat.name += 1
258static VNET_DEFINE(int, pim6);
259#define V_pim6 VNET(pim6)
260
261/*
262 * Hash function for a source, group entry
263 */
264#define MF6CHASH(a, g) MF6CHASHMOD((a).s6_addr32[0] ^ (a).s6_addr32[1] ^ \
265 (a).s6_addr32[2] ^ (a).s6_addr32[3] ^ \
266 (g).s6_addr32[0] ^ (g).s6_addr32[1] ^ \
267 (g).s6_addr32[2] ^ (g).s6_addr32[3])
268
269/*
270 * Find a route for a given origin IPv6 address and Multicast group address.
271 */
272#define MF6CFIND(o, g, rt) do { \
273 struct mf6c *_rt = mf6ctable[MF6CHASH(o,g)]; \
274 rt = NULL; \
275 MRT6STAT_INC(mrt6s_mfc_lookups); \
276 while (_rt) { \
277 if (IN6_ARE_ADDR_EQUAL(&_rt->mf6c_origin.sin6_addr, &(o)) && \
278 IN6_ARE_ADDR_EQUAL(&_rt->mf6c_mcastgrp.sin6_addr, &(g)) && \
279 (_rt->mf6c_stall == NULL)) { \
280 rt = _rt; \
281 break; \
282 } \
283 _rt = _rt->mf6c_next; \
284 } \
285 if (rt == NULL) { \
286 MRT6STAT_INC(mrt6s_mfc_misses); \
287 } \
288} while (/*CONSTCOND*/ 0)
289
290/*
291 * Macros to compute elapsed time efficiently
292 * Borrowed from Van Jacobson's scheduling code
293 * XXX: replace with timersub() ?
294 */
295#define TV_DELTA(a, b, delta) do { \
296 int xxs; \
297 \
298 delta = (a).tv_usec - (b).tv_usec; \
299 if ((xxs = (a).tv_sec - (b).tv_sec)) { \
300 switch (xxs) { \
301 case 2: \
302 delta += 1000000; \
303 /* FALLTHROUGH */ \
304 case 1: \
305 delta += 1000000; \
306 break; \
307 default: \
308 delta += (1000000 * xxs); \
309 } \
310 } \
311} while (/*CONSTCOND*/ 0)
312
313/* XXX: replace with timercmp(a, b, <) ? */
314#define TV_LT(a, b) (((a).tv_usec < (b).tv_usec && \
315 (a).tv_sec <= (b).tv_sec) || (a).tv_sec < (b).tv_sec)
316
317#ifdef UPCALL_TIMING
318#define UPCALL_MAX 50
319static u_long upcall_data[UPCALL_MAX + 1];
320static void collate();
321#endif /* UPCALL_TIMING */
322
323static int ip6_mrouter_init(struct socket *, int, int);
324static int add_m6fc(struct mf6cctl *);
325static int add_m6if(struct mif6ctl *);
326static int del_m6fc(struct mf6cctl *);
327static int del_m6if(mifi_t *);
328static int del_m6if_locked(mifi_t *);
329static int get_mif6_cnt(struct sioc_mif_req6 *);
330static int get_sg_cnt(struct sioc_sg_req6 *);
331
332static struct callout expire_upcalls_ch;
333
334int X_ip6_mforward(struct ip6_hdr *, struct ifnet *, struct mbuf *);
335int X_ip6_mrouter_done(void);
336int X_ip6_mrouter_set(struct socket *, struct sockopt *);
337int X_ip6_mrouter_get(struct socket *, struct sockopt *);
338int X_mrt6_ioctl(u_long, caddr_t);
339
340/*
341 * Handle MRT setsockopt commands to modify the multicast routing tables.
342 */
343int
344X_ip6_mrouter_set(struct socket *so, struct sockopt *sopt)
345{
346 int error = 0;
347 int optval;
348 struct mif6ctl mifc;
349 struct mf6cctl mfcc;
350 mifi_t mifi;
351
352 if (so != V_ip6_mrouter && sopt->sopt_name != MRT6_INIT)
353 return (EACCES);
354
355 switch (sopt->sopt_name) {
356 case MRT6_INIT:
357#ifdef MRT6_OINIT
358 case MRT6_OINIT:
359#endif
360 error = sooptcopyin(sopt, &optval, sizeof(optval),
361 sizeof(optval));
362 if (error)
363 break;
364 error = ip6_mrouter_init(so, optval, sopt->sopt_name);
365 break;
366 case MRT6_DONE:
367 error = X_ip6_mrouter_done();
368 break;
369 case MRT6_ADD_MIF:
370 error = sooptcopyin(sopt, &mifc, sizeof(mifc), sizeof(mifc));
371 if (error)
372 break;
373 error = add_m6if(&mifc);
374 break;
375 case MRT6_ADD_MFC:
376 error = sooptcopyin(sopt, &mfcc, sizeof(mfcc), sizeof(mfcc));
377 if (error)
378 break;
379 error = add_m6fc(&mfcc);
380 break;
381 case MRT6_DEL_MFC:
382 error = sooptcopyin(sopt, &mfcc, sizeof(mfcc), sizeof(mfcc));
383 if (error)
384 break;
385 error = del_m6fc(&mfcc);
386 break;
387 case MRT6_DEL_MIF:
388 error = sooptcopyin(sopt, &mifi, sizeof(mifi), sizeof(mifi));
389 if (error)
390 break;
391 error = del_m6if(&mifi);
392 break;
393 case MRT6_PIM:
394 error = sooptcopyin(sopt, &optval, sizeof(optval),
395 sizeof(optval));
396 if (error)
397 break;
398 error = set_pim6(&optval);
399 break;
400 default:
401 error = EOPNOTSUPP;
402 break;
403 }
404
405 return (error);
406}
407
408/*
409 * Handle MRT getsockopt commands
410 */
411int
412X_ip6_mrouter_get(struct socket *so, struct sockopt *sopt)
413{
414 int error = 0;
415
416 if (so != V_ip6_mrouter)
417 return (EACCES);
418
419 switch (sopt->sopt_name) {
420 case MRT6_PIM:
421 error = sooptcopyout(sopt, &V_pim6, sizeof(V_pim6));
422 break;
423 }
424 return (error);
425}
426
427/*
428 * Handle ioctl commands to obtain information from the cache
429 */
430int
431X_mrt6_ioctl(u_long cmd, caddr_t data)
432{
433 int ret;
434
435 ret = EINVAL;
436
437 switch (cmd) {
438 case SIOCGETSGCNT_IN6:
439 ret = get_sg_cnt((struct sioc_sg_req6 *)data);
440 break;
441
442 case SIOCGETMIFCNT_IN6:
443 ret = get_mif6_cnt((struct sioc_mif_req6 *)data);
444 break;
445
446 default:
447 break;
448 }
449
450 return (ret);
451}
452
453/*
454 * returns the packet, byte, rpf-failure count for the source group provided
455 */
456static int
457get_sg_cnt(struct sioc_sg_req6 *req)
458{
459 struct mf6c *rt;
460 int ret;
461
462 ret = 0;
463
464 MFC6_LOCK();
465
466 MF6CFIND(req->src.sin6_addr, req->grp.sin6_addr, rt);
467 if (rt == NULL) {
468 ret = ESRCH;
469 } else {
470 req->pktcnt = rt->mf6c_pkt_cnt;
471 req->bytecnt = rt->mf6c_byte_cnt;
472 req->wrong_if = rt->mf6c_wrong_if;
473 }
474
475 MFC6_UNLOCK();
476
477 return (ret);
478}
479
480/*
481 * returns the input and output packet and byte counts on the mif provided
482 */
483static int
484get_mif6_cnt(struct sioc_mif_req6 *req)
485{
486 mifi_t mifi;
487 int ret;
488
489 ret = 0;
490 mifi = req->mifi;
491
492 MIF6_LOCK();
493
494 if (mifi >= nummifs) {
495 ret = EINVAL;
496 } else {
497 req->icount = mif6table[mifi].m6_pkt_in;
498 req->ocount = mif6table[mifi].m6_pkt_out;
499 req->ibytes = mif6table[mifi].m6_bytes_in;
500 req->obytes = mif6table[mifi].m6_bytes_out;
501 }
502
503 MIF6_UNLOCK();
504
505 return (ret);
506}
507
508static int
509set_pim6(int *i)
510{
511 if ((*i != 1) && (*i != 0))
512 return (EINVAL);
513
514 V_pim6 = *i;
515
516 return (0);
517}
518
519/*
520 * Enable multicast routing
521 */
522static int
523ip6_mrouter_init(struct socket *so, int v, int cmd)
524{
525
526#ifdef MRT6DEBUG
527 if (V_mrt6debug)
528 log(LOG_DEBUG,
529 "ip6_mrouter_init: so_type = %d, pr_protocol = %d\n",
530 so->so_type, so->so_proto->pr_protocol);
531#endif
532
533 if (so->so_type != SOCK_RAW ||
534 so->so_proto->pr_protocol != IPPROTO_ICMPV6)
535 return (EOPNOTSUPP);
536
537 if (v != 1)
538 return (ENOPROTOOPT);
539
540 MROUTER6_LOCK();
541
542 if (V_ip6_mrouter != NULL) {
543 MROUTER6_UNLOCK();
544 return (EADDRINUSE);
545 }
546
547 V_ip6_mrouter = so;
548 V_ip6_mrouter_ver = cmd;
549
550 bzero((caddr_t)mf6ctable, sizeof(mf6ctable));
551 bzero((caddr_t)n6expire, sizeof(n6expire));
552
553 V_pim6 = 0;/* used for stubbing out/in pim stuff */
554
555 callout_init(&expire_upcalls_ch, 0);
556 callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT,
557 expire_upcalls, NULL);
558
559 MROUTER6_UNLOCK();
560
561#ifdef MRT6DEBUG
562 if (V_mrt6debug)
563 log(LOG_DEBUG, "ip6_mrouter_init\n");
564#endif
565
566 return (0);
567}
568
569/*
570 * Disable IPv6 multicast forwarding.
571 */
572int
573X_ip6_mrouter_done(void)
574{
575 mifi_t mifi;
576 int i;
577 struct mf6c *rt;
578 struct rtdetq *rte;
579
580 MROUTER6_LOCK();
581
582 if (V_ip6_mrouter == NULL) {
583 MROUTER6_UNLOCK();
584 return (EINVAL);
585 }
586
587 /*
588 * For each phyint in use, disable promiscuous reception of all IPv6
589 * multicasts.
590 */
591 for (mifi = 0; mifi < nummifs; mifi++) {
592 if (mif6table[mifi].m6_ifp &&
593 !(mif6table[mifi].m6_flags & MIFF_REGISTER)) {
594 if_allmulti(mif6table[mifi].m6_ifp, 0);
595 }
596 }
597 bzero((caddr_t)mif6table, sizeof(mif6table));
598 nummifs = 0;
599
600 V_pim6 = 0; /* used to stub out/in pim specific code */
601
602 callout_stop(&expire_upcalls_ch);
603
604 /*
605 * Free all multicast forwarding cache entries.
606 */
607 MFC6_LOCK();
608 for (i = 0; i < MF6CTBLSIZ; i++) {
609 rt = mf6ctable[i];
610 while (rt) {
611 struct mf6c *frt;
612
613 for (rte = rt->mf6c_stall; rte != NULL; ) {
614 struct rtdetq *n = rte->next;
615
616 m_free(rte->m);
617 free(rte, M_MRTABLE6);
618 rte = n;
619 }
620 frt = rt;
621 rt = rt->mf6c_next;
622 free(frt, M_MRTABLE6);
623 }
624 }
625 bzero((caddr_t)mf6ctable, sizeof(mf6ctable));
626 MFC6_UNLOCK();
627
628 /*
629 * Reset register interface
630 */
631 if (reg_mif_num != (mifi_t)-1 && multicast_register_if6 != NULL) {
632 if_detach(multicast_register_if6);
633 if_free(multicast_register_if6);
634 reg_mif_num = (mifi_t)-1;
635 multicast_register_if6 = NULL;
636 }
637
638 V_ip6_mrouter = NULL;
639 V_ip6_mrouter_ver = 0;
640
641 MROUTER6_UNLOCK();
642
643#ifdef MRT6DEBUG
644 if (V_mrt6debug)
645 log(LOG_DEBUG, "ip6_mrouter_done\n");
646#endif
647
648 return (0);
649}
650
651static struct sockaddr_in6 sin6 = { sizeof(sin6), AF_INET6 };
652
653/*
654 * Add a mif to the mif table
655 */
656static int
657add_m6if(struct mif6ctl *mifcp)
658{
659 struct mif6 *mifp;
660 struct ifnet *ifp;
661 int error;
662
663 MIF6_LOCK();
664
665 if (mifcp->mif6c_mifi >= MAXMIFS) {
666 MIF6_UNLOCK();
667 return (EINVAL);
668 }
669 mifp = mif6table + mifcp->mif6c_mifi;
670 if (mifp->m6_ifp != NULL) {
671 MIF6_UNLOCK();
672 return (EADDRINUSE); /* XXX: is it appropriate? */
673 }
674 if (mifcp->mif6c_pifi == 0 || mifcp->mif6c_pifi > V_if_index) {
675 MIF6_UNLOCK();
676 return (ENXIO);
677 }
678
679 ifp = ifnet_byindex(mifcp->mif6c_pifi);
680
681 if (mifcp->mif6c_flags & MIFF_REGISTER) {
682 if (reg_mif_num == (mifi_t)-1) {
683 ifp = if_alloc(IFT_OTHER);
684
685 if_initname(ifp, "register_mif", 0);
686 ifp->if_flags |= IFF_LOOPBACK;
687 if_attach(ifp);
688 multicast_register_if6 = ifp;
689 reg_mif_num = mifcp->mif6c_mifi;
690 /*
691 * it is impossible to guess the ifindex of the
692 * register interface. So mif6c_pifi is automatically
693 * calculated.
694 */
695 mifcp->mif6c_pifi = ifp->if_index;
696 } else {
697 ifp = multicast_register_if6;
698 }
699 } else {
700 /* Make sure the interface supports multicast */
701 if ((ifp->if_flags & IFF_MULTICAST) == 0) {
702 MIF6_UNLOCK();
703 return (EOPNOTSUPP);
704 }
705
706 error = if_allmulti(ifp, 1);
707 if (error) {
708 MIF6_UNLOCK();
709 return (error);
710 }
711 }
712
713 mifp->m6_flags = mifcp->mif6c_flags;
714 mifp->m6_ifp = ifp;
715
716 /* initialize per mif pkt counters */
717 mifp->m6_pkt_in = 0;
718 mifp->m6_pkt_out = 0;
719 mifp->m6_bytes_in = 0;
720 mifp->m6_bytes_out = 0;
721
722 /* Adjust nummifs up if the mifi is higher than nummifs */
723 if (nummifs <= mifcp->mif6c_mifi)
724 nummifs = mifcp->mif6c_mifi + 1;
725
726 MIF6_UNLOCK();
727
728#ifdef MRT6DEBUG
729 if (V_mrt6debug)
730 log(LOG_DEBUG,
731 "add_mif #%d, phyint %s\n",
732 mifcp->mif6c_mifi,
733 ifp->if_xname);
734#endif
735
736 return (0);
737}
738
739/*
740 * Delete a mif from the mif table
741 */
742static int
743del_m6if_locked(mifi_t *mifip)
744{
745 struct mif6 *mifp = mif6table + *mifip;
746 mifi_t mifi;
747 struct ifnet *ifp;
748
749 MIF6_LOCK_ASSERT();
750
751 if (*mifip >= nummifs)
752 return (EINVAL);
753 if (mifp->m6_ifp == NULL)
754 return (EINVAL);
755
756 if (!(mifp->m6_flags & MIFF_REGISTER)) {
757 /* XXX: TODO: Maintain an ALLMULTI refcount in struct ifnet. */
758 ifp = mifp->m6_ifp;
759 if_allmulti(ifp, 0);
760 } else {
761 if (reg_mif_num != (mifi_t)-1 &&
762 multicast_register_if6 != NULL) {
763 if_detach(multicast_register_if6);
764 if_free(multicast_register_if6);
765 reg_mif_num = (mifi_t)-1;
766 multicast_register_if6 = NULL;
767 }
768 }
769
770 bzero((caddr_t)mifp, sizeof(*mifp));
771
772 /* Adjust nummifs down */
773 for (mifi = nummifs; mifi > 0; mifi--)
774 if (mif6table[mifi - 1].m6_ifp)
775 break;
776 nummifs = mifi;
777
778#ifdef MRT6DEBUG
779 if (V_mrt6debug)
780 log(LOG_DEBUG, "del_m6if %d, nummifs %d\n", *mifip, nummifs);
781#endif
782
783 return (0);
784}
785
786static int
787del_m6if(mifi_t *mifip)
788{
789 int cc;
790
791 MIF6_LOCK();
792 cc = del_m6if_locked(mifip);
793 MIF6_UNLOCK();
794
795 return (cc);
796}
797
798/*
799 * Add an mfc entry
800 */
801static int
802add_m6fc(struct mf6cctl *mfccp)
803{
804 struct mf6c *rt;
805 u_long hash;
806 struct rtdetq *rte;
807 u_short nstl;
808 char ip6bufo[INET6_ADDRSTRLEN], ip6bufg[INET6_ADDRSTRLEN];
809
810 MFC6_LOCK();
811
812 MF6CFIND(mfccp->mf6cc_origin.sin6_addr,
813 mfccp->mf6cc_mcastgrp.sin6_addr, rt);
814
815 /* If an entry already exists, just update the fields */
816 if (rt) {
817#ifdef MRT6DEBUG
818 if (V_mrt6debug & DEBUG_MFC) {
819 log(LOG_DEBUG,
820 "add_m6fc no upcall h %d o %s g %s p %x\n",
821 ip6_sprintf(ip6bufo, &mfccp->mf6cc_origin.sin6_addr),
822 ip6_sprintf(ip6bufg, &mfccp->mf6cc_mcastgrp.sin6_addr),
823 mfccp->mf6cc_parent);
824 }
825#endif
826
827 rt->mf6c_parent = mfccp->mf6cc_parent;
828 rt->mf6c_ifset = mfccp->mf6cc_ifset;
829
830 MFC6_UNLOCK();
831 return (0);
832 }
833
834 /*
835 * Find the entry for which the upcall was made and update
836 */
837 hash = MF6CHASH(mfccp->mf6cc_origin.sin6_addr,
838 mfccp->mf6cc_mcastgrp.sin6_addr);
839 for (rt = mf6ctable[hash], nstl = 0; rt; rt = rt->mf6c_next) {
840 if (IN6_ARE_ADDR_EQUAL(&rt->mf6c_origin.sin6_addr,
841 &mfccp->mf6cc_origin.sin6_addr) &&
842 IN6_ARE_ADDR_EQUAL(&rt->mf6c_mcastgrp.sin6_addr,
843 &mfccp->mf6cc_mcastgrp.sin6_addr) &&
844 (rt->mf6c_stall != NULL)) {
845
846 if (nstl++)
847 log(LOG_ERR,
848 "add_m6fc: %s o %s g %s p %x dbx %p\n",
849 "multiple kernel entries",
850 ip6_sprintf(ip6bufo,
851 &mfccp->mf6cc_origin.sin6_addr),
852 ip6_sprintf(ip6bufg,
853 &mfccp->mf6cc_mcastgrp.sin6_addr),
854 mfccp->mf6cc_parent, rt->mf6c_stall);
855
856#ifdef MRT6DEBUG
857 if (V_mrt6debug & DEBUG_MFC)
858 log(LOG_DEBUG,
859 "add_m6fc o %s g %s p %x dbg %x\n",
860 ip6_sprintf(ip6bufo,
861 &mfccp->mf6cc_origin.sin6_addr),
862 ip6_sprintf(ip6bufg,
863 &mfccp->mf6cc_mcastgrp.sin6_addr),
864 mfccp->mf6cc_parent, rt->mf6c_stall);
865#endif
866
867 rt->mf6c_origin = mfccp->mf6cc_origin;
868 rt->mf6c_mcastgrp = mfccp->mf6cc_mcastgrp;
869 rt->mf6c_parent = mfccp->mf6cc_parent;
870 rt->mf6c_ifset = mfccp->mf6cc_ifset;
871 /* initialize pkt counters per src-grp */
872 rt->mf6c_pkt_cnt = 0;
873 rt->mf6c_byte_cnt = 0;
874 rt->mf6c_wrong_if = 0;
875
876 rt->mf6c_expire = 0; /* Don't clean this guy up */
877 n6expire[hash]--;
878
879 /* free packets Qed at the end of this entry */
880 for (rte = rt->mf6c_stall; rte != NULL; ) {
881 struct rtdetq *n = rte->next;
882 ip6_mdq(rte->m, rte->ifp, rt);
883 m_freem(rte->m);
884#ifdef UPCALL_TIMING
885 collate(&(rte->t));
886#endif /* UPCALL_TIMING */
887 free(rte, M_MRTABLE6);
888 rte = n;
889 }
890 rt->mf6c_stall = NULL;
891 }
892 }
893
894 /*
895 * It is possible that an entry is being inserted without an upcall
896 */
897 if (nstl == 0) {
898#ifdef MRT6DEBUG
899 if (V_mrt6debug & DEBUG_MFC)
900 log(LOG_DEBUG,
901 "add_mfc no upcall h %d o %s g %s p %x\n",
902 hash,
903 ip6_sprintf(ip6bufo, &mfccp->mf6cc_origin.sin6_addr),
904 ip6_sprintf(ip6bufg, &mfccp->mf6cc_mcastgrp.sin6_addr),
905 mfccp->mf6cc_parent);
906#endif
907
908 for (rt = mf6ctable[hash]; rt; rt = rt->mf6c_next) {
909
910 if (IN6_ARE_ADDR_EQUAL(&rt->mf6c_origin.sin6_addr,
911 &mfccp->mf6cc_origin.sin6_addr)&&
912 IN6_ARE_ADDR_EQUAL(&rt->mf6c_mcastgrp.sin6_addr,
913 &mfccp->mf6cc_mcastgrp.sin6_addr)) {
914
915 rt->mf6c_origin = mfccp->mf6cc_origin;
916 rt->mf6c_mcastgrp = mfccp->mf6cc_mcastgrp;
917 rt->mf6c_parent = mfccp->mf6cc_parent;
918 rt->mf6c_ifset = mfccp->mf6cc_ifset;
919 /* initialize pkt counters per src-grp */
920 rt->mf6c_pkt_cnt = 0;
921 rt->mf6c_byte_cnt = 0;
922 rt->mf6c_wrong_if = 0;
923
924 if (rt->mf6c_expire)
925 n6expire[hash]--;
926 rt->mf6c_expire = 0;
927 }
928 }
929 if (rt == NULL) {
930 /* no upcall, so make a new entry */
931 rt = (struct mf6c *)malloc(sizeof(*rt), M_MRTABLE6,
932 M_NOWAIT);
933 if (rt == NULL) {
934 MFC6_UNLOCK();
935 return (ENOBUFS);
936 }
937
938 /* insert new entry at head of hash chain */
939 rt->mf6c_origin = mfccp->mf6cc_origin;
940 rt->mf6c_mcastgrp = mfccp->mf6cc_mcastgrp;
941 rt->mf6c_parent = mfccp->mf6cc_parent;
942 rt->mf6c_ifset = mfccp->mf6cc_ifset;
943 /* initialize pkt counters per src-grp */
944 rt->mf6c_pkt_cnt = 0;
945 rt->mf6c_byte_cnt = 0;
946 rt->mf6c_wrong_if = 0;
947 rt->mf6c_expire = 0;
948 rt->mf6c_stall = NULL;
949
950 /* link into table */
951 rt->mf6c_next = mf6ctable[hash];
952 mf6ctable[hash] = rt;
953 }
954 }
955
956 MFC6_UNLOCK();
957 return (0);
958}
959
960#ifdef UPCALL_TIMING
961/*
962 * collect delay statistics on the upcalls
963 */
964static void
965collate(struct timeval *t)
966{
967 u_long d;
968 struct timeval tp;
969 u_long delta;
970
971 GET_TIME(tp);
972
973 if (TV_LT(*t, tp))
974 {
975 TV_DELTA(tp, *t, delta);
976
977 d = delta >> 10;
978 if (d > UPCALL_MAX)
979 d = UPCALL_MAX;
980
981 ++upcall_data[d];
982 }
983}
984#endif /* UPCALL_TIMING */
985
986/*
987 * Delete an mfc entry
988 */
989static int
990del_m6fc(struct mf6cctl *mfccp)
991{
992 struct sockaddr_in6 origin;
993 struct sockaddr_in6 mcastgrp;
994 struct mf6c *rt;
995 struct mf6c **nptr;
996 u_long hash;
997
998 origin = mfccp->mf6cc_origin;
999 mcastgrp = mfccp->mf6cc_mcastgrp;
1000 hash = MF6CHASH(origin.sin6_addr, mcastgrp.sin6_addr);
1001
1002#ifdef MRT6DEBUG
1003 if (V_mrt6debug & DEBUG_MFC) {
1004 char ip6bufo[INET6_ADDRSTRLEN], ip6bufg[INET6_ADDRSTRLEN];
1005 log(LOG_DEBUG,"del_m6fc orig %s mcastgrp %s\n",
1006 ip6_sprintf(ip6bufo, &origin.sin6_addr),
1007 ip6_sprintf(ip6bufg, &mcastgrp.sin6_addr));
1008 }
1009#endif
1010
1011 MFC6_LOCK();
1012
1013 nptr = &mf6ctable[hash];
1014 while ((rt = *nptr) != NULL) {
1015 if (IN6_ARE_ADDR_EQUAL(&origin.sin6_addr,
1016 &rt->mf6c_origin.sin6_addr) &&
1017 IN6_ARE_ADDR_EQUAL(&mcastgrp.sin6_addr,
1018 &rt->mf6c_mcastgrp.sin6_addr) &&
1019 rt->mf6c_stall == NULL)
1020 break;
1021
1022 nptr = &rt->mf6c_next;
1023 }
1024 if (rt == NULL) {
1025 MFC6_UNLOCK();
1026 return (EADDRNOTAVAIL);
1027 }
1028
1029 *nptr = rt->mf6c_next;
1030 free(rt, M_MRTABLE6);
1031
1032 MFC6_UNLOCK();
1033
1034 return (0);
1035}
1036
1037static int
1038socket_send(struct socket *s, struct mbuf *mm, struct sockaddr_in6 *src)
1039{
1040
1041 if (s) {
1042 if (sbappendaddr(&s->so_rcv,
1043 (struct sockaddr *)src,
1044 mm, (struct mbuf *)0) != 0) {
1045 sorwakeup(s);
1046 return (0);
1047 }
1048 }
1049 m_freem(mm);
1050 return (-1);
1051}
1052
1053/*
1054 * IPv6 multicast forwarding function. This function assumes that the packet
1055 * pointed to by "ip6" has arrived on (or is about to be sent to) the interface
1056 * pointed to by "ifp", and the packet is to be relayed to other networks
1057 * that have members of the packet's destination IPv6 multicast group.
1058 *
1059 * The packet is returned unscathed to the caller, unless it is
1060 * erroneous, in which case a non-zero return value tells the caller to
1061 * discard it.
1062 *
1063 * NOTE: this implementation assumes that m->m_pkthdr.rcvif is NULL iff
1064 * this function is called in the originating context (i.e., not when
1065 * forwarding a packet from other node). ip6_output(), which is currently the
1066 * only function that calls this function is called in the originating context,
1067 * explicitly ensures this condition. It is caller's responsibility to ensure
1068 * that if this function is called from somewhere else in the originating
1069 * context in the future.
1070 */
1071int
1072X_ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m)
1073{
1074 struct mf6c *rt;
1075 struct mif6 *mifp;
1076 struct mbuf *mm;
1077 mifi_t mifi;
1078 char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
1079
1080#ifdef MRT6DEBUG
1081 if (V_mrt6debug & DEBUG_FORWARD)
1082 log(LOG_DEBUG, "ip6_mforward: src %s, dst %s, ifindex %d\n",
1083 ip6_sprintf(ip6bufs, &ip6->ip6_src),
1084 ip6_sprintf(ip6bufd, &ip6->ip6_dst),
1085 ifp->if_index);
1086#endif
1087
1088 /*
1089 * Don't forward a packet with Hop limit of zero or one,
1090 * or a packet destined to a local-only group.
1091 */
1092 if (ip6->ip6_hlim <= 1 || IN6_IS_ADDR_MC_INTFACELOCAL(&ip6->ip6_dst) ||
1093 IN6_IS_ADDR_MC_LINKLOCAL(&ip6->ip6_dst))
1094 return (0);
1095 ip6->ip6_hlim--;
1096
1097 /*
1098 * Source address check: do not forward packets with unspecified
1099 * source. It was discussed in July 2000, on ipngwg mailing list.
1100 * This is rather more serious than unicast cases, because some
1101 * MLD packets can be sent with the unspecified source address
1102 * (although such packets must normally set 1 to the hop limit field).
1103 */
1104 if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) {
1105 IP6STAT_INC(ip6s_cantforward);
1106 if (V_ip6_log_time + V_ip6_log_interval < time_uptime) {
1107 V_ip6_log_time = time_uptime;
1108 log(LOG_DEBUG,
1109 "cannot forward "
1110 "from %s to %s nxt %d received on %s\n",
1111 ip6_sprintf(ip6bufs, &ip6->ip6_src),
1112 ip6_sprintf(ip6bufd, &ip6->ip6_dst),
1113 ip6->ip6_nxt,
1114 if_name(m->m_pkthdr.rcvif));
1115 }
1116 return (0);
1117 }
1118
1119 MFC6_LOCK();
1120
1121 /*
1122 * Determine forwarding mifs from the forwarding cache table
1123 */
1124 MF6CFIND(ip6->ip6_src, ip6->ip6_dst, rt);
1125
1126 /* Entry exists, so forward if necessary */
1127 if (rt) {
1128 MFC6_UNLOCK();
1129 return (ip6_mdq(m, ifp, rt));
1130 } else {
1131 /*
1132 * If we don't have a route for packet's origin,
1133 * Make a copy of the packet &
1134 * send message to routing daemon
1135 */
1136
1137 struct mbuf *mb0;
1138 struct rtdetq *rte;
1139 u_long hash;
1140/* int i, npkts;*/
1141#ifdef UPCALL_TIMING
1142 struct timeval tp;
1143
1144 GET_TIME(tp);
1145#endif /* UPCALL_TIMING */
1146
1147 MRT6STAT_INC(mrt6s_no_route);
1148#ifdef MRT6DEBUG
1149 if (V_mrt6debug & (DEBUG_FORWARD | DEBUG_MFC))
1150 log(LOG_DEBUG, "ip6_mforward: no rte s %s g %s\n",
1151 ip6_sprintf(ip6bufs, &ip6->ip6_src),
1152 ip6_sprintf(ip6bufd, &ip6->ip6_dst));
1153#endif
1154
1155 /*
1156 * Allocate mbufs early so that we don't do extra work if we
1157 * are just going to fail anyway.
1158 */
1159 rte = (struct rtdetq *)malloc(sizeof(*rte), M_MRTABLE6,
1160 M_NOWAIT);
1161 if (rte == NULL) {
1162 MFC6_UNLOCK();
1163 return (ENOBUFS);
1164 }
1165 mb0 = m_copy(m, 0, M_COPYALL);
1166 /*
1167 * Pullup packet header if needed before storing it,
1168 * as other references may modify it in the meantime.
1169 */
1170 if (mb0 &&
1171 (M_HASCL(mb0) || mb0->m_len < sizeof(struct ip6_hdr)))
1172 mb0 = m_pullup(mb0, sizeof(struct ip6_hdr));
1173 if (mb0 == NULL) {
1174 free(rte, M_MRTABLE6);
1175 MFC6_UNLOCK();
1176 return (ENOBUFS);
1177 }
1178
1179 /* is there an upcall waiting for this packet? */
1180 hash = MF6CHASH(ip6->ip6_src, ip6->ip6_dst);
1181 for (rt = mf6ctable[hash]; rt; rt = rt->mf6c_next) {
1182 if (IN6_ARE_ADDR_EQUAL(&ip6->ip6_src,
1183 &rt->mf6c_origin.sin6_addr) &&
1184 IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
1185 &rt->mf6c_mcastgrp.sin6_addr) &&
1186 (rt->mf6c_stall != NULL))
1187 break;
1188 }
1189
1190 if (rt == NULL) {
1191 struct mrt6msg *im;
1192#ifdef MRT6_OINIT
1193 struct omrt6msg *oim;
1194#endif
1195
1196 /* no upcall, so make a new entry */
1197 rt = (struct mf6c *)malloc(sizeof(*rt), M_MRTABLE6,
1198 M_NOWAIT);
1199 if (rt == NULL) {
1200 free(rte, M_MRTABLE6);
1201 m_freem(mb0);
1202 MFC6_UNLOCK();
1203 return (ENOBUFS);
1204 }
1205 /*
1206 * Make a copy of the header to send to the user
1207 * level process
1208 */
1209 mm = m_copy(mb0, 0, sizeof(struct ip6_hdr));
1210
1211 if (mm == NULL) {
1212 free(rte, M_MRTABLE6);
1213 m_freem(mb0);
1214 free(rt, M_MRTABLE6);
1215 MFC6_UNLOCK();
1216 return (ENOBUFS);
1217 }
1218
1219 /*
1220 * Send message to routing daemon
1221 */
1222 sin6.sin6_addr = ip6->ip6_src;
1223
1224 im = NULL;
1225#ifdef MRT6_OINIT
1226 oim = NULL;
1227#endif
1228 switch (V_ip6_mrouter_ver) {
1229#ifdef MRT6_OINIT
1230 case MRT6_OINIT:
1231 oim = mtod(mm, struct omrt6msg *);
1232 oim->im6_msgtype = MRT6MSG_NOCACHE;
1233 oim->im6_mbz = 0;
1234 break;
1235#endif
1236 case MRT6_INIT:
1237 im = mtod(mm, struct mrt6msg *);
1238 im->im6_msgtype = MRT6MSG_NOCACHE;
1239 im->im6_mbz = 0;
1240 break;
1241 default:
1242 free(rte, M_MRTABLE6);
1243 m_freem(mb0);
1244 free(rt, M_MRTABLE6);
1245 MFC6_UNLOCK();
1246 return (EINVAL);
1247 }
1248
1249#ifdef MRT6DEBUG
1250 if (V_mrt6debug & DEBUG_FORWARD)
1251 log(LOG_DEBUG,
1252 "getting the iif info in the kernel\n");
1253#endif
1254
1255 for (mifp = mif6table, mifi = 0;
1256 mifi < nummifs && mifp->m6_ifp != ifp;
1257 mifp++, mifi++)
1258 ;
1259
1260 switch (V_ip6_mrouter_ver) {
1261#ifdef MRT6_OINIT
1262 case MRT6_OINIT:
1263 oim->im6_mif = mifi;
1264 break;
1265#endif
1266 case MRT6_INIT:
1267 im->im6_mif = mifi;
1268 break;
1269 }
1270
1271 if (socket_send(V_ip6_mrouter, mm, &sin6) < 0) {
1272 log(LOG_WARNING, "ip6_mforward: ip6_mrouter "
1273 "socket queue full\n");
1274 MRT6STAT_INC(mrt6s_upq_sockfull);
1275 free(rte, M_MRTABLE6);
1276 m_freem(mb0);
1277 free(rt, M_MRTABLE6);
1278 MFC6_UNLOCK();
1279 return (ENOBUFS);
1280 }
1281
1282 MRT6STAT_INC(mrt6s_upcalls);
1283
1284 /* insert new entry at head of hash chain */
1285 bzero(rt, sizeof(*rt));
1286 rt->mf6c_origin.sin6_family = AF_INET6;
1287 rt->mf6c_origin.sin6_len = sizeof(struct sockaddr_in6);
1288 rt->mf6c_origin.sin6_addr = ip6->ip6_src;
1289 rt->mf6c_mcastgrp.sin6_family = AF_INET6;
1290 rt->mf6c_mcastgrp.sin6_len = sizeof(struct sockaddr_in6);
1291 rt->mf6c_mcastgrp.sin6_addr = ip6->ip6_dst;
1292 rt->mf6c_expire = UPCALL_EXPIRE;
1293 n6expire[hash]++;
1294 rt->mf6c_parent = MF6C_INCOMPLETE_PARENT;
1295
1296 /* link into table */
1297 rt->mf6c_next = mf6ctable[hash];
1298 mf6ctable[hash] = rt;
1299 /* Add this entry to the end of the queue */
1300 rt->mf6c_stall = rte;
1301 } else {
1302 /* determine if q has overflowed */
1303 struct rtdetq **p;
1304 int npkts = 0;
1305
1306 for (p = &rt->mf6c_stall; *p != NULL; p = &(*p)->next)
1307 if (++npkts > MAX_UPQ6) {
1308 MRT6STAT_INC(mrt6s_upq_ovflw);
1309 free(rte, M_MRTABLE6);
1310 m_freem(mb0);
1311 MFC6_UNLOCK();
1312 return (0);
1313 }
1314
1315 /* Add this entry to the end of the queue */
1316 *p = rte;
1317 }
1318
1319 rte->next = NULL;
1320 rte->m = mb0;
1321 rte->ifp = ifp;
1322#ifdef UPCALL_TIMING
1323 rte->t = tp;
1324#endif /* UPCALL_TIMING */
1325
1326 MFC6_UNLOCK();
1327
1328 return (0);
1329 }
1330}
1331
1332/*
1333 * Clean up cache entries if upcalls are not serviced
1334 * Call from the Slow Timeout mechanism, every half second.
1335 */
1336static void
1337expire_upcalls(void *unused)
1338{
1339 struct rtdetq *rte;
1340 struct mf6c *mfc, **nptr;
1341 int i;
1342
1343 MFC6_LOCK();
1344 for (i = 0; i < MF6CTBLSIZ; i++) {
1345 if (n6expire[i] == 0)
1346 continue;
1347 nptr = &mf6ctable[i];
1348 while ((mfc = *nptr) != NULL) {
1349 rte = mfc->mf6c_stall;
1350 /*
1351 * Skip real cache entries
1352 * Make sure it wasn't marked to not expire (shouldn't happen)
1353 * If it expires now
1354 */
1355 if (rte != NULL &&
1356 mfc->mf6c_expire != 0 &&
1357 --mfc->mf6c_expire == 0) {
1358#ifdef MRT6DEBUG
1359 if (V_mrt6debug & DEBUG_EXPIRE) {
1360 char ip6bufo[INET6_ADDRSTRLEN];
1361 char ip6bufg[INET6_ADDRSTRLEN];
1362 log(LOG_DEBUG, "expire_upcalls: expiring (%s %s)\n",
1363 ip6_sprintf(ip6bufo, &mfc->mf6c_origin.sin6_addr),
1364 ip6_sprintf(ip6bufg, &mfc->mf6c_mcastgrp.sin6_addr));
1365 }
1366#endif
1367 /*
1368 * drop all the packets
1369 * free the mbuf with the pkt, if, timing info
1370 */
1371 do {
1372 struct rtdetq *n = rte->next;
1373 m_freem(rte->m);
1374 free(rte, M_MRTABLE6);
1375 rte = n;
1376 } while (rte != NULL);
1377 MRT6STAT_INC(mrt6s_cache_cleanups);
1378 n6expire[i]--;
1379
1380 *nptr = mfc->mf6c_next;
1381 free(mfc, M_MRTABLE6);
1382 } else {
1383 nptr = &mfc->mf6c_next;
1384 }
1385 }
1386 }
1387 MFC6_UNLOCK();
1388 callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT,
1389 expire_upcalls, NULL);
1390}
1391
1392/*
1393 * Packet forwarding routine once entry in the cache is made
1394 */
1395static int
1396ip6_mdq(struct mbuf *m, struct ifnet *ifp, struct mf6c *rt)
1397{
1398 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1399 mifi_t mifi, iif;
1400 struct mif6 *mifp;
1401 int plen = m->m_pkthdr.len;
1402 struct in6_addr src0, dst0; /* copies for local work */
1403 u_int32_t iszone, idzone, oszone, odzone;
1404 int error = 0;
1405
1406/*
1407 * Macro to send packet on mif. Since RSVP packets don't get counted on
1408 * input, they shouldn't get counted on output, so statistics keeping is
1409 * separate.
1410 */
1411
1412#define MC6_SEND(ip6, mifp, m) do { \
1413 if ((mifp)->m6_flags & MIFF_REGISTER) \
1414 register_send((ip6), (mifp), (m)); \
1415 else \
1416 phyint_send((ip6), (mifp), (m)); \
1417} while (/*CONSTCOND*/ 0)
1418
1419 /*
1420 * Don't forward if it didn't arrive from the parent mif
1421 * for its origin.
1422 */
1423 mifi = rt->mf6c_parent;
1424 if ((mifi >= nummifs) || (mif6table[mifi].m6_ifp != ifp)) {
1425 /* came in the wrong interface */
1426#ifdef MRT6DEBUG
1427 if (V_mrt6debug & DEBUG_FORWARD)
1428 log(LOG_DEBUG,
1429 "wrong if: ifid %d mifi %d mififid %x\n",
1430 ifp->if_index, mifi,
1431 mif6table[mifi].m6_ifp->if_index);
1432#endif
1433 MRT6STAT_INC(mrt6s_wrong_if);
1434 rt->mf6c_wrong_if++;
1435 /*
1436 * If we are doing PIM processing, and we are forwarding
1437 * packets on this interface, send a message to the
1438 * routing daemon.
1439 */
1440 /* have to make sure this is a valid mif */
1441 if (mifi < nummifs && mif6table[mifi].m6_ifp)
1442 if (V_pim6 && (m->m_flags & M_LOOP) == 0) {
1443 /*
1444 * Check the M_LOOP flag to avoid an
1445 * unnecessary PIM assert.
1446 * XXX: M_LOOP is an ad-hoc hack...
1447 */
1448 static struct sockaddr_in6 sin6 =
1449 { sizeof(sin6), AF_INET6 };
1450
1451 struct mbuf *mm;
1452 struct mrt6msg *im;
1453#ifdef MRT6_OINIT
1454 struct omrt6msg *oim;
1455#endif
1456
1457 mm = m_copy(m, 0, sizeof(struct ip6_hdr));
1458 if (mm &&
1459 (M_HASCL(mm) ||
1460 mm->m_len < sizeof(struct ip6_hdr)))
1461 mm = m_pullup(mm, sizeof(struct ip6_hdr));
1462 if (mm == NULL)
1463 return (ENOBUFS);
1464
1465#ifdef MRT6_OINIT
1466 oim = NULL;
1467#endif
1468 im = NULL;
1469 switch (V_ip6_mrouter_ver) {
1470#ifdef MRT6_OINIT
1471 case MRT6_OINIT:
1472 oim = mtod(mm, struct omrt6msg *);
1473 oim->im6_msgtype = MRT6MSG_WRONGMIF;
1474 oim->im6_mbz = 0;
1475 break;
1476#endif
1477 case MRT6_INIT:
1478 im = mtod(mm, struct mrt6msg *);
1479 im->im6_msgtype = MRT6MSG_WRONGMIF;
1480 im->im6_mbz = 0;
1481 break;
1482 default:
1483 m_freem(mm);
1484 return (EINVAL);
1485 }
1486
1487 for (mifp = mif6table, iif = 0;
1488 iif < nummifs && mifp &&
1489 mifp->m6_ifp != ifp;
1490 mifp++, iif++)
1491 ;
1492
1493 switch (V_ip6_mrouter_ver) {
1494#ifdef MRT6_OINIT
1495 case MRT6_OINIT:
1496 oim->im6_mif = iif;
1497 sin6.sin6_addr = oim->im6_src;
1498 break;
1499#endif
1500 case MRT6_INIT:
1501 im->im6_mif = iif;
1502 sin6.sin6_addr = im->im6_src;
1503 break;
1504 }
1505
1506 MRT6STAT_INC(mrt6s_upcalls);
1507
1508 if (socket_send(V_ip6_mrouter, mm, &sin6) < 0) {
1509#ifdef MRT6DEBUG
1510 if (V_mrt6debug)
1511 log(LOG_WARNING, "mdq, ip6_mrouter socket queue full\n");
1512#endif
1513 MRT6STAT_INC(mrt6s_upq_sockfull);
1514 return (ENOBUFS);
1515 } /* if socket Q full */
1516 } /* if PIM */
1517 return (0);
1518 } /* if wrong iif */
1519
1520 /* If I sourced this packet, it counts as output, else it was input. */
1521 if (m->m_pkthdr.rcvif == NULL) {
1522 /* XXX: is rcvif really NULL when output?? */
1523 mif6table[mifi].m6_pkt_out++;
1524 mif6table[mifi].m6_bytes_out += plen;
1525 } else {
1526 mif6table[mifi].m6_pkt_in++;
1527 mif6table[mifi].m6_bytes_in += plen;
1528 }
1529 rt->mf6c_pkt_cnt++;
1530 rt->mf6c_byte_cnt += plen;
1531
1532 /*
1533 * For each mif, forward a copy of the packet if there are group
1534 * members downstream on the interface.
1535 */
1536 src0 = ip6->ip6_src;
1537 dst0 = ip6->ip6_dst;
1538 if ((error = in6_setscope(&src0, ifp, &iszone)) != 0 ||
1539 (error = in6_setscope(&dst0, ifp, &idzone)) != 0) {
1540 IP6STAT_INC(ip6s_badscope);
1541 return (error);
1542 }
1543 for (mifp = mif6table, mifi = 0; mifi < nummifs; mifp++, mifi++) {
1544 if (IF_ISSET(mifi, &rt->mf6c_ifset)) {
1545 /*
1546 * check if the outgoing packet is going to break
1547 * a scope boundary.
1548 * XXX For packets through PIM register tunnel
1549 * interface, we believe a routing daemon.
1550 */
1551 if (!(mif6table[rt->mf6c_parent].m6_flags &
1552 MIFF_REGISTER) &&
1553 !(mif6table[mifi].m6_flags & MIFF_REGISTER)) {
1554 if (in6_setscope(&src0, mif6table[mifi].m6_ifp,
1555 &oszone) ||
1556 in6_setscope(&dst0, mif6table[mifi].m6_ifp,
1557 &odzone) ||
1558 iszone != oszone ||
1559 idzone != odzone) {
1560 IP6STAT_INC(ip6s_badscope);
1561 continue;
1562 }
1563 }
1564
1565 mifp->m6_pkt_out++;
1566 mifp->m6_bytes_out += plen;
1567 MC6_SEND(ip6, mifp, m);
1568 }
1569 }
1570 return (0);
1571}
1572
1573static void
1574phyint_send(struct ip6_hdr *ip6, struct mif6 *mifp, struct mbuf *m)
1575{
1576 struct mbuf *mb_copy;
1577 struct ifnet *ifp = mifp->m6_ifp;
1578 int error = 0;
1579 u_long linkmtu;
1580
1581 /*
1582 * Make a new reference to the packet; make sure that
1583 * the IPv6 header is actually copied, not just referenced,
1584 * so that ip6_output() only scribbles on the copy.
1585 */
1586 mb_copy = m_copy(m, 0, M_COPYALL);
1587 if (mb_copy &&
1588 (M_HASCL(mb_copy) || mb_copy->m_len < sizeof(struct ip6_hdr)))
1589 mb_copy = m_pullup(mb_copy, sizeof(struct ip6_hdr));
1590 if (mb_copy == NULL) {
1591 return;
1592 }
1593 /* set MCAST flag to the outgoing packet */
1594 mb_copy->m_flags |= M_MCAST;
1595
1596 /*
1597 * If we sourced the packet, call ip6_output since we may devide
1598 * the packet into fragments when the packet is too big for the
1599 * outgoing interface.
1600 * Otherwise, we can simply send the packet to the interface
1601 * sending queue.
1602 */
1603 if (m->m_pkthdr.rcvif == NULL) {
1604 struct ip6_moptions im6o;
1605
1606 im6o.im6o_multicast_ifp = ifp;
1607 /* XXX: ip6_output will override ip6->ip6_hlim */
1608 im6o.im6o_multicast_hlim = ip6->ip6_hlim;
1609 im6o.im6o_multicast_loop = 1;
1610 error = ip6_output(mb_copy, NULL, NULL, IPV6_FORWARDING, &im6o,
1611 NULL, NULL);
1612
1613#ifdef MRT6DEBUG
1614 if (V_mrt6debug & DEBUG_XMIT)
1615 log(LOG_DEBUG, "phyint_send on mif %d err %d\n",
1616 mifp - mif6table, error);
1617#endif
1618 return;
1619 }
1620
1621 /*
1622 * If configured to loop back multicasts by default,
1623 * loop back a copy now.
1624 */
1625 if (in6_mcast_loop) {
1626 struct sockaddr_in6 dst6;
1627
1628 bzero(&dst6, sizeof(dst6));
1629 dst6.sin6_len = sizeof(struct sockaddr_in6);
1630 dst6.sin6_family = AF_INET6;
1631 dst6.sin6_addr = ip6->ip6_dst;
1632 ip6_mloopback(ifp, m, &dst6);
1633 }
1634
1635 /*
1636 * Put the packet into the sending queue of the outgoing interface
1637 * if it would fit in the MTU of the interface.
1638 */
1639 linkmtu = IN6_LINKMTU(ifp);
1640 if (mb_copy->m_pkthdr.len <= linkmtu || linkmtu < IPV6_MMTU) {
1641 struct sockaddr_in6 dst6;
1642
1643 bzero(&dst6, sizeof(dst6));
1644 dst6.sin6_len = sizeof(struct sockaddr_in6);
1645 dst6.sin6_family = AF_INET6;
1646 dst6.sin6_addr = ip6->ip6_dst;
120#include <netinet6/ip6_var.h>
121#include <netinet6/scope6_var.h>
122#include <netinet6/nd6.h>
123#include <netinet6/ip6_mroute.h>
124#include <netinet6/ip6protosw.h>
125#include <netinet6/pim6.h>
126#include <netinet6/pim6_var.h>
127
128static MALLOC_DEFINE(M_MRTABLE6, "mf6c", "multicast forwarding cache entry");
129
130/* XXX: this is a very common idiom; move to <sys/mbuf.h> ? */
131#define M_HASCL(m) ((m)->m_flags & M_EXT)
132
133static int ip6_mdq(struct mbuf *, struct ifnet *, struct mf6c *);
134static void phyint_send(struct ip6_hdr *, struct mif6 *, struct mbuf *);
135static int register_send(struct ip6_hdr *, struct mif6 *, struct mbuf *);
136static int set_pim6(int *);
137static int socket_send(struct socket *, struct mbuf *,
138 struct sockaddr_in6 *);
139
140extern int in6_mcast_loop;
141extern struct domain inet6domain;
142
143static const struct encaptab *pim6_encap_cookie;
144static const struct ip6protosw in6_pim_protosw = {
145 .pr_type = SOCK_RAW,
146 .pr_domain = &inet6domain,
147 .pr_protocol = IPPROTO_PIM,
148 .pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR,
149 .pr_input = pim6_input,
150 .pr_output = rip6_output,
151 .pr_ctloutput = rip6_ctloutput,
152 .pr_usrreqs = &rip6_usrreqs
153};
154static int pim6_encapcheck(const struct mbuf *, int, int, void *);
155
156static VNET_DEFINE(int, ip6_mrouter_ver) = 0;
157#define V_ip6_mrouter_ver VNET(ip6_mrouter_ver)
158
159SYSCTL_DECL(_net_inet6);
160SYSCTL_DECL(_net_inet6_ip6);
161static SYSCTL_NODE(_net_inet6, IPPROTO_PIM, pim, CTLFLAG_RW, 0, "PIM");
162
163static struct mrt6stat mrt6stat;
164SYSCTL_STRUCT(_net_inet6_ip6, OID_AUTO, mrt6stat, CTLFLAG_RW,
165 &mrt6stat, mrt6stat,
166 "Multicast Routing Statistics (struct mrt6stat, netinet6/ip6_mroute.h)");
167
168#define MRT6STAT_INC(name) mrt6stat.name += 1
169#define NO_RTE_FOUND 0x1
170#define RTE_FOUND 0x2
171
172static struct mtx mrouter6_mtx;
173#define MROUTER6_LOCK() mtx_lock(&mrouter6_mtx)
174#define MROUTER6_UNLOCK() mtx_unlock(&mrouter6_mtx)
175#define MROUTER6_LOCK_ASSERT() do { \
176 mtx_assert(&mrouter6_mtx, MA_OWNED); \
177 NET_ASSERT_GIANT(); \
178} while (0)
179#define MROUTER6_LOCK_INIT() \
180 mtx_init(&mrouter6_mtx, "IPv6 multicast forwarding", NULL, MTX_DEF)
181#define MROUTER6_LOCK_DESTROY() mtx_destroy(&mrouter6_mtx)
182
183static struct mf6c *mf6ctable[MF6CTBLSIZ];
184SYSCTL_OPAQUE(_net_inet6_ip6, OID_AUTO, mf6ctable, CTLFLAG_RD,
185 &mf6ctable, sizeof(mf6ctable), "S,*mf6ctable[MF6CTBLSIZ]",
186 "IPv6 Multicast Forwarding Table (struct *mf6ctable[MF6CTBLSIZ], "
187 "netinet6/ip6_mroute.h)");
188
189static struct mtx mfc6_mtx;
190#define MFC6_LOCK() mtx_lock(&mfc6_mtx)
191#define MFC6_UNLOCK() mtx_unlock(&mfc6_mtx)
192#define MFC6_LOCK_ASSERT() do { \
193 mtx_assert(&mfc6_mtx, MA_OWNED); \
194 NET_ASSERT_GIANT(); \
195} while (0)
196#define MFC6_LOCK_INIT() \
197 mtx_init(&mfc6_mtx, "IPv6 multicast forwarding cache", NULL, MTX_DEF)
198#define MFC6_LOCK_DESTROY() mtx_destroy(&mfc6_mtx)
199
200static u_char n6expire[MF6CTBLSIZ];
201
202static struct mif6 mif6table[MAXMIFS];
203SYSCTL_OPAQUE(_net_inet6_ip6, OID_AUTO, mif6table, CTLFLAG_RD,
204 &mif6table, sizeof(mif6table), "S,mif6[MAXMIFS]",
205 "IPv6 Multicast Interfaces (struct mif6[MAXMIFS], netinet6/ip6_mroute.h)");
206
207static struct mtx mif6_mtx;
208#define MIF6_LOCK() mtx_lock(&mif6_mtx)
209#define MIF6_UNLOCK() mtx_unlock(&mif6_mtx)
210#define MIF6_LOCK_ASSERT() mtx_assert(&mif6_mtx, MA_OWNED)
211#define MIF6_LOCK_INIT() \
212 mtx_init(&mif6_mtx, "IPv6 multicast interfaces", NULL, MTX_DEF)
213#define MIF6_LOCK_DESTROY() mtx_destroy(&mif6_mtx)
214
215#ifdef MRT6DEBUG
216static VNET_DEFINE(u_int, mrt6debug) = 0; /* debug level */
217#define V_mrt6debug VNET(mrt6debug)
218#define DEBUG_MFC 0x02
219#define DEBUG_FORWARD 0x04
220#define DEBUG_EXPIRE 0x08
221#define DEBUG_XMIT 0x10
222#define DEBUG_REG 0x20
223#define DEBUG_PIM 0x40
224#endif
225
226static void expire_upcalls(void *);
227#define EXPIRE_TIMEOUT (hz / 4) /* 4x / second */
228#define UPCALL_EXPIRE 6 /* number of timeouts */
229
230/*
231 * XXX TODO: maintain a count to if_allmulti() calls in struct ifnet.
232 */
233
234/*
235 * 'Interfaces' associated with decapsulator (so we can tell
236 * packets that went through it from ones that get reflected
237 * by a broken gateway). Different from IPv4 register_if,
238 * these interfaces are linked into the system ifnet list,
239 * because per-interface IPv6 statistics are maintained in
240 * ifp->if_afdata. But it does not have any routes point
241 * to them. I.e., packets can't be sent this way. They
242 * only exist as a placeholder for multicast source
243 * verification.
244 */
245static struct ifnet *multicast_register_if6;
246
247#define ENCAP_HOPS 64
248
249/*
250 * Private variables.
251 */
252static mifi_t nummifs = 0;
253static mifi_t reg_mif_num = (mifi_t)-1;
254
255static struct pim6stat pim6stat;
256SYSCTL_STRUCT(_net_inet6_pim, PIM6CTL_STATS, stats, CTLFLAG_RW,
257 &pim6stat, pim6stat,
258 "PIM Statistics (struct pim6stat, netinet6/pim6_var.h)");
259
260#define PIM6STAT_INC(name) pim6stat.name += 1
261static VNET_DEFINE(int, pim6);
262#define V_pim6 VNET(pim6)
263
264/*
265 * Hash function for a source, group entry
266 */
267#define MF6CHASH(a, g) MF6CHASHMOD((a).s6_addr32[0] ^ (a).s6_addr32[1] ^ \
268 (a).s6_addr32[2] ^ (a).s6_addr32[3] ^ \
269 (g).s6_addr32[0] ^ (g).s6_addr32[1] ^ \
270 (g).s6_addr32[2] ^ (g).s6_addr32[3])
271
272/*
273 * Find a route for a given origin IPv6 address and Multicast group address.
274 */
275#define MF6CFIND(o, g, rt) do { \
276 struct mf6c *_rt = mf6ctable[MF6CHASH(o,g)]; \
277 rt = NULL; \
278 MRT6STAT_INC(mrt6s_mfc_lookups); \
279 while (_rt) { \
280 if (IN6_ARE_ADDR_EQUAL(&_rt->mf6c_origin.sin6_addr, &(o)) && \
281 IN6_ARE_ADDR_EQUAL(&_rt->mf6c_mcastgrp.sin6_addr, &(g)) && \
282 (_rt->mf6c_stall == NULL)) { \
283 rt = _rt; \
284 break; \
285 } \
286 _rt = _rt->mf6c_next; \
287 } \
288 if (rt == NULL) { \
289 MRT6STAT_INC(mrt6s_mfc_misses); \
290 } \
291} while (/*CONSTCOND*/ 0)
292
293/*
294 * Macros to compute elapsed time efficiently
295 * Borrowed from Van Jacobson's scheduling code
296 * XXX: replace with timersub() ?
297 */
298#define TV_DELTA(a, b, delta) do { \
299 int xxs; \
300 \
301 delta = (a).tv_usec - (b).tv_usec; \
302 if ((xxs = (a).tv_sec - (b).tv_sec)) { \
303 switch (xxs) { \
304 case 2: \
305 delta += 1000000; \
306 /* FALLTHROUGH */ \
307 case 1: \
308 delta += 1000000; \
309 break; \
310 default: \
311 delta += (1000000 * xxs); \
312 } \
313 } \
314} while (/*CONSTCOND*/ 0)
315
316/* XXX: replace with timercmp(a, b, <) ? */
317#define TV_LT(a, b) (((a).tv_usec < (b).tv_usec && \
318 (a).tv_sec <= (b).tv_sec) || (a).tv_sec < (b).tv_sec)
319
320#ifdef UPCALL_TIMING
321#define UPCALL_MAX 50
322static u_long upcall_data[UPCALL_MAX + 1];
323static void collate();
324#endif /* UPCALL_TIMING */
325
326static int ip6_mrouter_init(struct socket *, int, int);
327static int add_m6fc(struct mf6cctl *);
328static int add_m6if(struct mif6ctl *);
329static int del_m6fc(struct mf6cctl *);
330static int del_m6if(mifi_t *);
331static int del_m6if_locked(mifi_t *);
332static int get_mif6_cnt(struct sioc_mif_req6 *);
333static int get_sg_cnt(struct sioc_sg_req6 *);
334
335static struct callout expire_upcalls_ch;
336
337int X_ip6_mforward(struct ip6_hdr *, struct ifnet *, struct mbuf *);
338int X_ip6_mrouter_done(void);
339int X_ip6_mrouter_set(struct socket *, struct sockopt *);
340int X_ip6_mrouter_get(struct socket *, struct sockopt *);
341int X_mrt6_ioctl(u_long, caddr_t);
342
343/*
344 * Handle MRT setsockopt commands to modify the multicast routing tables.
345 */
346int
347X_ip6_mrouter_set(struct socket *so, struct sockopt *sopt)
348{
349 int error = 0;
350 int optval;
351 struct mif6ctl mifc;
352 struct mf6cctl mfcc;
353 mifi_t mifi;
354
355 if (so != V_ip6_mrouter && sopt->sopt_name != MRT6_INIT)
356 return (EACCES);
357
358 switch (sopt->sopt_name) {
359 case MRT6_INIT:
360#ifdef MRT6_OINIT
361 case MRT6_OINIT:
362#endif
363 error = sooptcopyin(sopt, &optval, sizeof(optval),
364 sizeof(optval));
365 if (error)
366 break;
367 error = ip6_mrouter_init(so, optval, sopt->sopt_name);
368 break;
369 case MRT6_DONE:
370 error = X_ip6_mrouter_done();
371 break;
372 case MRT6_ADD_MIF:
373 error = sooptcopyin(sopt, &mifc, sizeof(mifc), sizeof(mifc));
374 if (error)
375 break;
376 error = add_m6if(&mifc);
377 break;
378 case MRT6_ADD_MFC:
379 error = sooptcopyin(sopt, &mfcc, sizeof(mfcc), sizeof(mfcc));
380 if (error)
381 break;
382 error = add_m6fc(&mfcc);
383 break;
384 case MRT6_DEL_MFC:
385 error = sooptcopyin(sopt, &mfcc, sizeof(mfcc), sizeof(mfcc));
386 if (error)
387 break;
388 error = del_m6fc(&mfcc);
389 break;
390 case MRT6_DEL_MIF:
391 error = sooptcopyin(sopt, &mifi, sizeof(mifi), sizeof(mifi));
392 if (error)
393 break;
394 error = del_m6if(&mifi);
395 break;
396 case MRT6_PIM:
397 error = sooptcopyin(sopt, &optval, sizeof(optval),
398 sizeof(optval));
399 if (error)
400 break;
401 error = set_pim6(&optval);
402 break;
403 default:
404 error = EOPNOTSUPP;
405 break;
406 }
407
408 return (error);
409}
410
411/*
412 * Handle MRT getsockopt commands
413 */
414int
415X_ip6_mrouter_get(struct socket *so, struct sockopt *sopt)
416{
417 int error = 0;
418
419 if (so != V_ip6_mrouter)
420 return (EACCES);
421
422 switch (sopt->sopt_name) {
423 case MRT6_PIM:
424 error = sooptcopyout(sopt, &V_pim6, sizeof(V_pim6));
425 break;
426 }
427 return (error);
428}
429
430/*
431 * Handle ioctl commands to obtain information from the cache
432 */
433int
434X_mrt6_ioctl(u_long cmd, caddr_t data)
435{
436 int ret;
437
438 ret = EINVAL;
439
440 switch (cmd) {
441 case SIOCGETSGCNT_IN6:
442 ret = get_sg_cnt((struct sioc_sg_req6 *)data);
443 break;
444
445 case SIOCGETMIFCNT_IN6:
446 ret = get_mif6_cnt((struct sioc_mif_req6 *)data);
447 break;
448
449 default:
450 break;
451 }
452
453 return (ret);
454}
455
456/*
457 * returns the packet, byte, rpf-failure count for the source group provided
458 */
459static int
460get_sg_cnt(struct sioc_sg_req6 *req)
461{
462 struct mf6c *rt;
463 int ret;
464
465 ret = 0;
466
467 MFC6_LOCK();
468
469 MF6CFIND(req->src.sin6_addr, req->grp.sin6_addr, rt);
470 if (rt == NULL) {
471 ret = ESRCH;
472 } else {
473 req->pktcnt = rt->mf6c_pkt_cnt;
474 req->bytecnt = rt->mf6c_byte_cnt;
475 req->wrong_if = rt->mf6c_wrong_if;
476 }
477
478 MFC6_UNLOCK();
479
480 return (ret);
481}
482
483/*
484 * returns the input and output packet and byte counts on the mif provided
485 */
486static int
487get_mif6_cnt(struct sioc_mif_req6 *req)
488{
489 mifi_t mifi;
490 int ret;
491
492 ret = 0;
493 mifi = req->mifi;
494
495 MIF6_LOCK();
496
497 if (mifi >= nummifs) {
498 ret = EINVAL;
499 } else {
500 req->icount = mif6table[mifi].m6_pkt_in;
501 req->ocount = mif6table[mifi].m6_pkt_out;
502 req->ibytes = mif6table[mifi].m6_bytes_in;
503 req->obytes = mif6table[mifi].m6_bytes_out;
504 }
505
506 MIF6_UNLOCK();
507
508 return (ret);
509}
510
511static int
512set_pim6(int *i)
513{
514 if ((*i != 1) && (*i != 0))
515 return (EINVAL);
516
517 V_pim6 = *i;
518
519 return (0);
520}
521
522/*
523 * Enable multicast routing
524 */
525static int
526ip6_mrouter_init(struct socket *so, int v, int cmd)
527{
528
529#ifdef MRT6DEBUG
530 if (V_mrt6debug)
531 log(LOG_DEBUG,
532 "ip6_mrouter_init: so_type = %d, pr_protocol = %d\n",
533 so->so_type, so->so_proto->pr_protocol);
534#endif
535
536 if (so->so_type != SOCK_RAW ||
537 so->so_proto->pr_protocol != IPPROTO_ICMPV6)
538 return (EOPNOTSUPP);
539
540 if (v != 1)
541 return (ENOPROTOOPT);
542
543 MROUTER6_LOCK();
544
545 if (V_ip6_mrouter != NULL) {
546 MROUTER6_UNLOCK();
547 return (EADDRINUSE);
548 }
549
550 V_ip6_mrouter = so;
551 V_ip6_mrouter_ver = cmd;
552
553 bzero((caddr_t)mf6ctable, sizeof(mf6ctable));
554 bzero((caddr_t)n6expire, sizeof(n6expire));
555
556 V_pim6 = 0;/* used for stubbing out/in pim stuff */
557
558 callout_init(&expire_upcalls_ch, 0);
559 callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT,
560 expire_upcalls, NULL);
561
562 MROUTER6_UNLOCK();
563
564#ifdef MRT6DEBUG
565 if (V_mrt6debug)
566 log(LOG_DEBUG, "ip6_mrouter_init\n");
567#endif
568
569 return (0);
570}
571
572/*
573 * Disable IPv6 multicast forwarding.
574 */
575int
576X_ip6_mrouter_done(void)
577{
578 mifi_t mifi;
579 int i;
580 struct mf6c *rt;
581 struct rtdetq *rte;
582
583 MROUTER6_LOCK();
584
585 if (V_ip6_mrouter == NULL) {
586 MROUTER6_UNLOCK();
587 return (EINVAL);
588 }
589
590 /*
591 * For each phyint in use, disable promiscuous reception of all IPv6
592 * multicasts.
593 */
594 for (mifi = 0; mifi < nummifs; mifi++) {
595 if (mif6table[mifi].m6_ifp &&
596 !(mif6table[mifi].m6_flags & MIFF_REGISTER)) {
597 if_allmulti(mif6table[mifi].m6_ifp, 0);
598 }
599 }
600 bzero((caddr_t)mif6table, sizeof(mif6table));
601 nummifs = 0;
602
603 V_pim6 = 0; /* used to stub out/in pim specific code */
604
605 callout_stop(&expire_upcalls_ch);
606
607 /*
608 * Free all multicast forwarding cache entries.
609 */
610 MFC6_LOCK();
611 for (i = 0; i < MF6CTBLSIZ; i++) {
612 rt = mf6ctable[i];
613 while (rt) {
614 struct mf6c *frt;
615
616 for (rte = rt->mf6c_stall; rte != NULL; ) {
617 struct rtdetq *n = rte->next;
618
619 m_free(rte->m);
620 free(rte, M_MRTABLE6);
621 rte = n;
622 }
623 frt = rt;
624 rt = rt->mf6c_next;
625 free(frt, M_MRTABLE6);
626 }
627 }
628 bzero((caddr_t)mf6ctable, sizeof(mf6ctable));
629 MFC6_UNLOCK();
630
631 /*
632 * Reset register interface
633 */
634 if (reg_mif_num != (mifi_t)-1 && multicast_register_if6 != NULL) {
635 if_detach(multicast_register_if6);
636 if_free(multicast_register_if6);
637 reg_mif_num = (mifi_t)-1;
638 multicast_register_if6 = NULL;
639 }
640
641 V_ip6_mrouter = NULL;
642 V_ip6_mrouter_ver = 0;
643
644 MROUTER6_UNLOCK();
645
646#ifdef MRT6DEBUG
647 if (V_mrt6debug)
648 log(LOG_DEBUG, "ip6_mrouter_done\n");
649#endif
650
651 return (0);
652}
653
654static struct sockaddr_in6 sin6 = { sizeof(sin6), AF_INET6 };
655
656/*
657 * Add a mif to the mif table
658 */
659static int
660add_m6if(struct mif6ctl *mifcp)
661{
662 struct mif6 *mifp;
663 struct ifnet *ifp;
664 int error;
665
666 MIF6_LOCK();
667
668 if (mifcp->mif6c_mifi >= MAXMIFS) {
669 MIF6_UNLOCK();
670 return (EINVAL);
671 }
672 mifp = mif6table + mifcp->mif6c_mifi;
673 if (mifp->m6_ifp != NULL) {
674 MIF6_UNLOCK();
675 return (EADDRINUSE); /* XXX: is it appropriate? */
676 }
677 if (mifcp->mif6c_pifi == 0 || mifcp->mif6c_pifi > V_if_index) {
678 MIF6_UNLOCK();
679 return (ENXIO);
680 }
681
682 ifp = ifnet_byindex(mifcp->mif6c_pifi);
683
684 if (mifcp->mif6c_flags & MIFF_REGISTER) {
685 if (reg_mif_num == (mifi_t)-1) {
686 ifp = if_alloc(IFT_OTHER);
687
688 if_initname(ifp, "register_mif", 0);
689 ifp->if_flags |= IFF_LOOPBACK;
690 if_attach(ifp);
691 multicast_register_if6 = ifp;
692 reg_mif_num = mifcp->mif6c_mifi;
693 /*
694 * it is impossible to guess the ifindex of the
695 * register interface. So mif6c_pifi is automatically
696 * calculated.
697 */
698 mifcp->mif6c_pifi = ifp->if_index;
699 } else {
700 ifp = multicast_register_if6;
701 }
702 } else {
703 /* Make sure the interface supports multicast */
704 if ((ifp->if_flags & IFF_MULTICAST) == 0) {
705 MIF6_UNLOCK();
706 return (EOPNOTSUPP);
707 }
708
709 error = if_allmulti(ifp, 1);
710 if (error) {
711 MIF6_UNLOCK();
712 return (error);
713 }
714 }
715
716 mifp->m6_flags = mifcp->mif6c_flags;
717 mifp->m6_ifp = ifp;
718
719 /* initialize per mif pkt counters */
720 mifp->m6_pkt_in = 0;
721 mifp->m6_pkt_out = 0;
722 mifp->m6_bytes_in = 0;
723 mifp->m6_bytes_out = 0;
724
725 /* Adjust nummifs up if the mifi is higher than nummifs */
726 if (nummifs <= mifcp->mif6c_mifi)
727 nummifs = mifcp->mif6c_mifi + 1;
728
729 MIF6_UNLOCK();
730
731#ifdef MRT6DEBUG
732 if (V_mrt6debug)
733 log(LOG_DEBUG,
734 "add_mif #%d, phyint %s\n",
735 mifcp->mif6c_mifi,
736 ifp->if_xname);
737#endif
738
739 return (0);
740}
741
742/*
743 * Delete a mif from the mif table
744 */
745static int
746del_m6if_locked(mifi_t *mifip)
747{
748 struct mif6 *mifp = mif6table + *mifip;
749 mifi_t mifi;
750 struct ifnet *ifp;
751
752 MIF6_LOCK_ASSERT();
753
754 if (*mifip >= nummifs)
755 return (EINVAL);
756 if (mifp->m6_ifp == NULL)
757 return (EINVAL);
758
759 if (!(mifp->m6_flags & MIFF_REGISTER)) {
760 /* XXX: TODO: Maintain an ALLMULTI refcount in struct ifnet. */
761 ifp = mifp->m6_ifp;
762 if_allmulti(ifp, 0);
763 } else {
764 if (reg_mif_num != (mifi_t)-1 &&
765 multicast_register_if6 != NULL) {
766 if_detach(multicast_register_if6);
767 if_free(multicast_register_if6);
768 reg_mif_num = (mifi_t)-1;
769 multicast_register_if6 = NULL;
770 }
771 }
772
773 bzero((caddr_t)mifp, sizeof(*mifp));
774
775 /* Adjust nummifs down */
776 for (mifi = nummifs; mifi > 0; mifi--)
777 if (mif6table[mifi - 1].m6_ifp)
778 break;
779 nummifs = mifi;
780
781#ifdef MRT6DEBUG
782 if (V_mrt6debug)
783 log(LOG_DEBUG, "del_m6if %d, nummifs %d\n", *mifip, nummifs);
784#endif
785
786 return (0);
787}
788
789static int
790del_m6if(mifi_t *mifip)
791{
792 int cc;
793
794 MIF6_LOCK();
795 cc = del_m6if_locked(mifip);
796 MIF6_UNLOCK();
797
798 return (cc);
799}
800
801/*
802 * Add an mfc entry
803 */
804static int
805add_m6fc(struct mf6cctl *mfccp)
806{
807 struct mf6c *rt;
808 u_long hash;
809 struct rtdetq *rte;
810 u_short nstl;
811 char ip6bufo[INET6_ADDRSTRLEN], ip6bufg[INET6_ADDRSTRLEN];
812
813 MFC6_LOCK();
814
815 MF6CFIND(mfccp->mf6cc_origin.sin6_addr,
816 mfccp->mf6cc_mcastgrp.sin6_addr, rt);
817
818 /* If an entry already exists, just update the fields */
819 if (rt) {
820#ifdef MRT6DEBUG
821 if (V_mrt6debug & DEBUG_MFC) {
822 log(LOG_DEBUG,
823 "add_m6fc no upcall h %d o %s g %s p %x\n",
824 ip6_sprintf(ip6bufo, &mfccp->mf6cc_origin.sin6_addr),
825 ip6_sprintf(ip6bufg, &mfccp->mf6cc_mcastgrp.sin6_addr),
826 mfccp->mf6cc_parent);
827 }
828#endif
829
830 rt->mf6c_parent = mfccp->mf6cc_parent;
831 rt->mf6c_ifset = mfccp->mf6cc_ifset;
832
833 MFC6_UNLOCK();
834 return (0);
835 }
836
837 /*
838 * Find the entry for which the upcall was made and update
839 */
840 hash = MF6CHASH(mfccp->mf6cc_origin.sin6_addr,
841 mfccp->mf6cc_mcastgrp.sin6_addr);
842 for (rt = mf6ctable[hash], nstl = 0; rt; rt = rt->mf6c_next) {
843 if (IN6_ARE_ADDR_EQUAL(&rt->mf6c_origin.sin6_addr,
844 &mfccp->mf6cc_origin.sin6_addr) &&
845 IN6_ARE_ADDR_EQUAL(&rt->mf6c_mcastgrp.sin6_addr,
846 &mfccp->mf6cc_mcastgrp.sin6_addr) &&
847 (rt->mf6c_stall != NULL)) {
848
849 if (nstl++)
850 log(LOG_ERR,
851 "add_m6fc: %s o %s g %s p %x dbx %p\n",
852 "multiple kernel entries",
853 ip6_sprintf(ip6bufo,
854 &mfccp->mf6cc_origin.sin6_addr),
855 ip6_sprintf(ip6bufg,
856 &mfccp->mf6cc_mcastgrp.sin6_addr),
857 mfccp->mf6cc_parent, rt->mf6c_stall);
858
859#ifdef MRT6DEBUG
860 if (V_mrt6debug & DEBUG_MFC)
861 log(LOG_DEBUG,
862 "add_m6fc o %s g %s p %x dbg %x\n",
863 ip6_sprintf(ip6bufo,
864 &mfccp->mf6cc_origin.sin6_addr),
865 ip6_sprintf(ip6bufg,
866 &mfccp->mf6cc_mcastgrp.sin6_addr),
867 mfccp->mf6cc_parent, rt->mf6c_stall);
868#endif
869
870 rt->mf6c_origin = mfccp->mf6cc_origin;
871 rt->mf6c_mcastgrp = mfccp->mf6cc_mcastgrp;
872 rt->mf6c_parent = mfccp->mf6cc_parent;
873 rt->mf6c_ifset = mfccp->mf6cc_ifset;
874 /* initialize pkt counters per src-grp */
875 rt->mf6c_pkt_cnt = 0;
876 rt->mf6c_byte_cnt = 0;
877 rt->mf6c_wrong_if = 0;
878
879 rt->mf6c_expire = 0; /* Don't clean this guy up */
880 n6expire[hash]--;
881
882 /* free packets Qed at the end of this entry */
883 for (rte = rt->mf6c_stall; rte != NULL; ) {
884 struct rtdetq *n = rte->next;
885 ip6_mdq(rte->m, rte->ifp, rt);
886 m_freem(rte->m);
887#ifdef UPCALL_TIMING
888 collate(&(rte->t));
889#endif /* UPCALL_TIMING */
890 free(rte, M_MRTABLE6);
891 rte = n;
892 }
893 rt->mf6c_stall = NULL;
894 }
895 }
896
897 /*
898 * It is possible that an entry is being inserted without an upcall
899 */
900 if (nstl == 0) {
901#ifdef MRT6DEBUG
902 if (V_mrt6debug & DEBUG_MFC)
903 log(LOG_DEBUG,
904 "add_mfc no upcall h %d o %s g %s p %x\n",
905 hash,
906 ip6_sprintf(ip6bufo, &mfccp->mf6cc_origin.sin6_addr),
907 ip6_sprintf(ip6bufg, &mfccp->mf6cc_mcastgrp.sin6_addr),
908 mfccp->mf6cc_parent);
909#endif
910
911 for (rt = mf6ctable[hash]; rt; rt = rt->mf6c_next) {
912
913 if (IN6_ARE_ADDR_EQUAL(&rt->mf6c_origin.sin6_addr,
914 &mfccp->mf6cc_origin.sin6_addr)&&
915 IN6_ARE_ADDR_EQUAL(&rt->mf6c_mcastgrp.sin6_addr,
916 &mfccp->mf6cc_mcastgrp.sin6_addr)) {
917
918 rt->mf6c_origin = mfccp->mf6cc_origin;
919 rt->mf6c_mcastgrp = mfccp->mf6cc_mcastgrp;
920 rt->mf6c_parent = mfccp->mf6cc_parent;
921 rt->mf6c_ifset = mfccp->mf6cc_ifset;
922 /* initialize pkt counters per src-grp */
923 rt->mf6c_pkt_cnt = 0;
924 rt->mf6c_byte_cnt = 0;
925 rt->mf6c_wrong_if = 0;
926
927 if (rt->mf6c_expire)
928 n6expire[hash]--;
929 rt->mf6c_expire = 0;
930 }
931 }
932 if (rt == NULL) {
933 /* no upcall, so make a new entry */
934 rt = (struct mf6c *)malloc(sizeof(*rt), M_MRTABLE6,
935 M_NOWAIT);
936 if (rt == NULL) {
937 MFC6_UNLOCK();
938 return (ENOBUFS);
939 }
940
941 /* insert new entry at head of hash chain */
942 rt->mf6c_origin = mfccp->mf6cc_origin;
943 rt->mf6c_mcastgrp = mfccp->mf6cc_mcastgrp;
944 rt->mf6c_parent = mfccp->mf6cc_parent;
945 rt->mf6c_ifset = mfccp->mf6cc_ifset;
946 /* initialize pkt counters per src-grp */
947 rt->mf6c_pkt_cnt = 0;
948 rt->mf6c_byte_cnt = 0;
949 rt->mf6c_wrong_if = 0;
950 rt->mf6c_expire = 0;
951 rt->mf6c_stall = NULL;
952
953 /* link into table */
954 rt->mf6c_next = mf6ctable[hash];
955 mf6ctable[hash] = rt;
956 }
957 }
958
959 MFC6_UNLOCK();
960 return (0);
961}
962
963#ifdef UPCALL_TIMING
964/*
965 * collect delay statistics on the upcalls
966 */
967static void
968collate(struct timeval *t)
969{
970 u_long d;
971 struct timeval tp;
972 u_long delta;
973
974 GET_TIME(tp);
975
976 if (TV_LT(*t, tp))
977 {
978 TV_DELTA(tp, *t, delta);
979
980 d = delta >> 10;
981 if (d > UPCALL_MAX)
982 d = UPCALL_MAX;
983
984 ++upcall_data[d];
985 }
986}
987#endif /* UPCALL_TIMING */
988
989/*
990 * Delete an mfc entry
991 */
992static int
993del_m6fc(struct mf6cctl *mfccp)
994{
995 struct sockaddr_in6 origin;
996 struct sockaddr_in6 mcastgrp;
997 struct mf6c *rt;
998 struct mf6c **nptr;
999 u_long hash;
1000
1001 origin = mfccp->mf6cc_origin;
1002 mcastgrp = mfccp->mf6cc_mcastgrp;
1003 hash = MF6CHASH(origin.sin6_addr, mcastgrp.sin6_addr);
1004
1005#ifdef MRT6DEBUG
1006 if (V_mrt6debug & DEBUG_MFC) {
1007 char ip6bufo[INET6_ADDRSTRLEN], ip6bufg[INET6_ADDRSTRLEN];
1008 log(LOG_DEBUG,"del_m6fc orig %s mcastgrp %s\n",
1009 ip6_sprintf(ip6bufo, &origin.sin6_addr),
1010 ip6_sprintf(ip6bufg, &mcastgrp.sin6_addr));
1011 }
1012#endif
1013
1014 MFC6_LOCK();
1015
1016 nptr = &mf6ctable[hash];
1017 while ((rt = *nptr) != NULL) {
1018 if (IN6_ARE_ADDR_EQUAL(&origin.sin6_addr,
1019 &rt->mf6c_origin.sin6_addr) &&
1020 IN6_ARE_ADDR_EQUAL(&mcastgrp.sin6_addr,
1021 &rt->mf6c_mcastgrp.sin6_addr) &&
1022 rt->mf6c_stall == NULL)
1023 break;
1024
1025 nptr = &rt->mf6c_next;
1026 }
1027 if (rt == NULL) {
1028 MFC6_UNLOCK();
1029 return (EADDRNOTAVAIL);
1030 }
1031
1032 *nptr = rt->mf6c_next;
1033 free(rt, M_MRTABLE6);
1034
1035 MFC6_UNLOCK();
1036
1037 return (0);
1038}
1039
1040static int
1041socket_send(struct socket *s, struct mbuf *mm, struct sockaddr_in6 *src)
1042{
1043
1044 if (s) {
1045 if (sbappendaddr(&s->so_rcv,
1046 (struct sockaddr *)src,
1047 mm, (struct mbuf *)0) != 0) {
1048 sorwakeup(s);
1049 return (0);
1050 }
1051 }
1052 m_freem(mm);
1053 return (-1);
1054}
1055
1056/*
1057 * IPv6 multicast forwarding function. This function assumes that the packet
1058 * pointed to by "ip6" has arrived on (or is about to be sent to) the interface
1059 * pointed to by "ifp", and the packet is to be relayed to other networks
1060 * that have members of the packet's destination IPv6 multicast group.
1061 *
1062 * The packet is returned unscathed to the caller, unless it is
1063 * erroneous, in which case a non-zero return value tells the caller to
1064 * discard it.
1065 *
1066 * NOTE: this implementation assumes that m->m_pkthdr.rcvif is NULL iff
1067 * this function is called in the originating context (i.e., not when
1068 * forwarding a packet from other node). ip6_output(), which is currently the
1069 * only function that calls this function is called in the originating context,
1070 * explicitly ensures this condition. It is caller's responsibility to ensure
1071 * that if this function is called from somewhere else in the originating
1072 * context in the future.
1073 */
1074int
1075X_ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m)
1076{
1077 struct mf6c *rt;
1078 struct mif6 *mifp;
1079 struct mbuf *mm;
1080 mifi_t mifi;
1081 char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
1082
1083#ifdef MRT6DEBUG
1084 if (V_mrt6debug & DEBUG_FORWARD)
1085 log(LOG_DEBUG, "ip6_mforward: src %s, dst %s, ifindex %d\n",
1086 ip6_sprintf(ip6bufs, &ip6->ip6_src),
1087 ip6_sprintf(ip6bufd, &ip6->ip6_dst),
1088 ifp->if_index);
1089#endif
1090
1091 /*
1092 * Don't forward a packet with Hop limit of zero or one,
1093 * or a packet destined to a local-only group.
1094 */
1095 if (ip6->ip6_hlim <= 1 || IN6_IS_ADDR_MC_INTFACELOCAL(&ip6->ip6_dst) ||
1096 IN6_IS_ADDR_MC_LINKLOCAL(&ip6->ip6_dst))
1097 return (0);
1098 ip6->ip6_hlim--;
1099
1100 /*
1101 * Source address check: do not forward packets with unspecified
1102 * source. It was discussed in July 2000, on ipngwg mailing list.
1103 * This is rather more serious than unicast cases, because some
1104 * MLD packets can be sent with the unspecified source address
1105 * (although such packets must normally set 1 to the hop limit field).
1106 */
1107 if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) {
1108 IP6STAT_INC(ip6s_cantforward);
1109 if (V_ip6_log_time + V_ip6_log_interval < time_uptime) {
1110 V_ip6_log_time = time_uptime;
1111 log(LOG_DEBUG,
1112 "cannot forward "
1113 "from %s to %s nxt %d received on %s\n",
1114 ip6_sprintf(ip6bufs, &ip6->ip6_src),
1115 ip6_sprintf(ip6bufd, &ip6->ip6_dst),
1116 ip6->ip6_nxt,
1117 if_name(m->m_pkthdr.rcvif));
1118 }
1119 return (0);
1120 }
1121
1122 MFC6_LOCK();
1123
1124 /*
1125 * Determine forwarding mifs from the forwarding cache table
1126 */
1127 MF6CFIND(ip6->ip6_src, ip6->ip6_dst, rt);
1128
1129 /* Entry exists, so forward if necessary */
1130 if (rt) {
1131 MFC6_UNLOCK();
1132 return (ip6_mdq(m, ifp, rt));
1133 } else {
1134 /*
1135 * If we don't have a route for packet's origin,
1136 * Make a copy of the packet &
1137 * send message to routing daemon
1138 */
1139
1140 struct mbuf *mb0;
1141 struct rtdetq *rte;
1142 u_long hash;
1143/* int i, npkts;*/
1144#ifdef UPCALL_TIMING
1145 struct timeval tp;
1146
1147 GET_TIME(tp);
1148#endif /* UPCALL_TIMING */
1149
1150 MRT6STAT_INC(mrt6s_no_route);
1151#ifdef MRT6DEBUG
1152 if (V_mrt6debug & (DEBUG_FORWARD | DEBUG_MFC))
1153 log(LOG_DEBUG, "ip6_mforward: no rte s %s g %s\n",
1154 ip6_sprintf(ip6bufs, &ip6->ip6_src),
1155 ip6_sprintf(ip6bufd, &ip6->ip6_dst));
1156#endif
1157
1158 /*
1159 * Allocate mbufs early so that we don't do extra work if we
1160 * are just going to fail anyway.
1161 */
1162 rte = (struct rtdetq *)malloc(sizeof(*rte), M_MRTABLE6,
1163 M_NOWAIT);
1164 if (rte == NULL) {
1165 MFC6_UNLOCK();
1166 return (ENOBUFS);
1167 }
1168 mb0 = m_copy(m, 0, M_COPYALL);
1169 /*
1170 * Pullup packet header if needed before storing it,
1171 * as other references may modify it in the meantime.
1172 */
1173 if (mb0 &&
1174 (M_HASCL(mb0) || mb0->m_len < sizeof(struct ip6_hdr)))
1175 mb0 = m_pullup(mb0, sizeof(struct ip6_hdr));
1176 if (mb0 == NULL) {
1177 free(rte, M_MRTABLE6);
1178 MFC6_UNLOCK();
1179 return (ENOBUFS);
1180 }
1181
1182 /* is there an upcall waiting for this packet? */
1183 hash = MF6CHASH(ip6->ip6_src, ip6->ip6_dst);
1184 for (rt = mf6ctable[hash]; rt; rt = rt->mf6c_next) {
1185 if (IN6_ARE_ADDR_EQUAL(&ip6->ip6_src,
1186 &rt->mf6c_origin.sin6_addr) &&
1187 IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
1188 &rt->mf6c_mcastgrp.sin6_addr) &&
1189 (rt->mf6c_stall != NULL))
1190 break;
1191 }
1192
1193 if (rt == NULL) {
1194 struct mrt6msg *im;
1195#ifdef MRT6_OINIT
1196 struct omrt6msg *oim;
1197#endif
1198
1199 /* no upcall, so make a new entry */
1200 rt = (struct mf6c *)malloc(sizeof(*rt), M_MRTABLE6,
1201 M_NOWAIT);
1202 if (rt == NULL) {
1203 free(rte, M_MRTABLE6);
1204 m_freem(mb0);
1205 MFC6_UNLOCK();
1206 return (ENOBUFS);
1207 }
1208 /*
1209 * Make a copy of the header to send to the user
1210 * level process
1211 */
1212 mm = m_copy(mb0, 0, sizeof(struct ip6_hdr));
1213
1214 if (mm == NULL) {
1215 free(rte, M_MRTABLE6);
1216 m_freem(mb0);
1217 free(rt, M_MRTABLE6);
1218 MFC6_UNLOCK();
1219 return (ENOBUFS);
1220 }
1221
1222 /*
1223 * Send message to routing daemon
1224 */
1225 sin6.sin6_addr = ip6->ip6_src;
1226
1227 im = NULL;
1228#ifdef MRT6_OINIT
1229 oim = NULL;
1230#endif
1231 switch (V_ip6_mrouter_ver) {
1232#ifdef MRT6_OINIT
1233 case MRT6_OINIT:
1234 oim = mtod(mm, struct omrt6msg *);
1235 oim->im6_msgtype = MRT6MSG_NOCACHE;
1236 oim->im6_mbz = 0;
1237 break;
1238#endif
1239 case MRT6_INIT:
1240 im = mtod(mm, struct mrt6msg *);
1241 im->im6_msgtype = MRT6MSG_NOCACHE;
1242 im->im6_mbz = 0;
1243 break;
1244 default:
1245 free(rte, M_MRTABLE6);
1246 m_freem(mb0);
1247 free(rt, M_MRTABLE6);
1248 MFC6_UNLOCK();
1249 return (EINVAL);
1250 }
1251
1252#ifdef MRT6DEBUG
1253 if (V_mrt6debug & DEBUG_FORWARD)
1254 log(LOG_DEBUG,
1255 "getting the iif info in the kernel\n");
1256#endif
1257
1258 for (mifp = mif6table, mifi = 0;
1259 mifi < nummifs && mifp->m6_ifp != ifp;
1260 mifp++, mifi++)
1261 ;
1262
1263 switch (V_ip6_mrouter_ver) {
1264#ifdef MRT6_OINIT
1265 case MRT6_OINIT:
1266 oim->im6_mif = mifi;
1267 break;
1268#endif
1269 case MRT6_INIT:
1270 im->im6_mif = mifi;
1271 break;
1272 }
1273
1274 if (socket_send(V_ip6_mrouter, mm, &sin6) < 0) {
1275 log(LOG_WARNING, "ip6_mforward: ip6_mrouter "
1276 "socket queue full\n");
1277 MRT6STAT_INC(mrt6s_upq_sockfull);
1278 free(rte, M_MRTABLE6);
1279 m_freem(mb0);
1280 free(rt, M_MRTABLE6);
1281 MFC6_UNLOCK();
1282 return (ENOBUFS);
1283 }
1284
1285 MRT6STAT_INC(mrt6s_upcalls);
1286
1287 /* insert new entry at head of hash chain */
1288 bzero(rt, sizeof(*rt));
1289 rt->mf6c_origin.sin6_family = AF_INET6;
1290 rt->mf6c_origin.sin6_len = sizeof(struct sockaddr_in6);
1291 rt->mf6c_origin.sin6_addr = ip6->ip6_src;
1292 rt->mf6c_mcastgrp.sin6_family = AF_INET6;
1293 rt->mf6c_mcastgrp.sin6_len = sizeof(struct sockaddr_in6);
1294 rt->mf6c_mcastgrp.sin6_addr = ip6->ip6_dst;
1295 rt->mf6c_expire = UPCALL_EXPIRE;
1296 n6expire[hash]++;
1297 rt->mf6c_parent = MF6C_INCOMPLETE_PARENT;
1298
1299 /* link into table */
1300 rt->mf6c_next = mf6ctable[hash];
1301 mf6ctable[hash] = rt;
1302 /* Add this entry to the end of the queue */
1303 rt->mf6c_stall = rte;
1304 } else {
1305 /* determine if q has overflowed */
1306 struct rtdetq **p;
1307 int npkts = 0;
1308
1309 for (p = &rt->mf6c_stall; *p != NULL; p = &(*p)->next)
1310 if (++npkts > MAX_UPQ6) {
1311 MRT6STAT_INC(mrt6s_upq_ovflw);
1312 free(rte, M_MRTABLE6);
1313 m_freem(mb0);
1314 MFC6_UNLOCK();
1315 return (0);
1316 }
1317
1318 /* Add this entry to the end of the queue */
1319 *p = rte;
1320 }
1321
1322 rte->next = NULL;
1323 rte->m = mb0;
1324 rte->ifp = ifp;
1325#ifdef UPCALL_TIMING
1326 rte->t = tp;
1327#endif /* UPCALL_TIMING */
1328
1329 MFC6_UNLOCK();
1330
1331 return (0);
1332 }
1333}
1334
1335/*
1336 * Clean up cache entries if upcalls are not serviced
1337 * Call from the Slow Timeout mechanism, every half second.
1338 */
1339static void
1340expire_upcalls(void *unused)
1341{
1342 struct rtdetq *rte;
1343 struct mf6c *mfc, **nptr;
1344 int i;
1345
1346 MFC6_LOCK();
1347 for (i = 0; i < MF6CTBLSIZ; i++) {
1348 if (n6expire[i] == 0)
1349 continue;
1350 nptr = &mf6ctable[i];
1351 while ((mfc = *nptr) != NULL) {
1352 rte = mfc->mf6c_stall;
1353 /*
1354 * Skip real cache entries
1355 * Make sure it wasn't marked to not expire (shouldn't happen)
1356 * If it expires now
1357 */
1358 if (rte != NULL &&
1359 mfc->mf6c_expire != 0 &&
1360 --mfc->mf6c_expire == 0) {
1361#ifdef MRT6DEBUG
1362 if (V_mrt6debug & DEBUG_EXPIRE) {
1363 char ip6bufo[INET6_ADDRSTRLEN];
1364 char ip6bufg[INET6_ADDRSTRLEN];
1365 log(LOG_DEBUG, "expire_upcalls: expiring (%s %s)\n",
1366 ip6_sprintf(ip6bufo, &mfc->mf6c_origin.sin6_addr),
1367 ip6_sprintf(ip6bufg, &mfc->mf6c_mcastgrp.sin6_addr));
1368 }
1369#endif
1370 /*
1371 * drop all the packets
1372 * free the mbuf with the pkt, if, timing info
1373 */
1374 do {
1375 struct rtdetq *n = rte->next;
1376 m_freem(rte->m);
1377 free(rte, M_MRTABLE6);
1378 rte = n;
1379 } while (rte != NULL);
1380 MRT6STAT_INC(mrt6s_cache_cleanups);
1381 n6expire[i]--;
1382
1383 *nptr = mfc->mf6c_next;
1384 free(mfc, M_MRTABLE6);
1385 } else {
1386 nptr = &mfc->mf6c_next;
1387 }
1388 }
1389 }
1390 MFC6_UNLOCK();
1391 callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT,
1392 expire_upcalls, NULL);
1393}
1394
1395/*
1396 * Packet forwarding routine once entry in the cache is made
1397 */
1398static int
1399ip6_mdq(struct mbuf *m, struct ifnet *ifp, struct mf6c *rt)
1400{
1401 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1402 mifi_t mifi, iif;
1403 struct mif6 *mifp;
1404 int plen = m->m_pkthdr.len;
1405 struct in6_addr src0, dst0; /* copies for local work */
1406 u_int32_t iszone, idzone, oszone, odzone;
1407 int error = 0;
1408
1409/*
1410 * Macro to send packet on mif. Since RSVP packets don't get counted on
1411 * input, they shouldn't get counted on output, so statistics keeping is
1412 * separate.
1413 */
1414
1415#define MC6_SEND(ip6, mifp, m) do { \
1416 if ((mifp)->m6_flags & MIFF_REGISTER) \
1417 register_send((ip6), (mifp), (m)); \
1418 else \
1419 phyint_send((ip6), (mifp), (m)); \
1420} while (/*CONSTCOND*/ 0)
1421
1422 /*
1423 * Don't forward if it didn't arrive from the parent mif
1424 * for its origin.
1425 */
1426 mifi = rt->mf6c_parent;
1427 if ((mifi >= nummifs) || (mif6table[mifi].m6_ifp != ifp)) {
1428 /* came in the wrong interface */
1429#ifdef MRT6DEBUG
1430 if (V_mrt6debug & DEBUG_FORWARD)
1431 log(LOG_DEBUG,
1432 "wrong if: ifid %d mifi %d mififid %x\n",
1433 ifp->if_index, mifi,
1434 mif6table[mifi].m6_ifp->if_index);
1435#endif
1436 MRT6STAT_INC(mrt6s_wrong_if);
1437 rt->mf6c_wrong_if++;
1438 /*
1439 * If we are doing PIM processing, and we are forwarding
1440 * packets on this interface, send a message to the
1441 * routing daemon.
1442 */
1443 /* have to make sure this is a valid mif */
1444 if (mifi < nummifs && mif6table[mifi].m6_ifp)
1445 if (V_pim6 && (m->m_flags & M_LOOP) == 0) {
1446 /*
1447 * Check the M_LOOP flag to avoid an
1448 * unnecessary PIM assert.
1449 * XXX: M_LOOP is an ad-hoc hack...
1450 */
1451 static struct sockaddr_in6 sin6 =
1452 { sizeof(sin6), AF_INET6 };
1453
1454 struct mbuf *mm;
1455 struct mrt6msg *im;
1456#ifdef MRT6_OINIT
1457 struct omrt6msg *oim;
1458#endif
1459
1460 mm = m_copy(m, 0, sizeof(struct ip6_hdr));
1461 if (mm &&
1462 (M_HASCL(mm) ||
1463 mm->m_len < sizeof(struct ip6_hdr)))
1464 mm = m_pullup(mm, sizeof(struct ip6_hdr));
1465 if (mm == NULL)
1466 return (ENOBUFS);
1467
1468#ifdef MRT6_OINIT
1469 oim = NULL;
1470#endif
1471 im = NULL;
1472 switch (V_ip6_mrouter_ver) {
1473#ifdef MRT6_OINIT
1474 case MRT6_OINIT:
1475 oim = mtod(mm, struct omrt6msg *);
1476 oim->im6_msgtype = MRT6MSG_WRONGMIF;
1477 oim->im6_mbz = 0;
1478 break;
1479#endif
1480 case MRT6_INIT:
1481 im = mtod(mm, struct mrt6msg *);
1482 im->im6_msgtype = MRT6MSG_WRONGMIF;
1483 im->im6_mbz = 0;
1484 break;
1485 default:
1486 m_freem(mm);
1487 return (EINVAL);
1488 }
1489
1490 for (mifp = mif6table, iif = 0;
1491 iif < nummifs && mifp &&
1492 mifp->m6_ifp != ifp;
1493 mifp++, iif++)
1494 ;
1495
1496 switch (V_ip6_mrouter_ver) {
1497#ifdef MRT6_OINIT
1498 case MRT6_OINIT:
1499 oim->im6_mif = iif;
1500 sin6.sin6_addr = oim->im6_src;
1501 break;
1502#endif
1503 case MRT6_INIT:
1504 im->im6_mif = iif;
1505 sin6.sin6_addr = im->im6_src;
1506 break;
1507 }
1508
1509 MRT6STAT_INC(mrt6s_upcalls);
1510
1511 if (socket_send(V_ip6_mrouter, mm, &sin6) < 0) {
1512#ifdef MRT6DEBUG
1513 if (V_mrt6debug)
1514 log(LOG_WARNING, "mdq, ip6_mrouter socket queue full\n");
1515#endif
1516 MRT6STAT_INC(mrt6s_upq_sockfull);
1517 return (ENOBUFS);
1518 } /* if socket Q full */
1519 } /* if PIM */
1520 return (0);
1521 } /* if wrong iif */
1522
1523 /* If I sourced this packet, it counts as output, else it was input. */
1524 if (m->m_pkthdr.rcvif == NULL) {
1525 /* XXX: is rcvif really NULL when output?? */
1526 mif6table[mifi].m6_pkt_out++;
1527 mif6table[mifi].m6_bytes_out += plen;
1528 } else {
1529 mif6table[mifi].m6_pkt_in++;
1530 mif6table[mifi].m6_bytes_in += plen;
1531 }
1532 rt->mf6c_pkt_cnt++;
1533 rt->mf6c_byte_cnt += plen;
1534
1535 /*
1536 * For each mif, forward a copy of the packet if there are group
1537 * members downstream on the interface.
1538 */
1539 src0 = ip6->ip6_src;
1540 dst0 = ip6->ip6_dst;
1541 if ((error = in6_setscope(&src0, ifp, &iszone)) != 0 ||
1542 (error = in6_setscope(&dst0, ifp, &idzone)) != 0) {
1543 IP6STAT_INC(ip6s_badscope);
1544 return (error);
1545 }
1546 for (mifp = mif6table, mifi = 0; mifi < nummifs; mifp++, mifi++) {
1547 if (IF_ISSET(mifi, &rt->mf6c_ifset)) {
1548 /*
1549 * check if the outgoing packet is going to break
1550 * a scope boundary.
1551 * XXX For packets through PIM register tunnel
1552 * interface, we believe a routing daemon.
1553 */
1554 if (!(mif6table[rt->mf6c_parent].m6_flags &
1555 MIFF_REGISTER) &&
1556 !(mif6table[mifi].m6_flags & MIFF_REGISTER)) {
1557 if (in6_setscope(&src0, mif6table[mifi].m6_ifp,
1558 &oszone) ||
1559 in6_setscope(&dst0, mif6table[mifi].m6_ifp,
1560 &odzone) ||
1561 iszone != oszone ||
1562 idzone != odzone) {
1563 IP6STAT_INC(ip6s_badscope);
1564 continue;
1565 }
1566 }
1567
1568 mifp->m6_pkt_out++;
1569 mifp->m6_bytes_out += plen;
1570 MC6_SEND(ip6, mifp, m);
1571 }
1572 }
1573 return (0);
1574}
1575
1576static void
1577phyint_send(struct ip6_hdr *ip6, struct mif6 *mifp, struct mbuf *m)
1578{
1579 struct mbuf *mb_copy;
1580 struct ifnet *ifp = mifp->m6_ifp;
1581 int error = 0;
1582 u_long linkmtu;
1583
1584 /*
1585 * Make a new reference to the packet; make sure that
1586 * the IPv6 header is actually copied, not just referenced,
1587 * so that ip6_output() only scribbles on the copy.
1588 */
1589 mb_copy = m_copy(m, 0, M_COPYALL);
1590 if (mb_copy &&
1591 (M_HASCL(mb_copy) || mb_copy->m_len < sizeof(struct ip6_hdr)))
1592 mb_copy = m_pullup(mb_copy, sizeof(struct ip6_hdr));
1593 if (mb_copy == NULL) {
1594 return;
1595 }
1596 /* set MCAST flag to the outgoing packet */
1597 mb_copy->m_flags |= M_MCAST;
1598
1599 /*
1600 * If we sourced the packet, call ip6_output since we may devide
1601 * the packet into fragments when the packet is too big for the
1602 * outgoing interface.
1603 * Otherwise, we can simply send the packet to the interface
1604 * sending queue.
1605 */
1606 if (m->m_pkthdr.rcvif == NULL) {
1607 struct ip6_moptions im6o;
1608
1609 im6o.im6o_multicast_ifp = ifp;
1610 /* XXX: ip6_output will override ip6->ip6_hlim */
1611 im6o.im6o_multicast_hlim = ip6->ip6_hlim;
1612 im6o.im6o_multicast_loop = 1;
1613 error = ip6_output(mb_copy, NULL, NULL, IPV6_FORWARDING, &im6o,
1614 NULL, NULL);
1615
1616#ifdef MRT6DEBUG
1617 if (V_mrt6debug & DEBUG_XMIT)
1618 log(LOG_DEBUG, "phyint_send on mif %d err %d\n",
1619 mifp - mif6table, error);
1620#endif
1621 return;
1622 }
1623
1624 /*
1625 * If configured to loop back multicasts by default,
1626 * loop back a copy now.
1627 */
1628 if (in6_mcast_loop) {
1629 struct sockaddr_in6 dst6;
1630
1631 bzero(&dst6, sizeof(dst6));
1632 dst6.sin6_len = sizeof(struct sockaddr_in6);
1633 dst6.sin6_family = AF_INET6;
1634 dst6.sin6_addr = ip6->ip6_dst;
1635 ip6_mloopback(ifp, m, &dst6);
1636 }
1637
1638 /*
1639 * Put the packet into the sending queue of the outgoing interface
1640 * if it would fit in the MTU of the interface.
1641 */
1642 linkmtu = IN6_LINKMTU(ifp);
1643 if (mb_copy->m_pkthdr.len <= linkmtu || linkmtu < IPV6_MMTU) {
1644 struct sockaddr_in6 dst6;
1645
1646 bzero(&dst6, sizeof(dst6));
1647 dst6.sin6_len = sizeof(struct sockaddr_in6);
1648 dst6.sin6_family = AF_INET6;
1649 dst6.sin6_addr = ip6->ip6_dst;
1650
1651 IP_PROBE(send, NULL, NULL, ip6, ifp, NULL, ip6);
1647 /*
1648 * We just call if_output instead of nd6_output here, since
1649 * we need no ND for a multicast forwarded packet...right?
1650 */
1651 m_clrprotoflags(m); /* Avoid confusing lower layers. */
1652 error = (*ifp->if_output)(ifp, mb_copy,
1653 (struct sockaddr *)&dst6, NULL);
1654#ifdef MRT6DEBUG
1655 if (V_mrt6debug & DEBUG_XMIT)
1656 log(LOG_DEBUG, "phyint_send on mif %d err %d\n",
1657 mifp - mif6table, error);
1658#endif
1659 } else {
1660 /*
1661 * pMTU discovery is intentionally disabled by default, since
1662 * various router may notify pMTU in multicast, which can be
1663 * a DDoS to a router
1664 */
1665 if (V_ip6_mcast_pmtu)
1666 icmp6_error(mb_copy, ICMP6_PACKET_TOO_BIG, 0, linkmtu);
1667 else {
1668#ifdef MRT6DEBUG
1669 if (V_mrt6debug & DEBUG_XMIT) {
1670 char ip6bufs[INET6_ADDRSTRLEN];
1671 char ip6bufd[INET6_ADDRSTRLEN];
1672 log(LOG_DEBUG,
1673 "phyint_send: packet too big on %s o %s "
1674 "g %s size %d(discarded)\n",
1675 if_name(ifp),
1676 ip6_sprintf(ip6bufs, &ip6->ip6_src),
1677 ip6_sprintf(ip6bufd, &ip6->ip6_dst),
1678 mb_copy->m_pkthdr.len);
1679 }
1680#endif /* MRT6DEBUG */
1681 m_freem(mb_copy); /* simply discard the packet */
1682 }
1683 }
1684}
1685
1686static int
1687register_send(struct ip6_hdr *ip6, struct mif6 *mif, struct mbuf *m)
1688{
1689 struct mbuf *mm;
1690 int i, len = m->m_pkthdr.len;
1691 static struct sockaddr_in6 sin6 = { sizeof(sin6), AF_INET6 };
1692 struct mrt6msg *im6;
1693
1694#ifdef MRT6DEBUG
1695 if (V_mrt6debug) {
1696 char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
1697 log(LOG_DEBUG, "** IPv6 register_send **\n src %s dst %s\n",
1698 ip6_sprintf(ip6bufs, &ip6->ip6_src),
1699 ip6_sprintf(ip6bufd, &ip6->ip6_dst));
1700 }
1701#endif
1702 PIM6STAT_INC(pim6s_snd_registers);
1703
1704 /* Make a copy of the packet to send to the user level process. */
1705 mm = m_gethdr(M_NOWAIT, MT_DATA);
1706 if (mm == NULL)
1707 return (ENOBUFS);
1708 mm->m_data += max_linkhdr;
1709 mm->m_len = sizeof(struct ip6_hdr);
1710
1711 if ((mm->m_next = m_copy(m, 0, M_COPYALL)) == NULL) {
1712 m_freem(mm);
1713 return (ENOBUFS);
1714 }
1715 i = MHLEN - M_LEADINGSPACE(mm);
1716 if (i > len)
1717 i = len;
1718 mm = m_pullup(mm, i);
1719 if (mm == NULL)
1720 return (ENOBUFS);
1721/* TODO: check it! */
1722 mm->m_pkthdr.len = len + sizeof(struct ip6_hdr);
1723
1724 /*
1725 * Send message to routing daemon
1726 */
1727 sin6.sin6_addr = ip6->ip6_src;
1728
1729 im6 = mtod(mm, struct mrt6msg *);
1730 im6->im6_msgtype = MRT6MSG_WHOLEPKT;
1731 im6->im6_mbz = 0;
1732
1733 im6->im6_mif = mif - mif6table;
1734
1735 /* iif info is not given for reg. encap.n */
1736 MRT6STAT_INC(mrt6s_upcalls);
1737
1738 if (socket_send(V_ip6_mrouter, mm, &sin6) < 0) {
1739#ifdef MRT6DEBUG
1740 if (V_mrt6debug)
1741 log(LOG_WARNING,
1742 "register_send: ip6_mrouter socket queue full\n");
1743#endif
1744 MRT6STAT_INC(mrt6s_upq_sockfull);
1745 return (ENOBUFS);
1746 }
1747 return (0);
1748}
1749
1750/*
1751 * pim6_encapcheck() is called by the encap6_input() path at runtime to
1752 * determine if a packet is for PIM; allowing PIM to be dynamically loaded
1753 * into the kernel.
1754 */
1755static int
1756pim6_encapcheck(const struct mbuf *m, int off, int proto, void *arg)
1757{
1758
1759#ifdef DIAGNOSTIC
1760 KASSERT(proto == IPPROTO_PIM, ("not for IPPROTO_PIM"));
1761#endif
1762 if (proto != IPPROTO_PIM)
1763 return 0; /* not for us; reject the datagram. */
1764
1765 return 64; /* claim the datagram. */
1766}
1767
1768/*
1769 * PIM sparse mode hook
1770 * Receives the pim control messages, and passes them up to the listening
1771 * socket, using rip6_input.
1772 * The only message processed is the REGISTER pim message; the pim header
1773 * is stripped off, and the inner packet is passed to register_mforward.
1774 */
1775int
1776pim6_input(struct mbuf **mp, int *offp, int proto)
1777{
1778 struct pim *pim; /* pointer to a pim struct */
1779 struct ip6_hdr *ip6;
1780 int pimlen;
1781 struct mbuf *m = *mp;
1782 int minlen;
1783 int off = *offp;
1784
1785 PIM6STAT_INC(pim6s_rcv_total);
1786
1787 ip6 = mtod(m, struct ip6_hdr *);
1788 pimlen = m->m_pkthdr.len - *offp;
1789
1790 /*
1791 * Validate lengths
1792 */
1793 if (pimlen < PIM_MINLEN) {
1794 PIM6STAT_INC(pim6s_rcv_tooshort);
1795#ifdef MRT6DEBUG
1796 if (V_mrt6debug & DEBUG_PIM)
1797 log(LOG_DEBUG,"pim6_input: PIM packet too short\n");
1798#endif
1799 m_freem(m);
1800 return (IPPROTO_DONE);
1801 }
1802
1803 /*
1804 * if the packet is at least as big as a REGISTER, go ahead
1805 * and grab the PIM REGISTER header size, to avoid another
1806 * possible m_pullup() later.
1807 *
1808 * PIM_MINLEN == pimhdr + u_int32 == 8
1809 * PIM6_REG_MINLEN == pimhdr + reghdr + eip6hdr == 4 + 4 + 40
1810 */
1811 minlen = (pimlen >= PIM6_REG_MINLEN) ? PIM6_REG_MINLEN : PIM_MINLEN;
1812
1813 /*
1814 * Make sure that the IP6 and PIM headers in contiguous memory, and
1815 * possibly the PIM REGISTER header
1816 */
1817#ifndef PULLDOWN_TEST
1818 IP6_EXTHDR_CHECK(m, off, minlen, IPPROTO_DONE);
1819 /* adjust pointer */
1820 ip6 = mtod(m, struct ip6_hdr *);
1821
1822 /* adjust mbuf to point to the PIM header */
1823 pim = (struct pim *)((caddr_t)ip6 + off);
1824#else
1825 IP6_EXTHDR_GET(pim, struct pim *, m, off, minlen);
1826 if (pim == NULL) {
1827 PIM6STAT_INC(pim6s_rcv_tooshort);
1828 return (IPPROTO_DONE);
1829 }
1830#endif
1831
1832#define PIM6_CHECKSUM
1833#ifdef PIM6_CHECKSUM
1834 {
1835 int cksumlen;
1836
1837 /*
1838 * Validate checksum.
1839 * If PIM REGISTER, exclude the data packet
1840 */
1841 if (pim->pim_type == PIM_REGISTER)
1842 cksumlen = PIM_MINLEN;
1843 else
1844 cksumlen = pimlen;
1845
1846 if (in6_cksum(m, IPPROTO_PIM, off, cksumlen)) {
1847 PIM6STAT_INC(pim6s_rcv_badsum);
1848#ifdef MRT6DEBUG
1849 if (V_mrt6debug & DEBUG_PIM)
1850 log(LOG_DEBUG,
1851 "pim6_input: invalid checksum\n");
1852#endif
1853 m_freem(m);
1854 return (IPPROTO_DONE);
1855 }
1856 }
1857#endif /* PIM_CHECKSUM */
1858
1859 /* PIM version check */
1860 if (pim->pim_ver != PIM_VERSION) {
1861 PIM6STAT_INC(pim6s_rcv_badversion);
1862#ifdef MRT6DEBUG
1863 log(LOG_ERR,
1864 "pim6_input: incorrect version %d, expecting %d\n",
1865 pim->pim_ver, PIM_VERSION);
1866#endif
1867 m_freem(m);
1868 return (IPPROTO_DONE);
1869 }
1870
1871 if (pim->pim_type == PIM_REGISTER) {
1872 /*
1873 * since this is a REGISTER, we'll make a copy of the register
1874 * headers ip6+pim+u_int32_t+encap_ip6, to be passed up to the
1875 * routing daemon.
1876 */
1877 static struct sockaddr_in6 dst = { sizeof(dst), AF_INET6 };
1878
1879 struct mbuf *mcp;
1880 struct ip6_hdr *eip6;
1881 u_int32_t *reghdr;
1882 int rc;
1883#ifdef MRT6DEBUG
1884 char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
1885#endif
1886
1887 PIM6STAT_INC(pim6s_rcv_registers);
1888
1889 if ((reg_mif_num >= nummifs) || (reg_mif_num == (mifi_t) -1)) {
1890#ifdef MRT6DEBUG
1891 if (V_mrt6debug & DEBUG_PIM)
1892 log(LOG_DEBUG,
1893 "pim6_input: register mif not set: %d\n",
1894 reg_mif_num);
1895#endif
1896 m_freem(m);
1897 return (IPPROTO_DONE);
1898 }
1899
1900 reghdr = (u_int32_t *)(pim + 1);
1901
1902 if ((ntohl(*reghdr) & PIM_NULL_REGISTER))
1903 goto pim6_input_to_daemon;
1904
1905 /*
1906 * Validate length
1907 */
1908 if (pimlen < PIM6_REG_MINLEN) {
1909 PIM6STAT_INC(pim6s_rcv_tooshort);
1910 PIM6STAT_INC(pim6s_rcv_badregisters);
1911#ifdef MRT6DEBUG
1912 log(LOG_ERR,
1913 "pim6_input: register packet size too "
1914 "small %d from %s\n",
1915 pimlen, ip6_sprintf(ip6bufs, &ip6->ip6_src));
1916#endif
1917 m_freem(m);
1918 return (IPPROTO_DONE);
1919 }
1920
1921 eip6 = (struct ip6_hdr *) (reghdr + 1);
1922#ifdef MRT6DEBUG
1923 if (V_mrt6debug & DEBUG_PIM)
1924 log(LOG_DEBUG,
1925 "pim6_input[register], eip6: %s -> %s, "
1926 "eip6 plen %d\n",
1927 ip6_sprintf(ip6bufs, &eip6->ip6_src),
1928 ip6_sprintf(ip6bufd, &eip6->ip6_dst),
1929 ntohs(eip6->ip6_plen));
1930#endif
1931
1932 /* verify the version number of the inner packet */
1933 if ((eip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
1934 PIM6STAT_INC(pim6s_rcv_badregisters);
1935#ifdef MRT6DEBUG
1936 log(LOG_DEBUG, "pim6_input: invalid IP version (%d) "
1937 "of the inner packet\n",
1938 (eip6->ip6_vfc & IPV6_VERSION));
1939#endif
1940 m_freem(m);
1941 return (IPPROTO_NONE);
1942 }
1943
1944 /* verify the inner packet is destined to a mcast group */
1945 if (!IN6_IS_ADDR_MULTICAST(&eip6->ip6_dst)) {
1946 PIM6STAT_INC(pim6s_rcv_badregisters);
1947#ifdef MRT6DEBUG
1948 if (V_mrt6debug & DEBUG_PIM)
1949 log(LOG_DEBUG,
1950 "pim6_input: inner packet of register "
1951 "is not multicast %s\n",
1952 ip6_sprintf(ip6bufd, &eip6->ip6_dst));
1953#endif
1954 m_freem(m);
1955 return (IPPROTO_DONE);
1956 }
1957
1958 /*
1959 * make a copy of the whole header to pass to the daemon later.
1960 */
1961 mcp = m_copy(m, 0, off + PIM6_REG_MINLEN);
1962 if (mcp == NULL) {
1963#ifdef MRT6DEBUG
1964 log(LOG_ERR,
1965 "pim6_input: pim register: "
1966 "could not copy register head\n");
1967#endif
1968 m_freem(m);
1969 return (IPPROTO_DONE);
1970 }
1971
1972 /*
1973 * forward the inner ip6 packet; point m_data at the inner ip6.
1974 */
1975 m_adj(m, off + PIM_MINLEN);
1976#ifdef MRT6DEBUG
1977 if (V_mrt6debug & DEBUG_PIM) {
1978 log(LOG_DEBUG,
1979 "pim6_input: forwarding decapsulated register: "
1980 "src %s, dst %s, mif %d\n",
1981 ip6_sprintf(ip6bufs, &eip6->ip6_src),
1982 ip6_sprintf(ip6bufd, &eip6->ip6_dst),
1983 reg_mif_num);
1984 }
1985#endif
1986
1987 rc = if_simloop(mif6table[reg_mif_num].m6_ifp, m,
1988 dst.sin6_family, 0);
1989
1990 /* prepare the register head to send to the mrouting daemon */
1991 m = mcp;
1992 }
1993
1994 /*
1995 * Pass the PIM message up to the daemon; if it is a register message
1996 * pass the 'head' only up to the daemon. This includes the
1997 * encapsulator ip6 header, pim header, register header and the
1998 * encapsulated ip6 header.
1999 */
2000 pim6_input_to_daemon:
2001 rip6_input(&m, offp, proto);
2002 return (IPPROTO_DONE);
2003}
2004
2005static int
2006ip6_mroute_modevent(module_t mod, int type, void *unused)
2007{
2008
2009 switch (type) {
2010 case MOD_LOAD:
2011 MROUTER6_LOCK_INIT();
2012 MFC6_LOCK_INIT();
2013 MIF6_LOCK_INIT();
2014
2015 pim6_encap_cookie = encap_attach_func(AF_INET6, IPPROTO_PIM,
2016 pim6_encapcheck,
2017 (const struct protosw *)&in6_pim_protosw, NULL);
2018 if (pim6_encap_cookie == NULL) {
2019 printf("ip6_mroute: unable to attach pim6 encap\n");
2020 MIF6_LOCK_DESTROY();
2021 MFC6_LOCK_DESTROY();
2022 MROUTER6_LOCK_DESTROY();
2023 return (EINVAL);
2024 }
2025
2026 ip6_mforward = X_ip6_mforward;
2027 ip6_mrouter_done = X_ip6_mrouter_done;
2028 ip6_mrouter_get = X_ip6_mrouter_get;
2029 ip6_mrouter_set = X_ip6_mrouter_set;
2030 mrt6_ioctl = X_mrt6_ioctl;
2031 break;
2032
2033 case MOD_UNLOAD:
2034 if (V_ip6_mrouter != NULL)
2035 return EINVAL;
2036
2037 if (pim6_encap_cookie) {
2038 encap_detach(pim6_encap_cookie);
2039 pim6_encap_cookie = NULL;
2040 }
2041 X_ip6_mrouter_done();
2042 ip6_mforward = NULL;
2043 ip6_mrouter_done = NULL;
2044 ip6_mrouter_get = NULL;
2045 ip6_mrouter_set = NULL;
2046 mrt6_ioctl = NULL;
2047
2048 MIF6_LOCK_DESTROY();
2049 MFC6_LOCK_DESTROY();
2050 MROUTER6_LOCK_DESTROY();
2051 break;
2052
2053 default:
2054 return (EOPNOTSUPP);
2055 }
2056
2057 return (0);
2058}
2059
2060static moduledata_t ip6_mroutemod = {
2061 "ip6_mroute",
2062 ip6_mroute_modevent,
2063 0
2064};
2065
2066DECLARE_MODULE(ip6_mroute, ip6_mroutemod, SI_SUB_PSEUDO, SI_ORDER_ANY);
1652 /*
1653 * We just call if_output instead of nd6_output here, since
1654 * we need no ND for a multicast forwarded packet...right?
1655 */
1656 m_clrprotoflags(m); /* Avoid confusing lower layers. */
1657 error = (*ifp->if_output)(ifp, mb_copy,
1658 (struct sockaddr *)&dst6, NULL);
1659#ifdef MRT6DEBUG
1660 if (V_mrt6debug & DEBUG_XMIT)
1661 log(LOG_DEBUG, "phyint_send on mif %d err %d\n",
1662 mifp - mif6table, error);
1663#endif
1664 } else {
1665 /*
1666 * pMTU discovery is intentionally disabled by default, since
1667 * various router may notify pMTU in multicast, which can be
1668 * a DDoS to a router
1669 */
1670 if (V_ip6_mcast_pmtu)
1671 icmp6_error(mb_copy, ICMP6_PACKET_TOO_BIG, 0, linkmtu);
1672 else {
1673#ifdef MRT6DEBUG
1674 if (V_mrt6debug & DEBUG_XMIT) {
1675 char ip6bufs[INET6_ADDRSTRLEN];
1676 char ip6bufd[INET6_ADDRSTRLEN];
1677 log(LOG_DEBUG,
1678 "phyint_send: packet too big on %s o %s "
1679 "g %s size %d(discarded)\n",
1680 if_name(ifp),
1681 ip6_sprintf(ip6bufs, &ip6->ip6_src),
1682 ip6_sprintf(ip6bufd, &ip6->ip6_dst),
1683 mb_copy->m_pkthdr.len);
1684 }
1685#endif /* MRT6DEBUG */
1686 m_freem(mb_copy); /* simply discard the packet */
1687 }
1688 }
1689}
1690
1691static int
1692register_send(struct ip6_hdr *ip6, struct mif6 *mif, struct mbuf *m)
1693{
1694 struct mbuf *mm;
1695 int i, len = m->m_pkthdr.len;
1696 static struct sockaddr_in6 sin6 = { sizeof(sin6), AF_INET6 };
1697 struct mrt6msg *im6;
1698
1699#ifdef MRT6DEBUG
1700 if (V_mrt6debug) {
1701 char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
1702 log(LOG_DEBUG, "** IPv6 register_send **\n src %s dst %s\n",
1703 ip6_sprintf(ip6bufs, &ip6->ip6_src),
1704 ip6_sprintf(ip6bufd, &ip6->ip6_dst));
1705 }
1706#endif
1707 PIM6STAT_INC(pim6s_snd_registers);
1708
1709 /* Make a copy of the packet to send to the user level process. */
1710 mm = m_gethdr(M_NOWAIT, MT_DATA);
1711 if (mm == NULL)
1712 return (ENOBUFS);
1713 mm->m_data += max_linkhdr;
1714 mm->m_len = sizeof(struct ip6_hdr);
1715
1716 if ((mm->m_next = m_copy(m, 0, M_COPYALL)) == NULL) {
1717 m_freem(mm);
1718 return (ENOBUFS);
1719 }
1720 i = MHLEN - M_LEADINGSPACE(mm);
1721 if (i > len)
1722 i = len;
1723 mm = m_pullup(mm, i);
1724 if (mm == NULL)
1725 return (ENOBUFS);
1726/* TODO: check it! */
1727 mm->m_pkthdr.len = len + sizeof(struct ip6_hdr);
1728
1729 /*
1730 * Send message to routing daemon
1731 */
1732 sin6.sin6_addr = ip6->ip6_src;
1733
1734 im6 = mtod(mm, struct mrt6msg *);
1735 im6->im6_msgtype = MRT6MSG_WHOLEPKT;
1736 im6->im6_mbz = 0;
1737
1738 im6->im6_mif = mif - mif6table;
1739
1740 /* iif info is not given for reg. encap.n */
1741 MRT6STAT_INC(mrt6s_upcalls);
1742
1743 if (socket_send(V_ip6_mrouter, mm, &sin6) < 0) {
1744#ifdef MRT6DEBUG
1745 if (V_mrt6debug)
1746 log(LOG_WARNING,
1747 "register_send: ip6_mrouter socket queue full\n");
1748#endif
1749 MRT6STAT_INC(mrt6s_upq_sockfull);
1750 return (ENOBUFS);
1751 }
1752 return (0);
1753}
1754
1755/*
1756 * pim6_encapcheck() is called by the encap6_input() path at runtime to
1757 * determine if a packet is for PIM; allowing PIM to be dynamically loaded
1758 * into the kernel.
1759 */
1760static int
1761pim6_encapcheck(const struct mbuf *m, int off, int proto, void *arg)
1762{
1763
1764#ifdef DIAGNOSTIC
1765 KASSERT(proto == IPPROTO_PIM, ("not for IPPROTO_PIM"));
1766#endif
1767 if (proto != IPPROTO_PIM)
1768 return 0; /* not for us; reject the datagram. */
1769
1770 return 64; /* claim the datagram. */
1771}
1772
1773/*
1774 * PIM sparse mode hook
1775 * Receives the pim control messages, and passes them up to the listening
1776 * socket, using rip6_input.
1777 * The only message processed is the REGISTER pim message; the pim header
1778 * is stripped off, and the inner packet is passed to register_mforward.
1779 */
1780int
1781pim6_input(struct mbuf **mp, int *offp, int proto)
1782{
1783 struct pim *pim; /* pointer to a pim struct */
1784 struct ip6_hdr *ip6;
1785 int pimlen;
1786 struct mbuf *m = *mp;
1787 int minlen;
1788 int off = *offp;
1789
1790 PIM6STAT_INC(pim6s_rcv_total);
1791
1792 ip6 = mtod(m, struct ip6_hdr *);
1793 pimlen = m->m_pkthdr.len - *offp;
1794
1795 /*
1796 * Validate lengths
1797 */
1798 if (pimlen < PIM_MINLEN) {
1799 PIM6STAT_INC(pim6s_rcv_tooshort);
1800#ifdef MRT6DEBUG
1801 if (V_mrt6debug & DEBUG_PIM)
1802 log(LOG_DEBUG,"pim6_input: PIM packet too short\n");
1803#endif
1804 m_freem(m);
1805 return (IPPROTO_DONE);
1806 }
1807
1808 /*
1809 * if the packet is at least as big as a REGISTER, go ahead
1810 * and grab the PIM REGISTER header size, to avoid another
1811 * possible m_pullup() later.
1812 *
1813 * PIM_MINLEN == pimhdr + u_int32 == 8
1814 * PIM6_REG_MINLEN == pimhdr + reghdr + eip6hdr == 4 + 4 + 40
1815 */
1816 minlen = (pimlen >= PIM6_REG_MINLEN) ? PIM6_REG_MINLEN : PIM_MINLEN;
1817
1818 /*
1819 * Make sure that the IP6 and PIM headers in contiguous memory, and
1820 * possibly the PIM REGISTER header
1821 */
1822#ifndef PULLDOWN_TEST
1823 IP6_EXTHDR_CHECK(m, off, minlen, IPPROTO_DONE);
1824 /* adjust pointer */
1825 ip6 = mtod(m, struct ip6_hdr *);
1826
1827 /* adjust mbuf to point to the PIM header */
1828 pim = (struct pim *)((caddr_t)ip6 + off);
1829#else
1830 IP6_EXTHDR_GET(pim, struct pim *, m, off, minlen);
1831 if (pim == NULL) {
1832 PIM6STAT_INC(pim6s_rcv_tooshort);
1833 return (IPPROTO_DONE);
1834 }
1835#endif
1836
1837#define PIM6_CHECKSUM
1838#ifdef PIM6_CHECKSUM
1839 {
1840 int cksumlen;
1841
1842 /*
1843 * Validate checksum.
1844 * If PIM REGISTER, exclude the data packet
1845 */
1846 if (pim->pim_type == PIM_REGISTER)
1847 cksumlen = PIM_MINLEN;
1848 else
1849 cksumlen = pimlen;
1850
1851 if (in6_cksum(m, IPPROTO_PIM, off, cksumlen)) {
1852 PIM6STAT_INC(pim6s_rcv_badsum);
1853#ifdef MRT6DEBUG
1854 if (V_mrt6debug & DEBUG_PIM)
1855 log(LOG_DEBUG,
1856 "pim6_input: invalid checksum\n");
1857#endif
1858 m_freem(m);
1859 return (IPPROTO_DONE);
1860 }
1861 }
1862#endif /* PIM_CHECKSUM */
1863
1864 /* PIM version check */
1865 if (pim->pim_ver != PIM_VERSION) {
1866 PIM6STAT_INC(pim6s_rcv_badversion);
1867#ifdef MRT6DEBUG
1868 log(LOG_ERR,
1869 "pim6_input: incorrect version %d, expecting %d\n",
1870 pim->pim_ver, PIM_VERSION);
1871#endif
1872 m_freem(m);
1873 return (IPPROTO_DONE);
1874 }
1875
1876 if (pim->pim_type == PIM_REGISTER) {
1877 /*
1878 * since this is a REGISTER, we'll make a copy of the register
1879 * headers ip6+pim+u_int32_t+encap_ip6, to be passed up to the
1880 * routing daemon.
1881 */
1882 static struct sockaddr_in6 dst = { sizeof(dst), AF_INET6 };
1883
1884 struct mbuf *mcp;
1885 struct ip6_hdr *eip6;
1886 u_int32_t *reghdr;
1887 int rc;
1888#ifdef MRT6DEBUG
1889 char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
1890#endif
1891
1892 PIM6STAT_INC(pim6s_rcv_registers);
1893
1894 if ((reg_mif_num >= nummifs) || (reg_mif_num == (mifi_t) -1)) {
1895#ifdef MRT6DEBUG
1896 if (V_mrt6debug & DEBUG_PIM)
1897 log(LOG_DEBUG,
1898 "pim6_input: register mif not set: %d\n",
1899 reg_mif_num);
1900#endif
1901 m_freem(m);
1902 return (IPPROTO_DONE);
1903 }
1904
1905 reghdr = (u_int32_t *)(pim + 1);
1906
1907 if ((ntohl(*reghdr) & PIM_NULL_REGISTER))
1908 goto pim6_input_to_daemon;
1909
1910 /*
1911 * Validate length
1912 */
1913 if (pimlen < PIM6_REG_MINLEN) {
1914 PIM6STAT_INC(pim6s_rcv_tooshort);
1915 PIM6STAT_INC(pim6s_rcv_badregisters);
1916#ifdef MRT6DEBUG
1917 log(LOG_ERR,
1918 "pim6_input: register packet size too "
1919 "small %d from %s\n",
1920 pimlen, ip6_sprintf(ip6bufs, &ip6->ip6_src));
1921#endif
1922 m_freem(m);
1923 return (IPPROTO_DONE);
1924 }
1925
1926 eip6 = (struct ip6_hdr *) (reghdr + 1);
1927#ifdef MRT6DEBUG
1928 if (V_mrt6debug & DEBUG_PIM)
1929 log(LOG_DEBUG,
1930 "pim6_input[register], eip6: %s -> %s, "
1931 "eip6 plen %d\n",
1932 ip6_sprintf(ip6bufs, &eip6->ip6_src),
1933 ip6_sprintf(ip6bufd, &eip6->ip6_dst),
1934 ntohs(eip6->ip6_plen));
1935#endif
1936
1937 /* verify the version number of the inner packet */
1938 if ((eip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
1939 PIM6STAT_INC(pim6s_rcv_badregisters);
1940#ifdef MRT6DEBUG
1941 log(LOG_DEBUG, "pim6_input: invalid IP version (%d) "
1942 "of the inner packet\n",
1943 (eip6->ip6_vfc & IPV6_VERSION));
1944#endif
1945 m_freem(m);
1946 return (IPPROTO_NONE);
1947 }
1948
1949 /* verify the inner packet is destined to a mcast group */
1950 if (!IN6_IS_ADDR_MULTICAST(&eip6->ip6_dst)) {
1951 PIM6STAT_INC(pim6s_rcv_badregisters);
1952#ifdef MRT6DEBUG
1953 if (V_mrt6debug & DEBUG_PIM)
1954 log(LOG_DEBUG,
1955 "pim6_input: inner packet of register "
1956 "is not multicast %s\n",
1957 ip6_sprintf(ip6bufd, &eip6->ip6_dst));
1958#endif
1959 m_freem(m);
1960 return (IPPROTO_DONE);
1961 }
1962
1963 /*
1964 * make a copy of the whole header to pass to the daemon later.
1965 */
1966 mcp = m_copy(m, 0, off + PIM6_REG_MINLEN);
1967 if (mcp == NULL) {
1968#ifdef MRT6DEBUG
1969 log(LOG_ERR,
1970 "pim6_input: pim register: "
1971 "could not copy register head\n");
1972#endif
1973 m_freem(m);
1974 return (IPPROTO_DONE);
1975 }
1976
1977 /*
1978 * forward the inner ip6 packet; point m_data at the inner ip6.
1979 */
1980 m_adj(m, off + PIM_MINLEN);
1981#ifdef MRT6DEBUG
1982 if (V_mrt6debug & DEBUG_PIM) {
1983 log(LOG_DEBUG,
1984 "pim6_input: forwarding decapsulated register: "
1985 "src %s, dst %s, mif %d\n",
1986 ip6_sprintf(ip6bufs, &eip6->ip6_src),
1987 ip6_sprintf(ip6bufd, &eip6->ip6_dst),
1988 reg_mif_num);
1989 }
1990#endif
1991
1992 rc = if_simloop(mif6table[reg_mif_num].m6_ifp, m,
1993 dst.sin6_family, 0);
1994
1995 /* prepare the register head to send to the mrouting daemon */
1996 m = mcp;
1997 }
1998
1999 /*
2000 * Pass the PIM message up to the daemon; if it is a register message
2001 * pass the 'head' only up to the daemon. This includes the
2002 * encapsulator ip6 header, pim header, register header and the
2003 * encapsulated ip6 header.
2004 */
2005 pim6_input_to_daemon:
2006 rip6_input(&m, offp, proto);
2007 return (IPPROTO_DONE);
2008}
2009
2010static int
2011ip6_mroute_modevent(module_t mod, int type, void *unused)
2012{
2013
2014 switch (type) {
2015 case MOD_LOAD:
2016 MROUTER6_LOCK_INIT();
2017 MFC6_LOCK_INIT();
2018 MIF6_LOCK_INIT();
2019
2020 pim6_encap_cookie = encap_attach_func(AF_INET6, IPPROTO_PIM,
2021 pim6_encapcheck,
2022 (const struct protosw *)&in6_pim_protosw, NULL);
2023 if (pim6_encap_cookie == NULL) {
2024 printf("ip6_mroute: unable to attach pim6 encap\n");
2025 MIF6_LOCK_DESTROY();
2026 MFC6_LOCK_DESTROY();
2027 MROUTER6_LOCK_DESTROY();
2028 return (EINVAL);
2029 }
2030
2031 ip6_mforward = X_ip6_mforward;
2032 ip6_mrouter_done = X_ip6_mrouter_done;
2033 ip6_mrouter_get = X_ip6_mrouter_get;
2034 ip6_mrouter_set = X_ip6_mrouter_set;
2035 mrt6_ioctl = X_mrt6_ioctl;
2036 break;
2037
2038 case MOD_UNLOAD:
2039 if (V_ip6_mrouter != NULL)
2040 return EINVAL;
2041
2042 if (pim6_encap_cookie) {
2043 encap_detach(pim6_encap_cookie);
2044 pim6_encap_cookie = NULL;
2045 }
2046 X_ip6_mrouter_done();
2047 ip6_mforward = NULL;
2048 ip6_mrouter_done = NULL;
2049 ip6_mrouter_get = NULL;
2050 ip6_mrouter_set = NULL;
2051 mrt6_ioctl = NULL;
2052
2053 MIF6_LOCK_DESTROY();
2054 MFC6_LOCK_DESTROY();
2055 MROUTER6_LOCK_DESTROY();
2056 break;
2057
2058 default:
2059 return (EOPNOTSUPP);
2060 }
2061
2062 return (0);
2063}
2064
2065static moduledata_t ip6_mroutemod = {
2066 "ip6_mroute",
2067 ip6_mroute_modevent,
2068 0
2069};
2070
2071DECLARE_MODULE(ip6_mroute, ip6_mroutemod, SI_SUB_PSEUDO, SI_ORDER_ANY);