183998Sbrooks/* 283998Sbrooks * ng_gif_demux.c 3139823Simp */ 4139823Simp 5139823Simp/*- 683998Sbrooks * Copyright 2001 The Aerospace Corporation. All rights reserved. 783998Sbrooks * 883998Sbrooks * Redistribution and use in source and binary forms, with or without 983998Sbrooks * modification, are permitted provided that the following conditions 1083998Sbrooks * are met: 1184000Sbrooks * 1283998Sbrooks * 1. Redistributions of source code must retain the above copyright 1384000Sbrooks * notice, this list of conditions, and the following disclaimer. 1483998Sbrooks * 2. Redistributions in binary form must reproduce the above copyright 1584000Sbrooks * notice, this list of conditions, and the following disclaimer in the 1683998Sbrooks * documentation and/or other materials provided with the distribution. 1784000Sbrooks * 3. The name of The Aerospace Corporation may not be used to endorse or 1884000Sbrooks * promote products derived from this software. 1983998Sbrooks * 2083998Sbrooks * THIS SOFTWARE IS PROVIDED BY THE AEROSPACE CORPORATION ``AS IS'' AND 2183998Sbrooks * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2283998Sbrooks * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2383998Sbrooks * ARE DISCLAIMED. IN NO EVENT SHALL THE AEROSPACE CORPORATION BE LIABLE 2483998Sbrooks * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2583998Sbrooks * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2683998Sbrooks * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2783998Sbrooks * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2883998Sbrooks * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2983998Sbrooks * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3083998Sbrooks * SUCH DAMAGE. 3183998Sbrooks * 3283998Sbrooks * 3383998Sbrooks * Copyright (c) 1996-1999 Whistle Communications, Inc. 3483998Sbrooks * All rights reserved. 3583998Sbrooks * 3683998Sbrooks * Subject to the following obligations and disclaimer of warranty, use and 3783998Sbrooks * redistribution of this software, in source or object code forms, with or 3883998Sbrooks * without modifications are expressly permitted by Whistle Communications; 3983998Sbrooks * provided, however, that: 4083998Sbrooks * 1. Any and all reproductions of the source or object code must include the 4183998Sbrooks * copyright notice above and the following disclaimer of warranties; and 4283998Sbrooks * 2. No rights are granted, in any manner or form, to use Whistle 4383998Sbrooks * Communications, Inc. trademarks, including the mark "WHISTLE 4483998Sbrooks * COMMUNICATIONS" on advertising, endorsements, or otherwise except as 4583998Sbrooks * such appears in the above copyright notice or in the software. 4683998Sbrooks * 4783998Sbrooks * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND 4883998Sbrooks * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO 4983998Sbrooks * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, 5083998Sbrooks * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF 5183998Sbrooks * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 5283998Sbrooks * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY 5383998Sbrooks * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS 5483998Sbrooks * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. 5583998Sbrooks * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES 5683998Sbrooks * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING 5783998Sbrooks * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 5883998Sbrooks * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR 5983998Sbrooks * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY 6083998Sbrooks * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 6183998Sbrooks * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 6283998Sbrooks * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY 6383998Sbrooks * OF SUCH DAMAGE. 6483998Sbrooks * 6583998Sbrooks * $FreeBSD$ 6683998Sbrooks */ 6783998Sbrooks 6883998Sbrooks/* 6983998Sbrooks * ng_gif_demux(4) netgraph node type 7083998Sbrooks * 7183998Sbrooks * Packets received on the "gif" hook have their type header removed 7283998Sbrooks * and are passed to the appropriate hook protocol hook. Packets 7383998Sbrooks * recieved on a protocol hook have a type header added back and are 7483998Sbrooks * passed out the gif hook. The currently supported protocol hooks are: 7583998Sbrooks */ 7683998Sbrooks 7783998Sbrooks#include <sys/param.h> 7883998Sbrooks#include <sys/systm.h> 7983998Sbrooks#include <sys/kernel.h> 8083998Sbrooks#include <sys/malloc.h> 8183998Sbrooks#include <sys/ctype.h> 8283998Sbrooks#include <sys/mbuf.h> 8383998Sbrooks#include <sys/errno.h> 8483998Sbrooks#include <sys/socket.h> 8583998Sbrooks 8683998Sbrooks#include <netgraph/ng_message.h> 8783998Sbrooks#include <netgraph/netgraph.h> 8883998Sbrooks#include <netgraph/ng_parse.h> 8983998Sbrooks#include <netgraph/ng_gif_demux.h> 9083998Sbrooks 9183998Sbrooks#ifdef NG_SEPARATE_MALLOC 92227293Sedstatic MALLOC_DEFINE(M_NETGRAPH_GIF_DEMUX, "netgraph_gif_demux", 9383998Sbrooks "netgraph gif demux node"); 9483998Sbrooks#else 9583998Sbrooks#define M_NETGRAPH_GIF_DEMUX M_NETGRAPH 9683998Sbrooks#endif 9783998Sbrooks 9883998Sbrooks/* This struct describes one address family */ 9983998Sbrooksstruct iffam { 10083998Sbrooks sa_family_t family; /* Address family */ 10183998Sbrooks const char *hookname; /* Name for hook */ 10283998Sbrooks}; 10383998Sbrookstypedef const struct iffam *iffam_p; 10483998Sbrooks 10583998Sbrooks/* List of address families supported by our interface */ 10683998Sbrooksconst static struct iffam gFamilies[] = { 10783998Sbrooks { AF_INET, NG_GIF_DEMUX_HOOK_INET }, 10883998Sbrooks { AF_INET6, NG_GIF_DEMUX_HOOK_INET6 }, 10983998Sbrooks { AF_APPLETALK, NG_GIF_DEMUX_HOOK_ATALK }, 11083998Sbrooks { AF_IPX, NG_GIF_DEMUX_HOOK_IPX }, 11183998Sbrooks { AF_ATM, NG_GIF_DEMUX_HOOK_ATM }, 11283998Sbrooks { AF_NATM, NG_GIF_DEMUX_HOOK_NATM }, 11383998Sbrooks}; 11483998Sbrooks#define NUM_FAMILIES (sizeof(gFamilies) / sizeof(*gFamilies)) 11583998Sbrooks 11683998Sbrooks/* Per-node private data */ 11783998Sbrooksstruct ng_gif_demux_private { 11883998Sbrooks node_p node; /* Our netgraph node */ 11983998Sbrooks hook_p gif; /* The gif hook */ 12083998Sbrooks hook_p hooks[NUM_FAMILIES]; /* The protocol hooks */ 12183998Sbrooks}; 12283998Sbrookstypedef struct ng_gif_demux_private *priv_p; 12383998Sbrooks 12483998Sbrooks/* Netgraph node methods */ 12583998Sbrooksstatic ng_constructor_t ng_gif_demux_constructor; 12683998Sbrooksstatic ng_rcvmsg_t ng_gif_demux_rcvmsg; 12783998Sbrooksstatic ng_shutdown_t ng_gif_demux_shutdown; 12883998Sbrooksstatic ng_newhook_t ng_gif_demux_newhook; 12983998Sbrooksstatic ng_rcvdata_t ng_gif_demux_rcvdata; 13083998Sbrooksstatic ng_disconnect_t ng_gif_demux_disconnect; 13183998Sbrooks 13283998Sbrooks/* Helper stuff */ 13383998Sbrooksstatic iffam_p get_iffam_from_af(sa_family_t family); 13483998Sbrooksstatic iffam_p get_iffam_from_hook(priv_p priv, hook_p hook); 13583998Sbrooksstatic iffam_p get_iffam_from_name(const char *name); 13683998Sbrooksstatic hook_p *get_hook_from_iffam(priv_p priv, iffam_p iffam); 13783998Sbrooks 13883998Sbrooks/****************************************************************** 13983998Sbrooks NETGRAPH PARSE TYPES 14083998Sbrooks******************************************************************/ 14183998Sbrooks 14283998Sbrooks/* List of commands and how to convert arguments to/from ASCII */ 14383998Sbrooksstatic const struct ng_cmdlist ng_gif_demux_cmdlist[] = { 14483998Sbrooks { 0 } 14583998Sbrooks}; 14683998Sbrooks 14783998Sbrooks/* Node type descriptor */ 14883998Sbrooksstatic struct ng_type ng_gif_demux_typestruct = { 149129823Sjulian .version = NG_ABI_VERSION, 150129823Sjulian .name = NG_GIF_DEMUX_NODE_TYPE, 151129823Sjulian .constructor = ng_gif_demux_constructor, 152129823Sjulian .rcvmsg = ng_gif_demux_rcvmsg, 153129823Sjulian .shutdown = ng_gif_demux_shutdown, 154129823Sjulian .newhook = ng_gif_demux_newhook, 155129823Sjulian .rcvdata = ng_gif_demux_rcvdata, 156129823Sjulian .disconnect = ng_gif_demux_disconnect, 157129823Sjulian .cmdlist = ng_gif_demux_cmdlist, 15883998Sbrooks}; 15983998SbrooksNETGRAPH_INIT(gif_demux, &ng_gif_demux_typestruct); 16083998Sbrooks 16183998Sbrooks/************************************************************************ 16283998Sbrooks HELPER STUFF 16383998Sbrooks ************************************************************************/ 16483998Sbrooks 16583998Sbrooks/* 16683998Sbrooks * Get the family descriptor from the family ID 16783998Sbrooks */ 168131575Sstefanfstatic __inline iffam_p 16983998Sbrooksget_iffam_from_af(sa_family_t family) 17083998Sbrooks{ 17183998Sbrooks iffam_p iffam; 17283998Sbrooks int k; 17383998Sbrooks 17483998Sbrooks for (k = 0; k < NUM_FAMILIES; k++) { 17583998Sbrooks iffam = &gFamilies[k]; 17683998Sbrooks if (iffam->family == family) 17783998Sbrooks return (iffam); 17883998Sbrooks } 17983998Sbrooks return (NULL); 18083998Sbrooks} 18183998Sbrooks 18283998Sbrooks/* 18383998Sbrooks * Get the family descriptor from the hook 18483998Sbrooks */ 185131575Sstefanfstatic __inline iffam_p 18683998Sbrooksget_iffam_from_hook(priv_p priv, hook_p hook) 18783998Sbrooks{ 18883998Sbrooks int k; 18983998Sbrooks 19083998Sbrooks for (k = 0; k < NUM_FAMILIES; k++) 19183998Sbrooks if (priv->hooks[k] == hook) 19283998Sbrooks return (&gFamilies[k]); 19383998Sbrooks return (NULL); 19483998Sbrooks} 19583998Sbrooks 19683998Sbrooks/* 19783998Sbrooks * Get the hook from the iffam descriptor 19883998Sbrooks */ 19983998Sbrooks 200131575Sstefanfstatic __inline hook_p * 20183998Sbrooksget_hook_from_iffam(priv_p priv, iffam_p iffam) 20283998Sbrooks{ 20383998Sbrooks return (&priv->hooks[iffam - gFamilies]); 20483998Sbrooks} 20583998Sbrooks 20683998Sbrooks/* 20783998Sbrooks * Get the iffam descriptor from the name 20883998Sbrooks */ 209131575Sstefanfstatic __inline iffam_p 21083998Sbrooksget_iffam_from_name(const char *name) 21183998Sbrooks{ 21283998Sbrooks iffam_p iffam; 21383998Sbrooks int k; 21483998Sbrooks 21583998Sbrooks for (k = 0; k < NUM_FAMILIES; k++) { 21683998Sbrooks iffam = &gFamilies[k]; 21783998Sbrooks if (!strcmp(iffam->hookname, name)) 21883998Sbrooks return (iffam); 21983998Sbrooks } 22083998Sbrooks return (NULL); 22183998Sbrooks} 22283998Sbrooks 22383998Sbrooks/****************************************************************** 22483998Sbrooks NETGRAPH NODE METHODS 22583998Sbrooks******************************************************************/ 22683998Sbrooks 22783998Sbrooks/* 22883998Sbrooks * Node constructor 22983998Sbrooks */ 23083998Sbrooksstatic int 23183998Sbrooksng_gif_demux_constructor(node_p node) 23283998Sbrooks{ 23383998Sbrooks priv_p priv; 23483998Sbrooks 23583998Sbrooks /* Allocate and initialize private info */ 236220768Sglebius priv = malloc(sizeof(*priv), M_NETGRAPH_GIF_DEMUX, M_WAITOK | M_ZERO); 23783998Sbrooks priv->node = node; 23883998Sbrooks 23983998Sbrooks NG_NODE_SET_PRIVATE(node, priv); 24083998Sbrooks 24183998Sbrooks /* Done */ 24283998Sbrooks return (0); 24383998Sbrooks} 24483998Sbrooks 24583998Sbrooks/* 24683998Sbrooks * Method for attaching a new hook 24783998Sbrooks */ 24883998Sbrooksstatic int 24983998Sbrooksng_gif_demux_newhook(node_p node, hook_p hook, const char *name) 25083998Sbrooks{ 25183998Sbrooks const priv_p priv = NG_NODE_PRIVATE(node); 25283998Sbrooks iffam_p iffam; 25383998Sbrooks hook_p *hookptr; 25483998Sbrooks 25583998Sbrooks if (strcmp(NG_GIF_DEMUX_HOOK_GIF, name) == 0) 25683998Sbrooks hookptr = &priv->gif; 25783998Sbrooks else { 25883998Sbrooks iffam = get_iffam_from_name(name); 25983998Sbrooks if (iffam == NULL) 26083998Sbrooks return (EPFNOSUPPORT); 26183998Sbrooks hookptr = get_hook_from_iffam(NG_NODE_PRIVATE(node), iffam); 26283998Sbrooks } 26383998Sbrooks if (*hookptr != NULL) 26483998Sbrooks return (EISCONN); 26583998Sbrooks *hookptr = hook; 26683998Sbrooks return (0); 26783998Sbrooks} 26883998Sbrooks 26983998Sbrooks/* 27083998Sbrooks * Receive a control message 27183998Sbrooks */ 27283998Sbrooksstatic int 27383998Sbrooksng_gif_demux_rcvmsg(node_p node, item_p item, hook_p lasthook) 27483998Sbrooks{ 27583998Sbrooks struct ng_mesg *resp = NULL; 27683998Sbrooks int error = 0; 27783998Sbrooks struct ng_mesg *msg; 27883998Sbrooks 27983998Sbrooks NGI_GET_MSG(item, msg); 28083998Sbrooks switch (msg->header.typecookie) { 28183998Sbrooks case NGM_GIF_DEMUX_COOKIE: 28283998Sbrooks switch (msg->header.cmd) { 28383998Sbrooks /* XXX: Add commands here. */ 28483998Sbrooks default: 28583998Sbrooks error = EINVAL; 28683998Sbrooks break; 28783998Sbrooks } 28883998Sbrooks break; 28983998Sbrooks default: 29083998Sbrooks error = EINVAL; 29183998Sbrooks break; 29283998Sbrooks } 29383998Sbrooks 29483998Sbrooks /* Done */ 29583998Sbrooks NG_RESPOND_MSG(error, node, item, resp); 29683998Sbrooks NG_FREE_MSG(msg); 29783998Sbrooks return (error); 29883998Sbrooks} 29983998Sbrooks 30083998Sbrooks/* 30183998Sbrooks * Receive data on a hook 30283998Sbrooks */ 30383998Sbrooksstatic int 30483998Sbrooksng_gif_demux_rcvdata(hook_p hook, item_p item) 30583998Sbrooks{ 30683998Sbrooks const node_p node = NG_HOOK_NODE(hook); 30783998Sbrooks const priv_p priv = NG_NODE_PRIVATE(node); 30883998Sbrooks iffam_p iffam; 30983998Sbrooks hook_p outhook; 31083998Sbrooks int error = 0; 31183998Sbrooks struct mbuf *m; 31283998Sbrooks 31383998Sbrooks /* Pull the mbuf out of the item for processing. */ 31483998Sbrooks NGI_GET_M(item, m); 31583998Sbrooks 31683998Sbrooks if (hook == priv->gif) { 31783998Sbrooks /* 31883998Sbrooks * Pull off the address family header and find the 31983998Sbrooks * output hook. 32083998Sbrooks */ 32183998Sbrooks if (m->m_pkthdr.len < sizeof(sa_family_t)) { 32283998Sbrooks NG_FREE_M(m); 32383998Sbrooks NG_FREE_ITEM(item); 32483998Sbrooks return (EINVAL); 32583998Sbrooks } 32683998Sbrooks if (m->m_len < sizeof(sa_family_t) 32783998Sbrooks && (m = m_pullup(m, sizeof(sa_family_t))) == NULL) { 32883998Sbrooks NG_FREE_ITEM(item); 32983998Sbrooks return (ENOBUFS); 33083998Sbrooks } 33183998Sbrooks iffam = get_iffam_from_af(*mtod(m, sa_family_t *)); 33283998Sbrooks if (iffam == NULL) { 33383998Sbrooks NG_FREE_M(m); 33483998Sbrooks NG_FREE_ITEM(item); 33583998Sbrooks return (EINVAL); 33683998Sbrooks } 33783998Sbrooks outhook = *get_hook_from_iffam(priv, iffam); 33883998Sbrooks m_adj(m, sizeof(sa_family_t)); 33983998Sbrooks } else { 34083998Sbrooks /* 34183998Sbrooks * Add address family header and set the output hook. 34283998Sbrooks */ 34383998Sbrooks iffam = get_iffam_from_hook(priv, hook); 344243882Sglebius M_PREPEND(m, sizeof (iffam->family), M_NOWAIT); 34583998Sbrooks if (m == NULL) { 34683998Sbrooks NG_FREE_M(m); 34783998Sbrooks NG_FREE_ITEM(item); 34883998Sbrooks return (ENOBUFS); 34983998Sbrooks } 35083998Sbrooks bcopy(&iffam->family, mtod(m, sa_family_t *), 35183998Sbrooks sizeof(iffam->family)); 35283998Sbrooks outhook = priv->gif; 35383998Sbrooks } 35483998Sbrooks 35583998Sbrooks /* Stuff the mbuf back in. */ 35683998Sbrooks NGI_M(item) = m; 35783998Sbrooks 35883998Sbrooks /* Deliver packet */ 35983998Sbrooks NG_FWD_ITEM_HOOK(error, item, outhook); 36083998Sbrooks return (error); 36183998Sbrooks} 36283998Sbrooks 36383998Sbrooks/* 36483998Sbrooks * Shutdown node 36583998Sbrooks */ 36683998Sbrooksstatic int 36783998Sbrooksng_gif_demux_shutdown(node_p node) 36883998Sbrooks{ 36983998Sbrooks const priv_p priv = NG_NODE_PRIVATE(node); 37083998Sbrooks 371184205Sdes free(priv, M_NETGRAPH_GIF_DEMUX); 37283998Sbrooks NG_NODE_SET_PRIVATE(node, NULL); 37383998Sbrooks NG_NODE_UNREF(node); 37483998Sbrooks return (0); 37583998Sbrooks} 37683998Sbrooks 37783998Sbrooks/* 37883998Sbrooks * Hook disconnection. 37983998Sbrooks */ 38083998Sbrooksstatic int 38183998Sbrooksng_gif_demux_disconnect(hook_p hook) 38283998Sbrooks{ 38383998Sbrooks const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 38483998Sbrooks iffam_p iffam; 38583998Sbrooks 38683998Sbrooks if (hook == priv->gif) 38783998Sbrooks priv->gif = NULL; 38883998Sbrooks else { 38983998Sbrooks iffam = get_iffam_from_hook(priv, hook); 39083998Sbrooks if (iffam == NULL) 391213794Srpaulo panic("%s", __func__); 39283998Sbrooks *get_hook_from_iffam(priv, iffam) = NULL; 39383998Sbrooks } 39483998Sbrooks 39583998Sbrooks return (0); 39683998Sbrooks} 397