Add IP_VS_SVC_F_SECURE_TCP to mark a virtual service for the DoS-hardened TCP connection state table, and IP_VS_CONN_F_SECURE_TCP to carry that capability on a connection so the TCP state machine can select the hardened table for it. The service flag is 0x0100: bits 0x0008/0x0010/0x0020 are the scheduler bits, so leave 0x0040/0x0080 free for schedulers. Set IP_VS_CONN_F_SECURE_TCP on every connection bound to a destination whose service carries IP_VS_SVC_F_SECURE_TCP. Signed-off-by: Adriano Cordova --- Changes in v2: - Let IP_VS_SVC_F_SECURE_TCP be 0x0100, leaving 0x0040/0x0080 free for scheduler flags. - Let IP_VS_CONN_F_SECURE_TCP be (1 << 17) and drop it from IP_VS_CONN_F_BACKUP_MASK. - Set the flag in ip_vs_bind_dest() instead of at every ip_vs_conn_new() call site. (no changes since v2) include/uapi/linux/ip_vs.h | 2 ++ net/netfilter/ipvs/ip_vs_conn.c | 4 ++++ net/netfilter/ipvs/ip_vs_core.c | 3 +++ 3 files changed, 9 insertions(+) diff --git a/include/uapi/linux/ip_vs.h b/include/uapi/linux/ip_vs.h index 2c37c6ac7525..ade170109ff4 100644 --- a/include/uapi/linux/ip_vs.h +++ b/include/uapi/linux/ip_vs.h @@ -27,6 +27,7 @@ #define IP_VS_SVC_F_SCHED_SH_FALLBACK IP_VS_SVC_F_SCHED1 /* SH fallback */ #define IP_VS_SVC_F_SCHED_SH_PORT IP_VS_SVC_F_SCHED2 /* SH use port */ +#define IP_VS_SVC_F_SECURE_TCP 0x0100 /* use the hardened TCP table */ /* * IPVS sync daemon states @@ -105,6 +106,7 @@ /* Flags that are not sent to backup server start from bit 16 */ #define IP_VS_CONN_F_NFCT (1 << 16) /* use netfilter conntrack */ +#define IP_VS_CONN_F_SECURE_TCP (1 << 17) /* use the hardened TCP table */ /* Connection flags from destination that can be changed by user space */ #define IP_VS_CONN_F_DEST_MASK (IP_VS_CONN_F_FWD_MASK | \ diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c index 6fa3e1dc534c..0b465298b64b 100644 --- a/net/netfilter/ipvs/ip_vs_conn.c +++ b/net/netfilter/ipvs/ip_vs_conn.c @@ -1090,6 +1090,7 @@ ip_vs_bind_dest(struct ip_vs_conn *cp, struct ip_vs_dest *dest) { unsigned int conn_flags; __u32 flags; + struct ip_vs_service *svc; /* if dest is NULL, then return directly */ if (!dest) @@ -1102,6 +1103,9 @@ ip_vs_bind_dest(struct ip_vs_conn *cp, struct ip_vs_dest *dest) if (cp->protocol != IPPROTO_UDP) conn_flags &= ~IP_VS_CONN_F_ONE_PACKET; flags = cp->flags; + svc = rcu_dereference(dest->svc); + if (svc && (svc->flags & IP_VS_SVC_F_SECURE_TCP)) + flags |= IP_VS_CONN_F_SECURE_TCP; /* Bind with the destination and its corresponding transmitter */ if (flags & IP_VS_CONN_F_SYNC) { /* Synced conns are hashed, so they can not get this flag */ diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index ba0957798bad..aa8a3a964ffd 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@ -784,6 +784,9 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb, IP_VS_CONN_F_ONE_PACKET : 0; union nf_inet_addr daddr = { .all = { 0, 0, 0, 0 } }; + if (svc->flags & IP_VS_SVC_F_SECURE_TCP) + flags |= IP_VS_CONN_F_SECURE_TCP; + /* create a new connection entry */ IP_VS_DBG(6, "%s(): create a cache_bypass entry\n", __func__); { -- 2.51.0