chiark / gitweb /
Import release 0.1.12 v0.1.12
authorStephen Early <steve@greenend.org.uk>
Mon, 5 Nov 2001 14:51:00 +0000 (14:51 +0000)
committerStephen Early <steve@greenend.org.uk>
Wed, 18 May 2011 17:40:08 +0000 (18:40 +0100)
16 files changed:
Makefile.in
NEWS
TODO
conffile.c
debian/changelog
depend.sh [new file with mode: 0755]
example.conf
install-sh [new file with mode: 0755]
install.sh [deleted file]
netlink.c
netlink.h
resolver.c
secnet.c
secnet.h
slip.c
tun.c

index 9a912b5..80db7d9 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 distclean
+.PHONY:        all clean realclean distclean dist install
 
 PACKAGE:=secnet
-VERSION:=0.1.11
+VERSION:=0.1.12
 
 @SET_MAKE@
 
@@ -54,10 +54,10 @@ DISTFILES:=BUGS COPYING CREDITS INSTALL LICENSE.txt Makefile.in \
        conffile.c conffile.fl conffile.h conffile.y \
        conffile_internal.h config.h.bot \
        config.h.in config.h.top configure \
-       configure.in debian dh.c \
+       configure.in debian depend.sh dh.c \
        example.conf \
        getopt.c getopt1.c getopt.h \
-       install.sh ipaddr.c ipaddr.h ipaddr.py linux log.c md5.c md5.h \
+       install-sh ipaddr.c ipaddr.h ipaddr.py linux log.c md5.c md5.h \
        make-secnet-sites \
        modules.c netlink.c netlink.h process.c process.h \
        random.c resolver.c rsa.c \
@@ -98,20 +98,20 @@ config.status: configure
        ./config.status --recheck
 # End of config file remaking rules
 
-# Manual dependencies section - XXX use autodep eventually
-$(OBJECTS): config.h secnet.h util.h
-conffile.o conffile.tab.o conffile.yy.o: conffile.h conffile_internal.h
-secnet.o: conffile.h process.h
-process.o: process.h
-log.o: process.h
-md5.o: md5.h
-serpent.o transform.o: serpent.h
-serpent.o: serpentsboxes.h
-conffile.o: ipaddr.h
-site.c util.c: unaligned.h
+# C and header file dependency rules
+SOURCES:=$(OBJECTS:.o=.c)
+DEPENDS:=$(OBJECTS:.o=.d)
+
+$(DEPENDS): ${srcdir}/depend.sh
+
+%.d: %.c
+       ${srcdir}/depend.sh $(srcdir) $(CFLAGS) $< > $@
+
+-include $(DEPENDS)
+
+# Manual dependencies section
 conffile.yy.c: conffile.fl conffile.tab.c
 conffile.tab.c:        conffile.y
-netlink.o tun.o slip.o: netlink.h
 # End of manual dependencies section
 
 secnet:        $(OBJECTS)
@@ -120,15 +120,16 @@ version.c: Makefile
        echo "char version[]=\"secnet-$(VERSION)\";" >version.c
 
 install: all
-       $(INSTALL_PROGRAM) -D secnet $(sbindir)/`echo secnet|sed '$(transform)'`
-       $(INSTALL_PROGRAM) -D make-secnet-sites $(sbindir)/`echo make-secnet-sites|sed '$(transform)'`
-       $(INSTALL) -D ipaddr.py $(prefix)/share/secnet/ipaddr.py
+       $(INSTALL) -d $(prefix)/share/secnet $(sbindir)
+       $(INSTALL_PROGRAM) secnet $(sbindir)/`echo secnet|sed '$(transform)'`
+       $(INSTALL_PROGRAM) ${srcdir}/make-secnet-sites $(sbindir)/`echo make-secnet-sites|sed '$(transform)'`
+       $(INSTALL) ${srcdir}/ipaddr.py $(prefix)/share/secnet/ipaddr.py
 
 clean:
        $(RM) -f *.o *.yy.c *.tab.[ch] $(TARGETS) core version.c
 
 realclean:     clean
-       $(RM) -f *~ Makefile config.h \
+       $(RM) -f *~ Makefile config.h  *.d \
        config.log config.status config.cache \
        stamp-h Makefile.bak
 
diff --git a/NEWS b/NEWS
index 60cf744..4ad6647 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,32 @@ Netlink device that implements an Ethernet bridge.
 Modular transform code: choice of block ciphers, modes, sequence
 numbers / timestamps, etc. similar to IWJ's udptunnel
 
+Path-MTU discovery for each tunnel, and fragmentation/DF support in
+netlink code.
+
+* New in version 0.1.12
+
+IMPORTANT: fix calculation of 'now' in secnet.c; necessary for correct
+operation.
+
+(Only interesting for people building and modifying secnet by hand:
+the Makefile now works out most dependencies automatically.)
+
+The netlink code no longer produces an internal routing table sorted
+by netmask length.  Instead, netlink instances have a 'priority'; the
+table of routes is sorted by priority.  Devices like laptops that have
+tunnels that must sometimes 'mask' parts of other tunnels should be
+given higher priorities.  If a priority is not specified it is assumed
+to be zero.
+
+Example usage:
+site laptop { ...
+       link netlink {
+               route "192.168.73.74/31";
+               priority 10;
+       };
+};
+
 * New in version 0.1.11
 
 Lists of IP addresses in the configuration file can now include
diff --git a/TODO b/TODO
index e02c627..c7d8248 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,6 +1,3 @@
-Makefile.in: autodep stuff
-Make it work using the distributed install.sh (which doesn't support -D)
-
 dh.c: change format to binary from decimal string (without introducing
 endianness problems)
 
@@ -8,7 +5,7 @@ netlink.c: test the 'allow_route' option properly.
 
 process.c: capture output from children in sys_cmd() and log it
 
-random.c: test
+random.c: test properly
 
 resolver.c: ought to return a list of addresses for each address; the
 site code ought to remember them and try contacting them in turn.
index 3c629e4..318d608 100644 (file)
@@ -76,8 +76,6 @@ static list_t *dict_ilookup(dict_t *dict, atom_t key)
 static void dict_iadd(dict_t *dict, atom_t key, list_t *val)
 {
     struct entry *e;
-    /* XXX May want to permit redefinition of keys in the future */
-    /* (although it could be very confusing) */
     if (dict_ilookup_primitive(dict, key)) {
        fatal("duplicate key \"%s\" in dictionary\n",key);
     }
index 8ac5260..9931c97 100644 (file)
@@ -1,8 +1,5 @@
-secnet (0.1.11-1) unstable; urgency=low
+secnet (0.1.12-1) unstable; urgency=low
 
   * New upstream version.
 
-  * Note configuration file format has changed slightly; re-run
-    make-secnet-sites to fix it
-
  -- Stephen Early <steve@greenend.org.uk>  Sat, 27 Oct 2001 15:00:00 +0100
diff --git a/depend.sh b/depend.sh
new file mode 100755 (executable)
index 0000000..72fde4b
--- /dev/null
+++ b/depend.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# For more information see "Recursive Make Considered Harmful" at
+# http://www.canb.auug.org.au/~millerp/rmch/recu-make-cons-harm.html
+
+set -e
+set -u
+
+cutout="$1"
+shift
+
+# cutout may contain the character '.' which means a special thing to sed
+# Escape all '.'s (i.e. '..' -> '\.\.')
+cutout2="`echo ${cutout} | sed -e 's@\.@\\\.@g'`"
+
+# We don't bother depending on system header files (which have names
+# starting with '/'). We arrange for both the .o and the .d file to depend
+# on the appropriate header files. We're using VPATH, so we turn pathnames
+# of the form "${srcdir}/foo" into just "foo" (we expect srcdir to be
+# passed as our first command line argument)
+gcc -M -MG "$@" |
+sed -e 's@ /[^ ]*@@g' -e 's@^\(.*\)\.o:@\1.d \1.o:@' -e "s@${cutout2}/@@g"
index 49f2540..b6d5dc2 100644 (file)
@@ -1,22 +1,23 @@
 # secnet example configuration file
 
 # Log facility
-log syslog {
-       ident "secnet";
-       facility "local0";
+log logfile {
+       filename "/var/log/secnet";
+       class "info","notice","warning","error","security","fatal";
+       # There are some useful message classes that could replace
+       # this list:
+       #  'default' -> warning,error,security,fatal
+       #  'verbose' -> info,notice,default
+       #  'quiet'   -> fatal
 };
 
-# Alternatively you could log to a file:
-# log logfile {
-#      filename "/var/log/secnet";
-#      class "info","notice","warning","error","security","fatal";
-#      # There are some useful message classes that could replace
-#      # this list:
-#      #  'default' -> warning,error,security,fatal
-#      #  'verbose' -> info,notice,default
-#      #  'quiet'   -> fatal
+# Alternatively you could log to syslog:
+# log syslog {
+#      ident "secnet";
+#      facility "local0";
 # };
 
+
 # Systemwide configuration (all other configuration is per-site):
 # log          a log facility for program messages
 # userid       who we try to run as after setup
@@ -77,6 +78,10 @@ netlink tun {
        local-address "192.168.x.x"; # IP address of host's tunnel interface
        secnet-address "192.168.x.x"; # IP address of this secnet
 
+       # Tunnels are only allowed to use these networks; attempts to
+       # claim IP addresses in any other ranges is a configuration error
+       remote-networks "192.168.0.0/24", "172.16.0.0/12", "10.0.0.0/8";
+
        # MTU of the tunnel interface. Should be kept under the path-MTU
        # (by at least 60 bytes) between this secnet and its peers for
        # optimum performance.
@@ -129,7 +134,7 @@ log-events "setup-init","setup-timeout","activate-key","timeout-key","errors",
 # that it's non-blocking. XXX 'yes' isn't implemented yet.
 random randomfile("/dev/urandom",no);
 
-# If you're using the make-secnet-sites.py script then your local-name
+# If you're using the make-secnet-sites script then your local-name
 # will be of the form "vpnname/location/site" eg. "sgo/greenend/sinister"
 local-name "your-site-name";
 local-key rsa-private("/etc/secnet/key");
diff --git a/install-sh b/install-sh
new file mode 100755 (executable)
index 0000000..e843669
--- /dev/null
@@ -0,0 +1,250 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission.  M.I.T. makes no representations about the
+# suitability of this software for any purpose.  It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.  It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+       -c) instcmd="$cpprog"
+           shift
+           continue;;
+
+       -d) dir_arg=true
+           shift
+           continue;;
+
+       -m) chmodcmd="$chmodprog $2"
+           shift
+           shift
+           continue;;
+
+       -o) chowncmd="$chownprog $2"
+           shift
+           shift
+           continue;;
+
+       -g) chgrpcmd="$chgrpprog $2"
+           shift
+           shift
+           continue;;
+
+       -s) stripcmd="$stripprog"
+           shift
+           continue;;
+
+       -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+           shift
+           continue;;
+
+       -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+           shift
+           continue;;
+
+       *)  if [ x"$src" = x ]
+           then
+               src=$1
+           else
+               # this colon is to work around a 386BSD /bin/sh bug
+               :
+               dst=$1
+           fi
+           shift
+           continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+       echo "install:  no input file specified"
+       exit 1
+else
+       true
+fi
+
+if [ x"$dir_arg" != x ]; then
+       dst=$src
+       src=""
+       
+       if [ -d $dst ]; then
+               instcmd=:
+       else
+               instcmd=mkdir
+       fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad 
+# if $src (and thus $dsttmp) contains '*'.
+
+       if [ -f $src -o -d $src ]
+       then
+               true
+       else
+               echo "install:  $src does not exist"
+               exit 1
+       fi
+       
+       if [ x"$dst" = x ]
+       then
+               echo "install:  no destination specified"
+               exit 1
+       else
+               true
+       fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+       if [ -d $dst ]
+       then
+               dst="$dst"/`basename $src`
+       else
+               true
+       fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='   
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+       pathcomp="${pathcomp}${1}"
+       shift
+
+       if [ ! -d "${pathcomp}" ] ;
+        then
+               $mkdirprog "${pathcomp}"
+       else
+               true
+       fi
+
+       pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+       $doit $instcmd $dst &&
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+       if [ x"$transformarg" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               dstfile=`basename $dst $transformbasename | 
+                       sed $transformarg`$transformbasename
+       fi
+
+# don't allow the sed command to completely eliminate the filename
+
+       if [ x"$dstfile" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               true
+       fi
+
+# Make a temp file name in the proper directory.
+
+       dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+       $doit $instcmd $src $dsttmp &&
+
+       trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+       $doit $rmcmd -f $dstdir/$dstfile &&
+       $doit $mvcmd $dsttmp $dstdir/$dstfile 
+
+fi &&
+
+
+exit 0
diff --git a/install.sh b/install.sh
deleted file mode 100755 (executable)
index 0ff4b6a..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-#!/bin/sh
-
-#
-# install - install a program, script, or datafile
-# This comes from X11R5; it is not part of GNU.
-#
-# $XConsortium: install.sh,v 1.2 89/12/18 14:47:22 jim Exp $
-#
-# This script is compatible with the BSD install script, but was written
-# from scratch.
-#
-
-
-# set DOITPROG to echo to test this script
-
-# Don't use :- since 4.3BSD and earlier shells don't like it.
-doit="${DOITPROG-}"
-
-
-# put in absolute paths if you don't have them in your path; or use env. vars.
-
-mvprog="${MVPROG-mv}"
-cpprog="${CPPROG-cp}"
-chmodprog="${CHMODPROG-chmod}"
-chownprog="${CHOWNPROG-chown}"
-chgrpprog="${CHGRPPROG-chgrp}"
-stripprog="${STRIPPROG-strip}"
-rmprog="${RMPROG-rm}"
-
-instcmd="$mvprog"
-chmodcmd=""
-chowncmd=""
-chgrpcmd=""
-stripcmd=""
-rmcmd="$rmprog -f"
-mvcmd="$mvprog"
-src=""
-dst=""
-
-while [ x"$1" != x ]; do
-    case $1 in
-       -c) instcmd="$cpprog"
-           shift
-           continue;;
-
-       -m) chmodcmd="$chmodprog $2"
-           shift
-           shift
-           continue;;
-
-       -o) chowncmd="$chownprog $2"
-           shift
-           shift
-           continue;;
-
-       -g) chgrpcmd="$chgrpprog $2"
-           shift
-           shift
-           continue;;
-
-       -s) stripcmd="$stripprog"
-           shift
-           continue;;
-
-       *)  if [ x"$src" = x ]
-           then
-               src=$1
-           else
-               dst=$1
-           fi
-           shift
-           continue;;
-    esac
-done
-
-if [ x"$src" = x ]
-then
-       echo "install:  no input file specified"
-       exit 1
-fi
-
-if [ x"$dst" = x ]
-then
-       echo "install:  no destination specified"
-       exit 1
-fi
-
-
-# If destination is a directory, append the input filename; if your system
-# does not like double slashes in filenames, you may need to add some logic
-
-if [ -d $dst ]
-then
-       dst="$dst"/`basename $src`
-fi
-
-# Make a temp file name in the proper directory.
-
-dstdir=`dirname $dst`
-dsttmp=$dstdir/#inst.$$#
-
-# Move or copy the file name to the temp name
-
-$doit $instcmd $src $dsttmp
-
-# and set any options; do chmod last to preserve setuid bits
-
-if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; fi
-if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; fi
-if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; fi
-if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; fi
-
-# Now rename the file to the real destination.
-
-$doit $rmcmd $dst
-$doit $mvcmd $dsttmp $dst
-
-
-exit 0
index e41445c..b6650eb 100644 (file)
--- a/netlink.c
+++ b/netlink.c
@@ -266,7 +266,8 @@ static bool_t netlink_check(struct netlink *st, struct buffer_if *buf)
 }
 
 /* Deliver a packet. "client" is the _origin_ of the packet, not its
-destination.  */
+   destination, and is NULL for packets from the host and packets
+   generated internally in secnet.  */
 static void netlink_packet_deliver(struct netlink *st,
                                   struct netlink_client *client,
                                   struct buffer_if *buf)
@@ -288,7 +289,7 @@ static void netlink_packet_deliver(struct netlink *st,
        return;
     }
     
-    /* Packets from the host (client==NULL) will always be routed.  Packets
+    /* Packets from the host (client==NULL) may 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;
@@ -301,8 +302,9 @@ static void netlink_packet_deliver(struct netlink *st,
 
     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)) {
+    for (i=0; i<st->n_clients; i++) {
+       if (st->routes[i]->up &&
+           ipset_contains_addr(st->routes[i]->networks,dest)) {
            /* It's an available route to the correct destination. But is
               it better than the one we already have? */
 
@@ -310,14 +312,14 @@ static void netlink_packet_deliver(struct netlink *st,
               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;
+               if (!(st->routes[i]->options&OPT_ALLOWROUTE)) continue;
            }
            
-           if (st->routes[i].c->link_quality>best_quality
+           if (st->routes[i]->link_quality>best_quality
                || best_quality==0) {
-               best_quality=st->routes[i].c->link_quality;
+               best_quality=st->routes[i]->link_quality;
                best_match=i;
-               if (st->routes[i].c->options&OPT_ALLOWROUTE)
+               if (st->routes[i]->options&OPT_ALLOWROUTE)
                    found_allowed=True;
                /* If quality isn't perfect we may wish to
                   consider kicking the tunnel with a 0-length
@@ -350,7 +352,7 @@ static void netlink_packet_deliver(struct netlink *st,
        }
     } else {
        if (!allow_route &&
-           !(st->routes[best_match].c->options&OPT_ALLOWROUTE)) {
+           !(st->routes[best_match]->options&OPT_ALLOWROUTE)) {
            string_t s,d;
            s=ipaddr_to_string(source);
            d=ipaddr_to_string(dest);
@@ -365,9 +367,10 @@ static void netlink_packet_deliver(struct netlink *st,
            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++;
+           /* XXX Fragment if required */
+           st->routes[best_match]->deliver(
+               st->routes[best_match]->dst, buf);
+           st->routes[best_match]->outcount++;
            BUF_ASSERT_FREE(buf);
        } else {
            /* Generate ICMP destination unreachable */
@@ -465,9 +468,9 @@ static void netlink_incoming(struct netlink *st, struct netlink_client *client,
     source=ntohl(iph->saddr);
     dest=ntohl(iph->daddr);
 
-    /* Check source */
-    /* XXX consider generating ICMP if we're not point-to-point and we
-       don't like the packet */
+    /* Check source. If we don't like the source, there's no point
+       generating ICMP because we won't know how to get it to the
+       source of the packet. */
     if (client) {
        /* Check that the packet source is appropriate for the tunnel
           it came down */
@@ -500,8 +503,8 @@ static void netlink_incoming(struct netlink *st, struct netlink_client *client,
     /* If this is a point-to-point device we don't examine the
        destination address at all; we blindly send it down our
        one-and-only registered tunnel, or to the host, depending on
-       where it came from. */
-    /* XXX I think we should check destination addresses */
+       where it came from.  It's up to external software to check
+       address validity and generate ICMP, etc. */
     if (st->ptp) {
        if (client) {
            st->deliver_to_host(st->dst,buf);
@@ -512,8 +515,8 @@ static void netlink_incoming(struct netlink *st, struct netlink_client *client,
        return;
     }
 
-    /* (st->secnet_address needs checking before matching destination
-       addresses) */
+    /* st->secnet_address needs checking before matching destination
+       addresses */
     if (dest==st->secnet_address) {
        netlink_packet_local(st,client,buf);
        BUF_ASSERT_FREE(buf);
@@ -538,33 +541,28 @@ static void netlink_dev_incoming(void *sst, struct buffer_if *buf)
     netlink_incoming(st,NULL,buf);
 }
 
-static void netlink_set_softlinks(struct netlink *st, struct netlink_client *c,
-                                 bool_t up, uint32_t quality)
+static void netlink_set_quality(void *sst, uint32_t quality)
 {
-    uint32_t i;
+    struct netlink_client *c=sst;
+    struct netlink *st=c->nst;
 
-    if (!st->routes) return; /* Table has not yet been created */
-    for (i=0; i<st->n_routes; i++) {
-       if (st->routes[i].c==c) {
-           st->routes[i].quality=quality;
-           if (!st->routes[i].hard) {
-               st->routes[i].up=up;
-               st->set_route(st->dst,&st->routes[i]);
-           }
-       }
+    c->link_quality=quality;
+    c->up=(c->link_quality==LINK_QUALITY_DOWN)?False:True;
+    if (c->options&OPT_SOFTROUTE) {
+       st->set_routes(st->dst,c);
     }
 }
 
-static void netlink_set_quality(void *sst, uint32_t quality)
+static void netlink_output_subnets(struct netlink *st, uint32_t loglevel,
+                                  struct subnet_list *snets)
 {
-    struct netlink_client *c=sst;
-    struct netlink *st=c->nst;
+    uint32_t i;
+    string_t net;
 
-    c->link_quality=quality;
-    if (c->link_quality==LINK_QUALITY_DOWN) {
-       netlink_set_softlinks(st,c,False,c->link_quality);
-    } else {
-       netlink_set_softlinks(st,c,True,c->link_quality);
+    for (i=0; i<snets->entries; i++) {
+       net=subnet_to_string(snets->list[i]);
+       Message(loglevel,"%s ",net);
+       free(net);
     }
 }
 
@@ -580,24 +578,19 @@ static void netlink_dump_routes(struct netlink *st, bool_t requested)
        Message(c,"%s: point-to-point (remote end is %s); routes:\n",
                st->name, net);
        free(net);
-       for (i=0; i<st->n_routes; i++) {
-           net=subnet_to_string(st->routes[i].net);
-           Message(c,"%s ",net);
-           free(net);
-       }
+       netlink_output_subnets(st,c,st->clients->subnets);
        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);
+       for (i=0; i<st->n_clients; i++) {
+           netlink_output_subnets(st,c,st->routes[i]->subnets);
+           Message(c,"-> tunnel %s (%s,%s routes,%s,quality %d,use %d)\n",
+                   st->routes[i]->name,
+                   st->routes[i]->options&OPT_SOFTROUTE?"soft":"hard",
+                   st->routes[i]->options&OPT_ALLOWROUTE?"free":"restricted",
+                   st->routes[i]->up?"up":"down",
+                   st->routes[i]->link_quality,
+                   st->routes[i]->outcount);
        }
        net=ipaddr_to_string(st->secnet_address);
        Message(c,"%s/32 -> netlink \"%s\" (use %d)\n",
@@ -613,13 +606,14 @@ static void netlink_dump_routes(struct netlink *st, bool_t requested)
     }
 }
 
-static int netlink_compare_route_specificity(const void *ap, const void *bp)
+/* ap is a pointer to a member of the routes array */
+static int netlink_compare_client_priority(const void *ap, const void *bp)
 {
-    const struct netlink_route *a=ap;
-    const struct netlink_route *b=bp;
+    const struct netlink_client *const*a=ap;
+    const struct netlink_client *const*b=bp;
 
-    if (a->net.len==b->net.len) return 0;
-    if (a->net.len<b->net.len) return 1;
+    if ((*a)->priority==(*b)->priority) return 0;
+    if ((*a)->priority<(*b)->priority) return 1;
     return -1;
 }
 
@@ -627,42 +621,20 @@ static void netlink_phase_hook(void *sst, uint32_t new_phase)
 {
     struct netlink *st=sst;
     struct netlink_client *c;
-    uint32_t i,j;
+    uint32_t i;
 
     /* 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.  */
-    st->routes=safe_malloc(st->n_routes*sizeof(*st->routes),
+     * clients by priority.  */
+    st->routes=safe_malloc(st->n_clients*sizeof(*st->routes),
                           "netlink_phase_hook");
     /* Fill the table */
     i=0;
-    for (c=st->clients; c; c=c->next) {
-       for (j=0; j<c->subnets->entries; j++) {
-           st->routes[i].net=c->subnets->list[j];
-           st->routes[i].c=c;
-           /* Hard routes are always up;
-              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&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++;
-       }
-    }
-    /* ASSERT i==st->n_routes */
-    if (i!=st->n_routes) {
-       fatal("netlink: route count error: expected %d got %d\n",
-             st->n_routes,i);
-    }
-    /* Sort the table in descending order of specificity */
-    qsort(st->routes,st->n_routes,sizeof(*st->routes),
-         netlink_compare_route_specificity);
+    for (c=st->clients; c; c=c->next)
+       st->routes[i++]=c;
+    /* Sort the table in descending order of priority */
+    qsort(st->routes,st->n_clients,sizeof(*st->routes),
+         netlink_compare_client_priority);
 
     netlink_dump_routes(st,False);
 }
@@ -695,6 +667,13 @@ static bool_t netlink_inst_check_config(void *sst, struct buffer_if *buf)
     return True;
 }
 
+static void netlink_inst_set_mtu(void *sst, uint32_t new_mtu)
+{
+    struct netlink_client *c=sst;
+
+    c->mtu=new_mtu;
+}
+
 static void netlink_inst_reg(void *sst, netlink_deliver_fn *deliver, 
                             void *dst, uint32_t max_start_pad,
                             uint32_t max_end_pad)
@@ -724,7 +703,7 @@ static closure_t *netlink_inst_create(struct netlink *st,
     struct netlink_client *c;
     string_t name;
     struct ipset *networks;
-    uint32_t options;
+    uint32_t options,priority,mtu;
     list_t *l;
 
     name=dict_read_string(dict, "name", True, st->name, loc);
@@ -736,7 +715,10 @@ static closure_t *netlink_inst_create(struct netlink *st,
     options=string_list_to_word(dict_lookup(dict,"options"),
                                netlink_option_table,st->name);
 
-    if ((options&OPT_SOFTROUTE) && !st->set_route) {
+    priority=dict_read_number(dict,"priority",False,st->name,loc,0);
+    mtu=dict_read_number(dict,"mtu",False,st->name,loc,0);
+
+    if ((options&OPT_SOFTROUTE) && !st->set_routes) {
        cfgfatal(loc,st->name,"this netlink device does not support "
                 "soft routes.\n");
        return NULL;
@@ -772,18 +754,24 @@ static closure_t *netlink_inst_create(struct netlink *st,
     c->ops.set_quality=netlink_set_quality;
     c->ops.output_config=netlink_inst_output_config;
     c->ops.check_config=netlink_inst_check_config;
+    c->ops.set_mtu=netlink_inst_set_mtu;
     c->nst=st;
 
     c->networks=networks;
     c->subnets=ipset_to_subnet_list(networks);
+    c->priority=priority;
     c->deliver=NULL;
     c->dst=NULL;
     c->name=name;
-    c->options=options;
     c->link_quality=LINK_QUALITY_DOWN;
+    c->mtu=mtu?mtu:st->mtu;
+    c->options=options;
+    c->outcount=0;
+    c->up=False;
+    c->kup=False;
     c->next=st->clients;
     st->clients=c;
-    st->n_routes+=c->subnets->entries;
+    st->n_clients++;
 
     return &c->cl;
 }
@@ -811,7 +799,7 @@ static list_t *netlink_inst_apply(closure_t *self, struct cloc loc,
 netlink_deliver_fn *netlink_init(struct netlink *st,
                                 void *dst, struct cloc loc,
                                 dict_t *dict, string_t description,
-                                netlink_route_fn *set_route,
+                                netlink_route_fn *set_routes,
                                 netlink_deliver_fn *to_host)
 {
     item_t *sa, *ptpa;
@@ -825,7 +813,9 @@ netlink_deliver_fn *netlink_init(struct netlink *st,
     st->max_start_pad=0;
     st->max_end_pad=0;
     st->clients=NULL;
-    st->set_route=set_route;
+    st->routes=NULL;
+    st->n_clients=0;
+    st->set_routes=set_routes;
     st->deliver_to_host=to_host;
 
     st->name=dict_read_string(dict,"name",False,description,loc);
@@ -866,14 +856,12 @@ netlink_deliver_fn *netlink_init(struct netlink *st,
        st->secnet_address=string_item_to_ipaddr(ptpa,"netlink");
        st->ptp=True;
     }
-    /* XXX we may want to subtract secnet_address from networks here, to
-       be strictly correct.  It shouldn't make any practical difference,
+    /* To be strictly correct we could subtract secnet_address from
+       networks here.  It shouldn't make any practical difference,
        though, and will make the route dump look complicated... */
     st->subnets=ipset_to_subnet_list(st->networks);
     st->mtu=dict_read_number(dict, "mtu", False, "netlink", loc, DEFAULT_MTU);
     buffer_new(&st->icmp,ICMP_BUFSIZE);
-    st->n_routes=0;
-    st->routes=NULL;
     st->outcount=0;
     st->localcount=0;
 
@@ -898,17 +886,15 @@ struct null {
     struct netlink nl;
 };
 
-static bool_t null_set_route(void *sst, struct netlink_route *route)
+static bool_t null_set_route(void *sst, struct netlink_client *routes)
 {
     struct null *st=sst;
-    string_t t;
-
-    if (route->up!=route->kup) {
-       t=subnet_to_string(route->net);
-       Message(M_INFO,"%s: setting route %s to state %s\n",st->nl.name,
-               t, route->up?"up":"down");
-       free(t);
-       route->kup=route->up;
+
+    if (routes->up!=routes->kup) {
+       Message(M_INFO,"%s: setting routes for tunnel %s to state %s\n",
+               st->nl.name,routes->name,
+               routes->up?"up":"down");
+       routes->kup=routes->up;
        return True;
     }
     return False;
index 9f46fa8..a54ec01 100644 (file)
--- a/netlink.h
+++ b/netlink.h
@@ -15,26 +15,23 @@ struct netlink_client {
     struct netlink *nst;
     struct ipset *networks;
     struct subnet_list *subnets; /* Same information as 'networks' */
+    uint32_t priority; /* Higher priority clients have their networks
+                         checked first during routing.  This allows
+                         things like laptops to supersede whole
+                         networks. */
     netlink_deliver_fn *deliver;
     void *dst;
     string_t name;
     uint32_t link_quality;
+    uint32_t mtu;
     uint32_t options;
-    struct netlink_client *next;
-};
-
-struct netlink_route {
-    struct subnet net;
-    bool_t hard;
-    bool_t allow_route;
-    bool_t up;
-    bool_t kup;
-    uint32_t quality; /* provided by client */
     uint32_t outcount;
-    struct netlink_client *c;
+    bool_t up; /* Should these routes exist in the kernel? */
+    bool_t kup; /* Do these routes exist in the kernel? */
+    struct netlink_client *next;
 };
 
-typedef bool_t netlink_route_fn(void *cst, struct netlink_route *route);
+typedef bool_t netlink_route_fn(void *cst, struct netlink_client *routes);
 
 /* Netlink provides one function to the device driver, to call to deliver
    a packet from the device. The device driver provides one function to
@@ -47,18 +44,18 @@ struct netlink {
     uint32_t max_start_pad;
     uint32_t max_end_pad;
     struct ipset *networks; /* Local networks */
-    struct subnet_list *subnets; /* Same information as networks */
+    struct subnet_list *subnets; /* Same as networks, for display */
     struct ipset *remote_networks; /* Allowable remote networks */
     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;
+    struct netlink_client *clients; /* Linked list of clients */
+    struct netlink_client **routes; /* Array of clients, sorted by priority */
+    uint32_t n_clients;
     netlink_deliver_fn *deliver_to_host; /* Provided by driver */
-    netlink_route_fn *set_route; /* Provided by driver */
+    netlink_route_fn *set_routes; /* Provided by driver */
     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 */
 };
@@ -66,7 +63,7 @@ struct netlink {
 extern netlink_deliver_fn *netlink_init(struct netlink *st,
                                        void *dst, struct cloc loc,
                                        dict_t *dict, string_t description,
-                                       netlink_route_fn *set_route,
+                                       netlink_route_fn *set_routes,
                                        netlink_deliver_fn *to_host);
 
 #endif /* netlink_h */
index 9e0530c..282db80 100644 (file)
@@ -2,8 +2,12 @@
 
 #include <errno.h>
 #include "secnet.h"
+#ifndef HAVE_LIBADNS
+#error secnet requires ADNS version 1.0 or above
+#endif
 #include <adns.h>
 
+
 struct adns {
     closure_t cl;
     struct resolver_if ops;
index 20f9999..39a635a 100644 (file)
--- a/secnet.c
+++ b/secnet.c
@@ -281,7 +281,8 @@ static void run(void)
        if (gettimeofday(&tv_now, NULL)!=0) {
            fatal_perror("main loop: gettimeofday");
        }
-       now=(tv_now.tv_sec*1000)+(tv_now.tv_usec/1000);
+       now=((uint64_t)tv_now.tv_sec*(uint64_t)1000)+
+           ((uint64_t)tv_now.tv_usec/(uint64_t)1000);
        idx=0;
        for (i=reg; i; i=i->next) {
            i->after(i->state, fds+idx, i->nfds, &tv_now, &now);
index c40ed1b..7cdeeda 100644 (file)
--- a/secnet.h
+++ b/secnet.h
@@ -368,6 +368,7 @@ typedef void netlink_register_fn(void *st, netlink_deliver_fn *deliver,
                                 uint32_t max_end_pad);
 typedef void netlink_output_config_fn(void *st, struct buffer_if *buf);
 typedef bool_t netlink_check_config_fn(void *st, struct buffer_if *buf);
+typedef void netlink_set_mtu_fn(void *st, uint32_t new_mtu);
 struct netlink_if {
     void *st;
     netlink_register_fn *reg;
@@ -375,6 +376,7 @@ struct netlink_if {
     netlink_link_quality_fn *set_quality;
     netlink_output_config_fn *output_config;
     netlink_check_config_fn *check_config;
+    netlink_set_mtu_fn *set_mtu;
 };
 
 /* DH interface */
diff --git a/slip.c b/slip.c
index 60152c9..fe6cb15 100644 (file)
--- a/slip.c
+++ b/slip.c
@@ -37,7 +37,7 @@ static void slip_stuff(struct slip *st, struct buffer_if *buf, int fd)
 
     BUF_ASSERT_USED(buf);
 
-    /* XXX crunchy bytestuff code */
+    /* There's probably a much more efficient way of implementing this */
     txbuf[j++]=SLIP_END;
     for (i=buf->start; i<(buf->start+buf->size); i++) {
        switch (*i) {
@@ -71,8 +71,6 @@ static void slip_unstuff(struct slip *st, uint8_t *buf, uint32_t l)
 {
     uint32_t i;
 
-    /* XXX really crude unstuff code */
-    /* XXX check for buffer overflow */
     BUF_ASSERT_USED(st->buff);
     for (i=0; i<l; i++) {
        if (st->pending_esc) {
@@ -239,8 +237,8 @@ static void userv_invoke_userv(struct userv *st)
     string_t addrs;
     string_t nets;
     string_t s;
-    struct netlink_route *r;
-    struct ipset *isnets;
+    struct netlink_client *r;
+    struct ipset *allnets;
     struct subnet_list *snets;
     int i;
     uint8_t confirm;
@@ -257,21 +255,18 @@ static void userv_invoke_userv(struct userv *st)
             ipaddr_to_string(st->slip.local_address),
             ipaddr_to_string(st->slip.nl.secnet_address),st->slip.nl.mtu);
 
-    r=st->slip.nl.routes;
-    isnets=ipset_new();
-    for (i=0; i<st->slip.nl.n_routes; i++) {
-       if (r[i].up) {
-           struct ipset *sn,*nis;
-           r[i].kup=True;
-           sn=ipset_from_subnet(r[i].net);
-           nis=ipset_union(isnets,sn);
-           ipset_free(sn);
-           ipset_free(isnets);
-           isnets=nis;
+    allnets=ipset_new();
+    for (r=st->slip.nl.clients; r; r=r->next) {
+       if (r->up) {
+           struct ipset *nan;
+           r->kup=True;
+           nan=ipset_union(allnets,r->networks);
+           ipset_free(allnets);
+           allnets=nan;
        }
     }
-    snets=ipset_to_subnet_list(isnets);
-    ipset_free(isnets);
+    snets=ipset_to_subnet_list(allnets);
+    ipset_free(allnets);
     nets=safe_malloc(20*snets->entries,"userv_invoke_userv:nets");
     *nets=0;
     for (i=0; i<snets->entries; i++) {
@@ -412,9 +407,4 @@ init_module slip_module;
 void slip_module(dict_t *dict)
 {
     add_closure(dict,"userv-ipif",userv_apply);
-#if 0
-    /* TODO */
-    add_closure(dict,"pty-slip",ptyslip_apply);
-    add_closure(dict,"slipd",slipd_apply);
-#endif /* 0 */
 }
diff --git a/tun.c b/tun.c
index 20ae29b..74247f5 100644 (file)
--- a/tun.c
+++ b/tun.c
@@ -81,22 +81,27 @@ static void tun_deliver_to_kernel(void *sst, struct buffer_if *buf)
     BUF_FREE(buf);
 }
 
-static bool_t tun_set_route(void *sst, struct netlink_route *route)
+static bool_t tun_set_route(void *sst, struct netlink_client *routes)
 {
     struct tun *st=sst;
     string_t network, mask, secnetaddr;
-
-    if (route->up != route->kup) {
-       network=ipaddr_to_string(route->net.prefix);
-       mask=ipaddr_to_string(route->net.mask);
-       secnetaddr=ipaddr_to_string(st->nl.secnet_address);
-       Message(M_INFO,"%s: %s route %s/%d %s kernel routing table\n",
-               st->nl.name,route->up?"adding":"deleting",network,
-               route->net.len,route->up?"to":"from");
-       sys_cmd(st->route_path,"route",route->up?"add":"del","-net",network,
-               "netmask",mask,"gw",secnetaddr,(char *)0);
-       free(network); free(mask); free(secnetaddr);
-       route->kup=route->up;
+    struct subnet_list *nets;
+    uint32_t i;
+
+    if (routes->up != routes->kup) {
+       nets=routes->subnets;
+       for (i=0; i<nets->entries; i++) {
+           network=ipaddr_to_string(nets->list[i].prefix);
+           mask=ipaddr_to_string(nets->list[i].mask);
+           secnetaddr=ipaddr_to_string(st->nl.secnet_address);
+           Message(M_INFO,"%s: %s route %s/%d %s kernel routing table\n",
+                   st->nl.name,routes->up?"adding":"deleting",network,
+                   nets->list[i].len,routes->up?"to":"from");
+           sys_cmd(st->route_path,"route",routes->up?"add":"del",
+                   "-net",network,"netmask",mask,"gw",secnetaddr,(char *)0);
+           free(network); free(mask); free(secnetaddr);
+       }
+       routes->kup=routes->up;
        return True;
     }
     return False;
@@ -107,9 +112,7 @@ static void tun_phase_hook(void *sst, uint32_t newphase)
     struct tun *st=sst;
     string_t hostaddr,secnetaddr;
     uint8_t mtu[6];
-    string_t network,mask;
-    struct netlink_route *r;
-    int i;
+    struct netlink_client *r;
 
     if (st->tun_old) {
        if (st->search_for_if) {
@@ -180,19 +183,15 @@ static void tun_phase_hook(void *sst, uint32_t newphase)
     snprintf(mtu,6,"%d",st->nl.mtu);
     mtu[5]=0;
 
+    /* XXX on FreeBSD the "-broadcast" and "pointopoint" must be left
+       out. It assumes a point-to-point interface if two IP addresses
+       are specified. */
     sys_cmd(st->ifconfig_path,"ifconfig",st->interface_name,
            hostaddr,"netmask","255.255.255.255","-broadcast",
            "pointopoint",secnetaddr,"mtu",mtu,"up",(char *)0);
 
-    r=st->nl.routes;
-    for (i=0; i<st->nl.n_routes; i++) {
-       if (r[i].up && !r[i].kup) {
-           network=ipaddr_to_string(r[i].net.prefix);
-           mask=ipaddr_to_string(r[i].net.mask);
-           sys_cmd(st->route_path,"route","add","-net",network,
-                   "netmask",mask,"gw",secnetaddr,(char *)0);
-           r[i].kup=True;
-       }
+    for (r=st->nl.clients; r; r=r->next) {
+       tun_set_route(st,r);
     }
 
     /* Register for poll() */