Initial revision
diff --git a/ggsn/.deps/cmdline.P b/ggsn/.deps/cmdline.P
new file mode 100644
index 0000000..f8c0fb9
--- /dev/null
+++ b/ggsn/.deps/cmdline.P
@@ -0,0 +1,33 @@
+cmdline.o: cmdline.c /usr/include/stdio.h /usr/include/features.h \
+  /usr/include/sys/cdefs.h /usr/include/gnu/stubs.h \
+  /usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stddef.h \
+  /usr/include/bits/types.h /usr/include/libio.h /usr/include/_G_config.h \
+  /usr/include/wchar.h /usr/include/bits/wchar.h /usr/include/gconv.h \
+  /usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stdarg.h \
+  /usr/include/bits/stdio_lim.h /usr/include/bits/stdio.h \
+  /usr/include/stdlib.h /usr/include/string.h /usr/include/bits/string.h \
+  /usr/include/bits/string2.h /usr/include/endian.h \
+  /usr/include/bits/endian.h /usr/include/getopt.h cmdline.h
+cmdline.c :
+/usr/include/stdio.h :
+/usr/include/features.h :
+/usr/include/sys/cdefs.h :
+/usr/include/gnu/stubs.h :
+/usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stddef.h :
+/usr/include/bits/types.h :
+/usr/include/libio.h :
+/usr/include/_G_config.h :
+/usr/include/wchar.h :
+/usr/include/bits/wchar.h :
+/usr/include/gconv.h :
+/usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stdarg.h :
+/usr/include/bits/stdio_lim.h :
+/usr/include/bits/stdio.h :
+/usr/include/stdlib.h :
+/usr/include/string.h :
+/usr/include/bits/string.h :
+/usr/include/bits/string2.h :
+/usr/include/endian.h :
+/usr/include/bits/endian.h :
+/usr/include/getopt.h :
+cmdline.h :
diff --git a/ggsn/.deps/ggsn.P b/ggsn/.deps/ggsn.P
new file mode 100644
index 0000000..3d4612e
--- /dev/null
+++ b/ggsn/.deps/ggsn.P
@@ -0,0 +1,146 @@
+ggsn.o: ggsn.c /usr/include/syslog.h /usr/include/sys/syslog.h \
+  /usr/include/features.h /usr/include/sys/cdefs.h \
+  /usr/include/gnu/stubs.h \
+  /usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stdarg.h \
+  /usr/include/ctype.h /usr/include/bits/types.h \
+  /usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stddef.h \
+  /usr/include/bits/pthreadtypes.h /usr/include/bits/sched.h \
+  /usr/include/endian.h /usr/include/bits/endian.h /usr/include/xlocale.h \
+  /usr/include/netdb.h /usr/include/netinet/in.h /usr/include/stdint.h \
+  /usr/include/bits/wchar.h /usr/include/bits/wordsize.h \
+  /usr/include/bits/socket.h \
+  /usr/lib/gcc-lib/i386-redhat-linux/2.96/include/limits.h \
+  /usr/lib/gcc-lib/i386-redhat-linux/2.96/include/syslimits.h \
+  /usr/include/limits.h /usr/include/bits/posix1_lim.h \
+  /usr/include/bits/local_lim.h /usr/include/linux/limits.h \
+  /usr/include/bits/posix2_lim.h /usr/include/bits/xopen_lim.h \
+  /usr/include/bits/stdio_lim.h /usr/include/sys/types.h \
+  /usr/include/time.h /usr/include/sys/select.h \
+  /usr/include/bits/select.h /usr/include/bits/sigset.h \
+  /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
+  /usr/include/bits/sockaddr.h /usr/include/asm/socket.h \
+  /usr/include/asm/sockios.h /usr/include/bits/in.h \
+  /usr/include/bits/byteswap.h /usr/include/rpc/netdb.h \
+  /usr/include/bits/siginfo.h /usr/include/bits/netdb.h \
+  /usr/include/signal.h /usr/include/bits/signum.h \
+  /usr/include/bits/sigaction.h /usr/include/bits/sigcontext.h \
+  /usr/include/asm/sigcontext.h /usr/include/bits/sigstack.h \
+  /usr/include/ucontext.h /usr/include/sys/ucontext.h \
+  /usr/include/bits/sigthread.h /usr/include/stdio.h /usr/include/libio.h \
+  /usr/include/_G_config.h /usr/include/wchar.h /usr/include/gconv.h \
+  /usr/include/bits/stdio.h /usr/include/string.h \
+  /usr/include/bits/string.h /usr/include/bits/string2.h \
+  /usr/include/stdlib.h /usr/include/bits/waitflags.h \
+  /usr/include/bits/waitstatus.h /usr/include/alloca.h \
+  /usr/include/sys/socket.h /usr/include/sys/uio.h \
+  /usr/include/bits/uio.h /usr/include/arpa/inet.h \
+  /usr/include/sys/wait.h /usr/include/sys/resource.h \
+  /usr/include/bits/resource.h /usr/include/sys/stat.h \
+  /usr/include/bits/stat.h /usr/include/unistd.h \
+  /usr/include/bits/posix_opt.h /usr/include/bits/environments.h \
+  /usr/include/bits/confname.h /usr/include/getopt.h \
+  /usr/include/sys/ioctl.h /usr/include/bits/ioctls.h \
+  /usr/include/asm/ioctls.h /usr/include/asm/ioctl.h \
+  /usr/include/bits/ioctl-types.h /usr/include/sys/ttydefaults.h \
+  /usr/include/net/if.h /usr/include/errno.h /usr/include/bits/errno.h \
+  /usr/include/linux/errno.h /usr/include/asm/errno.h \
+  /usr/include/asm/types.h /usr/include/linux/netlink.h tun.h \
+  ../gtp/pdp.h ../gtp/gtp.h cmdline.h
+ggsn.c :
+/usr/include/syslog.h :
+/usr/include/sys/syslog.h :
+/usr/include/features.h :
+/usr/include/sys/cdefs.h :
+/usr/include/gnu/stubs.h :
+/usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stdarg.h :
+/usr/include/ctype.h :
+/usr/include/bits/types.h :
+/usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stddef.h :
+/usr/include/bits/pthreadtypes.h :
+/usr/include/bits/sched.h :
+/usr/include/endian.h :
+/usr/include/bits/endian.h :
+/usr/include/xlocale.h :
+/usr/include/netdb.h :
+/usr/include/netinet/in.h :
+/usr/include/stdint.h :
+/usr/include/bits/wchar.h :
+/usr/include/bits/wordsize.h :
+/usr/include/bits/socket.h :
+/usr/lib/gcc-lib/i386-redhat-linux/2.96/include/limits.h :
+/usr/lib/gcc-lib/i386-redhat-linux/2.96/include/syslimits.h :
+/usr/include/limits.h :
+/usr/include/bits/posix1_lim.h :
+/usr/include/bits/local_lim.h :
+/usr/include/linux/limits.h :
+/usr/include/bits/posix2_lim.h :
+/usr/include/bits/xopen_lim.h :
+/usr/include/bits/stdio_lim.h :
+/usr/include/sys/types.h :
+/usr/include/time.h :
+/usr/include/sys/select.h :
+/usr/include/bits/select.h :
+/usr/include/bits/sigset.h :
+/usr/include/bits/time.h :
+/usr/include/sys/sysmacros.h :
+/usr/include/bits/sockaddr.h :
+/usr/include/asm/socket.h :
+/usr/include/asm/sockios.h :
+/usr/include/bits/in.h :
+/usr/include/bits/byteswap.h :
+/usr/include/rpc/netdb.h :
+/usr/include/bits/siginfo.h :
+/usr/include/bits/netdb.h :
+/usr/include/signal.h :
+/usr/include/bits/signum.h :
+/usr/include/bits/sigaction.h :
+/usr/include/bits/sigcontext.h :
+/usr/include/asm/sigcontext.h :
+/usr/include/bits/sigstack.h :
+/usr/include/ucontext.h :
+/usr/include/sys/ucontext.h :
+/usr/include/bits/sigthread.h :
+/usr/include/stdio.h :
+/usr/include/libio.h :
+/usr/include/_G_config.h :
+/usr/include/wchar.h :
+/usr/include/gconv.h :
+/usr/include/bits/stdio.h :
+/usr/include/string.h :
+/usr/include/bits/string.h :
+/usr/include/bits/string2.h :
+/usr/include/stdlib.h :
+/usr/include/bits/waitflags.h :
+/usr/include/bits/waitstatus.h :
+/usr/include/alloca.h :
+/usr/include/sys/socket.h :
+/usr/include/sys/uio.h :
+/usr/include/bits/uio.h :
+/usr/include/arpa/inet.h :
+/usr/include/sys/wait.h :
+/usr/include/sys/resource.h :
+/usr/include/bits/resource.h :
+/usr/include/sys/stat.h :
+/usr/include/bits/stat.h :
+/usr/include/unistd.h :
+/usr/include/bits/posix_opt.h :
+/usr/include/bits/environments.h :
+/usr/include/bits/confname.h :
+/usr/include/getopt.h :
+/usr/include/sys/ioctl.h :
+/usr/include/bits/ioctls.h :
+/usr/include/asm/ioctls.h :
+/usr/include/asm/ioctl.h :
+/usr/include/bits/ioctl-types.h :
+/usr/include/sys/ttydefaults.h :
+/usr/include/net/if.h :
+/usr/include/errno.h :
+/usr/include/bits/errno.h :
+/usr/include/linux/errno.h :
+/usr/include/asm/errno.h :
+/usr/include/asm/types.h :
+/usr/include/linux/netlink.h :
+tun.h :
+../gtp/pdp.h :
+../gtp/gtp.h :
+cmdline.h :
diff --git a/ggsn/.deps/ggsnopt.P b/ggsn/.deps/ggsnopt.P
new file mode 100644
index 0000000..f96b6f3
--- /dev/null
+++ b/ggsn/.deps/ggsnopt.P
@@ -0,0 +1,33 @@
+ggsnopt.o: ggsnopt.c /usr/include/stdio.h /usr/include/features.h \
+  /usr/include/sys/cdefs.h /usr/include/gnu/stubs.h \
+  /usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stddef.h \
+  /usr/include/bits/types.h /usr/include/libio.h /usr/include/_G_config.h \
+  /usr/include/wchar.h /usr/include/bits/wchar.h /usr/include/gconv.h \
+  /usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stdarg.h \
+  /usr/include/bits/stdio_lim.h /usr/include/bits/stdio.h \
+  /usr/include/stdlib.h /usr/include/string.h /usr/include/bits/string.h \
+  /usr/include/bits/string2.h /usr/include/endian.h \
+  /usr/include/bits/endian.h /usr/include/getopt.h ggsnopt.h
+ggsnopt.c :
+/usr/include/stdio.h :
+/usr/include/features.h :
+/usr/include/sys/cdefs.h :
+/usr/include/gnu/stubs.h :
+/usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stddef.h :
+/usr/include/bits/types.h :
+/usr/include/libio.h :
+/usr/include/_G_config.h :
+/usr/include/wchar.h :
+/usr/include/bits/wchar.h :
+/usr/include/gconv.h :
+/usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stdarg.h :
+/usr/include/bits/stdio_lim.h :
+/usr/include/bits/stdio.h :
+/usr/include/stdlib.h :
+/usr/include/string.h :
+/usr/include/bits/string.h :
+/usr/include/bits/string2.h :
+/usr/include/endian.h :
+/usr/include/bits/endian.h :
+/usr/include/getopt.h :
+ggsnopt.h :
diff --git a/ggsn/.deps/tun.P b/ggsn/.deps/tun.P
new file mode 100644
index 0000000..29f9cf4
--- /dev/null
+++ b/ggsn/.deps/tun.P
@@ -0,0 +1,108 @@
+tun.o: tun.c /usr/include/syslog.h /usr/include/sys/syslog.h \
+  /usr/include/features.h /usr/include/sys/cdefs.h \
+  /usr/include/gnu/stubs.h \
+  /usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stdarg.h \
+  /usr/include/stdio.h \
+  /usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stddef.h \
+  /usr/include/bits/types.h /usr/include/libio.h /usr/include/_G_config.h \
+  /usr/include/wchar.h /usr/include/bits/wchar.h /usr/include/gconv.h \
+  /usr/include/bits/stdio_lim.h /usr/include/bits/stdio.h \
+  /usr/include/stdlib.h /usr/include/sys/types.h /usr/include/time.h \
+  /usr/include/sys/socket.h /usr/include/sys/uio.h \
+  /usr/include/bits/uio.h /usr/include/bits/socket.h \
+  /usr/lib/gcc-lib/i386-redhat-linux/2.96/include/limits.h \
+  /usr/lib/gcc-lib/i386-redhat-linux/2.96/include/syslimits.h \
+  /usr/include/limits.h /usr/include/bits/sockaddr.h \
+  /usr/include/asm/socket.h /usr/include/asm/sockios.h \
+  /usr/include/netinet/in.h /usr/include/stdint.h \
+  /usr/include/bits/wordsize.h /usr/include/bits/in.h \
+  /usr/include/endian.h /usr/include/bits/endian.h \
+  /usr/include/bits/byteswap.h /usr/include/arpa/inet.h \
+  /usr/include/sys/stat.h /usr/include/bits/stat.h \
+  /usr/include/sys/time.h /usr/include/bits/time.h \
+  /usr/include/sys/select.h /usr/include/bits/select.h \
+  /usr/include/bits/sigset.h /usr/include/unistd.h \
+  /usr/include/bits/posix_opt.h /usr/include/bits/confname.h \
+  /usr/include/string.h /usr/include/bits/string.h \
+  /usr/include/bits/string2.h /usr/include/errno.h \
+  /usr/include/bits/errno.h /usr/include/linux/errno.h \
+  /usr/include/asm/errno.h /usr/include/fcntl.h /usr/include/bits/fcntl.h \
+  /usr/include/sys/ioctl.h /usr/include/bits/ioctls.h \
+  /usr/include/asm/ioctls.h /usr/include/asm/ioctl.h \
+  /usr/include/bits/ioctl-types.h /usr/include/sys/ttydefaults.h \
+  /usr/include/linux/if.h /usr/include/linux/types.h \
+  /usr/include/linux/posix_types.h /usr/include/linux/stddef.h \
+  /usr/include/asm/posix_types.h /usr/include/asm/types.h \
+  /usr/include/linux/socket.h /usr/include/linux/if_tun.h tun.h
+tun.c :
+/usr/include/syslog.h :
+/usr/include/sys/syslog.h :
+/usr/include/features.h :
+/usr/include/sys/cdefs.h :
+/usr/include/gnu/stubs.h :
+/usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stdarg.h :
+/usr/include/stdio.h :
+/usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stddef.h :
+/usr/include/bits/types.h :
+/usr/include/libio.h :
+/usr/include/_G_config.h :
+/usr/include/wchar.h :
+/usr/include/bits/wchar.h :
+/usr/include/gconv.h :
+/usr/include/bits/stdio_lim.h :
+/usr/include/bits/stdio.h :
+/usr/include/stdlib.h :
+/usr/include/sys/types.h :
+/usr/include/time.h :
+/usr/include/sys/socket.h :
+/usr/include/sys/uio.h :
+/usr/include/bits/uio.h :
+/usr/include/bits/socket.h :
+/usr/lib/gcc-lib/i386-redhat-linux/2.96/include/limits.h :
+/usr/lib/gcc-lib/i386-redhat-linux/2.96/include/syslimits.h :
+/usr/include/limits.h :
+/usr/include/bits/sockaddr.h :
+/usr/include/asm/socket.h :
+/usr/include/asm/sockios.h :
+/usr/include/netinet/in.h :
+/usr/include/stdint.h :
+/usr/include/bits/wordsize.h :
+/usr/include/bits/in.h :
+/usr/include/endian.h :
+/usr/include/bits/endian.h :
+/usr/include/bits/byteswap.h :
+/usr/include/arpa/inet.h :
+/usr/include/sys/stat.h :
+/usr/include/bits/stat.h :
+/usr/include/sys/time.h :
+/usr/include/bits/time.h :
+/usr/include/sys/select.h :
+/usr/include/bits/select.h :
+/usr/include/bits/sigset.h :
+/usr/include/unistd.h :
+/usr/include/bits/posix_opt.h :
+/usr/include/bits/confname.h :
+/usr/include/string.h :
+/usr/include/bits/string.h :
+/usr/include/bits/string2.h :
+/usr/include/errno.h :
+/usr/include/bits/errno.h :
+/usr/include/linux/errno.h :
+/usr/include/asm/errno.h :
+/usr/include/fcntl.h :
+/usr/include/bits/fcntl.h :
+/usr/include/sys/ioctl.h :
+/usr/include/bits/ioctls.h :
+/usr/include/asm/ioctls.h :
+/usr/include/asm/ioctl.h :
+/usr/include/bits/ioctl-types.h :
+/usr/include/sys/ttydefaults.h :
+/usr/include/linux/if.h :
+/usr/include/linux/types.h :
+/usr/include/linux/posix_types.h :
+/usr/include/linux/stddef.h :
+/usr/include/asm/posix_types.h :
+/usr/include/asm/types.h :
+/usr/include/linux/socket.h :
+/usr/include/linux/if_tun.h :
+tun.h :
diff --git a/ggsn/Makefile b/ggsn/Makefile
new file mode 100644
index 0000000..1403f43
--- /dev/null
+++ b/ggsn/Makefile
@@ -0,0 +1,343 @@
+# Generated automatically from Makefile.in by configure.
+# Makefile.in generated automatically by automake 1.4 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = /bin/sh
+
+srcdir = .
+top_srcdir = ..
+prefix = /usr/local
+exec_prefix = ${prefix}
+
+bindir = ${exec_prefix}/bin
+sbindir = ${exec_prefix}/sbin
+libexecdir = ${exec_prefix}/libexec
+datadir = ${prefix}/share
+sysconfdir = ${prefix}/etc
+sharedstatedir = ${prefix}/com
+localstatedir = ${prefix}/var
+libdir = ${exec_prefix}/lib
+infodir = ${prefix}/info
+mandir = ${prefix}/man
+includedir = ${prefix}/include
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/OpenGGSN
+pkglibdir = $(libdir)/OpenGGSN
+pkgincludedir = $(includedir)/OpenGGSN
+
+top_builddir = ..
+
+ACLOCAL = aclocal
+AUTOCONF = autoconf
+AUTOMAKE = automake
+AUTOHEADER = autoheader
+
+INSTALL = /usr/bin/install -c
+INSTALL_PROGRAM = ${INSTALL} $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_SCRIPT = ${INSTALL_PROGRAM}
+transform = s,x,x,
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = i686-pc-linux
+host_triplet = i686-pc-linux-gnu
+AS = @AS@
+AWK = gawk
+CC = gcc
+DLLTOOL = @DLLTOOL@
+LIBTOOL = $(SHELL) $(top_builddir)/libtool
+LN_S = ln -s
+MAKEINFO = makeinfo
+OBJDUMP = @OBJDUMP@
+PACKAGE = OpenGGSN
+RANLIB = ranlib
+VERSION = 0.5
+
+bin_PROGRAMS = ggsn
+
+CFLAGS = -O2 -fno-builtin -Wall -ansi -DSBINDIR='"$(sbindir)"' -lgtp
+
+ggsn_SOURCES = ggsn.c tun.c tun.h cmdline.c cmdline.h
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_CLEAN_FILES = 
+PROGRAMS =  $(bin_PROGRAMS)
+
+
+DEFS =  -DSTDC_HEADERS=1 -DHAVE_SYS_WAIT_H=1 -DHAVE_FCNTL_H=1 -DHAVE_STRINGS_H=1 -DHAVE_SYS_IOCTL_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_SYSLOG_H=1 -DHAVE_UNISTD_H=1 -DTIME_WITH_SYS_TIME=1 -DHAVE_SELECT=1 -DHAVE_SOCKET=1 -DHAVE_STRDUP=1 -DHAVE_STRERROR=1 -DHAVE_STRTOUL=1 -DPACKAGE=\"OpenGGSN\" -DVERSION=\"0.5\"  -I. -I$(srcdir) 
+CPPFLAGS = 
+LDFLAGS = 
+LIBS = 
+ggsn_OBJECTS =  ggsn.o tun.o cmdline.o
+ggsn_LDADD = $(LDADD)
+ggsn_DEPENDENCIES = 
+ggsn_LDFLAGS = 
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = gtar
+GZIP_ENV = --best
+DEP_FILES =  .deps/cmdline.P .deps/ggsn.P .deps/tun.P
+SOURCES = $(ggsn_SOURCES)
+OBJECTS = $(ggsn_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .lo .o .s
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu ggsn/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-binPROGRAMS:
+
+clean-binPROGRAMS:
+	-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+distclean-binPROGRAMS:
+
+maintainer-clean-binPROGRAMS:
+
+install-binPROGRAMS: $(bin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(bindir)
+	@list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    echo " $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
+	    $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+	  else :; fi; \
+	done
+
+uninstall-binPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+	done
+
+.s.o:
+	$(COMPILE) -c $<
+
+.S.o:
+	$(COMPILE) -c $<
+
+mostlyclean-compile:
+	-rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+	-rm -f *.tab.c
+
+maintainer-clean-compile:
+
+.s.lo:
+	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.S.lo:
+	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+
+maintainer-clean-libtool:
+
+ggsn: $(ggsn_OBJECTS) $(ggsn_DEPENDENCIES)
+	@rm -f ggsn
+	$(LINK) $(ggsn_LDFLAGS) $(ggsn_OBJECTS) $(ggsn_LDADD) $(LIBS)
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	here=`pwd` && cd $(srcdir) \
+	  && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+	  || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+	-rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = ggsn
+
+distdir: $(DISTFILES)
+	here=`cd $(top_builddir) && pwd`; \
+	top_distdir=`cd $(top_distdir) && pwd`; \
+	distdir=`cd $(distdir) && pwd`; \
+	cd $(top_srcdir) \
+	  && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu ggsn/Makefile
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  if test -d $$d/$$file; then \
+	    cp -pr $$d/$$file $(distdir)/$$file; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	    || cp -p $$d/$$file $(distdir)/$$file || :; \
+	  fi; \
+	done
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+	-rm -rf .deps
+
+maintainer-clean-depend:
+
+%.o: %.c
+	@echo '$(COMPILE) -c $<'; \
+	$(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+	@-cp .deps/$(*F).pp .deps/$(*F).P; \
+	tr ' ' '\012' < .deps/$(*F).pp \
+	  | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+	    >> .deps/$(*F).P; \
+	rm .deps/$(*F).pp
+
+%.lo: %.c
+	@echo '$(LTCOMPILE) -c $<'; \
+	$(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+	@-sed -e 's/^\([^:]*\)\.o[ 	]*:/\1.lo \1.o :/' \
+	  < .deps/$(*F).pp > .deps/$(*F).P; \
+	tr ' ' '\012' < .deps/$(*F).pp \
+	  | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+	    >> .deps/$(*F).P; \
+	rm -f .deps/$(*F).pp
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am: install-binPROGRAMS
+install-exec: install-exec-am
+
+install-data-am:
+install-data: install-data-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am: uninstall-binPROGRAMS
+uninstall: uninstall-am
+all-am: Makefile $(PROGRAMS)
+all-redirect: all-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+	$(mkinstalldirs)  $(DESTDIR)$(bindir)
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-rm -f Makefile $(CONFIG_CLEAN_FILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-binPROGRAMS mostlyclean-compile \
+		mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+		mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-binPROGRAMS clean-compile clean-libtool clean-tags \
+		clean-depend clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-binPROGRAMS distclean-compile distclean-libtool \
+		distclean-tags distclean-depend distclean-generic \
+		clean-am
+	-rm -f libtool
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-binPROGRAMS \
+		maintainer-clean-compile maintainer-clean-libtool \
+		maintainer-clean-tags maintainer-clean-depend \
+		maintainer-clean-generic distclean-am
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
+maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile mostlyclean-libtool distclean-libtool \
+clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir \
+mostlyclean-depend distclean-depend clean-depend \
+maintainer-clean-depend info-am info dvi-am dvi check check-am \
+installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+cmdline.c: cmdline.ggo
+	gengetopt < cmdline.ggo --unamed-opts
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/ggsn/Makefile.am b/ggsn/Makefile.am
new file mode 100644
index 0000000..05211a6
--- /dev/null
+++ b/ggsn/Makefile.am
@@ -0,0 +1,11 @@
+bin_PROGRAMS = ggsn
+
+CFLAGS = -O2 -fno-builtin -Wall -ansi -DSBINDIR='"$(sbindir)"' -lgtp
+
+ggsn_SOURCES = ggsn.c tun.c tun.h cmdline.c cmdline.h
+
+cmdline.c: cmdline.ggo
+	gengetopt < cmdline.ggo --unamed-opts
+
+
+
diff --git a/ggsn/Makefile.in b/ggsn/Makefile.in
new file mode 100644
index 0000000..6fc4bcd
--- /dev/null
+++ b/ggsn/Makefile.in
@@ -0,0 +1,343 @@
+# Makefile.in generated automatically by automake 1.4 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+AS = @AS@
+AWK = @AWK@
+CC = @CC@
+DLLTOOL = @DLLTOOL@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+MAKEINFO = @MAKEINFO@
+OBJDUMP = @OBJDUMP@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+VERSION = @VERSION@
+
+bin_PROGRAMS = ggsn
+
+CFLAGS = -O2 -fno-builtin -Wall -ansi -DSBINDIR='"$(sbindir)"' -lgtp
+
+ggsn_SOURCES = ggsn.c tun.c tun.h cmdline.c cmdline.h
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_CLEAN_FILES = 
+PROGRAMS =  $(bin_PROGRAMS)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) 
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+ggsn_OBJECTS =  ggsn.o tun.o cmdline.o
+ggsn_LDADD = $(LDADD)
+ggsn_DEPENDENCIES = 
+ggsn_LDFLAGS = 
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON =  Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = gtar
+GZIP_ENV = --best
+DEP_FILES =  .deps/cmdline.P .deps/ggsn.P .deps/tun.P
+SOURCES = $(ggsn_SOURCES)
+OBJECTS = $(ggsn_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .lo .o .s
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu ggsn/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-binPROGRAMS:
+
+clean-binPROGRAMS:
+	-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+distclean-binPROGRAMS:
+
+maintainer-clean-binPROGRAMS:
+
+install-binPROGRAMS: $(bin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(bindir)
+	@list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    echo " $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
+	    $(LIBTOOL)  --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+	  else :; fi; \
+	done
+
+uninstall-binPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	list='$(bin_PROGRAMS)'; for p in $$list; do \
+	  rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+	done
+
+.s.o:
+	$(COMPILE) -c $<
+
+.S.o:
+	$(COMPILE) -c $<
+
+mostlyclean-compile:
+	-rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+	-rm -f *.tab.c
+
+maintainer-clean-compile:
+
+.s.lo:
+	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.S.lo:
+	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+
+maintainer-clean-libtool:
+
+ggsn: $(ggsn_OBJECTS) $(ggsn_DEPENDENCIES)
+	@rm -f ggsn
+	$(LINK) $(ggsn_LDFLAGS) $(ggsn_OBJECTS) $(ggsn_LDADD) $(LIBS)
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	here=`pwd` && cd $(srcdir) \
+	  && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+	  || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+	-rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = ggsn
+
+distdir: $(DISTFILES)
+	here=`cd $(top_builddir) && pwd`; \
+	top_distdir=`cd $(top_distdir) && pwd`; \
+	distdir=`cd $(distdir) && pwd`; \
+	cd $(top_srcdir) \
+	  && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu ggsn/Makefile
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  if test -d $$d/$$file; then \
+	    cp -pr $$d/$$file $(distdir)/$$file; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	    || cp -p $$d/$$file $(distdir)/$$file || :; \
+	  fi; \
+	done
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+	-rm -rf .deps
+
+maintainer-clean-depend:
+
+%.o: %.c
+	@echo '$(COMPILE) -c $<'; \
+	$(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+	@-cp .deps/$(*F).pp .deps/$(*F).P; \
+	tr ' ' '\012' < .deps/$(*F).pp \
+	  | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+	    >> .deps/$(*F).P; \
+	rm .deps/$(*F).pp
+
+%.lo: %.c
+	@echo '$(LTCOMPILE) -c $<'; \
+	$(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+	@-sed -e 's/^\([^:]*\)\.o[ 	]*:/\1.lo \1.o :/' \
+	  < .deps/$(*F).pp > .deps/$(*F).P; \
+	tr ' ' '\012' < .deps/$(*F).pp \
+	  | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+	    >> .deps/$(*F).P; \
+	rm -f .deps/$(*F).pp
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am: install-binPROGRAMS
+install-exec: install-exec-am
+
+install-data-am:
+install-data: install-data-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am: uninstall-binPROGRAMS
+uninstall: uninstall-am
+all-am: Makefile $(PROGRAMS)
+all-redirect: all-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+	$(mkinstalldirs)  $(DESTDIR)$(bindir)
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-rm -f Makefile $(CONFIG_CLEAN_FILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-binPROGRAMS mostlyclean-compile \
+		mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+		mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-binPROGRAMS clean-compile clean-libtool clean-tags \
+		clean-depend clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-binPROGRAMS distclean-compile distclean-libtool \
+		distclean-tags distclean-depend distclean-generic \
+		clean-am
+	-rm -f libtool
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-binPROGRAMS \
+		maintainer-clean-compile maintainer-clean-libtool \
+		maintainer-clean-tags maintainer-clean-depend \
+		maintainer-clean-generic distclean-am
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
+maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile mostlyclean-libtool distclean-libtool \
+clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir \
+mostlyclean-depend distclean-depend clean-depend \
+maintainer-clean-depend info-am info dvi-am dvi check check-am \
+installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+cmdline.c: cmdline.ggo
+	gengetopt < cmdline.ggo --unamed-opts
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/ggsn/cmdline.c b/ggsn/cmdline.c
new file mode 100644
index 0000000..2d07644
--- /dev/null
+++ b/ggsn/cmdline.c
@@ -0,0 +1,529 @@
+/*
+  File autogenerated by gengetopt version 2.8rc
+  generated with the following command:
+  ../../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:
+  we make no copyright claims on it.
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+/* If we use autoconf.  */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+/* Check for configure's getopt check result.  */
+#ifndef HAVE_GETOPT_LONG
+#include "getopt.h"
+#else
+#include <getopt.h>
+#endif
+
+#ifndef HAVE_STRDUP
+#define strdup gengetopt_strdup
+#endif /* HAVE_STRDUP */
+
+#include "cmdline.h"
+
+
+void
+cmdline_parser_print_version (void)
+{
+  printf ("%s %s\n", PACKAGE, VERSION);
+}
+
+void
+cmdline_parser_print_help (void)
+{
+  cmdline_parser_print_version ();
+  printf("\n"
+  "Usage: %s [OPTIONS]...\n", PACKAGE);
+  printf("   -h         --help             Print help and exit\n");
+  printf("   -V         --version          Print version and exit\n");
+  printf("   -f         --fg               Run in foreground (default=off)\n");
+  printf("   -d         --debug            Run in debug mode (default=off)\n");
+  printf("   -cSTRING   --conf=STRING      Read configuration file (default='/etc/ggsn.conf')\n");
+  printf("              --pidfile=STRING   Filename of process id file (default='/var/run/ggsn.pid')\n");
+  printf("              --statedir=STRING  Directory of nonvolatile data (default='/var/lib/ggsn/')\n");
+  printf("   -lSTRING   --listen=STRING    Local interface\n");
+  printf("   -nSTRING   --net=STRING       Network (default='192.168.0.0')\n");
+  printf("              --mask=STRING      Network mask (default='255.255.255.0')\n");
+  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");
+}
+
+
+#ifndef HAVE_STRDUP
+/* gengetopt_strdup(): automatically generated from strdup.c. */
+/* strdup.c replacement of strdup, which is not standard */
+static char *
+gengetopt_strdup (const char *s)
+{
+  char *result = (char*)malloc(strlen(s) + 1);
+  if (result == (char*)0)
+    return (char*)0;
+  strcpy(result, s);
+  return result;
+}
+#endif /* HAVE_STRDUP */
+
+int
+cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+{
+  int c;	/* Character of the parsed option.  */
+  int missing_required_options = 0;
+
+  args_info->help_given = 0 ;
+  args_info->version_given = 0 ;
+  args_info->fg_given = 0 ;
+  args_info->debug_given = 0 ;
+  args_info->conf_given = 0 ;
+  args_info->pidfile_given = 0 ;
+  args_info->statedir_given = 0 ;
+  args_info->listen_given = 0 ;
+  args_info->net_given = 0 ;
+  args_info->mask_given = 0 ;
+  args_info->timelimit_given = 0 ;
+  args_info->apn_given = 0 ;
+  args_info->qos_given = 0 ;
+#define clear_args() { \
+  args_info->fg_flag = 0;\
+  args_info->debug_flag = 0;\
+  args_info->conf_arg = strdup("/etc/ggsn.conf") ;\
+  args_info->pidfile_arg = strdup("/var/run/ggsn.pid") ;\
+  args_info->statedir_arg = strdup("/var/lib/ggsn/") ;\
+  args_info->listen_arg = NULL; \
+  args_info->net_arg = strdup("192.168.0.0") ;\
+  args_info->mask_arg = strdup("255.255.255.0") ;\
+  args_info->timelimit_arg = 0 ;\
+  args_info->apn_arg = strdup("internet") ;\
+  args_info->qos_arg = 0x0b921f ;\
+}
+
+  clear_args();
+
+  optarg = 0;
+  optind = 1;
+  opterr = 1;
+  optopt = '?';
+
+  while (1)
+    {
+      int option_index = 0;
+      char *stop_char;
+      static struct option long_options[] = {
+        { "help",	0, NULL, 'h' },
+        { "version",	0, NULL, 'V' },
+        { "fg",	0, NULL, 'f' },
+        { "debug",	0, NULL, 'd' },
+        { "conf",	1, NULL, 'c' },
+        { "pidfile",	1, NULL, 0 },
+        { "statedir",	1, NULL, 0 },
+        { "listen",	1, NULL, 'l' },
+        { "net",	1, NULL, 'n' },
+        { "mask",	1, NULL, 0 },
+        { "timelimit",	1, NULL, 0 },
+        { "apn",	1, NULL, 'a' },
+        { "qos",	1, NULL, 'q' },
+        { NULL,	0, NULL, 0 }
+      };
+
+      c = getopt_long (argc, argv, "hVfdc:l:n:a:q:", long_options, &option_index);
+
+      if (c == -1) break;	/* Exit from `while (1)' loop.  */
+
+      switch (c)
+        {
+        case 'h':	/* Print help and exit.  */
+          clear_args ();
+          cmdline_parser_print_help ();
+          exit (EXIT_SUCCESS);
+
+        case 'V':	/* Print version and exit.  */
+          clear_args ();
+          cmdline_parser_print_version ();
+          exit (EXIT_SUCCESS);
+
+        case 'f':	/* Run in foreground.  */
+          if (args_info->fg_given)
+            {
+              fprintf (stderr, "%s: `--fg' (`-f') option given more than once\n", PACKAGE);
+              clear_args ();
+              exit (EXIT_FAILURE);
+            }
+          args_info->fg_given = 1;
+          args_info->fg_flag = !(args_info->fg_flag);
+          break;
+
+        case 'd':	/* Run in debug mode.  */
+          if (args_info->debug_given)
+            {
+              fprintf (stderr, "%s: `--debug' (`-d') option given more than once\n", PACKAGE);
+              clear_args ();
+              exit (EXIT_FAILURE);
+            }
+          args_info->debug_given = 1;
+          args_info->debug_flag = !(args_info->debug_flag);
+          break;
+
+        case 'c':	/* Read configuration file.  */
+          if (args_info->conf_given)
+            {
+              fprintf (stderr, "%s: `--conf' (`-c') option given more than once\n", PACKAGE);
+              clear_args ();
+              exit (EXIT_FAILURE);
+            }
+          args_info->conf_given = 1;
+          args_info->conf_arg = strdup (optarg);
+          break;
+
+        case 'l':	/* Local interface.  */
+          if (args_info->listen_given)
+            {
+              fprintf (stderr, "%s: `--listen' (`-l') option given more than once\n", PACKAGE);
+              clear_args ();
+              exit (EXIT_FAILURE);
+            }
+          args_info->listen_given = 1;
+          args_info->listen_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)
+            {
+              fprintf (stderr, "%s: `--apn' (`-a') option given more than once\n", PACKAGE);
+              clear_args ();
+              exit (EXIT_FAILURE);
+            }
+          args_info->apn_given = 1;
+          args_info->apn_arg = strdup (optarg);
+          break;
+
+        case 'q':	/* Requested quality of service.  */
+          if (args_info->qos_given)
+            {
+              fprintf (stderr, "%s: `--qos' (`-q') option given more than once\n", PACKAGE);
+              clear_args ();
+              exit (EXIT_FAILURE);
+            }
+          args_info->qos_given = 1;
+          args_info->qos_arg = strtol (optarg,&stop_char,0);
+          break;
+
+
+        case 0:	/* Long option with no short option */
+          /* Filename of process id file.  */
+          if (strcmp (long_options[option_index].name, "pidfile") == 0)
+          {
+            if (args_info->pidfile_given)
+              {
+                fprintf (stderr, "%s: `--pidfile' option given more than once\n", PACKAGE);
+                clear_args ();
+                exit (EXIT_FAILURE);
+              }
+            args_info->pidfile_given = 1;
+            args_info->pidfile_arg = strdup (optarg);
+            break;
+          }
+          /* Directory of nonvolatile data.  */
+          else if (strcmp (long_options[option_index].name, "statedir") == 0)
+          {
+            if (args_info->statedir_given)
+              {
+                fprintf (stderr, "%s: `--statedir' option given more than once\n", PACKAGE);
+                clear_args ();
+                exit (EXIT_FAILURE);
+              }
+            args_info->statedir_given = 1;
+            args_info->statedir_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;
+          }
+          /* Exit after timelimit seconds.  */
+          else if (strcmp (long_options[option_index].name, "timelimit") == 0)
+          {
+            if (args_info->timelimit_given)
+              {
+                fprintf (stderr, "%s: `--timelimit' option given more than once\n", PACKAGE);
+                clear_args ();
+                exit (EXIT_FAILURE);
+              }
+            args_info->timelimit_given = 1;
+            args_info->timelimit_arg = strtol (optarg,&stop_char,0);
+            break;
+          }
+
+        case '?':	/* Invalid option.  */
+          /* `getopt_long' already printed an error message.  */
+          exit (EXIT_FAILURE);
+
+        default:	/* bug: option not considered.  */
+          fprintf (stderr, "%s: option unknown: %c\n", PACKAGE, c);
+          abort ();
+        } /* switch */
+    } /* while */
+
+
+  if ( missing_required_options )
+    exit (EXIT_FAILURE);
+
+  return 0;
+}
+
+#define CONFIGPARSERBUFSIZE 1024
+
+int
+cmdline_parser_configfile (char * const filename, struct gengetopt_args_info *args_info, int override)
+{
+  FILE* file;
+  char linebuf[CONFIGPARSERBUFSIZE];
+  int line_num = 0;
+  int len;
+  int fnum;
+  char fopt[CONFIGPARSERBUFSIZE], farg[CONFIGPARSERBUFSIZE];
+  char *stop_char;
+
+  if ((file = fopen(filename, "r")) == NULL)
+    {
+      fprintf (stderr, "%s: Error opening configuration file '%s'\n",
+               PACKAGE, filename);
+      exit (EXIT_FAILURE);
+    }
+
+  while ((fgets(linebuf, CONFIGPARSERBUFSIZE, file)) != NULL)
+    {
+      ++line_num;
+      len = strlen(linebuf);
+      if (len == CONFIGPARSERBUFSIZE-1)
+        {
+          fprintf (stderr, "%s: Line longer than %d characters found in configuration file '%s'\n",
+                   PACKAGE, CONFIGPARSERBUFSIZE, filename);
+          exit (EXIT_FAILURE);
+        }
+
+      if (linebuf[0] == '#')
+        continue; /* Line was a comment */
+    
+      /* Get the option */
+      if ((fnum = sscanf(linebuf, "%s %s", fopt, farg)) > 0)
+        {
+          if (!strcmp(fopt, "help"))
+            {
+              if (override || !args_info->help_given)
+                {
+                  args_info->help_given = 1;
+                  
+                }
+              continue;
+            }
+          if (!strcmp(fopt, "version"))
+            {
+              if (override || !args_info->version_given)
+                {
+                  args_info->version_given = 1;
+                  
+                }
+              continue;
+            }
+          if (!strcmp(fopt, "fg"))
+            {
+              if (override || !args_info->fg_given)
+                {
+                  args_info->fg_given = 1;
+                  args_info->fg_flag = !(args_info->fg_flag);
+                }
+              continue;
+            }
+          if (!strcmp(fopt, "debug"))
+            {
+              if (override || !args_info->debug_given)
+                {
+                  args_info->debug_given = 1;
+                  args_info->debug_flag = !(args_info->debug_flag);
+                }
+              continue;
+            }
+          if (!strcmp(fopt, "conf"))
+            {
+              if (override || !args_info->conf_given)
+                {
+                  args_info->conf_given = 1;
+                  if (fnum == 2)
+                    args_info->conf_arg = strdup (farg);
+                  else
+                    {
+                      fprintf (stderr, "%s:%d: required <option_name> <option_val>\n",
+                               filename, line_num);
+                      exit (EXIT_FAILURE);
+                    }
+                }
+              continue;
+            }
+          if (!strcmp(fopt, "pidfile"))
+            {
+              if (override || !args_info->pidfile_given)
+                {
+                  args_info->pidfile_given = 1;
+                  if (fnum == 2)
+                    args_info->pidfile_arg = strdup (farg);
+                  else
+                    {
+                      fprintf (stderr, "%s:%d: required <option_name> <option_val>\n",
+                               filename, line_num);
+                      exit (EXIT_FAILURE);
+                    }
+                }
+              continue;
+            }
+          if (!strcmp(fopt, "statedir"))
+            {
+              if (override || !args_info->statedir_given)
+                {
+                  args_info->statedir_given = 1;
+                  if (fnum == 2)
+                    args_info->statedir_arg = strdup (farg);
+                  else
+                    {
+                      fprintf (stderr, "%s:%d: required <option_name> <option_val>\n",
+                               filename, line_num);
+                      exit (EXIT_FAILURE);
+                    }
+                }
+              continue;
+            }
+          if (!strcmp(fopt, "listen"))
+            {
+              if (override || !args_info->listen_given)
+                {
+                  args_info->listen_given = 1;
+                  if (fnum == 2)
+                    args_info->listen_arg = strdup (farg);
+                  else
+                    {
+                      fprintf (stderr, "%s:%d: required <option_name> <option_val>\n",
+                               filename, line_num);
+                      exit (EXIT_FAILURE);
+                    }
+                }
+              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, "timelimit"))
+            {
+              if (override || !args_info->timelimit_given)
+                {
+                  args_info->timelimit_given = 1;
+                  if (fnum == 2)
+                    args_info->timelimit_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, "apn"))
+            {
+              if (override || !args_info->apn_given)
+                {
+                  args_info->apn_given = 1;
+                  if (fnum == 2)
+                    args_info->apn_arg = strdup (farg);
+                  else
+                    {
+                      fprintf (stderr, "%s:%d: required <option_name> <option_val>\n",
+                               filename, line_num);
+                      exit (EXIT_FAILURE);
+                    }
+                }
+              continue;
+            }
+          if (!strcmp(fopt, "qos"))
+            {
+              if (override || !args_info->qos_given)
+                {
+                  args_info->qos_given = 1;
+                  if (fnum == 2)
+                    args_info->qos_arg = strtol (farg,&stop_char,0);
+                  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! */
+          fprintf (stderr, "%s: Unknown option '%s' found in %s\n",
+                   PACKAGE, fopt, filename);
+          exit (EXIT_FAILURE);
+        }
+    } /* while */
+  fclose(file); /* No error checking on close */
+
+  return 0;
+}
diff --git a/ggsn/cmdline.ggo b/ggsn/cmdline.ggo
new file mode 100644
index 0000000..5d3e601
--- /dev/null
+++ b/ggsn/cmdline.ggo
@@ -0,0 +1,29 @@
+#  OpenGGSN - Gateway GPRS Support Node
+#  Copyright (C) 2002 Mondru AB.
+#  
+#  The contents of this file may be used under the terms of the GNU
+#  General Public License Version 2, provided that the above copyright
+#  notice and this permission notice is included in all copies or
+#  substantial portions of the software.
+#  
+#  The initial developer of the original code is
+#  Jens Jakobsen <jj@openggsn.org>
+#  
+#  Contributor(s):
+
+
+option  "fg"          f "Run in foreground"             flag   off
+option  "debug"       d "Run in debug mode"             flag   off
+
+option  "conf"        c "Read configuration file"       string default="/etc/ggsn.conf" no
+option  "pidfile"     - "Filename of process id file"   string default="/var/run/ggsn.pid" no
+option  "statedir"    - "Directory of nonvolatile data" string default="/var/lib/ggsn/" no
+
+option  "listen"      l "Local interface"               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  "timelimit"   - "Exit after timelimit seconds"  int default="0" no
+
+option  "apn"         a "Access point name"             string default="internet" no
+option  "qos"         q "Requested quality of service"  int    default="0x0b921f" no
diff --git a/ggsn/cmdline.h b/ggsn/cmdline.h
new file mode 100644
index 0000000..e08cfe8
--- /dev/null
+++ b/ggsn/cmdline.h
@@ -0,0 +1,61 @@
+/* cmdline.h */
+
+/* File autogenerated by gengetopt version 2.8rc  */
+
+#ifndef _cmdline_h
+#define _cmdline_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* Don't define PACKAGE and VERSION if we use automake.  */
+#ifndef PACKAGE
+#define PACKAGE ""
+#endif
+
+#ifndef VERSION
+#define VERSION ""
+#endif
+
+struct gengetopt_args_info
+{
+  int fg_flag;	/* Run in foreground (default=off).  */
+  int debug_flag;	/* Run in debug mode (default=off).  */
+  char * conf_arg;	/* Read configuration file (default='/etc/ggsn.conf').  */
+  char * pidfile_arg;	/* Filename of process id file (default='/var/run/ggsn.pid').  */
+  char * statedir_arg;	/* Directory of nonvolatile data (default='/var/lib/ggsn/').  */
+  char * listen_arg;	/* Local interface.  */
+  char * net_arg;	/* Network (default='192.168.0.0').  */
+  char * mask_arg;	/* Network mask (default='255.255.255.0').  */
+  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').  */
+
+  int help_given ;	/* Whether help was given.  */
+  int version_given ;	/* Whether version was given.  */
+  int fg_given ;	/* Whether fg was given.  */
+  int debug_given ;	/* Whether debug was given.  */
+  int conf_given ;	/* Whether conf was given.  */
+  int pidfile_given ;	/* Whether pidfile was given.  */
+  int statedir_given ;	/* Whether statedir was given.  */
+  int listen_given ;	/* Whether listen was given.  */
+  int net_given ;	/* Whether net was given.  */
+  int mask_given ;	/* Whether mask was given.  */
+  int timelimit_given ;	/* Whether timelimit was given.  */
+  int apn_given ;	/* Whether apn was given.  */
+  int qos_given ;	/* Whether qos was given.  */
+
+} ;
+
+int cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info);
+
+void cmdline_parser_print_help(void);
+void cmdline_parser_print_version(void);
+
+int cmdline_parser_configfile (char * const filename, struct gengetopt_args_info *args_info, int override);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* _cmdline_h */
diff --git a/ggsn/ggsn.c b/ggsn/ggsn.c
new file mode 100644
index 0000000..a850de8
--- /dev/null
+++ b/ggsn/ggsn.c
@@ -0,0 +1,424 @@
+/* 
+ *  OpenGGSN - Gateway GPRS Support Node
+ *  Copyright (C) 2002 Mondru AB.
+ * 
+ *  The contents of this file may be used under the terms of the GNU
+ *  General Public License Version 2, provided that the above copyright
+ *  notice and this permission notice is included in all copies or
+ *  substantial portions of the software.
+ * 
+ *  The initial developer of the original code is
+ *  Jens Jakobsen <jj@openggsn.org>
+ * 
+ *  Contributor(s):
+ * 
+ */
+
+/* ggsn.c
+ *
+ */
+
+#ifdef __linux__
+#define _GNU_SOURCE 1		/* strdup() prototype, broken arpa/inet.h */
+#endif
+
+
+#include <syslog.h>
+#include <ctype.h>
+#include <netdb.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <sys/socket.h>  
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <features.h>
+
+#include <errno.h>
+
+#include <asm/types.h>
+#include <sys/socket.h>
+#include <linux/netlink.h> 
+
+#include <time.h>
+
+#include "tun.h"
+#include "../gtp/pdp.h"
+#include "../gtp/gtp.h"
+#include "cmdline.h"
+
+
+int maxfd = 0;	                /* For select() */
+int tun_fd = -1;		/* Network file descriptor */
+struct tun_t *tun;              /* TUN instance            */
+struct in_addr net, mask;       /* Network interface       */
+int debug;                      /* Print debug output */
+
+
+/* Used to write process ID to file. Assume someone else will delete */
+void log_pid(char *pidfile) {
+  FILE *file;
+  mode_t oldmask;
+  
+  oldmask = umask(022);
+  file = fopen(pidfile, "w");
+  umask(oldmask);
+  if(!file)
+    return;
+  fprintf(file, "%d\n", getpid());
+  fclose(file);
+}
+
+
+int encaps_printf(void *p, void *packet, unsigned len)
+{
+  int i;
+  if (debug) {
+    printf("The packet looks like this:\n");
+    for( i=0; i<len; i++) {
+      printf("%02x ", (unsigned char)*(char *)(packet+i));
+      if (!((i+1)%16)) printf("\n");
+    };
+    printf("\n"); 
+  }
+  return 0;
+}
+
+int 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_;
+
+  if (debug) {
+  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) {
+  pdp_ipdel(pdp);
+  return 0;
+}
+
+
+
+int create_context(struct pdp_t *pdp) {
+
+  if (debug) 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 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, "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 encaps_gtp(void *gsn, struct tun_t *tun, void *pack, unsigned len) {
+  struct pdp_t *pdp;
+  struct in_addr addr;
+  struct ul66_t eua;
+  /*printf("encaps_gtp. Packet received: forwarding to gtp.\n");*/
+  /* First we need to extract the IP destination address */
+  memcpy(&addr.s_addr, pack+16, 4); /* This ought to be dest addr */
+  pdp_ntoeua(&addr, &eua);
+  if (pdp_ipget(&pdp, tun, &eua) == 0) {
+    return gtp_gpdu((struct gsn_t*) gsn, pdp, pack, len);
+  }
+  else {
+    if (debug) printf("Received packet with no destination!!!\n");
+    return 0;
+  }
+}
+
+
+int encaps_tun(struct pdp_t *pdp, void *pack, unsigned len) {
+  /*  printf("encaps_tun. Packet received: forwarding to tun\n");*/
+  return tun_encaps((struct tun_t*) pdp->ipif, pack, len);
+}
+
+
+int main(int argc, char **argv)
+{
+  /* gengeopt declarations */
+  struct gengetopt_args_info args_info;
+
+  struct hostent *host;
+
+  struct in_addr listen;
+	
+  int gtpfd = -1;		/* Network file descriptor */
+  struct gsn_t *gsn;            /* GSN instance            */
+
+  fd_set fds;			/* For select() */
+  struct timeval idleTime;	/* How long to select() */
+  int i;                          /* for loop */
+
+  struct ul_t qos, apn;
+  unsigned char qosh[3], apnh[256];
+
+  int timelimit; /* Number of seconds to be connected */
+  int starttime; /* Time program was started */
+
+  /* open a connection to the syslog daemon */
+  /*openlog(PACKAGE, LOG_PID, LOG_DAEMON);*/
+  openlog(PACKAGE, (LOG_PID | LOG_PERROR), LOG_DAEMON);
+
+  if (cmdline_parser (argc, argv, &args_info) != 0)
+    exit(1);
+  if (args_info.debug_flag) {
+    printf("listen: %s\n", args_info.listen_arg);
+    printf("conf: %s\n", args_info.conf_arg);
+    printf("fg: %d\n", args_info.fg_flag);
+    printf("debug: %d\n", args_info.debug_flag);
+    printf("qos: %#08x\n", args_info.qos_arg);
+    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("pidfile: %s\n", args_info.pidfile_arg);
+    printf("statedir: %s\n", args_info.statedir_arg);
+    printf("timelimit: %d\n", args_info.timelimit_arg);
+  }
+
+  /* Try out our new parser */
+  
+  if (cmdline_parser_configfile (args_info.conf_arg, &args_info, 0) != 0)
+    exit(1);
+  if (args_info.debug_flag) {
+    printf("cmdline_parser_configfile\n");
+    printf("listen: %s\n", args_info.listen_arg);
+    printf("conf: %s\n", args_info.conf_arg);
+    printf("fg: %d\n", args_info.fg_flag);
+    printf("debug: %d\n", args_info.debug_flag);
+    printf("qos: %#08x\n", args_info.qos_arg);
+    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("pidfile: %s\n", args_info.pidfile_arg);
+    printf("statedir: %s\n", args_info.statedir_arg);
+    printf("timelimit: %d\n", args_info.timelimit_arg);
+  }
+
+  /* Handle each option */
+
+  /* foreground                                                   */
+  /* If flag not given run as a daemon                            */
+  if (!args_info.fg_flag)
+    {
+      closelog(); 
+      /* Close the standard file descriptors. */
+      /* Is this really needed ? */
+      freopen("/dev/null", "w", stdout);
+      freopen("/dev/null", "w", stderr);
+      freopen("/dev/null", "r", stdin);
+      daemon(0, 0);
+      /* Open log again. This time with new pid */
+      openlog(PACKAGE, LOG_PID, LOG_DAEMON);
+    }
+
+  /* debug                                                        */
+  debug = args_info.debug_flag;
+
+  /* pidfile */
+  /* This has to be done after we have our final pid */
+  if (args_info.pidfile_arg) {
+    log_pid(args_info.pidfile_arg);
+  }
+
+  /* listen                                                       */
+  /* If no listen option is specified listen to any local port    */
+  /* Do hostname lookup to translate hostname to IP address       */
+  if (args_info.listen_arg) {
+    if (!(host = gethostbyname(args_info.listen_arg))) {
+      fprintf(stderr, "%s: Invalid listening address: %s!\n", 
+	      PACKAGE, args_info.listen_arg);
+      syslog(LOG_ERR, "Invalid listening address: %s!", 
+	     args_info.listen_arg);
+      return 1;
+    }
+    else {
+      memcpy(&listen.s_addr, host->h_addr, host->h_length);
+    }
+  }
+  else {
+    listen.s_addr = htonl(INADDR_ANY);
+  }
+  
+  /* 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);
+      return 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);
+      return 1;
+    }
+  }
+
+  /* Timelimit                                                       */
+  timelimit = args_info.timelimit_arg;
+  starttime = time(NULL);
+  
+  /* qos                                                             */
+  qos.l = 3;
+  qos.v = qosh;
+  qos.v[2] = (args_info.qos_arg) & 0xff;
+  qos.v[1] = ((args_info.qos_arg) >> 8) & 0xff;
+  qos.v[0] = ((args_info.qos_arg) >> 16) & 0xff;
+  
+  /* apn                                                             */
+  if (strlen(args_info.apn_arg)>255) {
+    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);
+
+  if (debug) printf("gtpclient: Initialising GTP tunnel\n");
+  
+  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);
+  gtp_set_cb_delete_context(gsn, delete_context);
+  
+  gtp_set_cb_create_context(gsn, create_context);
+  create_tun();
+
+  /******************************************************************/
+  /* Main select loop                                               */
+  /******************************************************************/
+
+  while (((starttime + timelimit) > time(NULL)) || (0 == timelimit)) {
+	
+    FD_ZERO(&fds);
+    if (tun_fd != -1) FD_SET(tun_fd, &fds);
+    if (gtpfd != -1) FD_SET(gtpfd, &fds);
+    
+    gtp_retranstimeout(gsn, &idleTime);
+    switch (select(maxfd + 1, &fds, NULL, NULL, &idleTime)) {
+    case -1:	/* Error with select() *
+		   if (errno != EINTR)
+		   syslog(LOG_ERR, "CTRL: Error with select(), quitting");
+		   *goto leave_clear_call;*/
+      syslog(LOG_ERR, "GGSN: select = -1");
+      break;  
+    case 0:
+      gtp_retrans(gsn); /* Only retransmit if nothing else */
+      break; 
+    default:
+      break;
+    }
+
+    if (tun_fd != -1 && FD_ISSET(tun_fd, &fds) && 
+	tun_decaps(tun, encaps_gtp, gsn) < 0) {
+      syslog(LOG_ERR, "TUN read failed (fd)=(%d)", tun_fd);
+    }
+
+    if (gtpfd != -1 && FD_ISSET(gtpfd, &fds) && 
+	gtp_decaps(gsn) < 0) {
+      syslog(LOG_ERR, "GTP read failed (gre)=(%d)", gtpfd);
+    }
+    
+    
+    }
+
+  gtp_free(gsn);
+  
+  return 1;
+  
+}
+
diff --git a/ggsn/tun.c b/ggsn/tun.c
new file mode 100644
index 0000000..72ea264
--- /dev/null
+++ b/ggsn/tun.c
@@ -0,0 +1,128 @@
+/* 
+ *  OpenGGSN - Gateway GPRS Support Node
+ *  Copyright (C) 2002 Mondru AB.
+ * 
+ *  The contents of this file may be used under the terms of the GNU
+ *  General Public License Version 2, provided that the above copyright
+ *  notice and this permission notice is included in all copies or
+ *  substantial portions of the software.
+ * 
+ *  The initial developer of the original code is
+ *  Jens Jakobsen <jj@openggsn.org>
+ * 
+ *  Contributor(s):
+ * 
+ */
+
+/*
+ * tun.c: Contains all TUN functionality. Should be able to handle multiple
+ * tunnels in the same program. Each tunnel is identified by the socket. 
+ * I suppose that no other state information than the socket is needed.
+ *
+ *  - tun_newtun: Initialise TUN tunnel.
+ *  - tun_freetun: Free a device previously created with tun_newtun.
+ *  - tun_encaps: Encapsulate packet in TUN tunnel and send off
+ *  - tun_decaps: Extract packet from TUN tunnel and call function to
+ *    ship it off as GTP encapsulated packet. 
+ *
+ * TODO:
+ *  - Do we need to handle fragmentation?
+ */
+
+
+#include <syslog.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <linux/if.h>
+#include <errno.h>
+#include <linux/if_tun.h>
+
+
+#include "tun.h"
+
+
+int tun_newtun(struct tun_t **tun)
+{
+  struct ifreq ifr;
+
+  if (!(*tun = calloc(1, sizeof(struct tun_t)))) {
+    syslog(LOG_ERR, "%s %d. calloc(nmemb=%d, size=%d) failed: Error = %s(%d)",
+	   __FILE__, __LINE__, 1, sizeof(struct tun_t), 
+	   strerror(errno), errno);
+    return EOF;
+  }
+
+  if (((*tun)->fd  = open("/dev/net/tun", O_RDWR)) < 0) {
+    syslog(LOG_ERR, "TUN: open() failed");
+    return -1;
+  }
+
+  memset(&ifr, 0, sizeof(ifr));
+  ifr.ifr_flags = IFF_TUN | IFF_NO_PI; /* Tun device, no packet info */
+  strncpy(ifr.ifr_name, (*tun)->devname, IFNAMSIZ);
+
+  if (ioctl((*tun)->fd, TUNSETIFF, (void *) &ifr) < 0) {
+    syslog(LOG_ERR, "TUN: ioctl() failed");
+    close((*tun)->fd);
+    return -1;
+  } 
+
+  ioctl((*tun)->fd, TUNSETNOCSUM, 1); /* Disable checksums */
+
+  strncpy((*tun)->devname, ifr.ifr_name, IFNAMSIZ);
+
+  return (*tun)->fd;
+}
+
+int tun_freetun(struct tun_t *tun)
+{
+  if (close(tun->fd)) {
+    syslog(LOG_ERR, "%s %d. close(fd=%d) failed: Error = %s", 
+	   __FILE__, __LINE__, tun->fd, strerror(errno));
+    return EOF;
+  }
+  free(tun);
+  return 0;
+}
+
+
+int tun_decaps(struct tun_t *tun, 
+	       int (*cb) (void *cl, struct tun_t*, void *pack, unsigned len),
+	       void *cl)
+{
+	unsigned char buffer[PACKET_MAX + 64 /*TODO: ip header */ ];
+	int status;
+
+
+	if ((status = read(tun->fd, buffer, sizeof(buffer))) <= 0) {
+		syslog(LOG_ERR, "TUN: read(fd=%d,buffer=%lx,len=%d) from network failed: status = %d error = %s",
+		       tun->fd, (unsigned long) buffer, sizeof(buffer), status, status ? strerror(errno) : "No error");
+		return -1;
+	}
+
+	/* Need to include code to verify packet src and dest addresses */
+	return cb(cl, tun, buffer, status);
+}
+
+int tun_encaps(struct tun_t *tun, void *pack, unsigned len)
+{
+	return write(tun->fd, pack, len);
+}
diff --git a/ggsn/tun.h b/ggsn/tun.h
new file mode 100644
index 0000000..03dc7df
--- /dev/null
+++ b/ggsn/tun.h
@@ -0,0 +1,48 @@
+/* 
+ *  OpenGGSN - Gateway GPRS Support Node
+ *  Copyright (C) 2002 Mondru AB.
+ * 
+ *  The contents of this file may be used under the terms of the GNU
+ *  General Public License Version 2, provided that the above copyright
+ *  notice and this permission notice is included in all copies or
+ *  substantial portions of the software.
+ * 
+ *  The initial developer of the original code is
+ *  Jens Jakobsen <jj@openggsn.org>
+ * 
+ *  Contributor(s):
+ * 
+ */
+
+#ifndef _TUN_H
+#define _TUN_H
+
+#define hton8(x)  (x)
+#define ntoh8(x)  (x)
+#define hton16(x) htons(x)
+#define ntoh16(x) ntohs(x)
+#define hton32(x) htonl(x)
+#define ntoh32(x) ntohl(x)
+
+#define PACKET_MAX      8196 /* TODO */
+
+/* ***********************************************************
+ * Information storage for each tun instance
+ *************************************************************/
+
+struct tun_t {
+  int fd;                /* File descriptor to network interface */
+  struct in_addr addr;   /* IP address of tun interface */
+  char devname[IFNAMSIZ];/* Name of the tun device */
+};
+
+
+extern int tun_newtun(struct tun_t **tun);
+extern int tun_freetun(struct tun_t *tun);
+extern int tun_decaps(struct tun_t *tun, 
+     int (*cb) (void *cl, struct tun_t*, void *pack, unsigned len),
+		      void *cl);
+extern int tun_encaps(struct tun_t *tun, void *pack, unsigned len);
+
+
+#endif	/* !_TUN_H */