xref: /dragonfly/sys/netgraph7/UI/ng_UI.c (revision b5523eac)
10147868eSNuno Antunes /*
20147868eSNuno Antunes  * ng_UI.c
30147868eSNuno Antunes  */
40147868eSNuno Antunes 
50147868eSNuno Antunes /*-
60147868eSNuno Antunes  * Copyright (c) 1996-1999 Whistle Communications, Inc.
70147868eSNuno Antunes  * All rights reserved.
80147868eSNuno Antunes  *
90147868eSNuno Antunes  * Subject to the following obligations and disclaimer of warranty, use and
100147868eSNuno Antunes  * redistribution of this software, in source or object code forms, with or
110147868eSNuno Antunes  * without modifications are expressly permitted by Whistle Communications;
120147868eSNuno Antunes  * provided, however, that:
130147868eSNuno Antunes  * 1. Any and all reproductions of the source or object code must include the
140147868eSNuno Antunes  *    copyright notice above and the following disclaimer of warranties; and
150147868eSNuno Antunes  * 2. No rights are granted, in any manner or form, to use Whistle
160147868eSNuno Antunes  *    Communications, Inc. trademarks, including the mark "WHISTLE
170147868eSNuno Antunes  *    COMMUNICATIONS" on advertising, endorsements, or otherwise except as
180147868eSNuno Antunes  *    such appears in the above copyright notice or in the software.
190147868eSNuno Antunes  *
200147868eSNuno Antunes  * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
210147868eSNuno Antunes  * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
220147868eSNuno Antunes  * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
230147868eSNuno Antunes  * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
240147868eSNuno Antunes  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
250147868eSNuno Antunes  * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
260147868eSNuno Antunes  * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
270147868eSNuno Antunes  * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
280147868eSNuno Antunes  * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
290147868eSNuno Antunes  * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
300147868eSNuno Antunes  * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
310147868eSNuno Antunes  * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
320147868eSNuno Antunes  * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
330147868eSNuno Antunes  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
340147868eSNuno Antunes  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
350147868eSNuno Antunes  * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
360147868eSNuno Antunes  * OF SUCH DAMAGE.
370147868eSNuno Antunes  *
380147868eSNuno Antunes  * Author: Julian Elischer <julian@freebsd.org>
390147868eSNuno Antunes  *
400147868eSNuno Antunes  * $FreeBSD: src/sys/netgraph/ng_UI.c,v 1.20 2005/01/07 01:45:39 imp Exp $
410147868eSNuno Antunes  * $Whistle: ng_UI.c,v 1.14 1999/11/01 09:24:51 julian Exp $
420147868eSNuno Antunes  */
430147868eSNuno Antunes 
440147868eSNuno Antunes #include <sys/param.h>
450147868eSNuno Antunes #include <sys/systm.h>
460147868eSNuno Antunes #include <sys/errno.h>
470147868eSNuno Antunes #include <sys/kernel.h>
480147868eSNuno Antunes #include <sys/malloc.h>
490147868eSNuno Antunes #include <sys/mbuf.h>
500147868eSNuno Antunes 
510147868eSNuno Antunes #include <netgraph7/ng_message.h>
520147868eSNuno Antunes #include <netgraph7/netgraph.h>
530147868eSNuno Antunes #include "ng_UI.h"
540147868eSNuno Antunes 
550147868eSNuno Antunes /*
560147868eSNuno Antunes  * DEFINITIONS
570147868eSNuno Antunes  */
580147868eSNuno Antunes 
590147868eSNuno Antunes /* Everything, starting with sdlc on has defined UI as 0x03 */
600147868eSNuno Antunes #define HDLC_UI	0x03
610147868eSNuno Antunes 
620147868eSNuno Antunes /* Node private data */
630147868eSNuno Antunes struct ng_UI_private {
640147868eSNuno Antunes 	hook_p  downlink;
650147868eSNuno Antunes 	hook_p  uplink;
660147868eSNuno Antunes };
670147868eSNuno Antunes typedef struct ng_UI_private *priv_p;
680147868eSNuno Antunes 
690147868eSNuno Antunes /* Netgraph node methods */
700147868eSNuno Antunes static ng_constructor_t	ng_UI_constructor;
710147868eSNuno Antunes static ng_rcvmsg_t	ng_UI_rcvmsg;
720147868eSNuno Antunes static ng_shutdown_t	ng_UI_shutdown;
730147868eSNuno Antunes static ng_newhook_t	ng_UI_newhook;
740147868eSNuno Antunes static ng_rcvdata_t	ng_UI_rcvdata;
750147868eSNuno Antunes static ng_disconnect_t	ng_UI_disconnect;
760147868eSNuno Antunes 
770147868eSNuno Antunes /* Node type descriptor */
780147868eSNuno Antunes static struct ng_type typestruct = {
790147868eSNuno Antunes 	.version =	NG_ABI_VERSION,
800147868eSNuno Antunes 	.name =		NG_UI_NODE_TYPE,
810147868eSNuno Antunes 	.constructor =	ng_UI_constructor,
820147868eSNuno Antunes 	.rcvmsg =	ng_UI_rcvmsg,
830147868eSNuno Antunes 	.shutdown =	ng_UI_shutdown,
840147868eSNuno Antunes 	.newhook =	ng_UI_newhook,
850147868eSNuno Antunes 	.rcvdata =	ng_UI_rcvdata,
860147868eSNuno Antunes 	.disconnect =	ng_UI_disconnect,
870147868eSNuno Antunes };
880147868eSNuno Antunes NETGRAPH_INIT(UI, &typestruct);
890147868eSNuno Antunes 
900147868eSNuno Antunes /************************************************************************
910147868eSNuno Antunes 			NETGRAPH NODE STUFF
920147868eSNuno Antunes  ************************************************************************/
930147868eSNuno Antunes 
940147868eSNuno Antunes /*
950147868eSNuno Antunes  * Create a newborn node. We start with an implicit reference.
960147868eSNuno Antunes  */
970147868eSNuno Antunes 
980147868eSNuno Antunes static int
ng_UI_constructor(node_p node)990147868eSNuno Antunes ng_UI_constructor(node_p node)
1000147868eSNuno Antunes {
1010147868eSNuno Antunes 	priv_p  priv;
1020147868eSNuno Antunes 
1030147868eSNuno Antunes 	/* Allocate private structure */
1040147868eSNuno Antunes 	priv = kmalloc(sizeof(*priv), M_NETGRAPH,
1050147868eSNuno Antunes 		       M_WAITOK | M_NULLOK | M_ZERO);
1060147868eSNuno Antunes 	if (priv == NULL) {
1070147868eSNuno Antunes 		return (ENOMEM);
1080147868eSNuno Antunes 	}
1090147868eSNuno Antunes 	NG_NODE_SET_PRIVATE(node, priv);
1100147868eSNuno Antunes 	return (0);
1110147868eSNuno Antunes }
1120147868eSNuno Antunes 
1130147868eSNuno Antunes /*
1140147868eSNuno Antunes  * Give our ok for a hook to be added
1150147868eSNuno Antunes  */
1160147868eSNuno Antunes static int
ng_UI_newhook(node_p node,hook_p hook,const char * name)1170147868eSNuno Antunes ng_UI_newhook(node_p node, hook_p hook, const char *name)
1180147868eSNuno Antunes {
1190147868eSNuno Antunes 	const priv_p priv = NG_NODE_PRIVATE(node);
1200147868eSNuno Antunes 
1210147868eSNuno Antunes 	if (!strcmp(name, NG_UI_HOOK_DOWNSTREAM)) {
1220147868eSNuno Antunes 		if (priv->downlink)
1230147868eSNuno Antunes 			return (EISCONN);
1240147868eSNuno Antunes 		priv->downlink = hook;
1250147868eSNuno Antunes 	} else if (!strcmp(name, NG_UI_HOOK_UPSTREAM)) {
1260147868eSNuno Antunes 		if (priv->uplink)
1270147868eSNuno Antunes 			return (EISCONN);
1280147868eSNuno Antunes 		priv->uplink = hook;
1290147868eSNuno Antunes 	} else
1300147868eSNuno Antunes 		return (EINVAL);
1310147868eSNuno Antunes 	return (0);
1320147868eSNuno Antunes }
1330147868eSNuno Antunes 
1340147868eSNuno Antunes /*
1350147868eSNuno Antunes  * Receive a control message
1360147868eSNuno Antunes  */
1370147868eSNuno Antunes static int
ng_UI_rcvmsg(node_p node,item_p item,hook_p lasthook)1380147868eSNuno Antunes ng_UI_rcvmsg(node_p node, item_p item, hook_p lasthook)
1390147868eSNuno Antunes {
1400147868eSNuno Antunes 	int	error;
1410147868eSNuno Antunes 	const priv_p priv = NG_NODE_PRIVATE(node);
1420147868eSNuno Antunes 	struct ng_mesg *msg;
1430147868eSNuno Antunes 
1440147868eSNuno Antunes 	msg = NGI_MSG(item); /* only peeking */
1450147868eSNuno Antunes 	if ((msg->header.typecookie == NGM_FLOW_COOKIE) && lasthook)  {
1460147868eSNuno Antunes 		if (lasthook == priv->downlink) {
1470147868eSNuno Antunes 			if (priv->uplink) {
1480147868eSNuno Antunes 				NG_FWD_ITEM_HOOK(error, item, priv->uplink);
1490147868eSNuno Antunes 				return (error);
1500147868eSNuno Antunes 			}
1510147868eSNuno Antunes 		} else {
1520147868eSNuno Antunes 			if (priv->downlink) {
1530147868eSNuno Antunes 				NG_FWD_ITEM_HOOK(error, item, priv->downlink);
1540147868eSNuno Antunes 				return (error);
1550147868eSNuno Antunes 			}
1560147868eSNuno Antunes 		}
1570147868eSNuno Antunes 	}
1580147868eSNuno Antunes 
1590147868eSNuno Antunes 	NG_FREE_ITEM(item);
1600147868eSNuno Antunes 	return (EINVAL);
1610147868eSNuno Antunes }
1620147868eSNuno Antunes 
1630147868eSNuno Antunes #define MAX_ENCAPS_HDR	1
1640147868eSNuno Antunes #define ERROUT(x)	do { error = (x); goto done; } while (0)
1650147868eSNuno Antunes 
1660147868eSNuno Antunes /*
1670147868eSNuno Antunes  * Receive a data frame
1680147868eSNuno Antunes  */
1690147868eSNuno Antunes static int
ng_UI_rcvdata(hook_p hook,item_p item)1700147868eSNuno Antunes ng_UI_rcvdata(hook_p hook, item_p item)
1710147868eSNuno Antunes {
1720147868eSNuno Antunes 	const node_p node = NG_HOOK_NODE(hook);
1730147868eSNuno Antunes 	const priv_p priv = NG_NODE_PRIVATE(node);
1740147868eSNuno Antunes 	struct mbuf *m;
1750147868eSNuno Antunes 	int error = 0;
1760147868eSNuno Antunes 
1770147868eSNuno Antunes 	NGI_GET_M(item, m);
1780147868eSNuno Antunes 	if (hook == priv->downlink) {
1790147868eSNuno Antunes 		u_char *start, *ptr;
1800147868eSNuno Antunes 
1810147868eSNuno Antunes 		if (m->m_len < MAX_ENCAPS_HDR
1820147868eSNuno Antunes 		    && !(m = m_pullup(m, MAX_ENCAPS_HDR)))
1830147868eSNuno Antunes 			ERROUT(ENOBUFS);
1840147868eSNuno Antunes 		ptr = start = mtod(m, u_char *);
1850147868eSNuno Antunes 
1860147868eSNuno Antunes 		/* Must be UI frame */
1870147868eSNuno Antunes 		if (*ptr++ != HDLC_UI)
1880147868eSNuno Antunes 			ERROUT(0);
1890147868eSNuno Antunes 
1900147868eSNuno Antunes 		m_adj(m, ptr - start);
1910147868eSNuno Antunes 		NG_FWD_NEW_DATA(error, item, priv->uplink, m);	/* m -> NULL */
1920147868eSNuno Antunes 	} else if (hook == priv->uplink) {
193*b5523eacSSascha Wildner 		M_PREPEND(m, 1, M_NOWAIT);	/* Prepend IP NLPID */
1940147868eSNuno Antunes 		if (!m)
1950147868eSNuno Antunes 			ERROUT(ENOBUFS);
1960147868eSNuno Antunes 		mtod(m, u_char *)[0] = HDLC_UI;
1970147868eSNuno Antunes 		NG_FWD_NEW_DATA(error, item, priv->downlink, m);	/* m -> NULL */
1980147868eSNuno Antunes 	} else
1990147868eSNuno Antunes 		panic(__func__);
2000147868eSNuno Antunes 
2010147868eSNuno Antunes done:
2020147868eSNuno Antunes 	NG_FREE_M(m);	/* does nothing if m == NULL */
2030147868eSNuno Antunes 	if (item)
2040147868eSNuno Antunes 		NG_FREE_ITEM(item);
2050147868eSNuno Antunes 	return (error);
2060147868eSNuno Antunes }
2070147868eSNuno Antunes 
2080147868eSNuno Antunes /*
2090147868eSNuno Antunes  * Shutdown node
2100147868eSNuno Antunes  */
2110147868eSNuno Antunes static int
ng_UI_shutdown(node_p node)2120147868eSNuno Antunes ng_UI_shutdown(node_p node)
2130147868eSNuno Antunes {
2140147868eSNuno Antunes 	const priv_p priv = NG_NODE_PRIVATE(node);
2150147868eSNuno Antunes 
2160147868eSNuno Antunes 	/* Take down netgraph node */
2170147868eSNuno Antunes 	kfree(priv, M_NETGRAPH);
2180147868eSNuno Antunes 	NG_NODE_SET_PRIVATE(node, NULL);
2190147868eSNuno Antunes 	NG_NODE_UNREF(node);
2200147868eSNuno Antunes 	return (0);
2210147868eSNuno Antunes }
2220147868eSNuno Antunes 
2230147868eSNuno Antunes /*
2240147868eSNuno Antunes  * Hook disconnection
2250147868eSNuno Antunes  */
2260147868eSNuno Antunes static int
ng_UI_disconnect(hook_p hook)2270147868eSNuno Antunes ng_UI_disconnect(hook_p hook)
2280147868eSNuno Antunes {
2290147868eSNuno Antunes 	const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
2300147868eSNuno Antunes 
2310147868eSNuno Antunes 	if (hook == priv->downlink)
2320147868eSNuno Antunes 		priv->downlink = NULL;
2330147868eSNuno Antunes 	else if (hook == priv->uplink)
2340147868eSNuno Antunes 		priv->uplink = NULL;
2350147868eSNuno Antunes 	else
2360147868eSNuno Antunes 		panic(__func__);
2370147868eSNuno Antunes 	/*
2380147868eSNuno Antunes 	 * If we are not already shutting down,
2390147868eSNuno Antunes 	 * and we have no more hooks, then DO shut down.
2400147868eSNuno Antunes 	 */
2410147868eSNuno Antunes 	if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0)
2420147868eSNuno Antunes 	&& (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) {
2430147868eSNuno Antunes 			ng_rmnode_self(NG_HOOK_NODE(hook));
2440147868eSNuno Antunes 	}
2450147868eSNuno Antunes 	return (0);
2460147868eSNuno Antunes }
2470147868eSNuno Antunes 
248