options.c 14.2 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 17 18 19
 *
 *      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>
#include <linux/kernel.h>
#include <linux/skbuff.h>

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

25 26 27 28 29 30
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_ack_ratio	      = DCCPF_INITIAL_ACK_RATIO;
int sysctl_dccp_feat_send_ack_vector = DCCPF_INITIAL_SEND_ACK_VECTOR;
int sysctl_dccp_feat_send_ndp_count  = DCCPF_INITIAL_SEND_NDP_COUNT;
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52

static u32 dccp_decode_value_var(const unsigned char *bf, const u8 len)
{
	u32 value = 0;

	if (len > 3)
		value += *bf++ << 24;
	if (len > 2)
		value += *bf++ << 16;
	if (len > 1)
		value += *bf++ << 8;
	if (len > 0)
		value += *bf;

	return value;
}

int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
{
	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;
53
	u64 ackno = DCCP_SKB_CB(skb)->dccpd_ack_seq;
54 55
	unsigned char *options = (unsigned char *)dh + dccp_hdr_len(skb);
	unsigned char *opt_ptr = options;
56 57
	const unsigned char *opt_end = (unsigned char *)dh +
					(dh->dccph_doff * 4);
58 59 60
	struct dccp_options_received *opt_recv = &dp->dccps_options_received;
	unsigned char opt, len;
	unsigned char *value;
61
	u32 elapsed_time;
62 63
	int rc;
	int mandatory = 0;
64 65 66

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

67
	opt = len = 0;
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
	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)
				goto out_invalid_option;

			len = *opt_ptr++;
			if (len < 3)
				goto out_invalid_option;
			/*
			 * Remove the type and len fields, leaving
			 * just the value size
			 */
			len	-= 2;
			value	= opt_ptr;
			opt_ptr += len;

			if (opt_ptr > opt_end)
				goto out_invalid_option;
		}

		switch (opt) {
		case DCCPO_PADDING:
			break;
96 97 98
		case DCCPO_MANDATORY:
			if (mandatory)
				goto out_invalid_option;
99 100
			if (pkt_type != DCCP_PKT_DATA)
				mandatory = 1;
101
			break;
102 103 104 105 106
		case DCCPO_NDP_COUNT:
			if (len > 3)
				goto out_invalid_option;

			opt_recv->dccpor_ndp = dccp_decode_value_var(value, len);
107
			dccp_pr_debug("%s rx opt: NDP count=%d\n", dccp_role(sk),
108
				      opt_recv->dccpor_ndp);
109
			break;
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
		case DCCPO_CHANGE_L:
			/* fall through */
		case DCCPO_CHANGE_R:
			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 (len < 2)
				goto out_invalid_option;
			if (dccp_feat_confirm_recv(sk, opt, *value,
						   value + 1, len - 1))
				goto out_invalid_option;
			break;
135
		case DCCPO_ACK_VECTOR_0:
136
		case DCCPO_ACK_VECTOR_1:
137
			if (pkt_type == DCCP_PKT_DATA)
138
				break;
139

140
			if (dccp_msk(sk)->dccpms_send_ack_vector &&
141
			    dccp_ackvec_parse(sk, skb, &ackno, opt, value, len))
142
				goto out_invalid_option;
143 144 145 146 147
			break;
		case DCCPO_TIMESTAMP:
			if (len != 4)
				goto out_invalid_option;

148
			opt_recv->dccpor_timestamp = ntohl(*(__be32 *)value);
149 150

			dp->dccps_timestamp_echo = opt_recv->dccpor_timestamp;
151
			dp->dccps_timestamp_time = ktime_get_real();
152

153 154
			dccp_pr_debug("%s rx opt: TIMESTAMP=%u, ackno=%llu\n",
				      dccp_role(sk), opt_recv->dccpor_timestamp,
155
				      (unsigned long long)
156 157 158
				      DCCP_SKB_CB(skb)->dccpd_ack_seq);
			break;
		case DCCPO_TIMESTAMP_ECHO:
I
Ian McDonald 已提交
159
			if (len != 4 && len != 6 && len != 8)
160 161
				goto out_invalid_option;

162
			opt_recv->dccpor_timestamp_echo = ntohl(*(__be32 *)value);
163

164
			dccp_pr_debug("%s rx opt: TIMESTAMP_ECHO=%u, len=%d, "
165
				      "ackno=%llu", dccp_role(sk),
166
				      opt_recv->dccpor_timestamp_echo,
167 168
				      len + 2,
				      (unsigned long long)
I
Ian McDonald 已提交
169 170 171
				      DCCP_SKB_CB(skb)->dccpd_ack_seq);


172 173
			if (len == 4) {
				dccp_pr_debug_cat("\n");
174
				break;
175
			}
176 177

			if (len == 6)
178
				elapsed_time = ntohs(*(__be16 *)(value + 4));
179
			else
180
				elapsed_time = ntohl(*(__be32 *)(value + 4));
181

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

184 185 186
			/* Give precedence to the biggest ELAPSED_TIME */
			if (elapsed_time > opt_recv->dccpor_elapsed_time)
				opt_recv->dccpor_elapsed_time = elapsed_time;
187 188
			break;
		case DCCPO_ELAPSED_TIME:
I
Ian McDonald 已提交
189
			if (len != 2 && len != 4)
190 191 192 193
				goto out_invalid_option;

			if (pkt_type == DCCP_PKT_DATA)
				continue;
I
Ian McDonald 已提交
194 195

			if (len == 2)
196
				elapsed_time = ntohs(*(__be16 *)value);
I
Ian McDonald 已提交
197
			else
198
				elapsed_time = ntohl(*(__be32 *)value);
199 200 201

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

203 204
			dccp_pr_debug("%s rx opt: ELAPSED_TIME=%d\n",
				      dccp_role(sk), elapsed_time);
205 206
			break;
			/*
207
			 * From RFC 4340, sec. 10.3:
208
			 *
209 210 211 212 213
			 *	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.
214 215 216 217
			 */
		case 128 ... 191: {
			const u16 idx = value - options;

218 219 220
			if (ccid_hc_rx_parse_options(dp->dccps_hc_rx_ccid, sk,
						     opt, len, idx,
						     value) != 0)
221 222 223 224 225 226
				goto out_invalid_option;
		}
			break;
		case 192 ... 255: {
			const u16 idx = value - options;

227 228 229
			if (ccid_hc_tx_parse_options(dp->dccps_hc_tx_ccid, sk,
						     opt, len, idx,
						     value) != 0)
230 231 232 233
				goto out_invalid_option;
		}
			break;
		default:
234 235
			DCCP_CRIT("DCCP(%p): option %d(len=%d) not "
				  "implemented, ignoring", sk, opt, len);
236
			break;
237
		}
238 239 240

		if (opt != DCCPO_MANDATORY)
			mandatory = 0;
241 242
	}

243 244 245 246
	/* mandatory was the last byte in option list -> reset connection */
	if (mandatory)
		goto out_invalid_option;

247 248 249 250 251
	return 0;

out_invalid_option:
	DCCP_INC_STATS_BH(DCCP_MIB_INVALIDOPT);
	DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_OPTION_ERROR;
252
	DCCP_WARN("DCCP(%p): invalid option %d, len=%d", sk, opt, len);
253 254 255
	return -1;
}

256 257
EXPORT_SYMBOL_GPL(dccp_parse_options);

258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
static void dccp_encode_value_var(const u32 value, unsigned char *to,
				  const unsigned int len)
{
	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);
}

static inline int dccp_ndp_len(const int ndp)
{
	return likely(ndp <= 0xFF) ? 1 : ndp <= 0xFFFF ? 2 : 3;
}

276
int dccp_insert_option(struct sock *sk, struct sk_buff *skb,
277 278 279 280 281
			const unsigned char option,
			const void *value, const unsigned char len)
{
	unsigned char *to;

282 283
	if (DCCP_SKB_CB(skb)->dccpd_opt_len + len + 2 > DCCP_MAX_OPT_LEN)
		return -1;
284 285 286 287 288 289 290 291

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

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

	memcpy(to, value, len);
292
	return 0;
293 294 295 296
}

EXPORT_SYMBOL_GPL(dccp_insert_option);

297
static int dccp_insert_option_ndp(struct sock *sk, struct sk_buff *skb)
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
{
	struct dccp_sock *dp = dccp_sk(sk);
	int ndp = dp->dccps_ndp_count;

	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)
313
			return -1;
314 315 316 317 318 319 320 321

		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);
	}
322 323

	return 0;
324 325 326 327
}

static inline int dccp_elapsed_time_len(const u32 elapsed_time)
{
328
	return elapsed_time == 0 ? 0 : elapsed_time <= 0xFFFF ? 2 : 4;
329 330
}

331 332
int dccp_insert_option_elapsed_time(struct sock *sk, struct sk_buff *skb,
				    u32 elapsed_time)
333 334 335 336 337
{
	const int elapsed_time_len = dccp_elapsed_time_len(elapsed_time);
	const int len = 2 + elapsed_time_len;
	unsigned char *to;

I
Ian McDonald 已提交
338
	if (elapsed_time_len == 0)
339
		return 0;
340

341 342
	if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
		return -1;
343 344 345 346 347 348 349

	DCCP_SKB_CB(skb)->dccpd_opt_len += len;

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

I
Ian McDonald 已提交
350
	if (elapsed_time_len == 2) {
351
		const __be16 var16 = htons((u16)elapsed_time);
I
Ian McDonald 已提交
352 353
		memcpy(to, &var16, 2);
	} else {
354
		const __be32 var32 = htonl(elapsed_time);
I
Ian McDonald 已提交
355 356
		memcpy(to, &var32, 4);
	}
357

358
	return 0;
359 360
}

361
EXPORT_SYMBOL_GPL(dccp_insert_option_elapsed_time);
362

363
int dccp_insert_option_timestamp(struct sock *sk, struct sk_buff *skb)
364
{
365
	__be32 now = htonl(dccp_timestamp());
I
Ian McDonald 已提交
366 367 368
	/* 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 */

369
	return dccp_insert_option(sk, skb, DCCPO_TIMESTAMP, &now, sizeof(now));
370 371
}

372 373
EXPORT_SYMBOL_GPL(dccp_insert_option_timestamp);

374 375
static int dccp_insert_option_timestamp_echo(struct sock *sk,
					     struct sk_buff *skb)
376 377
{
	struct dccp_sock *dp = dccp_sk(sk);
378
	__be32 tstamp_echo;
379
	int len, elapsed_time_len;
380
	unsigned char *to;
381 382 383
	const suseconds_t delta = ktime_us_delta(ktime_get_real(),
						 dp->dccps_timestamp_time);
	u32 elapsed_time = delta / 10;
384 385 386
	elapsed_time_len = dccp_elapsed_time_len(elapsed_time);
	len = 6 + elapsed_time_len;

387 388
	if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
		return -1;
389 390 391 392 393 394 395 396 397 398

	DCCP_SKB_CB(skb)->dccpd_opt_len += len;

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

	tstamp_echo = htonl(dp->dccps_timestamp_echo);
	memcpy(to, &tstamp_echo, 4);
	to += 4;
399

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

	dp->dccps_timestamp_echo = 0;
409
	dp->dccps_timestamp_time = ktime_set(0, 0);
410
	return 0;
411 412
}

413
static int dccp_insert_feat_opt(struct sk_buff *skb, u8 type, u8 feat,
414
				u8 *val, u8 len)
415 416 417 418
{
	u8 *to;

	if (DCCP_SKB_CB(skb)->dccpd_opt_len + len + 3 > DCCP_MAX_OPT_LEN) {
419
		DCCP_WARN("packet too small for feature %d option!\n", feat);
420 421 422 423 424 425 426 427 428 429 430 431 432
		return -1;
	}

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

	to    = skb_push(skb, len + 3);
	*to++ = type;
	*to++ = len + 3;
	*to++ = feat;

	if (len)
		memcpy(to, val, len);

433 434 435
	dccp_pr_debug("%s(%s (%d), ...), length %d\n",
		      dccp_feat_typename(type),
		      dccp_feat_name(feat), feat, len);
436 437 438
	return 0;
}

439
static int dccp_insert_options_feat(struct sock *sk, struct sk_buff *skb)
440 441
{
	struct dccp_sock *dp = dccp_sk(sk);
442
	struct dccp_minisock *dmsk = dccp_msk(sk);
443 444 445 446
	struct dccp_opt_pend *opt, *next;
	int change = 0;

	/* confirm any options [NN opts] */
447
	list_for_each_entry_safe(opt, next, &dmsk->dccpms_conf, dccpop_node) {
448 449 450 451 452 453 454 455
		dccp_insert_feat_opt(skb, opt->dccpop_type,
				     opt->dccpop_feat, opt->dccpop_val,
				     opt->dccpop_len);
		/* fear empty confirms */
		if (opt->dccpop_val)
			kfree(opt->dccpop_val);
		kfree(opt);
	}
456
	INIT_LIST_HEAD(&dmsk->dccpms_conf);
457 458

	/* see which features we need to send */
459
	list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) {
460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497
		/* see if we need to send any confirm */
		if (opt->dccpop_sc) {
			dccp_insert_feat_opt(skb, opt->dccpop_type + 1,
					     opt->dccpop_feat,
					     opt->dccpop_sc->dccpoc_val,
					     opt->dccpop_sc->dccpoc_len);

			BUG_ON(!opt->dccpop_sc->dccpoc_val);
			kfree(opt->dccpop_sc->dccpoc_val);
			kfree(opt->dccpop_sc);
			opt->dccpop_sc = NULL;
		}

		/* any option not confirmed, re-send it */
		if (!opt->dccpop_conf) {
			dccp_insert_feat_opt(skb, opt->dccpop_type,
					     opt->dccpop_feat, opt->dccpop_val,
					     opt->dccpop_len);
			change++;
		}
	}

	/* Retransmit timer.
	 * If this is the master listening sock, we don't set a timer on it.  It
	 * should be fine because if the dude doesn't receive our RESPONSE
	 * [which will contain the CHANGE] he will send another REQUEST which
	 * will "retrnasmit" the change.
	 */
	if (change && dp->dccps_role != DCCP_ROLE_LISTEN) {
		dccp_pr_debug("reset feat negotiation timer %p\n", sk);

		/* XXX don't reset the timer on re-transmissions.  I.e. reset it
		 * only when sending new stuff i guess.  Currently the timer
		 * never backs off because on re-transmission it just resets it!
		 */
		inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
					  inet_csk(sk)->icsk_rto, DCCP_RTO_MAX);
	}
498 499

	return 0;
500 501
}

502
int dccp_insert_options(struct sock *sk, struct sk_buff *skb)
503 504
{
	struct dccp_sock *dp = dccp_sk(sk);
505
	struct dccp_minisock *dmsk = dccp_msk(sk);
506 507 508

	DCCP_SKB_CB(skb)->dccpd_opt_len = 0;

509
	if (dmsk->dccpms_send_ndp_count &&
510 511
	    dccp_insert_option_ndp(sk, skb))
		return -1;
512 513

	if (!dccp_packet_without_ack(skb)) {
514
		if (dmsk->dccpms_send_ack_vector &&
515 516 517 518 519 520 521
		    dccp_ackvec_pending(dp->dccps_hc_rx_ackvec) &&
		    dccp_insert_option_ackvec(sk, skb))
			return -1;

		if (dp->dccps_timestamp_echo != 0 &&
		    dccp_insert_option_timestamp_echo(sk, skb))
			return -1;
522 523
	}

524
	if (dp->dccps_hc_rx_insert_options) {
525 526
		if (ccid_hc_rx_insert_options(dp->dccps_hc_rx_ccid, sk, skb))
			return -1;
527 528
		dp->dccps_hc_rx_insert_options = 0;
	}
529

530
	/* Feature negotiation */
531 532 533 534 535
	/* Data packets can't do feat negotiation */
	if (DCCP_SKB_CB(skb)->dccpd_type != DCCP_PKT_DATA &&
	    DCCP_SKB_CB(skb)->dccpd_type != DCCP_PKT_DATAACK &&
	    dccp_insert_options_feat(sk, skb))
		return -1;
536

537 538 539 540 541 542 543 544
	/*
	 * Obtain RTT sample from Request/Response exchange.
	 * This is currently used in CCID 3 initialisation.
	 */
	if (DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_REQUEST &&
	    dccp_insert_option_timestamp(sk, skb))
		return -1;

545 546 547 548 549 550 551 552 553 554 555 556
	/* XXX: insert other options when appropriate */

	if (DCCP_SKB_CB(skb)->dccpd_opt_len != 0) {
		/* The length of all options has to be a multiple of 4 */
		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;
		}
	}
557 558

	return 0;
559
}