diff --git a/sgsnemu/cmdline.c b/sgsnemu/cmdline.c index f40c583..83897cf 100644 --- a/sgsnemu/cmdline.c +++ b/sgsnemu/cmdline.c @@ -47,7 +47,11 @@ const char *gengetopt_args_info_help[] = { " -i, --imsi=STRING IMSI (default=`240010123456789')", " --nsapi=INT NSAPI (default=`0')", " -m, --msisdn=STRING Mobile Station ISDN number (default=`46702123456')", - " -q, --qos=INT Requested quality of service (default=`0x0b921f')", + " -q, --qos=INT Requested quality of service (default=`0x000b921f')", + " --qose1=INT Requested quality of service Extension 1 (example=`0x9396404074f9ffff')", + " --qose2=INT Requested quality of service Extension 2 (example=`0x11')", + " --qose3=INT Requested quality of service Extension 3 (example=`0x0101')", + " --qose4=INT Requested quality of service Extension 4 (example=`0x4040')", " --charging=INT Charging characteristics (default=`0x0800')", " -u, --uid=STRING Login user ID (default=`mig')", " -p, --pwd=STRING Login password (default=`hemmelig')", @@ -125,6 +129,10 @@ void clear_given (struct gengetopt_args_info *args_info) args_info->nsapi_given = 0 ; args_info->msisdn_given = 0 ; args_info->qos_given = 0 ; + args_info->qose1_given = 0 ; + args_info->qose2_given = 0 ; + args_info->qose3_given = 0 ; + args_info->qose4_given = 0 ; args_info->charging_given = 0 ; args_info->uid_given = 0 ; args_info->pwd_given = 0 ; @@ -180,8 +188,16 @@ void clear_args (struct gengetopt_args_info *args_info) args_info->nsapi_orig = NULL; args_info->msisdn_arg = gengetopt_strdup ("46702123456"); args_info->msisdn_orig = NULL; - args_info->qos_arg = 0x0b921f; + args_info->qos_arg = 0x000b921f; args_info->qos_orig = NULL; + args_info->qose1_arg = 0x9396404074f9ffff; + args_info->qose1_orig = NULL; + args_info->qose2_arg = 0x11; + args_info->qose2_orig = NULL; + args_info->qose3_arg = 0x0101; + args_info->qose3_orig = NULL; + args_info->qose4_arg = 0x4040; + args_info->qose4_orig = NULL; args_info->charging_arg = 0x0800; args_info->charging_orig = NULL; args_info->uid_arg = gengetopt_strdup ("mig"); @@ -792,6 +808,10 @@ cmdline_parser_internal (int argc, char * const *argv, struct gengetopt_args_inf { "nsapi", 1, NULL, 0 }, { "msisdn", 1, NULL, 'm' }, { "qos", 1, NULL, 'q' }, + { "qose1", 1, NULL, 0 }, + { "qose2", 1, NULL, 0 }, + { "qose3", 1, NULL, 0 }, + { "qose4", 1, NULL, 0 }, { "charging", 1, NULL, 0 }, { "uid", 1, NULL, 'u' }, { "pwd", 1, NULL, 'p' }, @@ -1163,6 +1183,82 @@ 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); } + /* QoS Extension 1. */ + else if (strcmp (long_options[option_index].name, "qose1") == 0) + { + if (args_info->qose1_given) + { + fprintf (stderr, "%s: `--qose1' option given more than once\n", PACKAGE); + exit (EXIT_FAILURE); + } + args_info->qose1_given = 1; + args_info->qose1_arg = strtoull (optarg, &stop_char, 0); + if (!(stop_char && *stop_char == '\0')) { + fprintf(stderr, "%s: invalid numeric value: %s\n", argv[0], optarg); + goto failure; + } + if (args_info->qose1_orig) + free (args_info->qose1_orig); /* free previous string */ + args_info->qose1_orig = gengetopt_strdup (optarg); + break; + } + /* QoS Extension 2. */ + else if (strcmp (long_options[option_index].name, "qose2") == 0) + { + if (args_info->qose2_given) + { + fprintf (stderr, "%s: `--qose2' option given more than once\n", PACKAGE); + exit (EXIT_FAILURE); + } + args_info->qose2_given = 1; + args_info->qose2_arg = strtol (optarg, &stop_char, 0); + if (!(stop_char && *stop_char == '\0')) { + fprintf(stderr, "%s: invalid numeric value: %s\n", argv[0], optarg); + goto failure; + } + if (args_info->qose2_orig) + free (args_info->qose2_orig); /* free previous string */ + args_info->qose2_orig = gengetopt_strdup (optarg); + break; + } + /* QoS Extension 3. */ + else if (strcmp (long_options[option_index].name, "qose3") == 0) + { + if (args_info->qose3_given) + { + fprintf (stderr, "%s: `--qose3' option given more than once\n", PACKAGE); + exit (EXIT_FAILURE); + } + args_info->qose3_given = 1; + args_info->qose3_arg = strtol (optarg, &stop_char, 0); + if (!(stop_char && *stop_char == '\0')) { + fprintf(stderr, "%s: invalid numeric value: %s\n", argv[0], optarg); + goto failure; + } + if (args_info->qose3_orig) + free (args_info->qose3_orig); /* free previous string */ + args_info->qose3_orig = gengetopt_strdup (optarg); + break; + } + /* QoS Extension 4. */ + else if (strcmp (long_options[option_index].name, "qose4") == 0) + { + if (args_info->qose4_given) + { + fprintf (stderr, "%s: `--qose4' option given more than once\n", PACKAGE); + exit (EXIT_FAILURE); + } + args_info->qose4_given = 1; + args_info->qose4_arg = strtol (optarg, &stop_char, 0); + if (!(stop_char && *stop_char == '\0')) { + fprintf(stderr, "%s: invalid numeric value: %s\n", argv[0], optarg); + goto failure; + } + if (args_info->qose4_orig) + free (args_info->qose4_orig); /* free previous string */ + args_info->qose4_orig = gengetopt_strdup (optarg); + break; + } /* Radio Access Technology Type. */ else if (strcmp (long_options[option_index].name, "rattype") == 0) { diff --git a/sgsnemu/cmdline.h b/sgsnemu/cmdline.h index 0871f3e..869262f 100644 --- a/sgsnemu/cmdline.h +++ b/sgsnemu/cmdline.h @@ -85,6 +85,14 @@ struct gengetopt_args_info int qos_arg; /* Requested quality of service (default='0x0b921f'). */ char * qos_orig; /* Requested quality of service original value given at command line. */ const char *qos_help; /* Requested quality of service help description. */ + unsigned long long int qose1_arg; /* Requested quality of service Extension 1 */ + char * qose1_orig; /* Requested quality of service Extension 1 original value given at command line. */ + int qose2_arg; /* Requested quality of service Extension 2 */ + char * qose2_orig; /* Requested quality of service Extension 2 original value given at command line. */ + int qose3_arg; /* Requested quality of service Extension 3 */ + char * qose3_orig; /* Requested quality of service Extension 3 original value given at command line. */ + int qose4_arg; /* Requested quality of service Extension 4 */ + char * qose4_orig; /* Requested quality of service Extension 4 original value given at command line. */ int charging_arg; /* Charging characteristics (default='0x0800'). */ char * charging_orig; /* Charging characteristics original value given at command line. */ const char *charging_help; /* Charging characteristics help description. */ @@ -144,6 +152,10 @@ struct gengetopt_args_info int nsapi_given ; /* Whether nsapi was given. */ int msisdn_given ; /* Whether msisdn was given. */ int qos_given ; /* Whether qos was given. */ + int qose1_given ; /* Whether qos Extension 1 was given. */ + int qose2_given ; /* Whether qos Extension 2 was given. */ + int qose3_given ; /* Whether qos Extension 3 was given. */ + int qose4_given ; /* Whether qos Extension 4 was given. */ int charging_given ; /* Whether charging was given. */ int uid_given ; /* Whether uid was given. */ int pwd_given ; /* Whether pwd was given. */ diff --git a/sgsnemu/sgsnemu.c b/sgsnemu/sgsnemu.c index 9a15d32..edee09e 100644 --- a/sgsnemu/sgsnemu.c +++ b/sgsnemu/sgsnemu.c @@ -246,6 +246,10 @@ int process_options(int argc, char **argv) { printf("debug: %d\n", args_info.debug_flag); if (args_info.imsi_arg) printf("imsi: %s\n", args_info.imsi_arg); printf("qos: %#08x\n", args_info.qos_arg); + printf("qose1: %#0.16llx\n", args_info.qose1_arg); + printf("qose2: %#04x\n", args_info.qose2_arg); + printf("qose3: %#06x\n", args_info.qose3_arg); + printf("qose4: %#06x\n", args_info.qose4_arg); printf("charging: %#04x\n", args_info.charging_arg); if (args_info.apn_arg) printf("apn: %s\n", args_info.apn_arg); if (args_info.msisdn_arg) printf("msisdn: %s\n", args_info.msisdn_arg); @@ -280,6 +284,10 @@ int process_options(int argc, char **argv) { printf("debug: %d\n", args_info.debug_flag); if (args_info.imsi_arg) printf("imsi: %s\n", args_info.imsi_arg); printf("qos: %#08x\n", args_info.qos_arg); + printf("qose1: %#0.16llx\n", args_info.qose1_arg); + printf("qose2: %#04x\n", args_info.qose2_arg); + printf("qose3: %#06x\n", args_info.qose3_arg); + printf("qose4: %#06x\n", args_info.qose4_arg); printf("charging: %#04x\n", args_info.charging_arg); if (args_info.apn_arg) printf("apn: %s\n", args_info.apn_arg); if (args_info.msisdn_arg) printf("msisdn: %s\n", args_info.msisdn_arg); @@ -431,11 +439,38 @@ int process_options(int argc, char **argv) { /* qos */ - options.qos.l = 3; - options.qos.v[2] = (args_info.qos_arg) & 0xff; - options.qos.v[1] = ((args_info.qos_arg) >> 8) & 0xff; - options.qos.v[0] = ((args_info.qos_arg) >> 16) & 0xff; - + options.qos.l = 4; + options.qos.v[3] = (args_info.qos_arg) & 0xff; + options.qos.v[2] = ((args_info.qos_arg) >> 8)& 0xff; + options.qos.v[1] = ((args_info.qos_arg) >> 16) & 0xff; + options.qos.v[0] = ((args_info.qos_arg) >> 24) & 0xff; + /* Extensions according to 3GPP TS 24.008 */ + if (args_info.qose1_given == 1 ) { + options.qos.l = 12; + options.qos.v[11] = (args_info.qose1_arg) & 0xff; + options.qos.v[10] = ((args_info.qose1_arg) >> 8)& 0xff; + options.qos.v[9] = ((args_info.qose1_arg) >> 16)& 0xff; + options.qos.v[8] = ((args_info.qose1_arg) >> 24)& 0xff; + options.qos.v[7] = ((args_info.qose1_arg) >> 32)& 0xff; + options.qos.v[6] = ((args_info.qose1_arg) >> 40) & 0xff; + options.qos.v[5] = ((args_info.qose1_arg) >> 48) & 0xff; + options.qos.v[4] = ((args_info.qose1_arg) >> 56) & 0xff; + if (args_info.qose2_given == 1 ) { + options.qos.l = 13; + options.qos.v[12] = (args_info.qose2_arg) & 0xff; + if (args_info.qose3_given == 1 ) { + options.qos.l = 15; + options.qos.v[14] = (args_info.qose3_arg) & 0xff; + options.qos.v[13] = ((args_info.qose3_arg) >> 8)& 0xff; + if (args_info.qose4_given == 1 ) { + options.qos.l = 17; + options.qos.v[16] = (args_info.qose4_arg) & 0xff; + options.qos.v[15] = ((args_info.qose4_arg) >> 8)& 0xff; + } + } + } + } + /* charging */ options.cch = args_info.charging_arg; @@ -1316,18 +1351,18 @@ int main(int argc, char **argv) pdp->ipif = tun; /* TODO */ iparr[n].pdp = pdp; - if (options.qos.l > sizeof(pdp->qos_req0)) { - sys_err(LOG_ERR, __FILE__, __LINE__, 0, "QoS length too big"); - exit(1); - } - else { - memcpy(pdp->qos_req0, options.qos.v, options.qos.l); + if (options.gtpversion == 0) { + if (options.qos.l - 1 > sizeof(pdp->qos_req0)) { + sys_err(LOG_ERR, __FILE__, __LINE__, 0, "QoS length too big"); + exit(1); + } + else { + memcpy(pdp->qos_req0, options.qos.v, options.qos.l); + } } - /* TODO */ - pdp->qos_req.l = 4; - pdp->qos_req.v[0] = 0x00; - memcpy(pdp->qos_req.v+1, options.qos.v, options.qos.l); + pdp->qos_req.l = options.qos.l ; + memcpy(pdp->qos_req.v, options.qos.v, options.qos.l); pdp->selmode = options.selmode;