diff options
author | glebius <glebius@FreeBSD.org> | 2005-03-22 15:49:22 +0000 |
---|---|---|
committer | glebius <glebius@FreeBSD.org> | 2005-03-22 15:49:22 +0000 |
commit | 4beb15977bf4db80be6ebd3851f35211fed3e0a8 (patch) | |
tree | 57fd7cbf346fbeaa0a19c926773cabc0afc0825b | |
parent | 6da33dec9de9012f23d9b0f195821a23ee2ec796 (diff) | |
download | FreeBSD-src-4beb15977bf4db80be6ebd3851f35211fed3e0a8.zip FreeBSD-src-4beb15977bf4db80be6ebd3851f35211fed3e0a8.tar.gz |
Add a possibility to bypass unmodified accounted data to special
hook(s). Data received on these hook(s) is sent back to ifaceX hook(s).
-rw-r--r-- | sys/netgraph/netflow/ng_netflow.c | 53 | ||||
-rw-r--r-- | sys/netgraph/netflow/ng_netflow.h | 2 |
2 files changed, 50 insertions, 5 deletions
diff --git a/sys/netgraph/netflow/ng_netflow.c b/sys/netgraph/netflow/ng_netflow.c index f8a4c28..cb3ded7 100644 --- a/sys/netgraph/netflow/ng_netflow.c +++ b/sys/netgraph/netflow/ng_netflow.c @@ -235,6 +235,31 @@ ng_netflow_newhook(node_p node, hook_p hook, const char *name) */ iface->info.ifinfo_dlt = DLT_EN10MB; + } else if (strncmp(name, NG_NETFLOW_HOOK_OUT, + strlen(NG_NETFLOW_HOOK_OUT)) == 0) { + iface_p iface; + int ifnum = -1; + const char *cp; + char *eptr; + + cp = name + strlen(NG_NETFLOW_HOOK_OUT); + if (!isdigit(*cp) || (cp[0] == '0' && cp[1] != '\0')) + return (EINVAL); + + ifnum = (int)strtoul(cp, &eptr, 10); + if (*eptr != '\0' || ifnum < 0 || ifnum >= NG_NETFLOW_MAXIFACES) + return (EINVAL); + + /* See if hook is already connected */ + if (priv->ifaces[ifnum].out != NULL) + return (EISCONN); + + iface = &priv->ifaces[ifnum]; + + /* Link private info and hook together */ + NG_HOOK_SET_PRIVATE(hook, iface); + iface->out = hook; + } else if (strcmp(name, NG_NETFLOW_HOOK_EXPORT) == 0) { if (priv->export != NULL) @@ -411,12 +436,11 @@ 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); - struct mbuf *m; + struct mbuf *m = NULL; struct ip *ip; int pullup_len = 0; int error = 0; - NGI_GET_M(item, m); if (hook == priv->export) { /* * Data arrived on export hook. @@ -426,6 +450,19 @@ 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) + ERROUT(ENOTCONN); + + NG_FWD_ITEM_HOOK(error, item, iface->hook); + return (error); + } + + NGI_GET_M(item, m); + /* Increase counters. */ iface->info.ifinfo_packets++; @@ -444,7 +481,7 @@ ng_netflow_rcvdata (hook_p hook, item_p item) pullup_len += length; \ if ((m)->m_pkthdr.len < (pullup_len)) { \ error = EINVAL; \ - goto done; \ + goto bypass; \ } \ if ((m)->m_len < (pullup_len) && \ (((m) = m_pullup((m),(pullup_len))) == NULL)) { \ @@ -471,7 +508,7 @@ ng_netflow_rcvdata (hook_p hook, item_p item) ip = (struct ip *)(eh + 1); break; default: - goto done; /* pass this frame */ + goto bypass; /* pass this frame */ } break; } @@ -480,7 +517,7 @@ ng_netflow_rcvdata (hook_p hook, item_p item) ip = mtod(m, struct ip *); break; default: - goto done; + goto bypass; break; } @@ -519,6 +556,12 @@ ng_netflow_rcvdata (hook_p hook, item_p item) error = ng_netflow_flow_add(priv, ip, iface, m->m_pkthdr.rcvif); +bypass: + if (iface->out != NULL) { + /* XXX: error gets overwritten here */ + NG_FWD_NEW_DATA(error, item, iface->out, m); + return (error); + } done: if (item) NG_FREE_ITEM(item); diff --git a/sys/netgraph/netflow/ng_netflow.h b/sys/netgraph/netflow/ng_netflow.h index 7bb3d97..68f89c7 100644 --- a/sys/netgraph/netflow/ng_netflow.h +++ b/sys/netgraph/netflow/ng_netflow.h @@ -39,6 +39,7 @@ /* Hook names */ #define NG_NETFLOW_HOOK_DATA "iface" +#define NG_NETFLOW_HOOK_OUT "out" #define NG_NETFLOW_HOOK_EXPORT "export" /* Netgraph commands understood by netflow node */ @@ -205,6 +206,7 @@ struct flow_entry { /* Private hook data */ struct ng_netflow_iface { hook_p hook; /* NULL when disconnected */ + hook_p out; /* NULL when no bypass hook */ struct ng_netflow_ifinfo info; }; |