Ports are shared and you can kill -HUP to do a reload (of config file).

git-svn-id: https://unbound.nlnetlabs.nl/svn/trunk@137 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
wouter 2007-02-23 10:04:50 +00:00
parent df0bfecb92
commit 3d6f070744
13 changed files with 186 additions and 131 deletions

View 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

View 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");

View 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.

View 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.

View 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 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_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 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,59 +310,27 @@ listen_create(struct comm_base* base, int num_ifs, const char* ifs[],
return NULL;
}
/* getaddrinfo */
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_PASSIVE;
/* no name lookups on our listening ports */
if(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(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);
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;
}
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);
return NULL;
}
}
} else for(i = 0; i<num_ifs; i++) {
if(str_is_ip6(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);
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);
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.");
@ -395,10 +361,77 @@ listen_delete(struct listen_dnsport* front)
struct listen_port*
listening_ports_open(struct config_file* cfg)
{
return calloc(1,1);
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(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) {
return NULL;
}
/* create ip4 and ip6 ports so that return addresses are nice. */
if(cfg->num_ifs == 0) {
if(do_ip6) {
hints.ai_family = AF_INET6;
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(!ports_create_if(NULL, cfg->do_udp, cfg->do_tcp,
&hints, portbuf, &list)) {
listening_ports_free(list);
return NULL;
}
}
} 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(!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(!ports_create_if(cfg->ifs[i], cfg->do_udp,
cfg->do_tcp, &hints, portbuf, &list)) {
listening_ports_free(list);
return NULL;
}
}
}
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;
}
}

View 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

View 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);

View 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;

View 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

View 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 */

View 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 | ;

View 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;
}

View 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;