diff options
Diffstat (limited to 'net/dccp/options.c')
-rw-r--r-- | net/dccp/options.c | 341 |
1 files changed, 178 insertions, 163 deletions
diff --git a/net/dccp/options.c b/net/dccp/options.c index 0809b63cb055..e5a32979d7d7 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c | |||
@@ -23,23 +23,20 @@ | |||
23 | #include "dccp.h" | 23 | #include "dccp.h" |
24 | #include "feat.h" | 24 | #include "feat.h" |
25 | 25 | ||
26 | int sysctl_dccp_feat_sequence_window = DCCPF_INITIAL_SEQUENCE_WINDOW; | 26 | u64 dccp_decode_value_var(const u8 *bf, const u8 len) |
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) | ||
34 | { | 27 | { |
35 | u32 value = 0; | 28 | u64 value = 0; |
36 | 29 | ||
30 | if (len >= DCCP_OPTVAL_MAXLEN) | ||
31 | value += ((u64)*bf++) << 40; | ||
32 | if (len > 4) | ||
33 | value += ((u64)*bf++) << 32; | ||
37 | if (len > 3) | 34 | if (len > 3) |
38 | value += *bf++ << 24; | 35 | value += ((u64)*bf++) << 24; |
39 | if (len > 2) | 36 | if (len > 2) |
40 | value += *bf++ << 16; | 37 | value += ((u64)*bf++) << 16; |
41 | if (len > 1) | 38 | if (len > 1) |
42 | value += *bf++ << 8; | 39 | value += ((u64)*bf++) << 8; |
43 | if (len > 0) | 40 | if (len > 0) |
44 | value += *bf; | 41 | value += *bf; |
45 | 42 | ||
@@ -57,7 +54,6 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq, | |||
57 | struct dccp_sock *dp = dccp_sk(sk); | 54 | struct dccp_sock *dp = dccp_sk(sk); |
58 | const struct dccp_hdr *dh = dccp_hdr(skb); | 55 | const struct dccp_hdr *dh = dccp_hdr(skb); |
59 | const u8 pkt_type = DCCP_SKB_CB(skb)->dccpd_type; | 56 | const u8 pkt_type = DCCP_SKB_CB(skb)->dccpd_type; |
60 | u64 ackno = DCCP_SKB_CB(skb)->dccpd_ack_seq; | ||
61 | unsigned char *options = (unsigned char *)dh + dccp_hdr_len(skb); | 57 | unsigned char *options = (unsigned char *)dh + dccp_hdr_len(skb); |
62 | unsigned char *opt_ptr = options; | 58 | unsigned char *opt_ptr = options; |
63 | const unsigned char *opt_end = (unsigned char *)dh + | 59 | const unsigned char *opt_end = (unsigned char *)dh + |
@@ -99,18 +95,11 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq, | |||
99 | } | 95 | } |
100 | 96 | ||
101 | /* | 97 | /* |
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 | 98 | * CCID-specific options are ignored during connection setup, as |
109 | * negotiation may still be in progress (see RFC 4340, 10.3). | 99 | * negotiation may still be in progress (see RFC 4340, 10.3). |
110 | * The same applies to Ack Vectors, as these depend on the CCID. | 100 | * The same applies to Ack Vectors, as these depend on the CCID. |
111 | * | ||
112 | */ | 101 | */ |
113 | if (dreq != NULL && (opt >= 128 || | 102 | if (dreq != NULL && (opt >= DCCPO_MIN_RX_CCID_SPECIFIC || |
114 | opt == DCCPO_ACK_VECTOR_0 || opt == DCCPO_ACK_VECTOR_1)) | 103 | opt == DCCPO_ACK_VECTOR_0 || opt == DCCPO_ACK_VECTOR_1)) |
115 | goto ignore_option; | 104 | goto ignore_option; |
116 | 105 | ||
@@ -131,43 +120,13 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq, | |||
131 | dccp_pr_debug("%s opt: NDP count=%llu\n", dccp_role(sk), | 120 | dccp_pr_debug("%s opt: NDP count=%llu\n", dccp_role(sk), |
132 | (unsigned long long)opt_recv->dccpor_ndp); | 121 | (unsigned long long)opt_recv->dccpor_ndp); |
133 | break; | 122 | break; |
134 | case DCCPO_CHANGE_L: | 123 | case DCCPO_CHANGE_L ... DCCPO_CONFIRM_R: |
135 | /* fall through */ | 124 | if (pkt_type == DCCP_PKT_DATA) /* RFC 4340, 6 */ |
136 | case DCCPO_CHANGE_R: | ||
137 | if (pkt_type == DCCP_PKT_DATA) | ||
138 | break; | 125 | break; |
139 | if (len < 2) | 126 | rc = dccp_feat_parse_options(sk, dreq, mandatory, opt, |
140 | goto out_invalid_option; | 127 | *value, value + 1, len - 1); |
141 | rc = dccp_feat_change_recv(sk, opt, *value, value + 1, | 128 | if (rc) |
142 | len - 1); | 129 | goto out_featneg_failed; |
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; | ||
171 | break; | 130 | break; |
172 | case DCCPO_TIMESTAMP: | 131 | case DCCPO_TIMESTAMP: |
173 | if (len != 4) | 132 | if (len != 4) |
@@ -195,6 +154,8 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq, | |||
195 | dccp_role(sk), ntohl(opt_val), | 154 | dccp_role(sk), ntohl(opt_val), |
196 | (unsigned long long) | 155 | (unsigned long long) |
197 | DCCP_SKB_CB(skb)->dccpd_ack_seq); | 156 | DCCP_SKB_CB(skb)->dccpd_ack_seq); |
157 | /* schedule an Ack in case this sender is quiescent */ | ||
158 | inet_csk_schedule_ack(sk); | ||
198 | break; | 159 | break; |
199 | case DCCPO_TIMESTAMP_ECHO: | 160 | case DCCPO_TIMESTAMP_ECHO: |
200 | if (len != 4 && len != 6 && len != 8) | 161 | if (len != 4 && len != 6 && len != 8) |
@@ -251,23 +212,25 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq, | |||
251 | dccp_pr_debug("%s rx opt: ELAPSED_TIME=%d\n", | 212 | dccp_pr_debug("%s rx opt: ELAPSED_TIME=%d\n", |
252 | dccp_role(sk), elapsed_time); | 213 | dccp_role(sk), elapsed_time); |
253 | break; | 214 | break; |
254 | case 128 ... 191: { | 215 | case DCCPO_MIN_RX_CCID_SPECIFIC ... DCCPO_MAX_RX_CCID_SPECIFIC: |
255 | const u16 idx = value - options; | ||
256 | |||
257 | if (ccid_hc_rx_parse_options(dp->dccps_hc_rx_ccid, sk, | 216 | if (ccid_hc_rx_parse_options(dp->dccps_hc_rx_ccid, sk, |
258 | opt, len, idx, | 217 | pkt_type, opt, value, len)) |
259 | value) != 0) | ||
260 | goto out_invalid_option; | 218 | goto out_invalid_option; |
261 | } | ||
262 | break; | 219 | break; |
263 | case 192 ... 255: { | 220 | case DCCPO_ACK_VECTOR_0: |
264 | const u16 idx = value - options; | 221 | case DCCPO_ACK_VECTOR_1: |
265 | 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 | */ | ||
230 | case DCCPO_MIN_TX_CCID_SPECIFIC ... DCCPO_MAX_TX_CCID_SPECIFIC: | ||
266 | 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, |
267 | opt, len, idx, | 232 | pkt_type, opt, value, len)) |
268 | value) != 0) | ||
269 | goto out_invalid_option; | 233 | goto out_invalid_option; |
270 | } | ||
271 | break; | 234 | break; |
272 | default: | 235 | default: |
273 | DCCP_CRIT("DCCP(%p): option %d(len=%d) not " | 236 | DCCP_CRIT("DCCP(%p): option %d(len=%d) not " |
@@ -289,8 +252,10 @@ out_nonsensical_length: | |||
289 | 252 | ||
290 | out_invalid_option: | 253 | out_invalid_option: |
291 | DCCP_INC_STATS_BH(DCCP_MIB_INVALIDOPT); | 254 | DCCP_INC_STATS_BH(DCCP_MIB_INVALIDOPT); |
292 | DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_OPTION_ERROR; | 255 | rc = DCCP_RESET_CODE_OPTION_ERROR; |
293 | DCCP_WARN("DCCP(%p): invalid option %d, len=%d", sk, opt, len); | 256 | out_featneg_failed: |
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; | ||
294 | DCCP_SKB_CB(skb)->dccpd_reset_data[0] = opt; | 259 | DCCP_SKB_CB(skb)->dccpd_reset_data[0] = opt; |
295 | DCCP_SKB_CB(skb)->dccpd_reset_data[1] = len > 0 ? value[0] : 0; | 260 | DCCP_SKB_CB(skb)->dccpd_reset_data[1] = len > 0 ? value[0] : 0; |
296 | DCCP_SKB_CB(skb)->dccpd_reset_data[2] = len > 1 ? value[1] : 0; | 261 | DCCP_SKB_CB(skb)->dccpd_reset_data[2] = len > 1 ? value[1] : 0; |
@@ -299,9 +264,12 @@ out_invalid_option: | |||
299 | 264 | ||
300 | EXPORT_SYMBOL_GPL(dccp_parse_options); | 265 | EXPORT_SYMBOL_GPL(dccp_parse_options); |
301 | 266 | ||
302 | static void dccp_encode_value_var(const u32 value, unsigned char *to, | 267 | void dccp_encode_value_var(const u64 value, u8 *to, const u8 len) |
303 | const unsigned int len) | ||
304 | { | 268 | { |
269 | if (len >= DCCP_OPTVAL_MAXLEN) | ||
270 | *to++ = (value & 0xFF0000000000ull) >> 40; | ||
271 | if (len > 4) | ||
272 | *to++ = (value & 0xFF00000000ull) >> 32; | ||
305 | if (len > 3) | 273 | if (len > 3) |
306 | *to++ = (value & 0xFF000000) >> 24; | 274 | *to++ = (value & 0xFF000000) >> 24; |
307 | if (len > 2) | 275 | if (len > 2) |
@@ -461,92 +429,140 @@ static int dccp_insert_option_timestamp_echo(struct dccp_sock *dp, | |||
461 | return 0; | 429 | return 0; |
462 | } | 430 | } |
463 | 431 | ||
464 | static int dccp_insert_feat_opt(struct sk_buff *skb, u8 type, u8 feat, | 432 | static int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb) |
465 | u8 *val, u8 len) | ||
466 | { | 433 | { |
467 | u8 *to; | 434 | struct dccp_sock *dp = dccp_sk(sk); |
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; | ||
468 | 444 | ||
469 | if (DCCP_SKB_CB(skb)->dccpd_opt_len + len + 3 > DCCP_MAX_OPT_LEN) { | 445 | if (dcb->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) { |
470 | DCCP_WARN("packet too small for feature %d option!\n", feat); | 446 | DCCP_WARN("Lacking space for %u bytes on %s packet\n", len, |
447 | dccp_packet_name(dcb->dccpd_type)); | ||
471 | return -1; | 448 | return -1; |
472 | } | 449 | } |
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; | ||
473 | 464 | ||
474 | DCCP_SKB_CB(skb)->dccpd_opt_len += len + 3; | 465 | to = skb_push(skb, len); |
466 | len = buflen; | ||
467 | from = av->av_buf + av->av_buf_head; | ||
468 | tail = av->av_buf + DCCPAV_MAX_ACKVEC_LEN; | ||
475 | 469 | ||
476 | to = skb_push(skb, len + 3); | 470 | for (i = 0; i < nr_opts; ++i) { |
477 | *to++ = type; | 471 | int copylen = len; |
478 | *to++ = len + 3; | ||
479 | *to++ = feat; | ||
480 | 472 | ||
481 | if (len) | 473 | if (len > DCCP_SINGLE_OPT_MAXLEN) |
482 | memcpy(to, val, len); | 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; | ||
483 | 484 | ||
484 | dccp_pr_debug("%s(%s (%d), ...), length %d\n", | 485 | /* Check if buf_head wraps */ |
485 | dccp_feat_typename(type), | 486 | if (from + copylen > tail) { |
486 | dccp_feat_name(feat), feat, len); | 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; | ||
487 | return 0; | 506 | return 0; |
488 | } | 507 | } |
489 | 508 | ||
490 | static int dccp_insert_options_feat(struct sock *sk, struct sk_buff *skb) | 509 | /** |
510 | * dccp_insert_option_mandatory - Mandatory option (5.8.2) | ||
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) | ||
491 | { | 515 | { |
492 | struct dccp_sock *dp = dccp_sk(sk); | 516 | if (DCCP_SKB_CB(skb)->dccpd_opt_len >= DCCP_MAX_OPT_LEN) |
493 | struct dccp_minisock *dmsk = dccp_msk(sk); | 517 | return -1; |
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 | } | ||
523 | 518 | ||
524 | /* any option not confirmed, re-send it */ | 519 | DCCP_SKB_CB(skb)->dccpd_opt_len++; |
525 | if (!opt->dccpop_conf) { | 520 | *skb_push(skb, 1) = DCCPO_MANDATORY; |
526 | dccp_insert_feat_opt(skb, opt->dccpop_type, | 521 | return 0; |
527 | opt->dccpop_feat, opt->dccpop_val, | 522 | } |
528 | opt->dccpop_len); | 523 | |
529 | change++; | 524 | /** |
530 | } | 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 | { | ||
539 | u8 tot_len, *to; | ||
540 | |||
541 | /* take the `Feature' field and possible repetition into account */ | ||
542 | if (len > (DCCP_SINGLE_OPT_MAXLEN - 2)) { | ||
543 | DCCP_WARN("length %u for feature %u too large\n", len, feat); | ||
544 | return -1; | ||
531 | } | 545 | } |
532 | 546 | ||
533 | /* Retransmit timer. | 547 | if (unlikely(val == NULL || len == 0)) |
534 | * If this is the master listening sock, we don't set a timer on it. It | 548 | len = repeat_first = 0; |
535 | * should be fine because if the dude doesn't receive our RESPONSE | 549 | tot_len = 3 + repeat_first + len; |
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); | ||
541 | 550 | ||
542 | /* XXX don't reset the timer on re-transmissions. I.e. reset it | 551 | if (DCCP_SKB_CB(skb)->dccpd_opt_len + tot_len > DCCP_MAX_OPT_LEN) { |
543 | * only when sending new stuff i guess. Currently the timer | 552 | DCCP_WARN("packet too small for feature %d option!\n", feat); |
544 | * never backs off because on re-transmission it just resets it! | 553 | return -1; |
545 | */ | ||
546 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, | ||
547 | inet_csk(sk)->icsk_rto, DCCP_RTO_MAX); | ||
548 | } | 554 | } |
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; | ||
549 | 561 | ||
562 | if (repeat_first) | ||
563 | *to++ = *val; | ||
564 | if (len) | ||
565 | memcpy(to, val, len); | ||
550 | return 0; | 566 | return 0; |
551 | } | 567 | } |
552 | 568 | ||
@@ -565,19 +581,30 @@ static void dccp_insert_option_padding(struct sk_buff *skb) | |||
565 | int dccp_insert_options(struct sock *sk, struct sk_buff *skb) | 581 | int dccp_insert_options(struct sock *sk, struct sk_buff *skb) |
566 | { | 582 | { |
567 | struct dccp_sock *dp = dccp_sk(sk); | 583 | struct dccp_sock *dp = dccp_sk(sk); |
568 | struct dccp_minisock *dmsk = dccp_msk(sk); | ||
569 | 584 | ||
570 | DCCP_SKB_CB(skb)->dccpd_opt_len = 0; | 585 | DCCP_SKB_CB(skb)->dccpd_opt_len = 0; |
571 | 586 | ||
572 | if (dmsk->dccpms_send_ndp_count && | 587 | if (dp->dccps_send_ndp_count && dccp_insert_option_ndp(sk, skb)) |
573 | dccp_insert_option_ndp(sk, skb)) | ||
574 | return -1; | 588 | return -1; |
575 | 589 | ||
576 | if (!dccp_packet_without_ack(skb)) { | 590 | if (DCCP_SKB_CB(skb)->dccpd_type != DCCP_PKT_DATA) { |
577 | if (dmsk->dccpms_send_ack_vector && | 591 | |
578 | dccp_ackvec_pending(dp->dccps_hc_rx_ackvec) && | 592 | /* Feature Negotiation */ |
579 | dccp_insert_option_ackvec(sk, skb)) | 593 | if (dccp_feat_insert_opts(dp, NULL, skb)) |
580 | return -1; | 594 | 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 | } | ||
581 | } | 608 | } |
582 | 609 | ||
583 | if (dp->dccps_hc_rx_insert_options) { | 610 | if (dp->dccps_hc_rx_insert_options) { |
@@ -586,21 +613,6 @@ int dccp_insert_options(struct sock *sk, struct sk_buff *skb) | |||
586 | dp->dccps_hc_rx_insert_options = 0; | 613 | dp->dccps_hc_rx_insert_options = 0; |
587 | } | 614 | } |
588 | 615 | ||
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 | |||
604 | if (dp->dccps_timestamp_echo != 0 && | 616 | if (dp->dccps_timestamp_echo != 0 && |
605 | dccp_insert_option_timestamp_echo(dp, NULL, skb)) | 617 | dccp_insert_option_timestamp_echo(dp, NULL, skb)) |
606 | return -1; | 618 | return -1; |
@@ -613,6 +625,9 @@ int dccp_insert_options_rsk(struct dccp_request_sock *dreq, struct sk_buff *skb) | |||
613 | { | 625 | { |
614 | DCCP_SKB_CB(skb)->dccpd_opt_len = 0; | 626 | DCCP_SKB_CB(skb)->dccpd_opt_len = 0; |
615 | 627 | ||
628 | if (dccp_feat_insert_opts(NULL, dreq, skb)) | ||
629 | return -1; | ||
630 | |||
616 | if (dreq->dreq_timestamp_echo != 0 && | 631 | if (dreq->dreq_timestamp_echo != 0 && |
617 | dccp_insert_option_timestamp_echo(NULL, dreq, skb)) | 632 | dccp_insert_option_timestamp_echo(NULL, dreq, skb)) |
618 | return -1; | 633 | return -1; |