42#include <sys/counter.h>
43#include <sys/kernel.h>
45#include <sys/limits.h>
46#include <sys/malloc.h>
48#include <sys/socket.h>
49#include <sys/syslog.h>
54#include <net/ethernet.h>
56#include <net/if_arp.h>
57#include <net/if_var.h>
58#include <net/if_vlan_var.h>
60#include <netinet/in.h>
61#include <netinet/in_systm.h>
62#include <netinet/ip.h>
63#include <netinet/ip6.h>
64#include <netinet/tcp.h>
65#include <netinet/udp.h>
66#include <netinet/sctp.h>
247 priv = malloc(
sizeof(*
priv), M_NETGRAPH, M_WAITOK | M_ZERO);
250 priv->maxfibs = rt_numfibs;
252 M_NETGRAPH, M_WAITOK | M_ZERO);
267 callout_init(&
priv->exp_callout, 1);
293 if (!isdigit(*cp) || (cp[0] ==
'0' && cp[1] !=
'\0'))
296 ifnum = (int)strtoul(cp, &eptr, 10);
301 if (
priv->ifaces[ifnum].hook != NULL)
304 iface = &
priv->ifaces[ifnum];
325 if (!isdigit(*cp) || (cp[0] ==
'0' && cp[1] !=
'\0'))
328 ifnum = (int)strtoul(cp, &eptr, 10);
333 if (
priv->ifaces[ifnum].out != NULL)
336 iface = &
priv->ifaces[ifnum];
343 if (
priv->export != NULL)
356 if (
priv->export9 != NULL)
359 priv->export9 = hook;
399 const uint16_t *index;
404 index = (uint16_t *)msg->
data;
409 if (
priv->ifaces[*index].hook == NULL)
415 memcpy((
void *)i, (
void *)&
priv->ifaces[*index].info,
416 sizeof(
priv->ifaces[*index].info));
435 if (
iface->hook == NULL)
440 iface->info.ifinfo_dlt = DLT_EN10MB;
443 iface->info.ifinfo_dlt = DLT_RAW;
465 if (
iface->hook == NULL)
593 struct mbuf *m = NULL, *m_old = NULL;
594 struct ip *ip = NULL;
595 struct ip6_hdr *ip6 = NULL;
597 int pullup_len = 0, off;
598 uint8_t acct = 0, bypass = 0,
flags = 0, upper_proto = 0;
599 int error = 0, l3_off = 0;
600 unsigned int src_if_index;
601 caddr_t upper_ptr = NULL;
605 if ((hook ==
priv->export) || (hook ==
priv->export9)) {
610 log(LOG_ERR,
"ng_netflow: incoming data on export hook!\n");
614 if (hook == iface->
hook) {
618 }
else if (hook == iface->
out) {
625 if ((!bypass) && (iface->
info.
conf &
629 while (mtag != NULL) {
654 m_tag_prepend(
NGI_M(item), mtag);
678#define M_CHECK(length) do { \
679 pullup_len += length; \
680 if (((m)->m_pkthdr.len < (pullup_len)) || \
681 ((pullup_len) > MHLEN)) { \
685 if ((m)->m_len < (pullup_len) && \
686 (((m) = m_pullup((m),(pullup_len))) == NULL)) { \
695 struct ether_header *eh;
698 M_CHECK(
sizeof(
struct ether_header));
699 eh = mtod(m,
struct ether_header *);
702 etype = ntohs(eh->ether_type);
707 eh = mtod(m,
struct ether_header *);
708 ip = (
struct ip *)(eh + 1);
709 l3_off =
sizeof(
struct ether_header);
719 M_CHECK(
sizeof(
struct ip6_hdr));
720 eh = mtod(m,
struct ether_header *);
721 ip6 = (
struct ip6_hdr *)(eh + 1);
722 l3_off =
sizeof(
struct ether_header);
727 struct ether_vlan_header *evh;
729 M_CHECK(
sizeof(
struct ether_vlan_header) -
730 sizeof(
struct ether_header));
731 evh = mtod(m,
struct ether_vlan_header *);
732 etype = ntohs(evh->evl_proto);
733 l3_off =
sizeof(
struct ether_vlan_header);
735 if (etype == ETHERTYPE_IP) {
738 ip = (
struct ip *)(evh + 1);
742 }
else if (etype == ETHERTYPE_IPV6) {
743 M_CHECK(
sizeof(
struct ip6_hdr));
744 ip6 = (
struct ip6_hdr *)(evh + 1);
756 ip = mtod(m,
struct ip *);
765 M_CHECK(
sizeof(
struct ip6_hdr) -
sizeof(
struct ip));
766 ip6 = mtod(m,
struct ip6_hdr *);
780 if ((ip != NULL) && ((ip->ip_off & htons(IP_OFFMASK)) == 0)) {
781 if ((ip->ip_v != IPVERSION) ||
782 ((ip->ip_hl << 2) <
sizeof(
struct ip)))
788 M_CHECK((ip->ip_hl << 2) -
sizeof(
struct ip));
792 upper_proto = ip->ip_p;
800 M_CHECK(
sizeof(
struct tcphdr));
803 M_CHECK(
sizeof(
struct udphdr));
806 M_CHECK(
sizeof(
struct sctphdr));
809 }
else if (ip != NULL) {
815 upper_proto = ip->ip_p;
816 if ((ip->ip_v != IPVERSION) ||
817 ((ip->ip_hl << 2) <
sizeof(
struct ip)))
820 }
else if (ip6 != NULL) {
821 int cur = ip6->ip6_nxt, hdr_off = 0;
822 struct ip6_ext *ip6e;
823 struct ip6_frag *ip6f;
825 if (
priv->export9 == NULL)
832 if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION)
846 M_CHECK(
sizeof(
struct tcphdr));
849 M_CHECK(
sizeof(
struct udphdr));
852 M_CHECK(
sizeof(
struct sctphdr));
856 case IPPROTO_HOPOPTS:
857 case IPPROTO_ROUTING:
858 case IPPROTO_DSTOPTS:
859 M_CHECK(
sizeof(
struct ip6_ext));
860 ip6e = (
struct ip6_ext *)(mtod(m, caddr_t) +
862 upper_proto = ip6e->ip6e_nxt;
863 hdr_off = (ip6e->ip6e_len + 1) << 3;
868 M_CHECK(
sizeof(
struct ip6_ext));
869 ip6e = (
struct ip6_ext *)(mtod(m, caddr_t) +
871 upper_proto = ip6e->ip6e_nxt;
872 hdr_off = (ip6e->ip6e_len + 2) << 2;
875 case IPPROTO_FRAGMENT:
876 M_CHECK(
sizeof(
struct ip6_frag));
877 ip6f = (
struct ip6_frag *)(mtod(m, caddr_t) +
879 upper_proto = ip6f->ip6f_nxt;
880 hdr_off =
sizeof(
struct ip6_frag);
909 priv->nfinfo_realloc_mbuf++;
912 ip = (
struct ip *)(mtod(m, caddr_t) + l3_off);
913 else if (ip6 != NULL)
914 ip6 = (
struct ip6_hdr *)(mtod(m, caddr_t) + l3_off);
917 upper_ptr = (caddr_t)(mtod(m, caddr_t) + off);
922 if (m->m_pkthdr.rcvif != NULL)
923 src_if_index = m->m_pkthdr.rcvif->if_index;
929 if (fib >=
priv->maxfibs) {
930 CTR2(KTR_NET,
"ng_netflow_rcvdata(): packet fib %d is out of "
931 "range of available fibs: 0 .. %d",
949 upper_proto,
flags, src_if_index);
951#if defined(INET6) && defined(INET)
957 upper_proto,
flags, src_if_index);
968 counter_u64_add(
priv->nfinfo_spackets, 1);
969 counter_u64_add(
priv->nfinfo_sbytes,
971 }
else if (ip6 != NULL) {
972 counter_u64_add(
priv->nfinfo_spackets6, 1);
973 counter_u64_add(
priv->nfinfo_sbytes6,
997 callout_drain(&
priv->exp_callout);
1012 free(
priv->fib_data, M_NETGRAPH);
1013 free(
priv, M_NETGRAPH);
1026 if (iface != NULL) {
1027 if (iface->
hook == hook)
1029 if (iface->
out == hook)
1034 if (hook ==
priv->export) {
1035 if (
priv->export9 == NULL)
1036 callout_drain(&
priv->exp_callout);
1037 priv->export = NULL;
1040 if (hook ==
priv->export9) {
1041 if (
priv->export == NULL)
1042 callout_drain(&
priv->exp_callout);
1043 priv->export9 = NULL;
void ng_netflow_cache_flush(priv_p priv)
int ng_netflow_fib_init(priv_p priv, int fib)
int ng_netflow_flow_show(priv_p priv, struct ngnf_show_header *req, struct ngnf_show_header *resp)
void ng_netflow_cache_init(priv_p priv)
void ng_netflow_copyinfo(priv_p priv, struct ng_netflow_info *i)
void ng_netflow_copyv9info(priv_p priv, struct ng_netflow_v9info *i)
#define NG_HOOK_NODE(hook)
int ng_rcvmsg_t(node_p node, item_p item, hook_p lasthook)
#define NG_FWD_ITEM_HOOK(error, item, hook)
int ng_disconnect_t(hook_p hook)
#define NG_NODE_SET_PRIVATE(node, val)
#define NG_RESPOND_MSG(error, here, item, resp)
#define NG_NODE_UNREF(node)
#define NG_HOOK_SET_PRIVATE(hook, val)
int ng_rmnode_self(node_p here)
#define NG_FWD_NEW_DATA(error, item, hook, m)
int ng_close_t(node_p node)
int ng_rcvdata_t(hook_p hook, item_p item)
int ng_shutdown_t(node_p node)
#define NG_FREE_ITEM(item)
int ng_constructor_t(node_p node)
#define NG_NODE_NUMHOOKS(node)
#define NGI_GET_MSG(i, m)
#define NG_NODE_PRIVATE(node)
int ng_newhook_t(node_p node, hook_p hook, const char *name)
#define NG_HOOK_PRIVATE(hook)
#define NG_MKRESPONSE(rsp, msg, len, how)
static const struct ng_parse_struct_field ng_netflow_settemplate_type_fields[]
static const struct ng_parse_struct_field ng_netflow_v9info_type_fields[]
static const struct ng_cmdlist ng_netflow_cmds[]
static ng_newhook_t ng_netflow_newhook
static const struct ng_parse_struct_field ng_netflow_setifindex_type_fields[]
static ng_rcvdata_t ng_netflow_rcvdata
static ng_shutdown_t ng_netflow_rmnode
NETGRAPH_INIT(netflow, &ng_netflow_typestruct)
static struct ng_type ng_netflow_typestruct
static const struct ng_parse_struct_field ng_netflow_settimeouts_type_fields[]
static const struct ng_parse_type ng_netflow_ifinfo_type
static const struct ng_parse_type ng_netflow_setdlt_type
static ng_constructor_t ng_netflow_constructor
static const struct ng_parse_struct_field ng_netflow_ifinfo_type_fields[]
static const struct ng_parse_struct_field ng_netflow_setconfig_type_fields[]
static const struct ng_parse_struct_field ng_netflow_setdlt_type_fields[]
static const struct ng_parse_type ng_netflow_setconfig_type
static const struct ng_parse_type ng_netflow_settimeouts_type
static const struct ng_parse_type ng_netflow_settemplate_type
static const struct ng_parse_type ng_netflow_info_type
static ng_close_t ng_netflow_close
static const struct ng_parse_type ng_netflow_setifindex_type
static const struct ng_parse_type ng_netflow_v9info_type
static ng_rcvmsg_t ng_netflow_rcvmsg
static const struct ng_parse_struct_field ng_netflow_info_type_fields[]
static const struct ng_parse_type ng_netflow_setmtu_type
static const struct ng_parse_struct_field ng_netflow_setmtu_type_fields[]
static ng_disconnect_t ng_netflow_disconnect
#define NG_NETFLOW_SETIFINDEX_TYPE
#define NG_NETFLOW_IFINFO_TYPE
#define NG_NETFLOW_INFO_TYPE
#define NG_NETFLOW_SETTIMEOUTS_TYPE
#define NG_NETFLOW_IS_FRAG
#define NG_NETFLOW_HOOK_EXPORT
#define NG_NETFLOW_CONF_INGRESS
#define NG_NETFLOW_SETDLT_TYPE
#define NG_NETFLOW_SETMTU_TYPE
#define MTAG_NETFLOW_CALLED
callout_func_t ng_netflow_expire
#define priv_to_fib(priv, fib)
#define NG_NETFLOW_HOOK_OUT
#define NG_NETFLOW_CONF_EGRESS
#define NG_NETFLOW_SETTEMPLATE_TYPE
#define NG_NETFLOW_HOOK_EXPORT9
#define NG_NETFLOW_HOOK_DATA
#define NG_NETFLOW_FLOW_FLAGS
#define NG_NETFLOW_CONF_THISONCE
int ng_netflow_flow6_add(priv_p, fib_export_p, struct ip6_hdr *, caddr_t, uint8_t, uint8_t, unsigned int)
#define NG_NETFLOW_CONF_ONCE
@ NGM_NETFLOW_SETTIMEOUTS
@ NGM_NETFLOW_SETTEMPLATE
#define NG_NETFLOW_NODE_TYPE
#define NG_NETFLOW_V9INFO_TYPE
int ng_netflow_flow_add(priv_p, fib_export_p, struct ip *, caddr_t, uint8_t, uint8_t, unsigned int)
#define NGM_NETFLOW_COOKIE
#define NG_NETFLOW_SETCONFIG_TYPE
#define NG_NETFLOW_MAXIFACES
const struct ng_parse_type ng_parse_uint16_type
const struct ng_parse_type ng_parse_struct_type
struct ng_mesg::ng_msghdr header
struct ng_netflow_ifinfo info
uint32_t inactive_timeout