Esempio n. 1
0
static void
sscfu_send_lower(struct sscfu *sscf, void *p, enum sscop_aasig sig,
    struct mbuf *m, u_int arg)
{
	node_p node = (node_p)p;
	struct priv *priv = NG_NODE_PRIVATE(node);
	int error;
	struct sscop_arg *a;

	if (priv->lower == NULL) {
		if (m != NULL)
			m_freem(m);
		return;
	}
	if (m == NULL) {
		MGETHDR(m, M_NOWAIT, MT_DATA);
		if (m == NULL)
			return;
		m->m_len = sizeof(struct sscop_arg);
		m->m_pkthdr.len = m->m_len;
	} else {
		M_PREPEND(m, sizeof(struct sscop_arg), M_NOWAIT);
		if (m == NULL)
			return;
	}
	a = mtod(m, struct sscop_arg *);
	a->sig = sig;
	a->arg = arg;

	NG_SEND_DATA_ONLY(error, priv->lower, m);
}
Esempio n. 2
0
/*
 * Add a new hook
 */
static int
ng_vjc_newhook(node_p node, hook_p hook, const char *name)
{
	const priv_p priv = NG_NODE_PRIVATE(node);
	hook_p *hookp;

	/* Get hook */
	if (strcmp(name, NG_VJC_HOOK_IP) == 0)
		hookp = &priv->ip;
	else if (strcmp(name, NG_VJC_HOOK_VJCOMP) == 0)
		hookp = &priv->vjcomp;
	else if (strcmp(name, NG_VJC_HOOK_VJUNCOMP) == 0)
		hookp = &priv->vjuncomp;
	else if (strcmp(name, NG_VJC_HOOK_VJIP) == 0)
		hookp = &priv->vjip;
	else
		return (EINVAL);

	/* See if already connected */
	if (*hookp)
		return (EISCONN);

	/* OK */
	*hookp = hook;
	return (0);
}
Esempio n. 3
0
static int
ng_sscfu_rcvlower(hook_p hook, item_p item)
{
	node_p node = NG_HOOK_NODE(hook);
	struct priv *priv = NG_NODE_PRIVATE(node);
	struct mbuf *m;
	struct sscop_arg a;

	if (!priv->enabled || priv->upper == NULL) {
		NG_FREE_ITEM(item);
		return (0);
	}

	NGI_GET_M(item, m);
	NG_FREE_ITEM(item);

	if (!(m->m_flags & M_PKTHDR)) {
		printf("no pkthdr\n");
		m_freem(m);
		return (EINVAL);
	}

	/*
	 * Strip of the SSCOP header.
	 */
	if (m->m_len < (int)sizeof(a) && (m = m_pullup(m, sizeof(a))) == NULL)
		return (ENOMEM);
	bcopy((caddr_t)mtod(m, struct sscop_arg *), &a, sizeof(a));
	m_adj(m, sizeof(a));

	sscfu_input(priv->sscf, a.sig, m, a.arg);

	return (0);
}
Esempio n. 4
0
static void
bt3c_forward(node_p node, hook_p hook, void *arg1, int arg2)
{
	bt3c_softc_p	 sc = (bt3c_softc_p) NG_NODE_PRIVATE(node);
	struct mbuf	*m = NULL;
	int		 error;

	if (sc == NULL)
		return;

	if (sc->hook != NULL && NG_HOOK_IS_VALID(sc->hook)) {
		for (;;) {
			IF_DEQUEUE(&sc->inq, m);
			if (m == NULL)
				break;

			NG_SEND_DATA_ONLY(error, sc->hook, m);
			if (error != 0)
				NG_BT3C_STAT_IERROR(sc->stat);
		}
	} else {
		IF_LOCK(&sc->inq);
		for (;;) {
			_IF_DEQUEUE(&sc->inq, m);
			if (m == NULL)
				break;

			NG_BT3C_STAT_IERROR(sc->stat);
			NG_FREE_M(m);
		}
		IF_UNLOCK(&sc->inq);
	}
} /* bt3c_forward */
Esempio n. 5
0
/*
 * Destroy node
 */
static int
ng_ksocket_shutdown(node_p node)
{
	const priv_p priv = NG_NODE_PRIVATE(node);
	priv_p embryo;

	/* Close our socket (if any) */
	if (priv->so != NULL) {
		atomic_clear_int(&priv->so->so_rcv.ssb_flags, SSB_UPCALL);
		atomic_clear_int(&priv->so->so_snd.ssb_flags, SSB_UPCALL);
		priv->so->so_upcall = NULL;
		soclose(priv->so, FNONBLOCK);
		priv->so = NULL;
	}

	/* If we are an embryo, take ourselves out of the parent's list */
	if (priv->flags & KSF_EMBRYONIC) {
		LIST_REMOVE(priv, siblings);
		priv->flags &= ~KSF_EMBRYONIC;
	}

	/* Remove any embryonic children we have */
	while (!LIST_EMPTY(&priv->embryos)) {
		embryo = LIST_FIRST(&priv->embryos);
		ng_rmnode_self(embryo->node);
	}

	/* Take down netgraph node */
	bzero(priv, sizeof(*priv));
	kfree(priv, M_NETGRAPH);
	NG_NODE_SET_PRIVATE(node, NULL);
	NG_NODE_UNREF(node);		/* let the node escape */
	return (0);
}
Esempio n. 6
0
static int
ng_sscop_rcvupper(hook_p hook, item_p item)
{
	struct priv *priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
	struct sscop_arg a;
	struct mbuf *m;

	if (!priv->enabled) {
		NG_FREE_ITEM(item);
		return (EINVAL);
	}

	/*
	 * If the lower layer is not connected allow to proceed.
	 * The lower layer sending function will drop outgoing frames,
	 * and the sscop will timeout any establish requests.
	 */
	NGI_GET_M(item, m);
	NG_FREE_ITEM(item);

	if (!(m->m_flags & M_PKTHDR)) {
		printf("no pkthdr\n");
		m_freem(m);
		return (EINVAL);
	}
	if (m->m_len < (int)sizeof(a) && (m = m_pullup(m, sizeof(a))) == NULL)
		return (ENOBUFS);
	bcopy((caddr_t)mtod(m, struct sscop_arg *), &a, sizeof(a));
	m_adj(m, sizeof(a));

	return (sscop_aasig(priv->sscop, a.sig, m, a.arg));
}
Esempio n. 7
0
static void
sscop_send_manage(struct sscop *sscop, void *p, enum sscop_maasig sig,
    struct SSCOP_MBUF_T *m, u_int err, u_int cnt)
{
	node_p node = (node_p)p;
	struct priv *priv = NG_NODE_PRIVATE(node);
	int error;
	struct sscop_merr *e;
	struct sscop_marg *a;

	if (priv->manage == NULL) {
		if (m != NULL)
			m_freem(m);
		priv->stats.maa_dropped++;
		return;
	}

	if (sig == SSCOP_MERROR_indication) {
		MGETHDR(m, M_NOWAIT, MT_DATA);
		if (m == NULL)
			return;
		m->m_len = sizeof(*e);
		m->m_pkthdr.len = m->m_len;
		e = mtod(m, struct sscop_merr *);
		e->sig = sig;
		e->err = err;
		e->cnt = cnt;
		priv->stats.errors++;
	} else if (m == NULL) {
Esempio n. 8
0
/*
 * DATA
 */
static int
ng_sscop_rcvlower(hook_p hook, item_p item)
{
	struct priv *priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
	struct mbuf *m;

	if (!priv->enabled) {
		NG_FREE_ITEM(item);
		return EINVAL;
	}

	/*
	 * If we are disconnected at the upper layer and in the IDLE
	 * state, drop any incoming packet.
	 */
	if (priv->upper != NULL || sscop_getstate(priv->sscop) != SSCOP_IDLE) {
		NGI_GET_M(item, m);
		priv->stats.in_packets++;
		sscop_input(priv->sscop, m);
	} else {
		priv->stats.in_dropped++;
	}
	NG_FREE_ITEM(item);

	return (0);
}
Esempio n. 9
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);
}
Esempio n. 10
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);
}
Esempio n. 11
0
/*
 * Receive incoming data on our hook.  Send it out the socket.
 */
static int
ng_ksocket_rcvdata(hook_p hook, item_p item)
{
	struct thread *td = curthread;	/* XXX broken */
	const node_p node = NG_HOOK_NODE(hook);
	const priv_p priv = NG_NODE_PRIVATE(node);
	struct socket *const so = priv->so;
	struct sockaddr *sa = NULL;
	int error;
	struct mbuf *m;
	struct sa_tag *stag;

	/* Extract data */
	NGI_GET_M(item, m);
	NG_FREE_ITEM(item);

	/*
	 * Look if socket address is stored in packet tags.
	 * If sockaddr is ours, or provided by a third party (zero id),
	 * then we accept it.
	 */
	if (((stag = (struct sa_tag *)m_tag_locate(m, NGM_KSOCKET_COOKIE,
	    NG_KSOCKET_TAG_SOCKADDR, NULL)) != NULL) &&
	    (stag->id == NG_NODE_ID(node) || stag->id == 0))
		sa = &stag->sa;

	/* Reset specific mbuf flags to prevent addressing problems. */
	m->m_flags &= ~(M_BCAST|M_MCAST);

	/* Send packet */
	error = sosend(so, sa, 0, m, 0, 0, td);

	return (error);
}
Esempio n. 12
0
static int
ng_bt3c_shutdown(node_p node)
{
	bt3c_softc_p	sc = (bt3c_softc_p) NG_NODE_PRIVATE(node);

	/* Let old node go */
	NG_NODE_SET_PRIVATE(node, NULL);
	NG_NODE_UNREF(node);

	/* Create new fresh one if we are not going down */
	if (sc == NULL)
		goto out;

	/* Create new Netgraph node */
	if (ng_make_node_common(&typestruct, &sc->node) != 0) {
		device_printf(sc->dev, "Could not create Netgraph node\n");
		sc->node = NULL;
		goto out;
	}

	/* Name new Netgraph node */
	if (ng_name_node(sc->node,  device_get_nameunit(sc->dev)) != 0) {
		device_printf(sc->dev, "Could not name Netgraph node\n");
		NG_NODE_UNREF(sc->node);
		sc->node = NULL;
		goto out;
	}

	NG_NODE_SET_PRIVATE(sc->node, sc);
out:
	return (0);
} /* ng_bt3c_shutdown */
Esempio n. 13
0
static int
ng_sscop_disconnect(hook_p hook)
{
	node_p node = NG_HOOK_NODE(hook);
	struct priv *priv = NG_NODE_PRIVATE(node);

	if(hook == priv->upper)
		priv->upper = NULL;
	else if(hook == priv->lower)
		priv->lower = NULL;
	else if(hook == priv->manage)
		priv->manage = NULL;

	if(NG_NODE_NUMHOOKS(node) == 0) {
		if(NG_NODE_IS_VALID(node))
			ng_rmnode_self(node);
	} else {
		/*
		 * Imply a release request, if the upper layer is
		 * disconnected.
		 */
		if(priv->upper == NULL && priv->lower != NULL &&
		   priv->enabled &&
		   sscop_getstate(priv->sscop) != SSCOP_IDLE) {
			sscop_aasig(priv->sscop, SSCOP_RELEASE_request,
			    NULL, 0);
		}
	}
	return 0;
}
Esempio n. 14
0
static int
ng_sscfu_disconnect(hook_p hook)
{
	node_p node = NG_HOOK_NODE(hook);
	struct priv *priv = NG_NODE_PRIVATE(node);

	if (hook == priv->upper)
		priv->upper = NULL;
	else if (hook == priv->lower)
		priv->lower = NULL;
	else {
		log(LOG_ERR, "bogus hook");
		return (EINVAL);
	}

	if (NG_NODE_NUMHOOKS(node) == 0) {
		if (NG_NODE_IS_VALID(node))
			ng_rmnode_self(node);
	} else {
		/*
		 * Because there are no timeouts reset the protocol
		 * if the lower layer is disconnected.
		 */
		if (priv->lower == NULL &&
		    priv->enabled &&
		    sscfu_getstate(priv->sscf) != SSCFU_RELEASED)
			sscfu_reset(priv->sscf);
	}
	return (0);
}
Esempio n. 15
0
static int
ng_ubt_disconnect(hook_p hook)
{
	struct ubt_softc	*sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));

	UBT_NG_LOCK(sc);

	if (hook != sc->sc_hook) {
		UBT_NG_UNLOCK(sc);

		return (EINVAL);
	}

	sc->sc_hook = NULL;

	/* Kick off task to stop all USB xfers */
	ubt_task_schedule(sc, UBT_FLAG_T_STOP_ALL);

	/* Drain queues */
	NG_BT_MBUFQ_DRAIN(&sc->sc_cmdq);
	NG_BT_MBUFQ_DRAIN(&sc->sc_aclq);
	NG_BT_MBUFQ_DRAIN(&sc->sc_scoq);

	UBT_NG_UNLOCK(sc);

	return (0);
} /* ng_ubt_disconnect */
Esempio n. 16
0
/*
 * Do local shutdown processing..
 * All our links and the name have already been removed.
 * If we are a persistant device, we might refuse to go away.
 * In the case of a persistant node we signal the framework that we
 * are still in business by clearing the NGF_INVALID bit. However
 * If we find the NGF_REALLY_DIE bit set, this means that
 * we REALLY need to die (e.g. hardware removed).
 * This would have been set using the NG_NODE_REALLY_DIE(node)
 * macro in some device dependent function (not shown here) before
 * calling ng_rmnode_self().
 */
static int
ng_xxx_shutdown(node_p node)
{
	const xxx_p privdata = NG_NODE_PRIVATE(node);

#ifndef PERSISTANT_NODE
	NG_NODE_SET_PRIVATE(node, NULL);
	NG_NODE_UNREF(node);
	free(privdata, M_NETGRAPH);
#else
	if (node->nd_flags & NGF_REALLY_DIE) {
		/*
		 * WE came here because the widget card is being unloaded,
		 * so stop being persistant.
		 * Actually undo all the things we did on creation.
		 */
		NG_NODE_SET_PRIVATE(node, NULL);
		NG_NODE_UNREF(privdata->node);
		free(privdata, M_NETGRAPH);
		return (0);
	}
	NG_NODE_REVIVE(node);		/* tell ng_rmnode() we will persist */
#endif /* PERSISTANT_NODE */
	return (0);
}
Esempio n. 17
0
/*
 * Decode an incoming frame coming from the switch
 */
static int
ngfrm_decode(node_p node, item_p item)
{
	const sc_p  sc = NG_NODE_PRIVATE(node);
	char       *data;
	int         alen;
	u_int	    dlci = 0;
	int	    error = 0;
	int	    ctxnum;
	struct mbuf *m;

	NGI_GET_M(item, m);
	if (m->m_len < 4 && (m = m_pullup(m, 4)) == NULL) {
		error = ENOBUFS;
		goto out;
	}
	data = mtod(m, char *);
	if ((alen = sc->addrlen) == 0) {
		sc->addrlen = alen = ngfrm_addrlen(data);
	}
	switch (alen) {
	case 2:
		SHIFTIN(makeup + 0, data[0], dlci);
		SHIFTIN(makeup + 1, data[1], dlci);
		break;
	case 3:
		SHIFTIN(makeup + 0, data[0], dlci);
		SHIFTIN(makeup + 1, data[1], dlci);
		SHIFTIN(makeup + 3, data[2], dlci);	/* 3 and 2 is correct */
		break;
	case 4:
		SHIFTIN(makeup + 0, data[0], dlci);
		SHIFTIN(makeup + 1, data[1], dlci);
		SHIFTIN(makeup + 2, data[2], dlci);
		SHIFTIN(makeup + 3, data[3], dlci);
		break;
	default:
		error = EINVAL;
		goto out;
	}

	if (dlci > 1023) {
		error = EINVAL;
		goto out;
	}
	ctxnum = sc->ALT[dlci];
	if ((ctxnum & CTX_VALID) && sc->channel[ctxnum &= CTX_VALUE].hook) {
		/* Send it */
		m_adj(m, alen);
		NG_FWD_NEW_DATA(error, item, sc->channel[ctxnum].hook, m);
		return (error);
	} else {
		error = ENETDOWN;
	}
out:
	NG_FREE_ITEM(item);
	NG_FREE_M(m);
	return (error);
}
Esempio n. 18
0
/*
 * Receive data, and do something with it.
 * Actually we receive a queue item which holds the data.
 * If we free the item it will also free the data unless we have
 * previously disassociated it using the NGI_GET_M() macro.
 * Possibly send it out on another link after processing.
 * Possibly do something different if it comes from different
 * hooks. The caller will never free m, so if we use up this data or
 * abort we must free it.
 *
 * If we want, we may decide to force this data to be queued and reprocessed
 * at the netgraph NETISR time.
 * We would do that by setting the HK_QUEUE flag on our hook. We would do that
 * in the connect() method.
 */
static int
ng_xxx_rcvdata(hook_p hook, item_p item )
{
	const xxx_p xxxp = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
	int chan = -2;
	int dlci = -2;
	int error;
	struct mbuf *m;

	NGI_GET_M(item, m);
	if (NG_HOOK_PRIVATE(hook)) {
		dlci = ((struct XXX_hookinfo *) NG_HOOK_PRIVATE(hook))->dlci;
		chan = ((struct XXX_hookinfo *) NG_HOOK_PRIVATE(hook))->channel;
		if (dlci != -1) {
			/* If received on a DLCI hook process for this
			 * channel and pass it to the downstream module.
			 * Normally one would add a multiplexing header at
			 * the front here */
			/* M_PREPEND(....)	; */
			/* mtod(m, xxxxxx)->dlci = dlci; */
			NG_FWD_NEW_DATA(error, item,
				xxxp->downstream_hook.hook, m);
			xxxp->packets_out++;
		} else {
			/* data came from the multiplexed link */
			dlci = 1;	/* get dlci from header */
			/* madjust(....) *//* chop off header */
			for (chan = 0; chan < XXX_NUM_DLCIS; chan++)
				if (xxxp->channel[chan].dlci == dlci)
					break;
			if (chan == XXX_NUM_DLCIS) {
				NG_FREE_ITEM(item);
				NG_FREE_M(m);
				return (ENETUNREACH);
			}
			/* If we were called at splnet, use the following:
			 * NG_SEND_DATA_ONLY(error, otherhook, m); if this
			 * node is running at some SPL other than SPLNET
			 * then you should use instead: error =
			 * ng_queueit(otherhook, m, NULL); m = NULL;
			 * This queues the data using the standard NETISR
			 * system and schedules the data to be picked
			 * up again once the system has moved to SPLNET and
			 * the processing of the data can continue. After
			 * these are run 'm' should be considered
			 * as invalid and NG_SEND_DATA actually zaps them. */
			NG_FWD_NEW_DATA(error, item,
				xxxp->channel[chan].hook, m);
			xxxp->packets_in++;
		}
	} else {
		/* It's the debug hook, throw it away.. */
		if (hook == xxxp->downstream_hook.hook) {
			NG_FREE_ITEM(item);
			NG_FREE_M(m);
		}
	}
	return 0;
}
Esempio n. 19
0
static int
ng_ksocket_connect(hook_p hook)
{
	node_p node = NG_HOOK_NODE(hook);
	const priv_p priv = NG_NODE_PRIVATE(node);
	struct socket *const so = priv->so;

	/* Add our hook for incoming data and other events */
	priv->so->so_upcallarg = (caddr_t)node;
	priv->so->so_upcall = ng_ksocket_incoming;
	SOCKBUF_LOCK(&priv->so->so_rcv);
	priv->so->so_rcv.sb_flags |= SB_UPCALL;
	SOCKBUF_UNLOCK(&priv->so->so_rcv);
	SOCKBUF_LOCK(&priv->so->so_snd);
	priv->so->so_snd.sb_flags |= SB_UPCALL;
	SOCKBUF_UNLOCK(&priv->so->so_snd);
	SOCK_LOCK(priv->so);
	sosetstate(priv->so, SS_NBIO);
	SOCK_UNLOCK(priv->so);
	/*
	 * --Original comment--
	 * On a cloned socket we may have already received one or more
	 * upcalls which we couldn't handle without a hook.  Handle
	 * those now.
	 * We cannot call the upcall function directly
	 * from here, because until this function has returned our
	 * hook isn't connected.
	 *
	 * ---meta comment for -current ---
	 * XXX This is dubius.
	 * Upcalls between the time that the hook was
	 * first created and now (on another processesor) will
	 * be earlier on the queue than the request to finalise the hook.
	 * By the time the hook is finalised,
	 * The queued upcalls will have happenned and the code
	 * will have discarded them because of a lack of a hook.
	 * (socket not open).
	 *
	 * This is a bad byproduct of the complicated way in which hooks
	 * are now created (3 daisy chained async events).
	 *
	 * Since we are a netgraph operation 
	 * We know that we hold a lock on this node. This forces the
	 * request we make below to be queued rather than implemented
	 * immediatly which will cause the upcall function to be called a bit
	 * later.
	 * However, as we will run any waiting queued operations immediatly
	 * after doing this one, if we have not finalised the other end
	 * of the hook, those queued operations will fail.
	 */
	if (priv->flags & KSF_CLONED) {
		ng_send_fn(node, NULL, &ng_ksocket_incoming2, so, M_WAITOK | M_NULLOK);
	}

	return (0);
}
Esempio n. 20
0
/*
 * Connect the data socket to a named control socket node.
 */
static int
ng_connect_data(struct sockaddr *nam, struct ngpcb *pcbp)
{
	struct sockaddr_ng *sap;
	node_p farnode;
	struct ngsock *priv;
	int error;
	item_p item;

	/* If we are already connected, don't do it again. */
	if (pcbp->sockdata != NULL)
		return (EISCONN);

	/*
	 * Find the target (victim) and check it doesn't already have
	 * a data socket. Also check it is a 'socket' type node.
	 * Use ng_package_data() and ng_address_path() to do this.
	 */

	sap = (struct sockaddr_ng *) nam;
	/* The item will hold the node reference. */
	item = ng_package_data(NULL, NG_WAITOK);

	if ((error = ng_address_path(NULL, item,  sap->sg_data, 0))) {
		ng_free_item(item);
		return (error);
	}

	/*
	 * Extract node from item and free item. Remember we now have
	 * a reference on the node. The item holds it for us.
	 * when we free the item we release the reference.
	 */
	farnode = item->el_dest; /* shortcut */
	if (strcmp(farnode->nd_type->name, NG_SOCKET_NODE_TYPE) != 0) {
		ng_free_item(item); /* drop the reference to the node */
		return (EINVAL);
	}
	priv = NG_NODE_PRIVATE(farnode);
	if (priv->datasock != NULL) {
		ng_free_item(item);	/* drop the reference to the node */
		return (EADDRINUSE);
	}

	/*
	 * Link the PCB and the private data struct. and note the extra
	 * reference. Drop the extra reference on the node.
	 */
	mtx_lock(&priv->mtx);
	priv->datasock = pcbp;
	pcbp->sockdata = priv;
	priv->refs++;
	mtx_unlock(&priv->mtx);
	ng_free_item(item);	/* drop the reference to the node */
	return (0);
}
Esempio n. 21
0
/*
 * Shutdown node
 */
static int
ngfrm_shutdown(node_p node)
{
	const sc_p sc = NG_NODE_PRIVATE(node);

	NG_NODE_SET_PRIVATE(node, NULL);
	FREE(sc, M_NETGRAPH);
	NG_NODE_UNREF(node);
	return (0);
}
Esempio n. 22
0
/*
 * Do local shutdown processing..
 * Cut any remaining links and free our local resources.
 */
static int
nglmi_shutdown(node_p node)
{
	const sc_p sc = NG_NODE_PRIVATE(node);

	NG_NODE_SET_PRIVATE(node, NULL);
	NG_NODE_UNREF(sc->node);
	free(sc, M_NETGRAPH);
	return (0);
}
Esempio n. 23
0
static void
bt3c_send(node_p node, hook_p hook, void *arg, int completed)
{
	bt3c_softc_p	 sc = (bt3c_softc_p) NG_NODE_PRIVATE(node);
	struct mbuf	*m = NULL;
	int		 i, wrote, len;

	if (sc == NULL)
		return;

	if (completed)
		sc->flags &= ~BT3C_XMIT;

	if (sc->flags & BT3C_XMIT)
		return;

	bt3c_set_address(sc, 0x7080);

	for (wrote = 0; wrote < BT3C_FIFO_SIZE; ) {
		IF_DEQUEUE(&sc->outq, m);
		if (m == NULL)
			break;

		while (m != NULL) {
			len = min((BT3C_FIFO_SIZE - wrote), m->m_len);

			for (i = 0; i < len; i++)
				bt3c_write_data(sc, m->m_data[i]);

			wrote += len;
			m->m_data += len;
			m->m_len -= len;

			if (m->m_len > 0)
				break;

			m = m_free(m);
		}

		if (m != NULL) {
			IF_PREPEND(&sc->outq, m);
			break;
		}

		NG_BT3C_STAT_PCKTS_SENT(sc->stat);
	}

	if (wrote > 0) {
		NG_BT3C_INFO(sc->dev, "Wrote %d bytes\n", wrote);
		NG_BT3C_STAT_BYTES_SENT(sc->stat, wrote);

		bt3c_write(sc, 0x7005, wrote);
		sc->flags |= BT3C_XMIT;
	}
} /* bt3c_send */
Esempio n. 24
0
/*
 * Flow control message from upper layer.
 * This is very experimental:
 * If we get a message from the upper layer, that somebody has passed its
 * high water mark, we stop updating the receive window.
 * If we get a low watermark passed, then we raise the window up
 * to max - current.
 * If we get a queue status and it indicates a current below the
 * high watermark, we unstop window updates (if they are stopped) and
 * raise the window to highwater - current.
 */
static int
flow_upper(node_p node, struct ng_mesg *msg)
{
	struct ngm_queue_state *q;
	struct priv *priv = NG_NODE_PRIVATE(node);
	u_int window, space;

	if (msg->header.arglen != sizeof(struct ngm_queue_state))
		return (EINVAL);
	q = (struct ngm_queue_state *)msg->data;

	switch (msg->header.cmd) {

	  case NGM_HIGH_WATER_PASSED:
		if (priv->flow) {
			VERBOSE(priv, SSCOP_DBG_FLOW, (priv->sscop, priv,
			    "flow control stopped"));
			priv->flow = 0;
		}
		break;

	  case NGM_LOW_WATER_PASSED:
		window = sscop_window(priv->sscop, 0);
		space = q->max_queuelen_packets - q->current;
		if (space > window) {
			VERBOSE(priv, SSCOP_DBG_FLOW, (priv->sscop, priv,
			    "flow control opened window by %u messages",
			    space - window));
			(void)sscop_window(priv->sscop, space - window);
		}
		priv->flow = 1;
		break;

	  case NGM_SYNC_QUEUE_STATE:
		if (q->high_watermark <= q->current)
			break;
		window = sscop_window(priv->sscop, 0);
		if (priv->flow)
			space = q->max_queuelen_packets - q->current;
		else
			space = q->high_watermark - q->current;
		if (space > window) {
			VERBOSE(priv, SSCOP_DBG_FLOW, (priv->sscop, priv,
			    "flow control opened window by %u messages",
			    space - window));
			(void)sscop_window(priv->sscop, space - window);
		}
		priv->flow = 1;
		break;

	  default:
		return (EINVAL);
	}
	return (0);
}
Esempio n. 25
0
static int
ng_split_shutdown(node_p node)
{
	const priv_p	priv = NG_NODE_PRIVATE(node);

	NG_NODE_SET_PRIVATE(node, NULL);
	NG_NODE_UNREF(node);
	free(priv, M_NETGRAPH);

	return (0);
}
Esempio n. 26
0
static int ng_vboxnetflt_shutdown(node_p node)
{
    PVBOXNETFLTINS pThis = NG_NODE_PRIVATE(node);
    bool fActive;

    /* Prevent node shutdown if we're active */
    if (pThis->enmTrunkState == INTNETTRUNKIFSTATE_ACTIVE)
        return (EBUSY);
    NG_NODE_UNREF(node);
    return (0);
}
Esempio n. 27
0
File: udbp.c Progetto: MarginC/kame
/*
 * Dook disconnection
 *
 * For this type, removal of the last link destroys the node
 */
Static int
ng_udbp_disconnect(hook_p hook)
{
	const udbp_p sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
	sc->hook = NULL;

	if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0)
	&& (NG_NODE_IS_VALID(NG_HOOK_NODE(hook))))
		ng_rmnode_self(NG_HOOK_NODE(hook));
	return (0);
}
Esempio n. 28
0
static int
ng_ubt_connect(hook_p hook)
{
	struct ubt_softc	*sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));

	NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook));

	UBT_NG_LOCK(sc);
	ubt_task_schedule(sc, UBT_FLAG_T_START_ALL);
	UBT_NG_UNLOCK(sc);

	return (0);
} /* ng_ubt_connect */
Esempio n. 29
0
/*
 * Get a netgraph control message.
 * We actually recieve a queue item that has a pointer to the message.
 * If we free the item, the message will be freed too, unless we remove
 * it from the item using NGI_GET_MSG();
 * The return address is also stored in the item, as an ng_ID_t,
 * accessible as NGI_RETADDR(item);
 * Check it is one we understand. If needed, send a response.
 * We could save the address for an async action later, but don't here.
 * Always free the message.
 * The response should be in a malloc'd region that the caller can 'free'.
 * A response is not required.
 * Theoretically you could respond defferently to old message types if
 * the cookie in the header didn't match what we consider to be current
 * (so that old userland programs could continue to work).
 */
static int
ng_xxx_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
	const xxx_p xxxp = NG_NODE_PRIVATE(node);
	struct ng_mesg *resp = NULL;
	int error = 0;
	struct ng_mesg *msg;

	NGI_GET_MSG(item, msg);
	/* Deal with message according to cookie and command */
	switch (msg->header.typecookie) {
	case NGM_XXX_COOKIE:
		switch (msg->header.cmd) {
		case NGM_XXX_GET_STATUS:
		    {
			struct ngxxxstat *stats;

			NG_MKRESPONSE(resp, msg, sizeof(*stats), M_NOWAIT);
			if (!resp) {
				error = ENOMEM;
				break;
			}
			stats = (struct ngxxxstat *) resp->data;
			stats->packets_in = xxxp->packets_in;
			stats->packets_out = xxxp->packets_out;
			break;
		    }
		case NGM_XXX_SET_FLAG:
			if (msg->header.arglen != sizeof(u_int32_t)) {
				error = EINVAL;
				break;
			}
			xxxp->flags = *((u_int32_t *) msg->data);
			break;
		default:
			error = EINVAL;		/* unknown command */
			break;
		}
		break;
	default:
		error = EINVAL;			/* unknown cookie type */
		break;
	}

	/* Take care of synchronous response, if any */
	NG_RESPOND_MSG(error, node, item, resp);
	/* Free the message and return */
	NG_FREE_MSG(msg);
	return(error);
}
Esempio n. 30
0
/*
 * If only one hook, allow read(2) and write(2) to work.
 */
static int
ngs_connect(hook_p hook)
{
	node_p node = NG_HOOK_NODE(hook);
	struct ngsock *priv = NG_NODE_PRIVATE(node);

	if ((priv->datasock) && (priv->datasock->ng_socket)) {
		if (NG_NODE_NUMHOOKS(node) == 1)
			sosetstate(priv->datasock->ng_socket, SS_ISCONNECTED);
		else
			soclrstate(priv->datasock->ng_socket, SS_ISCONNECTED);
	}
	return (0);
}