blob: bb43eab686d2007d795fa8077136ae4d153399a4 [file] [log] [blame]
Philipp22611be2016-08-10 12:08:03 +02001/* GPRS SNDCP XID field encoding/decoding as per 3GPP TS 44.065 */
2
3/* (C) 2016 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
4 * All Rights Reserved
5 *
6 * Author: Philipp Maier
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Affero General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Affero General Public License for more details.
17 *
18 * You should have received a copy of the GNU Affero General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include <stdio.h>
23#include <string.h>
24#include <stdint.h>
25#include <math.h>
26#include <errno.h>
27
28#include <osmocom/core/utils.h>
29#include <osmocom/core/msgb.h>
30#include <osmocom/core/linuxlist.h>
31#include <osmocom/core/talloc.h>
32#include <osmocom/gsm/tlv.h>
33
34#include <openbsc/debug.h>
35#include <openbsc/gprs_llc.h>
36#include <openbsc/sgsn.h>
37#include <openbsc/gprs_sndcp_xid.h>
38
39/* When the propose bit in an SNDCP-XID compression field is set to zero,
40 * the algorithm identifier is stripped. The algoritm parameters are specific
41 * for each algorithms. The following struct is used to pass the information
42 * about the referenced algorithm to the parser. */
43struct entity_algo_table {
44 unsigned int entity; /* see also: 6.5.1.1.3 and 6.6.1.1.3 */
45 unsigned int algo; /* see also: 6.5.1.1.4 and 6.6.1.1.4 */
46 unsigned int compclass; /* Can be either SNDCP_XID_DATA_COMPRESSION or
47 SNDCP_XID_PROTOCOL_COMPRESSION */
48};
49
50/* FUNCTIONS RELATED TO SNDCP-XID ENCODING */
51
52/* Encode applicable sapis (works the same in all three compression schemes) */
53static int encode_pcomp_applicable_sapis(uint8_t *dst,
54 const uint8_t *nsapis,
55 uint8_t nsapis_len)
56{
57 /* NOTE: Buffer *dst needs offer at 2 bytes
58 * of space to store the generation results */
59
60 uint16_t blob;
61 uint8_t nsapi;
62 int i;
63
64 /* Bail if number of possible nsapis exceeds valid range
65 * (Only 11 nsapis possible for PDP-Contexts) */
66 OSMO_ASSERT(nsapis_len <= 11);
67
68 /* Encode applicable SAPIs */
69 blob = 0;
70 for (i = 0; i < nsapis_len; i++) {
71 nsapi = nsapis[i];
72 /* Only NSAPI 5 to 15 are applicable for user traffic (PDP-
73 * contexts). Only for these NSAPIs SNDCP-XID parameters
74 * can apply. See also 3GPP TS 44.065, 5.1 Service primitives */
75 OSMO_ASSERT(nsapi >= 5 && nsapi <= 15);
76 blob |= (1 << nsapi);
77 }
78
79 /* Store result */
80 *dst = (blob >> 8) & 0xFF;
81 dst++;
82 *dst = blob & 0xFF;
83
84 return 2;
85}
86
87/* Encode rfc1144 parameter field
88 * (see also: 3GPP TS 44.065, 6.5.2.1, Table 5) */
89static int encode_pcomp_rfc1144_params(uint8_t *dst, unsigned int dst_maxlen,
90 const struct
91 gprs_sndcp_pcomp_rfc1144_params *params)
92{
93 /* NOTE: Buffer *dst should offer at least 3 bytes
94 * of space to store the generation results */
95
96 int dst_counter = 0;
97 int rc;
98
99 OSMO_ASSERT(dst_maxlen >= 3);
100
101 /* Zero out buffer */
102 memset(dst, 0, dst_maxlen);
103
104 /* Encode applicable SAPIs */
105 rc = encode_pcomp_applicable_sapis(dst, params->nsapi,
106 params->nsapi_len);
107 dst += rc;
108 dst_counter += rc;
109
110 /* Encode s01 (see also: 3GPP TS 44.065, 6.5.2.1, Table 5) */
111 OSMO_ASSERT(params->s01 >= 0);
112 OSMO_ASSERT(params->s01 <= 255);
113 *dst = params->s01;
114 dst++;
115 dst_counter++;
116
117 /* Return generated length */
118 return dst_counter;
119}
120
121/*
122 * Encode rfc2507 parameter field
123 * (see also: 3GPP TS 44.065, 6.5.3.1, Table 6)
124 */
125static int encode_pcomp_rfc2507_params(uint8_t *dst, unsigned int dst_maxlen,
126 const struct
127 gprs_sndcp_pcomp_rfc2507_params *params)
128{
129 /* NOTE: Buffer *dst should offer at least 3 bytes
130 * of space to store the generation results */
131
132 int dst_counter = 0;
133 int rc;
134
135 OSMO_ASSERT(dst_maxlen >= 9);
136
137 /* Zero out buffer */
138 memset(dst, 0, dst_maxlen);
139
140 /* Encode applicable SAPIs */
141 rc = encode_pcomp_applicable_sapis(dst, params->nsapi,
142 params->nsapi_len);
143 dst += rc;
144 dst_counter += rc;
145
146 /* Encode F_MAX_PERIOD (see also: 3GPP TS 44.065, 6.5.3.1, Table 6) */
147 OSMO_ASSERT(params->f_max_period >= 1);
148 OSMO_ASSERT(params->f_max_period <= 65535);
149 *dst = (params->f_max_period >> 8) & 0xFF;
150 dst++;
151 dst_counter++;
152 *dst = (params->f_max_period) & 0xFF;
153 dst++;
154 dst_counter++;
155
156 /* Encode F_MAX_TIME (see also: 3GPP TS 44.065, 6.5.3.1, Table 6) */
157 OSMO_ASSERT(params->f_max_time >= 1);
158 OSMO_ASSERT(params->f_max_time <= 255);
159 *dst = params->f_max_time;
160 dst++;
161 dst_counter++;
162
163 /* Encode MAX_HEADER (see also: 3GPP TS 44.065, 6.5.3.1, Table 6) */
164 OSMO_ASSERT(params->max_header >= 60);
165 OSMO_ASSERT(params->max_header <= 255);
166 *dst = params->max_header;
167 dst++;
168 dst_counter++;
169
170 /* Encode TCP_SPACE (see also: 3GPP TS 44.065, 6.5.3.1, Table 6) */
171 OSMO_ASSERT(params->tcp_space >= 3);
172 OSMO_ASSERT(params->tcp_space <= 255);
173 *dst = params->tcp_space;
174 dst++;
175 dst_counter++;
176
177 /* Encode NON_TCP_SPACE (see also: 3GPP TS 44.065, 6.5.3.1, Table 6) */
178 OSMO_ASSERT(params->non_tcp_space >= 3);
179 OSMO_ASSERT(params->non_tcp_space <= 65535);
180 *dst = (params->non_tcp_space >> 8) & 0xFF;
181 dst++;
182 dst_counter++;
183 *dst = (params->non_tcp_space) & 0xFF;
184 dst++;
185 dst_counter++;
186
187 /* Return generated length */
188 return dst_counter;
189}
190
191/* Encode ROHC parameter field
192 * (see also: 3GPP TS 44.065, 6.5.4.1, Table 10) */
193static int encode_pcomp_rohc_params(uint8_t *dst, unsigned int dst_maxlen,
194 const struct gprs_sndcp_pcomp_rohc_params
195 *params)
196{
197 /* NOTE: Buffer *dst should offer at least 36
198 * (2 * 16 Profiles + 2 * 3 Parameter) bytes
199 * of memory space to store generation results */
200
201 int i;
202 int dst_counter = 0;
203 int rc;
204
205 OSMO_ASSERT(dst_maxlen >= 38);
206
207 /* Bail if number of ROHC profiles exceeds limit
208 * (ROHC supports only a maximum of 16 different profiles) */
Philipp22611be2016-08-10 12:08:03 +0200209 OSMO_ASSERT(params->profile_len <= 16);
210
211 /* Zero out buffer */
212 memset(dst, 0, dst_maxlen);
213
214 /* Encode applicable SAPIs */
215 rc = encode_pcomp_applicable_sapis(dst, params->nsapi,
216 params->nsapi_len);
217 dst += rc;
218 dst_counter += rc;
219
220 /* Encode MAX_CID (see also: 3GPP TS 44.065, 6.5.4.1, Table 10) */
221 OSMO_ASSERT(params->max_cid >= 0);
222 OSMO_ASSERT(params->max_cid <= 16383);
223 *dst = (params->max_cid >> 8) & 0xFF;
224 dst++;
225 *dst = params->max_cid & 0xFF;
226 dst++;
227 dst_counter += 2;
228
229 /* Encode MAX_HEADER (see also: 3GPP TS 44.065, 6.5.4.1, Table 10) */
230 OSMO_ASSERT(params->max_header >= 60);
231 OSMO_ASSERT(params->max_header <= 255);
232 *dst = (params->max_header >> 8) & 0xFF;
233 dst++;
234 *dst = params->max_header & 0xFF;
235 dst++;
236 dst_counter += 2;
237
238 /* Encode ROHC Profiles (see also: 3GPP TS 44.065, 6.5.4.1, Table 10) */
239 for (i = 0; i < params->profile_len; i++) {
240 *dst = (params->profile[i] >> 8) & 0xFF;
241 dst++;
242 *dst = params->profile[i] & 0xFF;
243 dst++;
244 dst_counter += 2;
245 }
246
247 /* Return generated length */
248 return dst_counter;
249}
250
251/* Encode V.42bis parameter field
252 * (see also: 3GPP TS 44.065, 6.6.2.1, Table 7a) */
253static int encode_dcomp_v42bis_params(uint8_t *dst, unsigned int dst_maxlen,
254 const struct
255 gprs_sndcp_dcomp_v42bis_params *params)
256{
257 /* NOTE: Buffer *dst should offer at least 6 bytes
258 * of space to store the generation results */
259
260 int dst_counter = 0;
261 int rc;
262
263 OSMO_ASSERT(dst_maxlen >= 6);
264
265 /* Zero out buffer */
266 memset(dst, 0, dst_maxlen);
267
268 /* Encode applicable SAPIs */
269 rc = encode_pcomp_applicable_sapis(dst, params->nsapi,
270 params->nsapi_len);
271 dst += rc;
272 dst_counter += rc;
273
274 /* Encode P0 (see also: 3GPP TS 44.065, 6.6.2.1, Table 7a) */
275 OSMO_ASSERT(params->p0 >= 0);
276 OSMO_ASSERT(params->p0 <= 3);
277 *dst = params->p0 & 0x03;
278 dst++;
279 dst_counter++;
280
281 /* Encode P1 (see also: 3GPP TS 44.065, 6.6.2.1, Table 7a) */
282 OSMO_ASSERT(params->p1 >= 512);
283 OSMO_ASSERT(params->p1 <= 65535);
284 *dst = (params->p1 >> 8) & 0xFF;
285 dst++;
286 *dst = params->p1 & 0xFF;
287 dst++;
288 dst_counter += 2;
289
290 /* Encode P2 (see also: 3GPP TS 44.065, 6.6.2.1, Table 7a) */
291 OSMO_ASSERT(params->p2 >= 6);
292 OSMO_ASSERT(params->p2 <= 250);
293 *dst = params->p2;
294 dst++;
295 dst_counter++;
296
297 /* Return generated length */
298 return dst_counter;
299}
300
301/* Encode V44 parameter field
302 * (see also: 3GPP TS 44.065, 6.6.3.1, Table 7c) */
303static int encode_dcomp_v44_params(uint8_t *dst, unsigned int dst_maxlen,
304 const struct gprs_sndcp_dcomp_v44_params
305 *params)
306{
307 /* NOTE: Buffer *dst should offer at least 12 bytes
308 * of space to store the generation results */
309
310 int dst_counter = 0;
311 int rc;
312
313 OSMO_ASSERT(dst_maxlen >= 12);
314
315 /* Zero out buffer */
316 memset(dst, 0, dst_maxlen);
317
318 /* Encode applicable SAPIs */
319 rc = encode_pcomp_applicable_sapis(dst, params->nsapi,
320 params->nsapi_len);
321 dst += rc;
322 dst_counter += rc;
323
324 /* Encode C0 (see also: 3GPP TS 44.065, 6.6.3.1, Table 7c) */
325 OSMO_ASSERT(params->c0 == 0x80 || params->c0 == 0xC0);
326 *dst = params->c0 & 0xC0;
327 dst++;
328 dst_counter++;
329
330 /* Encode P0 (see also: 3GPP TS 44.065, 6.6.3.1, Table 7c) */
331 OSMO_ASSERT(params->p0 >= 0);
332 OSMO_ASSERT(params->p0 <= 3);
333 *dst = params->p0 & 0x03;
334 dst++;
335 dst_counter++;
336
337 /* Encode P1T (see also: 3GPP TS 44.065, 6.6.3.1, Table 7c) */
338 OSMO_ASSERT(params->p1t >= 256);
339 OSMO_ASSERT(params->p1t <= 65535);
340 *dst = (params->p1t >> 8) & 0xFF;
341 dst++;
342 *dst = params->p1t & 0xFF;
343 dst++;
344 dst_counter += 2;
345
346 /* Encode P1R (see also: 3GPP TS 44.065, 6.6.3.1, Table 7c) */
347 OSMO_ASSERT(params->p1r >= 256);
348 OSMO_ASSERT(params->p1r <= 65535);
349 *dst = (params->p1r >> 8) & 0xFF;
350 dst++;
351 *dst = params->p1r & 0xFF;
352 dst++;
353 dst_counter += 2;
354
355 /* Encode P3T (see also: 3GPP TS 44.065, 6.6.3.1, Table 7c) */
356 OSMO_ASSERT(params->p3t >= 0);
357 OSMO_ASSERT(params->p3t <= 65535);
358 OSMO_ASSERT(params->p3t >= 2 * params->p1t);
359 *dst = (params->p3t >> 8) & 0xFF;
360 dst++;
361 *dst = params->p3t & 0xFF;
362 dst++;
363 dst_counter += 2;
364
365 /* Encode P3R (see also: 3GPP TS 44.065, 6.6.3.1, Table 7c) */
366 OSMO_ASSERT(params->p3r >= 0);
367 OSMO_ASSERT(params->p3r <= 65535);
368 OSMO_ASSERT(params->p3r >= 2 * params->p1r);
369 *dst = (params->p3r >> 8) & 0xFF;
370 dst++;
371 *dst = params->p3r & 0xFF;
372 dst++;
373 dst_counter += 2;
374
375 /* Return generated length */
376 return dst_counter;
377}
378
379/* Encode data or protocol control information compression field
380 * (see also: 3GPP TS 44.065, 6.6.1.1, Figure 9 and
381 * 3GPP TS 44.065, 6.5.1.1, Figure 7) */
382static int encode_comp_field(uint8_t *dst, unsigned int dst_maxlen,
383 const struct gprs_sndcp_comp_field *comp_field)
384{
385 int dst_counter = 0;
386 int len;
387 int expected_length;
388 int i;
389
390 uint8_t payload_bytes[256];
391 int payload_bytes_len = -1;
392
393 /* If possible, try do encode payload bytes first */
394 if (comp_field->rfc1144_params) {
395 payload_bytes_len =
396 encode_pcomp_rfc1144_params(payload_bytes,
397 sizeof(payload_bytes),
398 comp_field->rfc1144_params);
399 } else if (comp_field->rfc2507_params) {
400 payload_bytes_len =
401 encode_pcomp_rfc2507_params(payload_bytes,
402 sizeof(payload_bytes),
403 comp_field->rfc2507_params);
404 } else if (comp_field->rohc_params) {
405 payload_bytes_len =
406 encode_pcomp_rohc_params(payload_bytes,
407 sizeof(payload_bytes),
408 comp_field->rohc_params);
409 } else if (comp_field->v42bis_params) {
410 payload_bytes_len =
411 encode_dcomp_v42bis_params(payload_bytes,
412 sizeof(payload_bytes),
413 comp_field->v42bis_params);
414 } else if (comp_field->v44_params) {
415 payload_bytes_len =
416 encode_dcomp_v44_params(payload_bytes,
417 sizeof(payload_bytes),
418 comp_field->v44_params);
419 } else
420 OSMO_ASSERT(false);
421
422 /* Bail immediately if payload byte generation failed */
423 OSMO_ASSERT(payload_bytes_len >= 0);
424
425 /* Bail if comp_len is out of bounds */
426 OSMO_ASSERT(comp_field->comp_len <= sizeof(comp_field->comp));
427
428 /* Calculate length field of the data block */
429 if (comp_field->p) {
430 len =
431 payload_bytes_len +
432 ceil((double)(comp_field->comp_len) / 2.0);
433 expected_length = len + 3;
434 } else {
435 len = payload_bytes_len;
436 expected_length = len + 2;
437 }
438
439 /* Bail immediately if no sufficient memory space is supplied */
440 OSMO_ASSERT(dst_maxlen >= expected_length);
441
442 /* Check if the entity number is within bounds */
443 OSMO_ASSERT(comp_field->entity <= 0x1f);
444
445 /* Check if the algorithm number is within bounds */
446 OSMO_ASSERT(comp_field->algo >= 0 || comp_field->algo <= 0x1f);
447
448 /* Zero out buffer */
449 memset(dst, 0, dst_maxlen);
450
451 /* Encode Propose bit */
452 if (comp_field->p)
453 *dst |= (1 << 7);
454
455 /* Encode entity number */
456 *dst |= comp_field->entity & 0x1F;
457 dst++;
458 dst_counter++;
459
460 /* Encode algorithm number */
461 if (comp_field->p) {
462 *dst |= comp_field->algo & 0x1F;
463 dst++;
464 dst_counter++;
465 }
466
467 /* Encode length field */
468 *dst |= len & 0xFF;
469 dst++;
470 dst_counter++;
471
472 /* Encode PCOMP/DCOMP values */
473 if (comp_field->p) {
474 for (i = 0; i < comp_field->comp_len; i++) {
475 /* Check if submitted PCOMP/DCOMP
476 values are within bounds */
Philippae9beda2016-09-28 15:10:14 +0200477 if (comp_field->comp[i] > 0x0F)
Philipp22611be2016-08-10 12:08:03 +0200478 return -EINVAL;
479
480 if (i & 1) {
481 *dst |= comp_field->comp[i] & 0x0F;
482 dst++;
483 dst_counter++;
484 } else
485 *dst |= (comp_field->comp[i] << 4) & 0xF0;
486 }
487
488 if (i & 1) {
489 dst++;
490 dst_counter++;
491 }
492 }
493
494 /* Append payload bytes */
495 memcpy(dst, payload_bytes, payload_bytes_len);
496 dst_counter += payload_bytes_len;
497
498 /* Return generated length */
499 return dst_counter;
500}
501
502/* Find out to which compression class the specified comp-field belongs
503 * (header compression or data compression?) */
504int gprs_sndcp_get_compression_class(const struct gprs_sndcp_comp_field
505 *comp_field)
506{
507 OSMO_ASSERT(comp_field);
508
509 if (comp_field->rfc1144_params)
510 return SNDCP_XID_PROTOCOL_COMPRESSION;
511 else if (comp_field->rfc2507_params)
512 return SNDCP_XID_PROTOCOL_COMPRESSION;
513 else if (comp_field->rohc_params)
514 return SNDCP_XID_PROTOCOL_COMPRESSION;
515 else if (comp_field->v42bis_params)
516 return SNDCP_XID_DATA_COMPRESSION;
517 else if (comp_field->v44_params)
518 return SNDCP_XID_DATA_COMPRESSION;
519 else
520 return -EINVAL;
521}
522
523/* Convert all compression fields to bytstreams */
524static int gprs_sndcp_pack_fields(const struct llist_head *comp_fields,
525 uint8_t *dst,
526 unsigned int dst_maxlen, int class)
527{
528 struct gprs_sndcp_comp_field *comp_field;
529 int byte_counter = 0;
530 int rc;
531
532 llist_for_each_entry_reverse(comp_field, comp_fields, list) {
533 if (class == gprs_sndcp_get_compression_class(comp_field)) {
534 rc = encode_comp_field(dst + byte_counter,
535 dst_maxlen - byte_counter,
536 comp_field);
537
538 /* When input data is correct, there is
539 * no reason for the encoder to fail! */
540 OSMO_ASSERT(rc >= 0);
541
542 byte_counter += rc;
543 }
544 }
545
546 /* Return generated length */
547 return byte_counter;
548}
549
550/* Transform a list with compression fields into an SNDCP-XID message (dst) */
551int gprs_sndcp_compile_xid(uint8_t *dst, unsigned int dst_maxlen,
552 const struct llist_head *comp_fields)
553{
554 int rc;
555 int byte_counter = 0;
556 uint8_t comp_bytes[512];
557 uint8_t xid_version_number[1] = { CURRENT_SNDCP_VERSION };
558
559 OSMO_ASSERT(comp_fields);
560 OSMO_ASSERT(dst);
561 OSMO_ASSERT(dst_maxlen >= 2 + sizeof(xid_version_number));
562
563 /* Bail if there is no input */
564 if (llist_empty(comp_fields))
565 return -EINVAL;
566
567 /* Prepend header */
568 dst =
569 tlv_put(dst, SNDCP_XID_VERSION_NUMBER,
570 sizeof(xid_version_number), xid_version_number);
571 byte_counter += (sizeof(xid_version_number) + 2);
572
573 /* Add data compression fields */
574 rc = gprs_sndcp_pack_fields(comp_fields, comp_bytes,
575 sizeof(comp_bytes),
576 SNDCP_XID_DATA_COMPRESSION);
577 OSMO_ASSERT(rc >= 0);
578
579 if (rc > 0) {
580 dst = tlv_put(dst, SNDCP_XID_DATA_COMPRESSION, rc, comp_bytes);
581 byte_counter += rc + 2;
582 }
583
584 /* Add header compression fields */
585 rc = gprs_sndcp_pack_fields(comp_fields, comp_bytes,
586 sizeof(comp_bytes),
587 SNDCP_XID_PROTOCOL_COMPRESSION);
588 OSMO_ASSERT(rc >= 0);
589
590 if (rc > 0) {
591 dst = tlv_put(dst, SNDCP_XID_PROTOCOL_COMPRESSION, rc,
592 comp_bytes);
593 byte_counter += rc + 2;
594 }
595
596 /* Return generated length */
597 return byte_counter;
598}
599
600/* FUNCTIONS RELATED TO SNDCP-XID DECODING */
601
602/* Decode applicable sapis (works the same in all three compression schemes) */
603static int decode_pcomp_applicable_sapis(uint8_t *nsapis,
604 uint8_t *nsapis_len,
605 const uint8_t *src,
606 unsigned int src_len)
607{
608 uint16_t blob;
609 int i;
610 int nsapi_len = 0;
611
612 /* Exit immediately if no result can be stored */
613 if (!nsapis)
614 return -EINVAL;
615
616 /* Exit immediately if not enough input data is available */
617 if (src_len < 2)
618 return -EINVAL;
619
620 /* Read bitmask */
621 blob = *src;
622 blob = (blob << 8) & 0xFF00;
623 src++;
624 blob |= (*src) & 0xFF;
625 blob = (blob >> 5);
626
627 /* Decode applicable SAPIs */
628 for (i = 0; i < 15; i++) {
629 if ((blob >> i) & 1) {
630 nsapis[nsapi_len] = i + 5;
631 nsapi_len++;
632 }
633 }
634
635 /* Return consumed length */
636 *nsapis_len = nsapi_len;
637 return 2;
638}
639
640/* Decode 16 bit field */
641static int decode_pcomp_16_bit_field(int *value_int, uint16_t * value_uint16,
642 const uint8_t *src,
643 unsigned int src_len,
644 int value_min, int value_max)
645{
646 uint16_t blob;
647
648 /* Reset values to zero (just to be sure) */
649 if (value_int)
650 *value_int = -1;
651 if (value_uint16)
652 *value_uint16 = 0;
653
654 /* Exit if not enough src are available */
655 if (src_len < 2)
656 return -EINVAL;
657
658 /* Decode bit value */
659 blob = *src;
660 blob = (blob << 8) & 0xFF00;
661 src++;
662 blob |= *src;
663
664 /* Check if parsed value is within bounds */
665 if (blob < value_min)
666 return -EINVAL;
667 if (blob > value_max)
668 return -EINVAL;
669
670 /* Hand back results to the caller */
671 if (value_int)
672 *value_int = blob;
673 if (value_uint16)
674 *value_uint16 = blob;
675
676 /* Return consumed length */
677 return 2;
678}
679
680/* Decode 8 bit field */
681static int decode_pcomp_8_bit_field(int *value_int, uint8_t *value_uint8,
682 const uint8_t *src,
683 unsigned int src_len,
684 int value_min, int value_max)
685{
686 uint8_t blob;
687
688 /* Reset values to invalid (just to be sure) */
689 if (value_int)
690 *value_int = -1;
691 if (value_uint8)
692 *value_uint8 = 0;
693
694 /* Exit if not enough src are available */
695 if (src_len < 1)
696 return -EINVAL;
697
698 /* Decode bit value */
699 blob = *src;
700
701 /* Check if parsed value is within bounds */
702 if (blob < value_min)
703 return -EINVAL;
704 if (blob > value_max)
705 return -EINVAL;
706
707 /* Hand back results to the caller */
708 if (value_int)
709 *value_int = blob;
710 if (value_uint8)
711 *value_uint8 = blob;
712
713 /* Return consumed length */
714 return 1;
715}
716
717/* Decode rfc1144 parameter field see also: 3GPP TS 44.065, 6.5.2.1, Table 5) */
718static int decode_pcomp_rfc1144_params(struct gprs_sndcp_pcomp_rfc1144_params
719 *params, const uint8_t *src,
720 unsigned int src_len)
721{
722 int rc;
723 int byte_counter = 0;
724
725 /* Mark all optional parameters invalid by default */
726 params->s01 = -1;
727
728 /* Decode applicable SAPIs */
729 rc = decode_pcomp_applicable_sapis(params->nsapi, &params->nsapi_len,
730 src, src_len);
731 if (rc > 0) {
732 byte_counter += rc;
733 src += rc;
734 } else
735 return byte_counter;
736
737 /* Decode parameter S0 -1
738 * (see also: 3GPP TS 44.065, 6.5.2.1, Table 5) */
739 rc = decode_pcomp_8_bit_field(&params->s01, NULL, src,
740 src_len - byte_counter, 0, 255);
741 if (rc <= 0)
742 return byte_counter;
743 byte_counter += rc;
744 src += rc;
745
746 /* Return consumed length */
747 return byte_counter;
748}
749
750/* Decode rfc2507 parameter field
751 * (see also: 3GPP TS 44.065, 6.5.3.1, Table 6) */
752static int decode_pcomp_rfc2507_params(struct gprs_sndcp_pcomp_rfc2507_params
753 *params, const uint8_t *src,
754 unsigned int src_len)
755{
756 int rc;
757 int byte_counter = 0;
758
759 /* Mark all optional parameters invalid by default */
760 params->f_max_period = -1;
761 params->f_max_time = -1;
762 params->max_header = -1;
763 params->tcp_space = -1;
764 params->non_tcp_space = -1;
765
766 /* Decode applicable SAPIs */
767 rc = decode_pcomp_applicable_sapis(params->nsapi, &params->nsapi_len,
768 src, src_len);
769 if (rc > 0) {
770 byte_counter += rc;
771 src += rc;
772 } else
773 return byte_counter;
774
775 /* Decode F_MAX_PERIOD (see also: 3GPP TS 44.065, 6.5.3.1, Table 6) */
776 rc = decode_pcomp_16_bit_field(&params->f_max_period, NULL, src,
777 src_len - byte_counter, 1, 65535);
778 if (rc <= 0)
779 return byte_counter;
780 byte_counter += rc;
781 src += rc;
782
783 /* Decode F_MAX_TIME (see also: 3GPP TS 44.065, 6.5.3.1, Table 6) */
784 rc = decode_pcomp_8_bit_field(&params->f_max_time, NULL, src,
785 src_len - byte_counter, 1, 255);
786 if (rc <= 0)
787 return byte_counter;
788 byte_counter += rc;
789 src += rc;
790
791 /* Decode MAX_HEADER (see also: 3GPP TS 44.065, 6.5.3.1, Table 6) */
792 rc = decode_pcomp_8_bit_field(&params->max_header, NULL, src,
793 src_len - byte_counter, 60, 255);
794 if (rc <= 0)
795 return byte_counter;
796 byte_counter += rc;
797 src += rc;
798
799 /* Decode TCP_SPACE (see also: 3GPP TS 44.065, 6.5.3.1, Table 6) */
800 rc = decode_pcomp_8_bit_field(&params->tcp_space, NULL, src,
801 src_len - byte_counter, 3, 255);
802 if (rc <= 0)
803 return byte_counter;
804 byte_counter += rc;
805 src += rc;
806
807 /* Decode NON_TCP_SPACE (see also: 3GPP TS 44.065, 6.5.3.1, Table 6) */
808 rc = decode_pcomp_16_bit_field(&params->non_tcp_space, NULL, src,
809 src_len - byte_counter, 3, 65535);
810 if (rc <= 0)
811 return byte_counter;
812 byte_counter += rc;
813 src += rc;
814
815 /* Return consumed length */
816 return byte_counter;
817}
818
819/* Decode ROHC parameter field (see also: 3GPP TS 44.065, 6.5.4.1, Table 10) */
820static int decode_pcomp_rohc_params(struct gprs_sndcp_pcomp_rohc_params *params,
821 const uint8_t *src, unsigned int src_len)
822{
823 int rc;
824 int byte_counter = 0;
825 int i;
826
827 /* Mark all optional parameters invalid by default */
828 params->max_cid = -1;
829 params->max_header = -1;
830
831 /* Decode applicable SAPIs */
832 rc = decode_pcomp_applicable_sapis(params->nsapi, &params->nsapi_len,
833 src, src_len);
834 if (rc <= 0)
835 return byte_counter;
836 byte_counter += rc;
837 src += rc;
838
839 /* Decode MAX_CID (see also: 3GPP TS 44.065, 6.5.4.1, Table 10) */
840 rc = decode_pcomp_16_bit_field(&params->max_cid, NULL, src,
841 src_len - byte_counter, 0, 16383);
842 if (rc <= 0)
843 return byte_counter;
844 byte_counter += rc;
845 src += rc;
846
847 /* Decode MAX_HEADER (see also: 3GPP TS 44.065, 6.5.4.1, Table 10) */
848 rc = decode_pcomp_16_bit_field(&params->max_header, NULL, src,
849 src_len - byte_counter, 60, 255);
850 if (rc <= 0)
851 return byte_counter;
852 byte_counter += rc;
853 src += rc;
854
855 /* Decode Profiles (see also: 3GPP TS 44.065, 6.5.4.1, Table 10) */
856 for (i = 0; i < 16; i++) {
857 params->profile_len = 0;
858 rc = decode_pcomp_16_bit_field(NULL, &params->profile[i], src,
859 src_len - byte_counter, 0,
860 65535);
861 if (rc <= 0)
862 return byte_counter;
863 byte_counter += rc;
864 src += rc;
865 params->profile_len = i + 1;
866 }
867
868 /* Return consumed length */
869 return byte_counter;
870}
871
872/* Decode V.42bis parameter field
873 * (see also: 3GPP TS 44.065, 6.6.2.1, Table 7a) */
874static int decode_dcomp_v42bis_params(struct gprs_sndcp_dcomp_v42bis_params
875 *params, const uint8_t *src,
876 unsigned int src_len)
877{
878 int rc;
879 int byte_counter = 0;
880
881 /* Mark all optional parameters invalid by default */
882 params->p0 = -1;
883 params->p1 = -1;
884 params->p2 = -1;
885
886 /* Decode applicable SAPIs */
887 rc = decode_pcomp_applicable_sapis(params->nsapi, &params->nsapi_len,
888 src, src_len);
889 if (rc > 0) {
890 byte_counter += rc;
891 src += rc;
892 } else
893 return byte_counter;
894
895 /* Decode P0 (see also: 3GPP TS 44.065, 6.6.2.1, Table 7a) */
896 rc = decode_pcomp_8_bit_field(&params->p0, NULL, src,
897 src_len - byte_counter, 0, 3);
898 if (rc <= 0)
899 return byte_counter;
900 byte_counter += rc;
901 src += rc;
902
903 /* Decode P1 (see also: 3GPP TS 44.065, 6.6.2.1, Table 7a) */
904 rc = decode_pcomp_16_bit_field(&params->p1, NULL, src,
905 src_len - byte_counter, 512, 65535);
906 if (rc <= 0)
907 return byte_counter;
908 byte_counter += rc;
909 src += rc;
910
911 /* Decode P2 (see also: 3GPP TS 44.065, 6.6.2.1, Table 7a) */
912 rc = decode_pcomp_8_bit_field(&params->p2, NULL, src,
913 src_len - byte_counter, 6, 250);
914 if (rc <= 0)
915 return byte_counter;
916 byte_counter += rc;
917 src += rc;
918
919 /* Return consumed length */
920 return byte_counter;
921}
922
923/* Decode V44 parameter field (see also: 3GPP TS 44.065, 6.6.3.1, Table 7c) */
924static int decode_dcomp_v44_params(struct gprs_sndcp_dcomp_v44_params *params,
925 const uint8_t *src, unsigned int src_len)
926{
927 int rc;
928 int byte_counter = 0;
929
930 /* Mark all optional parameters invalid by default */
931 params->c0 = -1;
932 params->p0 = -1;
933 params->p1t = -1;
934 params->p1r = -1;
935 params->p3t = -1;
936 params->p3r = -1;
937
938 /* Decode applicable SAPIs */
939 rc = decode_pcomp_applicable_sapis(params->nsapi, &params->nsapi_len,
940 src, src_len);
941 if (rc > 0) {
942 byte_counter += rc;
943 src += rc;
944 } else
945 return byte_counter;
946
947 /* Decode C0 (see also: 3GPP TS 44.065, 6.6.3.1, Table 7c) */
948 rc = decode_pcomp_8_bit_field(&params->c0, NULL, src,
949 src_len - byte_counter, 0, 255);
950 if (rc <= 0)
951 return byte_counter;
952 if ((params->c0 != 0x80) && (params->c0 != 0xC0))
953 return -EINVAL;
954 byte_counter += rc;
955 src += rc;
956
957 /* Decode P0 (see also: 3GPP TS 44.065, 6.6.3.1, Table 7c) */
958 rc = decode_pcomp_8_bit_field(&params->p0, NULL, src,
959 src_len - byte_counter, 0, 3);
960 if (rc <= 0)
961 return byte_counter;
962 byte_counter += rc;
963 src += rc;
964
965 /* Decode P1T (see also: 3GPP TS 44.065, 6.6.3.1, Table 7c) */
966 rc = decode_pcomp_16_bit_field(&params->p1t, NULL, src,
967 src_len - byte_counter, 265, 65535);
968 if (rc <= 0)
969 return byte_counter;
970 byte_counter += rc;
971 src += rc;
972
973 /* Decode P1R (see also: 3GPP TS 44.065, 6.6.3.1, Table 7c) */
974 rc = decode_pcomp_16_bit_field(&params->p1r, NULL, src,
975 src_len - byte_counter, 265, 65535);
976 if (rc <= 0)
977 return byte_counter;
978 byte_counter += rc;
979 src += rc;
980
981 /* Decode P3T (see also: 3GPP TS 44.065, 6.6.3.1, Table 7c) */
982 rc = decode_pcomp_16_bit_field(&params->p3t, NULL, src,
983 src_len - byte_counter, 265, 65535);
984 if (rc <= 0)
985 return byte_counter;
986 if (params->p3t < 2 * params->p1t)
987 return -EINVAL;
988 byte_counter += rc;
989 src += rc;
990
991 /* Decode P3R (see also: 3GPP TS 44.065, 6.6.3.1, Table 7c) */
992 rc = decode_pcomp_16_bit_field(&params->p3r, NULL, src,
993 src_len - byte_counter, 265, 65535);
994 if (rc <= 0)
995 return byte_counter;
996 if (params->p3r < 2 * params->p1r)
997 return -EINVAL;
998 byte_counter += rc;
999 src += rc;
1000
1001 /* Return consumed length */
1002 return byte_counter;
1003}
1004
1005/* Lookup algorithm identfier by entity ID */
1006static int lookup_algorithm_identifier(int entity, const struct
1007 entity_algo_table
1008 *lt, unsigned int lt_len, int compclass)
1009{
1010 int i;
1011
1012 if (!lt)
1013 return -1;
1014
1015 for (i = 0; i < lt_len; i++) {
1016 if ((lt[i].entity == entity)
1017 && (lt[i].compclass == compclass))
1018 return lt[i].algo;
1019 }
1020
1021 return -1;
1022}
1023
1024/* Helper function for decode_comp_field(), decodes
1025 * numeric pcomp/dcomp values */
1026static int decode_comp_values(struct gprs_sndcp_comp_field *comp_field,
1027 const uint8_t *src, int compclass)
1028{
1029 int src_counter = 0;
1030 int i;
1031
1032 if (comp_field->p) {
1033 /* Determine the number of expected PCOMP/DCOMP values */
1034 if (compclass == SNDCP_XID_PROTOCOL_COMPRESSION) {
1035 /* For protocol compression */
1036 switch (comp_field->algo) {
1037 case RFC_1144:
1038 comp_field->comp_len = RFC1144_PCOMP_NUM;
1039 break;
1040 case RFC_2507:
1041 comp_field->comp_len = RFC2507_PCOMP_NUM;
1042 break;
1043 case ROHC:
1044 comp_field->comp_len = ROHC_PCOMP_NUM;
1045 break;
1046
1047 /* Exit if the algorithem type encodes
1048 something unknown / unspecified */
1049 default:
1050 return -EINVAL;
1051 }
1052 } else {
1053 /* For data compression */
1054 switch (comp_field->algo) {
1055 case V42BIS:
1056 comp_field->comp_len = V42BIS_DCOMP_NUM;
1057 break;
1058 case V44:
1059 comp_field->comp_len = V44_DCOMP_NUM;
1060 break;
1061
1062 /* Exit if the algorithem type encodes
1063 something unknown / unspecified */
1064 default:
1065 return -EINVAL;
1066 }
1067 }
1068
1069 for (i = 0; i < comp_field->comp_len; i++) {
1070 if (i & 1) {
1071 comp_field->comp[i] = (*src) & 0x0F;
1072 src++;
1073 src_counter++;
1074 } else
1075 comp_field->comp[i] = ((*src) >> 4) & 0x0F;
1076 }
1077
1078 if (i & 1) {
1079 src++;
1080 src_counter++;
1081 }
1082 }
1083
1084 return src_counter;
1085}
1086
1087/* Helper function for decode_comp_field(), decodes the parameters
1088 * which are protocol compression specific */
1089static int decode_pcomp_params(struct gprs_sndcp_comp_field *comp_field,
1090 const uint8_t *src, int src_len)
1091{
1092 int rc;
1093
1094 switch (comp_field->algo) {
1095 case RFC_1144:
1096 comp_field->rfc1144_params = talloc_zero(comp_field, struct
1097 gprs_sndcp_pcomp_rfc1144_params);
1098 rc = decode_pcomp_rfc1144_params(comp_field->rfc1144_params,
1099 src, src_len);
1100 if (rc < 0)
1101 talloc_free(comp_field->rfc1144_params);
1102 break;
1103 case RFC_2507:
1104 comp_field->rfc2507_params = talloc_zero(comp_field, struct
1105 gprs_sndcp_pcomp_rfc2507_params);
1106 rc = decode_pcomp_rfc2507_params(comp_field->rfc2507_params,
1107 src, src_len);
1108 if (rc < 0)
1109 talloc_free(comp_field->rfc1144_params);
1110 break;
1111 case ROHC:
1112 comp_field->rohc_params = talloc_zero(comp_field, struct
1113 gprs_sndcp_pcomp_rohc_params);
1114 rc = decode_pcomp_rohc_params(comp_field->rohc_params, src,
1115 src_len);
1116 if (rc < 0)
1117 talloc_free(comp_field->rohc_params);
1118 break;
1119
1120 /* If no suitable decoder is detected,
1121 leave the remaining bytes undecoded */
1122 default:
1123 rc = src_len;
1124 }
1125
1126 if (rc < 0) {
1127 comp_field->rfc1144_params = NULL;
1128 comp_field->rfc2507_params = NULL;
1129 comp_field->rohc_params = NULL;
1130 }
1131
1132 return rc;
1133}
1134
1135/* Helper function for decode_comp_field(), decodes the parameters
1136 * which are data compression specific */
1137static int decode_dcomp_params(struct gprs_sndcp_comp_field *comp_field,
1138 const uint8_t *src, int src_len)
1139{
1140 int rc;
1141
1142 switch (comp_field->algo) {
1143 case V42BIS:
1144 comp_field->v42bis_params = talloc_zero(comp_field, struct
1145 gprs_sndcp_dcomp_v42bis_params);
1146 rc = decode_dcomp_v42bis_params(comp_field->v42bis_params, src,
1147 src_len);
1148 if (rc < 0)
1149 talloc_free(comp_field->v42bis_params);
1150 break;
1151 case V44:
1152 comp_field->v44_params = talloc_zero(comp_field, struct
1153 gprs_sndcp_dcomp_v44_params);
1154 rc = decode_dcomp_v44_params(comp_field->v44_params, src,
1155 src_len);
1156 if (rc < 0)
1157 talloc_free(comp_field->v44_params);
1158 break;
1159
1160 /* If no suitable decoder is detected,
1161 * leave the remaining bytes undecoded */
1162 default:
1163 rc = src_len;
1164 }
1165
1166 if (rc < 0) {
1167 comp_field->v42bis_params = NULL;
1168 comp_field->v44_params = NULL;
1169 }
1170
1171 return rc;
1172}
1173
1174/* Decode data or protocol control information compression field
1175 * (see also: 3GPP TS 44.065, 6.6.1.1, Figure 9 and
1176 * 3GPP TS 44.065, 6.5.1.1, Figure 7) */
1177static int decode_comp_field(struct gprs_sndcp_comp_field *comp_field,
1178 const uint8_t *src, unsigned int src_len,
1179 const struct entity_algo_table *lt,
1180 unsigned int lt_len, int compclass)
1181{
1182 int src_counter = 0;
1183 unsigned int len;
1184 int rc;
1185
1186 OSMO_ASSERT(comp_field);
1187
1188 /* Exit immediately if it is clear that no
1189 parseable data is present */
1190 if (src_len < 1 || !src)
1191 return -EINVAL;
1192
1193 /* Zero out target struct */
1194 memset(comp_field, 0, sizeof(struct gprs_sndcp_comp_field));
1195
1196 /* Decode Propose bit and Entity number */
1197 if ((*src) & 0x80)
1198 comp_field->p = 1;
1199 comp_field->entity = (*src) & 0x1F;
1200 src_counter++;
1201 src++;
1202
1203 /* Decode algorithm number (if present) */
1204 if (comp_field->p) {
1205 comp_field->algo = (*src) & 0x1F;
1206 src_counter++;
1207 src++;
1208 }
1209 /* Alternatively take the information from the lookup table */
1210 else
1211 comp_field->algo =
1212 lookup_algorithm_identifier(comp_field->entity, lt,
1213 lt_len, compclass);
1214
1215 /* Decode length field */
1216 len = *src;
1217 src_counter++;
1218 src++;
1219
1220 /* Decode PCOMP/DCOMP values */
1221 rc = decode_comp_values(comp_field, src, compclass);
1222 if (rc < 0)
1223 return -EINVAL;
1224 src_counter += rc;
1225 src += rc;
1226 len -= rc;
1227
1228 /* Decode algorithm specific payload data */
1229 if (compclass == SNDCP_XID_PROTOCOL_COMPRESSION)
1230 rc = decode_pcomp_params(comp_field, src, len);
1231 else if (compclass == SNDCP_XID_DATA_COMPRESSION)
1232 rc = decode_dcomp_params(comp_field, src, len);
1233 else
1234 return -EINVAL;
1235
1236 if (rc >= 0)
1237 src_counter += rc;
1238 else
1239 return -EINVAL;
1240
1241 /* Return consumed length */
1242 return src_counter;
1243}
1244
1245/* Helper function for gprs_sndcp_decode_xid() to decode XID blocks */
1246static int decode_xid_block(struct llist_head *comp_fields, uint8_t tag,
1247 uint16_t tag_len, const uint8_t *val,
1248 const struct entity_algo_table *lt,
1249 unsigned int lt_len)
1250{
1251 struct gprs_sndcp_comp_field *comp_field;
1252 int byte_counter = 0;
1253 int comp_field_count = 0;
1254 int rc;
1255
1256 byte_counter = 0;
1257 do {
1258 /* Bail if more than the maximum number of
1259 comp_fields is generated */
1260 if (comp_field_count > MAX_ENTITIES * 2) {
1261 return -EINVAL;
1262 }
1263
1264 /* Parse and add comp_field */
1265 comp_field =
1266 talloc_zero(comp_fields, struct gprs_sndcp_comp_field);
1267
1268 rc = decode_comp_field(comp_field, val + byte_counter,
1269 tag_len - byte_counter, lt, lt_len, tag);
1270
1271 if (rc < 0) {
1272 talloc_free(comp_field);
1273 return -EINVAL;
1274 }
1275
1276 byte_counter += rc;
1277 llist_add(&comp_field->list, comp_fields);
1278 comp_field_count++;
1279 }
1280 while (tag_len - byte_counter > 0);
1281
1282 return byte_counter;
1283}
1284
1285/* Transform an SNDCP-XID message (src) into a list of SNDCP-XID fields */
1286static int gprs_sndcp_decode_xid(struct llist_head *comp_fields,
1287 const uint8_t *src, unsigned int src_len,
1288 const struct
1289 entity_algo_table
1290 *lt, unsigned int lt_len)
1291{
1292 int src_pos = 0;
1293 uint8_t tag;
1294 uint16_t tag_len;
1295 const uint8_t *val;
1296 int byte_counter = 0;
1297 int rc;
1298 int tlv_count = 0;
1299
1300 /* Valid TLV-Tag and types */
1301 static const struct tlv_definition sndcp_xid_def = {
1302 .def = {
1303 [SNDCP_XID_VERSION_NUMBER] = {TLV_TYPE_TLV,},
1304 [SNDCP_XID_DATA_COMPRESSION] = {TLV_TYPE_TLV,},
1305 [SNDCP_XID_PROTOCOL_COMPRESSION] = {TLV_TYPE_TLV,},
1306 },
1307 };
1308
1309 /* Parse TLV-Encoded SNDCP-XID message and defer payload
1310 to the apporpiate sub-parser functions */
1311 while (1) {
1312
1313 /* Bail if an the maximum number of TLV fields
1314 * have been parsed */
1315 if (tlv_count >= 3) {
1316 talloc_free(comp_fields);
1317 return -EINVAL;
1318 }
1319
1320 /* Parse TLV field */
1321 rc = tlv_parse_one(&tag, &tag_len, &val, &sndcp_xid_def,
1322 src + src_pos, src_len - src_pos);
1323 if (rc > 0)
1324 src_pos += rc;
1325 else {
1326 talloc_free(comp_fields);
1327 return -EINVAL;
1328 }
1329
1330 /* Decode compression parameters */
1331 if ((tag == SNDCP_XID_PROTOCOL_COMPRESSION)
1332 || (tag == SNDCP_XID_DATA_COMPRESSION)) {
1333 rc = decode_xid_block(comp_fields, tag, tag_len, val,
1334 lt, lt_len);
1335
1336 if (rc < 0) {
1337 talloc_free(comp_fields);
1338 return -EINVAL;
1339 } else
1340 byte_counter += rc;
1341 }
1342
1343 /* Stop when no further TLV elements can be expected */
1344 if (src_len - src_pos <= 2)
1345 break;
1346
1347 tlv_count++;
1348 }
1349
1350 return 0;
1351}
1352
1353/* Fill up lookutable from a list with comression entitiy fields */
1354static int gprs_sndcp_fill_table(struct
1355 entity_algo_table *lt,
1356 unsigned int lt_len,
1357 const struct llist_head *comp_fields)
1358{
1359 struct gprs_sndcp_comp_field *comp_field;
1360 int i = 0;
Philippae9beda2016-09-28 15:10:14 +02001361 int rc;
Philipp22611be2016-08-10 12:08:03 +02001362
1363 if (!comp_fields)
1364 return -EINVAL;
1365 if (!lt)
1366 return -EINVAL;
1367
Philippae9beda2016-09-28 15:10:14 +02001368 memset(lt, 0, sizeof(*lt));
Philipp22611be2016-08-10 12:08:03 +02001369
1370 llist_for_each_entry(comp_field, comp_fields, list) {
Philippae9beda2016-09-28 15:10:14 +02001371 if (comp_field->algo >= 0) {
1372 lt[i].entity = comp_field->entity;
1373 lt[i].algo = comp_field->algo;
1374 rc = gprs_sndcp_get_compression_class(comp_field);
Philipp22611be2016-08-10 12:08:03 +02001375
Philippae9beda2016-09-28 15:10:14 +02001376 if (rc < 0) {
1377 memset(lt, 0, sizeof(*lt));
1378 return -EINVAL;
1379 }
Philipp22611be2016-08-10 12:08:03 +02001380
Philippae9beda2016-09-28 15:10:14 +02001381 lt[i].compclass = rc;
1382 i++;
Philipp22611be2016-08-10 12:08:03 +02001383 }
Philipp22611be2016-08-10 12:08:03 +02001384 }
1385
1386 return i;
1387}
1388
1389/* Complete comp field params
1390 * (if a param (dst) is not valid, it will be copied from source (src) */
1391static int complete_comp_field_params(struct gprs_sndcp_comp_field
1392 *comp_field_dst, const struct
1393 gprs_sndcp_comp_field *comp_field_src)
1394{
1395 if (comp_field_dst->algo < 0)
1396 return -EINVAL;
1397
1398 if (comp_field_dst->rfc1144_params && comp_field_src->rfc1144_params) {
1399 if (comp_field_dst->rfc1144_params->s01 < 0) {
1400 comp_field_dst->rfc1144_params->s01 =
1401 comp_field_src->rfc1144_params->s01;
1402 }
1403 return 0;
1404 }
1405
1406 if (comp_field_dst->rfc2507_params && comp_field_src->rfc2507_params) {
1407
1408 if (comp_field_dst->rfc2507_params->f_max_period < 0) {
1409 comp_field_dst->rfc2507_params->f_max_period =
1410 comp_field_src->rfc2507_params->f_max_period;
1411 }
1412 if (comp_field_dst->rfc2507_params->f_max_time < 0) {
1413 comp_field_dst->rfc2507_params->f_max_time =
1414 comp_field_src->rfc2507_params->f_max_time;
1415 }
1416 if (comp_field_dst->rfc2507_params->max_header < 0) {
1417 comp_field_dst->rfc2507_params->max_header =
1418 comp_field_src->rfc2507_params->max_header;
1419 }
1420 if (comp_field_dst->rfc2507_params->tcp_space < 0) {
1421 comp_field_dst->rfc2507_params->tcp_space =
1422 comp_field_src->rfc2507_params->tcp_space;
1423 }
1424 if (comp_field_dst->rfc2507_params->non_tcp_space < 0) {
1425 comp_field_dst->rfc2507_params->non_tcp_space =
1426 comp_field_src->rfc2507_params->non_tcp_space;
1427 }
1428 return 0;
1429 }
1430
1431 if (comp_field_dst->rohc_params && comp_field_src->rohc_params) {
1432 if (comp_field_dst->rohc_params->max_cid < 0) {
1433 comp_field_dst->rohc_params->max_cid =
1434 comp_field_src->rohc_params->max_cid;
1435 }
1436 if (comp_field_dst->rohc_params->max_header < 0) {
1437 comp_field_dst->rohc_params->max_header =
1438 comp_field_src->rohc_params->max_header;
1439 }
1440 if (comp_field_dst->rohc_params->profile_len > 0) {
1441 memcpy(comp_field_dst->rohc_params->profile,
1442 comp_field_src->rohc_params->profile,
1443 sizeof(comp_field_dst->rohc_params->profile));
1444 comp_field_dst->rohc_params->profile_len =
1445 comp_field_src->rohc_params->profile_len;
1446 }
1447
1448 return 0;
1449 }
1450
1451 if (comp_field_dst->v42bis_params && comp_field_src->v42bis_params) {
1452 if (comp_field_dst->v42bis_params->p0 < 0) {
1453 comp_field_dst->v42bis_params->p0 =
1454 comp_field_src->v42bis_params->p0;
1455 }
1456 if (comp_field_dst->v42bis_params->p1 < 0) {
1457 comp_field_dst->v42bis_params->p1 =
1458 comp_field_src->v42bis_params->p1;
1459 }
1460 if (comp_field_dst->v42bis_params->p2 < 0) {
1461 comp_field_dst->v42bis_params->p2 =
1462 comp_field_src->v42bis_params->p2;
1463 }
1464 return 0;
1465 }
1466
1467 if (comp_field_dst->v44_params && comp_field_src->v44_params) {
1468 if (comp_field_dst->v44_params->c0 < 0) {
1469 comp_field_dst->v44_params->c0 =
1470 comp_field_src->v44_params->c0;
1471 }
1472 if (comp_field_dst->v44_params->p0 < 0) {
1473 comp_field_dst->v44_params->p0 =
1474 comp_field_src->v44_params->p0;
1475 }
1476 if (comp_field_dst->v44_params->p1t < 0) {
1477 comp_field_dst->v44_params->p1t =
1478 comp_field_src->v44_params->p1t;
1479 }
1480 if (comp_field_dst->v44_params->p1r < 0) {
1481 comp_field_dst->v44_params->p1r =
1482 comp_field_src->v44_params->p1r;
1483 }
1484 if (comp_field_dst->v44_params->p3t < 0) {
1485 comp_field_dst->v44_params->p3t =
1486 comp_field_src->v44_params->p3t;
1487 }
1488 if (comp_field_dst->v44_params->p3r < 0) {
1489 comp_field_dst->v44_params->p3r =
1490 comp_field_src->v44_params->p3r;
1491 }
1492 return 0;
1493 }
1494
1495 /* There should be at least exist one param set
1496 * in the destination struct, otherwise something
1497 * must be wrong! */
1498 return -EINVAL;
1499}
1500
1501/* Complete missing parameters in a comp_field */
1502static int gprs_sndcp_complete_comp_field(struct gprs_sndcp_comp_field
1503 *comp_field, const struct llist_head
1504 *comp_fields)
1505{
1506 struct gprs_sndcp_comp_field *comp_field_src;
1507 int rc = 0;
1508
1509 llist_for_each_entry(comp_field_src, comp_fields, list) {
1510 if (comp_field_src->entity == comp_field->entity) {
1511
1512 /* Complete header fields */
1513 if (comp_field_src->comp_len > 0) {
1514 memcpy(comp_field->comp,
1515 comp_field_src->comp,
1516 sizeof(comp_field_src->comp));
1517 comp_field->comp_len = comp_field_src->comp_len;
1518 }
1519
1520 /* Complete parameter fields */
1521 rc = complete_comp_field_params(comp_field,
1522 comp_field_src);
1523 }
1524 }
1525
1526 return rc;
1527}
1528
1529/* Complete missing parameters of all comp_field in a list */
1530static int gprs_sndcp_complete_comp_fields(struct llist_head
1531 *comp_fields_incomplete,
1532 const struct llist_head *comp_fields)
1533{
1534 struct gprs_sndcp_comp_field *comp_field_incomplete;
1535 int rc;
1536
1537 llist_for_each_entry(comp_field_incomplete, comp_fields_incomplete,
1538 list) {
1539
1540 rc = gprs_sndcp_complete_comp_field(comp_field_incomplete,
1541 comp_fields);
1542 if (rc < 0)
1543 return -EINVAL;
1544
1545 }
1546
1547 return 0;
1548}
1549
1550/* Transform an SNDCP-XID message (src) into a list of SNDCP-XID fields */
1551struct llist_head *gprs_sndcp_parse_xid(const void *ctx,
1552 const uint8_t *src,
1553 unsigned int src_len,
1554 const struct llist_head
1555 *comp_fields_req)
1556{
1557 int rc;
1558 int lt_len;
1559 struct llist_head *comp_fields;
1560 struct entity_algo_table lt[MAX_ENTITIES * 2];
1561
1562 OSMO_ASSERT(src);
1563
1564 comp_fields = talloc_zero(ctx, struct llist_head);
1565 INIT_LLIST_HEAD(comp_fields);
1566
1567 if (comp_fields_req) {
1568 /* Generate lookup table */
1569 lt_len =
1570 gprs_sndcp_fill_table(lt, MAX_ENTITIES * 2,
1571 comp_fields_req);
1572 if (lt_len < 0) {
1573 talloc_free(comp_fields);
1574 return NULL;
1575 }
1576
1577 /* Parse SNDCP-CID XID-Field */
1578 rc = gprs_sndcp_decode_xid(comp_fields, src, src_len, lt,
1579 lt_len);
1580 if (rc < 0) {
1581 talloc_free(comp_fields);
1582 return NULL;
1583 }
1584
1585 rc = gprs_sndcp_complete_comp_fields(comp_fields,
1586 comp_fields_req);
1587 if (rc < 0) {
1588 talloc_free(comp_fields);
1589 return NULL;
1590 }
1591
1592 } else {
1593 /* Parse SNDCP-CID XID-Field */
1594 rc = gprs_sndcp_decode_xid(comp_fields, src, src_len, NULL, 0);
1595 if (rc < 0) {
1596 talloc_free(comp_fields);
1597 return NULL;
1598 }
1599 }
1600
1601 return comp_fields;
1602}
1603
1604/* Helper for gprs_sndcp_dump_comp_fields(),
1605 * dumps protocol compression parameters */
1606static void dump_pcomp_params(const struct gprs_sndcp_comp_field
1607 *comp_field, unsigned int logl)
1608{
1609 int i;
1610
1611 switch (comp_field->algo) {
1612 case RFC_1144:
1613 if (comp_field->rfc1144_params == NULL) {
1614 LOGP(DSNDCP, logl,
1615 " gprs_sndcp_pcomp_rfc1144_params=NULL\n");
1616 break;
1617 }
1618 LOGP(DSNDCP, logl, " gprs_sndcp_pcomp_rfc1144_params {\n");
1619 LOGP(DSNDCP, logl,
1620 " nsapi_len=%d;\n",
1621 comp_field->rfc1144_params->nsapi_len);
1622 if (comp_field->rfc1144_params->nsapi_len == 0)
1623 LOGP(DSNDCP, logl, " nsapi[] = NULL;\n");
1624 for (i = 0; i < comp_field->rfc1144_params->nsapi_len; i++) {
1625 LOGP(DSNDCP, logl,
1626 " nsapi[%d]=%d;\n", i,
1627 comp_field->rfc1144_params->nsapi[i]);
1628 }
1629 LOGP(DSNDCP, logl, " s01=%d;\n",
1630 comp_field->rfc1144_params->s01);
1631 LOGP(DSNDCP, logl, " }\n");
1632 break;
1633 case RFC_2507:
1634 if (comp_field->rfc2507_params == NULL) {
1635 LOGP(DSNDCP, logl,
1636 " gprs_sndcp_pcomp_rfc2507_params=NULL\n");
1637 break;
1638 }
1639 LOGP(DSNDCP, logl, " gprs_sndcp_pcomp_rfc2507_params {\n");
1640 LOGP(DSNDCP, logl,
1641 " nsapi_len=%d;\n",
1642 comp_field->rfc2507_params->nsapi_len);
1643 if (comp_field->rfc2507_params->nsapi_len == 0)
1644 LOGP(DSNDCP, logl, " nsapi[] = NULL;\n");
1645 for (i = 0; i < comp_field->rfc2507_params->nsapi_len; i++) {
1646 LOGP(DSNDCP, logl,
1647 " nsapi[%d]=%d;\n", i,
1648 comp_field->rfc2507_params->nsapi[i]);
1649 }
1650 LOGP(DSNDCP, logl,
1651 " f_max_period=%d;\n",
1652 comp_field->rfc2507_params->f_max_period);
1653 LOGP(DSNDCP, logl,
1654 " f_max_time=%d;\n",
1655 comp_field->rfc2507_params->f_max_time);
1656 LOGP(DSNDCP, logl,
1657 " max_header=%d;\n",
1658 comp_field->rfc2507_params->max_header);
1659 LOGP(DSNDCP, logl,
1660 " tcp_space=%d;\n",
1661 comp_field->rfc2507_params->tcp_space);
1662 LOGP(DSNDCP, logl,
1663 " non_tcp_space=%d;\n",
1664 comp_field->rfc2507_params->non_tcp_space);
1665 LOGP(DSNDCP, logl, " }\n");
1666 break;
1667 case ROHC:
1668 if (comp_field->rohc_params == NULL) {
1669 LOGP(DSNDCP, logl,
1670 " gprs_sndcp_pcomp_rohc_params=NULL\n");
1671 break;
1672 }
1673 LOGP(DSNDCP, logl, " gprs_sndcp_pcomp_rohc_params {\n");
1674 LOGP(DSNDCP, logl,
1675 " nsapi_len=%d;\n",
1676 comp_field->rohc_params->nsapi_len);
1677 if (comp_field->rohc_params->nsapi_len == 0)
1678 LOGP(DSNDCP, logl, " nsapi[] = NULL;\n");
1679 for (i = 0; i < comp_field->rohc_params->nsapi_len; i++) {
1680 LOGP(DSNDCP, logl,
1681 " nsapi[%d]=%d;\n", i,
1682 comp_field->rohc_params->nsapi[i]);
1683 }
1684 LOGP(DSNDCP, logl,
1685 " max_cid=%d;\n", comp_field->rohc_params->max_cid);
1686 LOGP(DSNDCP, logl,
1687 " max_header=%d;\n",
1688 comp_field->rohc_params->max_header);
1689 LOGP(DSNDCP, logl,
1690 " profile_len=%d;\n",
1691 comp_field->rohc_params->profile_len);
1692 if (comp_field->rohc_params->profile_len == 0)
1693 LOGP(DSNDCP, logl, " profile[] = NULL;\n");
1694 for (i = 0; i < comp_field->rohc_params->profile_len; i++)
1695 LOGP(DSNDCP, logl,
1696 " profile[%d]=%04x;\n",
1697 i, comp_field->rohc_params->profile[i]);
1698 LOGP(DSNDCP, logl, " }\n");
1699 break;
1700 }
1701
1702}
1703
1704/* Helper for gprs_sndcp_dump_comp_fields(),
1705 * data protocol compression parameters */
1706static void dump_dcomp_params(const struct gprs_sndcp_comp_field
1707 *comp_field, unsigned int logl)
1708{
1709 int i;
1710
1711 switch (comp_field->algo) {
1712 case V42BIS:
1713 if (comp_field->v42bis_params == NULL) {
1714 LOGP(DSNDCP, logl,
1715 " gprs_sndcp_dcomp_v42bis_params=NULL\n");
1716 break;
1717 }
1718 LOGP(DSNDCP, logl, " gprs_sndcp_dcomp_v42bis_params {\n");
1719 LOGP(DSNDCP, logl,
1720 " nsapi_len=%d;\n",
1721 comp_field->v42bis_params->nsapi_len);
1722 if (comp_field->v42bis_params->nsapi_len == 0)
1723 LOGP(DSNDCP, logl, " nsapi[] = NULL;\n");
1724 for (i = 0; i < comp_field->v42bis_params->nsapi_len; i++)
1725 LOGP(DSNDCP, logl,
1726 " nsapi[%d]=%d;\n", i,
1727 comp_field->v42bis_params->nsapi[i]);
1728 LOGP(DSNDCP, logl, " p0=%d;\n",
1729 comp_field->v42bis_params->p0);
1730 LOGP(DSNDCP, logl, " p1=%d;\n",
1731 comp_field->v42bis_params->p1);
1732 LOGP(DSNDCP, logl, " p2=%d;\n",
1733 comp_field->v42bis_params->p2);
1734 LOGP(DSNDCP, logl, " }\n");
1735 break;
1736 case V44:
1737 if (comp_field->v44_params == NULL) {
1738 LOGP(DSNDCP, logl,
1739 " gprs_sndcp_dcomp_v44_params=NULL\n");
1740 break;
1741 }
1742 LOGP(DSNDCP, logl, " gprs_sndcp_dcomp_v44_params {\n");
1743 LOGP(DSNDCP, logl,
1744 " nsapi_len=%d;\n",
1745 comp_field->v44_params->nsapi_len);
1746 if (comp_field->v44_params->nsapi_len == 0)
1747 LOGP(DSNDCP, logl, " nsapi[] = NULL;\n");
1748 for (i = 0; i < comp_field->v44_params->nsapi_len; i++) {
1749 LOGP(DSNDCP, logl,
1750 " nsapi[%d]=%d;\n", i,
1751 comp_field->v44_params->nsapi[i]);
1752 }
1753 LOGP(DSNDCP, logl, " c0=%d;\n",
1754 comp_field->v44_params->c0);
1755 LOGP(DSNDCP, logl, " p0=%d;\n",
1756 comp_field->v44_params->p0);
1757 LOGP(DSNDCP, logl, " p1t=%d;\n",
1758 comp_field->v44_params->p1t);
1759 LOGP(DSNDCP, logl, " p1r=%d;\n",
1760 comp_field->v44_params->p1r);
1761 LOGP(DSNDCP, logl, " p3t=%d;\n",
1762 comp_field->v44_params->p3t);
1763 LOGP(DSNDCP, logl, " p3r=%d;\n",
1764 comp_field->v44_params->p3r);
1765 LOGP(DSNDCP, logl, " }\n");
1766 break;
1767 }
1768}
1769
1770/* Dump a list with SNDCP-XID fields (Debug) */
1771void gprs_sndcp_dump_comp_fields(const struct llist_head *comp_fields,
1772 unsigned int logl)
1773{
1774 struct gprs_sndcp_comp_field *comp_field;
1775 int i;
1776 int compclass;
1777
1778 OSMO_ASSERT(comp_fields);
1779
1780 llist_for_each_entry(comp_field, comp_fields, list) {
1781 LOGP(DSNDCP, logl, "SNDCP-XID:\n");
1782 LOGP(DSNDCP, logl, "struct gprs_sndcp_comp_field {\n");
1783 LOGP(DSNDCP, logl, " entity=%d;\n", comp_field->entity);
1784 LOGP(DSNDCP, logl, " algo=%d;\n", comp_field->algo);
1785 LOGP(DSNDCP, logl, " comp_len=%d;\n", comp_field->comp_len);
1786 if (comp_field->comp_len == 0)
1787 LOGP(DSNDCP, logl, " comp[] = NULL;\n");
1788 for (i = 0; i < comp_field->comp_len; i++) {
1789 LOGP(DSNDCP, logl, " comp[%d]=%d;\n", i,
1790 comp_field->comp[i]);
1791 }
1792
1793 compclass = gprs_sndcp_get_compression_class(comp_field);
1794
1795 if (compclass == SNDCP_XID_PROTOCOL_COMPRESSION) {
1796 dump_pcomp_params(comp_field, logl);
1797 } else if (compclass == SNDCP_XID_DATA_COMPRESSION) {
1798 dump_dcomp_params(comp_field, logl);
1799 }
1800
1801 LOGP(DSNDCP, logl, "}\n");
1802 }
1803
1804}