33 #define PCAP_DONT_INCLUDE_PCAP_BPF_H 1 34 #define SC_PCAP_DONT_INCLUDE_PCAP_H 1 64 #include <sys/ioctl.h> 67 #ifdef HAVE_PACKET_EBPF 69 #include <bpf/libbpf.h> 82 #ifdef HAVE_PCAP_PCAP_H 83 #include <pcap/pcap.h> 88 #if HAVE_LINUX_IF_ETHER_H 89 #include <linux/if_ether.h> 92 #if HAVE_LINUX_IF_PACKET_H 93 #include <linux/if_packet.h> 96 #if HAVE_LINUX_IF_ARP_H 97 #include <linux/if_arp.h> 100 #if HAVE_LINUX_FILTER_H 101 #include <linux/filter.h> 105 #include <sys/mman.h> 108 #ifdef HAVE_HW_TIMESTAMPING 109 #include <linux/net_tstamp.h> 116 #ifndef HAVE_AF_PACKET 153 "support for AF_PACKET enabled, on Linux host please recompile " 154 "with --enable-af-packet", tv->
name);
160 #define AFP_IFACE_NAME_LENGTH 48 162 #define AFP_STATE_DOWN 0 163 #define AFP_STATE_UP 1 165 #define AFP_RECONNECT_TIMEOUT 500000 166 #define AFP_DOWN_COUNTER_INTERVAL 40 168 #define POLL_TIMEOUT 100 170 #ifndef TP_STATUS_USER_BUSY 172 #define TP_STATUS_USER_BUSY (1 << 31) 175 #ifndef TP_STATUS_VLAN_VALID 176 #define TP_STATUS_VLAN_VALID (1 << 4) 193 struct tpacket2_hdr *
h2;
194 #ifdef HAVE_TPACKET_V3 195 struct tpacket3_hdr *h3;
200 static int AFPBypassCallback(
Packet *p);
201 static int AFPXDPBypassCallback(
Packet *p);
223 #ifdef HAVE_PACKET_EBPF 279 struct tpacket_req req;
280 #ifdef HAVE_TPACKET_V3 281 struct tpacket_req3 req3;
308 static int AFPGetIfnumByDev(
int fd,
const char *ifname,
int verbose);
309 static int AFPGetDevFlags(
int fd,
const char *ifname);
310 static int AFPDerefSocket(
AFPPeer* peer);
311 static int AFPRefSocket(
AFPPeer* peer);
314 static unsigned int nr_cpus;
367 if (ptv->
mpeer == NULL) {
378 static void AFPPeerClean(
AFPPeer *peer)
398 peerslist.peered = 0;
413 #define AFP_PEERS_MAX_TRY 4 414 #define AFP_PEERS_WAIT 20000 418 if (peerslist.cnt != peerslist.peered) {
442 memset(peer, 0,
sizeof(
AFPPeer));
448 peer->
turn = peerslist.turn++;
474 if (mtu != out_mtu) {
476 "MTU on %s (%d) and %s (%d) are not equal, " 477 "transmission of packets bigger than %d will fail.",
480 (out_mtu > mtu) ? mtu : out_mtu);
482 peerslist.peered += 2;
492 static int AFPPeersListWaitTurn(
AFPPeer *peer)
495 if (peerslist.turn == 0)
503 static void AFPPeersListReachedInc(
void)
505 if (peerslist.turn == 0)
509 SCLogInfo(
"All AFP capture threads are running.");
518 static int AFPPeersListStarted(
void)
520 return !peerslist.turn;
557 static int AFPCreateSocket(
AFPThreadVars *ptv,
char *devname,
int verbose);
561 #ifdef PACKET_STATISTICS 562 struct tpacket_stats kstats;
563 socklen_t
len =
sizeof (
struct tpacket_stats);
564 if (getsockopt(ptv->
socket, SOL_PACKET, PACKET_STATISTICS,
565 &kstats, &len) > -1) {
566 SCLogDebug(
"(%s) Kernel: Packets %" PRIu32
", dropped %" PRIu32
"",
568 kstats.tp_packets, kstats.tp_drops);
592 struct sockaddr_ll from;
595 struct cmsghdr *cmsg;
598 char buf[CMSG_SPACE(
sizeof(
struct tpacket_auxdata))];
600 unsigned char aux_checksum = 0;
602 msg.msg_name = &from;
603 msg.msg_namelen =
sizeof(from);
606 msg.msg_control = &cmsg_buf;
607 msg.msg_controllen =
sizeof(cmsg_buf);
617 caplen = recvmsg(ptv->
socket, &msg, MSG_TRUNC);
632 #ifdef HAVE_PACKET_EBPF 633 p->afp_v.v4_map_fd = ptv->v4_map_fd;
634 p->afp_v.v6_map_fd = ptv->v6_map_fd;
639 #ifdef HAVE_PACKET_EBPF 640 p->afp_v.v4_map_fd = ptv->v4_map_fd;
641 p->afp_v.v6_map_fd = ptv->v6_map_fd;
646 if (ioctl(ptv->
socket, SIOCGSTAMP, &p->
ts) == -1) {
658 SllHdr * hdrp = (SllHdr *)ptv->
data;
660 hdrp->sll_protocol = from.sll_protocol;
669 SCLogDebug(
"pktlen: %" PRIu32
" (pkt %p, pkt data %p)",
689 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
690 struct tpacket_auxdata *aux;
692 if (cmsg->cmsg_len < CMSG_LEN(
sizeof(
struct tpacket_auxdata)) ||
693 cmsg->cmsg_level != SOL_PACKET ||
694 cmsg->cmsg_type != PACKET_AUXDATA)
697 aux = (
struct tpacket_auxdata *)CMSG_DATA(cmsg);
699 if (aux_checksum && (aux->tp_status & TP_STATUS_CSUMNOTREADY)) {
725 struct sockaddr_ll socket_address;
730 uint16_t vlan_tci = 0;
741 if (p->
ethh == NULL) {
746 socket_address.sll_ifindex =
SC_ATOMIC_GET(p->afp_v.peer->if_idx);
748 socket_address.sll_halen = ETH_ALEN;
750 memcpy(socket_address.sll_addr, p->
ethh, 6);
757 h.
raw = p->afp_v.relptr;
759 if (version == TPACKET_V2) {
764 vlan_tci = h.
h2->tp_vlan_tci;
767 #ifdef HAVE_TPACKET_V3 769 vlan_tci = h.h3->hv1.tp_vlan_tci;
783 *(uint16_t *)(pstart + 2 * ETH_ALEN) = htons(0x8100);
784 *(uint16_t *)(pstart + 2 * ETH_ALEN + 2) = htons(vlan_tci);
790 if (sendto(socket, pstart, plen, 0,
791 (
struct sockaddr*) &socket_address,
792 sizeof(
struct sockaddr_ll)) < 0) {
806 static void AFPReleaseDataFromRing(
Packet *p)
811 AFPWritePacket(p, TPACKET_V2);
814 if (AFPDerefSocket(p->afp_v.mpeer) == 0)
817 if (p->afp_v.relptr) {
819 h.
raw = p->afp_v.relptr;
820 h.
h2->tp_status = TP_STATUS_KERNEL;
827 #ifdef HAVE_TPACKET_V3 828 static void AFPReleasePacketV3(
Packet *p)
833 AFPWritePacket(p, TPACKET_V3);
839 static void AFPReleasePacket(
Packet *p)
841 AFPReleaseDataFromRing(p);
858 uint8_t emergency_flush = 0;
878 if (read_pkts == 0) {
879 if (loop_start == -1) {
906 h.
h2->tp_status = TP_STATUS_KERNEL;
917 #ifdef HAVE_PACKET_EBPF 918 p->afp_v.v4_map_fd = ptv->v4_map_fd;
919 p->afp_v.v6_map_fd = ptv->v6_map_fd;
924 #ifdef HAVE_PACKET_EBPF 925 p->afp_v.v4_map_fd = ptv->v4_map_fd;
926 p->afp_v.v6_map_fd = ptv->v6_map_fd;
939 if (h.
h2->tp_len > h.
h2->tp_snaplen) {
940 SCLogDebug(
"Packet length (%d) > snaplen (%d), truncating",
941 h.
h2->tp_len, h.
h2->tp_snaplen);
947 p->
vlan_id[0] = h.
h2->tp_vlan_tci & 0x0fff;
957 p->afp_v.relptr = h.
raw;
959 p->afp_v.mpeer = ptv->
mpeer;
960 AFPRefSocket(ptv->
mpeer);
966 p->afp_v.peer = NULL;
974 h.
h2->tp_status = TP_STATUS_KERNEL;
984 p->
ts.tv_sec = h.
h2->tp_sec;
985 p->
ts.tv_usec = h.
h2->tp_nsec/1000;
986 SCLogDebug(
"pktlen: %" PRIu32
" (pkt %p, pkt data %p)",
1002 if (h.
h2->tp_status & TP_STATUS_CSUMNOTREADY) {
1006 if (h.
h2->tp_status & TP_STATUS_LOSING) {
1007 emergency_flush = 1;
1008 AFPDumpCounters(ptv);
1013 h.
h2->tp_status = TP_STATUS_KERNEL;
1017 h.
h2->tp_status = TP_STATUS_KERNEL;
1036 #ifdef HAVE_TPACKET_V3 1037 static inline void AFPFlushBlock(
struct tpacket_block_desc *pbd)
1039 pbd->hdr.bh1.block_status = TP_STATUS_KERNEL;
1042 static inline int AFPParsePacketV3(
AFPThreadVars *ptv,
struct tpacket_block_desc *pbd,
struct tpacket3_hdr *ppd)
1051 #ifdef HAVE_PACKET_EBPF 1052 p->afp_v.v4_map_fd = ptv->v4_map_fd;
1053 p->afp_v.v6_map_fd = ptv->v6_map_fd;
1057 #ifdef HAVE_PACKET_EBPF 1058 p->afp_v.v4_map_fd = ptv->v4_map_fd;
1059 p->afp_v.v6_map_fd = ptv->v6_map_fd;
1069 p->
vlan_id[0] = ppd->hv1.tp_vlan_tci & 0x0fff;
1075 if (
PacketSetData(p, (
unsigned char*)ppd + ppd->tp_mac, ppd->tp_snaplen) == -1) {
1079 p->afp_v.relptr = ppd;
1081 p->afp_v.mpeer = ptv->
mpeer;
1082 AFPRefSocket(ptv->
mpeer);
1088 p->afp_v.peer = NULL;
1091 if (
PacketCopyData(p, (
unsigned char*)ppd + ppd->tp_mac, ppd->tp_snaplen) == -1) {
1097 p->
ts.tv_sec = ppd->tp_sec;
1098 p->
ts.tv_usec = ppd->tp_nsec/1000;
1099 SCLogDebug(
"pktlen: %" PRIu32
" (pkt %p, pkt data %p)",
1115 if (ppd->tp_status & TP_STATUS_CSUMNOTREADY) {
1128 static inline int AFPWalkBlock(
AFPThreadVars *ptv,
struct tpacket_block_desc *pbd)
1130 int num_pkts = pbd->hdr.bh1.num_pkts, i;
1134 ppd = (uint8_t *)pbd + pbd->hdr.bh1.offset_to_first_pkt;
1135 for (i = 0; i < num_pkts; ++i) {
1136 ret = AFPParsePacketV3(ptv, pbd,
1137 (
struct tpacket3_hdr *)ppd);
1150 ppd = ppd + ((
struct tpacket3_hdr *)ppd)->tp_next_offset;
1168 #ifdef HAVE_TPACKET_V3 1169 struct tpacket_block_desc *pbd;
1182 if ((pbd->hdr.bh1.block_status & TP_STATUS_USER) == 0) {
1186 ret = AFPWalkBlock(ptv, pbd);
1208 static int AFPRefSocket(
AFPPeer* peer)
1223 static int AFPDerefSocket(
AFPPeer* peer)
1247 #ifdef HAVE_TPACKET_V3 1260 #ifdef HAVE_TPACKET_V3 1278 static int AFPReadAndDiscard(
AFPThreadVars *ptv,
struct timeval *synctv,
1279 uint64_t *discarded_pkts)
1281 struct sockaddr_ll from;
1286 struct cmsghdr cmsg;
1287 char buf[CMSG_SPACE(
sizeof(
struct tpacket_auxdata))];
1295 msg.msg_name = &from;
1296 msg.msg_namelen =
sizeof(from);
1299 msg.msg_control = &cmsg_buf;
1300 msg.msg_controllen =
sizeof(cmsg_buf);
1304 iov.iov_base = ptv->
data;
1306 (void)recvmsg(ptv->
socket, &msg, MSG_TRUNC);
1308 if (ioctl(ptv->
socket, SIOCGSTAMP, &ts) == -1) {
1313 if ((ts.tv_sec > synctv->tv_sec) ||
1314 (ts.tv_sec >= synctv->tv_sec &&
1315 ts.tv_usec > synctv->tv_usec)) {
1321 static int AFPReadAndDiscardFromRing(
AFPThreadVars *ptv,
struct timeval *synctv,
1322 uint64_t *discarded_pkts)
1330 #ifdef HAVE_TPACKET_V3 1333 struct tpacket_block_desc *pbd;
1335 *discarded_pkts += pbd->hdr.bh1.num_pkts;
1336 struct tpacket3_hdr *ppd =
1337 (
struct tpacket3_hdr *)((uint8_t *)pbd + pbd->hdr.bh1.offset_to_first_pkt);
1338 if (((time_t)ppd->tp_sec > synctv->tv_sec) ||
1339 ((time_t)ppd->tp_sec == synctv->tv_sec &&
1340 (suseconds_t) (ppd->tp_nsec / 1000) > (suseconds_t)synctv->tv_usec)) {
1352 if (h.
raw == NULL) {
1355 (*discarded_pkts)++;
1356 if (((time_t)h.
h2->tp_sec > synctv->tv_sec) ||
1357 ((time_t)h.
h2->tp_sec == synctv->tv_sec &&
1358 (suseconds_t) (h.
h2->tp_nsec / 1000) > synctv->tv_usec)) {
1362 h.
h2->tp_status = TP_STATUS_KERNEL;
1381 static int AFPSynchronizeStart(
AFPThreadVars *ptv, uint64_t *discarded_pkts)
1383 struct timeval synctv;
1387 fds.events = POLLIN;
1390 synctv.tv_sec = 0xffffffff;
1391 synctv.tv_usec = 0xffffffff;
1396 (fds.revents & (POLLHUP|POLLRDHUP|POLLERR|POLLNVAL))) {
1398 fds.revents & (POLLHUP|POLLRDHUP|POLLERR|POLLNVAL));
1401 if (AFPPeersListStarted() && synctv.tv_sec == (time_t) 0xffffffff) {
1402 gettimeofday(&synctv, NULL);
1405 r = AFPReadAndDiscardFromRing(ptv, &synctv, discarded_pkts);
1407 r = AFPReadAndDiscard(ptv, &synctv, discarded_pkts);
1418 }
else if (r == 0 && AFPPeersListStarted()) {
1444 int afp_activate_r = AFPCreateSocket(ptv, ptv->
iface, 0);
1445 if (afp_activate_r != 0) {
1450 return afp_activate_r;
1468 time_t last_dump = 0;
1469 time_t current_time;
1471 uint64_t discarded_pkts = 0;
1477 AFPReadFunc = AFPReadFromRingV3;
1479 AFPReadFunc = AFPReadFromRing;
1482 AFPReadFunc = AFPRead;
1487 while (AFPPeersListWaitTurn(ptv->
mpeer)) {
1493 r = AFPCreateSocket(ptv, ptv->
iface, 1);
1503 AFPPeersListReachedInc();
1507 AFPSynchronizeStart(ptv, &discarded_pkts);
1510 #ifdef PACKET_STATISTICS 1511 struct tpacket_stats kstats;
1512 socklen_t
len =
sizeof (
struct tpacket_stats);
1513 if (getsockopt(ptv->
socket, SOL_PACKET, PACKET_STATISTICS,
1514 &kstats, &len) > -1) {
1516 SCLogDebug(
"(%s) Kernel socket startup: Packets %" PRIu32
1517 ", dropped %" PRIu32
"",
1519 kstats.tp_packets, kstats.tp_drops);
1520 pkts = kstats.tp_packets - discarded_pkts - kstats.tp_drops;
1528 fds.events = POLLIN;
1541 r = AFPTryReopen(ptv);
1559 (fds.revents & (POLLHUP|POLLRDHUP|POLLERR|POLLNVAL))) {
1560 if (fds.revents & (POLLHUP | POLLRDHUP)) {
1563 }
else if (fds.revents & POLLERR) {
1566 if (recv(ptv->
socket, &c,
sizeof c, MSG_PEEK) != -1)
1569 "Error reading data from iface '%s': (%d) %s",
1570 ptv->
iface, errno, strerror(errno));
1573 }
else if (fds.revents & POLLNVAL) {
1579 r = AFPReadFunc(ptv);
1583 current_time = time(NULL);
1584 if (current_time != last_dump) {
1585 AFPDumpCounters(ptv);
1586 last_dump = current_time;
1592 "AFPRead error reading data from iface '%s': (%d) %s",
1593 ptv->
iface, errno, strerror(errno));
1600 AFPDumpCounters(ptv);
1605 current_time = time(NULL);
1606 if (current_time != last_dump) {
1607 AFPDumpCounters(ptv);
1608 last_dump = current_time;
1611 TmThreadsCaptureInjectPacket(tv, ptv->
slot, NULL);
1613 }
else if ((r < 0) && (errno != EINTR)) {
1616 errno, strerror(errno));
1623 AFPDumpCounters(ptv);
1628 static int AFPGetDevFlags(
int fd,
const char *ifname)
1632 memset(&ifr, 0,
sizeof(ifr));
1633 strlcpy(ifr.ifr_name, ifname,
sizeof(ifr.ifr_name));
1635 if (ioctl(fd, SIOCGIFFLAGS, &ifr) == -1) {
1637 ifname, strerror(errno));
1641 return ifr.ifr_flags;
1645 static int AFPGetIfnumByDev(
int fd,
const char *ifname,
int verbose)
1649 memset(&ifr, 0,
sizeof(ifr));
1650 strlcpy(ifr.ifr_name, ifname,
sizeof(ifr.ifr_name));
1652 if (ioctl(fd, SIOCGIFINDEX, &ifr) == -1) {
1655 ifname, strerror(errno));
1659 return ifr.ifr_ifindex;
1662 static int AFPGetDevLinktype(
int fd,
const char *ifname)
1666 memset(&ifr, 0,
sizeof(ifr));
1667 strlcpy(ifr.ifr_name, ifname,
sizeof(ifr.ifr_name));
1669 if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) {
1671 ifname, strerror(errno));
1675 switch (ifr.ifr_hwaddr.sa_family) {
1676 case ARPHRD_LOOPBACK:
1682 return ifr.ifr_hwaddr.sa_family;
1690 int fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
1696 ltype = AFPGetDevLinktype(fd, ifname);
1702 static int AFPComputeRingParams(
AFPThreadVars *ptv,
int order)
1727 int tp_hdrlen =
sizeof(
struct tpacket_hdr);
1734 "Unable to get MTU, setting snaplen to sane default of 1514");
1739 ptv->
req.tp_frame_size = TPACKET_ALIGN(snaplen +TPACKET_ALIGN(TPACKET_ALIGN(tp_hdrlen) +
sizeof(
struct sockaddr_ll) + ETH_HLEN) - ETH_HLEN);
1740 ptv->
req.tp_block_size = getpagesize() << order;
1741 int frames_per_block = ptv->
req.tp_block_size / ptv->
req.tp_frame_size;
1742 if (frames_per_block == 0) {
1747 ptv->
req.tp_block_nr = ptv->
req.tp_frame_nr / frames_per_block + 1;
1749 ptv->
req.tp_frame_nr = ptv->
req.tp_block_nr * frames_per_block;
1750 SCLogPerf(
"AF_PACKET RX Ring params: block_size=%d block_nr=%d frame_size=%d frame_nr=%d",
1751 ptv->
req.tp_block_size, ptv->
req.tp_block_nr,
1752 ptv->
req.tp_frame_size, ptv->
req.tp_frame_nr);
1756 #ifdef HAVE_TPACKET_V3 1760 ptv->req3.tp_frame_size = 2048;
1761 int frames_per_block = 0;
1762 int tp_hdrlen =
sizeof(
struct tpacket3_hdr);
1769 "Unable to get MTU, setting snaplen to sane default of 1514");
1774 ptv->
req.tp_frame_size = TPACKET_ALIGN(snaplen +TPACKET_ALIGN(TPACKET_ALIGN(tp_hdrlen) +
sizeof(
struct sockaddr_ll) + ETH_HLEN) - ETH_HLEN);
1775 frames_per_block = ptv->req3.tp_block_size / ptv->req3.tp_frame_size;
1777 if (frames_per_block == 0) {
1779 "Block size is too small, it should be at least %d",
1780 ptv->req3.tp_frame_size);
1783 ptv->req3.tp_block_nr = ptv->
ring_size / frames_per_block + 1;
1785 ptv->req3.tp_frame_nr = ptv->req3.tp_block_nr * frames_per_block;
1787 ptv->req3.tp_feature_req_word = TP_FT_REQ_FILL_RXHASH;
1788 SCLogPerf(
"AF_PACKET V3 RX Ring params: block_size=%d block_nr=%d frame_size=%d frame_nr=%d (mem: %d)",
1789 ptv->req3.tp_block_size, ptv->req3.tp_block_nr,
1790 ptv->req3.tp_frame_size, ptv->req3.tp_frame_nr,
1791 ptv->req3.tp_block_size * ptv->req3.tp_block_nr
1800 unsigned int len =
sizeof(val), i;
1804 #ifdef HAVE_TPACKET_V3 1812 if (getsockopt(ptv->
socket, SOL_PACKET, PACKET_HDRLEN, &val, &len) < 0) {
1813 if (errno == ENOPROTOOPT) {
1816 "Too old kernel giving up (need 3.2 for TPACKET_V3)");
1819 "Too old kernel giving up (need 2.6.27 at least)");
1827 #ifdef HAVE_TPACKET_V3 1832 if (setsockopt(ptv->
socket, SOL_PACKET, PACKET_VERSION, &val,
1835 "Can't activate TPACKET_V2/TPACKET_V3 on packet socket: %s",
1840 #ifdef HAVE_HW_TIMESTAMPING 1841 int req = SOF_TIMESTAMPING_RAW_HARDWARE;
1842 if (setsockopt(ptv->
socket, SOL_PACKET, PACKET_TIMESTAMP, (
void *) &req,
1845 "Can't activate hardware timestamping on packet socket: %s",
1856 if (setsockopt(ptv->
socket, SOL_PACKET, PACKET_RESERVE, (
void *) &reserve,
1857 sizeof(reserve)) < 0) {
1859 "Can't activate reserve on packet socket: %s",
1866 #ifdef HAVE_TPACKET_V3 1868 if (AFPComputeRingParamsV3(ptv) != 1) {
1871 r = setsockopt(ptv->
socket, SOL_PACKET, PACKET_RX_RING,
1872 (
void *) &ptv->req3,
sizeof(ptv->req3));
1875 "Unable to allocate RX Ring for iface %s: (%d) %s",
1884 if (AFPComputeRingParams(ptv, order) != 1) {
1885 SCLogInfo(
"Ring parameter are incorrect. Please correct the devel");
1889 r = setsockopt(ptv->
socket, SOL_PACKET, PACKET_RX_RING,
1890 (
void *) &ptv->
req,
sizeof(ptv->
req));
1893 if (errno == ENOMEM) {
1894 SCLogInfo(
"Memory issue with ring parameters. Retrying.");
1898 "Unable to allocate RX Ring for iface %s: (%d) %s",
1909 "Unable to allocate RX Ring for iface %s (order 0 failed)",
1913 #ifdef HAVE_TPACKET_V3 1918 #ifdef HAVE_TPACKET_V3 1920 ptv->
ring_buflen = ptv->req3.tp_block_nr * ptv->req3.tp_block_size;
1924 #ifdef HAVE_TPACKET_V3 1927 mmap_flag = MAP_SHARED;
1929 mmap_flag |= MAP_LOCKED;
1931 mmap_flag, ptv->
socket, 0);
1937 #ifdef HAVE_TPACKET_V3 1944 for (i = 0; i < ptv->req3.tp_block_nr; ++i) {
1945 ptv->
ring_v3[i].iov_base = ptv->
ring_buf + (i * ptv->req3.tp_block_size);
1946 ptv->
ring_v3[i].iov_len = ptv->req3.tp_block_size;
1956 memset(ptv->
ring_v2, 0, ptv->
req.tp_frame_nr * sizeof (
union thdr *));
1959 for (i = 0; i < ptv->
req.tp_block_nr; ++i) {
1960 void *base = &(ptv->
ring_buf[i * ptv->
req.tp_block_size]);
1962 for (j = 0; j < ptv->
req.tp_block_size / ptv->
req.tp_frame_size; ++j, ++ptv->
frame_offset) {
1964 base += ptv->
req.tp_frame_size;
1968 #ifdef HAVE_TPACKET_V3 1990 #ifdef HAVE_PACKET_FANOUT 1991 int fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
1997 uint32_t option = (mode << 16) | (
id & 0xffff);
1998 int r = setsockopt(fd, SOL_PACKET,
PACKET_FANOUT,(
void *)&option,
sizeof(option));
2002 SCLogPerf(
"fanout not supported by kernel: %s", strerror(errno));
2011 #ifdef HAVE_PACKET_EBPF 2018 "Fanout file descriptor is invalid");
2022 if (setsockopt(ptv->
socket, SOL_PACKET, PACKET_FANOUT_DATA, &pfd,
sizeof(pfd))) {
2036 "Filter file descriptor is invalid");
2040 if (setsockopt(ptv->
socket, SOL_SOCKET, SO_ATTACH_BPF, &pfd,
sizeof(pfd))) {
2044 SCLogInfo(
"Activated eBPF filter on socket");
2050 static int AFPCreateSocket(
AFPThreadVars *ptv,
char *devname,
int verbose)
2054 struct packet_mreq sock_params;
2055 struct sockaddr_ll bind_address;
2059 ptv->
socket = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
2065 if_idx = AFPGetIfnumByDev(ptv->
socket, devname, verbose);
2072 memset(&bind_address, 0,
sizeof(bind_address));
2073 bind_address.sll_family = AF_PACKET;
2074 bind_address.sll_protocol = htons(ETH_P_ALL);
2075 bind_address.sll_ifindex = if_idx;
2076 if (bind_address.sll_ifindex == -1) {
2083 int if_flags = AFPGetDevFlags(ptv->
socket, ptv->
iface);
2084 if (if_flags == -1) {
2087 "Couldn't get flags for interface '%s'",
2092 }
else if ((if_flags & (IFF_UP | IFF_RUNNING)) == 0) {
2095 "Interface '%s' is down",
2104 memset(&sock_params, 0,
sizeof(sock_params));
2105 sock_params.mr_type = PACKET_MR_PROMISC;
2106 sock_params.mr_ifindex = bind_address.sll_ifindex;
2107 r = setsockopt(ptv->
socket, SOL_PACKET, PACKET_ADD_MEMBERSHIP,(
void *)&sock_params,
sizeof(sock_params));
2110 "Couldn't switch iface %s to promiscuous, error %s",
2111 devname, strerror(errno));
2118 if (setsockopt(ptv->
socket, SOL_PACKET, PACKET_AUXDATA, &val,
2119 sizeof(val)) == -1 && errno != ENOPROTOOPT) {
2121 "'kernel' checksum mode not supported, falling back to full mode.");
2132 if (setsockopt(ptv->
socket, SOL_SOCKET, SO_RCVBUF,
2136 "Couldn't set buffer size to %d on iface %s, error %s",
2142 r = bind(ptv->
socket, (
struct sockaddr *)&bind_address,
sizeof(bind_address));
2145 if (errno == ENETDOWN) {
2147 "Couldn't bind AF_PACKET socket, iface %s is down",
2151 "Couldn't bind AF_PACKET socket to iface %s, error %s",
2152 devname, strerror(errno));
2160 #ifdef HAVE_PACKET_FANOUT 2165 uint32_t option = (mode << 16) | (
id & 0xffff);
2169 "Couldn't set fanout mode, error %s",
2176 #ifdef HAVE_PACKET_EBPF 2178 r = SockFanoutSeteBPF(ptv);
2181 "Coudn't set EBPF, error %s",
2189 ret = AFPSetupRing(ptv, devname);
2194 SCLogDebug(
"Using interface '%s' via socket %d", (
char *)devname, ptv->
socket);
2236 struct sock_fprog fcode;
2239 #ifdef HAVE_PACKET_EBPF 2241 return SetEbpfFilter(ptv);
2248 SCLogInfo(
"Using BPF '%s' on iface '%s'",
2252 char errbuf[PCAP_ERRBUF_SIZE];
2260 sizeof(errbuf)) == -1) {
2267 fcode.len = filter.
bf_len;
2268 fcode.filter = (
struct sock_filter*)filter.
bf_insns;
2270 rc = setsockopt(ptv->
socket, SOL_SOCKET, SO_ATTACH_FILTER, &fcode,
sizeof(fcode));
2281 #ifdef HAVE_PACKET_EBPF 2290 static int AFPInsertHalfFlow(
int mapd,
void *key, uint64_t inittime)
2292 struct pair value[nr_cpus];
2301 for (i = 0; i < nr_cpus; i++) {
2302 value[i].time = inittime;
2303 value[i].packets = 0;
2306 SCLogDebug(
"Inserting element in eBPF mapping: %lu", inittime);
2307 if (bpf_map_update_elem(mapd, key, value, BPF_NOEXIST) != 0) {
2341 static int AFPBypassCallback(
Packet *p)
2343 #ifdef HAVE_PACKET_EBPF 2344 SCLogDebug(
"Calling af_packet callback function");
2356 struct timespec curtime;
2357 uint64_t inittime = 0;
2361 if (clock_gettime(CLOCK_MONOTONIC, &curtime) == 0) {
2362 inittime = curtime.tv_sec * 1000000000;
2366 if (p->afp_v.v4_map_fd == -1) {
2369 struct flowv4_keys key = {};
2376 if (AFPInsertHalfFlow(p->afp_v.v4_map_fd, &key, inittime) == 0) {
2383 if (AFPInsertHalfFlow(p->afp_v.v4_map_fd, &key, inittime) == 0) {
2386 EBPFUpdateFlow(p->
flow, p);
2393 if (p->afp_v.v6_map_fd == -1) {
2397 struct flowv6_keys key = {};
2398 for (i = 0; i < 4; i++) {
2405 if (AFPInsertHalfFlow(p->afp_v.v6_map_fd, &key, inittime) == 0) {
2408 for (i = 0; i < 4; i++) {
2414 if (AFPInsertHalfFlow(p->afp_v.v6_map_fd, &key, inittime) == 0) {
2417 EBPFUpdateFlow(p->
flow, p);
2435 static int AFPXDPBypassCallback(
Packet *p)
2437 #ifdef HAVE_PACKET_XDP 2438 SCLogDebug(
"Calling af_packet callback function");
2450 struct timespec curtime;
2451 uint64_t inittime = 0;
2455 if (clock_gettime(CLOCK_MONOTONIC, &curtime) == 0) {
2456 inittime = curtime.tv_sec * 1000000000;
2459 struct flowv4_keys key = {};
2460 if (p->afp_v.v4_map_fd == -1) {
2470 if (AFPInsertHalfFlow(p->afp_v.v4_map_fd, &key, inittime) == 0) {
2477 if (AFPInsertHalfFlow(p->afp_v.v4_map_fd, &key, inittime) == 0) {
2486 if (p->afp_v.v6_map_fd == -1) {
2490 struct flowv6_keys key = {};
2491 for (i = 0; i < 4; i++) {
2498 if (AFPInsertHalfFlow(p->afp_v.v6_map_fd, &key, inittime) == 0) {
2501 for (i = 0; i < 4; i++) {
2507 if (AFPInsertHalfFlow(p->afp_v.v6_map_fd, &key, inittime) == 0) {
2530 if (initdata == NULL) {
2564 #ifdef HAVE_PACKET_FANOUT 2583 #ifdef HAVE_PACKET_EBPF 2585 ptv->v4_map_fd = EBPFGetMapFDByName(ptv->
iface,
"flow_table_v4");
2586 if (ptv->v4_map_fd == -1) {
2589 ptv->v6_map_fd = EBPFGetMapFDByName(ptv->
iface,
"flow_table_v6");
2590 if (ptv->v6_map_fd == -1) {
2596 #ifdef PACKET_STATISTICS 2612 " in dropping all non matching packets.");
2623 #define T_DATA_SIZE 70000 2625 if (ptv->
data == NULL) {
2633 *data = (
void *)ptv;
2641 if ((
ConfGetBool(
"vlan.use-for-tracking", &vlanbool)) == 1 && vlanbool == 0) {
2665 #ifdef PACKET_STATISTICS 2666 AFPDumpCounters(ptv);
2667 SCLogPerf(
"(%s) Kernel: Packets %" PRIu64
", dropped %" PRIu64
"",
2685 #ifdef HAVE_PACKET_XDP 2688 if (ptv->
data != NULL) {
2775 *data = (
void *)dtv;
ChecksumValidationMode checksum_mode
char iface[AFP_IFACE_NAME_LENGTH]
#define GET_IPV4_SRC_ADDR_U32(p)
TmEcode AFPPeersListInit()
Init the global list of AFPPeer.
#define TM_FLAG_DECODE_TM
DecodeThreadVars * DecodeThreadVarsAlloc(ThreadVars *tv)
Alloc and setup DecodeThreadVars.
void TmModuleDecodeAFPRegister(void)
Registration Function for DecodeAFP.
int(* BypassPacketsFlow)(struct Packet_ *)
#define AFP_BLOCK_SIZE_DEFAULT_ORDER
#define SCMutexDestroy(x)
#define TAILQ_FIRST(head)
#define SC_ATOMIC_DECLARE(type, name)
wrapper to declare an atomic variable including a (spin) lock to protect it.
uint16_t UtilCpuGetNumProcessorsConfigured(void)
Get the number of cpus configured in the system.
#define TAILQ_FOREACH(var, head, field)
struct HtpBodyChunk_ * next
uint16_t capture_kernel_packets
size_t strlcpy(char *dst, const char *src, size_t siz)
#define LINKTYPE_LINUX_SLL
int DecodePPP(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq)
#define PACKET_TEST_ACTION(p, a)
struct bpf_insn * bf_insns
#define SET_PKT_LEN(p, len)
TmEcode AFPPeersListCheck()
Check that all AFPPeer got a peer.
Structure to hold thread specific variables.
#define AFP_RECONNECT_TIMEOUT
void PacketDecodeFinalize(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p)
Finalize decoding of a packet.
#define IPV4_GET_IPPROTO(p)
int AFPGetLinkType(const char *ifname)
void AFPPeersListClean()
Clean the global peers list.
struct AFPPeersList_ AFPPeersList
int DecodeRaw(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq)
TmEcode(* Func)(ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *)
int ConfGetBool(const char *name, int *val)
Retrieve a configuration value as an boolen.
#define GET_IPV4_DST_ADDR_U32(p)
char iface[AFP_IFACE_NAME_LENGTH]
void DecodeRegisterPerfCounters(DecodeThreadVars *dtv, ThreadVars *tv)
TmEcode ReceiveAFP(ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *)
int GetIfaceMaxPacketSize(const char *pcap_dev)
output max packet size for a link
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
#define TP_STATUS_VLAN_VALID
uint16_t capture_kernel_drops
volatile uint8_t suricata_ctl_flags
#define SC_ATOMIC_SUB(name, val)
sub a value from our atomic variable
#define TAILQ_HEAD(name, type)
int AFPIsFanoutSupported(void)
test if we can use FANOUT. Older kernels like those in CentOS6 have HAVE_PACKET_FANOUT defined but fa...
int DecodeNull(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq)
Packet * PacketGetFromQueueOrAlloc(void)
Get a packet. We try to get a packet from the packetpool first, but if that is empty we alloc a packe...
TmEcode(* PktAcqLoop)(ThreadVars *, void *, void *)
void(* ReleasePacket)(struct Packet_ *)
void PacketFreeOrRelease(Packet *p)
Return a packet to where it was allocated.
#define SC_ATOMIC_DESTROY(name)
Destroy the lock used to protect this variable.
#define PKT_SET_SRC(p, src_val)
int SCKernelVersionIsAtLeast(int major, int minor)
#define TM_FLAG_RECEIVE_TM
TmEcode(* PktAcqBreakLoop)(ThreadVars *, void *)
uint16_t StatsRegisterCounter(const char *name, struct ThreadVars_ *tv)
Registers a normal, unqualified counter.
#define SC_ATOMIC_INIT(name)
Initialize the previously declared atomic variable and it's lock.
#define SCMutexUnlock(mut)
#define AFP_COPY_MODE_NONE
void TmqhOutputPacketpool(ThreadVars *t, Packet *p)
TmEcode ReceiveAFPLoop(ThreadVars *tv, void *data, void *slot)
Main AF_PACKET reading Loop function.
TmEcode ReceiveAFPThreadDeinit(ThreadVars *, void *)
DeInit function closes af packet socket at exit.
#define PACKET_FANOUT_HASH
#define SCMutexInit(mut, mutattr)
#define GET_IPV6_DST_ADDR(p)
void TmModuleReceiveAFPRegister(void)
Registration Function for RecieveAFP.
int DecodeEthernet(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq)
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
TmEcode ReceiveAFPThreadInit(ThreadVars *, const void *, void **)
Init function for ReceiveAFP.
Structure to hold thread specific data for all decode modules.
#define TAILQ_REMOVE(head, elm, field)
void(* RegisterTests)(void)
TmEcode(* ThreadDeinit)(ThreadVars *, void *)
#define AFP_DOWN_COUNTER_INTERVAL
int GetIfaceMTU(const char *pcap_dev)
output the link MTU
struct TmSlot_ * slot_next
int SCBPFCompile(int snaplen_arg, int linktype_arg, struct bpf_program *program, const char *buf, int optimize, uint32_t mask, char *errbuf, size_t errbuf_len)
void StatsIncr(ThreadVars *tv, uint16_t id)
Increments the local counter.
#define PKT_IGNORE_CHECKSUM
unsigned int frame_offset
#define PKT_PSEUDO_STREAM_END
TmEcode AFPSetBPFFilter(AFPThreadVars *ptv)
LiveDevice * LiveGetDevice(const char *name)
Get a pointer to the device at idx.
TmEcode DecodeAFPThreadInit(ThreadVars *, const void *, void **)
void(* ThreadExitPrintStats)(ThreadVars *, void *)
#define AFPV_CLEANUP(afpv)
#define LINKTYPE_GRE_OVER_IP
#define SCLogWarning(err_code,...)
Macro used to log WARNING messages.
TmEcode DecodeAFPThreadDeinit(ThreadVars *tv, void *data)
int DecodeSll(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq)
#define TAILQ_INSERT_TAIL(head, elm, field)
void PacketPoolWait(void)
int ChecksumAutoModeCheck(uint32_t thread_count, unsigned int iface_count, unsigned int iface_fail)
Check if the number of invalid checksums indicate checksum offloading in place.
void(* DerefFunc)(void *)
#define GET_IPV6_SRC_ADDR(p)
char iface[AFP_IFACE_NAME_LENGTH]
#define SC_ATOMIC_SET(name, val)
Set the value for the atomic variable.
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
int PacketSetData(Packet *p, uint8_t *pktdata, uint32_t pktlen)
Set data for Packet and set length when zeo copy is used.
TmModule tmm_modules[TMM_SIZE]
uint32_t default_packet_size
struct AFPThreadVars_ AFPThreadVars
Structure to hold thread specific variables.
#define StatsSyncCountersIfSignalled(tv)
TmEcode(* ThreadInit)(ThreadVars *, const void *, void **)
#define GET_TCP_DST_PORT(p)
#define SC_ATOMIC_GET(name)
Get the value from the atomic variable.
#define PACKET_FANOUT_FLAG_DEFRAG
#define TP_STATUS_USER_BUSY
void DecodeUpdatePacketCounters(ThreadVars *tv, const DecodeThreadVars *dtv, const Packet *p)
#define PKT_IS_PSEUDOPKT(p)
return 1 if the packet is a pseudo packet
ChecksumValidationMode checksum_mode
#define LINKTYPE_ETHERNET
struct LiveDevice_ * livedev
#define AFP_EMERGENCY_MODE
#define AFP_PEERS_MAX_TRY
Per thread variable structure.
void ReceiveAFPThreadExitStats(ThreadVars *, void *)
This function prints stats to the screen at exit.
#define AFP_COPY_MODE_IPS
#define AFP_VLAN_DISABLED
void StatsAddUI64(ThreadVars *tv, uint16_t id, uint64_t x)
Adds a value of type uint64_t to the local counter.
char out_iface[AFP_IFACE_NAME_LENGTH]
void SCBPFFree(struct bpf_program *program)
void DecodeThreadVarsFree(ThreadVars *tv, DecodeThreadVars *dtv)
#define GET_TCP_SRC_PORT(p)
#define AFP_IFACE_NAME_LENGTH
int PacketCopyData(Packet *p, uint8_t *pktdata, uint32_t pktlen)
Copy data to Packet payload and set packet length.
TmEcode DecodeAFP(ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *)
This function passes off to link type decoders.
uint64_t StatsGetLocalCounterValue(ThreadVars *tv, uint16_t id)
Get the value of the local copy of the counter that hold this id.