(fwd) Re: netgraph on disc(4)
Gleb Smirnoff
glebius at FreeBSD.org
Mon May 29 04:52:31 PDT 2006
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 at elischer.org> -----
Y>
Y> From: Julian Elischer <julian at elischer.org>
Y> Subject: Re: netgraph on disc(4)
Y> To: Yann Berthier <yb at bashibuzuk.net>
Y> CC: freebsd-net at freebsd.org
Y> X-Original-To: yb at cc.6f2.net
Y> Delivered-To: yb at 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 at 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 at freebsd.org mailing list
Y> >http://lists.freebsd.org/mailman/listinfo/freebsd-net
Y> >To unsubscribe, send any mail to "freebsd-net-unsubscribe at 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
-------------- next part --------------
/*-
* 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);
}
-------------- next part --------------
/*-
* 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_ */
More information about the freebsd-net
mailing list