aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/dccp/dccp.h2
-rw-r--r--net/dccp/ipv4.c9
-rw-r--r--net/dccp/ipv6.c16
-rw-r--r--net/dccp/output.c53
-rw-r--r--net/dccp/timer.c20
5 files changed, 56 insertions, 44 deletions
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index 743d85fcd651..1c2e3ec2eb57 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -226,7 +226,7 @@ static inline void dccp_csum_outgoing(struct sk_buff *skb)
226 226
227extern void dccp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb); 227extern void dccp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb);
228 228
229extern int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb); 229extern int dccp_retransmit_skb(struct sock *sk);
230 230
231extern void dccp_send_ack(struct sock *sk); 231extern void dccp_send_ack(struct sock *sk);
232extern void dccp_reqsk_send_ack(struct sk_buff *sk, struct request_sock *rsk); 232extern void dccp_reqsk_send_ack(struct sk_buff *sk, struct request_sock *rsk);
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index a835b88237cb..882c5c4de69e 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -196,8 +196,8 @@ static inline void dccp_do_pmtu_discovery(struct sock *sk,
196static void dccp_v4_err(struct sk_buff *skb, u32 info) 196static void dccp_v4_err(struct sk_buff *skb, u32 info)
197{ 197{
198 const struct iphdr *iph = (struct iphdr *)skb->data; 198 const struct iphdr *iph = (struct iphdr *)skb->data;
199 const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + 199 const u8 offset = iph->ihl << 2;
200 (iph->ihl << 2)); 200 const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset);
201 struct dccp_sock *dp; 201 struct dccp_sock *dp;
202 struct inet_sock *inet; 202 struct inet_sock *inet;
203 const int type = icmp_hdr(skb)->type; 203 const int type = icmp_hdr(skb)->type;
@@ -207,7 +207,8 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
207 int err; 207 int err;
208 struct net *net = dev_net(skb->dev); 208 struct net *net = dev_net(skb->dev);
209 209
210 if (skb->len < (iph->ihl << 2) + 8) { 210 if (skb->len < offset + sizeof(*dh) ||
211 skb->len < offset + __dccp_basic_hdr_len(dh)) {
211 ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS); 212 ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);
212 return; 213 return;
213 } 214 }
@@ -238,7 +239,7 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
238 dp = dccp_sk(sk); 239 dp = dccp_sk(sk);
239 seq = dccp_hdr_seq(dh); 240 seq = dccp_hdr_seq(dh);
240 if ((1 << sk->sk_state) & ~(DCCPF_REQUESTING | DCCPF_LISTEN) && 241 if ((1 << sk->sk_state) & ~(DCCPF_REQUESTING | DCCPF_LISTEN) &&
241 !between48(seq, dp->dccps_swl, dp->dccps_swh)) { 242 !between48(seq, dp->dccps_awl, dp->dccps_awh)) {
242 NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS); 243 NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
243 goto out; 244 goto out;
244 } 245 }
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index da509127e00c..5e1ee0da2c40 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -89,12 +89,19 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
89{ 89{
90 struct ipv6hdr *hdr = (struct ipv6hdr *)skb->data; 90 struct ipv6hdr *hdr = (struct ipv6hdr *)skb->data;
91 const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset); 91 const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset);
92 struct dccp_sock *dp;
92 struct ipv6_pinfo *np; 93 struct ipv6_pinfo *np;
93 struct sock *sk; 94 struct sock *sk;
94 int err; 95 int err;
95 __u64 seq; 96 __u64 seq;
96 struct net *net = dev_net(skb->dev); 97 struct net *net = dev_net(skb->dev);
97 98
99 if (skb->len < offset + sizeof(*dh) ||
100 skb->len < offset + __dccp_basic_hdr_len(dh)) {
101 ICMP6_INC_STATS_BH(__in6_dev_get(skb->dev), ICMP6_MIB_INERRORS);
102 return;
103 }
104
98 sk = inet6_lookup(net, &dccp_hashinfo, 105 sk = inet6_lookup(net, &dccp_hashinfo,
99 &hdr->daddr, dh->dccph_dport, 106 &hdr->daddr, dh->dccph_dport,
100 &hdr->saddr, dh->dccph_sport, inet6_iif(skb)); 107 &hdr->saddr, dh->dccph_sport, inet6_iif(skb));
@@ -116,6 +123,14 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
116 if (sk->sk_state == DCCP_CLOSED) 123 if (sk->sk_state == DCCP_CLOSED)
117 goto out; 124 goto out;
118 125
126 dp = dccp_sk(sk);
127 seq = dccp_hdr_seq(dh);
128 if ((1 << sk->sk_state) & ~(DCCPF_REQUESTING | DCCPF_LISTEN) &&
129 !between48(seq, dp->dccps_awl, dp->dccps_awh)) {
130 NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
131 goto out;
132 }
133
119 np = inet6_sk(sk); 134 np = inet6_sk(sk);
120 135
121 if (type == ICMPV6_PKT_TOOBIG) { 136 if (type == ICMPV6_PKT_TOOBIG) {
@@ -168,7 +183,6 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
168 183
169 icmpv6_err_convert(type, code, &err); 184 icmpv6_err_convert(type, code, &err);
170 185
171 seq = dccp_hdr_seq(dh);
172 /* Might be for an request_sock */ 186 /* Might be for an request_sock */
173 switch (sk->sk_state) { 187 switch (sk->sk_state) {
174 struct request_sock *req, **prev; 188 struct request_sock *req, **prev;
diff --git a/net/dccp/output.c b/net/dccp/output.c
index fe20068c5d8e..d06945c7d3df 100644
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -53,8 +53,11 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
53 dccp_packet_hdr_len(dcb->dccpd_type); 53 dccp_packet_hdr_len(dcb->dccpd_type);
54 int err, set_ack = 1; 54 int err, set_ack = 1;
55 u64 ackno = dp->dccps_gsr; 55 u64 ackno = dp->dccps_gsr;
56 56 /*
57 dccp_inc_seqno(&dp->dccps_gss); 57 * Increment GSS here already in case the option code needs it.
58 * Update GSS for real only if option processing below succeeds.
59 */
60 dcb->dccpd_seq = ADD48(dp->dccps_gss, 1);
58 61
59 switch (dcb->dccpd_type) { 62 switch (dcb->dccpd_type) {
60 case DCCP_PKT_DATA: 63 case DCCP_PKT_DATA:
@@ -66,6 +69,9 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
66 69
67 case DCCP_PKT_REQUEST: 70 case DCCP_PKT_REQUEST:
68 set_ack = 0; 71 set_ack = 0;
72 /* Use ISS on the first (non-retransmitted) Request. */
73 if (icsk->icsk_retransmits == 0)
74 dcb->dccpd_seq = dp->dccps_iss;
69 /* fall through */ 75 /* fall through */
70 76
71 case DCCP_PKT_SYNC: 77 case DCCP_PKT_SYNC:
@@ -84,8 +90,6 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
84 break; 90 break;
85 } 91 }
86 92
87 dcb->dccpd_seq = dp->dccps_gss;
88
89 if (dccp_insert_options(sk, skb)) { 93 if (dccp_insert_options(sk, skb)) {
90 kfree_skb(skb); 94 kfree_skb(skb);
91 return -EPROTO; 95 return -EPROTO;
@@ -103,7 +107,7 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
103 /* XXX For now we're using only 48 bits sequence numbers */ 107 /* XXX For now we're using only 48 bits sequence numbers */
104 dh->dccph_x = 1; 108 dh->dccph_x = 1;
105 109
106 dp->dccps_awh = dp->dccps_gss; 110 dccp_update_gss(sk, dcb->dccpd_seq);
107 dccp_hdr_set_seq(dh, dp->dccps_gss); 111 dccp_hdr_set_seq(dh, dp->dccps_gss);
108 if (set_ack) 112 if (set_ack)
109 dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), ackno); 113 dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), ackno);
@@ -112,6 +116,11 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
112 case DCCP_PKT_REQUEST: 116 case DCCP_PKT_REQUEST:
113 dccp_hdr_request(skb)->dccph_req_service = 117 dccp_hdr_request(skb)->dccph_req_service =
114 dp->dccps_service; 118 dp->dccps_service;
119 /*
120 * Limit Ack window to ISS <= P.ackno <= GSS, so that
121 * only Responses to Requests we sent are considered.
122 */
123 dp->dccps_awl = dp->dccps_iss;
115 break; 124 break;
116 case DCCP_PKT_RESET: 125 case DCCP_PKT_RESET:
117 dccp_hdr_reset(skb)->dccph_reset_code = 126 dccp_hdr_reset(skb)->dccph_reset_code =
@@ -284,14 +293,26 @@ void dccp_write_xmit(struct sock *sk, int block)
284 } 293 }
285} 294}
286 295
287int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb) 296/**
297 * dccp_retransmit_skb - Retransmit Request, Close, or CloseReq packets
298 * There are only four retransmittable packet types in DCCP:
299 * - Request in client-REQUEST state (sec. 8.1.1),
300 * - CloseReq in server-CLOSEREQ state (sec. 8.3),
301 * - Close in node-CLOSING state (sec. 8.3),
302 * - Acks in client-PARTOPEN state (sec. 8.1.5, handled by dccp_delack_timer()).
303 * This function expects sk->sk_send_head to contain the original skb.
304 */
305int dccp_retransmit_skb(struct sock *sk)
288{ 306{
307 WARN_ON(sk->sk_send_head == NULL);
308
289 if (inet_csk(sk)->icsk_af_ops->rebuild_header(sk) != 0) 309 if (inet_csk(sk)->icsk_af_ops->rebuild_header(sk) != 0)
290 return -EHOSTUNREACH; /* Routing failure or similar. */ 310 return -EHOSTUNREACH; /* Routing failure or similar. */
291 311
292 return dccp_transmit_skb(sk, (skb_cloned(skb) ? 312 /* this count is used to distinguish original and retransmitted skb */
293 pskb_copy(skb, GFP_ATOMIC): 313 inet_csk(sk)->icsk_retransmits++;
294 skb_clone(skb, GFP_ATOMIC))); 314
315 return dccp_transmit_skb(sk, skb_clone(sk->sk_send_head, GFP_ATOMIC));
295} 316}
296 317
297struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst, 318struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
@@ -437,19 +458,7 @@ static inline void dccp_connect_init(struct sock *sk)
437 458
438 dccp_sync_mss(sk, dst_mtu(dst)); 459 dccp_sync_mss(sk, dst_mtu(dst));
439 460
440 /* 461 /* Initialise GAR as per 8.5; AWL/AWH are set in dccp_transmit_skb() */
441 * SWL and AWL are initially adjusted so that they are not less than
442 * the initial Sequence Numbers received and sent, respectively:
443 * SWL := max(GSR + 1 - floor(W/4), ISR),
444 * AWL := max(GSS - W' + 1, ISS).
445 * These adjustments MUST be applied only at the beginning of the
446 * connection.
447 */
448 dccp_update_gss(sk, dp->dccps_iss);
449 dccp_set_seqno(&dp->dccps_awl, max48(dp->dccps_awl, dp->dccps_iss));
450
451 /* S.GAR - greatest valid acknowledgement number received on a non-Sync;
452 * initialized to S.ISS (sec. 8.5) */
453 dp->dccps_gar = dp->dccps_iss; 462 dp->dccps_gar = dp->dccps_iss;
454 463
455 icsk->icsk_retransmits = 0; 464 icsk->icsk_retransmits = 0;
diff --git a/net/dccp/timer.c b/net/dccp/timer.c
index 6a5b961b6f5c..54b3c7e9e016 100644
--- a/net/dccp/timer.c
+++ b/net/dccp/timer.c
@@ -99,21 +99,11 @@ static void dccp_retransmit_timer(struct sock *sk)
99 } 99 }
100 100
101 /* 101 /*
102 * sk->sk_send_head has to have one skb with
103 * DCCP_SKB_CB(skb)->dccpd_type set to one of the retransmittable DCCP
104 * packet types. The only packets eligible for retransmission are:
105 * -- Requests in client-REQUEST state (sec. 8.1.1)
106 * -- Acks in client-PARTOPEN state (sec. 8.1.5)
107 * -- CloseReq in server-CLOSEREQ state (sec. 8.3)
108 * -- Close in node-CLOSING state (sec. 8.3) */
109 WARN_ON(sk->sk_send_head == NULL);
110
111 /*
112 * More than than 4MSL (8 minutes) has passed, a RESET(aborted) was 102 * More than than 4MSL (8 minutes) has passed, a RESET(aborted) was
113 * sent, no need to retransmit, this sock is dead. 103 * sent, no need to retransmit, this sock is dead.
114 */ 104 */
115 if (dccp_write_timeout(sk)) 105 if (dccp_write_timeout(sk))
116 goto out; 106 return;
117 107
118 /* 108 /*
119 * We want to know the number of packets retransmitted, not the 109 * We want to know the number of packets retransmitted, not the
@@ -122,30 +112,28 @@ static void dccp_retransmit_timer(struct sock *sk)
122 if (icsk->icsk_retransmits == 0) 112 if (icsk->icsk_retransmits == 0)
123 DCCP_INC_STATS_BH(DCCP_MIB_TIMEOUTS); 113 DCCP_INC_STATS_BH(DCCP_MIB_TIMEOUTS);
124 114
125 if (dccp_retransmit_skb(sk, sk->sk_send_head) < 0) { 115 if (dccp_retransmit_skb(sk) != 0) {
126 /* 116 /*
127 * Retransmission failed because of local congestion, 117 * Retransmission failed because of local congestion,
128 * do not backoff. 118 * do not backoff.
129 */ 119 */
130 if (icsk->icsk_retransmits == 0) 120 if (--icsk->icsk_retransmits == 0)
131 icsk->icsk_retransmits = 1; 121 icsk->icsk_retransmits = 1;
132 inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, 122 inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
133 min(icsk->icsk_rto, 123 min(icsk->icsk_rto,
134 TCP_RESOURCE_PROBE_INTERVAL), 124 TCP_RESOURCE_PROBE_INTERVAL),
135 DCCP_RTO_MAX); 125 DCCP_RTO_MAX);
136 goto out; 126 return;
137 } 127 }
138 128
139backoff: 129backoff:
140 icsk->icsk_backoff++; 130 icsk->icsk_backoff++;
141 icsk->icsk_retransmits++;
142 131
143 icsk->icsk_rto = min(icsk->icsk_rto << 1, DCCP_RTO_MAX); 132 icsk->icsk_rto = min(icsk->icsk_rto << 1, DCCP_RTO_MAX);
144 inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto, 133 inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto,
145 DCCP_RTO_MAX); 134 DCCP_RTO_MAX);
146 if (icsk->icsk_retransmits > sysctl_dccp_retries1) 135 if (icsk->icsk_retransmits > sysctl_dccp_retries1)
147 __sk_dst_reset(sk); 136 __sk_dst_reset(sk);
148out:;
149} 137}
150 138
151static void dccp_write_timer(unsigned long data) 139static void dccp_write_timer(unsigned long data)