aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp
diff options
context:
space:
mode:
authorGerrit Renker <gerrit@erg.abdn.ac.uk>2007-12-13 09:29:24 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 17:57:50 -0500
commit8b819412481494fb6861c08d360b75fabcbbfbbf (patch)
treeddd9f976f051fb5cff794992b38613bbbfcb9cc1 /net/dccp
parent7913350663e2756ecb91dd3a7c773806b943426e (diff)
[DCCP]: Allow to parse options on Request Sockets
The option parsing code currently only parses on full sk's. This causes a problem for options sent during the initial handshake (in particular timestamps and feature-negotiation options). Therefore, this patch extends the option parsing code with an additional argument for request_socks: if it is non-NULL, options are parsed on the request socket, otherwise the normal path (parsing on the sk) is used. Subsequent patches, which implement feature negotiation during connection setup, make use of this facility. Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk> Signed-off-by: Ian McDonald <ian.mcdonald@jandi.co.nz> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dccp')
-rw-r--r--net/dccp/input.c6
-rw-r--r--net/dccp/ipv4.c8
-rw-r--r--net/dccp/ipv6.c8
-rw-r--r--net/dccp/options.c34
4 files changed, 34 insertions, 22 deletions
diff --git a/net/dccp/input.c b/net/dccp/input.c
index dacd4fd3c63c..08392ed86c25 100644
--- a/net/dccp/input.c
+++ b/net/dccp/input.c
@@ -369,7 +369,7 @@ int dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
369 if (dccp_check_seqno(sk, skb)) 369 if (dccp_check_seqno(sk, skb))
370 goto discard; 370 goto discard;
371 371
372 if (dccp_parse_options(sk, skb)) 372 if (dccp_parse_options(sk, NULL, skb))
373 goto discard; 373 goto discard;
374 374
375 if (DCCP_SKB_CB(skb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ) 375 if (DCCP_SKB_CB(skb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ)
@@ -427,7 +427,7 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
427 goto out_invalid_packet; 427 goto out_invalid_packet;
428 } 428 }
429 429
430 if (dccp_parse_options(sk, skb)) 430 if (dccp_parse_options(sk, NULL, skb))
431 goto out_invalid_packet; 431 goto out_invalid_packet;
432 432
433 /* Obtain usec RTT sample from SYN exchange (used by CCID 3) */ 433 /* Obtain usec RTT sample from SYN exchange (used by CCID 3) */
@@ -609,7 +609,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
609 /* 609 /*
610 * Step 8: Process options and mark acknowledgeable 610 * Step 8: Process options and mark acknowledgeable
611 */ 611 */
612 if (dccp_parse_options(sk, skb)) 612 if (dccp_parse_options(sk, NULL, skb))
613 goto discard; 613 goto discard;
614 614
615 if (dcb->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ) 615 if (dcb->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ)
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index db17b83e8d3e..02fc91ce2505 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -600,11 +600,12 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
600 if (req == NULL) 600 if (req == NULL)
601 goto drop; 601 goto drop;
602 602
603 if (dccp_parse_options(sk, skb))
604 goto drop_and_free;
605
606 dccp_reqsk_init(req, skb); 603 dccp_reqsk_init(req, skb);
607 604
605 dreq = dccp_rsk(req);
606 if (dccp_parse_options(sk, dreq, skb))
607 goto drop_and_free;
608
608 if (security_inet_conn_request(sk, skb, req)) 609 if (security_inet_conn_request(sk, skb, req))
609 goto drop_and_free; 610 goto drop_and_free;
610 611
@@ -621,7 +622,6 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
621 * In fact we defer setting S.GSR, S.SWL, S.SWH to 622 * In fact we defer setting S.GSR, S.SWL, S.SWH to
622 * dccp_create_openreq_child. 623 * dccp_create_openreq_child.
623 */ 624 */
624 dreq = dccp_rsk(req);
625 dreq->dreq_isr = dcb->dccpd_seq; 625 dreq->dreq_isr = dcb->dccpd_seq;
626 dreq->dreq_iss = dccp_v4_init_sequence(skb); 626 dreq->dreq_iss = dccp_v4_init_sequence(skb);
627 dreq->dreq_service = service; 627 dreq->dreq_service = service;
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index a08e2cb11915..f42b75ce7f5c 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -415,11 +415,12 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
415 if (req == NULL) 415 if (req == NULL)
416 goto drop; 416 goto drop;
417 417
418 if (dccp_parse_options(sk, skb))
419 goto drop_and_free;
420
421 dccp_reqsk_init(req, skb); 418 dccp_reqsk_init(req, skb);
422 419
420 dreq = dccp_rsk(req);
421 if (dccp_parse_options(sk, dreq, skb))
422 goto drop_and_free;
423
423 if (security_inet_conn_request(sk, skb, req)) 424 if (security_inet_conn_request(sk, skb, req))
424 goto drop_and_free; 425 goto drop_and_free;
425 426
@@ -449,7 +450,6 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
449 * In fact we defer setting S.GSR, S.SWL, S.SWH to 450 * In fact we defer setting S.GSR, S.SWL, S.SWH to
450 * dccp_create_openreq_child. 451 * dccp_create_openreq_child.
451 */ 452 */
452 dreq = dccp_rsk(req);
453 dreq->dreq_isr = dcb->dccpd_seq; 453 dreq->dreq_isr = dcb->dccpd_seq;
454 dreq->dreq_iss = dccp_v6_init_sequence(skb); 454 dreq->dreq_iss = dccp_v6_init_sequence(skb);
455 dreq->dreq_service = service; 455 dreq->dreq_service = service;
diff --git a/net/dccp/options.c b/net/dccp/options.c
index 523250b45ea5..f496d4dc7efc 100644
--- a/net/dccp/options.c
+++ b/net/dccp/options.c
@@ -46,7 +46,13 @@ static u32 dccp_decode_value_var(const unsigned char *bf, const u8 len)
46 return value; 46 return value;
47} 47}
48 48
49int dccp_parse_options(struct sock *sk, struct sk_buff *skb) 49/**
50 * dccp_parse_options - Parse DCCP options present in @skb
51 * @sk: client|server|listening dccp socket (when @dreq != NULL)
52 * @dreq: request socket to use during connection setup, or NULL
53 */
54int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq,
55 struct sk_buff *skb)
50{ 56{
51 struct dccp_sock *dp = dccp_sk(sk); 57 struct dccp_sock *dp = dccp_sk(sk);
52 const struct dccp_hdr *dh = dccp_hdr(skb); 58 const struct dccp_hdr *dh = dccp_hdr(skb);
@@ -92,6 +98,20 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
92 goto out_invalid_option; 98 goto out_invalid_option;
93 } 99 }
94 100
101 /*
102 * CCID-Specific Options (from RFC 4340, sec. 10.3):
103 *
104 * Option numbers 128 through 191 are for options sent from the
105 * HC-Sender to the HC-Receiver; option numbers 192 through 255
106 * are for options sent from the HC-Receiver to the HC-Sender.
107 *
108 * CCID-specific options are ignored during connection setup, as
109 * negotiation may still be in progress (see RFC 4340, 10.3).
110 *
111 */
112 if (dreq != NULL && opt >= 128)
113 goto ignore_option;
114
95 switch (opt) { 115 switch (opt) {
96 case DCCPO_PADDING: 116 case DCCPO_PADDING:
97 break; 117 break;
@@ -150,6 +170,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
150 opt_val = get_unaligned((__be32 *)value); 170 opt_val = get_unaligned((__be32 *)value);
151 opt_recv->dccpor_timestamp = ntohl(opt_val); 171 opt_recv->dccpor_timestamp = ntohl(opt_val);
152 172
173 /* FIXME: if dreq != NULL, don't store this on listening socket */
153 dp->dccps_timestamp_echo = opt_recv->dccpor_timestamp; 174 dp->dccps_timestamp_echo = opt_recv->dccpor_timestamp;
154 dp->dccps_timestamp_time = ktime_get_real(); 175 dp->dccps_timestamp_time = ktime_get_real();
155 176
@@ -213,15 +234,6 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
213 dccp_pr_debug("%s rx opt: ELAPSED_TIME=%d\n", 234 dccp_pr_debug("%s rx opt: ELAPSED_TIME=%d\n",
214 dccp_role(sk), elapsed_time); 235 dccp_role(sk), elapsed_time);
215 break; 236 break;
216 /*
217 * From RFC 4340, sec. 10.3:
218 *
219 * Option numbers 128 through 191 are for
220 * options sent from the HC-Sender to the
221 * HC-Receiver; option numbers 192 through 255
222 * are for options sent from the HC-Receiver to
223 * the HC-Sender.
224 */
225 case 128 ... 191: { 237 case 128 ... 191: {
226 const u16 idx = value - options; 238 const u16 idx = value - options;
227 239
@@ -245,7 +257,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
245 "implemented, ignoring", sk, opt, len); 257 "implemented, ignoring", sk, opt, len);
246 break; 258 break;
247 } 259 }
248 260ignore_option:
249 if (opt != DCCPO_MANDATORY) 261 if (opt != DCCPO_MANDATORY)
250 mandatory = 0; 262 mandatory = 0;
251 } 263 }