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 94static 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 */ 101struct iffam { 102 sa_family_t family; /* Address family */ 103 const char *hookname; /* Name for hook */ 104}; 105typedef const struct iffam *iffam_p; 106 107/* List of address families supported by our interface */ 108const 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 */ 119struct 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}; 124typedef struct ng_gif_demux_private *priv_p; 125 126/* Netgraph node methods */ 127static ng_constructor_t ng_gif_demux_constructor; 128static ng_rcvmsg_t ng_gif_demux_rcvmsg; 129static ng_shutdown_t ng_gif_demux_shutdown; 130static ng_newhook_t ng_gif_demux_newhook; 131static ng_rcvdata_t ng_gif_demux_rcvdata; 132static ng_disconnect_t ng_gif_demux_disconnect; 133 134/* Helper stuff */ 135static iffam_p get_iffam_from_af(sa_family_t family); 136static iffam_p get_iffam_from_hook(priv_p priv, hook_p hook); 137static iffam_p get_iffam_from_name(const char *name); 138static 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 */ 145static const struct ng_cmdlist ng_gif_demux_cmdlist[] = { 146 { 0 } 147}; 148 149/* Node type descriptor */ 150static 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}; 161NETGRAPH_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 */ 170static __inline iffam_p 171get_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 */ 187static __inline iffam_p 188get_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 202static __inline hook_p * 203get_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 */ 211static __inline iffam_p 212get_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 */ 232static int 233ng_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 */ 250static int 251ng_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 */ 274static int 275ng_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 */ 305static int 306ng_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 */ 368static int 369ng_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 */ 382static int 383ng_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