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