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