* Program our multicast filter. What we're actually doing is * programming the multicast filter of the parent. This has the * side effect of causing the parent interface to receive multicast * traffic that it doesn't really want, which ends up being discarded * later by the upper protocol layers. Unfortunately, there's no way * to avoid this: there really is only one physical interface. */
| 575 | * to avoid this: there really is only one physical interface. |
| 576 | */ |
| 577 | static int |
| 578 | vlan_setmulti(struct ifnet *ifp) |
| 579 | { |
| 580 | struct ifnet *ifp_p; |
| 581 | struct ifmultiaddr *ifma; |
| 582 | struct ifvlan *sc; |
| 583 | struct vlan_mc_entry *mc; |
| 584 | int error; |
| 585 | |
| 586 | VLAN_XLOCK_ASSERT(); |
| 587 | |
| 588 | /* Find the parent. */ |
| 589 | sc = ifp->if_softc; |
| 590 | ifp_p = PARENT(sc); |
| 591 | |
| 592 | CURVNET_SET_QUIET(ifp_p->if_vnet); |
| 593 | |
| 594 | /* First, remove any existing filter entries. */ |
| 595 | while ((mc = CK_SLIST_FIRST(&sc->vlan_mc_listhead)) != NULL) { |
| 596 | CK_SLIST_REMOVE_HEAD(&sc->vlan_mc_listhead, mc_entries); |
| 597 | (void)if_delmulti(ifp_p, (struct sockaddr *)&mc->mc_addr); |
| 598 | NET_EPOCH_CALL(vlan_mc_free, &mc->mc_epoch_ctx); |
| 599 | } |
| 600 | |
| 601 | /* Now program new ones. */ |
| 602 | IF_ADDR_WLOCK(ifp); |
| 603 | CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { |
| 604 | if (ifma->ifma_addr->sa_family != AF_LINK) |
| 605 | continue; |
| 606 | mc = malloc(sizeof(struct vlan_mc_entry), M_VLAN, M_NOWAIT); |
| 607 | if (mc == NULL) { |
| 608 | IF_ADDR_WUNLOCK(ifp); |
| 609 | return (ENOMEM); |
| 610 | } |
| 611 | bcopy(ifma->ifma_addr, &mc->mc_addr, ifma->ifma_addr->sa_len); |
| 612 | mc->mc_addr.sdl_index = ifp_p->if_index; |
| 613 | CK_SLIST_INSERT_HEAD(&sc->vlan_mc_listhead, mc, mc_entries); |
| 614 | } |
| 615 | IF_ADDR_WUNLOCK(ifp); |
| 616 | CK_SLIST_FOREACH (mc, &sc->vlan_mc_listhead, mc_entries) { |
| 617 | error = if_addmulti(ifp_p, (struct sockaddr *)&mc->mc_addr, |
| 618 | NULL); |
| 619 | if (error) |
| 620 | return (error); |
| 621 | } |
| 622 | |
| 623 | CURVNET_RESTORE(); |
| 624 | return (0); |
| 625 | } |
| 626 | |
| 627 | /* |
| 628 | * A handler for parent interface link layer address changes. |
no test coverage detected