Date: Mon, 29 May 2006 15:51:46 +0400 From: Gleb Smirnoff <glebius@FreeBSD.org> To: Yann Berthier <yb@bashibuzuk.net> Cc: net@FreeBSD.org Subject: Re: (fwd) Re: netgraph on disc(4) Message-ID: <20060529115146.GQ27819@cell.sick.ru> In-Reply-To: <20060528194319.GL1424@bashibuzuk.net> References: <20060528194319.GL1424@bashibuzuk.net>
next in thread | previous in thread | raw e-mail | index | archive | help
--YrQNB5Deg1WGKZi3 Content-Type: text/plain; charset=koi8-r Content-Disposition: inline On Sun, May 28, 2006 at 09:43:19PM +0200, Yann Berthier wrote: Y> Y> Hello Gleb, Y> Y> err, sorry for the forward if you saw the thread already but, have Y> you any input on this ? that's not critical but still, i see value in Y> being able to use ng_netflow on traffic flowing on dummy interfaces Y> (lo, disc, ...) I've have written some code to wrap any interface some time ago. Here it is attached. Sorry, I didn't ever used it and not sure it is compilable on recent FreeBSD versions. Y> best regards, Y> Y> - yann Y> Y> ----- Forwarded message from Julian Elischer <julian@elischer.org> ----- Y> Y> From: Julian Elischer <julian@elischer.org> Y> Subject: Re: netgraph on disc(4) Y> To: Yann Berthier <yb@bashibuzuk.net> Y> CC: freebsd-net@freebsd.org Y> X-Original-To: yb@cc.6f2.net Y> Delivered-To: yb@cc.6f2.net Y> Date: Thu, 25 May 2006 11:46:18 -0700 Y> User-Agent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.13) Gecko/20060414 Y> X-Accept-Language: en-us, en Y> In-Reply-To: <20060525152228.GL1424@bashibuzuk.net> Y> Y> Yann Berthier wrote: Y> Y> I think that Gleb had some changes that allowed netgraph to attach to Y> ANY interface. Y> Y> Gleb? Y> Y> > Hello, Y> > Y> > I wanted to use ng_netflow on a disc interface, but it seems that no Y> > node is created for loopback and the like . Indeed, I found an old Y> > post from gnn@ dating back from march 2000 on this subject, along Y> > with the PR kern/17631. Is somebody reconsidering this idea by any Y> > chance ? Y> > Y> > thnaks, Y> > Y> > - yann Y> >_______________________________________________ Y> >freebsd-net@freebsd.org mailing list Y> >http://lists.freebsd.org/mailman/listinfo/freebsd-net Y> >To unsubscribe, send any mail to "freebsd-net-unsubscribe@freebsd.org" Y> > Y> > Y> Y> ----- End forwarded message ----- Y> Y> -- Y> http://flowog.6f2.net/ - A NetFlow collecting house -- Totus tuus, Glebius. GLEBIUS-RIPN GLEB-RIPE --YrQNB5Deg1WGKZi3 Content-Type: text/plain; charset=koi8-r Content-Disposition: attachment; filename="ng_ifwrap.c" /*- * Copyright (c) 2004 Gleb Smirnoff * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #if 0 #define DFUNC(msg) printf("ifwrap: %s: %s\n", __func__, msg); #define DLINE(msg) printf("ifwrap: -%d-: %s", __LINE__, msg ); #else #define DFUNC(msg) #define DLINE(msg) #endif #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/mbuf.h> #include <sys/malloc.h> #include <sys/errno.h> #include <sys/socket.h> #include <net/if.h> #include <net/if_var.h> #include <net/route.h> #include <netgraph/ng_message.h> #include <netgraph/ng_parse.h> #include <netgraph/netgraph.h> #include <netgraph/ng_ifwrap.h> #define ERROUT(x) do { error = (x); goto done; } while (0) /* Netgraph methods */ static ng_constructor_t ng_ifwrap_constructor; static ng_rcvmsg_t ng_ifwrap_rcvmsg; static ng_shutdown_t ng_ifwrap_shutdown; static ng_newhook_t ng_ifwrap_newhook; static ng_rcvdata_t ng_ifwrap_rcvdata; static ng_disconnect_t ng_ifwrap_disconnect; /* New routines for interface */ static int ng_ifwrap_output(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); static void ng_ifwrap_input(struct ifnet *, struct mbuf *); /* * Our internal tag to store next hop and rtentry. It is declared * here, since noone except of this node should take care of it. */ struct ifwrap_tag { struct m_tag mt; struct rtentry *rt; struct sockaddr sa; }; #define TAGSIZ (sizeof(struct ifwrap_tag) - sizeof(struct m_tag)) /* Free method for our tags */ static void ifwrap_tag_free(struct m_tag *); /* List of commands and how to convert arguments to/from ASCII */ static const struct ng_cmdlist ng_ifwrap_cmdlist[] = { { NGM_IFWRAP_COOKIE, NGM_IFWRAP_ATTACH, "attach", &ng_parse_string_type, NULL }, { 0 } }; /* Netgraph node type descriptor */ static struct ng_type ng_ifwrap_typestruct = { .version = NG_ABI_VERSION, .name = NG_IFWRAP_NODE_TYPE, .constructor = ng_ifwrap_constructor, .rcvmsg = ng_ifwrap_rcvmsg, .shutdown = ng_ifwrap_shutdown, .newhook = ng_ifwrap_newhook, .rcvdata = ng_ifwrap_rcvdata, .disconnect = ng_ifwrap_disconnect, .cmdlist = ng_ifwrap_cmdlist, }; NETGRAPH_INIT(ifwrap, &ng_ifwrap_typestruct); /* Information we store for each node */ struct ng_ifwrap_priv { struct ifnet *ifp; /* pointer to our ifnet */ node_p node; /* back pointer to node */ hook_p upper; /* hook for input */ hook_p lower; /* hook for output */ /* Pointers to original routines */ int (*if_output) (struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); void (*if_input) (struct ifnet *, struct mbuf *); }; typedef struct ng_ifwrap_priv *priv_p; /* This is where we store pointer from iface to node private date. This * makes us incompatible with ng_fec(4). */ #define IFP2NG(ifp) (priv_p )(ifp->if_afdata[AF_NETGRAPH]) #define IFP2NG_SET(ifp, val) ifp->if_afdata[AF_NETGRAPH] = (val); /****************************************************************************** * Netgraph methods ******************************************************************************/ static int ng_ifwrap_constructor(node_p node) { priv_p priv; MALLOC(priv, priv_p, sizeof(*priv), M_NETGRAPH, M_NOWAIT | M_ZERO); if (priv == NULL) return (ENOMEM); NG_NODE_SET_PRIVATE(node, priv); priv->node = node; return (0); } /* * Hooks are almost the same as ng_ether's, and so is this callback. */ static int ng_ifwrap_newhook(node_p node, hook_p hook, const char *name) { const priv_p priv = NG_NODE_PRIVATE(node); hook_p *hookptr; if (strcmp(name, NG_IFWRAP_HOOK_UPPER) == 0) hookptr = &priv->upper; else if (strcmp(name, NG_IFWRAP_HOOK_LOWER) == 0) hookptr = &priv->lower; else return (EINVAL); /* Check if already connected */ if (*hookptr != NULL) return (EISCONN); *hookptr = hook; return (0); } static int ng_ifwrap_rcvmsg(node_p node, item_p item, hook_p lasthook) { const priv_p priv = NG_NODE_PRIVATE(node); struct ng_mesg *msg, *resp = NULL; int error = 0; NGI_GET_MSG(item, msg); switch (msg->header.typecookie) { case NGM_IFWRAP_COOKIE: switch (msg->header.cmd) { case NGM_IFWRAP_ATTACH: /* Check if we are already initialized */ if (priv->ifp != NULL) ERROUT(EISCONN); if (msg->header.arglen == 0) ERROUT(EINVAL); if ((priv->ifp = ifunit((char *)msg->data)) == NULL) ERROUT(ENOENT); /* * Not all interfaces have both input and output * method. Those are not supported. */ if (priv->ifp->if_input == NULL || priv->ifp->if_output == NULL) ERROUT(ENOTSUP); /* * XXX: There is no mutex to lock struct ifnet yet, * so we will hold afdata_mtx for the whole surgery * procedure. This will not stop races, since other * struct-ifnet-surgeons does not do it same way. */ IF_AFDATA_LOCK(priv->ifp); /* Check if someone already have grabbed AF_NETGRAPH */ if(IFP2NG(priv->ifp) != NULL) { IF_AFDATA_UNLOCK(priv->ifp); priv->ifp = NULL; ERROUT(EISCONN); } IFP2NG_SET(priv->ifp, priv); priv->if_input = priv->ifp->if_input; priv->ifp->if_input = ng_ifwrap_input; priv->if_output = priv->ifp->if_output; priv->ifp->if_output = ng_ifwrap_output; IF_AFDATA_UNLOCK(priv->ifp); break; default: error = EINVAL; break; } break; default: error = EINVAL; break; } done: NG_RESPOND_MSG(error, node, item, resp); NG_FREE_MSG(msg); return(error); } static int ng_ifwrap_rcvdata(hook_p hook, item_p item ) { const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); struct mbuf *m; int error = 0; NGI_GET_M(item, m); NG_FREE_ITEM(item); /* Check if we have attached interface */ if (priv->ifp == NULL) { NG_FREE_M(m); return (ENOTCONN); } if (hook == priv->upper) { (priv->if_input)(priv->ifp, m); return (0); } else if (hook == priv->lower) { struct ifwrap_tag *tag; struct sockaddr *dst; tag = (struct ifwrap_tag *)m_tag_locate(m, NGM_IFWRAP_COOKIE, NG_IFWRAP_TAG_OUTPUT, NULL); if (tag == NULL) { DFUNC("no tag in input packet"); NG_FREE_M(m); return (EDESTADDRREQ); } dst = &tag->sa; error = (priv->if_output)(priv->ifp, m, dst, tag->rt); return (error); } else panic("ng_ifwrap: unknown hook"); /* not reach */ return (0); } static int ng_ifwrap_shutdown(node_p node) { const priv_p priv = NG_NODE_PRIVATE(node); if (priv->ifp != NULL) { IF_AFDATA_LOCK(priv->ifp); IFP2NG_SET(priv->ifp, NULL); /* Restore old methods */ priv->ifp->if_input = priv->if_input; priv->ifp->if_output = priv->if_output; IF_AFDATA_UNLOCK(priv->ifp); } NG_NODE_UNREF(node); FREE(priv, M_NETGRAPH); return (0); } static int ng_ifwrap_disconnect(hook_p hook) { const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); if (hook == priv->lower) priv->lower = NULL; if (hook == priv->upper) priv->upper = NULL; return (0); } static int ng_ifwrap_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rt) { const priv_p priv = IFP2NG(ifp); struct ifwrap_tag *tag; int error = 0; DFUNC("in"); if (priv->upper == NULL) return (priv->if_output)(ifp, m, dst, rt); /* Save rt and dst in mbuf tag */ if ((tag = (struct ifwrap_tag *)m_tag_alloc(NGM_IFWRAP_COOKIE, NG_IFWRAP_TAG_OUTPUT, TAGSIZ, M_DONTWAIT)) == NULL) { m_freem(m); return (ENOMEM); } tag->mt.m_tag_free = &ifwrap_tag_free; bcopy(dst, &tag->sa, dst->sa_len); /* do not allow ip_output() to free our rt */ if (rt != NULL) { RT_LOCK(rt); RT_ADDREF(rt); RT_UNLOCK(rt); tag->rt = rt; } else tag->rt = NULL; m_tag_prepend(m, &tag->mt); NG_SEND_DATA_ONLY(error, priv->upper, m); return (error); } static void ng_ifwrap_input(struct ifnet *ifp, struct mbuf *m) { const priv_p priv = IFP2NG(ifp); int error; DFUNC("in"); if (priv->lower == NULL) return (priv->if_input)(ifp, m); NG_SEND_DATA_ONLY(error, priv->lower, m); return; } /****************************************************************************** * Helper functions ******************************************************************************/ static void ifwrap_tag_free(struct m_tag *mt) { struct ifwrap_tag *tag = (struct ifwrap_tag *)mt; DFUNC("in"); if (tag->rt != NULL) RTFREE(tag->rt); m_tag_free_default(mt); } --YrQNB5Deg1WGKZi3 Content-Type: text/plain; charset=koi8-r Content-Disposition: attachment; filename="ng_ifwrap.h" /*- * Copyright (c) 2004 Gleb Smirnoff * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHIFWRAP IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _NETGRAPH_NG_IFWRAP_H_ #define _NETGRAPH_NG_IFWRAP_H_ #define NG_IFWRAP_NODE_TYPE "ifwrap" #define NGM_IFWRAP_COOKIE 1094849975 /* Hook names, just like in ng_ether */ #define NG_IFWRAP_HOOK_LOWER "lower" /* -> input */ #define NG_IFWRAP_HOOK_UPPER "upper" /* -> output */ /* Tags */ enum { NG_IFWRAP_TAG_OUTPUT, /* stores parameters of if_output() */ }; /* Netgraph commands */ enum { NGM_IFWRAP_ATTACH, /* attach to interface */ }; #endif /* _NETGRAPH_NG_IFWRAP_H_ */ --YrQNB5Deg1WGKZi3--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20060529115146.GQ27819>