ng_split.c revision 149577
172909Sjulian/*-
272909Sjulian *
372909Sjulian * Copyright (c) 1999-2000, Vitaly V Belekhov
472909Sjulian * All rights reserved.
572909Sjulian *
672909Sjulian * Redistribution and use in source and binary forms, with or without
772909Sjulian * modification, are permitted provided that the following conditions
872909Sjulian * are met:
972909Sjulian * 1. Redistributions of source code must retain the above copyright
1072909Sjulian *    notice unmodified, this list of conditions, and the following
1172909Sjulian *    disclaimer.
1272909Sjulian * 2. Redistributions in binary form must reproduce the above copyright
1372909Sjulian *    notice, this list of conditions and the following disclaimer in the
1472909Sjulian *    documentation and/or other materials provided with the distribution.
1572909Sjulian *
1672909Sjulian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1772909Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1872909Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1972909Sjulian * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2072909Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2172909Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2272909Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2372909Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2472909Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2572909Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2672909Sjulian * SUCH DAMAGE.
2772909Sjulian *
2880304Sbrooks * $FreeBSD: head/sys/netgraph/ng_split.c 149577 2005-08-29 13:47:08Z glebius $
2972909Sjulian *
3072909Sjulian */
3172909Sjulian
3272909Sjulian#include <sys/param.h>
3372909Sjulian#include <sys/systm.h>
3472909Sjulian#include <sys/errno.h>
3572909Sjulian#include <sys/kernel.h>
3672909Sjulian#include <sys/malloc.h>
3772909Sjulian#include <sys/mbuf.h>
3872909Sjulian#include <sys/errno.h>
3972909Sjulian#include <sys/sockio.h>
4072909Sjulian#include <sys/socket.h>
4172909Sjulian#include <sys/syslog.h>
4272909Sjulian
4372909Sjulian#include <netgraph/ng_message.h>
4472909Sjulian#include <netgraph/netgraph.h>
4572909Sjulian#include <netgraph/ng_split.h>
4672909Sjulian
4772909Sjulian/* Netgraph methods */
4872909Sjulianstatic ng_constructor_t ng_split_constructor;
4980304Sbrooksstatic ng_shutdown_t ng_split_shutdown;
5072909Sjulianstatic ng_newhook_t ng_split_newhook;
5172909Sjulianstatic ng_rcvdata_t ng_split_rcvdata;
5272909Sjulianstatic ng_disconnect_t ng_split_disconnect;
5372909Sjulian
5472909Sjulian/* Node type descriptor */
5572909Sjulianstatic struct ng_type typestruct = {
56129823Sjulian	.version =	NG_ABI_VERSION,
57129823Sjulian	.name =		NG_SPLIT_NODE_TYPE,
58129823Sjulian	.constructor =	ng_split_constructor,
59129823Sjulian	.shutdown =	ng_split_shutdown,
60129823Sjulian	.newhook =	ng_split_newhook,
61129823Sjulian	.rcvdata =	ng_split_rcvdata,
62129823Sjulian	.disconnect =	ng_split_disconnect,
6372909Sjulian};
6472909SjulianNETGRAPH_INIT(ng_split, &typestruct);
6572909Sjulian
6672909Sjulian/* Node private data */
6772909Sjulianstruct ng_split_private {
6880304Sbrooks	hook_p out;
6980304Sbrooks	hook_p in;
7080304Sbrooks	hook_p mixed;
7172909Sjulian	node_p	node;			/* Our netgraph node */
7272909Sjulian};
7372909Sjuliantypedef struct ng_split_private *priv_p;
7472909Sjulian
7572909Sjulian/************************************************************************
7672909Sjulian			NETGRAPH NODE STUFF
7772909Sjulian ************************************************************************/
7872909Sjulian
7972909Sjulian/*
8072909Sjulian * Constructor for a node
8172909Sjulian */
8272909Sjulianstatic int
8372909Sjulianng_split_constructor(node_p node)
8472909Sjulian{
8580304Sbrooks	priv_p		priv;
8672909Sjulian
8772909Sjulian	/* Allocate node */
8872909Sjulian	MALLOC(priv, priv_p, sizeof(*priv), M_NETGRAPH, M_ZERO | M_NOWAIT);
8972909Sjulian	if (priv == NULL)
9072909Sjulian		return (ENOMEM);
9172909Sjulian
9272909Sjulian	/* Link together node and private info */
9372909Sjulian	NG_NODE_SET_PRIVATE(node, priv);
9472909Sjulian	priv->node = node;
9572909Sjulian
9672909Sjulian	/* Done */
9772909Sjulian	return (0);
9872909Sjulian}
9972909Sjulian
10072909Sjulian/*
10172909Sjulian * Give our ok for a hook to be added
10272909Sjulian */
10372909Sjulianstatic int
10472909Sjulianng_split_newhook(node_p node, hook_p hook, const char *name)
10572909Sjulian{
10680304Sbrooks	priv_p		priv = NG_NODE_PRIVATE(node);
10780304Sbrooks	hook_p		*localhook;
10872909Sjulian
10980304Sbrooks	if (strcmp(name, NG_SPLIT_HOOK_MIXED) == 0) {
11080304Sbrooks		localhook = &priv->mixed;
11180304Sbrooks	} else if (strcmp(name, NG_SPLIT_HOOK_IN) == 0) {
11280304Sbrooks		localhook = &priv->in;
11380304Sbrooks	} else if (strcmp(name, NG_SPLIT_HOOK_OUT) == 0) {
11480304Sbrooks		localhook = &priv->out;
115146544Sglebius	} else
116146544Sglebius		return (EINVAL);
11772909Sjulian
11880304Sbrooks	if (*localhook != NULL)
11980304Sbrooks		return (EISCONN);
12080304Sbrooks	*localhook = hook;
12180304Sbrooks	NG_HOOK_SET_PRIVATE(hook, localhook);
12280304Sbrooks
12372909Sjulian	return (0);
12472909Sjulian}
12572909Sjulian
12672909Sjulian/*
12772909Sjulian * Recive data from a hook.
12872909Sjulian */
12972909Sjulianstatic int
13072909Sjulianng_split_rcvdata(hook_p hook, item_p item)
13172909Sjulian{
13280304Sbrooks	const priv_p	priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
13380304Sbrooks	int		error = 0;
13472909Sjulian
13580304Sbrooks	if (hook == priv->out) {
13680304Sbrooks		printf("ng_split: got packet from out hook!\n");
13772909Sjulian		NG_FREE_ITEM(item);
13880304Sbrooks		error = EINVAL;
13980304Sbrooks	} else if ((hook == priv->in) && (priv->mixed != NULL)) {
14072909Sjulian		NG_FWD_ITEM_HOOK(error, item, priv->mixed);
14180304Sbrooks	} else if ((hook == priv->mixed) && (priv->out != NULL)) {
14280304Sbrooks		NG_FWD_ITEM_HOOK(error, item, priv->out);
14372909Sjulian	}
14480304Sbrooks
145149577Sglebius	if (item)
146149577Sglebius		NG_FREE_ITEM(item);
147149577Sglebius
14872909Sjulian	return (error);
14972909Sjulian}
15072909Sjulian
15172909Sjulianstatic int
15280304Sbrooksng_split_shutdown(node_p node)
15372909Sjulian{
15480304Sbrooks	const priv_p	priv = NG_NODE_PRIVATE(node);
15572909Sjulian
15672909Sjulian	NG_NODE_SET_PRIVATE(node, NULL);
15772909Sjulian	NG_NODE_UNREF(node);
15872909Sjulian	FREE(priv, M_NETGRAPH);
15972909Sjulian
16072909Sjulian	return (0);
16172909Sjulian}
16272909Sjulian
16372909Sjulian/*
16472909Sjulian * Hook disconnection
16572909Sjulian */
16672909Sjulianstatic int
16772909Sjulianng_split_disconnect(hook_p hook)
16872909Sjulian{
16980304Sbrooks	hook_p		*localhook = NG_HOOK_PRIVATE(hook);
17080304Sbrooks
17187599Sobrien	KASSERT(localhook != NULL, ("%s: null info", __func__));
17280304Sbrooks	*localhook = NULL;
17372909Sjulian	if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0)
17480304Sbrooks	    && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) {
17580304Sbrooks		ng_rmnode_self(NG_HOOK_NODE(hook));
17672909Sjulian	}
17772909Sjulian
17872909Sjulian	return (0);
17972909Sjulian}
180