|
|
|
@ -49,6 +49,7 @@
|
|
|
|
|
#include "util-cpu.h"
|
|
|
|
|
#include "util-debug.h"
|
|
|
|
|
#include "util-device.h"
|
|
|
|
|
#include "util-ebpf.h"
|
|
|
|
|
#include "util-error.h"
|
|
|
|
|
#include "util-privs.h"
|
|
|
|
|
#include "util-optimize.h"
|
|
|
|
@ -222,6 +223,11 @@ typedef struct AFPThreadVars_
|
|
|
|
|
/* data link type for the thread */
|
|
|
|
|
uint32_t datalink;
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_PACKET_EBPF
|
|
|
|
|
int v4_map_fd;
|
|
|
|
|
int v6_map_fd;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
unsigned int frame_offset;
|
|
|
|
|
|
|
|
|
|
ChecksumValidationMode checksum_mode;
|
|
|
|
@ -620,9 +626,17 @@ static int AFPRead(AFPThreadVars *ptv)
|
|
|
|
|
PKT_SET_SRC(p, PKT_SRC_WIRE);
|
|
|
|
|
if (ptv->flags & AFP_BYPASS) {
|
|
|
|
|
p->BypassPacketsFlow = AFPBypassCallback;
|
|
|
|
|
#ifdef HAVE_PACKET_EBPF
|
|
|
|
|
p->afp_v.v4_map_fd = ptv->v4_map_fd;
|
|
|
|
|
p->afp_v.v6_map_fd = ptv->v6_map_fd;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
if (ptv->flags & AFP_XDPBYPASS) {
|
|
|
|
|
p->BypassPacketsFlow = AFPXDPBypassCallback;
|
|
|
|
|
#ifdef HAVE_PACKET_EBPF
|
|
|
|
|
p->afp_v.v4_map_fd = ptv->v4_map_fd;
|
|
|
|
|
p->afp_v.v6_map_fd = ptv->v6_map_fd;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* get timestamp of packet via ioctl */
|
|
|
|
@ -895,9 +909,17 @@ static int AFPReadFromRing(AFPThreadVars *ptv)
|
|
|
|
|
PKT_SET_SRC(p, PKT_SRC_WIRE);
|
|
|
|
|
if (ptv->flags & AFP_BYPASS) {
|
|
|
|
|
p->BypassPacketsFlow = AFPBypassCallback;
|
|
|
|
|
#ifdef HAVE_PACKET_EBPF
|
|
|
|
|
p->afp_v.v4_map_fd = ptv->v4_map_fd;
|
|
|
|
|
p->afp_v.v6_map_fd = ptv->v6_map_fd;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
if (ptv->flags & AFP_XDPBYPASS) {
|
|
|
|
|
p->BypassPacketsFlow = AFPXDPBypassCallback;
|
|
|
|
|
#ifdef HAVE_PACKET_EBPF
|
|
|
|
|
p->afp_v.v4_map_fd = ptv->v4_map_fd;
|
|
|
|
|
p->afp_v.v6_map_fd = ptv->v6_map_fd;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Suricata will treat packet so telling it is busy, this
|
|
|
|
@ -945,6 +967,7 @@ static int AFPReadFromRing(AFPThreadVars *ptv)
|
|
|
|
|
SCReturnInt(AFP_FAILURE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Timestamp */
|
|
|
|
|
p->ts.tv_sec = h.h2->tp_sec;
|
|
|
|
|
p->ts.tv_usec = h.h2->tp_nsec/1000;
|
|
|
|
@ -1013,9 +1036,17 @@ static inline int AFPParsePacketV3(AFPThreadVars *ptv, struct tpacket_block_desc
|
|
|
|
|
PKT_SET_SRC(p, PKT_SRC_WIRE);
|
|
|
|
|
if (ptv->flags & AFP_BYPASS) {
|
|
|
|
|
p->BypassPacketsFlow = AFPBypassCallback;
|
|
|
|
|
#ifdef HAVE_PACKET_EBPF
|
|
|
|
|
p->afp_v.v4_map_fd = ptv->v4_map_fd;
|
|
|
|
|
p->afp_v.v6_map_fd = ptv->v6_map_fd;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
if (ptv->flags & AFP_XDPBYPASS) {
|
|
|
|
|
p->BypassPacketsFlow = AFPXDPBypassCallback;
|
|
|
|
|
#ifdef HAVE_PACKET_EBPF
|
|
|
|
|
p->afp_v.v4_map_fd = ptv->v4_map_fd;
|
|
|
|
|
p->afp_v.v6_map_fd = ptv->v6_map_fd;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ptv->pkts++;
|
|
|
|
@ -2281,13 +2312,7 @@ static int AFPBypassCallback(Packet *p)
|
|
|
|
|
inittime = curtime.tv_sec * 1000000000;
|
|
|
|
|
}
|
|
|
|
|
if (PKT_IS_IPV4(p)) {
|
|
|
|
|
/* FIXME cache this and handle error at cache time*/
|
|
|
|
|
int mapd = EBPFGetMapFDByName("flow_table_v4");
|
|
|
|
|
if (mapd == -1) {
|
|
|
|
|
SCLogNotice("Can't find eBPF map fd for '%s'", "flow_table_v4");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
/* FIXME error handling */
|
|
|
|
|
SCLogDebug("add an IPv4");
|
|
|
|
|
struct flowv4_keys key = {};
|
|
|
|
|
key.src = htonl(GET_IPV4_SRC_ADDR_U32(p));
|
|
|
|
|
key.dst = htonl(GET_IPV4_DST_ADDR_U32(p));
|
|
|
|
@ -2295,14 +2320,14 @@ static int AFPBypassCallback(Packet *p)
|
|
|
|
|
key.port16[1] = GET_TCP_DST_PORT(p);
|
|
|
|
|
|
|
|
|
|
key.ip_proto = IPV4_GET_IPPROTO(p);
|
|
|
|
|
if (AFPInsertHalfFlow(mapd, &key, inittime) == 0) {
|
|
|
|
|
if (AFPInsertHalfFlow(p->afp_v.v4_map_fd, &key, inittime) == 0) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
key.src = htonl(GET_IPV4_DST_ADDR_U32(p));
|
|
|
|
|
key.dst = htonl(GET_IPV4_SRC_ADDR_U32(p));
|
|
|
|
|
key.port16[0] = GET_TCP_DST_PORT(p);
|
|
|
|
|
key.port16[1] = GET_TCP_SRC_PORT(p);
|
|
|
|
|
if (AFPInsertHalfFlow(mapd, &key, inittime) == 0) {
|
|
|
|
|
if (AFPInsertHalfFlow(p->afp_v.v4_map_fd, &key, inittime) == 0) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return 1;
|
|
|
|
@ -2310,16 +2335,8 @@ static int AFPBypassCallback(Packet *p)
|
|
|
|
|
/* For IPv6 case we don't handle extended header in eBPF */
|
|
|
|
|
if (PKT_IS_IPV6(p) &&
|
|
|
|
|
((IPV6_GET_NH(p) == IPPROTO_TCP) || (IPV6_GET_NH(p) == IPPROTO_UDP))) {
|
|
|
|
|
/* FIXME cache this and handle error at cache time*/
|
|
|
|
|
int mapd = EBPFGetMapFDByName("flow_table_v6");
|
|
|
|
|
int i = 0;
|
|
|
|
|
if (mapd == -1) {
|
|
|
|
|
SCLogNotice("Can't find eBPF map fd for '%s'", "flow_table_v6");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
int i;
|
|
|
|
|
SCLogDebug("add an IPv6");
|
|
|
|
|
/* FIXME error handling */
|
|
|
|
|
/* FIXME filter out next hdr IPV6 packets */
|
|
|
|
|
struct flowv6_keys key = {};
|
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
|
key.src[i] = ntohl(GET_IPV6_SRC_ADDR(p)[i]);
|
|
|
|
@ -2328,7 +2345,7 @@ static int AFPBypassCallback(Packet *p)
|
|
|
|
|
key.port16[0] = GET_TCP_SRC_PORT(p);
|
|
|
|
|
key.port16[1] = GET_TCP_DST_PORT(p);
|
|
|
|
|
key.ip_proto = IPV6_GET_NH(p);
|
|
|
|
|
if (AFPInsertHalfFlow(mapd, &key, inittime) == 0) {
|
|
|
|
|
if (AFPInsertHalfFlow(p->afp_v.v6_map_fd, &key, inittime) == 0) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
@ -2337,7 +2354,7 @@ static int AFPBypassCallback(Packet *p)
|
|
|
|
|
}
|
|
|
|
|
key.port16[0] = GET_TCP_DST_PORT(p);
|
|
|
|
|
key.port16[1] = GET_TCP_SRC_PORT(p);
|
|
|
|
|
if (AFPInsertHalfFlow(mapd, &key, inittime) == 0) {
|
|
|
|
|
if (AFPInsertHalfFlow(p->afp_v.v6_map_fd, &key, inittime) == 0) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return 1;
|
|
|
|
@ -2367,13 +2384,6 @@ static int AFPXDPBypassCallback(Packet *p)
|
|
|
|
|
inittime = curtime.tv_sec * 1000000000;
|
|
|
|
|
}
|
|
|
|
|
if (PKT_IS_IPV4(p)) {
|
|
|
|
|
/* FIXME cache this and handle error at cache time*/
|
|
|
|
|
int mapd = EBPFGetMapFDByName("flow_table_v4");
|
|
|
|
|
if (mapd == -1) {
|
|
|
|
|
SCLogNotice("Can't find eBPF map fd for '%s'", "flow_table_v4");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
/* FIXME error handling */
|
|
|
|
|
struct flowv4_keys key = {};
|
|
|
|
|
key.src = GET_IPV4_SRC_ADDR_U32(p);
|
|
|
|
|
key.dst = GET_IPV4_DST_ADDR_U32(p);
|
|
|
|
@ -2381,14 +2391,14 @@ static int AFPXDPBypassCallback(Packet *p)
|
|
|
|
|
key.port16[0] = htons(GET_TCP_SRC_PORT(p));
|
|
|
|
|
key.port16[1] = htons(GET_TCP_DST_PORT(p));
|
|
|
|
|
key.ip_proto = IPV4_GET_IPPROTO(p);
|
|
|
|
|
if (AFPInsertHalfFlow(mapd, &key, inittime) == 0) {
|
|
|
|
|
if (AFPInsertHalfFlow(p->afp_v.v4_map_fd, &key, inittime) == 0) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
key.src = GET_IPV4_DST_ADDR_U32(p);
|
|
|
|
|
key.dst = GET_IPV4_SRC_ADDR_U32(p);
|
|
|
|
|
key.port16[0] = htons(GET_TCP_DST_PORT(p));
|
|
|
|
|
key.port16[1] = htons(GET_TCP_SRC_PORT(p));
|
|
|
|
|
if (AFPInsertHalfFlow(mapd, &key, inittime) == 0) {
|
|
|
|
|
if (AFPInsertHalfFlow(p->afp_v.v4_map_fd, &key, inittime) == 0) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return 1;
|
|
|
|
@ -2396,16 +2406,8 @@ static int AFPXDPBypassCallback(Packet *p)
|
|
|
|
|
/* For IPv6 case we don't handle extended header in eBPF */
|
|
|
|
|
if (PKT_IS_IPV6(p) &&
|
|
|
|
|
((IPV6_GET_NH(p) == IPPROTO_TCP) || (IPV6_GET_NH(p) == IPPROTO_UDP))) {
|
|
|
|
|
/* FIXME cache this and handle error at cache time*/
|
|
|
|
|
int mapd = EBPFGetMapFDByName("flow_table_v6");
|
|
|
|
|
int i = 0;
|
|
|
|
|
if (mapd == -1) {
|
|
|
|
|
SCLogNotice("Can't find eBPF map fd for '%s'", "flow_table_v6");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
SCLogDebug("add an IPv6");
|
|
|
|
|
/* FIXME error handling */
|
|
|
|
|
/* FIXME filter out next hdr IPV6 packets */
|
|
|
|
|
int i;
|
|
|
|
|
struct flowv6_keys key = {};
|
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
|
key.src[i] = GET_IPV6_SRC_ADDR(p)[i];
|
|
|
|
@ -2414,7 +2416,7 @@ static int AFPXDPBypassCallback(Packet *p)
|
|
|
|
|
key.port16[0] = htons(GET_TCP_SRC_PORT(p));
|
|
|
|
|
key.port16[1] = htons(GET_TCP_DST_PORT(p));
|
|
|
|
|
key.ip_proto = IPV6_GET_NH(p);
|
|
|
|
|
if (AFPInsertHalfFlow(mapd, &key, inittime) == 0) {
|
|
|
|
|
if (AFPInsertHalfFlow(p->afp_v.v6_map_fd, &key, inittime) == 0) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
@ -2423,7 +2425,7 @@ static int AFPXDPBypassCallback(Packet *p)
|
|
|
|
|
}
|
|
|
|
|
key.port16[0] = htons(GET_TCP_DST_PORT(p));
|
|
|
|
|
key.port16[1] = htons(GET_TCP_SRC_PORT(p));
|
|
|
|
|
if (AFPInsertHalfFlow(mapd, &key, inittime) == 0) {
|
|
|
|
|
if (AFPInsertHalfFlow(p->afp_v.v6_map_fd, &key, inittime) == 0) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return 1;
|
|
|
|
@ -2499,6 +2501,19 @@ TmEcode ReceiveAFPThreadInit(ThreadVars *tv, const void *initdata, void **data)
|
|
|
|
|
ptv->ebpf_filter_fd = afpconfig->ebpf_filter_fd;
|
|
|
|
|
ptv->xdp_mode = afpconfig->xdp_mode;
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_PACKET_EBPF
|
|
|
|
|
if (ptv->flags & (AFP_BYPASS|AFP_XDPBYPASS)) {
|
|
|
|
|
ptv->v4_map_fd = EBPFGetMapFDByName("flow_table_v4");
|
|
|
|
|
if (ptv->v4_map_fd == -1) {
|
|
|
|
|
SCLogError(SC_ERR_INVALID_VALUE, "Can't find eBPF map fd for '%s'", "flow_table_v4");
|
|
|
|
|
}
|
|
|
|
|
ptv->v6_map_fd = EBPFGetMapFDByName("flow_table_v6");
|
|
|
|
|
if (ptv->v6_map_fd == -1) {
|
|
|
|
|
SCLogError(SC_ERR_INVALID_VALUE, "Can't find eBPF map fd for '%s'", "flow_table_v6");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef PACKET_STATISTICS
|
|
|
|
|
ptv->capture_kernel_packets = StatsRegisterCounter("capture.kernel_packets",
|
|
|
|
|
ptv->tv);
|
|
|
|
|