1a1fd9364Slogwang /*-
2*22ce4affSfengbojiang * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3a1fd9364Slogwang *
4a1fd9364Slogwang * Copyright (c) 1999-2000, Vitaly V Belekhov
5a1fd9364Slogwang * All rights reserved.
6a1fd9364Slogwang *
7a1fd9364Slogwang * Redistribution and use in source and binary forms, with or without
8a1fd9364Slogwang * modification, are permitted provided that the following conditions
9a1fd9364Slogwang * are met:
10a1fd9364Slogwang * 1. Redistributions of source code must retain the above copyright
11a1fd9364Slogwang * notice unmodified, this list of conditions, and the following
12a1fd9364Slogwang * disclaimer.
13a1fd9364Slogwang * 2. Redistributions in binary form must reproduce the above copyright
14a1fd9364Slogwang * notice, this list of conditions and the following disclaimer in the
15a1fd9364Slogwang * documentation and/or other materials provided with the distribution.
16a1fd9364Slogwang *
17a1fd9364Slogwang * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18a1fd9364Slogwang * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19a1fd9364Slogwang * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20a1fd9364Slogwang * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21a1fd9364Slogwang * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22a1fd9364Slogwang * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23a1fd9364Slogwang * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24a1fd9364Slogwang * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25a1fd9364Slogwang * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26a1fd9364Slogwang * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27a1fd9364Slogwang * SUCH DAMAGE.
28a1fd9364Slogwang *
29a1fd9364Slogwang * $FreeBSD$
30a1fd9364Slogwang *
31a1fd9364Slogwang */
32a1fd9364Slogwang
33a1fd9364Slogwang #include <sys/param.h>
34a1fd9364Slogwang #include <sys/systm.h>
35a1fd9364Slogwang #include <sys/errno.h>
36a1fd9364Slogwang #include <sys/kernel.h>
37a1fd9364Slogwang #include <sys/malloc.h>
38a1fd9364Slogwang #include <sys/mbuf.h>
39a1fd9364Slogwang #include <sys/errno.h>
40a1fd9364Slogwang #include <sys/sockio.h>
41a1fd9364Slogwang #include <sys/socket.h>
42a1fd9364Slogwang #include <sys/syslog.h>
43a1fd9364Slogwang
44a1fd9364Slogwang #include <netgraph/ng_message.h>
45a1fd9364Slogwang #include <netgraph/netgraph.h>
46a1fd9364Slogwang #include <netgraph/ng_split.h>
47a1fd9364Slogwang
48a1fd9364Slogwang /* Netgraph methods */
49a1fd9364Slogwang static ng_constructor_t ng_split_constructor;
50a1fd9364Slogwang static ng_shutdown_t ng_split_shutdown;
51a1fd9364Slogwang static ng_newhook_t ng_split_newhook;
52a1fd9364Slogwang static ng_rcvdata_t ng_split_rcvdata;
53a1fd9364Slogwang static ng_disconnect_t ng_split_disconnect;
54a1fd9364Slogwang
55a1fd9364Slogwang /* Node type descriptor */
56a1fd9364Slogwang static struct ng_type typestruct = {
57a1fd9364Slogwang .version = NG_ABI_VERSION,
58a1fd9364Slogwang .name = NG_SPLIT_NODE_TYPE,
59a1fd9364Slogwang .constructor = ng_split_constructor,
60a1fd9364Slogwang .shutdown = ng_split_shutdown,
61a1fd9364Slogwang .newhook = ng_split_newhook,
62a1fd9364Slogwang .rcvdata = ng_split_rcvdata,
63a1fd9364Slogwang .disconnect = ng_split_disconnect,
64a1fd9364Slogwang };
65a1fd9364Slogwang NETGRAPH_INIT(ng_split, &typestruct);
66a1fd9364Slogwang
67a1fd9364Slogwang /* Node private data */
68a1fd9364Slogwang struct ng_split_private {
69a1fd9364Slogwang hook_p out;
70a1fd9364Slogwang hook_p in;
71a1fd9364Slogwang hook_p mixed;
72a1fd9364Slogwang node_p node; /* Our netgraph node */
73a1fd9364Slogwang };
74a1fd9364Slogwang typedef struct ng_split_private *priv_p;
75a1fd9364Slogwang
76a1fd9364Slogwang /************************************************************************
77a1fd9364Slogwang NETGRAPH NODE STUFF
78a1fd9364Slogwang ************************************************************************/
79a1fd9364Slogwang
80a1fd9364Slogwang /*
81a1fd9364Slogwang * Constructor for a node
82a1fd9364Slogwang */
83a1fd9364Slogwang static int
ng_split_constructor(node_p node)84a1fd9364Slogwang ng_split_constructor(node_p node)
85a1fd9364Slogwang {
86a1fd9364Slogwang priv_p priv;
87a1fd9364Slogwang
88a1fd9364Slogwang /* Allocate node */
89a1fd9364Slogwang priv = malloc(sizeof(*priv), M_NETGRAPH, M_ZERO | M_WAITOK);
90a1fd9364Slogwang
91a1fd9364Slogwang /* Link together node and private info */
92a1fd9364Slogwang NG_NODE_SET_PRIVATE(node, priv);
93a1fd9364Slogwang priv->node = node;
94a1fd9364Slogwang
95a1fd9364Slogwang /* Done */
96a1fd9364Slogwang return (0);
97a1fd9364Slogwang }
98a1fd9364Slogwang
99a1fd9364Slogwang /*
100a1fd9364Slogwang * Give our ok for a hook to be added
101a1fd9364Slogwang */
102a1fd9364Slogwang static int
ng_split_newhook(node_p node,hook_p hook,const char * name)103a1fd9364Slogwang ng_split_newhook(node_p node, hook_p hook, const char *name)
104a1fd9364Slogwang {
105a1fd9364Slogwang priv_p priv = NG_NODE_PRIVATE(node);
106a1fd9364Slogwang hook_p *localhook;
107a1fd9364Slogwang
108a1fd9364Slogwang if (strcmp(name, NG_SPLIT_HOOK_MIXED) == 0) {
109a1fd9364Slogwang localhook = &priv->mixed;
110a1fd9364Slogwang } else if (strcmp(name, NG_SPLIT_HOOK_IN) == 0) {
111a1fd9364Slogwang localhook = &priv->in;
112a1fd9364Slogwang } else if (strcmp(name, NG_SPLIT_HOOK_OUT) == 0) {
113a1fd9364Slogwang localhook = &priv->out;
114a1fd9364Slogwang } else
115a1fd9364Slogwang return (EINVAL);
116a1fd9364Slogwang
117a1fd9364Slogwang if (*localhook != NULL)
118a1fd9364Slogwang return (EISCONN);
119a1fd9364Slogwang *localhook = hook;
120a1fd9364Slogwang NG_HOOK_SET_PRIVATE(hook, localhook);
121a1fd9364Slogwang
122a1fd9364Slogwang return (0);
123a1fd9364Slogwang }
124a1fd9364Slogwang
125a1fd9364Slogwang /*
126a1fd9364Slogwang * Recive data from a hook.
127a1fd9364Slogwang */
128a1fd9364Slogwang static int
ng_split_rcvdata(hook_p hook,item_p item)129a1fd9364Slogwang ng_split_rcvdata(hook_p hook, item_p item)
130a1fd9364Slogwang {
131a1fd9364Slogwang const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
132a1fd9364Slogwang int error = 0;
133a1fd9364Slogwang
134a1fd9364Slogwang if (hook == priv->out) {
135a1fd9364Slogwang printf("ng_split: got packet from out hook!\n");
136a1fd9364Slogwang NG_FREE_ITEM(item);
137a1fd9364Slogwang error = EINVAL;
138a1fd9364Slogwang } else if ((hook == priv->in) && (priv->mixed != NULL)) {
139a1fd9364Slogwang NG_FWD_ITEM_HOOK(error, item, priv->mixed);
140a1fd9364Slogwang } else if ((hook == priv->mixed) && (priv->out != NULL)) {
141a1fd9364Slogwang NG_FWD_ITEM_HOOK(error, item, priv->out);
142a1fd9364Slogwang }
143a1fd9364Slogwang
144a1fd9364Slogwang if (item)
145a1fd9364Slogwang NG_FREE_ITEM(item);
146a1fd9364Slogwang
147a1fd9364Slogwang return (error);
148a1fd9364Slogwang }
149a1fd9364Slogwang
150a1fd9364Slogwang static int
ng_split_shutdown(node_p node)151a1fd9364Slogwang ng_split_shutdown(node_p node)
152a1fd9364Slogwang {
153a1fd9364Slogwang const priv_p priv = NG_NODE_PRIVATE(node);
154a1fd9364Slogwang
155a1fd9364Slogwang NG_NODE_SET_PRIVATE(node, NULL);
156a1fd9364Slogwang NG_NODE_UNREF(node);
157a1fd9364Slogwang free(priv, M_NETGRAPH);
158a1fd9364Slogwang
159a1fd9364Slogwang return (0);
160a1fd9364Slogwang }
161a1fd9364Slogwang
162a1fd9364Slogwang /*
163a1fd9364Slogwang * Hook disconnection
164a1fd9364Slogwang */
165a1fd9364Slogwang static int
ng_split_disconnect(hook_p hook)166a1fd9364Slogwang ng_split_disconnect(hook_p hook)
167a1fd9364Slogwang {
168a1fd9364Slogwang hook_p *localhook = NG_HOOK_PRIVATE(hook);
169a1fd9364Slogwang
170a1fd9364Slogwang KASSERT(localhook != NULL, ("%s: null info", __func__));
171a1fd9364Slogwang *localhook = NULL;
172a1fd9364Slogwang if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0)
173a1fd9364Slogwang && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) {
174a1fd9364Slogwang ng_rmnode_self(NG_HOOK_NODE(hook));
175a1fd9364Slogwang }
176a1fd9364Slogwang
177a1fd9364Slogwang return (0);
178a1fd9364Slogwang }
179