diff options
author | Dag-Erling Smørgrav <des@FreeBSD.org> | 2014-05-14 18:44:22 +0000 |
---|---|---|
committer | Dag-Erling Smørgrav <des@FreeBSD.org> | 2014-05-14 18:44:22 +0000 |
commit | 79dd93c19fd35899133800562b0db20f1a4c0f56 (patch) | |
tree | 86c1332d2843f4c80ae64365c16ba04306b6f542 /services | |
parent | f61d78fb42d2662643e7f0dbdcb97adbc2589dbc (diff) | |
download | src-79dd93c19fd35899133800562b0db20f1a4c0f56.tar.gz src-79dd93c19fd35899133800562b0db20f1a4c0f56.zip |
import unbound 1.4.22vendor/unbound/1.4.22
Notes
Notes:
svn path=/vendor/unbound/dist/; revision=266077
svn path=/vendor/unbound/1.4.22/; revision=266078; tag=vendor/unbound/1.4.22
Diffstat (limited to 'services')
-rw-r--r-- | services/cache/dns.c | 23 | ||||
-rw-r--r-- | services/cache/dns.h | 20 | ||||
-rw-r--r-- | services/cache/infra.c | 22 | ||||
-rw-r--r-- | services/cache/infra.h | 20 | ||||
-rw-r--r-- | services/cache/rrset.c | 21 | ||||
-rw-r--r-- | services/cache/rrset.h | 20 | ||||
-rw-r--r-- | services/listen_dnsport.c | 142 | ||||
-rw-r--r-- | services/listen_dnsport.h | 40 | ||||
-rw-r--r-- | services/localzone.c | 329 | ||||
-rw-r--r-- | services/localzone.h | 29 | ||||
-rw-r--r-- | services/mesh.c | 55 | ||||
-rw-r--r-- | services/mesh.h | 33 | ||||
-rw-r--r-- | services/modstack.c | 20 | ||||
-rw-r--r-- | services/modstack.h | 20 | ||||
-rw-r--r-- | services/outbound_list.c | 20 | ||||
-rw-r--r-- | services/outbound_list.h | 20 | ||||
-rw-r--r-- | services/outside_network.c | 242 | ||||
-rw-r--r-- | services/outside_network.h | 40 |
18 files changed, 610 insertions, 506 deletions
diff --git a/services/cache/dns.c b/services/cache/dns.c index 7dadb5c39656..f2a04a227cb9 100644 --- a/services/cache/dns.c +++ b/services/cache/dns.c @@ -21,16 +21,16 @@ * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @@ -50,6 +50,7 @@ #include "util/net_help.h" #include "util/regional.h" #include "util/config_file.h" +#include "ldns/sbuffer.h" /** store rrsets in the rrset cache. * @param env: module environment with caches. @@ -615,7 +616,7 @@ synth_dname_msg(struct ub_packed_rrset_key* rrset, struct regional* region, newd->rr_ttl[0] = newd->ttl; msg->rep->ttl = newd->ttl; msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(newd->ttl); - ldns_write_uint16(newd->rr_data[0], newlen); + sldns_write_uint16(newd->rr_data[0], newlen); memmove(newd->rr_data[0] + sizeof(uint16_t), newname, newlen); msg->rep->an_numrrsets ++; msg->rep->rrset_count ++; diff --git a/services/cache/dns.h b/services/cache/dns.h index 508f34441118..a7a6190cffba 100644 --- a/services/cache/dns.h +++ b/services/cache/dns.h @@ -21,16 +21,16 @@ * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** diff --git a/services/cache/infra.c b/services/cache/infra.c index 42d6acad1a22..07f2103d756b 100644 --- a/services/cache/infra.c +++ b/services/cache/infra.c @@ -21,16 +21,16 @@ * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @@ -39,7 +39,7 @@ * This file contains the infrastructure cache. */ #include "config.h" -#include <ldns/rr.h> +#include "ldns/rrdef.h" #include "services/cache/infra.h" #include "util/storage/slabhash.h" #include "util/storage/lookup3.h" diff --git a/services/cache/infra.h b/services/cache/infra.h index d3976aed7113..fc54f7f0df00 100644 --- a/services/cache/infra.h +++ b/services/cache/infra.h @@ -21,16 +21,16 @@ * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** diff --git a/services/cache/rrset.c b/services/cache/rrset.c index 642236231121..5f52dbce1948 100644 --- a/services/cache/rrset.c +++ b/services/cache/rrset.c @@ -21,16 +21,16 @@ * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @@ -40,6 +40,7 @@ */ #include "config.h" #include "services/cache/rrset.h" +#include "ldns/rrdef.h" #include "util/storage/slabhash.h" #include "util/config_file.h" #include "util/data/packed_rrset.h" diff --git a/services/cache/rrset.h b/services/cache/rrset.h index 92ced928b304..98e44a4e5268 100644 --- a/services/cache/rrset.h +++ b/services/cache/rrset.h @@ -21,16 +21,16 @@ * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** diff --git a/services/listen_dnsport.c b/services/listen_dnsport.c index 368faaea4211..8b1d62e3a209 100644 --- a/services/listen_dnsport.c +++ b/services/listen_dnsport.c @@ -21,16 +21,16 @@ * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @@ -49,6 +49,7 @@ #include "util/log.h" #include "util/config_file.h" #include "util/net_help.h" +#include "ldns/sbuffer.h" #ifdef HAVE_NETDB_H #include <netdb.h> @@ -75,7 +76,7 @@ verbose_print_addr(struct addrinfo *addr) #endif /* INET6 */ if(inet_ntop(addr->ai_family, sinaddr, buf, (socklen_t)sizeof(buf)) == 0) { - strncpy(buf, "(null)", sizeof(buf)); + (void)strlcpy(buf, "(null)", sizeof(buf)); } buf[sizeof(buf)-1] = 0; verbose(VERB_ALGO, "creating %s%s socket %s %d", @@ -91,10 +92,10 @@ verbose_print_addr(struct addrinfo *addr) int create_udp_sock(int family, int socktype, struct sockaddr* addr, socklen_t addrlen, int v6only, int* inuse, int* noproto, - int rcv, int snd) + int rcv, int snd, int listen, int* reuseport) { int s; -#if defined(IPV6_USE_MIN_MTU) +#if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_USE_MIN_MTU) int on=1; #endif #ifdef IPV6_MTU @@ -129,6 +130,50 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr, *noproto = 0; return -1; } + if(listen) { +#ifdef SO_REUSEADDR + if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on, + (socklen_t)sizeof(on)) < 0) { +#ifndef USE_WINSOCK + log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s", + strerror(errno)); + if(errno != ENOSYS) { + close(s); + *noproto = 0; + *inuse = 0; + return -1; + } +#else + log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s", + wsa_strerror(WSAGetLastError())); + closesocket(s); + *noproto = 0; + *inuse = 0; + return -1; +#endif + } +#endif /* SO_REUSEADDR */ +#if defined(__linux__) && defined(SO_REUSEPORT) + /* Linux specific: try to set SO_REUSEPORT so that incoming + * queries are distributed evenly among the receiving threads. + * Each thread must have its own socket bound to the same port, + * with SO_REUSEPORT set on each socket. + */ + if (reuseport && *reuseport && + setsockopt(s, SOL_SOCKET, SO_REUSEPORT, (void*)&on, + (socklen_t)sizeof(on)) < 0) { +#ifdef ENOPROTOOPT + if(errno != ENOPROTOOPT || verbosity >= 3) + log_warn("setsockopt(.. SO_REUSEPORT ..) failed: %s", + strerror(errno)); +#endif + /* this option is not essential, we can continue */ + *reuseport = 0; + } +#else + (void)reuseport; +#endif /* defined(__linux__) && defined(SO_REUSEPORT) */ + } if(rcv) { #ifdef SO_RCVBUF int got; @@ -391,10 +436,11 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr, } int -create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto) +create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto, + int* reuseport) { int s; -#if defined(SO_REUSEADDR) || defined(IPV6_V6ONLY) +#if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_V6ONLY) int on = 1; #endif /* SO_REUSEADDR || IPV6_V6ONLY */ verbose_print_addr(addr); @@ -432,6 +478,26 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto) return -1; } #endif /* SO_REUSEADDR */ +#if defined(__linux__) && defined(SO_REUSEPORT) + /* Linux specific: try to set SO_REUSEPORT so that incoming + * connections are distributed evenly among the receiving threads. + * Each thread must have its own socket bound to the same port, + * with SO_REUSEPORT set on each socket. + */ + if (reuseport && *reuseport && + setsockopt(s, SOL_SOCKET, SO_REUSEPORT, (void*)&on, + (socklen_t)sizeof(on)) < 0) { +#ifdef ENOPROTOOPT + if(errno != ENOPROTOOPT || verbosity >= 3) + log_warn("setsockopt(.. SO_REUSEPORT ..) failed: %s", + strerror(errno)); +#endif + /* this option is not essential, we can continue */ + *reuseport = 0; + } +#else + (void)reuseport; +#endif /* defined(__linux__) && defined(SO_REUSEPORT) */ #if defined(IPV6_V6ONLY) if(addr->ai_family == AF_INET6 && v6only) { if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, @@ -499,7 +565,8 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto) */ static int make_sock(int stype, const char* ifname, const char* port, - struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd) + struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd, + int* reuseport) { struct addrinfo *res = NULL; int r, s, inuse, noproto; @@ -526,14 +593,15 @@ make_sock(int stype, const char* ifname, const char* port, verbose_print_addr(res); s = create_udp_sock(res->ai_family, res->ai_socktype, (struct sockaddr*)res->ai_addr, res->ai_addrlen, - v6only, &inuse, &noproto, (int)rcv, (int)snd); + v6only, &inuse, &noproto, (int)rcv, (int)snd, 1, + reuseport); if(s == -1 && inuse) { log_err("bind: address already in use"); } else if(s == -1 && noproto && hints->ai_family == AF_INET6){ *noip6 = 1; } } else { - s = create_tcp_accept_sock(res, v6only, &noproto); + s = create_tcp_accept_sock(res, v6only, &noproto, reuseport); if(s == -1 && noproto && hints->ai_family == AF_INET6){ *noip6 = 1; } @@ -545,7 +613,8 @@ make_sock(int stype, const char* ifname, const char* port, /** make socket and first see if ifname contains port override info */ static int make_sock_port(int stype, const char* ifname, const char* port, - struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd) + struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd, + int* reuseport) { char* s = strchr(ifname, '@'); if(s) { @@ -562,14 +631,15 @@ make_sock_port(int stype, const char* ifname, const char* port, *noip6 = 0; return -1; } - strncpy(newif, ifname, sizeof(newif)); + (void)strlcpy(newif, ifname, sizeof(newif)); newif[s-ifname] = 0; - strncpy(p, s+1, sizeof(p)); + (void)strlcpy(p, s+1, sizeof(p)); p[strlen(s+1)]=0; return make_sock(stype, newif, p, hints, v6only, noip6, - rcv, snd); + rcv, snd, reuseport); } - return make_sock(stype, ifname, port, hints, v6only, noip6, rcv, snd); + return make_sock(stype, ifname, port, hints, v6only, noip6, rcv, snd, + reuseport); } /** @@ -661,19 +731,21 @@ set_recvpktinfo(int s, int family) * @param rcv: receive buffer size for UDP * @param snd: send buffer size for UDP * @param ssl_port: ssl service port number + * @param reuseport: try to set SO_REUSEPORT if nonNULL and true. + * set to false on exit if reuseport failed due to no kernel support. * @return: returns false on error. */ static int ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp, struct addrinfo *hints, const char* port, struct listen_port** list, - size_t rcv, size_t snd, int ssl_port) + size_t rcv, size_t snd, int ssl_port, int* reuseport) { int s, noip6=0; if(!do_udp && !do_tcp) return 0; if(do_auto) { if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1, - &noip6, rcv, snd)) == -1) { + &noip6, rcv, snd, reuseport)) == -1) { if(noip6) { log_warn("IPv6 protocol not available"); return 1; @@ -700,7 +772,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp, } else if(do_udp) { /* regular udp socket */ if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1, - &noip6, rcv, snd)) == -1) { + &noip6, rcv, snd, reuseport)) == -1) { if(noip6) { log_warn("IPv6 protocol not available"); return 1; @@ -721,7 +793,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp, atoi(strchr(ifname, '@')+1) == ssl_port) || (!strchr(ifname, '@') && atoi(port) == ssl_port)); if((s = make_sock_port(SOCK_STREAM, ifname, port, hints, 1, - &noip6, 0, 0)) == -1) { + &noip6, 0, 0, reuseport)) == -1) { if(noip6) { /*log_warn("IPv6 protocol not available");*/ return 1; @@ -772,7 +844,7 @@ listen_create(struct comm_base* base, struct listen_port* ports, if(!front) return NULL; front->cps = NULL; - front->udp_buff = ldns_buffer_new(bufsize); + front->udp_buff = sldns_buffer_new(bufsize); if(!front->udp_buff) { free(front); return NULL; @@ -835,12 +907,12 @@ listen_delete(struct listen_dnsport* front) if(!front) return; listen_list_delete(front->cps); - ldns_buffer_free(front->udp_buff); + sldns_buffer_free(front->udp_buff); free(front); } struct listen_port* -listening_ports_open(struct config_file* cfg) +listening_ports_open(struct config_file* cfg, int* reuseport) { struct listen_port* list = NULL; struct addrinfo hints; @@ -876,7 +948,7 @@ listening_ports_open(struct config_file* cfg) do_auto, cfg->do_udp, do_tcp, &hints, portbuf, &list, cfg->so_rcvbuf, cfg->so_sndbuf, - cfg->ssl_port)) { + cfg->ssl_port, reuseport)) { listening_ports_free(list); return NULL; } @@ -887,7 +959,7 @@ listening_ports_open(struct config_file* cfg) do_auto, cfg->do_udp, do_tcp, &hints, portbuf, &list, cfg->so_rcvbuf, cfg->so_sndbuf, - cfg->ssl_port)) { + cfg->ssl_port, reuseport)) { listening_ports_free(list); return NULL; } @@ -900,7 +972,7 @@ listening_ports_open(struct config_file* cfg) if(!ports_create_if(cfg->ifs[i], 0, cfg->do_udp, do_tcp, &hints, portbuf, &list, cfg->so_rcvbuf, cfg->so_sndbuf, - cfg->ssl_port)) { + cfg->ssl_port, reuseport)) { listening_ports_free(list); return NULL; } @@ -911,7 +983,7 @@ listening_ports_open(struct config_file* cfg) if(!ports_create_if(cfg->ifs[i], 0, cfg->do_udp, do_tcp, &hints, portbuf, &list, cfg->so_rcvbuf, cfg->so_sndbuf, - cfg->ssl_port)) { + cfg->ssl_port, reuseport)) { listening_ports_free(list); return NULL; } @@ -941,7 +1013,7 @@ size_t listen_get_mem(struct listen_dnsport* listen) { size_t s = sizeof(*listen) + sizeof(*listen->base) + sizeof(*listen->udp_buff) + - ldns_buffer_capacity(listen->udp_buff); + sldns_buffer_capacity(listen->udp_buff); struct listen_list* p; for(p = listen->cps; p; p = p->next) { s += sizeof(*p); diff --git a/services/listen_dnsport.h b/services/listen_dnsport.h index 4d37aca5eee4..61fb9a0b44e8 100644 --- a/services/listen_dnsport.h +++ b/services/listen_dnsport.h @@ -21,16 +21,16 @@ * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @@ -46,6 +46,7 @@ struct listen_list; struct config_file; struct addrinfo; +struct sldns_buffer; /** * Listening for queries structure. @@ -57,7 +58,7 @@ struct listen_dnsport { /** buffer shared by UDP connections, since there is only one datagram at any time. */ - ldns_buffer* udp_buff; + struct sldns_buffer* udp_buff; /** list of comm points used to get incoming events */ struct listen_list* cps; @@ -106,9 +107,13 @@ struct listen_port { * interfaces for IP4 and/or IP6, for UDP and/or TCP. * On the given port number. It creates the sockets. * @param cfg: settings on what ports to open. + * @param reuseport: set to true if you want reuseport, or NULL to not have it, + * set to false on exit if reuseport failed to apply (because of no + * kernel support). * @return: linked list of ports or NULL on error. */ -struct listen_port* listening_ports_open(struct config_file* cfg); +struct listen_port* listening_ports_open(struct config_file* cfg, + int* reuseport); /** * Close and delete the (list of) listening ports. @@ -178,19 +183,26 @@ void listen_start_accept(struct listen_dnsport* listen); IPv6 proto (family) is not available. * @param rcv: set size on rcvbuf with socket option, if 0 it is not set. * @param snd: set size on sndbuf with socket option, if 0 it is not set. + * @param listen: if true, this is a listening UDP port, eg port 53, and + * set SO_REUSEADDR on it. + * @param reuseport: if nonNULL and true, try to set SO_REUSEPORT on + * listening UDP port. Set to false on return if it failed to do so. * @return: the socket. -1 on error. */ int create_udp_sock(int family, int socktype, struct sockaddr* addr, socklen_t addrlen, int v6only, int* inuse, int* noproto, int rcv, - int snd); + int snd, int listen, int* reuseport); /** * Create and bind TCP listening socket * @param addr: address info ready to make socket. * @param v6only: enable ip6 only flag on ip6 sockets. * @param noproto: if error caused by lack of protocol support. + * @param reuseport: if nonNULL and true, try to set SO_REUSEPORT on + * listening UDP port. Set to false on return if it failed to do so. * @return: the socket. -1 on error. */ -int create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto); +int create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto, + int* reuseport); #endif /* LISTEN_DNSPORT_H */ diff --git a/services/localzone.c b/services/localzone.c index 4a2187ec4f25..ac889799b430 100644 --- a/services/localzone.c +++ b/services/localzone.c @@ -21,16 +21,16 @@ * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @@ -39,9 +39,9 @@ * This file contains functions to enable local zone authority service. */ #include "config.h" -#include <ldns/dname.h> -#include <ldns/host2wire.h> #include "services/localzone.h" +#include "ldns/str2wire.h" +#include "ldns/sbuffer.h" #include "util/regional.h" #include "util/config_file.h" #include "util/data/dname.h" @@ -59,7 +59,7 @@ local_zones_create(void) if(!zones) return NULL; rbtree_init(&zones->ztree, &local_zone_cmp); - lock_quick_init(&zones->lock); + lock_rw_init(&zones->lock); lock_protect(&zones->lock, &zones->ztree, sizeof(zones->ztree)); /* also lock protects the rbnode's in struct local_zone */ return zones; @@ -78,7 +78,7 @@ local_zones_delete(struct local_zones* zones) { if(!zones) return; - lock_quick_destroy(&zones->lock); + lock_rw_destroy(&zones->lock); /* walk through zones and delete them all */ traverse_postorder(&zones->ztree, lzdel, NULL); free(zones); @@ -125,19 +125,10 @@ local_data_cmp(const void* d1, const void* d2) int parse_dname(const char* str, uint8_t** res, size_t* len, int* labs) { - ldns_rdf* rdf; - *res = NULL; - *len = 0; + *res = sldns_str2wire_dname(str, len); *labs = 0; - rdf = ldns_dname_new_frm_str(str); - if(!rdf) { - log_err("cannot parse name %s", str); - return 0; - } - *res = memdup(ldns_rdf_data(rdf), ldns_rdf_size(rdf)); - ldns_rdf_deep_free(rdf); if(!*res) { - log_err("out of memory"); + log_err("cannot parse name %s", str); return 0; } *labs = dname_count_size_labels(*res, len); @@ -183,16 +174,16 @@ lz_enter_zone_dname(struct local_zones* zones, uint8_t* nm, size_t len, } /* add to rbtree */ - lock_quick_lock(&zones->lock); + lock_rw_wrlock(&zones->lock); lock_rw_wrlock(&z->lock); if(!rbtree_insert(&zones->ztree, &z->node)) { log_warn("duplicate local-zone"); lock_rw_unlock(&z->lock); local_zone_delete(z); - lock_quick_unlock(&zones->lock); + lock_rw_unlock(&zones->lock); return NULL; } - lock_quick_unlock(&zones->lock); + lock_rw_unlock(&zones->lock); return z; } @@ -225,39 +216,28 @@ lz_enter_zone(struct local_zones* zones, const char* name, const char* type, /** return name and class and rdata of rr; parses string */ static int get_rr_content(const char* str, uint8_t** nm, uint16_t* type, - uint16_t* dclass, time_t* ttl, ldns_buffer* rdata) + uint16_t* dclass, time_t* ttl, uint8_t* rr, size_t len, + uint8_t** rdata, size_t* rdata_len) { - ldns_rr* rr = NULL; - ldns_status status = ldns_rr_new_frm_str(&rr, str, 3600, NULL, NULL); - if(status != LDNS_STATUS_OK) { - log_err("error parsing local-data '%s': %s", - str, ldns_get_errorstr_by_id(status)); - ldns_rr_free(rr); + size_t dname_len = 0; + int e = sldns_str2wire_rr_buf(str, rr, &len, &dname_len, 3600, + NULL, 0, NULL, 0); + if(e) { + log_err("error parsing local-data at %d: '%s': %s", + LDNS_WIREPARSE_OFFSET(e), str, + sldns_get_errorstr_parse(e)); return 0; } - *nm = memdup(ldns_rdf_data(ldns_rr_owner(rr)), - ldns_rdf_size(ldns_rr_owner(rr))); + *nm = memdup(rr, dname_len); if(!*nm) { log_err("out of memory"); - ldns_rr_free(rr); return 0; } - *dclass = ldns_rr_get_class(rr); - *type = ldns_rr_get_type(rr); - *ttl = (time_t)ldns_rr_ttl(rr); - ldns_buffer_clear(rdata); - ldns_buffer_skip(rdata, 2); - status = ldns_rr_rdata2buffer_wire(rdata, rr); - ldns_rr_free(rr); - if(status != LDNS_STATUS_OK) { - log_err("error converting RR '%s' to wireformat: %s", - str, ldns_get_errorstr_by_id(status)); - free(*nm); - *nm = NULL; - return 0; - } - ldns_buffer_flip(rdata); - ldns_buffer_write_u16_at(rdata, 0, ldns_buffer_limit(rdata) - 2); + *dclass = sldns_wirerr_get_class(rr, len, dname_len); + *type = sldns_wirerr_get_type(rr, len, dname_len); + *ttl = (time_t)sldns_wirerr_get_ttl(rr, len, dname_len); + *rdata = sldns_wirerr_get_rdatawl(rr, len, dname_len); + *rdata_len = sldns_wirerr_get_rdatalen(rr, len, dname_len)+2; return 1; } @@ -265,18 +245,18 @@ get_rr_content(const char* str, uint8_t** nm, uint16_t* type, static int get_rr_nameclass(const char* str, uint8_t** nm, uint16_t* dclass) { - ldns_rr* rr = NULL; - ldns_status status = ldns_rr_new_frm_str(&rr, str, 3600, NULL, NULL); - if(status != LDNS_STATUS_OK) { - log_err("error parsing local-data '%s': %s", - str, ldns_get_errorstr_by_id(status)); - ldns_rr_free(rr); + uint8_t rr[LDNS_RR_BUF_SIZE]; + size_t len = sizeof(rr), dname_len = 0; + int s = sldns_str2wire_rr_buf(str, rr, &len, &dname_len, 3600, + NULL, 0, NULL, 0); + if(s != 0) { + log_err("error parsing local-data at %d '%s': %s", + LDNS_WIREPARSE_OFFSET(s), str, + sldns_get_errorstr_parse(s)); return 0; } - *nm = memdup(ldns_rdf_data(ldns_rr_owner(rr)), - ldns_rdf_size(ldns_rr_owner(rr))); - *dclass = ldns_rr_get_class(rr); - ldns_rr_free(rr); + *nm = memdup(rr, dname_len); + *dclass = sldns_wirerr_get_class(rr, len, dname_len); if(!*nm) { log_err("out of memory"); return 0; @@ -304,13 +284,12 @@ local_data_find_type(struct local_data* data, uint16_t type) /** check for RR duplicates */ static int -rr_is_duplicate(struct packed_rrset_data* pd, ldns_buffer* buf) +rr_is_duplicate(struct packed_rrset_data* pd, uint8_t* rdata, size_t rdata_len) { size_t i; for(i=0; i<pd->count; i++) { - if(ldns_buffer_limit(buf) == pd->rr_len[i] && - memcmp(ldns_buffer_begin(buf), pd->rr_data[i], - ldns_buffer_limit(buf)) == 0) + if(pd->rr_len[i] == rdata_len && + memcmp(pd->rr_data[i], rdata, rdata_len) == 0) return 1; } return 0; @@ -356,7 +335,7 @@ new_local_rrset(struct regional* region, struct local_data* node, /** insert RR into RRset data structure; Wastes a couple of bytes */ static int insert_rr(struct regional* region, struct packed_rrset_data* pd, - ldns_buffer* buf, time_t ttl) + uint8_t* rdata, size_t rdata_len, time_t ttl) { size_t* oldlen = pd->rr_len; time_t* oldttl = pd->rr_ttl; @@ -379,10 +358,9 @@ insert_rr(struct regional* region, struct packed_rrset_data* pd, memcpy(pd->rr_data+1, olddata, sizeof(*pd->rr_data)*(pd->count-1)); } - pd->rr_len[0] = ldns_buffer_limit(buf); + pd->rr_len[0] = rdata_len; pd->rr_ttl[0] = ttl; - pd->rr_data[0] = regional_alloc_init(region, - ldns_buffer_begin(buf), ldns_buffer_limit(buf)); + pd->rr_data[0] = regional_alloc_init(region, rdata, rdata_len); if(!pd->rr_data[0]) { log_err("out of memory"); return 0; @@ -440,8 +418,7 @@ lz_find_create_node(struct local_zone* z, uint8_t* nm, size_t nmlen, /** enter data RR into auth zone */ static int -lz_enter_rr_into_zone(struct local_zone* z, ldns_buffer* buf, - const char* rrstr) +lz_enter_rr_into_zone(struct local_zone* z, const char* rrstr) { uint8_t* nm; size_t nmlen; @@ -451,7 +428,11 @@ lz_enter_rr_into_zone(struct local_zone* z, ldns_buffer* buf, struct packed_rrset_data* pd; uint16_t rrtype = 0, rrclass = 0; time_t ttl = 0; - if(!get_rr_content(rrstr, &nm, &rrtype, &rrclass, &ttl, buf)) { + uint8_t rr[LDNS_RR_BUF_SIZE]; + uint8_t* rdata; + size_t rdata_len; + if(!get_rr_content(rrstr, &nm, &rrtype, &rrclass, &ttl, rr, sizeof(rr), + &rdata, &rdata_len)) { log_err("bad local-data: %s", rrstr); return 0; } @@ -487,16 +468,16 @@ lz_enter_rr_into_zone(struct local_zone* z, ldns_buffer* buf, log_assert(rrset && pd); /* check for duplicate RR */ - if(rr_is_duplicate(pd, buf)) { + if(rr_is_duplicate(pd, rdata, rdata_len)) { verbose(VERB_ALGO, "ignoring duplicate RR: %s", rrstr); return 1; } - return insert_rr(z->region, pd, buf, ttl); + return insert_rr(z->region, pd, rdata, rdata_len, ttl); } /** enter a data RR into auth data; a zone for it must exist */ static int -lz_enter_rr_str(struct local_zones* zones, const char* rr, ldns_buffer* buf) +lz_enter_rr_str(struct local_zones* zones, const char* rr) { uint8_t* rr_name; uint16_t rr_class; @@ -509,16 +490,16 @@ lz_enter_rr_str(struct local_zones* zones, const char* rr, ldns_buffer* buf) return 0; } labs = dname_count_size_labels(rr_name, &len); - lock_quick_lock(&zones->lock); + lock_rw_rdlock(&zones->lock); z = local_zones_lookup(zones, rr_name, len, labs, rr_class); if(!z) { - lock_quick_unlock(&zones->lock); + lock_rw_unlock(&zones->lock); fatal_exit("internal error: no zone for rr %s", rr); } lock_rw_wrlock(&z->lock); - lock_quick_unlock(&zones->lock); + lock_rw_unlock(&zones->lock); free(rr_name); - r = lz_enter_rr_into_zone(z, buf, rr); + r = lz_enter_rr_into_zone(z, rr); lock_rw_unlock(&z->lock); return r; } @@ -549,13 +530,13 @@ lz_exists(struct local_zones* zones, const char* name) log_err("bad name %s", name); return 0; } - lock_quick_lock(&zones->lock); + lock_rw_rdlock(&zones->lock); if(rbtree_search(&zones->ztree, &z.node)) { - lock_quick_unlock(&zones->lock); + lock_rw_unlock(&zones->lock); free(z.name); return 1; } - lock_quick_unlock(&zones->lock); + lock_rw_unlock(&zones->lock); free(z.name); return 0; } @@ -582,7 +563,7 @@ lz_nodefault(struct config_file* cfg, const char* name) /** enter AS112 default zone */ static int add_as112_default(struct local_zones* zones, struct config_file* cfg, - ldns_buffer* buf, const char* name) + const char* name) { struct local_zone* z; char str[1024]; /* known long enough */ @@ -592,12 +573,12 @@ add_as112_default(struct local_zones* zones, struct config_file* cfg, return 0; snprintf(str, sizeof(str), "%s 10800 IN SOA localhost. " "nobody.invalid. 1 3600 1200 604800 10800", name); - if(!lz_enter_rr_into_zone(z, buf, str)) { + if(!lz_enter_rr_into_zone(z, str)) { lock_rw_unlock(&z->lock); return 0; } snprintf(str, sizeof(str), "%s 10800 IN NS localhost. ", name); - if(!lz_enter_rr_into_zone(z, buf, str)) { + if(!lz_enter_rr_into_zone(z, str)) { lock_rw_unlock(&z->lock); return 0; } @@ -607,8 +588,7 @@ add_as112_default(struct local_zones* zones, struct config_file* cfg, /** enter default zones */ static int -lz_enter_defaults(struct local_zones* zones, struct config_file* cfg, - ldns_buffer* buf) +lz_enter_defaults(struct local_zones* zones, struct config_file* cfg) { struct local_zone* z; @@ -619,14 +599,14 @@ lz_enter_defaults(struct local_zones* zones, struct config_file* cfg, !lz_nodefault(cfg, "localhost.")) { if(!(z=lz_enter_zone(zones, "localhost.", "static", LDNS_RR_CLASS_IN)) || - !lz_enter_rr_into_zone(z, buf, + !lz_enter_rr_into_zone(z, "localhost. 10800 IN NS localhost.") || - !lz_enter_rr_into_zone(z, buf, + !lz_enter_rr_into_zone(z, "localhost. 10800 IN SOA localhost. nobody.invalid. " "1 3600 1200 604800 10800") || - !lz_enter_rr_into_zone(z, buf, + !lz_enter_rr_into_zone(z, "localhost. 10800 IN A 127.0.0.1") || - !lz_enter_rr_into_zone(z, buf, + !lz_enter_rr_into_zone(z, "localhost. 10800 IN AAAA ::1")) { log_err("out of memory adding default zone"); if(z) { lock_rw_unlock(&z->lock); } @@ -639,12 +619,12 @@ lz_enter_defaults(struct local_zones* zones, struct config_file* cfg, !lz_nodefault(cfg, "127.in-addr.arpa.")) { if(!(z=lz_enter_zone(zones, "127.in-addr.arpa.", "static", LDNS_RR_CLASS_IN)) || - !lz_enter_rr_into_zone(z, buf, + !lz_enter_rr_into_zone(z, "127.in-addr.arpa. 10800 IN NS localhost.") || - !lz_enter_rr_into_zone(z, buf, + !lz_enter_rr_into_zone(z, "127.in-addr.arpa. 10800 IN SOA localhost. " "nobody.invalid. 1 3600 1200 604800 10800") || - !lz_enter_rr_into_zone(z, buf, + !lz_enter_rr_into_zone(z, "1.0.0.127.in-addr.arpa. 10800 IN PTR localhost.")) { log_err("out of memory adding default zone"); if(z) { lock_rw_unlock(&z->lock); } @@ -657,12 +637,12 @@ lz_enter_defaults(struct local_zones* zones, struct config_file* cfg, !lz_nodefault(cfg, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.")) { if(!(z=lz_enter_zone(zones, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.", "static", LDNS_RR_CLASS_IN)) || - !lz_enter_rr_into_zone(z, buf, + !lz_enter_rr_into_zone(z, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN NS localhost.") || - !lz_enter_rr_into_zone(z, buf, + !lz_enter_rr_into_zone(z, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN SOA localhost. " "nobody.invalid. 1 3600 1200 604800 10800") || - !lz_enter_rr_into_zone(z, buf, + !lz_enter_rr_into_zone(z, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN PTR localhost.")) { log_err("out of memory adding default zone"); if(z) { lock_rw_unlock(&z->lock); } @@ -670,37 +650,37 @@ lz_enter_defaults(struct local_zones* zones, struct config_file* cfg, } lock_rw_unlock(&z->lock); } - if ( !add_as112_default(zones, cfg, buf, "10.in-addr.arpa.") || - !add_as112_default(zones, cfg, buf, "16.172.in-addr.arpa.") || - !add_as112_default(zones, cfg, buf, "17.172.in-addr.arpa.") || - !add_as112_default(zones, cfg, buf, "18.172.in-addr.arpa.") || - !add_as112_default(zones, cfg, buf, "19.172.in-addr.arpa.") || - !add_as112_default(zones, cfg, buf, "20.172.in-addr.arpa.") || - !add_as112_default(zones, cfg, buf, "21.172.in-addr.arpa.") || - !add_as112_default(zones, cfg, buf, "22.172.in-addr.arpa.") || - !add_as112_default(zones, cfg, buf, "23.172.in-addr.arpa.") || - !add_as112_default(zones, cfg, buf, "24.172.in-addr.arpa.") || - !add_as112_default(zones, cfg, buf, "25.172.in-addr.arpa.") || - !add_as112_default(zones, cfg, buf, "26.172.in-addr.arpa.") || - !add_as112_default(zones, cfg, buf, "27.172.in-addr.arpa.") || - !add_as112_default(zones, cfg, buf, "28.172.in-addr.arpa.") || - !add_as112_default(zones, cfg, buf, "29.172.in-addr.arpa.") || - !add_as112_default(zones, cfg, buf, "30.172.in-addr.arpa.") || - !add_as112_default(zones, cfg, buf, "31.172.in-addr.arpa.") || - !add_as112_default(zones, cfg, buf, "168.192.in-addr.arpa.") || - !add_as112_default(zones, cfg, buf, "0.in-addr.arpa.") || - !add_as112_default(zones, cfg, buf, "254.169.in-addr.arpa.") || - !add_as112_default(zones, cfg, buf, "2.0.192.in-addr.arpa.") || - !add_as112_default(zones, cfg, buf, "100.51.198.in-addr.arpa.") || - !add_as112_default(zones, cfg, buf, "113.0.203.in-addr.arpa.") || - !add_as112_default(zones, cfg, buf, "255.255.255.255.in-addr.arpa.") || - !add_as112_default(zones, cfg, buf, "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.") || - !add_as112_default(zones, cfg, buf, "d.f.ip6.arpa.") || - !add_as112_default(zones, cfg, buf, "8.e.f.ip6.arpa.") || - !add_as112_default(zones, cfg, buf, "9.e.f.ip6.arpa.") || - !add_as112_default(zones, cfg, buf, "a.e.f.ip6.arpa.") || - !add_as112_default(zones, cfg, buf, "b.e.f.ip6.arpa.") || - !add_as112_default(zones, cfg, buf, "8.b.d.0.1.0.0.2.ip6.arpa.")) { + if ( !add_as112_default(zones, cfg, "10.in-addr.arpa.") || + !add_as112_default(zones, cfg, "16.172.in-addr.arpa.") || + !add_as112_default(zones, cfg, "17.172.in-addr.arpa.") || + !add_as112_default(zones, cfg, "18.172.in-addr.arpa.") || + !add_as112_default(zones, cfg, "19.172.in-addr.arpa.") || + !add_as112_default(zones, cfg, "20.172.in-addr.arpa.") || + !add_as112_default(zones, cfg, "21.172.in-addr.arpa.") || + !add_as112_default(zones, cfg, "22.172.in-addr.arpa.") || + !add_as112_default(zones, cfg, "23.172.in-addr.arpa.") || + !add_as112_default(zones, cfg, "24.172.in-addr.arpa.") || + !add_as112_default(zones, cfg, "25.172.in-addr.arpa.") || + !add_as112_default(zones, cfg, "26.172.in-addr.arpa.") || + !add_as112_default(zones, cfg, "27.172.in-addr.arpa.") || + !add_as112_default(zones, cfg, "28.172.in-addr.arpa.") || + !add_as112_default(zones, cfg, "29.172.in-addr.arpa.") || + !add_as112_default(zones, cfg, "30.172.in-addr.arpa.") || + !add_as112_default(zones, cfg, "31.172.in-addr.arpa.") || + !add_as112_default(zones, cfg, "168.192.in-addr.arpa.") || + !add_as112_default(zones, cfg, "0.in-addr.arpa.") || + !add_as112_default(zones, cfg, "254.169.in-addr.arpa.") || + !add_as112_default(zones, cfg, "2.0.192.in-addr.arpa.") || + !add_as112_default(zones, cfg, "100.51.198.in-addr.arpa.") || + !add_as112_default(zones, cfg, "113.0.203.in-addr.arpa.") || + !add_as112_default(zones, cfg, "255.255.255.255.in-addr.arpa.") || + !add_as112_default(zones, cfg, "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.") || + !add_as112_default(zones, cfg, "d.f.ip6.arpa.") || + !add_as112_default(zones, cfg, "8.e.f.ip6.arpa.") || + !add_as112_default(zones, cfg, "9.e.f.ip6.arpa.") || + !add_as112_default(zones, cfg, "a.e.f.ip6.arpa.") || + !add_as112_default(zones, cfg, "b.e.f.ip6.arpa.") || + !add_as112_default(zones, cfg, "8.b.d.0.1.0.0.2.ip6.arpa.")) { log_err("out of memory adding default zone"); return 0; } @@ -713,7 +693,7 @@ init_parents(struct local_zones* zones) { struct local_zone* node, *prev = NULL, *p; int m; - lock_quick_lock(&zones->lock); + lock_rw_wrlock(&zones->lock); RBTREE_FOR(node, struct local_zone*, &zones->ztree) { lock_rw_wrlock(&node->lock); node->parent = NULL; @@ -738,7 +718,7 @@ init_parents(struct local_zones* zones) prev = node; lock_rw_unlock(&node->lock); } - lock_quick_unlock(&zones->lock); + lock_rw_unlock(&zones->lock); } /** enter implicit transparent zone for local-data: without local-zone: */ @@ -768,7 +748,7 @@ lz_setup_implicit(struct local_zones* zones, struct config_file* cfg) return 0; } labs = dname_count_size_labels(rr_name, &len); - lock_quick_lock(&zones->lock); + lock_rw_rdlock(&zones->lock); if(!local_zones_lookup(zones, rr_name, len, labs, rr_class)) { if(!have_name) { dclass = rr_class; @@ -783,7 +763,7 @@ lz_setup_implicit(struct local_zones* zones, struct config_file* cfg) /* process other classes later */ free(rr_name); have_other_classes = 1; - lock_quick_unlock(&zones->lock); + lock_rw_unlock(&zones->lock); continue; } /* find smallest shared topdomain */ @@ -794,7 +774,7 @@ lz_setup_implicit(struct local_zones* zones, struct config_file* cfg) match = m; } } else free(rr_name); - lock_quick_unlock(&zones->lock); + lock_rw_unlock(&zones->lock); } if(have_name) { uint8_t* n2; @@ -825,12 +805,11 @@ lz_setup_implicit(struct local_zones* zones, struct config_file* cfg) /** enter auth data */ static int -lz_enter_data(struct local_zones* zones, struct config_file* cfg, - ldns_buffer* buf) +lz_enter_data(struct local_zones* zones, struct config_file* cfg) { struct config_strlist* p; for(p = cfg->local_data; p; p = p->next) { - if(!lz_enter_rr_str(zones, p->str, buf)) + if(!lz_enter_rr_str(zones, p->str)) return 0; } return 1; @@ -851,35 +830,27 @@ lz_freeup_cfg(struct config_file* cfg) int local_zones_apply_cfg(struct local_zones* zones, struct config_file* cfg) { - ldns_buffer* buf = ldns_buffer_new(65535); - if(!buf) fatal_exit("cannot create temporary buffer"); - /* create zones from zone statements. */ if(!lz_enter_zones(zones, cfg)) { - ldns_buffer_free(buf); return 0; } /* apply default zones+content (unless disabled, or overridden) */ - if(!lz_enter_defaults(zones, cfg, buf)) { - ldns_buffer_free(buf); + if(!lz_enter_defaults(zones, cfg)) { return 0; } /* create implicit transparent zone from data. */ if(!lz_setup_implicit(zones, cfg)) { - ldns_buffer_free(buf); return 0; } /* setup parent ptrs for lookup during data entry */ init_parents(zones); /* insert local data */ - if(!lz_enter_data(zones, cfg, buf)) { - ldns_buffer_free(buf); + if(!lz_enter_data(zones, cfg)) { return 0; } /* freeup memory from cfg struct. */ lz_freeup_cfg(cfg); - ldns_buffer_free(buf); return 1; } @@ -948,7 +919,7 @@ local_zone_out(struct local_zone* z) void local_zones_print(struct local_zones* zones) { struct local_zone* z; - lock_quick_lock(&zones->lock); + lock_rw_rdlock(&zones->lock); log_info("number of auth zones %u", (unsigned)zones->ztree.count); RBTREE_FOR(z, struct local_zone*, &zones->ztree) { lock_rw_rdlock(&z->lock); @@ -985,13 +956,13 @@ void local_zones_print(struct local_zones* zones) local_zone_out(z); lock_rw_unlock(&z->lock); } - lock_quick_unlock(&zones->lock); + lock_rw_unlock(&zones->lock); } /** encode answer consisting of 1 rrset */ static int local_encode(struct query_info* qinfo, struct edns_data* edns, - ldns_buffer* buf, struct regional* temp, + sldns_buffer* buf, struct regional* temp, struct ub_packed_rrset_key* rrset, int ansec, int rcode) { struct reply_info rep; @@ -1011,20 +982,20 @@ local_encode(struct query_info* qinfo, struct edns_data* edns, edns->ext_rcode = 0; edns->bits &= EDNS_DO; if(!reply_info_answer_encode(qinfo, &rep, - *(uint16_t*)ldns_buffer_begin(buf), - ldns_buffer_read_u16_at(buf, 2), + *(uint16_t*)sldns_buffer_begin(buf), + sldns_buffer_read_u16_at(buf, 2), buf, 0, 0, temp, udpsize, edns, (int)(edns->bits&EDNS_DO), 0)) error_encode(buf, (LDNS_RCODE_SERVFAIL|BIT_AA), qinfo, - *(uint16_t*)ldns_buffer_begin(buf), - ldns_buffer_read_u16_at(buf, 2), edns); + *(uint16_t*)sldns_buffer_begin(buf), + sldns_buffer_read_u16_at(buf, 2), edns); return 1; } /** answer local data match */ static int local_data_answer(struct local_zone* z, struct query_info* qinfo, - struct edns_data* edns, ldns_buffer* buf, struct regional* temp, + struct edns_data* edns, sldns_buffer* buf, struct regional* temp, int labs, struct local_data** ldp) { struct local_data key; @@ -1071,18 +1042,18 @@ local_data_answer(struct local_zone* z, struct query_info* qinfo, */ static int lz_zone_answer(struct local_zone* z, struct query_info* qinfo, - struct edns_data* edns, ldns_buffer* buf, struct regional* temp, + struct edns_data* edns, sldns_buffer* buf, struct regional* temp, struct local_data* ld) { if(z->type == local_zone_deny) { /** no reply at all, signal caller by clearing buffer. */ - ldns_buffer_clear(buf); - ldns_buffer_flip(buf); + sldns_buffer_clear(buf); + sldns_buffer_flip(buf); return 1; } else if(z->type == local_zone_refuse) { error_encode(buf, (LDNS_RCODE_REFUSED|BIT_AA), qinfo, - *(uint16_t*)ldns_buffer_begin(buf), - ldns_buffer_read_u16_at(buf, 2), edns); + *(uint16_t*)sldns_buffer_begin(buf), + sldns_buffer_read_u16_at(buf, 2), edns); return 1; } else if(z->type == local_zone_static || z->type == local_zone_redirect) { @@ -1098,8 +1069,8 @@ lz_zone_answer(struct local_zone* z, struct query_info* qinfo, return local_encode(qinfo, edns, buf, temp, z->soa, 0, rcode); error_encode(buf, (rcode|BIT_AA), qinfo, - *(uint16_t*)ldns_buffer_begin(buf), - ldns_buffer_read_u16_at(buf, 2), edns); + *(uint16_t*)sldns_buffer_begin(buf), + sldns_buffer_read_u16_at(buf, 2), edns); return 1; } else if(z->type == local_zone_typetransparent) { /* no NODATA or NXDOMAINS for this zone type */ @@ -1115,8 +1086,8 @@ lz_zone_answer(struct local_zone* z, struct query_info* qinfo, return local_encode(qinfo, edns, buf, temp, z->soa, 0, rcode); error_encode(buf, (rcode|BIT_AA), qinfo, - *(uint16_t*)ldns_buffer_begin(buf), - ldns_buffer_read_u16_at(buf, 2), edns); + *(uint16_t*)sldns_buffer_begin(buf), + sldns_buffer_read_u16_at(buf, 2), edns); return 1; } @@ -1126,7 +1097,7 @@ lz_zone_answer(struct local_zone* z, struct query_info* qinfo, int local_zones_answer(struct local_zones* zones, struct query_info* qinfo, - struct edns_data* edns, ldns_buffer* buf, struct regional* temp) + struct edns_data* edns, sldns_buffer* buf, struct regional* temp) { /* see if query is covered by a zone, * if so: - try to match (exact) local data @@ -1135,15 +1106,15 @@ local_zones_answer(struct local_zones* zones, struct query_info* qinfo, struct local_data* ld; struct local_zone* z; int r; - lock_quick_lock(&zones->lock); + lock_rw_rdlock(&zones->lock); z = local_zones_lookup(zones, qinfo->qname, qinfo->qname_len, labs, qinfo->qclass); if(!z) { - lock_quick_unlock(&zones->lock); + lock_rw_unlock(&zones->lock); return 0; } lock_rw_rdlock(&z->lock); - lock_quick_unlock(&zones->lock); + lock_rw_unlock(&zones->lock); if(local_data_answer(z, qinfo, edns, buf, temp, labs, &ld)) { lock_rw_unlock(&z->lock); @@ -1255,7 +1226,7 @@ void local_zones_del_zone(struct local_zones* zones, struct local_zone* z) } int -local_zones_add_RR(struct local_zones* zones, const char* rr, ldns_buffer* buf) +local_zones_add_RR(struct local_zones* zones, const char* rr) { uint8_t* rr_name; uint16_t rr_class; @@ -1267,21 +1238,23 @@ local_zones_add_RR(struct local_zones* zones, const char* rr, ldns_buffer* buf) return 0; } labs = dname_count_size_labels(rr_name, &len); - lock_quick_lock(&zones->lock); + /* could first try readlock then get writelock if zone does not exist, + * but we do not add enough RRs (from multiple threads) to optimize */ + lock_rw_wrlock(&zones->lock); z = local_zones_lookup(zones, rr_name, len, labs, rr_class); if(!z) { z = local_zones_add_zone(zones, rr_name, len, labs, rr_class, local_zone_transparent); if(!z) { - lock_quick_unlock(&zones->lock); + lock_rw_unlock(&zones->lock); return 0; } } else { free(rr_name); } lock_rw_wrlock(&z->lock); - lock_quick_unlock(&zones->lock); - r = lz_enter_rr_into_zone(z, buf, rr); + lock_rw_unlock(&zones->lock); + r = lz_enter_rr_into_zone(z, rr); lock_rw_unlock(&z->lock); return r; } @@ -1326,15 +1299,15 @@ void local_zones_del_data(struct local_zones* zones, /* find zone */ struct local_zone* z; struct local_data* d; - lock_quick_lock(&zones->lock); + lock_rw_rdlock(&zones->lock); z = local_zones_lookup(zones, name, len, labs, dclass); if(!z) { /* no such zone, we're done */ - lock_quick_unlock(&zones->lock); + lock_rw_unlock(&zones->lock); return; } lock_rw_wrlock(&z->lock); - lock_quick_unlock(&zones->lock); + lock_rw_unlock(&zones->lock); /* find the domain */ d = lz_find_node(z, name, len, labs); diff --git a/services/localzone.h b/services/localzone.h index 794988e66bb9..788fbfb3ba2b 100644 --- a/services/localzone.h +++ b/services/localzone.h @@ -21,16 +21,16 @@ * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @@ -48,6 +48,7 @@ struct regional; struct config_file; struct edns_data; struct query_info; +struct sldns_buffer; /** * Local zone type @@ -77,7 +78,7 @@ enum localzone_type { */ struct local_zones { /** lock on the localzone tree */ - lock_quick_t lock; + lock_rw_t lock; /** rbtree of struct local_zone */ rbtree_t ztree; }; @@ -224,7 +225,7 @@ void local_zones_print(struct local_zones* zones); * value is true, but the buffer is cleared (empty). */ int local_zones_answer(struct local_zones* zones, struct query_info* qinfo, - struct edns_data* edns, ldns_buffer* buf, struct regional* temp); + struct edns_data* edns, struct sldns_buffer* buf, struct regional* temp); /** * Parse the string into localzone type. @@ -286,11 +287,9 @@ void local_zones_del_zone(struct local_zones* zones, struct local_zone* zone); * name of the RR is created. * @param zones: the zones tree. Not locked by caller. * @param rr: string with on RR. - * @param buf: buffer for scratch. * @return false on failure. */ -int local_zones_add_RR(struct local_zones* zones, const char* rr, - ldns_buffer* buf); +int local_zones_add_RR(struct local_zones* zones, const char* rr); /** * Remove data from domain name in the tree. diff --git a/services/mesh.c b/services/mesh.c index a8cb115ab935..bc711d9b3ed6 100644 --- a/services/mesh.c +++ b/services/mesh.c @@ -21,16 +21,16 @@ * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @@ -43,7 +43,6 @@ * send back to clients. */ #include "config.h" -#include <ldns/wire2host.h> #include "services/mesh.h" #include "services/outbound_list.h" #include "services/cache/dns.h" @@ -56,6 +55,7 @@ #include "util/fptr_wlist.h" #include "util/alloc.h" #include "util/config_file.h" +#include "ldns/sbuffer.h" /** subtract timers and the values do not overflow or become negative */ static void @@ -162,7 +162,7 @@ mesh_create(struct module_stack* stack, struct module_env* env) return NULL; } mesh->histogram = timehist_setup(); - mesh->qbuf_bak = ldns_buffer_new(env->cfg->msg_buffer_size); + mesh->qbuf_bak = sldns_buffer_new(env->cfg->msg_buffer_size); if(!mesh->histogram || !mesh->qbuf_bak) { free(mesh); log_err("mesh area alloc: out of memory"); @@ -210,7 +210,7 @@ mesh_delete(struct mesh_area* mesh) while(mesh->all.count) mesh_delete_helper(mesh->all.root); timehist_delete(mesh->histogram); - ldns_buffer_free(mesh->qbuf_bak); + sldns_buffer_free(mesh->qbuf_bak); free(mesh); } @@ -234,7 +234,7 @@ mesh_delete_all(struct mesh_area* mesh) mesh->jostle_last = NULL; } -int mesh_make_new_space(struct mesh_area* mesh, ldns_buffer* qbuf) +int mesh_make_new_space(struct mesh_area* mesh, sldns_buffer* qbuf) { struct mesh_state* m = mesh->jostle_first; /* free space is available */ @@ -253,7 +253,7 @@ int mesh_make_new_space(struct mesh_area* mesh, ldns_buffer* qbuf) m->s.qinfo.qname, m->s.qinfo.qtype, m->s.qinfo.qclass); /* backup the query */ - if(qbuf) ldns_buffer_copy(mesh->qbuf_bak, qbuf); + if(qbuf) sldns_buffer_copy(mesh->qbuf_bak, qbuf); /* notify supers */ if(m->super_set.count > 0) { verbose(VERB_ALGO, "notify supers of failure"); @@ -265,7 +265,7 @@ int mesh_make_new_space(struct mesh_area* mesh, ldns_buffer* qbuf) mesh_state_delete(&m->s); /* restore the query - note that the qinfo ptr to * the querybuffer is then correct again. */ - if(qbuf) ldns_buffer_copy(qbuf, mesh->qbuf_bak); + if(qbuf) sldns_buffer_copy(qbuf, mesh->qbuf_bak); return 1; } } @@ -372,7 +372,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo, int mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo, - uint16_t qflags, struct edns_data* edns, ldns_buffer* buf, + uint16_t qflags, struct edns_data* edns, sldns_buffer* buf, uint16_t qid, mesh_cb_func_t cb, void* cb_arg) { struct mesh_state* s = mesh_area_find(mesh, qinfo, qflags&BIT_RD, 0); @@ -800,7 +800,7 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep, (*r->cb)(r->cb_arg, rcode, r->buf, sec_status_unchecked, NULL); } else { size_t udp_size = r->edns.udp_size; - ldns_buffer_clear(r->buf); + sldns_buffer_clear(r->buf); r->edns.edns_version = EDNS_ADVERTISED_VERSION; r->edns.udp_size = EDNS_ADVERTISED_SIZE; r->edns.ext_rcode = 0; @@ -858,11 +858,11 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep, prev->edns.udp_size == r->edns.udp_size) { /* if the previous reply is identical to this one, fix ID */ if(prev->query_reply.c->buffer != r->query_reply.c->buffer) - ldns_buffer_copy(r->query_reply.c->buffer, + sldns_buffer_copy(r->query_reply.c->buffer, prev->query_reply.c->buffer); - ldns_buffer_write_at(r->query_reply.c->buffer, 0, + sldns_buffer_write_at(r->query_reply.c->buffer, 0, &r->qid, sizeof(uint16_t)); - ldns_buffer_write_at(r->query_reply.c->buffer, 12, + sldns_buffer_write_at(r->query_reply.c->buffer, 12, r->qname, m->s.qinfo.qname_len); comm_point_send_reply(&r->query_reply); } else if(rcode) { @@ -892,17 +892,17 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep, m->s.env->mesh->num_reply_addrs--; end_time = *m->s.env->now_tv; timeval_subtract(&duration, &end_time, &r->start_time); - verbose(VERB_ALGO, "query took %lld.%6.6d sec", + verbose(VERB_ALGO, "query took " ARG_LL "d.%6.6d sec", (long long)duration.tv_sec, (int)duration.tv_usec); m->s.env->mesh->replies_sent++; timeval_add(&m->s.env->mesh->replies_sum_wait, &duration); timehist_insert(m->s.env->mesh->histogram, &duration); if(m->s.env->cfg->stat_extended) { - uint16_t rc = FLAGS_GET_RCODE(ldns_buffer_read_u16_at(r-> + uint16_t rc = FLAGS_GET_RCODE(sldns_buffer_read_u16_at(r-> query_reply.c->buffer, 2)); if(secure) m->s.env->mesh->ans_secure++; m->s.env->mesh->ans_rcode[ rc ] ++; - if(rc == 0 && LDNS_ANCOUNT(ldns_buffer_begin(r-> + if(rc == 0 && LDNS_ANCOUNT(sldns_buffer_begin(r-> query_reply.c->buffer)) == 0) m->s.env->mesh->ans_nodata++; } @@ -956,7 +956,7 @@ struct mesh_state* mesh_area_find(struct mesh_area* mesh, } int mesh_state_add_cb(struct mesh_state* s, struct edns_data* edns, - ldns_buffer* buf, mesh_cb_func_t cb, void* cb_arg, + sldns_buffer* buf, mesh_cb_func_t cb, void* cb_arg, uint16_t qid, uint16_t qflags) { struct mesh_cb* r = regional_alloc(s->s.region, @@ -1138,7 +1138,8 @@ mesh_stats(struct mesh_area* mesh, const char* str) timeval_divide(&avg, &mesh->replies_sum_wait, mesh->replies_sent); log_info("average recursion processing time " - "%lld.%6.6d sec", (long long)avg.tv_sec, (int)avg.tv_usec); + ARG_LL "d.%6.6d sec", + (long long)avg.tv_sec, (int)avg.tv_usec); log_info("histogram of recursion processing times"); timehist_log(mesh->histogram, "recursions"); } @@ -1167,7 +1168,7 @@ mesh_get_mem(struct mesh_area* mesh) struct mesh_state* m; size_t s = sizeof(*mesh) + sizeof(struct timehist) + sizeof(struct th_buck)*mesh->histogram->num + - sizeof(ldns_buffer) + ldns_buffer_capacity(mesh->qbuf_bak); + sizeof(sldns_buffer) + sldns_buffer_capacity(mesh->qbuf_bak); RBTREE_FOR(m, struct mesh_state*, &mesh->all) { /* all, including m itself allocated in qstate region */ s += regional_get_mem(m->s.region); diff --git a/services/mesh.h b/services/mesh.h index 54a3cafecc9e..fbfbbcb4a94b 100644 --- a/services/mesh.h +++ b/services/mesh.h @@ -21,16 +21,16 @@ * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @@ -51,6 +51,7 @@ #include "util/data/msgparse.h" #include "util/module.h" #include "services/modstack.h" +struct sldns_buffer; struct mesh_state; struct mesh_reply; struct mesh_cb; @@ -125,7 +126,7 @@ struct mesh_area { /** backup of query if other operations recurse and need the * network buffers */ - ldns_buffer* qbuf_bak; + struct sldns_buffer* qbuf_bak; /** double linked list of the run-to-completion query states. * These are query states with a reply */ @@ -219,7 +220,7 @@ struct mesh_reply { * Mesh result callback func. * called as func(cb_arg, rcode, buffer_with_reply, security, why_bogus); */ -typedef void (*mesh_cb_func_t)(void*, int, ldns_buffer*, enum sec_status, +typedef void (*mesh_cb_func_t)(void*, int, struct sldns_buffer*, enum sec_status, char*); /** @@ -235,7 +236,7 @@ struct mesh_cb { /** flags of query, for reply flags */ uint16_t qflags; /** buffer for reply */ - ldns_buffer* buf; + struct sldns_buffer* buf; /** callback routine for results. if rcode != 0 buf has message. * called as cb(cb_arg, rcode, buf, sec_state); @@ -294,7 +295,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo, * @return 0 on error. */ int mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo, - uint16_t qflags, struct edns_data* edns, ldns_buffer* buf, + uint16_t qflags, struct edns_data* edns, struct sldns_buffer* buf, uint16_t qid, mesh_cb_func_t cb, void* cb_arg); /** @@ -473,7 +474,7 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns, * @return: 0 on alloc error. */ int mesh_state_add_cb(struct mesh_state* s, struct edns_data* edns, - ldns_buffer* buf, mesh_cb_func_t cb, void* cb_arg, uint16_t qid, + struct sldns_buffer* buf, mesh_cb_func_t cb, void* cb_arg, uint16_t qid, uint16_t qflags); /** @@ -548,7 +549,7 @@ int mesh_state_ref_compare(const void* ap, const void* bp); * You can pass NULL if there is no buffer that must be backed up. * @return false if no space is available. */ -int mesh_make_new_space(struct mesh_area* mesh, ldns_buffer* qbuf); +int mesh_make_new_space(struct mesh_area* mesh, struct sldns_buffer* qbuf); /** * Insert mesh state into a double linked list. Inserted at end. diff --git a/services/modstack.c b/services/modstack.c index 7395598c31cd..56515a61f369 100644 --- a/services/modstack.c +++ b/services/modstack.c @@ -21,16 +21,16 @@ * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** diff --git a/services/modstack.h b/services/modstack.h index 869b593ad264..cb8613299abb 100644 --- a/services/modstack.h +++ b/services/modstack.h @@ -21,16 +21,16 @@ * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** diff --git a/services/outbound_list.c b/services/outbound_list.c index be491490411d..ad73380bcf81 100644 --- a/services/outbound_list.c +++ b/services/outbound_list.c @@ -21,16 +21,16 @@ * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** diff --git a/services/outbound_list.h b/services/outbound_list.h index 5631910f6f8c..ad59e42d1929 100644 --- a/services/outbound_list.h +++ b/services/outbound_list.h @@ -21,16 +21,16 @@ * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** diff --git a/services/outside_network.c b/services/outside_network.c index 373d8f353688..fedbd0fa8c8e 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -21,16 +21,16 @@ * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @@ -45,7 +45,6 @@ # include <sys/types.h> #endif #include <sys/time.h> -#include <ldns/wire2host.h> #include "services/outside_network.h" #include "services/listen_dnsport.h" #include "services/cache/infra.h" @@ -58,6 +57,7 @@ #include "util/net_help.h" #include "util/random.h" #include "util/fptr_wlist.h" +#include "ldns/sbuffer.h" #ifdef HAVE_OPENSSL_SSL_H #include <openssl/ssl.h> #endif @@ -76,10 +76,10 @@ /** initiate TCP transaction for serviced query */ static void serviced_tcp_initiate(struct outside_network* outnet, - struct serviced_query* sq, ldns_buffer* buff); + struct serviced_query* sq, sldns_buffer* buff); /** with a fd available, randomize and send UDP */ static int randomize_and_send_udp(struct outside_network* outnet, - struct pending* pend, ldns_buffer* packet, int timeout); + struct pending* pend, sldns_buffer* packet, int timeout); int pending_cmp(const void* key1, const void* key2) @@ -263,9 +263,9 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len) pend->query = w; pend->c->repinfo.addrlen = w->addrlen; memcpy(&pend->c->repinfo.addr, &w->addr, w->addrlen); - ldns_buffer_clear(pend->c->buffer); - ldns_buffer_write(pend->c->buffer, pkt, pkt_len); - ldns_buffer_flip(pend->c->buffer); + sldns_buffer_clear(pend->c->buffer); + sldns_buffer_write(pend->c->buffer, pkt, pkt_len); + sldns_buffer_flip(pend->c->buffer); pend->c->tcp_is_reading = 0; pend->c->tcp_byte_count = 0; comm_point_start_listening(pend->c, s, -1); @@ -325,8 +325,8 @@ outnet_tcp_cb(struct comm_point* c, void* arg, int error, /* pass error below and exit */ } else { /* check ID */ - if(ldns_buffer_limit(c->buffer) < sizeof(uint16_t) || - LDNS_ID_WIRE(ldns_buffer_begin(c->buffer))!=pend->id) { + if(sldns_buffer_limit(c->buffer) < sizeof(uint16_t) || + LDNS_ID_WIRE(sldns_buffer_begin(c->buffer))!=pend->id) { log_addr(VERB_QUERY, "outnettcp: bad ID in reply, from:", &pend->query->addr, pend->query->addrlen); @@ -372,18 +372,20 @@ outnet_send_wait_udp(struct outside_network* outnet) pend = outnet->udp_wait_first; outnet->udp_wait_first = pend->next_waiting; if(!pend->next_waiting) outnet->udp_wait_last = NULL; - ldns_buffer_clear(outnet->udp_buff); - ldns_buffer_write(outnet->udp_buff, pend->pkt, pend->pkt_len); - ldns_buffer_flip(outnet->udp_buff); + sldns_buffer_clear(outnet->udp_buff); + sldns_buffer_write(outnet->udp_buff, pend->pkt, pend->pkt_len); + sldns_buffer_flip(outnet->udp_buff); free(pend->pkt); /* freeing now makes get_mem correct */ pend->pkt = NULL; pend->pkt_len = 0; if(!randomize_and_send_udp(outnet, pend, outnet->udp_buff, pend->timeout)) { /* callback error on pending */ - fptr_ok(fptr_whitelist_pending_udp(pend->cb)); - (void)(*pend->cb)(outnet->unused_fds->cp, pend->cb_arg, - NETEVENT_CLOSED, NULL); + if(pend->cb) { + fptr_ok(fptr_whitelist_pending_udp(pend->cb)); + (void)(*pend->cb)(outnet->unused_fds->cp, pend->cb_arg, + NETEVENT_CLOSED, NULL); + } pending_delete(outnet, pend); } } @@ -402,14 +404,14 @@ outnet_udp_cb(struct comm_point* c, void* arg, int error, verbose(VERB_QUERY, "outnetudp got udp error %d", error); return 0; } - if(ldns_buffer_limit(c->buffer) < LDNS_HEADER_SIZE) { + if(sldns_buffer_limit(c->buffer) < LDNS_HEADER_SIZE) { verbose(VERB_QUERY, "outnetudp udp too short"); return 0; } log_assert(reply_info); /* setup lookup key */ - key.id = (unsigned)LDNS_ID_WIRE(ldns_buffer_begin(c->buffer)); + key.id = (unsigned)LDNS_ID_WIRE(sldns_buffer_begin(c->buffer)); memcpy(&key.addr, &reply_info->addr, reply_info->addrlen); key.addrlen = reply_info->addrlen; verbose(VERB_ALGO, "Incoming reply id = %4.4x", key.id); @@ -460,8 +462,10 @@ outnet_udp_cb(struct comm_point* c, void* arg, int error, verbose(VERB_ALGO, "outnet handle udp reply"); /* delete from tree first in case callback creates a retry */ (void)rbtree_delete(outnet->pending, p->node.key); - fptr_ok(fptr_whitelist_pending_udp(p->cb)); - (void)(*p->cb)(p->pc->cp, p->cb_arg, NETEVENT_NOERROR, reply_info); + if(p->cb) { + fptr_ok(fptr_whitelist_pending_udp(p->cb)); + (void)(*p->cb)(p->pc->cp, p->cb_arg, NETEVENT_NOERROR, reply_info); + } portcomm_loweruse(outnet, p->pc); pending_delete(NULL, p); outnet_send_wait_udp(outnet); @@ -496,6 +500,17 @@ calc_num46(char** ifs, int num_ifs, int do_ip4, int do_ip6, } +void +pending_udp_timer_delay_cb(void* arg) +{ + struct pending* p = (struct pending*)arg; + struct outside_network* outnet = p->outnet; + verbose(VERB_ALGO, "timeout udp with delay"); + portcomm_loweruse(outnet, p->pc); + pending_delete(outnet, p); + outnet_send_wait_udp(outnet); +} + void pending_udp_timer_cb(void *arg) { @@ -503,8 +518,20 @@ pending_udp_timer_cb(void *arg) struct outside_network* outnet = p->outnet; /* it timed out */ verbose(VERB_ALGO, "timeout udp"); - fptr_ok(fptr_whitelist_pending_udp(p->cb)); - (void)(*p->cb)(p->pc->cp, p->cb_arg, NETEVENT_TIMEOUT, NULL); + if(p->cb) { + fptr_ok(fptr_whitelist_pending_udp(p->cb)); + (void)(*p->cb)(p->pc->cp, p->cb_arg, NETEVENT_TIMEOUT, NULL); + } + /* if delayclose, keep port open for a longer time. + * But if the udpwaitlist exists, then we are struggling to + * keep up with demand for sockets, so do not wait, but service + * the customer (customer service more important than portICMPs) */ + if(outnet->delayclose && !outnet->udp_wait_first) { + p->cb = NULL; + p->timer->callback = &pending_udp_timer_delay_cb; + comm_timer_set(p->timer, &outnet->delay_tv); + return; + } portcomm_loweruse(outnet, p->pc); pending_delete(outnet, p); outnet_send_wait_udp(outnet); @@ -561,7 +588,7 @@ outside_network_create(struct comm_base *base, size_t bufsize, struct ub_randstate* rnd, int use_caps_for_id, int* availports, int numavailports, size_t unwanted_threshold, void (*unwanted_action)(void*), void* unwanted_param, int do_udp, - void* sslctx) + void* sslctx, int delayclose) { struct outside_network* outnet = (struct outside_network*) calloc(1, sizeof(struct outside_network)); @@ -583,6 +610,13 @@ outside_network_create(struct comm_base *base, size_t bufsize, outnet->unwanted_param = unwanted_param; outnet->use_caps_for_id = use_caps_for_id; outnet->do_udp = do_udp; +#ifndef S_SPLINT_S + if(delayclose) { + outnet->delayclose = 1; + outnet->delay_tv.tv_sec = delayclose/1000; + outnet->delay_tv.tv_usec = (delayclose%1000)*1000; + } +#endif if(numavailports == 0) { log_err("no outgoing ports available"); outside_network_delete(outnet); @@ -609,7 +643,7 @@ outside_network_create(struct comm_base *base, size_t bufsize, return NULL; } } - if( !(outnet->udp_buff = ldns_buffer_new(bufsize)) || + if( !(outnet->udp_buff = sldns_buffer_new(bufsize)) || !(outnet->pending = rbtree_create(pending_cmp)) || !(outnet->serviced = rbtree_create(serviced_cmp)) || !create_pending_tcp(outnet, bufsize)) { @@ -731,7 +765,7 @@ outside_network_delete(struct outside_network* outnet) free(outnet->serviced); } if(outnet->udp_buff) - ldns_buffer_free(outnet->udp_buff); + sldns_buffer_free(outnet->udp_buff); if(outnet->unused_fds) { struct port_comm* p = outnet->unused_fds, *np; while(p) { @@ -849,13 +883,13 @@ udp_sockport(struct sockaddr_storage* addr, socklen_t addrlen, int port, sa->sin6_port = (in_port_t)htons((uint16_t)port); fd = create_udp_sock(AF_INET6, SOCK_DGRAM, (struct sockaddr*)addr, addrlen, 1, inuse, &noproto, - 0, 0); + 0, 0, 0, NULL); } else { struct sockaddr_in* sa = (struct sockaddr_in*)addr; sa->sin_port = (in_port_t)htons((uint16_t)port); fd = create_udp_sock(AF_INET, SOCK_DGRAM, (struct sockaddr*)addr, addrlen, 1, inuse, &noproto, - 0, 0); + 0, 0, 0, NULL); } return fd; } @@ -863,18 +897,18 @@ udp_sockport(struct sockaddr_storage* addr, socklen_t addrlen, int port, /** Select random ID */ static int select_id(struct outside_network* outnet, struct pending* pend, - ldns_buffer* packet) + sldns_buffer* packet) { int id_tries = 0; pend->id = ((unsigned)ub_random(outnet->rnd)>>8) & 0xffff; - LDNS_ID_SET(ldns_buffer_begin(packet), pend->id); + LDNS_ID_SET(sldns_buffer_begin(packet), pend->id); /* insert in tree */ pend->node.key = pend; while(!rbtree_insert(outnet->pending, &pend->node)) { /* change ID to avoid collision */ pend->id = ((unsigned)ub_random(outnet->rnd)>>8) & 0xffff; - LDNS_ID_SET(ldns_buffer_begin(packet), pend->id); + LDNS_ID_SET(sldns_buffer_begin(packet), pend->id); id_tries++; if(id_tries == MAX_ID_RETRY) { pend->id=99999; /* non existant ID */ @@ -958,7 +992,7 @@ select_ifport(struct outside_network* outnet, struct pending* pend, static int randomize_and_send_udp(struct outside_network* outnet, struct pending* pend, - ldns_buffer* packet, int timeout) + sldns_buffer* packet, int timeout) { struct timeval tv; @@ -997,7 +1031,7 @@ randomize_and_send_udp(struct outside_network* outnet, struct pending* pend, } struct pending* -pending_udp_query(struct outside_network* outnet, ldns_buffer* packet, +pending_udp_query(struct outside_network* outnet, sldns_buffer* packet, struct sockaddr_storage* addr, socklen_t addrlen, int timeout, comm_point_callback_t* cb, void* cb_arg) { @@ -1020,8 +1054,8 @@ pending_udp_query(struct outside_network* outnet, ldns_buffer* packet, /* no unused fd, cannot create a new port (randomly) */ verbose(VERB_ALGO, "no fds available, udp query waiting"); pend->timeout = timeout; - pend->pkt_len = ldns_buffer_limit(packet); - pend->pkt = (uint8_t*)memdup(ldns_buffer_begin(packet), + pend->pkt_len = sldns_buffer_limit(packet); + pend->pkt = (uint8_t*)memdup(sldns_buffer_begin(packet), pend->pkt_len); if(!pend->pkt) { comm_timer_delete(pend->timer); @@ -1080,7 +1114,7 @@ outnet_tcptimer(void* arg) } struct waiting_tcp* -pending_tcp_query(struct outside_network* outnet, ldns_buffer* packet, +pending_tcp_query(struct outside_network* outnet, sldns_buffer* packet, struct sockaddr_storage* addr, socklen_t addrlen, int timeout, comm_point_callback_t* callback, void* callback_arg, int ssl_upstream) { @@ -1090,7 +1124,7 @@ pending_tcp_query(struct outside_network* outnet, ldns_buffer* packet, uint16_t id; /* if no buffer is free allocate space to store query */ w = (struct waiting_tcp*)malloc(sizeof(struct waiting_tcp) - + (pend?0:ldns_buffer_limit(packet))); + + (pend?0:sldns_buffer_limit(packet))); if(!w) { return NULL; } @@ -1101,7 +1135,7 @@ pending_tcp_query(struct outside_network* outnet, ldns_buffer* packet, w->pkt = NULL; w->pkt_len = 0; id = ((unsigned)ub_random(outnet->rnd)>>8) & 0xffff; - LDNS_ID_SET(ldns_buffer_begin(packet), id); + LDNS_ID_SET(sldns_buffer_begin(packet), id); memcpy(&w->addr, addr, addrlen); w->addrlen = addrlen; w->outnet = outnet; @@ -1115,16 +1149,16 @@ pending_tcp_query(struct outside_network* outnet, ldns_buffer* packet, comm_timer_set(w->timer, &tv); if(pend) { /* we have a buffer available right now */ - if(!outnet_tcp_take_into_use(w, ldns_buffer_begin(packet), - ldns_buffer_limit(packet))) { + if(!outnet_tcp_take_into_use(w, sldns_buffer_begin(packet), + sldns_buffer_limit(packet))) { waiting_tcp_delete(w); return NULL; } } else { /* queue up */ w->pkt = (uint8_t*)w + sizeof(struct waiting_tcp); - w->pkt_len = ldns_buffer_limit(packet); - memmove(w->pkt, ldns_buffer_begin(packet), w->pkt_len); + w->pkt_len = sldns_buffer_limit(packet); + memmove(w->pkt, sldns_buffer_begin(packet), w->pkt_len); w->next_waiting = NULL; if(outnet->tcp_wait_last) outnet->tcp_wait_last->next_waiting = w; @@ -1136,31 +1170,31 @@ pending_tcp_query(struct outside_network* outnet, ldns_buffer* packet, /** create query for serviced queries */ static void -serviced_gen_query(ldns_buffer* buff, uint8_t* qname, size_t qnamelen, +serviced_gen_query(sldns_buffer* buff, uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass, uint16_t flags) { - ldns_buffer_clear(buff); + sldns_buffer_clear(buff); /* skip id */ - ldns_buffer_write_u16(buff, flags); - ldns_buffer_write_u16(buff, 1); /* qdcount */ - ldns_buffer_write_u16(buff, 0); /* ancount */ - ldns_buffer_write_u16(buff, 0); /* nscount */ - ldns_buffer_write_u16(buff, 0); /* arcount */ - ldns_buffer_write(buff, qname, qnamelen); - ldns_buffer_write_u16(buff, qtype); - ldns_buffer_write_u16(buff, qclass); - ldns_buffer_flip(buff); + sldns_buffer_write_u16(buff, flags); + sldns_buffer_write_u16(buff, 1); /* qdcount */ + sldns_buffer_write_u16(buff, 0); /* ancount */ + sldns_buffer_write_u16(buff, 0); /* nscount */ + sldns_buffer_write_u16(buff, 0); /* arcount */ + sldns_buffer_write(buff, qname, qnamelen); + sldns_buffer_write_u16(buff, qtype); + sldns_buffer_write_u16(buff, qclass); + sldns_buffer_flip(buff); } /** lookup serviced query in serviced query rbtree */ static struct serviced_query* -lookup_serviced(struct outside_network* outnet, ldns_buffer* buff, int dnssec, +lookup_serviced(struct outside_network* outnet, sldns_buffer* buff, int dnssec, struct sockaddr_storage* addr, socklen_t addrlen) { struct serviced_query key; key.node.key = &key; - key.qbuf = ldns_buffer_begin(buff); - key.qbuflen = ldns_buffer_limit(buff); + key.qbuf = sldns_buffer_begin(buff); + key.qbuflen = sldns_buffer_limit(buff); key.dnssec = dnssec; memcpy(&key.addr, addr, addrlen); key.addrlen = addrlen; @@ -1170,7 +1204,7 @@ lookup_serviced(struct outside_network* outnet, ldns_buffer* buff, int dnssec, /** Create new serviced entry */ static struct serviced_query* -serviced_create(struct outside_network* outnet, ldns_buffer* buff, int dnssec, +serviced_create(struct outside_network* outnet, sldns_buffer* buff, int dnssec, int want_dnssec, int tcp_upstream, int ssl_upstream, struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, size_t zonelen, int qtype) @@ -1182,12 +1216,12 @@ serviced_create(struct outside_network* outnet, ldns_buffer* buff, int dnssec, if(!sq) return NULL; sq->node.key = sq; - sq->qbuf = memdup(ldns_buffer_begin(buff), ldns_buffer_limit(buff)); + sq->qbuf = memdup(sldns_buffer_begin(buff), sldns_buffer_limit(buff)); if(!sq->qbuf) { free(sq); return NULL; } - sq->qbuflen = ldns_buffer_limit(buff); + sq->qbuflen = sldns_buffer_limit(buff); sq->zone = memdup(zone, zonelen); if(!sq->zone) { free(sq->qbuf); @@ -1312,17 +1346,17 @@ serviced_perturb_qname(struct ub_randstate* rnd, uint8_t* qbuf, size_t len) /** put serviced query into a buffer */ static void -serviced_encode(struct serviced_query* sq, ldns_buffer* buff, int with_edns) +serviced_encode(struct serviced_query* sq, sldns_buffer* buff, int with_edns) { /* if we are using 0x20 bits for ID randomness, perturb them */ if(sq->outnet->use_caps_for_id) { serviced_perturb_qname(sq->outnet->rnd, sq->qbuf, sq->qbuflen); } /* generate query */ - ldns_buffer_clear(buff); - ldns_buffer_write_u16(buff, 0); /* id placeholder */ - ldns_buffer_write(buff, sq->qbuf, sq->qbuflen); - ldns_buffer_flip(buff); + sldns_buffer_clear(buff); + sldns_buffer_write_u16(buff, 0); /* id placeholder */ + sldns_buffer_write(buff, sq->qbuf, sq->qbuflen); + sldns_buffer_flip(buff); if(with_edns) { /* add edns section */ struct edns_data edns; @@ -1346,7 +1380,7 @@ serviced_encode(struct serviced_query* sq, ldns_buffer* buff, int with_edns) if(sq->dnssec & EDNS_DO) edns.bits = EDNS_DO; if(sq->dnssec & BIT_CD) - LDNS_CD_SET(ldns_buffer_begin(buff)); + LDNS_CD_SET(sldns_buffer_begin(buff)); attach_edns_record(buff, &edns); } } @@ -1359,7 +1393,7 @@ serviced_encode(struct serviced_query* sq, ldns_buffer* buff, int with_edns) * @return 0 on error. */ static int -serviced_udp_send(struct serviced_query* sq, ldns_buffer* buff) +serviced_udp_send(struct serviced_query* sq, sldns_buffer* buff) { int rtt, vs; uint8_t edns_lame_known; @@ -1399,21 +1433,21 @@ serviced_udp_send(struct serviced_query* sq, ldns_buffer* buff) /** check that perturbed qname is identical */ static int -serviced_check_qname(ldns_buffer* pkt, uint8_t* qbuf, size_t qbuflen) +serviced_check_qname(sldns_buffer* pkt, uint8_t* qbuf, size_t qbuflen) { - uint8_t* d1 = ldns_buffer_at(pkt, 12); + uint8_t* d1 = sldns_buffer_at(pkt, 12); uint8_t* d2 = qbuf+10; uint8_t len1, len2; int count = 0; log_assert(qbuflen >= 15 /* 10 header, root, type, class */); len1 = *d1++; len2 = *d2++; - if(ldns_buffer_limit(pkt) < 12+1+4) /* packet too small for qname */ + if(sldns_buffer_limit(pkt) < 12+1+4) /* packet too small for qname */ return 0; while(len1 != 0 || len2 != 0) { if(LABEL_IS_PTR(len1)) { - d1 = ldns_buffer_at(pkt, PTR_OFFSET(len1, *d1)); - if(d1 >= ldns_buffer_at(pkt, ldns_buffer_limit(pkt))) + d1 = sldns_buffer_at(pkt, PTR_OFFSET(len1, *d1)); + if(d1 >= sldns_buffer_at(pkt, sldns_buffer_limit(pkt))) return 0; len1 = *d1++; if(count++ > MAX_COMPRESS_PTRS) @@ -1463,10 +1497,10 @@ serviced_callbacks(struct serviced_query* sq, int error, struct comm_point* c, verbose(VERB_ALGO, "svcd callbacks start"); if(sq->outnet->use_caps_for_id && error == NETEVENT_NOERROR && c) { /* noerror and nxdomain must have a qname in reply */ - if(ldns_buffer_read_u16_at(c->buffer, 4) == 0 && - (LDNS_RCODE_WIRE(ldns_buffer_begin(c->buffer)) + if(sldns_buffer_read_u16_at(c->buffer, 4) == 0 && + (LDNS_RCODE_WIRE(sldns_buffer_begin(c->buffer)) == LDNS_RCODE_NOERROR || - LDNS_RCODE_WIRE(ldns_buffer_begin(c->buffer)) + LDNS_RCODE_WIRE(sldns_buffer_begin(c->buffer)) == LDNS_RCODE_NXDOMAIN)) { verbose(VERB_DETAIL, "no qname in reply to check 0x20ID"); log_addr(VERB_DETAIL, "from server", @@ -1474,7 +1508,7 @@ serviced_callbacks(struct serviced_query* sq, int error, struct comm_point* c, log_buf(VERB_DETAIL, "for packet", c->buffer); error = NETEVENT_CLOSED; c = NULL; - } else if(ldns_buffer_read_u16_at(c->buffer, 4) > 0 && + } else if(sldns_buffer_read_u16_at(c->buffer, 4) > 0 && !serviced_check_qname(c->buffer, sq->qbuf, sq->qbuflen)) { verbose(VERB_DETAIL, "wrong 0x20-ID in reply qname"); @@ -1484,12 +1518,12 @@ serviced_callbacks(struct serviced_query* sq, int error, struct comm_point* c, error = NETEVENT_CAPSFAIL; /* and cleanup too */ pkt_dname_tolower(c->buffer, - ldns_buffer_at(c->buffer, 12)); + sldns_buffer_at(c->buffer, 12)); } else { verbose(VERB_ALGO, "good 0x20-ID in reply qname"); /* cleanup caps, prettier cache contents. */ pkt_dname_tolower(c->buffer, - ldns_buffer_at(c->buffer, 12)); + sldns_buffer_at(c->buffer, 12)); } } if(dobackup && c) { @@ -1497,8 +1531,8 @@ serviced_callbacks(struct serviced_query* sq, int error, struct comm_point* c, * may send outgoing queries that overwrite the buffer. * use secondary buffer to store the query. * This is a data copy, but faster than packet to server */ - backlen = ldns_buffer_limit(c->buffer); - backup_p = memdup(ldns_buffer_begin(c->buffer), backlen); + backlen = sldns_buffer_limit(c->buffer); + backup_p = memdup(sldns_buffer_begin(c->buffer), backlen); if(!backup_p) { log_err("malloc failure in serviced query callbacks"); error = NETEVENT_CLOSED; @@ -1510,9 +1544,9 @@ serviced_callbacks(struct serviced_query* sq, int error, struct comm_point* c, while((p=sq->cblist) != NULL) { sq->cblist = p->next; /* remove this element */ if(dobackup && c) { - ldns_buffer_clear(c->buffer); - ldns_buffer_write(c->buffer, backup_p, backlen); - ldns_buffer_flip(c->buffer); + sldns_buffer_clear(c->buffer); + sldns_buffer_write(c->buffer, backup_p, backlen); + sldns_buffer_flip(c->buffer); } fptr_ok(fptr_whitelist_serviced_query(p->cb)); (void)(*p->cb)(c, p->cb_arg, error, rep); @@ -1541,8 +1575,8 @@ serviced_tcp_callback(struct comm_point* c, void* arg, int error, infra_update_tcp_works(sq->outnet->infra, &sq->addr, sq->addrlen, sq->zone, sq->zonelen); if(error==NETEVENT_NOERROR && sq->status == serviced_query_TCP_EDNS && - (LDNS_RCODE_WIRE(ldns_buffer_begin(c->buffer)) == - LDNS_RCODE_FORMERR || LDNS_RCODE_WIRE(ldns_buffer_begin( + (LDNS_RCODE_WIRE(sldns_buffer_begin(c->buffer)) == + LDNS_RCODE_FORMERR || LDNS_RCODE_WIRE(sldns_buffer_begin( c->buffer)) == LDNS_RCODE_NOTIMPL) ) { /* attempt to fallback to nonEDNS */ sq->status = serviced_query_TCP_EDNS_fallback; @@ -1550,10 +1584,10 @@ serviced_tcp_callback(struct comm_point* c, void* arg, int error, return 0; } else if(error==NETEVENT_NOERROR && sq->status == serviced_query_TCP_EDNS_fallback && - (LDNS_RCODE_WIRE(ldns_buffer_begin(c->buffer)) == + (LDNS_RCODE_WIRE(sldns_buffer_begin(c->buffer)) == LDNS_RCODE_NOERROR || LDNS_RCODE_WIRE( - ldns_buffer_begin(c->buffer)) == LDNS_RCODE_NXDOMAIN - || LDNS_RCODE_WIRE(ldns_buffer_begin(c->buffer)) + sldns_buffer_begin(c->buffer)) == LDNS_RCODE_NXDOMAIN + || LDNS_RCODE_WIRE(sldns_buffer_begin(c->buffer)) == LDNS_RCODE_YXDOMAIN)) { /* the fallback produced a result that looks promising, note * that this server should be approached without EDNS */ @@ -1599,7 +1633,7 @@ serviced_tcp_callback(struct comm_point* c, void* arg, int error, static void serviced_tcp_initiate(struct outside_network* outnet, - struct serviced_query* sq, ldns_buffer* buff) + struct serviced_query* sq, sldns_buffer* buff) { verbose(VERB_ALGO, "initiate TCP query %s", sq->status==serviced_query_TCP_EDNS?"EDNS":""); @@ -1618,7 +1652,7 @@ serviced_tcp_initiate(struct outside_network* outnet, /** Send serviced query over TCP return false on initial failure */ static int -serviced_tcp_send(struct serviced_query* sq, ldns_buffer* buff) +serviced_tcp_send(struct serviced_query* sq, sldns_buffer* buff) { int vs, rtt; uint8_t edns_lame_known; @@ -1697,9 +1731,9 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error, if(!fallback_tcp) { if( (sq->status == serviced_query_UDP_EDNS ||sq->status == serviced_query_UDP_EDNS_FRAG) - && (LDNS_RCODE_WIRE(ldns_buffer_begin(c->buffer)) + && (LDNS_RCODE_WIRE(sldns_buffer_begin(c->buffer)) == LDNS_RCODE_FORMERR || LDNS_RCODE_WIRE( - ldns_buffer_begin(c->buffer)) == LDNS_RCODE_NOTIMPL)) { + sldns_buffer_begin(c->buffer)) == LDNS_RCODE_NOTIMPL)) { /* try to get an answer by falling back without EDNS */ verbose(VERB_ALGO, "serviced query: attempt without EDNS"); sq->status = serviced_query_UDP_EDNS_fallback; @@ -1732,9 +1766,9 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error, sq->edns_lame_known = 1; } else if(sq->status == serviced_query_UDP_EDNS_fallback && !sq->edns_lame_known && (LDNS_RCODE_WIRE( - ldns_buffer_begin(c->buffer)) == LDNS_RCODE_NOERROR || - LDNS_RCODE_WIRE(ldns_buffer_begin(c->buffer)) == - LDNS_RCODE_NXDOMAIN || LDNS_RCODE_WIRE(ldns_buffer_begin( + sldns_buffer_begin(c->buffer)) == LDNS_RCODE_NOERROR || + LDNS_RCODE_WIRE(sldns_buffer_begin(c->buffer)) == + LDNS_RCODE_NXDOMAIN || LDNS_RCODE_WIRE(sldns_buffer_begin( c->buffer)) == LDNS_RCODE_YXDOMAIN)) { /* the fallback produced a result that looks promising, note * that this server should be approached without EDNS */ @@ -1773,7 +1807,7 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error, } /* end of if_!fallback_tcp */ /* perform TC flag check and TCP fallback after updating our * cache entries for EDNS status and RTT times */ - if(LDNS_TC_WIRE(ldns_buffer_begin(c->buffer)) || fallback_tcp) { + if(LDNS_TC_WIRE(sldns_buffer_begin(c->buffer)) || fallback_tcp) { /* fallback to TCP */ /* this discards partial UDP contents */ if(sq->status == serviced_query_UDP_EDNS || @@ -1796,7 +1830,7 @@ outnet_serviced_query(struct outside_network* outnet, uint16_t flags, int dnssec, int want_dnssec, int tcp_upstream, int ssl_upstream, struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, size_t zonelen, comm_point_callback_t* callback, - void* callback_arg, ldns_buffer* buff) + void* callback_arg, sldns_buffer* buff) { struct serviced_query* sq; struct service_callback* cb; @@ -1925,7 +1959,7 @@ size_t outnet_get_mem(struct outside_network* outnet) struct port_comm* pc; size_t s = sizeof(*outnet) + sizeof(*outnet->base) + sizeof(*outnet->udp_buff) + - ldns_buffer_capacity(outnet->udp_buff); + sldns_buffer_capacity(outnet->udp_buff); /* second buffer is not ours */ for(pc = outnet->unused_fds; pc; pc = pc->next) { s += sizeof(*pc) + comm_point_get_mem(pc->cp); diff --git a/services/outside_network.h b/services/outside_network.h index 87fe8ff108de..dda9d6f5a235 100644 --- a/services/outside_network.h +++ b/services/outside_network.h @@ -21,16 +21,16 @@ * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @@ -54,6 +54,7 @@ struct waiting_udp; struct infra_cache; struct port_comm; struct port_if; +struct sldns_buffer; /** * Send queries to outside servers and wait for answers from servers. @@ -69,7 +70,7 @@ struct outside_network { /** buffer shared by UDP connections, since there is only one datagram at any time. */ - ldns_buffer* udp_buff; + struct sldns_buffer* udp_buff; /** serviced_callbacks malloc overhead when processing multiple * identical serviced queries to the same server. */ size_t svcd_overhead; @@ -94,6 +95,10 @@ struct outside_network { struct port_comm* unused_fds; /** if udp is done */ int do_udp; + /** if udp is delay-closed (delayed answers do not meet closed port)*/ + int delayclose; + /** timeout for delayclose */ + struct timeval delay_tv; /** array of outgoing IP4 interfaces */ struct port_if* ip4_ifs; @@ -376,6 +381,8 @@ struct serviced_query { * @param unwanted_param: user parameter to action. * @param do_udp: if udp is done. * @param sslctx: context to create outgoing connections with (if enabled). + * @param delayclose: if not 0, udp sockets are delayed before timeout closure. + * msec to wait on timeouted udp sockets. * @return: the new structure (with no pending answers) or NULL on error. */ struct outside_network* outside_network_create(struct comm_base* base, @@ -384,7 +391,7 @@ struct outside_network* outside_network_create(struct comm_base* base, struct ub_randstate* rnd, int use_caps_for_id, int* availports, int numavailports, size_t unwanted_threshold, void (*unwanted_action)(void*), void* unwanted_param, int do_udp, - void* sslctx); + void* sslctx, int delayclose); /** * Delete outside_network structure. @@ -411,7 +418,7 @@ void outside_network_quit_prepare(struct outside_network* outnet); * @return: NULL on error for malloc or socket. Else the pending query object. */ struct pending* pending_udp_query(struct outside_network* outnet, - ldns_buffer* packet, struct sockaddr_storage* addr, + struct sldns_buffer* packet, struct sockaddr_storage* addr, socklen_t addrlen, int timeout, comm_point_callback_t* callback, void* callback_arg); @@ -431,7 +438,7 @@ struct pending* pending_udp_query(struct outside_network* outnet, * @return: false on error for malloc or socket. Else the pending TCP object. */ struct waiting_tcp* pending_tcp_query(struct outside_network* outnet, - ldns_buffer* packet, struct sockaddr_storage* addr, + struct sldns_buffer* packet, struct sockaddr_storage* addr, socklen_t addrlen, int timeout, comm_point_callback_t* callback, void* callback_arg, int ssl_upstream); @@ -476,7 +483,7 @@ struct serviced_query* outnet_serviced_query(struct outside_network* outnet, uint16_t flags, int dnssec, int want_dnssec, int tcp_upstream, int ssl_upstream, struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, size_t zonelen, comm_point_callback_t* callback, - void* callback_arg, ldns_buffer* buff); + void* callback_arg, struct sldns_buffer* buff); /** * Remove service query callback. @@ -515,6 +522,9 @@ int outnet_tcp_cb(struct comm_point* c, void* arg, int error, /** callback for udp timeout */ void pending_udp_timer_cb(void *arg); +/** callback for udp delay for timeout */ +void pending_udp_timer_delay_cb(void *arg); + /** callback for outgoing TCP timer event */ void outnet_tcptimer(void* arg); |