1 /* 2 * ng_gif_demux.c 3 */ 4 5 /*- 6 * SPDX-License-Identifier: BSD-3-Clause AND BSD-2-Clause 7 * 8 * Copyright 2001 The Aerospace Corporation. All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions, and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. The name of The Aerospace Corporation may not be used to endorse or 20 * promote products derived from this software. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AEROSPACE CORPORATION ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AEROSPACE CORPORATION BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * 35 * Copyright (c) 1996-1999 Whistle Communications, Inc. 36 * All rights reserved. 37 * 38 * Subject to the following obligations and disclaimer of warranty, use and 39 * redistribution of this software, in source or object code forms, with or 40 * without modifications are expressly permitted by Whistle Communications; 41 * provided, however, that: 42 * 1. Any and all reproductions of the source or object code must include the 43 * copyright notice above and the following disclaimer of warranties; and 44 * 2. No rights are granted, in any manner or form, to use Whistle 45 * Communications, Inc. trademarks, including the mark "WHISTLE 46 * COMMUNICATIONS" on advertising, endorsements, or otherwise except as 47 * such appears in the above copyright notice or in the software. 48 * 49 * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND 50 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO 51 * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, 52 * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF 53 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 54 * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY 55 * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS 56 * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. 57 * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES 58 * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING 59 * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 60 * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR 61 * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY 62 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 63 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 64 * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY 65 * OF SUCH DAMAGE. 66 * 67 * $FreeBSD$ 68 */ 69 70 /* 71 * ng_gif_demux(4) netgraph node type 72 * 73 * Packets received on the "gif" hook have their type header removed 74 * and are passed to the appropriate hook protocol hook. Packets 75 * received on a protocol hook have a type header added back and are 76 * passed out the gif hook. The currently supported protocol hooks are: 77 */ 78 79 #include <sys/param.h> 80 #include <sys/systm.h> 81 #include <sys/kernel.h> 82 #include <sys/malloc.h> 83 #include <sys/ctype.h> 84 #include <sys/mbuf.h> 85 #include <sys/errno.h> 86 #include <sys/socket.h> 87 88 #include <netgraph/ng_message.h> 89 #include <netgraph/netgraph.h> 90 #include <netgraph/ng_parse.h> 91 #include <netgraph/ng_gif_demux.h> 92 93 #ifdef NG_SEPARATE_MALLOC 94 static MALLOC_DEFINE(M_NETGRAPH_GIF_DEMUX, "netgraph_gif_demux", 95 "netgraph gif demux node"); 96 #else 97 #define M_NETGRAPH_GIF_DEMUX M_NETGRAPH 98 #endif 99 100 /* This struct describes one address family */ 101 struct iffam { 102 sa_family_t family; /* Address family */ 103 const char *hookname; /* Name for hook */ 104 }; 105 typedef const struct iffam *iffam_p; 106 107 /* List of address families supported by our interface */ 108 const static struct iffam gFamilies[] = { 109 { AF_INET, NG_GIF_DEMUX_HOOK_INET }, 110 { AF_INET6, NG_GIF_DEMUX_HOOK_INET6 }, 111 { AF_APPLETALK, NG_GIF_DEMUX_HOOK_ATALK }, 112 { AF_IPX, NG_GIF_DEMUX_HOOK_IPX }, 113 { AF_ATM, NG_GIF_DEMUX_HOOK_ATM }, 114 { AF_NATM, NG_GIF_DEMUX_HOOK_NATM }, 115 }; 116 #define NUM_FAMILIES nitems(gFamilies) 117 118 /* Per-node private data */ 119 struct ng_gif_demux_private { 120 node_p node; /* Our netgraph node */ 121 hook_p gif; /* The gif hook */ 122 hook_p hooks[NUM_FAMILIES]; /* The protocol hooks */ 123 }; 124 typedef struct ng_gif_demux_private *priv_p; 125 126 /* Netgraph node methods */ 127 static ng_constructor_t ng_gif_demux_constructor; 128 static ng_rcvmsg_t ng_gif_demux_rcvmsg; 129 static ng_shutdown_t ng_gif_demux_shutdown; 130 static ng_newhook_t ng_gif_demux_newhook; 131 static ng_rcvdata_t ng_gif_demux_rcvdata; 132 static ng_disconnect_t ng_gif_demux_disconnect; 133 134 /* Helper stuff */ 135 static iffam_p get_iffam_from_af(sa_family_t family); 136 static iffam_p get_iffam_from_hook(priv_p priv, hook_p hook); 137 static iffam_p get_iffam_from_name(const char *name); 138 static hook_p *get_hook_from_iffam(priv_p priv, iffam_p iffam); 139 140 /****************************************************************** 141 NETGRAPH PARSE TYPES 142 ******************************************************************/ 143 144 /* List of commands and how to convert arguments to/from ASCII */ 145 static const struct ng_cmdlist ng_gif_demux_cmdlist[] = { 146 { 0 } 147 }; 148 149 /* Node type descriptor */ 150 static struct ng_type ng_gif_demux_typestruct = { 151 .version = NG_ABI_VERSION, 152 .name = NG_GIF_DEMUX_NODE_TYPE, 153 .constructor = ng_gif_demux_constructor, 154 .rcvmsg = ng_gif_demux_rcvmsg, 155 .shutdown = ng_gif_demux_shutdown, 156 .newhook = ng_gif_demux_newhook, 157 .rcvdata = ng_gif_demux_rcvdata, 158 .disconnect = ng_gif_demux_disconnect, 159 .cmdlist = ng_gif_demux_cmdlist, 160 }; 161 NETGRAPH_INIT(gif_demux, &ng_gif_demux_typestruct); 162 163 /************************************************************************ 164 HELPER STUFF 165 ************************************************************************/ 166 167 /* 168 * Get the family descriptor from the family ID 169 */ 170 static __inline iffam_p 171 get_iffam_from_af(sa_family_t family) 172 { 173 iffam_p iffam; 174 int k; 175 176 for (k = 0; k < NUM_FAMILIES; k++) { 177 iffam = &gFamilies[k]; 178 if (iffam->family == family) 179 return (iffam); 180 } 181 return (NULL); 182 } 183 184 /* 185 * Get the family descriptor from the hook 186 */ 187 static __inline iffam_p 188 get_iffam_from_hook(priv_p priv, hook_p hook) 189 { 190 int k; 191 192 for (k = 0; k < NUM_FAMILIES; k++) 193 if (priv->hooks[k] == hook) 194 return (&gFamilies[k]); 195 return (NULL); 196 } 197 198 /* 199 * Get the hook from the iffam descriptor 200 */ 201 202 static __inline hook_p * 203 get_hook_from_iffam(priv_p priv, iffam_p iffam) 204 { 205 return (&priv->hooks[iffam - gFamilies]); 206 } 207 208 /* 209 * Get the iffam descriptor from the name 210 */ 211 static __inline iffam_p 212 get_iffam_from_name(const char *name) 213 { 214 iffam_p iffam; 215 int k; 216 217 for (k = 0; k < NUM_FAMILIES; k++) { 218 iffam = &gFamilies[k]; 219 if (!strcmp(iffam->hookname, name)) 220 return (iffam); 221 } 222 return (NULL); 223 } 224 225 /****************************************************************** 226 NETGRAPH NODE METHODS 227 ******************************************************************/ 228 229 /* 230 * Node constructor 231 */ 232 static int 233 ng_gif_demux_constructor(node_p node) 234 { 235 priv_p priv; 236 237 /* Allocate and initialize private info */ 238 priv = malloc(sizeof(*priv), M_NETGRAPH_GIF_DEMUX, M_WAITOK | M_ZERO); 239 priv->node = node; 240 241 NG_NODE_SET_PRIVATE(node, priv); 242 243 /* Done */ 244 return (0); 245 } 246 247 /* 248 * Method for attaching a new hook 249 */ 250 static int 251 ng_gif_demux_newhook(node_p node, hook_p hook, const char *name) 252 { 253 const priv_p priv = NG_NODE_PRIVATE(node); 254 iffam_p iffam; 255 hook_p *hookptr; 256 257 if (strcmp(NG_GIF_DEMUX_HOOK_GIF, name) == 0) 258 hookptr = &priv->gif; 259 else { 260 iffam = get_iffam_from_name(name); 261 if (iffam == NULL) 262 return (EPFNOSUPPORT); 263 hookptr = get_hook_from_iffam(NG_NODE_PRIVATE(node), iffam); 264 } 265 if (*hookptr != NULL) 266 return (EISCONN); 267 *hookptr = hook; 268 return (0); 269 } 270 271 /* 272 * Receive a control message 273 */ 274 static int 275 ng_gif_demux_rcvmsg(node_p node, item_p item, hook_p lasthook) 276 { 277 struct ng_mesg *resp = NULL; 278 int error = 0; 279 struct ng_mesg *msg; 280 281 NGI_GET_MSG(item, msg); 282 switch (msg->header.typecookie) { 283 case NGM_GIF_DEMUX_COOKIE: 284 switch (msg->header.cmd) { 285 /* XXX: Add commands here. */ 286 default: 287 error = EINVAL; 288 break; 289 } 290 break; 291 default: 292 error = EINVAL; 293 break; 294 } 295 296 /* Done */ 297 NG_RESPOND_MSG(error, node, item, resp); 298 NG_FREE_MSG(msg); 299 return (error); 300 } 301 302 /* 303 * Receive data on a hook 304 */ 305 static int 306 ng_gif_demux_rcvdata(hook_p hook, item_p item) 307 { 308 const node_p node = NG_HOOK_NODE(hook); 309 const priv_p priv = NG_NODE_PRIVATE(node); 310 iffam_p iffam; 311 hook_p outhook; 312 int error = 0; 313 struct mbuf *m; 314 315 /* Pull the mbuf out of the item for processing. */ 316 NGI_GET_M(item, m); 317 318 if (hook == priv->gif) { 319 /* 320 * Pull off the address family header and find the 321 * output hook. 322 */ 323 if (m->m_pkthdr.len < sizeof(sa_family_t)) { 324 NG_FREE_M(m); 325 NG_FREE_ITEM(item); 326 return (EINVAL); 327 } 328 if (m->m_len < sizeof(sa_family_t) 329 && (m = m_pullup(m, sizeof(sa_family_t))) == NULL) { 330 NG_FREE_ITEM(item); 331 return (ENOBUFS); 332 } 333 iffam = get_iffam_from_af(*mtod(m, sa_family_t *)); 334 if (iffam == NULL) { 335 NG_FREE_M(m); 336 NG_FREE_ITEM(item); 337 return (EINVAL); 338 } 339 outhook = *get_hook_from_iffam(priv, iffam); 340 m_adj(m, sizeof(sa_family_t)); 341 } else { 342 /* 343 * Add address family header and set the output hook. 344 */ 345 iffam = get_iffam_from_hook(priv, hook); 346 M_PREPEND(m, sizeof (iffam->family), M_NOWAIT); 347 if (m == NULL) { 348 NG_FREE_M(m); 349 NG_FREE_ITEM(item); 350 return (ENOBUFS); 351 } 352 bcopy(&iffam->family, mtod(m, sa_family_t *), 353 sizeof(iffam->family)); 354 outhook = priv->gif; 355 } 356 357 /* Stuff the mbuf back in. */ 358 NGI_M(item) = m; 359 360 /* Deliver packet */ 361 NG_FWD_ITEM_HOOK(error, item, outhook); 362 return (error); 363 } 364 365 /* 366 * Shutdown node 367 */ 368 static int 369 ng_gif_demux_shutdown(node_p node) 370 { 371 const priv_p priv = NG_NODE_PRIVATE(node); 372 373 free(priv, M_NETGRAPH_GIF_DEMUX); 374 NG_NODE_SET_PRIVATE(node, NULL); 375 NG_NODE_UNREF(node); 376 return (0); 377 } 378 379 /* 380 * Hook disconnection. 381 */ 382 static int 383 ng_gif_demux_disconnect(hook_p hook) 384 { 385 const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 386 iffam_p iffam; 387 388 if (hook == priv->gif) 389 priv->gif = NULL; 390 else { 391 iffam = get_iffam_from_hook(priv, hook); 392 if (iffam == NULL) 393 panic("%s", __func__); 394 *get_hook_from_iffam(priv, iffam) = NULL; 395 } 396 397 return (0); 398 } 399