@@ -241,6 +241,8 @@ extern int sysctl_tcp_workaround_signed_windows;
extern int sysctl_tcp_slow_start_after_idle;
extern int sysctl_tcp_max_ssthresh;
extern int sysctl_tcp_cookie_size;
+extern int sysctl_tcp_syn_data_limit;
+extern int sysctl_tcp_syn_ack_data_limit;
extern int sysctl_tcp_thin_linear_timeouts;
extern int sysctl_tcp_thin_dupack;
@@ -30,6 +30,9 @@ static int tcp_adv_win_scale_min = -31;
static int tcp_adv_win_scale_max = 31;
static int ip_ttl_min = 1;
static int ip_ttl_max = 255;
+static int tcp_cookie_max = TCP_COOKIE_MAX;
+static int tcp_syn_data_max = TCP_MSS_DEFAULT - 40;
+static int tcp_syn_ack_data_max = TCP_MSS_DESIRED;
/* Update system visible IP port range */
static void set_local_port_range(int range[2])
@@ -588,7 +591,27 @@ static struct ctl_table ipv4_table[] = {
.data = &sysctl_tcp_cookie_size,
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = proc_dointvec
+ .proc_handler = proc_dointvec_minmax,
+ .extra1 = &zero,
+ .extra2 = &tcp_cookie_max,
+ },
+ {
+ .procname = "tcp_syn_data_limit",
+ .data = &sysctl_tcp_syn_data_limit,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_minmax,
+ .extra1 = &zero,
+ .extra2 = &tcp_syn_data_max,
+ },
+ {
+ .procname = "tcp_syn_ack_data_limit",
+ .data = &sysctl_tcp_syn_ack_data_limit,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_minmax,
+ .extra1 = &zero,
+ .extra2 = &tcp_syn_ack_data_max,
},
{
.procname = "tcp_thin_linear_timeouts",
@@ -63,6 +63,15 @@ int sysctl_tcp_slow_start_after_idle __read_mostly = 1;
int sysctl_tcp_cookie_size __read_mostly = 0; /* TCP_COOKIE_MAX */
EXPORT_SYMBOL_GPL(sysctl_tcp_cookie_size);
+int sysctl_tcp_syn_data_limit __read_mostly = TCP_MSS_DEFAULT - 40;
+EXPORT_SYMBOL_GPL(sysctl_tcp_syn_data_limit);
+
+/* As a matter of security policy, keep the initial setting small for most
+ * client systems to avoid their use in amplification DoS attacks.
+ */
+int sysctl_tcp_syn_ack_data_limit __read_mostly = 80; /* TCP_MSS_DESIRED */
+EXPORT_SYMBOL_GPL(sysctl_tcp_syn_ack_data_limit);
+
/* Account for new data that has been sent to the network. */
static void tcp_event_new_data_sent(struct sock *sk, struct sk_buff *skb)
@@ -2418,10 +2427,16 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
struct tcp_md5sig_key *md5;
int tcp_header_size;
int mss;
- int s_data_desired = 0;
+ int s_data_desired;
- if (cvp != NULL && cvp->s_data_constant && cvp->s_data_desired)
+ if (cvp != NULL &&
+ cvp->s_data_constant &&
+ cvp->s_data_desired > 0 &&
+ cvp->s_data_desired <= sysctl_tcp_syn_ack_data_limit)
s_data_desired = cvp->s_data_desired;
+ else
+ s_data_desired = 0;
+
skb = sock_wmalloc(sk, MAX_TCP_HEADER + 15 + s_data_desired, 1, GFP_ATOMIC);
if (skb == NULL)
return NULL;
Circa 15 months ago, my first submitted patch was a sysctl, and there was a conflict that appeared in a later merge of trees. Experts, am I in the right ballpark this time around? Later, I'll submit the manpage patch to linux-man@vger.kernel.org too. === Use most recently specified symbols of RFC-to-be-6013. Allows different global s_data limits for SYN and SYN_ACK. Signed-off-by: William.Allen.Simpson@gmail.com --- include/net/tcp.h | 2 ++ net/ipv4/sysctl_net_ipv4.c | 25 ++++++++++++++++++++++++- net/ipv4/tcp_output.c | 19 +++++++++++++++++-- 3 files changed, 43 insertions(+), 3 deletions(-)