14cf49a43SJulian Elischer /*
24cf49a43SJulian Elischer * ng_UI.c
3c398230bSWarner Losh */
4c398230bSWarner Losh
5c398230bSWarner Losh /*-
64cf49a43SJulian Elischer * Copyright (c) 1996-1999 Whistle Communications, Inc.
74cf49a43SJulian Elischer * All rights reserved.
84cf49a43SJulian Elischer *
94cf49a43SJulian Elischer * Subject to the following obligations and disclaimer of warranty, use and
104cf49a43SJulian Elischer * redistribution of this software, in source or object code forms, with or
114cf49a43SJulian Elischer * without modifications are expressly permitted by Whistle Communications;
124cf49a43SJulian Elischer * provided, however, that:
134cf49a43SJulian Elischer * 1. Any and all reproductions of the source or object code must include the
144cf49a43SJulian Elischer * copyright notice above and the following disclaimer of warranties; and
154cf49a43SJulian Elischer * 2. No rights are granted, in any manner or form, to use Whistle
164cf49a43SJulian Elischer * Communications, Inc. trademarks, including the mark "WHISTLE
174cf49a43SJulian Elischer * COMMUNICATIONS" on advertising, endorsements, or otherwise except as
184cf49a43SJulian Elischer * such appears in the above copyright notice or in the software.
194cf49a43SJulian Elischer *
204cf49a43SJulian Elischer * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
214cf49a43SJulian Elischer * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
224cf49a43SJulian Elischer * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
234cf49a43SJulian Elischer * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
244cf49a43SJulian Elischer * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
254cf49a43SJulian Elischer * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
264cf49a43SJulian Elischer * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
274cf49a43SJulian Elischer * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
284cf49a43SJulian Elischer * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
294cf49a43SJulian Elischer * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
304cf49a43SJulian Elischer * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
314cf49a43SJulian Elischer * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
324cf49a43SJulian Elischer * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
334cf49a43SJulian Elischer * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
344cf49a43SJulian Elischer * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
354cf49a43SJulian Elischer * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
364cf49a43SJulian Elischer * OF SUCH DAMAGE.
374cf49a43SJulian Elischer *
38cc3bbd68SJulian Elischer * Author: Julian Elischer <julian@freebsd.org>
3974f5c6aaSJulian Elischer * $Whistle: ng_UI.c,v 1.14 1999/11/01 09:24:51 julian Exp $
404cf49a43SJulian Elischer */
414cf49a43SJulian Elischer
424cf49a43SJulian Elischer #include <sys/param.h>
434cf49a43SJulian Elischer #include <sys/systm.h>
444cf49a43SJulian Elischer #include <sys/errno.h>
454cf49a43SJulian Elischer #include <sys/kernel.h>
464cf49a43SJulian Elischer #include <sys/malloc.h>
474cf49a43SJulian Elischer #include <sys/mbuf.h>
484cf49a43SJulian Elischer #include <sys/errno.h>
494cf49a43SJulian Elischer
504cf49a43SJulian Elischer #include <netgraph/ng_message.h>
514cf49a43SJulian Elischer #include <netgraph/netgraph.h>
524cf49a43SJulian Elischer #include <netgraph/ng_UI.h>
534cf49a43SJulian Elischer
544cf49a43SJulian Elischer /*
554cf49a43SJulian Elischer * DEFINITIONS
564cf49a43SJulian Elischer */
574cf49a43SJulian Elischer
584cf49a43SJulian Elischer /* Everything, starting with sdlc on has defined UI as 0x03 */
594cf49a43SJulian Elischer #define HDLC_UI 0x03
604cf49a43SJulian Elischer
614cf49a43SJulian Elischer /* Node private data */
623a58352eSArchie Cobbs struct ng_UI_private {
634cf49a43SJulian Elischer hook_p downlink;
644cf49a43SJulian Elischer hook_p uplink;
654cf49a43SJulian Elischer };
663a58352eSArchie Cobbs typedef struct ng_UI_private *priv_p;
674cf49a43SJulian Elischer
684cf49a43SJulian Elischer /* Netgraph node methods */
6974f5c6aaSJulian Elischer static ng_constructor_t ng_UI_constructor;
7074f5c6aaSJulian Elischer static ng_rcvmsg_t ng_UI_rcvmsg;
71069154d5SJulian Elischer static ng_shutdown_t ng_UI_shutdown;
7274f5c6aaSJulian Elischer static ng_newhook_t ng_UI_newhook;
7374f5c6aaSJulian Elischer static ng_rcvdata_t ng_UI_rcvdata;
7474f5c6aaSJulian Elischer static ng_disconnect_t ng_UI_disconnect;
754cf49a43SJulian Elischer
764cf49a43SJulian Elischer /* Node type descriptor */
774cf49a43SJulian Elischer static struct ng_type typestruct = {
78f8aae777SJulian Elischer .version = NG_ABI_VERSION,
79f8aae777SJulian Elischer .name = NG_UI_NODE_TYPE,
80f8aae777SJulian Elischer .constructor = ng_UI_constructor,
81f8aae777SJulian Elischer .rcvmsg = ng_UI_rcvmsg,
82f8aae777SJulian Elischer .shutdown = ng_UI_shutdown,
83f8aae777SJulian Elischer .newhook = ng_UI_newhook,
84f8aae777SJulian Elischer .rcvdata = ng_UI_rcvdata,
85f8aae777SJulian Elischer .disconnect = ng_UI_disconnect,
864cf49a43SJulian Elischer };
874cf49a43SJulian Elischer NETGRAPH_INIT(UI, &typestruct);
884cf49a43SJulian Elischer
894cf49a43SJulian Elischer /************************************************************************
904cf49a43SJulian Elischer NETGRAPH NODE STUFF
914cf49a43SJulian Elischer ************************************************************************/
924cf49a43SJulian Elischer
934cf49a43SJulian Elischer /*
944cf49a43SJulian Elischer * Create a newborn node. We start with an implicit reference.
954cf49a43SJulian Elischer */
964cf49a43SJulian Elischer
974cf49a43SJulian Elischer static int
ng_UI_constructor(node_p node)9830400f03SJulian Elischer ng_UI_constructor(node_p node)
994cf49a43SJulian Elischer {
1004cf49a43SJulian Elischer priv_p priv;
1014cf49a43SJulian Elischer
1024cf49a43SJulian Elischer /* Allocate private structure */
103674d86bfSGleb Smirnoff priv = malloc(sizeof(*priv), M_NETGRAPH, M_WAITOK | M_ZERO);
10430400f03SJulian Elischer NG_NODE_SET_PRIVATE(node, priv);
1054cf49a43SJulian Elischer return (0);
1064cf49a43SJulian Elischer }
1074cf49a43SJulian Elischer
1084cf49a43SJulian Elischer /*
1094cf49a43SJulian Elischer * Give our ok for a hook to be added
1104cf49a43SJulian Elischer */
1114cf49a43SJulian Elischer static int
ng_UI_newhook(node_p node,hook_p hook,const char * name)1124cf49a43SJulian Elischer ng_UI_newhook(node_p node, hook_p hook, const char *name)
1134cf49a43SJulian Elischer {
11430400f03SJulian Elischer const priv_p priv = NG_NODE_PRIVATE(node);
1154cf49a43SJulian Elischer
1164cf49a43SJulian Elischer if (!strcmp(name, NG_UI_HOOK_DOWNSTREAM)) {
1174cf49a43SJulian Elischer if (priv->downlink)
1184cf49a43SJulian Elischer return (EISCONN);
1194cf49a43SJulian Elischer priv->downlink = hook;
1204cf49a43SJulian Elischer } else if (!strcmp(name, NG_UI_HOOK_UPSTREAM)) {
1214cf49a43SJulian Elischer if (priv->uplink)
1224cf49a43SJulian Elischer return (EISCONN);
1234cf49a43SJulian Elischer priv->uplink = hook;
1244cf49a43SJulian Elischer } else
1254cf49a43SJulian Elischer return (EINVAL);
1264cf49a43SJulian Elischer return (0);
1274cf49a43SJulian Elischer }
1284cf49a43SJulian Elischer
1294cf49a43SJulian Elischer /*
1304cf49a43SJulian Elischer * Receive a control message
1314cf49a43SJulian Elischer */
1324cf49a43SJulian Elischer static int
ng_UI_rcvmsg(node_p node,item_p item,hook_p lasthook)133069154d5SJulian Elischer ng_UI_rcvmsg(node_p node, item_p item, hook_p lasthook)
1344cf49a43SJulian Elischer {
135069154d5SJulian Elischer int error;
13630400f03SJulian Elischer const priv_p priv = NG_NODE_PRIVATE(node);
137069154d5SJulian Elischer struct ng_mesg *msg;
138859a4d16SJulian Elischer
139069154d5SJulian Elischer msg = NGI_MSG(item); /* only peeking */
140859a4d16SJulian Elischer if ((msg->header.typecookie == NGM_FLOW_COOKIE) && lasthook) {
141859a4d16SJulian Elischer if (lasthook == priv->downlink) {
142859a4d16SJulian Elischer if (priv->uplink) {
14330400f03SJulian Elischer NG_FWD_ITEM_HOOK(error, item, priv->uplink);
144069154d5SJulian Elischer return (error);
145859a4d16SJulian Elischer }
146859a4d16SJulian Elischer } else {
147859a4d16SJulian Elischer if (priv->downlink) {
14830400f03SJulian Elischer NG_FWD_ITEM_HOOK(error, item, priv->downlink);
149069154d5SJulian Elischer return (error);
150859a4d16SJulian Elischer }
151859a4d16SJulian Elischer }
152859a4d16SJulian Elischer }
153859a4d16SJulian Elischer
15430400f03SJulian Elischer NG_FREE_ITEM(item);
1554cf49a43SJulian Elischer return (EINVAL);
1564cf49a43SJulian Elischer }
1574cf49a43SJulian Elischer
1584cf49a43SJulian Elischer #define MAX_ENCAPS_HDR 1
1594cf49a43SJulian Elischer #define ERROUT(x) do { error = (x); goto done; } while (0)
1604cf49a43SJulian Elischer
1614cf49a43SJulian Elischer /*
1624cf49a43SJulian Elischer * Receive a data frame
1634cf49a43SJulian Elischer */
1644cf49a43SJulian Elischer static int
ng_UI_rcvdata(hook_p hook,item_p item)165069154d5SJulian Elischer ng_UI_rcvdata(hook_p hook, item_p item)
1664cf49a43SJulian Elischer {
16730400f03SJulian Elischer const node_p node = NG_HOOK_NODE(hook);
16830400f03SJulian Elischer const priv_p priv = NG_NODE_PRIVATE(node);
169069154d5SJulian Elischer struct mbuf *m;
1704cf49a43SJulian Elischer int error = 0;
1714cf49a43SJulian Elischer
172069154d5SJulian Elischer NGI_GET_M(item, m);
1734cf49a43SJulian Elischer if (hook == priv->downlink) {
1744cf49a43SJulian Elischer u_char *start, *ptr;
1754cf49a43SJulian Elischer
1761cf3fa79SJulian Elischer if (m->m_len < MAX_ENCAPS_HDR
1771cf3fa79SJulian Elischer && !(m = m_pullup(m, MAX_ENCAPS_HDR)))
1784cf49a43SJulian Elischer ERROUT(ENOBUFS);
1794cf49a43SJulian Elischer ptr = start = mtod(m, u_char *);
1804cf49a43SJulian Elischer
1814cf49a43SJulian Elischer /* Must be UI frame */
1824cf49a43SJulian Elischer if (*ptr++ != HDLC_UI)
1834cf49a43SJulian Elischer ERROUT(0);
1844cf49a43SJulian Elischer
1854cf49a43SJulian Elischer m_adj(m, ptr - start);
186069154d5SJulian Elischer NG_FWD_NEW_DATA(error, item, priv->uplink, m); /* m -> NULL */
1874cf49a43SJulian Elischer } else if (hook == priv->uplink) {
188*eb1b1807SGleb Smirnoff M_PREPEND(m, 1, M_NOWAIT); /* Prepend IP NLPID */
1894cf49a43SJulian Elischer if (!m)
1904cf49a43SJulian Elischer ERROUT(ENOBUFS);
1914cf49a43SJulian Elischer mtod(m, u_char *)[0] = HDLC_UI;
192069154d5SJulian Elischer NG_FWD_NEW_DATA(error, item, priv->downlink, m); /* m -> NULL */
1934cf49a43SJulian Elischer } else
194d28843a4SRui Paulo panic("%s", __func__);
1954cf49a43SJulian Elischer
1964cf49a43SJulian Elischer done:
197069154d5SJulian Elischer NG_FREE_M(m); /* does nothing if m == NULL */
198069154d5SJulian Elischer if (item)
199069154d5SJulian Elischer NG_FREE_ITEM(item);
2004cf49a43SJulian Elischer return (error);
2014cf49a43SJulian Elischer }
2024cf49a43SJulian Elischer
2034cf49a43SJulian Elischer /*
2044cf49a43SJulian Elischer * Shutdown node
2054cf49a43SJulian Elischer */
2064cf49a43SJulian Elischer static int
ng_UI_shutdown(node_p node)207069154d5SJulian Elischer ng_UI_shutdown(node_p node)
2084cf49a43SJulian Elischer {
20930400f03SJulian Elischer const priv_p priv = NG_NODE_PRIVATE(node);
2104cf49a43SJulian Elischer
2114cf49a43SJulian Elischer /* Take down netgraph node */
2121ede983cSDag-Erling Smørgrav free(priv, M_NETGRAPH);
21330400f03SJulian Elischer NG_NODE_SET_PRIVATE(node, NULL);
21430400f03SJulian Elischer NG_NODE_UNREF(node);
2154cf49a43SJulian Elischer return (0);
2164cf49a43SJulian Elischer }
2174cf49a43SJulian Elischer
2184cf49a43SJulian Elischer /*
2194cf49a43SJulian Elischer * Hook disconnection
2204cf49a43SJulian Elischer */
2214cf49a43SJulian Elischer static int
ng_UI_disconnect(hook_p hook)2224cf49a43SJulian Elischer ng_UI_disconnect(hook_p hook)
2234cf49a43SJulian Elischer {
22430400f03SJulian Elischer const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
2254cf49a43SJulian Elischer
226069154d5SJulian Elischer if (hook == priv->downlink)
2274cf49a43SJulian Elischer priv->downlink = NULL;
2284cf49a43SJulian Elischer else if (hook == priv->uplink)
2294cf49a43SJulian Elischer priv->uplink = NULL;
2304cf49a43SJulian Elischer else
231d28843a4SRui Paulo panic("%s", __func__);
232069154d5SJulian Elischer /*
233069154d5SJulian Elischer * If we are not already shutting down,
234069154d5SJulian Elischer * and we have no more hooks, then DO shut down.
235069154d5SJulian Elischer */
23630400f03SJulian Elischer if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0)
23730400f03SJulian Elischer && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) {
23830400f03SJulian Elischer ng_rmnode_self(NG_HOOK_NODE(hook));
239069154d5SJulian Elischer }
2404cf49a43SJulian Elischer return (0);
2414cf49a43SJulian Elischer }
242