diff options
author | jjako <jjako> | 2002-12-16 13:33:51 +0000 |
---|---|---|
committer | jjako <jjako> | 2002-12-16 13:33:51 +0000 |
commit | 52c2414f6cabefb0427475756e8ac4856180bc59 (patch) | |
tree | 5ecb31a74c392c36a7d7c802f18d37349973bf00 /gtp/gtpie.c |
Initial revision
Diffstat (limited to 'gtp/gtpie.c')
-rw-r--r-- | gtp/gtpie.c | 513 |
1 files changed, 513 insertions, 0 deletions
diff --git a/gtp/gtpie.c b/gtp/gtpie.c new file mode 100644 index 0000000..8fd4a20 --- /dev/null +++ b/gtp/gtpie.c @@ -0,0 +1,513 @@ +/* + * OpenGGSN - Gateway GPRS Support Node + * Copyright (C) 2002 Mondru AB. + * + * The contents of this file may be used under the terms of the GNU + * General Public License Version 2, provided that the above copyright + * notice and this permission notice is included in all copies or + * substantial portions of the software. + * + * The initial developer of the original code is + * Jens Jakobsen <jj@openggsn.org> + * + * Contributor(s): + * + */ + +/* + * gtpie.c: Contains functions to encapsulate and decapsulate GTP + * information elements + * + * + * Encapsulation + * - gtpie_tlv, gtpie_tv0, gtpie_tv1, gtpie_tv2 ... Adds information + * elements to a buffer. + * + * Decapsulation + * - gtpie_decaps: Returns array with pointers to information elements. + * - getie_getie: Returns the pointer of a particular element. + * - gtpie_gettlv: Copies tlv information element. Return 0 on success. + * - gtpie_gettv: Copies tv information element. Return 0 on success. + * + */ + +#include <stdio.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <string.h> + +#include "gtpie.h" + +int gtpie_tlv(void *p, int *length, int size, u_int8_t t, int l, void *v) { + if ((*length + 3 + l) >= size) return 1; + ((union gtpie_member*) (p + *length))->tlv.t = hton8(t); + ((union gtpie_member*) (p + *length))->tlv.l = hton16(l); + memcpy((void*) (p + *length +3), v, l); + *length += 3 + l; + return 0; +} + +int gtpie_tv0(void *p, int *length, int size, u_int8_t t, int l, u_int8_t *v) { + if ((*length + 1 + l) >= size) return 1; + ((union gtpie_member*) (p + *length))->tv0.t = hton8(t); + memcpy((void*) (p + *length +1), v, l); + *length += 1 + l; + return 0; +} + +int gtpie_tv1(void *p, int *length, int size, u_int8_t t, u_int8_t v) { + if ((*length + 2) >= size) return 1; + ((union gtpie_member*) (p + *length))->tv1.t = hton8(t); + ((union gtpie_member*) (p + *length))->tv1.v = hton8(v); + *length += 2; + return 0; +} + +int gtpie_tv2(void *p, int *length, int size, u_int8_t t, u_int16_t v) { + if ((*length + 3) >= size) return 1; + ((union gtpie_member*) (p + *length))->tv2.t = hton8(t); + ((union gtpie_member*) (p + *length))->tv2.v = hton16(v); + *length += 3; + return 0; +} + +int gtpie_tv4(void *p, int *length, int size, u_int8_t t, u_int32_t v) { + if ((*length + 5) >= size) return 1; + ((union gtpie_member*) (p + *length))->tv4.t = hton8(t); + ((union gtpie_member*) (p + *length))->tv4.v = hton32(v); + *length += 5; + return 0; +} + +int gtpie_getie(union gtpie_member* ie[], int type, int instance) { + int j; + for (j=0; j< GTPIE_SIZE; j++) { + if ((ie[j] != 0) && (ie[j]->t == type)) { + if (instance-- == 0) return j; + } + } + return -1; +} + +int gtpie_exist(union gtpie_member* ie[], int type, int instance) { + int j; + for (j=0; j< GTPIE_SIZE; j++) { + if ((ie[j] != 0) && (ie[j]->t == type)) { + if (instance-- == 0) return 1; + } + } + return 0; +} + +int gtpie_gettlv(union gtpie_member* ie[], int type, int instance, + int *length, void *dst, int size){ + int ien; + ien = gtpie_getie(ie, type, instance); + if (ien>=0) { + *length = ntoh16(ie[ien]->tlv.l); + if (*length <= size) + memcpy(dst, ie[ien]->tlv.v, *length); + else + return EOF; + } + return 0; +} + +int gtpie_gettv0(union gtpie_member* ie[], int type, int instance, + void *dst, int size){ + int ien; + ien = gtpie_getie(ie, type, instance); + if (ien>=0) + memcpy(dst, ie[ien]->tv0.v, size); + else + return EOF; + return 0; +} + +int gtpie_gettv1(union gtpie_member* ie[], int type, int instance, + uint8_t *dst){ + int ien; + ien = gtpie_getie(ie, type, instance); + if (ien>=0) + *dst = ntoh8(ie[ien]->tv1.v); + else + return EOF; + return 0; +} + +int gtpie_gettv2(union gtpie_member* ie[], int type, int instance, + uint16_t *dst){ + int ien; + ien = gtpie_getie(ie, type, instance); + if (ien>=0) + *dst = ntoh16(ie[ien]->tv2.v); + else + return EOF; + return 0; +} + +int gtpie_gettv4(union gtpie_member* ie[], int type, int instance, + uint32_t *dst){ + int ien; + ien = gtpie_getie(ie, type, instance); + if (ien>=0) + *dst = ntoh32(ie[ien]->tv4.v); + else + return EOF; + return 0; +} + +int gtpie_decaps(union gtpie_member* ie[], void *pack, unsigned len) { + int i; + int j = 0; + unsigned char *p; + unsigned char *end; + + end = (unsigned char*) pack + len; + p = pack; + + memset(ie, 0, 4 * GTPIE_SIZE); + + while (p<end) { + if (GTPIE_DEBUG) { + printf("The packet looks like this:\n"); + for( i=0; i<(end-p); i++) { + printf("%02x ", (unsigned char)*(char *)(p+i)); + if (!((i+1)%16)) printf("\n"); + }; + printf("\n"); + } + + switch (*p) { + case GTPIE_CAUSE: /* TV GTPIE types with value length 1 */ + case GTPIE_REORDER: + case GTPIE_MAP_CAUSE: + case GTPIE_MS_VALIDATED: + case GTPIE_RECOVERY: + case GTPIE_SELECTION_MODE: + case GTPIE_TEARDOWN: + case GTPIE_NSAPI: + case GTPIE_RANAP_CAUSE: + case GTPIE_RP_SMS: + case GTPIE_RP: + case GTPIE_MS_NOT_REACH: + if (j<GTPIE_SIZE) { + ie[j] = (union gtpie_member*) p; + if (GTPIE_DEBUG) printf("GTPIE TV1 found. Type %d, value %d\n", + ie[j]->tv1.t, ie[j]->tv1.v); + p+= 1 + 1; + j++; + } + break; + case GTPIE_FL_DI: /* TV GTPIE types with value length 2 */ + case GTPIE_FL_C: + case GTPIE_PFI: + case GTPIE_CHARGING_C: + case GTPIE_TRACE_REF: + case GTPIE_TRACE_TYPE: + if (j<GTPIE_SIZE) { + ie[j] = (union gtpie_member*) p; + if (GTPIE_DEBUG) printf("GTPIE TV2 found. Type %d, value %d\n", + ie[j]->tv2.t, ie[j]->tv2.v); + p+= 1 + 2; + j++; + } + break; + case GTPIE_QOS_PROFILE0: /* TV GTPIE types with value length 3 */ + case GTPIE_P_TMSI_S: + if (j<GTPIE_SIZE) { + ie[j] = (union gtpie_member*) p; + if (GTPIE_DEBUG) printf("GTPIE TV 3 found. Type %d, value %d, %d, %d\n", + ie[j]->tv0.t, ie[j]->tv0.v[0], + ie[j]->tv0.v[1], ie[j]->tv0.v[2]); + p+= 1 + 3; + j++; + } + break; + case GTPIE_TLLI: /* TV GTPIE types with value length 4 */ + case GTPIE_P_TMSI: + case GTPIE_CHARGING_ID: + if (j<GTPIE_SIZE) { + /* case GTPIE_TEI_DI: gtp1 */ + /* case GTPIE_TEI_C: gtp1 */ + ie[j] = (union gtpie_member*) p; + if (GTPIE_DEBUG) printf("GTPIE TV 4 found. Type %d, value %d\n", + ie[j]->tv4.t, ie[j]->tv4.v); + p+= 1 + 4; + j++; + } + break; + case GTPIE_TEI_DII: /* TV GTPIE types with value length 5 */ + if (j<GTPIE_SIZE) { + ie[j] = (union gtpie_member*) p; + if (GTPIE_DEBUG) printf("GTPIE TV 5 found. Type %d\n", ie[j]->tv0.t); + p+= 1 + 5; + j++; + } + break; + case GTPIE_RAB_CONTEXT: /* TV GTPIE types with value length 7 */ + if (j<GTPIE_SIZE) { + ie[j] = (union gtpie_member*) p; + if (GTPIE_DEBUG) printf("GTPIE TV 7 found. Type %d\n", ie[j]->tv0.t); + p+= 1 + 7; + j++; + } + break; + case GTPIE_IMSI: /* TV GTPIE types with value length 8 */ + case GTPIE_RAI: + if (j<GTPIE_SIZE) { + ie[j] = (union gtpie_member*) p; + if (GTPIE_DEBUG) printf("GTPIE TV 8 found. Type %d, value 0x%llx\n", + ie[j]->tv0.t, ie[j]->tv8.v); + p+= 1 + 8; + j++; + } + break; + case GTPIE_AUTH_TRIPLET: /* TV GTPIE types with value length 28 */ + if (j<GTPIE_SIZE) { + ie[j] = (union gtpie_member*) p; + if (GTPIE_DEBUG) printf("GTPIE TV 28 found. Type %d\n", ie[j]->tv0.t); + p+= 1 + 28; + j++; + } + break; + case GTPIE_EXT_HEADER_T: /* GTP extension header */ + if (j<GTPIE_SIZE) { + ie[j] = (union gtpie_member*) p; + if (GTPIE_DEBUG) printf("GTPIE GTP extension header found. Type %d\n", + ie[j]->ext.t); + p+= 2 + ntoh8(ie[j]->ext.l); + j++; + } + break; + case GTPIE_EUA: /* TLV GTPIE types with variable length */ + case GTPIE_MM_CONTEXT: + case GTPIE_PDP_CONTEXT: + case GTPIE_APN: + case GTPIE_PCO: + case GTPIE_GSN_ADDR: + case GTPIE_MSISDN: + case GTPIE_QOS_PROFILE: + case GTPIE_AUTH_QUINTUP: + case GTPIE_TFT: + case GTPIE_TARGET_INF: + case GTPIE_UTRAN_TRANS: + case GTPIE_RAB_SETUP: + case GTPIE_TRIGGER_ID: + case GTPIE_OMC_ID: + case GTPIE_CHARGING_ADDR: + case GTPIE_PRIVATE: + if (j<GTPIE_SIZE) { + ie[j] = (union gtpie_member*) p; + if (GTPIE_DEBUG) printf("GTPIE TLV found. Type %d\n", ie[j]->tlv.t); + p+= 3 + ntoh16(ie[j]->tlv.l); + j++; + } + break; + default: + if (GTPIE_DEBUG) printf("GTPIE something unknown. Type %d\n", *p); + return EOF; /* We received something unknown */ + } + } + if (p==end) { + if (GTPIE_DEBUG) printf("GTPIE normal return. %lx %lx\n", + (unsigned long) p, (unsigned long) end); + return 0; /* We landed at the end of the packet: OK */ + } + else { + if (GTPIE_DEBUG) printf("GTPIE exceeded end of packet. %lx %lx\n", + (unsigned long) p, (unsigned long) end); + return EOF; /* We exceeded the end of the packet: Error */ + } +} + +int gtpie_encaps(union gtpie_member *ie[], void *pack, unsigned *len) { + int i; + unsigned char *p; + unsigned char *end; + union gtpie_member *m; + int iesize; + + p = pack; + + memset(pack, 0, GTPIE_MAX); + end = p + GTPIE_MAX; + for (i=1; i<GTPIE_SIZE; i++) if (ie[i] != 0) { + if (GTPIE_DEBUG) printf("gtpie_encaps. Type %d\n", i); + m=(union gtpie_member *)p; + switch (i) { + case GTPIE_CAUSE: /* TV GTPIE types with value length 1 */ + case GTPIE_REORDER: + case GTPIE_MAP_CAUSE: + case GTPIE_MS_VALIDATED: + case GTPIE_RECOVERY: + case GTPIE_SELECTION_MODE: + case GTPIE_TEARDOWN: + case GTPIE_NSAPI: + case GTPIE_RANAP_CAUSE: + case GTPIE_RP_SMS: + case GTPIE_RP: + case GTPIE_MS_NOT_REACH: + iesize = 2; + break; + case GTPIE_FL_DI: /* TV GTPIE types with value length 2 */ + case GTPIE_FL_C: + case GTPIE_PFI: + case GTPIE_CHARGING_C: + case GTPIE_TRACE_REF: + case GTPIE_TRACE_TYPE: + iesize = 3; + break; + case GTPIE_QOS_PROFILE0: /* TV GTPIE types with value length 3 */ + case GTPIE_P_TMSI_S: + iesize = 4; + break; + case GTPIE_TLLI: /* TV GTPIE types with value length 4 */ + case GTPIE_P_TMSI: + /* case GTPIE_TEI_DI: only in gtp1*/ + /* case GTPIE_TEI_C: only in gtp1*/ + case GTPIE_CHARGING_ID: + iesize = 5; + break; + case GTPIE_TEI_DII: /* TV GTPIE types with value length 5 */ + iesize = 6; + break; + case GTPIE_RAB_CONTEXT: /* TV GTPIE types with value length 7 */ + iesize = 8; + break; + case GTPIE_IMSI: /* TV GTPIE types with value length 8 */ + case GTPIE_RAI: + iesize = 9; + break; + case GTPIE_AUTH_TRIPLET: /* TV GTPIE types with value length 28 */ + iesize = 29; + break; + case GTPIE_EXT_HEADER_T: /* GTP extension header */ + iesize = 2 + hton8(ie[i]->ext.l); + break; + case GTPIE_EUA: /* TLV GTPIE types with length length 2 */ + case GTPIE_MM_CONTEXT: + case GTPIE_PDP_CONTEXT: + case GTPIE_APN: + case GTPIE_PCO: + case GTPIE_GSN_ADDR: + case GTPIE_MSISDN: + case GTPIE_QOS_PROFILE: + case GTPIE_AUTH_QUINTUP: + case GTPIE_TFT: + case GTPIE_TARGET_INF: + case GTPIE_UTRAN_TRANS: + case GTPIE_RAB_SETUP: + case GTPIE_TRIGGER_ID: + case GTPIE_OMC_ID: + case GTPIE_CHARGING_ADDR: + case GTPIE_PRIVATE: + iesize = 3 + hton16(ie[i]->tlv.l); + break; + default: + return 2; /* We received something unknown */ + } + if (p+iesize < end) { + memcpy(p, ie[i], iesize); + p += iesize; + *len += iesize; + } + else return 2; /* Out of space */ + } + return 0; +} + +int gtpie_encaps2(union gtpie_member ie[], int size, + void *pack, unsigned *len) { + int i, j; + unsigned char *p; + unsigned char *end; + union gtpie_member *m; + int iesize; + + p = pack; + + memset(pack, 0, GTPIE_MAX); + end = p + GTPIE_MAX; + for (j=0; j<GTPIE_SIZE; j++) for (i=0; i<size; i++) if (ie[i].t == j) { + if (GTPIE_DEBUG) printf("gtpie_encaps. Number %d, Type %d\n", i, ie[i].t); + m=(union gtpie_member *)p; + switch (ie[i].t) { + case GTPIE_CAUSE: /* TV GTPIE types with value length 1 */ + case GTPIE_REORDER: + case GTPIE_MAP_CAUSE: + case GTPIE_MS_VALIDATED: + case GTPIE_RECOVERY: + case GTPIE_SELECTION_MODE: + case GTPIE_TEARDOWN: + case GTPIE_NSAPI: + case GTPIE_RANAP_CAUSE: + case GTPIE_RP_SMS: + case GTPIE_RP: + case GTPIE_MS_NOT_REACH: + iesize = 2; + break; + case GTPIE_PFI: /* TV GTPIE types with value length 2 */ + case GTPIE_CHARGING_C: + case GTPIE_TRACE_REF: + case GTPIE_TRACE_TYPE: + iesize = 3; + break; + case GTPIE_QOS_PROFILE0: /* TV GTPIE types with value length 3 */ + case GTPIE_P_TMSI_S: + iesize = 4; + break; + case GTPIE_TLLI: /* TV GTPIE types with value length 4 */ + case GTPIE_P_TMSI: + case GTPIE_TEI_DI: + case GTPIE_TEI_C: + iesize = 5; + break; + case GTPIE_TEI_DII: /* TV GTPIE types with value length 5 */ + iesize = 6; + break; + case GTPIE_RAB_CONTEXT: /* TV GTPIE types with value length 7 */ + iesize = 8; + break; + case GTPIE_IMSI: /* TV GTPIE types with value length 8 */ + case GTPIE_RAI: + iesize = 9; + break; + case GTPIE_AUTH_TRIPLET: /* TV GTPIE types with value length 28 */ + iesize = 29; + break; + case GTPIE_EXT_HEADER_T: /* GTP extension header */ + iesize = 2 + hton8(ie[i].ext.l); + break; + case GTPIE_CHARGING_ID: /* TLV GTPIE types with length length 2 */ + case GTPIE_EUA: + case GTPIE_MM_CONTEXT: + case GTPIE_PDP_CONTEXT: + case GTPIE_APN: + case GTPIE_PCO: + case GTPIE_GSN_ADDR: + case GTPIE_MSISDN: + case GTPIE_QOS_PROFILE: + case GTPIE_AUTH_QUINTUP: + case GTPIE_TFT: + case GTPIE_TARGET_INF: + case GTPIE_UTRAN_TRANS: + case GTPIE_RAB_SETUP: + case GTPIE_TRIGGER_ID: + case GTPIE_OMC_ID: + case GTPIE_CHARGING_ADDR: + case GTPIE_PRIVATE: + iesize = 3 + hton16(ie[i].tlv.l); + break; + default: + return 2; /* We received something unknown */ + } + if (p+iesize < end) { + memcpy(p, &ie[i], iesize); + p += iesize; + *len += iesize; + } + else return 2; /* Out of space */ + } + return 0; +} |