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