ng_gif_demux.c revision 129823
1200110Snetchild/*
2200110Snetchild * ng_gif_demux.c
3200110Snetchild *
4200110Snetchild * Copyright 2001 The Aerospace Corporation.  All rights reserved.
5200110Snetchild *
6200110Snetchild * Redistribution and use in source and binary forms, with or without
7200110Snetchild * modification, are permitted provided that the following conditions
8200110Snetchild * are met:
9200110Snetchild *
10200110Snetchild * 1. Redistributions of source code must retain the above copyright
11200110Snetchild *    notice, this list of conditions, and the following disclaimer.
12200110Snetchild * 2. Redistributions in binary form must reproduce the above copyright
13200110Snetchild *    notice, this list of conditions, and the following disclaimer in the
14200110Snetchild *    documentation and/or other materials provided with the distribution.
15200110Snetchild * 3. The name of The Aerospace Corporation may not be used to endorse or
16200110Snetchild *    promote products derived from this software.
17200110Snetchild *
18200110Snetchild * THIS SOFTWARE IS PROVIDED BY THE AEROSPACE CORPORATION ``AS IS'' AND
19200110Snetchild * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20200110Snetchild * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21200110Snetchild * ARE DISCLAIMED.  IN NO EVENT SHALL THE AEROSPACE CORPORATION BE LIABLE
22200110Snetchild * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23200110Snetchild * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24200110Snetchild * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25200110Snetchild * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26200110Snetchild * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27200110Snetchild * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28200110Snetchild * SUCH DAMAGE.
29200110Snetchild *
30200110Snetchild *
31200110Snetchild * Copyright (c) 1996-1999 Whistle Communications, Inc.
32200110Snetchild * All rights reserved.
33200110Snetchild *
34200110Snetchild * Subject to the following obligations and disclaimer of warranty, use and
35200110Snetchild * redistribution of this software, in source or object code forms, with or
36200110Snetchild * without modifications are expressly permitted by Whistle Communications;
37200110Snetchild * provided, however, that:
38200110Snetchild * 1. Any and all reproductions of the source or object code must include the
39200110Snetchild *    copyright notice above and the following disclaimer of warranties; and
40200110Snetchild * 2. No rights are granted, in any manner or form, to use Whistle
41200110Snetchild *    Communications, Inc. trademarks, including the mark "WHISTLE
42200110Snetchild *    COMMUNICATIONS" on advertising, endorsements, or otherwise except as
43200110Snetchild *    such appears in the above copyright notice or in the software.
44200110Snetchild *
45200110Snetchild * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
46200110Snetchild * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
47200110Snetchild * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
48200110Snetchild * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
49200110Snetchild * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
50200110Snetchild * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
51200110Snetchild * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
52200110Snetchild * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
53200110Snetchild * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
54200110Snetchild * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
55200110Snetchild * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
56200110Snetchild * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
57200110Snetchild * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
58200110Snetchild * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
59200110Snetchild * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
60 * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
61 * OF SUCH DAMAGE.
62 *
63 * $FreeBSD: head/sys/netgraph/ng_gif_demux.c 129823 2004-05-29 00:51:19Z julian $
64 */
65
66/*
67 * ng_gif_demux(4) netgraph node type
68 *
69 * Packets received on the "gif" hook have their type header removed
70 * and are passed to the appropriate hook protocol hook.  Packets
71 * recieved on a protocol hook have a type header added back and are
72 * passed out the gif hook. The currently supported protocol hooks are:
73 */
74
75#include <sys/param.h>
76#include <sys/systm.h>
77#include <sys/kernel.h>
78#include <sys/malloc.h>
79#include <sys/ctype.h>
80#include <sys/mbuf.h>
81#include <sys/errno.h>
82#include <sys/socket.h>
83
84#include <netgraph/ng_message.h>
85#include <netgraph/netgraph.h>
86#include <netgraph/ng_parse.h>
87#include <netgraph/ng_gif_demux.h>
88
89#ifdef NG_SEPARATE_MALLOC
90MALLOC_DEFINE(M_NETGRAPH_GIF_DEMUX, "netgraph_gif_demux",
91    "netgraph gif demux node");
92#else
93#define M_NETGRAPH_GIF_DEMUX M_NETGRAPH
94#endif
95
96/* This struct describes one address family */
97struct iffam {
98	sa_family_t	family;		/* Address family */
99	const char	*hookname;	/* Name for hook */
100};
101typedef const struct iffam *iffam_p;
102
103/* List of address families supported by our interface */
104const static struct iffam gFamilies[] = {
105	{ AF_INET,	NG_GIF_DEMUX_HOOK_INET	},
106	{ AF_INET6,	NG_GIF_DEMUX_HOOK_INET6	},
107	{ AF_APPLETALK,	NG_GIF_DEMUX_HOOK_ATALK	},
108	{ AF_IPX,	NG_GIF_DEMUX_HOOK_IPX	},
109	{ AF_ATM,	NG_GIF_DEMUX_HOOK_ATM	},
110	{ AF_NATM,	NG_GIF_DEMUX_HOOK_NATM	},
111};
112#define NUM_FAMILIES		(sizeof(gFamilies) / sizeof(*gFamilies))
113
114/* Per-node private data */
115struct ng_gif_demux_private {
116	node_p	node;			/* Our netgraph node */
117	hook_p	gif;			/* The gif hook */
118	hook_p	hooks[NUM_FAMILIES];	/* The protocol hooks */
119};
120typedef struct ng_gif_demux_private *priv_p;
121
122/* Netgraph node methods */
123static ng_constructor_t	ng_gif_demux_constructor;
124static ng_rcvmsg_t	ng_gif_demux_rcvmsg;
125static ng_shutdown_t	ng_gif_demux_shutdown;
126static ng_newhook_t	ng_gif_demux_newhook;
127static ng_rcvdata_t	ng_gif_demux_rcvdata;
128static ng_disconnect_t	ng_gif_demux_disconnect;
129
130/* Helper stuff */
131static iffam_p	get_iffam_from_af(sa_family_t family);
132static iffam_p	get_iffam_from_hook(priv_p priv, hook_p hook);
133static iffam_p	get_iffam_from_name(const char *name);
134static hook_p	*get_hook_from_iffam(priv_p priv, iffam_p iffam);
135
136/******************************************************************
137		    NETGRAPH PARSE TYPES
138******************************************************************/
139
140/* List of commands and how to convert arguments to/from ASCII */
141static const struct ng_cmdlist ng_gif_demux_cmdlist[] = {
142	{ 0 }
143};
144
145/* Node type descriptor */
146static struct ng_type ng_gif_demux_typestruct = {
147	.version =	NG_ABI_VERSION,
148	.name =		NG_GIF_DEMUX_NODE_TYPE,
149	.constructor =	ng_gif_demux_constructor,
150	.rcvmsg =	ng_gif_demux_rcvmsg,
151	.shutdown =	ng_gif_demux_shutdown,
152	.newhook =	ng_gif_demux_newhook,
153	.rcvdata =	ng_gif_demux_rcvdata,
154	.disconnect =	ng_gif_demux_disconnect,
155	.cmdlist =	ng_gif_demux_cmdlist,
156};
157NETGRAPH_INIT(gif_demux, &ng_gif_demux_typestruct);
158
159/************************************************************************
160		    HELPER STUFF
161 ************************************************************************/
162
163/*
164 * Get the family descriptor from the family ID
165 */
166static __inline__ iffam_p
167get_iffam_from_af(sa_family_t family)
168{
169	iffam_p iffam;
170	int k;
171
172	for (k = 0; k < NUM_FAMILIES; k++) {
173		iffam = &gFamilies[k];
174		if (iffam->family == family)
175			return (iffam);
176	}
177	return (NULL);
178}
179
180/*
181 * Get the family descriptor from the hook
182 */
183static __inline__ iffam_p
184get_iffam_from_hook(priv_p priv, hook_p hook)
185{
186	int k;
187
188	for (k = 0; k < NUM_FAMILIES; k++)
189		if (priv->hooks[k] == hook)
190			return (&gFamilies[k]);
191	return (NULL);
192}
193
194/*
195 * Get the hook from the iffam descriptor
196 */
197
198static __inline__ hook_p *
199get_hook_from_iffam(priv_p priv, iffam_p iffam)
200{
201	return (&priv->hooks[iffam - gFamilies]);
202}
203
204/*
205 * Get the iffam descriptor from the name
206 */
207static __inline__ iffam_p
208get_iffam_from_name(const char *name)
209{
210	iffam_p iffam;
211	int k;
212
213	for (k = 0; k < NUM_FAMILIES; k++) {
214		iffam = &gFamilies[k];
215		if (!strcmp(iffam->hookname, name))
216			return (iffam);
217	}
218	return (NULL);
219}
220
221/******************************************************************
222		    NETGRAPH NODE METHODS
223******************************************************************/
224
225/*
226 * Node constructor
227 */
228static int
229ng_gif_demux_constructor(node_p node)
230{
231	priv_p priv;
232
233	/* Allocate and initialize private info */
234	MALLOC(priv, priv_p, sizeof(*priv), M_NETGRAPH_GIF_DEMUX,
235	    M_NOWAIT | M_ZERO);
236	if (priv == NULL)
237		return (ENOMEM);
238	priv->node = node;
239
240	NG_NODE_SET_PRIVATE(node, priv);
241
242	/* Done */
243	return (0);
244}
245
246/*
247 * Method for attaching a new hook
248 */
249static	int
250ng_gif_demux_newhook(node_p node, hook_p hook, const char *name)
251{
252	const priv_p priv = NG_NODE_PRIVATE(node);
253	iffam_p iffam;
254	hook_p *hookptr;
255
256	if (strcmp(NG_GIF_DEMUX_HOOK_GIF, name) == 0)
257		hookptr = &priv->gif;
258	else {
259		iffam = get_iffam_from_name(name);
260		if (iffam == NULL)
261			return (EPFNOSUPPORT);
262		hookptr = get_hook_from_iffam(NG_NODE_PRIVATE(node), iffam);
263	}
264	if (*hookptr != NULL)
265		return (EISCONN);
266	*hookptr = hook;
267	return (0);
268}
269
270/*
271 * Receive a control message
272 */
273static int
274ng_gif_demux_rcvmsg(node_p node, item_p item, hook_p lasthook)
275{
276	struct ng_mesg *resp = NULL;
277	int error = 0;
278	struct ng_mesg *msg;
279
280	NGI_GET_MSG(item, msg);
281	switch (msg->header.typecookie) {
282	case NGM_GIF_DEMUX_COOKIE:
283		switch (msg->header.cmd) {
284		/* XXX: Add commands here. */
285		default:
286			error = EINVAL;
287			break;
288		}
289		break;
290	default:
291		error = EINVAL;
292		break;
293	}
294
295	/* Done */
296	NG_RESPOND_MSG(error, node, item, resp);
297	NG_FREE_MSG(msg);
298	return (error);
299}
300
301/*
302 * Receive data on a hook
303 */
304static int
305ng_gif_demux_rcvdata(hook_p hook, item_p item)
306{
307	const node_p node = NG_HOOK_NODE(hook);
308	const priv_p priv = NG_NODE_PRIVATE(node);
309	iffam_p iffam;
310	hook_p outhook;
311	int error = 0;
312	struct mbuf *m;
313
314	/* Pull the mbuf out of the item for processing. */
315	NGI_GET_M(item, m);
316
317	if (hook == priv->gif) {
318		/*
319		 * Pull off the address family header and find the
320		 * output hook.
321		 */
322		if (m->m_pkthdr.len < sizeof(sa_family_t)) {
323			NG_FREE_M(m);
324			NG_FREE_ITEM(item);
325			return (EINVAL);
326		}
327		if (m->m_len < sizeof(sa_family_t)
328		    && (m = m_pullup(m, sizeof(sa_family_t))) == NULL) {
329			NG_FREE_ITEM(item);
330			return (ENOBUFS);
331		}
332		iffam = get_iffam_from_af(*mtod(m, sa_family_t *));
333		if (iffam == NULL) {
334			NG_FREE_M(m);
335			NG_FREE_ITEM(item);
336			return (EINVAL);
337		}
338		outhook = *get_hook_from_iffam(priv, iffam);
339		m_adj(m, sizeof(sa_family_t));
340	} else {
341		/*
342		 * Add address family header and set the output hook.
343		 */
344		iffam = get_iffam_from_hook(priv, hook);
345		M_PREPEND(m, sizeof (iffam->family), M_DONTWAIT);
346		if (m == NULL) {
347			NG_FREE_M(m);
348			NG_FREE_ITEM(item);
349			return (ENOBUFS);
350		}
351		bcopy(&iffam->family, mtod(m, sa_family_t *),
352		    sizeof(iffam->family));
353		outhook = priv->gif;
354	}
355
356	/* Stuff the mbuf back in. */
357	NGI_M(item) = m;
358
359	/* Deliver packet */
360	NG_FWD_ITEM_HOOK(error, item, outhook);
361	return (error);
362}
363
364/*
365 * Shutdown node
366 */
367static int
368ng_gif_demux_shutdown(node_p node)
369{
370	const priv_p priv = NG_NODE_PRIVATE(node);
371
372	FREE(priv, M_NETGRAPH_GIF_DEMUX);
373	NG_NODE_SET_PRIVATE(node, NULL);
374	NG_NODE_UNREF(node);
375	return (0);
376}
377
378/*
379 * Hook disconnection.
380 */
381static int
382ng_gif_demux_disconnect(hook_p hook)
383{
384	const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
385	iffam_p iffam;
386
387	if (hook == priv->gif)
388		priv->gif = NULL;
389	else {
390		iffam = get_iffam_from_hook(priv, hook);
391		if (iffam == NULL)
392			panic(__func__);
393		*get_hook_from_iffam(priv, iffam) = NULL;
394	}
395
396	return (0);
397}
398