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().
This commit is contained in:
Gleb Smirnoff 2005-03-21 15:40:25 +00:00
parent 1d03bd1684
commit 2b38b68736

View File

@ -426,49 +426,98 @@ ng_netflow_rcvdata (hook_p hook, item_p item)
ERROUT(EINVAL); ERROUT(EINVAL);
}; };
/* increase counters */ /* Increase counters. */
iface->info.ifinfo_packets++; 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) { switch (iface->info.ifinfo_dlt) {
case DLT_EN10MB: /* Ethernet */ case DLT_EN10MB: /* Ethernet */
{ {
struct ether_header *eh; struct ether_header *eh;
uint16_t etype; uint16_t etype;
if (CHECK_MLEN(m, (sizeof(struct ether_header)))) M_CHECK(sizeof(struct ether_header));
ERROUT(EINVAL);
if (CHECK_PULLUP(m, (sizeof(struct ether_header))))
ERROUT(ENOBUFS);
eh = mtod(m, 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); etype = ntohs(eh->ether_type);
switch (etype) { switch (etype) {
case ETHERTYPE_IP: 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; break;
default: 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; break;
} }
case DLT_RAW: case DLT_RAW:
ip = mtod(m, struct ip *);
break; break;
default: default:
ERROUT(EINVAL); panic("ng_netflow entered deadcode");
break;
} }
if (CHECK_MLEN(m, sizeof(struct ip))) #undef M_CHECK
ERROUT(EINVAL);
if (CHECK_PULLUP(m, sizeof(struct ip))) error = ng_netflow_flow_add(priv, ip, iface, m->m_pkthdr.rcvif);
ERROUT(ENOBUFS);
error = ng_netflow_flow_add(priv, &m, iface);
done: done:
if (item) if (item)