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