/* * Remove all multicast addresses of the port. */ static void vsw_mac_multicast_remove_all(vsw_t *vswp, vsw_port_t *portp, int type) { mac_client_handle_t mch; mcst_addr_t *mcap; kmutex_t *mca_lockp; ASSERT((type == VSW_LOCALDEV) || (type == VSW_VNETPORT)); if (type == VSW_LOCALDEV) { ASSERT(RW_WRITE_HELD(&vswp->maccl_rwlock)); mch = vswp->mch; mcap = vswp->mcap; mca_lockp = &vswp->mca_lock; } else { ASSERT(RW_WRITE_HELD(&portp->maccl_rwlock)); mch = portp->p_mch; mcap = portp->mcap; mca_lockp = &portp->mca_lock; } if (mch == NULL) return; mutex_enter(mca_lockp); for (; mcap != NULL; mcap = mcap->nextp) { if (!mcap->mac_added) continue; (void) mac_multicast_remove(mch, (uchar_t *)&mcap->mca); mcap->mac_added = B_FALSE; } mutex_exit(mca_lockp); }
static void i_xnbo_close_mac(xnb_t *xnbp, boolean_t locked) { xnbo_t *xnbop = xnbp->xnb_flavour_data; xmca_t *loop; ASSERT(!locked || MUTEX_HELD(&xnbp->xnb_state_lock)); if (xnbop->o_mh == NULL) return; if (xnbop->o_running) xnbop->o_running = B_FALSE; if (!locked) mutex_enter(&xnbp->xnb_state_lock); loop = xnbop->o_mca; xnbop->o_mca = NULL; if (!locked) mutex_exit(&xnbp->xnb_state_lock); while (loop != NULL) { xmca_t *next = loop->next; DTRACE_PROBE3(mcast_remove, (char *), "close", (void *), xnbp, (etheraddr_t *), loop->addr); (void) mac_multicast_remove(xnbop->o_mch, loop->addr); kmem_free(loop, sizeof (*loop)); loop = next; } if (xnbop->o_promiscuous) { if (xnbop->o_mphp != NULL) { mac_promisc_remove(xnbop->o_mphp); xnbop->o_mphp = NULL; } xnbop->o_promiscuous = B_FALSE; } else { if (xnbop->o_mch != NULL) mac_rx_clear(xnbop->o_mch); } if (xnbop->o_mah != NULL) { (void) mac_unicast_remove(xnbop->o_mch, xnbop->o_mah); xnbop->o_mah = NULL; } if (xnbop->o_mch != NULL) { mac_client_close(xnbop->o_mch, 0); xnbop->o_mch = NULL; } mac_close(xnbop->o_mh); xnbop->o_mh = NULL; }
/* * Remove multicast addr. */ void vsw_mac_multicast_remove(vsw_t *vswp, vsw_port_t *port, mcst_addr_t *mcst_p, int type) { mac_client_handle_t mch; WRITE_MACCL_ENTER(vswp, port, type); mch = (type == VSW_LOCALDEV) ? vswp->mch : port->p_mch; if (mch != NULL && mcst_p->mac_added) { mac_multicast_remove(mch, mcst_p->mca.ether_addr_octet); mcst_p->mac_added = B_FALSE; } RW_MACCL_EXIT(vswp, port, type); }
/* * Find the multicast address `addr', return B_TRUE if it is one that * we receive. If `remove', remove it from the set received. */ static boolean_t xnbo_mcast_find(xnb_t *xnbp, ether_addr_t *addr, boolean_t remove) { xnbo_t *xnbop = xnbp->xnb_flavour_data; xmca_t *prev, *del, *this; ASSERT(MUTEX_HELD(&xnbp->xnb_state_lock)); ASSERT(xnbop->o_promiscuous == B_FALSE); prev = del = NULL; this = xnbop->o_mca; while (this != NULL) { if (bcmp(&this->addr, addr, sizeof (this->addr)) == 0) { del = this; if (remove) { if (prev == NULL) xnbop->o_mca = this->next; else prev->next = this->next; } break; } prev = this; this = this->next; } if (del == NULL) return (B_FALSE); if (remove) { DTRACE_PROBE3(mcast_remove, (char *), "remove", (void *), xnbp, (etheraddr_t *), del->addr); mac_multicast_remove(xnbop->o_mch, del->addr); kmem_free(del, sizeof (*del)); } return (B_TRUE); }
/* ARGSUSED */ static int pfp_setpacket_sockopt(sock_lower_handle_t handle, int option_name, const void *optval, socklen_t optlen) { struct packet_mreq mreq; struct pfpsock *ps; int error = 0; int opt; ps = (struct pfpsock *)handle; if (!ps->ps_bound) return (EPROTO); if ((option_name == PACKET_ADD_MEMBERSHIP) || (option_name == PACKET_DROP_MEMBERSHIP)) { if (!ps->ps_bound) return (EPROTO); bcopy(optval, &mreq, sizeof (mreq)); if (ps->ps_linkid != mreq.mr_ifindex) return (EINVAL); if (mreq.mr_alen != ((struct sockaddr_ll *)&ps->ps_sock)->sll_halen) return (EINVAL); } switch (option_name) { case PACKET_ADD_MEMBERSHIP : switch (mreq.mr_type) { case PACKET_MR_MULTICAST : error = mac_multicast_add(ps->ps_mch, mreq.mr_address); break; case PACKET_MR_PROMISC : error = pfp_set_promisc(ps, MAC_CLIENT_PROMISC_ALL); break; case PACKET_MR_ALLMULTI : error = pfp_set_promisc(ps, MAC_CLIENT_PROMISC_MULTI); break; } break; case PACKET_DROP_MEMBERSHIP : switch (mreq.mr_type) { case PACKET_MR_MULTICAST : mac_multicast_remove(ps->ps_mch, mreq.mr_address); break; case PACKET_MR_PROMISC : if (ps->ps_promisc != MAC_CLIENT_PROMISC_ALL) return (EINVAL); error = pfp_set_promisc(ps, MAC_CLIENT_PROMISC_FILTERED); break; case PACKET_MR_ALLMULTI : if (ps->ps_promisc != MAC_CLIENT_PROMISC_MULTI) return (EINVAL); error = pfp_set_promisc(ps, MAC_CLIENT_PROMISC_FILTERED); break; } break; case PACKET_AUXDATA : if (optlen == sizeof (int)) { opt = *(int *)optval; ps->ps_auxdata = (opt != 0); } else { error = EINVAL; } break; default : error = EINVAL; break; } return (error); }