blob: 232183e4d5eb967cd279137ab41f30e665781f40 [file] [log] [blame]
jjako52c24142002-12-16 13:33:51 +00001/*
2 * OpenGGSN - Gateway GPRS Support Node
3 * 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 Weltebed35df2011-11-02 13:06:18 +010042int gtpie_tlv(void *p, unsigned int *length, unsigned int size, uint8_t t,
43 int l, void *v)
44{
45 if ((*length + 3 + l) >= size)
46 return 1;
47 ((union gtpie_member *)(p + *length))->tlv.t = hton8(t);
48 ((union gtpie_member *)(p + *length))->tlv.l = hton16(l);
49 memcpy((void *)(p + *length + 3), v, l);
50 *length += 3 + l;
51 return 0;
jjako52c24142002-12-16 13:33:51 +000052}
53
Harald Weltebed35df2011-11-02 13:06:18 +010054int gtpie_tv0(void *p, unsigned int *length, unsigned int size, uint8_t t,
55 int l, uint8_t * v)
56{
57 if ((*length + 1 + l) >= size)
58 return 1;
59 ((union gtpie_member *)(p + *length))->tv0.t = hton8(t);
60 memcpy((void *)(p + *length + 1), v, l);
61 *length += 1 + l;
62 return 0;
jjako52c24142002-12-16 13:33:51 +000063}
64
Harald Weltebed35df2011-11-02 13:06:18 +010065int gtpie_tv1(void *p, unsigned int *length, unsigned int size, uint8_t t,
66 uint8_t v)
67{
68 if ((*length + 2) >= size)
69 return 1;
70 ((union gtpie_member *)(p + *length))->tv1.t = hton8(t);
71 ((union gtpie_member *)(p + *length))->tv1.v = hton8(v);
72 *length += 2;
73 return 0;
jjako52c24142002-12-16 13:33:51 +000074}
75
Harald Weltebed35df2011-11-02 13:06:18 +010076int gtpie_tv2(void *p, unsigned int *length, unsigned int size, uint8_t t,
77 uint16_t v)
78{
79 if ((*length + 3) >= size)
80 return 1;
81 ((union gtpie_member *)(p + *length))->tv2.t = hton8(t);
82 ((union gtpie_member *)(p + *length))->tv2.v = hton16(v);
83 *length += 3;
84 return 0;
jjako52c24142002-12-16 13:33:51 +000085}
86
Harald Weltebed35df2011-11-02 13:06:18 +010087int gtpie_tv4(void *p, unsigned int *length, unsigned int size, uint8_t t,
88 uint32_t v)
89{
90 if ((*length + 5) >= size)
91 return 1;
92 ((union gtpie_member *)(p + *length))->tv4.t = hton8(t);
93 ((union gtpie_member *)(p + *length))->tv4.v = hton32(v);
94 *length += 5;
95 return 0;
jjako52c24142002-12-16 13:33:51 +000096}
97
Harald Weltebed35df2011-11-02 13:06:18 +010098int gtpie_tv8(void *p, unsigned int *length, unsigned int size, uint8_t t,
99 uint64_t v)
100{
101 if ((*length + 9) >= size)
102 return 1;
103 ((union gtpie_member *)(p + *length))->tv8.t = hton8(t);
104 ((union gtpie_member *)(p + *length))->tv8.v = hton64(v);
105 *length += 9;
106 return 0;
jjako08d331d2003-10-13 20:33:30 +0000107}
108
Harald Weltebed35df2011-11-02 13:06:18 +0100109int gtpie_getie(union gtpie_member *ie[], int type, int instance)
110{
111 int j;
112 for (j = 0; j < GTPIE_SIZE; j++) {
113 if ((ie[j] != 0) && (ie[j]->t == type)) {
114 if (instance-- == 0)
115 return j;
116 }
jjako08d331d2003-10-13 20:33:30 +0000117 }
Harald Weltebed35df2011-11-02 13:06:18 +0100118 return -1;
jjako52c24142002-12-16 13:33:51 +0000119}
120
Harald Weltebed35df2011-11-02 13:06:18 +0100121int gtpie_exist(union gtpie_member *ie[], int type, int instance)
122{
123 int j;
124 for (j = 0; j < GTPIE_SIZE; j++) {
125 if ((ie[j] != 0) && (ie[j]->t == type)) {
126 if (instance-- == 0)
127 return 1;
128 }
129 }
130 return 0;
131}
jjako52c24142002-12-16 13:33:51 +0000132
Harald Weltebed35df2011-11-02 13:06:18 +0100133int gtpie_gettlv(union gtpie_member *ie[], int type, int instance,
134 unsigned int *length, void *dst, unsigned int size)
135{
136 int ien;
137 ien = gtpie_getie(ie, type, instance);
138 if (ien >= 0) {
139 *length = ntoh16(ie[ien]->tlv.l);
140 if (*length <= size)
141 memcpy(dst, ie[ien]->tlv.v, *length);
142 else
143 return EOF;
144 }
145 return 0;
146}
147
148int gtpie_gettv0(union gtpie_member *ie[], int type, int instance,
149 void *dst, unsigned int size)
150{
151 int ien;
152 ien = gtpie_getie(ie, type, instance);
153 if (ien >= 0)
154 memcpy(dst, ie[ien]->tv0.v, size);
155 else
156 return EOF;
157 return 0;
158}
159
160int gtpie_gettv1(union gtpie_member *ie[], int type, int instance,
161 uint8_t * dst)
162{
163 int ien;
164 ien = gtpie_getie(ie, type, instance);
165 if (ien >= 0)
166 *dst = ntoh8(ie[ien]->tv1.v);
167 else
168 return EOF;
169 return 0;
170}
171
172int gtpie_gettv2(union gtpie_member *ie[], int type, int instance,
173 uint16_t * dst)
174{
175 int ien;
176 ien = gtpie_getie(ie, type, instance);
177 if (ien >= 0)
178 *dst = ntoh16(ie[ien]->tv2.v);
179 else
180 return EOF;
181 return 0;
182}
183
184int gtpie_gettv4(union gtpie_member *ie[], int type, int instance,
185 uint32_t * dst)
186{
187 int ien;
188 ien = gtpie_getie(ie, type, instance);
189 if (ien >= 0)
190 *dst = ntoh32(ie[ien]->tv4.v);
191 else
192 return EOF;
193 return 0;
194}
195
196int gtpie_gettv8(union gtpie_member *ie[], int type, int instance,
197 uint64_t * dst)
198{
199 int ien;
200 ien = gtpie_getie(ie, type, instance);
201 if (ien >= 0)
202 *dst = ntoh64(ie[ien]->tv8.v);
203 else
204 return EOF;
205 return 0;
206}
207
208int gtpie_decaps(union gtpie_member *ie[], int version, void *pack,
209 unsigned len)
210{
211 int i;
212 int j = 0;
213 unsigned char *p;
214 unsigned char *end;
215
216 end = (unsigned char *)pack + len;
217 p = pack;
218
219 memset(ie, 0, sizeof(union gtpie_member *) * GTPIE_SIZE);
220
221 while ((p < end) && (j < GTPIE_SIZE)) {
222 if (GTPIE_DEBUG) {
223 printf("The packet looks like this:\n");
224 for (i = 0; i < (end - p); i++) {
225 printf("%02x ",
226 (unsigned char)*(char *)(p + i));
227 if (!((i + 1) % 16))
228 printf("\n");
229 };
230 printf("\n");
231 }
232
233 switch (*p) {
234 case GTPIE_CAUSE: /* TV GTPIE types with value length 1 */
235 case GTPIE_REORDER:
236 case GTPIE_MAP_CAUSE:
237 case GTPIE_MS_VALIDATED:
238 case GTPIE_RECOVERY:
239 case GTPIE_SELECTION_MODE:
240 case GTPIE_TEARDOWN:
241 case GTPIE_NSAPI:
242 case GTPIE_RANAP_CAUSE:
243 case GTPIE_RP_SMS:
244 case GTPIE_RP:
245 case GTPIE_MS_NOT_REACH:
246 if (j < GTPIE_SIZE) {
247 ie[j] = (union gtpie_member *)p;
248 if (GTPIE_DEBUG)
249 printf
250 ("GTPIE TV1 found. Type %d, value %d\n",
251 ie[j]->tv1.t, ie[j]->tv1.v);
252 p += 1 + 1;
253 j++;
254 }
255 break;
256 case GTPIE_FL_DI: /* TV GTPIE types with value length 2 or 4 */
257 case GTPIE_FL_C:
258 if (version != 0) {
259 if (j < GTPIE_SIZE) { /* GTPIE_TEI_DI & GTPIE_TEI_C with length 4 */
260 /* case GTPIE_TEI_DI: gtp1 */
261 /* case GTPIE_TEI_C: gtp1 */
262 ie[j] = (union gtpie_member *)p;
263 if (GTPIE_DEBUG)
264 printf
265 ("GTPIE TV 4 found. Type %d, value %d\n",
266 ie[j]->tv4.t,
267 ie[j]->tv4.v);
268 p += 1 + 4;
269 j++;
270 }
271 break;
272 }
273 case GTPIE_PFI: /* TV GTPIE types with value length 2 */
274 case GTPIE_CHARGING_C:
275 case GTPIE_TRACE_REF:
276 case GTPIE_TRACE_TYPE:
277 if (j < GTPIE_SIZE) {
278 ie[j] = (union gtpie_member *)p;
279 if (GTPIE_DEBUG)
280 printf
281 ("GTPIE TV2 found. Type %d, value %d\n",
282 ie[j]->tv2.t, ie[j]->tv2.v);
283 p += 1 + 2;
284 j++;
285 }
286 break;
287 case GTPIE_QOS_PROFILE0: /* TV GTPIE types with value length 3 */
288 case GTPIE_P_TMSI_S:
289 if (j < GTPIE_SIZE) {
290 ie[j] = (union gtpie_member *)p;
291 if (GTPIE_DEBUG)
292 printf
293 ("GTPIE TV 3 found. Type %d, value %d, %d, %d\n",
294 ie[j]->tv0.t, ie[j]->tv0.v[0],
295 ie[j]->tv0.v[1], ie[j]->tv0.v[2]);
296 p += 1 + 3;
297 j++;
298 }
299 break;
300 case GTPIE_TLLI: /* TV GTPIE types with value length 4 */
301 case GTPIE_P_TMSI:
302 case GTPIE_CHARGING_ID:
303 /* case GTPIE_TEI_DI: Handled by GTPIE_FL_DI */
304 /* case GTPIE_TEI_C: Handled by GTPIE_FL_DI */
305 if (j < GTPIE_SIZE) {
306 ie[j] = (union gtpie_member *)p;
307 if (GTPIE_DEBUG)
308 printf
309 ("GTPIE TV 4 found. Type %d, value %d\n",
310 ie[j]->tv4.t, ie[j]->tv4.v);
311 p += 1 + 4;
312 j++;
313 }
314 break;
315 case GTPIE_TEI_DII: /* TV GTPIE types with value length 5 */
316 if (j < GTPIE_SIZE) {
317 ie[j] = (union gtpie_member *)p;
318 if (GTPIE_DEBUG)
319 printf("GTPIE TV 5 found. Type %d\n",
320 ie[j]->tv0.t);
321 p += 1 + 5;
322 j++;
323 }
324 break;
325 case GTPIE_RAB_CONTEXT: /* TV GTPIE types with value length 7 */
326 if (j < GTPIE_SIZE) {
327 ie[j] = (union gtpie_member *)p;
328 if (GTPIE_DEBUG)
329 printf("GTPIE TV 7 found. Type %d\n",
330 ie[j]->tv0.t);
331 p += 1 + 7;
332 j++;
333 }
334 break;
335 case GTPIE_IMSI: /* TV GTPIE types with value length 8 */
336 if (j < GTPIE_SIZE) {
337 ie[j] = (union gtpie_member *)p;
338 if (GTPIE_DEBUG)
339 printf
340 ("GTPIE_IMSI - GTPIE TV 8 found. Type %d, value 0x%llx\n",
341 ie[j]->tv0.t, ie[j]->tv8.v);
342 p += 1 + 8;
343 j++;
344 }
345 break;
346 case GTPIE_RAI: /* TV GTPIE types with value length 6 */
347 if (j < GTPIE_SIZE) {
348 ie[j] = (union gtpie_member *)p;
349 if (GTPIE_DEBUG)
350 printf
351 ("GTPIE_RAI - GTPIE TV 6 found. Type %d, value 0x%llx\n",
352 ie[j]->tv0.t, ie[j]->tv8.v);
353 p += 1 + 6;
354 j++;
355 }
356 break;
357 case GTPIE_AUTH_TRIPLET: /* TV GTPIE types with value length 28 */
358 if (j < GTPIE_SIZE) {
359 ie[j] = (union gtpie_member *)p;
360 if (GTPIE_DEBUG)
361 printf("GTPIE TV 28 found. Type %d\n",
362 ie[j]->tv0.t);
363 p += 1 + 28;
364 j++;
365 }
366 break;
367 case GTPIE_EXT_HEADER_T: /* GTP extension header */
368 if (j < GTPIE_SIZE) {
369 ie[j] = (union gtpie_member *)p;
370 if (GTPIE_DEBUG)
371 printf
372 ("GTPIE GTP extension header found. Type %d\n",
373 ie[j]->ext.t);
374 p += 2 + ntoh8(ie[j]->ext.l);
375 j++;
376 }
377 break;
378 case GTPIE_EUA: /* TLV GTPIE types with variable length */
379 case GTPIE_MM_CONTEXT:
380 case GTPIE_PDP_CONTEXT:
381 case GTPIE_APN:
382 case GTPIE_PCO:
383 case GTPIE_GSN_ADDR:
384 case GTPIE_MSISDN:
385 case GTPIE_QOS_PROFILE:
386 case GTPIE_AUTH_QUINTUP:
387 case GTPIE_TFT:
388 case GTPIE_TARGET_INF:
389 case GTPIE_UTRAN_TRANS:
390 case GTPIE_RAB_SETUP:
391 case GTPIE_TRIGGER_ID:
392 case GTPIE_OMC_ID:
393 case GTPIE_CHARGING_ADDR:
394 case GTPIE_RAT_TYPE:
395 case GTPIE_USER_LOC:
396 case GTPIE_MS_TZ:
397 case GTPIE_IMEI_SV:
398 case GTPIE_PRIVATE:
399 if (j < GTPIE_SIZE) {
400 ie[j] = (union gtpie_member *)p;
401 if (GTPIE_DEBUG)
402 printf("GTPIE TLV found. Type %d\n",
403 ie[j]->tlv.t);
404 p += 3 + ntoh16(ie[j]->tlv.l);
405 j++;
406 }
407 break;
408 default:
409 if (GTPIE_DEBUG)
410 printf("GTPIE something unknown. Type %d\n",
411 *p);
412 return EOF; /* We received something unknown */
413 }
414 }
415 if (p == end) {
416 if (GTPIE_DEBUG)
417 printf("GTPIE normal return. %lx %lx\n",
418 (unsigned long)p, (unsigned long)end);
419 return 0; /* We landed at the end of the packet: OK */
420 } else if (!(j < GTPIE_SIZE)) {
421 if (GTPIE_DEBUG)
422 printf("GTPIE too many elements.\n");
423 return EOF; /* We received too many information elements */
424 } else {
425 if (GTPIE_DEBUG)
426 printf("GTPIE exceeded end of packet. %lx %lx\n",
427 (unsigned long)p, (unsigned long)end);
428 return EOF; /* We exceeded the end of the packet: Error */
429 }
430}
431
432int gtpie_encaps(union gtpie_member *ie[], void *pack, unsigned *len)
433{
434 int i;
435 unsigned char *p;
436 unsigned char *end;
437 union gtpie_member *m;
438 int iesize;
439
440 p = pack;
441
442 memset(pack, 0, GTPIE_MAX);
443 end = p + GTPIE_MAX;
444 for (i = 1; i < GTPIE_SIZE; i++)
445 if (ie[i] != 0) {
446 if (GTPIE_DEBUG)
447 printf("gtpie_encaps. Type %d\n", i);
448 m = (union gtpie_member *)p;
449 switch (i) {
450 case GTPIE_CAUSE: /* TV GTPIE types with value length 1 */
451 case GTPIE_REORDER:
452 case GTPIE_MAP_CAUSE:
453 case GTPIE_MS_VALIDATED:
454 case GTPIE_RECOVERY:
455 case GTPIE_SELECTION_MODE:
456 case GTPIE_TEARDOWN:
457 case GTPIE_NSAPI:
458 case GTPIE_RANAP_CAUSE:
459 case GTPIE_RP_SMS:
460 case GTPIE_RP:
461 case GTPIE_MS_NOT_REACH:
462 iesize = 2;
463 break;
464 case GTPIE_FL_DI: /* TV GTPIE types with value length 2 */
465 case GTPIE_FL_C:
466 case GTPIE_PFI:
467 case GTPIE_CHARGING_C:
468 case GTPIE_TRACE_REF:
469 case GTPIE_TRACE_TYPE:
470 iesize = 3;
471 break;
472 case GTPIE_QOS_PROFILE0: /* TV GTPIE types with value length 3 */
473 case GTPIE_P_TMSI_S:
474 iesize = 4;
475 break;
476 case GTPIE_TLLI: /* TV GTPIE types with value length 4 */
477 case GTPIE_P_TMSI:
478 /* case GTPIE_TEI_DI: only in gtp1 */
479 /* case GTPIE_TEI_C: only in gtp1 */
480 case GTPIE_CHARGING_ID:
481 iesize = 5;
482 break;
483 case GTPIE_TEI_DII: /* TV GTPIE types with value length 5 */
484 iesize = 6;
485 break;
486 case GTPIE_RAB_CONTEXT: /* TV GTPIE types with value length 7 */
487 iesize = 8;
488 break;
489 case GTPIE_IMSI: /* TV GTPIE types with value length 8 */
490 case GTPIE_RAI:
491 iesize = 9;
492 break;
493 case GTPIE_AUTH_TRIPLET: /* TV GTPIE types with value length 28 */
494 iesize = 29;
495 break;
496 case GTPIE_EXT_HEADER_T: /* GTP extension header */
497 iesize = 2 + hton8(ie[i]->ext.l);
498 break;
499 case GTPIE_EUA: /* TLV GTPIE types with length length 2 */
500 case GTPIE_MM_CONTEXT:
501 case GTPIE_PDP_CONTEXT:
502 case GTPIE_APN:
503 case GTPIE_PCO:
504 case GTPIE_GSN_ADDR:
505 case GTPIE_MSISDN:
506 case GTPIE_QOS_PROFILE:
507 case GTPIE_AUTH_QUINTUP:
508 case GTPIE_TFT:
509 case GTPIE_TARGET_INF:
510 case GTPIE_UTRAN_TRANS:
511 case GTPIE_RAB_SETUP:
512 case GTPIE_TRIGGER_ID:
513 case GTPIE_OMC_ID:
514 case GTPIE_CHARGING_ADDR:
515 case GTPIE_PRIVATE:
516 iesize = 3 + hton16(ie[i]->tlv.l);
517 break;
518 default:
519 return 2; /* We received something unknown */
520 }
521 if (p + iesize < end) {
522 memcpy(p, ie[i], iesize);
523 p += iesize;
524 *len += iesize;
525 } else
526 return 2; /* Out of space */
527 }
528 return 0;
jjako52c24142002-12-16 13:33:51 +0000529}
530
Harald Weltef54a1f42010-05-04 11:08:38 +0200531int gtpie_encaps2(union gtpie_member ie[], unsigned int size,
Harald Weltebed35df2011-11-02 13:06:18 +0100532 void *pack, unsigned *len)
533{
534 unsigned int i, j;
535 unsigned char *p;
536 unsigned char *end;
537 union gtpie_member *m;
538 int iesize;
jjako52c24142002-12-16 13:33:51 +0000539
Harald Weltebed35df2011-11-02 13:06:18 +0100540 p = pack;
541
542 memset(pack, 0, GTPIE_MAX);
543 end = p + GTPIE_MAX;
544 for (j = 0; j < GTPIE_SIZE; j++)
545 for (i = 0; i < size; i++)
546 if (ie[i].t == j) {
547 if (GTPIE_DEBUG)
548 printf
549 ("gtpie_encaps. Number %d, Type %d\n",
550 i, ie[i].t);
551 m = (union gtpie_member *)p;
552 switch (ie[i].t) {
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:
565 iesize = 2;
566 break;
567 case GTPIE_PFI: /* TV GTPIE types with value length 2 */
568 case GTPIE_CHARGING_C:
569 case GTPIE_TRACE_REF:
570 case GTPIE_TRACE_TYPE:
571 iesize = 3;
572 break;
573 case GTPIE_QOS_PROFILE0: /* TV GTPIE types with value length 3 */
574 case GTPIE_P_TMSI_S:
575 iesize = 4;
576 break;
577 case GTPIE_TLLI: /* TV GTPIE types with value length 4 */
578 case GTPIE_P_TMSI:
579 case GTPIE_TEI_DI:
580 case GTPIE_TEI_C:
581 iesize = 5;
582 break;
583 case GTPIE_TEI_DII: /* TV GTPIE types with value length 5 */
584 iesize = 6;
585 break;
586 case GTPIE_RAB_CONTEXT: /* TV GTPIE types with value length 7 */
587 iesize = 8;
588 break;
589 case GTPIE_IMSI: /* TV GTPIE types with value length 8 */
590 case GTPIE_RAI:
591 iesize = 9;
592 break;
593 case GTPIE_AUTH_TRIPLET: /* TV GTPIE types with value length 28 */
594 iesize = 29;
595 break;
596 case GTPIE_EXT_HEADER_T: /* GTP extension header */
597 iesize = 2 + hton8(ie[i].ext.l);
598 break;
599 case GTPIE_CHARGING_ID: /* TLV GTPIE types with length length 2 */
600 case GTPIE_EUA:
601 case GTPIE_MM_CONTEXT:
602 case GTPIE_PDP_CONTEXT:
603 case GTPIE_APN:
604 case GTPIE_PCO:
605 case GTPIE_GSN_ADDR:
606 case GTPIE_MSISDN:
607 case GTPIE_QOS_PROFILE:
608 case GTPIE_AUTH_QUINTUP:
609 case GTPIE_TFT:
610 case GTPIE_TARGET_INF:
611 case GTPIE_UTRAN_TRANS:
612 case GTPIE_RAB_SETUP:
613 case GTPIE_TRIGGER_ID:
614 case GTPIE_OMC_ID:
615 case GTPIE_CHARGING_ADDR:
616 case GTPIE_PRIVATE:
617 iesize = 3 + hton16(ie[i].tlv.l);
618 break;
619 default:
620 return 2; /* We received something unknown */
621 }
622 if (p + iesize < end) {
623 memcpy(p, &ie[i], iesize);
624 p += iesize;
625 *len += iesize;
626 } else
627 return 2; /* Out of space */
628 }
629 return 0;
jjako52c24142002-12-16 13:33:51 +0000630}