diff options
author | Stuart Henderson <sthen@cvs.openbsd.org> | 2013-11-26 12:50:31 +0000 |
---|---|---|
committer | Stuart Henderson <sthen@cvs.openbsd.org> | 2013-11-26 12:50:31 +0000 |
commit | b665eb4cb1ea56ccad7fee700f05c85dec76e702 (patch) | |
tree | 8453629bcc74596d1a3588c5a534658f6a7b3503 /usr.sbin/nsd/xfrd-tcp.h | |
parent | 9f9bd245ba092cf635e0212513052b389360c9ba (diff) |
import NSD 4.0.0, tests from Dorian Büttner, Patrik Lundin, requested by brad@
Diffstat (limited to 'usr.sbin/nsd/xfrd-tcp.h')
-rw-r--r-- | usr.sbin/nsd/xfrd-tcp.h | 95 |
1 files changed, 82 insertions, 13 deletions
diff --git a/usr.sbin/nsd/xfrd-tcp.h b/usr.sbin/nsd/xfrd-tcp.h index e42e1a4456a..ac3f9dc5aab 100644 --- a/usr.sbin/nsd/xfrd-tcp.h +++ b/usr.sbin/nsd/xfrd-tcp.h @@ -1,7 +1,7 @@ /* * xfrd-tcp.h - XFR (transfer) Daemon TCP system header file. Manages tcp conn. * - * Copyright (c) 2001-2011, NLnet Labs. All rights reserved. + * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. * * See LICENSE for the license. * @@ -10,7 +10,6 @@ #ifndef XFRD_TCP_H #define XFRD_TCP_H -#include "config.h" #include "xfrd.h" struct buffer; @@ -21,6 +20,7 @@ struct region; struct dname; struct acl_options; +struct xfrd_tcp_pipeline; typedef struct xfrd_tcp xfrd_tcp_t; typedef struct xfrd_tcp_set xfrd_tcp_set_t; /* @@ -28,12 +28,14 @@ typedef struct xfrd_tcp_set xfrd_tcp_set_t; */ struct xfrd_tcp_set { /* tcp connections, each has packet and read/wr state */ - struct xfrd_tcp *tcp_state[XFRD_MAX_TCP]; + struct xfrd_tcp_pipeline *tcp_state[XFRD_MAX_TCP]; /* number of TCP connections in use. */ int tcp_count; /* TCP timeout. */ int tcp_timeout; - /* linked list of zones waiting for a TCP connection */ + /* rbtree with pipelines sorted by master */ + rbtree_t* pipetree; + /* double linked list of zones waiting for a TCP connection */ struct xfrd_zone *tcp_waiting_first, *tcp_waiting_last; }; @@ -61,27 +63,91 @@ struct xfrd_tcp { struct buffer* packet; }; +/* use illegal pointer value to denote skipped ID number. + * if this does not work, we can allocate with malloc */ +#define TCP_NULL_SKIP ((struct xfrd_zone*)-1) +/* the number of ID values (16 bits) for a pipeline */ +#define ID_PIPE_NUM 65536 + +/** + * Structure to keep track of a pipelined set of queries on + * an open tcp connection. The queries may be answered with + * interleaved answer packets, the ID number disambiguates. + * Sorted by the master IP address so you can use lookup with + * smaller-or-equal to find the tcp connection most suitable. + */ +struct xfrd_tcp_pipeline { + /* the rbtree node, sorted by IP and nr of unused queries */ + rbnode_t node; + /* destination IP address */ +#ifdef INET6 + struct sockaddr_storage ip; +#else + struct sockaddr_in ip; +#endif /* INET6 */ + socklen_t ip_len; + /* number of unused IDs. used IDs are waiting to send their query, + * or have been sent but not not all answer packets have been received. + * Sorted by num_unused, so a lookup smaller-equal for 65536 finds the + * connection to that master that has the most free IDs. */ + int num_unused; + /* number of skip-set IDs (these are 'in-use') */ + int num_skip; + + int handler_added; + /* the event handler for this pipe (it'll disambiguate by ID) */ + struct event handler; + + /* the tcp connection to use for reading */ + xfrd_tcp_t* tcp_r; + /* the tcp connection to use for writing, if it is done successfully, + * then the first zone from the sendlist can be removed. */ + xfrd_tcp_t* tcp_w; + /* once a byte has been written, handshake complete */ + int connection_established; + + /* list of queries that want to send, first to get write event, + * if NULL, no write event interest */ + struct xfrd_zone* tcp_send_first, *tcp_send_last; + /* the unused and id arrays must be last in the structure */ + /* per-ID number the queries that have this ID number, every + * query owns one ID numbers (until it is done). NULL: unused + * When a query is done but not all answer-packets have been + * consumed for that ID number, the rest is skipped, this + * is denoted with the pointer-value TCP_NULL_SKIP, the ids that + * are skipped are not on the unused list. They may be + * removed once the last answer packet is skipped. + * ID_PIPE_NUM-num_unused values in the id array are nonNULL (either + * a zone pointer or SKIP) */ + struct xfrd_zone* id[ID_PIPE_NUM]; + /* unused ID numbers; the first part of the array contains the IDs */ + uint16_t unused[ID_PIPE_NUM]; +}; + /* create set of tcp connections */ xfrd_tcp_set_t* xfrd_tcp_set_create(struct region* region); /* init tcp state */ -xfrd_tcp_t* xfrd_tcp_create(struct region* region); +xfrd_tcp_t* xfrd_tcp_create(struct region* region, size_t bufsize); /* obtain tcp connection for a zone (or wait) */ void xfrd_tcp_obtain(xfrd_tcp_set_t* set, struct xfrd_zone* zone); /* release tcp connection for a zone (starts waiting) */ void xfrd_tcp_release(xfrd_tcp_set_t* set, struct xfrd_zone* zone); +/* release tcp pipe entirely (does not stop the zones inside it) */ +void xfrd_tcp_pipe_release(xfrd_tcp_set_t* set, struct xfrd_tcp_pipeline* tp, + int conn); /* use tcp connection to start xfr */ -void xfrd_tcp_xfr(xfrd_tcp_set_t* set, struct xfrd_zone* zone); +void xfrd_tcp_setup_write_packet(struct xfrd_tcp_pipeline* tp, + struct xfrd_zone* zone); /* initialize tcp_state for a zone. Opens the connection. true on success.*/ -int xfrd_tcp_open(xfrd_tcp_set_t* set, struct xfrd_zone* zone); +int xfrd_tcp_open(xfrd_tcp_set_t* set, struct xfrd_tcp_pipeline* tp, struct xfrd_zone* zone); /* read data from tcp, maybe partial read */ -void xfrd_tcp_read(xfrd_tcp_set_t* set, struct xfrd_zone* zone); +void xfrd_tcp_read(struct xfrd_tcp_pipeline* tp); /* write data to tcp, maybe a partial write */ -void xfrd_tcp_write(xfrd_tcp_set_t* set, struct xfrd_zone* zone); +void xfrd_tcp_write(struct xfrd_tcp_pipeline* tp, struct xfrd_zone* zone); +/* handle tcp pipe events */ +void xfrd_handle_tcp_pipe(int fd, short event, void* arg); -/* see if the tcp connection is in the reading stage (else writin) */ -static inline int xfrd_tcp_is_reading(xfrd_tcp_set_t* set, int conn) -{return set->tcp_state[conn]->is_reading;} /* * Read from a stream connection (size16)+packet into buffer. * returns value is @@ -103,7 +169,7 @@ int conn_write(xfrd_tcp_t* conn); /* setup DNS packet for a query of this type */ void xfrd_setup_packet(struct buffer* packet, - uint16_t type, uint16_t klass, const struct dname* dname); + uint16_t type, uint16_t klass, const struct dname* dname, uint16_t qid); /* write soa in network format to the packet buffer */ void xfrd_write_soa_buffer(struct buffer* packet, const struct dname* apex, struct xfrd_soa* soa); @@ -122,4 +188,7 @@ socklen_t xfrd_acl_sockaddr_frm(struct acl_options* acl, struct sockaddr_in *frm); #endif /* INET6 */ +/* create pipeline tcp structure */ +struct xfrd_tcp_pipeline* xfrd_tcp_pipeline_create(region_type* region); + #endif /* XFRD_TCP_H */ |