mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-17 15:27:36 +00:00
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:
parent
68c56249b0
commit
1d03bd1684
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=143923
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2004 Gleb Smirnoff <glebius@FreeBSD.org>
|
||||
* Copyright (c) 2004-2005 Gleb Smirnoff <glebius@FreeBSD.org>
|
||||
* Copyright (c) 2001-2003 Roman V. Palagin <romanp@unshadow.net>
|
||||
* 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);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2004 Gleb Smirnoff <glebius@FreeBSD.org>
|
||||
* Copyright (c) 2004-2005 Gleb Smirnoff <glebius@FreeBSD.org>
|
||||
* Copyright (c) 2001-2003 Roman V. Palagin <romanp@unshadow.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
@ -46,6 +46,8 @@ static const char rcs_id[] =
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/udp.h>
|
||||
|
||||
#include <netgraph/ng_message.h>
|
||||
#include <netgraph/ng_parse.h>
|
||||
@ -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);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2004 Gleb Smirnoff <glebius@FreeBSD.org>
|
||||
* Copyright (c) 2004-2005 Gleb Smirnoff <glebius@FreeBSD.org>
|
||||
* Copyright (c) 2001-2003 Roman V. Palagin <romanp@unshadow.net>
|
||||
* 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 */
|
||||
|
Loading…
Reference in New Issue
Block a user