aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/options.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/dccp/options.c')
-rw-r--r--net/dccp/options.c100
1 files changed, 89 insertions, 11 deletions
diff --git a/net/dccp/options.c b/net/dccp/options.c
index cd3061813009..f06ffcfc8d71 100644
--- a/net/dccp/options.c
+++ b/net/dccp/options.c
@@ -54,7 +54,6 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq,
54 struct dccp_sock *dp = dccp_sk(sk); 54 struct dccp_sock *dp = dccp_sk(sk);
55 const struct dccp_hdr *dh = dccp_hdr(skb); 55 const struct dccp_hdr *dh = dccp_hdr(skb);
56 const u8 pkt_type = DCCP_SKB_CB(skb)->dccpd_type; 56 const u8 pkt_type = DCCP_SKB_CB(skb)->dccpd_type;
57 u64 ackno = DCCP_SKB_CB(skb)->dccpd_ack_seq;
58 unsigned char *options = (unsigned char *)dh + dccp_hdr_len(skb); 57 unsigned char *options = (unsigned char *)dh + dccp_hdr_len(skb);
59 unsigned char *opt_ptr = options; 58 unsigned char *opt_ptr = options;
60 const unsigned char *opt_end = (unsigned char *)dh + 59 const unsigned char *opt_end = (unsigned char *)dh +
@@ -129,14 +128,6 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq,
129 if (rc) 128 if (rc)
130 goto out_featneg_failed; 129 goto out_featneg_failed;
131 break; 130 break;
132 case DCCPO_ACK_VECTOR_0:
133 case DCCPO_ACK_VECTOR_1:
134 if (dccp_packet_without_ack(skb)) /* RFC 4340, 11.4 */
135 break;
136 if (dp->dccps_hc_rx_ackvec != NULL &&
137 dccp_ackvec_parse(sk, skb, &ackno, opt, value, len))
138 goto out_invalid_option;
139 break;
140 case DCCPO_TIMESTAMP: 131 case DCCPO_TIMESTAMP:
141 if (len != 4) 132 if (len != 4)
142 goto out_invalid_option; 133 goto out_invalid_option;
@@ -226,6 +217,16 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq,
226 pkt_type, opt, value, len)) 217 pkt_type, opt, value, len))
227 goto out_invalid_option; 218 goto out_invalid_option;
228 break; 219 break;
220 case DCCPO_ACK_VECTOR_0:
221 case DCCPO_ACK_VECTOR_1:
222 if (dccp_packet_without_ack(skb)) /* RFC 4340, 11.4 */
223 break;
224 /*
225 * Ack vectors are processed by the TX CCID if it is
226 * interested. The RX CCID need not parse Ack Vectors,
227 * since it is only interested in clearing old state.
228 * Fall through.
229 */
229 case DCCPO_MIN_TX_CCID_SPECIFIC ... DCCPO_MAX_TX_CCID_SPECIFIC: 230 case DCCPO_MIN_TX_CCID_SPECIFIC ... DCCPO_MAX_TX_CCID_SPECIFIC:
230 if (ccid_hc_tx_parse_options(dp->dccps_hc_tx_ccid, sk, 231 if (ccid_hc_tx_parse_options(dp->dccps_hc_tx_ccid, sk,
231 pkt_type, opt, value, len)) 232 pkt_type, opt, value, len))
@@ -340,6 +341,7 @@ static inline int dccp_elapsed_time_len(const u32 elapsed_time)
340 return elapsed_time == 0 ? 0 : elapsed_time <= 0xFFFF ? 2 : 4; 341 return elapsed_time == 0 ? 0 : elapsed_time <= 0xFFFF ? 2 : 4;
341} 342}
342 343
344/* FIXME: This function is currently not used anywhere */
343int dccp_insert_option_elapsed_time(struct sk_buff *skb, u32 elapsed_time) 345int dccp_insert_option_elapsed_time(struct sk_buff *skb, u32 elapsed_time)
344{ 346{
345 const int elapsed_time_len = dccp_elapsed_time_len(elapsed_time); 347 const int elapsed_time_len = dccp_elapsed_time_len(elapsed_time);
@@ -424,6 +426,83 @@ static int dccp_insert_option_timestamp_echo(struct dccp_sock *dp,
424 return 0; 426 return 0;
425} 427}
426 428
429static int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
430{
431 struct dccp_sock *dp = dccp_sk(sk);
432 struct dccp_ackvec *av = dp->dccps_hc_rx_ackvec;
433 struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
434 const u16 buflen = dccp_ackvec_buflen(av);
435 /* Figure out how many options do we need to represent the ackvec */
436 const u8 nr_opts = DIV_ROUND_UP(buflen, DCCP_SINGLE_OPT_MAXLEN);
437 u16 len = buflen + 2 * nr_opts;
438 u8 i, nonce = 0;
439 const unsigned char *tail, *from;
440 unsigned char *to;
441
442 if (dcb->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) {
443 DCCP_WARN("Lacking space for %u bytes on %s packet\n", len,
444 dccp_packet_name(dcb->dccpd_type));
445 return -1;
446 }
447 /*
448 * Since Ack Vectors are variable-length, we can not always predict
449 * their size. To catch exception cases where the space is running out
450 * on the skb, a separate Sync is scheduled to carry the Ack Vector.
451 */
452 if (len > DCCPAV_MIN_OPTLEN &&
453 len + dcb->dccpd_opt_len + skb->len > dp->dccps_mss_cache) {
454 DCCP_WARN("No space left for Ack Vector (%u) on skb (%u+%u), "
455 "MPS=%u ==> reduce payload size?\n", len, skb->len,
456 dcb->dccpd_opt_len, dp->dccps_mss_cache);
457 dp->dccps_sync_scheduled = 1;
458 return 0;
459 }
460 dcb->dccpd_opt_len += len;
461
462 to = skb_push(skb, len);
463 len = buflen;
464 from = av->av_buf + av->av_buf_head;
465 tail = av->av_buf + DCCPAV_MAX_ACKVEC_LEN;
466
467 for (i = 0; i < nr_opts; ++i) {
468 int copylen = len;
469
470 if (len > DCCP_SINGLE_OPT_MAXLEN)
471 copylen = DCCP_SINGLE_OPT_MAXLEN;
472
473 /*
474 * RFC 4340, 12.2: Encode the Nonce Echo for this Ack Vector via
475 * its type; ack_nonce is the sum of all individual buf_nonce's.
476 */
477 nonce ^= av->av_buf_nonce[i];
478
479 *to++ = DCCPO_ACK_VECTOR_0 + av->av_buf_nonce[i];
480 *to++ = copylen + 2;
481
482 /* Check if buf_head wraps */
483 if (from + copylen > tail) {
484 const u16 tailsize = tail - from;
485
486 memcpy(to, from, tailsize);
487 to += tailsize;
488 len -= tailsize;
489 copylen -= tailsize;
490 from = av->av_buf;
491 }
492
493 memcpy(to, from, copylen);
494 from += copylen;
495 to += copylen;
496 len -= copylen;
497 }
498 /*
499 * Each sent Ack Vector is recorded in the list, as per A.2 of RFC 4340.
500 */
501 if (dccp_ackvec_update_records(av, dcb->dccpd_seq, nonce))
502 return -ENOBUFS;
503 return 0;
504}
505
427/** 506/**
428 * dccp_insert_option_mandatory - Mandatory option (5.8.2) 507 * dccp_insert_option_mandatory - Mandatory option (5.8.2)
429 * Note that since we are using skb_push, this function needs to be called 508 * Note that since we are using skb_push, this function needs to be called
@@ -519,8 +598,7 @@ int dccp_insert_options(struct sock *sk, struct sk_buff *skb)
519 if (dccp_insert_option_timestamp(skb)) 598 if (dccp_insert_option_timestamp(skb))
520 return -1; 599 return -1;
521 600
522 } else if (dp->dccps_hc_rx_ackvec != NULL && 601 } else if (dccp_ackvec_pending(sk) &&
523 dccp_ackvec_pending(dp->dccps_hc_rx_ackvec) &&
524 dccp_insert_option_ackvec(sk, skb)) { 602 dccp_insert_option_ackvec(sk, skb)) {
525 return -1; 603 return -1;
526 } 604 }