1 /* $OpenBSD: ip_mroute.c,v 1.131 2021/12/15 17:21:08 deraadt Exp $ */ 2 /* $NetBSD: ip_mroute.c,v 1.85 2004/04/26 01:31:57 matt Exp $ */ 3 4 /* 5 * Copyright (c) 1989 Stephen Deering 6 * Copyright (c) 1992, 1993 7 * The Regents of the University of California. All rights reserved. 8 * 9 * This code is derived from software contributed to Berkeley by 10 * Stephen Deering of Stanford University. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * @(#)ip_mroute.c 8.2 (Berkeley) 11/15/93 37 */ 38 39 /* 40 * IP multicast forwarding procedures 41 * 42 * Written by David Waitzman, BBN Labs, August 1988. 43 * Modified by Steve Deering, Stanford, February 1989. 44 * Modified by Mark J. Steiglitz, Stanford, May, 1991 45 * Modified by Van Jacobson, LBL, January 1993 46 * Modified by Ajit Thyagarajan, PARC, August 1993 47 * Modified by Bill Fenner, PARC, April 1994 48 * Modified by Charles M. Hannum, NetBSD, May 1995. 49 * Modified by Ahmed Helmy, SGI, June 1996 50 * Modified by George Edmond Eddy (Rusty), ISI, February 1998 51 * Modified by Pavlin Radoslavov, USC/ISI, May 1998, August 1999, October 2000 52 * Modified by Hitoshi Asaeda, WIDE, August 2000 53 * Modified by Pavlin Radoslavov, ICSI, October 2002 54 * 55 * MROUTING Revision: 1.2 56 * advanced API support, bandwidth metering and signaling 57 */ 58 59 #include <sys/param.h> 60 #include <sys/systm.h> 61 #include <sys/mbuf.h> 62 #include <sys/socket.h> 63 #include <sys/socketvar.h> 64 #include <sys/protosw.h> 65 #include <sys/ioctl.h> 66 #include <sys/syslog.h> 67 68 #include <net/if.h> 69 #include <net/if_var.h> 70 #include <net/route.h> 71 72 #include <netinet/in.h> 73 #include <netinet/ip.h> 74 #include <netinet/ip_var.h> 75 #include <netinet/in_pcb.h> 76 #include <netinet/igmp.h> 77 #include <netinet/ip_mroute.h> 78 79 /* #define MCAST_DEBUG */ 80 81 #ifdef MCAST_DEBUG 82 int mcast_debug = 1; 83 #define DPRINTF(fmt, args...) \ 84 do { \ 85 if (mcast_debug) \ 86 printf("%s:%d " fmt "\n", \ 87 __func__, __LINE__, ## args); \ 88 } while (0) 89 #else 90 #define DPRINTF(fmt, args...) \ 91 do { } while (0) 92 #endif 93 94 /* 95 * Globals. All but ip_mrouter and ip_mrtproto could be static, 96 * except for netstat or debugging purposes. 97 */ 98 struct socket *ip_mrouter[RT_TABLEID_MAX + 1]; 99 struct rttimer_queue *mrouterq[RT_TABLEID_MAX + 1]; 100 uint64_t mrt_count[RT_TABLEID_MAX + 1]; 101 int ip_mrtproto = IGMP_DVMRP; /* for netstat only */ 102 103 struct mrtstat mrtstat; 104 105 struct rtentry *mfc_find(struct ifnet *, struct in_addr *, 106 struct in_addr *, unsigned int); 107 int get_sg_cnt(unsigned int, struct sioc_sg_req *); 108 int get_vif_cnt(unsigned int, struct sioc_vif_req *); 109 int mrt_rtwalk_mfcsysctl(struct rtentry *, void *, unsigned int); 110 int ip_mrouter_init(struct socket *, struct mbuf *); 111 int mrouter_rtwalk_delete(struct rtentry *, void *, unsigned int); 112 int get_version(struct mbuf *); 113 int add_vif(struct socket *, struct mbuf *); 114 int del_vif(struct socket *, struct mbuf *); 115 void update_mfc_params(struct mfcctl2 *, int, unsigned int); 116 void mfc_expire_route(struct rtentry *, struct rttimer *); 117 int mfc_add(struct mfcctl2 *, struct in_addr *, struct in_addr *, 118 int, unsigned int, int); 119 int add_mfc(struct socket *, struct mbuf *); 120 int del_mfc(struct socket *, struct mbuf *); 121 int set_api_config(struct socket *, struct mbuf *); /* chose API capabilities */ 122 int get_api_support(struct mbuf *); 123 int get_api_config(struct mbuf *); 124 int socket_send(struct socket *, struct mbuf *, 125 struct sockaddr_in *); 126 int ip_mdq(struct mbuf *, struct ifnet *, struct rtentry *); 127 struct ifnet *if_lookupbyvif(vifi_t, unsigned int); 128 struct rtentry *rt_mcast_add(struct ifnet *, struct sockaddr *, 129 struct sockaddr *); 130 void mrt_mcast_del(struct rtentry *, unsigned int); 131 132 /* 133 * Kernel multicast routing API capabilities and setup. 134 * If more API capabilities are added to the kernel, they should be 135 * recorded in `mrt_api_support'. 136 */ 137 static const u_int32_t mrt_api_support = (MRT_MFC_FLAGS_DISABLE_WRONGVIF | 138 MRT_MFC_RP); 139 static u_int32_t mrt_api_config = 0; 140 141 /* 142 * Find a route for a given origin IP address and Multicast group address 143 * Type of service parameter to be added in the future!!! 144 * Statistics are updated by the caller if needed 145 * (mrtstat.mrts_mfc_lookups and mrtstat.mrts_mfc_misses) 146 */ 147 struct rtentry * 148 mfc_find(struct ifnet *ifp, struct in_addr *origin, struct in_addr *group, 149 unsigned int rtableid) 150 { 151 struct rtentry *rt; 152 struct sockaddr_in msin; 153 154 memset(&msin, 0, sizeof(msin)); 155 msin.sin_len = sizeof(msin); 156 msin.sin_family = AF_INET; 157 msin.sin_addr = *group; 158 159 rt = rtalloc(sintosa(&msin), 0, rtableid); 160 do { 161 if (!rtisvalid(rt)) { 162 rtfree(rt); 163 return NULL; 164 } 165 /* Don't consider non multicast routes. */ 166 if (ISSET(rt->rt_flags, RTF_HOST | RTF_MULTICAST) != 167 (RTF_HOST | RTF_MULTICAST)) 168 continue; 169 /* Return first occurrence if interface is not specified. */ 170 if (ifp == NULL) 171 return (rt); 172 if (rt->rt_ifidx == ifp->if_index) 173 return (rt); 174 } while ((rt = rtable_iterate(rt)) != NULL); 175 176 return (NULL); 177 } 178 179 /* 180 * Handle MRT setsockopt commands to modify the multicast routing tables. 181 */ 182 int 183 ip_mrouter_set(struct socket *so, int optname, struct mbuf *m) 184 { 185 struct inpcb *inp = sotoinpcb(so); 186 int error; 187 188 if (optname != MRT_INIT && 189 so != ip_mrouter[inp->inp_rtableid]) 190 error = ENOPROTOOPT; 191 else 192 switch (optname) { 193 case MRT_INIT: 194 error = ip_mrouter_init(so, m); 195 break; 196 case MRT_DONE: 197 error = ip_mrouter_done(so); 198 break; 199 case MRT_ADD_VIF: 200 error = add_vif(so, m); 201 break; 202 case MRT_DEL_VIF: 203 error = del_vif(so, m); 204 break; 205 case MRT_ADD_MFC: 206 error = add_mfc(so, m); 207 break; 208 case MRT_DEL_MFC: 209 error = del_mfc(so, m); 210 break; 211 case MRT_API_CONFIG: 212 error = set_api_config(so, m); 213 break; 214 default: 215 error = ENOPROTOOPT; 216 break; 217 } 218 219 return (error); 220 } 221 222 /* 223 * Handle MRT getsockopt commands 224 */ 225 int 226 ip_mrouter_get(struct socket *so, int optname, struct mbuf *m) 227 { 228 struct inpcb *inp = sotoinpcb(so); 229 int error; 230 231 if (so != ip_mrouter[inp->inp_rtableid]) 232 error = ENOPROTOOPT; 233 else { 234 switch (optname) { 235 case MRT_VERSION: 236 error = get_version(m); 237 break; 238 case MRT_API_SUPPORT: 239 error = get_api_support(m); 240 break; 241 case MRT_API_CONFIG: 242 error = get_api_config(m); 243 break; 244 default: 245 error = ENOPROTOOPT; 246 break; 247 } 248 } 249 250 return (error); 251 } 252 253 /* 254 * Handle ioctl commands to obtain information from the cache 255 */ 256 int 257 mrt_ioctl(struct socket *so, u_long cmd, caddr_t data) 258 { 259 struct inpcb *inp = sotoinpcb(so); 260 int error; 261 262 if (inp == NULL) 263 return (ENOTCONN); 264 265 if (so != ip_mrouter[inp->inp_rtableid]) 266 error = EINVAL; 267 else 268 switch (cmd) { 269 case SIOCGETVIFCNT: 270 NET_RLOCK_IN_IOCTL(); 271 error = get_vif_cnt(inp->inp_rtableid, 272 (struct sioc_vif_req *)data); 273 NET_RUNLOCK_IN_IOCTL(); 274 break; 275 case SIOCGETSGCNT: 276 NET_RLOCK_IN_IOCTL(); 277 error = get_sg_cnt(inp->inp_rtableid, 278 (struct sioc_sg_req *)data); 279 NET_RUNLOCK_IN_IOCTL(); 280 break; 281 default: 282 error = ENOTTY; 283 break; 284 } 285 286 return (error); 287 } 288 289 /* 290 * returns the packet, byte, rpf-failure count for the source group provided 291 */ 292 int 293 get_sg_cnt(unsigned int rtableid, struct sioc_sg_req *req) 294 { 295 struct rtentry *rt; 296 struct mfc *mfc; 297 298 rt = mfc_find(NULL, &req->src, &req->grp, rtableid); 299 if (rt == NULL) { 300 req->pktcnt = req->bytecnt = req->wrong_if = 0xffffffff; 301 return (EADDRNOTAVAIL); 302 } 303 304 req->pktcnt = req->bytecnt = req->wrong_if = 0; 305 do { 306 /* Don't consider non multicast routes. */ 307 if (ISSET(rt->rt_flags, RTF_HOST | RTF_MULTICAST) != 308 (RTF_HOST | RTF_MULTICAST)) 309 continue; 310 311 mfc = (struct mfc *)rt->rt_llinfo; 312 if (mfc == NULL) 313 continue; 314 315 req->pktcnt += mfc->mfc_pkt_cnt; 316 req->bytecnt += mfc->mfc_byte_cnt; 317 req->wrong_if += mfc->mfc_wrong_if; 318 } while ((rt = rtable_iterate(rt)) != NULL); 319 320 return (0); 321 } 322 323 /* 324 * returns the input and output packet and byte counts on the vif provided 325 */ 326 int 327 get_vif_cnt(unsigned int rtableid, struct sioc_vif_req *req) 328 { 329 struct ifnet *ifp; 330 struct vif *v; 331 vifi_t vifi = req->vifi; 332 333 if ((ifp = if_lookupbyvif(vifi, rtableid)) == NULL) 334 return (EINVAL); 335 336 v = (struct vif *)ifp->if_mcast; 337 req->icount = v->v_pkt_in; 338 req->ocount = v->v_pkt_out; 339 req->ibytes = v->v_bytes_in; 340 req->obytes = v->v_bytes_out; 341 342 return (0); 343 } 344 345 int 346 mrt_sysctl_vif(void *oldp, size_t *oldlenp) 347 { 348 caddr_t where = oldp; 349 size_t needed, given; 350 struct ifnet *ifp; 351 struct vif *vifp; 352 struct vifinfo vinfo; 353 354 given = *oldlenp; 355 needed = 0; 356 memset(&vinfo, 0, sizeof vinfo); 357 TAILQ_FOREACH(ifp, &ifnet, if_list) { 358 if ((vifp = (struct vif *)ifp->if_mcast) == NULL) 359 continue; 360 361 vinfo.v_vifi = vifp->v_id; 362 vinfo.v_flags = vifp->v_flags; 363 vinfo.v_threshold = vifp->v_threshold; 364 vinfo.v_lcl_addr = vifp->v_lcl_addr; 365 vinfo.v_rmt_addr = vifp->v_rmt_addr; 366 vinfo.v_pkt_in = vifp->v_pkt_in; 367 vinfo.v_pkt_out = vifp->v_pkt_out; 368 vinfo.v_bytes_in = vifp->v_bytes_in; 369 vinfo.v_bytes_out = vifp->v_bytes_out; 370 371 needed += sizeof(vinfo); 372 if (where && needed <= given) { 373 int error; 374 375 error = copyout(&vinfo, where, sizeof(vinfo)); 376 if (error) 377 return (error); 378 where += sizeof(vinfo); 379 } 380 } 381 if (where) { 382 *oldlenp = needed; 383 if (given < needed) 384 return (ENOMEM); 385 } else 386 *oldlenp = (11 * needed) / 10; 387 388 return (0); 389 } 390 391 struct mfcsysctlarg { 392 struct mfcinfo *msa_minfos; 393 size_t msa_len; 394 size_t msa_needed; 395 }; 396 397 int 398 mrt_rtwalk_mfcsysctl(struct rtentry *rt, void *arg, unsigned int rtableid) 399 { 400 struct mfc *mfc = (struct mfc *)rt->rt_llinfo; 401 struct mfcsysctlarg *msa = (struct mfcsysctlarg *)arg; 402 struct ifnet *ifp; 403 struct vif *v; 404 struct mfcinfo *minfo; 405 int new = 0; 406 407 /* Skip entries being removed. */ 408 if (mfc == NULL) 409 return (0); 410 411 /* Skip non-multicast routes. */ 412 if (ISSET(rt->rt_flags, RTF_HOST | RTF_MULTICAST) != 413 (RTF_HOST | RTF_MULTICAST)) 414 return (0); 415 416 /* User just asked for the output size. */ 417 if (msa->msa_minfos == NULL) { 418 msa->msa_needed += sizeof(*minfo); 419 return (0); 420 } 421 422 /* Skip route with invalid interfaces. */ 423 if ((ifp = if_get(rt->rt_ifidx)) == NULL) 424 return (0); 425 if ((v = (struct vif *)ifp->if_mcast) == NULL) { 426 if_put(ifp); 427 return (0); 428 } 429 430 for (minfo = msa->msa_minfos; 431 (uint8_t *)minfo < ((uint8_t *)msa->msa_minfos + msa->msa_len); 432 minfo++) { 433 /* Find a new entry or update old entry. */ 434 if (minfo->mfc_origin.s_addr != 435 satosin(rt->rt_gateway)->sin_addr.s_addr || 436 minfo->mfc_mcastgrp.s_addr != 437 satosin(rt_key(rt))->sin_addr.s_addr) { 438 if (minfo->mfc_origin.s_addr != 0 || 439 minfo->mfc_mcastgrp.s_addr != 0) 440 continue; 441 442 new = 1; 443 } 444 445 minfo->mfc_origin = satosin(rt->rt_gateway)->sin_addr; 446 minfo->mfc_mcastgrp = satosin(rt_key(rt))->sin_addr; 447 minfo->mfc_parent = mfc->mfc_parent; 448 minfo->mfc_pkt_cnt += mfc->mfc_pkt_cnt; 449 minfo->mfc_byte_cnt += mfc->mfc_byte_cnt; 450 minfo->mfc_ttls[v->v_id] = mfc->mfc_ttl; 451 break; 452 } 453 454 if (new != 0) 455 msa->msa_needed += sizeof(*minfo); 456 457 if_put(ifp); 458 459 return (0); 460 } 461 462 int 463 mrt_sysctl_mfc(void *oldp, size_t *oldlenp) 464 { 465 unsigned int rtableid; 466 int error; 467 struct mfcsysctlarg msa; 468 469 if (oldp != NULL && *oldlenp > MAXPHYS) 470 return (EINVAL); 471 472 if (oldp != NULL) 473 msa.msa_minfos = malloc(*oldlenp, M_TEMP, M_WAITOK | M_ZERO); 474 else 475 msa.msa_minfos = NULL; 476 477 msa.msa_len = *oldlenp; 478 msa.msa_needed = 0; 479 480 for (rtableid = 0; rtableid <= RT_TABLEID_MAX; rtableid++) { 481 rtable_walk(rtableid, AF_INET, NULL, mrt_rtwalk_mfcsysctl, 482 &msa); 483 } 484 485 if (msa.msa_minfos != NULL && msa.msa_needed > 0 && 486 (error = copyout(msa.msa_minfos, oldp, msa.msa_needed)) != 0) { 487 free(msa.msa_minfos, M_TEMP, *oldlenp); 488 return (error); 489 } 490 491 free(msa.msa_minfos, M_TEMP, *oldlenp); 492 *oldlenp = msa.msa_needed; 493 494 return (0); 495 } 496 497 /* 498 * Enable multicast routing 499 */ 500 int 501 ip_mrouter_init(struct socket *so, struct mbuf *m) 502 { 503 struct inpcb *inp = sotoinpcb(so); 504 unsigned int rtableid = inp->inp_rtableid; 505 int *v; 506 507 if (so->so_type != SOCK_RAW || 508 so->so_proto->pr_protocol != IPPROTO_IGMP) 509 return (EOPNOTSUPP); 510 511 if (m == NULL || m->m_len < sizeof(int)) 512 return (EINVAL); 513 514 v = mtod(m, int *); 515 if (*v != 1) 516 return (EINVAL); 517 518 if (ip_mrouter[rtableid] != NULL || 519 mrouterq[rtableid] != NULL) 520 return (EADDRINUSE); 521 522 ip_mrouter[rtableid] = so; 523 mrouterq[rtableid] = rt_timer_queue_create(MCAST_EXPIRE_FREQUENCY); 524 525 return (0); 526 } 527 528 int 529 mrouter_rtwalk_delete(struct rtentry *rt, void *arg, unsigned int rtableid) 530 { 531 /* Skip non-multicast routes. */ 532 if (ISSET(rt->rt_flags, RTF_HOST | RTF_MULTICAST) != 533 (RTF_HOST | RTF_MULTICAST)) 534 return (0); 535 536 return EEXIST; 537 } 538 539 /* 540 * Disable multicast routing 541 */ 542 int 543 ip_mrouter_done(struct socket *so) 544 { 545 struct inpcb *inp = sotoinpcb(so); 546 struct ifnet *ifp; 547 unsigned int rtableid = inp->inp_rtableid; 548 int error; 549 550 NET_ASSERT_LOCKED(); 551 552 /* Delete all remaining installed multicast routes. */ 553 do { 554 struct rtentry *rt = NULL; 555 556 error = rtable_walk(rtableid, AF_INET, &rt, 557 mrouter_rtwalk_delete, NULL); 558 if (rt != NULL && error == EEXIST) { 559 mrt_mcast_del(rt, rtableid); 560 error = EAGAIN; 561 } 562 rtfree(rt); 563 } while (error == EAGAIN); 564 565 /* Unregister all interfaces in the domain. */ 566 TAILQ_FOREACH(ifp, &ifnet, if_list) { 567 if (ifp->if_rdomain != rtableid) 568 continue; 569 570 vif_delete(ifp); 571 } 572 573 mrt_api_config = 0; 574 575 rt_timer_queue_destroy(mrouterq[rtableid]); 576 mrouterq[rtableid] = NULL; 577 ip_mrouter[rtableid] = NULL; 578 mrt_count[rtableid] = 0; 579 580 return (0); 581 } 582 583 int 584 get_version(struct mbuf *m) 585 { 586 int *v = mtod(m, int *); 587 588 *v = 0x0305; /* XXX !!!! */ 589 m->m_len = sizeof(int); 590 return (0); 591 } 592 593 /* 594 * Configure API capabilities 595 */ 596 int 597 set_api_config(struct socket *so, struct mbuf *m) 598 { 599 struct inpcb *inp = sotoinpcb(so); 600 struct ifnet *ifp; 601 u_int32_t *apival; 602 unsigned int rtableid = inp->inp_rtableid; 603 604 if (m == NULL || m->m_len < sizeof(u_int32_t)) 605 return (EINVAL); 606 607 apival = mtod(m, u_int32_t *); 608 609 /* 610 * We can set the API capabilities only if it is the first operation 611 * after MRT_INIT. I.e.: 612 * - there are no vifs installed 613 * - the MFC table is empty 614 */ 615 TAILQ_FOREACH(ifp, &ifnet, if_list) { 616 if (ifp->if_rdomain != rtableid) 617 continue; 618 if (ifp->if_mcast == NULL) 619 continue; 620 621 *apival = 0; 622 return (EPERM); 623 } 624 if (mrt_count[rtableid] > 0) { 625 *apival = 0; 626 return (EPERM); 627 } 628 629 mrt_api_config = *apival & mrt_api_support; 630 *apival = mrt_api_config; 631 632 return (0); 633 } 634 635 /* 636 * Get API capabilities 637 */ 638 int 639 get_api_support(struct mbuf *m) 640 { 641 u_int32_t *apival; 642 643 if (m == NULL || m->m_len < sizeof(u_int32_t)) 644 return (EINVAL); 645 646 apival = mtod(m, u_int32_t *); 647 648 *apival = mrt_api_support; 649 650 return (0); 651 } 652 653 /* 654 * Get API configured capabilities 655 */ 656 int 657 get_api_config(struct mbuf *m) 658 { 659 u_int32_t *apival; 660 661 if (m == NULL || m->m_len < sizeof(u_int32_t)) 662 return (EINVAL); 663 664 apival = mtod(m, u_int32_t *); 665 666 *apival = mrt_api_config; 667 668 return (0); 669 } 670 671 static struct sockaddr_in sin = { sizeof(sin), AF_INET }; 672 673 int 674 add_vif(struct socket *so, struct mbuf *m) 675 { 676 struct inpcb *inp = sotoinpcb(so); 677 struct vifctl *vifcp; 678 struct vif *vifp; 679 struct ifaddr *ifa; 680 struct ifnet *ifp; 681 struct ifreq ifr; 682 int error; 683 unsigned int rtableid = inp->inp_rtableid; 684 685 NET_ASSERT_LOCKED(); 686 687 if (m == NULL || m->m_len < sizeof(struct vifctl)) 688 return (EINVAL); 689 690 vifcp = mtod(m, struct vifctl *); 691 if (vifcp->vifc_vifi >= MAXVIFS) 692 return (EINVAL); 693 if (in_nullhost(vifcp->vifc_lcl_addr)) 694 return (EADDRNOTAVAIL); 695 if (if_lookupbyvif(vifcp->vifc_vifi, rtableid) != NULL) 696 return (EADDRINUSE); 697 698 /* Tunnels are no longer supported use gif(4) instead. */ 699 if (vifcp->vifc_flags & VIFF_TUNNEL) 700 return (EOPNOTSUPP); 701 { 702 sin.sin_addr = vifcp->vifc_lcl_addr; 703 ifa = ifa_ifwithaddr(sintosa(&sin), rtableid); 704 if (ifa == NULL) 705 return (EADDRNOTAVAIL); 706 } 707 708 /* Use the physical interface associated with the address. */ 709 ifp = ifa->ifa_ifp; 710 if (ifp->if_mcast != NULL) 711 return (EADDRINUSE); 712 713 { 714 /* Make sure the interface supports multicast. */ 715 if ((ifp->if_flags & IFF_MULTICAST) == 0) 716 return (EOPNOTSUPP); 717 718 /* Enable promiscuous reception of all IP multicasts. */ 719 memset(&ifr, 0, sizeof(ifr)); 720 satosin(&ifr.ifr_addr)->sin_len = sizeof(struct sockaddr_in); 721 satosin(&ifr.ifr_addr)->sin_family = AF_INET; 722 satosin(&ifr.ifr_addr)->sin_addr = zeroin_addr; 723 error = (*ifp->if_ioctl)(ifp, SIOCADDMULTI, (caddr_t)&ifr); 724 if (error) 725 return (error); 726 } 727 728 vifp = malloc(sizeof(*vifp), M_MRTABLE, M_WAITOK | M_ZERO); 729 ifp->if_mcast = (caddr_t)vifp; 730 731 vifp->v_id = vifcp->vifc_vifi; 732 vifp->v_flags = vifcp->vifc_flags; 733 vifp->v_threshold = vifcp->vifc_threshold; 734 vifp->v_lcl_addr = vifcp->vifc_lcl_addr; 735 vifp->v_rmt_addr = vifcp->vifc_rmt_addr; 736 737 return (0); 738 } 739 740 int 741 del_vif(struct socket *so, struct mbuf *m) 742 { 743 struct inpcb *inp = sotoinpcb(so); 744 struct ifnet *ifp; 745 vifi_t *vifip; 746 unsigned int rtableid = inp->inp_rtableid; 747 748 NET_ASSERT_LOCKED(); 749 750 if (m == NULL || m->m_len < sizeof(vifi_t)) 751 return (EINVAL); 752 753 vifip = mtod(m, vifi_t *); 754 if ((ifp = if_lookupbyvif(*vifip, rtableid)) == NULL) 755 return (EADDRNOTAVAIL); 756 757 vif_delete(ifp); 758 return (0); 759 } 760 761 void 762 vif_delete(struct ifnet *ifp) 763 { 764 struct vif *v; 765 struct ifreq ifr; 766 767 if ((v = (struct vif *)ifp->if_mcast) == NULL) 768 return; 769 770 ifp->if_mcast = NULL; 771 772 memset(&ifr, 0, sizeof(ifr)); 773 satosin(&ifr.ifr_addr)->sin_len = sizeof(struct sockaddr_in); 774 satosin(&ifr.ifr_addr)->sin_family = AF_INET; 775 satosin(&ifr.ifr_addr)->sin_addr = zeroin_addr; 776 KERNEL_LOCK(); 777 (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr); 778 KERNEL_UNLOCK(); 779 780 free(v, M_MRTABLE, sizeof(*v)); 781 } 782 783 void 784 mfc_expire_route(struct rtentry *rt, struct rttimer *rtt) 785 { 786 struct mfc *mfc = (struct mfc *)rt->rt_llinfo; 787 unsigned int rtableid = rtt->rtt_tableid; 788 789 /* Skip entry being deleted. */ 790 if (mfc == NULL) 791 return; 792 793 DPRINTF("Route domain %d origin %#08X group %#08x interface %d " 794 "expire %s", rtt->rtt_tableid, 795 satosin(rt->rt_gateway)->sin_addr.s_addr, 796 satosin(rt_key(rt))->sin_addr.s_addr, 797 rt->rt_ifidx, mfc->mfc_expire ? "yes" : "no"); 798 799 /* Not expired, add it back to the queue. */ 800 if (mfc->mfc_expire == 0) { 801 mfc->mfc_expire = 1; 802 rt_timer_add(rt, mfc_expire_route, mrouterq[rtableid], 803 rtableid); 804 return; 805 } 806 807 mrt_mcast_del(rt, rtableid); 808 } 809 810 int 811 mfc_add_route(struct ifnet *ifp, struct sockaddr *origin, 812 struct sockaddr *group, struct mfcctl2 *mfccp, int wait) 813 { 814 struct vif *v = (struct vif *)ifp->if_mcast; 815 struct rtentry *rt; 816 struct mfc *mfc; 817 unsigned int rtableid = ifp->if_rdomain; 818 819 rt = rt_mcast_add(ifp, origin, group); 820 if (rt == NULL) 821 return (EHOSTUNREACH); 822 823 mfc = malloc(sizeof(*mfc), M_MRTABLE, wait | M_ZERO); 824 if (mfc == NULL) { 825 DPRINTF("origin %#08X group %#08X parent %d (%s) " 826 "malloc failed", 827 satosin(origin)->sin_addr.s_addr, 828 satosin(group)->sin_addr.s_addr, 829 mfccp->mfcc_parent, ifp->if_xname); 830 mrt_mcast_del(rt, rtableid); 831 rtfree(rt); 832 return (ENOMEM); 833 } 834 835 rt->rt_llinfo = (caddr_t)mfc; 836 837 rt_timer_add(rt, mfc_expire_route, mrouterq[rtableid], 838 rtableid); 839 840 mfc->mfc_parent = mfccp->mfcc_parent; 841 mfc->mfc_pkt_cnt = 0; 842 mfc->mfc_byte_cnt = 0; 843 mfc->mfc_wrong_if = 0; 844 mfc->mfc_ttl = mfccp->mfcc_ttls[v->v_id]; 845 mfc->mfc_flags = mfccp->mfcc_flags[v->v_id] & mrt_api_config & 846 MRT_MFC_FLAGS_ALL; 847 mfc->mfc_expire = 0; 848 849 /* set the RP address */ 850 if (mrt_api_config & MRT_MFC_RP) 851 mfc->mfc_rp = mfccp->mfcc_rp; 852 else 853 mfc->mfc_rp = zeroin_addr; 854 855 rtfree(rt); 856 857 return (0); 858 } 859 860 void 861 update_mfc_params(struct mfcctl2 *mfccp, int wait, unsigned int rtableid) 862 { 863 struct rtentry *rt; 864 struct mfc *mfc; 865 struct ifnet *ifp; 866 int i; 867 struct sockaddr_in osin, msin; 868 869 memset(&osin, 0, sizeof(osin)); 870 osin.sin_len = sizeof(osin); 871 osin.sin_family = AF_INET; 872 osin.sin_addr = mfccp->mfcc_origin; 873 874 memset(&msin, 0, sizeof(msin)); 875 msin.sin_len = sizeof(msin); 876 msin.sin_family = AF_INET; 877 msin.sin_addr = mfccp->mfcc_mcastgrp; 878 879 for (i = 0; i < MAXVIFS; i++) { 880 /* Don't add/del upstream routes here. */ 881 if (i == mfccp->mfcc_parent) 882 continue; 883 884 /* Test for vif existence and then update the entry. */ 885 if ((ifp = if_lookupbyvif(i, rtableid)) == NULL) 886 continue; 887 888 rt = mfc_find(ifp, &mfccp->mfcc_origin, 889 &mfccp->mfcc_mcastgrp, rtableid); 890 891 /* vif not configured or removed. */ 892 if (mfccp->mfcc_ttls[i] == 0) { 893 /* Route doesn't exist, nothing to do. */ 894 if (rt == NULL) 895 continue; 896 897 DPRINTF("del route (group %#08X) for vif %d (%s)", 898 mfccp->mfcc_mcastgrp.s_addr, i, ifp->if_xname); 899 mrt_mcast_del(rt, rtableid); 900 rtfree(rt); 901 continue; 902 } 903 904 /* Route exists, look for changes. */ 905 if (rt != NULL) { 906 mfc = (struct mfc *)rt->rt_llinfo; 907 /* Skip route being deleted. */ 908 if (mfc == NULL) { 909 rtfree(rt); 910 continue; 911 } 912 913 /* No new changes to apply. */ 914 if (mfccp->mfcc_ttls[i] == mfc->mfc_ttl && 915 mfccp->mfcc_parent == mfc->mfc_parent) { 916 rtfree(rt); 917 continue; 918 } 919 920 DPRINTF("update route (group %#08X) for vif %d (%s)", 921 mfccp->mfcc_mcastgrp.s_addr, i, ifp->if_xname); 922 mfc->mfc_ttl = mfccp->mfcc_ttls[i]; 923 mfc->mfc_parent = mfccp->mfcc_parent; 924 rtfree(rt); 925 continue; 926 } 927 928 DPRINTF("add route (group %#08X) for vif %d (%s)", 929 mfccp->mfcc_mcastgrp.s_addr, i, ifp->if_xname); 930 931 mfc_add_route(ifp, sintosa(&osin), sintosa(&msin), 932 mfccp, wait); 933 } 934 935 /* Create route for the parent interface. */ 936 if ((ifp = if_lookupbyvif(mfccp->mfcc_parent, rtableid)) == NULL) { 937 DPRINTF("failed to find upstream interface %d", 938 mfccp->mfcc_parent); 939 return; 940 } 941 942 /* We already have a route, nothing to do here. */ 943 if ((rt = mfc_find(ifp, &mfccp->mfcc_origin, 944 &mfccp->mfcc_mcastgrp, rtableid)) != NULL) { 945 rtfree(rt); 946 return; 947 } 948 949 DPRINTF("add upstream route (group %#08X) for if %s", 950 mfccp->mfcc_mcastgrp.s_addr, ifp->if_xname); 951 mfc_add_route(ifp, sintosa(&osin), sintosa(&msin), mfccp, wait); 952 } 953 954 int 955 mfc_add(struct mfcctl2 *mfcctl2, struct in_addr *origin, 956 struct in_addr *group, int vidx, unsigned int rtableid, int wait) 957 { 958 struct ifnet *ifp; 959 struct vif *v; 960 struct mfcctl2 mfcctl; 961 962 ifp = if_lookupbyvif(vidx, rtableid); 963 if (ifp == NULL || 964 (v = (struct vif *)ifp->if_mcast) == NULL) 965 return (EHOSTUNREACH); 966 967 memset(&mfcctl, 0, sizeof(mfcctl)); 968 if (mfcctl2 == NULL) { 969 mfcctl.mfcc_origin = *origin; 970 mfcctl.mfcc_mcastgrp = *group; 971 mfcctl.mfcc_parent = vidx; 972 } else 973 memcpy(&mfcctl, mfcctl2, sizeof(mfcctl)); 974 975 update_mfc_params(&mfcctl, wait, rtableid); 976 977 return (0); 978 } 979 980 int 981 add_mfc(struct socket *so, struct mbuf *m) 982 { 983 struct inpcb *inp = sotoinpcb(so); 984 struct mfcctl2 mfcctl2; 985 int mfcctl_size = sizeof(struct mfcctl); 986 unsigned int rtableid = inp->inp_rtableid; 987 988 NET_ASSERT_LOCKED(); 989 990 if (mrt_api_config & MRT_API_FLAGS_ALL) 991 mfcctl_size = sizeof(struct mfcctl2); 992 993 if (m == NULL || m->m_len < mfcctl_size) 994 return (EINVAL); 995 996 /* 997 * select data size depending on API version. 998 */ 999 if (mrt_api_config & MRT_API_FLAGS_ALL) { 1000 struct mfcctl2 *mp2 = mtod(m, struct mfcctl2 *); 1001 memcpy((caddr_t)&mfcctl2, mp2, sizeof(*mp2)); 1002 } else { 1003 struct mfcctl *mp = mtod(m, struct mfcctl *); 1004 memcpy((caddr_t)&mfcctl2, mp, sizeof(*mp)); 1005 memset((caddr_t)&mfcctl2 + sizeof(struct mfcctl), 0, 1006 sizeof(mfcctl2) - sizeof(struct mfcctl)); 1007 } 1008 1009 if (mfc_add(&mfcctl2, &mfcctl2.mfcc_origin, &mfcctl2.mfcc_mcastgrp, 1010 mfcctl2.mfcc_parent, rtableid, M_WAITOK) == -1) 1011 return (EINVAL); 1012 1013 return (0); 1014 } 1015 1016 int 1017 del_mfc(struct socket *so, struct mbuf *m) 1018 { 1019 struct inpcb *inp = sotoinpcb(so); 1020 struct rtentry *rt; 1021 struct mfcctl2 mfcctl2; 1022 int mfcctl_size = sizeof(struct mfcctl); 1023 struct mfcctl *mp; 1024 unsigned int rtableid = inp->inp_rtableid; 1025 1026 NET_ASSERT_LOCKED(); 1027 1028 /* 1029 * XXX: for deleting MFC entries the information in entries 1030 * of size "struct mfcctl" is sufficient. 1031 */ 1032 1033 if (m == NULL || m->m_len < mfcctl_size) 1034 return (EINVAL); 1035 1036 mp = mtod(m, struct mfcctl *); 1037 1038 memcpy((caddr_t)&mfcctl2, mp, sizeof(*mp)); 1039 memset((caddr_t)&mfcctl2 + sizeof(struct mfcctl), 0, 1040 sizeof(mfcctl2) - sizeof(struct mfcctl)); 1041 1042 DPRINTF("origin %#08X group %#08X rtableid %d", 1043 mfcctl2.mfcc_origin.s_addr, mfcctl2.mfcc_mcastgrp.s_addr, rtableid); 1044 1045 while ((rt = mfc_find(NULL, &mfcctl2.mfcc_origin, 1046 &mfcctl2.mfcc_mcastgrp, rtableid)) != NULL) { 1047 mrt_mcast_del(rt, rtableid); 1048 rtfree(rt); 1049 } 1050 1051 return (0); 1052 } 1053 1054 int 1055 socket_send(struct socket *s, struct mbuf *mm, struct sockaddr_in *src) 1056 { 1057 if (s != NULL) { 1058 if (sbappendaddr(s, &s->so_rcv, sintosa(src), mm, NULL) != 0) { 1059 sorwakeup(s); 1060 return (0); 1061 } 1062 } 1063 m_freem(mm); 1064 return (-1); 1065 } 1066 1067 /* 1068 * IP multicast forwarding function. This function assumes that the packet 1069 * pointed to by "ip" has arrived on (or is about to be sent to) the interface 1070 * pointed to by "ifp", and the packet is to be relayed to other networks 1071 * that have members of the packet's destination IP multicast group. 1072 * 1073 * The packet is returned unscathed to the caller, unless it is 1074 * erroneous, in which case a non-zero return value tells the caller to 1075 * discard it. 1076 */ 1077 1078 #define IP_HDR_LEN 20 /* # bytes of fixed IP header (excluding options) */ 1079 #define TUNNEL_LEN 12 /* # bytes of IP option for tunnel encapsulation */ 1080 1081 int 1082 ip_mforward(struct mbuf *m, struct ifnet *ifp) 1083 { 1084 struct ip *ip = mtod(m, struct ip *); 1085 struct vif *v; 1086 struct rtentry *rt; 1087 static int srctun = 0; 1088 struct mbuf *mm; 1089 unsigned int rtableid = ifp->if_rdomain; 1090 1091 if (ip->ip_hl < (IP_HDR_LEN + TUNNEL_LEN) >> 2 || 1092 ((u_char *)(ip + 1))[1] != IPOPT_LSRR) { 1093 /* 1094 * Packet arrived via a physical interface or 1095 * an encapsulated tunnel or a register_vif. 1096 */ 1097 } else { 1098 /* 1099 * Packet arrived through a source-route tunnel. 1100 * Source-route tunnels are no longer supported. 1101 */ 1102 if ((srctun++ % 1000) == 0) 1103 log(LOG_ERR, "ip_mforward: received source-routed " 1104 "packet from %x\n", ntohl(ip->ip_src.s_addr)); 1105 return (EOPNOTSUPP); 1106 } 1107 1108 /* 1109 * Don't forward a packet with time-to-live of zero or one, 1110 * or a packet destined to a local-only group. 1111 */ 1112 if (ip->ip_ttl <= 1 || IN_LOCAL_GROUP(ip->ip_dst.s_addr)) 1113 return (0); 1114 1115 /* 1116 * Determine forwarding vifs from the forwarding cache table 1117 */ 1118 ++mrtstat.mrts_mfc_lookups; 1119 rt = mfc_find(NULL, &ip->ip_src, &ip->ip_dst, rtableid); 1120 1121 /* Entry exists, so forward if necessary */ 1122 if (rt != NULL) { 1123 return (ip_mdq(m, ifp, rt)); 1124 } else { 1125 /* 1126 * If we don't have a route for packet's origin, 1127 * Make a copy of the packet & send message to routing daemon 1128 */ 1129 int hlen = ip->ip_hl << 2; 1130 1131 ++mrtstat.mrts_mfc_misses; 1132 mrtstat.mrts_no_route++; 1133 1134 { 1135 struct igmpmsg *im; 1136 1137 /* 1138 * Locate the vifi for the incoming interface for 1139 * this packet. 1140 * If none found, drop packet. 1141 */ 1142 if ((v = (struct vif *)ifp->if_mcast) == NULL) 1143 return (EHOSTUNREACH); 1144 /* 1145 * Make a copy of the header to send to the user level 1146 * process 1147 */ 1148 mm = m_copym(m, 0, hlen, M_NOWAIT); 1149 if (mm == NULL || 1150 (mm = m_pullup(mm, hlen)) == NULL) 1151 return (ENOBUFS); 1152 1153 /* 1154 * Send message to routing daemon to install 1155 * a route into the kernel table 1156 */ 1157 1158 im = mtod(mm, struct igmpmsg *); 1159 im->im_msgtype = IGMPMSG_NOCACHE; 1160 im->im_mbz = 0; 1161 im->im_vif = v->v_id; 1162 1163 mrtstat.mrts_upcalls++; 1164 1165 sin.sin_addr = ip->ip_src; 1166 if (socket_send(ip_mrouter[rtableid], mm, &sin) < 0) { 1167 log(LOG_WARNING, "ip_mforward: ip_mrouter " 1168 "socket queue full\n"); 1169 ++mrtstat.mrts_upq_sockfull; 1170 return (ENOBUFS); 1171 } 1172 1173 mfc_add(NULL, &ip->ip_src, &ip->ip_dst, v->v_id, 1174 rtableid, M_NOWAIT); 1175 } 1176 1177 return (0); 1178 } 1179 } 1180 1181 /* 1182 * Packet forwarding routine once entry in the cache is made 1183 */ 1184 int 1185 ip_mdq(struct mbuf *m, struct ifnet *ifp0, struct rtentry *rt) 1186 { 1187 struct ip *ip = mtod(m, struct ip *); 1188 struct mfc *mfc = (struct mfc *)rt->rt_llinfo; 1189 struct vif *v = (struct vif *)ifp0->if_mcast; 1190 struct ifnet *ifp; 1191 struct mbuf *mc; 1192 struct ip_moptions imo; 1193 1194 /* Sanity check: we have all promised pointers. */ 1195 if (v == NULL || mfc == NULL) { 1196 rtfree(rt); 1197 return (EHOSTUNREACH); 1198 } 1199 1200 /* 1201 * Don't forward if it didn't arrive from the parent vif for its origin. 1202 */ 1203 if (mfc->mfc_parent != v->v_id) { 1204 /* came in the wrong interface */ 1205 ++mrtstat.mrts_wrong_if; 1206 mfc->mfc_wrong_if++; 1207 rtfree(rt); 1208 return (0); 1209 } 1210 1211 /* If I sourced this packet, it counts as output, else it was input. */ 1212 if (in_hosteq(ip->ip_src, v->v_lcl_addr)) { 1213 v->v_pkt_out++; 1214 v->v_bytes_out += m->m_pkthdr.len; 1215 } else { 1216 v->v_pkt_in++; 1217 v->v_bytes_in += m->m_pkthdr.len; 1218 } 1219 1220 /* 1221 * For each vif, decide if a copy of the packet should be forwarded. 1222 * Forward if: 1223 * - the ttl exceeds the vif's threshold 1224 * - there are group members downstream on interface 1225 */ 1226 do { 1227 /* Don't consider non multicast routes. */ 1228 if (ISSET(rt->rt_flags, RTF_HOST | RTF_MULTICAST) != 1229 (RTF_HOST | RTF_MULTICAST)) 1230 continue; 1231 1232 mfc = (struct mfc *)rt->rt_llinfo; 1233 if (mfc == NULL) 1234 continue; 1235 1236 mfc->mfc_pkt_cnt++; 1237 mfc->mfc_byte_cnt += m->m_pkthdr.len; 1238 1239 /* Don't let this route expire. */ 1240 mfc->mfc_expire = 0; 1241 1242 if (ip->ip_ttl <= mfc->mfc_ttl) 1243 continue; 1244 if ((ifp = if_get(rt->rt_ifidx)) == NULL) 1245 continue; 1246 1247 /* Sanity check: did we configure this? */ 1248 if ((v = (struct vif *)ifp->if_mcast) == NULL) { 1249 if_put(ifp); 1250 continue; 1251 } 1252 1253 /* Don't send in the upstream interface. */ 1254 if (mfc->mfc_parent == v->v_id) { 1255 if_put(ifp); 1256 continue; 1257 } 1258 1259 v->v_pkt_out++; 1260 v->v_bytes_out += m->m_pkthdr.len; 1261 1262 /* 1263 * Make a new reference to the packet; make sure 1264 * that the IP header is actually copied, not 1265 * just referenced, so that ip_output() only 1266 * scribbles on the copy. 1267 */ 1268 mc = m_dup_pkt(m, max_linkhdr, M_NOWAIT); 1269 if (mc == NULL) { 1270 if_put(ifp); 1271 rtfree(rt); 1272 return (ENOBUFS); 1273 } 1274 1275 /* 1276 * if physical interface option, extract the options 1277 * and then send 1278 */ 1279 imo.imo_ifidx = rt->rt_ifidx; 1280 imo.imo_ttl = ip->ip_ttl - IPTTLDEC; 1281 imo.imo_loop = 1; 1282 1283 ip_output(mc, NULL, NULL, IP_FORWARDING, &imo, NULL, 0); 1284 if_put(ifp); 1285 } while ((rt = rtable_iterate(rt)) != NULL); 1286 1287 return (0); 1288 } 1289 1290 struct ifnet * 1291 if_lookupbyvif(vifi_t vifi, unsigned int rtableid) 1292 { 1293 struct vif *v; 1294 struct ifnet *ifp; 1295 1296 TAILQ_FOREACH(ifp, &ifnet, if_list) { 1297 if (ifp->if_rdomain != rtableid) 1298 continue; 1299 if ((v = (struct vif *)ifp->if_mcast) == NULL) 1300 continue; 1301 if (v->v_id != vifi) 1302 continue; 1303 1304 return (ifp); 1305 } 1306 1307 return (NULL); 1308 } 1309 1310 struct rtentry * 1311 rt_mcast_add(struct ifnet *ifp, struct sockaddr *origin, struct sockaddr *group) 1312 { 1313 struct ifaddr *ifa; 1314 int rv; 1315 unsigned int rtableid = ifp->if_rdomain; 1316 1317 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { 1318 if (ifa->ifa_addr->sa_family == AF_INET) 1319 break; 1320 } 1321 if (ifa == NULL) { 1322 DPRINTF("ifa == NULL"); 1323 return (NULL); 1324 } 1325 1326 rv = rt_ifa_add(ifa, RTF_HOST | RTF_MULTICAST | RTF_MPATH, 1327 group, ifp->if_rdomain); 1328 if (rv != 0) { 1329 DPRINTF("rt_ifa_add failed (%d)", rv); 1330 return (NULL); 1331 } 1332 1333 mrt_count[rtableid]++; 1334 1335 return (mfc_find(ifp, NULL, &satosin(group)->sin_addr, rtableid)); 1336 } 1337 1338 void 1339 mrt_mcast_del(struct rtentry *rt, unsigned int rtableid) 1340 { 1341 struct ifnet *ifp; 1342 int error; 1343 1344 /* Remove all timers related to this route. */ 1345 rt_timer_remove_all(rt); 1346 1347 free(rt->rt_llinfo, M_MRTABLE, sizeof(struct mfc)); 1348 rt->rt_llinfo = NULL; 1349 1350 ifp = if_get(rt->rt_ifidx); 1351 if (ifp == NULL) 1352 return; 1353 error = rtdeletemsg(rt, ifp, rtableid); 1354 if_put(ifp); 1355 1356 if (error) 1357 DPRINTF("delete route error %d\n", error); 1358 1359 mrt_count[rtableid]--; 1360 } 1361