diff options
Diffstat (limited to 'net')
| -rw-r--r-- | net/dccp/dccp.h | 1 | ||||
| -rw-r--r-- | net/dccp/input.c | 29 | ||||
| -rw-r--r-- | net/dccp/proto.c | 1 | ||||
| -rw-r--r-- | net/dccp/sysctl.c | 10 | 
4 files changed, 32 insertions, 9 deletions
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index e2822018320..a602d9212c6 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -92,6 +92,7 @@ extern int  sysctl_dccp_feat_ack_ratio;  extern int  sysctl_dccp_feat_send_ack_vector;  extern int  sysctl_dccp_feat_send_ndp_count;  extern int  sysctl_dccp_tx_qlen; +extern int  sysctl_dccp_sync_ratelimit;  /*   *	48-bit sequence number arithmetic (signed and unsigned) diff --git a/net/dccp/input.c b/net/dccp/input.c index 86ad3ba0649..19d7e1dbd87 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c @@ -122,6 +122,23 @@ static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb)  		    (ackno != DCCP_PKT_WITHOUT_ACK_SEQ))  			dp->dccps_gar = ackno;  	} else { +		unsigned long now = jiffies; +		/* +		 *   Step 6: Check sequence numbers +		 *      Otherwise, +		 *         If P.type == Reset, +		 *            Send Sync packet acknowledging S.GSR +		 *         Otherwise, +		 *            Send Sync packet acknowledging P.seqno +		 *      Drop packet and return +		 * +		 *   These Syncs are rate-limited as per RFC 4340, 7.5.4: +		 *   at most 1 / (dccp_sync_rate_limit * HZ) Syncs per second. +		 */ +		if (time_before(now, (dp->dccps_rate_last + +				      sysctl_dccp_sync_ratelimit))) +			return 0; +  		DCCP_WARN("DCCP: Step 6 failed for %s packet, "  			  "(LSWL(%llu) <= P.seqno(%llu) <= S.SWH(%llu)) and "  			  "(P.ackno %s or LAWL(%llu) <= P.ackno(%llu) <= S.AWH(%llu), " @@ -132,15 +149,9 @@ static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb)  							      : "exists",  			  (unsigned long long) lawl, (unsigned long long) ackno,  			  (unsigned long long) dp->dccps_awh); -		/* -		 *   Step 6: Check sequence numbers -		 *      Otherwise, -		 *         If P.type == Reset, -		 *            Send Sync packet acknowledging S.GSR -		 *         Otherwise, -		 *            Send Sync packet acknowledging P.seqno -		 *      Drop packet and return -		 */ + +		dp->dccps_rate_last = now; +  		if (dh->dccph_type == DCCP_PKT_RESET)  			seqno = dp->dccps_gsr;  		dccp_send_sync(sk, seqno, DCCP_PKT_SYNC); diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 14ec1d21452..604de8bfa06 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -219,6 +219,7 @@ int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)  	sk->sk_write_space	= dccp_write_space;  	icsk->icsk_sync_mss	= dccp_sync_mss;  	dp->dccps_mss_cache	= 536; +	dp->dccps_rate_last	= jiffies;  	dp->dccps_role		= DCCP_ROLE_UNDEFINED;  	dp->dccps_service	= DCCP_SERVICE_CODE_IS_ABSENT;  	dp->dccps_l_ack_ratio	= dp->dccps_r_ack_ratio = 1; diff --git a/net/dccp/sysctl.c b/net/dccp/sysctl.c index 1260aabac5e..9364b2fb4db 100644 --- a/net/dccp/sysctl.c +++ b/net/dccp/sysctl.c @@ -18,6 +18,9 @@  #error This file should not be compiled without CONFIG_SYSCTL defined  #endif +/* rate-limit for syncs in reply to sequence-invalid packets; RFC 4340, 7.5.4 */ +int sysctl_dccp_sync_ratelimit	__read_mostly = HZ / 8; +  static struct ctl_table dccp_default_table[] = {  	{  		.procname	= "seq_window", @@ -89,6 +92,13 @@ static struct ctl_table dccp_default_table[] = {  		.mode		= 0644,  		.proc_handler	= proc_dointvec,  	}, +	{ +		.procname	= "sync_ratelimit", +		.data		= &sysctl_dccp_sync_ratelimit, +		.maxlen		= sizeof(sysctl_dccp_sync_ratelimit), +		.mode		= 0644, +		.proc_handler	= proc_dointvec_ms_jiffies, +	},  	{ .ctl_name = 0, }  };  |