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 */ 62 struct ng_UI_private { 63 hook_p downlink; 64 hook_p uplink; 65 }; 66 typedef struct ng_UI_private *priv_p; 67 68 /* Netgraph node methods */ 69 static ng_constructor_t ng_UI_constructor; 70 static ng_rcvmsg_t ng_UI_rcvmsg; 71 static ng_shutdown_t ng_UI_shutdown; 72 static ng_newhook_t ng_UI_newhook; 73 static ng_rcvdata_t ng_UI_rcvdata; 74 static ng_disconnect_t ng_UI_disconnect; 75 76 /* Node type descriptor */ 77 static 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 }; 87 NETGRAPH_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 97 static int 98 ng_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 */ 111 static int 112 ng_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 */ 132 static int 133 ng_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 */ 164 static int 165 ng_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 196 done: 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 */ 206 static int 207 ng_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 */ 221 static int 222 ng_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