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