chiark / gitweb /
Import release 0.1.0 v0.1.0
authorStephen Early <steve@greenend.org.uk>
Tue, 25 Sep 2001 23:19:00 +0000 (00:19 +0100)
committerStephen Early <steve@greenend.org.uk>
Wed, 18 May 2011 12:25:01 +0000 (13:25 +0100)
INSTALL
Makefile.in
NOTES
TODO
netlink.c
rsa.c
secnet.c
secnet.h
site.c
udp.c
util.c

diff --git a/INSTALL b/INSTALL
index db1fabf..af48a93 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -7,6 +7,8 @@ VERSIONS.
 PROTOCOL COMPATIBILITY WAS BROKEN BETWEEN secnet-0.06, secnet-0.07 AND
 secnet-0.08 FOR ENDIANNESS FIXES.
 
+THERE WILL BE ANOTHER CHANGE IN PROTOCOL IN THE secnet-0.1.x SERIES
+
 * Preparation
 
 ** System software support
index 5465a36..a06fcae 100644 (file)
@@ -18,7 +18,7 @@
 .PHONY:        all clean realclean dist install
 
 PACKAGE:=secnet
-VERSION:=0.09
+VERSION:=0.1.0
 
 @SET_MAKE@
 
diff --git a/NOTES b/NOTES
index a815905..8e53ac7 100644 (file)
--- a/NOTES
+++ b/NOTES
@@ -77,14 +77,14 @@ is always fresh.
 
 Messages:
 
-1) A->B: *,iA,msg1,A,B,nA
+1) A->B: *,iA,msg1,A,B,protorange-A,nA
 
-2) B->A: iA,iB,msg2,B,A,nB,nA
+2) B->A: iA,iB,msg2,B,A,chosen-protocol,nB,nA
 
 (The order of B and A reverses in alternate messages so that the same
 code can be used to construct them...)
 
-3) A->B: {iB,iA,msg3,A,B,nA,nB,g^x mod m}_PK_A^-1
+3) A->B: {iB,iA,msg3,A,B,protorange-A,chosen-protocol,nA,nB,g^x mod m}_PK_A^-1
 
 If message 1 was a replay then A will not generate message 3, because
 it doesn't recognise nA.
@@ -92,11 +92,18 @@ it doesn't recognise nA.
 If message 2 was from an attacker then B will not generate message 4,
 because it doesn't recognise nB.
 
-4) B->A: {iA,iB,msg4,B,A,nB,nA,g^y mod m}_PK_B^-1
+If an attacker is trying to manipulate the chosen protocol, B can spot
+this when it sees A's message 3.
+
+4) B->A: {iA,iB,msg4,B,A,protorange-B,chosen-protocol,nB,nA,g^y mod m}_PK_B^-1
 
 At this point, A and B share a key, k. B must keep retransmitting
 message 4 until it receives a packet encrypted using key k.
 
+A can abandon the exchange if the chosen protocol is not the one that
+it would have chosen knowing the acceptable protocol ranges of A and
+B.
+
 5) A: iB,iA,msg5,(ping/msg5)_k
 
 6) B: iA,iB,msg6,(pong/msg6)_k
diff --git a/TODO b/TODO
index 3f5f028..071a716 100644 (file)
--- a/TODO
+++ b/TODO
@@ -20,11 +20,10 @@ secnet.c: done
 
 site.c: the site_incoming() routing could be implemented much more
 cleanly using a table. There's still quite a lot of redundancy in this
-file. Abandon key exchanges when a bad packet is received. Tell
-netlink link is down if it's down and we don't have address for other
-end.
+file. Abandon key exchanges when a bad packet is received. Modify
+protocol to include version fields, as described in the NOTES file.
 
-transform.c: done. Needs checking for endianness problems.
+transform.c: done. JDA reports endianness problems are fixed.
 
 udp.c: done
 
index 3fbc3cf..0cbb27d 100644 (file)
--- a/netlink.c
+++ b/netlink.c
@@ -1,18 +1,19 @@
 /* User-kernel network link */
 
-/* We will eventually support a variety of methods for extracting
-   packets from the kernel: userv-ipif, ipif on its own (when we run
-   as root), the kernel TUN driver, SLIP to a pty, an external netlink
-   daemon. There is a performance/security tradeoff. */
+/* We support a variety of methods for extracting packets from the
+   kernel: userv-ipif, ipif on its own (when we run as root), the
+   kernel TUN driver.  Possible future methods: SLIP to a pty, an
+   external netlink daemon.  There is a performance/security
+   tradeoff. */
 
 /* When dealing with SLIP (to a pty, or ipif) we have separate rx, tx
-   and client buffers. When receiving we may read() any amount, not
-   just whole packets. When transmitting we need to bytestuff anyway,
+   and client buffers.  When receiving we may read() any amount, not
+   just whole packets.  When transmitting we need to bytestuff anyway,
    and may be part-way through receiving. */
 
-/* Each netlink device is actually a router, with its own IP
-   address. We do things like decreasing the TTL and recalculating the
-   header checksum, generating ICMP, responding to pings, etc. */
+/* Each netlink device is actually a router, with its own IP address.
+   We do things like decreasing the TTL and recalculating the header
+   checksum, generating ICMP, responding to pings, etc. */
 
 /* This is where we have the anti-spoofing paranoia - before sending a
    packet to the kernel we check that the tunnel it came over could
@@ -31,7 +32,7 @@
 #include <linux/if_tun.h>
 #endif
 
-/* XXX where do we find if_tun on other architectures? */
+/* XXX where do we find if_tun on other platforms? */
 
 #define DEFAULT_BUFSIZE 2048
 #define DEFAULT_MTU 1000
@@ -63,6 +64,7 @@ struct netlink {
     uint32_t max_start_pad;
     uint32_t max_end_pad;
     struct subnet_list networks;
+    struct subnet_list exclude_remote_networks;
     uint32_t local_address; /* host interface address */
     uint32_t secnet_address; /* our own address */
     uint32_t mtu;
@@ -534,6 +536,20 @@ static void *netlink_regnets(void *sst, struct subnet_list *nets,
            "max_start_pad=%d, max_end_pad=%d\n",
            nets->entries,max_start_pad,max_end_pad);
 
+    /* Check that nets does not intersect with st->networks or
+       st->exclude_remote_networks; refuse to register if it does. */
+    if (subnet_lists_intersect(&st->networks,nets)) {
+       Message(M_ERROR,"%s: site %s specifies networks that "
+               "intersect with our local networks\n",st->name,client_name);
+       return False;
+    }
+    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 False;
+    }
+
     c=safe_malloc(sizeof(*c),"netlink_regnets");
     c->networks=nets;
     c->deliver=deliver;
@@ -571,13 +587,15 @@ static netlink_deliver_fn *netlink_init(struct netlink *st,
     if (!st->name) st->name=description;
     dict_read_subnet_list(dict, "networks", True, "netlink", loc,
                          &st->networks);
+    dict_read_subnet_list(dict, "exclude-remote-networks", False, "netlink",
+                         loc, &st->exclude_remote_networks);
+    /* local-address and secnet-address do not have to be in local-networks;
+       however, they should be advertised in the 'sites' file for the
+       local site. */
     st->local_address=string_to_ipaddr(
        dict_find_item(dict,"local-address", True, "netlink", loc),"netlink");
     st->secnet_address=string_to_ipaddr(
        dict_find_item(dict,"secnet-address", True, "netlink", loc),"netlink");
-    if (!subnet_match(&st->networks,st->local_address)) {
-       cfgfatal(loc,"netlink","local-address must be in local networks\n");
-    }
     st->mtu=dict_read_number(dict, "mtu", False, "netlink", loc, DEFAULT_MTU);
     buffer_new(&st->icmp,ICMP_BUFSIZE);
 
@@ -842,6 +860,8 @@ struct tun {
     string_t interface_name;
     string_t ifconfig_path;
     string_t route_path;
+    bool_t tun_old;
+    bool_t search_for_if; /* Applies to tun-old only */
     struct buffer_if *buff; /* We receive packets into here
                               and send them to the netlink code. */
     netlink_deliver_fn *netlink_to_tunnel;
@@ -906,6 +926,65 @@ static void tun_phase_hook(void *sst, uint32_t newphase)
     struct netlink_client *c;
     int i;
 
+    if (st->tun_old) {
+       if (st->search_for_if) {
+           string_t dname;
+           int i;
+
+           /* ASSERT st->interface_name */
+           dname=safe_malloc(strlen(st->device_path)+4,"tun_old_apply");
+           st->interface_name=safe_malloc(8,"tun_phase_hook");
+       
+           for (i=0; i<255; i++) {
+               sprintf(dname,"%s%d",st->device_path,i);
+               if ((st->fd=open(dname,O_RDWR))>0) {
+                   sprintf(st->interface_name,"tun%d",i);
+                   Message(M_INFO,"%s: allocated network interface %s "
+                           "through %s\n",st->nl.name,st->interface_name,
+                           dname);
+                   break;
+               }
+           }
+           if (st->fd==-1) {
+               fatal("%s: unable to open any TUN device (%s...)\n",
+                     st->nl.name,st->device_path);
+           }
+       } else {
+           st->fd=open(st->device_path,O_RDWR);
+           if (st->fd==-1) {
+               fatal_perror("%s: unable to open TUN device file %s",
+                            st->nl.name,st->device_path);
+           }
+       }
+    } else {
+#ifdef HAVE_LINUX_IF_H
+       struct ifreq ifr;
+
+       /* New TUN interface: open the device, then do ioctl TUNSETIFF
+          to set or find out the network interface name. */
+       st->fd=open(st->device_path,O_RDWR);
+       if (st->fd==-1) {
+           fatal_perror("%s: can't open device file %s",st->nl.name,
+                        st->device_path);
+       }
+       memset(&ifr,0,sizeof(ifr));
+       ifr.ifr_flags = IFF_TUN | IFF_NO_PI; /* Just send/receive IP packets,
+                                               no extra headers */
+       if (st->interface_name)
+           strncpy(ifr.ifr_name,st->interface_name,IFNAMSIZ);
+       if (ioctl(st->fd,TUNSETIFF,&ifr)<0) {
+           fatal_perror("%s: ioctl(TUNSETIFF)",st->nl.name);
+       }
+       if (!st->interface_name) {
+           st->interface_name=safe_malloc(strlen(ifr.ifr_name)+1,"tun_apply");
+           strcpy(st->interface_name,ifr.ifr_name);
+           Message(M_INFO,"%s: allocated network interface %s\n",st->nl.name,
+                   st->interface_name);
+       }
+#else
+       fatal("netlink.c:tun_phase_hook:!tun_old unexpected\n");
+#endif /* HAVE_LINUX_IF_H */
+    }
     /* All the networks we'll be using have been registered. Invoke ifconfig
        to set the TUN device's address, and route to add routes to all
        our networks. */
@@ -939,7 +1018,6 @@ static list_t *tun_apply(closure_t *self, struct cloc loc, dict_t *context,
     struct tun *st;
     item_t *item;
     dict_t *dict;
-    struct ifreq ifr;
 
     st=safe_malloc(sizeof(*st),"tun_apply");
 
@@ -954,6 +1032,7 @@ static list_t *tun_apply(closure_t *self, struct cloc loc, dict_t *context,
        netlink_init(&st->nl,st,loc,dict,
                     "netlink-tun",tun_deliver_to_kernel);
 
+    st->tun_old=False;
     st->device_path=dict_read_string(dict,"device",False,"tun-netlink",loc);
     st->interface_name=dict_read_string(dict,"interface",False,
                                        "tun-netlink",loc);
@@ -967,29 +1046,7 @@ static list_t *tun_apply(closure_t *self, struct cloc loc, dict_t *context,
     if (!st->route_path) st->route_path="route";
     st->buff=find_cl_if(dict,"buffer",CL_BUFFER,True,"tun-netlink",loc);
 
-    /* New TUN interface: open the device, then do ioctl TUNSETIFF
-       to set or find out the network interface name. */
-    st->fd=open(st->device_path,O_RDWR);
-    if (st->fd==-1) {
-       fatal_perror("%s: can't open device file %s",st->nl.name,
-                    st->device_path);
-    }
-    memset(&ifr,0,sizeof(ifr));
-    ifr.ifr_flags = IFF_TUN | IFF_NO_PI; /* Just send/receive IP packets,
-                                           no extra headers */
-    if (st->interface_name)
-       strncpy(ifr.ifr_name,st->interface_name,IFNAMSIZ);
-    if (ioctl(st->fd,TUNSETIFF,&ifr)<0) {
-       fatal_perror("%s: ioctl(TUNSETIFF)",st->nl.name);
-    }
-    if (!st->interface_name) {
-       st->interface_name=safe_malloc(strlen(ifr.ifr_name)+1,"tun_apply");
-       strcpy(st->interface_name,ifr.ifr_name);
-       Message(M_INFO,"%s: allocated network interface %s\n",st->nl.name,
-               st->interface_name);
-    }
-
-    add_hook(PHASE_DROPPRIV,tun_phase_hook,st);
+    add_hook(PHASE_GETRESOURCES,tun_phase_hook,st);
 
     return new_closure(&st->nl.cl);
 }
@@ -1001,7 +1058,6 @@ static list_t *tun_old_apply(closure_t *self, struct cloc loc, dict_t *context,
     struct tun *st;
     item_t *item;
     dict_t *dict;
-    bool_t search_for_if;
 
     st=safe_malloc(sizeof(*st),"tun_old_apply");
 
@@ -1019,11 +1075,12 @@ static list_t *tun_old_apply(closure_t *self, struct cloc loc, dict_t *context,
        netlink_init(&st->nl,st,loc,dict,
                     "netlink-tun",tun_deliver_to_kernel);
 
+    st->tun_old=True;
     st->device_path=dict_read_string(dict,"device",False,"tun-netlink",loc);
     st->interface_name=dict_read_string(dict,"interface",False,
                                        "tun-netlink",loc);
-    search_for_if=dict_read_bool(dict,"interface-search",False,"tun-netlink",
-                                loc,st->device_path==NULL);
+    st->search_for_if=dict_read_bool(dict,"interface-search",False,
+                                    "tun-netlink",loc,st->device_path==NULL);
     st->ifconfig_path=dict_read_string(dict,"ifconfig-path",False,
                                       "tun-netlink",loc);
     st->route_path=dict_read_string(dict,"route-path",False,"tun-netlink",loc);
@@ -1038,43 +1095,17 @@ static list_t *tun_old_apply(closure_t *self, struct cloc loc, dict_t *context,
        'device' as the prefix and try numbers from 0--255. If it's set
        to false, treat 'device' as the whole name, and require than an
        appropriate interface name be specified. */
-    if (search_for_if) {
-       string_t dname;
-       int i;
-
-       if (st->interface_name) {
-           cfgfatal(loc,"tun-old","you may not specify an interface name "
-                    "in interface-search mode\n");
-       }
-       dname=safe_malloc(strlen(st->device_path)+4,"tun_old_apply");
-       st->interface_name=safe_malloc(8,"tun_old_apply");
-       
-       for (i=0; i<255; i++) {
-           sprintf(dname,"%s%d",st->device_path,i);
-           if ((st->fd=open(dname,O_RDWR))>0) {
-               sprintf(st->interface_name,"tun%d",i);
-               Message(M_INFO,"%s: allocated network interface %s "
-                       "through %s\n",st->nl.name,st->interface_name,dname);
-               break;
-           }
-       }
-       if (st->fd==-1) {
-           fatal("%s: unable to open any TUN device (%s...)\n",
-                 st->nl.name,st->device_path);
-       }
-    } else {
-       if (!st->interface_name) {
-           cfgfatal(loc,"tun-old","you must specify an interface name "
-                    "when you explicitly specify a TUN device file\n");
-       }
-       st->fd=open(st->device_path,O_RDWR);
-       if (st->fd==-1) {
-           fatal_perror("%s: unable to open TUN device file %s",
-                        st->nl.name,st->device_path);
-       }
+    if (st->search_for_if && st->interface_name) {
+       cfgfatal(loc,"tun-old","you may not specify an interface name "
+                "in interface-search mode\n");
     }
+    if (!st->search_for_if && !st->interface_name) {
+       cfgfatal(loc,"tun-old","you must specify an interface name "
+                "when you explicitly specify a TUN device file\n");
+    }
+
 
-    add_hook(PHASE_DROPPRIV,tun_phase_hook,st);
+    add_hook(PHASE_GETRESOURCES,tun_phase_hook,st);
 
     return new_closure(&st->nl.cl);
 }
diff --git a/rsa.c b/rsa.c
index d1107a9..0b6f147 100644 (file)
--- a/rsa.c
+++ b/rsa.c
@@ -228,8 +228,15 @@ static list_t *rsapriv_apply(closure_t *self, struct cloc loc, dict_t *context,
 
     f=fopen(filename,"rb");
     if (!f) {
-       fatal_perror("rsa-private (%s:%d): cannot open file \"%s\"",
-                    loc.file,loc.line,filename);
+       if (just_check_config) {
+           Message(M_WARNING,"rsa-private (%s:%d): cannot open keyfile "
+                   "\"%s\"; assuming it's valid while we check the "
+                   "rest of the configuration\n",loc.file,loc.line,filename);
+           goto assume_valid;
+       } else {
+           fatal_perror("rsa-private (%s:%d): cannot open file \"%s\"",
+                        loc.file,loc.line,filename);
+       }
     }
 
     /* Check that the ID string is correct */
@@ -327,6 +334,7 @@ static list_t *rsapriv_apply(closure_t *self, struct cloc loc, dict_t *context,
     free(c);
     mpz_clear(&e);
 
+assume_valid:
     return new_closure(&st->cl);
 }
 
index e70fbe1..be94f95 100644 (file)
--- a/secnet.c
+++ b/secnet.c
@@ -21,6 +21,7 @@ extern char version[];
 
 /* Command-line options (possibly config-file options too) */
 static char *configfile="/etc/secnet/secnet.conf";
+bool_t just_check_config=False;
 static char *userid=NULL;
 static uid_t uid=0;
 static bool_t background=True;
@@ -58,10 +59,11 @@ static void parse_options(int argc, char **argv)
            {"quiet", 0, 0, 'f'},
            {"debug", 1, 0, 'd'},
            {"config", 1, 0, 'c'},
+           {"just-check-config", 0, 0, 'j'},
            {0,0,0,0}
        };
 
-       c=getopt_long(argc, argv, "vwdnc:ft:",
+       c=getopt_long(argc, argv, "vwdnjc:ft:",
                      long_options, &option_index);
        if (c==-1)
            break;
@@ -75,6 +77,7 @@ static void parse_options(int argc, char **argv)
                    "  -w, --nowarnings        suppress warnings\n"
                    "  -v, --verbose           output extra diagnostics\n"
                    "  -c, --config=filename   specify a configuration file\n"
+                   "  -j, --just-check-config stop after reading configfile\n"
                    "  -n, --nodetach          do not run in background\n"
                    "  -d, --debug=item,...    set debug options\n"
                    "      --help              display this help and exit\n"
@@ -112,6 +115,10 @@ static void parse_options(int argc, char **argv)
                fatal("secnet: no config filename specified");
            break;
 
+       case 'j':
+           just_check_config=True;
+           break;
+
        case '?':
            break;
 
@@ -339,6 +346,14 @@ int main(int argc, char **argv)
 
     enter_phase(PHASE_SETUP);
     setup(config);
+
+    if (just_check_config) {
+       Message(M_INFO,"configuration file check complete\n");
+       exit(0);
+    }
+
+    enter_phase(PHASE_GETRESOURCES);
+    /* Appropriate phase hooks will have been run */
     
     enter_phase(PHASE_DROPPRIV);
     droppriv();
index 35e06d1..f0f3a3e 100644 (file)
--- a/secnet.h
+++ b/secnet.h
@@ -34,11 +34,19 @@ struct subnet_list {
 /* Match an address (in HOST byte order) with a subnet list.
    Returns True if matched. */
 extern bool_t subnet_match(struct subnet_list *list, uint32_t address);
+extern bool_t subnets_intersect(struct subnet a, struct subnet b);
+extern bool_t subnet_intersects_with_list(struct subnet a,
+                                         struct subnet_list *b);
+extern bool_t subnet_lists_intersect(struct subnet_list *a,
+                                    struct subnet_list *b);
 
 /***** END of shared types *****/
 
 /***** CONFIGURATION support *****/
 
+extern bool_t just_check_config; /* If True then we're going to exit after
+                                   reading the configuration file */
+
 typedef struct dict dict_t;        /* Configuration dictionary */
 typedef struct closure closure_t;
 typedef struct item item_t;
@@ -179,10 +187,11 @@ extern void register_for_poll(void *st, beforepoll_fn *before,
 #define PHASE_GETOPTS       1  /* Process command-line arguments */
 #define PHASE_READCONFIG    2  /* Parse and process configuration file */
 #define PHASE_SETUP         3  /* Process information in configuration */
-#define PHASE_DROPPRIV      4  /* Last chance for privileged operations */
-#define PHASE_RUN           5
-#define PHASE_SHUTDOWN      6  /* About to die; delete key material, etc. */
-#define NR_PHASES           7
+#define PHASE_GETRESOURCES  4  /* Obtain all external resources */
+#define PHASE_DROPPRIV      5  /* Last chance for privileged operations */
+#define PHASE_RUN           6
+#define PHASE_SHUTDOWN      7  /* About to die; delete key material, etc. */
+#define NR_PHASES           8
 
 typedef void hook_fn(void *self, uint32_t newphase);
 bool_t add_hook(uint32_t phase, hook_fn *f, void *state);
diff --git a/site.c b/site.c
index 22f1575..efa1ebb 100644 (file)
--- a/site.c
+++ b/site.c
@@ -1096,7 +1096,8 @@ static list_t *site_apply(closure_t *self, struct cloc loc, dict_t *context,
        site() closures for all sites including our own): refuse to
        talk to ourselves */
     if (strcmp(st->localname,st->remotename)==0) {
-       Message(M_INFO,"site %s: talking to ourselves!\n",st->localname);
+       Message(M_INFO,"site %s: local-name==name -> ignoring this site\n",
+               st->localname);
        free(st);
        return NULL;
     }
diff --git a/udp.c b/udp.c
index f055962..ba9f9d6 100644 (file)
--- a/udp.c
+++ b/udp.c
@@ -41,6 +41,7 @@ struct udp {
     closure_t cl;
     struct comm_if ops;
     struct cloc loc;
+    uint16_t port;
     int fd;
     struct buffer_if *rbuf;
     struct notify_list *notify;
@@ -145,14 +146,40 @@ static bool_t udp_sendmsg(void *commst, struct buffer_if *buf,
     return True;
 }
 
+static void udp_phase_hook(void *sst, uint32_t new_phase)
+{
+    struct udp *st=sst;
+    struct sockaddr_in addr;
+
+    st->fd=socket(AF_INET, SOCK_DGRAM, 0);
+    if (st->fd<0) {
+       fatal_perror("udp (%s:%d): socket",st->loc.file,st->loc.line);
+    }
+    if (fcntl(st->fd, F_SETFL, fcntl(st->fd, F_GETFL)|O_NONBLOCK)==-1) {
+       fatal_perror("udp (%s:%d): fcntl(set O_NONBLOCK)",
+                    st->loc.file,st->loc.line);
+    }
+    if (fcntl(st->fd, F_SETFD, FD_CLOEXEC)==-1) {
+       fatal_perror("udp (%s:%d): fcntl(set FD_CLOEXEC)",
+                    st->loc.file,st->loc.line);
+    }
+
+    memset(&addr, 0, sizeof(addr));
+    addr.sin_family=AF_INET;
+    addr.sin_port=htons(st->port);
+    if (bind(st->fd, (struct sockaddr *)&addr, sizeof(addr))!=0) {
+       fatal_perror("udp (%s:%d): bind",st->loc.file,st->loc.line);
+    }
+
+    register_for_poll(st,udp_beforepoll,udp_afterpoll,1,"udp");
+}
+
 static list_t *udp_apply(closure_t *self, struct cloc loc, dict_t *context,
                         list_t *args)
 {
     struct udp *st;
     item_t *i;
     dict_t *d;
-    uint16_t local_port=0;
-    struct sockaddr_in addr;
 
     st=safe_malloc(sizeof(*st),"udp_apply(st)");
     st->loc=loc;
@@ -164,6 +191,7 @@ static list_t *udp_apply(closure_t *self, struct cloc loc, dict_t *context,
     st->ops.request_notify=request_notify;
     st->ops.release_notify=release_notify;
     st->ops.sendmsg=udp_sendmsg;
+    st->port=0;
 
     i=list_elem(args,0);
     if (!i || i->type!=t_dict) {
@@ -171,32 +199,10 @@ static list_t *udp_apply(closure_t *self, struct cloc loc, dict_t *context,
     }
     d=i->data.dict;
 
-    local_port=dict_read_number(d,"port",False,"udp",st->loc,0);
+    st->port=dict_read_number(d,"port",True,"udp",st->loc,0);
     st->rbuf=find_cl_if(d,"buffer",CL_BUFFER,True,"udp",st->loc);
 
-    st->fd=socket(AF_INET, SOCK_DGRAM, 0);
-    if (st->fd<0) {
-       fatal_perror("udp_apply (%s:%d): socket",loc.file,loc.line);
-    }
-    if (fcntl(st->fd, F_SETFL, fcntl(st->fd, F_GETFL)|O_NONBLOCK)==-1) {
-       fatal_perror("udp_apply (%s:%d): fcntl(set O_NONBLOCK)",
-                    loc.file,loc.line);
-    }
-    if (fcntl(st->fd, F_SETFD, FD_CLOEXEC)==-1) {
-       fatal_perror("udp_apply (%s:%d): fcntl(set FD_CLOEXEC)",
-                    loc.file,loc.line);
-    }
-
-    memset(&addr, 0, sizeof(addr));
-    addr.sin_family=AF_INET;
-    if (local_port) {
-       addr.sin_port=htons(local_port);
-    }
-    if (bind(st->fd, (struct sockaddr *)&addr, sizeof(addr))!=0) {
-       fatal_perror("udp_apply (%s:%d): bind",loc.file,loc.line);
-    }
-
-    register_for_poll(st,udp_beforepoll,udp_afterpoll,1,"udp");
+    add_hook(PHASE_GETRESOURCES,udp_phase_hook,st);
 
     return new_closure(&st->cl);
 }
diff --git a/util.c b/util.c
index 053e81e..0ffdcdd 100644 (file)
--- a/util.c
+++ b/util.c
@@ -248,6 +248,31 @@ bool_t subnet_match(struct subnet_list *list, uint32_t address)
     return False;
 }
 
+bool_t subnets_intersect(struct subnet a, struct subnet b)
+{
+    uint32_t mask=a.mask&b.mask;
+    return ((a.prefix&mask)==(b.prefix&mask));
+}
+
+bool_t subnet_intersects_with_list(struct subnet a, struct subnet_list *b)
+{
+    uint32_t i;
+
+    for (i=0; i<b->entries; i++) {
+       if (subnets_intersect(a,b->list[i])) return True;
+    }
+    return False;
+}
+
+bool_t subnet_lists_intersect(struct subnet_list *a, struct subnet_list *b)
+{
+    uint32_t i;
+    for (i=0; i<a->entries; i++) {
+       if (subnet_intersects_with_list(a->list[i],b)) return True;
+    }
+    return False;
+}
+
 /* The string buffer must be at least 16 bytes long */
 string_t ipaddr_to_string(uint32_t addr)
 {
@@ -415,6 +440,7 @@ static char *phases[NR_PHASES]={
     "PHASE_GETOPTS",
     "PHASE_READCONFIG",
     "PHASE_SETUP",
+    "PHASE_GETRESOURCES",
     "PHASE_DROPPRIV",
     "PHASE_RUN",
     "PHASE_SHUTDOWN"
@@ -424,12 +450,13 @@ void enter_phase(uint32_t new_phase)
 {
     struct phase_hook *i;
 
-    Message(M_DEBUG_PHASE,"entering %s... ", phases[new_phase]);
+    if (hooks[new_phase])
+       Message(M_DEBUG_PHASE,"Running hooks for %s...\n", phases[new_phase]);
     current_phase=new_phase;
 
     for (i=hooks[new_phase]; i; i=i->next)
        i->fn(i->state, new_phase);
-    Message(M_DEBUG_PHASE,"now in %s\n",phases[new_phase]);
+    Message(M_DEBUG_PHASE,"Now in %s\n",phases[new_phase]);
 }
 
 bool_t add_hook(uint32_t phase, hook_fn *fn, void *state)