ng_split.c revision 80304
1258945Sroberto/*-
2280849Scy *
3258945Sroberto * Copyright (c) 1999-2000, Vitaly V Belekhov
4258945Sroberto * All rights reserved.
5258945Sroberto *
6258945Sroberto * Redistribution and use in source and binary forms, with or without
7258945Sroberto * modification, are permitted provided that the following conditions
8258945Sroberto * are met:
9258945Sroberto * 1. Redistributions of source code must retain the above copyright
10258945Sroberto *    notice unmodified, this list of conditions, and the following
11258945Sroberto *    disclaimer.
12258945Sroberto * 2. Redistributions in binary form must reproduce the above copyright
13258945Sroberto *    notice, this list of conditions and the following disclaimer in the
14258945Sroberto *    documentation and/or other materials provided with the distribution.
15258945Sroberto *
16258945Sroberto * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17258945Sroberto * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18280849Scy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19258945Sroberto * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20258945Sroberto * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21258945Sroberto * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22258945Sroberto * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23258945Sroberto * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24258945Sroberto * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25258945Sroberto * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26258945Sroberto * SUCH DAMAGE.
27258945Sroberto *
28258945Sroberto * $FreeBSD: head/sys/netgraph/ng_split.c 80304 2001-07-24 23:33:06Z brooks $
29258945Sroberto *
30258945Sroberto */
31258945Sroberto
32258945Sroberto#include <sys/param.h>
33258945Sroberto#include <sys/systm.h>
34258945Sroberto#include <sys/errno.h>
35258945Sroberto#include <sys/kernel.h>
36258945Sroberto#include <sys/malloc.h>
37258945Sroberto#include <sys/mbuf.h>
38258945Sroberto#include <sys/errno.h>
39258945Sroberto#include <sys/sockio.h>
40258945Sroberto#include <sys/socket.h>
41258945Sroberto#include <sys/syslog.h>
42258945Sroberto
43258945Sroberto#include <netgraph/ng_message.h>
44258945Sroberto#include <netgraph/netgraph.h>
45258945Sroberto#include <netgraph/ng_split.h>
46258945Sroberto
47258945Sroberto/* Netgraph methods */
48258945Srobertostatic ng_constructor_t ng_split_constructor;
49258945Srobertostatic ng_shutdown_t ng_split_shutdown;
50258945Srobertostatic ng_newhook_t ng_split_newhook;
51258945Srobertostatic ng_rcvdata_t ng_split_rcvdata;
52258945Srobertostatic ng_disconnect_t ng_split_disconnect;
53258945Sroberto
54258945Sroberto/* Node type descriptor */
55258945Srobertostatic struct ng_type typestruct = {
56258945Sroberto	NG_ABI_VERSION,
57258945Sroberto	NG_SPLIT_NODE_TYPE,
58258945Sroberto	NULL,
59258945Sroberto	ng_split_constructor,
60258945Sroberto	NULL,
61258945Sroberto	ng_split_shutdown,
62258945Sroberto	ng_split_newhook,
63258945Sroberto	NULL,
64258945Sroberto	NULL,
65258945Sroberto	ng_split_rcvdata,
66258945Sroberto	ng_split_disconnect,
67258945Sroberto	NULL
68258945Sroberto};
69258945SrobertoNETGRAPH_INIT(ng_split, &typestruct);
70258945Sroberto
71258945Sroberto/* Node private data */
72258945Srobertostruct ng_split_private {
73258945Sroberto	hook_p out;
74258945Sroberto	hook_p in;
75258945Sroberto	hook_p mixed;
76258945Sroberto	node_p	node;			/* Our netgraph node */
77258945Sroberto};
78258945Srobertotypedef struct ng_split_private *priv_p;
79258945Sroberto
80258945Sroberto/************************************************************************
81258945Sroberto			NETGRAPH NODE STUFF
82258945Sroberto ************************************************************************/
83258945Sroberto
84258945Sroberto/*
85258945Sroberto * Constructor for a node
86258945Sroberto */
87258945Srobertostatic int
88258945Srobertong_split_constructor(node_p node)
89258945Sroberto{
90258945Sroberto	priv_p		priv;
91258945Sroberto
92258945Sroberto	/* Allocate node */
93258945Sroberto	MALLOC(priv, priv_p, sizeof(*priv), M_NETGRAPH, M_ZERO | M_NOWAIT);
94258945Sroberto	if (priv == NULL)
95258945Sroberto		return (ENOMEM);
96258945Sroberto	bzero(priv, sizeof(*priv));
97258945Sroberto
98258945Sroberto	/* Link together node and private info */
99258945Sroberto	NG_NODE_SET_PRIVATE(node, priv);
100258945Sroberto	priv->node = node;
101258945Sroberto
102258945Sroberto	/* Done */
103258945Sroberto	return (0);
104258945Sroberto}
105258945Sroberto
106258945Sroberto/*
107258945Sroberto * Give our ok for a hook to be added
108258945Sroberto */
109258945Srobertostatic int
110258945Srobertong_split_newhook(node_p node, hook_p hook, const char *name)
111258945Sroberto{
112258945Sroberto	priv_p		priv = NG_NODE_PRIVATE(node);
113258945Sroberto	hook_p		*localhook;
114258945Sroberto
115258945Sroberto	if (strcmp(name, NG_SPLIT_HOOK_MIXED) == 0) {
116258945Sroberto		localhook = &priv->mixed;
117258945Sroberto	} else if (strcmp(name, NG_SPLIT_HOOK_IN) == 0) {
118258945Sroberto		localhook = &priv->in;
119258945Sroberto	} else if (strcmp(name, NG_SPLIT_HOOK_OUT) == 0) {
120258945Sroberto		localhook = &priv->out;
121258945Sroberto	} else {
122258945Sroberto		return (EPFNOSUPPORT);
123258945Sroberto	}
124258945Sroberto
125258945Sroberto	if (*localhook != NULL)
126258945Sroberto		return (EISCONN);
127258945Sroberto	*localhook = hook;
128258945Sroberto	NG_HOOK_SET_PRIVATE(hook, localhook);
129258945Sroberto
130258945Sroberto	return (0);
131258945Sroberto}
132258945Sroberto
133258945Sroberto/*
134258945Sroberto * Recive data from a hook.
135258945Sroberto */
136258945Srobertostatic int
137258945Srobertong_split_rcvdata(hook_p hook, item_p item)
138258945Sroberto{
139258945Sroberto	const priv_p	priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
140258945Sroberto	int		error = 0;
141258945Sroberto
142258945Sroberto	if (hook == priv->out) {
143258945Sroberto		printf("ng_split: got packet from out hook!\n");
144258945Sroberto		NG_FREE_ITEM(item);
145258945Sroberto		error = EINVAL;
146258945Sroberto	} else if ((hook == priv->in) && (priv->mixed != NULL)) {
147258945Sroberto		NG_FWD_ITEM_HOOK(error, item, priv->mixed);
148258945Sroberto	} else if ((hook == priv->mixed) && (priv->out != NULL)) {
149258945Sroberto		NG_FWD_ITEM_HOOK(error, item, priv->out);
150258945Sroberto	}
151258945Sroberto
152258945Sroberto	return (error);
153258945Sroberto}
154258945Sroberto
155258945Srobertostatic int
156258945Srobertong_split_shutdown(node_p node)
157258945Sroberto{
158258945Sroberto	const priv_p	priv = NG_NODE_PRIVATE(node);
159258945Sroberto
160258945Sroberto	NG_NODE_SET_PRIVATE(node, NULL);
161258945Sroberto	NG_NODE_UNREF(node);
162258945Sroberto	FREE(priv, M_NETGRAPH);
163258945Sroberto
164258945Sroberto	return (0);
165258945Sroberto}
166258945Sroberto
167258945Sroberto/*
168258945Sroberto * Hook disconnection
169258945Sroberto */
170258945Srobertostatic int
171258945Srobertong_split_disconnect(hook_p hook)
172258945Sroberto{
173258945Sroberto	hook_p		*localhook = NG_HOOK_PRIVATE(hook);
174258945Sroberto
175258945Sroberto	KASSERT(localhook != NULL, ("%s: null info", __FUNCTION__));
176258945Sroberto	*localhook = NULL;
177258945Sroberto	if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0)
178258945Sroberto	    && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) {
179258945Sroberto		ng_rmnode_self(NG_HOOK_NODE(hook));
180258945Sroberto	}
181258945Sroberto
182258945Sroberto	return (0);
183258945Sroberto}
184258945Sroberto