chiark / gitweb /
Import release 0.1.10 v0.1.10
authorStephen Early <steve@greenend.org.uk>
Mon, 22 Oct 2001 13:13:00 +0000 (14:13 +0100)
committerStephen Early <steve@greenend.org.uk>
Wed, 18 May 2011 17:35:59 +0000 (18:35 +0100)
22 files changed:
Makefile.in
NEWS
README
TODO
conffile.c
config.h.bot
config.h.in
configure
configure.in
debian/changelog
example.conf
ipaddr.c
log.c
make-secnet-sites
netlink.c
netlink.h
secnet.c
secnet.h
site.c
slip.c
transform.c
tun.c

index c8a67ad3a7e0885f9691a80d01caae95746169f8..0e4926c0b590a311c88336ffdb141678c0ac7fcc 100644 (file)
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-.PHONY:        all clean realclean dist install
+.PHONY:        all clean realclean dist install distclean
 
 PACKAGE:=secnet
-VERSION:=0.1.9
+VERSION:=0.1.10
 
 @SET_MAKE@
 
@@ -132,6 +132,8 @@ realclean:  clean
        config.log config.status config.cache \
        stamp-h Makefile.bak
 
+distclean:     realclean
+
 pfname:=$(PACKAGE)-$(VERSION)
 dist:
        $(RM) -rf $(pfname)
diff --git a/NEWS b/NEWS
index c26e086b55834ec383f74ba80318a24e1f39b6b4..be5c38ac77ff2b5a351976a472919920002a7fcc 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,13 +1,83 @@
 * Planned for the future
 
-New configuration syntax for netlinks: basic 'netlink' closure yields
-a pure closure that can be applied in each site() to generate a
-netlink for that site (with routes, options, etc.).  Works well for
-point-to-point: that netlink can be used directly by just one site.
-Much cleaner separation between site() and netlink code this way.
+Netlink device that implements an Ethernet bridge.
 
-(Backward compatibility will be kept for a while.)
+Modular transform code: choice of block ciphers, modes, sequence
+numbers / timestamps, etc. similar to IWJ's udptunnel
 
+* New in versino 0.1.11
+
+* New in version 0.1.10
+
+WARNING: THIS VERSION MAKES A CHANGE TO THE CONFIGURATION FILE FORMAT
+THAT IS NOT BACKWARD COMPATIBLE.  However, in most configurations the
+change only affects the sites.conf file, which is generated by the
+make-secnet-sites script; after you regenerate your sites.conf using
+version 0.1.10, everything should continue to work.
+
+Netlink devices now interact slightly differently with the 'site'
+code.  When you invoke a netlink closure like 'tun' or 'userv-ipif',
+you get another closure back.  You then invoke this closure (usually
+in the site definitions) to specify things like routes and options.
+The result of this invocation should be used as the 'link' option in
+site configurations.
+
+All this really means is that instead of site configurations looking
+like this:
+
+foo {
+       name "foo";
+       networks "a", "b", "c";
+       etc.
+};
+
+...they look like this:
+
+foo {
+       name "foo";
+       link netlink { routes "a", "b", "c"; };
+       etc.
+};
+
+This change was made to enable the 'site' code to be completely free
+of any knowledge of the contents of the packets it transmits.  It
+should now be possible in the future to tunnel other protocols like
+IPv6, IPX, raw Ethernet frames, etc. without changing the 'site' code
+at all.
+
+Point-to-point netlink devices work slightly differently; when you
+apply the 'tun', 'userv-ipif', etc. closure and specify the
+ptp-address option, you must also specify the 'routes' option.  The
+result of this invocation should be passed directly to the 'link'
+option of the site configuration.  You can do things like this:
+
+sites site {
+       name "foo";
+       link tun {
+               networks "192.168.73.76/32";
+               local-address "192.168.73.76"; # IP address of interface
+               ptp-address "192.168.73.75"; # IP address of other end of link
+               routes "192.168.73.74/32";
+               mtu 1400;
+               buffer sysbuffer();
+       };
+       etc.
+};
+
+The route dump obtained by sending SIGUSR1 to secnet now includes
+packet counts.
+
+Point-to-point mode has now been tested.
+
+tun-old has now been tested, and the annoying 'untested' message has
+been removed.  Thanks to SGT and JDA.
+
+secnet now closes its stdin, stdout and stderr just after
+backgrounding.
+
+Bugfix: specifying network "0.0.0.0/0" (or "default") now works
+correctly.
+               
 * New in version 0.1.9
 
 The netlink code may now generate ICMP responses to ICMP messages that
diff --git a/README b/README
index 255892d9eebb32cf9d336e2c57d3bfc8c1f12852..4fe279daa47c1a4a68e6129acaf18784e14902d8 100644 (file)
--- a/README
+++ b/README
@@ -34,6 +34,20 @@ providing complete links between multiple sites to a simple
 laptop-to-host link), read the section in this file on 'Creating a
 VPN'.
 
+* Mailing lists and bug reporting
+
+There are two mailing lists associated with secnet: an 'announce' list
+and a 'discuss' list.  Their addresses are:
+http://www.chiark.greenend.org.uk/mailman/listinfo/secnet-announce
+http://www.chiark.greenend.org.uk/mailman/listinfo/secnet-discuss
+
+The -announce list receives one message per secnet release.  The
+-discuss list is for general discussion, including help with
+configuration, bug reports, feature requests, etc.
+
+Bug reports should be sent to <steve@greenend.org.uk>; they will be
+forwarded to the -discuss list by me.
+
 * Creating a VPN
 
 XXX TODO
@@ -151,7 +165,17 @@ in configuration space to tell it what to do:
 
 * secnet command line options
 
-XXX TODO
+Usage: secnet [OPTION]...
+
+  -f, --silent, --quiet   suppress error messages
+  -w, --nowarnings        suppress warnings
+  -v, --verbose           output extra diagnostics
+  -c, --config=filename   specify a configuration file
+  -j, --just-check-config stop after reading configfile
+  -n, --nodetach          do not run in background
+  -d, --debug=item,...    set debug options
+      --help              display this help and exit
+      --version           output version information and exit
 
 * secnet builtin modules
 
@@ -247,7 +271,7 @@ Defines:
 site: dict argument
   local-name (string): this site's name for itself
   name (string): the name of the site's peer
-  netlink (netlink closure)
+  link (netlink closure)
   comm (comm closure)
   resolver (resolver closure)
   random (randomsrc closure)
@@ -255,7 +279,6 @@ site: dict argument
   address (string): optional, DNS name used to find our peer
   port (integer): mandatory if 'address' is specified: the port used
     to contact our peer
-  networks (string list): networks that our peer may claim traffic for
   key (rsapubkey closure): our peer's public key
   transform (transform closure): how to mangle packets sent between sites
   dh (dh closure)
@@ -282,12 +305,6 @@ site: dict argument
     dump-packets: every key setup packet we see
     errors: failure of name resolution, internal errors
     all: everything (too much!)
-  netlink-options (string list): options to pass to netlink device when
-    registering remote networks
-    soft: create 'soft' routes that go away when there's no key established
-      with the peer
-    allow-route: allow packets from our peer to be sent down other tunnels,
-      as well as to the host
 
 ** transform
 
@@ -297,7 +314,7 @@ Defines:
 ** netlink
 
 Defines:
-  null-netlink (closure => netlink closure)
+  null-netlink (closure => closure or netlink closure)
 
 null-netlink: dict argument
   name (string): name for netlink device, used in log messages
@@ -309,9 +326,20 @@ null-netlink: dict argument
   ptp-address (string): IP address of the other end of a point-to-point link
   mtu (integer): MTU of host's tunnel interface
 
-Only one of secnet-address or ptp-address may be specified. If
-point-to-point mode is in use then precisely one tunnel must register
-with the netlink device.
+Only one of secnet-address or ptp-address may be specified.  If
+point-to-point mode is in use then the "routes" option must also be
+specified, and netlink returns a netlink closure that should be used
+directly with the "link" option to the site closure.  If
+point-to-point mode is not in use then netlink returns a closure that
+may be invoked using a dict argument with the following keys to yield
+a netlink closure:
+  routes (string list): networks reachable down the tunnel attached to
+    this instance of netlink
+  options (string list):
+    allow-route: allow packets coming from this tunnel to be routed to
+      other tunnels as well as the host (used for mobile devices like laptops)
+    soft-route: remove these routes from the host's routing table when
+      the tunnel link quality is zero
 
 Netlink will dump its current routing table to the system/log on
 receipt of SIGUSR1.
diff --git a/TODO b/TODO
index f32d1097476838ed77cce3b189d0f19169b5e270..5ae53cf8cf4070b270c44950698b472112c63da6 100644 (file)
--- a/TODO
+++ b/TODO
@@ -7,7 +7,7 @@ ipaddr.c: implement the useful functionality from ipaddr.py
 
 netlink.c: investigate why 'default' routes don't appear to work
 (reported by JDA).
-Implement the 'allow_route' option properly.
+Test the 'allow_route' option properly.
 
 random.c: test
 
@@ -27,13 +27,11 @@ fails in use?
 userv-ipif doesn't like the same bit of network to be specified
 twice. Use the new functionality in ipaddr.c once it's done to prevent
 this.
-
-tun.c: jdamery reports tun-old code works on Linux-2.2.
-Unresolved problem with ioctl(TUNSETIFF) sometimes returning EINVAL, seems
-to be related to early 2.4.x (x<=5) series kernels. 2.4.9 and above seem ok;
-2.4.[678] untested.
+Work out why slip.c doesn't compile on Solaris-2.5.1
 
 transform.c: separate the transforms into multiple parts, which can
 then be combined in the configuration file.  Will allow the user to
 plug in different block ciphers, invent an authenticity-only mode,
 etc.
+
+udp.c: actually send NAKs rather than just complaining.
index e9c84d3cb4aa82fc9a49eeaea73d6f1eb8f0827b..f33354e6e075b36b38e2d20ad21c3c6ab9f2d5e1 100644 (file)
@@ -335,6 +335,9 @@ static list_t *process_invocation(dict_t *context, struct p_node *i)
     if (cl->type != t_closure) {
        cfgfatal(i->l->loc,"conffile","only closures can be invoked\n");
     }
+    if (!cl->data.closure->apply) {
+       cfgfatal(i->l->loc,"conffile","this closure cannot be invoked\n");
+    }
     args=process_ilist(context, i->r);
     return cl->data.closure->apply(cl->data.closure, i->loc, context, args);
 }
@@ -725,6 +728,13 @@ static struct subnet string_to_subnet(item_t *i, string_t desc)
        cfgfatal(i->loc,desc,"expecting a string (subnet specification)\n");
     }
 
+    if (strcmp(i->data.string,"default")==0) {
+       s.prefix=0;
+       s.mask=0;
+       s.len=0;
+       return s;
+    }
+
     /* We expect strings of the form "a.b.c.d[/n]", i.e. the dots are
        NOT optional. The subnet mask is optional; if missing it is assumed
        to be /32. */
@@ -740,7 +750,7 @@ static struct subnet string_to_subnet(item_t *i, string_t desc)
        cfgfatal(i->loc,desc,"\"%s\": range error\n",i->data.string);
     }
     s.prefix=(a<<24)|(b<<16)|(c<<8)|(d);
-    s.mask=(~0UL << (32-n));
+    s.mask=n?(~0UL << (32-n)):0;
     s.len=n;
     if (s.prefix & ~s.mask) {
        cfgfatal(i->loc,desc,"\"%s\": prefix not fully contained "
index 68a2684566da0891d37b506e973b470fec3b6b04..889736c5ee511249344e0b743ddecdaa1eda6805 100644 (file)
@@ -44,6 +44,8 @@ typedef unsigned char uint8_t;
 #endif
 
 #ifndef HAVE_SNPRINTF
+#include <stdio.h>
+#include <stdarg.h>
 #include "snprintf.h"
 #endif
 
index 1984cee58db302bc3c587915535b3fc0c1a6cdc9..d7044fcaab104aae7523d80cfd3c0909d9137f7f 100644 (file)
 
 /* Define if you have the gnugetopt library (-lgnugetopt).  */
 #undef HAVE_LIBGNUGETOPT
+
+/* Define if you have the nsl library (-lnsl).  */
+#undef HAVE_LIBNSL
+
+/* Define if you have the resolv library (-lresolv).  */
+#undef HAVE_LIBRESOLV
+
+/* Define if you have the socket library (-lsocket).  */
+#undef HAVE_LIBSOCKET
 /* -*- c -*- */
 
 /* These are from config.h.bot, pasted onto the end of config.h.in. */
@@ -125,6 +134,8 @@ typedef unsigned char uint8_t;
 #endif
 
 #ifndef HAVE_SNPRINTF
+#include <stdio.h>
+#include <stdarg.h>
 #include "snprintf.h"
 #endif
 
index fb7aef33e0afca7bff1d361a28f1e1b9a2a0c87f..3c5ffcb8df18d8f1511c0a2f875d0c04a330a2a3 100755 (executable)
--- a/configure
+++ b/configure
@@ -1549,8 +1549,55 @@ else
   echo "$ac_t""no" 1>&6
 fi
 
+echo $ac_n "checking for __gmpz_init_set_str in -lgmp""... $ac_c" 1>&6
+echo "configure:1554: checking for __gmpz_init_set_str in -lgmp" >&5
+ac_lib_var=`echo gmp'_'__gmpz_init_set_str | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lgmp  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1562 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char __gmpz_init_set_str();
+
+int main() {
+__gmpz_init_set_str()
+; return 0; }
+EOF
+if { (eval echo configure:1573: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_lib=HAVE_LIB`echo gmp | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+  LIBS="-lgmp $LIBS"
+
+else
+  echo "$ac_t""no" 1>&6
+fi
+
 echo $ac_n "checking for yywrap in -lfl""... $ac_c" 1>&6
-echo "configure:1554: checking for yywrap in -lfl" >&5
+echo "configure:1601: checking for yywrap in -lfl" >&5
 ac_lib_var=`echo fl'_'yywrap | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1558,7 +1605,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lfl  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1562 "configure"
+#line 1609 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -1569,7 +1616,7 @@ int main() {
 yywrap()
 ; return 0; }
 EOF
-if { (eval echo configure:1573: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1620: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -1596,27 +1643,27 @@ else
   echo "$ac_t""no" 1>&6
 fi
 
-echo $ac_n "checking for adns_init in -ladns""... $ac_c" 1>&6
-echo "configure:1601: checking for adns_init in -ladns" >&5
-ac_lib_var=`echo adns'_'adns_init | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for inet_ntoa in -lnsl""... $ac_c" 1>&6
+echo "configure:1648: checking for inet_ntoa in -lnsl" >&5
+ac_lib_var=`echo nsl'_'inet_ntoa | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   ac_save_LIBS="$LIBS"
-LIBS="-ladns  $LIBS"
+LIBS="-lnsl  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1609 "configure"
+#line 1656 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
     builtin and then its argument prototype would still apply.  */
-char adns_init();
+char inet_ntoa();
 
 int main() {
-adns_init()
+inet_ntoa()
 ; return 0; }
 EOF
-if { (eval echo configure:1620: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1667: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -1631,20 +1678,20 @@ LIBS="$ac_save_LIBS"
 fi
 if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
   echo "$ac_t""yes" 1>&6
-    ac_tr_lib=HAVE_LIB`echo adns | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+    ac_tr_lib=HAVE_LIB`echo nsl | sed -e 's/[^a-zA-Z0-9_]/_/g' \
     -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
   cat >> confdefs.h <<EOF
 #define $ac_tr_lib 1
 EOF
 
-  LIBS="-ladns $LIBS"
+  LIBS="-lnsl $LIBS"
 
 else
   echo "$ac_t""no" 1>&6
 fi
 
 echo $ac_n "checking for getopt_long in -lgetopt""... $ac_c" 1>&6
-echo "configure:1648: checking for getopt_long in -lgetopt" >&5
+echo "configure:1695: checking for getopt_long in -lgetopt" >&5
 ac_lib_var=`echo getopt'_'getopt_long | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1652,7 +1699,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lgetopt  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1656 "configure"
+#line 1703 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -1663,7 +1710,7 @@ int main() {
 getopt_long()
 ; return 0; }
 EOF
-if { (eval echo configure:1667: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1714: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -1691,7 +1738,7 @@ else
 fi
 
 echo $ac_n "checking for getopt_long in -lgnugetopt""... $ac_c" 1>&6
-echo "configure:1695: checking for getopt_long in -lgnugetopt" >&5
+echo "configure:1742: checking for getopt_long in -lgnugetopt" >&5
 ac_lib_var=`echo gnugetopt'_'getopt_long | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1699,7 +1746,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lgnugetopt  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1703 "configure"
+#line 1750 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -1710,7 +1757,7 @@ int main() {
 getopt_long()
 ; return 0; }
 EOF
-if { (eval echo configure:1714: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1761: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -1737,17 +1784,158 @@ else
   echo "$ac_t""no" 1>&6
 fi
 
+echo $ac_n "checking for socket in -lsocket""... $ac_c" 1>&6
+echo "configure:1789: checking for socket in -lsocket" >&5
+ac_lib_var=`echo socket'_'socket | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lsocket  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1797 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char socket();
+
+int main() {
+socket()
+; return 0; }
+EOF
+if { (eval echo configure:1808: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_lib=HAVE_LIB`echo socket | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+  LIBS="-lsocket $LIBS"
+
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for inet_aton in -lresolv""... $ac_c" 1>&6
+echo "configure:1836: checking for inet_aton in -lresolv" >&5
+ac_lib_var=`echo resolv'_'inet_aton | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lresolv  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1844 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char inet_aton();
+
+int main() {
+inet_aton()
+; return 0; }
+EOF
+if { (eval echo configure:1855: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_lib=HAVE_LIB`echo resolv | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+  LIBS="-lresolv $LIBS"
+
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for adns_init in -ladns""... $ac_c" 1>&6
+echo "configure:1883: checking for adns_init in -ladns" >&5
+ac_lib_var=`echo adns'_'adns_init | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-ladns  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1891 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char adns_init();
+
+int main() {
+adns_init()
+; return 0; }
+EOF
+if { (eval echo configure:1902: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_lib=HAVE_LIB`echo adns | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+  LIBS="-ladns $LIBS"
+
+else
+  echo "$ac_t""no" 1>&6
+fi
+
 
 
 for ac_func in getopt_long 
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:1746: checking for $ac_func" >&5
+echo "configure:1934: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1751 "configure"
+#line 1939 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -1770,7 +1958,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:1774: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1962: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -1798,12 +1986,12 @@ done
 for ac_func in snprintf 
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:1802: checking for $ac_func" >&5
+echo "configure:1990: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1807 "configure"
+#line 1995 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -1826,7 +2014,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:1830: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2018: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -1854,19 +2042,19 @@ done
 # The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
 # for constant arguments.  Useless!
 echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6
-echo "configure:1858: checking for working alloca.h" >&5
+echo "configure:2046: checking for working alloca.h" >&5
 if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1863 "configure"
+#line 2051 "configure"
 #include "confdefs.h"
 #include <alloca.h>
 int main() {
 char *p = alloca(2 * sizeof(int));
 ; return 0; }
 EOF
-if { (eval echo configure:1870: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2058: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ac_cv_header_alloca_h=yes
 else
@@ -1887,12 +2075,12 @@ EOF
 fi
 
 echo $ac_n "checking for alloca""... $ac_c" 1>&6
-echo "configure:1891: checking for alloca" >&5
+echo "configure:2079: checking for alloca" >&5
 if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1896 "configure"
+#line 2084 "configure"
 #include "confdefs.h"
 
 #ifdef __GNUC__
@@ -1920,7 +2108,7 @@ int main() {
 char *p = (char *) alloca(1);
 ; return 0; }
 EOF
-if { (eval echo configure:1924: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2112: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ac_cv_func_alloca_works=yes
 else
@@ -1952,12 +2140,12 @@ EOF
 
 
 echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6
-echo "configure:1956: checking whether alloca needs Cray hooks" >&5
+echo "configure:2144: checking whether alloca needs Cray hooks" >&5
 if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1961 "configure"
+#line 2149 "configure"
 #include "confdefs.h"
 #if defined(CRAY) && ! defined(CRAY2)
 webecray
@@ -1982,12 +2170,12 @@ echo "$ac_t""$ac_cv_os_cray" 1>&6
 if test $ac_cv_os_cray = yes; then
 for ac_func in _getb67 GETB67 getb67; do
   echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:1986: checking for $ac_func" >&5
+echo "configure:2174: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1991 "configure"
+#line 2179 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -2010,7 +2198,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:2014: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2202: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -2037,7 +2225,7 @@ done
 fi
 
 echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6
-echo "configure:2041: checking stack direction for C alloca" >&5
+echo "configure:2229: checking stack direction for C alloca" >&5
 if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -2045,7 +2233,7 @@ else
   ac_cv_c_stack_direction=0
 else
   cat > conftest.$ac_ext <<EOF
-#line 2049 "configure"
+#line 2237 "configure"
 #include "confdefs.h"
 find_stack_direction ()
 {
@@ -2064,7 +2252,7 @@ main ()
   exit (find_stack_direction() < 0);
 }
 EOF
-if { (eval echo configure:2068: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:2256: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ac_cv_c_stack_direction=1
 else
index 3fc0cd21f2404f6c750eea1dfd9cde615a9a0b95..8bc960e3ad69dd07986c7dfc8ef7d2735fc53bac 100644 (file)
@@ -21,12 +21,18 @@ AC_CHECK_SIZEOF(unsigned int)
 AC_CHECK_SIZEOF(unsigned short)
 AC_CHECK_SIZEOF(unsigned char)
 
+dnl the order in which libraries is checked is important
+dnl eg. adns on Solaris 2.5.1 depends on -lnsl and -lsocket
 AC_CHECK_LIB(gmp,mpz_init_set_str)
 AC_CHECK_LIB(gmp2,mpz_init_set_str)
+AC_CHECK_LIB(gmp,__gmpz_init_set_str)
 AC_CHECK_LIB(fl,yywrap)
-AC_CHECK_LIB(adns,adns_init)
+AC_CHECK_LIB(nsl,inet_ntoa)
 AC_CHECK_LIB(getopt,getopt_long)
 AC_CHECK_LIB(gnugetopt,getopt_long)
+AC_CHECK_LIB(socket,socket)
+AC_CHECK_LIB(resolv,inet_aton)
+AC_CHECK_LIB(adns,adns_init)
 
 dnl check for getopt in standard library
 AC_SUBST(LIBOBJS)
index 23f75aed314a696a9e7040cdb24c7d40e84919f2..2011174b03830a6df4aba366c9878633049c5774 100644 (file)
@@ -1,4 +1,4 @@
-secnet (0.1.9-1) unstable; urgency=low
+secnet (0.1.10-1) unstable; urgency=low
 
   * New upstream version.
 
index 189b44235f237e20c26443dde2abdd0d398a35db..49f2540f571145c16714c641e07c4bfc6327bc05 100644 (file)
@@ -69,6 +69,7 @@ netlink tun {
        name "netlink-tun"; # Printed in log messages from this netlink
 #      interface "tun0"; # You may set your own interface name if you wish;
                # if you don't one will be chosen for you.
+#      device "/dev/net/tun";
 
        # local networks served by this netlink device
        # incoming tunneled packets for other networks will be discarded
@@ -109,7 +110,7 @@ netlink tun {
 # host and port for your site end up on this machine at the port you
 # specify here.
 comm udp {
-       port xxxx;
+       port 410;
        buffer sysbuffer(4096);
 };
 
index 2dc5928819cd543b328b7ef9788c4702f0c01753..f42e82016319b702cd31b88e9075e8663d2ee04b 100644 (file)
--- a/ipaddr.c
+++ b/ipaddr.c
@@ -74,7 +74,8 @@ string_t subnet_to_string(struct subnet *sn)
        mask=(mask<<1);
     }
     if (i!=sn->len) {
-       fatal("subnet_to_string: invalid subnet structure!\n");
+       fatal("subnet_to_string: invalid subnet structure "
+             "(i=%d sn->len=%d mask=0x%08x)!\n",i,sn->len,sn->mask);
     }
     snprintf(s, 19, "%d.%d.%d.%d/%d", a, b, c, d, sn->len);
     return s;
diff --git a/log.c b/log.c
index dd51b25984028a513f7308c9da3d9bc139f7f104..32f0901e96830b3df1fdc5dac346c09a3d9b6149 100644 (file)
--- a/log.c
+++ b/log.c
@@ -8,7 +8,7 @@
 #include "process.h"
 
 bool_t secnet_is_daemon=False;
-uint32_t message_level=M_WARNING|M_ERROR|M_SECURITY|M_FATAL;
+uint32_t message_level=M_WARNING|M_ERR|M_SECURITY|M_FATAL;
 struct log_if *system_log=NULL;
 
 static void vMessage(uint32_t class, char *message, va_list args)
@@ -32,7 +32,7 @@ static void vMessage(uint32_t class, char *message, va_list args)
     } else {
        /* Messages go to stdout/stderr */
        if (class & message_level) {
-           if (class&M_FATAL || class&M_ERROR || class&M_WARNING) {
+           if (class&M_FATAL || class&M_ERR || class&M_WARNING) {
                dest=stderr;
            }
            vfprintf(dest,message,args);
@@ -271,11 +271,11 @@ static struct flagstr message_class_table[]={
     { "info", M_INFO },
     { "notice", M_NOTICE },
     { "warning", M_WARNING },
-    { "error", M_ERROR },
+    { "error", M_ERR },
     { "security", M_SECURITY },
     { "fatal", M_FATAL },
-    { "default", M_WARNING|M_ERROR|M_SECURITY|M_FATAL },
-    { "verbose", M_INFO|M_NOTICE|M_WARNING|M_ERROR|M_SECURITY|M_FATAL },
+    { "default", M_WARNING|M_ERR|M_SECURITY|M_FATAL },
+    { "verbose", M_INFO|M_NOTICE|M_WARNING|M_ERR|M_SECURITY|M_FATAL },
     { "quiet", M_FATAL },
     { NULL, 0 }
 };
@@ -334,7 +334,7 @@ static int msgclass_to_syslogpriority(uint32_t m)
     case M_INFO: return LOG_INFO;
     case M_NOTICE: return LOG_NOTICE;
     case M_WARNING: return LOG_WARNING;
-    case M_ERROR: return LOG_ERR;
+    case M_ERR: return LOG_ERR;
     case M_SECURITY: return LOG_CRIT;
     case M_FATAL: return LOG_EMERG;
     default: return LOG_NOTICE;
index fb8802863adeaacacb2760a407e18f9d2e778300..5d6de21a8ce591604e013486fcacbdfe20212643 100755 (executable)
@@ -58,7 +58,7 @@ sys.path.append("/usr/local/share/secnet")
 sys.path.append("/usr/share/secnet")
 import ipaddr
 
-VERSION="0.1.9"
+VERSION="0.1.10"
 
 class vpn:
        def __init__(self,name):
@@ -100,12 +100,12 @@ class nets:
                i=sc.intersection(self.set)
                return i.is_empty()
        def out(self):
-               rn=''
-               if (self.w[0]=='restrict-nets'): rn='# '
-               return '%s%s %s;'%(rn,self.w[0],
-                       string.join(map(lambda x:'"%s/%s"'%(x.ip_str(),
+               if (self.w[0]=='restrict-nets'): pattern="# restrict-nets %s;"
+               else:
+                       pattern="link netlink { routes %s; };"
+               return pattern%string.join(map(lambda x:'"%s/%s"'%(x.ip_str(),
                                x.mask.netmask_bits_str),
-                               self.set.as_list_of_networks()),","))
+                               self.set.as_list_of_networks()),",")
 
 class dhgroup:
        def __init__(self,w):
index b7cdb4cdef4a4ca6496f18b2ffa0cd08f3900f57..4426a7c3575d31f79d1a8293a135d5cfe9d9cd02 100644 (file)
--- a/netlink.c
+++ b/netlink.c
@@ -14,6 +14,9 @@
 #include "netlink.h"
 #include "process.h"
 
+#define OPT_SOFTROUTE   1
+#define OPT_ALLOWROUTE  2
+
 /* Generic IP checksum routine */
 static inline uint16_t ip_csum(uint8_t *iph,uint32_t count)
 {
@@ -262,9 +265,8 @@ static bool_t netlink_check(struct netlink *st, struct buffer_if *buf)
     return True;
 }
 
-/* Deliver a packet. "client" points to the _origin_ of the packet, not
-   its destination. (May be used when sending ICMP response - avoid
-   asymmetric routing.) */
+/* Deliver a packet. "client" is the _origin_ of the packet, not its
+destination.  */
 static void netlink_packet_deliver(struct netlink *st,
                                   struct netlink_client *client,
                                   struct buffer_if *buf)
@@ -273,84 +275,105 @@ static void netlink_packet_deliver(struct netlink *st,
     uint32_t dest=ntohl(iph->daddr);
     uint32_t source=ntohl(iph->saddr);
     uint32_t best_quality;
+    bool_t allow_route=False;
+    bool_t found_allowed=False;
     int best_match;
     int i;
 
     BUF_ASSERT_USED(buf);
 
     if (dest==st->secnet_address) {
-       Message(M_ERROR,"%s: trying to deliver a packet to myself!\n");
+       Message(M_ERR,"%s: trying to deliver a packet to myself!\n");
        BUF_FREE(buf);
        return;
     }
     
-    /* XXX we're going to need an extra value 'allow_route' for the
-       source of the packet. It's always True for packets from the
-       host. For packets from tunnels, we consult the client
-       options. If !allow_route and the destination is a tunnel that
-       also doesn't allow routing, we must reject the packet with an
-       'administratively prohibited' or something similar ICMP. */
-    if (!client) {
-       /* Origin of packet is host or secnet. Might be for a tunnel. */
-       best_quality=0;
-       best_match=-1;
-       for (i=0; i<st->n_routes; i++) {
-           if (st->routes[i].up && subnet_match(&st->routes[i].net,dest)) {
-               if (st->routes[i].c->link_quality>best_quality
-                   || best_quality==0) {
-                   best_quality=st->routes[i].c->link_quality;
-                   best_match=i;
-                   /* If quality isn't perfect we may wish to
-                      consider kicking the tunnel with a 0-length
-                      packet to prompt it to perform a key setup.
-                      Then it'll eventually decide it's up or
-                      down. */
-                   /* If quality is perfect we don't need to search
-                       any more. */
-                   if (best_quality>=MAXIMUM_LINK_QUALITY) break;
-               }
-           }
-       }
-       if (best_match==-1) {
-           /* Not going down a tunnel. Might be for the host. 
-              XXX think about this - only situation should be if we're
-              sending ICMP. */
-           if (source!=st->secnet_address) {
-               Message(M_ERROR,"netlink_packet_deliver: outgoing packet "
-                       "from host that won't fit down any of our tunnels!\n");
-               /* XXX I think this could also occur if a soft tunnel just
-                  went down, but still had packets queued in the kernel. */
-               BUF_FREE(buf);
-           } else {
-               st->deliver_to_host(st->dst,NULL,buf);
-               BUF_ASSERT_FREE(buf);
+    /* Packets from the host (client==NULL) will always be routed.  Packets
+       from clients with the allow_route option will also be routed. */
+    if (!client || (client && (client->options & OPT_ALLOWROUTE)))
+       allow_route=True;
+
+    /* If !allow_route, we check the routing table anyway, and if
+       there's a suitable route with OPT_ALLOWROUTE set we use it.  If
+       there's a suitable route, but none with OPT_ALLOWROUTE set then
+       we generate ICMP 'communication with destination network
+       administratively prohibited'. */
+
+    best_quality=0;
+    best_match=-1;
+    for (i=0; i<st->n_routes; i++) {
+       if (st->routes[i].up && subnet_match(&st->routes[i].net,dest)) {
+           /* It's an available route to the correct destination. But is
+              it better than the one we already have? */
+
+           /* If we have already found an allowed route then we don't
+              bother looking at routes we're not allowed to use.  If
+              we don't yet have an allowed route we'll consider any.  */
+           if (!allow_route && found_allowed) {
+               if (!(st->routes[i].c->options&OPT_ALLOWROUTE)) continue;
            }
-       } else {
-           if (best_quality>0) {
-               st->routes[best_match].c->deliver(
-                   st->routes[best_match].c->dst,
-                   st->routes[best_match].c, buf);
-               BUF_ASSERT_FREE(buf);
-           } else {
-               /* Generate ICMP destination unreachable */
-               netlink_icmp_simple(st,buf,client,3,0); /* client==NULL */
-               BUF_FREE(buf);
+           
+           if (st->routes[i].c->link_quality>best_quality
+               || best_quality==0) {
+               best_quality=st->routes[i].c->link_quality;
+               best_match=i;
+               if (st->routes[i].c->options&OPT_ALLOWROUTE)
+                   found_allowed=True;
+               /* If quality isn't perfect we may wish to
+                  consider kicking the tunnel with a 0-length
+                  packet to prompt it to perform a key setup.
+                  Then it'll eventually decide it's up or
+                  down. */
+               /* If quality is perfect and we're allowed to use the
+                  route we don't need to search any more. */
+               if (best_quality>=MAXIMUM_LINK_QUALITY && 
+                   (allow_route || found_allowed)) break;
            }
        }
-    } else { /* client is set */
-       /* We know the origin is a tunnel - packet must be for the host */
-       /* XXX THIS IS NOT NECESSARILY TRUE, AND NEEDS FIXING */
-       /* THIS FUNCTION MUST JUST DELIVER THE PACKET: IT MUST ASSUME
-          THE PACKET HAS ALREADY BEEN CHECKED */
+    }
+    if (best_match==-1) {
+       /* The packet's not going down a tunnel.  It might (ought to)
+          be for the host.   */
        if (subnet_matches_list(&st->networks,dest)) {
-           st->deliver_to_host(st->dst,NULL,buf);
+           st->deliver_to_host(st->dst,buf);
+           st->outcount++;
            BUF_ASSERT_FREE(buf);
        } else {
-           Message(M_ERROR,"%s: packet from tunnel %s can't be delivered "
-                   "to the host\n",st->name,client->name);
+           string_t s,d;
+           s=ipaddr_to_string(source);
+           d=ipaddr_to_string(dest);
+           Message(M_ERR,"%s: don't know where to deliver packet "
+                   "(s=%s, d=%s)\n", st->name, s, d);
+           free(s); free(d);
            netlink_icmp_simple(st,buf,client,3,0);
            BUF_FREE(buf);
        }
+    } else {
+       if (!allow_route &&
+           !(st->routes[best_match].c->options&OPT_ALLOWROUTE)) {
+           string_t s,d;
+           s=ipaddr_to_string(source);
+           d=ipaddr_to_string(dest);
+           /* We have a usable route but aren't allowed to use it.
+              Generate ICMP destination unreachable: communication
+              with destination network administratively prohibited */
+           Message(M_NOTICE,"%s: denied forwarding for packet (s=%s, d=%s)\n",
+                   st->name,s,d);
+           free(s); free(d);
+                   
+           netlink_icmp_simple(st,buf,client,3,9);
+           BUF_FREE(buf);
+       }
+       if (best_quality>0) {
+           st->routes[best_match].c->deliver(
+               st->routes[best_match].c->dst, buf);
+           st->routes[best_match].outcount++;
+           BUF_ASSERT_FREE(buf);
+       } else {
+           /* Generate ICMP destination unreachable */
+           netlink_icmp_simple(st,buf,client,3,0); /* client==NULL */
+           BUF_FREE(buf);
+       }
     }
     BUF_ASSERT_FREE(buf);
 }
@@ -385,6 +408,8 @@ static void netlink_packet_local(struct netlink *st,
 {
     struct icmphdr *h;
 
+    st->localcount++;
+
     h=(struct icmphdr *)buf->start;
 
     if ((ntohs(h->iph.frag_off)&0xbfff)!=0) {
@@ -422,10 +447,9 @@ static void netlink_packet_local(struct netlink *st,
 
 /* If cid==NULL packet is from host, otherwise cid specifies which tunnel 
    it came from. */
-static void netlink_incoming(void *sst, void *cid, struct buffer_if *buf)
+static void netlink_incoming(struct netlink *st, struct netlink_client *client,
+                            struct buffer_if *buf)
 {
-    struct netlink *st=sst;
-    struct netlink_client *client=cid;
     uint32_t source,dest;
     struct iphdr *iph;
 
@@ -445,7 +469,7 @@ static void netlink_incoming(void *sst, void *cid, struct buffer_if *buf)
     if (client) {
        /* Check that the packet source is appropriate for the tunnel
           it came down */
-       if (!subnet_matches_list(client->networks,source)) {
+       if (!subnet_matches_list(&client->networks,source)) {
            string_t s,d;
            s=ipaddr_to_string(source);
            d=ipaddr_to_string(dest);
@@ -476,9 +500,9 @@ static void netlink_incoming(void *sst, void *cid, struct buffer_if *buf)
        or to the host, depending on where it came from. */
     if (st->ptp) {
        if (client) {
-           st->deliver_to_host(st->dst,NULL,buf);
+           st->deliver_to_host(st->dst,buf);
        } else {
-           st->clients->deliver(st->clients->dst,NULL,buf);
+           st->clients->deliver(st->clients->dst,buf);
        }
        BUF_ASSERT_FREE(buf);
        return;
@@ -509,6 +533,21 @@ static void netlink_incoming(void *sst, void *cid, struct buffer_if *buf)
     BUF_ASSERT_FREE(buf);
 }
 
+static void netlink_inst_incoming(void *sst, struct buffer_if *buf)
+{
+    struct netlink_client *c=sst;
+    struct netlink *st=c->nst;
+
+    netlink_incoming(st,c,buf);
+}
+
+static void netlink_dev_incoming(void *sst, struct buffer_if *buf)
+{
+    struct netlink *st=sst;
+
+    netlink_incoming(st,NULL,buf);
+}
+
 static void netlink_set_softlinks(struct netlink *st, struct netlink_client *c,
                                  bool_t up, uint32_t quality)
 {
@@ -526,10 +565,10 @@ static void netlink_set_softlinks(struct netlink *st, struct netlink_client *c,
     }
 }
 
-static void netlink_set_quality(void *sst, void *cid, uint32_t quality)
+static void netlink_set_quality(void *sst, uint32_t quality)
 {
-    struct netlink *st=sst;
-    struct netlink_client *c=cid;
+    struct netlink_client *c=sst;
+    struct netlink *st=c->nst;
 
     c->link_quality=quality;
     if (c->link_quality==LINK_QUALITY_DOWN) {
@@ -539,62 +578,6 @@ static void netlink_set_quality(void *sst, void *cid, uint32_t quality)
     }
 }
 
-static void *netlink_regnets(void *sst, struct subnet_list *nets,
-                            netlink_deliver_fn *deliver, void *dst,
-                            uint32_t max_start_pad, uint32_t max_end_pad,
-                            uint32_t options, string_t client_name)
-{
-    struct netlink *st=sst;
-    struct netlink_client *c;
-
-    Message(M_DEBUG_CONFIG,"netlink_regnets: request for %d networks, "
-           "max_start_pad=%d, max_end_pad=%d\n",
-           nets->entries,max_start_pad,max_end_pad);
-
-    if ((options&NETLINK_OPTION_SOFTROUTE) && !st->set_route) {
-       Message(M_ERROR,"%s: this netlink device does not support "
-               "soft routes.\n");
-       return NULL;
-    }
-
-    if (options&NETLINK_OPTION_SOFTROUTE) {
-       /* XXX for now we assume that soft routes require root privilege;
-          this may not always be true. The device driver can tell us. */
-       require_root_privileges=True;
-       require_root_privileges_explanation="netlink: soft routes";
-    }
-
-    /* Check that nets do not intersect st->exclude_remote_networks;
-       refuse to register if they do. */
-    if (subnet_lists_intersect(&st->exclude_remote_networks,nets)) {
-       Message(M_ERROR,"%s: site %s specifies networks that "
-               "intersect with the explicitly excluded remote networks\n",
-               st->name,client_name);
-       return NULL;
-    }
-
-    if (st->clients && st->ptp) {
-       fatal("%s: only one site may use a point-to-point netlink device\n",
-             st->name);
-       return NULL;
-    }
-
-    c=safe_malloc(sizeof(*c),"netlink_regnets");
-    c->networks=nets;
-    c->deliver=deliver;
-    c->dst=dst;
-    c->name=client_name;
-    c->options=options;
-    c->link_quality=LINK_QUALITY_DOWN;
-    c->next=st->clients;
-    st->clients=c;
-    if (max_start_pad > st->max_start_pad) st->max_start_pad=max_start_pad;
-    if (max_end_pad > st->max_end_pad) st->max_end_pad=max_end_pad;
-    st->n_routes+=nets->entries;
-
-    return c;
-}
-
 static void netlink_dump_routes(struct netlink *st, bool_t requested)
 {
     int i;
@@ -602,23 +585,39 @@ static void netlink_dump_routes(struct netlink *st, bool_t requested)
     uint32_t c=M_INFO;
 
     if (requested) c=M_WARNING;
-    Message(c,"%s: routing table:\n",st->name);
-    for (i=0; i<st->n_routes; i++) {
-       net=subnet_to_string(&st->routes[i].net);
-       Message(c,"%s -> tunnel %s (%s,%s route,%s,quality %d)\n",net,
-               st->routes[i].c->name,
-               st->routes[i].hard?"hard":"soft",
-               st->routes[i].allow_route?"free":"restricted",
-               st->routes[i].up?"up":"down",
-               st->routes[i].quality);
+    if (st->ptp) {
+       net=ipaddr_to_string(st->secnet_address);
+       Message(c,"%s: point-to-point (remote end is %s); routes:\n",
+               st->name, net);
        free(net);
-    }
-    Message(c,"%s/32 -> netlink \"%s\"\n",
-           ipaddr_to_string(st->secnet_address),st->name);
-    for (i=0; i<st->networks.entries; i++) {
-       net=subnet_to_string(&st->networks.list[i]);
-       Message(c,"%s -> host\n",net);
+       for (i=0; i<st->n_routes; i++) {
+           net=subnet_to_string(&st->routes[i].net);
+           Message(c,"%s ",net);
+           free(net);
+       }
+       Message(c,"\n");
+    } else {
+       Message(c,"%s: routing table:\n",st->name);
+       for (i=0; i<st->n_routes; i++) {
+           net=subnet_to_string(&st->routes[i].net);
+           Message(c,"%s -> tunnel %s (%s,%s route,%s,quality %d,use %d)\n",net,
+                   st->routes[i].c->name,
+                   st->routes[i].hard?"hard":"soft",
+                   st->routes[i].allow_route?"free":"restricted",
+                   st->routes[i].up?"up":"down",
+                   st->routes[i].quality,
+                   st->routes[i].outcount);
+           free(net);
+       }
+       net=ipaddr_to_string(st->secnet_address);
+       Message(c,"%s/32 -> netlink \"%s\" (use %d)\n",
+               net,st->name,st->localcount);
        free(net);
+       for (i=0; i<st->networks.entries; i++) {
+           net=subnet_to_string(&st->networks.list[i]);
+           Message(c,"%s -> host (use %d)\n",net,st->outcount);
+           free(net);
+       }
     }
 }
 
@@ -638,13 +637,6 @@ static void netlink_phase_hook(void *sst, uint32_t new_phase)
     struct netlink_client *c;
     uint32_t i,j;
 
-    if (!st->clients && st->ptp) {
-       /* Point-to-point netlink devices must have precisely one
-          client. If none has registered by now, complain. */
-       fatal("%s: point-to-point netlink devices must have precisely "
-             "one client. This one doesn't have any.\n",st->name);
-    }
-
     /* All the networks serviced by the various tunnels should now
      * have been registered.  We build a routing table by sorting the
      * routes into most-specific-first order.  */
@@ -653,17 +645,21 @@ static void netlink_phase_hook(void *sst, uint32_t new_phase)
     /* Fill the table */
     i=0;
     for (c=st->clients; c; c=c->next) {
-       for (j=0; j<c->networks->entries; j++) {
-           st->routes[i].net=c->networks->list[j];
+       for (j=0; j<c->networks.entries; j++) {
+           st->routes[i].net=c->networks.list[j];
            st->routes[i].c=c;
            /* Hard routes are always up;
-              soft routes default to down */
-           st->routes[i].up=c->options&NETLINK_OPTION_SOFTROUTE?False:True;
+              soft routes default to down; routes with no 'deliver' function
+              default to down */
+           st->routes[i].up=c->deliver?
+               (c->options&OPT_SOFTROUTE?False:True):
+               False;
            st->routes[i].kup=False;
-           st->routes[i].hard=c->options&NETLINK_OPTION_SOFTROUTE?False:True;
-           st->routes[i].allow_route=c->options&NETLINK_OPTION_ALLOW_ROUTE?
+           st->routes[i].hard=c->options&OPT_SOFTROUTE?False:True;
+           st->routes[i].allow_route=c->options&OPT_ALLOWROUTE?
                True:False;
            st->routes[i].quality=c->link_quality;
+           st->routes[i].outcount=0;
            i++;
        }
     }
@@ -686,6 +682,116 @@ static void netlink_signal_handler(void *sst, int signum)
     netlink_dump_routes(st,True);
 }
 
+static void netlink_inst_reg(void *sst, netlink_deliver_fn *deliver, 
+                            void *dst, uint32_t max_start_pad,
+                            uint32_t max_end_pad)
+{
+    struct netlink_client *c=sst;
+    struct netlink *st=c->nst;
+
+    if (max_start_pad > st->max_start_pad) st->max_start_pad=max_start_pad;
+    if (max_end_pad > st->max_end_pad) st->max_end_pad=max_end_pad;
+    c->deliver=deliver;
+    c->dst=dst;
+}
+
+static struct flagstr netlink_option_table[]={
+    { "soft", OPT_SOFTROUTE },
+    { "allow-route", OPT_ALLOWROUTE },
+    { NULL, 0}
+};
+/* This is the routine that gets called when the closure that's
+   returned by an invocation of a netlink device closure (eg. tun,
+   userv-ipif) is invoked.  It's used to create routes and pass in
+   information about them; the closure it returns is used by site
+   code.  */
+static closure_t *netlink_inst_create(struct netlink *st,
+                                     struct cloc loc, dict_t *dict)
+{
+    struct netlink_client *c;
+    string_t name;
+    struct subnet_list networks;
+    uint32_t options;
+
+    name=dict_read_string(dict, "name", True, st->name, loc);
+
+    dict_read_subnet_list(dict, "routes", True, st->name, loc,
+                         &networks);
+    options=string_list_to_word(dict_lookup(dict,"options"),
+                               netlink_option_table,st->name);
+
+    if ((options&OPT_SOFTROUTE) && !st->set_route) {
+       cfgfatal(loc,st->name,"this netlink device does not support "
+                "soft routes.\n");
+       return NULL;
+    }
+
+    if (options&OPT_SOFTROUTE) {
+       /* XXX for now we assume that soft routes require root privilege;
+          this may not always be true. The device driver can tell us. */
+       require_root_privileges=True;
+       require_root_privileges_explanation="netlink: soft routes";
+       if (st->ptp) {
+           cfgfatal(loc,st->name,"point-to-point netlinks do not support "
+                    "soft routes.\n");
+           return NULL;
+       }
+    }
+
+    /* Check that nets do not intersect st->exclude_remote_networks;
+       refuse to register if they do. */
+    if (subnet_lists_intersect(&st->exclude_remote_networks,&networks)) {
+       cfgfatal(loc,st->name,"networks intersect with the explicitly "
+                "excluded remote networks\n");
+       return NULL;
+    }
+
+    c=safe_malloc(sizeof(*c),"netlink_inst_create");
+    c->cl.description=name;
+    c->cl.type=CL_NETLINK;
+    c->cl.apply=NULL;
+    c->cl.interface=&c->ops;
+    c->ops.st=c;
+    c->ops.reg=netlink_inst_reg;
+    c->ops.deliver=netlink_inst_incoming;
+    c->ops.set_quality=netlink_set_quality;
+    c->nst=st;
+
+    c->networks=networks;
+    c->deliver=NULL;
+    c->dst=NULL;
+    c->name=name;
+    c->options=options;
+    c->link_quality=LINK_QUALITY_DOWN;
+    c->next=st->clients;
+    st->clients=c;
+    st->n_routes+=networks.entries;
+
+    return &c->cl;
+}
+
+static list_t *netlink_inst_apply(closure_t *self, struct cloc loc,
+                                 dict_t *context, list_t *args)
+{
+    struct netlink *st=self->interface;
+
+    dict_t *dict;
+    item_t *item;
+    closure_t *cl;
+
+    Message(M_DEBUG_CONFIG,"netlink_inst_apply\n");
+
+    item=list_elem(args,0);
+    if (!item || item->type!=t_dict) {
+       cfgfatal(loc,st->name,"must have a dictionary argument\n");
+    }
+    dict=item->data.dict;
+
+    cl=netlink_inst_create(st,loc,dict);
+
+    return new_closure(cl);
+}
+
 netlink_deliver_fn *netlink_init(struct netlink *st,
                                 void *dst, struct cloc loc,
                                 dict_t *dict, string_t description,
@@ -696,13 +802,9 @@ netlink_deliver_fn *netlink_init(struct netlink *st,
 
     st->dst=dst;
     st->cl.description=description;
-    st->cl.type=CL_NETLINK;
-    st->cl.apply=NULL;
-    st->cl.interface=&st->ops;
-    st->ops.st=st;
-    st->ops.regnets=netlink_regnets;
-    st->ops.deliver=netlink_incoming;
-    st->ops.set_quality=netlink_set_quality;
+    st->cl.type=CL_PURE;
+    st->cl.apply=netlink_inst_apply;
+    st->cl.interface=st;
     st->max_start_pad=0;
     st->max_end_pad=0;
     st->clients=NULL;
@@ -715,11 +817,8 @@ netlink_deliver_fn *netlink_init(struct netlink *st,
                          &st->networks);
     dict_read_subnet_list(dict, "exclude-remote-networks", False, "netlink",
                          loc, &st->exclude_remote_networks);
-    /* secnet-address does not have to be in local-networks;
-       however, it should be advertised in the 'sites' file for the
-       local site. */
     sa=dict_find_item(dict,"secnet-address",False,"netlink",loc);
-    ptpa=dict_find_item(dict,"ptp-address", False, "netlink", loc);
+    ptpa=dict_find_item(dict,"ptp-address",False,"netlink",loc);
     if (sa && ptpa) {
        cfgfatal(loc,st->name,"you may not specify secnet-address and "
                 "ptp-address in the same netlink device\n");
@@ -739,11 +838,22 @@ netlink_deliver_fn *netlink_init(struct netlink *st,
     buffer_new(&st->icmp,ICMP_BUFSIZE);
     st->n_routes=0;
     st->routes=NULL;
+    st->outcount=0;
+    st->localcount=0;
 
     add_hook(PHASE_SETUP,netlink_phase_hook,st);
     request_signal_notification(SIGUSR1, netlink_signal_handler, st);
 
-    return netlink_incoming;
+    /* If we're point-to-point then we return a CL_NETLINK directly,
+       rather than a CL_NETLINK_OLD or pure closure (depending on
+       compatibility).  This CL_NETLINK is for our one and only
+       client.  Our cl.apply function is NULL. */
+    if (st->ptp) {
+       closure_t *cl;
+       cl=netlink_inst_create(st,loc,dict);
+       st->cl=*cl;
+    }
+    return netlink_dev_incoming;
 }
 
 /* No connection to the kernel at all... */
@@ -768,7 +878,7 @@ static bool_t null_set_route(void *sst, struct netlink_route *route)
     return False;
 }
            
-static void null_deliver(void *sst, void *cid, struct buffer_if *buf)
+static void null_deliver(void *sst, struct buffer_if *buf)
 {
     return;
 }
index 4cc80af41f6f6139babed6377d8b57ae07ae5fcc..c13b0ae44cce6c58fa8488c4c25848639f29df96 100644 (file)
--- a/netlink.h
+++ b/netlink.h
@@ -7,8 +7,13 @@
 #define DEFAULT_MTU 1000
 #define ICMP_BUFSIZE 1024
 
+struct netlink;
+
 struct netlink_client {
-    struct subnet_list *networks;
+    closure_t cl;
+    struct netlink_if ops;
+    struct netlink *nst;
+    struct subnet_list networks;
     netlink_deliver_fn *deliver;
     void *dst;
     string_t name;
@@ -24,6 +29,7 @@ struct netlink_route {
     bool_t up;
     bool_t kup;
     uint32_t quality; /* provided by client */
+    uint32_t outcount;
     struct netlink_client *c;
 };
 
@@ -35,15 +41,14 @@ typedef bool_t netlink_route_fn(void *cst, struct netlink_route *route);
 
 struct netlink {
     closure_t cl;
-    struct netlink_if ops;
     void *dst; /* Pointer to host interface state */
     string_t name;
     uint32_t max_start_pad;
     uint32_t max_end_pad;
     struct subnet_list networks;
     struct subnet_list exclude_remote_networks;
-    uint32_t secnet_address; /* our own address, or possibly the address of
-                               the other end of a point-to-point link */
+    uint32_t secnet_address; /* our own address, or the address of the
+                               other end of a point-to-point link */
     bool_t ptp;
     uint32_t mtu;
     struct netlink_client *clients;
@@ -52,6 +57,8 @@ struct netlink {
     struct buffer_if icmp; /* Buffer for assembly of outgoing ICMP */
     uint32_t n_routes; /* How many routes do we know about? */
     struct netlink_route *routes;
+    uint32_t outcount; /* Packets sent to host */
+    uint32_t localcount; /* Packets sent to secnet */
 };
 
 extern netlink_deliver_fn *netlink_init(struct netlink *st,
index 57b4f052074d8a471c4936cd8b4952d3407f9759..a3cf15334d32e60fd2122567878982203693b283 100644 (file)
--- a/secnet.c
+++ b/secnet.c
@@ -106,7 +106,7 @@ static void parse_options(int argc, char **argv)
            break;
 
        case 'v':
-           message_level|=M_INFO|M_NOTICE|M_WARNING|M_ERROR|M_SECURITY|
+           message_level|=M_INFO|M_NOTICE|M_WARNING|M_ERR|M_SECURITY|
                M_FATAL;
            break;
 
@@ -141,12 +141,12 @@ static void parse_options(int argc, char **argv)
            break;
 
        default:
-           Message(M_ERROR,"secnet: Unknown getopt code %c\n",c);
+           Message(M_ERR,"secnet: Unknown getopt code %c\n",c);
        }
     }
 
     if (argc-optind != 0) {
-       Message(M_ERROR,"secnet: You gave extra command line parameters, "
+       Message(M_ERR,"secnet: You gave extra command line parameters, "
                "which were ignored.\n");
     }
 }
index 2535030f17fef6da146944d3384dca7b99cdf85d..3821b81cddf2386592409754f78f70a9d4ee75e1 100644 (file)
--- a/secnet.h
+++ b/secnet.h
@@ -135,7 +135,7 @@ extern uint32_t string_list_to_word(list_t *l, struct flagstr *f,
 #define M_INFO        0x008
 #define M_NOTICE       0x010
 #define M_WARNING      0x020
-#define M_ERROR               0x040
+#define M_ERR         0x040
 #define M_SECURITY     0x080
 #define M_FATAL               0x100
 
@@ -220,26 +220,26 @@ extern string_t require_root_privileges_explanation;
 /* Module initialisation function type - modules export one function of
    this type which is called to initialise them. For dynamically loaded
    modules it's called "secnet_module". */
-typedef void (init_module)(dict_t *dict);
+typedef void init_module(dict_t *dict);
 
 /***** END of module support *****/
 
 /***** CLOSURE TYPES and interface definitions *****/
 
-#define CL_PURE        0
-#define CL_RESOLVER    1
-#define CL_RANDOMSRC   2
-#define CL_RSAPUBKEY   3
-#define CL_RSAPRIVKEY  4
-#define CL_COMM        5
-#define CL_IPIF        6
-#define CL_LOG         7
-#define CL_SITE        8
-#define CL_TRANSFORM   9
-#define CL_NETLINK    10
-#define CL_DH         11
-#define CL_HASH       12
-#define CL_BUFFER     13
+#define CL_PURE         0
+#define CL_RESOLVER     1
+#define CL_RANDOMSRC    2
+#define CL_RSAPUBKEY    3
+#define CL_RSAPRIVKEY   4
+#define CL_COMM         5
+#define CL_IPIF         6
+#define CL_LOG          7
+#define CL_SITE         8
+#define CL_TRANSFORM    9
+#define CL_DH          11
+#define CL_HASH        12
+#define CL_BUFFER      13
+#define CL_NETLINK     14
 
 struct buffer_if;
 
@@ -374,7 +374,7 @@ struct transform_if {
    netlink_regnets_fn.  If buf has size 0 then the function is just
    being called for its site-effects (eg. making the site code attempt
    to bring up a network link) */
-typedef void netlink_deliver_fn(void *st, void *cid, struct buffer_if *buf);
+typedef void netlink_deliver_fn(void *st, struct buffer_if *buf);
 /* site code can tell netlink when outgoing packets will be dropped,
    so netlink can generate appropriate ICMP and make routing decisions */
 #define LINK_QUALITY_DOWN 0   /* No chance of a packet being delivered */
@@ -382,21 +382,14 @@ typedef void netlink_deliver_fn(void *st, void *cid, struct buffer_if *buf);
 #define LINK_QUALITY_DOWN_CURRENT_ADDRESS 2 /* Link down, current address information */
 #define LINK_QUALITY_UP 3     /* Link active */
 #define MAXIMUM_LINK_QUALITY 3
-typedef void netlink_link_quality_fn(void *st, void *cid, uint32_t quality);
-/* Register for packets from specified networks. Return value is
-   client identifier.  'hard_route' indicates whether the routes being
-   registered are permanent (hard) or temporary (soft); some types of
-   netlink device can only cope with hard routes. */
-#define NETLINK_OPTION_SOFTROUTE    1
-#define NETLINK_OPTION_ALLOW_ROUTE  2
-typedef void *netlink_regnets_fn(void *st, struct subnet_list *networks,
-                                netlink_deliver_fn *deliver, void *dst,
-                                uint32_t max_start_pad, uint32_t max_end_pad,
-                                uint32_t options, string_t client_name);
+typedef void netlink_link_quality_fn(void *st, uint32_t quality);
+typedef void netlink_register_fn(void *st, netlink_deliver_fn *deliver,
+                                void *dst, uint32_t max_start_pad,
+                                uint32_t max_end_pad);
 
 struct netlink_if {
     void *st;
-    netlink_regnets_fn *regnets;
+    netlink_register_fn *reg;
     netlink_deliver_fn *deliver;
     netlink_link_quality_fn *set_quality;
 };
diff --git a/site.c b/site.c
index 8223fb3f81d678e228cd606aeb5d65aa7c92a609..fc045c9098c5ebfc57cfc9604a5f0d3394d4a7bd 100644 (file)
--- a/site.c
+++ b/site.c
@@ -1,13 +1,22 @@
 /* site.c - manage communication with a remote network site */
 
+/* The 'site' code doesn't know anything about the structure of the
+   packets it's transmitting.  In fact, under the new netlink
+   configuration scheme it doesn't need to know anything at all about
+   IP addresses, except how to contact its peer.  This means it could
+   potentially be used to tunnel other protocols too (IPv6, IPX, plain
+   old Ethernet frames) if appropriate netlink code can be written
+   (and that ought not to be too hard, eg. using the TUN/TAP device to
+   pretend to be an Ethernet interface).  */
+
 #include "secnet.h"
 #include <stdio.h>
+#include <string.h>
 /* MBM asserts the next one is needed for compilation under BSD. */
 #include <sys/socket.h>
 
 #include <sys/mman.h>
 #include "util.h"
-#include "ipaddr.h"
 #include "unaligned.h"
 
 #define SETUP_BUFFER_LEN 2048
@@ -120,12 +129,6 @@ static struct flagstr log_event_table[]={
     { NULL, 0 }
 };
 
-static struct flagstr netlink_option_table[]={
-    { "soft", NETLINK_OPTION_SOFTROUTE },
-    { "allow-route", NETLINK_OPTION_ALLOW_ROUTE },
-    { NULL, 0}
-};
-
 struct site {
     closure_t cl;
     struct site_if ops;
@@ -141,7 +144,6 @@ struct site {
     struct log_if *log;
     struct random_if *random;
     struct rsaprivkey_if *privkey;
-    struct subnet_list remotenets;
     struct rsapubkey_if *pubkey;
     struct transform_if *transform;
     struct dh_if *dh;
@@ -168,8 +170,6 @@ struct site {
     uint32_t state;
     uint64_t now; /* Most recently seen time */
 
-    void *netlink_cid;
-
     uint32_t remote_session_id;
     struct transform_inst_if *current_transform;
     bool_t current_valid;
@@ -210,8 +210,8 @@ static void slog(struct site *st, uint32_t event, string_t msg, ...)
        case LOG_STATE: class=M_DEBUG; break;
        case LOG_DROP: class=M_DEBUG; break;
        case LOG_DUMP: class=M_DEBUG; break;
-       case LOG_ERROR: class=M_ERROR; break;
-       default: class=M_ERROR; break;
+       case LOG_ERROR: class=M_ERR; break;
+       default: class=M_ERR; break;
        }
 
        vsnprintf(buf,240,msg,ap);
@@ -636,7 +636,7 @@ static bool_t process_msg0(struct site *st, struct buffer_if *msg0,
     switch(type) {
     case LABEL_MSG9:
        /* Deliver to netlink layer */
-       st->netlink->deliver(st->netlink->st,st->netlink_cid,msg0);
+       st->netlink->deliver(st->netlink->st,msg0);
        return True;
        break;
     default:
@@ -770,7 +770,7 @@ static void set_link_quality(struct site *st)
     else
        quality=LINK_QUALITY_DOWN;
 
-    st->netlink->set_quality(st->netlink->st,st->netlink_cid,quality);
+    st->netlink->set_quality(st->netlink->st,quality);
 }
 
 static void enter_state_run(struct site *st)
@@ -954,7 +954,7 @@ static void site_afterpoll(void *sst, struct pollfd *fds, int nfds,
 /* This function is called by the netlink device to deliver packets
    intended for the remote network. The packet is in "raw" wire
    format, but is guaranteed to be word-aligned. */
-static void site_outgoing(void *sst, void *cid, struct buffer_if *buf)
+static void site_outgoing(void *sst, struct buffer_if *buf)
 {
     struct site *st=sst;
     string_t transform_err;
@@ -1142,7 +1142,6 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context,
     struct site *st;
     item_t *item;
     dict_t *dict;
-    uint32_t netlink_options;
 
     st=safe_malloc(sizeof(*st),"site_apply");
 
@@ -1171,7 +1170,7 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context,
        free(st);
        return NULL;
     }
-    st->netlink=find_cl_if(dict,"netlink",CL_NETLINK,True,"site",loc);
+    st->netlink=find_cl_if(dict,"link",CL_NETLINK,True,"site",loc);
     st->comm=find_cl_if(dict,"comm",CL_COMM,True,"site",loc);
     st->resolver=find_cl_if(dict,"resolver",CL_RESOLVER,True,"site",loc);
     st->log=find_cl_if(dict,"log",CL_LOG,True,"site",loc);
@@ -1182,8 +1181,6 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context,
     if (st->address)
        st->remoteport=dict_read_number(dict,"port",True,"site",loc,0);
     else st->remoteport=0;
-    dict_read_subnet_list(dict, "networks", True, "site", loc,
-                         &st->remotenets);
     st->pubkey=find_cl_if(dict,"key",CL_RSAPUBKEY,True,"site",loc);
 
     st->transform=
@@ -1216,9 +1213,6 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context,
     st->log_events=string_list_to_word(dict_lookup(dict,"log-events"),
                                       log_event_table,"site");
 
-    netlink_options=string_list_to_word(dict_lookup(dict,"netlink-options"),
-                                       netlink_option_table,"site");
-
     st->tunname=safe_malloc(strlen(st->localname)+strlen(st->remotename)+5,
                            "site_apply");
     sprintf(st->tunname,"%s<->%s",st->localname,st->remotename);
@@ -1249,17 +1243,9 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context,
     st->sharedsecret=safe_malloc(st->transform->keylen,"site:sharedsecret");
 
     /* We need to register the remote networks with the netlink device */
-    st->netlink_cid=st->netlink->regnets(st->netlink->st, &st->remotenets,
-                                        site_outgoing, st,
-                                        st->transform->max_start_pad+(4*4),
-                                        st->transform->max_end_pad,
-                                        netlink_options, st->tunname);
-    if (!st->netlink_cid) {
-       Message(M_WARNING,"%s: netlink device did not let us register "
-               "our remote networks. This site will not start.\n",
-               st->tunname);
-       return NULL; /* XXX should free site first */
-    }
+    st->netlink->reg(st->netlink->st, site_outgoing, st,
+                    st->transform->max_start_pad+(4*4),
+                    st->transform->max_end_pad);
 
     st->comm->request_notify(st->comm->st, st, site_incoming);
 
diff --git a/slip.c b/slip.c
index cff8f63df63788c966428b4c0dc6b43facdc8d37..d0a77c0b7a118ee7c63fa25c6216d105f2adffd7 100644 (file)
--- a/slip.c
+++ b/slip.c
@@ -91,8 +91,7 @@ static void slip_unstuff(struct slip *st, uint8_t *buf, uint32_t l)
            switch (buf[i]) {
            case SLIP_END:
                if (st->buff->size>0) {
-                   st->netlink_to_tunnel(&st->nl,NULL,
-                                         st->buff);
+                   st->netlink_to_tunnel(&st->nl,st->buff);
                    BUF_ALLOC(st->buff,"userv_afterpoll");
                }
                buffer_init(st->buff,st->nl.max_start_pad);
@@ -162,7 +161,7 @@ static void userv_afterpoll(void *sst, struct pollfd *fds, int nfds,
     if (nfds==0) return;
 
     if (fds[1].revents&POLLERR) {
-       Message(M_ERROR,"%s: userv_afterpoll: POLLERR!\n",st->slip.nl.name);
+       Message(M_ERR,"%s: userv_afterpoll: POLLERR!\n",st->slip.nl.name);
     }
     if (fds[1].revents&POLLIN) {
        l=read(st->rxfd,rxbuf,DEFAULT_BUFSIZE);
@@ -178,8 +177,7 @@ static void userv_afterpoll(void *sst, struct pollfd *fds, int nfds,
 }
 
 /* Send buf to the kernel. Free buf before returning. */
-static void userv_deliver_to_kernel(void *sst, void *cid,
-                                   struct buffer_if *buf)
+static void userv_deliver_to_kernel(void *sst, struct buffer_if *buf)
 {
     struct userv *st=sst;
 
@@ -214,8 +212,8 @@ static void userv_userv_callback(void *sst, pid_t pid, int status)
 struct userv_entry_rec {
     string_t path;
     char **argv;
-    int stdin;
-    int stdout;
+    int in;
+    int out;
     /* XXX perhaps we should collect and log stderr? */
 };
 
@@ -223,8 +221,8 @@ static void userv_entry(void *sst)
 {
     struct userv_entry_rec *st=sst;
 
-    dup2(st->stdin,0);
-    dup2(st->stdout,1);
+    dup2(st->in,0);
+    dup2(st->out,1);
 
     /* XXX close all other fds */
     setsid();
@@ -288,8 +286,8 @@ static void userv_invoke_userv(struct userv *st)
 
     er=safe_malloc(sizeof(*r),"userv_invoke_userv: er");
 
-    er->stdin=c_stdin[0];
-    er->stdout=c_stdout[1];
+    er->in=c_stdin[0];
+    er->out=c_stdout[1];
     /* The arguments are:
        userv
        service-user
@@ -307,8 +305,8 @@ static void userv_invoke_userv(struct userv *st)
 
     st->pid=makesubproc(userv_entry, userv_userv_callback,
                        er, st, st->slip.nl.name);
-    close(er->stdin);
-    close(er->stdout);
+    close(er->in);
+    close(er->out);
     free(er->argv);
     free(er);
     free(addrs);
index 4c55b454c317defe095bfd01bd3e6b20882fd3c2..dba0ef8193334651ec963dbefd25c196c4bc213a 100644 (file)
@@ -8,6 +8,7 @@
    the packets sent over the wire. */
 
 #include <stdio.h>
+#include <string.h>
 #include "secnet.h"
 #include "util.h"
 #include "serpent.h"
@@ -53,7 +54,7 @@ static bool_t transform_setkey(void *sst, uint8_t *key, uint32_t keylen)
     struct transform_inst *ti=sst;
 
     if (keylen<REQUIRED_KEYLEN) {
-       Message(M_ERROR,"transform_create: insufficient key material supplied "
+       Message(M_ERR,"transform_create: insufficient key material supplied "
                "(need %d bytes, got %d)\n",REQUIRED_KEYLEN,keylen);
        return False;
     }
diff --git a/tun.c b/tun.c
index 0f88791703c68a2d06e1fe122b3c6e12b6a73e92..90b9161022abc0d5c268702733ee1db7190cfb92 100644 (file)
--- a/tun.c
+++ b/tun.c
@@ -64,14 +64,13 @@ static void tun_afterpoll(void *sst, struct pollfd *fds, int nfds,
        }
        if (l>0) {
            st->buff->size=l;
-           st->netlink_to_tunnel(&st->nl,NULL,st->buff);
+           st->netlink_to_tunnel(&st->nl,st->buff);
            BUF_ASSERT_FREE(st->buff);
        }
     }
 }
 
-static void tun_deliver_to_kernel(void *sst, void *cid,
-                                 struct buffer_if *buf)
+static void tun_deliver_to_kernel(void *sst, struct buffer_if *buf)
 {
     struct tun *st=sst;
 
@@ -261,7 +260,7 @@ static list_t *tun_old_apply(closure_t *self, struct cloc loc, dict_t *context,
 
     st->netlink_to_tunnel=
        netlink_init(&st->nl,st,loc,dict,
-                    "netlink-tun",NULL,tun_deliver_to_kernel);
+                    "netlink-tun",tun_set_route,tun_deliver_to_kernel);
 
     st->tun_old=True;
     st->device_path=dict_read_string(dict,"device",False,"tun-netlink",loc);