diff options
author | Yann BONNAMY <yann_bonnamy@yahoo.fr> | 2010-10-29 17:07:44 +0200 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2010-10-29 17:07:44 +0200 |
commit | 944dce3e66f3bc5b74f24dfbbee2370a231a39a9 (patch) | |
tree | a7450adfa49d387929c5f5dc97313d60737a53db | |
parent | 87490d7fa9052ca1fe1b67ba01c46611f9925ded (diff) |
Add support for GTP IE's from 3GPP R7
This adds support for the followng new GTP Information Elements:
RAT_TYPE, USER_LOC, MS_TZ, IMEI_SV
Furthermore, it allows to specify those fields as sgsnemu command line
arguments.
-rw-r--r-- | gtp/gtp.c | 17 | ||||
-rw-r--r-- | gtp/gtpie.c | 4 | ||||
-rw-r--r-- | gtp/gtpie.h | 4 | ||||
-rw-r--r-- | gtp/pdp.h | 8 | ||||
-rw-r--r-- | sgsnemu/cmdline.c | 69 | ||||
-rw-r--r-- | sgsnemu/cmdline.h | 16 | ||||
-rw-r--r-- | sgsnemu/sgsnemu.c | 209 |
7 files changed, 327 insertions, 0 deletions
@@ -1136,6 +1136,23 @@ extern int gtp_create_context_req(struct gsn_t *gsn, struct pdp_t *pdp, gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID, pdp->omcid.l, pdp->omcid.v); + /* new R7 fields */ + if (pdp->rattype_given == 1) + gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_RAT_TYPE, + pdp->rattype.l, pdp->rattype.v); + + if (pdp->userloc_given == 1) + gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_USER_LOC, + pdp->userloc.l, pdp->userloc.v); + + if (pdp->mstz_given == 1) + gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MS_TZ, + pdp->mstz.l, pdp->mstz.v); + + if (pdp->imeisv_given == 1) + gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_IMEI_SV, + pdp->imeisv.l, pdp->imeisv.v); + /* TODO hisaddr0 */ gtp_req(gsn, pdp->version, pdp, &packet, length, &pdp->hisaddr0, cbp); diff --git a/gtp/gtpie.c b/gtp/gtpie.c index c75408e..80370a5 100644 --- a/gtp/gtpie.c +++ b/gtp/gtpie.c @@ -328,6 +328,10 @@ int gtpie_decaps(union gtpie_member* ie[], int version, void *pack, unsigned len case GTPIE_TRIGGER_ID: case GTPIE_OMC_ID: case GTPIE_CHARGING_ADDR: + case GTPIE_RAT_TYPE: + case GTPIE_USER_LOC: + case GTPIE_MS_TZ: + case GTPIE_IMEI_SV: case GTPIE_PRIVATE: if (j<GTPIE_SIZE) { ie[j] = (union gtpie_member*) p; diff --git a/gtp/gtpie.h b/gtp/gtpie.h index 83886f5..b8fe1e7 100644 --- a/gtp/gtpie.h +++ b/gtp/gtpie.h @@ -104,6 +104,10 @@ hton64(uint64_t q) #define GTPIE_EXT_HEADER_T 141 /* Extension Header Type List */ #define GTPIE_TRIGGER_ID 142 /* Trigger Id */ #define GTPIE_OMC_ID 143 /* OMC Identity */ +#define GTPIE_RAT_TYPE 151 /* Radio Access Technology Type */ +#define GTPIE_USER_LOC 152 /* User Location Information */ +#define GTPIE_MS_TZ 153 /* MS Time Zone */ +#define GTPIE_IMEI_SV 154 /* IMEI Software Version */ /* 239-250 Reserved for the GPRS charging protocol (see GTP' in GSM 12.15) */ #define GTPIE_CHARGING_ADDR 251 /* Charging Gateway Address */ /* 252-254 Reserved for the GPRS charging protocol (see GTP' in GSM 12.15) */ @@ -188,6 +188,14 @@ struct pdp_t { struct ul255_t pco_req; /* Requested packet control options. */ struct ul255_t pco_neg; /* Negotiated packet control options. */ uint32_t selmode; /* Selection mode. */ + struct ul255_t rattype; /* Radio Access Technology Type */ + int rattype_given; /* Radio Access Technology Type given*/ + struct ul255_t userloc; /* User Location Information */ + int userloc_given; /* User Location Information given*/ + struct ul255_t mstz; /* MS Time Zone */ + int mstz_given; /* MS Time Zone given*/ + struct ul255_t imeisv; /* IMEI Software Version */ + int imeisv_given; /* IMEI Software Version given*/ /* Additional parameters used by library */ diff --git a/sgsnemu/cmdline.c b/sgsnemu/cmdline.c index 0bf6332..f40c583 100644 --- a/sgsnemu/cmdline.c +++ b/sgsnemu/cmdline.c @@ -40,6 +40,10 @@ const char *gengetopt_args_info_help[] = { " --gtpversion=INT GTP version to use (default=`1')", " -a, --apn=STRING Access point name (default=`internet')", " --selmode=INT Selection mode (default=`0x01')", + " --rattype=INT Radio Access Technology Type (optional-1to5)", + " --userloc=STRING User Location Information (optional-type.MCC.MNC.LAC.CIorSACorRAC)", + " --mstz=STRING MS Time Zone (optional- sign.NbQuartersOfAnHour.DSTAdjustment)", + " --imeisv=STRING IMEI(SV) International Mobile Equipment Identity (and Software Version) (optional,16 digits)", " -i, --imsi=STRING IMSI (default=`240010123456789')", " --nsapi=INT NSAPI (default=`0')", " -m, --msisdn=STRING Mobile Station ISDN number (default=`46702123456')", @@ -113,6 +117,10 @@ void clear_given (struct gengetopt_args_info *args_info) args_info->gtpversion_given = 0 ; args_info->apn_given = 0 ; args_info->selmode_given = 0 ; + args_info->rattype_given = 0 ; + args_info->userloc_given = 0 ; + args_info->mstz_given = 0 ; + args_info->imeisv_given = 0 ; args_info->imsi_given = 0 ; args_info->nsapi_given = 0 ; args_info->msisdn_given = 0 ; @@ -158,6 +166,14 @@ void clear_args (struct gengetopt_args_info *args_info) args_info->apn_orig = NULL; args_info->selmode_arg = 0x01; args_info->selmode_orig = NULL; + args_info->rattype_arg = "1"; + args_info->rattype_orig = NULL; + args_info->userloc_arg = strdup("02509946241207"); + args_info->userloc_orig = NULL; + args_info->mstz_arg = strdup("0"); + args_info->mstz_orig = NULL; + args_info->imeisv_arg = strdup("2143658709214365"); + args_info->imeisv_orig = NULL; args_info->imsi_arg = gengetopt_strdup ("240010123456789"); args_info->imsi_orig = NULL; args_info->nsapi_arg = 0; @@ -768,6 +784,10 @@ cmdline_parser_internal (int argc, char * const *argv, struct gengetopt_args_inf { "gtpversion", 1, NULL, 0 }, { "apn", 1, NULL, 'a' }, { "selmode", 1, NULL, 0 }, + { "rattype", 1, NULL, 0}, + { "userloc", 1, NULL, 0}, + { "mstz", 1, NULL, 0}, + { "imeisv", 1, NULL, 0}, { "imsi", 1, NULL, 'i' }, { "nsapi", 1, NULL, 0 }, { "msisdn", 1, NULL, 'm' }, @@ -1143,6 +1163,55 @@ cmdline_parser_internal (int argc, char * const *argv, struct gengetopt_args_inf free (args_info->selmode_orig); /* free previous string */ args_info->selmode_orig = gengetopt_strdup (optarg); } + /* Radio Access Technology Type. */ + else if (strcmp (long_options[option_index].name, "rattype") == 0) + { + if (args_info->rattype_given) + { + fprintf (stderr, "%s: `--rattype' option given more than once\n", PACKAGE); + exit (EXIT_FAILURE); + } + args_info->rattype_given = 1; + /* args_info->rattype_arg = strtol (optarg,&stop_char,0); */ + args_info->rattype_arg = strdup (optarg); + break; + } + /* User Location Information. */ + else if (strcmp (long_options[option_index].name, "userloc") == 0) + { + if (args_info->userloc_given) + { + fprintf (stderr, "%s: `--userloc' option given more than once\n", PACKAGE); + exit (EXIT_FAILURE); + } + args_info->userloc_given = 1; + args_info->userloc_arg = strdup (optarg); + break; + } + /* MS Time Zone */ + else if (strcmp (long_options[option_index].name, "mstz") == 0) + { + if (args_info->mstz_given) + { + fprintf (stderr, "%s: `--mstz' option given more than once\n", PACKAGE); + exit (EXIT_FAILURE); + } + args_info->mstz_given = 1; + args_info->mstz_arg = strdup (optarg); + break; + } + /* IMEI(SV) */ + else if (strcmp (long_options[option_index].name, "imeisv") == 0) + { + if (args_info->imeisv_given) + { + fprintf (stderr, "%s: `--imeisv' option given more than once\n", PACKAGE); + exit (EXIT_FAILURE); + } + args_info->imeisv_given = 1; + args_info->imeisv_arg = strdup (optarg); + break; + } /* NSAPI. */ else if (strcmp (long_options[option_index].name, "nsapi") == 0) { diff --git a/sgsnemu/cmdline.h b/sgsnemu/cmdline.h index a15480d..0871f3e 100644 --- a/sgsnemu/cmdline.h +++ b/sgsnemu/cmdline.h @@ -61,6 +61,18 @@ struct gengetopt_args_info int selmode_arg; /* Selection mode (default='0x01'). */ char * selmode_orig; /* Selection mode original value given at command line. */ const char *selmode_help; /* Selection mode help description. */ + char * rattype_arg; /* Radio Access Technology Type (optional). */ + char * rattype_orig; + char * rattype_help; + char * userloc_arg; /* User Location Information (optional). */ + char * userloc_orig; + char * userloc_help; + char * mstz_arg; /* MS Time Zone (optional). */ + char * mstz_orig; + char * mstz_help; + char * imeisv_arg; /* IMEI(SV) (optional). */ + char * imeisv_orig; + char * imeisv_help; char * imsi_arg; /* IMSI (default='240010123456789'). */ char * imsi_orig; /* IMSI original value given at command line. */ const char *imsi_help; /* IMSI help description. */ @@ -124,6 +136,10 @@ struct gengetopt_args_info int gtpversion_given ; /* Whether gtpversion was given. */ int apn_given ; /* Whether apn was given. */ int selmode_given ; /* Whether selmode was given. */ + int rattype_given ; /* Whether rattype was given. */ + int userloc_given ; /* Whether userloc was given. */ + int mstz_given ; /* Whether mstz was given. */ + int imeisv_given ; /* Whether imeisv was given. */ int imsi_given ; /* Whether imsi was given. */ int nsapi_given ; /* Whether nsapi was given. */ int msisdn_given ; /* Whether msisdn was given. */ diff --git a/sgsnemu/sgsnemu.c b/sgsnemu/sgsnemu.c index 2675c0f..9a15d32 100644 --- a/sgsnemu/sgsnemu.c +++ b/sgsnemu/sgsnemu.c @@ -104,6 +104,14 @@ struct { uint16_t cch; struct ul255_t apn; uint8_t selmode; + struct ul255_t rattype; + int rattype_given; + struct ul255_t userloc; + int userloc_given; + struct ul255_t mstz; + int mstz_given; + struct ul255_t imeisv; + int imeisv_given; struct ul16_t msisdn; } options; @@ -211,6 +219,23 @@ int process_options(int argc, char **argv) { struct hostent *host; unsigned int n; + uint16_t i; + uint8_t a; + uint8_t b; + char * tmp; + char * pch; + char * type; + char * mcc; + char * mnc; + char * lac; + int lac_d; + char * rest; + char *userloc_el[] = {"TYPE","MCC","MNC","LAC","REST"}; + char *mstz_el[] = {"SIGN","QUARTERS","DST"}; + int sign ; + int nbquarters ; + int DST ; + if (cmdline_parser (argc, argv, &args_info) != 0) return -1; @@ -449,6 +474,174 @@ int process_options(int argc, char **argv) { options.selmode = args_info.selmode_arg; printf("Using selection mode: %d\n", args_info.selmode_arg); + /* rattype */ + if (args_info.rattype_given == 1 ) { + options.rattype_given = 1 ; + options.rattype.l = strlen(args_info.rattype_arg) ; + options.rattype.v[0] = atoi(args_info.rattype_arg) ; + printf("Using RAT Type: %s\n", args_info.rattype_arg); + } + + /* userloc */ + if (args_info.userloc_given == 1 ) { + printf("Using User Location Information: %s\n", args_info.userloc_arg); + tmp = args_info.userloc_arg ; + n=0; + pch = strtok (tmp,"."); + while (pch != NULL) { + userloc_el[n] = pch ; + pch = strtok (NULL, "."); + n++; + } + + options.userloc_given = 1 ; + options.userloc.l = 8 ; + + /* 3GPP Geographic Location Type t0 / t1 / t2 */ + type = userloc_el[0]; + printf("->type : %c\n", type[0]); + if ( (strlen(type)!=1) || (!isdigit(type[0])) ) { + printf("Invalid type \n"); + return -1; + } + /* options.userloc.v[0] = 0x00 */ + options.userloc.v[0] = type[0] - 48; + + /* MCC */ + mcc = userloc_el[1] ; + printf("->mcc : %s\n", mcc); + if (strlen(mcc)!=3) { + printf("Invalid MCC lenght\n"); + return -1; + } + + /* MNC */ + mnc = userloc_el[2] ; + printf("->mnc : %s\n", mnc); + + /* octet 5 - MCC Digit 2 - MCC Digit 1 */ + /* options.userloc.v[1] = 0x52 */ + a = (uint8_t) (mcc[0] - 48); + b = (uint8_t) (mcc[1] - 48); + options.userloc.v[1] = 16*b+a ; + + /* octet 6 - MNC Digit 3 - MCC Digit 3 */ + /* options.userloc.v[2] = 0xf0 */ + a = (uint8_t) (mcc[2] - 48); + + if ( (strlen(mnc) > 3) || (strlen(mnc) < 2)) { + printf("Invalid MNC lenght\n"); + return -1; + } + if (strlen(mnc)==2) { + b = 15 ; + } + if (strlen(mnc)==3) { + b = (uint8_t) (mnc[2] - 48); + } + options.userloc.v[2] = 16*b+a ; + + /* octet 7 - MNC Digit 2 - MNC Digit 1 */ + /* options.userloc.v[3] = 0x99*/ + a = (uint8_t) (mnc[0]- 48); + b = (uint8_t) (mnc[1]- 48); + options.userloc.v[3] = 16*b+a ; + + /* LAC */ + lac = userloc_el[3] ; + /*options.userloc.v[4] = 0x12 ; */ + /*options.userloc.v[5] = 0x10 ; */ + printf("->LAC: %s\n", lac); + lac_d = atoi(lac); + if (lac_d>65535 || lac_d<1) { + printf("Invalid LAC\n"); + return -1; + } + i = lac_d >> 8 ; + options.userloc.v[4] = i; /* octet 8 - LAC */ + options.userloc.v[5] = lac_d; /* octet 9 - LAC */ + + /* CI/SAC/RAC */ + rest = userloc_el[4] ; + printf("->CI/SAC/RAC : %s\n", rest); + lac_d = atoi(rest); + if (lac_d>65535 || lac_d<1) { + printf("Invalid CI/SAC/RAC\n"); + return -1; + } + /*options.userloc.v[6] = 0x04 ; */ + /*options.userloc.v[7] = 0xb7 ; */ + i = lac_d >> 8 ; + options.userloc.v[6] = i; /* octet 10 - t0,CI / t1,SAC / t2,RAC */ + options.userloc.v[7] = lac_d; /* octet 11 - t0,CI / t1,SAC / t2,RAC */ + } + /* mstz */ + if (args_info.mstz_given == 1 ) { + options.mstz_given = 1 ; + options.mstz.l = 2 ; + + printf("Using MS Time Zone: %s\n", args_info.mstz_arg); + tmp = args_info.mstz_arg ; + n=0; + pch = strtok (tmp,"."); + while (pch != NULL) { + mstz_el[n] = pch ; + pch = strtok (NULL, "."); + n++; + } + + /* sign */ + sign = atoi(mstz_el[0]) ; + printf("->Sign (0=+ / 1=-): %d\n", sign); + if ( sign!=0 && sign!=1 ) { + printf("Invalid Sign \n"); + return -1; + } + /* nbquarters */ + nbquarters = atoi(mstz_el[1]) ; + printf("->Number of Quarters of an Hour : %d\n", nbquarters); + if ( nbquarters<0 || nbquarters>79 ) { + printf("Invalid Number of Quarters \n"); + return -1; + } + /* DST */ + DST = atoi(mstz_el[2]) ; + printf("->Daylight Saving Time Adjustment : %d\n", DST); + if ( DST<0 || DST>3 ) { + printf("Invalid DST Adjustment \n"); + return -1; + } + /* 12345678 + bits 123 = unit of # of quarters of an hour + bits 678 = # of quarters of an hour / 10 + bit 5 = sign + */ + i= nbquarters % 10 ; + i = i << 4 ; + i = i + nbquarters / 10 + 8 * sign; + /* options.mstz.v[0] = 0x69 ; */ + /* options.mstz.v[1] = 0x01 ; */ + options.mstz.v[0] = i ; + options.mstz.v[1] = DST ; + n = (i & 0x08) ? '-' : '+'; + printf("->Human Readable MS Time Zone : GMT %c %d hours %d minutes\n", n , nbquarters / 4, nbquarters % 4 * 15); + } + + /* imeisv */ + if (args_info.imeisv_given == 1 ) { + options.imeisv_given = 1 ; + if (strlen(args_info.imeisv_arg)!=16) { + printf("Invalid IMEI(SV)\n"); + return -1; + } + options.imeisv.l = 8 ; + for(n=0; n<8; n++) { + a = (uint8_t) (args_info.imeisv_arg [2*n] - 48) ; + b = (uint8_t) (args_info.imeisv_arg [2*n + 1] - 48) ; + options.imeisv.v[n] = 16*b+a ; + } + printf("Using IMEI(SV): %s\n", args_info.imeisv_arg); + } /* msisdn */ if (strlen(args_info.msisdn_arg)>(sizeof(options.msisdn.v)-1)) { @@ -1138,6 +1331,22 @@ int main(int argc, char **argv) pdp->selmode = options.selmode; + pdp->rattype.l = options.rattype.l; + memcpy(pdp->rattype.v, options.rattype.v, options.rattype.l); + pdp->rattype_given = options.rattype_given; + + pdp->userloc.l = options.userloc.l; + memcpy(pdp->userloc.v, options.userloc.v, options.userloc.l); + pdp->userloc_given = options.userloc_given; + + pdp->mstz.l = options.mstz.l; + memcpy(pdp->mstz.v, options.mstz.v, options.mstz.l); + pdp->mstz_given = options.mstz_given; + + pdp->imeisv.l = options.imeisv.l; + memcpy(pdp->imeisv.v, options.imeisv.v, options.imeisv.l); + pdp->imeisv_given = options.imeisv_given; + if (options.apn.l > sizeof(pdp->apn_use.v)) { sys_err(LOG_ERR, __FILE__, __LINE__, 0, "APN length too big"); exit(1); |