aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/proto.c
diff options
context:
space:
mode:
authorGerrit Renker <gerrit@erg.abdn.ac.uk>2008-09-04 01:30:19 -0400
committerGerrit Renker <gerrit@erg.abdn.ac.uk>2008-09-04 01:45:30 -0400
commit3a53a9adfa269da7fa40fc476f09e46155c0143d (patch)
tree9090efbd2aa9cc24ea50c63336a029e018509529 /net/dccp/proto.c
parentc926c6aed3e444e8c88a768f063b2de8fd6ae760 (diff)
dccp: Integration of dynamic feature activation - part 1 (socket setup)
This first patch out of three replaces the hardcoded default settings with initialisation code for the dynamic feature negotiation. Note on retransmitting Confirm options: --------------------------------------- This patch also defers flushing the client feature-negotiation queue, due to the following considerations. As long as the client is in PARTOPEN, it needs to retransmit the Confirm options for the Change options received on the DCCP-Response from the server. Otherwise, if the packet containing the Confirm options gets dropped in the network, the connection aborts due to undefined feature negotiation state. Thanks to Leandro Melo de Sales who reported a bug in an earlier revision of the patch set, resulting from not retransmitting the Confirm options. The patch now ensures that the client feature-negotiation queue is flushed only when entering the OPEN state. Since confirmed Change options are removed as soon as they are confirmed (in the DCCP-Response), this ensures that Confirm options are retransmitted. Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk> Acked-by: Ian McDonald <ian.mcdonald@jandi.co.nz>
Diffstat (limited to 'net/dccp/proto.c')
-rw-r--r--net/dccp/proto.c46
1 files changed, 6 insertions, 40 deletions
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 6550452d59e2..0d420790b795 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -67,6 +67,9 @@ void dccp_set_state(struct sock *sk, const int state)
67 case DCCP_OPEN: 67 case DCCP_OPEN:
68 if (oldstate != DCCP_OPEN) 68 if (oldstate != DCCP_OPEN)
69 DCCP_INC_STATS(DCCP_MIB_CURRESTAB); 69 DCCP_INC_STATS(DCCP_MIB_CURRESTAB);
70 /* Client retransmits all Confirm options until entering OPEN */
71 if (oldstate == DCCP_PARTOPEN)
72 dccp_feat_list_purge(&dccp_sk(sk)->dccps_featneg);
70 break; 73 break;
71 74
72 case DCCP_CLOSED: 75 case DCCP_CLOSED:
@@ -175,7 +178,6 @@ EXPORT_SYMBOL_GPL(dccp_state_name);
175int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized) 178int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)
176{ 179{
177 struct dccp_sock *dp = dccp_sk(sk); 180 struct dccp_sock *dp = dccp_sk(sk);
178 struct dccp_minisock *dmsk = dccp_msk(sk);
179 struct inet_connection_sock *icsk = inet_csk(sk); 181 struct inet_connection_sock *icsk = inet_csk(sk);
180 182
181 dccp_minisock_init(&dp->dccps_minisock); 183 dccp_minisock_init(&dp->dccps_minisock);
@@ -194,45 +196,9 @@ int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)
194 dccp_init_xmit_timers(sk); 196 dccp_init_xmit_timers(sk);
195 197
196 INIT_LIST_HEAD(&dp->dccps_featneg); 198 INIT_LIST_HEAD(&dp->dccps_featneg);
197 /* 199 /* control socket doesn't need feat nego */
198 * FIXME: We're hardcoding the CCID, and doing this at this point makes 200 if (likely(ctl_sock_initialized))
199 * the listening (master) sock get CCID control blocks, which is not 201 return dccp_feat_init(sk);
200 * necessary, but for now, to not mess with the test userspace apps,
201 * lets leave it here, later the real solution is to do this in a
202 * setsockopt(CCIDs-I-want/accept). -acme
203 */
204 if (likely(ctl_sock_initialized)) {
205 int rc = dccp_feat_init(sk);
206
207 if (rc)
208 return rc;
209
210 if (dmsk->dccpms_send_ack_vector) {
211 dp->dccps_hc_rx_ackvec = dccp_ackvec_alloc(GFP_KERNEL);
212 if (dp->dccps_hc_rx_ackvec == NULL)
213 return -ENOMEM;
214 }
215 dp->dccps_hc_rx_ccid = ccid_hc_rx_new(dmsk->dccpms_rx_ccid,
216 sk, GFP_KERNEL);
217 dp->dccps_hc_tx_ccid = ccid_hc_tx_new(dmsk->dccpms_tx_ccid,
218 sk, GFP_KERNEL);
219 if (unlikely(dp->dccps_hc_rx_ccid == NULL ||
220 dp->dccps_hc_tx_ccid == NULL)) {
221 ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk);
222 ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk);
223 if (dmsk->dccpms_send_ack_vector) {
224 dccp_ackvec_free(dp->dccps_hc_rx_ackvec);
225 dp->dccps_hc_rx_ackvec = NULL;
226 }
227 dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;
228 return -ENOMEM;
229 }
230 } else {
231 /* control socket doesn't need feat nego */
232 INIT_LIST_HEAD(&dmsk->dccpms_pending);
233 INIT_LIST_HEAD(&dmsk->dccpms_conf);
234 }
235
236 return 0; 202 return 0;
237} 203}
238 204