summaryrefslogtreecommitdiffstats
path: root/sys/netgraph/netflow/ng_netflow.c
diff options
context:
space:
mode:
authorglebius <glebius@FreeBSD.org>2005-03-21 15:40:25 +0000
committerglebius <glebius@FreeBSD.org>2005-03-21 15:40:25 +0000
commitb4470372ca452e826631f686b6e651a110e72675 (patch)
tree668c14edbf45186cd8c12e102c805a25cf1420e0 /sys/netgraph/netflow/ng_netflow.c
parentf55027e9fb92a9b34b346d1411fd9c5b6e779df9 (diff)
downloadFreeBSD-src-b4470372ca452e826631f686b6e651a110e72675.zip
FreeBSD-src-b4470372ca452e826631f686b6e651a110e72675.tar.gz
Refactor node so that it does not modify mbuf contents. Next step would
be pass-thru mode, when traffic is not copied by ng_tee, but passed thru ng_netflow. Changes made: - In ng_netflow_rcvdata() do all necessary pulluping: Ethernet header, IP header, and TCP/UDP header. - Pass only pointer to struct ip to ng_netflow_flow_add(). Any TCP/UDP headers are guaranteed to by after it. - Merge make_flow_rec() function into ng_netflow_flow_add().
Diffstat (limited to 'sys/netgraph/netflow/ng_netflow.c')
-rw-r--r--sys/netgraph/netflow/ng_netflow.c87
1 files changed, 68 insertions, 19 deletions
diff --git a/sys/netgraph/netflow/ng_netflow.c b/sys/netgraph/netflow/ng_netflow.c
index 1944ce4..f8a4c28 100644
--- a/sys/netgraph/netflow/ng_netflow.c
+++ b/sys/netgraph/netflow/ng_netflow.c
@@ -426,49 +426,98 @@ ng_netflow_rcvdata (hook_p hook, item_p item)
ERROUT(EINVAL);
};
- /* increase counters */
+ /* Increase counters. */
iface->info.ifinfo_packets++;
+ /*
+ * Depending on interface data link type and packet contents
+ * we pullup enough data, so that ng_netflow_flow_add() does not
+ * need to know about mbuf at all. We keep current length of data
+ * needed to be contiguous in pullup_len. mtod() is done at the
+ * very end one more time, since m can had changed after pulluping.
+ *
+ * In case of unrecognized data we don't return error, but just
+ * pass data to downstream hook, if it is available.
+ */
+
+#define M_CHECK(length) do { \
+ pullup_len += length; \
+ if ((m)->m_pkthdr.len < (pullup_len)) { \
+ error = EINVAL; \
+ goto done; \
+ } \
+ if ((m)->m_len < (pullup_len) && \
+ (((m) = m_pullup((m),(pullup_len))) == NULL)) { \
+ error = ENOBUFS; \
+ goto done; \
+ } \
+} while (0)
+
switch (iface->info.ifinfo_dlt) {
case DLT_EN10MB: /* Ethernet */
- {
+ {
struct ether_header *eh;
uint16_t etype;
- if (CHECK_MLEN(m, (sizeof(struct ether_header))))
- ERROUT(EINVAL);
-
- if (CHECK_PULLUP(m, (sizeof(struct ether_header))))
- ERROUT(ENOBUFS);
-
+ M_CHECK(sizeof(struct ether_header));
eh = mtod(m, struct ether_header *);
- /* make sure this is IP frame */
+ /* Make sure this is IP frame. */
etype = ntohs(eh->ether_type);
switch (etype) {
case ETHERTYPE_IP:
- m_adj(m, sizeof(struct ether_header));
+ M_CHECK(sizeof(struct ip));
+ eh = mtod(m, struct ether_header *);
+ ip = (struct ip *)(eh + 1);
break;
default:
- ERROUT(EINVAL); /* ignore this frame */
+ goto done; /* pass this frame */
}
+ break;
+ }
+ case DLT_RAW: /* IP packets */
+ M_CHECK(sizeof(struct ip));
+ ip = mtod(m, struct ip *);
+ break;
+ default:
+ goto done;
+ break;
+ }
+ /*
+ * In case of IP header with options, we haven't pulled
+ * up enough, yet.
+ */
+ pullup_len += (ip->ip_hl << 2) - sizeof(struct ip);
+
+ switch (ip->ip_p) {
+ case IPPROTO_TCP:
+ M_CHECK(sizeof(struct tcphdr));
+ break;
+ case IPPROTO_UDP:
+ M_CHECK(sizeof(struct udphdr));
break;
}
+
+ switch (iface->info.ifinfo_dlt) {
+ case DLT_EN10MB:
+ {
+ struct ether_header *eh;
+
+ eh = mtod(m, struct ether_header *);
+ ip = (struct ip *)(eh + 1);
+ break;
+ }
case DLT_RAW:
+ ip = mtod(m, struct ip *);
break;
default:
- ERROUT(EINVAL);
- break;
+ panic("ng_netflow entered deadcode");
}
- if (CHECK_MLEN(m, sizeof(struct ip)))
- ERROUT(EINVAL);
-
- if (CHECK_PULLUP(m, sizeof(struct ip)))
- ERROUT(ENOBUFS);
+#undef M_CHECK
- error = ng_netflow_flow_add(priv, &m, iface);
+ error = ng_netflow_flow_add(priv, ip, iface, m->m_pkthdr.rcvif);
done:
if (item)
OpenPOWER on IntegriCloud