options.c 16.1 KB
Newer Older
1 2 3 4
/*
 *  net/dccp/options.c
 *
 *  An implementation of the DCCP protocol
I
Ian McDonald 已提交
5 6
 *  Copyright (c) 2005 Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
 *  Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
7
 *  Copyright (c) 2005 Ian McDonald <ian.mcdonald@jandi.co.nz>
8 9 10 11 12 13 14 15 16
 *
 *      This program is free software; you can redistribute it and/or
 *      modify it under the terms of the GNU General Public License
 *      as published by the Free Software Foundation; either version
 *      2 of the License, or (at your option) any later version.
 */
#include <linux/dccp.h>
#include <linux/module.h>
#include <linux/types.h>
G
Gerrit Renker 已提交
17
#include <asm/unaligned.h>
18 19 20
#include <linux/kernel.h>
#include <linux/skbuff.h>

21
#include "ackvec.h"
22 23
#include "ccid.h"
#include "dccp.h"
24
#include "feat.h"
25

26 27 28 29 30 31
int sysctl_dccp_feat_sequence_window = DCCPF_INITIAL_SEQUENCE_WINDOW;
int sysctl_dccp_feat_rx_ccid	      = DCCPF_INITIAL_CCID;
int sysctl_dccp_feat_tx_ccid	      = DCCPF_INITIAL_CCID;
int sysctl_dccp_feat_send_ack_vector = DCCPF_INITIAL_SEND_ACK_VECTOR;
int sysctl_dccp_feat_send_ndp_count  = DCCPF_INITIAL_SEND_NDP_COUNT;

32
u64 dccp_decode_value_var(const u8 *bf, const u8 len)
33
{
34
	u64 value = 0;
35

36 37 38 39
	if (len >= DCCP_OPTVAL_MAXLEN)
		value += ((u64)*bf++) << 40;
	if (len > 4)
		value += ((u64)*bf++) << 32;
40
	if (len > 3)
41
		value += ((u64)*bf++) << 24;
42
	if (len > 2)
43
		value += ((u64)*bf++) << 16;
44
	if (len > 1)
45
		value += ((u64)*bf++) << 8;
46 47 48 49 50 51
	if (len > 0)
		value += *bf;

	return value;
}

52 53 54 55 56 57 58
/**
 * dccp_parse_options  -  Parse DCCP options present in @skb
 * @sk: client|server|listening dccp socket (when @dreq != NULL)
 * @dreq: request socket to use during connection setup, or NULL
 */
int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq,
		       struct sk_buff *skb)
59 60 61 62
{
	struct dccp_sock *dp = dccp_sk(sk);
	const struct dccp_hdr *dh = dccp_hdr(skb);
	const u8 pkt_type = DCCP_SKB_CB(skb)->dccpd_type;
63
	u64 ackno = DCCP_SKB_CB(skb)->dccpd_ack_seq;
64 65
	unsigned char *options = (unsigned char *)dh + dccp_hdr_len(skb);
	unsigned char *opt_ptr = options;
66 67
	const unsigned char *opt_end = (unsigned char *)dh +
					(dh->dccph_doff * 4);
68 69
	struct dccp_options_received *opt_recv = &dp->dccps_options_received;
	unsigned char opt, len;
70
	unsigned char *uninitialized_var(value);
71
	u32 elapsed_time;
G
Gerrit Renker 已提交
72
	__be32 opt_val;
73 74
	int rc;
	int mandatory = 0;
75 76 77

	memset(opt_recv, 0, sizeof(*opt_recv));

78
	opt = len = 0;
79 80 81 82 83 84 85 86
	while (opt_ptr != opt_end) {
		opt   = *opt_ptr++;
		len   = 0;
		value = NULL;

		/* Check if this isn't a single byte option */
		if (opt > DCCPO_MAX_RESERVED) {
			if (opt_ptr == opt_end)
87
				goto out_nonsensical_length;
88 89

			len = *opt_ptr++;
90 91
			if (len < 2)
				goto out_nonsensical_length;
92 93 94 95 96 97 98 99 100
			/*
			 * Remove the type and len fields, leaving
			 * just the value size
			 */
			len	-= 2;
			value	= opt_ptr;
			opt_ptr += len;

			if (opt_ptr > opt_end)
101
				goto out_nonsensical_length;
102 103
		}

104
		/*
105 106 107 108 109 110
		 * CCID-Specific Options (from RFC 4340, sec. 10.3):
		 *
		 * Option numbers 128 through 191 are for options sent from the
		 * HC-Sender to the HC-Receiver; option numbers 192 through 255
		 * are for options sent from the HC-Receiver to	the HC-Sender.
		 *
111 112
		 * CCID-specific options are ignored during connection setup, as
		 * negotiation may still be in progress (see RFC 4340, 10.3).
113
		 * The same applies to Ack Vectors, as these depend on the CCID.
114
		 *
115
		 */
116
		if (dreq != NULL && (opt >= 128 ||
117
		    opt == DCCPO_ACK_VECTOR_0 || opt == DCCPO_ACK_VECTOR_1))
118 119
			goto ignore_option;

120 121 122
		switch (opt) {
		case DCCPO_PADDING:
			break;
123 124 125
		case DCCPO_MANDATORY:
			if (mandatory)
				goto out_invalid_option;
126 127
			if (pkt_type != DCCP_PKT_DATA)
				mandatory = 1;
128
			break;
129
		case DCCPO_NDP_COUNT:
130
			if (len > 6)
131 132 133
				goto out_invalid_option;

			opt_recv->dccpor_ndp = dccp_decode_value_var(value, len);
134 135
			dccp_pr_debug("%s opt: NDP count=%llu\n", dccp_role(sk),
				      (unsigned long long)opt_recv->dccpor_ndp);
136
			break;
137 138 139 140
		case DCCPO_CHANGE_L:
			/* fall through */
		case DCCPO_CHANGE_R:
			if (pkt_type == DCCP_PKT_DATA)
141
				break;
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
			if (len < 2)
				goto out_invalid_option;
			rc = dccp_feat_change_recv(sk, opt, *value, value + 1,
						   len - 1);
			/*
			 * When there is a change error, change_recv is
			 * responsible for dealing with it.  i.e. reply with an
			 * empty confirm.
			 * If the change was mandatory, then we need to die.
			 */
			if (rc && mandatory)
				goto out_invalid_option;
			break;
		case DCCPO_CONFIRM_L:
			/* fall through */
		case DCCPO_CONFIRM_R:
			if (pkt_type == DCCP_PKT_DATA)
				break;
			if (len < 2)	/* FIXME this disallows empty confirm */
				goto out_invalid_option;
			if (dccp_feat_confirm_recv(sk, opt, *value,
						   value + 1, len - 1))
				goto out_invalid_option;
			break;
		case DCCPO_ACK_VECTOR_0:
		case DCCPO_ACK_VECTOR_1:
			if (dccp_packet_without_ack(skb))   /* RFC 4340, 11.4 */
				break;

			if (dccp_msk(sk)->dccpms_send_ack_vector &&
			    dccp_ackvec_parse(sk, skb, &ackno, opt, value, len))
				goto out_invalid_option;
174
			break;
175 176 177
		case DCCPO_TIMESTAMP:
			if (len != 4)
				goto out_invalid_option;
178 179 180 181 182
			/*
			 * RFC 4340 13.1: "The precise time corresponding to
			 * Timestamp Value zero is not specified". We use
			 * zero to indicate absence of a meaningful timestamp.
			 */
G
Gerrit Renker 已提交
183
			opt_val = get_unaligned((__be32 *)value);
184 185 186 187
			if (unlikely(opt_val == 0)) {
				DCCP_WARN("Timestamp with zero value\n");
				break;
			}
188

189 190 191 192 193 194 195 196
			if (dreq != NULL) {
				dreq->dreq_timestamp_echo = ntohl(opt_val);
				dreq->dreq_timestamp_time = dccp_timestamp();
			} else {
				opt_recv->dccpor_timestamp =
					dp->dccps_timestamp_echo = ntohl(opt_val);
				dp->dccps_timestamp_time = dccp_timestamp();
			}
197
			dccp_pr_debug("%s rx opt: TIMESTAMP=%u, ackno=%llu\n",
198
				      dccp_role(sk), ntohl(opt_val),
199
				      (unsigned long long)
200 201 202
				      DCCP_SKB_CB(skb)->dccpd_ack_seq);
			break;
		case DCCPO_TIMESTAMP_ECHO:
I
Ian McDonald 已提交
203
			if (len != 4 && len != 6 && len != 8)
204 205
				goto out_invalid_option;

G
Gerrit Renker 已提交
206 207
			opt_val = get_unaligned((__be32 *)value);
			opt_recv->dccpor_timestamp_echo = ntohl(opt_val);
208

209
			dccp_pr_debug("%s rx opt: TIMESTAMP_ECHO=%u, len=%d, "
210
				      "ackno=%llu", dccp_role(sk),
211
				      opt_recv->dccpor_timestamp_echo,
212 213
				      len + 2,
				      (unsigned long long)
I
Ian McDonald 已提交
214 215
				      DCCP_SKB_CB(skb)->dccpd_ack_seq);

G
Gerrit Renker 已提交
216
			value += 4;
I
Ian McDonald 已提交
217

G
Gerrit Renker 已提交
218
			if (len == 4) {		/* no elapsed time included */
219
				dccp_pr_debug_cat("\n");
220
				break;
221
			}
222

G
Gerrit Renker 已提交
223 224 225 226 227 228 229
			if (len == 6) {		/* 2-byte elapsed time */
				__be16 opt_val2 = get_unaligned((__be16 *)value);
				elapsed_time = ntohs(opt_val2);
			} else {		/* 4-byte elapsed time */
				opt_val = get_unaligned((__be32 *)value);
				elapsed_time = ntohl(opt_val);
			}
230

G
Gerrit Renker 已提交
231
			dccp_pr_debug_cat(", ELAPSED_TIME=%u\n", elapsed_time);
232

233 234 235
			/* Give precedence to the biggest ELAPSED_TIME */
			if (elapsed_time > opt_recv->dccpor_elapsed_time)
				opt_recv->dccpor_elapsed_time = elapsed_time;
236 237
			break;
		case DCCPO_ELAPSED_TIME:
238 239
			if (dccp_packet_without_ack(skb))   /* RFC 4340, 13.2 */
				break;
I
Ian McDonald 已提交
240

G
Gerrit Renker 已提交
241 242 243
			if (len == 2) {
				__be16 opt_val2 = get_unaligned((__be16 *)value);
				elapsed_time = ntohs(opt_val2);
244
			} else if (len == 4) {
G
Gerrit Renker 已提交
245 246
				opt_val = get_unaligned((__be32 *)value);
				elapsed_time = ntohl(opt_val);
247 248
			} else {
				goto out_invalid_option;
G
Gerrit Renker 已提交
249
			}
250 251 252

			if (elapsed_time > opt_recv->dccpor_elapsed_time)
				opt_recv->dccpor_elapsed_time = elapsed_time;
I
Ian McDonald 已提交
253

254 255
			dccp_pr_debug("%s rx opt: ELAPSED_TIME=%d\n",
				      dccp_role(sk), elapsed_time);
256
			break;
257 258 259
		case 128 ... 191: {
			const u16 idx = value - options;

260
			if (ccid_hc_rx_parse_options(dp->dccps_hc_rx_ccid, sk,
261 262
						     opt, len, idx,
						     value) != 0)
263
				goto out_invalid_option;
264
		}
265
			break;
266 267 268
		case 192 ... 255: {
			const u16 idx = value - options;

269
			if (ccid_hc_tx_parse_options(dp->dccps_hc_tx_ccid, sk,
270 271
						     opt, len, idx,
						     value) != 0)
272
				goto out_invalid_option;
273
		}
274 275
			break;
		default:
276 277
			DCCP_CRIT("DCCP(%p): option %d(len=%d) not "
				  "implemented, ignoring", sk, opt, len);
278
			break;
279
		}
280
ignore_option:
281 282
		if (opt != DCCPO_MANDATORY)
			mandatory = 0;
283 284
	}

285 286 287 288
	/* mandatory was the last byte in option list -> reset connection */
	if (mandatory)
		goto out_invalid_option;

289 290
out_nonsensical_length:
	/* RFC 4340, 5.8: ignore option and all remaining option space */
291 292 293 294
	return 0;

out_invalid_option:
	DCCP_INC_STATS_BH(DCCP_MIB_INVALIDOPT);
295 296
	DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_OPTION_ERROR;
	DCCP_WARN("DCCP(%p): invalid option %d, len=%d", sk, opt, len);
297 298 299
	DCCP_SKB_CB(skb)->dccpd_reset_data[0] = opt;
	DCCP_SKB_CB(skb)->dccpd_reset_data[1] = len > 0 ? value[0] : 0;
	DCCP_SKB_CB(skb)->dccpd_reset_data[2] = len > 1 ? value[1] : 0;
300 301 302
	return -1;
}

303 304
EXPORT_SYMBOL_GPL(dccp_parse_options);

305
void dccp_encode_value_var(const u64 value, u8 *to, const u8 len)
306
{
307 308 309 310
	if (len >= DCCP_OPTVAL_MAXLEN)
		*to++ = (value & 0xFF0000000000ull) >> 40;
	if (len > 4)
		*to++ = (value & 0xFF00000000ull) >> 32;
311 312 313 314 315 316 317 318 319 320
	if (len > 3)
		*to++ = (value & 0xFF000000) >> 24;
	if (len > 2)
		*to++ = (value & 0xFF0000) >> 16;
	if (len > 1)
		*to++ = (value & 0xFF00) >> 8;
	if (len > 0)
		*to++ = (value & 0xFF);
}

321
static inline u8 dccp_ndp_len(const u64 ndp)
322
{
323 324 325
	if (likely(ndp <= 0xFF))
		return 1;
	return likely(ndp <= USHORT_MAX) ? 2 : (ndp <= UINT_MAX ? 4 : 6);
326 327
}

328
int dccp_insert_option(struct sock *sk, struct sk_buff *skb,
329 330 331 332 333
			const unsigned char option,
			const void *value, const unsigned char len)
{
	unsigned char *to;

334 335
	if (DCCP_SKB_CB(skb)->dccpd_opt_len + len + 2 > DCCP_MAX_OPT_LEN)
		return -1;
336 337 338 339 340 341 342 343

	DCCP_SKB_CB(skb)->dccpd_opt_len += len + 2;

	to    = skb_push(skb, len + 2);
	*to++ = option;
	*to++ = len + 2;

	memcpy(to, value, len);
344
	return 0;
345 346 347 348
}

EXPORT_SYMBOL_GPL(dccp_insert_option);

349
static int dccp_insert_option_ndp(struct sock *sk, struct sk_buff *skb)
350 351
{
	struct dccp_sock *dp = dccp_sk(sk);
352
	u64 ndp = dp->dccps_ndp_count;
353 354 355 356 357 358 359 360 361 362 363 364

	if (dccp_non_data_packet(skb))
		++dp->dccps_ndp_count;
	else
		dp->dccps_ndp_count = 0;

	if (ndp > 0) {
		unsigned char *ptr;
		const int ndp_len = dccp_ndp_len(ndp);
		const int len = ndp_len + 2;

		if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
365
			return -1;
366 367 368 369 370 371 372 373

		DCCP_SKB_CB(skb)->dccpd_opt_len += len;

		ptr = skb_push(skb, len);
		*ptr++ = DCCPO_NDP_COUNT;
		*ptr++ = len;
		dccp_encode_value_var(ndp, ptr, ndp_len);
	}
374 375

	return 0;
376 377 378 379
}

static inline int dccp_elapsed_time_len(const u32 elapsed_time)
{
380
	return elapsed_time == 0 ? 0 : elapsed_time <= 0xFFFF ? 2 : 4;
381 382
}

383 384
int dccp_insert_option_elapsed_time(struct sock *sk, struct sk_buff *skb,
				    u32 elapsed_time)
385 386 387 388 389
{
	const int elapsed_time_len = dccp_elapsed_time_len(elapsed_time);
	const int len = 2 + elapsed_time_len;
	unsigned char *to;

I
Ian McDonald 已提交
390
	if (elapsed_time_len == 0)
391
		return 0;
392

393 394
	if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
		return -1;
395 396 397 398 399 400 401

	DCCP_SKB_CB(skb)->dccpd_opt_len += len;

	to    = skb_push(skb, len);
	*to++ = DCCPO_ELAPSED_TIME;
	*to++ = len;

I
Ian McDonald 已提交
402
	if (elapsed_time_len == 2) {
403
		const __be16 var16 = htons((u16)elapsed_time);
I
Ian McDonald 已提交
404 405
		memcpy(to, &var16, 2);
	} else {
406
		const __be32 var32 = htonl(elapsed_time);
I
Ian McDonald 已提交
407 408
		memcpy(to, &var32, 4);
	}
409

410
	return 0;
411 412
}

413
EXPORT_SYMBOL_GPL(dccp_insert_option_elapsed_time);
414

415
int dccp_insert_option_timestamp(struct sock *sk, struct sk_buff *skb)
416
{
417
	__be32 now = htonl(dccp_timestamp());
I
Ian McDonald 已提交
418 419 420
	/* yes this will overflow but that is the point as we want a
	 * 10 usec 32 bit timer which mean it wraps every 11.9 hours */

421
	return dccp_insert_option(sk, skb, DCCPO_TIMESTAMP, &now, sizeof(now));
422 423
}

424 425
EXPORT_SYMBOL_GPL(dccp_insert_option_timestamp);

426 427
static int dccp_insert_option_timestamp_echo(struct dccp_sock *dp,
					     struct dccp_request_sock *dreq,
428
					     struct sk_buff *skb)
429
{
430
	__be32 tstamp_echo;
431
	unsigned char *to;
432 433 434 435 436 437 438 439 440 441 442 443
	u32 elapsed_time, elapsed_time_len, len;

	if (dreq != NULL) {
		elapsed_time = dccp_timestamp() - dreq->dreq_timestamp_time;
		tstamp_echo  = htonl(dreq->dreq_timestamp_echo);
		dreq->dreq_timestamp_echo = 0;
	} else {
		elapsed_time = dccp_timestamp() - dp->dccps_timestamp_time;
		tstamp_echo  = htonl(dp->dccps_timestamp_echo);
		dp->dccps_timestamp_echo = 0;
	}

444 445 446
	elapsed_time_len = dccp_elapsed_time_len(elapsed_time);
	len = 6 + elapsed_time_len;

447 448
	if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
		return -1;
449 450 451 452 453 454 455 456 457

	DCCP_SKB_CB(skb)->dccpd_opt_len += len;

	to    = skb_push(skb, len);
	*to++ = DCCPO_TIMESTAMP_ECHO;
	*to++ = len;

	memcpy(to, &tstamp_echo, 4);
	to += 4;
458

I
Ian McDonald 已提交
459
	if (elapsed_time_len == 2) {
460
		const __be16 var16 = htons((u16)elapsed_time);
I
Ian McDonald 已提交
461 462
		memcpy(to, &var16, 2);
	} else if (elapsed_time_len == 4) {
463
		const __be32 var32 = htonl(elapsed_time);
I
Ian McDonald 已提交
464 465
		memcpy(to, &var32, 4);
	}
466

467
	return 0;
468 469
}

470 471 472 473 474 475 476 477 478 479 480 481 482 483 484
/**
 * dccp_insert_option_mandatory  -  Mandatory option (5.8.2)
 * Note that since we are using skb_push, this function needs to be called
 * _after_ inserting the option it is supposed to influence (stack order).
 */
int dccp_insert_option_mandatory(struct sk_buff *skb)
{
	if (DCCP_SKB_CB(skb)->dccpd_opt_len >= DCCP_MAX_OPT_LEN)
		return -1;

	DCCP_SKB_CB(skb)->dccpd_opt_len++;
	*skb_push(skb, 1) = DCCPO_MANDATORY;
	return 0;
}

485 486 487 488 489 490 491 492 493 494 495 496 497 498
/**
 * dccp_insert_fn_opt  -  Insert single Feature-Negotiation option into @skb
 * @type: %DCCPO_CHANGE_L, %DCCPO_CHANGE_R, %DCCPO_CONFIRM_L, %DCCPO_CONFIRM_R
 * @feat: one out of %dccp_feature_numbers
 * @val: NN value or SP array (preferred element first) to copy
 * @len: true length of @val in bytes (excluding first element repetition)
 * @repeat_first: whether to copy the first element of @val twice
 * The last argument is used to construct Confirm options, where the preferred
 * value and the preference list appear separately (RFC 4340, 6.3.1). Preference
 * lists are kept such that the preferred entry is always first, so we only need
 * to copy twice, and avoid the overhead of cloning into a bigger array.
 */
int dccp_insert_fn_opt(struct sk_buff *skb, u8 type, u8 feat,
		       u8 *val, u8 len, bool repeat_first)
499
{
500
	u8 tot_len, *to;
501

502 503 504
	/* take the `Feature' field and possible repetition into account */
	if (len > (DCCP_SINGLE_OPT_MAXLEN - 2)) {
		DCCP_WARN("length %u for feature %u too large\n", len, feat);
505
		return -1;
506
	}
507

508 509 510 511 512 513 514 515 516
	if (unlikely(val == NULL || len == 0))
		len = repeat_first = 0;
	tot_len = 3 + repeat_first + len;

	if (DCCP_SKB_CB(skb)->dccpd_opt_len + tot_len > DCCP_MAX_OPT_LEN) {
		DCCP_WARN("packet too small for feature %d option!\n", feat);
		return -1;
	}
	DCCP_SKB_CB(skb)->dccpd_opt_len += tot_len;
517

518
	to    = skb_push(skb, tot_len);
519
	*to++ = type;
520
	*to++ = tot_len;
521
	*to++ = feat;
522

523 524
	if (repeat_first)
		*to++ = *val;
525 526
	if (len)
		memcpy(to, val, len);
527

528 529 530
	dccp_pr_debug("%s(%s (%d), ...), length %d\n",
		      dccp_feat_typename(type),
		      dccp_feat_name(feat), feat, len);
531 532 533
	return 0;
}

534 535 536 537 538 539 540 541 542 543 544 545
/* The length of all options needs to be a multiple of 4 (5.8) */
static void dccp_insert_option_padding(struct sk_buff *skb)
{
	int padding = DCCP_SKB_CB(skb)->dccpd_opt_len % 4;

	if (padding != 0) {
		padding = 4 - padding;
		memset(skb_push(skb, padding), 0, padding);
		DCCP_SKB_CB(skb)->dccpd_opt_len += padding;
	}
}

546
int dccp_insert_options(struct sock *sk, struct sk_buff *skb)
547 548
{
	struct dccp_sock *dp = dccp_sk(sk);
549
	struct dccp_minisock *dmsk = dccp_msk(sk);
550 551 552

	DCCP_SKB_CB(skb)->dccpd_opt_len = 0;

553 554
	if (dmsk->dccpms_send_ndp_count &&
	    dccp_insert_option_ndp(sk, skb))
555
		return -1;
556

557 558 559 560
	if (DCCP_SKB_CB(skb)->dccpd_type != DCCP_PKT_DATA) {

		/* Feature Negotiation */
		if (dccp_feat_insert_opts(dp, NULL, skb))
561
			return -1;
562 563 564 565 566 567 568 569 570 571 572 573 574 575

		if (DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_REQUEST) {
			/*
			 * Obtain RTT sample from Request/Response exchange.
			 * This is currently used in CCID 3 initialisation.
			 */
			if (dccp_insert_option_timestamp(sk, skb))
				return -1;

		} else if (dmsk->dccpms_send_ack_vector	&&
			   dccp_ackvec_pending(dp->dccps_hc_rx_ackvec) &&
			   dccp_insert_option_ackvec(sk, skb)) {
				return -1;
		}
576 577
	}

578
	if (dp->dccps_hc_rx_insert_options) {
579 580
		if (ccid_hc_rx_insert_options(dp->dccps_hc_rx_ccid, sk, skb))
			return -1;
581 582
		dp->dccps_hc_rx_insert_options = 0;
	}
583

584 585 586 587
	if (dp->dccps_timestamp_echo != 0 &&
	    dccp_insert_option_timestamp_echo(dp, NULL, skb))
		return -1;

588 589 590
	dccp_insert_option_padding(skb);
	return 0;
}
591

592 593 594
int dccp_insert_options_rsk(struct dccp_request_sock *dreq, struct sk_buff *skb)
{
	DCCP_SKB_CB(skb)->dccpd_opt_len = 0;
595

596 597 598
	if (dccp_feat_insert_opts(NULL, dreq, skb))
		return -1;

599 600 601
	if (dreq->dreq_timestamp_echo != 0 &&
	    dccp_insert_option_timestamp_echo(NULL, dreq, skb))
		return -1;
602

603
	dccp_insert_option_padding(skb);
604
	return 0;
605
}