aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/minisocks.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/dccp/minisocks.c')
-rw-r--r--net/dccp/minisocks.c24
1 files changed, 16 insertions, 8 deletions
diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c
index e267e6f4c9a5..abd07a443219 100644
--- a/net/dccp/minisocks.c
+++ b/net/dccp/minisocks.c
@@ -142,6 +142,13 @@ struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
142 struct dccp_request_sock *dreq = dccp_rsk(req); 142 struct dccp_request_sock *dreq = dccp_rsk(req);
143 bool own_req; 143 bool own_req;
144 144
145 /* TCP/DCCP listeners became lockless.
146 * DCCP stores complex state in its request_sock, so we need
147 * a protection for them, now this code runs without being protected
148 * by the parent (listener) lock.
149 */
150 spin_lock_bh(&dreq->dreq_lock);
151
145 /* Check for retransmitted REQUEST */ 152 /* Check for retransmitted REQUEST */
146 if (dccp_hdr(skb)->dccph_type == DCCP_PKT_REQUEST) { 153 if (dccp_hdr(skb)->dccph_type == DCCP_PKT_REQUEST) {
147 154
@@ -156,7 +163,7 @@ struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
156 inet_rtx_syn_ack(sk, req); 163 inet_rtx_syn_ack(sk, req);
157 } 164 }
158 /* Network Duplicate, discard packet */ 165 /* Network Duplicate, discard packet */
159 return NULL; 166 goto out;
160 } 167 }
161 168
162 DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_PACKET_ERROR; 169 DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_PACKET_ERROR;
@@ -182,20 +189,20 @@ struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
182 189
183 child = inet_csk(sk)->icsk_af_ops->syn_recv_sock(sk, skb, req, NULL, 190 child = inet_csk(sk)->icsk_af_ops->syn_recv_sock(sk, skb, req, NULL,
184 req, &own_req); 191 req, &own_req);
185 if (!child) 192 if (child) {
186 goto listen_overflow; 193 child = inet_csk_complete_hashdance(sk, child, req, own_req);
187 194 goto out;
188 return inet_csk_complete_hashdance(sk, child, req, own_req); 195 }
189 196
190listen_overflow:
191 dccp_pr_debug("listen_overflow!\n");
192 DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_TOO_BUSY; 197 DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_TOO_BUSY;
193drop: 198drop:
194 if (dccp_hdr(skb)->dccph_type != DCCP_PKT_RESET) 199 if (dccp_hdr(skb)->dccph_type != DCCP_PKT_RESET)
195 req->rsk_ops->send_reset(sk, skb); 200 req->rsk_ops->send_reset(sk, skb);
196 201
197 inet_csk_reqsk_queue_drop(sk, req); 202 inet_csk_reqsk_queue_drop(sk, req);
198 return NULL; 203out:
204 spin_unlock_bh(&dreq->dreq_lock);
205 return child;
199} 206}
200 207
201EXPORT_SYMBOL_GPL(dccp_check_req); 208EXPORT_SYMBOL_GPL(dccp_check_req);
@@ -246,6 +253,7 @@ int dccp_reqsk_init(struct request_sock *req,
246{ 253{
247 struct dccp_request_sock *dreq = dccp_rsk(req); 254 struct dccp_request_sock *dreq = dccp_rsk(req);
248 255
256 spin_lock_init(&dreq->dreq_lock);
249 inet_rsk(req)->ir_rmt_port = dccp_hdr(skb)->dccph_sport; 257 inet_rsk(req)->ir_rmt_port = dccp_hdr(skb)->dccph_sport;
250 inet_rsk(req)->ir_num = ntohs(dccp_hdr(skb)->dccph_dport); 258 inet_rsk(req)->ir_num = ntohs(dccp_hdr(skb)->dccph_dport);
251 inet_rsk(req)->acked = 0; 259 inet_rsk(req)->acked = 0;