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