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