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