Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: conntrack: unify established states for SCTP paths

An SCTP endpoint can start an association through a path and tear it
down over another one. That means the initial path will not see the
shutdown sequence, and the conntrack entry will remain in ESTABLISHED
state for 5 days.

By merging the HEARTBEAT_ACKED and ESTABLISHED states into one
ESTABLISHED state, there remains no difference between a primary or
secondary path. The timeout for the merged ESTABLISHED state is set to
210 seconds (hb_interval * max_path_retrans + rto_max). So, even if a
path doesn't see the shutdown sequence, it will expire in a reasonable
amount of time.

With this change in place, there is now more than one state from which
we can transition to ESTABLISHED, COOKIE_ECHOED and HEARTBEAT_SENT, so
handle the setting of ASSURED bit whenever a state change has happened
and the new state is ESTABLISHED. Removed the check for dir==REPLY since
the transition to ESTABLISHED can happen only in the reply direction.

Fixes: 9fb9cbb1082d ("[NETFILTER]: Add nf_conntrack subsystem.")
Signed-off-by: Sriram Yagnaraman <sriram.yagnaraman@est.tech>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

Sriram Yagnaraman and committed by
Pablo Neira Ayuso
a44b7651 13bd9b31

+44 -71
+3 -7
Documentation/networking/nf_conntrack-sysctl.rst
··· 173 173 default 3 174 174 175 175 nf_conntrack_sctp_timeout_established - INTEGER (seconds) 176 - default 432000 (5 days) 176 + default 210 177 + 178 + Default is set to (hb_interval * path_max_retrans + rto_max) 177 179 178 180 nf_conntrack_sctp_timeout_shutdown_sent - INTEGER (seconds) 179 181 default 0.3 ··· 191 189 192 190 This timeout is used to setup conntrack entry on secondary paths. 193 191 Default is set to hb_interval. 194 - 195 - nf_conntrack_sctp_timeout_heartbeat_acked - INTEGER (seconds) 196 - default 210 197 - 198 - This timeout is used to setup conntrack entry on secondary paths. 199 - Default is set to (hb_interval * path_max_retrans + rto_max) 200 192 201 193 nf_conntrack_udp_timeout - INTEGER (seconds) 202 194 default 30
+1 -1
include/uapi/linux/netfilter/nf_conntrack_sctp.h
··· 15 15 SCTP_CONNTRACK_SHUTDOWN_RECD, 16 16 SCTP_CONNTRACK_SHUTDOWN_ACK_SENT, 17 17 SCTP_CONNTRACK_HEARTBEAT_SENT, 18 - SCTP_CONNTRACK_HEARTBEAT_ACKED, 18 + SCTP_CONNTRACK_HEARTBEAT_ACKED, /* no longer used */ 19 19 SCTP_CONNTRACK_MAX 20 20 }; 21 21
+39 -54
net/netfilter/nf_conntrack_proto_sctp.c
··· 27 27 #include <net/netfilter/nf_conntrack_ecache.h> 28 28 #include <net/netfilter/nf_conntrack_timeout.h> 29 29 30 - /* FIXME: Examine ipfilter's timeouts and conntrack transitions more 31 - closely. They're more complex. --RR 32 - 33 - And so for me for SCTP :D -Kiran */ 34 - 35 30 static const char *const sctp_conntrack_names[] = { 36 - "NONE", 37 - "CLOSED", 38 - "COOKIE_WAIT", 39 - "COOKIE_ECHOED", 40 - "ESTABLISHED", 41 - "SHUTDOWN_SENT", 42 - "SHUTDOWN_RECD", 43 - "SHUTDOWN_ACK_SENT", 44 - "HEARTBEAT_SENT", 45 - "HEARTBEAT_ACKED", 31 + [SCTP_CONNTRACK_NONE] = "NONE", 32 + [SCTP_CONNTRACK_CLOSED] = "CLOSED", 33 + [SCTP_CONNTRACK_COOKIE_WAIT] = "COOKIE_WAIT", 34 + [SCTP_CONNTRACK_COOKIE_ECHOED] = "COOKIE_ECHOED", 35 + [SCTP_CONNTRACK_ESTABLISHED] = "ESTABLISHED", 36 + [SCTP_CONNTRACK_SHUTDOWN_SENT] = "SHUTDOWN_SENT", 37 + [SCTP_CONNTRACK_SHUTDOWN_RECD] = "SHUTDOWN_RECD", 38 + [SCTP_CONNTRACK_SHUTDOWN_ACK_SENT] = "SHUTDOWN_ACK_SENT", 39 + [SCTP_CONNTRACK_HEARTBEAT_SENT] = "HEARTBEAT_SENT", 46 40 }; 47 41 48 42 #define SECS * HZ ··· 48 54 [SCTP_CONNTRACK_CLOSED] = 10 SECS, 49 55 [SCTP_CONNTRACK_COOKIE_WAIT] = 3 SECS, 50 56 [SCTP_CONNTRACK_COOKIE_ECHOED] = 3 SECS, 51 - [SCTP_CONNTRACK_ESTABLISHED] = 5 DAYS, 57 + [SCTP_CONNTRACK_ESTABLISHED] = 210 SECS, 52 58 [SCTP_CONNTRACK_SHUTDOWN_SENT] = 300 SECS / 1000, 53 59 [SCTP_CONNTRACK_SHUTDOWN_RECD] = 300 SECS / 1000, 54 60 [SCTP_CONNTRACK_SHUTDOWN_ACK_SENT] = 3 SECS, 55 61 [SCTP_CONNTRACK_HEARTBEAT_SENT] = 30 SECS, 56 - [SCTP_CONNTRACK_HEARTBEAT_ACKED] = 210 SECS, 57 62 }; 58 63 59 64 #define SCTP_FLAG_HEARTBEAT_VTAG_FAILED 1 ··· 66 73 #define sSR SCTP_CONNTRACK_SHUTDOWN_RECD 67 74 #define sSA SCTP_CONNTRACK_SHUTDOWN_ACK_SENT 68 75 #define sHS SCTP_CONNTRACK_HEARTBEAT_SENT 69 - #define sHA SCTP_CONNTRACK_HEARTBEAT_ACKED 70 76 #define sIV SCTP_CONNTRACK_MAX 71 77 72 78 /* ··· 88 96 CLOSED - We have seen a SHUTDOWN_COMPLETE chunk in the direction of 89 97 the SHUTDOWN chunk. Connection is closed. 90 98 HEARTBEAT_SENT - We have seen a HEARTBEAT in a new flow. 91 - HEARTBEAT_ACKED - We have seen a HEARTBEAT-ACK in the direction opposite to 92 - that of the HEARTBEAT chunk. Secondary connection is 93 - established. 94 99 */ 95 100 96 101 /* TODO ··· 104 115 static const u8 sctp_conntracks[2][11][SCTP_CONNTRACK_MAX] = { 105 116 { 106 117 /* ORIGINAL */ 107 - /* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS, sHA */ 108 - /* init */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCW, sHA}, 109 - /* init_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCL, sHA}, 110 - /* abort */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL}, 111 - /* shutdown */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA, sCL, sSS}, 112 - /* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA, sSA, sHA}, 113 - /* error */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCL, sHA},/* Can't have Stale cookie*/ 114 - /* cookie_echo */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA, sCL, sHA},/* 5.2.4 - Big TODO */ 115 - /* cookie_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCL, sHA},/* Can't come in orig dir */ 116 - /* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL, sCL, sHA}, 117 - /* heartbeat */ {sHS, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS, sHA}, 118 - /* heartbeat_ack*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS, sHA} 118 + /* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS */ 119 + /* init */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCW}, 120 + /* init_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCL}, 121 + /* abort */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL}, 122 + /* shutdown */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA, sCL}, 123 + /* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA, sSA}, 124 + /* error */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCL},/* Can't have Stale cookie*/ 125 + /* cookie_echo */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA, sCL},/* 5.2.4 - Big TODO */ 126 + /* cookie_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCL},/* Can't come in orig dir */ 127 + /* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL, sCL}, 128 + /* heartbeat */ {sHS, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS}, 129 + /* heartbeat_ack*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS}, 119 130 }, 120 131 { 121 132 /* REPLY */ 122 - /* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS, sHA */ 123 - /* init */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sIV, sHA},/* INIT in sCL Big TODO */ 124 - /* init_ack */ {sIV, sCW, sCW, sCE, sES, sSS, sSR, sSA, sIV, sHA}, 125 - /* abort */ {sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sIV, sCL}, 126 - /* shutdown */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA, sIV, sSR}, 127 - /* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA, sIV, sHA}, 128 - /* error */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA, sIV, sHA}, 129 - /* cookie_echo */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sIV, sHA},/* Can't come in reply dir */ 130 - /* cookie_ack */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA, sIV, sHA}, 131 - /* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL, sIV, sHA}, 132 - /* heartbeat */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS, sHA}, 133 - /* heartbeat_ack*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHA, sHA} 133 + /* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS */ 134 + /* init */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sIV},/* INIT in sCL Big TODO */ 135 + /* init_ack */ {sIV, sCW, sCW, sCE, sES, sSS, sSR, sSA, sIV}, 136 + /* abort */ {sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sIV}, 137 + /* shutdown */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA, sIV}, 138 + /* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA, sIV}, 139 + /* error */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA, sIV}, 140 + /* cookie_echo */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sIV},/* Can't come in reply dir */ 141 + /* cookie_ack */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA, sIV}, 142 + /* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL, sIV}, 143 + /* heartbeat */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS}, 144 + /* heartbeat_ack*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sES}, 134 145 } 135 146 }; 136 147 ··· 497 508 } 498 509 499 510 ct->proto.sctp.state = new_state; 500 - if (old_state != new_state) 511 + if (old_state != new_state) { 501 512 nf_conntrack_event_cache(IPCT_PROTOINFO, ct); 513 + if (new_state == SCTP_CONNTRACK_ESTABLISHED && 514 + !test_and_set_bit(IPS_ASSURED_BIT, &ct->status)) 515 + nf_conntrack_event_cache(IPCT_ASSURED, ct); 516 + } 502 517 } 503 518 spin_unlock_bh(&ct->lock); 504 519 ··· 515 522 timeouts = nf_sctp_pernet(nf_ct_net(ct))->timeouts; 516 523 517 524 nf_ct_refresh_acct(ct, ctinfo, skb, timeouts[new_state]); 518 - 519 - if (old_state == SCTP_CONNTRACK_COOKIE_ECHOED && 520 - dir == IP_CT_DIR_REPLY && 521 - new_state == SCTP_CONNTRACK_ESTABLISHED) { 522 - pr_debug("Setting assured bit\n"); 523 - set_bit(IPS_ASSURED_BIT, &ct->status); 524 - nf_conntrack_event_cache(IPCT_ASSURED, ct); 525 - } 526 525 527 526 return NF_ACCEPT; 528 527
-8
net/netfilter/nf_conntrack_standalone.c
··· 601 601 NF_SYSCTL_CT_PROTO_TIMEOUT_SCTP_SHUTDOWN_RECD, 602 602 NF_SYSCTL_CT_PROTO_TIMEOUT_SCTP_SHUTDOWN_ACK_SENT, 603 603 NF_SYSCTL_CT_PROTO_TIMEOUT_SCTP_HEARTBEAT_SENT, 604 - NF_SYSCTL_CT_PROTO_TIMEOUT_SCTP_HEARTBEAT_ACKED, 605 604 #endif 606 605 #ifdef CONFIG_NF_CT_PROTO_DCCP 607 606 NF_SYSCTL_CT_PROTO_TIMEOUT_DCCP_REQUEST, ··· 885 886 .mode = 0644, 886 887 .proc_handler = proc_dointvec_jiffies, 887 888 }, 888 - [NF_SYSCTL_CT_PROTO_TIMEOUT_SCTP_HEARTBEAT_ACKED] = { 889 - .procname = "nf_conntrack_sctp_timeout_heartbeat_acked", 890 - .maxlen = sizeof(unsigned int), 891 - .mode = 0644, 892 - .proc_handler = proc_dointvec_jiffies, 893 - }, 894 889 #endif 895 890 #ifdef CONFIG_NF_CT_PROTO_DCCP 896 891 [NF_SYSCTL_CT_PROTO_TIMEOUT_DCCP_REQUEST] = { ··· 1028 1035 XASSIGN(SHUTDOWN_RECD, sn); 1029 1036 XASSIGN(SHUTDOWN_ACK_SENT, sn); 1030 1037 XASSIGN(HEARTBEAT_SENT, sn); 1031 - XASSIGN(HEARTBEAT_ACKED, sn); 1032 1038 #undef XASSIGN 1033 1039 #endif 1034 1040 }