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