blob: dfea5febcdf8ceb3747168a928f5fa5e858a6aaf [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,
Philippdb142dc2016-12-22 14:15:20 +0100552 const struct llist_head *comp_fields, int version)
Philipp22611be2016-08-10 12:08:03 +0200553{
554 int rc;
555 int byte_counter = 0;
556 uint8_t comp_bytes[512];
Philippdb142dc2016-12-22 14:15:20 +0100557 uint8_t xid_version_number[1];
Philipp22611be2016-08-10 12:08:03 +0200558
559 OSMO_ASSERT(comp_fields);
560 OSMO_ASSERT(dst);
561 OSMO_ASSERT(dst_maxlen >= 2 + sizeof(xid_version_number));
562
Philippdb142dc2016-12-22 14:15:20 +0100563 /* Prepend header with version number */
564 if (version >= 0) {
565 xid_version_number[0] = (uint8_t) (version & 0xff);
566 dst =
567 tlv_put(dst, SNDCP_XID_VERSION_NUMBER,
568 sizeof(xid_version_number), xid_version_number);
569 byte_counter += (sizeof(xid_version_number) + 2);
570 }
Philipp22611be2016-08-10 12:08:03 +0200571
Philippdb142dc2016-12-22 14:15:20 +0100572 /* Stop if there is no compression fields supplied */
573 if (llist_empty(comp_fields))
574 return byte_counter;
Philipp22611be2016-08-10 12:08:03 +0200575
576 /* Add data compression fields */
577 rc = gprs_sndcp_pack_fields(comp_fields, comp_bytes,
578 sizeof(comp_bytes),
579 SNDCP_XID_DATA_COMPRESSION);
580 OSMO_ASSERT(rc >= 0);
581
582 if (rc > 0) {
583 dst = tlv_put(dst, SNDCP_XID_DATA_COMPRESSION, rc, comp_bytes);
584 byte_counter += rc + 2;
585 }
586
587 /* Add header compression fields */
588 rc = gprs_sndcp_pack_fields(comp_fields, comp_bytes,
589 sizeof(comp_bytes),
590 SNDCP_XID_PROTOCOL_COMPRESSION);
591 OSMO_ASSERT(rc >= 0);
592
593 if (rc > 0) {
594 dst = tlv_put(dst, SNDCP_XID_PROTOCOL_COMPRESSION, rc,
595 comp_bytes);
596 byte_counter += rc + 2;
597 }
598
599 /* Return generated length */
600 return byte_counter;
601}
602
603/* FUNCTIONS RELATED TO SNDCP-XID DECODING */
604
605/* Decode applicable sapis (works the same in all three compression schemes) */
606static int decode_pcomp_applicable_sapis(uint8_t *nsapis,
607 uint8_t *nsapis_len,
608 const uint8_t *src,
609 unsigned int src_len)
610{
611 uint16_t blob;
612 int i;
613 int nsapi_len = 0;
614
615 /* Exit immediately if no result can be stored */
616 if (!nsapis)
617 return -EINVAL;
618
619 /* Exit immediately if not enough input data is available */
620 if (src_len < 2)
621 return -EINVAL;
622
623 /* Read bitmask */
624 blob = *src;
625 blob = (blob << 8) & 0xFF00;
626 src++;
627 blob |= (*src) & 0xFF;
628 blob = (blob >> 5);
629
630 /* Decode applicable SAPIs */
631 for (i = 0; i < 15; i++) {
632 if ((blob >> i) & 1) {
633 nsapis[nsapi_len] = i + 5;
634 nsapi_len++;
635 }
636 }
637
638 /* Return consumed length */
639 *nsapis_len = nsapi_len;
640 return 2;
641}
642
643/* Decode 16 bit field */
644static int decode_pcomp_16_bit_field(int *value_int, uint16_t * value_uint16,
645 const uint8_t *src,
646 unsigned int src_len,
647 int value_min, int value_max)
648{
649 uint16_t blob;
650
651 /* Reset values to zero (just to be sure) */
652 if (value_int)
653 *value_int = -1;
654 if (value_uint16)
655 *value_uint16 = 0;
656
657 /* Exit if not enough src are available */
658 if (src_len < 2)
659 return -EINVAL;
660
661 /* Decode bit value */
662 blob = *src;
663 blob = (blob << 8) & 0xFF00;
664 src++;
665 blob |= *src;
666
667 /* Check if parsed value is within bounds */
668 if (blob < value_min)
669 return -EINVAL;
670 if (blob > value_max)
671 return -EINVAL;
672
673 /* Hand back results to the caller */
674 if (value_int)
675 *value_int = blob;
676 if (value_uint16)
677 *value_uint16 = blob;
678
679 /* Return consumed length */
680 return 2;
681}
682
683/* Decode 8 bit field */
684static int decode_pcomp_8_bit_field(int *value_int, uint8_t *value_uint8,
685 const uint8_t *src,
686 unsigned int src_len,
687 int value_min, int value_max)
688{
689 uint8_t blob;
690
691 /* Reset values to invalid (just to be sure) */
692 if (value_int)
693 *value_int = -1;
694 if (value_uint8)
695 *value_uint8 = 0;
696
697 /* Exit if not enough src are available */
698 if (src_len < 1)
699 return -EINVAL;
700
701 /* Decode bit value */
702 blob = *src;
703
704 /* Check if parsed value is within bounds */
705 if (blob < value_min)
706 return -EINVAL;
707 if (blob > value_max)
708 return -EINVAL;
709
710 /* Hand back results to the caller */
711 if (value_int)
712 *value_int = blob;
713 if (value_uint8)
714 *value_uint8 = blob;
715
716 /* Return consumed length */
717 return 1;
718}
719
720/* Decode rfc1144 parameter field see also: 3GPP TS 44.065, 6.5.2.1, Table 5) */
721static int decode_pcomp_rfc1144_params(struct gprs_sndcp_pcomp_rfc1144_params
722 *params, const uint8_t *src,
723 unsigned int src_len)
724{
725 int rc;
726 int byte_counter = 0;
727
728 /* Mark all optional parameters invalid by default */
729 params->s01 = -1;
730
731 /* Decode applicable SAPIs */
732 rc = decode_pcomp_applicable_sapis(params->nsapi, &params->nsapi_len,
733 src, src_len);
734 if (rc > 0) {
735 byte_counter += rc;
736 src += rc;
737 } else
738 return byte_counter;
739
740 /* Decode parameter S0 -1
741 * (see also: 3GPP TS 44.065, 6.5.2.1, Table 5) */
742 rc = decode_pcomp_8_bit_field(&params->s01, NULL, src,
743 src_len - byte_counter, 0, 255);
744 if (rc <= 0)
745 return byte_counter;
746 byte_counter += rc;
747 src += rc;
748
749 /* Return consumed length */
750 return byte_counter;
751}
752
753/* Decode rfc2507 parameter field
754 * (see also: 3GPP TS 44.065, 6.5.3.1, Table 6) */
755static int decode_pcomp_rfc2507_params(struct gprs_sndcp_pcomp_rfc2507_params
756 *params, const uint8_t *src,
757 unsigned int src_len)
758{
759 int rc;
760 int byte_counter = 0;
761
762 /* Mark all optional parameters invalid by default */
763 params->f_max_period = -1;
764 params->f_max_time = -1;
765 params->max_header = -1;
766 params->tcp_space = -1;
767 params->non_tcp_space = -1;
768
769 /* Decode applicable SAPIs */
770 rc = decode_pcomp_applicable_sapis(params->nsapi, &params->nsapi_len,
771 src, src_len);
772 if (rc > 0) {
773 byte_counter += rc;
774 src += rc;
775 } else
776 return byte_counter;
777
778 /* Decode F_MAX_PERIOD (see also: 3GPP TS 44.065, 6.5.3.1, Table 6) */
779 rc = decode_pcomp_16_bit_field(&params->f_max_period, NULL, src,
780 src_len - byte_counter, 1, 65535);
781 if (rc <= 0)
782 return byte_counter;
783 byte_counter += rc;
784 src += rc;
785
786 /* Decode F_MAX_TIME (see also: 3GPP TS 44.065, 6.5.3.1, Table 6) */
787 rc = decode_pcomp_8_bit_field(&params->f_max_time, NULL, src,
788 src_len - byte_counter, 1, 255);
789 if (rc <= 0)
790 return byte_counter;
791 byte_counter += rc;
792 src += rc;
793
794 /* Decode MAX_HEADER (see also: 3GPP TS 44.065, 6.5.3.1, Table 6) */
795 rc = decode_pcomp_8_bit_field(&params->max_header, NULL, src,
796 src_len - byte_counter, 60, 255);
797 if (rc <= 0)
798 return byte_counter;
799 byte_counter += rc;
800 src += rc;
801
802 /* Decode TCP_SPACE (see also: 3GPP TS 44.065, 6.5.3.1, Table 6) */
803 rc = decode_pcomp_8_bit_field(&params->tcp_space, NULL, src,
804 src_len - byte_counter, 3, 255);
805 if (rc <= 0)
806 return byte_counter;
807 byte_counter += rc;
808 src += rc;
809
810 /* Decode NON_TCP_SPACE (see also: 3GPP TS 44.065, 6.5.3.1, Table 6) */
811 rc = decode_pcomp_16_bit_field(&params->non_tcp_space, NULL, src,
812 src_len - byte_counter, 3, 65535);
813 if (rc <= 0)
814 return byte_counter;
815 byte_counter += rc;
816 src += rc;
817
818 /* Return consumed length */
819 return byte_counter;
820}
821
822/* Decode ROHC parameter field (see also: 3GPP TS 44.065, 6.5.4.1, Table 10) */
823static int decode_pcomp_rohc_params(struct gprs_sndcp_pcomp_rohc_params *params,
824 const uint8_t *src, unsigned int src_len)
825{
826 int rc;
827 int byte_counter = 0;
828 int i;
829
830 /* Mark all optional parameters invalid by default */
831 params->max_cid = -1;
832 params->max_header = -1;
833
834 /* Decode applicable SAPIs */
835 rc = decode_pcomp_applicable_sapis(params->nsapi, &params->nsapi_len,
836 src, src_len);
837 if (rc <= 0)
838 return byte_counter;
839 byte_counter += rc;
840 src += rc;
841
842 /* Decode MAX_CID (see also: 3GPP TS 44.065, 6.5.4.1, Table 10) */
843 rc = decode_pcomp_16_bit_field(&params->max_cid, NULL, src,
844 src_len - byte_counter, 0, 16383);
845 if (rc <= 0)
846 return byte_counter;
847 byte_counter += rc;
848 src += rc;
849
850 /* Decode MAX_HEADER (see also: 3GPP TS 44.065, 6.5.4.1, Table 10) */
851 rc = decode_pcomp_16_bit_field(&params->max_header, NULL, src,
852 src_len - byte_counter, 60, 255);
853 if (rc <= 0)
854 return byte_counter;
855 byte_counter += rc;
856 src += rc;
857
858 /* Decode Profiles (see also: 3GPP TS 44.065, 6.5.4.1, Table 10) */
859 for (i = 0; i < 16; i++) {
860 params->profile_len = 0;
861 rc = decode_pcomp_16_bit_field(NULL, &params->profile[i], src,
862 src_len - byte_counter, 0,
863 65535);
864 if (rc <= 0)
865 return byte_counter;
866 byte_counter += rc;
867 src += rc;
868 params->profile_len = i + 1;
869 }
870
871 /* Return consumed length */
872 return byte_counter;
873}
874
875/* Decode V.42bis parameter field
876 * (see also: 3GPP TS 44.065, 6.6.2.1, Table 7a) */
877static int decode_dcomp_v42bis_params(struct gprs_sndcp_dcomp_v42bis_params
878 *params, const uint8_t *src,
879 unsigned int src_len)
880{
881 int rc;
882 int byte_counter = 0;
883
884 /* Mark all optional parameters invalid by default */
885 params->p0 = -1;
886 params->p1 = -1;
887 params->p2 = -1;
888
889 /* Decode applicable SAPIs */
890 rc = decode_pcomp_applicable_sapis(params->nsapi, &params->nsapi_len,
891 src, src_len);
892 if (rc > 0) {
893 byte_counter += rc;
894 src += rc;
895 } else
896 return byte_counter;
897
898 /* Decode P0 (see also: 3GPP TS 44.065, 6.6.2.1, Table 7a) */
899 rc = decode_pcomp_8_bit_field(&params->p0, NULL, src,
900 src_len - byte_counter, 0, 3);
901 if (rc <= 0)
902 return byte_counter;
903 byte_counter += rc;
904 src += rc;
905
906 /* Decode P1 (see also: 3GPP TS 44.065, 6.6.2.1, Table 7a) */
907 rc = decode_pcomp_16_bit_field(&params->p1, NULL, src,
908 src_len - byte_counter, 512, 65535);
909 if (rc <= 0)
910 return byte_counter;
911 byte_counter += rc;
912 src += rc;
913
914 /* Decode P2 (see also: 3GPP TS 44.065, 6.6.2.1, Table 7a) */
915 rc = decode_pcomp_8_bit_field(&params->p2, NULL, src,
916 src_len - byte_counter, 6, 250);
917 if (rc <= 0)
918 return byte_counter;
919 byte_counter += rc;
920 src += rc;
921
922 /* Return consumed length */
923 return byte_counter;
924}
925
926/* Decode V44 parameter field (see also: 3GPP TS 44.065, 6.6.3.1, Table 7c) */
927static int decode_dcomp_v44_params(struct gprs_sndcp_dcomp_v44_params *params,
928 const uint8_t *src, unsigned int src_len)
929{
930 int rc;
931 int byte_counter = 0;
932
933 /* Mark all optional parameters invalid by default */
934 params->c0 = -1;
935 params->p0 = -1;
936 params->p1t = -1;
937 params->p1r = -1;
938 params->p3t = -1;
939 params->p3r = -1;
940
941 /* Decode applicable SAPIs */
942 rc = decode_pcomp_applicable_sapis(params->nsapi, &params->nsapi_len,
943 src, src_len);
944 if (rc > 0) {
945 byte_counter += rc;
946 src += rc;
947 } else
948 return byte_counter;
949
950 /* Decode C0 (see also: 3GPP TS 44.065, 6.6.3.1, Table 7c) */
951 rc = decode_pcomp_8_bit_field(&params->c0, NULL, src,
952 src_len - byte_counter, 0, 255);
953 if (rc <= 0)
954 return byte_counter;
955 if ((params->c0 != 0x80) && (params->c0 != 0xC0))
956 return -EINVAL;
957 byte_counter += rc;
958 src += rc;
959
960 /* Decode P0 (see also: 3GPP TS 44.065, 6.6.3.1, Table 7c) */
961 rc = decode_pcomp_8_bit_field(&params->p0, NULL, src,
962 src_len - byte_counter, 0, 3);
963 if (rc <= 0)
964 return byte_counter;
965 byte_counter += rc;
966 src += rc;
967
968 /* Decode P1T (see also: 3GPP TS 44.065, 6.6.3.1, Table 7c) */
969 rc = decode_pcomp_16_bit_field(&params->p1t, NULL, src,
970 src_len - byte_counter, 265, 65535);
971 if (rc <= 0)
972 return byte_counter;
973 byte_counter += rc;
974 src += rc;
975
976 /* Decode P1R (see also: 3GPP TS 44.065, 6.6.3.1, Table 7c) */
977 rc = decode_pcomp_16_bit_field(&params->p1r, NULL, src,
978 src_len - byte_counter, 265, 65535);
979 if (rc <= 0)
980 return byte_counter;
981 byte_counter += rc;
982 src += rc;
983
984 /* Decode P3T (see also: 3GPP TS 44.065, 6.6.3.1, Table 7c) */
985 rc = decode_pcomp_16_bit_field(&params->p3t, NULL, src,
986 src_len - byte_counter, 265, 65535);
987 if (rc <= 0)
988 return byte_counter;
989 if (params->p3t < 2 * params->p1t)
990 return -EINVAL;
991 byte_counter += rc;
992 src += rc;
993
994 /* Decode P3R (see also: 3GPP TS 44.065, 6.6.3.1, Table 7c) */
995 rc = decode_pcomp_16_bit_field(&params->p3r, NULL, src,
996 src_len - byte_counter, 265, 65535);
997 if (rc <= 0)
998 return byte_counter;
999 if (params->p3r < 2 * params->p1r)
1000 return -EINVAL;
1001 byte_counter += rc;
1002 src += rc;
1003
1004 /* Return consumed length */
1005 return byte_counter;
1006}
1007
1008/* Lookup algorithm identfier by entity ID */
1009static int lookup_algorithm_identifier(int entity, const struct
1010 entity_algo_table
1011 *lt, unsigned int lt_len, int compclass)
1012{
1013 int i;
1014
1015 if (!lt)
1016 return -1;
1017
1018 for (i = 0; i < lt_len; i++) {
1019 if ((lt[i].entity == entity)
1020 && (lt[i].compclass == compclass))
1021 return lt[i].algo;
1022 }
1023
1024 return -1;
1025}
1026
1027/* Helper function for decode_comp_field(), decodes
1028 * numeric pcomp/dcomp values */
1029static int decode_comp_values(struct gprs_sndcp_comp_field *comp_field,
1030 const uint8_t *src, int compclass)
1031{
1032 int src_counter = 0;
1033 int i;
1034
1035 if (comp_field->p) {
1036 /* Determine the number of expected PCOMP/DCOMP values */
1037 if (compclass == SNDCP_XID_PROTOCOL_COMPRESSION) {
1038 /* For protocol compression */
1039 switch (comp_field->algo) {
1040 case RFC_1144:
1041 comp_field->comp_len = RFC1144_PCOMP_NUM;
1042 break;
1043 case RFC_2507:
1044 comp_field->comp_len = RFC2507_PCOMP_NUM;
1045 break;
1046 case ROHC:
1047 comp_field->comp_len = ROHC_PCOMP_NUM;
1048 break;
1049
1050 /* Exit if the algorithem type encodes
1051 something unknown / unspecified */
1052 default:
1053 return -EINVAL;
1054 }
1055 } else {
1056 /* For data compression */
1057 switch (comp_field->algo) {
1058 case V42BIS:
1059 comp_field->comp_len = V42BIS_DCOMP_NUM;
1060 break;
1061 case V44:
1062 comp_field->comp_len = V44_DCOMP_NUM;
1063 break;
1064
1065 /* Exit if the algorithem type encodes
1066 something unknown / unspecified */
1067 default:
1068 return -EINVAL;
1069 }
1070 }
1071
1072 for (i = 0; i < comp_field->comp_len; i++) {
1073 if (i & 1) {
1074 comp_field->comp[i] = (*src) & 0x0F;
1075 src++;
1076 src_counter++;
1077 } else
1078 comp_field->comp[i] = ((*src) >> 4) & 0x0F;
1079 }
1080
1081 if (i & 1) {
1082 src++;
1083 src_counter++;
1084 }
1085 }
1086
1087 return src_counter;
1088}
1089
1090/* Helper function for decode_comp_field(), decodes the parameters
1091 * which are protocol compression specific */
1092static int decode_pcomp_params(struct gprs_sndcp_comp_field *comp_field,
1093 const uint8_t *src, int src_len)
1094{
1095 int rc;
1096
1097 switch (comp_field->algo) {
1098 case RFC_1144:
1099 comp_field->rfc1144_params = talloc_zero(comp_field, struct
1100 gprs_sndcp_pcomp_rfc1144_params);
1101 rc = decode_pcomp_rfc1144_params(comp_field->rfc1144_params,
1102 src, src_len);
1103 if (rc < 0)
1104 talloc_free(comp_field->rfc1144_params);
1105 break;
1106 case RFC_2507:
1107 comp_field->rfc2507_params = talloc_zero(comp_field, struct
1108 gprs_sndcp_pcomp_rfc2507_params);
1109 rc = decode_pcomp_rfc2507_params(comp_field->rfc2507_params,
1110 src, src_len);
1111 if (rc < 0)
1112 talloc_free(comp_field->rfc1144_params);
1113 break;
1114 case ROHC:
1115 comp_field->rohc_params = talloc_zero(comp_field, struct
1116 gprs_sndcp_pcomp_rohc_params);
1117 rc = decode_pcomp_rohc_params(comp_field->rohc_params, src,
1118 src_len);
1119 if (rc < 0)
1120 talloc_free(comp_field->rohc_params);
1121 break;
1122
1123 /* If no suitable decoder is detected,
1124 leave the remaining bytes undecoded */
1125 default:
1126 rc = src_len;
1127 }
1128
1129 if (rc < 0) {
1130 comp_field->rfc1144_params = NULL;
1131 comp_field->rfc2507_params = NULL;
1132 comp_field->rohc_params = NULL;
1133 }
1134
1135 return rc;
1136}
1137
1138/* Helper function for decode_comp_field(), decodes the parameters
1139 * which are data compression specific */
1140static int decode_dcomp_params(struct gprs_sndcp_comp_field *comp_field,
1141 const uint8_t *src, int src_len)
1142{
1143 int rc;
1144
1145 switch (comp_field->algo) {
1146 case V42BIS:
1147 comp_field->v42bis_params = talloc_zero(comp_field, struct
1148 gprs_sndcp_dcomp_v42bis_params);
1149 rc = decode_dcomp_v42bis_params(comp_field->v42bis_params, src,
1150 src_len);
1151 if (rc < 0)
1152 talloc_free(comp_field->v42bis_params);
1153 break;
1154 case V44:
1155 comp_field->v44_params = talloc_zero(comp_field, struct
1156 gprs_sndcp_dcomp_v44_params);
1157 rc = decode_dcomp_v44_params(comp_field->v44_params, src,
1158 src_len);
1159 if (rc < 0)
1160 talloc_free(comp_field->v44_params);
1161 break;
1162
1163 /* If no suitable decoder is detected,
1164 * leave the remaining bytes undecoded */
1165 default:
1166 rc = src_len;
1167 }
1168
1169 if (rc < 0) {
1170 comp_field->v42bis_params = NULL;
1171 comp_field->v44_params = NULL;
1172 }
1173
1174 return rc;
1175}
1176
1177/* Decode data or protocol control information compression field
1178 * (see also: 3GPP TS 44.065, 6.6.1.1, Figure 9 and
1179 * 3GPP TS 44.065, 6.5.1.1, Figure 7) */
1180static int decode_comp_field(struct gprs_sndcp_comp_field *comp_field,
1181 const uint8_t *src, unsigned int src_len,
1182 const struct entity_algo_table *lt,
1183 unsigned int lt_len, int compclass)
1184{
1185 int src_counter = 0;
1186 unsigned int len;
1187 int rc;
1188
1189 OSMO_ASSERT(comp_field);
1190
1191 /* Exit immediately if it is clear that no
1192 parseable data is present */
1193 if (src_len < 1 || !src)
1194 return -EINVAL;
1195
1196 /* Zero out target struct */
1197 memset(comp_field, 0, sizeof(struct gprs_sndcp_comp_field));
1198
1199 /* Decode Propose bit and Entity number */
1200 if ((*src) & 0x80)
1201 comp_field->p = 1;
1202 comp_field->entity = (*src) & 0x1F;
1203 src_counter++;
1204 src++;
1205
1206 /* Decode algorithm number (if present) */
1207 if (comp_field->p) {
1208 comp_field->algo = (*src) & 0x1F;
1209 src_counter++;
1210 src++;
1211 }
1212 /* Alternatively take the information from the lookup table */
1213 else
1214 comp_field->algo =
1215 lookup_algorithm_identifier(comp_field->entity, lt,
1216 lt_len, compclass);
1217
1218 /* Decode length field */
1219 len = *src;
1220 src_counter++;
1221 src++;
1222
1223 /* Decode PCOMP/DCOMP values */
1224 rc = decode_comp_values(comp_field, src, compclass);
1225 if (rc < 0)
1226 return -EINVAL;
1227 src_counter += rc;
1228 src += rc;
1229 len -= rc;
1230
1231 /* Decode algorithm specific payload data */
1232 if (compclass == SNDCP_XID_PROTOCOL_COMPRESSION)
1233 rc = decode_pcomp_params(comp_field, src, len);
1234 else if (compclass == SNDCP_XID_DATA_COMPRESSION)
1235 rc = decode_dcomp_params(comp_field, src, len);
1236 else
1237 return -EINVAL;
1238
1239 if (rc >= 0)
1240 src_counter += rc;
1241 else
1242 return -EINVAL;
1243
1244 /* Return consumed length */
1245 return src_counter;
1246}
1247
1248/* Helper function for gprs_sndcp_decode_xid() to decode XID blocks */
1249static int decode_xid_block(struct llist_head *comp_fields, uint8_t tag,
1250 uint16_t tag_len, const uint8_t *val,
1251 const struct entity_algo_table *lt,
1252 unsigned int lt_len)
1253{
1254 struct gprs_sndcp_comp_field *comp_field;
1255 int byte_counter = 0;
1256 int comp_field_count = 0;
1257 int rc;
1258
1259 byte_counter = 0;
1260 do {
1261 /* Bail if more than the maximum number of
1262 comp_fields is generated */
1263 if (comp_field_count > MAX_ENTITIES * 2) {
1264 return -EINVAL;
1265 }
1266
1267 /* Parse and add comp_field */
1268 comp_field =
1269 talloc_zero(comp_fields, struct gprs_sndcp_comp_field);
1270
1271 rc = decode_comp_field(comp_field, val + byte_counter,
1272 tag_len - byte_counter, lt, lt_len, tag);
1273
1274 if (rc < 0) {
1275 talloc_free(comp_field);
1276 return -EINVAL;
1277 }
1278
1279 byte_counter += rc;
1280 llist_add(&comp_field->list, comp_fields);
1281 comp_field_count++;
1282 }
1283 while (tag_len - byte_counter > 0);
1284
1285 return byte_counter;
1286}
1287
1288/* Transform an SNDCP-XID message (src) into a list of SNDCP-XID fields */
Philippdb142dc2016-12-22 14:15:20 +01001289static int gprs_sndcp_decode_xid(int *version, struct llist_head *comp_fields,
Philipp22611be2016-08-10 12:08:03 +02001290 const uint8_t *src, unsigned int src_len,
Philippdb142dc2016-12-22 14:15:20 +01001291 const struct entity_algo_table *lt,
1292 unsigned int lt_len)
Philipp22611be2016-08-10 12:08:03 +02001293{
1294 int src_pos = 0;
1295 uint8_t tag;
1296 uint16_t tag_len;
1297 const uint8_t *val;
1298 int byte_counter = 0;
1299 int rc;
1300 int tlv_count = 0;
1301
Philippdb142dc2016-12-22 14:15:20 +01001302 /* Preset version value as invalid */
1303 if (version)
1304 *version = -1;
1305
Philipp22611be2016-08-10 12:08:03 +02001306 /* Valid TLV-Tag and types */
1307 static const struct tlv_definition sndcp_xid_def = {
1308 .def = {
1309 [SNDCP_XID_VERSION_NUMBER] = {TLV_TYPE_TLV,},
1310 [SNDCP_XID_DATA_COMPRESSION] = {TLV_TYPE_TLV,},
1311 [SNDCP_XID_PROTOCOL_COMPRESSION] = {TLV_TYPE_TLV,},
1312 },
1313 };
1314
1315 /* Parse TLV-Encoded SNDCP-XID message and defer payload
1316 to the apporpiate sub-parser functions */
1317 while (1) {
1318
1319 /* Bail if an the maximum number of TLV fields
1320 * have been parsed */
1321 if (tlv_count >= 3) {
1322 talloc_free(comp_fields);
1323 return -EINVAL;
1324 }
1325
1326 /* Parse TLV field */
1327 rc = tlv_parse_one(&tag, &tag_len, &val, &sndcp_xid_def,
1328 src + src_pos, src_len - src_pos);
1329 if (rc > 0)
1330 src_pos += rc;
1331 else {
1332 talloc_free(comp_fields);
1333 return -EINVAL;
1334 }
1335
Philippdb142dc2016-12-22 14:15:20 +01001336 /* Decode sndcp xid version number */
1337 if (version && tag == SNDCP_XID_VERSION_NUMBER)
1338 *version = val[0];
1339
Philipp22611be2016-08-10 12:08:03 +02001340 /* Decode compression parameters */
1341 if ((tag == SNDCP_XID_PROTOCOL_COMPRESSION)
1342 || (tag == SNDCP_XID_DATA_COMPRESSION)) {
1343 rc = decode_xid_block(comp_fields, tag, tag_len, val,
1344 lt, lt_len);
1345
1346 if (rc < 0) {
1347 talloc_free(comp_fields);
1348 return -EINVAL;
1349 } else
1350 byte_counter += rc;
1351 }
1352
1353 /* Stop when no further TLV elements can be expected */
1354 if (src_len - src_pos <= 2)
1355 break;
1356
1357 tlv_count++;
1358 }
1359
1360 return 0;
1361}
1362
1363/* Fill up lookutable from a list with comression entitiy fields */
1364static int gprs_sndcp_fill_table(struct
1365 entity_algo_table *lt,
1366 unsigned int lt_len,
1367 const struct llist_head *comp_fields)
1368{
1369 struct gprs_sndcp_comp_field *comp_field;
1370 int i = 0;
Philippae9beda2016-09-28 15:10:14 +02001371 int rc;
Philipp22611be2016-08-10 12:08:03 +02001372
1373 if (!comp_fields)
1374 return -EINVAL;
1375 if (!lt)
1376 return -EINVAL;
1377
Philippae9beda2016-09-28 15:10:14 +02001378 memset(lt, 0, sizeof(*lt));
Philipp22611be2016-08-10 12:08:03 +02001379
1380 llist_for_each_entry(comp_field, comp_fields, list) {
Philippae9beda2016-09-28 15:10:14 +02001381 if (comp_field->algo >= 0) {
1382 lt[i].entity = comp_field->entity;
1383 lt[i].algo = comp_field->algo;
1384 rc = gprs_sndcp_get_compression_class(comp_field);
Philipp22611be2016-08-10 12:08:03 +02001385
Philippae9beda2016-09-28 15:10:14 +02001386 if (rc < 0) {
1387 memset(lt, 0, sizeof(*lt));
1388 return -EINVAL;
1389 }
Philipp22611be2016-08-10 12:08:03 +02001390
Philippae9beda2016-09-28 15:10:14 +02001391 lt[i].compclass = rc;
1392 i++;
Philipp22611be2016-08-10 12:08:03 +02001393 }
Philipp22611be2016-08-10 12:08:03 +02001394 }
1395
1396 return i;
1397}
1398
1399/* Complete comp field params
1400 * (if a param (dst) is not valid, it will be copied from source (src) */
1401static int complete_comp_field_params(struct gprs_sndcp_comp_field
1402 *comp_field_dst, const struct
1403 gprs_sndcp_comp_field *comp_field_src)
1404{
1405 if (comp_field_dst->algo < 0)
1406 return -EINVAL;
1407
1408 if (comp_field_dst->rfc1144_params && comp_field_src->rfc1144_params) {
1409 if (comp_field_dst->rfc1144_params->s01 < 0) {
1410 comp_field_dst->rfc1144_params->s01 =
1411 comp_field_src->rfc1144_params->s01;
1412 }
1413 return 0;
1414 }
1415
1416 if (comp_field_dst->rfc2507_params && comp_field_src->rfc2507_params) {
1417
1418 if (comp_field_dst->rfc2507_params->f_max_period < 0) {
1419 comp_field_dst->rfc2507_params->f_max_period =
1420 comp_field_src->rfc2507_params->f_max_period;
1421 }
1422 if (comp_field_dst->rfc2507_params->f_max_time < 0) {
1423 comp_field_dst->rfc2507_params->f_max_time =
1424 comp_field_src->rfc2507_params->f_max_time;
1425 }
1426 if (comp_field_dst->rfc2507_params->max_header < 0) {
1427 comp_field_dst->rfc2507_params->max_header =
1428 comp_field_src->rfc2507_params->max_header;
1429 }
1430 if (comp_field_dst->rfc2507_params->tcp_space < 0) {
1431 comp_field_dst->rfc2507_params->tcp_space =
1432 comp_field_src->rfc2507_params->tcp_space;
1433 }
1434 if (comp_field_dst->rfc2507_params->non_tcp_space < 0) {
1435 comp_field_dst->rfc2507_params->non_tcp_space =
1436 comp_field_src->rfc2507_params->non_tcp_space;
1437 }
1438 return 0;
1439 }
1440
1441 if (comp_field_dst->rohc_params && comp_field_src->rohc_params) {
1442 if (comp_field_dst->rohc_params->max_cid < 0) {
1443 comp_field_dst->rohc_params->max_cid =
1444 comp_field_src->rohc_params->max_cid;
1445 }
1446 if (comp_field_dst->rohc_params->max_header < 0) {
1447 comp_field_dst->rohc_params->max_header =
1448 comp_field_src->rohc_params->max_header;
1449 }
1450 if (comp_field_dst->rohc_params->profile_len > 0) {
1451 memcpy(comp_field_dst->rohc_params->profile,
1452 comp_field_src->rohc_params->profile,
1453 sizeof(comp_field_dst->rohc_params->profile));
1454 comp_field_dst->rohc_params->profile_len =
1455 comp_field_src->rohc_params->profile_len;
1456 }
1457
1458 return 0;
1459 }
1460
1461 if (comp_field_dst->v42bis_params && comp_field_src->v42bis_params) {
1462 if (comp_field_dst->v42bis_params->p0 < 0) {
1463 comp_field_dst->v42bis_params->p0 =
1464 comp_field_src->v42bis_params->p0;
1465 }
1466 if (comp_field_dst->v42bis_params->p1 < 0) {
1467 comp_field_dst->v42bis_params->p1 =
1468 comp_field_src->v42bis_params->p1;
1469 }
1470 if (comp_field_dst->v42bis_params->p2 < 0) {
1471 comp_field_dst->v42bis_params->p2 =
1472 comp_field_src->v42bis_params->p2;
1473 }
1474 return 0;
1475 }
1476
1477 if (comp_field_dst->v44_params && comp_field_src->v44_params) {
1478 if (comp_field_dst->v44_params->c0 < 0) {
1479 comp_field_dst->v44_params->c0 =
1480 comp_field_src->v44_params->c0;
1481 }
1482 if (comp_field_dst->v44_params->p0 < 0) {
1483 comp_field_dst->v44_params->p0 =
1484 comp_field_src->v44_params->p0;
1485 }
1486 if (comp_field_dst->v44_params->p1t < 0) {
1487 comp_field_dst->v44_params->p1t =
1488 comp_field_src->v44_params->p1t;
1489 }
1490 if (comp_field_dst->v44_params->p1r < 0) {
1491 comp_field_dst->v44_params->p1r =
1492 comp_field_src->v44_params->p1r;
1493 }
1494 if (comp_field_dst->v44_params->p3t < 0) {
1495 comp_field_dst->v44_params->p3t =
1496 comp_field_src->v44_params->p3t;
1497 }
1498 if (comp_field_dst->v44_params->p3r < 0) {
1499 comp_field_dst->v44_params->p3r =
1500 comp_field_src->v44_params->p3r;
1501 }
1502 return 0;
1503 }
1504
1505 /* There should be at least exist one param set
1506 * in the destination struct, otherwise something
1507 * must be wrong! */
1508 return -EINVAL;
1509}
1510
1511/* Complete missing parameters in a comp_field */
1512static int gprs_sndcp_complete_comp_field(struct gprs_sndcp_comp_field
1513 *comp_field, const struct llist_head
1514 *comp_fields)
1515{
1516 struct gprs_sndcp_comp_field *comp_field_src;
1517 int rc = 0;
1518
1519 llist_for_each_entry(comp_field_src, comp_fields, list) {
1520 if (comp_field_src->entity == comp_field->entity) {
1521
1522 /* Complete header fields */
1523 if (comp_field_src->comp_len > 0) {
1524 memcpy(comp_field->comp,
1525 comp_field_src->comp,
1526 sizeof(comp_field_src->comp));
1527 comp_field->comp_len = comp_field_src->comp_len;
1528 }
1529
1530 /* Complete parameter fields */
1531 rc = complete_comp_field_params(comp_field,
1532 comp_field_src);
1533 }
1534 }
1535
1536 return rc;
1537}
1538
1539/* Complete missing parameters of all comp_field in a list */
1540static int gprs_sndcp_complete_comp_fields(struct llist_head
1541 *comp_fields_incomplete,
1542 const struct llist_head *comp_fields)
1543{
1544 struct gprs_sndcp_comp_field *comp_field_incomplete;
1545 int rc;
1546
1547 llist_for_each_entry(comp_field_incomplete, comp_fields_incomplete,
1548 list) {
1549
1550 rc = gprs_sndcp_complete_comp_field(comp_field_incomplete,
1551 comp_fields);
1552 if (rc < 0)
1553 return -EINVAL;
1554
1555 }
1556
1557 return 0;
1558}
1559
1560/* Transform an SNDCP-XID message (src) into a list of SNDCP-XID fields */
Philippdb142dc2016-12-22 14:15:20 +01001561struct llist_head *gprs_sndcp_parse_xid(int *version,
1562 const void *ctx,
Philipp22611be2016-08-10 12:08:03 +02001563 const uint8_t *src,
1564 unsigned int src_len,
1565 const struct llist_head
1566 *comp_fields_req)
1567{
1568 int rc;
1569 int lt_len;
1570 struct llist_head *comp_fields;
1571 struct entity_algo_table lt[MAX_ENTITIES * 2];
1572
Philippdb142dc2016-12-22 14:15:20 +01001573 /* In case of a zero length field, just exit */
1574 if (src_len == 0)
1575 return NULL;
1576
1577 /* We should go any further if we have a field length greater
1578 * zero and a null pointer as buffer! */
Philipp22611be2016-08-10 12:08:03 +02001579 OSMO_ASSERT(src);
1580
1581 comp_fields = talloc_zero(ctx, struct llist_head);
1582 INIT_LLIST_HEAD(comp_fields);
1583
1584 if (comp_fields_req) {
1585 /* Generate lookup table */
1586 lt_len =
1587 gprs_sndcp_fill_table(lt, MAX_ENTITIES * 2,
1588 comp_fields_req);
1589 if (lt_len < 0) {
1590 talloc_free(comp_fields);
1591 return NULL;
1592 }
1593
1594 /* Parse SNDCP-CID XID-Field */
Philippdb142dc2016-12-22 14:15:20 +01001595 rc = gprs_sndcp_decode_xid(version, comp_fields, src, src_len,
1596 lt, lt_len);
Philipp22611be2016-08-10 12:08:03 +02001597 if (rc < 0) {
1598 talloc_free(comp_fields);
1599 return NULL;
1600 }
1601
1602 rc = gprs_sndcp_complete_comp_fields(comp_fields,
1603 comp_fields_req);
1604 if (rc < 0) {
1605 talloc_free(comp_fields);
1606 return NULL;
1607 }
1608
1609 } else {
1610 /* Parse SNDCP-CID XID-Field */
Philippdb142dc2016-12-22 14:15:20 +01001611 rc = gprs_sndcp_decode_xid(version, comp_fields, src, src_len,
1612 NULL, 0);
Philipp22611be2016-08-10 12:08:03 +02001613 if (rc < 0) {
1614 talloc_free(comp_fields);
1615 return NULL;
1616 }
1617 }
1618
1619 return comp_fields;
1620}
1621
1622/* Helper for gprs_sndcp_dump_comp_fields(),
1623 * dumps protocol compression parameters */
1624static void dump_pcomp_params(const struct gprs_sndcp_comp_field
1625 *comp_field, unsigned int logl)
1626{
1627 int i;
1628
1629 switch (comp_field->algo) {
1630 case RFC_1144:
1631 if (comp_field->rfc1144_params == NULL) {
1632 LOGP(DSNDCP, logl,
1633 " gprs_sndcp_pcomp_rfc1144_params=NULL\n");
1634 break;
1635 }
1636 LOGP(DSNDCP, logl, " gprs_sndcp_pcomp_rfc1144_params {\n");
1637 LOGP(DSNDCP, logl,
1638 " nsapi_len=%d;\n",
1639 comp_field->rfc1144_params->nsapi_len);
1640 if (comp_field->rfc1144_params->nsapi_len == 0)
1641 LOGP(DSNDCP, logl, " nsapi[] = NULL;\n");
1642 for (i = 0; i < comp_field->rfc1144_params->nsapi_len; i++) {
1643 LOGP(DSNDCP, logl,
1644 " nsapi[%d]=%d;\n", i,
1645 comp_field->rfc1144_params->nsapi[i]);
1646 }
1647 LOGP(DSNDCP, logl, " s01=%d;\n",
1648 comp_field->rfc1144_params->s01);
1649 LOGP(DSNDCP, logl, " }\n");
1650 break;
1651 case RFC_2507:
1652 if (comp_field->rfc2507_params == NULL) {
1653 LOGP(DSNDCP, logl,
1654 " gprs_sndcp_pcomp_rfc2507_params=NULL\n");
1655 break;
1656 }
1657 LOGP(DSNDCP, logl, " gprs_sndcp_pcomp_rfc2507_params {\n");
1658 LOGP(DSNDCP, logl,
1659 " nsapi_len=%d;\n",
1660 comp_field->rfc2507_params->nsapi_len);
1661 if (comp_field->rfc2507_params->nsapi_len == 0)
1662 LOGP(DSNDCP, logl, " nsapi[] = NULL;\n");
1663 for (i = 0; i < comp_field->rfc2507_params->nsapi_len; i++) {
1664 LOGP(DSNDCP, logl,
1665 " nsapi[%d]=%d;\n", i,
1666 comp_field->rfc2507_params->nsapi[i]);
1667 }
1668 LOGP(DSNDCP, logl,
1669 " f_max_period=%d;\n",
1670 comp_field->rfc2507_params->f_max_period);
1671 LOGP(DSNDCP, logl,
1672 " f_max_time=%d;\n",
1673 comp_field->rfc2507_params->f_max_time);
1674 LOGP(DSNDCP, logl,
1675 " max_header=%d;\n",
1676 comp_field->rfc2507_params->max_header);
1677 LOGP(DSNDCP, logl,
1678 " tcp_space=%d;\n",
1679 comp_field->rfc2507_params->tcp_space);
1680 LOGP(DSNDCP, logl,
1681 " non_tcp_space=%d;\n",
1682 comp_field->rfc2507_params->non_tcp_space);
1683 LOGP(DSNDCP, logl, " }\n");
1684 break;
1685 case ROHC:
1686 if (comp_field->rohc_params == NULL) {
1687 LOGP(DSNDCP, logl,
1688 " gprs_sndcp_pcomp_rohc_params=NULL\n");
1689 break;
1690 }
1691 LOGP(DSNDCP, logl, " gprs_sndcp_pcomp_rohc_params {\n");
1692 LOGP(DSNDCP, logl,
1693 " nsapi_len=%d;\n",
1694 comp_field->rohc_params->nsapi_len);
1695 if (comp_field->rohc_params->nsapi_len == 0)
1696 LOGP(DSNDCP, logl, " nsapi[] = NULL;\n");
1697 for (i = 0; i < comp_field->rohc_params->nsapi_len; i++) {
1698 LOGP(DSNDCP, logl,
1699 " nsapi[%d]=%d;\n", i,
1700 comp_field->rohc_params->nsapi[i]);
1701 }
1702 LOGP(DSNDCP, logl,
1703 " max_cid=%d;\n", comp_field->rohc_params->max_cid);
1704 LOGP(DSNDCP, logl,
1705 " max_header=%d;\n",
1706 comp_field->rohc_params->max_header);
1707 LOGP(DSNDCP, logl,
1708 " profile_len=%d;\n",
1709 comp_field->rohc_params->profile_len);
1710 if (comp_field->rohc_params->profile_len == 0)
1711 LOGP(DSNDCP, logl, " profile[] = NULL;\n");
1712 for (i = 0; i < comp_field->rohc_params->profile_len; i++)
1713 LOGP(DSNDCP, logl,
1714 " profile[%d]=%04x;\n",
1715 i, comp_field->rohc_params->profile[i]);
1716 LOGP(DSNDCP, logl, " }\n");
1717 break;
1718 }
1719
1720}
1721
1722/* Helper for gprs_sndcp_dump_comp_fields(),
1723 * data protocol compression parameters */
1724static void dump_dcomp_params(const struct gprs_sndcp_comp_field
1725 *comp_field, unsigned int logl)
1726{
1727 int i;
1728
1729 switch (comp_field->algo) {
1730 case V42BIS:
1731 if (comp_field->v42bis_params == NULL) {
1732 LOGP(DSNDCP, logl,
1733 " gprs_sndcp_dcomp_v42bis_params=NULL\n");
1734 break;
1735 }
1736 LOGP(DSNDCP, logl, " gprs_sndcp_dcomp_v42bis_params {\n");
1737 LOGP(DSNDCP, logl,
1738 " nsapi_len=%d;\n",
1739 comp_field->v42bis_params->nsapi_len);
1740 if (comp_field->v42bis_params->nsapi_len == 0)
1741 LOGP(DSNDCP, logl, " nsapi[] = NULL;\n");
1742 for (i = 0; i < comp_field->v42bis_params->nsapi_len; i++)
1743 LOGP(DSNDCP, logl,
1744 " nsapi[%d]=%d;\n", i,
1745 comp_field->v42bis_params->nsapi[i]);
1746 LOGP(DSNDCP, logl, " p0=%d;\n",
1747 comp_field->v42bis_params->p0);
1748 LOGP(DSNDCP, logl, " p1=%d;\n",
1749 comp_field->v42bis_params->p1);
1750 LOGP(DSNDCP, logl, " p2=%d;\n",
1751 comp_field->v42bis_params->p2);
1752 LOGP(DSNDCP, logl, " }\n");
1753 break;
1754 case V44:
1755 if (comp_field->v44_params == NULL) {
1756 LOGP(DSNDCP, logl,
1757 " gprs_sndcp_dcomp_v44_params=NULL\n");
1758 break;
1759 }
1760 LOGP(DSNDCP, logl, " gprs_sndcp_dcomp_v44_params {\n");
1761 LOGP(DSNDCP, logl,
1762 " nsapi_len=%d;\n",
1763 comp_field->v44_params->nsapi_len);
1764 if (comp_field->v44_params->nsapi_len == 0)
1765 LOGP(DSNDCP, logl, " nsapi[] = NULL;\n");
1766 for (i = 0; i < comp_field->v44_params->nsapi_len; i++) {
1767 LOGP(DSNDCP, logl,
1768 " nsapi[%d]=%d;\n", i,
1769 comp_field->v44_params->nsapi[i]);
1770 }
1771 LOGP(DSNDCP, logl, " c0=%d;\n",
1772 comp_field->v44_params->c0);
1773 LOGP(DSNDCP, logl, " p0=%d;\n",
1774 comp_field->v44_params->p0);
1775 LOGP(DSNDCP, logl, " p1t=%d;\n",
1776 comp_field->v44_params->p1t);
1777 LOGP(DSNDCP, logl, " p1r=%d;\n",
1778 comp_field->v44_params->p1r);
1779 LOGP(DSNDCP, logl, " p3t=%d;\n",
1780 comp_field->v44_params->p3t);
1781 LOGP(DSNDCP, logl, " p3r=%d;\n",
1782 comp_field->v44_params->p3r);
1783 LOGP(DSNDCP, logl, " }\n");
1784 break;
1785 }
1786}
1787
1788/* Dump a list with SNDCP-XID fields (Debug) */
1789void gprs_sndcp_dump_comp_fields(const struct llist_head *comp_fields,
1790 unsigned int logl)
1791{
1792 struct gprs_sndcp_comp_field *comp_field;
1793 int i;
1794 int compclass;
1795
1796 OSMO_ASSERT(comp_fields);
1797
1798 llist_for_each_entry(comp_field, comp_fields, list) {
1799 LOGP(DSNDCP, logl, "SNDCP-XID:\n");
1800 LOGP(DSNDCP, logl, "struct gprs_sndcp_comp_field {\n");
1801 LOGP(DSNDCP, logl, " entity=%d;\n", comp_field->entity);
1802 LOGP(DSNDCP, logl, " algo=%d;\n", comp_field->algo);
1803 LOGP(DSNDCP, logl, " comp_len=%d;\n", comp_field->comp_len);
1804 if (comp_field->comp_len == 0)
1805 LOGP(DSNDCP, logl, " comp[] = NULL;\n");
1806 for (i = 0; i < comp_field->comp_len; i++) {
1807 LOGP(DSNDCP, logl, " comp[%d]=%d;\n", i,
1808 comp_field->comp[i]);
1809 }
1810
1811 compclass = gprs_sndcp_get_compression_class(comp_field);
1812
1813 if (compclass == SNDCP_XID_PROTOCOL_COMPRESSION) {
1814 dump_pcomp_params(comp_field, logl);
1815 } else if (compclass == SNDCP_XID_DATA_COMPRESSION) {
1816 dump_dcomp_params(comp_field, logl);
1817 }
1818
1819 LOGP(DSNDCP, logl, "}\n");
1820 }
1821
1822}