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