/* * Add multicast addr. */ int vsw_mac_multicast_add(vsw_t *vswp, vsw_port_t *port, mcst_addr_t *mcst_p, int type) { int ret = 0; mac_client_handle_t mch; WRITE_MACCL_ENTER(vswp, port, type); mch = (type == VSW_LOCALDEV) ? vswp->mch : port->p_mch; if (mch != NULL) { ret = mac_multicast_add(mch, mcst_p->mca.ether_addr_octet); if (ret != 0) { cmn_err(CE_WARN, "!vsw%d: unable to " "program multicast address(%s) err=%d", vswp->instance, ether_sprintf((void *)&mcst_p->mca), ret); RW_MACCL_EXIT(vswp, port, type); return (ret); } mcst_p->mac_added = B_TRUE; } RW_MACCL_EXIT(vswp, port, type); return (ret); }
/* * Add the multicast address `addr' to the set received. */ static boolean_t xnbo_mcast_add(xnb_t *xnbp, ether_addr_t *addr) { xnbo_t *xnbop = xnbp->xnb_flavour_data; boolean_t r = B_FALSE; ASSERT(xnbop->o_promiscuous == B_FALSE); mutex_enter(&xnbp->xnb_state_lock); if (xnbo_mcast_find(xnbp, addr, B_FALSE)) { r = B_TRUE; } else if (mac_multicast_add(xnbop->o_mch, (const uint8_t *)addr) == 0) { xmca_t *mca; DTRACE_PROBE3(mcast_add, (char *), "add", (void *), xnbp, (etheraddr_t *), addr); mca = kmem_alloc(sizeof (*mca), KM_SLEEP); bcopy(addr, &mca->addr, sizeof (mca->addr)); mca->next = xnbop->o_mca; xnbop->o_mca = mca; r = B_TRUE; }
/* * Add all multicast addresses of the port. */ static void vsw_mac_multicast_add_all(vsw_t *vswp, vsw_port_t *portp, int type) { mcst_addr_t *mcap; mac_client_handle_t mch; kmutex_t *mca_lockp; int rv; 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 = mcap; mcap != NULL; mcap = mcap->nextp) { if (mcap->mac_added) continue; rv = mac_multicast_add(mch, (uchar_t *)&mcap->mca); if (rv == 0) { mcap->mac_added = B_TRUE; } else { cmn_err(CE_WARN, "!vsw%d: unable to program " "multicast address(%s) err=%d", vswp->instance, ether_sprintf((void *)&mcap->mca), rv); } } mutex_exit(mca_lockp); }
/* 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); }