/*1* ng_UI.c2*/34/*-5* Copyright (c) 1996-1999 Whistle Communications, Inc.6* All rights reserved.7*8* Subject to the following obligations and disclaimer of warranty, use and9* redistribution of this software, in source or object code forms, with or10* without modifications are expressly permitted by Whistle Communications;11* provided, however, that:12* 1. Any and all reproductions of the source or object code must include the13* copyright notice above and the following disclaimer of warranties; and14* 2. No rights are granted, in any manner or form, to use Whistle15* Communications, Inc. trademarks, including the mark "WHISTLE16* COMMUNICATIONS" on advertising, endorsements, or otherwise except as17* such appears in the above copyright notice or in the software.18*19* THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND20* TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO21* REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,22* INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF23* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.24* WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY25* REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS26* SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.27* IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES28* RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING29* WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,30* PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR31* SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY32* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT33* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF34* THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY35* OF SUCH DAMAGE.36*37* Author: Julian Elischer <[email protected]>38* $Whistle: ng_UI.c,v 1.14 1999/11/01 09:24:51 julian Exp $39*/4041#include <sys/param.h>42#include <sys/systm.h>43#include <sys/errno.h>44#include <sys/kernel.h>45#include <sys/malloc.h>46#include <sys/mbuf.h>47#include <sys/errno.h>4849#include <netgraph/ng_message.h>50#include <netgraph/netgraph.h>51#include <netgraph/ng_UI.h>5253/*54* DEFINITIONS55*/5657/* Everything, starting with sdlc on has defined UI as 0x03 */58#define HDLC_UI 0x035960/* Node private data */61struct ng_UI_private {62hook_p downlink;63hook_p uplink;64};65typedef struct ng_UI_private *priv_p;6667/* Netgraph node methods */68static ng_constructor_t ng_UI_constructor;69static ng_rcvmsg_t ng_UI_rcvmsg;70static ng_shutdown_t ng_UI_shutdown;71static ng_newhook_t ng_UI_newhook;72static ng_rcvdata_t ng_UI_rcvdata;73static ng_disconnect_t ng_UI_disconnect;7475/* Node type descriptor */76static struct ng_type typestruct = {77.version = NG_ABI_VERSION,78.name = NG_UI_NODE_TYPE,79.constructor = ng_UI_constructor,80.rcvmsg = ng_UI_rcvmsg,81.shutdown = ng_UI_shutdown,82.newhook = ng_UI_newhook,83.rcvdata = ng_UI_rcvdata,84.disconnect = ng_UI_disconnect,85};86NETGRAPH_INIT(UI, &typestruct);8788/************************************************************************89NETGRAPH NODE STUFF90************************************************************************/9192/*93* Create a newborn node. We start with an implicit reference.94*/9596static int97ng_UI_constructor(node_p node)98{99priv_p priv;100101/* Allocate private structure */102priv = malloc(sizeof(*priv), M_NETGRAPH, M_WAITOK | M_ZERO);103NG_NODE_SET_PRIVATE(node, priv);104return (0);105}106107/*108* Give our ok for a hook to be added109*/110static int111ng_UI_newhook(node_p node, hook_p hook, const char *name)112{113const priv_p priv = NG_NODE_PRIVATE(node);114115if (!strcmp(name, NG_UI_HOOK_DOWNSTREAM)) {116if (priv->downlink)117return (EISCONN);118priv->downlink = hook;119} else if (!strcmp(name, NG_UI_HOOK_UPSTREAM)) {120if (priv->uplink)121return (EISCONN);122priv->uplink = hook;123} else124return (EINVAL);125return (0);126}127128/*129* Receive a control message130*/131static int132ng_UI_rcvmsg(node_p node, item_p item, hook_p lasthook)133{134int error;135const priv_p priv = NG_NODE_PRIVATE(node);136struct ng_mesg *msg;137138msg = NGI_MSG(item); /* only peeking */139if ((msg->header.typecookie == NGM_FLOW_COOKIE) && lasthook) {140if (lasthook == priv->downlink) {141if (priv->uplink) {142NG_FWD_ITEM_HOOK(error, item, priv->uplink);143return (error);144}145} else {146if (priv->downlink) {147NG_FWD_ITEM_HOOK(error, item, priv->downlink);148return (error);149}150}151}152153NG_FREE_ITEM(item);154return (EINVAL);155}156157#define MAX_ENCAPS_HDR 1158#define ERROUT(x) do { error = (x); goto done; } while (0)159160/*161* Receive a data frame162*/163static int164ng_UI_rcvdata(hook_p hook, item_p item)165{166const node_p node = NG_HOOK_NODE(hook);167const priv_p priv = NG_NODE_PRIVATE(node);168struct mbuf *m;169int error = 0;170171NGI_GET_M(item, m);172if (hook == priv->downlink) {173u_char *start, *ptr;174175if (m->m_len < MAX_ENCAPS_HDR176&& !(m = m_pullup(m, MAX_ENCAPS_HDR)))177ERROUT(ENOBUFS);178ptr = start = mtod(m, u_char *);179180/* Must be UI frame */181if (*ptr++ != HDLC_UI)182ERROUT(0);183184m_adj(m, ptr - start);185NG_FWD_NEW_DATA(error, item, priv->uplink, m); /* m -> NULL */186} else if (hook == priv->uplink) {187M_PREPEND(m, 1, M_NOWAIT); /* Prepend IP NLPID */188if (!m)189ERROUT(ENOBUFS);190mtod(m, u_char *)[0] = HDLC_UI;191NG_FWD_NEW_DATA(error, item, priv->downlink, m); /* m -> NULL */192} else193panic("%s", __func__);194195done:196NG_FREE_M(m); /* does nothing if m == NULL */197if (item)198NG_FREE_ITEM(item);199return (error);200}201202/*203* Shutdown node204*/205static int206ng_UI_shutdown(node_p node)207{208const priv_p priv = NG_NODE_PRIVATE(node);209210/* Take down netgraph node */211free(priv, M_NETGRAPH);212NG_NODE_SET_PRIVATE(node, NULL);213NG_NODE_UNREF(node);214return (0);215}216217/*218* Hook disconnection219*/220static int221ng_UI_disconnect(hook_p hook)222{223const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));224225if (hook == priv->downlink)226priv->downlink = NULL;227else if (hook == priv->uplink)228priv->uplink = NULL;229else230panic("%s", __func__);231/*232* If we are not already shutting down,233* and we have no more hooks, then DO shut down.234*/235if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0)236&& (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) {237ng_rmnode_self(NG_HOOK_NODE(hook));238}239return (0);240}241242243