+ - created log_assert, that throws assertions to the logfile.

+       - listen_dnsport service. Binds ports.


git-svn-id: file:///svn/unbound/trunk@35 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2007-01-25 16:08:52 +00:00
parent 225d48f13a
commit 3284b2f6f6
8 changed files with 382 additions and 13 deletions

View file

@ -111,7 +111,7 @@ AC_PROG_LIBTOOL
# Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS([getopt.h stdarg.h stdbool.h netinet/in.h time.h sys/param.h sys/socket.h],,, [AC_INCLUDES_DEFAULT])
AC_CHECK_HEADERS([getopt.h stdarg.h stdbool.h netinet/in.h time.h sys/param.h sys/socket.h arpa/inet.h],,, [AC_INCLUDES_DEFAULT])
# check for types
AC_CHECK_TYPE(int8_t, char)

View file

@ -43,14 +43,21 @@
#include "config.h"
#include "util/log.h"
#include "util/netevent.h"
#include "services/listen_dnsport.h"
/** default port to listen for queries, passed to getaddrinfo */
#define UNBOUND_DNS_PORT "53"
/** buffer size for network connections */
#define BUFSZ 65552
/** print usage. */
static void usage()
{
printf("usage: unbound [options]\n");
printf("\tstart unbound daemon DNS resolver.\n");
printf("\t-h\tthis help\n");
printf("\t-v\tverbose (multiple times increase verbosity)\n");
printf("-h this help\n");
printf("-p port the port to listen on\n");
printf("-v verbose (multiple times increase verbosity)\n");
printf("Version %s\n", PACKAGE_VERSION);
printf("BSD licensed, see LICENSE file in source package.\n");
printf("Report bugs to %s.\n", PACKAGE_BUGREPORT);
@ -70,12 +77,21 @@ int
main(int argc, char* argv[])
{
struct comm_base *base = 0;
struct listen_dnsport* front = 0;
int do_ip4=1, do_ip6=1, do_udp=1, do_tcp=1;
const char* port = UNBOUND_DNS_PORT;
int c;
log_init();
/* parse the options */
while( (c=getopt(argc, argv, "hv")) != -1) {
while( (c=getopt(argc, argv, "hvp:")) != -1) {
switch(c) {
case 'p':
if(!atoi(optarg))
fatal_exit("invalid port '%s'", optarg);
port = optarg;
verbose(VERB_ALGO, "using port: %s", port);
break;
case 'v':
verbosity ++;
break;
@ -94,12 +110,20 @@ main(int argc, char* argv[])
return 1;
}
log_info("Start of %s.", PACKAGE_STRING);
/* setup */
base = comm_base_create();
if(!base)
fatal_exit("could not create commbase");
fatal_exit("could not create event handling base");
front = listen_create(base, 0, NULL, port, do_ip4, do_ip6,
do_udp, do_tcp, BUFSZ);
if(!front)
fatal_exit("could not create listening sockets");
log_info("Start of %s.", PACKAGE_STRING);
/* cleanup */
verbose(VERB_ALGO, "Exit cleanup.");
listen_delete(front);
comm_base_delete(base);
return 0;
}

View file

@ -5,6 +5,8 @@
- fixed libevent configure flag.
- detects event_base_free() in new libevent 1.2 version.
- getopt in daemon. fatal_exit() and verbose() logging funcs.
- created log_assert, that throws assertions to the logfile.
- listen_dnsport service. Binds ports.
24 January 2007: Wouter
- cleaned up configure.ac.

View file

@ -40,4 +40,296 @@
*/
#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>
/** number of queued TCP connections for listen() */
#define TCP_BACKLOG 5
/** number of simultaneous open TCP connections */
#define TCP_COUNT 10
/** callback of comm_point_callback_t for events. */
static int listen_udp_callback(struct comm_point* cp, void* arg, int error)
{
return 0;
}
/** callback of comm_point_callback_t for events. */
static int listen_tcp_callback(struct comm_point* cp, void* arg, int error)
{
return 0;
}
/**
* Debug print of the getaddrinfo returned address.
* @param addr: the address returned.
*/
static void
verbose_print_addr(struct addrinfo *addr)
{
if(verbosity >= VERB_ALGO) {
char buf[100];
if(inet_ntop(addr->ai_family,
&((struct sockaddr_in*)addr->ai_addr)->sin_addr, buf,
sizeof(buf)) == 0) {
strncpy(buf, "(null)", sizeof(buf));
}
verbose(VERB_ALGO, "creating %s %s socket %s %d",
addr->ai_family==AF_INET?"inet":
addr->ai_family==AF_INET6?"inet6":"otherfamily",
addr->ai_socktype==SOCK_DGRAM?"udp":
addr->ai_socktype==SOCK_STREAM?"tcp":"otherprotocol",
buf,
ntohs(((struct sockaddr_in*)addr->ai_addr)->sin_port));
}
}
/**
* Create and bind UDP socket
* @param addr: address info ready to make socket.
* @return: the socket. -1 on error.
*/
static int
create_udp_sock(struct addrinfo *addr)
{
int s, flag;
verbose_print_addr(addr);
if((s = socket(addr->ai_family, addr->ai_socktype, 0)) == -1) {
log_err("can't create socket: %s", strerror(errno));
return -1;
}
if(bind(s, (struct sockaddr*)addr->ai_addr, addr->ai_addrlen) != 0) {
log_err("can't bind socket: %s", strerror(errno));
return -1;
}
if((flag = fcntl(s, F_GETFL)) == -1) {
log_err("can't fcntl F_GETFL: %s", strerror(errno));
flag = 0;
}
flag |= O_NONBLOCK;
if(fcntl(s, F_SETFL, flag) == -1) {
log_err("can't fcntl F_SETFL: %s", strerror(errno));
return -1;
}
return s;
}
/**
* Create and bind TCP listening socket
* @param addr: address info ready to make socket.
* @return: the socket. -1 on error.
*/
static int
create_tcp_accept_sock(struct addrinfo *addr)
{
int s, flag;
#ifdef SO_REUSEADDR
int on = 1;
#endif /* SO_REUSEADDR */
verbose_print_addr(addr);
if((s = socket(addr->ai_family, addr->ai_socktype, 0)) == -1) {
log_err("can't create socket: %s", strerror(errno));
return -1;
}
#ifdef SO_REUSEADDR
if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
strerror(errno));
return -1;
}
#endif /* SO_REUSEADDR */
if(bind(s, (struct sockaddr*)addr->ai_addr, addr->ai_addrlen) != 0) {
log_err("can't bind socket: %s", strerror(errno));
return -1;
}
if((flag = fcntl(s, F_GETFL)) == -1) {
log_err("can't fcntl F_GETFL: %s", strerror(errno));
flag = 0;
}
flag |= O_NONBLOCK;
if(fcntl(s, F_SETFL, flag) == -1) {
log_err("can't fcntl F_SETFL: %s", strerror(errno));
return -1;
}
if(listen(s, TCP_BACKLOG) == -1) {
log_err("can't listen: %s", strerror(errno));
return -1;
}
return s;
}
/**
* Create socket from getaddrinfo results
*/
static int
make_sock(int stype, const char* ifname, const char* port,
struct addrinfo *hints)
{
struct addrinfo *res = NULL;
int r, s;
hints->ai_socktype = stype;
if((r=getaddrinfo(ifname, port, hints, &res)) != 0 || !res) {
log_err("node %s:%s getaddrinfo: %s %s",
ifname?ifname:"default", port, gai_strerror(r),
r==EAI_SYSTEM?strerror(errno):"");
return -1;
}
if(stype == SOCK_DGRAM)
s = create_udp_sock(res);
else s = create_tcp_accept_sock(res);
freeaddrinfo(res);
return s;
}
/**
* Helper for listen_create. 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.
* @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)
{
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,
listen_udp_callback, front);
if(!cp_udp) {
log_err("can't create commpoint");
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,
listen_tcp_callback, front);
if(!cp_tcp) {
log_err("can't create commpoint");
comm_point_delete(cp_udp);
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 0;
}
el_udp->com = cp_udp;
el_udp->next = front->cps;
front->cps = el_udp;
comm_point_set_cb_arg(el_udp->com, el_udp);
el_tcp->com = cp_tcp;
el_tcp->next = front->cps;
front->cps = el_tcp;
comm_point_set_cb_arg(el_tcp->com, el_tcp);
return 1;
}
struct listen_dnsport*
listen_create(struct comm_base* base, int num_ifs, const char* ifs[],
const char* port, int do_ip4, int do_ip6, int do_udp, int do_tcp,
size_t bufsize)
{
struct addrinfo hints;
int i;
struct listen_dnsport* front = (struct listen_dnsport*)
malloc(sizeof(struct listen_dnsport));
if(!front)
return NULL;
front->cps = NULL;
front->udp_buff = ldns_buffer_new(bufsize);
if(!front->udp_buff) {
free(front);
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;
if(!do_ip4 && !do_ip6) {
listen_delete(front);
return NULL;
} else 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;
}
if(num_ifs == 0) {
if(!listen_create_if(NULL, front, base, port,
do_udp, do_tcp, &hints, bufsize)) {
listen_delete(front);
return NULL;
}
} else for(i = 0; i<num_ifs; i++) {
if(!listen_create_if(ifs[i], front, base, port,
do_udp, do_tcp, &hints, bufsize)) {
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);
}

View file

@ -44,6 +44,7 @@
#include "config.h"
struct comm_base;
struct listen_list;
/**
* Listening for queries structure.
@ -52,6 +53,23 @@ struct comm_base;
struct listen_dnsport {
/** 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;
/** list of comm points used to get incoming events */
struct listen_list *cps;
};
/**
* Single linked list to store event points.
*/
struct listen_list {
/** next in list */
struct listen_list *next;
/** event info */
struct comm_point *com;
};
/**
@ -67,11 +85,13 @@ struct listen_dnsport {
* @param do_ip6: listen to ip6 queries.
* @param do_udp: listen to udp queries.
* @param do_tcp: listen to tcp queries.
* @return: the malloced listening structure, ready for use.
* @param bufsize: size of datagram buffer.
* @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);
int num_ifs, const char* ifs[], const char* port,
int do_ip4, int do_ip6, int do_udp, int do_tcp,
size_t bufsize);
/**
* delete the listening structure

View file

@ -108,4 +108,19 @@ void fatal_exit(const char* format, ...) ATTR_FORMAT(printf, 1, 2);
*/
void log_vmsg(const char* type, const char *format, va_list args);
/** always assert for now. */
#define UNBOUND_ASSERT 1
/**
* an assertion that is thrown to the logfile.
*/
#ifdef UNBOUND_ASSERT
# define log_assert(x) \
do { if(!(x)) \
fatal_exit("%s:%d: %s: assertion %s failed", \
__FILE__, __LINE__, __func__, #x); \
} while(0);
#else
# define log_assert(x) /*nothing*/
#endif
#endif /* UTIL_LOG_H */

View file

@ -325,12 +325,13 @@ comm_point_create_tcp(struct comm_base *base, int fd, int num, size_t bufsize,
void
comm_point_close(struct comm_point* c)
{
if(c->fd != -1)
close(c->fd);
c->fd = -1;
if(event_del(&c->ev->ev) != 0) {
log_err("could not event_del on close");
}
/* close fd after removing from event lists, or epoll/etc messes up */
if(c->fd != -1)
close(c->fd);
c->fd = -1;
}
void
@ -345,7 +346,15 @@ comm_point_delete(struct comm_point* c)
comm_point_delete(c->tcp_handlers[i]);
free(c->tcp_handlers);
}
if(c->type == comm_tcp)
ldns_buffer_free(c->buffer);
free(c->ev);
free(c);
}
void
comm_point_set_cb_arg(struct comm_point* c, void *arg)
{
log_assert(c);
c->cb_arg = arg;
}

View file

@ -225,4 +225,11 @@ void comm_point_close(struct comm_point* c);
*/
void comm_point_delete(struct comm_point* c);
/**
* Reset the callback argument for a comm point.
* @param c: the comm point to change.
* @param arg: the new callback user argument.
*/
void comm_point_set_cb_arg(struct comm_point* c, void *arg);
#endif /* NET_EVENT_H */