mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
udp work.
git-svn-id: file:///svn/unbound/trunk@45 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
9becddebbc
commit
775158882e
7 changed files with 180 additions and 45 deletions
|
|
@ -45,17 +45,87 @@
|
|||
#include "util/netevent.h"
|
||||
#include "services/listen_dnsport.h"
|
||||
|
||||
/** handles callbacks from listening event interface */
|
||||
static int worker_handle_request(ldns_buffer* packet, void* arg)
|
||||
/** 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(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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -55,18 +55,6 @@
|
|||
/** 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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,12 +43,9 @@
|
|||
#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
|
||||
|
|
|
|||
|
|
@ -146,12 +146,51 @@ comm_base_dispatch(struct comm_base* b)
|
|||
}
|
||||
}
|
||||
|
||||
/** send a UDP reply */
|
||||
static void
|
||||
comm_point_udp_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(event),
|
||||
void* arg)
|
||||
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 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");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,13 +55,15 @@
|
|||
|
||||
#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 */
|
||||
|
|
|
|||
Loading…
Reference in a new issue