|
@@ -421,8 +421,13 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
|
|
goto out_invalid_packet;
|
|
goto out_invalid_packet;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * If option processing (Step 8) failed, return 1 here so that
|
|
|
|
+ * dccp_v4_do_rcv() sends a Reset. The Reset code depends on
|
|
|
|
+ * the option type and is set in dccp_parse_options().
|
|
|
|
+ */
|
|
if (dccp_parse_options(sk, NULL, skb))
|
|
if (dccp_parse_options(sk, NULL, skb))
|
|
- goto out_invalid_packet;
|
|
|
|
|
|
+ return 1;
|
|
|
|
|
|
/* Obtain usec RTT sample from SYN exchange (used by CCID 3) */
|
|
/* Obtain usec RTT sample from SYN exchange (used by CCID 3) */
|
|
if (likely(dp->dccps_options_received.dccpor_timestamp_echo))
|
|
if (likely(dp->dccps_options_received.dccpor_timestamp_echo))
|
|
@@ -475,6 +480,15 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
|
|
*/
|
|
*/
|
|
dccp_set_state(sk, DCCP_PARTOPEN);
|
|
dccp_set_state(sk, DCCP_PARTOPEN);
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * If feature negotiation was successful, activate features now;
|
|
|
|
+ * an activation failure means that this host could not activate
|
|
|
|
+ * one ore more features (e.g. insufficient memory), which would
|
|
|
|
+ * leave at least one feature in an undefined state.
|
|
|
|
+ */
|
|
|
|
+ if (dccp_feat_activate_values(sk, &dp->dccps_featneg))
|
|
|
|
+ goto unable_to_proceed;
|
|
|
|
+
|
|
/* Make sure socket is routed, for correct metrics. */
|
|
/* Make sure socket is routed, for correct metrics. */
|
|
icsk->icsk_af_ops->rebuild_header(sk);
|
|
icsk->icsk_af_ops->rebuild_header(sk);
|
|
|
|
|
|
@@ -509,6 +523,16 @@ out_invalid_packet:
|
|
/* dccp_v4_do_rcv will send a reset */
|
|
/* dccp_v4_do_rcv will send a reset */
|
|
DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_PACKET_ERROR;
|
|
DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_PACKET_ERROR;
|
|
return 1;
|
|
return 1;
|
|
|
|
+
|
|
|
|
+unable_to_proceed:
|
|
|
|
+ DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_ABORTED;
|
|
|
|
+ /*
|
|
|
|
+ * We mark this socket as no longer usable, so that the loop in
|
|
|
|
+ * dccp_sendmsg() terminates and the application gets notified.
|
|
|
|
+ */
|
|
|
|
+ dccp_set_state(sk, DCCP_CLOSED);
|
|
|
|
+ sk->sk_err = ECOMM;
|
|
|
|
+ return 1;
|
|
}
|
|
}
|
|
|
|
|
|
static int dccp_rcv_respond_partopen_state_process(struct sock *sk,
|
|
static int dccp_rcv_respond_partopen_state_process(struct sock *sk,
|
|
@@ -600,7 +624,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
- if (sk->sk_state != DCCP_REQUESTING) {
|
|
|
|
|
|
+ if (sk->sk_state != DCCP_REQUESTING && sk->sk_state != DCCP_RESPOND) {
|
|
if (dccp_check_seqno(sk, skb))
|
|
if (dccp_check_seqno(sk, skb))
|
|
goto discard;
|
|
goto discard;
|
|
|
|
|
|
@@ -665,8 +689,6 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
|
|
return 1;
|
|
return 1;
|
|
|
|
|
|
case DCCP_REQUESTING:
|
|
case DCCP_REQUESTING:
|
|
- /* FIXME: do congestion control initialization */
|
|
|
|
-
|
|
|
|
queued = dccp_rcv_request_sent_state_process(sk, skb, dh, len);
|
|
queued = dccp_rcv_request_sent_state_process(sk, skb, dh, len);
|
|
if (queued >= 0)
|
|
if (queued >= 0)
|
|
return queued;
|
|
return queued;
|