diff options
Diffstat (limited to 'net/dccp/options.c')
-rw-r--r-- | net/dccp/options.c | 341 |
1 files changed, 163 insertions, 178 deletions
diff --git a/net/dccp/options.c b/net/dccp/options.c index e5a32979d7d7..0809b63cb055 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c | |||
@@ -23,20 +23,23 @@ | |||
23 | #include "dccp.h" | 23 | #include "dccp.h" |
24 | #include "feat.h" | 24 | #include "feat.h" |
25 | 25 | ||
26 | u64 dccp_decode_value_var(const u8 *bf, const u8 len) | 26 | int sysctl_dccp_feat_sequence_window = DCCPF_INITIAL_SEQUENCE_WINDOW; |
27 | int sysctl_dccp_feat_rx_ccid = DCCPF_INITIAL_CCID; | ||
28 | int sysctl_dccp_feat_tx_ccid = DCCPF_INITIAL_CCID; | ||
29 | int sysctl_dccp_feat_ack_ratio = DCCPF_INITIAL_ACK_RATIO; | ||
30 | int sysctl_dccp_feat_send_ack_vector = DCCPF_INITIAL_SEND_ACK_VECTOR; | ||
31 | int sysctl_dccp_feat_send_ndp_count = DCCPF_INITIAL_SEND_NDP_COUNT; | ||
32 | |||
33 | static u32 dccp_decode_value_var(const unsigned char *bf, const u8 len) | ||
27 | { | 34 | { |
28 | u64 value = 0; | 35 | u32 value = 0; |
29 | 36 | ||
30 | if (len >= DCCP_OPTVAL_MAXLEN) | ||
31 | value += ((u64)*bf++) << 40; | ||
32 | if (len > 4) | ||
33 | value += ((u64)*bf++) << 32; | ||
34 | if (len > 3) | 37 | if (len > 3) |
35 | value += ((u64)*bf++) << 24; | 38 | value += *bf++ << 24; |
36 | if (len > 2) | 39 | if (len > 2) |
37 | value += ((u64)*bf++) << 16; | 40 | value += *bf++ << 16; |
38 | if (len > 1) | 41 | if (len > 1) |
39 | value += ((u64)*bf++) << 8; | 42 | value += *bf++ << 8; |
40 | if (len > 0) | 43 | if (len > 0) |
41 | value += *bf; | 44 | value += *bf; |
42 | 45 | ||
@@ -54,6 +57,7 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq, | |||
54 | struct dccp_sock *dp = dccp_sk(sk); | 57 | struct dccp_sock *dp = dccp_sk(sk); |
55 | const struct dccp_hdr *dh = dccp_hdr(skb); | 58 | const struct dccp_hdr *dh = dccp_hdr(skb); |
56 | const u8 pkt_type = DCCP_SKB_CB(skb)->dccpd_type; | 59 | const u8 pkt_type = DCCP_SKB_CB(skb)->dccpd_type; |
60 | u64 ackno = DCCP_SKB_CB(skb)->dccpd_ack_seq; | ||
57 | unsigned char *options = (unsigned char *)dh + dccp_hdr_len(skb); | 61 | unsigned char *options = (unsigned char *)dh + dccp_hdr_len(skb); |
58 | unsigned char *opt_ptr = options; | 62 | unsigned char *opt_ptr = options; |
59 | const unsigned char *opt_end = (unsigned char *)dh + | 63 | const unsigned char *opt_end = (unsigned char *)dh + |
@@ -95,11 +99,18 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq, | |||
95 | } | 99 | } |
96 | 100 | ||
97 | /* | 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 | * | ||
98 | * CCID-specific options are ignored during connection setup, as | 108 | * CCID-specific options are ignored during connection setup, as |
99 | * negotiation may still be in progress (see RFC 4340, 10.3). | 109 | * negotiation may still be in progress (see RFC 4340, 10.3). |
100 | * The same applies to Ack Vectors, as these depend on the CCID. | 110 | * The same applies to Ack Vectors, as these depend on the CCID. |
111 | * | ||
101 | */ | 112 | */ |
102 | if (dreq != NULL && (opt >= DCCPO_MIN_RX_CCID_SPECIFIC || | 113 | if (dreq != NULL && (opt >= 128 || |
103 | opt == DCCPO_ACK_VECTOR_0 || opt == DCCPO_ACK_VECTOR_1)) | 114 | opt == DCCPO_ACK_VECTOR_0 || opt == DCCPO_ACK_VECTOR_1)) |
104 | goto ignore_option; | 115 | goto ignore_option; |
105 | 116 | ||
@@ -120,13 +131,43 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq, | |||
120 | dccp_pr_debug("%s opt: NDP count=%llu\n", dccp_role(sk), | 131 | dccp_pr_debug("%s opt: NDP count=%llu\n", dccp_role(sk), |
121 | (unsigned long long)opt_recv->dccpor_ndp); | 132 | (unsigned long long)opt_recv->dccpor_ndp); |
122 | break; | 133 | break; |
123 | case DCCPO_CHANGE_L ... DCCPO_CONFIRM_R: | 134 | case DCCPO_CHANGE_L: |
124 | if (pkt_type == DCCP_PKT_DATA) /* RFC 4340, 6 */ | 135 | /* fall through */ |
136 | case DCCPO_CHANGE_R: | ||
137 | if (pkt_type == DCCP_PKT_DATA) | ||
125 | break; | 138 | break; |
126 | rc = dccp_feat_parse_options(sk, dreq, mandatory, opt, | 139 | if (len < 2) |
127 | *value, value + 1, len - 1); | 140 | goto out_invalid_option; |
128 | if (rc) | 141 | rc = dccp_feat_change_recv(sk, opt, *value, value + 1, |
129 | goto out_featneg_failed; | 142 | len - 1); |
143 | /* | ||
144 | * When there is a change error, change_recv is | ||
145 | * responsible for dealing with it. i.e. reply with an | ||
146 | * empty confirm. | ||
147 | * If the change was mandatory, then we need to die. | ||
148 | */ | ||
149 | if (rc && mandatory) | ||
150 | goto out_invalid_option; | ||
151 | break; | ||
152 | case DCCPO_CONFIRM_L: | ||
153 | /* fall through */ | ||
154 | case DCCPO_CONFIRM_R: | ||
155 | if (pkt_type == DCCP_PKT_DATA) | ||
156 | break; | ||
157 | if (len < 2) /* FIXME this disallows empty confirm */ | ||
158 | goto out_invalid_option; | ||
159 | if (dccp_feat_confirm_recv(sk, opt, *value, | ||
160 | value + 1, len - 1)) | ||
161 | goto out_invalid_option; | ||
162 | break; | ||
163 | case DCCPO_ACK_VECTOR_0: | ||
164 | case DCCPO_ACK_VECTOR_1: | ||
165 | if (dccp_packet_without_ack(skb)) /* RFC 4340, 11.4 */ | ||
166 | break; | ||
167 | |||
168 | if (dccp_msk(sk)->dccpms_send_ack_vector && | ||
169 | dccp_ackvec_parse(sk, skb, &ackno, opt, value, len)) | ||
170 | goto out_invalid_option; | ||
130 | break; | 171 | break; |
131 | case DCCPO_TIMESTAMP: | 172 | case DCCPO_TIMESTAMP: |
132 | if (len != 4) | 173 | if (len != 4) |
@@ -154,8 +195,6 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq, | |||
154 | dccp_role(sk), ntohl(opt_val), | 195 | dccp_role(sk), ntohl(opt_val), |
155 | (unsigned long long) | 196 | (unsigned long long) |
156 | DCCP_SKB_CB(skb)->dccpd_ack_seq); | 197 | DCCP_SKB_CB(skb)->dccpd_ack_seq); |
157 | /* schedule an Ack in case this sender is quiescent */ | ||
158 | inet_csk_schedule_ack(sk); | ||
159 | break; | 198 | break; |
160 | case DCCPO_TIMESTAMP_ECHO: | 199 | case DCCPO_TIMESTAMP_ECHO: |
161 | if (len != 4 && len != 6 && len != 8) | 200 | if (len != 4 && len != 6 && len != 8) |
@@ -212,25 +251,23 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq, | |||
212 | dccp_pr_debug("%s rx opt: ELAPSED_TIME=%d\n", | 251 | dccp_pr_debug("%s rx opt: ELAPSED_TIME=%d\n", |
213 | dccp_role(sk), elapsed_time); | 252 | dccp_role(sk), elapsed_time); |
214 | break; | 253 | break; |
215 | case DCCPO_MIN_RX_CCID_SPECIFIC ... DCCPO_MAX_RX_CCID_SPECIFIC: | 254 | case 128 ... 191: { |
255 | const u16 idx = value - options; | ||
256 | |||
216 | if (ccid_hc_rx_parse_options(dp->dccps_hc_rx_ccid, sk, | 257 | if (ccid_hc_rx_parse_options(dp->dccps_hc_rx_ccid, sk, |
217 | pkt_type, opt, value, len)) | 258 | opt, len, idx, |
259 | value) != 0) | ||
218 | goto out_invalid_option; | 260 | goto out_invalid_option; |
261 | } | ||
219 | break; | 262 | break; |
220 | case DCCPO_ACK_VECTOR_0: | 263 | case 192 ... 255: { |
221 | case DCCPO_ACK_VECTOR_1: | 264 | const u16 idx = value - options; |
222 | if (dccp_packet_without_ack(skb)) /* RFC 4340, 11.4 */ | 265 | |
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 | */ | ||
230 | case DCCPO_MIN_TX_CCID_SPECIFIC ... DCCPO_MAX_TX_CCID_SPECIFIC: | ||
231 | if (ccid_hc_tx_parse_options(dp->dccps_hc_tx_ccid, sk, | 266 | if (ccid_hc_tx_parse_options(dp->dccps_hc_tx_ccid, sk, |
232 | pkt_type, opt, value, len)) | 267 | opt, len, idx, |
268 | value) != 0) | ||
233 | goto out_invalid_option; | 269 | goto out_invalid_option; |
270 | } | ||
234 | break; | 271 | break; |
235 | default: | 272 | default: |
236 | DCCP_CRIT("DCCP(%p): option %d(len=%d) not " | 273 | DCCP_CRIT("DCCP(%p): option %d(len=%d) not " |
@@ -252,10 +289,8 @@ out_nonsensical_length: | |||
252 | 289 | ||
253 | out_invalid_option: | 290 | out_invalid_option: |
254 | DCCP_INC_STATS_BH(DCCP_MIB_INVALIDOPT); | 291 | DCCP_INC_STATS_BH(DCCP_MIB_INVALIDOPT); |
255 | rc = DCCP_RESET_CODE_OPTION_ERROR; | 292 | DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_OPTION_ERROR; |
256 | out_featneg_failed: | 293 | DCCP_WARN("DCCP(%p): invalid option %d, len=%d", sk, opt, len); |
257 | DCCP_WARN("DCCP(%p): Option %d (len=%d) error=%u\n", sk, opt, len, rc); | ||
258 | DCCP_SKB_CB(skb)->dccpd_reset_code = rc; | ||
259 | DCCP_SKB_CB(skb)->dccpd_reset_data[0] = opt; | 294 | DCCP_SKB_CB(skb)->dccpd_reset_data[0] = opt; |
260 | DCCP_SKB_CB(skb)->dccpd_reset_data[1] = len > 0 ? value[0] : 0; | 295 | DCCP_SKB_CB(skb)->dccpd_reset_data[1] = len > 0 ? value[0] : 0; |
261 | DCCP_SKB_CB(skb)->dccpd_reset_data[2] = len > 1 ? value[1] : 0; | 296 | DCCP_SKB_CB(skb)->dccpd_reset_data[2] = len > 1 ? value[1] : 0; |
@@ -264,12 +299,9 @@ out_featneg_failed: | |||
264 | 299 | ||
265 | EXPORT_SYMBOL_GPL(dccp_parse_options); | 300 | EXPORT_SYMBOL_GPL(dccp_parse_options); |
266 | 301 | ||
267 | void dccp_encode_value_var(const u64 value, u8 *to, const u8 len) | 302 | static void dccp_encode_value_var(const u32 value, unsigned char *to, |
303 | const unsigned int len) | ||
268 | { | 304 | { |
269 | if (len >= DCCP_OPTVAL_MAXLEN) | ||
270 | *to++ = (value & 0xFF0000000000ull) >> 40; | ||
271 | if (len > 4) | ||
272 | *to++ = (value & 0xFF00000000ull) >> 32; | ||
273 | if (len > 3) | 305 | if (len > 3) |
274 | *to++ = (value & 0xFF000000) >> 24; | 306 | *to++ = (value & 0xFF000000) >> 24; |
275 | if (len > 2) | 307 | if (len > 2) |
@@ -429,140 +461,92 @@ static int dccp_insert_option_timestamp_echo(struct dccp_sock *dp, | |||
429 | return 0; | 461 | return 0; |
430 | } | 462 | } |
431 | 463 | ||
432 | static int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb) | 464 | static int dccp_insert_feat_opt(struct sk_buff *skb, u8 type, u8 feat, |
465 | u8 *val, u8 len) | ||
433 | { | 466 | { |
434 | struct dccp_sock *dp = dccp_sk(sk); | 467 | u8 *to; |
435 | struct dccp_ackvec *av = dp->dccps_hc_rx_ackvec; | ||
436 | struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); | ||
437 | const u16 buflen = dccp_ackvec_buflen(av); | ||
438 | /* Figure out how many options do we need to represent the ackvec */ | ||
439 | const u8 nr_opts = DIV_ROUND_UP(buflen, DCCP_SINGLE_OPT_MAXLEN); | ||
440 | u16 len = buflen + 2 * nr_opts; | ||
441 | u8 i, nonce = 0; | ||
442 | const unsigned char *tail, *from; | ||
443 | unsigned char *to; | ||
444 | 468 | ||
445 | if (dcb->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) { | 469 | if (DCCP_SKB_CB(skb)->dccpd_opt_len + len + 3 > DCCP_MAX_OPT_LEN) { |
446 | DCCP_WARN("Lacking space for %u bytes on %s packet\n", len, | 470 | DCCP_WARN("packet too small for feature %d option!\n", feat); |
447 | dccp_packet_name(dcb->dccpd_type)); | ||
448 | return -1; | 471 | return -1; |
449 | } | 472 | } |
450 | /* | ||
451 | * Since Ack Vectors are variable-length, we can not always predict | ||
452 | * their size. To catch exception cases where the space is running out | ||
453 | * on the skb, a separate Sync is scheduled to carry the Ack Vector. | ||
454 | */ | ||
455 | if (len > DCCPAV_MIN_OPTLEN && | ||
456 | len + dcb->dccpd_opt_len + skb->len > dp->dccps_mss_cache) { | ||
457 | DCCP_WARN("No space left for Ack Vector (%u) on skb (%u+%u), " | ||
458 | "MPS=%u ==> reduce payload size?\n", len, skb->len, | ||
459 | dcb->dccpd_opt_len, dp->dccps_mss_cache); | ||
460 | dp->dccps_sync_scheduled = 1; | ||
461 | return 0; | ||
462 | } | ||
463 | dcb->dccpd_opt_len += len; | ||
464 | 473 | ||
465 | to = skb_push(skb, len); | 474 | DCCP_SKB_CB(skb)->dccpd_opt_len += len + 3; |
466 | len = buflen; | ||
467 | from = av->av_buf + av->av_buf_head; | ||
468 | tail = av->av_buf + DCCPAV_MAX_ACKVEC_LEN; | ||
469 | 475 | ||
470 | for (i = 0; i < nr_opts; ++i) { | 476 | to = skb_push(skb, len + 3); |
471 | int copylen = len; | 477 | *to++ = type; |
472 | 478 | *to++ = len + 3; | |
473 | if (len > DCCP_SINGLE_OPT_MAXLEN) | 479 | *to++ = feat; |
474 | copylen = DCCP_SINGLE_OPT_MAXLEN; | ||
475 | |||
476 | /* | ||
477 | * RFC 4340, 12.2: Encode the Nonce Echo for this Ack Vector via | ||
478 | * its type; ack_nonce is the sum of all individual buf_nonce's. | ||
479 | */ | ||
480 | nonce ^= av->av_buf_nonce[i]; | ||
481 | |||
482 | *to++ = DCCPO_ACK_VECTOR_0 + av->av_buf_nonce[i]; | ||
483 | *to++ = copylen + 2; | ||
484 | |||
485 | /* Check if buf_head wraps */ | ||
486 | if (from + copylen > tail) { | ||
487 | const u16 tailsize = tail - from; | ||
488 | |||
489 | memcpy(to, from, tailsize); | ||
490 | to += tailsize; | ||
491 | len -= tailsize; | ||
492 | copylen -= tailsize; | ||
493 | from = av->av_buf; | ||
494 | } | ||
495 | |||
496 | memcpy(to, from, copylen); | ||
497 | from += copylen; | ||
498 | to += copylen; | ||
499 | len -= copylen; | ||
500 | } | ||
501 | /* | ||
502 | * Each sent Ack Vector is recorded in the list, as per A.2 of RFC 4340. | ||
503 | */ | ||
504 | if (dccp_ackvec_update_records(av, dcb->dccpd_seq, nonce)) | ||
505 | return -ENOBUFS; | ||
506 | return 0; | ||
507 | } | ||
508 | 480 | ||
509 | /** | 481 | if (len) |
510 | * dccp_insert_option_mandatory - Mandatory option (5.8.2) | 482 | memcpy(to, val, len); |
511 | * Note that since we are using skb_push, this function needs to be called | ||
512 | * _after_ inserting the option it is supposed to influence (stack order). | ||
513 | */ | ||
514 | int dccp_insert_option_mandatory(struct sk_buff *skb) | ||
515 | { | ||
516 | if (DCCP_SKB_CB(skb)->dccpd_opt_len >= DCCP_MAX_OPT_LEN) | ||
517 | return -1; | ||
518 | 483 | ||
519 | DCCP_SKB_CB(skb)->dccpd_opt_len++; | 484 | dccp_pr_debug("%s(%s (%d), ...), length %d\n", |
520 | *skb_push(skb, 1) = DCCPO_MANDATORY; | 485 | dccp_feat_typename(type), |
486 | dccp_feat_name(feat), feat, len); | ||
521 | return 0; | 487 | return 0; |
522 | } | 488 | } |
523 | 489 | ||
524 | /** | 490 | static int dccp_insert_options_feat(struct sock *sk, struct sk_buff *skb) |
525 | * dccp_insert_fn_opt - Insert single Feature-Negotiation option into @skb | ||
526 | * @type: %DCCPO_CHANGE_L, %DCCPO_CHANGE_R, %DCCPO_CONFIRM_L, %DCCPO_CONFIRM_R | ||
527 | * @feat: one out of %dccp_feature_numbers | ||
528 | * @val: NN value or SP array (preferred element first) to copy | ||
529 | * @len: true length of @val in bytes (excluding first element repetition) | ||
530 | * @repeat_first: whether to copy the first element of @val twice | ||
531 | * The last argument is used to construct Confirm options, where the preferred | ||
532 | * value and the preference list appear separately (RFC 4340, 6.3.1). Preference | ||
533 | * lists are kept such that the preferred entry is always first, so we only need | ||
534 | * to copy twice, and avoid the overhead of cloning into a bigger array. | ||
535 | */ | ||
536 | int dccp_insert_fn_opt(struct sk_buff *skb, u8 type, u8 feat, | ||
537 | u8 *val, u8 len, bool repeat_first) | ||
538 | { | 491 | { |
539 | u8 tot_len, *to; | 492 | struct dccp_sock *dp = dccp_sk(sk); |
493 | struct dccp_minisock *dmsk = dccp_msk(sk); | ||
494 | struct dccp_opt_pend *opt, *next; | ||
495 | int change = 0; | ||
496 | |||
497 | /* confirm any options [NN opts] */ | ||
498 | list_for_each_entry_safe(opt, next, &dmsk->dccpms_conf, dccpop_node) { | ||
499 | dccp_insert_feat_opt(skb, opt->dccpop_type, | ||
500 | opt->dccpop_feat, opt->dccpop_val, | ||
501 | opt->dccpop_len); | ||
502 | /* fear empty confirms */ | ||
503 | if (opt->dccpop_val) | ||
504 | kfree(opt->dccpop_val); | ||
505 | kfree(opt); | ||
506 | } | ||
507 | INIT_LIST_HEAD(&dmsk->dccpms_conf); | ||
508 | |||
509 | /* see which features we need to send */ | ||
510 | list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) { | ||
511 | /* see if we need to send any confirm */ | ||
512 | if (opt->dccpop_sc) { | ||
513 | dccp_insert_feat_opt(skb, opt->dccpop_type + 1, | ||
514 | opt->dccpop_feat, | ||
515 | opt->dccpop_sc->dccpoc_val, | ||
516 | opt->dccpop_sc->dccpoc_len); | ||
517 | |||
518 | BUG_ON(!opt->dccpop_sc->dccpoc_val); | ||
519 | kfree(opt->dccpop_sc->dccpoc_val); | ||
520 | kfree(opt->dccpop_sc); | ||
521 | opt->dccpop_sc = NULL; | ||
522 | } | ||
540 | 523 | ||
541 | /* take the `Feature' field and possible repetition into account */ | 524 | /* any option not confirmed, re-send it */ |
542 | if (len > (DCCP_SINGLE_OPT_MAXLEN - 2)) { | 525 | if (!opt->dccpop_conf) { |
543 | DCCP_WARN("length %u for feature %u too large\n", len, feat); | 526 | dccp_insert_feat_opt(skb, opt->dccpop_type, |
544 | return -1; | 527 | opt->dccpop_feat, opt->dccpop_val, |
528 | opt->dccpop_len); | ||
529 | change++; | ||
530 | } | ||
545 | } | 531 | } |
546 | 532 | ||
547 | if (unlikely(val == NULL || len == 0)) | 533 | /* Retransmit timer. |
548 | len = repeat_first = 0; | 534 | * If this is the master listening sock, we don't set a timer on it. It |
549 | tot_len = 3 + repeat_first + len; | 535 | * should be fine because if the dude doesn't receive our RESPONSE |
536 | * [which will contain the CHANGE] he will send another REQUEST which | ||
537 | * will "retrnasmit" the change. | ||
538 | */ | ||
539 | if (change && dp->dccps_role != DCCP_ROLE_LISTEN) { | ||
540 | dccp_pr_debug("reset feat negotiation timer %p\n", sk); | ||
550 | 541 | ||
551 | if (DCCP_SKB_CB(skb)->dccpd_opt_len + tot_len > DCCP_MAX_OPT_LEN) { | 542 | /* XXX don't reset the timer on re-transmissions. I.e. reset it |
552 | DCCP_WARN("packet too small for feature %d option!\n", feat); | 543 | * only when sending new stuff i guess. Currently the timer |
553 | return -1; | 544 | * never backs off because on re-transmission it just resets it! |
545 | */ | ||
546 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, | ||
547 | inet_csk(sk)->icsk_rto, DCCP_RTO_MAX); | ||
554 | } | 548 | } |
555 | DCCP_SKB_CB(skb)->dccpd_opt_len += tot_len; | ||
556 | |||
557 | to = skb_push(skb, tot_len); | ||
558 | *to++ = type; | ||
559 | *to++ = tot_len; | ||
560 | *to++ = feat; | ||
561 | 549 | ||
562 | if (repeat_first) | ||
563 | *to++ = *val; | ||
564 | if (len) | ||
565 | memcpy(to, val, len); | ||
566 | return 0; | 550 | return 0; |
567 | } | 551 | } |
568 | 552 | ||
@@ -581,30 +565,19 @@ static void dccp_insert_option_padding(struct sk_buff *skb) | |||
581 | int dccp_insert_options(struct sock *sk, struct sk_buff *skb) | 565 | int dccp_insert_options(struct sock *sk, struct sk_buff *skb) |
582 | { | 566 | { |
583 | struct dccp_sock *dp = dccp_sk(sk); | 567 | struct dccp_sock *dp = dccp_sk(sk); |
568 | struct dccp_minisock *dmsk = dccp_msk(sk); | ||
584 | 569 | ||
585 | DCCP_SKB_CB(skb)->dccpd_opt_len = 0; | 570 | DCCP_SKB_CB(skb)->dccpd_opt_len = 0; |
586 | 571 | ||
587 | if (dp->dccps_send_ndp_count && dccp_insert_option_ndp(sk, skb)) | 572 | if (dmsk->dccpms_send_ndp_count && |
573 | dccp_insert_option_ndp(sk, skb)) | ||
588 | return -1; | 574 | return -1; |
589 | 575 | ||
590 | if (DCCP_SKB_CB(skb)->dccpd_type != DCCP_PKT_DATA) { | 576 | if (!dccp_packet_without_ack(skb)) { |
591 | 577 | if (dmsk->dccpms_send_ack_vector && | |
592 | /* Feature Negotiation */ | 578 | dccp_ackvec_pending(dp->dccps_hc_rx_ackvec) && |
593 | if (dccp_feat_insert_opts(dp, NULL, skb)) | 579 | dccp_insert_option_ackvec(sk, skb)) |
594 | return -1; | 580 | return -1; |
595 | |||
596 | if (DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_REQUEST) { | ||
597 | /* | ||
598 | * Obtain RTT sample from Request/Response exchange. | ||
599 | * This is currently used in CCID 3 initialisation. | ||
600 | */ | ||
601 | if (dccp_insert_option_timestamp(sk, skb)) | ||
602 | return -1; | ||
603 | |||
604 | } else if (dccp_ackvec_pending(sk) && | ||
605 | dccp_insert_option_ackvec(sk, skb)) { | ||
606 | return -1; | ||
607 | } | ||
608 | } | 581 | } |
609 | 582 | ||
610 | if (dp->dccps_hc_rx_insert_options) { | 583 | if (dp->dccps_hc_rx_insert_options) { |
@@ -613,6 +586,21 @@ int dccp_insert_options(struct sock *sk, struct sk_buff *skb) | |||
613 | dp->dccps_hc_rx_insert_options = 0; | 586 | dp->dccps_hc_rx_insert_options = 0; |
614 | } | 587 | } |
615 | 588 | ||
589 | /* Feature negotiation */ | ||
590 | /* Data packets can't do feat negotiation */ | ||
591 | if (DCCP_SKB_CB(skb)->dccpd_type != DCCP_PKT_DATA && | ||
592 | DCCP_SKB_CB(skb)->dccpd_type != DCCP_PKT_DATAACK && | ||
593 | dccp_insert_options_feat(sk, skb)) | ||
594 | return -1; | ||
595 | |||
596 | /* | ||
597 | * Obtain RTT sample from Request/Response exchange. | ||
598 | * This is currently used in CCID 3 initialisation. | ||
599 | */ | ||
600 | if (DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_REQUEST && | ||
601 | dccp_insert_option_timestamp(sk, skb)) | ||
602 | return -1; | ||
603 | |||
616 | if (dp->dccps_timestamp_echo != 0 && | 604 | if (dp->dccps_timestamp_echo != 0 && |
617 | dccp_insert_option_timestamp_echo(dp, NULL, skb)) | 605 | dccp_insert_option_timestamp_echo(dp, NULL, skb)) |
618 | return -1; | 606 | return -1; |
@@ -625,9 +613,6 @@ int dccp_insert_options_rsk(struct dccp_request_sock *dreq, struct sk_buff *skb) | |||
625 | { | 613 | { |
626 | DCCP_SKB_CB(skb)->dccpd_opt_len = 0; | 614 | DCCP_SKB_CB(skb)->dccpd_opt_len = 0; |
627 | 615 | ||
628 | if (dccp_feat_insert_opts(NULL, dreq, skb)) | ||
629 | return -1; | ||
630 | |||
631 | if (dreq->dreq_timestamp_echo != 0 && | 616 | if (dreq->dreq_timestamp_echo != 0 && |
632 | dccp_insert_option_timestamp_echo(NULL, dreq, skb)) | 617 | dccp_insert_option_timestamp_echo(NULL, dreq, skb)) |
633 | return -1; | 618 | return -1; |