/** 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.
}
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;
}
- 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.
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;
}
/** 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*
/** 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;
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;
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);
/* 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;
}
#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.
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;
};
/**
* @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.