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$ 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 40227293Sedstatic MALLOC_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 */ 89220768Sglebius priv = malloc(sizeof(*priv), M_NETGRAPH_HUB, M_WAITOK | M_ZERO); 90207680Szec 91207680Szec NG_NODE_SET_PRIVATE(node, priv); 92128355Sru return (0); 93128355Sru} 94128355Sru 95207680Szec/* 96207680Szec * Receive a control message 97207680Szec */ 98128355Srustatic int 99207680Szecng_hub_rcvmsg(node_p node, item_p item, hook_p lasthook) 100207680Szec{ 101207680Szec const priv_p priv = NG_NODE_PRIVATE(node); 102207680Szec int error = 0; 103207680Szec struct ng_mesg *msg; 104207680Szec 105207680Szec NGI_GET_MSG(item, msg); 106207680Szec if (msg->header.typecookie == NGM_HUB_COOKIE && 107207680Szec msg->header.cmd == NGM_HUB_SET_PERSISTENT) { 108207680Szec priv->persistent = 1; 109207680Szec } else { 110207680Szec error = EINVAL; 111207680Szec } 112207680Szec 113207680Szec NG_FREE_MSG(msg); 114207680Szec return (error); 115207680Szec} 116207680Szec 117207680Szecstatic int 118128355Srung_hub_rcvdata(hook_p hook, item_p item) 119128355Sru{ 120128355Sru const node_p node = NG_HOOK_NODE(hook); 121128355Sru int error = 0; 122128355Sru hook_p hook2; 123128355Sru struct mbuf * const m = NGI_M(item), *m2; 124128355Sru int nhooks; 125128355Sru 126128355Sru if ((nhooks = NG_NODE_NUMHOOKS(node)) == 1) { 127128355Sru NG_FREE_ITEM(item); 128128355Sru return (0); 129128355Sru } 130128355Sru LIST_FOREACH(hook2, &node->nd_hooks, hk_hooks) { 131128355Sru if (hook2 == hook) 132128355Sru continue; 133128355Sru if (--nhooks == 1) 134128355Sru NG_FWD_ITEM_HOOK(error, item, hook2); 135128355Sru else { 136243882Sglebius if ((m2 = m_dup(m, M_NOWAIT)) == NULL) { 137128355Sru NG_FREE_ITEM(item); 138128355Sru return (ENOBUFS); 139128355Sru } 140131155Sjulian NG_SEND_DATA_ONLY(error, hook2, m2); 141128355Sru if (error) 142128371Sru continue; /* don't give up */ 143128355Sru } 144128355Sru } 145128355Sru 146128355Sru return (error); 147128355Sru} 148128355Sru 149207680Szec/* 150207680Szec * Shutdown node 151207680Szec */ 152128355Srustatic int 153207680Szecng_hub_shutdown(node_p node) 154207680Szec{ 155207680Szec const priv_p priv = NG_NODE_PRIVATE(node); 156207680Szec 157207680Szec free(priv, M_NETGRAPH_HUB); 158220416Szec NG_NODE_SET_PRIVATE(node, NULL); 159220416Szec NG_NODE_UNREF(node); 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