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