Esempio n. 1
0
/* ------------------------------------------------------------------------ */
void *
ipf_lookup_res_name(ipf_main_softc_t *softc, int unit, u_int type, char *name,
    lookupfunc_t *funcptr)
{
	ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
	ipf_lookup_t **l;
	void *ptr = NULL;
	int i;

	READ_ENTER(&softc->ipf_poolrw);

	for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) {
		if (type == (*l)->ipfl_type) {
			ptr = (*(*l)->ipfl_select_add_ref)(softl->ipf_back[i],
							   unit, name);
			if (ptr != NULL && funcptr != NULL) {
				*funcptr = (*l)->ipfl_addr_find;
			}
			break;
		}
	}

	if (i == MAX_BACKENDS) {
		ptr = NULL;
		if (funcptr != NULL)
			*funcptr = NULL;
	}

	RWLOCK_EXIT(&softc->ipf_poolrw);

	return ptr;
}
Esempio n. 2
0
/*
 * clean up after ourselves.
 */
void
ipf_p_pptp_del(ipf_main_softc_t *softc, ap_session_t *aps)
{
	pptp_pxy_t *pptp;

	pptp = aps->aps_data;

	if (pptp != NULL) {
		/*
		 * Don't bother changing any of the NAT structure details,
		 * *_del() is on a callback from aps_free(), from nat_delete()
		 */

		READ_ENTER(&softc->ipf_state);
		if (pptp->pptp_state != NULL) {
			ipf_state_setpending(softc, pptp->pptp_state);
		}
		RWLOCK_EXIT(&softc->ipf_state);

		if (pptp->pptp_nat != NULL)
			ipf_nat_setpending(softc, pptp->pptp_nat);
		pptp->pptp_rule->in_flags |= IPN_DELETE;
		ipf_nat_rule_deref(softc, &pptp->pptp_rule);
	}
}
Esempio n. 3
0
/* ARGSUSED */
static void
vsw_if_rx_cb(void *arg, mac_resource_handle_t mrh, mblk_t *mp,
    boolean_t loopback)
{
	_NOTE(ARGUNUSED(mrh))

	vsw_t		*vswp = (vsw_t *)arg;
	mblk_t		*mpt;
	int		count;

	ASSERT(vswp != NULL);

	D1(vswp, "%s: enter", __func__);

	READ_ENTER(&vswp->if_lockrw);
	if (vswp->if_state & VSW_IF_UP) {
		RW_EXIT(&vswp->if_lockrw);
		count = vsw_vlan_frame_untag(vswp, VSW_LOCALDEV, &mp, &mpt);
		if (count != 0) {
			mac_rx(vswp->if_mh, NULL, mp);
		}
	} else {
		RW_EXIT(&vswp->if_lockrw);
		freemsgchain(mp);
	}

	D1(vswp, "%s: exit", __func__);
}
Esempio n. 4
0
/*
 * clean up after ourselves.
 */
void
ippr_pptp_del(ap_session_t *aps)
{
	pptp_pxy_t *pptp;

	pptp = aps->aps_data;

	if (pptp != NULL) {
		/*
		 * Don't bother changing any of the NAT structure details,
		 * *_del() is on a callback from aps_free(), from nat_delete()
		 */

		READ_ENTER(&ipf_state);
		if (pptp->pptp_state != NULL) {
			pptp->pptp_state->is_die = fr_ticks + 1;
			pptp->pptp_state->is_me = NULL;
			fr_queuefront(&pptp->pptp_state->is_sti);
		}
		RWLOCK_EXIT(&ipf_state);

		pptp->pptp_state = NULL;
		pptp->pptp_nat = NULL;
	}
}
Esempio n. 5
0
int
ipsc_attachis(struct ipstate *is)
{
	frentry_t *fr;
	ipscan_t *i;

	READ_ENTER(&ipsc_rwlock);
	fr = is->is_rule;
	if (fr) {
		i = fr->fr_isc;
		if ((i != NULL) && (i != (ipscan_t *)-1)) {
			is->is_isc = i;
			ATOMIC_INC32(i->ipsc_sref);
			if (i->ipsc_clen)
				is->is_flags |= IS_SC_CLIENT;
			else
				is->is_flags |= IS_SC_MATCHC;
			if (i->ipsc_slen)
				is->is_flags |= IS_SC_SERVER;
			else
				is->is_flags |= IS_SC_MATCHS;
		}
	}
	RWLOCK_EXIT(&ipsc_rwlock);
	return 0;
}
Esempio n. 6
0
/*
 * Program unicast and multicast addresses of vsw interface and the ports
 * into the network device.
 */
void
vsw_set_addrs(vsw_t *vswp)
{
	vsw_port_list_t	*plist = &vswp->plist;
	vsw_port_t	*port;
	int		rv;

	READ_ENTER(&vswp->if_lockrw);

	if (vswp->if_state & VSW_IF_UP) {

		/* Open a mac client and program addresses */
		rv = vsw_mac_client_init(vswp, NULL, VSW_LOCALDEV);
		if (rv != 0) {
			cmn_err(CE_NOTE,
			    "!vsw%d: failed to program interface "
			    "unicast address\n", vswp->instance);
		}

		/*
		 * Notify the MAC layer of the changed address.
		 */
		if (rv == 0) {
			mac_unicst_update(vswp->if_mh,
			    (uint8_t *)&vswp->if_addr);
		}

	}

	RW_EXIT(&vswp->if_lockrw);

	WRITE_ENTER(&plist->lockrw);

	/* program unicast address of ports in the network device */
	for (port = plist->head; port != NULL; port = port->p_next) {
		if (port->addr_set) /* addr already set */
			continue;

		/* Open a mac client and program addresses */
		rv = vsw_mac_client_init(vswp, port, VSW_VNETPORT);
		if (rv != 0) {
			cmn_err(CE_NOTE,
			    "!vsw%d: failed to program port(%d) "
			    "unicast address\n", vswp->instance,
			    port->p_instance);
		}
	}
	/* announce macaddr of vnets to the physical switch */
	if (vsw_publish_macaddr_count != 0) {	/* enabled */
		for (port = plist->head; port != NULL; port = port->p_next) {
			vsw_publish_macaddr(vswp, port);
		}
	}

	RW_EXIT(&plist->lockrw);
}
Esempio n. 7
0
/*
 * Cleanup MAC client related stuff for all ports.
 */
void
vsw_mac_cleanup_ports(vsw_t *vswp)
{
	vsw_port_list_t		*plist = &vswp->plist;
	vsw_port_t		*port;

	READ_ENTER(&plist->lockrw);
	for (port = plist->head; port != NULL; port = port->p_next) {
		vsw_mac_client_cleanup(vswp, port, VSW_VNETPORT);
	}
	RW_EXIT(&plist->lockrw);
}
Esempio n. 8
0
/*
 * Remove unicast, multicast addresses and close mac clients
 * for the vsw interface and all ports.
 */
void
vsw_unset_addrs(vsw_t *vswp)
{
	READ_ENTER(&vswp->if_lockrw);
	if (vswp->if_state & VSW_IF_UP) {

		/* Cleanup and close the mac client for the interface */
		vsw_mac_client_cleanup(vswp, NULL, VSW_LOCALDEV);
	}
	RW_EXIT(&vswp->if_lockrw);

	/* Cleanup and close the mac clients for all ports */
	vsw_mac_cleanup_ports(vswp);
}
Esempio n. 9
0
int
ipsc_detachis(struct ipstate *is)
{
	ipscan_t *i;

	READ_ENTER(&ipsc_rwlock);
	if ((i = is->is_isc) && (i != (ipscan_t *)-1)) {
		ATOMIC_DEC32(i->ipsc_sref);
		is->is_isc = NULL;
		is->is_flags &= ~(IS_SC_CLIENT|IS_SC_SERVER);
	}
	RWLOCK_EXIT(&ipsc_rwlock);
	return 0;
}
Esempio n. 10
0
/*ARGSUSED*/
void
ipf_lookup_sync(ipf_main_softc_t *softc, void *ifp)
{
	ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
	ipf_lookup_t **l;
	int i;

	READ_ENTER(&softc->ipf_poolrw);

	for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++)
		if ((*l)->ipfl_sync != NULL)
			(*(*l)->ipfl_sync)(softc, softl->ipf_back[i]);

	RWLOCK_EXIT(&softc->ipf_poolrw);
}
Esempio n. 11
0
int
ipsc_attachfr(struct frentry *fr)
{
	ipscan_t *i;

	if (fr->fr_isctag[0]) {
		READ_ENTER(&ipsc_rwlock);
		i = ipsc_lookup(fr->fr_isctag);
		if (i != NULL) {
			ATOMIC_INC32(i->ipsc_fref);
		}
		RWLOCK_EXIT(&ipsc_rwlock);
		if (i == NULL)
			return ENOENT;
		fr->fr_isc = i;
	}
	return 0;
}
Esempio n. 12
0
/* ------------------------------------------------------------------------ */
void *
ipf_lookup_find_htable(ipf_main_softc_t *softc, int unit, char *name)
{
	ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
	ipf_lookup_t **l;
	void *tab = NULL;
	int i;

	READ_ENTER(&softc->ipf_poolrw);

	for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++)
		if (IPLT_HASH == (*l)->ipfl_type) {
			tab = ipf_htable_find(softl->ipf_back[i], unit, name);
			break;
		}

	RWLOCK_EXIT(&softc->ipf_poolrw);

	return tab;
}
Esempio n. 13
0
void
ippr_pptp_donatstate(fr_info_t *fin, nat_t *nat, pptp_pxy_t *pptp)
{
	fr_info_t fi;
	grehdr_t gre;
	nat_t *nat2;
	u_char p;
	ip_t *ip;

	ip = fin->fin_ip;
	p = ip->ip_p;

	nat2 = pptp->pptp_nat;
	if ((nat2 == NULL) || (pptp->pptp_state == NULL)) {
		bcopy((char *)fin, (char *)&fi, sizeof(fi));
		bzero((char *)&gre, sizeof(gre));
		fi.fin_fi.fi_p = IPPROTO_GRE;
		fi.fin_fr = &pptpfr;
		if ((nat->nat_dir == NAT_OUTBOUND && fin->fin_out) ||
		    (nat->nat_dir == NAT_INBOUND && !fin->fin_out)) {
			fi.fin_data[0] = pptp->pptp_call[0];
			fi.fin_data[1] = pptp->pptp_call[1];
		} else {
			fi.fin_data[0] = pptp->pptp_call[1];
			fi.fin_data[1] = pptp->pptp_call[0];
		}
		ip = fin->fin_ip;
		ip->ip_p = IPPROTO_GRE;
		fi.fin_flx &= ~(FI_TCPUDP|FI_STATE|FI_FRAG);
		fi.fin_flx |= FI_IGNORE;
		fi.fin_dp = &gre;
		gre.gr_flags = htons(1 << 13);
		if (fin->fin_out && nat->nat_dir == NAT_INBOUND) {
			fi.fin_fi.fi_saddr = fin->fin_fi.fi_daddr;
			fi.fin_fi.fi_daddr = nat->nat_outip.s_addr;
		} else if (!fin->fin_out && nat->nat_dir == NAT_OUTBOUND) {
			fi.fin_fi.fi_saddr = nat->nat_inip.s_addr;
			fi.fin_fi.fi_daddr = fin->fin_fi.fi_saddr;
		}
	}

	/*
	 * Update NAT timeout/create NAT if missing.
	 */
	if (nat2 != NULL)
		fr_queueback(&nat2->nat_tqe);
	else {
		MUTEX_ENTER(&ipf_nat_new);
		nat2 = nat_new(&fi, &pptp->pptp_rule, &pptp->pptp_nat,
			       NAT_SLAVE, nat->nat_dir);
		MUTEX_EXIT(&ipf_nat_new);
		pptp->pptp_nat = nat2;
		if (nat2 != NULL) {
			(void) nat_proto(&fi, nat2, 0);
			MUTEX_ENTER(&nat2->nat_lock);
			nat_update(&fi, nat2);
			MUTEX_EXIT(&nat2->nat_lock);
		}
	}

	READ_ENTER(&ipf_state);
	if (pptp->pptp_state != NULL) {
		fr_queueback(&pptp->pptp_state->is_sti);
		RWLOCK_EXIT(&ipf_state);
	} else {
		RWLOCK_EXIT(&ipf_state);
		if (nat2 != NULL) {
			if (nat->nat_dir == NAT_INBOUND)
				fi.fin_fi.fi_daddr = nat2->nat_inip.s_addr;
			else
				fi.fin_fi.fi_saddr = nat2->nat_inip.s_addr;
		}
		fi.fin_ifp = NULL;
		pptp->pptp_state = fr_addstate(&fi, &pptp->pptp_state,
					       0);
	}
	ip->ip_p = p;
	return;
}
Esempio n. 14
0
/*
 * Forward pkts to any devices or interfaces which have registered
 * an interest in them (i.e. multicast groups).
 */
static int
vsw_forward_grp(vsw_t *vswp, mblk_t *mp, int caller, vsw_port_t *arg)
{
	struct ether_header	*ehp = (struct ether_header *)mp->b_rptr;
	mfdb_ent_t		*entp = NULL;
	mfdb_ent_t		*tpp = NULL;
	vsw_port_t 		*port;
	uint64_t		key = 0;
	mblk_t			*nmp = NULL;
	mblk_t			*ret_m = NULL;
	boolean_t		check_if = B_TRUE;

	/*
	 * Convert address to hash table key
	 */
	KEY_HASH(key, &ehp->ether_dhost);

	D1(vswp, "%s: key 0x%llx", __func__, key);

	/*
	 * If pkt came from either a vnet or down the stack (if we are
	 * plumbed) and we are in layer 2 mode, then we send the pkt out
	 * over the physical adapter, and then check to see if any other
	 * vnets are interested in it.
	 */
	if ((vswp->smode & VSW_LAYER2) &&
	    ((caller == VSW_VNETPORT) || (caller == VSW_LOCALDEV))) {
		nmp = vsw_dupmsgchain(mp);
		if (nmp) {
			if ((ret_m = vsw_tx_msg(vswp, nmp, caller, arg))
			    != NULL) {
				DERR(vswp, "%s: dropping pkt(s) consisting of "
				    "%ld bytes of data for physical device",
				    __func__, MBLKL(ret_m));
				freemsgchain(ret_m);
			}
		}
	}

	READ_ENTER(&vswp->mfdbrw);
	if (mod_hash_find(vswp->mfdb, (mod_hash_key_t)key,
	    (mod_hash_val_t *)&entp) != 0) {
		D3(vswp, "%s: no table entry found for addr 0x%llx",
		    __func__, key);
	} else {
		/*
		 * Send to list of devices associated with this address...
		 */
		for (tpp = entp; tpp != NULL; tpp = tpp->nextp) {

			/* dont send to ourselves */
			if ((caller == VSW_VNETPORT) &&
			    (tpp->d_addr == (void *)arg)) {
				port = (vsw_port_t *)tpp->d_addr;
				D3(vswp, "%s: not sending to ourselves"
				    " : port %d", __func__, port->p_instance);
				continue;

			} else if ((caller == VSW_LOCALDEV) &&
			    (tpp->d_type == VSW_LOCALDEV)) {
				D2(vswp, "%s: not sending back up stack",
				    __func__);
				continue;
			}

			if (tpp->d_type == VSW_VNETPORT) {
				port = (vsw_port_t *)tpp->d_addr;
				D3(vswp, "%s: sending to port %ld for addr "
				    "0x%llx", __func__, port->p_instance, key);

				nmp = vsw_dupmsgchain(mp);
				if (nmp) {
					/*
					 * The vswp->mfdbrw is protecting the
					 * portp from getting destroyed here.
					 * So, no ref_cnt is incremented here.
					 */
					(void) vsw_portsend(port, nmp);
				}
			} else {
				vsw_mac_rx(vswp, NULL,
				    mp, VSW_MACRX_COPYMSG);
				D2(vswp, "%s: sending up stack"
				    " for addr 0x%llx", __func__, key);
				check_if = B_FALSE;
			}
		}
	}

	RW_EXIT(&vswp->mfdbrw);

	/*
	 * If the pkt came from either a vnet or from physical device,
	 * and if we havent already sent the pkt up the stack then we
	 * check now if we can/should (i.e. the interface is plumbed
	 * and in promisc mode).
	 */
	if ((check_if) &&
	    ((caller == VSW_VNETPORT) || (caller == VSW_PHYSDEV))) {
		vsw_mac_rx(vswp, NULL, mp,
		    VSW_MACRX_PROMISC | VSW_MACRX_COPYMSG);
	}

	freemsgchain(mp);

	D1(vswp, "%s: exit", __func__);

	return (0);
}
Esempio n. 15
0
/*
 * Forward the ethernet frame to all ports (VNETPORTs, PHYSDEV, LOCALDEV),
 * except the caller (port on which frame arrived).
 */
static int
vsw_forward_all(vsw_t *vswp, mblk_t *mp, int caller, vsw_port_t *arg)
{
	vsw_port_list_t	*plist = &vswp->plist;
	vsw_port_t	*portp;
	mblk_t		*nmp = NULL;
	mblk_t		*ret_m = NULL;
	int		skip_port = 0;

	D1(vswp, "vsw_forward_all: enter\n");

	/*
	 * Broadcast message from inside ldoms so send to outside
	 * world if in either of layer 2 modes.
	 */
	if ((vswp->smode & VSW_LAYER2) &&
	    ((caller == VSW_LOCALDEV) || (caller == VSW_VNETPORT))) {

		nmp = vsw_dupmsgchain(mp);
		if (nmp) {
			if ((ret_m = vsw_tx_msg(vswp, nmp, caller, arg))
			    != NULL) {
				DERR(vswp, "%s: dropping pkt(s) "
				    "consisting of %ld bytes of data for"
				    " physical device", __func__, MBLKL(ret_m));
				freemsgchain(ret_m);
			}
		}
	}

	if (caller == VSW_VNETPORT)
		skip_port = 1;

	/*
	 * Broadcast message from other vnet (layer 2 or 3) or outside
	 * world (layer 2 only), send up stack if plumbed.
	 */
	if ((caller == VSW_PHYSDEV) || (caller == VSW_VNETPORT)) {
		vsw_mac_rx(vswp, NULL, mp, VSW_MACRX_COPYMSG);
	}

	/* send it to all VNETPORTs */
	READ_ENTER(&plist->lockrw);
	for (portp = plist->head; portp != NULL; portp = portp->p_next) {
		D2(vswp, "vsw_forward_all: port %d", portp->p_instance);
		/*
		 * Caution ! - don't reorder these two checks as arg
		 * will be NULL if the caller is PHYSDEV. skip_port is
		 * only set if caller is VNETPORT.
		 */
		if ((skip_port) && (portp == arg)) {
			continue;
		} else {
			nmp = vsw_dupmsgchain(mp);
			if (nmp) {
				/*
				 * The plist->lockrw is protecting the
				 * portp from getting destroyed here.
				 * So, no ref_cnt is incremented here.
				 */
				(void) vsw_portsend(portp, nmp);
			} else {
				DERR(vswp, "vsw_forward_all: nmp NULL");
			}
		}
	}
	RW_EXIT(&plist->lockrw);

	freemsgchain(mp);

	D1(vswp, "vsw_forward_all: exit\n");
	return (0);
}
Esempio n. 16
0
void
ipf_p_pptp_donatstate(fr_info_t *fin, nat_t *nat, pptp_pxy_t *pptp)
{
	ipf_main_softc_t *softc = fin->fin_main_soft;
	fr_info_t fi;
	grehdr_t gre;
	nat_t *nat2;
	u_char p;
	ip_t *ip;

	ip = fin->fin_ip;
	p = ip->ip_p;

	nat2 = pptp->pptp_nat;
	if ((nat2 == NULL) || (pptp->pptp_state == NULL)) {
		bcopy((char *)fin, (char *)&fi, sizeof(fi));
		bzero((char *)&gre, sizeof(gre));
		fi.fin_fi.fi_p = IPPROTO_GRE;
		fi.fin_fr = &pptpfr;
		if ((nat->nat_dir == NAT_OUTBOUND && fin->fin_out) ||
		    (nat->nat_dir == NAT_INBOUND && !fin->fin_out)) {
			fi.fin_data[0] = pptp->pptp_call[0];
			fi.fin_data[1] = pptp->pptp_call[1];
		} else {
			fi.fin_data[0] = pptp->pptp_call[1];
			fi.fin_data[1] = pptp->pptp_call[0];
		}
		ip = fin->fin_ip;
		ip->ip_p = IPPROTO_GRE;
		fi.fin_flx &= ~(FI_TCPUDP|FI_STATE|FI_FRAG);
		fi.fin_flx |= FI_IGNORE;
		fi.fin_dp = &gre;
		gre.gr_flags = htons(1 << 13);

		fi.fin_fi.fi_saddr = nat->nat_osrcaddr;
		fi.fin_fi.fi_daddr = nat->nat_odstaddr;
	}

	/*
	 * Update NAT timeout/create NAT if missing.
	 */
	if (nat2 != NULL)
		ipf_queueback(softc->ipf_ticks, &nat2->nat_tqe);
	else {
#ifdef USE_MUTEXES
		ipf_nat_softc_t *softn = softc->ipf_nat_soft;
#endif

		MUTEX_ENTER(&softn->ipf_nat_new);
		nat2 = ipf_nat_add(&fi, pptp->pptp_rule, &pptp->pptp_nat,
				   NAT_SLAVE, nat->nat_dir);
		MUTEX_EXIT(&softn->ipf_nat_new);
		if (nat2 != NULL) {
			(void) ipf_nat_proto(&fi, nat2, 0);
			MUTEX_ENTER(&nat2->nat_lock);
			ipf_nat_update(&fi, nat2);
			MUTEX_EXIT(&nat2->nat_lock);
		}
	}

	READ_ENTER(&softc->ipf_state);
	if (pptp->pptp_state != NULL) {
		ipf_queueback(softc->ipf_ticks, &pptp->pptp_state->is_sti);
		RWLOCK_EXIT(&softc->ipf_state);
	} else {
		RWLOCK_EXIT(&softc->ipf_state);
		if (nat2 != NULL) {
			if (nat->nat_dir == NAT_INBOUND)
				fi.fin_fi.fi_daddr = nat2->nat_ndstaddr;
			else
				fi.fin_fi.fi_saddr = nat2->nat_osrcaddr;
		}
		fi.fin_ifp = NULL;
		(void) ipf_state_add(softc, &fi, &pptp->pptp_state, 0);
	}
	ip->ip_p = p;
	return;
}