]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
Ports are shared and you can kill -HUP to do a reload (of config file).
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Fri, 23 Feb 2007 10:04:50 +0000 (10:04 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Fri, 23 Feb 2007 10:04:50 +0000 (10:04 +0000)
git-svn-id: file:///svn/unbound/trunk@137 be551aaa-1e26-0410-a405-d3ace91eadb9

13 files changed:
daemon/daemon.c
daemon/worker.c
daemon/worker.h
doc/Changelog
services/listen_dnsport.c
services/listen_dnsport.h
services/outside_network.c
testcode/fake_event.c
util/config_file.c
util/config_file.h
util/configparser.y
util/netevent.c
util/netevent.h

index a2bc58abd191522ec2b53ad374c35373180ac065..39c3d1c82d2cd884f1936310bae154607cfcf518 100644 (file)
@@ -83,14 +83,17 @@ daemon_fork(struct daemon* daemon)
        daemon->num = 1;
        daemon->workers = (struct worker**)calloc((size_t)daemon->num, 
                sizeof(struct worker*));
-       if(!(daemon->workers[0] = worker_init(daemon->cfg, BUFSZ)))
+       if(!(daemon->workers[0] = worker_init(daemon->cfg, daemon->ports, 
+               BUFSZ)))
                fatal_exit("could not initialize thread # %d", 0);
        daemon->workers[0]->daemon = daemon;
        daemon->workers[0]->thread_num = 0;
 
        log_info("start of service (%s).", PACKAGE_STRING);
        worker_work(daemon->workers[0]);
-       daemon->need_to_exit = 1;
+       if(daemon->workers[0]->need_to_restart)
+               daemon->need_to_exit = 0;
+       else    daemon->need_to_exit = 1;
 }
 
 void 
index b4d46e9edeb3534e1c9e78ec92751bf60bdffacc..87b5a430ade41925819cd024782aae5347848797 100644 (file)
@@ -191,6 +191,7 @@ worker_sighandler(int sig, void* arg)
        switch(sig) {
                case SIGHUP:
                        log_info("caught signal SIGHUP");
+                       worker->need_to_restart = 1;
                        comm_base_exit(worker->base);
                        break;
                case SIGINT:
@@ -208,12 +209,14 @@ worker_sighandler(int sig, void* arg)
 }
 
 struct worker* 
-worker_init(struct config_file *cfg, size_t buffer_size)
+worker_init(struct config_file *cfg, struct listen_port* ports,
+       size_t buffer_size)
 {
        struct worker* worker = (struct worker*)calloc(1, 
                sizeof(struct worker));
        if(!worker) 
                return NULL;
+       worker->need_to_restart = 0;
        worker->base = comm_base_create();
        if(!worker->base) {
                log_err("could not create event handling base");
@@ -229,8 +232,7 @@ worker_init(struct config_file *cfg, size_t buffer_size)
                worker_delete(worker);
                return NULL;
        }
-       worker->front = listen_create(worker->base, 0, NULL, cfg->port, 
-               cfg->do_ip4, cfg->do_ip6, cfg->do_udp, cfg->do_tcp, 
+       worker->front = listen_create(worker->base, ports,
                buffer_size, worker_handle_request, worker);
        if(!worker->front) {
                log_err("could not create listening sockets");
index c0d1671096943731432a11c99957b3c19f2a7807..7458e0a2a606a054d50ba75310a337a257c319a0 100644 (file)
@@ -50,6 +50,7 @@ struct listen_dnsport;
 struct outside_network;
 struct config_file;
 struct daemon;
+struct listen_port;
 
 /** size of table used for random numbers. large to be more secure. */
 #define RND_STATE_SIZE 256
@@ -86,16 +87,20 @@ struct worker {
 
        /** random() table for this worker. */
        char* rndstate;
+       /** do we need to restart (instead of exit) ? */
+       int need_to_restart;
 };
 
 /**
  * Initialize worker.
  * Allocates event base, listens to ports
  * @param cfg: configuration settings.
+ * @param ports: list of shared query ports.
  * @param buffer_size: size of datagram buffer.
  * @return: The worker, or NULL on error.
  */
-struct worker* worker_init(struct config_file *cfg, size_t buffer_size);
+struct worker* worker_init(struct config_file *cfg, struct listen_port* ports,
+       size_t buffer_size);
 
 /**
  * Make worker work.
index 43d0511a28022240cfebd9d148e22491b10ef35c..bc612886471ef1ac0406983cc7cc513649fd11bf 100644 (file)
@@ -1,3 +1,9 @@
+23 February 2007: Wouter
+       - Can do reloads on sigHUP. Everything is stopped, and freed,
+         except the listening ports. Then the config file is reread.
+         And everything is started again (and listening ports if needed).
+       - Ports for queries are shared.
+
 22 February 2007: Wouter
        - Have a config file. Removed commandline options, moved to config.
        - tests use config file.
index ce00bbaa029822ba4be1177b6f78ada0424f29a4..f44c49ea3f1deaf5e21812c7db3a1b223f07b57e 100644 (file)
@@ -43,6 +43,7 @@
 #include "services/outside_network.h"
 #include "util/netevent.h"
 #include "util/log.h"
+#include "util/config_file.h"
 #include "util/net_help.h"
 
 #ifdef HAVE_SYS_TYPES_H
@@ -218,93 +219,90 @@ make_sock(int stype, const char* ifname, const char* port,
 }
 
 /**
- * Helper for listen_create. Creates one interface (or NULL for default).
+ * Add port to open ports list.
+ * @param list: list head. changed.
+ * @param s: fd.
+ * @param is_udp: if fd is UDP.
+ * @return false on failure. list in unchanged then.
+ */
+static int
+port_insert(struct listen_port** list, int s, int is_udp)
+{
+       struct listen_port* item = (struct listen_port*)malloc(
+               sizeof(struct listen_port));
+       if(!item)
+               return 0;
+       item->next = *list;
+       item->fd = s;
+       item->is_udp = is_udp;
+       *list = item;
+       return 1;
+}
+
+/**
+ * Helper for ports_open. Creates one interface (or NULL for default).
  * @param ifname: The interface ip address.
- * @param front: The the listening info.
- * @param base: Event base.
- * @param port: Port number to use (as string).
  * @param do_udp: if udp should be used.
  * @param do_tcp: if udp should be used.
  * @param hints: for getaddrinfo. family and flags have to be set by caller.
- * @param bufsize: TCP buffer size.
- * @param cb: callback function
- * @param cb_arg: user parameter for callback function.
+ * @param port: Port number to use (as string).
+ * @param list: list of open ports, appended to, changed to point to list head.
  * @return: returns false on error.
  */
 static int
-listen_create_if(const char* ifname, struct listen_dnsport* front, 
-       struct comm_base* base, const char* port, int do_udp, int do_tcp, 
-       struct addrinfo *hints, size_t bufsize, comm_point_callback_t* cb, 
-       void *cb_arg)
+ports_create_if(const char* ifname, int do_udp, int do_tcp, 
+       struct addrinfo *hints, const char* port, struct listen_port** list)
 {
-       struct comm_point *cp_udp = NULL, *cp_tcp = NULL;
-       struct listen_list *el_udp, *el_tcp;
        int s;
        if(!do_udp && !do_tcp)
                return 0;
        if(do_udp) {
                if((s = make_sock(SOCK_DGRAM, ifname, port, hints)) == -1)
                        return 0;
-               cp_udp = comm_point_create_udp(base, s, front->udp_buff, 
-                       cb, cb_arg);
-               if(!cp_udp) {
-                       log_err("can't create commpoint");      
+               if(!port_insert(list, s, 1)) {
                        close(s);
                        return 0;
                }
        }
        if(do_tcp) {
                if((s = make_sock(SOCK_STREAM, ifname, port, hints)) == -1) {
-                       comm_point_delete(cp_udp);
                        return 0;
                }
-               cp_tcp = comm_point_create_tcp(base, s, TCP_COUNT, bufsize, 
-                       cb, cb_arg);
-               if(!cp_tcp) {
-                       log_err("can't create commpoint");      
-                       comm_point_delete(cp_udp);
+               if(!port_insert(list, s, 0)) {
                        close(s);
                        return 0;
                }
        }
-       /* add commpoints to the listen structure */
-       el_udp = (struct listen_list*)malloc(sizeof(struct listen_list));
-       if(!el_udp) {
-               log_err("out of memory");
-               comm_point_delete(cp_udp);
-               comm_point_delete(cp_tcp);
-               return 0;
-       }
-       el_tcp = (struct listen_list*)malloc(sizeof(struct listen_list));
-       if(!el_tcp) {
-               log_err("out of memory");
-               free(el_udp);
-               comm_point_delete(cp_udp);
-               comm_point_delete(cp_tcp);
+       return 1;
+}
+
+/** 
+ * Add items to commpoint list in front.
+ * @param c: commpoint to add.
+ * @param front: listen struct.
+ * @return: false on failure.
+ */
+static int
+listen_cp_insert(struct comm_point* c, struct listen_dnsport* front)
+{
+       struct listen_list* item = (struct listen_list*)malloc(
+               sizeof(struct listen_list));
+       if(!item)
                return 0;
-       }
-       el_udp->com = cp_udp;
-       el_udp->next = front->cps;
-       front->cps = el_udp;
-       el_tcp->com = cp_tcp;
-       el_tcp->next = front->cps;
-       front->cps = el_tcp;
+       item->com = c;
+       item->next = front->cps;
+       front->cps = item;
        return 1;
 }
 
 struct listen_dnsport* 
-listen_create(struct comm_base* base, int num_ifs, const char* ifs[], 
-       int port, int do_ip4, int do_ip6, int do_udp, int do_tcp,
+listen_create(struct comm_base* base, struct listen_port* ports,
        size_t bufsize, comm_point_callback_t* cb, void *cb_arg)
 {
-       struct addrinfo hints;
-       int i;
-       char portbuf[10];
        struct listen_dnsport* front = (struct listen_dnsport*)
                malloc(sizeof(struct listen_dnsport));
        if(!front)
                return NULL;
-       snprintf(portbuf, sizeof(portbuf), "%d", port);
        front->cps = NULL;
        front->udp_buff = ldns_buffer_new(bufsize);
        if(!front->udp_buff) {
@@ -312,93 +310,128 @@ listen_create(struct comm_base* base, int num_ifs, const char* ifs[],
                return NULL;
        }
        
+       /* create comm points as needed */
+       while(ports) {
+               struct comm_point* cp = NULL;
+               if(ports->is_udp) 
+                       cp = comm_point_create_udp(base, ports->fd, 
+                               front->udp_buff, cb, cb_arg);
+               else    cp = comm_point_create_tcp(base, ports->fd, 
+                               TCP_COUNT, bufsize, cb, cb_arg);
+               if(!cp) {
+                       log_err("can't create commpoint");      
+                       listen_delete(front);
+                       return NULL;
+               }
+               cp->do_not_close = 1;
+               if(!listen_cp_insert(cp, front)) {
+                       log_err("malloc failed");
+                       comm_point_delete(cp);
+                       listen_delete(front);
+                       return NULL;
+               }
+               ports = ports->next;
+       }
+       if(!front->cps) {
+               log_err("Could not open sockets to accept queries.");
+               listen_delete(front);
+               return NULL;
+       }
+
+       return front;
+}
+
+void 
+listen_delete(struct listen_dnsport* front)
+{
+       struct listen_list *p, *pn;
+       if(!front) 
+               return;
+       p = front->cps;
+       while(p) {
+               pn = p->next;
+               comm_point_delete(p->com);
+               free(p);
+               p = pn;
+       }
+       ldns_buffer_free(front->udp_buff);
+       free(front);
+}
+
+struct listen_port* 
+listening_ports_open(struct config_file* cfg)
+{
+       struct listen_port* list = NULL;
+       struct addrinfo hints;
+       int i, do_ip4, do_ip6;
+       char portbuf[32];
+       snprintf(portbuf, sizeof(portbuf), "%d", cfg->port);
+       do_ip4 = cfg->do_ip4;
+       do_ip6 = cfg->do_ip6;
+
        /* getaddrinfo */
        memset(&hints, 0, sizeof(hints));
        hints.ai_flags = AI_PASSIVE;
        /* no name lookups on our listening ports */
-       if(num_ifs > 0)
+       if(cfg->num_ifs > 0)
                hints.ai_flags |= AI_NUMERICHOST;
        hints.ai_family = AF_UNSPEC;
 #ifndef INET6
        do_ip6 = 0;
 #endif
        if(!do_ip4 && !do_ip6) {
-               listen_delete(front);
                return NULL;
        }
-
        /* create ip4 and ip6 ports so that return addresses are nice. */
-       if(num_ifs == 0) {
+       if(cfg->num_ifs == 0) {
                if(do_ip6) {
                        hints.ai_family = AF_INET6;
-                       if(!listen_create_if(NULL, front, base, portbuf
-                               do_udp, do_tcp, &hints, bufsize, cb, cb_arg)) {
-                               listen_delete(front);
+                       if(!ports_create_if(NULL, cfg->do_udp, cfg->do_tcp
+                               &hints, portbuf, &list)) {
+                               listening_ports_free(list);
                                return NULL;
                        }
                }
                if(do_ip4) {
                        hints.ai_family = AF_INET;
-                       if(!listen_create_if(NULL, front, base, portbuf
-                               do_udp, do_tcp, &hints, bufsize, cb, cb_arg)) {
-                               listen_delete(front);
+                       if(!ports_create_if(NULL, cfg->do_udp, cfg->do_tcp
+                               &hints, portbuf, &list)) {
+                               listening_ports_free(list);
                                return NULL;
                        }
                }
-       } else for(i = 0; i<num_ifs; i++) {
-               if(str_is_ip6(ifs[i])) {
+       } else for(i = 0; i<cfg->num_ifs; i++) {
+               if(str_is_ip6(cfg->ifs[i])) {
                        if(!do_ip6)
                                continue;
                        hints.ai_family = AF_INET6;
-                       if(!listen_create_if(ifs[i], front, base, portbuf
-                               do_udp, do_tcp, &hints, bufsize, cb, cb_arg)) {
-                               listen_delete(front);
+                       if(!ports_create_if(cfg->ifs[i], cfg->do_udp
+                               cfg->do_tcp, &hints, portbuf, &list)) {
+                               listening_ports_free(list);
                                return NULL;
                        }
                } else {
                        if(!do_ip4)
                                continue;
                        hints.ai_family = AF_INET;
-                       if(!listen_create_if(ifs[i], front, base, portbuf
-                               do_udp, do_tcp, &hints, bufsize, cb, cb_arg)) {
-                               listen_delete(front);
+                       if(!ports_create_if(cfg->ifs[i], cfg->do_udp
+                               cfg->do_tcp, &hints, portbuf, &list)) {
+                               listening_ports_free(list);
                                return NULL;
                        }
                }
        }
-       if(!front->cps) {
-               log_err("Could not open sockets to accept queries.");
-               listen_delete(front);
-               return NULL;
-       }
-
-       return front;
-}
-
-void 
-listen_delete(struct listen_dnsport* front)
-{
-       struct listen_list *p, *pn;
-       if(!front) 
-               return;
-       p = front->cps;
-       while(p) {
-               pn = p->next;
-               comm_point_delete(p->com);
-               free(p);
-               p = pn;
-       }
-       ldns_buffer_free(front->udp_buff);
-       free(front);
-}
-
-struct listen_port* 
-listening_ports_open(struct config_file* cfg)
-{
-       return calloc(1,1);
+       return list;
 }
 
 void listening_ports_free(struct listen_port* list)
 {
-       free(list);
+       struct listen_port* nx;
+       while(list) {
+               nx = list->next;
+               if(list->fd != -1)
+                       close(list->fd);
+               free(list);
+               list = nx;
+       }
 }
index 3b644fe4339a48e22cd7d8c0fe434203738d7a41..ce774697a39daab0e93d94616d85af9b54882895 100644 (file)
@@ -89,6 +89,9 @@ struct listen_port {
 
 /**
  * Create shared listening ports
+ * Getaddrinfo, create socket, bind and listen to zero or more 
+ * interfaces for IP4 and/or IP6, for UDP and/or TCP.
+ * On the given port number. It creates the sockets.
  * @param cfg: settings on what ports to open.
  * @return: linked list of ports or NULL on error.
  */
@@ -100,18 +103,10 @@ struct listen_port* listening_ports_open(struct config_file* cfg);
 void listening_ports_free(struct listen_port* list);
 
 /**
- * Getaddrinfo, create socket, bind and listen to zero or more 
- * interfaces for IP4 and/or IP6, for UDP and/or TCP.
- * On the given port number. It creates the listening sockets.
+ * Create commpoints with for this thread for the shared ports.
  * @param base: the comm_base that provides event functionality.
- * @param num_ifs: number of interfaces to listen on. Can be 0,
  *     for default all ifs.
- * @param ifs: array of strings with interface specs, IP addresses.
- * @param port: the port number to bind to.
- * @param do_ip4: listen to ip4 queries.
- * @param do_ip6: listen to ip6 queries.
- * @param do_udp: listen to udp queries.
- * @param do_tcp: listen to tcp queries.
+ * @param ports: the list of shared ports.
  * @param bufsize: size of datagram buffer.
  * @param cb: callback function when a request arrives. It is passed
  *       the packet and user argument. Return true to send a reply.
@@ -119,9 +114,8 @@ void listening_ports_free(struct listen_port* list);
  * @return: the malloced listening structure, ready for use. NULL on error.
  */
 struct listen_dnsport* listen_create(struct comm_base* base,
-       int num_ifs, const char* ifs[], int port,
-       int do_ip4, int do_ip6, int do_udp, int do_tcp,
-       size_t bufsize, comm_point_callback_t* cb, void* cb_arg);
+       struct listen_port* ports, size_t bufsize, 
+       comm_point_callback_t* cb, void* cb_arg);
 
 /**
  * delete the listening structure
index 7a75ef4df9f90c87f3f06de07fc432e322dd253f..1c24a9bd715d5ca92c5be758a673eab182629c38 100644 (file)
@@ -164,7 +164,7 @@ open_udp_port_range(const char* ifname, struct addrinfo* hints, int porthint)
 {
        struct addrinfo *res = NULL;
        int r, s;
-       char portstr[20];
+       char portstr[32];
        if(porthint != -1)
                snprintf(portstr, sizeof(portstr), "%d", porthint);
 
index d6132d421664984332a656772df3b5df11221650..839646bf7b9d7a8473550cca56faa97ef91af79a 100644 (file)
@@ -479,10 +479,7 @@ run_scenario(struct replay_runtime* runtime)
 /*********** Dummy routines ***********/
 
 struct listen_dnsport* 
-listen_create(struct comm_base* base, int ATTR_UNUSED(num_ifs), 
-       const char* ATTR_UNUSED(ifs[]), int ATTR_UNUSED(port),
-       int ATTR_UNUSED(do_ip4), int ATTR_UNUSED(do_ip6), 
-       int ATTR_UNUSED(do_udp), int ATTR_UNUSED(do_tcp),
+listen_create(struct comm_base* base, struct listen_port* ATTR_UNUSED(ports),
        size_t bufsize, comm_point_callback_t* cb, void* cb_arg)
 {
        struct replay_runtime* runtime = (struct replay_runtime*)base;
index 0c2660476db322440fc906ab361a3ba63e26f1dd..0db8d067b1433620123c5348e3a62ccc133d44e3 100644 (file)
@@ -91,6 +91,8 @@ config_create()
        }
        cfg->fwd_port = UNBOUND_DNS_PORT;
        cfg->do_daemonize = 0;
+       cfg->num_ifs = 0;
+       cfg->ifs = NULL;
        return cfg;
 }
 
@@ -104,6 +106,7 @@ create_cfg_parser(struct config_file* cfg, char* filename)
        cfg_parser->line = 1;
        cfg_parser->errors = 0;
        cfg_parser->cfg = cfg;
+       cfg_parser->server_settings_seen = 0;
 }
 
 int 
index 42e2d7ebfc313b158449b4d4e4d5dcfbfca7bd4e..54648663890ee190b70dc3f21437b87b0f4724b4 100644 (file)
@@ -74,6 +74,11 @@ struct config_file {
        /** forwarder port */
        int fwd_port;
 
+       /** number of interfaces to open. If 0 default all interfaces. */
+       int num_ifs;
+       /** interface description strings (IP addresses) */
+       char **ifs;
+
        /** chrootdir, if not "" or chroot will be done */
        char* chrootdir;
        /** username to change to, if not "". */
@@ -115,6 +120,8 @@ struct config_parser_state {
        int errors;
        /** the result of parsing is stored here. */
        struct config_file* cfg;
+       /** has server: already been seen. */
+       int server_settings_seen;
 };
 
 /** global config parser object used during config parsing */
index 3632062b83b4b254fa96297b5597dc398d42d157..7dd8bbdde4f1c78c28252dfab9607d41b925a200 100644 (file)
@@ -52,7 +52,6 @@ void ub_c_error(const char *message);
 
 /* these need to be global, otherwise they cannot be used inside yacc */
 extern struct config_parser_state* cfg_parser;
-static int server_settings_seen = 0;
 
 #if 0
 #define OUTYY(s)  printf s /* used ONLY when debugging */
@@ -80,10 +79,10 @@ toplevelvar: serverstart contents_server ;
 /* server: declaration */
 serverstart: VAR_SERVER
        { OUTYY(("\nP(server:)\n")); 
-               if(server_settings_seen) {
+               if(cfg_parser->server_settings_seen) {
                        yyerror("duplicate server: element.");
                }
-               server_settings_seen = 1;
+               cfg_parser->server_settings_seen = 1;
        }
        ;
 contents_server: contents_server content_server | ;
index 36789131f56dfcf274edcdc336983d8c950c2c51..f0a8958359c3c079a2a8afdc5dd80fa747fd995c 100644 (file)
@@ -516,6 +516,7 @@ comm_point_create_udp(struct comm_base *base, int fd, ldns_buffer* buffer,
        c->tcp_free = NULL;
        c->type = comm_udp;
        c->tcp_do_close = 0;
+       c->do_not_close = 0;
        c->tcp_do_toggle_rw = 0;
        c->callback = callback;
        c->cb_arg = callback_arg;
@@ -569,6 +570,7 @@ comm_point_create_tcp_handler(struct comm_base *base,
        c->tcp_free = NULL;
        c->type = comm_tcp;
        c->tcp_do_close = 0;
+       c->do_not_close = 0;
        c->tcp_do_toggle_rw = 0;
        c->callback = callback;
        c->cb_arg = callback_arg;
@@ -623,6 +625,7 @@ comm_point_create_tcp(struct comm_base *base, int fd, int num, size_t bufsize,
        c->tcp_free = NULL;
        c->type = comm_tcp_accept;
        c->tcp_do_close = 0;
+       c->do_not_close = 0;
        c->tcp_do_toggle_rw = 0;
        c->callback = NULL;
        c->cb_arg = NULL;
@@ -659,7 +662,7 @@ comm_point_close(struct comm_point* c)
                log_err("could not event_del on close");
        }
        /* close fd after removing from event lists, or epoll.. is messed up */
-       if(c->fd != -1)
+       if(c->fd != -1 && !c->do_not_close)
                close(c->fd);
        c->fd = -1;
 }
index 9822936eab1c00e809a9f05965be7350e42e623f..9b3098b6feab4840215a79d3d96ff3611236a041 100644 (file)
@@ -139,6 +139,9 @@ struct comm_point {
        } type;
 
        /* ---------- Behaviour ----------- */
+       /** if set the connection is NOT closed on delete. */
+       int do_not_close;
+
        /** if set, the connection is closed on error, on timeout, 
            and after read/write completes. No callback is done. */
        int tcp_do_close;