diff -Naupr ipt-netflow-2.6_orig/compat.h ipt-netflow/compat.h --- ipt-netflow-2.6_orig/compat.h 2023-08-03 19:43:17.629152119 +0700 +++ ipt-netflow/compat.h 2023-08-03 19:43:23.622484925 +0700 @@ -170,10 +170,6 @@ static int __ethtool_get_settings(struct # define CHECK_OK 0 #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35) -# define use_module ref_module -#endif - #ifndef NF_IP_LOCAL_IN /* 2.6.25 */ # define NF_IP_PRE_ROUTING NF_INET_PRE_ROUTING # define NF_IP_LOCAL_IN NF_INET_LOCAL_IN @@ -207,9 +203,9 @@ err: } #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0) +#ifdef HAVE_TOTALRAM_PAGES #define num_physpages totalram_pages() -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) +#elif defined HAVE_TOTALRAM_PAGES_REF #define num_physpages totalram_pages #endif @@ -775,4 +771,25 @@ struct module *find_module(const char *n } #endif +/* Copy from 294f69e662d1 ("compiler_attributes.h: Add 'fallthrough' pseudo + * keyword for switch/case use") */ +#ifndef fallthrough +# if defined __has_attribute && __has_attribute(__fallthrough__) +# define fallthrough __attribute__((__fallthrough__)) +# else +# define fallthrough do {} while (0) /* fallthrough */ +# endif +#endif + +#ifndef HAVE_NF_CT_EVENT_NOTIFIER_CT_EVENT +/* + * nat event callback parameter is constified in 5.15+ + * but it prevents module building with previous kernel versions + */ +# define NF_CT_EVENT struct nf_ct_event +# define ct_event fcn +#else +# define NF_CT_EVENT const struct nf_ct_event +#endif + #endif /* COMPAT_NETFLOW_H */ diff -Naupr ipt-netflow-2.6_orig/gen_compat_def ipt-netflow/gen_compat_def --- ipt-netflow-2.6_orig/gen_compat_def 2023-08-03 19:43:17.629152119 +0700 +++ ipt-netflow/gen_compat_def 2023-08-03 19:43:23.622484925 +0700 @@ -1,8 +1,9 @@ #!/bin/bash -efu # SPDX-License-Identifier: GPL-2.0-only # -# Generate defines based on kernel having -# some symbols declared +# Generate defines based on kernel having some symbols declared. +# Tests should work without linking, because kernel may not be +# completely compiled (only prepared). # # Copyright (C) 2019-2021 # @@ -41,7 +42,15 @@ kbuild_test_compile() { echo "// Output:" sed "s/^/\/\/ /" log echo - if ! egrep -q 'has no member named|undeclared|storage size of .* isn.t known|No such file or directory' log; then + if ! egrep -q \ + -e 'has no member named' \ + -e 'undeclared' \ + -e 'storage size of .* isn.t known' \ + -e 'No such file or directory' \ + -e 'incompatible types when initializing' \ + -e 'initializer element is not constant' \ + -e 'dereferencing pointer to incomplete type' \ + log; then echo "Error: unexpected error from compiler" >&2 cat log >&2 echo >&2 @@ -50,9 +59,9 @@ kbuild_test_compile() { fi } -# Test that symbol is defined. +# Test that symbol is defined (will catch functions mostly). kbuild_test_symbol() { - echo -n "Test symbol $* " >&2 + echo -n "Test function $* " >&2 kbuild_test_compile ${1^^} $1 ${2-} <<-EOF #include ${2:+#include <$2>} @@ -61,6 +70,16 @@ kbuild_test_symbol() { EOF } +# Test that symbol is defined (functions and globals). +kbuild_test_ref() { + echo -n "Test symbol $* " >&2 + kbuild_test_compile ${1^^}_REF $1 ${2-} <<-EOF + #include + ${2:+#include <$2>} + MODULE_LICENSE("GPL"); + void *test = &$1; + EOF +} # Test that struct is defined. kbuild_test_struct() { echo -n "Test struct $* " >&2 @@ -72,6 +91,20 @@ kbuild_test_struct() { EOF } +# Test that struct have member +kbuild_test_member() { + echo -n "Test member $* " >&2 + structname=${1%.*} + member=${1#*.} + def=${1^^} + def=${def//./_} + kbuild_test_compile $def "struct $1" ${2-} <<-EOF + #include + ${2:+#include <$2>} + MODULE_LICENSE("GPL"); + typeof(((struct $structname*)0)->$member) test; + EOF +} echo "// Autogenerated for $KDIR" echo @@ -87,6 +120,15 @@ kbuild_test_symbol synchronize_sched lin 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 +# 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 echo "// End of compat_def.h" diff -Naupr ipt-netflow-2.6_orig/ipt_NETFLOW.c ipt-netflow/ipt_NETFLOW.c --- ipt-netflow-2.6_orig/ipt_NETFLOW.c 2023-08-03 19:43:17.629152119 +0700 +++ ipt-netflow/ipt_NETFLOW.c 2023-08-03 19:43:23.622484925 +0700 @@ -87,7 +87,7 @@ #if defined(CONFIG_NF_NAT_NEEDED) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39) # include #endif -#ifndef CONFIG_BRIDGE_NETFILTER +#if !IS_ENABLED(CONFIG_BRIDGE_NETFILTER) # ifdef ENABLE_PHYSDEV_OVER # warning "Requested physdev override is not compiled." # undef ENABLE_PHYSDEV_OVER @@ -1929,21 +1929,23 @@ static ctl_table netflow_net_table[] = { { } }; #else /* >= 2.6.25 */ +# ifdef HAVE_REGISTER_SYSCTL_PATHS static struct ctl_path netflow_sysctl_path[] = { { .procname = "net", -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) +# if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) .ctl_name = CTL_NET -#endif +# endif }, { .procname = "netflow" }, { } }; +# endif #endif /* 2.6.25 */ #endif /* CONFIG_SYSCTL */ /* socket code */ -static void sk_error_report(struct sock *sk) +static void netflow_sk_error_report(struct sock *sk) { struct ipt_netflow_sock *usock; @@ -1974,7 +1976,7 @@ static struct socket *usock_open_sock(st } sock->sk->sk_allocation = GFP_ATOMIC; sock->sk->sk_prot->unhash(sock->sk); /* hidden from input */ - sock->sk->sk_error_report = &sk_error_report; /* clear ECONNREFUSED */ + sock->sk->sk_error_report = &netflow_sk_error_report; /* clear ECONNREFUSED */ sock->sk->sk_user_data = usock; sock->sk->sk_reuse = SK_CAN_REUSE; @@ -2226,7 +2228,7 @@ static int parse_sampler(char *ptr) printk(KERN_ERR "ipt_NETFLOW: sampler parse error (%s '%s').\n", "unknown mode", ptr); ret = -EINVAL; - /* FALLTHROUGH */ + fallthrough; case '\0': /* empty */ case 'n': /* none */ case 'o': /* off */ @@ -3532,7 +3534,7 @@ static inline __u8 hook2dir(const __u8 h } #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(5,7,0) +#ifndef HAVE_PUT_UNALIGNED_BE24 static inline void put_unaligned_be24(u32 val, unsigned char *p) { *p++ = val >> 16; @@ -3654,7 +3656,7 @@ static inline void add_tpl_field(__u8 *p put_unaligned_be16(nf->options, ptr); break; case SRC_MASK: *ptr = nf->s_mask; break; case DST_MASK: *ptr = nf->d_mask; break; - case icmpTypeCodeIPv4: /*FALLTHROUGH*/ + case icmpTypeCodeIPv4: fallthrough; case icmpTypeCodeIPv6: put_unaligned(nf->tuple.d_port, (__be16 *)ptr); break; case MUL_IGMP_TYPE: *ptr = nf->tuple.d_port; break; case flowEndReason: *ptr = nf->flowEndReason; break; @@ -4501,7 +4503,7 @@ static void netflow_work_fn(struct work_ wk_count = 0; wk_trylock = 0; wk_llist = 0; - wk_cpu = smp_processor_id(); + wk_cpu = __smp_processor_id(); wk_start = jiffies; pdus = netflow_scan_and_export(DONT_FLUSH); @@ -4597,7 +4599,20 @@ static void rate_timer_calc( #ifdef CONFIG_NF_NAT_NEEDED #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) static struct nf_ct_event_notifier *saved_event_cb __read_mostly = NULL; -static int netflow_conntrack_event(const unsigned int events, struct nf_ct_event *item) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,15,0) +static int netflow_conntrack_expect_event(const unsigned int events, const struct nf_exp_event *item) +{ + struct nf_ct_event_notifier *notifier; + + /* Call netlink first. */ + notifier = rcu_dereference(saved_event_cb); + if (likely(notifier)) + return notifier->exp_event(events, item); + else + return 0; +} +#endif +static int netflow_conntrack_event(const unsigned int events, NF_CT_EVENT *item) #else static int netflow_conntrack_event(struct notifier_block *this, unsigned long events, void *ptr) #endif @@ -4619,7 +4634,7 @@ static int netflow_conntrack_event(struc /* Call netlink first. */ notifier = rcu_dereference(saved_event_cb); if (likely(notifier)) - ret = notifier->fcn(events, item); + ret = notifier->ct_event(events, item); #endif if (unlikely(!natevents)) return ret; @@ -4684,7 +4699,10 @@ static struct notifier_block ctnl_notifi }; #else static struct nf_ct_event_notifier ctnl_notifier = { - .fcn = netflow_conntrack_event + .ct_event = netflow_conntrack_event, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,15,0) + .exp_event = netflow_conntrack_expect_event, +#endif }; #endif /* since 2.6.31 */ #endif /* CONFIG_NF_NAT_NEEDED */ @@ -4753,39 +4771,7 @@ static inline __u16 observed_hdrs(const return SetXBit(3); /* Unknown header. */ } -/* http://www.iana.org/assignments/ip-parameters/ip-parameters.xhtml */ -static const __u8 ip4_opt_table[] = { - [7] = 0, /* RR */ /* parsed manually because of 0 */ - [134] = 1, /* CIPSO */ - [133] = 2, /* E-SEC */ - [68] = 3, /* TS */ - [131] = 4, /* LSR */ - [130] = 5, /* SEC */ - [1] = 6, /* NOP */ - [0] = 7, /* EOOL */ - [15] = 8, /* ENCODE */ - [142] = 9, /* VISA */ - [205] = 10, /* FINN */ - [12] = 11, /* MTUR */ - [11] = 12, /* MTUP */ - [10] = 13, /* ZSU */ - [137] = 14, /* SSR */ - [136] = 15, /* SID */ - [151] = 16, /* DPS */ - [150] = 17, /* NSAPA */ - [149] = 18, /* SDB */ - [147] = 19, /* ADDEXT */ - [148] = 20, /* RTRALT */ - [82] = 21, /* TR */ - [145] = 22, /* EIP */ - [144] = 23, /* IMITD */ - [30] = 25, /* EXP */ - [94] = 25, /* EXP */ - [158] = 25, /* EXP */ - [222] = 25, /* EXP */ - [25] = 30, /* QS */ - [152] = 31, /* UMP */ -}; +/* https://www.iana.org/assignments/ip-parameters/ip-parameters.xhtml */ /* Parse IPv4 Options array int ipv4Options IPFIX value. */ static inline __u32 ip4_options(const u_int8_t *p, const unsigned int optsize) { @@ -4794,20 +4780,22 @@ static inline __u32 ip4_options(const u_ for (i = 0; likely(i < optsize); ) { u_int8_t op = p[i++]; + u_int8_t nn = op & 0x17; /* 5 bits option number */ - if (op == 7) /* RR: bit 0 */ - ret |= 1; - else if (likely(op < ARRAY_SIZE(ip4_opt_table))) { - /* Btw, IANA doc is messed up in a crazy way: - * http://www.ietf.org/mail-archive/web/ipfix/current/msg06008.html (2011) - * I decided to follow IANA _text_ description from - * http://www.iana.org/assignments/ipfix/ipfix.xhtml (2013-09-18) - * - * Set proper bit for htonl later. */ - if (ip4_opt_table[op]) - ret |= 1 << (32 - ip4_opt_table[op]); - } - if (likely(i >= optsize || op == 0)) + /* + * "Note that for identifying an option not just the 5-bit Option + * Number, but all 8 bits of the Option Type need to match one + * of the IPv4 options specified at + * http://www.iana.org/assignments/ip-parameters. + * + * Options are mapped to bits according to their option numbers. + * Option number X is mapped to bit X." - In inverted order, see + * RFC 5102 Errata 2944. + */ + + if (likely(nn < 32)) + ret |= 1 << (31 - nn); + if (i >= optsize || op == 0) /* 0 is EOOL. */ break; else if (unlikely(op == 1)) continue; @@ -4826,19 +4814,19 @@ static inline __u32 tcp_options(const st const unsigned int optsize = th->doff * 4 - sizeof(struct tcphdr); __u8 _opt[TCPHDR_MAXSIZE]; const u_int8_t *p; - __u32 ret; + __u32 ret = 0; unsigned int i; p = skb_header_pointer(skb, ptr + sizeof(struct tcphdr), optsize, _opt); if (unlikely(!p)) - return 0; - ret = 0; + return ret; + for (i = 0; likely(i < optsize); ) { u_int8_t opt = p[i++]; if (likely(opt < 32)) { /* IANA doc is messed up, see above. */ - ret |= 1 << (32 - opt); + ret |= 1 << (31 - opt); } if (likely(i >= optsize || opt == 0)) break; @@ -5451,9 +5439,15 @@ static void unset_notifier_cb(NET_STRUCT notifier = rcu_dereference(nf_conntrack_event_cb); if (notifier == &ctnl_notifier) { - if (saved_event_cb == NULL) + if (saved_event_cb == NULL) { +#ifdef HAVE_NF_CT_EVENT_NOTIFIER_CT_EVENT + /* b86c0e6429da ("netfilter: ecache: prepare for event + * notifier merge") */ + nf_conntrack_unregister_notifier(net); +#else nf_conntrack_unregister_notifier(NET_ARG &ctnl_notifier); - else +#endif + } else rcu_assign_pointer(nf_conntrack_event_cb, saved_event_cb); } else printk(KERN_ERR "ipt_NETFLOW: natevents already disabled.\n"); @@ -5494,12 +5488,8 @@ static void register_ct_events(void) } /* Reference netlink module to prevent it's unsafe unload before us. */ if (!netlink_m && (netlink_m = find_module(NETLINK_M))) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(5,9,0) - use_module(THIS_MODULE, netlink_m); -#else if (!try_module_get(netlink_m)) netlink_m = NULL; -#endif } /* Register ct events callback. */ @@ -5527,10 +5517,9 @@ static void unregister_ct_events(void) #else /* < v3.2 */ unset_notifier_cb(); #endif /* v3.2 */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,9,0) module_put(netlink_m); netlink_m = NULL; -#endif + rcu_assign_pointer(saved_event_cb, NULL); #else /* < v2.6.31 */ nf_conntrack_unregister_notifier(&ctnl_notifier); @@ -5679,7 +5668,11 @@ static int __init ipt_netflow_init(void) #endif ); #else /* 2.6.25 */ +# ifdef HAVE_REGISTER_SYSCTL_PATHS netflow_sysctl_header = register_sysctl_paths(netflow_sysctl_path, netflow_sysctl_table); +# else + netflow_sysctl_header = register_sysctl("net/netflow", netflow_sysctl_table); +# endif #endif if (!netflow_sysctl_header) { printk(KERN_ERR "netflow: can't register to sysctl\n"); diff -Naupr ipt-netflow-2.6_orig/Makefile.in ipt-netflow/Makefile.in --- ipt-netflow-2.6_orig/Makefile.in 2023-08-03 19:43:17.629152119 +0700 +++ ipt-netflow/Makefile.in 2023-08-03 19:43:23.622484925 +0700 @@ -27,7 +27,8 @@ ipt_NETFLOW.ko: version.h ipt_NETFLOW.c make -C $(KDIR) M=$(CURDIR) modules @touch $@ compat_def.h: gen_compat_def - ./gen_compat_def > $@ + ./gen_compat_def > $@- + mv $@- $@ sparse: | version.h ipt_NETFLOW.c ipt_NETFLOW.h compat.h Makefile @rm -f ipt_NETFLOW.ko ipt_NETFLOW.o @echo Compiling for kernel $(KVERSION) diff -Naupr ipt-netflow-2.6_orig/murmur3.h ipt-netflow/murmur3.h --- ipt-netflow-2.6_orig/murmur3.h 2023-08-03 19:43:17.629152119 +0700 +++ ipt-netflow/murmur3.h 2023-08-03 19:43:23.622484925 +0700 @@ -32,8 +32,8 @@ static inline uint32_t murmur3(const voi } tail = (const uint8_t*)blocks; switch (len & 3) { - case 3: k1 ^= tail[2] << 16; /* FALLTHROUGH */ - case 2: k1 ^= tail[1] << 8; /* FALLTHROUGH */ + case 3: k1 ^= tail[2] << 16; fallthrough; + case 2: k1 ^= tail[1] << 8; fallthrough; case 1: k1 ^= tail[0]; h1 ^= rotl32(k1 * c1, 15) * c2; }