cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

options.c (16738B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *  net/dccp/options.c
      4 *
      5 *  An implementation of the DCCP protocol
      6 *  Copyright (c) 2005 Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
      7 *  Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
      8 *  Copyright (c) 2005 Ian McDonald <ian.mcdonald@jandi.co.nz>
      9 */
     10#include <linux/dccp.h>
     11#include <linux/module.h>
     12#include <linux/types.h>
     13#include <asm/unaligned.h>
     14#include <linux/kernel.h>
     15#include <linux/skbuff.h>
     16
     17#include "ackvec.h"
     18#include "ccid.h"
     19#include "dccp.h"
     20#include "feat.h"
     21
     22u64 dccp_decode_value_var(const u8 *bf, const u8 len)
     23{
     24	u64 value = 0;
     25
     26	if (len >= DCCP_OPTVAL_MAXLEN)
     27		value += ((u64)*bf++) << 40;
     28	if (len > 4)
     29		value += ((u64)*bf++) << 32;
     30	if (len > 3)
     31		value += ((u64)*bf++) << 24;
     32	if (len > 2)
     33		value += ((u64)*bf++) << 16;
     34	if (len > 1)
     35		value += ((u64)*bf++) << 8;
     36	if (len > 0)
     37		value += *bf;
     38
     39	return value;
     40}
     41
     42/**
     43 * dccp_parse_options  -  Parse DCCP options present in @skb
     44 * @sk: client|server|listening dccp socket (when @dreq != NULL)
     45 * @dreq: request socket to use during connection setup, or NULL
     46 * @skb: frame to parse
     47 */
     48int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq,
     49		       struct sk_buff *skb)
     50{
     51	struct dccp_sock *dp = dccp_sk(sk);
     52	const struct dccp_hdr *dh = dccp_hdr(skb);
     53	const u8 pkt_type = DCCP_SKB_CB(skb)->dccpd_type;
     54	unsigned char *options = (unsigned char *)dh + dccp_hdr_len(skb);
     55	unsigned char *opt_ptr = options;
     56	const unsigned char *opt_end = (unsigned char *)dh +
     57					(dh->dccph_doff * 4);
     58	struct dccp_options_received *opt_recv = &dp->dccps_options_received;
     59	unsigned char opt, len;
     60	unsigned char *value;
     61	u32 elapsed_time;
     62	__be32 opt_val;
     63	int rc;
     64	int mandatory = 0;
     65
     66	memset(opt_recv, 0, sizeof(*opt_recv));
     67
     68	opt = len = 0;
     69	while (opt_ptr != opt_end) {
     70		opt   = *opt_ptr++;
     71		len   = 0;
     72		value = NULL;
     73
     74		/* Check if this isn't a single byte option */
     75		if (opt > DCCPO_MAX_RESERVED) {
     76			if (opt_ptr == opt_end)
     77				goto out_nonsensical_length;
     78
     79			len = *opt_ptr++;
     80			if (len < 2)
     81				goto out_nonsensical_length;
     82			/*
     83			 * Remove the type and len fields, leaving
     84			 * just the value size
     85			 */
     86			len	-= 2;
     87			value	= opt_ptr;
     88			opt_ptr += len;
     89
     90			if (opt_ptr > opt_end)
     91				goto out_nonsensical_length;
     92		}
     93
     94		/*
     95		 * CCID-specific options are ignored during connection setup, as
     96		 * negotiation may still be in progress (see RFC 4340, 10.3).
     97		 * The same applies to Ack Vectors, as these depend on the CCID.
     98		 */
     99		if (dreq != NULL && (opt >= DCCPO_MIN_RX_CCID_SPECIFIC ||
    100		    opt == DCCPO_ACK_VECTOR_0 || opt == DCCPO_ACK_VECTOR_1))
    101			goto ignore_option;
    102
    103		switch (opt) {
    104		case DCCPO_PADDING:
    105			break;
    106		case DCCPO_MANDATORY:
    107			if (mandatory)
    108				goto out_invalid_option;
    109			if (pkt_type != DCCP_PKT_DATA)
    110				mandatory = 1;
    111			break;
    112		case DCCPO_NDP_COUNT:
    113			if (len > 6)
    114				goto out_invalid_option;
    115
    116			opt_recv->dccpor_ndp = dccp_decode_value_var(value, len);
    117			dccp_pr_debug("%s opt: NDP count=%llu\n", dccp_role(sk),
    118				      (unsigned long long)opt_recv->dccpor_ndp);
    119			break;
    120		case DCCPO_CHANGE_L ... DCCPO_CONFIRM_R:
    121			if (pkt_type == DCCP_PKT_DATA)      /* RFC 4340, 6 */
    122				break;
    123			if (len == 0)
    124				goto out_invalid_option;
    125			rc = dccp_feat_parse_options(sk, dreq, mandatory, opt,
    126						    *value, value + 1, len - 1);
    127			if (rc)
    128				goto out_featneg_failed;
    129			break;
    130		case DCCPO_TIMESTAMP:
    131			if (len != 4)
    132				goto out_invalid_option;
    133			/*
    134			 * RFC 4340 13.1: "The precise time corresponding to
    135			 * Timestamp Value zero is not specified". We use
    136			 * zero to indicate absence of a meaningful timestamp.
    137			 */
    138			opt_val = get_unaligned((__be32 *)value);
    139			if (unlikely(opt_val == 0)) {
    140				DCCP_WARN("Timestamp with zero value\n");
    141				break;
    142			}
    143
    144			if (dreq != NULL) {
    145				dreq->dreq_timestamp_echo = ntohl(opt_val);
    146				dreq->dreq_timestamp_time = dccp_timestamp();
    147			} else {
    148				opt_recv->dccpor_timestamp =
    149					dp->dccps_timestamp_echo = ntohl(opt_val);
    150				dp->dccps_timestamp_time = dccp_timestamp();
    151			}
    152			dccp_pr_debug("%s rx opt: TIMESTAMP=%u, ackno=%llu\n",
    153				      dccp_role(sk), ntohl(opt_val),
    154				      (unsigned long long)
    155				      DCCP_SKB_CB(skb)->dccpd_ack_seq);
    156			/* schedule an Ack in case this sender is quiescent */
    157			inet_csk_schedule_ack(sk);
    158			break;
    159		case DCCPO_TIMESTAMP_ECHO:
    160			if (len != 4 && len != 6 && len != 8)
    161				goto out_invalid_option;
    162
    163			opt_val = get_unaligned((__be32 *)value);
    164			opt_recv->dccpor_timestamp_echo = ntohl(opt_val);
    165
    166			dccp_pr_debug("%s rx opt: TIMESTAMP_ECHO=%u, len=%d, "
    167				      "ackno=%llu", dccp_role(sk),
    168				      opt_recv->dccpor_timestamp_echo,
    169				      len + 2,
    170				      (unsigned long long)
    171				      DCCP_SKB_CB(skb)->dccpd_ack_seq);
    172
    173			value += 4;
    174
    175			if (len == 4) {		/* no elapsed time included */
    176				dccp_pr_debug_cat("\n");
    177				break;
    178			}
    179
    180			if (len == 6) {		/* 2-byte elapsed time */
    181				__be16 opt_val2 = get_unaligned((__be16 *)value);
    182				elapsed_time = ntohs(opt_val2);
    183			} else {		/* 4-byte elapsed time */
    184				opt_val = get_unaligned((__be32 *)value);
    185				elapsed_time = ntohl(opt_val);
    186			}
    187
    188			dccp_pr_debug_cat(", ELAPSED_TIME=%u\n", elapsed_time);
    189
    190			/* Give precedence to the biggest ELAPSED_TIME */
    191			if (elapsed_time > opt_recv->dccpor_elapsed_time)
    192				opt_recv->dccpor_elapsed_time = elapsed_time;
    193			break;
    194		case DCCPO_ELAPSED_TIME:
    195			if (dccp_packet_without_ack(skb))   /* RFC 4340, 13.2 */
    196				break;
    197
    198			if (len == 2) {
    199				__be16 opt_val2 = get_unaligned((__be16 *)value);
    200				elapsed_time = ntohs(opt_val2);
    201			} else if (len == 4) {
    202				opt_val = get_unaligned((__be32 *)value);
    203				elapsed_time = ntohl(opt_val);
    204			} else {
    205				goto out_invalid_option;
    206			}
    207
    208			if (elapsed_time > opt_recv->dccpor_elapsed_time)
    209				opt_recv->dccpor_elapsed_time = elapsed_time;
    210
    211			dccp_pr_debug("%s rx opt: ELAPSED_TIME=%d\n",
    212				      dccp_role(sk), elapsed_time);
    213			break;
    214		case DCCPO_MIN_RX_CCID_SPECIFIC ... DCCPO_MAX_RX_CCID_SPECIFIC:
    215			if (ccid_hc_rx_parse_options(dp->dccps_hc_rx_ccid, sk,
    216						     pkt_type, opt, value, len))
    217				goto out_invalid_option;
    218			break;
    219		case DCCPO_ACK_VECTOR_0:
    220		case DCCPO_ACK_VECTOR_1:
    221			if (dccp_packet_without_ack(skb))   /* RFC 4340, 11.4 */
    222				break;
    223			/*
    224			 * Ack vectors are processed by the TX CCID if it is
    225			 * interested. The RX CCID need not parse Ack Vectors,
    226			 * since it is only interested in clearing old state.
    227			 */
    228			fallthrough;
    229		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						     pkt_type, opt, value, len))
    232				goto out_invalid_option;
    233			break;
    234		default:
    235			DCCP_CRIT("DCCP(%p): option %d(len=%d) not "
    236				  "implemented, ignoring", sk, opt, len);
    237			break;
    238		}
    239ignore_option:
    240		if (opt != DCCPO_MANDATORY)
    241			mandatory = 0;
    242	}
    243
    244	/* mandatory was the last byte in option list -> reset connection */
    245	if (mandatory)
    246		goto out_invalid_option;
    247
    248out_nonsensical_length:
    249	/* RFC 4340, 5.8: ignore option and all remaining option space */
    250	return 0;
    251
    252out_invalid_option:
    253	DCCP_INC_STATS(DCCP_MIB_INVALIDOPT);
    254	rc = DCCP_RESET_CODE_OPTION_ERROR;
    255out_featneg_failed:
    256	DCCP_WARN("DCCP(%p): Option %d (len=%d) error=%u\n", sk, opt, len, rc);
    257	DCCP_SKB_CB(skb)->dccpd_reset_code = rc;
    258	DCCP_SKB_CB(skb)->dccpd_reset_data[0] = opt;
    259	DCCP_SKB_CB(skb)->dccpd_reset_data[1] = len > 0 ? value[0] : 0;
    260	DCCP_SKB_CB(skb)->dccpd_reset_data[2] = len > 1 ? value[1] : 0;
    261	return -1;
    262}
    263
    264EXPORT_SYMBOL_GPL(dccp_parse_options);
    265
    266void dccp_encode_value_var(const u64 value, u8 *to, const u8 len)
    267{
    268	if (len >= DCCP_OPTVAL_MAXLEN)
    269		*to++ = (value & 0xFF0000000000ull) >> 40;
    270	if (len > 4)
    271		*to++ = (value & 0xFF00000000ull) >> 32;
    272	if (len > 3)
    273		*to++ = (value & 0xFF000000) >> 24;
    274	if (len > 2)
    275		*to++ = (value & 0xFF0000) >> 16;
    276	if (len > 1)
    277		*to++ = (value & 0xFF00) >> 8;
    278	if (len > 0)
    279		*to++ = (value & 0xFF);
    280}
    281
    282static inline u8 dccp_ndp_len(const u64 ndp)
    283{
    284	if (likely(ndp <= 0xFF))
    285		return 1;
    286	return likely(ndp <= USHRT_MAX) ? 2 : (ndp <= UINT_MAX ? 4 : 6);
    287}
    288
    289int dccp_insert_option(struct sk_buff *skb, const unsigned char option,
    290		       const void *value, const unsigned char len)
    291{
    292	unsigned char *to;
    293
    294	if (DCCP_SKB_CB(skb)->dccpd_opt_len + len + 2 > DCCP_MAX_OPT_LEN)
    295		return -1;
    296
    297	DCCP_SKB_CB(skb)->dccpd_opt_len += len + 2;
    298
    299	to    = skb_push(skb, len + 2);
    300	*to++ = option;
    301	*to++ = len + 2;
    302
    303	memcpy(to, value, len);
    304	return 0;
    305}
    306
    307EXPORT_SYMBOL_GPL(dccp_insert_option);
    308
    309static int dccp_insert_option_ndp(struct sock *sk, struct sk_buff *skb)
    310{
    311	struct dccp_sock *dp = dccp_sk(sk);
    312	u64 ndp = dp->dccps_ndp_count;
    313
    314	if (dccp_non_data_packet(skb))
    315		++dp->dccps_ndp_count;
    316	else
    317		dp->dccps_ndp_count = 0;
    318
    319	if (ndp > 0) {
    320		unsigned char *ptr;
    321		const int ndp_len = dccp_ndp_len(ndp);
    322		const int len = ndp_len + 2;
    323
    324		if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
    325			return -1;
    326
    327		DCCP_SKB_CB(skb)->dccpd_opt_len += len;
    328
    329		ptr = skb_push(skb, len);
    330		*ptr++ = DCCPO_NDP_COUNT;
    331		*ptr++ = len;
    332		dccp_encode_value_var(ndp, ptr, ndp_len);
    333	}
    334
    335	return 0;
    336}
    337
    338static inline int dccp_elapsed_time_len(const u32 elapsed_time)
    339{
    340	return elapsed_time == 0 ? 0 : elapsed_time <= 0xFFFF ? 2 : 4;
    341}
    342
    343static int dccp_insert_option_timestamp(struct sk_buff *skb)
    344{
    345	__be32 now = htonl(dccp_timestamp());
    346	/* yes this will overflow but that is the point as we want a
    347	 * 10 usec 32 bit timer which mean it wraps every 11.9 hours */
    348
    349	return dccp_insert_option(skb, DCCPO_TIMESTAMP, &now, sizeof(now));
    350}
    351
    352static int dccp_insert_option_timestamp_echo(struct dccp_sock *dp,
    353					     struct dccp_request_sock *dreq,
    354					     struct sk_buff *skb)
    355{
    356	__be32 tstamp_echo;
    357	unsigned char *to;
    358	u32 elapsed_time, elapsed_time_len, len;
    359
    360	if (dreq != NULL) {
    361		elapsed_time = dccp_timestamp() - dreq->dreq_timestamp_time;
    362		tstamp_echo  = htonl(dreq->dreq_timestamp_echo);
    363		dreq->dreq_timestamp_echo = 0;
    364	} else {
    365		elapsed_time = dccp_timestamp() - dp->dccps_timestamp_time;
    366		tstamp_echo  = htonl(dp->dccps_timestamp_echo);
    367		dp->dccps_timestamp_echo = 0;
    368	}
    369
    370	elapsed_time_len = dccp_elapsed_time_len(elapsed_time);
    371	len = 6 + elapsed_time_len;
    372
    373	if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
    374		return -1;
    375
    376	DCCP_SKB_CB(skb)->dccpd_opt_len += len;
    377
    378	to    = skb_push(skb, len);
    379	*to++ = DCCPO_TIMESTAMP_ECHO;
    380	*to++ = len;
    381
    382	memcpy(to, &tstamp_echo, 4);
    383	to += 4;
    384
    385	if (elapsed_time_len == 2) {
    386		const __be16 var16 = htons((u16)elapsed_time);
    387		memcpy(to, &var16, 2);
    388	} else if (elapsed_time_len == 4) {
    389		const __be32 var32 = htonl(elapsed_time);
    390		memcpy(to, &var32, 4);
    391	}
    392
    393	return 0;
    394}
    395
    396static int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
    397{
    398	struct dccp_sock *dp = dccp_sk(sk);
    399	struct dccp_ackvec *av = dp->dccps_hc_rx_ackvec;
    400	struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
    401	const u16 buflen = dccp_ackvec_buflen(av);
    402	/* Figure out how many options do we need to represent the ackvec */
    403	const u8 nr_opts = DIV_ROUND_UP(buflen, DCCP_SINGLE_OPT_MAXLEN);
    404	u16 len = buflen + 2 * nr_opts;
    405	u8 i, nonce = 0;
    406	const unsigned char *tail, *from;
    407	unsigned char *to;
    408
    409	if (dcb->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) {
    410		DCCP_WARN("Lacking space for %u bytes on %s packet\n", len,
    411			  dccp_packet_name(dcb->dccpd_type));
    412		return -1;
    413	}
    414	/*
    415	 * Since Ack Vectors are variable-length, we can not always predict
    416	 * their size. To catch exception cases where the space is running out
    417	 * on the skb, a separate Sync is scheduled to carry the Ack Vector.
    418	 */
    419	if (len > DCCPAV_MIN_OPTLEN &&
    420	    len + dcb->dccpd_opt_len + skb->len > dp->dccps_mss_cache) {
    421		DCCP_WARN("No space left for Ack Vector (%u) on skb (%u+%u), "
    422			  "MPS=%u ==> reduce payload size?\n", len, skb->len,
    423			  dcb->dccpd_opt_len, dp->dccps_mss_cache);
    424		dp->dccps_sync_scheduled = 1;
    425		return 0;
    426	}
    427	dcb->dccpd_opt_len += len;
    428
    429	to   = skb_push(skb, len);
    430	len  = buflen;
    431	from = av->av_buf + av->av_buf_head;
    432	tail = av->av_buf + DCCPAV_MAX_ACKVEC_LEN;
    433
    434	for (i = 0; i < nr_opts; ++i) {
    435		int copylen = len;
    436
    437		if (len > DCCP_SINGLE_OPT_MAXLEN)
    438			copylen = DCCP_SINGLE_OPT_MAXLEN;
    439
    440		/*
    441		 * RFC 4340, 12.2: Encode the Nonce Echo for this Ack Vector via
    442		 * its type; ack_nonce is the sum of all individual buf_nonce's.
    443		 */
    444		nonce ^= av->av_buf_nonce[i];
    445
    446		*to++ = DCCPO_ACK_VECTOR_0 + av->av_buf_nonce[i];
    447		*to++ = copylen + 2;
    448
    449		/* Check if buf_head wraps */
    450		if (from + copylen > tail) {
    451			const u16 tailsize = tail - from;
    452
    453			memcpy(to, from, tailsize);
    454			to	+= tailsize;
    455			len	-= tailsize;
    456			copylen	-= tailsize;
    457			from	= av->av_buf;
    458		}
    459
    460		memcpy(to, from, copylen);
    461		from += copylen;
    462		to   += copylen;
    463		len  -= copylen;
    464	}
    465	/*
    466	 * Each sent Ack Vector is recorded in the list, as per A.2 of RFC 4340.
    467	 */
    468	if (dccp_ackvec_update_records(av, dcb->dccpd_seq, nonce))
    469		return -ENOBUFS;
    470	return 0;
    471}
    472
    473/**
    474 * dccp_insert_option_mandatory  -  Mandatory option (5.8.2)
    475 * @skb: frame into which to insert option
    476 *
    477 * Note that since we are using skb_push, this function needs to be called
    478 * _after_ inserting the option it is supposed to influence (stack order).
    479 */
    480int dccp_insert_option_mandatory(struct sk_buff *skb)
    481{
    482	if (DCCP_SKB_CB(skb)->dccpd_opt_len >= DCCP_MAX_OPT_LEN)
    483		return -1;
    484
    485	DCCP_SKB_CB(skb)->dccpd_opt_len++;
    486	*(u8 *)skb_push(skb, 1) = DCCPO_MANDATORY;
    487	return 0;
    488}
    489
    490/**
    491 * dccp_insert_fn_opt  -  Insert single Feature-Negotiation option into @skb
    492 * @skb: frame to insert feature negotiation option into
    493 * @type: %DCCPO_CHANGE_L, %DCCPO_CHANGE_R, %DCCPO_CONFIRM_L, %DCCPO_CONFIRM_R
    494 * @feat: one out of %dccp_feature_numbers
    495 * @val: NN value or SP array (preferred element first) to copy
    496 * @len: true length of @val in bytes (excluding first element repetition)
    497 * @repeat_first: whether to copy the first element of @val twice
    498 *
    499 * The last argument is used to construct Confirm options, where the preferred
    500 * value and the preference list appear separately (RFC 4340, 6.3.1). Preference
    501 * lists are kept such that the preferred entry is always first, so we only need
    502 * to copy twice, and avoid the overhead of cloning into a bigger array.
    503 */
    504int dccp_insert_fn_opt(struct sk_buff *skb, u8 type, u8 feat,
    505		       u8 *val, u8 len, bool repeat_first)
    506{
    507	u8 tot_len, *to;
    508
    509	/* take the `Feature' field and possible repetition into account */
    510	if (len > (DCCP_SINGLE_OPT_MAXLEN - 2)) {
    511		DCCP_WARN("length %u for feature %u too large\n", len, feat);
    512		return -1;
    513	}
    514
    515	if (unlikely(val == NULL || len == 0))
    516		len = repeat_first = false;
    517	tot_len = 3 + repeat_first + len;
    518
    519	if (DCCP_SKB_CB(skb)->dccpd_opt_len + tot_len > DCCP_MAX_OPT_LEN) {
    520		DCCP_WARN("packet too small for feature %d option!\n", feat);
    521		return -1;
    522	}
    523	DCCP_SKB_CB(skb)->dccpd_opt_len += tot_len;
    524
    525	to    = skb_push(skb, tot_len);
    526	*to++ = type;
    527	*to++ = tot_len;
    528	*to++ = feat;
    529
    530	if (repeat_first)
    531		*to++ = *val;
    532	if (len)
    533		memcpy(to, val, len);
    534	return 0;
    535}
    536
    537/* The length of all options needs to be a multiple of 4 (5.8) */
    538static void dccp_insert_option_padding(struct sk_buff *skb)
    539{
    540	int padding = DCCP_SKB_CB(skb)->dccpd_opt_len % 4;
    541
    542	if (padding != 0) {
    543		padding = 4 - padding;
    544		memset(skb_push(skb, padding), 0, padding);
    545		DCCP_SKB_CB(skb)->dccpd_opt_len += padding;
    546	}
    547}
    548
    549int dccp_insert_options(struct sock *sk, struct sk_buff *skb)
    550{
    551	struct dccp_sock *dp = dccp_sk(sk);
    552
    553	DCCP_SKB_CB(skb)->dccpd_opt_len = 0;
    554
    555	if (dp->dccps_send_ndp_count && dccp_insert_option_ndp(sk, skb))
    556		return -1;
    557
    558	if (DCCP_SKB_CB(skb)->dccpd_type != DCCP_PKT_DATA) {
    559
    560		/* Feature Negotiation */
    561		if (dccp_feat_insert_opts(dp, NULL, skb))
    562			return -1;
    563
    564		if (DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_REQUEST) {
    565			/*
    566			 * Obtain RTT sample from Request/Response exchange.
    567			 * This is currently used for TFRC initialisation.
    568			 */
    569			if (dccp_insert_option_timestamp(skb))
    570				return -1;
    571
    572		} else if (dccp_ackvec_pending(sk) &&
    573			   dccp_insert_option_ackvec(sk, skb)) {
    574				return -1;
    575		}
    576	}
    577
    578	if (dp->dccps_hc_rx_insert_options) {
    579		if (ccid_hc_rx_insert_options(dp->dccps_hc_rx_ccid, sk, skb))
    580			return -1;
    581		dp->dccps_hc_rx_insert_options = 0;
    582	}
    583
    584	if (dp->dccps_timestamp_echo != 0 &&
    585	    dccp_insert_option_timestamp_echo(dp, NULL, skb))
    586		return -1;
    587
    588	dccp_insert_option_padding(skb);
    589	return 0;
    590}
    591
    592int dccp_insert_options_rsk(struct dccp_request_sock *dreq, struct sk_buff *skb)
    593{
    594	DCCP_SKB_CB(skb)->dccpd_opt_len = 0;
    595
    596	if (dccp_feat_insert_opts(NULL, dreq, skb))
    597		return -1;
    598
    599	/* Obtain RTT sample from Response/Ack exchange (used by TFRC). */
    600	if (dccp_insert_option_timestamp(skb))
    601		return -1;
    602
    603	if (dreq->dreq_timestamp_echo != 0 &&
    604	    dccp_insert_option_timestamp_echo(NULL, dreq, skb))
    605		return -1;
    606
    607	dccp_insert_option_padding(skb);
    608	return 0;
    609}