Exemple #1
0
/*
 * 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);
}
Exemple #2
0
/*
 * 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;
	}
Exemple #3
0
/*
 * 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);
}