diff options
-rw-r--r-- | sys/netgraph/netflow/netflow.c | 10 | ||||
-rw-r--r-- | sys/netgraph/netflow/ng_netflow.c | 100 | ||||
-rw-r--r-- | sys/netgraph/netflow/ng_netflow.h | 26 |
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 */ |