1/* 2 * ng_UI.c 3 */ 4 5/*- 6 * Copyright (c) 1996-1999 Whistle Communications, Inc. 7 * All rights reserved. 8 * 9 * Subject to the following obligations and disclaimer of warranty, use and 10 * redistribution of this software, in source or object code forms, with or 11 * without modifications are expressly permitted by Whistle Communications; 12 * provided, however, that: 13 * 1. Any and all reproductions of the source or object code must include the 14 * copyright notice above and the following disclaimer of warranties; and 15 * 2. No rights are granted, in any manner or form, to use Whistle 16 * Communications, Inc. trademarks, including the mark "WHISTLE 17 * COMMUNICATIONS" on advertising, endorsements, or otherwise except as 18 * such appears in the above copyright notice or in the software. 19 * 20 * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND 21 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO 22 * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, 23 * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF 24 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 25 * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY 26 * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS 27 * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. 28 * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES 29 * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING 30 * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 31 * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR 32 * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 35 * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY 36 * OF SUCH DAMAGE. 37 * 38 * Author: Julian Elischer <julian@freebsd.org> 39 * $Whistle: ng_UI.c,v 1.14 1999/11/01 09:24:51 julian Exp $ 40 */ 41 42#include <sys/param.h> 43#include <sys/systm.h> 44#include <sys/errno.h> 45#include <sys/kernel.h> 46#include <sys/malloc.h> 47#include <sys/mbuf.h> 48#include <sys/errno.h> 49 50#include <netgraph/ng_message.h> 51#include <netgraph/netgraph.h> 52#include <netgraph/ng_UI.h> 53 54/* 55 * DEFINITIONS 56 */ 57 58/* Everything, starting with sdlc on has defined UI as 0x03 */ 59#define HDLC_UI 0x03 60 61/* Node private data */ 62struct ng_UI_private { 63 hook_p downlink; 64 hook_p uplink; 65}; 66typedef struct ng_UI_private *priv_p; 67 68/* Netgraph node methods */ 69static ng_constructor_t ng_UI_constructor; 70static ng_rcvmsg_t ng_UI_rcvmsg; 71static ng_shutdown_t ng_UI_shutdown; 72static ng_newhook_t ng_UI_newhook; 73static ng_rcvdata_t ng_UI_rcvdata; 74static ng_disconnect_t ng_UI_disconnect; 75 76/* Node type descriptor */ 77static struct ng_type typestruct = { 78 .version = NG_ABI_VERSION, 79 .name = NG_UI_NODE_TYPE, 80 .constructor = ng_UI_constructor, 81 .rcvmsg = ng_UI_rcvmsg, 82 .shutdown = ng_UI_shutdown, 83 .newhook = ng_UI_newhook, 84 .rcvdata = ng_UI_rcvdata, 85 .disconnect = ng_UI_disconnect, 86}; 87NETGRAPH_INIT(UI, &typestruct); 88 89/************************************************************************ 90 NETGRAPH NODE STUFF 91 ************************************************************************/ 92 93/* 94 * Create a newborn node. We start with an implicit reference. 95 */ 96 97static int 98ng_UI_constructor(node_p node) 99{ 100 priv_p priv; 101 102 /* Allocate private structure */ 103 priv = malloc(sizeof(*priv), M_NETGRAPH, M_WAITOK | M_ZERO); 104 NG_NODE_SET_PRIVATE(node, priv); 105 return (0); 106} 107 108/* 109 * Give our ok for a hook to be added 110 */ 111static int 112ng_UI_newhook(node_p node, hook_p hook, const char *name) 113{ 114 const priv_p priv = NG_NODE_PRIVATE(node); 115 116 if (!strcmp(name, NG_UI_HOOK_DOWNSTREAM)) { 117 if (priv->downlink) 118 return (EISCONN); 119 priv->downlink = hook; 120 } else if (!strcmp(name, NG_UI_HOOK_UPSTREAM)) { 121 if (priv->uplink) 122 return (EISCONN); 123 priv->uplink = hook; 124 } else 125 return (EINVAL); 126 return (0); 127} 128 129/* 130 * Receive a control message 131 */ 132static int 133ng_UI_rcvmsg(node_p node, item_p item, hook_p lasthook) 134{ 135 int error; 136 const priv_p priv = NG_NODE_PRIVATE(node); 137 struct ng_mesg *msg; 138 139 msg = NGI_MSG(item); /* only peeking */ 140 if ((msg->header.typecookie == NGM_FLOW_COOKIE) && lasthook) { 141 if (lasthook == priv->downlink) { 142 if (priv->uplink) { 143 NG_FWD_ITEM_HOOK(error, item, priv->uplink); 144 return (error); 145 } 146 } else { 147 if (priv->downlink) { 148 NG_FWD_ITEM_HOOK(error, item, priv->downlink); 149 return (error); 150 } 151 } 152 } 153 154 NG_FREE_ITEM(item); 155 return (EINVAL); 156} 157 158#define MAX_ENCAPS_HDR 1 159#define ERROUT(x) do { error = (x); goto done; } while (0) 160 161/* 162 * Receive a data frame 163 */ 164static int 165ng_UI_rcvdata(hook_p hook, item_p item) 166{ 167 const node_p node = NG_HOOK_NODE(hook); 168 const priv_p priv = NG_NODE_PRIVATE(node); 169 struct mbuf *m; 170 int error = 0; 171 172 NGI_GET_M(item, m); 173 if (hook == priv->downlink) { 174 u_char *start, *ptr; 175 176 if (m->m_len < MAX_ENCAPS_HDR 177 && !(m = m_pullup(m, MAX_ENCAPS_HDR))) 178 ERROUT(ENOBUFS); 179 ptr = start = mtod(m, u_char *); 180 181 /* Must be UI frame */ 182 if (*ptr++ != HDLC_UI) 183 ERROUT(0); 184 185 m_adj(m, ptr - start); 186 NG_FWD_NEW_DATA(error, item, priv->uplink, m); /* m -> NULL */ 187 } else if (hook == priv->uplink) { 188 M_PREPEND(m, 1, M_NOWAIT); /* Prepend IP NLPID */ 189 if (!m) 190 ERROUT(ENOBUFS); 191 mtod(m, u_char *)[0] = HDLC_UI; 192 NG_FWD_NEW_DATA(error, item, priv->downlink, m); /* m -> NULL */ 193 } else 194 panic("%s", __func__); 195 196done: 197 NG_FREE_M(m); /* does nothing if m == NULL */ 198 if (item) 199 NG_FREE_ITEM(item); 200 return (error); 201} 202 203/* 204 * Shutdown node 205 */ 206static int 207ng_UI_shutdown(node_p node) 208{ 209 const priv_p priv = NG_NODE_PRIVATE(node); 210 211 /* Take down netgraph node */ 212 free(priv, M_NETGRAPH); 213 NG_NODE_SET_PRIVATE(node, NULL); 214 NG_NODE_UNREF(node); 215 return (0); 216} 217 218/* 219 * Hook disconnection 220 */ 221static int 222ng_UI_disconnect(hook_p hook) 223{ 224 const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 225 226 if (hook == priv->downlink) 227 priv->downlink = NULL; 228 else if (hook == priv->uplink) 229 priv->uplink = NULL; 230 else 231 panic("%s", __func__); 232 /* 233 * If we are not already shutting down, 234 * and we have no more hooks, then DO shut down. 235 */ 236 if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0) 237 && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) { 238 ng_rmnode_self(NG_HOOK_NODE(hook)); 239 } 240 return (0); 241} 242