diff options
author | Gerrit Renker <gerrit@erg.abdn.ac.uk> | 2008-09-04 01:30:19 -0400 |
---|---|---|
committer | Gerrit Renker <gerrit@erg.abdn.ac.uk> | 2008-09-04 01:45:26 -0400 |
commit | 828755cee087e4a34f45d6c9db661ccd0631cc6d (patch) | |
tree | 07e687e6f5c559a49467ca3f56117ec58d9549b3 | |
parent | 3001fc0569651f2d0c3b45adc991351471b0c382 (diff) |
dccp: Per-socket initialisation of feature negotiation
This provides feature-negotiation initialisation for both DCCP sockets and
DCCP request_sockets, to support feature negotiation during connection setup.
It also resolves a FIXME regarding the congestion control initialisation.
Thanks to Wei Yongjun for help with the IPv6 side of this patch.
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Acked-by: Ian McDonald <ian.mcdonald@jandi.co.nz>
-rw-r--r-- | include/linux/dccp.h | 4 | ||||
-rw-r--r-- | net/dccp/dccp.h | 3 | ||||
-rw-r--r-- | net/dccp/feat.c | 19 | ||||
-rw-r--r-- | net/dccp/feat.h | 1 | ||||
-rw-r--r-- | net/dccp/input.c | 2 | ||||
-rw-r--r-- | net/dccp/ipv4.c | 3 | ||||
-rw-r--r-- | net/dccp/ipv6.c | 3 | ||||
-rw-r--r-- | net/dccp/minisocks.c | 7 | ||||
-rw-r--r-- | net/dccp/proto.c | 1 |
9 files changed, 37 insertions, 6 deletions
diff --git a/include/linux/dccp.h b/include/linux/dccp.h index 3978aff197d9..484b8a1fb023 100644 --- a/include/linux/dccp.h +++ b/include/linux/dccp.h | |||
@@ -412,6 +412,7 @@ extern void dccp_minisock_init(struct dccp_minisock *dmsk); | |||
412 | * @dreq_iss: initial sequence number sent on the Response (RFC 4340, 7.1) | 412 | * @dreq_iss: initial sequence number sent on the Response (RFC 4340, 7.1) |
413 | * @dreq_isr: initial sequence number received on the Request | 413 | * @dreq_isr: initial sequence number received on the Request |
414 | * @dreq_service: service code present on the Request (there is just one) | 414 | * @dreq_service: service code present on the Request (there is just one) |
415 | * @dreq_featneg: feature negotiation options for this connection | ||
415 | * The following two fields are analogous to the ones in dccp_sock: | 416 | * The following two fields are analogous to the ones in dccp_sock: |
416 | * @dreq_timestamp_echo: last received timestamp to echo (13.1) | 417 | * @dreq_timestamp_echo: last received timestamp to echo (13.1) |
417 | * @dreq_timestamp_echo: the time of receiving the last @dreq_timestamp_echo | 418 | * @dreq_timestamp_echo: the time of receiving the last @dreq_timestamp_echo |
@@ -421,6 +422,7 @@ struct dccp_request_sock { | |||
421 | __u64 dreq_iss; | 422 | __u64 dreq_iss; |
422 | __u64 dreq_isr; | 423 | __u64 dreq_isr; |
423 | __be32 dreq_service; | 424 | __be32 dreq_service; |
425 | struct list_head dreq_featneg; | ||
424 | __u32 dreq_timestamp_echo; | 426 | __u32 dreq_timestamp_echo; |
425 | __u32 dreq_timestamp_time; | 427 | __u32 dreq_timestamp_time; |
426 | }; | 428 | }; |
@@ -498,6 +500,7 @@ struct dccp_ackvec; | |||
498 | * @dccps_mss_cache - current value of MSS (path MTU minus header sizes) | 500 | * @dccps_mss_cache - current value of MSS (path MTU minus header sizes) |
499 | * @dccps_rate_last - timestamp for rate-limiting DCCP-Sync (RFC 4340, 7.5.4) | 501 | * @dccps_rate_last - timestamp for rate-limiting DCCP-Sync (RFC 4340, 7.5.4) |
500 | * @dccps_minisock - associated minisock (accessed via dccp_msk) | 502 | * @dccps_minisock - associated minisock (accessed via dccp_msk) |
503 | * @dccps_featneg - tracks feature-negotiation state (mostly during handshake) | ||
501 | * @dccps_hc_rx_ackvec - rx half connection ack vector | 504 | * @dccps_hc_rx_ackvec - rx half connection ack vector |
502 | * @dccps_hc_rx_ccid - CCID used for the receiver (or receiving half-connection) | 505 | * @dccps_hc_rx_ccid - CCID used for the receiver (or receiving half-connection) |
503 | * @dccps_hc_tx_ccid - CCID used for the sender (or sending half-connection) | 506 | * @dccps_hc_tx_ccid - CCID used for the sender (or sending half-connection) |
@@ -535,6 +538,7 @@ struct dccp_sock { | |||
535 | __u64 dccps_ndp_count:48; | 538 | __u64 dccps_ndp_count:48; |
536 | unsigned long dccps_rate_last; | 539 | unsigned long dccps_rate_last; |
537 | struct dccp_minisock dccps_minisock; | 540 | struct dccp_minisock dccps_minisock; |
541 | struct list_head dccps_featneg; | ||
538 | struct dccp_ackvec *dccps_hc_rx_ackvec; | 542 | struct dccp_ackvec *dccps_hc_rx_ackvec; |
539 | struct ccid *dccps_hc_rx_ccid; | 543 | struct ccid *dccps_hc_rx_ccid; |
540 | struct ccid *dccps_hc_tx_ccid; | 544 | struct ccid *dccps_hc_tx_ccid; |
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index b4bc6e095a0e..ab096c06bba0 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h | |||
@@ -252,7 +252,8 @@ extern const char *dccp_state_name(const int state); | |||
252 | extern void dccp_set_state(struct sock *sk, const int state); | 252 | extern void dccp_set_state(struct sock *sk, const int state); |
253 | extern void dccp_done(struct sock *sk); | 253 | extern void dccp_done(struct sock *sk); |
254 | 254 | ||
255 | extern void dccp_reqsk_init(struct request_sock *req, struct sk_buff *skb); | 255 | extern int dccp_reqsk_init(struct request_sock *rq, struct dccp_sock const *dp, |
256 | struct sk_buff const *skb); | ||
256 | 257 | ||
257 | extern int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb); | 258 | extern int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb); |
258 | 259 | ||
diff --git a/net/dccp/feat.c b/net/dccp/feat.c index 2ec2cd117699..faade82856fe 100644 --- a/net/dccp/feat.c +++ b/net/dccp/feat.c | |||
@@ -279,6 +279,25 @@ void dccp_feat_list_purge(struct list_head *fn_list) | |||
279 | } | 279 | } |
280 | EXPORT_SYMBOL_GPL(dccp_feat_list_purge); | 280 | EXPORT_SYMBOL_GPL(dccp_feat_list_purge); |
281 | 281 | ||
282 | /* generate @to as full clone of @from - @to must not contain any nodes */ | ||
283 | int dccp_feat_clone_list(struct list_head const *from, struct list_head *to) | ||
284 | { | ||
285 | struct dccp_feat_entry *entry, *new; | ||
286 | |||
287 | INIT_LIST_HEAD(to); | ||
288 | list_for_each_entry(entry, from, node) { | ||
289 | new = dccp_feat_clone_entry(entry); | ||
290 | if (new == NULL) | ||
291 | goto cloning_failed; | ||
292 | list_add_tail(&new->node, to); | ||
293 | } | ||
294 | return 0; | ||
295 | |||
296 | cloning_failed: | ||
297 | dccp_feat_list_purge(to); | ||
298 | return -ENOMEM; | ||
299 | } | ||
300 | |||
282 | int dccp_feat_change(struct dccp_minisock *dmsk, u8 type, u8 feature, | 301 | int dccp_feat_change(struct dccp_minisock *dmsk, u8 type, u8 feature, |
283 | u8 *val, u8 len, gfp_t gfp) | 302 | u8 *val, u8 len, gfp_t gfp) |
284 | { | 303 | { |
diff --git a/net/dccp/feat.h b/net/dccp/feat.h index 94203c230c65..7e953fd0a79b 100644 --- a/net/dccp/feat.h +++ b/net/dccp/feat.h | |||
@@ -95,6 +95,7 @@ extern int dccp_feat_confirm_recv(struct sock *sk, u8 type, u8 feature, | |||
95 | u8 *val, u8 len); | 95 | u8 *val, u8 len); |
96 | extern void dccp_feat_clean(struct dccp_minisock *dmsk); | 96 | extern void dccp_feat_clean(struct dccp_minisock *dmsk); |
97 | extern int dccp_feat_clone(struct sock *oldsk, struct sock *newsk); | 97 | extern int dccp_feat_clone(struct sock *oldsk, struct sock *newsk); |
98 | extern int dccp_feat_clone_list(struct list_head const *, struct list_head *); | ||
98 | extern int dccp_feat_init(struct dccp_minisock *dmsk); | 99 | extern int dccp_feat_init(struct dccp_minisock *dmsk); |
99 | 100 | ||
100 | #endif /* _DCCP_FEAT_H */ | 101 | #endif /* _DCCP_FEAT_H */ |
diff --git a/net/dccp/input.c b/net/dccp/input.c index 779d0ed9ae94..3070015edc75 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c | |||
@@ -590,8 +590,6 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
590 | if (inet_csk(sk)->icsk_af_ops->conn_request(sk, | 590 | if (inet_csk(sk)->icsk_af_ops->conn_request(sk, |
591 | skb) < 0) | 591 | skb) < 0) |
592 | return 1; | 592 | return 1; |
593 | |||
594 | /* FIXME: do congestion control initialization */ | ||
595 | goto discard; | 593 | goto discard; |
596 | } | 594 | } |
597 | if (dh->dccph_type == DCCP_PKT_RESET) | 595 | if (dh->dccph_type == DCCP_PKT_RESET) |
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 882c5c4de69e..0ce84ea89119 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c | |||
@@ -595,7 +595,8 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
595 | if (req == NULL) | 595 | if (req == NULL) |
596 | goto drop; | 596 | goto drop; |
597 | 597 | ||
598 | dccp_reqsk_init(req, skb); | 598 | if (dccp_reqsk_init(req, dccp_sk(sk), skb)) |
599 | goto drop_and_free; | ||
599 | 600 | ||
600 | dreq = dccp_rsk(req); | 601 | dreq = dccp_rsk(req); |
601 | if (dccp_parse_options(sk, dreq, skb)) | 602 | if (dccp_parse_options(sk, dreq, skb)) |
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 5e1ee0da2c40..33e8a1ea3041 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c | |||
@@ -424,7 +424,8 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
424 | if (req == NULL) | 424 | if (req == NULL) |
425 | goto drop; | 425 | goto drop; |
426 | 426 | ||
427 | dccp_reqsk_init(req, skb); | 427 | if (dccp_reqsk_init(req, dccp_sk(sk), skb)) |
428 | goto drop_and_free; | ||
428 | 429 | ||
429 | dreq = dccp_rsk(req); | 430 | dreq = dccp_rsk(req); |
430 | if (dccp_parse_options(sk, dreq, skb)) | 431 | if (dccp_parse_options(sk, dreq, skb)) |
diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c index b2804e2d1b8c..e487133ae079 100644 --- a/net/dccp/minisocks.c +++ b/net/dccp/minisocks.c | |||
@@ -125,6 +125,7 @@ struct sock *dccp_create_openreq_child(struct sock *sk, | |||
125 | newdp->dccps_timestamp_time = dreq->dreq_timestamp_time; | 125 | newdp->dccps_timestamp_time = dreq->dreq_timestamp_time; |
126 | newicsk->icsk_rto = DCCP_TIMEOUT_INIT; | 126 | newicsk->icsk_rto = DCCP_TIMEOUT_INIT; |
127 | 127 | ||
128 | INIT_LIST_HEAD(&newdp->dccps_featneg); | ||
128 | if (dccp_feat_clone(sk, newsk)) | 129 | if (dccp_feat_clone(sk, newsk)) |
129 | goto out_free; | 130 | goto out_free; |
130 | 131 | ||
@@ -304,7 +305,8 @@ void dccp_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, | |||
304 | 305 | ||
305 | EXPORT_SYMBOL_GPL(dccp_reqsk_send_ack); | 306 | EXPORT_SYMBOL_GPL(dccp_reqsk_send_ack); |
306 | 307 | ||
307 | void dccp_reqsk_init(struct request_sock *req, struct sk_buff *skb) | 308 | int dccp_reqsk_init(struct request_sock *req, |
309 | struct dccp_sock const *dp, struct sk_buff const *skb) | ||
308 | { | 310 | { |
309 | struct dccp_request_sock *dreq = dccp_rsk(req); | 311 | struct dccp_request_sock *dreq = dccp_rsk(req); |
310 | 312 | ||
@@ -312,6 +314,9 @@ void dccp_reqsk_init(struct request_sock *req, struct sk_buff *skb) | |||
312 | inet_rsk(req)->acked = 0; | 314 | inet_rsk(req)->acked = 0; |
313 | req->rcv_wnd = sysctl_dccp_feat_sequence_window; | 315 | req->rcv_wnd = sysctl_dccp_feat_sequence_window; |
314 | dreq->dreq_timestamp_echo = 0; | 316 | dreq->dreq_timestamp_echo = 0; |
317 | |||
318 | /* inherit feature negotiation options from listening socket */ | ||
319 | return dccp_feat_clone_list(&dp->dccps_featneg, &dreq->dreq_featneg); | ||
315 | } | 320 | } |
316 | 321 | ||
317 | EXPORT_SYMBOL_GPL(dccp_reqsk_init); | 322 | EXPORT_SYMBOL_GPL(dccp_reqsk_init); |
diff --git a/net/dccp/proto.c b/net/dccp/proto.c index d0bd34819761..1cdf4ae99605 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c | |||
@@ -193,6 +193,7 @@ int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized) | |||
193 | 193 | ||
194 | dccp_init_xmit_timers(sk); | 194 | dccp_init_xmit_timers(sk); |
195 | 195 | ||
196 | INIT_LIST_HEAD(&dp->dccps_featneg); | ||
196 | /* | 197 | /* |
197 | * FIXME: We're hardcoding the CCID, and doing this at this point makes | 198 | * FIXME: We're hardcoding the CCID, and doing this at this point makes |
198 | * the listening (master) sock get CCID control blocks, which is not | 199 | * the listening (master) sock get CCID control blocks, which is not |