summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerrit Renker <gerrit@erg.abdn.ac.uk>2008-12-08 01:16:27 -0800
committerDavid S. Miller <davem@davemloft.net>2008-12-08 01:16:27 -0800
commit991d927c8652b2ab51bd8eef2b773bb2c77d457b (patch)
treeb21cab0ebe4b9f93a2c57b6dc6cd2f38ec828301
parent192b27ff35bad4cf76cc4239419e9f805935e4f8 (diff)
dccp: Integration of dynamic feature activation - part 3 (client side)
This integrates feature-activation in the client: 1. When dccp_parse_options() fails, the reset code is already set; request_sent\ _state_process() currently overrides this with `Packet Error', which is not intended - changed to use the reset code supplied by dccp_parse_options(). 2. When feature negotiation fails, the socket should be marked as not usable, so that the application is notified that an error occurred. This is achieved by a new label 'unable_to_proceed': generating an error code of `Aborted', setting the socket state to CLOSED, returning with ECOMM in sk_err. 3. Avoids parsing the Ack twice in Respond state by not doing option processing again in dccp_rcv_respond_partopen_state_process (as option processing has already been done on the request_sock in dccp_check_req). Since this addresses congestion-control initialisation, a corresponding FIXME has been removed. Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk> Acked-by: Ian McDonald <ian.mcdonald@jandi.co.nz> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/dccp/input.c30
1 files changed, 26 insertions, 4 deletions
diff --git a/net/dccp/input.c b/net/dccp/input.c
index 3070015edc75..0672b7e1763e 100644
--- a/net/dccp/input.c
+++ b/net/dccp/input.c
@@ -421,8 +421,13 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
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))
- goto out_invalid_packet;
+ return 1;
/* Obtain usec RTT sample from SYN exchange (used by CCID 3) */
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);
+ /*
+ * 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. */
icsk->icsk_af_ops->rebuild_header(sk);
@@ -509,6 +523,16 @@ out_invalid_packet:
/* dccp_v4_do_rcv will send a reset */
DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_PACKET_ERROR;
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,
@@ -600,7 +624,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
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))
goto discard;
@@ -665,8 +689,6 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
return 1;
case DCCP_REQUESTING:
- /* FIXME: do congestion control initialization */
-
queued = dccp_rcv_request_sent_state_process(sk, skb, dh, len);
if (queued >= 0)
return queued;