aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2011-11-02 13:06:18 +0100
committerHarald Welte <laforge@gnumonks.org>2011-11-02 13:06:18 +0100
commitbed35df298f4914fabedfc7c9387af3f2f9a9e9f (patch)
tree0079fe22d0839637d8c777d2eebb91cd35b065c2
parentca36f293648ee19056df7ea9a1cbfcc93c800dc8 (diff)
Convert all code to Linux coding style
After so many years of silence, we don't expect the original author to return to the project. To make things a bit simpler for us, we convert the coding style to what we are used to (Linux style). The conversion was made using the 'Lindent' script which is part of the Linux kernel.
-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;
+}