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 */ 881ede983cSDag-Erling Smørgrav priv = malloc(sizeof(*priv), M_NETGRAPH, M_ZERO | M_NOWAIT); 89cdee49f9SJulian Elischer if (priv == NULL) 90cdee49f9SJulian Elischer return (ENOMEM); 91cdee49f9SJulian Elischer 92cdee49f9SJulian Elischer /* Link together node and private info */ 93cdee49f9SJulian Elischer NG_NODE_SET_PRIVATE(node, priv); 94cdee49f9SJulian Elischer priv->node = node; 95cdee49f9SJulian Elischer 96cdee49f9SJulian Elischer /* Done */ 97cdee49f9SJulian Elischer return (0); 98cdee49f9SJulian Elischer } 99cdee49f9SJulian Elischer 100cdee49f9SJulian Elischer /* 101cdee49f9SJulian Elischer * Give our ok for a hook to be added 102cdee49f9SJulian Elischer */ 103cdee49f9SJulian Elischer static int 104cdee49f9SJulian Elischer ng_split_newhook(node_p node, hook_p hook, const char *name) 105cdee49f9SJulian Elischer { 106cdee49f9SJulian Elischer priv_p priv = NG_NODE_PRIVATE(node); 107bb5c977fSBrooks Davis hook_p *localhook; 108cdee49f9SJulian Elischer 109bb5c977fSBrooks Davis if (strcmp(name, NG_SPLIT_HOOK_MIXED) == 0) { 110bb5c977fSBrooks Davis localhook = &priv->mixed; 111bb5c977fSBrooks Davis } else if (strcmp(name, NG_SPLIT_HOOK_IN) == 0) { 112bb5c977fSBrooks Davis localhook = &priv->in; 113bb5c977fSBrooks Davis } else if (strcmp(name, NG_SPLIT_HOOK_OUT) == 0) { 114bb5c977fSBrooks Davis localhook = &priv->out; 115a09c9f01SGleb Smirnoff } else 116a09c9f01SGleb Smirnoff return (EINVAL); 117bb5c977fSBrooks Davis 118bb5c977fSBrooks Davis if (*localhook != NULL) 119cdee49f9SJulian Elischer return (EISCONN); 120bb5c977fSBrooks Davis *localhook = hook; 121bb5c977fSBrooks Davis NG_HOOK_SET_PRIVATE(hook, localhook); 122cdee49f9SJulian Elischer 123cdee49f9SJulian Elischer return (0); 124cdee49f9SJulian Elischer } 125cdee49f9SJulian Elischer 126cdee49f9SJulian Elischer /* 127cdee49f9SJulian Elischer * Recive data from a hook. 128cdee49f9SJulian Elischer */ 129cdee49f9SJulian Elischer static int 130cdee49f9SJulian Elischer ng_split_rcvdata(hook_p hook, item_p item) 131cdee49f9SJulian Elischer { 132cdee49f9SJulian Elischer const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 133cdee49f9SJulian Elischer int error = 0; 134cdee49f9SJulian Elischer 135bb5c977fSBrooks Davis if (hook == priv->out) { 136cdee49f9SJulian Elischer printf("ng_split: got packet from out hook!\n"); 137cdee49f9SJulian Elischer NG_FREE_ITEM(item); 138bb5c977fSBrooks Davis error = EINVAL; 139bb5c977fSBrooks Davis } else if ((hook == priv->in) && (priv->mixed != NULL)) { 140cdee49f9SJulian Elischer NG_FWD_ITEM_HOOK(error, item, priv->mixed); 141bb5c977fSBrooks Davis } else if ((hook == priv->mixed) && (priv->out != NULL)) { 142bb5c977fSBrooks Davis NG_FWD_ITEM_HOOK(error, item, priv->out); 143cdee49f9SJulian Elischer } 144bb5c977fSBrooks Davis 1453ff2ed9eSGleb Smirnoff if (item) 1463ff2ed9eSGleb Smirnoff NG_FREE_ITEM(item); 1473ff2ed9eSGleb Smirnoff 148cdee49f9SJulian Elischer return (error); 149cdee49f9SJulian Elischer } 150cdee49f9SJulian Elischer 151cdee49f9SJulian Elischer static int 152bb5c977fSBrooks Davis ng_split_shutdown(node_p node) 153cdee49f9SJulian Elischer { 154cdee49f9SJulian Elischer const priv_p priv = NG_NODE_PRIVATE(node); 155cdee49f9SJulian Elischer 156cdee49f9SJulian Elischer NG_NODE_SET_PRIVATE(node, NULL); 157cdee49f9SJulian Elischer NG_NODE_UNREF(node); 1581ede983cSDag-Erling Smørgrav free(priv, M_NETGRAPH); 159cdee49f9SJulian Elischer 160cdee49f9SJulian Elischer return (0); 161cdee49f9SJulian Elischer } 162cdee49f9SJulian Elischer 163cdee49f9SJulian Elischer /* 164cdee49f9SJulian Elischer * Hook disconnection 165cdee49f9SJulian Elischer */ 166cdee49f9SJulian Elischer static int 167cdee49f9SJulian Elischer ng_split_disconnect(hook_p hook) 168cdee49f9SJulian Elischer { 169bb5c977fSBrooks Davis hook_p *localhook = NG_HOOK_PRIVATE(hook); 170cdee49f9SJulian Elischer 1716e551fb6SDavid E. O'Brien KASSERT(localhook != NULL, ("%s: null info", __func__)); 172bb5c977fSBrooks Davis *localhook = NULL; 173cdee49f9SJulian Elischer if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0) 174cdee49f9SJulian Elischer && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) { 175cdee49f9SJulian Elischer ng_rmnode_self(NG_HOOK_NODE(hook)); 176cdee49f9SJulian Elischer } 177cdee49f9SJulian Elischer 178cdee49f9SJulian Elischer return (0); 179cdee49f9SJulian Elischer } 180