2 * OpenGGSN - Gateway GPRS Support Node
3 * Copyright (C) 2002 Mondru AB.
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.
13 * gtpie.c: Contains functions to encapsulate and decapsulate GTP
14 * information elements
18 * - gtpie_tlv, gtpie_tv0, gtpie_tv1, gtpie_tv2 ... Adds information
19 * elements to a buffer.
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.
29 #include <../config.h>
36 #include <sys/types.h>
37 #include <netinet/in.h>
42 int gtpie_tlv(void *p
, unsigned int *length
, unsigned int size
, uint8_t t
,
45 if ((*length
+ 3 + l
) >= size
)
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
);
54 int gtpie_tv0(void *p
, unsigned int *length
, unsigned int size
, uint8_t t
,
57 if ((*length
+ 1 + l
) >= size
)
59 ((union gtpie_member
*)(p
+ *length
))->tv0
.t
= hton8(t
);
60 memcpy((void *)(p
+ *length
+ 1), v
, l
);
65 int gtpie_tv1(void *p
, unsigned int *length
, unsigned int size
, uint8_t t
,
68 if ((*length
+ 2) >= size
)
70 ((union gtpie_member
*)(p
+ *length
))->tv1
.t
= hton8(t
);
71 ((union gtpie_member
*)(p
+ *length
))->tv1
.v
= hton8(v
);
76 int gtpie_tv2(void *p
, unsigned int *length
, unsigned int size
, uint8_t t
,
79 if ((*length
+ 3) >= size
)
81 ((union gtpie_member
*)(p
+ *length
))->tv2
.t
= hton8(t
);
82 ((union gtpie_member
*)(p
+ *length
))->tv2
.v
= hton16(v
);
87 int gtpie_tv4(void *p
, unsigned int *length
, unsigned int size
, uint8_t t
,
90 if ((*length
+ 5) >= size
)
92 ((union gtpie_member
*)(p
+ *length
))->tv4
.t
= hton8(t
);
93 ((union gtpie_member
*)(p
+ *length
))->tv4
.v
= hton32(v
);
98 int gtpie_tv8(void *p
, unsigned int *length
, unsigned int size
, uint8_t t
,
101 if ((*length
+ 9) >= size
)
103 ((union gtpie_member
*)(p
+ *length
))->tv8
.t
= hton8(t
);
104 ((union gtpie_member
*)(p
+ *length
))->tv8
.v
= hton64(v
);
109 int gtpie_getie(union gtpie_member
*ie
[], int type
, int instance
)
112 for (j
= 0; j
< GTPIE_SIZE
; j
++) {
113 if ((ie
[j
] != 0) && (ie
[j
]->t
== type
)) {
121 int gtpie_exist(union gtpie_member
*ie
[], int type
, int instance
)
124 for (j
= 0; j
< GTPIE_SIZE
; j
++) {
125 if ((ie
[j
] != 0) && (ie
[j
]->t
== type
)) {
133 int gtpie_gettlv(union gtpie_member
*ie
[], int type
, int instance
,
134 unsigned int *length
, void *dst
, unsigned int size
)
137 ien
= gtpie_getie(ie
, type
, instance
);
139 *length
= ntoh16(ie
[ien
]->tlv
.l
);
141 memcpy(dst
, ie
[ien
]->tlv
.v
, *length
);
148 int gtpie_gettv0(union gtpie_member
*ie
[], int type
, int instance
,
149 void *dst
, unsigned int size
)
152 ien
= gtpie_getie(ie
, type
, instance
);
154 memcpy(dst
, ie
[ien
]->tv0
.v
, size
);
160 int gtpie_gettv1(union gtpie_member
*ie
[], int type
, int instance
,
164 ien
= gtpie_getie(ie
, type
, instance
);
166 *dst
= ntoh8(ie
[ien
]->tv1
.v
);
172 int gtpie_gettv2(union gtpie_member
*ie
[], int type
, int instance
,
176 ien
= gtpie_getie(ie
, type
, instance
);
178 *dst
= ntoh16(ie
[ien
]->tv2
.v
);
184 int gtpie_gettv4(union gtpie_member
*ie
[], int type
, int instance
,
188 ien
= gtpie_getie(ie
, type
, instance
);
190 *dst
= ntoh32(ie
[ien
]->tv4
.v
);
196 int gtpie_gettv8(union gtpie_member
*ie
[], int type
, int instance
,
200 ien
= gtpie_getie(ie
, type
, instance
);
202 *dst
= ntoh64(ie
[ien
]->tv8
.v
);
208 int gtpie_decaps(union gtpie_member
*ie
[], int version
, void *pack
,
216 end
= (unsigned char *)pack
+ len
;
219 memset(ie
, 0, sizeof(union gtpie_member
*) * GTPIE_SIZE
);
221 while ((p
< end
) && (j
< GTPIE_SIZE
)) {
223 printf("The packet looks like this:\n");
224 for (i
= 0; i
< (end
- p
); i
++) {
226 (unsigned char)*(char *)(p
+ i
));
234 case GTPIE_CAUSE
: /* TV GTPIE types with value length 1 */
236 case GTPIE_MAP_CAUSE
:
237 case GTPIE_MS_VALIDATED
:
239 case GTPIE_SELECTION_MODE
:
242 case GTPIE_RANAP_CAUSE
:
245 case GTPIE_MS_NOT_REACH
:
247 if (j
< GTPIE_SIZE
) {
248 ie
[j
] = (union gtpie_member
*)p
;
251 ("GTPIE TV1 found. Type %d, value %d\n",
252 ie
[j
]->tv1
.t
, ie
[j
]->tv1
.v
);
257 case GTPIE_FL_DI
: /* TV GTPIE types with value length 2 or 4 */
260 if (j
< GTPIE_SIZE
) { /* GTPIE_TEI_DI & GTPIE_TEI_C with length 4 */
261 /* case GTPIE_TEI_DI: gtp1 */
262 /* case GTPIE_TEI_C: gtp1 */
263 ie
[j
] = (union gtpie_member
*)p
;
266 ("GTPIE TV 4 found. Type %d, value %d\n",
274 case GTPIE_PFI
: /* TV GTPIE types with value length 2 */
275 case GTPIE_CHARGING_C
:
276 case GTPIE_TRACE_REF
:
277 case GTPIE_TRACE_TYPE
:
278 if (j
< GTPIE_SIZE
) {
279 ie
[j
] = (union gtpie_member
*)p
;
282 ("GTPIE TV2 found. Type %d, value %d\n",
283 ie
[j
]->tv2
.t
, ie
[j
]->tv2
.v
);
288 case GTPIE_QOS_PROFILE0
: /* TV GTPIE types with value length 3 */
290 if (j
< GTPIE_SIZE
) {
291 ie
[j
] = (union gtpie_member
*)p
;
294 ("GTPIE TV 3 found. Type %d, value %d, %d, %d\n",
295 ie
[j
]->tv0
.t
, ie
[j
]->tv0
.v
[0],
296 ie
[j
]->tv0
.v
[1], ie
[j
]->tv0
.v
[2]);
301 case GTPIE_TLLI
: /* TV GTPIE types with value length 4 */
303 case GTPIE_CHARGING_ID
:
304 /* case GTPIE_TEI_DI: Handled by GTPIE_FL_DI */
305 /* case GTPIE_TEI_C: Handled by GTPIE_FL_DI */
306 if (j
< GTPIE_SIZE
) {
307 ie
[j
] = (union gtpie_member
*)p
;
310 ("GTPIE TV 4 found. Type %d, value %d\n",
311 ie
[j
]->tv4
.t
, ie
[j
]->tv4
.v
);
316 case GTPIE_TEI_DII
: /* TV GTPIE types with value length 5 */
317 if (j
< GTPIE_SIZE
) {
318 ie
[j
] = (union gtpie_member
*)p
;
320 printf("GTPIE TV 5 found. Type %d\n",
326 case GTPIE_RAB_CONTEXT
: /* TV GTPIE types with value length 7 */
327 if (j
< GTPIE_SIZE
) {
328 ie
[j
] = (union gtpie_member
*)p
;
330 printf("GTPIE TV 7 found. Type %d\n",
336 case GTPIE_IMSI
: /* TV GTPIE types with value length 8 */
337 if (j
< GTPIE_SIZE
) {
338 ie
[j
] = (union gtpie_member
*)p
;
341 ("GTPIE_IMSI - GTPIE TV 8 found. Type %d, value 0x%llx\n",
342 ie
[j
]->tv0
.t
, ie
[j
]->tv8
.v
);
347 case GTPIE_RAI
: /* TV GTPIE types with value length 6 */
348 if (j
< GTPIE_SIZE
) {
349 ie
[j
] = (union gtpie_member
*)p
;
352 ("GTPIE_RAI - GTPIE TV 6 found. Type %d, value 0x%llx\n",
353 ie
[j
]->tv0
.t
, ie
[j
]->tv8
.v
);
358 case GTPIE_AUTH_TRIPLET
: /* TV GTPIE types with value length 28 */
359 if (j
< GTPIE_SIZE
) {
360 ie
[j
] = (union gtpie_member
*)p
;
362 printf("GTPIE TV 28 found. Type %d\n",
368 case GTPIE_EXT_HEADER_T
: /* GTP extension header */
369 if (j
< GTPIE_SIZE
) {
370 ie
[j
] = (union gtpie_member
*)p
;
373 ("GTPIE GTP extension header found. Type %d\n",
375 p
+= 2 + ntoh8(ie
[j
]->ext
.l
);
379 case GTPIE_EUA
: /* TLV GTPIE types with variable length */
380 case GTPIE_MM_CONTEXT
:
381 case GTPIE_PDP_CONTEXT
:
386 case GTPIE_QOS_PROFILE
:
387 case GTPIE_AUTH_QUINTUP
:
389 case GTPIE_TARGET_INF
:
390 case GTPIE_UTRAN_TRANS
:
391 case GTPIE_RAB_SETUP
:
392 case GTPIE_TRIGGER_ID
:
394 case GTPIE_CHARGING_ADDR
:
400 if (j
< GTPIE_SIZE
) {
401 ie
[j
] = (union gtpie_member
*)p
;
403 printf("GTPIE TLV found. Type %d\n",
405 p
+= 3 + ntoh16(ie
[j
]->tlv
.l
);
411 printf("GTPIE something unknown. Type %d\n",
413 return EOF
; /* We received something unknown */
418 printf("GTPIE normal return. %lx %lx\n",
419 (unsigned long)p
, (unsigned long)end
);
420 return 0; /* We landed at the end of the packet: OK */
421 } else if (!(j
< GTPIE_SIZE
)) {
423 printf("GTPIE too many elements.\n");
424 return EOF
; /* We received too many information elements */
427 printf("GTPIE exceeded end of packet. %lx %lx\n",
428 (unsigned long)p
, (unsigned long)end
);
429 return EOF
; /* We exceeded the end of the packet: Error */
433 int gtpie_encaps(union gtpie_member
*ie
[], void *pack
, unsigned *len
)
442 memset(pack
, 0, GTPIE_MAX
);
444 for (i
= 1; i
< GTPIE_SIZE
; i
++)
447 printf("gtpie_encaps. Type %d\n", i
);
449 case GTPIE_CAUSE
: /* TV GTPIE types with value length 1 */
451 case GTPIE_MAP_CAUSE
:
452 case GTPIE_MS_VALIDATED
:
454 case GTPIE_SELECTION_MODE
:
457 case GTPIE_RANAP_CAUSE
:
460 case GTPIE_MS_NOT_REACH
:
464 case GTPIE_FL_DI
: /* TV GTPIE types with value length 2 */
467 case GTPIE_CHARGING_C
:
468 case GTPIE_TRACE_REF
:
469 case GTPIE_TRACE_TYPE
:
472 case GTPIE_QOS_PROFILE0
: /* TV GTPIE types with value length 3 */
476 case GTPIE_TLLI
: /* TV GTPIE types with value length 4 */
478 /* case GTPIE_TEI_DI: only in gtp1 */
479 /* case GTPIE_TEI_C: only in gtp1 */
480 case GTPIE_CHARGING_ID
:
483 case GTPIE_TEI_DII
: /* TV GTPIE types with value length 5 */
486 case GTPIE_RAB_CONTEXT
: /* TV GTPIE types with value length 7 */
489 case GTPIE_IMSI
: /* TV GTPIE types with value length 8 */
493 case GTPIE_AUTH_TRIPLET
: /* TV GTPIE types with value length 28 */
496 case GTPIE_EXT_HEADER_T
: /* GTP extension header */
497 iesize
= 2 + hton8(ie
[i
]->ext
.l
);
499 case GTPIE_EUA
: /* TLV GTPIE types with length length 2 */
500 case GTPIE_MM_CONTEXT
:
501 case GTPIE_PDP_CONTEXT
:
506 case GTPIE_QOS_PROFILE
:
507 case GTPIE_AUTH_QUINTUP
:
509 case GTPIE_TARGET_INF
:
510 case GTPIE_UTRAN_TRANS
:
511 case GTPIE_RAB_SETUP
:
512 case GTPIE_TRIGGER_ID
:
514 case GTPIE_CHARGING_ADDR
:
516 iesize
= 3 + hton16(ie
[i
]->tlv
.l
);
519 return 2; /* We received something unknown */
521 if (p
+ iesize
< end
) {
522 memcpy(p
, ie
[i
], iesize
);
526 return 2; /* Out of space */
531 int gtpie_encaps2(union gtpie_member ie
[], unsigned int size
,
532 void *pack
, unsigned *len
)
541 memset(pack
, 0, GTPIE_MAX
);
543 for (j
= 0; j
< GTPIE_SIZE
; j
++)
544 for (i
= 0; i
< size
; i
++)
548 ("gtpie_encaps. Number %d, Type %d\n",
551 case GTPIE_CAUSE
: /* TV GTPIE types with value length 1 */
553 case GTPIE_MAP_CAUSE
:
554 case GTPIE_MS_VALIDATED
:
556 case GTPIE_SELECTION_MODE
:
559 case GTPIE_RANAP_CAUSE
:
562 case GTPIE_MS_NOT_REACH
:
566 case GTPIE_PFI
: /* TV GTPIE types with value length 2 */
567 case GTPIE_CHARGING_C
:
568 case GTPIE_TRACE_REF
:
569 case GTPIE_TRACE_TYPE
:
572 case GTPIE_QOS_PROFILE0
: /* TV GTPIE types with value length 3 */
576 case GTPIE_TLLI
: /* TV GTPIE types with value length 4 */
582 case GTPIE_TEI_DII
: /* TV GTPIE types with value length 5 */
585 case GTPIE_RAB_CONTEXT
: /* TV GTPIE types with value length 7 */
588 case GTPIE_IMSI
: /* TV GTPIE types with value length 8 */
592 case GTPIE_AUTH_TRIPLET
: /* TV GTPIE types with value length 28 */
595 case GTPIE_EXT_HEADER_T
: /* GTP extension header */
596 iesize
= 2 + hton8(ie
[i
].ext
.l
);
598 case GTPIE_CHARGING_ID
: /* TLV GTPIE types with length length 2 */
600 case GTPIE_MM_CONTEXT
:
601 case GTPIE_PDP_CONTEXT
:
606 case GTPIE_QOS_PROFILE
:
607 case GTPIE_AUTH_QUINTUP
:
609 case GTPIE_TARGET_INF
:
610 case GTPIE_UTRAN_TRANS
:
611 case GTPIE_RAB_SETUP
:
612 case GTPIE_TRIGGER_ID
:
614 case GTPIE_CHARGING_ADDR
:
616 iesize
= 3 + hton16(ie
[i
].tlv
.l
);
619 return 2; /* We received something unknown */
621 if (p
+ iesize
< end
) {
622 memcpy(p
, &ie
[i
], iesize
);
626 return 2; /* Out of space */