Ejemplo n.º 1
0
/*
 * Give our ok for a hook to be added...
 * If we are not running this might kick a device into life.
 * Possibly decode information out of the hook name.
 * Add the hook's private info to the hook structure.
 * (if we had some). In this example, we assume that there is a
 * an array of structs, called 'channel' in the private info,
 * one for each active channel. The private
 * pointer of each hook points to the appropriate XXX_hookinfo struct
 * so that the source of an input packet is easily identified.
 * (a dlci is a frame relay channel)
 */
static int
ng_xxx_newhook(node_p node, hook_p hook, const char *name)
{
	const xxx_p xxxp = NG_NODE_PRIVATE(node);
	const char *cp;
	int dlci = 0;
	int chan;

#if 0
	/* Possibly start up the device if it's not already going */
	if ((xxxp->flags & SCF_RUNNING) == 0) {
		ng_xxx_start_hardware(xxxp);
	}
#endif

	/* Example of how one might use hooks with embedded numbers: All
	 * hooks start with 'dlci' and have a decimal trailing channel
	 * number up to 4 digits Use the leadin defined int he associated .h
	 * file. */
	if (strncmp(name,
	    NG_XXX_HOOK_DLCI_LEADIN, strlen(NG_XXX_HOOK_DLCI_LEADIN)) == 0) {
		char *eptr;

		cp = name + strlen(NG_XXX_HOOK_DLCI_LEADIN);
		if (!isdigit(*cp) || (cp[0] == '0' && cp[1] != '\0'))
			return (EINVAL);
		dlci = (int)strtoul(cp, &eptr, 10);
		if (*eptr != '\0' || dlci < 0 || dlci > 1023)
			return (EINVAL);

		/* We have a dlci, now either find it, or allocate it */
		for (chan = 0; chan < XXX_NUM_DLCIS; chan++)
			if (xxxp->channel[chan].dlci == dlci)
				break;
		if (chan == XXX_NUM_DLCIS) {
			for (chan = 0; chan < XXX_NUM_DLCIS; chan++)
				if (xxxp->channel[chan].dlci == -2)
					break;
			if (chan == XXX_NUM_DLCIS)
				return (ENOBUFS);
			xxxp->channel[chan].dlci = dlci;
		}
		if (xxxp->channel[chan].hook != NULL)
			return (EADDRINUSE);
		NG_HOOK_SET_PRIVATE(hook, xxxp->channel + chan);
		xxxp->channel[chan].hook = hook;
		return (0);
	} else if (strcmp(name, NG_XXX_HOOK_DOWNSTREAM) == 0) {
		/* Example of simple predefined hooks. */
		/* do something specific to the downstream connection */
		xxxp->downstream_hook.hook = hook;
		NG_HOOK_SET_PRIVATE(hook, &xxxp->downstream_hook);
	} else if (strcmp(name, NG_XXX_HOOK_DEBUG) == 0) {
		/* do something specific to a debug connection */
		xxxp->debughook = hook;
		NG_HOOK_SET_PRIVATE(hook, NULL);
	} else
		return (EINVAL);	/* not a hook we know about */
	return(0);
}
Ejemplo n.º 2
0
/*
 * Add a hook
 */
static int
ngt_newhook(node_p node, hook_p hook, const char *name)
{
	const sc_p sc = NG_NODE_PRIVATE(node);

	if (strcmp(name, NG_TEE_HOOK_RIGHT) == 0) {
		sc->right.hook = hook;
		bzero(&sc->right.stats, sizeof(sc->right.stats));
		NG_HOOK_SET_PRIVATE(hook, &sc->right);
	} else if (strcmp(name, NG_TEE_HOOK_LEFT) == 0) {
		sc->left.hook = hook;
		bzero(&sc->left.stats, sizeof(sc->left.stats));
		NG_HOOK_SET_PRIVATE(hook, &sc->left);
	} else if (strcmp(name, NG_TEE_HOOK_RIGHT2LEFT) == 0) {
		sc->right2left.hook = hook;
		bzero(&sc->right2left.stats, sizeof(sc->right2left.stats));
		NG_HOOK_SET_PRIVATE(hook, &sc->right2left);
	} else if (strcmp(name, NG_TEE_HOOK_LEFT2RIGHT) == 0) {
		sc->left2right.hook = hook;
		bzero(&sc->left2right.stats, sizeof(sc->left2right.stats));
		NG_HOOK_SET_PRIVATE(hook, &sc->left2right);
	} else
		return (EINVAL);
	return (0);
}
Ejemplo n.º 3
0
static int
ng_vlan_newhook(node_p node, hook_p hook, const char *name)
{
	const priv_p priv = NG_NODE_PRIVATE(node);

	if (strcmp(name, NG_VLAN_HOOK_DOWNSTREAM) == 0)
		priv->downstream_hook = hook;
	else if (strcmp(name, NG_VLAN_HOOK_NOMATCH) == 0)
		priv->nomatch_hook = hook;
	else {
		/*
		 * Any other hook name is valid and can
		 * later be associated with a filter rule.
		 */
	}
	NG_HOOK_SET_PRIVATE(hook, NULL);
	return (0);
}
Ejemplo n.º 4
0
/*
 * The LMI channel has a private pointer which is the same as the
 * node private pointer. The debug channel has a NULL private pointer.
 */
static int
nglmi_newhook(node_p node, hook_p hook, const char *name)
{
	sc_p sc = NG_NODE_PRIVATE(node);

	if (strcmp(name, NG_LMI_HOOK_DEBUG) == 0) {
		NG_HOOK_SET_PRIVATE(hook, NULL);
		return (0);
	}
	if (sc->flags & SCF_CONNECTED) {
		/* already connected, return an error */
		return (EINVAL);
	}
	if (strcmp(name, NG_LMI_HOOK_ANNEXA) == 0) {
		sc->lmi_annexA = hook;
		NG_HOOK_SET_PRIVATE(hook, NG_NODE_PRIVATE(node));
		sc->protoID = 8;
		SETLMITYPE(sc, SCF_ANNEX_A);
		sc->protoname = NAME_ANNEXA;
		nglmi_startup_fixed(sc, hook);
	} else if (strcmp(name, NG_LMI_HOOK_ANNEXD) == 0) {
		sc->lmi_annexD = hook;
		NG_HOOK_SET_PRIVATE(hook, NG_NODE_PRIVATE(node));
		sc->protoID = 8;
		SETLMITYPE(sc, SCF_ANNEX_D);
		sc->protoname = NAME_ANNEXD;
		nglmi_startup_fixed(sc, hook);
	} else if (strcmp(name, NG_LMI_HOOK_GROUPOF4) == 0) {
		sc->lmi_group4 = hook;
		NG_HOOK_SET_PRIVATE(hook, NG_NODE_PRIVATE(node));
		sc->protoID = 9;
		SETLMITYPE(sc, SCF_GROUP4);
		sc->protoname = NAME_GROUP4;
		nglmi_startup_fixed(sc, hook);
	} else if (strcmp(name, NG_LMI_HOOK_AUTO0) == 0) {
		/* Note this, and if B is already installed, we're complete */
		sc->lmi_channel0 = hook;
		sc->protoname = NAME_NONE;
		NG_HOOK_SET_PRIVATE(hook, NG_NODE_PRIVATE(node));
		if (sc->lmi_channel1023)
			nglmi_startup_auto(sc);
	} else if (strcmp(name, NG_LMI_HOOK_AUTO1023) == 0) {
		/* Note this, and if A is already installed, we're complete */
		sc->lmi_channel1023 = hook;
		sc->protoname = NAME_NONE;
		NG_HOOK_SET_PRIVATE(hook, NG_NODE_PRIVATE(node));
		if (sc->lmi_channel0)
			nglmi_startup_auto(sc);
	} else
		return (EINVAL);		/* unknown hook */
	return (0);
}
Ejemplo n.º 5
0
Archivo: udbp.c Proyecto: MarginC/kame
/*
 * Give our ok for a hook to be added...
 * If we are not running this might kick a device into life.
 * Possibly decode information out of the hook name.
 * Add the hook's private info to the hook structure.
 * (if we had some). In this example, we assume that there is a
 * an array of structs, called 'channel' in the private info,
 * one for each active channel. The private
 * pointer of each hook points to the appropriate UDBP_hookinfo struct
 * so that the source of an input packet is easily identified.
 */
Static int
ng_udbp_newhook(node_p node, hook_p hook, const char *name)
{
	const udbp_p sc = NG_NODE_PRIVATE(node);

#if 0
	/* Possibly start up the device if it's not already going */
	if ((sc->flags & SCF_RUNNING) == 0) {
		ng_udbp_start_hardware(sc);
	}
#endif

	if (strcmp(name, NG_UDBP_HOOK_NAME) == 0) {
		sc->hook = hook;
		NG_HOOK_SET_PRIVATE(hook, NULL);
	} else {
		return (EINVAL);	/* not a hook we know about */
	}
	return(0);
}
Ejemplo n.º 6
0
/*
 * Give our ok for a hook to be added
 */
static int
ng_split_newhook(node_p node, hook_p hook, const char *name)
{
	priv_p		priv = NG_NODE_PRIVATE(node);
	hook_p		*localhook;

	if (strcmp(name, NG_SPLIT_HOOK_MIXED) == 0) {
		localhook = &priv->mixed;
	} else if (strcmp(name, NG_SPLIT_HOOK_IN) == 0) {
		localhook = &priv->in;
	} else if (strcmp(name, NG_SPLIT_HOOK_OUT) == 0) {
		localhook = &priv->out;
	} else
		return (EINVAL);

	if (*localhook != NULL)
		return (EISCONN);
	*localhook = hook;
	NG_HOOK_SET_PRIVATE(hook, localhook);

	return (0);
}
Ejemplo n.º 7
0
static int
ng_vlan_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
	const priv_p priv = NG_NODE_PRIVATE(node);
	struct ng_mesg *msg, *resp = NULL;
	struct ng_vlan_filter *vf;
	hook_p hook;
	struct ng_vlan_table *t;
	uintptr_t hook_data;
	int i, vlan_count;
	uint16_t vid;
	int error = 0;

	NGI_GET_MSG(item, msg);
	/* Deal with message according to cookie and command. */
	switch (msg->header.typecookie) {
	case NGM_VLAN_COOKIE:
		switch (msg->header.cmd) {
		case NGM_VLAN_ADD_FILTER:
			/* Check that message is long enough. */
			if (msg->header.arglen != sizeof(*vf)) {
				error = EINVAL;
				break;
			}
			vf = (struct ng_vlan_filter *)msg->data;
			/* Sanity check the VLAN ID value. */
#ifdef	NG_VLAN_USE_OLD_VLAN_NAME
			if (vf->vid == 0 && vf->vid != vf->vlan) {
				vf->vid = vf->vlan;
			} else if (vf->vid != 0 && vf->vlan != 0 &&
			    vf->vid != vf->vlan) {
				error = EINVAL;
				break;
			}
#endif
			if (vf->vid & ~EVL_VLID_MASK ||
			    vf->pcp & ~7 ||
			    vf->cfi & ~1) {
				error = EINVAL;
				break;
			}
			/* Check that a referenced hook exists. */
			hook = ng_findhook(node, vf->hook_name);
			if (hook == NULL) {
				error = ENOENT;
				break;
			}
			/* And is not one of the special hooks. */
			if (hook == priv->downstream_hook ||
			    hook == priv->nomatch_hook) {
				error = EINVAL;
				break;
			}
			/* And is not already in service. */
			if (IS_HOOK_VLAN_SET(NG_HOOK_PRIVATE(hook))) {
				error = EEXIST;
				break;
			}
			/* Check we don't already trap this VLAN. */
			if (priv->vlan_hook[vf->vid] != NULL) {
				error = EEXIST;
				break;
			}
			/* Link vlan and hook together. */
			NG_HOOK_SET_PRIVATE(hook,
			    (void *)(HOOK_VLAN_TAG_SET_MASK |
			    EVL_MAKETAG(vf->vid, vf->pcp, vf->cfi)));
			priv->vlan_hook[vf->vid] = hook;
			break;
		case NGM_VLAN_DEL_FILTER:
			/* Check that message is long enough. */
			if (msg->header.arglen != NG_HOOKSIZ) {
				error = EINVAL;
				break;
			}
			/* Check that hook exists and is active. */
			hook = ng_findhook(node, (char *)msg->data);
			if (hook == NULL) {
				error = ENOENT;
				break;
			}
			hook_data = (uintptr_t)NG_HOOK_PRIVATE(hook);
			if (IS_HOOK_VLAN_SET(hook_data) == 0) {
				error = ENOENT;
				break;
			}

			KASSERT(priv->vlan_hook[EVL_VLANOFTAG(hook_data)] == hook,
			    ("%s: NGM_VLAN_DEL_FILTER: Invalid VID for Hook = %s\n",
			    __func__, (char *)msg->data));

			/* Purge a rule that refers to this hook. */
			priv->vlan_hook[EVL_VLANOFTAG(hook_data)] = NULL;
			NG_HOOK_SET_PRIVATE(hook, NULL);
			break;
		case NGM_VLAN_DEL_VID_FLT:
			/* Check that message is long enough. */
			if (msg->header.arglen != sizeof(uint16_t)) {
				error = EINVAL;
				break;
			}
			vid = (*((uint16_t *)msg->data));
			/* Sanity check the VLAN ID value. */
			if (vid & ~EVL_VLID_MASK) {
				error = EINVAL;
				break;
			}
			/* Check that hook exists and is active. */
			hook = priv->vlan_hook[vid];
			if (hook == NULL) {
				error = ENOENT;
				break;
			}
			hook_data = (uintptr_t)NG_HOOK_PRIVATE(hook);
			if (IS_HOOK_VLAN_SET(hook_data) == 0) {
				error = ENOENT;
				break;
			}

			KASSERT(EVL_VLANOFTAG(hook_data) == vid,
			    ("%s: NGM_VLAN_DEL_VID_FLT:"
			    " Invalid VID Hook = %us, must be: %us\n",
			    __func__, (uint16_t )EVL_VLANOFTAG(hook_data),
			    vid));

			/* Purge a rule that refers to this hook. */
			priv->vlan_hook[vid] = NULL;
			NG_HOOK_SET_PRIVATE(hook, NULL);
			break;
		case NGM_VLAN_GET_TABLE:
			/* Calculate vlans. */
			vlan_count = 0;
			for (i = 0; i < (EVL_VLID_MASK + 1); i ++) {
				if (priv->vlan_hook[i] != NULL &&
				    NG_HOOK_IS_VALID(priv->vlan_hook[i]))
					vlan_count ++;
			}

			/* Allocate memory for responce. */
			NG_MKRESPONSE(resp, msg, sizeof(*t) +
			    vlan_count * sizeof(*t->filter), M_NOWAIT);
			if (resp == NULL) {
				error = ENOMEM;
				break;
			}

			/* Pack data to responce. */
			t = (struct ng_vlan_table *)resp->data;
			t->n = 0;
			vf = &t->filter[0];
			for (i = 0; i < (EVL_VLID_MASK + 1); i ++) {
				hook = priv->vlan_hook[i];
				if (hook == NULL || NG_HOOK_NOT_VALID(hook))
					continue;
				hook_data = (uintptr_t)NG_HOOK_PRIVATE(hook);
				if (IS_HOOK_VLAN_SET(hook_data) == 0)
					continue;

				KASSERT(EVL_VLANOFTAG(hook_data) == i,
				    ("%s: NGM_VLAN_GET_TABLE:"
				    " hook %s VID = %us, must be: %i\n",
				    __func__, NG_HOOK_NAME(hook),
				    (uint16_t)EVL_VLANOFTAG(hook_data), i));

#ifdef	NG_VLAN_USE_OLD_VLAN_NAME
				vf->vlan = i;
#endif
				vf->vid = i;
				vf->pcp = EVL_PRIOFTAG(hook_data);
				vf->cfi = EVL_CFIOFTAG(hook_data);
				strncpy(vf->hook_name,
				    NG_HOOK_NAME(hook), NG_HOOKSIZ);
				vf ++;
				t->n ++;
			}
			break;
		case NGM_VLAN_GET_DECAP:
			NG_MKRESPONSE(resp, msg, sizeof(uint32_t), M_NOWAIT);
			if (resp == NULL) {
				error = ENOMEM;
				break;
			}
			(*((uint32_t *)resp->data)) = priv->decap_enable;
			break;
		case NGM_VLAN_SET_DECAP:
			if (msg->header.arglen != sizeof(uint32_t)) {
				error = EINVAL;
				break;
			}
			priv->decap_enable = (*((uint32_t *)msg->data));
			break;
		case NGM_VLAN_GET_ENCAP:
			NG_MKRESPONSE(resp, msg, sizeof(uint32_t), M_NOWAIT);
			if (resp == NULL) {
				error = ENOMEM;
				break;
			}
			(*((uint32_t *)resp->data)) = priv->encap_enable;
			break;
		case NGM_VLAN_SET_ENCAP:
			if (msg->header.arglen != sizeof(uint32_t)) {
				error = EINVAL;
				break;
			}
			priv->encap_enable = (*((uint32_t *)msg->data));
			break;
		case NGM_VLAN_GET_ENCAP_PROTO:
			NG_MKRESPONSE(resp, msg, sizeof(uint16_t), M_NOWAIT);
			if (resp == NULL) {
				error = ENOMEM;
				break;
			}
			(*((uint16_t *)resp->data)) = ntohs(priv->encap_proto);
			break;
		case NGM_VLAN_SET_ENCAP_PROTO:
			if (msg->header.arglen != sizeof(uint16_t)) {
				error = EINVAL;
				break;
			}
			priv->encap_proto = htons((*((uint16_t *)msg->data)));
			break;
		default: /* Unknown command. */
			error = EINVAL;
			break;
		}
		break;
	case NGM_FLOW_COOKIE:
	    {
		struct ng_mesg *copy;

		/*
		 * Flow control messages should come only
		 * from downstream.
		 */

		if (lasthook == NULL)
			break;
		if (lasthook != priv->downstream_hook)
			break;
		/* Broadcast the event to all uplinks. */
		for (i = 0; i < (EVL_VLID_MASK + 1); i ++) {
			if (priv->vlan_hook[i] == NULL)
				continue;

			NG_COPYMESSAGE(copy, msg, M_NOWAIT);
			if (copy == NULL)
				continue;
			NG_SEND_MSG_HOOK(error, node, copy,
			    priv->vlan_hook[i], 0);
		}
		break;
	    }
	default: /* Unknown type cookie. */
		error = EINVAL;
		break;
	}
	NG_RESPOND_MSG(error, node, item, resp);
	NG_FREE_MSG(msg);
	return (error);
}
Ejemplo n.º 8
0
/*
 * We allow any hook to be connected to the node.
 * There is no per-hook private information though.
 */
static int
ngs_newhook(node_p node, hook_p hook, const char *name)
{
	NG_HOOK_SET_PRIVATE(hook, NG_NODE_PRIVATE(node));
	return (0);
}
Ejemplo n.º 9
0
/*
 * Add a new hook
 *
 * We allow hooks called "debug", "downstream" and dlci[0-1023]
 * The hook's private info points to our stash of info about that
 * channel. A NULL pointer is debug and a DLCI of -1 means downstream.
 */
static int
ngfrm_newhook(node_p node, hook_p hook, const char *name)
{
	const sc_p sc = NG_NODE_PRIVATE(node);
	const char *cp;
	char *eptr;
	int dlci = 0;
	int ctxnum;

	/* Check if it's our friend the control hook */
	if (strcmp(name, NG_FRAMERELAY_HOOK_DEBUG) == 0) {
		NG_HOOK_SET_PRIVATE(hook, NULL);	/* paranoid */
		return (0);
	}

	/*
	 * All other hooks either start with 'dlci' and have a decimal
	 * trailing channel number up to 4 digits, or are the downstream
	 * hook.
	 */
	if (strncmp(name, NG_FRAMERELAY_HOOK_DLCI,
	    strlen(NG_FRAMERELAY_HOOK_DLCI)) != 0) {

		/* It must be the downstream connection */
		if (strcmp(name, NG_FRAMERELAY_HOOK_DOWNSTREAM) != 0)
			return EINVAL;

		/* Make sure we haven't already got one (paranoid) */
		if (sc->downstream.hook)
			return (EADDRINUSE);

		/* OK add it */
		NG_HOOK_SET_PRIVATE(hook, &sc->downstream);
		sc->downstream.hook = hook;
		sc->downstream.dlci = -1;
		sc->downstream.flags |= CHAN_ACTIVE;
		sc->datahooks++;
		return (0);
	}

	/* Must be a dlci hook at this point */
	cp = name + strlen(NG_FRAMERELAY_HOOK_DLCI);
	if (!isdigit(*cp) || (cp[0] == '0' && cp[1] != '\0'))
		return (EINVAL);
	dlci = (int)strtoul(cp, &eptr, 10);
	if (*eptr != '\0' || dlci < 0 || dlci > 1023)
		return (EINVAL);

	/*
	 * We have a dlci, now either find it, or allocate it. It's possible
	 * that we might have seen packets for it already and made an entry
	 * for it.
	 */
	ctxnum = ngfrm_allocate_CTX(sc, dlci);
	if (ctxnum == -1)
		return (ENOBUFS);

	/*
	 * Be paranoid: if it's got a hook already, that dlci is in use .
	 * Generic code can not catch all the synonyms (e.g. dlci016 vs
	 * dlci16)
	 */
	if (sc->channel[ctxnum].hook != NULL)
		return (EADDRINUSE);

	/*
	 * Put our hooks into it (pun not intended)
	 */
	sc->channel[ctxnum].flags |= CHAN_ACTIVE;
	NG_HOOK_SET_PRIVATE(hook, sc->channel + ctxnum);
	sc->channel[ctxnum].hook = hook;
	sc->datahooks++;
	return (0);
}