xref: /freebsd/sys/netgraph/ng_UI.c (revision 30400f03aa3c764fffcb7d3158634778a035a183)
14cf49a43SJulian Elischer 
24cf49a43SJulian Elischer /*
34cf49a43SJulian Elischer  * ng_UI.c
44cf49a43SJulian Elischer  *
54cf49a43SJulian Elischer  * Copyright (c) 1996-1999 Whistle Communications, Inc.
64cf49a43SJulian Elischer  * All rights reserved.
74cf49a43SJulian Elischer  *
84cf49a43SJulian Elischer  * Subject to the following obligations and disclaimer of warranty, use and
94cf49a43SJulian Elischer  * redistribution of this software, in source or object code forms, with or
104cf49a43SJulian Elischer  * without modifications are expressly permitted by Whistle Communications;
114cf49a43SJulian Elischer  * provided, however, that:
124cf49a43SJulian Elischer  * 1. Any and all reproductions of the source or object code must include the
134cf49a43SJulian Elischer  *    copyright notice above and the following disclaimer of warranties; and
144cf49a43SJulian Elischer  * 2. No rights are granted, in any manner or form, to use Whistle
154cf49a43SJulian Elischer  *    Communications, Inc. trademarks, including the mark "WHISTLE
164cf49a43SJulian Elischer  *    COMMUNICATIONS" on advertising, endorsements, or otherwise except as
174cf49a43SJulian Elischer  *    such appears in the above copyright notice or in the software.
184cf49a43SJulian Elischer  *
194cf49a43SJulian Elischer  * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
204cf49a43SJulian Elischer  * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
214cf49a43SJulian Elischer  * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
224cf49a43SJulian Elischer  * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
234cf49a43SJulian Elischer  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
244cf49a43SJulian Elischer  * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
254cf49a43SJulian Elischer  * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
264cf49a43SJulian Elischer  * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
274cf49a43SJulian Elischer  * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
284cf49a43SJulian Elischer  * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
294cf49a43SJulian Elischer  * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
304cf49a43SJulian Elischer  * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
314cf49a43SJulian Elischer  * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
324cf49a43SJulian Elischer  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
334cf49a43SJulian Elischer  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
344cf49a43SJulian Elischer  * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
354cf49a43SJulian Elischer  * OF SUCH DAMAGE.
364cf49a43SJulian Elischer  *
37cc3bbd68SJulian Elischer  * Author: Julian Elischer <julian@freebsd.org>
384cf49a43SJulian Elischer  *
394cf49a43SJulian Elischer  * $FreeBSD$
4074f5c6aaSJulian Elischer  * $Whistle: ng_UI.c,v 1.14 1999/11/01 09:24:51 julian Exp $
414cf49a43SJulian Elischer  */
424cf49a43SJulian Elischer 
434cf49a43SJulian Elischer #include <sys/param.h>
444cf49a43SJulian Elischer #include <sys/systm.h>
454cf49a43SJulian Elischer #include <sys/errno.h>
464cf49a43SJulian Elischer #include <sys/kernel.h>
474cf49a43SJulian Elischer #include <sys/malloc.h>
484cf49a43SJulian Elischer #include <sys/mbuf.h>
494cf49a43SJulian Elischer #include <sys/errno.h>
504cf49a43SJulian Elischer 
514cf49a43SJulian Elischer 
524cf49a43SJulian Elischer #include <netgraph/ng_message.h>
534cf49a43SJulian Elischer #include <netgraph/netgraph.h>
544cf49a43SJulian Elischer #include <netgraph/ng_UI.h>
554cf49a43SJulian Elischer 
564cf49a43SJulian Elischer /*
574cf49a43SJulian Elischer  * DEFINITIONS
584cf49a43SJulian Elischer  */
594cf49a43SJulian Elischer 
604cf49a43SJulian Elischer /* Everything, starting with sdlc on has defined UI as 0x03 */
614cf49a43SJulian Elischer #define HDLC_UI	0x03
624cf49a43SJulian Elischer 
634cf49a43SJulian Elischer /* Node private data */
643a58352eSArchie Cobbs struct ng_UI_private {
654cf49a43SJulian Elischer 	hook_p  downlink;
664cf49a43SJulian Elischer 	hook_p  uplink;
674cf49a43SJulian Elischer };
683a58352eSArchie Cobbs typedef struct ng_UI_private *priv_p;
694cf49a43SJulian Elischer 
704cf49a43SJulian Elischer /* Netgraph node methods */
7174f5c6aaSJulian Elischer static ng_constructor_t	ng_UI_constructor;
7274f5c6aaSJulian Elischer static ng_rcvmsg_t	ng_UI_rcvmsg;
73069154d5SJulian Elischer static ng_shutdown_t	ng_UI_shutdown;
7474f5c6aaSJulian Elischer static ng_newhook_t	ng_UI_newhook;
7574f5c6aaSJulian Elischer static ng_rcvdata_t	ng_UI_rcvdata;
7674f5c6aaSJulian Elischer static ng_disconnect_t	ng_UI_disconnect;
774cf49a43SJulian Elischer 
784cf49a43SJulian Elischer /* Node type descriptor */
794cf49a43SJulian Elischer static struct ng_type typestruct = {
80589f6ed8SJulian Elischer 	NG_ABI_VERSION,
814cf49a43SJulian Elischer 	NG_UI_NODE_TYPE,
824cf49a43SJulian Elischer 	NULL,
834cf49a43SJulian Elischer 	ng_UI_constructor,
844cf49a43SJulian Elischer 	ng_UI_rcvmsg,
85069154d5SJulian Elischer 	ng_UI_shutdown,
864cf49a43SJulian Elischer 	ng_UI_newhook,
874cf49a43SJulian Elischer 	NULL,
884cf49a43SJulian Elischer 	NULL,
894cf49a43SJulian Elischer 	ng_UI_rcvdata,
90f8307e12SArchie Cobbs 	ng_UI_disconnect,
91f8307e12SArchie Cobbs 	NULL
924cf49a43SJulian Elischer };
934cf49a43SJulian Elischer NETGRAPH_INIT(UI, &typestruct);
944cf49a43SJulian Elischer 
954cf49a43SJulian Elischer /************************************************************************
964cf49a43SJulian Elischer 			NETGRAPH NODE STUFF
974cf49a43SJulian Elischer  ************************************************************************/
984cf49a43SJulian Elischer 
994cf49a43SJulian Elischer /*
1004cf49a43SJulian Elischer  * Create a newborn node. We start with an implicit reference.
1014cf49a43SJulian Elischer  */
1024cf49a43SJulian Elischer 
1034cf49a43SJulian Elischer static int
10430400f03SJulian Elischer ng_UI_constructor(node_p node)
1054cf49a43SJulian Elischer {
1064cf49a43SJulian Elischer 	priv_p  priv;
1074cf49a43SJulian Elischer 
1084cf49a43SJulian Elischer 	/* Allocate private structure */
10999cdf4ccSDavid Malone 	MALLOC(priv, priv_p, sizeof(*priv), M_NETGRAPH, M_NOWAIT | M_ZERO);
110069154d5SJulian Elischer 	if (priv == NULL) {
1114cf49a43SJulian Elischer 		return (ENOMEM);
1124cf49a43SJulian Elischer 	}
11330400f03SJulian Elischer 	NG_NODE_SET_PRIVATE(node, priv);
1144cf49a43SJulian Elischer 	return (0);
1154cf49a43SJulian Elischer }
1164cf49a43SJulian Elischer 
1174cf49a43SJulian Elischer /*
1184cf49a43SJulian Elischer  * Give our ok for a hook to be added
1194cf49a43SJulian Elischer  */
1204cf49a43SJulian Elischer static int
1214cf49a43SJulian Elischer ng_UI_newhook(node_p node, hook_p hook, const char *name)
1224cf49a43SJulian Elischer {
12330400f03SJulian Elischer 	const priv_p priv = NG_NODE_PRIVATE(node);
1244cf49a43SJulian Elischer 
1254cf49a43SJulian Elischer 	if (!strcmp(name, NG_UI_HOOK_DOWNSTREAM)) {
1264cf49a43SJulian Elischer 		if (priv->downlink)
1274cf49a43SJulian Elischer 			return (EISCONN);
1284cf49a43SJulian Elischer 		priv->downlink = hook;
1294cf49a43SJulian Elischer 	} else if (!strcmp(name, NG_UI_HOOK_UPSTREAM)) {
1304cf49a43SJulian Elischer 		if (priv->uplink)
1314cf49a43SJulian Elischer 			return (EISCONN);
1324cf49a43SJulian Elischer 		priv->uplink = hook;
1334cf49a43SJulian Elischer 	} else
1344cf49a43SJulian Elischer 		return (EINVAL);
1354cf49a43SJulian Elischer 	return (0);
1364cf49a43SJulian Elischer }
1374cf49a43SJulian Elischer 
1384cf49a43SJulian Elischer /*
1394cf49a43SJulian Elischer  * Receive a control message
1404cf49a43SJulian Elischer  */
1414cf49a43SJulian Elischer static int
142069154d5SJulian Elischer ng_UI_rcvmsg(node_p node, item_p item, hook_p lasthook)
1434cf49a43SJulian Elischer {
144069154d5SJulian Elischer 	int	error;
14530400f03SJulian Elischer 	const priv_p priv = NG_NODE_PRIVATE(node);
146069154d5SJulian Elischer 	struct ng_mesg *msg;
147859a4d16SJulian Elischer 
148069154d5SJulian Elischer 	msg = NGI_MSG(item); /* only peeking */
149859a4d16SJulian Elischer 	if ((msg->header.typecookie == NGM_FLOW_COOKIE) && lasthook)  {
150859a4d16SJulian Elischer 		if (lasthook == priv->downlink) {
151859a4d16SJulian Elischer 			if (priv->uplink) {
15230400f03SJulian Elischer 				NG_FWD_ITEM_HOOK(error, item, priv->uplink);
153069154d5SJulian Elischer 				return (error);
154859a4d16SJulian Elischer 			}
155859a4d16SJulian Elischer 		} else {
156859a4d16SJulian Elischer 			if (priv->downlink) {
15730400f03SJulian Elischer 				NG_FWD_ITEM_HOOK(error, item, priv->downlink);
158069154d5SJulian Elischer 				return (error);
159859a4d16SJulian Elischer 			}
160859a4d16SJulian Elischer 		}
161859a4d16SJulian Elischer 	}
162859a4d16SJulian Elischer 
16330400f03SJulian Elischer 	NG_FREE_ITEM(item);
1644cf49a43SJulian Elischer 	return (EINVAL);
1654cf49a43SJulian Elischer }
1664cf49a43SJulian Elischer 
1674cf49a43SJulian Elischer #define MAX_ENCAPS_HDR	1
1684cf49a43SJulian Elischer #define ERROUT(x)	do { error = (x); goto done; } while (0)
1694cf49a43SJulian Elischer 
1704cf49a43SJulian Elischer /*
1714cf49a43SJulian Elischer  * Receive a data frame
1724cf49a43SJulian Elischer  */
1734cf49a43SJulian Elischer static int
174069154d5SJulian Elischer ng_UI_rcvdata(hook_p hook, item_p item)
1754cf49a43SJulian Elischer {
17630400f03SJulian Elischer 	const node_p node = NG_HOOK_NODE(hook);
17730400f03SJulian Elischer 	const priv_p priv = NG_NODE_PRIVATE(node);
178069154d5SJulian Elischer 	struct mbuf *m;
1794cf49a43SJulian Elischer 	int error = 0;
1804cf49a43SJulian Elischer 
181069154d5SJulian Elischer 	NGI_GET_M(item, m);
1824cf49a43SJulian Elischer 	if (hook == priv->downlink) {
1834cf49a43SJulian Elischer 		u_char *start, *ptr;
1844cf49a43SJulian Elischer 
185bef9dae0SJulian Elischer 		if (!m || (m->m_len < MAX_ENCAPS_HDR
186bef9dae0SJulian Elischer 		    && !(m = m_pullup(m, MAX_ENCAPS_HDR))))
1874cf49a43SJulian Elischer 			ERROUT(ENOBUFS);
1884cf49a43SJulian Elischer 		ptr = start = mtod(m, u_char *);
1894cf49a43SJulian Elischer 
1904cf49a43SJulian Elischer 		/* Must be UI frame */
1914cf49a43SJulian Elischer 		if (*ptr++ != HDLC_UI)
1924cf49a43SJulian Elischer 			ERROUT(0);
1934cf49a43SJulian Elischer 
1944cf49a43SJulian Elischer 		m_adj(m, ptr - start);
195069154d5SJulian Elischer 		NG_FWD_NEW_DATA(error, item, priv->uplink, m);	/* m -> NULL */
1964cf49a43SJulian Elischer 	} else if (hook == priv->uplink) {
1974cf49a43SJulian Elischer 		M_PREPEND(m, 1, M_DONTWAIT);	/* Prepend IP NLPID */
1984cf49a43SJulian Elischer 		if (!m)
1994cf49a43SJulian Elischer 			ERROUT(ENOBUFS);
2004cf49a43SJulian Elischer 		mtod(m, u_char *)[0] = HDLC_UI;
201069154d5SJulian Elischer 		NG_FWD_NEW_DATA(error, item, priv->downlink, m);	/* m -> NULL */
2024cf49a43SJulian Elischer 	} else
2034cf49a43SJulian Elischer 		panic(__FUNCTION__);
2044cf49a43SJulian Elischer 
2054cf49a43SJulian Elischer done:
206069154d5SJulian Elischer 	NG_FREE_M(m);	/* does nothing if m == NULL */
207069154d5SJulian Elischer 	if (item)
208069154d5SJulian Elischer 		NG_FREE_ITEM(item);
2094cf49a43SJulian Elischer 	return (error);
2104cf49a43SJulian Elischer }
2114cf49a43SJulian Elischer 
2124cf49a43SJulian Elischer /*
2134cf49a43SJulian Elischer  * Shutdown node
2144cf49a43SJulian Elischer  */
2154cf49a43SJulian Elischer static int
216069154d5SJulian Elischer ng_UI_shutdown(node_p node)
2174cf49a43SJulian Elischer {
21830400f03SJulian Elischer 	const priv_p priv = NG_NODE_PRIVATE(node);
2194cf49a43SJulian Elischer 
2204cf49a43SJulian Elischer 	/* Take down netgraph node */
2214cf49a43SJulian Elischer 	FREE(priv, M_NETGRAPH);
22230400f03SJulian Elischer 	NG_NODE_SET_PRIVATE(node, NULL);
22330400f03SJulian Elischer 	NG_NODE_UNREF(node);
2244cf49a43SJulian Elischer 	return (0);
2254cf49a43SJulian Elischer }
2264cf49a43SJulian Elischer 
2274cf49a43SJulian Elischer /*
2284cf49a43SJulian Elischer  * Hook disconnection
2294cf49a43SJulian Elischer  */
2304cf49a43SJulian Elischer static int
2314cf49a43SJulian Elischer ng_UI_disconnect(hook_p hook)
2324cf49a43SJulian Elischer {
23330400f03SJulian Elischer 	const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
2344cf49a43SJulian Elischer 
235069154d5SJulian Elischer 	if (hook == priv->downlink)
2364cf49a43SJulian Elischer 		priv->downlink = NULL;
2374cf49a43SJulian Elischer 	else if (hook == priv->uplink)
2384cf49a43SJulian Elischer 		priv->uplink = NULL;
2394cf49a43SJulian Elischer 	else
2404cf49a43SJulian Elischer 		panic(__FUNCTION__);
241069154d5SJulian Elischer 	/*
242069154d5SJulian Elischer 	 * If we are not already shutting down,
243069154d5SJulian Elischer 	 * and we have no more hooks, then DO shut down.
244069154d5SJulian Elischer 	 */
24530400f03SJulian Elischer 	if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0)
24630400f03SJulian Elischer 	&& (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) {
24730400f03SJulian Elischer 			ng_rmnode_self(NG_HOOK_NODE(hook));
248069154d5SJulian Elischer 	}
2494cf49a43SJulian Elischer 	return (0);
2504cf49a43SJulian Elischer }
2514cf49a43SJulian Elischer 
252