ng_UI.c revision 243882
1264095Semaste/*
2264095Semaste * ng_UI.c
3264095Semaste */
4264095Semaste
5264095Semaste/*-
6264095Semaste * Copyright (c) 1996-1999 Whistle Communications, Inc.
7264095Semaste * All rights reserved.
8264095Semaste *
9264095Semaste * Subject to the following obligations and disclaimer of warranty, use and
10264095Semaste * redistribution of this software, in source or object code forms, with or
11264095Semaste * without modifications are expressly permitted by Whistle Communications;
12264095Semaste * provided, however, that:
13264095Semaste * 1. Any and all reproductions of the source or object code must include the
14264095Semaste *    copyright notice above and the following disclaimer of warranties; and
15264095Semaste * 2. No rights are granted, in any manner or form, to use Whistle
16264095Semaste *    Communications, Inc. trademarks, including the mark "WHISTLE
17264095Semaste *    COMMUNICATIONS" on advertising, endorsements, or otherwise except as
18264095Semaste *    such appears in the above copyright notice or in the software.
19264095Semaste *
20264095Semaste * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
21264095Semaste * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
22264095Semaste * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
23264095Semaste * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
24264095Semaste * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
25264095Semaste * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
26264095Semaste * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
27264095Semaste * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
28264095Semaste * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
29264095Semaste * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
30264095Semaste * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
31264095Semaste * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
32264095Semaste * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
33264095Semaste * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34264095Semaste * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35264095Semaste * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
36264095Semaste * OF SUCH DAMAGE.
37264095Semaste *
38264095Semaste * Author: Julian Elischer <julian@freebsd.org>
39264095Semaste *
40264095Semaste * $FreeBSD: head/sys/netgraph/ng_UI.c 243882 2012-12-05 08:04:20Z glebius $
41264095Semaste * $Whistle: ng_UI.c,v 1.14 1999/11/01 09:24:51 julian Exp $
42264095Semaste */
43264095Semaste
44264095Semaste#include <sys/param.h>
45264095Semaste#include <sys/systm.h>
46264095Semaste#include <sys/errno.h>
47264095Semaste#include <sys/kernel.h>
48264095Semaste#include <sys/malloc.h>
49264095Semaste#include <sys/mbuf.h>
50264095Semaste#include <sys/errno.h>
51264095Semaste
52264095Semaste
53264095Semaste#include <netgraph/ng_message.h>
54264095Semaste#include <netgraph/netgraph.h>
55264095Semaste#include <netgraph/ng_UI.h>
56264095Semaste
57264095Semaste/*
58264095Semaste * DEFINITIONS
59264095Semaste */
60264095Semaste
61264095Semaste/* Everything, starting with sdlc on has defined UI as 0x03 */
62264095Semaste#define HDLC_UI	0x03
63271880Semaste
64264095Semaste/* Node private data */
65264095Semastestruct ng_UI_private {
66264095Semaste	hook_p  downlink;
67264095Semaste	hook_p  uplink;
68264095Semaste};
69264095Semastetypedef struct ng_UI_private *priv_p;
70264095Semaste
71264095Semaste/* Netgraph node methods */
72264095Semastestatic ng_constructor_t	ng_UI_constructor;
73264095Semastestatic ng_rcvmsg_t	ng_UI_rcvmsg;
74271880Semastestatic ng_shutdown_t	ng_UI_shutdown;
75271880Semastestatic ng_newhook_t	ng_UI_newhook;
76271880Semastestatic ng_rcvdata_t	ng_UI_rcvdata;
77271880Semastestatic ng_disconnect_t	ng_UI_disconnect;
78271880Semaste
79271880Semaste/* Node type descriptor */
80271880Semastestatic struct ng_type typestruct = {
81271880Semaste	.version =	NG_ABI_VERSION,
82264095Semaste	.name =		NG_UI_NODE_TYPE,
83264095Semaste	.constructor =	ng_UI_constructor,
84264095Semaste	.rcvmsg =	ng_UI_rcvmsg,
85264095Semaste	.shutdown =	ng_UI_shutdown,
86264095Semaste	.newhook =	ng_UI_newhook,
87264095Semaste	.rcvdata =	ng_UI_rcvdata,
88264095Semaste	.disconnect =	ng_UI_disconnect,
89264095Semaste};
90264095SemasteNETGRAPH_INIT(UI, &typestruct);
91264095Semaste
92264095Semaste/************************************************************************
93264095Semaste			NETGRAPH NODE STUFF
94264095Semaste ************************************************************************/
95264095Semaste
96264095Semaste/*
97264095Semaste * Create a newborn node. We start with an implicit reference.
98264095Semaste */
99264095Semaste
100264095Semastestatic int
101264095Semasteng_UI_constructor(node_p node)
102264095Semaste{
103264095Semaste	priv_p  priv;
104264095Semaste
105264095Semaste	/* Allocate private structure */
106264095Semaste	priv = malloc(sizeof(*priv), M_NETGRAPH, M_WAITOK | M_ZERO);
107264095Semaste	NG_NODE_SET_PRIVATE(node, priv);
108264095Semaste	return (0);
109264095Semaste}
110264095Semaste
111264095Semaste/*
112264095Semaste * Give our ok for a hook to be added
113264095Semaste */
114264095Semastestatic int
115264095Semasteng_UI_newhook(node_p node, hook_p hook, const char *name)
116264095Semaste{
117264095Semaste	const priv_p priv = NG_NODE_PRIVATE(node);
118264095Semaste
119264095Semaste	if (!strcmp(name, NG_UI_HOOK_DOWNSTREAM)) {
120264095Semaste		if (priv->downlink)
121264095Semaste			return (EISCONN);
122264095Semaste		priv->downlink = hook;
123264095Semaste	} else if (!strcmp(name, NG_UI_HOOK_UPSTREAM)) {
124264095Semaste		if (priv->uplink)
125264095Semaste			return (EISCONN);
126264095Semaste		priv->uplink = hook;
127264095Semaste	} else
128264095Semaste		return (EINVAL);
129264095Semaste	return (0);
130264095Semaste}
131264095Semaste
132264095Semaste/*
133264095Semaste * Receive a control message
134264095Semaste */
135264095Semastestatic int
136264095Semasteng_UI_rcvmsg(node_p node, item_p item, hook_p lasthook)
137264095Semaste{
138264095Semaste	int	error;
139264095Semaste	const priv_p priv = NG_NODE_PRIVATE(node);
140264095Semaste	struct ng_mesg *msg;
141264095Semaste
142264095Semaste	msg = NGI_MSG(item); /* only peeking */
143264095Semaste	if ((msg->header.typecookie == NGM_FLOW_COOKIE) && lasthook)  {
144264095Semaste		if (lasthook == priv->downlink) {
145264095Semaste			if (priv->uplink) {
146264095Semaste				NG_FWD_ITEM_HOOK(error, item, priv->uplink);
147264095Semaste				return (error);
148264095Semaste			}
149264095Semaste		} else {
150264095Semaste			if (priv->downlink) {
151264095Semaste				NG_FWD_ITEM_HOOK(error, item, priv->downlink);
152264095Semaste				return (error);
153264095Semaste			}
154264095Semaste		}
155264095Semaste	}
156264095Semaste
157264095Semaste	NG_FREE_ITEM(item);
158264095Semaste	return (EINVAL);
159264095Semaste}
160264095Semaste
161264095Semaste#define MAX_ENCAPS_HDR	1
162264095Semaste#define ERROUT(x)	do { error = (x); goto done; } while (0)
163264095Semaste
164264095Semaste/*
165264095Semaste * Receive a data frame
166264095Semaste */
167264095Semastestatic int
168264095Semasteng_UI_rcvdata(hook_p hook, item_p item)
169264095Semaste{
170264095Semaste	const node_p node = NG_HOOK_NODE(hook);
171264095Semaste	const priv_p priv = NG_NODE_PRIVATE(node);
172264095Semaste	struct mbuf *m;
173264095Semaste	int error = 0;
174264095Semaste
175264095Semaste	NGI_GET_M(item, m);
176264095Semaste	if (hook == priv->downlink) {
177264095Semaste		u_char *start, *ptr;
178264095Semaste
179264095Semaste		if (m->m_len < MAX_ENCAPS_HDR
180264095Semaste		    && !(m = m_pullup(m, MAX_ENCAPS_HDR)))
181264095Semaste			ERROUT(ENOBUFS);
182264095Semaste		ptr = start = mtod(m, u_char *);
183264095Semaste
184264095Semaste		/* Must be UI frame */
185264095Semaste		if (*ptr++ != HDLC_UI)
186264095Semaste			ERROUT(0);
187264095Semaste
188264095Semaste		m_adj(m, ptr - start);
189264095Semaste		NG_FWD_NEW_DATA(error, item, priv->uplink, m);	/* m -> NULL */
190264095Semaste	} else if (hook == priv->uplink) {
191264095Semaste		M_PREPEND(m, 1, M_NOWAIT);	/* Prepend IP NLPID */
192264095Semaste		if (!m)
193264095Semaste			ERROUT(ENOBUFS);
194264095Semaste		mtod(m, u_char *)[0] = HDLC_UI;
195264095Semaste		NG_FWD_NEW_DATA(error, item, priv->downlink, m);	/* m -> NULL */
196264095Semaste	} else
197264095Semaste		panic("%s", __func__);
198264095Semaste
199264095Semastedone:
200264095Semaste	NG_FREE_M(m);	/* does nothing if m == NULL */
201264095Semaste	if (item)
202264095Semaste		NG_FREE_ITEM(item);
203264095Semaste	return (error);
204264095Semaste}
205264095Semaste
206264095Semaste/*
207264095Semaste * Shutdown node
208264095Semaste */
209264095Semastestatic int
210264095Semasteng_UI_shutdown(node_p node)
211264095Semaste{
212264095Semaste	const priv_p priv = NG_NODE_PRIVATE(node);
213264095Semaste
214264095Semaste	/* Take down netgraph node */
215264095Semaste	free(priv, M_NETGRAPH);
216264095Semaste	NG_NODE_SET_PRIVATE(node, NULL);
217264095Semaste	NG_NODE_UNREF(node);
218264095Semaste	return (0);
219264095Semaste}
220264095Semaste
221264095Semaste/*
222264095Semaste * Hook disconnection
223264095Semaste */
224264095Semastestatic int
225264095Semasteng_UI_disconnect(hook_p hook)
226264095Semaste{
227264095Semaste	const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
228264095Semaste
229264095Semaste	if (hook == priv->downlink)
230264095Semaste		priv->downlink = NULL;
231264095Semaste	else if (hook == priv->uplink)
232264095Semaste		priv->uplink = NULL;
233264095Semaste	else
234264095Semaste		panic("%s", __func__);
235264095Semaste	/*
236264095Semaste	 * If we are not already shutting down,
237264095Semaste	 * and we have no more hooks, then DO shut down.
238264095Semaste	 */
239264095Semaste	if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0)
240264095Semaste	&& (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) {
241264095Semaste			ng_rmnode_self(NG_HOOK_NODE(hook));
242264095Semaste	}
243264095Semaste	return (0);
244264095Semaste}
245264095Semaste
246264095Semaste