blob: 4cfb373c3d7eac7072f8a0277ecb6730bea6a819 [file] [log] [blame]
jjako52c24142002-12-16 13:33:51 +00001/*
Harald Welte632e8432017-09-05 18:12:14 +02002 * OsmoGGSN - Gateway GPRS Support Node
jjako52c24142002-12-16 13:33:51 +00003 * Copyright (C) 2002 Mondru AB.
4 *
5 * The contents of this file may be used under the terms of the GNU
6 * General Public License Version 2, provided that the above copyright
7 * notice and this permission notice is included in all copies or
8 * substantial portions of the software.
9 *
jjako52c24142002-12-16 13:33:51 +000010 */
11
12/*
13 * gtpie.c: Contains functions to encapsulate and decapsulate GTP
14 * information elements
15 *
16 *
17 * Encapsulation
18 * - gtpie_tlv, gtpie_tv0, gtpie_tv1, gtpie_tv2 ... Adds information
19 * elements to a buffer.
20 *
21 * Decapsulation
22 * - gtpie_decaps: Returns array with pointers to information elements.
23 * - getie_getie: Returns the pointer of a particular element.
24 * - gtpie_gettlv: Copies tlv information element. Return 0 on success.
25 * - gtpie_gettv: Copies tv information element. Return 0 on success.
26 *
27 */
28
jjako0fe0df02004-09-17 11:30:40 +000029#include <../config.h>
30
31#ifdef HAVE_STDINT_H
32#include <stdint.h>
33#endif
34
jjako52c24142002-12-16 13:33:51 +000035#include <stdio.h>
36#include <sys/types.h>
37#include <netinet/in.h>
38#include <string.h>
39
40#include "gtpie.h"
41
Harald Weltec5150ce2017-10-13 06:35:46 +020042/*! Encode a TLV type Information Element.
43 * \param[inout] p Pointer to output packet to which IE is appended
44 * \param[inout] length Up to which byte length is \a p used/filled
45 * \param[in] size Total size of \a p in bytes
46 * \param[in] t Tag / Information Element Identifier
47 * \param[in] l Length of value \a v in bytes
48 * \param[in] v Pointer to input value
49 * \returns 0 on success, 1 on error */
Harald Weltebed35df2011-11-02 13:06:18 +010050int gtpie_tlv(void *p, unsigned int *length, unsigned int size, uint8_t t,
Harald Welte02af9b32017-10-13 05:04:33 +020051 int l, const void *v)
Harald Weltebed35df2011-11-02 13:06:18 +010052{
53 if ((*length + 3 + l) >= size)
54 return 1;
55 ((union gtpie_member *)(p + *length))->tlv.t = hton8(t);
56 ((union gtpie_member *)(p + *length))->tlv.l = hton16(l);
57 memcpy((void *)(p + *length + 3), v, l);
58 *length += 3 + l;
59 return 0;
jjako52c24142002-12-16 13:33:51 +000060}
61
Harald Weltec5150ce2017-10-13 06:35:46 +020062/*! Encode a TV0 (Tag + value) type Information Element.
63 * \param[inout] p Pointer to output packet to which IE is appended
64 * \param[inout] length Up to which byte length is \a p used/filled
65 * \param[in] size Total size of \a p in bytes
66 * \param[in] t Tag / Information Element Identifier
67 * \param[in] l Length of value \a v in bytes
68 * \param[in] v Pointer to input value
69 * \returns 0 on success, 1 on error */
Harald Weltebed35df2011-11-02 13:06:18 +010070int gtpie_tv0(void *p, unsigned int *length, unsigned int size, uint8_t t,
Harald Welte02af9b32017-10-13 05:04:33 +020071 int l, const uint8_t * v)
Harald Weltebed35df2011-11-02 13:06:18 +010072{
73 if ((*length + 1 + l) >= size)
74 return 1;
75 ((union gtpie_member *)(p + *length))->tv0.t = hton8(t);
76 memcpy((void *)(p + *length + 1), v, l);
77 *length += 1 + l;
78 return 0;
jjako52c24142002-12-16 13:33:51 +000079}
80
Harald Weltec5150ce2017-10-13 06:35:46 +020081/*! Encode a TV1 (Tag + 8bit value) type Information Element.
82 * \param[inout] p Pointer to output packet to which IE is appended
83 * \param[inout] length Up to which byte length is \a p used/filled
84 * \param[in] size Total size of \a p in bytes
85 * \param[in] t Tag / Information Element Identifier
86 * \param[in] v Input value
87 * \returns 0 on success, 1 on error */
Harald Weltebed35df2011-11-02 13:06:18 +010088int gtpie_tv1(void *p, unsigned int *length, unsigned int size, uint8_t t,
89 uint8_t v)
90{
91 if ((*length + 2) >= size)
92 return 1;
93 ((union gtpie_member *)(p + *length))->tv1.t = hton8(t);
94 ((union gtpie_member *)(p + *length))->tv1.v = hton8(v);
95 *length += 2;
96 return 0;
jjako52c24142002-12-16 13:33:51 +000097}
98
Harald Weltec5150ce2017-10-13 06:35:46 +020099/*! Encode a TV2 (Tag + 16bit value) type Information Element.
100 * \param[inout] p Pointer to output packet to which IE is appended
101 * \param[inout] length Up to which byte length is \a p used/filled
102 * \param[in] size Total size of \a p in bytes
103 * \param[in] t Tag / Information Element Identifier
104 * \param[in] v Input value
105 * \returns 0 on success, 1 on error */
Harald Weltebed35df2011-11-02 13:06:18 +0100106int gtpie_tv2(void *p, unsigned int *length, unsigned int size, uint8_t t,
107 uint16_t v)
108{
109 if ((*length + 3) >= size)
110 return 1;
111 ((union gtpie_member *)(p + *length))->tv2.t = hton8(t);
112 ((union gtpie_member *)(p + *length))->tv2.v = hton16(v);
113 *length += 3;
114 return 0;
jjako52c24142002-12-16 13:33:51 +0000115}
116
Harald Weltec5150ce2017-10-13 06:35:46 +0200117/*! Encode a TV4 (Tag + 32bit value) type Information Element.
118 * \param[inout] p Pointer to output packet to which IE is appended
119 * \param[inout] length Up to which byte length is \a p used/filled
120 * \param[in] size Total size of \a p in bytes
121 * \param[in] t Tag / Information Element Identifier
122 * \param[in] v Input value
123 * \returns 0 on success, 1 on error */
Harald Weltebed35df2011-11-02 13:06:18 +0100124int gtpie_tv4(void *p, unsigned int *length, unsigned int size, uint8_t t,
125 uint32_t v)
126{
127 if ((*length + 5) >= size)
128 return 1;
129 ((union gtpie_member *)(p + *length))->tv4.t = hton8(t);
130 ((union gtpie_member *)(p + *length))->tv4.v = hton32(v);
131 *length += 5;
132 return 0;
jjako52c24142002-12-16 13:33:51 +0000133}
134
Harald Weltec5150ce2017-10-13 06:35:46 +0200135/*! Encode a TV8 (Tag + 64bit value) type Information Element.
136 * \param[inout] p Pointer to output packet to which IE is appended
137 * \param[inout] length Up to which byte length is \a p used/filled
138 * \param[in] size Total size of \a p in bytes
139 * \param[in] t Tag / Information Element Identifier
140 * \param[in] v Input value
141 * \returns 0 on success, 1 on error */
Harald Weltebed35df2011-11-02 13:06:18 +0100142int gtpie_tv8(void *p, unsigned int *length, unsigned int size, uint8_t t,
143 uint64_t v)
144{
145 if ((*length + 9) >= size)
146 return 1;
147 ((union gtpie_member *)(p + *length))->tv8.t = hton8(t);
148 ((union gtpie_member *)(p + *length))->tv8.v = hton64(v);
149 *length += 9;
150 return 0;
jjako08d331d2003-10-13 20:33:30 +0000151}
152
Harald Weltec5150ce2017-10-13 06:35:46 +0200153/*! Obtain a GTP IE for a given tag/IEI from a list/array.
154 * \param[in] ie Array of GTPIE
155 * \param[in] type Tag/IEI for which we're looking
156 * \param[in] instance Instance (number of occurence) of this IEI
157 * \returns index into \a ie on success; -1 if not found */
Harald Weltebed35df2011-11-02 13:06:18 +0100158int gtpie_getie(union gtpie_member *ie[], int type, int instance)
159{
160 int j;
161 for (j = 0; j < GTPIE_SIZE; j++) {
162 if ((ie[j] != 0) && (ie[j]->t == type)) {
163 if (instance-- == 0)
164 return j;
165 }
jjako08d331d2003-10-13 20:33:30 +0000166 }
Harald Weltebed35df2011-11-02 13:06:18 +0100167 return -1;
jjako52c24142002-12-16 13:33:51 +0000168}
169
Harald Weltec5150ce2017-10-13 06:35:46 +0200170/*! Determine if IE for a given tag/IEI exists in a list/array.
171 * \param[in] ie Array of GTPIE
172 * \param[in] type Tag/IEI for which we're looking
173 * \param[in] instance Instance (number of occurence) of this IEI
174 * \returns 1 if IEI instance present in \a ie; 0 if not */
Harald Weltebed35df2011-11-02 13:06:18 +0100175int gtpie_exist(union gtpie_member *ie[], int type, int instance)
176{
177 int j;
178 for (j = 0; j < GTPIE_SIZE; j++) {
179 if ((ie[j] != 0) && (ie[j]->t == type)) {
180 if (instance-- == 0)
181 return 1;
182 }
183 }
184 return 0;
185}
jjako52c24142002-12-16 13:33:51 +0000186
Harald Weltec5150ce2017-10-13 06:35:46 +0200187/*! Obtain Value of TLV-type IE for a given tag/IEI from a list/array.
188 * \param[in] ie Array of GTPIE
189 * \param[in] type Tag/IEI for which we're looking
190 * \param[in] instance Instance (number of occurence) of this IEI
191 * \param[out] length Length of IE
192 * \param[inout] dst Caller-allocated buffer where to store value
193 * \param[in] size Size of \a dst in bytes
194 * \returns 0 on sucess; EOF in case value is larger than \a size */
Harald Weltebed35df2011-11-02 13:06:18 +0100195int gtpie_gettlv(union gtpie_member *ie[], int type, int instance,
196 unsigned int *length, void *dst, unsigned int size)
197{
198 int ien;
199 ien = gtpie_getie(ie, type, instance);
200 if (ien >= 0) {
201 *length = ntoh16(ie[ien]->tlv.l);
202 if (*length <= size)
203 memcpy(dst, ie[ien]->tlv.v, *length);
204 else
205 return EOF;
206 }
207 return 0;
208}
209
Harald Weltec5150ce2017-10-13 06:35:46 +0200210/*! Obtain Value of TV0-type IE for a given tag/IEI from a list/array.
211 * \param[in] ie Array of GTPIE
212 * \param[in] type Tag/IEI for which we're looking
213 * \param[in] instance Instance (number of occurence) of this IEI
214 * \param[inout] dst Caller-allocated buffer where to store value
215 * \param[in] size Size of value in bytes
216 * \returns 0 on sucess; EOF in case IE not found */
Harald Weltebed35df2011-11-02 13:06:18 +0100217int gtpie_gettv0(union gtpie_member *ie[], int type, int instance,
218 void *dst, unsigned int size)
219{
220 int ien;
221 ien = gtpie_getie(ie, type, instance);
222 if (ien >= 0)
223 memcpy(dst, ie[ien]->tv0.v, size);
224 else
225 return EOF;
226 return 0;
227}
228
Harald Weltec5150ce2017-10-13 06:35:46 +0200229/*! Obtain Value of TV1-type IE for a given tag/IEI from a list/array.
230 * \param[in] ie Array of GTPIE
231 * \param[in] type Tag/IEI for which we're looking
232 * \param[in] instance Instance (number of occurence) of this IEI
233 * \param[inout] dst Caller-allocated buffer where to store value
234 * \returns 0 on sucess; EOF in case IE not found */
Harald Weltebed35df2011-11-02 13:06:18 +0100235int gtpie_gettv1(union gtpie_member *ie[], int type, int instance,
236 uint8_t * dst)
237{
238 int ien;
239 ien = gtpie_getie(ie, type, instance);
240 if (ien >= 0)
241 *dst = ntoh8(ie[ien]->tv1.v);
242 else
243 return EOF;
244 return 0;
245}
246
Harald Weltec5150ce2017-10-13 06:35:46 +0200247/*! Obtain Value of TV2-type IE for a given tag/IEI from a list/array.
248 * \param[in] ie Array of GTPIE
249 * \param[in] type Tag/IEI for which we're looking
250 * \param[in] instance Instance (number of occurence) of this IEI
251 * \param[inout] dst Caller-allocated buffer where to store value
252 * \returns 0 on sucess; EOF in case IE not found */
Harald Weltebed35df2011-11-02 13:06:18 +0100253int gtpie_gettv2(union gtpie_member *ie[], int type, int instance,
254 uint16_t * dst)
255{
256 int ien;
257 ien = gtpie_getie(ie, type, instance);
258 if (ien >= 0)
259 *dst = ntoh16(ie[ien]->tv2.v);
260 else
261 return EOF;
262 return 0;
263}
264
Harald Weltec5150ce2017-10-13 06:35:46 +0200265/*! Obtain Value of TV4-type IE for a given tag/IEI from a list/array.
266 * \param[in] ie Array of GTPIE
267 * \param[in] type Tag/IEI for which we're looking
268 * \param[in] instance Instance (number of occurence) of this IEI
269 * \param[inout] dst Caller-allocated buffer where to store value
270 * \returns 0 on sucess; EOF in case IE not found */
Harald Weltebed35df2011-11-02 13:06:18 +0100271int gtpie_gettv4(union gtpie_member *ie[], int type, int instance,
272 uint32_t * dst)
273{
274 int ien;
275 ien = gtpie_getie(ie, type, instance);
276 if (ien >= 0)
277 *dst = ntoh32(ie[ien]->tv4.v);
278 else
279 return EOF;
280 return 0;
281}
282
Harald Weltec5150ce2017-10-13 06:35:46 +0200283/*! Obtain Value of TV8-type IE for a given tag/IEI from a list/array.
284 * \param[in] ie Array of GTPIE
285 * \param[in] type Tag/IEI for which we're looking
286 * \param[in] instance Instance (number of occurence) of this IEI
287 * \param[inout] dst Caller-allocated buffer where to store value
288 * \returns 0 on sucess; EOF in case IE not found */
Harald Weltebed35df2011-11-02 13:06:18 +0100289int gtpie_gettv8(union gtpie_member *ie[], int type, int instance,
290 uint64_t * dst)
291{
292 int ien;
293 ien = gtpie_getie(ie, type, instance);
294 if (ien >= 0)
295 *dst = ntoh64(ie[ien]->tv8.v);
296 else
297 return EOF;
298 return 0;
299}
300
Harald Weltec5150ce2017-10-13 06:35:46 +0200301/*! Parse an incoming GTP packet into its Information Elements.
302 * \param[out] ie Caller-allocated Array of GTPIE
303 * \param[in] version GTP protocol version
304 * \param[in] pack Pointer to raw GTP packet (payload part)
305 * \param[in] len Length of \a pack in bytes
306 * \returns 0 on sucess; EOF in case IE not found */
Harald Weltebed35df2011-11-02 13:06:18 +0100307int gtpie_decaps(union gtpie_member *ie[], int version, void *pack,
308 unsigned len)
309{
310 int i;
311 int j = 0;
312 unsigned char *p;
313 unsigned char *end;
314
315 end = (unsigned char *)pack + len;
316 p = pack;
317
318 memset(ie, 0, sizeof(union gtpie_member *) * GTPIE_SIZE);
319
320 while ((p < end) && (j < GTPIE_SIZE)) {
321 if (GTPIE_DEBUG) {
322 printf("The packet looks like this:\n");
323 for (i = 0; i < (end - p); i++) {
324 printf("%02x ",
325 (unsigned char)*(char *)(p + i));
326 if (!((i + 1) % 16))
327 printf("\n");
328 };
329 printf("\n");
330 }
331
332 switch (*p) {
333 case GTPIE_CAUSE: /* TV GTPIE types with value length 1 */
334 case GTPIE_REORDER:
335 case GTPIE_MAP_CAUSE:
336 case GTPIE_MS_VALIDATED:
337 case GTPIE_RECOVERY:
338 case GTPIE_SELECTION_MODE:
339 case GTPIE_TEARDOWN:
340 case GTPIE_NSAPI:
341 case GTPIE_RANAP_CAUSE:
342 case GTPIE_RP_SMS:
343 case GTPIE_RP:
344 case GTPIE_MS_NOT_REACH:
BJovke03dbafb2016-09-15 13:41:41 +0200345 case GTPIE_BCM:
Harald Weltebed35df2011-11-02 13:06:18 +0100346 if (j < GTPIE_SIZE) {
347 ie[j] = (union gtpie_member *)p;
348 if (GTPIE_DEBUG)
349 printf
350 ("GTPIE TV1 found. Type %d, value %d\n",
351 ie[j]->tv1.t, ie[j]->tv1.v);
352 p += 1 + 1;
353 j++;
354 }
355 break;
356 case GTPIE_FL_DI: /* TV GTPIE types with value length 2 or 4 */
357 case GTPIE_FL_C:
358 if (version != 0) {
359 if (j < GTPIE_SIZE) { /* GTPIE_TEI_DI & GTPIE_TEI_C with length 4 */
360 /* case GTPIE_TEI_DI: gtp1 */
361 /* case GTPIE_TEI_C: gtp1 */
362 ie[j] = (union gtpie_member *)p;
363 if (GTPIE_DEBUG)
364 printf
365 ("GTPIE TV 4 found. Type %d, value %d\n",
366 ie[j]->tv4.t,
367 ie[j]->tv4.v);
368 p += 1 + 4;
369 j++;
370 }
371 break;
372 }
373 case GTPIE_PFI: /* TV GTPIE types with value length 2 */
374 case GTPIE_CHARGING_C:
375 case GTPIE_TRACE_REF:
376 case GTPIE_TRACE_TYPE:
377 if (j < GTPIE_SIZE) {
378 ie[j] = (union gtpie_member *)p;
379 if (GTPIE_DEBUG)
380 printf
381 ("GTPIE TV2 found. Type %d, value %d\n",
382 ie[j]->tv2.t, ie[j]->tv2.v);
383 p += 1 + 2;
384 j++;
385 }
386 break;
387 case GTPIE_QOS_PROFILE0: /* TV GTPIE types with value length 3 */
388 case GTPIE_P_TMSI_S:
389 if (j < GTPIE_SIZE) {
390 ie[j] = (union gtpie_member *)p;
391 if (GTPIE_DEBUG)
392 printf
393 ("GTPIE TV 3 found. Type %d, value %d, %d, %d\n",
394 ie[j]->tv0.t, ie[j]->tv0.v[0],
395 ie[j]->tv0.v[1], ie[j]->tv0.v[2]);
396 p += 1 + 3;
397 j++;
398 }
399 break;
400 case GTPIE_TLLI: /* TV GTPIE types with value length 4 */
401 case GTPIE_P_TMSI:
402 case GTPIE_CHARGING_ID:
403 /* case GTPIE_TEI_DI: Handled by GTPIE_FL_DI */
404 /* case GTPIE_TEI_C: Handled by GTPIE_FL_DI */
405 if (j < GTPIE_SIZE) {
406 ie[j] = (union gtpie_member *)p;
407 if (GTPIE_DEBUG)
408 printf
409 ("GTPIE TV 4 found. Type %d, value %d\n",
410 ie[j]->tv4.t, ie[j]->tv4.v);
411 p += 1 + 4;
412 j++;
413 }
414 break;
415 case GTPIE_TEI_DII: /* TV GTPIE types with value length 5 */
416 if (j < GTPIE_SIZE) {
417 ie[j] = (union gtpie_member *)p;
418 if (GTPIE_DEBUG)
419 printf("GTPIE TV 5 found. Type %d\n",
420 ie[j]->tv0.t);
421 p += 1 + 5;
422 j++;
423 }
424 break;
425 case GTPIE_RAB_CONTEXT: /* TV GTPIE types with value length 7 */
426 if (j < GTPIE_SIZE) {
427 ie[j] = (union gtpie_member *)p;
428 if (GTPIE_DEBUG)
429 printf("GTPIE TV 7 found. Type %d\n",
430 ie[j]->tv0.t);
431 p += 1 + 7;
432 j++;
433 }
434 break;
435 case GTPIE_IMSI: /* TV GTPIE types with value length 8 */
436 if (j < GTPIE_SIZE) {
437 ie[j] = (union gtpie_member *)p;
438 if (GTPIE_DEBUG)
439 printf
440 ("GTPIE_IMSI - GTPIE TV 8 found. Type %d, value 0x%llx\n",
441 ie[j]->tv0.t, ie[j]->tv8.v);
442 p += 1 + 8;
443 j++;
444 }
445 break;
446 case GTPIE_RAI: /* TV GTPIE types with value length 6 */
447 if (j < GTPIE_SIZE) {
448 ie[j] = (union gtpie_member *)p;
449 if (GTPIE_DEBUG)
450 printf
451 ("GTPIE_RAI - GTPIE TV 6 found. Type %d, value 0x%llx\n",
452 ie[j]->tv0.t, ie[j]->tv8.v);
453 p += 1 + 6;
454 j++;
455 }
456 break;
457 case GTPIE_AUTH_TRIPLET: /* TV GTPIE types with value length 28 */
458 if (j < GTPIE_SIZE) {
459 ie[j] = (union gtpie_member *)p;
460 if (GTPIE_DEBUG)
461 printf("GTPIE TV 28 found. Type %d\n",
462 ie[j]->tv0.t);
463 p += 1 + 28;
464 j++;
465 }
466 break;
467 case GTPIE_EXT_HEADER_T: /* GTP extension header */
468 if (j < GTPIE_SIZE) {
469 ie[j] = (union gtpie_member *)p;
470 if (GTPIE_DEBUG)
471 printf
472 ("GTPIE GTP extension header found. Type %d\n",
473 ie[j]->ext.t);
474 p += 2 + ntoh8(ie[j]->ext.l);
475 j++;
476 }
477 break;
478 case GTPIE_EUA: /* TLV GTPIE types with variable length */
479 case GTPIE_MM_CONTEXT:
480 case GTPIE_PDP_CONTEXT:
481 case GTPIE_APN:
482 case GTPIE_PCO:
483 case GTPIE_GSN_ADDR:
484 case GTPIE_MSISDN:
485 case GTPIE_QOS_PROFILE:
486 case GTPIE_AUTH_QUINTUP:
487 case GTPIE_TFT:
488 case GTPIE_TARGET_INF:
489 case GTPIE_UTRAN_TRANS:
490 case GTPIE_RAB_SETUP:
491 case GTPIE_TRIGGER_ID:
492 case GTPIE_OMC_ID:
493 case GTPIE_CHARGING_ADDR:
494 case GTPIE_RAT_TYPE:
495 case GTPIE_USER_LOC:
496 case GTPIE_MS_TZ:
497 case GTPIE_IMEI_SV:
498 case GTPIE_PRIVATE:
499 if (j < GTPIE_SIZE) {
500 ie[j] = (union gtpie_member *)p;
501 if (GTPIE_DEBUG)
502 printf("GTPIE TLV found. Type %d\n",
503 ie[j]->tlv.t);
504 p += 3 + ntoh16(ie[j]->tlv.l);
505 j++;
506 }
507 break;
508 default:
509 if (GTPIE_DEBUG)
510 printf("GTPIE something unknown. Type %d\n",
511 *p);
512 return EOF; /* We received something unknown */
513 }
514 }
515 if (p == end) {
516 if (GTPIE_DEBUG)
517 printf("GTPIE normal return. %lx %lx\n",
518 (unsigned long)p, (unsigned long)end);
519 return 0; /* We landed at the end of the packet: OK */
520 } else if (!(j < GTPIE_SIZE)) {
521 if (GTPIE_DEBUG)
522 printf("GTPIE too many elements.\n");
523 return EOF; /* We received too many information elements */
524 } else {
525 if (GTPIE_DEBUG)
526 printf("GTPIE exceeded end of packet. %lx %lx\n",
527 (unsigned long)p, (unsigned long)end);
528 return EOF; /* We exceeded the end of the packet: Error */
529 }
530}
531
Harald Weltec5150ce2017-10-13 06:35:46 +0200532/*! Encode GTP packet payload from Array of Information Elements.
533 * \param[out] ie Input Array of GTPIE
534 * \param[out] pack Pointer to caller-allocated buffer for raw GTP packet (GTPIE_MAX length)
535 * \param[out] len Encoded length of \a pack in bytes
536 * \returns 0 on sucess; 2 for out-of-space */
Harald Weltebed35df2011-11-02 13:06:18 +0100537int gtpie_encaps(union gtpie_member *ie[], void *pack, unsigned *len)
538{
539 int i;
540 unsigned char *p;
541 unsigned char *end;
Harald Weltebed35df2011-11-02 13:06:18 +0100542 int iesize;
543
544 p = pack;
545
546 memset(pack, 0, GTPIE_MAX);
547 end = p + GTPIE_MAX;
548 for (i = 1; i < GTPIE_SIZE; i++)
549 if (ie[i] != 0) {
550 if (GTPIE_DEBUG)
551 printf("gtpie_encaps. Type %d\n", i);
Harald Weltebed35df2011-11-02 13:06:18 +0100552 switch (i) {
553 case GTPIE_CAUSE: /* TV GTPIE types with value length 1 */
554 case GTPIE_REORDER:
555 case GTPIE_MAP_CAUSE:
556 case GTPIE_MS_VALIDATED:
557 case GTPIE_RECOVERY:
558 case GTPIE_SELECTION_MODE:
559 case GTPIE_TEARDOWN:
560 case GTPIE_NSAPI:
561 case GTPIE_RANAP_CAUSE:
562 case GTPIE_RP_SMS:
563 case GTPIE_RP:
564 case GTPIE_MS_NOT_REACH:
BJovke03dbafb2016-09-15 13:41:41 +0200565 case GTPIE_BCM:
Harald Weltebed35df2011-11-02 13:06:18 +0100566 iesize = 2;
567 break;
568 case GTPIE_FL_DI: /* TV GTPIE types with value length 2 */
569 case GTPIE_FL_C:
570 case GTPIE_PFI:
571 case GTPIE_CHARGING_C:
572 case GTPIE_TRACE_REF:
573 case GTPIE_TRACE_TYPE:
574 iesize = 3;
575 break;
576 case GTPIE_QOS_PROFILE0: /* TV GTPIE types with value length 3 */
577 case GTPIE_P_TMSI_S:
578 iesize = 4;
579 break;
580 case GTPIE_TLLI: /* TV GTPIE types with value length 4 */
581 case GTPIE_P_TMSI:
582 /* case GTPIE_TEI_DI: only in gtp1 */
583 /* case GTPIE_TEI_C: only in gtp1 */
584 case GTPIE_CHARGING_ID:
585 iesize = 5;
586 break;
587 case GTPIE_TEI_DII: /* TV GTPIE types with value length 5 */
588 iesize = 6;
589 break;
590 case GTPIE_RAB_CONTEXT: /* TV GTPIE types with value length 7 */
591 iesize = 8;
592 break;
593 case GTPIE_IMSI: /* TV GTPIE types with value length 8 */
594 case GTPIE_RAI:
595 iesize = 9;
596 break;
597 case GTPIE_AUTH_TRIPLET: /* TV GTPIE types with value length 28 */
598 iesize = 29;
599 break;
600 case GTPIE_EXT_HEADER_T: /* GTP extension header */
601 iesize = 2 + hton8(ie[i]->ext.l);
602 break;
603 case GTPIE_EUA: /* TLV GTPIE types with length length 2 */
604 case GTPIE_MM_CONTEXT:
605 case GTPIE_PDP_CONTEXT:
606 case GTPIE_APN:
607 case GTPIE_PCO:
608 case GTPIE_GSN_ADDR:
609 case GTPIE_MSISDN:
610 case GTPIE_QOS_PROFILE:
611 case GTPIE_AUTH_QUINTUP:
612 case GTPIE_TFT:
613 case GTPIE_TARGET_INF:
614 case GTPIE_UTRAN_TRANS:
615 case GTPIE_RAB_SETUP:
616 case GTPIE_TRIGGER_ID:
617 case GTPIE_OMC_ID:
618 case GTPIE_CHARGING_ADDR:
619 case GTPIE_PRIVATE:
620 iesize = 3 + hton16(ie[i]->tlv.l);
621 break;
622 default:
623 return 2; /* We received something unknown */
624 }
625 if (p + iesize < end) {
626 memcpy(p, ie[i], iesize);
627 p += iesize;
628 *len += iesize;
629 } else
630 return 2; /* Out of space */
631 }
632 return 0;
jjako52c24142002-12-16 13:33:51 +0000633}
634
Harald Weltec5150ce2017-10-13 06:35:46 +0200635/*! Encode GTP packet payload from Array of Information Elements.
636 * \param[out] ie Input Array of GTPIE
637 * \param[in] size Size of ?
638 * \param[out] pack Pointer to caller-allocated buffer for raw GTP packet (GTPIE_MAX length)
639 * \param[out] len Encoded length of \a pack in bytes
640 * \returns 0 on sucess; 2 for out-of-space */
Harald Weltef54a1f42010-05-04 11:08:38 +0200641int gtpie_encaps2(union gtpie_member ie[], unsigned int size,
Harald Weltebed35df2011-11-02 13:06:18 +0100642 void *pack, unsigned *len)
643{
644 unsigned int i, j;
645 unsigned char *p;
646 unsigned char *end;
Harald Weltebed35df2011-11-02 13:06:18 +0100647 int iesize;
jjako52c24142002-12-16 13:33:51 +0000648
Harald Weltebed35df2011-11-02 13:06:18 +0100649 p = pack;
650
651 memset(pack, 0, GTPIE_MAX);
652 end = p + GTPIE_MAX;
653 for (j = 0; j < GTPIE_SIZE; j++)
654 for (i = 0; i < size; i++)
655 if (ie[i].t == j) {
656 if (GTPIE_DEBUG)
657 printf
658 ("gtpie_encaps. Number %d, Type %d\n",
659 i, ie[i].t);
Harald Weltebed35df2011-11-02 13:06:18 +0100660 switch (ie[i].t) {
661 case GTPIE_CAUSE: /* TV GTPIE types with value length 1 */
662 case GTPIE_REORDER:
663 case GTPIE_MAP_CAUSE:
664 case GTPIE_MS_VALIDATED:
665 case GTPIE_RECOVERY:
666 case GTPIE_SELECTION_MODE:
667 case GTPIE_TEARDOWN:
668 case GTPIE_NSAPI:
669 case GTPIE_RANAP_CAUSE:
670 case GTPIE_RP_SMS:
671 case GTPIE_RP:
672 case GTPIE_MS_NOT_REACH:
BJovke03dbafb2016-09-15 13:41:41 +0200673 case GTPIE_BCM:
Harald Weltebed35df2011-11-02 13:06:18 +0100674 iesize = 2;
675 break;
676 case GTPIE_PFI: /* TV GTPIE types with value length 2 */
677 case GTPIE_CHARGING_C:
678 case GTPIE_TRACE_REF:
679 case GTPIE_TRACE_TYPE:
680 iesize = 3;
681 break;
682 case GTPIE_QOS_PROFILE0: /* TV GTPIE types with value length 3 */
683 case GTPIE_P_TMSI_S:
684 iesize = 4;
685 break;
686 case GTPIE_TLLI: /* TV GTPIE types with value length 4 */
687 case GTPIE_P_TMSI:
688 case GTPIE_TEI_DI:
689 case GTPIE_TEI_C:
690 iesize = 5;
691 break;
692 case GTPIE_TEI_DII: /* TV GTPIE types with value length 5 */
693 iesize = 6;
694 break;
695 case GTPIE_RAB_CONTEXT: /* TV GTPIE types with value length 7 */
696 iesize = 8;
697 break;
698 case GTPIE_IMSI: /* TV GTPIE types with value length 8 */
699 case GTPIE_RAI:
700 iesize = 9;
701 break;
702 case GTPIE_AUTH_TRIPLET: /* TV GTPIE types with value length 28 */
703 iesize = 29;
704 break;
705 case GTPIE_EXT_HEADER_T: /* GTP extension header */
706 iesize = 2 + hton8(ie[i].ext.l);
707 break;
708 case GTPIE_CHARGING_ID: /* TLV GTPIE types with length length 2 */
709 case GTPIE_EUA:
710 case GTPIE_MM_CONTEXT:
711 case GTPIE_PDP_CONTEXT:
712 case GTPIE_APN:
713 case GTPIE_PCO:
714 case GTPIE_GSN_ADDR:
715 case GTPIE_MSISDN:
716 case GTPIE_QOS_PROFILE:
717 case GTPIE_AUTH_QUINTUP:
718 case GTPIE_TFT:
719 case GTPIE_TARGET_INF:
720 case GTPIE_UTRAN_TRANS:
721 case GTPIE_RAB_SETUP:
722 case GTPIE_TRIGGER_ID:
723 case GTPIE_OMC_ID:
724 case GTPIE_CHARGING_ADDR:
725 case GTPIE_PRIVATE:
726 iesize = 3 + hton16(ie[i].tlv.l);
727 break;
728 default:
729 return 2; /* We received something unknown */
730 }
731 if (p + iesize < end) {
732 memcpy(p, &ie[i], iesize);
733 p += iesize;
734 *len += iesize;
735 } else
736 return 2; /* Out of space */
737 }
738 return 0;
jjako52c24142002-12-16 13:33:51 +0000739}