]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
outside_network start.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Wed, 31 Jan 2007 15:38:44 +0000 (15:38 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Wed, 31 Jan 2007 15:38:44 +0000 (15:38 +0000)
git-svn-id: file:///svn/unbound/trunk@48 be551aaa-1e26-0410-a405-d3ace91eadb9

configure.ac
daemon/unbound.c
daemon/worker.c
daemon/worker.h
doc/Changelog
services/listen_dnsport.c
services/listen_dnsport.h
services/outside_network.c [new file with mode: 0644]
services/outside_network.h [new file with mode: 0644]
util/rbtree.h

index 7117bebb2936d7364f364c33e80ae91cca8a0f6c..57defe0c023f146ea84044696ba414fe7890ea21 100644 (file)
@@ -300,6 +300,8 @@ AH_BOTTOM([
 
 #include "ldns/ldns.h"
 
+/** default port to listen for queries, passed to getaddrinfo */
+#define UNBOUND_DNS_PORT "53"
 ])
 
 AC_CONFIG_FILES([Makefile])
index 91e930beb5c6ca56623a6ab84d546deb06b32654..373d1280bfcb8897f894aaa1a83fa9d98b7011d0 100644 (file)
@@ -44,8 +44,6 @@
 #include "util/log.h"
 #include "daemon/worker.h"
 
-/** default port to listen for queries, passed to getaddrinfo */
-#define UNBOUND_DNS_PORT "53"
 /** buffer size for network connections */
 #define BUFSZ 65552
 
@@ -77,8 +75,12 @@ main(int argc, char* argv[])
 {
        struct worker* worker = NULL;
        int do_ip4=1, do_ip6=1, do_udp=1, do_tcp=1;
+       size_t numports=3;
+       int baseport=10000;
        const char* port = UNBOUND_DNS_PORT;
        int c;
+       const char* fwd = "127.0.0.1";
+       const char* fwdport = UNBOUND_DNS_PORT;
 
        log_init();
        /* parse the options */
@@ -88,6 +90,7 @@ main(int argc, char* argv[])
                        if(!atoi(optarg))
                                fatal_exit("invalid port '%s'", optarg);
                        port = optarg;
+                       baseport = atoi(optarg)+2000;
                        verbose(VERB_ALGO, "using port: %s", port);
                        break;
                case 'v':
@@ -109,10 +112,14 @@ main(int argc, char* argv[])
        }
 
        /* setup */
-       worker = worker_init(port, do_ip4, do_ip6, do_udp, do_tcp, BUFSZ);
+       worker = worker_init(port, do_ip4, do_ip6, do_udp, do_tcp, BUFSZ,
+               numports, baseport);
        if(!worker) {
                fatal_exit("could not initialize");
        }
+       if(!worker_set_fwd(worker, fwd, fwdport)) {
+               fatal_exit("could set forwarder address");
+       }
        
        /* drop user priviliges and chroot if needed */
        log_info("Start of %s.", PACKAGE_STRING);
index ca2b5f43a67b3fa33cb848b460889e2d6c84681f..6f75254578ec62cfc3b3e1cecf7e21a9242d6e17 100644 (file)
 #include "daemon/worker.h"
 #include "util/netevent.h"
 #include "services/listen_dnsport.h"
+#include "services/outside_network.h"
+
+#ifdef HAVE_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+#include <netdb.h>
+#include <errno.h>
+
+/** timeout in seconds for UDP queries to auth servers. TODO: proper rtt */
+#define UDP_QUERY_TIMEOUT 5
 
 /** process incoming request */
 static void worker_process_query(struct worker* worker) 
 {
        /* query the forwarding address */
-       
+       pending_udp_query(worker->back, worker->query_reply.c->buffer, 
+               &worker->fwd_addr, worker->fwd_addrlen, UDP_QUERY_TIMEOUT);
 }
 
 /** check request sanity. Returns error code, 0 OK, or -1 discard. 
@@ -124,7 +135,8 @@ static int worker_handle_request(struct comm_point* c, void* arg, int error,
 }
 
 struct worker* worker_init(const char* port, int do_ip4, int do_ip6,
-       int do_udp, int do_tcp, size_t buffer_size)
+       int do_udp, int do_tcp, size_t buffer_size, size_t numports,
+       int base_port)
 {
        struct worker* worker = (struct worker*)calloc(1, 
                sizeof(struct worker));
@@ -143,10 +155,22 @@ struct worker* worker_init(const char* port, int do_ip4, int do_ip6,
                log_err("could not create listening sockets");
                return NULL;
        }
+       worker->back = outside_network_create(worker->base,
+               buffer_size, numports, NULL, 0, do_ip4, do_ip6, base_port);
+       if(!worker->back) {
+               comm_base_delete(worker->base);
+               log_err("could not create outgoing sockets");
+               return NULL;
+       }
+       /* init random(), large table size. */
+       if(!initstate(time(NULL)^getpid(), worker->rndstate, RND_STATE_SIZE)) {
+               log_err("could not init random numbers.");
+               comm_base_delete(worker->base);
+               return NULL;
+       }
        return worker;
 }
 
-
 void worker_work(struct worker* worker)
 {
        comm_base_dispatch(worker->base);
@@ -157,6 +181,26 @@ void worker_delete(struct worker* worker)
        if(!worker) 
                return;
        listen_delete(worker->front);
+       outside_network_delete(worker->back);
        comm_base_delete(worker->base);
        free(worker);
 }
+
+int worker_set_fwd(struct worker* worker, const char* ip, const char* port)
+{
+       struct addrinfo *res = NULL;
+       int r;
+       log_assert(worker && ip);
+       if(!port) 
+               port = UNBOUND_DNS_PORT;
+       if((r=getaddrinfo(ip, port, NULL, &res)) != 0 || !res) {
+               log_err("failed %s:%s getaddrinfo: %s %s",
+                       ip, port,
+                       gai_strerror(r), r==EAI_SYSTEM?strerror(errno):"");
+               return 0;
+       }
+       worker->fwd_addrlen = res->ai_addrlen;
+       memcpy(&worker->fwd_addr, &res->ai_addr, res->ai_addrlen);
+       freeaddrinfo(res);
+       return 1;
+}
index b8ae640125b0dfe5cdae411f4435d2cea9796dec..30f17167257839d69bafe58b5aab65e9d8932686 100644 (file)
 #include "config.h"
 #include "util/netevent.h"
 struct listen_dnsport;
+struct outside_network;
+
+/** size of table used for random numbers. large to be more secure. */
+#define RND_STATE_SIZE 256
 
 /**
  * Structure holding working information for unbound.
@@ -58,11 +62,23 @@ struct worker {
        /** the frontside listening interface where request events come in */
        struct listen_dnsport* front;
 
+       /** the backside outside network interface to the auth servers */
+       struct outside_network* back;
+
        /** our one and only query, packet buffer and where to send. */
        struct comm_reply query_reply;
 
        /** number of requests currently active */
        int num_requests;
+
+       /** random() table for this worker. */
+       char rndstate[RND_STATE_SIZE];
+
+       /** address to forward to */
+       struct sockaddr_storage fwd_addr;
+
+       /** length of fwd_addr */
+       socklen_t fwd_addrlen;
 };
 
 /**
@@ -74,10 +90,13 @@ struct worker {
  * @param do_udp: listen to udp queries.
  * @param do_tcp: listen to tcp queries.
  * @param buffer_size: size of datagram buffer.
+ * @param numports: number of outgoing ports.
+ * @param base_port: -1 or specify base of outgoing port range.
  * @return: The worker, or NULL on error.
  */
 struct worker* worker_init(const char* port, int do_ip4, int do_ip6,
-       int do_udp, int do_tcp, size_t buffer_size);
+       int do_udp, int do_tcp, size_t buffer_size, size_t numports,
+       int base_port);
 
 /**
  * Make worker work.
@@ -89,4 +108,13 @@ void worker_work(struct worker* worker);
  */
 void worker_delete(struct worker* worker);
 
+/**
+ * Set forwarder
+ * @param worker: the worker to modify.
+ * @param ip: the server name.
+ * @param port: port on server or NULL for default 53.
+ * @return: false on error.
+ */
+int worker_set_fwd(struct worker* worker, const char* ip, const char* port);
+
 #endif /* DAEMON_WORKER_H */
index 31a420d35ca0a2e9e31b4f229ec18d078f98c151..8d5d2afb5b6199db9e23d778325c36ada592f1c7 100644 (file)
@@ -5,6 +5,7 @@
        - netevent communication reply storage structure.
        - minimal query header sanity checking for worker.
        - copied over rbtree implementation from NSD (BSD licensed too).
+       - outgoing network query service work.
 
 30 January 2007: Wouter
        - links in example/ldns-testpkts.c and .h for premade packet support.
index ec5781189f28b5efc68783df7f6bfa19924f55f7..d28012326e8dcd8bd9002b29eb3afbb1f67a7e71 100644 (file)
@@ -79,12 +79,7 @@ verbose_print_addr(struct addrinfo *addr)
        }
 }
 
-/**
- * Create and bind UDP socket
- * @param addr: address info ready to make socket.
- * @return: the socket. -1 on error.
- */
-static int
+int
 create_udp_sock(struct addrinfo *addr)
 {
        int s, flag;
index 70818db275ccf6ce0d7b334f50e1b5c166063a77..385fea964a9552e374cd856c259cecf1738a1166 100644 (file)
@@ -45,6 +45,7 @@
 #include "config.h"
 #include "util/netevent.h"
 struct listen_list;
+struct addrinfo;
 
 /**
  * Listening for queries structure.
@@ -101,4 +102,13 @@ struct listen_dnsport* listen_create(struct comm_base* base,
  */
 void listen_delete(struct listen_dnsport* listen);
 
+
+/**
+ * Create and bind nonblocking UDP socket
+ * @param addr: address info ready to make socket.
+ * @return: the socket. -1 on error.
+ */
+int create_udp_sock(struct addrinfo *addr);
+
+
 #endif /* LISTEN_DNSPORT_H */
diff --git a/services/outside_network.c b/services/outside_network.c
new file mode 100644 (file)
index 0000000..e81dc87
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ * services/outside_network.c - implement sending of queries and wait answer.
+ *
+ * Copyright (c) 2007, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file
+ *
+ * This file has functions to send queries to authoritative servers and
+ * wait for the pending answer events.
+ */
+
+#include "services/outside_network.h"
+#include "services/listen_dnsport.h"
+#include "util/netevent.h"
+#include "util/log.h"
+
+#ifdef HAVE_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+#include <netdb.h>
+#include <errno.h>
+#include <fcntl.h>
+
+/** compare function of pending rbtree */
+static int pending_cmp(const void* key1, const void* key2)
+{
+       struct pending *p1 = (struct pending*)key1;
+       struct pending *p2 = (struct pending*)key2;
+       if(p1->id < p2->id)
+               return -1;
+       if(p1->id > p2->id)
+               return 1;
+       log_assert(p1->id == p2->id);
+       if(p1->addrlen < p2->addrlen)
+               return -1;
+       if(p1->addrlen > p2->addrlen)
+               return 1;
+       log_assert(p1->addrlen == p2->addrlen);
+       return memcmp(&p1->addr, &p2->addr, p1->addrlen);
+}
+
+/** compare function of pending_timeout rbtree */
+static int pending_timeout_cmp(const void* key1, const void* key2)
+{
+       struct pending_timeout *p1 = (struct pending_timeout*)key1;
+       struct pending_timeout *p2 = (struct pending_timeout*)key2;
+       if(p1->timeout.tv_sec < p2->timeout.tv_sec)
+               return -1;
+       if(p1->timeout.tv_sec > p2->timeout.tv_sec)
+               return 1;
+       log_assert(p1->timeout.tv_sec == p2->timeout.tv_sec);
+       if(p1->timeout.tv_usec < p2->timeout.tv_usec)
+               return -1;
+       if(p1->timeout.tv_usec > p2->timeout.tv_usec)
+               return 1;
+       log_assert(p1->timeout.tv_usec == p2->timeout.tv_usec);
+       if(p1 < p2)
+               return -1;
+       if(p1 > p2)
+               return 1;
+       return 0;
+}
+
+/** callback for incoming udp answers from the network. */
+static int outnet_udp_cb(struct comm_point* c, void* my_arg, int error,
+       struct comm_reply *reply_info)
+{
+       log_info("answer cb");
+       return 0;
+}
+
+/** open another udp port to listen to, every thread has its own range
+  * of open ports.
+  * @param ifname: on which interface to open the port.
+  * @param hints: hints on family and passiveness preset.
+  * @param porthint: if not -1, it gives the port to base range on.
+  * @return: file descriptor
+  */
+static int open_udp_port_range(const char* ifname, struct addrinfo* hints,
+       int porthint)
+{
+       struct addrinfo *res = NULL;
+       int r, s;
+       char portstr[20];
+       if(porthint != -1)
+               snprintf(portstr, sizeof(portstr), "%d", porthint);
+
+       if((r=getaddrinfo(ifname, ((porthint==-1)?NULL:portstr), hints, 
+               &res)) != 0 || !res) {
+               log_err("node %s:%s getaddrinfo: %s %s",
+                       ifname?ifname:"default", (porthint!=-1)?portstr:"eph", 
+                       gai_strerror(r), r==EAI_SYSTEM?strerror(errno):"");
+               return -1;
+       }
+       s = create_udp_sock(res);
+       freeaddrinfo(res);
+       return s;
+}
+
+/**
+ * Create range of UDP ports on the given interface.
+ */
+static int 
+make_udp_range(struct outside_network* outnet, const char* ifname, 
+       size_t num_ports, size_t off, int do_ip4, int do_ip6, int porthint)
+{
+       size_t i;
+       struct addrinfo hints;
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_flags = AI_PASSIVE;
+       if(ifname)
+               hints.ai_flags |= AI_NUMERICHOST;
+       hints.ai_family = AF_UNSPEC;
+       if(do_ip4 && do_ip6)
+               hints.ai_family = AF_UNSPEC;
+       else if(do_ip4)
+               hints.ai_family = AF_INET;
+       else if(do_ip6)
+               hints.ai_family = AF_INET6;
+       hints.ai_socktype = SOCK_DGRAM;
+       for(i=0; i<num_ports; i++) {
+               int fd = open_udp_port_range(ifname, &hints, porthint);
+               if(fd == -1) {
+                       return 0;
+               }
+               if(porthint != -1) 
+                       porthint++;
+               outnet->udp_ports[i+off] = comm_point_create_udp(
+                       outnet->base, fd, outnet->udp_buff, outnet_udp_cb,
+                       outnet);
+               if(!outnet->udp_ports[i+off]) {
+                       return 0;
+               }
+       }
+       return 1;
+}
+
+struct outside_network* 
+outside_network_create(struct comm_base *base, size_t bufsize, 
+       size_t num_ports, const char** ifs, int num_ifs, int do_ip4, 
+       int do_ip6, int port_base)
+{
+       struct outside_network* outnet = (struct outside_network*)
+               calloc(1, sizeof(struct outside_network));
+       int k;
+       if(!outnet) {
+               log_err("malloc failed");
+               return NULL;
+       }
+       outnet->base = base;
+       outnet->num_udp = (num_ifs?num_ports * num_ifs:num_ports);
+       if(     !(outnet->udp_buff = ldns_buffer_new(bufsize)) ||
+               !(outnet->udp_ports = (struct comm_point **)calloc(
+                       outnet->num_udp, sizeof(struct comm_point*))) ||
+               !(outnet->pending = rbtree_create(pending_cmp)) ||
+               !(outnet->pending_timeout = rbtree_create(
+                       pending_timeout_cmp))) {
+               log_err("malloc failed");
+               outside_network_delete(outnet);
+               return NULL;
+       }
+       if(num_ifs == 0) {
+               if(!make_udp_range(outnet, NULL, num_ports, 0, do_ip4, 
+                       do_ip6, port_base)) {
+                       outside_network_delete(outnet);
+                       return NULL;
+               }
+       }
+       else for(k=0; k<num_ifs; k++) {
+               if(!make_udp_range(outnet, ifs[k], num_ports, k*num_ports, 
+                       do_ip4, do_ip6, port_base)) {
+                       outside_network_delete(outnet);
+                       return NULL;
+               }
+       }
+
+       return outnet;
+}
+
+void outside_network_delete(struct outside_network* outnet)
+{
+       if(!outnet)
+               return;
+       /* check every element, since we can be called on malloc error */
+       if(outnet->pending) {
+               struct pending *p, *np;
+               p = (struct pending*)rbtree_first(outnet->pending);
+               while(p) {
+                       np = (struct pending*)rbtree_next((rbnode_t*)p);
+                       pending_delete(NULL, p);
+                       p = np;
+               }
+               free(outnet->pending);
+       }
+       if(outnet->pending_timeout) {
+               log_assert(outnet->pending_timeout->count == 0);
+               free(outnet->pending_timeout);
+       }
+       if(outnet->udp_buff)
+               ldns_buffer_free(outnet->udp_buff);
+       if(outnet->udp_ports) {
+               size_t i;
+               for(i=0; i<outnet->num_udp; i++) {
+                       if(outnet->udp_ports[i])
+                               comm_point_delete(outnet->udp_ports[i]);
+               }
+               free(outnet->udp_ports);
+       }
+       free(outnet);
+}
+
+void pending_delete(struct outside_network* outnet, struct pending* p)
+{
+       if(!p)
+               return;
+       if(outnet) {
+               (void)rbtree_delete(outnet->pending, p->node.key);
+               (void)rbtree_delete(outnet->pending_timeout, 
+                       p->timeout->node.key);
+       }
+       free(p->timeout);
+       free(p);
+}
+
+void pending_udp_query(struct outside_network* outnet, ldns_buffer* packet, 
+       struct sockaddr_storage* addr, socklen_t addrlen, int timeout)
+{
+       /* choose a random outgoing port and interface */
+       /* uses lousy random() function. TODO: entropy source. */
+       double precho = (double)random() * (double)outnet->num_udp / 
+               ((double)RAND_MAX + 1.0);
+       int chosen = (int)precho;
+       /* don't trust in perfect double rounding */
+       if(chosen < 0) chosen = 0;
+       if(chosen >= (int)outnet->num_udp) chosen = (int)outnet->num_udp-1;
+}
diff --git a/services/outside_network.h b/services/outside_network.h
new file mode 100644 (file)
index 0000000..dee5394
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * services/outside_network.h - listen to answers from the network
+ *
+ * Copyright (c) 2007, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file
+ *
+ * This file has functions to send queries to authoritative servers,
+ * and wait for the pending answer, with timeouts.
+ */
+
+#ifndef OUTSIDE_NETWORK_H
+#define OUTSIDE_NETWORK_H
+
+#include "config.h"
+#include "util/rbtree.h"
+struct pending;
+struct pending_timeout;
+struct comm_point;
+struct comm_base;
+
+/**
+ * Send queries to outside servers and wait for answers from servers.
+ * Contains answer-listen sockets.
+ */
+struct outside_network {
+       /** Base for select calls */
+       struct comm_base* base;
+
+       /** buffer shared by UDP connections, since there is only one
+           datagram at any time. */
+       ldns_buffer* udp_buff;
+
+       /** 
+        * Array of udp comm point* that are used to listen to pending events.
+        * Each is on a different port.
+        */
+       struct comm_point **udp_ports;
+       /** number of udp ports */
+       size_t num_udp;
+
+       /** pending answers. sorted by id, addr */
+       rbtree_t *pending;
+       /** Each pending answer has a timeout, sorted by timeout. */
+       rbtree_t *pending_timeout;
+};
+
+/**
+ * A query that has an answer pending for it.
+ */
+struct pending {
+       /** redblacktree entry, key is the pending struct(id, addr). */
+       rbnode_t node;
+       /** the ID for the query */
+       uint16_t id;
+       /** remote address. */
+       struct sockaddr_storage addr;
+       /** length of addr field in use. */
+       socklen_t addrlen;
+       /** comm point it was sent on (and reply must come back on). */
+       struct comm_point* c;
+       /** the timeout of the query */
+       struct pending_timeout *timeout;
+};
+
+/**
+ * Timeout structure for pending queries
+ */
+struct pending_timeout {
+       /** entry in rbtree. key is timeout value, then pending ptr(uniq). */
+       rbnode_t node;
+       /** timeout, an absolute time value. */
+       struct timeval timeout;
+       /** pending query */
+       struct pending* pending;
+};
+
+/**
+ * Create outside_network structure with N udp ports.
+ * @param base: the communication base to use for event handling.
+ * @param bufsize: size for network buffers.
+ * @param num_ports: number of udp ports to open per interface.
+ * @param ifs: interface names (or NULL for default interface).
+ * @param num_ifs: number of names in array ifs.
+ * @param do_ip4: service IP4.
+ * @param do_ip6: service IP6.
+ * @param port_base: if -1 system assigns ports, otherwise try to get
+ *    the ports numbered from this starting number.
+ * @return: the new empty structure or NULL on error.
+ */
+struct outside_network* outside_network_create(struct comm_base *base,
+       size_t bufsize, size_t num_ports, const char** ifs, int num_ifs,
+       int do_ip4, int do_ip6, int port_base);
+
+/**
+ * Delete outside_network structure.
+ * @param outnet: object to delete.
+ */
+void outside_network_delete(struct outside_network* outnet);
+
+/**
+ * Send UDP query, create pending answer.
+ * @param outnet: provides the event handling
+ * @param packet: wireformat query to send to destination.
+ * @param addr: address to send to.
+ * @param addrlen: length of addr.
+ * @param timeout: in seconds from now.
+ */
+void pending_udp_query(struct outside_network* outnet, ldns_buffer* packet, 
+       struct sockaddr_storage* addr, socklen_t addrlen, int timeout);
+
+/**
+ * Delete pending answer.
+ * @param outnet: outside network the pending query is part of.
+ *    Used internal, if NULL, p is not unlinked from rbtree.
+ * @param p: deleted
+ */
+void pending_delete(struct outside_network* outnet, struct pending* p);
+
+#endif /* OUTSIDE_NETWORK_H */
index e2353e8c2f82efec0f5091b926ac886464da4382..1507eb30257caeeec6d2637e2f8c9cffef176920 100644 (file)
@@ -37,6 +37,7 @@
  */
 
 /**
+ * \file
  * Red black tree. Implementation taken from NSD 3.0.5, adjusted for use
  * in unbound (memory allocation, logging and so on).
  */