aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ggsn/cmdline.c1974
-rw-r--r--ggsn/cmdline.h199
-rw-r--r--ggsn/ggsn.c924
-rw-r--r--gtp/gtp.c5425
-rw-r--r--gtp/gtp.h457
-rw-r--r--gtp/gtpie.c1029
-rw-r--r--gtp/gtpie.h289
-rw-r--r--gtp/lookupa.c256
-rw-r--r--gtp/lookupa.h8
-rw-r--r--gtp/pdp.c309
-rw-r--r--gtp/pdp.h274
-rw-r--r--gtp/queue.c402
-rw-r--r--gtp/queue.h55
-rw-r--r--lib/getopt.c1320
-rw-r--r--lib/getopt1.c197
-rw-r--r--lib/gnugetopt.h105
-rw-r--r--lib/ippool.c939
-rw-r--r--lib/ippool.h49
-rwxr-xr-xlib/lookup.c96
-rwxr-xr-xlib/lookup.h5
-rw-r--r--lib/syserr.c87
-rw-r--r--lib/syserr.h2
-rw-r--r--lib/tun.c1178
-rw-r--r--lib/tun.h61
-rw-r--r--sgsnemu/cmdline.c3449
-rw-r--r--sgsnemu/cmdline.h369
-rw-r--r--sgsnemu/sgsnemu.c3006
27 files changed, 11558 insertions, 10906 deletions
diff --git a/ggsn/cmdline.c b/ggsn/cmdline.c
index d83376f..c5da6b4 100644
--- a/ggsn/cmdline.c
+++ b/ggsn/cmdline.c
@@ -23,878 +23,939 @@
const char *gengetopt_args_info_purpose = "";
-const char *gengetopt_args_info_usage = "Usage: " CMDLINE_PARSER_PACKAGE " [OPTIONS]...";
+const char *gengetopt_args_info_usage =
+ "Usage: " CMDLINE_PARSER_PACKAGE " [OPTIONS]...";
const char *gengetopt_args_info_help[] = {
- " -h, --help Print help and exit",
- " -V, --version Print version and exit",
- " -f, --fg Run in foreground (default=off)",
- " -d, --debug Run in debug mode (default=off)",
- " -c, --conf=STRING Read configuration file (default=`/etc/ggsn.conf')",
- " --pidfile=STRING Filename of process id file \n (default=`/var/run/ggsn.pid')",
- " --statedir=STRING Directory of nonvolatile data \n (default=`/var/lib/ggsn/')",
- " -l, --listen=STRING Local interface",
- " -n, --net=STRING Network (default=`192.168.0.0/24')",
- " --ipup=STRING Script to run after link-up",
- " --ipdown=STRING Script to run after link-down",
- " --dynip=STRING Dynamic IP address pool",
- " --statip=STRING Static IP address pool",
- " --pcodns1=STRING PCO DNS Server 1 (default=`0.0.0.0')",
- " --pcodns2=STRING PCO DNS Server 2 (default=`0.0.0.0')",
- " --timelimit=INT Exit after timelimit seconds (default=`0')",
- " -a, --apn=STRING Access point name (default=`internet')",
- " -q, --qos=INT Requested quality of service (default=`0x0b921f')",
- 0
+ " -h, --help Print help and exit",
+ " -V, --version Print version and exit",
+ " -f, --fg Run in foreground (default=off)",
+ " -d, --debug Run in debug mode (default=off)",
+ " -c, --conf=STRING Read configuration file (default=`/etc/ggsn.conf')",
+ " --pidfile=STRING Filename of process id file \n (default=`/var/run/ggsn.pid')",
+ " --statedir=STRING Directory of nonvolatile data \n (default=`/var/lib/ggsn/')",
+ " -l, --listen=STRING Local interface",
+ " -n, --net=STRING Network (default=`192.168.0.0/24')",
+ " --ipup=STRING Script to run after link-up",
+ " --ipdown=STRING Script to run after link-down",
+ " --dynip=STRING Dynamic IP address pool",
+ " --statip=STRING Static IP address pool",
+ " --pcodns1=STRING PCO DNS Server 1 (default=`0.0.0.0')",
+ " --pcodns2=STRING PCO DNS Server 2 (default=`0.0.0.0')",
+ " --timelimit=INT Exit after timelimit seconds (default=`0')",
+ " -a, --apn=STRING Access point name (default=`internet')",
+ " -q, --qos=INT Requested quality of service (default=`0x0b921f')",
+ 0
};
static
-void clear_given (struct gengetopt_args_info *args_info);
+void clear_given(struct gengetopt_args_info *args_info);
static
-void clear_args (struct gengetopt_args_info *args_info);
+void clear_args(struct gengetopt_args_info *args_info);
static int
-cmdline_parser_internal (int argc, char * const *argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required, const char *additional_error);
-
-struct line_list
-{
- char * string_arg;
- struct line_list * next;
+cmdline_parser_internal(int argc, char *const *argv,
+ struct gengetopt_args_info *args_info, int override,
+ int initialize, int check_required,
+ const char *additional_error);
+
+struct line_list {
+ char *string_arg;
+ struct line_list *next;
};
static struct line_list *cmd_line_list = 0;
static struct line_list *cmd_line_list_tmp = 0;
-static void
-free_cmd_list(void)
+static void free_cmd_list(void)
{
- /* free the list of a previous call */
- if (cmd_line_list)
- {
- while (cmd_line_list) {
- cmd_line_list_tmp = cmd_line_list;
- cmd_line_list = cmd_line_list->next;
- free (cmd_line_list_tmp->string_arg);
- free (cmd_line_list_tmp);
- }
- }
+ /* free the list of a previous call */
+ if (cmd_line_list) {
+ while (cmd_line_list) {
+ cmd_line_list_tmp = cmd_line_list;
+ cmd_line_list = cmd_line_list->next;
+ free(cmd_line_list_tmp->string_arg);
+ free(cmd_line_list_tmp);
+ }
+ }
}
-
-static char *
-gengetopt_strdup (const char *s);
+static char *gengetopt_strdup(const char *s);
static
-void clear_given (struct gengetopt_args_info *args_info)
+void clear_given(struct gengetopt_args_info *args_info)
{
- args_info->help_given = 0 ;
- args_info->version_given = 0 ;
- args_info->fg_given = 0 ;
- args_info->debug_given = 0 ;
- args_info->conf_given = 0 ;
- args_info->pidfile_given = 0 ;
- args_info->statedir_given = 0 ;
- args_info->listen_given = 0 ;
- args_info->net_given = 0 ;
- args_info->ipup_given = 0 ;
- args_info->ipdown_given = 0 ;
- args_info->dynip_given = 0 ;
- args_info->statip_given = 0 ;
- args_info->pcodns1_given = 0 ;
- args_info->pcodns2_given = 0 ;
- args_info->timelimit_given = 0 ;
- args_info->apn_given = 0 ;
- args_info->qos_given = 0 ;
+ args_info->help_given = 0;
+ args_info->version_given = 0;
+ args_info->fg_given = 0;
+ args_info->debug_given = 0;
+ args_info->conf_given = 0;
+ args_info->pidfile_given = 0;
+ args_info->statedir_given = 0;
+ args_info->listen_given = 0;
+ args_info->net_given = 0;
+ args_info->ipup_given = 0;
+ args_info->ipdown_given = 0;
+ args_info->dynip_given = 0;
+ args_info->statip_given = 0;
+ args_info->pcodns1_given = 0;
+ args_info->pcodns2_given = 0;
+ args_info->timelimit_given = 0;
+ args_info->apn_given = 0;
+ args_info->qos_given = 0;
}
static
-void clear_args (struct gengetopt_args_info *args_info)
+void clear_args(struct gengetopt_args_info *args_info)
{
- args_info->fg_flag = 0;
- args_info->debug_flag = 0;
- args_info->conf_arg = gengetopt_strdup ("/etc/ggsn.conf");
- args_info->conf_orig = NULL;
- args_info->pidfile_arg = gengetopt_strdup ("/var/run/ggsn.pid");
- args_info->pidfile_orig = NULL;
- args_info->statedir_arg = gengetopt_strdup ("/var/lib/ggsn/");
- args_info->statedir_orig = NULL;
- args_info->listen_arg = NULL;
- args_info->listen_orig = NULL;
- args_info->net_arg = gengetopt_strdup ("192.168.0.0/24");
- args_info->net_orig = NULL;
- args_info->ipup_arg = NULL;
- args_info->ipup_orig = NULL;
- args_info->ipdown_arg = NULL;
- args_info->ipdown_orig = NULL;
- args_info->dynip_arg = NULL;
- args_info->dynip_orig = NULL;
- args_info->statip_arg = NULL;
- args_info->statip_orig = NULL;
- args_info->pcodns1_arg = gengetopt_strdup ("0.0.0.0");
- args_info->pcodns1_orig = NULL;
- args_info->pcodns2_arg = gengetopt_strdup ("0.0.0.0");
- args_info->pcodns2_orig = NULL;
- args_info->timelimit_arg = 0;
- args_info->timelimit_orig = NULL;
- args_info->apn_arg = gengetopt_strdup ("internet");
- args_info->apn_orig = NULL;
- args_info->qos_arg = 0x0b921f;
- args_info->qos_orig = NULL;
-
+ args_info->fg_flag = 0;
+ args_info->debug_flag = 0;
+ args_info->conf_arg = gengetopt_strdup("/etc/ggsn.conf");
+ args_info->conf_orig = NULL;
+ args_info->pidfile_arg = gengetopt_strdup("/var/run/ggsn.pid");
+ args_info->pidfile_orig = NULL;
+ args_info->statedir_arg = gengetopt_strdup("/var/lib/ggsn/");
+ args_info->statedir_orig = NULL;
+ args_info->listen_arg = NULL;
+ args_info->listen_orig = NULL;
+ args_info->net_arg = gengetopt_strdup("192.168.0.0/24");
+ args_info->net_orig = NULL;
+ args_info->ipup_arg = NULL;
+ args_info->ipup_orig = NULL;
+ args_info->ipdown_arg = NULL;
+ args_info->ipdown_orig = NULL;
+ args_info->dynip_arg = NULL;
+ args_info->dynip_orig = NULL;
+ args_info->statip_arg = NULL;
+ args_info->statip_orig = NULL;
+ args_info->pcodns1_arg = gengetopt_strdup("0.0.0.0");
+ args_info->pcodns1_orig = NULL;
+ args_info->pcodns2_arg = gengetopt_strdup("0.0.0.0");
+ args_info->pcodns2_orig = NULL;
+ args_info->timelimit_arg = 0;
+ args_info->timelimit_orig = NULL;
+ args_info->apn_arg = gengetopt_strdup("internet");
+ args_info->apn_orig = NULL;
+ args_info->qos_arg = 0x0b921f;
+ args_info->qos_orig = NULL;
+
}
static
void init_args_info(struct gengetopt_args_info *args_info)
{
- args_info->help_help = gengetopt_args_info_help[0] ;
- args_info->version_help = gengetopt_args_info_help[1] ;
- args_info->fg_help = gengetopt_args_info_help[2] ;
- args_info->debug_help = gengetopt_args_info_help[3] ;
- args_info->conf_help = gengetopt_args_info_help[4] ;
- args_info->pidfile_help = gengetopt_args_info_help[5] ;
- args_info->statedir_help = gengetopt_args_info_help[6] ;
- args_info->listen_help = gengetopt_args_info_help[7] ;
- args_info->net_help = gengetopt_args_info_help[8] ;
- args_info->ipup_help = gengetopt_args_info_help[9] ;
- args_info->ipdown_help = gengetopt_args_info_help[10] ;
- args_info->dynip_help = gengetopt_args_info_help[11] ;
- args_info->statip_help = gengetopt_args_info_help[12] ;
- args_info->pcodns1_help = gengetopt_args_info_help[13] ;
- args_info->pcodns2_help = gengetopt_args_info_help[14] ;
- args_info->timelimit_help = gengetopt_args_info_help[15] ;
- args_info->apn_help = gengetopt_args_info_help[16] ;
- args_info->qos_help = gengetopt_args_info_help[17] ;
-
+ args_info->help_help = gengetopt_args_info_help[0];
+ args_info->version_help = gengetopt_args_info_help[1];
+ args_info->fg_help = gengetopt_args_info_help[2];
+ args_info->debug_help = gengetopt_args_info_help[3];
+ args_info->conf_help = gengetopt_args_info_help[4];
+ args_info->pidfile_help = gengetopt_args_info_help[5];
+ args_info->statedir_help = gengetopt_args_info_help[6];
+ args_info->listen_help = gengetopt_args_info_help[7];
+ args_info->net_help = gengetopt_args_info_help[8];
+ args_info->ipup_help = gengetopt_args_info_help[9];
+ args_info->ipdown_help = gengetopt_args_info_help[10];
+ args_info->dynip_help = gengetopt_args_info_help[11];
+ args_info->statip_help = gengetopt_args_info_help[12];
+ args_info->pcodns1_help = gengetopt_args_info_help[13];
+ args_info->pcodns2_help = gengetopt_args_info_help[14];
+ args_info->timelimit_help = gengetopt_args_info_help[15];
+ args_info->apn_help = gengetopt_args_info_help[16];
+ args_info->qos_help = gengetopt_args_info_help[17];
+
}
-void
-cmdline_parser_print_version (void)
+void cmdline_parser_print_version(void)
{
- printf ("%s %s\n", CMDLINE_PARSER_PACKAGE, CMDLINE_PARSER_VERSION);
+ printf("%s %s\n", CMDLINE_PARSER_PACKAGE, CMDLINE_PARSER_VERSION);
}
-void
-cmdline_parser_print_help (void)
+void cmdline_parser_print_help(void)
{
- int i = 0;
- cmdline_parser_print_version ();
+ int i = 0;
+ cmdline_parser_print_version();
- if (strlen(gengetopt_args_info_purpose) > 0)
- printf("\n%s\n", gengetopt_args_info_purpose);
+ if (strlen(gengetopt_args_info_purpose) > 0)
+ printf("\n%s\n", gengetopt_args_info_purpose);
- printf("\n%s\n\n", gengetopt_args_info_usage);
- while (gengetopt_args_info_help[i])
- printf("%s\n", gengetopt_args_info_help[i++]);
+ printf("\n%s\n\n", gengetopt_args_info_usage);
+ while (gengetopt_args_info_help[i])
+ printf("%s\n", gengetopt_args_info_help[i++]);
}
-void
-cmdline_parser_init (struct gengetopt_args_info *args_info)
+void cmdline_parser_init(struct gengetopt_args_info *args_info)
{
- clear_given (args_info);
- clear_args (args_info);
- init_args_info (args_info);
+ clear_given(args_info);
+ clear_args(args_info);
+ init_args_info(args_info);
}
-static void
-cmdline_parser_release (struct gengetopt_args_info *args_info)
+static void cmdline_parser_release(struct gengetopt_args_info *args_info)
{
-
- if (args_info->conf_arg)
- {
- free (args_info->conf_arg); /* free previous argument */
- args_info->conf_arg = 0;
- }
- if (args_info->conf_orig)
- {
- free (args_info->conf_orig); /* free previous argument */
- args_info->conf_orig = 0;
- }
- if (args_info->pidfile_arg)
- {
- free (args_info->pidfile_arg); /* free previous argument */
- args_info->pidfile_arg = 0;
- }
- if (args_info->pidfile_orig)
- {
- free (args_info->pidfile_orig); /* free previous argument */
- args_info->pidfile_orig = 0;
- }
- if (args_info->statedir_arg)
- {
- free (args_info->statedir_arg); /* free previous argument */
- args_info->statedir_arg = 0;
- }
- if (args_info->statedir_orig)
- {
- free (args_info->statedir_orig); /* free previous argument */
- args_info->statedir_orig = 0;
- }
- if (args_info->listen_arg)
- {
- free (args_info->listen_arg); /* free previous argument */
- args_info->listen_arg = 0;
- }
- if (args_info->listen_orig)
- {
- free (args_info->listen_orig); /* free previous argument */
- args_info->listen_orig = 0;
- }
- if (args_info->net_arg)
- {
- free (args_info->net_arg); /* free previous argument */
- args_info->net_arg = 0;
- }
- if (args_info->net_orig)
- {
- free (args_info->net_orig); /* free previous argument */
- args_info->net_orig = 0;
- }
- if (args_info->ipup_arg)
- {
- free (args_info->ipup_arg); /* free previous argument */
- args_info->ipup_arg = 0;
- }
- if (args_info->ipup_orig)
- {
- free (args_info->ipup_orig); /* free previous argument */
- args_info->ipup_orig = 0;
- }
- if (args_info->ipdown_arg)
- {
- free (args_info->ipdown_arg); /* free previous argument */
- args_info->ipdown_arg = 0;
- }
- if (args_info->ipdown_orig)
- {
- free (args_info->ipdown_orig); /* free previous argument */
- args_info->ipdown_orig = 0;
- }
- if (args_info->dynip_arg)
- {
- free (args_info->dynip_arg); /* free previous argument */
- args_info->dynip_arg = 0;
- }
- if (args_info->dynip_orig)
- {
- free (args_info->dynip_orig); /* free previous argument */
- args_info->dynip_orig = 0;
- }
- if (args_info->statip_arg)
- {
- free (args_info->statip_arg); /* free previous argument */
- args_info->statip_arg = 0;
- }
- if (args_info->statip_orig)
- {
- free (args_info->statip_orig); /* free previous argument */
- args_info->statip_orig = 0;
- }
- if (args_info->pcodns1_arg)
- {
- free (args_info->pcodns1_arg); /* free previous argument */
- args_info->pcodns1_arg = 0;
- }
- if (args_info->pcodns1_orig)
- {
- free (args_info->pcodns1_orig); /* free previous argument */
- args_info->pcodns1_orig = 0;
- }
- if (args_info->pcodns2_arg)
- {
- free (args_info->pcodns2_arg); /* free previous argument */
- args_info->pcodns2_arg = 0;
- }
- if (args_info->pcodns2_orig)
- {
- free (args_info->pcodns2_orig); /* free previous argument */
- args_info->pcodns2_orig = 0;
- }
- if (args_info->timelimit_orig)
- {
- free (args_info->timelimit_orig); /* free previous argument */
- args_info->timelimit_orig = 0;
- }
- if (args_info->apn_arg)
- {
- free (args_info->apn_arg); /* free previous argument */
- args_info->apn_arg = 0;
- }
- if (args_info->apn_orig)
- {
- free (args_info->apn_orig); /* free previous argument */
- args_info->apn_orig = 0;
- }
- if (args_info->qos_orig)
- {
- free (args_info->qos_orig); /* free previous argument */
- args_info->qos_orig = 0;
- }
-
- clear_given (args_info);
+
+ if (args_info->conf_arg) {
+ free(args_info->conf_arg); /* free previous argument */
+ args_info->conf_arg = 0;
+ }
+ if (args_info->conf_orig) {
+ free(args_info->conf_orig); /* free previous argument */
+ args_info->conf_orig = 0;
+ }
+ if (args_info->pidfile_arg) {
+ free(args_info->pidfile_arg); /* free previous argument */
+ args_info->pidfile_arg = 0;
+ }
+ if (args_info->pidfile_orig) {
+ free(args_info->pidfile_orig); /* free previous argument */
+ args_info->pidfile_orig = 0;
+ }
+ if (args_info->statedir_arg) {
+ free(args_info->statedir_arg); /* free previous argument */
+ args_info->statedir_arg = 0;
+ }
+ if (args_info->statedir_orig) {
+ free(args_info->statedir_orig); /* free previous argument */
+ args_info->statedir_orig = 0;
+ }
+ if (args_info->listen_arg) {
+ free(args_info->listen_arg); /* free previous argument */
+ args_info->listen_arg = 0;
+ }
+ if (args_info->listen_orig) {
+ free(args_info->listen_orig); /* free previous argument */
+ args_info->listen_orig = 0;
+ }
+ if (args_info->net_arg) {
+ free(args_info->net_arg); /* free previous argument */
+ args_info->net_arg = 0;
+ }
+ if (args_info->net_orig) {
+ free(args_info->net_orig); /* free previous argument */
+ args_info->net_orig = 0;
+ }
+ if (args_info->ipup_arg) {
+ free(args_info->ipup_arg); /* free previous argument */
+ args_info->ipup_arg = 0;
+ }
+ if (args_info->ipup_orig) {
+ free(args_info->ipup_orig); /* free previous argument */
+ args_info->ipup_orig = 0;
+ }
+ if (args_info->ipdown_arg) {
+ free(args_info->ipdown_arg); /* free previous argument */
+ args_info->ipdown_arg = 0;
+ }
+ if (args_info->ipdown_orig) {
+ free(args_info->ipdown_orig); /* free previous argument */
+ args_info->ipdown_orig = 0;
+ }
+ if (args_info->dynip_arg) {
+ free(args_info->dynip_arg); /* free previous argument */
+ args_info->dynip_arg = 0;
+ }
+ if (args_info->dynip_orig) {
+ free(args_info->dynip_orig); /* free previous argument */
+ args_info->dynip_orig = 0;
+ }
+ if (args_info->statip_arg) {
+ free(args_info->statip_arg); /* free previous argument */
+ args_info->statip_arg = 0;
+ }
+ if (args_info->statip_orig) {
+ free(args_info->statip_orig); /* free previous argument */
+ args_info->statip_orig = 0;
+ }
+ if (args_info->pcodns1_arg) {
+ free(args_info->pcodns1_arg); /* free previous argument */
+ args_info->pcodns1_arg = 0;
+ }
+ if (args_info->pcodns1_orig) {
+ free(args_info->pcodns1_orig); /* free previous argument */
+ args_info->pcodns1_orig = 0;
+ }
+ if (args_info->pcodns2_arg) {
+ free(args_info->pcodns2_arg); /* free previous argument */
+ args_info->pcodns2_arg = 0;
+ }
+ if (args_info->pcodns2_orig) {
+ free(args_info->pcodns2_orig); /* free previous argument */
+ args_info->pcodns2_orig = 0;
+ }
+ if (args_info->timelimit_orig) {
+ free(args_info->timelimit_orig); /* free previous argument */
+ args_info->timelimit_orig = 0;
+ }
+ if (args_info->apn_arg) {
+ free(args_info->apn_arg); /* free previous argument */
+ args_info->apn_arg = 0;
+ }
+ if (args_info->apn_orig) {
+ free(args_info->apn_orig); /* free previous argument */
+ args_info->apn_orig = 0;
+ }
+ if (args_info->qos_orig) {
+ free(args_info->qos_orig); /* free previous argument */
+ args_info->qos_orig = 0;
+ }
+
+ clear_given(args_info);
}
int
-cmdline_parser_file_save(const char *filename, struct gengetopt_args_info *args_info)
+cmdline_parser_file_save(const char *filename,
+ struct gengetopt_args_info *args_info)
{
- FILE *outfile;
- int i = 0;
-
- outfile = fopen(filename, "w");
-
- if (!outfile)
- {
- fprintf (stderr, "%s: cannot open file for writing: %s\n", CMDLINE_PARSER_PACKAGE, filename);
- return EXIT_FAILURE;
- }
-
- if (args_info->help_given) {
- fprintf(outfile, "%s\n", "help");
- }
- if (args_info->version_given) {
- fprintf(outfile, "%s\n", "version");
- }
- if (args_info->fg_given) {
- fprintf(outfile, "%s\n", "fg");
- }
- if (args_info->debug_given) {
- fprintf(outfile, "%s\n", "debug");
- }
- if (args_info->conf_given) {
- if (args_info->conf_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "conf", args_info->conf_orig);
- } else {
- fprintf(outfile, "%s\n", "conf");
- }
- }
- if (args_info->pidfile_given) {
- if (args_info->pidfile_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "pidfile", args_info->pidfile_orig);
- } else {
- fprintf(outfile, "%s\n", "pidfile");
- }
- }
- if (args_info->statedir_given) {
- if (args_info->statedir_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "statedir", args_info->statedir_orig);
- } else {
- fprintf(outfile, "%s\n", "statedir");
- }
- }
- if (args_info->listen_given) {
- if (args_info->listen_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "listen", args_info->listen_orig);
- } else {
- fprintf(outfile, "%s\n", "listen");
- }
- }
- if (args_info->net_given) {
- if (args_info->net_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "net", args_info->net_orig);
- } else {
- fprintf(outfile, "%s\n", "net");
- }
- }
- if (args_info->ipup_given) {
- if (args_info->ipup_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "ipup", args_info->ipup_orig);
- } else {
- fprintf(outfile, "%s\n", "ipup");
- }
- }
- if (args_info->ipdown_given) {
- if (args_info->ipdown_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "ipdown", args_info->ipdown_orig);
- } else {
- fprintf(outfile, "%s\n", "ipdown");
- }
- }
- if (args_info->dynip_given) {
- if (args_info->dynip_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "dynip", args_info->dynip_orig);
- } else {
- fprintf(outfile, "%s\n", "dynip");
- }
- }
- if (args_info->statip_given) {
- if (args_info->statip_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "statip", args_info->statip_orig);
- } else {
- fprintf(outfile, "%s\n", "statip");
- }
- }
- if (args_info->pcodns1_given) {
- if (args_info->pcodns1_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "pcodns1", args_info->pcodns1_orig);
- } else {
- fprintf(outfile, "%s\n", "pcodns1");
- }
- }
- if (args_info->pcodns2_given) {
- if (args_info->pcodns2_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "pcodns2", args_info->pcodns2_orig);
- } else {
- fprintf(outfile, "%s\n", "pcodns2");
- }
- }
- if (args_info->timelimit_given) {
- if (args_info->timelimit_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "timelimit", args_info->timelimit_orig);
- } else {
- fprintf(outfile, "%s\n", "timelimit");
- }
- }
- if (args_info->apn_given) {
- if (args_info->apn_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "apn", args_info->apn_orig);
- } else {
- fprintf(outfile, "%s\n", "apn");
- }
- }
- if (args_info->qos_given) {
- if (args_info->qos_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "qos", args_info->qos_orig);
- } else {
- fprintf(outfile, "%s\n", "qos");
- }
- }
-
- fclose (outfile);
-
- i = EXIT_SUCCESS;
- return i;
+ FILE *outfile;
+ int i = 0;
+
+ outfile = fopen(filename, "w");
+
+ if (!outfile) {
+ fprintf(stderr, "%s: cannot open file for writing: %s\n",
+ CMDLINE_PARSER_PACKAGE, filename);
+ return EXIT_FAILURE;
+ }
+
+ if (args_info->help_given) {
+ fprintf(outfile, "%s\n", "help");
+ }
+ if (args_info->version_given) {
+ fprintf(outfile, "%s\n", "version");
+ }
+ if (args_info->fg_given) {
+ fprintf(outfile, "%s\n", "fg");
+ }
+ if (args_info->debug_given) {
+ fprintf(outfile, "%s\n", "debug");
+ }
+ if (args_info->conf_given) {
+ if (args_info->conf_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "conf",
+ args_info->conf_orig);
+ } else {
+ fprintf(outfile, "%s\n", "conf");
+ }
+ }
+ if (args_info->pidfile_given) {
+ if (args_info->pidfile_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "pidfile",
+ args_info->pidfile_orig);
+ } else {
+ fprintf(outfile, "%s\n", "pidfile");
+ }
+ }
+ if (args_info->statedir_given) {
+ if (args_info->statedir_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "statedir",
+ args_info->statedir_orig);
+ } else {
+ fprintf(outfile, "%s\n", "statedir");
+ }
+ }
+ if (args_info->listen_given) {
+ if (args_info->listen_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "listen",
+ args_info->listen_orig);
+ } else {
+ fprintf(outfile, "%s\n", "listen");
+ }
+ }
+ if (args_info->net_given) {
+ if (args_info->net_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "net",
+ args_info->net_orig);
+ } else {
+ fprintf(outfile, "%s\n", "net");
+ }
+ }
+ if (args_info->ipup_given) {
+ if (args_info->ipup_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "ipup",
+ args_info->ipup_orig);
+ } else {
+ fprintf(outfile, "%s\n", "ipup");
+ }
+ }
+ if (args_info->ipdown_given) {
+ if (args_info->ipdown_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "ipdown",
+ args_info->ipdown_orig);
+ } else {
+ fprintf(outfile, "%s\n", "ipdown");
+ }
+ }
+ if (args_info->dynip_given) {
+ if (args_info->dynip_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "dynip",
+ args_info->dynip_orig);
+ } else {
+ fprintf(outfile, "%s\n", "dynip");
+ }
+ }
+ if (args_info->statip_given) {
+ if (args_info->statip_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "statip",
+ args_info->statip_orig);
+ } else {
+ fprintf(outfile, "%s\n", "statip");
+ }
+ }
+ if (args_info->pcodns1_given) {
+ if (args_info->pcodns1_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "pcodns1",
+ args_info->pcodns1_orig);
+ } else {
+ fprintf(outfile, "%s\n", "pcodns1");
+ }
+ }
+ if (args_info->pcodns2_given) {
+ if (args_info->pcodns2_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "pcodns2",
+ args_info->pcodns2_orig);
+ } else {
+ fprintf(outfile, "%s\n", "pcodns2");
+ }
+ }
+ if (args_info->timelimit_given) {
+ if (args_info->timelimit_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "timelimit",
+ args_info->timelimit_orig);
+ } else {
+ fprintf(outfile, "%s\n", "timelimit");
+ }
+ }
+ if (args_info->apn_given) {
+ if (args_info->apn_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "apn",
+ args_info->apn_orig);
+ } else {
+ fprintf(outfile, "%s\n", "apn");
+ }
+ }
+ if (args_info->qos_given) {
+ if (args_info->qos_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "qos",
+ args_info->qos_orig);
+ } else {
+ fprintf(outfile, "%s\n", "qos");
+ }
+ }
+
+ fclose(outfile);
+
+ i = EXIT_SUCCESS;
+ return i;
}
-void
-cmdline_parser_free (struct gengetopt_args_info *args_info)
+void cmdline_parser_free(struct gengetopt_args_info *args_info)
{
- cmdline_parser_release (args_info);
+ cmdline_parser_release(args_info);
}
-
/* gengetopt_strdup() */
/* strdup.c replacement of strdup, which is not standard */
-char *
-gengetopt_strdup (const char *s)
+char *gengetopt_strdup(const char *s)
{
- char *result = NULL;
- if (!s)
- return result;
-
- result = (char*)malloc(strlen(s) + 1);
- if (result == (char*)0)
- return (char*)0;
- strcpy(result, s);
- return result;
+ char *result = NULL;
+ if (!s)
+ return result;
+
+ result = (char *)malloc(strlen(s) + 1);
+ if (result == (char *)0)
+ return (char *)0;
+ strcpy(result, s);
+ return result;
}
int
-cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+cmdline_parser(int argc, char *const *argv,
+ struct gengetopt_args_info *args_info)
{
- return cmdline_parser2 (argc, argv, args_info, 0, 1, 1);
+ return cmdline_parser2(argc, argv, args_info, 0, 1, 1);
}
int
-cmdline_parser2 (int argc, char * const *argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required)
+cmdline_parser2(int argc, char *const *argv,
+ struct gengetopt_args_info *args_info, int override,
+ int initialize, int check_required)
{
- int result;
+ int result;
+
+ result =
+ cmdline_parser_internal(argc, argv, args_info, override, initialize,
+ check_required, NULL);
- result = cmdline_parser_internal (argc, argv, args_info, override, initialize, check_required, NULL);
+ if (result == EXIT_FAILURE) {
+ cmdline_parser_free(args_info);
+ exit(EXIT_FAILURE);
+ }
- if (result == EXIT_FAILURE)
- {
- cmdline_parser_free (args_info);
- exit (EXIT_FAILURE);
- }
-
- return result;
+ return result;
}
int
-cmdline_parser_required (struct gengetopt_args_info *args_info, const char *prog_name)
+cmdline_parser_required(struct gengetopt_args_info *args_info,
+ const char *prog_name)
{
- return EXIT_SUCCESS;
+ return EXIT_SUCCESS;
}
int
-cmdline_parser_internal (int argc, char * const *argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required, const char *additional_error)
+cmdline_parser_internal(int argc, char *const *argv,
+ struct gengetopt_args_info *args_info, int override,
+ int initialize, int check_required,
+ const char *additional_error)
{
- int c; /* Character of the parsed option. */
-
- int error = 0;
- struct gengetopt_args_info local_args_info;
-
- if (initialize)
- cmdline_parser_init (args_info);
-
- cmdline_parser_init (&local_args_info);
-
- optarg = 0;
- optind = 0;
- opterr = 1;
- optopt = '?';
-
- while (1)
- {
- int option_index = 0;
- char *stop_char;
-
- static struct option long_options[] = {
- { "help", 0, NULL, 'h' },
- { "version", 0, NULL, 'V' },
- { "fg", 0, NULL, 'f' },
- { "debug", 0, NULL, 'd' },
- { "conf", 1, NULL, 'c' },
- { "pidfile", 1, NULL, 0 },
- { "statedir", 1, NULL, 0 },
- { "listen", 1, NULL, 'l' },
- { "net", 1, NULL, 'n' },
- { "ipup", 1, NULL, 0 },
- { "ipdown", 1, NULL, 0 },
- { "dynip", 1, NULL, 0 },
- { "statip", 1, NULL, 0 },
- { "pcodns1", 1, NULL, 0 },
- { "pcodns2", 1, NULL, 0 },
- { "timelimit", 1, NULL, 0 },
- { "apn", 1, NULL, 'a' },
- { "qos", 1, NULL, 'q' },
- { NULL, 0, NULL, 0 }
- };
-
- stop_char = 0;
- c = getopt_long (argc, argv, "hVfdc:l:n:a:q:", long_options, &option_index);
-
- if (c == -1) break; /* Exit from `while (1)' loop. */
-
- switch (c)
- {
- case 'h': /* Print help and exit. */
- cmdline_parser_print_help ();
- cmdline_parser_free (&local_args_info);
- exit (EXIT_SUCCESS);
-
- case 'V': /* Print version and exit. */
- cmdline_parser_print_version ();
- cmdline_parser_free (&local_args_info);
- exit (EXIT_SUCCESS);
-
- case 'f': /* Run in foreground. */
- if (local_args_info.fg_given)
- {
- fprintf (stderr, "%s: `--fg' (`-f') option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->fg_given && ! override)
- continue;
- local_args_info.fg_given = 1;
- args_info->fg_given = 1;
- args_info->fg_flag = !(args_info->fg_flag);
- break;
-
- case 'd': /* Run in debug mode. */
- if (local_args_info.debug_given)
- {
- fprintf (stderr, "%s: `--debug' (`-d') option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->debug_given && ! override)
- continue;
- local_args_info.debug_given = 1;
- args_info->debug_given = 1;
- args_info->debug_flag = !(args_info->debug_flag);
- break;
-
- case 'c': /* Read configuration file. */
- if (local_args_info.conf_given)
- {
- fprintf (stderr, "%s: `--conf' (`-c') option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->conf_given && ! override)
- continue;
- local_args_info.conf_given = 1;
- args_info->conf_given = 1;
- if (args_info->conf_arg)
- free (args_info->conf_arg); /* free previous string */
- args_info->conf_arg = gengetopt_strdup (optarg);
- if (args_info->conf_orig)
- free (args_info->conf_orig); /* free previous string */
- args_info->conf_orig = gengetopt_strdup (optarg);
- break;
-
- case 'l': /* Local interface. */
- if (local_args_info.listen_given)
- {
- fprintf (stderr, "%s: `--listen' (`-l') option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->listen_given && ! override)
- continue;
- local_args_info.listen_given = 1;
- args_info->listen_given = 1;
- if (args_info->listen_arg)
- free (args_info->listen_arg); /* free previous string */
- args_info->listen_arg = gengetopt_strdup (optarg);
- if (args_info->listen_orig)
- free (args_info->listen_orig); /* free previous string */
- args_info->listen_orig = gengetopt_strdup (optarg);
- break;
-
- case 'n': /* Network. */
- if (local_args_info.net_given)
- {
- fprintf (stderr, "%s: `--net' (`-n') option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->net_given && ! override)
- continue;
- local_args_info.net_given = 1;
- args_info->net_given = 1;
- if (args_info->net_arg)
- free (args_info->net_arg); /* free previous string */
- args_info->net_arg = gengetopt_strdup (optarg);
- if (args_info->net_orig)
- free (args_info->net_orig); /* free previous string */
- args_info->net_orig = gengetopt_strdup (optarg);
- break;
-
- case 'a': /* Access point name. */
- if (local_args_info.apn_given)
- {
- fprintf (stderr, "%s: `--apn' (`-a') option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->apn_given && ! override)
- continue;
- local_args_info.apn_given = 1;
- args_info->apn_given = 1;
- if (args_info->apn_arg)
- free (args_info->apn_arg); /* free previous string */
- args_info->apn_arg = gengetopt_strdup (optarg);
- if (args_info->apn_orig)
- free (args_info->apn_orig); /* free previous string */
- args_info->apn_orig = gengetopt_strdup (optarg);
- break;
-
- case 'q': /* Requested quality of service. */
- if (local_args_info.qos_given)
- {
- fprintf (stderr, "%s: `--qos' (`-q') option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->qos_given && ! override)
- continue;
- local_args_info.qos_given = 1;
- args_info->qos_given = 1;
- args_info->qos_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->qos_orig)
- free (args_info->qos_orig); /* free previous string */
- args_info->qos_orig = gengetopt_strdup (optarg);
- break;
-
-
- case 0: /* Long option with no short option */
- /* Filename of process id file. */
- if (strcmp (long_options[option_index].name, "pidfile") == 0)
- {
- if (local_args_info.pidfile_given)
- {
- fprintf (stderr, "%s: `--pidfile' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->pidfile_given && ! override)
- continue;
- local_args_info.pidfile_given = 1;
- args_info->pidfile_given = 1;
- if (args_info->pidfile_arg)
- free (args_info->pidfile_arg); /* free previous string */
- args_info->pidfile_arg = gengetopt_strdup (optarg);
- if (args_info->pidfile_orig)
- free (args_info->pidfile_orig); /* free previous string */
- args_info->pidfile_orig = gengetopt_strdup (optarg);
- }
- /* Directory of nonvolatile data. */
- else if (strcmp (long_options[option_index].name, "statedir") == 0)
- {
- if (local_args_info.statedir_given)
- {
- fprintf (stderr, "%s: `--statedir' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->statedir_given && ! override)
- continue;
- local_args_info.statedir_given = 1;
- args_info->statedir_given = 1;
- if (args_info->statedir_arg)
- free (args_info->statedir_arg); /* free previous string */
- args_info->statedir_arg = gengetopt_strdup (optarg);
- if (args_info->statedir_orig)
- free (args_info->statedir_orig); /* free previous string */
- args_info->statedir_orig = gengetopt_strdup (optarg);
- }
- /* Script to run after link-up. */
- else if (strcmp (long_options[option_index].name, "ipup") == 0)
- {
- if (local_args_info.ipup_given)
- {
- fprintf (stderr, "%s: `--ipup' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->ipup_given && ! override)
- continue;
- local_args_info.ipup_given = 1;
- args_info->ipup_given = 1;
- if (args_info->ipup_arg)
- free (args_info->ipup_arg); /* free previous string */
- args_info->ipup_arg = gengetopt_strdup (optarg);
- if (args_info->ipup_orig)
- free (args_info->ipup_orig); /* free previous string */
- args_info->ipup_orig = gengetopt_strdup (optarg);
- }
- /* Script to run after link-down. */
- else if (strcmp (long_options[option_index].name, "ipdown") == 0)
- {
- if (local_args_info.ipdown_given)
- {
- fprintf (stderr, "%s: `--ipdown' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->ipdown_given && ! override)
- continue;
- local_args_info.ipdown_given = 1;
- args_info->ipdown_given = 1;
- if (args_info->ipdown_arg)
- free (args_info->ipdown_arg); /* free previous string */
- args_info->ipdown_arg = gengetopt_strdup (optarg);
- if (args_info->ipdown_orig)
- free (args_info->ipdown_orig); /* free previous string */
- args_info->ipdown_orig = gengetopt_strdup (optarg);
- }
- /* Dynamic IP address pool. */
- else if (strcmp (long_options[option_index].name, "dynip") == 0)
- {
- if (local_args_info.dynip_given)
- {
- fprintf (stderr, "%s: `--dynip' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->dynip_given && ! override)
- continue;
- local_args_info.dynip_given = 1;
- args_info->dynip_given = 1;
- if (args_info->dynip_arg)
- free (args_info->dynip_arg); /* free previous string */
- args_info->dynip_arg = gengetopt_strdup (optarg);
- if (args_info->dynip_orig)
- free (args_info->dynip_orig); /* free previous string */
- args_info->dynip_orig = gengetopt_strdup (optarg);
- }
- /* Static IP address pool. */
- else if (strcmp (long_options[option_index].name, "statip") == 0)
- {
- if (local_args_info.statip_given)
- {
- fprintf (stderr, "%s: `--statip' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->statip_given && ! override)
- continue;
- local_args_info.statip_given = 1;
- args_info->statip_given = 1;
- if (args_info->statip_arg)
- free (args_info->statip_arg); /* free previous string */
- args_info->statip_arg = gengetopt_strdup (optarg);
- if (args_info->statip_orig)
- free (args_info->statip_orig); /* free previous string */
- args_info->statip_orig = gengetopt_strdup (optarg);
- }
- /* PCO DNS Server 1. */
- else if (strcmp (long_options[option_index].name, "pcodns1") == 0)
- {
- if (local_args_info.pcodns1_given)
- {
- fprintf (stderr, "%s: `--pcodns1' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->pcodns1_given && ! override)
- continue;
- local_args_info.pcodns1_given = 1;
- args_info->pcodns1_given = 1;
- if (args_info->pcodns1_arg)
- free (args_info->pcodns1_arg); /* free previous string */
- args_info->pcodns1_arg = gengetopt_strdup (optarg);
- if (args_info->pcodns1_orig)
- free (args_info->pcodns1_orig); /* free previous string */
- args_info->pcodns1_orig = gengetopt_strdup (optarg);
- }
- /* PCO DNS Server 2. */
- else if (strcmp (long_options[option_index].name, "pcodns2") == 0)
- {
- if (local_args_info.pcodns2_given)
- {
- fprintf (stderr, "%s: `--pcodns2' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->pcodns2_given && ! override)
- continue;
- local_args_info.pcodns2_given = 1;
- args_info->pcodns2_given = 1;
- if (args_info->pcodns2_arg)
- free (args_info->pcodns2_arg); /* free previous string */
- args_info->pcodns2_arg = gengetopt_strdup (optarg);
- if (args_info->pcodns2_orig)
- free (args_info->pcodns2_orig); /* free previous string */
- args_info->pcodns2_orig = gengetopt_strdup (optarg);
- }
- /* Exit after timelimit seconds. */
- else if (strcmp (long_options[option_index].name, "timelimit") == 0)
- {
- if (local_args_info.timelimit_given)
- {
- fprintf (stderr, "%s: `--timelimit' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->timelimit_given && ! override)
- continue;
- local_args_info.timelimit_given = 1;
- args_info->timelimit_given = 1;
- args_info->timelimit_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->timelimit_orig)
- free (args_info->timelimit_orig); /* free previous string */
- args_info->timelimit_orig = gengetopt_strdup (optarg);
- }
-
- break;
- case '?': /* Invalid option. */
- /* `getopt_long' already printed an error message. */
- goto failure;
-
- default: /* bug: option not considered. */
- fprintf (stderr, "%s: option unknown: %c%s\n", CMDLINE_PARSER_PACKAGE, c, (additional_error ? additional_error : ""));
- abort ();
- } /* switch */
- } /* while */
-
-
-
-
- cmdline_parser_release (&local_args_info);
-
- if ( error )
- return (EXIT_FAILURE);
-
- return 0;
+ int c; /* Character of the parsed option. */
+
+ int error = 0;
+ struct gengetopt_args_info local_args_info;
+
+ if (initialize)
+ cmdline_parser_init(args_info);
+
+ cmdline_parser_init(&local_args_info);
+
+ optarg = 0;
+ optind = 0;
+ opterr = 1;
+ optopt = '?';
+
+ while (1) {
+ int option_index = 0;
+ char *stop_char;
+
+ static struct option long_options[] = {
+ {"help", 0, NULL, 'h'},
+ {"version", 0, NULL, 'V'},
+ {"fg", 0, NULL, 'f'},
+ {"debug", 0, NULL, 'd'},
+ {"conf", 1, NULL, 'c'},
+ {"pidfile", 1, NULL, 0},
+ {"statedir", 1, NULL, 0},
+ {"listen", 1, NULL, 'l'},
+ {"net", 1, NULL, 'n'},
+ {"ipup", 1, NULL, 0},
+ {"ipdown", 1, NULL, 0},
+ {"dynip", 1, NULL, 0},
+ {"statip", 1, NULL, 0},
+ {"pcodns1", 1, NULL, 0},
+ {"pcodns2", 1, NULL, 0},
+ {"timelimit", 1, NULL, 0},
+ {"apn", 1, NULL, 'a'},
+ {"qos", 1, NULL, 'q'},
+ {NULL, 0, NULL, 0}
+ };
+
+ stop_char = 0;
+ c = getopt_long(argc, argv, "hVfdc:l:n:a:q:", long_options,
+ &option_index);
+
+ if (c == -1)
+ break; /* Exit from `while (1)' loop. */
+
+ switch (c) {
+ case 'h': /* Print help and exit. */
+ cmdline_parser_print_help();
+ cmdline_parser_free(&local_args_info);
+ exit(EXIT_SUCCESS);
+
+ case 'V': /* Print version and exit. */
+ cmdline_parser_print_version();
+ cmdline_parser_free(&local_args_info);
+ exit(EXIT_SUCCESS);
+
+ case 'f': /* Run in foreground. */
+ if (local_args_info.fg_given) {
+ fprintf(stderr,
+ "%s: `--fg' (`-f') option given more than once%s\n",
+ argv[0],
+ (additional_error ? additional_error :
+ ""));
+ goto failure;
+ }
+ if (args_info->fg_given && !override)
+ continue;
+ local_args_info.fg_given = 1;
+ args_info->fg_given = 1;
+ args_info->fg_flag = !(args_info->fg_flag);
+ break;
+
+ case 'd': /* Run in debug mode. */
+ if (local_args_info.debug_given) {
+ fprintf(stderr,
+ "%s: `--debug' (`-d') option given more than once%s\n",
+ argv[0],
+ (additional_error ? additional_error :
+ ""));
+ goto failure;
+ }
+ if (args_info->debug_given && !override)
+ continue;
+ local_args_info.debug_given = 1;
+ args_info->debug_given = 1;
+ args_info->debug_flag = !(args_info->debug_flag);
+ break;
+
+ case 'c': /* Read configuration file. */
+ if (local_args_info.conf_given) {
+ fprintf(stderr,
+ "%s: `--conf' (`-c') option given more than once%s\n",
+ argv[0],
+ (additional_error ? additional_error :
+ ""));
+ goto failure;
+ }
+ if (args_info->conf_given && !override)
+ continue;
+ local_args_info.conf_given = 1;
+ args_info->conf_given = 1;
+ if (args_info->conf_arg)
+ free(args_info->conf_arg); /* free previous string */
+ args_info->conf_arg = gengetopt_strdup(optarg);
+ if (args_info->conf_orig)
+ free(args_info->conf_orig); /* free previous string */
+ args_info->conf_orig = gengetopt_strdup(optarg);
+ break;
+
+ case 'l': /* Local interface. */
+ if (local_args_info.listen_given) {
+ fprintf(stderr,
+ "%s: `--listen' (`-l') option given more than once%s\n",
+ argv[0],
+ (additional_error ? additional_error :
+ ""));
+ goto failure;
+ }
+ if (args_info->listen_given && !override)
+ continue;
+ local_args_info.listen_given = 1;
+ args_info->listen_given = 1;
+ if (args_info->listen_arg)
+ free(args_info->listen_arg); /* free previous string */
+ args_info->listen_arg = gengetopt_strdup(optarg);
+ if (args_info->listen_orig)
+ free(args_info->listen_orig); /* free previous string */
+ args_info->listen_orig = gengetopt_strdup(optarg);
+ break;
+
+ case 'n': /* Network. */
+ if (local_args_info.net_given) {
+ fprintf(stderr,
+ "%s: `--net' (`-n') option given more than once%s\n",
+ argv[0],
+ (additional_error ? additional_error :
+ ""));
+ goto failure;
+ }
+ if (args_info->net_given && !override)
+ continue;
+ local_args_info.net_given = 1;
+ args_info->net_given = 1;
+ if (args_info->net_arg)
+ free(args_info->net_arg); /* free previous string */
+ args_info->net_arg = gengetopt_strdup(optarg);
+ if (args_info->net_orig)
+ free(args_info->net_orig); /* free previous string */
+ args_info->net_orig = gengetopt_strdup(optarg);
+ break;
+
+ case 'a': /* Access point name. */
+ if (local_args_info.apn_given) {
+ fprintf(stderr,
+ "%s: `--apn' (`-a') option given more than once%s\n",
+ argv[0],
+ (additional_error ? additional_error :
+ ""));
+ goto failure;
+ }
+ if (args_info->apn_given && !override)
+ continue;
+ local_args_info.apn_given = 1;
+ args_info->apn_given = 1;
+ if (args_info->apn_arg)
+ free(args_info->apn_arg); /* free previous string */
+ args_info->apn_arg = gengetopt_strdup(optarg);
+ if (args_info->apn_orig)
+ free(args_info->apn_orig); /* free previous string */
+ args_info->apn_orig = gengetopt_strdup(optarg);
+ break;
+
+ case 'q': /* Requested quality of service. */
+ if (local_args_info.qos_given) {
+ fprintf(stderr,
+ "%s: `--qos' (`-q') option given more than once%s\n",
+ argv[0],
+ (additional_error ? additional_error :
+ ""));
+ goto failure;
+ }
+ if (args_info->qos_given && !override)
+ continue;
+ local_args_info.qos_given = 1;
+ args_info->qos_given = 1;
+ args_info->qos_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->qos_orig)
+ free(args_info->qos_orig); /* free previous string */
+ args_info->qos_orig = gengetopt_strdup(optarg);
+ break;
+
+ case 0: /* Long option with no short option */
+ /* Filename of process id file. */
+ if (strcmp(long_options[option_index].name, "pidfile")
+ == 0) {
+ if (local_args_info.pidfile_given) {
+ fprintf(stderr,
+ "%s: `--pidfile' option given more than once%s\n",
+ argv[0],
+ (additional_error ?
+ additional_error : ""));
+ goto failure;
+ }
+ if (args_info->pidfile_given && !override)
+ continue;
+ local_args_info.pidfile_given = 1;
+ args_info->pidfile_given = 1;
+ if (args_info->pidfile_arg)
+ free(args_info->pidfile_arg); /* free previous string */
+ args_info->pidfile_arg =
+ gengetopt_strdup(optarg);
+ if (args_info->pidfile_orig)
+ free(args_info->pidfile_orig); /* free previous string */
+ args_info->pidfile_orig =
+ gengetopt_strdup(optarg);
+ }
+ /* Directory of nonvolatile data. */
+ else if (strcmp
+ (long_options[option_index].name,
+ "statedir") == 0) {
+ if (local_args_info.statedir_given) {
+ fprintf(stderr,
+ "%s: `--statedir' option given more than once%s\n",
+ argv[0],
+ (additional_error ?
+ additional_error : ""));
+ goto failure;
+ }
+ if (args_info->statedir_given && !override)
+ continue;
+ local_args_info.statedir_given = 1;
+ args_info->statedir_given = 1;
+ if (args_info->statedir_arg)
+ free(args_info->statedir_arg); /* free previous string */
+ args_info->statedir_arg =
+ gengetopt_strdup(optarg);
+ if (args_info->statedir_orig)
+ free(args_info->statedir_orig); /* free previous string */
+ args_info->statedir_orig =
+ gengetopt_strdup(optarg);
+ }
+ /* Script to run after link-up. */
+ else if (strcmp(long_options[option_index].name, "ipup")
+ == 0) {
+ if (local_args_info.ipup_given) {
+ fprintf(stderr,
+ "%s: `--ipup' option given more than once%s\n",
+ argv[0],
+ (additional_error ?
+ additional_error : ""));
+ goto failure;
+ }
+ if (args_info->ipup_given && !override)
+ continue;
+ local_args_info.ipup_given = 1;
+ args_info->ipup_given = 1;
+ if (args_info->ipup_arg)
+ free(args_info->ipup_arg); /* free previous string */
+ args_info->ipup_arg = gengetopt_strdup(optarg);
+ if (args_info->ipup_orig)
+ free(args_info->ipup_orig); /* free previous string */
+ args_info->ipup_orig = gengetopt_strdup(optarg);
+ }
+ /* Script to run after link-down. */
+ else if (strcmp
+ (long_options[option_index].name,
+ "ipdown") == 0) {
+ if (local_args_info.ipdown_given) {
+ fprintf(stderr,
+ "%s: `--ipdown' option given more than once%s\n",
+ argv[0],
+ (additional_error ?
+ additional_error : ""));
+ goto failure;
+ }
+ if (args_info->ipdown_given && !override)
+ continue;
+ local_args_info.ipdown_given = 1;
+ args_info->ipdown_given = 1;
+ if (args_info->ipdown_arg)
+ free(args_info->ipdown_arg); /* free previous string */
+ args_info->ipdown_arg =
+ gengetopt_strdup(optarg);
+ if (args_info->ipdown_orig)
+ free(args_info->ipdown_orig); /* free previous string */
+ args_info->ipdown_orig =
+ gengetopt_strdup(optarg);
+ }
+ /* Dynamic IP address pool. */
+ else if (strcmp
+ (long_options[option_index].name,
+ "dynip") == 0) {
+ if (local_args_info.dynip_given) {
+ fprintf(stderr,
+ "%s: `--dynip' option given more than once%s\n",
+ argv[0],
+ (additional_error ?
+ additional_error : ""));
+ goto failure;
+ }
+ if (args_info->dynip_given && !override)
+ continue;
+ local_args_info.dynip_given = 1;
+ args_info->dynip_given = 1;
+ if (args_info->dynip_arg)
+ free(args_info->dynip_arg); /* free previous string */
+ args_info->dynip_arg = gengetopt_strdup(optarg);
+ if (args_info->dynip_orig)
+ free(args_info->dynip_orig); /* free previous string */
+ args_info->dynip_orig =
+ gengetopt_strdup(optarg);
+ }
+ /* Static IP address pool. */
+ else if (strcmp
+ (long_options[option_index].name,
+ "statip") == 0) {
+ if (local_args_info.statip_given) {
+ fprintf(stderr,
+ "%s: `--statip' option given more than once%s\n",
+ argv[0],
+ (additional_error ?
+ additional_error : ""));
+ goto failure;
+ }
+ if (args_info->statip_given && !override)
+ continue;
+ local_args_info.statip_given = 1;
+ args_info->statip_given = 1;
+ if (args_info->statip_arg)
+ free(args_info->statip_arg); /* free previous string */
+ args_info->statip_arg =
+ gengetopt_strdup(optarg);
+ if (args_info->statip_orig)
+ free(args_info->statip_orig); /* free previous string */
+ args_info->statip_orig =
+ gengetopt_strdup(optarg);
+ }
+ /* PCO DNS Server 1. */
+ else if (strcmp
+ (long_options[option_index].name,
+ "pcodns1") == 0) {
+ if (local_args_info.pcodns1_given) {
+ fprintf(stderr,
+ "%s: `--pcodns1' option given more than once%s\n",
+ argv[0],
+ (additional_error ?
+ additional_error : ""));
+ goto failure;
+ }
+ if (args_info->pcodns1_given && !override)
+ continue;
+ local_args_info.pcodns1_given = 1;
+ args_info->pcodns1_given = 1;
+ if (args_info->pcodns1_arg)
+ free(args_info->pcodns1_arg); /* free previous string */
+ args_info->pcodns1_arg =
+ gengetopt_strdup(optarg);
+ if (args_info->pcodns1_orig)
+ free(args_info->pcodns1_orig); /* free previous string */
+ args_info->pcodns1_orig =
+ gengetopt_strdup(optarg);
+ }
+ /* PCO DNS Server 2. */
+ else if (strcmp
+ (long_options[option_index].name,
+ "pcodns2") == 0) {
+ if (local_args_info.pcodns2_given) {
+ fprintf(stderr,
+ "%s: `--pcodns2' option given more than once%s\n",
+ argv[0],
+ (additional_error ?
+ additional_error : ""));
+ goto failure;
+ }
+ if (args_info->pcodns2_given && !override)
+ continue;
+ local_args_info.pcodns2_given = 1;
+ args_info->pcodns2_given = 1;
+ if (args_info->pcodns2_arg)
+ free(args_info->pcodns2_arg); /* free previous string */
+ args_info->pcodns2_arg =
+ gengetopt_strdup(optarg);
+ if (args_info->pcodns2_orig)
+ free(args_info->pcodns2_orig); /* free previous string */
+ args_info->pcodns2_orig =
+ gengetopt_strdup(optarg);
+ }
+ /* Exit after timelimit seconds. */
+ else if (strcmp
+ (long_options[option_index].name,
+ "timelimit") == 0) {
+ if (local_args_info.timelimit_given) {
+ fprintf(stderr,
+ "%s: `--timelimit' option given more than once%s\n",
+ argv[0],
+ (additional_error ?
+ additional_error : ""));
+ goto failure;
+ }
+ if (args_info->timelimit_given && !override)
+ continue;
+ local_args_info.timelimit_given = 1;
+ args_info->timelimit_given = 1;
+ args_info->timelimit_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->timelimit_orig)
+ free(args_info->timelimit_orig); /* free previous string */
+ args_info->timelimit_orig =
+ gengetopt_strdup(optarg);
+ }
+
+ break;
+ case '?': /* Invalid option. */
+ /* `getopt_long' already printed an error message. */
+ goto failure;
+
+ default: /* bug: option not considered. */
+ fprintf(stderr, "%s: option unknown: %c%s\n",
+ CMDLINE_PARSER_PACKAGE, c,
+ (additional_error ? additional_error : ""));
+ abort();
+ } /* switch */
+ } /* while */
+
+ cmdline_parser_release(&local_args_info);
+
+ if (error)
+ return (EXIT_FAILURE);
+
+ return 0;
failure:
-
- cmdline_parser_release (&local_args_info);
- return (EXIT_FAILURE);
+
+ cmdline_parser_release(&local_args_info);
+ return (EXIT_FAILURE);
}
#ifndef CONFIG_FILE_LINE_SIZE
@@ -905,168 +966,167 @@ failure:
#define CONFIG_FILE_LINE_BUFFER_SIZE (CONFIG_FILE_LINE_SIZE+3)
/* 3 is for "--" and "=" */
-char my_argv[CONFIG_FILE_LINE_BUFFER_SIZE+1];
+char my_argv[CONFIG_FILE_LINE_BUFFER_SIZE + 1];
int
-cmdline_parser_configfile (char * const filename, struct gengetopt_args_info *args_info, int override, int initialize, int check_required)
+cmdline_parser_configfile(char *const filename,
+ struct gengetopt_args_info *args_info, int override,
+ int initialize, int check_required)
{
- FILE* file;
- char linebuf[CONFIG_FILE_LINE_SIZE];
- int line_num = 0;
- int i, result, equal;
- char *fopt, *farg;
- char *str_index;
- size_t len, next_token;
- char delimiter;
- int my_argc = 0;
- char **my_argv_arg;
- char *additional_error;
-
- /* store the program name */
- cmd_line_list_tmp = (struct line_list *) malloc (sizeof (struct line_list));
- cmd_line_list_tmp->next = cmd_line_list;
- cmd_line_list = cmd_line_list_tmp;
- cmd_line_list->string_arg = gengetopt_strdup (CMDLINE_PARSER_PACKAGE);
-
- if ((file = fopen(filename, "r")) == NULL)
- {
- fprintf (stderr, "%s: Error opening configuration file '%s'\n",
- CMDLINE_PARSER_PACKAGE, filename);
- result = EXIT_FAILURE;
- goto conf_failure;
- }
-
- while ((fgets(linebuf, CONFIG_FILE_LINE_SIZE, file)) != NULL)
- {
- ++line_num;
- my_argv[0] = '\0';
- len = strlen(linebuf);
- if (len > (CONFIG_FILE_LINE_BUFFER_SIZE-1))
- {
- fprintf (stderr, "%s:%s:%d: Line too long in configuration file\n",
- CMDLINE_PARSER_PACKAGE, filename, line_num);
- result = EXIT_FAILURE;
- goto conf_failure;
- }
-
- /* find first non-whitespace character in the line */
- next_token = strspn ( linebuf, " \t\r\n");
- str_index = linebuf + next_token;
-
- if ( str_index[0] == '\0' || str_index[0] == '#')
- continue; /* empty line or comment line is skipped */
-
- fopt = str_index;
-
- /* truncate fopt at the end of the first non-valid character */
- next_token = strcspn (fopt, " \t\r\n=");
-
- if (fopt[next_token] == '\0') /* the line is over */
- {
- farg = NULL;
- equal = 0;
- goto noarg;
- }
-
- /* remember if equal sign is present */
- equal = (fopt[next_token] == '=');
- fopt[next_token++] = '\0';
-
- /* advance pointers to the next token after the end of fopt */
- next_token += strspn (fopt + next_token, " \t\r\n");
- /* check for the presence of equal sign, and if so, skip it */
- if ( !equal )
- if ((equal = (fopt[next_token] == '=')))
- {
- next_token++;
- next_token += strspn (fopt + next_token, " \t\r\n");
- }
- str_index += next_token;
-
- /* find argument */
- farg = str_index;
- if ( farg[0] == '\"' || farg[0] == '\'' )
- { /* quoted argument */
- str_index = strchr (++farg, str_index[0] ); /* skip opening quote */
- if (! str_index)
- {
- fprintf
- (stderr,
- "%s:%s:%d: unterminated string in configuration file\n",
- CMDLINE_PARSER_PACKAGE, filename, line_num);
- result = EXIT_FAILURE;
- goto conf_failure;
- }
- }
- else
- { /* read up the remaining part up to a delimiter */
- next_token = strcspn (farg, " \t\r\n#\'\"");
- str_index += next_token;
- }
-
- /* truncate farg at the delimiter and store it for further check */
- delimiter = *str_index, *str_index++ = '\0';
-
- /* everything but comment is illegal at the end of line */
- if (delimiter != '\0' && delimiter != '#')
- {
- str_index += strspn(str_index, " \t\r\n");
- if (*str_index != '\0' && *str_index != '#')
- {
- fprintf
- (stderr,
- "%s:%s:%d: malformed string in configuration file\n",
- CMDLINE_PARSER_PACKAGE, filename, line_num);
- result = EXIT_FAILURE;
- goto conf_failure;
- }
- }
-
- noarg:
- ++my_argc;
- len = strlen(fopt);
-
- strcat (my_argv, len > 1 ? "--" : "-");
- strcat (my_argv, fopt);
- if (len > 1 && ((farg &&*farg) || equal))
- strcat (my_argv, "=");
- if (farg && *farg)
- strcat (my_argv, farg);
-
- cmd_line_list_tmp = (struct line_list *) malloc (sizeof (struct line_list));
- cmd_line_list_tmp->next = cmd_line_list;
- cmd_line_list = cmd_line_list_tmp;
- cmd_line_list->string_arg = gengetopt_strdup(my_argv);
- } /* while */
-
- ++my_argc; /* for program name */
- my_argv_arg = (char **) malloc((my_argc+1) * sizeof(char *));
- cmd_line_list_tmp = cmd_line_list;
- for (i = my_argc - 1; i >= 0; --i) {
- my_argv_arg[i] = cmd_line_list_tmp->string_arg;
- cmd_line_list_tmp = cmd_line_list_tmp->next;
- }
- my_argv_arg[my_argc] = 0;
-
- additional_error = (char *)malloc(strlen(filename) + strlen(ADDITIONAL_ERROR) + 1);
- strcpy (additional_error, ADDITIONAL_ERROR);
- strcat (additional_error, filename);
- result =
- cmdline_parser_internal (my_argc, my_argv_arg, args_info, override, initialize, check_required, additional_error);
-
- free (additional_error);
- free (my_argv_arg);
+ FILE *file;
+ char linebuf[CONFIG_FILE_LINE_SIZE];
+ int line_num = 0;
+ int i, result, equal;
+ char *fopt, *farg;
+ char *str_index;
+ size_t len, next_token;
+ char delimiter;
+ int my_argc = 0;
+ char **my_argv_arg;
+ char *additional_error;
+
+ /* store the program name */
+ cmd_line_list_tmp =
+ (struct line_list *)malloc(sizeof(struct line_list));
+ cmd_line_list_tmp->next = cmd_line_list;
+ cmd_line_list = cmd_line_list_tmp;
+ cmd_line_list->string_arg = gengetopt_strdup(CMDLINE_PARSER_PACKAGE);
+
+ if ((file = fopen(filename, "r")) == NULL) {
+ fprintf(stderr, "%s: Error opening configuration file '%s'\n",
+ CMDLINE_PARSER_PACKAGE, filename);
+ result = EXIT_FAILURE;
+ goto conf_failure;
+ }
+
+ while ((fgets(linebuf, CONFIG_FILE_LINE_SIZE, file)) != NULL) {
+ ++line_num;
+ my_argv[0] = '\0';
+ len = strlen(linebuf);
+ if (len > (CONFIG_FILE_LINE_BUFFER_SIZE - 1)) {
+ fprintf(stderr,
+ "%s:%s:%d: Line too long in configuration file\n",
+ CMDLINE_PARSER_PACKAGE, filename, line_num);
+ result = EXIT_FAILURE;
+ goto conf_failure;
+ }
+
+ /* find first non-whitespace character in the line */
+ next_token = strspn(linebuf, " \t\r\n");
+ str_index = linebuf + next_token;
+
+ if (str_index[0] == '\0' || str_index[0] == '#')
+ continue; /* empty line or comment line is skipped */
+
+ fopt = str_index;
+
+ /* truncate fopt at the end of the first non-valid character */
+ next_token = strcspn(fopt, " \t\r\n=");
+
+ if (fopt[next_token] == '\0') { /* the line is over */
+ farg = NULL;
+ equal = 0;
+ goto noarg;
+ }
+
+ /* remember if equal sign is present */
+ equal = (fopt[next_token] == '=');
+ fopt[next_token++] = '\0';
+
+ /* advance pointers to the next token after the end of fopt */
+ next_token += strspn(fopt + next_token, " \t\r\n");
+ /* check for the presence of equal sign, and if so, skip it */
+ if (!equal)
+ if ((equal = (fopt[next_token] == '='))) {
+ next_token++;
+ next_token +=
+ strspn(fopt + next_token, " \t\r\n");
+ }
+ str_index += next_token;
+
+ /* find argument */
+ farg = str_index;
+ if (farg[0] == '\"' || farg[0] == '\'') { /* quoted argument */
+ str_index = strchr(++farg, str_index[0]); /* skip opening quote */
+ if (!str_index) {
+ fprintf
+ (stderr,
+ "%s:%s:%d: unterminated string in configuration file\n",
+ CMDLINE_PARSER_PACKAGE, filename,
+ line_num);
+ result = EXIT_FAILURE;
+ goto conf_failure;
+ }
+ } else { /* read up the remaining part up to a delimiter */
+ next_token = strcspn(farg, " \t\r\n#\'\"");
+ str_index += next_token;
+ }
+
+ /* truncate farg at the delimiter and store it for further check */
+ delimiter = *str_index, *str_index++ = '\0';
+
+ /* everything but comment is illegal at the end of line */
+ if (delimiter != '\0' && delimiter != '#') {
+ str_index += strspn(str_index, " \t\r\n");
+ if (*str_index != '\0' && *str_index != '#') {
+ fprintf
+ (stderr,
+ "%s:%s:%d: malformed string in configuration file\n",
+ CMDLINE_PARSER_PACKAGE, filename,
+ line_num);
+ result = EXIT_FAILURE;
+ goto conf_failure;
+ }
+ }
+
+noarg:
+ ++my_argc;
+ len = strlen(fopt);
+
+ strcat(my_argv, len > 1 ? "--" : "-");
+ strcat(my_argv, fopt);
+ if (len > 1 && ((farg && *farg) || equal))
+ strcat(my_argv, "=");
+ if (farg && *farg)
+ strcat(my_argv, farg);
+
+ cmd_line_list_tmp =
+ (struct line_list *)malloc(sizeof(struct line_list));
+ cmd_line_list_tmp->next = cmd_line_list;
+ cmd_line_list = cmd_line_list_tmp;
+ cmd_line_list->string_arg = gengetopt_strdup(my_argv);
+ } /* while */
+
+ ++my_argc; /* for program name */
+ my_argv_arg = (char **)malloc((my_argc + 1) * sizeof(char *));
+ cmd_line_list_tmp = cmd_line_list;
+ for (i = my_argc - 1; i >= 0; --i) {
+ my_argv_arg[i] = cmd_line_list_tmp->string_arg;
+ cmd_line_list_tmp = cmd_line_list_tmp->next;
+ }
+ my_argv_arg[my_argc] = 0;
+
+ additional_error =
+ (char *)malloc(strlen(filename) + strlen(ADDITIONAL_ERROR) + 1);
+ strcpy(additional_error, ADDITIONAL_ERROR);
+ strcat(additional_error, filename);
+ result =
+ cmdline_parser_internal(my_argc, my_argv_arg, args_info, override,
+ initialize, check_required,
+ additional_error);
+
+ free(additional_error);
+ free(my_argv_arg);
conf_failure:
- if (file)
- fclose(file);
-
- free_cmd_list();
- if (result == EXIT_FAILURE)
- {
- cmdline_parser_free (args_info);
- exit (EXIT_FAILURE);
- }
-
- return result;
+ if (file)
+ fclose(file);
+
+ free_cmd_list();
+ if (result == EXIT_FAILURE) {
+ cmdline_parser_free(args_info);
+ exit(EXIT_FAILURE);
+ }
+
+ return result;
}
diff --git a/ggsn/cmdline.h b/ggsn/cmdline.h
index d9e3086..23a6eee 100644
--- a/ggsn/cmdline.h
+++ b/ggsn/cmdline.h
@@ -12,7 +12,7 @@
#ifdef __cplusplus
extern "C" {
-#endif /* __cplusplus */
+#endif /* __cplusplus */
#ifndef CMDLINE_PARSER_PACKAGE
#define CMDLINE_PARSER_PACKAGE PACKAGE
@@ -22,105 +22,104 @@ extern "C" {
#define CMDLINE_PARSER_VERSION VERSION
#endif
-struct gengetopt_args_info
-{
- const char *help_help; /* Print help and exit help description. */
- const char *version_help; /* Print version and exit help description. */
- int fg_flag; /* Run in foreground (default=off). */
- const char *fg_help; /* Run in foreground help description. */
- int debug_flag; /* Run in debug mode (default=off). */
- const char *debug_help; /* Run in debug mode help description. */
- char * conf_arg; /* Read configuration file (default='/etc/ggsn.conf'). */
- char * conf_orig; /* Read configuration file original value given at command line. */
- const char *conf_help; /* Read configuration file help description. */
- char * pidfile_arg; /* Filename of process id file (default='/var/run/ggsn.pid'). */
- char * pidfile_orig; /* Filename of process id file original value given at command line. */
- const char *pidfile_help; /* Filename of process id file help description. */
- char * statedir_arg; /* Directory of nonvolatile data (default='/var/lib/ggsn/'). */
- char * statedir_orig; /* Directory of nonvolatile data original value given at command line. */
- const char *statedir_help; /* Directory of nonvolatile data help description. */
- char * listen_arg; /* Local interface. */
- char * listen_orig; /* Local interface original value given at command line. */
- const char *listen_help; /* Local interface help description. */
- char * net_arg; /* Network (default='192.168.0.0/24'). */
- char * net_orig; /* Network original value given at command line. */
- const char *net_help; /* Network help description. */
- char * ipup_arg; /* Script to run after link-up. */
- char * ipup_orig; /* Script to run after link-up original value given at command line. */
- const char *ipup_help; /* Script to run after link-up help description. */
- char * ipdown_arg; /* Script to run after link-down. */
- char * ipdown_orig; /* Script to run after link-down original value given at command line. */
- const char *ipdown_help; /* Script to run after link-down help description. */
- char * dynip_arg; /* Dynamic IP address pool. */
- char * dynip_orig; /* Dynamic IP address pool original value given at command line. */
- const char *dynip_help; /* Dynamic IP address pool help description. */
- char * statip_arg; /* Static IP address pool. */
- char * statip_orig; /* Static IP address pool original value given at command line. */
- const char *statip_help; /* Static IP address pool help description. */
- char * pcodns1_arg; /* PCO DNS Server 1 (default='0.0.0.0'). */
- char * pcodns1_orig; /* PCO DNS Server 1 original value given at command line. */
- const char *pcodns1_help; /* PCO DNS Server 1 help description. */
- char * pcodns2_arg; /* PCO DNS Server 2 (default='0.0.0.0'). */
- char * pcodns2_orig; /* PCO DNS Server 2 original value given at command line. */
- const char *pcodns2_help; /* PCO DNS Server 2 help description. */
- int timelimit_arg; /* Exit after timelimit seconds (default='0'). */
- char * timelimit_orig; /* Exit after timelimit seconds original value given at command line. */
- const char *timelimit_help; /* Exit after timelimit seconds help description. */
- char * apn_arg; /* Access point name (default='internet'). */
- char * apn_orig; /* Access point name original value given at command line. */
- const char *apn_help; /* Access point name help description. */
- 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. */
-
- int help_given ; /* Whether help was given. */
- int version_given ; /* Whether version was given. */
- int fg_given ; /* Whether fg was given. */
- int debug_given ; /* Whether debug was given. */
- int conf_given ; /* Whether conf was given. */
- int pidfile_given ; /* Whether pidfile was given. */
- int statedir_given ; /* Whether statedir was given. */
- int listen_given ; /* Whether listen was given. */
- int net_given ; /* Whether net was given. */
- int ipup_given ; /* Whether ipup was given. */
- int ipdown_given ; /* Whether ipdown was given. */
- int dynip_given ; /* Whether dynip was given. */
- int statip_given ; /* Whether statip was given. */
- int pcodns1_given ; /* Whether pcodns1 was given. */
- int pcodns2_given ; /* Whether pcodns2 was given. */
- int timelimit_given ; /* Whether timelimit was given. */
- int apn_given ; /* Whether apn was given. */
- int qos_given ; /* Whether qos was given. */
-
-} ;
-
-extern const char *gengetopt_args_info_purpose;
-extern const char *gengetopt_args_info_usage;
-extern const char *gengetopt_args_info_help[];
-
-int cmdline_parser (int argc, char * const *argv,
- struct gengetopt_args_info *args_info);
-int cmdline_parser2 (int argc, char * const *argv,
- struct gengetopt_args_info *args_info,
- int override, int initialize, int check_required);
-int cmdline_parser_file_save(const char *filename,
- struct gengetopt_args_info *args_info);
-
-void cmdline_parser_print_help(void);
-void cmdline_parser_print_version(void);
-
-void cmdline_parser_init (struct gengetopt_args_info *args_info);
-void cmdline_parser_free (struct gengetopt_args_info *args_info);
-
-int cmdline_parser_configfile (char * const filename,
- struct gengetopt_args_info *args_info,
- int override, int initialize, int check_required);
-
-int cmdline_parser_required (struct gengetopt_args_info *args_info,
- const char *prog_name);
-
+ struct gengetopt_args_info {
+ const char *help_help; /* Print help and exit help description. */
+ const char *version_help; /* Print version and exit help description. */
+ int fg_flag; /* Run in foreground (default=off). */
+ const char *fg_help; /* Run in foreground help description. */
+ int debug_flag; /* Run in debug mode (default=off). */
+ const char *debug_help; /* Run in debug mode help description. */
+ char *conf_arg; /* Read configuration file (default='/etc/ggsn.conf'). */
+ char *conf_orig; /* Read configuration file original value given at command line. */
+ const char *conf_help; /* Read configuration file help description. */
+ char *pidfile_arg; /* Filename of process id file (default='/var/run/ggsn.pid'). */
+ char *pidfile_orig; /* Filename of process id file original value given at command line. */
+ const char *pidfile_help; /* Filename of process id file help description. */
+ char *statedir_arg; /* Directory of nonvolatile data (default='/var/lib/ggsn/'). */
+ char *statedir_orig; /* Directory of nonvolatile data original value given at command line. */
+ const char *statedir_help; /* Directory of nonvolatile data help description. */
+ char *listen_arg; /* Local interface. */
+ char *listen_orig; /* Local interface original value given at command line. */
+ const char *listen_help; /* Local interface help description. */
+ char *net_arg; /* Network (default='192.168.0.0/24'). */
+ char *net_orig; /* Network original value given at command line. */
+ const char *net_help; /* Network help description. */
+ char *ipup_arg; /* Script to run after link-up. */
+ char *ipup_orig; /* Script to run after link-up original value given at command line. */
+ const char *ipup_help; /* Script to run after link-up help description. */
+ char *ipdown_arg; /* Script to run after link-down. */
+ char *ipdown_orig; /* Script to run after link-down original value given at command line. */
+ const char *ipdown_help; /* Script to run after link-down help description. */
+ char *dynip_arg; /* Dynamic IP address pool. */
+ char *dynip_orig; /* Dynamic IP address pool original value given at command line. */
+ const char *dynip_help; /* Dynamic IP address pool help description. */
+ char *statip_arg; /* Static IP address pool. */
+ char *statip_orig; /* Static IP address pool original value given at command line. */
+ const char *statip_help; /* Static IP address pool help description. */
+ char *pcodns1_arg; /* PCO DNS Server 1 (default='0.0.0.0'). */
+ char *pcodns1_orig; /* PCO DNS Server 1 original value given at command line. */
+ const char *pcodns1_help; /* PCO DNS Server 1 help description. */
+ char *pcodns2_arg; /* PCO DNS Server 2 (default='0.0.0.0'). */
+ char *pcodns2_orig; /* PCO DNS Server 2 original value given at command line. */
+ const char *pcodns2_help; /* PCO DNS Server 2 help description. */
+ int timelimit_arg; /* Exit after timelimit seconds (default='0'). */
+ char *timelimit_orig; /* Exit after timelimit seconds original value given at command line. */
+ const char *timelimit_help; /* Exit after timelimit seconds help description. */
+ char *apn_arg; /* Access point name (default='internet'). */
+ char *apn_orig; /* Access point name original value given at command line. */
+ const char *apn_help; /* Access point name help description. */
+ 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. */
+
+ int help_given; /* Whether help was given. */
+ int version_given; /* Whether version was given. */
+ int fg_given; /* Whether fg was given. */
+ int debug_given; /* Whether debug was given. */
+ int conf_given; /* Whether conf was given. */
+ int pidfile_given; /* Whether pidfile was given. */
+ int statedir_given; /* Whether statedir was given. */
+ int listen_given; /* Whether listen was given. */
+ int net_given; /* Whether net was given. */
+ int ipup_given; /* Whether ipup was given. */
+ int ipdown_given; /* Whether ipdown was given. */
+ int dynip_given; /* Whether dynip was given. */
+ int statip_given; /* Whether statip was given. */
+ int pcodns1_given; /* Whether pcodns1 was given. */
+ int pcodns2_given; /* Whether pcodns2 was given. */
+ int timelimit_given; /* Whether timelimit was given. */
+ int apn_given; /* Whether apn was given. */
+ int qos_given; /* Whether qos was given. */
+
+ };
+
+ extern const char *gengetopt_args_info_purpose;
+ extern const char *gengetopt_args_info_usage;
+ extern const char *gengetopt_args_info_help[];
+
+ int cmdline_parser(int argc, char *const *argv,
+ struct gengetopt_args_info *args_info);
+ int cmdline_parser2(int argc, char *const *argv,
+ struct gengetopt_args_info *args_info,
+ int override, int initialize, int check_required);
+ int cmdline_parser_file_save(const char *filename,
+ struct gengetopt_args_info *args_info);
+
+ void cmdline_parser_print_help(void);
+ void cmdline_parser_print_version(void);
+
+ void cmdline_parser_init(struct gengetopt_args_info *args_info);
+ void cmdline_parser_free(struct gengetopt_args_info *args_info);
+
+ int cmdline_parser_configfile(char *const filename,
+ struct gengetopt_args_info *args_info,
+ int override, int initialize,
+ int check_required);
+
+ int cmdline_parser_required(struct gengetopt_args_info *args_info,
+ const char *prog_name);
#ifdef __cplusplus
}
-#endif /* __cplusplus */
-#endif /* CMDLINE_H */
+#endif /* __cplusplus */
+#endif /* CMDLINE_H */
diff --git a/ggsn/ggsn.c b/ggsn/ggsn.c
index 9e0b597..1152519 100644
--- a/ggsn/ggsn.c
+++ b/ggsn/ggsn.c
@@ -39,7 +39,7 @@
#include <fcntl.h>
#include <unistd.h>
-#include <sys/socket.h>
+#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
@@ -55,507 +55,539 @@
#include "cmdline.h"
int end = 0;
-int maxfd = 0; /* For select() */
+int maxfd = 0; /* For select() */
struct in_addr listen_;
-struct in_addr netaddr, destaddr, net, mask; /* Network interface */
-struct in_addr dns1, dns2; /* PCO DNS address */
-char *ipup, *ipdown; /* Filename of scripts */
-int debug; /* Print debug output */
+struct in_addr netaddr, destaddr, net, mask; /* Network interface */
+struct in_addr dns1, dns2; /* PCO DNS address */
+char *ipup, *ipdown; /* Filename of scripts */
+int debug; /* Print debug output */
struct ul255_t pco;
struct ul255_t qos;
struct ul255_t apn;
-struct gsn_t *gsn; /* GSN instance */
-struct tun_t *tun; /* TUN instance */
-struct ippool_t *ippool; /* Pool of IP addresses */
+struct gsn_t *gsn; /* GSN instance */
+struct tun_t *tun; /* TUN instance */
+struct ippool_t *ippool; /* Pool of IP addresses */
/* To exit gracefully. Used with GCC compilation flag -pg and gprof */
-void signal_handler(int s) {
- if (debug) printf("Received signal %d, exiting.\n", s);
- end = 1;
+void signal_handler(int s)
+{
+ if (debug)
+ printf("Received signal %d, exiting.\n", s);
+ end = 1;
}
/* Used to write process ID to file. Assume someone else will delete */
-void log_pid(char *pidfile) {
- FILE *file;
- mode_t oldmask;
-
- oldmask = umask(022);
- file = fopen(pidfile, "w");
- umask(oldmask);
- if(!file) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "Failed to create process ID file: %s!", pidfile);
- return;
- }
- fprintf(file, "%d\n", (int) getpid());
- fclose(file);
+void log_pid(char *pidfile)
+{
+ FILE *file;
+ mode_t oldmask;
+
+ oldmask = umask(022);
+ file = fopen(pidfile, "w");
+ umask(oldmask);
+ if (!file) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "Failed to create process ID file: %s!", pidfile);
+ return;
+ }
+ fprintf(file, "%d\n", (int)getpid());
+ fclose(file);
}
#if defined(__sun__)
-int daemon(int nochdir, int noclose) {
- int fd;
-
- switch (fork()) {
- case -1:
- return (-1);
- case 0:
- break;
- default:
- _exit(0);
- }
-
- if (setsid() == -1)
- return (-1);
-
- if (!nochdir) chdir("/");
-
- if (!noclose && (fd = open("/dev/null", O_RDWR, 0)) != -1) {
- dup2(fd, STDIN_FILENO);
- dup2(fd, STDOUT_FILENO);
- dup2(fd, STDERR_FILENO);
- if (fd > 2) close (fd);
- }
- return (0);
+int daemon(int nochdir, int noclose)
+{
+ int fd;
+
+ switch (fork()) {
+ case -1:
+ return (-1);
+ case 0:
+ break;
+ default:
+ _exit(0);
+ }
+
+ if (setsid() == -1)
+ return (-1);
+
+ if (!nochdir)
+ chdir("/");
+
+ if (!noclose && (fd = open("/dev/null", O_RDWR, 0)) != -1) {
+ dup2(fd, STDIN_FILENO);
+ dup2(fd, STDOUT_FILENO);
+ dup2(fd, STDERR_FILENO);
+ if (fd > 2)
+ close(fd);
+ }
+ return (0);
}
#endif
-
int encaps_printf(void *p, void *packet, unsigned len)
{
- unsigned int i;
- if (debug) {
- printf("The packet looks like this:\n");
- for( i=0; i<len; i++) {
- printf("%02x ", (unsigned char)*(char *)(packet+i));
- if (!((i+1)%16)) printf("\n");
- };
- printf("\n");
- }
- return 0;
+ unsigned int i;
+ if (debug) {
+ printf("The packet looks like this:\n");
+ for (i = 0; i < len; i++) {
+ printf("%02x ", (unsigned char)*(char *)(packet + i));
+ if (!((i + 1) % 16))
+ printf("\n");
+ };
+ printf("\n");
+ }
+ return 0;
}
-int delete_context(struct pdp_t *pdp) {
- if (debug) printf("Deleting PDP context\n");
- if (pdp->peer)
- ippool_freeip(ippool, (struct ippoolm_t *) pdp->peer);
- else
- sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Peer not defined!");
- return 0;
+int delete_context(struct pdp_t *pdp)
+{
+ if (debug)
+ printf("Deleting PDP context\n");
+ if (pdp->peer)
+ ippool_freeip(ippool, (struct ippoolm_t *)pdp->peer);
+ else
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Peer not defined!");
+ return 0;
}
+int create_context_ind(struct pdp_t *pdp)
+{
+ struct in_addr addr;
+ struct ippoolm_t *member;
-int create_context_ind(struct pdp_t *pdp) {
- struct in_addr addr;
- struct ippoolm_t *member;
+ if (debug)
+ printf("Received create PDP context request\n");
- if (debug) printf("Received create PDP context request\n");
+ pdp->eua.l = 0; /* TODO: Indicates dynamic IP */
- pdp->eua.l=0; /* TODO: Indicates dynamic IP */
+ /* ulcpy(&pdp->qos_neg, &pdp->qos_req, sizeof(pdp->qos_req.v)); */
+ memcpy(pdp->qos_neg0, pdp->qos_req0, sizeof(pdp->qos_req0));
+ memcpy(&pdp->pco_neg, &pco, sizeof(pdp->pco_neg));
- /* ulcpy(&pdp->qos_neg, &pdp->qos_req, sizeof(pdp->qos_req.v)); */
- memcpy(pdp->qos_neg0, pdp->qos_req0, sizeof(pdp->qos_req0));
- memcpy(&pdp->pco_neg, &pco, sizeof(pdp->pco_neg));
+ memcpy(pdp->qos_neg.v, pdp->qos_req.v, pdp->qos_req.l); /* TODO */
+ pdp->qos_neg.l = pdp->qos_req.l;
- memcpy(pdp->qos_neg.v, pdp->qos_req.v, pdp->qos_req.l); /* TODO */
- pdp->qos_neg.l = pdp->qos_req.l;
-
- if (pdp_euaton(&pdp->eua, &addr)) {
- addr.s_addr = 0; /* Request dynamic */
- }
+ if (pdp_euaton(&pdp->eua, &addr)) {
+ addr.s_addr = 0; /* Request dynamic */
+ }
- if (ippool_newip(ippool, &member, &addr, 0)) {
- gtp_create_context_resp(gsn, pdp, GTPCAUSE_NO_RESOURCES);
- return 0; /* Allready in use, or no more available */
- }
+ if (ippool_newip(ippool, &member, &addr, 0)) {
+ gtp_create_context_resp(gsn, pdp, GTPCAUSE_NO_RESOURCES);
+ return 0; /* Allready in use, or no more available */
+ }
- pdp_ntoeua(&member->addr, &pdp->eua);
- pdp->peer = member;
- pdp->ipif = tun; /* TODO */
- member->peer = pdp;
+ pdp_ntoeua(&member->addr, &pdp->eua);
+ pdp->peer = member;
+ pdp->ipif = tun; /* TODO */
+ member->peer = pdp;
- gtp_create_context_resp(gsn, pdp, GTPCAUSE_ACC_REQ);
- return 0; /* Success */
+ gtp_create_context_resp(gsn, pdp, GTPCAUSE_ACC_REQ);
+ return 0; /* Success */
}
-
/* Callback for receiving messages from tun */
-int cb_tun_ind(struct tun_t *tun, void *pack, unsigned len) {
- struct ippoolm_t *ipm;
- struct in_addr dst;
- struct tun_packet_t *iph = (struct tun_packet_t*) pack;
-
- dst.s_addr = iph->dst;
-
- if (debug) printf("Received packet from tun!\n");
-
- if (ippool_getip(ippool, &ipm, &dst)) {
- if (debug) printf("Received packet with no destination!!!\n");
- return 0;
- }
-
- if (ipm->peer) /* Check if a peer protocol is defined */
- gtp_data_req(gsn, (struct pdp_t*) ipm->peer, pack, len);
- return 0;
-}
+int cb_tun_ind(struct tun_t *tun, void *pack, unsigned len)
+{
+ struct ippoolm_t *ipm;
+ struct in_addr dst;
+ struct tun_packet_t *iph = (struct tun_packet_t *)pack;
-int encaps_tun(struct pdp_t *pdp, void *pack, unsigned len) {
- if (debug) printf("encaps_tun. Packet received: forwarding to tun\n");
- return tun_encaps((struct tun_t*) pdp->ipif, pack, len);
+ dst.s_addr = iph->dst;
+
+ if (debug)
+ printf("Received packet from tun!\n");
+
+ if (ippool_getip(ippool, &ipm, &dst)) {
+ if (debug)
+ printf("Received packet with no destination!!!\n");
+ return 0;
+ }
+
+ if (ipm->peer) /* Check if a peer protocol is defined */
+ gtp_data_req(gsn, (struct pdp_t *)ipm->peer, pack, len);
+ return 0;
}
+int encaps_tun(struct pdp_t *pdp, void *pack, unsigned len)
+{
+ if (debug)
+ printf("encaps_tun. Packet received: forwarding to tun\n");
+ return tun_encaps((struct tun_t *)pdp->ipif, pack, len);
+}
int main(int argc, char **argv)
{
- /* gengeopt declarations */
- struct gengetopt_args_info args_info;
+ /* gengeopt declarations */
+ struct gengetopt_args_info args_info;
- struct hostent *host;
+ struct hostent *host;
- /* Handle keyboard interrupt SIGINT */
- struct sigaction s;
- s.sa_handler = (void *) signal_handler;
- if ((0 != sigemptyset( &s.sa_mask )) && debug)
- printf("sigemptyset failed.\n");
- s.sa_flags = SA_RESETHAND;
- if ((sigaction(SIGINT, &s, NULL) != 0) && debug)
- printf("Could not register SIGINT signal handler.\n");
-
- fd_set fds; /* For select() */
- struct timeval idleTime; /* How long to select() */
+ /* Handle keyboard interrupt SIGINT */
+ struct sigaction s;
+ s.sa_handler = (void *)signal_handler;
+ if ((0 != sigemptyset(&s.sa_mask)) && debug)
+ printf("sigemptyset failed.\n");
+ s.sa_flags = SA_RESETHAND;
+ if ((sigaction(SIGINT, &s, NULL) != 0) && debug)
+ printf("Could not register SIGINT signal handler.\n");
+ fd_set fds; /* For select() */
+ struct timeval idleTime; /* How long to select() */
- int timelimit; /* Number of seconds to be connected */
- int starttime; /* Time program was started */
+ int timelimit; /* Number of seconds to be connected */
+ int starttime; /* Time program was started */
- /* open a connection to the syslog daemon */
- /*openlog(PACKAGE, LOG_PID, LOG_DAEMON);*/
+ /* open a connection to the syslog daemon */
+ /*openlog(PACKAGE, LOG_PID, LOG_DAEMON); */
- /* TODO: Only use LOG__PERROR for linux */
+ /* TODO: Only use LOG__PERROR for linux */
#ifdef __linux__
- openlog(PACKAGE, (LOG_PID | LOG_PERROR), LOG_DAEMON);
+ openlog(PACKAGE, (LOG_PID | LOG_PERROR), LOG_DAEMON);
#else
- openlog(PACKAGE, (LOG_PID), LOG_DAEMON);
+ openlog(PACKAGE, (LOG_PID), LOG_DAEMON);
#endif
-
- if (cmdline_parser (argc, argv, &args_info) != 0)
- exit(1);
- if (args_info.debug_flag) {
- printf("listen: %s\n", args_info.listen_arg);
- if (args_info.conf_arg) printf("conf: %s\n", args_info.conf_arg);
- printf("fg: %d\n", args_info.fg_flag);
- printf("debug: %d\n", args_info.debug_flag);
- printf("qos: %#08x\n", args_info.qos_arg);
- if (args_info.apn_arg) printf("apn: %s\n", args_info.apn_arg);
- if (args_info.net_arg) printf("net: %s\n", args_info.net_arg);
- if (args_info.dynip_arg) printf("dynip: %s\n", args_info.dynip_arg);
- if (args_info.statip_arg) printf("statip: %s\n", args_info.statip_arg);
- if (args_info.ipup_arg) printf("ipup: %s\n", args_info.ipup_arg);
- if (args_info.ipdown_arg) printf("ipdown: %s\n", args_info.ipdown_arg);
- if (args_info.pidfile_arg) printf("pidfile: %s\n", args_info.pidfile_arg);
- if (args_info.statedir_arg) printf("statedir: %s\n", args_info.statedir_arg);
- printf("timelimit: %d\n", args_info.timelimit_arg);
- }
-
- /* Try out our new parser */
-
- if (cmdline_parser_configfile (args_info.conf_arg, &args_info, 0, 0, 0) != 0)
- exit(1);
- if (args_info.debug_flag) {
- printf("cmdline_parser_configfile\n");
- printf("listen: %s\n", args_info.listen_arg);
- printf("conf: %s\n", args_info.conf_arg);
- printf("fg: %d\n", args_info.fg_flag);
- printf("debug: %d\n", args_info.debug_flag);
- printf("qos: %#08x\n", args_info.qos_arg);
- if (args_info.apn_arg) printf("apn: %s\n", args_info.apn_arg);
- if (args_info.net_arg) printf("net: %s\n", args_info.net_arg);
- if (args_info.dynip_arg) printf("dynip: %s\n", args_info.dynip_arg);
- if (args_info.statip_arg) printf("statip: %s\n", args_info.statip_arg);
- if (args_info.ipup_arg) printf("ipup: %s\n", args_info.ipup_arg);
- if (args_info.ipdown_arg) printf("ipdown: %s\n", args_info.ipdown_arg);
- if (args_info.pidfile_arg) printf("pidfile: %s\n", args_info.pidfile_arg);
- if (args_info.statedir_arg) printf("statedir: %s\n", args_info.statedir_arg);
- printf("timelimit: %d\n", args_info.timelimit_arg);
- }
-
- /* Handle each option */
-
- /* debug */
- debug = args_info.debug_flag;
-
- /* listen */
- /* Do hostname lookup to translate hostname to IP address */
- /* Any port listening is not possible as a valid address is */
- /* required for create_pdp_context_response messages */
- if (args_info.listen_arg) {
- if (!(host = gethostbyname(args_info.listen_arg))) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "Invalid listening address: %s!", args_info.listen_arg);
- exit(1);
- }
- else {
- memcpy(&listen_.s_addr, host->h_addr, host->h_length);
- }
- }
- else {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "Listening address must be specified! "
- "Please use command line option --listen or "
- "edit %s configuration file\n", args_info.conf_arg);
- exit(1);
- }
-
-
- /* net */
- /* Store net as in_addr net and mask */
- if (args_info.net_arg) {
- if(ippool_aton(&net, &mask, args_info.net_arg, 0)) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "Invalid network address: %s!", args_info.net_arg);
- exit(1);
- }
- netaddr.s_addr = htonl(ntohl(net.s_addr) + 1);
- destaddr.s_addr = htonl(ntohl(net.s_addr) + 1);
- }
- else {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "Network address must be specified: %s!", args_info.net_arg);
- exit(1);
- }
-
- /* dynip */
- if (!args_info.dynip_arg) {
- if (ippool_new(&ippool, args_info.net_arg, NULL, 1, 0,
- IPPOOL_NONETWORK | IPPOOL_NOGATEWAY | IPPOOL_NOBROADCAST)) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "Failed to allocate IP pool!");
- exit(1);
- }
- }
- else {
- if (ippool_new(&ippool, args_info.dynip_arg, NULL, 1 ,0,
- IPPOOL_NONETWORK | IPPOOL_NOGATEWAY | IPPOOL_NOBROADCAST)) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "Failed to allocate IP pool!");
- exit(1);
- }
- }
-
- /* DNS1 and DNS2 */
+ if (cmdline_parser(argc, argv, &args_info) != 0)
+ exit(1);
+ if (args_info.debug_flag) {
+ printf("listen: %s\n", args_info.listen_arg);
+ if (args_info.conf_arg)
+ printf("conf: %s\n", args_info.conf_arg);
+ printf("fg: %d\n", args_info.fg_flag);
+ printf("debug: %d\n", args_info.debug_flag);
+ printf("qos: %#08x\n", args_info.qos_arg);
+ if (args_info.apn_arg)
+ printf("apn: %s\n", args_info.apn_arg);
+ if (args_info.net_arg)
+ printf("net: %s\n", args_info.net_arg);
+ if (args_info.dynip_arg)
+ printf("dynip: %s\n", args_info.dynip_arg);
+ if (args_info.statip_arg)
+ printf("statip: %s\n", args_info.statip_arg);
+ if (args_info.ipup_arg)
+ printf("ipup: %s\n", args_info.ipup_arg);
+ if (args_info.ipdown_arg)
+ printf("ipdown: %s\n", args_info.ipdown_arg);
+ if (args_info.pidfile_arg)
+ printf("pidfile: %s\n", args_info.pidfile_arg);
+ if (args_info.statedir_arg)
+ printf("statedir: %s\n", args_info.statedir_arg);
+ printf("timelimit: %d\n", args_info.timelimit_arg);
+ }
+
+ /* Try out our new parser */
+
+ if (cmdline_parser_configfile(args_info.conf_arg, &args_info, 0, 0, 0)
+ != 0)
+ exit(1);
+ if (args_info.debug_flag) {
+ printf("cmdline_parser_configfile\n");
+ printf("listen: %s\n", args_info.listen_arg);
+ printf("conf: %s\n", args_info.conf_arg);
+ printf("fg: %d\n", args_info.fg_flag);
+ printf("debug: %d\n", args_info.debug_flag);
+ printf("qos: %#08x\n", args_info.qos_arg);
+ if (args_info.apn_arg)
+ printf("apn: %s\n", args_info.apn_arg);
+ if (args_info.net_arg)
+ printf("net: %s\n", args_info.net_arg);
+ if (args_info.dynip_arg)
+ printf("dynip: %s\n", args_info.dynip_arg);
+ if (args_info.statip_arg)
+ printf("statip: %s\n", args_info.statip_arg);
+ if (args_info.ipup_arg)
+ printf("ipup: %s\n", args_info.ipup_arg);
+ if (args_info.ipdown_arg)
+ printf("ipdown: %s\n", args_info.ipdown_arg);
+ if (args_info.pidfile_arg)
+ printf("pidfile: %s\n", args_info.pidfile_arg);
+ if (args_info.statedir_arg)
+ printf("statedir: %s\n", args_info.statedir_arg);
+ printf("timelimit: %d\n", args_info.timelimit_arg);
+ }
+
+ /* Handle each option */
+
+ /* debug */
+ debug = args_info.debug_flag;
+
+ /* listen */
+ /* Do hostname lookup to translate hostname to IP address */
+ /* Any port listening is not possible as a valid address is */
+ /* required for create_pdp_context_response messages */
+ if (args_info.listen_arg) {
+ if (!(host = gethostbyname(args_info.listen_arg))) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "Invalid listening address: %s!",
+ args_info.listen_arg);
+ exit(1);
+ } else {
+ memcpy(&listen_.s_addr, host->h_addr, host->h_length);
+ }
+ } else {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "Listening address must be specified! "
+ "Please use command line option --listen or "
+ "edit %s configuration file\n", args_info.conf_arg);
+ exit(1);
+ }
+
+ /* net */
+ /* Store net as in_addr net and mask */
+ if (args_info.net_arg) {
+ if (ippool_aton(&net, &mask, args_info.net_arg, 0)) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "Invalid network address: %s!",
+ args_info.net_arg);
+ exit(1);
+ }
+ netaddr.s_addr = htonl(ntohl(net.s_addr) + 1);
+ destaddr.s_addr = htonl(ntohl(net.s_addr) + 1);
+ } else {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "Network address must be specified: %s!",
+ args_info.net_arg);
+ exit(1);
+ }
+
+ /* dynip */
+ if (!args_info.dynip_arg) {
+ if (ippool_new(&ippool, args_info.net_arg, NULL, 1, 0,
+ IPPOOL_NONETWORK | IPPOOL_NOGATEWAY |
+ IPPOOL_NOBROADCAST)) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "Failed to allocate IP pool!");
+ exit(1);
+ }
+ } else {
+ if (ippool_new(&ippool, args_info.dynip_arg, NULL, 1, 0,
+ IPPOOL_NONETWORK | IPPOOL_NOGATEWAY |
+ IPPOOL_NOBROADCAST)) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "Failed to allocate IP pool!");
+ exit(1);
+ }
+ }
+
+ /* DNS1 and DNS2 */
#ifdef HAVE_INET_ATON
- dns1.s_addr = 0;
- if (args_info.pcodns1_arg) {
- if (0 == inet_aton(args_info.pcodns1_arg, &dns1)) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "Failed to convert pcodns1!");
- exit(1);
- }
- }
- dns2.s_addr = 0;
- if (args_info.pcodns2_arg) {
- if (0 == inet_aton(args_info.pcodns2_arg, &dns2)) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "Failed to convert pcodns2!");
- exit(1);
- }
- }
+ dns1.s_addr = 0;
+ if (args_info.pcodns1_arg) {
+ if (0 == inet_aton(args_info.pcodns1_arg, &dns1)) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "Failed to convert pcodns1!");
+ exit(1);
+ }
+ }
+ dns2.s_addr = 0;
+ if (args_info.pcodns2_arg) {
+ if (0 == inet_aton(args_info.pcodns2_arg, &dns2)) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "Failed to convert pcodns2!");
+ exit(1);
+ }
+ }
#else
- dns1.s_addr = 0;
- if (args_info.pcodns1_arg) {
- dns1.s_addr = inet_addr(args_info.pcodns1_arg);
- if (dns1.s_addr == -1) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "Failed to convert pcodns1!");
- exit(1);
- }
- }
- dns2.s_addr = 0;
- if (args_info.pcodns2_arg) {
- dns2.s_addr = inet_addr(args_info.pcodns2_arg);
- if (dns2.s_addr == -1) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "Failed to convert pcodns2!");
- exit(1);
- }
- }
+ dns1.s_addr = 0;
+ if (args_info.pcodns1_arg) {
+ dns1.s_addr = inet_addr(args_info.pcodns1_arg);
+ if (dns1.s_addr == -1) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "Failed to convert pcodns1!");
+ exit(1);
+ }
+ }
+ dns2.s_addr = 0;
+ if (args_info.pcodns2_arg) {
+ dns2.s_addr = inet_addr(args_info.pcodns2_arg);
+ if (dns2.s_addr == -1) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "Failed to convert pcodns2!");
+ exit(1);
+ }
+ }
#endif
-
- pco.l = 20;
- pco.v[0] = 0x80; /* x0000yyy x=1, yyy=000: PPP */
- pco.v[1] = 0x80; /* IPCP */
- pco.v[2] = 0x21;
- pco.v[3] = 0x10; /* Length of contents */
- pco.v[4] = 0x02; /* ACK */
- pco.v[5] = 0x00; /* ID: Need to match request */
- pco.v[6] = 0x00; /* Length */
- pco.v[7] = 0x10;
- pco.v[8] = 0x81; /* DNS 1 */
- pco.v[9] = 0x06;
- memcpy(&pco.v[10], &dns1, sizeof(dns1));
- pco.v[14] = 0x83;
- pco.v[15] = 0x06; /* DNS 2 */
- memcpy(&pco.v[16], &dns2, sizeof(dns2));
-
- /* ipup */
- ipup = args_info.ipup_arg;
-
- /* ipdown */
- ipdown = args_info.ipdown_arg;
-
- /* Timelimit */
- timelimit = args_info.timelimit_arg;
- starttime = time(NULL);
-
- /* qos */
- qos.l = 3;
- qos.v[2] = (args_info.qos_arg) & 0xff;
- qos.v[1] = ((args_info.qos_arg) >> 8) & 0xff;
- qos.v[0] = ((args_info.qos_arg) >> 16) & 0xff;
-
- /* apn */
- if (strlen(args_info.apn_arg) > (sizeof(apn.v)-1)) {
- printf("Invalid APN\n");
- return -1;
- }
- apn.l = strlen(args_info.apn_arg) + 1;
- apn.v[0] = (char) strlen(args_info.apn_arg);
- strncpy((char *) &apn.v[1], args_info.apn_arg, sizeof(apn.v)-1);
-
-
- /* foreground */
- /* If flag not given run as a daemon */
- if (!args_info.fg_flag)
- {
- FILE *f;
- int rc;
- closelog();
- /* Close the standard file descriptors. */
- /* Is this really needed ? */
- f = freopen("/dev/null", "w", stdout);
- if (f == NULL) {
- sys_err(LOG_WARNING, __FILE__, __LINE__, 0,
- "Could not redirect stdout to /dev/null");
- }
- f = freopen("/dev/null", "w", stderr);
- if (f == NULL) {
- sys_err(LOG_WARNING, __FILE__, __LINE__, 0,
- "Could not redirect stderr to /dev/null");
- }
- f = freopen("/dev/null", "r", stdin);
- if (f == NULL) {
- sys_err(LOG_WARNING, __FILE__, __LINE__, 0,
- "Could not redirect stdin to /dev/null");
- }
- rc = daemon(0, 0);
- if (rc != 0) {
- sys_err(LOG_ERR, __FILE__, __LINE__, rc, "Could not daemonize");
- exit(1);
- }
- /* Open log again. This time with new pid */
- openlog(PACKAGE, LOG_PID, LOG_DAEMON);
- }
-
- /* pidfile */
- /* This has to be done after we have our final pid */
- if (args_info.pidfile_arg) {
- log_pid(args_info.pidfile_arg);
- }
-
-
- if (debug) printf("gtpclient: Initialising GTP tunnel\n");
-
- if (gtp_new(&gsn, args_info.statedir_arg, &listen_, GTP_MODE_GGSN)) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "Failed to create gtp");
- exit(1);
- }
- if (gsn->fd0 > maxfd) maxfd = gsn->fd0;
- if (gsn->fd1c > maxfd) maxfd = gsn->fd1c;
- if (gsn->fd1u > maxfd) maxfd = gsn->fd1u;
-
- gtp_set_cb_data_ind(gsn, encaps_tun);
- gtp_set_cb_delete_context(gsn, delete_context);
- gtp_set_cb_create_context_ind(gsn, create_context_ind);
-
-
- /* Create a tunnel interface */
- if (debug) printf("Creating tun interface\n");
- if (tun_new((struct tun_t**) &tun)) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "Failed to create tun");
- if (debug) printf("Failed to create tun\n");
- exit(1);
- }
-
- if (debug) printf("Setting tun IP address\n");
- if (tun_setaddr(tun, &netaddr, &destaddr, &mask)) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "Failed to set tun IP address");
- if (debug) printf("Failed to set tun IP address\n");
- exit(1);
- }
-
-
- tun_set_cb_ind(tun, cb_tun_ind);
- if (tun->fd > maxfd) maxfd = tun->fd;
-
- if (ipup) tun_runscript(tun, ipup);
+ pco.l = 20;
+ pco.v[0] = 0x80; /* x0000yyy x=1, yyy=000: PPP */
+ pco.v[1] = 0x80; /* IPCP */
+ pco.v[2] = 0x21;
+ pco.v[3] = 0x10; /* Length of contents */
+ pco.v[4] = 0x02; /* ACK */
+ pco.v[5] = 0x00; /* ID: Need to match request */
+ pco.v[6] = 0x00; /* Length */
+ pco.v[7] = 0x10;
+ pco.v[8] = 0x81; /* DNS 1 */
+ pco.v[9] = 0x06;
+ memcpy(&pco.v[10], &dns1, sizeof(dns1));
+ pco.v[14] = 0x83;
+ pco.v[15] = 0x06; /* DNS 2 */
+ memcpy(&pco.v[16], &dns2, sizeof(dns2));
+
+ /* ipup */
+ ipup = args_info.ipup_arg;
+
+ /* ipdown */
+ ipdown = args_info.ipdown_arg;
+
+ /* Timelimit */
+ timelimit = args_info.timelimit_arg;
+ starttime = time(NULL);
+
+ /* qos */
+ qos.l = 3;
+ qos.v[2] = (args_info.qos_arg) & 0xff;
+ qos.v[1] = ((args_info.qos_arg) >> 8) & 0xff;
+ qos.v[0] = ((args_info.qos_arg) >> 16) & 0xff;
+
+ /* apn */
+ if (strlen(args_info.apn_arg) > (sizeof(apn.v) - 1)) {
+ printf("Invalid APN\n");
+ return -1;
+ }
+ apn.l = strlen(args_info.apn_arg) + 1;
+ apn.v[0] = (char)strlen(args_info.apn_arg);
+ strncpy((char *)&apn.v[1], args_info.apn_arg, sizeof(apn.v) - 1);
+
+ /* foreground */
+ /* If flag not given run as a daemon */
+ if (!args_info.fg_flag) {
+ FILE *f;
+ int rc;
+ closelog();
+ /* Close the standard file descriptors. */
+ /* Is this really needed ? */
+ f = freopen("/dev/null", "w", stdout);
+ if (f == NULL) {
+ sys_err(LOG_WARNING, __FILE__, __LINE__, 0,
+ "Could not redirect stdout to /dev/null");
+ }
+ f = freopen("/dev/null", "w", stderr);
+ if (f == NULL) {
+ sys_err(LOG_WARNING, __FILE__, __LINE__, 0,
+ "Could not redirect stderr to /dev/null");
+ }
+ f = freopen("/dev/null", "r", stdin);
+ if (f == NULL) {
+ sys_err(LOG_WARNING, __FILE__, __LINE__, 0,
+ "Could not redirect stdin to /dev/null");
+ }
+ rc = daemon(0, 0);
+ if (rc != 0) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, rc,
+ "Could not daemonize");
+ exit(1);
+ }
+ /* Open log again. This time with new pid */
+ openlog(PACKAGE, LOG_PID, LOG_DAEMON);
+ }
+
+ /* pidfile */
+ /* This has to be done after we have our final pid */
+ if (args_info.pidfile_arg) {
+ log_pid(args_info.pidfile_arg);
+ }
+
+ if (debug)
+ printf("gtpclient: Initialising GTP tunnel\n");
+
+ if (gtp_new(&gsn, args_info.statedir_arg, &listen_, GTP_MODE_GGSN)) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Failed to create gtp");
+ exit(1);
+ }
+ if (gsn->fd0 > maxfd)
+ maxfd = gsn->fd0;
+ if (gsn->fd1c > maxfd)
+ maxfd = gsn->fd1c;
+ if (gsn->fd1u > maxfd)
+ maxfd = gsn->fd1u;
+
+ gtp_set_cb_data_ind(gsn, encaps_tun);
+ gtp_set_cb_delete_context(gsn, delete_context);
+ gtp_set_cb_create_context_ind(gsn, create_context_ind);
+
+ /* Create a tunnel interface */
+ if (debug)
+ printf("Creating tun interface\n");
+ if (tun_new((struct tun_t **)&tun)) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Failed to create tun");
+ if (debug)
+ printf("Failed to create tun\n");
+ exit(1);
+ }
+
+ if (debug)
+ printf("Setting tun IP address\n");
+ if (tun_setaddr(tun, &netaddr, &destaddr, &mask)) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "Failed to set tun IP address");
+ if (debug)
+ printf("Failed to set tun IP address\n");
+ exit(1);
+ }
+
+ tun_set_cb_ind(tun, cb_tun_ind);
+ if (tun->fd > maxfd)
+ maxfd = tun->fd;
+
+ if (ipup)
+ tun_runscript(tun, ipup);
/******************************************************************/
- /* Main select loop */
+ /* Main select loop */
/******************************************************************/
- while ((((starttime + timelimit) > time(NULL)) || (0 == timelimit)) && (!end)) {
-
- FD_ZERO(&fds);
- if (tun) FD_SET(tun->fd, &fds);
- FD_SET(gsn->fd0, &fds);
- FD_SET(gsn->fd1c, &fds);
- FD_SET(gsn->fd1u, &fds);
-
- gtp_retranstimeout(gsn, &idleTime);
- switch (select(maxfd + 1, &fds, NULL, NULL, &idleTime)) {
- case -1: /* errno == EINTR : unblocked signal */
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "select() returned -1");
- /* On error, select returns without modifying fds */
- FD_ZERO(&fds);
- break;
- case 0:
- /* printf("Select returned 0\n"); */
- gtp_retrans(gsn); /* Only retransmit if nothing else */
- break;
- default:
- break;
- }
-
- if (tun->fd != -1 && FD_ISSET(tun->fd, &fds) &&
- tun_decaps(tun) < 0) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "TUN read failed (fd)=(%d)", tun->fd);
- }
-
- if (FD_ISSET(gsn->fd0, &fds))
- gtp_decaps0(gsn);
-
- if (FD_ISSET(gsn->fd1c, &fds))
- gtp_decaps1c(gsn);
-
- if (FD_ISSET(gsn->fd1u, &fds))
- gtp_decaps1u(gsn);
-
- }
-
- cmdline_parser_free(&args_info);
- ippool_free(ippool);
- gtp_free(gsn);
- tun_free(tun);
-
- return 1;
-
-}
+ while ((((starttime + timelimit) > time(NULL)) || (0 == timelimit))
+ && (!end)) {
+
+ FD_ZERO(&fds);
+ if (tun)
+ FD_SET(tun->fd, &fds);
+ FD_SET(gsn->fd0, &fds);
+ FD_SET(gsn->fd1c, &fds);
+ FD_SET(gsn->fd1u, &fds);
+
+ gtp_retranstimeout(gsn, &idleTime);
+ switch (select(maxfd + 1, &fds, NULL, NULL, &idleTime)) {
+ case -1: /* errno == EINTR : unblocked signal */
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "select() returned -1");
+ /* On error, select returns without modifying fds */
+ FD_ZERO(&fds);
+ break;
+ case 0:
+ /* printf("Select returned 0\n"); */
+ gtp_retrans(gsn); /* Only retransmit if nothing else */
+ break;
+ default:
+ break;
+ }
+
+ if (tun->fd != -1 && FD_ISSET(tun->fd, &fds) &&
+ tun_decaps(tun) < 0) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "TUN read failed (fd)=(%d)", tun->fd);
+ }
+
+ if (FD_ISSET(gsn->fd0, &fds))
+ gtp_decaps0(gsn);
+
+ if (FD_ISSET(gsn->fd1c, &fds))
+ gtp_decaps1c(gsn);
+
+ if (FD_ISSET(gsn->fd1u, &fds))
+ gtp_decaps1u(gsn);
+
+ }
+
+ cmdline_parser_free(&args_info);
+ ippool_free(ippool);
+ gtp_free(gsn);
+ tun_free(tun);
+
+ return 1;
+}
diff --git a/gtp/gtp.c b/gtp/gtp.c
index 4f75fd5..768d8c7 100644
--- a/gtp/gtp.c
+++ b/gtp/gtp.c
@@ -17,7 +17,6 @@
* - Do we need to handle fragmentation?
*/
-
#ifdef __linux__
#define _GNU_SOURCE 1
#endif
@@ -52,128 +51,127 @@
#include "gtpie.h"
#include "queue.h"
-
/* Error reporting functions */
-void gtp_err(int priority, char *filename, int linenum, char *fmt, ...) {
- va_list args;
- char buf[ERRMSG_SIZE];
-
- va_start(args, fmt);
- vsnprintf(buf, ERRMSG_SIZE, fmt, args);
- va_end(args);
- buf[ERRMSG_SIZE-1] = 0;
- syslog(priority, "%s: %d: %s", filename, linenum, buf);
+void gtp_err(int priority, char *filename, int linenum, char *fmt, ...)
+{
+ va_list args;
+ char buf[ERRMSG_SIZE];
+
+ va_start(args, fmt);
+ vsnprintf(buf, ERRMSG_SIZE, fmt, args);
+ va_end(args);
+ buf[ERRMSG_SIZE - 1] = 0;
+ syslog(priority, "%s: %d: %s", filename, linenum, buf);
}
void gtp_errpack(int pri, char *fn, int ln, struct sockaddr_in *peer,
- void *pack, unsigned len, char *fmt, ...) {
-
- va_list args;
- char buf[ERRMSG_SIZE];
- char buf2[ERRMSG_SIZE];
- unsigned int n;
- int pos;
-
- va_start(args, fmt);
- vsnprintf(buf, ERRMSG_SIZE, fmt, args);
- va_end(args);
- buf[ERRMSG_SIZE-1] = 0;
-
- snprintf(buf2, ERRMSG_SIZE, "Packet from %s:%u, length: %d, content:",
- inet_ntoa(peer->sin_addr),
- ntohs(peer->sin_port),
- len);
- buf2[ERRMSG_SIZE-1] = 0;
- pos = strlen(buf2);
- for(n=0; n<len; n++) {
- if ((pos+4)<ERRMSG_SIZE) {
- sprintf((buf2+pos), " %02hhx", ((unsigned char*)pack)[n]);
- pos += 3;
- }
- }
- buf2[pos] = 0;
-
- syslog(pri, "%s: %d: %s. %s", fn, ln, buf, buf2);
-
-}
+ void *pack, unsigned len, char *fmt, ...)
+{
+ va_list args;
+ char buf[ERRMSG_SIZE];
+ char buf2[ERRMSG_SIZE];
+ unsigned int n;
+ int pos;
+
+ va_start(args, fmt);
+ vsnprintf(buf, ERRMSG_SIZE, fmt, args);
+ va_end(args);
+ buf[ERRMSG_SIZE - 1] = 0;
+
+ snprintf(buf2, ERRMSG_SIZE, "Packet from %s:%u, length: %d, content:",
+ inet_ntoa(peer->sin_addr), ntohs(peer->sin_port), len);
+ buf2[ERRMSG_SIZE - 1] = 0;
+ pos = strlen(buf2);
+ for (n = 0; n < len; n++) {
+ if ((pos + 4) < ERRMSG_SIZE) {
+ sprintf((buf2 + pos), " %02hhx",
+ ((unsigned char *)pack)[n]);
+ pos += 3;
+ }
+ }
+ buf2[pos] = 0;
+ syslog(pri, "%s: %d: %s. %s", fn, ln, buf, buf2);
+}
/* API Functions */
-const char* gtp_version()
+const char *gtp_version()
{
- return VERSION;
+ return VERSION;
}
/* gtp_new */
/* gtp_free */
-int gtp_newpdp(struct gsn_t* gsn, struct pdp_t **pdp,
- uint64_t imsi, uint8_t nsapi) {
- return pdp_newpdp(pdp, imsi, nsapi, NULL);
+int gtp_newpdp(struct gsn_t *gsn, struct pdp_t **pdp,
+ uint64_t imsi, uint8_t nsapi)
+{
+ return pdp_newpdp(pdp, imsi, nsapi, NULL);
}
-int gtp_freepdp(struct gsn_t* gsn, struct pdp_t *pdp) {
- return pdp_freepdp(pdp);
+int gtp_freepdp(struct gsn_t *gsn, struct pdp_t *pdp)
+{
+ return pdp_freepdp(pdp);
}
/* gtp_gpdu */
-extern int gtp_fd(struct gsn_t *gsn) {
- return gsn->fd0;
+extern int gtp_fd(struct gsn_t *gsn)
+{
+ return gsn->fd0;
}
/* gtp_decaps */
/* gtp_retrans */
/* gtp_retranstimeout */
-
int gtp_set_cb_unsup_ind(struct gsn_t *gsn,
- int (*cb) (struct sockaddr_in *peer)) {
- gsn->cb_unsup_ind = cb;
- return 0;
+ int (*cb) (struct sockaddr_in * peer))
+{
+ gsn->cb_unsup_ind = cb;
+ return 0;
}
int gtp_set_cb_extheader_ind(struct gsn_t *gsn,
- int (*cb) (struct sockaddr_in *peer)) {
- gsn->cb_extheader_ind = cb;
- return 0;
+ int (*cb) (struct sockaddr_in * peer))
+{
+ gsn->cb_extheader_ind = cb;
+ return 0;
}
-
/* API: Initialise delete context callback */
/* Called whenever a pdp context is deleted for any reason */
-int gtp_set_cb_delete_context(struct gsn_t *gsn,
- int (*cb) (struct pdp_t* pdp))
+int gtp_set_cb_delete_context(struct gsn_t *gsn, int (*cb) (struct pdp_t * pdp))
{
- gsn->cb_delete_context = cb;
- return 0;
+ gsn->cb_delete_context = cb;
+ return 0;
}
int gtp_set_cb_conf(struct gsn_t *gsn,
- int (*cb) (int type, int cause,
- struct pdp_t* pdp, void *cbp)) {
- gsn->cb_conf = cb;
- return 0;
+ int (*cb) (int type, int cause,
+ struct pdp_t * pdp, void *cbp))
+{
+ gsn->cb_conf = cb;
+ return 0;
}
int gtp_set_cb_recovery(struct gsn_t *gsn,
- int (*cb) (struct sockaddr_in *peer,
- uint8_t recovery)) {
- gsn->cb_recovery = cb;
- return 0;
+ int (*cb) (struct sockaddr_in * peer, uint8_t recovery))
+{
+ gsn->cb_recovery = cb;
+ return 0;
}
extern int gtp_set_cb_data_ind(struct gsn_t *gsn,
- int (*cb_data_ind) (struct pdp_t* pdp,
- void* pack,
- unsigned len))
+ int (*cb_data_ind) (struct pdp_t * pdp,
+ void *pack, unsigned len))
{
- gsn->cb_data_ind = cb_data_ind;
- return 0;
+ gsn->cb_data_ind = cb_data_ind;
+ return 0;
}
/**
@@ -184,35 +182,38 @@ extern int gtp_set_cb_data_ind(struct gsn_t *gsn,
* to hold the packet header.
* returns the length of the header. 0 on error.
**/
-static unsigned int get_default_gtp(int version, uint8_t type, void *packet) {
- struct gtp0_header *gtp0_default = (struct gtp0_header*) packet;
- struct gtp1_header_long *gtp1_default = (struct gtp1_header_long*) packet;
- switch (version) {
- case 0:
- /* Initialise "standard" GTP0 header */
- memset(gtp0_default, 0, sizeof(struct gtp0_header));
- gtp0_default->flags=0x1e;
- gtp0_default->type=hton8(type);
- gtp0_default->spare1=0xff;
- gtp0_default->spare2=0xff;
- gtp0_default->spare3=0xff;
- gtp0_default->number=0xff;
- return GTP0_HEADER_SIZE;
- case 1:
- /* Initialise "standard" GTP1 header */
- /* 29.060: 8.2: S=1 and PN=0 */
- /* 29.060 9.3.1: For GTP-U messages Echo Request, Echo Response */
- /* and Supported Extension Headers Notification, the S field shall be */
- /* set to 1 */
- /* Currently extension headers are not supported */
- memset(gtp1_default, 0, sizeof(struct gtp1_header_long));
- gtp1_default->flags=0x32; /* No extension, enable sequence, no N-PDU */
- gtp1_default->type=hton8(type);
- return GTP1_HEADER_SIZE_LONG;
- default:
- gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown GTP packet version");
- return 0;
- }
+static unsigned int get_default_gtp(int version, uint8_t type, void *packet)
+{
+ struct gtp0_header *gtp0_default = (struct gtp0_header *)packet;
+ struct gtp1_header_long *gtp1_default =
+ (struct gtp1_header_long *)packet;
+ switch (version) {
+ case 0:
+ /* Initialise "standard" GTP0 header */
+ memset(gtp0_default, 0, sizeof(struct gtp0_header));
+ gtp0_default->flags = 0x1e;
+ gtp0_default->type = hton8(type);
+ gtp0_default->spare1 = 0xff;
+ gtp0_default->spare2 = 0xff;
+ gtp0_default->spare3 = 0xff;
+ gtp0_default->number = 0xff;
+ return GTP0_HEADER_SIZE;
+ case 1:
+ /* Initialise "standard" GTP1 header */
+ /* 29.060: 8.2: S=1 and PN=0 */
+ /* 29.060 9.3.1: For GTP-U messages Echo Request, Echo Response */
+ /* and Supported Extension Headers Notification, the S field shall be */
+ /* set to 1 */
+ /* Currently extension headers are not supported */
+ memset(gtp1_default, 0, sizeof(struct gtp1_header_long));
+ gtp1_default->flags = 0x32; /* No extension, enable sequence, no N-PDU */
+ gtp1_default->type = hton8(type);
+ return GTP1_HEADER_SIZE_LONG;
+ default:
+ gtp_err(LOG_ERR, __FILE__, __LINE__,
+ "Unknown GTP packet version");
+ return 0;
+ }
}
/**
@@ -220,18 +221,18 @@ static unsigned int get_default_gtp(int version, uint8_t type, void *packet) {
* Get sequence number of a packet.
* Returns 0 on error
**/
-static uint16_t get_seq(void *pack) {
- union gtp_packet *packet = (union gtp_packet *) pack;
-
- if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
- return ntoh16(packet->gtp0.h.seq);
- }
- else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
- return ntoh16(packet->gtp1l.h.seq);
- } else {
- gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
- return 0;
- }
+static uint16_t get_seq(void *pack)
+{
+ union gtp_packet *packet = (union gtp_packet *)pack;
+
+ if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
+ return ntoh16(packet->gtp0.h.seq);
+ } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
+ return ntoh16(packet->gtp1l.h.seq);
+ } else {
+ gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
+ return 0;
+ }
}
/**
@@ -239,13 +240,14 @@ static uint16_t get_seq(void *pack) {
* Get tunnel identifier of a packet.
* Returns 0 on error
**/
-static uint64_t get_tid(void *pack) {
- union gtp_packet *packet = (union gtp_packet *) pack;
-
- if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
- return packet->gtp0.h.tid;
- }
- return 0;
+static uint64_t get_tid(void *pack)
+{
+ union gtp_packet *packet = (union gtp_packet *)pack;
+
+ if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
+ return packet->gtp0.h.tid;
+ }
+ return 0;
}
/**
@@ -253,21 +255,20 @@ static uint64_t get_tid(void *pack) {
* Get the header length of a packet.
* Returns 0 on error
**/
-static uint16_t get_hlen(void *pack) {
- union gtp_packet *packet = (union gtp_packet *) pack;
-
- if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
- return GTP0_HEADER_SIZE;
- }
- else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
- return GTP1_HEADER_SIZE_LONG;
- }
- else if ((packet->flags & 0xe7) == 0x20) { /* Short version 1 */
- return GTP1_HEADER_SIZE_SHORT;
- } else {
- gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
- return 0;
- }
+static uint16_t get_hlen(void *pack)
+{
+ union gtp_packet *packet = (union gtp_packet *)pack;
+
+ if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
+ return GTP0_HEADER_SIZE;
+ } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
+ return GTP1_HEADER_SIZE_LONG;
+ } else if ((packet->flags & 0xe7) == 0x20) { /* Short version 1 */
+ return GTP1_HEADER_SIZE_SHORT;
+ } else {
+ gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
+ return 0;
+ }
}
/**
@@ -275,55 +276,53 @@ static uint16_t get_hlen(void *pack) {
* Get the tunnel endpoint identifier (flow label) of a packet.
* Returns 0xffffffff on error.
**/
-static uint32_t get_tei(void *pack) {
- union gtp_packet *packet = (union gtp_packet *) pack;
-
- if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
- return ntoh16(packet->gtp0.h.flow);
- }
- else if ((packet->flags & 0xe0) == 0x20) { /* Version 1 */
- return ntoh32(packet->gtp1l.h.tei);
- }
- else {
- gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
- return 0xffffffff;
- }
+static uint32_t get_tei(void *pack)
+{
+ union gtp_packet *packet = (union gtp_packet *)pack;
+
+ if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
+ return ntoh16(packet->gtp0.h.flow);
+ } else if ((packet->flags & 0xe0) == 0x20) { /* Version 1 */
+ return ntoh32(packet->gtp1l.h.tei);
+ } else {
+ gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
+ return 0xffffffff;
+ }
}
-
int print_packet(void *packet, unsigned len)
{
- unsigned int i;
- printf("The packet looks like this (%d bytes):\n", len);
- for( i=0; i<len; i++) {
- printf("%02x ", (unsigned char)*(char *)(packet+i));
- if (!((i+1)%16)) printf("\n");
- };
- printf("\n");
- return 0;
+ unsigned int i;
+ printf("The packet looks like this (%d bytes):\n", len);
+ for (i = 0; i < len; i++) {
+ printf("%02x ", (unsigned char)*(char *)(packet + i));
+ if (!((i + 1) % 16))
+ printf("\n");
+ };
+ printf("\n");
+ return 0;
}
-char* snprint_packet(struct gsn_t *gsn, struct sockaddr_in *peer,
- void *pack, unsigned len, char *buf, int size) {
- unsigned int n;
- int pos;
- snprintf(buf, size, "Packet from %s:%u, length: %d, content:",
- inet_ntoa(peer->sin_addr),
- ntohs(peer->sin_port),
- len);
- buf[size-1] = 0;
- pos = strlen(buf);
- for(n=0; n<len; n++) {
- if ((pos+4)<size) {
- sprintf((buf+pos), " %02hhx", ((unsigned char*)pack)[n]);
- pos += 3;
- }
- }
- buf[pos] = 0;
- return buf;
+char *snprint_packet(struct gsn_t *gsn, struct sockaddr_in *peer,
+ void *pack, unsigned len, char *buf, int size)
+{
+ unsigned int n;
+ int pos;
+ snprintf(buf, size, "Packet from %s:%u, length: %d, content:",
+ inet_ntoa(peer->sin_addr), ntohs(peer->sin_port), len);
+ buf[size - 1] = 0;
+ pos = strlen(buf);
+ for (n = 0; n < len; n++) {
+ if ((pos + 4) < size) {
+ sprintf((buf + pos), " %02hhx",
+ ((unsigned char *)pack)[n]);
+ pos += 3;
+ }
+ }
+ buf[pos] = 0;
+ return buf;
}
-
/* ***********************************************************
* Reliable delivery of signalling messages
*
@@ -403,71 +402,74 @@ char* snprint_packet(struct gsn_t *gsn, struct sockaddr_in *peer,
*************************************************************/
int gtp_req(struct gsn_t *gsn, int version, struct pdp_t *pdp,
- union gtp_packet *packet, int len,
- struct in_addr *inetaddr, void *cbp) {
- struct sockaddr_in addr;
- struct qmsg_t *qmsg;
- int fd;
-
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_addr = *inetaddr;
+ union gtp_packet *packet, int len,
+ struct in_addr *inetaddr, void *cbp)
+{
+ struct sockaddr_in addr;
+ struct qmsg_t *qmsg;
+ int fd;
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_addr = *inetaddr;
#if defined(__FreeBSD__) || defined(__APPLE__)
- addr.sin_len = sizeof(addr);
+ addr.sin_len = sizeof(addr);
#endif
- if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
- addr.sin_port = htons(GTP0_PORT);
- packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
- packet->gtp0.h.seq = hton16(gsn->seq_next);
- if (pdp)
- packet->gtp0.h.tid = (pdp->imsi & 0x0fffffffffffffffull) +
- ((uint64_t)pdp->nsapi << 60);
- if (pdp && ((packet->gtp0.h.type == GTP_GPDU) ||
- (packet->gtp0.h.type == GTP_ERROR)))
- packet->gtp0.h.flow=hton16(pdp->flru);
- else if (pdp)
- packet->gtp0.h.flow=hton16(pdp->flrc);
- fd = gsn->fd0;
- }
- else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
- addr.sin_port = htons(GTP1C_PORT);
- packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
- packet->gtp1l.h.seq = hton16(gsn->seq_next);
- if (pdp && ((packet->gtp1l.h.type == GTP_GPDU) ||
- (packet->gtp1l.h.type == GTP_ERROR)))
- packet->gtp1l.h.tei=hton32(pdp->teid_gn);
- else if (pdp)
- packet->gtp1l.h.tei=hton32(pdp->teic_gn);
- fd = gsn->fd1c;
- } else {
- gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
- return -1;
- }
-
- if (sendto(fd, packet, len, 0,
- (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- gsn->err_sendto++;
- gtp_err(LOG_ERR, __FILE__, __LINE__, "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s", fd, (unsigned long) &packet, len, strerror(errno));
- return -1;
- }
-
- /* Use new queue structure */
- if (queue_newmsg(gsn->queue_req, &qmsg, &addr, gsn->seq_next)) {
- gsn->err_queuefull++;
- gtp_err(LOG_ERR, __FILE__, __LINE__, "Retransmit queue is full");
- }
- else {
- memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
- qmsg->l = len;
- qmsg->timeout = time(NULL) + 3; /* When to timeout */
- qmsg->retrans = 0; /* No retransmissions so far */
- qmsg->cbp = cbp;
- qmsg->type = ntoh8(packet->gtp0.h.type);
- qmsg->fd = fd;
- }
- gsn->seq_next++; /* Count up this time */
- return 0;
+ if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
+ addr.sin_port = htons(GTP0_PORT);
+ packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
+ packet->gtp0.h.seq = hton16(gsn->seq_next);
+ if (pdp)
+ packet->gtp0.h.tid =
+ (pdp->imsi & 0x0fffffffffffffffull) +
+ ((uint64_t) pdp->nsapi << 60);
+ if (pdp && ((packet->gtp0.h.type == GTP_GPDU)
+ || (packet->gtp0.h.type == GTP_ERROR)))
+ packet->gtp0.h.flow = hton16(pdp->flru);
+ else if (pdp)
+ packet->gtp0.h.flow = hton16(pdp->flrc);
+ fd = gsn->fd0;
+ } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
+ addr.sin_port = htons(GTP1C_PORT);
+ packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
+ packet->gtp1l.h.seq = hton16(gsn->seq_next);
+ if (pdp && ((packet->gtp1l.h.type == GTP_GPDU) ||
+ (packet->gtp1l.h.type == GTP_ERROR)))
+ packet->gtp1l.h.tei = hton32(pdp->teid_gn);
+ else if (pdp)
+ packet->gtp1l.h.tei = hton32(pdp->teic_gn);
+ fd = gsn->fd1c;
+ } else {
+ gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
+ return -1;
+ }
+
+ if (sendto(fd, packet, len, 0,
+ (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ gsn->err_sendto++;
+ gtp_err(LOG_ERR, __FILE__, __LINE__,
+ "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s", fd,
+ (unsigned long)&packet, len, strerror(errno));
+ return -1;
+ }
+
+ /* Use new queue structure */
+ if (queue_newmsg(gsn->queue_req, &qmsg, &addr, gsn->seq_next)) {
+ gsn->err_queuefull++;
+ gtp_err(LOG_ERR, __FILE__, __LINE__,
+ "Retransmit queue is full");
+ } else {
+ memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
+ qmsg->l = len;
+ qmsg->timeout = time(NULL) + 3; /* When to timeout */
+ qmsg->retrans = 0; /* No retransmissions so far */
+ qmsg->cbp = cbp;
+ qmsg->type = ntoh8(packet->gtp0.h.type);
+ qmsg->fd = fd;
+ }
+ gsn->seq_next++; /* Count up this time */
+ return 0;
}
/* gtp_conf
@@ -475,373 +477,402 @@ int gtp_req(struct gsn_t *gsn, int version, struct pdp_t *pdp,
* return 0 on success, EOF if packet was not found */
int gtp_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
- union gtp_packet *packet, int len, uint8_t *type, void **cbp) {
-
- uint16_t seq;
-
- if ((packet->gtp0.h.flags & 0xe0) == 0x00)
- seq = ntoh16(packet->gtp0.h.seq);
- else if ((packet->gtp1l.h.flags & 0xe2) == 0x22)
- seq = ntoh16(packet->gtp1l.h.seq);
- else {
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, packet, len,
- "Unknown GTP packet version");
- return EOF;
- }
-
- if (queue_freemsg_seq(gsn->queue_req, peer, seq, type, cbp)) {
- gsn->err_seq++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, packet, len,
- "Confirmation packet not found in queue");
- return EOF;
- }
-
- return 0;
+ union gtp_packet *packet, int len, uint8_t * type, void **cbp)
+{
+
+ uint16_t seq;
+
+ if ((packet->gtp0.h.flags & 0xe0) == 0x00)
+ seq = ntoh16(packet->gtp0.h.seq);
+ else if ((packet->gtp1l.h.flags & 0xe2) == 0x22)
+ seq = ntoh16(packet->gtp1l.h.seq);
+ else {
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, packet, len,
+ "Unknown GTP packet version");
+ return EOF;
+ }
+
+ if (queue_freemsg_seq(gsn->queue_req, peer, seq, type, cbp)) {
+ gsn->err_seq++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, packet, len,
+ "Confirmation packet not found in queue");
+ return EOF;
+ }
+
+ return 0;
}
-int gtp_retrans(struct gsn_t *gsn) {
- /* Retransmit any outstanding packets */
- /* Remove from queue if maxretrans exceeded */
- time_t now;
- struct qmsg_t *qmsg;
- now = time(NULL);
- /*printf("Retrans: New beginning %d\n", (int) now);*/
-
- while ((!queue_getfirst(gsn->queue_req, &qmsg)) &&
- (qmsg->timeout <= now)) {
- /*printf("Retrans timeout found: %d\n", (int) time(NULL));*/
- if (qmsg->retrans > 3) { /* To many retrans */
- if (gsn->cb_conf) gsn->cb_conf(qmsg->type, EOF, NULL, qmsg->cbp);
- queue_freemsg(gsn->queue_req, qmsg);
- }
- else {
- if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
- (struct sockaddr *) &qmsg->peer, sizeof(struct sockaddr_in)) < 0) {
- gsn->err_sendto++;
- gtp_err(LOG_ERR, __FILE__, __LINE__, "Sendto(fd0=%d, msg=%lx, len=%d) failed: Error = %s", gsn->fd0, (unsigned long) &qmsg->p, qmsg->l, strerror(errno));
- }
- queue_back(gsn->queue_req, qmsg);
- qmsg->timeout = now + 3;
- qmsg->retrans++;
- }
- }
-
- /* Also clean up reply timeouts */
- while ((!queue_getfirst(gsn->queue_resp, &qmsg)) &&
- (qmsg->timeout < now)) {
- /*printf("Retrans (reply) timeout found: %d\n", (int) time(NULL));*/
- queue_freemsg(gsn->queue_resp, qmsg);
- }
-
- return 0;
+int gtp_retrans(struct gsn_t *gsn)
+{
+ /* Retransmit any outstanding packets */
+ /* Remove from queue if maxretrans exceeded */
+ time_t now;
+ struct qmsg_t *qmsg;
+ now = time(NULL);
+ /*printf("Retrans: New beginning %d\n", (int) now); */
+
+ while ((!queue_getfirst(gsn->queue_req, &qmsg)) &&
+ (qmsg->timeout <= now)) {
+ /*printf("Retrans timeout found: %d\n", (int) time(NULL)); */
+ if (qmsg->retrans > 3) { /* To many retrans */
+ if (gsn->cb_conf)
+ gsn->cb_conf(qmsg->type, EOF, NULL, qmsg->cbp);
+ queue_freemsg(gsn->queue_req, qmsg);
+ } else {
+ if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
+ (struct sockaddr *)&qmsg->peer,
+ sizeof(struct sockaddr_in)) < 0) {
+ gsn->err_sendto++;
+ gtp_err(LOG_ERR, __FILE__, __LINE__,
+ "Sendto(fd0=%d, msg=%lx, len=%d) failed: Error = %s",
+ gsn->fd0, (unsigned long)&qmsg->p,
+ qmsg->l, strerror(errno));
+ }
+ queue_back(gsn->queue_req, qmsg);
+ qmsg->timeout = now + 3;
+ qmsg->retrans++;
+ }
+ }
+
+ /* Also clean up reply timeouts */
+ while ((!queue_getfirst(gsn->queue_resp, &qmsg)) &&
+ (qmsg->timeout < now)) {
+ /*printf("Retrans (reply) timeout found: %d\n", (int) time(NULL)); */
+ queue_freemsg(gsn->queue_resp, qmsg);
+ }
+
+ return 0;
}
-int gtp_retranstimeout(struct gsn_t *gsn, struct timeval *timeout) {
- time_t now, later;
- struct qmsg_t *qmsg;
-
- if (queue_getfirst(gsn->queue_req, &qmsg)) {
- timeout->tv_sec = 10;
- timeout->tv_usec = 0;
- }
- else {
- now = time(NULL);
- later = qmsg->timeout;
- timeout->tv_sec = later - now;
- timeout->tv_usec = 0;
- if (timeout->tv_sec < 0) timeout->tv_sec = 0; /* No negative allowed */
- if (timeout->tv_sec > 10) timeout->tv_sec = 10; /* Max sleep for 10 sec*/
- }
- return 0;
+int gtp_retranstimeout(struct gsn_t *gsn, struct timeval *timeout)
+{
+ time_t now, later;
+ struct qmsg_t *qmsg;
+
+ if (queue_getfirst(gsn->queue_req, &qmsg)) {
+ timeout->tv_sec = 10;
+ timeout->tv_usec = 0;
+ } else {
+ now = time(NULL);
+ later = qmsg->timeout;
+ timeout->tv_sec = later - now;
+ timeout->tv_usec = 0;
+ if (timeout->tv_sec < 0)
+ timeout->tv_sec = 0; /* No negative allowed */
+ if (timeout->tv_sec > 10)
+ timeout->tv_sec = 10; /* Max sleep for 10 sec */
+ }
+ return 0;
}
-int gtp_resp(int version, struct gsn_t *gsn, struct pdp_t *pdp,
+int gtp_resp(int version, struct gsn_t *gsn, struct pdp_t *pdp,
union gtp_packet *packet, int len,
- struct sockaddr_in *peer, int fd,
- uint16_t seq, uint64_t tid) {
- struct qmsg_t *qmsg;
-
- if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
- packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
- packet->gtp0.h.seq = hton16(seq);
- packet->gtp0.h.tid = tid;
- if (pdp && ((packet->gtp0.h.type == GTP_GPDU) ||
- (packet->gtp0.h.type == GTP_ERROR)))
- packet->gtp0.h.flow=hton16(pdp->flru);
- else if (pdp)
- packet->gtp0.h.flow=hton16(pdp->flrc);
- }
- else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
- packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
- packet->gtp1l.h.seq = hton16(seq);
- if (pdp && (fd == gsn->fd1u))
- packet->gtp1l.h.tei=hton32(pdp->teid_gn);
- else if (pdp)
- packet->gtp1l.h.tei=hton32(pdp->teic_gn);
- }
- else {
- gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
- return -1;
- }
-
- if (fcntl(fd, F_SETFL, 0)) {
- gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
- return -1;
- }
-
- if (sendto(fd, packet, len, 0,
- (struct sockaddr *) peer, sizeof(struct sockaddr_in)) < 0) {
- gsn->err_sendto++;
- gtp_err(LOG_ERR, __FILE__, __LINE__, "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s", fd, (unsigned long) &packet, len, strerror(errno));
- return -1;
- }
-
- /* Use new queue structure */
- if (queue_newmsg(gsn->queue_resp, &qmsg, peer, seq)) {
- gsn->err_queuefull++;
- gtp_err(LOG_ERR, __FILE__, __LINE__, "Retransmit queue is full");
- }
- else {
- memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
- qmsg->l = len;
- qmsg->timeout = time(NULL) + 60; /* When to timeout */
- qmsg->retrans = 0; /* No retransmissions so far */
- qmsg->cbp = NULL;
- qmsg->type = 0;
- qmsg->fd = fd;
- }
- return 0;
+ struct sockaddr_in *peer, int fd, uint16_t seq, uint64_t tid)
+{
+ struct qmsg_t *qmsg;
+
+ if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
+ packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
+ packet->gtp0.h.seq = hton16(seq);
+ packet->gtp0.h.tid = tid;
+ if (pdp && ((packet->gtp0.h.type == GTP_GPDU) ||
+ (packet->gtp0.h.type == GTP_ERROR)))
+ packet->gtp0.h.flow = hton16(pdp->flru);
+ else if (pdp)
+ packet->gtp0.h.flow = hton16(pdp->flrc);
+ } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
+ packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
+ packet->gtp1l.h.seq = hton16(seq);
+ if (pdp && (fd == gsn->fd1u))
+ packet->gtp1l.h.tei = hton32(pdp->teid_gn);
+ else if (pdp)
+ packet->gtp1l.h.tei = hton32(pdp->teic_gn);
+ } else {
+ gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
+ return -1;
+ }
+
+ if (fcntl(fd, F_SETFL, 0)) {
+ gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
+ return -1;
+ }
+
+ if (sendto(fd, packet, len, 0,
+ (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
+ gsn->err_sendto++;
+ gtp_err(LOG_ERR, __FILE__, __LINE__,
+ "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s", fd,
+ (unsigned long)&packet, len, strerror(errno));
+ return -1;
+ }
+
+ /* Use new queue structure */
+ if (queue_newmsg(gsn->queue_resp, &qmsg, peer, seq)) {
+ gsn->err_queuefull++;
+ gtp_err(LOG_ERR, __FILE__, __LINE__,
+ "Retransmit queue is full");
+ } else {
+ memcpy(&qmsg->p, packet, sizeof(union gtp_packet));
+ qmsg->l = len;
+ qmsg->timeout = time(NULL) + 60; /* When to timeout */
+ qmsg->retrans = 0; /* No retransmissions so far */
+ qmsg->cbp = NULL;
+ qmsg->type = 0;
+ qmsg->fd = fd;
+ }
+ return 0;
}
int gtp_notification(struct gsn_t *gsn, int version,
union gtp_packet *packet, int len,
- struct sockaddr_in *peer, int fd,
- uint16_t seq) {
-
- struct sockaddr_in addr;
-
- memcpy(&addr, peer, sizeof(addr));
-
- /* In GTP0 notifications are treated as replies. In GTP1 they
- are requests for which there is no reply */
-
- if (fd == gsn->fd1c)
- addr.sin_port = htons(GTP1C_PORT);
- else if (fd == gsn->fd1u)
- addr.sin_port = htons(GTP1C_PORT);
-
- if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
- packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
- packet->gtp0.h.seq = hton16(seq);
- }
- else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
- packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
- packet->gtp1l.h.seq = hton16(seq);
- }
- else {
- gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
- return -1;
- }
-
- if (fcntl(fd, F_SETFL, 0)) {
- gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
- return -1;
- }
-
- if (sendto(fd, packet, len, 0,
- (struct sockaddr *) &addr, sizeof(struct sockaddr_in)) < 0) {
- gsn->err_sendto++;
- gtp_err(LOG_ERR, __FILE__, __LINE__, "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s", fd, (unsigned long) &packet, len, strerror(errno));
- return -1;
- }
- return 0;
-}
+ struct sockaddr_in *peer, int fd, uint16_t seq)
+{
+
+ struct sockaddr_in addr;
+
+ memcpy(&addr, peer, sizeof(addr));
+
+ /* In GTP0 notifications are treated as replies. In GTP1 they
+ are requests for which there is no reply */
+
+ if (fd == gsn->fd1c)
+ addr.sin_port = htons(GTP1C_PORT);
+ else if (fd == gsn->fd1u)
+ addr.sin_port = htons(GTP1C_PORT);
-int gtp_dublicate(struct gsn_t *gsn, int version,
- struct sockaddr_in *peer, uint16_t seq) {
- struct qmsg_t *qmsg;
-
- if(queue_seqget(gsn->queue_resp, &qmsg, peer, seq)) {
- return EOF; /* Notfound */
- }
-
- if (fcntl(qmsg->fd, F_SETFL, 0)) {
- gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
- return -1;
- }
-
- if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
- (struct sockaddr *) peer, sizeof(struct sockaddr_in)) < 0) {
- gsn->err_sendto++;
- gtp_err(LOG_ERR, __FILE__, __LINE__, "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s", qmsg->fd, (unsigned long) &qmsg->p, qmsg->l, strerror(errno));
- }
- return 0;
+ if ((packet->flags & 0xe0) == 0x00) { /* Version 0 */
+ packet->gtp0.h.length = hton16(len - GTP0_HEADER_SIZE);
+ packet->gtp0.h.seq = hton16(seq);
+ } else if ((packet->flags & 0xe2) == 0x22) { /* Version 1 with seq */
+ packet->gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT);
+ packet->gtp1l.h.seq = hton16(seq);
+ } else {
+ gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown packet flag");
+ return -1;
+ }
+
+ if (fcntl(fd, F_SETFL, 0)) {
+ gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
+ return -1;
+ }
+
+ if (sendto(fd, packet, len, 0,
+ (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) {
+ gsn->err_sendto++;
+ gtp_err(LOG_ERR, __FILE__, __LINE__,
+ "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s", fd,
+ (unsigned long)&packet, len, strerror(errno));
+ return -1;
+ }
+ return 0;
}
+int gtp_dublicate(struct gsn_t *gsn, int version,
+ struct sockaddr_in *peer, uint16_t seq)
+{
+ struct qmsg_t *qmsg;
+ if (queue_seqget(gsn->queue_resp, &qmsg, peer, seq)) {
+ return EOF; /* Notfound */
+ }
+
+ if (fcntl(qmsg->fd, F_SETFL, 0)) {
+ gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
+ return -1;
+ }
+
+ if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
+ (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) {
+ gsn->err_sendto++;
+ gtp_err(LOG_ERR, __FILE__, __LINE__,
+ "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s",
+ qmsg->fd, (unsigned long)&qmsg->p, qmsg->l,
+ strerror(errno));
+ }
+ return 0;
+}
/* Perform restoration and recovery error handling as described in 29.060 */
-static void log_restart(struct gsn_t *gsn) {
+static void log_restart(struct gsn_t *gsn)
+{
FILE *f;
int i, rc;
int counter = 0;
char filename[NAMESIZE];
- filename[NAMESIZE-1] = 0; /* No null term. guarantee by strncpy */
- strncpy(filename, gsn->statedir, NAMESIZE-1);
- strncat(filename, RESTART_FILE,
- NAMESIZE-1-sizeof(RESTART_FILE));
+ filename[NAMESIZE - 1] = 0; /* No null term. guarantee by strncpy */
+ strncpy(filename, gsn->statedir, NAMESIZE - 1);
+ strncat(filename, RESTART_FILE, NAMESIZE - 1 - sizeof(RESTART_FILE));
i = umask(022);
/* We try to open file. On failure we will later try to create file */
if (!(f = fopen(filename, "r"))) {
- gtp_err(LOG_ERR, __FILE__, __LINE__, "State information file (%s) not found. Creating new file.", filename);
+ gtp_err(LOG_ERR, __FILE__, __LINE__,
+ "State information file (%s) not found. Creating new file.",
+ filename);
+ } else {
+ umask(i);
+ rc = fscanf(f, "%d", &counter);
+ if (rc != 1) {
+ gtp_err(LOG_ERR, __FILE__, __LINE__,
+ "fscanf failed to read counter value");
+ return;
+ }
+ if (fclose(f)) {
+ gtp_err(LOG_ERR, __FILE__, __LINE__,
+ "fclose failed: Error = %s", strerror(errno));
+ }
}
- else {
- umask(i);
- rc = fscanf(f, "%d", &counter);
- if (rc != 1) {
- gtp_err(LOG_ERR, __FILE__, __LINE__, "fscanf failed to read counter value");
- return;
- }
- if (fclose(f)) {
- gtp_err(LOG_ERR, __FILE__, __LINE__, "fclose failed: Error = %s", strerror(errno));
- }
- }
-
- gsn->restart_counter = (unsigned char) counter;
+
+ gsn->restart_counter = (unsigned char)counter;
gsn->restart_counter++;
-
+
if (!(f = fopen(filename, "w"))) {
- gtp_err(LOG_ERR, __FILE__, __LINE__, "fopen(path=%s, mode=%s) failed: Error = %s", filename, "w", strerror(errno));
- return;
+ gtp_err(LOG_ERR, __FILE__, __LINE__,
+ "fopen(path=%s, mode=%s) failed: Error = %s", filename,
+ "w", strerror(errno));
+ return;
}
umask(i);
fprintf(f, "%d\n", gsn->restart_counter);
if (fclose(f)) {
- gtp_err(LOG_ERR, __FILE__, __LINE__, "fclose failed: Error = %s", strerror(errno));
- return;
+ gtp_err(LOG_ERR, __FILE__, __LINE__,
+ "fclose failed: Error = %s", strerror(errno));
+ return;
}
}
-
-
int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
- int mode)
+ int mode)
{
- struct sockaddr_in addr;
-
- syslog(LOG_ERR, "GTP: gtp_newgsn() started");
-
- *gsn = calloc(sizeof(struct gsn_t), 1); /* TODO */
-
- (*gsn)->statedir = statedir;
- log_restart(*gsn);
-
- /* Initialise sequence number */
- (*gsn)->seq_next = (*gsn)->restart_counter * 1024;
-
- /* Initialise request retransmit queue */
- queue_new(&(*gsn)->queue_req);
- queue_new(&(*gsn)->queue_resp);
-
- /* Initialise pdp table */
- pdp_init();
-
- /* Initialise call back functions */
- (*gsn)->cb_create_context_ind = 0;
- (*gsn)->cb_delete_context = 0;
- (*gsn)->cb_unsup_ind = 0;
- (*gsn)->cb_conf = 0;
- (*gsn)->cb_data_ind = 0;
-
- /* Store function parameters */
- (*gsn)->gsnc = *listen;
- (*gsn)->gsnu = *listen;
- (*gsn)->mode = mode;
-
-
- /* Create GTP version 0 socket */
- if (((*gsn)->fd0 = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
- (*gsn)->err_socket++;
- gtp_err(LOG_ERR, __FILE__, __LINE__, "socket(domain=%d, type=%d, protocol=%d) failed: Error = %s", AF_INET, SOCK_DGRAM, 0, strerror(errno));
- return -1;
- }
-
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_addr = *listen; /* Same IP for user traffic and signalling*/
- addr.sin_port = htons(GTP0_PORT);
+ struct sockaddr_in addr;
+
+ syslog(LOG_ERR, "GTP: gtp_newgsn() started");
+
+ *gsn = calloc(sizeof(struct gsn_t), 1); /* TODO */
+
+ (*gsn)->statedir = statedir;
+ log_restart(*gsn);
+
+ /* Initialise sequence number */
+ (*gsn)->seq_next = (*gsn)->restart_counter * 1024;
+
+ /* Initialise request retransmit queue */
+ queue_new(&(*gsn)->queue_req);
+ queue_new(&(*gsn)->queue_resp);
+
+ /* Initialise pdp table */
+ pdp_init();
+
+ /* Initialise call back functions */
+ (*gsn)->cb_create_context_ind = 0;
+ (*gsn)->cb_delete_context = 0;
+ (*gsn)->cb_unsup_ind = 0;
+ (*gsn)->cb_conf = 0;
+ (*gsn)->cb_data_ind = 0;
+
+ /* Store function parameters */
+ (*gsn)->gsnc = *listen;
+ (*gsn)->gsnu = *listen;
+ (*gsn)->mode = mode;
+
+ /* Create GTP version 0 socket */
+ if (((*gsn)->fd0 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ (*gsn)->err_socket++;
+ gtp_err(LOG_ERR, __FILE__, __LINE__,
+ "socket(domain=%d, type=%d, protocol=%d) failed: Error = %s",
+ AF_INET, SOCK_DGRAM, 0, strerror(errno));
+ return -1;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
+ addr.sin_port = htons(GTP0_PORT);
#if defined(__FreeBSD__) || defined(__APPLE__)
- addr.sin_len = sizeof(addr);
+ addr.sin_len = sizeof(addr);
#endif
-
- if (bind((*gsn)->fd0, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- (*gsn)->err_socket++;
- gtp_err(LOG_ERR, __FILE__, __LINE__, "bind(fd0=%d, addr=%lx, len=%d) failed: Error = %s", (*gsn)->fd0, (unsigned long) &addr, sizeof(addr), strerror(errno));
- return -1;
- }
-
- /* Create GTP version 1 control plane socket */
- if (((*gsn)->fd1c = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
- (*gsn)->err_socket++;
- gtp_err(LOG_ERR, __FILE__, __LINE__, "socket(domain=%d, type=%d, protocol=%d) failed: Error = %s", AF_INET, SOCK_DGRAM, 0, strerror(errno));
- return -1;
- }
-
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_addr = *listen; /* Same IP for user traffic and signalling*/
- addr.sin_port = htons(GTP1C_PORT);
+
+ if (bind((*gsn)->fd0, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ (*gsn)->err_socket++;
+ gtp_err(LOG_ERR, __FILE__, __LINE__,
+ "bind(fd0=%d, addr=%lx, len=%d) failed: Error = %s",
+ (*gsn)->fd0, (unsigned long)&addr, sizeof(addr),
+ strerror(errno));
+ return -1;
+ }
+
+ /* Create GTP version 1 control plane socket */
+ if (((*gsn)->fd1c = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ (*gsn)->err_socket++;
+ gtp_err(LOG_ERR, __FILE__, __LINE__,
+ "socket(domain=%d, type=%d, protocol=%d) failed: Error = %s",
+ AF_INET, SOCK_DGRAM, 0, strerror(errno));
+ return -1;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
+ addr.sin_port = htons(GTP1C_PORT);
#if defined(__FreeBSD__) || defined(__APPLE__)
- addr.sin_len = sizeof(addr);
+ addr.sin_len = sizeof(addr);
#endif
-
- if (bind((*gsn)->fd1c, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- (*gsn)->err_socket++;
- gtp_err(LOG_ERR, __FILE__, __LINE__, "bind(fd1c=%d, addr=%lx, len=%d) failed: Error = %s", (*gsn)->fd1c, (unsigned long) &addr, sizeof(addr), strerror(errno));
- return -1;
- }
-
- /* Create GTP version 1 user plane socket */
- if (((*gsn)->fd1u = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
- (*gsn)->err_socket++;
- gtp_err(LOG_ERR, __FILE__, __LINE__, "socket(domain=%d, type=%d, protocol=%d) failed: Error = %s", AF_INET, SOCK_DGRAM, 0, strerror(errno));
- return -1;
- }
-
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_addr = *listen; /* Same IP for user traffic and signalling*/
- addr.sin_port = htons(GTP1U_PORT);
+
+ if (bind((*gsn)->fd1c, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ (*gsn)->err_socket++;
+ gtp_err(LOG_ERR, __FILE__, __LINE__,
+ "bind(fd1c=%d, addr=%lx, len=%d) failed: Error = %s",
+ (*gsn)->fd1c, (unsigned long)&addr, sizeof(addr),
+ strerror(errno));
+ return -1;
+ }
+
+ /* Create GTP version 1 user plane socket */
+ if (((*gsn)->fd1u = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ (*gsn)->err_socket++;
+ gtp_err(LOG_ERR, __FILE__, __LINE__,
+ "socket(domain=%d, type=%d, protocol=%d) failed: Error = %s",
+ AF_INET, SOCK_DGRAM, 0, strerror(errno));
+ return -1;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_addr = *listen; /* Same IP for user traffic and signalling */
+ addr.sin_port = htons(GTP1U_PORT);
#if defined(__FreeBSD__) || defined(__APPLE__)
- addr.sin_len = sizeof(addr);
+ addr.sin_len = sizeof(addr);
#endif
-
- if (bind((*gsn)->fd1u, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- (*gsn)->err_socket++;
- gtp_err(LOG_ERR, __FILE__, __LINE__, "bind(fd1c=%d, addr=%lx, len=%d) failed: Error = %s", (*gsn)->fd1c, (unsigned long) &addr, sizeof(addr), strerror(errno));
- return -1;
- }
-
- return 0;
+
+ if (bind((*gsn)->fd1u, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ (*gsn)->err_socket++;
+ gtp_err(LOG_ERR, __FILE__, __LINE__,
+ "bind(fd1c=%d, addr=%lx, len=%d) failed: Error = %s",
+ (*gsn)->fd1c, (unsigned long)&addr, sizeof(addr),
+ strerror(errno));
+ return -1;
+ }
+
+ return 0;
}
-int gtp_free(struct gsn_t *gsn) {
+int gtp_free(struct gsn_t *gsn)
+{
- /* Clean up retransmit queues */
- queue_free(gsn->queue_req);
- queue_free(gsn->queue_resp);
-
- close(gsn->fd0);
- close(gsn->fd1c);
- close(gsn->fd1u);
+ /* Clean up retransmit queues */
+ queue_free(gsn->queue_req);
+ queue_free(gsn->queue_resp);
- free(gsn);
- return 0;
+ close(gsn->fd0);
+ close(gsn->fd1c);
+ close(gsn->fd1u);
+
+ free(gsn);
+ return 0;
}
/* ***********************************************************
@@ -877,71 +908,78 @@ int gtp_free(struct gsn_t *gsn) {
int gtp_echo_req(struct gsn_t *gsn, int version, void *cbp,
struct in_addr *inetaddr)
{
- union gtp_packet packet;
- unsigned int length = get_default_gtp(version, GTP_ECHO_REQ, &packet);
- return gtp_req(gsn, version, NULL, &packet, length, inetaddr, cbp);
+ union gtp_packet packet;
+ unsigned int length = get_default_gtp(version, GTP_ECHO_REQ, &packet);
+ return gtp_req(gsn, version, NULL, &packet, length, inetaddr, cbp);
}
/* Send off an echo reply */
int gtp_echo_resp(struct gsn_t *gsn, int version,
- struct sockaddr_in *peer, int fd,
- void *pack, unsigned len)
+ struct sockaddr_in *peer, int fd, void *pack, unsigned len)
{
- union gtp_packet packet;
- unsigned int length = get_default_gtp(version, GTP_ECHO_RSP, &packet);
- gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY, gsn->restart_counter);
- return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
- get_seq(pack), get_tid(pack));
+ union gtp_packet packet;
+ unsigned int length = get_default_gtp(version, GTP_ECHO_RSP, &packet);
+ gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
+ gsn->restart_counter);
+ return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
+ get_seq(pack), get_tid(pack));
}
-
/* Handle a received echo request */
-int gtp_echo_ind(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
- int fd, void *pack, unsigned len) {
+int gtp_echo_ind(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
+ int fd, void *pack, unsigned len)
+{
- /* Check if it was a dublicate request */
- if(!gtp_dublicate(gsn, 0, peer, get_seq(pack))) return 0;
+ /* Check if it was a dublicate request */
+ if (!gtp_dublicate(gsn, 0, peer, get_seq(pack)))
+ return 0;
- /* Send off reply to request */
- return gtp_echo_resp(gsn, version, peer, fd, pack, len);
+ /* Send off reply to request */
+ return gtp_echo_resp(gsn, version, peer, fd, pack, len);
}
/* Handle a received echo reply */
int gtp_echo_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
- void *pack, unsigned len) {
- union gtpie_member *ie[GTPIE_SIZE];
- unsigned char recovery;
- void *cbp = NULL;
- uint8_t type = 0;
- int hlen = get_hlen(pack);
-
- /* Remove packet from queue */
- if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp)) return EOF;
-
- /* Extract information elements into a pointer array */
- if (gtpie_decaps(ie, version, pack+hlen, len-hlen)) {
- gsn->invalid++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Invalid message format");
- if (gsn->cb_conf) gsn->cb_conf(type, EOF, NULL, cbp);
- return EOF;
- }
-
- if (gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing mandatory field");
- if (gsn->cb_conf) gsn->cb_conf(type, EOF, NULL, cbp);
- return EOF;
- }
-
- /* Echo reply packages does not have a cause information element */
- /* Instead we return the recovery number in the callback function */
- if (gsn->cb_conf) gsn->cb_conf(type, recovery, NULL, cbp);
-
- if (gsn->cb_recovery) gsn->cb_recovery(peer, recovery);
-
- return 0;
+ void *pack, unsigned len)
+{
+ union gtpie_member *ie[GTPIE_SIZE];
+ unsigned char recovery;
+ void *cbp = NULL;
+ uint8_t type = 0;
+ int hlen = get_hlen(pack);
+
+ /* Remove packet from queue */
+ if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
+ return EOF;
+
+ /* Extract information elements into a pointer array */
+ if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
+ gsn->invalid++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
+ "Invalid message format");
+ if (gsn->cb_conf)
+ gsn->cb_conf(type, EOF, NULL, cbp);
+ return EOF;
+ }
+
+ if (gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
+ "Missing mandatory field");
+ if (gsn->cb_conf)
+ gsn->cb_conf(type, EOF, NULL, cbp);
+ return EOF;
+ }
+
+ /* Echo reply packages does not have a cause information element */
+ /* Instead we return the recovery number in the callback function */
+ if (gsn->cb_conf)
+ gsn->cb_conf(type, recovery, NULL, cbp);
+
+ if (gsn->cb_recovery)
+ gsn->cb_recovery(peer, recovery);
+
+ return 0;
}
/* Send off a Version Not Supported message */
@@ -958,52 +996,55 @@ int gtp_echo_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
int gtp_unsup_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
int fd, void *pack, unsigned len)
{
- union gtp_packet packet;
+ union gtp_packet packet;
- /* GTP 1 is the highest supported protocol */
- unsigned int length = get_default_gtp(1, GTP_NOT_SUPPORTED, &packet);
- return gtp_notification(gsn, version, &packet, length,
- peer, fd, 0);
+ /* GTP 1 is the highest supported protocol */
+ unsigned int length = get_default_gtp(1, GTP_NOT_SUPPORTED, &packet);
+ return gtp_notification(gsn, version, &packet, length, peer, fd, 0);
}
/* Handle a Version Not Supported message */
-int gtp_unsup_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
- void *pack, unsigned len) {
+int gtp_unsup_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
+ void *pack, unsigned len)
+{
- if (gsn->cb_unsup_ind) gsn->cb_unsup_ind(peer);
-
- return 0;
+ if (gsn->cb_unsup_ind)
+ gsn->cb_unsup_ind(peer);
+
+ return 0;
}
/* Send off an Supported Extension Headers Notification */
int gtp_extheader_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
int fd, void *pack, unsigned len)
{
- union gtp_packet packet;
- unsigned int length = get_default_gtp(version, GTP_SUPP_EXT_HEADER, &packet);
+ union gtp_packet packet;
+ unsigned int length =
+ get_default_gtp(version, GTP_SUPP_EXT_HEADER, &packet);
- uint8_t pdcp_pdu = GTP_EXT_PDCP_PDU;
+ uint8_t pdcp_pdu = GTP_EXT_PDCP_PDU;
- if (version < 1)
- return 0;
+ if (version < 1)
+ return 0;
- /* We report back that we support only PDCP PDU headers */
- gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EXT_HEADER_T, sizeof(pdcp_pdu),
- &pdcp_pdu);
+ /* We report back that we support only PDCP PDU headers */
+ gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EXT_HEADER_T,
+ sizeof(pdcp_pdu), &pdcp_pdu);
- return gtp_notification(gsn, version, &packet, length,
- peer, fd, get_seq(pack));
+ return gtp_notification(gsn, version, &packet, length,
+ peer, fd, get_seq(pack));
}
/* Handle a Supported Extension Headers Notification */
-int gtp_extheader_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
- void *pack, unsigned len) {
+int gtp_extheader_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
+ void *pack, unsigned len)
+{
- if (gsn->cb_extheader_ind) gsn->cb_extheader_ind(peer);
-
- return 0;
-}
+ if (gsn->cb_extheader_ind)
+ gsn->cb_extheader_ind(peer);
+ return 0;
+}
/* ***********************************************************
* Session management messages
@@ -1018,1466 +1059,1564 @@ int gtp_extheader_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
*************************************************************/
/* API: Send Create PDP Context Request (7.3.1) */
-extern int gtp_create_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
- void *cbp) {
- union gtp_packet packet;
- unsigned int length = get_default_gtp(pdp->version, GTP_CREATE_PDP_REQ, &packet);
- struct pdp_t *linked_pdp = NULL;
-
- /* TODO: Secondary PDP Context Activation Procedure */
- /* In secondary activation procedure the PDP context is identified
- by tei in the header. The following fields are omitted: Selection
- mode, IMSI, MSISDN, End User Address, Access Point Name and
- Protocol Configuration Options */
-
- if (pdp->secondary) {
- if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
- gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown linked PDP context");
- return EOF;
- }
- }
-
- if (pdp->version == 0) {
- gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
- sizeof(pdp->qos_req0), pdp->qos_req0);
- }
-
- /* Section 7.7.2 */
- if (pdp->version == 1) {
- if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
- gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
- sizeof(pdp->imsi), (uint8_t*) &pdp->imsi);
- }
-
- /* Section 7.7.3 Routing Area Information */
- if (pdp->rai_given == 1)
- gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_RAI,
- pdp->rai.l, (uint8_t*) &pdp->rai.v);
-
-
- /* Section 7.7.11 */
- if (pdp->norecovery_given == 0)
- gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
- gsn->restart_counter);
-
- /* Section 7.7.12 */
- if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
- gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_SELECTION_MODE,
- pdp->selmode);
-
- if (pdp->version == 0) {
- gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
- pdp->fllu);
- gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
- pdp->fllc);
- }
-
- /* Section 7.7.13 */
- if (pdp->version == 1) {
- gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
- pdp->teid_own);
-
- /* Section 7.7.14 */
- if (!pdp->teic_confirmed)
- gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
- pdp->teic_own);
-
- /* Section 7.7.17 */
- gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI,
- pdp->nsapi);
-
- /* Section 7.7.17 */
- if (pdp->secondary) /* Secondary PDP Context Activation Procedure */
- gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI,
- linked_pdp->nsapi);
-
- /* Section 7.7.23 */
- if (pdp->cch_pdp) /* Only include charging if flags are set */
- gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_CHARGING_C,
- pdp->cch_pdp);
- }
-
- /* TODO
- gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
- pdp->traceref);
- gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
- pdp->tracetype); */
-
- /* Section 7.7.27 */
- if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
- gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
- pdp->eua.l, pdp->eua.v);
-
-
- /* Section 7.7.30 */
- if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
- gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_APN,
- pdp->apn_use.l, pdp->apn_use.v);
-
- /* Section 7.7.31 */
- if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
- if (pdp->pco_req.l)
- gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
- pdp->pco_req.l, pdp->pco_req.v);
-
- /* Section 7.7.32 */
- gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
- pdp->gsnlc.l, pdp->gsnlc.v);
- /* Section 7.7.32 */
- gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
- pdp->gsnlu.l, pdp->gsnlu.v);
-
- /* Section 7.7.33 */
- if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
- gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MSISDN,
- pdp->msisdn.l, pdp->msisdn.v);
-
- /* Section 7.7.34 */
- if (pdp->version == 1)
- gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
- pdp->qos_req.l, pdp->qos_req.v);
-
- /* Section 7.7.36 */
- if ((pdp->version == 1) && pdp->tft.l)
- gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
- pdp->tft.l, pdp->tft.v);
-
- /* Section 7.7.41 */
- if ((pdp->version == 1) && pdp->triggerid.l)
- gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
- pdp->triggerid.l, pdp->triggerid.v);
-
- /* Section 7.7.42 */
- if ((pdp->version == 1) && pdp->omcid.l)
- 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);
-
- return 0;
+extern int gtp_create_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
+ void *cbp)
+{
+ union gtp_packet packet;
+ unsigned int length =
+ get_default_gtp(pdp->version, GTP_CREATE_PDP_REQ, &packet);
+ struct pdp_t *linked_pdp = NULL;
+
+ /* TODO: Secondary PDP Context Activation Procedure */
+ /* In secondary activation procedure the PDP context is identified
+ by tei in the header. The following fields are omitted: Selection
+ mode, IMSI, MSISDN, End User Address, Access Point Name and
+ Protocol Configuration Options */
+
+ if (pdp->secondary) {
+ if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
+ gtp_err(LOG_ERR, __FILE__, __LINE__,
+ "Unknown linked PDP context");
+ return EOF;
+ }
+ }
+
+ if (pdp->version == 0) {
+ gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
+ sizeof(pdp->qos_req0), pdp->qos_req0);
+ }
+
+ /* Section 7.7.2 */
+ if (pdp->version == 1) {
+ if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
+ gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
+ sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
+ }
+
+ /* Section 7.7.3 Routing Area Information */
+ if (pdp->rai_given == 1)
+ gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_RAI,
+ pdp->rai.l, (uint8_t *) & pdp->rai.v);
+
+ /* Section 7.7.11 */
+ if (pdp->norecovery_given == 0)
+ gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
+ gsn->restart_counter);
+
+ /* Section 7.7.12 */
+ if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
+ gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_SELECTION_MODE,
+ pdp->selmode);
+
+ if (pdp->version == 0) {
+ gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
+ gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
+ }
+
+ /* Section 7.7.13 */
+ if (pdp->version == 1) {
+ gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
+ pdp->teid_own);
+
+ /* Section 7.7.14 */
+ if (!pdp->teic_confirmed)
+ gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
+ pdp->teic_own);
+
+ /* Section 7.7.17 */
+ gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
+
+ /* Section 7.7.17 */
+ if (pdp->secondary) /* Secondary PDP Context Activation Procedure */
+ gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI,
+ linked_pdp->nsapi);
+
+ /* Section 7.7.23 */
+ if (pdp->cch_pdp) /* Only include charging if flags are set */
+ gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_CHARGING_C,
+ pdp->cch_pdp);
+ }
+
+ /* TODO
+ gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
+ pdp->traceref);
+ gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
+ pdp->tracetype); */
+
+ /* Section 7.7.27 */
+ if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
+ gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
+ pdp->eua.l, pdp->eua.v);
+
+ /* Section 7.7.30 */
+ if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
+ gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_APN,
+ pdp->apn_use.l, pdp->apn_use.v);
+
+ /* Section 7.7.31 */
+ if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
+ if (pdp->pco_req.l)
+ gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
+ pdp->pco_req.l, pdp->pco_req.v);
+
+ /* Section 7.7.32 */
+ gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
+ pdp->gsnlc.l, pdp->gsnlc.v);
+ /* Section 7.7.32 */
+ gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
+ pdp->gsnlu.l, pdp->gsnlu.v);
+
+ /* Section 7.7.33 */
+ if (!pdp->secondary) /* Not Secondary PDP Context Activation Procedure */
+ gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_MSISDN,
+ pdp->msisdn.l, pdp->msisdn.v);
+
+ /* Section 7.7.34 */
+ if (pdp->version == 1)
+ gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
+ pdp->qos_req.l, pdp->qos_req.v);
+
+ /* Section 7.7.36 */
+ if ((pdp->version == 1) && pdp->tft.l)
+ gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
+ pdp->tft.l, pdp->tft.v);
+
+ /* Section 7.7.41 */
+ if ((pdp->version == 1) && pdp->triggerid.l)
+ gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
+ pdp->triggerid.l, pdp->triggerid.v);
+
+ /* Section 7.7.42 */
+ if ((pdp->version == 1) && pdp->omcid.l)
+ 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);
+
+ return 0;
}
/* API: Application response to context indication */
-int gtp_create_context_resp(struct gsn_t *gsn, struct pdp_t *pdp, int cause) {
-
- /* Now send off a reply to the peer */
- gtp_create_pdp_resp(gsn, pdp->version, pdp, cause);
-
- if (cause != GTPCAUSE_ACC_REQ) {
- pdp_freepdp(pdp);
- }
-
- return 0;
+int gtp_create_context_resp(struct gsn_t *gsn, struct pdp_t *pdp, int cause)
+{
+
+ /* Now send off a reply to the peer */
+ gtp_create_pdp_resp(gsn, pdp->version, pdp, cause);
+
+ if (cause != GTPCAUSE_ACC_REQ) {
+ pdp_freepdp(pdp);
+ }
+
+ return 0;
}
/* API: Register create context indication callback */
int gtp_set_cb_create_context_ind(struct gsn_t *gsn,
- int (*cb_create_context_ind) (struct pdp_t* pdp))
+ int (*cb_create_context_ind) (struct pdp_t *
+ pdp))
{
- gsn->cb_create_context_ind = cb_create_context_ind;
- return 0;
+ gsn->cb_create_context_ind = cb_create_context_ind;
+ return 0;
}
-
/* Send Create PDP Context Response */
-int gtp_create_pdp_resp(struct gsn_t *gsn, int version, struct pdp_t *pdp,
- uint8_t cause) {
- union gtp_packet packet;
- unsigned int length = get_default_gtp(version, GTP_CREATE_PDP_RSP, &packet);
-
- gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
-
- if (cause == GTPCAUSE_ACC_REQ) {
-
- if (version == 0)
- gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
- sizeof(pdp->qos_neg0), pdp->qos_neg0);
-
- gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_REORDER,
- pdp->reorder);
- gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
- gsn->restart_counter);
-
- if (version == 0) {
- gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
- pdp->fllu);
- gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
- pdp->fllc);
- }
-
- if (version == 1) {
- gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
- pdp->teid_own);
- gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
- pdp->teic_own);
- }
-
- /* TODO: We use teic_own as charging ID */
- gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
- pdp->teic_own);
-
- gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
- pdp->eua.l, pdp->eua.v);
-
- if (pdp->pco_neg.l) { /* Optional PCO */
- gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
- pdp->pco_neg.l, pdp->pco_neg.v);
- }
-
- gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
- pdp->gsnlc.l, pdp->gsnlc.v);
- gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
- pdp->gsnlu.l, pdp->gsnlu.v);
-
- if (version == 1)
- gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
- pdp->qos_neg.l, pdp->qos_neg.v);
-
- /* TODO: Charging gateway address */
- }
-
- return gtp_resp(version, gsn, pdp, &packet, length, &pdp->sa_peer,
- pdp->fd, pdp->seq, pdp->tid);
+int gtp_create_pdp_resp(struct gsn_t *gsn, int version, struct pdp_t *pdp,
+ uint8_t cause)
+{
+ union gtp_packet packet;
+ unsigned int length =
+ get_default_gtp(version, GTP_CREATE_PDP_RSP, &packet);
+
+ gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
+
+ if (cause == GTPCAUSE_ACC_REQ) {
+
+ if (version == 0)
+ gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
+ sizeof(pdp->qos_neg0), pdp->qos_neg0);
+
+ gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_REORDER,
+ pdp->reorder);
+ gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
+ gsn->restart_counter);
+
+ if (version == 0) {
+ gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
+ pdp->fllu);
+ gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
+ pdp->fllc);
+ }
+
+ if (version == 1) {
+ gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
+ pdp->teid_own);
+ gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
+ pdp->teic_own);
+ }
+
+ /* TODO: We use teic_own as charging ID */
+ gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
+ pdp->teic_own);
+
+ gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
+ pdp->eua.l, pdp->eua.v);
+
+ if (pdp->pco_neg.l) { /* Optional PCO */
+ gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_PCO,
+ pdp->pco_neg.l, pdp->pco_neg.v);
+ }
+
+ gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
+ pdp->gsnlc.l, pdp->gsnlc.v);
+ gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
+ pdp->gsnlu.l, pdp->gsnlu.v);
+
+ if (version == 1)
+ gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
+ pdp->qos_neg.l, pdp->qos_neg.v);
+
+ /* TODO: Charging gateway address */
+ }
+
+ return gtp_resp(version, gsn, pdp, &packet, length, &pdp->sa_peer,
+ pdp->fd, pdp->seq, pdp->tid);
}
/* Handle Create PDP Context Request */
int gtp_create_pdp_ind(struct gsn_t *gsn, int version,
- struct sockaddr_in *peer, int fd,
- void *pack, unsigned len) {
- struct pdp_t *pdp, *pdp_old;
- struct pdp_t pdp_buf;
- union gtpie_member* ie[GTPIE_SIZE];
- uint8_t recovery;
-
- uint16_t seq = get_seq(pack);
- int hlen = get_hlen(pack);
- uint8_t linked_nsapi = 0;
- struct pdp_t *linked_pdp = NULL;
-
- if(!gtp_dublicate(gsn, version, peer, seq)) return 0;
-
- pdp = &pdp_buf;
- memset(pdp, 0, sizeof(struct pdp_t));
-
- if (version == 0) {
- pdp->imsi = ((union gtp_packet*)pack)->gtp0.h.tid & 0x0fffffffffffffffull;
- pdp->nsapi = (((union gtp_packet*)pack)->gtp0.h.tid & 0xf000000000000000ull) >> 60;
- }
-
- pdp->seq = seq;
- pdp->sa_peer = *peer;
- pdp->fd = fd;
- pdp->version = version;
-
- /* Decode information elements */
- if (gtpie_decaps(ie, version, pack+hlen, len-hlen)) {
- gsn->invalid++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Invalid message format");
- if (0 == version)
- return EOF;
- else
- return gtp_create_pdp_resp(gsn, version, pdp, GTPCAUSE_INVALID_MESSAGE);
- }
-
- if (version == 1) {
- /* Linked NSAPI (conditional) */
- /* If included this is the Secondary PDP Context Activation Procedure */
- /* In secondary activation IMSI is not included, so the context must be */
- /* identified by the tei */
- if (!gtpie_gettv1(ie, GTPIE_NSAPI, 1, &linked_nsapi)) {
-
- /* Find the primary PDP context */
- if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
- gsn->incorrect++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Incorrect optional information field");
- return gtp_create_pdp_resp(gsn, version, pdp,
- GTPCAUSE_OPT_IE_INCORRECT);
- }
-
- /* Check that the primary PDP context matches linked nsapi */
- if (linked_pdp->nsapi != linked_nsapi) {
- gsn->incorrect++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Incorrect optional information field");
- return gtp_create_pdp_resp(gsn, version, pdp,
- GTPCAUSE_OPT_IE_INCORRECT);
- }
-
- /* Copy parameters from primary context */
- pdp->selmode = linked_pdp->selmode;
- pdp->imsi = linked_pdp->imsi;
- pdp->msisdn = linked_pdp->msisdn;
- pdp->eua = linked_pdp->eua;
- pdp->pco_req = linked_pdp->pco_req;
- pdp->apn_req = linked_pdp->apn_req;
- pdp->teic_gn = linked_pdp->teic_gn;
- pdp->secondary = 1;
- }
- } /* if (version == 1) */
-
- if (version == 0) {
- if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
- pdp->qos_req0, sizeof(pdp->qos_req0))) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing mandatory information field");
- return gtp_create_pdp_resp(gsn, version, pdp, GTPCAUSE_MAN_IE_MISSING);
- }
- }
-
- if ((version == 1) && (!linked_pdp)) {
- /* Not Secondary PDP Context Activation Procedure */
- /* IMSI (conditional) */
- if (gtpie_gettv0(ie, GTPIE_IMSI, 0, &pdp->imsi, sizeof(pdp->imsi))) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing mandatory information field");
- return gtp_create_pdp_resp(gsn, version, pdp,
- GTPCAUSE_MAN_IE_MISSING);
- }
- }
-
- /* Recovery (optional) */
- if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
- if (gsn->cb_recovery) gsn->cb_recovery(peer, recovery);
- }
-
- /* Selection mode (conditional) */
- if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
- if (gtpie_gettv0(ie, GTPIE_SELECTION_MODE, 0,
- &pdp->selmode, sizeof(pdp->selmode))) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing mandatory information field");
- return gtp_create_pdp_resp(gsn, version, pdp,
- GTPCAUSE_MAN_IE_MISSING);
- }
- }
-
- if (version == 0) {
- if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing mandatory information field");
- return gtp_create_pdp_resp(gsn, version, pdp,
- GTPCAUSE_MAN_IE_MISSING);
- }
-
- if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing mandatory information field");
- return gtp_create_pdp_resp(gsn, version, pdp,
- GTPCAUSE_MAN_IE_MISSING);
- }
- }
-
-
- if (version == 1) {
- /* TEID (mandatory) */
- if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing mandatory information field");
- return gtp_create_pdp_resp(gsn, version, pdp,
- GTPCAUSE_MAN_IE_MISSING);
- }
-
- /* TEIC (conditional) */
- if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
- if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing mandatory information field");
- return gtp_create_pdp_resp(gsn, version, pdp,
- GTPCAUSE_MAN_IE_MISSING);
- }
- }
-
- /* NSAPI (mandatory) */
- if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing mandatory information field");
- return gtp_create_pdp_resp(gsn, version, pdp,
- GTPCAUSE_MAN_IE_MISSING);
- }
- }
-
-
- /* Charging Characteriatics (optional) */
- /* Trace reference (optional) */
- /* Trace type (optional) */
- /* Charging Characteriatics (optional) */
-
- if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
- /* End User Address (conditional) */
- if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
- &pdp->eua.v, sizeof(pdp->eua.v))) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing mandatory information field");
- return gtp_create_pdp_resp(gsn, version, pdp,
- GTPCAUSE_MAN_IE_MISSING);
- }
-
- /* APN */
- if (gtpie_gettlv(ie, GTPIE_APN, 0, &pdp->apn_req.l,
- &pdp->apn_req.v, sizeof(pdp->apn_req.v))) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing mandatory information field");
- return gtp_create_pdp_resp(gsn, version, pdp,
- GTPCAUSE_MAN_IE_MISSING);
- }
-
- /* Extract protocol configuration options (optional) */
- if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
- &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
- }
- }
-
- /* SGSN address for signalling (mandatory) */
- if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
- &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing mandatory information field");
- return gtp_create_pdp_resp(gsn, version, pdp,
- GTPCAUSE_MAN_IE_MISSING);
- }
-
- /* SGSN address for user traffic (mandatory) */
- if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
- &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing mandatory information field");
- return gtp_create_pdp_resp(gsn, version, pdp,
- GTPCAUSE_MAN_IE_MISSING);
- }
-
- if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
- /* MSISDN (conditional) */
- if (gtpie_gettlv(ie, GTPIE_MSISDN, 0, &pdp->msisdn.l,
- &pdp->msisdn.v, sizeof(pdp->msisdn.v))) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing mandatory information field");
- return gtp_create_pdp_resp(gsn, version, pdp,
- GTPCAUSE_MAN_IE_MISSING);
- }
- }
-
- if (version == 1) {
- /* QoS (mandatory) */
- if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
- &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing mandatory information field");
- return gtp_create_pdp_resp(gsn, version, pdp,
- GTPCAUSE_MAN_IE_MISSING);
- }
-
- /* TFT (conditional) */
- if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
- &pdp->tft.v, sizeof(pdp->tft.v))) {
- }
-
- /* Trigger ID */
- /* OMC identity */
- }
-
- /* Initialize our own IP addresses */
- in_addr2gsna(&pdp->gsnlc, &gsn->gsnc);
- in_addr2gsna(&pdp->gsnlu, &gsn->gsnu);
-
- if (GTP_DEBUG) printf("gtp_create_pdp_ind: Before pdp_tidget\n");
-
- if (!pdp_getimsi(&pdp_old, pdp->imsi, pdp->nsapi)) {
- /* Found old pdp with same tid. Now the voodoo begins! */
- /* 09.60 / 29.060 allows create on existing context to "steal" */
- /* the context which was allready established */
- /* We check that the APN, selection mode and MSISDN is the same */
- if (GTP_DEBUG) printf("gtp_create_pdp_ind: Old context found\n");
- if ((pdp->apn_req.l == pdp_old->apn_req.l)
- && (!memcmp(pdp->apn_req.v, pdp_old->apn_req.v, pdp->apn_req.l))
- && (pdp->selmode == pdp_old->selmode)
- && (pdp->msisdn.l == pdp_old->msisdn.l)
- && (!memcmp(pdp->msisdn.v, pdp_old->msisdn.v, pdp->msisdn.l))) {
- /* OK! We are dealing with the same APN. We will copy new
- * parameters to the old pdp and send off confirmation
- * We ignore the following information elements:
- * QoS: MS will get originally negotiated QoS.
- * End user address (EUA). MS will get old EUA anyway.
- * Protocol configuration option (PCO): Only application can verify */
-
- if (GTP_DEBUG) printf("gtp_create_pdp_ind: Old context found\n");
-
- /* Copy remote flow label */
- pdp_old->flru = pdp->flru;
- pdp_old->flrc = pdp->flrc;
-
- /* Copy remote tei */
- pdp_old->teid_gn = pdp->teid_gn;
- pdp_old->teic_gn = pdp->teic_gn;
-
- /* Copy peer GSN address */
- pdp_old->gsnrc.l = pdp->gsnrc.l;
- memcpy(&pdp_old->gsnrc.v, &pdp->gsnrc.v, pdp->gsnrc.l);
- pdp_old->gsnru.l = pdp->gsnru.l;
- memcpy(&pdp_old->gsnru.v, &pdp->gsnru.v, pdp->gsnru.l);
-
- /* Copy request parameters */
- pdp_old->seq = pdp->seq;
- pdp_old->sa_peer = pdp->sa_peer;
- pdp_old->fd = pdp->fd = fd;
- pdp_old->version = pdp->version = version;
-
- /* Switch to using the old pdp context */
- pdp = pdp_old;
-
- /* Confirm to peer that things were "successful" */
- return gtp_create_pdp_resp(gsn, version, pdp, GTPCAUSE_ACC_REQ);
- }
- else { /* This is not the same PDP context. Delete the old one. */
-
- if (GTP_DEBUG) printf("gtp_create_pdp_ind: Deleting old context\n");
-
- if (gsn->cb_delete_context) gsn->cb_delete_context(pdp_old);
- pdp_freepdp(pdp_old);
-
- if (GTP_DEBUG) printf("gtp_create_pdp_ind: Deleted...\n");
- }
- }
-
- pdp_newpdp(&pdp, pdp->imsi, pdp->nsapi, pdp);
-
- /* Callback function to validata login */
- if (gsn->cb_create_context_ind !=0)
- return gsn->cb_create_context_ind(pdp);
- else {
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "No create_context_ind callback defined");
- return gtp_create_pdp_resp(gsn, version, pdp, GTPCAUSE_NOT_SUPPORTED);
- }
-}
+ struct sockaddr_in *peer, int fd,
+ void *pack, unsigned len)
+{
+ struct pdp_t *pdp, *pdp_old;
+ struct pdp_t pdp_buf;
+ union gtpie_member *ie[GTPIE_SIZE];
+ uint8_t recovery;
+
+ uint16_t seq = get_seq(pack);
+ int hlen = get_hlen(pack);
+ uint8_t linked_nsapi = 0;
+ struct pdp_t *linked_pdp = NULL;
+
+ if (!gtp_dublicate(gsn, version, peer, seq))
+ return 0;
+
+ pdp = &pdp_buf;
+ memset(pdp, 0, sizeof(struct pdp_t));
+
+ if (version == 0) {
+ pdp->imsi =
+ ((union gtp_packet *)pack)->gtp0.
+ h.tid & 0x0fffffffffffffffull;
+ pdp->nsapi =
+ (((union gtp_packet *)pack)->gtp0.
+ h.tid & 0xf000000000000000ull) >> 60;
+ }
+
+ pdp->seq = seq;
+ pdp->sa_peer = *peer;
+ pdp->fd = fd;
+ pdp->version = version;
+
+ /* Decode information elements */
+ if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
+ gsn->invalid++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
+ "Invalid message format");
+ if (0 == version)
+ return EOF;
+ else
+ return gtp_create_pdp_resp(gsn, version, pdp,
+ GTPCAUSE_INVALID_MESSAGE);
+ }
+
+ if (version == 1) {
+ /* Linked NSAPI (conditional) */
+ /* If included this is the Secondary PDP Context Activation Procedure */
+ /* In secondary activation IMSI is not included, so the context must be */
+ /* identified by the tei */
+ if (!gtpie_gettv1(ie, GTPIE_NSAPI, 1, &linked_nsapi)) {
+
+ /* Find the primary PDP context */
+ if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
+ gsn->incorrect++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
+ pack, len,
+ "Incorrect optional information field");
+ return gtp_create_pdp_resp(gsn, version, pdp,
+ GTPCAUSE_OPT_IE_INCORRECT);
+ }
+
+ /* Check that the primary PDP context matches linked nsapi */
+ if (linked_pdp->nsapi != linked_nsapi) {
+ gsn->incorrect++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
+ pack, len,
+ "Incorrect optional information field");
+ return gtp_create_pdp_resp(gsn, version, pdp,
+ GTPCAUSE_OPT_IE_INCORRECT);
+ }
+
+ /* Copy parameters from primary context */
+ pdp->selmode = linked_pdp->selmode;
+ pdp->imsi = linked_pdp->imsi;
+ pdp->msisdn = linked_pdp->msisdn;
+ pdp->eua = linked_pdp->eua;
+ pdp->pco_req = linked_pdp->pco_req;
+ pdp->apn_req = linked_pdp->apn_req;
+ pdp->teic_gn = linked_pdp->teic_gn;
+ pdp->secondary = 1;
+ }
+ }
+ /* if (version == 1) */
+ if (version == 0) {
+ if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
+ pdp->qos_req0, sizeof(pdp->qos_req0))) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
+ len, "Missing mandatory information field");
+ return gtp_create_pdp_resp(gsn, version, pdp,
+ GTPCAUSE_MAN_IE_MISSING);
+ }
+ }
+
+ if ((version == 1) && (!linked_pdp)) {
+ /* Not Secondary PDP Context Activation Procedure */
+ /* IMSI (conditional) */
+ if (gtpie_gettv0
+ (ie, GTPIE_IMSI, 0, &pdp->imsi, sizeof(pdp->imsi))) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
+ len, "Missing mandatory information field");
+ return gtp_create_pdp_resp(gsn, version, pdp,
+ GTPCAUSE_MAN_IE_MISSING);
+ }
+ }
+
+ /* Recovery (optional) */
+ if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
+ if (gsn->cb_recovery)
+ gsn->cb_recovery(peer, recovery);
+ }
+
+ /* Selection mode (conditional) */
+ if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
+ if (gtpie_gettv0(ie, GTPIE_SELECTION_MODE, 0,
+ &pdp->selmode, sizeof(pdp->selmode))) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
+ len, "Missing mandatory information field");
+ return gtp_create_pdp_resp(gsn, version, pdp,
+ GTPCAUSE_MAN_IE_MISSING);
+ }
+ }
+
+ if (version == 0) {
+ if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
+ len, "Missing mandatory information field");
+ return gtp_create_pdp_resp(gsn, version, pdp,
+ GTPCAUSE_MAN_IE_MISSING);
+ }
+
+ if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
+ len, "Missing mandatory information field");
+ return gtp_create_pdp_resp(gsn, version, pdp,
+ GTPCAUSE_MAN_IE_MISSING);
+ }
+ }
+
+ if (version == 1) {
+ /* TEID (mandatory) */
+ if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
+ len, "Missing mandatory information field");
+ return gtp_create_pdp_resp(gsn, version, pdp,
+ GTPCAUSE_MAN_IE_MISSING);
+ }
+
+ /* TEIC (conditional) */
+ if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
+ if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
+ pack, len,
+ "Missing mandatory information field");
+ return gtp_create_pdp_resp(gsn, version, pdp,
+ GTPCAUSE_MAN_IE_MISSING);
+ }
+ }
+
+ /* NSAPI (mandatory) */
+ if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
+ len, "Missing mandatory information field");
+ return gtp_create_pdp_resp(gsn, version, pdp,
+ GTPCAUSE_MAN_IE_MISSING);
+ }
+ }
+
+ /* Charging Characteriatics (optional) */
+ /* Trace reference (optional) */
+ /* Trace type (optional) */
+ /* Charging Characteriatics (optional) */
+
+ if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
+ /* End User Address (conditional) */
+ if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
+ &pdp->eua.v, sizeof(pdp->eua.v))) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
+ len, "Missing mandatory information field");
+ return gtp_create_pdp_resp(gsn, version, pdp,
+ GTPCAUSE_MAN_IE_MISSING);
+ }
+
+ /* APN */
+ if (gtpie_gettlv(ie, GTPIE_APN, 0, &pdp->apn_req.l,
+ &pdp->apn_req.v, sizeof(pdp->apn_req.v))) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
+ len, "Missing mandatory information field");
+ return gtp_create_pdp_resp(gsn, version, pdp,
+ GTPCAUSE_MAN_IE_MISSING);
+ }
+
+ /* Extract protocol configuration options (optional) */
+ if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
+ &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
+ }
+ }
+ /* SGSN address for signalling (mandatory) */
+ if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
+ &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
+ "Missing mandatory information field");
+ return gtp_create_pdp_resp(gsn, version, pdp,
+ GTPCAUSE_MAN_IE_MISSING);
+ }
+
+ /* SGSN address for user traffic (mandatory) */
+ if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
+ &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
+ "Missing mandatory information field");
+ return gtp_create_pdp_resp(gsn, version, pdp,
+ GTPCAUSE_MAN_IE_MISSING);
+ }
+
+ if (!linked_pdp) { /* Not Secondary PDP Context Activation Procedure */
+ /* MSISDN (conditional) */
+ if (gtpie_gettlv(ie, GTPIE_MSISDN, 0, &pdp->msisdn.l,
+ &pdp->msisdn.v, sizeof(pdp->msisdn.v))) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
+ len, "Missing mandatory information field");
+ return gtp_create_pdp_resp(gsn, version, pdp,
+ GTPCAUSE_MAN_IE_MISSING);
+ }
+ }
+
+ if (version == 1) {
+ /* QoS (mandatory) */
+ if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
+ &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
+ len, "Missing mandatory information field");
+ return gtp_create_pdp_resp(gsn, version, pdp,
+ GTPCAUSE_MAN_IE_MISSING);
+ }
+
+ /* TFT (conditional) */
+ if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
+ &pdp->tft.v, sizeof(pdp->tft.v))) {
+ }
+
+ /* Trigger ID */
+ /* OMC identity */
+ }
+
+ /* Initialize our own IP addresses */
+ in_addr2gsna(&pdp->gsnlc, &gsn->gsnc);
+ in_addr2gsna(&pdp->gsnlu, &gsn->gsnu);
+
+ if (GTP_DEBUG)
+ printf("gtp_create_pdp_ind: Before pdp_tidget\n");
+
+ if (!pdp_getimsi(&pdp_old, pdp->imsi, pdp->nsapi)) {
+ /* Found old pdp with same tid. Now the voodoo begins! */
+ /* 09.60 / 29.060 allows create on existing context to "steal" */
+ /* the context which was allready established */
+ /* We check that the APN, selection mode and MSISDN is the same */
+ if (GTP_DEBUG)
+ printf("gtp_create_pdp_ind: Old context found\n");
+ if ((pdp->apn_req.l == pdp_old->apn_req.l)
+ &&
+ (!memcmp
+ (pdp->apn_req.v, pdp_old->apn_req.v, pdp->apn_req.l))
+ && (pdp->selmode == pdp_old->selmode)
+ && (pdp->msisdn.l == pdp_old->msisdn.l)
+ &&
+ (!memcmp(pdp->msisdn.v, pdp_old->msisdn.v, pdp->msisdn.l)))
+ {
+ /* OK! We are dealing with the same APN. We will copy new
+ * parameters to the old pdp and send off confirmation
+ * We ignore the following information elements:
+ * QoS: MS will get originally negotiated QoS.
+ * End user address (EUA). MS will get old EUA anyway.
+ * Protocol configuration option (PCO): Only application can verify */
+
+ if (GTP_DEBUG)
+ printf
+ ("gtp_create_pdp_ind: Old context found\n");
+
+ /* Copy remote flow label */
+ pdp_old->flru = pdp->flru;
+ pdp_old->flrc = pdp->flrc;
+
+ /* Copy remote tei */
+ pdp_old->teid_gn = pdp->teid_gn;
+ pdp_old->teic_gn = pdp->teic_gn;
+
+ /* Copy peer GSN address */
+ pdp_old->gsnrc.l = pdp->gsnrc.l;
+ memcpy(&pdp_old->gsnrc.v, &pdp->gsnrc.v, pdp->gsnrc.l);
+ pdp_old->gsnru.l = pdp->gsnru.l;
+ memcpy(&pdp_old->gsnru.v, &pdp->gsnru.v, pdp->gsnru.l);
+
+ /* Copy request parameters */
+ pdp_old->seq = pdp->seq;
+ pdp_old->sa_peer = pdp->sa_peer;
+ pdp_old->fd = pdp->fd = fd;
+ pdp_old->version = pdp->version = version;
+
+ /* Switch to using the old pdp context */
+ pdp = pdp_old;
+
+ /* Confirm to peer that things were "successful" */
+ return gtp_create_pdp_resp(gsn, version, pdp,
+ GTPCAUSE_ACC_REQ);
+ } else { /* This is not the same PDP context. Delete the old one. */
+
+ if (GTP_DEBUG)
+ printf
+ ("gtp_create_pdp_ind: Deleting old context\n");
+
+ if (gsn->cb_delete_context)
+ gsn->cb_delete_context(pdp_old);
+ pdp_freepdp(pdp_old);
+
+ if (GTP_DEBUG)
+ printf("gtp_create_pdp_ind: Deleted...\n");
+ }
+ }
+
+ pdp_newpdp(&pdp, pdp->imsi, pdp->nsapi, pdp);
+
+ /* Callback function to validata login */
+ if (gsn->cb_create_context_ind != 0)
+ return gsn->cb_create_context_ind(pdp);
+ else {
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
+ "No create_context_ind callback defined");
+ return gtp_create_pdp_resp(gsn, version, pdp,
+ GTPCAUSE_NOT_SUPPORTED);
+ }
+}
/* Handle Create PDP Context Response */
int gtp_create_pdp_conf(struct gsn_t *gsn, int version,
- struct sockaddr_in *peer,
- void *pack, unsigned len) {
- struct pdp_t *pdp;
- union gtpie_member *ie[GTPIE_SIZE];
- uint8_t cause, recovery;
- void *cbp = NULL;
- uint8_t type = 0;
- int hlen = get_hlen(pack);
-
- /* Remove packet from queue */
- if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp)) return EOF;
-
- /* Find the context in question */
- if (pdp_getgtp1(&pdp, get_tei(pack))) {
- gsn->err_unknownpdp++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Unknown PDP context");
- if (gsn->cb_conf) gsn->cb_conf(type, EOF, NULL, cbp);
- return EOF;
- }
-
- /* Register that we have received a valid teic from GGSN */
- pdp->teic_confirmed = 1;
-
- /* Decode information elements */
- if (gtpie_decaps(ie, version, pack+hlen, len-hlen)) {
- gsn->invalid++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Invalid message format");
- if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
- /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
- pdp_freepdp(pdp); */
- return EOF;
- }
-
- /* Extract cause value (mandatory) */
- if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing mandatory information field");
- if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
- /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
- pdp_freepdp(pdp); */
- return EOF;
- }
-
- /* Extract recovery (optional) */
- if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
- if (gsn->cb_recovery) gsn->cb_recovery(peer, recovery);
- }
-
- /* Extract protocol configuration options (optional) */
- if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
- &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
- }
-
- /* Check all conditional information elements */
- if (GTPCAUSE_ACC_REQ == cause) {
-
- if (version == 0) {
- if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
- &pdp->qos_neg0, sizeof(pdp->qos_neg0))) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing conditional information field");
- if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
- /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
- pdp_freepdp(pdp); */
- return EOF;
- }
- }
-
- if (gtpie_gettv1(ie, GTPIE_REORDER, 0, &pdp->reorder)) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing conditional information field");
- if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
- /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
- pdp_freepdp(pdp); */
- return EOF;
- }
-
- if (version == 0) {
- if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing conditional information field");
- if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
- /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
- pdp_freepdp(pdp); */
- return EOF;
- }
-
- if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing conditional information field");
- if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
- /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
- pdp_freepdp(pdp); */
- return EOF;
- }
- }
-
- if (version == 1) {
- if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing conditional information field");
- if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
- /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
- pdp_freepdp(pdp); */
- return EOF;
- }
-
- if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing conditional information field");
- if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
- /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
- pdp_freepdp(pdp); */
- return EOF;
- }
- }
-
- if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing conditional information field");
- if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
- /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
- pdp_freepdp(pdp); */
- }
-
- if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
- &pdp->eua.v, sizeof(pdp->eua.v))) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing conditional information field");
- if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
- /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
- pdp_freepdp(pdp); */
- return EOF;
- }
-
- if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
- &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing conditional information field");
- if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
- /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
- pdp_freepdp(pdp); */
- return EOF;
- }
-
- if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
- &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing conditional information field");
- if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
- /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
- pdp_freepdp(pdp); */
- return EOF;
- }
-
- if (version == 1) {
- if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
- &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing conditional information field");
- if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
- /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
- pdp_freepdp(pdp); */
- return EOF;
- }
- }
-
- }
-
- if (gsn->cb_conf) gsn->cb_conf(type, cause, pdp, cbp);
-
- return 0;
-}
+ struct sockaddr_in *peer, void *pack, unsigned len)
+{
+ struct pdp_t *pdp;
+ union gtpie_member *ie[GTPIE_SIZE];
+ uint8_t cause, recovery;
+ void *cbp = NULL;
+ uint8_t type = 0;
+ int hlen = get_hlen(pack);
+
+ /* Remove packet from queue */
+ if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
+ return EOF;
+
+ /* Find the context in question */
+ if (pdp_getgtp1(&pdp, get_tei(pack))) {
+ gsn->err_unknownpdp++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
+ "Unknown PDP context");
+ if (gsn->cb_conf)
+ gsn->cb_conf(type, EOF, NULL, cbp);
+ return EOF;
+ }
+ /* Register that we have received a valid teic from GGSN */
+ pdp->teic_confirmed = 1;
+
+ /* Decode information elements */
+ if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
+ gsn->invalid++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
+ "Invalid message format");
+ if (gsn->cb_conf)
+ gsn->cb_conf(type, EOF, pdp, cbp);
+ /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
+ pdp_freepdp(pdp); */
+ return EOF;
+ }
+
+ /* Extract cause value (mandatory) */
+ if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
+ "Missing mandatory information field");
+ if (gsn->cb_conf)
+ gsn->cb_conf(type, EOF, pdp, cbp);
+ /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
+ pdp_freepdp(pdp); */
+ return EOF;
+ }
+
+ /* Extract recovery (optional) */
+ if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
+ if (gsn->cb_recovery)
+ gsn->cb_recovery(peer, recovery);
+ }
+
+ /* Extract protocol configuration options (optional) */
+ if (!gtpie_gettlv(ie, GTPIE_PCO, 0, &pdp->pco_req.l,
+ &pdp->pco_req.v, sizeof(pdp->pco_req.v))) {
+ }
+
+ /* Check all conditional information elements */
+ if (GTPCAUSE_ACC_REQ == cause) {
+
+ if (version == 0) {
+ if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
+ &pdp->qos_neg0,
+ sizeof(pdp->qos_neg0))) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
+ pack, len,
+ "Missing conditional information field");
+ if (gsn->cb_conf)
+ gsn->cb_conf(type, EOF, pdp, cbp);
+ /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
+ pdp_freepdp(pdp); */
+ return EOF;
+ }
+ }
+
+ if (gtpie_gettv1(ie, GTPIE_REORDER, 0, &pdp->reorder)) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
+ len,
+ "Missing conditional information field");
+ if (gsn->cb_conf)
+ gsn->cb_conf(type, EOF, pdp, cbp);
+ /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
+ pdp_freepdp(pdp); */
+ return EOF;
+ }
+
+ if (version == 0) {
+ if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
+ pack, len,
+ "Missing conditional information field");
+ if (gsn->cb_conf)
+ gsn->cb_conf(type, EOF, pdp, cbp);
+ /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
+ pdp_freepdp(pdp); */
+ return EOF;
+ }
+
+ if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
+ pack, len,
+ "Missing conditional information field");
+ if (gsn->cb_conf)
+ gsn->cb_conf(type, EOF, pdp, cbp);
+ /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
+ pdp_freepdp(pdp); */
+ return EOF;
+ }
+ }
+
+ if (version == 1) {
+ if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
+ pack, len,
+ "Missing conditional information field");
+ if (gsn->cb_conf)
+ gsn->cb_conf(type, EOF, pdp, cbp);
+ /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
+ pdp_freepdp(pdp); */
+ return EOF;
+ }
+
+ if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
+ pack, len,
+ "Missing conditional information field");
+ if (gsn->cb_conf)
+ gsn->cb_conf(type, EOF, pdp, cbp);
+ /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
+ pdp_freepdp(pdp); */
+ return EOF;
+ }
+ }
+
+ if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
+ len,
+ "Missing conditional information field");
+ if (gsn->cb_conf)
+ gsn->cb_conf(type, EOF, pdp, cbp);
+ /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
+ pdp_freepdp(pdp); */
+ }
+
+ if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
+ &pdp->eua.v, sizeof(pdp->eua.v))) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
+ len,
+ "Missing conditional information field");
+ if (gsn->cb_conf)
+ gsn->cb_conf(type, EOF, pdp, cbp);
+ /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
+ pdp_freepdp(pdp); */
+ return EOF;
+ }
+
+ if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
+ &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
+ len,
+ "Missing conditional information field");
+ if (gsn->cb_conf)
+ gsn->cb_conf(type, EOF, pdp, cbp);
+ /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
+ pdp_freepdp(pdp); */
+ return EOF;
+ }
+
+ if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
+ &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
+ len,
+ "Missing conditional information field");
+ if (gsn->cb_conf)
+ gsn->cb_conf(type, EOF, pdp, cbp);
+ /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
+ pdp_freepdp(pdp); */
+ return EOF;
+ }
+
+ if (version == 1) {
+ if (gtpie_gettlv
+ (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
+ &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
+ pack, len,
+ "Missing conditional information field");
+ if (gsn->cb_conf)
+ gsn->cb_conf(type, EOF, pdp, cbp);
+ /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
+ pdp_freepdp(pdp); */
+ return EOF;
+ }
+ }
+
+ }
+
+ if (gsn->cb_conf)
+ gsn->cb_conf(type, cause, pdp, cbp);
+
+ return 0;
+}
/* API: Send Update PDP Context Request */
int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
- struct in_addr* inetaddr) {
- union gtp_packet packet;
- unsigned int length = get_default_gtp(pdp->version, GTP_UPDATE_PDP_REQ, &packet);
-
- if (pdp->version == 0)
- gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
- sizeof(pdp->qos_req0), pdp->qos_req0);
-
- /* Include IMSI if updating with unknown teic_gn */
- if ((pdp->version == 1) && (!pdp->teic_gn))
- gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
- sizeof(pdp->imsi), (uint8_t*) &pdp->imsi);
-
- gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
- gsn->restart_counter);
-
- if (pdp->version == 0) {
- gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
- pdp->fllu);
- gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
- pdp->fllc);
- }
-
- if (pdp->version == 1) {
- gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
- pdp->teid_own);
-
- if (!pdp->teic_confirmed)
- gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
- pdp->teic_own);
- }
-
- gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI,
- pdp->nsapi);
-
- /* TODO
- gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
- pdp->traceref);
- gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
- pdp->tracetype); */
-
- /* TODO if ggsn update message
- gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
- pdp->eua.l, pdp->eua.v);
- */
-
- gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
- pdp->gsnlc.l, pdp->gsnlc.v);
- gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
- pdp->gsnlu.l, pdp->gsnlu.v);
-
- if (pdp->version == 1)
- gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
- pdp->qos_req.l, pdp->qos_req.v);
-
-
- if ((pdp->version == 1) && pdp->tft.l)
- gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
- pdp->tft.l, pdp->tft.v);
-
- if ((pdp->version == 1) && pdp->triggerid.l)
- gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
- pdp->triggerid.l, pdp->triggerid.v);
-
- if ((pdp->version == 1) && pdp->omcid.l)
- gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
- pdp->omcid.l, pdp->omcid.v);
-
- gtp_req(gsn, pdp->version, NULL, &packet, length, inetaddr, cbp);
-
- return 0;
-}
+ struct in_addr *inetaddr)
+{
+ union gtp_packet packet;
+ unsigned int length =
+ get_default_gtp(pdp->version, GTP_UPDATE_PDP_REQ, &packet);
+
+ if (pdp->version == 0)
+ gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
+ sizeof(pdp->qos_req0), pdp->qos_req0);
+
+ /* Include IMSI if updating with unknown teic_gn */
+ if ((pdp->version == 1) && (!pdp->teic_gn))
+ gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_IMSI,
+ sizeof(pdp->imsi), (uint8_t *) & pdp->imsi);
+
+ gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
+ gsn->restart_counter);
+
+ if (pdp->version == 0) {
+ gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI, pdp->fllu);
+ gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C, pdp->fllc);
+ }
+
+ if (pdp->version == 1) {
+ gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
+ pdp->teid_own);
+
+ if (!pdp->teic_confirmed)
+ gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
+ pdp->teic_own);
+ }
+ gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
+
+ /* TODO
+ gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_REF,
+ pdp->traceref);
+ gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_TRACE_TYPE,
+ pdp->tracetype); */
+
+ /* TODO if ggsn update message
+ gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
+ pdp->eua.l, pdp->eua.v);
+ */
+
+ gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
+ pdp->gsnlc.l, pdp->gsnlc.v);
+ gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
+ pdp->gsnlu.l, pdp->gsnlu.v);
+
+ if (pdp->version == 1)
+ gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
+ pdp->qos_req.l, pdp->qos_req.v);
+
+ if ((pdp->version == 1) && pdp->tft.l)
+ gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TFT,
+ pdp->tft.l, pdp->tft.v);
+
+ if ((pdp->version == 1) && pdp->triggerid.l)
+ gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_TRIGGER_ID,
+ pdp->triggerid.l, pdp->triggerid.v);
+
+ if ((pdp->version == 1) && pdp->omcid.l)
+ gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
+ pdp->omcid.l, pdp->omcid.v);
+
+ gtp_req(gsn, pdp->version, NULL, &packet, length, inetaddr, cbp);
+
+ return 0;
+}
/* Send Update PDP Context Response */
-int gtp_update_pdp_resp(struct gsn_t *gsn, int version,
- struct sockaddr_in *peer, int fd,
+int gtp_update_pdp_resp(struct gsn_t *gsn, int version,
+ struct sockaddr_in *peer, int fd,
void *pack, unsigned len,
- struct pdp_t *pdp, uint8_t cause) {
-
- union gtp_packet packet;
- unsigned int length = get_default_gtp(version, GTP_UPDATE_PDP_RSP, &packet);
-
- gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
-
- if (cause == GTPCAUSE_ACC_REQ) {
-
- if (version == 0)
- gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
- sizeof(pdp->qos_neg0), pdp->qos_neg0);
-
- gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
- gsn->restart_counter);
-
- if (version == 0) {
- gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
- pdp->fllu);
- gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
- pdp->fllc);
- }
-
- if (version == 1) {
- gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
- pdp->teid_own);
-
- if (!pdp->teic_confirmed)
- gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_C,
- pdp->teic_own);
- }
-
- /* TODO we use teid_own as charging ID address */
- gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
- pdp->teid_own);
-
- /* If ggsn
- gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
- pdp->eua.l, pdp->eua.v); */
-
- gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
- pdp->gsnlc.l, pdp->gsnlc.v);
- gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
- pdp->gsnlu.l, pdp->gsnlu.v);
-
- if (version == 1)
- gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
- pdp->qos_neg.l, pdp->qos_neg.v);
-
- /* TODO: Charging gateway address */
- }
-
- return gtp_resp(version, gsn, pdp, &packet, length, peer,
- fd, get_seq(pack), get_tid(pack));
-}
+ struct pdp_t *pdp, uint8_t cause)
+{
+
+ union gtp_packet packet;
+ unsigned int length =
+ get_default_gtp(version, GTP_UPDATE_PDP_RSP, &packet);
+
+ gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
+
+ if (cause == GTPCAUSE_ACC_REQ) {
+
+ if (version == 0)
+ gtpie_tv0(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE0,
+ sizeof(pdp->qos_neg0), pdp->qos_neg0);
+
+ gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_RECOVERY,
+ gsn->restart_counter);
+
+ if (version == 0) {
+ gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_DI,
+ pdp->fllu);
+ gtpie_tv2(&packet, &length, GTP_MAX, GTPIE_FL_C,
+ pdp->fllc);
+ }
+
+ if (version == 1) {
+ gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_TEI_DI,
+ pdp->teid_own);
+
+ if (!pdp->teic_confirmed)
+ gtpie_tv4(&packet, &length, GTP_MAX,
+ GTPIE_TEI_C, pdp->teic_own);
+ }
+
+ /* TODO we use teid_own as charging ID address */
+ gtpie_tv4(&packet, &length, GTP_MAX, GTPIE_CHARGING_ID,
+ pdp->teid_own);
+
+ /* If ggsn
+ gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_EUA,
+ pdp->eua.l, pdp->eua.v); */
+ gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
+ pdp->gsnlc.l, pdp->gsnlc.v);
+ gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_GSN_ADDR,
+ pdp->gsnlu.l, pdp->gsnlu.v);
+
+ if (version == 1)
+ gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_QOS_PROFILE,
+ pdp->qos_neg.l, pdp->qos_neg.v);
+
+ /* TODO: Charging gateway address */
+ }
+
+ return gtp_resp(version, gsn, pdp, &packet, length, peer,
+ fd, get_seq(pack), get_tid(pack));
+}
/* Handle Update PDP Context Request */
int gtp_update_pdp_ind(struct gsn_t *gsn, int version,
- struct sockaddr_in *peer, int fd,
- void *pack, unsigned len) {
- struct pdp_t *pdp;
- struct pdp_t pdp_backup;
- union gtpie_member* ie[GTPIE_SIZE];
- uint8_t recovery;
-
- uint16_t seq = get_seq(pack);
- int hlen = get_hlen(pack);
-
- uint64_t imsi;
- uint8_t nsapi;
-
- /* Is this a dublicate ? */
- if(!gtp_dublicate(gsn, version, peer, seq)) {
- return 0; /* We allready send of response once */
- }
-
-
- /* Decode information elements */
- if (gtpie_decaps(ie, version, pack+hlen, len-hlen)) {
- gsn->invalid++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Invalid message format");
- if (0 == version)
- return EOF;
- else
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
- NULL, GTPCAUSE_INVALID_MESSAGE);
- }
-
- /* Finding PDP: */
- /* For GTP0 we use the tunnel identifier to provide imsi and nsapi. */
- /* For GTP1 we must use imsi and nsapi if imsi is present. Otherwise */
- /* we have to use the tunnel endpoint identifier */
- if (version == 0) {
- imsi = ((union gtp_packet*)pack)->gtp0.h.tid & 0x0fffffffffffffffull;
- nsapi = (((union gtp_packet*)pack)->gtp0.h.tid & 0xf000000000000000ull) >> 60;
-
- /* Find the context in question */
- if (pdp_getimsi(&pdp, imsi, nsapi)) {
- gsn->err_unknownpdp++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Unknown PDP context");
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
- NULL, GTPCAUSE_NON_EXIST);
- }
- }
- else if (version == 1) {
- /* NSAPI (mandatory) */
- if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing mandatory information field");
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
- NULL, GTPCAUSE_MAN_IE_MISSING);
- }
-
- /* IMSI (conditional) */
- if (gtpie_gettv0(ie, GTPIE_IMSI, 0, &imsi, sizeof(imsi))) {
- /* Find the context in question */
- if (pdp_getgtp1(&pdp, get_tei(pack))) {
- gsn->err_unknownpdp++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Unknown PDP context");
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
- NULL, GTPCAUSE_NON_EXIST);
- }
- }
- else {
- /* Find the context in question */
- if (pdp_getimsi(&pdp, imsi, nsapi)) {
- gsn->err_unknownpdp++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Unknown PDP context");
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
- NULL, GTPCAUSE_NON_EXIST);
- }
- }
- }
- else {
- gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown version");
- return EOF;
- }
-
- /* Make a backup copy in case anything is wrong */
- memcpy(&pdp_backup, pdp, sizeof(pdp_backup));
-
- if (version == 0) {
- if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
- pdp->qos_req0, sizeof(pdp->qos_req0))) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing mandatory information field");
- memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
- pdp, GTPCAUSE_MAN_IE_MISSING);
- }
- }
-
- /* Recovery (optional) */
- if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
- if (gsn->cb_recovery) gsn->cb_recovery(peer, recovery);
- }
-
- if (version == 0) {
- if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing mandatory information field");
- memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
- GTPCAUSE_MAN_IE_MISSING);
- }
-
- if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing mandatory information field");
- memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
- GTPCAUSE_MAN_IE_MISSING);
- }
- }
-
-
- if (version == 1) {
- /* TEID (mandatory) */
- if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing mandatory information field");
- memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
- GTPCAUSE_MAN_IE_MISSING);
- }
-
- /* TEIC (conditional) */
- /* If TEIC is not included it means that we have allready received it */
- /* TODO: From 29.060 it is not clear if TEI_C MUST be included for */
- /* all updated contexts, or only for one of the linked contexts */
- gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn);
-
- /* NSAPI (mandatory) */
- if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing mandatory information field");
- memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
- GTPCAUSE_MAN_IE_MISSING);
- }
- }
-
- /* Trace reference (optional) */
- /* Trace type (optional) */
-
- /* End User Address (conditional) TODO: GGSN Initiated
- if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
- &pdp->eua.v, sizeof(pdp->eua.v))) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing mandatory information field");
- memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
- return gtp_update_pdp_resp(gsn, version, pdp,
- GTPCAUSE_MAN_IE_MISSING);
- } */
-
-
- /* SGSN address for signalling (mandatory) */
- /* It is weird that this is mandatory when TEIC is conditional */
- if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
- &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing mandatory information field");
- memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
- GTPCAUSE_MAN_IE_MISSING);
- }
-
- /* SGSN address for user traffic (mandatory) */
- if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
- &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing mandatory information field");
- memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
- GTPCAUSE_MAN_IE_MISSING);
- }
-
- if (version == 1) {
- /* QoS (mandatory) */
- if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
- &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing mandatory information field");
- memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
- GTPCAUSE_MAN_IE_MISSING);
- }
-
- /* TFT (conditional) */
- if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
- &pdp->tft.v, sizeof(pdp->tft.v))) {
- }
-
- /* OMC identity */
- }
-
- /* Confirm to peer that things were "successful" */
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
- GTPCAUSE_ACC_REQ);
-}
+ struct sockaddr_in *peer, int fd,
+ void *pack, unsigned len)
+{
+ struct pdp_t *pdp;
+ struct pdp_t pdp_backup;
+ union gtpie_member *ie[GTPIE_SIZE];
+ uint8_t recovery;
+
+ uint16_t seq = get_seq(pack);
+ int hlen = get_hlen(pack);
+
+ uint64_t imsi;
+ uint8_t nsapi;
+
+ /* Is this a dublicate ? */
+ if (!gtp_dublicate(gsn, version, peer, seq)) {
+ return 0; /* We allready send of response once */
+ }
+
+ /* Decode information elements */
+ if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
+ gsn->invalid++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
+ "Invalid message format");
+ if (0 == version)
+ return EOF;
+ else
+ return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
+ len, NULL,
+ GTPCAUSE_INVALID_MESSAGE);
+ }
+
+ /* Finding PDP: */
+ /* For GTP0 we use the tunnel identifier to provide imsi and nsapi. */
+ /* For GTP1 we must use imsi and nsapi if imsi is present. Otherwise */
+ /* we have to use the tunnel endpoint identifier */
+ if (version == 0) {
+ imsi =
+ ((union gtp_packet *)pack)->gtp0.
+ h.tid & 0x0fffffffffffffffull;
+ nsapi =
+ (((union gtp_packet *)pack)->gtp0.
+ h.tid & 0xf000000000000000ull) >> 60;
+
+ /* Find the context in question */
+ if (pdp_getimsi(&pdp, imsi, nsapi)) {
+ gsn->err_unknownpdp++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
+ len, "Unknown PDP context");
+ return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
+ len, NULL,
+ GTPCAUSE_NON_EXIST);
+ }
+ } else if (version == 1) {
+ /* NSAPI (mandatory) */
+ if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
+ len, "Missing mandatory information field");
+ return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
+ len, NULL,
+ GTPCAUSE_MAN_IE_MISSING);
+ }
+
+ /* IMSI (conditional) */
+ if (gtpie_gettv0(ie, GTPIE_IMSI, 0, &imsi, sizeof(imsi))) {
+ /* Find the context in question */
+ if (pdp_getgtp1(&pdp, get_tei(pack))) {
+ gsn->err_unknownpdp++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
+ pack, len, "Unknown PDP context");
+ return gtp_update_pdp_resp(gsn, version, peer,
+ fd, pack, len, NULL,
+ GTPCAUSE_NON_EXIST);
+ }
+ } else {
+ /* Find the context in question */
+ if (pdp_getimsi(&pdp, imsi, nsapi)) {
+ gsn->err_unknownpdp++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer,
+ pack, len, "Unknown PDP context");
+ return gtp_update_pdp_resp(gsn, version, peer,
+ fd, pack, len, NULL,
+ GTPCAUSE_NON_EXIST);
+ }
+ }
+ } else {
+ gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown version");
+ return EOF;
+ }
+
+ /* Make a backup copy in case anything is wrong */
+ memcpy(&pdp_backup, pdp, sizeof(pdp_backup));
+
+ if (version == 0) {
+ if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
+ pdp->qos_req0, sizeof(pdp->qos_req0))) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
+ len, "Missing mandatory information field");
+ memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
+ return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
+ len, pdp,
+ GTPCAUSE_MAN_IE_MISSING);
+ }
+ }
+
+ /* Recovery (optional) */
+ if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
+ if (gsn->cb_recovery)
+ gsn->cb_recovery(peer, recovery);
+ }
+
+ if (version == 0) {
+ if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
+ len, "Missing mandatory information field");
+ memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
+ return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
+ len, pdp,
+ GTPCAUSE_MAN_IE_MISSING);
+ }
+
+ if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
+ len, "Missing mandatory information field");
+ memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
+ return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
+ len, pdp,
+ GTPCAUSE_MAN_IE_MISSING);
+ }
+ }
+
+ if (version == 1) {
+ /* TEID (mandatory) */
+ if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
+ len, "Missing mandatory information field");
+ memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
+ return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
+ len, pdp,
+ GTPCAUSE_MAN_IE_MISSING);
+ }
+
+ /* TEIC (conditional) */
+ /* If TEIC is not included it means that we have allready received it */
+ /* TODO: From 29.060 it is not clear if TEI_C MUST be included for */
+ /* all updated contexts, or only for one of the linked contexts */
+ gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn);
+
+ /* NSAPI (mandatory) */
+ if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &pdp->nsapi)) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
+ len, "Missing mandatory information field");
+ memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
+ return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
+ len, pdp,
+ GTPCAUSE_MAN_IE_MISSING);
+ }
+ }
+
+ /* Trace reference (optional) */
+ /* Trace type (optional) */
+
+ /* End User Address (conditional) TODO: GGSN Initiated
+ if (gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
+ &pdp->eua.v, sizeof(pdp->eua.v))) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
+ "Missing mandatory information field");
+ memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
+ return gtp_update_pdp_resp(gsn, version, pdp,
+ GTPCAUSE_MAN_IE_MISSING);
+ } */
+
+ /* SGSN address for signalling (mandatory) */
+ /* It is weird that this is mandatory when TEIC is conditional */
+ if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
+ &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
+ "Missing mandatory information field");
+ memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
+ return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
+ pdp, GTPCAUSE_MAN_IE_MISSING);
+ }
+
+ /* SGSN address for user traffic (mandatory) */
+ if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
+ &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
+ "Missing mandatory information field");
+ memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
+ return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
+ pdp, GTPCAUSE_MAN_IE_MISSING);
+ }
+ if (version == 1) {
+ /* QoS (mandatory) */
+ if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
+ &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
+ len, "Missing mandatory information field");
+ memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
+ return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
+ len, pdp,
+ GTPCAUSE_MAN_IE_MISSING);
+ }
+
+ /* TFT (conditional) */
+ if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
+ &pdp->tft.v, sizeof(pdp->tft.v))) {
+ }
+
+ /* OMC identity */
+ }
+
+ /* Confirm to peer that things were "successful" */
+ return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
+ GTPCAUSE_ACC_REQ);
+}
/* Handle Update PDP Context Response */
int gtp_update_pdp_conf(struct gsn_t *gsn, int version,
- struct sockaddr_in *peer,
- void *pack, unsigned len) {
- struct pdp_t *pdp;
- union gtpie_member *ie[GTPIE_SIZE];
- uint8_t cause, recovery;
- void *cbp = NULL;
- uint8_t type = 0;
-
- /* Remove packet from queue */
- if (gtp_conf(gsn, 0, peer, pack, len, &type, &cbp)) return EOF;
-
- /* Find the context in question */
- if (pdp_getgtp0(&pdp, ntoh16(((union gtp_packet*)pack)->gtp0.h.flow))) {
- gsn->err_unknownpdp++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Unknown PDP context");
- if (gsn->cb_conf) gsn->cb_conf(type, cause, NULL, cbp);
- return EOF;
- }
-
- /* Register that we have received a valid teic from GGSN */
- pdp->teic_confirmed = 1;
-
- /* Decode information elements */
- if (gtpie_decaps(ie, 0, pack+GTP0_HEADER_SIZE, len-GTP0_HEADER_SIZE)) {
- gsn->invalid++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Invalid message format");
- if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
- /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
- pdp_freepdp(pdp); */
- return EOF;
- }
-
- /* Extract cause value (mandatory) */
- if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing mandatory information field");
- if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
- /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
- pdp_freepdp(pdp); */
- return EOF;
- }
-
- /* Extract recovery (optional) */
- if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
- if (gsn->cb_recovery) gsn->cb_recovery(peer, recovery);
- }
-
- /* Check all conditional information elements */
- if (GTPCAUSE_ACC_REQ != cause) {
- if (gsn->cb_conf) gsn->cb_conf(type, cause, pdp, cbp);
- /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
- pdp_freepdp(pdp); */
- return 0;
- }
- else {
- /* Check for missing conditionary information elements */
- if (!(gtpie_exist(ie, GTPIE_QOS_PROFILE0, 0) &&
- gtpie_exist(ie, GTPIE_REORDER, 0) &&
- gtpie_exist(ie, GTPIE_FL_DI, 0) &&
- gtpie_exist(ie, GTPIE_FL_C, 0) &&
- gtpie_exist(ie, GTPIE_CHARGING_ID, 0) &&
- gtpie_exist(ie, GTPIE_EUA, 0) &&
- gtpie_exist(ie, GTPIE_GSN_ADDR, 0) &&
- gtpie_exist(ie, GTPIE_GSN_ADDR, 1))) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing conditional information field");
- if (gsn->cb_conf) gsn->cb_conf(type, EOF, pdp, cbp);
- /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
- pdp_freepdp(pdp); */
- return EOF;
- }
-
- /* Update pdp with new values */
- gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
- pdp->qos_neg0, sizeof(pdp->qos_neg0));
- gtpie_gettv1(ie, GTPIE_REORDER, 0, &pdp->reorder);
- gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru);
- gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc);
- gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid);
- gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
- &pdp->eua.v, sizeof(pdp->eua.v));
- gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
- &pdp->gsnrc.v, sizeof(pdp->gsnrc.v));
- gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
- &pdp->gsnru.v, sizeof(pdp->gsnru.v));
-
- if (gsn->cb_conf) gsn->cb_conf(type, cause, pdp, cbp);
- return 0; /* Succes */
- }
-}
+ struct sockaddr_in *peer, void *pack, unsigned len)
+{
+ struct pdp_t *pdp;
+ union gtpie_member *ie[GTPIE_SIZE];
+ uint8_t cause, recovery;
+ void *cbp = NULL;
+ uint8_t type = 0;
+
+ /* Remove packet from queue */
+ if (gtp_conf(gsn, 0, peer, pack, len, &type, &cbp))
+ return EOF;
+
+ /* Find the context in question */
+ if (pdp_getgtp0(&pdp, ntoh16(((union gtp_packet *)pack)->gtp0.h.flow))) {
+ gsn->err_unknownpdp++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
+ "Unknown PDP context");
+ if (gsn->cb_conf)
+ gsn->cb_conf(type, cause, NULL, cbp);
+ return EOF;
+ }
+ /* Register that we have received a valid teic from GGSN */
+ pdp->teic_confirmed = 1;
+
+ /* Decode information elements */
+ if (gtpie_decaps
+ (ie, 0, pack + GTP0_HEADER_SIZE, len - GTP0_HEADER_SIZE)) {
+ gsn->invalid++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
+ "Invalid message format");
+ if (gsn->cb_conf)
+ gsn->cb_conf(type, EOF, pdp, cbp);
+ /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
+ pdp_freepdp(pdp); */
+ return EOF;
+ }
+
+ /* Extract cause value (mandatory) */
+ if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
+ "Missing mandatory information field");
+ if (gsn->cb_conf)
+ gsn->cb_conf(type, EOF, pdp, cbp);
+ /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
+ pdp_freepdp(pdp); */
+ return EOF;
+ }
+
+ /* Extract recovery (optional) */
+ if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
+ if (gsn->cb_recovery)
+ gsn->cb_recovery(peer, recovery);
+ }
+
+ /* Check all conditional information elements */
+ if (GTPCAUSE_ACC_REQ != cause) {
+ if (gsn->cb_conf)
+ gsn->cb_conf(type, cause, pdp, cbp);
+ /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
+ pdp_freepdp(pdp); */
+ return 0;
+ } else {
+ /* Check for missing conditionary information elements */
+ if (!(gtpie_exist(ie, GTPIE_QOS_PROFILE0, 0) &&
+ gtpie_exist(ie, GTPIE_REORDER, 0) &&
+ gtpie_exist(ie, GTPIE_FL_DI, 0) &&
+ gtpie_exist(ie, GTPIE_FL_C, 0) &&
+ gtpie_exist(ie, GTPIE_CHARGING_ID, 0) &&
+ gtpie_exist(ie, GTPIE_EUA, 0) &&
+ gtpie_exist(ie, GTPIE_GSN_ADDR, 0) &&
+ gtpie_exist(ie, GTPIE_GSN_ADDR, 1))) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
+ len,
+ "Missing conditional information field");
+ if (gsn->cb_conf)
+ gsn->cb_conf(type, EOF, pdp, cbp);
+ /* if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
+ pdp_freepdp(pdp); */
+ return EOF;
+ }
+
+ /* Update pdp with new values */
+ gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
+ pdp->qos_neg0, sizeof(pdp->qos_neg0));
+ gtpie_gettv1(ie, GTPIE_REORDER, 0, &pdp->reorder);
+ gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru);
+ gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc);
+ gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid);
+ gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
+ &pdp->eua.v, sizeof(pdp->eua.v));
+ gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
+ &pdp->gsnrc.v, sizeof(pdp->gsnrc.v));
+ gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
+ &pdp->gsnru.v, sizeof(pdp->gsnru.v));
+
+ if (gsn->cb_conf)
+ gsn->cb_conf(type, cause, pdp, cbp);
+ return 0; /* Succes */
+ }
+}
/* API: Send Delete PDP Context Request */
int gtp_delete_context_req(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
- int teardown) {
- union gtp_packet packet;
- unsigned int length = get_default_gtp(pdp->version, GTP_DELETE_PDP_REQ, &packet);
- struct in_addr addr;
- struct pdp_t *linked_pdp;
- struct pdp_t *secondary_pdp;
- int n;
- int count = 0;
-
- if (gsna2in_addr(&addr, &pdp->gsnrc)) {
- gsn->err_address++;
- gtp_err(LOG_ERR, __FILE__, __LINE__, "GSN address conversion failed");
- return EOF;
- }
-
- if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
- gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown linked PDP context");
- return EOF;
- }
-
- if (!teardown) {
- for (n=0; n< PDP_MAXNSAPI; n++)
- if (linked_pdp->secondary_tei[n]) count++;
- if (count <= 1) {
- gtp_err(LOG_ERR, __FILE__, __LINE__,
- "Must use teardown for last context");
- return EOF;
- }
- }
-
- if (pdp->version == 1) {
- if (teardown)
- gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_TEARDOWN,
- 0xff);
-
- gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI,
- pdp->nsapi);
- }
-
- gtp_req(gsn, pdp->version, pdp, &packet, length, &addr, cbp);
-
- if (teardown) { /* Remove all contexts */
- for (n=0; n< PDP_MAXNSAPI; n++) {
- if (linked_pdp->secondary_tei[n]) {
- if (pdp_getgtp1(&secondary_pdp, linked_pdp->secondary_tei[n])) {
- gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown secondary PDP context");
- return EOF;
- }
- if (linked_pdp != secondary_pdp) {
- if (gsn->cb_delete_context) gsn->cb_delete_context(secondary_pdp);
- pdp_freepdp(secondary_pdp);
- }
- }
- }
- if (gsn->cb_delete_context) gsn->cb_delete_context(linked_pdp);
- pdp_freepdp(linked_pdp);
- }
- else {
- if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
- if (pdp == linked_pdp) {
- linked_pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
- linked_pdp->nodata = 1;
- }
- else
- pdp_freepdp(pdp);
- }
-
- return 0;
+ int teardown)
+{
+ union gtp_packet packet;
+ unsigned int length =
+ get_default_gtp(pdp->version, GTP_DELETE_PDP_REQ, &packet);
+ struct in_addr addr;
+ struct pdp_t *linked_pdp;
+ struct pdp_t *secondary_pdp;
+ int n;
+ int count = 0;
+
+ if (gsna2in_addr(&addr, &pdp->gsnrc)) {
+ gsn->err_address++;
+ gtp_err(LOG_ERR, __FILE__, __LINE__,
+ "GSN address conversion failed");
+ return EOF;
+ }
+
+ if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
+ gtp_err(LOG_ERR, __FILE__, __LINE__,
+ "Unknown linked PDP context");
+ return EOF;
+ }
+
+ if (!teardown) {
+ for (n = 0; n < PDP_MAXNSAPI; n++)
+ if (linked_pdp->secondary_tei[n])
+ count++;
+ if (count <= 1) {
+ gtp_err(LOG_ERR, __FILE__, __LINE__,
+ "Must use teardown for last context");
+ return EOF;
+ }
+ }
+
+ if (pdp->version == 1) {
+ if (teardown)
+ gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_TEARDOWN,
+ 0xff);
+
+ gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_NSAPI, pdp->nsapi);
+ }
+
+ gtp_req(gsn, pdp->version, pdp, &packet, length, &addr, cbp);
+
+ if (teardown) { /* Remove all contexts */
+ for (n = 0; n < PDP_MAXNSAPI; n++) {
+ if (linked_pdp->secondary_tei[n]) {
+ if (pdp_getgtp1
+ (&secondary_pdp,
+ linked_pdp->secondary_tei[n])) {
+ gtp_err(LOG_ERR, __FILE__, __LINE__,
+ "Unknown secondary PDP context");
+ return EOF;
+ }
+ if (linked_pdp != secondary_pdp) {
+ if (gsn->cb_delete_context)
+ gsn->cb_delete_context
+ (secondary_pdp);
+ pdp_freepdp(secondary_pdp);
+ }
+ }
+ }
+ if (gsn->cb_delete_context)
+ gsn->cb_delete_context(linked_pdp);
+ pdp_freepdp(linked_pdp);
+ } else {
+ if (gsn->cb_delete_context)
+ gsn->cb_delete_context(pdp);
+ if (pdp == linked_pdp) {
+ linked_pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
+ linked_pdp->nodata = 1;
+ } else
+ pdp_freepdp(pdp);
+ }
+
+ return 0;
}
/* Send Delete PDP Context Response */
int gtp_delete_pdp_resp(struct gsn_t *gsn, int version,
struct sockaddr_in *peer, int fd,
- void *pack, unsigned len,
- struct pdp_t *pdp, struct pdp_t *linked_pdp,
+ void *pack, unsigned len,
+ struct pdp_t *pdp, struct pdp_t *linked_pdp,
uint8_t cause, int teardown)
{
- union gtp_packet packet;
- struct pdp_t *secondary_pdp;
- unsigned int length = get_default_gtp(version, GTP_DELETE_PDP_RSP, &packet);
- int n;
-
- gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
-
- gtp_resp(version, gsn, pdp, &packet, length, peer, fd,
- get_seq(pack), get_tid(pack));
-
- if (cause == GTPCAUSE_ACC_REQ) {
- if ((teardown) || (version == 0)) { /* Remove all contexts */
- for (n=0; n< PDP_MAXNSAPI; n++) {
- if (linked_pdp->secondary_tei[n]) {
- if (pdp_getgtp1(&secondary_pdp, linked_pdp->secondary_tei[n])) {
- gtp_err(LOG_ERR, __FILE__, __LINE__,
- "Unknown secondary PDP context");
- return EOF;
- }
- if (linked_pdp != secondary_pdp) {
- if (gsn->cb_delete_context) gsn->cb_delete_context(secondary_pdp);
- pdp_freepdp(secondary_pdp);
- }
- }
- }
- if (gsn->cb_delete_context) gsn->cb_delete_context(linked_pdp);
- pdp_freepdp(linked_pdp);
- }
- else { /* Remove only current context */
- if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
- if (pdp == linked_pdp) {
- linked_pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
- linked_pdp->nodata = 1;
- }
- else
- pdp_freepdp(pdp);
- }
- } /* if (cause == GTPCAUSE_ACC_REQ) */
-
- return 0;
+ union gtp_packet packet;
+ struct pdp_t *secondary_pdp;
+ unsigned int length =
+ get_default_gtp(version, GTP_DELETE_PDP_RSP, &packet);
+ int n;
+
+ gtpie_tv1(&packet, &length, GTP_MAX, GTPIE_CAUSE, cause);
+
+ gtp_resp(version, gsn, pdp, &packet, length, peer, fd,
+ get_seq(pack), get_tid(pack));
+
+ if (cause == GTPCAUSE_ACC_REQ) {
+ if ((teardown) || (version == 0)) { /* Remove all contexts */
+ for (n = 0; n < PDP_MAXNSAPI; n++) {
+ if (linked_pdp->secondary_tei[n]) {
+ if (pdp_getgtp1
+ (&secondary_pdp,
+ linked_pdp->secondary_tei[n])) {
+ gtp_err(LOG_ERR, __FILE__,
+ __LINE__,
+ "Unknown secondary PDP context");
+ return EOF;
+ }
+ if (linked_pdp != secondary_pdp) {
+ if (gsn->cb_delete_context)
+ gsn->cb_delete_context
+ (secondary_pdp);
+ pdp_freepdp(secondary_pdp);
+ }
+ }
+ }
+ if (gsn->cb_delete_context)
+ gsn->cb_delete_context(linked_pdp);
+ pdp_freepdp(linked_pdp);
+ } else { /* Remove only current context */
+ if (gsn->cb_delete_context)
+ gsn->cb_delete_context(pdp);
+ if (pdp == linked_pdp) {
+ linked_pdp->secondary_tei[pdp->nsapi & 0xf0] =
+ 0;
+ linked_pdp->nodata = 1;
+ } else
+ pdp_freepdp(pdp);
+ }
+ }
+ /* if (cause == GTPCAUSE_ACC_REQ) */
+ return 0;
}
/* Handle Delete PDP Context Request */
int gtp_delete_pdp_ind(struct gsn_t *gsn, int version,
struct sockaddr_in *peer, int fd,
- void *pack, unsigned len) {
- struct pdp_t *pdp = NULL;
- struct pdp_t *linked_pdp = NULL;
- union gtpie_member* ie[GTPIE_SIZE];
-
- uint16_t seq = get_seq(pack);
- int hlen = get_hlen(pack);
-
- uint8_t nsapi;
- uint8_t teardown = 0;
- int n;
- int count = 0;
-
- /* Is this a dublicate ? */
- if(!gtp_dublicate(gsn, version, peer, seq)) {
- return 0; /* We allready send off response once */
- }
-
- /* Find the linked context in question */
- if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
- gsn->err_unknownpdp++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Unknown PDP context");
- return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len, NULL, NULL,
- GTPCAUSE_NON_EXIST, teardown);
- }
-
- /* If version 0 this is also the secondary context */
- if (version == 0)
- pdp = linked_pdp;
-
- /* Decode information elements */
- if (gtpie_decaps(ie, version, pack+hlen, len-hlen)) {
- gsn->invalid++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Invalid message format");
- if (0 == version)
- return EOF;
- else
- return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len, NULL, NULL,
- GTPCAUSE_INVALID_MESSAGE, teardown);
- }
-
- if (version == 1) {
- /* NSAPI (mandatory) */
- if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing mandatory information field");
- return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len, NULL, NULL,
- GTPCAUSE_MAN_IE_MISSING, teardown);
- }
-
- /* Find the context in question */
- if (pdp_getgtp1(&pdp, linked_pdp->secondary_tei[nsapi & 0x0f])) {
- gsn->err_unknownpdp++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Unknown PDP context");
- return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len, NULL, NULL,
- GTPCAUSE_NON_EXIST, teardown);
- }
-
- /* Teardown (conditional) */
- gtpie_gettv1(ie, GTPIE_TEARDOWN, 0, &teardown);
-
- if (!teardown) {
- for (n=0; n< PDP_MAXNSAPI; n++)
- if (linked_pdp->secondary_tei[n]) count++;
- if (count <= 1) {
- return 0; /* 29.060 7.3.5 Ignore message */
- }
- }
- }
-
- return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
- pdp, linked_pdp, GTPCAUSE_ACC_REQ, teardown);
-}
+ void *pack, unsigned len)
+{
+ struct pdp_t *pdp = NULL;
+ struct pdp_t *linked_pdp = NULL;
+ union gtpie_member *ie[GTPIE_SIZE];
+ uint16_t seq = get_seq(pack);
+ int hlen = get_hlen(pack);
+
+ uint8_t nsapi;
+ uint8_t teardown = 0;
+ int n;
+ int count = 0;
+
+ /* Is this a dublicate ? */
+ if (!gtp_dublicate(gsn, version, peer, seq)) {
+ return 0; /* We allready send off response once */
+ }
+
+ /* Find the linked context in question */
+ if (pdp_getgtp1(&linked_pdp, get_tei(pack))) {
+ gsn->err_unknownpdp++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
+ "Unknown PDP context");
+ return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
+ NULL, NULL, GTPCAUSE_NON_EXIST,
+ teardown);
+ }
+
+ /* If version 0 this is also the secondary context */
+ if (version == 0)
+ pdp = linked_pdp;
+
+ /* Decode information elements */
+ if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
+ gsn->invalid++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
+ "Invalid message format");
+ if (0 == version)
+ return EOF;
+ else
+ return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
+ len, NULL, NULL,
+ GTPCAUSE_INVALID_MESSAGE,
+ teardown);
+ }
+
+ if (version == 1) {
+ /* NSAPI (mandatory) */
+ if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
+ len, "Missing mandatory information field");
+ return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
+ len, NULL, NULL,
+ GTPCAUSE_MAN_IE_MISSING,
+ teardown);
+ }
+
+ /* Find the context in question */
+ if (pdp_getgtp1(&pdp, linked_pdp->secondary_tei[nsapi & 0x0f])) {
+ gsn->err_unknownpdp++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
+ len, "Unknown PDP context");
+ return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
+ len, NULL, NULL,
+ GTPCAUSE_NON_EXIST,
+ teardown);
+ }
+
+ /* Teardown (conditional) */
+ gtpie_gettv1(ie, GTPIE_TEARDOWN, 0, &teardown);
+
+ if (!teardown) {
+ for (n = 0; n < PDP_MAXNSAPI; n++)
+ if (linked_pdp->secondary_tei[n])
+ count++;
+ if (count <= 1) {
+ return 0; /* 29.060 7.3.5 Ignore message */
+ }
+ }
+ }
+
+ return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
+ pdp, linked_pdp, GTPCAUSE_ACC_REQ, teardown);
+}
/* Handle Delete PDP Context Response */
int gtp_delete_pdp_conf(struct gsn_t *gsn, int version,
- struct sockaddr_in *peer,
- void *pack, unsigned len) {
- union gtpie_member *ie[GTPIE_SIZE];
- uint8_t cause;
- void *cbp = NULL;
- uint8_t type = 0;
- int hlen = get_hlen(pack);
-
- /* Remove packet from queue */
- if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp)) return EOF;
-
- /* Decode information elements */
- if (gtpie_decaps(ie, version, pack+hlen, len-hlen)) {
- gsn->invalid++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Invalid message format");
- if (gsn->cb_conf) gsn->cb_conf(type, EOF, NULL, cbp);
- return EOF;
- }
-
- /* Extract cause value (mandatory) */
- if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
- gsn->missing++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Missing mandatory information field");
- if (gsn->cb_conf) gsn->cb_conf(type, EOF, NULL, cbp);
- return EOF;
- }
-
- /* Check the cause value (again) */
- if ((GTPCAUSE_ACC_REQ != cause) && (GTPCAUSE_NON_EXIST != cause)) {
- gsn->err_cause++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Unexpected cause value received: %d", cause);
- if (gsn->cb_conf) gsn->cb_conf(type, cause, NULL, cbp);
- return EOF;
- }
-
- /* Callback function to notify application */
- if (gsn->cb_conf) gsn->cb_conf(type, cause, NULL, cbp);
-
- return 0;
+ struct sockaddr_in *peer, void *pack, unsigned len)
+{
+ union gtpie_member *ie[GTPIE_SIZE];
+ uint8_t cause;
+ void *cbp = NULL;
+ uint8_t type = 0;
+ int hlen = get_hlen(pack);
+
+ /* Remove packet from queue */
+ if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
+ return EOF;
+
+ /* Decode information elements */
+ if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
+ gsn->invalid++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
+ "Invalid message format");
+ if (gsn->cb_conf)
+ gsn->cb_conf(type, EOF, NULL, cbp);
+ return EOF;
+ }
+
+ /* Extract cause value (mandatory) */
+ if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
+ gsn->missing++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
+ "Missing mandatory information field");
+ if (gsn->cb_conf)
+ gsn->cb_conf(type, EOF, NULL, cbp);
+ return EOF;
+ }
+
+ /* Check the cause value (again) */
+ if ((GTPCAUSE_ACC_REQ != cause) && (GTPCAUSE_NON_EXIST != cause)) {
+ gsn->err_cause++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
+ "Unexpected cause value received: %d", cause);
+ if (gsn->cb_conf)
+ gsn->cb_conf(type, cause, NULL, cbp);
+ return EOF;
+ }
+
+ /* Callback function to notify application */
+ if (gsn->cb_conf)
+ gsn->cb_conf(type, cause, NULL, cbp);
+
+ return 0;
}
/* Send Error Indication (response to a GPDU message */
@@ -2485,89 +2624,90 @@ int gtp_error_ind_resp(struct gsn_t *gsn, int version,
struct sockaddr_in *peer, int fd,
void *pack, unsigned len)
{
- union gtp_packet packet;
- unsigned int length = get_default_gtp(version, GTP_ERROR, &packet);
-
- return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
- get_seq(pack), get_tid(pack));
+ union gtp_packet packet;
+ unsigned int length = get_default_gtp(version, GTP_ERROR, &packet);
+
+ return gtp_resp(version, gsn, NULL, &packet, length, peer, fd,
+ get_seq(pack), get_tid(pack));
}
/* Handle Error Indication */
int gtp_error_ind_conf(struct gsn_t *gsn, int version,
- struct sockaddr_in *peer,
- void *pack, unsigned len) {
- struct pdp_t *pdp;
-
- /* Find the context in question */
- if (pdp_tidget(&pdp, ((union gtp_packet*)pack)->gtp0.h.tid)) {
- gsn->err_unknownpdp++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Unknown PDP context");
- return EOF;
- }
-
- gsn->err_unknownpdp++; /* TODO: Change counter */
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Received Error Indication");
-
- if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
- pdp_freepdp(pdp);
- return 0;
+ struct sockaddr_in *peer, void *pack, unsigned len)
+{
+ struct pdp_t *pdp;
+
+ /* Find the context in question */
+ if (pdp_tidget(&pdp, ((union gtp_packet *)pack)->gtp0.h.tid)) {
+ gsn->err_unknownpdp++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
+ "Unknown PDP context");
+ return EOF;
+ }
+
+ gsn->err_unknownpdp++; /* TODO: Change counter */
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
+ "Received Error Indication");
+
+ if (gsn->cb_delete_context)
+ gsn->cb_delete_context(pdp);
+ pdp_freepdp(pdp);
+ return 0;
}
int gtp_gpdu_ind(struct gsn_t *gsn, int version,
- struct sockaddr_in *peer, int fd,
- void *pack, unsigned len) {
-
- int hlen = GTP1_HEADER_SIZE_SHORT;
-
- /* Need to include code to verify packet src and dest addresses */
- struct pdp_t *pdp;
-
- if (version == 0) {
- if (pdp_getgtp0(&pdp, ntoh16(((union gtp_packet*)pack)->gtp0.h.flow))) {
- gsn->err_unknownpdp++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Unknown PDP context");
- return gtp_error_ind_resp(gsn, version, peer, fd, pack, len);
- }
- hlen = GTP0_HEADER_SIZE;
- }
- else if (version == 1) {
- if (pdp_getgtp1(&pdp, ntoh32(((union gtp_packet*)pack)->gtp1l.h.tei))) {
- gsn->err_unknownpdp++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Unknown PDP context");
- return gtp_error_ind_resp(gsn, version, peer, fd, pack, len);
- }
-
- /* Is this a long or a short header ? */
- if (((union gtp_packet*)pack)->gtp1l.h.flags & 0x07)
- hlen = GTP1_HEADER_SIZE_LONG;
- else
- hlen = GTP1_HEADER_SIZE_SHORT;
- }
- else {
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Unknown version");
- }
-
- /* If the GPDU was not from the peer GSN tell him to delete context */
- if (memcmp(&peer->sin_addr, pdp->gsnru.v, pdp->gsnru.l)) { /* TODO Range? */
- gsn->err_unknownpdp++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
- "Unknown PDP context");
- return gtp_error_ind_resp(gsn, version, peer, fd, pack, len);
- }
-
- /* Callback function */
- if (gsn->cb_data_ind !=0)
- return gsn->cb_data_ind(pdp, pack+hlen, len-hlen);
-
- return 0;
-}
+ struct sockaddr_in *peer, int fd, void *pack, unsigned len)
+{
+ int hlen = GTP1_HEADER_SIZE_SHORT;
+
+ /* Need to include code to verify packet src and dest addresses */
+ struct pdp_t *pdp;
+
+ if (version == 0) {
+ if (pdp_getgtp0
+ (&pdp, ntoh16(((union gtp_packet *)pack)->gtp0.h.flow))) {
+ gsn->err_unknownpdp++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
+ len, "Unknown PDP context");
+ return gtp_error_ind_resp(gsn, version, peer, fd, pack,
+ len);
+ }
+ hlen = GTP0_HEADER_SIZE;
+ } else if (version == 1) {
+ if (pdp_getgtp1
+ (&pdp, ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei))) {
+ gsn->err_unknownpdp++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack,
+ len, "Unknown PDP context");
+ return gtp_error_ind_resp(gsn, version, peer, fd, pack,
+ len);
+ }
+
+ /* Is this a long or a short header ? */
+ if (((union gtp_packet *)pack)->gtp1l.h.flags & 0x07)
+ hlen = GTP1_HEADER_SIZE_LONG;
+ else
+ hlen = GTP1_HEADER_SIZE_SHORT;
+ } else {
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
+ "Unknown version");
+ }
+
+ /* If the GPDU was not from the peer GSN tell him to delete context */
+ if (memcmp(&peer->sin_addr, pdp->gsnru.v, pdp->gsnru.l)) { /* TODO Range? */
+ gsn->err_unknownpdp++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, peer, pack, len,
+ "Unknown PDP context");
+ return gtp_error_ind_resp(gsn, version, peer, fd, pack, len);
+ }
+ /* Callback function */
+ if (gsn->cb_data_ind != 0)
+ return gsn->cb_data_ind(pdp, pack + hlen, len - hlen);
+
+ return 0;
+}
/* Receives GTP packet and sends off for further processing
* Function will check the validity of the header. If the header
@@ -2576,505 +2716,548 @@ int gtp_gpdu_ind(struct gsn_t *gsn, int version,
* TODO: Need to decide on return values! */
int gtp_decaps0(struct gsn_t *gsn)
{
- unsigned char buffer[PACKET_MAX];
- struct sockaddr_in peer;
- size_t peerlen;
- int status;
- struct gtp0_header *pheader;
- int version = 0; /* GTP version should be determined from header!*/
- int fd = gsn->fd0;
-
- /* TODO: Need strategy of userspace buffering and blocking */
- /* Currently read is non-blocking and send is blocking. */
- /* This means that the program have to wait for busy send calls...*/
-
- while (1) { /* Loop until no more to read */
- if (fcntl(gsn->fd0, F_SETFL, O_NONBLOCK)) {
- gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
- return -1;
- }
- peerlen = sizeof(peer);
- if ((status =
- recvfrom(gsn->fd0, buffer, sizeof(buffer), 0,
- (struct sockaddr *) &peer, &peerlen)) < 0 ) {
- if (errno == EAGAIN) return 0;
- gsn->err_readfrom++;
- gtp_err(LOG_ERR, __FILE__, __LINE__, "recvfrom(fd0=%d, buffer=%lx, len=%d) failed: status = %d error = %s", gsn->fd0, (unsigned long) buffer, sizeof(buffer), status, status ? strerror(errno) : "No error");
- return -1;
- }
-
- /* Need at least 1 byte in order to check version */
- if (status < (1)) {
- gsn->empty++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
- "Discarding packet - too small");
- continue;
- }
-
- pheader = (struct gtp0_header *) (buffer);
-
- /* Version should be gtp0 (or earlier) */
- /* 09.60 is somewhat unclear on this issue. On gsn->fd0 we expect only */
- /* GTP 0 messages. If other version message is received we reply that we */
- /* only support version 0, implying that this is the only version */
- /* supported on this port */
- if (((pheader->flags & 0xe0) > 0x00)) {
- gsn->unsup++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
- "Unsupported GTP version");
- gtp_unsup_req(gsn, 0, &peer, gsn->fd0, buffer, status); /* 29.60: 11.1.1 */
- continue;
- }
-
- /* Check length of gtp0 packet */
- if (status < GTP0_HEADER_SIZE) {
- gsn->tooshort++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
- "GTP0 packet too short");
- continue; /* Silently discard 29.60: 11.1.2 */
- }
-
- /* Check packet length field versus length of packet */
- if (status != (ntoh16(pheader->length) + GTP0_HEADER_SIZE)) {
- gsn->tooshort++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
- "GTP packet length field does not match actual length");
- continue; /* Silently discard */
- }
-
- if ((gsn->mode == GTP_MODE_GGSN) &&
- ((pheader->type == GTP_CREATE_PDP_RSP) ||
- (pheader->type == GTP_UPDATE_PDP_RSP) ||
- (pheader->type == GTP_DELETE_PDP_RSP))) {
- gsn->unexpect++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
- "Unexpected GTP Signalling Message");
- continue; /* Silently discard 29.60: 11.1.4 */
- }
-
- if ((gsn->mode == GTP_MODE_SGSN) &&
- ((pheader->type == GTP_CREATE_PDP_REQ) ||
- (pheader->type == GTP_UPDATE_PDP_REQ) ||
- (pheader->type == GTP_DELETE_PDP_REQ))) {
- gsn->unexpect++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
- "Unexpected GTP Signalling Message");
- continue; /* Silently discard 29.60: 11.1.4 */
- }
-
- switch (pheader->type) {
- case GTP_ECHO_REQ:
- gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
- break;
- case GTP_ECHO_RSP:
- gtp_echo_conf(gsn, version, &peer, buffer, status);
- break;
- case GTP_NOT_SUPPORTED:
- gtp_unsup_ind(gsn, &peer, buffer, status);
- break;
- case GTP_CREATE_PDP_REQ:
- gtp_create_pdp_ind(gsn, version, &peer, fd, buffer, status);
- break;
- case GTP_CREATE_PDP_RSP:
- gtp_create_pdp_conf(gsn, version, &peer, buffer, status);
- break;
- case GTP_UPDATE_PDP_REQ:
- gtp_update_pdp_ind(gsn, version, &peer, fd, buffer, status);
- break;
- case GTP_UPDATE_PDP_RSP:
- gtp_update_pdp_conf(gsn, version, &peer, buffer, status);
- break;
- case GTP_DELETE_PDP_REQ:
- gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer, status);
- break;
- case GTP_DELETE_PDP_RSP:
- gtp_delete_pdp_conf(gsn, version, &peer, buffer, status);
- break;
- case GTP_ERROR:
- gtp_error_ind_conf(gsn, version, &peer, buffer, status);
- break;
- case GTP_GPDU:
- gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
- break;
- default:
- gsn->unknown++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
- "Unknown GTP message type received");
- break;
- }
- }
+ unsigned char buffer[PACKET_MAX];
+ struct sockaddr_in peer;
+ size_t peerlen;
+ int status;
+ struct gtp0_header *pheader;
+ int version = 0; /* GTP version should be determined from header! */
+ int fd = gsn->fd0;
+
+ /* TODO: Need strategy of userspace buffering and blocking */
+ /* Currently read is non-blocking and send is blocking. */
+ /* This means that the program have to wait for busy send calls... */
+
+ while (1) { /* Loop until no more to read */
+ if (fcntl(gsn->fd0, F_SETFL, O_NONBLOCK)) {
+ gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
+ return -1;
+ }
+ peerlen = sizeof(peer);
+ if ((status =
+ recvfrom(gsn->fd0, buffer, sizeof(buffer), 0,
+ (struct sockaddr *)&peer, &peerlen)) < 0) {
+ if (errno == EAGAIN)
+ return 0;
+ gsn->err_readfrom++;
+ gtp_err(LOG_ERR, __FILE__, __LINE__,
+ "recvfrom(fd0=%d, buffer=%lx, len=%d) failed: status = %d error = %s",
+ gsn->fd0, (unsigned long)buffer, sizeof(buffer),
+ status, status ? strerror(errno) : "No error");
+ return -1;
+ }
+
+ /* Need at least 1 byte in order to check version */
+ if (status < (1)) {
+ gsn->empty++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
+ status, "Discarding packet - too small");
+ continue;
+ }
+
+ pheader = (struct gtp0_header *)(buffer);
+
+ /* Version should be gtp0 (or earlier) */
+ /* 09.60 is somewhat unclear on this issue. On gsn->fd0 we expect only */
+ /* GTP 0 messages. If other version message is received we reply that we */
+ /* only support version 0, implying that this is the only version */
+ /* supported on this port */
+ if (((pheader->flags & 0xe0) > 0x00)) {
+ gsn->unsup++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
+ status, "Unsupported GTP version");
+ gtp_unsup_req(gsn, 0, &peer, gsn->fd0, buffer, status); /* 29.60: 11.1.1 */
+ continue;
+ }
+
+ /* Check length of gtp0 packet */
+ if (status < GTP0_HEADER_SIZE) {
+ gsn->tooshort++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
+ status, "GTP0 packet too short");
+ continue; /* Silently discard 29.60: 11.1.2 */
+ }
+
+ /* Check packet length field versus length of packet */
+ if (status != (ntoh16(pheader->length) + GTP0_HEADER_SIZE)) {
+ gsn->tooshort++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
+ status,
+ "GTP packet length field does not match actual length");
+ continue; /* Silently discard */
+ }
+
+ if ((gsn->mode == GTP_MODE_GGSN) &&
+ ((pheader->type == GTP_CREATE_PDP_RSP) ||
+ (pheader->type == GTP_UPDATE_PDP_RSP) ||
+ (pheader->type == GTP_DELETE_PDP_RSP))) {
+ gsn->unexpect++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
+ status,
+ "Unexpected GTP Signalling Message");
+ continue; /* Silently discard 29.60: 11.1.4 */
+ }
+
+ if ((gsn->mode == GTP_MODE_SGSN) &&
+ ((pheader->type == GTP_CREATE_PDP_REQ) ||
+ (pheader->type == GTP_UPDATE_PDP_REQ) ||
+ (pheader->type == GTP_DELETE_PDP_REQ))) {
+ gsn->unexpect++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
+ status,
+ "Unexpected GTP Signalling Message");
+ continue; /* Silently discard 29.60: 11.1.4 */
+ }
+
+ switch (pheader->type) {
+ case GTP_ECHO_REQ:
+ gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
+ break;
+ case GTP_ECHO_RSP:
+ gtp_echo_conf(gsn, version, &peer, buffer, status);
+ break;
+ case GTP_NOT_SUPPORTED:
+ gtp_unsup_ind(gsn, &peer, buffer, status);
+ break;
+ case GTP_CREATE_PDP_REQ:
+ gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
+ status);
+ break;
+ case GTP_CREATE_PDP_RSP:
+ gtp_create_pdp_conf(gsn, version, &peer, buffer,
+ status);
+ break;
+ case GTP_UPDATE_PDP_REQ:
+ gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
+ status);
+ break;
+ case GTP_UPDATE_PDP_RSP:
+ gtp_update_pdp_conf(gsn, version, &peer, buffer,
+ status);
+ break;
+ case GTP_DELETE_PDP_REQ:
+ gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
+ status);
+ break;
+ case GTP_DELETE_PDP_RSP:
+ gtp_delete_pdp_conf(gsn, version, &peer, buffer,
+ status);
+ break;
+ case GTP_ERROR:
+ gtp_error_ind_conf(gsn, version, &peer, buffer, status);
+ break;
+ case GTP_GPDU:
+ gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
+ break;
+ default:
+ gsn->unknown++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
+ status,
+ "Unknown GTP message type received");
+ break;
+ }
+ }
}
-
int gtp_decaps1c(struct gsn_t *gsn)
{
- unsigned char buffer[PACKET_MAX];
- struct sockaddr_in peer;
- size_t peerlen;
- int status;
- struct gtp1_header_short *pheader;
- int version = 1; /* TODO GTP version should be determined from header!*/
- int fd = gsn->fd1c;
-
- /* TODO: Need strategy of userspace buffering and blocking */
- /* Currently read is non-blocking and send is blocking. */
- /* This means that the program have to wait for busy send calls...*/
-
- while (1) { /* Loop until no more to read */
- if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
- gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
- return -1;
- }
- peerlen = sizeof(peer);
- if ((status =
- recvfrom(fd, buffer, sizeof(buffer), 0,
- (struct sockaddr *) &peer, &peerlen)) < 0 ) {
- if (errno == EAGAIN) return 0;
- gsn->err_readfrom++;
- gtp_err(LOG_ERR, __FILE__, __LINE__, "recvfrom(fd=%d, buffer=%lx, len=%d) failed: status = %d error = %s", fd, (unsigned long) buffer, sizeof(buffer), status, status ? strerror(errno) : "No error");
- return -1;
- }
-
- /* Need at least 1 byte in order to check version */
- if (status < (1)) {
- gsn->empty++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
- "Discarding packet - too small");
- continue;
- }
-
- pheader = (struct gtp1_header_short *) (buffer);
-
- /* Version must be no larger than GTP 1 */
- if (((pheader->flags & 0xe0) > 0x20)) {
- gsn->unsup++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
- "Unsupported GTP version");
- gtp_unsup_req(gsn, version, &peer, fd, buffer, status);
- /*29.60: 11.1.1*/
- continue;
- }
-
- /* Version must be at least GTP 1 */
- /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
- /* GTP 1 messages. If GTP 0 message is received we silently discard */
- /* the message */
- if (((pheader->flags & 0xe0) < 0x20)) {
- gsn->unsup++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
- "Unsupported GTP version");
- continue;
- }
-
- /* Check packet flag field */
- if (((pheader->flags & 0xf7) != 0x32)) {
- gsn->unsup++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
- "Unsupported packet flag");
- continue;
- }
-
- /* Check length of packet */
- if (status < GTP1_HEADER_SIZE_LONG) {
- gsn->tooshort++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
- "GTP packet too short");
- continue; /* Silently discard 29.60: 11.1.2 */
- }
-
- /* Check packet length field versus length of packet */
- if (status != (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
- gsn->tooshort++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
- "GTP packet length field does not match actual length");
- continue; /* Silently discard */
- }
-
- /* Check for extension headers */
- /* TODO: We really should cycle through the headers and determine */
- /* if any have the comprehension required flag set */
- if (((pheader->flags & 0x04) != 0x00)) {
- gsn->unsup++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
- "Unsupported extension header");
- gtp_extheader_req(gsn, version, &peer, fd, buffer, status);
-
- continue;
- }
-
- if ((gsn->mode == GTP_MODE_GGSN) &&
- ((pheader->type == GTP_CREATE_PDP_RSP) ||
- (pheader->type == GTP_UPDATE_PDP_RSP) ||
- (pheader->type == GTP_DELETE_PDP_RSP))) {
- gsn->unexpect++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
- "Unexpected GTP Signalling Message");
- continue; /* Silently discard 29.60: 11.1.4 */
- }
-
- if ((gsn->mode == GTP_MODE_SGSN) &&
- ((pheader->type == GTP_CREATE_PDP_REQ) ||
- (pheader->type == GTP_UPDATE_PDP_REQ) ||
- (pheader->type == GTP_DELETE_PDP_REQ))) {
- gsn->unexpect++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
- "Unexpected GTP Signalling Message");
- continue; /* Silently discard 29.60: 11.1.4 */
- }
-
- switch (pheader->type) {
- case GTP_ECHO_REQ:
- gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
- break;
- case GTP_ECHO_RSP:
- gtp_echo_conf(gsn, version, &peer, buffer, status);
- break;
- case GTP_NOT_SUPPORTED:
- gtp_unsup_ind(gsn, &peer, buffer, status);
- break;
- case GTP_SUPP_EXT_HEADER:
- gtp_extheader_ind(gsn, &peer, buffer, status);
- break;
- case GTP_CREATE_PDP_REQ:
- gtp_create_pdp_ind(gsn, version, &peer, fd, buffer, status);
- break;
- case GTP_CREATE_PDP_RSP:
- gtp_create_pdp_conf(gsn, version, &peer, buffer, status);
- break;
- case GTP_UPDATE_PDP_REQ:
- gtp_update_pdp_ind(gsn, version, &peer, fd, buffer, status);
- break;
- case GTP_UPDATE_PDP_RSP:
- gtp_update_pdp_conf(gsn, version, &peer, buffer, status);
- break;
- case GTP_DELETE_PDP_REQ:
- gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer, status);
- break;
- case GTP_DELETE_PDP_RSP:
- gtp_delete_pdp_conf(gsn, version, &peer, buffer, status);
- break;
- case GTP_ERROR:
- gtp_error_ind_conf(gsn, version, &peer, buffer, status);
- break;
- default:
- gsn->unknown++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
- "Unknown GTP message type received");
- break;
- }
- }
+ unsigned char buffer[PACKET_MAX];
+ struct sockaddr_in peer;
+ size_t peerlen;
+ int status;
+ struct gtp1_header_short *pheader;
+ int version = 1; /* TODO GTP version should be determined from header! */
+ int fd = gsn->fd1c;
+
+ /* TODO: Need strategy of userspace buffering and blocking */
+ /* Currently read is non-blocking and send is blocking. */
+ /* This means that the program have to wait for busy send calls... */
+
+ while (1) { /* Loop until no more to read */
+ if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
+ gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
+ return -1;
+ }
+ peerlen = sizeof(peer);
+ if ((status =
+ recvfrom(fd, buffer, sizeof(buffer), 0,
+ (struct sockaddr *)&peer, &peerlen)) < 0) {
+ if (errno == EAGAIN)
+ return 0;
+ gsn->err_readfrom++;
+ gtp_err(LOG_ERR, __FILE__, __LINE__,
+ "recvfrom(fd=%d, buffer=%lx, len=%d) failed: status = %d error = %s",
+ fd, (unsigned long)buffer, sizeof(buffer),
+ status, status ? strerror(errno) : "No error");
+ return -1;
+ }
+
+ /* Need at least 1 byte in order to check version */
+ if (status < (1)) {
+ gsn->empty++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
+ status, "Discarding packet - too small");
+ continue;
+ }
+
+ pheader = (struct gtp1_header_short *)(buffer);
+
+ /* Version must be no larger than GTP 1 */
+ if (((pheader->flags & 0xe0) > 0x20)) {
+ gsn->unsup++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
+ status, "Unsupported GTP version");
+ gtp_unsup_req(gsn, version, &peer, fd, buffer, status);
+ /*29.60: 11.1.1 */
+ continue;
+ }
+
+ /* Version must be at least GTP 1 */
+ /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
+ /* GTP 1 messages. If GTP 0 message is received we silently discard */
+ /* the message */
+ if (((pheader->flags & 0xe0) < 0x20)) {
+ gsn->unsup++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
+ status, "Unsupported GTP version");
+ continue;
+ }
+
+ /* Check packet flag field */
+ if (((pheader->flags & 0xf7) != 0x32)) {
+ gsn->unsup++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
+ status, "Unsupported packet flag");
+ continue;
+ }
+
+ /* Check length of packet */
+ if (status < GTP1_HEADER_SIZE_LONG) {
+ gsn->tooshort++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
+ status, "GTP packet too short");
+ continue; /* Silently discard 29.60: 11.1.2 */
+ }
+
+ /* Check packet length field versus length of packet */
+ if (status !=
+ (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
+ gsn->tooshort++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
+ status,
+ "GTP packet length field does not match actual length");
+ continue; /* Silently discard */
+ }
+
+ /* Check for extension headers */
+ /* TODO: We really should cycle through the headers and determine */
+ /* if any have the comprehension required flag set */
+ if (((pheader->flags & 0x04) != 0x00)) {
+ gsn->unsup++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
+ status, "Unsupported extension header");
+ gtp_extheader_req(gsn, version, &peer, fd, buffer,
+ status);
+
+ continue;
+ }
+
+ if ((gsn->mode == GTP_MODE_GGSN) &&
+ ((pheader->type == GTP_CREATE_PDP_RSP) ||
+ (pheader->type == GTP_UPDATE_PDP_RSP) ||
+ (pheader->type == GTP_DELETE_PDP_RSP))) {
+ gsn->unexpect++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
+ status,
+ "Unexpected GTP Signalling Message");
+ continue; /* Silently discard 29.60: 11.1.4 */
+ }
+
+ if ((gsn->mode == GTP_MODE_SGSN) &&
+ ((pheader->type == GTP_CREATE_PDP_REQ) ||
+ (pheader->type == GTP_UPDATE_PDP_REQ) ||
+ (pheader->type == GTP_DELETE_PDP_REQ))) {
+ gsn->unexpect++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
+ status,
+ "Unexpected GTP Signalling Message");
+ continue; /* Silently discard 29.60: 11.1.4 */
+ }
+
+ switch (pheader->type) {
+ case GTP_ECHO_REQ:
+ gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
+ break;
+ case GTP_ECHO_RSP:
+ gtp_echo_conf(gsn, version, &peer, buffer, status);
+ break;
+ case GTP_NOT_SUPPORTED:
+ gtp_unsup_ind(gsn, &peer, buffer, status);
+ break;
+ case GTP_SUPP_EXT_HEADER:
+ gtp_extheader_ind(gsn, &peer, buffer, status);
+ break;
+ case GTP_CREATE_PDP_REQ:
+ gtp_create_pdp_ind(gsn, version, &peer, fd, buffer,
+ status);
+ break;
+ case GTP_CREATE_PDP_RSP:
+ gtp_create_pdp_conf(gsn, version, &peer, buffer,
+ status);
+ break;
+ case GTP_UPDATE_PDP_REQ:
+ gtp_update_pdp_ind(gsn, version, &peer, fd, buffer,
+ status);
+ break;
+ case GTP_UPDATE_PDP_RSP:
+ gtp_update_pdp_conf(gsn, version, &peer, buffer,
+ status);
+ break;
+ case GTP_DELETE_PDP_REQ:
+ gtp_delete_pdp_ind(gsn, version, &peer, fd, buffer,
+ status);
+ break;
+ case GTP_DELETE_PDP_RSP:
+ gtp_delete_pdp_conf(gsn, version, &peer, buffer,
+ status);
+ break;
+ case GTP_ERROR:
+ gtp_error_ind_conf(gsn, version, &peer, buffer, status);
+ break;
+ default:
+ gsn->unknown++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
+ status,
+ "Unknown GTP message type received");
+ break;
+ }
+ }
}
int gtp_decaps1u(struct gsn_t *gsn)
{
- unsigned char buffer[PACKET_MAX];
- struct sockaddr_in peer;
- size_t peerlen;
- int status;
- struct gtp1_header_short *pheader;
- int version = 1; /* GTP version should be determined from header!*/
- int fd = gsn->fd1u;
-
- /* TODO: Need strategy of userspace buffering and blocking */
- /* Currently read is non-blocking and send is blocking. */
- /* This means that the program have to wait for busy send calls...*/
-
- while (1) { /* Loop until no more to read */
- if (fcntl(gsn->fd1u, F_SETFL, O_NONBLOCK)) {
- gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
- return -1;
- }
- peerlen = sizeof(peer);
- if ((status =
- recvfrom(gsn->fd1u, buffer, sizeof(buffer), 0,
- (struct sockaddr *) &peer, &peerlen)) < 0 ) {
- if (errno == EAGAIN) return 0;
- gsn->err_readfrom++;
- gtp_err(LOG_ERR, __FILE__, __LINE__, "recvfrom(fd1u=%d, buffer=%lx, len=%d) failed: status = %d error = %s", gsn->fd1u, (unsigned long) buffer, sizeof(buffer), status, status ? strerror(errno) : "No error");
- return -1;
- }
-
- /* Need at least 1 byte in order to check version */
- if (status < (1)) {
- gsn->empty++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
- "Discarding packet - too small");
- continue;
- }
-
- pheader = (struct gtp1_header_short *) (buffer);
-
- /* Version must be no larger than GTP 1 */
- if (((pheader->flags & 0xe0) > 0x20)) {
- gsn->unsup++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
- "Unsupported GTP version");
- gtp_unsup_req(gsn, 1, &peer, gsn->fd1c, buffer, status);/*29.60: 11.1.1*/
- continue;
- }
-
- /* Version must be at least GTP 1 */
- /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
- /* GTP 1 messages. If GTP 0 message is received we silently discard */
- /* the message */
- if (((pheader->flags & 0xe0) < 0x20)) {
- gsn->unsup++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
- "Unsupported GTP version");
- continue;
- }
-
- /* Check packet flag field (allow both with and without sequence number)*/
- if (((pheader->flags & 0xf5) != 0x30)) {
- gsn->unsup++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
- "Unsupported packet flag");
- continue;
- }
-
- /* Check length of packet */
- if (status < GTP1_HEADER_SIZE_SHORT) {
- gsn->tooshort++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
- "GTP packet too short");
- continue; /* Silently discard 29.60: 11.1.2 */
- }
-
- /* Check packet length field versus length of packet */
- if (status != (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
- gsn->tooshort++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
- "GTP packet length field does not match actual length");
- continue; /* Silently discard */
- }
-
- /* Check for extension headers */
- /* TODO: We really should cycle through the headers and determine */
- /* if any have the comprehension required flag set */
- if (((pheader->flags & 0x04) != 0x00)) {
- gsn->unsup++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
- "Unsupported extension header");
- gtp_extheader_req(gsn, version, &peer, fd, buffer, status);
-
- continue;
- }
-
- switch (pheader->type) {
- case GTP_ECHO_REQ:
- gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
- break;
- case GTP_ECHO_RSP:
- gtp_echo_conf(gsn, version, &peer, buffer, status);
- break;
- case GTP_SUPP_EXT_HEADER:
- gtp_extheader_ind(gsn, &peer, buffer, status);
- break;
- case GTP_ERROR:
- gtp_error_ind_conf(gsn, version, &peer, buffer, status);
- break;
- /* Supported header extensions */
- case GTP_GPDU:
- gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
- break;
- default:
- gsn->unknown++;
- gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer, status,
- "Unknown GTP message type received");
- break;
- }
- }
+ unsigned char buffer[PACKET_MAX];
+ struct sockaddr_in peer;
+ size_t peerlen;
+ int status;
+ struct gtp1_header_short *pheader;
+ int version = 1; /* GTP version should be determined from header! */
+ int fd = gsn->fd1u;
+
+ /* TODO: Need strategy of userspace buffering and blocking */
+ /* Currently read is non-blocking and send is blocking. */
+ /* This means that the program have to wait for busy send calls... */
+
+ while (1) { /* Loop until no more to read */
+ if (fcntl(gsn->fd1u, F_SETFL, O_NONBLOCK)) {
+ gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
+ return -1;
+ }
+ peerlen = sizeof(peer);
+ if ((status =
+ recvfrom(gsn->fd1u, buffer, sizeof(buffer), 0,
+ (struct sockaddr *)&peer, &peerlen)) < 0) {
+ if (errno == EAGAIN)
+ return 0;
+ gsn->err_readfrom++;
+ gtp_err(LOG_ERR, __FILE__, __LINE__,
+ "recvfrom(fd1u=%d, buffer=%lx, len=%d) failed: status = %d error = %s",
+ gsn->fd1u, (unsigned long)buffer,
+ sizeof(buffer), status,
+ status ? strerror(errno) : "No error");
+ return -1;
+ }
+
+ /* Need at least 1 byte in order to check version */
+ if (status < (1)) {
+ gsn->empty++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
+ status, "Discarding packet - too small");
+ continue;
+ }
+
+ pheader = (struct gtp1_header_short *)(buffer);
+
+ /* Version must be no larger than GTP 1 */
+ if (((pheader->flags & 0xe0) > 0x20)) {
+ gsn->unsup++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
+ status, "Unsupported GTP version");
+ gtp_unsup_req(gsn, 1, &peer, gsn->fd1c, buffer, status); /*29.60: 11.1.1 */
+ continue;
+ }
+
+ /* Version must be at least GTP 1 */
+ /* 29.060 is somewhat unclear on this issue. On gsn->fd1c we expect only */
+ /* GTP 1 messages. If GTP 0 message is received we silently discard */
+ /* the message */
+ if (((pheader->flags & 0xe0) < 0x20)) {
+ gsn->unsup++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
+ status, "Unsupported GTP version");
+ continue;
+ }
+
+ /* Check packet flag field (allow both with and without sequence number) */
+ if (((pheader->flags & 0xf5) != 0x30)) {
+ gsn->unsup++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
+ status, "Unsupported packet flag");
+ continue;
+ }
+
+ /* Check length of packet */
+ if (status < GTP1_HEADER_SIZE_SHORT) {
+ gsn->tooshort++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
+ status, "GTP packet too short");
+ continue; /* Silently discard 29.60: 11.1.2 */
+ }
+
+ /* Check packet length field versus length of packet */
+ if (status !=
+ (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) {
+ gsn->tooshort++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
+ status,
+ "GTP packet length field does not match actual length");
+ continue; /* Silently discard */
+ }
+
+ /* Check for extension headers */
+ /* TODO: We really should cycle through the headers and determine */
+ /* if any have the comprehension required flag set */
+ if (((pheader->flags & 0x04) != 0x00)) {
+ gsn->unsup++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
+ status, "Unsupported extension header");
+ gtp_extheader_req(gsn, version, &peer, fd, buffer,
+ status);
+
+ continue;
+ }
+
+ switch (pheader->type) {
+ case GTP_ECHO_REQ:
+ gtp_echo_ind(gsn, version, &peer, fd, buffer, status);
+ break;
+ case GTP_ECHO_RSP:
+ gtp_echo_conf(gsn, version, &peer, buffer, status);
+ break;
+ case GTP_SUPP_EXT_HEADER:
+ gtp_extheader_ind(gsn, &peer, buffer, status);
+ break;
+ case GTP_ERROR:
+ gtp_error_ind_conf(gsn, version, &peer, buffer, status);
+ break;
+ /* Supported header extensions */
+ case GTP_GPDU:
+ gtp_gpdu_ind(gsn, version, &peer, fd, buffer, status);
+ break;
+ default:
+ gsn->unknown++;
+ gtp_errpack(LOG_ERR, __FILE__, __LINE__, &peer, buffer,
+ status,
+ "Unknown GTP message type received");
+ break;
+ }
+ }
}
-int gtp_data_req(struct gsn_t *gsn, struct pdp_t* pdp,
- void *pack, unsigned len)
+int gtp_data_req(struct gsn_t *gsn, struct pdp_t *pdp, void *pack, unsigned len)
{
- union gtp_packet packet;
- struct sockaddr_in addr;
- int fd;
- int length;
+ union gtp_packet packet;
+ struct sockaddr_in addr;
+ int fd;
+ int length;
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
#if defined(__FreeBSD__) || defined(__APPLE__)
- addr.sin_len = sizeof(addr);
+ addr.sin_len = sizeof(addr);
#endif
- memcpy(&addr.sin_addr, pdp->gsnru.v,pdp->gsnru.l); /* TODO range check */
-
- if (pdp->version == 0) {
-
- length = GTP0_HEADER_SIZE+len;
- addr.sin_port = htons(GTP0_PORT);
- fd = gsn->fd0;
-
- get_default_gtp(0, GTP_GPDU, &packet);
- packet.gtp0.h.length = hton16(len);
- packet.gtp0.h.seq = hton16(pdp->gtpsntx++);
- packet.gtp0.h.flow = hton16(pdp->flru);
- packet.gtp0.h.tid = (pdp->imsi & 0x0fffffffffffffffull) + ((uint64_t)pdp->nsapi << 60);
-
- if (len > sizeof (union gtp_packet) - sizeof(struct gtp0_header)) {
- gsn->err_memcpy++;
- gtp_err(LOG_ERR, __FILE__, __LINE__,
- "Memcpy failed: %d > %d", len,
- sizeof (union gtp_packet) - sizeof(struct gtp0_header));
- return EOF;
- }
- memcpy(packet.gtp0.p, pack, len); /* TODO Should be avoided! */
- }
- else if (pdp->version == 1) {
-
- length = GTP1_HEADER_SIZE_LONG+len;
- addr.sin_port = htons(GTP1U_PORT);
- fd = gsn->fd1u;
-
- get_default_gtp(1, GTP_GPDU, &packet);
- packet.gtp1l.h.length = hton16(len-GTP1_HEADER_SIZE_SHORT+
- GTP1_HEADER_SIZE_LONG);
- packet.gtp1l.h.seq = hton16(pdp->gtpsntx++);
- packet.gtp1l.h.tei = hton32(pdp->teid_gn);
-
- if (len > sizeof (union gtp_packet) - sizeof(struct gtp1_header_long)) {
- gsn->err_memcpy++;
- gtp_err(LOG_ERR, __FILE__, __LINE__,
- "Memcpy failed: %d > %d", len,
- sizeof (union gtp_packet) - sizeof(struct gtp0_header));
- return EOF;
- }
- memcpy(packet.gtp1l.p, pack, len); /* TODO Should be avoided! */
- }
- else {
- gtp_err(LOG_ERR, __FILE__, __LINE__,
- "Unknown version");
- return EOF;
- }
-
- if (fcntl(fd, F_SETFL, 0)) {
- gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
- return -1;
- }
-
- if (sendto(fd, &packet, length, 0,
- (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- gsn->err_sendto++;
- gtp_err(LOG_ERR, __FILE__, __LINE__, "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s", fd, (unsigned long) &packet, GTP0_HEADER_SIZE+len, strerror(errno));
- return EOF;
- }
- return 0;
-}
+ memcpy(&addr.sin_addr, pdp->gsnru.v, pdp->gsnru.l); /* TODO range check */
+
+ if (pdp->version == 0) {
+
+ length = GTP0_HEADER_SIZE + len;
+ addr.sin_port = htons(GTP0_PORT);
+ fd = gsn->fd0;
+
+ get_default_gtp(0, GTP_GPDU, &packet);
+ packet.gtp0.h.length = hton16(len);
+ packet.gtp0.h.seq = hton16(pdp->gtpsntx++);
+ packet.gtp0.h.flow = hton16(pdp->flru);
+ packet.gtp0.h.tid =
+ (pdp->imsi & 0x0fffffffffffffffull) +
+ ((uint64_t) pdp->nsapi << 60);
+
+ if (len > sizeof(union gtp_packet) - sizeof(struct gtp0_header)) {
+ gsn->err_memcpy++;
+ gtp_err(LOG_ERR, __FILE__, __LINE__,
+ "Memcpy failed: %d > %d", len,
+ sizeof(union gtp_packet) -
+ sizeof(struct gtp0_header));
+ return EOF;
+ }
+ memcpy(packet.gtp0.p, pack, len); /* TODO Should be avoided! */
+ } else if (pdp->version == 1) {
+
+ length = GTP1_HEADER_SIZE_LONG + len;
+ addr.sin_port = htons(GTP1U_PORT);
+ fd = gsn->fd1u;
+
+ get_default_gtp(1, GTP_GPDU, &packet);
+ packet.gtp1l.h.length = hton16(len - GTP1_HEADER_SIZE_SHORT +
+ GTP1_HEADER_SIZE_LONG);
+ packet.gtp1l.h.seq = hton16(pdp->gtpsntx++);
+ packet.gtp1l.h.tei = hton32(pdp->teid_gn);
+
+ if (len >
+ sizeof(union gtp_packet) -
+ sizeof(struct gtp1_header_long)) {
+ gsn->err_memcpy++;
+ gtp_err(LOG_ERR, __FILE__, __LINE__,
+ "Memcpy failed: %d > %d", len,
+ sizeof(union gtp_packet) -
+ sizeof(struct gtp0_header));
+ return EOF;
+ }
+ memcpy(packet.gtp1l.p, pack, len); /* TODO Should be avoided! */
+ } else {
+ gtp_err(LOG_ERR, __FILE__, __LINE__, "Unknown version");
+ return EOF;
+ }
+ if (fcntl(fd, F_SETFL, 0)) {
+ gtp_err(LOG_ERR, __FILE__, __LINE__, "fnctl()");
+ return -1;
+ }
+
+ if (sendto(fd, &packet, length, 0,
+ (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ gsn->err_sendto++;
+ gtp_err(LOG_ERR, __FILE__, __LINE__,
+ "Sendto(fd=%d, msg=%lx, len=%d) failed: Error = %s", fd,
+ (unsigned long)&packet, GTP0_HEADER_SIZE + len,
+ strerror(errno));
+ return EOF;
+ }
+ return 0;
+}
/* ***********************************************************
* Conversion functions
*************************************************************/
-int char2ul_t(char* src, struct ul_t dst) {
- dst.l = strlen(src)+1;
- dst.v = malloc(dst.l);
- dst.v[0] = dst.l - 1;
- memcpy(&dst.v[1], src, dst.v[0]);
- return 0;
+int char2ul_t(char *src, struct ul_t dst)
+{
+ dst.l = strlen(src) + 1;
+ dst.v = malloc(dst.l);
+ dst.v[0] = dst.l - 1;
+ memcpy(&dst.v[1], src, dst.v[0]);
+ return 0;
}
/* ***********************************************************
@@ -3090,40 +3273,40 @@ int char2ul_t(char* src, struct ul_t dst) {
* port number.
*************************************************************/
-int ipv42eua(struct ul66_t *eua, struct in_addr *src) {
- eua->v[0] = 0xf1; /* IETF */
- eua->v[1] = 0x21; /* IPv4 */
- if (src) {
- eua->l = 6;
- memcpy(&eua->v[2], src, 4);
- }
- else
- {
- eua->l = 2;
- }
- return 0;
+int ipv42eua(struct ul66_t *eua, struct in_addr *src)
+{
+ eua->v[0] = 0xf1; /* IETF */
+ eua->v[1] = 0x21; /* IPv4 */
+ if (src) {
+ eua->l = 6;
+ memcpy(&eua->v[2], src, 4);
+ } else {
+ eua->l = 2;
+ }
+ return 0;
}
-int eua2ipv4(struct in_addr *dst, struct ul66_t *eua) {
- if ((eua->l != 6) ||
- (eua->v[0] != 0xf1) ||
- (eua->v[1] = 0x21))
- return -1; /* Not IPv4 address*/
- memcpy(dst, &eua->v[2], 4);
- return 0;
+int eua2ipv4(struct in_addr *dst, struct ul66_t *eua)
+{
+ if ((eua->l != 6) || (eua->v[0] != 0xf1) || (eua->v[1] = 0x21))
+ return -1; /* Not IPv4 address */
+ memcpy(dst, &eua->v[2], 4);
+ return 0;
}
-int gsna2in_addr(struct in_addr *dst, struct ul16_t *gsna) {
- memset(dst, 0, sizeof(struct in_addr));
- if (gsna->l != 4) return EOF; /* Return if not IPv4 */
- memcpy(dst, gsna->v, gsna->l);
- return 0;
+int gsna2in_addr(struct in_addr *dst, struct ul16_t *gsna)
+{
+ memset(dst, 0, sizeof(struct in_addr));
+ if (gsna->l != 4)
+ return EOF; /* Return if not IPv4 */
+ memcpy(dst, gsna->v, gsna->l);
+ return 0;
}
-int in_addr2gsna(struct ul16_t *gsna, struct in_addr *src) {
- memset(gsna, 0, sizeof(struct ul16_t));
- gsna->l = 4;
- memcpy(gsna->v, src, gsna->l);
- return 0;
+int in_addr2gsna(struct ul16_t *gsna, struct in_addr *src)
+{
+ memset(gsna, 0, sizeof(struct ul16_t));
+ gsna->l = 4;
+ memcpy(gsna->v, src, gsna->l);
+ return 0;
}
-
diff --git a/gtp/gtp.h b/gtp/gtp.h
index fb4cc3d..7417f08 100644
--- a/gtp/gtp.h
+++ b/gtp/gtp.h
@@ -12,7 +12,7 @@
#ifndef _GTP_H
#define _GTP_H
-#define GTP_DEBUG 0 /* Print debug information */
+#define GTP_DEBUG 0 /* Print debug information */
#define GTP_MODE_GGSN 1
#define GTP_MODE_SGSN 2
@@ -22,7 +22,7 @@
#define GTP1U_PORT 2152
#define PACKET_MAX 8196
-#define GTP_MAX 0xffff /* TODO: Choose right number */
+#define GTP_MAX 0xffff /* TODO: Choose right number */
#define GTP0_HEADER_SIZE 20
#define GTP1_HEADER_SIZE_SHORT 8
#define GTP1_HEADER_SIZE_LONG 12
@@ -34,107 +34,104 @@
#define NAMESIZE 1024
/* GTP version 1 extension header type definitions. */
-#define GTP_EXT_PDCP_PDU 0xC0 /* PDCP PDU Number */
+#define GTP_EXT_PDCP_PDU 0xC0 /* PDCP PDU Number */
/* GTP version 1 message type definitions. Also covers version 0 except *
* for anonymous PDP context which was superceded in version 1 */
/* 0 For future use. */
-#define GTP_ECHO_REQ 1 /* Echo Request */
-#define GTP_ECHO_RSP 2 /* Echo Response */
-#define GTP_NOT_SUPPORTED 3 /* Version Not Supported */
-#define GTP_ALIVE_REQ 4 /* Node Alive Request */
-#define GTP_ALIVE_RSP 5 /* Node Alive Response */
-#define GTP_REDIR_REQ 6 /* Redirection Request */
-#define GTP_REDIR_RSP 7 /* Redirection Response */
+#define GTP_ECHO_REQ 1 /* Echo Request */
+#define GTP_ECHO_RSP 2 /* Echo Response */
+#define GTP_NOT_SUPPORTED 3 /* Version Not Supported */
+#define GTP_ALIVE_REQ 4 /* Node Alive Request */
+#define GTP_ALIVE_RSP 5 /* Node Alive Response */
+#define GTP_REDIR_REQ 6 /* Redirection Request */
+#define GTP_REDIR_RSP 7 /* Redirection Response */
/* 8-15 For future use. */
-#define GTP_CREATE_PDP_REQ 16 /* Create PDP Context Request */
-#define GTP_CREATE_PDP_RSP 17 /* Create PDP Context Response */
-#define GTP_UPDATE_PDP_REQ 18 /* Update PDP Context Request */
-#define GTP_UPDATE_PDP_RSP 19 /* Update PDP Context Response */
-#define GTP_DELETE_PDP_REQ 20 /* Delete PDP Context Request */
-#define GTP_DELETE_PDP_RSP 21 /* Delete PDP Context Response */
-/* 22-25 For future use. */ /* In version GTP 1 anonomous PDP context */
-#define GTP_ERROR 26 /* Error Indication */
-#define GTP_PDU_NOT_REQ 27 /* PDU Notification Request */
-#define GTP_PDU_NOT_RSP 28 /* PDU Notification Response */
-#define GTP_PDU_NOT_REJ_REQ 29 /* PDU Notification Reject Request */
-#define GTP_PDU_NOT_REJ_RSP 30 /* PDU Notification Reject Response */
-#define GTP_SUPP_EXT_HEADER 31 /* Supported Extension Headers Notification */
-#define GTP_SND_ROUTE_REQ 32 /* Send Routeing Information for GPRS Request */
-#define GTP_SND_ROUTE_RSP 33 /* Send Routeing Information for GPRS Response */
-#define GTP_FAILURE_REQ 34 /* Failure Report Request */
-#define GTP_FAILURE_RSP 35 /* Failure Report Response */
-#define GTP_MS_PRESENT_REQ 36 /* Note MS GPRS Present Request */
-#define GTP_MS_PRESENT_RSP 37 /* Note MS GPRS Present Response */
-/* 38-47 For future use. */
-#define GTP_IDEN_REQ 48 /* Identification Request */
-#define GTP_IDEN_RSP 49 /* Identification Response */
-#define GTP_SGSN_CONTEXT_REQ 50 /* SGSN Context Request */
-#define GTP_SGSN_CONTEXT_RSP 51 /* SGSN Context Response */
-#define GTP_SGSN_CONTEXT_ACK 52 /* SGSN Context Acknowledge */
-#define GTP_FWD_RELOC_REQ 53 /* Forward Relocation Request */
-#define GTP_FWD_RELOC_RSP 54 /* Forward Relocation Response */
-#define GTP_FWD_RELOC_COMPL 55 /* Forward Relocation Complete */
-#define GTP_RELOC_CANCEL_REQ 56 /* Relocation Cancel Request */
-#define GTP_RELOC_CANCEL_RSP 57 /* Relocation Cancel Response */
-#define GTP_FWD_SRNS 58 /* Forward SRNS Context */
-#define GTP_FWD_RELOC_ACK 59 /* Forward Relocation Complete Acknowledge */
-#define GTP_FWD_SRNS_ACK 60 /* Forward SRNS Context Acknowledge */
+#define GTP_CREATE_PDP_REQ 16 /* Create PDP Context Request */
+#define GTP_CREATE_PDP_RSP 17 /* Create PDP Context Response */
+#define GTP_UPDATE_PDP_REQ 18 /* Update PDP Context Request */
+#define GTP_UPDATE_PDP_RSP 19 /* Update PDP Context Response */
+#define GTP_DELETE_PDP_REQ 20 /* Delete PDP Context Request */
+#define GTP_DELETE_PDP_RSP 21 /* Delete PDP Context Response */
+ /* 22-25 For future use. *//* In version GTP 1 anonomous PDP context */
+#define GTP_ERROR 26 /* Error Indication */
+#define GTP_PDU_NOT_REQ 27 /* PDU Notification Request */
+#define GTP_PDU_NOT_RSP 28 /* PDU Notification Response */
+#define GTP_PDU_NOT_REJ_REQ 29 /* PDU Notification Reject Request */
+#define GTP_PDU_NOT_REJ_RSP 30 /* PDU Notification Reject Response */
+#define GTP_SUPP_EXT_HEADER 31 /* Supported Extension Headers Notification */
+#define GTP_SND_ROUTE_REQ 32 /* Send Routeing Information for GPRS Request */
+#define GTP_SND_ROUTE_RSP 33 /* Send Routeing Information for GPRS Response */
+#define GTP_FAILURE_REQ 34 /* Failure Report Request */
+#define GTP_FAILURE_RSP 35 /* Failure Report Response */
+#define GTP_MS_PRESENT_REQ 36 /* Note MS GPRS Present Request */
+#define GTP_MS_PRESENT_RSP 37 /* Note MS GPRS Present Response */
+/* 38-47 For future use. */
+#define GTP_IDEN_REQ 48 /* Identification Request */
+#define GTP_IDEN_RSP 49 /* Identification Response */
+#define GTP_SGSN_CONTEXT_REQ 50 /* SGSN Context Request */
+#define GTP_SGSN_CONTEXT_RSP 51 /* SGSN Context Response */
+#define GTP_SGSN_CONTEXT_ACK 52 /* SGSN Context Acknowledge */
+#define GTP_FWD_RELOC_REQ 53 /* Forward Relocation Request */
+#define GTP_FWD_RELOC_RSP 54 /* Forward Relocation Response */
+#define GTP_FWD_RELOC_COMPL 55 /* Forward Relocation Complete */
+#define GTP_RELOC_CANCEL_REQ 56 /* Relocation Cancel Request */
+#define GTP_RELOC_CANCEL_RSP 57 /* Relocation Cancel Response */
+#define GTP_FWD_SRNS 58 /* Forward SRNS Context */
+#define GTP_FWD_RELOC_ACK 59 /* Forward Relocation Complete Acknowledge */
+#define GTP_FWD_SRNS_ACK 60 /* Forward SRNS Context Acknowledge */
/* 61-239 For future use. */
-#define GTP_DATA_TRAN_REQ 240 /* Data Record Transfer Request */
-#define GTP_DATA_TRAN_RSP 241 /* Data Record Transfer Response */
+#define GTP_DATA_TRAN_REQ 240 /* Data Record Transfer Request */
+#define GTP_DATA_TRAN_RSP 241 /* Data Record Transfer Response */
/* 242-254 For future use. */
-#define GTP_GPDU 255 /* G-PDU */
-
+#define GTP_GPDU 255 /* G-PDU */
/* GTP information element cause codes from 29.060 v3.9.0 7.7 */
/* */
-#define GTPCAUSE_REQ_IMSI 0 /* Request IMSI */
-#define GTPCAUSE_REQ_IMEI 1 /* Request IMEI */
-#define GTPCAUSE_REQ_IMSI_IMEI 2 /* Request IMSI and IMEI */
-#define GTPCAUSE_NO_ID_NEEDED 3 /* No identity needed */
-#define GTPCAUSE_MS_REFUSES_X 4 /* MS refuses */
-#define GTPCAUSE_MS_NOT_RESP_X 5 /* MS is not GPRS responding */
-#define GTPCAUSE_006 6 /* For future use 6-48 */
-#define GTPCAUSE_049 49 /* Cause values reserved for GPRS charging protocol use (See GTP' in GSM 12.15) 49-63 */
-#define GTPCAUSE_064 64 /* For future use 64-127 */
-#define GTPCAUSE_ACC_REQ 128 /* Request accepted */
-#define GTPCAUSE_129 129 /* For future use 129-176 */
-#define GTPCAUSE_177 177 /* Cause values reserved for GPRS charging protocol use (See GTP' In GSM 12.15) 177-191 */
-#define GTPCAUSE_NON_EXIST 192 /* Non-existent */
-#define GTPCAUSE_INVALID_MESSAGE 193 /* Invalid message format */
-#define GTPCAUSE_IMSI_NOT_KNOWN 194 /* IMSI not known */
-#define GTPCAUSE_MS_DETACHED 195 /* MS is GPRS detached */
-#define GTPCAUSE_MS_NOT_RESP 196 /* MS is not GPRS responding */
-#define GTPCAUSE_MS_REFUSES 197 /* MS refuses */
-#define GTPCAUSE_198 198 /* For future use */
-#define GTPCAUSE_NO_RESOURCES 199 /* No resources available */
-#define GTPCAUSE_NOT_SUPPORTED 200 /* Service not supported */
-#define GTPCAUSE_MAN_IE_INCORRECT 201 /* Mandatory IE incorrect */
-#define GTPCAUSE_MAN_IE_MISSING 202 /* Mandatory IE missing */
-#define GTPCAUSE_OPT_IE_INCORRECT 203 /* Optional IE incorrect */
-#define GTPCAUSE_SYS_FAIL 204 /* System failure */
-#define GTPCAUSE_ROAMING_REST 205 /* Roaming Restriction */
-#define GTPCAUSE_PTIMSI_MISMATCH 206 /* P-TMSI signature mismatch */
-#define GTPCAUSE_CONN_SUSP 207 /* GPRS connection suspended */
-#define GTPCAUSE_AUTH_FAIL 208 /* Authentication failure */
-#define GTPCAUSE_USER_AUTH_FAIL 209 /* User authentication failed */
-#define GTPCAUSE_CONTEXT_NOT_FOUND 210 /* Context not found */
-#define GTPCAUSE_ADDR_OCCUPIED 211 /* All dynamic PDP addresses are occupied */
-#define GTPCAUSE_NO_MEMORY 212 /* No memory is available */
-#define GTPCAUSE_RELOC_FAIL 213 /* Relocation failure */
-#define GTPCAUSE_UNKNOWN_MAN_EXTHEADER 214 /* Unknown mandatory extension header */
-#define GTPCAUSE_SEM_ERR_TFT 215 /* Semantic error in the TFT operation */
-#define GTPCAUSE_SYN_ERR_TFT 216 /* Syntactic error in the TFT operation */
-#define GTPCAUSE_SEM_ERR_FILTER 217 /* Semantic errors in packet filter(s) */
-#define GTPCAUSE_SYN_ERR_FILTER 218 /* Syntactic errors in packet filter(s) */
-#define GTPCAUSE_MISSING_APN 219 /* Missing or unknown APN*/
-#define GTPCAUSE_UNKNOWN_PDP 220 /* Unknown PDP address or PDP type */
-#define GTPCAUSE_221 221 /* For Future Use 221-240 */
-#define GTPCAUSE_241 241 /* Cause Values Reserved For Gprs Charging Protocol Use (See Gtp' In Gsm 12.15) 241-255 */
-
-
+#define GTPCAUSE_REQ_IMSI 0 /* Request IMSI */
+#define GTPCAUSE_REQ_IMEI 1 /* Request IMEI */
+#define GTPCAUSE_REQ_IMSI_IMEI 2 /* Request IMSI and IMEI */
+#define GTPCAUSE_NO_ID_NEEDED 3 /* No identity needed */
+#define GTPCAUSE_MS_REFUSES_X 4 /* MS refuses */
+#define GTPCAUSE_MS_NOT_RESP_X 5 /* MS is not GPRS responding */
+#define GTPCAUSE_006 6 /* For future use 6-48 */
+#define GTPCAUSE_049 49 /* Cause values reserved for GPRS charging protocol use (See GTP' in GSM 12.15) 49-63 */
+#define GTPCAUSE_064 64 /* For future use 64-127 */
+#define GTPCAUSE_ACC_REQ 128 /* Request accepted */
+#define GTPCAUSE_129 129 /* For future use 129-176 */
+#define GTPCAUSE_177 177 /* Cause values reserved for GPRS charging protocol use (See GTP' In GSM 12.15) 177-191 */
+#define GTPCAUSE_NON_EXIST 192 /* Non-existent */
+#define GTPCAUSE_INVALID_MESSAGE 193 /* Invalid message format */
+#define GTPCAUSE_IMSI_NOT_KNOWN 194 /* IMSI not known */
+#define GTPCAUSE_MS_DETACHED 195 /* MS is GPRS detached */
+#define GTPCAUSE_MS_NOT_RESP 196 /* MS is not GPRS responding */
+#define GTPCAUSE_MS_REFUSES 197 /* MS refuses */
+#define GTPCAUSE_198 198 /* For future use */
+#define GTPCAUSE_NO_RESOURCES 199 /* No resources available */
+#define GTPCAUSE_NOT_SUPPORTED 200 /* Service not supported */
+#define GTPCAUSE_MAN_IE_INCORRECT 201 /* Mandatory IE incorrect */
+#define GTPCAUSE_MAN_IE_MISSING 202 /* Mandatory IE missing */
+#define GTPCAUSE_OPT_IE_INCORRECT 203 /* Optional IE incorrect */
+#define GTPCAUSE_SYS_FAIL 204 /* System failure */
+#define GTPCAUSE_ROAMING_REST 205 /* Roaming Restriction */
+#define GTPCAUSE_PTIMSI_MISMATCH 206 /* P-TMSI signature mismatch */
+#define GTPCAUSE_CONN_SUSP 207 /* GPRS connection suspended */
+#define GTPCAUSE_AUTH_FAIL 208 /* Authentication failure */
+#define GTPCAUSE_USER_AUTH_FAIL 209 /* User authentication failed */
+#define GTPCAUSE_CONTEXT_NOT_FOUND 210 /* Context not found */
+#define GTPCAUSE_ADDR_OCCUPIED 211 /* All dynamic PDP addresses are occupied */
+#define GTPCAUSE_NO_MEMORY 212 /* No memory is available */
+#define GTPCAUSE_RELOC_FAIL 213 /* Relocation failure */
+#define GTPCAUSE_UNKNOWN_MAN_EXTHEADER 214 /* Unknown mandatory extension header */
+#define GTPCAUSE_SEM_ERR_TFT 215 /* Semantic error in the TFT operation */
+#define GTPCAUSE_SYN_ERR_TFT 216 /* Syntactic error in the TFT operation */
+#define GTPCAUSE_SEM_ERR_FILTER 217 /* Semantic errors in packet filter(s) */
+#define GTPCAUSE_SYN_ERR_FILTER 218 /* Syntactic errors in packet filter(s) */
+#define GTPCAUSE_MISSING_APN 219 /* Missing or unknown APN */
+#define GTPCAUSE_UNKNOWN_PDP 220 /* Unknown PDP address or PDP type */
+#define GTPCAUSE_221 221 /* For Future Use 221-240 */
+#define GTPCAUSE_241 241 /* Cause Values Reserved For Gprs Charging Protocol Use (See Gtp' In Gsm 12.15) 241-255 */
/* GTP 0 header.
* Explanation to some of the fields:
@@ -147,75 +144,72 @@
* Tunnel ID is IMSI+NSAPI. Unique identifier of PDP context. Is somewhat
* redundant because the header also includes flow. */
-struct gtp0_header { /* Descriptions from 3GPP 09.60 */
- uint8_t flags; /* 01 bitfield, with typical values */
- /* 000..... Version: 1 (0) */
- /* ...1111. Spare (7) */
- /* .......0 SNDCP N-PDU Number flag (0) */
- uint8_t type; /* 02 Message type. T-PDU = 0xff */
- uint16_t length; /* 03 Length (of G-PDU excluding header) */
- uint16_t seq; /* 05 Sequence Number */
- uint16_t flow; /* 07 Flow Label ( = 0 for signalling) */
- uint8_t number; /* 09 SNDCP N-PDU LCC Number ( 0 = 0xff) */
- uint8_t spare1; /* 10 Spare */
- uint8_t spare2; /* 11 Spare */
- uint8_t spare3; /* 12 Spare */
- uint64_t tid; /* 13 Tunnel ID */
-}; /* 20 */
-
-struct gtp1_header_short { /* Descriptions from 3GPP 29060 */
- uint8_t flags; /* 01 bitfield, with typical values */
- /* 001..... Version: 1 */
- /* ...1.... Protocol Type: GTP=1, GTP'=0 */
- /* ....0... Spare = 0 */
- /* .....0.. Extension header flag: 0 */
- /* ......0. Sequence number flag: 0 */
- /* .......0 PN: N-PDU Number flag */
- uint8_t type; /* 02 Message type. T-PDU = 0xff */
- uint16_t length; /* 03 Length (of IP packet or signalling) */
- uint32_t tei; /* 05 - 08 Tunnel Endpoint ID */
+struct gtp0_header { /* Descriptions from 3GPP 09.60 */
+ uint8_t flags; /* 01 bitfield, with typical values */
+ /* 000..... Version: 1 (0) */
+ /* ...1111. Spare (7) */
+ /* .......0 SNDCP N-PDU Number flag (0) */
+ uint8_t type; /* 02 Message type. T-PDU = 0xff */
+ uint16_t length; /* 03 Length (of G-PDU excluding header) */
+ uint16_t seq; /* 05 Sequence Number */
+ uint16_t flow; /* 07 Flow Label ( = 0 for signalling) */
+ uint8_t number; /* 09 SNDCP N-PDU LCC Number ( 0 = 0xff) */
+ uint8_t spare1; /* 10 Spare */
+ uint8_t spare2; /* 11 Spare */
+ uint8_t spare3; /* 12 Spare */
+ uint64_t tid; /* 13 Tunnel ID */
+}; /* 20 */
+
+struct gtp1_header_short { /* Descriptions from 3GPP 29060 */
+ uint8_t flags; /* 01 bitfield, with typical values */
+ /* 001..... Version: 1 */
+ /* ...1.... Protocol Type: GTP=1, GTP'=0 */
+ /* ....0... Spare = 0 */
+ /* .....0.. Extension header flag: 0 */
+ /* ......0. Sequence number flag: 0 */
+ /* .......0 PN: N-PDU Number flag */
+ uint8_t type; /* 02 Message type. T-PDU = 0xff */
+ uint16_t length; /* 03 Length (of IP packet or signalling) */
+ uint32_t tei; /* 05 - 08 Tunnel Endpoint ID */
};
-struct gtp1_header_long { /* Descriptions from 3GPP 29060 */
- uint8_t flags; /* 01 bitfield, with typical values */
- /* 001..... Version: 1 */
- /* ...1.... Protocol Type: GTP=1, GTP'=0 */
- /* ....0... Spare = 0 */
- /* .....0.. Extension header flag: 0 */
- /* ......1. Sequence number flag: 1 */
- /* .......0 PN: N-PDU Number flag */
- uint8_t type; /* 02 Message type. T-PDU = 0xff */
- uint16_t length; /* 03 Length (of IP packet or signalling) */
- uint32_t tei; /* 05 Tunnel Endpoint ID */
- uint16_t seq; /* 10 Sequence Number */
- uint8_t npdu; /* 11 N-PDU Number */
- uint8_t next; /* 12 Next extension header type. Empty = 0 */
+struct gtp1_header_long { /* Descriptions from 3GPP 29060 */
+ uint8_t flags; /* 01 bitfield, with typical values */
+ /* 001..... Version: 1 */
+ /* ...1.... Protocol Type: GTP=1, GTP'=0 */
+ /* ....0... Spare = 0 */
+ /* .....0.. Extension header flag: 0 */
+ /* ......1. Sequence number flag: 1 */
+ /* .......0 PN: N-PDU Number flag */
+ uint8_t type; /* 02 Message type. T-PDU = 0xff */
+ uint16_t length; /* 03 Length (of IP packet or signalling) */
+ uint32_t tei; /* 05 Tunnel Endpoint ID */
+ uint16_t seq; /* 10 Sequence Number */
+ uint8_t npdu; /* 11 N-PDU Number */
+ uint8_t next; /* 12 Next extension header type. Empty = 0 */
};
struct gtp0_packet {
- struct gtp0_header h;
- uint8_t p[GTP_MAX];
-} __attribute__((packed));
+ struct gtp0_header h;
+ uint8_t p[GTP_MAX];
+} __attribute__ ((packed));
struct gtp1_packet_short {
- struct gtp1_header_short h;
- uint8_t p[GTP_MAX];
-} __attribute__((packed));
+ struct gtp1_header_short h;
+ uint8_t p[GTP_MAX];
+} __attribute__ ((packed));
struct gtp1_packet_long {
- struct gtp1_header_long h;
- uint8_t p[GTP_MAX];
-} __attribute__((packed));
+ struct gtp1_header_long h;
+ uint8_t p[GTP_MAX];
+} __attribute__ ((packed));
union gtp_packet {
- uint8_t flags;
- struct gtp0_packet gtp0;
- struct gtp1_packet_short gtp1s;
- struct gtp1_packet_long gtp1l;
-} __attribute__((packed));
-
-
-
+ uint8_t flags;
+ struct gtp0_packet gtp0;
+ struct gtp1_packet_short gtp1s;
+ struct gtp1_packet_long gtp1l;
+} __attribute__ ((packed));
/* ***********************************************************
* Information storage for each gsn instance
@@ -233,64 +227,63 @@ union gtp_packet {
*************************************************************/
struct gsn_t {
- /* Parameters related to the network interface */
-
- int fd0; /* GTP0 file descriptor */
- int fd1c; /* GTP1 control plane file descriptor */
- int fd1u; /* GTP0 user plane file descriptor */
- int mode; /* Mode of operation: GGSN or SGSN */
- struct in_addr gsnc; /* IP address of this gsn for signalling */
- struct in_addr gsnu; /* IP address of this gsn for user traffic */
-
- /* Parameters related to signalling messages */
- uint16_t seq_next; /* Next sequence number to use */
- int seq_first; /* First packet in queue (oldest timeout) */
- int seq_last; /* Last packet in queue (youngest timeout) */
-
- unsigned char restart_counter; /* Increment on restart. Stored on disk */
- char *statedir; /* Disk location for permanent storage */
-
- struct queue_t *queue_req; /* Request queue */
- struct queue_t *queue_resp; /* Response queue */
-
- /* Call back functions */
- int (*cb_delete_context) (struct pdp_t*);
- int (*cb_create_context_ind) (struct pdp_t*);
- int (*cb_unsup_ind) (struct sockaddr_in *peer);
- int (*cb_extheader_ind) (struct sockaddr_in *peer);
- int (*cb_conf) (int type, int cause, struct pdp_t *pdp, void* cbp);
- int (*cb_data_ind) (struct pdp_t* pdp, void* pack, unsigned len);
- int (*cb_recovery) (struct sockaddr_in *peer, uint8_t recovery);
-
- /* Counters */
-
- uint64_t err_socket; /* Number of socket errors */
- uint64_t err_readfrom; /* Number of readfrom errors */
- uint64_t err_sendto; /* Number of sendto errors */
- uint64_t err_memcpy; /* Number of memcpy */
- uint64_t err_queuefull; /* Number of times queue was full */
- uint64_t err_seq; /* Number of seq out of range */
- uint64_t err_address; /* GSN address conversion failed */
- uint64_t err_unknownpdp; /* GSN address conversion failed */
- uint64_t err_unknowntid; /* Application supplied unknown imsi+nsapi */
- uint64_t err_cause; /* Unexpected cause value received */
- uint64_t err_outofpdp; /* Out of storage for PDP contexts */
-
- uint64_t empty; /* Number of empty packets */
- uint64_t unsup; /* Number of unsupported version 29.60 11.1.1 */
- uint64_t tooshort; /* Number of too short headers 29.60 11.1.2 */
- uint64_t unknown; /* Number of unknown messages 29.60 11.1.3 */
- uint64_t unexpect; /* Number of unexpected messages 29.60 11.1.4 */
- uint64_t dublicate; /* Number of dublicate or unsolicited replies */
- uint64_t missing; /* Number of missing information field messages */
- uint64_t incorrect; /* Number of incorrect information field messages */
- uint64_t invalid; /* Number of invalid message format messages */
+ /* Parameters related to the network interface */
+
+ int fd0; /* GTP0 file descriptor */
+ int fd1c; /* GTP1 control plane file descriptor */
+ int fd1u; /* GTP0 user plane file descriptor */
+ int mode; /* Mode of operation: GGSN or SGSN */
+ struct in_addr gsnc; /* IP address of this gsn for signalling */
+ struct in_addr gsnu; /* IP address of this gsn for user traffic */
+
+ /* Parameters related to signalling messages */
+ uint16_t seq_next; /* Next sequence number to use */
+ int seq_first; /* First packet in queue (oldest timeout) */
+ int seq_last; /* Last packet in queue (youngest timeout) */
+
+ unsigned char restart_counter; /* Increment on restart. Stored on disk */
+ char *statedir; /* Disk location for permanent storage */
+
+ struct queue_t *queue_req; /* Request queue */
+ struct queue_t *queue_resp; /* Response queue */
+
+ /* Call back functions */
+ int (*cb_delete_context) (struct pdp_t *);
+ int (*cb_create_context_ind) (struct pdp_t *);
+ int (*cb_unsup_ind) (struct sockaddr_in * peer);
+ int (*cb_extheader_ind) (struct sockaddr_in * peer);
+ int (*cb_conf) (int type, int cause, struct pdp_t * pdp, void *cbp);
+ int (*cb_data_ind) (struct pdp_t * pdp, void *pack, unsigned len);
+ int (*cb_recovery) (struct sockaddr_in * peer, uint8_t recovery);
+
+ /* Counters */
+
+ uint64_t err_socket; /* Number of socket errors */
+ uint64_t err_readfrom; /* Number of readfrom errors */
+ uint64_t err_sendto; /* Number of sendto errors */
+ uint64_t err_memcpy; /* Number of memcpy */
+ uint64_t err_queuefull; /* Number of times queue was full */
+ uint64_t err_seq; /* Number of seq out of range */
+ uint64_t err_address; /* GSN address conversion failed */
+ uint64_t err_unknownpdp; /* GSN address conversion failed */
+ uint64_t err_unknowntid; /* Application supplied unknown imsi+nsapi */
+ uint64_t err_cause; /* Unexpected cause value received */
+ uint64_t err_outofpdp; /* Out of storage for PDP contexts */
+
+ uint64_t empty; /* Number of empty packets */
+ uint64_t unsup; /* Number of unsupported version 29.60 11.1.1 */
+ uint64_t tooshort; /* Number of too short headers 29.60 11.1.2 */
+ uint64_t unknown; /* Number of unknown messages 29.60 11.1.3 */
+ uint64_t unexpect; /* Number of unexpected messages 29.60 11.1.4 */
+ uint64_t dublicate; /* Number of dublicate or unsolicited replies */
+ uint64_t missing; /* Number of missing information field messages */
+ uint64_t incorrect; /* Number of incorrect information field messages */
+ uint64_t invalid; /* Number of invalid message format messages */
};
-
/* External API functions */
-extern const char* gtp_version();
+extern const char *gtp_version();
extern int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
int mode);
@@ -300,27 +293,29 @@ extern int gtp_newpdp(struct gsn_t *gsn, struct pdp_t **pdp,
uint64_t imsi, uint8_t nsapi);
extern int gtp_freepdp(struct gsn_t *gsn, struct pdp_t *pdp);
-extern int gtp_create_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
+extern int gtp_create_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
void *cbp);
extern int gtp_set_cb_create_context_ind(struct gsn_t *gsn,
- int (*cb_create_context_ind) (struct pdp_t* pdp));
+ int (*cb_create_context_ind) (struct
+ pdp_t *
+ pdp));
-extern int gtp_create_context_resp(struct gsn_t *gsn, struct pdp_t *pdp,
+extern int gtp_create_context_resp(struct gsn_t *gsn, struct pdp_t *pdp,
int cause);
-extern int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp,
- void *cbp, struct in_addr* inetaddr);
+extern int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp,
+ void *cbp, struct in_addr *inetaddr);
-extern int gtp_delete_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
+extern int gtp_delete_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
void *cbp, int teardown);
extern int gtp_data_req(struct gsn_t *gsn, struct pdp_t *pdp,
void *pack, unsigned len);
extern int gtp_set_cb_data_ind(struct gsn_t *gsn,
- int (*cb_data_ind) (struct pdp_t* pdp, void* pack, unsigned len));
-
+ int (*cb_data_ind) (struct pdp_t * pdp,
+ void *pack, unsigned len));
extern int gtp_fd(struct gsn_t *gsn);
extern int gtp_decaps0(struct gsn_t *gsn);
@@ -329,45 +324,46 @@ extern int gtp_decaps1u(struct gsn_t *gsn);
extern int gtp_retrans(struct gsn_t *gsn);
extern int gtp_retranstimeout(struct gsn_t *gsn, struct timeval *timeout);
-extern int gtp_set_cb_delete_context(struct gsn_t *gsn,
- int (*cb_delete_context) (struct pdp_t* pdp));
+extern int gtp_set_cb_delete_context(struct gsn_t *gsn,
+ int (*cb_delete_context) (struct pdp_t *
+ pdp));
/*extern int gtp_set_cb_create_context(struct gsn_t *gsn,
int (*cb_create_context) (struct pdp_t* pdp)); */
extern int gtp_set_cb_unsup_ind(struct gsn_t *gsn,
- int (*cb) (struct sockaddr_in *peer));
+ int (*cb) (struct sockaddr_in * peer));
extern int gtp_set_cb_extheader_ind(struct gsn_t *gsn,
- int (*cb) (struct sockaddr_in *peer));
-
+ int (*cb) (struct sockaddr_in * peer));
extern int gtp_set_cb_conf(struct gsn_t *gsn,
- int (*cb) (int type, int cause, struct pdp_t* pdp, void *cbp));
+ int (*cb) (int type, int cause, struct pdp_t * pdp,
+ void *cbp));
int gtp_set_cb_recovery(struct gsn_t *gsn,
- int (*cb) (struct sockaddr_in *peer, uint8_t recovery));
+ int (*cb) (struct sockaddr_in * peer,
+ uint8_t recovery));
/* Internal functions (not part of the API */
extern int gtp_echo_req(struct gsn_t *gsn, int version, void *cbp,
struct in_addr *inetaddrs);
-extern int gtp_echo_resp(struct gsn_t *gsn, int version,
+extern int gtp_echo_resp(struct gsn_t *gsn, int version,
struct sockaddr_in *peer, int fd,
void *pack, unsigned len);
-extern int gtp_echo_ind(struct gsn_t *gsn, int version,
- struct sockaddr_in *peer, int fd,
+extern int gtp_echo_ind(struct gsn_t *gsn, int version,
+ struct sockaddr_in *peer, int fd,
void *pack, unsigned len);
-extern int gtp_echo_conf(struct gsn_t *gsn, int version,
- struct sockaddr_in *peer,
- void *pack, unsigned len);
+extern int gtp_echo_conf(struct gsn_t *gsn, int version,
+ struct sockaddr_in *peer, void *pack, unsigned len);
-extern int gtp_unsup_req(struct gsn_t *gsn, int version,
+extern int gtp_unsup_req(struct gsn_t *gsn, int version,
struct sockaddr_in *peer,
int fd, void *pack, unsigned len);
extern int gtp_unsup_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
void *pack, unsigned len);
-extern int gtp_create_pdp_resp(struct gsn_t *gsn, int version,
+extern int gtp_create_pdp_resp(struct gsn_t *gsn, int version,
struct pdp_t *pdp, uint8_t cause);
extern int gtp_create_pdp_ind(struct gsn_t *gsn, int version,
@@ -379,14 +375,14 @@ extern int gtp_create_pdp_conf(struct gsn_t *gsn, int version,
void *pack, unsigned len);
extern int gtp_update_pdp_req(struct gsn_t *gsn, int version, void *cbp,
- struct in_addr* inetaddr, struct pdp_t *pdp);
+ struct in_addr *inetaddr, struct pdp_t *pdp);
extern int gtp_delete_pdp_req(struct gsn_t *gsn, int version, void *cbp,
struct pdp_t *pdp);
extern int gtp_delete_pdp_resp(struct gsn_t *gsn, int version,
struct sockaddr_in *peer, int fd,
- void *pack, unsigned len,
+ void *pack, unsigned len,
struct pdp_t *pdp, struct pdp_t *linked_pdp,
uint8_t cause, int teardown);
@@ -398,10 +394,9 @@ extern int gtp_delete_pdp_conf(struct gsn_t *gsn, int version,
struct sockaddr_in *peer,
void *pack, unsigned len);
-
extern int ipv42eua(struct ul66_t *eua, struct in_addr *src);
extern int eua2ipv4(struct in_addr *dst, struct ul66_t *eua);
extern int gsna2in_addr(struct in_addr *dst, struct ul16_t *gsna);
extern int in_addr2gsna(struct ul16_t *gsna, struct in_addr *src);
-#endif /* !_GTP_H */
+#endif /* !_GTP_H */
diff --git a/gtp/gtpie.c b/gtp/gtpie.c
index 39561d2..232183e 100644
--- a/gtp/gtpie.c
+++ b/gtp/gtpie.c
@@ -39,523 +39,592 @@
#include "gtpie.h"
-int gtpie_tlv(void *p, unsigned int *length, unsigned int size, uint8_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_tlv(void *p, unsigned int *length, unsigned int size, uint8_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, unsigned int *length, unsigned int size, uint8_t t, int l, uint8_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_tv0(void *p, unsigned int *length, unsigned int size, uint8_t t,
+ int l, uint8_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, unsigned int *length, unsigned int size, uint8_t t, uint8_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_tv1(void *p, unsigned int *length, unsigned int size, uint8_t t,
+ uint8_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, unsigned int *length, unsigned int size, uint8_t t, uint16_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_tv2(void *p, unsigned int *length, unsigned int size, uint8_t t,
+ uint16_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, unsigned int *length, unsigned int size, uint8_t t, uint32_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_tv4(void *p, unsigned int *length, unsigned int size, uint8_t t,
+ uint32_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_tv8(void *p, unsigned int *length, unsigned int size, uint8_t t, uint64_t v) {
- if ((*length + 9) >= size) return 1;
- ((union gtpie_member*) (p + *length))->tv8.t = hton8(t);
- ((union gtpie_member*) (p + *length))->tv8.v = hton64(v);
- *length += 9;
- return 0;
+int gtpie_tv8(void *p, unsigned int *length, unsigned int size, uint8_t t,
+ uint64_t v)
+{
+ if ((*length + 9) >= size)
+ return 1;
+ ((union gtpie_member *)(p + *length))->tv8.t = hton8(t);
+ ((union gtpie_member *)(p + *length))->tv8.v = hton64(v);
+ *length += 9;
+ 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_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_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,
- unsigned int *length, void *dst, unsigned 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_gettlv(union gtpie_member *ie[], int type, int instance,
+ unsigned int *length, void *dst, unsigned 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, unsigned 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_gettv0(union gtpie_member *ie[], int type, int instance,
+ void *dst, unsigned 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_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_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_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_gettv8(union gtpie_member* ie[], int type, int instance,
- uint64_t *dst){
- int ien;
- ien = gtpie_getie(ie, type, instance);
- if (ien>=0)
- *dst = ntoh64(ie[ien]->tv8.v);
- else
- return EOF;
- return 0;
+int gtpie_gettv8(union gtpie_member *ie[], int type, int instance,
+ uint64_t * dst)
+{
+ int ien;
+ ien = gtpie_getie(ie, type, instance);
+ if (ien >= 0)
+ *dst = ntoh64(ie[ien]->tv8.v);
+ else
+ return EOF;
+ return 0;
}
-int gtpie_decaps(union gtpie_member* ie[], int version, void *pack, unsigned len) {
- int i;
- int j = 0;
- unsigned char *p;
- unsigned char *end;
+int gtpie_decaps(union gtpie_member *ie[], int version, void *pack,
+ unsigned len)
+{
+ int i;
+ int j = 0;
+ unsigned char *p;
+ unsigned char *end;
+
+ end = (unsigned char *)pack + len;
+ p = pack;
- end = (unsigned char*) pack + len;
- p = pack;
+ memset(ie, 0, sizeof(union gtpie_member *) * GTPIE_SIZE);
- memset(ie, 0, sizeof(union gtpie_member *) * GTPIE_SIZE);
+ while ((p < end) && (j < GTPIE_SIZE)) {
+ 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");
+ }
- while ((p<end) && (j<GTPIE_SIZE)) {
- 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 or 4 */
- case GTPIE_FL_C:
- if (version != 0) {
- if (j<GTPIE_SIZE) { /* GTPIE_TEI_DI & GTPIE_TEI_C with length 4 */
- /* 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++;
+ 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 or 4 */
+ case GTPIE_FL_C:
+ if (version != 0) {
+ if (j < GTPIE_SIZE) { /* GTPIE_TEI_DI & GTPIE_TEI_C with length 4 */
+ /* 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_PFI: /* TV GTPIE types with value length 2 */
+ 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:
+ /* case GTPIE_TEI_DI: Handled by GTPIE_FL_DI */
+ /* case GTPIE_TEI_C: Handled by GTPIE_FL_DI */
+ if (j < GTPIE_SIZE) {
+ 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 */
+ if (j < GTPIE_SIZE) {
+ ie[j] = (union gtpie_member *)p;
+ if (GTPIE_DEBUG)
+ printf
+ ("GTPIE_IMSI - 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_RAI: /* TV GTPIE types with value length 6 */
+ if (j < GTPIE_SIZE) {
+ ie[j] = (union gtpie_member *)p;
+ if (GTPIE_DEBUG)
+ printf
+ ("GTPIE_RAI - GTPIE TV 6 found. Type %d, value 0x%llx\n",
+ ie[j]->tv0.t, ie[j]->tv8.v);
+ p += 1 + 6;
+ 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_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;
+ 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 (!(j < GTPIE_SIZE)) {
+ if (GTPIE_DEBUG)
+ printf("GTPIE too many elements.\n");
+ return EOF; /* We received too many information elements */
+ } 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 */
}
- break;
- }
- case GTPIE_PFI: /* TV GTPIE types with value length 2 */
- 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:
- /* case GTPIE_TEI_DI: Handled by GTPIE_FL_DI */
- /* case GTPIE_TEI_C: Handled by GTPIE_FL_DI */
- if (j<GTPIE_SIZE) {
- 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 */
- if (j<GTPIE_SIZE) {
- ie[j] = (union gtpie_member*) p;
- if (GTPIE_DEBUG) printf("GTPIE_IMSI - 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_RAI: /* TV GTPIE types with value length 6 */
- if (j<GTPIE_SIZE) {
- ie[j] = (union gtpie_member*) p;
- if (GTPIE_DEBUG) printf("GTPIE_RAI - GTPIE TV 6 found. Type %d, value 0x%llx\n",
- ie[j]->tv0.t, ie[j]->tv8.v);
- p+= 1 + 6;
- 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_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;
- 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 (!(j<GTPIE_SIZE)) {
- if (GTPIE_DEBUG) printf("GTPIE too many elements.\n");
- return EOF; /* We received too many information elements */
- }
- 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;
+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;
+ 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[], unsigned int size,
- void *pack, unsigned *len) {
- unsigned int i, j;
- unsigned char *p;
- unsigned char *end;
- union gtpie_member *m;
- int iesize;
-
- p = pack;
+ void *pack, unsigned *len)
+{
+ unsigned 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;
+ 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;
}
diff --git a/gtp/gtpie.h b/gtp/gtpie.h
index b8fe1e7..340a76c 100644
--- a/gtp/gtpie.h
+++ b/gtp/gtpie.h
@@ -21,14 +21,13 @@
#define ntoh32(x) ntohl(x)
#if BYTE_ORDER == LITTLE_ENDIAN
-static __inline uint64_t
-hton64(uint64_t q)
+static __inline uint64_t hton64(uint64_t q)
{
- register uint32_t u, l;
- u = q >> 32;
- l = (uint32_t) q;
+ register uint32_t u, l;
+ u = q >> 32;
+ l = (uint32_t) q;
- return htonl(u) | ((uint64_t)htonl(l) << 32);
+ return htonl(u) | ((uint64_t) htonl(l) << 32);
}
#define ntoh64(_x) hton64(_x)
@@ -42,127 +41,124 @@ hton64(uint64_t q)
#error "Please fix <machine/endian.h>"
#endif
+#define GTPIE_SIZE 256 /* Max number of information elements */
+#define GTPIE_MAX 0xffff /* Max length of information elements */
+#define GTPIE_MAX_TV 28 /* Max length of type value pair */
+#define GTPIE_MAX_TLV 0xffff-3 /* Max length of TLV (GTP length is 16 bit) */
-#define GTPIE_SIZE 256 /* Max number of information elements */
-#define GTPIE_MAX 0xffff /* Max length of information elements */
-#define GTPIE_MAX_TV 28 /* Max length of type value pair */
-#define GTPIE_MAX_TLV 0xffff-3 /* Max length of TLV (GTP length is 16 bit) */
-
-#define GTPIE_DEBUG 0 /* Print debug information */
+#define GTPIE_DEBUG 0 /* Print debug information */
/* GTP Information elements from 29.060 v3.9.0 7.7 Information Elements */
/* Also covers version 0. Note that version 0 6: QOS Profile was superceded *
* by 135: QOS Profile in version 1 */
-#define GTPIE_CAUSE 1 /* Cause 1 */
-#define GTPIE_IMSI 2 /* International Mobile Subscriber Identity 8 */
-#define GTPIE_RAI 3 /* Routing Area Identity (RAI) 8 */
-#define GTPIE_TLLI 4 /* Temporary Logical Link Identity (TLLI) 4 */
-#define GTPIE_P_TMSI 5 /* Packet TMSI (P-TMSI) 4 */
-#define GTPIE_QOS_PROFILE0 6 /* Quality of Service Profile GTP version 0 3*/
- /* 6-7 SPARE */ /* 6 is QoS Profile vers 0 */
-#define GTPIE_REORDER 8 /* Reordering Required 1 */
-#define GTPIE_AUTH_TRIPLET 9 /* Authentication Triplet 28 */
- /* 10 SPARE */
-#define GTPIE_MAP_CAUSE 11 /* MAP Cause 1 */
-#define GTPIE_P_TMSI_S 12 /* P-TMSI Signature 3 */
-#define GTPIE_MS_VALIDATED 13 /* MS Validated 1 */
-#define GTPIE_RECOVERY 14 /* Recovery 1 */
-#define GTPIE_SELECTION_MODE 15 /* Selection Mode 1 */
-#define GTPIE_FL_DI 16 /* Flow Label Data I 2 */
-#define GTPIE_TEI_DI 16 /* Tunnel Endpoint Identifier Data I 4 */
-#define GTPIE_TEI_C 17 /* Tunnel Endpoint Identifier Control Plane 4 */
-#define GTPIE_FL_C 17 /* Flow Label Signalling 2 */
-#define GTPIE_TEI_DII 18 /* Tunnel Endpoint Identifier Data II 5 */
-#define GTPIE_TEARDOWN 19 /* Teardown Ind 1 */
-#define GTPIE_NSAPI 20 /* NSAPI 1 */
-#define GTPIE_RANAP_CAUSE 21 /* RANAP Cause 1 */
-#define GTPIE_RAB_CONTEXT 22 /* RAB Context 7 */
-#define GTPIE_RP_SMS 23 /* Radio Priority SMS 1 */
-#define GTPIE_RP 24 /* Radio Priority 1 */
-#define GTPIE_PFI 25 /* Packet Flow Id 2 */
-#define GTPIE_CHARGING_C 26 /* Charging Characteristics 2 */
-#define GTPIE_TRACE_REF 27 /* Trace Reference 2 */
-#define GTPIE_TRACE_TYPE 28 /* Trace Type 2 */
-#define GTPIE_MS_NOT_REACH 29 /* MS Not Reachable Reason 1 */
- /* 30-116 UNUSED */
+#define GTPIE_CAUSE 1 /* Cause 1 */
+#define GTPIE_IMSI 2 /* International Mobile Subscriber Identity 8 */
+#define GTPIE_RAI 3 /* Routing Area Identity (RAI) 8 */
+#define GTPIE_TLLI 4 /* Temporary Logical Link Identity (TLLI) 4 */
+#define GTPIE_P_TMSI 5 /* Packet TMSI (P-TMSI) 4 */
+#define GTPIE_QOS_PROFILE0 6 /* Quality of Service Profile GTP version 0 3 */
+ /* 6-7 SPARE *//* 6 is QoS Profile vers 0 */
+#define GTPIE_REORDER 8 /* Reordering Required 1 */
+#define GTPIE_AUTH_TRIPLET 9 /* Authentication Triplet 28 */
+ /* 10 SPARE */
+#define GTPIE_MAP_CAUSE 11 /* MAP Cause 1 */
+#define GTPIE_P_TMSI_S 12 /* P-TMSI Signature 3 */
+#define GTPIE_MS_VALIDATED 13 /* MS Validated 1 */
+#define GTPIE_RECOVERY 14 /* Recovery 1 */
+#define GTPIE_SELECTION_MODE 15 /* Selection Mode 1 */
+#define GTPIE_FL_DI 16 /* Flow Label Data I 2 */
+#define GTPIE_TEI_DI 16 /* Tunnel Endpoint Identifier Data I 4 */
+#define GTPIE_TEI_C 17 /* Tunnel Endpoint Identifier Control Plane 4 */
+#define GTPIE_FL_C 17 /* Flow Label Signalling 2 */
+#define GTPIE_TEI_DII 18 /* Tunnel Endpoint Identifier Data II 5 */
+#define GTPIE_TEARDOWN 19 /* Teardown Ind 1 */
+#define GTPIE_NSAPI 20 /* NSAPI 1 */
+#define GTPIE_RANAP_CAUSE 21 /* RANAP Cause 1 */
+#define GTPIE_RAB_CONTEXT 22 /* RAB Context 7 */
+#define GTPIE_RP_SMS 23 /* Radio Priority SMS 1 */
+#define GTPIE_RP 24 /* Radio Priority 1 */
+#define GTPIE_PFI 25 /* Packet Flow Id 2 */
+#define GTPIE_CHARGING_C 26 /* Charging Characteristics 2 */
+#define GTPIE_TRACE_REF 27 /* Trace Reference 2 */
+#define GTPIE_TRACE_TYPE 28 /* Trace Type 2 */
+#define GTPIE_MS_NOT_REACH 29 /* MS Not Reachable Reason 1 */
+ /* 30-116 UNUSED */
/* 117-126 Reserved for the GPRS charging protocol (see GTP' in GSM 12.15) */
-#define GTPIE_CHARGING_ID 127 /* Charging ID 4 */
-#define GTPIE_EUA 128 /* End User Address */
-#define GTPIE_MM_CONTEXT 129 /* MM Context */
-#define GTPIE_PDP_CONTEXT 130 /* PDP Context */
-#define GTPIE_APN 131 /* Access Point Name */
-#define GTPIE_PCO 132 /* Protocol Configuration Options */
-#define GTPIE_GSN_ADDR 133 /* GSN Address */
-#define GTPIE_MSISDN 134 /* MS International PSTN/ISDN Number */
-#define GTPIE_QOS_PROFILE 135 /* Quality of Service Profile */
-#define GTPIE_AUTH_QUINTUP 136 /* Authentication Quintuplet */
-#define GTPIE_TFT 137 /* Traffic Flow Template */
-#define GTPIE_TARGET_INF 138 /* Target Identification */
-#define GTPIE_UTRAN_TRANS 139 /* UTRAN Transparent Container */
-#define GTPIE_RAB_SETUP 140 /* RAB Setup Information */
-#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 */
+#define GTPIE_CHARGING_ID 127 /* Charging ID 4 */
+#define GTPIE_EUA 128 /* End User Address */
+#define GTPIE_MM_CONTEXT 129 /* MM Context */
+#define GTPIE_PDP_CONTEXT 130 /* PDP Context */
+#define GTPIE_APN 131 /* Access Point Name */
+#define GTPIE_PCO 132 /* Protocol Configuration Options */
+#define GTPIE_GSN_ADDR 133 /* GSN Address */
+#define GTPIE_MSISDN 134 /* MS International PSTN/ISDN Number */
+#define GTPIE_QOS_PROFILE 135 /* Quality of Service Profile */
+#define GTPIE_AUTH_QUINTUP 136 /* Authentication Quintuplet */
+#define GTPIE_TFT 137 /* Traffic Flow Template */
+#define GTPIE_TARGET_INF 138 /* Target Identification */
+#define GTPIE_UTRAN_TRANS 139 /* UTRAN Transparent Container */
+#define GTPIE_RAB_SETUP 140 /* RAB Setup Information */
+#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 */
+#define GTPIE_CHARGING_ADDR 251 /* Charging Gateway Address */
/* 252-254 Reserved for the GPRS charging protocol (see GTP' in GSM 12.15) */
-#define GTPIE_PRIVATE 255 /* Private Extension */
-
+#define GTPIE_PRIVATE 255 /* Private Extension */
/* GTP information element structs in network order */
-struct gtpie_ext { /* Extension header */
- uint8_t t; /* Type */
- uint8_t l; /* Length */
- uint8_t *p; /* Value */
-} __attribute__((packed));
-
-struct gtpie_tlv { /* Type length value pair */
- uint8_t t; /* Type */
- uint16_t l; /* Length */
- uint8_t v[GTPIE_MAX_TLV]; /* Value */
-} __attribute__((packed));
-
-struct gtpie_tv0 { /* 1 byte type value pair */
- uint8_t t; /* Type */
- uint8_t v[GTPIE_MAX_TV]; /* Pointer to value */
-}__attribute__((packed));
-
-struct gtpie_tv1 { /* 1 byte type value pair */
- uint8_t t; /* Type */
- uint8_t v; /* Value */
-}__attribute__((packed));
-
-struct gtpie_tv2 { /* 2 byte type value pair */
- uint8_t t; /* Type */
- uint16_t v; /* Value */
-}__attribute__((packed));
-
-struct gtpie_tv4 { /* 4 byte type value pair */
- uint8_t t; /* Type */
- uint32_t v; /* Value */
-}__attribute__((packed));
-
-struct gtpie_tv8 { /* 8 byte type value pair */
- uint8_t t; /* Type */
- uint64_t v; /* Value */
-}__attribute__((packed));
-
+struct gtpie_ext { /* Extension header */
+ uint8_t t; /* Type */
+ uint8_t l; /* Length */
+ uint8_t *p; /* Value */
+} __attribute__ ((packed));
+
+struct gtpie_tlv { /* Type length value pair */
+ uint8_t t; /* Type */
+ uint16_t l; /* Length */
+ uint8_t v[GTPIE_MAX_TLV]; /* Value */
+} __attribute__ ((packed));
+
+struct gtpie_tv0 { /* 1 byte type value pair */
+ uint8_t t; /* Type */
+ uint8_t v[GTPIE_MAX_TV]; /* Pointer to value */
+} __attribute__ ((packed));
+
+struct gtpie_tv1 { /* 1 byte type value pair */
+ uint8_t t; /* Type */
+ uint8_t v; /* Value */
+} __attribute__ ((packed));
+
+struct gtpie_tv2 { /* 2 byte type value pair */
+ uint8_t t; /* Type */
+ uint16_t v; /* Value */
+} __attribute__ ((packed));
+
+struct gtpie_tv4 { /* 4 byte type value pair */
+ uint8_t t; /* Type */
+ uint32_t v; /* Value */
+} __attribute__ ((packed));
+
+struct gtpie_tv8 { /* 8 byte type value pair */
+ uint8_t t; /* Type */
+ uint64_t v; /* Value */
+} __attribute__ ((packed));
union gtpie_member {
- uint8_t t;
- struct gtpie_ext ext;
- struct gtpie_tlv tlv;
- struct gtpie_tv0 tv0;
- struct gtpie_tv1 tv1;
- struct gtpie_tv2 tv2;
- struct gtpie_tv4 tv4;
- struct gtpie_tv8 tv8;
-}__attribute__((packed));
+ uint8_t t;
+ struct gtpie_ext ext;
+ struct gtpie_tlv tlv;
+ struct gtpie_tv0 tv0;
+ struct gtpie_tv1 tv1;
+ struct gtpie_tv2 tv2;
+ struct gtpie_tv4 tv4;
+ struct gtpie_tv8 tv8;
+} __attribute__ ((packed));
/*
cause
@@ -214,45 +210,46 @@ private
*/
struct tlv1 {
- uint8_t type;
- uint8_t length;
-}__attribute__((packed));
+ uint8_t type;
+ uint8_t length;
+} __attribute__ ((packed));
struct tlv2 {
- uint8_t type;
- uint16_t length;
-}__attribute__((packed));
+ uint8_t type;
+ uint16_t length;
+} __attribute__ ((packed));
extern int gtpie_tlv(void *p, unsigned int *length, unsigned int size,
uint8_t t, int l, void *v);
-extern int gtpie_tv0(void *p, unsigned int *length, unsigned int size,
- uint8_t t, int l, uint8_t *v);
-extern int gtpie_tv1(void *p, unsigned int *length, unsigned int size, uint8_t t, uint8_t v);
-extern int gtpie_tv2(void *p, unsigned int *length, unsigned int size, uint8_t t, uint16_t v);
-extern int gtpie_tv4(void *p, unsigned int *length, unsigned int size, uint8_t t, uint32_t v);
-extern int gtpie_tv8(void *p, unsigned int *length, unsigned int size, uint8_t t, uint64_t v);
-extern int gtpie_getie(union gtpie_member* ie[], int type, int instance);
-extern int gtpie_exist(union gtpie_member* ie[], int type, int instance);
-extern int gtpie_gettlv(union gtpie_member* ie[], int type, int instance,
+extern int gtpie_tv0(void *p, unsigned int *length, unsigned int size,
+ uint8_t t, int l, uint8_t * v);
+extern int gtpie_tv1(void *p, unsigned int *length, unsigned int size,
+ uint8_t t, uint8_t v);
+extern int gtpie_tv2(void *p, unsigned int *length, unsigned int size,
+ uint8_t t, uint16_t v);
+extern int gtpie_tv4(void *p, unsigned int *length, unsigned int size,
+ uint8_t t, uint32_t v);
+extern int gtpie_tv8(void *p, unsigned int *length, unsigned int size,
+ uint8_t t, uint64_t v);
+extern int gtpie_getie(union gtpie_member *ie[], int type, int instance);
+extern int gtpie_exist(union gtpie_member *ie[], int type, int instance);
+extern int gtpie_gettlv(union gtpie_member *ie[], int type, int instance,
unsigned int *length, void *dst, unsigned int size);
-extern int gtpie_gettv0(union gtpie_member* ie[], int type, int instance,
+extern int gtpie_gettv0(union gtpie_member *ie[], int type, int instance,
void *dst, unsigned int size);
-extern int gtpie_gettv1(union gtpie_member* ie[], int type, int instance,
- uint8_t *dst);
-extern int gtpie_gettv2(union gtpie_member* ie[], int type, int instance,
- uint16_t *dst);
-extern int gtpie_gettv4(union gtpie_member* ie[], int type, int instance,
- uint32_t *dst);
-extern int gtpie_gettv8(union gtpie_member* ie[], int type, int instance,
- uint64_t *dst);
-
-extern int gtpie_decaps(union gtpie_member* ie[], int version,
+extern int gtpie_gettv1(union gtpie_member *ie[], int type, int instance,
+ uint8_t * dst);
+extern int gtpie_gettv2(union gtpie_member *ie[], int type, int instance,
+ uint16_t * dst);
+extern int gtpie_gettv4(union gtpie_member *ie[], int type, int instance,
+ uint32_t * dst);
+extern int gtpie_gettv8(union gtpie_member *ie[], int type, int instance,
+ uint64_t * dst);
+
+extern int gtpie_decaps(union gtpie_member *ie[], int version,
void *pack, unsigned len);
-extern int gtpie_encaps(union gtpie_member* ie[], void *pack, unsigned *len);
+extern int gtpie_encaps(union gtpie_member *ie[], void *pack, unsigned *len);
extern int gtpie_encaps2(union gtpie_member ie[], unsigned int size,
- void *pack, unsigned *len);
-
-
-#endif /* !_GTPIE_H */
-
+ void *pack, unsigned *len);
+#endif /* !_GTPIE_H */
diff --git a/gtp/lookupa.c b/gtp/lookupa.c
index 8ff114b..1eff74a 100644
--- a/gtp/lookupa.c
+++ b/gtp/lookupa.c
@@ -81,52 +81,64 @@ acceptable. Do NOT use for cryptographic purposes.
--------------------------------------------------------------------
*/
-ub4 lookup( k, length, level)
-register ub1 *k; /* the key */
-register ub4 length; /* the length of the key */
-register ub4 level; /* the previous hash, or an arbitrary value */
+ub4 lookup(k, length, level)
+register ub1 *k; /* the key */
+register ub4 length; /* the length of the key */
+register ub4 level; /* the previous hash, or an arbitrary value */
{
- register ub4 a,b,c,len;
+ register ub4 a, b, c, len;
- /* Set up the internal state */
- len = length;
- a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
- c = level; /* the previous hash value */
+ /* Set up the internal state */
+ len = length;
+ a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
+ c = level; /* the previous hash value */
/*---------------------------------------- handle most of the key */
- while (len >= 12)
- {
- a += (k[0] +((ub4)k[1]<<8) +((ub4)k[2]<<16) +((ub4)k[3]<<24));
- b += (k[4] +((ub4)k[5]<<8) +((ub4)k[6]<<16) +((ub4)k[7]<<24));
- c += (k[8] +((ub4)k[9]<<8) +((ub4)k[10]<<16)+((ub4)k[11]<<24));
- mix(a,b,c);
- k += 12; len -= 12;
- }
+ while (len >= 12) {
+ a += (k[0] + ((ub4) k[1] << 8) + ((ub4) k[2] << 16) +
+ ((ub4) k[3] << 24));
+ b += (k[4] + ((ub4) k[5] << 8) + ((ub4) k[6] << 16) +
+ ((ub4) k[7] << 24));
+ c += (k[8] + ((ub4) k[9] << 8) + ((ub4) k[10] << 16) +
+ ((ub4) k[11] << 24));
+ mix(a, b, c);
+ k += 12;
+ len -= 12;
+ }
/*------------------------------------- handle the last 11 bytes */
- c += length;
- switch(len) /* all the case statements fall through */
- {
- case 11: c+=((ub4)k[10]<<24);
- case 10: c+=((ub4)k[9]<<16);
- case 9 : c+=((ub4)k[8]<<8);
- /* the first byte of c is reserved for the length */
- case 8 : b+=((ub4)k[7]<<24);
- case 7 : b+=((ub4)k[6]<<16);
- case 6 : b+=((ub4)k[5]<<8);
- case 5 : b+=k[4];
- case 4 : a+=((ub4)k[3]<<24);
- case 3 : a+=((ub4)k[2]<<16);
- case 2 : a+=((ub4)k[1]<<8);
- case 1 : a+=k[0];
- /* case 0: nothing left to add */
- }
- mix(a,b,c);
+ c += length;
+ switch (len) { /* all the case statements fall through */
+ case 11:
+ c += ((ub4) k[10] << 24);
+ case 10:
+ c += ((ub4) k[9] << 16);
+ case 9:
+ c += ((ub4) k[8] << 8);
+ /* the first byte of c is reserved for the length */
+ case 8:
+ b += ((ub4) k[7] << 24);
+ case 7:
+ b += ((ub4) k[6] << 16);
+ case 6:
+ b += ((ub4) k[5] << 8);
+ case 5:
+ b += k[4];
+ case 4:
+ a += ((ub4) k[3] << 24);
+ case 3:
+ a += ((ub4) k[2] << 16);
+ case 2:
+ a += ((ub4) k[1] << 8);
+ case 1:
+ a += k[0];
+ /* case 0: nothing left to add */
+ }
+ mix(a, b, c);
/*-------------------------------------------- report the result */
- return c;
+ return c;
}
-
/*
--------------------------------------------------------------------
mixc -- mixc 8 4-bit values as quickly and thoroughly as possible.
@@ -169,78 +181,120 @@ Use to detect changes between revisions of documents, assuming nobody
is trying to cause collisions. Do NOT use for cryptography.
--------------------------------------------------------------------
*/
-void checksum( k, len, state)
+void checksum(k, len, state)
register ub1 *k;
-register ub4 len;
+register ub4 len;
register ub4 *state;
{
- register ub4 a,b,c,d,e,f,g,h,length;
+ register ub4 a, b, c, d, e, f, g, h, length;
- /* Use the length and level; add in the golden ratio. */
- length = len;
- a=state[0]; b=state[1]; c=state[2]; d=state[3];
- e=state[4]; f=state[5]; g=state[6]; h=state[7];
+ /* Use the length and level; add in the golden ratio. */
+ length = len;
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+ e = state[4];
+ f = state[5];
+ g = state[6];
+ h = state[7];
/*---------------------------------------- handle most of the key */
- while (len >= 32)
- {
- a += (k[0] +(k[1]<<8) +(k[2]<<16) +(k[3]<<24));
- b += (k[4] +(k[5]<<8) +(k[6]<<16) +(k[7]<<24));
- c += (k[8] +(k[9]<<8) +(k[10]<<16)+(k[11]<<24));
- d += (k[12]+(k[13]<<8)+(k[14]<<16)+(k[15]<<24));
- e += (k[16]+(k[17]<<8)+(k[18]<<16)+(k[19]<<24));
- f += (k[20]+(k[21]<<8)+(k[22]<<16)+(k[23]<<24));
- g += (k[24]+(k[25]<<8)+(k[26]<<16)+(k[27]<<24));
- h += (k[28]+(k[29]<<8)+(k[30]<<16)+(k[31]<<24));
- mixc(a,b,c,d,e,f,g,h);
- mixc(a,b,c,d,e,f,g,h);
- mixc(a,b,c,d,e,f,g,h);
- mixc(a,b,c,d,e,f,g,h);
- k += 32; len -= 32;
- }
+ while (len >= 32) {
+ a += (k[0] + (k[1] << 8) + (k[2] << 16) + (k[3] << 24));
+ b += (k[4] + (k[5] << 8) + (k[6] << 16) + (k[7] << 24));
+ c += (k[8] + (k[9] << 8) + (k[10] << 16) + (k[11] << 24));
+ d += (k[12] + (k[13] << 8) + (k[14] << 16) + (k[15] << 24));
+ e += (k[16] + (k[17] << 8) + (k[18] << 16) + (k[19] << 24));
+ f += (k[20] + (k[21] << 8) + (k[22] << 16) + (k[23] << 24));
+ g += (k[24] + (k[25] << 8) + (k[26] << 16) + (k[27] << 24));
+ h += (k[28] + (k[29] << 8) + (k[30] << 16) + (k[31] << 24));
+ mixc(a, b, c, d, e, f, g, h);
+ mixc(a, b, c, d, e, f, g, h);
+ mixc(a, b, c, d, e, f, g, h);
+ mixc(a, b, c, d, e, f, g, h);
+ k += 32;
+ len -= 32;
+ }
/*------------------------------------- handle the last 31 bytes */
- h += length;
- switch(len)
- {
- case 31: h+=(k[30]<<24);
- case 30: h+=(k[29]<<16);
- case 29: h+=(k[28]<<8);
- case 28: g+=(k[27]<<24);
- case 27: g+=(k[26]<<16);
- case 26: g+=(k[25]<<8);
- case 25: g+=k[24];
- case 24: f+=(k[23]<<24);
- case 23: f+=(k[22]<<16);
- case 22: f+=(k[21]<<8);
- case 21: f+=k[20];
- case 20: e+=(k[19]<<24);
- case 19: e+=(k[18]<<16);
- case 18: e+=(k[17]<<8);
- case 17: e+=k[16];
- case 16: d+=(k[15]<<24);
- case 15: d+=(k[14]<<16);
- case 14: d+=(k[13]<<8);
- case 13: d+=k[12];
- case 12: c+=(k[11]<<24);
- case 11: c+=(k[10]<<16);
- case 10: c+=(k[9]<<8);
- case 9 : c+=k[8];
- case 8 : b+=(k[7]<<24);
- case 7 : b+=(k[6]<<16);
- case 6 : b+=(k[5]<<8);
- case 5 : b+=k[4];
- case 4 : a+=(k[3]<<24);
- case 3 : a+=(k[2]<<16);
- case 2 : a+=(k[1]<<8);
- case 1 : a+=k[0];
- }
- mixc(a,b,c,d,e,f,g,h);
- mixc(a,b,c,d,e,f,g,h);
- mixc(a,b,c,d,e,f,g,h);
- mixc(a,b,c,d,e,f,g,h);
+ h += length;
+ switch (len) {
+ case 31:
+ h += (k[30] << 24);
+ case 30:
+ h += (k[29] << 16);
+ case 29:
+ h += (k[28] << 8);
+ case 28:
+ g += (k[27] << 24);
+ case 27:
+ g += (k[26] << 16);
+ case 26:
+ g += (k[25] << 8);
+ case 25:
+ g += k[24];
+ case 24:
+ f += (k[23] << 24);
+ case 23:
+ f += (k[22] << 16);
+ case 22:
+ f += (k[21] << 8);
+ case 21:
+ f += k[20];
+ case 20:
+ e += (k[19] << 24);
+ case 19:
+ e += (k[18] << 16);
+ case 18:
+ e += (k[17] << 8);
+ case 17:
+ e += k[16];
+ case 16:
+ d += (k[15] << 24);
+ case 15:
+ d += (k[14] << 16);
+ case 14:
+ d += (k[13] << 8);
+ case 13:
+ d += k[12];
+ case 12:
+ c += (k[11] << 24);
+ case 11:
+ c += (k[10] << 16);
+ case 10:
+ c += (k[9] << 8);
+ case 9:
+ c += k[8];
+ case 8:
+ b += (k[7] << 24);
+ case 7:
+ b += (k[6] << 16);
+ case 6:
+ b += (k[5] << 8);
+ case 5:
+ b += k[4];
+ case 4:
+ a += (k[3] << 24);
+ case 3:
+ a += (k[2] << 16);
+ case 2:
+ a += (k[1] << 8);
+ case 1:
+ a += k[0];
+ }
+ mixc(a, b, c, d, e, f, g, h);
+ mixc(a, b, c, d, e, f, g, h);
+ mixc(a, b, c, d, e, f, g, h);
+ mixc(a, b, c, d, e, f, g, h);
/*-------------------------------------------- report the result */
- state[0]=a; state[1]=b; state[2]=c; state[3]=d;
- state[4]=e; state[5]=f; state[6]=g; state[7]=h;
+ state[0] = a;
+ state[1] = b;
+ state[2] = c;
+ state[3] = d;
+ state[4] = e;
+ state[5] = f;
+ state[6] = g;
+ state[7] = h;
}
diff --git a/gtp/lookupa.h b/gtp/lookupa.h
index 16784a9..a733509 100644
--- a/gtp/lookupa.h
+++ b/gtp/lookupa.h
@@ -16,14 +16,14 @@ Source is http://burtleburtle.net/bob/c/lookupa.h
#ifndef LOOKUPA
#define LOOKUPA
-typedef unsigned long int ub4; /* unsigned 4-byte quantities */
-typedef unsigned char ub1;
+typedef unsigned long int ub4; /* unsigned 4-byte quantities */
+typedef unsigned char ub1;
#define CHECKSTATE 8
#define hashsize(n) ((ub4)1<<(n))
#define hashmask(n) (hashsize(n)-1)
-ub4 lookup(/*_ ub1 *k, ub4 length, ub4 level _*/);
-void checksum(/*_ ub1 *k, ub4 length, ub4 *state _*/);
+ub4 lookup( /*_ ub1 *k, ub4 length, ub4 level _*/ );
+void checksum( /*_ ub1 *k, ub4 length, ub4 *state _*/ );
#endif /* LOOKUPA */
diff --git a/gtp/pdp.c b/gtp/pdp.c
index 648d70d..7ce9128 100644
--- a/gtp/pdp.c
+++ b/gtp/pdp.c
@@ -31,8 +31,8 @@
* Global variables TODO: most should be moved to gsn_t
*************************************************************/
-struct pdp_t pdpa[PDP_MAX]; /* PDP storage */
-struct pdp_t* hashtid[PDP_MAX];/* Hash table for IMSI + NSAPI */
+struct pdp_t pdpa[PDP_MAX]; /* PDP storage */
+struct pdp_t *hashtid[PDP_MAX]; /* Hash table for IMSI + NSAPI */
/* struct pdp_t* haship[PDP_MAX]; Hash table for IP and network interface */
/* ***********************************************************
@@ -107,144 +107,171 @@ struct pdp_t* hashtid[PDP_MAX];/* Hash table for IMSI + NSAPI */
*
*************************************************************/
-int pdp_init() {
- memset(&pdpa, 0, sizeof(pdpa));
- memset(&hashtid, 0, sizeof(hashtid));
- /* memset(&haship, 0, sizeof(haship)); */
+int pdp_init()
+{
+ memset(&pdpa, 0, sizeof(pdpa));
+ memset(&hashtid, 0, sizeof(hashtid));
+ /* memset(&haship, 0, sizeof(haship)); */
- return 0;
+ return 0;
}
-int pdp_newpdp(struct pdp_t **pdp, uint64_t imsi, uint8_t nsapi,
- struct pdp_t *pdp_old){
- int n;
- for (n=0; n<PDP_MAX; n++) { /* TODO: Need to do better than linear search */
- if (pdpa[n].inuse == 0) {
- *pdp = &pdpa[n];
- if (NULL != pdp_old) memcpy(*pdp, pdp_old, sizeof(struct pdp_t));
- else memset(*pdp, 0, sizeof(struct pdp_t));
- (*pdp)->inuse = 1;
- (*pdp)->imsi = imsi;
- (*pdp)->nsapi = nsapi;
- (*pdp)->fllc = (uint16_t) n + 1;
- (*pdp)->fllu = (uint16_t) n + 1;
- (*pdp)->teid_own = (uint32_t) n + 1;
- if (!(*pdp)->secondary) (*pdp)->teic_own = (uint32_t) n + 1;
- pdp_tidset(*pdp, pdp_gettid(imsi, nsapi));
-
- /* Insert reference in primary context */
- if (((*pdp)->teic_own > 0 ) && ((*pdp)->teic_own <= PDP_MAX)) {
- pdpa[(*pdp)->teic_own-1].secondary_tei[(*pdp)->nsapi & 0x0f] =
- (*pdp)->teid_own;
- }
-
- return 0;
- }
- }
- return EOF; /* No more available */
+int pdp_newpdp(struct pdp_t **pdp, uint64_t imsi, uint8_t nsapi,
+ struct pdp_t *pdp_old)
+{
+ int n;
+ for (n = 0; n < PDP_MAX; n++) { /* TODO: Need to do better than linear search */
+ if (pdpa[n].inuse == 0) {
+ *pdp = &pdpa[n];
+ if (NULL != pdp_old)
+ memcpy(*pdp, pdp_old, sizeof(struct pdp_t));
+ else
+ memset(*pdp, 0, sizeof(struct pdp_t));
+ (*pdp)->inuse = 1;
+ (*pdp)->imsi = imsi;
+ (*pdp)->nsapi = nsapi;
+ (*pdp)->fllc = (uint16_t) n + 1;
+ (*pdp)->fllu = (uint16_t) n + 1;
+ (*pdp)->teid_own = (uint32_t) n + 1;
+ if (!(*pdp)->secondary)
+ (*pdp)->teic_own = (uint32_t) n + 1;
+ pdp_tidset(*pdp, pdp_gettid(imsi, nsapi));
+
+ /* Insert reference in primary context */
+ if (((*pdp)->teic_own > 0)
+ && ((*pdp)->teic_own <= PDP_MAX)) {
+ pdpa[(*pdp)->teic_own -
+ 1].secondary_tei[(*pdp)->nsapi & 0x0f] =
+ (*pdp)->teid_own;
+ }
+
+ return 0;
+ }
+ }
+ return EOF; /* No more available */
}
-int pdp_freepdp(struct pdp_t *pdp){
- pdp_tiddel(pdp);
+int pdp_freepdp(struct pdp_t *pdp)
+{
+ pdp_tiddel(pdp);
- /* Remove any references in primary context */
- if ((pdp->secondary) && (pdp->teic_own > 0 ) && (pdp->teic_own <= PDP_MAX)) {
- pdpa[pdp->teic_own-1].secondary_tei[pdp->nsapi & 0x0f] = 0;
- }
+ /* Remove any references in primary context */
+ if ((pdp->secondary) && (pdp->teic_own > 0)
+ && (pdp->teic_own <= PDP_MAX)) {
+ pdpa[pdp->teic_own - 1].secondary_tei[pdp->nsapi & 0x0f] = 0;
+ }
- memset(pdp, 0, sizeof(struct pdp_t));
- return 0;
+ memset(pdp, 0, sizeof(struct pdp_t));
+ return 0;
}
-int pdp_getpdp(struct pdp_t **pdp){
- *pdp = &pdpa[0];
- return 0;
+int pdp_getpdp(struct pdp_t **pdp)
+{
+ *pdp = &pdpa[0];
+ return 0;
}
-int pdp_getgtp0(struct pdp_t **pdp, uint16_t fl){
- if ((fl>PDP_MAX) || (fl<1)) {
- return EOF; /* Not found */
- }
- else {
- *pdp = &pdpa[fl-1];
- if ((*pdp)->inuse) return 0;
- else return EOF;
- /* Context exists. We do no further validity checking. */
- }
+int pdp_getgtp0(struct pdp_t **pdp, uint16_t fl)
+{
+ if ((fl > PDP_MAX) || (fl < 1)) {
+ return EOF; /* Not found */
+ } else {
+ *pdp = &pdpa[fl - 1];
+ if ((*pdp)->inuse)
+ return 0;
+ else
+ return EOF;
+ /* Context exists. We do no further validity checking. */
+ }
}
-int pdp_getgtp1(struct pdp_t **pdp, uint32_t tei){
- if ((tei>PDP_MAX) || (tei<1)) {
- return EOF; /* Not found */
- }
- else {
- *pdp = &pdpa[tei-1];
- if ((*pdp)->inuse) return 0;
- else return EOF;
- /* Context exists. We do no further validity checking. */
- }
+int pdp_getgtp1(struct pdp_t **pdp, uint32_t tei)
+{
+ if ((tei > PDP_MAX) || (tei < 1)) {
+ return EOF; /* Not found */
+ } else {
+ *pdp = &pdpa[tei - 1];
+ if ((*pdp)->inuse)
+ return 0;
+ else
+ return EOF;
+ /* Context exists. We do no further validity checking. */
+ }
}
-
-int pdp_tidhash(uint64_t tid) {
- return (lookup(&tid, sizeof(tid), 0) % PDP_MAX);
+int pdp_tidhash(uint64_t tid)
+{
+ return (lookup(&tid, sizeof(tid), 0) % PDP_MAX);
}
-int pdp_tidset(struct pdp_t *pdp, uint64_t tid) {
- int hash = pdp_tidhash(tid);
- struct pdp_t *pdp2;
- struct pdp_t *pdp_prev = NULL;
- if (PDP_DEBUG) printf("Begin pdp_tidset tid = %llx\n", tid);
- pdp->tidnext = NULL;
- pdp->tid = tid;
- for (pdp2 = hashtid[hash]; pdp2; pdp2 = pdp2->tidnext)
- pdp_prev = pdp2;
- if (!pdp_prev)
- hashtid[hash] = pdp;
- else
- pdp_prev->tidnext = pdp;
- if (PDP_DEBUG) printf("End pdp_tidset\n");
- return 0;
+int pdp_tidset(struct pdp_t *pdp, uint64_t tid)
+{
+ int hash = pdp_tidhash(tid);
+ struct pdp_t *pdp2;
+ struct pdp_t *pdp_prev = NULL;
+ if (PDP_DEBUG)
+ printf("Begin pdp_tidset tid = %llx\n", tid);
+ pdp->tidnext = NULL;
+ pdp->tid = tid;
+ for (pdp2 = hashtid[hash]; pdp2; pdp2 = pdp2->tidnext)
+ pdp_prev = pdp2;
+ if (!pdp_prev)
+ hashtid[hash] = pdp;
+ else
+ pdp_prev->tidnext = pdp;
+ if (PDP_DEBUG)
+ printf("End pdp_tidset\n");
+ return 0;
}
-int pdp_tiddel(struct pdp_t *pdp) {
- int hash = pdp_tidhash(pdp->tid);
- struct pdp_t *pdp2;
- struct pdp_t *pdp_prev = NULL;
- if (PDP_DEBUG) printf("Begin pdp_tiddel tid = %llx\n", pdp->tid);
- for (pdp2 = hashtid[hash]; pdp2; pdp2 = pdp2->tidnext) {
- if (pdp2 == pdp) {
- if (!pdp_prev)
- hashtid[hash] = pdp2->tidnext;
- else
- pdp_prev->tidnext = pdp2->tidnext;
- if (PDP_DEBUG) printf("End pdp_tiddel: PDP found\n");
- return 0;
- }
- pdp_prev = pdp2;
- }
- if (PDP_DEBUG) printf("End pdp_tiddel: PDP not found\n");
- return EOF; /* End of linked list and not found */
+int pdp_tiddel(struct pdp_t *pdp)
+{
+ int hash = pdp_tidhash(pdp->tid);
+ struct pdp_t *pdp2;
+ struct pdp_t *pdp_prev = NULL;
+ if (PDP_DEBUG)
+ printf("Begin pdp_tiddel tid = %llx\n", pdp->tid);
+ for (pdp2 = hashtid[hash]; pdp2; pdp2 = pdp2->tidnext) {
+ if (pdp2 == pdp) {
+ if (!pdp_prev)
+ hashtid[hash] = pdp2->tidnext;
+ else
+ pdp_prev->tidnext = pdp2->tidnext;
+ if (PDP_DEBUG)
+ printf("End pdp_tiddel: PDP found\n");
+ return 0;
+ }
+ pdp_prev = pdp2;
+ }
+ if (PDP_DEBUG)
+ printf("End pdp_tiddel: PDP not found\n");
+ return EOF; /* End of linked list and not found */
}
-int pdp_tidget(struct pdp_t **pdp, uint64_t tid) {
- int hash = pdp_tidhash(tid);
- struct pdp_t *pdp2;
- if (PDP_DEBUG) printf("Begin pdp_tidget tid = %llx\n", tid);
- for (pdp2 = hashtid[hash]; pdp2; pdp2 = pdp2->tidnext) {
- if (pdp2->tid == tid) {
- *pdp = pdp2;
- if (PDP_DEBUG) printf("Begin pdp_tidget. Found\n");
- return 0;
- }
- }
- if (PDP_DEBUG) printf("Begin pdp_tidget. Not found\n");
- return EOF; /* End of linked list and not found */
+int pdp_tidget(struct pdp_t **pdp, uint64_t tid)
+{
+ int hash = pdp_tidhash(tid);
+ struct pdp_t *pdp2;
+ if (PDP_DEBUG)
+ printf("Begin pdp_tidget tid = %llx\n", tid);
+ for (pdp2 = hashtid[hash]; pdp2; pdp2 = pdp2->tidnext) {
+ if (pdp2->tid == tid) {
+ *pdp = pdp2;
+ if (PDP_DEBUG)
+ printf("Begin pdp_tidget. Found\n");
+ return 0;
+ }
+ }
+ if (PDP_DEBUG)
+ printf("Begin pdp_tidget. Not found\n");
+ return EOF; /* End of linked list and not found */
}
-int pdp_getimsi(struct pdp_t **pdp, uint64_t imsi, uint8_t nsapi) {
- return pdp_tidget(pdp,
- (imsi & 0x0fffffffffffffffull) + ((uint64_t)nsapi << 60));
+int pdp_getimsi(struct pdp_t **pdp, uint64_t imsi, uint8_t nsapi)
+{
+ return pdp_tidget(pdp,
+ (imsi & 0x0fffffffffffffffull) +
+ ((uint64_t) nsapi << 60));
}
/*
@@ -320,32 +347,36 @@ int pdp_ipget(struct pdp_t **pdp, void* ipif, struct ul66_t *eua) {
*/
/* Various conversion functions */
-int pdp_ntoeua(struct in_addr *src, struct ul66_t *eua) {
- eua->l=6;
- eua->v[0]=0xf1; /* IETF */
- eua->v[1]=0x21; /* IPv4 */
- memcpy(&eua->v[2], src, 4); /* Copy a 4 byte address */
- return 0;
+int pdp_ntoeua(struct in_addr *src, struct ul66_t *eua)
+{
+ eua->l = 6;
+ eua->v[0] = 0xf1; /* IETF */
+ eua->v[1] = 0x21; /* IPv4 */
+ memcpy(&eua->v[2], src, 4); /* Copy a 4 byte address */
+ return 0;
}
-int pdp_euaton(struct ul66_t *eua, struct in_addr *dst) {
- if((eua->l!=6) || (eua->v[0]!=0xf1) || (eua->v[1]!=0x21)) {
- return EOF;
- }
- memcpy(dst, &eua->v[2], 4); /* Copy a 4 byte address */
- return 0;
+int pdp_euaton(struct ul66_t *eua, struct in_addr *dst)
+{
+ if ((eua->l != 6) || (eua->v[0] != 0xf1) || (eua->v[1] != 0x21)) {
+ return EOF;
+ }
+ memcpy(dst, &eua->v[2], 4); /* Copy a 4 byte address */
+ return 0;
}
-uint64_t pdp_gettid(uint64_t imsi, uint8_t nsapi) {
- return (imsi & 0x0fffffffffffffffull) + ((uint64_t)nsapi << 60);
+uint64_t pdp_gettid(uint64_t imsi, uint8_t nsapi)
+{
+ return (imsi & 0x0fffffffffffffffull) + ((uint64_t) nsapi << 60);
}
-int ulcpy(void* dst, void* src, size_t size) {
- if (((struct ul255_t*)src)->l <= size) {
- ((struct ul255_t*)dst)->l = ((struct ul255_t*)src)->l;
- memcpy(((struct ul255_t*)dst)->v, ((struct ul255_t*)src)->v,
- ((struct ul255_t*)dst)->l);
- return 0;
- }
- else return EOF;
+int ulcpy(void *dst, void *src, size_t size)
+{
+ if (((struct ul255_t *)src)->l <= size) {
+ ((struct ul255_t *)dst)->l = ((struct ul255_t *)src)->l;
+ memcpy(((struct ul255_t *)dst)->v, ((struct ul255_t *)src)->v,
+ ((struct ul255_t *)dst)->l);
+ return 0;
+ } else
+ return EOF;
}
diff --git a/gtp/pdp.h b/gtp/pdp.h
index e3bd06d..b069a6f 100644
--- a/gtp/pdp.h
+++ b/gtp/pdp.h
@@ -12,42 +12,40 @@
#ifndef _PDP_H
#define _PDP_H
-#define PDP_MAX 1024 /* Max number of PDP contexts */
-#define PDP_MAXNSAPI 16 /* Max number of NSAPI */
+#define PDP_MAX 1024 /* Max number of PDP contexts */
+#define PDP_MAXNSAPI 16 /* Max number of NSAPI */
-#define PDP_DEBUG 0 /* Print debug information */
+#define PDP_DEBUG 0 /* Print debug information */
/* GTP Information elements from 29.060 v3.9.0 7.7 Information Elements */
/* Also covers version 0. Note that version 0 6: QOS Profile was superceded *
* by 135: QOS Profile in version 1 */
-
struct sl_t {
-unsigned int l;
-char *v;
+ unsigned int l;
+ char *v;
};
struct ul_t {
-unsigned int l;
-unsigned char *v;
+ unsigned int l;
+ unsigned char *v;
};
struct ul16_t {
-unsigned int l;
-unsigned char v[16];
+ unsigned int l;
+ unsigned char v[16];
};
struct ul66_t {
-unsigned int l;
-unsigned char v[66];
+ unsigned int l;
+ unsigned char v[66];
};
struct ul255_t {
-unsigned int l;
-unsigned char v[255];
+ unsigned int l;
+ unsigned char v[255];
};
-
/* *****************************************************************
* Information storage for each PDP context
*
@@ -103,131 +101,130 @@ unsigned char v[255];
*****************************************************************/
struct pdp_t {
- /* Parameter determining if this PDP is in use. */
- uint8_t inuse; /* 0=free. 1=used by somebody */
-
- /* Pointers related to hash tables */
- struct pdp_t *tidnext;
- struct pdp_t *ipnext;
-
- /* Parameters shared by all PDP context belonging to the same MS */
-
- void *ipif; /* IP network interface */
- void *peer; /* Pointer to peer protocol */
- void *asap; /* Application specific service access point */
-
- uint64_t imsi; /* International Mobile Subscriber Identity.*/
- struct ul16_t msisdn; /* The basic MSISDN of the MS. */
- uint8_t mnrg; /* Indicates whether the MS is marked as not reachable for PS at the HLR. (1 bit, not transmitted) */
- uint8_t cch_sub; /* The charging characteristics for the MS, e.g. normal, prepaid, flat-rate, and/or hot billing subscription. (not transmitted) */
- uint16_t traceref; /* Identifies a record or a collection of records for a particular trace. */
- uint16_t tracetype;/* Indicates the type of trace. */
- struct ul_t triggerid;/* Identifies the entity that initiated the trace. */
- struct ul_t omcid; /* Identifies the OMC that shall receive the trace record(s). */
- uint8_t rec_hlr; /* Indicates if HLR or VLR is performing database recovery. (1 bit, not transmitted) */
-
- /* Parameters specific to each individual PDP context */
-
- uint8_t pdp_id; /* Index of the PDP context. (PDP context identifier) */
- uint8_t pdp_state;/* PDP State Packet data protocol state, INACTIVE or ACTIVE. (1 bit, not transmitted) */
- /* struct ul_t pdp_type; * PDP type; e.g. PPP or IP. */
- /* struct ul_t pdp_addr; * PDP address; e.g. an IP address. */
- struct ul66_t eua; /* End user address. PDP type and address combined */
- uint8_t pdp_dyn; /* Indicates whether PDP Address is static or dynamic. (1 bit, not transmitted) */
- struct ul255_t apn_req;/* The APN requested. */
- struct ul255_t apn_sub;/* The APN received from the HLR. */
- struct ul255_t apn_use;/* The APN Network Identifier currently used. */
- uint8_t nsapi; /* Network layer Service Access Point Identifier. (4 bit) */
- uint16_t ti; /* Transaction Identifier. (4 or 12 bit) */
-
- uint32_t teic_own; /* (Own Tunnel Endpoint Identifier Control) */
- uint32_t teid_own; /* (Own Tunnel Endpoint Identifier Data I) */
- uint32_t teic_gn; /* Tunnel Endpoint Identifier for the Gn and Gp interfaces. (Control plane) */
- uint32_t teid_gn; /* Tunnel Endpoint Identifier for the Gn and Gp interfaces. (Data I) */
- uint32_t tei_iu; /* Tunnel Endpoint Identifier for the Iu interface. */
-
- uint16_t fllc; /* (Local Flow Label Control, gtp0) */
- uint16_t fllu; /* (Local Flow Label Data I, gtp0) */
- uint16_t flrc; /* (Remote gn/gp Flow Label Control, gtp0) */
- uint16_t flru; /* (Remote gn/gp Flow Label Data I, gtp0) */
-
- struct ul255_t tft; /* Traffic flow template. */
- /*struct ul16_t sgsnc; * The IP address of the SGSN currently serving this MS. (Control plane) */
- /*struct ul16_t sgsnu; * The IP address of the SGSN currently serving this MS. (User plane) */
- /*struct ul16_t ggsnc; * The IP address of the GGSN currently used. (Control plane) */
- /*struct ul16_t ggsnu; * The IP address of the GGSN currently used. (User plane) */
-
- struct ul16_t gsnlc; /* The IP address of the local GSN. (Control plane) */
- struct ul16_t gsnlu; /* The IP address of the local GSN. (User plane) */
- struct ul16_t gsnrc; /* The IP address of the remote GSN. (Control plane) */
- struct ul16_t gsnru; /* The IP address of the remote GSN. (User plane) */
-
- uint8_t vplmn_allow; /* Specifies whether the MS is allowed to use the APN in the domain of the HPLMN only, or additionally the APN in the domain of the VPLMN. (1 bit) */
- uint8_t qos_sub0[3]; /* The quality of service profile subscribed. */
- uint8_t qos_req0[3]; /* The quality of service profile requested. */
- uint8_t qos_neg0[3]; /* The quality of service profile negotiated. */
- struct ul255_t qos_sub; /* The quality of service profile subscribed. */
- struct ul255_t qos_req; /* The quality of service profile requested. */
- struct ul255_t qos_neg; /* The quality of service profile negotiated. */
- uint8_t radio_pri;/* The RLC/MAC radio priority level for uplink user data transmission. (4 bit) */
- uint16_t flow_id; /* Packet flow identifier. */
- /* struct ul_t bssqos_neg; * The aggregate BSS quality of service profile negotiated for the packet flow that this PDP context belongs to. (NOT GTP)*/
- uint8_t sndcpd; /* SNDCP sequence number of the next downlink N-PDU to be sent to the MS. */
- uint8_t sndcpu; /* SNDCP sequence number of the next uplink N-PDU expected from the MS. */
- uint8_t rec_sgsn; /* Indicates if the SGSN is performing database recovery. (1 bit, not transmitted) */
+ /* Parameter determining if this PDP is in use. */
+ uint8_t inuse; /* 0=free. 1=used by somebody */
+
+ /* Pointers related to hash tables */
+ struct pdp_t *tidnext;
+ struct pdp_t *ipnext;
+
+ /* Parameters shared by all PDP context belonging to the same MS */
+
+ void *ipif; /* IP network interface */
+ void *peer; /* Pointer to peer protocol */
+ void *asap; /* Application specific service access point */
+
+ uint64_t imsi; /* International Mobile Subscriber Identity. */
+ struct ul16_t msisdn; /* The basic MSISDN of the MS. */
+ uint8_t mnrg; /* Indicates whether the MS is marked as not reachable for PS at the HLR. (1 bit, not transmitted) */
+ uint8_t cch_sub; /* The charging characteristics for the MS, e.g. normal, prepaid, flat-rate, and/or hot billing subscription. (not transmitted) */
+ uint16_t traceref; /* Identifies a record or a collection of records for a particular trace. */
+ uint16_t tracetype; /* Indicates the type of trace. */
+ struct ul_t triggerid; /* Identifies the entity that initiated the trace. */
+ struct ul_t omcid; /* Identifies the OMC that shall receive the trace record(s). */
+ uint8_t rec_hlr; /* Indicates if HLR or VLR is performing database recovery. (1 bit, not transmitted) */
+
+ /* Parameters specific to each individual PDP context */
+
+ uint8_t pdp_id; /* Index of the PDP context. (PDP context identifier) */
+ uint8_t pdp_state; /* PDP State Packet data protocol state, INACTIVE or ACTIVE. (1 bit, not transmitted) */
+ /* struct ul_t pdp_type; * PDP type; e.g. PPP or IP. */
+ /* struct ul_t pdp_addr; * PDP address; e.g. an IP address. */
+ struct ul66_t eua; /* End user address. PDP type and address combined */
+ uint8_t pdp_dyn; /* Indicates whether PDP Address is static or dynamic. (1 bit, not transmitted) */
+ struct ul255_t apn_req; /* The APN requested. */
+ struct ul255_t apn_sub; /* The APN received from the HLR. */
+ struct ul255_t apn_use; /* The APN Network Identifier currently used. */
+ uint8_t nsapi; /* Network layer Service Access Point Identifier. (4 bit) */
+ uint16_t ti; /* Transaction Identifier. (4 or 12 bit) */
+
+ uint32_t teic_own; /* (Own Tunnel Endpoint Identifier Control) */
+ uint32_t teid_own; /* (Own Tunnel Endpoint Identifier Data I) */
+ uint32_t teic_gn; /* Tunnel Endpoint Identifier for the Gn and Gp interfaces. (Control plane) */
+ uint32_t teid_gn; /* Tunnel Endpoint Identifier for the Gn and Gp interfaces. (Data I) */
+ uint32_t tei_iu; /* Tunnel Endpoint Identifier for the Iu interface. */
+
+ uint16_t fllc; /* (Local Flow Label Control, gtp0) */
+ uint16_t fllu; /* (Local Flow Label Data I, gtp0) */
+ uint16_t flrc; /* (Remote gn/gp Flow Label Control, gtp0) */
+ uint16_t flru; /* (Remote gn/gp Flow Label Data I, gtp0) */
+
+ struct ul255_t tft; /* Traffic flow template. */
+ /*struct ul16_t sgsnc; * The IP address of the SGSN currently serving this MS. (Control plane) */
+ /*struct ul16_t sgsnu; * The IP address of the SGSN currently serving this MS. (User plane) */
+ /*struct ul16_t ggsnc; * The IP address of the GGSN currently used. (Control plane) */
+ /*struct ul16_t ggsnu; * The IP address of the GGSN currently used. (User plane) */
+
+ struct ul16_t gsnlc; /* The IP address of the local GSN. (Control plane) */
+ struct ul16_t gsnlu; /* The IP address of the local GSN. (User plane) */
+ struct ul16_t gsnrc; /* The IP address of the remote GSN. (Control plane) */
+ struct ul16_t gsnru; /* The IP address of the remote GSN. (User plane) */
+
+ uint8_t vplmn_allow; /* Specifies whether the MS is allowed to use the APN in the domain of the HPLMN only, or additionally the APN in the domain of the VPLMN. (1 bit) */
+ uint8_t qos_sub0[3]; /* The quality of service profile subscribed. */
+ uint8_t qos_req0[3]; /* The quality of service profile requested. */
+ uint8_t qos_neg0[3]; /* The quality of service profile negotiated. */
+ struct ul255_t qos_sub; /* The quality of service profile subscribed. */
+ struct ul255_t qos_req; /* The quality of service profile requested. */
+ struct ul255_t qos_neg; /* The quality of service profile negotiated. */
+ uint8_t radio_pri; /* The RLC/MAC radio priority level for uplink user data transmission. (4 bit) */
+ uint16_t flow_id; /* Packet flow identifier. */
+ /* struct ul_t bssqos_neg; * The aggregate BSS quality of service profile negotiated for the packet flow that this PDP context belongs to. (NOT GTP) */
+ uint8_t sndcpd; /* SNDCP sequence number of the next downlink N-PDU to be sent to the MS. */
+ uint8_t sndcpu; /* SNDCP sequence number of the next uplink N-PDU expected from the MS. */
+ uint8_t rec_sgsn; /* Indicates if the SGSN is performing database recovery. (1 bit, not transmitted) */
/* uint16_t gtpsnd; GTP-U sequence number of the next downlink N-PDU to be sent to the SGSN / received from the GGSN. */
/* uint16_t gtpsnu; GTP-U sequence number of the next uplink N-PDU to be received from the SGSN / sent to the GGSN */
- uint16_t gtpsntx; /* GTP-U sequence number of the next downlink N-PDU to be sent (09.60 section 8.1.1.1) */
- uint16_t gtpsnrx; /* GTP-U sequence number of the next uplink N-PDU to be received (09.60 section 8.1.1.1) */
- uint8_t pdcpsndd; /* Sequence number of the next downlink in-sequence PDCP-PDU to be sent to the MS. */
- uint8_t pdcpsndu; /* Sequence number of the next uplink in-sequence PDCP-PDU expected from the MS. */
- uint32_t cid; /* Charging identifier, identifies charging records generated by SGSN and GGSN. */
- uint16_t cch_pdp; /* The charging characteristics for this PDP context, e.g. normal, prepaid, flat-rate, and/or hot billing. */
- struct ul16_t rnc_addr;/* The IP address of the RNC currently used. */
- uint8_t reorder; /* Specifies whether the GGSN shall reorder N-PDUs received from the SGSN / Specifies whether the SGSN shall reorder N-PDUs before delivering the N-PSUs to the MS. (1 bit) */
- 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 rai; /* Routing Area Information */
- int rai_given; /* Routing Area 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*/
- int norecovery_given; /* norecovery given*/
-
- /* Additional parameters used by library */
-
- int version; /* Protocol version currently in use. 0 or 1 */
-
- uint64_t tid; /* Combination of imsi and nsapi */
- uint16_t seq; /* Sequence number of last request */
- struct sockaddr_in sa_peer; /* Address of last request */
- int fd; /* File descriptor request was received on */
-
- uint8_t teic_confirmed; /* 0: Not confirmed. 1: Confirmed */
-
- /* Parameters used for secondary activation procedure (tei data) */
- /* If (secondary == 1) then teic_own indicates linked PDP context */
- uint8_t secondary; /* 0: Primary (control). 1: Secondary (data only) */
- uint8_t nodata; /* 0: User plane PDP context. 1: No user plane */
-
- /* Secondary contexts of this primary context */
- uint32_t secondary_tei[PDP_MAXNSAPI];
-
- /* IP address used for Create and Update PDP Context Requests */
- struct in_addr hisaddr0; /* Server address */
- struct in_addr hisaddr1; /* Server address */
-
- /* to be used by libgtp callers/users (to attach their own private state) */
- void *priv;
+ uint16_t gtpsntx; /* GTP-U sequence number of the next downlink N-PDU to be sent (09.60 section 8.1.1.1) */
+ uint16_t gtpsnrx; /* GTP-U sequence number of the next uplink N-PDU to be received (09.60 section 8.1.1.1) */
+ uint8_t pdcpsndd; /* Sequence number of the next downlink in-sequence PDCP-PDU to be sent to the MS. */
+ uint8_t pdcpsndu; /* Sequence number of the next uplink in-sequence PDCP-PDU expected from the MS. */
+ uint32_t cid; /* Charging identifier, identifies charging records generated by SGSN and GGSN. */
+ uint16_t cch_pdp; /* The charging characteristics for this PDP context, e.g. normal, prepaid, flat-rate, and/or hot billing. */
+ struct ul16_t rnc_addr; /* The IP address of the RNC currently used. */
+ uint8_t reorder; /* Specifies whether the GGSN shall reorder N-PDUs received from the SGSN / Specifies whether the SGSN shall reorder N-PDUs before delivering the N-PSUs to the MS. (1 bit) */
+ 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 rai; /* Routing Area Information */
+ int rai_given; /* Routing Area 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 */
+ int norecovery_given; /* norecovery given */
+
+ /* Additional parameters used by library */
+
+ int version; /* Protocol version currently in use. 0 or 1 */
+
+ uint64_t tid; /* Combination of imsi and nsapi */
+ uint16_t seq; /* Sequence number of last request */
+ struct sockaddr_in sa_peer; /* Address of last request */
+ int fd; /* File descriptor request was received on */
+
+ uint8_t teic_confirmed; /* 0: Not confirmed. 1: Confirmed */
+
+ /* Parameters used for secondary activation procedure (tei data) */
+ /* If (secondary == 1) then teic_own indicates linked PDP context */
+ uint8_t secondary; /* 0: Primary (control). 1: Secondary (data only) */
+ uint8_t nodata; /* 0: User plane PDP context. 1: No user plane */
+
+ /* Secondary contexts of this primary context */
+ uint32_t secondary_tei[PDP_MAXNSAPI];
+
+ /* IP address used for Create and Update PDP Context Requests */
+ struct in_addr hisaddr0; /* Server address */
+ struct in_addr hisaddr1; /* Server address */
+
+ /* to be used by libgtp callers/users (to attach their own private state) */
+ void *priv;
};
-
/* functions related to pdp_t management */
int pdp_init();
int pdp_newpdp(struct pdp_t **pdp, uint64_t imsi, uint8_t nsapi,
@@ -245,7 +242,6 @@ int pdp_tidset(struct pdp_t *pdp, uint64_t tid);
int pdp_tiddel(struct pdp_t *pdp);
int pdp_tidget(struct pdp_t **pdp, uint64_t tid);
-
/*
int pdp_iphash(void* ipif, struct ul66_t *eua);
int pdp_ipset(struct pdp_t *pdp, void* ipif, struct ul66_t *eua);
@@ -256,6 +252,6 @@ int pdp_ipget(struct pdp_t **pdp, void* ipif, struct ul66_t *eua);
int pdp_ntoeua(struct in_addr *src, struct ul66_t *eua);
int pdp_euaton(struct ul66_t *eua, struct in_addr *dst);
uint64_t pdp_gettid(uint64_t imsi, uint8_t nsapi);
-int ulcpy(void* dst, void* src, size_t size);
+int ulcpy(void *dst, void *src, size_t size);
-#endif /* !_PDP_H */
+#endif /* !_PDP_H */
diff --git a/gtp/queue.c b/gtp/queue.c
index 7fdf9df..02c18ec 100644
--- a/gtp/queue.c
+++ b/gtp/queue.c
@@ -29,224 +29,260 @@
#include "gtp.h"
#include "queue.h"
-int queue_print(struct queue_t *queue) {
- int n;
- printf("Queue: %x Next: %d First: %d Last: %d\n", (int) queue, queue->next, queue->first, queue->last);
- printf("# State seq next prev timeout retrans\n");
- for (n=0; n<QUEUE_SIZE; n++) {
- printf("%d %d %d %d %d %d %d\n",
- n,
- queue->qmsga[n].state,
- queue->qmsga[n].seq,
- queue->qmsga[n].next,
- queue->qmsga[n].prev,
- (int) queue->qmsga[n].timeout,
- queue->qmsga[n].retrans);
- }
- return 0;
+int queue_print(struct queue_t *queue)
+{
+ int n;
+ printf("Queue: %x Next: %d First: %d Last: %d\n", (int)queue,
+ queue->next, queue->first, queue->last);
+ printf("# State seq next prev timeout retrans\n");
+ for (n = 0; n < QUEUE_SIZE; n++) {
+ printf("%d %d %d %d %d %d %d\n",
+ n,
+ queue->qmsga[n].state,
+ queue->qmsga[n].seq,
+ queue->qmsga[n].next,
+ queue->qmsga[n].prev,
+ (int)queue->qmsga[n].timeout, queue->qmsga[n].retrans);
+ }
+ return 0;
}
-int queue_seqhash(struct sockaddr_in *peer, uint16_t seq) {
- /* With QUEUE_HASH_SIZE = 2^16 this describes all possible
- seq values. Thus we have perfect hash for the request queue.
- For the response queue we might have collisions, but not very
- often.
- For performance optimisation we should remove the modulus
- operator, but this is only valid for QUEUE_HASH_SIZE = 2^16 */
- return seq % QUEUE_HASH_SIZE;
+int queue_seqhash(struct sockaddr_in *peer, uint16_t seq)
+{
+ /* With QUEUE_HASH_SIZE = 2^16 this describes all possible
+ seq values. Thus we have perfect hash for the request queue.
+ For the response queue we might have collisions, but not very
+ often.
+ For performance optimisation we should remove the modulus
+ operator, but this is only valid for QUEUE_HASH_SIZE = 2^16 */
+ return seq % QUEUE_HASH_SIZE;
}
int queue_seqset(struct queue_t *queue, struct qmsg_t *qmsg,
- struct sockaddr_in *peer, uint16_t seq) {
- int hash = queue_seqhash(peer, seq);
- struct qmsg_t *qmsg2;
- struct qmsg_t *qmsg_prev = NULL;
-
- if (QUEUE_DEBUG) printf("Begin queue_seqset seq = %d\n", (int) seq);
- if (QUEUE_DEBUG) printf("SIZEOF PEER %d, *PEER %d\n", sizeof(peer), sizeof(*peer));
-
- qmsg->seq = seq;
- memcpy(&qmsg->peer, peer, sizeof(*peer));
-
- for (qmsg2 = queue->hashseq[hash]; qmsg2; qmsg2 = qmsg2->seqnext)
- qmsg_prev = qmsg2;
- if (!qmsg_prev)
- queue->hashseq[hash] = qmsg;
- else
- qmsg_prev->seqnext = qmsg;
- if (QUEUE_DEBUG) printf("End queue_seqset\n");
- return 0;
-}
+ struct sockaddr_in *peer, uint16_t seq)
+{
+ int hash = queue_seqhash(peer, seq);
+ struct qmsg_t *qmsg2;
+ struct qmsg_t *qmsg_prev = NULL;
+
+ if (QUEUE_DEBUG)
+ printf("Begin queue_seqset seq = %d\n", (int)seq);
+ if (QUEUE_DEBUG)
+ printf("SIZEOF PEER %d, *PEER %d\n", sizeof(peer),
+ sizeof(*peer));
+ qmsg->seq = seq;
+ memcpy(&qmsg->peer, peer, sizeof(*peer));
-int queue_seqdel(struct queue_t *queue, struct qmsg_t *qmsg) {
- int hash = queue_seqhash(&qmsg->peer, qmsg->seq);
- struct qmsg_t *qmsg2;
- struct qmsg_t *qmsg_prev = NULL;
- if (QUEUE_DEBUG) printf("Begin queue_seqdel seq = %d\n", (int) qmsg->seq);
-
- for (qmsg2 = queue->hashseq[hash]; qmsg2; qmsg2 = qmsg2->seqnext) {
- if (qmsg == qmsg) {
- if (!qmsg_prev)
- queue->hashseq[hash] = qmsg2->seqnext;
- else
- qmsg_prev->seqnext = qmsg2->seqnext;
- if (QUEUE_DEBUG) printf("End queue_seqset: SEQ found\n");
- return 0;
- }
- qmsg_prev = qmsg2;
- }
- printf("End queue_seqset: SEQ not found\n");
- return EOF; /* End of linked list and not found */
+ for (qmsg2 = queue->hashseq[hash]; qmsg2; qmsg2 = qmsg2->seqnext)
+ qmsg_prev = qmsg2;
+ if (!qmsg_prev)
+ queue->hashseq[hash] = qmsg;
+ else
+ qmsg_prev->seqnext = qmsg;
+ if (QUEUE_DEBUG)
+ printf("End queue_seqset\n");
+ return 0;
}
+int queue_seqdel(struct queue_t *queue, struct qmsg_t *qmsg)
+{
+ int hash = queue_seqhash(&qmsg->peer, qmsg->seq);
+ struct qmsg_t *qmsg2;
+ struct qmsg_t *qmsg_prev = NULL;
+ if (QUEUE_DEBUG)
+ printf("Begin queue_seqdel seq = %d\n", (int)qmsg->seq);
+
+ for (qmsg2 = queue->hashseq[hash]; qmsg2; qmsg2 = qmsg2->seqnext) {
+ if (qmsg == qmsg) {
+ if (!qmsg_prev)
+ queue->hashseq[hash] = qmsg2->seqnext;
+ else
+ qmsg_prev->seqnext = qmsg2->seqnext;
+ if (QUEUE_DEBUG)
+ printf("End queue_seqset: SEQ found\n");
+ return 0;
+ }
+ qmsg_prev = qmsg2;
+ }
+ printf("End queue_seqset: SEQ not found\n");
+ return EOF; /* End of linked list and not found */
+}
/* Allocates and initialises new queue structure */
-int queue_new(struct queue_t **queue) {
- if (QUEUE_DEBUG) printf("queue_new\n");
- *queue = calloc(1, sizeof(struct queue_t));
- (*queue)->next = 0;
- (*queue)->first = -1;
- (*queue)->last = -1;
-
- if (QUEUE_DEBUG) queue_print(*queue);
- if (*queue) return 0;
- else return EOF;
+int queue_new(struct queue_t **queue)
+{
+ if (QUEUE_DEBUG)
+ printf("queue_new\n");
+ *queue = calloc(1, sizeof(struct queue_t));
+ (*queue)->next = 0;
+ (*queue)->first = -1;
+ (*queue)->last = -1;
+
+ if (QUEUE_DEBUG)
+ queue_print(*queue);
+ if (*queue)
+ return 0;
+ else
+ return EOF;
}
/* Deallocates queue structure */
-int queue_free(struct queue_t *queue) {
- if (QUEUE_DEBUG) printf("queue_free\n");
- if (QUEUE_DEBUG) queue_print(queue);
- free(queue);
- return 0;
+int queue_free(struct queue_t *queue)
+{
+ if (QUEUE_DEBUG)
+ printf("queue_free\n");
+ if (QUEUE_DEBUG)
+ queue_print(queue);
+ free(queue);
+ return 0;
}
int queue_newmsg(struct queue_t *queue, struct qmsg_t **qmsg,
- struct sockaddr_in *peer, uint16_t seq) {
- if (QUEUE_DEBUG) printf("queue_newmsg %d\n", (int) seq);
- if (queue->qmsga[queue->next].state == 1) {
- return EOF; /* Queue is full */
- }
- else {
- *qmsg = &queue->qmsga[queue->next];
- queue_seqset(queue, *qmsg, peer, seq);
- (*qmsg)->state = 1; /* Space taken */
- (*qmsg)->this = queue->next;
- (*qmsg)->next=-1; /* End of the queue */
- (*qmsg)->prev=queue->last; /* Link to the previous */
- if (queue->last != -1)
- queue->qmsga[queue->last].next=queue->next; /* Link previous to us */
- queue->last = queue->next; /* End of queue */
- if (queue->first == -1) queue->first = queue->next;
- queue->next = (queue->next+1) % QUEUE_SIZE; /* Increment */
- if (QUEUE_DEBUG) queue_print(queue);
- return 0;
- }
+ struct sockaddr_in *peer, uint16_t seq)
+{
+ if (QUEUE_DEBUG)
+ printf("queue_newmsg %d\n", (int)seq);
+ if (queue->qmsga[queue->next].state == 1) {
+ return EOF; /* Queue is full */
+ } else {
+ *qmsg = &queue->qmsga[queue->next];
+ queue_seqset(queue, *qmsg, peer, seq);
+ (*qmsg)->state = 1; /* Space taken */
+ (*qmsg)->this = queue->next;
+ (*qmsg)->next = -1; /* End of the queue */
+ (*qmsg)->prev = queue->last; /* Link to the previous */
+ if (queue->last != -1)
+ queue->qmsga[queue->last].next = queue->next; /* Link previous to us */
+ queue->last = queue->next; /* End of queue */
+ if (queue->first == -1)
+ queue->first = queue->next;
+ queue->next = (queue->next + 1) % QUEUE_SIZE; /* Increment */
+ if (QUEUE_DEBUG)
+ queue_print(queue);
+ return 0;
+ }
}
-int queue_freemsg(struct queue_t *queue, struct qmsg_t *qmsg) {
- if (QUEUE_DEBUG) printf("queue_freemsg\n");
- if (qmsg->state != 1) {
- return EOF; /* Not in queue */
- }
+int queue_freemsg(struct queue_t *queue, struct qmsg_t *qmsg)
+{
+ if (QUEUE_DEBUG)
+ printf("queue_freemsg\n");
+ if (qmsg->state != 1) {
+ return EOF; /* Not in queue */
+ }
- queue_seqdel(queue, qmsg);
+ queue_seqdel(queue, qmsg);
- if (qmsg->next == -1) /* Are we the last in queue? */
- queue->last = qmsg->prev;
- else
- queue->qmsga[qmsg->next].prev = qmsg->prev;
-
- if (qmsg->prev == -1) /* Are we the first in queue? */
- queue->first = qmsg->next;
- else
- queue->qmsga[qmsg->prev].next = qmsg->next;
+ if (qmsg->next == -1) /* Are we the last in queue? */
+ queue->last = qmsg->prev;
+ else
+ queue->qmsga[qmsg->next].prev = qmsg->prev;
- memset(qmsg, 0, sizeof(struct qmsg_t)); /* Just to be safe */
+ if (qmsg->prev == -1) /* Are we the first in queue? */
+ queue->first = qmsg->next;
+ else
+ queue->qmsga[qmsg->prev].next = qmsg->next;
- if (QUEUE_DEBUG) queue_print(queue);
+ memset(qmsg, 0, sizeof(struct qmsg_t)); /* Just to be safe */
- return 0;
+ if (QUEUE_DEBUG)
+ queue_print(queue);
+
+ return 0;
}
-int queue_back(struct queue_t *queue, struct qmsg_t *qmsg) {
- if (QUEUE_DEBUG) printf("queue_back\n");
- if (qmsg->state != 1) {
- return EOF; /* Not in queue */
- }
-
- /* Insert stuff to maintain hash table */
-
- if (qmsg->next != -1) {/* Only swop if there are others */
- queue->qmsga[qmsg->next].prev = qmsg->prev;
- queue->first = qmsg->next;
-
- qmsg->next = -1;
- qmsg->prev = queue->last;
- if (queue->last != -1) queue->qmsga[queue->last].next = qmsg->this;
- queue->last = qmsg->this;
- }
- if (QUEUE_DEBUG) queue_print(queue);
- return 0;
+int queue_back(struct queue_t *queue, struct qmsg_t *qmsg)
+{
+ if (QUEUE_DEBUG)
+ printf("queue_back\n");
+ if (qmsg->state != 1) {
+ return EOF; /* Not in queue */
+ }
+
+ /* Insert stuff to maintain hash table */
+
+ if (qmsg->next != -1) { /* Only swop if there are others */
+ queue->qmsga[qmsg->next].prev = qmsg->prev;
+ queue->first = qmsg->next;
+
+ qmsg->next = -1;
+ qmsg->prev = queue->last;
+ if (queue->last != -1)
+ queue->qmsga[queue->last].next = qmsg->this;
+ queue->last = qmsg->this;
+ }
+ if (QUEUE_DEBUG)
+ queue_print(queue);
+ return 0;
}
/* Get the element with a particular sequence number */
-int queue_getfirst(struct queue_t *queue, struct qmsg_t **qmsg) {
- /*printf("queue_getfirst\n");*/
- if (queue->first == -1) {
- *qmsg = NULL;
- return EOF; /* End of queue = queue is empty. */
- }
- *qmsg = &queue->qmsga[queue->first];
- if (QUEUE_DEBUG) queue_print(queue);
- return 0;
+int queue_getfirst(struct queue_t *queue, struct qmsg_t **qmsg)
+{
+ /*printf("queue_getfirst\n"); */
+ if (queue->first == -1) {
+ *qmsg = NULL;
+ return EOF; /* End of queue = queue is empty. */
+ }
+ *qmsg = &queue->qmsga[queue->first];
+ if (QUEUE_DEBUG)
+ queue_print(queue);
+ return 0;
}
int queue_getseqx(struct queue_t *queue, struct qmsg_t **qmsg,
- struct sockaddr_in *peer, uint16_t seq) {
- int n;
- if (QUEUE_DEBUG) printf("queue_getseq, %d\n", (int) seq);
- if (QUEUE_DEBUG) queue_print(queue);
- for (n=0; n<QUEUE_SIZE; n++) {
- if ((queue->qmsga[n].seq == seq) &&
- (!memcmp(&queue->qmsga[n].peer, peer, sizeof(*peer)))) {
- *qmsg = &queue->qmsga[n];
- return 0;
- }
- }
- return EOF; /* Not found */
+ struct sockaddr_in *peer, uint16_t seq)
+{
+ int n;
+ if (QUEUE_DEBUG)
+ printf("queue_getseq, %d\n", (int)seq);
+ if (QUEUE_DEBUG)
+ queue_print(queue);
+ for (n = 0; n < QUEUE_SIZE; n++) {
+ if ((queue->qmsga[n].seq == seq) &&
+ (!memcmp(&queue->qmsga[n].peer, peer, sizeof(*peer)))) {
+ *qmsg = &queue->qmsga[n];
+ return 0;
+ }
+ }
+ return EOF; /* Not found */
}
int queue_seqget(struct queue_t *queue, struct qmsg_t **qmsg,
- struct sockaddr_in *peer, uint16_t seq) {
- int hash = queue_seqhash(peer, seq);
- struct qmsg_t *qmsg2;
- if (QUEUE_DEBUG) printf("Begin queue_seqget seq = %d\n", (int) seq);
- for (qmsg2 = queue->hashseq[hash]; qmsg2; qmsg2 = qmsg2->seqnext) {
- if ((qmsg2->seq == seq) &&
- (!memcmp(&qmsg2->peer, peer, sizeof(*peer)))) {
- *qmsg = qmsg2;
- if (QUEUE_DEBUG) printf("End queue_seqget. Found\n");
- return 0;
- }
- }
- if (QUEUE_DEBUG) printf("End queue_seqget. Not found\n");
- return EOF; /* End of linked list and not found */
+ struct sockaddr_in *peer, uint16_t seq)
+{
+ int hash = queue_seqhash(peer, seq);
+ struct qmsg_t *qmsg2;
+ if (QUEUE_DEBUG)
+ printf("Begin queue_seqget seq = %d\n", (int)seq);
+ for (qmsg2 = queue->hashseq[hash]; qmsg2; qmsg2 = qmsg2->seqnext) {
+ if ((qmsg2->seq == seq) &&
+ (!memcmp(&qmsg2->peer, peer, sizeof(*peer)))) {
+ *qmsg = qmsg2;
+ if (QUEUE_DEBUG)
+ printf("End queue_seqget. Found\n");
+ return 0;
+ }
+ }
+ if (QUEUE_DEBUG)
+ printf("End queue_seqget. Not found\n");
+ return EOF; /* End of linked list and not found */
}
-int queue_freemsg_seq(struct queue_t *queue, struct sockaddr_in *peer,
- uint16_t seq, uint8_t *type, void **cbp) {
- struct qmsg_t *qmsg;
- if (queue_seqget(queue, &qmsg, peer, seq)) {
- *cbp = NULL;
- *type = 0;
- return EOF;
- }
- *cbp = qmsg->cbp;
- *type = qmsg->type;
- if (queue_freemsg(queue, qmsg)) {
- return EOF;
- }
- return 0;
+int queue_freemsg_seq(struct queue_t *queue, struct sockaddr_in *peer,
+ uint16_t seq, uint8_t * type, void **cbp)
+{
+ struct qmsg_t *qmsg;
+ if (queue_seqget(queue, &qmsg, peer, seq)) {
+ *cbp = NULL;
+ *type = 0;
+ return EOF;
+ }
+ *cbp = qmsg->cbp;
+ *type = qmsg->type;
+ if (queue_freemsg(queue, qmsg)) {
+ return EOF;
+ }
+ return 0;
}
diff --git a/gtp/queue.h b/gtp/queue.h
index 46fa22d..556b6ef 100644
--- a/gtp/queue.h
+++ b/gtp/queue.h
@@ -17,37 +17,36 @@
#ifndef _QUEUE_H
#define _QUEUE_H
-#define QUEUE_DEBUG 0 /* Print debug information */
+#define QUEUE_DEBUG 0 /* Print debug information */
-#define QUEUE_SIZE 1024 /* Size of retransmission queue */
-#define QUEUE_HASH_SIZE 65536 /* Size of hash table (2^16) */
+#define QUEUE_SIZE 1024 /* Size of retransmission queue */
+#define QUEUE_HASH_SIZE 65536 /* Size of hash table (2^16) */
-struct qmsg_t { /* Holder for queued packets */
- int state; /* 0=empty, 1=full */
- uint16_t seq; /* The sequence number */
- uint8_t type; /* The type of packet */
- void *cbp; /* Application specific pointer */
- union gtp_packet p; /* The packet stored */
- int l; /* Length of the packet */
- int fd; /* Socket packet was sent to / received from */
- struct sockaddr_in peer;/* Address packet was sent to / received from */
- struct qmsg_t *seqnext; /* Pointer to next in sequence hash list */
- int next; /* Pointer to the next in queue. -1: Last */
- int prev; /* Pointer to the previous in queue. -1: First */
- int this; /* Pointer to myself */
- time_t timeout; /* When do we retransmit this packet? */
- int retrans; /* How many times did we retransmit this? */
+struct qmsg_t { /* Holder for queued packets */
+ int state; /* 0=empty, 1=full */
+ uint16_t seq; /* The sequence number */
+ uint8_t type; /* The type of packet */
+ void *cbp; /* Application specific pointer */
+ union gtp_packet p; /* The packet stored */
+ int l; /* Length of the packet */
+ int fd; /* Socket packet was sent to / received from */
+ struct sockaddr_in peer; /* Address packet was sent to / received from */
+ struct qmsg_t *seqnext; /* Pointer to next in sequence hash list */
+ int next; /* Pointer to the next in queue. -1: Last */
+ int prev; /* Pointer to the previous in queue. -1: First */
+ int this; /* Pointer to myself */
+ time_t timeout; /* When do we retransmit this packet? */
+ int retrans; /* How many times did we retransmit this? */
};
struct queue_t {
- struct qmsg_t qmsga[QUEUE_SIZE]; /* Array holding signalling messages */
- void *hashseq[QUEUE_HASH_SIZE]; /* Hash array */
- int next; /* Next location in queue to use */
- int first; /* First packet in queue (oldest timeout) */
- int last; /* Last packet in queue (youngest timeout) */
+ struct qmsg_t qmsga[QUEUE_SIZE]; /* Array holding signalling messages */
+ void *hashseq[QUEUE_HASH_SIZE]; /* Hash array */
+ int next; /* Next location in queue to use */
+ int first; /* First packet in queue (oldest timeout) */
+ int last; /* Last packet in queue (youngest timeout) */
};
-
/* Allocates and initialises new queue structure */
int queue_new(struct queue_t **queue);
/* Deallocates queue structure */
@@ -63,11 +62,9 @@ int queue_back(struct queue_t *queue, struct qmsg_t *qmsg);
int queue_getfirst(struct queue_t *queue, struct qmsg_t **qmsg);
/* Get the element with a particular sequence number */
int queue_seqget(struct queue_t *queue, struct qmsg_t **qmsg,
- struct sockaddr_in *peer, uint16_t seq);
+ struct sockaddr_in *peer, uint16_t seq);
/* Free message based on sequence number */
int queue_freemsg_seq(struct queue_t *queue, struct sockaddr_in *peer,
- uint16_t seq, uint8_t *type, void **cbp);
-
-
-#endif /* !_QUEUE_H */
+ uint16_t seq, uint8_t * type, void **cbp);
+#endif /* !_QUEUE_H */
diff --git a/lib/getopt.c b/lib/getopt.c
index 9bafa45..f6e2a8e 100644
--- a/lib/getopt.c
+++ b/lib/getopt.c
@@ -24,19 +24,19 @@
/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
Ditto for AIX 3.2 and <stdlib.h>. */
#ifndef _NO_PROTO
-# define _NO_PROTO
+#define _NO_PROTO
#endif
#ifdef HAVE_CONFIG_H
-# include <config.h>
+#include <config.h>
#endif
#if !defined __STDC__ || !__STDC__
/* This is a separate conditional since some stdc systems
reject `defined (const)'. */
-# ifndef const
-# define const
-# endif
+#ifndef const
+#define const
+#endif
#endif
#include <stdio.h>
@@ -51,41 +51,40 @@
#define GETOPT_INTERFACE_VERSION 2
#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
-# include <gnu-versions.h>
-# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
-# define ELIDE_CODE
-# endif
+#include <gnu-versions.h>
+#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
+#define ELIDE_CODE
+#endif
#endif
#ifndef ELIDE_CODE
-
/* This needs to come after some library #include
to get __GNU_LIBRARY__ defined. */
#ifdef __GNU_LIBRARY__
/* Don't include stdlib.h for non-GNU C libraries because some of them
contain conflicting prototypes for getopt. */
-# include <stdlib.h>
-# include <unistd.h>
-#endif /* GNU C library. */
+#include <stdlib.h>
+#include <unistd.h>
+#endif /* GNU C library. */
#ifdef VMS
-# include <unixlib.h>
-# if HAVE_STRING_H - 0
-# include <string.h>
-# endif
+#include <unixlib.h>
+#if HAVE_STRING_H - 0
+#include <string.h>
+#endif
#endif
#ifndef _
/* This is for other GNU distributions with internationalized messages. */
-# if defined HAVE_LIBINTL_H || defined _LIBC
-# include <libintl.h>
-# ifndef _
-# define _(msgid) gettext (msgid)
-# endif
-# else
-# define _(msgid) (msgid)
-# endif
+#if defined HAVE_LIBINTL_H || defined _LIBC
+#include <libintl.h>
+#ifndef _
+#define _(msgid) gettext (msgid)
+#endif
+#else
+#define _(msgid) (msgid)
+#endif
#endif
/* This version of `getopt' appears to the caller like standard Unix `getopt'
@@ -182,9 +181,8 @@ int optopt = '?';
of the value of `ordering'. In the case of RETURN_IN_ORDER, only
`--' can cause `getopt' to return -1 with `optind' != ARGC. */
-static enum
-{
- REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+static enum {
+ REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
} ordering;
/* Value of POSIXLY_CORRECT environment variable. */
@@ -195,35 +193,33 @@ static char *posixly_correct;
because there are many ways it can cause trouble.
On some systems, it contains special magic macros that don't work
in GCC. */
-# include <string.h>
-# define my_index strchr
+#include <string.h>
+#define my_index strchr
#else
-# if HAVE_STRING_H
-# include <string.h>
-# else
-# include <strings.h>
-# endif
+#if HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
/* Avoid depending on library functions or files
whose names are inconsistent. */
#ifndef getenv
-extern char *getenv ();
+extern char *getenv();
#endif
-static char *
-my_index (str, chr)
- const char *str;
- int chr;
+static char *my_index(str, chr)
+const char *str;
+int chr;
{
- while (*str)
- {
- if (*str == chr)
- return (char *) str;
- str++;
- }
- return 0;
+ while (*str) {
+ if (*str == chr)
+ return (char *)str;
+ str++;
+ }
+ return 0;
}
/* If using GCC, we can safely declare strlen this way.
@@ -231,11 +227,11 @@ my_index (str, chr)
#ifdef __GNUC__
/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
That was relevant to code that was here before. */
-# if (!defined __STDC__ || !__STDC__) && !defined strlen
+#if (!defined __STDC__ || !__STDC__) && !defined strlen
/* gcc with -traditional declares the built-in strlen to return int,
and has done so at least since version 2.4.5. -- rms. */
-extern int strlen (const char *);
-# endif /* not __STDC__ */
+extern int strlen(const char *);
+#endif /* not __STDC__ */
#endif /* __GNUC__ */
#endif /* not __GNU_LIBRARY__ */
@@ -259,28 +255,28 @@ extern char **__libc_argv;
/* Bash 2.0 gives us an environment variable containing flags
indicating ARGV elements that should not be considered arguments. */
-# ifdef USE_NONOPTION_FLAGS
+#ifdef USE_NONOPTION_FLAGS
/* Defined in getopt_init.c */
extern char *__getopt_nonoption_flags;
static int nonoption_flags_max_len;
static int nonoption_flags_len;
-# endif
+#endif
-# ifdef USE_NONOPTION_FLAGS
-# define SWAP_FLAGS(ch1, ch2) \
+#ifdef USE_NONOPTION_FLAGS
+#define SWAP_FLAGS(ch1, ch2) \
if (nonoption_flags_len > 0) \
{ \
char __tmp = __getopt_nonoption_flags[ch1]; \
__getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \
__getopt_nonoption_flags[ch2] = __tmp; \
}
-# else
-# define SWAP_FLAGS(ch1, ch2)
-# endif
-#else /* !_LIBC */
-# define SWAP_FLAGS(ch1, ch2)
-#endif /* _LIBC */
+#else
+#define SWAP_FLAGS(ch1, ch2)
+#endif
+#else /* !_LIBC */
+#define SWAP_FLAGS(ch1, ch2)
+#endif /* _LIBC */
/* Exchange two adjacent subsequences of ARGV.
One subsequence is elements [first_nonopt,last_nonopt)
@@ -292,158 +288,145 @@ static int nonoption_flags_len;
the new indices of the non-options in ARGV after they are moved. */
#if defined __STDC__ && __STDC__
-static void exchange (char **);
+static void exchange(char **);
#endif
-static void
-exchange (argv)
- char **argv;
+static void exchange(argv)
+char **argv;
{
- int bottom = first_nonopt;
- int middle = last_nonopt;
- int top = optind;
- char *tem;
+ int bottom = first_nonopt;
+ int middle = last_nonopt;
+ int top = optind;
+ char *tem;
- /* Exchange the shorter segment with the far end of the longer segment.
- That puts the shorter segment into the right place.
- It leaves the longer segment in the right place overall,
- but it consists of two parts that need to be swapped next. */
+ /* Exchange the shorter segment with the far end of the longer segment.
+ That puts the shorter segment into the right place.
+ It leaves the longer segment in the right place overall,
+ but it consists of two parts that need to be swapped next. */
#if defined _LIBC && defined USE_NONOPTION_FLAGS
- /* First make sure the handling of the `__getopt_nonoption_flags'
- string can work normally. Our top argument must be in the range
- of the string. */
- if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len)
- {
- /* We must extend the array. The user plays games with us and
- presents new arguments. */
- char *new_str = malloc (top + 1);
- if (new_str == NULL)
- nonoption_flags_len = nonoption_flags_max_len = 0;
- else
- {
- memset (__mempcpy (new_str, __getopt_nonoption_flags,
- nonoption_flags_max_len),
- '\0', top + 1 - nonoption_flags_max_len);
- nonoption_flags_max_len = top + 1;
- __getopt_nonoption_flags = new_str;
+ /* First make sure the handling of the `__getopt_nonoption_flags'
+ string can work normally. Our top argument must be in the range
+ of the string. */
+ if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) {
+ /* We must extend the array. The user plays games with us and
+ presents new arguments. */
+ char *new_str = malloc(top + 1);
+ if (new_str == NULL)
+ nonoption_flags_len = nonoption_flags_max_len = 0;
+ else {
+ memset(__mempcpy(new_str, __getopt_nonoption_flags,
+ nonoption_flags_max_len),
+ '\0', top + 1 - nonoption_flags_max_len);
+ nonoption_flags_max_len = top + 1;
+ __getopt_nonoption_flags = new_str;
+ }
}
- }
#endif
- while (top > middle && middle > bottom)
- {
- if (top - middle > middle - bottom)
- {
- /* Bottom segment is the short one. */
- int len = middle - bottom;
- register int i;
-
- /* Swap it with the top part of the top segment. */
- for (i = 0; i < len; i++)
- {
- tem = argv[bottom + i];
- argv[bottom + i] = argv[top - (middle - bottom) + i];
- argv[top - (middle - bottom) + i] = tem;
- SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
- }
- /* Exclude the moved bottom segment from further swapping. */
- top -= len;
- }
- else
- {
- /* Top segment is the short one. */
- int len = top - middle;
- register int i;
-
- /* Swap it with the bottom part of the bottom segment. */
- for (i = 0; i < len; i++)
- {
- tem = argv[bottom + i];
- argv[bottom + i] = argv[middle + i];
- argv[middle + i] = tem;
- SWAP_FLAGS (bottom + i, middle + i);
- }
- /* Exclude the moved top segment from further swapping. */
- bottom += len;
+ while (top > middle && middle > bottom) {
+ if (top - middle > middle - bottom) {
+ /* Bottom segment is the short one. */
+ int len = middle - bottom;
+ register int i;
+
+ /* Swap it with the top part of the top segment. */
+ for (i = 0; i < len; i++) {
+ tem = argv[bottom + i];
+ argv[bottom + i] =
+ argv[top - (middle - bottom) + i];
+ argv[top - (middle - bottom) + i] = tem;
+ SWAP_FLAGS(bottom + i,
+ top - (middle - bottom) + i);
+ }
+ /* Exclude the moved bottom segment from further swapping. */
+ top -= len;
+ } else {
+ /* Top segment is the short one. */
+ int len = top - middle;
+ register int i;
+
+ /* Swap it with the bottom part of the bottom segment. */
+ for (i = 0; i < len; i++) {
+ tem = argv[bottom + i];
+ argv[bottom + i] = argv[middle + i];
+ argv[middle + i] = tem;
+ SWAP_FLAGS(bottom + i, middle + i);
+ }
+ /* Exclude the moved top segment from further swapping. */
+ bottom += len;
+ }
}
- }
- /* Update records for the slots the non-options now occupy. */
+ /* Update records for the slots the non-options now occupy. */
- first_nonopt += (optind - last_nonopt);
- last_nonopt = optind;
+ first_nonopt += (optind - last_nonopt);
+ last_nonopt = optind;
}
/* Initialize the internal data when the first call is made. */
#if defined __STDC__ && __STDC__
-static const char *_getopt_initialize (int, char *const *, const char *);
+static const char *_getopt_initialize(int, char *const *, const char *);
#endif
-static const char *
-_getopt_initialize (argc, argv, optstring)
- int argc;
- char *const *argv;
- const char *optstring;
+static const char *_getopt_initialize(argc, argv, optstring)
+int argc;
+char *const *argv;
+const char *optstring;
{
- /* Start processing options with ARGV-element 1 (since ARGV-element 0
- is the program name); the sequence of previously skipped
- non-option ARGV-elements is empty. */
+ /* Start processing options with ARGV-element 1 (since ARGV-element 0
+ is the program name); the sequence of previously skipped
+ non-option ARGV-elements is empty. */
- first_nonopt = last_nonopt = optind;
+ first_nonopt = last_nonopt = optind;
- nextchar = NULL;
+ nextchar = NULL;
- posixly_correct = getenv ("POSIXLY_CORRECT");
+ posixly_correct = getenv("POSIXLY_CORRECT");
- /* Determine how to handle the ordering of options and nonoptions. */
+ /* Determine how to handle the ordering of options and nonoptions. */
- if (optstring[0] == '-')
- {
- ordering = RETURN_IN_ORDER;
- ++optstring;
- }
- else if (optstring[0] == '+')
- {
- ordering = REQUIRE_ORDER;
- ++optstring;
- }
- else if (posixly_correct != NULL)
- ordering = REQUIRE_ORDER;
- else
- ordering = PERMUTE;
+ if (optstring[0] == '-') {
+ ordering = RETURN_IN_ORDER;
+ ++optstring;
+ } else if (optstring[0] == '+') {
+ ordering = REQUIRE_ORDER;
+ ++optstring;
+ } else if (posixly_correct != NULL)
+ ordering = REQUIRE_ORDER;
+ else
+ ordering = PERMUTE;
#if defined _LIBC && defined USE_NONOPTION_FLAGS
- if (posixly_correct == NULL
- && argc == __libc_argc && argv == __libc_argv)
- {
- if (nonoption_flags_max_len == 0)
- {
- if (__getopt_nonoption_flags == NULL
- || __getopt_nonoption_flags[0] == '\0')
- nonoption_flags_max_len = -1;
- else
- {
- const char *orig_str = __getopt_nonoption_flags;
- int len = nonoption_flags_max_len = strlen (orig_str);
- if (nonoption_flags_max_len < argc)
- nonoption_flags_max_len = argc;
- __getopt_nonoption_flags =
- (char *) malloc (nonoption_flags_max_len);
- if (__getopt_nonoption_flags == NULL)
- nonoption_flags_max_len = -1;
- else
- memset (__mempcpy (__getopt_nonoption_flags, orig_str, len),
- '\0', nonoption_flags_max_len - len);
- }
- }
- nonoption_flags_len = nonoption_flags_max_len;
- }
- else
- nonoption_flags_len = 0;
+ if (posixly_correct == NULL
+ && argc == __libc_argc && argv == __libc_argv) {
+ if (nonoption_flags_max_len == 0) {
+ if (__getopt_nonoption_flags == NULL
+ || __getopt_nonoption_flags[0] == '\0')
+ nonoption_flags_max_len = -1;
+ else {
+ const char *orig_str = __getopt_nonoption_flags;
+ int len = nonoption_flags_max_len =
+ strlen(orig_str);
+ if (nonoption_flags_max_len < argc)
+ nonoption_flags_max_len = argc;
+ __getopt_nonoption_flags =
+ (char *)malloc(nonoption_flags_max_len);
+ if (__getopt_nonoption_flags == NULL)
+ nonoption_flags_max_len = -1;
+ else
+ memset(__mempcpy
+ (__getopt_nonoption_flags,
+ orig_str, len), '\0',
+ nonoption_flags_max_len - len);
+ }
+ }
+ nonoption_flags_len = nonoption_flags_max_len;
+ } else
+ nonoption_flags_len = 0;
#endif
- return optstring;
+ return optstring;
}
/* Scan elements of ARGV (whose length is ARGC) for option characters
@@ -502,554 +485,527 @@ _getopt_initialize (argc, argv, optstring)
If LONG_ONLY is nonzero, '-' as well as '--' can introduce
long-named options. */
-int
-_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
- int argc;
- char *const *argv;
- const char *optstring;
- const struct option *longopts;
- int *longind;
- int long_only;
+int _getopt_internal(argc, argv, optstring, longopts, longind, long_only)
+int argc;
+char *const *argv;
+const char *optstring;
+const struct option *longopts;
+int *longind;
+int long_only;
{
- int print_errors = opterr;
- if (optstring[0] == ':')
- print_errors = 0;
+ int print_errors = opterr;
+ if (optstring[0] == ':')
+ print_errors = 0;
- if (argc < 1)
- return -1;
+ if (argc < 1)
+ return -1;
- optarg = NULL;
+ optarg = NULL;
- if (optind == 0 || !__getopt_initialized)
- {
- if (optind == 0)
- optind = 1; /* Don't scan ARGV[0], the program name. */
- optstring = _getopt_initialize (argc, argv, optstring);
- __getopt_initialized = 1;
- }
+ if (optind == 0 || !__getopt_initialized) {
+ if (optind == 0)
+ optind = 1; /* Don't scan ARGV[0], the program name. */
+ optstring = _getopt_initialize(argc, argv, optstring);
+ __getopt_initialized = 1;
+ }
- /* Test whether ARGV[optind] points to a non-option argument.
- Either it does not have option syntax, or there is an environment flag
- from the shell indicating it is not an option. The later information
- is only used when the used in the GNU libc. */
+ /* Test whether ARGV[optind] points to a non-option argument.
+ Either it does not have option syntax, or there is an environment flag
+ from the shell indicating it is not an option. The later information
+ is only used when the used in the GNU libc. */
#if defined _LIBC && defined USE_NONOPTION_FLAGS
-# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \
+#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \
|| (optind < nonoption_flags_len \
&& __getopt_nonoption_flags[optind] == '1'))
#else
-# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0')
+#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0')
#endif
- if (nextchar == NULL || *nextchar == '\0')
- {
- /* Advance to the next ARGV-element. */
-
- /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
- moved back by the user (who may also have changed the arguments). */
- if (last_nonopt > optind)
- last_nonopt = optind;
- if (first_nonopt > optind)
- first_nonopt = optind;
+ if (nextchar == NULL || *nextchar == '\0') {
+ /* Advance to the next ARGV-element. */
- if (ordering == PERMUTE)
- {
- /* If we have just processed some options following some non-options,
- exchange them so that the options come first. */
+ /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
+ moved back by the user (who may also have changed the arguments). */
+ if (last_nonopt > optind)
+ last_nonopt = optind;
+ if (first_nonopt > optind)
+ first_nonopt = optind;
- if (first_nonopt != last_nonopt && last_nonopt != optind)
- exchange ((char **) argv);
- else if (last_nonopt != optind)
- first_nonopt = optind;
+ if (ordering == PERMUTE) {
+ /* If we have just processed some options following some non-options,
+ exchange them so that the options come first. */
- /* Skip any additional non-options
- and extend the range of non-options previously skipped. */
+ if (first_nonopt != last_nonopt
+ && last_nonopt != optind)
+ exchange((char **)argv);
+ else if (last_nonopt != optind)
+ first_nonopt = optind;
- while (optind < argc && NONOPTION_P)
- optind++;
- last_nonopt = optind;
- }
+ /* Skip any additional non-options
+ and extend the range of non-options previously skipped. */
- /* The special ARGV-element `--' means premature end of options.
- Skip it like a null option,
- then exchange with previous non-options as if it were an option,
- then skip everything else like a non-option. */
+ while (optind < argc && NONOPTION_P)
+ optind++;
+ last_nonopt = optind;
+ }
- if (optind != argc && !strcmp (argv[optind], "--"))
- {
- optind++;
+ /* The special ARGV-element `--' means premature end of options.
+ Skip it like a null option,
+ then exchange with previous non-options as if it were an option,
+ then skip everything else like a non-option. */
- if (first_nonopt != last_nonopt && last_nonopt != optind)
- exchange ((char **) argv);
- else if (first_nonopt == last_nonopt)
- first_nonopt = optind;
- last_nonopt = argc;
+ if (optind != argc && !strcmp(argv[optind], "--")) {
+ optind++;
- optind = argc;
- }
+ if (first_nonopt != last_nonopt
+ && last_nonopt != optind)
+ exchange((char **)argv);
+ else if (first_nonopt == last_nonopt)
+ first_nonopt = optind;
+ last_nonopt = argc;
- /* If we have done all the ARGV-elements, stop the scan
- and back over any non-options that we skipped and permuted. */
+ optind = argc;
+ }
- if (optind == argc)
- {
- /* Set the next-arg-index to point at the non-options
- that we previously skipped, so the caller will digest them. */
- if (first_nonopt != last_nonopt)
- optind = first_nonopt;
- return -1;
- }
+ /* If we have done all the ARGV-elements, stop the scan
+ and back over any non-options that we skipped and permuted. */
- /* If we have come to a non-option and did not permute it,
- either stop the scan or describe it to the caller and pass it by. */
+ if (optind == argc) {
+ /* Set the next-arg-index to point at the non-options
+ that we previously skipped, so the caller will digest them. */
+ if (first_nonopt != last_nonopt)
+ optind = first_nonopt;
+ return -1;
+ }
- if (NONOPTION_P)
- {
- if (ordering == REQUIRE_ORDER)
- return -1;
- optarg = argv[optind++];
- return 1;
- }
+ /* If we have come to a non-option and did not permute it,
+ either stop the scan or describe it to the caller and pass it by. */
- /* We have found another option-ARGV-element.
- Skip the initial punctuation. */
+ if (NONOPTION_P) {
+ if (ordering == REQUIRE_ORDER)
+ return -1;
+ optarg = argv[optind++];
+ return 1;
+ }
- nextchar = (argv[optind] + 1
- + (longopts != NULL && argv[optind][1] == '-'));
- }
+ /* We have found another option-ARGV-element.
+ Skip the initial punctuation. */
- /* Decode the current option-ARGV-element. */
-
- /* Check whether the ARGV-element is a long option.
-
- If long_only and the ARGV-element has the form "-f", where f is
- a valid short option, don't consider it an abbreviated form of
- a long option that starts with f. Otherwise there would be no
- way to give the -f short option.
-
- On the other hand, if there's a long option "fubar" and
- the ARGV-element is "-fu", do consider that an abbreviation of
- the long option, just like "--fu", and not "-f" with arg "u".
-
- This distinction seems to be the most useful approach. */
-
- if (longopts != NULL
- && (argv[optind][1] == '-'
- || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
- {
- char *nameend;
- const struct option *p;
- const struct option *pfound = NULL;
- int exact = 0;
- int ambig = 0;
- int indfound = -1;
- int option_index;
-
- for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
- /* Do nothing. */ ;
-
- /* Test all long options for either exact match
- or abbreviated matches. */
- for (p = longopts, option_index = 0; p->name; p++, option_index++)
- if (!strncmp (p->name, nextchar, nameend - nextchar))
- {
- if ((unsigned int) (nameend - nextchar)
- == (unsigned int) strlen (p->name))
- {
- /* Exact match found. */
- pfound = p;
- indfound = option_index;
- exact = 1;
- break;
- }
- else if (pfound == NULL)
- {
- /* First nonexact match found. */
- pfound = p;
- indfound = option_index;
- }
- else if (long_only
- || pfound->has_arg != p->has_arg
- || pfound->flag != p->flag
- || pfound->val != p->val)
- /* Second or later nonexact match found. */
- ambig = 1;
- }
-
- if (ambig && !exact)
- {
- if (print_errors)
- fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
- argv[0], argv[optind]);
- nextchar += strlen (nextchar);
- optind++;
- optopt = 0;
- return '?';
+ nextchar = (argv[optind] + 1
+ + (longopts != NULL && argv[optind][1] == '-'));
}
- if (pfound != NULL)
- {
- option_index = indfound;
- optind++;
- if (*nameend)
- {
- /* Don't test has_arg with >, because some C compilers don't
- allow it to be used on enums. */
- if (pfound->has_arg)
- optarg = nameend + 1;
- else
- {
- if (print_errors)
- {
- if (argv[optind - 1][1] == '-')
- /* --option */
- fprintf (stderr,
- _("%s: option `--%s' doesn't allow an argument\n"),
- argv[0], pfound->name);
- else
- /* +option or -option */
- fprintf (stderr,
- _("%s: option `%c%s' doesn't allow an argument\n"),
- argv[0], argv[optind - 1][0], pfound->name);
- }
-
- nextchar += strlen (nextchar);
-
- optopt = pfound->val;
- return '?';
+ /* Decode the current option-ARGV-element. */
+
+ /* Check whether the ARGV-element is a long option.
+
+ If long_only and the ARGV-element has the form "-f", where f is
+ a valid short option, don't consider it an abbreviated form of
+ a long option that starts with f. Otherwise there would be no
+ way to give the -f short option.
+
+ On the other hand, if there's a long option "fubar" and
+ the ARGV-element is "-fu", do consider that an abbreviation of
+ the long option, just like "--fu", and not "-f" with arg "u".
+
+ This distinction seems to be the most useful approach. */
+
+ if (longopts != NULL
+ && (argv[optind][1] == '-'
+ || (long_only
+ && (argv[optind][2]
+ || !my_index(optstring, argv[optind][1]))))) {
+ char *nameend;
+ const struct option *p;
+ const struct option *pfound = NULL;
+ int exact = 0;
+ int ambig = 0;
+ int indfound = -1;
+ int option_index;
+
+ for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
+ /* Do nothing. */ ;
+
+ /* Test all long options for either exact match
+ or abbreviated matches. */
+ for (p = longopts, option_index = 0; p->name;
+ p++, option_index++)
+ if (!strncmp(p->name, nextchar, nameend - nextchar)) {
+ if ((unsigned int)(nameend - nextchar)
+ == (unsigned int)strlen(p->name)) {
+ /* Exact match found. */
+ pfound = p;
+ indfound = option_index;
+ exact = 1;
+ break;
+ } else if (pfound == NULL) {
+ /* First nonexact match found. */
+ pfound = p;
+ indfound = option_index;
+ } else if (long_only
+ || pfound->has_arg != p->has_arg
+ || pfound->flag != p->flag
+ || pfound->val != p->val)
+ /* Second or later nonexact match found. */
+ ambig = 1;
+ }
+
+ if (ambig && !exact) {
+ if (print_errors)
+ fprintf(stderr,
+ _("%s: option `%s' is ambiguous\n"),
+ argv[0], argv[optind]);
+ nextchar += strlen(nextchar);
+ optind++;
+ optopt = 0;
+ return '?';
}
- }
- else if (pfound->has_arg == 1)
- {
- if (optind < argc)
- optarg = argv[optind++];
- else
- {
- if (print_errors)
- fprintf (stderr,
- _("%s: option `%s' requires an argument\n"),
- argv[0], argv[optind - 1]);
- nextchar += strlen (nextchar);
- optopt = pfound->val;
- return optstring[0] == ':' ? ':' : '?';
+
+ if (pfound != NULL) {
+ option_index = indfound;
+ optind++;
+ if (*nameend) {
+ /* Don't test has_arg with >, because some C compilers don't
+ allow it to be used on enums. */
+ if (pfound->has_arg)
+ optarg = nameend + 1;
+ else {
+ if (print_errors) {
+ if (argv[optind - 1][1] == '-')
+ /* --option */
+ fprintf(stderr,
+ _
+ ("%s: option `--%s' doesn't allow an argument\n"),
+ argv[0],
+ pfound->name);
+ else
+ /* +option or -option */
+ fprintf(stderr,
+ _
+ ("%s: option `%c%s' doesn't allow an argument\n"),
+ argv[0],
+ argv[optind -
+ 1][0],
+ pfound->name);
+ }
+
+ nextchar += strlen(nextchar);
+
+ optopt = pfound->val;
+ return '?';
+ }
+ } else if (pfound->has_arg == 1) {
+ if (optind < argc)
+ optarg = argv[optind++];
+ else {
+ if (print_errors)
+ fprintf(stderr,
+ _
+ ("%s: option `%s' requires an argument\n"),
+ argv[0],
+ argv[optind - 1]);
+ nextchar += strlen(nextchar);
+ optopt = pfound->val;
+ return optstring[0] == ':' ? ':' : '?';
+ }
+ }
+ nextchar += strlen(nextchar);
+ if (longind != NULL)
+ *longind = option_index;
+ if (pfound->flag) {
+ *(pfound->flag) = pfound->val;
+ return 0;
+ }
+ return pfound->val;
}
- }
- nextchar += strlen (nextchar);
- if (longind != NULL)
- *longind = option_index;
- if (pfound->flag)
- {
- *(pfound->flag) = pfound->val;
- return 0;
- }
- return pfound->val;
- }
- /* Can't find it as a long option. If this is not getopt_long_only,
- or the option starts with '--' or is not a valid short
- option, then it's an error.
- Otherwise interpret it as a short option. */
- if (!long_only || argv[optind][1] == '-'
- || my_index (optstring, *nextchar) == NULL)
- {
- if (print_errors)
- {
- if (argv[optind][1] == '-')
- /* --option */
- fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
- argv[0], nextchar);
- else
- /* +option or -option */
- fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
- argv[0], argv[optind][0], nextchar);
- }
- nextchar = (char *) "";
- optind++;
- optopt = 0;
- return '?';
+ /* Can't find it as a long option. If this is not getopt_long_only,
+ or the option starts with '--' or is not a valid short
+ option, then it's an error.
+ Otherwise interpret it as a short option. */
+ if (!long_only || argv[optind][1] == '-'
+ || my_index(optstring, *nextchar) == NULL) {
+ if (print_errors) {
+ if (argv[optind][1] == '-')
+ /* --option */
+ fprintf(stderr,
+ _
+ ("%s: unrecognized option `--%s'\n"),
+ argv[0], nextchar);
+ else
+ /* +option or -option */
+ fprintf(stderr,
+ _
+ ("%s: unrecognized option `%c%s'\n"),
+ argv[0], argv[optind][0],
+ nextchar);
+ }
+ nextchar = (char *)"";
+ optind++;
+ optopt = 0;
+ return '?';
+ }
}
- }
- /* Look at and handle the next short option-character. */
-
- {
- char c = *nextchar++;
- char *temp = my_index (optstring, c);
-
- /* Increment `optind' when we start to process its last character. */
- if (*nextchar == '\0')
- ++optind;
-
- if (temp == NULL || c == ':')
- {
- if (print_errors)
- {
- if (posixly_correct)
- /* 1003.2 specifies the format of this message. */
- fprintf (stderr, _("%s: illegal option -- %c\n"),
- argv[0], c);
- else
- fprintf (stderr, _("%s: invalid option -- %c\n"),
- argv[0], c);
- }
- optopt = c;
- return '?';
- }
- /* Convenience. Treat POSIX -W foo same as long option --foo */
- if (temp[0] == 'W' && temp[1] == ';')
- {
- char *nameend;
- const struct option *p;
- const struct option *pfound = NULL;
- int exact = 0;
- int ambig = 0;
- int indfound = 0;
- int option_index;
-
- /* This is an option that requires an argument. */
- if (*nextchar != '\0')
- {
- optarg = nextchar;
- /* If we end this ARGV-element by taking the rest as an arg,
- we must advance to the next element now. */
- optind++;
- }
- else if (optind == argc)
- {
- if (print_errors)
- {
- /* 1003.2 specifies the format of this message. */
- fprintf (stderr, _("%s: option requires an argument -- %c\n"),
- argv[0], c);
- }
- optopt = c;
- if (optstring[0] == ':')
- c = ':';
- else
- c = '?';
- return c;
- }
- else
- /* We already incremented `optind' once;
- increment it again when taking next ARGV-elt as argument. */
- optarg = argv[optind++];
-
- /* optarg is now the argument, see if it's in the
- table of longopts. */
-
- for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++)
- /* Do nothing. */ ;
-
- /* Test all long options for either exact match
- or abbreviated matches. */
- for (p = longopts, option_index = 0; p->name; p++, option_index++)
- if (!strncmp (p->name, nextchar, nameend - nextchar))
- {
- if ((unsigned int) (nameend - nextchar) == strlen (p->name))
- {
- /* Exact match found. */
- pfound = p;
- indfound = option_index;
- exact = 1;
- break;
+ /* Look at and handle the next short option-character. */
+
+ {
+ char c = *nextchar++;
+ char *temp = my_index(optstring, c);
+
+ /* Increment `optind' when we start to process its last character. */
+ if (*nextchar == '\0')
+ ++optind;
+
+ if (temp == NULL || c == ':') {
+ if (print_errors) {
+ if (posixly_correct)
+ /* 1003.2 specifies the format of this message. */
+ fprintf(stderr,
+ _("%s: illegal option -- %c\n"),
+ argv[0], c);
+ else
+ fprintf(stderr,
+ _("%s: invalid option -- %c\n"),
+ argv[0], c);
+ }
+ optopt = c;
+ return '?';
}
- else if (pfound == NULL)
- {
- /* First nonexact match found. */
- pfound = p;
- indfound = option_index;
+ /* Convenience. Treat POSIX -W foo same as long option --foo */
+ if (temp[0] == 'W' && temp[1] == ';') {
+ char *nameend;
+ const struct option *p;
+ const struct option *pfound = NULL;
+ int exact = 0;
+ int ambig = 0;
+ int indfound = 0;
+ int option_index;
+
+ /* This is an option that requires an argument. */
+ if (*nextchar != '\0') {
+ optarg = nextchar;
+ /* If we end this ARGV-element by taking the rest as an arg,
+ we must advance to the next element now. */
+ optind++;
+ } else if (optind == argc) {
+ if (print_errors) {
+ /* 1003.2 specifies the format of this message. */
+ fprintf(stderr,
+ _
+ ("%s: option requires an argument -- %c\n"),
+ argv[0], c);
+ }
+ optopt = c;
+ if (optstring[0] == ':')
+ c = ':';
+ else
+ c = '?';
+ return c;
+ } else
+ /* We already incremented `optind' once;
+ increment it again when taking next ARGV-elt as argument. */
+ optarg = argv[optind++];
+
+ /* optarg is now the argument, see if it's in the
+ table of longopts. */
+
+ for (nextchar = nameend = optarg;
+ *nameend && *nameend != '='; nameend++)
+ /* Do nothing. */ ;
+
+ /* Test all long options for either exact match
+ or abbreviated matches. */
+ for (p = longopts, option_index = 0; p->name;
+ p++, option_index++)
+ if (!strncmp
+ (p->name, nextchar, nameend - nextchar)) {
+ if ((unsigned int)(nameend -
+ nextchar) ==
+ strlen(p->name)) {
+ /* Exact match found. */
+ pfound = p;
+ indfound = option_index;
+ exact = 1;
+ break;
+ } else if (pfound == NULL) {
+ /* First nonexact match found. */
+ pfound = p;
+ indfound = option_index;
+ } else
+ /* Second or later nonexact match found. */
+ ambig = 1;
+ }
+ if (ambig && !exact) {
+ if (print_errors)
+ fprintf(stderr,
+ _
+ ("%s: option `-W %s' is ambiguous\n"),
+ argv[0], argv[optind]);
+ nextchar += strlen(nextchar);
+ optind++;
+ return '?';
+ }
+ if (pfound != NULL) {
+ option_index = indfound;
+ if (*nameend) {
+ /* Don't test has_arg with >, because some C compilers don't
+ allow it to be used on enums. */
+ if (pfound->has_arg)
+ optarg = nameend + 1;
+ else {
+ if (print_errors)
+ fprintf(stderr, _("\
+%s: option `-W %s' doesn't allow an argument\n"), argv[0], pfound->name);
+
+ nextchar += strlen(nextchar);
+ return '?';
+ }
+ } else if (pfound->has_arg == 1) {
+ if (optind < argc)
+ optarg = argv[optind++];
+ else {
+ if (print_errors)
+ fprintf(stderr,
+ _
+ ("%s: option `%s' requires an argument\n"),
+ argv[0],
+ argv[optind -
+ 1]);
+ nextchar += strlen(nextchar);
+ return optstring[0] ==
+ ':' ? ':' : '?';
+ }
+ }
+ nextchar += strlen(nextchar);
+ if (longind != NULL)
+ *longind = option_index;
+ if (pfound->flag) {
+ *(pfound->flag) = pfound->val;
+ return 0;
+ }
+ return pfound->val;
+ }
+ nextchar = NULL;
+ return 'W'; /* Let the application handle it. */
}
- else
- /* Second or later nonexact match found. */
- ambig = 1;
- }
- if (ambig && !exact)
- {
- if (print_errors)
- fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"),
- argv[0], argv[optind]);
- nextchar += strlen (nextchar);
- optind++;
- return '?';
- }
- if (pfound != NULL)
- {
- option_index = indfound;
- if (*nameend)
- {
- /* Don't test has_arg with >, because some C compilers don't
- allow it to be used on enums. */
- if (pfound->has_arg)
- optarg = nameend + 1;
- else
- {
- if (print_errors)
- fprintf (stderr, _("\
-%s: option `-W %s' doesn't allow an argument\n"),
- argv[0], pfound->name);
-
- nextchar += strlen (nextchar);
- return '?';
- }
- }
- else if (pfound->has_arg == 1)
- {
- if (optind < argc)
- optarg = argv[optind++];
- else
- {
- if (print_errors)
- fprintf (stderr,
- _("%s: option `%s' requires an argument\n"),
- argv[0], argv[optind - 1]);
- nextchar += strlen (nextchar);
- return optstring[0] == ':' ? ':' : '?';
- }
- }
- nextchar += strlen (nextchar);
- if (longind != NULL)
- *longind = option_index;
- if (pfound->flag)
- {
- *(pfound->flag) = pfound->val;
- return 0;
- }
- return pfound->val;
- }
- nextchar = NULL;
- return 'W'; /* Let the application handle it. */
- }
- if (temp[1] == ':')
- {
- if (temp[2] == ':')
- {
- /* This is an option that accepts an argument optionally. */
- if (*nextchar != '\0')
- {
- optarg = nextchar;
- optind++;
- }
- else
- optarg = NULL;
- nextchar = NULL;
- }
- else
- {
- /* This is an option that requires an argument. */
- if (*nextchar != '\0')
- {
- optarg = nextchar;
- /* If we end this ARGV-element by taking the rest as an arg,
- we must advance to the next element now. */
- optind++;
- }
- else if (optind == argc)
- {
- if (print_errors)
- {
- /* 1003.2 specifies the format of this message. */
- fprintf (stderr,
- _("%s: option requires an argument -- %c\n"),
- argv[0], c);
- }
- optopt = c;
- if (optstring[0] == ':')
- c = ':';
- else
- c = '?';
- }
- else
- /* We already incremented `optind' once;
- increment it again when taking next ARGV-elt as argument. */
- optarg = argv[optind++];
- nextchar = NULL;
- }
- }
- return c;
- }
+ if (temp[1] == ':') {
+ if (temp[2] == ':') {
+ /* This is an option that accepts an argument optionally. */
+ if (*nextchar != '\0') {
+ optarg = nextchar;
+ optind++;
+ } else
+ optarg = NULL;
+ nextchar = NULL;
+ } else {
+ /* This is an option that requires an argument. */
+ if (*nextchar != '\0') {
+ optarg = nextchar;
+ /* If we end this ARGV-element by taking the rest as an arg,
+ we must advance to the next element now. */
+ optind++;
+ } else if (optind == argc) {
+ if (print_errors) {
+ /* 1003.2 specifies the format of this message. */
+ fprintf(stderr,
+ _
+ ("%s: option requires an argument -- %c\n"),
+ argv[0], c);
+ }
+ optopt = c;
+ if (optstring[0] == ':')
+ c = ':';
+ else
+ c = '?';
+ } else
+ /* We already incremented `optind' once;
+ increment it again when taking next ARGV-elt as argument. */
+ optarg = argv[optind++];
+ nextchar = NULL;
+ }
+ }
+ return c;
+ }
}
-int
-getopt (argc, argv, optstring)
- int argc;
- char *const *argv;
- const char *optstring;
+int getopt(argc, argv, optstring)
+int argc;
+char *const *argv;
+const char *optstring;
{
- return _getopt_internal (argc, argv, optstring,
- (const struct option *) 0,
- (int *) 0,
- 0);
+ return _getopt_internal(argc, argv, optstring,
+ (const struct option *)0, (int *)0, 0);
}
-#endif /* Not ELIDE_CODE. */
+#endif /* Not ELIDE_CODE. */
#ifdef TEST
/* Compile with -DTEST to make an executable for use in testing
the above definition of `getopt'. */
-int
-main (argc, argv)
- int argc;
- char **argv;
+int main(argc, argv)
+int argc;
+char **argv;
{
- int c;
- int digit_optind = 0;
-
- while (1)
- {
- int this_option_optind = optind ? optind : 1;
-
- c = getopt (argc, argv, "abc:d:0123456789");
- if (c == -1)
- break;
-
- switch (c)
- {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- if (digit_optind != 0 && digit_optind != this_option_optind)
- printf ("digits occur in two different argv-elements.\n");
- digit_optind = this_option_optind;
- printf ("option %c\n", c);
- break;
-
- case 'a':
- printf ("option a\n");
- break;
-
- case 'b':
- printf ("option b\n");
- break;
-
- case 'c':
- printf ("option c with value `%s'\n", optarg);
- break;
-
- case '?':
- break;
-
- default:
- printf ("?? getopt returned character code 0%o ??\n", c);
+ int c;
+ int digit_optind = 0;
+
+ while (1) {
+ int this_option_optind = optind ? optind : 1;
+
+ c = getopt(argc, argv, "abc:d:0123456789");
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0
+ && digit_optind != this_option_optind)
+ printf
+ ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf("option %c\n", c);
+ break;
+
+ case 'a':
+ printf("option a\n");
+ break;
+
+ case 'b':
+ printf("option b\n");
+ break;
+
+ case 'c':
+ printf("option c with value `%s'\n", optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf("?? getopt returned character code 0%o ??\n", c);
+ }
}
- }
- if (optind < argc)
- {
- printf ("non-option ARGV-elements: ");
- while (optind < argc)
- printf ("%s ", argv[optind++]);
- printf ("\n");
- }
+ if (optind < argc) {
+ printf("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf("%s ", argv[optind++]);
+ printf("\n");
+ }
- exit (0);
+ exit(0);
}
#endif /* TEST */
diff --git a/lib/getopt1.c b/lib/getopt1.c
index 22a7efb..c4e4190 100644
--- a/lib/getopt1.c
+++ b/lib/getopt1.c
@@ -52,7 +52,6 @@
#ifndef ELIDE_CODE
-
/* This needs to come after some library #include
to get __GNU_LIBRARY__ defined. */
#ifdef __GNU_LIBRARY__
@@ -63,15 +62,15 @@
#define NULL 0
#endif
-int
-getopt_long (argc, argv, options, long_options, opt_index)
- int argc;
- char *const *argv;
- const char *options;
- const struct option *long_options;
- int *opt_index;
+int getopt_long(argc, argv, options, long_options, opt_index)
+int argc;
+char *const *argv;
+const char *options;
+const struct option *long_options;
+int *opt_index;
{
- return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
+ return _getopt_internal(argc, argv, options, long_options, opt_index,
+ 0);
}
/* Like getopt_long, but '-' as well as '--' can indicate a long option.
@@ -79,110 +78,106 @@ getopt_long (argc, argv, options, long_options, opt_index)
but does match a short option, it is parsed as a short option
instead. */
-int
-getopt_long_only (argc, argv, options, long_options, opt_index)
- int argc;
- char *const *argv;
- const char *options;
- const struct option *long_options;
- int *opt_index;
+int getopt_long_only(argc, argv, options, long_options, opt_index)
+int argc;
+char *const *argv;
+const char *options;
+const struct option *long_options;
+int *opt_index;
{
- return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
+ return _getopt_internal(argc, argv, options, long_options, opt_index,
+ 1);
}
-
-#endif /* Not ELIDE_CODE. */
+#endif /* Not ELIDE_CODE. */
#ifdef TEST
#include <stdio.h>
-int
-main (argc, argv)
- int argc;
- char **argv;
+int main(argc, argv)
+int argc;
+char **argv;
{
- int c;
- int digit_optind = 0;
-
- while (1)
- {
- int this_option_optind = optind ? optind : 1;
- int option_index = 0;
- static struct option long_options[] =
- {
- {"add", 1, 0, 0},
- {"append", 0, 0, 0},
- {"delete", 1, 0, 0},
- {"verbose", 0, 0, 0},
- {"create", 0, 0, 0},
- {"file", 1, 0, 0},
- {0, 0, 0, 0}
- };
-
- c = getopt_long (argc, argv, "abc:d:0123456789",
- long_options, &option_index);
- if (c == -1)
- break;
-
- switch (c)
- {
- case 0:
- printf ("option %s", long_options[option_index].name);
- if (optarg)
- printf (" with arg %s", optarg);
- printf ("\n");
- break;
-
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- if (digit_optind != 0 && digit_optind != this_option_optind)
- printf ("digits occur in two different argv-elements.\n");
- digit_optind = this_option_optind;
- printf ("option %c\n", c);
- break;
-
- case 'a':
- printf ("option a\n");
- break;
-
- case 'b':
- printf ("option b\n");
- break;
-
- case 'c':
- printf ("option c with value `%s'\n", optarg);
- break;
-
- case 'd':
- printf ("option d with value `%s'\n", optarg);
- break;
-
- case '?':
- break;
-
- default:
- printf ("?? getopt returned character code 0%o ??\n", c);
+ int c;
+ int digit_optind = 0;
+
+ while (1) {
+ int this_option_optind = optind ? optind : 1;
+ int option_index = 0;
+ static struct option long_options[] = {
+ {"add", 1, 0, 0},
+ {"append", 0, 0, 0},
+ {"delete", 1, 0, 0},
+ {"verbose", 0, 0, 0},
+ {"create", 0, 0, 0},
+ {"file", 1, 0, 0},
+ {0, 0, 0, 0}
+ };
+
+ c = getopt_long(argc, argv, "abc:d:0123456789",
+ long_options, &option_index);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 0:
+ printf("option %s", long_options[option_index].name);
+ if (optarg)
+ printf(" with arg %s", optarg);
+ printf("\n");
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0
+ && digit_optind != this_option_optind)
+ printf
+ ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf("option %c\n", c);
+ break;
+
+ case 'a':
+ printf("option a\n");
+ break;
+
+ case 'b':
+ printf("option b\n");
+ break;
+
+ case 'c':
+ printf("option c with value `%s'\n", optarg);
+ break;
+
+ case 'd':
+ printf("option d with value `%s'\n", optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf("?? getopt returned character code 0%o ??\n", c);
+ }
}
- }
- if (optind < argc)
- {
- printf ("non-option ARGV-elements: ");
- while (optind < argc)
- printf ("%s ", argv[optind++]);
- printf ("\n");
- }
+ if (optind < argc) {
+ printf("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf("%s ", argv[optind++]);
+ printf("\n");
+ }
- exit (0);
+ exit(0);
}
#endif /* TEST */
diff --git a/lib/gnugetopt.h b/lib/gnugetopt.h
index a1b8dd6..31a693e 100644
--- a/lib/gnugetopt.h
+++ b/lib/gnugetopt.h
@@ -20,7 +20,7 @@
#ifndef _GETOPT_H
#ifndef __need_getopt
-# define _GETOPT_H 1
+#define _GETOPT_H 1
#endif
/* If __GNU_LIBRARY__ is not already defined, either we are being used
@@ -31,7 +31,7 @@
if it's from glibc. (Why ctype.h? It's guaranteed to exist and it
doesn't flood the namespace with stuff the way some other headers do.) */
#if !defined __GNU_LIBRARY__
-# include <ctype.h>
+#include <ctype.h>
#endif
#ifdef __cplusplus
@@ -44,7 +44,7 @@ extern "C" {
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
-extern char *optarg;
+ extern char *optarg;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
@@ -58,16 +58,16 @@ extern char *optarg;
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
-extern int optind;
+ extern int optind;
/* Callers store zero here to inhibit the error message `getopt' prints
for unrecognized options. */
-extern int opterr;
+ extern int opterr;
/* Set to an option character which was unrecognized. */
-extern int optopt;
+ extern int optopt;
#ifndef __need_getopt
/* Describe the long-named options requested by the application.
@@ -91,27 +91,25 @@ extern int optopt;
one). For long options that have a zero `flag' field, `getopt'
returns the contents of the `val' field. */
-struct option
-{
-# if (defined __STDC__ && __STDC__) || defined __cplusplus
- const char *name;
-# else
- char *name;
-# endif
- /* has_arg can't be an enum because some compilers complain about
- type mismatches in all the code that assumes it is an int. */
- int has_arg;
- int *flag;
- int val;
-};
+ struct option {
+#if (defined __STDC__ && __STDC__) || defined __cplusplus
+ const char *name;
+#else
+ char *name;
+#endif
+ /* has_arg can't be an enum because some compilers complain about
+ type mismatches in all the code that assumes it is an int. */
+ int has_arg;
+ int *flag;
+ int val;
+ };
/* Names for the values of the `has_arg' field of `struct option'. */
-# define no_argument 0
-# define required_argument 1
-# define optional_argument 2
-#endif /* need getopt */
-
+#define no_argument 0
+#define required_argument 1
+#define optional_argument 2
+#endif /* need getopt */
/* Get definitions and prototypes for functions to process the
arguments in ARGV (ARGC of them, minus the program name) for
@@ -138,43 +136,44 @@ struct option
`getopt'. */
#if (defined __STDC__ && __STDC__) || defined __cplusplus
-# ifdef __GNU_LIBRARY__
+#ifdef __GNU_LIBRARY__
/* Many other libraries have conflicting prototypes for getopt, with
differences in the consts, in stdlib.h. To avoid compilation
errors, only prototype getopt for the GNU C library. */
-extern int getopt (int __argc, char *const *__argv, const char *__shortopts);
-# else /* not __GNU_LIBRARY__ */
-extern int getopt ();
-# endif /* __GNU_LIBRARY__ */
-
-# ifndef __need_getopt
-extern int getopt_long (int __argc, char *const *__argv, const char *__shortopts,
- const struct option *__longopts, int *__longind);
-extern int getopt_long_only (int __argc, char *const *__argv,
- const char *__shortopts,
- const struct option *__longopts, int *__longind);
+ extern int getopt(int __argc, char *const *__argv,
+ const char *__shortopts);
+#else /* not __GNU_LIBRARY__ */
+ extern int getopt();
+#endif /* __GNU_LIBRARY__ */
+
+#ifndef __need_getopt
+ extern int getopt_long(int __argc, char *const *__argv,
+ const char *__shortopts,
+ const struct option *__longopts, int *__longind);
+ extern int getopt_long_only(int __argc, char *const *__argv,
+ const char *__shortopts,
+ const struct option *__longopts,
+ int *__longind);
/* Internal only. Users should not call this directly. */
-extern int _getopt_internal (int __argc, char *const *__argv,
- const char *__shortopts,
- const struct option *__longopts, int *__longind,
- int __long_only);
-# endif
-#else /* not __STDC__ */
-extern int getopt ();
-# ifndef __need_getopt
-extern int getopt_long ();
-extern int getopt_long_only ();
-
-extern int _getopt_internal ();
-# endif
-#endif /* __STDC__ */
+ extern int _getopt_internal(int __argc, char *const *__argv,
+ const char *__shortopts,
+ const struct option *__longopts,
+ int *__longind, int __long_only);
+#endif
+#else /* not __STDC__ */
+ extern int getopt();
+#ifndef __need_getopt
+ extern int getopt_long();
+ extern int getopt_long_only();
+
+ extern int _getopt_internal();
+#endif
+#endif /* __STDC__ */
#ifdef __cplusplus
}
#endif
-
/* Make sure we later can get all the definitions and declarations. */
#undef __need_getopt
-
-#endif /* getopt.h */
+#endif /* getopt.h */
diff --git a/lib/ippool.c b/lib/ippool.c
index fa3d8af..7ece1e8 100644
--- a/lib/ippool.c
+++ b/lib/ippool.c
@@ -10,9 +10,9 @@
*/
#include <sys/types.h>
-#include <netinet/in.h> /* in_addr */
-#include <stdlib.h> /* calloc */
-#include <stdio.h> /* sscanf */
+#include <netinet/in.h> /* in_addr */
+#include <stdlib.h> /* calloc */
+#include <stdio.h> /* sscanf */
#include <syslog.h>
#include <string.h>
#include <sys/socket.h>
@@ -21,312 +21,320 @@
#include "ippool.h"
#include "lookup.h"
-
-int ippool_printaddr(struct ippool_t *this) {
- unsigned int n;
- printf("ippool_printaddr\n");
- printf("Firstdyn %d\n", this->firstdyn - this->member);
- printf("Lastdyn %d\n", this->lastdyn - this->member);
- printf("Firststat %d\n", this->firststat - this->member);
- printf("Laststat %d\n", this->laststat - this->member);
- printf("Listsize %d\n", this->listsize);
-
- for (n=0; n<this->listsize; n++) {
- printf("Unit %d inuse %d prev %d next %d addr %s %x\n",
- n,
- this->member[n].inuse,
- this->member[n].prev - this->member,
- this->member[n].next - this->member,
- inet_ntoa(this->member[n].addr),
- this->member[n].addr.s_addr
- );
- }
- return 0;
+int ippool_printaddr(struct ippool_t *this)
+{
+ unsigned int n;
+ printf("ippool_printaddr\n");
+ printf("Firstdyn %d\n", this->firstdyn - this->member);
+ printf("Lastdyn %d\n", this->lastdyn - this->member);
+ printf("Firststat %d\n", this->firststat - this->member);
+ printf("Laststat %d\n", this->laststat - this->member);
+ printf("Listsize %d\n", this->listsize);
+
+ for (n = 0; n < this->listsize; n++) {
+ printf("Unit %d inuse %d prev %d next %d addr %s %x\n",
+ n,
+ this->member[n].inuse,
+ this->member[n].prev - this->member,
+ this->member[n].next - this->member,
+ inet_ntoa(this->member[n].addr),
+ this->member[n].addr.s_addr);
+ }
+ return 0;
}
-int ippool_hashadd(struct ippool_t *this, struct ippoolm_t *member) {
- uint32_t hash;
- struct ippoolm_t *p;
- struct ippoolm_t *p_prev = NULL;
-
- /* Insert into hash table */
- hash = ippool_hash4(&member->addr) & this->hashmask;
- for (p = this->hash[hash]; p; p = p->nexthash)
- p_prev = p;
- if (!p_prev)
- this->hash[hash] = member;
- else
- p_prev->nexthash = member;
- return 0; /* Always OK to insert */
+int ippool_hashadd(struct ippool_t *this, struct ippoolm_t *member)
+{
+ uint32_t hash;
+ struct ippoolm_t *p;
+ struct ippoolm_t *p_prev = NULL;
+
+ /* Insert into hash table */
+ hash = ippool_hash4(&member->addr) & this->hashmask;
+ for (p = this->hash[hash]; p; p = p->nexthash)
+ p_prev = p;
+ if (!p_prev)
+ this->hash[hash] = member;
+ else
+ p_prev->nexthash = member;
+ return 0; /* Always OK to insert */
}
-int ippool_hashdel(struct ippool_t *this, struct ippoolm_t *member) {
- uint32_t hash;
- struct ippoolm_t *p;
- struct ippoolm_t *p_prev = NULL;
-
- /* Find in hash table */
- hash = ippool_hash4(&member->addr) & this->hashmask;
- for (p = this->hash[hash]; p; p = p->nexthash) {
- if (p == member) {
- break;
- }
- p_prev = p;
- }
-
- if (p!= member) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "ippool_hashdel: Tried to delete member not in hash table");
- return -1;
- }
-
- if (!p_prev)
- this->hash[hash] = p->nexthash;
- else
- p_prev->nexthash = p->nexthash;
-
- return 0;
+int ippool_hashdel(struct ippool_t *this, struct ippoolm_t *member)
+{
+ uint32_t hash;
+ struct ippoolm_t *p;
+ struct ippoolm_t *p_prev = NULL;
+
+ /* Find in hash table */
+ hash = ippool_hash4(&member->addr) & this->hashmask;
+ for (p = this->hash[hash]; p; p = p->nexthash) {
+ if (p == member) {
+ break;
+ }
+ p_prev = p;
+ }
+
+ if (p != member) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "ippool_hashdel: Tried to delete member not in hash table");
+ return -1;
+ }
+
+ if (!p_prev)
+ this->hash[hash] = p->nexthash;
+ else
+ p_prev->nexthash = p->nexthash;
+
+ return 0;
}
-
-unsigned long int ippool_hash4(struct in_addr *addr) {
- return lookup((unsigned char*) &addr->s_addr, sizeof(addr->s_addr), 0);
+unsigned long int ippool_hash4(struct in_addr *addr)
+{
+ return lookup((unsigned char *)&addr->s_addr, sizeof(addr->s_addr), 0);
}
#ifndef IPPOOL_NOIP6
-unsigned long int ippool_hash6(struct in6_addr *addr) {
- return lookup((unsigned char*) addr->u6_addr8, sizeof(addr->u6_addr8), 0);
+unsigned long int ippool_hash6(struct in6_addr *addr)
+{
+ return lookup((unsigned char *)addr->u6_addr8, sizeof(addr->u6_addr8),
+ 0);
}
#endif
-
/* Get IP address and mask */
int ippool_aton(struct in_addr *addr, struct in_addr *mask,
- char *pool, int number) {
-
- /* Parse only first instance of network for now */
- /* Eventually "number" will indicate the token which we want to parse */
-
- unsigned int a1, a2, a3, a4;
- unsigned int m1, m2, m3, m4;
- int c;
- int m;
- int masklog;
-
- c = sscanf(pool, "%u.%u.%u.%u/%u.%u.%u.%u",
- &a1, &a2, &a3, &a4,
- &m1, &m2, &m3, &m4);
- switch (c) {
- case 4:
- mask->s_addr = 0xffffffff;
- break;
- case 5:
- if (m1 > 32) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Invalid mask");
- return -1; /* Invalid mask */
- }
- mask->s_addr = htonl(0xffffffff << (32 - m1));
- break;
- case 8:
- if (m1 >= 256 || m2 >= 256 || m3 >= 256 || m4 >= 256) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Invalid mask");
- return -1; /* Wrong mask format */
- }
- m = m1 * 0x1000000 + m2 * 0x10000 + m3 * 0x100 + m4;
- for (masklog = 0; ((1 << masklog) < ((~m)+1)); masklog++);
- if (((~m)+1) != (1 << masklog)) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Invalid mask");
- return -1; /* Wrong mask format (not all ones followed by all zeros)*/
- }
- mask->s_addr = htonl(m);
- break;
- default:
- sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Invalid mask");
- return -1; /* Invalid mask */
- }
-
- if (a1 >= 256 || a2 >= 256 || a3 >= 256 || a4 >= 256) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Wrong IP address format");
- return -1;
- }
- else
- addr->s_addr = htonl(a1 * 0x1000000 + a2 * 0x10000 + a3 * 0x100 + a4);
-
- return 0;
+ char *pool, int number)
+{
+
+ /* Parse only first instance of network for now */
+ /* Eventually "number" will indicate the token which we want to parse */
+
+ unsigned int a1, a2, a3, a4;
+ unsigned int m1, m2, m3, m4;
+ int c;
+ int m;
+ int masklog;
+
+ c = sscanf(pool, "%u.%u.%u.%u/%u.%u.%u.%u",
+ &a1, &a2, &a3, &a4, &m1, &m2, &m3, &m4);
+ switch (c) {
+ case 4:
+ mask->s_addr = 0xffffffff;
+ break;
+ case 5:
+ if (m1 > 32) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Invalid mask");
+ return -1; /* Invalid mask */
+ }
+ mask->s_addr = htonl(0xffffffff << (32 - m1));
+ break;
+ case 8:
+ if (m1 >= 256 || m2 >= 256 || m3 >= 256 || m4 >= 256) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Invalid mask");
+ return -1; /* Wrong mask format */
+ }
+ m = m1 * 0x1000000 + m2 * 0x10000 + m3 * 0x100 + m4;
+ for (masklog = 0; ((1 << masklog) < ((~m) + 1)); masklog++) ;
+ if (((~m) + 1) != (1 << masklog)) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Invalid mask");
+ return -1; /* Wrong mask format (not all ones followed by all zeros) */
+ }
+ mask->s_addr = htonl(m);
+ break;
+ default:
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Invalid mask");
+ return -1; /* Invalid mask */
+ }
+
+ if (a1 >= 256 || a2 >= 256 || a3 >= 256 || a4 >= 256) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "Wrong IP address format");
+ return -1;
+ } else
+ addr->s_addr =
+ htonl(a1 * 0x1000000 + a2 * 0x10000 + a3 * 0x100 + a4);
+
+ return 0;
}
/* Create new address pool */
-int ippool_new(struct ippool_t **this, char *dyn, char *stat,
- int allowdyn, int allowstat, int flags) {
-
- /* Parse only first instance of pool for now */
-
- int i;
- struct in_addr addr;
- struct in_addr mask;
- struct in_addr stataddr;
- struct in_addr statmask;
- unsigned int m;
- int listsize;
- int dynsize;
- unsigned int statsize;
-
- if (!allowdyn) {
- dynsize = 0;
- }
- else {
- if (ippool_aton(&addr, &mask, dyn, 0)) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "Failed to parse dynamic pool");
- return -1;
- }
-
- /* Set IPPOOL_NONETWORK if IPPOOL_NOGATEWAY is set */
- if (flags & IPPOOL_NOGATEWAY) {
- flags |= IPPOOL_NONETWORK;
- }
-
- m = ntohl(mask.s_addr);
- dynsize = ((~m)+1);
- if (flags & IPPOOL_NONETWORK) /* Exclude network address from pool */
- dynsize--;
- if (flags & IPPOOL_NOGATEWAY) /* Exclude gateway address from pool */
- dynsize--;
- if (flags & IPPOOL_NOBROADCAST) /* Exclude broadcast address from pool */
- dynsize--;
- }
-
- if (!allowstat) {
- statsize = 0;
- stataddr.s_addr = 0;
- statmask.s_addr = 0;
- }
- else {
- if (ippool_aton(&stataddr, &statmask, stat, 0)) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "Failed to parse static range");
- return -1;
- }
-
- m = ntohl(statmask.s_addr);
- statsize = ((~m)+1);
- if (statsize > IPPOOL_STATSIZE) statsize = IPPOOL_STATSIZE;
- }
-
- listsize = dynsize + statsize; /* Allocate space for static IP addresses */
-
- if (!(*this = calloc(sizeof(struct ippool_t), 1))) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "Failed to allocate memory for ippool");
- return -1;
- }
-
- (*this)->allowdyn = allowdyn;
- (*this)->allowstat = allowstat;
- (*this)->stataddr = stataddr;
- (*this)->statmask = statmask;
-
- (*this)->listsize += listsize;
- if (!((*this)->member = calloc(sizeof(struct ippoolm_t), listsize))){
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "Failed to allocate memory for members in ippool");
- return -1;
- }
-
- for ((*this)->hashlog = 0;
- ((1 << (*this)->hashlog) < listsize);
- (*this)->hashlog++);
-
- /* printf ("Hashlog %d %d %d\n", (*this)->hashlog, listsize, (1 << (*this)->hashlog)); */
-
- /* Determine hashsize */
- (*this)->hashsize = 1 << (*this)->hashlog; /* Fails if mask=0: All Internet*/
- (*this)->hashmask = (*this)->hashsize -1;
-
- /* Allocate hash table */
- if (!((*this)->hash = calloc(sizeof(struct ippoolm_t), (*this)->hashsize))){
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "Failed to allocate memory for hash members in ippool");
- return -1;
- }
-
- (*this)->firstdyn = NULL;
- (*this)->lastdyn = NULL;
- for (i = 0; i<dynsize; i++) {
-
- if (flags & IPPOOL_NOGATEWAY)
- (*this)->member[i].addr.s_addr = htonl(ntohl(addr.s_addr) + i + 2);
- else if (flags & IPPOOL_NONETWORK)
- (*this)->member[i].addr.s_addr = htonl(ntohl(addr.s_addr) + i + 1);
- else
- (*this)->member[i].addr.s_addr = htonl(ntohl(addr.s_addr) + i);
-
- (*this)->member[i].inuse = 0;
-
- /* Insert into list of unused */
- (*this)->member[i].prev = (*this)->lastdyn;
- if ((*this)->lastdyn) {
- (*this)->lastdyn->next = &((*this)->member[i]);
- }
- else {
- (*this)->firstdyn = &((*this)->member[i]);
- }
- (*this)->lastdyn = &((*this)->member[i]);
- (*this)->member[i].next = NULL; /* Redundant */
-
- ( void)ippool_hashadd(*this, &(*this)->member[i]);
- }
-
- (*this)->firststat = NULL;
- (*this)->laststat = NULL;
- for (i = dynsize; i<listsize; i++) {
-
- (*this)->member[i].addr.s_addr = 0;
- (*this)->member[i].inuse = 0;
-
- /* Insert into list of unused */
- (*this)->member[i].prev = (*this)->laststat;
- if ((*this)->laststat) {
- (*this)->laststat->next = &((*this)->member[i]);
- }
- else {
- (*this)->firststat = &((*this)->member[i]);
- }
- (*this)->laststat = &((*this)->member[i]);
- (*this)->member[i].next = NULL; /* Redundant */
- }
-
- if (0) (void)ippool_printaddr(*this);
- return 0;
+int ippool_new(struct ippool_t **this, char *dyn, char *stat,
+ int allowdyn, int allowstat, int flags)
+{
+
+ /* Parse only first instance of pool for now */
+
+ int i;
+ struct in_addr addr;
+ struct in_addr mask;
+ struct in_addr stataddr;
+ struct in_addr statmask;
+ unsigned int m;
+ int listsize;
+ int dynsize;
+ unsigned int statsize;
+
+ if (!allowdyn) {
+ dynsize = 0;
+ } else {
+ if (ippool_aton(&addr, &mask, dyn, 0)) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "Failed to parse dynamic pool");
+ return -1;
+ }
+
+ /* Set IPPOOL_NONETWORK if IPPOOL_NOGATEWAY is set */
+ if (flags & IPPOOL_NOGATEWAY) {
+ flags |= IPPOOL_NONETWORK;
+ }
+
+ m = ntohl(mask.s_addr);
+ dynsize = ((~m) + 1);
+ if (flags & IPPOOL_NONETWORK) /* Exclude network address from pool */
+ dynsize--;
+ if (flags & IPPOOL_NOGATEWAY) /* Exclude gateway address from pool */
+ dynsize--;
+ if (flags & IPPOOL_NOBROADCAST) /* Exclude broadcast address from pool */
+ dynsize--;
+ }
+
+ if (!allowstat) {
+ statsize = 0;
+ stataddr.s_addr = 0;
+ statmask.s_addr = 0;
+ } else {
+ if (ippool_aton(&stataddr, &statmask, stat, 0)) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "Failed to parse static range");
+ return -1;
+ }
+
+ m = ntohl(statmask.s_addr);
+ statsize = ((~m) + 1);
+ if (statsize > IPPOOL_STATSIZE)
+ statsize = IPPOOL_STATSIZE;
+ }
+
+ listsize = dynsize + statsize; /* Allocate space for static IP addresses */
+
+ if (!(*this = calloc(sizeof(struct ippool_t), 1))) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "Failed to allocate memory for ippool");
+ return -1;
+ }
+
+ (*this)->allowdyn = allowdyn;
+ (*this)->allowstat = allowstat;
+ (*this)->stataddr = stataddr;
+ (*this)->statmask = statmask;
+
+ (*this)->listsize += listsize;
+ if (!((*this)->member = calloc(sizeof(struct ippoolm_t), listsize))) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "Failed to allocate memory for members in ippool");
+ return -1;
+ }
+
+ for ((*this)->hashlog = 0;
+ ((1 << (*this)->hashlog) < listsize); (*this)->hashlog++) ;
+
+ /* printf ("Hashlog %d %d %d\n", (*this)->hashlog, listsize, (1 << (*this)->hashlog)); */
+
+ /* Determine hashsize */
+ (*this)->hashsize = 1 << (*this)->hashlog; /* Fails if mask=0: All Internet */
+ (*this)->hashmask = (*this)->hashsize - 1;
+
+ /* Allocate hash table */
+ if (!
+ ((*this)->hash =
+ calloc(sizeof(struct ippoolm_t), (*this)->hashsize))) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "Failed to allocate memory for hash members in ippool");
+ return -1;
+ }
+
+ (*this)->firstdyn = NULL;
+ (*this)->lastdyn = NULL;
+ for (i = 0; i < dynsize; i++) {
+
+ if (flags & IPPOOL_NOGATEWAY)
+ (*this)->member[i].addr.s_addr =
+ htonl(ntohl(addr.s_addr) + i + 2);
+ else if (flags & IPPOOL_NONETWORK)
+ (*this)->member[i].addr.s_addr =
+ htonl(ntohl(addr.s_addr) + i + 1);
+ else
+ (*this)->member[i].addr.s_addr =
+ htonl(ntohl(addr.s_addr) + i);
+
+ (*this)->member[i].inuse = 0;
+
+ /* Insert into list of unused */
+ (*this)->member[i].prev = (*this)->lastdyn;
+ if ((*this)->lastdyn) {
+ (*this)->lastdyn->next = &((*this)->member[i]);
+ } else {
+ (*this)->firstdyn = &((*this)->member[i]);
+ }
+ (*this)->lastdyn = &((*this)->member[i]);
+ (*this)->member[i].next = NULL; /* Redundant */
+
+ (void)ippool_hashadd(*this, &(*this)->member[i]);
+ }
+
+ (*this)->firststat = NULL;
+ (*this)->laststat = NULL;
+ for (i = dynsize; i < listsize; i++) {
+
+ (*this)->member[i].addr.s_addr = 0;
+ (*this)->member[i].inuse = 0;
+
+ /* Insert into list of unused */
+ (*this)->member[i].prev = (*this)->laststat;
+ if ((*this)->laststat) {
+ (*this)->laststat->next = &((*this)->member[i]);
+ } else {
+ (*this)->firststat = &((*this)->member[i]);
+ }
+ (*this)->laststat = &((*this)->member[i]);
+ (*this)->member[i].next = NULL; /* Redundant */
+ }
+
+ if (0)
+ (void)ippool_printaddr(*this);
+ return 0;
}
-
-
/* Delete existing address pool */
-int ippool_free(struct ippool_t *this) {
- free(this->hash);
- free(this->member);
- free(this);
- return 0; /* Always OK */
+int ippool_free(struct ippool_t *this)
+{
+ free(this->hash);
+ free(this->member);
+ free(this);
+ return 0; /* Always OK */
}
/* Find an IP address in the pool */
int ippool_getip(struct ippool_t *this, struct ippoolm_t **member,
- struct in_addr *addr) {
- struct ippoolm_t *p;
- uint32_t hash;
-
- /* Find in hash table */
- hash = ippool_hash4(addr) & this->hashmask;
- for (p = this->hash[hash]; p; p = p->nexthash) {
- if ((p->addr.s_addr == addr->s_addr) && (p->inuse)) {
- if (member) *member = p;
- return 0;
- }
- }
- if (member) *member = NULL;
- /*sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Address could not be found");*/
- return -1;
+ struct in_addr *addr)
+{
+ struct ippoolm_t *p;
+ uint32_t hash;
+
+ /* Find in hash table */
+ hash = ippool_hash4(addr) & this->hashmask;
+ for (p = this->hash[hash]; p; p = p->nexthash) {
+ if ((p->addr.s_addr == addr->s_addr) && (p->inuse)) {
+ if (member)
+ *member = p;
+ return 0;
+ }
+ }
+ if (member)
+ *member = NULL;
+ /*sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Address could not be found"); */
+ return -1;
}
/**
@@ -337,188 +345,193 @@ int ippool_getip(struct ippool_t *this, struct ippoolm_t **member,
* address space.
**/
int ippool_newip(struct ippool_t *this, struct ippoolm_t **member,
- struct in_addr *addr, int statip) {
- struct ippoolm_t *p;
- struct ippoolm_t *p2 = NULL;
- uint32_t hash;
-
- /* If static:
- * Look in dynaddr.
- * If found remove from firstdyn/lastdyn linked list.
- * Else allocate from stataddr.
- * Remove from firststat/laststat linked list.
- * Insert into hash table.
- *
- * If dynamic
- * Remove from firstdyn/lastdyn linked list.
- *
- */
-
- if (0) (void)ippool_printaddr(this);
-
- /* First check to see if this type of address is allowed */
- if ((addr) && (addr->s_addr) && statip) { /* IP address given */
- if (!this->allowstat) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Static IP address not allowed");
- return -1;
- }
- if ((addr->s_addr & this->statmask.s_addr) != this->stataddr.s_addr) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Static out of range");
- return -1;
- }
- }
- else {
- if (!this->allowdyn) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "Dynamic IP address not allowed");
- return -1;
- }
- }
-
- /* If IP address given try to find it in dynamic address pool */
- if ((addr) && (addr->s_addr)) { /* IP address given */
- /* Find in hash table */
- hash = ippool_hash4(addr) & this->hashmask;
- for (p = this->hash[hash]; p; p = p->nexthash) {
- if ((p->addr.s_addr == addr->s_addr)) {
- p2 = p;
- break;
- }
- }
- }
-
- /* If IP was already allocated we can not use it */
- if ((!statip) && (p2) && (p2->inuse)) {
- p2 = NULL;
- }
-
- /* If not found yet and dynamic IP then allocate dynamic IP */
- if ((!p2) && (!statip)) {
- if (!this ->firstdyn) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "No more IP addresses available");
- return -1;
- }
- else
- p2 = this ->firstdyn;
- }
-
- if (p2) { /* Was allocated from dynamic address pool */
- if (p2->inuse) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "IP address allready in use");
- return -1; /* Allready in use / Should not happen */
- }
-
- /* Remove from linked list of free dynamic addresses */
- if (p2->prev)
- p2->prev->next = p2->next;
- else
- this->firstdyn = p2->next;
- if (p2->next)
- p2->next->prev = p2->prev;
- else
- this->lastdyn = p2->prev;
- p2->next = NULL;
- p2->prev = NULL;
- p2->inuse = 1; /* Dynamic address in use */
-
- *member = p2;
- if (0) (void)ippool_printaddr(this);
- return 0; /* Success */
- }
-
- /* It was not possible to allocate from dynamic address pool */
- /* Try to allocate from static address space */
-
- if ((addr) && (addr->s_addr) && (statip)) { /* IP address given */
- if (!this->firststat) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "No more IP addresses available");
- return -1; /* No more available */
- }
- else
- p2 = this ->firststat;
-
- /* Remove from linked list of free static addresses */
- if (p2->prev)
- p2->prev->next = p2->next;
- else
- this->firststat = p2->next;
- if (p2->next)
- p2->next->prev = p2->prev;
- else
- this->laststat = p2->prev;
- p2->next = NULL;
- p2->prev = NULL;
- p2->inuse = 2; /* Static address in use */
- memcpy(&p2->addr, addr, sizeof(addr));
- *member = p2;
- (void)ippool_hashadd(this, *member);
- if (0) (void)ippool_printaddr(this);
- return 0; /* Success */
- }
-
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "Could not allocate IP address");
- return -1; /* Should never get here. TODO: Bad code */
+ struct in_addr *addr, int statip)
+{
+ struct ippoolm_t *p;
+ struct ippoolm_t *p2 = NULL;
+ uint32_t hash;
+
+ /* If static:
+ * Look in dynaddr.
+ * If found remove from firstdyn/lastdyn linked list.
+ * Else allocate from stataddr.
+ * Remove from firststat/laststat linked list.
+ * Insert into hash table.
+ *
+ * If dynamic
+ * Remove from firstdyn/lastdyn linked list.
+ *
+ */
+
+ if (0)
+ (void)ippool_printaddr(this);
+
+ /* First check to see if this type of address is allowed */
+ if ((addr) && (addr->s_addr) && statip) { /* IP address given */
+ if (!this->allowstat) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "Static IP address not allowed");
+ return -1;
+ }
+ if ((addr->s_addr & this->statmask.s_addr) !=
+ this->stataddr.s_addr) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "Static out of range");
+ return -1;
+ }
+ } else {
+ if (!this->allowdyn) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "Dynamic IP address not allowed");
+ return -1;
+ }
+ }
+
+ /* If IP address given try to find it in dynamic address pool */
+ if ((addr) && (addr->s_addr)) { /* IP address given */
+ /* Find in hash table */
+ hash = ippool_hash4(addr) & this->hashmask;
+ for (p = this->hash[hash]; p; p = p->nexthash) {
+ if ((p->addr.s_addr == addr->s_addr)) {
+ p2 = p;
+ break;
+ }
+ }
+ }
+
+ /* If IP was already allocated we can not use it */
+ if ((!statip) && (p2) && (p2->inuse)) {
+ p2 = NULL;
+ }
+
+ /* If not found yet and dynamic IP then allocate dynamic IP */
+ if ((!p2) && (!statip)) {
+ if (!this->firstdyn) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "No more IP addresses available");
+ return -1;
+ } else
+ p2 = this->firstdyn;
+ }
+
+ if (p2) { /* Was allocated from dynamic address pool */
+ if (p2->inuse) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "IP address allready in use");
+ return -1; /* Allready in use / Should not happen */
+ }
+
+ /* Remove from linked list of free dynamic addresses */
+ if (p2->prev)
+ p2->prev->next = p2->next;
+ else
+ this->firstdyn = p2->next;
+ if (p2->next)
+ p2->next->prev = p2->prev;
+ else
+ this->lastdyn = p2->prev;
+ p2->next = NULL;
+ p2->prev = NULL;
+ p2->inuse = 1; /* Dynamic address in use */
+
+ *member = p2;
+ if (0)
+ (void)ippool_printaddr(this);
+ return 0; /* Success */
+ }
+
+ /* It was not possible to allocate from dynamic address pool */
+ /* Try to allocate from static address space */
+
+ if ((addr) && (addr->s_addr) && (statip)) { /* IP address given */
+ if (!this->firststat) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "No more IP addresses available");
+ return -1; /* No more available */
+ } else
+ p2 = this->firststat;
+
+ /* Remove from linked list of free static addresses */
+ if (p2->prev)
+ p2->prev->next = p2->next;
+ else
+ this->firststat = p2->next;
+ if (p2->next)
+ p2->next->prev = p2->prev;
+ else
+ this->laststat = p2->prev;
+ p2->next = NULL;
+ p2->prev = NULL;
+ p2->inuse = 2; /* Static address in use */
+ memcpy(&p2->addr, addr, sizeof(addr));
+ *member = p2;
+ (void)ippool_hashadd(this, *member);
+ if (0)
+ (void)ippool_printaddr(this);
+ return 0; /* Success */
+ }
+
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "Could not allocate IP address");
+ return -1; /* Should never get here. TODO: Bad code */
}
-
-int ippool_freeip(struct ippool_t *this, struct ippoolm_t *member) {
-
- if (0) (void)ippool_printaddr(this);
-
- if (!member->inuse) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Address not in use");
- return -1; /* Not in use: Should not happen */
- }
-
- switch (member->inuse) {
- case 0: /* Not in use: Should not happen */
- sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Address not in use");
- return -1;
- case 1: /* Allocated from dynamic address space */
- /* Insert into list of unused */
- member->prev = this->lastdyn;
- if (this->lastdyn) {
- this->lastdyn->next = member;
- }
- else {
- this->firstdyn = member;
- }
- this->lastdyn = member;
-
- member->inuse = 0;
- member->peer = NULL;
- if (0) (void)ippool_printaddr(this);
- return 0;
- case 2: /* Allocated from static address space */
- if (ippool_hashdel(this, member))
- return -1;
- /* Insert into list of unused */
- member->prev = this->laststat;
- if (this->laststat) {
- this->laststat->next = member;
- }
- else {
- this->firststat = member;
- }
- this->laststat = member;
-
- member->inuse = 0;
- member->addr.s_addr = 0;
- member->peer = NULL;
- member->nexthash = NULL;
- if (0) (void)ippool_printaddr(this);
- return 0;
- default: /* Should not happen */
- sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Could not free IP address");
- return -1;
- }
+int ippool_freeip(struct ippool_t *this, struct ippoolm_t *member)
+{
+
+ if (0)
+ (void)ippool_printaddr(this);
+
+ if (!member->inuse) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Address not in use");
+ return -1; /* Not in use: Should not happen */
+ }
+
+ switch (member->inuse) {
+ case 0: /* Not in use: Should not happen */
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Address not in use");
+ return -1;
+ case 1: /* Allocated from dynamic address space */
+ /* Insert into list of unused */
+ member->prev = this->lastdyn;
+ if (this->lastdyn) {
+ this->lastdyn->next = member;
+ } else {
+ this->firstdyn = member;
+ }
+ this->lastdyn = member;
+
+ member->inuse = 0;
+ member->peer = NULL;
+ if (0)
+ (void)ippool_printaddr(this);
+ return 0;
+ case 2: /* Allocated from static address space */
+ if (ippool_hashdel(this, member))
+ return -1;
+ /* Insert into list of unused */
+ member->prev = this->laststat;
+ if (this->laststat) {
+ this->laststat->next = member;
+ } else {
+ this->firststat = member;
+ }
+ this->laststat = member;
+
+ member->inuse = 0;
+ member->addr.s_addr = 0;
+ member->peer = NULL;
+ member->nexthash = NULL;
+ if (0)
+ (void)ippool_printaddr(this);
+ return 0;
+ default: /* Should not happen */
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "Could not free IP address");
+ return -1;
+ }
}
-
#ifndef IPPOOL_NOIP6
extern unsigned long int ippool_hash6(struct in6_addr *addr);
extern int ippool_getip6(struct ippool_t *this, struct in6_addr *addr);
diff --git a/lib/ippool.h b/lib/ippool.h
index 02691a6..534140d 100644
--- a/lib/ippool.h
+++ b/lib/ippool.h
@@ -34,35 +34,35 @@
#define IPPOOL_STATSIZE 0x10000
-struct ippoolm_t; /* Forward declaration */
+struct ippoolm_t; /* Forward declaration */
struct ippool_t {
- unsigned int listsize; /* Total number of addresses */
- int allowdyn; /* Allow dynamic IP address allocation */
- int allowstat; /* Allow static IP address allocation */
- struct in_addr stataddr; /* Static address range network address */
- struct in_addr statmask; /* Static address range network mask */
- struct ippoolm_t *member; /* Listsize array of members */
- unsigned int hashsize; /* Size of hash table */
- int hashlog; /* Log2 size of hash table */
- int hashmask; /* Bitmask for calculating hash */
- struct ippoolm_t **hash; /* Hashsize array of pointer to member */
- struct ippoolm_t *firstdyn; /* Pointer to first free dynamic member */
- struct ippoolm_t *lastdyn; /* Pointer to last free dynamic member */
- struct ippoolm_t *firststat; /* Pointer to first free static member */
- struct ippoolm_t *laststat; /* Pointer to last free static member */
+ unsigned int listsize; /* Total number of addresses */
+ int allowdyn; /* Allow dynamic IP address allocation */
+ int allowstat; /* Allow static IP address allocation */
+ struct in_addr stataddr; /* Static address range network address */
+ struct in_addr statmask; /* Static address range network mask */
+ struct ippoolm_t *member; /* Listsize array of members */
+ unsigned int hashsize; /* Size of hash table */
+ int hashlog; /* Log2 size of hash table */
+ int hashmask; /* Bitmask for calculating hash */
+ struct ippoolm_t **hash; /* Hashsize array of pointer to member */
+ struct ippoolm_t *firstdyn; /* Pointer to first free dynamic member */
+ struct ippoolm_t *lastdyn; /* Pointer to last free dynamic member */
+ struct ippoolm_t *firststat; /* Pointer to first free static member */
+ struct ippoolm_t *laststat; /* Pointer to last free static member */
};
struct ippoolm_t {
#ifndef IPPOOL_NOIP6
- struct in6_addr addr; /* IP address of this member */
+ struct in6_addr addr; /* IP address of this member */
#else
- struct in_addr addr; /* IP address of this member */
+ struct in_addr addr; /* IP address of this member */
#endif
- int inuse; /* 0=available; 1= dynamic; 2 = static */
- struct ippoolm_t *nexthash; /* Linked list part of hash table */
- struct ippoolm_t *prev, *next; /* Linked list of free dynamic or static */
- void *peer; /* Pointer to peer protocol handler */
+ int inuse; /* 0=available; 1= dynamic; 2 = static */
+ struct ippoolm_t *nexthash; /* Linked list part of hash table */
+ struct ippoolm_t *prev, *next; /* Linked list of free dynamic or static */
+ void *peer; /* Pointer to peer protocol handler */
};
/* The above structures require approximately 20+4 = 24 bytes for
@@ -73,7 +73,7 @@ struct ippoolm_t {
extern unsigned long int ippool_hash4(struct in_addr *addr);
/* Create new address pool */
-extern int ippool_new(struct ippool_t **this, char *dyn, char *stat,
+extern int ippool_new(struct ippool_t **this, char *dyn, char *stat,
int allowdyn, int allowstat, int flags);
/* Delete existing address pool */
@@ -81,7 +81,7 @@ extern int ippool_free(struct ippool_t *this);
/* Find an IP address in the pool */
extern int ippool_getip(struct ippool_t *this, struct ippoolm_t **member,
- struct in_addr *addr);
+ struct in_addr *addr);
/* Get an IP address. If addr = 0.0.0.0 get a dynamic IP address. Otherwise
check to see if the given address is available */
@@ -95,11 +95,10 @@ extern int ippool_freeip(struct ippool_t *this, struct ippoolm_t *member);
extern int ippool_aton(struct in_addr *addr, struct in_addr *mask,
char *pool, int number);
-
#ifndef IPPOOL_NOIP6
extern unsigned long int ippool_hash6(struct in6_addr *addr);
extern int ippool_getip6(struct ippool_t *this, struct in6_addr *addr);
extern int ippool_returnip6(struct ippool_t *this, struct in6_addr *addr);
#endif
-#endif /* !_IPPOOL_H */
+#endif /* !_IPPOOL_H */
diff --git a/lib/lookup.c b/lib/lookup.c
index 02e2491..d2f13c4 100755
--- a/lib/lookup.c
+++ b/lib/lookup.c
@@ -17,10 +17,10 @@
* statistical properties and speed. It is NOT recommended for cryptographic
* purposes.
**/
-unsigned long int lookup( k, length, level)
-register unsigned char *k; /* the key */
-register unsigned long int length; /* the length of the key */
-register unsigned long int level; /* the previous hash, or an arbitrary value*/
+unsigned long int lookup(k, length, level)
+register unsigned char *k; /* the key */
+register unsigned long int length; /* the length of the key */
+register unsigned long int level; /* the previous hash, or an arbitrary value */
{
#define mix(a,b,c) \
@@ -36,45 +36,57 @@ register unsigned long int level; /* the previous hash, or an arbitrary value*/
c -= a; c -= b; c ^= (b>>15); \
}
- typedef unsigned long int ub4; /* unsigned 4-byte quantities */
- typedef unsigned char ub1; /* unsigned 1-byte quantities */
- register unsigned long int a,b,c,len;
-
- /* Set up the internal state */
- len = length;
- a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
- c = level; /* the previous hash value */
-
+ typedef unsigned long int ub4; /* unsigned 4-byte quantities */
+ typedef unsigned char ub1; /* unsigned 1-byte quantities */
+ register unsigned long int a, b, c, len;
+
+ /* Set up the internal state */
+ len = length;
+ a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
+ c = level; /* the previous hash value */
+
/*---------------------------------------- handle most of the key */
- while (len >= 12)
- {
- a += (k[0] +((ub4)k[1]<<8) +((ub4)k[2]<<16) +((ub4)k[3]<<24));
- b += (k[4] +((ub4)k[5]<<8) +((ub4)k[6]<<16) +((ub4)k[7]<<24));
- c += (k[8] +((ub4)k[9]<<8) +((ub4)k[10]<<16)+((ub4)k[11]<<24));
- mix(a,b,c);
- k += 12; len -= 12;
- }
-
+ while (len >= 12) {
+ a += (k[0] + ((ub4) k[1] << 8) + ((ub4) k[2] << 16) +
+ ((ub4) k[3] << 24));
+ b += (k[4] + ((ub4) k[5] << 8) + ((ub4) k[6] << 16) +
+ ((ub4) k[7] << 24));
+ c += (k[8] + ((ub4) k[9] << 8) + ((ub4) k[10] << 16) +
+ ((ub4) k[11] << 24));
+ mix(a, b, c);
+ k += 12;
+ len -= 12;
+ }
+
/*------------------------------------- handle the last 11 bytes */
- c += length;
- switch(len) /* all the case statements fall through */
- {
- case 11: c+=((ub4)k[10]<<24);
- case 10: c+=((ub4)k[9]<<16);
- case 9 : c+=((ub4)k[8]<<8);
- /* the first byte of c is reserved for the length */
- case 8 : b+=((ub4)k[7]<<24);
- case 7 : b+=((ub4)k[6]<<16);
- case 6 : b+=((ub4)k[5]<<8);
- case 5 : b+=k[4];
- case 4 : a+=((ub4)k[3]<<24);
- case 3 : a+=((ub4)k[2]<<16);
- case 2 : a+=((ub4)k[1]<<8);
- case 1 : a+=k[0];
- /* case 0: nothing left to add */
- }
- mix(a,b,c);
+ c += length;
+ switch (len) { /* all the case statements fall through */
+ case 11:
+ c += ((ub4) k[10] << 24);
+ case 10:
+ c += ((ub4) k[9] << 16);
+ case 9:
+ c += ((ub4) k[8] << 8);
+ /* the first byte of c is reserved for the length */
+ case 8:
+ b += ((ub4) k[7] << 24);
+ case 7:
+ b += ((ub4) k[6] << 16);
+ case 6:
+ b += ((ub4) k[5] << 8);
+ case 5:
+ b += k[4];
+ case 4:
+ a += ((ub4) k[3] << 24);
+ case 3:
+ a += ((ub4) k[2] << 16);
+ case 2:
+ a += ((ub4) k[1] << 8);
+ case 1:
+ a += k[0];
+ /* case 0: nothing left to add */
+ }
+ mix(a, b, c);
/*-------------------------------------------- report the result */
- return c;
+ return c;
}
-
diff --git a/lib/lookup.h b/lib/lookup.h
index 18b94c1..2df6c50 100755
--- a/lib/lookup.h
+++ b/lib/lookup.h
@@ -20,6 +20,7 @@
#ifndef _LOOKUP_H
#define _LOOKUP_H
-unsigned long int lookup( unsigned char *k, unsigned long int length, unsigned long int level);
+unsigned long int lookup(unsigned char *k, unsigned long int length,
+ unsigned long int level);
-#endif /* !_LOOKUP_H */
+#endif /* !_LOOKUP_H */
diff --git a/lib/syserr.c b/lib/syserr.c
index 002d8c3..048cd45 100644
--- a/lib/syserr.c
+++ b/lib/syserr.c
@@ -20,52 +20,55 @@
#include "syserr.h"
+void sys_err(int pri, char *fn, int ln, int en, char *fmt, ...)
+{
+ va_list args;
+ char buf[SYSERR_MSGSIZE];
-void sys_err(int pri, char *fn, int ln, int en, char *fmt, ...) {
- va_list args;
- char buf[SYSERR_MSGSIZE];
-
- va_start(args, fmt);
- vsnprintf(buf, SYSERR_MSGSIZE, fmt, args);
- va_end(args);
- buf[SYSERR_MSGSIZE-1] = 0; /* Make sure it is null terminated */
- if (en)
- syslog(pri, "%s: %d: %d (%s) %s", fn, ln, en, strerror(en), buf);
- else
- syslog(pri, "%s: %d: %s", fn, ln, buf);
+ va_start(args, fmt);
+ vsnprintf(buf, SYSERR_MSGSIZE, fmt, args);
+ va_end(args);
+ buf[SYSERR_MSGSIZE - 1] = 0; /* Make sure it is null terminated */
+ if (en)
+ syslog(pri, "%s: %d: %d (%s) %s", fn, ln, en, strerror(en),
+ buf);
+ else
+ syslog(pri, "%s: %d: %s", fn, ln, buf);
}
void sys_errpack(int pri, char *fn, int ln, int en, struct sockaddr_in *peer,
- void *pack, unsigned len, char *fmt, ...) {
-
- va_list args;
- char buf[SYSERR_MSGSIZE];
- char buf2[SYSERR_MSGSIZE];
- unsigned int n;
- int pos;
-
- va_start(args, fmt);
- vsnprintf(buf, SYSERR_MSGSIZE, fmt, args);
- va_end(args);
- buf[SYSERR_MSGSIZE-1] = 0;
+ void *pack, unsigned len, char *fmt, ...)
+{
+
+ va_list args;
+ char buf[SYSERR_MSGSIZE];
+ char buf2[SYSERR_MSGSIZE];
+ unsigned int n;
+ int pos;
+
+ va_start(args, fmt);
+ vsnprintf(buf, SYSERR_MSGSIZE, fmt, args);
+ va_end(args);
+ buf[SYSERR_MSGSIZE - 1] = 0;
+
+ snprintf(buf2, SYSERR_MSGSIZE,
+ "Packet from %s:%u, length: %d, content:",
+ inet_ntoa(peer->sin_addr), ntohs(peer->sin_port), len);
+ buf2[SYSERR_MSGSIZE - 1] = 0;
+ pos = strlen(buf2);
+ for (n = 0; n < len; n++) {
+ if ((pos + 4) < SYSERR_MSGSIZE) {
+ sprintf((buf2 + pos), " %02hhx",
+ ((unsigned char *)pack)[n]);
+ pos += 3;
+ }
+ }
+ buf2[pos] = 0;
- snprintf(buf2, SYSERR_MSGSIZE, "Packet from %s:%u, length: %d, content:",
- inet_ntoa(peer->sin_addr),
- ntohs(peer->sin_port),
- len);
- buf2[SYSERR_MSGSIZE-1] = 0;
- pos = strlen(buf2);
- for(n=0; n<len; n++) {
- if ((pos+4)<SYSERR_MSGSIZE) {
- sprintf((buf2+pos), " %02hhx", ((unsigned char*)pack)[n]);
- pos += 3;
- }
- }
- buf2[pos] = 0;
-
- if (en)
- syslog(pri, "%s: %d: %d (%s) %s. %s", fn, ln, en, strerror(en), buf, buf2);
- else
- syslog(pri, "%s: %d: %s. %s", fn, ln, buf, buf2);
+ if (en)
+ syslog(pri, "%s: %d: %d (%s) %s. %s", fn, ln, en, strerror(en),
+ buf, buf2);
+ else
+ syslog(pri, "%s: %d: %s. %s", fn, ln, buf, buf2);
}
diff --git a/lib/syserr.h b/lib/syserr.h
index a1ccb2d..e3ebdf0 100644
--- a/lib/syserr.h
+++ b/lib/syserr.h
@@ -18,4 +18,4 @@ void sys_err(int pri, char *filename, int en, int line, char *fmt, ...);
void sys_errpack(int pri, char *fn, int ln, int en, struct sockaddr_in *peer,
void *pack, unsigned len, char *fmt, ...);
-#endif /* !_SYSERR_H */
+#endif /* !_SYSERR_H */
diff --git a/lib/tun.c b/lib/tun.c
index 03d057c..f2fb14a 100644
--- a/lib/tun.c
+++ b/lib/tun.c
@@ -16,7 +16,6 @@
*
*/
-
#include <syslog.h>
#include <stdio.h>
#include <stdlib.h>
@@ -64,76 +63,72 @@
#error "Unknown platform!"
#endif
-
#include "tun.h"
#include "syserr.h"
-
#if defined(__linux__)
int tun_nlattr(struct nlmsghdr *n, int nsize, int type, void *d, int dlen)
{
- int len = RTA_LENGTH(dlen);
- int alen = NLMSG_ALIGN(n->nlmsg_len);
- struct rtattr *rta = (struct rtattr*) (((void*)n) + alen);
- if (alen + len > nsize)
- return -1;
- rta->rta_len = len;
- rta->rta_type = type;
- memcpy(RTA_DATA(rta), d, dlen);
- n->nlmsg_len = alen + len;
- return 0;
+ int len = RTA_LENGTH(dlen);
+ int alen = NLMSG_ALIGN(n->nlmsg_len);
+ struct rtattr *rta = (struct rtattr *)(((void *)n) + alen);
+ if (alen + len > nsize)
+ return -1;
+ rta->rta_len = len;
+ rta->rta_type = type;
+ memcpy(RTA_DATA(rta), d, dlen);
+ n->nlmsg_len = alen + len;
+ return 0;
}
-int tun_gifindex(struct tun_t *this, __u32 *index) {
- struct ifreq ifr;
- int fd;
-
- memset (&ifr, '\0', sizeof (ifr));
- ifr.ifr_addr.sa_family = AF_INET;
- ifr.ifr_dstaddr.sa_family = AF_INET;
- ifr.ifr_netmask.sa_family = AF_INET;
- strncpy(ifr.ifr_name, this->devname, IFNAMSIZ);
- ifr.ifr_name[IFNAMSIZ-1] = 0; /* Make sure to terminate */
- if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
- sys_err(LOG_ERR, __FILE__, __LINE__, errno,
- "socket() failed");
- }
- if (ioctl(fd, SIOCGIFINDEX, &ifr)) {
- sys_err(LOG_ERR, __FILE__, __LINE__, errno,
- "ioctl() failed");
- close(fd);
- return -1;
- }
- close(fd);
- *index = ifr.ifr_ifindex;
- return 0;
+int tun_gifindex(struct tun_t *this, __u32 * index)
+{
+ struct ifreq ifr;
+ int fd;
+
+ memset(&ifr, '\0', sizeof(ifr));
+ ifr.ifr_addr.sa_family = AF_INET;
+ ifr.ifr_dstaddr.sa_family = AF_INET;
+ ifr.ifr_netmask.sa_family = AF_INET;
+ strncpy(ifr.ifr_name, this->devname, IFNAMSIZ);
+ ifr.ifr_name[IFNAMSIZ - 1] = 0; /* Make sure to terminate */
+ if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno, "socket() failed");
+ }
+ if (ioctl(fd, SIOCGIFINDEX, &ifr)) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno, "ioctl() failed");
+ close(fd);
+ return -1;
+ }
+ close(fd);
+ *index = ifr.ifr_ifindex;
+ return 0;
}
#endif
-int tun_sifflags(struct tun_t *this, int flags) {
- struct ifreq ifr;
- int fd;
-
- memset (&ifr, '\0', sizeof (ifr));
- ifr.ifr_flags = flags;
- strncpy(ifr.ifr_name, this->devname, IFNAMSIZ);
- ifr.ifr_name[IFNAMSIZ-1] = 0; /* Make sure to terminate */
- if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
- sys_err(LOG_ERR, __FILE__, __LINE__, errno,
- "socket() failed");
- }
- if (ioctl(fd, SIOCSIFFLAGS, &ifr)) {
- sys_err(LOG_ERR, __FILE__, __LINE__, errno,
- "ioctl(SIOCSIFFLAGS) failed");
- close(fd);
- return -1;
- }
- close(fd);
- return 0;
+int tun_sifflags(struct tun_t *this, int flags)
+{
+ struct ifreq ifr;
+ int fd;
+
+ memset(&ifr, '\0', sizeof(ifr));
+ ifr.ifr_flags = flags;
+ strncpy(ifr.ifr_name, this->devname, IFNAMSIZ);
+ ifr.ifr_name[IFNAMSIZ - 1] = 0; /* Make sure to terminate */
+ if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno, "socket() failed");
+ }
+ if (ioctl(fd, SIOCSIFFLAGS, &ifr)) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno,
+ "ioctl(SIOCSIFFLAGS) failed");
+ close(fd);
+ return -1;
+ }
+ close(fd);
+ return 0;
}
-
/* Currently unused
int tun_addroute2(struct tun_t *this,
struct in_addr *dst,
@@ -232,390 +227,377 @@ int tun_addroute2(struct tun_t *this,
int tun_addaddr(struct tun_t *this,
struct in_addr *addr,
- struct in_addr *dstaddr,
- struct in_addr *netmask) {
+ struct in_addr *dstaddr, struct in_addr *netmask)
+{
#if defined(__linux__)
- struct {
- struct nlmsghdr n;
- struct ifaddrmsg i;
- char buf[TUN_NLBUFSIZE];
- } req;
-
- struct sockaddr_nl local;
- socklen_t addr_len;
- int fd;
- int status;
-
- struct sockaddr_nl nladdr;
- struct iovec iov;
- struct msghdr msg;
-
- if (!this->addrs) /* Use ioctl for first addr to make ping work */
- return tun_setaddr(this, addr, dstaddr, netmask);
-
- memset(&req, 0, sizeof(req));
- req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
- req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE;
- req.n.nlmsg_type = RTM_NEWADDR;
- req.i.ifa_family = AF_INET;
- req.i.ifa_prefixlen = 32; /* 32 FOR IPv4 */
- req.i.ifa_flags = 0;
- req.i.ifa_scope = RT_SCOPE_HOST; /* TODO or 0 */
- if (tun_gifindex(this, &req.i.ifa_index)) {
- return -1;
- }
-
- tun_nlattr(&req.n, sizeof(req), IFA_ADDRESS, addr, sizeof(addr));
- tun_nlattr(&req.n, sizeof(req), IFA_LOCAL, dstaddr, sizeof(dstaddr));
-
- if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0) {
- sys_err(LOG_ERR, __FILE__, __LINE__, errno,
- "socket() failed");
- return -1;
- }
-
- memset(&local, 0, sizeof(local));
- local.nl_family = AF_NETLINK;
- local.nl_groups = 0;
-
- if (bind(fd, (struct sockaddr*)&local, sizeof(local)) < 0) {
- sys_err(LOG_ERR, __FILE__, __LINE__, errno,
- "bind() failed");
- close(fd);
- return -1;
- }
-
- addr_len = sizeof(local);
- if (getsockname(fd, (struct sockaddr*)&local, &addr_len) < 0) {
- sys_err(LOG_ERR, __FILE__, __LINE__, errno,
- "getsockname() failed");
- close(fd);
- return -1;
- }
-
- if (addr_len != sizeof(local)) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "Wrong address length %d", addr_len);
- close(fd);
- return -1;
- }
-
- if (local.nl_family != AF_NETLINK) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "Wrong address family %d", local.nl_family);
- close(fd);
- return -1;
- }
-
- iov.iov_base = (void*)&req.n;
- iov.iov_len = req.n.nlmsg_len;
-
- msg.msg_name = (void*)&nladdr;
- msg.msg_namelen = sizeof(nladdr),
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
- msg.msg_control = NULL;
- msg.msg_controllen = 0;
- msg.msg_flags = 0;
-
- memset(&nladdr, 0, sizeof(nladdr));
- nladdr.nl_family = AF_NETLINK;
- nladdr.nl_pid = 0;
- nladdr.nl_groups = 0;
-
- req.n.nlmsg_seq = 0;
- req.n.nlmsg_flags |= NLM_F_ACK;
-
- status = sendmsg(fd, &msg, 0); /* TODO Error check */
-
- tun_sifflags(this, IFF_UP | IFF_RUNNING); /* TODO */
- close(fd);
- this->addrs++;
- return 0;
+ struct {
+ struct nlmsghdr n;
+ struct ifaddrmsg i;
+ char buf[TUN_NLBUFSIZE];
+ } req;
+
+ struct sockaddr_nl local;
+ socklen_t addr_len;
+ int fd;
+ int status;
+
+ struct sockaddr_nl nladdr;
+ struct iovec iov;
+ struct msghdr msg;
+
+ if (!this->addrs) /* Use ioctl for first addr to make ping work */
+ return tun_setaddr(this, addr, dstaddr, netmask);
+
+ memset(&req, 0, sizeof(req));
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
+ req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE;
+ req.n.nlmsg_type = RTM_NEWADDR;
+ req.i.ifa_family = AF_INET;
+ req.i.ifa_prefixlen = 32; /* 32 FOR IPv4 */
+ req.i.ifa_flags = 0;
+ req.i.ifa_scope = RT_SCOPE_HOST; /* TODO or 0 */
+ if (tun_gifindex(this, &req.i.ifa_index)) {
+ return -1;
+ }
+
+ tun_nlattr(&req.n, sizeof(req), IFA_ADDRESS, addr, sizeof(addr));
+ tun_nlattr(&req.n, sizeof(req), IFA_LOCAL, dstaddr, sizeof(dstaddr));
+
+ if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno, "socket() failed");
+ return -1;
+ }
+
+ memset(&local, 0, sizeof(local));
+ local.nl_family = AF_NETLINK;
+ local.nl_groups = 0;
+
+ if (bind(fd, (struct sockaddr *)&local, sizeof(local)) < 0) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno, "bind() failed");
+ close(fd);
+ return -1;
+ }
+
+ addr_len = sizeof(local);
+ if (getsockname(fd, (struct sockaddr *)&local, &addr_len) < 0) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno,
+ "getsockname() failed");
+ close(fd);
+ return -1;
+ }
+
+ if (addr_len != sizeof(local)) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "Wrong address length %d", addr_len);
+ close(fd);
+ return -1;
+ }
+
+ if (local.nl_family != AF_NETLINK) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "Wrong address family %d", local.nl_family);
+ close(fd);
+ return -1;
+ }
+
+ iov.iov_base = (void *)&req.n;
+ iov.iov_len = req.n.nlmsg_len;
+
+ msg.msg_name = (void *)&nladdr;
+ msg.msg_namelen = sizeof(nladdr), msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = NULL;
+ msg.msg_controllen = 0;
+ msg.msg_flags = 0;
+
+ memset(&nladdr, 0, sizeof(nladdr));
+ nladdr.nl_family = AF_NETLINK;
+ nladdr.nl_pid = 0;
+ nladdr.nl_groups = 0;
+
+ req.n.nlmsg_seq = 0;
+ req.n.nlmsg_flags |= NLM_F_ACK;
+
+ status = sendmsg(fd, &msg, 0); /* TODO Error check */
+
+ tun_sifflags(this, IFF_UP | IFF_RUNNING); /* TODO */
+ close(fd);
+ this->addrs++;
+ return 0;
#elif defined (__FreeBSD__) || defined (__APPLE__)
- int fd;
- struct ifaliasreq areq;
-
- /* TODO: Is this needed on FreeBSD? */
- if (!this->addrs) /* Use ioctl for first addr to make ping work */
- return tun_setaddr(this, addr, dstaddr, netmask); /* TODO dstaddr */
-
- memset(&areq, 0, sizeof(areq));
+ int fd;
+ struct ifaliasreq areq;
+
+ /* TODO: Is this needed on FreeBSD? */
+ if (!this->addrs) /* Use ioctl for first addr to make ping work */
+ return tun_setaddr(this, addr, dstaddr, netmask); /* TODO dstaddr */
+
+ memset(&areq, 0, sizeof(areq));
+
+ /* Set up interface name */
+ strncpy(areq.ifra_name, this->devname, IFNAMSIZ);
+ areq.ifra_name[IFNAMSIZ - 1] = 0; /* Make sure to terminate */
+
+ ((struct sockaddr_in *)&areq.ifra_addr)->sin_family = AF_INET;
+ ((struct sockaddr_in *)&areq.ifra_addr)->sin_len =
+ sizeof(areq.ifra_addr);
+ ((struct sockaddr_in *)&areq.ifra_addr)->sin_addr.s_addr = addr->s_addr;
+
+ ((struct sockaddr_in *)&areq.ifra_mask)->sin_family = AF_INET;
+ ((struct sockaddr_in *)&areq.ifra_mask)->sin_len =
+ sizeof(areq.ifra_mask);
+ ((struct sockaddr_in *)&areq.ifra_mask)->sin_addr.s_addr =
+ netmask->s_addr;
+
+ /* For some reason FreeBSD uses ifra_broadcast for specifying dstaddr */
+ ((struct sockaddr_in *)&areq.ifra_broadaddr)->sin_family = AF_INET;
+ ((struct sockaddr_in *)&areq.ifra_broadaddr)->sin_len =
+ sizeof(areq.ifra_broadaddr);
+ ((struct sockaddr_in *)&areq.ifra_broadaddr)->sin_addr.s_addr =
+ dstaddr->s_addr;
+
+ /* Create a channel to the NET kernel. */
+ if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno, "socket() failed");
+ return -1;
+ }
+
+ if (ioctl(fd, SIOCAIFADDR, (void *)&areq) < 0) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno,
+ "ioctl(SIOCAIFADDR) failed");
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+ this->addrs++;
+ return 0;
- /* Set up interface name */
- strncpy(areq.ifra_name, this->devname, IFNAMSIZ);
- areq.ifra_name[IFNAMSIZ-1] = 0; /* Make sure to terminate */
-
- ((struct sockaddr_in*) &areq.ifra_addr)->sin_family = AF_INET;
- ((struct sockaddr_in*) &areq.ifra_addr)->sin_len = sizeof(areq.ifra_addr);
- ((struct sockaddr_in*) &areq.ifra_addr)->sin_addr.s_addr = addr->s_addr;
-
- ((struct sockaddr_in*) &areq.ifra_mask)->sin_family = AF_INET;
- ((struct sockaddr_in*) &areq.ifra_mask)->sin_len = sizeof(areq.ifra_mask);
- ((struct sockaddr_in*) &areq.ifra_mask)->sin_addr.s_addr = netmask->s_addr;
-
- /* For some reason FreeBSD uses ifra_broadcast for specifying dstaddr */
- ((struct sockaddr_in*) &areq.ifra_broadaddr)->sin_family = AF_INET;
- ((struct sockaddr_in*) &areq.ifra_broadaddr)->sin_len =
- sizeof(areq.ifra_broadaddr);
- ((struct sockaddr_in*) &areq.ifra_broadaddr)->sin_addr.s_addr =
- dstaddr->s_addr;
-
- /* Create a channel to the NET kernel. */
- if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
- sys_err(LOG_ERR, __FILE__, __LINE__, errno,
- "socket() failed");
- return -1;
- }
-
- if (ioctl(fd, SIOCAIFADDR, (void *) &areq) < 0) {
- sys_err(LOG_ERR, __FILE__, __LINE__, errno,
- "ioctl(SIOCAIFADDR) failed");
- close(fd);
- return -1;
- }
+#elif defined (__sun__)
- close(fd);
- this->addrs++;
- return 0;
+ if (!this->addrs) /* Use ioctl for first addr to make ping work */
+ return tun_setaddr(this, addr, dstaddr, netmask);
-#elif defined (__sun__)
-
- if (!this->addrs) /* Use ioctl for first addr to make ping work */
- return tun_setaddr(this, addr, dstaddr, netmask);
-
- sys_err(LOG_ERR, __FILE__, __LINE__, errno,
- "Setting multiple addresses not possible on Solaris");
- return -1;
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno,
+ "Setting multiple addresses not possible on Solaris");
+ return -1;
#else
#error "Unknown platform!"
#endif
-
-}
+}
int tun_setaddr(struct tun_t *this,
struct in_addr *addr,
- struct in_addr *dstaddr,
- struct in_addr *netmask)
+ struct in_addr *dstaddr, struct in_addr *netmask)
{
- struct ifreq ifr;
- int fd;
+ struct ifreq ifr;
+ int fd;
- memset (&ifr, '\0', sizeof (ifr));
- ifr.ifr_addr.sa_family = AF_INET;
- ifr.ifr_dstaddr.sa_family = AF_INET;
+ memset(&ifr, '\0', sizeof(ifr));
+ ifr.ifr_addr.sa_family = AF_INET;
+ ifr.ifr_dstaddr.sa_family = AF_INET;
#if defined(__linux__)
- ifr.ifr_netmask.sa_family = AF_INET;
+ ifr.ifr_netmask.sa_family = AF_INET;
#elif defined(__FreeBSD__) || defined (__APPLE__)
- ((struct sockaddr_in *) &ifr.ifr_addr)->sin_len =
- sizeof (struct sockaddr_in);
- ((struct sockaddr_in *) &ifr.ifr_dstaddr)->sin_len =
- sizeof (struct sockaddr_in);
+ ((struct sockaddr_in *)&ifr.ifr_addr)->sin_len =
+ sizeof(struct sockaddr_in);
+ ((struct sockaddr_in *)&ifr.ifr_dstaddr)->sin_len =
+ sizeof(struct sockaddr_in);
#endif
- strncpy(ifr.ifr_name, this->devname, IFNAMSIZ);
- ifr.ifr_name[IFNAMSIZ-1] = 0; /* Make sure to terminate */
-
- /* Create a channel to the NET kernel. */
- if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
- sys_err(LOG_ERR, __FILE__, __LINE__, errno,
- "socket() failed");
- return -1;
- }
-
- if (addr) { /* Set the interface address */
- this->addr.s_addr = addr->s_addr;
- memcpy(&((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr, addr,
- sizeof(*addr));
- if (ioctl(fd, SIOCSIFADDR, (void *) &ifr) < 0) {
- if (errno != EEXIST) {
- sys_err(LOG_ERR, __FILE__, __LINE__, errno,
- "ioctl(SIOCSIFADDR) failed");
- }
- else {
- sys_err(LOG_WARNING, __FILE__, __LINE__, errno,
- "ioctl(SIOCSIFADDR): Address already exists");
- }
- close(fd);
- return -1;
- }
- }
-
- if (dstaddr) { /* Set the destination address */
- this->dstaddr.s_addr = dstaddr->s_addr;
- memcpy(&((struct sockaddr_in *) &ifr.ifr_dstaddr)->sin_addr,
- dstaddr, sizeof(*dstaddr));
- if (ioctl(fd, SIOCSIFDSTADDR, (caddr_t) &ifr) < 0) {
- sys_err(LOG_ERR, __FILE__, __LINE__, errno,
- "ioctl(SIOCSIFDSTADDR) failed");
- close(fd);
- return -1;
- }
- }
-
- if (netmask) { /* Set the netmask */
- this->netmask.s_addr = netmask->s_addr;
+ strncpy(ifr.ifr_name, this->devname, IFNAMSIZ);
+ ifr.ifr_name[IFNAMSIZ - 1] = 0; /* Make sure to terminate */
+
+ /* Create a channel to the NET kernel. */
+ if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno, "socket() failed");
+ return -1;
+ }
+
+ if (addr) { /* Set the interface address */
+ this->addr.s_addr = addr->s_addr;
+ memcpy(&((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr, addr,
+ sizeof(*addr));
+ if (ioctl(fd, SIOCSIFADDR, (void *)&ifr) < 0) {
+ if (errno != EEXIST) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno,
+ "ioctl(SIOCSIFADDR) failed");
+ } else {
+ sys_err(LOG_WARNING, __FILE__, __LINE__, errno,
+ "ioctl(SIOCSIFADDR): Address already exists");
+ }
+ close(fd);
+ return -1;
+ }
+ }
+
+ if (dstaddr) { /* Set the destination address */
+ this->dstaddr.s_addr = dstaddr->s_addr;
+ memcpy(&((struct sockaddr_in *)&ifr.ifr_dstaddr)->sin_addr,
+ dstaddr, sizeof(*dstaddr));
+ if (ioctl(fd, SIOCSIFDSTADDR, (caddr_t) & ifr) < 0) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno,
+ "ioctl(SIOCSIFDSTADDR) failed");
+ close(fd);
+ return -1;
+ }
+ }
+
+ if (netmask) { /* Set the netmask */
+ this->netmask.s_addr = netmask->s_addr;
#if defined(__linux__)
- memcpy(&((struct sockaddr_in *) &ifr.ifr_netmask)->sin_addr,
- netmask, sizeof(*netmask));
+ memcpy(&((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr,
+ netmask, sizeof(*netmask));
#elif defined(__FreeBSD__) || defined (__APPLE__)
- ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr =
- netmask->s_addr;
+ ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr =
+ netmask->s_addr;
#elif defined(__sun__)
- ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr =
- netmask->s_addr;
+ ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr =
+ netmask->s_addr;
#else
#error "Unknown platform!"
#endif
- if (ioctl(fd, SIOCSIFNETMASK, (void *) &ifr) < 0) {
- sys_err(LOG_ERR, __FILE__, __LINE__, errno,
- "ioctl(SIOCSIFNETMASK) failed");
- close(fd);
- return -1;
- }
- }
-
- close(fd);
- this->addrs++;
-
- /* On linux the route to the interface is set automatically
- on FreeBSD we have to do this manually */
+ if (ioctl(fd, SIOCSIFNETMASK, (void *)&ifr) < 0) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno,
+ "ioctl(SIOCSIFNETMASK) failed");
+ close(fd);
+ return -1;
+ }
+ }
+
+ close(fd);
+ this->addrs++;
- /* TODO: How does it work on Solaris? */
+ /* On linux the route to the interface is set automatically
+ on FreeBSD we have to do this manually */
- tun_sifflags(this, IFF_UP | IFF_RUNNING);
+ /* TODO: How does it work on Solaris? */
+
+ tun_sifflags(this, IFF_UP | IFF_RUNNING);
#if defined(__FreeBSD__) || defined (__APPLE__)
- tun_addroute(this, dstaddr, addr, netmask);
- this->routes = 1;
+ tun_addroute(this, dstaddr, addr, netmask);
+ this->routes = 1;
#endif
- return 0;
+ return 0;
}
int tun_route(struct tun_t *this,
struct in_addr *dst,
- struct in_addr *gateway,
- struct in_addr *mask,
- int delete)
+ struct in_addr *gateway, struct in_addr *mask, int delete)
{
-
- /* TODO: Learn how to set routing table on sun */
+ /* TODO: Learn how to set routing table on sun */
#if defined(__linux__)
- struct rtentry r;
- int fd;
-
- memset (&r, '\0', sizeof (r));
- r.rt_flags = RTF_UP | RTF_GATEWAY; /* RTF_HOST not set */
+ struct rtentry r;
+ int fd;
+
+ memset(&r, '\0', sizeof(r));
+ r.rt_flags = RTF_UP | RTF_GATEWAY; /* RTF_HOST not set */
+
+ /* Create a channel to the NET kernel. */
+ if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno, "socket() failed");
+ return -1;
+ }
+
+ r.rt_dst.sa_family = AF_INET;
+ r.rt_gateway.sa_family = AF_INET;
+ r.rt_genmask.sa_family = AF_INET;
+ memcpy(&((struct sockaddr_in *)&r.rt_dst)->sin_addr, dst, sizeof(*dst));
+ memcpy(&((struct sockaddr_in *)&r.rt_gateway)->sin_addr, gateway,
+ sizeof(*gateway));
+ memcpy(&((struct sockaddr_in *)&r.rt_genmask)->sin_addr, mask,
+ sizeof(*mask));
+
+ if (delete) {
+ if (ioctl(fd, SIOCDELRT, (void *)&r) < 0) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno,
+ "ioctl(SIOCDELRT) failed");
+ close(fd);
+ return -1;
+ }
+ } else {
+ if (ioctl(fd, SIOCADDRT, (void *)&r) < 0) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno,
+ "ioctl(SIOCADDRT) failed");
+ close(fd);
+ return -1;
+ }
+ }
+ close(fd);
+ return 0;
- /* Create a channel to the NET kernel. */
- if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
- sys_err(LOG_ERR, __FILE__, __LINE__, errno,
- "socket() failed");
- return -1;
- }
-
- r.rt_dst.sa_family = AF_INET;
- r.rt_gateway.sa_family = AF_INET;
- r.rt_genmask.sa_family = AF_INET;
- memcpy(&((struct sockaddr_in *) &r.rt_dst)->sin_addr, dst, sizeof(*dst));
- memcpy(&((struct sockaddr_in *) &r.rt_gateway)->sin_addr, gateway,
- sizeof(*gateway));
- memcpy(&((struct sockaddr_in *) &r.rt_genmask)->sin_addr, mask,
- sizeof(*mask));
-
- if (delete) {
- if (ioctl(fd, SIOCDELRT, (void *) &r) < 0) {
- sys_err(LOG_ERR, __FILE__, __LINE__, errno,
- "ioctl(SIOCDELRT) failed");
- close(fd);
- return -1;
- }
- }
- else {
- if (ioctl(fd, SIOCADDRT, (void *) &r) < 0) {
- sys_err(LOG_ERR, __FILE__, __LINE__, errno,
- "ioctl(SIOCADDRT) failed");
- close(fd);
- return -1;
- }
- }
- close(fd);
- return 0;
-
#elif defined(__FreeBSD__) || defined (__APPLE__)
-struct {
- struct rt_msghdr rt;
- struct sockaddr_in dst;
- struct sockaddr_in gate;
- struct sockaddr_in mask;
-} req;
-
- int fd;
- struct rt_msghdr *rtm;
-
- if((fd = socket(AF_ROUTE, SOCK_RAW, 0)) == -1) {
- sys_err(LOG_ERR, __FILE__, __LINE__, errno,
- "socket() failed");
- return -1;
- }
-
- memset(&req, 0x00, sizeof(req));
-
- rtm = &req.rt;
-
- rtm->rtm_msglen = sizeof(req);
- rtm->rtm_version = RTM_VERSION;
- if (delete) {
- rtm->rtm_type = RTM_DELETE;
- }
- else {
- rtm->rtm_type = RTM_ADD;
- }
- rtm->rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC; /* TODO */
- rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
- rtm->rtm_pid = getpid();
- rtm->rtm_seq = 0044; /* TODO */
-
- req.dst.sin_family = AF_INET;
- req.dst.sin_len = sizeof(req.dst);
- req.mask.sin_family = AF_INET;
- req.mask.sin_len = sizeof(req.mask);
- req.gate.sin_family = AF_INET;
- req.gate.sin_len = sizeof(req.gate);
-
- req.dst.sin_addr.s_addr = dst->s_addr;
- req.mask.sin_addr.s_addr = mask->s_addr;
- req.gate.sin_addr.s_addr = gateway->s_addr;
-
- if(write(fd, rtm, rtm->rtm_msglen) < 0) {
- sys_err(LOG_ERR, __FILE__, __LINE__, errno,
- "write() failed");
- close(fd);
- return -1;
- }
- close(fd);
- return 0;
+ struct {
+ struct rt_msghdr rt;
+ struct sockaddr_in dst;
+ struct sockaddr_in gate;
+ struct sockaddr_in mask;
+ } req;
+
+ int fd;
+ struct rt_msghdr *rtm;
+
+ if ((fd = socket(AF_ROUTE, SOCK_RAW, 0)) == -1) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno, "socket() failed");
+ return -1;
+ }
+
+ memset(&req, 0x00, sizeof(req));
+
+ rtm = &req.rt;
+
+ rtm->rtm_msglen = sizeof(req);
+ rtm->rtm_version = RTM_VERSION;
+ if (delete) {
+ rtm->rtm_type = RTM_DELETE;
+ } else {
+ rtm->rtm_type = RTM_ADD;
+ }
+ rtm->rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC; /* TODO */
+ rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
+ rtm->rtm_pid = getpid();
+ rtm->rtm_seq = 0044; /* TODO */
+
+ req.dst.sin_family = AF_INET;
+ req.dst.sin_len = sizeof(req.dst);
+ req.mask.sin_family = AF_INET;
+ req.mask.sin_len = sizeof(req.mask);
+ req.gate.sin_family = AF_INET;
+ req.gate.sin_len = sizeof(req.gate);
+
+ req.dst.sin_addr.s_addr = dst->s_addr;
+ req.mask.sin_addr.s_addr = mask->s_addr;
+ req.gate.sin_addr.s_addr = gateway->s_addr;
+
+ if (write(fd, rtm, rtm->rtm_msglen) < 0) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno, "write() failed");
+ close(fd);
+ return -1;
+ }
+ close(fd);
+ return 0;
#elif defined(__sun__)
- sys_err(LOG_WARNING, __FILE__, __LINE__, errno,
- "Could not set up routing on Solaris. Please add route manually.");
- return 0;
-
+ sys_err(LOG_WARNING, __FILE__, __LINE__, errno,
+ "Could not set up routing on Solaris. Please add route manually.");
+ return 0;
+
#else
#error "Unknown platform!"
#endif
@@ -624,172 +606,179 @@ struct {
int tun_addroute(struct tun_t *this,
struct in_addr *dst,
- struct in_addr *gateway,
- struct in_addr *mask)
+ struct in_addr *gateway, struct in_addr *mask)
{
- return tun_route(this, dst, gateway, mask, 0);
+ return tun_route(this, dst, gateway, mask, 0);
}
int tun_delroute(struct tun_t *this,
struct in_addr *dst,
- struct in_addr *gateway,
- struct in_addr *mask)
+ struct in_addr *gateway, struct in_addr *mask)
{
- return tun_route(this, dst, gateway, mask, 1);
+ return tun_route(this, dst, gateway, mask, 1);
}
-
int tun_new(struct tun_t **tun)
{
#if defined(__linux__)
- struct ifreq ifr;
+ struct ifreq ifr;
#elif defined(__FreeBSD__) || defined (__APPLE__)
- char devname[IFNAMSIZ+5]; /* "/dev/" + ifname */
- int devnum;
- struct ifaliasreq areq;
- int fd;
+ char devname[IFNAMSIZ + 5]; /* "/dev/" + ifname */
+ int devnum;
+ struct ifaliasreq areq;
+ int fd;
#elif defined(__sun__)
- int if_fd, ppa = -1;
- static int ip_fd = 0;
- int muxid;
- struct ifreq ifr;
+ int if_fd, ppa = -1;
+ static int ip_fd = 0;
+ int muxid;
+ struct ifreq ifr;
#else
#error "Unknown platform!"
#endif
-
- if (!(*tun = calloc(1, sizeof(struct tun_t)))) {
- sys_err(LOG_ERR, __FILE__, __LINE__, errno, "calloc() failed");
- return EOF;
- }
-
- (*tun)->cb_ind = NULL;
- (*tun)->addrs = 0;
- (*tun)->routes = 0;
-
-#if defined(__linux__)
- /* Open the actual tun device */
- if (((*tun)->fd = open("/dev/net/tun", O_RDWR)) < 0) {
- sys_err(LOG_ERR, __FILE__, __LINE__, errno, "open() failed");
- return -1;
- }
-
- /* Set device flags. For some weird reason this is also the method
- used to obtain the network interface name */
- memset(&ifr, 0, sizeof(ifr));
- ifr.ifr_flags = IFF_TUN | IFF_NO_PI; /* Tun device, no packet info */
- if (ioctl((*tun)->fd, TUNSETIFF, (void *) &ifr) < 0) {
- sys_err(LOG_ERR, __FILE__, __LINE__, errno, "ioctl() failed");
- close((*tun)->fd);
- return -1;
- }
-
- strncpy((*tun)->devname, ifr.ifr_name, IFNAMSIZ);
- (*tun)->devname[IFNAMSIZ-1] = 0;
-
- ioctl((*tun)->fd, TUNSETNOCSUM, 1); /* Disable checksums */
- return 0;
-
-#elif defined(__FreeBSD__) || defined (__APPLE__)
-
- /* Find suitable device */
- for (devnum = 0; devnum < 255; devnum++) { /* TODO 255 */
- snprintf(devname, sizeof(devname), "/dev/tun%d", devnum);
- devname[sizeof(devname)] = 0;
- if (((*tun)->fd = open(devname, O_RDWR)) >= 0) break;
- if (errno != EBUSY) break;
- }
- if ((*tun)->fd < 0) {
- sys_err(LOG_ERR, __FILE__, __LINE__, errno, "Can't find tunnel device");
- return -1;
- }
-
- snprintf((*tun)->devname, sizeof((*tun)->devname), "tun%d", devnum);
- (*tun)->devname[sizeof((*tun)->devname)] = 0;
- /* The tun device we found might have "old" IP addresses allocated */
- /* We need to delete those. This problem is not present on Linux */
+ if (!(*tun = calloc(1, sizeof(struct tun_t)))) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno, "calloc() failed");
+ return EOF;
+ }
- memset(&areq, 0, sizeof(areq));
+ (*tun)->cb_ind = NULL;
+ (*tun)->addrs = 0;
+ (*tun)->routes = 0;
- /* Set up interface name */
- strncpy(areq.ifra_name, (*tun)->devname, IFNAMSIZ);
- areq.ifra_name[IFNAMSIZ-1] = 0; /* Make sure to terminate */
+#if defined(__linux__)
+ /* Open the actual tun device */
+ if (((*tun)->fd = open("/dev/net/tun", O_RDWR)) < 0) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno, "open() failed");
+ return -1;
+ }
+
+ /* Set device flags. For some weird reason this is also the method
+ used to obtain the network interface name */
+ memset(&ifr, 0, sizeof(ifr));
+ ifr.ifr_flags = IFF_TUN | IFF_NO_PI; /* Tun device, no packet info */
+ if (ioctl((*tun)->fd, TUNSETIFF, (void *)&ifr) < 0) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno, "ioctl() failed");
+ close((*tun)->fd);
+ return -1;
+ }
+
+ strncpy((*tun)->devname, ifr.ifr_name, IFNAMSIZ);
+ (*tun)->devname[IFNAMSIZ - 1] = 0;
+
+ ioctl((*tun)->fd, TUNSETNOCSUM, 1); /* Disable checksums */
+ return 0;
- /* Create a channel to the NET kernel. */
- if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
- sys_err(LOG_ERR, __FILE__, __LINE__, errno,
- "socket() failed");
- return -1;
- }
-
- /* Delete any IP addresses until SIOCDIFADDR fails */
- while (ioctl(fd, SIOCDIFADDR, (void *) &areq) != -1);
+#elif defined(__FreeBSD__) || defined (__APPLE__)
- close(fd);
- return 0;
+ /* Find suitable device */
+ for (devnum = 0; devnum < 255; devnum++) { /* TODO 255 */
+ snprintf(devname, sizeof(devname), "/dev/tun%d", devnum);
+ devname[sizeof(devname)] = 0;
+ if (((*tun)->fd = open(devname, O_RDWR)) >= 0)
+ break;
+ if (errno != EBUSY)
+ break;
+ }
+ if ((*tun)->fd < 0) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno,
+ "Can't find tunnel device");
+ return -1;
+ }
+
+ snprintf((*tun)->devname, sizeof((*tun)->devname), "tun%d", devnum);
+ (*tun)->devname[sizeof((*tun)->devname)] = 0;
+
+ /* The tun device we found might have "old" IP addresses allocated */
+ /* We need to delete those. This problem is not present on Linux */
+
+ memset(&areq, 0, sizeof(areq));
+
+ /* Set up interface name */
+ strncpy(areq.ifra_name, (*tun)->devname, IFNAMSIZ);
+ areq.ifra_name[IFNAMSIZ - 1] = 0; /* Make sure to terminate */
+
+ /* Create a channel to the NET kernel. */
+ if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno, "socket() failed");
+ return -1;
+ }
+
+ /* Delete any IP addresses until SIOCDIFADDR fails */
+ while (ioctl(fd, SIOCDIFADDR, (void *)&areq) != -1) ;
+
+ close(fd);
+ return 0;
#elif defined(__sun__)
- if( (ip_fd = open("/dev/udp", O_RDWR, 0)) < 0){
- sys_err(LOG_ERR, __FILE__, __LINE__, errno, "Can't open /dev/udp");
- return -1;
- }
-
- if( ((*tun)->fd = open("/dev/tun", O_RDWR, 0)) < 0){
- sys_err(LOG_ERR, __FILE__, __LINE__, errno, "Can't open /dev/tun");
- return -1;
- }
-
- /* Assign a new PPA and get its unit number. */
- if( (ppa = ioctl((*tun)->fd, TUNNEWPPA, -1)) < 0){
- sys_err(LOG_ERR, __FILE__, __LINE__, errno, "Can't assign new interface");
- return -1;
- }
-
- if( (if_fd = open("/dev/tun", O_RDWR, 0)) < 0){
- sys_err(LOG_ERR, __FILE__, __LINE__, errno, "Can't open /dev/tun (2)");
- return -1;
- }
- if(ioctl(if_fd, I_PUSH, "ip") < 0){
- sys_err(LOG_ERR, __FILE__, __LINE__, errno, "Can't push IP module");
- return -1;
- }
-
- /* Assign ppa according to the unit number returned by tun device */
- if(ioctl(if_fd, IF_UNITSEL, (char *)&ppa) < 0){
- sys_err(LOG_ERR, __FILE__, __LINE__, errno, "Can't set PPA %d", ppa);
- return -1;
- }
-
- /* Link the two streams */
- if ((muxid = ioctl(ip_fd, I_LINK, if_fd)) < 0) {
- sys_err(LOG_ERR, __FILE__, __LINE__, errno, "Can't link TUN device to IP");
- return -1;
- }
-
- close (if_fd);
-
- snprintf((*tun)->devname, sizeof((*tun)->devname), "tun%d", ppa);
- (*tun)->devname[sizeof((*tun)->devname)] = 0;
-
- memset(&ifr, 0, sizeof(ifr));
- strcpy(ifr.ifr_name, (*tun)->devname);
- ifr.ifr_ip_muxid = muxid;
-
- if (ioctl(ip_fd, SIOCSIFMUXID, &ifr) < 0) {
- ioctl(ip_fd, I_PUNLINK, muxid);
- sys_err(LOG_ERR, __FILE__, __LINE__, errno, "Can't set multiplexor id");
- return -1;
- }
-
- /* if (fcntl (fd, F_SETFL, O_NONBLOCK) < 0)
- msg (M_ERR, "Set file descriptor to non-blocking failed"); */
-
- return 0;
+ if ((ip_fd = open("/dev/udp", O_RDWR, 0)) < 0) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno,
+ "Can't open /dev/udp");
+ return -1;
+ }
+
+ if (((*tun)->fd = open("/dev/tun", O_RDWR, 0)) < 0) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno,
+ "Can't open /dev/tun");
+ return -1;
+ }
+
+ /* Assign a new PPA and get its unit number. */
+ if ((ppa = ioctl((*tun)->fd, TUNNEWPPA, -1)) < 0) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno,
+ "Can't assign new interface");
+ return -1;
+ }
+
+ if ((if_fd = open("/dev/tun", O_RDWR, 0)) < 0) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno,
+ "Can't open /dev/tun (2)");
+ return -1;
+ }
+ if (ioctl(if_fd, I_PUSH, "ip") < 0) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno,
+ "Can't push IP module");
+ return -1;
+ }
+
+ /* Assign ppa according to the unit number returned by tun device */
+ if (ioctl(if_fd, IF_UNITSEL, (char *)&ppa) < 0) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno, "Can't set PPA %d",
+ ppa);
+ return -1;
+ }
+
+ /* Link the two streams */
+ if ((muxid = ioctl(ip_fd, I_LINK, if_fd)) < 0) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno,
+ "Can't link TUN device to IP");
+ return -1;
+ }
+
+ close(if_fd);
+
+ snprintf((*tun)->devname, sizeof((*tun)->devname), "tun%d", ppa);
+ (*tun)->devname[sizeof((*tun)->devname)] = 0;
+
+ memset(&ifr, 0, sizeof(ifr));
+ strcpy(ifr.ifr_name, (*tun)->devname);
+ ifr.ifr_ip_muxid = muxid;
+
+ if (ioctl(ip_fd, SIOCSIFMUXID, &ifr) < 0) {
+ ioctl(ip_fd, I_PUNLINK, muxid);
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno,
+ "Can't set multiplexor id");
+ return -1;
+ }
+
+ /* if (fcntl (fd, F_SETFL, O_NONBLOCK) < 0)
+ msg (M_ERR, "Set file descriptor to non-blocking failed"); */
+
+ return 0;
#else
#error "Unknown platform!"
@@ -800,107 +789,106 @@ int tun_new(struct tun_t **tun)
int tun_free(struct tun_t *tun)
{
- if (tun->routes) {
- tun_delroute(tun, &tun->dstaddr, &tun->addr, &tun->netmask);
- }
+ if (tun->routes) {
+ tun_delroute(tun, &tun->dstaddr, &tun->addr, &tun->netmask);
+ }
- if (close(tun->fd)) {
- sys_err(LOG_ERR, __FILE__, __LINE__, errno, "close() failed");
- }
+ if (close(tun->fd)) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno, "close() failed");
+ }
- /* TODO: For solaris we need to unlink streams */
+ /* TODO: For solaris we need to unlink streams */
- free(tun);
- return 0;
+ free(tun);
+ return 0;
}
-
-int tun_set_cb_ind(struct tun_t *this,
- int (*cb_ind) (struct tun_t *tun, void *pack, unsigned len)) {
- this->cb_ind = cb_ind;
- return 0;
+int tun_set_cb_ind(struct tun_t *this,
+ int (*cb_ind) (struct tun_t * tun, void *pack, unsigned len))
+{
+ this->cb_ind = cb_ind;
+ return 0;
}
-
int tun_decaps(struct tun_t *this)
{
#if defined(__linux__) || defined (__FreeBSD__) || defined (__APPLE__)
- unsigned char buffer[PACKET_MAX];
- int status;
-
- if ((status = read(this->fd, buffer, sizeof(buffer))) <= 0) {
- sys_err(LOG_ERR, __FILE__, __LINE__, errno, "read() failed");
- return -1;
- }
-
- if (this->cb_ind)
- return this->cb_ind(this, buffer, status);
+ unsigned char buffer[PACKET_MAX];
+ int status;
- return 0;
+ if ((status = read(this->fd, buffer, sizeof(buffer))) <= 0) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno, "read() failed");
+ return -1;
+ }
+
+ if (this->cb_ind)
+ return this->cb_ind(this, buffer, status);
+
+ return 0;
#elif defined (__sun__)
- unsigned char buffer[PACKET_MAX];
- struct strbuf sbuf;
- int f = 0;
-
- sbuf.maxlen = PACKET_MAX;
- sbuf.buf = buffer;
- if (getmsg(this->fd, NULL, &sbuf, &f) < 0) {
- sys_err(LOG_ERR, __FILE__, __LINE__, errno, "getmsg() failed");
- return -1;
- }
+ unsigned char buffer[PACKET_MAX];
+ struct strbuf sbuf;
+ int f = 0;
- if (this->cb_ind)
- return this->cb_ind(this, buffer, sbuf.len);
+ sbuf.maxlen = PACKET_MAX;
+ sbuf.buf = buffer;
+ if (getmsg(this->fd, NULL, &sbuf, &f) < 0) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno, "getmsg() failed");
+ return -1;
+ }
+
+ if (this->cb_ind)
+ return this->cb_ind(this, buffer, sbuf.len);
+
+ return 0;
- return 0;
-
#endif
}
-
int tun_encaps(struct tun_t *tun, void *pack, unsigned len)
{
#if defined(__linux__) || defined (__FreeBSD__) || defined (__APPLE__)
- return write(tun->fd, pack, len);
+ return write(tun->fd, pack, len);
#elif defined (__sun__)
- struct strbuf sbuf;
- sbuf.len = len;
- sbuf.buf = pack;
- return putmsg(tun->fd, NULL, &sbuf, 0);
+ struct strbuf sbuf;
+ sbuf.len = len;
+ sbuf.buf = pack;
+ return putmsg(tun->fd, NULL, &sbuf, 0);
#endif
}
-int tun_runscript(struct tun_t *tun, char* script) {
-
- char buf[TUN_SCRIPTSIZE];
- char snet[TUN_ADDRSIZE];
- char smask[TUN_ADDRSIZE];
- int rc;
-
- strncpy(snet, inet_ntoa(tun->addr), sizeof(snet));
- snet[sizeof(snet)-1] = 0;
- strncpy(smask, inet_ntoa(tun->netmask), sizeof(smask));
- smask[sizeof(smask)-1] = 0;
-
- /* system("ipup /dev/tun0 192.168.0.10 255.255.255.0"); */
- snprintf(buf, sizeof(buf), "%s %s %s %s",
- script, tun->devname, snet, smask);
- buf[sizeof(buf)-1] = 0;
- rc = system(buf);
- if (rc == -1) {
- sys_err(LOG_ERR, __FILE__, __LINE__, errno, "Error executing command %s",
- buf);
- return -1;
- }
- return 0;
+int tun_runscript(struct tun_t *tun, char *script)
+{
+
+ char buf[TUN_SCRIPTSIZE];
+ char snet[TUN_ADDRSIZE];
+ char smask[TUN_ADDRSIZE];
+ int rc;
+
+ strncpy(snet, inet_ntoa(tun->addr), sizeof(snet));
+ snet[sizeof(snet) - 1] = 0;
+ strncpy(smask, inet_ntoa(tun->netmask), sizeof(smask));
+ smask[sizeof(smask) - 1] = 0;
+
+ /* system("ipup /dev/tun0 192.168.0.10 255.255.255.0"); */
+ snprintf(buf, sizeof(buf), "%s %s %s %s",
+ script, tun->devname, snet, smask);
+ buf[sizeof(buf) - 1] = 0;
+ rc = system(buf);
+ if (rc == -1) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, errno,
+ "Error executing command %s", buf);
+ return -1;
+ }
+ return 0;
}
diff --git a/lib/tun.h b/lib/tun.h
index 7972c53..ce7b91c 100644
--- a/lib/tun.h
+++ b/lib/tun.h
@@ -12,44 +12,42 @@
#ifndef _TUN_H
#define _TUN_H
-#define PACKET_MAX 8196 /* Maximum packet size we receive */
+#define PACKET_MAX 8196 /* Maximum packet size we receive */
#define TUN_SCRIPTSIZE 256
#define TUN_ADDRSIZE 128
#define TUN_NLBUFSIZE 1024
struct tun_packet_t {
- unsigned int ver:4;
- unsigned int ihl:4;
- unsigned int dscp:6;
- unsigned int ecn:2;
- unsigned int length:16;
- unsigned int id:16;
- unsigned int flags:3;
- unsigned int fragment:13;
- unsigned int ttl:8;
- unsigned int protocol:8;
- unsigned int check:16;
- unsigned int src:32;
- unsigned int dst:32;
+ unsigned int ver:4;
+ unsigned int ihl:4;
+ unsigned int dscp:6;
+ unsigned int ecn:2;
+ unsigned int length:16;
+ unsigned int id:16;
+ unsigned int flags:3;
+ unsigned int fragment:13;
+ unsigned int ttl:8;
+ unsigned int protocol:8;
+ unsigned int check:16;
+ unsigned int src:32;
+ unsigned int dst:32;
};
-
/* ***********************************************************
* Information storage for each tun instance
*************************************************************/
struct tun_t {
- int fd; /* File descriptor to tun interface */
- struct in_addr addr;
- struct in_addr dstaddr;
- struct in_addr netmask;
- int addrs; /* Number of allocated IP addresses */
- int routes; /* One if we allocated an automatic route */
- char devname[IFNAMSIZ];/* Name of the tun device */
- int (*cb_ind) (struct tun_t *tun, void *pack, unsigned len);
+ int fd; /* File descriptor to tun interface */
+ struct in_addr addr;
+ struct in_addr dstaddr;
+ struct in_addr netmask;
+ int addrs; /* Number of allocated IP addresses */
+ int routes; /* One if we allocated an automatic route */
+ char devname[IFNAMSIZ]; /* Name of the tun device */
+ int (*cb_ind) (struct tun_t * tun, void *pack, unsigned len);
};
-
extern int tun_new(struct tun_t **tun);
extern int tun_free(struct tun_t *tun);
extern int tun_decaps(struct tun_t *this);
@@ -58,17 +56,16 @@ extern int tun_encaps(struct tun_t *tun, void *pack, unsigned len);
extern int tun_addaddr(struct tun_t *this, struct in_addr *addr,
struct in_addr *dstaddr, struct in_addr *netmask);
-
-extern int tun_setaddr(struct tun_t *this, struct in_addr *our_adr,
+extern int tun_setaddr(struct tun_t *this, struct in_addr *our_adr,
struct in_addr *his_adr, struct in_addr *net_mask);
-int tun_addroute(struct tun_t *this, struct in_addr *dst,
+int tun_addroute(struct tun_t *this, struct in_addr *dst,
struct in_addr *gateway, struct in_addr *mask);
-extern int tun_set_cb_ind(struct tun_t *this,
- int (*cb_ind) (struct tun_t *tun, void *pack, unsigned len));
-
+extern int tun_set_cb_ind(struct tun_t *this,
+ int (*cb_ind) (struct tun_t * tun, void *pack,
+ unsigned len));
-extern int tun_runscript(struct tun_t *tun, char* script);
+extern int tun_runscript(struct tun_t *tun, char *script);
-#endif /* !_TUN_H */
+#endif /* !_TUN_H */
diff --git a/sgsnemu/cmdline.c b/sgsnemu/cmdline.c
index 1c4c041..1ff1a59 100644
--- a/sgsnemu/cmdline.c
+++ b/sgsnemu/cmdline.c
@@ -23,1560 +23,1732 @@
const char *gengetopt_args_info_purpose = "";
-const char *gengetopt_args_info_usage = "Usage: " CMDLINE_PARSER_PACKAGE " [OPTIONS]...";
+const char *gengetopt_args_info_usage =
+ "Usage: " CMDLINE_PARSER_PACKAGE " [OPTIONS]...";
const char *gengetopt_args_info_help[] = {
- " -h, --help Print help and exit",
- " -V, --version Print version and exit",
- " -d, --debug Run in debug mode (default=off)",
- " -c, --conf=STRING Read configuration file",
- " --pidfile=STRING Filename of process id file (default=`./sgsnemu.pid')",
- " --statedir=STRING Directory of nonvolatile data (default=`./')",
- " --dns=STRING DNS Server to use",
- " -l, --listen=STRING Local interface",
- " -r, --remote=STRING Remote host",
- " --contexts=INT Number of contexts (default=`1')",
- " --timelimit=INT Exit after timelimit seconds (default=`0')",
- " --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)",
- " --rai=STRING Routing Area Information (optional-MCC.MNC.LAC.RAC)",
- " --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')",
- " -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')",
- " --createif Create local network interface (default=off)",
- " -n, --net=STRING Network address for local interface",
- " --defaultroute Create default route (default=off)",
- " --ipup=STRING Script to run after link-up",
- " --ipdown=STRING Script to run after link-down",
- " --pinghost=STRING Ping remote host",
- " --pingrate=INT Number of ping req per second (default=`1')",
- " --pingsize=INT Number of ping data bytes (default=`56')",
- " --pingcount=INT Number of ping req to send (default=`0')",
- " --pingquiet Do not print ping packet info (default=off)",
- " --norecovery Do not send recovery (default=off)",
- 0
+ " -h, --help Print help and exit",
+ " -V, --version Print version and exit",
+ " -d, --debug Run in debug mode (default=off)",
+ " -c, --conf=STRING Read configuration file",
+ " --pidfile=STRING Filename of process id file (default=`./sgsnemu.pid')",
+ " --statedir=STRING Directory of nonvolatile data (default=`./')",
+ " --dns=STRING DNS Server to use",
+ " -l, --listen=STRING Local interface",
+ " -r, --remote=STRING Remote host",
+ " --contexts=INT Number of contexts (default=`1')",
+ " --timelimit=INT Exit after timelimit seconds (default=`0')",
+ " --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)",
+ " --rai=STRING Routing Area Information (optional-MCC.MNC.LAC.RAC)",
+ " --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')",
+ " -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')",
+ " --createif Create local network interface (default=off)",
+ " -n, --net=STRING Network address for local interface",
+ " --defaultroute Create default route (default=off)",
+ " --ipup=STRING Script to run after link-up",
+ " --ipdown=STRING Script to run after link-down",
+ " --pinghost=STRING Ping remote host",
+ " --pingrate=INT Number of ping req per second (default=`1')",
+ " --pingsize=INT Number of ping data bytes (default=`56')",
+ " --pingcount=INT Number of ping req to send (default=`0')",
+ " --pingquiet Do not print ping packet info (default=off)",
+ " --norecovery Do not send recovery (default=off)",
+ 0
};
static
-void clear_given (struct gengetopt_args_info *args_info);
+void clear_given(struct gengetopt_args_info *args_info);
static
-void clear_args (struct gengetopt_args_info *args_info);
+void clear_args(struct gengetopt_args_info *args_info);
static int
-cmdline_parser_internal (int argc, char * const *argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required, const char *additional_error);
-
-struct line_list
-{
- char * string_arg;
- struct line_list * next;
+cmdline_parser_internal(int argc, char *const *argv,
+ struct gengetopt_args_info *args_info, int override,
+ int initialize, int check_required,
+ const char *additional_error);
+
+struct line_list {
+ char *string_arg;
+ struct line_list *next;
};
static struct line_list *cmd_line_list = 0;
static struct line_list *cmd_line_list_tmp = 0;
-static void
-free_cmd_list(void)
+static void free_cmd_list(void)
{
- /* free the list of a previous call */
- if (cmd_line_list)
- {
- while (cmd_line_list) {
- cmd_line_list_tmp = cmd_line_list;
- cmd_line_list = cmd_line_list->next;
- free (cmd_line_list_tmp->string_arg);
- free (cmd_line_list_tmp);
- }
- }
+ /* free the list of a previous call */
+ if (cmd_line_list) {
+ while (cmd_line_list) {
+ cmd_line_list_tmp = cmd_line_list;
+ cmd_line_list = cmd_line_list->next;
+ free(cmd_line_list_tmp->string_arg);
+ free(cmd_line_list_tmp);
+ }
+ }
}
-
-static char *
-gengetopt_strdup (const char *s);
+static char *gengetopt_strdup(const char *s);
static
-void clear_given (struct gengetopt_args_info *args_info)
+void clear_given(struct gengetopt_args_info *args_info)
{
- args_info->help_given = 0 ;
- args_info->version_given = 0 ;
- args_info->debug_given = 0 ;
- args_info->conf_given = 0 ;
- args_info->pidfile_given = 0 ;
- args_info->statedir_given = 0 ;
- args_info->dns_given = 0 ;
- args_info->listen_given = 0 ;
- args_info->remote_given = 0 ;
- args_info->contexts_given = 0 ;
- args_info->timelimit_given = 0 ;
- 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->rai_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 ;
- 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 ;
- args_info->createif_given = 0 ;
- args_info->net_given = 0 ;
- args_info->defaultroute_given = 0 ;
- args_info->ipup_given = 0 ;
- args_info->ipdown_given = 0 ;
- args_info->pinghost_given = 0 ;
- args_info->pingrate_given = 0 ;
- args_info->pingsize_given = 0 ;
- args_info->pingcount_given = 0 ;
- args_info->pingquiet_given = 0 ;
- args_info->norecovery_given = 0 ;
+ args_info->help_given = 0;
+ args_info->version_given = 0;
+ args_info->debug_given = 0;
+ args_info->conf_given = 0;
+ args_info->pidfile_given = 0;
+ args_info->statedir_given = 0;
+ args_info->dns_given = 0;
+ args_info->listen_given = 0;
+ args_info->remote_given = 0;
+ args_info->contexts_given = 0;
+ args_info->timelimit_given = 0;
+ 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->rai_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;
+ 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;
+ args_info->createif_given = 0;
+ args_info->net_given = 0;
+ args_info->defaultroute_given = 0;
+ args_info->ipup_given = 0;
+ args_info->ipdown_given = 0;
+ args_info->pinghost_given = 0;
+ args_info->pingrate_given = 0;
+ args_info->pingsize_given = 0;
+ args_info->pingcount_given = 0;
+ args_info->pingquiet_given = 0;
+ args_info->norecovery_given = 0;
}
static
-void clear_args (struct gengetopt_args_info *args_info)
+void clear_args(struct gengetopt_args_info *args_info)
{
- args_info->debug_flag = 0;
- args_info->conf_arg = NULL;
- args_info->conf_orig = NULL;
- args_info->pidfile_arg = gengetopt_strdup ("./sgsnemu.pid");
- args_info->pidfile_orig = NULL;
- args_info->statedir_arg = gengetopt_strdup ("./");
- args_info->statedir_orig = NULL;
- args_info->dns_arg = NULL;
- args_info->dns_orig = NULL;
- args_info->listen_arg = NULL;
- args_info->listen_orig = NULL;
- args_info->remote_arg = NULL;
- args_info->remote_orig = NULL;
- args_info->contexts_arg = 1;
- args_info->contexts_orig = NULL;
- args_info->timelimit_arg = 0;
- args_info->timelimit_orig = NULL;
- args_info->gtpversion_arg = 1;
- args_info->gtpversion_orig = NULL;
- args_info->apn_arg = gengetopt_strdup ("internet");
- 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->rai_arg = strdup("02509946241207");
- args_info->rai_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;
- args_info->nsapi_orig = NULL;
- args_info->msisdn_arg = gengetopt_strdup ("46702123456");
- args_info->msisdn_orig = NULL;
- 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");
- args_info->uid_orig = NULL;
- args_info->pwd_arg = gengetopt_strdup ("hemmelig");
- args_info->pwd_orig = NULL;
- args_info->createif_flag = 0;
- args_info->net_arg = NULL;
- args_info->net_orig = NULL;
- args_info->defaultroute_flag = 0;
- args_info->ipup_arg = NULL;
- args_info->ipup_orig = NULL;
- args_info->ipdown_arg = NULL;
- args_info->ipdown_orig = NULL;
- args_info->pinghost_arg = NULL;
- args_info->pinghost_orig = NULL;
- args_info->pingrate_arg = 1;
- args_info->pingrate_orig = NULL;
- args_info->pingsize_arg = 56;
- args_info->pingsize_orig = NULL;
- args_info->pingcount_arg = 0;
- args_info->pingcount_orig = NULL;
- args_info->pingquiet_flag = 0;
- args_info->norecovery_flag = 0;
-
+ args_info->debug_flag = 0;
+ args_info->conf_arg = NULL;
+ args_info->conf_orig = NULL;
+ args_info->pidfile_arg = gengetopt_strdup("./sgsnemu.pid");
+ args_info->pidfile_orig = NULL;
+ args_info->statedir_arg = gengetopt_strdup("./");
+ args_info->statedir_orig = NULL;
+ args_info->dns_arg = NULL;
+ args_info->dns_orig = NULL;
+ args_info->listen_arg = NULL;
+ args_info->listen_orig = NULL;
+ args_info->remote_arg = NULL;
+ args_info->remote_orig = NULL;
+ args_info->contexts_arg = 1;
+ args_info->contexts_orig = NULL;
+ args_info->timelimit_arg = 0;
+ args_info->timelimit_orig = NULL;
+ args_info->gtpversion_arg = 1;
+ args_info->gtpversion_orig = NULL;
+ args_info->apn_arg = gengetopt_strdup("internet");
+ 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->rai_arg = strdup("02509946241207");
+ args_info->rai_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;
+ args_info->nsapi_orig = NULL;
+ args_info->msisdn_arg = gengetopt_strdup("46702123456");
+ args_info->msisdn_orig = NULL;
+ 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");
+ args_info->uid_orig = NULL;
+ args_info->pwd_arg = gengetopt_strdup("hemmelig");
+ args_info->pwd_orig = NULL;
+ args_info->createif_flag = 0;
+ args_info->net_arg = NULL;
+ args_info->net_orig = NULL;
+ args_info->defaultroute_flag = 0;
+ args_info->ipup_arg = NULL;
+ args_info->ipup_orig = NULL;
+ args_info->ipdown_arg = NULL;
+ args_info->ipdown_orig = NULL;
+ args_info->pinghost_arg = NULL;
+ args_info->pinghost_orig = NULL;
+ args_info->pingrate_arg = 1;
+ args_info->pingrate_orig = NULL;
+ args_info->pingsize_arg = 56;
+ args_info->pingsize_orig = NULL;
+ args_info->pingcount_arg = 0;
+ args_info->pingcount_orig = NULL;
+ args_info->pingquiet_flag = 0;
+ args_info->norecovery_flag = 0;
+
}
static
void init_args_info(struct gengetopt_args_info *args_info)
{
- args_info->help_help = gengetopt_args_info_help[0] ;
- args_info->version_help = gengetopt_args_info_help[1] ;
- args_info->debug_help = gengetopt_args_info_help[2] ;
- args_info->conf_help = gengetopt_args_info_help[3] ;
- args_info->pidfile_help = gengetopt_args_info_help[4] ;
- args_info->statedir_help = gengetopt_args_info_help[5] ;
- args_info->dns_help = gengetopt_args_info_help[6] ;
- args_info->listen_help = gengetopt_args_info_help[7] ;
- args_info->remote_help = gengetopt_args_info_help[8] ;
- args_info->contexts_help = gengetopt_args_info_help[9] ;
- args_info->timelimit_help = gengetopt_args_info_help[10] ;
- args_info->gtpversion_help = gengetopt_args_info_help[11] ;
- args_info->apn_help = gengetopt_args_info_help[12] ;
- args_info->selmode_help = gengetopt_args_info_help[13] ;
- args_info->imsi_help = gengetopt_args_info_help[14] ;
- args_info->nsapi_help = gengetopt_args_info_help[15] ;
- args_info->msisdn_help = gengetopt_args_info_help[16] ;
- args_info->qos_help = gengetopt_args_info_help[17] ;
- args_info->charging_help = gengetopt_args_info_help[18] ;
- args_info->uid_help = gengetopt_args_info_help[19] ;
- args_info->pwd_help = gengetopt_args_info_help[20] ;
- args_info->createif_help = gengetopt_args_info_help[21] ;
- args_info->net_help = gengetopt_args_info_help[22] ;
- args_info->defaultroute_help = gengetopt_args_info_help[23] ;
- args_info->ipup_help = gengetopt_args_info_help[24] ;
- args_info->ipdown_help = gengetopt_args_info_help[25] ;
- args_info->pinghost_help = gengetopt_args_info_help[26] ;
- args_info->pingrate_help = gengetopt_args_info_help[27] ;
- args_info->pingsize_help = gengetopt_args_info_help[28] ;
- args_info->pingcount_help = gengetopt_args_info_help[29] ;
- args_info->pingquiet_help = gengetopt_args_info_help[30] ;
- args_info->norecovery_help = gengetopt_args_info_help[31] ;
-
+ args_info->help_help = gengetopt_args_info_help[0];
+ args_info->version_help = gengetopt_args_info_help[1];
+ args_info->debug_help = gengetopt_args_info_help[2];
+ args_info->conf_help = gengetopt_args_info_help[3];
+ args_info->pidfile_help = gengetopt_args_info_help[4];
+ args_info->statedir_help = gengetopt_args_info_help[5];
+ args_info->dns_help = gengetopt_args_info_help[6];
+ args_info->listen_help = gengetopt_args_info_help[7];
+ args_info->remote_help = gengetopt_args_info_help[8];
+ args_info->contexts_help = gengetopt_args_info_help[9];
+ args_info->timelimit_help = gengetopt_args_info_help[10];
+ args_info->gtpversion_help = gengetopt_args_info_help[11];
+ args_info->apn_help = gengetopt_args_info_help[12];
+ args_info->selmode_help = gengetopt_args_info_help[13];
+ args_info->imsi_help = gengetopt_args_info_help[14];
+ args_info->nsapi_help = gengetopt_args_info_help[15];
+ args_info->msisdn_help = gengetopt_args_info_help[16];
+ args_info->qos_help = gengetopt_args_info_help[17];
+ args_info->charging_help = gengetopt_args_info_help[18];
+ args_info->uid_help = gengetopt_args_info_help[19];
+ args_info->pwd_help = gengetopt_args_info_help[20];
+ args_info->createif_help = gengetopt_args_info_help[21];
+ args_info->net_help = gengetopt_args_info_help[22];
+ args_info->defaultroute_help = gengetopt_args_info_help[23];
+ args_info->ipup_help = gengetopt_args_info_help[24];
+ args_info->ipdown_help = gengetopt_args_info_help[25];
+ args_info->pinghost_help = gengetopt_args_info_help[26];
+ args_info->pingrate_help = gengetopt_args_info_help[27];
+ args_info->pingsize_help = gengetopt_args_info_help[28];
+ args_info->pingcount_help = gengetopt_args_info_help[29];
+ args_info->pingquiet_help = gengetopt_args_info_help[30];
+ args_info->norecovery_help = gengetopt_args_info_help[31];
+
}
-void
-cmdline_parser_print_version (void)
+void cmdline_parser_print_version(void)
{
- printf ("%s %s\n", CMDLINE_PARSER_PACKAGE, CMDLINE_PARSER_VERSION);
+ printf("%s %s\n", CMDLINE_PARSER_PACKAGE, CMDLINE_PARSER_VERSION);
}
-void
-cmdline_parser_print_help (void)
+void cmdline_parser_print_help(void)
{
- int i = 0;
- cmdline_parser_print_version ();
+ int i = 0;
+ cmdline_parser_print_version();
- if (strlen(gengetopt_args_info_purpose) > 0)
- printf("\n%s\n", gengetopt_args_info_purpose);
+ if (strlen(gengetopt_args_info_purpose) > 0)
+ printf("\n%s\n", gengetopt_args_info_purpose);
- printf("\n%s\n\n", gengetopt_args_info_usage);
- while (gengetopt_args_info_help[i])
- printf("%s\n", gengetopt_args_info_help[i++]);
+ printf("\n%s\n\n", gengetopt_args_info_usage);
+ while (gengetopt_args_info_help[i])
+ printf("%s\n", gengetopt_args_info_help[i++]);
}
-void
-cmdline_parser_init (struct gengetopt_args_info *args_info)
+void cmdline_parser_init(struct gengetopt_args_info *args_info)
{
- clear_given (args_info);
- clear_args (args_info);
- init_args_info (args_info);
+ clear_given(args_info);
+ clear_args(args_info);
+ init_args_info(args_info);
}
-static void
-cmdline_parser_release (struct gengetopt_args_info *args_info)
+static void cmdline_parser_release(struct gengetopt_args_info *args_info)
{
-
- if (args_info->conf_arg)
- {
- free (args_info->conf_arg); /* free previous argument */
- args_info->conf_arg = 0;
- }
- if (args_info->conf_orig)
- {
- free (args_info->conf_orig); /* free previous argument */
- args_info->conf_orig = 0;
- }
- if (args_info->pidfile_arg)
- {
- free (args_info->pidfile_arg); /* free previous argument */
- args_info->pidfile_arg = 0;
- }
- if (args_info->pidfile_orig)
- {
- free (args_info->pidfile_orig); /* free previous argument */
- args_info->pidfile_orig = 0;
- }
- if (args_info->statedir_arg)
- {
- free (args_info->statedir_arg); /* free previous argument */
- args_info->statedir_arg = 0;
- }
- if (args_info->statedir_orig)
- {
- free (args_info->statedir_orig); /* free previous argument */
- args_info->statedir_orig = 0;
- }
- if (args_info->dns_arg)
- {
- free (args_info->dns_arg); /* free previous argument */
- args_info->dns_arg = 0;
- }
- if (args_info->dns_orig)
- {
- free (args_info->dns_orig); /* free previous argument */
- args_info->dns_orig = 0;
- }
- if (args_info->listen_arg)
- {
- free (args_info->listen_arg); /* free previous argument */
- args_info->listen_arg = 0;
- }
- if (args_info->listen_orig)
- {
- free (args_info->listen_orig); /* free previous argument */
- args_info->listen_orig = 0;
- }
- if (args_info->remote_arg)
- {
- free (args_info->remote_arg); /* free previous argument */
- args_info->remote_arg = 0;
- }
- if (args_info->remote_orig)
- {
- free (args_info->remote_orig); /* free previous argument */
- args_info->remote_orig = 0;
- }
- if (args_info->contexts_orig)
- {
- free (args_info->contexts_orig); /* free previous argument */
- args_info->contexts_orig = 0;
- }
- if (args_info->timelimit_orig)
- {
- free (args_info->timelimit_orig); /* free previous argument */
- args_info->timelimit_orig = 0;
- }
- if (args_info->gtpversion_orig)
- {
- free (args_info->gtpversion_orig); /* free previous argument */
- args_info->gtpversion_orig = 0;
- }
- if (args_info->apn_arg)
- {
- free (args_info->apn_arg); /* free previous argument */
- args_info->apn_arg = 0;
- }
- if (args_info->apn_orig)
- {
- free (args_info->apn_orig); /* free previous argument */
- args_info->apn_orig = 0;
- }
- if (args_info->selmode_orig)
- {
- free (args_info->selmode_orig); /* free previous argument */
- args_info->selmode_orig = 0;
- }
- if (args_info->imsi_arg)
- {
- free (args_info->imsi_arg); /* free previous argument */
- args_info->imsi_arg = 0;
- }
- if (args_info->imsi_orig)
- {
- free (args_info->imsi_orig); /* free previous argument */
- args_info->imsi_orig = 0;
- }
- if (args_info->nsapi_orig)
- {
- free (args_info->nsapi_orig); /* free previous argument */
- args_info->nsapi_orig = 0;
- }
- if (args_info->msisdn_arg)
- {
- free (args_info->msisdn_arg); /* free previous argument */
- args_info->msisdn_arg = 0;
- }
- if (args_info->msisdn_orig)
- {
- free (args_info->msisdn_orig); /* free previous argument */
- args_info->msisdn_orig = 0;
- }
- if (args_info->qos_orig)
- {
- free (args_info->qos_orig); /* free previous argument */
- args_info->qos_orig = 0;
- }
- if (args_info->charging_orig)
- {
- free (args_info->charging_orig); /* free previous argument */
- args_info->charging_orig = 0;
- }
- if (args_info->uid_arg)
- {
- free (args_info->uid_arg); /* free previous argument */
- args_info->uid_arg = 0;
- }
- if (args_info->uid_orig)
- {
- free (args_info->uid_orig); /* free previous argument */
- args_info->uid_orig = 0;
- }
- if (args_info->pwd_arg)
- {
- free (args_info->pwd_arg); /* free previous argument */
- args_info->pwd_arg = 0;
- }
- if (args_info->pwd_orig)
- {
- free (args_info->pwd_orig); /* free previous argument */
- args_info->pwd_orig = 0;
- }
- if (args_info->net_arg)
- {
- free (args_info->net_arg); /* free previous argument */
- args_info->net_arg = 0;
- }
- if (args_info->net_orig)
- {
- free (args_info->net_orig); /* free previous argument */
- args_info->net_orig = 0;
- }
- if (args_info->ipup_arg)
- {
- free (args_info->ipup_arg); /* free previous argument */
- args_info->ipup_arg = 0;
- }
- if (args_info->ipup_orig)
- {
- free (args_info->ipup_orig); /* free previous argument */
- args_info->ipup_orig = 0;
- }
- if (args_info->ipdown_arg)
- {
- free (args_info->ipdown_arg); /* free previous argument */
- args_info->ipdown_arg = 0;
- }
- if (args_info->ipdown_orig)
- {
- free (args_info->ipdown_orig); /* free previous argument */
- args_info->ipdown_orig = 0;
- }
- if (args_info->pinghost_arg)
- {
- free (args_info->pinghost_arg); /* free previous argument */
- args_info->pinghost_arg = 0;
- }
- if (args_info->pinghost_orig)
- {
- free (args_info->pinghost_orig); /* free previous argument */
- args_info->pinghost_orig = 0;
- }
- if (args_info->pingrate_orig)
- {
- free (args_info->pingrate_orig); /* free previous argument */
- args_info->pingrate_orig = 0;
- }
- if (args_info->pingsize_orig)
- {
- free (args_info->pingsize_orig); /* free previous argument */
- args_info->pingsize_orig = 0;
- }
- if (args_info->pingcount_orig)
- {
- free (args_info->pingcount_orig); /* free previous argument */
- args_info->pingcount_orig = 0;
- }
-
- clear_given (args_info);
+
+ if (args_info->conf_arg) {
+ free(args_info->conf_arg); /* free previous argument */
+ args_info->conf_arg = 0;
+ }
+ if (args_info->conf_orig) {
+ free(args_info->conf_orig); /* free previous argument */
+ args_info->conf_orig = 0;
+ }
+ if (args_info->pidfile_arg) {
+ free(args_info->pidfile_arg); /* free previous argument */
+ args_info->pidfile_arg = 0;
+ }
+ if (args_info->pidfile_orig) {
+ free(args_info->pidfile_orig); /* free previous argument */
+ args_info->pidfile_orig = 0;
+ }
+ if (args_info->statedir_arg) {
+ free(args_info->statedir_arg); /* free previous argument */
+ args_info->statedir_arg = 0;
+ }
+ if (args_info->statedir_orig) {
+ free(args_info->statedir_orig); /* free previous argument */
+ args_info->statedir_orig = 0;
+ }
+ if (args_info->dns_arg) {
+ free(args_info->dns_arg); /* free previous argument */
+ args_info->dns_arg = 0;
+ }
+ if (args_info->dns_orig) {
+ free(args_info->dns_orig); /* free previous argument */
+ args_info->dns_orig = 0;
+ }
+ if (args_info->listen_arg) {
+ free(args_info->listen_arg); /* free previous argument */
+ args_info->listen_arg = 0;
+ }
+ if (args_info->listen_orig) {
+ free(args_info->listen_orig); /* free previous argument */
+ args_info->listen_orig = 0;
+ }
+ if (args_info->remote_arg) {
+ free(args_info->remote_arg); /* free previous argument */
+ args_info->remote_arg = 0;
+ }
+ if (args_info->remote_orig) {
+ free(args_info->remote_orig); /* free previous argument */
+ args_info->remote_orig = 0;
+ }
+ if (args_info->contexts_orig) {
+ free(args_info->contexts_orig); /* free previous argument */
+ args_info->contexts_orig = 0;
+ }
+ if (args_info->timelimit_orig) {
+ free(args_info->timelimit_orig); /* free previous argument */
+ args_info->timelimit_orig = 0;
+ }
+ if (args_info->gtpversion_orig) {
+ free(args_info->gtpversion_orig); /* free previous argument */
+ args_info->gtpversion_orig = 0;
+ }
+ if (args_info->apn_arg) {
+ free(args_info->apn_arg); /* free previous argument */
+ args_info->apn_arg = 0;
+ }
+ if (args_info->apn_orig) {
+ free(args_info->apn_orig); /* free previous argument */
+ args_info->apn_orig = 0;
+ }
+ if (args_info->selmode_orig) {
+ free(args_info->selmode_orig); /* free previous argument */
+ args_info->selmode_orig = 0;
+ }
+ if (args_info->imsi_arg) {
+ free(args_info->imsi_arg); /* free previous argument */
+ args_info->imsi_arg = 0;
+ }
+ if (args_info->imsi_orig) {
+ free(args_info->imsi_orig); /* free previous argument */
+ args_info->imsi_orig = 0;
+ }
+ if (args_info->nsapi_orig) {
+ free(args_info->nsapi_orig); /* free previous argument */
+ args_info->nsapi_orig = 0;
+ }
+ if (args_info->msisdn_arg) {
+ free(args_info->msisdn_arg); /* free previous argument */
+ args_info->msisdn_arg = 0;
+ }
+ if (args_info->msisdn_orig) {
+ free(args_info->msisdn_orig); /* free previous argument */
+ args_info->msisdn_orig = 0;
+ }
+ if (args_info->qos_orig) {
+ free(args_info->qos_orig); /* free previous argument */
+ args_info->qos_orig = 0;
+ }
+ if (args_info->charging_orig) {
+ free(args_info->charging_orig); /* free previous argument */
+ args_info->charging_orig = 0;
+ }
+ if (args_info->uid_arg) {
+ free(args_info->uid_arg); /* free previous argument */
+ args_info->uid_arg = 0;
+ }
+ if (args_info->uid_orig) {
+ free(args_info->uid_orig); /* free previous argument */
+ args_info->uid_orig = 0;
+ }
+ if (args_info->pwd_arg) {
+ free(args_info->pwd_arg); /* free previous argument */
+ args_info->pwd_arg = 0;
+ }
+ if (args_info->pwd_orig) {
+ free(args_info->pwd_orig); /* free previous argument */
+ args_info->pwd_orig = 0;
+ }
+ if (args_info->net_arg) {
+ free(args_info->net_arg); /* free previous argument */
+ args_info->net_arg = 0;
+ }
+ if (args_info->net_orig) {
+ free(args_info->net_orig); /* free previous argument */
+ args_info->net_orig = 0;
+ }
+ if (args_info->ipup_arg) {
+ free(args_info->ipup_arg); /* free previous argument */
+ args_info->ipup_arg = 0;
+ }
+ if (args_info->ipup_orig) {
+ free(args_info->ipup_orig); /* free previous argument */
+ args_info->ipup_orig = 0;
+ }
+ if (args_info->ipdown_arg) {
+ free(args_info->ipdown_arg); /* free previous argument */
+ args_info->ipdown_arg = 0;
+ }
+ if (args_info->ipdown_orig) {
+ free(args_info->ipdown_orig); /* free previous argument */
+ args_info->ipdown_orig = 0;
+ }
+ if (args_info->pinghost_arg) {
+ free(args_info->pinghost_arg); /* free previous argument */
+ args_info->pinghost_arg = 0;
+ }
+ if (args_info->pinghost_orig) {
+ free(args_info->pinghost_orig); /* free previous argument */
+ args_info->pinghost_orig = 0;
+ }
+ if (args_info->pingrate_orig) {
+ free(args_info->pingrate_orig); /* free previous argument */
+ args_info->pingrate_orig = 0;
+ }
+ if (args_info->pingsize_orig) {
+ free(args_info->pingsize_orig); /* free previous argument */
+ args_info->pingsize_orig = 0;
+ }
+ if (args_info->pingcount_orig) {
+ free(args_info->pingcount_orig); /* free previous argument */
+ args_info->pingcount_orig = 0;
+ }
+
+ clear_given(args_info);
}
int
-cmdline_parser_file_save(const char *filename, struct gengetopt_args_info *args_info)
+cmdline_parser_file_save(const char *filename,
+ struct gengetopt_args_info *args_info)
{
- FILE *outfile;
- int i = 0;
-
- outfile = fopen(filename, "w");
-
- if (!outfile)
- {
- fprintf (stderr, "%s: cannot open file for writing: %s\n", CMDLINE_PARSER_PACKAGE, filename);
- return EXIT_FAILURE;
- }
-
- if (args_info->help_given) {
- fprintf(outfile, "%s\n", "help");
- }
- if (args_info->version_given) {
- fprintf(outfile, "%s\n", "version");
- }
- if (args_info->debug_given) {
- fprintf(outfile, "%s\n", "debug");
- }
- if (args_info->conf_given) {
- if (args_info->conf_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "conf", args_info->conf_orig);
- } else {
- fprintf(outfile, "%s\n", "conf");
- }
- }
- if (args_info->pidfile_given) {
- if (args_info->pidfile_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "pidfile", args_info->pidfile_orig);
- } else {
- fprintf(outfile, "%s\n", "pidfile");
- }
- }
- if (args_info->statedir_given) {
- if (args_info->statedir_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "statedir", args_info->statedir_orig);
- } else {
- fprintf(outfile, "%s\n", "statedir");
- }
- }
- if (args_info->dns_given) {
- if (args_info->dns_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "dns", args_info->dns_orig);
- } else {
- fprintf(outfile, "%s\n", "dns");
- }
- }
- if (args_info->listen_given) {
- if (args_info->listen_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "listen", args_info->listen_orig);
- } else {
- fprintf(outfile, "%s\n", "listen");
- }
- }
- if (args_info->remote_given) {
- if (args_info->remote_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "remote", args_info->remote_orig);
- } else {
- fprintf(outfile, "%s\n", "remote");
- }
- }
- if (args_info->contexts_given) {
- if (args_info->contexts_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "contexts", args_info->contexts_orig);
- } else {
- fprintf(outfile, "%s\n", "contexts");
- }
- }
- if (args_info->timelimit_given) {
- if (args_info->timelimit_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "timelimit", args_info->timelimit_orig);
- } else {
- fprintf(outfile, "%s\n", "timelimit");
- }
- }
- if (args_info->gtpversion_given) {
- if (args_info->gtpversion_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "gtpversion", args_info->gtpversion_orig);
- } else {
- fprintf(outfile, "%s\n", "gtpversion");
- }
- }
- if (args_info->apn_given) {
- if (args_info->apn_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "apn", args_info->apn_orig);
- } else {
- fprintf(outfile, "%s\n", "apn");
- }
- }
- if (args_info->selmode_given) {
- if (args_info->selmode_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "selmode", args_info->selmode_orig);
- } else {
- fprintf(outfile, "%s\n", "selmode");
- }
- }
- if (args_info->imsi_given) {
- if (args_info->imsi_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "imsi", args_info->imsi_orig);
- } else {
- fprintf(outfile, "%s\n", "imsi");
- }
- }
- if (args_info->nsapi_given) {
- if (args_info->nsapi_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "nsapi", args_info->nsapi_orig);
- } else {
- fprintf(outfile, "%s\n", "nsapi");
- }
- }
- if (args_info->msisdn_given) {
- if (args_info->msisdn_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "msisdn", args_info->msisdn_orig);
- } else {
- fprintf(outfile, "%s\n", "msisdn");
- }
- }
- if (args_info->qos_given) {
- if (args_info->qos_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "qos", args_info->qos_orig);
- } else {
- fprintf(outfile, "%s\n", "qos");
- }
- }
- if (args_info->charging_given) {
- if (args_info->charging_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "charging", args_info->charging_orig);
- } else {
- fprintf(outfile, "%s\n", "charging");
- }
- }
- if (args_info->uid_given) {
- if (args_info->uid_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "uid", args_info->uid_orig);
- } else {
- fprintf(outfile, "%s\n", "uid");
- }
- }
- if (args_info->pwd_given) {
- if (args_info->pwd_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "pwd", args_info->pwd_orig);
- } else {
- fprintf(outfile, "%s\n", "pwd");
- }
- }
- if (args_info->createif_given) {
- fprintf(outfile, "%s\n", "createif");
- }
- if (args_info->net_given) {
- if (args_info->net_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "net", args_info->net_orig);
- } else {
- fprintf(outfile, "%s\n", "net");
- }
- }
- if (args_info->defaultroute_given) {
- fprintf(outfile, "%s\n", "defaultroute");
- }
- if (args_info->ipup_given) {
- if (args_info->ipup_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "ipup", args_info->ipup_orig);
- } else {
- fprintf(outfile, "%s\n", "ipup");
- }
- }
- if (args_info->ipdown_given) {
- if (args_info->ipdown_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "ipdown", args_info->ipdown_orig);
- } else {
- fprintf(outfile, "%s\n", "ipdown");
- }
- }
- if (args_info->pinghost_given) {
- if (args_info->pinghost_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "pinghost", args_info->pinghost_orig);
- } else {
- fprintf(outfile, "%s\n", "pinghost");
- }
- }
- if (args_info->pingrate_given) {
- if (args_info->pingrate_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "pingrate", args_info->pingrate_orig);
- } else {
- fprintf(outfile, "%s\n", "pingrate");
- }
- }
- if (args_info->pingsize_given) {
- if (args_info->pingsize_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "pingsize", args_info->pingsize_orig);
- } else {
- fprintf(outfile, "%s\n", "pingsize");
- }
- }
- if (args_info->pingcount_given) {
- if (args_info->pingcount_orig) {
- fprintf(outfile, "%s=\"%s\"\n", "pingcount", args_info->pingcount_orig);
- } else {
- fprintf(outfile, "%s\n", "pingcount");
- }
- }
- if (args_info->pingquiet_given) {
- fprintf(outfile, "%s\n", "pingquiet");
- }
- if (args_info->norecovery_given) {
- fprintf(outfile, "%s\n", "norecovery");
- }
-
- fclose (outfile);
-
- i = EXIT_SUCCESS;
- return i;
+ FILE *outfile;
+ int i = 0;
+
+ outfile = fopen(filename, "w");
+
+ if (!outfile) {
+ fprintf(stderr, "%s: cannot open file for writing: %s\n",
+ CMDLINE_PARSER_PACKAGE, filename);
+ return EXIT_FAILURE;
+ }
+
+ if (args_info->help_given) {
+ fprintf(outfile, "%s\n", "help");
+ }
+ if (args_info->version_given) {
+ fprintf(outfile, "%s\n", "version");
+ }
+ if (args_info->debug_given) {
+ fprintf(outfile, "%s\n", "debug");
+ }
+ if (args_info->conf_given) {
+ if (args_info->conf_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "conf",
+ args_info->conf_orig);
+ } else {
+ fprintf(outfile, "%s\n", "conf");
+ }
+ }
+ if (args_info->pidfile_given) {
+ if (args_info->pidfile_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "pidfile",
+ args_info->pidfile_orig);
+ } else {
+ fprintf(outfile, "%s\n", "pidfile");
+ }
+ }
+ if (args_info->statedir_given) {
+ if (args_info->statedir_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "statedir",
+ args_info->statedir_orig);
+ } else {
+ fprintf(outfile, "%s\n", "statedir");
+ }
+ }
+ if (args_info->dns_given) {
+ if (args_info->dns_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "dns",
+ args_info->dns_orig);
+ } else {
+ fprintf(outfile, "%s\n", "dns");
+ }
+ }
+ if (args_info->listen_given) {
+ if (args_info->listen_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "listen",
+ args_info->listen_orig);
+ } else {
+ fprintf(outfile, "%s\n", "listen");
+ }
+ }
+ if (args_info->remote_given) {
+ if (args_info->remote_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "remote",
+ args_info->remote_orig);
+ } else {
+ fprintf(outfile, "%s\n", "remote");
+ }
+ }
+ if (args_info->contexts_given) {
+ if (args_info->contexts_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "contexts",
+ args_info->contexts_orig);
+ } else {
+ fprintf(outfile, "%s\n", "contexts");
+ }
+ }
+ if (args_info->timelimit_given) {
+ if (args_info->timelimit_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "timelimit",
+ args_info->timelimit_orig);
+ } else {
+ fprintf(outfile, "%s\n", "timelimit");
+ }
+ }
+ if (args_info->gtpversion_given) {
+ if (args_info->gtpversion_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "gtpversion",
+ args_info->gtpversion_orig);
+ } else {
+ fprintf(outfile, "%s\n", "gtpversion");
+ }
+ }
+ if (args_info->apn_given) {
+ if (args_info->apn_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "apn",
+ args_info->apn_orig);
+ } else {
+ fprintf(outfile, "%s\n", "apn");
+ }
+ }
+ if (args_info->selmode_given) {
+ if (args_info->selmode_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "selmode",
+ args_info->selmode_orig);
+ } else {
+ fprintf(outfile, "%s\n", "selmode");
+ }
+ }
+ if (args_info->imsi_given) {
+ if (args_info->imsi_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "imsi",
+ args_info->imsi_orig);
+ } else {
+ fprintf(outfile, "%s\n", "imsi");
+ }
+ }
+ if (args_info->nsapi_given) {
+ if (args_info->nsapi_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "nsapi",
+ args_info->nsapi_orig);
+ } else {
+ fprintf(outfile, "%s\n", "nsapi");
+ }
+ }
+ if (args_info->msisdn_given) {
+ if (args_info->msisdn_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "msisdn",
+ args_info->msisdn_orig);
+ } else {
+ fprintf(outfile, "%s\n", "msisdn");
+ }
+ }
+ if (args_info->qos_given) {
+ if (args_info->qos_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "qos",
+ args_info->qos_orig);
+ } else {
+ fprintf(outfile, "%s\n", "qos");
+ }
+ }
+ if (args_info->charging_given) {
+ if (args_info->charging_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "charging",
+ args_info->charging_orig);
+ } else {
+ fprintf(outfile, "%s\n", "charging");
+ }
+ }
+ if (args_info->uid_given) {
+ if (args_info->uid_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "uid",
+ args_info->uid_orig);
+ } else {
+ fprintf(outfile, "%s\n", "uid");
+ }
+ }
+ if (args_info->pwd_given) {
+ if (args_info->pwd_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "pwd",
+ args_info->pwd_orig);
+ } else {
+ fprintf(outfile, "%s\n", "pwd");
+ }
+ }
+ if (args_info->createif_given) {
+ fprintf(outfile, "%s\n", "createif");
+ }
+ if (args_info->net_given) {
+ if (args_info->net_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "net",
+ args_info->net_orig);
+ } else {
+ fprintf(outfile, "%s\n", "net");
+ }
+ }
+ if (args_info->defaultroute_given) {
+ fprintf(outfile, "%s\n", "defaultroute");
+ }
+ if (args_info->ipup_given) {
+ if (args_info->ipup_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "ipup",
+ args_info->ipup_orig);
+ } else {
+ fprintf(outfile, "%s\n", "ipup");
+ }
+ }
+ if (args_info->ipdown_given) {
+ if (args_info->ipdown_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "ipdown",
+ args_info->ipdown_orig);
+ } else {
+ fprintf(outfile, "%s\n", "ipdown");
+ }
+ }
+ if (args_info->pinghost_given) {
+ if (args_info->pinghost_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "pinghost",
+ args_info->pinghost_orig);
+ } else {
+ fprintf(outfile, "%s\n", "pinghost");
+ }
+ }
+ if (args_info->pingrate_given) {
+ if (args_info->pingrate_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "pingrate",
+ args_info->pingrate_orig);
+ } else {
+ fprintf(outfile, "%s\n", "pingrate");
+ }
+ }
+ if (args_info->pingsize_given) {
+ if (args_info->pingsize_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "pingsize",
+ args_info->pingsize_orig);
+ } else {
+ fprintf(outfile, "%s\n", "pingsize");
+ }
+ }
+ if (args_info->pingcount_given) {
+ if (args_info->pingcount_orig) {
+ fprintf(outfile, "%s=\"%s\"\n", "pingcount",
+ args_info->pingcount_orig);
+ } else {
+ fprintf(outfile, "%s\n", "pingcount");
+ }
+ }
+ if (args_info->pingquiet_given) {
+ fprintf(outfile, "%s\n", "pingquiet");
+ }
+ if (args_info->norecovery_given) {
+ fprintf(outfile, "%s\n", "norecovery");
+ }
+
+ fclose(outfile);
+
+ i = EXIT_SUCCESS;
+ return i;
}
-void
-cmdline_parser_free (struct gengetopt_args_info *args_info)
+void cmdline_parser_free(struct gengetopt_args_info *args_info)
{
- cmdline_parser_release (args_info);
+ cmdline_parser_release(args_info);
}
-
/* gengetopt_strdup() */
/* strdup.c replacement of strdup, which is not standard */
-char *
-gengetopt_strdup (const char *s)
+char *gengetopt_strdup(const char *s)
{
- char *result = NULL;
- if (!s)
- return result;
-
- result = (char*)malloc(strlen(s) + 1);
- if (result == (char*)0)
- return (char*)0;
- strcpy(result, s);
- return result;
+ char *result = NULL;
+ if (!s)
+ return result;
+
+ result = (char *)malloc(strlen(s) + 1);
+ if (result == (char *)0)
+ return (char *)0;
+ strcpy(result, s);
+ return result;
}
int
-cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+cmdline_parser(int argc, char *const *argv,
+ struct gengetopt_args_info *args_info)
{
- return cmdline_parser2 (argc, argv, args_info, 0, 1, 1);
+ return cmdline_parser2(argc, argv, args_info, 0, 1, 1);
}
int
-cmdline_parser2 (int argc, char * const *argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required)
+cmdline_parser2(int argc, char *const *argv,
+ struct gengetopt_args_info *args_info, int override,
+ int initialize, int check_required)
{
- int result;
+ int result;
+
+ result =
+ cmdline_parser_internal(argc, argv, args_info, override, initialize,
+ check_required, NULL);
- result = cmdline_parser_internal (argc, argv, args_info, override, initialize, check_required, NULL);
+ if (result == EXIT_FAILURE) {
+ cmdline_parser_free(args_info);
+ exit(EXIT_FAILURE);
+ }
- if (result == EXIT_FAILURE)
- {
- cmdline_parser_free (args_info);
- exit (EXIT_FAILURE);
- }
-
- return result;
+ return result;
}
int
-cmdline_parser_required (struct gengetopt_args_info *args_info, const char *prog_name)
+cmdline_parser_required(struct gengetopt_args_info *args_info,
+ const char *prog_name)
{
- return EXIT_SUCCESS;
+ return EXIT_SUCCESS;
}
int
-cmdline_parser_internal (int argc, char * const *argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required, const char *additional_error)
+cmdline_parser_internal(int argc, char *const *argv,
+ struct gengetopt_args_info *args_info, int override,
+ int initialize, int check_required,
+ const char *additional_error)
{
- int c; /* Character of the parsed option. */
-
- int error = 0;
- struct gengetopt_args_info local_args_info;
-
- if (initialize)
- cmdline_parser_init (args_info);
-
- cmdline_parser_init (&local_args_info);
-
- optarg = 0;
- optind = 0;
- opterr = 1;
- optopt = '?';
-
- while (1)
- {
- int option_index = 0;
- char *stop_char;
-
- static struct option long_options[] = {
- { "help", 0, NULL, 'h' },
- { "version", 0, NULL, 'V' },
- { "debug", 0, NULL, 'd' },
- { "conf", 1, NULL, 'c' },
- { "pidfile", 1, NULL, 0 },
- { "statedir", 1, NULL, 0 },
- { "dns", 1, NULL, 0 },
- { "listen", 1, NULL, 'l' },
- { "remote", 1, NULL, 'r' },
- { "contexts", 1, NULL, 0 },
- { "timelimit", 1, NULL, 0 },
- { "gtpversion", 1, NULL, 0 },
- { "apn", 1, NULL, 'a' },
- { "selmode", 1, NULL, 0 },
- { "rattype", 1, NULL, 0},
- { "userloc", 1, NULL, 0},
- { "rai", 1, NULL, 0},
- { "mstz", 1, NULL, 0},
- { "imeisv", 1, NULL, 0},
- { "imsi", 1, NULL, 'i' },
- { "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' },
- { "createif", 0, NULL, 0 },
- { "net", 1, NULL, 'n' },
- { "defaultroute", 0, NULL, 0 },
- { "ipup", 1, NULL, 0 },
- { "ipdown", 1, NULL, 0 },
- { "pinghost", 1, NULL, 0 },
- { "pingrate", 1, NULL, 0 },
- { "pingsize", 1, NULL, 0 },
- { "pingcount", 1, NULL, 0 },
- { "pingquiet", 0, NULL, 0 },
- { "norecovery", 0, NULL, 0 },
- { NULL, 0, NULL, 0 }
- };
-
- stop_char = 0;
- c = getopt_long (argc, argv, "hVdc:l:r:a:i:m:q:u:p:n:", long_options, &option_index);
-
- if (c == -1) break; /* Exit from `while (1)' loop. */
-
- switch (c)
- {
- case 'h': /* Print help and exit. */
- cmdline_parser_print_help ();
- cmdline_parser_free (&local_args_info);
- exit (EXIT_SUCCESS);
-
- case 'V': /* Print version and exit. */
- cmdline_parser_print_version ();
- cmdline_parser_free (&local_args_info);
- exit (EXIT_SUCCESS);
-
- case 'd': /* Run in debug mode. */
- if (local_args_info.debug_given)
- {
- fprintf (stderr, "%s: `--debug' (`-d') option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->debug_given && ! override)
- continue;
- local_args_info.debug_given = 1;
- args_info->debug_given = 1;
- args_info->debug_flag = !(args_info->debug_flag);
- break;
-
- case 'c': /* Read configuration file. */
- if (local_args_info.conf_given)
- {
- fprintf (stderr, "%s: `--conf' (`-c') option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->conf_given && ! override)
- continue;
- local_args_info.conf_given = 1;
- args_info->conf_given = 1;
- if (args_info->conf_arg)
- free (args_info->conf_arg); /* free previous string */
- args_info->conf_arg = gengetopt_strdup (optarg);
- if (args_info->conf_orig)
- free (args_info->conf_orig); /* free previous string */
- args_info->conf_orig = gengetopt_strdup (optarg);
- break;
-
- case 'l': /* Local interface. */
- if (local_args_info.listen_given)
- {
- fprintf (stderr, "%s: `--listen' (`-l') option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->listen_given && ! override)
- continue;
- local_args_info.listen_given = 1;
- args_info->listen_given = 1;
- if (args_info->listen_arg)
- free (args_info->listen_arg); /* free previous string */
- args_info->listen_arg = gengetopt_strdup (optarg);
- if (args_info->listen_orig)
- free (args_info->listen_orig); /* free previous string */
- args_info->listen_orig = gengetopt_strdup (optarg);
- break;
-
- case 'r': /* Remote host. */
- if (local_args_info.remote_given)
- {
- fprintf (stderr, "%s: `--remote' (`-r') option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->remote_given && ! override)
- continue;
- local_args_info.remote_given = 1;
- args_info->remote_given = 1;
- if (args_info->remote_arg)
- free (args_info->remote_arg); /* free previous string */
- args_info->remote_arg = gengetopt_strdup (optarg);
- if (args_info->remote_orig)
- free (args_info->remote_orig); /* free previous string */
- args_info->remote_orig = gengetopt_strdup (optarg);
- break;
-
- case 'a': /* Access point name. */
- if (local_args_info.apn_given)
- {
- fprintf (stderr, "%s: `--apn' (`-a') option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->apn_given && ! override)
- continue;
- local_args_info.apn_given = 1;
- args_info->apn_given = 1;
- if (args_info->apn_arg)
- free (args_info->apn_arg); /* free previous string */
- args_info->apn_arg = gengetopt_strdup (optarg);
- if (args_info->apn_orig)
- free (args_info->apn_orig); /* free previous string */
- args_info->apn_orig = gengetopt_strdup (optarg);
- break;
-
- case 'i': /* IMSI. */
- if (local_args_info.imsi_given)
- {
- fprintf (stderr, "%s: `--imsi' (`-i') option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->imsi_given && ! override)
- continue;
- local_args_info.imsi_given = 1;
- args_info->imsi_given = 1;
- if (args_info->imsi_arg)
- free (args_info->imsi_arg); /* free previous string */
- args_info->imsi_arg = gengetopt_strdup (optarg);
- if (args_info->imsi_orig)
- free (args_info->imsi_orig); /* free previous string */
- args_info->imsi_orig = gengetopt_strdup (optarg);
- break;
-
- case 'm': /* Mobile Station ISDN number. */
- if (local_args_info.msisdn_given)
- {
- fprintf (stderr, "%s: `--msisdn' (`-m') option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->msisdn_given && ! override)
- continue;
- local_args_info.msisdn_given = 1;
- args_info->msisdn_given = 1;
- if (args_info->msisdn_arg)
- free (args_info->msisdn_arg); /* free previous string */
- args_info->msisdn_arg = gengetopt_strdup (optarg);
- if (args_info->msisdn_orig)
- free (args_info->msisdn_orig); /* free previous string */
- args_info->msisdn_orig = gengetopt_strdup (optarg);
- break;
-
- case 'q': /* Requested quality of service. */
- if (local_args_info.qos_given)
- {
- fprintf (stderr, "%s: `--qos' (`-q') option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->qos_given && ! override)
- continue;
- local_args_info.qos_given = 1;
- args_info->qos_given = 1;
- args_info->qos_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->qos_orig)
- free (args_info->qos_orig); /* free previous string */
- args_info->qos_orig = gengetopt_strdup (optarg);
- break;
-
- case 'u': /* Login user ID. */
- if (local_args_info.uid_given)
- {
- fprintf (stderr, "%s: `--uid' (`-u') option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->uid_given && ! override)
- continue;
- local_args_info.uid_given = 1;
- args_info->uid_given = 1;
- if (args_info->uid_arg)
- free (args_info->uid_arg); /* free previous string */
- args_info->uid_arg = gengetopt_strdup (optarg);
- if (args_info->uid_orig)
- free (args_info->uid_orig); /* free previous string */
- args_info->uid_orig = gengetopt_strdup (optarg);
- break;
-
- case 'p': /* Login password. */
- if (local_args_info.pwd_given)
- {
- fprintf (stderr, "%s: `--pwd' (`-p') option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->pwd_given && ! override)
- continue;
- local_args_info.pwd_given = 1;
- args_info->pwd_given = 1;
- if (args_info->pwd_arg)
- free (args_info->pwd_arg); /* free previous string */
- args_info->pwd_arg = gengetopt_strdup (optarg);
- if (args_info->pwd_orig)
- free (args_info->pwd_orig); /* free previous string */
- args_info->pwd_orig = gengetopt_strdup (optarg);
- break;
-
- case 'n': /* Network address for local interface. */
- if (local_args_info.net_given)
- {
- fprintf (stderr, "%s: `--net' (`-n') option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->net_given && ! override)
- continue;
- local_args_info.net_given = 1;
- args_info->net_given = 1;
- if (args_info->net_arg)
- free (args_info->net_arg); /* free previous string */
- args_info->net_arg = gengetopt_strdup (optarg);
- if (args_info->net_orig)
- free (args_info->net_orig); /* free previous string */
- args_info->net_orig = gengetopt_strdup (optarg);
- break;
-
-
- case 0: /* Long option with no short option */
- /* Filename of process id file. */
- if (strcmp (long_options[option_index].name, "pidfile") == 0)
- {
- if (local_args_info.pidfile_given)
- {
- fprintf (stderr, "%s: `--pidfile' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->pidfile_given && ! override)
- continue;
- local_args_info.pidfile_given = 1;
- args_info->pidfile_given = 1;
- if (args_info->pidfile_arg)
- free (args_info->pidfile_arg); /* free previous string */
- args_info->pidfile_arg = gengetopt_strdup (optarg);
- if (args_info->pidfile_orig)
- free (args_info->pidfile_orig); /* free previous string */
- args_info->pidfile_orig = gengetopt_strdup (optarg);
- }
- /* Directory of nonvolatile data. */
- else if (strcmp (long_options[option_index].name, "statedir") == 0)
- {
- if (local_args_info.statedir_given)
- {
- fprintf (stderr, "%s: `--statedir' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->statedir_given && ! override)
- continue;
- local_args_info.statedir_given = 1;
- args_info->statedir_given = 1;
- if (args_info->statedir_arg)
- free (args_info->statedir_arg); /* free previous string */
- args_info->statedir_arg = gengetopt_strdup (optarg);
- if (args_info->statedir_orig)
- free (args_info->statedir_orig); /* free previous string */
- args_info->statedir_orig = gengetopt_strdup (optarg);
- }
- /* DNS Server to use. */
- else if (strcmp (long_options[option_index].name, "dns") == 0)
- {
- if (local_args_info.dns_given)
- {
- fprintf (stderr, "%s: `--dns' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->dns_given && ! override)
- continue;
- local_args_info.dns_given = 1;
- args_info->dns_given = 1;
- if (args_info->dns_arg)
- free (args_info->dns_arg); /* free previous string */
- args_info->dns_arg = gengetopt_strdup (optarg);
- if (args_info->dns_orig)
- free (args_info->dns_orig); /* free previous string */
- args_info->dns_orig = gengetopt_strdup (optarg);
- }
- /* Number of contexts. */
- else if (strcmp (long_options[option_index].name, "contexts") == 0)
- {
- if (local_args_info.contexts_given)
- {
- fprintf (stderr, "%s: `--contexts' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->contexts_given && ! override)
- continue;
- local_args_info.contexts_given = 1;
- args_info->contexts_given = 1;
- args_info->contexts_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->contexts_orig)
- free (args_info->contexts_orig); /* free previous string */
- args_info->contexts_orig = gengetopt_strdup (optarg);
- }
- /* Exit after timelimit seconds. */
- else if (strcmp (long_options[option_index].name, "timelimit") == 0)
- {
- if (local_args_info.timelimit_given)
- {
- fprintf (stderr, "%s: `--timelimit' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->timelimit_given && ! override)
- continue;
- local_args_info.timelimit_given = 1;
- args_info->timelimit_given = 1;
- args_info->timelimit_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->timelimit_orig)
- free (args_info->timelimit_orig); /* free previous string */
- args_info->timelimit_orig = gengetopt_strdup (optarg);
- }
- /* GTP version to use. */
- else if (strcmp (long_options[option_index].name, "gtpversion") == 0)
- {
- if (local_args_info.gtpversion_given)
- {
- fprintf (stderr, "%s: `--gtpversion' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->gtpversion_given && ! override)
- continue;
- local_args_info.gtpversion_given = 1;
- args_info->gtpversion_given = 1;
- args_info->gtpversion_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->gtpversion_orig)
- free (args_info->gtpversion_orig); /* free previous string */
- args_info->gtpversion_orig = gengetopt_strdup (optarg);
- }
- /* Selection mode. */
- else if (strcmp (long_options[option_index].name, "selmode") == 0)
- {
- if (local_args_info.selmode_given)
- {
- fprintf (stderr, "%s: `--selmode' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->selmode_given && ! override)
- continue;
- local_args_info.selmode_given = 1;
- args_info->selmode_given = 1;
- args_info->selmode_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->selmode_orig)
- 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)
- {
- 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;
- }
- /* Routing Area Information. */
- else if (strcmp (long_options[option_index].name, "rai") == 0)
- {
- if (args_info->rai_given)
- {
- fprintf (stderr, "%s: `--rai' option given more than once\n", PACKAGE);
- exit (EXIT_FAILURE);
- }
- args_info->rai_given = 1;
- args_info->rai_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)
- {
- if (local_args_info.nsapi_given)
- {
- fprintf (stderr, "%s: `--nsapi' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->nsapi_given && ! override)
- continue;
- local_args_info.nsapi_given = 1;
- args_info->nsapi_given = 1;
- args_info->nsapi_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->nsapi_orig)
- free (args_info->nsapi_orig); /* free previous string */
- args_info->nsapi_orig = gengetopt_strdup (optarg);
- }
- /* Charging characteristics. */
- else if (strcmp (long_options[option_index].name, "charging") == 0)
- {
- if (local_args_info.charging_given)
- {
- fprintf (stderr, "%s: `--charging' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->charging_given && ! override)
- continue;
- local_args_info.charging_given = 1;
- args_info->charging_given = 1;
- args_info->charging_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->charging_orig)
- free (args_info->charging_orig); /* free previous string */
- args_info->charging_orig = gengetopt_strdup (optarg);
- }
- /* Create local network interface. */
- else if (strcmp (long_options[option_index].name, "createif") == 0)
- {
- if (local_args_info.createif_given)
- {
- fprintf (stderr, "%s: `--createif' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->createif_given && ! override)
- continue;
- local_args_info.createif_given = 1;
- args_info->createif_given = 1;
- args_info->createif_flag = !(args_info->createif_flag);
- }
- /* Create default route. */
- else if (strcmp (long_options[option_index].name, "defaultroute") == 0)
- {
- if (local_args_info.defaultroute_given)
- {
- fprintf (stderr, "%s: `--defaultroute' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->defaultroute_given && ! override)
- continue;
- local_args_info.defaultroute_given = 1;
- args_info->defaultroute_given = 1;
- args_info->defaultroute_flag = !(args_info->defaultroute_flag);
- }
- /* Script to run after link-up. */
- else if (strcmp (long_options[option_index].name, "ipup") == 0)
- {
- if (local_args_info.ipup_given)
- {
- fprintf (stderr, "%s: `--ipup' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->ipup_given && ! override)
- continue;
- local_args_info.ipup_given = 1;
- args_info->ipup_given = 1;
- if (args_info->ipup_arg)
- free (args_info->ipup_arg); /* free previous string */
- args_info->ipup_arg = gengetopt_strdup (optarg);
- if (args_info->ipup_orig)
- free (args_info->ipup_orig); /* free previous string */
- args_info->ipup_orig = gengetopt_strdup (optarg);
- }
- /* Script to run after link-down. */
- else if (strcmp (long_options[option_index].name, "ipdown") == 0)
- {
- if (local_args_info.ipdown_given)
- {
- fprintf (stderr, "%s: `--ipdown' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->ipdown_given && ! override)
- continue;
- local_args_info.ipdown_given = 1;
- args_info->ipdown_given = 1;
- if (args_info->ipdown_arg)
- free (args_info->ipdown_arg); /* free previous string */
- args_info->ipdown_arg = gengetopt_strdup (optarg);
- if (args_info->ipdown_orig)
- free (args_info->ipdown_orig); /* free previous string */
- args_info->ipdown_orig = gengetopt_strdup (optarg);
- }
- /* Ping remote host. */
- else if (strcmp (long_options[option_index].name, "pinghost") == 0)
- {
- if (local_args_info.pinghost_given)
- {
- fprintf (stderr, "%s: `--pinghost' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->pinghost_given && ! override)
- continue;
- local_args_info.pinghost_given = 1;
- args_info->pinghost_given = 1;
- if (args_info->pinghost_arg)
- free (args_info->pinghost_arg); /* free previous string */
- args_info->pinghost_arg = gengetopt_strdup (optarg);
- if (args_info->pinghost_orig)
- free (args_info->pinghost_orig); /* free previous string */
- args_info->pinghost_orig = gengetopt_strdup (optarg);
- }
- /* Number of ping req per second. */
- else if (strcmp (long_options[option_index].name, "pingrate") == 0)
- {
- if (local_args_info.pingrate_given)
- {
- fprintf (stderr, "%s: `--pingrate' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->pingrate_given && ! override)
- continue;
- local_args_info.pingrate_given = 1;
- args_info->pingrate_given = 1;
- args_info->pingrate_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->pingrate_orig)
- free (args_info->pingrate_orig); /* free previous string */
- args_info->pingrate_orig = gengetopt_strdup (optarg);
- }
- /* Number of ping data bytes. */
- else if (strcmp (long_options[option_index].name, "pingsize") == 0)
- {
- if (local_args_info.pingsize_given)
- {
- fprintf (stderr, "%s: `--pingsize' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->pingsize_given && ! override)
- continue;
- local_args_info.pingsize_given = 1;
- args_info->pingsize_given = 1;
- args_info->pingsize_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->pingsize_orig)
- free (args_info->pingsize_orig); /* free previous string */
- args_info->pingsize_orig = gengetopt_strdup (optarg);
- }
- /* Number of ping req to send. */
- else if (strcmp (long_options[option_index].name, "pingcount") == 0)
- {
- if (local_args_info.pingcount_given)
- {
- fprintf (stderr, "%s: `--pingcount' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->pingcount_given && ! override)
- continue;
- local_args_info.pingcount_given = 1;
- args_info->pingcount_given = 1;
- args_info->pingcount_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->pingcount_orig)
- free (args_info->pingcount_orig); /* free previous string */
- args_info->pingcount_orig = gengetopt_strdup (optarg);
- }
- /* Do not print ping packet info. */
- else if (strcmp (long_options[option_index].name, "pingquiet") == 0)
- {
- if (local_args_info.pingquiet_given)
- {
- fprintf (stderr, "%s: `--pingquiet' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->pingquiet_given && ! override)
- continue;
- local_args_info.pingquiet_given = 1;
- args_info->pingquiet_given = 1;
- args_info->pingquiet_flag = !(args_info->pingquiet_flag);
- }
- /* Do not send recovery. */
- else if (strcmp (long_options[option_index].name, "norecovery") == 0)
- {
- if (local_args_info.norecovery_given)
- {
- fprintf (stderr, "%s: `--norecovery' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
- goto failure;
- }
- if (args_info->norecovery_given && ! override)
- continue;
- local_args_info.norecovery_given = 1;
- args_info->norecovery_given = 1;
- args_info->norecovery_flag = !(args_info->norecovery_flag);
- }
-
- break;
- case '?': /* Invalid option. */
- /* `getopt_long' already printed an error message. */
- goto failure;
-
- default: /* bug: option not considered. */
- fprintf (stderr, "%s: option unknown: %c%s\n", CMDLINE_PARSER_PACKAGE, c, (additional_error ? additional_error : ""));
- abort ();
- } /* switch */
- } /* while */
-
-
-
-
- cmdline_parser_release (&local_args_info);
-
- if ( error )
- return (EXIT_FAILURE);
-
- return 0;
+ int c; /* Character of the parsed option. */
+
+ int error = 0;
+ struct gengetopt_args_info local_args_info;
+
+ if (initialize)
+ cmdline_parser_init(args_info);
+
+ cmdline_parser_init(&local_args_info);
+
+ optarg = 0;
+ optind = 0;
+ opterr = 1;
+ optopt = '?';
+
+ while (1) {
+ int option_index = 0;
+ char *stop_char;
+
+ static struct option long_options[] = {
+ {"help", 0, NULL, 'h'},
+ {"version", 0, NULL, 'V'},
+ {"debug", 0, NULL, 'd'},
+ {"conf", 1, NULL, 'c'},
+ {"pidfile", 1, NULL, 0},
+ {"statedir", 1, NULL, 0},
+ {"dns", 1, NULL, 0},
+ {"listen", 1, NULL, 'l'},
+ {"remote", 1, NULL, 'r'},
+ {"contexts", 1, NULL, 0},
+ {"timelimit", 1, NULL, 0},
+ {"gtpversion", 1, NULL, 0},
+ {"apn", 1, NULL, 'a'},
+ {"selmode", 1, NULL, 0},
+ {"rattype", 1, NULL, 0},
+ {"userloc", 1, NULL, 0},
+ {"rai", 1, NULL, 0},
+ {"mstz", 1, NULL, 0},
+ {"imeisv", 1, NULL, 0},
+ {"imsi", 1, NULL, 'i'},
+ {"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'},
+ {"createif", 0, NULL, 0},
+ {"net", 1, NULL, 'n'},
+ {"defaultroute", 0, NULL, 0},
+ {"ipup", 1, NULL, 0},
+ {"ipdown", 1, NULL, 0},
+ {"pinghost", 1, NULL, 0},
+ {"pingrate", 1, NULL, 0},
+ {"pingsize", 1, NULL, 0},
+ {"pingcount", 1, NULL, 0},
+ {"pingquiet", 0, NULL, 0},
+ {"norecovery", 0, NULL, 0},
+ {NULL, 0, NULL, 0}
+ };
+
+ stop_char = 0;
+ c = getopt_long(argc, argv, "hVdc:l:r:a:i:m:q:u:p:n:",
+ long_options, &option_index);
+
+ if (c == -1)
+ break; /* Exit from `while (1)' loop. */
+
+ switch (c) {
+ case 'h': /* Print help and exit. */
+ cmdline_parser_print_help();
+ cmdline_parser_free(&local_args_info);
+ exit(EXIT_SUCCESS);
+
+ case 'V': /* Print version and exit. */
+ cmdline_parser_print_version();
+ cmdline_parser_free(&local_args_info);
+ exit(EXIT_SUCCESS);
+
+ case 'd': /* Run in debug mode. */
+ if (local_args_info.debug_given) {
+ fprintf(stderr,
+ "%s: `--debug' (`-d') option given more than once%s\n",
+ argv[0],
+ (additional_error ? additional_error :
+ ""));
+ goto failure;
+ }
+ if (args_info->debug_given && !override)
+ continue;
+ local_args_info.debug_given = 1;
+ args_info->debug_given = 1;
+ args_info->debug_flag = !(args_info->debug_flag);
+ break;
+
+ case 'c': /* Read configuration file. */
+ if (local_args_info.conf_given) {
+ fprintf(stderr,
+ "%s: `--conf' (`-c') option given more than once%s\n",
+ argv[0],
+ (additional_error ? additional_error :
+ ""));
+ goto failure;
+ }
+ if (args_info->conf_given && !override)
+ continue;
+ local_args_info.conf_given = 1;
+ args_info->conf_given = 1;
+ if (args_info->conf_arg)
+ free(args_info->conf_arg); /* free previous string */
+ args_info->conf_arg = gengetopt_strdup(optarg);
+ if (args_info->conf_orig)
+ free(args_info->conf_orig); /* free previous string */
+ args_info->conf_orig = gengetopt_strdup(optarg);
+ break;
+
+ case 'l': /* Local interface. */
+ if (local_args_info.listen_given) {
+ fprintf(stderr,
+ "%s: `--listen' (`-l') option given more than once%s\n",
+ argv[0],
+ (additional_error ? additional_error :
+ ""));
+ goto failure;
+ }
+ if (args_info->listen_given && !override)
+ continue;
+ local_args_info.listen_given = 1;
+ args_info->listen_given = 1;
+ if (args_info->listen_arg)
+ free(args_info->listen_arg); /* free previous string */
+ args_info->listen_arg = gengetopt_strdup(optarg);
+ if (args_info->listen_orig)
+ free(args_info->listen_orig); /* free previous string */
+ args_info->listen_orig = gengetopt_strdup(optarg);
+ break;
+
+ case 'r': /* Remote host. */
+ if (local_args_info.remote_given) {
+ fprintf(stderr,
+ "%s: `--remote' (`-r') option given more than once%s\n",
+ argv[0],
+ (additional_error ? additional_error :
+ ""));
+ goto failure;
+ }
+ if (args_info->remote_given && !override)
+ continue;
+ local_args_info.remote_given = 1;
+ args_info->remote_given = 1;
+ if (args_info->remote_arg)
+ free(args_info->remote_arg); /* free previous string */
+ args_info->remote_arg = gengetopt_strdup(optarg);
+ if (args_info->remote_orig)
+ free(args_info->remote_orig); /* free previous string */
+ args_info->remote_orig = gengetopt_strdup(optarg);
+ break;
+
+ case 'a': /* Access point name. */
+ if (local_args_info.apn_given) {
+ fprintf(stderr,
+ "%s: `--apn' (`-a') option given more than once%s\n",
+ argv[0],
+ (additional_error ? additional_error :
+ ""));
+ goto failure;
+ }
+ if (args_info->apn_given && !override)
+ continue;
+ local_args_info.apn_given = 1;
+ args_info->apn_given = 1;
+ if (args_info->apn_arg)
+ free(args_info->apn_arg); /* free previous string */
+ args_info->apn_arg = gengetopt_strdup(optarg);
+ if (args_info->apn_orig)
+ free(args_info->apn_orig); /* free previous string */
+ args_info->apn_orig = gengetopt_strdup(optarg);
+ break;
+
+ case 'i': /* IMSI. */
+ if (local_args_info.imsi_given) {
+ fprintf(stderr,
+ "%s: `--imsi' (`-i') option given more than once%s\n",
+ argv[0],
+ (additional_error ? additional_error :
+ ""));
+ goto failure;
+ }
+ if (args_info->imsi_given && !override)
+ continue;
+ local_args_info.imsi_given = 1;
+ args_info->imsi_given = 1;
+ if (args_info->imsi_arg)
+ free(args_info->imsi_arg); /* free previous string */
+ args_info->imsi_arg = gengetopt_strdup(optarg);
+ if (args_info->imsi_orig)
+ free(args_info->imsi_orig); /* free previous string */
+ args_info->imsi_orig = gengetopt_strdup(optarg);
+ break;
+
+ case 'm': /* Mobile Station ISDN number. */
+ if (local_args_info.msisdn_given) {
+ fprintf(stderr,
+ "%s: `--msisdn' (`-m') option given more than once%s\n",
+ argv[0],
+ (additional_error ? additional_error :
+ ""));
+ goto failure;
+ }
+ if (args_info->msisdn_given && !override)
+ continue;
+ local_args_info.msisdn_given = 1;
+ args_info->msisdn_given = 1;
+ if (args_info->msisdn_arg)
+ free(args_info->msisdn_arg); /* free previous string */
+ args_info->msisdn_arg = gengetopt_strdup(optarg);
+ if (args_info->msisdn_orig)
+ free(args_info->msisdn_orig); /* free previous string */
+ args_info->msisdn_orig = gengetopt_strdup(optarg);
+ break;
+
+ case 'q': /* Requested quality of service. */
+ if (local_args_info.qos_given) {
+ fprintf(stderr,
+ "%s: `--qos' (`-q') option given more than once%s\n",
+ argv[0],
+ (additional_error ? additional_error :
+ ""));
+ goto failure;
+ }
+ if (args_info->qos_given && !override)
+ continue;
+ local_args_info.qos_given = 1;
+ args_info->qos_given = 1;
+ args_info->qos_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->qos_orig)
+ free(args_info->qos_orig); /* free previous string */
+ args_info->qos_orig = gengetopt_strdup(optarg);
+ break;
+
+ case 'u': /* Login user ID. */
+ if (local_args_info.uid_given) {
+ fprintf(stderr,
+ "%s: `--uid' (`-u') option given more than once%s\n",
+ argv[0],
+ (additional_error ? additional_error :
+ ""));
+ goto failure;
+ }
+ if (args_info->uid_given && !override)
+ continue;
+ local_args_info.uid_given = 1;
+ args_info->uid_given = 1;
+ if (args_info->uid_arg)
+ free(args_info->uid_arg); /* free previous string */
+ args_info->uid_arg = gengetopt_strdup(optarg);
+ if (args_info->uid_orig)
+ free(args_info->uid_orig); /* free previous string */
+ args_info->uid_orig = gengetopt_strdup(optarg);
+ break;
+
+ case 'p': /* Login password. */
+ if (local_args_info.pwd_given) {
+ fprintf(stderr,
+ "%s: `--pwd' (`-p') option given more than once%s\n",
+ argv[0],
+ (additional_error ? additional_error :
+ ""));
+ goto failure;
+ }
+ if (args_info->pwd_given && !override)
+ continue;
+ local_args_info.pwd_given = 1;
+ args_info->pwd_given = 1;
+ if (args_info->pwd_arg)
+ free(args_info->pwd_arg); /* free previous string */
+ args_info->pwd_arg = gengetopt_strdup(optarg);
+ if (args_info->pwd_orig)
+ free(args_info->pwd_orig); /* free previous string */
+ args_info->pwd_orig = gengetopt_strdup(optarg);
+ break;
+
+ case 'n': /* Network address for local interface. */
+ if (local_args_info.net_given) {
+ fprintf(stderr,
+ "%s: `--net' (`-n') option given more than once%s\n",
+ argv[0],
+ (additional_error ? additional_error :
+ ""));
+ goto failure;
+ }
+ if (args_info->net_given && !override)
+ continue;
+ local_args_info.net_given = 1;
+ args_info->net_given = 1;
+ if (args_info->net_arg)
+ free(args_info->net_arg); /* free previous string */
+ args_info->net_arg = gengetopt_strdup(optarg);
+ if (args_info->net_orig)
+ free(args_info->net_orig); /* free previous string */
+ args_info->net_orig = gengetopt_strdup(optarg);
+ break;
+
+ case 0: /* Long option with no short option */
+ /* Filename of process id file. */
+ if (strcmp(long_options[option_index].name, "pidfile")
+ == 0) {
+ if (local_args_info.pidfile_given) {
+ fprintf(stderr,
+ "%s: `--pidfile' option given more than once%s\n",
+ argv[0],
+ (additional_error ?
+ additional_error : ""));
+ goto failure;
+ }
+ if (args_info->pidfile_given && !override)
+ continue;
+ local_args_info.pidfile_given = 1;
+ args_info->pidfile_given = 1;
+ if (args_info->pidfile_arg)
+ free(args_info->pidfile_arg); /* free previous string */
+ args_info->pidfile_arg =
+ gengetopt_strdup(optarg);
+ if (args_info->pidfile_orig)
+ free(args_info->pidfile_orig); /* free previous string */
+ args_info->pidfile_orig =
+ gengetopt_strdup(optarg);
+ }
+ /* Directory of nonvolatile data. */
+ else if (strcmp
+ (long_options[option_index].name,
+ "statedir") == 0) {
+ if (local_args_info.statedir_given) {
+ fprintf(stderr,
+ "%s: `--statedir' option given more than once%s\n",
+ argv[0],
+ (additional_error ?
+ additional_error : ""));
+ goto failure;
+ }
+ if (args_info->statedir_given && !override)
+ continue;
+ local_args_info.statedir_given = 1;
+ args_info->statedir_given = 1;
+ if (args_info->statedir_arg)
+ free(args_info->statedir_arg); /* free previous string */
+ args_info->statedir_arg =
+ gengetopt_strdup(optarg);
+ if (args_info->statedir_orig)
+ free(args_info->statedir_orig); /* free previous string */
+ args_info->statedir_orig =
+ gengetopt_strdup(optarg);
+ }
+ /* DNS Server to use. */
+ else if (strcmp(long_options[option_index].name, "dns")
+ == 0) {
+ if (local_args_info.dns_given) {
+ fprintf(stderr,
+ "%s: `--dns' option given more than once%s\n",
+ argv[0],
+ (additional_error ?
+ additional_error : ""));
+ goto failure;
+ }
+ if (args_info->dns_given && !override)
+ continue;
+ local_args_info.dns_given = 1;
+ args_info->dns_given = 1;
+ if (args_info->dns_arg)
+ free(args_info->dns_arg); /* free previous string */
+ args_info->dns_arg = gengetopt_strdup(optarg);
+ if (args_info->dns_orig)
+ free(args_info->dns_orig); /* free previous string */
+ args_info->dns_orig = gengetopt_strdup(optarg);
+ }
+ /* Number of contexts. */
+ else if (strcmp
+ (long_options[option_index].name,
+ "contexts") == 0) {
+ if (local_args_info.contexts_given) {
+ fprintf(stderr,
+ "%s: `--contexts' option given more than once%s\n",
+ argv[0],
+ (additional_error ?
+ additional_error : ""));
+ goto failure;
+ }
+ if (args_info->contexts_given && !override)
+ continue;
+ local_args_info.contexts_given = 1;
+ args_info->contexts_given = 1;
+ args_info->contexts_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->contexts_orig)
+ free(args_info->contexts_orig); /* free previous string */
+ args_info->contexts_orig =
+ gengetopt_strdup(optarg);
+ }
+ /* Exit after timelimit seconds. */
+ else if (strcmp
+ (long_options[option_index].name,
+ "timelimit") == 0) {
+ if (local_args_info.timelimit_given) {
+ fprintf(stderr,
+ "%s: `--timelimit' option given more than once%s\n",
+ argv[0],
+ (additional_error ?
+ additional_error : ""));
+ goto failure;
+ }
+ if (args_info->timelimit_given && !override)
+ continue;
+ local_args_info.timelimit_given = 1;
+ args_info->timelimit_given = 1;
+ args_info->timelimit_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->timelimit_orig)
+ free(args_info->timelimit_orig); /* free previous string */
+ args_info->timelimit_orig =
+ gengetopt_strdup(optarg);
+ }
+ /* GTP version to use. */
+ else if (strcmp
+ (long_options[option_index].name,
+ "gtpversion") == 0) {
+ if (local_args_info.gtpversion_given) {
+ fprintf(stderr,
+ "%s: `--gtpversion' option given more than once%s\n",
+ argv[0],
+ (additional_error ?
+ additional_error : ""));
+ goto failure;
+ }
+ if (args_info->gtpversion_given && !override)
+ continue;
+ local_args_info.gtpversion_given = 1;
+ args_info->gtpversion_given = 1;
+ args_info->gtpversion_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->gtpversion_orig)
+ free(args_info->gtpversion_orig); /* free previous string */
+ args_info->gtpversion_orig =
+ gengetopt_strdup(optarg);
+ }
+ /* Selection mode. */
+ else if (strcmp
+ (long_options[option_index].name,
+ "selmode") == 0) {
+ if (local_args_info.selmode_given) {
+ fprintf(stderr,
+ "%s: `--selmode' option given more than once%s\n",
+ argv[0],
+ (additional_error ?
+ additional_error : ""));
+ goto failure;
+ }
+ if (args_info->selmode_given && !override)
+ continue;
+ local_args_info.selmode_given = 1;
+ args_info->selmode_given = 1;
+ args_info->selmode_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->selmode_orig)
+ 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) {
+ 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;
+ }
+ /* Routing Area Information. */
+ else if (strcmp(long_options[option_index].name, "rai")
+ == 0) {
+ if (args_info->rai_given) {
+ fprintf(stderr,
+ "%s: `--rai' option given more than once\n",
+ PACKAGE);
+ exit(EXIT_FAILURE);
+ }
+ args_info->rai_given = 1;
+ args_info->rai_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) {
+ if (local_args_info.nsapi_given) {
+ fprintf(stderr,
+ "%s: `--nsapi' option given more than once%s\n",
+ argv[0],
+ (additional_error ?
+ additional_error : ""));
+ goto failure;
+ }
+ if (args_info->nsapi_given && !override)
+ continue;
+ local_args_info.nsapi_given = 1;
+ args_info->nsapi_given = 1;
+ args_info->nsapi_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->nsapi_orig)
+ free(args_info->nsapi_orig); /* free previous string */
+ args_info->nsapi_orig =
+ gengetopt_strdup(optarg);
+ }
+ /* Charging characteristics. */
+ else if (strcmp
+ (long_options[option_index].name,
+ "charging") == 0) {
+ if (local_args_info.charging_given) {
+ fprintf(stderr,
+ "%s: `--charging' option given more than once%s\n",
+ argv[0],
+ (additional_error ?
+ additional_error : ""));
+ goto failure;
+ }
+ if (args_info->charging_given && !override)
+ continue;
+ local_args_info.charging_given = 1;
+ args_info->charging_given = 1;
+ args_info->charging_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->charging_orig)
+ free(args_info->charging_orig); /* free previous string */
+ args_info->charging_orig =
+ gengetopt_strdup(optarg);
+ }
+ /* Create local network interface. */
+ else if (strcmp
+ (long_options[option_index].name,
+ "createif") == 0) {
+ if (local_args_info.createif_given) {
+ fprintf(stderr,
+ "%s: `--createif' option given more than once%s\n",
+ argv[0],
+ (additional_error ?
+ additional_error : ""));
+ goto failure;
+ }
+ if (args_info->createif_given && !override)
+ continue;
+ local_args_info.createif_given = 1;
+ args_info->createif_given = 1;
+ args_info->createif_flag =
+ !(args_info->createif_flag);
+ }
+ /* Create default route. */
+ else if (strcmp
+ (long_options[option_index].name,
+ "defaultroute") == 0) {
+ if (local_args_info.defaultroute_given) {
+ fprintf(stderr,
+ "%s: `--defaultroute' option given more than once%s\n",
+ argv[0],
+ (additional_error ?
+ additional_error : ""));
+ goto failure;
+ }
+ if (args_info->defaultroute_given && !override)
+ continue;
+ local_args_info.defaultroute_given = 1;
+ args_info->defaultroute_given = 1;
+ args_info->defaultroute_flag =
+ !(args_info->defaultroute_flag);
+ }
+ /* Script to run after link-up. */
+ else if (strcmp(long_options[option_index].name, "ipup")
+ == 0) {
+ if (local_args_info.ipup_given) {
+ fprintf(stderr,
+ "%s: `--ipup' option given more than once%s\n",
+ argv[0],
+ (additional_error ?
+ additional_error : ""));
+ goto failure;
+ }
+ if (args_info->ipup_given && !override)
+ continue;
+ local_args_info.ipup_given = 1;
+ args_info->ipup_given = 1;
+ if (args_info->ipup_arg)
+ free(args_info->ipup_arg); /* free previous string */
+ args_info->ipup_arg = gengetopt_strdup(optarg);
+ if (args_info->ipup_orig)
+ free(args_info->ipup_orig); /* free previous string */
+ args_info->ipup_orig = gengetopt_strdup(optarg);
+ }
+ /* Script to run after link-down. */
+ else if (strcmp
+ (long_options[option_index].name,
+ "ipdown") == 0) {
+ if (local_args_info.ipdown_given) {
+ fprintf(stderr,
+ "%s: `--ipdown' option given more than once%s\n",
+ argv[0],
+ (additional_error ?
+ additional_error : ""));
+ goto failure;
+ }
+ if (args_info->ipdown_given && !override)
+ continue;
+ local_args_info.ipdown_given = 1;
+ args_info->ipdown_given = 1;
+ if (args_info->ipdown_arg)
+ free(args_info->ipdown_arg); /* free previous string */
+ args_info->ipdown_arg =
+ gengetopt_strdup(optarg);
+ if (args_info->ipdown_orig)
+ free(args_info->ipdown_orig); /* free previous string */
+ args_info->ipdown_orig =
+ gengetopt_strdup(optarg);
+ }
+ /* Ping remote host. */
+ else if (strcmp
+ (long_options[option_index].name,
+ "pinghost") == 0) {
+ if (local_args_info.pinghost_given) {
+ fprintf(stderr,
+ "%s: `--pinghost' option given more than once%s\n",
+ argv[0],
+ (additional_error ?
+ additional_error : ""));
+ goto failure;
+ }
+ if (args_info->pinghost_given && !override)
+ continue;
+ local_args_info.pinghost_given = 1;
+ args_info->pinghost_given = 1;
+ if (args_info->pinghost_arg)
+ free(args_info->pinghost_arg); /* free previous string */
+ args_info->pinghost_arg =
+ gengetopt_strdup(optarg);
+ if (args_info->pinghost_orig)
+ free(args_info->pinghost_orig); /* free previous string */
+ args_info->pinghost_orig =
+ gengetopt_strdup(optarg);
+ }
+ /* Number of ping req per second. */
+ else if (strcmp
+ (long_options[option_index].name,
+ "pingrate") == 0) {
+ if (local_args_info.pingrate_given) {
+ fprintf(stderr,
+ "%s: `--pingrate' option given more than once%s\n",
+ argv[0],
+ (additional_error ?
+ additional_error : ""));
+ goto failure;
+ }
+ if (args_info->pingrate_given && !override)
+ continue;
+ local_args_info.pingrate_given = 1;
+ args_info->pingrate_given = 1;
+ args_info->pingrate_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->pingrate_orig)
+ free(args_info->pingrate_orig); /* free previous string */
+ args_info->pingrate_orig =
+ gengetopt_strdup(optarg);
+ }
+ /* Number of ping data bytes. */
+ else if (strcmp
+ (long_options[option_index].name,
+ "pingsize") == 0) {
+ if (local_args_info.pingsize_given) {
+ fprintf(stderr,
+ "%s: `--pingsize' option given more than once%s\n",
+ argv[0],
+ (additional_error ?
+ additional_error : ""));
+ goto failure;
+ }
+ if (args_info->pingsize_given && !override)
+ continue;
+ local_args_info.pingsize_given = 1;
+ args_info->pingsize_given = 1;
+ args_info->pingsize_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->pingsize_orig)
+ free(args_info->pingsize_orig); /* free previous string */
+ args_info->pingsize_orig =
+ gengetopt_strdup(optarg);
+ }
+ /* Number of ping req to send. */
+ else if (strcmp
+ (long_options[option_index].name,
+ "pingcount") == 0) {
+ if (local_args_info.pingcount_given) {
+ fprintf(stderr,
+ "%s: `--pingcount' option given more than once%s\n",
+ argv[0],
+ (additional_error ?
+ additional_error : ""));
+ goto failure;
+ }
+ if (args_info->pingcount_given && !override)
+ continue;
+ local_args_info.pingcount_given = 1;
+ args_info->pingcount_given = 1;
+ args_info->pingcount_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->pingcount_orig)
+ free(args_info->pingcount_orig); /* free previous string */
+ args_info->pingcount_orig =
+ gengetopt_strdup(optarg);
+ }
+ /* Do not print ping packet info. */
+ else if (strcmp
+ (long_options[option_index].name,
+ "pingquiet") == 0) {
+ if (local_args_info.pingquiet_given) {
+ fprintf(stderr,
+ "%s: `--pingquiet' option given more than once%s\n",
+ argv[0],
+ (additional_error ?
+ additional_error : ""));
+ goto failure;
+ }
+ if (args_info->pingquiet_given && !override)
+ continue;
+ local_args_info.pingquiet_given = 1;
+ args_info->pingquiet_given = 1;
+ args_info->pingquiet_flag =
+ !(args_info->pingquiet_flag);
+ }
+ /* Do not send recovery. */
+ else if (strcmp
+ (long_options[option_index].name,
+ "norecovery") == 0) {
+ if (local_args_info.norecovery_given) {
+ fprintf(stderr,
+ "%s: `--norecovery' option given more than once%s\n",
+ argv[0],
+ (additional_error ?
+ additional_error : ""));
+ goto failure;
+ }
+ if (args_info->norecovery_given && !override)
+ continue;
+ local_args_info.norecovery_given = 1;
+ args_info->norecovery_given = 1;
+ args_info->norecovery_flag =
+ !(args_info->norecovery_flag);
+ }
+
+ break;
+ case '?': /* Invalid option. */
+ /* `getopt_long' already printed an error message. */
+ goto failure;
+
+ default: /* bug: option not considered. */
+ fprintf(stderr, "%s: option unknown: %c%s\n",
+ CMDLINE_PARSER_PACKAGE, c,
+ (additional_error ? additional_error : ""));
+ abort();
+ } /* switch */
+ } /* while */
+
+ cmdline_parser_release(&local_args_info);
+
+ if (error)
+ return (EXIT_FAILURE);
+
+ return 0;
failure:
-
- cmdline_parser_release (&local_args_info);
- return (EXIT_FAILURE);
+
+ cmdline_parser_release(&local_args_info);
+ return (EXIT_FAILURE);
}
#ifndef CONFIG_FILE_LINE_SIZE
@@ -1587,168 +1759,167 @@ failure:
#define CONFIG_FILE_LINE_BUFFER_SIZE (CONFIG_FILE_LINE_SIZE+3)
/* 3 is for "--" and "=" */
-char my_argv[CONFIG_FILE_LINE_BUFFER_SIZE+1];
+char my_argv[CONFIG_FILE_LINE_BUFFER_SIZE + 1];
int
-cmdline_parser_configfile (char * const filename, struct gengetopt_args_info *args_info, int override, int initialize, int check_required)
+cmdline_parser_configfile(char *const filename,
+ struct gengetopt_args_info *args_info, int override,
+ int initialize, int check_required)
{
- FILE* file;
- char linebuf[CONFIG_FILE_LINE_SIZE];
- int line_num = 0;
- int i, result, equal;
- char *fopt, *farg;
- char *str_index;
- size_t len, next_token;
- char delimiter;
- int my_argc = 0;
- char **my_argv_arg;
- char *additional_error;
-
- /* store the program name */
- cmd_line_list_tmp = (struct line_list *) malloc (sizeof (struct line_list));
- cmd_line_list_tmp->next = cmd_line_list;
- cmd_line_list = cmd_line_list_tmp;
- cmd_line_list->string_arg = gengetopt_strdup (CMDLINE_PARSER_PACKAGE);
-
- if ((file = fopen(filename, "r")) == NULL)
- {
- fprintf (stderr, "%s: Error opening configuration file '%s'\n",
- CMDLINE_PARSER_PACKAGE, filename);
- result = EXIT_FAILURE;
- goto conf_failure;
- }
-
- while ((fgets(linebuf, CONFIG_FILE_LINE_SIZE, file)) != NULL)
- {
- ++line_num;
- my_argv[0] = '\0';
- len = strlen(linebuf);
- if (len > (CONFIG_FILE_LINE_BUFFER_SIZE-1))
- {
- fprintf (stderr, "%s:%s:%d: Line too long in configuration file\n",
- CMDLINE_PARSER_PACKAGE, filename, line_num);
- result = EXIT_FAILURE;
- goto conf_failure;
- }
-
- /* find first non-whitespace character in the line */
- next_token = strspn ( linebuf, " \t\r\n");
- str_index = linebuf + next_token;
-
- if ( str_index[0] == '\0' || str_index[0] == '#')
- continue; /* empty line or comment line is skipped */
-
- fopt = str_index;
-
- /* truncate fopt at the end of the first non-valid character */
- next_token = strcspn (fopt, " \t\r\n=");
-
- if (fopt[next_token] == '\0') /* the line is over */
- {
- farg = NULL;
- equal = 0;
- goto noarg;
- }
-
- /* remember if equal sign is present */
- equal = (fopt[next_token] == '=');
- fopt[next_token++] = '\0';
-
- /* advance pointers to the next token after the end of fopt */
- next_token += strspn (fopt + next_token, " \t\r\n");
- /* check for the presence of equal sign, and if so, skip it */
- if ( !equal )
- if ((equal = (fopt[next_token] == '=')))
- {
- next_token++;
- next_token += strspn (fopt + next_token, " \t\r\n");
- }
- str_index += next_token;
-
- /* find argument */
- farg = str_index;
- if ( farg[0] == '\"' || farg[0] == '\'' )
- { /* quoted argument */
- str_index = strchr (++farg, str_index[0] ); /* skip opening quote */
- if (! str_index)
- {
- fprintf
- (stderr,
- "%s:%s:%d: unterminated string in configuration file\n",
- CMDLINE_PARSER_PACKAGE, filename, line_num);
- result = EXIT_FAILURE;
- goto conf_failure;
- }
- }
- else
- { /* read up the remaining part up to a delimiter */
- next_token = strcspn (farg, " \t\r\n#\'\"");
- str_index += next_token;
- }
-
- /* truncate farg at the delimiter and store it for further check */
- delimiter = *str_index, *str_index++ = '\0';
-
- /* everything but comment is illegal at the end of line */
- if (delimiter != '\0' && delimiter != '#')
- {
- str_index += strspn(str_index, " \t\r\n");
- if (*str_index != '\0' && *str_index != '#')
- {
- fprintf
- (stderr,
- "%s:%s:%d: malformed string in configuration file\n",
- CMDLINE_PARSER_PACKAGE, filename, line_num);
- result = EXIT_FAILURE;
- goto conf_failure;
- }
- }
-
- noarg:
- ++my_argc;
- len = strlen(fopt);
-
- strcat (my_argv, len > 1 ? "--" : "-");
- strcat (my_argv, fopt);
- if (len > 1 && ((farg &&*farg) || equal))
- strcat (my_argv, "=");
- if (farg && *farg)
- strcat (my_argv, farg);
-
- cmd_line_list_tmp = (struct line_list *) malloc (sizeof (struct line_list));
- cmd_line_list_tmp->next = cmd_line_list;
- cmd_line_list = cmd_line_list_tmp;
- cmd_line_list->string_arg = gengetopt_strdup(my_argv);
- } /* while */
-
- ++my_argc; /* for program name */
- my_argv_arg = (char **) malloc((my_argc+1) * sizeof(char *));
- cmd_line_list_tmp = cmd_line_list;
- for (i = my_argc - 1; i >= 0; --i) {
- my_argv_arg[i] = cmd_line_list_tmp->string_arg;
- cmd_line_list_tmp = cmd_line_list_tmp->next;
- }
- my_argv_arg[my_argc] = 0;
-
- additional_error = (char *)malloc(strlen(filename) + strlen(ADDITIONAL_ERROR) + 1);
- strcpy (additional_error, ADDITIONAL_ERROR);
- strcat (additional_error, filename);
- result =
- cmdline_parser_internal (my_argc, my_argv_arg, args_info, override, initialize, check_required, additional_error);
-
- free (additional_error);
- free (my_argv_arg);
+ FILE *file;
+ char linebuf[CONFIG_FILE_LINE_SIZE];
+ int line_num = 0;
+ int i, result, equal;
+ char *fopt, *farg;
+ char *str_index;
+ size_t len, next_token;
+ char delimiter;
+ int my_argc = 0;
+ char **my_argv_arg;
+ char *additional_error;
+
+ /* store the program name */
+ cmd_line_list_tmp =
+ (struct line_list *)malloc(sizeof(struct line_list));
+ cmd_line_list_tmp->next = cmd_line_list;
+ cmd_line_list = cmd_line_list_tmp;
+ cmd_line_list->string_arg = gengetopt_strdup(CMDLINE_PARSER_PACKAGE);
+
+ if ((file = fopen(filename, "r")) == NULL) {
+ fprintf(stderr, "%s: Error opening configuration file '%s'\n",
+ CMDLINE_PARSER_PACKAGE, filename);
+ result = EXIT_FAILURE;
+ goto conf_failure;
+ }
+
+ while ((fgets(linebuf, CONFIG_FILE_LINE_SIZE, file)) != NULL) {
+ ++line_num;
+ my_argv[0] = '\0';
+ len = strlen(linebuf);
+ if (len > (CONFIG_FILE_LINE_BUFFER_SIZE - 1)) {
+ fprintf(stderr,
+ "%s:%s:%d: Line too long in configuration file\n",
+ CMDLINE_PARSER_PACKAGE, filename, line_num);
+ result = EXIT_FAILURE;
+ goto conf_failure;
+ }
+
+ /* find first non-whitespace character in the line */
+ next_token = strspn(linebuf, " \t\r\n");
+ str_index = linebuf + next_token;
+
+ if (str_index[0] == '\0' || str_index[0] == '#')
+ continue; /* empty line or comment line is skipped */
+
+ fopt = str_index;
+
+ /* truncate fopt at the end of the first non-valid character */
+ next_token = strcspn(fopt, " \t\r\n=");
+
+ if (fopt[next_token] == '\0') { /* the line is over */
+ farg = NULL;
+ equal = 0;
+ goto noarg;
+ }
+
+ /* remember if equal sign is present */
+ equal = (fopt[next_token] == '=');
+ fopt[next_token++] = '\0';
+
+ /* advance pointers to the next token after the end of fopt */
+ next_token += strspn(fopt + next_token, " \t\r\n");
+ /* check for the presence of equal sign, and if so, skip it */
+ if (!equal)
+ if ((equal = (fopt[next_token] == '='))) {
+ next_token++;
+ next_token +=
+ strspn(fopt + next_token, " \t\r\n");
+ }
+ str_index += next_token;
+
+ /* find argument */
+ farg = str_index;
+ if (farg[0] == '\"' || farg[0] == '\'') { /* quoted argument */
+ str_index = strchr(++farg, str_index[0]); /* skip opening quote */
+ if (!str_index) {
+ fprintf
+ (stderr,
+ "%s:%s:%d: unterminated string in configuration file\n",
+ CMDLINE_PARSER_PACKAGE, filename,
+ line_num);
+ result = EXIT_FAILURE;
+ goto conf_failure;
+ }
+ } else { /* read up the remaining part up to a delimiter */
+ next_token = strcspn(farg, " \t\r\n#\'\"");
+ str_index += next_token;
+ }
+
+ /* truncate farg at the delimiter and store it for further check */
+ delimiter = *str_index, *str_index++ = '\0';
+
+ /* everything but comment is illegal at the end of line */
+ if (delimiter != '\0' && delimiter != '#') {
+ str_index += strspn(str_index, " \t\r\n");
+ if (*str_index != '\0' && *str_index != '#') {
+ fprintf
+ (stderr,
+ "%s:%s:%d: malformed string in configuration file\n",
+ CMDLINE_PARSER_PACKAGE, filename,
+ line_num);
+ result = EXIT_FAILURE;
+ goto conf_failure;
+ }
+ }
+
+noarg:
+ ++my_argc;
+ len = strlen(fopt);
+
+ strcat(my_argv, len > 1 ? "--" : "-");
+ strcat(my_argv, fopt);
+ if (len > 1 && ((farg && *farg) || equal))
+ strcat(my_argv, "=");
+ if (farg && *farg)
+ strcat(my_argv, farg);
+
+ cmd_line_list_tmp =
+ (struct line_list *)malloc(sizeof(struct line_list));
+ cmd_line_list_tmp->next = cmd_line_list;
+ cmd_line_list = cmd_line_list_tmp;
+ cmd_line_list->string_arg = gengetopt_strdup(my_argv);
+ } /* while */
+
+ ++my_argc; /* for program name */
+ my_argv_arg = (char **)malloc((my_argc + 1) * sizeof(char *));
+ cmd_line_list_tmp = cmd_line_list;
+ for (i = my_argc - 1; i >= 0; --i) {
+ my_argv_arg[i] = cmd_line_list_tmp->string_arg;
+ cmd_line_list_tmp = cmd_line_list_tmp->next;
+ }
+ my_argv_arg[my_argc] = 0;
+
+ additional_error =
+ (char *)malloc(strlen(filename) + strlen(ADDITIONAL_ERROR) + 1);
+ strcpy(additional_error, ADDITIONAL_ERROR);
+ strcat(additional_error, filename);
+ result =
+ cmdline_parser_internal(my_argc, my_argv_arg, args_info, override,
+ initialize, check_required,
+ additional_error);
+
+ free(additional_error);
+ free(my_argv_arg);
conf_failure:
- if (file)
- fclose(file);
-
- free_cmd_list();
- if (result == EXIT_FAILURE)
- {
- cmdline_parser_free (args_info);
- exit (EXIT_FAILURE);
- }
-
- return result;
+ if (file)
+ fclose(file);
+
+ free_cmd_list();
+ if (result == EXIT_FAILURE) {
+ cmdline_parser_free(args_info);
+ exit(EXIT_FAILURE);
+ }
+
+ return result;
}
diff --git a/sgsnemu/cmdline.h b/sgsnemu/cmdline.h
index 24185f4..17f7c18 100644
--- a/sgsnemu/cmdline.h
+++ b/sgsnemu/cmdline.h
@@ -12,7 +12,7 @@
#ifdef __cplusplus
extern "C" {
-#endif /* __cplusplus */
+#endif /* __cplusplus */
#ifndef CMDLINE_PARSER_PACKAGE
#define CMDLINE_PARSER_PACKAGE PACKAGE
@@ -22,190 +22,189 @@ extern "C" {
#define CMDLINE_PARSER_VERSION VERSION
#endif
-struct gengetopt_args_info
-{
- const char *help_help; /* Print help and exit help description. */
- const char *version_help; /* Print version and exit help description. */
- int debug_flag; /* Run in debug mode (default=off). */
- const char *debug_help; /* Run in debug mode help description. */
- char * conf_arg; /* Read configuration file. */
- char * conf_orig; /* Read configuration file original value given at command line. */
- const char *conf_help; /* Read configuration file help description. */
- char * pidfile_arg; /* Filename of process id file (default='./sgsnemu.pid'). */
- char * pidfile_orig; /* Filename of process id file original value given at command line. */
- const char *pidfile_help; /* Filename of process id file help description. */
- char * statedir_arg; /* Directory of nonvolatile data (default='./'). */
- char * statedir_orig; /* Directory of nonvolatile data original value given at command line. */
- const char *statedir_help; /* Directory of nonvolatile data help description. */
- char * dns_arg; /* DNS Server to use. */
- char * dns_orig; /* DNS Server to use original value given at command line. */
- const char *dns_help; /* DNS Server to use help description. */
- char * listen_arg; /* Local interface. */
- char * listen_orig; /* Local interface original value given at command line. */
- const char *listen_help; /* Local interface help description. */
- char * remote_arg; /* Remote host. */
- char * remote_orig; /* Remote host original value given at command line. */
- const char *remote_help; /* Remote host help description. */
- int contexts_arg; /* Number of contexts (default='1'). */
- char * contexts_orig; /* Number of contexts original value given at command line. */
- const char *contexts_help; /* Number of contexts help description. */
- int timelimit_arg; /* Exit after timelimit seconds (default='0'). */
- char * timelimit_orig; /* Exit after timelimit seconds original value given at command line. */
- const char *timelimit_help; /* Exit after timelimit seconds help description. */
- int gtpversion_arg; /* GTP version to use (default='1'). */
- char * gtpversion_orig; /* GTP version to use original value given at command line. */
- const char *gtpversion_help; /* GTP version to use help description. */
- char * apn_arg; /* Access point name (default='internet'). */
- char * apn_orig; /* Access point name original value given at command line. */
- const char *apn_help; /* Access point name help description. */
- 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 * rai_arg; /* Routing Area Information (optional). */
- char * rai_orig;
- char * rai_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. */
- int nsapi_arg; /* NSAPI (default='0'). */
- char * nsapi_orig; /* NSAPI original value given at command line. */
- const char *nsapi_help; /* NSAPI help description. */
- char * msisdn_arg; /* Mobile Station ISDN number (default='46702123456'). */
- char * msisdn_orig; /* Mobile Station ISDN number original value given at command line. */
- const char *msisdn_help; /* Mobile Station ISDN number help description. */
- 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. */
- char * uid_arg; /* Login user ID (default='mig'). */
- char * uid_orig; /* Login user ID original value given at command line. */
- const char *uid_help; /* Login user ID help description. */
- char * pwd_arg; /* Login password (default='hemmelig'). */
- char * pwd_orig; /* Login password original value given at command line. */
- const char *pwd_help; /* Login password help description. */
- int createif_flag; /* Create local network interface (default=off). */
- const char *createif_help; /* Create local network interface help description. */
- char * net_arg; /* Network address for local interface. */
- char * net_orig; /* Network address for local interface original value given at command line. */
- const char *net_help; /* Network address for local interface help description. */
- int defaultroute_flag; /* Create default route (default=off). */
- const char *defaultroute_help; /* Create default route help description. */
- char * ipup_arg; /* Script to run after link-up. */
- char * ipup_orig; /* Script to run after link-up original value given at command line. */
- const char *ipup_help; /* Script to run after link-up help description. */
- char * ipdown_arg; /* Script to run after link-down. */
- char * ipdown_orig; /* Script to run after link-down original value given at command line. */
- const char *ipdown_help; /* Script to run after link-down help description. */
- char * pinghost_arg; /* Ping remote host. */
- char * pinghost_orig; /* Ping remote host original value given at command line. */
- const char *pinghost_help; /* Ping remote host help description. */
- int pingrate_arg; /* Number of ping req per second (default='1'). */
- char * pingrate_orig; /* Number of ping req per second original value given at command line. */
- const char *pingrate_help; /* Number of ping req per second help description. */
- int pingsize_arg; /* Number of ping data bytes (default='56'). */
- char * pingsize_orig; /* Number of ping data bytes original value given at command line. */
- const char *pingsize_help; /* Number of ping data bytes help description. */
- int pingcount_arg; /* Number of ping req to send (default='0'). */
- char * pingcount_orig; /* Number of ping req to send original value given at command line. */
- const char *pingcount_help; /* Number of ping req to send help description. */
- int pingquiet_flag; /* Do not print ping packet info (default=off). */
- const char *pingquiet_help; /* Do not print ping packet info help description. */
- int norecovery_flag; /* Do not print ping packet info (default=off). */
- const char *norecovery_help; /* Do not print ping packet info help description. */
-
- int help_given ; /* Whether help was given. */
- int version_given ; /* Whether version was given. */
- int debug_given ; /* Whether debug was given. */
- int conf_given ; /* Whether conf was given. */
- int pidfile_given ; /* Whether pidfile was given. */
- int statedir_given ; /* Whether statedir was given. */
- int dns_given ; /* Whether dns was given. */
- int listen_given ; /* Whether listen was given. */
- int remote_given ; /* Whether remote was given. */
- int contexts_given ; /* Whether contexts was given. */
- int timelimit_given ; /* Whether timelimit was given. */
- 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 rai_given ; /* Whether RAI 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. */
- 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. */
- int createif_given ; /* Whether createif was given. */
- int net_given ; /* Whether net was given. */
- int defaultroute_given ; /* Whether defaultroute was given. */
- int ipup_given ; /* Whether ipup was given. */
- int ipdown_given ; /* Whether ipdown was given. */
- int pinghost_given ; /* Whether pinghost was given. */
- int pingrate_given ; /* Whether pingrate was given. */
- int pingsize_given ; /* Whether pingsize was given. */
- int pingcount_given ; /* Whether pingcount was given. */
- int pingquiet_given ; /* Whether pingquiet was given. */
- int norecovery_given ; /* Whether norecovery was given. */
-
-} ;
-
-extern const char *gengetopt_args_info_purpose;
-extern const char *gengetopt_args_info_usage;
-extern const char *gengetopt_args_info_help[];
-
-int cmdline_parser (int argc, char * const *argv,
- struct gengetopt_args_info *args_info);
-int cmdline_parser2 (int argc, char * const *argv,
- struct gengetopt_args_info *args_info,
- int override, int initialize, int check_required);
-int cmdline_parser_file_save(const char *filename,
- struct gengetopt_args_info *args_info);
-
-void cmdline_parser_print_help(void);
-void cmdline_parser_print_version(void);
-
-void cmdline_parser_init (struct gengetopt_args_info *args_info);
-void cmdline_parser_free (struct gengetopt_args_info *args_info);
-
-int cmdline_parser_configfile (char * const filename,
- struct gengetopt_args_info *args_info,
- int override, int initialize, int check_required);
-
-int cmdline_parser_required (struct gengetopt_args_info *args_info,
- const char *prog_name);
-
+ struct gengetopt_args_info {
+ const char *help_help; /* Print help and exit help description. */
+ const char *version_help; /* Print version and exit help description. */
+ int debug_flag; /* Run in debug mode (default=off). */
+ const char *debug_help; /* Run in debug mode help description. */
+ char *conf_arg; /* Read configuration file. */
+ char *conf_orig; /* Read configuration file original value given at command line. */
+ const char *conf_help; /* Read configuration file help description. */
+ char *pidfile_arg; /* Filename of process id file (default='./sgsnemu.pid'). */
+ char *pidfile_orig; /* Filename of process id file original value given at command line. */
+ const char *pidfile_help; /* Filename of process id file help description. */
+ char *statedir_arg; /* Directory of nonvolatile data (default='./'). */
+ char *statedir_orig; /* Directory of nonvolatile data original value given at command line. */
+ const char *statedir_help; /* Directory of nonvolatile data help description. */
+ char *dns_arg; /* DNS Server to use. */
+ char *dns_orig; /* DNS Server to use original value given at command line. */
+ const char *dns_help; /* DNS Server to use help description. */
+ char *listen_arg; /* Local interface. */
+ char *listen_orig; /* Local interface original value given at command line. */
+ const char *listen_help; /* Local interface help description. */
+ char *remote_arg; /* Remote host. */
+ char *remote_orig; /* Remote host original value given at command line. */
+ const char *remote_help; /* Remote host help description. */
+ int contexts_arg; /* Number of contexts (default='1'). */
+ char *contexts_orig; /* Number of contexts original value given at command line. */
+ const char *contexts_help; /* Number of contexts help description. */
+ int timelimit_arg; /* Exit after timelimit seconds (default='0'). */
+ char *timelimit_orig; /* Exit after timelimit seconds original value given at command line. */
+ const char *timelimit_help; /* Exit after timelimit seconds help description. */
+ int gtpversion_arg; /* GTP version to use (default='1'). */
+ char *gtpversion_orig; /* GTP version to use original value given at command line. */
+ const char *gtpversion_help; /* GTP version to use help description. */
+ char *apn_arg; /* Access point name (default='internet'). */
+ char *apn_orig; /* Access point name original value given at command line. */
+ const char *apn_help; /* Access point name help description. */
+ 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 *rai_arg; /* Routing Area Information (optional). */
+ char *rai_orig;
+ char *rai_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. */
+ int nsapi_arg; /* NSAPI (default='0'). */
+ char *nsapi_orig; /* NSAPI original value given at command line. */
+ const char *nsapi_help; /* NSAPI help description. */
+ char *msisdn_arg; /* Mobile Station ISDN number (default='46702123456'). */
+ char *msisdn_orig; /* Mobile Station ISDN number original value given at command line. */
+ const char *msisdn_help; /* Mobile Station ISDN number help description. */
+ 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. */
+ char *uid_arg; /* Login user ID (default='mig'). */
+ char *uid_orig; /* Login user ID original value given at command line. */
+ const char *uid_help; /* Login user ID help description. */
+ char *pwd_arg; /* Login password (default='hemmelig'). */
+ char *pwd_orig; /* Login password original value given at command line. */
+ const char *pwd_help; /* Login password help description. */
+ int createif_flag; /* Create local network interface (default=off). */
+ const char *createif_help; /* Create local network interface help description. */
+ char *net_arg; /* Network address for local interface. */
+ char *net_orig; /* Network address for local interface original value given at command line. */
+ const char *net_help; /* Network address for local interface help description. */
+ int defaultroute_flag; /* Create default route (default=off). */
+ const char *defaultroute_help; /* Create default route help description. */
+ char *ipup_arg; /* Script to run after link-up. */
+ char *ipup_orig; /* Script to run after link-up original value given at command line. */
+ const char *ipup_help; /* Script to run after link-up help description. */
+ char *ipdown_arg; /* Script to run after link-down. */
+ char *ipdown_orig; /* Script to run after link-down original value given at command line. */
+ const char *ipdown_help; /* Script to run after link-down help description. */
+ char *pinghost_arg; /* Ping remote host. */
+ char *pinghost_orig; /* Ping remote host original value given at command line. */
+ const char *pinghost_help; /* Ping remote host help description. */
+ int pingrate_arg; /* Number of ping req per second (default='1'). */
+ char *pingrate_orig; /* Number of ping req per second original value given at command line. */
+ const char *pingrate_help; /* Number of ping req per second help description. */
+ int pingsize_arg; /* Number of ping data bytes (default='56'). */
+ char *pingsize_orig; /* Number of ping data bytes original value given at command line. */
+ const char *pingsize_help; /* Number of ping data bytes help description. */
+ int pingcount_arg; /* Number of ping req to send (default='0'). */
+ char *pingcount_orig; /* Number of ping req to send original value given at command line. */
+ const char *pingcount_help; /* Number of ping req to send help description. */
+ int pingquiet_flag; /* Do not print ping packet info (default=off). */
+ const char *pingquiet_help; /* Do not print ping packet info help description. */
+ int norecovery_flag; /* Do not print ping packet info (default=off). */
+ const char *norecovery_help; /* Do not print ping packet info help description. */
+
+ int help_given; /* Whether help was given. */
+ int version_given; /* Whether version was given. */
+ int debug_given; /* Whether debug was given. */
+ int conf_given; /* Whether conf was given. */
+ int pidfile_given; /* Whether pidfile was given. */
+ int statedir_given; /* Whether statedir was given. */
+ int dns_given; /* Whether dns was given. */
+ int listen_given; /* Whether listen was given. */
+ int remote_given; /* Whether remote was given. */
+ int contexts_given; /* Whether contexts was given. */
+ int timelimit_given; /* Whether timelimit was given. */
+ 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 rai_given; /* Whether RAI 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. */
+ 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. */
+ int createif_given; /* Whether createif was given. */
+ int net_given; /* Whether net was given. */
+ int defaultroute_given; /* Whether defaultroute was given. */
+ int ipup_given; /* Whether ipup was given. */
+ int ipdown_given; /* Whether ipdown was given. */
+ int pinghost_given; /* Whether pinghost was given. */
+ int pingrate_given; /* Whether pingrate was given. */
+ int pingsize_given; /* Whether pingsize was given. */
+ int pingcount_given; /* Whether pingcount was given. */
+ int pingquiet_given; /* Whether pingquiet was given. */
+ int norecovery_given; /* Whether norecovery was given. */
+
+ };
+
+ extern const char *gengetopt_args_info_purpose;
+ extern const char *gengetopt_args_info_usage;
+ extern const char *gengetopt_args_info_help[];
+
+ int cmdline_parser(int argc, char *const *argv,
+ struct gengetopt_args_info *args_info);
+ int cmdline_parser2(int argc, char *const *argv,
+ struct gengetopt_args_info *args_info,
+ int override, int initialize, int check_required);
+ int cmdline_parser_file_save(const char *filename,
+ struct gengetopt_args_info *args_info);
+
+ void cmdline_parser_print_help(void);
+ void cmdline_parser_print_version(void);
+
+ void cmdline_parser_init(struct gengetopt_args_info *args_info);
+ void cmdline_parser_free(struct gengetopt_args_info *args_info);
+
+ int cmdline_parser_configfile(char *const filename,
+ struct gengetopt_args_info *args_info,
+ int override, int initialize,
+ int check_required);
+
+ int cmdline_parser_required(struct gengetopt_args_info *args_info,
+ const char *prog_name);
#ifdef __cplusplus
}
-#endif /* __cplusplus */
-#endif /* CMDLINE_H */
+#endif /* __cplusplus */
+#endif /* CMDLINE_H */
diff --git a/sgsnemu/sgsnemu.c b/sgsnemu/sgsnemu.c
index 48a33ea..79494c9 100644
--- a/sgsnemu/sgsnemu.c
+++ b/sgsnemu/sgsnemu.c
@@ -14,12 +14,10 @@
*
*/
-
#ifdef __linux__
-#define _GNU_SOURCE 1 /* strdup() prototype, broken arpa/inet.h */
+#define _GNU_SOURCE 1 /* strdup() prototype, broken arpa/inet.h */
#endif
-
#include <syslog.h>
#include <ctype.h>
#include <netdb.h>
@@ -51,15 +49,15 @@
#include "../gtp/gtp.h"
#include "cmdline.h"
-#define IPADDRLEN 256 /* Character length of addresses */
-#define MAXCONTEXTS 1024 /* Max number of allowed contexts */
+#define IPADDRLEN 256 /* Character length of addresses */
+#define MAXCONTEXTS 1024 /* Max number of allowed contexts */
/* HASH tables for IP address allocation */
struct iphash_t {
- uint8_t inuse; /* 0=free. 1=used by somebody */
- struct iphash_t *ipnext;
- struct pdp_t *pdp;
- struct in_addr addr;
+ uint8_t inuse; /* 0=free. 1=used by somebody */
+ struct iphash_t *ipnext;
+ struct pdp_t *pdp;
+ struct in_addr addr;
};
struct iphash_t iparr[MAXCONTEXTS];
struct iphash_t *iphash[MAXCONTEXTS];
@@ -73,52 +71,51 @@ struct iphash_t *iphash[MAXCONTEXTS];
/* 5: Disconnected */
int state = 0;
-struct gsn_t *gsn = NULL; /* GSN instance */
-struct tun_t *tun = NULL; /* TUN instance */
-int maxfd = 0; /* For select() */
-int echoversion = 1; /* First try this version */
+struct gsn_t *gsn = NULL; /* GSN instance */
+struct tun_t *tun = NULL; /* TUN instance */
+int maxfd = 0; /* For select() */
+int echoversion = 1; /* First try this version */
/* Struct with local versions of gengetopt options */
struct {
- int debug; /* Print debug messages */
- int createif; /* Create local network interface */
- struct in_addr netaddr, destaddr, net, mask; /* Network interface */
- char *ipup, *ipdown; /* Filename of scripts */
- int defaultroute; /* Set up default route */
- struct in_addr pinghost; /* Remote ping host */
- int pingrate;
- int pingsize;
- int pingcount;
- int pingquiet;
- struct in_addr listen;
- struct in_addr remote;
- struct in_addr dns;
- int contexts; /* Number of contexts to create */
- int timelimit; /* Number of seconds to be connected */
- char *statedir;
- uint64_t imsi;
- uint8_t nsapi;
- int gtpversion;
- struct ul255_t pco;
- struct ul255_t qos;
- 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 rai;
- int rai_given;
- struct ul255_t mstz;
- int mstz_given;
- struct ul255_t imeisv;
- int imeisv_given;
- struct ul16_t msisdn;
- int norecovery_given;
+ int debug; /* Print debug messages */
+ int createif; /* Create local network interface */
+ struct in_addr netaddr, destaddr, net, mask; /* Network interface */
+ char *ipup, *ipdown; /* Filename of scripts */
+ int defaultroute; /* Set up default route */
+ struct in_addr pinghost; /* Remote ping host */
+ int pingrate;
+ int pingsize;
+ int pingcount;
+ int pingquiet;
+ struct in_addr listen;
+ struct in_addr remote;
+ struct in_addr dns;
+ int contexts; /* Number of contexts to create */
+ int timelimit; /* Number of seconds to be connected */
+ char *statedir;
+ uint64_t imsi;
+ uint8_t nsapi;
+ int gtpversion;
+ struct ul255_t pco;
+ struct ul255_t qos;
+ 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 rai;
+ int rai_given;
+ struct ul255_t mstz;
+ int mstz_given;
+ struct ul255_t imeisv;
+ int imeisv_given;
+ struct ul16_t msisdn;
+ int norecovery_given;
} options;
-
/* Definitions to use for PING. Most of the ping code was derived from */
/* the original ping program by Mike Muuss */
@@ -128,23 +125,23 @@ struct {
#define CREATEPING_ICMP 8
struct ip_ping {
- uint8_t ipver; /* Type and header length*/
- uint8_t tos; /* Type of Service */
- uint16_t length; /* Total length */
- uint16_t fragid; /* Identifier */
- uint16_t offset; /* Flags and fragment offset */
- uint8_t ttl; /* Time to live */
- uint8_t protocol; /* Protocol */
- uint16_t ipcheck; /* Header checksum */
- uint32_t src; /* Source address */
- uint32_t dst; /* Destination */
- uint8_t type; /* Type and header length*/
- uint8_t code; /* Code */
- uint16_t checksum; /* Header checksum */
- uint16_t ident; /* Identifier */
- uint16_t seq; /* Sequence number */
- uint8_t data[CREATEPING_MAX]; /* Data */
-} __attribute__((packed));
+ uint8_t ipver; /* Type and header length */
+ uint8_t tos; /* Type of Service */
+ uint16_t length; /* Total length */
+ uint16_t fragid; /* Identifier */
+ uint16_t offset; /* Flags and fragment offset */
+ uint8_t ttl; /* Time to live */
+ uint8_t protocol; /* Protocol */
+ uint16_t ipcheck; /* Header checksum */
+ uint32_t src; /* Source address */
+ uint32_t dst; /* Destination */
+ uint8_t type; /* Type and header length */
+ uint8_t code; /* Code */
+ uint16_t checksum; /* Header checksum */
+ uint16_t ident; /* Identifier */
+ uint16_t seq; /* Sequence number */
+ uint8_t data[CREATEPING_MAX]; /* Data */
+} __attribute__ ((packed));
/* Statistical values for ping */
int nreceived = 0;
@@ -153,1489 +150,1562 @@ int ntransmitted = 0;
int tmin = 999999999;
int tmax = 0;
int tsum = 0;
-int pingseq = 0; /* Ping sequence counter */
+int pingseq = 0; /* Ping sequence counter */
struct timeval firstping;
-int ipset(struct iphash_t *ipaddr, struct in_addr *addr) {
- int hash = ippool_hash4(addr) % MAXCONTEXTS;
- struct iphash_t *h;
- struct iphash_t *prev = NULL;
- ipaddr->ipnext = NULL;
- ipaddr->addr.s_addr = addr->s_addr;
- for (h = iphash[hash]; h; h = h->ipnext)
- prev = h;
- if (!prev)
- iphash[hash] = ipaddr;
- else
- prev->ipnext = ipaddr;
- return 0;
+int ipset(struct iphash_t *ipaddr, struct in_addr *addr)
+{
+ int hash = ippool_hash4(addr) % MAXCONTEXTS;
+ struct iphash_t *h;
+ struct iphash_t *prev = NULL;
+ ipaddr->ipnext = NULL;
+ ipaddr->addr.s_addr = addr->s_addr;
+ for (h = iphash[hash]; h; h = h->ipnext)
+ prev = h;
+ if (!prev)
+ iphash[hash] = ipaddr;
+ else
+ prev->ipnext = ipaddr;
+ return 0;
}
-int ipdel(struct iphash_t *ipaddr) {
- int hash = ippool_hash4(&ipaddr->addr) % MAXCONTEXTS;
- struct iphash_t *h;
- struct iphash_t *prev = NULL;
- for (h = iphash[hash]; h; h = h->ipnext) {
- if (h == ipaddr) {
- if (!prev)
- iphash[hash] = h->ipnext;
- else
- prev->ipnext = h->ipnext;
- return 0;
- }
- prev = h;
- }
- return EOF; /* End of linked list and not found */
+int ipdel(struct iphash_t *ipaddr)
+{
+ int hash = ippool_hash4(&ipaddr->addr) % MAXCONTEXTS;
+ struct iphash_t *h;
+ struct iphash_t *prev = NULL;
+ for (h = iphash[hash]; h; h = h->ipnext) {
+ if (h == ipaddr) {
+ if (!prev)
+ iphash[hash] = h->ipnext;
+ else
+ prev->ipnext = h->ipnext;
+ return 0;
+ }
+ prev = h;
+ }
+ return EOF; /* End of linked list and not found */
}
-int ipget(struct iphash_t **ipaddr, struct in_addr *addr) {
- int hash = ippool_hash4(addr) % MAXCONTEXTS;
- struct iphash_t *h;
- for (h = iphash[hash]; h; h = h->ipnext) {
- if ((h->addr.s_addr == addr->s_addr)) {
- *ipaddr = h;
- return 0;
- }
- }
- return EOF; /* End of linked list and not found */
+int ipget(struct iphash_t **ipaddr, struct in_addr *addr)
+{
+ int hash = ippool_hash4(addr) % MAXCONTEXTS;
+ struct iphash_t *h;
+ for (h = iphash[hash]; h; h = h->ipnext) {
+ if ((h->addr.s_addr == addr->s_addr)) {
+ *ipaddr = h;
+ return 0;
+ }
+ }
+ return EOF; /* End of linked list and not found */
}
-
/* Used to write process ID to file. Assume someone else will delete */
-void log_pid(char *pidfile) {
- FILE *file;
- mode_t oldmask;
-
- oldmask = umask(022);
- file = fopen(pidfile, "w");
- umask(oldmask);
- if(!file)
- return;
- fprintf(file, "%d\n", (int) getpid());
- fclose(file);
+void log_pid(char *pidfile)
+{
+ FILE *file;
+ mode_t oldmask;
+
+ oldmask = umask(022);
+ file = fopen(pidfile, "w");
+ umask(oldmask);
+ if (!file)
+ return;
+ fprintf(file, "%d\n", (int)getpid());
+ fclose(file);
}
+int process_options(int argc, char **argv)
+{
+ /* gengeopt declarations */
+ struct gengetopt_args_info args_info;
+
+ 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 *rai_el[] = { "MCC", "MNC", "LAC", "RAC" };
+ char *mstz_el[] = { "SIGN", "QUARTERS", "DST" };
+ int sign;
+ int nbquarters;
+ int DST;
+
+ if (cmdline_parser(argc, argv, &args_info) != 0)
+ return -1;
+ if (args_info.debug_flag) {
+ if (args_info.remote_arg)
+ printf("remote: %s\n", args_info.remote_arg);
+ if (args_info.listen_arg)
+ printf("listen: %s\n", args_info.listen_arg);
+ if (args_info.conf_arg)
+ printf("conf: %s\n", args_info.conf_arg);
+ 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);
+ if (args_info.uid_arg)
+ printf("uid: %s\n", args_info.uid_arg);
+ if (args_info.pwd_arg)
+ printf("pwd: %s\n", args_info.pwd_arg);
+ if (args_info.pidfile_arg)
+ printf("pidfile: %s\n", args_info.pidfile_arg);
+ if (args_info.statedir_arg)
+ printf("statedir: %s\n", args_info.statedir_arg);
+ if (args_info.dns_arg)
+ printf("dns: %s\n", args_info.dns_arg);
+ printf("contexts: %d\n", args_info.contexts_arg);
+ printf("timelimit: %d\n", args_info.timelimit_arg);
+ printf("createif: %d\n", args_info.createif_flag);
+ if (args_info.ipup_arg)
+ printf("ipup: %s\n", args_info.ipup_arg);
+ if (args_info.ipdown_arg)
+ printf("ipdown: %s\n", args_info.ipdown_arg);
+ printf("defaultroute: %d\n", args_info.defaultroute_flag);
+ if (args_info.pinghost_arg)
+ printf("pinghost: %s\n", args_info.pinghost_arg);
+ printf("pingrate: %d\n", args_info.pingrate_arg);
+ printf("pingsize: %d\n", args_info.pingsize_arg);
+ printf("pingcount: %d\n", args_info.pingcount_arg);
+ printf("pingquiet: %d\n", args_info.pingquiet_flag);
+ printf("norecovery: %d\n", args_info.norecovery_flag);
+ }
+
+ /* Try out our new parser */
+
+ if (args_info.conf_arg) {
+ if (cmdline_parser_configfile
+ (args_info.conf_arg, &args_info, 0, 0, 0) != 0)
+ return -1;
+ if (args_info.debug_flag) {
+ printf("cmdline_parser_configfile\n");
+ if (args_info.remote_arg)
+ printf("remote: %s\n", args_info.remote_arg);
+ if (args_info.listen_arg)
+ printf("listen: %s\n", args_info.listen_arg);
+ if (args_info.conf_arg)
+ printf("conf: %s\n", args_info.conf_arg);
+ 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);
+ if (args_info.uid_arg)
+ printf("uid: %s\n", args_info.uid_arg);
+ if (args_info.pwd_arg)
+ printf("pwd: %s\n", args_info.pwd_arg);
+ if (args_info.pidfile_arg)
+ printf("pidfile: %s\n", args_info.pidfile_arg);
+ if (args_info.statedir_arg)
+ printf("statedir: %s\n",
+ args_info.statedir_arg);
+ if (args_info.dns_arg)
+ printf("dns: %s\n", args_info.dns_arg);
+ printf("contexts: %d\n", args_info.contexts_arg);
+ printf("timelimit: %d\n", args_info.timelimit_arg);
+ printf("createif: %d\n", args_info.createif_flag);
+ if (args_info.ipup_arg)
+ printf("ipup: %s\n", args_info.ipup_arg);
+ if (args_info.ipdown_arg)
+ printf("ipdown: %s\n", args_info.ipdown_arg);
+ printf("defaultroute: %d\n",
+ args_info.defaultroute_flag);
+ if (args_info.pinghost_arg)
+ printf("pinghost: %s\n",
+ args_info.pinghost_arg);
+ printf("pingrate: %d\n", args_info.pingrate_arg);
+ printf("pingsize: %d\n", args_info.pingsize_arg);
+ printf("pingcount: %d\n", args_info.pingcount_arg);
+ printf("pingquiet: %d\n", args_info.pingquiet_flag);
+ printf("norecovery: %d\n", args_info.norecovery_flag);
+ }
+ }
+
+ /* Handle each option */
+
+ /* foreground */
+ /* If fg flag not given run as a daemon */
+ /* Do not allow sgsnemu to run as deamon
+ if (!args_info.fg_flag)
+ {
+ closelog();
+ freopen("/dev/null", "w", stdout);
+ freopen("/dev/null", "w", stderr);
+ freopen("/dev/null", "r", stdin);
+ daemon(0, 0);
+ openlog(PACKAGE, LOG_PID, LOG_DAEMON);
+ } */
+
+ /* debug */
+ options.debug = args_info.debug_flag;
+
+ /* pidfile */
+ /* This has to be done after we have our final pid */
+ if (args_info.pidfile_arg) {
+ log_pid(args_info.pidfile_arg);
+ }
+
+ /* dns */
+ /* If no dns option is given use system default */
+ /* Do hostname lookup to translate hostname to IP address */
+ printf("\n");
+ if (args_info.dns_arg) {
+ if (!(host = gethostbyname(args_info.dns_arg))) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "Invalid DNS address: %s!", args_info.dns_arg);
+ return -1;
+ } else {
+ memcpy(&options.dns.s_addr, host->h_addr,
+ host->h_length);
+ _res.nscount = 1;
+ _res.nsaddr_list[0].sin_addr = options.dns;
+ printf("Using DNS server: %s (%s)\n",
+ args_info.dns_arg, inet_ntoa(options.dns));
+ }
+ } else {
+ options.dns.s_addr = 0;
+ printf("Using default DNS server\n");
+ }
+
+ /* listen */
+ /* If no listen option is specified listen to any local port */
+ /* Do hostname lookup to translate hostname to IP address */
+ if (args_info.listen_arg) {
+ if (!(host = gethostbyname(args_info.listen_arg))) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "Invalid listening address: %s!",
+ args_info.listen_arg);
+ return -1;
+ } else {
+ memcpy(&options.listen.s_addr, host->h_addr,
+ host->h_length);
+ printf("Local IP address is: %s (%s)\n",
+ args_info.listen_arg, inet_ntoa(options.listen));
+ }
+ } else {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "Listening address must be specified: %s!",
+ args_info.listen_arg);
+ return -1;
+ }
+
+ /* remote */
+ /* If no remote option is specified terminate */
+ /* Do hostname lookup to translate hostname to IP address */
+ if (args_info.remote_arg) {
+ if (!(host = gethostbyname(args_info.remote_arg))) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "Invalid remote address: %s!",
+ args_info.remote_arg);
+ return -1;
+ } else {
+ memcpy(&options.remote.s_addr, host->h_addr,
+ host->h_length);
+ printf("Remote IP address is: %s (%s)\n",
+ args_info.remote_arg, inet_ntoa(options.remote));
+ }
+ } else {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "No remote address given!");
+ return -1;
+ }
+
+ /* imsi */
+ if (strlen(args_info.imsi_arg) != 15) {
+ printf("Invalid IMSI\n");
+ return -1;
+ }
+
+ options.imsi = 0xf000000000000000ull;
+ options.imsi |= ((uint64_t) (args_info.imsi_arg[0] - 48));
+ options.imsi |= ((uint64_t) (args_info.imsi_arg[1] - 48)) << 4;
+ options.imsi |= ((uint64_t) (args_info.imsi_arg[2] - 48)) << 8;
+ options.imsi |= ((uint64_t) (args_info.imsi_arg[3] - 48)) << 12;
+ options.imsi |= ((uint64_t) (args_info.imsi_arg[4] - 48)) << 16;
+ options.imsi |= ((uint64_t) (args_info.imsi_arg[5] - 48)) << 20;
+ options.imsi |= ((uint64_t) (args_info.imsi_arg[6] - 48)) << 24;
+ options.imsi |= ((uint64_t) (args_info.imsi_arg[7] - 48)) << 28;
+ options.imsi |= ((uint64_t) (args_info.imsi_arg[8] - 48)) << 32;
+ options.imsi |= ((uint64_t) (args_info.imsi_arg[9] - 48)) << 36;
+ options.imsi |= ((uint64_t) (args_info.imsi_arg[10] - 48)) << 40;
+ options.imsi |= ((uint64_t) (args_info.imsi_arg[11] - 48)) << 44;
+ options.imsi |= ((uint64_t) (args_info.imsi_arg[12] - 48)) << 48;
+ options.imsi |= ((uint64_t) (args_info.imsi_arg[13] - 48)) << 52;
+ options.imsi |= ((uint64_t) (args_info.imsi_arg[14] - 48)) << 56;
+
+ printf("IMSI is: %s (%#08llx)\n",
+ args_info.imsi_arg, options.imsi);
+
+ /* nsapi */
+ if ((args_info.nsapi_arg > 15) || (args_info.nsapi_arg < 0)) {
+ printf("Invalid NSAPI\n");
+ return -1;
+ }
+ options.nsapi = args_info.nsapi_arg;
+ printf("Using NSAPI: %d\n", args_info.nsapi_arg);
+
+ /* qos */
+ 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;
-int process_options(int argc, char **argv) {
- /* gengeopt declarations */
- struct gengetopt_args_info args_info;
-
- 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 *rai_el[] = {"MCC","MNC","LAC","RAC"};
- char *mstz_el[] = {"SIGN","QUARTERS","DST"};
- int sign ;
- int nbquarters ;
- int DST ;
-
-
- if (cmdline_parser (argc, argv, &args_info) != 0)
- return -1;
- if (args_info.debug_flag) {
- if (args_info.remote_arg) printf("remote: %s\n", args_info.remote_arg);
- if (args_info.listen_arg) printf("listen: %s\n", args_info.listen_arg);
- if (args_info.conf_arg) printf("conf: %s\n", args_info.conf_arg);
- 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);
- if (args_info.uid_arg) printf("uid: %s\n", args_info.uid_arg);
- if (args_info.pwd_arg) printf("pwd: %s\n", args_info.pwd_arg);
- if (args_info.pidfile_arg) printf("pidfile: %s\n", args_info.pidfile_arg);
- if (args_info.statedir_arg) printf("statedir: %s\n", args_info.statedir_arg);
- if (args_info.dns_arg) printf("dns: %s\n", args_info.dns_arg);
- printf("contexts: %d\n", args_info.contexts_arg);
- printf("timelimit: %d\n", args_info.timelimit_arg);
- printf("createif: %d\n", args_info.createif_flag);
- if (args_info.ipup_arg) printf("ipup: %s\n", args_info.ipup_arg);
- if (args_info.ipdown_arg) printf("ipdown: %s\n", args_info.ipdown_arg);
- printf("defaultroute: %d\n", args_info.defaultroute_flag);
- if (args_info.pinghost_arg) printf("pinghost: %s\n", args_info.pinghost_arg);
- printf("pingrate: %d\n", args_info.pingrate_arg);
- printf("pingsize: %d\n", args_info.pingsize_arg);
- printf("pingcount: %d\n", args_info.pingcount_arg);
- printf("pingquiet: %d\n", args_info.pingquiet_flag);
- printf("norecovery: %d\n", args_info.norecovery_flag);
- }
-
- /* Try out our new parser */
-
- if (args_info.conf_arg) {
- if (cmdline_parser_configfile (args_info.conf_arg, &args_info, 0, 0, 0) != 0)
- return -1;
- if (args_info.debug_flag) {
- printf("cmdline_parser_configfile\n");
- if (args_info.remote_arg) printf("remote: %s\n", args_info.remote_arg);
- if (args_info.listen_arg) printf("listen: %s\n", args_info.listen_arg);
- if (args_info.conf_arg) printf("conf: %s\n", args_info.conf_arg);
- 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);
- if (args_info.uid_arg) printf("uid: %s\n", args_info.uid_arg);
- if (args_info.pwd_arg) printf("pwd: %s\n", args_info.pwd_arg);
- if (args_info.pidfile_arg) printf("pidfile: %s\n", args_info.pidfile_arg);
- if (args_info.statedir_arg) printf("statedir: %s\n", args_info.statedir_arg);
- if (args_info.dns_arg) printf("dns: %s\n", args_info.dns_arg);
- printf("contexts: %d\n", args_info.contexts_arg);
- printf("timelimit: %d\n", args_info.timelimit_arg);
- printf("createif: %d\n", args_info.createif_flag);
- if (args_info.ipup_arg) printf("ipup: %s\n", args_info.ipup_arg);
- if (args_info.ipdown_arg) printf("ipdown: %s\n", args_info.ipdown_arg);
- printf("defaultroute: %d\n", args_info.defaultroute_flag);
- if (args_info.pinghost_arg) printf("pinghost: %s\n", args_info.pinghost_arg);
- printf("pingrate: %d\n", args_info.pingrate_arg);
- printf("pingsize: %d\n", args_info.pingsize_arg);
- printf("pingcount: %d\n", args_info.pingcount_arg);
- printf("pingquiet: %d\n", args_info.pingquiet_flag);
- printf("norecovery: %d\n", args_info.norecovery_flag);
- }
- }
-
- /* Handle each option */
-
- /* foreground */
- /* If fg flag not given run as a daemon */
- /* Do not allow sgsnemu to run as deamon
- if (!args_info.fg_flag)
- {
- closelog();
- freopen("/dev/null", "w", stdout);
- freopen("/dev/null", "w", stderr);
- freopen("/dev/null", "r", stdin);
- daemon(0, 0);
- openlog(PACKAGE, LOG_PID, LOG_DAEMON);
- } */
-
- /* debug */
- options.debug = args_info.debug_flag;
-
- /* pidfile */
- /* This has to be done after we have our final pid */
- if (args_info.pidfile_arg) {
- log_pid(args_info.pidfile_arg);
- }
-
- /* dns */
- /* If no dns option is given use system default */
- /* Do hostname lookup to translate hostname to IP address */
- printf("\n");
- if (args_info.dns_arg) {
- if (!(host = gethostbyname(args_info.dns_arg))) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "Invalid DNS address: %s!", args_info.dns_arg);
- return -1;
- }
- else {
- memcpy(&options.dns.s_addr, host->h_addr, host->h_length);
- _res.nscount = 1;
- _res.nsaddr_list[0].sin_addr = options.dns;
- printf("Using DNS server: %s (%s)\n",
- args_info.dns_arg, inet_ntoa(options.dns));
- }
- }
- else {
- options.dns.s_addr= 0;
- printf("Using default DNS server\n");
- }
-
- /* listen */
- /* If no listen option is specified listen to any local port */
- /* Do hostname lookup to translate hostname to IP address */
- if (args_info.listen_arg) {
- if (!(host = gethostbyname(args_info.listen_arg))) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "Invalid listening address: %s!", args_info.listen_arg);
- return -1;
- }
- else {
- memcpy(&options.listen.s_addr, host->h_addr, host->h_length);
- printf("Local IP address is: %s (%s)\n",
- args_info.listen_arg, inet_ntoa(options.listen));
- }
- }
- else {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "Listening address must be specified: %s!", args_info.listen_arg);
- return -1;
- }
-
-
- /* remote */
- /* If no remote option is specified terminate */
- /* Do hostname lookup to translate hostname to IP address */
- if (args_info.remote_arg) {
- if (!(host = gethostbyname(args_info.remote_arg))) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "Invalid remote address: %s!", args_info.remote_arg);
- return -1;
- }
- else {
- memcpy(&options.remote.s_addr, host->h_addr, host->h_length);
- printf("Remote IP address is: %s (%s)\n",
- args_info.remote_arg, inet_ntoa(options.remote));
- }
- }
- else {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "No remote address given!");
- return -1;
- }
-
-
- /* imsi */
- if (strlen(args_info.imsi_arg)!=15) {
- printf("Invalid IMSI\n");
- return -1;
- }
-
- options.imsi = 0xf000000000000000ull;
- options.imsi |= ((uint64_t) (args_info.imsi_arg[ 0]-48));
- options.imsi |= ((uint64_t) (args_info.imsi_arg[ 1]-48)) << 4;
- options.imsi |= ((uint64_t) (args_info.imsi_arg[ 2]-48)) << 8;
- options.imsi |= ((uint64_t) (args_info.imsi_arg[ 3]-48)) << 12;
- options.imsi |= ((uint64_t) (args_info.imsi_arg[ 4]-48)) << 16;
- options.imsi |= ((uint64_t) (args_info.imsi_arg[ 5]-48)) << 20;
- options.imsi |= ((uint64_t) (args_info.imsi_arg[ 6]-48)) << 24;
- options.imsi |= ((uint64_t) (args_info.imsi_arg[ 7]-48)) << 28;
- options.imsi |= ((uint64_t) (args_info.imsi_arg[ 8]-48)) << 32;
- options.imsi |= ((uint64_t) (args_info.imsi_arg[ 9]-48)) << 36;
- options.imsi |= ((uint64_t) (args_info.imsi_arg[10]-48)) << 40;
- options.imsi |= ((uint64_t) (args_info.imsi_arg[11]-48)) << 44;
- options.imsi |= ((uint64_t) (args_info.imsi_arg[12]-48)) << 48;
- options.imsi |= ((uint64_t) (args_info.imsi_arg[13]-48)) << 52;
- options.imsi |= ((uint64_t) (args_info.imsi_arg[14]-48)) << 56;
-
- printf("IMSI is: %s (%#08llx)\n",
- args_info.imsi_arg, options.imsi);
-
-
- /* nsapi */
- if ((args_info.nsapi_arg > 15) ||
- (args_info.nsapi_arg < 0)) {
- printf("Invalid NSAPI\n");
- return -1;
- }
- options.nsapi = args_info.nsapi_arg;
- printf("Using NSAPI: %d\n", args_info.nsapi_arg);
-
-
- /* qos */
- 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;
+ /* contexts */
+ if (args_info.contexts_arg > MAXCONTEXTS) {
+ printf("Contexts has to be less than %d\n", MAXCONTEXTS);
+ return -1;
}
- }
- }
- }
-
- /* charging */
- options.cch = args_info.charging_arg;
-
- /* contexts */
- if (args_info.contexts_arg > MAXCONTEXTS) {
- printf("Contexts has to be less than %d\n", MAXCONTEXTS);
- return -1;
- }
- options.contexts = args_info.contexts_arg;
-
- /* Timelimit */
- options.timelimit = args_info.timelimit_arg;
-
- /* gtpversion */
- if ((args_info.gtpversion_arg > 1) ||
- (args_info.gtpversion_arg < 0)) {
- printf("Invalid GTP version\n");
- return -1;
- }
- options.gtpversion = args_info.gtpversion_arg;
- printf("Using GTP version: %d\n", args_info.gtpversion_arg);
-
-
- /* apn */
- if (strlen(args_info.apn_arg) > (sizeof(options.apn.v)-1)) {
- printf("Invalid APN\n");
- return -1;
- }
- options.apn.l = strlen(args_info.apn_arg);
- strncpy((char *)options.apn.v, args_info.apn_arg, sizeof(options.apn.v));
- options.apn.v[sizeof(options.apn.v)-1] = 0;
- printf("Using APN: %s\n", args_info.apn_arg);
-
-
- /* selmode */
- 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 */
- }
-
- /* RAI */
- if (args_info.rai_given == 1 ) {
- printf("Using RAI: %s\n", args_info.rai_arg);
- tmp = args_info.rai_arg ;
- n=0;
- pch = strtok (tmp,".");
- while (pch != NULL) {
- rai_el[n] = pch ;
- pch = strtok (NULL, ".");
- n++;
- }
-
- options.rai_given = 1 ;
- options.rai.l = 6 ;
-
-
- /* MCC */
- mcc = rai_el[0] ;
- printf("->mcc : %s\n", mcc);
- if (strlen(mcc)!=3) {
- printf("Invalid MCC lenght\n");
- return -1;
- }
-
- /* MNC */
- mnc = rai_el[1] ;
- printf("->mnc : %s\n", mnc);
-
- a = (uint8_t) (mcc[0] - 48);
- b = (uint8_t) (mcc[1] - 48);
- options.rai.v[0] = 16*b+a ;
-
- /* octet 3 - MNC Digit 3 - MCC Digit 3 */
- 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.rai.v[1] = 16*b+a ;
-
- /* octet 4 - MNC Digit 2 - MNC Digit 1 */
- a = (uint8_t) (mnc[0]- 48);
- b = (uint8_t) (mnc[1]- 48);
- options.rai.v[2] = 16*b+a ;
-
- /* LAC */
- lac = rai_el[2] ;
- 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.rai.v[3] = i; /* octet 5 - LAC */
- options.rai.v[4] = lac_d; /* octet 6 - LAC */
-
- /* RAC */
- rest = rai_el[3] ;
- printf("->RAC : %s\n", rest);
- lac_d = atoi(rest);
- if (lac_d>255 || lac_d<1) {
- printf("Invalid RAC\n");
- return -1;
- }
- options.rai.v[5] = lac_d; /* octet 7 - 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)) {
- printf("Invalid MSISDN\n");
- return -1;
- }
- options.msisdn.l = 1;
- options.msisdn.v[0] = 0x91; /* International format */
- for(n=0; n<strlen(args_info.msisdn_arg); n++) {
- if ((n%2) == 0) {
- options.msisdn.v[((int)n/2)+1] = args_info.msisdn_arg[n] - 48 + 0xf0;
- options.msisdn.l += 1;
- }
- else {
- options.msisdn.v[((int)n/2)+1] =
- (options.msisdn.v[((int)n/2)+1] & 0x0f) +
- (args_info.msisdn_arg[n] - 48) * 16;
- }
- }
- printf("Using MSISDN: %s\n", args_info.msisdn_arg);
-
- /* UID and PWD */
- /* Might need to also insert stuff like DNS etc. */
- if ((strlen(args_info.uid_arg) + strlen(args_info.pwd_arg) + 10)>
- (sizeof(options.pco.v)-1)) {
- printf("invalid UID and PWD\n");
- return -1;
- }
- options.pco.l = strlen(args_info.uid_arg) + strlen(args_info.pwd_arg) + 10;
- options.pco.v[0] = 0x80; /* PPP */
- options.pco.v[1] = 0xc0; /* PAP */
- options.pco.v[2] = 0x23;
- options.pco.v[3] = strlen(args_info.uid_arg) + strlen(args_info.pwd_arg) + 6;
- options.pco.v[4] = 0x01; /* Authenticate request */
- options.pco.v[5] = 0x01;
- options.pco.v[6] = 0x00; /* MSB of length */
- options.pco.v[7] = strlen(args_info.uid_arg) + strlen(args_info.pwd_arg) + 6;
- options.pco.v[8] = strlen(args_info.uid_arg);
- memcpy(&options.pco.v[9], args_info.uid_arg, strlen(args_info.uid_arg));
- options.pco.v[9+strlen(args_info.uid_arg)] = strlen(args_info.pwd_arg);
- memcpy(&options.pco.v[10+strlen(args_info.uid_arg)],
- args_info.pwd_arg, strlen(args_info.pwd_arg));
-
- /* createif */
- options.createif = args_info.createif_flag;
-
- /* net */
- /* Store net as in_addr net and mask */
- if (args_info.net_arg) {
- if(ippool_aton(&options.net, &options.mask, args_info.net_arg, 0)) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "Invalid network address: %s!", args_info.net_arg);
- exit(1);
- }
+ options.contexts = args_info.contexts_arg;
+ /* Timelimit */
+ options.timelimit = args_info.timelimit_arg;
+
+ /* gtpversion */
+ if ((args_info.gtpversion_arg > 1) || (args_info.gtpversion_arg < 0)) {
+ printf("Invalid GTP version\n");
+ return -1;
+ }
+ options.gtpversion = args_info.gtpversion_arg;
+ printf("Using GTP version: %d\n", args_info.gtpversion_arg);
+
+ /* apn */
+ if (strlen(args_info.apn_arg) > (sizeof(options.apn.v) - 1)) {
+ printf("Invalid APN\n");
+ return -1;
+ }
+ options.apn.l = strlen(args_info.apn_arg);
+ strncpy((char *)options.apn.v, args_info.apn_arg,
+ sizeof(options.apn.v));
+ options.apn.v[sizeof(options.apn.v) - 1] = 0;
+ printf("Using APN: %s\n", args_info.apn_arg);
+
+ /* selmode */
+ 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 */
+ }
+
+ /* RAI */
+ if (args_info.rai_given == 1) {
+ printf("Using RAI: %s\n", args_info.rai_arg);
+ tmp = args_info.rai_arg;
+ n = 0;
+ pch = strtok(tmp, ".");
+ while (pch != NULL) {
+ rai_el[n] = pch;
+ pch = strtok(NULL, ".");
+ n++;
+ }
+
+ options.rai_given = 1;
+ options.rai.l = 6;
+
+ /* MCC */
+ mcc = rai_el[0];
+ printf("->mcc : %s\n", mcc);
+ if (strlen(mcc) != 3) {
+ printf("Invalid MCC lenght\n");
+ return -1;
+ }
+
+ /* MNC */
+ mnc = rai_el[1];
+ printf("->mnc : %s\n", mnc);
+
+ a = (uint8_t) (mcc[0] - 48);
+ b = (uint8_t) (mcc[1] - 48);
+ options.rai.v[0] = 16 * b + a;
+
+ /* octet 3 - MNC Digit 3 - MCC Digit 3 */
+ 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.rai.v[1] = 16 * b + a;
+
+ /* octet 4 - MNC Digit 2 - MNC Digit 1 */
+ a = (uint8_t) (mnc[0] - 48);
+ b = (uint8_t) (mnc[1] - 48);
+ options.rai.v[2] = 16 * b + a;
+
+ /* LAC */
+ lac = rai_el[2];
+ 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.rai.v[3] = i; /* octet 5 - LAC */
+ options.rai.v[4] = lac_d; /* octet 6 - LAC */
+
+ /* RAC */
+ rest = rai_el[3];
+ printf("->RAC : %s\n", rest);
+ lac_d = atoi(rest);
+ if (lac_d > 255 || lac_d < 1) {
+ printf("Invalid RAC\n");
+ return -1;
+ }
+ options.rai.v[5] = lac_d; /* octet 7 - 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)) {
+ printf("Invalid MSISDN\n");
+ return -1;
+ }
+ options.msisdn.l = 1;
+ options.msisdn.v[0] = 0x91; /* International format */
+ for (n = 0; n < strlen(args_info.msisdn_arg); n++) {
+ if ((n % 2) == 0) {
+ options.msisdn.v[((int)n / 2) + 1] =
+ args_info.msisdn_arg[n] - 48 + 0xf0;
+ options.msisdn.l += 1;
+ } else {
+ options.msisdn.v[((int)n / 2) + 1] =
+ (options.msisdn.v[((int)n / 2) + 1] & 0x0f) +
+ (args_info.msisdn_arg[n] - 48) * 16;
+ }
+ }
+ printf("Using MSISDN: %s\n", args_info.msisdn_arg);
+
+ /* UID and PWD */
+ /* Might need to also insert stuff like DNS etc. */
+ if ((strlen(args_info.uid_arg) + strlen(args_info.pwd_arg) + 10) >
+ (sizeof(options.pco.v) - 1)) {
+ printf("invalid UID and PWD\n");
+ return -1;
+ }
+ options.pco.l =
+ strlen(args_info.uid_arg) + strlen(args_info.pwd_arg) + 10;
+ options.pco.v[0] = 0x80; /* PPP */
+ options.pco.v[1] = 0xc0; /* PAP */
+ options.pco.v[2] = 0x23;
+ options.pco.v[3] =
+ strlen(args_info.uid_arg) + strlen(args_info.pwd_arg) + 6;
+ options.pco.v[4] = 0x01; /* Authenticate request */
+ options.pco.v[5] = 0x01;
+ options.pco.v[6] = 0x00; /* MSB of length */
+ options.pco.v[7] =
+ strlen(args_info.uid_arg) + strlen(args_info.pwd_arg) + 6;
+ options.pco.v[8] = strlen(args_info.uid_arg);
+ memcpy(&options.pco.v[9], args_info.uid_arg, strlen(args_info.uid_arg));
+ options.pco.v[9 + strlen(args_info.uid_arg)] =
+ strlen(args_info.pwd_arg);
+ memcpy(&options.pco.v[10 + strlen(args_info.uid_arg)],
+ args_info.pwd_arg, strlen(args_info.pwd_arg));
+
+ /* createif */
+ options.createif = args_info.createif_flag;
+
+ /* net */
+ /* Store net as in_addr net and mask */
+ if (args_info.net_arg) {
+ if (ippool_aton
+ (&options.net, &options.mask, args_info.net_arg, 0)) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "Invalid network address: %s!",
+ args_info.net_arg);
+ exit(1);
+ }
#if defined (__sun__)
- options.netaddr.s_addr = htonl(ntohl(options.net.s_addr) + 1);
- options.destaddr.s_addr = htonl(ntohl(options.net.s_addr) + 1);
+ options.netaddr.s_addr = htonl(ntohl(options.net.s_addr) + 1);
+ options.destaddr.s_addr = htonl(ntohl(options.net.s_addr) + 1);
#else
- options.netaddr.s_addr = options.net.s_addr;
- options.destaddr.s_addr = options.net.s_addr;
+ options.netaddr.s_addr = options.net.s_addr;
+ options.destaddr.s_addr = options.net.s_addr;
#endif
- }
- else {
- options.net.s_addr = 0;
- options.mask.s_addr = 0;
- options.netaddr.s_addr = 0;
- options.destaddr.s_addr = 0;
- }
-
- /* ipup */
- options.ipup = args_info.ipup_arg;
-
- /* ipdown */
- options.ipdown = args_info.ipdown_arg;
-
- /* statedir */
- options.statedir = args_info.statedir_arg;
-
- /* defaultroute */
- options.defaultroute = args_info.defaultroute_flag;
-
-
- /* pinghost */
- /* Store ping host as in_addr */
- if (args_info.pinghost_arg) {
- if (!(host = gethostbyname(args_info.pinghost_arg))) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "Invalid ping host: %s!", args_info.pinghost_arg);
- return -1;
- }
- else {
- memcpy(&options.pinghost.s_addr, host->h_addr, host->h_length);
- printf("Using ping host: %s (%s)\n",
- args_info.pinghost_arg, inet_ntoa(options.pinghost));
- }
- }
-
- /* Other ping parameters */
- options.pingrate = args_info.pingrate_arg;
- options.pingsize = args_info.pingsize_arg;
- options.pingcount = args_info.pingcount_arg;
- options.pingquiet = args_info.pingquiet_flag;
-
- /* norecovery */
- options.norecovery_given = args_info.norecovery_flag;
-
- return 0;
+ } else {
+ options.net.s_addr = 0;
+ options.mask.s_addr = 0;
+ options.netaddr.s_addr = 0;
+ options.destaddr.s_addr = 0;
+ }
-}
+ /* ipup */
+ options.ipup = args_info.ipup_arg;
+
+ /* ipdown */
+ options.ipdown = args_info.ipdown_arg;
+
+ /* statedir */
+ options.statedir = args_info.statedir_arg;
+
+ /* defaultroute */
+ options.defaultroute = args_info.defaultroute_flag;
+
+ /* pinghost */
+ /* Store ping host as in_addr */
+ if (args_info.pinghost_arg) {
+ if (!(host = gethostbyname(args_info.pinghost_arg))) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "Invalid ping host: %s!",
+ args_info.pinghost_arg);
+ return -1;
+ } else {
+ memcpy(&options.pinghost.s_addr, host->h_addr,
+ host->h_length);
+ printf("Using ping host: %s (%s)\n",
+ args_info.pinghost_arg,
+ inet_ntoa(options.pinghost));
+ }
+ }
+ /* Other ping parameters */
+ options.pingrate = args_info.pingrate_arg;
+ options.pingsize = args_info.pingsize_arg;
+ options.pingcount = args_info.pingcount_arg;
+ options.pingquiet = args_info.pingquiet_flag;
+
+ /* norecovery */
+ options.norecovery_given = args_info.norecovery_flag;
+
+ return 0;
-int encaps_printf(struct pdp_t *pdp, void *pack, unsigned len) {
- unsigned int i;
- printf("The packet looks like this:\n");
- for( i=0; i<len; i++) {
- printf("%02x ", (unsigned char)*(char *)(pack+i));
- if (!((i+1)%16)) printf("\n");
- };
- printf("\n");
- return 0;
}
-char * print_ipprot(int t) {
- switch (t) {
- case 1: return "ICMP";
- case 6: return "TCP";
- case 17: return "UDP";
- default: return "Unknown";
- };
+int encaps_printf(struct pdp_t *pdp, void *pack, unsigned len)
+{
+ unsigned int i;
+ printf("The packet looks like this:\n");
+ for (i = 0; i < len; i++) {
+ printf("%02x ", (unsigned char)*(char *)(pack + i));
+ if (!((i + 1) % 16))
+ printf("\n");
+ };
+ printf("\n");
+ return 0;
}
+char *print_ipprot(int t)
+{
+ switch (t) {
+ case 1:
+ return "ICMP";
+ case 6:
+ return "TCP";
+ case 17:
+ return "UDP";
+ default:
+ return "Unknown";
+ };
+}
-char * print_icmptype(int t) {
- static char *ttab[] = {
- "Echo Reply",
- "ICMP 1",
- "ICMP 2",
- "Dest Unreachable",
- "Source Quench",
- "Redirect",
- "ICMP 6",
- "ICMP 7",
- "Echo",
- "ICMP 9",
- "ICMP 10",
- "Time Exceeded",
- "Parameter Problem",
- "Timestamp",
- "Timestamp Reply",
- "Info Request",
- "Info Reply"
- };
- if( t < 0 || t > 16 )
- return("OUT-OF-RANGE");
- return(ttab[t]);
+char *print_icmptype(int t)
+{
+ static char *ttab[] = {
+ "Echo Reply",
+ "ICMP 1",
+ "ICMP 2",
+ "Dest Unreachable",
+ "Source Quench",
+ "Redirect",
+ "ICMP 6",
+ "ICMP 7",
+ "Echo",
+ "ICMP 9",
+ "ICMP 10",
+ "Time Exceeded",
+ "Parameter Problem",
+ "Timestamp",
+ "Timestamp Reply",
+ "Info Request",
+ "Info Reply"
+ };
+ if (t < 0 || t > 16)
+ return ("OUT-OF-RANGE");
+ return (ttab[t]);
}
-int msisdn_add(struct ul16_t *src, struct ul16_t *dst, int add) {
- unsigned int n;
- uint64_t i64 = 0;
- uint8_t msa[sizeof(i64) * 3]; /* Allocate 3 digits per octet (0..255) */
- unsigned int msalen = 0;
-
- /* Convert to uint64_t from ul16_t format (most significant digit first) */
- /* ul16_t format always starts with 0x91 to indicate international format */
- /* In ul16_t format 0x0f/0xf0 indicates that digit is not used */
- for (n=0; n< src->l; n++) {
- if ((src->v[n] & 0x0f) != 0x0f) {
- i64 *= 10;
- i64 += src->v[n] & 0x0f;
- }
- if ((src->v[n] & 0xf0) != 0xf0) {
- i64 *= 10;
- i64 += (src->v[n] & 0xf0) >> 4;
- }
- }
-
- i64 += add;
-
- /* Generate array with least significant digit in first octet */
- while (i64) {
- msa[msalen++] = i64 % 10;
- i64 = i64 / 10;
- }
-
- /* Convert back to ul16_t format */
- for(n=0; n<msalen; n++) {
- if ((n%2) == 0) {
- dst->v[((int)n/2)] = msa[msalen-n-1] + 0xf0;
- dst->l += 1;
- }
- else {
- dst->v[((int)n/2)] = (dst->v[((int)n/2)] & 0x0f) +
- msa[msalen-n-1] * 16;
- }
- }
-
- return 0;
+int msisdn_add(struct ul16_t *src, struct ul16_t *dst, int add)
+{
+ unsigned int n;
+ uint64_t i64 = 0;
+ uint8_t msa[sizeof(i64) * 3]; /* Allocate 3 digits per octet (0..255) */
+ unsigned int msalen = 0;
+
+ /* Convert to uint64_t from ul16_t format (most significant digit first) */
+ /* ul16_t format always starts with 0x91 to indicate international format */
+ /* In ul16_t format 0x0f/0xf0 indicates that digit is not used */
+ for (n = 0; n < src->l; n++) {
+ if ((src->v[n] & 0x0f) != 0x0f) {
+ i64 *= 10;
+ i64 += src->v[n] & 0x0f;
+ }
+ if ((src->v[n] & 0xf0) != 0xf0) {
+ i64 *= 10;
+ i64 += (src->v[n] & 0xf0) >> 4;
+ }
+ }
+
+ i64 += add;
+
+ /* Generate array with least significant digit in first octet */
+ while (i64) {
+ msa[msalen++] = i64 % 10;
+ i64 = i64 / 10;
+ }
+
+ /* Convert back to ul16_t format */
+ for (n = 0; n < msalen; n++) {
+ if ((n % 2) == 0) {
+ dst->v[((int)n / 2)] = msa[msalen - n - 1] + 0xf0;
+ dst->l += 1;
+ } else {
+ dst->v[((int)n / 2)] = (dst->v[((int)n / 2)] & 0x0f) +
+ msa[msalen - n - 1] * 16;
+ }
+ }
+
+ return 0;
}
-int imsi_add(uint64_t src, uint64_t *dst, int add) {
- /* TODO: big endian / small endian ??? */
- uint64_t i64 = 0;
-
- /* Convert from uint64_t bcd to uint64_t integer format */
- /* The resulting integer format is multiplied by 10 */
- while (src) {
- if ((src & 0x0f) != 0x0f) {
- i64 *= 10;
- i64 += (src & 0x0f);
- }
- if ((src & 0xf0) != 0xf0) {
- i64 *= 10;
- i64 += (src & 0xf0) >> 4;
- }
- src = src >> 8;
- }
-
- i64 += add * 10;
-
- *dst = 0;
- while (i64) {
- *dst = *dst << 4;
- *dst += (i64 % 10);
- i64 = i64 / 10;
- }
-
- *dst |= 0xf000000000000000ull;
-
- return 0;
+int imsi_add(uint64_t src, uint64_t * dst, int add)
+{
+ /* TODO: big endian / small endian ??? */
+ uint64_t i64 = 0;
+
+ /* Convert from uint64_t bcd to uint64_t integer format */
+ /* The resulting integer format is multiplied by 10 */
+ while (src) {
+ if ((src & 0x0f) != 0x0f) {
+ i64 *= 10;
+ i64 += (src & 0x0f);
+ }
+ if ((src & 0xf0) != 0xf0) {
+ i64 *= 10;
+ i64 += (src & 0xf0) >> 4;
+ }
+ src = src >> 8;
+ }
+
+ i64 += add * 10;
+
+ *dst = 0;
+ while (i64) {
+ *dst = *dst << 4;
+ *dst += (i64 % 10);
+ i64 = i64 / 10;
+ }
+
+ *dst |= 0xf000000000000000ull;
+
+ return 0;
}
/* Calculate time left until we have to send off next ping packet */
-int ping_timeout(struct timeval *tp) {
- struct timezone tz;
- struct timeval tv;
- int diff;
- if ((options.pinghost.s_addr) && (2 == state) &&
- ((pingseq < options.pingcount) || (options.pingcount == 0))) {
- gettimeofday(&tv, &tz);
- diff = 1000000 / options.pingrate * pingseq -
- 1000000 * (tv.tv_sec - firstping.tv_sec) -
- (tv.tv_usec - firstping.tv_usec); /* Microseconds safe up to 500 sec */
- tp->tv_sec = 0;
- if (diff > 0)
- tp->tv_usec = diff;
- else {
- /* For some reason we get packet loss if set to zero */
- tp->tv_usec = 100000 / options.pingrate; /* 10 times pingrate */
- tp->tv_usec = 0;
- }
- }
- return 0;
+int ping_timeout(struct timeval *tp)
+{
+ struct timezone tz;
+ struct timeval tv;
+ int diff;
+ if ((options.pinghost.s_addr) && (2 == state) &&
+ ((pingseq < options.pingcount) || (options.pingcount == 0))) {
+ gettimeofday(&tv, &tz);
+ diff = 1000000 / options.pingrate * pingseq - 1000000 * (tv.tv_sec - firstping.tv_sec) - (tv.tv_usec - firstping.tv_usec); /* Microseconds safe up to 500 sec */
+ tp->tv_sec = 0;
+ if (diff > 0)
+ tp->tv_usec = diff;
+ else {
+ /* For some reason we get packet loss if set to zero */
+ tp->tv_usec = 100000 / options.pingrate; /* 10 times pingrate */
+ tp->tv_usec = 0;
+ }
+ }
+ return 0;
}
/* Print out statistics when at the end of ping sequence */
int ping_finish()
{
- struct timezone tz;
- struct timeval tv;
- int elapsed;
- gettimeofday(&tv, &tz);
- elapsed = 1000000 * (tv.tv_sec - firstping.tv_sec) +
- (tv.tv_usec - firstping.tv_usec); /* Microseconds */
- printf("\n");
- printf("\n----%s PING Statistics----\n", inet_ntoa(options.pinghost));
- printf("%d packets transmitted in %.3f seconds, ", ntransmitted,
- elapsed / 1000000.0);
- printf("%d packets received, ", nreceived );
- if (ntransmitted) {
- if( nreceived > ntransmitted)
- printf("-- somebody's printing up packets!");
- else
- printf("%d%% packet loss",
- (int) (((ntransmitted-nreceived)*100) /
- ntransmitted));
- }
- printf("\n");
- if (options.debug) printf("%d packets received in total\n", ntreceived );
- if (nreceived && tsum)
- printf("round-trip (ms) min/avg/max = %.3f/%.3f/%.3f\n\n",
- tmin/1000.0,
- tsum/1000.0/nreceived,
- tmax/1000.0 );
- printf("%d packets transmitted \n", ntreceived );
-
- ntransmitted = 0;
- return 0;
+ struct timezone tz;
+ struct timeval tv;
+ int elapsed;
+ gettimeofday(&tv, &tz);
+ elapsed = 1000000 * (tv.tv_sec - firstping.tv_sec) + (tv.tv_usec - firstping.tv_usec); /* Microseconds */
+ printf("\n");
+ printf("\n----%s PING Statistics----\n", inet_ntoa(options.pinghost));
+ printf("%d packets transmitted in %.3f seconds, ", ntransmitted,
+ elapsed / 1000000.0);
+ printf("%d packets received, ", nreceived);
+ if (ntransmitted) {
+ if (nreceived > ntransmitted)
+ printf("-- somebody's printing up packets!");
+ else
+ printf("%d%% packet loss",
+ (int)(((ntransmitted - nreceived) * 100) /
+ ntransmitted));
+ }
+ printf("\n");
+ if (options.debug)
+ printf("%d packets received in total\n", ntreceived);
+ if (nreceived && tsum)
+ printf("round-trip (ms) min/avg/max = %.3f/%.3f/%.3f\n\n",
+ tmin / 1000.0, tsum / 1000.0 / nreceived, tmax / 1000.0);
+ printf("%d packets transmitted \n", ntreceived);
+
+ ntransmitted = 0;
+ return 0;
}
/* Handle a received ping packet. Print out line and update statistics. */
-int encaps_ping(struct pdp_t *pdp, void *pack, unsigned len) {
- struct timezone tz;
- struct timeval tv;
- struct timeval *tp;
- struct ip_ping *pingpack = pack;
- struct in_addr src;
- int triptime;
-
- src.s_addr = pingpack->src;
-
- gettimeofday(&tv, &tz);
- if (options.debug) printf("%d.%6d ", (int) tv.tv_sec, (int) tv.tv_usec);
-
- if (len < CREATEPING_IP + CREATEPING_ICMP) {
- printf("packet too short (%d bytes) from %s\n", len,
- inet_ntoa(src));
- return 0;
- }
-
- ntreceived++;
- if (pingpack->protocol != 1) {
- if (!options.pingquiet) printf("%d bytes from %s: ip_protocol=%d (%s)\n",
- len, inet_ntoa(src), pingpack->protocol,
- print_ipprot(pingpack->protocol));
- return 0;
- }
-
- if (pingpack->type != 0) {
- if (!options.pingquiet) printf("%d bytes from %s: icmp_type=%d (%s) icmp_code=%d\n",
- len, inet_ntoa(src), pingpack->type,
- print_icmptype(pingpack->type), pingpack->code);
- return 0;
- }
-
- nreceived++;
- if (!options.pingquiet) printf("%d bytes from %s: icmp_seq=%d", len,
- inet_ntoa(src), ntohs(pingpack->seq));
-
- if (len >= sizeof(struct timeval) + CREATEPING_IP + CREATEPING_ICMP) {
- gettimeofday(&tv, &tz);
- tp = (struct timeval *) pingpack->data;
- if( (tv.tv_usec -= tp->tv_usec) < 0 ) {
- tv.tv_sec--;
- tv.tv_usec += 1000000;
- }
- tv.tv_sec -= tp->tv_sec;
-
- triptime = tv.tv_sec*1000000+(tv.tv_usec);
- tsum += triptime;
- if( triptime < tmin )
- tmin = triptime;
- if( triptime > tmax )
- tmax = triptime;
-
- if (!options.pingquiet) printf(" time=%.3f ms\n", triptime/1000.0);
-
- }
- else
- if (!options.pingquiet) printf("\n");
- return 0;
+int encaps_ping(struct pdp_t *pdp, void *pack, unsigned len)
+{
+ struct timezone tz;
+ struct timeval tv;
+ struct timeval *tp;
+ struct ip_ping *pingpack = pack;
+ struct in_addr src;
+ int triptime;
+
+ src.s_addr = pingpack->src;
+
+ gettimeofday(&tv, &tz);
+ if (options.debug)
+ printf("%d.%6d ", (int)tv.tv_sec, (int)tv.tv_usec);
+
+ if (len < CREATEPING_IP + CREATEPING_ICMP) {
+ printf("packet too short (%d bytes) from %s\n", len,
+ inet_ntoa(src));
+ return 0;
+ }
+
+ ntreceived++;
+ if (pingpack->protocol != 1) {
+ if (!options.pingquiet)
+ printf("%d bytes from %s: ip_protocol=%d (%s)\n",
+ len, inet_ntoa(src), pingpack->protocol,
+ print_ipprot(pingpack->protocol));
+ return 0;
+ }
+
+ if (pingpack->type != 0) {
+ if (!options.pingquiet)
+ printf
+ ("%d bytes from %s: icmp_type=%d (%s) icmp_code=%d\n",
+ len, inet_ntoa(src), pingpack->type,
+ print_icmptype(pingpack->type), pingpack->code);
+ return 0;
+ }
+
+ nreceived++;
+ if (!options.pingquiet)
+ printf("%d bytes from %s: icmp_seq=%d", len,
+ inet_ntoa(src), ntohs(pingpack->seq));
+
+ if (len >= sizeof(struct timeval) + CREATEPING_IP + CREATEPING_ICMP) {
+ gettimeofday(&tv, &tz);
+ tp = (struct timeval *)pingpack->data;
+ if ((tv.tv_usec -= tp->tv_usec) < 0) {
+ tv.tv_sec--;
+ tv.tv_usec += 1000000;
+ }
+ tv.tv_sec -= tp->tv_sec;
+
+ triptime = tv.tv_sec * 1000000 + (tv.tv_usec);
+ tsum += triptime;
+ if (triptime < tmin)
+ tmin = triptime;
+ if (triptime > tmax)
+ tmax = triptime;
+
+ if (!options.pingquiet)
+ printf(" time=%.3f ms\n", triptime / 1000.0);
+
+ } else if (!options.pingquiet)
+ printf("\n");
+ return 0;
}
/* Create a new ping packet and send it off to peer. */
int create_ping(void *gsn, struct pdp_t *pdp,
- struct in_addr *dst, int seq, unsigned int datasize) {
-
- struct ip_ping pack;
- uint16_t *p = (uint16_t *) &pack;
- uint8_t *p8 = (uint8_t *) &pack;
- struct in_addr src;
- unsigned int n;
- long int sum = 0;
- int count = 0;
-
- struct timezone tz;
- struct timeval *tp = (struct timeval *) &p8[CREATEPING_IP + CREATEPING_ICMP];
-
- if (datasize > CREATEPING_MAX) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "Ping size to large: %d!", datasize);
- return -1;
- }
-
- memcpy(&src, &(pdp->eua.v[2]), 4); /* Copy a 4 byte address */
-
- pack.ipver = 0x45;
- pack.tos = 0x00;
- pack.length = htons(CREATEPING_IP + CREATEPING_ICMP + datasize);
- pack.fragid = 0x0000;
- pack.offset = 0x0040;
- pack.ttl = 0x40;
- pack.protocol = 0x01;
- pack.ipcheck = 0x0000;
- pack.src = src.s_addr;
- pack.dst = dst->s_addr;
- pack.type = 0x08;
- pack.code = 0x00;
- pack.checksum = 0x0000;
- pack.ident = 0x0000;
- pack.seq = htons(seq);
-
- /* Generate ICMP payload */
- p8 = (uint8_t *) &pack + CREATEPING_IP + CREATEPING_ICMP;
- for (n=0; n<(datasize); n++) p8[n] = n;
-
- if (datasize >= sizeof(struct timeval))
- gettimeofday(tp, &tz);
-
- /* Calculate IP header checksum */
- p = (uint16_t *) &pack;
- count = CREATEPING_IP;
- sum = 0;
- while (count>1) {
- sum += *p++;
- count -= 2;
- }
- while (sum>>16)
- sum = (sum & 0xffff) + (sum >> 16);
- pack.ipcheck = ~sum;
-
-
- /* Calculate ICMP checksum */
- count = CREATEPING_ICMP + datasize; /* Length of ICMP message */
- sum = 0;
- p = (uint16_t *) &pack;
- p += CREATEPING_IP / 2;
- while (count>1) {
- sum += *p++;
- count -= 2;
- }
- if (count>0)
- sum += * (unsigned char *) p;
- while (sum>>16)
- sum = (sum & 0xffff) + (sum >> 16);
- pack.checksum = ~sum;
-
- ntransmitted++;
- return gtp_data_req(gsn, pdp, &pack, 28 + datasize);
+ struct in_addr *dst, int seq, unsigned int datasize)
+{
+
+ struct ip_ping pack;
+ uint16_t *p = (uint16_t *) & pack;
+ uint8_t *p8 = (uint8_t *) & pack;
+ struct in_addr src;
+ unsigned int n;
+ long int sum = 0;
+ int count = 0;
+
+ struct timezone tz;
+ struct timeval *tp =
+ (struct timeval *)&p8[CREATEPING_IP + CREATEPING_ICMP];
+
+ if (datasize > CREATEPING_MAX) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "Ping size to large: %d!", datasize);
+ return -1;
+ }
+
+ memcpy(&src, &(pdp->eua.v[2]), 4); /* Copy a 4 byte address */
+
+ pack.ipver = 0x45;
+ pack.tos = 0x00;
+ pack.length = htons(CREATEPING_IP + CREATEPING_ICMP + datasize);
+ pack.fragid = 0x0000;
+ pack.offset = 0x0040;
+ pack.ttl = 0x40;
+ pack.protocol = 0x01;
+ pack.ipcheck = 0x0000;
+ pack.src = src.s_addr;
+ pack.dst = dst->s_addr;
+ pack.type = 0x08;
+ pack.code = 0x00;
+ pack.checksum = 0x0000;
+ pack.ident = 0x0000;
+ pack.seq = htons(seq);
+
+ /* Generate ICMP payload */
+ p8 = (uint8_t *) & pack + CREATEPING_IP + CREATEPING_ICMP;
+ for (n = 0; n < (datasize); n++)
+ p8[n] = n;
+
+ if (datasize >= sizeof(struct timeval))
+ gettimeofday(tp, &tz);
+
+ /* Calculate IP header checksum */
+ p = (uint16_t *) & pack;
+ count = CREATEPING_IP;
+ sum = 0;
+ while (count > 1) {
+ sum += *p++;
+ count -= 2;
+ }
+ while (sum >> 16)
+ sum = (sum & 0xffff) + (sum >> 16);
+ pack.ipcheck = ~sum;
+
+ /* Calculate ICMP checksum */
+ count = CREATEPING_ICMP + datasize; /* Length of ICMP message */
+ sum = 0;
+ p = (uint16_t *) & pack;
+ p += CREATEPING_IP / 2;
+ while (count > 1) {
+ sum += *p++;
+ count -= 2;
+ }
+ if (count > 0)
+ sum += *(unsigned char *)p;
+ while (sum >> 16)
+ sum = (sum & 0xffff) + (sum >> 16);
+ pack.checksum = ~sum;
+
+ ntransmitted++;
+ return gtp_data_req(gsn, pdp, &pack, 28 + datasize);
}
-
-int delete_context(struct pdp_t *pdp) {
+int delete_context(struct pdp_t *pdp)
+{
- if (tun && options.ipdown) tun_runscript(tun, options.ipdown);
+ if (tun && options.ipdown)
+ tun_runscript(tun, options.ipdown);
- ipdel((struct iphash_t*) pdp->peer);
- memset(pdp->peer, 0, sizeof(struct iphash_t)); /* To be sure */
+ ipdel((struct iphash_t *)pdp->peer);
+ memset(pdp->peer, 0, sizeof(struct iphash_t)); /* To be sure */
- if (1 == options.contexts)
- state = 5; /* Disconnected */
+ if (1 == options.contexts)
+ state = 5; /* Disconnected */
- return 0;
+ return 0;
}
-
/* Callback for receiving messages from tun */
-int cb_tun_ind(struct tun_t *tun, void *pack, unsigned len) {
- struct iphash_t *ipm;
- struct in_addr src;
- struct tun_packet_t *iph = (struct tun_packet_t*) pack;
-
- src.s_addr = iph->src;
-
- if (ipget(&ipm, &src)) {
- printf("Received packet without a valid source address!!!\n");
- return 0;
- }
-
- if (ipm->pdp) /* Check if a peer protocol is defined */
- gtp_data_req(gsn, ipm->pdp, pack, len);
- return 0;
+int cb_tun_ind(struct tun_t *tun, void *pack, unsigned len)
+{
+ struct iphash_t *ipm;
+ struct in_addr src;
+ struct tun_packet_t *iph = (struct tun_packet_t *)pack;
+
+ src.s_addr = iph->src;
+
+ if (ipget(&ipm, &src)) {
+ printf("Received packet without a valid source address!!!\n");
+ return 0;
+ }
+
+ if (ipm->pdp) /* Check if a peer protocol is defined */
+ gtp_data_req(gsn, ipm->pdp, pack, len);
+ return 0;
}
-int create_pdp_conf(struct pdp_t *pdp, void *cbp, int cause) {
- struct in_addr addr;
-
- struct iphash_t *iph = (struct iphash_t*) cbp;
-
- if (cause < 0) {
- printf("Create PDP Context Request timed out\n");
- if (iph->pdp->version == 1) {
- printf("Retrying with version 0\n");
- iph->pdp->version = 0;
- gtp_create_context_req(gsn, iph->pdp, iph);
- return 0;
- }
- else {
- state = 0;
- pdp_freepdp(iph->pdp);
- iph->pdp = NULL;
- return EOF;
- }
- }
-
- if (cause != 128) {
- printf("Received create PDP context response. Cause value: %d\n", cause);
- state = 0;
- pdp_freepdp(iph->pdp);
- iph->pdp = NULL;
- return EOF; /* Not what we expected */
- }
-
- if (pdp_euaton(&pdp->eua, &addr)) {
- printf("Received create PDP context response. Cause value: %d\n", cause);
- pdp_freepdp(iph->pdp);
- iph->pdp = NULL;
- state = 0;
- return EOF; /* Not a valid IP address */
- }
-
- printf("Received create PDP context response. IP address: %s\n",
- inet_ntoa(addr));
-
- if ((options.createif) && (!options.net.s_addr)) {
- struct in_addr m;
+int create_pdp_conf(struct pdp_t *pdp, void *cbp, int cause)
+{
+ struct in_addr addr;
+
+ struct iphash_t *iph = (struct iphash_t *)cbp;
+
+ if (cause < 0) {
+ printf("Create PDP Context Request timed out\n");
+ if (iph->pdp->version == 1) {
+ printf("Retrying with version 0\n");
+ iph->pdp->version = 0;
+ gtp_create_context_req(gsn, iph->pdp, iph);
+ return 0;
+ } else {
+ state = 0;
+ pdp_freepdp(iph->pdp);
+ iph->pdp = NULL;
+ return EOF;
+ }
+ }
+
+ if (cause != 128) {
+ printf
+ ("Received create PDP context response. Cause value: %d\n",
+ cause);
+ state = 0;
+ pdp_freepdp(iph->pdp);
+ iph->pdp = NULL;
+ return EOF; /* Not what we expected */
+ }
+
+ if (pdp_euaton(&pdp->eua, &addr)) {
+ printf
+ ("Received create PDP context response. Cause value: %d\n",
+ cause);
+ pdp_freepdp(iph->pdp);
+ iph->pdp = NULL;
+ state = 0;
+ return EOF; /* Not a valid IP address */
+ }
+
+ printf("Received create PDP context response. IP address: %s\n",
+ inet_ntoa(addr));
+
+ if ((options.createif) && (!options.net.s_addr)) {
+ struct in_addr m;
#ifdef HAVE_INET_ATON
- inet_aton("255.255.255.255", &m);
+ inet_aton("255.255.255.255", &m);
#else
- m.s_addr = -1;
+ m.s_addr = -1;
#endif
- /* printf("Setting up interface and routing\n");*/
- tun_addaddr(tun, &addr, &addr, &m);
- if (options.defaultroute) {
- struct in_addr rm;
- rm.s_addr = 0;
- tun_addroute(tun, &rm, &addr, &rm);
- }
- if (options.ipup) tun_runscript(tun, options.ipup);
- }
-
- ipset((struct iphash_t*) pdp->peer, &addr);
-
- state = 2; /* Connected */
-
- return 0;
-}
+ /* printf("Setting up interface and routing\n"); */
+ tun_addaddr(tun, &addr, &addr, &m);
+ if (options.defaultroute) {
+ struct in_addr rm;
+ rm.s_addr = 0;
+ tun_addroute(tun, &rm, &addr, &rm);
+ }
+ if (options.ipup)
+ tun_runscript(tun, options.ipup);
+ }
-int delete_pdp_conf(struct pdp_t *pdp, int cause) {
- printf("Received delete PDP context response. Cause value: %d\n", cause);
- return 0;
+ ipset((struct iphash_t *)pdp->peer, &addr);
+
+ state = 2; /* Connected */
+
+ return 0;
}
-int echo_conf(int recovery) {
-
- if (recovery < 0) {
- printf("Echo Request timed out\n");
- if (echoversion == 1) {
- printf("Retrying with version 0\n");
- echoversion = 0;
- gtp_echo_req(gsn, echoversion, NULL, &options.remote);
- return 0;
- }
- else {
- state = 0;
- return EOF;
- }
- }
- else {
- printf("Received echo response\n");
- if (!options.contexts) state = 5;
- }
- return 0;
+int delete_pdp_conf(struct pdp_t *pdp, int cause)
+{
+ printf("Received delete PDP context response. Cause value: %d\n",
+ cause);
+ return 0;
}
-int conf(int type, int cause, struct pdp_t* pdp, void *cbp) {
- /* if (cause < 0) return 0; Some error occurred. We don't care */
- switch (type) {
- case GTP_ECHO_REQ:
- return echo_conf(cause);
- case GTP_CREATE_PDP_REQ:
- return create_pdp_conf(pdp, cbp, cause);
- case GTP_DELETE_PDP_REQ:
- if (cause !=128) return 0; /* Request not accepted. We don't care */
- return delete_pdp_conf(pdp, cause);
- default:
- return 0;
- }
+int echo_conf(int recovery)
+{
+
+ if (recovery < 0) {
+ printf("Echo Request timed out\n");
+ if (echoversion == 1) {
+ printf("Retrying with version 0\n");
+ echoversion = 0;
+ gtp_echo_req(gsn, echoversion, NULL, &options.remote);
+ return 0;
+ } else {
+ state = 0;
+ return EOF;
+ }
+ } else {
+ printf("Received echo response\n");
+ if (!options.contexts)
+ state = 5;
+ }
+ return 0;
}
+int conf(int type, int cause, struct pdp_t *pdp, void *cbp)
+{
+ /* if (cause < 0) return 0; Some error occurred. We don't care */
+ switch (type) {
+ case GTP_ECHO_REQ:
+ return echo_conf(cause);
+ case GTP_CREATE_PDP_REQ:
+ return create_pdp_conf(pdp, cbp, cause);
+ case GTP_DELETE_PDP_REQ:
+ if (cause != 128)
+ return 0; /* Request not accepted. We don't care */
+ return delete_pdp_conf(pdp, cause);
+ default:
+ return 0;
+ }
+}
-int encaps_tun(struct pdp_t *pdp, void *pack, unsigned len) {
- /* printf("encaps_tun. Packet received: forwarding to tun\n");*/
- return tun_encaps((struct tun_t*) pdp->ipif, pack, len);
+int encaps_tun(struct pdp_t *pdp, void *pack, unsigned len)
+{
+ /* printf("encaps_tun. Packet received: forwarding to tun\n"); */
+ return tun_encaps((struct tun_t *)pdp->ipif, pack, len);
}
int main(int argc, char **argv)
{
- fd_set fds; /* For select() */
- struct timeval idleTime; /* How long to select() */
- struct pdp_t *pdp;
- int n;
- int starttime = time(NULL); /* Time program was started */
- int stoptime = 0; /* Time to exit */
- int pingtimeout = 0; /* Time to print ping statistics */
-
- struct timezone tz; /* Used for calculating ping times */
- struct timeval tv;
- int diff;
-
- /* open a connection to the syslog daemon */
- /*openlog(PACKAGE, LOG_PID, LOG_DAEMON);*/
- /* TODO: Only use LOG__PERROR for linux */
+ fd_set fds; /* For select() */
+ struct timeval idleTime; /* How long to select() */
+ struct pdp_t *pdp;
+ int n;
+ int starttime = time(NULL); /* Time program was started */
+ int stoptime = 0; /* Time to exit */
+ int pingtimeout = 0; /* Time to print ping statistics */
+
+ struct timezone tz; /* Used for calculating ping times */
+ struct timeval tv;
+ int diff;
+
+ /* open a connection to the syslog daemon */
+ /*openlog(PACKAGE, LOG_PID, LOG_DAEMON); */
+ /* TODO: Only use LOG__PERROR for linux */
#ifdef __linux__
- openlog(PACKAGE, (LOG_PID | LOG_PERROR), LOG_DAEMON);
+ openlog(PACKAGE, (LOG_PID | LOG_PERROR), LOG_DAEMON);
#else
- openlog(PACKAGE, (LOG_PID), LOG_DAEMON);
+ openlog(PACKAGE, (LOG_PID), LOG_DAEMON);
#endif
+ /* Process options given in configuration file and command line */
+ if (process_options(argc, argv))
+ exit(1);
+
+ printf("\nInitialising GTP library\n");
+ if (gtp_new(&gsn, options.statedir, &options.listen, GTP_MODE_SGSN)) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Failed to create gtp");
+ exit(1);
+ }
+ if (gsn->fd0 > maxfd)
+ maxfd = gsn->fd0;
+ if (gsn->fd1c > maxfd)
+ maxfd = gsn->fd1c;
+ if (gsn->fd1u > maxfd)
+ maxfd = gsn->fd1u;
+
+ gtp_set_cb_delete_context(gsn, delete_context);
+ gtp_set_cb_conf(gsn, conf);
+ if (options.createif)
+ gtp_set_cb_data_ind(gsn, encaps_tun);
+ else
+ gtp_set_cb_data_ind(gsn, encaps_ping);
+
+ if (options.createif) {
+ printf("Setting up interface\n");
+ /* Create a tunnel interface */
+ if (tun_new((struct tun_t **)&tun)) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "Failed to create tun");
+ exit(1);
+ }
+ tun_set_cb_ind(tun, cb_tun_ind);
+ if (tun->fd > maxfd)
+ maxfd = tun->fd;
+ }
+
+ if ((options.createif) && (options.net.s_addr)) {
+ /* printf("Setting up interface and routing\n"); */
+ tun_addaddr(tun, &options.netaddr, &options.destaddr,
+ &options.mask);
+ if (options.defaultroute) {
+ struct in_addr rm;
+ rm.s_addr = 0;
+ tun_addroute(tun, &rm, &options.destaddr, &rm);
+ }
+ if (options.ipup)
+ tun_runscript(tun, options.ipup);
+ }
- /* Process options given in configuration file and command line */
- if (process_options(argc, argv))
- exit(1);
-
- printf("\nInitialising GTP library\n");
- if (gtp_new(&gsn, options.statedir, &options.listen, GTP_MODE_SGSN)) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "Failed to create gtp");
- exit(1);
- }
- if (gsn->fd0 > maxfd) maxfd = gsn->fd0;
- if (gsn->fd1c > maxfd) maxfd = gsn->fd1c;
- if (gsn->fd1u > maxfd) maxfd = gsn->fd1u;
-
- gtp_set_cb_delete_context(gsn, delete_context);
- gtp_set_cb_conf(gsn, conf);
- if (options.createif)
- gtp_set_cb_data_ind(gsn, encaps_tun);
- else
- gtp_set_cb_data_ind(gsn, encaps_ping);
-
- if (options.createif) {
- printf("Setting up interface\n");
- /* Create a tunnel interface */
- if (tun_new((struct tun_t**) &tun)) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "Failed to create tun");
- exit(1);
- }
- tun_set_cb_ind(tun, cb_tun_ind);
- if (tun->fd > maxfd) maxfd = tun->fd;
- }
-
- if ((options.createif) && (options.net.s_addr)) {
- /* printf("Setting up interface and routing\n");*/
- tun_addaddr(tun, &options.netaddr, &options.destaddr, &options.mask);
- if (options.defaultroute) {
- struct in_addr rm;
- rm.s_addr = 0;
- tun_addroute(tun, &rm, &options.destaddr, &rm);
- }
- if (options.ipup) tun_runscript(tun, options.ipup);
- }
-
-
- /* Initialise hash tables */
- memset(&iphash, 0, sizeof(iphash));
- memset(&iparr, 0, sizeof(iparr));
-
- printf("Done initialising GTP library\n\n");
-
- /* See if anybody is there */
- printf("Sending off echo request\n");
- echoversion = options.gtpversion;
- gtp_echo_req(gsn, echoversion, NULL, &options.remote); /* Is remote alive? */
-
- for(n=0; n<options.contexts; n++) {
- uint64_t myimsi;
- printf("Setting up PDP context #%d\n", n);
- iparr[n].inuse = 1; /* TODO */
-
- imsi_add(options.imsi, &myimsi, n);
-
- /* Allocated here. */
- /* If create context failes we have to deallocate ourselves. */
- /* Otherwise it is deallocated by gtplib */
- pdp_newpdp(&pdp, myimsi, options.nsapi, NULL);
-
- pdp->peer = &iparr[n];
- pdp->ipif = tun; /* TODO */
- iparr[n].pdp = pdp;
-
- 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);
- }
- }
-
- pdp->qos_req.l = options.qos.l ;
- memcpy(pdp->qos_req.v, options.qos.v, options.qos.l);
-
- 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->rai.l = options.rai.l;
- memcpy(pdp->rai.v, options.rai.v, options.rai.l);
- pdp->rai_given = options.rai_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;
-
- pdp->norecovery_given = options.norecovery_given;
-
- if (options.apn.l > sizeof(pdp->apn_use.v)) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0, "APN length too big");
- exit(1);
- }
- else {
- pdp->apn_use.l = options.apn.l;
- memcpy(pdp->apn_use.v, options.apn.v, options.apn.l);
- }
-
- pdp->gsnlc.l = sizeof(options.listen);
- memcpy(pdp->gsnlc.v, &options.listen, sizeof(options.listen));
- pdp->gsnlu.l = sizeof(options.listen);
- memcpy(pdp->gsnlu.v, &options.listen, sizeof(options.listen));
-
- if (options.msisdn.l > sizeof(pdp->msisdn.v)) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0, "MSISDN length too big");
- exit(1);
- }
- else {
- msisdn_add(&options.msisdn, &pdp->msisdn, n);
- }
-
- ipv42eua(&pdp->eua, NULL); /* Request dynamic IP address */
-
- if (options.pco.l > sizeof(pdp->pco_req.v)) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0, "PCO length too big");
- exit(1);
- }
- else {
- pdp->pco_req.l = options.pco.l;
- memcpy(pdp->pco_req.v, options.pco.v, options.pco.l);
- }
-
- pdp->version = options.gtpversion;
-
- pdp->hisaddr0 = options.remote;
- pdp->hisaddr1 = options.remote;
-
- pdp->cch_pdp = options.cch; /* 2048 = Normal, 1024 = Prepaid,
- 512 = Flat rate, 256 = Hot billing */
-
- /* Create context */
- /* We send this of once. Retransmissions are handled by gtplib */
- gtp_create_context_req(gsn, pdp, &iparr[n]);
- }
-
- state = 1; /* Enter wait_connection state */
-
- printf("Waiting for response from ggsn........\n\n");
+ /* Initialise hash tables */
+ memset(&iphash, 0, sizeof(iphash));
+ memset(&iparr, 0, sizeof(iparr));
+
+ printf("Done initialising GTP library\n\n");
+
+ /* See if anybody is there */
+ printf("Sending off echo request\n");
+ echoversion = options.gtpversion;
+ gtp_echo_req(gsn, echoversion, NULL, &options.remote); /* Is remote alive? */
+
+ for (n = 0; n < options.contexts; n++) {
+ uint64_t myimsi;
+ printf("Setting up PDP context #%d\n", n);
+ iparr[n].inuse = 1; /* TODO */
+
+ imsi_add(options.imsi, &myimsi, n);
+
+ /* Allocated here. */
+ /* If create context failes we have to deallocate ourselves. */
+ /* Otherwise it is deallocated by gtplib */
+ pdp_newpdp(&pdp, myimsi, options.nsapi, NULL);
+
+ pdp->peer = &iparr[n];
+ pdp->ipif = tun; /* TODO */
+ iparr[n].pdp = pdp;
+
+ 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);
+ }
+ }
+
+ pdp->qos_req.l = options.qos.l;
+ memcpy(pdp->qos_req.v, options.qos.v, options.qos.l);
+
+ 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->rai.l = options.rai.l;
+ memcpy(pdp->rai.v, options.rai.v, options.rai.l);
+ pdp->rai_given = options.rai_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;
+
+ pdp->norecovery_given = options.norecovery_given;
+
+ if (options.apn.l > sizeof(pdp->apn_use.v)) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "APN length too big");
+ exit(1);
+ } else {
+ pdp->apn_use.l = options.apn.l;
+ memcpy(pdp->apn_use.v, options.apn.v, options.apn.l);
+ }
+
+ pdp->gsnlc.l = sizeof(options.listen);
+ memcpy(pdp->gsnlc.v, &options.listen, sizeof(options.listen));
+ pdp->gsnlu.l = sizeof(options.listen);
+ memcpy(pdp->gsnlu.v, &options.listen, sizeof(options.listen));
+
+ if (options.msisdn.l > sizeof(pdp->msisdn.v)) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "MSISDN length too big");
+ exit(1);
+ } else {
+ msisdn_add(&options.msisdn, &pdp->msisdn, n);
+ }
+
+ ipv42eua(&pdp->eua, NULL); /* Request dynamic IP address */
+
+ if (options.pco.l > sizeof(pdp->pco_req.v)) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "PCO length too big");
+ exit(1);
+ } else {
+ pdp->pco_req.l = options.pco.l;
+ memcpy(pdp->pco_req.v, options.pco.v, options.pco.l);
+ }
+
+ pdp->version = options.gtpversion;
+
+ pdp->hisaddr0 = options.remote;
+ pdp->hisaddr1 = options.remote;
+
+ pdp->cch_pdp = options.cch; /* 2048 = Normal, 1024 = Prepaid,
+ 512 = Flat rate, 256 = Hot billing */
+
+ /* Create context */
+ /* We send this of once. Retransmissions are handled by gtplib */
+ gtp_create_context_req(gsn, pdp, &iparr[n]);
+ }
+ state = 1; /* Enter wait_connection state */
+
+ printf("Waiting for response from ggsn........\n\n");
/******************************************************************/
- /* Main select loop */
+ /* Main select loop */
/******************************************************************/
- while ((0 != state) && (5 != state)) {
-
- /* Take down client after timeout after disconnect */
- if ((4 == state) && ((stoptime) <= time(NULL))) {
- state = 5;
- }
-
- /* Take down client after timelimit timeout */
- if ((2 == state) && (options.timelimit) &&
- ((starttime + options.timelimit) <= time(NULL))) {
- state = 3;
- }
-
- /* Take down client after ping timeout */
- if ((2 == state) && (pingtimeout) && (pingtimeout <= time(NULL))) {
- state = 3;
- }
-
- /* Set pingtimeout for later disconnection */
- if (options.pingcount && ntransmitted >= options.pingcount) {
- pingtimeout = time(NULL) + 5; /* Extra seconds */
- }
-
- /* Print statistics if no more ping packets are missing */
- if (ntransmitted && options.pingcount && nreceived >= options.pingcount) {
- ping_finish();
- if (!options.createif)
- state = 3;
- }
-
- /* Send off disconnect */
- if (3 == state) {
- state = 4;
- stoptime = time(NULL) + 5; /* Extra seconds to allow disconnect */
- for(n=0; n<options.contexts; n++) {
- /* Delete context */
- printf("Disconnecting PDP context #%d\n", n);
- gtp_delete_context_req(gsn, iparr[n].pdp, NULL, 1);
- if ((options.pinghost.s_addr !=0) && ntransmitted) ping_finish();
- }
- }
-
- /* Send of ping packets */
- diff = 0;
- while (( diff<=0 ) &&
- /* Send off an ICMP ping packet */
- /*if (*/(options.pinghost.s_addr) && (2 == state) &&
- ((pingseq < options.pingcount) || (options.pingcount == 0))) {
- if (!pingseq) gettimeofday(&firstping, &tz); /* Set time of first ping */
- gettimeofday(&tv, &tz);
- diff = 1000000 / options.pingrate * pingseq -
- 1000000 * (tv.tv_sec - firstping.tv_sec) -
- (tv.tv_usec - firstping.tv_usec); /* Microseconds safe up to 500 sec */
- if (diff <=0) {
- if (options.debug) printf("Create_ping %d\n", diff);
- create_ping(gsn, iparr[pingseq % options.contexts].pdp,
- &options.pinghost, pingseq, options.pingsize);
- pingseq++;
- }
- }
-
- FD_ZERO(&fds);
- if (tun) FD_SET(tun->fd, &fds);
- FD_SET(gsn->fd0, &fds);
- FD_SET(gsn->fd1c, &fds);
- FD_SET(gsn->fd1u, &fds);
-
- gtp_retranstimeout(gsn, &idleTime);
- ping_timeout(&idleTime);
-
- if (options.debug) printf("idletime.tv_sec %d, idleTime.tv_usec %d\n",
- (int) idleTime.tv_sec, (int) idleTime.tv_usec);
-
- switch (select(maxfd + 1, &fds, NULL, NULL, &idleTime)) {
- case -1:
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "Select returned -1");
- break;
- case 0:
- gtp_retrans(gsn); /* Only retransmit if nothing else */
- break;
- default:
- break;
- }
-
- if ((tun) && FD_ISSET(tun->fd, &fds) && tun_decaps(tun) < 0) {
- sys_err(LOG_ERR, __FILE__, __LINE__, 0,
- "TUN decaps failed");
- }
-
- if (FD_ISSET(gsn->fd0, &fds))
- gtp_decaps0(gsn);
-
- if (FD_ISSET(gsn->fd1c, &fds))
- gtp_decaps1c(gsn);
-
- if (FD_ISSET(gsn->fd1u, &fds))
- gtp_decaps1u(gsn);
- }
-
- gtp_free(gsn); /* Clean up the gsn instance */
-
- if (options.createif)
- tun_free(tun);
-
- if (0 == state)
- exit(1); /* Indicate error */
-
- return 0;
-}
+ while ((0 != state) && (5 != state)) {
+
+ /* Take down client after timeout after disconnect */
+ if ((4 == state) && ((stoptime) <= time(NULL))) {
+ state = 5;
+ }
+
+ /* Take down client after timelimit timeout */
+ if ((2 == state) && (options.timelimit) &&
+ ((starttime + options.timelimit) <= time(NULL))) {
+ state = 3;
+ }
+
+ /* Take down client after ping timeout */
+ if ((2 == state) && (pingtimeout)
+ && (pingtimeout <= time(NULL))) {
+ state = 3;
+ }
+
+ /* Set pingtimeout for later disconnection */
+ if (options.pingcount && ntransmitted >= options.pingcount) {
+ pingtimeout = time(NULL) + 5; /* Extra seconds */
+ }
+
+ /* Print statistics if no more ping packets are missing */
+ if (ntransmitted && options.pingcount
+ && nreceived >= options.pingcount) {
+ ping_finish();
+ if (!options.createif)
+ state = 3;
+ }
+
+ /* Send off disconnect */
+ if (3 == state) {
+ state = 4;
+ stoptime = time(NULL) + 5; /* Extra seconds to allow disconnect */
+ for (n = 0; n < options.contexts; n++) {
+ /* Delete context */
+ printf("Disconnecting PDP context #%d\n", n);
+ gtp_delete_context_req(gsn, iparr[n].pdp, NULL,
+ 1);
+ if ((options.pinghost.s_addr != 0)
+ && ntransmitted)
+ ping_finish();
+ }
+ }
+
+ /* Send of ping packets */
+ diff = 0;
+ while ((diff <= 0) &&
+ /* Send off an ICMP ping packet */
+ /*if ( */ (options.pinghost.s_addr) && (2 == state) &&
+ ((pingseq < options.pingcount)
+ || (options.pingcount == 0))) {
+ if (!pingseq)
+ gettimeofday(&firstping, &tz); /* Set time of first ping */
+ gettimeofday(&tv, &tz);
+ diff = 1000000 / options.pingrate * pingseq - 1000000 * (tv.tv_sec - firstping.tv_sec) - (tv.tv_usec - firstping.tv_usec); /* Microseconds safe up to 500 sec */
+ if (diff <= 0) {
+ if (options.debug)
+ printf("Create_ping %d\n", diff);
+ create_ping(gsn,
+ iparr[pingseq %
+ options.contexts].pdp,
+ &options.pinghost, pingseq,
+ options.pingsize);
+ pingseq++;
+ }
+ }
+
+ FD_ZERO(&fds);
+ if (tun)
+ FD_SET(tun->fd, &fds);
+ FD_SET(gsn->fd0, &fds);
+ FD_SET(gsn->fd1c, &fds);
+ FD_SET(gsn->fd1u, &fds);
+
+ gtp_retranstimeout(gsn, &idleTime);
+ ping_timeout(&idleTime);
+
+ if (options.debug)
+ printf("idletime.tv_sec %d, idleTime.tv_usec %d\n",
+ (int)idleTime.tv_sec, (int)idleTime.tv_usec);
+
+ switch (select(maxfd + 1, &fds, NULL, NULL, &idleTime)) {
+ case -1:
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "Select returned -1");
+ break;
+ case 0:
+ gtp_retrans(gsn); /* Only retransmit if nothing else */
+ break;
+ default:
+ break;
+ }
+
+ if ((tun) && FD_ISSET(tun->fd, &fds) && tun_decaps(tun) < 0) {
+ sys_err(LOG_ERR, __FILE__, __LINE__, 0,
+ "TUN decaps failed");
+ }
+
+ if (FD_ISSET(gsn->fd0, &fds))
+ gtp_decaps0(gsn);
+
+ if (FD_ISSET(gsn->fd1c, &fds))
+ gtp_decaps1c(gsn);
+
+ if (FD_ISSET(gsn->fd1u, &fds))
+ gtp_decaps1u(gsn);
+ }
+
+ gtp_free(gsn); /* Clean up the gsn instance */
+ if (options.createif)
+ tun_free(tun);
+
+ if (0 == state)
+ exit(1); /* Indicate error */
+
+ return 0;
+}