Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

ipt_NETFLOW: add compatibility with 6.8+ (include 6.11) #230

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 14 additions & 42 deletions compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,14 @@ union nf_inet_addr {
# define BEFORE2632(x,y)
# endif

# if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)
# define ctl_table struct ctl_table
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This lacks support for < 3.17

--- a/compat.h
+++ b/compat.h
@@ -80,10 +80,16 @@ union nf_inet_addr {
 #  define s_ctl_table const struct ctl_table
 # elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)
 #  define s_ctl_table struct ctl_table
+# else
+#  define s_ctl_table ctl_table
 # endif
 
-# if !defined(HAVE_GRSECURITY_H) && LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)
-#  define ctl_table_no_const struct ctl_table
+# ifndef HAVE_GRSECURITY_H
+#  if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)
+#   define ctl_table_no_const struct ctl_table
+#  else
+#   define ctl_table_no_const ctl_table
+#  endif
 # endif
 #endif
 

# if LINUX_VERSION_CODE >= KERNEL_VERSION(6,11,0)
# define s_ctl_table const struct ctl_table
# elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)
# define s_ctl_table struct ctl_table
# endif

# ifndef HAVE_GRSECURITY_H
# define ctl_table_no_const ctl_table
# if !defined(HAVE_GRSECURITY_H) && LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)
# define ctl_table_no_const struct ctl_table
# endif
#endif

Expand Down Expand Up @@ -216,7 +218,7 @@ struct timeval {
long tv_usec; /* microseconds */
};

unsigned long timeval_to_jiffies(const struct timeval *tv)
static inline unsigned long timeval_to_jiffies(const struct timeval *tv)
{
return timespec64_to_jiffies(&(struct timespec64){
tv->tv_sec,
Expand All @@ -225,6 +227,10 @@ unsigned long timeval_to_jiffies(const struct timeval *tv)
}
#endif

#if !defined(HAVE_STRSCPY) && !defined(strscpy)
#define strscpy strlcpy
#endif

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
# ifdef ktime_to_timeval
/* ktime_to_timeval is defined on 64bit and inline on 32bit cpu */
Expand Down Expand Up @@ -380,10 +386,10 @@ static int sockaddr_cmp(const struct sockaddr_storage *sa1, const struct sockadd
return 0;
}

#ifndef IN6PTON_XDIGIT
#ifndef HAVE_IN6_PTON
#define hex_to_bin compat_hex_to_bin
/* lib/hexdump.c */
int hex_to_bin(char ch)
static inline int hex_to_bin(char ch)
{
if ((ch >= '0') && (ch <= '9'))
return ch - '0';
Expand Down Expand Up @@ -593,7 +599,7 @@ int in6_pton(const char *src, int srclen,
*end = s;
return ret;
}
#endif /* IN6PTON_XDIGIT */
#endif /* HAVE_IN6_PTON */

#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,2,0)
# define sock_create_kern(f, t, p, s) sock_create_kern(&init_net, f, t, p, s)
Expand Down Expand Up @@ -712,40 +718,6 @@ static inline void do_gettimeofday(struct timeval *tv)
}
#endif

#define TOLOWER(x) ((x) | 0x20)
unsigned long long strtoul(const char *cp, char **endp, unsigned int base)
{
unsigned long long result = 0;

if (!base) {
if (cp[0] == '0') {
if (TOLOWER(cp[1]) == 'x' && isxdigit(cp[2]))
base = 16;
else
base = 8;
} else {
base = 10;
}
}

if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x')
cp += 2;

while (isxdigit(*cp)) {
unsigned int value;

value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10;
if (value >= base)
break;
result = result * base + value;
cp++;
}
if (endp)
*endp = (char *)cp;

return result;
}

#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,12,0)
/*
* find_module() is unexported in v5.12:
Expand Down
17 changes: 16 additions & 1 deletion gen_compat_def
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,15 @@ kbuild_test_ref() {
void *test = &$1;
EOF
}

# Test symbol if include exists
kbuild_test_symbol_include() {
echo "Test file exists $KDIR/include/$2" >&2
if [ -f $KDIR/include/$2 ]; then
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Testing kernel header existence at the file system level is very fragile and does not work for all kernel versions equally well.

Also e.g. the Debian linux-headers-* packages have split up the headers into /lib/modules/X.Y.Z-amd64/build -> /usr/src/linux-headers-X.Y.Z-amd64 and /lib/modules/X.Y.Z-amd64/source -> /usr/src/linux-headers-X.Y.Z-common
I tried checking in both locations, but that didn't work either for all kernel versions.

kbuild_test_symbol $*
fi
}

# Test that struct is defined.
kbuild_test_struct() {
echo -n "Test struct $* " >&2
Expand Down Expand Up @@ -121,14 +130,20 @@ kbuild_test_symbol nf_bridge_info_get linux/netfilter_bridge.h
# Stumbled on 5.9
kbuild_test_struct vlan_dev_priv linux/if_vlan.h
# Kernel version check broken by centos8
kbuild_test_symbol put_unaligned_be24 asm/unaligned.h
kbuild_test_symbol_include put_unaligned_be24 asm-generic/unaligned.h
kbuild_test_symbol_include put_unaligned_be24 linux/unaligned/generic.h
kbuild_test_symbol_include put_unaligned_be24 linux/unaligned.h
# totalram_pages changed from atomic to inline function.
kbuild_test_symbol totalram_pages linux/mm.h
kbuild_test_ref totalram_pages linux/mm.h
# b86c0e6429da ("netfilter: ecache: prepare for event notifier merge")
kbuild_test_member nf_ct_event_notifier.ct_event net/netfilter/nf_conntrack_ecache.h
# 6.4: 0199849acd07 ("sysctl: remove register_sysctl_paths()")
kbuild_test_symbol register_sysctl_paths linux/sysctl.h
# 6.8: d26270061ae6 ("string: Remove strlcpy()")
kbuild_test_symbol strscpy linux/string.h
# 2.6.18 lacks in6_pton and in4_pton
kbuild_test_symbol in6_pton linux/inet.h

echo "// End of compat_def.h"

Expand Down
47 changes: 28 additions & 19 deletions ipt_NETFLOW.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
#include <linux/in6.h>
#include <linux/inet.h>
#include <linux/kernel.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE > KERNEL_VERSION(5,10,0)
#include <linux/kstrtox.h>
#endif
#include <linux/ip.h>
#include <linux/udp.h>
#include <linux/icmp.h>
Expand Down Expand Up @@ -67,8 +71,11 @@
# include <net/netfilter/nf_conntrack.h>
# include <net/netfilter/nf_conntrack_core.h>
#endif
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(6,12,0)
#include <asm/unaligned.h>
#else
#include <linux/unaligned.h>
#endif
#ifdef HAVE_LLIST
/* llist.h is officially defined since linux 3.1,
* but centos6 have it backported on its 2.6.32.el6 */
Expand Down Expand Up @@ -1519,7 +1526,7 @@ static int switch_promisc(int newpromisc)

#ifdef CONFIG_SYSCTL
/* sysctl /proc/sys/net/netflow */
static int hsize_procctl(ctl_table *ctl, int write, BEFORE2632(struct file *filp,)
static int hsize_procctl(s_ctl_table *ctl, int write, BEFORE2632(struct file *filp,)
void __user *buffer, size_t *lenp, loff_t *fpos)
{
int ret, hsize;
Expand All @@ -1536,7 +1543,7 @@ static int hsize_procctl(ctl_table *ctl, int write, BEFORE2632(struct file *filp
return ret;
}

static int sndbuf_procctl(ctl_table *ctl, int write, BEFORE2632(struct file *filp,)
static int sndbuf_procctl(s_ctl_table *ctl, int write, BEFORE2632(struct file *filp,)
void __user *buffer, size_t *lenp, loff_t *fpos)
{
int ret;
Expand Down Expand Up @@ -1571,7 +1578,7 @@ static int sndbuf_procctl(ctl_table *ctl, int write, BEFORE2632(struct file *fil
}

static void free_templates(void);
static int destination_procctl(ctl_table *ctl, int write, BEFORE2632(struct file *filp,)
static int destination_procctl(s_ctl_table *ctl, int write, BEFORE2632(struct file *filp,)
void __user *buffer, size_t *lenp, loff_t *fpos)
{
int ret;
Expand All @@ -1588,7 +1595,7 @@ static int destination_procctl(ctl_table *ctl, int write, BEFORE2632(struct file
}

#ifdef ENABLE_AGGR
static int aggregation_procctl(ctl_table *ctl, int write, BEFORE2632(struct file *filp,)
static int aggregation_procctl(s_ctl_table *ctl, int write, BEFORE2632(struct file *filp,)
void __user *buffer, size_t *lenp, loff_t *fpos)
{
int ret;
Expand All @@ -1603,7 +1610,7 @@ static int aggregation_procctl(ctl_table *ctl, int write, BEFORE2632(struct file
#endif

#ifdef ENABLE_PROMISC
static int promisc_procctl(ctl_table *ctl, int write, BEFORE2632(struct file *filp,)
static int promisc_procctl(s_ctl_table *ctl, int write, BEFORE2632(struct file *filp,)
void __user *buffer, size_t *lenp, loff_t *fpos)
{
int newpromisc = promisc;
Expand All @@ -1620,7 +1627,7 @@ static int promisc_procctl(ctl_table *ctl, int write, BEFORE2632(struct file *fi

#ifdef ENABLE_SAMPLER
static int parse_sampler(char *ptr);
static int sampler_procctl(ctl_table *ctl, int write, BEFORE2632(struct file *filp,)
static int sampler_procctl(s_ctl_table *ctl, int write, BEFORE2632(struct file *filp,)
void __user *buffer, size_t *lenp, loff_t *fpos)
{
int ret;
Expand Down Expand Up @@ -1653,7 +1660,7 @@ static int sampler_procctl(ctl_table *ctl, int write, BEFORE2632(struct file *fi

#ifdef SNMP_RULES
static int add_snmp_rules(char *ptr);
static int snmp_procctl(ctl_table *ctl, int write, BEFORE2632(struct file *filp,)
static int snmp_procctl(s_ctl_table *ctl, int write, BEFORE2632(struct file *filp,)
void __user *buffer, size_t *lenp, loff_t *fpos)
{
int ret;
Expand All @@ -1678,7 +1685,7 @@ static void clear_ipt_netflow_stat(void)
}
}

static int flush_procctl(ctl_table *ctl, int write, BEFORE2632(struct file *filp,)
static int flush_procctl(s_ctl_table *ctl, int write, BEFORE2632(struct file *filp,)
void __user *buffer, size_t *lenp, loff_t *fpos)
{
int ret;
Expand Down Expand Up @@ -1707,7 +1714,7 @@ static int flush_procctl(ctl_table *ctl, int write, BEFORE2632(struct file *filp
return ret;
}

static int protocol_procctl(ctl_table *ctl, int write, BEFORE2632(struct file *filp,)
static int protocol_procctl(s_ctl_table *ctl, int write, BEFORE2632(struct file *filp,)
void __user *buffer, size_t *lenp, loff_t *fpos)
{
int ret;
Expand Down Expand Up @@ -1740,7 +1747,7 @@ static int protocol_procctl(ctl_table *ctl, int write, BEFORE2632(struct file *f
#ifdef CONFIG_NF_NAT_NEEDED
static void register_ct_events(void);
static void unregister_ct_events(void);
static int natevents_procctl(ctl_table *ctl, int write, BEFORE2632(struct file *filp,)
static int natevents_procctl(s_ctl_table *ctl, int write, BEFORE2632(struct file *filp,)
void __user *buffer, size_t *lenp, loff_t *fpos)
{
int ret;
Expand Down Expand Up @@ -1777,7 +1784,7 @@ static void ctl_table_renumber(ctl_table *table)
#define _CTL_NAME(x)
#define ctl_table_renumber(x)
#endif
static ctl_table netflow_sysctl_table[] = {
static ctl_table_no_const netflow_sysctl_table[] = {
{
.procname = "active_timeout",
.mode = 0644,
Expand Down Expand Up @@ -1905,7 +1912,9 @@ static ctl_table netflow_sysctl_table[] = {
.proc_handler = &natevents_procctl,
},
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(6,11,0)
{ }
#endif
};

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
Expand Down Expand Up @@ -2396,7 +2405,7 @@ static int add_destinations(const char *ptr)
++end;
if (succ &&
(*end == ':' || *end == '.' || *end == 'p' || *end == '#'))
sin6->sin6_port = htons(strtoul(++end, (char **)&end, 0));
sin6->sin6_port = htons(simple_strtoul(++end, (char **)&end, 0));
if (succ && *end == '@') {
++end;
sout->sin6_family = AF_INET6;
Expand All @@ -2411,7 +2420,7 @@ static int add_destinations(const char *ptr)
sin->sin_port = htons(2055);
succ = in4_pton(ptr, len, (u8 *)&sin->sin_addr, -1, &end);
if (succ && *end == ':')
sin->sin_port = htons(strtoul(++end, (char **)&end, 0));
sin->sin_port = htons(simple_strtoul(++end, (char **)&end, 0));
if (succ && *end == '@') {
++end;
sout->sin_family = AF_INET;
Expand Down Expand Up @@ -4087,7 +4096,7 @@ static int ethtool_drvinfo(unsigned char *ptr, size_t size, struct net_device *d
ops->get_drvinfo(dev, &info);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)
else if (dev->dev.parent && dev->dev.parent->driver) {
strlcpy(info.driver, dev->dev.parent->driver->name, sizeof(info.driver));
strscpy(info.driver, dev->dev.parent->driver->name, sizeof(info.driver));
}
#endif
n = scnprintf(ptr, len, "%s", info.driver);
Expand Down Expand Up @@ -5684,7 +5693,7 @@ static int __init ipt_netflow_init(void)
if (!destination)
destination = destination_buf;
if (destination != destination_buf) {
strlcpy(destination_buf, destination, sizeof(destination_buf));
strscpy(destination_buf, destination, sizeof(destination_buf));
destination = destination_buf;
}
if (add_destinations(destination) < 0)
Expand All @@ -5694,7 +5703,7 @@ static int __init ipt_netflow_init(void)
if (!aggregation)
aggregation = aggregation_buf;
if (aggregation != aggregation_buf) {
strlcpy(aggregation_buf, aggregation, sizeof(aggregation_buf));
strscpy(aggregation_buf, aggregation, sizeof(aggregation_buf));
aggregation = aggregation_buf;
}
add_aggregation(aggregation);
Expand All @@ -5704,7 +5713,7 @@ static int __init ipt_netflow_init(void)
if (!sampler)
sampler = sampler_buf;
if (sampler != sampler_buf) {
strlcpy(sampler_buf, sampler, sizeof(sampler_buf));
strscpy(sampler_buf, sampler, sizeof(sampler_buf));
sampler = sampler_buf;
}
parse_sampler(sampler);
Expand All @@ -5721,7 +5730,7 @@ static int __init ipt_netflow_init(void)
if (!snmp_rules)
snmp_rules = snmp_rules_buf;
if (snmp_rules != snmp_rules_buf) {
strlcpy(snmp_rules_buf, snmp_rules, sizeof(snmp_rules_buf));
strscpy(snmp_rules_buf, snmp_rules, sizeof(snmp_rules_buf));
snmp_rules = snmp_rules_buf;
}
add_snmp_rules(snmp_rules);
Expand Down