diff --git a/.github/workflows/msbuild.yml b/.github/workflows/msbuild.yml new file mode 100644 index 0000000000000..4a5d3097d7f90 --- /dev/null +++ b/.github/workflows/msbuild.yml @@ -0,0 +1,32 @@ +name: MSBuild + +on: [push] + +env: + # Path to the solution file relative to the root of the project. + SOLUTION_FILE_PATH: . + + # Configuration type to build. + # You can convert this to a build matrix if you need coverage of multiple configuration types. + # https://docs.github.com/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix + BUILD_CONFIGURATION: Release + +jobs: + build: + runs-on: windows-latest + + steps: + - uses: actions/checkout@v2 + + - name: Add MSBuild to PATH + uses: microsoft/setup-msbuild@v1 + + - name: Restore NuGet packages + working-directory: ${{env.GITHUB_WORKSPACE}} + run: nuget restore ${{env.SOLUTION_FILE_PATH}} + + - name: Build + working-directory: ${{env.GITHUB_WORKSPACE}} + # Add additional options to the MSBuild command line here (like platform or verbosity level). + # See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference + run: msbuild /m /p:Configuration=${{env.BUILD_CONFIGURATION}} ${{env.SOLUTION_FILE_PATH}} diff --git a/include/uapi/linux/netfilter/xt_CONNMARK.h b/include/uapi/linux/netfilter/xt_CONNMARK.h index 36cc956ead1ae..1aa5c955ee1ee 100644 --- a/include/uapi/linux/netfilter/xt_CONNMARK.h +++ b/include/uapi/linux/netfilter/xt_CONNMARK.h @@ -1,7 +1,42 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef _XT_CONNMARK_H_target -#define _XT_CONNMARK_H_target +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +#ifndef _XT_CONNMARK_H +#define _XT_CONNMARK_H -#include +#include -#endif /*_XT_CONNMARK_H_target*/ +/* Copyright (C) 2002,2004 MARA Systems AB + * by Henrik Nordstrom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +enum { + XT_CONNMARK_SET = 0, + XT_CONNMARK_SAVE, + XT_CONNMARK_RESTORE +}; + +enum { + D_SHIFT_LEFT = 0, + D_SHIFT_RIGHT, +}; + +struct xt_connmark_tginfo1 { + __u32 ctmark, ctmask, nfmask; + __u8 mode; +}; + +struct xt_connmark_tginfo2 { + __u32 ctmark, ctmask, nfmask; + __u8 shift_dir, shift_bits, mode; +}; + +struct xt_connmark_mtinfo1 { + __u32 mark, mask; + __u8 invert; +}; + +#endif /*_XT_CONNMARK_H*/ diff --git a/include/uapi/linux/netfilter/xt_DSCP.h b/include/uapi/linux/netfilter/xt_DSCP.h index 223d635e8b6f7..7594e4df8587a 100644 --- a/include/uapi/linux/netfilter/xt_DSCP.h +++ b/include/uapi/linux/netfilter/xt_DSCP.h @@ -1,27 +1,32 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* x_tables module for setting the IPv4/IPv6 DSCP field +/* x_tables module for matching the IPv4/IPv6 DSCP field * * (C) 2002 Harald Welte - * based on ipt_FTOS.c (C) 2000 by Matthew G. Marsh * This software is distributed under GNU GPL v2, 1991 * * See RFC2474 for a description of the DSCP field within the IP Header. * - * xt_DSCP.h,v 1.7 2002/03/14 12:03:13 laforge Exp + * xt_dscp.h,v 1.3 2002/08/05 19:00:21 laforge Exp */ -#ifndef _XT_DSCP_TARGET_H -#define _XT_DSCP_TARGET_H -#include +#ifndef _XT_DSCP_H +#define _XT_DSCP_H + #include -/* target info */ -struct xt_DSCP_info { +#define XT_DSCP_MASK 0xfc /* 11111100 */ +#define XT_DSCP_SHIFT 2 +#define XT_DSCP_MAX 0x3f /* 00111111 */ + +/* match info */ +struct xt_dscp_info { __u8 dscp; + __u8 invert; }; -struct xt_tos_target_info { - __u8 tos_value; +struct xt_tos_match_info { __u8 tos_mask; + __u8 tos_value; + __u8 invert; }; -#endif /* _XT_DSCP_TARGET_H */ +#endif /* _XT_DSCP_H */ diff --git a/include/uapi/linux/netfilter/xt_MARK.h b/include/uapi/linux/netfilter/xt_MARK.h index f1fe2b4be9332..9d0526ced8f0d 100644 --- a/include/uapi/linux/netfilter/xt_MARK.h +++ b/include/uapi/linux/netfilter/xt_MARK.h @@ -1,7 +1,16 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef _XT_MARK_H_target -#define _XT_MARK_H_target +#ifndef _XT_MARK_H +#define _XT_MARK_H -#include +#include -#endif /*_XT_MARK_H_target */ +struct xt_mark_tginfo2 { + __u32 mark, mask; +}; + +struct xt_mark_mtinfo1 { + __u32 mark, mask; + __u8 invert; +}; + +#endif /*_XT_MARK_H*/ diff --git a/include/uapi/linux/netfilter/xt_RATEEST.h b/include/uapi/linux/netfilter/xt_RATEEST.h index 2b87a71e6266e..52a37bdc1837a 100644 --- a/include/uapi/linux/netfilter/xt_RATEEST.h +++ b/include/uapi/linux/netfilter/xt_RATEEST.h @@ -1,17 +1,39 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef _XT_RATEEST_TARGET_H -#define _XT_RATEEST_TARGET_H +#ifndef _XT_RATEEST_MATCH_H +#define _XT_RATEEST_MATCH_H #include #include -struct xt_rateest_target_info { - char name[IFNAMSIZ]; - __s8 interval; - __u8 ewma_log; +enum xt_rateest_match_flags { + XT_RATEEST_MATCH_INVERT = 1<<0, + XT_RATEEST_MATCH_ABS = 1<<1, + XT_RATEEST_MATCH_REL = 1<<2, + XT_RATEEST_MATCH_DELTA = 1<<3, + XT_RATEEST_MATCH_BPS = 1<<4, + XT_RATEEST_MATCH_PPS = 1<<5, +}; + +enum xt_rateest_match_mode { + XT_RATEEST_MATCH_NONE, + XT_RATEEST_MATCH_EQ, + XT_RATEEST_MATCH_LT, + XT_RATEEST_MATCH_GT, +}; + +struct xt_rateest_match_info { + char name1[IFNAMSIZ]; + char name2[IFNAMSIZ]; + __u16 flags; + __u16 mode; + __u32 bps1; + __u32 pps1; + __u32 bps2; + __u32 pps2; /* Used internally by the kernel */ - struct xt_rateest *est __attribute__((aligned(8))); + struct xt_rateest *est1 __attribute__((aligned(8))); + struct xt_rateest *est2 __attribute__((aligned(8))); }; -#endif /* _XT_RATEEST_TARGET_H */ +#endif /* _XT_RATEEST_MATCH_H */ diff --git a/include/uapi/linux/netfilter/xt_TCPMSS.h b/include/uapi/linux/netfilter/xt_TCPMSS.h index 65ea6c9dab4b6..2268f58b4dec7 100644 --- a/include/uapi/linux/netfilter/xt_TCPMSS.h +++ b/include/uapi/linux/netfilter/xt_TCPMSS.h @@ -1,13 +1,12 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef _XT_TCPMSS_H -#define _XT_TCPMSS_H +#ifndef _XT_TCPMSS_MATCH_H +#define _XT_TCPMSS_MATCH_H #include -struct xt_tcpmss_info { - __u16 mss; +struct xt_tcpmss_match_info { + __u16 mss_min, mss_max; + __u8 invert; }; -#define XT_TCPMSS_CLAMP_PMTU 0xffff - -#endif /* _XT_TCPMSS_H */ +#endif /*_XT_TCPMSS_MATCH_H*/ diff --git a/include/uapi/linux/netfilter_ipv4/ipt_ECN.h b/include/uapi/linux/netfilter_ipv4/ipt_ECN.h index e3630fd045b8d..8121bec470267 100644 --- a/include/uapi/linux/netfilter_ipv4/ipt_ECN.h +++ b/include/uapi/linux/netfilter_ipv4/ipt_ECN.h @@ -1,34 +1,16 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* Header file for iptables ipt_ECN target - * - * (C) 2002 by Harald Welte - * - * This software is distributed under GNU GPL v2, 1991 - * - * ipt_ECN.h,v 1.3 2002/05/29 12:17:40 laforge Exp -*/ -#ifndef _IPT_ECN_TARGET_H -#define _IPT_ECN_TARGET_H +#ifndef _IPT_ECN_H +#define _IPT_ECN_H -#include -#include +#include +#define ipt_ecn_info xt_ecn_info -#define IPT_ECN_IP_MASK (~XT_DSCP_MASK) - -#define IPT_ECN_OP_SET_IP 0x01 /* set ECN bits of IPv4 header */ -#define IPT_ECN_OP_SET_ECE 0x10 /* set ECE bit of TCP header */ -#define IPT_ECN_OP_SET_CWR 0x20 /* set CWR bit of TCP header */ - -#define IPT_ECN_OP_MASK 0xce - -struct ipt_ECN_info { - __u8 operation; /* bitset of operations */ - __u8 ip_ect; /* ECT codepoint of IPv4 header, pre-shifted */ - union { - struct { - __u8 ece:1, cwr:1; /* TCP ECT bits */ - } tcp; - } proto; +enum { + IPT_ECN_IP_MASK = XT_ECN_IP_MASK, + IPT_ECN_OP_MATCH_IP = XT_ECN_OP_MATCH_IP, + IPT_ECN_OP_MATCH_ECE = XT_ECN_OP_MATCH_ECE, + IPT_ECN_OP_MATCH_CWR = XT_ECN_OP_MATCH_CWR, + IPT_ECN_OP_MATCH_MASK = XT_ECN_OP_MATCH_MASK, }; -#endif /* _IPT_ECN_TARGET_H */ +#endif /* IPT_ECN_H */ diff --git a/include/uapi/linux/netfilter_ipv4/ipt_TTL.h b/include/uapi/linux/netfilter_ipv4/ipt_TTL.h index 57d2fc67a9437..ad0226a8629b2 100644 --- a/include/uapi/linux/netfilter_ipv4/ipt_TTL.h +++ b/include/uapi/linux/netfilter_ipv4/ipt_TTL.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* TTL modification module for IP tables - * (C) 2000 by Harald Welte */ +/* IP tables module for matching the value of the TTL + * (C) 2000 by Harald Welte */ #ifndef _IPT_TTL_H #define _IPT_TTL_H @@ -8,14 +8,14 @@ #include enum { - IPT_TTL_SET = 0, - IPT_TTL_INC, - IPT_TTL_DEC + IPT_TTL_EQ = 0, /* equals */ + IPT_TTL_NE, /* not equals */ + IPT_TTL_LT, /* less than */ + IPT_TTL_GT, /* greater than */ }; -#define IPT_TTL_MAXMODE IPT_TTL_DEC -struct ipt_TTL_info { +struct ipt_ttl_info { __u8 mode; __u8 ttl; }; diff --git a/include/uapi/linux/netfilter_ipv6/ip6t_HL.h b/include/uapi/linux/netfilter_ipv6/ip6t_HL.h index eaed56a287b47..6b62f9418eb21 100644 --- a/include/uapi/linux/netfilter_ipv6/ip6t_HL.h +++ b/include/uapi/linux/netfilter_ipv6/ip6t_HL.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* Hop Limit modification module for ip6tables +/* ip6tables module for matching the Hop Limit value * Maciej Soltysiak - * Based on HW's TTL module */ + * Based on HW's ttl module */ #ifndef _IP6T_HL_H #define _IP6T_HL_H @@ -9,14 +9,14 @@ #include enum { - IP6T_HL_SET = 0, - IP6T_HL_INC, - IP6T_HL_DEC + IP6T_HL_EQ = 0, /* equals */ + IP6T_HL_NE, /* not equals */ + IP6T_HL_LT, /* less than */ + IP6T_HL_GT, /* greater than */ }; -#define IP6T_HL_MAXMODE IP6T_HL_DEC -struct ip6t_HL_info { +struct ip6t_hl_info { __u8 mode; __u8 hop_limit; }; diff --git a/net/netfilter/xt_DSCP.c b/net/netfilter/xt_DSCP.c index eababc354ff10..fb0169a8f9bbd 100644 --- a/net/netfilter/xt_DSCP.c +++ b/net/netfilter/xt_DSCP.c @@ -1,11 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-only -/* x_tables module for setting the IPv4/IPv6 DSCP field, Version 1.8 +/* IP tables module for matching the value of the IPv4/IPv6 DSCP field * * (C) 2002 by Harald Welte - * based on ipt_FTOS.c (C) 2000 by Matthew G. Marsh - * - * See RFC2474 for a description of the DSCP field within the IP Header. -*/ + */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include #include @@ -14,148 +11,100 @@ #include #include -#include +#include MODULE_AUTHOR("Harald Welte "); -MODULE_DESCRIPTION("Xtables: DSCP/TOS field modification"); +MODULE_DESCRIPTION("Xtables: DSCP/TOS field match"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("ipt_DSCP"); -MODULE_ALIAS("ip6t_DSCP"); -MODULE_ALIAS("ipt_TOS"); -MODULE_ALIAS("ip6t_TOS"); +MODULE_ALIAS("ipt_dscp"); +MODULE_ALIAS("ip6t_dscp"); +MODULE_ALIAS("ipt_tos"); +MODULE_ALIAS("ip6t_tos"); -static unsigned int -dscp_tg(struct sk_buff *skb, const struct xt_action_param *par) +static bool +dscp_mt(const struct sk_buff *skb, struct xt_action_param *par) { - const struct xt_DSCP_info *dinfo = par->targinfo; + const struct xt_dscp_info *info = par->matchinfo; u_int8_t dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT; - if (dscp != dinfo->dscp) { - if (skb_ensure_writable(skb, sizeof(struct iphdr))) - return NF_DROP; - - ipv4_change_dsfield(ip_hdr(skb), - (__force __u8)(~XT_DSCP_MASK), - dinfo->dscp << XT_DSCP_SHIFT); - - } - return XT_CONTINUE; + return (dscp == info->dscp) ^ !!info->invert; } -static unsigned int -dscp_tg6(struct sk_buff *skb, const struct xt_action_param *par) +static bool +dscp_mt6(const struct sk_buff *skb, struct xt_action_param *par) { - const struct xt_DSCP_info *dinfo = par->targinfo; + const struct xt_dscp_info *info = par->matchinfo; u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT; - if (dscp != dinfo->dscp) { - if (skb_ensure_writable(skb, sizeof(struct ipv6hdr))) - return NF_DROP; - - ipv6_change_dsfield(ipv6_hdr(skb), - (__force __u8)(~XT_DSCP_MASK), - dinfo->dscp << XT_DSCP_SHIFT); - } - return XT_CONTINUE; + return (dscp == info->dscp) ^ !!info->invert; } -static int dscp_tg_check(const struct xt_tgchk_param *par) +static int dscp_mt_check(const struct xt_mtchk_param *par) { - const struct xt_DSCP_info *info = par->targinfo; + const struct xt_dscp_info *info = par->matchinfo; if (info->dscp > XT_DSCP_MAX) return -EDOM; - return 0; -} - -static unsigned int -tos_tg(struct sk_buff *skb, const struct xt_action_param *par) -{ - const struct xt_tos_target_info *info = par->targinfo; - struct iphdr *iph = ip_hdr(skb); - u_int8_t orig, nv; - - orig = ipv4_get_dsfield(iph); - nv = (orig & ~info->tos_mask) ^ info->tos_value; - if (orig != nv) { - if (skb_ensure_writable(skb, sizeof(struct iphdr))) - return NF_DROP; - iph = ip_hdr(skb); - ipv4_change_dsfield(iph, 0, nv); - } - - return XT_CONTINUE; + return 0; } -static unsigned int -tos_tg6(struct sk_buff *skb, const struct xt_action_param *par) +static bool tos_mt(const struct sk_buff *skb, struct xt_action_param *par) { - const struct xt_tos_target_info *info = par->targinfo; - struct ipv6hdr *iph = ipv6_hdr(skb); - u_int8_t orig, nv; - - orig = ipv6_get_dsfield(iph); - nv = (orig & ~info->tos_mask) ^ info->tos_value; - - if (orig != nv) { - if (skb_ensure_writable(skb, sizeof(struct iphdr))) - return NF_DROP; - iph = ipv6_hdr(skb); - ipv6_change_dsfield(iph, 0, nv); - } - - return XT_CONTINUE; + const struct xt_tos_match_info *info = par->matchinfo; + + if (xt_family(par) == NFPROTO_IPV4) + return ((ip_hdr(skb)->tos & info->tos_mask) == + info->tos_value) ^ !!info->invert; + else + return ((ipv6_get_dsfield(ipv6_hdr(skb)) & info->tos_mask) == + info->tos_value) ^ !!info->invert; } -static struct xt_target dscp_tg_reg[] __read_mostly = { +static struct xt_match dscp_mt_reg[] __read_mostly = { { - .name = "DSCP", + .name = "dscp", .family = NFPROTO_IPV4, - .checkentry = dscp_tg_check, - .target = dscp_tg, - .targetsize = sizeof(struct xt_DSCP_info), - .table = "mangle", + .checkentry = dscp_mt_check, + .match = dscp_mt, + .matchsize = sizeof(struct xt_dscp_info), .me = THIS_MODULE, }, { - .name = "DSCP", + .name = "dscp", .family = NFPROTO_IPV6, - .checkentry = dscp_tg_check, - .target = dscp_tg6, - .targetsize = sizeof(struct xt_DSCP_info), - .table = "mangle", + .checkentry = dscp_mt_check, + .match = dscp_mt6, + .matchsize = sizeof(struct xt_dscp_info), .me = THIS_MODULE, }, { - .name = "TOS", + .name = "tos", .revision = 1, .family = NFPROTO_IPV4, - .table = "mangle", - .target = tos_tg, - .targetsize = sizeof(struct xt_tos_target_info), + .match = tos_mt, + .matchsize = sizeof(struct xt_tos_match_info), .me = THIS_MODULE, }, { - .name = "TOS", + .name = "tos", .revision = 1, .family = NFPROTO_IPV6, - .table = "mangle", - .target = tos_tg6, - .targetsize = sizeof(struct xt_tos_target_info), + .match = tos_mt, + .matchsize = sizeof(struct xt_tos_match_info), .me = THIS_MODULE, }, }; -static int __init dscp_tg_init(void) +static int __init dscp_mt_init(void) { - return xt_register_targets(dscp_tg_reg, ARRAY_SIZE(dscp_tg_reg)); + return xt_register_matches(dscp_mt_reg, ARRAY_SIZE(dscp_mt_reg)); } -static void __exit dscp_tg_exit(void) +static void __exit dscp_mt_exit(void) { - xt_unregister_targets(dscp_tg_reg, ARRAY_SIZE(dscp_tg_reg)); + xt_unregister_matches(dscp_mt_reg, ARRAY_SIZE(dscp_mt_reg)); } -module_init(dscp_tg_init); -module_exit(dscp_tg_exit); +module_init(dscp_mt_init); +module_exit(dscp_mt_exit); diff --git a/net/netfilter/xt_HL.c b/net/netfilter/xt_HL.c index 7873b834c3004..c1a70f8f04417 100644 --- a/net/netfilter/xt_HL.c +++ b/net/netfilter/xt_HL.c @@ -1,159 +1,93 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * TTL modification target for IP tables - * (C) 2000,2005 by Harald Welte + * IP tables module for matching the value of the TTL + * (C) 2000,2001 by Harald Welte * - * Hop Limit modification target for ip6tables - * Maciej Soltysiak + * Hop Limit matching module + * (C) 2001-2002 Maciej Soltysiak */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include -#include + #include #include -#include +#include +#include #include -#include -#include +#include +#include -MODULE_AUTHOR("Harald Welte "); MODULE_AUTHOR("Maciej Soltysiak "); -MODULE_DESCRIPTION("Xtables: Hoplimit/TTL Limit field modification target"); +MODULE_DESCRIPTION("Xtables: Hoplimit/TTL field match"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("ipt_ttl"); +MODULE_ALIAS("ip6t_hl"); -static unsigned int -ttl_tg(struct sk_buff *skb, const struct xt_action_param *par) +static bool ttl_mt(const struct sk_buff *skb, struct xt_action_param *par) { - struct iphdr *iph; - const struct ipt_TTL_info *info = par->targinfo; - int new_ttl; - - if (skb_ensure_writable(skb, sizeof(*iph))) - return NF_DROP; - - iph = ip_hdr(skb); + const struct ipt_ttl_info *info = par->matchinfo; + const u8 ttl = ip_hdr(skb)->ttl; switch (info->mode) { - case IPT_TTL_SET: - new_ttl = info->ttl; - break; - case IPT_TTL_INC: - new_ttl = iph->ttl + info->ttl; - if (new_ttl > 255) - new_ttl = 255; - break; - case IPT_TTL_DEC: - new_ttl = iph->ttl - info->ttl; - if (new_ttl < 0) - new_ttl = 0; - break; - default: - new_ttl = iph->ttl; - break; + case IPT_TTL_EQ: + return ttl == info->ttl; + case IPT_TTL_NE: + return ttl != info->ttl; + case IPT_TTL_LT: + return ttl < info->ttl; + case IPT_TTL_GT: + return ttl > info->ttl; } - if (new_ttl != iph->ttl) { - csum_replace2(&iph->check, htons(iph->ttl << 8), - htons(new_ttl << 8)); - iph->ttl = new_ttl; - } - - return XT_CONTINUE; + return false; } -static unsigned int -hl_tg6(struct sk_buff *skb, const struct xt_action_param *par) +static bool hl_mt6(const struct sk_buff *skb, struct xt_action_param *par) { - struct ipv6hdr *ip6h; - const struct ip6t_HL_info *info = par->targinfo; - int new_hl; - - if (skb_ensure_writable(skb, sizeof(*ip6h))) - return NF_DROP; - - ip6h = ipv6_hdr(skb); + const struct ip6t_hl_info *info = par->matchinfo; + const struct ipv6hdr *ip6h = ipv6_hdr(skb); switch (info->mode) { - case IP6T_HL_SET: - new_hl = info->hop_limit; - break; - case IP6T_HL_INC: - new_hl = ip6h->hop_limit + info->hop_limit; - if (new_hl > 255) - new_hl = 255; - break; - case IP6T_HL_DEC: - new_hl = ip6h->hop_limit - info->hop_limit; - if (new_hl < 0) - new_hl = 0; - break; - default: - new_hl = ip6h->hop_limit; - break; + case IP6T_HL_EQ: + return ip6h->hop_limit == info->hop_limit; + case IP6T_HL_NE: + return ip6h->hop_limit != info->hop_limit; + case IP6T_HL_LT: + return ip6h->hop_limit < info->hop_limit; + case IP6T_HL_GT: + return ip6h->hop_limit > info->hop_limit; } - ip6h->hop_limit = new_hl; - - return XT_CONTINUE; -} - -static int ttl_tg_check(const struct xt_tgchk_param *par) -{ - const struct ipt_TTL_info *info = par->targinfo; - - if (info->mode > IPT_TTL_MAXMODE) - return -EINVAL; - if (info->mode != IPT_TTL_SET && info->ttl == 0) - return -EINVAL; - return 0; -} - -static int hl_tg6_check(const struct xt_tgchk_param *par) -{ - const struct ip6t_HL_info *info = par->targinfo; - - if (info->mode > IP6T_HL_MAXMODE) - return -EINVAL; - if (info->mode != IP6T_HL_SET && info->hop_limit == 0) - return -EINVAL; - return 0; + return false; } -static struct xt_target hl_tg_reg[] __read_mostly = { +static struct xt_match hl_mt_reg[] __read_mostly = { { - .name = "TTL", + .name = "ttl", .revision = 0, .family = NFPROTO_IPV4, - .target = ttl_tg, - .targetsize = sizeof(struct ipt_TTL_info), - .table = "mangle", - .checkentry = ttl_tg_check, + .match = ttl_mt, + .matchsize = sizeof(struct ipt_ttl_info), .me = THIS_MODULE, }, { - .name = "HL", + .name = "hl", .revision = 0, .family = NFPROTO_IPV6, - .target = hl_tg6, - .targetsize = sizeof(struct ip6t_HL_info), - .table = "mangle", - .checkentry = hl_tg6_check, + .match = hl_mt6, + .matchsize = sizeof(struct ip6t_hl_info), .me = THIS_MODULE, }, }; -static int __init hl_tg_init(void) +static int __init hl_mt_init(void) { - return xt_register_targets(hl_tg_reg, ARRAY_SIZE(hl_tg_reg)); + return xt_register_matches(hl_mt_reg, ARRAY_SIZE(hl_mt_reg)); } -static void __exit hl_tg_exit(void) +static void __exit hl_mt_exit(void) { - xt_unregister_targets(hl_tg_reg, ARRAY_SIZE(hl_tg_reg)); + xt_unregister_matches(hl_mt_reg, ARRAY_SIZE(hl_mt_reg)); } -module_init(hl_tg_init); -module_exit(hl_tg_exit); -MODULE_ALIAS("ipt_TTL"); -MODULE_ALIAS("ip6t_HL"); +module_init(hl_mt_init); +module_exit(hl_mt_exit); diff --git a/net/netfilter/xt_RATEEST.c b/net/netfilter/xt_RATEEST.c index 2236455b10a36..72324bd976af8 100644 --- a/net/netfilter/xt_RATEEST.c +++ b/net/netfilter/xt_RATEEST.c @@ -5,225 +5,149 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include #include -#include +#include #include -#define RATEEST_HSIZE 16 -struct xt_rateest_net { - struct mutex hash_lock; - struct hlist_head hash[RATEEST_HSIZE]; -}; - -static unsigned int xt_rateest_id; - -static unsigned int jhash_rnd __read_mostly; - -static unsigned int xt_rateest_hash(const char *name) -{ - return jhash(name, FIELD_SIZEOF(struct xt_rateest, name), jhash_rnd) & - (RATEEST_HSIZE - 1); -} - -static void xt_rateest_hash_insert(struct xt_rateest_net *xn, - struct xt_rateest *est) +static bool +xt_rateest_mt(const struct sk_buff *skb, struct xt_action_param *par) { - unsigned int h; - - h = xt_rateest_hash(est->name); - hlist_add_head(&est->list, &xn->hash[h]); -} + const struct xt_rateest_match_info *info = par->matchinfo; + struct gnet_stats_rate_est64 sample = {0}; + u_int32_t bps1, bps2, pps1, pps2; + bool ret = true; + + gen_estimator_read(&info->est1->rate_est, &sample); + + if (info->flags & XT_RATEEST_MATCH_DELTA) { + bps1 = info->bps1 >= sample.bps ? info->bps1 - sample.bps : 0; + pps1 = info->pps1 >= sample.pps ? info->pps1 - sample.pps : 0; + } else { + bps1 = sample.bps; + pps1 = sample.pps; + } -static struct xt_rateest *__xt_rateest_lookup(struct xt_rateest_net *xn, - const char *name) -{ - struct xt_rateest *est; - unsigned int h; - - h = xt_rateest_hash(name); - hlist_for_each_entry(est, &xn->hash[h], list) { - if (strcmp(est->name, name) == 0) { - est->refcnt++; - return est; + if (info->flags & XT_RATEEST_MATCH_ABS) { + bps2 = info->bps2; + pps2 = info->pps2; + } else { + gen_estimator_read(&info->est2->rate_est, &sample); + + if (info->flags & XT_RATEEST_MATCH_DELTA) { + bps2 = info->bps2 >= sample.bps ? info->bps2 - sample.bps : 0; + pps2 = info->pps2 >= sample.pps ? info->pps2 - sample.pps : 0; + } else { + bps2 = sample.bps; + pps2 = sample.pps; } } - return NULL; -} - -struct xt_rateest *xt_rateest_lookup(struct net *net, const char *name) -{ - struct xt_rateest_net *xn = net_generic(net, xt_rateest_id); - struct xt_rateest *est; - - mutex_lock(&xn->hash_lock); - est = __xt_rateest_lookup(xn, name); - mutex_unlock(&xn->hash_lock); - return est; -} -EXPORT_SYMBOL_GPL(xt_rateest_lookup); - -void xt_rateest_put(struct net *net, struct xt_rateest *est) -{ - struct xt_rateest_net *xn = net_generic(net, xt_rateest_id); - - mutex_lock(&xn->hash_lock); - if (--est->refcnt == 0) { - hlist_del(&est->list); - gen_kill_estimator(&est->rate_est); - /* - * gen_estimator est_timer() might access est->lock or bstats, - * wait a RCU grace period before freeing 'est' - */ - kfree_rcu(est, rcu); + switch (info->mode) { + case XT_RATEEST_MATCH_LT: + if (info->flags & XT_RATEEST_MATCH_BPS) + ret &= bps1 < bps2; + if (info->flags & XT_RATEEST_MATCH_PPS) + ret &= pps1 < pps2; + break; + case XT_RATEEST_MATCH_GT: + if (info->flags & XT_RATEEST_MATCH_BPS) + ret &= bps1 > bps2; + if (info->flags & XT_RATEEST_MATCH_PPS) + ret &= pps1 > pps2; + break; + case XT_RATEEST_MATCH_EQ: + if (info->flags & XT_RATEEST_MATCH_BPS) + ret &= bps1 == bps2; + if (info->flags & XT_RATEEST_MATCH_PPS) + ret &= pps1 == pps2; + break; } - mutex_unlock(&xn->hash_lock); + + ret ^= info->flags & XT_RATEEST_MATCH_INVERT ? true : false; + return ret; } -EXPORT_SYMBOL_GPL(xt_rateest_put); -static unsigned int -xt_rateest_tg(struct sk_buff *skb, const struct xt_action_param *par) +static int xt_rateest_mt_checkentry(const struct xt_mtchk_param *par) { - const struct xt_rateest_target_info *info = par->targinfo; - struct gnet_stats_basic_packed *stats = &info->est->bstats; + struct xt_rateest_match_info *info = par->matchinfo; + struct xt_rateest *est1, *est2; + int ret = -EINVAL; - spin_lock_bh(&info->est->lock); - stats->bytes += skb->len; - stats->packets++; - spin_unlock_bh(&info->est->lock); + if (hweight32(info->flags & (XT_RATEEST_MATCH_ABS | + XT_RATEEST_MATCH_REL)) != 1) + goto err1; - return XT_CONTINUE; -} + if (!(info->flags & (XT_RATEEST_MATCH_BPS | XT_RATEEST_MATCH_PPS))) + goto err1; -static int xt_rateest_tg_checkentry(const struct xt_tgchk_param *par) -{ - struct xt_rateest_net *xn = net_generic(par->net, xt_rateest_id); - struct xt_rateest_target_info *info = par->targinfo; - struct xt_rateest *est; - struct { - struct nlattr opt; - struct gnet_estimator est; - } cfg; - int ret; - - net_get_random_once(&jhash_rnd, sizeof(jhash_rnd)); - - mutex_lock(&xn->hash_lock); - est = __xt_rateest_lookup(xn, info->name); - if (est) { - mutex_unlock(&xn->hash_lock); - /* - * If estimator parameters are specified, they must match the - * existing estimator. - */ - if ((!info->interval && !info->ewma_log) || - (info->interval != est->params.interval || - info->ewma_log != est->params.ewma_log)) { - xt_rateest_put(par->net, est); - return -EINVAL; - } - info->est = est; - return 0; + switch (info->mode) { + case XT_RATEEST_MATCH_EQ: + case XT_RATEEST_MATCH_LT: + case XT_RATEEST_MATCH_GT: + break; + default: + goto err1; } - ret = -ENOMEM; - est = kzalloc(sizeof(*est), GFP_KERNEL); - if (!est) + ret = -ENOENT; + est1 = xt_rateest_lookup(par->net, info->name1); + if (!est1) goto err1; - strlcpy(est->name, info->name, sizeof(est->name)); - spin_lock_init(&est->lock); - est->refcnt = 1; - est->params.interval = info->interval; - est->params.ewma_log = info->ewma_log; - - cfg.opt.nla_len = nla_attr_size(sizeof(cfg.est)); - cfg.opt.nla_type = TCA_STATS_RATE_EST; - cfg.est.interval = info->interval; - cfg.est.ewma_log = info->ewma_log; - - ret = gen_new_estimator(&est->bstats, NULL, &est->rate_est, - &est->lock, NULL, &cfg.opt); - if (ret < 0) - goto err2; - - info->est = est; - xt_rateest_hash_insert(xn, est); - mutex_unlock(&xn->hash_lock); + est2 = NULL; + if (info->flags & XT_RATEEST_MATCH_REL) { + est2 = xt_rateest_lookup(par->net, info->name2); + if (!est2) + goto err2; + } + + info->est1 = est1; + info->est2 = est2; return 0; err2: - kfree(est); + xt_rateest_put(par->net, est1); err1: - mutex_unlock(&xn->hash_lock); return ret; } -static void xt_rateest_tg_destroy(const struct xt_tgdtor_param *par) +static void xt_rateest_mt_destroy(const struct xt_mtdtor_param *par) { - struct xt_rateest_target_info *info = par->targinfo; + struct xt_rateest_match_info *info = par->matchinfo; - xt_rateest_put(par->net, info->est); + xt_rateest_put(par->net, info->est1); + if (info->est2) + xt_rateest_put(par->net, info->est2); } -static struct xt_target xt_rateest_tg_reg __read_mostly = { - .name = "RATEEST", +static struct xt_match xt_rateest_mt_reg __read_mostly = { + .name = "rateest", .revision = 0, .family = NFPROTO_UNSPEC, - .target = xt_rateest_tg, - .checkentry = xt_rateest_tg_checkentry, - .destroy = xt_rateest_tg_destroy, - .targetsize = sizeof(struct xt_rateest_target_info), - .usersize = offsetof(struct xt_rateest_target_info, est), + .match = xt_rateest_mt, + .checkentry = xt_rateest_mt_checkentry, + .destroy = xt_rateest_mt_destroy, + .matchsize = sizeof(struct xt_rateest_match_info), + .usersize = offsetof(struct xt_rateest_match_info, est1), .me = THIS_MODULE, }; -static __net_init int xt_rateest_net_init(struct net *net) +static int __init xt_rateest_mt_init(void) { - struct xt_rateest_net *xn = net_generic(net, xt_rateest_id); - int i; - - mutex_init(&xn->hash_lock); - for (i = 0; i < ARRAY_SIZE(xn->hash); i++) - INIT_HLIST_HEAD(&xn->hash[i]); - return 0; + return xt_register_match(&xt_rateest_mt_reg); } -static struct pernet_operations xt_rateest_net_ops = { - .init = xt_rateest_net_init, - .id = &xt_rateest_id, - .size = sizeof(struct xt_rateest_net), -}; - -static int __init xt_rateest_tg_init(void) +static void __exit xt_rateest_mt_fini(void) { - int err = register_pernet_subsys(&xt_rateest_net_ops); - - if (err) - return err; - return xt_register_target(&xt_rateest_tg_reg); + xt_unregister_match(&xt_rateest_mt_reg); } -static void __exit xt_rateest_tg_fini(void) -{ - xt_unregister_target(&xt_rateest_tg_reg); - unregister_pernet_subsys(&xt_rateest_net_ops); -} - - MODULE_AUTHOR("Patrick McHardy "); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Xtables: packet rate estimator"); -MODULE_ALIAS("ipt_RATEEST"); -MODULE_ALIAS("ip6t_RATEEST"); -module_init(xt_rateest_tg_init); -module_exit(xt_rateest_tg_fini); +MODULE_DESCRIPTION("xtables rate estimator match"); +MODULE_ALIAS("ipt_rateest"); +MODULE_ALIAS("ip6t_rateest"); +module_init(xt_rateest_mt_init); +module_exit(xt_rateest_mt_fini); diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c index 122db9fbb9f49..37704ab017992 100644 --- a/net/netfilter/xt_TCPMSS.c +++ b/net/netfilter/xt_TCPMSS.c @@ -1,345 +1,107 @@ // SPDX-License-Identifier: GPL-2.0-only -/* - * This is a module which is used for setting the MSS option in TCP packets. - * - * Copyright (C) 2000 Marc Boucher - * Copyright (C) 2007 Patrick McHardy +/* Kernel module to match TCP MSS values. */ + +/* Copyright (C) 2000 Marc Boucher + * Portions (C) 2005 by Harald Welte */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include -#include -#include -#include -#include -#include -#include -#include -#include #include +#include +#include + #include #include -#include -#include -#include MODULE_LICENSE("GPL"); MODULE_AUTHOR("Marc Boucher "); -MODULE_DESCRIPTION("Xtables: TCP Maximum Segment Size (MSS) adjustment"); -MODULE_ALIAS("ipt_TCPMSS"); -MODULE_ALIAS("ip6t_TCPMSS"); +MODULE_DESCRIPTION("Xtables: TCP MSS match"); +MODULE_ALIAS("ipt_tcpmss"); +MODULE_ALIAS("ip6t_tcpmss"); -static inline unsigned int -optlen(const u_int8_t *opt, unsigned int offset) +static bool +tcpmss_mt(const struct sk_buff *skb, struct xt_action_param *par) { - /* Beware zero-length options: make finite progress */ - if (opt[offset] <= TCPOPT_NOP || opt[offset+1] == 0) - return 1; - else - return opt[offset+1]; -} - -static u_int32_t tcpmss_reverse_mtu(struct net *net, - const struct sk_buff *skb, - unsigned int family) -{ - struct flowi fl; - struct rtable *rt = NULL; - u_int32_t mtu = ~0U; - - if (family == PF_INET) { - struct flowi4 *fl4 = &fl.u.ip4; - memset(fl4, 0, sizeof(*fl4)); - fl4->daddr = ip_hdr(skb)->saddr; - } else { - struct flowi6 *fl6 = &fl.u.ip6; - - memset(fl6, 0, sizeof(*fl6)); - fl6->daddr = ipv6_hdr(skb)->saddr; - } - - nf_route(net, (struct dst_entry **)&rt, &fl, false, family); - if (rt != NULL) { - mtu = dst_mtu(&rt->dst); - dst_release(&rt->dst); - } - return mtu; -} - -static int -tcpmss_mangle_packet(struct sk_buff *skb, - const struct xt_action_param *par, - unsigned int family, - unsigned int tcphoff, - unsigned int minlen) -{ - const struct xt_tcpmss_info *info = par->targinfo; - struct tcphdr *tcph; - int len, tcp_hdrlen; - unsigned int i; - __be16 oldval; - u16 newmss; - u8 *opt; - - /* This is a fragment, no TCP header is available */ - if (par->fragoff != 0) - return 0; - - if (skb_ensure_writable(skb, skb->len)) - return -1; - - len = skb->len - tcphoff; - if (len < (int)sizeof(struct tcphdr)) - return -1; - - tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); - tcp_hdrlen = tcph->doff * 4; - - if (len < tcp_hdrlen || tcp_hdrlen < sizeof(struct tcphdr)) - return -1; - - if (info->mss == XT_TCPMSS_CLAMP_PMTU) { - struct net *net = xt_net(par); - unsigned int in_mtu = tcpmss_reverse_mtu(net, skb, family); - unsigned int min_mtu = min(dst_mtu(skb_dst(skb)), in_mtu); - - if (min_mtu <= minlen) { - net_err_ratelimited("unknown or invalid path-MTU (%u)\n", - min_mtu); - return -1; - } - newmss = min_mtu - minlen; - } else - newmss = info->mss; - - opt = (u_int8_t *)tcph; - for (i = sizeof(struct tcphdr); i <= tcp_hdrlen - TCPOLEN_MSS; i += optlen(opt, i)) { - if (opt[i] == TCPOPT_MSS && opt[i+1] == TCPOLEN_MSS) { - u_int16_t oldmss; - - oldmss = (opt[i+2] << 8) | opt[i+3]; - - /* Never increase MSS, even when setting it, as - * doing so results in problems for hosts that rely - * on MSS being set correctly. - */ - if (oldmss <= newmss) - return 0; - - opt[i+2] = (newmss & 0xff00) >> 8; - opt[i+3] = newmss & 0x00ff; - - inet_proto_csum_replace2(&tcph->check, skb, - htons(oldmss), htons(newmss), - false); - return 0; + const struct xt_tcpmss_match_info *info = par->matchinfo; + const struct tcphdr *th; + struct tcphdr _tcph; + /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */ + const u_int8_t *op; + u8 _opt[15 * 4 - sizeof(_tcph)]; + unsigned int i, optlen; + + /* If we don't have the whole header, drop packet. */ + th = skb_header_pointer(skb, par->thoff, sizeof(_tcph), &_tcph); + if (th == NULL) + goto dropit; + + /* Malformed. */ + if (th->doff*4 < sizeof(*th)) + goto dropit; + + optlen = th->doff*4 - sizeof(*th); + if (!optlen) + goto out; + + /* Truncated options. */ + op = skb_header_pointer(skb, par->thoff + sizeof(*th), optlen, _opt); + if (op == NULL) + goto dropit; + + for (i = 0; i < optlen; ) { + if (op[i] == TCPOPT_MSS + && (optlen - i) >= TCPOLEN_MSS + && op[i+1] == TCPOLEN_MSS) { + u_int16_t mssval; + + mssval = (op[i+2] << 8) | op[i+3]; + + return (mssval >= info->mss_min && + mssval <= info->mss_max) ^ info->invert; } + if (op[i] < 2) + i++; + else + i += op[i+1] ? : 1; } +out: + return info->invert; - /* There is data after the header so the option can't be added - * without moving it, and doing so may make the SYN packet - * itself too large. Accept the packet unmodified instead. - */ - if (len > tcp_hdrlen) - return 0; - - /* tcph->doff has 4 bits, do not wrap it to 0 */ - if (tcp_hdrlen >= 15 * 4) - return 0; - - /* - * MSS Option not found ?! add it.. - */ - if (skb_tailroom(skb) < TCPOLEN_MSS) { - if (pskb_expand_head(skb, 0, - TCPOLEN_MSS - skb_tailroom(skb), - GFP_ATOMIC)) - return -1; - tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); - } - - skb_put(skb, TCPOLEN_MSS); - - /* - * IPv4: RFC 1122 states "If an MSS option is not received at - * connection setup, TCP MUST assume a default send MSS of 536". - * IPv6: RFC 2460 states IPv6 has a minimum MTU of 1280 and a minimum - * length IPv6 header of 60, ergo the default MSS value is 1220 - * Since no MSS was provided, we must use the default values - */ - if (xt_family(par) == NFPROTO_IPV4) - newmss = min(newmss, (u16)536); - else - newmss = min(newmss, (u16)1220); - - opt = (u_int8_t *)tcph + sizeof(struct tcphdr); - memmove(opt + TCPOLEN_MSS, opt, len - sizeof(struct tcphdr)); - - inet_proto_csum_replace2(&tcph->check, skb, - htons(len), htons(len + TCPOLEN_MSS), true); - opt[0] = TCPOPT_MSS; - opt[1] = TCPOLEN_MSS; - opt[2] = (newmss & 0xff00) >> 8; - opt[3] = newmss & 0x00ff; - - inet_proto_csum_replace4(&tcph->check, skb, 0, *((__be32 *)opt), false); - - oldval = ((__be16 *)tcph)[6]; - tcph->doff += TCPOLEN_MSS/4; - inet_proto_csum_replace2(&tcph->check, skb, - oldval, ((__be16 *)tcph)[6], false); - return TCPOLEN_MSS; -} - -static unsigned int -tcpmss_tg4(struct sk_buff *skb, const struct xt_action_param *par) -{ - struct iphdr *iph = ip_hdr(skb); - __be16 newlen; - int ret; - - ret = tcpmss_mangle_packet(skb, par, - PF_INET, - iph->ihl * 4, - sizeof(*iph) + sizeof(struct tcphdr)); - if (ret < 0) - return NF_DROP; - if (ret > 0) { - iph = ip_hdr(skb); - newlen = htons(ntohs(iph->tot_len) + ret); - csum_replace2(&iph->check, iph->tot_len, newlen); - iph->tot_len = newlen; - } - return XT_CONTINUE; -} - -#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) -static unsigned int -tcpmss_tg6(struct sk_buff *skb, const struct xt_action_param *par) -{ - struct ipv6hdr *ipv6h = ipv6_hdr(skb); - u8 nexthdr; - __be16 frag_off, oldlen, newlen; - int tcphoff; - int ret; - - nexthdr = ipv6h->nexthdr; - tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr, &frag_off); - if (tcphoff < 0) - return NF_DROP; - ret = tcpmss_mangle_packet(skb, par, - PF_INET6, - tcphoff, - sizeof(*ipv6h) + sizeof(struct tcphdr)); - if (ret < 0) - return NF_DROP; - if (ret > 0) { - ipv6h = ipv6_hdr(skb); - oldlen = ipv6h->payload_len; - newlen = htons(ntohs(oldlen) + ret); - if (skb->ip_summed == CHECKSUM_COMPLETE) - skb->csum = csum_add(csum_sub(skb->csum, oldlen), - newlen); - ipv6h->payload_len = newlen; - } - return XT_CONTINUE; -} -#endif - -/* Must specify -p tcp --syn */ -static inline bool find_syn_match(const struct xt_entry_match *m) -{ - const struct xt_tcp *tcpinfo = (const struct xt_tcp *)m->data; - - if (strcmp(m->u.kernel.match->name, "tcp") == 0 && - tcpinfo->flg_cmp & TCPHDR_SYN && - !(tcpinfo->invflags & XT_TCP_INV_FLAGS)) - return true; - +dropit: + par->hotdrop = true; return false; } -static int tcpmss_tg4_check(const struct xt_tgchk_param *par) -{ - const struct xt_tcpmss_info *info = par->targinfo; - const struct ipt_entry *e = par->entryinfo; - const struct xt_entry_match *ematch; - - if (info->mss == XT_TCPMSS_CLAMP_PMTU && - (par->hook_mask & ~((1 << NF_INET_FORWARD) | - (1 << NF_INET_LOCAL_OUT) | - (1 << NF_INET_POST_ROUTING))) != 0) { - pr_info_ratelimited("path-MTU clamping only supported in FORWARD, OUTPUT and POSTROUTING hooks\n"); - return -EINVAL; - } - if (par->nft_compat) - return 0; - - xt_ematch_foreach(ematch, e) - if (find_syn_match(ematch)) - return 0; - pr_info_ratelimited("Only works on TCP SYN packets\n"); - return -EINVAL; -} - -#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) -static int tcpmss_tg6_check(const struct xt_tgchk_param *par) -{ - const struct xt_tcpmss_info *info = par->targinfo; - const struct ip6t_entry *e = par->entryinfo; - const struct xt_entry_match *ematch; - - if (info->mss == XT_TCPMSS_CLAMP_PMTU && - (par->hook_mask & ~((1 << NF_INET_FORWARD) | - (1 << NF_INET_LOCAL_OUT) | - (1 << NF_INET_POST_ROUTING))) != 0) { - pr_info_ratelimited("path-MTU clamping only supported in FORWARD, OUTPUT and POSTROUTING hooks\n"); - return -EINVAL; - } - if (par->nft_compat) - return 0; - - xt_ematch_foreach(ematch, e) - if (find_syn_match(ematch)) - return 0; - pr_info_ratelimited("Only works on TCP SYN packets\n"); - return -EINVAL; -} -#endif - -static struct xt_target tcpmss_tg_reg[] __read_mostly = { +static struct xt_match tcpmss_mt_reg[] __read_mostly = { { + .name = "tcpmss", .family = NFPROTO_IPV4, - .name = "TCPMSS", - .checkentry = tcpmss_tg4_check, - .target = tcpmss_tg4, - .targetsize = sizeof(struct xt_tcpmss_info), + .match = tcpmss_mt, + .matchsize = sizeof(struct xt_tcpmss_match_info), .proto = IPPROTO_TCP, .me = THIS_MODULE, }, -#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) { + .name = "tcpmss", .family = NFPROTO_IPV6, - .name = "TCPMSS", - .checkentry = tcpmss_tg6_check, - .target = tcpmss_tg6, - .targetsize = sizeof(struct xt_tcpmss_info), + .match = tcpmss_mt, + .matchsize = sizeof(struct xt_tcpmss_match_info), .proto = IPPROTO_TCP, .me = THIS_MODULE, }, -#endif }; -static int __init tcpmss_tg_init(void) +static int __init tcpmss_mt_init(void) { - return xt_register_targets(tcpmss_tg_reg, ARRAY_SIZE(tcpmss_tg_reg)); + return xt_register_matches(tcpmss_mt_reg, ARRAY_SIZE(tcpmss_mt_reg)); } -static void __exit tcpmss_tg_exit(void) +static void __exit tcpmss_mt_exit(void) { - xt_unregister_targets(tcpmss_tg_reg, ARRAY_SIZE(tcpmss_tg_reg)); + xt_unregister_matches(tcpmss_mt_reg, ARRAY_SIZE(tcpmss_mt_reg)); } -module_init(tcpmss_tg_init); -module_exit(tcpmss_tg_exit); +module_init(tcpmss_mt_init); +module_exit(tcpmss_mt_exit); diff --git a/tools/memory-model/litmus-tests/Z6.0+pooncelock+poonceLock+pombonce.litmus b/tools/memory-model/litmus-tests/Z6.0+pooncelock+poonceLock+pombonce.litmus index 415248fb66990..10a2aa04cd078 100644 --- a/tools/memory-model/litmus-tests/Z6.0+pooncelock+poonceLock+pombonce.litmus +++ b/tools/memory-model/litmus-tests/Z6.0+pooncelock+poonceLock+pombonce.litmus @@ -1,12 +1,11 @@ -C Z6.0+pooncelock+poonceLock+pombonce +C Z6.0+pooncelock+pooncelock+pombonce (* - * Result: Never + * Result: Sometimes * - * This litmus test demonstrates how smp_mb__after_spinlock() may be - * used to ensure that accesses in different critical sections for a - * given lock running on different CPUs are nevertheless seen in order - * by CPUs not holding that lock. + * This example demonstrates that a pair of accesses made by different + * processes each while holding a given lock will not necessarily be + * seen as ordered by a third process not holding that lock. *) {} @@ -24,7 +23,6 @@ P1(int *y, int *z, spinlock_t *mylock) int r0; spin_lock(mylock); - smp_mb__after_spinlock(); r0 = READ_ONCE(*y); WRITE_ONCE(*z, 1); spin_unlock(mylock);