]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
udp work.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Wed, 31 Jan 2007 09:32:30 +0000 (09:32 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Wed, 31 Jan 2007 09:32:30 +0000 (09:32 +0000)
git-svn-id: file:///svn/unbound/trunk@45 be551aaa-1e26-0410-a405-d3ace91eadb9

daemon/worker.c
daemon/worker.h
doc/Changelog
services/listen_dnsport.c
services/listen_dnsport.h
util/netevent.c
util/netevent.h

index 38540dffcdacbefd28b78235f702678d127b9cd6..2aff3bb63a84c39bb2ebb66a9b14e96f776b8bc7 100644 (file)
 #include "util/netevent.h"
 #include "services/listen_dnsport.h"
 
+/** process incoming request */
+static void worker_process_query(struct worker* worker) 
+{
+       /* query the forwarding address */
+       
+}
+
+/** check request sanity. Returns error code, 0 OK, or -1 discard. */
+static int worker_check_request(ldns_buffer* pkt)
+{
+       if(ldns_buffer_limit(pkt) < LDNS_HEADER_SIZE) {
+               verbose(VERB_DETAIL, "request too short, discarded");
+               return -1;
+       }
+       if(LDNS_QR_WIRE(ldns_buffer_begin(pkt))) {
+               verbose(VERB_DETAIL, "request has QR bit on, discarded");
+               return -1;
+       }
+       if(LDNS_OPCODE_WIRE(ldns_buffer_begin(pkt)) != LDNS_PACKET_QUERY) {
+               verbose(VERB_DETAIL, "request unknown opcode %d", 
+                       LDNS_OPCODE_WIRE(ldns_buffer_begin(pkt)));
+               return LDNS_RCODE_NOTIMPL;
+       }
+       if(LDNS_QDCOUNT(ldns_buffer_begin(pkt)) != 1) {
+               verbose(VERB_DETAIL, "request wrong nr qd=%d", 
+                       LDNS_QDCOUNT(ldns_buffer_begin(pkt)));
+               return LDNS_RCODE_FORMERR;
+       }
+       if(LDNS_ANCOUNT(ldns_buffer_begin(pkt)) != 0) {
+               verbose(VERB_DETAIL, "request wrong nr an=%d", 
+                       LDNS_ANCOUNT(ldns_buffer_begin(pkt)));
+               return LDNS_RCODE_FORMERR;
+       }
+       if(LDNS_NSCOUNT(ldns_buffer_begin(pkt)) != 0) {
+               verbose(VERB_DETAIL, "request wrong nr ns=%d", 
+                       LDNS_NSCOUNT(ldns_buffer_begin(pkt)));
+               return LDNS_RCODE_FORMERR;
+       }
+       if(LDNS_ARCOUNT(ldns_buffer_begin(pkt)) != 0) {
+               verbose(VERB_DETAIL, "request wrong nr ar=%d", 
+                       LDNS_ARCOUNT(ldns_buffer_begin(pkt)));
+               return LDNS_RCODE_FORMERR;
+       }
+       return 0;
+}
+
 /** handles callbacks from listening event interface */
-static int worker_handle_request(ldns_buffer* packet, void* arg)
+static int worker_handle_request(struct comm_point* c, void* arg, int error,
+       struct comm_reply* repinfo)
 {
+       struct worker* worker = (struct worker*)arg;
+       int ret;
        log_info("worker handle request");
+       if(error != 0) {
+               log_err("called with err=%d", error);
+               return 0;
+       }
+       if((ret=worker_check_request(c->buffer)) != 0) {
+               if(ret != -1) {
+                       LDNS_RCODE_SET(ldns_buffer_begin(c->buffer), ret);
+                       return 1;
+               }
+               return 0;
+       }
+       if(worker->num_requests > 0) {
+               verbose(VERB_DETAIL, "worker: too many requests active. "
+                       "dropping incoming query.");
+               return 0;
+       }
+       /* answer it */
+       worker->num_requests ++;
+       memcpy(&worker->query_reply, repinfo, sizeof(struct comm_reply));
+       worker_process_query(worker);
        return 0;
 }
 
 struct worker* worker_init(const char* port, int do_ip4, int do_ip6,
        int do_udp, int do_tcp, size_t buffer_size)
 {
-       struct worker* worker = (struct worker*)malloc(sizeof(struct worker));
+       struct worker* worker = (struct worker*)calloc(1, 
+               sizeof(struct worker));
        if(!worker) 
                return NULL;
        worker->base = comm_base_create();
index aa184992d9722d3b5a2025ff6abd9dda59482341..b8ae640125b0dfe5cdae411f4435d2cea9796dec 100644 (file)
@@ -44,7 +44,7 @@
 #define DAEMON_WORKER_H
 
 #include "config.h"
-struct comm_base;
+#include "util/netevent.h"
 struct listen_dnsport;
 
 /**
@@ -57,6 +57,12 @@ struct worker {
 
        /** the frontside listening interface where request events come in */
        struct listen_dnsport* front;
+
+       /** our one and only query, packet buffer and where to send. */
+       struct comm_reply query_reply;
+
+       /** number of requests currently active */
+       int num_requests;
 };
 
 /**
index 01273603e2640d54cdb91414ea05156bcfccc1dd..c620816e4e13ac120e21e5dfdd1e412c40777dcf 100644 (file)
@@ -1,5 +1,9 @@
 31 January 2007: Wouter
        - Added makedist.sh script to make release tarball.
+       - Removed listen callback layer, did not add anything.
+       - Added UDP recv to netevent, worker callback for udp.
+       - netevent communication reply storage structure.
+       - minimal query header sanity checking for worker.
 
 30 January 2007: Wouter
        - links in example/ldns-testpkts.c and .h for premade packet support.
index 448bd468a2647d2a1e776c746788481c8bb8a88d..ec5781189f28b5efc68783df7f6bfa19924f55f7 100644 (file)
 /** 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.
@@ -199,12 +187,15 @@ make_sock(int stype, const char* ifname, const char* port,
  * @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.
  * @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 addrinfo *hints, size_t bufsize, comm_point_callback_t* cb, 
+       void *cb_arg)
 {
        struct comm_point *cp_udp = NULL, *cp_tcp = NULL;
        struct listen_list *el_udp, *el_tcp;
@@ -215,7 +206,7 @@ listen_create_if(const char* ifname, struct listen_dnsport* front,
                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);
+                       cb, cb_arg);
                if(!cp_udp) {
                        log_err("can't create commpoint");      
                        close(s);
@@ -228,7 +219,7 @@ listen_create_if(const char* ifname, struct listen_dnsport* front,
                        return 0;
                }
                cp_tcp = comm_point_create_tcp(base, s, TCP_COUNT, bufsize, 
-                       listen_tcp_callback, front);
+                       cb, cb_arg);
                if(!cp_tcp) {
                        log_err("can't create commpoint");      
                        comm_point_delete(cp_udp);
@@ -254,18 +245,16 @@ listen_create_if(const char* ifname, struct listen_dnsport* front,
        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, listen_dnsport_cb_t* cb, void *cb_arg)
+       size_t bufsize, comm_point_callback_t* cb, void *cb_arg)
 {
        struct addrinfo hints;
        int i;
@@ -274,8 +263,6 @@ listen_create(struct comm_base* base, int num_ifs, const char* ifs[],
        if(!front)
                return NULL;
        front->cps = NULL;
-       front->cb = cb;
-       front->cb_arg = cb_arg;
        front->udp_buff = ldns_buffer_new(bufsize);
        if(!front->udp_buff) {
                free(front);
@@ -304,13 +291,13 @@ listen_create(struct comm_base* base, int num_ifs, const char* ifs[],
 
        if(num_ifs == 0) {
                if(!listen_create_if(NULL, front, base, port, 
-                       do_udp, do_tcp, &hints, bufsize)) {
+                       do_udp, do_tcp, &hints, bufsize, cb, cb_arg)) {
                        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)) {
+                       do_udp, do_tcp, &hints, bufsize, cb, cb_arg)) {
                        listen_delete(front);
                        return NULL;
                }
index a4b0e05e7eea0fe0b9a498410eef233db81b3045..70818db275ccf6ce0d7b334f50e1b5c166063a77 100644 (file)
 #define LISTEN_DNSPORT_H
 
 #include "config.h"
-struct comm_base;
+#include "util/netevent.h"
 struct listen_list;
 
-/** The callback type for a incoming request packet */
-typedef int listen_dnsport_cb_t(ldns_buffer* packet, void* arg);
-
 /**
  * Listening for queries structure.
  * Contains list of query-listen sockets.
@@ -63,12 +60,6 @@ struct listen_dnsport {
 
        /** list of comm points used to get incoming events */
        struct listen_list *cps;
-       
-       /** callback function that accepts incoming message. */
-       listen_dnsport_cb_t* cb;
-
-       /** callback argument */
-       void *cb_arg;
 };
 
 /**
@@ -95,14 +86,15 @@ struct listen_list {
  * @param do_udp: listen to udp queries.
  * @param do_tcp: listen to tcp queries.
  * @param bufsize: size of datagram buffer.
- * @param cb: callback function when a request arrives.
+ * @param cb: callback function when a request arrives. It is passed
+ *       the packet and user argument. Return true to send a reply.
  * @param cb_arg: user data argument for callback function.
  * @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[], const char* port,
        int do_ip4, int do_ip6, int do_udp, int do_tcp,
-       size_t bufsize, listen_dnsport_cb_t* cb, void *cb_arg);
+       size_t bufsize, comm_point_callback_t* cb, void *cb_arg);
 
 /**
  * delete the listening structure
index 246198dbe104776a892e62ef1862b1440cc264fa..95622ad6885378686c018e445f20b88452fed2f6 100644 (file)
@@ -146,12 +146,51 @@ comm_base_dispatch(struct comm_base* b)
        }
 }
 
+/** send a UDP reply */
+static void
+comm_point_send_udp_msg(struct comm_point *c, struct sockaddr* addr,
+       socklen_t addrlen) {
+       ssize_t sent;
+       sent = sendto(c->fd, ldns_buffer_begin(c->buffer), 
+               ldns_buffer_remaining(c->buffer), 0,
+               addr, addrlen);
+       if(sent == -1) {
+               log_err("sendto failed: %s", strerror(errno));
+       } else if((size_t)sent != ldns_buffer_remaining(c->buffer)) {
+               log_err("sent %d in place of %d bytes", 
+                       sent, (int)ldns_buffer_remaining(c->buffer));
+       }
+}
+
 static void 
-comm_point_udp_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(event), 
-       void* arg)
+comm_point_udp_callback(int fd, short event, void* arg)
 {
-       struct comm_point* c = (struct comm_point*)arg;
-       log_info("callback udp for %x", (int)c);
+       struct comm_reply rep;
+       ssize_t recv;
+
+       rep.c = (struct comm_point*)arg;
+
+       verbose(VERB_ALGO, "callback udp");
+       if(!(event&EV_READ))
+               return;
+       log_assert(rep.c && rep.c->buffer && rep.c->fd == fd);
+       ldns_buffer_clear(rep.c->buffer);
+       recv = recvfrom(fd, ldns_buffer_begin(rep.c->buffer), 
+               ldns_buffer_remaining(rep.c->buffer), 0, 
+               (struct sockaddr*)&rep.addr, &rep.addrlen);
+       if(recv == -1) {
+               if(errno != EAGAIN && errno != EINTR) {
+                       log_err("recvfrom failed: %s", strerror(errno));
+               }
+               return;
+       }
+       ldns_buffer_skip(rep.c->buffer, recv);
+       ldns_buffer_flip(rep.c->buffer);
+       if((*rep.c->callback)(rep.c, rep.c->cb_arg, 0, &rep)) {
+               /* send back immediate reply */
+               comm_point_send_udp_msg(rep.c, (struct sockaddr*)&rep.addr, 
+                       rep.addrlen);
+       }
 }
 
 static void 
@@ -358,3 +397,15 @@ comm_point_set_cb_arg(struct comm_point* c, void *arg)
        log_assert(c);
        c->cb_arg = arg;
 }
+
+void comm_point_send_reply(struct comm_reply *repinfo)
+{
+       log_assert(repinfo && repinfo->c);
+       if(repinfo->c->type == comm_udp) {
+               comm_point_send_udp_msg(repinfo->c, 
+                       (struct sockaddr*)&repinfo->addr, repinfo->addrlen);
+       } else {
+               log_info("tcp reply");
+       }
+}
+
index 3360b870200cd9a4b4a3d87a7326f73a1bee1c13..754e5d0aa339bba31a97256817d50d7f900a5f1f 100644 (file)
 
 #include "config.h"
 struct comm_point;
+struct comm_reply;
 
 /* internal event notification data storage structure. */
 struct internal_event;
 struct internal_base;
 
 /** callback from communication point function type */
-typedef int comm_point_callback_t(struct comm_point*, void*, int);
+typedef int comm_point_callback_t(struct comm_point*, void*, int, 
+       struct comm_reply*);
 
 /**
  * A communication point dispatcher. Thread specific.
@@ -142,10 +144,15 @@ struct comm_point {
            nonzero. If nonzero, it is an errno value.
            If the connection is closed (by remote end) then the
            callback is called with error set to -1.
+           If a timeout happens on the connection, the error is set to -2.
+           The reply_info can be copied if the reply needs to happen at a
+           later time. It consists of a struct with commpoint and address.
+           It can be passed to a msg send routine some time later.
+           Note the reply information is temporary and must be copied.
 
            declare as: 
-           int my_callback(struct comm_point* c, void* my_arg, 
-               int timeout, int error);
+           int my_callback(struct comm_point* c, void* my_arg, int error,
+               struct comm_reply *reply_info);
 
            if the routine returns 0, nothing is done.
            Notzero, the buffer will be sent back to client.
@@ -157,6 +164,18 @@ struct comm_point {
        void *cb_arg;
 };
 
+/**
+ * Reply information for a communication point.
+ */
+struct comm_reply {
+       /** the comm_point with fd to send reply on to. */
+       struct comm_point *c;
+       /** the address (for UDP based communication) */
+       struct sockaddr_storage addr;
+       /** length of address */
+       socklen_t addrlen;
+};
+
 /**
  * Create a new comm base.
  * @return: the new comm base. NULL on error.
@@ -232,4 +251,10 @@ void comm_point_delete(struct comm_point* c);
  */
 void comm_point_set_cb_arg(struct comm_point* c, void *arg);
 
+/**
+ * Send reply. Put message into commpoint buffer.
+ * @param repinfo: The reply info copied from a commpoint callback call.
+ */
+void comm_point_send_reply(struct comm_reply *repinfo);
+
 #endif /* NET_EVENT_H */