ng_hub.c revision 207680
1128355Sru/*- 2128355Sru * Copyright (c) 2004 Ruslan Ermilov 3128355Sru * All rights reserved. 4128355Sru * 5128355Sru * Redistribution and use in source and binary forms, with or without 6128355Sru * modification, are permitted provided that the following conditions 7128355Sru * are met: 8128355Sru * 1. Redistributions of source code must retain the above copyright 9128355Sru * notice, this list of conditions and the following disclaimer. 10128355Sru * 2. Redistributions in binary form must reproduce the above copyright 11128355Sru * notice, this list of conditions and the following disclaimer in the 12128355Sru * documentation and/or other materials provided with the distribution. 13128355Sru * 14128355Sru * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15128355Sru * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16128355Sru * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17128355Sru * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18128355Sru * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19128355Sru * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20128355Sru * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21128355Sru * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22128355Sru * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23128355Sru * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24128355Sru * SUCH DAMAGE. 25128355Sru * 26128355Sru * $FreeBSD: head/sys/netgraph/ng_hub.c 207680 2010-05-05 22:06:05Z zec $ 27128355Sru */ 28128355Sru 29128355Sru#include <sys/param.h> 30128355Sru#include <sys/errno.h> 31128355Sru#include <sys/kernel.h> 32128355Sru#include <sys/mbuf.h> 33128355Sru#include <sys/systm.h> 34128355Sru 35128355Sru#include <netgraph/ng_message.h> 36128355Sru#include <netgraph/ng_hub.h> 37128355Sru#include <netgraph/netgraph.h> 38128355Sru 39207680Szec#ifdef NG_SEPARATE_MALLOC 40207680SzecMALLOC_DEFINE(M_NETGRAPH_HUB, "netgraph_hub", "netgraph hub node"); 41207680Szec#else 42207680Szec#define M_NETGRAPH_HUB M_NETGRAPH 43207680Szec#endif 44207680Szec 45207680Szec/* Per-node private data */ 46207680Szecstruct ng_hub_private { 47207680Szec int persistent; /* can exist w/o hooks */ 48207680Szec}; 49207680Szectypedef struct ng_hub_private *priv_p; 50207680Szec 51207680Szec/* Netgraph node methods */ 52128355Srustatic ng_constructor_t ng_hub_constructor; 53207680Szecstatic ng_rcvmsg_t ng_hub_rcvmsg; 54207680Szecstatic ng_shutdown_t ng_hub_shutdown; 55128355Srustatic ng_rcvdata_t ng_hub_rcvdata; 56128355Srustatic ng_disconnect_t ng_hub_disconnect; 57128355Sru 58207680Szec/* List of commands and how to convert arguments to/from ASCII */ 59207680Szecstatic const struct ng_cmdlist ng_hub_cmdlist[] = { 60207680Szec { 61207680Szec NGM_HUB_COOKIE, 62207680Szec NGM_HUB_SET_PERSISTENT, 63207680Szec "setpersistent", 64207680Szec NULL, 65207680Szec NULL 66207680Szec }, 67207680Szec { 0 } 68207680Szec}; 69207680Szec 70128355Srustatic struct ng_type ng_hub_typestruct = { 71128355Sru .version = NG_ABI_VERSION, 72128355Sru .name = NG_HUB_NODE_TYPE, 73128355Sru .constructor = ng_hub_constructor, 74207680Szec .rcvmsg = ng_hub_rcvmsg, 75207680Szec .shutdown = ng_hub_shutdown, 76128355Sru .rcvdata = ng_hub_rcvdata, 77128355Sru .disconnect = ng_hub_disconnect, 78207680Szec .cmdlist = ng_hub_cmdlist, 79128355Sru}; 80128355SruNETGRAPH_INIT(hub, &ng_hub_typestruct); 81128355Sru 82128355Sru 83128355Srustatic int 84128355Srung_hub_constructor(node_p node) 85128355Sru{ 86207680Szec priv_p priv; 87128355Sru 88207680Szec /* Allocate and initialize private info */ 89207680Szec priv = malloc(sizeof(*priv), M_NETGRAPH_HUB, M_NOWAIT | M_ZERO); 90207680Szec if (priv == NULL) 91207680Szec return (ENOMEM); 92207680Szec 93207680Szec NG_NODE_SET_PRIVATE(node, priv); 94128355Sru return (0); 95128355Sru} 96128355Sru 97207680Szec/* 98207680Szec * Receive a control message 99207680Szec */ 100128355Srustatic int 101207680Szecng_hub_rcvmsg(node_p node, item_p item, hook_p lasthook) 102207680Szec{ 103207680Szec const priv_p priv = NG_NODE_PRIVATE(node); 104207680Szec int error = 0; 105207680Szec struct ng_mesg *msg; 106207680Szec 107207680Szec NGI_GET_MSG(item, msg); 108207680Szec if (msg->header.typecookie == NGM_HUB_COOKIE && 109207680Szec msg->header.cmd == NGM_HUB_SET_PERSISTENT) { 110207680Szec priv->persistent = 1; 111207680Szec } else { 112207680Szec error = EINVAL; 113207680Szec } 114207680Szec 115207680Szec NG_FREE_MSG(msg); 116207680Szec return (error); 117207680Szec} 118207680Szec 119207680Szecstatic int 120128355Srung_hub_rcvdata(hook_p hook, item_p item) 121128355Sru{ 122128355Sru const node_p node = NG_HOOK_NODE(hook); 123128355Sru int error = 0; 124128355Sru hook_p hook2; 125128355Sru struct mbuf * const m = NGI_M(item), *m2; 126128355Sru int nhooks; 127128355Sru 128128355Sru if ((nhooks = NG_NODE_NUMHOOKS(node)) == 1) { 129128355Sru NG_FREE_ITEM(item); 130128355Sru return (0); 131128355Sru } 132128355Sru LIST_FOREACH(hook2, &node->nd_hooks, hk_hooks) { 133128355Sru if (hook2 == hook) 134128355Sru continue; 135128355Sru if (--nhooks == 1) 136128355Sru NG_FWD_ITEM_HOOK(error, item, hook2); 137128355Sru else { 138128355Sru if ((m2 = m_dup(m, M_DONTWAIT)) == NULL) { 139128355Sru NG_FREE_ITEM(item); 140128355Sru return (ENOBUFS); 141128355Sru } 142131155Sjulian NG_SEND_DATA_ONLY(error, hook2, m2); 143128355Sru if (error) 144128371Sru continue; /* don't give up */ 145128355Sru } 146128355Sru } 147128355Sru 148128355Sru return (error); 149128355Sru} 150128355Sru 151207680Szec/* 152207680Szec * Shutdown node 153207680Szec */ 154128355Srustatic int 155207680Szecng_hub_shutdown(node_p node) 156207680Szec{ 157207680Szec const priv_p priv = NG_NODE_PRIVATE(node); 158207680Szec 159207680Szec free(priv, M_NETGRAPH_HUB); 160207680Szec return (0); 161207680Szec} 162207680Szec 163207680Szecstatic int 164128355Srung_hub_disconnect(hook_p hook) 165128355Sru{ 166207680Szec const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 167128355Sru 168128355Sru if (NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0 && 169207680Szec NG_NODE_IS_VALID(NG_HOOK_NODE(hook)) && !priv->persistent) 170128355Sru ng_rmnode_self(NG_HOOK_NODE(hook)); 171128355Sru return (0); 172128355Sru} 173