Changeset View
Changeset View
Standalone View
Standalone View
sys/netgraph/netflow/netflow.c
Show First 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | |||||
#include <sys/syslog.h> | #include <sys/syslog.h> | ||||
#include <sys/socket.h> | #include <sys/socket.h> | ||||
#include <vm/uma.h> | #include <vm/uma.h> | ||||
#include <net/if.h> | #include <net/if.h> | ||||
#include <net/if_dl.h> | #include <net/if_dl.h> | ||||
#include <net/if_var.h> | #include <net/if_var.h> | ||||
#include <net/route.h> | #include <net/route.h> | ||||
#include <net/route/nhop.h> | |||||
#include <net/route/route_ctl.h> | |||||
#include <net/ethernet.h> | #include <net/ethernet.h> | ||||
#include <netinet/in.h> | #include <netinet/in.h> | ||||
#include <netinet/in_fib.h> | |||||
#include <netinet/in_systm.h> | #include <netinet/in_systm.h> | ||||
#include <netinet/ip.h> | #include <netinet/ip.h> | ||||
#include <netinet/ip6.h> | #include <netinet/ip6.h> | ||||
#include <netinet/tcp.h> | #include <netinet/tcp.h> | ||||
#include <netinet/udp.h> | #include <netinet/udp.h> | ||||
#include <netinet6/in6_fib.h> | |||||
#include <netgraph/ng_message.h> | #include <netgraph/ng_message.h> | ||||
#include <netgraph/netgraph.h> | #include <netgraph/netgraph.h> | ||||
#include <netgraph/netflow/netflow.h> | #include <netgraph/netflow/netflow.h> | ||||
#include <netgraph/netflow/netflow_v9.h> | #include <netgraph/netflow/netflow_v9.h> | ||||
#include <netgraph/netflow/ng_netflow.h> | #include <netgraph/netflow/ng_netflow.h> | ||||
#define NBUCKETS (65536) /* must be power of 2 */ | #define NBUCKETS (65536) /* must be power of 2 */ | ||||
▲ Show 20 Lines • Show All 76 Lines • ▼ Show 20 Lines | return FULL_HASH(r->src.r_src6.__u6_addr.__u6_addr32[3], | ||||
r->dst.r_dst6.__u6_addr.__u6_addr32[3], r->r_sport, | r->dst.r_dst6.__u6_addr.__u6_addr32[3], r->r_sport, | ||||
r->r_dport); | r->r_dport); | ||||
default: | default: | ||||
return ADDR_HASH(r->src.r_src6.__u6_addr.__u6_addr32[3], | return ADDR_HASH(r->src.r_src6.__u6_addr.__u6_addr32[3], | ||||
r->dst.r_dst6.__u6_addr.__u6_addr32[3]); | r->dst.r_dst6.__u6_addr.__u6_addr32[3]); | ||||
} | } | ||||
} | } | ||||
static inline int | |||||
ip6_masklen(struct in6_addr *saddr, struct rt_addrinfo *info) | |||||
{ | |||||
const int nbits = sizeof(*saddr) * NBBY; | |||||
int mlen; | |||||
if (info->rti_addrs & RTA_NETMASK) | |||||
bit_count((bitstr_t *)saddr, 0, nbits, &mlen); | |||||
else | |||||
mlen = nbits; | |||||
return (mlen); | |||||
} | |||||
#endif | #endif | ||||
/* | /* | ||||
* Detach export datagram from priv, if there is any. | * Detach export datagram from priv, if there is any. | ||||
* If there is no, allocate a new one. | * If there is no, allocate a new one. | ||||
*/ | */ | ||||
static item_p | static item_p | ||||
get_export_dgram(priv_p priv, fib_export_p fe) | get_export_dgram(priv_p priv, fib_export_p fe) | ||||
▲ Show 20 Lines • Show All 146 Lines • ▼ Show 20 Lines | |||||
* as this was done in previous version. Need to test & profile | * as this was done in previous version. Need to test & profile | ||||
* to be sure. | * to be sure. | ||||
*/ | */ | ||||
static int | static int | ||||
hash_insert(priv_p priv, struct flow_hash_entry *hsh, struct flow_rec *r, | hash_insert(priv_p priv, struct flow_hash_entry *hsh, struct flow_rec *r, | ||||
int plen, uint8_t flags, uint8_t tcp_flags) | int plen, uint8_t flags, uint8_t tcp_flags) | ||||
{ | { | ||||
struct flow_entry *fle; | struct flow_entry *fle; | ||||
struct sockaddr_in sin, sin_mask; | |||||
struct sockaddr_dl rt_gateway; | |||||
struct rt_addrinfo info; | |||||
mtx_assert(&hsh->mtx, MA_OWNED); | mtx_assert(&hsh->mtx, MA_OWNED); | ||||
fle = uma_zalloc_arg(priv->zone, priv, M_NOWAIT); | fle = uma_zalloc_arg(priv->zone, priv, M_NOWAIT); | ||||
if (fle == NULL) { | if (fle == NULL) { | ||||
priv->nfinfo_alloc_failed++; | priv->nfinfo_alloc_failed++; | ||||
return (ENOMEM); | return (ENOMEM); | ||||
} | } | ||||
Show All 10 Lines | hash_insert(priv_p priv, struct flow_hash_entry *hsh, struct flow_rec *r, | ||||
fle->f.first = fle->f.last = time_uptime; | fle->f.first = fle->f.last = time_uptime; | ||||
/* | /* | ||||
* First we do route table lookup on destination address. So we can | * First we do route table lookup on destination address. So we can | ||||
* fill in out_ifx, dst_mask, nexthop, and dst_as in future releases. | * fill in out_ifx, dst_mask, nexthop, and dst_as in future releases. | ||||
*/ | */ | ||||
if ((flags & NG_NETFLOW_CONF_NODSTLOOKUP) == 0) { | if ((flags & NG_NETFLOW_CONF_NODSTLOOKUP) == 0) { | ||||
bzero(&sin, sizeof(sin)); | struct rtentry *rt; | ||||
sin.sin_len = sizeof(struct sockaddr_in); | struct route_nhop_data rnd; | ||||
sin.sin_family = AF_INET; | |||||
sin.sin_addr = fle->f.r.r_dst; | |||||
rt_gateway.sdl_len = sizeof(rt_gateway); | rt = fib4_lookup_rt(r->fib, fle->f.r.r_dst, 0, NHR_NONE, &rnd); | ||||
sin_mask.sin_len = sizeof(struct sockaddr_in); | if (rt != NULL) { | ||||
bzero(&info, sizeof(info)); | struct in_addr addr; | ||||
uint32_t scopeid; | |||||
struct nhop_object *nh = rnd.rnd_nhop; | |||||
int plen; | |||||
info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&rt_gateway; | rt_get_inet_prefix_plen(rt, &addr, &plen, &scopeid); | ||||
info.rti_info[RTAX_NETMASK] = (struct sockaddr *)&sin_mask; | fle->f.fle_o_ifx = nh->nh_ifp->if_index; | ||||
if (nh->gw_sa.sa_len == AF_INET) | |||||
if (rib_lookup_info(r->fib, (struct sockaddr *)&sin, NHR_REF, 0, | fle->f.next_hop = nh->gw4_sa.sin_addr; | ||||
&info) == 0) { | fle->f.dst_mask = plen; | ||||
fle->f.fle_o_ifx = info.rti_ifp->if_index; | |||||
if (info.rti_flags & RTF_GATEWAY && | |||||
rt_gateway.sdl_family == AF_INET) | |||||
fle->f.next_hop = | |||||
((struct sockaddr_in *)&rt_gateway)->sin_addr; | |||||
if (info.rti_addrs & RTA_NETMASK) | |||||
fle->f.dst_mask = bitcount32(sin_mask.sin_addr.s_addr); | |||||
else if (info.rti_flags & RTF_HOST) | |||||
/* Give up. We can't determine mask :( */ | |||||
fle->f.dst_mask = 32; | |||||
rib_free_info(&info); | |||||
} | } | ||||
} | } | ||||
/* Do route lookup on source address, to fill in src_mask. */ | /* Do route lookup on source address, to fill in src_mask. */ | ||||
if ((flags & NG_NETFLOW_CONF_NOSRCLOOKUP) == 0) { | if ((flags & NG_NETFLOW_CONF_NOSRCLOOKUP) == 0) { | ||||
bzero(&sin, sizeof(sin)); | struct rtentry *rt; | ||||
sin.sin_len = sizeof(struct sockaddr_in); | struct route_nhop_data rnd; | ||||
sin.sin_family = AF_INET; | |||||
sin.sin_addr = fle->f.r.r_src; | |||||
sin_mask.sin_len = sizeof(struct sockaddr_in); | rt = fib4_lookup_rt(r->fib, fle->f.r.r_src, 0, NHR_NONE, &rnd); | ||||
bzero(&info, sizeof(info)); | if (rt != NULL) { | ||||
struct in_addr addr; | |||||
uint32_t scopeid; | |||||
int plen; | |||||
info.rti_info[RTAX_NETMASK] = (struct sockaddr *)&sin_mask; | rt_get_inet_prefix_plen(rt, &addr, &plen, &scopeid); | ||||
fle->f.src_mask = plen; | |||||
if (rib_lookup_info(r->fib, (struct sockaddr *)&sin, 0, 0, | |||||
&info) == 0) { | |||||
if (info.rti_addrs & RTA_NETMASK) | |||||
fle->f.src_mask = | |||||
bitcount32(sin_mask.sin_addr.s_addr); | |||||
else if (info.rti_flags & RTF_HOST) | |||||
/* Give up. We can't determine mask :( */ | |||||
fle->f.src_mask = 32; | |||||
} | } | ||||
} | } | ||||
/* Push new flow at the and of hash. */ | /* Push new flow at the and of hash. */ | ||||
TAILQ_INSERT_TAIL(&hsh->head, fle, fle_hash); | TAILQ_INSERT_TAIL(&hsh->head, fle, fle_hash); | ||||
return (0); | return (0); | ||||
} | } | ||||
#ifdef INET6 | #ifdef INET6 | ||||
static int | static int | ||||
hash6_insert(priv_p priv, struct flow_hash_entry *hsh6, struct flow6_rec *r, | hash6_insert(priv_p priv, struct flow_hash_entry *hsh6, struct flow6_rec *r, | ||||
int plen, uint8_t flags, uint8_t tcp_flags) | int plen, uint8_t flags, uint8_t tcp_flags) | ||||
{ | { | ||||
struct flow6_entry *fle6; | struct flow6_entry *fle6; | ||||
struct sockaddr_in6 sin6, sin6_mask; | |||||
struct sockaddr_dl rt_gateway; | |||||
struct rt_addrinfo info; | |||||
mtx_assert(&hsh6->mtx, MA_OWNED); | mtx_assert(&hsh6->mtx, MA_OWNED); | ||||
fle6 = uma_zalloc_arg(priv->zone6, priv, M_NOWAIT); | fle6 = uma_zalloc_arg(priv->zone6, priv, M_NOWAIT); | ||||
if (fle6 == NULL) { | if (fle6 == NULL) { | ||||
priv->nfinfo_alloc_failed++; | priv->nfinfo_alloc_failed++; | ||||
return (ENOMEM); | return (ENOMEM); | ||||
} | } | ||||
Show All 11 Lines | hash6_insert(priv_p priv, struct flow_hash_entry *hsh6, struct flow6_rec *r, | ||||
fle6->f.first = fle6->f.last = time_uptime; | fle6->f.first = fle6->f.last = time_uptime; | ||||
/* | /* | ||||
* First we do route table lookup on destination address. So we can | * First we do route table lookup on destination address. So we can | ||||
* fill in out_ifx, dst_mask, nexthop, and dst_as in future releases. | * fill in out_ifx, dst_mask, nexthop, and dst_as in future releases. | ||||
*/ | */ | ||||
if ((flags & NG_NETFLOW_CONF_NODSTLOOKUP) == 0) { | if ((flags & NG_NETFLOW_CONF_NODSTLOOKUP) == 0) { | ||||
bzero(&sin6, sizeof(struct sockaddr_in6)); | struct rtentry *rt; | ||||
sin6.sin6_len = sizeof(struct sockaddr_in6); | struct route_nhop_data rnd; | ||||
sin6.sin6_family = AF_INET6; | |||||
sin6.sin6_addr = r->dst.r_dst6; | |||||
rt_gateway.sdl_len = sizeof(rt_gateway); | rt = fib6_lookup_rt(r->fib, &fle6->f.r.dst.r_dst6, 0, NHR_NONE, &rnd); | ||||
sin6_mask.sin6_len = sizeof(struct sockaddr_in6); | if (rt != NULL) { | ||||
bzero(&info, sizeof(info)); | struct in6_addr addr; | ||||
uint32_t scopeid; | |||||
struct nhop_object *nh = rnd.rnd_nhop; | |||||
int plen; | |||||
info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&rt_gateway; | rt_get_inet6_prefix_plen(rt, &addr, &plen, &scopeid); | ||||
info.rti_info[RTAX_NETMASK] = (struct sockaddr *)&sin6_mask; | fle6->f.fle_o_ifx = nh->nh_ifp->if_index; | ||||
if (nh->gw_sa.sa_len == AF_INET6) | |||||
if (rib_lookup_info(r->fib, (struct sockaddr *)&sin6, NHR_REF, | fle6->f.n.next_hop6 = nh->gw6_sa.sin6_addr; | ||||
0, &info) == 0) { | fle6->f.dst_mask = plen; | ||||
fle6->f.fle_o_ifx = info.rti_ifp->if_index; | |||||
if (info.rti_flags & RTF_GATEWAY && | |||||
rt_gateway.sdl_family == AF_INET6) | |||||
fle6->f.n.next_hop6 = | |||||
((struct sockaddr_in6 *)&rt_gateway)->sin6_addr; | |||||
fle6->f.dst_mask = | |||||
ip6_masklen(&sin6_mask.sin6_addr, &info); | |||||
rib_free_info(&info); | |||||
} | } | ||||
} | } | ||||
if ((flags & NG_NETFLOW_CONF_NOSRCLOOKUP) == 0) { | if ((flags & NG_NETFLOW_CONF_NOSRCLOOKUP) == 0) { | ||||
/* Do route lookup on source address, to fill in src_mask. */ | /* Do route lookup on source address, to fill in src_mask. */ | ||||
bzero(&sin6, sizeof(struct sockaddr_in6)); | struct rtentry *rt; | ||||
sin6.sin6_len = sizeof(struct sockaddr_in6); | struct route_nhop_data rnd; | ||||
sin6.sin6_family = AF_INET6; | |||||
sin6.sin6_addr = r->src.r_src6; | |||||
sin6_mask.sin6_len = sizeof(struct sockaddr_in6); | rt = fib6_lookup_rt(r->fib, &fle6->f.r.src.r_src6, 0, NHR_NONE, &rnd); | ||||
bzero(&info, sizeof(info)); | if (rt != NULL) { | ||||
struct in6_addr addr; | |||||
uint32_t scopeid; | |||||
int plen; | |||||
info.rti_info[RTAX_NETMASK] = (struct sockaddr *)&sin6_mask; | rt_get_inet6_prefix_plen(rt, &addr, &plen, &scopeid); | ||||
fle6->f.src_mask = plen; | |||||
if (rib_lookup_info(r->fib, (struct sockaddr *)&sin6, 0, 0, | } | ||||
&info) == 0) | |||||
fle6->f.src_mask = | |||||
ip6_masklen(&sin6_mask.sin6_addr, &info); | |||||
} | } | ||||
/* Push new flow at the and of hash. */ | /* Push new flow at the and of hash. */ | ||||
TAILQ_INSERT_TAIL(&hsh6->head, (struct flow_entry *)fle6, fle_hash); | TAILQ_INSERT_TAIL(&hsh6->head, (struct flow_entry *)fle6, fle_hash); | ||||
return (0); | return (0); | ||||
} | } | ||||
#endif | #endif | ||||
▲ Show 20 Lines • Show All 710 Lines • Show Last 20 Lines |