1 /* $OpenBSD: ip_mroute.c,v 1.140 2023/12/06 09:27:17 bluhm 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 KERNEL_LOCK(); 722 error = (*ifp->if_ioctl)(ifp, SIOCADDMULTI, (caddr_t)&ifr); 723 KERNEL_UNLOCK(); 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, u_int rtableid) 785 { 786 struct mfc *mfc = (struct mfc *)rt->rt_llinfo; 787 788 /* Skip entry being deleted. */ 789 if (mfc == NULL) 790 return; 791 792 DPRINTF("Route domain %d origin %#08X group %#08x interface %d " 793 "expire %s", rtableid, satosin(rt->rt_gateway)->sin_addr.s_addr, 794 satosin(rt_key(rt))->sin_addr.s_addr, 795 rt->rt_ifidx, mfc->mfc_expire ? "yes" : "no"); 796 797 /* Not expired, add it back to the queue. */ 798 if (mfc->mfc_expire == 0) { 799 mfc->mfc_expire = 1; 800 rt_timer_add(rt, &ip_mrouterq, rtableid); 801 return; 802 } 803 804 mrt_mcast_del(rt, rtableid); 805 } 806 807 int 808 mfc_add_route(struct ifnet *ifp, struct sockaddr *origin, 809 struct sockaddr *group, struct mfcctl2 *mfccp, int wait) 810 { 811 struct vif *v = (struct vif *)ifp->if_mcast; 812 struct rtentry *rt; 813 struct mfc *mfc; 814 unsigned int rtableid = ifp->if_rdomain; 815 816 rt = rt_mcast_add(ifp, origin, group); 817 if (rt == NULL) 818 return (EHOSTUNREACH); 819 820 mfc = malloc(sizeof(*mfc), M_MRTABLE, wait | M_ZERO); 821 if (mfc == NULL) { 822 DPRINTF("origin %#08X group %#08X parent %d (%s) " 823 "malloc failed", 824 satosin(origin)->sin_addr.s_addr, 825 satosin(group)->sin_addr.s_addr, 826 mfccp->mfcc_parent, ifp->if_xname); 827 mrt_mcast_del(rt, rtableid); 828 rtfree(rt); 829 return (ENOMEM); 830 } 831 832 rt->rt_llinfo = (caddr_t)mfc; 833 834 rt_timer_add(rt, &ip_mrouterq, rtableid); 835 836 mfc->mfc_parent = mfccp->mfcc_parent; 837 mfc->mfc_pkt_cnt = 0; 838 mfc->mfc_byte_cnt = 0; 839 mfc->mfc_wrong_if = 0; 840 mfc->mfc_ttl = mfccp->mfcc_ttls[v->v_id]; 841 mfc->mfc_flags = mfccp->mfcc_flags[v->v_id] & mrt_api_config & 842 MRT_MFC_FLAGS_ALL; 843 mfc->mfc_expire = 0; 844 845 /* set the RP address */ 846 if (mrt_api_config & MRT_MFC_RP) 847 mfc->mfc_rp = mfccp->mfcc_rp; 848 else 849 mfc->mfc_rp = zeroin_addr; 850 851 rtfree(rt); 852 853 return (0); 854 } 855 856 void 857 update_mfc_params(struct mfcctl2 *mfccp, int wait, unsigned int rtableid) 858 { 859 struct rtentry *rt; 860 struct mfc *mfc; 861 struct ifnet *ifp; 862 int i; 863 struct sockaddr_in osin, msin; 864 865 memset(&osin, 0, sizeof(osin)); 866 osin.sin_len = sizeof(osin); 867 osin.sin_family = AF_INET; 868 osin.sin_addr = mfccp->mfcc_origin; 869 870 memset(&msin, 0, sizeof(msin)); 871 msin.sin_len = sizeof(msin); 872 msin.sin_family = AF_INET; 873 msin.sin_addr = mfccp->mfcc_mcastgrp; 874 875 for (i = 0; i < MAXVIFS; i++) { 876 /* Don't add/del upstream routes here. */ 877 if (i == mfccp->mfcc_parent) 878 continue; 879 880 /* Test for vif existence and then update the entry. */ 881 if ((ifp = if_lookupbyvif(i, rtableid)) == NULL) 882 continue; 883 884 rt = mfc_find(ifp, &mfccp->mfcc_origin, 885 &mfccp->mfcc_mcastgrp, rtableid); 886 887 /* vif not configured or removed. */ 888 if (mfccp->mfcc_ttls[i] == 0) { 889 /* Route doesn't exist, nothing to do. */ 890 if (rt == NULL) 891 continue; 892 893 DPRINTF("del route (group %#08X) for vif %d (%s)", 894 mfccp->mfcc_mcastgrp.s_addr, i, ifp->if_xname); 895 mrt_mcast_del(rt, rtableid); 896 rtfree(rt); 897 continue; 898 } 899 900 /* Route exists, look for changes. */ 901 if (rt != NULL) { 902 mfc = (struct mfc *)rt->rt_llinfo; 903 /* Skip route being deleted. */ 904 if (mfc == NULL) { 905 rtfree(rt); 906 continue; 907 } 908 909 /* No new changes to apply. */ 910 if (mfccp->mfcc_ttls[i] == mfc->mfc_ttl && 911 mfccp->mfcc_parent == mfc->mfc_parent) { 912 rtfree(rt); 913 continue; 914 } 915 916 DPRINTF("update route (group %#08X) for vif %d (%s)", 917 mfccp->mfcc_mcastgrp.s_addr, i, ifp->if_xname); 918 mfc->mfc_ttl = mfccp->mfcc_ttls[i]; 919 mfc->mfc_parent = mfccp->mfcc_parent; 920 rtfree(rt); 921 continue; 922 } 923 924 DPRINTF("add route (group %#08X) for vif %d (%s)", 925 mfccp->mfcc_mcastgrp.s_addr, i, ifp->if_xname); 926 927 mfc_add_route(ifp, sintosa(&osin), sintosa(&msin), 928 mfccp, wait); 929 } 930 931 /* Create route for the parent interface. */ 932 if ((ifp = if_lookupbyvif(mfccp->mfcc_parent, rtableid)) == NULL) { 933 DPRINTF("failed to find upstream interface %d", 934 mfccp->mfcc_parent); 935 return; 936 } 937 938 /* We already have a route, nothing to do here. */ 939 if ((rt = mfc_find(ifp, &mfccp->mfcc_origin, 940 &mfccp->mfcc_mcastgrp, rtableid)) != NULL) { 941 rtfree(rt); 942 return; 943 } 944 945 DPRINTF("add upstream route (group %#08X) for if %s", 946 mfccp->mfcc_mcastgrp.s_addr, ifp->if_xname); 947 mfc_add_route(ifp, sintosa(&osin), sintosa(&msin), mfccp, wait); 948 } 949 950 int 951 mfc_add(struct mfcctl2 *mfcctl2, struct in_addr *origin, 952 struct in_addr *group, int vidx, unsigned int rtableid, int wait) 953 { 954 struct ifnet *ifp; 955 struct vif *v; 956 struct mfcctl2 mfcctl; 957 958 ifp = if_lookupbyvif(vidx, rtableid); 959 if (ifp == NULL || 960 (v = (struct vif *)ifp->if_mcast) == NULL) 961 return (EHOSTUNREACH); 962 963 memset(&mfcctl, 0, sizeof(mfcctl)); 964 if (mfcctl2 == NULL) { 965 mfcctl.mfcc_origin = *origin; 966 mfcctl.mfcc_mcastgrp = *group; 967 mfcctl.mfcc_parent = vidx; 968 } else 969 memcpy(&mfcctl, mfcctl2, sizeof(mfcctl)); 970 971 update_mfc_params(&mfcctl, wait, rtableid); 972 973 return (0); 974 } 975 976 int 977 add_mfc(struct socket *so, struct mbuf *m) 978 { 979 struct inpcb *inp = sotoinpcb(so); 980 struct mfcctl2 mfcctl2; 981 int mfcctl_size = sizeof(struct mfcctl); 982 unsigned int rtableid = inp->inp_rtableid; 983 984 NET_ASSERT_LOCKED(); 985 986 if (mrt_api_config & MRT_API_FLAGS_ALL) 987 mfcctl_size = sizeof(struct mfcctl2); 988 989 if (m == NULL || m->m_len < mfcctl_size) 990 return (EINVAL); 991 992 /* 993 * select data size depending on API version. 994 */ 995 if (mrt_api_config & MRT_API_FLAGS_ALL) { 996 struct mfcctl2 *mp2 = mtod(m, struct mfcctl2 *); 997 memcpy((caddr_t)&mfcctl2, mp2, sizeof(*mp2)); 998 } else { 999 struct mfcctl *mp = mtod(m, struct mfcctl *); 1000 memcpy((caddr_t)&mfcctl2, mp, sizeof(*mp)); 1001 memset((caddr_t)&mfcctl2 + sizeof(struct mfcctl), 0, 1002 sizeof(mfcctl2) - sizeof(struct mfcctl)); 1003 } 1004 1005 if (mfc_add(&mfcctl2, &mfcctl2.mfcc_origin, &mfcctl2.mfcc_mcastgrp, 1006 mfcctl2.mfcc_parent, rtableid, M_WAITOK) == -1) 1007 return (EINVAL); 1008 1009 return (0); 1010 } 1011 1012 int 1013 del_mfc(struct socket *so, struct mbuf *m) 1014 { 1015 struct inpcb *inp = sotoinpcb(so); 1016 struct rtentry *rt; 1017 struct mfcctl2 mfcctl2; 1018 int mfcctl_size = sizeof(struct mfcctl); 1019 struct mfcctl *mp; 1020 unsigned int rtableid = inp->inp_rtableid; 1021 1022 NET_ASSERT_LOCKED(); 1023 1024 /* 1025 * XXX: for deleting MFC entries the information in entries 1026 * of size "struct mfcctl" is sufficient. 1027 */ 1028 1029 if (m == NULL || m->m_len < mfcctl_size) 1030 return (EINVAL); 1031 1032 mp = mtod(m, struct mfcctl *); 1033 1034 memcpy((caddr_t)&mfcctl2, mp, sizeof(*mp)); 1035 memset((caddr_t)&mfcctl2 + sizeof(struct mfcctl), 0, 1036 sizeof(mfcctl2) - sizeof(struct mfcctl)); 1037 1038 DPRINTF("origin %#08X group %#08X rtableid %d", 1039 mfcctl2.mfcc_origin.s_addr, mfcctl2.mfcc_mcastgrp.s_addr, rtableid); 1040 1041 while ((rt = mfc_find(NULL, &mfcctl2.mfcc_origin, 1042 &mfcctl2.mfcc_mcastgrp, rtableid)) != NULL) { 1043 mrt_mcast_del(rt, rtableid); 1044 rtfree(rt); 1045 } 1046 1047 return (0); 1048 } 1049 1050 int 1051 socket_send(struct socket *so, struct mbuf *mm, struct sockaddr_in *src) 1052 { 1053 if (so != NULL) { 1054 struct inpcb *inp = sotoinpcb(so); 1055 int ret; 1056 1057 mtx_enter(&inp->inp_mtx); 1058 ret = sbappendaddr(so, &so->so_rcv, sintosa(src), mm, NULL); 1059 mtx_leave(&inp->inp_mtx); 1060 1061 if (ret != 0) { 1062 sorwakeup(so); 1063 return (0); 1064 } 1065 } 1066 m_freem(mm); 1067 return (-1); 1068 } 1069 1070 /* 1071 * IP multicast forwarding function. This function assumes that the packet 1072 * pointed to by "ip" has arrived on (or is about to be sent to) the interface 1073 * pointed to by "ifp", and the packet is to be relayed to other networks 1074 * that have members of the packet's destination IP multicast group. 1075 * 1076 * The packet is returned unscathed to the caller, unless it is 1077 * erroneous, in which case a non-zero return value tells the caller to 1078 * discard it. 1079 */ 1080 1081 #define IP_HDR_LEN 20 /* # bytes of fixed IP header (excluding options) */ 1082 #define TUNNEL_LEN 12 /* # bytes of IP option for tunnel encapsulation */ 1083 1084 int 1085 ip_mforward(struct mbuf *m, struct ifnet *ifp) 1086 { 1087 struct ip *ip = mtod(m, struct ip *); 1088 struct vif *v; 1089 struct rtentry *rt; 1090 static int srctun = 0; 1091 struct mbuf *mm; 1092 unsigned int rtableid = ifp->if_rdomain; 1093 1094 if (ip->ip_hl < (IP_HDR_LEN + TUNNEL_LEN) >> 2 || 1095 ((u_char *)(ip + 1))[1] != IPOPT_LSRR) { 1096 /* 1097 * Packet arrived via a physical interface or 1098 * an encapsulated tunnel or a register_vif. 1099 */ 1100 } else { 1101 /* 1102 * Packet arrived through a source-route tunnel. 1103 * Source-route tunnels are no longer supported. 1104 */ 1105 if ((srctun++ % 1000) == 0) 1106 log(LOG_ERR, "ip_mforward: received source-routed " 1107 "packet from %x\n", ntohl(ip->ip_src.s_addr)); 1108 return (EOPNOTSUPP); 1109 } 1110 1111 /* 1112 * Don't forward a packet with time-to-live of zero or one, 1113 * or a packet destined to a local-only group. 1114 */ 1115 if (ip->ip_ttl <= 1 || IN_LOCAL_GROUP(ip->ip_dst.s_addr)) 1116 return (0); 1117 1118 /* 1119 * Determine forwarding vifs from the forwarding cache table 1120 */ 1121 ++mrtstat.mrts_mfc_lookups; 1122 rt = mfc_find(NULL, &ip->ip_src, &ip->ip_dst, rtableid); 1123 1124 /* Entry exists, so forward if necessary */ 1125 if (rt != NULL) { 1126 return (ip_mdq(m, ifp, rt)); 1127 } else { 1128 /* 1129 * If we don't have a route for packet's origin, 1130 * Make a copy of the packet & send message to routing daemon 1131 */ 1132 int hlen = ip->ip_hl << 2; 1133 1134 ++mrtstat.mrts_mfc_misses; 1135 mrtstat.mrts_no_route++; 1136 1137 { 1138 struct igmpmsg *im; 1139 1140 /* 1141 * Locate the vifi for the incoming interface for 1142 * this packet. 1143 * If none found, drop packet. 1144 */ 1145 if ((v = (struct vif *)ifp->if_mcast) == NULL) 1146 return (EHOSTUNREACH); 1147 /* 1148 * Make a copy of the header to send to the user level 1149 * process 1150 */ 1151 mm = m_copym(m, 0, hlen, M_NOWAIT); 1152 if (mm == NULL || 1153 (mm = m_pullup(mm, hlen)) == NULL) 1154 return (ENOBUFS); 1155 1156 /* 1157 * Send message to routing daemon to install 1158 * a route into the kernel table 1159 */ 1160 1161 im = mtod(mm, struct igmpmsg *); 1162 im->im_msgtype = IGMPMSG_NOCACHE; 1163 im->im_mbz = 0; 1164 im->im_vif = v->v_id; 1165 1166 mrtstat.mrts_upcalls++; 1167 1168 sin.sin_addr = ip->ip_src; 1169 if (socket_send(ip_mrouter[rtableid], mm, &sin) < 0) { 1170 log(LOG_WARNING, "ip_mforward: ip_mrouter " 1171 "socket queue full\n"); 1172 ++mrtstat.mrts_upq_sockfull; 1173 return (ENOBUFS); 1174 } 1175 1176 mfc_add(NULL, &ip->ip_src, &ip->ip_dst, v->v_id, 1177 rtableid, M_NOWAIT); 1178 } 1179 1180 return (0); 1181 } 1182 } 1183 1184 /* 1185 * Packet forwarding routine once entry in the cache is made 1186 */ 1187 int 1188 ip_mdq(struct mbuf *m, struct ifnet *ifp0, struct rtentry *rt) 1189 { 1190 struct ip *ip = mtod(m, struct ip *); 1191 struct mfc *mfc = (struct mfc *)rt->rt_llinfo; 1192 struct vif *v = (struct vif *)ifp0->if_mcast; 1193 struct ifnet *ifp; 1194 struct mbuf *mc; 1195 struct ip_moptions imo; 1196 1197 /* Sanity check: we have all promised pointers. */ 1198 if (v == NULL || mfc == NULL) { 1199 rtfree(rt); 1200 return (EHOSTUNREACH); 1201 } 1202 1203 /* 1204 * Don't forward if it didn't arrive from the parent vif for its origin. 1205 */ 1206 if (mfc->mfc_parent != v->v_id) { 1207 /* came in the wrong interface */ 1208 ++mrtstat.mrts_wrong_if; 1209 mfc->mfc_wrong_if++; 1210 rtfree(rt); 1211 return (0); 1212 } 1213 1214 /* If I sourced this packet, it counts as output, else it was input. */ 1215 if (in_hosteq(ip->ip_src, v->v_lcl_addr)) { 1216 v->v_pkt_out++; 1217 v->v_bytes_out += m->m_pkthdr.len; 1218 } else { 1219 v->v_pkt_in++; 1220 v->v_bytes_in += m->m_pkthdr.len; 1221 } 1222 1223 /* 1224 * For each vif, decide if a copy of the packet should be forwarded. 1225 * Forward if: 1226 * - the ttl exceeds the vif's threshold 1227 * - there are group members downstream on interface 1228 */ 1229 do { 1230 /* Don't consider non multicast routes. */ 1231 if (ISSET(rt->rt_flags, RTF_HOST | RTF_MULTICAST) != 1232 (RTF_HOST | RTF_MULTICAST)) 1233 continue; 1234 1235 mfc = (struct mfc *)rt->rt_llinfo; 1236 if (mfc == NULL) 1237 continue; 1238 1239 mfc->mfc_pkt_cnt++; 1240 mfc->mfc_byte_cnt += m->m_pkthdr.len; 1241 1242 /* Don't let this route expire. */ 1243 mfc->mfc_expire = 0; 1244 1245 if (ip->ip_ttl <= mfc->mfc_ttl) 1246 continue; 1247 if ((ifp = if_get(rt->rt_ifidx)) == NULL) 1248 continue; 1249 1250 /* Sanity check: did we configure this? */ 1251 if ((v = (struct vif *)ifp->if_mcast) == NULL) { 1252 if_put(ifp); 1253 continue; 1254 } 1255 1256 /* Don't send in the upstream interface. */ 1257 if (mfc->mfc_parent == v->v_id) { 1258 if_put(ifp); 1259 continue; 1260 } 1261 1262 v->v_pkt_out++; 1263 v->v_bytes_out += m->m_pkthdr.len; 1264 1265 /* 1266 * Make a new reference to the packet; make sure 1267 * that the IP header is actually copied, not 1268 * just referenced, so that ip_output() only 1269 * scribbles on the copy. 1270 */ 1271 mc = m_dup_pkt(m, max_linkhdr, M_NOWAIT); 1272 if (mc == NULL) { 1273 if_put(ifp); 1274 rtfree(rt); 1275 return (ENOBUFS); 1276 } 1277 1278 /* 1279 * if physical interface option, extract the options 1280 * and then send 1281 */ 1282 imo.imo_ifidx = rt->rt_ifidx; 1283 imo.imo_ttl = ip->ip_ttl - IPTTLDEC; 1284 imo.imo_loop = 1; 1285 1286 ip_output(mc, NULL, NULL, IP_FORWARDING, &imo, NULL, 0); 1287 if_put(ifp); 1288 } while ((rt = rtable_iterate(rt)) != NULL); 1289 1290 return (0); 1291 } 1292 1293 struct ifnet * 1294 if_lookupbyvif(vifi_t vifi, unsigned int rtableid) 1295 { 1296 struct vif *v; 1297 struct ifnet *ifp; 1298 1299 TAILQ_FOREACH(ifp, &ifnetlist, if_list) { 1300 if (ifp->if_rdomain != rtableid) 1301 continue; 1302 if ((v = (struct vif *)ifp->if_mcast) == NULL) 1303 continue; 1304 if (v->v_id != vifi) 1305 continue; 1306 1307 return (ifp); 1308 } 1309 1310 return (NULL); 1311 } 1312 1313 struct rtentry * 1314 rt_mcast_add(struct ifnet *ifp, struct sockaddr *origin, struct sockaddr *group) 1315 { 1316 struct ifaddr *ifa; 1317 int rv; 1318 unsigned int rtableid = ifp->if_rdomain; 1319 1320 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { 1321 if (ifa->ifa_addr->sa_family == AF_INET) 1322 break; 1323 } 1324 if (ifa == NULL) { 1325 DPRINTF("ifa == NULL"); 1326 return (NULL); 1327 } 1328 1329 rv = rt_ifa_add(ifa, RTF_HOST | RTF_MULTICAST | RTF_MPATH, 1330 group, ifp->if_rdomain); 1331 if (rv != 0) { 1332 DPRINTF("rt_ifa_add failed (%d)", rv); 1333 return (NULL); 1334 } 1335 1336 mrt_count[rtableid]++; 1337 1338 return (mfc_find(ifp, NULL, &satosin(group)->sin_addr, rtableid)); 1339 } 1340 1341 void 1342 mrt_mcast_del(struct rtentry *rt, unsigned int rtableid) 1343 { 1344 struct ifnet *ifp; 1345 int error; 1346 1347 /* Remove all timers related to this route. */ 1348 rt_timer_remove_all(rt); 1349 1350 free(rt->rt_llinfo, M_MRTABLE, sizeof(struct mfc)); 1351 rt->rt_llinfo = NULL; 1352 1353 ifp = if_get(rt->rt_ifidx); 1354 if (ifp == NULL) 1355 return; 1356 error = rtdeletemsg(rt, ifp, rtableid); 1357 if_put(ifp); 1358 1359 if (error) 1360 DPRINTF("delete route error %d\n", error); 1361 1362 mrt_count[rtableid]--; 1363 } 1364