ng_gif.c revision 129823
183998Sbrooks/* 283998Sbrooks * ng_gif.c 383998Sbrooks * 483998Sbrooks * Copyright 2001 The Aerospace Corporation. All rights reserved. 583998Sbrooks * 683998Sbrooks * Redistribution and use in source and binary forms, with or without 783998Sbrooks * modification, are permitted provided that the following conditions 883998Sbrooks * are met: 984000Sbrooks * 1083998Sbrooks * 1. Redistributions of source code must retain the above copyright 1184000Sbrooks * notice, this list of conditions, and the following disclaimer. 1283998Sbrooks * 2. Redistributions in binary form must reproduce the above copyright 1384000Sbrooks * notice, this list of conditions, and the following disclaimer in the 1483998Sbrooks * documentation and/or other materials provided with the distribution. 1584000Sbrooks * 3. The name of The Aerospace Corporation may not be used to endorse or 1684000Sbrooks * promote products derived from this software. 1783998Sbrooks * 1883998Sbrooks * THIS SOFTWARE IS PROVIDED BY THE AEROSPACE CORPORATION ``AS IS'' AND 1983998Sbrooks * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2083998Sbrooks * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2183998Sbrooks * ARE DISCLAIMED. IN NO EVENT SHALL THE AEROSPACE CORPORATION BE LIABLE 2283998Sbrooks * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2383998Sbrooks * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2483998Sbrooks * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2583998Sbrooks * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2683998Sbrooks * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2783998Sbrooks * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2883998Sbrooks * SUCH DAMAGE. 2983998Sbrooks * 3083998Sbrooks * 3183998Sbrooks * Copyright (c) 1996-2000 Whistle Communications, Inc. 3283998Sbrooks * All rights reserved. 3383998Sbrooks * 3483998Sbrooks * Subject to the following obligations and disclaimer of warranty, use and 3583998Sbrooks * redistribution of this software, in source or object code forms, with or 3683998Sbrooks * without modifications are expressly permitted by Whistle Communications; 3783998Sbrooks * provided, however, that: 3883998Sbrooks * 1. Any and all reproductions of the source or object code must include the 3983998Sbrooks * copyright notice above and the following disclaimer of warranties; and 4083998Sbrooks * 2. No rights are granted, in any manner or form, to use Whistle 4183998Sbrooks * Communications, Inc. trademarks, including the mark "WHISTLE 4283998Sbrooks * COMMUNICATIONS" on advertising, endorsements, or otherwise except as 4383998Sbrooks * such appears in the above copyright notice or in the software. 4483998Sbrooks * 4583998Sbrooks * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND 4683998Sbrooks * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO 4783998Sbrooks * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, 4883998Sbrooks * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF 4983998Sbrooks * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 5083998Sbrooks * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY 5183998Sbrooks * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS 5283998Sbrooks * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. 5383998Sbrooks * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES 5483998Sbrooks * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING 5583998Sbrooks * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 5683998Sbrooks * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR 5783998Sbrooks * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY 5883998Sbrooks * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 5983998Sbrooks * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 6083998Sbrooks * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY 6183998Sbrooks * OF SUCH DAMAGE. 6283998Sbrooks * 6383998Sbrooks * $FreeBSD: head/sys/netgraph/ng_gif.c 129823 2004-05-29 00:51:19Z julian $ 6483998Sbrooks */ 6583998Sbrooks 6683998Sbrooks/* 6783998Sbrooks * ng_gif(4) netgraph node type 6883998Sbrooks */ 6983998Sbrooks 7083998Sbrooks#include <sys/param.h> 7183998Sbrooks#include <sys/systm.h> 7283998Sbrooks#include <sys/kernel.h> 7383998Sbrooks#include <sys/malloc.h> 7483998Sbrooks#include <sys/mbuf.h> 7583998Sbrooks#include <sys/errno.h> 7683998Sbrooks#include <sys/syslog.h> 7783998Sbrooks#include <sys/socket.h> 7883998Sbrooks 7983998Sbrooks#include <net/if.h> 8083998Sbrooks#include <net/route.h> 8183998Sbrooks#include <net/if_types.h> 8283998Sbrooks#include <net/if_var.h> 8383998Sbrooks#include <net/if_gif.h> 8483998Sbrooks 8583998Sbrooks#include <netgraph/ng_message.h> 8683998Sbrooks#include <netgraph/netgraph.h> 8783998Sbrooks#include <netgraph/ng_parse.h> 8883998Sbrooks#include <netgraph/ng_gif.h> 8983998Sbrooks 9083998Sbrooks#define IFP2NG(ifp) ((struct ng_node *)((struct gif_softc *)(ifp))->gif_netgraph) 9183998Sbrooks 9283998Sbrooks/* Per-node private data */ 9383998Sbrooksstruct private { 9483998Sbrooks struct ifnet *ifp; /* associated interface */ 9583998Sbrooks hook_p lower; /* lower OR orphan hook connection */ 9683998Sbrooks u_char lowerOrphan; /* whether lower is lower or orphan */ 9783998Sbrooks}; 9883998Sbrookstypedef struct private *priv_p; 9983998Sbrooks 10083998Sbrooks/* Functional hooks called from if_gif.c */ 10183998Sbrooksstatic void ng_gif_input(struct ifnet *ifp, struct mbuf **mp, int af); 10283998Sbrooksstatic void ng_gif_input_orphan(struct ifnet *ifp, struct mbuf *m, int af); 10383998Sbrooksstatic void ng_gif_attach(struct ifnet *ifp); 10483998Sbrooksstatic void ng_gif_detach(struct ifnet *ifp); 10583998Sbrooks 10683998Sbrooks/* Other functions */ 10783998Sbrooksstatic void ng_gif_input2(node_p node, struct mbuf **mp, int af); 10883998Sbrooksstatic int ng_gif_glue_af(struct mbuf **mp, int af); 10983998Sbrooksstatic int ng_gif_rcv_lower(node_p node, struct mbuf *m, meta_p meta); 11083998Sbrooks 11183998Sbrooks/* Netgraph node methods */ 11283998Sbrooksstatic ng_constructor_t ng_gif_constructor; 11383998Sbrooksstatic ng_rcvmsg_t ng_gif_rcvmsg; 11483998Sbrooksstatic ng_shutdown_t ng_gif_shutdown; 11583998Sbrooksstatic ng_newhook_t ng_gif_newhook; 11683998Sbrooksstatic ng_connect_t ng_gif_connect; 11783998Sbrooksstatic ng_rcvdata_t ng_gif_rcvdata; 11883998Sbrooksstatic ng_disconnect_t ng_gif_disconnect; 11983998Sbrooksstatic int ng_gif_mod_event(module_t mod, int event, void *data); 12083998Sbrooks 12183998Sbrooks/* List of commands and how to convert arguments to/from ASCII */ 12283998Sbrooksstatic const struct ng_cmdlist ng_gif_cmdlist[] = { 12383998Sbrooks { 12483998Sbrooks NGM_GIF_COOKIE, 12583998Sbrooks NGM_GIF_GET_IFNAME, 12683998Sbrooks "getifname", 12783998Sbrooks NULL, 12883998Sbrooks &ng_parse_string_type 12983998Sbrooks }, 13083998Sbrooks { 13183998Sbrooks NGM_GIF_COOKIE, 13283998Sbrooks NGM_GIF_GET_IFINDEX, 13383998Sbrooks "getifindex", 13483998Sbrooks NULL, 13583998Sbrooks &ng_parse_int32_type 13683998Sbrooks }, 13783998Sbrooks { 0 } 13883998Sbrooks}; 13983998Sbrooks 14083998Sbrooksstatic struct ng_type ng_gif_typestruct = { 141129823Sjulian .version = NG_ABI_VERSION, 142129823Sjulian .name = NG_GIF_NODE_TYPE, 143129823Sjulian .mod_event = ng_gif_mod_event, 144129823Sjulian .constructor = ng_gif_constructor, 145129823Sjulian .rcvmsg = ng_gif_rcvmsg, 146129823Sjulian .shutdown = ng_gif_shutdown, 147129823Sjulian .newhook = ng_gif_newhook, 148129823Sjulian .connect = ng_gif_connect, 149129823Sjulian .rcvdata = ng_gif_rcvdata, 150129823Sjulian .disconnect = ng_gif_disconnect, 151129823Sjulian .cmdlist = ng_gif_cmdlist, 15283998Sbrooks}; 15383998SbrooksMODULE_VERSION(ng_gif, 1); 15483998SbrooksMODULE_DEPEND(ng_gif, if_gif, 1,1,1); 15583998SbrooksNETGRAPH_INIT(gif, &ng_gif_typestruct); 15683998Sbrooks 15783998Sbrooks/****************************************************************** 15883998Sbrooks GIF FUNCTION HOOKS 15983998Sbrooks******************************************************************/ 16083998Sbrooks 16183998Sbrooks/* 16283998Sbrooks * Handle a packet that has come in on an interface. We get to 16383998Sbrooks * look at it here before any upper layer protocols do. 16483998Sbrooks * 16583998Sbrooks * NOTE: this function will get called at splimp() 16683998Sbrooks */ 16783998Sbrooksstatic void 16883998Sbrooksng_gif_input(struct ifnet *ifp, struct mbuf **mp, int af) 16983998Sbrooks{ 17083998Sbrooks const node_p node = IFP2NG(ifp); 17183998Sbrooks const priv_p priv = NG_NODE_PRIVATE(node); 17283998Sbrooks 17383998Sbrooks /* If "lower" hook not connected, let packet continue */ 17483998Sbrooks if (priv->lower == NULL || priv->lowerOrphan) 17583998Sbrooks return; 17683998Sbrooks ng_gif_input2(node, mp, af); 17783998Sbrooks} 17883998Sbrooks 17983998Sbrooks/* 18083998Sbrooks * Handle a packet that has come in on an interface, and which 18183998Sbrooks * does not match any of our known protocols (an ``orphan''). 18283998Sbrooks * 18383998Sbrooks * NOTE: this function will get called at splimp() 18483998Sbrooks */ 18583998Sbrooksstatic void 18683998Sbrooksng_gif_input_orphan(struct ifnet *ifp, struct mbuf *m, int af) 18783998Sbrooks{ 18883998Sbrooks const node_p node = IFP2NG(ifp); 18983998Sbrooks const priv_p priv = NG_NODE_PRIVATE(node); 19083998Sbrooks 19183998Sbrooks /* If "orphan" hook not connected, let packet continue */ 19283998Sbrooks if (priv->lower == NULL || !priv->lowerOrphan) { 19383998Sbrooks m_freem(m); 19483998Sbrooks return; 19583998Sbrooks } 19683998Sbrooks ng_gif_input2(node, &m, af); 19783998Sbrooks if (m != NULL) 19883998Sbrooks m_freem(m); 19983998Sbrooks} 20083998Sbrooks 20183998Sbrooks/* 20283998Sbrooks * Handle a packet that has come in on a gif interface. 20383998Sbrooks * Attach the address family to the mbuf for later use. 20483998Sbrooks * 20583998Sbrooks * NOTE: this function will get called at splimp() 20683998Sbrooks */ 20783998Sbrooksstatic void 20883998Sbrooksng_gif_input2(node_p node, struct mbuf **mp, int af) 20983998Sbrooks{ 21083998Sbrooks const priv_p priv = NG_NODE_PRIVATE(node); 21183998Sbrooks int error; 21283998Sbrooks 21383998Sbrooks /* Glue address family on */ 21483998Sbrooks if ((error = ng_gif_glue_af(mp, af)) != 0) 21583998Sbrooks return; 21683998Sbrooks 21783998Sbrooks /* Send out lower/orphan hook */ 21883998Sbrooks NG_SEND_DATA_ONLY(error, priv->lower, *mp); 21983998Sbrooks *mp = NULL; 22083998Sbrooks} 22183998Sbrooks 22283998Sbrooks/* 22383998Sbrooks * A new gif interface has been attached. 22483998Sbrooks * Create a new node for it, etc. 22583998Sbrooks */ 22683998Sbrooksstatic void 22783998Sbrooksng_gif_attach(struct ifnet *ifp) 22883998Sbrooks{ 22983998Sbrooks priv_p priv; 23083998Sbrooks node_p node; 23183998Sbrooks 23283998Sbrooks /* Create node */ 23387599Sobrien KASSERT(!IFP2NG(ifp), ("%s: node already exists?", __func__)); 23483998Sbrooks if (ng_make_node_common(&ng_gif_typestruct, &node) != 0) { 23583998Sbrooks log(LOG_ERR, "%s: can't %s for %s\n", 236121816Sbrooks __func__, "create node", ifp->if_xname); 23783998Sbrooks return; 23883998Sbrooks } 23983998Sbrooks 24083998Sbrooks /* Allocate private data */ 24183998Sbrooks MALLOC(priv, priv_p, sizeof(*priv), M_NETGRAPH, M_NOWAIT | M_ZERO); 24283998Sbrooks if (priv == NULL) { 24383998Sbrooks log(LOG_ERR, "%s: can't %s for %s\n", 244121816Sbrooks __func__, "allocate memory", ifp->if_xname); 24583998Sbrooks NG_NODE_UNREF(node); 24683998Sbrooks return; 24783998Sbrooks } 24883998Sbrooks NG_NODE_SET_PRIVATE(node, priv); 24983998Sbrooks priv->ifp = ifp; 25083998Sbrooks IFP2NG(ifp) = node; 25183998Sbrooks 25283998Sbrooks /* Try to give the node the same name as the interface */ 253121816Sbrooks if (ng_name_node(node, ifp->if_xname) != 0) { 25483998Sbrooks log(LOG_WARNING, "%s: can't name node %s\n", 255121816Sbrooks __func__, ifp->if_xname); 25683998Sbrooks } 25783998Sbrooks} 25883998Sbrooks 25983998Sbrooks/* 26084060Sbrooks * An interface is being detached. 26183998Sbrooks * REALLY Destroy its node. 26283998Sbrooks */ 26383998Sbrooksstatic void 26483998Sbrooksng_gif_detach(struct ifnet *ifp) 26583998Sbrooks{ 26683998Sbrooks const node_p node = IFP2NG(ifp); 267126203Sphk priv_p priv; 26883998Sbrooks 26983998Sbrooks if (node == NULL) /* no node (why not?), ignore */ 27083998Sbrooks return; 271126196Scperciva priv = NG_NODE_PRIVATE(node); 27283998Sbrooks NG_NODE_REALLY_DIE(node); /* Force real removal of node */ 27383998Sbrooks /* 27483998Sbrooks * We can't assume the ifnet is still around when we run shutdown 27583998Sbrooks * So zap it now. XXX We HOPE that anything running at this time 27683998Sbrooks * handles it (as it should in the non netgraph case). 27783998Sbrooks */ 27883998Sbrooks IFP2NG(ifp) = NULL; 27983998Sbrooks priv->ifp = NULL; /* XXX race if interrupted an output packet */ 28083998Sbrooks ng_rmnode_self(node); /* remove all netgraph parts */ 28183998Sbrooks} 28283998Sbrooks 28383998Sbrooks/* 28484060Sbrooks * Optimization for gluing the address family onto 28583998Sbrooks * the front of an incoming packet. 28683998Sbrooks */ 28783998Sbrooksstatic int 28883998Sbrooksng_gif_glue_af(struct mbuf **mp, int af) 28983998Sbrooks{ 29083998Sbrooks struct mbuf *m = *mp; 29183998Sbrooks int error = 0; 29283998Sbrooks sa_family_t tmp_af; 29383998Sbrooks 29483998Sbrooks tmp_af = (sa_family_t) af; 29583998Sbrooks 29683998Sbrooks /* 29783998Sbrooks * XXX: should try to bring back some of the optimizations from 29883998Sbrooks * ng_ether.c 29983998Sbrooks */ 30083998Sbrooks 30183998Sbrooks /* 30283998Sbrooks * Doing anything more is likely to get more 30383998Sbrooks * expensive than it's worth.. 30483998Sbrooks * it's probable that everything else is in one 30583998Sbrooks * big lump. The next node will do an m_pullup() 30683998Sbrooks * for exactly the amount of data it needs and 30783998Sbrooks * hopefully everything after that will not 30883998Sbrooks * need one. So let's just use M_PREPEND. 30983998Sbrooks */ 310111119Simp M_PREPEND(m, sizeof (tmp_af), M_DONTWAIT); 31183998Sbrooks if (m == NULL) { 31283998Sbrooks error = ENOBUFS; 31383998Sbrooks goto done; 31483998Sbrooks } 31583998Sbrooks 31683998Sbrooks#if 0 31783998Sbrookscopy: 31883998Sbrooks#endif 31983998Sbrooks /* Copy header and return (possibly new) mbuf */ 32083998Sbrooks *mtod(m, sa_family_t *) = tmp_af; 32183998Sbrooks#if 0 32283998Sbrooks bcopy((caddr_t)&tmp_af, mtod(m, sa_family_t *), sizeof(tmp_af)); 32383998Sbrooks#endif 32483998Sbrooksdone: 32583998Sbrooks *mp = m; 32683998Sbrooks return error; 32783998Sbrooks} 32883998Sbrooks 32983998Sbrooks/****************************************************************** 33083998Sbrooks NETGRAPH NODE METHODS 33183998Sbrooks******************************************************************/ 33283998Sbrooks 33383998Sbrooks/* 33483998Sbrooks * It is not possible or allowable to create a node of this type. 33583998Sbrooks * Nodes get created when the interface is attached (or, when 33683998Sbrooks * this node type's KLD is loaded). 33783998Sbrooks */ 33883998Sbrooksstatic int 33983998Sbrooksng_gif_constructor(node_p node) 34083998Sbrooks{ 34183998Sbrooks return (EINVAL); 34283998Sbrooks} 34383998Sbrooks 34483998Sbrooks/* 34583998Sbrooks * Check for attaching a new hook. 34683998Sbrooks */ 34783998Sbrooksstatic int 34883998Sbrooksng_gif_newhook(node_p node, hook_p hook, const char *name) 34983998Sbrooks{ 35083998Sbrooks const priv_p priv = NG_NODE_PRIVATE(node); 35183998Sbrooks u_char orphan = priv->lowerOrphan; 35283998Sbrooks hook_p *hookptr; 35383998Sbrooks 35483998Sbrooks /* Divert hook is an alias for lower */ 35583998Sbrooks if (strcmp(name, NG_GIF_HOOK_DIVERT) == 0) 35683998Sbrooks name = NG_GIF_HOOK_LOWER; 35783998Sbrooks 35883998Sbrooks /* Which hook? */ 35983998Sbrooks if (strcmp(name, NG_GIF_HOOK_LOWER) == 0) { 36083998Sbrooks hookptr = &priv->lower; 36183998Sbrooks orphan = 0; 36283998Sbrooks } else if (strcmp(name, NG_GIF_HOOK_ORPHAN) == 0) { 36383998Sbrooks hookptr = &priv->lower; 36483998Sbrooks orphan = 1; 36583998Sbrooks } else 36683998Sbrooks return (EINVAL); 36783998Sbrooks 36883998Sbrooks /* Check if already connected (shouldn't be, but doesn't hurt) */ 36983998Sbrooks if (*hookptr != NULL) 37083998Sbrooks return (EISCONN); 37183998Sbrooks 37283998Sbrooks /* OK */ 37383998Sbrooks *hookptr = hook; 37483998Sbrooks priv->lowerOrphan = orphan; 37583998Sbrooks return (0); 37683998Sbrooks} 37783998Sbrooks 37883998Sbrooks/* 37983998Sbrooks * Hooks are attached, adjust to force queueing. 38083998Sbrooks * We don't really care which hook it is. 38183998Sbrooks * they should all be queuing for outgoing data. 38283998Sbrooks */ 38383998Sbrooksstatic int 38483998Sbrooksng_gif_connect(hook_p hook) 38583998Sbrooks{ 38683998Sbrooks NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook)); 38783998Sbrooks return (0); 38883998Sbrooks} 38983998Sbrooks 39083998Sbrooks/* 39183998Sbrooks * Receive an incoming control message. 39283998Sbrooks */ 39383998Sbrooksstatic int 39483998Sbrooksng_gif_rcvmsg(node_p node, item_p item, hook_p lasthook) 39583998Sbrooks{ 39683998Sbrooks const priv_p priv = NG_NODE_PRIVATE(node); 39783998Sbrooks struct ng_mesg *resp = NULL; 39883998Sbrooks int error = 0; 39983998Sbrooks struct ng_mesg *msg; 40083998Sbrooks 40183998Sbrooks NGI_GET_MSG(item, msg); 40283998Sbrooks switch (msg->header.typecookie) { 40383998Sbrooks case NGM_GIF_COOKIE: 40483998Sbrooks switch (msg->header.cmd) { 40583998Sbrooks case NGM_GIF_GET_IFNAME: 40683998Sbrooks NG_MKRESPONSE(resp, msg, IFNAMSIZ + 1, M_NOWAIT); 40783998Sbrooks if (resp == NULL) { 40883998Sbrooks error = ENOMEM; 40983998Sbrooks break; 41083998Sbrooks } 411121816Sbrooks strlcpy(resp->data, priv->ifp->if_xname, IFNAMSIZ + 1); 41283998Sbrooks break; 41383998Sbrooks case NGM_GIF_GET_IFINDEX: 41483998Sbrooks NG_MKRESPONSE(resp, msg, sizeof(u_int32_t), M_NOWAIT); 41583998Sbrooks if (resp == NULL) { 41683998Sbrooks error = ENOMEM; 41783998Sbrooks break; 41883998Sbrooks } 41983998Sbrooks *((u_int32_t *)resp->data) = priv->ifp->if_index; 42083998Sbrooks break; 42183998Sbrooks default: 42283998Sbrooks error = EINVAL; 42383998Sbrooks break; 42483998Sbrooks } 42583998Sbrooks break; 42683998Sbrooks default: 42783998Sbrooks error = EINVAL; 42883998Sbrooks break; 42983998Sbrooks } 43083998Sbrooks NG_RESPOND_MSG(error, node, item, resp); 43183998Sbrooks NG_FREE_MSG(msg); 43283998Sbrooks return (error); 43383998Sbrooks} 43483998Sbrooks 43583998Sbrooks/* 43683998Sbrooks * Receive data on a hook. 43783998Sbrooks */ 43883998Sbrooksstatic int 43983998Sbrooksng_gif_rcvdata(hook_p hook, item_p item) 44083998Sbrooks{ 44183998Sbrooks const node_p node = NG_HOOK_NODE(hook); 44283998Sbrooks const priv_p priv = NG_NODE_PRIVATE(node); 44383998Sbrooks struct mbuf *m; 44483998Sbrooks meta_p meta; 44583998Sbrooks 44683998Sbrooks NGI_GET_M(item, m); 44783998Sbrooks NGI_GET_META(item, meta); 44883998Sbrooks NG_FREE_ITEM(item); 44983998Sbrooks if (hook == priv->lower) 45083998Sbrooks return ng_gif_rcv_lower(node, m, meta); 45187599Sobrien panic("%s: weird hook", __func__); 45283998Sbrooks} 45383998Sbrooks 45483998Sbrooks/* 45583998Sbrooks * Handle an mbuf received on the "lower" hook. 45683998Sbrooks */ 45783998Sbrooksstatic int 45883998Sbrooksng_gif_rcv_lower(node_p node, struct mbuf *m, meta_p meta) 45983998Sbrooks{ 46083998Sbrooks struct sockaddr dst; 46183998Sbrooks const priv_p priv = NG_NODE_PRIVATE(node); 46283998Sbrooks 46383998Sbrooks bzero(&dst, sizeof(dst)); 46483998Sbrooks 46583998Sbrooks /* We don't process metadata. */ 46683998Sbrooks NG_FREE_META(meta); 46783998Sbrooks 46883998Sbrooks /* Make sure header is fully pulled up */ 46983998Sbrooks if (m->m_pkthdr.len < sizeof(sa_family_t)) { 47083998Sbrooks NG_FREE_M(m); 47183998Sbrooks return (EINVAL); 47283998Sbrooks } 47383998Sbrooks if (m->m_len < sizeof(sa_family_t) 47483998Sbrooks && (m = m_pullup(m, sizeof(sa_family_t))) == NULL) { 47583998Sbrooks return (ENOBUFS); 47683998Sbrooks } 47783998Sbrooks 47883998Sbrooks dst.sa_family = *mtod(m, sa_family_t *); 47983998Sbrooks m_adj(m, sizeof(sa_family_t)); 48083998Sbrooks 48183998Sbrooks /* Send it on its way */ 48283998Sbrooks /* 48383998Sbrooks * XXX: gif_output only uses dst for the family and passes the 48483998Sbrooks * fourth argument (rt) to in{,6}_gif_output which ignore it. 48583998Sbrooks * If this changes ng_gif will probably break. 48683998Sbrooks */ 48783998Sbrooks return gif_output(priv->ifp, m, &dst, NULL); 48883998Sbrooks} 48983998Sbrooks 49083998Sbrooks/* 49183998Sbrooks * Shutdown node. This resets the node but does not remove it 49283998Sbrooks * unless the REALLY_DIE flag is set. 49383998Sbrooks */ 49483998Sbrooksstatic int 49583998Sbrooksng_gif_shutdown(node_p node) 49683998Sbrooks{ 49783998Sbrooks const priv_p priv = NG_NODE_PRIVATE(node); 49883998Sbrooks 49983998Sbrooks if (node->nd_flags & NG_REALLY_DIE) { 50083998Sbrooks /* 50183998Sbrooks * WE came here because the gif interface is being destroyed, 50283998Sbrooks * so stop being persistant. 50383998Sbrooks * Actually undo all the things we did on creation. 50483998Sbrooks * Assume the ifp has already been freed. 50583998Sbrooks */ 50683998Sbrooks NG_NODE_SET_PRIVATE(node, NULL); 50783998Sbrooks FREE(priv, M_NETGRAPH); 50883998Sbrooks NG_NODE_UNREF(node); /* free node itself */ 50983998Sbrooks return (0); 51083998Sbrooks } 51183998Sbrooks node->nd_flags &= ~NG_INVALID; /* Signal ng_rmnode we are persisant */ 51283998Sbrooks return (0); 51383998Sbrooks} 51483998Sbrooks 51583998Sbrooks/* 51683998Sbrooks * Hook disconnection. 51783998Sbrooks */ 51883998Sbrooksstatic int 51983998Sbrooksng_gif_disconnect(hook_p hook) 52083998Sbrooks{ 52183998Sbrooks const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 52283998Sbrooks 52383998Sbrooks if (hook == priv->lower) { 52483998Sbrooks priv->lower = NULL; 52583998Sbrooks priv->lowerOrphan = 0; 52683998Sbrooks } else 52787599Sobrien panic("%s: weird hook", __func__); 52883998Sbrooks if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0) 52983998Sbrooks && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) 53083998Sbrooks ng_rmnode_self(NG_HOOK_NODE(hook)); /* reset node */ 53183998Sbrooks 53283998Sbrooks return (0); 53383998Sbrooks} 53483998Sbrooks 53583998Sbrooks/****************************************************************** 53683998Sbrooks INITIALIZATION 53783998Sbrooks******************************************************************/ 53883998Sbrooks 53983998Sbrooks/* 54083998Sbrooks * Handle loading and unloading for this node type. 54183998Sbrooks */ 54283998Sbrooksstatic int 54383998Sbrooksng_gif_mod_event(module_t mod, int event, void *data) 54483998Sbrooks{ 54583998Sbrooks struct ifnet *ifp; 54683998Sbrooks int error = 0; 54783998Sbrooks int s; 54883998Sbrooks 54983998Sbrooks s = splnet(); 55083998Sbrooks switch (event) { 55183998Sbrooks case MOD_LOAD: 55283998Sbrooks 55383998Sbrooks /* Register function hooks */ 55483998Sbrooks if (ng_gif_attach_p != NULL) { 55583998Sbrooks error = EEXIST; 55683998Sbrooks break; 55783998Sbrooks } 55883998Sbrooks ng_gif_attach_p = ng_gif_attach; 55983998Sbrooks ng_gif_detach_p = ng_gif_detach; 56083998Sbrooks ng_gif_input_p = ng_gif_input; 56183998Sbrooks ng_gif_input_orphan_p = ng_gif_input_orphan; 56283998Sbrooks 56383998Sbrooks /* Create nodes for any already-existing gif interfaces */ 564108172Shsu IFNET_RLOCK(); 56583998Sbrooks TAILQ_FOREACH(ifp, &ifnet, if_link) { 56683998Sbrooks if (ifp->if_type == IFT_GIF) 56783998Sbrooks ng_gif_attach(ifp); 56883998Sbrooks } 569108172Shsu IFNET_RUNLOCK(); 57083998Sbrooks break; 57183998Sbrooks 57283998Sbrooks case MOD_UNLOAD: 57383998Sbrooks 57483998Sbrooks /* 57583998Sbrooks * Note that the base code won't try to unload us until 57683998Sbrooks * all nodes have been removed, and that can't happen 57783998Sbrooks * until all gif interfaces are destroyed. In any 57883998Sbrooks * case, we know there are no nodes left if the action 57983998Sbrooks * is MOD_UNLOAD, so there's no need to detach any nodes. 58083998Sbrooks * 58183998Sbrooks * XXX: what about manual unloads?!? 58283998Sbrooks */ 58383998Sbrooks 58483998Sbrooks /* Unregister function hooks */ 58583998Sbrooks ng_gif_attach_p = NULL; 58683998Sbrooks ng_gif_detach_p = NULL; 58783998Sbrooks ng_gif_input_p = NULL; 58883998Sbrooks ng_gif_input_orphan_p = NULL; 58983998Sbrooks break; 59083998Sbrooks 59183998Sbrooks default: 59283998Sbrooks error = EOPNOTSUPP; 59383998Sbrooks break; 59483998Sbrooks } 59583998Sbrooks splx(s); 59683998Sbrooks return (error); 59783998Sbrooks} 59883998Sbrooks 599