11573Srgrimes/* 21573Srgrimes * ng_UI.c 31573Srgrimes */ 41573Srgrimes 51573Srgrimes/*- 61573Srgrimes * Copyright (c) 1996-1999 Whistle Communications, Inc. 71573Srgrimes * All rights reserved. 81573Srgrimes * 91573Srgrimes * Subject to the following obligations and disclaimer of warranty, use and 101573Srgrimes * redistribution of this software, in source or object code forms, with or 111573Srgrimes * without modifications are expressly permitted by Whistle Communications; 121573Srgrimes * provided, however, that: 131573Srgrimes * 1. Any and all reproductions of the source or object code must include the 141573Srgrimes * copyright notice above and the following disclaimer of warranties; and 151573Srgrimes * 2. No rights are granted, in any manner or form, to use Whistle 161573Srgrimes * Communications, Inc. trademarks, including the mark "WHISTLE 171573Srgrimes * COMMUNICATIONS" on advertising, endorsements, or otherwise except as 181573Srgrimes * such appears in the above copyright notice or in the software. 191573Srgrimes * 201573Srgrimes * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND 211573Srgrimes * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO 221573Srgrimes * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, 231573Srgrimes * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF 241573Srgrimes * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 251573Srgrimes * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY 261573Srgrimes * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS 271573Srgrimes * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. 281573Srgrimes * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES 2950476Speter * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING 301573Srgrimes * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 311573Srgrimes * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR 321573Srgrimes * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY 3379531Sru * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 341573Srgrimes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 351573Srgrimes * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY 361573Srgrimes * OF SUCH DAMAGE. 3759460Sphantom * 3859460Sphantom * Author: Julian Elischer <julian@freebsd.org> 391573Srgrimes * 4084306Sru * $FreeBSD$ 411573Srgrimes * $Whistle: ng_UI.c,v 1.14 1999/11/01 09:24:51 julian Exp $ 421573Srgrimes */ 431573Srgrimes 441573Srgrimes#include <sys/param.h> 451573Srgrimes#include <sys/systm.h> 46108028Sru#include <sys/errno.h> 471573Srgrimes#include <sys/kernel.h> 481573Srgrimes#include <sys/malloc.h> 491573Srgrimes#include <sys/mbuf.h> 501573Srgrimes#include <sys/errno.h> 511573Srgrimes 521573Srgrimes 531573Srgrimes#include <netgraph/ng_message.h> 541573Srgrimes#include <netgraph/netgraph.h> 5514855Smpp#include <netgraph/ng_UI.h> 561573Srgrimes 571573Srgrimes/* 581573Srgrimes * DEFINITIONS 591573Srgrimes */ 601573Srgrimes 611573Srgrimes/* Everything, starting with sdlc on has defined UI as 0x03 */ 62108040Sru#define HDLC_UI 0x03 631573Srgrimes 641573Srgrimes/* Node private data */ 651573Srgrimesstruct ng_UI_private { 661573Srgrimes hook_p downlink; 671573Srgrimes hook_p uplink; 68139184Skeramida}; 69139184Skeramidatypedef struct ng_UI_private *priv_p; 70139184Skeramida 71139184Skeramida/* Netgraph node methods */ 7250941Sphantomstatic ng_constructor_t ng_UI_constructor; 7350941Sphantomstatic ng_rcvmsg_t ng_UI_rcvmsg; 74139187Skeramidastatic ng_shutdown_t ng_UI_shutdown; 751573Srgrimesstatic ng_newhook_t ng_UI_newhook; 761573Srgrimesstatic ng_rcvdata_t ng_UI_rcvdata; 771573Srgrimesstatic ng_disconnect_t ng_UI_disconnect; 781573Srgrimes 791573Srgrimes/* Node type descriptor */ 801573Srgrimesstatic struct ng_type typestruct = { 811573Srgrimes .version = NG_ABI_VERSION, 821573Srgrimes .name = NG_UI_NODE_TYPE, 831573Srgrimes .constructor = ng_UI_constructor, 841573Srgrimes .rcvmsg = ng_UI_rcvmsg, 851573Srgrimes .shutdown = ng_UI_shutdown, 861573Srgrimes .newhook = ng_UI_newhook, 871573Srgrimes .rcvdata = ng_UI_rcvdata, 881573Srgrimes .disconnect = ng_UI_disconnect, 891573Srgrimes}; 901573SrgrimesNETGRAPH_INIT(UI, &typestruct); 911573Srgrimes 921573Srgrimes/************************************************************************ 931573Srgrimes NETGRAPH NODE STUFF 941573Srgrimes ************************************************************************/ 951573Srgrimes 961573Srgrimes/* 971573Srgrimes * Create a newborn node. We start with an implicit reference. 981573Srgrimes */ 991573Srgrimes 1001573Srgrimesstatic int 1011573Srgrimesng_UI_constructor(node_p node) 1021573Srgrimes{ 10350941Sphantom priv_p priv; 104108028Sru 1051573Srgrimes /* Allocate private structure */ 106108028Sru priv = malloc(sizeof(*priv), M_NETGRAPH, M_WAITOK | M_ZERO); 1071573Srgrimes NG_NODE_SET_PRIVATE(node, priv); 1081573Srgrimes return (0); 1091573Srgrimes} 11032436Salex 1111573Srgrimes/* 112139184Skeramida * Give our ok for a hook to be added 113139184Skeramida */ 1141573Srgrimesstatic int 1151573Srgrimesng_UI_newhook(node_p node, hook_p hook, const char *name) 11617780Smpp{ 117108028Sru const priv_p priv = NG_NODE_PRIVATE(node); 11820097Swosch 11917906Swosch if (!strcmp(name, NG_UI_HOOK_DOWNSTREAM)) { 120108028Sru if (priv->downlink) 12117906Swosch return (EISCONN); 122108028Sru priv->downlink = hook; 12317906Swosch } else if (!strcmp(name, NG_UI_HOOK_UPSTREAM)) { 124 if (priv->uplink) 125 return (EISCONN); 126 priv->uplink = hook; 127 } else 128 return (EINVAL); 129 return (0); 130} 131 132/* 133 * Receive a control message 134 */ 135static int 136ng_UI_rcvmsg(node_p node, item_p item, hook_p lasthook) 137{ 138 int error; 139 const priv_p priv = NG_NODE_PRIVATE(node); 140 struct ng_mesg *msg; 141 142 msg = NGI_MSG(item); /* only peeking */ 143 if ((msg->header.typecookie == NGM_FLOW_COOKIE) && lasthook) { 144 if (lasthook == priv->downlink) { 145 if (priv->uplink) { 146 NG_FWD_ITEM_HOOK(error, item, priv->uplink); 147 return (error); 148 } 149 } else { 150 if (priv->downlink) { 151 NG_FWD_ITEM_HOOK(error, item, priv->downlink); 152 return (error); 153 } 154 } 155 } 156 157 NG_FREE_ITEM(item); 158 return (EINVAL); 159} 160 161#define MAX_ENCAPS_HDR 1 162#define ERROUT(x) do { error = (x); goto done; } while (0) 163 164/* 165 * Receive a data frame 166 */ 167static int 168ng_UI_rcvdata(hook_p hook, item_p item) 169{ 170 const node_p node = NG_HOOK_NODE(hook); 171 const priv_p priv = NG_NODE_PRIVATE(node); 172 struct mbuf *m; 173 int error = 0; 174 175 NGI_GET_M(item, m); 176 if (hook == priv->downlink) { 177 u_char *start, *ptr; 178 179 if (m->m_len < MAX_ENCAPS_HDR 180 && !(m = m_pullup(m, MAX_ENCAPS_HDR))) 181 ERROUT(ENOBUFS); 182 ptr = start = mtod(m, u_char *); 183 184 /* Must be UI frame */ 185 if (*ptr++ != HDLC_UI) 186 ERROUT(0); 187 188 m_adj(m, ptr - start); 189 NG_FWD_NEW_DATA(error, item, priv->uplink, m); /* m -> NULL */ 190 } else if (hook == priv->uplink) { 191 M_PREPEND(m, 1, M_DONTWAIT); /* Prepend IP NLPID */ 192 if (!m) 193 ERROUT(ENOBUFS); 194 mtod(m, u_char *)[0] = HDLC_UI; 195 NG_FWD_NEW_DATA(error, item, priv->downlink, m); /* m -> NULL */ 196 } else 197 panic("%s", __func__); 198 199done: 200 NG_FREE_M(m); /* does nothing if m == NULL */ 201 if (item) 202 NG_FREE_ITEM(item); 203 return (error); 204} 205 206/* 207 * Shutdown node 208 */ 209static int 210ng_UI_shutdown(node_p node) 211{ 212 const priv_p priv = NG_NODE_PRIVATE(node); 213 214 /* Take down netgraph node */ 215 free(priv, M_NETGRAPH); 216 NG_NODE_SET_PRIVATE(node, NULL); 217 NG_NODE_UNREF(node); 218 return (0); 219} 220 221/* 222 * Hook disconnection 223 */ 224static int 225ng_UI_disconnect(hook_p hook) 226{ 227 const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 228 229 if (hook == priv->downlink) 230 priv->downlink = NULL; 231 else if (hook == priv->uplink) 232 priv->uplink = NULL; 233 else 234 panic("%s", __func__); 235 /* 236 * If we are not already shutting down, 237 * and we have no more hooks, then DO shut down. 238 */ 239 if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0) 240 && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) { 241 ng_rmnode_self(NG_HOOK_NODE(hook)); 242 } 243 return (0); 244} 245 246