ng_hub.c revision 220416
1139778Simp/*- 21541Srgrimes * Copyright (c) 2004 Ruslan Ermilov 31541Srgrimes * All rights reserved. 41541Srgrimes * 51541Srgrimes * Redistribution and use in source and binary forms, with or without 61541Srgrimes * modification, are permitted provided that the following conditions 71541Srgrimes * are met: 81541Srgrimes * 1. Redistributions of source code must retain the above copyright 91541Srgrimes * notice, this list of conditions and the following disclaimer. 101541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111541Srgrimes * notice, this list of conditions and the following disclaimer in the 121541Srgrimes * documentation and/or other materials provided with the distribution. 131541Srgrimes * 141541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 151541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 161541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 171541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 181541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 191541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 201541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 211541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 221541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 231541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 241541Srgrimes * SUCH DAMAGE. 251541Srgrimes * 261541Srgrimes * $FreeBSD: head/sys/netgraph/ng_hub.c 220416 2011-04-07 11:40:10Z zec $ 271541Srgrimes */ 281541Srgrimes 291541Srgrimes#include <sys/param.h> 301541Srgrimes#include <sys/errno.h> 311541Srgrimes#include <sys/kernel.h> 321541Srgrimes#include <sys/mbuf.h> 331541Srgrimes#include <sys/systm.h> 3422521Sdyson 3550477Speter#include <netgraph/ng_message.h> 361541Srgrimes#include <netgraph/ng_hub.h> 371541Srgrimes#include <netgraph/netgraph.h> 38202283Slulf 39202283Slulf#ifdef NG_SEPARATE_MALLOC 402177SpaulMALLOC_DEFINE(M_NETGRAPH_HUB, "netgraph_hub", "netgraph hub node"); 41254260Spfg#else 4231557Sjkh#define M_NETGRAPH_HUB M_NETGRAPH 43254260Spfg#endif 4444512Sbde 451541Srgrimes/* Per-node private data */ 46254260Spfgstruct ng_hub_private { 47254260Spfg int persistent; /* can exist w/o hooks */ 4834266Sjulian}; 4924477Sbdetypedef struct ng_hub_private *priv_p; 5024477Sbde 5124477Sbde/* Netgraph node methods */ 5224477Sbdestatic ng_constructor_t ng_hub_constructor; 53251809Spfgstatic ng_rcvmsg_t ng_hub_rcvmsg; 54251809Spfgstatic ng_shutdown_t ng_hub_shutdown; 55251809Spfgstatic ng_rcvdata_t ng_hub_rcvdata; 5624477Sbdestatic ng_disconnect_t ng_hub_disconnect; 57254283Spfg 58252103Spfg/* List of commands and how to convert arguments to/from ASCII */ 59254283Spfgstatic const struct ng_cmdlist ng_hub_cmdlist[] = { 60254283Spfg { 61254283Spfg NGM_HUB_COOKIE, 62252103Spfg NGM_HUB_SET_PERSISTENT, 63252103Spfg "setpersistent", 6422521Sdyson NULL, 6596596Siedowse NULL 6696596Siedowse }, 6796596Siedowse { 0 } 6896596Siedowse}; 6922521Sdyson 7022521Sdysonstatic struct ng_type ng_hub_typestruct = { 711541Srgrimes .version = NG_ABI_VERSION, 7222521Sdyson .name = NG_HUB_NODE_TYPE, 7322521Sdyson .constructor = ng_hub_constructor, 74202283Slulf .rcvmsg = ng_hub_rcvmsg, 75221126Sjhb .shutdown = ng_hub_shutdown, 7622521Sdyson .rcvdata = ng_hub_rcvdata, 771541Srgrimes .disconnect = ng_hub_disconnect, 78202283Slulf .cmdlist = ng_hub_cmdlist, 7922521Sdyson}; 801541SrgrimesNETGRAPH_INIT(hub, &ng_hub_typestruct); 811541Srgrimes 821541Srgrimes 83221126Sjhbstatic int 84221126Sjhbng_hub_constructor(node_p node) 85221126Sjhb{ 86221126Sjhb priv_p priv; 8779561Siedowse 88221126Sjhb /* Allocate and initialize private info */ 89221126Sjhb priv = malloc(sizeof(*priv), M_NETGRAPH_HUB, M_NOWAIT | M_ZERO); 90221126Sjhb if (priv == NULL) 9196596Siedowse return (ENOMEM); 9296596Siedowse 93221126Sjhb NG_NODE_SET_PRIVATE(node, priv); 9496596Siedowse return (0); 95254260Spfg} 96254260Spfg 97221126Sjhb/* 98254260Spfg * Receive a control message 9996596Siedowse */ 10096596Siedowsestatic int 101231168Spfgng_hub_rcvmsg(node_p node, item_p item, hook_p lasthook) 102231168Spfg{ 10396596Siedowse const priv_p priv = NG_NODE_PRIVATE(node); 104231168Spfg int error = 0; 10596596Siedowse struct ng_mesg *msg; 106231168Spfg 107254260Spfg NGI_GET_MSG(item, msg); 108254260Spfg if (msg->header.typecookie == NGM_HUB_COOKIE && 109245820Spfg msg->header.cmd == NGM_HUB_SET_PERSISTENT) { 110245820Spfg priv->persistent = 1; 111254260Spfg } else { 112254260Spfg error = EINVAL; 1131541Srgrimes } 1141541Srgrimes 11596596Siedowse NG_FREE_MSG(msg); 11696596Siedowse return (error); 11796596Siedowse} 11896596Siedowse 119130763Sbdestatic int 12096596Siedowseng_hub_rcvdata(hook_p hook, item_p item) 12196596Siedowse{ 12296596Siedowse const node_p node = NG_HOOK_NODE(hook); 12396596Siedowse int error = 0; 1241541Srgrimes hook_p hook2; 12596596Siedowse struct mbuf * const m = NGI_M(item), *m2; 12696596Siedowse int nhooks; 12796596Siedowse 12896596Siedowse if ((nhooks = NG_NODE_NUMHOOKS(node)) == 1) { 12996596Siedowse NG_FREE_ITEM(item); 13096596Siedowse return (0); 13196596Siedowse } 13296596Siedowse LIST_FOREACH(hook2, &node->nd_hooks, hk_hooks) { 13396596Siedowse if (hook2 == hook) 13496596Siedowse continue; 13596596Siedowse if (--nhooks == 1) 13696596Siedowse NG_FWD_ITEM_HOOK(error, item, hook2); 13796596Siedowse else { 13896596Siedowse if ((m2 = m_dup(m, M_DONTWAIT)) == NULL) { 13996596Siedowse NG_FREE_ITEM(item); 14096596Siedowse return (ENOBUFS); 14196596Siedowse } 14296596Siedowse NG_SEND_DATA_ONLY(error, hook2, m2); 14396596Siedowse if (error) 1441541Srgrimes continue; /* don't give up */ 1451541Srgrimes } 1461541Srgrimes } 14722521Sdyson 14822521Sdyson return (error); 14922521Sdyson} 15076357Smckusick 15176357Smckusick/* 15276357Smckusick * Shutdown node 153202283Slulf */ 154202283Slulfstatic int 155217582Sjhbng_hub_shutdown(node_p node) 156260988Spfg{ 157260988Spfg const priv_p priv = NG_NODE_PRIVATE(node); 158260988Spfg 159260988Spfg free(priv, M_NETGRAPH_HUB); 160260988Spfg NG_NODE_SET_PRIVATE(node, NULL); 161260988Spfg NG_NODE_UNREF(node); 162260988Spfg return (0); 163217582Sjhb} 164217582Sjhb 16555206Speterstatic int 1661541Srgrimesng_hub_disconnect(hook_p hook) 1671541Srgrimes{ 16896877Siedowse const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 1691541Srgrimes 1701541Srgrimes if (NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0 && 171252103Spfg NG_NODE_IS_VALID(NG_HOOK_NODE(hook)) && !priv->persistent) 1721541Srgrimes ng_rmnode_self(NG_HOOK_NODE(hook)); 1731541Srgrimes return (0); 1741541Srgrimes} 1751541Srgrimes