Ping support
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 @@
   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 @@
   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 @@
   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 @@
   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 @@
   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 @@
   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 @@
         { "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 @@
         { "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 @@
           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 @@
             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 @@
             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 @@
             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 @@
                 }
               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 <option_name> <option_val>\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 <option_name> <option_val>\n",
-                               filename, line_num);
-                      exit (EXIT_FAILURE);
-                    }
-                }
-              continue;
-            }
           if (!strcmp(fopt, "contexts"))
             {
               if (override || !args_info->contexts_given)
@@ -641,15 +747,6 @@
                 }
               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 @@
                 }
               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 <option_name> <option_val>\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 <option_name> <option_val>\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 <option_name> <option_val>\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 <option_name> <option_val>\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 <option_name> <option_val>\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 <option_name> <option_val>\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 <option_name> <option_val>\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 <option_name> <option_val>\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  "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  "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 @@
   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 @@
   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 @@
   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 @@
   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 <unistd.h>
 #include <sys/socket.h>
 #include <sys/ioctl.h>
+#include <sys/time.h>
 #include <net/if.h>
 #include <features.h>
 #include <errno.h>
@@ -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 *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<len; i++) {
-    printf("%02x ", (unsigned char)*(char *)(packet+i));
+    printf("%02x ", (unsigned char)*(char *)(pack+i));
     if (!((i+1)%16)) printf("\n");
   };
-  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]);
+}
+
+/* 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 @@
   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 @@
       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 @@
       }
       
       /*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 @@
   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 @@
     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 @@
   /* 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 @@
     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 @@
       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 @@
   }
 
   /* 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 @@
       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 @@
   }
 
 
-  /* 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 @@
   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 @@
   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 @@
     }
     
     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 @@
 
   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 @@
 	/* 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 @@
     
     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 @@
 
     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;
   
 }