summaryrefslogtreecommitdiffstats
path: root/sys/netgraph
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netgraph')
-rw-r--r--sys/netgraph/netflow/netflow.c10
-rw-r--r--sys/netgraph/netflow/ng_netflow.c100
-rw-r--r--sys/netgraph/netflow/ng_netflow.h26
3 files changed, 116 insertions, 20 deletions
diff --git a/sys/netgraph/netflow/netflow.c b/sys/netgraph/netflow/netflow.c
index 51a87dd..29193ab 100644
--- a/sys/netgraph/netflow/netflow.c
+++ b/sys/netgraph/netflow/netflow.c
@@ -389,8 +389,7 @@ ng_netflow_cache_flush(priv_p priv)
/* Insert packet from into flow cache. */
int
-ng_netflow_flow_add(priv_p priv, struct ip *ip, iface_p iface,
- struct ifnet *ifp)
+ng_netflow_flow_add(priv_p priv, struct ip *ip, unsigned int src_if_index)
{
register struct flow_entry *fle, *fle1;
struct flow_hash_entry *hsh;
@@ -421,12 +420,7 @@ ng_netflow_flow_add(priv_p priv, struct ip *ip, iface_p iface,
r.r_ip_p = ip->ip_p;
r.r_tos = ip->ip_tos;
- /* Configured in_ifx overrides mbuf's */
- if (iface->info.ifinfo_index == 0) {
- if (ifp != NULL)
- r.r_i_ifx = ifp->if_index;
- } else
- r.r_i_ifx = iface->info.ifinfo_index;
+ r.r_i_ifx = src_if_index;
/*
* XXX NOTE: only first fragment of fragmented TCP, UDP and
diff --git a/sys/netgraph/netflow/ng_netflow.c b/sys/netgraph/netflow/ng_netflow.c
index c813e50..76fece8 100644
--- a/sys/netgraph/netflow/ng_netflow.c
+++ b/sys/netgraph/netflow/ng_netflow.c
@@ -106,6 +106,14 @@ static const struct ng_parse_type ng_netflow_settimeouts_type = {
&ng_netflow_settimeouts_type_fields
};
+/* Parse type for ng_netflow_setconfig */
+static const struct ng_parse_struct_field ng_netflow_setconfig_type_fields[]
+ = NG_NETFLOW_SETCONFIG_TYPE;
+static const struct ng_parse_type ng_netflow_setconfig_type = {
+ &ng_parse_struct_type,
+ &ng_netflow_setconfig_type_fields
+};
+
/* List of commands and how to convert arguments to/from ASCII */
static const struct ng_cmdlist ng_netflow_cmds[] = {
{
@@ -143,6 +151,13 @@ static const struct ng_cmdlist ng_netflow_cmds[] = {
&ng_netflow_settimeouts_type,
NULL
},
+ {
+ NGM_NETFLOW_COOKIE,
+ NGM_NETFLOW_SETCONFIG,
+ "setconfig",
+ &ng_netflow_setconfig_type,
+ NULL
+ },
{ 0 }
};
@@ -167,7 +182,7 @@ static int
ng_netflow_constructor(node_p node)
{
priv_p priv;
- int error = 0;
+ int error = 0, i;
/* Initialize private data */
MALLOC(priv, priv_p, sizeof(*priv), M_NETGRAPH, M_NOWAIT);
@@ -183,6 +198,10 @@ ng_netflow_constructor(node_p node)
priv->info.nfinfo_inact_t = INACTIVE_TIMEOUT;
priv->info.nfinfo_act_t = ACTIVE_TIMEOUT;
+ /* Set default config */
+ for (i = 0; i < NG_NETFLOW_MAXIFACES; i++)
+ priv->ifaces[i].info.conf = NG_NETFLOW_CONF_INGRESS;
+
/* Initialize callout handle */
callout_init(&priv->exp_callout, CALLOUT_MPSAFE);
@@ -399,6 +418,22 @@ ng_netflow_rcvmsg (node_p node, item_p item, hook_p lasthook)
break;
}
+ case NGM_NETFLOW_SETCONFIG:
+ {
+ struct ng_netflow_setconfig *set;
+
+ if (msg->header.arglen != sizeof(struct ng_netflow_settimeouts))
+ ERROUT(EINVAL);
+
+ set = (struct ng_netflow_setconfig *)msg->data;
+
+ if (set->iface >= NG_NETFLOW_MAXIFACES)
+ ERROUT(EINVAL);
+
+ priv->ifaces[set->iface].info.conf = set->conf;
+
+ break;
+ }
case NGM_NETFLOW_SHOW:
{
uint32_t *last;
@@ -445,10 +480,13 @@ ng_netflow_rcvdata (hook_p hook, item_p item)
const node_p node = NG_HOOK_NODE(hook);
const priv_p priv = NG_NODE_PRIVATE(node);
const iface_p iface = NG_HOOK_PRIVATE(hook);
+ hook_p out;
struct mbuf *m = NULL;
struct ip *ip;
+ struct m_tag *mtag;
int pullup_len = 0;
- int error = 0;
+ int error = 0, bypass = 0;
+ unsigned int src_if_index;
if (hook == priv->export) {
/*
@@ -459,16 +497,48 @@ ng_netflow_rcvdata (hook_p hook, item_p item)
ERROUT(EINVAL);
};
- if (hook == iface->out) {
- /*
- * Data arrived on out hook. Bypass it.
- */
- if (iface->hook == NULL)
+ if (hook == iface->hook) {
+ if ((iface->info.conf & NG_NETFLOW_CONF_INGRESS) == 0)
+ bypass = 1;
+ out = iface->out;
+ } else if (hook == iface->out) {
+ if ((iface->info.conf & NG_NETFLOW_CONF_EGRESS) == 0)
+ bypass = 1;
+ out = iface->hook;
+ } else
+ ERROUT(EINVAL);
+
+ if ((!bypass) &&
+ (iface->info.conf & (NG_NETFLOW_CONF_ONCE | NG_NETFLOW_CONF_THISONCE))) {
+ mtag = m_tag_locate(NGI_M(item), MTAG_NETFLOW,
+ MTAG_NETFLOW_CALLED, NULL);
+ while (mtag != NULL) {
+ if ((iface->info.conf & NG_NETFLOW_CONF_ONCE) ||
+ ((ng_ID_t *)(mtag + 1))[0] == NG_NODE_ID(node)) {
+ bypass = 1;
+ break;
+ }
+ mtag = m_tag_locate(NGI_M(item), MTAG_NETFLOW,
+ MTAG_NETFLOW_CALLED, mtag);
+ }
+ }
+
+ if (bypass) {
+ if (out == NULL)
ERROUT(ENOTCONN);
- NG_FWD_ITEM_HOOK(error, item, iface->hook);
+ NG_FWD_ITEM_HOOK(error, item, out);
return (error);
}
+
+ if (iface->info.conf & (NG_NETFLOW_CONF_ONCE | NG_NETFLOW_CONF_THISONCE)) {
+ mtag = m_tag_alloc(MTAG_NETFLOW, MTAG_NETFLOW_CALLED,
+ sizeof(ng_ID_t), M_NOWAIT);
+ if (mtag) {
+ ((ng_ID_t *)(mtag + 1))[0] = NG_NODE_ID(node);
+ m_tag_prepend(NGI_M(item), mtag);
+ }
+ }
NGI_GET_M(item, m);
@@ -592,12 +662,20 @@ ng_netflow_rcvdata (hook_p hook, item_p item)
#undef M_CHECK
- error = ng_netflow_flow_add(priv, ip, iface, m->m_pkthdr.rcvif);
+ /* Determine packet input interface. Prefer configured. */
+ src_if_index = 0;
+ if (hook == iface->out || iface->info.ifinfo_index == 0) {
+ if (m->m_pkthdr.rcvif != NULL)
+ src_if_index = m->m_pkthdr.rcvif->if_index;
+ } else
+ src_if_index = iface->info.ifinfo_index;
+
+ error = ng_netflow_flow_add(priv, ip, src_if_index);
bypass:
- if (iface->out != NULL) {
+ if (out != NULL) {
/* XXX: error gets overwritten here */
- NG_FWD_NEW_DATA(error, item, iface->out, m);
+ NG_FWD_NEW_DATA(error, item, out, m);
return (error);
}
done:
diff --git a/sys/netgraph/netflow/ng_netflow.h b/sys/netgraph/netflow/ng_netflow.h
index bd35cf0..a7f52f3 100644
--- a/sys/netgraph/netflow/ng_netflow.h
+++ b/sys/netgraph/netflow/ng_netflow.h
@@ -50,6 +50,7 @@ enum {
NGM_NETFLOW_SETDLT = 4, /* set data-link type */
NGM_NETFLOW_SETIFINDEX = 5, /* set interface index */
NGM_NETFLOW_SETTIMEOUTS = 6, /* set active/inactive flow timeouts */
+ NGM_NETFLOW_SETCONFIG = 7, /* set flow generation options */
};
/* This structure is returned by the NGM_NETFLOW_INFO message */
@@ -71,6 +72,7 @@ struct ng_netflow_ifinfo {
uint8_t ifinfo_dlt; /* Data Link Type, DLT_XXX */
#define MAXDLTNAMELEN 20
u_int16_t ifinfo_index; /* connected iface index */
+ uint32_t conf;
};
@@ -92,6 +94,17 @@ struct ng_netflow_settimeouts {
uint32_t active_timeout; /* flow active timeout */
};
+#define NG_NETFLOW_CONF_INGRESS 1
+#define NG_NETFLOW_CONF_EGRESS 2
+#define NG_NETFLOW_CONF_ONCE 4
+#define NG_NETFLOW_CONF_THISONCE 8
+
+/* This structure is passed to NGM_NETFLOW_SETCONFIG */
+struct ng_netflow_setconfig {
+ u_int16_t iface; /* which iface config change */
+ u_int32_t conf; /* new config */
+};
+
/* This is unique data, which identifies flow */
struct flow_rec {
struct in_addr r_src;
@@ -182,6 +195,7 @@ struct flow_entry {
{ "packets", &ng_parse_uint32_type }, \
{ "data link type", &ng_parse_uint8_type }, \
{ "index", &ng_parse_uint16_type }, \
+ { "conf", &ng_parse_uint32_type }, \
{ NULL } \
}
@@ -206,6 +220,13 @@ struct flow_entry {
{ NULL } \
}
+/* Parse the setifindex structure */
+#define NG_NETFLOW_SETCONFIG_TYPE { \
+ { "iface", &ng_parse_uint16_type }, \
+ { "conf", &ng_parse_uint32_type }, \
+ { NULL } \
+}
+
/* Private hook data */
struct ng_netflow_iface {
hook_p hook; /* NULL when disconnected */
@@ -263,12 +284,15 @@ struct flow_hash_entry {
#define ERROUT(x) { error = (x); goto done; }
+#define MTAG_NETFLOW 1221656444
+#define MTAG_NETFLOW_CALLED 0
+
/* Prototypes for netflow.c */
int ng_netflow_cache_init(priv_p);
void ng_netflow_cache_flush(priv_p);
void ng_netflow_copyinfo(priv_p, struct ng_netflow_info *);
timeout_t ng_netflow_expire;
-int ng_netflow_flow_add(priv_p, struct ip *, iface_p, struct ifnet *);
+int ng_netflow_flow_add(priv_p, struct ip *, unsigned int src_if_index);
int ng_netflow_flow_show(priv_p, uint32_t last, struct ng_mesg *);
#endif /* _KERNEL */
OpenPOWER on IntegriCloud