1cdee49f9SJulian Elischer /*- 2cdee49f9SJulian Elischer * 3cdee49f9SJulian Elischer * Copyright (c) 1999-2000, Vitaly V Belekhov 4cdee49f9SJulian Elischer * All rights reserved. 5cdee49f9SJulian Elischer * 6cdee49f9SJulian Elischer * Redistribution and use in source and binary forms, with or without 7cdee49f9SJulian Elischer * modification, are permitted provided that the following conditions 8cdee49f9SJulian Elischer * are met: 9cdee49f9SJulian Elischer * 1. Redistributions of source code must retain the above copyright 10cdee49f9SJulian Elischer * notice unmodified, this list of conditions, and the following 11cdee49f9SJulian Elischer * disclaimer. 12cdee49f9SJulian Elischer * 2. Redistributions in binary form must reproduce the above copyright 13cdee49f9SJulian Elischer * notice, this list of conditions and the following disclaimer in the 14cdee49f9SJulian Elischer * documentation and/or other materials provided with the distribution. 15cdee49f9SJulian Elischer * 16cdee49f9SJulian Elischer * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17cdee49f9SJulian Elischer * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18cdee49f9SJulian Elischer * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19cdee49f9SJulian Elischer * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20cdee49f9SJulian Elischer * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21cdee49f9SJulian Elischer * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22cdee49f9SJulian Elischer * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23cdee49f9SJulian Elischer * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24cdee49f9SJulian Elischer * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25cdee49f9SJulian Elischer * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26cdee49f9SJulian Elischer * SUCH DAMAGE. 27cdee49f9SJulian Elischer * 28cdee49f9SJulian Elischer * $FreeBSD$ 29cdee49f9SJulian Elischer * 30cdee49f9SJulian Elischer */ 31cdee49f9SJulian Elischer 32cdee49f9SJulian Elischer #include <sys/param.h> 33cdee49f9SJulian Elischer #include <sys/systm.h> 34cdee49f9SJulian Elischer #include <sys/errno.h> 35cdee49f9SJulian Elischer #include <sys/kernel.h> 36cdee49f9SJulian Elischer #include <sys/malloc.h> 37cdee49f9SJulian Elischer #include <sys/mbuf.h> 38cdee49f9SJulian Elischer #include <sys/errno.h> 39cdee49f9SJulian Elischer #include <sys/sockio.h> 40cdee49f9SJulian Elischer #include <sys/socket.h> 41cdee49f9SJulian Elischer #include <sys/syslog.h> 42cdee49f9SJulian Elischer 43cdee49f9SJulian Elischer #include <netgraph/ng_message.h> 44cdee49f9SJulian Elischer #include <netgraph/netgraph.h> 45cdee49f9SJulian Elischer #include <netgraph/ng_split.h> 46cdee49f9SJulian Elischer 47cdee49f9SJulian Elischer /* Netgraph methods */ 48cdee49f9SJulian Elischer static ng_constructor_t ng_split_constructor; 49bb5c977fSBrooks Davis static ng_shutdown_t ng_split_shutdown; 50cdee49f9SJulian Elischer static ng_newhook_t ng_split_newhook; 51cdee49f9SJulian Elischer static ng_rcvdata_t ng_split_rcvdata; 52cdee49f9SJulian Elischer static ng_disconnect_t ng_split_disconnect; 53cdee49f9SJulian Elischer 54cdee49f9SJulian Elischer /* Node type descriptor */ 55cdee49f9SJulian Elischer static struct ng_type typestruct = { 56f8aae777SJulian Elischer .version = NG_ABI_VERSION, 57f8aae777SJulian Elischer .name = NG_SPLIT_NODE_TYPE, 58f8aae777SJulian Elischer .constructor = ng_split_constructor, 59f8aae777SJulian Elischer .shutdown = ng_split_shutdown, 60f8aae777SJulian Elischer .newhook = ng_split_newhook, 61f8aae777SJulian Elischer .rcvdata = ng_split_rcvdata, 62f8aae777SJulian Elischer .disconnect = ng_split_disconnect, 63cdee49f9SJulian Elischer }; 64cdee49f9SJulian Elischer NETGRAPH_INIT(ng_split, &typestruct); 65cdee49f9SJulian Elischer 66cdee49f9SJulian Elischer /* Node private data */ 67cdee49f9SJulian Elischer struct ng_split_private { 68bb5c977fSBrooks Davis hook_p out; 69bb5c977fSBrooks Davis hook_p in; 70cdee49f9SJulian Elischer hook_p mixed; 71cdee49f9SJulian Elischer node_p node; /* Our netgraph node */ 72cdee49f9SJulian Elischer }; 73cdee49f9SJulian Elischer typedef struct ng_split_private *priv_p; 74cdee49f9SJulian Elischer 75cdee49f9SJulian Elischer /************************************************************************ 76cdee49f9SJulian Elischer NETGRAPH NODE STUFF 77cdee49f9SJulian Elischer ************************************************************************/ 78cdee49f9SJulian Elischer 79cdee49f9SJulian Elischer /* 80cdee49f9SJulian Elischer * Constructor for a node 81cdee49f9SJulian Elischer */ 82cdee49f9SJulian Elischer static int 83cdee49f9SJulian Elischer ng_split_constructor(node_p node) 84cdee49f9SJulian Elischer { 85cdee49f9SJulian Elischer priv_p priv; 86cdee49f9SJulian Elischer 87cdee49f9SJulian Elischer /* Allocate node */ 88cdee49f9SJulian Elischer MALLOC(priv, priv_p, sizeof(*priv), M_NETGRAPH, M_ZERO | M_NOWAIT); 89cdee49f9SJulian Elischer if (priv == NULL) 90cdee49f9SJulian Elischer return (ENOMEM); 91cdee49f9SJulian Elischer bzero(priv, sizeof(*priv)); 92cdee49f9SJulian Elischer 93cdee49f9SJulian Elischer /* Link together node and private info */ 94cdee49f9SJulian Elischer NG_NODE_SET_PRIVATE(node, priv); 95cdee49f9SJulian Elischer priv->node = node; 96cdee49f9SJulian Elischer 97cdee49f9SJulian Elischer /* Done */ 98cdee49f9SJulian Elischer return (0); 99cdee49f9SJulian Elischer } 100cdee49f9SJulian Elischer 101cdee49f9SJulian Elischer /* 102cdee49f9SJulian Elischer * Give our ok for a hook to be added 103cdee49f9SJulian Elischer */ 104cdee49f9SJulian Elischer static int 105cdee49f9SJulian Elischer ng_split_newhook(node_p node, hook_p hook, const char *name) 106cdee49f9SJulian Elischer { 107cdee49f9SJulian Elischer priv_p priv = NG_NODE_PRIVATE(node); 108bb5c977fSBrooks Davis hook_p *localhook; 109cdee49f9SJulian Elischer 110bb5c977fSBrooks Davis if (strcmp(name, NG_SPLIT_HOOK_MIXED) == 0) { 111bb5c977fSBrooks Davis localhook = &priv->mixed; 112bb5c977fSBrooks Davis } else if (strcmp(name, NG_SPLIT_HOOK_IN) == 0) { 113bb5c977fSBrooks Davis localhook = &priv->in; 114bb5c977fSBrooks Davis } else if (strcmp(name, NG_SPLIT_HOOK_OUT) == 0) { 115bb5c977fSBrooks Davis localhook = &priv->out; 116bb5c977fSBrooks Davis } else { 117cdee49f9SJulian Elischer return (EPFNOSUPPORT); 118cdee49f9SJulian Elischer } 119bb5c977fSBrooks Davis 120bb5c977fSBrooks Davis if (*localhook != NULL) 121cdee49f9SJulian Elischer return (EISCONN); 122bb5c977fSBrooks Davis *localhook = hook; 123bb5c977fSBrooks Davis NG_HOOK_SET_PRIVATE(hook, localhook); 124cdee49f9SJulian Elischer 125cdee49f9SJulian Elischer return (0); 126cdee49f9SJulian Elischer } 127cdee49f9SJulian Elischer 128cdee49f9SJulian Elischer /* 129cdee49f9SJulian Elischer * Recive data from a hook. 130cdee49f9SJulian Elischer */ 131cdee49f9SJulian Elischer static int 132cdee49f9SJulian Elischer ng_split_rcvdata(hook_p hook, item_p item) 133cdee49f9SJulian Elischer { 134cdee49f9SJulian Elischer const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 135cdee49f9SJulian Elischer int error = 0; 136cdee49f9SJulian Elischer 137bb5c977fSBrooks Davis if (hook == priv->out) { 138cdee49f9SJulian Elischer printf("ng_split: got packet from out hook!\n"); 139cdee49f9SJulian Elischer NG_FREE_ITEM(item); 140bb5c977fSBrooks Davis error = EINVAL; 141bb5c977fSBrooks Davis } else if ((hook == priv->in) && (priv->mixed != NULL)) { 142cdee49f9SJulian Elischer NG_FWD_ITEM_HOOK(error, item, priv->mixed); 143bb5c977fSBrooks Davis } else if ((hook == priv->mixed) && (priv->out != NULL)) { 144bb5c977fSBrooks Davis NG_FWD_ITEM_HOOK(error, item, priv->out); 145cdee49f9SJulian Elischer } 146bb5c977fSBrooks Davis 147cdee49f9SJulian Elischer return (error); 148cdee49f9SJulian Elischer } 149cdee49f9SJulian Elischer 150cdee49f9SJulian Elischer static int 151bb5c977fSBrooks Davis ng_split_shutdown(node_p node) 152cdee49f9SJulian Elischer { 153cdee49f9SJulian Elischer const priv_p priv = NG_NODE_PRIVATE(node); 154cdee49f9SJulian Elischer 155cdee49f9SJulian Elischer NG_NODE_SET_PRIVATE(node, NULL); 156cdee49f9SJulian Elischer NG_NODE_UNREF(node); 157cdee49f9SJulian Elischer FREE(priv, M_NETGRAPH); 158cdee49f9SJulian Elischer 159cdee49f9SJulian Elischer return (0); 160cdee49f9SJulian Elischer } 161cdee49f9SJulian Elischer 162cdee49f9SJulian Elischer /* 163cdee49f9SJulian Elischer * Hook disconnection 164cdee49f9SJulian Elischer */ 165cdee49f9SJulian Elischer static int 166cdee49f9SJulian Elischer ng_split_disconnect(hook_p hook) 167cdee49f9SJulian Elischer { 168bb5c977fSBrooks Davis hook_p *localhook = NG_HOOK_PRIVATE(hook); 169cdee49f9SJulian Elischer 1706e551fb6SDavid E. O'Brien KASSERT(localhook != NULL, ("%s: null info", __func__)); 171bb5c977fSBrooks Davis *localhook = NULL; 172cdee49f9SJulian Elischer if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0) 173cdee49f9SJulian Elischer && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) { 174cdee49f9SJulian Elischer ng_rmnode_self(NG_HOOK_NODE(hook)); 175cdee49f9SJulian Elischer } 176cdee49f9SJulian Elischer 177cdee49f9SJulian Elischer return (0); 178cdee49f9SJulian Elischer } 179