ng_UI.c revision 139823
1243730Srwatson/*
2243730Srwatson * ng_UI.c
3243730Srwatson */
4243730Srwatson
5243730Srwatson/*-
6243730Srwatson * Copyright (c) 1996-1999 Whistle Communications, Inc.
7243730Srwatson * All rights reserved.
8243730Srwatson *
9243730Srwatson * Subject to the following obligations and disclaimer of warranty, use and
10243730Srwatson * redistribution of this software, in source or object code forms, with or
11243730Srwatson * without modifications are expressly permitted by Whistle Communications;
12243730Srwatson * provided, however, that:
13243730Srwatson * 1. Any and all reproductions of the source or object code must include the
14243730Srwatson *    copyright notice above and the following disclaimer of warranties; and
15243730Srwatson * 2. No rights are granted, in any manner or form, to use Whistle
16243730Srwatson *    Communications, Inc. trademarks, including the mark "WHISTLE
17243730Srwatson *    COMMUNICATIONS" on advertising, endorsements, or otherwise except as
18243730Srwatson *    such appears in the above copyright notice or in the software.
19243730Srwatson *
20243730Srwatson * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
21243730Srwatson * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
22243730Srwatson * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
23243730Srwatson * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
24243730Srwatson * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
25243730Srwatson * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
26243730Srwatson * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
27243730Srwatson * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
28243730Srwatson * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
29243730Srwatson * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
30243730Srwatson * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
31243730Srwatson * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
32243730Srwatson * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
33243730Srwatson * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34243730Srwatson * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35243730Srwatson * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
36243730Srwatson * OF SUCH DAMAGE.
37243730Srwatson *
38243730Srwatson * Author: Julian Elischer <julian@freebsd.org>
39243730Srwatson *
40243730Srwatson * $FreeBSD: head/sys/netgraph/ng_UI.c 139823 2005-01-07 01:45:51Z imp $
41243730Srwatson * $Whistle: ng_UI.c,v 1.14 1999/11/01 09:24:51 julian Exp $
42243730Srwatson */
43243730Srwatson
44243730Srwatson#include <sys/param.h>
45243730Srwatson#include <sys/systm.h>
46243730Srwatson#include <sys/errno.h>
47243730Srwatson#include <sys/kernel.h>
48243730Srwatson#include <sys/malloc.h>
49243730Srwatson#include <sys/mbuf.h>
50243730Srwatson#include <sys/errno.h>
51243730Srwatson
52243730Srwatson
53243730Srwatson#include <netgraph/ng_message.h>
54243730Srwatson#include <netgraph/netgraph.h>
55243730Srwatson#include <netgraph/ng_UI.h>
56243730Srwatson
57243730Srwatson/*
58243730Srwatson * DEFINITIONS
59243730Srwatson */
60243730Srwatson
61243730Srwatson/* Everything, starting with sdlc on has defined UI as 0x03 */
62243730Srwatson#define HDLC_UI	0x03
63243730Srwatson
64243730Srwatson/* Node private data */
65243730Srwatsonstruct ng_UI_private {
66243730Srwatson	hook_p  downlink;
67243730Srwatson	hook_p  uplink;
68243730Srwatson};
69243730Srwatsontypedef struct ng_UI_private *priv_p;
70243730Srwatson
71243730Srwatson/* Netgraph node methods */
72243730Srwatsonstatic ng_constructor_t	ng_UI_constructor;
73243730Srwatsonstatic ng_rcvmsg_t	ng_UI_rcvmsg;
74243730Srwatsonstatic ng_shutdown_t	ng_UI_shutdown;
75243730Srwatsonstatic ng_newhook_t	ng_UI_newhook;
76243730Srwatsonstatic ng_rcvdata_t	ng_UI_rcvdata;
77243730Srwatsonstatic ng_disconnect_t	ng_UI_disconnect;
78243730Srwatson
79243730Srwatson/* Node type descriptor */
80243730Srwatsonstatic struct ng_type typestruct = {
81243730Srwatson	.version =	NG_ABI_VERSION,
82243730Srwatson	.name =		NG_UI_NODE_TYPE,
83243730Srwatson	.constructor =	ng_UI_constructor,
84243730Srwatson	.rcvmsg =	ng_UI_rcvmsg,
85243730Srwatson	.shutdown =	ng_UI_shutdown,
86243730Srwatson	.newhook =	ng_UI_newhook,
87243730Srwatson	.rcvdata =	ng_UI_rcvdata,
88243730Srwatson	.disconnect =	ng_UI_disconnect,
89243730Srwatson};
90243730SrwatsonNETGRAPH_INIT(UI, &typestruct);
91243730Srwatson
92243730Srwatson/************************************************************************
93243730Srwatson			NETGRAPH NODE STUFF
94243730Srwatson ************************************************************************/
95243730Srwatson
96243730Srwatson/*
97243730Srwatson * Create a newborn node. We start with an implicit reference.
98243730Srwatson */
99243730Srwatson
100243730Srwatsonstatic int
101243730Srwatsonng_UI_constructor(node_p node)
102243730Srwatson{
103243730Srwatson	priv_p  priv;
104243730Srwatson
105243730Srwatson	/* Allocate private structure */
106243730Srwatson	MALLOC(priv, priv_p, sizeof(*priv), M_NETGRAPH, M_NOWAIT | M_ZERO);
107243730Srwatson	if (priv == NULL) {
108243730Srwatson		return (ENOMEM);
109243730Srwatson	}
110243730Srwatson	NG_NODE_SET_PRIVATE(node, priv);
111243730Srwatson	return (0);
112243730Srwatson}
113243730Srwatson
114243730Srwatson/*
115243730Srwatson * Give our ok for a hook to be added
116243730Srwatson */
117243730Srwatsonstatic int
118243730Srwatsonng_UI_newhook(node_p node, hook_p hook, const char *name)
119243730Srwatson{
120243730Srwatson	const priv_p priv = NG_NODE_PRIVATE(node);
121243730Srwatson
122243730Srwatson	if (!strcmp(name, NG_UI_HOOK_DOWNSTREAM)) {
123243730Srwatson		if (priv->downlink)
124243730Srwatson			return (EISCONN);
125243730Srwatson		priv->downlink = hook;
126243730Srwatson	} else if (!strcmp(name, NG_UI_HOOK_UPSTREAM)) {
127243730Srwatson		if (priv->uplink)
128243730Srwatson			return (EISCONN);
129243730Srwatson		priv->uplink = hook;
130243730Srwatson	} else
131243730Srwatson		return (EINVAL);
132243730Srwatson	return (0);
133243730Srwatson}
134243730Srwatson
135243730Srwatson/*
136243730Srwatson * Receive a control message
137243730Srwatson */
138243730Srwatsonstatic int
139243730Srwatsonng_UI_rcvmsg(node_p node, item_p item, hook_p lasthook)
140243730Srwatson{
141243730Srwatson	int	error;
142243730Srwatson	const priv_p priv = NG_NODE_PRIVATE(node);
143243730Srwatson	struct ng_mesg *msg;
144243730Srwatson
145243730Srwatson	msg = NGI_MSG(item); /* only peeking */
146243730Srwatson	if ((msg->header.typecookie == NGM_FLOW_COOKIE) && lasthook)  {
147243730Srwatson		if (lasthook == priv->downlink) {
148243730Srwatson			if (priv->uplink) {
149243730Srwatson				NG_FWD_ITEM_HOOK(error, item, priv->uplink);
150243730Srwatson				return (error);
151243730Srwatson			}
152243730Srwatson		} else {
153243730Srwatson			if (priv->downlink) {
154243730Srwatson				NG_FWD_ITEM_HOOK(error, item, priv->downlink);
155243730Srwatson				return (error);
156243730Srwatson			}
157243730Srwatson		}
158243730Srwatson	}
159243730Srwatson
160243730Srwatson	NG_FREE_ITEM(item);
161243730Srwatson	return (EINVAL);
162243730Srwatson}
163243730Srwatson
164243730Srwatson#define MAX_ENCAPS_HDR	1
165243730Srwatson#define ERROUT(x)	do { error = (x); goto done; } while (0)
166243730Srwatson
167243730Srwatson/*
168243730Srwatson * Receive a data frame
169243730Srwatson */
170243730Srwatsonstatic int
171243730Srwatsonng_UI_rcvdata(hook_p hook, item_p item)
172243730Srwatson{
173243730Srwatson	const node_p node = NG_HOOK_NODE(hook);
174243730Srwatson	const priv_p priv = NG_NODE_PRIVATE(node);
175243730Srwatson	struct mbuf *m;
176243730Srwatson	int error = 0;
177243730Srwatson
178243730Srwatson	NGI_GET_M(item, m);
179243730Srwatson	if (hook == priv->downlink) {
180243730Srwatson		u_char *start, *ptr;
181243730Srwatson
182243730Srwatson		if (m->m_len < MAX_ENCAPS_HDR
183243730Srwatson		    && !(m = m_pullup(m, MAX_ENCAPS_HDR)))
184243730Srwatson			ERROUT(ENOBUFS);
185243730Srwatson		ptr = start = mtod(m, u_char *);
186243730Srwatson
187243730Srwatson		/* Must be UI frame */
188243730Srwatson		if (*ptr++ != HDLC_UI)
189243730Srwatson			ERROUT(0);
190243730Srwatson
191243730Srwatson		m_adj(m, ptr - start);
192243730Srwatson		NG_FWD_NEW_DATA(error, item, priv->uplink, m);	/* m -> NULL */
193243730Srwatson	} else if (hook == priv->uplink) {
194243730Srwatson		M_PREPEND(m, 1, M_DONTWAIT);	/* Prepend IP NLPID */
195243730Srwatson		if (!m)
196243730Srwatson			ERROUT(ENOBUFS);
197243730Srwatson		mtod(m, u_char *)[0] = HDLC_UI;
198243730Srwatson		NG_FWD_NEW_DATA(error, item, priv->downlink, m);	/* m -> NULL */
199243730Srwatson	} else
200243730Srwatson		panic(__func__);
201243730Srwatson
202243730Srwatsondone:
203243730Srwatson	NG_FREE_M(m);	/* does nothing if m == NULL */
204243730Srwatson	if (item)
205243730Srwatson		NG_FREE_ITEM(item);
206243730Srwatson	return (error);
207243730Srwatson}
208243730Srwatson
209243730Srwatson/*
210243730Srwatson * Shutdown node
211243730Srwatson */
212243730Srwatsonstatic int
213243730Srwatsonng_UI_shutdown(node_p node)
214243730Srwatson{
215243730Srwatson	const priv_p priv = NG_NODE_PRIVATE(node);
216243730Srwatson
217243730Srwatson	/* Take down netgraph node */
218243730Srwatson	FREE(priv, M_NETGRAPH);
219243730Srwatson	NG_NODE_SET_PRIVATE(node, NULL);
220243730Srwatson	NG_NODE_UNREF(node);
221243730Srwatson	return (0);
222243730Srwatson}
223243730Srwatson
224243730Srwatson/*
225243730Srwatson * Hook disconnection
226243730Srwatson */
227243730Srwatsonstatic int
228243730Srwatsonng_UI_disconnect(hook_p hook)
229243730Srwatson{
230243730Srwatson	const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
231243730Srwatson
232243730Srwatson	if (hook == priv->downlink)
233243730Srwatson		priv->downlink = NULL;
234243730Srwatson	else if (hook == priv->uplink)
235243730Srwatson		priv->uplink = NULL;
236243730Srwatson	else
237243730Srwatson		panic(__func__);
238243730Srwatson	/*
239243730Srwatson	 * If we are not already shutting down,
240243730Srwatson	 * and we have no more hooks, then DO shut down.
241243730Srwatson	 */
242243730Srwatson	if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0)
243243730Srwatson	&& (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) {
244243730Srwatson			ng_rmnode_self(NG_HOOK_NODE(hook));
245243730Srwatson	}
246243730Srwatson	return (0);
247243730Srwatson}
248243730Srwatson
249243730Srwatson