aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/proto.c
diff options
context:
space:
mode:
authorGerrit Renker <gerrit@erg.abdn.ac.uk>2008-12-08 04:15:26 -0500
committerDavid S. Miller <davem@davemloft.net>2008-12-08 04:15:26 -0500
commit6eb55d172b5f6de65afdae6285f8d732e4785bf7 (patch)
treedbc81b2610db0e62cf2c69a0da9dfa68ea3ff8c1 /net/dccp/proto.c
parentb74ca3a896b9ab5f952bc440154758e708c48884 (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. The patch also 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. Note on retransmitting Confirm options: --------------------------------------- Implementation experience showed that it is necessary to retransmit Confirm options. Thanks to Leandro Melo de Sales who reported a bug in an earlier revision of the patch set, resulting from not retransmitting these options. 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. 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>
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 db225f93cd5a..0941f8fe1675 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -61,6 +61,9 @@ void dccp_set_state(struct sock *sk, const int state)
61 case DCCP_OPEN: 61 case DCCP_OPEN:
62 if (oldstate != DCCP_OPEN) 62 if (oldstate != DCCP_OPEN)
63 DCCP_INC_STATS(DCCP_MIB_CURRESTAB); 63 DCCP_INC_STATS(DCCP_MIB_CURRESTAB);
64 /* Client retransmits all Confirm options until entering OPEN */
65 if (oldstate == DCCP_PARTOPEN)
66 dccp_feat_list_purge(&dccp_sk(sk)->dccps_featneg);
64 break; 67 break;
65 68
66 case DCCP_CLOSED: 69 case DCCP_CLOSED:
@@ -169,7 +172,6 @@ EXPORT_SYMBOL_GPL(dccp_state_name);
169int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized) 172int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)
170{ 173{
171 struct dccp_sock *dp = dccp_sk(sk); 174 struct dccp_sock *dp = dccp_sk(sk);
172 struct dccp_minisock *dmsk = dccp_msk(sk);
173 struct inet_connection_sock *icsk = inet_csk(sk); 175 struct inet_connection_sock *icsk = inet_csk(sk);
174 176
175 dccp_minisock_init(&dp->dccps_minisock); 177 dccp_minisock_init(&dp->dccps_minisock);
@@ -188,45 +190,9 @@ int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)
188 dccp_init_xmit_timers(sk); 190 dccp_init_xmit_timers(sk);
189 191
190 INIT_LIST_HEAD(&dp->dccps_featneg); 192 INIT_LIST_HEAD(&dp->dccps_featneg);
191 /* 193 /* control socket doesn't need feat nego */
192 * FIXME: We're hardcoding the CCID, and doing this at this point makes 194 if (likely(ctl_sock_initialized))
193 * the listening (master) sock get CCID control blocks, which is not 195 return dccp_feat_init(sk);
194 * necessary, but for now, to not mess with the test userspace apps,
195 * lets leave it here, later the real solution is to do this in a
196 * setsockopt(CCIDs-I-want/accept). -acme
197 */
198 if (likely(ctl_sock_initialized)) {
199 int rc = dccp_feat_init(sk);
200
201 if (rc)
202 return rc;
203
204 if (dmsk->dccpms_send_ack_vector) {
205 dp->dccps_hc_rx_ackvec = dccp_ackvec_alloc(GFP_KERNEL);
206 if (dp->dccps_hc_rx_ackvec == NULL)
207 return -ENOMEM;
208 }
209 dp->dccps_hc_rx_ccid = ccid_hc_rx_new(dmsk->dccpms_rx_ccid,
210 sk, GFP_KERNEL);
211 dp->dccps_hc_tx_ccid = ccid_hc_tx_new(dmsk->dccpms_tx_ccid,
212 sk, GFP_KERNEL);
213 if (unlikely(dp->dccps_hc_rx_ccid == NULL ||
214 dp->dccps_hc_tx_ccid == NULL)) {
215 ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk);
216 ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk);
217 if (dmsk->dccpms_send_ack_vector) {
218 dccp_ackvec_free(dp->dccps_hc_rx_ackvec);
219 dp->dccps_hc_rx_ackvec = NULL;
220 }
221 dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;
222 return -ENOMEM;
223 }
224 } else {
225 /* control socket doesn't need feat nego */
226 INIT_LIST_HEAD(&dmsk->dccpms_pending);
227 INIT_LIST_HEAD(&dmsk->dccpms_conf);
228 }
229
230 return 0; 196 return 0;
231} 197}
232 198