ng_gif.c revision 129823
1112694Stegge/*
2112694Stegge * ng_gif.c
3112694Stegge *
4112694Stegge * Copyright 2001 The Aerospace Corporation.  All rights reserved.
5112694Stegge *
6112694Stegge * Redistribution and use in source and binary forms, with or without
7112694Stegge * modification, are permitted provided that the following conditions
8112694Stegge * are met:
9112694Stegge *
10112694Stegge * 1. Redistributions of source code must retain the above copyright
11112694Stegge *    notice, this list of conditions, and the following disclaimer.
12112694Stegge * 2. Redistributions in binary form must reproduce the above copyright
13112694Stegge *    notice, this list of conditions, and the following disclaimer in the
14112694Stegge *    documentation and/or other materials provided with the distribution.
15112694Stegge * 3. The name of The Aerospace Corporation may not be used to endorse or
16112694Stegge *    promote products derived from this software.
17112694Stegge *
18112694Stegge * THIS SOFTWARE IS PROVIDED BY THE AEROSPACE CORPORATION ``AS IS'' AND
19112694Stegge * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20112694Stegge * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21112694Stegge * ARE DISCLAIMED.  IN NO EVENT SHALL THE AEROSPACE CORPORATION BE LIABLE
22112694Stegge * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23112694Stegge * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24112694Stegge * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25112694Stegge * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26112694Stegge * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27116192Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28116192Sobrien * SUCH DAMAGE.
29116192Sobrien *
30112694Stegge *
31112694Stegge * Copyright (c) 1996-2000 Whistle Communications, Inc.
32112694Stegge * All rights reserved.
33112694Stegge *
34112694Stegge * Subject to the following obligations and disclaimer of warranty, use and
35112694Stegge * redistribution of this software, in source or object code forms, with or
36114216Skan * without modifications are expressly permitted by Whistle Communications;
37112694Stegge * provided, however, that:
38112694Stegge * 1. Any and all reproductions of the source or object code must include the
39112694Stegge *    copyright notice above and the following disclaimer of warranties; and
40112694Stegge * 2. No rights are granted, in any manner or form, to use Whistle
41112694Stegge *    Communications, Inc. trademarks, including the mark "WHISTLE
42112694Stegge *    COMMUNICATIONS" on advertising, endorsements, or otherwise except as
43112694Stegge *    such appears in the above copyright notice or in the software.
44112694Stegge *
45118986Salc * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
46112694Stegge * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
47112694Stegge * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
48118986Salc * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
49119088Salc * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
50112694Stegge * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
51112694Stegge * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
52112694Stegge * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
53112694Stegge * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
54112694Stegge * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
55112694Stegge * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
56112694Stegge * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
57112694Stegge * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
58112694Stegge * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
59112694Stegge * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
60112694Stegge * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
61112694Stegge * OF SUCH DAMAGE.
62112694Stegge *
63112694Stegge * $FreeBSD: head/sys/netgraph/ng_gif.c 129823 2004-05-29 00:51:19Z julian $
64112694Stegge */
65112694Stegge
66112694Stegge/*
67112694Stegge * ng_gif(4) netgraph node type
68112694Stegge */
69112694Stegge
70112694Stegge#include <sys/param.h>
71112694Stegge#include <sys/systm.h>
72112694Stegge#include <sys/kernel.h>
73112694Stegge#include <sys/malloc.h>
74112694Stegge#include <sys/mbuf.h>
75112694Stegge#include <sys/errno.h>
76112694Stegge#include <sys/syslog.h>
77112694Stegge#include <sys/socket.h>
78112694Stegge
79112694Stegge#include <net/if.h>
80112694Stegge#include <net/route.h>
81112694Stegge#include <net/if_types.h>
82112694Stegge#include <net/if_var.h>
83112694Stegge#include <net/if_gif.h>
84112694Stegge
85112694Stegge#include <netgraph/ng_message.h>
86112694Stegge#include <netgraph/netgraph.h>
87112694Stegge#include <netgraph/ng_parse.h>
88112694Stegge#include <netgraph/ng_gif.h>
89112694Stegge
90112694Stegge#define IFP2NG(ifp)  ((struct ng_node *)((struct gif_softc *)(ifp))->gif_netgraph)
91112694Stegge
92112694Stegge/* Per-node private data */
93112694Steggestruct private {
94112694Stegge	struct ifnet	*ifp;		/* associated interface */
95112694Stegge	hook_p		lower;		/* lower OR orphan hook connection */
96112694Stegge	u_char		lowerOrphan;	/* whether lower is lower or orphan */
97112694Stegge};
98112694Steggetypedef struct private *priv_p;
99112694Stegge
100112694Stegge/* Functional hooks called from if_gif.c */
101112694Steggestatic void	ng_gif_input(struct ifnet *ifp, struct mbuf **mp, int af);
102112694Steggestatic void	ng_gif_input_orphan(struct ifnet *ifp, struct mbuf *m, int af);
103112694Steggestatic void	ng_gif_attach(struct ifnet *ifp);
104112694Steggestatic void	ng_gif_detach(struct ifnet *ifp);
105136943Sphk
106112694Stegge/* Other functions */
107112694Steggestatic void	ng_gif_input2(node_p node, struct mbuf **mp, int af);
108112694Steggestatic int	ng_gif_glue_af(struct mbuf **mp, int af);
109112694Steggestatic int	ng_gif_rcv_lower(node_p node, struct mbuf *m, meta_p meta);
110112694Stegge
111136943Sphk/* Netgraph node methods */
112136943Sphkstatic ng_constructor_t	ng_gif_constructor;
113136968Sphkstatic ng_rcvmsg_t	ng_gif_rcvmsg;
114112694Steggestatic ng_shutdown_t	ng_gif_shutdown;
115112694Steggestatic ng_newhook_t	ng_gif_newhook;
116112694Steggestatic ng_connect_t	ng_gif_connect;
117112694Steggestatic ng_rcvdata_t	ng_gif_rcvdata;
118112694Steggestatic ng_disconnect_t	ng_gif_disconnect;
119112694Steggestatic int		ng_gif_mod_event(module_t mod, int event, void *data);
120112694Stegge
121112694Stegge/* List of commands and how to convert arguments to/from ASCII */
122112694Steggestatic const struct ng_cmdlist ng_gif_cmdlist[] = {
123112694Stegge	{
124112694Stegge	  NGM_GIF_COOKIE,
125112694Stegge	  NGM_GIF_GET_IFNAME,
126112694Stegge	  "getifname",
127112694Stegge	  NULL,
128112694Stegge	  &ng_parse_string_type
129112694Stegge	},
130140782Sphk	{
131140782Sphk	  NGM_GIF_COOKIE,
132140782Sphk	  NGM_GIF_GET_IFINDEX,
133140782Sphk	  "getifindex",
134115145Salc	  NULL,
135112694Stegge	  &ng_parse_int32_type
136112694Stegge	},
137112694Stegge	{ 0 }
138112694Stegge};
139112694Stegge
140136943Sphkstatic struct ng_type ng_gif_typestruct = {
141136943Sphk	.version =	NG_ABI_VERSION,
142136943Sphk	.name =		NG_GIF_NODE_TYPE,
143136943Sphk	.mod_event =	ng_gif_mod_event,
144136943Sphk	.constructor =	ng_gif_constructor,
145136943Sphk	.rcvmsg =	ng_gif_rcvmsg,
146136943Sphk	.shutdown =	ng_gif_shutdown,
147136943Sphk	.newhook =	ng_gif_newhook,
148112694Stegge	.connect =	ng_gif_connect,
149112694Stegge	.rcvdata =	ng_gif_rcvdata,
150136968Sphk	.disconnect =	ng_gif_disconnect,
151112694Stegge	.cmdlist =	ng_gif_cmdlist,
152112694Stegge};
153140048SphkMODULE_VERSION(ng_gif, 1);
154112694SteggeMODULE_DEPEND(ng_gif, if_gif, 1,1,1);
155112694SteggeNETGRAPH_INIT(gif, &ng_gif_typestruct);
156112694Stegge
157112694Stegge/******************************************************************
158112694Stegge		       GIF FUNCTION HOOKS
159112694Stegge******************************************************************/
160136968Sphk
161112694Stegge/*
162112694Stegge * Handle a packet that has come in on an interface. We get to
163112694Stegge * look at it here before any upper layer protocols do.
164112694Stegge *
165112694Stegge * NOTE: this function will get called at splimp()
166112694Stegge */
167112694Steggestatic void
168112694Steggeng_gif_input(struct ifnet *ifp, struct mbuf **mp, int af)
169112694Stegge{
170112694Stegge	const node_p node = IFP2NG(ifp);
171112694Stegge	const priv_p priv = NG_NODE_PRIVATE(node);
172112694Stegge
173112694Stegge	/* If "lower" hook not connected, let packet continue */
174112694Stegge	if (priv->lower == NULL || priv->lowerOrphan)
175112694Stegge		return;
176112694Stegge	ng_gif_input2(node, mp, af);
177112694Stegge}
178112694Stegge
179112694Stegge/*
180112694Stegge * Handle a packet that has come in on an interface, and which
181112694Stegge * does not match any of our known protocols (an ``orphan'').
182112694Stegge *
183112694Stegge * NOTE: this function will get called at splimp()
184112694Stegge */
185112694Steggestatic void
186112694Steggeng_gif_input_orphan(struct ifnet *ifp, struct mbuf *m, int af)
187112694Stegge{
188112694Stegge	const node_p node = IFP2NG(ifp);
189112694Stegge	const priv_p priv = NG_NODE_PRIVATE(node);
190112694Stegge
191119049Sphk	/* If "orphan" hook not connected, let packet continue */
192119049Sphk	if (priv->lower == NULL || !priv->lowerOrphan) {
193112694Stegge		m_freem(m);
194112694Stegge		return;
195112694Stegge	}
196112694Stegge	ng_gif_input2(node, &m, af);
197119049Sphk	if (m != NULL)
198119049Sphk		m_freem(m);
199119049Sphk}
200112694Stegge
201112694Stegge/*
202112694Stegge * Handle a packet that has come in on a gif interface.
203112694Stegge * Attach the address family to the mbuf for later use.
204112694Stegge *
205112694Stegge * NOTE: this function will get called at splimp()
206112694Stegge */
207122747Sphkstatic void
208112694Steggeng_gif_input2(node_p node, struct mbuf **mp, int af)
209112694Stegge{
210112694Stegge	const priv_p priv = NG_NODE_PRIVATE(node);
211112694Stegge	int error;
212121354Stegge
213121354Stegge	/* Glue address family on */
214112694Stegge	if ((error = ng_gif_glue_af(mp, af)) != 0)
215112694Stegge		return;
216112694Stegge
217112694Stegge	/* Send out lower/orphan hook */
218112694Stegge	NG_SEND_DATA_ONLY(error, priv->lower, *mp);
219112694Stegge	*mp = NULL;
220119049Sphk}
221119049Sphk
222112694Stegge/*
223121354Stegge * A new gif interface has been attached.
224112694Stegge * Create a new node for it, etc.
225112694Stegge */
226112694Steggestatic void
227112694Steggeng_gif_attach(struct ifnet *ifp)
228112694Stegge{
229112694Stegge	priv_p priv;
230112694Stegge	node_p node;
231112694Stegge
232112694Stegge	/* Create node */
233112694Stegge	KASSERT(!IFP2NG(ifp), ("%s: node already exists?", __func__));
234112694Stegge	if (ng_make_node_common(&ng_gif_typestruct, &node) != 0) {
235112694Stegge		log(LOG_ERR, "%s: can't %s for %s\n",
236112694Stegge		    __func__, "create node", ifp->if_xname);
237112694Stegge		return;
238112694Stegge	}
239112694Stegge
240112694Stegge	/* Allocate private data */
241112694Stegge	MALLOC(priv, priv_p, sizeof(*priv), M_NETGRAPH, M_NOWAIT | M_ZERO);
242112694Stegge	if (priv == NULL) {
243112694Stegge		log(LOG_ERR, "%s: can't %s for %s\n",
244121354Stegge		    __func__, "allocate memory", ifp->if_xname);
245121354Stegge		NG_NODE_UNREF(node);
246112694Stegge		return;
247112694Stegge	}
248112694Stegge	NG_NODE_SET_PRIVATE(node, priv);
249112694Stegge	priv->ifp = ifp;
250112694Stegge	IFP2NG(ifp) = node;
251112724Stegge
252112694Stegge	/* Try to give the node the same name as the interface */
253112694Stegge	if (ng_name_node(node, ifp->if_xname) != 0) {
254140051Sphk		log(LOG_WARNING, "%s: can't name node %s\n",
255112694Stegge		    __func__, ifp->if_xname);
256112694Stegge	}
257112694Stegge}
258112694Stegge
259112694Stegge/*
260112694Stegge * An interface is being detached.
261112694Stegge * REALLY Destroy its node.
262112694Stegge */
263112694Steggestatic void
264112694Steggeng_gif_detach(struct ifnet *ifp)
265112694Stegge{
266112694Stegge	const node_p node = IFP2NG(ifp);
267112694Stegge	priv_p priv;
268112694Stegge
269112694Stegge	if (node == NULL)		/* no node (why not?), ignore */
270112694Stegge		return;
271112694Stegge	priv = NG_NODE_PRIVATE(node);
272112694Stegge	NG_NODE_REALLY_DIE(node);	/* Force real removal of node */
273112694Stegge	/*
274112694Stegge	 * We can't assume the ifnet is still around when we run shutdown
275112694Stegge	 * So zap it now. XXX We HOPE that anything running at this time
276112694Stegge	 * handles it (as it should in the non netgraph case).
277112694Stegge	 */
278112694Stegge	IFP2NG(ifp) = NULL;
279112694Stegge	priv->ifp = NULL;	/* XXX race if interrupted an output packet */
280112694Stegge	ng_rmnode_self(node);		/* remove all netgraph parts */
281112694Stegge}
282112694Stegge
283112694Stegge/*
284112694Stegge * Optimization for gluing the address family onto
285112694Stegge * the front of an incoming packet.
286112694Stegge */
287112694Steggestatic int
288112694Steggeng_gif_glue_af(struct mbuf **mp, int af)
289112694Stegge{
290112694Stegge	struct mbuf *m = *mp;
291112694Stegge	int error = 0;
292112694Stegge	sa_family_t tmp_af;
293112694Stegge
294112694Stegge	tmp_af = (sa_family_t) af;
295112694Stegge
296112694Stegge	/*
297112694Stegge	 * XXX: should try to bring back some of the optimizations from
298112694Stegge	 * ng_ether.c
299112694Stegge	 */
300112694Stegge
301112694Stegge	/*
302112694Stegge	 * Doing anything more is likely to get more
303112694Stegge	 * expensive than it's worth..
304112694Stegge	 * it's probable that everything else is in one
305112694Stegge	 * big lump. The next node will do an m_pullup()
306112694Stegge	 * for exactly the amount of data it needs and
307112694Stegge	 * hopefully everything after that will not
308112694Stegge	 * need one. So let's just use M_PREPEND.
309112694Stegge	 */
310112694Stegge	M_PREPEND(m, sizeof (tmp_af), M_DONTWAIT);
311112694Stegge	if (m == NULL) {
312112694Stegge		error = ENOBUFS;
313112694Stegge		goto done;
314112694Stegge	}
315112694Stegge
316112694Stegge#if 0
317112694Steggecopy:
318112694Stegge#endif
319112694Stegge	/* Copy header and return (possibly new) mbuf */
320112694Stegge	*mtod(m, sa_family_t *) = tmp_af;
321112694Stegge#if 0
322112694Stegge	bcopy((caddr_t)&tmp_af, mtod(m, sa_family_t *), sizeof(tmp_af));
323112694Stegge#endif
324112694Steggedone:
325112694Stegge	*mp = m;
326112694Stegge	return error;
327112694Stegge}
328112694Stegge
329112694Stegge/******************************************************************
330112694Stegge		    NETGRAPH NODE METHODS
331112694Stegge******************************************************************/
332112694Stegge
333112718Stegge/*
334112694Stegge * It is not possible or allowable to create a node of this type.
335112694Stegge * Nodes get created when the interface is attached (or, when
336112694Stegge * this node type's KLD is loaded).
337112694Stegge */
338112694Steggestatic int
339112694Steggeng_gif_constructor(node_p node)
340112694Stegge{
341112694Stegge	return (EINVAL);
342112694Stegge}
343112694Stegge
344112694Stegge/*
345112694Stegge * Check for attaching a new hook.
346112694Stegge */
347112694Steggestatic	int
348112694Steggeng_gif_newhook(node_p node, hook_p hook, const char *name)
349112694Stegge{
350112694Stegge	const priv_p priv = NG_NODE_PRIVATE(node);
351112694Stegge	u_char orphan = priv->lowerOrphan;
352112694Stegge	hook_p *hookptr;
353112694Stegge
354112694Stegge	/* Divert hook is an alias for lower */
355112694Stegge	if (strcmp(name, NG_GIF_HOOK_DIVERT) == 0)
356112694Stegge		name = NG_GIF_HOOK_LOWER;
357112694Stegge
358112694Stegge	/* Which hook? */
359112694Stegge	if (strcmp(name, NG_GIF_HOOK_LOWER) == 0) {
360112694Stegge		hookptr = &priv->lower;
361112694Stegge		orphan = 0;
362112694Stegge	} else if (strcmp(name, NG_GIF_HOOK_ORPHAN) == 0) {
363112694Stegge		hookptr = &priv->lower;
364112694Stegge		orphan = 1;
365112694Stegge	} else
366112694Stegge		return (EINVAL);
367112694Stegge
368112694Stegge	/* Check if already connected (shouldn't be, but doesn't hurt) */
369112694Stegge	if (*hookptr != NULL)
370112694Stegge		return (EISCONN);
371112694Stegge
372112694Stegge	/* OK */
373112694Stegge	*hookptr = hook;
374112694Stegge	priv->lowerOrphan = orphan;
375112694Stegge	return (0);
376112694Stegge}
377112694Stegge
378112694Stegge/*
379112694Stegge * Hooks are attached, adjust to force queueing.
380112694Stegge * We don't really care which hook it is.
381112694Stegge * they should all be queuing for outgoing data.
382112694Stegge */
383112694Steggestatic	int
384112694Steggeng_gif_connect(hook_p hook)
385112694Stegge{
386112694Stegge	NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook));
387112694Stegge	return (0);
388112694Stegge}
389112694Stegge
390112694Stegge/*
391112694Stegge * Receive an incoming control message.
392112694Stegge */
393112694Steggestatic int
394112694Steggeng_gif_rcvmsg(node_p node, item_p item, hook_p lasthook)
395112694Stegge{
396112694Stegge	const priv_p priv = NG_NODE_PRIVATE(node);
397112694Stegge	struct ng_mesg *resp = NULL;
398112694Stegge	int error = 0;
399112694Stegge	struct ng_mesg *msg;
400112694Stegge
401112694Stegge	NGI_GET_MSG(item, msg);
402112694Stegge	switch (msg->header.typecookie) {
403112694Stegge	case NGM_GIF_COOKIE:
404112694Stegge		switch (msg->header.cmd) {
405112718Stegge		case NGM_GIF_GET_IFNAME:
406112694Stegge			NG_MKRESPONSE(resp, msg, IFNAMSIZ + 1, M_NOWAIT);
407112694Stegge			if (resp == NULL) {
408112694Stegge				error = ENOMEM;
409112694Stegge				break;
410112694Stegge			}
411112694Stegge			strlcpy(resp->data, priv->ifp->if_xname, IFNAMSIZ + 1);
412112694Stegge			break;
413112694Stegge		case NGM_GIF_GET_IFINDEX:
414112694Stegge			NG_MKRESPONSE(resp, msg, sizeof(u_int32_t), M_NOWAIT);
415112694Stegge			if (resp == NULL) {
416112694Stegge				error = ENOMEM;
417112694Stegge				break;
418112694Stegge			}
419112694Stegge			*((u_int32_t *)resp->data) = priv->ifp->if_index;
420112694Stegge			break;
421112694Stegge		default:
422112694Stegge			error = EINVAL;
423112694Stegge			break;
424112694Stegge		}
425112694Stegge		break;
426112694Stegge	default:
427112694Stegge		error = EINVAL;
428112694Stegge		break;
429112694Stegge	}
430130023Stjr	NG_RESPOND_MSG(error, node, item, resp);
431130023Stjr	NG_FREE_MSG(msg);
432112694Stegge	return (error);
433112694Stegge}
434112694Stegge
435112694Stegge/*
436112694Stegge * Receive data on a hook.
437112694Stegge */
438112694Steggestatic int
439112694Steggeng_gif_rcvdata(hook_p hook, item_p item)
440112694Stegge{
441112694Stegge	const node_p node = NG_HOOK_NODE(hook);
442112694Stegge	const priv_p priv = NG_NODE_PRIVATE(node);
443136966Sphk	struct mbuf *m;
444112694Stegge	meta_p meta;
445112694Stegge
446112694Stegge	NGI_GET_M(item, m);
447112694Stegge	NGI_GET_META(item, meta);
448112694Stegge	NG_FREE_ITEM(item);
449112694Stegge	if (hook == priv->lower)
450112694Stegge		return ng_gif_rcv_lower(node, m, meta);
451112694Stegge	panic("%s: weird hook", __func__);
452112694Stegge}
453112694Stegge
454112694Stegge/*
455112694Stegge * Handle an mbuf received on the "lower" hook.
456112694Stegge */
457112694Steggestatic int
458112694Steggeng_gif_rcv_lower(node_p node, struct mbuf *m, meta_p meta)
459112694Stegge{
460112694Stegge	struct sockaddr	dst;
461112694Stegge	const priv_p priv = NG_NODE_PRIVATE(node);
462112694Stegge
463112694Stegge	bzero(&dst, sizeof(dst));
464112694Stegge
465112694Stegge	/* We don't process metadata. */
466112694Stegge	NG_FREE_META(meta);
467112694Stegge
468112694Stegge	/* Make sure header is fully pulled up */
469112694Stegge	if (m->m_pkthdr.len < sizeof(sa_family_t)) {
470112694Stegge		NG_FREE_M(m);
471112694Stegge		return (EINVAL);
472112694Stegge	}
473112694Stegge	if (m->m_len < sizeof(sa_family_t)
474112694Stegge	    && (m = m_pullup(m, sizeof(sa_family_t))) == NULL) {
475112694Stegge		return (ENOBUFS);
476112694Stegge	}
477112694Stegge
478112694Stegge	dst.sa_family = *mtod(m, sa_family_t *);
479112694Stegge	m_adj(m, sizeof(sa_family_t));
480112694Stegge
481112694Stegge	/* Send it on its way */
482112694Stegge	/*
483112694Stegge	 * XXX: gif_output only uses dst for the family and passes the
484112694Stegge	 * fourth argument (rt) to in{,6}_gif_output which ignore it.
485112694Stegge	 * If this changes ng_gif will probably break.
486112694Stegge	 */
487112694Stegge	return gif_output(priv->ifp, m, &dst, NULL);
488112718Stegge}
489112694Stegge
490/*
491 * Shutdown node. This resets the node but does not remove it
492 * unless the REALLY_DIE flag is set.
493 */
494static int
495ng_gif_shutdown(node_p node)
496{
497	const priv_p priv = NG_NODE_PRIVATE(node);
498
499	if (node->nd_flags & NG_REALLY_DIE) {
500		/*
501		 * WE came here because the gif interface is being destroyed,
502		 * so stop being persistant.
503		 * Actually undo all the things we did on creation.
504		 * Assume the ifp has already been freed.
505		 */
506		NG_NODE_SET_PRIVATE(node, NULL);
507		FREE(priv, M_NETGRAPH);
508		NG_NODE_UNREF(node);	/* free node itself */
509		return (0);
510	}
511	node->nd_flags &= ~NG_INVALID;	/* Signal ng_rmnode we are persisant */
512	return (0);
513}
514
515/*
516 * Hook disconnection.
517 */
518static int
519ng_gif_disconnect(hook_p hook)
520{
521	const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
522
523	if (hook == priv->lower) {
524		priv->lower = NULL;
525		priv->lowerOrphan = 0;
526	} else
527		panic("%s: weird hook", __func__);
528	if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0)
529	    && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook))))
530		ng_rmnode_self(NG_HOOK_NODE(hook));	/* reset node */
531
532	return (0);
533}
534
535/******************************************************************
536		    	INITIALIZATION
537******************************************************************/
538
539/*
540 * Handle loading and unloading for this node type.
541 */
542static int
543ng_gif_mod_event(module_t mod, int event, void *data)
544{
545	struct ifnet *ifp;
546	int error = 0;
547	int s;
548
549	s = splnet();
550	switch (event) {
551	case MOD_LOAD:
552
553		/* Register function hooks */
554		if (ng_gif_attach_p != NULL) {
555			error = EEXIST;
556			break;
557		}
558		ng_gif_attach_p = ng_gif_attach;
559		ng_gif_detach_p = ng_gif_detach;
560		ng_gif_input_p = ng_gif_input;
561		ng_gif_input_orphan_p = ng_gif_input_orphan;
562
563		/* Create nodes for any already-existing gif interfaces */
564		IFNET_RLOCK();
565		TAILQ_FOREACH(ifp, &ifnet, if_link) {
566			if (ifp->if_type == IFT_GIF)
567				ng_gif_attach(ifp);
568		}
569		IFNET_RUNLOCK();
570		break;
571
572	case MOD_UNLOAD:
573
574		/*
575		 * Note that the base code won't try to unload us until
576		 * all nodes have been removed, and that can't happen
577		 * until all gif interfaces are destroyed. In any
578		 * case, we know there are no nodes left if the action
579		 * is MOD_UNLOAD, so there's no need to detach any nodes.
580		 *
581		 * XXX: what about manual unloads?!?
582		 */
583
584		/* Unregister function hooks */
585		ng_gif_attach_p = NULL;
586		ng_gif_detach_p = NULL;
587		ng_gif_input_p = NULL;
588		ng_gif_input_orphan_p = NULL;
589		break;
590
591	default:
592		error = EOPNOTSUPP;
593		break;
594	}
595	splx(s);
596	return (error);
597}
598
599