172909Sjulian/*- 272909Sjulian * 372909Sjulian * Copyright (c) 1999-2000, Vitaly V Belekhov 472909Sjulian * All rights reserved. 572909Sjulian * 672909Sjulian * Redistribution and use in source and binary forms, with or without 772909Sjulian * modification, are permitted provided that the following conditions 872909Sjulian * are met: 972909Sjulian * 1. Redistributions of source code must retain the above copyright 1072909Sjulian * notice unmodified, this list of conditions, and the following 1172909Sjulian * disclaimer. 1272909Sjulian * 2. Redistributions in binary form must reproduce the above copyright 1372909Sjulian * notice, this list of conditions and the following disclaimer in the 1472909Sjulian * documentation and/or other materials provided with the distribution. 1572909Sjulian * 1672909Sjulian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1772909Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1872909Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1972909Sjulian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2072909Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2172909Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2272909Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2372909Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2472909Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2572909Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2672909Sjulian * SUCH DAMAGE. 2772909Sjulian * 2880304Sbrooks * $FreeBSD$ 2972909Sjulian * 3072909Sjulian */ 3172909Sjulian 3272909Sjulian#include <sys/param.h> 3372909Sjulian#include <sys/systm.h> 3472909Sjulian#include <sys/errno.h> 3572909Sjulian#include <sys/kernel.h> 3672909Sjulian#include <sys/malloc.h> 3772909Sjulian#include <sys/mbuf.h> 3872909Sjulian#include <sys/errno.h> 3972909Sjulian#include <sys/sockio.h> 4072909Sjulian#include <sys/socket.h> 4172909Sjulian#include <sys/syslog.h> 4272909Sjulian 4372909Sjulian#include <netgraph/ng_message.h> 4472909Sjulian#include <netgraph/netgraph.h> 4572909Sjulian#include <netgraph/ng_split.h> 4672909Sjulian 4772909Sjulian/* Netgraph methods */ 4872909Sjulianstatic ng_constructor_t ng_split_constructor; 4980304Sbrooksstatic ng_shutdown_t ng_split_shutdown; 5072909Sjulianstatic ng_newhook_t ng_split_newhook; 5172909Sjulianstatic ng_rcvdata_t ng_split_rcvdata; 5272909Sjulianstatic ng_disconnect_t ng_split_disconnect; 5372909Sjulian 5472909Sjulian/* Node type descriptor */ 5572909Sjulianstatic struct ng_type typestruct = { 56129823Sjulian .version = NG_ABI_VERSION, 57129823Sjulian .name = NG_SPLIT_NODE_TYPE, 58129823Sjulian .constructor = ng_split_constructor, 59129823Sjulian .shutdown = ng_split_shutdown, 60129823Sjulian .newhook = ng_split_newhook, 61129823Sjulian .rcvdata = ng_split_rcvdata, 62129823Sjulian .disconnect = ng_split_disconnect, 6372909Sjulian}; 6472909SjulianNETGRAPH_INIT(ng_split, &typestruct); 6572909Sjulian 6672909Sjulian/* Node private data */ 6772909Sjulianstruct ng_split_private { 6880304Sbrooks hook_p out; 6980304Sbrooks hook_p in; 7080304Sbrooks hook_p mixed; 7172909Sjulian node_p node; /* Our netgraph node */ 7272909Sjulian}; 7372909Sjuliantypedef struct ng_split_private *priv_p; 7472909Sjulian 7572909Sjulian/************************************************************************ 7672909Sjulian NETGRAPH NODE STUFF 7772909Sjulian ************************************************************************/ 7872909Sjulian 7972909Sjulian/* 8072909Sjulian * Constructor for a node 8172909Sjulian */ 8272909Sjulianstatic int 8372909Sjulianng_split_constructor(node_p node) 8472909Sjulian{ 8580304Sbrooks priv_p priv; 8672909Sjulian 8772909Sjulian /* Allocate node */ 88220768Sglebius priv = malloc(sizeof(*priv), M_NETGRAPH, M_ZERO | M_WAITOK); 8972909Sjulian 9072909Sjulian /* Link together node and private info */ 9172909Sjulian NG_NODE_SET_PRIVATE(node, priv); 9272909Sjulian priv->node = node; 9372909Sjulian 9472909Sjulian /* Done */ 9572909Sjulian return (0); 9672909Sjulian} 9772909Sjulian 9872909Sjulian/* 9972909Sjulian * Give our ok for a hook to be added 10072909Sjulian */ 10172909Sjulianstatic int 10272909Sjulianng_split_newhook(node_p node, hook_p hook, const char *name) 10372909Sjulian{ 10480304Sbrooks priv_p priv = NG_NODE_PRIVATE(node); 10580304Sbrooks hook_p *localhook; 10672909Sjulian 10780304Sbrooks if (strcmp(name, NG_SPLIT_HOOK_MIXED) == 0) { 10880304Sbrooks localhook = &priv->mixed; 10980304Sbrooks } else if (strcmp(name, NG_SPLIT_HOOK_IN) == 0) { 11080304Sbrooks localhook = &priv->in; 11180304Sbrooks } else if (strcmp(name, NG_SPLIT_HOOK_OUT) == 0) { 11280304Sbrooks localhook = &priv->out; 113146544Sglebius } else 114146544Sglebius return (EINVAL); 11572909Sjulian 11680304Sbrooks if (*localhook != NULL) 11780304Sbrooks return (EISCONN); 11880304Sbrooks *localhook = hook; 11980304Sbrooks NG_HOOK_SET_PRIVATE(hook, localhook); 12080304Sbrooks 12172909Sjulian return (0); 12272909Sjulian} 12372909Sjulian 12472909Sjulian/* 12572909Sjulian * Recive data from a hook. 12672909Sjulian */ 12772909Sjulianstatic int 12872909Sjulianng_split_rcvdata(hook_p hook, item_p item) 12972909Sjulian{ 13080304Sbrooks const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 13180304Sbrooks int error = 0; 13272909Sjulian 13380304Sbrooks if (hook == priv->out) { 13480304Sbrooks printf("ng_split: got packet from out hook!\n"); 13572909Sjulian NG_FREE_ITEM(item); 13680304Sbrooks error = EINVAL; 13780304Sbrooks } else if ((hook == priv->in) && (priv->mixed != NULL)) { 13872909Sjulian NG_FWD_ITEM_HOOK(error, item, priv->mixed); 13980304Sbrooks } else if ((hook == priv->mixed) && (priv->out != NULL)) { 14080304Sbrooks NG_FWD_ITEM_HOOK(error, item, priv->out); 14172909Sjulian } 14280304Sbrooks 143149577Sglebius if (item) 144149577Sglebius NG_FREE_ITEM(item); 145149577Sglebius 14672909Sjulian return (error); 14772909Sjulian} 14872909Sjulian 14972909Sjulianstatic int 15080304Sbrooksng_split_shutdown(node_p node) 15172909Sjulian{ 15280304Sbrooks const priv_p priv = NG_NODE_PRIVATE(node); 15372909Sjulian 15472909Sjulian NG_NODE_SET_PRIVATE(node, NULL); 15572909Sjulian NG_NODE_UNREF(node); 156184205Sdes free(priv, M_NETGRAPH); 15772909Sjulian 15872909Sjulian return (0); 15972909Sjulian} 16072909Sjulian 16172909Sjulian/* 16272909Sjulian * Hook disconnection 16372909Sjulian */ 16472909Sjulianstatic int 16572909Sjulianng_split_disconnect(hook_p hook) 16672909Sjulian{ 16780304Sbrooks hook_p *localhook = NG_HOOK_PRIVATE(hook); 16880304Sbrooks 16987599Sobrien KASSERT(localhook != NULL, ("%s: null info", __func__)); 17080304Sbrooks *localhook = NULL; 17172909Sjulian if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0) 17280304Sbrooks && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) { 17380304Sbrooks ng_rmnode_self(NG_HOOK_NODE(hook)); 17472909Sjulian } 17572909Sjulian 17672909Sjulian return (0); 17772909Sjulian} 178