diff --git a/sys/netgraph/netflow/netflow.c b/sys/netgraph/netflow/netflow.c index 3d1d62a65eed..cd84e90f24df 100644 --- a/sys/netgraph/netflow/netflow.c +++ b/sys/netgraph/netflow/netflow.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2004 Gleb Smirnoff + * Copyright (c) 2004-2005 Gleb Smirnoff * Copyright (c) 2001-2003 Roman V. Palagin * All rights reserved. * @@ -304,90 +304,6 @@ hash_insert(priv_p priv, int slot, struct flow_rec *r, int plen, return (0); } -static __inline int -make_flow_rec(struct mbuf **m, int *plen, struct flow_rec *r, - uint8_t *tcp_flags, u_int16_t i_ifx) -{ - register struct ip *ip; - int hlen; - int error = 0; - - ip = mtod(*m, struct ip*); - - /* check version */ - if (ip->ip_v != IPVERSION) - return (EINVAL); - - /* verify min header length */ - hlen = ip->ip_hl << 2; - - if (hlen < sizeof(struct ip)) - return (EINVAL); - - r->r_src = ip->ip_src; - r->r_dst = ip->ip_dst; - - /* save packet length */ - *plen = ntohs(ip->ip_len); - - r->r_ip_p = ip->ip_p; - r->r_tos = ip->ip_tos; - - /* Configured in_ifx overrides mbuf's */ - if (i_ifx == 0) { - if ((*m)->m_pkthdr.rcvif) - r->r_i_ifx = (*m)->m_pkthdr.rcvif->if_index; - } else - r->r_i_ifx = i_ifx; - - /* - * XXX NOTE: only first fragment of fragmented TCP, UDP and - * ICMP packet will be recorded with proper s_port and d_port. - * Following fragments will be recorded simply as IP packet with - * ip_proto = ip->ip_p and s_port, d_port set to zero. - * I know, it looks like bug. But I don't want to re-implement - * ip packet assebmling here. Anyway, (in)famous trafd works this way - - * and nobody complains yet :) - */ - if(ip->ip_off & htons(IP_OFFMASK)) - return (0); - - /* skip IP header */ - m_adj(*m, hlen); - - switch(r->r_ip_p) { - case IPPROTO_TCP: - { - register struct tcphdr *tcp; - - /* verify that packet is not truncated */ - if (CHECK_MLEN(*m, sizeof(struct tcphdr))) - ERROUT(EINVAL); - - if (CHECK_PULLUP(*m, sizeof(struct tcphdr))) - ERROUT(ENOBUFS); - - tcp = mtod(*m, struct tcphdr*); - r->r_sport = tcp->th_sport; - r->r_dport = tcp->th_dport; - *tcp_flags = tcp->th_flags; - break; - } - case IPPROTO_UDP: - /* verify that packet is not truncated */ - if (CHECK_MLEN(*m, sizeof(struct udphdr))) - ERROUT(EINVAL); - - if (CHECK_PULLUP(*m, sizeof(struct udphdr))) - ERROUT(ENOBUFS); - - r->r_ports = *(mtod(*m, uint32_t *)); - break; - } - -done: - return (error); -} /* * Non-static functions called from ng_netflow.c @@ -469,21 +385,73 @@ ng_netflow_cache_flush(priv_p priv) /* Insert packet from &m into flow cache. */ int -ng_netflow_flow_add(priv_p priv, struct mbuf **m, iface_p iface) +ng_netflow_flow_add(priv_p priv, struct ip *ip, iface_p iface, + struct ifnet *ifp) { struct flow_hash_entry *h = priv->hash; register struct flow_entry *fle; struct flow_rec r; - int plen; - int error = 0; + int hlen, plen; uint32_t slot; uint8_t tcp_flags = 0; - /* Try to fill *rec */ + /* Try to fill flow_rec r */ bzero(&r, sizeof(r)); - if ((error = make_flow_rec(m, &plen, &r, &tcp_flags, - iface->info.ifinfo_index))) - return (error); + /* check version */ + if (ip->ip_v != IPVERSION) + return (EINVAL); + + /* verify min header length */ + hlen = ip->ip_hl << 2; + + if (hlen < sizeof(struct ip)) + return (EINVAL); + + r.r_src = ip->ip_src; + r.r_dst = ip->ip_dst; + + /* save packet length */ + plen = ntohs(ip->ip_len); + + 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; + + /* + * XXX NOTE: only first fragment of fragmented TCP, UDP and + * ICMP packet will be recorded with proper s_port and d_port. + * Following fragments will be recorded simply as IP packet with + * ip_proto = ip->ip_p and s_port, d_port set to zero. + * I know, it looks like bug. But I don't want to re-implement + * ip packet assebmling here. Anyway, (in)famous trafd works this way - + * and nobody complains yet :) + */ + if(ip->ip_off & htons(IP_OFFMASK)) + goto flow_rec_done; + + switch(r.r_ip_p) { + case IPPROTO_TCP: + { + register struct tcphdr *tcp; + + tcp = (struct tcphdr *)((caddr_t )ip + hlen); + r.r_sport = tcp->th_sport; + r.r_dport = tcp->th_dport; + tcp_flags = tcp->th_flags; + break; + } + case IPPROTO_UDP: + r.r_ports = *(uint32_t *)((caddr_t )ip + hlen); + break; + } + +flow_rec_done: slot = ip_hash(&r); diff --git a/sys/netgraph/netflow/ng_netflow.c b/sys/netgraph/netflow/ng_netflow.c index d6532e84b808..1944ce4735ed 100644 --- a/sys/netgraph/netflow/ng_netflow.c +++ b/sys/netgraph/netflow/ng_netflow.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2004 Gleb Smirnoff + * Copyright (c) 2004-2005 Gleb Smirnoff * Copyright (c) 2001-2003 Roman V. Palagin * All rights reserved. * @@ -46,6 +46,8 @@ static const char rcs_id[] = #include #include #include +#include +#include #include #include @@ -410,6 +412,8 @@ ng_netflow_rcvdata (hook_p hook, item_p item) const priv_p priv = NG_NODE_PRIVATE(node); const iface_p iface = NG_HOOK_PRIVATE(hook); struct mbuf *m; + struct ip *ip; + int pullup_len = 0; int error = 0; NGI_GET_M(item, m); diff --git a/sys/netgraph/netflow/ng_netflow.h b/sys/netgraph/netflow/ng_netflow.h index 0f8ebcf0d735..7bb3d97ebb1e 100644 --- a/sys/netgraph/netflow/ng_netflow.h +++ b/sys/netgraph/netflow/ng_netflow.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2004 Gleb Smirnoff + * Copyright (c) 2004-2005 Gleb Smirnoff * Copyright (c) 2001-2003 Roman V. Palagin * All rights reserved. * @@ -256,11 +256,6 @@ struct flow_hash_entry { LIST_HEAD( ,flow_entry) head; }; -/* Make sure packet large enough to contain len bytes */ -#define CHECK_MLEN(m, length) ((m)->m_pkthdr.len < (length)) -#define CHECK_PULLUP(m, length) ((m)->m_len < (length) && \ - (((m) = m_pullup((m),(length))) == NULL)) - #define ERROUT(x) { error = (x); goto done; } /* Prototypes for netflow.c */ @@ -268,7 +263,7 @@ 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 mbuf **, iface_p); +int ng_netflow_flow_add(priv_p, struct ip *, iface_p, struct ifnet *); int ng_netflow_flow_show(priv_p, uint32_t last, struct ng_mesg *); #endif /* _KERNEL */