From: Wouter Wijngaards Date: Fri, 2 Feb 2007 13:44:00 +0000 (+0000) Subject: Functioning DNS udp forwarding. X-Git-Tag: release-0.0~66 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fe87dd7b526242cd4aedc3e66bb27114064a4bd6;p=thirdparty%2Funbound.git Functioning DNS udp forwarding. git-svn-id: file:///svn/unbound/trunk@59 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/daemon/worker.c b/daemon/worker.c index f676e497a..bb83e73b1 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -54,13 +54,47 @@ /** timeout in seconds for UDP queries to auth servers. TODO: proper rtt */ #define UDP_QUERY_TIMEOUT 5 +/** the size of ID and flags, opcode, rcode in dns packet */ +#define ID_AND_FLAGS 4 + +/** reply to query with given error code */ +static void replyerror(int r, struct worker* worker) +{ + LDNS_QR_SET(ldns_buffer_begin(worker->query_reply.c->buffer)); + LDNS_RCODE_SET(ldns_buffer_begin(worker->query_reply.c->buffer), r); + comm_point_send_reply(&worker->query_reply); + worker->num_requests --; +} + +/** process incoming replies from the network */ +static int worker_handle_reply(struct comm_point* c, void* arg, int error, + struct comm_reply* ATTR_UNUSED(reply_info)) +{ + struct worker* worker = (struct worker*)arg; + if(error != 0) { + replyerror(LDNS_RCODE_SERVFAIL, worker); + return 0; + } + /* woohoo a reply! */ + ldns_buffer_clear(worker->query_reply.c->buffer); + ldns_buffer_skip(worker->query_reply.c->buffer, ID_AND_FLAGS); + ldns_buffer_write(worker->query_reply.c->buffer, + ldns_buffer_at(c->buffer, ID_AND_FLAGS), + ldns_buffer_limit(c->buffer) - ID_AND_FLAGS); + LDNS_QR_SET(ldns_buffer_begin(worker->query_reply.c->buffer)); + ldns_buffer_flip(worker->query_reply.c->buffer); + comm_point_send_reply(&worker->query_reply); + worker->num_requests --; + return 0; +} /** 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); + &worker->fwd_addr, worker->fwd_addrlen, UDP_QUERY_TIMEOUT, + worker_handle_reply, worker); } /** check request sanity. Returns error code, 0 OK, or -1 discard. @@ -117,6 +151,7 @@ static int worker_handle_request(struct comm_point* c, void* arg, int error, } if((ret=worker_check_request(c->buffer)) != 0) { if(ret != -1) { + LDNS_QR_SET(ldns_buffer_begin(c->buffer)); LDNS_RCODE_SET(ldns_buffer_begin(c->buffer), ret); return 1; } diff --git a/doc/Changelog b/doc/Changelog index 2cf55294a..58f2e3f0f 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -5,6 +5,7 @@ - listens on both ip4 and ip6 ports to provide correct return address. - worker fwder address filled correctly. - fixup timer code. + - forwards udp queries and sends answer. 1 February 2007: Wouter - outside network more UDP work. diff --git a/services/outside_network.c b/services/outside_network.c index 41f98d77a..d2ef6e9e2 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -106,9 +106,8 @@ static int outnet_udp_cb(struct comm_point* c, void* arg, int error, return 0; } comm_timer_disable(p->timer); - /* TODO handle it */ log_info("outnet handle udp reply"); - + (void)(*p->cb)(p->c, p->cb_arg, 0, NULL); return 0; } @@ -225,9 +224,10 @@ static void calc_num46(const char** ifs, int num_ifs, /** callback for udp timeout */ static void pending_udp_timer_cb(void *arg) { - /* struct pending* p = (struct pending*)arg; */ - /* it timed out . TODO handle it. */ + struct pending* p = (struct pending*)arg; + /* it timed out */ log_info("timeout udp"); + (void)(*p->cb)(p->c, p->cb_arg, -2, NULL); } struct outside_network* @@ -344,7 +344,8 @@ void pending_delete(struct outside_network* outnet, struct pending* p) /** create a new pending item with given characteristics, false on failure */ static struct pending* new_pending(struct outside_network* outnet, ldns_buffer* packet, - struct sockaddr_storage* addr, socklen_t addrlen) + struct sockaddr_storage* addr, socklen_t addrlen, + comm_point_callback_t* callback, void* callback_arg) { /* alloc */ int id_tries = 0; @@ -364,6 +365,8 @@ new_pending(struct outside_network* outnet, ldns_buffer* packet, pend->id = LDNS_ID_WIRE(ldns_buffer_begin(packet)); memcpy(&pend->addr, addr, addrlen); pend->addrlen = addrlen; + pend->cb = callback; + pend->cb_arg = callback_arg; /* insert in tree */ pend->node.key = pend; @@ -436,14 +439,16 @@ static void select_port(struct outside_network* outnet, struct pending* pend) void pending_udp_query(struct outside_network* outnet, ldns_buffer* packet, - struct sockaddr_storage* addr, socklen_t addrlen, int timeout) + struct sockaddr_storage* addr, socklen_t addrlen, int timeout, + comm_point_callback_t* cb, void* cb_arg) { struct pending* pend; struct timeval tv; /* create pending struct (and possibly change ID to be unique) */ - if(!(pend=new_pending(outnet, packet, addr, addrlen))) { + if(!(pend=new_pending(outnet, packet, addr, addrlen, cb, cb_arg))) { /* callback user for the error */ + (void)(*cb)(NULL, cb_arg, -1, NULL); return; } select_port(outnet, pend); @@ -454,6 +459,7 @@ void pending_udp_query(struct outside_network* outnet, ldns_buffer* packet, /* error, call error callback function */ pending_delete(outnet, pend); /* callback user for the error */ + (void)(*pend->cb)(pend->c, pend->cb_arg, -1, NULL); return; } diff --git a/services/outside_network.h b/services/outside_network.h index 1176877d0..4659238db 100644 --- a/services/outside_network.h +++ b/services/outside_network.h @@ -45,10 +45,9 @@ #include "config.h" #include "util/rbtree.h" +#include "util/netevent.h" struct pending; struct pending_timeout; -struct comm_point; -struct comm_base; /** * Send queries to outside servers and wait for answers from servers. @@ -97,6 +96,10 @@ struct pending { struct comm_point* c; /** timeout event */ struct comm_timer* timer; + /** callback for the timeout, error or reply to the message */ + comm_point_callback_t* cb; + /** callback user argument */ + void* cb_arg; }; /** @@ -129,9 +132,12 @@ void outside_network_delete(struct outside_network* outnet); * @param addr: address to send to. * @param addrlen: length of addr. * @param timeout: in seconds from now. + * @param callback: function to call on error, timeout or reply. + * @param callback_arg: user argument for callback function. */ void pending_udp_query(struct outside_network* outnet, ldns_buffer* packet, - struct sockaddr_storage* addr, socklen_t addrlen, int timeout); + struct sockaddr_storage* addr, socklen_t addrlen, int timeout, + comm_point_callback_t* callback, void* callback_arg); /** * Delete pending answer.