ng_split.c revision 87599
1208963Srdivacky/*-
2208963Srdivacky *
3265420Simp * Copyright (c) 1999-2000, Vitaly V Belekhov
4231057Sdim * All rights reserved.
5214562Srpaulo *
6265831Simp * Redistribution and use in source and binary forms, with or without
7246259Sdim * modification, are permitted provided that the following conditions
8246259Sdim * are met:
9246259Sdim * 1. Redistributions of source code must retain the above copyright
10246259Sdim *    notice unmodified, this list of conditions, and the following
11246259Sdim *    disclaimer.
12246259Sdim * 2. Redistributions in binary form must reproduce the above copyright
13255722Semaste *    notice, this list of conditions and the following disclaimer in the
14246259Sdim *    documentation and/or other materials provided with the distribution.
15208963Srdivacky *
16246259Sdim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17208963Srdivacky * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18208963Srdivacky * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19208963Srdivacky * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20208963Srdivacky * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21234353Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22208963Srdivacky * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23212904Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24208963Srdivacky * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25208963Srdivacky * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26276479Sdim * SUCH DAMAGE.
27276479Sdim *
28208963Srdivacky * $FreeBSD: head/sys/netgraph/ng_split.c 87599 2001-12-10 08:09:49Z obrien $
29212904Sdim *
30246259Sdim */
31208963Srdivacky
32208963Srdivacky#include <sys/param.h>
33210299Sed#include <sys/systm.h>
34208963Srdivacky#include <sys/errno.h>
35208963Srdivacky#include <sys/kernel.h>
36208963Srdivacky#include <sys/malloc.h>
37208963Srdivacky#include <sys/mbuf.h>
38221345Sdim#include <sys/errno.h>
39208963Srdivacky#include <sys/sockio.h>
40221345Sdim#include <sys/socket.h>
41208963Srdivacky#include <sys/syslog.h>
42249423Sdim
43234353Sdim#include <netgraph/ng_message.h>
44208963Srdivacky#include <netgraph/netgraph.h>
45280031Sdim#include <netgraph/ng_split.h>
46208963Srdivacky
47249423Sdim/* Netgraph methods */
48234353Sdimstatic ng_constructor_t ng_split_constructor;
49261991Sdimstatic ng_shutdown_t ng_split_shutdown;
50276479Sdimstatic ng_newhook_t ng_split_newhook;
51208963Srdivackystatic ng_rcvdata_t ng_split_rcvdata;
52208963Srdivackystatic ng_disconnect_t ng_split_disconnect;
53208963Srdivacky
54226633Sdim/* Node type descriptor */
55208963Srdivackystatic struct ng_type typestruct = {
56208963Srdivacky	NG_ABI_VERSION,
57234353Sdim	NG_SPLIT_NODE_TYPE,
58208963Srdivacky	NULL,
59276783Sdim	ng_split_constructor,
60296417Sdim	NULL,
61276783Sdim	ng_split_shutdown,
62276783Sdim	ng_split_newhook,
63276783Sdim	NULL,
64276783Sdim	NULL,
65208963Srdivacky	ng_split_rcvdata,
66296417Sdim	ng_split_disconnect,
67208963Srdivacky	NULL
68224145Sdim};
69208963SrdivackyNETGRAPH_INIT(ng_split, &typestruct);
70234353Sdim
71296417Sdim/* Node private data */
72208963Srdivackystruct ng_split_private {
73224145Sdim	hook_p out;
74208963Srdivacky	hook_p in;
75259473Sdim	hook_p mixed;
76296417Sdim	node_p	node;			/* Our netgraph node */
77208963Srdivacky};
78224145Sdimtypedef struct ng_split_private *priv_p;
79208963Srdivacky
80262613Sdim/************************************************************************
81296417Sdim			NETGRAPH NODE STUFF
82262613Sdim ************************************************************************/
83262613Sdim
84262613Sdim/*
85208963Srdivacky * Constructor for a node
86296417Sdim */
87208963Srdivackystatic int
88224145Sdimng_split_constructor(node_p node)
89218893Sdim{
90218893Sdim	priv_p		priv;
91231057Sdim
92231057Sdim	/* Allocate node */
93301993Sbdrewery	MALLOC(priv, priv_p, sizeof(*priv), M_NETGRAPH, M_ZERO | M_NOWAIT);
94301993Sbdrewery	if (priv == NULL)
95301993Sbdrewery		return (ENOMEM);
96288943Sdim	bzero(priv, sizeof(*priv));
97291495Sbdrewery
98288943Sdim	/* Link together node and private info */
99291495Sbdrewery	NG_NODE_SET_PRIVATE(node, priv);
100288943Sdim	priv->node = node;
101296417Sdim
102296417Sdim	/* Done */
103255722Semaste	return (0);
104296417Sdim}
105255722Semaste
106296417Sdim/*
107296417Sdim * Give our ok for a hook to be added
108296417Sdim */
109231057Sdimstatic int
110231057Sdimng_split_newhook(node_p node, hook_p hook, const char *name)
111288943Sdim{
112296417Sdim	priv_p		priv = NG_NODE_PRIVATE(node);
113288943Sdim	hook_p		*localhook;
114288943Sdim
115288943Sdim	if (strcmp(name, NG_SPLIT_HOOK_MIXED) == 0) {
116255722Semaste		localhook = &priv->mixed;
117255722Semaste	} else if (strcmp(name, NG_SPLIT_HOOK_IN) == 0) {
118265831Simp		localhook = &priv->in;
119255722Semaste	} else if (strcmp(name, NG_SPLIT_HOOK_OUT) == 0) {
120255722Semaste		localhook = &priv->out;
121255722Semaste	} else {
122255722Semaste		return (EPFNOSUPPORT);
123255722Semaste	}
124255722Semaste
125255722Semaste	if (*localhook != NULL)
126255722Semaste		return (EISCONN);
127255722Semaste	*localhook = hook;
128255722Semaste	NG_HOOK_SET_PRIVATE(hook, localhook);
129276479Sdim
130288943Sdim	return (0);
131255722Semaste}
132255722Semaste
133255722Semaste/*
134255722Semaste * Recive data from a hook.
135255722Semaste */
136288943Sdimstatic int
137288943Sdimng_split_rcvdata(hook_p hook, item_p item)
138288943Sdim{
139288943Sdim	const priv_p	priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
140288943Sdim	int		error = 0;
141280031Sdim
142280031Sdim	if (hook == priv->out) {
143255722Semaste		printf("ng_split: got packet from out hook!\n");
144255722Semaste		NG_FREE_ITEM(item);
145255722Semaste		error = EINVAL;
146255722Semaste	} else if ((hook == priv->in) && (priv->mixed != NULL)) {
147255722Semaste		NG_FWD_ITEM_HOOK(error, item, priv->mixed);
148296417Sdim	} else if ((hook == priv->mixed) && (priv->out != NULL)) {
149296417Sdim		NG_FWD_ITEM_HOOK(error, item, priv->out);
150255722Semaste	}
151276479Sdim
152288943Sdim	return (error);
153288943Sdim}
154280031Sdim
155276479Sdimstatic int
156296417Sdimng_split_shutdown(node_p node)
157296417Sdim{
158280031Sdim	const priv_p	priv = NG_NODE_PRIVATE(node);
159255722Semaste
160255722Semaste	NG_NODE_SET_PRIVATE(node, NULL);
161276479Sdim	NG_NODE_UNREF(node);
162255722Semaste	FREE(priv, M_NETGRAPH);
163255722Semaste
164255722Semaste	return (0);
165255722Semaste}
166255722Semaste
167255722Semaste/*
168255722Semaste * Hook disconnection
169296417Sdim */
170255722Semastestatic int
171255722Semasteng_split_disconnect(hook_p hook)
172255722Semaste{
173255722Semaste	hook_p		*localhook = NG_HOOK_PRIVATE(hook);
174255722Semaste
175265831Simp	KASSERT(localhook != NULL, ("%s: null info", __func__));
176255722Semaste	*localhook = NULL;
177246259Sdim	if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0)
178208963Srdivacky	    && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) {
179214562Srpaulo		ng_rmnode_self(NG_HOOK_NODE(hook));
180214562Srpaulo	}
181263778Sdim
182263778Sdim	return (0);
183208963Srdivacky}
184