From 5da6845e836d315fc31fb7d3e08a9fd55ff7ad1d Mon Sep 17 00:00:00 2001 From: jjako Date: Tue, 28 Jan 2003 16:08:47 +0000 Subject: [PATCH] Ping support --- sgsnemu/cmdline.c | 438 ++++++++++++++++++++++++------- sgsnemu/cmdline.ggo | 16 +- sgsnemu/cmdline.h | 30 ++- sgsnemu/sgsnemu.c | 614 +++++++++++++++++++++++++++++++------------- 4 files changed, 820 insertions(+), 278 deletions(-) diff --git a/sgsnemu/cmdline.c b/sgsnemu/cmdline.c index d8f51df..836e160 100644 --- a/sgsnemu/cmdline.c +++ b/sgsnemu/cmdline.c @@ -1,7 +1,7 @@ /* - File autogenerated by gengetopt version 2.8 + File autogenerated by gengetopt version 2.8rc generated with the following command: - gengetopt --conf-parser + ../../gengetopt-2.8rc/src/gengetopt --conf-parser The developers of gengetopt consider the fixed text that goes in all gengetopt output files to be in the public domain: @@ -52,10 +52,7 @@ cmdline_parser_print_help (void) printf(" --dns=STRING DNS Server to use\n"); printf(" -lSTRING --listen=STRING Local interface\n"); printf(" -rSTRING --remote=STRING Remote host\n"); - printf(" -nSTRING --net=STRING Network (default='192.168.0.0')\n"); - printf(" --mask=STRING Network mask (default='255.255.255.0')\n"); printf(" --contexts=INT Number of contexts (default='1')\n"); - printf(" --static Allocate static tun ifterface (default=off)\n"); printf(" --timelimit=INT Exit after timelimit seconds (default='0')\n"); printf(" -aSTRING --apn=STRING Access point name (default='internet')\n"); printf(" -iSTRING --imsi=STRING IMSI (default='240010123456789')\n"); @@ -63,6 +60,17 @@ cmdline_parser_print_help (void) printf(" -qINT --qos=INT Requested quality of service (default='0x0b921f')\n"); printf(" -uSTRING --uid=STRING Login user ID (default='mig')\n"); printf(" -pSTRING --pwd=STRING Login password (default='hemmelig')\n"); + printf(" --createif Create local network interface (default=off)\n"); + printf(" --ipup=STRING Script to run after link-up\n"); + printf(" --ipdown=STRING Script to run after link-down\n"); + printf(" --defaultroute Add default route after link-up (default=off)\n"); + printf(" --net=STRING Network (default='0.0.0.0')\n"); + printf(" --mask=STRING Network mask (default='0.0.0.0')\n"); + printf(" --pinghost=STRING Ping remote host\n"); + printf(" --pingrate=INT Number of ping req per second (default='1')\n"); + printf(" --pingsize=INT Number of ping data bytes (default='56')\n"); + printf(" --pingcount=INT Number of ping req to send (default='0')\n"); + printf(" --pingquiet Do not print ping packet info (default=off)\n"); } @@ -96,10 +104,7 @@ cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_i args_info->dns_given = 0 ; args_info->listen_given = 0 ; args_info->remote_given = 0 ; - args_info->net_given = 0 ; - args_info->mask_given = 0 ; args_info->contexts_given = 0 ; - args_info->static_given = 0 ; args_info->timelimit_given = 0 ; args_info->apn_given = 0 ; args_info->imsi_given = 0 ; @@ -107,6 +112,17 @@ cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_i args_info->qos_given = 0 ; args_info->uid_given = 0 ; args_info->pwd_given = 0 ; + args_info->createif_given = 0 ; + args_info->ipup_given = 0 ; + args_info->ipdown_given = 0 ; + args_info->defaultroute_given = 0 ; + args_info->net_given = 0 ; + args_info->mask_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 ; #define clear_args() { \ args_info->fg_flag = 0;\ args_info->debug_flag = 0;\ @@ -116,10 +132,7 @@ cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_i args_info->dns_arg = NULL; \ args_info->listen_arg = NULL; \ args_info->remote_arg = NULL; \ - args_info->net_arg = strdup("192.168.0.0") ;\ - args_info->mask_arg = strdup("255.255.255.0") ;\ args_info->contexts_arg = 1 ;\ - args_info->static_flag = 0;\ args_info->timelimit_arg = 0 ;\ args_info->apn_arg = strdup("internet") ;\ args_info->imsi_arg = strdup("240010123456789") ;\ @@ -127,6 +140,17 @@ cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_i args_info->qos_arg = 0x0b921f ;\ args_info->uid_arg = strdup("mig") ;\ args_info->pwd_arg = strdup("hemmelig") ;\ + args_info->createif_flag = 0;\ + args_info->ipup_arg = NULL; \ + args_info->ipdown_arg = NULL; \ + args_info->defaultroute_flag = 0;\ + args_info->net_arg = strdup("0.0.0.0") ;\ + args_info->mask_arg = strdup("0.0.0.0") ;\ + args_info->pinghost_arg = NULL; \ + args_info->pingrate_arg = 1 ;\ + args_info->pingsize_arg = 56 ;\ + args_info->pingcount_arg = 0 ;\ + args_info->pingquiet_flag = 0;\ } clear_args(); @@ -151,10 +175,7 @@ cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_i { "dns", 1, NULL, 0 }, { "listen", 1, NULL, 'l' }, { "remote", 1, NULL, 'r' }, - { "net", 1, NULL, 'n' }, - { "mask", 1, NULL, 0 }, { "contexts", 1, NULL, 0 }, - { "static", 0, NULL, 0 }, { "timelimit", 1, NULL, 0 }, { "apn", 1, NULL, 'a' }, { "imsi", 1, NULL, 'i' }, @@ -162,10 +183,21 @@ cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_i { "qos", 1, NULL, 'q' }, { "uid", 1, NULL, 'u' }, { "pwd", 1, NULL, 'p' }, + { "createif", 0, NULL, 0 }, + { "ipup", 1, NULL, 0 }, + { "ipdown", 1, NULL, 0 }, + { "defaultroute", 0, NULL, 0 }, + { "net", 1, NULL, 0 }, + { "mask", 1, NULL, 0 }, + { "pinghost", 1, NULL, 0 }, + { "pingrate", 1, NULL, 0 }, + { "pingsize", 1, NULL, 0 }, + { "pingcount", 1, NULL, 0 }, + { "pingquiet", 0, NULL, 0 }, { NULL, 0, NULL, 0 } }; - c = getopt_long (argc, argv, "hVfdc:l:r:n:a:i:m:q:u:p:", long_options, &option_index); + c = getopt_long (argc, argv, "hVfdc:l:r:a:i:m:q:u:p:", long_options, &option_index); if (c == -1) break; /* Exit from `while (1)' loop. */ @@ -236,17 +268,6 @@ cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_i args_info->remote_arg = strdup (optarg); break; - case 'n': /* Network. */ - if (args_info->net_given) - { - fprintf (stderr, "%s: `--net' (`-n') option given more than once\n", PACKAGE); - clear_args (); - exit (EXIT_FAILURE); - } - args_info->net_given = 1; - args_info->net_arg = strdup (optarg); - break; - case 'a': /* Access point name. */ if (args_info->apn_given) { @@ -354,19 +375,6 @@ cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_i args_info->dns_arg = strdup (optarg); break; } - /* Network mask. */ - else if (strcmp (long_options[option_index].name, "mask") == 0) - { - if (args_info->mask_given) - { - fprintf (stderr, "%s: `--mask' option given more than once\n", PACKAGE); - clear_args (); - exit (EXIT_FAILURE); - } - args_info->mask_given = 1; - args_info->mask_arg = strdup (optarg); - break; - } /* Number of contexts. */ else if (strcmp (long_options[option_index].name, "contexts") == 0) { @@ -380,19 +388,6 @@ cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_i args_info->contexts_arg = strtol (optarg,&stop_char,0); break; } - /* Allocate static tun ifterface. */ - else if (strcmp (long_options[option_index].name, "static") == 0) - { - if (args_info->static_given) - { - fprintf (stderr, "%s: `--static' option given more than once\n", PACKAGE); - clear_args (); - exit (EXIT_FAILURE); - } - args_info->static_given = 1; - args_info->static_flag = !(args_info->static_flag); - break; - } /* Exit after timelimit seconds. */ else if (strcmp (long_options[option_index].name, "timelimit") == 0) { @@ -406,6 +401,149 @@ cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_i args_info->timelimit_arg = strtol (optarg,&stop_char,0); break; } + /* Create local network interface. */ + else if (strcmp (long_options[option_index].name, "createif") == 0) + { + if (args_info->createif_given) + { + fprintf (stderr, "%s: `--createif' option given more than once\n", PACKAGE); + clear_args (); + exit (EXIT_FAILURE); + } + args_info->createif_given = 1; + args_info->createif_flag = !(args_info->createif_flag); + break; + } + /* Script to run after link-up. */ + else if (strcmp (long_options[option_index].name, "ipup") == 0) + { + if (args_info->ipup_given) + { + fprintf (stderr, "%s: `--ipup' option given more than once\n", PACKAGE); + clear_args (); + exit (EXIT_FAILURE); + } + args_info->ipup_given = 1; + args_info->ipup_arg = strdup (optarg); + break; + } + /* Script to run after link-down. */ + else if (strcmp (long_options[option_index].name, "ipdown") == 0) + { + if (args_info->ipdown_given) + { + fprintf (stderr, "%s: `--ipdown' option given more than once\n", PACKAGE); + clear_args (); + exit (EXIT_FAILURE); + } + args_info->ipdown_given = 1; + args_info->ipdown_arg = strdup (optarg); + break; + } + /* Add default route after link-up. */ + else if (strcmp (long_options[option_index].name, "defaultroute") == 0) + { + if (args_info->defaultroute_given) + { + fprintf (stderr, "%s: `--defaultroute' option given more than once\n", PACKAGE); + clear_args (); + exit (EXIT_FAILURE); + } + args_info->defaultroute_given = 1; + args_info->defaultroute_flag = !(args_info->defaultroute_flag); + break; + } + /* Network. */ + else if (strcmp (long_options[option_index].name, "net") == 0) + { + if (args_info->net_given) + { + fprintf (stderr, "%s: `--net' option given more than once\n", PACKAGE); + clear_args (); + exit (EXIT_FAILURE); + } + args_info->net_given = 1; + args_info->net_arg = strdup (optarg); + break; + } + /* Network mask. */ + else if (strcmp (long_options[option_index].name, "mask") == 0) + { + if (args_info->mask_given) + { + fprintf (stderr, "%s: `--mask' option given more than once\n", PACKAGE); + clear_args (); + exit (EXIT_FAILURE); + } + args_info->mask_given = 1; + args_info->mask_arg = strdup (optarg); + break; + } + /* Ping remote host. */ + else if (strcmp (long_options[option_index].name, "pinghost") == 0) + { + if (args_info->pinghost_given) + { + fprintf (stderr, "%s: `--pinghost' option given more than once\n", PACKAGE); + clear_args (); + exit (EXIT_FAILURE); + } + args_info->pinghost_given = 1; + args_info->pinghost_arg = strdup (optarg); + break; + } + /* Number of ping req per second. */ + else if (strcmp (long_options[option_index].name, "pingrate") == 0) + { + if (args_info->pingrate_given) + { + fprintf (stderr, "%s: `--pingrate' option given more than once\n", PACKAGE); + clear_args (); + exit (EXIT_FAILURE); + } + args_info->pingrate_given = 1; + args_info->pingrate_arg = strtol (optarg,&stop_char,0); + break; + } + /* Number of ping data bytes. */ + else if (strcmp (long_options[option_index].name, "pingsize") == 0) + { + if (args_info->pingsize_given) + { + fprintf (stderr, "%s: `--pingsize' option given more than once\n", PACKAGE); + clear_args (); + exit (EXIT_FAILURE); + } + args_info->pingsize_given = 1; + args_info->pingsize_arg = strtol (optarg,&stop_char,0); + break; + } + /* Number of ping req to send. */ + else if (strcmp (long_options[option_index].name, "pingcount") == 0) + { + if (args_info->pingcount_given) + { + fprintf (stderr, "%s: `--pingcount' option given more than once\n", PACKAGE); + clear_args (); + exit (EXIT_FAILURE); + } + args_info->pingcount_given = 1; + args_info->pingcount_arg = strtol (optarg,&stop_char,0); + break; + } + /* Do not print ping packet info. */ + else if (strcmp (long_options[option_index].name, "pingquiet") == 0) + { + if (args_info->pingquiet_given) + { + fprintf (stderr, "%s: `--pingquiet' option given more than once\n", PACKAGE); + clear_args (); + exit (EXIT_FAILURE); + } + args_info->pingquiet_given = 1; + args_info->pingquiet_flag = !(args_info->pingquiet_flag); + break; + } case '?': /* Invalid option. */ /* `getopt_long' already printed an error message. */ @@ -593,38 +731,6 @@ cmdline_parser_configfile (char * const filename, struct gengetopt_args_info *ar } continue; } - if (!strcmp(fopt, "net")) - { - if (override || !args_info->net_given) - { - args_info->net_given = 1; - if (fnum == 2) - args_info->net_arg = strdup (farg); - else - { - fprintf (stderr, "%s:%d: required \n", - filename, line_num); - exit (EXIT_FAILURE); - } - } - continue; - } - if (!strcmp(fopt, "mask")) - { - if (override || !args_info->mask_given) - { - args_info->mask_given = 1; - if (fnum == 2) - args_info->mask_arg = strdup (farg); - else - { - fprintf (stderr, "%s:%d: required \n", - filename, line_num); - exit (EXIT_FAILURE); - } - } - continue; - } if (!strcmp(fopt, "contexts")) { if (override || !args_info->contexts_given) @@ -641,15 +747,6 @@ cmdline_parser_configfile (char * const filename, struct gengetopt_args_info *ar } continue; } - if (!strcmp(fopt, "static")) - { - if (override || !args_info->static_given) - { - args_info->static_given = 1; - args_info->static_flag = !(args_info->static_flag); - } - continue; - } if (!strcmp(fopt, "timelimit")) { if (override || !args_info->timelimit_given) @@ -762,6 +859,161 @@ cmdline_parser_configfile (char * const filename, struct gengetopt_args_info *ar } continue; } + if (!strcmp(fopt, "createif")) + { + if (override || !args_info->createif_given) + { + args_info->createif_given = 1; + args_info->createif_flag = !(args_info->createif_flag); + } + continue; + } + if (!strcmp(fopt, "ipup")) + { + if (override || !args_info->ipup_given) + { + args_info->ipup_given = 1; + if (fnum == 2) + args_info->ipup_arg = strdup (farg); + else + { + fprintf (stderr, "%s:%d: required \n", + filename, line_num); + exit (EXIT_FAILURE); + } + } + continue; + } + if (!strcmp(fopt, "ipdown")) + { + if (override || !args_info->ipdown_given) + { + args_info->ipdown_given = 1; + if (fnum == 2) + args_info->ipdown_arg = strdup (farg); + else + { + fprintf (stderr, "%s:%d: required \n", + filename, line_num); + exit (EXIT_FAILURE); + } + } + continue; + } + if (!strcmp(fopt, "defaultroute")) + { + if (override || !args_info->defaultroute_given) + { + args_info->defaultroute_given = 1; + args_info->defaultroute_flag = !(args_info->defaultroute_flag); + } + continue; + } + if (!strcmp(fopt, "net")) + { + if (override || !args_info->net_given) + { + args_info->net_given = 1; + if (fnum == 2) + args_info->net_arg = strdup (farg); + else + { + fprintf (stderr, "%s:%d: required \n", + filename, line_num); + exit (EXIT_FAILURE); + } + } + continue; + } + if (!strcmp(fopt, "mask")) + { + if (override || !args_info->mask_given) + { + args_info->mask_given = 1; + if (fnum == 2) + args_info->mask_arg = strdup (farg); + else + { + fprintf (stderr, "%s:%d: required \n", + filename, line_num); + exit (EXIT_FAILURE); + } + } + continue; + } + if (!strcmp(fopt, "pinghost")) + { + if (override || !args_info->pinghost_given) + { + args_info->pinghost_given = 1; + if (fnum == 2) + args_info->pinghost_arg = strdup (farg); + else + { + fprintf (stderr, "%s:%d: required \n", + filename, line_num); + exit (EXIT_FAILURE); + } + } + continue; + } + if (!strcmp(fopt, "pingrate")) + { + if (override || !args_info->pingrate_given) + { + args_info->pingrate_given = 1; + if (fnum == 2) + args_info->pingrate_arg = strtol (farg,&stop_char,0); + else + { + fprintf (stderr, "%s:%d: required \n", + filename, line_num); + exit (EXIT_FAILURE); + } + } + continue; + } + if (!strcmp(fopt, "pingsize")) + { + if (override || !args_info->pingsize_given) + { + args_info->pingsize_given = 1; + if (fnum == 2) + args_info->pingsize_arg = strtol (farg,&stop_char,0); + else + { + fprintf (stderr, "%s:%d: required \n", + filename, line_num); + exit (EXIT_FAILURE); + } + } + continue; + } + if (!strcmp(fopt, "pingcount")) + { + if (override || !args_info->pingcount_given) + { + args_info->pingcount_given = 1; + if (fnum == 2) + args_info->pingcount_arg = strtol (farg,&stop_char,0); + else + { + fprintf (stderr, "%s:%d: required \n", + filename, line_num); + exit (EXIT_FAILURE); + } + } + continue; + } + if (!strcmp(fopt, "pingquiet")) + { + if (override || !args_info->pingquiet_given) + { + args_info->pingquiet_given = 1; + args_info->pingquiet_flag = !(args_info->pingquiet_flag); + } + continue; + } /* Tried all known options. This one is unknown! */ diff --git a/sgsnemu/cmdline.ggo b/sgsnemu/cmdline.ggo index 6b21818..7d5fcfb 100644 --- a/sgsnemu/cmdline.ggo +++ b/sgsnemu/cmdline.ggo @@ -21,11 +21,8 @@ option "statedir" - "Directory of nonvolatile data" string default="./" no option "dns" - "DNS Server to use" string no option "listen" l "Local interface" string no option "remote" r "Remote host" string no -option "net" n "Network" string default="192.168.0.0" no -option "mask" - "Network mask" string default="255.255.255.0" no option "contexts" - "Number of contexts" int default="1" no -option "static" - "Allocate static tun ifterface" flag off option "timelimit" - "Exit after timelimit seconds" int default="0" no option "apn" a "Access point name" string default="internet" no @@ -35,3 +32,16 @@ option "qos" q "Requested quality of service" int default="0x0b921 option "uid" u "Login user ID" string default="mig" no option "pwd" p "Login password" string default="hemmelig" no +option "createif" - "Create local network interface" flag off +option "ipup" - "Script to run after link-up" string no +option "ipdown" - "Script to run after link-down" string no +option "defaultroute" - "Add default route after link-up" flag off +option "net" - "Network" string default="0.0.0.0" no +option "mask" - "Network mask" string default="0.0.0.0" no + +option "pinghost" - "Ping remote host" string no +option "pingrate" - "Number of ping req per second" int default="1" no +option "pingsize" - "Number of ping data bytes" int default="56" no +option "pingcount" - "Number of ping req to send" int default="0" no +option "pingquiet" - "Do not print ping packet info" flag off + diff --git a/sgsnemu/cmdline.h b/sgsnemu/cmdline.h index c29caf0..475ea1c 100644 --- a/sgsnemu/cmdline.h +++ b/sgsnemu/cmdline.h @@ -1,6 +1,6 @@ /* cmdline.h */ -/* File autogenerated by gengetopt version 2.8 */ +/* File autogenerated by gengetopt version 2.8rc */ #ifndef _cmdline_h #define _cmdline_h @@ -28,10 +28,7 @@ struct gengetopt_args_info char * dns_arg; /* DNS Server to use. */ char * listen_arg; /* Local interface. */ char * remote_arg; /* Remote host. */ - char * net_arg; /* Network (default='192.168.0.0'). */ - char * mask_arg; /* Network mask (default='255.255.255.0'). */ int contexts_arg; /* Number of contexts (default='1'). */ - int static_flag; /* Allocate static tun ifterface (default=off). */ int timelimit_arg; /* Exit after timelimit seconds (default='0'). */ char * apn_arg; /* Access point name (default='internet'). */ char * imsi_arg; /* IMSI (default='240010123456789'). */ @@ -39,6 +36,17 @@ struct gengetopt_args_info int qos_arg; /* Requested quality of service (default='0x0b921f'). */ char * uid_arg; /* Login user ID (default='mig'). */ char * pwd_arg; /* Login password (default='hemmelig'). */ + int createif_flag; /* Create local network interface (default=off). */ + char * ipup_arg; /* Script to run after link-up. */ + char * ipdown_arg; /* Script to run after link-down. */ + int defaultroute_flag; /* Add default route after link-up (default=off). */ + char * net_arg; /* Network (default='0.0.0.0'). */ + char * mask_arg; /* Network mask (default='0.0.0.0'). */ + char * pinghost_arg; /* Ping remote host. */ + int pingrate_arg; /* Number of ping req per second (default='1'). */ + int pingsize_arg; /* Number of ping data bytes (default='56'). */ + int pingcount_arg; /* Number of ping req to send (default='0'). */ + int pingquiet_flag; /* Do not print ping packet info (default=off). */ int help_given ; /* Whether help was given. */ int version_given ; /* Whether version was given. */ @@ -50,10 +58,7 @@ struct gengetopt_args_info int dns_given ; /* Whether dns was given. */ int listen_given ; /* Whether listen was given. */ int remote_given ; /* Whether remote was given. */ - int net_given ; /* Whether net was given. */ - int mask_given ; /* Whether mask was given. */ int contexts_given ; /* Whether contexts was given. */ - int static_given ; /* Whether static was given. */ int timelimit_given ; /* Whether timelimit was given. */ int apn_given ; /* Whether apn was given. */ int imsi_given ; /* Whether imsi was given. */ @@ -61,6 +66,17 @@ struct gengetopt_args_info int qos_given ; /* Whether qos was given. */ int uid_given ; /* Whether uid was given. */ int pwd_given ; /* Whether pwd was given. */ + int createif_given ; /* Whether createif was given. */ + int ipup_given ; /* Whether ipup was given. */ + int ipdown_given ; /* Whether ipdown was given. */ + int defaultroute_given ; /* Whether defaultroute was given. */ + int net_given ; /* Whether net was given. */ + int mask_given ; /* Whether mask 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. */ } ; diff --git a/sgsnemu/sgsnemu.c b/sgsnemu/sgsnemu.c index dd24fce..0230b55 100644 --- a/sgsnemu/sgsnemu.c +++ b/sgsnemu/sgsnemu.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -55,6 +56,8 @@ #include "../gtp/gtp.h" #include "cmdline.h" +#define SGSNEMU_BUFSIZE 1024 + /* State variable */ /* 0: Idle */ /* 1: Wait_connect */ @@ -68,22 +71,274 @@ struct tun_t *tun; /* TUN instance */ struct tun_t *tun1, *tun2; /* TUN instance for client */ int tun_fd1 = -1; /* Network file descriptor */ int tun_fd2 = -1; /* Network file descriptor */ -struct in_addr net, mask; /* Network interface */ -int stattun; /* Allocate static tun */ +/* Variables matching program configuration parameters */ int debug; /* Print debug messages */ +struct in_addr net, mask; /* Network interface */ +int createif; /* Create local network interface */ +char *ipup, *ipdown; /* Filename of scripts */ +int defaultroute; /* Set up default route */ +struct in_addr pinghost; /* Remote ping host */ +int pingrate, pingsize, pingcount, pingquiet; +struct in_addr listen_, remote; +struct in_addr dns; +int contexts; /* Number of contexts to create */ +int timelimit; /* Number of seconds to be connected */ -int encaps_printf(void *p, void *packet, unsigned len) -{ + +/* Definitions to use for PING. Most of the ping code was derived from */ +/* the original ping program by Mike Muuss */ + +/* IP header and ICMP echo header */ +#define CREATEPING_MAX 2048 +#define CREATEPING_IP 20 +#define CREATEPING_ICMP 8 + +struct ip_ping { + u_int8_t ipver; /* Type and header length*/ + u_int8_t tos; /* Type of Service */ + u_int16_t length; /* Total length */ + u_int16_t fragid; /* Identifier */ + u_int16_t offset; /* Flags and fragment offset */ + u_int8_t ttl; /* Time to live */ + u_int8_t protocol; /* Protocol */ + u_int16_t ipcheck; /* Header checksum */ + u_int32_t src; /* Source address */ + u_int32_t dst; /* Destination */ + u_int8_t type; /* Type and header length*/ + u_int8_t code; /* Code */ + u_int16_t checksum; /* Header checksum */ + u_int16_t ident; /* Identifier */ + u_int16_t seq; /* Sequence number */ + u_int8_t data[CREATEPING_MAX]; /* Data */ +} __attribute__((packed)); + +/* Statistical values for ping */ +int nreceived = 0; +int ntreceived = 0; +int ntransmitted = 0; +int tmin = 999999999; +int tmax = 0; +int tsum = 0; + + +int encaps_printf(struct pdp_t *pdp, void *pack, unsigned len) { int i; printf("The packet looks like this:\n"); for( i=0; i 16 ) + return("OUT-OF-RANGE"); + return(ttab[t]); +} + +/* Print out statistics when at the end of ping sequence */ +int ping_finish() +{ + printf("\n"); + printf("\n----%s PING Statistics----\n", inet_ntoa(pinghost)); + printf("%d packets transmitted, ", ntransmitted ); + 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 (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 ); + 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 (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 (!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 (!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 (!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 (!pingquiet) printf(" time=%.3f ms\n", triptime/1000.0); + + } + else + if (!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, int datasize) { + + struct ip_ping pack; + u_int16_t *p = (u_int16_t *) &pack; + u_int8_t *p8 = (u_int8_t *) &pack; + struct in_addr src; + 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) { + fprintf(stderr, "%s: Ping size to large: %d!\n", + PACKAGE, datasize); + syslog(LOG_ERR, "Ping size to large: %d!", + datasize); + exit(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 = (u_int8_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 = (u_int16_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 = (u_int16_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_gpdu(gsn, pdp, &pack, 28 + datasize); +} + + /* Used to write process ID to file. Assume someone else will delete */ void log_pid(char *pidfile) { FILE *file; @@ -98,77 +353,9 @@ void log_pid(char *pidfile) { fclose(file); } - -int create_tun() { - char buf[1024]; - char snet[100], smask[100]; - - if ((tun_fd = tun_newtun((struct tun_t**) &tun)) > maxfd) - maxfd = tun_fd; - - if (tun_fd == -1) { - printf("Failed to open tun\n"); - exit(1); - } - - strncpy(snet, inet_ntoa(net), 100); - strncpy(smask, inet_ntoa(mask), 100); - - sprintf(buf, "/sbin/ifconfig %s %s mtu 1450 netmask %s", - tun->devname, snet, smask); - if (debug) printf("%s\n", buf); - system(buf); - - system("echo 1 > /proc/sys/net/ipv4/ip_forward"); - - return 0; -} - -int getip(struct pdp_t *pdp, void* ipif, struct ul66_t *eua, - struct in_addr *net, struct in_addr *mask) { - struct in_addr addr; - uint32_t ip_start, ip_end, ip_cur; - struct pdp_t *pdp_; - struct ul66_t eua_; - - printf("Begin getip %d %d %2x%2x%2x%2x\n", (unsigned)ipif, eua->l, - eua->v[2],eua->v[3],eua->v[4],eua->v[5]); - - ip_start = ntoh32(net->s_addr & mask->s_addr); - ip_end = ntoh32(hton32(ip_start) | ~mask->s_addr); - - /* By convention the first address is the network address, and the last */ - /* address is the broadcast address. This way two IP addresses are "lost" */ - ip_start++; - - if (eua->l == 0) { /* No address supplied. Find one that is available! */ - /* This routine does linear search. In order to support millions of - * addresses we should instead keep a linked list of available adresses */ - for (ip_cur = ip_start; ip_cur < ip_end; ip_cur++) { - addr.s_addr = hton32(ip_cur); - pdp_ntoeua(&addr, &eua_); - if (pdp_ipget(&pdp_, ipif, &eua_) == -1) { - pdp_ntoeua(&addr, &pdp->eua); - pdp->ipif = ipif; - return 0; - }; - } - return EOF; /* No addresses available */ - } - else { /* Address supplied */ - if (pdp_ipget(&pdp_, ipif, eua) == -1) { - pdp->ipif = ipif; - pdp->eua.l = eua->l; - memcpy(pdp->eua.v, eua->v, eua->l); - return 0; - } - else return EOF; /* Specified address not available */ - } -} - int delete_context(struct pdp_t *pdp) { - - if (!stattun) { + char buf[SGSNEMU_BUFSIZE]; + if ((createif) && (pdp->ipif!=0)) { tun_freetun((struct tun_t*) pdp->ipif); /* Clean up locally */ @@ -181,26 +368,37 @@ int delete_context(struct pdp_t *pdp) { tun_fd2=-1; } } + + if (ipdown) { + /* system("ipdown /dev/tun0 192.168.0.10"); */ + snprintf(buf, sizeof(buf), "%s %s %hu.%hu.%hu.%hu", + ipdown, + ((struct tun_t*) pdp->ipif)->devname, + pdp->eua.v[2], pdp->eua.v[3], pdp->eua.v[4], pdp->eua.v[5]); + if (debug) printf("%s\n", buf); + system(buf); + } pdp_ipdel(pdp); return 0; } int create_pdp_conf(struct pdp_t *pdp, int cause) { - char buf[1024]; + char buf[SGSNEMU_BUFSIZE]; + char snet[SGSNEMU_BUFSIZE]; + char smask[SGSNEMU_BUFSIZE]; printf("Received create PDP context response. Cause value: %d\n", cause); if ((cause == 128) && (pdp->eua.l == 6)) { - - - if (stattun) { + + if (!createif) { pdp->ipif = tun1; } else { printf("Setting up interface and routing\n"); if ((tun_fd = tun_newtun((struct tun_t**) &pdp->ipif)) > maxfd) maxfd = tun_fd; - + /* HACK: Only support select of up to two tun interfaces */ if (NULL == tun1) { tun1 = pdp->ipif; @@ -212,21 +410,43 @@ int create_pdp_conf(struct pdp_t *pdp, int cause) { } /*system("/sbin/ifconfig tun0 192.168.0.10");*/ - sprintf(buf, "/sbin/ifconfig %s %hu.%hu.%hu.%hu", + snprintf(buf, sizeof(buf), "/sbin/ifconfig %s %hu.%hu.%hu.%hu", ((struct tun_t*) pdp->ipif)->devname, pdp->eua.v[2], pdp->eua.v[3], pdp->eua.v[4], pdp->eua.v[5]); - printf(buf); printf("\n"); + /* if (debug) */ printf("%s\n", buf); system(buf); + + /* system("route add -host 192.168.0.10 dev tun0"); */ + /* It seams as if we do not need to set up a route to a p-t-p interface + snprintf(buf, sizeof(buf), + "/sbin/route add -host %hu.%hu.%hu.%hu dev %s", + pdp->eua.v[2], pdp->eua.v[3], pdp->eua.v[4], pdp->eua.v[5], + ((struct tun_t*) pdp->ipif)->devname); + if (debug) printf("%s\n", buf); + system(buf);*/ + + if (defaultroute) { + strncpy(snet, inet_ntoa(net), sizeof(snet)); + strncpy(smask, inet_ntoa(mask), sizeof(smask)); + /* system("route add -net 0.0.0.0 netmask 0.0.0.0 gw 192.168.0.1"); */ + snprintf(buf, sizeof(buf), + "/sbin/route add -net %s netmask %s gw %hu.%hu.%hu.%hu", + snet, smask, + pdp->eua.v[2], pdp->eua.v[3], pdp->eua.v[4], pdp->eua.v[5]); + /* if (debug) */ printf("%s\n", buf); + system(buf); + } + + if (ipup) { + /* system("ipup /dev/tun0 192.168.0.10"); */ + snprintf(buf, sizeof(buf), "%s %s %hu.%hu.%hu.%hu", + ipup, + ((struct tun_t*) pdp->ipif)->devname, + pdp->eua.v[2], pdp->eua.v[3], pdp->eua.v[4], pdp->eua.v[5]); + if (debug) printf("%s\n", buf); + system(buf); + } - - /*system("route add -net 192.168.0.0 netmask 255.255.255.0 gw 192.168.0.10");*/ - sprintf(buf, "/sbin/route add -net %hu.%hu.%hu.0 netmask 255.255.255.0 gw %hu.%hu.%hu.%hu", - pdp->eua.v[2], pdp->eua.v[3], pdp->eua.v[4], - pdp->eua.v[2], pdp->eua.v[3], pdp->eua.v[4], pdp->eua.v[5]); - printf(buf); printf("\n"); - system(buf); - - system("echo 1 > /proc/sys/net/ipv4/ip_forward"); } pdp_ipset(pdp, pdp->ipif, &pdp->eua); @@ -242,30 +462,17 @@ int create_pdp_conf(struct pdp_t *pdp, int cause) { return 0; } - -int create_pdp_ind(struct pdp_t *pdp) { - - printf("Received create PDP context request\n"); - - 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_neg)); - - getip(pdp, &tun, &pdp->eua, &net, &mask); - pdp_ipset(pdp, pdp->ipif, &pdp->eua); - - return 0; /* Success */ -} - - int delete_pdp_conf(struct pdp_t *pdp, int cause) { printf("Received delete PDP context response. Cause value: %d\n", cause); + state = 0; /* Idle */ return 0; } int echo_conf(struct pdp_t *pdp, int cause) { - printf("Received echo response. Cause value: %d\n", cause); + if (cause <0) + printf("Echo request timed out\n"); + else + printf("Received echo response.\n"); return 0; } @@ -298,7 +505,7 @@ int encaps_gtp_client(void *gsn, struct tun_t *tun, void *pack, unsigned len) { return gtp_gpdu((struct gsn_t*) gsn, pdp, pack, len); } else { - printf("Received packet with no destination!!!\n"); + printf("Received packet without a valid source address!!!\n"); return 0; } } @@ -313,27 +520,18 @@ int main(int argc, char **argv) /* gengeopt declarations */ struct gengetopt_args_info args_info; - /* function-local options */ struct hostent *host; - - struct in_addr listen, remote; - struct in_addr dns; - int gtpfd = -1; /* Network file descriptor */ struct gsn_t *gsn; /* GSN instance */ - fd_set fds; /* For select() */ struct timeval idleTime; /* How long to select() */ - - struct pdp_t *pdp[2]; - + struct pdp_t *pdp[50]; int n; /* For counter */ + int starttime; /* Time program was started */ + int pingseq = 0; /* Ping sequence counter */ - int contexts; /* Number of contexts to create */ - int timelimit; /* Number of seconds to be connected */ - int starttime; /* Time program was started */ - + /* function-local options */ struct ul_t imsi, qos, apn, msisdn; unsigned char qosh[3], imsih[8], apnh[256], msisdnh[256]; struct ul255_t pco; @@ -357,14 +555,22 @@ int main(int argc, char **argv) printf("msisdn: %s\n", args_info.msisdn_arg); printf("uid: %s\n", args_info.uid_arg); printf("pwd: %s\n", args_info.pwd_arg); - printf("static: %d\n", args_info.static_flag); - printf("net: %s\n", args_info.net_arg); - printf("mask: %s\n", args_info.mask_arg); printf("pidfile: %s\n", args_info.pidfile_arg); printf("statedir: %s\n", args_info.statedir_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); + printf("ipup: %s\n", args_info.ipup_arg); + printf("ipdown: %s\n", args_info.ipdown_arg); + printf("defaultroute: %d\n", args_info.defaultroute_flag); + printf("net: %s\n", args_info.net_arg); + printf("mask: %s\n", args_info.mask_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); } /* Try out our new parser */ @@ -385,21 +591,29 @@ int main(int argc, char **argv) printf("msisdn: %s\n", args_info.msisdn_arg); printf("uid: %s\n", args_info.uid_arg); printf("pwd: %s\n", args_info.pwd_arg); - printf("static: %d\n", args_info.static_flag); - printf("net: %s\n", args_info.net_arg); - printf("mask: %s\n", args_info.mask_arg); printf("pidfile: %s\n", args_info.pidfile_arg); printf("statedir: %s\n", args_info.statedir_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); + printf("ipup: %s\n", args_info.ipup_arg); + printf("ipdown: %s\n", args_info.ipdown_arg); + printf("defaultroute: %d\n", args_info.defaultroute_flag); + printf("net: %s\n", args_info.net_arg); + printf("mask: %s\n", args_info.mask_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); } } /* Handle each option */ /* foreground */ - /* If flag not given run as a daemon */ + /* If fg flag not given run as a daemon */ if (!args_info.fg_flag) { closelog(); @@ -422,7 +636,7 @@ int main(int argc, char **argv) } /* dns */ - /* If no dns option is given use system default */ + /* 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) { @@ -457,8 +671,8 @@ int main(int argc, char **argv) exit(1); } else { - memcpy(&listen.s_addr, host->h_addr, host->h_length); - printf("Local IP address is: %s (%s)\n", args_info.listen_arg, inet_ntoa(listen)); + memcpy(&listen_.s_addr, host->h_addr, host->h_length); + printf("Local IP address is: %s (%s)\n", args_info.listen_arg, inet_ntoa(listen_)); } } else { @@ -494,30 +708,6 @@ int main(int argc, char **argv) } - /* net */ - /* Store net as in_addr */ - if (args_info.net_arg) { - if (!inet_aton(args_info.net_arg, &net)) { - fprintf(stderr, "%s: Invalid network address: %s!\n", - PACKAGE, args_info.net_arg); - syslog(LOG_ERR, "Invalid network address: %s!", - args_info.net_arg); - exit(1); - } - } - - /* mask */ - /* Store mask as in_addr */ - if (args_info.mask_arg) { - if (!inet_aton(args_info.mask_arg, &mask)) { - fprintf(stderr, "%s: Invalid network mask: %s!\n", - PACKAGE, args_info.mask_arg); - syslog(LOG_ERR, "Invalid network mask: %s!", - args_info.mask_arg); - exit(1); - } - } - /* imsi */ if (strlen(args_info.imsi_arg)!=15) { printf("Invalid IMSI\n"); @@ -551,6 +741,10 @@ int main(int argc, char **argv) qos.v[0] = ((args_info.qos_arg) >> 16) & 0xff; /* contexts */ + if (args_info.contexts_arg>16) { + printf("Contexts has to be less than 16\n"); + exit(1); + } contexts = args_info.contexts_arg; /* Timelimit */ @@ -607,27 +801,76 @@ int main(int argc, char **argv) pco.v[9+strlen(args_info.uid_arg)] = strlen(args_info.pwd_arg); memcpy(&pco.v[10+strlen(args_info.uid_arg)], args_info.pwd_arg, strlen(args_info.pwd_arg)); - /* static */ - stattun = args_info.static_flag; + /* createif */ + createif = args_info.createif_flag; + + /* ipup */ + ipup = args_info.ipup_arg; + + /* ipdown */ + ipdown = args_info.ipdown_arg; + + /* defaultroute */ + defaultroute = args_info.defaultroute_flag; + + /* net */ + /* Store net as in_addr */ + if (args_info.net_arg) { + if (!inet_aton(args_info.net_arg, &net)) { + fprintf(stderr, "%s: Invalid network address: %s!\n", + PACKAGE, args_info.net_arg); + syslog(LOG_ERR, "Invalid network address: %s!", + args_info.net_arg); + exit(1); + } + } + + /* mask */ + /* Store mask as in_addr */ + if (args_info.mask_arg) { + if (!inet_aton(args_info.mask_arg, &mask)) { + fprintf(stderr, "%s: Invalid network mask: %s!\n", + PACKAGE, args_info.mask_arg); + syslog(LOG_ERR, "Invalid network mask: %s!", + args_info.mask_arg); + exit(1); + } + } + + /* pinghost */ + /* Store ping host as in_addr */ + if (args_info.pinghost_arg) { + if (!inet_aton(args_info.pinghost_arg, &pinghost)) { + fprintf(stderr, "%s: Invalid ping host: %s!\n", + PACKAGE, args_info.pinghost_arg); + syslog(LOG_ERR, "Invalid ping host: %s!", + args_info.pinghost_arg); + exit(1); + } + } + + /* Other ping parameters */ + pingrate = args_info.pingrate_arg; + pingsize = args_info.pingsize_arg; + pingcount = args_info.pingcount_arg; + pingquiet = args_info.pingquiet_flag; printf("\nInitialising GTP library\n"); - if ((gtpfd = gtp_new(&gsn, args_info.statedir_arg, &listen)) > maxfd) + if ((gtpfd = gtp_new(&gsn, args_info.statedir_arg, &listen_)) > maxfd) maxfd = gtpfd; if ((gtpfd = gtp_fd(gsn)) > maxfd) maxfd = gtpfd; - gtp_set_cb_gpdu(gsn, encaps_tun); + if (createif) + gtp_set_cb_gpdu(gsn, encaps_tun); + else + gtp_set_cb_gpdu(gsn, encaps_ping); + gtp_set_cb_delete_context(gsn, delete_context); gtp_set_cb_conf(gsn, conf); printf("Done initialising GTP library\n\n"); - - if (stattun) { - create_tun(); - tun1 = tun; - tun_fd1 = tun1->fd; - } /* See if anybody is there */ printf("Sending off echo request\n"); @@ -660,9 +903,9 @@ int main(int argc, char **argv) } pdp[n]->gsnlc.l = 4; - memcpy(pdp[n]->gsnlc.v, &listen, 4); + memcpy(pdp[n]->gsnlc.v, &listen_, 4); pdp[n]->gsnlu.l = 4; - memcpy(pdp[n]->gsnlu.v, &listen, 4); + memcpy(pdp[n]->gsnlu.v, &listen_, 4); if (msisdn.l > sizeof(pdp[n]->msisdn.v)) { exit(1); @@ -691,12 +934,13 @@ int main(int argc, char **argv) printf("Waiting for response from ggsn........\n\n"); - + /******************************************************************/ /* Main select loop */ /******************************************************************/ - while (((starttime + timelimit + 10) > time(NULL)) || (0 == timelimit)) { + while ((((starttime + timelimit + 10) > time(NULL)) + || (0 == timelimit)) && (state!=0)) { /* Take down client connections at some stage */ if (((starttime + timelimit) <= time(NULL)) && (0 != timelimit) && (2 == state)) { @@ -705,9 +949,23 @@ int main(int argc, char **argv) /* Delete context */ printf("Disconnecting PDP context #%d\n", n); if (gtpfd != -1) gtp_delete_context(gsn, pdp[n], NULL); + if ((pinghost.s_addr !=0) && ntransmitted) ping_finish(); } +} + + + /* Ping */ + while ((2 == state) && (pinghost.s_addr !=0) && + ((pingseq < pingcount) || (pingcount == 0)) && + (starttime + pingseq/pingrate) <= time(NULL)) { + create_ping(gsn, pdp[pingseq % contexts], + &pinghost, pingseq++, pingsize); } + if (ntransmitted && pingcount && nreceived >= pingcount) + ping_finish(); + + FD_ZERO(&fds); if (tun_fd1 != -1) FD_SET(tun_fd1, &fds); if (tun_fd2 != -1) FD_SET(tun_fd2, &fds); @@ -715,6 +973,12 @@ int main(int argc, char **argv) gtp_retranstimeout(gsn, &idleTime); + if ((pinghost.s_addr !=0) && + ((idleTime.tv_sec !=0) || (idleTime.tv_usec !=0))) { + idleTime.tv_sec = 0; + idleTime.tv_usec = 1000000 / pingrate; + } + switch (select(maxfd + 1, &fds, NULL, NULL, &idleTime)) { case -1: syslog(LOG_ERR, "sgsnemu: select = -1"); @@ -740,15 +1004,15 @@ int main(int argc, char **argv) if (gtpfd != -1 && FD_ISSET(gtpfd, &fds) && gtp_decaps(gsn) < 0) { - syslog(LOG_ERR, "GTP read failed (gre)=(%d)", gtpfd); + syslog(LOG_ERR, "GTP read failed (gtpfd)=(%d)", gtpfd); } - } + } gtp_free(gsn); /* Clean up the gsn instance */ - return 1; + return 0; }