/*1* ng_gif_demux.c2*/34/*-5* SPDX-License-Identifier: BSD-3-Clause AND BSD-2-Clause6*7* Copyright 2001 The Aerospace Corporation. All rights reserved.8*9* Redistribution and use in source and binary forms, with or without10* modification, are permitted provided that the following conditions11* are met:12*13* 1. Redistributions of source code must retain the above copyright14* notice, this list of conditions, and the following disclaimer.15* 2. Redistributions in binary form must reproduce the above copyright16* notice, this list of conditions, and the following disclaimer in the17* documentation and/or other materials provided with the distribution.18* 3. The name of The Aerospace Corporation may not be used to endorse or19* promote products derived from this software.20*21* THIS SOFTWARE IS PROVIDED BY THE AEROSPACE CORPORATION ``AS IS'' AND22* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE23* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE24* ARE DISCLAIMED. IN NO EVENT SHALL THE AEROSPACE CORPORATION BE LIABLE25* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL26* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS27* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)28* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT29* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY30* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF31* SUCH DAMAGE.32*33*34* Copyright (c) 1996-1999 Whistle Communications, Inc.35* All rights reserved.36*37* Subject to the following obligations and disclaimer of warranty, use and38* redistribution of this software, in source or object code forms, with or39* without modifications are expressly permitted by Whistle Communications;40* provided, however, that:41* 1. Any and all reproductions of the source or object code must include the42* copyright notice above and the following disclaimer of warranties; and43* 2. No rights are granted, in any manner or form, to use Whistle44* Communications, Inc. trademarks, including the mark "WHISTLE45* COMMUNICATIONS" on advertising, endorsements, or otherwise except as46* such appears in the above copyright notice or in the software.47*48* THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND49* TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO50* REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,51* INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF52* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.53* WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY54* REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS55* SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.56* IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES57* RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING58* WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,59* PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR60* SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY61* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT62* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF63* THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY64* OF SUCH DAMAGE.65*/6667/*68* ng_gif_demux(4) netgraph node type69*70* Packets received on the "gif" hook have their type header removed71* and are passed to the appropriate hook protocol hook. Packets72* received on a protocol hook have a type header added back and are73* passed out the gif hook. The currently supported protocol hooks are:74*/7576#include <sys/param.h>77#include <sys/systm.h>78#include <sys/kernel.h>79#include <sys/malloc.h>80#include <sys/ctype.h>81#include <sys/mbuf.h>82#include <sys/errno.h>83#include <sys/socket.h>8485#include <netgraph/ng_message.h>86#include <netgraph/netgraph.h>87#include <netgraph/ng_parse.h>88#include <netgraph/ng_gif_demux.h>8990#ifdef NG_SEPARATE_MALLOC91static MALLOC_DEFINE(M_NETGRAPH_GIF_DEMUX, "netgraph_gif_demux",92"netgraph gif demux node");93#else94#define M_NETGRAPH_GIF_DEMUX M_NETGRAPH95#endif9697/* This struct describes one address family */98struct iffam {99sa_family_t family; /* Address family */100const char *hookname; /* Name for hook */101};102typedef const struct iffam *iffam_p;103104/* List of address families supported by our interface */105const static struct iffam gFamilies[] = {106{ AF_INET, NG_GIF_DEMUX_HOOK_INET },107{ AF_INET6, NG_GIF_DEMUX_HOOK_INET6 },108{ AF_APPLETALK, NG_GIF_DEMUX_HOOK_ATALK },109{ AF_IPX, NG_GIF_DEMUX_HOOK_IPX },110{ AF_ATM, NG_GIF_DEMUX_HOOK_ATM },111{ AF_NATM, NG_GIF_DEMUX_HOOK_NATM },112};113#define NUM_FAMILIES nitems(gFamilies)114115/* Per-node private data */116struct ng_gif_demux_private {117node_p node; /* Our netgraph node */118hook_p gif; /* The gif hook */119hook_p hooks[NUM_FAMILIES]; /* The protocol hooks */120};121typedef struct ng_gif_demux_private *priv_p;122123/* Netgraph node methods */124static ng_constructor_t ng_gif_demux_constructor;125static ng_rcvmsg_t ng_gif_demux_rcvmsg;126static ng_shutdown_t ng_gif_demux_shutdown;127static ng_newhook_t ng_gif_demux_newhook;128static ng_rcvdata_t ng_gif_demux_rcvdata;129static ng_disconnect_t ng_gif_demux_disconnect;130131/* Helper stuff */132static iffam_p get_iffam_from_af(sa_family_t family);133static iffam_p get_iffam_from_hook(priv_p priv, hook_p hook);134static iffam_p get_iffam_from_name(const char *name);135static hook_p *get_hook_from_iffam(priv_p priv, iffam_p iffam);136137/******************************************************************138NETGRAPH PARSE TYPES139******************************************************************/140141/* List of commands and how to convert arguments to/from ASCII */142static const struct ng_cmdlist ng_gif_demux_cmdlist[] = {143{ 0 }144};145146/* Node type descriptor */147static struct ng_type ng_gif_demux_typestruct = {148.version = NG_ABI_VERSION,149.name = NG_GIF_DEMUX_NODE_TYPE,150.constructor = ng_gif_demux_constructor,151.rcvmsg = ng_gif_demux_rcvmsg,152.shutdown = ng_gif_demux_shutdown,153.newhook = ng_gif_demux_newhook,154.rcvdata = ng_gif_demux_rcvdata,155.disconnect = ng_gif_demux_disconnect,156.cmdlist = ng_gif_demux_cmdlist,157};158NETGRAPH_INIT(gif_demux, &ng_gif_demux_typestruct);159160/************************************************************************161HELPER STUFF162************************************************************************/163164/*165* Get the family descriptor from the family ID166*/167static __inline iffam_p168get_iffam_from_af(sa_family_t family)169{170iffam_p iffam;171int k;172173for (k = 0; k < NUM_FAMILIES; k++) {174iffam = &gFamilies[k];175if (iffam->family == family)176return (iffam);177}178return (NULL);179}180181/*182* Get the family descriptor from the hook183*/184static __inline iffam_p185get_iffam_from_hook(priv_p priv, hook_p hook)186{187int k;188189for (k = 0; k < NUM_FAMILIES; k++)190if (priv->hooks[k] == hook)191return (&gFamilies[k]);192return (NULL);193}194195/*196* Get the hook from the iffam descriptor197*/198199static __inline hook_p *200get_hook_from_iffam(priv_p priv, iffam_p iffam)201{202return (&priv->hooks[iffam - gFamilies]);203}204205/*206* Get the iffam descriptor from the name207*/208static __inline iffam_p209get_iffam_from_name(const char *name)210{211iffam_p iffam;212int k;213214for (k = 0; k < NUM_FAMILIES; k++) {215iffam = &gFamilies[k];216if (!strcmp(iffam->hookname, name))217return (iffam);218}219return (NULL);220}221222/******************************************************************223NETGRAPH NODE METHODS224******************************************************************/225226/*227* Node constructor228*/229static int230ng_gif_demux_constructor(node_p node)231{232priv_p priv;233234/* Allocate and initialize private info */235priv = malloc(sizeof(*priv), M_NETGRAPH_GIF_DEMUX, M_WAITOK | M_ZERO);236priv->node = node;237238NG_NODE_SET_PRIVATE(node, priv);239240/* Done */241return (0);242}243244/*245* Method for attaching a new hook246*/247static int248ng_gif_demux_newhook(node_p node, hook_p hook, const char *name)249{250const priv_p priv = NG_NODE_PRIVATE(node);251iffam_p iffam;252hook_p *hookptr;253254if (strcmp(NG_GIF_DEMUX_HOOK_GIF, name) == 0)255hookptr = &priv->gif;256else {257iffam = get_iffam_from_name(name);258if (iffam == NULL)259return (EPFNOSUPPORT);260hookptr = get_hook_from_iffam(NG_NODE_PRIVATE(node), iffam);261}262if (*hookptr != NULL)263return (EISCONN);264*hookptr = hook;265return (0);266}267268/*269* Receive a control message270*/271static int272ng_gif_demux_rcvmsg(node_p node, item_p item, hook_p lasthook)273{274struct ng_mesg *resp = NULL;275int error = 0;276struct ng_mesg *msg;277278NGI_GET_MSG(item, msg);279switch (msg->header.typecookie) {280case NGM_GIF_DEMUX_COOKIE:281switch (msg->header.cmd) {282/* XXX: Add commands here. */283default:284error = EINVAL;285break;286}287break;288default:289error = EINVAL;290break;291}292293/* Done */294NG_RESPOND_MSG(error, node, item, resp);295NG_FREE_MSG(msg);296return (error);297}298299/*300* Receive data on a hook301*/302static int303ng_gif_demux_rcvdata(hook_p hook, item_p item)304{305const node_p node = NG_HOOK_NODE(hook);306const priv_p priv = NG_NODE_PRIVATE(node);307iffam_p iffam;308hook_p outhook;309int error = 0;310struct mbuf *m;311312/* Pull the mbuf out of the item for processing. */313NGI_GET_M(item, m);314315if (hook == priv->gif) {316/*317* Pull off the address family header and find the318* output hook.319*/320if (m->m_pkthdr.len < sizeof(sa_family_t)) {321NG_FREE_M(m);322NG_FREE_ITEM(item);323return (EINVAL);324}325if (m->m_len < sizeof(sa_family_t)326&& (m = m_pullup(m, sizeof(sa_family_t))) == NULL) {327NG_FREE_ITEM(item);328return (ENOBUFS);329}330iffam = get_iffam_from_af(*mtod(m, sa_family_t *));331if (iffam == NULL) {332NG_FREE_M(m);333NG_FREE_ITEM(item);334return (EINVAL);335}336outhook = *get_hook_from_iffam(priv, iffam);337m_adj(m, sizeof(sa_family_t));338} else {339/*340* Add address family header and set the output hook.341*/342iffam = get_iffam_from_hook(priv, hook);343M_PREPEND(m, sizeof (iffam->family), M_NOWAIT);344if (m == NULL) {345NG_FREE_M(m);346NG_FREE_ITEM(item);347return (ENOBUFS);348}349bcopy(&iffam->family, mtod(m, sa_family_t *),350sizeof(iffam->family));351outhook = priv->gif;352}353354/* Stuff the mbuf back in. */355NGI_M(item) = m;356357/* Deliver packet */358NG_FWD_ITEM_HOOK(error, item, outhook);359return (error);360}361362/*363* Shutdown node364*/365static int366ng_gif_demux_shutdown(node_p node)367{368const priv_p priv = NG_NODE_PRIVATE(node);369370free(priv, M_NETGRAPH_GIF_DEMUX);371NG_NODE_SET_PRIVATE(node, NULL);372NG_NODE_UNREF(node);373return (0);374}375376/*377* Hook disconnection.378*/379static int380ng_gif_demux_disconnect(hook_p hook)381{382const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));383iffam_p iffam;384385if (hook == priv->gif)386priv->gif = NULL;387else {388iffam = get_iffam_from_hook(priv, hook);389if (iffam == NULL)390panic("%s", __func__);391*get_hook_from_iffam(priv, iffam) = NULL;392}393394return (0);395}396397398