Support for external ipup script
diff --git a/ggsn/cmdline.c b/ggsn/cmdline.c
index ef50f7c..3c5d7e2 100644
--- a/ggsn/cmdline.c
+++ b/ggsn/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:
@@ -55,6 +55,8 @@
   printf("              --timelimit=INT    Exit after timelimit seconds (default='0')\n");
   printf("   -aSTRING   --apn=STRING       Access point name (default='internet')\n");
   printf("   -qINT      --qos=INT          Requested quality of service (default='0x0b921f')\n");
+  printf("              --ipup=STRING      Script to run after link-up\n");
+  printf("              --ipdown=STRING    Script to run after link-down\n");
 }
 
 
@@ -91,6 +93,8 @@
   args_info->timelimit_given = 0 ;
   args_info->apn_given = 0 ;
   args_info->qos_given = 0 ;
+  args_info->ipup_given = 0 ;
+  args_info->ipdown_given = 0 ;
 #define clear_args() { \
   args_info->fg_flag = 0;\
   args_info->debug_flag = 0;\
@@ -103,6 +107,8 @@
   args_info->timelimit_arg = 0 ;\
   args_info->apn_arg = strdup("internet") ;\
   args_info->qos_arg = 0x0b921f ;\
+  args_info->ipup_arg = NULL; \
+  args_info->ipdown_arg = NULL; \
 }
 
   clear_args();
@@ -130,6 +136,8 @@
         { "timelimit",	1, NULL, 0 },
         { "apn",	1, NULL, 'a' },
         { "qos",	1, NULL, 'q' },
+        { "ipup",	1, NULL, 0 },
+        { "ipdown",	1, NULL, 0 },
         { NULL,	0, NULL, 0 }
       };
 
@@ -280,6 +288,32 @@
             args_info->timelimit_arg = strtol (optarg,&stop_char,0);
             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;
+          }
 
         case '?':	/* Invalid option.  */
           /* `getopt_long' already printed an error message.  */
@@ -515,6 +549,38 @@
                 }
               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;
+            }
           
 
           /* Tried all known options. This one is unknown! */
diff --git a/ggsn/cmdline.ggo b/ggsn/cmdline.ggo
index 5d3e601..c4d281d 100644
--- a/ggsn/cmdline.ggo
+++ b/ggsn/cmdline.ggo
@@ -27,3 +27,7 @@
 
 option  "apn"         a "Access point name"             string default="internet" no
 option  "qos"         q "Requested quality of service"  int    default="0x0b921f" no
+
+option  "ipup"        - "Script to run after link-up"    string no
+option  "ipdown"      - "Script to run after link-down"  string no
+
diff --git a/ggsn/cmdline.h b/ggsn/cmdline.h
index f0c177f..22c723f 100644
--- a/ggsn/cmdline.h
+++ b/ggsn/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
@@ -31,6 +31,8 @@
   int timelimit_arg;	/* Exit after timelimit seconds (default='0').  */
   char * apn_arg;	/* Access point name (default='internet').  */
   int qos_arg;	/* Requested quality of service (default='0x0b921f').  */
+  char * ipup_arg;	/* Script to run after link-up.  */
+  char * ipdown_arg;	/* Script to run after link-down.  */
 
   int help_given ;	/* Whether help was given.  */
   int version_given ;	/* Whether version was given.  */
@@ -45,6 +47,8 @@
   int timelimit_given ;	/* Whether timelimit was given.  */
   int apn_given ;	/* Whether apn was given.  */
   int qos_given ;	/* Whether qos was given.  */
+  int ipup_given ;	/* Whether ipup was given.  */
+  int ipdown_given ;	/* Whether ipdown was given.  */
 
 } ;
 
diff --git a/ggsn/ggsn.c b/ggsn/ggsn.c
index effe226..3f9767b 100644
--- a/ggsn/ggsn.c
+++ b/ggsn/ggsn.c
@@ -61,6 +61,7 @@
 int tun_fd = -1;		/* Network file descriptor */
 struct tun_t *tun;              /* TUN instance            */
 struct in_addr net, mask;       /* Network interface       */
+char *ipup, *ipdown;            /* Filename of scripts */
 int debug;                      /* Print debug output */
 
 
@@ -175,16 +176,26 @@
     exit(1);
   }
 
-  strncpy(snet, inet_ntoa(net), 100);
-  strncpy(smask, inet_ntoa(mask), 100);
+  strncpy(snet, inet_ntoa(net), sizeof(snet)); 
+  snet[sizeof(snet)-1] = 0;
+  strncpy(smask, inet_ntoa(mask), sizeof(smask));
+  smask[sizeof(smask)-1] = 0;
 
-  sprintf(buf, "/sbin/ifconfig %s %s mtu 1450 netmask %s",
+  snprintf(buf, sizeof(buf), "/sbin/ifconfig %s %s mtu 1450 netmask %s",
 	  tun->devname, snet, smask);
+  buf[sizeof(buf)-1] = 0;
   if (debug) printf("%s\n", buf);
   system(buf);
 
-  system("echo 1 > /proc/sys/net/ipv4/ip_forward");
-  
+  if (ipup) {
+    /* system("ipup /dev/tun0 192.168.0.10"); */
+    snprintf(buf, sizeof(buf), "%s %s %s %s",
+	     ipup, tun->devname, snet, smask);
+    buf[sizeof(buf)-1] = 0;
+    if (debug) printf("%s\n", buf);
+    system(buf);
+  }
+
   return 0;
 }
 
@@ -249,6 +260,8 @@
     printf("apn: %s\n", args_info.apn_arg);
     printf("net: %s\n", args_info.net_arg);
     printf("mask: %s\n", args_info.mask_arg);
+    printf("ipup: %s\n", args_info.ipup_arg);
+    printf("ipdown: %s\n", args_info.ipdown_arg);
     printf("pidfile: %s\n", args_info.pidfile_arg);
     printf("statedir: %s\n", args_info.statedir_arg);
     printf("timelimit: %d\n", args_info.timelimit_arg);
@@ -268,6 +281,8 @@
     printf("apn: %s\n", args_info.apn_arg);
     printf("net: %s\n", args_info.net_arg);
     printf("mask: %s\n", args_info.mask_arg);
+    printf("ipup: %s\n", args_info.ipup_arg);
+    printf("ipdown: %s\n", args_info.ipdown_arg);
     printf("pidfile: %s\n", args_info.pidfile_arg);
     printf("statedir: %s\n", args_info.statedir_arg);
     printf("timelimit: %d\n", args_info.timelimit_arg);
@@ -342,6 +357,12 @@
     }
   }
 
+  /* ipup */
+  ipup = args_info.ipup_arg;
+
+  /* ipdown */
+  ipdown = args_info.ipdown_arg;
+
   /* Timelimit                                                       */
   timelimit = args_info.timelimit_arg;
   starttime = time(NULL);
@@ -354,14 +375,14 @@
   qos.v[0] = ((args_info.qos_arg) >> 16) & 0xff;
   
   /* apn                                                             */
-  if (strlen(args_info.apn_arg)>255) {
+  if (strlen(args_info.apn_arg)>(sizeof(apnh)-1)) {
     printf("invalid APN\n");
     exit(1);
   }
   apn.l = strlen(args_info.apn_arg) + 1;
   apn.v = apnh;
   apn.v[0] = (char) strlen(args_info.apn_arg);
-  strncpy(&apn.v[1], args_info.apn_arg, 255);
+  strncpy(&apn.v[1], args_info.apn_arg, (sizeof(apnh)-1));
 
   if (debug) printf("gtpclient: Initialising GTP tunnel\n");
   
@@ -410,11 +431,11 @@
 
     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);