ng_split.c revision 80304
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 80304 2001-07-24 23:33:06Z brooks $
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 = {
5672909Sjulian	NG_ABI_VERSION,
5772909Sjulian	NG_SPLIT_NODE_TYPE,
5872909Sjulian	NULL,
5972909Sjulian	ng_split_constructor,
6080304Sbrooks	NULL,
6180304Sbrooks	ng_split_shutdown,
6272909Sjulian	ng_split_newhook,
6372909Sjulian	NULL,
6480304Sbrooks	NULL,
6572909Sjulian	ng_split_rcvdata,
6672909Sjulian	ng_split_disconnect,
6772909Sjulian	NULL
6872909Sjulian};
6972909SjulianNETGRAPH_INIT(ng_split, &typestruct);
7072909Sjulian
7172909Sjulian/* Node private data */
7272909Sjulianstruct ng_split_private {
7380304Sbrooks	hook_p out;
7480304Sbrooks	hook_p in;
7580304Sbrooks	hook_p mixed;
7672909Sjulian	node_p	node;			/* Our netgraph node */
7772909Sjulian};
7872909Sjuliantypedef struct ng_split_private *priv_p;
7972909Sjulian
8072909Sjulian/************************************************************************
8172909Sjulian			NETGRAPH NODE STUFF
8272909Sjulian ************************************************************************/
8372909Sjulian
8472909Sjulian/*
8572909Sjulian * Constructor for a node
8672909Sjulian */
8772909Sjulianstatic int
8872909Sjulianng_split_constructor(node_p node)
8972909Sjulian{
9080304Sbrooks	priv_p		priv;
9172909Sjulian
9272909Sjulian	/* Allocate node */
9372909Sjulian	MALLOC(priv, priv_p, sizeof(*priv), M_NETGRAPH, M_ZERO | M_NOWAIT);
9472909Sjulian	if (priv == NULL)
9572909Sjulian		return (ENOMEM);
9672909Sjulian	bzero(priv, sizeof(*priv));
9772909Sjulian
9872909Sjulian	/* Link together node and private info */
9972909Sjulian	NG_NODE_SET_PRIVATE(node, priv);
10072909Sjulian	priv->node = node;
10172909Sjulian
10272909Sjulian	/* Done */
10372909Sjulian	return (0);
10472909Sjulian}
10572909Sjulian
10672909Sjulian/*
10772909Sjulian * Give our ok for a hook to be added
10872909Sjulian */
10972909Sjulianstatic int
11072909Sjulianng_split_newhook(node_p node, hook_p hook, const char *name)
11172909Sjulian{
11280304Sbrooks	priv_p		priv = NG_NODE_PRIVATE(node);
11380304Sbrooks	hook_p		*localhook;
11472909Sjulian
11580304Sbrooks	if (strcmp(name, NG_SPLIT_HOOK_MIXED) == 0) {
11680304Sbrooks		localhook = &priv->mixed;
11780304Sbrooks	} else if (strcmp(name, NG_SPLIT_HOOK_IN) == 0) {
11880304Sbrooks		localhook = &priv->in;
11980304Sbrooks	} else if (strcmp(name, NG_SPLIT_HOOK_OUT) == 0) {
12080304Sbrooks		localhook = &priv->out;
12172909Sjulian	} else {
12280304Sbrooks		return (EPFNOSUPPORT);
12372909Sjulian	}
12472909Sjulian
12580304Sbrooks	if (*localhook != NULL)
12680304Sbrooks		return (EISCONN);
12780304Sbrooks	*localhook = hook;
12880304Sbrooks	NG_HOOK_SET_PRIVATE(hook, localhook);
12980304Sbrooks
13072909Sjulian	return (0);
13172909Sjulian}
13272909Sjulian
13372909Sjulian/*
13472909Sjulian * Recive data from a hook.
13572909Sjulian */
13672909Sjulianstatic int
13772909Sjulianng_split_rcvdata(hook_p hook, item_p item)
13872909Sjulian{
13980304Sbrooks	const priv_p	priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
14080304Sbrooks	int		error = 0;
14172909Sjulian
14280304Sbrooks	if (hook == priv->out) {
14380304Sbrooks		printf("ng_split: got packet from out hook!\n");
14472909Sjulian		NG_FREE_ITEM(item);
14580304Sbrooks		error = EINVAL;
14680304Sbrooks	} else if ((hook == priv->in) && (priv->mixed != NULL)) {
14772909Sjulian		NG_FWD_ITEM_HOOK(error, item, priv->mixed);
14880304Sbrooks	} else if ((hook == priv->mixed) && (priv->out != NULL)) {
14980304Sbrooks		NG_FWD_ITEM_HOOK(error, item, priv->out);
15072909Sjulian	}
15180304Sbrooks
15272909Sjulian	return (error);
15372909Sjulian}
15472909Sjulian
15572909Sjulianstatic int
15680304Sbrooksng_split_shutdown(node_p node)
15772909Sjulian{
15880304Sbrooks	const priv_p	priv = NG_NODE_PRIVATE(node);
15972909Sjulian
16072909Sjulian	NG_NODE_SET_PRIVATE(node, NULL);
16172909Sjulian	NG_NODE_UNREF(node);
16272909Sjulian	FREE(priv, M_NETGRAPH);
16372909Sjulian
16472909Sjulian	return (0);
16572909Sjulian}
16672909Sjulian
16772909Sjulian/*
16872909Sjulian * Hook disconnection
16972909Sjulian */
17072909Sjulianstatic int
17172909Sjulianng_split_disconnect(hook_p hook)
17272909Sjulian{
17380304Sbrooks	hook_p		*localhook = NG_HOOK_PRIVATE(hook);
17480304Sbrooks
17580304Sbrooks	KASSERT(localhook != NULL, ("%s: null info", __FUNCTION__));
17680304Sbrooks	*localhook = NULL;
17772909Sjulian	if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0)
17880304Sbrooks	    && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) {
17980304Sbrooks		ng_rmnode_self(NG_HOOK_NODE(hook));
18072909Sjulian	}
18172909Sjulian
18272909Sjulian	return (0);
18372909Sjulian}
184