diff --git a/code/bngblaster/src/io/io_socket.c b/code/bngblaster/src/io/io_socket.c index f9ad6162..9993a946 100644 --- a/code/bngblaster/src/io/io_socket.c +++ b/code/bngblaster/src/io/io_socket.c @@ -132,6 +132,22 @@ io_socket_open(io_handle_s *io) { io->interface->name, strerror(errno), errno); return false; } + /* Ignore outgoing packets if socket is used for RX. + * PACKET_IGNORE_OUTGOING option is supported since linux 4.20. */ + if(io->direction == IO_INGRESS) { + int one=1; + if(setsockopt(io->fd, SOL_PACKET, PACKET_IGNORE_OUTGOING, &one, sizeof(one)) == -1) { + kernel_version_s kv = get_kernel_version(); + const char *hint = ""; + if((kv.major < 4) || (kv.major == 4 && kv.minor < 20)) { + hint = " Unsupported on linux kernel below 4.20."; + } + LOG(ERROR, + "Warning: Failed to set PACKET_IGNORE_OUTGOING for interface %s RX socket - %s (%d).%s" + " TX packets might be seen on RX.\n", + io->interface->name, strerror(errno), errno, hint); + } + } if(io->direction == IO_EGRESS && interface->config->qdisc_bypass) { if(!set_qdisc_bypass(io)) { return false; diff --git a/code/common/src/utils.c b/code/common/src/utils.c index 34125342..c11e3dee 100644 --- a/code/common/src/utils.c +++ b/code/common/src/utils.c @@ -8,6 +8,27 @@ * SPDX-License-Identifier: BSD-3-Clause */ #include "utils.h" +#include + +/* + * Get linux kernel version major,minor and patch number. + */ +kernel_version_s get_kernel_version(void) +{ + struct utsname buffer; + kernel_version_s kv = {0, 0, 0}; + + if (uname(&buffer) != 0) { + return kv; // returns zeros on failure + } + + sscanf(buffer.release, "%u.%u.%u", + &kv.major, + &kv.minor, + &kv.patch); + + return kv; +} /* * Simple big endian reader. diff --git a/code/common/src/utils.h b/code/common/src/utils.h index a58c74b3..7a204abc 100644 --- a/code/common/src/utils.h +++ b/code/common/src/utils.h @@ -11,6 +11,15 @@ #define __COMMON_UTILS_H__ #include "common.h" +typedef struct kernel_version_ +{ + uint32_t major; + uint32_t minor; + uint32_t patch; +} kernel_version_s; + +kernel_version_s get_kernel_version(void); + uint64_t read_be_uint(uint8_t *data, size_t length); bool write_be_uint(uint8_t *data, size_t length, uint64_t value); bool inc_be_uint(uint8_t *data, size_t length);