Esempio n. 1
0
/* ------------------------------------------------------------------------ */
void
ipf_lookup_iterderef(ipf_main_softc_t *softc, u_32_t type, void *data)
{
	ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
	struct iplookupiterkey *lkey;
	iplookupiterkey_t key;
	int i;

	key.ilik_key = type;
	lkey = &key.ilik_unstr;

	if (lkey->ilik_ival != IPFGENITER_LOOKUP)
		return;

	WRITE_ENTER(&softc->ipf_poolrw);

	for (i = 0; i < MAX_BACKENDS; i++) {
		if (lkey->ilik_type == backends[i]->ipfl_type) {
			(*backends[i]->ipfl_iter_deref)(softc,
							softl->ipf_back[i],
							lkey->ilik_otype,
							lkey->ilik_unit,
							data);
			break;
		}
	}
	RWLOCK_EXIT(&softc->ipf_poolrw);
}
Esempio n. 2
0
static int
ipf_modunload(void)
{
	int error, i;

	if (fr_refcnt)
		return EBUSY;

	if (fr_running >= 0) {
		ipf_pfil_unhook();
		ipf_event_dereg();
		WRITE_ENTER(&ipf_global);
		error = ipfdetach();
		RWLOCK_EXIT(&ipf_global);
		if (error != 0)
			return error;
	} else
		error = 0;

	RW_DESTROY(&ipf_global);
	RW_DESTROY(&ipf_mutex);
	RW_DESTROY(&ipf_frcache);

	fr_running = -2;

	for (i = 0; ipf_devfiles[i]; i++) {
		if (ipf_devs[i] != NULL)
			destroy_dev(ipf_devs[i]);
	}

	printf("%s unloaded\n", ipfilter_version);

	return error;
}
Esempio n. 3
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. 4
0
/* ------------------------------------------------------------------------ */
void
ipf_lookup_expire(ipf_main_softc_t *softc)
{
	ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
	int i;

	WRITE_ENTER(&softc->ipf_poolrw);
	for (i = 0; i < MAX_BACKENDS; i++)
		(*backends[i]->ipfl_expire)(softc, softl->ipf_back[i]);
	RWLOCK_EXIT(&softc->ipf_poolrw);
}
Esempio n. 5
0
/* ------------------------------------------------------------------------ */
static int
ipf_lookup_iterate(ipf_main_softc_t *softc, void *data, int uid, void *ctx)
{
	ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
	ipflookupiter_t iter;
	ipftoken_t *token;
	int err, i;
	SPL_INT(s);

	err = ipf_inobj(softc, data, NULL, &iter, IPFOBJ_LOOKUPITER);
	if (err != 0)
		return err;

	if (iter.ili_unit < IPL_LOGALL && iter.ili_unit > IPL_LOGMAX) {
		IPFERROR(50038);
		return EINVAL;
	}

	if (iter.ili_ival != IPFGENITER_LOOKUP) {
		IPFERROR(50039);
		return EINVAL;
	}

	SPL_SCHED(s);
	token = ipf_token_find(softc, iter.ili_key, uid, ctx);
	if (token == NULL) {
		SPL_X(s);
		IPFERROR(50040);
		return ESRCH;
	}

	for (i = 0; i < MAX_BACKENDS; i++) {
		if (iter.ili_type == backends[i]->ipfl_type) {
			err = (*backends[i]->ipfl_iter_next)(softc,
							     softl->ipf_back[i],
							     token, &iter);
			break;
		}
	}
	SPL_X(s);

	if (i == MAX_BACKENDS) {
		IPFERROR(50041);
		err = EINVAL;
	}

	WRITE_ENTER(&softc->ipf_tokens);
	ipf_token_deref(softc, token);
	RWLOCK_EXIT(&softc->ipf_tokens);

	return err;
}
Esempio n. 6
0
/*
 * vsw_port_mac_reconfig -- Cleanup and close the MAC client
 * and reopen and re-configure the MAC client with new flags etc.
 * This function is useful for two different purposes:
 *	1) To update the MAC client with new vlan-ids. This is done
 *	   by freeing the existing vlan-ids and reopen with the new
 *	   vlan-ids.
 *
 *	2) If the Hybrid mode status of a port changes, then the
 *	   MAC client need to be closed and re-opened, otherwise,
 *	   Share related resources may not be freed(hybird mode disabled)
 *	   or assigned(hybrid mode enabled). To accomplish this,
 *	   this function simply closes and reopens the MAC client.
 *	   The reopen will result in using the flags based on the
 *	   new hybrid mode of the port.
 */
void
vsw_port_mac_reconfig(vsw_port_t *portp, boolean_t update_vlans,
    uint16_t new_pvid, vsw_vlanid_t *new_vids, int new_nvids)
{
	vsw_t *vswp = portp->p_vswp;
	int rv;

	D1(vswp, "%s: enter", __func__);
	/*
	 * Remove the multi-cast addresses, unicast address
	 * and close the mac-client.
	 */
	mutex_enter(&vswp->mac_lock);
	WRITE_ENTER(&portp->maccl_rwlock);
	vsw_mac_multicast_remove_all(vswp, portp, VSW_VNETPORT);
	vsw_unset_hw(vswp, portp, VSW_VNETPORT);
	vsw_maccl_close(vswp, portp, VSW_VNETPORT);

	if (update_vlans == B_TRUE) {
		if (portp->nvids != 0) {
			kmem_free(portp->vids,
			    sizeof (vsw_vlanid_t) * portp->nvids);
			portp->vids = NULL;
			portp->nvids = 0;
		}
		portp->vids = new_vids;
		portp->nvids = new_nvids;
		portp->pvid = new_pvid;
	}

	/*
	 * Now re-open the mac-client and
	 * configure unicast addr and multicast addrs.
	 */
	rv = vsw_maccl_open(vswp, portp, VSW_VNETPORT);
	if (rv != 0) {
		goto recret;
	}

	if (vsw_set_hw(vswp, portp, VSW_VNETPORT)) {
		cmn_err(CE_NOTE, "!vsw%d: port:%d failed to "
		    "set unicast address\n", vswp->instance, portp->p_instance);
		goto recret;
	}

	vsw_mac_multicast_add_all(vswp, portp, VSW_VNETPORT);

recret:
	RW_EXIT(&portp->maccl_rwlock);
	mutex_exit(&vswp->mac_lock);
	D1(vswp, "%s: exit", __func__);
}
Esempio n. 7
0
int
ipsc_add(caddr_t data)
{
	ipscan_t *i, *isc;
	int err;

	KMALLOC(isc, ipscan_t *);
	if (!isc)
		return ENOMEM;

	err = copyinptr(data, isc, sizeof(*isc));
	if (err) {
		KFREE(isc);
		return err;
	}

	WRITE_ENTER(&ipsc_rwlock);

	i = ipsc_lookup(isc->ipsc_tag);
	if (i) {
		RWLOCK_EXIT(&ipsc_rwlock);
		KFREE(isc);
		return EEXIST;
	}

	if (ipsc_tail) {
		ipsc_tail->ipsc_next = isc;
		isc->ipsc_pnext = &ipsc_tail->ipsc_next;
		ipsc_tail = isc;
	} else {
		ipsc_list = isc;
		ipsc_tail = isc;
		isc->ipsc_pnext = &ipsc_list;
	}
	isc->ipsc_next = NULL;

	isc->ipsc_hits = 0;
	isc->ipsc_fref = 0;
	isc->ipsc_sref = 0;
	isc->ipsc_active = 0;

	ipsc_stat.iscs_entries++;
	RWLOCK_EXIT(&ipsc_rwlock);
	return 0;
}
Esempio n. 8
0
/* ------------------------------------------------------------------------ */
void
ipf_lookup_deref(ipf_main_softc_t *softc, int type, void *ptr)
{
	ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
	int i;

	if (ptr == NULL)
		return;

	for (i = 0; i < MAX_BACKENDS; i++) {
		if (type == backends[i]->ipfl_type) {
			WRITE_ENTER(&softc->ipf_poolrw);
			(*backends[i]->ipfl_table_deref)(softc,
							 softl->ipf_back[i],
							 ptr);
			RWLOCK_EXIT(&softc->ipf_poolrw);
			break;
		}
	}
}
Esempio n. 9
0
int
ipsc_delete(caddr_t data)
{
	ipscan_t isc, *i;
	int err;

	err = copyinptr(data, &isc, sizeof(isc));
	if (err)
		return err;

	WRITE_ENTER(&ipsc_rwlock);

	i = ipsc_lookup(isc.ipsc_tag);
	if (i == NULL)
		err = ENOENT;
	else {
		if (i->ipsc_fref) {
			RWLOCK_EXIT(&ipsc_rwlock);
			return EBUSY;
		}

		*i->ipsc_pnext = i->ipsc_next;
		if (i->ipsc_next)
			i->ipsc_next->ipsc_pnext = i->ipsc_pnext;
		else {
			if (i->ipsc_pnext == &ipsc_list)
				ipsc_tail = NULL;
			else
				ipsc_tail = *(*i->ipsc_pnext)->ipsc_pnext;
		}

		ipsc_stat.iscs_entries--;
		KFREE(i);
	}
	RWLOCK_EXIT(&ipsc_rwlock);
	return err;
}
Esempio n. 10
0
/* ------------------------------------------------------------------------ */
int
ipf_lookup_ioctl(ipf_main_softc_t *softc, void *data, ioctlcmd_t cmd,
    int mode, int uid, void *ctx)
{
	int err;
	SPL_INT(s);

	mode = mode;	/* LINT */

	SPL_NET(s);

	switch (cmd)
	{
	case SIOCLOOKUPADDNODE :
	case SIOCLOOKUPADDNODEW :
		WRITE_ENTER(&softc->ipf_poolrw);
		err = ipf_lookup_addnode(softc, data, uid);
		RWLOCK_EXIT(&softc->ipf_poolrw);
		break;

	case SIOCLOOKUPDELNODE :
	case SIOCLOOKUPDELNODEW :
		WRITE_ENTER(&softc->ipf_poolrw);
		err = ipf_lookup_delnode(softc, data, uid);
		RWLOCK_EXIT(&softc->ipf_poolrw);
		break;

	case SIOCLOOKUPADDTABLE :
		WRITE_ENTER(&softc->ipf_poolrw);
		err = ipf_lookup_addtable(softc, data);
		RWLOCK_EXIT(&softc->ipf_poolrw);
		break;

	case SIOCLOOKUPDELTABLE :
		WRITE_ENTER(&softc->ipf_poolrw);
		err = ipf_lookup_deltable(softc, data);
		RWLOCK_EXIT(&softc->ipf_poolrw);
		break;

	case SIOCLOOKUPSTAT :
	case SIOCLOOKUPSTATW :
		WRITE_ENTER(&softc->ipf_poolrw);
		err = ipf_lookup_stats(softc, data);
		RWLOCK_EXIT(&softc->ipf_poolrw);
		break;

	case SIOCLOOKUPFLUSH :
		WRITE_ENTER(&softc->ipf_poolrw);
		err = ipf_lookup_flush(softc, data);
		RWLOCK_EXIT(&softc->ipf_poolrw);
		break;

	case SIOCLOOKUPITER :
		err = ipf_lookup_iterate(softc, data, uid, ctx);
		break;

	case SIOCIPFDELTOK :
		err = ipf_lookup_deltok(softc, data, uid, ctx);
		break;

	default :
		IPFERROR(50001);
		err = EINVAL;
		break;
	}
	SPL_X(s);
	return err;
}
Esempio n. 11
0
/*
 * Remove a multicast entry from the hashtable.
 *
 * Search hash table based on address. If match found, scan
 * list of ports associated with address. If specified port
 * found remove it from list.
 */
int
vsw_del_mcst(vsw_t *vswp, uint8_t devtype, uint64_t addr, void *arg)
{
	mfdb_ent_t	*ment = NULL;
	mfdb_ent_t	*curr_p, *prev_p;
	void		*tgt = NULL;

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

	if (devtype == VSW_VNETPORT) {
		tgt = (vsw_port_t *)arg;
		D2(vswp, "%s: removing port %d from mFDB for address"
		    " 0x%llx", __func__, ((vsw_port_t *)tgt)->p_instance, addr);
	} else {
		D2(vswp, "%s: removing entry", __func__);
		tgt = (void *)vswp;
	}

	WRITE_ENTER(&vswp->mfdbrw);
	if (mod_hash_find(vswp->mfdb, (mod_hash_key_t)addr,
	    (mod_hash_val_t *)&ment) != 0) {
		D2(vswp, "%s: address 0x%llx not in table", __func__, addr);
		RW_EXIT(&vswp->mfdbrw);
		return (1);
	}

	prev_p = curr_p = ment;

	while (curr_p != NULL) {
		if (curr_p->d_addr == (void *)tgt) {
			if (devtype == VSW_VNETPORT) {
				D2(vswp, "%s: port %d found", __func__,
				    ((vsw_port_t *)tgt)->p_instance);
			} else {
				D2(vswp, "%s: instance found", __func__);
			}

			if (prev_p == curr_p) {
				/*
				 * head of list, if no other element is in
				 * list then destroy this entry, otherwise
				 * just replace it with updated value.
				 */
				ment = curr_p->nextp;
				if (ment == NULL) {
					(void) mod_hash_destroy(vswp->mfdb,
					    (mod_hash_val_t)addr);
				} else {
					(void) mod_hash_replace(vswp->mfdb,
					    (mod_hash_key_t)addr,
					    (mod_hash_val_t)ment);
				}
			} else {
				/*
				 * Not head of list, no need to do
				 * replacement, just adjust list pointers.
				 */
				prev_p->nextp = curr_p->nextp;
			}
			break;
		}

		prev_p = curr_p;
		curr_p = curr_p->nextp;
	}

	RW_EXIT(&vswp->mfdbrw);

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

	if (curr_p == NULL)
		return (1);
	kmem_free(curr_p, sizeof (mfdb_ent_t));
	return (0);
}
Esempio n. 12
0
/*
 * Add a new multicast entry.
 *
 * Search hash table based on address. If match found then
 * update associated val (which is chain of ports), otherwise
 * create new key/val (addr/port) pair and insert into table.
 */
int
vsw_add_mcst(vsw_t *vswp, uint8_t devtype, uint64_t addr, void *arg)
{
	int		dup = 0;
	int		rv = 0;
	mfdb_ent_t	*ment = NULL;
	mfdb_ent_t	*tmp_ent = NULL;
	mfdb_ent_t	*new_ent = NULL;
	void		*tgt = NULL;

	if (devtype == VSW_VNETPORT) {
		/*
		 * Being invoked from a vnet.
		 */
		ASSERT(arg != NULL);
		tgt = arg;
		D2(NULL, "%s: port %d : address 0x%llx", __func__,
		    ((vsw_port_t *)arg)->p_instance, addr);
	} else {
		/*
		 * We are being invoked via the m_multicst mac entry
		 * point.
		 */
		D2(NULL, "%s: address 0x%llx", __func__, addr);
		tgt = (void *)vswp;
	}

	WRITE_ENTER(&vswp->mfdbrw);
	if (mod_hash_find(vswp->mfdb, (mod_hash_key_t)addr,
	    (mod_hash_val_t *)&ment) != 0) {

		/* address not currently in table */
		ment = kmem_alloc(sizeof (mfdb_ent_t), KM_SLEEP);
		ment->d_addr = (void *)tgt;
		ment->d_type = devtype;
		ment->nextp = NULL;

		if (mod_hash_insert(vswp->mfdb, (mod_hash_key_t)addr,
		    (mod_hash_val_t)ment) != 0) {
			DERR(vswp, "%s: hash table insertion failed", __func__);
			kmem_free(ment, sizeof (mfdb_ent_t));
			rv = 1;
		} else {
			D2(vswp, "%s: added initial entry for 0x%llx to "
			    "table", __func__, addr);
		}
	} else {
		/*
		 * Address in table. Check to see if specified port
		 * is already associated with the address. If not add
		 * it now.
		 */
		tmp_ent = ment;
		while (tmp_ent != NULL) {
			if (tmp_ent->d_addr == (void *)tgt) {
				if (devtype == VSW_VNETPORT) {
					DERR(vswp, "%s: duplicate port entry "
					    "found for portid %ld and key "
					    "0x%llx", __func__,
					    ((vsw_port_t *)arg)->p_instance,
					    addr);
				} else {
					DERR(vswp, "%s: duplicate entry found"
					    "for key 0x%llx", __func__, addr);
				}
				rv = 1;
				dup = 1;
				break;
			}
			tmp_ent = tmp_ent->nextp;
		}

		/*
		 * Port not on list so add it to end now.
		 */
		if (0 == dup) {
			D2(vswp, "%s: added entry for 0x%llx to table",
			    __func__, addr);
			new_ent = kmem_alloc(sizeof (mfdb_ent_t), KM_SLEEP);
			new_ent->d_addr = (void *)tgt;
			new_ent->d_type = devtype;
			new_ent->nextp = NULL;

			tmp_ent = ment;
			while (tmp_ent->nextp != NULL)
				tmp_ent = tmp_ent->nextp;

			tmp_ent->nextp = new_ent;
		}
	}

	RW_EXIT(&vswp->mfdbrw);
	return (rv);
}