ng_UI.c revision 184205
11638Srgrimes/*
21638Srgrimes * ng_UI.c
31638Srgrimes */
41638Srgrimes
51638Srgrimes/*-
61638Srgrimes * Copyright (c) 1996-1999 Whistle Communications, Inc.
71638Srgrimes * All rights reserved.
81638Srgrimes *
91638Srgrimes * Subject to the following obligations and disclaimer of warranty, use and
101638Srgrimes * redistribution of this software, in source or object code forms, with or
111638Srgrimes * without modifications are expressly permitted by Whistle Communications;
121638Srgrimes * provided, however, that:
131638Srgrimes * 1. Any and all reproductions of the source or object code must include the
141638Srgrimes *    copyright notice above and the following disclaimer of warranties; and
151638Srgrimes * 2. No rights are granted, in any manner or form, to use Whistle
161638Srgrimes *    Communications, Inc. trademarks, including the mark "WHISTLE
171638Srgrimes *    COMMUNICATIONS" on advertising, endorsements, or otherwise except as
181638Srgrimes *    such appears in the above copyright notice or in the software.
191638Srgrimes *
201638Srgrimes * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
211638Srgrimes * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
221638Srgrimes * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
231638Srgrimes * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
241638Srgrimes * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
251638Srgrimes * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
261638Srgrimes * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
271638Srgrimes * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
281638Srgrimes * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
291638Srgrimes * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
301638Srgrimes * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
311638Srgrimes * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
321638Srgrimes * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
3350476Speter * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
341638Srgrimes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
351638Srgrimes * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
361638Srgrimes * OF SUCH DAMAGE.
371638Srgrimes *
381638Srgrimes * Author: Julian Elischer <julian@freebsd.org>
391638Srgrimes *
401638Srgrimes * $FreeBSD: head/sys/netgraph/ng_UI.c 184205 2008-10-23 15:53:51Z des $
411638Srgrimes * $Whistle: ng_UI.c,v 1.14 1999/11/01 09:24:51 julian Exp $
421638Srgrimes */
431638Srgrimes
441638Srgrimes#include <sys/param.h>
451638Srgrimes#include <sys/systm.h>
461638Srgrimes#include <sys/errno.h>
471638Srgrimes#include <sys/kernel.h>
481638Srgrimes#include <sys/malloc.h>
491638Srgrimes#include <sys/mbuf.h>
501638Srgrimes#include <sys/errno.h>
511638Srgrimes
521638Srgrimes
531638Srgrimes#include <netgraph/ng_message.h>
541638Srgrimes#include <netgraph/netgraph.h>
551638Srgrimes#include <netgraph/ng_UI.h>
561638Srgrimes
571638Srgrimes/*
581638Srgrimes * DEFINITIONS
591638Srgrimes */
601638Srgrimes
611638Srgrimes/* Everything, starting with sdlc on has defined UI as 0x03 */
621638Srgrimes#define HDLC_UI	0x03
631638Srgrimes
641638Srgrimes/* Node private data */
651638Srgrimesstruct ng_UI_private {
661638Srgrimes	hook_p  downlink;
671638Srgrimes	hook_p  uplink;
681638Srgrimes};
691638Srgrimestypedef struct ng_UI_private *priv_p;
701638Srgrimes
711638Srgrimes/* Netgraph node methods */
721638Srgrimesstatic ng_constructor_t	ng_UI_constructor;
731638Srgrimesstatic ng_rcvmsg_t	ng_UI_rcvmsg;
741638Srgrimesstatic ng_shutdown_t	ng_UI_shutdown;
751638Srgrimesstatic ng_newhook_t	ng_UI_newhook;
761638Srgrimesstatic ng_rcvdata_t	ng_UI_rcvdata;
771638Srgrimesstatic ng_disconnect_t	ng_UI_disconnect;
781638Srgrimes
791638Srgrimes/* Node type descriptor */
801638Srgrimesstatic struct ng_type typestruct = {
811638Srgrimes	.version =	NG_ABI_VERSION,
821638Srgrimes	.name =		NG_UI_NODE_TYPE,
831638Srgrimes	.constructor =	ng_UI_constructor,
841638Srgrimes	.rcvmsg =	ng_UI_rcvmsg,
851638Srgrimes	.shutdown =	ng_UI_shutdown,
861638Srgrimes	.newhook =	ng_UI_newhook,
871638Srgrimes	.rcvdata =	ng_UI_rcvdata,
881638Srgrimes	.disconnect =	ng_UI_disconnect,
891638Srgrimes};
901638SrgrimesNETGRAPH_INIT(UI, &typestruct);
911638Srgrimes
921638Srgrimes/************************************************************************
931638Srgrimes			NETGRAPH NODE STUFF
941638Srgrimes ************************************************************************/
951638Srgrimes
961638Srgrimes/*
971638Srgrimes * Create a newborn node. We start with an implicit reference.
981638Srgrimes */
991638Srgrimes
1001638Srgrimesstatic int
1011638Srgrimesng_UI_constructor(node_p node)
1021638Srgrimes{
1031638Srgrimes	priv_p  priv;
1041638Srgrimes
1051638Srgrimes	/* Allocate private structure */
1061638Srgrimes	priv = malloc(sizeof(*priv), M_NETGRAPH, M_NOWAIT | M_ZERO);
1071638Srgrimes	if (priv == NULL) {
1081638Srgrimes		return (ENOMEM);
1091638Srgrimes	}
1101638Srgrimes	NG_NODE_SET_PRIVATE(node, priv);
1111638Srgrimes	return (0);
1121638Srgrimes}
1131638Srgrimes
1141638Srgrimes/*
1151638Srgrimes * Give our ok for a hook to be added
1161638Srgrimes */
1171638Srgrimesstatic int
1181638Srgrimesng_UI_newhook(node_p node, hook_p hook, const char *name)
1191638Srgrimes{
1201638Srgrimes	const priv_p priv = NG_NODE_PRIVATE(node);
1211638Srgrimes
1221638Srgrimes	if (!strcmp(name, NG_UI_HOOK_DOWNSTREAM)) {
1231638Srgrimes		if (priv->downlink)
1241638Srgrimes			return (EISCONN);
1251638Srgrimes		priv->downlink = hook;
1261638Srgrimes	} else if (!strcmp(name, NG_UI_HOOK_UPSTREAM)) {
1271638Srgrimes		if (priv->uplink)
1281638Srgrimes			return (EISCONN);
1291638Srgrimes		priv->uplink = hook;
1301638Srgrimes	} else
1311638Srgrimes		return (EINVAL);
1321638Srgrimes	return (0);
1331638Srgrimes}
1341638Srgrimes
1351638Srgrimes/*
1361638Srgrimes * Receive a control message
1371638Srgrimes */
1381638Srgrimesstatic int
1391638Srgrimesng_UI_rcvmsg(node_p node, item_p item, hook_p lasthook)
1401638Srgrimes{
1411638Srgrimes	int	error;
1421638Srgrimes	const priv_p priv = NG_NODE_PRIVATE(node);
1431638Srgrimes	struct ng_mesg *msg;
1441638Srgrimes
1451638Srgrimes	msg = NGI_MSG(item); /* only peeking */
1461638Srgrimes	if ((msg->header.typecookie == NGM_FLOW_COOKIE) && lasthook)  {
1471638Srgrimes		if (lasthook == priv->downlink) {
1481638Srgrimes			if (priv->uplink) {
1491638Srgrimes				NG_FWD_ITEM_HOOK(error, item, priv->uplink);
1501638Srgrimes				return (error);
1511638Srgrimes			}
15222188Sache		} else {
1531638Srgrimes			if (priv->downlink) {
1541638Srgrimes				NG_FWD_ITEM_HOOK(error, item, priv->downlink);
1551638Srgrimes				return (error);
1561638Srgrimes			}
1571638Srgrimes		}
1581638Srgrimes	}
1591638Srgrimes
1601638Srgrimes	NG_FREE_ITEM(item);
1611638Srgrimes	return (EINVAL);
1621638Srgrimes}
1631638Srgrimes
1641638Srgrimes#define MAX_ENCAPS_HDR	1
1651638Srgrimes#define ERROUT(x)	do { error = (x); goto done; } while (0)
1661638Srgrimes
16722188Sache/*
1681638Srgrimes * Receive a data frame
1691638Srgrimes */
1701638Srgrimesstatic int
1711638Srgrimesng_UI_rcvdata(hook_p hook, item_p item)
1721638Srgrimes{
1731638Srgrimes	const node_p node = NG_HOOK_NODE(hook);
1741638Srgrimes	const priv_p priv = NG_NODE_PRIVATE(node);
1751638Srgrimes	struct mbuf *m;
1761638Srgrimes	int error = 0;
1771638Srgrimes
1781638Srgrimes	NGI_GET_M(item, m);
1791638Srgrimes	if (hook == priv->downlink) {
1801638Srgrimes		u_char *start, *ptr;
1811638Srgrimes
18222188Sache		if (m->m_len < MAX_ENCAPS_HDR
1831638Srgrimes		    && !(m = m_pullup(m, MAX_ENCAPS_HDR)))
1841638Srgrimes			ERROUT(ENOBUFS);
1851638Srgrimes		ptr = start = mtod(m, u_char *);
1861638Srgrimes
1871638Srgrimes		/* Must be UI frame */
1881638Srgrimes		if (*ptr++ != HDLC_UI)
1891638Srgrimes			ERROUT(0);
1901638Srgrimes
1911638Srgrimes		m_adj(m, ptr - start);
1921638Srgrimes		NG_FWD_NEW_DATA(error, item, priv->uplink, m);	/* m -> NULL */
1931638Srgrimes	} else if (hook == priv->uplink) {
1941638Srgrimes		M_PREPEND(m, 1, M_DONTWAIT);	/* Prepend IP NLPID */
1951638Srgrimes		if (!m)
1961638Srgrimes			ERROUT(ENOBUFS);
1971638Srgrimes		mtod(m, u_char *)[0] = HDLC_UI;
1981638Srgrimes		NG_FWD_NEW_DATA(error, item, priv->downlink, m);	/* m -> NULL */
1991638Srgrimes	} else
2001638Srgrimes		panic(__func__);
2011638Srgrimes
20222188Sachedone:
2031638Srgrimes	NG_FREE_M(m);	/* does nothing if m == NULL */
2041638Srgrimes	if (item)
2051638Srgrimes		NG_FREE_ITEM(item);
2061638Srgrimes	return (error);
2071638Srgrimes}
2081638Srgrimes
2091638Srgrimes/*
2101638Srgrimes * Shutdown node
2111638Srgrimes */
2121638Srgrimesstatic int
2131638Srgrimesng_UI_shutdown(node_p node)
2141638Srgrimes{
2151638Srgrimes	const priv_p priv = NG_NODE_PRIVATE(node);
2161638Srgrimes
21722188Sache	/* Take down netgraph node */
2181638Srgrimes	free(priv, M_NETGRAPH);
2191638Srgrimes	NG_NODE_SET_PRIVATE(node, NULL);
2201638Srgrimes	NG_NODE_UNREF(node);
2211638Srgrimes	return (0);
2221638Srgrimes}
2231638Srgrimes
2241638Srgrimes/*
2251638Srgrimes * Hook disconnection
2261638Srgrimes */
2271638Srgrimesstatic int
2281638Srgrimesng_UI_disconnect(hook_p hook)
2291638Srgrimes{
2301638Srgrimes	const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
2311638Srgrimes
2321638Srgrimes	if (hook == priv->downlink)
2331638Srgrimes		priv->downlink = NULL;
2341638Srgrimes	else if (hook == priv->uplink)
2351638Srgrimes		priv->uplink = NULL;
2361638Srgrimes	else
2371638Srgrimes		panic(__func__);
2381638Srgrimes	/*
2391638Srgrimes	 * If we are not already shutting down,
2401638Srgrimes	 * and we have no more hooks, then DO shut down.
2411638Srgrimes	 */
2421638Srgrimes	if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0)
2431638Srgrimes	&& (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) {
2441638Srgrimes			ng_rmnode_self(NG_HOOK_NODE(hook));
2451638Srgrimes	}
2461638Srgrimes	return (0);
2471638Srgrimes}
2481638Srgrimes
24922188Sache