13b6c3722Schristos /* 23b6c3722Schristos * util/netevent.c - event notification 33b6c3722Schristos * 43b6c3722Schristos * Copyright (c) 2007, NLnet Labs. All rights reserved. 53b6c3722Schristos * 63b6c3722Schristos * This software is open source. 73b6c3722Schristos * 83b6c3722Schristos * Redistribution and use in source and binary forms, with or without 93b6c3722Schristos * modification, are permitted provided that the following conditions 103b6c3722Schristos * are met: 113b6c3722Schristos * 123b6c3722Schristos * Redistributions of source code must retain the above copyright notice, 133b6c3722Schristos * this list of conditions and the following disclaimer. 143b6c3722Schristos * 153b6c3722Schristos * Redistributions in binary form must reproduce the above copyright notice, 163b6c3722Schristos * this list of conditions and the following disclaimer in the documentation 173b6c3722Schristos * and/or other materials provided with the distribution. 183b6c3722Schristos * 193b6c3722Schristos * Neither the name of the NLNET LABS nor the names of its contributors may 203b6c3722Schristos * be used to endorse or promote products derived from this software without 213b6c3722Schristos * specific prior written permission. 223b6c3722Schristos * 233b6c3722Schristos * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 243b6c3722Schristos * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 253b6c3722Schristos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 263b6c3722Schristos * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 273b6c3722Schristos * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 283b6c3722Schristos * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 293b6c3722Schristos * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 303b6c3722Schristos * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 313b6c3722Schristos * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 323b6c3722Schristos * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 333b6c3722Schristos * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 343b6c3722Schristos */ 353b6c3722Schristos 363b6c3722Schristos /** 373b6c3722Schristos * \file 383b6c3722Schristos * 393b6c3722Schristos * This file contains event notification functions. 403b6c3722Schristos */ 413b6c3722Schristos #include "config.h" 423b6c3722Schristos #include "util/netevent.h" 433b6c3722Schristos #include "util/ub_event.h" 443b6c3722Schristos #include "util/log.h" 453b6c3722Schristos #include "util/net_help.h" 46f42d8de7Schristos #include "util/tcp_conn_limit.h" 473b6c3722Schristos #include "util/fptr_wlist.h" 48*14b2fa6eSchristos #include "util/proxy_protocol.h" 49*14b2fa6eSchristos #include "util/timeval_func.h" 503b6c3722Schristos #include "sldns/pkthdr.h" 513b6c3722Schristos #include "sldns/sbuffer.h" 527cd94d69Schristos #include "sldns/str2wire.h" 533b6c3722Schristos #include "dnstap/dnstap.h" 540cd9f4ecSchristos #include "dnscrypt/dnscrypt.h" 55f42d8de7Schristos #include "services/listen_dnsport.h" 561481e2a9Schristos #ifdef HAVE_SYS_TYPES_H 571481e2a9Schristos #include <sys/types.h> 581481e2a9Schristos #endif 591481e2a9Schristos #ifdef HAVE_SYS_SOCKET_H 601481e2a9Schristos #include <sys/socket.h> 611481e2a9Schristos #endif 621481e2a9Schristos #ifdef HAVE_NETDB_H 631481e2a9Schristos #include <netdb.h> 641481e2a9Schristos #endif 65*14b2fa6eSchristos #ifdef HAVE_POLL_H 66*14b2fa6eSchristos #include <poll.h> 67*14b2fa6eSchristos #endif 681481e2a9Schristos 693b6c3722Schristos #ifdef HAVE_OPENSSL_SSL_H 703b6c3722Schristos #include <openssl/ssl.h> 713b6c3722Schristos #endif 723b6c3722Schristos #ifdef HAVE_OPENSSL_ERR_H 733b6c3722Schristos #include <openssl/err.h> 743b6c3722Schristos #endif 75*14b2fa6eSchristos #ifdef HAVE_LINUX_NET_TSTAMP_H 76*14b2fa6eSchristos #include <linux/net_tstamp.h> 77*14b2fa6eSchristos #endif 783b6c3722Schristos /* -------- Start of local definitions -------- */ 793b6c3722Schristos /** if CMSG_ALIGN is not defined on this platform, a workaround */ 803b6c3722Schristos #ifndef CMSG_ALIGN 813b6c3722Schristos # ifdef __CMSG_ALIGN 823b6c3722Schristos # define CMSG_ALIGN(n) __CMSG_ALIGN(n) 833b6c3722Schristos # elif defined(CMSG_DATA_ALIGN) 843b6c3722Schristos # define CMSG_ALIGN _CMSG_DATA_ALIGN 853b6c3722Schristos # else 863b6c3722Schristos # define CMSG_ALIGN(len) (((len)+sizeof(long)-1) & ~(sizeof(long)-1)) 873b6c3722Schristos # endif 883b6c3722Schristos #endif 893b6c3722Schristos 903b6c3722Schristos /** if CMSG_LEN is not defined on this platform, a workaround */ 913b6c3722Schristos #ifndef CMSG_LEN 923b6c3722Schristos # define CMSG_LEN(len) (CMSG_ALIGN(sizeof(struct cmsghdr))+(len)) 933b6c3722Schristos #endif 943b6c3722Schristos 953b6c3722Schristos /** if CMSG_SPACE is not defined on this platform, a workaround */ 963b6c3722Schristos #ifndef CMSG_SPACE 973b6c3722Schristos # ifdef _CMSG_HDR_ALIGN 983b6c3722Schristos # define CMSG_SPACE(l) (CMSG_ALIGN(l)+_CMSG_HDR_ALIGN(sizeof(struct cmsghdr))) 993b6c3722Schristos # else 1003b6c3722Schristos # define CMSG_SPACE(l) (CMSG_ALIGN(l)+CMSG_ALIGN(sizeof(struct cmsghdr))) 1013b6c3722Schristos # endif 1023b6c3722Schristos #endif 1033b6c3722Schristos 104f42d8de7Schristos /** The TCP writing query timeout in milliseconds */ 1050cd9f4ecSchristos #define TCP_QUERY_TIMEOUT 120000 106f42d8de7Schristos /** The minimum actual TCP timeout to use, regardless of what we advertise, 107f42d8de7Schristos * in msec */ 108f42d8de7Schristos #define TCP_QUERY_TIMEOUT_MINIMUM 200 1093b6c3722Schristos 1103b6c3722Schristos #ifndef NONBLOCKING_IS_BROKEN 1113b6c3722Schristos /** number of UDP reads to perform per read indication from select */ 1123b6c3722Schristos #define NUM_UDP_PER_SELECT 100 1133b6c3722Schristos #else 1143b6c3722Schristos #define NUM_UDP_PER_SELECT 1 1153b6c3722Schristos #endif 1163b6c3722Schristos 117*14b2fa6eSchristos /** timeout in millisec to wait for write to unblock, packets dropped after.*/ 118*14b2fa6eSchristos #define SEND_BLOCKED_WAIT_TIMEOUT 200 119*14b2fa6eSchristos /** max number of times to wait for write to unblock, packets dropped after.*/ 120*14b2fa6eSchristos #define SEND_BLOCKED_MAX_RETRY 5 121*14b2fa6eSchristos 122*14b2fa6eSchristos /** Let's make timestamping code cleaner and redefine SO_TIMESTAMP* */ 123*14b2fa6eSchristos #ifndef SO_TIMESTAMP 124*14b2fa6eSchristos #define SO_TIMESTAMP 29 125*14b2fa6eSchristos #endif 126*14b2fa6eSchristos #ifndef SO_TIMESTAMPNS 127*14b2fa6eSchristos #define SO_TIMESTAMPNS 35 128*14b2fa6eSchristos #endif 129*14b2fa6eSchristos #ifndef SO_TIMESTAMPING 130*14b2fa6eSchristos #define SO_TIMESTAMPING 37 131*14b2fa6eSchristos #endif 1323b6c3722Schristos /** 1333b6c3722Schristos * The internal event structure for keeping ub_event info for the event. 1343b6c3722Schristos * Possibly other structures (list, tree) this is part of. 1353b6c3722Schristos */ 1363b6c3722Schristos struct internal_event { 1373b6c3722Schristos /** the comm base */ 1383b6c3722Schristos struct comm_base* base; 1393b6c3722Schristos /** ub_event event type */ 1403b6c3722Schristos struct ub_event* ev; 1413b6c3722Schristos }; 1423b6c3722Schristos 1433b6c3722Schristos /** 1443b6c3722Schristos * Internal base structure, so that every thread has its own events. 1453b6c3722Schristos */ 1463b6c3722Schristos struct internal_base { 1473b6c3722Schristos /** ub_event event_base type. */ 1483b6c3722Schristos struct ub_event_base* base; 1493b6c3722Schristos /** seconds time pointer points here */ 1503b6c3722Schristos time_t secs; 1513b6c3722Schristos /** timeval with current time */ 1523b6c3722Schristos struct timeval now; 1533b6c3722Schristos /** the event used for slow_accept timeouts */ 1543b6c3722Schristos struct ub_event* slow_accept; 1553b6c3722Schristos /** true if slow_accept is enabled */ 1563b6c3722Schristos int slow_accept_enabled; 157*14b2fa6eSchristos /** last log time for slow logging of file descriptor errors */ 158*14b2fa6eSchristos time_t last_slow_log; 159*14b2fa6eSchristos /** last log time for slow logging of write wait failures */ 160*14b2fa6eSchristos time_t last_writewait_log; 1613b6c3722Schristos }; 1623b6c3722Schristos 1633b6c3722Schristos /** 1643b6c3722Schristos * Internal timer structure, to store timer event in. 1653b6c3722Schristos */ 1663b6c3722Schristos struct internal_timer { 1673b6c3722Schristos /** the super struct from which derived */ 1683b6c3722Schristos struct comm_timer super; 1693b6c3722Schristos /** the comm base */ 1703b6c3722Schristos struct comm_base* base; 1713b6c3722Schristos /** ub_event event type */ 1723b6c3722Schristos struct ub_event* ev; 1733b6c3722Schristos /** is timer enabled */ 1743b6c3722Schristos uint8_t enabled; 1753b6c3722Schristos }; 1763b6c3722Schristos 1773b6c3722Schristos /** 1783b6c3722Schristos * Internal signal structure, to store signal event in. 1793b6c3722Schristos */ 1803b6c3722Schristos struct internal_signal { 1813b6c3722Schristos /** ub_event event type */ 1823b6c3722Schristos struct ub_event* ev; 1833b6c3722Schristos /** next in signal list */ 1843b6c3722Schristos struct internal_signal* next; 1853b6c3722Schristos }; 1863b6c3722Schristos 1873b6c3722Schristos /** create a tcp handler with a parent */ 1883b6c3722Schristos static struct comm_point* comm_point_create_tcp_handler( 1893b6c3722Schristos struct comm_base *base, struct comm_point* parent, size_t bufsize, 190f42d8de7Schristos struct sldns_buffer* spoolbuf, comm_point_callback_type* callback, 1911481e2a9Schristos void* callback_arg, struct unbound_socket* socket); 1923b6c3722Schristos 1933b6c3722Schristos /* -------- End of local definitions -------- */ 1943b6c3722Schristos 1953b6c3722Schristos struct comm_base* comm_base_create(int sigs)1963b6c3722Schristoscomm_base_create(int sigs) 1973b6c3722Schristos { 1983b6c3722Schristos struct comm_base* b = (struct comm_base*)calloc(1, 1993b6c3722Schristos sizeof(struct comm_base)); 2003b6c3722Schristos const char *evnm="event", *evsys="", *evmethod=""; 2013b6c3722Schristos 2023b6c3722Schristos if(!b) 2033b6c3722Schristos return NULL; 2043b6c3722Schristos b->eb = (struct internal_base*)calloc(1, sizeof(struct internal_base)); 2053b6c3722Schristos if(!b->eb) { 2063b6c3722Schristos free(b); 2073b6c3722Schristos return NULL; 2083b6c3722Schristos } 2093b6c3722Schristos b->eb->base = ub_default_event_base(sigs, &b->eb->secs, &b->eb->now); 2103b6c3722Schristos if(!b->eb->base) { 2113b6c3722Schristos free(b->eb); 2123b6c3722Schristos free(b); 2133b6c3722Schristos return NULL; 2143b6c3722Schristos } 2153b6c3722Schristos ub_comm_base_now(b); 2163b6c3722Schristos ub_get_event_sys(b->eb->base, &evnm, &evsys, &evmethod); 21787edd195Schristos verbose(VERB_ALGO, "%s %s uses %s method.", evnm, evsys, evmethod); 2183b6c3722Schristos return b; 2193b6c3722Schristos } 2203b6c3722Schristos 2213b6c3722Schristos struct comm_base* comm_base_create_event(struct ub_event_base * base)2223b6c3722Schristoscomm_base_create_event(struct ub_event_base* base) 2233b6c3722Schristos { 2243b6c3722Schristos struct comm_base* b = (struct comm_base*)calloc(1, 2253b6c3722Schristos sizeof(struct comm_base)); 2263b6c3722Schristos if(!b) 2273b6c3722Schristos return NULL; 2283b6c3722Schristos b->eb = (struct internal_base*)calloc(1, sizeof(struct internal_base)); 2293b6c3722Schristos if(!b->eb) { 2303b6c3722Schristos free(b); 2313b6c3722Schristos return NULL; 2323b6c3722Schristos } 2333b6c3722Schristos b->eb->base = base; 2343b6c3722Schristos ub_comm_base_now(b); 2353b6c3722Schristos return b; 2363b6c3722Schristos } 2373b6c3722Schristos 2383b6c3722Schristos void comm_base_delete(struct comm_base * b)2393b6c3722Schristoscomm_base_delete(struct comm_base* b) 2403b6c3722Schristos { 2413b6c3722Schristos if(!b) 2423b6c3722Schristos return; 2433b6c3722Schristos if(b->eb->slow_accept_enabled) { 2443b6c3722Schristos if(ub_event_del(b->eb->slow_accept) != 0) { 2453b6c3722Schristos log_err("could not event_del slow_accept"); 2463b6c3722Schristos } 2473b6c3722Schristos ub_event_free(b->eb->slow_accept); 2483b6c3722Schristos } 2493b6c3722Schristos ub_event_base_free(b->eb->base); 2503b6c3722Schristos b->eb->base = NULL; 2513b6c3722Schristos free(b->eb); 2523b6c3722Schristos free(b); 2533b6c3722Schristos } 2543b6c3722Schristos 2553b6c3722Schristos void comm_base_delete_no_base(struct comm_base * b)2563b6c3722Schristoscomm_base_delete_no_base(struct comm_base* b) 2573b6c3722Schristos { 2583b6c3722Schristos if(!b) 2593b6c3722Schristos return; 2603b6c3722Schristos if(b->eb->slow_accept_enabled) { 2613b6c3722Schristos if(ub_event_del(b->eb->slow_accept) != 0) { 2623b6c3722Schristos log_err("could not event_del slow_accept"); 2633b6c3722Schristos } 2643b6c3722Schristos ub_event_free(b->eb->slow_accept); 2653b6c3722Schristos } 2663b6c3722Schristos b->eb->base = NULL; 2673b6c3722Schristos free(b->eb); 2683b6c3722Schristos free(b); 2693b6c3722Schristos } 2703b6c3722Schristos 2713b6c3722Schristos void comm_base_timept(struct comm_base * b,time_t ** tt,struct timeval ** tv)2723b6c3722Schristoscomm_base_timept(struct comm_base* b, time_t** tt, struct timeval** tv) 2733b6c3722Schristos { 2743b6c3722Schristos *tt = &b->eb->secs; 2753b6c3722Schristos *tv = &b->eb->now; 2763b6c3722Schristos } 2773b6c3722Schristos 2783b6c3722Schristos void comm_base_dispatch(struct comm_base * b)2793b6c3722Schristoscomm_base_dispatch(struct comm_base* b) 2803b6c3722Schristos { 2813b6c3722Schristos int retval; 2823b6c3722Schristos retval = ub_event_base_dispatch(b->eb->base); 2833b6c3722Schristos if(retval < 0) { 2843b6c3722Schristos fatal_exit("event_dispatch returned error %d, " 2853b6c3722Schristos "errno is %s", retval, strerror(errno)); 2863b6c3722Schristos } 2873b6c3722Schristos } 2883b6c3722Schristos comm_base_exit(struct comm_base * b)2893b6c3722Schristosvoid comm_base_exit(struct comm_base* b) 2903b6c3722Schristos { 2913b6c3722Schristos if(ub_event_base_loopexit(b->eb->base) != 0) { 2923b6c3722Schristos log_err("Could not loopexit"); 2933b6c3722Schristos } 2943b6c3722Schristos } 2953b6c3722Schristos comm_base_set_slow_accept_handlers(struct comm_base * b,void (* stop_acc)(void *),void (* start_acc)(void *),void * arg)2963b6c3722Schristosvoid comm_base_set_slow_accept_handlers(struct comm_base* b, 2973b6c3722Schristos void (*stop_acc)(void*), void (*start_acc)(void*), void* arg) 2983b6c3722Schristos { 2993b6c3722Schristos b->stop_accept = stop_acc; 3003b6c3722Schristos b->start_accept = start_acc; 3013b6c3722Schristos b->cb_arg = arg; 3023b6c3722Schristos } 3033b6c3722Schristos comm_base_internal(struct comm_base * b)3043b6c3722Schristosstruct ub_event_base* comm_base_internal(struct comm_base* b) 3053b6c3722Schristos { 3063b6c3722Schristos return b->eb->base; 3073b6c3722Schristos } 3083b6c3722Schristos 3093b6c3722Schristos /** see if errno for udp has to be logged or not uses globals */ 3103b6c3722Schristos static int udp_send_errno_needs_log(struct sockaddr * addr,socklen_t addrlen)3113b6c3722Schristosudp_send_errno_needs_log(struct sockaddr* addr, socklen_t addrlen) 3123b6c3722Schristos { 3133b6c3722Schristos /* do not log transient errors (unless high verbosity) */ 3143b6c3722Schristos #if defined(ENETUNREACH) || defined(EHOSTDOWN) || defined(EHOSTUNREACH) || defined(ENETDOWN) 3153b6c3722Schristos switch(errno) { 3163b6c3722Schristos # ifdef ENETUNREACH 3173b6c3722Schristos case ENETUNREACH: 3183b6c3722Schristos # endif 3193b6c3722Schristos # ifdef EHOSTDOWN 3203b6c3722Schristos case EHOSTDOWN: 3213b6c3722Schristos # endif 3223b6c3722Schristos # ifdef EHOSTUNREACH 3233b6c3722Schristos case EHOSTUNREACH: 3243b6c3722Schristos # endif 3253b6c3722Schristos # ifdef ENETDOWN 3263b6c3722Schristos case ENETDOWN: 3273b6c3722Schristos # endif 3281481e2a9Schristos case EPERM: 3291481e2a9Schristos case EACCES: 3303b6c3722Schristos if(verbosity < VERB_ALGO) 3313b6c3722Schristos return 0; 3323b6c3722Schristos default: 3333b6c3722Schristos break; 3343b6c3722Schristos } 3353b6c3722Schristos #endif 3363b6c3722Schristos /* permission denied is gotten for every send if the 3373b6c3722Schristos * network is disconnected (on some OS), squelch it */ 3383b6c3722Schristos if( ((errno == EPERM) 3393b6c3722Schristos # ifdef EADDRNOTAVAIL 3403b6c3722Schristos /* 'Cannot assign requested address' also when disconnected */ 3413b6c3722Schristos || (errno == EADDRNOTAVAIL) 3423b6c3722Schristos # endif 3431481e2a9Schristos ) && verbosity < VERB_ALGO) 3443b6c3722Schristos return 0; 3457cd94d69Schristos # ifdef EADDRINUSE 3467cd94d69Schristos /* If SO_REUSEADDR is set, we could try to connect to the same server 3477cd94d69Schristos * from the same source port twice. */ 3487cd94d69Schristos if(errno == EADDRINUSE && verbosity < VERB_DETAIL) 3497cd94d69Schristos return 0; 3507cd94d69Schristos # endif 3513b6c3722Schristos /* squelch errors where people deploy AAAA ::ffff:bla for 3523b6c3722Schristos * authority servers, which we try for intranets. */ 3533b6c3722Schristos if(errno == EINVAL && addr_is_ip4mapped( 3543b6c3722Schristos (struct sockaddr_storage*)addr, addrlen) && 3553b6c3722Schristos verbosity < VERB_DETAIL) 3563b6c3722Schristos return 0; 3573b6c3722Schristos /* SO_BROADCAST sockopt can give access to 255.255.255.255, 3583b6c3722Schristos * but a dns cache does not need it. */ 3593b6c3722Schristos if(errno == EACCES && addr_is_broadcast( 3603b6c3722Schristos (struct sockaddr_storage*)addr, addrlen) && 3613b6c3722Schristos verbosity < VERB_DETAIL) 3623b6c3722Schristos return 0; 3633b6c3722Schristos return 1; 3643b6c3722Schristos } 3653b6c3722Schristos tcp_connect_errno_needs_log(struct sockaddr * addr,socklen_t addrlen)3663b6c3722Schristosint tcp_connect_errno_needs_log(struct sockaddr* addr, socklen_t addrlen) 3673b6c3722Schristos { 3683b6c3722Schristos return udp_send_errno_needs_log(addr, addrlen); 3693b6c3722Schristos } 3703b6c3722Schristos 3713b6c3722Schristos /* send a UDP reply */ 3723b6c3722Schristos int comm_point_send_udp_msg(struct comm_point * c,sldns_buffer * packet,struct sockaddr * addr,socklen_t addrlen,int is_connected)3733b6c3722Schristoscomm_point_send_udp_msg(struct comm_point *c, sldns_buffer* packet, 37416776186Schristos struct sockaddr* addr, socklen_t addrlen, int is_connected) 3753b6c3722Schristos { 3763b6c3722Schristos ssize_t sent; 3773b6c3722Schristos log_assert(c->fd != -1); 3783b6c3722Schristos #ifdef UNBOUND_DEBUG 3793b6c3722Schristos if(sldns_buffer_remaining(packet) == 0) 3803b6c3722Schristos log_err("error: send empty UDP packet"); 3813b6c3722Schristos #endif 3823b6c3722Schristos log_assert(addr && addrlen > 0); 38316776186Schristos if(!is_connected) { 3843b6c3722Schristos sent = sendto(c->fd, (void*)sldns_buffer_begin(packet), 3853b6c3722Schristos sldns_buffer_remaining(packet), 0, 3863b6c3722Schristos addr, addrlen); 38716776186Schristos } else { 38816776186Schristos sent = send(c->fd, (void*)sldns_buffer_begin(packet), 38916776186Schristos sldns_buffer_remaining(packet), 0); 39016776186Schristos } 3913b6c3722Schristos if(sent == -1) { 3923b6c3722Schristos /* try again and block, waiting for IO to complete, 3933b6c3722Schristos * we want to send the answer, and we will wait for 3943b6c3722Schristos * the ethernet interface buffer to have space. */ 3953b6c3722Schristos #ifndef USE_WINSOCK 396*14b2fa6eSchristos if(errno == EAGAIN || errno == EINTR || 3973b6c3722Schristos # ifdef EWOULDBLOCK 3983b6c3722Schristos errno == EWOULDBLOCK || 3993b6c3722Schristos # endif 4003b6c3722Schristos errno == ENOBUFS) { 4013b6c3722Schristos #else 4023b6c3722Schristos if(WSAGetLastError() == WSAEINPROGRESS || 403*14b2fa6eSchristos WSAGetLastError() == WSAEINTR || 4043b6c3722Schristos WSAGetLastError() == WSAENOBUFS || 4053b6c3722Schristos WSAGetLastError() == WSAEWOULDBLOCK) { 4063b6c3722Schristos #endif 407*14b2fa6eSchristos int retries = 0; 408*14b2fa6eSchristos /* if we set the fd blocking, other threads suddenly 409*14b2fa6eSchristos * have a blocking fd that they operate on */ 410*14b2fa6eSchristos while(sent == -1 && retries < SEND_BLOCKED_MAX_RETRY && ( 411*14b2fa6eSchristos #ifndef USE_WINSOCK 412*14b2fa6eSchristos errno == EAGAIN || errno == EINTR || 413*14b2fa6eSchristos # ifdef EWOULDBLOCK 414*14b2fa6eSchristos errno == EWOULDBLOCK || 415*14b2fa6eSchristos # endif 416*14b2fa6eSchristos errno == ENOBUFS 417*14b2fa6eSchristos #else 418*14b2fa6eSchristos WSAGetLastError() == WSAEINPROGRESS || 419*14b2fa6eSchristos WSAGetLastError() == WSAEINTR || 420*14b2fa6eSchristos WSAGetLastError() == WSAENOBUFS || 421*14b2fa6eSchristos WSAGetLastError() == WSAEWOULDBLOCK 422*14b2fa6eSchristos #endif 423*14b2fa6eSchristos )) { 424*14b2fa6eSchristos #if defined(HAVE_POLL) || defined(USE_WINSOCK) 425*14b2fa6eSchristos int send_nobufs = ( 426*14b2fa6eSchristos #ifndef USE_WINSOCK 427*14b2fa6eSchristos errno == ENOBUFS 428*14b2fa6eSchristos #else 429*14b2fa6eSchristos WSAGetLastError() == WSAENOBUFS 430*14b2fa6eSchristos #endif 431*14b2fa6eSchristos ); 432*14b2fa6eSchristos struct pollfd p; 433*14b2fa6eSchristos int pret; 434*14b2fa6eSchristos memset(&p, 0, sizeof(p)); 435*14b2fa6eSchristos p.fd = c->fd; 436*14b2fa6eSchristos p.events = POLLOUT | POLLERR | POLLHUP; 437*14b2fa6eSchristos # ifndef USE_WINSOCK 438*14b2fa6eSchristos pret = poll(&p, 1, SEND_BLOCKED_WAIT_TIMEOUT); 439*14b2fa6eSchristos # else 440*14b2fa6eSchristos pret = WSAPoll(&p, 1, 441*14b2fa6eSchristos SEND_BLOCKED_WAIT_TIMEOUT); 442*14b2fa6eSchristos # endif 443*14b2fa6eSchristos if(pret == 0) { 444*14b2fa6eSchristos /* timer expired */ 445*14b2fa6eSchristos struct comm_base* b = c->ev->base; 446*14b2fa6eSchristos if(b->eb->last_writewait_log+SLOW_LOG_TIME <= 447*14b2fa6eSchristos b->eb->secs) { 448*14b2fa6eSchristos b->eb->last_writewait_log = b->eb->secs; 449*14b2fa6eSchristos verbose(VERB_OPS, "send udp blocked " 450*14b2fa6eSchristos "for long, dropping packet."); 451*14b2fa6eSchristos } 452*14b2fa6eSchristos return 0; 453*14b2fa6eSchristos } else if(pret < 0 && 454*14b2fa6eSchristos #ifndef USE_WINSOCK 455*14b2fa6eSchristos errno != EAGAIN && errno != EINTR && 456*14b2fa6eSchristos # ifdef EWOULDBLOCK 457*14b2fa6eSchristos errno != EWOULDBLOCK && 458*14b2fa6eSchristos # endif 459*14b2fa6eSchristos errno != ENOBUFS 460*14b2fa6eSchristos #else 461*14b2fa6eSchristos WSAGetLastError() != WSAEINPROGRESS && 462*14b2fa6eSchristos WSAGetLastError() != WSAEINTR && 463*14b2fa6eSchristos WSAGetLastError() != WSAENOBUFS && 464*14b2fa6eSchristos WSAGetLastError() != WSAEWOULDBLOCK 465*14b2fa6eSchristos #endif 466*14b2fa6eSchristos ) { 467*14b2fa6eSchristos log_err("poll udp out failed: %s", 468*14b2fa6eSchristos sock_strerror(errno)); 469*14b2fa6eSchristos return 0; 470*14b2fa6eSchristos } else if((pret < 0 && 471*14b2fa6eSchristos #ifndef USE_WINSOCK 472*14b2fa6eSchristos errno == ENOBUFS 473*14b2fa6eSchristos #else 474*14b2fa6eSchristos WSAGetLastError() == WSAENOBUFS 475*14b2fa6eSchristos #endif 476*14b2fa6eSchristos ) || (send_nobufs && retries > 0)) { 477*14b2fa6eSchristos /* ENOBUFS, and poll returned without 478*14b2fa6eSchristos * a timeout. Or the retried send call 479*14b2fa6eSchristos * returned ENOBUFS. It is good to 480*14b2fa6eSchristos * wait a bit for the error to clear. */ 481*14b2fa6eSchristos /* The timeout is 20*(2^(retries+1)), 482*14b2fa6eSchristos * it increases exponentially, starting 483*14b2fa6eSchristos * at 40 msec. After 5 tries, 1240 msec 484*14b2fa6eSchristos * have passed in total, when poll 485*14b2fa6eSchristos * returned the error, and 1200 msec 486*14b2fa6eSchristos * when send returned the errors. */ 487*14b2fa6eSchristos #ifndef USE_WINSOCK 488*14b2fa6eSchristos pret = poll(NULL, 0, (SEND_BLOCKED_WAIT_TIMEOUT/10)<<(retries+1)); 489*14b2fa6eSchristos #else 490*14b2fa6eSchristos pret = WSAPoll(NULL, 0, (SEND_BLOCKED_WAIT_TIMEOUT/10)<<(retries+1)); 491*14b2fa6eSchristos #endif 492*14b2fa6eSchristos if(pret < 0 && 493*14b2fa6eSchristos #ifndef USE_WINSOCK 494*14b2fa6eSchristos errno != EAGAIN && errno != EINTR && 495*14b2fa6eSchristos # ifdef EWOULDBLOCK 496*14b2fa6eSchristos errno != EWOULDBLOCK && 497*14b2fa6eSchristos # endif 498*14b2fa6eSchristos errno != ENOBUFS 499*14b2fa6eSchristos #else 500*14b2fa6eSchristos WSAGetLastError() != WSAEINPROGRESS && 501*14b2fa6eSchristos WSAGetLastError() != WSAEINTR && 502*14b2fa6eSchristos WSAGetLastError() != WSAENOBUFS && 503*14b2fa6eSchristos WSAGetLastError() != WSAEWOULDBLOCK 504*14b2fa6eSchristos #endif 505*14b2fa6eSchristos ) { 506*14b2fa6eSchristos log_err("poll udp out timer failed: %s", 507*14b2fa6eSchristos sock_strerror(errno)); 508*14b2fa6eSchristos } 509*14b2fa6eSchristos } 510*14b2fa6eSchristos #endif /* defined(HAVE_POLL) || defined(USE_WINSOCK) */ 511*14b2fa6eSchristos retries++; 51216776186Schristos if (!is_connected) { 5133b6c3722Schristos sent = sendto(c->fd, (void*)sldns_buffer_begin(packet), 5143b6c3722Schristos sldns_buffer_remaining(packet), 0, 5153b6c3722Schristos addr, addrlen); 51616776186Schristos } else { 51716776186Schristos sent = send(c->fd, (void*)sldns_buffer_begin(packet), 51816776186Schristos sldns_buffer_remaining(packet), 0); 51916776186Schristos } 520*14b2fa6eSchristos } 5213b6c3722Schristos } 5223b6c3722Schristos } 5233b6c3722Schristos if(sent == -1) { 5243b6c3722Schristos if(!udp_send_errno_needs_log(addr, addrlen)) 5253b6c3722Schristos return 0; 52616776186Schristos if (!is_connected) { 52716776186Schristos verbose(VERB_OPS, "sendto failed: %s", sock_strerror(errno)); 52816776186Schristos } else { 52916776186Schristos verbose(VERB_OPS, "send failed: %s", sock_strerror(errno)); 53016776186Schristos } 53116776186Schristos if(addr) 5323b6c3722Schristos log_addr(VERB_OPS, "remote address is", 5333b6c3722Schristos (struct sockaddr_storage*)addr, addrlen); 5343b6c3722Schristos return 0; 5353b6c3722Schristos } else if((size_t)sent != sldns_buffer_remaining(packet)) { 5363b6c3722Schristos log_err("sent %d in place of %d bytes", 5373b6c3722Schristos (int)sent, (int)sldns_buffer_remaining(packet)); 5383b6c3722Schristos return 0; 5393b6c3722Schristos } 5403b6c3722Schristos return 1; 5413b6c3722Schristos } 5423b6c3722Schristos 5433b6c3722Schristos #if defined(AF_INET6) && defined(IPV6_PKTINFO) && (defined(HAVE_RECVMSG) || defined(HAVE_SENDMSG)) 5443b6c3722Schristos /** print debug ancillary info */ 5453b6c3722Schristos static void p_ancil(const char* str, struct comm_reply* r) 5463b6c3722Schristos { 5473b6c3722Schristos if(r->srctype != 4 && r->srctype != 6) { 5483b6c3722Schristos log_info("%s: unknown srctype %d", str, r->srctype); 5493b6c3722Schristos return; 5503b6c3722Schristos } 5511481e2a9Schristos 5523b6c3722Schristos if(r->srctype == 6) { 5531481e2a9Schristos #ifdef IPV6_PKTINFO 5543b6c3722Schristos char buf[1024]; 5553b6c3722Schristos if(inet_ntop(AF_INET6, &r->pktinfo.v6info.ipi6_addr, 5563b6c3722Schristos buf, (socklen_t)sizeof(buf)) == 0) { 5573b6c3722Schristos (void)strlcpy(buf, "(inet_ntop error)", sizeof(buf)); 5583b6c3722Schristos } 5593b6c3722Schristos buf[sizeof(buf)-1]=0; 5603b6c3722Schristos log_info("%s: %s %d", str, buf, r->pktinfo.v6info.ipi6_ifindex); 5611481e2a9Schristos #endif 5623b6c3722Schristos } else if(r->srctype == 4) { 5633b6c3722Schristos #ifdef IP_PKTINFO 5643b6c3722Schristos char buf1[1024], buf2[1024]; 5653b6c3722Schristos if(inet_ntop(AF_INET, &r->pktinfo.v4info.ipi_addr, 5663b6c3722Schristos buf1, (socklen_t)sizeof(buf1)) == 0) { 5673b6c3722Schristos (void)strlcpy(buf1, "(inet_ntop error)", sizeof(buf1)); 5683b6c3722Schristos } 5693b6c3722Schristos buf1[sizeof(buf1)-1]=0; 5703b6c3722Schristos #ifdef HAVE_STRUCT_IN_PKTINFO_IPI_SPEC_DST 5713b6c3722Schristos if(inet_ntop(AF_INET, &r->pktinfo.v4info.ipi_spec_dst, 5723b6c3722Schristos buf2, (socklen_t)sizeof(buf2)) == 0) { 5733b6c3722Schristos (void)strlcpy(buf2, "(inet_ntop error)", sizeof(buf2)); 5743b6c3722Schristos } 5753b6c3722Schristos buf2[sizeof(buf2)-1]=0; 5763b6c3722Schristos #else 5773b6c3722Schristos buf2[0]=0; 5783b6c3722Schristos #endif 5793b6c3722Schristos log_info("%s: %d %s %s", str, r->pktinfo.v4info.ipi_ifindex, 5803b6c3722Schristos buf1, buf2); 5813b6c3722Schristos #elif defined(IP_RECVDSTADDR) 5823b6c3722Schristos char buf1[1024]; 5833b6c3722Schristos if(inet_ntop(AF_INET, &r->pktinfo.v4addr, 5843b6c3722Schristos buf1, (socklen_t)sizeof(buf1)) == 0) { 5853b6c3722Schristos (void)strlcpy(buf1, "(inet_ntop error)", sizeof(buf1)); 5863b6c3722Schristos } 5873b6c3722Schristos buf1[sizeof(buf1)-1]=0; 5883b6c3722Schristos log_info("%s: %s", str, buf1); 5893b6c3722Schristos #endif /* IP_PKTINFO or PI_RECVDSTDADDR */ 5903b6c3722Schristos } 5913b6c3722Schristos } 5923b6c3722Schristos #endif /* AF_INET6 && IPV6_PKTINFO && HAVE_RECVMSG||HAVE_SENDMSG */ 5933b6c3722Schristos 5943b6c3722Schristos /** send a UDP reply over specified interface*/ 5953b6c3722Schristos static int 5963b6c3722Schristos comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet, 5973b6c3722Schristos struct sockaddr* addr, socklen_t addrlen, struct comm_reply* r) 5983b6c3722Schristos { 5993b6c3722Schristos #if defined(AF_INET6) && defined(IPV6_PKTINFO) && defined(HAVE_SENDMSG) 6003b6c3722Schristos ssize_t sent; 6013b6c3722Schristos struct msghdr msg; 6023b6c3722Schristos struct iovec iov[1]; 60316776186Schristos union { 60416776186Schristos struct cmsghdr hdr; 60516776186Schristos char buf[256]; 60616776186Schristos } control; 6073b6c3722Schristos #ifndef S_SPLINT_S 6083b6c3722Schristos struct cmsghdr *cmsg; 6093b6c3722Schristos #endif /* S_SPLINT_S */ 6103b6c3722Schristos 6113b6c3722Schristos log_assert(c->fd != -1); 6123b6c3722Schristos #ifdef UNBOUND_DEBUG 6133b6c3722Schristos if(sldns_buffer_remaining(packet) == 0) 6143b6c3722Schristos log_err("error: send empty UDP packet"); 6153b6c3722Schristos #endif 6163b6c3722Schristos log_assert(addr && addrlen > 0); 6173b6c3722Schristos 6183b6c3722Schristos msg.msg_name = addr; 6193b6c3722Schristos msg.msg_namelen = addrlen; 6203b6c3722Schristos iov[0].iov_base = sldns_buffer_begin(packet); 6213b6c3722Schristos iov[0].iov_len = sldns_buffer_remaining(packet); 6223b6c3722Schristos msg.msg_iov = iov; 6233b6c3722Schristos msg.msg_iovlen = 1; 62416776186Schristos msg.msg_control = control.buf; 6253b6c3722Schristos #ifndef S_SPLINT_S 62616776186Schristos msg.msg_controllen = sizeof(control.buf); 6273b6c3722Schristos #endif /* S_SPLINT_S */ 6283b6c3722Schristos msg.msg_flags = 0; 6293b6c3722Schristos 6303b6c3722Schristos #ifndef S_SPLINT_S 6313b6c3722Schristos cmsg = CMSG_FIRSTHDR(&msg); 6323b6c3722Schristos if(r->srctype == 4) { 6333b6c3722Schristos #ifdef IP_PKTINFO 6343b6c3722Schristos void* cmsg_data; 6353b6c3722Schristos msg.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo)); 63616776186Schristos log_assert(msg.msg_controllen <= sizeof(control.buf)); 6373b6c3722Schristos cmsg->cmsg_level = IPPROTO_IP; 6383b6c3722Schristos cmsg->cmsg_type = IP_PKTINFO; 6393b6c3722Schristos memmove(CMSG_DATA(cmsg), &r->pktinfo.v4info, 6403b6c3722Schristos sizeof(struct in_pktinfo)); 6413b6c3722Schristos /* unset the ifindex to not bypass the routing tables */ 6423b6c3722Schristos cmsg_data = CMSG_DATA(cmsg); 6433b6c3722Schristos ((struct in_pktinfo *) cmsg_data)->ipi_ifindex = 0; 6443b6c3722Schristos cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); 645*14b2fa6eSchristos /* zero the padding bytes inserted by the CMSG_LEN */ 646*14b2fa6eSchristos if(sizeof(struct in_pktinfo) < cmsg->cmsg_len) 647*14b2fa6eSchristos memset(((uint8_t*)(CMSG_DATA(cmsg))) + 648*14b2fa6eSchristos sizeof(struct in_pktinfo), 0, cmsg->cmsg_len 649*14b2fa6eSchristos - sizeof(struct in_pktinfo)); 6503b6c3722Schristos #elif defined(IP_SENDSRCADDR) 6513b6c3722Schristos msg.msg_controllen = CMSG_SPACE(sizeof(struct in_addr)); 65216776186Schristos log_assert(msg.msg_controllen <= sizeof(control.buf)); 6533b6c3722Schristos cmsg->cmsg_level = IPPROTO_IP; 6543b6c3722Schristos cmsg->cmsg_type = IP_SENDSRCADDR; 6553b6c3722Schristos memmove(CMSG_DATA(cmsg), &r->pktinfo.v4addr, 6563b6c3722Schristos sizeof(struct in_addr)); 6573b6c3722Schristos cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr)); 658*14b2fa6eSchristos /* zero the padding bytes inserted by the CMSG_LEN */ 659*14b2fa6eSchristos if(sizeof(struct in_addr) < cmsg->cmsg_len) 660*14b2fa6eSchristos memset(((uint8_t*)(CMSG_DATA(cmsg))) + 661*14b2fa6eSchristos sizeof(struct in_addr), 0, cmsg->cmsg_len 662*14b2fa6eSchristos - sizeof(struct in_addr)); 6633b6c3722Schristos #else 6643b6c3722Schristos verbose(VERB_ALGO, "no IP_PKTINFO or IP_SENDSRCADDR"); 6653b6c3722Schristos msg.msg_control = NULL; 6663b6c3722Schristos #endif /* IP_PKTINFO or IP_SENDSRCADDR */ 6673b6c3722Schristos } else if(r->srctype == 6) { 6683b6c3722Schristos void* cmsg_data; 6693b6c3722Schristos msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); 67016776186Schristos log_assert(msg.msg_controllen <= sizeof(control.buf)); 6713b6c3722Schristos cmsg->cmsg_level = IPPROTO_IPV6; 6723b6c3722Schristos cmsg->cmsg_type = IPV6_PKTINFO; 6733b6c3722Schristos memmove(CMSG_DATA(cmsg), &r->pktinfo.v6info, 6743b6c3722Schristos sizeof(struct in6_pktinfo)); 6753b6c3722Schristos /* unset the ifindex to not bypass the routing tables */ 6763b6c3722Schristos cmsg_data = CMSG_DATA(cmsg); 6773b6c3722Schristos ((struct in6_pktinfo *) cmsg_data)->ipi6_ifindex = 0; 6783b6c3722Schristos cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 679*14b2fa6eSchristos /* zero the padding bytes inserted by the CMSG_LEN */ 680*14b2fa6eSchristos if(sizeof(struct in6_pktinfo) < cmsg->cmsg_len) 681*14b2fa6eSchristos memset(((uint8_t*)(CMSG_DATA(cmsg))) + 682*14b2fa6eSchristos sizeof(struct in6_pktinfo), 0, cmsg->cmsg_len 683*14b2fa6eSchristos - sizeof(struct in6_pktinfo)); 6843b6c3722Schristos } else { 6853b6c3722Schristos /* try to pass all 0 to use default route */ 6863b6c3722Schristos msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); 68716776186Schristos log_assert(msg.msg_controllen <= sizeof(control.buf)); 6883b6c3722Schristos cmsg->cmsg_level = IPPROTO_IPV6; 6893b6c3722Schristos cmsg->cmsg_type = IPV6_PKTINFO; 6903b6c3722Schristos memset(CMSG_DATA(cmsg), 0, sizeof(struct in6_pktinfo)); 6913b6c3722Schristos cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 692*14b2fa6eSchristos /* zero the padding bytes inserted by the CMSG_LEN */ 693*14b2fa6eSchristos if(sizeof(struct in6_pktinfo) < cmsg->cmsg_len) 694*14b2fa6eSchristos memset(((uint8_t*)(CMSG_DATA(cmsg))) + 695*14b2fa6eSchristos sizeof(struct in6_pktinfo), 0, cmsg->cmsg_len 696*14b2fa6eSchristos - sizeof(struct in6_pktinfo)); 6973b6c3722Schristos } 6983b6c3722Schristos #endif /* S_SPLINT_S */ 699*14b2fa6eSchristos if(verbosity >= VERB_ALGO && r->srctype != 0) 7003b6c3722Schristos p_ancil("send_udp over interface", r); 7013b6c3722Schristos sent = sendmsg(c->fd, &msg, 0); 7023b6c3722Schristos if(sent == -1) { 7033b6c3722Schristos /* try again and block, waiting for IO to complete, 7043b6c3722Schristos * we want to send the answer, and we will wait for 7053b6c3722Schristos * the ethernet interface buffer to have space. */ 7063b6c3722Schristos #ifndef USE_WINSOCK 707*14b2fa6eSchristos if(errno == EAGAIN || errno == EINTR || 7083b6c3722Schristos # ifdef EWOULDBLOCK 7093b6c3722Schristos errno == EWOULDBLOCK || 7103b6c3722Schristos # endif 7113b6c3722Schristos errno == ENOBUFS) { 7123b6c3722Schristos #else 7133b6c3722Schristos if(WSAGetLastError() == WSAEINPROGRESS || 714*14b2fa6eSchristos WSAGetLastError() == WSAEINTR || 7153b6c3722Schristos WSAGetLastError() == WSAENOBUFS || 7163b6c3722Schristos WSAGetLastError() == WSAEWOULDBLOCK) { 7173b6c3722Schristos #endif 718*14b2fa6eSchristos int retries = 0; 719*14b2fa6eSchristos while(sent == -1 && retries < SEND_BLOCKED_MAX_RETRY && ( 720*14b2fa6eSchristos #ifndef USE_WINSOCK 721*14b2fa6eSchristos errno == EAGAIN || errno == EINTR || 722*14b2fa6eSchristos # ifdef EWOULDBLOCK 723*14b2fa6eSchristos errno == EWOULDBLOCK || 724*14b2fa6eSchristos # endif 725*14b2fa6eSchristos errno == ENOBUFS 726*14b2fa6eSchristos #else 727*14b2fa6eSchristos WSAGetLastError() == WSAEINPROGRESS || 728*14b2fa6eSchristos WSAGetLastError() == WSAEINTR || 729*14b2fa6eSchristos WSAGetLastError() == WSAENOBUFS || 730*14b2fa6eSchristos WSAGetLastError() == WSAEWOULDBLOCK 731*14b2fa6eSchristos #endif 732*14b2fa6eSchristos )) { 733*14b2fa6eSchristos #if defined(HAVE_POLL) || defined(USE_WINSOCK) 734*14b2fa6eSchristos int send_nobufs = ( 735*14b2fa6eSchristos #ifndef USE_WINSOCK 736*14b2fa6eSchristos errno == ENOBUFS 737*14b2fa6eSchristos #else 738*14b2fa6eSchristos WSAGetLastError() == WSAENOBUFS 739*14b2fa6eSchristos #endif 740*14b2fa6eSchristos ); 741*14b2fa6eSchristos struct pollfd p; 742*14b2fa6eSchristos int pret; 743*14b2fa6eSchristos memset(&p, 0, sizeof(p)); 744*14b2fa6eSchristos p.fd = c->fd; 745*14b2fa6eSchristos p.events = POLLOUT | POLLERR | POLLHUP; 746*14b2fa6eSchristos # ifndef USE_WINSOCK 747*14b2fa6eSchristos pret = poll(&p, 1, SEND_BLOCKED_WAIT_TIMEOUT); 748*14b2fa6eSchristos # else 749*14b2fa6eSchristos pret = WSAPoll(&p, 1, 750*14b2fa6eSchristos SEND_BLOCKED_WAIT_TIMEOUT); 751*14b2fa6eSchristos # endif 752*14b2fa6eSchristos if(pret == 0) { 753*14b2fa6eSchristos /* timer expired */ 754*14b2fa6eSchristos struct comm_base* b = c->ev->base; 755*14b2fa6eSchristos if(b->eb->last_writewait_log+SLOW_LOG_TIME <= 756*14b2fa6eSchristos b->eb->secs) { 757*14b2fa6eSchristos b->eb->last_writewait_log = b->eb->secs; 758*14b2fa6eSchristos verbose(VERB_OPS, "send udp blocked " 759*14b2fa6eSchristos "for long, dropping packet."); 760*14b2fa6eSchristos } 761*14b2fa6eSchristos return 0; 762*14b2fa6eSchristos } else if(pret < 0 && 763*14b2fa6eSchristos #ifndef USE_WINSOCK 764*14b2fa6eSchristos errno != EAGAIN && errno != EINTR && 765*14b2fa6eSchristos # ifdef EWOULDBLOCK 766*14b2fa6eSchristos errno != EWOULDBLOCK && 767*14b2fa6eSchristos # endif 768*14b2fa6eSchristos errno != ENOBUFS 769*14b2fa6eSchristos #else 770*14b2fa6eSchristos WSAGetLastError() != WSAEINPROGRESS && 771*14b2fa6eSchristos WSAGetLastError() != WSAEINTR && 772*14b2fa6eSchristos WSAGetLastError() != WSAENOBUFS && 773*14b2fa6eSchristos WSAGetLastError() != WSAEWOULDBLOCK 774*14b2fa6eSchristos #endif 775*14b2fa6eSchristos ) { 776*14b2fa6eSchristos log_err("poll udp out failed: %s", 777*14b2fa6eSchristos sock_strerror(errno)); 778*14b2fa6eSchristos return 0; 779*14b2fa6eSchristos } else if((pret < 0 && 780*14b2fa6eSchristos #ifndef USE_WINSOCK 781*14b2fa6eSchristos errno == ENOBUFS 782*14b2fa6eSchristos #else 783*14b2fa6eSchristos WSAGetLastError() == WSAENOBUFS 784*14b2fa6eSchristos #endif 785*14b2fa6eSchristos ) || (send_nobufs && retries > 0)) { 786*14b2fa6eSchristos /* ENOBUFS, and poll returned without 787*14b2fa6eSchristos * a timeout. Or the retried send call 788*14b2fa6eSchristos * returned ENOBUFS. It is good to 789*14b2fa6eSchristos * wait a bit for the error to clear. */ 790*14b2fa6eSchristos /* The timeout is 20*(2^(retries+1)), 791*14b2fa6eSchristos * it increases exponentially, starting 792*14b2fa6eSchristos * at 40 msec. After 5 tries, 1240 msec 793*14b2fa6eSchristos * have passed in total, when poll 794*14b2fa6eSchristos * returned the error, and 1200 msec 795*14b2fa6eSchristos * when send returned the errors. */ 796*14b2fa6eSchristos #ifndef USE_WINSOCK 797*14b2fa6eSchristos pret = poll(NULL, 0, (SEND_BLOCKED_WAIT_TIMEOUT/10)<<(retries+1)); 798*14b2fa6eSchristos #else 799*14b2fa6eSchristos pret = WSAPoll(NULL, 0, (SEND_BLOCKED_WAIT_TIMEOUT/10)<<(retries+1)); 800*14b2fa6eSchristos #endif 801*14b2fa6eSchristos if(pret < 0 && 802*14b2fa6eSchristos #ifndef USE_WINSOCK 803*14b2fa6eSchristos errno != EAGAIN && errno != EINTR && 804*14b2fa6eSchristos # ifdef EWOULDBLOCK 805*14b2fa6eSchristos errno != EWOULDBLOCK && 806*14b2fa6eSchristos # endif 807*14b2fa6eSchristos errno != ENOBUFS 808*14b2fa6eSchristos #else 809*14b2fa6eSchristos WSAGetLastError() != WSAEINPROGRESS && 810*14b2fa6eSchristos WSAGetLastError() != WSAEINTR && 811*14b2fa6eSchristos WSAGetLastError() != WSAENOBUFS && 812*14b2fa6eSchristos WSAGetLastError() != WSAEWOULDBLOCK 813*14b2fa6eSchristos #endif 814*14b2fa6eSchristos ) { 815*14b2fa6eSchristos log_err("poll udp out timer failed: %s", 816*14b2fa6eSchristos sock_strerror(errno)); 817*14b2fa6eSchristos } 818*14b2fa6eSchristos } 819*14b2fa6eSchristos #endif /* defined(HAVE_POLL) || defined(USE_WINSOCK) */ 820*14b2fa6eSchristos retries++; 8213b6c3722Schristos sent = sendmsg(c->fd, &msg, 0); 822*14b2fa6eSchristos } 8233b6c3722Schristos } 8243b6c3722Schristos } 8253b6c3722Schristos if(sent == -1) { 8263b6c3722Schristos if(!udp_send_errno_needs_log(addr, addrlen)) 8273b6c3722Schristos return 0; 8283b6c3722Schristos verbose(VERB_OPS, "sendmsg failed: %s", strerror(errno)); 8293b6c3722Schristos log_addr(VERB_OPS, "remote address is", 8303b6c3722Schristos (struct sockaddr_storage*)addr, addrlen); 8313b6c3722Schristos #ifdef __NetBSD__ 8323b6c3722Schristos /* netbsd 7 has IP_PKTINFO for recv but not send */ 8333b6c3722Schristos if(errno == EINVAL && r->srctype == 4) 8343b6c3722Schristos log_err("sendmsg: No support for sendmsg(IP_PKTINFO). " 8353b6c3722Schristos "Please disable interface-automatic"); 8363b6c3722Schristos #endif 8373b6c3722Schristos return 0; 8383b6c3722Schristos } else if((size_t)sent != sldns_buffer_remaining(packet)) { 8393b6c3722Schristos log_err("sent %d in place of %d bytes", 8403b6c3722Schristos (int)sent, (int)sldns_buffer_remaining(packet)); 8413b6c3722Schristos return 0; 8423b6c3722Schristos } 8433b6c3722Schristos return 1; 8443b6c3722Schristos #else 8453b6c3722Schristos (void)c; 8463b6c3722Schristos (void)packet; 8473b6c3722Schristos (void)addr; 8483b6c3722Schristos (void)addrlen; 8493b6c3722Schristos (void)r; 8503b6c3722Schristos log_err("sendmsg: IPV6_PKTINFO not supported"); 8513b6c3722Schristos return 0; 8523b6c3722Schristos #endif /* AF_INET6 && IPV6_PKTINFO && HAVE_SENDMSG */ 8533b6c3722Schristos } 8543b6c3722Schristos 85516776186Schristos /** return true is UDP receive error needs to be logged */ 85616776186Schristos static int udp_recv_needs_log(int err) 85716776186Schristos { 85816776186Schristos switch(err) { 85916776186Schristos case EACCES: /* some hosts send ICMP 'Permission Denied' */ 86016776186Schristos #ifndef USE_WINSOCK 86116776186Schristos case ECONNREFUSED: 86216776186Schristos # ifdef ENETUNREACH 86316776186Schristos case ENETUNREACH: 86416776186Schristos # endif 86516776186Schristos # ifdef EHOSTDOWN 86616776186Schristos case EHOSTDOWN: 86716776186Schristos # endif 86816776186Schristos # ifdef EHOSTUNREACH 86916776186Schristos case EHOSTUNREACH: 87016776186Schristos # endif 87116776186Schristos # ifdef ENETDOWN 87216776186Schristos case ENETDOWN: 87316776186Schristos # endif 87416776186Schristos #else /* USE_WINSOCK */ 87516776186Schristos case WSAECONNREFUSED: 87616776186Schristos case WSAENETUNREACH: 87716776186Schristos case WSAEHOSTDOWN: 87816776186Schristos case WSAEHOSTUNREACH: 87916776186Schristos case WSAENETDOWN: 88016776186Schristos #endif 88116776186Schristos if(verbosity >= VERB_ALGO) 88216776186Schristos return 1; 88316776186Schristos return 0; 88416776186Schristos default: 88516776186Schristos break; 88616776186Schristos } 88716776186Schristos return 1; 88816776186Schristos } 88916776186Schristos 890*14b2fa6eSchristos /** Parses the PROXYv2 header from buf and updates the comm_reply struct. 891*14b2fa6eSchristos * Returns 1 on success, 0 on failure. */ 892*14b2fa6eSchristos static int consume_pp2_header(struct sldns_buffer* buf, struct comm_reply* rep, 893*14b2fa6eSchristos int stream) { 894*14b2fa6eSchristos size_t size; 895*14b2fa6eSchristos struct pp2_header *header; 896*14b2fa6eSchristos int err = pp2_read_header(sldns_buffer_begin(buf), 897*14b2fa6eSchristos sldns_buffer_remaining(buf)); 898*14b2fa6eSchristos if(err) return 0; 899*14b2fa6eSchristos header = (struct pp2_header*)sldns_buffer_begin(buf); 900*14b2fa6eSchristos size = PP2_HEADER_SIZE + ntohs(header->len); 901*14b2fa6eSchristos if((header->ver_cmd & 0xF) == PP2_CMD_LOCAL) { 902*14b2fa6eSchristos /* A connection from the proxy itself. 903*14b2fa6eSchristos * No need to do anything with addresses. */ 904*14b2fa6eSchristos goto done; 905*14b2fa6eSchristos } 906*14b2fa6eSchristos if(header->fam_prot == PP2_UNSPEC_UNSPEC) { 907*14b2fa6eSchristos /* Unspecified family and protocol. This could be used for 908*14b2fa6eSchristos * health checks by proxies. 909*14b2fa6eSchristos * No need to do anything with addresses. */ 910*14b2fa6eSchristos goto done; 911*14b2fa6eSchristos } 912*14b2fa6eSchristos /* Read the proxied address */ 913*14b2fa6eSchristos switch(header->fam_prot) { 914*14b2fa6eSchristos case PP2_INET_STREAM: 915*14b2fa6eSchristos case PP2_INET_DGRAM: 916*14b2fa6eSchristos { 917*14b2fa6eSchristos struct sockaddr_in* addr = 918*14b2fa6eSchristos (struct sockaddr_in*)&rep->client_addr; 919*14b2fa6eSchristos addr->sin_family = AF_INET; 920*14b2fa6eSchristos addr->sin_addr.s_addr = header->addr.addr4.src_addr; 921*14b2fa6eSchristos addr->sin_port = header->addr.addr4.src_port; 922*14b2fa6eSchristos rep->client_addrlen = (socklen_t)sizeof(struct sockaddr_in); 923*14b2fa6eSchristos } 924*14b2fa6eSchristos /* Ignore the destination address; it should be us. */ 925*14b2fa6eSchristos break; 926*14b2fa6eSchristos case PP2_INET6_STREAM: 927*14b2fa6eSchristos case PP2_INET6_DGRAM: 928*14b2fa6eSchristos { 929*14b2fa6eSchristos struct sockaddr_in6* addr = 930*14b2fa6eSchristos (struct sockaddr_in6*)&rep->client_addr; 931*14b2fa6eSchristos memset(addr, 0, sizeof(*addr)); 932*14b2fa6eSchristos addr->sin6_family = AF_INET6; 933*14b2fa6eSchristos memcpy(&addr->sin6_addr, 934*14b2fa6eSchristos header->addr.addr6.src_addr, 16); 935*14b2fa6eSchristos addr->sin6_port = header->addr.addr6.src_port; 936*14b2fa6eSchristos rep->client_addrlen = (socklen_t)sizeof(struct sockaddr_in6); 937*14b2fa6eSchristos } 938*14b2fa6eSchristos /* Ignore the destination address; it should be us. */ 939*14b2fa6eSchristos break; 940*14b2fa6eSchristos default: 941*14b2fa6eSchristos log_err("proxy_protocol: unsupported family and " 942*14b2fa6eSchristos "protocol 0x%x", (int)header->fam_prot); 943*14b2fa6eSchristos return 0; 944*14b2fa6eSchristos } 945*14b2fa6eSchristos rep->is_proxied = 1; 946*14b2fa6eSchristos done: 947*14b2fa6eSchristos if(!stream) { 948*14b2fa6eSchristos /* We are reading a whole packet; 949*14b2fa6eSchristos * Move the rest of the data to overwrite the PROXYv2 header */ 950*14b2fa6eSchristos /* XXX can we do better to avoid memmove? */ 951*14b2fa6eSchristos memmove(header, ((char*)header)+size, 952*14b2fa6eSchristos sldns_buffer_limit(buf)-size); 953*14b2fa6eSchristos sldns_buffer_set_limit(buf, sldns_buffer_limit(buf)-size); 954*14b2fa6eSchristos } 955*14b2fa6eSchristos return 1; 956*14b2fa6eSchristos } 957*14b2fa6eSchristos 958*14b2fa6eSchristos #if defined(AF_INET6) && defined(IPV6_PKTINFO) && defined(HAVE_RECVMSG) 9593b6c3722Schristos void 9603b6c3722Schristos comm_point_udp_ancil_callback(int fd, short event, void* arg) 9613b6c3722Schristos { 9623b6c3722Schristos struct comm_reply rep; 9633b6c3722Schristos struct msghdr msg; 9643b6c3722Schristos struct iovec iov[1]; 9653b6c3722Schristos ssize_t rcv; 96616776186Schristos union { 96716776186Schristos struct cmsghdr hdr; 96816776186Schristos char buf[256]; 96916776186Schristos } ancil; 9703b6c3722Schristos int i; 9713b6c3722Schristos #ifndef S_SPLINT_S 9723b6c3722Schristos struct cmsghdr* cmsg; 9733b6c3722Schristos #endif /* S_SPLINT_S */ 974*14b2fa6eSchristos #ifdef HAVE_LINUX_NET_TSTAMP_H 975*14b2fa6eSchristos struct timespec *ts; 976*14b2fa6eSchristos #endif /* HAVE_LINUX_NET_TSTAMP_H */ 9773b6c3722Schristos 9783b6c3722Schristos rep.c = (struct comm_point*)arg; 9793b6c3722Schristos log_assert(rep.c->type == comm_udp); 9803b6c3722Schristos 9813b6c3722Schristos if(!(event&UB_EV_READ)) 9823b6c3722Schristos return; 9833b6c3722Schristos log_assert(rep.c && rep.c->buffer && rep.c->fd == fd); 9843b6c3722Schristos ub_comm_base_now(rep.c->ev->base); 9853b6c3722Schristos for(i=0; i<NUM_UDP_PER_SELECT; i++) { 9863b6c3722Schristos sldns_buffer_clear(rep.c->buffer); 987*14b2fa6eSchristos timeval_clear(&rep.c->recv_tv); 988*14b2fa6eSchristos rep.remote_addrlen = (socklen_t)sizeof(rep.remote_addr); 9893b6c3722Schristos log_assert(fd != -1); 9903b6c3722Schristos log_assert(sldns_buffer_remaining(rep.c->buffer) > 0); 991*14b2fa6eSchristos msg.msg_name = &rep.remote_addr; 992*14b2fa6eSchristos msg.msg_namelen = (socklen_t)sizeof(rep.remote_addr); 9933b6c3722Schristos iov[0].iov_base = sldns_buffer_begin(rep.c->buffer); 9943b6c3722Schristos iov[0].iov_len = sldns_buffer_remaining(rep.c->buffer); 9953b6c3722Schristos msg.msg_iov = iov; 9963b6c3722Schristos msg.msg_iovlen = 1; 99716776186Schristos msg.msg_control = ancil.buf; 9983b6c3722Schristos #ifndef S_SPLINT_S 99916776186Schristos msg.msg_controllen = sizeof(ancil.buf); 10003b6c3722Schristos #endif /* S_SPLINT_S */ 10013b6c3722Schristos msg.msg_flags = 0; 1002*14b2fa6eSchristos rcv = recvmsg(fd, &msg, MSG_DONTWAIT); 10033b6c3722Schristos if(rcv == -1) { 100416776186Schristos if(errno != EAGAIN && errno != EINTR 100516776186Schristos && udp_recv_needs_log(errno)) { 10063b6c3722Schristos log_err("recvmsg failed: %s", strerror(errno)); 10073b6c3722Schristos } 10083b6c3722Schristos return; 10093b6c3722Schristos } 1010*14b2fa6eSchristos rep.remote_addrlen = msg.msg_namelen; 10113b6c3722Schristos sldns_buffer_skip(rep.c->buffer, rcv); 10123b6c3722Schristos sldns_buffer_flip(rep.c->buffer); 10133b6c3722Schristos rep.srctype = 0; 1014*14b2fa6eSchristos rep.is_proxied = 0; 10153b6c3722Schristos #ifndef S_SPLINT_S 10163b6c3722Schristos for(cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; 10173b6c3722Schristos cmsg = CMSG_NXTHDR(&msg, cmsg)) { 10183b6c3722Schristos if( cmsg->cmsg_level == IPPROTO_IPV6 && 10193b6c3722Schristos cmsg->cmsg_type == IPV6_PKTINFO) { 10203b6c3722Schristos rep.srctype = 6; 10213b6c3722Schristos memmove(&rep.pktinfo.v6info, CMSG_DATA(cmsg), 10223b6c3722Schristos sizeof(struct in6_pktinfo)); 10233b6c3722Schristos break; 10243b6c3722Schristos #ifdef IP_PKTINFO 10253b6c3722Schristos } else if( cmsg->cmsg_level == IPPROTO_IP && 10263b6c3722Schristos cmsg->cmsg_type == IP_PKTINFO) { 10273b6c3722Schristos rep.srctype = 4; 10283b6c3722Schristos memmove(&rep.pktinfo.v4info, CMSG_DATA(cmsg), 10293b6c3722Schristos sizeof(struct in_pktinfo)); 10303b6c3722Schristos break; 10313b6c3722Schristos #elif defined(IP_RECVDSTADDR) 10323b6c3722Schristos } else if( cmsg->cmsg_level == IPPROTO_IP && 10333b6c3722Schristos cmsg->cmsg_type == IP_RECVDSTADDR) { 10343b6c3722Schristos rep.srctype = 4; 10353b6c3722Schristos memmove(&rep.pktinfo.v4addr, CMSG_DATA(cmsg), 10363b6c3722Schristos sizeof(struct in_addr)); 10373b6c3722Schristos break; 10383b6c3722Schristos #endif /* IP_PKTINFO or IP_RECVDSTADDR */ 1039*14b2fa6eSchristos #ifdef HAVE_LINUX_NET_TSTAMP_H 1040*14b2fa6eSchristos } else if( cmsg->cmsg_level == SOL_SOCKET && 1041*14b2fa6eSchristos cmsg->cmsg_type == SO_TIMESTAMPNS) { 1042*14b2fa6eSchristos ts = (struct timespec *)CMSG_DATA(cmsg); 1043*14b2fa6eSchristos TIMESPEC_TO_TIMEVAL(&rep.c->recv_tv, ts); 1044*14b2fa6eSchristos } else if( cmsg->cmsg_level == SOL_SOCKET && 1045*14b2fa6eSchristos cmsg->cmsg_type == SO_TIMESTAMPING) { 1046*14b2fa6eSchristos ts = (struct timespec *)CMSG_DATA(cmsg); 1047*14b2fa6eSchristos TIMESPEC_TO_TIMEVAL(&rep.c->recv_tv, ts); 1048*14b2fa6eSchristos } else if( cmsg->cmsg_level == SOL_SOCKET && 1049*14b2fa6eSchristos cmsg->cmsg_type == SO_TIMESTAMP) { 1050*14b2fa6eSchristos memmove(&rep.c->recv_tv, CMSG_DATA(cmsg), sizeof(struct timeval)); 1051*14b2fa6eSchristos #endif /* HAVE_LINUX_NET_TSTAMP_H */ 10523b6c3722Schristos } 10533b6c3722Schristos } 1054*14b2fa6eSchristos 1055*14b2fa6eSchristos if(verbosity >= VERB_ALGO && rep.srctype != 0) 10563b6c3722Schristos p_ancil("receive_udp on interface", &rep); 10573b6c3722Schristos #endif /* S_SPLINT_S */ 1058*14b2fa6eSchristos 1059*14b2fa6eSchristos if(rep.c->pp2_enabled && !consume_pp2_header(rep.c->buffer, 1060*14b2fa6eSchristos &rep, 0)) { 1061*14b2fa6eSchristos log_err("proxy_protocol: could not consume PROXYv2 header"); 1062*14b2fa6eSchristos return; 1063*14b2fa6eSchristos } 1064*14b2fa6eSchristos if(!rep.is_proxied) { 1065*14b2fa6eSchristos rep.client_addrlen = rep.remote_addrlen; 1066*14b2fa6eSchristos memmove(&rep.client_addr, &rep.remote_addr, 1067*14b2fa6eSchristos rep.remote_addrlen); 1068*14b2fa6eSchristos } 1069*14b2fa6eSchristos 10703b6c3722Schristos fptr_ok(fptr_whitelist_comm_point(rep.c->callback)); 10713b6c3722Schristos if((*rep.c->callback)(rep.c, rep.c->cb_arg, NETEVENT_NOERROR, &rep)) { 10723b6c3722Schristos /* send back immediate reply */ 1073*14b2fa6eSchristos struct sldns_buffer *buffer; 1074*14b2fa6eSchristos #ifdef USE_DNSCRYPT 1075*14b2fa6eSchristos buffer = rep.c->dnscrypt_buffer; 1076*14b2fa6eSchristos #else 1077*14b2fa6eSchristos buffer = rep.c->buffer; 1078*14b2fa6eSchristos #endif 1079*14b2fa6eSchristos (void)comm_point_send_udp_msg_if(rep.c, buffer, 1080*14b2fa6eSchristos (struct sockaddr*)&rep.remote_addr, 1081*14b2fa6eSchristos rep.remote_addrlen, &rep); 10823b6c3722Schristos } 10837cd94d69Schristos if(!rep.c || rep.c->fd == -1) /* commpoint closed */ 10843b6c3722Schristos break; 10853b6c3722Schristos } 10863b6c3722Schristos } 1087*14b2fa6eSchristos #endif /* AF_INET6 && IPV6_PKTINFO && HAVE_RECVMSG */ 10883b6c3722Schristos 10893b6c3722Schristos void 10903b6c3722Schristos comm_point_udp_callback(int fd, short event, void* arg) 10913b6c3722Schristos { 10923b6c3722Schristos struct comm_reply rep; 10933b6c3722Schristos ssize_t rcv; 10943b6c3722Schristos int i; 10950cd9f4ecSchristos struct sldns_buffer *buffer; 10963b6c3722Schristos 10973b6c3722Schristos rep.c = (struct comm_point*)arg; 10983b6c3722Schristos log_assert(rep.c->type == comm_udp); 10993b6c3722Schristos 11003b6c3722Schristos if(!(event&UB_EV_READ)) 11013b6c3722Schristos return; 11023b6c3722Schristos log_assert(rep.c && rep.c->buffer && rep.c->fd == fd); 11033b6c3722Schristos ub_comm_base_now(rep.c->ev->base); 11043b6c3722Schristos for(i=0; i<NUM_UDP_PER_SELECT; i++) { 11053b6c3722Schristos sldns_buffer_clear(rep.c->buffer); 1106*14b2fa6eSchristos rep.remote_addrlen = (socklen_t)sizeof(rep.remote_addr); 11073b6c3722Schristos log_assert(fd != -1); 11083b6c3722Schristos log_assert(sldns_buffer_remaining(rep.c->buffer) > 0); 11093b6c3722Schristos rcv = recvfrom(fd, (void*)sldns_buffer_begin(rep.c->buffer), 1110*14b2fa6eSchristos sldns_buffer_remaining(rep.c->buffer), MSG_DONTWAIT, 1111*14b2fa6eSchristos (struct sockaddr*)&rep.remote_addr, &rep.remote_addrlen); 11123b6c3722Schristos if(rcv == -1) { 11133b6c3722Schristos #ifndef USE_WINSOCK 111416776186Schristos if(errno != EAGAIN && errno != EINTR 111516776186Schristos && udp_recv_needs_log(errno)) 11163b6c3722Schristos log_err("recvfrom %d failed: %s", 11173b6c3722Schristos fd, strerror(errno)); 11183b6c3722Schristos #else 11193b6c3722Schristos if(WSAGetLastError() != WSAEINPROGRESS && 11203b6c3722Schristos WSAGetLastError() != WSAECONNRESET && 112116776186Schristos WSAGetLastError()!= WSAEWOULDBLOCK && 112216776186Schristos udp_recv_needs_log(WSAGetLastError())) 11233b6c3722Schristos log_err("recvfrom failed: %s", 11243b6c3722Schristos wsa_strerror(WSAGetLastError())); 11253b6c3722Schristos #endif 11263b6c3722Schristos return; 11273b6c3722Schristos } 11283b6c3722Schristos sldns_buffer_skip(rep.c->buffer, rcv); 11293b6c3722Schristos sldns_buffer_flip(rep.c->buffer); 11303b6c3722Schristos rep.srctype = 0; 1131*14b2fa6eSchristos rep.is_proxied = 0; 1132*14b2fa6eSchristos 1133*14b2fa6eSchristos if(rep.c->pp2_enabled && !consume_pp2_header(rep.c->buffer, 1134*14b2fa6eSchristos &rep, 0)) { 1135*14b2fa6eSchristos log_err("proxy_protocol: could not consume PROXYv2 header"); 1136*14b2fa6eSchristos return; 1137*14b2fa6eSchristos } 1138*14b2fa6eSchristos if(!rep.is_proxied) { 1139*14b2fa6eSchristos rep.client_addrlen = rep.remote_addrlen; 1140*14b2fa6eSchristos memmove(&rep.client_addr, &rep.remote_addr, 1141*14b2fa6eSchristos rep.remote_addrlen); 1142*14b2fa6eSchristos } 1143*14b2fa6eSchristos 11443b6c3722Schristos fptr_ok(fptr_whitelist_comm_point(rep.c->callback)); 11453b6c3722Schristos if((*rep.c->callback)(rep.c, rep.c->cb_arg, NETEVENT_NOERROR, &rep)) { 11463b6c3722Schristos /* send back immediate reply */ 11470cd9f4ecSchristos #ifdef USE_DNSCRYPT 11480cd9f4ecSchristos buffer = rep.c->dnscrypt_buffer; 11490cd9f4ecSchristos #else 11500cd9f4ecSchristos buffer = rep.c->buffer; 11510cd9f4ecSchristos #endif 11520cd9f4ecSchristos (void)comm_point_send_udp_msg(rep.c, buffer, 1153*14b2fa6eSchristos (struct sockaddr*)&rep.remote_addr, 1154*14b2fa6eSchristos rep.remote_addrlen, 0); 11553b6c3722Schristos } 11567cd94d69Schristos if(!rep.c || rep.c->fd != fd) /* commpoint closed to -1 or reused for 11573b6c3722Schristos another UDP port. Note rep.c cannot be reused with TCP fd. */ 11583b6c3722Schristos break; 11593b6c3722Schristos } 11603b6c3722Schristos } 11613b6c3722Schristos 116216776186Schristos int adjusted_tcp_timeout(struct comm_point* c) 116316776186Schristos { 116416776186Schristos if(c->tcp_timeout_msec < TCP_QUERY_TIMEOUT_MINIMUM) 116516776186Schristos return TCP_QUERY_TIMEOUT_MINIMUM; 116616776186Schristos return c->tcp_timeout_msec; 116716776186Schristos } 116816776186Schristos 11693b6c3722Schristos /** Use a new tcp handler for new query fd, set to read query */ 11703b6c3722Schristos static void 11710cd9f4ecSchristos setup_tcp_handler(struct comm_point* c, int fd, int cur, int max) 11723b6c3722Schristos { 1173f42d8de7Schristos int handler_usage; 117416776186Schristos log_assert(c->type == comm_tcp || c->type == comm_http); 11753b6c3722Schristos log_assert(c->fd == -1); 11763b6c3722Schristos sldns_buffer_clear(c->buffer); 11770cd9f4ecSchristos #ifdef USE_DNSCRYPT 11780cd9f4ecSchristos if (c->dnscrypt) 11790cd9f4ecSchristos sldns_buffer_clear(c->dnscrypt_buffer); 11800cd9f4ecSchristos #endif 11813b6c3722Schristos c->tcp_is_reading = 1; 11823b6c3722Schristos c->tcp_byte_count = 0; 11831481e2a9Schristos c->tcp_keepalive = 0; 11840cd9f4ecSchristos /* if more than half the tcp handlers are in use, use a shorter 11850cd9f4ecSchristos * timeout for this TCP connection, we need to make space for 11860cd9f4ecSchristos * other connections to be able to get attention */ 1187f42d8de7Schristos /* If > 50% TCP handler structures in use, set timeout to 1/100th 1188f42d8de7Schristos * configured value. 1189f42d8de7Schristos * If > 65%TCP handler structures in use, set to 1/500th configured 1190f42d8de7Schristos * value. 1191f42d8de7Schristos * If > 80% TCP handler structures in use, set to 0. 1192f42d8de7Schristos * 1193f42d8de7Schristos * If the timeout to use falls below 200 milliseconds, an actual 1194f42d8de7Schristos * timeout of 200ms is used. 1195f42d8de7Schristos */ 1196f42d8de7Schristos handler_usage = (cur * 100) / max; 1197f42d8de7Schristos if(handler_usage > 50 && handler_usage <= 65) 1198f42d8de7Schristos c->tcp_timeout_msec /= 100; 1199f42d8de7Schristos else if (handler_usage > 65 && handler_usage <= 80) 1200f42d8de7Schristos c->tcp_timeout_msec /= 500; 1201f42d8de7Schristos else if (handler_usage > 80) 1202f42d8de7Schristos c->tcp_timeout_msec = 0; 120316776186Schristos comm_point_start_listening(c, fd, adjusted_tcp_timeout(c)); 12043b6c3722Schristos } 12053b6c3722Schristos 12063b6c3722Schristos void comm_base_handle_slow_accept(int ATTR_UNUSED(fd), 12073b6c3722Schristos short ATTR_UNUSED(event), void* arg) 12083b6c3722Schristos { 12093b6c3722Schristos struct comm_base* b = (struct comm_base*)arg; 12103b6c3722Schristos /* timeout for the slow accept, re-enable accepts again */ 12113b6c3722Schristos if(b->start_accept) { 12123b6c3722Schristos verbose(VERB_ALGO, "wait is over, slow accept disabled"); 12133b6c3722Schristos fptr_ok(fptr_whitelist_start_accept(b->start_accept)); 12143b6c3722Schristos (*b->start_accept)(b->cb_arg); 12153b6c3722Schristos b->eb->slow_accept_enabled = 0; 12163b6c3722Schristos } 12173b6c3722Schristos } 12183b6c3722Schristos 12193b6c3722Schristos int comm_point_perform_accept(struct comm_point* c, 12203b6c3722Schristos struct sockaddr_storage* addr, socklen_t* addrlen) 12213b6c3722Schristos { 12223b6c3722Schristos int new_fd; 12233b6c3722Schristos *addrlen = (socklen_t)sizeof(*addr); 12247cd94d69Schristos #ifndef HAVE_ACCEPT4 12253b6c3722Schristos new_fd = accept(c->fd, (struct sockaddr*)addr, addrlen); 12267cd94d69Schristos #else 12277cd94d69Schristos /* SOCK_NONBLOCK saves extra calls to fcntl for the same result */ 12287cd94d69Schristos new_fd = accept4(c->fd, (struct sockaddr*)addr, addrlen, SOCK_NONBLOCK); 12297cd94d69Schristos #endif 12303b6c3722Schristos if(new_fd == -1) { 12313b6c3722Schristos #ifndef USE_WINSOCK 12323b6c3722Schristos /* EINTR is signal interrupt. others are closed connection. */ 12333b6c3722Schristos if( errno == EINTR || errno == EAGAIN 12343b6c3722Schristos #ifdef EWOULDBLOCK 12353b6c3722Schristos || errno == EWOULDBLOCK 12363b6c3722Schristos #endif 12373b6c3722Schristos #ifdef ECONNABORTED 12383b6c3722Schristos || errno == ECONNABORTED 12393b6c3722Schristos #endif 12403b6c3722Schristos #ifdef EPROTO 12413b6c3722Schristos || errno == EPROTO 12423b6c3722Schristos #endif /* EPROTO */ 12433b6c3722Schristos ) 12443b6c3722Schristos return -1; 12453b6c3722Schristos #if defined(ENFILE) && defined(EMFILE) 12463b6c3722Schristos if(errno == ENFILE || errno == EMFILE) { 12473b6c3722Schristos /* out of file descriptors, likely outside of our 12483b6c3722Schristos * control. stop accept() calls for some time */ 12493b6c3722Schristos if(c->ev->base->stop_accept) { 12503b6c3722Schristos struct comm_base* b = c->ev->base; 12513b6c3722Schristos struct timeval tv; 12523b6c3722Schristos verbose(VERB_ALGO, "out of file descriptors: " 12533b6c3722Schristos "slow accept"); 1254*14b2fa6eSchristos ub_comm_base_now(b); 1255*14b2fa6eSchristos if(b->eb->last_slow_log+SLOW_LOG_TIME <= 1256*14b2fa6eSchristos b->eb->secs) { 1257*14b2fa6eSchristos b->eb->last_slow_log = b->eb->secs; 1258*14b2fa6eSchristos verbose(VERB_OPS, "accept failed, " 1259*14b2fa6eSchristos "slow down accept for %d " 1260*14b2fa6eSchristos "msec: %s", 1261*14b2fa6eSchristos NETEVENT_SLOW_ACCEPT_TIME, 1262*14b2fa6eSchristos sock_strerror(errno)); 1263*14b2fa6eSchristos } 12643b6c3722Schristos b->eb->slow_accept_enabled = 1; 12653b6c3722Schristos fptr_ok(fptr_whitelist_stop_accept( 12663b6c3722Schristos b->stop_accept)); 12673b6c3722Schristos (*b->stop_accept)(b->cb_arg); 12683b6c3722Schristos /* set timeout, no mallocs */ 12693b6c3722Schristos tv.tv_sec = NETEVENT_SLOW_ACCEPT_TIME/1000; 12700cd9f4ecSchristos tv.tv_usec = (NETEVENT_SLOW_ACCEPT_TIME%1000)*1000; 12713b6c3722Schristos b->eb->slow_accept = ub_event_new(b->eb->base, 12723b6c3722Schristos -1, UB_EV_TIMEOUT, 12733b6c3722Schristos comm_base_handle_slow_accept, b); 12743b6c3722Schristos if(b->eb->slow_accept == NULL) { 12753b6c3722Schristos /* we do not want to log here, because 12763b6c3722Schristos * that would spam the logfiles. 12773b6c3722Schristos * error: "event_base_set failed." */ 12783b6c3722Schristos } 12793b6c3722Schristos else if(ub_event_add(b->eb->slow_accept, &tv) 12803b6c3722Schristos != 0) { 12813b6c3722Schristos /* we do not want to log here, 12823b6c3722Schristos * error: "event_add failed." */ 12833b6c3722Schristos } 1284*14b2fa6eSchristos } else { 1285*14b2fa6eSchristos log_err("accept, with no slow down, " 1286*14b2fa6eSchristos "failed: %s", sock_strerror(errno)); 12873b6c3722Schristos } 12883b6c3722Schristos return -1; 12893b6c3722Schristos } 12903b6c3722Schristos #endif 12913b6c3722Schristos #else /* USE_WINSOCK */ 12923b6c3722Schristos if(WSAGetLastError() == WSAEINPROGRESS || 12933b6c3722Schristos WSAGetLastError() == WSAECONNRESET) 12943b6c3722Schristos return -1; 12953b6c3722Schristos if(WSAGetLastError() == WSAEWOULDBLOCK) { 12963b6c3722Schristos ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_READ); 12973b6c3722Schristos return -1; 12983b6c3722Schristos } 12993b6c3722Schristos #endif 130016776186Schristos log_err_addr("accept failed", sock_strerror(errno), addr, 130116776186Schristos *addrlen); 13023b6c3722Schristos return -1; 13033b6c3722Schristos } 1304f42d8de7Schristos if(c->tcp_conn_limit && c->type == comm_tcp_accept) { 1305f42d8de7Schristos c->tcl_addr = tcl_addr_lookup(c->tcp_conn_limit, addr, *addrlen); 1306f42d8de7Schristos if(!tcl_new_connection(c->tcl_addr)) { 1307f42d8de7Schristos if(verbosity >= 3) 1308f42d8de7Schristos log_err_addr("accept rejected", 1309f42d8de7Schristos "connection limit exceeded", addr, *addrlen); 1310f42d8de7Schristos close(new_fd); 1311f42d8de7Schristos return -1; 1312f42d8de7Schristos } 1313f42d8de7Schristos } 13147cd94d69Schristos #ifndef HAVE_ACCEPT4 13153b6c3722Schristos fd_set_nonblock(new_fd); 13167cd94d69Schristos #endif 13173b6c3722Schristos return new_fd; 13183b6c3722Schristos } 13193b6c3722Schristos 13203b6c3722Schristos #ifdef USE_WINSOCK 13213b6c3722Schristos static long win_bio_cb(BIO *b, int oper, const char* ATTR_UNUSED(argp), 13221481e2a9Schristos #ifdef HAVE_BIO_SET_CALLBACK_EX 13231481e2a9Schristos size_t ATTR_UNUSED(len), 13241481e2a9Schristos #endif 13251481e2a9Schristos int ATTR_UNUSED(argi), long argl, 13261481e2a9Schristos #ifndef HAVE_BIO_SET_CALLBACK_EX 13271481e2a9Schristos long retvalue 13281481e2a9Schristos #else 13291481e2a9Schristos int retvalue, size_t* ATTR_UNUSED(processed) 13301481e2a9Schristos #endif 13311481e2a9Schristos ) 13323b6c3722Schristos { 13337cd94d69Schristos int wsa_err = WSAGetLastError(); /* store errcode before it is gone */ 13343b6c3722Schristos verbose(VERB_ALGO, "bio_cb %d, %s %s %s", oper, 13353b6c3722Schristos (oper&BIO_CB_RETURN)?"return":"before", 13363b6c3722Schristos (oper&BIO_CB_READ)?"read":((oper&BIO_CB_WRITE)?"write":"other"), 13377cd94d69Schristos wsa_err==WSAEWOULDBLOCK?"wsawb":""); 13383b6c3722Schristos /* on windows, check if previous operation caused EWOULDBLOCK */ 13393b6c3722Schristos if( (oper == (BIO_CB_READ|BIO_CB_RETURN) && argl == 0) || 13403b6c3722Schristos (oper == (BIO_CB_GETS|BIO_CB_RETURN) && argl == 0)) { 13417cd94d69Schristos if(wsa_err == WSAEWOULDBLOCK) 13423b6c3722Schristos ub_winsock_tcp_wouldblock((struct ub_event*) 13433b6c3722Schristos BIO_get_callback_arg(b), UB_EV_READ); 13443b6c3722Schristos } 13453b6c3722Schristos if( (oper == (BIO_CB_WRITE|BIO_CB_RETURN) && argl == 0) || 13463b6c3722Schristos (oper == (BIO_CB_PUTS|BIO_CB_RETURN) && argl == 0)) { 13477cd94d69Schristos if(wsa_err == WSAEWOULDBLOCK) 13483b6c3722Schristos ub_winsock_tcp_wouldblock((struct ub_event*) 13493b6c3722Schristos BIO_get_callback_arg(b), UB_EV_WRITE); 13503b6c3722Schristos } 13513b6c3722Schristos /* return original return value */ 13523b6c3722Schristos return retvalue; 13533b6c3722Schristos } 13543b6c3722Schristos 13553b6c3722Schristos /** set win bio callbacks for nonblocking operations */ 13563b6c3722Schristos void 13573b6c3722Schristos comm_point_tcp_win_bio_cb(struct comm_point* c, void* thessl) 13583b6c3722Schristos { 13593b6c3722Schristos SSL* ssl = (SSL*)thessl; 13603b6c3722Schristos /* set them both just in case, but usually they are the same BIO */ 13611481e2a9Schristos #ifdef HAVE_BIO_SET_CALLBACK_EX 13621481e2a9Schristos BIO_set_callback_ex(SSL_get_rbio(ssl), &win_bio_cb); 13631481e2a9Schristos #else 13643b6c3722Schristos BIO_set_callback(SSL_get_rbio(ssl), &win_bio_cb); 13651481e2a9Schristos #endif 13663b6c3722Schristos BIO_set_callback_arg(SSL_get_rbio(ssl), (char*)c->ev->ev); 13671481e2a9Schristos #ifdef HAVE_BIO_SET_CALLBACK_EX 13681481e2a9Schristos BIO_set_callback_ex(SSL_get_wbio(ssl), &win_bio_cb); 13691481e2a9Schristos #else 13703b6c3722Schristos BIO_set_callback(SSL_get_wbio(ssl), &win_bio_cb); 13711481e2a9Schristos #endif 13723b6c3722Schristos BIO_set_callback_arg(SSL_get_wbio(ssl), (char*)c->ev->ev); 13733b6c3722Schristos } 13743b6c3722Schristos #endif 13753b6c3722Schristos 137616776186Schristos #ifdef HAVE_NGHTTP2 137716776186Schristos /** Create http2 session server. Per connection, after TCP accepted.*/ 137816776186Schristos static int http2_session_server_create(struct http2_session* h2_session) 137916776186Schristos { 138016776186Schristos log_assert(h2_session->callbacks); 138116776186Schristos h2_session->is_drop = 0; 138216776186Schristos if(nghttp2_session_server_new(&h2_session->session, 138316776186Schristos h2_session->callbacks, 138416776186Schristos h2_session) == NGHTTP2_ERR_NOMEM) { 138516776186Schristos log_err("failed to create nghttp2 session server"); 138616776186Schristos return 0; 138716776186Schristos } 138816776186Schristos 138916776186Schristos return 1; 139016776186Schristos } 139116776186Schristos 139216776186Schristos /** Submit http2 setting to session. Once per session. */ 139316776186Schristos static int http2_submit_settings(struct http2_session* h2_session) 139416776186Schristos { 139516776186Schristos int ret; 139616776186Schristos nghttp2_settings_entry settings[1] = { 139716776186Schristos {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 139816776186Schristos h2_session->c->http2_max_streams}}; 139916776186Schristos 140016776186Schristos ret = nghttp2_submit_settings(h2_session->session, NGHTTP2_FLAG_NONE, 140116776186Schristos settings, 1); 140216776186Schristos if(ret) { 140316776186Schristos verbose(VERB_QUERY, "http2: submit_settings failed, " 140416776186Schristos "error: %s", nghttp2_strerror(ret)); 140516776186Schristos return 0; 140616776186Schristos } 140716776186Schristos return 1; 140816776186Schristos } 140916776186Schristos #endif /* HAVE_NGHTTP2 */ 141016776186Schristos 141116776186Schristos 14123b6c3722Schristos void 14133b6c3722Schristos comm_point_tcp_accept_callback(int fd, short event, void* arg) 14143b6c3722Schristos { 14153b6c3722Schristos struct comm_point* c = (struct comm_point*)arg, *c_hdl; 14163b6c3722Schristos int new_fd; 14173b6c3722Schristos log_assert(c->type == comm_tcp_accept); 14183b6c3722Schristos if(!(event & UB_EV_READ)) { 14193b6c3722Schristos log_info("ignoring tcp accept event %d", (int)event); 14203b6c3722Schristos return; 14213b6c3722Schristos } 14223b6c3722Schristos ub_comm_base_now(c->ev->base); 14233b6c3722Schristos /* find free tcp handler. */ 14243b6c3722Schristos if(!c->tcp_free) { 14253b6c3722Schristos log_warn("accepted too many tcp, connections full"); 14263b6c3722Schristos return; 14273b6c3722Schristos } 14283b6c3722Schristos /* accept incoming connection. */ 14293b6c3722Schristos c_hdl = c->tcp_free; 143087edd195Schristos /* clear leftover flags from previous use, and then set the 143187edd195Schristos * correct event base for the event structure for libevent */ 143287edd195Schristos ub_event_free(c_hdl->ev->ev); 14331481e2a9Schristos c_hdl->ev->ev = NULL; 143416776186Schristos if((c_hdl->type == comm_tcp && c_hdl->tcp_req_info) || 143516776186Schristos c_hdl->type == comm_local || c_hdl->type == comm_raw) 143616776186Schristos c_hdl->tcp_do_toggle_rw = 0; 143716776186Schristos else c_hdl->tcp_do_toggle_rw = 1; 143816776186Schristos 143916776186Schristos if(c_hdl->type == comm_http) { 144016776186Schristos #ifdef HAVE_NGHTTP2 144116776186Schristos if(!c_hdl->h2_session || 144216776186Schristos !http2_session_server_create(c_hdl->h2_session)) { 144316776186Schristos log_warn("failed to create nghttp2"); 144416776186Schristos return; 144516776186Schristos } 144616776186Schristos if(!c_hdl->h2_session || 144716776186Schristos !http2_submit_settings(c_hdl->h2_session)) { 144816776186Schristos log_warn("failed to submit http2 settings"); 144916776186Schristos return; 145016776186Schristos } 145116776186Schristos if(!c->ssl) { 145216776186Schristos c_hdl->tcp_do_toggle_rw = 0; 145316776186Schristos c_hdl->use_h2 = 1; 145416776186Schristos } 145516776186Schristos #endif 145616776186Schristos c_hdl->ev->ev = ub_event_new(c_hdl->ev->base->eb->base, -1, 145716776186Schristos UB_EV_PERSIST | UB_EV_READ | UB_EV_TIMEOUT, 145816776186Schristos comm_point_http_handle_callback, c_hdl); 145916776186Schristos } else { 146016776186Schristos c_hdl->ev->ev = ub_event_new(c_hdl->ev->base->eb->base, -1, 146116776186Schristos UB_EV_PERSIST | UB_EV_READ | UB_EV_TIMEOUT, 146216776186Schristos comm_point_tcp_handle_callback, c_hdl); 146316776186Schristos } 146487edd195Schristos if(!c_hdl->ev->ev) { 146587edd195Schristos log_warn("could not ub_event_new, dropped tcp"); 146687edd195Schristos return; 146787edd195Schristos } 14683b6c3722Schristos log_assert(fd != -1); 14690cd9f4ecSchristos (void)fd; 1470*14b2fa6eSchristos new_fd = comm_point_perform_accept(c, &c_hdl->repinfo.remote_addr, 1471*14b2fa6eSchristos &c_hdl->repinfo.remote_addrlen); 14723b6c3722Schristos if(new_fd == -1) 14733b6c3722Schristos return; 1474*14b2fa6eSchristos /* Copy remote_address to client_address. 1475*14b2fa6eSchristos * Simplest way/time for streams to do that. */ 1476*14b2fa6eSchristos c_hdl->repinfo.client_addrlen = c_hdl->repinfo.remote_addrlen; 1477*14b2fa6eSchristos memmove(&c_hdl->repinfo.client_addr, 1478*14b2fa6eSchristos &c_hdl->repinfo.remote_addr, 1479*14b2fa6eSchristos c_hdl->repinfo.remote_addrlen); 14803b6c3722Schristos if(c->ssl) { 14813b6c3722Schristos c_hdl->ssl = incoming_ssl_fd(c->ssl, new_fd); 14823b6c3722Schristos if(!c_hdl->ssl) { 14833b6c3722Schristos c_hdl->fd = new_fd; 14843b6c3722Schristos comm_point_close(c_hdl); 14853b6c3722Schristos return; 14863b6c3722Schristos } 14873b6c3722Schristos c_hdl->ssl_shake_state = comm_ssl_shake_read; 14883b6c3722Schristos #ifdef USE_WINSOCK 14893b6c3722Schristos comm_point_tcp_win_bio_cb(c_hdl, c_hdl->ssl); 14903b6c3722Schristos #endif 14913b6c3722Schristos } 14923b6c3722Schristos 14933b6c3722Schristos /* grab the tcp handler buffers */ 14943b6c3722Schristos c->cur_tcp_count++; 14953b6c3722Schristos c->tcp_free = c_hdl->tcp_free; 14961481e2a9Schristos c_hdl->tcp_free = NULL; 14973b6c3722Schristos if(!c->tcp_free) { 14983b6c3722Schristos /* stop accepting incoming queries for now. */ 14993b6c3722Schristos comm_point_stop_listening(c); 15003b6c3722Schristos } 15010cd9f4ecSchristos setup_tcp_handler(c_hdl, new_fd, c->cur_tcp_count, c->max_tcp_count); 15023b6c3722Schristos } 15033b6c3722Schristos 15043b6c3722Schristos /** Make tcp handler free for next assignment */ 15053b6c3722Schristos static void 15063b6c3722Schristos reclaim_tcp_handler(struct comm_point* c) 15073b6c3722Schristos { 15083b6c3722Schristos log_assert(c->type == comm_tcp); 15093b6c3722Schristos if(c->ssl) { 15103b6c3722Schristos #ifdef HAVE_SSL 15113b6c3722Schristos SSL_shutdown(c->ssl); 15123b6c3722Schristos SSL_free(c->ssl); 15133b6c3722Schristos c->ssl = NULL; 15143b6c3722Schristos #endif 15153b6c3722Schristos } 15163b6c3722Schristos comm_point_close(c); 15173b6c3722Schristos if(c->tcp_parent) { 15181481e2a9Schristos if(c != c->tcp_parent->tcp_free) { 15193b6c3722Schristos c->tcp_parent->cur_tcp_count--; 15203b6c3722Schristos c->tcp_free = c->tcp_parent->tcp_free; 15213b6c3722Schristos c->tcp_parent->tcp_free = c; 15221481e2a9Schristos } 15233b6c3722Schristos if(!c->tcp_free) { 15243b6c3722Schristos /* re-enable listening on accept socket */ 15253b6c3722Schristos comm_point_start_listening(c->tcp_parent, -1, -1); 15263b6c3722Schristos } 15273b6c3722Schristos } 152816776186Schristos c->tcp_more_read_again = NULL; 152916776186Schristos c->tcp_more_write_again = NULL; 15301481e2a9Schristos c->tcp_byte_count = 0; 1531*14b2fa6eSchristos c->pp2_header_state = pp2_header_none; 15321481e2a9Schristos sldns_buffer_clear(c->buffer); 15333b6c3722Schristos } 15343b6c3722Schristos 15353b6c3722Schristos /** do the callback when writing is done */ 15363b6c3722Schristos static void 15373b6c3722Schristos tcp_callback_writer(struct comm_point* c) 15383b6c3722Schristos { 15393b6c3722Schristos log_assert(c->type == comm_tcp); 154016776186Schristos if(!c->tcp_write_and_read) { 15413b6c3722Schristos sldns_buffer_clear(c->buffer); 154216776186Schristos c->tcp_byte_count = 0; 154316776186Schristos } 15443b6c3722Schristos if(c->tcp_do_toggle_rw) 15453b6c3722Schristos c->tcp_is_reading = 1; 15463b6c3722Schristos /* switch from listening(write) to listening(read) */ 1547f42d8de7Schristos if(c->tcp_req_info) { 1548f42d8de7Schristos tcp_req_info_handle_writedone(c->tcp_req_info); 1549f42d8de7Schristos } else { 15503b6c3722Schristos comm_point_stop_listening(c); 155116776186Schristos if(c->tcp_write_and_read) { 155216776186Schristos fptr_ok(fptr_whitelist_comm_point(c->callback)); 155316776186Schristos if( (*c->callback)(c, c->cb_arg, NETEVENT_PKT_WRITTEN, 155416776186Schristos &c->repinfo) ) { 155516776186Schristos comm_point_start_listening(c, -1, 155616776186Schristos adjusted_tcp_timeout(c)); 155716776186Schristos } 155816776186Schristos } else { 155916776186Schristos comm_point_start_listening(c, -1, 156016776186Schristos adjusted_tcp_timeout(c)); 156116776186Schristos } 15623b6c3722Schristos } 1563f42d8de7Schristos } 15643b6c3722Schristos 15653b6c3722Schristos /** do the callback when reading is done */ 15663b6c3722Schristos static void 15673b6c3722Schristos tcp_callback_reader(struct comm_point* c) 15683b6c3722Schristos { 15693b6c3722Schristos log_assert(c->type == comm_tcp || c->type == comm_local); 15703b6c3722Schristos sldns_buffer_flip(c->buffer); 15713b6c3722Schristos if(c->tcp_do_toggle_rw) 15723b6c3722Schristos c->tcp_is_reading = 0; 15733b6c3722Schristos c->tcp_byte_count = 0; 1574f42d8de7Schristos if(c->tcp_req_info) { 1575f42d8de7Schristos tcp_req_info_handle_readdone(c->tcp_req_info); 1576f42d8de7Schristos } else { 15773b6c3722Schristos if(c->type == comm_tcp) 15783b6c3722Schristos comm_point_stop_listening(c); 15793b6c3722Schristos fptr_ok(fptr_whitelist_comm_point(c->callback)); 15803b6c3722Schristos if( (*c->callback)(c, c->cb_arg, NETEVENT_NOERROR, &c->repinfo) ) { 158116776186Schristos comm_point_start_listening(c, -1, 158216776186Schristos adjusted_tcp_timeout(c)); 15833b6c3722Schristos } 15843b6c3722Schristos } 1585f42d8de7Schristos } 15863b6c3722Schristos 15877cd94d69Schristos #ifdef HAVE_SSL 158887edd195Schristos /** true if the ssl handshake error has to be squelched from the logs */ 158916776186Schristos int 159087edd195Schristos squelch_err_ssl_handshake(unsigned long err) 159187edd195Schristos { 159287edd195Schristos if(verbosity >= VERB_QUERY) 159387edd195Schristos return 0; /* only squelch on low verbosity */ 15941481e2a9Schristos if(ERR_GET_LIB(err) == ERR_LIB_SSL && 15951481e2a9Schristos (ERR_GET_REASON(err) == SSL_R_HTTPS_PROXY_REQUEST || 15961481e2a9Schristos ERR_GET_REASON(err) == SSL_R_HTTP_REQUEST || 15971481e2a9Schristos ERR_GET_REASON(err) == SSL_R_WRONG_VERSION_NUMBER || 15981481e2a9Schristos ERR_GET_REASON(err) == SSL_R_SSLV3_ALERT_BAD_CERTIFICATE 159987edd195Schristos #ifdef SSL_F_TLS_POST_PROCESS_CLIENT_HELLO 16001481e2a9Schristos || ERR_GET_REASON(err) == SSL_R_NO_SHARED_CIPHER 160187edd195Schristos #endif 160287edd195Schristos #ifdef SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO 16031481e2a9Schristos || ERR_GET_REASON(err) == SSL_R_UNKNOWN_PROTOCOL 16041481e2a9Schristos || ERR_GET_REASON(err) == SSL_R_UNSUPPORTED_PROTOCOL 160587edd195Schristos # ifdef SSL_R_VERSION_TOO_LOW 16061481e2a9Schristos || ERR_GET_REASON(err) == SSL_R_VERSION_TOO_LOW 160787edd195Schristos # endif 160887edd195Schristos #endif 16091481e2a9Schristos )) 161087edd195Schristos return 1; 161187edd195Schristos return 0; 161287edd195Schristos } 161387edd195Schristos #endif /* HAVE_SSL */ 161487edd195Schristos 16153b6c3722Schristos /** continue ssl handshake */ 16163b6c3722Schristos #ifdef HAVE_SSL 16173b6c3722Schristos static int 16183b6c3722Schristos ssl_handshake(struct comm_point* c) 16193b6c3722Schristos { 16203b6c3722Schristos int r; 16213b6c3722Schristos if(c->ssl_shake_state == comm_ssl_shake_hs_read) { 16223b6c3722Schristos /* read condition satisfied back to writing */ 16231481e2a9Schristos comm_point_listen_for_rw(c, 0, 1); 16243b6c3722Schristos c->ssl_shake_state = comm_ssl_shake_none; 16253b6c3722Schristos return 1; 16263b6c3722Schristos } 16273b6c3722Schristos if(c->ssl_shake_state == comm_ssl_shake_hs_write) { 16283b6c3722Schristos /* write condition satisfied, back to reading */ 16293b6c3722Schristos comm_point_listen_for_rw(c, 1, 0); 16303b6c3722Schristos c->ssl_shake_state = comm_ssl_shake_none; 16313b6c3722Schristos return 1; 16323b6c3722Schristos } 16333b6c3722Schristos 16343b6c3722Schristos ERR_clear_error(); 16353b6c3722Schristos r = SSL_do_handshake(c->ssl); 16363b6c3722Schristos if(r != 1) { 16373b6c3722Schristos int want = SSL_get_error(c->ssl, r); 16383b6c3722Schristos if(want == SSL_ERROR_WANT_READ) { 16393b6c3722Schristos if(c->ssl_shake_state == comm_ssl_shake_read) 16403b6c3722Schristos return 1; 16413b6c3722Schristos c->ssl_shake_state = comm_ssl_shake_read; 16423b6c3722Schristos comm_point_listen_for_rw(c, 1, 0); 16433b6c3722Schristos return 1; 16443b6c3722Schristos } else if(want == SSL_ERROR_WANT_WRITE) { 16453b6c3722Schristos if(c->ssl_shake_state == comm_ssl_shake_write) 16463b6c3722Schristos return 1; 16473b6c3722Schristos c->ssl_shake_state = comm_ssl_shake_write; 16483b6c3722Schristos comm_point_listen_for_rw(c, 0, 1); 16493b6c3722Schristos return 1; 16503b6c3722Schristos } else if(r == 0) { 16513b6c3722Schristos return 0; /* closed */ 16523b6c3722Schristos } else if(want == SSL_ERROR_SYSCALL) { 16533b6c3722Schristos /* SYSCALL and errno==0 means closed uncleanly */ 165416776186Schristos #ifdef EPIPE 165516776186Schristos if(errno == EPIPE && verbosity < 2) 165616776186Schristos return 0; /* silence 'broken pipe' */ 165716776186Schristos #endif 165816776186Schristos #ifdef ECONNRESET 165916776186Schristos if(errno == ECONNRESET && verbosity < 2) 166016776186Schristos return 0; /* silence reset by peer */ 166116776186Schristos #endif 16621481e2a9Schristos if(!tcp_connect_errno_needs_log( 1663*14b2fa6eSchristos (struct sockaddr*)&c->repinfo.remote_addr, 1664*14b2fa6eSchristos c->repinfo.remote_addrlen)) 16651481e2a9Schristos return 0; /* silence connect failures that 16661481e2a9Schristos show up because after connect this is the 16671481e2a9Schristos first system call that accesses the socket */ 16683b6c3722Schristos if(errno != 0) 16693b6c3722Schristos log_err("SSL_handshake syscall: %s", 16703b6c3722Schristos strerror(errno)); 16713b6c3722Schristos return 0; 16723b6c3722Schristos } else { 167387edd195Schristos unsigned long err = ERR_get_error(); 167487edd195Schristos if(!squelch_err_ssl_handshake(err)) { 1675*14b2fa6eSchristos log_crypto_err_io_code("ssl handshake failed", 1676*14b2fa6eSchristos want, err); 1677*14b2fa6eSchristos log_addr(VERB_OPS, "ssl handshake failed", 1678*14b2fa6eSchristos &c->repinfo.remote_addr, 1679*14b2fa6eSchristos c->repinfo.remote_addrlen); 168087edd195Schristos } 16813b6c3722Schristos return 0; 16823b6c3722Schristos } 16833b6c3722Schristos } 16843b6c3722Schristos /* this is where peer verification could take place */ 16857cd94d69Schristos if((SSL_get_verify_mode(c->ssl)&SSL_VERIFY_PEER)) { 16867cd94d69Schristos /* verification */ 16877cd94d69Schristos if(SSL_get_verify_result(c->ssl) == X509_V_OK) { 16881481e2a9Schristos #ifdef HAVE_SSL_GET1_PEER_CERTIFICATE 16891481e2a9Schristos X509* x = SSL_get1_peer_certificate(c->ssl); 16901481e2a9Schristos #else 16917cd94d69Schristos X509* x = SSL_get_peer_certificate(c->ssl); 16921481e2a9Schristos #endif 16937cd94d69Schristos if(!x) { 16947cd94d69Schristos log_addr(VERB_ALGO, "SSL connection failed: " 16957cd94d69Schristos "no certificate", 1696*14b2fa6eSchristos &c->repinfo.remote_addr, 1697*14b2fa6eSchristos c->repinfo.remote_addrlen); 16987cd94d69Schristos return 0; 16997cd94d69Schristos } 17007cd94d69Schristos log_cert(VERB_ALGO, "peer certificate", x); 17017cd94d69Schristos #ifdef HAVE_SSL_GET0_PEERNAME 17027cd94d69Schristos if(SSL_get0_peername(c->ssl)) { 17037cd94d69Schristos char buf[255]; 17047cd94d69Schristos snprintf(buf, sizeof(buf), "SSL connection " 17057cd94d69Schristos "to %s authenticated", 17067cd94d69Schristos SSL_get0_peername(c->ssl)); 1707*14b2fa6eSchristos log_addr(VERB_ALGO, buf, &c->repinfo.remote_addr, 1708*14b2fa6eSchristos c->repinfo.remote_addrlen); 17097cd94d69Schristos } else { 17107cd94d69Schristos #endif 17117cd94d69Schristos log_addr(VERB_ALGO, "SSL connection " 1712*14b2fa6eSchristos "authenticated", &c->repinfo.remote_addr, 1713*14b2fa6eSchristos c->repinfo.remote_addrlen); 17147cd94d69Schristos #ifdef HAVE_SSL_GET0_PEERNAME 17157cd94d69Schristos } 17167cd94d69Schristos #endif 17177cd94d69Schristos X509_free(x); 17187cd94d69Schristos } else { 17191481e2a9Schristos #ifdef HAVE_SSL_GET1_PEER_CERTIFICATE 17201481e2a9Schristos X509* x = SSL_get1_peer_certificate(c->ssl); 17211481e2a9Schristos #else 17227cd94d69Schristos X509* x = SSL_get_peer_certificate(c->ssl); 17231481e2a9Schristos #endif 17247cd94d69Schristos if(x) { 17257cd94d69Schristos log_cert(VERB_ALGO, "peer certificate", x); 17267cd94d69Schristos X509_free(x); 17277cd94d69Schristos } 17287cd94d69Schristos log_addr(VERB_ALGO, "SSL connection failed: " 17297cd94d69Schristos "failed to authenticate", 1730*14b2fa6eSchristos &c->repinfo.remote_addr, 1731*14b2fa6eSchristos c->repinfo.remote_addrlen); 17327cd94d69Schristos return 0; 17337cd94d69Schristos } 17347cd94d69Schristos } else { 17357cd94d69Schristos /* unauthenticated, the verify peer flag was not set 17367cd94d69Schristos * in c->ssl when the ssl object was created from ssl_ctx */ 1737*14b2fa6eSchristos log_addr(VERB_ALGO, "SSL connection", &c->repinfo.remote_addr, 1738*14b2fa6eSchristos c->repinfo.remote_addrlen); 17397cd94d69Schristos } 17403b6c3722Schristos 17411481e2a9Schristos #ifdef HAVE_SSL_GET0_ALPN_SELECTED 174216776186Schristos /* check if http2 use is negotiated */ 174316776186Schristos if(c->type == comm_http && c->h2_session) { 174416776186Schristos const unsigned char *alpn; 174516776186Schristos unsigned int alpnlen = 0; 174616776186Schristos SSL_get0_alpn_selected(c->ssl, &alpn, &alpnlen); 174716776186Schristos if(alpnlen == 2 && memcmp("h2", alpn, 2) == 0) { 174816776186Schristos /* connection upgraded to HTTP2 */ 174916776186Schristos c->tcp_do_toggle_rw = 0; 175016776186Schristos c->use_h2 = 1; 175116776186Schristos } 175216776186Schristos } 17531481e2a9Schristos #endif 175416776186Schristos 17553b6c3722Schristos /* setup listen rw correctly */ 17563b6c3722Schristos if(c->tcp_is_reading) { 17573b6c3722Schristos if(c->ssl_shake_state != comm_ssl_shake_read) 17583b6c3722Schristos comm_point_listen_for_rw(c, 1, 0); 17593b6c3722Schristos } else { 17601481e2a9Schristos comm_point_listen_for_rw(c, 0, 1); 17613b6c3722Schristos } 17623b6c3722Schristos c->ssl_shake_state = comm_ssl_shake_none; 17633b6c3722Schristos return 1; 17643b6c3722Schristos } 17653b6c3722Schristos #endif /* HAVE_SSL */ 17663b6c3722Schristos 17673b6c3722Schristos /** ssl read callback on TCP */ 17683b6c3722Schristos static int 17693b6c3722Schristos ssl_handle_read(struct comm_point* c) 17703b6c3722Schristos { 17713b6c3722Schristos #ifdef HAVE_SSL 17723b6c3722Schristos int r; 17733b6c3722Schristos if(c->ssl_shake_state != comm_ssl_shake_none) { 17743b6c3722Schristos if(!ssl_handshake(c)) 17753b6c3722Schristos return 0; 17763b6c3722Schristos if(c->ssl_shake_state != comm_ssl_shake_none) 17773b6c3722Schristos return 1; 17783b6c3722Schristos } 1779*14b2fa6eSchristos if(c->pp2_enabled && c->pp2_header_state != pp2_header_done) { 1780*14b2fa6eSchristos struct pp2_header* header = NULL; 1781*14b2fa6eSchristos size_t want_read_size = 0; 1782*14b2fa6eSchristos size_t current_read_size = 0; 1783*14b2fa6eSchristos if(c->pp2_header_state == pp2_header_none) { 1784*14b2fa6eSchristos want_read_size = PP2_HEADER_SIZE; 1785*14b2fa6eSchristos if(sldns_buffer_remaining(c->buffer)<want_read_size) { 1786*14b2fa6eSchristos log_err_addr("proxy_protocol: not enough " 1787*14b2fa6eSchristos "buffer size to read PROXYv2 header", "", 1788*14b2fa6eSchristos &c->repinfo.remote_addr, 1789*14b2fa6eSchristos c->repinfo.remote_addrlen); 1790*14b2fa6eSchristos return 0; 1791*14b2fa6eSchristos } 1792*14b2fa6eSchristos verbose(VERB_ALGO, "proxy_protocol: reading fixed " 1793*14b2fa6eSchristos "part of PROXYv2 header (len %lu)", 1794*14b2fa6eSchristos (unsigned long)want_read_size); 1795*14b2fa6eSchristos current_read_size = want_read_size; 1796*14b2fa6eSchristos if(c->tcp_byte_count < current_read_size) { 1797*14b2fa6eSchristos ERR_clear_error(); 1798*14b2fa6eSchristos if((r=SSL_read(c->ssl, (void*)sldns_buffer_at( 1799*14b2fa6eSchristos c->buffer, c->tcp_byte_count), 1800*14b2fa6eSchristos current_read_size - 1801*14b2fa6eSchristos c->tcp_byte_count)) <= 0) { 1802*14b2fa6eSchristos int want = SSL_get_error(c->ssl, r); 1803*14b2fa6eSchristos if(want == SSL_ERROR_ZERO_RETURN) { 1804*14b2fa6eSchristos if(c->tcp_req_info) 1805*14b2fa6eSchristos return tcp_req_info_handle_read_close(c->tcp_req_info); 1806*14b2fa6eSchristos return 0; /* shutdown, closed */ 1807*14b2fa6eSchristos } else if(want == SSL_ERROR_WANT_READ) { 1808*14b2fa6eSchristos #ifdef USE_WINSOCK 1809*14b2fa6eSchristos ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_READ); 1810*14b2fa6eSchristos #endif 1811*14b2fa6eSchristos return 1; /* read more later */ 1812*14b2fa6eSchristos } else if(want == SSL_ERROR_WANT_WRITE) { 1813*14b2fa6eSchristos c->ssl_shake_state = comm_ssl_shake_hs_write; 1814*14b2fa6eSchristos comm_point_listen_for_rw(c, 0, 1); 1815*14b2fa6eSchristos return 1; 1816*14b2fa6eSchristos } else if(want == SSL_ERROR_SYSCALL) { 1817*14b2fa6eSchristos #ifdef ECONNRESET 1818*14b2fa6eSchristos if(errno == ECONNRESET && verbosity < 2) 1819*14b2fa6eSchristos return 0; /* silence reset by peer */ 1820*14b2fa6eSchristos #endif 1821*14b2fa6eSchristos if(errno != 0) 1822*14b2fa6eSchristos log_err("SSL_read syscall: %s", 1823*14b2fa6eSchristos strerror(errno)); 1824*14b2fa6eSchristos return 0; 1825*14b2fa6eSchristos } 1826*14b2fa6eSchristos log_crypto_err_io("could not SSL_read", 1827*14b2fa6eSchristos want); 1828*14b2fa6eSchristos return 0; 1829*14b2fa6eSchristos } 1830*14b2fa6eSchristos c->tcp_byte_count += r; 1831*14b2fa6eSchristos sldns_buffer_skip(c->buffer, r); 1832*14b2fa6eSchristos if(c->tcp_byte_count != current_read_size) return 1; 1833*14b2fa6eSchristos c->pp2_header_state = pp2_header_init; 1834*14b2fa6eSchristos } 1835*14b2fa6eSchristos } 1836*14b2fa6eSchristos if(c->pp2_header_state == pp2_header_init) { 1837*14b2fa6eSchristos int err; 1838*14b2fa6eSchristos err = pp2_read_header( 1839*14b2fa6eSchristos sldns_buffer_begin(c->buffer), 1840*14b2fa6eSchristos sldns_buffer_limit(c->buffer)); 1841*14b2fa6eSchristos if(err) { 1842*14b2fa6eSchristos log_err("proxy_protocol: could not parse " 1843*14b2fa6eSchristos "PROXYv2 header (%s)", 1844*14b2fa6eSchristos pp_lookup_error(err)); 1845*14b2fa6eSchristos return 0; 1846*14b2fa6eSchristos } 1847*14b2fa6eSchristos header = (struct pp2_header*)sldns_buffer_begin(c->buffer); 1848*14b2fa6eSchristos want_read_size = ntohs(header->len); 1849*14b2fa6eSchristos if(sldns_buffer_limit(c->buffer) < 1850*14b2fa6eSchristos PP2_HEADER_SIZE + want_read_size) { 1851*14b2fa6eSchristos log_err_addr("proxy_protocol: not enough " 1852*14b2fa6eSchristos "buffer size to read PROXYv2 header", "", 1853*14b2fa6eSchristos &c->repinfo.remote_addr, 1854*14b2fa6eSchristos c->repinfo.remote_addrlen); 1855*14b2fa6eSchristos return 0; 1856*14b2fa6eSchristos } 1857*14b2fa6eSchristos verbose(VERB_ALGO, "proxy_protocol: reading variable " 1858*14b2fa6eSchristos "part of PROXYv2 header (len %lu)", 1859*14b2fa6eSchristos (unsigned long)want_read_size); 1860*14b2fa6eSchristos current_read_size = PP2_HEADER_SIZE + want_read_size; 1861*14b2fa6eSchristos if(want_read_size == 0) { 1862*14b2fa6eSchristos /* nothing more to read; header is complete */ 1863*14b2fa6eSchristos c->pp2_header_state = pp2_header_done; 1864*14b2fa6eSchristos } else if(c->tcp_byte_count < current_read_size) { 1865*14b2fa6eSchristos ERR_clear_error(); 1866*14b2fa6eSchristos if((r=SSL_read(c->ssl, (void*)sldns_buffer_at( 1867*14b2fa6eSchristos c->buffer, c->tcp_byte_count), 1868*14b2fa6eSchristos current_read_size - 1869*14b2fa6eSchristos c->tcp_byte_count)) <= 0) { 1870*14b2fa6eSchristos int want = SSL_get_error(c->ssl, r); 1871*14b2fa6eSchristos if(want == SSL_ERROR_ZERO_RETURN) { 1872*14b2fa6eSchristos if(c->tcp_req_info) 1873*14b2fa6eSchristos return tcp_req_info_handle_read_close(c->tcp_req_info); 1874*14b2fa6eSchristos return 0; /* shutdown, closed */ 1875*14b2fa6eSchristos } else if(want == SSL_ERROR_WANT_READ) { 1876*14b2fa6eSchristos #ifdef USE_WINSOCK 1877*14b2fa6eSchristos ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_READ); 1878*14b2fa6eSchristos #endif 1879*14b2fa6eSchristos return 1; /* read more later */ 1880*14b2fa6eSchristos } else if(want == SSL_ERROR_WANT_WRITE) { 1881*14b2fa6eSchristos c->ssl_shake_state = comm_ssl_shake_hs_write; 1882*14b2fa6eSchristos comm_point_listen_for_rw(c, 0, 1); 1883*14b2fa6eSchristos return 1; 1884*14b2fa6eSchristos } else if(want == SSL_ERROR_SYSCALL) { 1885*14b2fa6eSchristos #ifdef ECONNRESET 1886*14b2fa6eSchristos if(errno == ECONNRESET && verbosity < 2) 1887*14b2fa6eSchristos return 0; /* silence reset by peer */ 1888*14b2fa6eSchristos #endif 1889*14b2fa6eSchristos if(errno != 0) 1890*14b2fa6eSchristos log_err("SSL_read syscall: %s", 1891*14b2fa6eSchristos strerror(errno)); 1892*14b2fa6eSchristos return 0; 1893*14b2fa6eSchristos } 1894*14b2fa6eSchristos log_crypto_err_io("could not SSL_read", 1895*14b2fa6eSchristos want); 1896*14b2fa6eSchristos return 0; 1897*14b2fa6eSchristos } 1898*14b2fa6eSchristos c->tcp_byte_count += r; 1899*14b2fa6eSchristos sldns_buffer_skip(c->buffer, r); 1900*14b2fa6eSchristos if(c->tcp_byte_count != current_read_size) return 1; 1901*14b2fa6eSchristos c->pp2_header_state = pp2_header_done; 1902*14b2fa6eSchristos } 1903*14b2fa6eSchristos } 1904*14b2fa6eSchristos if(c->pp2_header_state != pp2_header_done || !header) { 1905*14b2fa6eSchristos log_err_addr("proxy_protocol: wrong state for the " 1906*14b2fa6eSchristos "PROXYv2 header", "", &c->repinfo.remote_addr, 1907*14b2fa6eSchristos c->repinfo.remote_addrlen); 1908*14b2fa6eSchristos return 0; 1909*14b2fa6eSchristos } 1910*14b2fa6eSchristos sldns_buffer_flip(c->buffer); 1911*14b2fa6eSchristos if(!consume_pp2_header(c->buffer, &c->repinfo, 1)) { 1912*14b2fa6eSchristos log_err_addr("proxy_protocol: could not consume " 1913*14b2fa6eSchristos "PROXYv2 header", "", &c->repinfo.remote_addr, 1914*14b2fa6eSchristos c->repinfo.remote_addrlen); 1915*14b2fa6eSchristos return 0; 1916*14b2fa6eSchristos } 1917*14b2fa6eSchristos verbose(VERB_ALGO, "proxy_protocol: successful read of " 1918*14b2fa6eSchristos "PROXYv2 header"); 1919*14b2fa6eSchristos /* Clear and reset the buffer to read the following 1920*14b2fa6eSchristos * DNS packet(s). */ 1921*14b2fa6eSchristos sldns_buffer_clear(c->buffer); 1922*14b2fa6eSchristos c->tcp_byte_count = 0; 1923*14b2fa6eSchristos return 1; 1924*14b2fa6eSchristos } 19253b6c3722Schristos if(c->tcp_byte_count < sizeof(uint16_t)) { 19263b6c3722Schristos /* read length bytes */ 19273b6c3722Schristos ERR_clear_error(); 19283b6c3722Schristos if((r=SSL_read(c->ssl, (void*)sldns_buffer_at(c->buffer, 19293b6c3722Schristos c->tcp_byte_count), (int)(sizeof(uint16_t) - 19303b6c3722Schristos c->tcp_byte_count))) <= 0) { 19313b6c3722Schristos int want = SSL_get_error(c->ssl, r); 19323b6c3722Schristos if(want == SSL_ERROR_ZERO_RETURN) { 1933f42d8de7Schristos if(c->tcp_req_info) 1934f42d8de7Schristos return tcp_req_info_handle_read_close(c->tcp_req_info); 19353b6c3722Schristos return 0; /* shutdown, closed */ 19363b6c3722Schristos } else if(want == SSL_ERROR_WANT_READ) { 19371481e2a9Schristos #ifdef USE_WINSOCK 19387cd94d69Schristos ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_READ); 19391481e2a9Schristos #endif 19403b6c3722Schristos return 1; /* read more later */ 19413b6c3722Schristos } else if(want == SSL_ERROR_WANT_WRITE) { 19423b6c3722Schristos c->ssl_shake_state = comm_ssl_shake_hs_write; 19433b6c3722Schristos comm_point_listen_for_rw(c, 0, 1); 19443b6c3722Schristos return 1; 19453b6c3722Schristos } else if(want == SSL_ERROR_SYSCALL) { 194687edd195Schristos #ifdef ECONNRESET 194787edd195Schristos if(errno == ECONNRESET && verbosity < 2) 194887edd195Schristos return 0; /* silence reset by peer */ 194987edd195Schristos #endif 19503b6c3722Schristos if(errno != 0) 19513b6c3722Schristos log_err("SSL_read syscall: %s", 19523b6c3722Schristos strerror(errno)); 19533b6c3722Schristos return 0; 19543b6c3722Schristos } 1955*14b2fa6eSchristos log_crypto_err_io("could not SSL_read", want); 19563b6c3722Schristos return 0; 19573b6c3722Schristos } 19583b6c3722Schristos c->tcp_byte_count += r; 19597cd94d69Schristos if(c->tcp_byte_count < sizeof(uint16_t)) 19603b6c3722Schristos return 1; 19613b6c3722Schristos if(sldns_buffer_read_u16_at(c->buffer, 0) > 19623b6c3722Schristos sldns_buffer_capacity(c->buffer)) { 19633b6c3722Schristos verbose(VERB_QUERY, "ssl: dropped larger than buffer"); 19643b6c3722Schristos return 0; 19653b6c3722Schristos } 19663b6c3722Schristos sldns_buffer_set_limit(c->buffer, 19673b6c3722Schristos sldns_buffer_read_u16_at(c->buffer, 0)); 19683b6c3722Schristos if(sldns_buffer_limit(c->buffer) < LDNS_HEADER_SIZE) { 19693b6c3722Schristos verbose(VERB_QUERY, "ssl: dropped bogus too short."); 19703b6c3722Schristos return 0; 19713b6c3722Schristos } 19727cd94d69Schristos sldns_buffer_skip(c->buffer, (ssize_t)(c->tcp_byte_count-sizeof(uint16_t))); 19733b6c3722Schristos verbose(VERB_ALGO, "Reading ssl tcp query of length %d", 19743b6c3722Schristos (int)sldns_buffer_limit(c->buffer)); 19753b6c3722Schristos } 19767cd94d69Schristos if(sldns_buffer_remaining(c->buffer) > 0) { 19773b6c3722Schristos ERR_clear_error(); 19783b6c3722Schristos r = SSL_read(c->ssl, (void*)sldns_buffer_current(c->buffer), 19793b6c3722Schristos (int)sldns_buffer_remaining(c->buffer)); 19803b6c3722Schristos if(r <= 0) { 19813b6c3722Schristos int want = SSL_get_error(c->ssl, r); 19823b6c3722Schristos if(want == SSL_ERROR_ZERO_RETURN) { 1983f42d8de7Schristos if(c->tcp_req_info) 1984f42d8de7Schristos return tcp_req_info_handle_read_close(c->tcp_req_info); 19853b6c3722Schristos return 0; /* shutdown, closed */ 19863b6c3722Schristos } else if(want == SSL_ERROR_WANT_READ) { 19871481e2a9Schristos #ifdef USE_WINSOCK 19887cd94d69Schristos ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_READ); 19891481e2a9Schristos #endif 19903b6c3722Schristos return 1; /* read more later */ 19913b6c3722Schristos } else if(want == SSL_ERROR_WANT_WRITE) { 19923b6c3722Schristos c->ssl_shake_state = comm_ssl_shake_hs_write; 19933b6c3722Schristos comm_point_listen_for_rw(c, 0, 1); 19943b6c3722Schristos return 1; 19953b6c3722Schristos } else if(want == SSL_ERROR_SYSCALL) { 199687edd195Schristos #ifdef ECONNRESET 199787edd195Schristos if(errno == ECONNRESET && verbosity < 2) 199887edd195Schristos return 0; /* silence reset by peer */ 199987edd195Schristos #endif 20003b6c3722Schristos if(errno != 0) 20013b6c3722Schristos log_err("SSL_read syscall: %s", 20023b6c3722Schristos strerror(errno)); 20033b6c3722Schristos return 0; 20043b6c3722Schristos } 2005*14b2fa6eSchristos log_crypto_err_io("could not SSL_read", want); 20063b6c3722Schristos return 0; 20073b6c3722Schristos } 20083b6c3722Schristos sldns_buffer_skip(c->buffer, (ssize_t)r); 20097cd94d69Schristos } 20103b6c3722Schristos if(sldns_buffer_remaining(c->buffer) <= 0) { 20113b6c3722Schristos tcp_callback_reader(c); 20123b6c3722Schristos } 20133b6c3722Schristos return 1; 20143b6c3722Schristos #else 20153b6c3722Schristos (void)c; 20163b6c3722Schristos return 0; 20173b6c3722Schristos #endif /* HAVE_SSL */ 20183b6c3722Schristos } 20193b6c3722Schristos 20203b6c3722Schristos /** ssl write callback on TCP */ 20213b6c3722Schristos static int 20223b6c3722Schristos ssl_handle_write(struct comm_point* c) 20233b6c3722Schristos { 20243b6c3722Schristos #ifdef HAVE_SSL 20253b6c3722Schristos int r; 20263b6c3722Schristos if(c->ssl_shake_state != comm_ssl_shake_none) { 20273b6c3722Schristos if(!ssl_handshake(c)) 20283b6c3722Schristos return 0; 20293b6c3722Schristos if(c->ssl_shake_state != comm_ssl_shake_none) 20303b6c3722Schristos return 1; 20313b6c3722Schristos } 20323b6c3722Schristos /* ignore return, if fails we may simply block */ 203387edd195Schristos (void)SSL_set_mode(c->ssl, (long)SSL_MODE_ENABLE_PARTIAL_WRITE); 203416776186Schristos if((c->tcp_write_and_read?c->tcp_write_byte_count:c->tcp_byte_count) < sizeof(uint16_t)) { 203516776186Schristos uint16_t len = htons(c->tcp_write_and_read?c->tcp_write_pkt_len:sldns_buffer_limit(c->buffer)); 20363b6c3722Schristos ERR_clear_error(); 203716776186Schristos if(c->tcp_write_and_read) { 203816776186Schristos if(c->tcp_write_pkt_len + 2 < LDNS_RR_BUF_SIZE) { 203916776186Schristos /* combine the tcp length and the query for 204016776186Schristos * write, this emulates writev */ 204116776186Schristos uint8_t buf[LDNS_RR_BUF_SIZE]; 204216776186Schristos memmove(buf, &len, sizeof(uint16_t)); 204316776186Schristos memmove(buf+sizeof(uint16_t), 204416776186Schristos c->tcp_write_pkt, 204516776186Schristos c->tcp_write_pkt_len); 204616776186Schristos r = SSL_write(c->ssl, 204716776186Schristos (void*)(buf+c->tcp_write_byte_count), 204816776186Schristos c->tcp_write_pkt_len + 2 - 204916776186Schristos c->tcp_write_byte_count); 205016776186Schristos } else { 205116776186Schristos r = SSL_write(c->ssl, 205216776186Schristos (void*)(((uint8_t*)&len)+c->tcp_write_byte_count), 205316776186Schristos (int)(sizeof(uint16_t)-c->tcp_write_byte_count)); 205416776186Schristos } 205516776186Schristos } else if(sizeof(uint16_t)+sldns_buffer_remaining(c->buffer) < 20567cd94d69Schristos LDNS_RR_BUF_SIZE) { 20577cd94d69Schristos /* combine the tcp length and the query for write, 20587cd94d69Schristos * this emulates writev */ 20597cd94d69Schristos uint8_t buf[LDNS_RR_BUF_SIZE]; 20607cd94d69Schristos memmove(buf, &len, sizeof(uint16_t)); 20617cd94d69Schristos memmove(buf+sizeof(uint16_t), 20627cd94d69Schristos sldns_buffer_current(c->buffer), 20637cd94d69Schristos sldns_buffer_remaining(c->buffer)); 20647cd94d69Schristos r = SSL_write(c->ssl, (void*)(buf+c->tcp_byte_count), 20657cd94d69Schristos (int)(sizeof(uint16_t)+ 20667cd94d69Schristos sldns_buffer_remaining(c->buffer) 20677cd94d69Schristos - c->tcp_byte_count)); 20687cd94d69Schristos } else { 20693b6c3722Schristos r = SSL_write(c->ssl, 20703b6c3722Schristos (void*)(((uint8_t*)&len)+c->tcp_byte_count), 20713b6c3722Schristos (int)(sizeof(uint16_t)-c->tcp_byte_count)); 20727cd94d69Schristos } 20733b6c3722Schristos if(r <= 0) { 20743b6c3722Schristos int want = SSL_get_error(c->ssl, r); 20753b6c3722Schristos if(want == SSL_ERROR_ZERO_RETURN) { 20763b6c3722Schristos return 0; /* closed */ 20773b6c3722Schristos } else if(want == SSL_ERROR_WANT_READ) { 207887edd195Schristos c->ssl_shake_state = comm_ssl_shake_hs_read; 20793b6c3722Schristos comm_point_listen_for_rw(c, 1, 0); 20803b6c3722Schristos return 1; /* wait for read condition */ 20813b6c3722Schristos } else if(want == SSL_ERROR_WANT_WRITE) { 20821481e2a9Schristos #ifdef USE_WINSOCK 20837cd94d69Schristos ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE); 20841481e2a9Schristos #endif 20853b6c3722Schristos return 1; /* write more later */ 20863b6c3722Schristos } else if(want == SSL_ERROR_SYSCALL) { 208787edd195Schristos #ifdef EPIPE 208887edd195Schristos if(errno == EPIPE && verbosity < 2) 208987edd195Schristos return 0; /* silence 'broken pipe' */ 209087edd195Schristos #endif 20913b6c3722Schristos if(errno != 0) 20923b6c3722Schristos log_err("SSL_write syscall: %s", 20933b6c3722Schristos strerror(errno)); 20943b6c3722Schristos return 0; 20953b6c3722Schristos } 2096*14b2fa6eSchristos log_crypto_err_io("could not SSL_write", want); 20973b6c3722Schristos return 0; 20983b6c3722Schristos } 209916776186Schristos if(c->tcp_write_and_read) { 210016776186Schristos c->tcp_write_byte_count += r; 210116776186Schristos if(c->tcp_write_byte_count < sizeof(uint16_t)) 210216776186Schristos return 1; 210316776186Schristos } else { 21043b6c3722Schristos c->tcp_byte_count += r; 21053b6c3722Schristos if(c->tcp_byte_count < sizeof(uint16_t)) 21063b6c3722Schristos return 1; 21073b6c3722Schristos sldns_buffer_set_position(c->buffer, c->tcp_byte_count - 21083b6c3722Schristos sizeof(uint16_t)); 210916776186Schristos } 211016776186Schristos if((!c->tcp_write_and_read && sldns_buffer_remaining(c->buffer) == 0) || (c->tcp_write_and_read && c->tcp_write_byte_count == c->tcp_write_pkt_len + 2)) { 21113b6c3722Schristos tcp_callback_writer(c); 21123b6c3722Schristos return 1; 21133b6c3722Schristos } 21143b6c3722Schristos } 211516776186Schristos log_assert(c->tcp_write_and_read || sldns_buffer_remaining(c->buffer) > 0); 211616776186Schristos log_assert(!c->tcp_write_and_read || c->tcp_write_byte_count < c->tcp_write_pkt_len + 2); 21173b6c3722Schristos ERR_clear_error(); 211816776186Schristos if(c->tcp_write_and_read) { 211916776186Schristos r = SSL_write(c->ssl, (void*)(c->tcp_write_pkt + c->tcp_write_byte_count - 2), 212016776186Schristos (int)(c->tcp_write_pkt_len + 2 - c->tcp_write_byte_count)); 212116776186Schristos } else { 21223b6c3722Schristos r = SSL_write(c->ssl, (void*)sldns_buffer_current(c->buffer), 21233b6c3722Schristos (int)sldns_buffer_remaining(c->buffer)); 212416776186Schristos } 21253b6c3722Schristos if(r <= 0) { 21263b6c3722Schristos int want = SSL_get_error(c->ssl, r); 21273b6c3722Schristos if(want == SSL_ERROR_ZERO_RETURN) { 21283b6c3722Schristos return 0; /* closed */ 21293b6c3722Schristos } else if(want == SSL_ERROR_WANT_READ) { 213087edd195Schristos c->ssl_shake_state = comm_ssl_shake_hs_read; 21313b6c3722Schristos comm_point_listen_for_rw(c, 1, 0); 21323b6c3722Schristos return 1; /* wait for read condition */ 21333b6c3722Schristos } else if(want == SSL_ERROR_WANT_WRITE) { 21341481e2a9Schristos #ifdef USE_WINSOCK 21357cd94d69Schristos ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE); 21361481e2a9Schristos #endif 21373b6c3722Schristos return 1; /* write more later */ 21383b6c3722Schristos } else if(want == SSL_ERROR_SYSCALL) { 213987edd195Schristos #ifdef EPIPE 214087edd195Schristos if(errno == EPIPE && verbosity < 2) 214187edd195Schristos return 0; /* silence 'broken pipe' */ 214287edd195Schristos #endif 21433b6c3722Schristos if(errno != 0) 21443b6c3722Schristos log_err("SSL_write syscall: %s", 21453b6c3722Schristos strerror(errno)); 21463b6c3722Schristos return 0; 21473b6c3722Schristos } 2148*14b2fa6eSchristos log_crypto_err_io("could not SSL_write", want); 21493b6c3722Schristos return 0; 21503b6c3722Schristos } 215116776186Schristos if(c->tcp_write_and_read) { 215216776186Schristos c->tcp_write_byte_count += r; 215316776186Schristos } else { 21543b6c3722Schristos sldns_buffer_skip(c->buffer, (ssize_t)r); 215516776186Schristos } 21563b6c3722Schristos 215716776186Schristos if((!c->tcp_write_and_read && sldns_buffer_remaining(c->buffer) == 0) || (c->tcp_write_and_read && c->tcp_write_byte_count == c->tcp_write_pkt_len + 2)) { 21583b6c3722Schristos tcp_callback_writer(c); 21593b6c3722Schristos } 21603b6c3722Schristos return 1; 21613b6c3722Schristos #else 21623b6c3722Schristos (void)c; 21633b6c3722Schristos return 0; 21643b6c3722Schristos #endif /* HAVE_SSL */ 21653b6c3722Schristos } 21663b6c3722Schristos 21673b6c3722Schristos /** handle ssl tcp connection with dns contents */ 21683b6c3722Schristos static int 216916776186Schristos ssl_handle_it(struct comm_point* c, int is_write) 21703b6c3722Schristos { 217116776186Schristos /* handle case where renegotiation wants read during write call 217216776186Schristos * or write during read calls */ 217316776186Schristos if(is_write && c->ssl_shake_state == comm_ssl_shake_hs_write) 217416776186Schristos return ssl_handle_read(c); 217516776186Schristos else if(!is_write && c->ssl_shake_state == comm_ssl_shake_hs_read) 217616776186Schristos return ssl_handle_write(c); 217716776186Schristos /* handle read events for read operation and write events for a 217816776186Schristos * write operation */ 217916776186Schristos else if(!is_write) 21803b6c3722Schristos return ssl_handle_read(c); 21813b6c3722Schristos return ssl_handle_write(c); 21823b6c3722Schristos } 21833b6c3722Schristos 2184*14b2fa6eSchristos /** 2185*14b2fa6eSchristos * Handle tcp reading callback. 21863b6c3722Schristos * @param fd: file descriptor of socket. 21873b6c3722Schristos * @param c: comm point to read from into buffer. 21883b6c3722Schristos * @param short_ok: if true, very short packets are OK (for comm_local). 21893b6c3722Schristos * @return: 0 on error 21903b6c3722Schristos */ 21913b6c3722Schristos static int 21923b6c3722Schristos comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok) 21933b6c3722Schristos { 21943b6c3722Schristos ssize_t r; 2195*14b2fa6eSchristos int recv_initial = 0; 21963b6c3722Schristos log_assert(c->type == comm_tcp || c->type == comm_local); 21973b6c3722Schristos if(c->ssl) 219816776186Schristos return ssl_handle_it(c, 0); 219916776186Schristos if(!c->tcp_is_reading && !c->tcp_write_and_read) 22003b6c3722Schristos return 0; 22013b6c3722Schristos 22023b6c3722Schristos log_assert(fd != -1); 2203*14b2fa6eSchristos if(c->pp2_enabled && c->pp2_header_state != pp2_header_done) { 2204*14b2fa6eSchristos struct pp2_header* header = NULL; 2205*14b2fa6eSchristos size_t want_read_size = 0; 2206*14b2fa6eSchristos size_t current_read_size = 0; 2207*14b2fa6eSchristos if(c->pp2_header_state == pp2_header_none) { 2208*14b2fa6eSchristos want_read_size = PP2_HEADER_SIZE; 2209*14b2fa6eSchristos if(sldns_buffer_remaining(c->buffer)<want_read_size) { 2210*14b2fa6eSchristos log_err_addr("proxy_protocol: not enough " 2211*14b2fa6eSchristos "buffer size to read PROXYv2 header", "", 2212*14b2fa6eSchristos &c->repinfo.remote_addr, 2213*14b2fa6eSchristos c->repinfo.remote_addrlen); 2214*14b2fa6eSchristos return 0; 2215*14b2fa6eSchristos } 2216*14b2fa6eSchristos verbose(VERB_ALGO, "proxy_protocol: reading fixed " 2217*14b2fa6eSchristos "part of PROXYv2 header (len %lu)", 2218*14b2fa6eSchristos (unsigned long)want_read_size); 2219*14b2fa6eSchristos current_read_size = want_read_size; 2220*14b2fa6eSchristos if(c->tcp_byte_count < current_read_size) { 2221*14b2fa6eSchristos r = recv(fd, (void*)sldns_buffer_at(c->buffer, 2222*14b2fa6eSchristos c->tcp_byte_count), 2223*14b2fa6eSchristos current_read_size-c->tcp_byte_count, MSG_DONTWAIT); 2224f42d8de7Schristos if(r == 0) { 2225f42d8de7Schristos if(c->tcp_req_info) 2226f42d8de7Schristos return tcp_req_info_handle_read_close(c->tcp_req_info); 22273b6c3722Schristos return 0; 2228f42d8de7Schristos } else if(r == -1) { 2229*14b2fa6eSchristos goto recv_error_initial; 2230*14b2fa6eSchristos } 2231*14b2fa6eSchristos c->tcp_byte_count += r; 2232*14b2fa6eSchristos sldns_buffer_skip(c->buffer, r); 2233*14b2fa6eSchristos if(c->tcp_byte_count != current_read_size) return 1; 2234*14b2fa6eSchristos c->pp2_header_state = pp2_header_init; 2235*14b2fa6eSchristos } 2236*14b2fa6eSchristos } 2237*14b2fa6eSchristos if(c->pp2_header_state == pp2_header_init) { 2238*14b2fa6eSchristos int err; 2239*14b2fa6eSchristos err = pp2_read_header( 2240*14b2fa6eSchristos sldns_buffer_begin(c->buffer), 2241*14b2fa6eSchristos sldns_buffer_limit(c->buffer)); 2242*14b2fa6eSchristos if(err) { 2243*14b2fa6eSchristos log_err("proxy_protocol: could not parse " 2244*14b2fa6eSchristos "PROXYv2 header (%s)", 2245*14b2fa6eSchristos pp_lookup_error(err)); 2246*14b2fa6eSchristos return 0; 2247*14b2fa6eSchristos } 2248*14b2fa6eSchristos header = (struct pp2_header*)sldns_buffer_begin(c->buffer); 2249*14b2fa6eSchristos want_read_size = ntohs(header->len); 2250*14b2fa6eSchristos if(sldns_buffer_limit(c->buffer) < 2251*14b2fa6eSchristos PP2_HEADER_SIZE + want_read_size) { 2252*14b2fa6eSchristos log_err_addr("proxy_protocol: not enough " 2253*14b2fa6eSchristos "buffer size to read PROXYv2 header", "", 2254*14b2fa6eSchristos &c->repinfo.remote_addr, 2255*14b2fa6eSchristos c->repinfo.remote_addrlen); 2256*14b2fa6eSchristos return 0; 2257*14b2fa6eSchristos } 2258*14b2fa6eSchristos verbose(VERB_ALGO, "proxy_protocol: reading variable " 2259*14b2fa6eSchristos "part of PROXYv2 header (len %lu)", 2260*14b2fa6eSchristos (unsigned long)want_read_size); 2261*14b2fa6eSchristos current_read_size = PP2_HEADER_SIZE + want_read_size; 2262*14b2fa6eSchristos if(want_read_size == 0) { 2263*14b2fa6eSchristos /* nothing more to read; header is complete */ 2264*14b2fa6eSchristos c->pp2_header_state = pp2_header_done; 2265*14b2fa6eSchristos } else if(c->tcp_byte_count < current_read_size) { 2266*14b2fa6eSchristos r = recv(fd, (void*)sldns_buffer_at(c->buffer, 2267*14b2fa6eSchristos c->tcp_byte_count), 2268*14b2fa6eSchristos current_read_size-c->tcp_byte_count, MSG_DONTWAIT); 2269*14b2fa6eSchristos if(r == 0) { 2270*14b2fa6eSchristos if(c->tcp_req_info) 2271*14b2fa6eSchristos return tcp_req_info_handle_read_close(c->tcp_req_info); 2272*14b2fa6eSchristos return 0; 2273*14b2fa6eSchristos } else if(r == -1) { 2274*14b2fa6eSchristos goto recv_error; 2275*14b2fa6eSchristos } 2276*14b2fa6eSchristos c->tcp_byte_count += r; 2277*14b2fa6eSchristos sldns_buffer_skip(c->buffer, r); 2278*14b2fa6eSchristos if(c->tcp_byte_count != current_read_size) return 1; 2279*14b2fa6eSchristos c->pp2_header_state = pp2_header_done; 2280*14b2fa6eSchristos } 2281*14b2fa6eSchristos } 2282*14b2fa6eSchristos if(c->pp2_header_state != pp2_header_done || !header) { 2283*14b2fa6eSchristos log_err_addr("proxy_protocol: wrong state for the " 2284*14b2fa6eSchristos "PROXYv2 header", "", &c->repinfo.remote_addr, 2285*14b2fa6eSchristos c->repinfo.remote_addrlen); 2286*14b2fa6eSchristos return 0; 2287*14b2fa6eSchristos } 2288*14b2fa6eSchristos sldns_buffer_flip(c->buffer); 2289*14b2fa6eSchristos if(!consume_pp2_header(c->buffer, &c->repinfo, 1)) { 2290*14b2fa6eSchristos log_err_addr("proxy_protocol: could not consume " 2291*14b2fa6eSchristos "PROXYv2 header", "", &c->repinfo.remote_addr, 2292*14b2fa6eSchristos c->repinfo.remote_addrlen); 2293*14b2fa6eSchristos return 0; 2294*14b2fa6eSchristos } 2295*14b2fa6eSchristos verbose(VERB_ALGO, "proxy_protocol: successful read of " 2296*14b2fa6eSchristos "PROXYv2 header"); 2297*14b2fa6eSchristos /* Clear and reset the buffer to read the following 2298*14b2fa6eSchristos * DNS packet(s). */ 2299*14b2fa6eSchristos sldns_buffer_clear(c->buffer); 2300*14b2fa6eSchristos c->tcp_byte_count = 0; 2301*14b2fa6eSchristos return 1; 2302*14b2fa6eSchristos } 2303*14b2fa6eSchristos 2304*14b2fa6eSchristos if(c->tcp_byte_count < sizeof(uint16_t)) { 2305*14b2fa6eSchristos /* read length bytes */ 2306*14b2fa6eSchristos r = recv(fd,(void*)sldns_buffer_at(c->buffer,c->tcp_byte_count), 2307*14b2fa6eSchristos sizeof(uint16_t)-c->tcp_byte_count, MSG_DONTWAIT); 2308*14b2fa6eSchristos if(r == 0) { 2309*14b2fa6eSchristos if(c->tcp_req_info) 2310*14b2fa6eSchristos return tcp_req_info_handle_read_close(c->tcp_req_info); 2311*14b2fa6eSchristos return 0; 2312*14b2fa6eSchristos } else if(r == -1) { 2313*14b2fa6eSchristos if(c->pp2_enabled) goto recv_error; 2314*14b2fa6eSchristos goto recv_error_initial; 2315*14b2fa6eSchristos } 2316*14b2fa6eSchristos c->tcp_byte_count += r; 2317*14b2fa6eSchristos if(c->tcp_byte_count != sizeof(uint16_t)) 2318*14b2fa6eSchristos return 1; 2319*14b2fa6eSchristos if(sldns_buffer_read_u16_at(c->buffer, 0) > 2320*14b2fa6eSchristos sldns_buffer_capacity(c->buffer)) { 2321*14b2fa6eSchristos verbose(VERB_QUERY, "tcp: dropped larger than buffer"); 2322*14b2fa6eSchristos return 0; 2323*14b2fa6eSchristos } 2324*14b2fa6eSchristos sldns_buffer_set_limit(c->buffer, 2325*14b2fa6eSchristos sldns_buffer_read_u16_at(c->buffer, 0)); 2326*14b2fa6eSchristos if(!short_ok && 2327*14b2fa6eSchristos sldns_buffer_limit(c->buffer) < LDNS_HEADER_SIZE) { 2328*14b2fa6eSchristos verbose(VERB_QUERY, "tcp: dropped bogus too short."); 2329*14b2fa6eSchristos return 0; 2330*14b2fa6eSchristos } 2331*14b2fa6eSchristos verbose(VERB_ALGO, "Reading tcp query of length %d", 2332*14b2fa6eSchristos (int)sldns_buffer_limit(c->buffer)); 2333*14b2fa6eSchristos } 2334*14b2fa6eSchristos 2335*14b2fa6eSchristos if(sldns_buffer_remaining(c->buffer) == 0) 2336*14b2fa6eSchristos log_err("in comm_point_tcp_handle_read buffer_remaining is " 2337*14b2fa6eSchristos "not > 0 as expected, continuing with (harmless) 0 " 2338*14b2fa6eSchristos "length recv"); 2339*14b2fa6eSchristos r = recv(fd, (void*)sldns_buffer_current(c->buffer), 2340*14b2fa6eSchristos sldns_buffer_remaining(c->buffer), MSG_DONTWAIT); 2341*14b2fa6eSchristos if(r == 0) { 2342*14b2fa6eSchristos if(c->tcp_req_info) 2343*14b2fa6eSchristos return tcp_req_info_handle_read_close(c->tcp_req_info); 2344*14b2fa6eSchristos return 0; 2345*14b2fa6eSchristos } else if(r == -1) { 2346*14b2fa6eSchristos goto recv_error; 2347*14b2fa6eSchristos } 2348*14b2fa6eSchristos sldns_buffer_skip(c->buffer, r); 2349*14b2fa6eSchristos if(sldns_buffer_remaining(c->buffer) <= 0) { 2350*14b2fa6eSchristos tcp_callback_reader(c); 2351*14b2fa6eSchristos } 2352*14b2fa6eSchristos return 1; 2353*14b2fa6eSchristos 2354*14b2fa6eSchristos recv_error_initial: 2355*14b2fa6eSchristos recv_initial = 1; 2356*14b2fa6eSchristos recv_error: 23573b6c3722Schristos #ifndef USE_WINSOCK 23583b6c3722Schristos if(errno == EINTR || errno == EAGAIN) 23593b6c3722Schristos return 1; 2360*14b2fa6eSchristos if(recv_initial) { 23613b6c3722Schristos #ifdef ECONNRESET 23623b6c3722Schristos if(errno == ECONNRESET && verbosity < 2) 23633b6c3722Schristos return 0; /* silence reset by peer */ 23643b6c3722Schristos #endif 23651481e2a9Schristos #ifdef ECONNREFUSED 23661481e2a9Schristos if(errno == ECONNREFUSED && verbosity < 2) 23671481e2a9Schristos return 0; /* silence reset by peer */ 23681481e2a9Schristos #endif 236916776186Schristos #ifdef ENETUNREACH 237016776186Schristos if(errno == ENETUNREACH && verbosity < 2) 237116776186Schristos return 0; /* silence it */ 237216776186Schristos #endif 237316776186Schristos #ifdef EHOSTDOWN 237416776186Schristos if(errno == EHOSTDOWN && verbosity < 2) 237516776186Schristos return 0; /* silence it */ 237616776186Schristos #endif 237716776186Schristos #ifdef EHOSTUNREACH 237816776186Schristos if(errno == EHOSTUNREACH && verbosity < 2) 237916776186Schristos return 0; /* silence it */ 238016776186Schristos #endif 238116776186Schristos #ifdef ENETDOWN 238216776186Schristos if(errno == ENETDOWN && verbosity < 2) 238316776186Schristos return 0; /* silence it */ 238416776186Schristos #endif 238516776186Schristos #ifdef EACCES 238616776186Schristos if(errno == EACCES && verbosity < 2) 238716776186Schristos return 0; /* silence it */ 238816776186Schristos #endif 238916776186Schristos #ifdef ENOTCONN 239016776186Schristos if(errno == ENOTCONN) { 2391*14b2fa6eSchristos log_err_addr("read (in tcp s) failed and this " 2392*14b2fa6eSchristos "could be because TCP Fast Open is " 2393*14b2fa6eSchristos "enabled [--disable-tfo-client " 2394*14b2fa6eSchristos "--disable-tfo-server] but does not " 2395*14b2fa6eSchristos "work", sock_strerror(errno), 2396*14b2fa6eSchristos &c->repinfo.remote_addr, 2397*14b2fa6eSchristos c->repinfo.remote_addrlen); 239816776186Schristos return 0; 239916776186Schristos } 240016776186Schristos #endif 2401*14b2fa6eSchristos } 24023b6c3722Schristos #else /* USE_WINSOCK */ 2403*14b2fa6eSchristos if(recv_initial) { 24041481e2a9Schristos if(WSAGetLastError() == WSAECONNREFUSED && verbosity < 2) 24051481e2a9Schristos return 0; 24061481e2a9Schristos if(WSAGetLastError() == WSAEHOSTDOWN && verbosity < 2) 24071481e2a9Schristos return 0; 24081481e2a9Schristos if(WSAGetLastError() == WSAEHOSTUNREACH && verbosity < 2) 24091481e2a9Schristos return 0; 24101481e2a9Schristos if(WSAGetLastError() == WSAENETDOWN && verbosity < 2) 24111481e2a9Schristos return 0; 24121481e2a9Schristos if(WSAGetLastError() == WSAENETUNREACH && verbosity < 2) 24131481e2a9Schristos return 0; 2414*14b2fa6eSchristos } 24153b6c3722Schristos if(WSAGetLastError() == WSAECONNRESET) 24163b6c3722Schristos return 0; 24173b6c3722Schristos if(WSAGetLastError() == WSAEINPROGRESS) 24183b6c3722Schristos return 1; 24193b6c3722Schristos if(WSAGetLastError() == WSAEWOULDBLOCK) { 24203b6c3722Schristos ub_winsock_tcp_wouldblock(c->ev->ev, 24213b6c3722Schristos UB_EV_READ); 24223b6c3722Schristos return 1; 24233b6c3722Schristos } 24243b6c3722Schristos #endif 242516776186Schristos log_err_addr("read (in tcp s)", sock_strerror(errno), 2426*14b2fa6eSchristos &c->repinfo.remote_addr, c->repinfo.remote_addrlen); 24273b6c3722Schristos return 0; 24283b6c3722Schristos } 24293b6c3722Schristos 24303b6c3722Schristos /** 24313b6c3722Schristos * Handle tcp writing callback. 24323b6c3722Schristos * @param fd: file descriptor of socket. 24333b6c3722Schristos * @param c: comm point to write buffer out of. 24343b6c3722Schristos * @return: 0 on error 24353b6c3722Schristos */ 24363b6c3722Schristos static int 24373b6c3722Schristos comm_point_tcp_handle_write(int fd, struct comm_point* c) 24383b6c3722Schristos { 24393b6c3722Schristos ssize_t r; 24400cd9f4ecSchristos struct sldns_buffer *buffer; 24413b6c3722Schristos log_assert(c->type == comm_tcp); 24420cd9f4ecSchristos #ifdef USE_DNSCRYPT 24430cd9f4ecSchristos buffer = c->dnscrypt_buffer; 24440cd9f4ecSchristos #else 24450cd9f4ecSchristos buffer = c->buffer; 24460cd9f4ecSchristos #endif 244716776186Schristos if(c->tcp_is_reading && !c->ssl && !c->tcp_write_and_read) 24483b6c3722Schristos return 0; 24493b6c3722Schristos log_assert(fd != -1); 245016776186Schristos if(((!c->tcp_write_and_read && c->tcp_byte_count == 0) || (c->tcp_write_and_read && c->tcp_write_byte_count == 0)) && c->tcp_check_nb_connect) { 24513b6c3722Schristos /* check for pending error from nonblocking connect */ 24523b6c3722Schristos /* from Stevens, unix network programming, vol1, 3rd ed, p450*/ 24533b6c3722Schristos int error = 0; 24543b6c3722Schristos socklen_t len = (socklen_t)sizeof(error); 24553b6c3722Schristos if(getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&error, 24563b6c3722Schristos &len) < 0){ 24573b6c3722Schristos #ifndef USE_WINSOCK 24583b6c3722Schristos error = errno; /* on solaris errno is error */ 24593b6c3722Schristos #else /* USE_WINSOCK */ 24603b6c3722Schristos error = WSAGetLastError(); 24613b6c3722Schristos #endif 24623b6c3722Schristos } 24633b6c3722Schristos #ifndef USE_WINSOCK 24643b6c3722Schristos #if defined(EINPROGRESS) && defined(EWOULDBLOCK) 24653b6c3722Schristos if(error == EINPROGRESS || error == EWOULDBLOCK) 24663b6c3722Schristos return 1; /* try again later */ 24673b6c3722Schristos else 24683b6c3722Schristos #endif 24693b6c3722Schristos if(error != 0 && verbosity < 2) 24703b6c3722Schristos return 0; /* silence lots of chatter in the logs */ 24713b6c3722Schristos else if(error != 0) { 24723b6c3722Schristos log_err_addr("tcp connect", strerror(error), 2473*14b2fa6eSchristos &c->repinfo.remote_addr, 2474*14b2fa6eSchristos c->repinfo.remote_addrlen); 24753b6c3722Schristos #else /* USE_WINSOCK */ 24763b6c3722Schristos /* examine error */ 24773b6c3722Schristos if(error == WSAEINPROGRESS) 24783b6c3722Schristos return 1; 24793b6c3722Schristos else if(error == WSAEWOULDBLOCK) { 24803b6c3722Schristos ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE); 24813b6c3722Schristos return 1; 24823b6c3722Schristos } else if(error != 0 && verbosity < 2) 24833b6c3722Schristos return 0; 24843b6c3722Schristos else if(error != 0) { 24853b6c3722Schristos log_err_addr("tcp connect", wsa_strerror(error), 2486*14b2fa6eSchristos &c->repinfo.remote_addr, 2487*14b2fa6eSchristos c->repinfo.remote_addrlen); 24883b6c3722Schristos #endif /* USE_WINSOCK */ 24893b6c3722Schristos return 0; 24903b6c3722Schristos } 24913b6c3722Schristos } 24923b6c3722Schristos if(c->ssl) 249316776186Schristos return ssl_handle_it(c, 1); 24943b6c3722Schristos 24950cd9f4ecSchristos #ifdef USE_MSG_FASTOPEN 24960cd9f4ecSchristos /* Only try this on first use of a connection that uses tfo, 24970cd9f4ecSchristos otherwise fall through to normal write */ 24980cd9f4ecSchristos /* Also, TFO support on WINDOWS not implemented at the moment */ 24990cd9f4ecSchristos if(c->tcp_do_fastopen == 1) { 25000cd9f4ecSchristos /* this form of sendmsg() does both a connect() and send() so need to 25010cd9f4ecSchristos look for various flavours of error*/ 250216776186Schristos uint16_t len = htons(c->tcp_write_and_read?c->tcp_write_pkt_len:sldns_buffer_limit(buffer)); 25030cd9f4ecSchristos struct msghdr msg; 25040cd9f4ecSchristos struct iovec iov[2]; 25050cd9f4ecSchristos c->tcp_do_fastopen = 0; 25060cd9f4ecSchristos memset(&msg, 0, sizeof(msg)); 250716776186Schristos if(c->tcp_write_and_read) { 250816776186Schristos iov[0].iov_base = (uint8_t*)&len + c->tcp_write_byte_count; 250916776186Schristos iov[0].iov_len = sizeof(uint16_t) - c->tcp_write_byte_count; 251016776186Schristos iov[1].iov_base = c->tcp_write_pkt; 251116776186Schristos iov[1].iov_len = c->tcp_write_pkt_len; 251216776186Schristos } else { 25130cd9f4ecSchristos iov[0].iov_base = (uint8_t*)&len + c->tcp_byte_count; 25140cd9f4ecSchristos iov[0].iov_len = sizeof(uint16_t) - c->tcp_byte_count; 25150cd9f4ecSchristos iov[1].iov_base = sldns_buffer_begin(buffer); 25160cd9f4ecSchristos iov[1].iov_len = sldns_buffer_limit(buffer); 251716776186Schristos } 25180cd9f4ecSchristos log_assert(iov[0].iov_len > 0); 2519*14b2fa6eSchristos msg.msg_name = &c->repinfo.remote_addr; 2520*14b2fa6eSchristos msg.msg_namelen = c->repinfo.remote_addrlen; 25210cd9f4ecSchristos msg.msg_iov = iov; 25220cd9f4ecSchristos msg.msg_iovlen = 2; 25230cd9f4ecSchristos r = sendmsg(fd, &msg, MSG_FASTOPEN); 25240cd9f4ecSchristos if (r == -1) { 25250cd9f4ecSchristos #if defined(EINPROGRESS) && defined(EWOULDBLOCK) 25260cd9f4ecSchristos /* Handshake is underway, maybe because no TFO cookie available. 25270cd9f4ecSchristos Come back to write the message*/ 25280cd9f4ecSchristos if(errno == EINPROGRESS || errno == EWOULDBLOCK) 25290cd9f4ecSchristos return 1; 25300cd9f4ecSchristos #endif 25310cd9f4ecSchristos if(errno == EINTR || errno == EAGAIN) 25320cd9f4ecSchristos return 1; 25330cd9f4ecSchristos /* Not handling EISCONN here as shouldn't ever hit that case.*/ 25341481e2a9Schristos if(errno != EPIPE 25351481e2a9Schristos #ifdef EOPNOTSUPP 25361481e2a9Schristos /* if /proc/sys/net/ipv4/tcp_fastopen is 25371481e2a9Schristos * disabled on Linux, sendmsg may return 25381481e2a9Schristos * 'Operation not supported', if so 25391481e2a9Schristos * fallthrough to ordinary connect. */ 25401481e2a9Schristos && errno != EOPNOTSUPP 25411481e2a9Schristos #endif 25421481e2a9Schristos && errno != 0) { 25431481e2a9Schristos if(verbosity < 2) 25440cd9f4ecSchristos return 0; /* silence lots of chatter in the logs */ 25450cd9f4ecSchristos log_err_addr("tcp sendmsg", strerror(errno), 2546*14b2fa6eSchristos &c->repinfo.remote_addr, 2547*14b2fa6eSchristos c->repinfo.remote_addrlen); 25480cd9f4ecSchristos return 0; 25490cd9f4ecSchristos } 25501481e2a9Schristos verbose(VERB_ALGO, "tcp sendmsg for fastopen failed (with %s), try normal connect", strerror(errno)); 25510cd9f4ecSchristos /* fallthrough to nonFASTOPEN 25520cd9f4ecSchristos * (MSG_FASTOPEN on Linux 3 produces EPIPE) 25530cd9f4ecSchristos * we need to perform connect() */ 2554*14b2fa6eSchristos if(connect(fd, (struct sockaddr *)&c->repinfo.remote_addr, 2555*14b2fa6eSchristos c->repinfo.remote_addrlen) == -1) { 25560cd9f4ecSchristos #ifdef EINPROGRESS 25570cd9f4ecSchristos if(errno == EINPROGRESS) 25580cd9f4ecSchristos return 1; /* wait until connect done*/ 25590cd9f4ecSchristos #endif 25600cd9f4ecSchristos #ifdef USE_WINSOCK 25610cd9f4ecSchristos if(WSAGetLastError() == WSAEINPROGRESS || 25620cd9f4ecSchristos WSAGetLastError() == WSAEWOULDBLOCK) 25630cd9f4ecSchristos return 1; /* wait until connect done*/ 25640cd9f4ecSchristos #endif 25650cd9f4ecSchristos if(tcp_connect_errno_needs_log( 2566*14b2fa6eSchristos (struct sockaddr *)&c->repinfo.remote_addr, 2567*14b2fa6eSchristos c->repinfo.remote_addrlen)) { 25680cd9f4ecSchristos log_err_addr("outgoing tcp: connect after EPIPE for fastopen", 2569*14b2fa6eSchristos strerror(errno), 2570*14b2fa6eSchristos &c->repinfo.remote_addr, 2571*14b2fa6eSchristos c->repinfo.remote_addrlen); 25720cd9f4ecSchristos } 25730cd9f4ecSchristos return 0; 25740cd9f4ecSchristos } 25750cd9f4ecSchristos 25760cd9f4ecSchristos } else { 257716776186Schristos if(c->tcp_write_and_read) { 257816776186Schristos c->tcp_write_byte_count += r; 257916776186Schristos if(c->tcp_write_byte_count < sizeof(uint16_t)) 258016776186Schristos return 1; 258116776186Schristos } else { 25820cd9f4ecSchristos c->tcp_byte_count += r; 25830cd9f4ecSchristos if(c->tcp_byte_count < sizeof(uint16_t)) 25840cd9f4ecSchristos return 1; 25850cd9f4ecSchristos sldns_buffer_set_position(buffer, c->tcp_byte_count - 25860cd9f4ecSchristos sizeof(uint16_t)); 258716776186Schristos } 258816776186Schristos if((!c->tcp_write_and_read && sldns_buffer_remaining(buffer) == 0) || (c->tcp_write_and_read && c->tcp_write_byte_count == c->tcp_write_pkt_len + 2)) { 25890cd9f4ecSchristos tcp_callback_writer(c); 25900cd9f4ecSchristos return 1; 25910cd9f4ecSchristos } 25920cd9f4ecSchristos } 25930cd9f4ecSchristos } 25940cd9f4ecSchristos #endif /* USE_MSG_FASTOPEN */ 25950cd9f4ecSchristos 259616776186Schristos if((c->tcp_write_and_read?c->tcp_write_byte_count:c->tcp_byte_count) < sizeof(uint16_t)) { 259716776186Schristos uint16_t len = htons(c->tcp_write_and_read?c->tcp_write_pkt_len:sldns_buffer_limit(buffer)); 25983b6c3722Schristos #ifdef HAVE_WRITEV 25993b6c3722Schristos struct iovec iov[2]; 260016776186Schristos if(c->tcp_write_and_read) { 260116776186Schristos iov[0].iov_base = (uint8_t*)&len + c->tcp_write_byte_count; 260216776186Schristos iov[0].iov_len = sizeof(uint16_t) - c->tcp_write_byte_count; 260316776186Schristos iov[1].iov_base = c->tcp_write_pkt; 260416776186Schristos iov[1].iov_len = c->tcp_write_pkt_len; 260516776186Schristos } else { 26063b6c3722Schristos iov[0].iov_base = (uint8_t*)&len + c->tcp_byte_count; 26073b6c3722Schristos iov[0].iov_len = sizeof(uint16_t) - c->tcp_byte_count; 26080cd9f4ecSchristos iov[1].iov_base = sldns_buffer_begin(buffer); 26090cd9f4ecSchristos iov[1].iov_len = sldns_buffer_limit(buffer); 261016776186Schristos } 26113b6c3722Schristos log_assert(iov[0].iov_len > 0); 26123b6c3722Schristos r = writev(fd, iov, 2); 26133b6c3722Schristos #else /* HAVE_WRITEV */ 261416776186Schristos if(c->tcp_write_and_read) { 261516776186Schristos r = send(fd, (void*)(((uint8_t*)&len)+c->tcp_write_byte_count), 261616776186Schristos sizeof(uint16_t)-c->tcp_write_byte_count, 0); 261716776186Schristos } else { 26183b6c3722Schristos r = send(fd, (void*)(((uint8_t*)&len)+c->tcp_byte_count), 26193b6c3722Schristos sizeof(uint16_t)-c->tcp_byte_count, 0); 262016776186Schristos } 26213b6c3722Schristos #endif /* HAVE_WRITEV */ 26223b6c3722Schristos if(r == -1) { 26233b6c3722Schristos #ifndef USE_WINSOCK 26243b6c3722Schristos # ifdef EPIPE 26253b6c3722Schristos if(errno == EPIPE && verbosity < 2) 26263b6c3722Schristos return 0; /* silence 'broken pipe' */ 26273b6c3722Schristos #endif 26283b6c3722Schristos if(errno == EINTR || errno == EAGAIN) 26293b6c3722Schristos return 1; 263087edd195Schristos #ifdef ECONNRESET 263187edd195Schristos if(errno == ECONNRESET && verbosity < 2) 263287edd195Schristos return 0; /* silence reset by peer */ 263387edd195Schristos #endif 26343b6c3722Schristos # ifdef HAVE_WRITEV 26353b6c3722Schristos log_err_addr("tcp writev", strerror(errno), 2636*14b2fa6eSchristos &c->repinfo.remote_addr, 2637*14b2fa6eSchristos c->repinfo.remote_addrlen); 26383b6c3722Schristos # else /* HAVE_WRITEV */ 26393b6c3722Schristos log_err_addr("tcp send s", strerror(errno), 2640*14b2fa6eSchristos &c->repinfo.remote_addr, 2641*14b2fa6eSchristos c->repinfo.remote_addrlen); 26423b6c3722Schristos # endif /* HAVE_WRITEV */ 26433b6c3722Schristos #else 26443b6c3722Schristos if(WSAGetLastError() == WSAENOTCONN) 26453b6c3722Schristos return 1; 26463b6c3722Schristos if(WSAGetLastError() == WSAEINPROGRESS) 26473b6c3722Schristos return 1; 26483b6c3722Schristos if(WSAGetLastError() == WSAEWOULDBLOCK) { 26493b6c3722Schristos ub_winsock_tcp_wouldblock(c->ev->ev, 26503b6c3722Schristos UB_EV_WRITE); 26513b6c3722Schristos return 1; 26523b6c3722Schristos } 265387edd195Schristos if(WSAGetLastError() == WSAECONNRESET && verbosity < 2) 265487edd195Schristos return 0; /* silence reset by peer */ 26553b6c3722Schristos log_err_addr("tcp send s", 26563b6c3722Schristos wsa_strerror(WSAGetLastError()), 2657*14b2fa6eSchristos &c->repinfo.remote_addr, 2658*14b2fa6eSchristos c->repinfo.remote_addrlen); 26593b6c3722Schristos #endif 26603b6c3722Schristos return 0; 26613b6c3722Schristos } 266216776186Schristos if(c->tcp_write_and_read) { 266316776186Schristos c->tcp_write_byte_count += r; 266416776186Schristos if(c->tcp_write_byte_count < sizeof(uint16_t)) 266516776186Schristos return 1; 266616776186Schristos } else { 26673b6c3722Schristos c->tcp_byte_count += r; 26683b6c3722Schristos if(c->tcp_byte_count < sizeof(uint16_t)) 26693b6c3722Schristos return 1; 26700cd9f4ecSchristos sldns_buffer_set_position(buffer, c->tcp_byte_count - 26713b6c3722Schristos sizeof(uint16_t)); 267216776186Schristos } 267316776186Schristos if((!c->tcp_write_and_read && sldns_buffer_remaining(buffer) == 0) || (c->tcp_write_and_read && c->tcp_write_byte_count == c->tcp_write_pkt_len + 2)) { 26743b6c3722Schristos tcp_callback_writer(c); 26753b6c3722Schristos return 1; 26763b6c3722Schristos } 26773b6c3722Schristos } 267816776186Schristos log_assert(c->tcp_write_and_read || sldns_buffer_remaining(buffer) > 0); 267916776186Schristos log_assert(!c->tcp_write_and_read || c->tcp_write_byte_count < c->tcp_write_pkt_len + 2); 268016776186Schristos if(c->tcp_write_and_read) { 268116776186Schristos r = send(fd, (void*)(c->tcp_write_pkt + c->tcp_write_byte_count - 2), 268216776186Schristos c->tcp_write_pkt_len + 2 - c->tcp_write_byte_count, 0); 268316776186Schristos } else { 26840cd9f4ecSchristos r = send(fd, (void*)sldns_buffer_current(buffer), 26850cd9f4ecSchristos sldns_buffer_remaining(buffer), 0); 268616776186Schristos } 26873b6c3722Schristos if(r == -1) { 26883b6c3722Schristos #ifndef USE_WINSOCK 26893b6c3722Schristos if(errno == EINTR || errno == EAGAIN) 26903b6c3722Schristos return 1; 269187edd195Schristos #ifdef ECONNRESET 269287edd195Schristos if(errno == ECONNRESET && verbosity < 2) 269387edd195Schristos return 0; /* silence reset by peer */ 269487edd195Schristos #endif 26953b6c3722Schristos #else 26963b6c3722Schristos if(WSAGetLastError() == WSAEINPROGRESS) 26973b6c3722Schristos return 1; 26983b6c3722Schristos if(WSAGetLastError() == WSAEWOULDBLOCK) { 26993b6c3722Schristos ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE); 27003b6c3722Schristos return 1; 27013b6c3722Schristos } 270287edd195Schristos if(WSAGetLastError() == WSAECONNRESET && verbosity < 2) 270387edd195Schristos return 0; /* silence reset by peer */ 27043b6c3722Schristos #endif 270516776186Schristos log_err_addr("tcp send r", sock_strerror(errno), 2706*14b2fa6eSchristos &c->repinfo.remote_addr, 2707*14b2fa6eSchristos c->repinfo.remote_addrlen); 27083b6c3722Schristos return 0; 27093b6c3722Schristos } 271016776186Schristos if(c->tcp_write_and_read) { 271116776186Schristos c->tcp_write_byte_count += r; 271216776186Schristos } else { 27130cd9f4ecSchristos sldns_buffer_skip(buffer, r); 271416776186Schristos } 27153b6c3722Schristos 271616776186Schristos if((!c->tcp_write_and_read && sldns_buffer_remaining(buffer) == 0) || (c->tcp_write_and_read && c->tcp_write_byte_count == c->tcp_write_pkt_len + 2)) { 27173b6c3722Schristos tcp_callback_writer(c); 27183b6c3722Schristos } 27193b6c3722Schristos 27203b6c3722Schristos return 1; 27213b6c3722Schristos } 27223b6c3722Schristos 2723*14b2fa6eSchristos /** read again to drain buffers when there could be more to read, returns 0 2724*14b2fa6eSchristos * on failure which means the comm point is closed. */ 2725*14b2fa6eSchristos static int 2726f42d8de7Schristos tcp_req_info_read_again(int fd, struct comm_point* c) 2727f42d8de7Schristos { 2728f42d8de7Schristos while(c->tcp_req_info->read_again) { 2729f42d8de7Schristos int r; 2730f42d8de7Schristos c->tcp_req_info->read_again = 0; 2731f42d8de7Schristos if(c->tcp_is_reading) 2732f42d8de7Schristos r = comm_point_tcp_handle_read(fd, c, 0); 2733f42d8de7Schristos else r = comm_point_tcp_handle_write(fd, c); 2734f42d8de7Schristos if(!r) { 2735f42d8de7Schristos reclaim_tcp_handler(c); 2736f42d8de7Schristos if(!c->tcp_do_close) { 2737f42d8de7Schristos fptr_ok(fptr_whitelist_comm_point( 2738f42d8de7Schristos c->callback)); 2739f42d8de7Schristos (void)(*c->callback)(c, c->cb_arg, 2740f42d8de7Schristos NETEVENT_CLOSED, NULL); 2741f42d8de7Schristos } 2742*14b2fa6eSchristos return 0; 2743f42d8de7Schristos } 2744f42d8de7Schristos } 2745*14b2fa6eSchristos return 1; 2746f42d8de7Schristos } 2747f42d8de7Schristos 274816776186Schristos /** read again to drain buffers when there could be more to read */ 274916776186Schristos static void 275016776186Schristos tcp_more_read_again(int fd, struct comm_point* c) 275116776186Schristos { 275216776186Schristos /* if the packet is done, but another one could be waiting on 275316776186Schristos * the connection, the callback signals this, and we try again */ 275416776186Schristos /* this continues until the read routines get EAGAIN or so, 275516776186Schristos * and thus does not call the callback, and the bool is 0 */ 275616776186Schristos int* moreread = c->tcp_more_read_again; 275716776186Schristos while(moreread && *moreread) { 275816776186Schristos *moreread = 0; 275916776186Schristos if(!comm_point_tcp_handle_read(fd, c, 0)) { 276016776186Schristos reclaim_tcp_handler(c); 276116776186Schristos if(!c->tcp_do_close) { 276216776186Schristos fptr_ok(fptr_whitelist_comm_point( 276316776186Schristos c->callback)); 276416776186Schristos (void)(*c->callback)(c, c->cb_arg, 276516776186Schristos NETEVENT_CLOSED, NULL); 276616776186Schristos } 276716776186Schristos return; 276816776186Schristos } 276916776186Schristos } 277016776186Schristos } 277116776186Schristos 277216776186Schristos /** write again to fill up when there could be more to write */ 277316776186Schristos static void 277416776186Schristos tcp_more_write_again(int fd, struct comm_point* c) 277516776186Schristos { 277616776186Schristos /* if the packet is done, but another is waiting to be written, 277716776186Schristos * the callback signals it and we try again. */ 277816776186Schristos /* this continues until the write routines get EAGAIN or so, 277916776186Schristos * and thus does not call the callback, and the bool is 0 */ 278016776186Schristos int* morewrite = c->tcp_more_write_again; 278116776186Schristos while(morewrite && *morewrite) { 278216776186Schristos *morewrite = 0; 278316776186Schristos if(!comm_point_tcp_handle_write(fd, c)) { 278416776186Schristos reclaim_tcp_handler(c); 278516776186Schristos if(!c->tcp_do_close) { 278616776186Schristos fptr_ok(fptr_whitelist_comm_point( 278716776186Schristos c->callback)); 278816776186Schristos (void)(*c->callback)(c, c->cb_arg, 278916776186Schristos NETEVENT_CLOSED, NULL); 279016776186Schristos } 279116776186Schristos return; 279216776186Schristos } 279316776186Schristos } 279416776186Schristos } 279516776186Schristos 27963b6c3722Schristos void 27973b6c3722Schristos comm_point_tcp_handle_callback(int fd, short event, void* arg) 27983b6c3722Schristos { 27993b6c3722Schristos struct comm_point* c = (struct comm_point*)arg; 28003b6c3722Schristos log_assert(c->type == comm_tcp); 28013b6c3722Schristos ub_comm_base_now(c->ev->base); 28023b6c3722Schristos 2803*14b2fa6eSchristos if(c->fd == -1 || c->fd != fd) 2804*14b2fa6eSchristos return; /* duplicate event, but commpoint closed. */ 2805*14b2fa6eSchristos 28060cd9f4ecSchristos #ifdef USE_DNSCRYPT 28070cd9f4ecSchristos /* Initialize if this is a dnscrypt socket */ 28080cd9f4ecSchristos if(c->tcp_parent) { 28090cd9f4ecSchristos c->dnscrypt = c->tcp_parent->dnscrypt; 28100cd9f4ecSchristos } 28110cd9f4ecSchristos if(c->dnscrypt && c->dnscrypt_buffer == c->buffer) { 28120cd9f4ecSchristos c->dnscrypt_buffer = sldns_buffer_new(sldns_buffer_capacity(c->buffer)); 28130cd9f4ecSchristos if(!c->dnscrypt_buffer) { 28140cd9f4ecSchristos log_err("Could not allocate dnscrypt buffer"); 28150cd9f4ecSchristos reclaim_tcp_handler(c); 28160cd9f4ecSchristos if(!c->tcp_do_close) { 28170cd9f4ecSchristos fptr_ok(fptr_whitelist_comm_point( 28180cd9f4ecSchristos c->callback)); 28190cd9f4ecSchristos (void)(*c->callback)(c, c->cb_arg, 28200cd9f4ecSchristos NETEVENT_CLOSED, NULL); 28210cd9f4ecSchristos } 28220cd9f4ecSchristos return; 28230cd9f4ecSchristos } 28240cd9f4ecSchristos } 28250cd9f4ecSchristos #endif 28260cd9f4ecSchristos 282787edd195Schristos if(event&UB_EV_TIMEOUT) { 282887edd195Schristos verbose(VERB_QUERY, "tcp took too long, dropped"); 282987edd195Schristos reclaim_tcp_handler(c); 283087edd195Schristos if(!c->tcp_do_close) { 283187edd195Schristos fptr_ok(fptr_whitelist_comm_point(c->callback)); 283287edd195Schristos (void)(*c->callback)(c, c->cb_arg, 283387edd195Schristos NETEVENT_TIMEOUT, NULL); 283487edd195Schristos } 283587edd195Schristos return; 283687edd195Schristos } 283716776186Schristos if(event&UB_EV_READ 283816776186Schristos #ifdef USE_MSG_FASTOPEN 283916776186Schristos && !(c->tcp_do_fastopen && (event&UB_EV_WRITE)) 284016776186Schristos #endif 284116776186Schristos ) { 2842f42d8de7Schristos int has_tcpq = (c->tcp_req_info != NULL); 284316776186Schristos int* moreread = c->tcp_more_read_again; 28443b6c3722Schristos if(!comm_point_tcp_handle_read(fd, c, 0)) { 28453b6c3722Schristos reclaim_tcp_handler(c); 28463b6c3722Schristos if(!c->tcp_do_close) { 28473b6c3722Schristos fptr_ok(fptr_whitelist_comm_point( 28483b6c3722Schristos c->callback)); 28493b6c3722Schristos (void)(*c->callback)(c, c->cb_arg, 28503b6c3722Schristos NETEVENT_CLOSED, NULL); 28513b6c3722Schristos } 285216776186Schristos return; 28533b6c3722Schristos } 2854*14b2fa6eSchristos if(has_tcpq && c->tcp_req_info && c->tcp_req_info->read_again) { 2855*14b2fa6eSchristos if(!tcp_req_info_read_again(fd, c)) 2856*14b2fa6eSchristos return; 2857*14b2fa6eSchristos } 285816776186Schristos if(moreread && *moreread) 285916776186Schristos tcp_more_read_again(fd, c); 28603b6c3722Schristos return; 28613b6c3722Schristos } 28623b6c3722Schristos if(event&UB_EV_WRITE) { 2863f42d8de7Schristos int has_tcpq = (c->tcp_req_info != NULL); 286416776186Schristos int* morewrite = c->tcp_more_write_again; 28653b6c3722Schristos if(!comm_point_tcp_handle_write(fd, c)) { 28663b6c3722Schristos reclaim_tcp_handler(c); 28673b6c3722Schristos if(!c->tcp_do_close) { 28683b6c3722Schristos fptr_ok(fptr_whitelist_comm_point( 28693b6c3722Schristos c->callback)); 28703b6c3722Schristos (void)(*c->callback)(c, c->cb_arg, 28713b6c3722Schristos NETEVENT_CLOSED, NULL); 28723b6c3722Schristos } 287316776186Schristos return; 28743b6c3722Schristos } 2875*14b2fa6eSchristos if(has_tcpq && c->tcp_req_info && c->tcp_req_info->read_again) { 2876*14b2fa6eSchristos if(!tcp_req_info_read_again(fd, c)) 2877*14b2fa6eSchristos return; 2878*14b2fa6eSchristos } 287916776186Schristos if(morewrite && *morewrite) 288016776186Schristos tcp_more_write_again(fd, c); 28813b6c3722Schristos return; 28823b6c3722Schristos } 28833b6c3722Schristos log_err("Ignored event %d for tcphdl.", event); 28843b6c3722Schristos } 28853b6c3722Schristos 28867cd94d69Schristos /** Make http handler free for next assignment */ 28877cd94d69Schristos static void 28887cd94d69Schristos reclaim_http_handler(struct comm_point* c) 28897cd94d69Schristos { 28907cd94d69Schristos log_assert(c->type == comm_http); 28917cd94d69Schristos if(c->ssl) { 28927cd94d69Schristos #ifdef HAVE_SSL 28937cd94d69Schristos SSL_shutdown(c->ssl); 28947cd94d69Schristos SSL_free(c->ssl); 28957cd94d69Schristos c->ssl = NULL; 28967cd94d69Schristos #endif 28977cd94d69Schristos } 28987cd94d69Schristos comm_point_close(c); 28997cd94d69Schristos if(c->tcp_parent) { 29001481e2a9Schristos if(c != c->tcp_parent->tcp_free) { 29017cd94d69Schristos c->tcp_parent->cur_tcp_count--; 29027cd94d69Schristos c->tcp_free = c->tcp_parent->tcp_free; 29037cd94d69Schristos c->tcp_parent->tcp_free = c; 29041481e2a9Schristos } 29057cd94d69Schristos if(!c->tcp_free) { 29067cd94d69Schristos /* re-enable listening on accept socket */ 29077cd94d69Schristos comm_point_start_listening(c->tcp_parent, -1, -1); 29087cd94d69Schristos } 29097cd94d69Schristos } 29107cd94d69Schristos } 29117cd94d69Schristos 29127cd94d69Schristos /** read more data for http (with ssl) */ 29137cd94d69Schristos static int 29147cd94d69Schristos ssl_http_read_more(struct comm_point* c) 29157cd94d69Schristos { 29167cd94d69Schristos #ifdef HAVE_SSL 29177cd94d69Schristos int r; 29187cd94d69Schristos log_assert(sldns_buffer_remaining(c->buffer) > 0); 29197cd94d69Schristos ERR_clear_error(); 29207cd94d69Schristos r = SSL_read(c->ssl, (void*)sldns_buffer_current(c->buffer), 29217cd94d69Schristos (int)sldns_buffer_remaining(c->buffer)); 29227cd94d69Schristos if(r <= 0) { 29237cd94d69Schristos int want = SSL_get_error(c->ssl, r); 29247cd94d69Schristos if(want == SSL_ERROR_ZERO_RETURN) { 29257cd94d69Schristos return 0; /* shutdown, closed */ 29267cd94d69Schristos } else if(want == SSL_ERROR_WANT_READ) { 29277cd94d69Schristos return 1; /* read more later */ 29287cd94d69Schristos } else if(want == SSL_ERROR_WANT_WRITE) { 29297cd94d69Schristos c->ssl_shake_state = comm_ssl_shake_hs_write; 29307cd94d69Schristos comm_point_listen_for_rw(c, 0, 1); 29317cd94d69Schristos return 1; 29327cd94d69Schristos } else if(want == SSL_ERROR_SYSCALL) { 293387edd195Schristos #ifdef ECONNRESET 293487edd195Schristos if(errno == ECONNRESET && verbosity < 2) 293587edd195Schristos return 0; /* silence reset by peer */ 293687edd195Schristos #endif 29377cd94d69Schristos if(errno != 0) 29387cd94d69Schristos log_err("SSL_read syscall: %s", 29397cd94d69Schristos strerror(errno)); 29407cd94d69Schristos return 0; 29417cd94d69Schristos } 2942*14b2fa6eSchristos log_crypto_err_io("could not SSL_read", want); 29437cd94d69Schristos return 0; 29447cd94d69Schristos } 29451481e2a9Schristos verbose(VERB_ALGO, "ssl http read more skip to %d + %d", 29461481e2a9Schristos (int)sldns_buffer_position(c->buffer), (int)r); 29477cd94d69Schristos sldns_buffer_skip(c->buffer, (ssize_t)r); 29487cd94d69Schristos return 1; 29497cd94d69Schristos #else 29507cd94d69Schristos (void)c; 29517cd94d69Schristos return 0; 29527cd94d69Schristos #endif /* HAVE_SSL */ 29537cd94d69Schristos } 29547cd94d69Schristos 29557cd94d69Schristos /** read more data for http */ 29567cd94d69Schristos static int 29577cd94d69Schristos http_read_more(int fd, struct comm_point* c) 29587cd94d69Schristos { 29597cd94d69Schristos ssize_t r; 29607cd94d69Schristos log_assert(sldns_buffer_remaining(c->buffer) > 0); 29617cd94d69Schristos r = recv(fd, (void*)sldns_buffer_current(c->buffer), 2962*14b2fa6eSchristos sldns_buffer_remaining(c->buffer), MSG_DONTWAIT); 29637cd94d69Schristos if(r == 0) { 29647cd94d69Schristos return 0; 29657cd94d69Schristos } else if(r == -1) { 29667cd94d69Schristos #ifndef USE_WINSOCK 29677cd94d69Schristos if(errno == EINTR || errno == EAGAIN) 29687cd94d69Schristos return 1; 29697cd94d69Schristos #else /* USE_WINSOCK */ 29707cd94d69Schristos if(WSAGetLastError() == WSAECONNRESET) 29717cd94d69Schristos return 0; 29727cd94d69Schristos if(WSAGetLastError() == WSAEINPROGRESS) 29737cd94d69Schristos return 1; 29747cd94d69Schristos if(WSAGetLastError() == WSAEWOULDBLOCK) { 29757cd94d69Schristos ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_READ); 29767cd94d69Schristos return 1; 29777cd94d69Schristos } 29787cd94d69Schristos #endif 297916776186Schristos log_err_addr("read (in http r)", sock_strerror(errno), 2980*14b2fa6eSchristos &c->repinfo.remote_addr, c->repinfo.remote_addrlen); 29817cd94d69Schristos return 0; 29827cd94d69Schristos } 29831481e2a9Schristos verbose(VERB_ALGO, "http read more skip to %d + %d", 29841481e2a9Schristos (int)sldns_buffer_position(c->buffer), (int)r); 29857cd94d69Schristos sldns_buffer_skip(c->buffer, r); 29867cd94d69Schristos return 1; 29877cd94d69Schristos } 29887cd94d69Schristos 29897cd94d69Schristos /** return true if http header has been read (one line complete) */ 29907cd94d69Schristos static int 29917cd94d69Schristos http_header_done(sldns_buffer* buf) 29927cd94d69Schristos { 29937cd94d69Schristos size_t i; 29947cd94d69Schristos for(i=sldns_buffer_position(buf); i<sldns_buffer_limit(buf); i++) { 29957cd94d69Schristos /* there was a \r before the \n, but we ignore that */ 29967cd94d69Schristos if((char)sldns_buffer_read_u8_at(buf, i) == '\n') 29977cd94d69Schristos return 1; 29987cd94d69Schristos } 29997cd94d69Schristos return 0; 30007cd94d69Schristos } 30017cd94d69Schristos 30027cd94d69Schristos /** return character string into buffer for header line, moves buffer 30037cd94d69Schristos * past that line and puts zero terminator into linefeed-newline */ 30047cd94d69Schristos static char* 30057cd94d69Schristos http_header_line(sldns_buffer* buf) 30067cd94d69Schristos { 30077cd94d69Schristos char* result = (char*)sldns_buffer_current(buf); 30087cd94d69Schristos size_t i; 30097cd94d69Schristos for(i=sldns_buffer_position(buf); i<sldns_buffer_limit(buf); i++) { 30107cd94d69Schristos /* terminate the string on the \r */ 30117cd94d69Schristos if((char)sldns_buffer_read_u8_at(buf, i) == '\r') 30127cd94d69Schristos sldns_buffer_write_u8_at(buf, i, 0); 30137cd94d69Schristos /* terminate on the \n and skip past the it and done */ 30147cd94d69Schristos if((char)sldns_buffer_read_u8_at(buf, i) == '\n') { 30157cd94d69Schristos sldns_buffer_write_u8_at(buf, i, 0); 30167cd94d69Schristos sldns_buffer_set_position(buf, i+1); 30177cd94d69Schristos return result; 30187cd94d69Schristos } 30197cd94d69Schristos } 30207cd94d69Schristos return NULL; 30217cd94d69Schristos } 30227cd94d69Schristos 30237cd94d69Schristos /** move unread buffer to start and clear rest for putting the rest into it */ 30247cd94d69Schristos static void 30257cd94d69Schristos http_moveover_buffer(sldns_buffer* buf) 30267cd94d69Schristos { 30277cd94d69Schristos size_t pos = sldns_buffer_position(buf); 30287cd94d69Schristos size_t len = sldns_buffer_remaining(buf); 30297cd94d69Schristos sldns_buffer_clear(buf); 30307cd94d69Schristos memmove(sldns_buffer_begin(buf), sldns_buffer_at(buf, pos), len); 30317cd94d69Schristos sldns_buffer_set_position(buf, len); 30327cd94d69Schristos } 30337cd94d69Schristos 30347cd94d69Schristos /** a http header is complete, process it */ 30357cd94d69Schristos static int 30367cd94d69Schristos http_process_initial_header(struct comm_point* c) 30377cd94d69Schristos { 30387cd94d69Schristos char* line = http_header_line(c->buffer); 30397cd94d69Schristos if(!line) return 1; 30407cd94d69Schristos verbose(VERB_ALGO, "http header: %s", line); 30417cd94d69Schristos if(strncasecmp(line, "HTTP/1.1 ", 9) == 0) { 30427cd94d69Schristos /* check returncode */ 30437cd94d69Schristos if(line[9] != '2') { 30447cd94d69Schristos verbose(VERB_ALGO, "http bad status %s", line+9); 30457cd94d69Schristos return 0; 30467cd94d69Schristos } 30477cd94d69Schristos } else if(strncasecmp(line, "Content-Length: ", 16) == 0) { 30487cd94d69Schristos if(!c->http_is_chunked) 30497cd94d69Schristos c->tcp_byte_count = (size_t)atoi(line+16); 30507cd94d69Schristos } else if(strncasecmp(line, "Transfer-Encoding: chunked", 19+7) == 0) { 30517cd94d69Schristos c->tcp_byte_count = 0; 30527cd94d69Schristos c->http_is_chunked = 1; 30537cd94d69Schristos } else if(line[0] == 0) { 30547cd94d69Schristos /* end of initial headers */ 30557cd94d69Schristos c->http_in_headers = 0; 30567cd94d69Schristos if(c->http_is_chunked) 30577cd94d69Schristos c->http_in_chunk_headers = 1; 30587cd94d69Schristos /* remove header text from front of buffer 30597cd94d69Schristos * the buffer is going to be used to return the data segment 30607cd94d69Schristos * itself and we don't want the header to get returned 30617cd94d69Schristos * prepended with it */ 30627cd94d69Schristos http_moveover_buffer(c->buffer); 30637cd94d69Schristos sldns_buffer_flip(c->buffer); 30647cd94d69Schristos return 1; 30657cd94d69Schristos } 30667cd94d69Schristos /* ignore other headers */ 30677cd94d69Schristos return 1; 30687cd94d69Schristos } 30697cd94d69Schristos 30707cd94d69Schristos /** a chunk header is complete, process it, return 0=fail, 1=continue next 30717cd94d69Schristos * header line, 2=done with chunked transfer*/ 30727cd94d69Schristos static int 30737cd94d69Schristos http_process_chunk_header(struct comm_point* c) 30747cd94d69Schristos { 30757cd94d69Schristos char* line = http_header_line(c->buffer); 30767cd94d69Schristos if(!line) return 1; 30777cd94d69Schristos if(c->http_in_chunk_headers == 3) { 30787cd94d69Schristos verbose(VERB_ALGO, "http chunk trailer: %s", line); 30797cd94d69Schristos /* are we done ? */ 30807cd94d69Schristos if(line[0] == 0 && c->tcp_byte_count == 0) { 30817cd94d69Schristos /* callback of http reader when NETEVENT_DONE, 30827cd94d69Schristos * end of data, with no data in buffer */ 30837cd94d69Schristos sldns_buffer_set_position(c->buffer, 0); 30847cd94d69Schristos sldns_buffer_set_limit(c->buffer, 0); 30857cd94d69Schristos fptr_ok(fptr_whitelist_comm_point(c->callback)); 30867cd94d69Schristos (void)(*c->callback)(c, c->cb_arg, NETEVENT_DONE, NULL); 30877cd94d69Schristos /* return that we are done */ 30887cd94d69Schristos return 2; 30897cd94d69Schristos } 30907cd94d69Schristos if(line[0] == 0) { 30917cd94d69Schristos /* continue with header of the next chunk */ 30927cd94d69Schristos c->http_in_chunk_headers = 1; 30937cd94d69Schristos /* remove header text from front of buffer */ 30947cd94d69Schristos http_moveover_buffer(c->buffer); 30957cd94d69Schristos sldns_buffer_flip(c->buffer); 30967cd94d69Schristos return 1; 30977cd94d69Schristos } 30987cd94d69Schristos /* ignore further trail headers */ 30997cd94d69Schristos return 1; 31007cd94d69Schristos } 31017cd94d69Schristos verbose(VERB_ALGO, "http chunk header: %s", line); 31027cd94d69Schristos if(c->http_in_chunk_headers == 1) { 31037cd94d69Schristos /* read chunked start line */ 31047cd94d69Schristos char* end = NULL; 31057cd94d69Schristos c->tcp_byte_count = (size_t)strtol(line, &end, 16); 31067cd94d69Schristos if(end == line) 31077cd94d69Schristos return 0; 31087cd94d69Schristos c->http_in_chunk_headers = 0; 31097cd94d69Schristos /* remove header text from front of buffer */ 31107cd94d69Schristos http_moveover_buffer(c->buffer); 31117cd94d69Schristos sldns_buffer_flip(c->buffer); 31127cd94d69Schristos if(c->tcp_byte_count == 0) { 31137cd94d69Schristos /* done with chunks, process chunk_trailer lines */ 31147cd94d69Schristos c->http_in_chunk_headers = 3; 31157cd94d69Schristos } 31167cd94d69Schristos return 1; 31177cd94d69Schristos } 31187cd94d69Schristos /* ignore other headers */ 31197cd94d69Schristos return 1; 31207cd94d69Schristos } 31217cd94d69Schristos 31221481e2a9Schristos /** handle nonchunked data segment, 0=fail, 1=wait */ 31237cd94d69Schristos static int 31247cd94d69Schristos http_nonchunk_segment(struct comm_point* c) 31257cd94d69Schristos { 31267cd94d69Schristos /* c->buffer at position..limit has new data we read in. 31277cd94d69Schristos * the buffer itself is full of nonchunked data. 31287cd94d69Schristos * we are looking to read tcp_byte_count more data 31297cd94d69Schristos * and then the transfer is done. */ 31307cd94d69Schristos size_t remainbufferlen; 31311481e2a9Schristos size_t got_now = sldns_buffer_limit(c->buffer); 31327cd94d69Schristos if(c->tcp_byte_count <= got_now) { 31337cd94d69Schristos /* done, this is the last data fragment */ 31347cd94d69Schristos c->http_stored = 0; 31357cd94d69Schristos sldns_buffer_set_position(c->buffer, 0); 31367cd94d69Schristos fptr_ok(fptr_whitelist_comm_point(c->callback)); 31377cd94d69Schristos (void)(*c->callback)(c, c->cb_arg, NETEVENT_DONE, NULL); 31387cd94d69Schristos return 1; 31397cd94d69Schristos } 31407cd94d69Schristos /* if we have the buffer space, 31417cd94d69Schristos * read more data collected into the buffer */ 31427cd94d69Schristos remainbufferlen = sldns_buffer_capacity(c->buffer) - 31437cd94d69Schristos sldns_buffer_limit(c->buffer); 31441481e2a9Schristos if(remainbufferlen+got_now >= c->tcp_byte_count || 31451481e2a9Schristos remainbufferlen >= (size_t)(c->ssl?16384:2048)) { 31467cd94d69Schristos size_t total = sldns_buffer_limit(c->buffer); 31477cd94d69Schristos sldns_buffer_clear(c->buffer); 31487cd94d69Schristos sldns_buffer_set_position(c->buffer, total); 31497cd94d69Schristos c->http_stored = total; 31507cd94d69Schristos /* return and wait to read more */ 31517cd94d69Schristos return 1; 31527cd94d69Schristos } 31537cd94d69Schristos /* call callback with this data amount, then 31547cd94d69Schristos * wait for more */ 31551481e2a9Schristos c->tcp_byte_count -= got_now; 31567cd94d69Schristos c->http_stored = 0; 31577cd94d69Schristos sldns_buffer_set_position(c->buffer, 0); 31587cd94d69Schristos fptr_ok(fptr_whitelist_comm_point(c->callback)); 31597cd94d69Schristos (void)(*c->callback)(c, c->cb_arg, NETEVENT_NOERROR, NULL); 31607cd94d69Schristos /* c->callback has to buffer_clear(c->buffer). */ 31617cd94d69Schristos /* return and wait to read more */ 31627cd94d69Schristos return 1; 31637cd94d69Schristos } 31647cd94d69Schristos 316516776186Schristos /** handle chunked data segment, return 0=fail, 1=wait, 2=process more */ 31667cd94d69Schristos static int 31677cd94d69Schristos http_chunked_segment(struct comm_point* c) 31687cd94d69Schristos { 31697cd94d69Schristos /* the c->buffer has from position..limit new data we read. */ 31707cd94d69Schristos /* the current chunk has length tcp_byte_count. 31717cd94d69Schristos * once we read that read more chunk headers. 31727cd94d69Schristos */ 31737cd94d69Schristos size_t remainbufferlen; 31747cd94d69Schristos size_t got_now = sldns_buffer_limit(c->buffer) - c->http_stored; 317516776186Schristos verbose(VERB_ALGO, "http_chunked_segment: got now %d, tcpbytcount %d, http_stored %d, buffer pos %d, buffer limit %d", (int)got_now, (int)c->tcp_byte_count, (int)c->http_stored, (int)sldns_buffer_position(c->buffer), (int)sldns_buffer_limit(c->buffer)); 31767cd94d69Schristos if(c->tcp_byte_count <= got_now) { 31777cd94d69Schristos /* the chunk has completed (with perhaps some extra data 31787cd94d69Schristos * from next chunk header and next chunk) */ 31797cd94d69Schristos /* save too much info into temp buffer */ 31807cd94d69Schristos size_t fraglen; 31817cd94d69Schristos struct comm_reply repinfo; 31827cd94d69Schristos c->http_stored = 0; 31837cd94d69Schristos sldns_buffer_skip(c->buffer, (ssize_t)c->tcp_byte_count); 31847cd94d69Schristos sldns_buffer_clear(c->http_temp); 31857cd94d69Schristos sldns_buffer_write(c->http_temp, 31867cd94d69Schristos sldns_buffer_current(c->buffer), 31877cd94d69Schristos sldns_buffer_remaining(c->buffer)); 31887cd94d69Schristos sldns_buffer_flip(c->http_temp); 31897cd94d69Schristos 31907cd94d69Schristos /* callback with this fragment */ 31917cd94d69Schristos fraglen = sldns_buffer_position(c->buffer); 31927cd94d69Schristos sldns_buffer_set_position(c->buffer, 0); 31937cd94d69Schristos sldns_buffer_set_limit(c->buffer, fraglen); 31947cd94d69Schristos repinfo = c->repinfo; 31957cd94d69Schristos fptr_ok(fptr_whitelist_comm_point(c->callback)); 31967cd94d69Schristos (void)(*c->callback)(c, c->cb_arg, NETEVENT_NOERROR, &repinfo); 31977cd94d69Schristos /* c->callback has to buffer_clear(). */ 31987cd94d69Schristos 31997cd94d69Schristos /* is commpoint deleted? */ 32007cd94d69Schristos if(!repinfo.c) { 32017cd94d69Schristos return 1; 32027cd94d69Schristos } 32037cd94d69Schristos /* copy waiting info */ 32047cd94d69Schristos sldns_buffer_clear(c->buffer); 32057cd94d69Schristos sldns_buffer_write(c->buffer, 32067cd94d69Schristos sldns_buffer_begin(c->http_temp), 32077cd94d69Schristos sldns_buffer_remaining(c->http_temp)); 32087cd94d69Schristos sldns_buffer_flip(c->buffer); 32097cd94d69Schristos /* process end of chunk trailer header lines, until 32107cd94d69Schristos * an empty line */ 32117cd94d69Schristos c->http_in_chunk_headers = 3; 32127cd94d69Schristos /* process more data in buffer (if any) */ 32137cd94d69Schristos return 2; 32147cd94d69Schristos } 32157cd94d69Schristos c->tcp_byte_count -= got_now; 32167cd94d69Schristos 32177cd94d69Schristos /* if we have the buffer space, 32187cd94d69Schristos * read more data collected into the buffer */ 32197cd94d69Schristos remainbufferlen = sldns_buffer_capacity(c->buffer) - 32207cd94d69Schristos sldns_buffer_limit(c->buffer); 32217cd94d69Schristos if(remainbufferlen >= c->tcp_byte_count || 32227cd94d69Schristos remainbufferlen >= 2048) { 32237cd94d69Schristos size_t total = sldns_buffer_limit(c->buffer); 32247cd94d69Schristos sldns_buffer_clear(c->buffer); 32257cd94d69Schristos sldns_buffer_set_position(c->buffer, total); 32267cd94d69Schristos c->http_stored = total; 32277cd94d69Schristos /* return and wait to read more */ 32287cd94d69Schristos return 1; 32297cd94d69Schristos } 32307cd94d69Schristos 32317cd94d69Schristos /* callback of http reader for a new part of the data */ 32327cd94d69Schristos c->http_stored = 0; 32337cd94d69Schristos sldns_buffer_set_position(c->buffer, 0); 32347cd94d69Schristos fptr_ok(fptr_whitelist_comm_point(c->callback)); 32357cd94d69Schristos (void)(*c->callback)(c, c->cb_arg, NETEVENT_NOERROR, NULL); 32367cd94d69Schristos /* c->callback has to buffer_clear(c->buffer). */ 32377cd94d69Schristos /* return and wait to read more */ 32387cd94d69Schristos return 1; 32397cd94d69Schristos } 32407cd94d69Schristos 324116776186Schristos #ifdef HAVE_NGHTTP2 324216776186Schristos /** Create new http2 session. Called when creating handling comm point. */ 324316776186Schristos static struct http2_session* http2_session_create(struct comm_point* c) 324416776186Schristos { 324516776186Schristos struct http2_session* session = calloc(1, sizeof(*session)); 324616776186Schristos if(!session) { 324716776186Schristos log_err("malloc failure while creating http2 session"); 324816776186Schristos return NULL; 324916776186Schristos } 325016776186Schristos session->c = c; 325116776186Schristos 325216776186Schristos return session; 325316776186Schristos } 325416776186Schristos #endif 325516776186Schristos 325616776186Schristos /** Delete http2 session. After closing connection or on error */ 325716776186Schristos static void http2_session_delete(struct http2_session* h2_session) 325816776186Schristos { 325916776186Schristos #ifdef HAVE_NGHTTP2 326016776186Schristos if(h2_session->callbacks) 326116776186Schristos nghttp2_session_callbacks_del(h2_session->callbacks); 326216776186Schristos free(h2_session); 326316776186Schristos #else 326416776186Schristos (void)h2_session; 326516776186Schristos #endif 326616776186Schristos } 326716776186Schristos 326816776186Schristos #ifdef HAVE_NGHTTP2 326916776186Schristos struct http2_stream* http2_stream_create(int32_t stream_id) 327016776186Schristos { 327116776186Schristos struct http2_stream* h2_stream = calloc(1, sizeof(*h2_stream)); 327216776186Schristos if(!h2_stream) { 327316776186Schristos log_err("malloc failure while creating http2 stream"); 327416776186Schristos return NULL; 327516776186Schristos } 327616776186Schristos h2_stream->stream_id = stream_id; 327716776186Schristos return h2_stream; 327816776186Schristos } 327916776186Schristos 328016776186Schristos /** Delete http2 stream. After session delete or stream close callback */ 328116776186Schristos static void http2_stream_delete(struct http2_session* h2_session, 328216776186Schristos struct http2_stream* h2_stream) 328316776186Schristos { 328416776186Schristos if(h2_stream->mesh_state) { 328516776186Schristos mesh_state_remove_reply(h2_stream->mesh, h2_stream->mesh_state, 328616776186Schristos h2_session->c); 328716776186Schristos h2_stream->mesh_state = NULL; 328816776186Schristos } 328916776186Schristos http2_req_stream_clear(h2_stream); 329016776186Schristos free(h2_stream); 329116776186Schristos } 329216776186Schristos #endif 329316776186Schristos 329416776186Schristos void http2_stream_add_meshstate(struct http2_stream* h2_stream, 329516776186Schristos struct mesh_area* mesh, struct mesh_state* m) 329616776186Schristos { 329716776186Schristos h2_stream->mesh = mesh; 329816776186Schristos h2_stream->mesh_state = m; 329916776186Schristos } 330016776186Schristos 330116776186Schristos /** delete http2 session server. After closing connection. */ 330216776186Schristos static void http2_session_server_delete(struct http2_session* h2_session) 330316776186Schristos { 330416776186Schristos #ifdef HAVE_NGHTTP2 330516776186Schristos struct http2_stream* h2_stream, *next; 330616776186Schristos nghttp2_session_del(h2_session->session); /* NULL input is fine */ 330716776186Schristos h2_session->session = NULL; 330816776186Schristos for(h2_stream = h2_session->first_stream; h2_stream;) { 330916776186Schristos next = h2_stream->next; 331016776186Schristos http2_stream_delete(h2_session, h2_stream); 331116776186Schristos h2_stream = next; 331216776186Schristos } 331316776186Schristos h2_session->first_stream = NULL; 331416776186Schristos h2_session->is_drop = 0; 331516776186Schristos h2_session->postpone_drop = 0; 331616776186Schristos h2_session->c->h2_stream = NULL; 331716776186Schristos #endif 331816776186Schristos (void)h2_session; 331916776186Schristos } 332016776186Schristos 332116776186Schristos #ifdef HAVE_NGHTTP2 332216776186Schristos void http2_session_add_stream(struct http2_session* h2_session, 332316776186Schristos struct http2_stream* h2_stream) 332416776186Schristos { 332516776186Schristos if(h2_session->first_stream) 332616776186Schristos h2_session->first_stream->prev = h2_stream; 332716776186Schristos h2_stream->next = h2_session->first_stream; 332816776186Schristos h2_session->first_stream = h2_stream; 332916776186Schristos } 333016776186Schristos 333116776186Schristos /** remove stream from session linked list. After stream close callback or 333216776186Schristos * closing connection */ 333316776186Schristos static void http2_session_remove_stream(struct http2_session* h2_session, 333416776186Schristos struct http2_stream* h2_stream) 333516776186Schristos { 333616776186Schristos if(h2_stream->prev) 333716776186Schristos h2_stream->prev->next = h2_stream->next; 333816776186Schristos else 333916776186Schristos h2_session->first_stream = h2_stream->next; 334016776186Schristos if(h2_stream->next) 334116776186Schristos h2_stream->next->prev = h2_stream->prev; 334216776186Schristos 334316776186Schristos } 334416776186Schristos 334516776186Schristos int http2_stream_close_cb(nghttp2_session* ATTR_UNUSED(session), 334616776186Schristos int32_t stream_id, uint32_t ATTR_UNUSED(error_code), void* cb_arg) 334716776186Schristos { 334816776186Schristos struct http2_stream* h2_stream; 334916776186Schristos struct http2_session* h2_session = (struct http2_session*)cb_arg; 335016776186Schristos if(!(h2_stream = nghttp2_session_get_stream_user_data( 335116776186Schristos h2_session->session, stream_id))) { 335216776186Schristos return 0; 335316776186Schristos } 335416776186Schristos http2_session_remove_stream(h2_session, h2_stream); 335516776186Schristos http2_stream_delete(h2_session, h2_stream); 335616776186Schristos return 0; 335716776186Schristos } 335816776186Schristos 335916776186Schristos ssize_t http2_recv_cb(nghttp2_session* ATTR_UNUSED(session), uint8_t* buf, 336016776186Schristos size_t len, int ATTR_UNUSED(flags), void* cb_arg) 336116776186Schristos { 336216776186Schristos struct http2_session* h2_session = (struct http2_session*)cb_arg; 336316776186Schristos ssize_t ret; 336416776186Schristos 336516776186Schristos log_assert(h2_session->c->type == comm_http); 336616776186Schristos log_assert(h2_session->c->h2_session); 336716776186Schristos 336816776186Schristos #ifdef HAVE_SSL 336916776186Schristos if(h2_session->c->ssl) { 337016776186Schristos int r; 337116776186Schristos ERR_clear_error(); 337216776186Schristos r = SSL_read(h2_session->c->ssl, buf, len); 337316776186Schristos if(r <= 0) { 337416776186Schristos int want = SSL_get_error(h2_session->c->ssl, r); 337516776186Schristos if(want == SSL_ERROR_ZERO_RETURN) { 337616776186Schristos return NGHTTP2_ERR_EOF; 337716776186Schristos } else if(want == SSL_ERROR_WANT_READ) { 337816776186Schristos return NGHTTP2_ERR_WOULDBLOCK; 337916776186Schristos } else if(want == SSL_ERROR_WANT_WRITE) { 338016776186Schristos h2_session->c->ssl_shake_state = comm_ssl_shake_hs_write; 338116776186Schristos comm_point_listen_for_rw(h2_session->c, 0, 1); 338216776186Schristos return NGHTTP2_ERR_WOULDBLOCK; 338316776186Schristos } else if(want == SSL_ERROR_SYSCALL) { 338416776186Schristos #ifdef ECONNRESET 338516776186Schristos if(errno == ECONNRESET && verbosity < 2) 338616776186Schristos return NGHTTP2_ERR_CALLBACK_FAILURE; 338716776186Schristos #endif 338816776186Schristos if(errno != 0) 338916776186Schristos log_err("SSL_read syscall: %s", 339016776186Schristos strerror(errno)); 339116776186Schristos return NGHTTP2_ERR_CALLBACK_FAILURE; 339216776186Schristos } 3393*14b2fa6eSchristos log_crypto_err_io("could not SSL_read", want); 339416776186Schristos return NGHTTP2_ERR_CALLBACK_FAILURE; 339516776186Schristos } 339616776186Schristos return r; 339716776186Schristos } 339816776186Schristos #endif /* HAVE_SSL */ 339916776186Schristos 3400*14b2fa6eSchristos ret = recv(h2_session->c->fd, buf, len, MSG_DONTWAIT); 340116776186Schristos if(ret == 0) { 340216776186Schristos return NGHTTP2_ERR_EOF; 340316776186Schristos } else if(ret < 0) { 340416776186Schristos #ifndef USE_WINSOCK 340516776186Schristos if(errno == EINTR || errno == EAGAIN) 340616776186Schristos return NGHTTP2_ERR_WOULDBLOCK; 340716776186Schristos #ifdef ECONNRESET 340816776186Schristos if(errno == ECONNRESET && verbosity < 2) 340916776186Schristos return NGHTTP2_ERR_CALLBACK_FAILURE; 341016776186Schristos #endif 341116776186Schristos log_err_addr("could not http2 recv: %s", strerror(errno), 3412*14b2fa6eSchristos &h2_session->c->repinfo.remote_addr, 3413*14b2fa6eSchristos h2_session->c->repinfo.remote_addrlen); 341416776186Schristos #else /* USE_WINSOCK */ 341516776186Schristos if(WSAGetLastError() == WSAECONNRESET) 341616776186Schristos return NGHTTP2_ERR_CALLBACK_FAILURE; 341716776186Schristos if(WSAGetLastError() == WSAEINPROGRESS) 341816776186Schristos return NGHTTP2_ERR_WOULDBLOCK; 341916776186Schristos if(WSAGetLastError() == WSAEWOULDBLOCK) { 342016776186Schristos ub_winsock_tcp_wouldblock(h2_session->c->ev->ev, 342116776186Schristos UB_EV_READ); 342216776186Schristos return NGHTTP2_ERR_WOULDBLOCK; 342316776186Schristos } 342416776186Schristos log_err_addr("could not http2 recv: %s", 342516776186Schristos wsa_strerror(WSAGetLastError()), 3426*14b2fa6eSchristos &h2_session->c->repinfo.remote_addr, 3427*14b2fa6eSchristos h2_session->c->repinfo.remote_addrlen); 342816776186Schristos #endif 342916776186Schristos return NGHTTP2_ERR_CALLBACK_FAILURE; 343016776186Schristos } 343116776186Schristos return ret; 343216776186Schristos } 343316776186Schristos #endif /* HAVE_NGHTTP2 */ 343416776186Schristos 343516776186Schristos /** Handle http2 read */ 343616776186Schristos static int 343716776186Schristos comm_point_http2_handle_read(int ATTR_UNUSED(fd), struct comm_point* c) 343816776186Schristos { 343916776186Schristos #ifdef HAVE_NGHTTP2 344016776186Schristos int ret; 344116776186Schristos log_assert(c->h2_session); 344216776186Schristos 344316776186Schristos /* reading until recv cb returns NGHTTP2_ERR_WOULDBLOCK */ 344416776186Schristos ret = nghttp2_session_recv(c->h2_session->session); 344516776186Schristos if(ret) { 344616776186Schristos if(ret != NGHTTP2_ERR_EOF && 344716776186Schristos ret != NGHTTP2_ERR_CALLBACK_FAILURE) { 344816776186Schristos char a[256]; 3449*14b2fa6eSchristos addr_to_str(&c->repinfo.remote_addr, 3450*14b2fa6eSchristos c->repinfo.remote_addrlen, a, sizeof(a)); 345116776186Schristos verbose(VERB_QUERY, "http2: session_recv from %s failed, " 345216776186Schristos "error: %s", a, nghttp2_strerror(ret)); 345316776186Schristos } 345416776186Schristos return 0; 345516776186Schristos } 345616776186Schristos if(nghttp2_session_want_write(c->h2_session->session)) { 345716776186Schristos c->tcp_is_reading = 0; 345816776186Schristos comm_point_stop_listening(c); 345916776186Schristos comm_point_start_listening(c, -1, adjusted_tcp_timeout(c)); 346016776186Schristos } else if(!nghttp2_session_want_read(c->h2_session->session)) 346116776186Schristos return 0; /* connection can be closed */ 346216776186Schristos return 1; 346316776186Schristos #else 346416776186Schristos (void)c; 346516776186Schristos return 0; 346616776186Schristos #endif 346716776186Schristos } 346816776186Schristos 34697cd94d69Schristos /** 34707cd94d69Schristos * Handle http reading callback. 34717cd94d69Schristos * @param fd: file descriptor of socket. 34727cd94d69Schristos * @param c: comm point to read from into buffer. 34737cd94d69Schristos * @return: 0 on error 34747cd94d69Schristos */ 34757cd94d69Schristos static int 34767cd94d69Schristos comm_point_http_handle_read(int fd, struct comm_point* c) 34777cd94d69Schristos { 34787cd94d69Schristos log_assert(c->type == comm_http); 34797cd94d69Schristos log_assert(fd != -1); 34807cd94d69Schristos 34817cd94d69Schristos /* if we are in ssl handshake, handle SSL handshake */ 34827cd94d69Schristos #ifdef HAVE_SSL 34837cd94d69Schristos if(c->ssl && c->ssl_shake_state != comm_ssl_shake_none) { 34847cd94d69Schristos if(!ssl_handshake(c)) 34857cd94d69Schristos return 0; 34867cd94d69Schristos if(c->ssl_shake_state != comm_ssl_shake_none) 34877cd94d69Schristos return 1; 34887cd94d69Schristos } 34897cd94d69Schristos #endif /* HAVE_SSL */ 34907cd94d69Schristos 34917cd94d69Schristos if(!c->tcp_is_reading) 34927cd94d69Schristos return 1; 349316776186Schristos 349416776186Schristos if(c->use_h2) { 349516776186Schristos return comm_point_http2_handle_read(fd, c); 349616776186Schristos } 349716776186Schristos 349816776186Schristos /* http version is <= http/1.1 */ 349916776186Schristos 350016776186Schristos if(c->http_min_version >= http_version_2) { 350116776186Schristos /* HTTP/2 failed, not allowed to use lower version. */ 350216776186Schristos return 0; 350316776186Schristos } 350416776186Schristos 35057cd94d69Schristos /* read more data */ 35067cd94d69Schristos if(c->ssl) { 35077cd94d69Schristos if(!ssl_http_read_more(c)) 35087cd94d69Schristos return 0; 35097cd94d69Schristos } else { 35107cd94d69Schristos if(!http_read_more(fd, c)) 35117cd94d69Schristos return 0; 35127cd94d69Schristos } 35137cd94d69Schristos 35141481e2a9Schristos if(c->http_stored >= sldns_buffer_position(c->buffer)) { 35151481e2a9Schristos /* read did not work but we wanted more data, there is 35161481e2a9Schristos * no bytes to process now. */ 35171481e2a9Schristos return 1; 35181481e2a9Schristos } 35197cd94d69Schristos sldns_buffer_flip(c->buffer); 352016776186Schristos /* if we are partway in a segment of data, position us at the point 352116776186Schristos * where we left off previously */ 352216776186Schristos if(c->http_stored < sldns_buffer_limit(c->buffer)) 352316776186Schristos sldns_buffer_set_position(c->buffer, c->http_stored); 352416776186Schristos else sldns_buffer_set_position(c->buffer, sldns_buffer_limit(c->buffer)); 352516776186Schristos 35267cd94d69Schristos while(sldns_buffer_remaining(c->buffer) > 0) { 352716776186Schristos /* Handle HTTP/1.x data */ 35287cd94d69Schristos /* if we are reading headers, read more headers */ 35297cd94d69Schristos if(c->http_in_headers || c->http_in_chunk_headers) { 35307cd94d69Schristos /* if header is done, process the header */ 35317cd94d69Schristos if(!http_header_done(c->buffer)) { 35327cd94d69Schristos /* copy remaining data to front of buffer 35337cd94d69Schristos * and set rest for writing into it */ 35347cd94d69Schristos http_moveover_buffer(c->buffer); 35357cd94d69Schristos /* return and wait to read more */ 35367cd94d69Schristos return 1; 35377cd94d69Schristos } 35387cd94d69Schristos if(!c->http_in_chunk_headers) { 35397cd94d69Schristos /* process initial headers */ 35407cd94d69Schristos if(!http_process_initial_header(c)) 35417cd94d69Schristos return 0; 35427cd94d69Schristos } else { 35437cd94d69Schristos /* process chunk headers */ 35447cd94d69Schristos int r = http_process_chunk_header(c); 35457cd94d69Schristos if(r == 0) return 0; 35467cd94d69Schristos if(r == 2) return 1; /* done */ 35477cd94d69Schristos /* r == 1, continue */ 35487cd94d69Schristos } 35497cd94d69Schristos /* see if we have more to process */ 35507cd94d69Schristos continue; 35517cd94d69Schristos } 35527cd94d69Schristos 35537cd94d69Schristos if(!c->http_is_chunked) { 35547cd94d69Schristos /* if we are reading nonchunks, process that*/ 35557cd94d69Schristos return http_nonchunk_segment(c); 35567cd94d69Schristos } else { 35577cd94d69Schristos /* if we are reading chunks, read the chunk */ 35587cd94d69Schristos int r = http_chunked_segment(c); 35597cd94d69Schristos if(r == 0) return 0; 35607cd94d69Schristos if(r == 1) return 1; 35617cd94d69Schristos continue; 35627cd94d69Schristos } 35637cd94d69Schristos } 35647cd94d69Schristos /* broke out of the loop; could not process header instead need 35657cd94d69Schristos * to read more */ 35667cd94d69Schristos /* moveover any remaining data and read more data */ 35677cd94d69Schristos http_moveover_buffer(c->buffer); 35687cd94d69Schristos /* return and wait to read more */ 35697cd94d69Schristos return 1; 35707cd94d69Schristos } 35717cd94d69Schristos 35727cd94d69Schristos /** check pending connect for http */ 35737cd94d69Schristos static int 35747cd94d69Schristos http_check_connect(int fd, struct comm_point* c) 35757cd94d69Schristos { 35767cd94d69Schristos /* check for pending error from nonblocking connect */ 35777cd94d69Schristos /* from Stevens, unix network programming, vol1, 3rd ed, p450*/ 35787cd94d69Schristos int error = 0; 35797cd94d69Schristos socklen_t len = (socklen_t)sizeof(error); 35807cd94d69Schristos if(getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&error, 35817cd94d69Schristos &len) < 0){ 35827cd94d69Schristos #ifndef USE_WINSOCK 35837cd94d69Schristos error = errno; /* on solaris errno is error */ 35847cd94d69Schristos #else /* USE_WINSOCK */ 35857cd94d69Schristos error = WSAGetLastError(); 35867cd94d69Schristos #endif 35877cd94d69Schristos } 35887cd94d69Schristos #ifndef USE_WINSOCK 35897cd94d69Schristos #if defined(EINPROGRESS) && defined(EWOULDBLOCK) 35907cd94d69Schristos if(error == EINPROGRESS || error == EWOULDBLOCK) 35917cd94d69Schristos return 1; /* try again later */ 35927cd94d69Schristos else 35937cd94d69Schristos #endif 35947cd94d69Schristos if(error != 0 && verbosity < 2) 35957cd94d69Schristos return 0; /* silence lots of chatter in the logs */ 35967cd94d69Schristos else if(error != 0) { 35977cd94d69Schristos log_err_addr("http connect", strerror(error), 3598*14b2fa6eSchristos &c->repinfo.remote_addr, c->repinfo.remote_addrlen); 35997cd94d69Schristos #else /* USE_WINSOCK */ 36007cd94d69Schristos /* examine error */ 36017cd94d69Schristos if(error == WSAEINPROGRESS) 36027cd94d69Schristos return 1; 36037cd94d69Schristos else if(error == WSAEWOULDBLOCK) { 36047cd94d69Schristos ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE); 36057cd94d69Schristos return 1; 36067cd94d69Schristos } else if(error != 0 && verbosity < 2) 36077cd94d69Schristos return 0; 36087cd94d69Schristos else if(error != 0) { 36097cd94d69Schristos log_err_addr("http connect", wsa_strerror(error), 3610*14b2fa6eSchristos &c->repinfo.remote_addr, c->repinfo.remote_addrlen); 36117cd94d69Schristos #endif /* USE_WINSOCK */ 36127cd94d69Schristos return 0; 36137cd94d69Schristos } 36147cd94d69Schristos /* keep on processing this socket */ 36157cd94d69Schristos return 2; 36167cd94d69Schristos } 36177cd94d69Schristos 36187cd94d69Schristos /** write more data for http (with ssl) */ 36197cd94d69Schristos static int 36207cd94d69Schristos ssl_http_write_more(struct comm_point* c) 36217cd94d69Schristos { 36227cd94d69Schristos #ifdef HAVE_SSL 36237cd94d69Schristos int r; 36247cd94d69Schristos log_assert(sldns_buffer_remaining(c->buffer) > 0); 36257cd94d69Schristos ERR_clear_error(); 36267cd94d69Schristos r = SSL_write(c->ssl, (void*)sldns_buffer_current(c->buffer), 36277cd94d69Schristos (int)sldns_buffer_remaining(c->buffer)); 36287cd94d69Schristos if(r <= 0) { 36297cd94d69Schristos int want = SSL_get_error(c->ssl, r); 36307cd94d69Schristos if(want == SSL_ERROR_ZERO_RETURN) { 36317cd94d69Schristos return 0; /* closed */ 36327cd94d69Schristos } else if(want == SSL_ERROR_WANT_READ) { 363387edd195Schristos c->ssl_shake_state = comm_ssl_shake_hs_read; 36347cd94d69Schristos comm_point_listen_for_rw(c, 1, 0); 36357cd94d69Schristos return 1; /* wait for read condition */ 36367cd94d69Schristos } else if(want == SSL_ERROR_WANT_WRITE) { 36377cd94d69Schristos return 1; /* write more later */ 36387cd94d69Schristos } else if(want == SSL_ERROR_SYSCALL) { 363987edd195Schristos #ifdef EPIPE 364087edd195Schristos if(errno == EPIPE && verbosity < 2) 364187edd195Schristos return 0; /* silence 'broken pipe' */ 364287edd195Schristos #endif 36437cd94d69Schristos if(errno != 0) 36447cd94d69Schristos log_err("SSL_write syscall: %s", 36457cd94d69Schristos strerror(errno)); 36467cd94d69Schristos return 0; 36477cd94d69Schristos } 3648*14b2fa6eSchristos log_crypto_err_io("could not SSL_write", want); 36497cd94d69Schristos return 0; 36507cd94d69Schristos } 36517cd94d69Schristos sldns_buffer_skip(c->buffer, (ssize_t)r); 36527cd94d69Schristos return 1; 36537cd94d69Schristos #else 36547cd94d69Schristos (void)c; 36557cd94d69Schristos return 0; 36567cd94d69Schristos #endif /* HAVE_SSL */ 36577cd94d69Schristos } 36587cd94d69Schristos 36597cd94d69Schristos /** write more data for http */ 36607cd94d69Schristos static int 36617cd94d69Schristos http_write_more(int fd, struct comm_point* c) 36627cd94d69Schristos { 36637cd94d69Schristos ssize_t r; 36647cd94d69Schristos log_assert(sldns_buffer_remaining(c->buffer) > 0); 36657cd94d69Schristos r = send(fd, (void*)sldns_buffer_current(c->buffer), 36667cd94d69Schristos sldns_buffer_remaining(c->buffer), 0); 36677cd94d69Schristos if(r == -1) { 36687cd94d69Schristos #ifndef USE_WINSOCK 36697cd94d69Schristos if(errno == EINTR || errno == EAGAIN) 36707cd94d69Schristos return 1; 36717cd94d69Schristos #else 36727cd94d69Schristos if(WSAGetLastError() == WSAEINPROGRESS) 36737cd94d69Schristos return 1; 36747cd94d69Schristos if(WSAGetLastError() == WSAEWOULDBLOCK) { 36757cd94d69Schristos ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE); 36767cd94d69Schristos return 1; 36777cd94d69Schristos } 36787cd94d69Schristos #endif 367916776186Schristos log_err_addr("http send r", sock_strerror(errno), 3680*14b2fa6eSchristos &c->repinfo.remote_addr, c->repinfo.remote_addrlen); 36817cd94d69Schristos return 0; 36827cd94d69Schristos } 36837cd94d69Schristos sldns_buffer_skip(c->buffer, r); 36847cd94d69Schristos return 1; 36857cd94d69Schristos } 36867cd94d69Schristos 368716776186Schristos #ifdef HAVE_NGHTTP2 368816776186Schristos ssize_t http2_send_cb(nghttp2_session* ATTR_UNUSED(session), const uint8_t* buf, 368916776186Schristos size_t len, int ATTR_UNUSED(flags), void* cb_arg) 369016776186Schristos { 369116776186Schristos ssize_t ret; 369216776186Schristos struct http2_session* h2_session = (struct http2_session*)cb_arg; 369316776186Schristos log_assert(h2_session->c->type == comm_http); 369416776186Schristos log_assert(h2_session->c->h2_session); 369516776186Schristos 369616776186Schristos #ifdef HAVE_SSL 369716776186Schristos if(h2_session->c->ssl) { 369816776186Schristos int r; 369916776186Schristos ERR_clear_error(); 370016776186Schristos r = SSL_write(h2_session->c->ssl, buf, len); 370116776186Schristos if(r <= 0) { 370216776186Schristos int want = SSL_get_error(h2_session->c->ssl, r); 370316776186Schristos if(want == SSL_ERROR_ZERO_RETURN) { 370416776186Schristos return NGHTTP2_ERR_CALLBACK_FAILURE; 370516776186Schristos } else if(want == SSL_ERROR_WANT_READ) { 370616776186Schristos h2_session->c->ssl_shake_state = comm_ssl_shake_hs_read; 370716776186Schristos comm_point_listen_for_rw(h2_session->c, 1, 0); 370816776186Schristos return NGHTTP2_ERR_WOULDBLOCK; 370916776186Schristos } else if(want == SSL_ERROR_WANT_WRITE) { 371016776186Schristos return NGHTTP2_ERR_WOULDBLOCK; 371116776186Schristos } else if(want == SSL_ERROR_SYSCALL) { 371216776186Schristos #ifdef EPIPE 371316776186Schristos if(errno == EPIPE && verbosity < 2) 371416776186Schristos return NGHTTP2_ERR_CALLBACK_FAILURE; 371516776186Schristos #endif 371616776186Schristos if(errno != 0) 371716776186Schristos log_err("SSL_write syscall: %s", 371816776186Schristos strerror(errno)); 371916776186Schristos return NGHTTP2_ERR_CALLBACK_FAILURE; 372016776186Schristos } 3721*14b2fa6eSchristos log_crypto_err_io("could not SSL_write", want); 372216776186Schristos return NGHTTP2_ERR_CALLBACK_FAILURE; 372316776186Schristos } 372416776186Schristos return r; 372516776186Schristos } 372616776186Schristos #endif /* HAVE_SSL */ 372716776186Schristos 372816776186Schristos ret = send(h2_session->c->fd, buf, len, 0); 372916776186Schristos if(ret == 0) { 373016776186Schristos return NGHTTP2_ERR_CALLBACK_FAILURE; 373116776186Schristos } else if(ret < 0) { 373216776186Schristos #ifndef USE_WINSOCK 373316776186Schristos if(errno == EINTR || errno == EAGAIN) 373416776186Schristos return NGHTTP2_ERR_WOULDBLOCK; 373516776186Schristos #ifdef EPIPE 373616776186Schristos if(errno == EPIPE && verbosity < 2) 373716776186Schristos return NGHTTP2_ERR_CALLBACK_FAILURE; 373816776186Schristos #endif 373916776186Schristos #ifdef ECONNRESET 374016776186Schristos if(errno == ECONNRESET && verbosity < 2) 374116776186Schristos return NGHTTP2_ERR_CALLBACK_FAILURE; 374216776186Schristos #endif 374316776186Schristos log_err_addr("could not http2 write: %s", strerror(errno), 3744*14b2fa6eSchristos &h2_session->c->repinfo.remote_addr, 3745*14b2fa6eSchristos h2_session->c->repinfo.remote_addrlen); 374616776186Schristos #else /* USE_WINSOCK */ 374716776186Schristos if(WSAGetLastError() == WSAENOTCONN) 374816776186Schristos return NGHTTP2_ERR_WOULDBLOCK; 374916776186Schristos if(WSAGetLastError() == WSAEINPROGRESS) 375016776186Schristos return NGHTTP2_ERR_WOULDBLOCK; 375116776186Schristos if(WSAGetLastError() == WSAEWOULDBLOCK) { 375216776186Schristos ub_winsock_tcp_wouldblock(h2_session->c->ev->ev, 375316776186Schristos UB_EV_WRITE); 375416776186Schristos return NGHTTP2_ERR_WOULDBLOCK; 375516776186Schristos } 375616776186Schristos if(WSAGetLastError() == WSAECONNRESET && verbosity < 2) 375716776186Schristos return NGHTTP2_ERR_CALLBACK_FAILURE; 375816776186Schristos log_err_addr("could not http2 write: %s", 375916776186Schristos wsa_strerror(WSAGetLastError()), 3760*14b2fa6eSchristos &h2_session->c->repinfo.remote_addr, 3761*14b2fa6eSchristos h2_session->c->repinfo.remote_addrlen); 376216776186Schristos #endif 376316776186Schristos return NGHTTP2_ERR_CALLBACK_FAILURE; 376416776186Schristos } 376516776186Schristos return ret; 376616776186Schristos } 376716776186Schristos #endif /* HAVE_NGHTTP2 */ 376816776186Schristos 376916776186Schristos /** Handle http2 writing */ 377016776186Schristos static int 377116776186Schristos comm_point_http2_handle_write(int ATTR_UNUSED(fd), struct comm_point* c) 377216776186Schristos { 377316776186Schristos #ifdef HAVE_NGHTTP2 377416776186Schristos int ret; 377516776186Schristos log_assert(c->h2_session); 377616776186Schristos 377716776186Schristos ret = nghttp2_session_send(c->h2_session->session); 377816776186Schristos if(ret) { 377916776186Schristos verbose(VERB_QUERY, "http2: session_send failed, " 378016776186Schristos "error: %s", nghttp2_strerror(ret)); 378116776186Schristos return 0; 378216776186Schristos } 378316776186Schristos 378416776186Schristos if(nghttp2_session_want_read(c->h2_session->session)) { 378516776186Schristos c->tcp_is_reading = 1; 378616776186Schristos comm_point_stop_listening(c); 378716776186Schristos comm_point_start_listening(c, -1, adjusted_tcp_timeout(c)); 378816776186Schristos } else if(!nghttp2_session_want_write(c->h2_session->session)) 378916776186Schristos return 0; /* connection can be closed */ 379016776186Schristos return 1; 379116776186Schristos #else 379216776186Schristos (void)c; 379316776186Schristos return 0; 379416776186Schristos #endif 379516776186Schristos } 379616776186Schristos 37977cd94d69Schristos /** 37987cd94d69Schristos * Handle http writing callback. 37997cd94d69Schristos * @param fd: file descriptor of socket. 38007cd94d69Schristos * @param c: comm point to write buffer out of. 38017cd94d69Schristos * @return: 0 on error 38027cd94d69Schristos */ 38037cd94d69Schristos static int 38047cd94d69Schristos comm_point_http_handle_write(int fd, struct comm_point* c) 38057cd94d69Schristos { 38067cd94d69Schristos log_assert(c->type == comm_http); 38077cd94d69Schristos log_assert(fd != -1); 38087cd94d69Schristos 38097cd94d69Schristos /* check pending connect errors, if that fails, we wait for more, 38107cd94d69Schristos * or we can continue to write contents */ 38117cd94d69Schristos if(c->tcp_check_nb_connect) { 38127cd94d69Schristos int r = http_check_connect(fd, c); 38137cd94d69Schristos if(r == 0) return 0; 38147cd94d69Schristos if(r == 1) return 1; 38157cd94d69Schristos c->tcp_check_nb_connect = 0; 38167cd94d69Schristos } 38177cd94d69Schristos /* if we are in ssl handshake, handle SSL handshake */ 38187cd94d69Schristos #ifdef HAVE_SSL 38197cd94d69Schristos if(c->ssl && c->ssl_shake_state != comm_ssl_shake_none) { 38207cd94d69Schristos if(!ssl_handshake(c)) 38217cd94d69Schristos return 0; 38227cd94d69Schristos if(c->ssl_shake_state != comm_ssl_shake_none) 38237cd94d69Schristos return 1; 38247cd94d69Schristos } 38257cd94d69Schristos #endif /* HAVE_SSL */ 38267cd94d69Schristos if(c->tcp_is_reading) 38277cd94d69Schristos return 1; 382816776186Schristos 382916776186Schristos if(c->use_h2) { 383016776186Schristos return comm_point_http2_handle_write(fd, c); 383116776186Schristos } 383216776186Schristos 383316776186Schristos /* http version is <= http/1.1 */ 383416776186Schristos 383516776186Schristos if(c->http_min_version >= http_version_2) { 383616776186Schristos /* HTTP/2 failed, not allowed to use lower version. */ 383716776186Schristos return 0; 383816776186Schristos } 383916776186Schristos 38407cd94d69Schristos /* if we are writing, write more */ 38417cd94d69Schristos if(c->ssl) { 38427cd94d69Schristos if(!ssl_http_write_more(c)) 38437cd94d69Schristos return 0; 38447cd94d69Schristos } else { 38457cd94d69Schristos if(!http_write_more(fd, c)) 38467cd94d69Schristos return 0; 38477cd94d69Schristos } 38487cd94d69Schristos 38497cd94d69Schristos /* we write a single buffer contents, that can contain 38507cd94d69Schristos * the http request, and then flip to read the results */ 38517cd94d69Schristos /* see if write is done */ 38527cd94d69Schristos if(sldns_buffer_remaining(c->buffer) == 0) { 38537cd94d69Schristos sldns_buffer_clear(c->buffer); 38547cd94d69Schristos if(c->tcp_do_toggle_rw) 38557cd94d69Schristos c->tcp_is_reading = 1; 38567cd94d69Schristos c->tcp_byte_count = 0; 38577cd94d69Schristos /* switch from listening(write) to listening(read) */ 38587cd94d69Schristos comm_point_stop_listening(c); 38597cd94d69Schristos comm_point_start_listening(c, -1, -1); 38607cd94d69Schristos } 38617cd94d69Schristos return 1; 38627cd94d69Schristos } 38637cd94d69Schristos 38647cd94d69Schristos void 38657cd94d69Schristos comm_point_http_handle_callback(int fd, short event, void* arg) 38667cd94d69Schristos { 38677cd94d69Schristos struct comm_point* c = (struct comm_point*)arg; 38687cd94d69Schristos log_assert(c->type == comm_http); 38697cd94d69Schristos ub_comm_base_now(c->ev->base); 38707cd94d69Schristos 387187edd195Schristos if(event&UB_EV_TIMEOUT) { 387287edd195Schristos verbose(VERB_QUERY, "http took too long, dropped"); 387387edd195Schristos reclaim_http_handler(c); 387487edd195Schristos if(!c->tcp_do_close) { 387587edd195Schristos fptr_ok(fptr_whitelist_comm_point(c->callback)); 387687edd195Schristos (void)(*c->callback)(c, c->cb_arg, 387787edd195Schristos NETEVENT_TIMEOUT, NULL); 387887edd195Schristos } 387987edd195Schristos return; 388087edd195Schristos } 38817cd94d69Schristos if(event&UB_EV_READ) { 38827cd94d69Schristos if(!comm_point_http_handle_read(fd, c)) { 38837cd94d69Schristos reclaim_http_handler(c); 38847cd94d69Schristos if(!c->tcp_do_close) { 38857cd94d69Schristos fptr_ok(fptr_whitelist_comm_point( 38867cd94d69Schristos c->callback)); 38877cd94d69Schristos (void)(*c->callback)(c, c->cb_arg, 38887cd94d69Schristos NETEVENT_CLOSED, NULL); 38897cd94d69Schristos } 38907cd94d69Schristos } 38917cd94d69Schristos return; 38927cd94d69Schristos } 38937cd94d69Schristos if(event&UB_EV_WRITE) { 38947cd94d69Schristos if(!comm_point_http_handle_write(fd, c)) { 38957cd94d69Schristos reclaim_http_handler(c); 38967cd94d69Schristos if(!c->tcp_do_close) { 38977cd94d69Schristos fptr_ok(fptr_whitelist_comm_point( 38987cd94d69Schristos c->callback)); 38997cd94d69Schristos (void)(*c->callback)(c, c->cb_arg, 39007cd94d69Schristos NETEVENT_CLOSED, NULL); 39017cd94d69Schristos } 39027cd94d69Schristos } 39037cd94d69Schristos return; 39047cd94d69Schristos } 39057cd94d69Schristos log_err("Ignored event %d for httphdl.", event); 39067cd94d69Schristos } 39077cd94d69Schristos 39083b6c3722Schristos void comm_point_local_handle_callback(int fd, short event, void* arg) 39093b6c3722Schristos { 39103b6c3722Schristos struct comm_point* c = (struct comm_point*)arg; 39113b6c3722Schristos log_assert(c->type == comm_local); 39123b6c3722Schristos ub_comm_base_now(c->ev->base); 39133b6c3722Schristos 39143b6c3722Schristos if(event&UB_EV_READ) { 39153b6c3722Schristos if(!comm_point_tcp_handle_read(fd, c, 1)) { 39163b6c3722Schristos fptr_ok(fptr_whitelist_comm_point(c->callback)); 39173b6c3722Schristos (void)(*c->callback)(c, c->cb_arg, NETEVENT_CLOSED, 39183b6c3722Schristos NULL); 39193b6c3722Schristos } 39203b6c3722Schristos return; 39213b6c3722Schristos } 39223b6c3722Schristos log_err("Ignored event %d for localhdl.", event); 39233b6c3722Schristos } 39243b6c3722Schristos 39253b6c3722Schristos void comm_point_raw_handle_callback(int ATTR_UNUSED(fd), 39263b6c3722Schristos short event, void* arg) 39273b6c3722Schristos { 39283b6c3722Schristos struct comm_point* c = (struct comm_point*)arg; 39293b6c3722Schristos int err = NETEVENT_NOERROR; 39303b6c3722Schristos log_assert(c->type == comm_raw); 39313b6c3722Schristos ub_comm_base_now(c->ev->base); 39323b6c3722Schristos 39333b6c3722Schristos if(event&UB_EV_TIMEOUT) 39343b6c3722Schristos err = NETEVENT_TIMEOUT; 39353b6c3722Schristos fptr_ok(fptr_whitelist_comm_point_raw(c->callback)); 39363b6c3722Schristos (void)(*c->callback)(c, c->cb_arg, err, NULL); 39373b6c3722Schristos } 39383b6c3722Schristos 39393b6c3722Schristos struct comm_point* 39403b6c3722Schristos comm_point_create_udp(struct comm_base *base, int fd, sldns_buffer* buffer, 3941*14b2fa6eSchristos int pp2_enabled, comm_point_callback_type* callback, 3942*14b2fa6eSchristos void* callback_arg, struct unbound_socket* socket) 39433b6c3722Schristos { 39443b6c3722Schristos struct comm_point* c = (struct comm_point*)calloc(1, 39453b6c3722Schristos sizeof(struct comm_point)); 39463b6c3722Schristos short evbits; 39473b6c3722Schristos if(!c) 39483b6c3722Schristos return NULL; 39493b6c3722Schristos c->ev = (struct internal_event*)calloc(1, 39503b6c3722Schristos sizeof(struct internal_event)); 39513b6c3722Schristos if(!c->ev) { 39523b6c3722Schristos free(c); 39533b6c3722Schristos return NULL; 39543b6c3722Schristos } 39553b6c3722Schristos c->ev->base = base; 39563b6c3722Schristos c->fd = fd; 39573b6c3722Schristos c->buffer = buffer; 39583b6c3722Schristos c->timeout = NULL; 39593b6c3722Schristos c->tcp_is_reading = 0; 39603b6c3722Schristos c->tcp_byte_count = 0; 39613b6c3722Schristos c->tcp_parent = NULL; 39623b6c3722Schristos c->max_tcp_count = 0; 39633b6c3722Schristos c->cur_tcp_count = 0; 39643b6c3722Schristos c->tcp_handlers = NULL; 39653b6c3722Schristos c->tcp_free = NULL; 39663b6c3722Schristos c->type = comm_udp; 39673b6c3722Schristos c->tcp_do_close = 0; 39683b6c3722Schristos c->do_not_close = 0; 39693b6c3722Schristos c->tcp_do_toggle_rw = 0; 39703b6c3722Schristos c->tcp_check_nb_connect = 0; 39710cd9f4ecSchristos #ifdef USE_MSG_FASTOPEN 39720cd9f4ecSchristos c->tcp_do_fastopen = 0; 39730cd9f4ecSchristos #endif 39740cd9f4ecSchristos #ifdef USE_DNSCRYPT 39750cd9f4ecSchristos c->dnscrypt = 0; 39760cd9f4ecSchristos c->dnscrypt_buffer = buffer; 39770cd9f4ecSchristos #endif 39783b6c3722Schristos c->inuse = 0; 39793b6c3722Schristos c->callback = callback; 39803b6c3722Schristos c->cb_arg = callback_arg; 39811481e2a9Schristos c->socket = socket; 3982*14b2fa6eSchristos c->pp2_enabled = pp2_enabled; 3983*14b2fa6eSchristos c->pp2_header_state = pp2_header_none; 39843b6c3722Schristos evbits = UB_EV_READ | UB_EV_PERSIST; 39853b6c3722Schristos /* ub_event stuff */ 39863b6c3722Schristos c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits, 39873b6c3722Schristos comm_point_udp_callback, c); 39883b6c3722Schristos if(c->ev->ev == NULL) { 39893b6c3722Schristos log_err("could not baseset udp event"); 39903b6c3722Schristos comm_point_delete(c); 39913b6c3722Schristos return NULL; 39923b6c3722Schristos } 39933b6c3722Schristos if(fd!=-1 && ub_event_add(c->ev->ev, c->timeout) != 0 ) { 39943b6c3722Schristos log_err("could not add udp event"); 39953b6c3722Schristos comm_point_delete(c); 39963b6c3722Schristos return NULL; 39973b6c3722Schristos } 399816776186Schristos c->event_added = 1; 39993b6c3722Schristos return c; 40003b6c3722Schristos } 40013b6c3722Schristos 4002*14b2fa6eSchristos #if defined(AF_INET6) && defined(IPV6_PKTINFO) && defined(HAVE_RECVMSG) 40033b6c3722Schristos struct comm_point* 40043b6c3722Schristos comm_point_create_udp_ancil(struct comm_base *base, int fd, 4005*14b2fa6eSchristos sldns_buffer* buffer, int pp2_enabled, 40061481e2a9Schristos comm_point_callback_type* callback, void* callback_arg, struct unbound_socket* socket) 40073b6c3722Schristos { 40083b6c3722Schristos struct comm_point* c = (struct comm_point*)calloc(1, 40093b6c3722Schristos sizeof(struct comm_point)); 40103b6c3722Schristos short evbits; 40113b6c3722Schristos if(!c) 40123b6c3722Schristos return NULL; 40133b6c3722Schristos c->ev = (struct internal_event*)calloc(1, 40143b6c3722Schristos sizeof(struct internal_event)); 40153b6c3722Schristos if(!c->ev) { 40163b6c3722Schristos free(c); 40173b6c3722Schristos return NULL; 40183b6c3722Schristos } 40193b6c3722Schristos c->ev->base = base; 40203b6c3722Schristos c->fd = fd; 40213b6c3722Schristos c->buffer = buffer; 40223b6c3722Schristos c->timeout = NULL; 40233b6c3722Schristos c->tcp_is_reading = 0; 40243b6c3722Schristos c->tcp_byte_count = 0; 40253b6c3722Schristos c->tcp_parent = NULL; 40263b6c3722Schristos c->max_tcp_count = 0; 40273b6c3722Schristos c->cur_tcp_count = 0; 40283b6c3722Schristos c->tcp_handlers = NULL; 40293b6c3722Schristos c->tcp_free = NULL; 40303b6c3722Schristos c->type = comm_udp; 40313b6c3722Schristos c->tcp_do_close = 0; 40323b6c3722Schristos c->do_not_close = 0; 40330cd9f4ecSchristos #ifdef USE_DNSCRYPT 40340cd9f4ecSchristos c->dnscrypt = 0; 40350cd9f4ecSchristos c->dnscrypt_buffer = buffer; 40360cd9f4ecSchristos #endif 40373b6c3722Schristos c->inuse = 0; 40383b6c3722Schristos c->tcp_do_toggle_rw = 0; 40393b6c3722Schristos c->tcp_check_nb_connect = 0; 40400cd9f4ecSchristos #ifdef USE_MSG_FASTOPEN 40410cd9f4ecSchristos c->tcp_do_fastopen = 0; 40420cd9f4ecSchristos #endif 40433b6c3722Schristos c->callback = callback; 40443b6c3722Schristos c->cb_arg = callback_arg; 40451481e2a9Schristos c->socket = socket; 4046*14b2fa6eSchristos c->pp2_enabled = pp2_enabled; 4047*14b2fa6eSchristos c->pp2_header_state = pp2_header_none; 40483b6c3722Schristos evbits = UB_EV_READ | UB_EV_PERSIST; 40493b6c3722Schristos /* ub_event stuff */ 40503b6c3722Schristos c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits, 40513b6c3722Schristos comm_point_udp_ancil_callback, c); 40523b6c3722Schristos if(c->ev->ev == NULL) { 40533b6c3722Schristos log_err("could not baseset udp event"); 40543b6c3722Schristos comm_point_delete(c); 40553b6c3722Schristos return NULL; 40563b6c3722Schristos } 40573b6c3722Schristos if(fd!=-1 && ub_event_add(c->ev->ev, c->timeout) != 0 ) { 40583b6c3722Schristos log_err("could not add udp event"); 40593b6c3722Schristos comm_point_delete(c); 40603b6c3722Schristos return NULL; 40613b6c3722Schristos } 406216776186Schristos c->event_added = 1; 40633b6c3722Schristos return c; 40643b6c3722Schristos } 4065*14b2fa6eSchristos #endif 40663b6c3722Schristos 40673b6c3722Schristos static struct comm_point* 40683b6c3722Schristos comm_point_create_tcp_handler(struct comm_base *base, 40693b6c3722Schristos struct comm_point* parent, size_t bufsize, 4070f42d8de7Schristos struct sldns_buffer* spoolbuf, comm_point_callback_type* callback, 40711481e2a9Schristos void* callback_arg, struct unbound_socket* socket) 40723b6c3722Schristos { 40733b6c3722Schristos struct comm_point* c = (struct comm_point*)calloc(1, 40743b6c3722Schristos sizeof(struct comm_point)); 40753b6c3722Schristos short evbits; 40763b6c3722Schristos if(!c) 40773b6c3722Schristos return NULL; 40783b6c3722Schristos c->ev = (struct internal_event*)calloc(1, 40793b6c3722Schristos sizeof(struct internal_event)); 40803b6c3722Schristos if(!c->ev) { 40813b6c3722Schristos free(c); 40823b6c3722Schristos return NULL; 40833b6c3722Schristos } 40843b6c3722Schristos c->ev->base = base; 40853b6c3722Schristos c->fd = -1; 40863b6c3722Schristos c->buffer = sldns_buffer_new(bufsize); 40873b6c3722Schristos if(!c->buffer) { 40883b6c3722Schristos free(c->ev); 40893b6c3722Schristos free(c); 40903b6c3722Schristos return NULL; 40913b6c3722Schristos } 40923b6c3722Schristos c->timeout = (struct timeval*)malloc(sizeof(struct timeval)); 40933b6c3722Schristos if(!c->timeout) { 40943b6c3722Schristos sldns_buffer_free(c->buffer); 40953b6c3722Schristos free(c->ev); 40963b6c3722Schristos free(c); 40973b6c3722Schristos return NULL; 40983b6c3722Schristos } 40993b6c3722Schristos c->tcp_is_reading = 0; 41003b6c3722Schristos c->tcp_byte_count = 0; 41013b6c3722Schristos c->tcp_parent = parent; 4102f42d8de7Schristos c->tcp_timeout_msec = parent->tcp_timeout_msec; 4103f42d8de7Schristos c->tcp_conn_limit = parent->tcp_conn_limit; 4104f42d8de7Schristos c->tcl_addr = NULL; 4105f42d8de7Schristos c->tcp_keepalive = 0; 41063b6c3722Schristos c->max_tcp_count = 0; 41073b6c3722Schristos c->cur_tcp_count = 0; 41083b6c3722Schristos c->tcp_handlers = NULL; 41093b6c3722Schristos c->tcp_free = NULL; 41103b6c3722Schristos c->type = comm_tcp; 41113b6c3722Schristos c->tcp_do_close = 0; 41123b6c3722Schristos c->do_not_close = 0; 41133b6c3722Schristos c->tcp_do_toggle_rw = 1; 41143b6c3722Schristos c->tcp_check_nb_connect = 0; 41150cd9f4ecSchristos #ifdef USE_MSG_FASTOPEN 41160cd9f4ecSchristos c->tcp_do_fastopen = 0; 41170cd9f4ecSchristos #endif 41180cd9f4ecSchristos #ifdef USE_DNSCRYPT 41190cd9f4ecSchristos c->dnscrypt = 0; 41200cd9f4ecSchristos /* We don't know just yet if this is a dnscrypt channel. Allocation 41210cd9f4ecSchristos * will be done when handling the callback. */ 41220cd9f4ecSchristos c->dnscrypt_buffer = c->buffer; 41230cd9f4ecSchristos #endif 41243b6c3722Schristos c->repinfo.c = c; 41253b6c3722Schristos c->callback = callback; 41263b6c3722Schristos c->cb_arg = callback_arg; 41271481e2a9Schristos c->socket = socket; 4128*14b2fa6eSchristos c->pp2_enabled = parent->pp2_enabled; 4129*14b2fa6eSchristos c->pp2_header_state = pp2_header_none; 4130f42d8de7Schristos if(spoolbuf) { 4131f42d8de7Schristos c->tcp_req_info = tcp_req_info_create(spoolbuf); 4132f42d8de7Schristos if(!c->tcp_req_info) { 4133f42d8de7Schristos log_err("could not create tcp commpoint"); 4134f42d8de7Schristos sldns_buffer_free(c->buffer); 4135f42d8de7Schristos free(c->timeout); 4136f42d8de7Schristos free(c->ev); 4137f42d8de7Schristos free(c); 4138f42d8de7Schristos return NULL; 4139f42d8de7Schristos } 4140f42d8de7Schristos c->tcp_req_info->cp = c; 4141f42d8de7Schristos c->tcp_do_close = 1; 4142f42d8de7Schristos c->tcp_do_toggle_rw = 0; 4143f42d8de7Schristos } 41443b6c3722Schristos /* add to parent free list */ 41453b6c3722Schristos c->tcp_free = parent->tcp_free; 41463b6c3722Schristos parent->tcp_free = c; 41473b6c3722Schristos /* ub_event stuff */ 41483b6c3722Schristos evbits = UB_EV_PERSIST | UB_EV_READ | UB_EV_TIMEOUT; 41493b6c3722Schristos c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits, 41503b6c3722Schristos comm_point_tcp_handle_callback, c); 41513b6c3722Schristos if(c->ev->ev == NULL) 41523b6c3722Schristos { 41533b6c3722Schristos log_err("could not basetset tcphdl event"); 41543b6c3722Schristos parent->tcp_free = c->tcp_free; 4155f42d8de7Schristos tcp_req_info_delete(c->tcp_req_info); 4156f42d8de7Schristos sldns_buffer_free(c->buffer); 4157f42d8de7Schristos free(c->timeout); 41583b6c3722Schristos free(c->ev); 41593b6c3722Schristos free(c); 41603b6c3722Schristos return NULL; 41613b6c3722Schristos } 41623b6c3722Schristos return c; 41633b6c3722Schristos } 41643b6c3722Schristos 416516776186Schristos static struct comm_point* 416616776186Schristos comm_point_create_http_handler(struct comm_base *base, 416716776186Schristos struct comm_point* parent, size_t bufsize, int harden_large_queries, 416816776186Schristos uint32_t http_max_streams, char* http_endpoint, 41691481e2a9Schristos comm_point_callback_type* callback, void* callback_arg, 41701481e2a9Schristos struct unbound_socket* socket) 417116776186Schristos { 417216776186Schristos struct comm_point* c = (struct comm_point*)calloc(1, 417316776186Schristos sizeof(struct comm_point)); 417416776186Schristos short evbits; 417516776186Schristos if(!c) 417616776186Schristos return NULL; 417716776186Schristos c->ev = (struct internal_event*)calloc(1, 417816776186Schristos sizeof(struct internal_event)); 417916776186Schristos if(!c->ev) { 418016776186Schristos free(c); 418116776186Schristos return NULL; 418216776186Schristos } 418316776186Schristos c->ev->base = base; 418416776186Schristos c->fd = -1; 418516776186Schristos c->buffer = sldns_buffer_new(bufsize); 418616776186Schristos if(!c->buffer) { 418716776186Schristos free(c->ev); 418816776186Schristos free(c); 418916776186Schristos return NULL; 419016776186Schristos } 419116776186Schristos c->timeout = (struct timeval*)malloc(sizeof(struct timeval)); 419216776186Schristos if(!c->timeout) { 419316776186Schristos sldns_buffer_free(c->buffer); 419416776186Schristos free(c->ev); 419516776186Schristos free(c); 419616776186Schristos return NULL; 419716776186Schristos } 419816776186Schristos c->tcp_is_reading = 0; 419916776186Schristos c->tcp_byte_count = 0; 420016776186Schristos c->tcp_parent = parent; 420116776186Schristos c->tcp_timeout_msec = parent->tcp_timeout_msec; 420216776186Schristos c->tcp_conn_limit = parent->tcp_conn_limit; 420316776186Schristos c->tcl_addr = NULL; 420416776186Schristos c->tcp_keepalive = 0; 420516776186Schristos c->max_tcp_count = 0; 420616776186Schristos c->cur_tcp_count = 0; 420716776186Schristos c->tcp_handlers = NULL; 420816776186Schristos c->tcp_free = NULL; 420916776186Schristos c->type = comm_http; 421016776186Schristos c->tcp_do_close = 1; 421116776186Schristos c->do_not_close = 0; 421216776186Schristos c->tcp_do_toggle_rw = 1; /* will be set to 0 after http2 upgrade */ 421316776186Schristos c->tcp_check_nb_connect = 0; 421416776186Schristos #ifdef USE_MSG_FASTOPEN 421516776186Schristos c->tcp_do_fastopen = 0; 421616776186Schristos #endif 421716776186Schristos #ifdef USE_DNSCRYPT 421816776186Schristos c->dnscrypt = 0; 421916776186Schristos c->dnscrypt_buffer = NULL; 422016776186Schristos #endif 422116776186Schristos c->repinfo.c = c; 422216776186Schristos c->callback = callback; 422316776186Schristos c->cb_arg = callback_arg; 42241481e2a9Schristos c->socket = socket; 4225*14b2fa6eSchristos c->pp2_enabled = 0; 4226*14b2fa6eSchristos c->pp2_header_state = pp2_header_none; 422716776186Schristos 422816776186Schristos c->http_min_version = http_version_2; 422916776186Schristos c->http2_stream_max_qbuffer_size = bufsize; 423016776186Schristos if(harden_large_queries && bufsize > 512) 423116776186Schristos c->http2_stream_max_qbuffer_size = 512; 423216776186Schristos c->http2_max_streams = http_max_streams; 423316776186Schristos if(!(c->http_endpoint = strdup(http_endpoint))) { 423416776186Schristos log_err("could not strdup http_endpoint"); 423516776186Schristos sldns_buffer_free(c->buffer); 423616776186Schristos free(c->timeout); 423716776186Schristos free(c->ev); 423816776186Schristos free(c); 423916776186Schristos return NULL; 424016776186Schristos } 424116776186Schristos c->use_h2 = 0; 424216776186Schristos #ifdef HAVE_NGHTTP2 424316776186Schristos if(!(c->h2_session = http2_session_create(c))) { 424416776186Schristos log_err("could not create http2 session"); 424516776186Schristos free(c->http_endpoint); 424616776186Schristos sldns_buffer_free(c->buffer); 424716776186Schristos free(c->timeout); 424816776186Schristos free(c->ev); 424916776186Schristos free(c); 425016776186Schristos return NULL; 425116776186Schristos } 425216776186Schristos if(!(c->h2_session->callbacks = http2_req_callbacks_create())) { 425316776186Schristos log_err("could not create http2 callbacks"); 425416776186Schristos http2_session_delete(c->h2_session); 425516776186Schristos free(c->http_endpoint); 425616776186Schristos sldns_buffer_free(c->buffer); 425716776186Schristos free(c->timeout); 425816776186Schristos free(c->ev); 425916776186Schristos free(c); 426016776186Schristos return NULL; 426116776186Schristos } 426216776186Schristos #endif 426316776186Schristos 426416776186Schristos /* add to parent free list */ 426516776186Schristos c->tcp_free = parent->tcp_free; 426616776186Schristos parent->tcp_free = c; 426716776186Schristos /* ub_event stuff */ 426816776186Schristos evbits = UB_EV_PERSIST | UB_EV_READ | UB_EV_TIMEOUT; 426916776186Schristos c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits, 427016776186Schristos comm_point_http_handle_callback, c); 427116776186Schristos if(c->ev->ev == NULL) 427216776186Schristos { 427316776186Schristos log_err("could not set http handler event"); 427416776186Schristos parent->tcp_free = c->tcp_free; 427516776186Schristos http2_session_delete(c->h2_session); 427616776186Schristos sldns_buffer_free(c->buffer); 427716776186Schristos free(c->timeout); 427816776186Schristos free(c->ev); 427916776186Schristos free(c); 428016776186Schristos return NULL; 428116776186Schristos } 428216776186Schristos return c; 428316776186Schristos } 428416776186Schristos 42853b6c3722Schristos struct comm_point* 4286f42d8de7Schristos comm_point_create_tcp(struct comm_base *base, int fd, int num, 428716776186Schristos int idle_timeout, int harden_large_queries, 428816776186Schristos uint32_t http_max_streams, char* http_endpoint, 428916776186Schristos struct tcl_list* tcp_conn_limit, size_t bufsize, 429016776186Schristos struct sldns_buffer* spoolbuf, enum listen_type port_type, 4291*14b2fa6eSchristos int pp2_enabled, comm_point_callback_type* callback, 4292*14b2fa6eSchristos void* callback_arg, struct unbound_socket* socket) 42933b6c3722Schristos { 42943b6c3722Schristos struct comm_point* c = (struct comm_point*)calloc(1, 42953b6c3722Schristos sizeof(struct comm_point)); 42963b6c3722Schristos short evbits; 42973b6c3722Schristos int i; 42983b6c3722Schristos /* first allocate the TCP accept listener */ 42993b6c3722Schristos if(!c) 43003b6c3722Schristos return NULL; 43013b6c3722Schristos c->ev = (struct internal_event*)calloc(1, 43023b6c3722Schristos sizeof(struct internal_event)); 43033b6c3722Schristos if(!c->ev) { 43043b6c3722Schristos free(c); 43053b6c3722Schristos return NULL; 43063b6c3722Schristos } 43073b6c3722Schristos c->ev->base = base; 43083b6c3722Schristos c->fd = fd; 43093b6c3722Schristos c->buffer = NULL; 43103b6c3722Schristos c->timeout = NULL; 43113b6c3722Schristos c->tcp_is_reading = 0; 43123b6c3722Schristos c->tcp_byte_count = 0; 4313f42d8de7Schristos c->tcp_timeout_msec = idle_timeout; 4314f42d8de7Schristos c->tcp_conn_limit = tcp_conn_limit; 4315f42d8de7Schristos c->tcl_addr = NULL; 4316f42d8de7Schristos c->tcp_keepalive = 0; 43173b6c3722Schristos c->tcp_parent = NULL; 43183b6c3722Schristos c->max_tcp_count = num; 43193b6c3722Schristos c->cur_tcp_count = 0; 43203b6c3722Schristos c->tcp_handlers = (struct comm_point**)calloc((size_t)num, 43213b6c3722Schristos sizeof(struct comm_point*)); 43223b6c3722Schristos if(!c->tcp_handlers) { 43233b6c3722Schristos free(c->ev); 43243b6c3722Schristos free(c); 43253b6c3722Schristos return NULL; 43263b6c3722Schristos } 43273b6c3722Schristos c->tcp_free = NULL; 43283b6c3722Schristos c->type = comm_tcp_accept; 43293b6c3722Schristos c->tcp_do_close = 0; 43303b6c3722Schristos c->do_not_close = 0; 43313b6c3722Schristos c->tcp_do_toggle_rw = 0; 43323b6c3722Schristos c->tcp_check_nb_connect = 0; 43330cd9f4ecSchristos #ifdef USE_MSG_FASTOPEN 43340cd9f4ecSchristos c->tcp_do_fastopen = 0; 43350cd9f4ecSchristos #endif 43360cd9f4ecSchristos #ifdef USE_DNSCRYPT 43370cd9f4ecSchristos c->dnscrypt = 0; 43380cd9f4ecSchristos c->dnscrypt_buffer = NULL; 43390cd9f4ecSchristos #endif 43403b6c3722Schristos c->callback = NULL; 43413b6c3722Schristos c->cb_arg = NULL; 43421481e2a9Schristos c->socket = socket; 4343*14b2fa6eSchristos c->pp2_enabled = (port_type==listen_type_http?0:pp2_enabled); 4344*14b2fa6eSchristos c->pp2_header_state = pp2_header_none; 43453b6c3722Schristos evbits = UB_EV_READ | UB_EV_PERSIST; 43463b6c3722Schristos /* ub_event stuff */ 43473b6c3722Schristos c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits, 43483b6c3722Schristos comm_point_tcp_accept_callback, c); 43493b6c3722Schristos if(c->ev->ev == NULL) { 43503b6c3722Schristos log_err("could not baseset tcpacc event"); 43513b6c3722Schristos comm_point_delete(c); 43523b6c3722Schristos return NULL; 43533b6c3722Schristos } 43543b6c3722Schristos if (ub_event_add(c->ev->ev, c->timeout) != 0) { 43553b6c3722Schristos log_err("could not add tcpacc event"); 43563b6c3722Schristos comm_point_delete(c); 43573b6c3722Schristos return NULL; 43583b6c3722Schristos } 435916776186Schristos c->event_added = 1; 436016776186Schristos /* now prealloc the handlers */ 43613b6c3722Schristos for(i=0; i<num; i++) { 436216776186Schristos if(port_type == listen_type_tcp || 436316776186Schristos port_type == listen_type_ssl || 436416776186Schristos port_type == listen_type_tcp_dnscrypt) { 43653b6c3722Schristos c->tcp_handlers[i] = comm_point_create_tcp_handler(base, 43661481e2a9Schristos c, bufsize, spoolbuf, callback, callback_arg, socket); 436716776186Schristos } else if(port_type == listen_type_http) { 436816776186Schristos c->tcp_handlers[i] = comm_point_create_http_handler( 436916776186Schristos base, c, bufsize, harden_large_queries, 437016776186Schristos http_max_streams, http_endpoint, 43711481e2a9Schristos callback, callback_arg, socket); 437216776186Schristos } 437316776186Schristos else { 437416776186Schristos log_err("could not create tcp handler, unknown listen " 437516776186Schristos "type"); 437616776186Schristos return NULL; 437716776186Schristos } 43783b6c3722Schristos if(!c->tcp_handlers[i]) { 43793b6c3722Schristos comm_point_delete(c); 43803b6c3722Schristos return NULL; 43813b6c3722Schristos } 43823b6c3722Schristos } 43833b6c3722Schristos 43843b6c3722Schristos return c; 43853b6c3722Schristos } 43863b6c3722Schristos 43873b6c3722Schristos struct comm_point* 43883b6c3722Schristos comm_point_create_tcp_out(struct comm_base *base, size_t bufsize, 43890cd9f4ecSchristos comm_point_callback_type* callback, void* callback_arg) 43903b6c3722Schristos { 43913b6c3722Schristos struct comm_point* c = (struct comm_point*)calloc(1, 43923b6c3722Schristos sizeof(struct comm_point)); 43933b6c3722Schristos short evbits; 43943b6c3722Schristos if(!c) 43953b6c3722Schristos return NULL; 43963b6c3722Schristos c->ev = (struct internal_event*)calloc(1, 43973b6c3722Schristos sizeof(struct internal_event)); 43983b6c3722Schristos if(!c->ev) { 43993b6c3722Schristos free(c); 44003b6c3722Schristos return NULL; 44013b6c3722Schristos } 44023b6c3722Schristos c->ev->base = base; 44033b6c3722Schristos c->fd = -1; 44043b6c3722Schristos c->buffer = sldns_buffer_new(bufsize); 44053b6c3722Schristos if(!c->buffer) { 44063b6c3722Schristos free(c->ev); 44073b6c3722Schristos free(c); 44083b6c3722Schristos return NULL; 44093b6c3722Schristos } 44103b6c3722Schristos c->timeout = NULL; 44113b6c3722Schristos c->tcp_is_reading = 0; 44123b6c3722Schristos c->tcp_byte_count = 0; 4413f42d8de7Schristos c->tcp_timeout_msec = TCP_QUERY_TIMEOUT; 4414f42d8de7Schristos c->tcp_conn_limit = NULL; 4415f42d8de7Schristos c->tcl_addr = NULL; 4416f42d8de7Schristos c->tcp_keepalive = 0; 44173b6c3722Schristos c->tcp_parent = NULL; 44183b6c3722Schristos c->max_tcp_count = 0; 44193b6c3722Schristos c->cur_tcp_count = 0; 44203b6c3722Schristos c->tcp_handlers = NULL; 44213b6c3722Schristos c->tcp_free = NULL; 44223b6c3722Schristos c->type = comm_tcp; 44233b6c3722Schristos c->tcp_do_close = 0; 44243b6c3722Schristos c->do_not_close = 0; 44253b6c3722Schristos c->tcp_do_toggle_rw = 1; 44263b6c3722Schristos c->tcp_check_nb_connect = 1; 44270cd9f4ecSchristos #ifdef USE_MSG_FASTOPEN 44280cd9f4ecSchristos c->tcp_do_fastopen = 1; 44290cd9f4ecSchristos #endif 44300cd9f4ecSchristos #ifdef USE_DNSCRYPT 44310cd9f4ecSchristos c->dnscrypt = 0; 44320cd9f4ecSchristos c->dnscrypt_buffer = c->buffer; 44330cd9f4ecSchristos #endif 44343b6c3722Schristos c->repinfo.c = c; 44353b6c3722Schristos c->callback = callback; 44363b6c3722Schristos c->cb_arg = callback_arg; 4437*14b2fa6eSchristos c->pp2_enabled = 0; 4438*14b2fa6eSchristos c->pp2_header_state = pp2_header_none; 44393b6c3722Schristos evbits = UB_EV_PERSIST | UB_EV_WRITE; 44403b6c3722Schristos c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits, 44413b6c3722Schristos comm_point_tcp_handle_callback, c); 44423b6c3722Schristos if(c->ev->ev == NULL) 44433b6c3722Schristos { 44443b6c3722Schristos log_err("could not baseset tcpout event"); 44453b6c3722Schristos sldns_buffer_free(c->buffer); 44463b6c3722Schristos free(c->ev); 44473b6c3722Schristos free(c); 44483b6c3722Schristos return NULL; 44493b6c3722Schristos } 44503b6c3722Schristos 44513b6c3722Schristos return c; 44523b6c3722Schristos } 44533b6c3722Schristos 44543b6c3722Schristos struct comm_point* 44557cd94d69Schristos comm_point_create_http_out(struct comm_base *base, size_t bufsize, 44567cd94d69Schristos comm_point_callback_type* callback, void* callback_arg, 44577cd94d69Schristos sldns_buffer* temp) 44587cd94d69Schristos { 44597cd94d69Schristos struct comm_point* c = (struct comm_point*)calloc(1, 44607cd94d69Schristos sizeof(struct comm_point)); 44617cd94d69Schristos short evbits; 44627cd94d69Schristos if(!c) 44637cd94d69Schristos return NULL; 44647cd94d69Schristos c->ev = (struct internal_event*)calloc(1, 44657cd94d69Schristos sizeof(struct internal_event)); 44667cd94d69Schristos if(!c->ev) { 44677cd94d69Schristos free(c); 44687cd94d69Schristos return NULL; 44697cd94d69Schristos } 44707cd94d69Schristos c->ev->base = base; 44717cd94d69Schristos c->fd = -1; 44727cd94d69Schristos c->buffer = sldns_buffer_new(bufsize); 44737cd94d69Schristos if(!c->buffer) { 44747cd94d69Schristos free(c->ev); 44757cd94d69Schristos free(c); 44767cd94d69Schristos return NULL; 44777cd94d69Schristos } 44787cd94d69Schristos c->timeout = NULL; 44797cd94d69Schristos c->tcp_is_reading = 0; 44807cd94d69Schristos c->tcp_byte_count = 0; 44817cd94d69Schristos c->tcp_parent = NULL; 44827cd94d69Schristos c->max_tcp_count = 0; 44837cd94d69Schristos c->cur_tcp_count = 0; 44847cd94d69Schristos c->tcp_handlers = NULL; 44857cd94d69Schristos c->tcp_free = NULL; 44867cd94d69Schristos c->type = comm_http; 44877cd94d69Schristos c->tcp_do_close = 0; 44887cd94d69Schristos c->do_not_close = 0; 44897cd94d69Schristos c->tcp_do_toggle_rw = 1; 44907cd94d69Schristos c->tcp_check_nb_connect = 1; 44917cd94d69Schristos c->http_in_headers = 1; 44927cd94d69Schristos c->http_in_chunk_headers = 0; 44937cd94d69Schristos c->http_is_chunked = 0; 44947cd94d69Schristos c->http_temp = temp; 44957cd94d69Schristos #ifdef USE_MSG_FASTOPEN 44967cd94d69Schristos c->tcp_do_fastopen = 1; 44977cd94d69Schristos #endif 44987cd94d69Schristos #ifdef USE_DNSCRYPT 44997cd94d69Schristos c->dnscrypt = 0; 45007cd94d69Schristos c->dnscrypt_buffer = c->buffer; 45017cd94d69Schristos #endif 45027cd94d69Schristos c->repinfo.c = c; 45037cd94d69Schristos c->callback = callback; 45047cd94d69Schristos c->cb_arg = callback_arg; 4505*14b2fa6eSchristos c->pp2_enabled = 0; 4506*14b2fa6eSchristos c->pp2_header_state = pp2_header_none; 45077cd94d69Schristos evbits = UB_EV_PERSIST | UB_EV_WRITE; 45087cd94d69Schristos c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits, 45097cd94d69Schristos comm_point_http_handle_callback, c); 45107cd94d69Schristos if(c->ev->ev == NULL) 45117cd94d69Schristos { 45127cd94d69Schristos log_err("could not baseset tcpout event"); 45137cd94d69Schristos #ifdef HAVE_SSL 45147cd94d69Schristos SSL_free(c->ssl); 45157cd94d69Schristos #endif 45167cd94d69Schristos sldns_buffer_free(c->buffer); 45177cd94d69Schristos free(c->ev); 45187cd94d69Schristos free(c); 45197cd94d69Schristos return NULL; 45207cd94d69Schristos } 45217cd94d69Schristos 45227cd94d69Schristos return c; 45237cd94d69Schristos } 45247cd94d69Schristos 45257cd94d69Schristos struct comm_point* 45263b6c3722Schristos comm_point_create_local(struct comm_base *base, int fd, size_t bufsize, 45270cd9f4ecSchristos comm_point_callback_type* callback, void* callback_arg) 45283b6c3722Schristos { 45293b6c3722Schristos struct comm_point* c = (struct comm_point*)calloc(1, 45303b6c3722Schristos sizeof(struct comm_point)); 45313b6c3722Schristos short evbits; 45323b6c3722Schristos if(!c) 45333b6c3722Schristos return NULL; 45343b6c3722Schristos c->ev = (struct internal_event*)calloc(1, 45353b6c3722Schristos sizeof(struct internal_event)); 45363b6c3722Schristos if(!c->ev) { 45373b6c3722Schristos free(c); 45383b6c3722Schristos return NULL; 45393b6c3722Schristos } 45403b6c3722Schristos c->ev->base = base; 45413b6c3722Schristos c->fd = fd; 45423b6c3722Schristos c->buffer = sldns_buffer_new(bufsize); 45433b6c3722Schristos if(!c->buffer) { 45443b6c3722Schristos free(c->ev); 45453b6c3722Schristos free(c); 45463b6c3722Schristos return NULL; 45473b6c3722Schristos } 45483b6c3722Schristos c->timeout = NULL; 45493b6c3722Schristos c->tcp_is_reading = 1; 45503b6c3722Schristos c->tcp_byte_count = 0; 45513b6c3722Schristos c->tcp_parent = NULL; 45523b6c3722Schristos c->max_tcp_count = 0; 45533b6c3722Schristos c->cur_tcp_count = 0; 45543b6c3722Schristos c->tcp_handlers = NULL; 45553b6c3722Schristos c->tcp_free = NULL; 45563b6c3722Schristos c->type = comm_local; 45573b6c3722Schristos c->tcp_do_close = 0; 45583b6c3722Schristos c->do_not_close = 1; 45593b6c3722Schristos c->tcp_do_toggle_rw = 0; 45603b6c3722Schristos c->tcp_check_nb_connect = 0; 45610cd9f4ecSchristos #ifdef USE_MSG_FASTOPEN 45620cd9f4ecSchristos c->tcp_do_fastopen = 0; 45630cd9f4ecSchristos #endif 45640cd9f4ecSchristos #ifdef USE_DNSCRYPT 45650cd9f4ecSchristos c->dnscrypt = 0; 45660cd9f4ecSchristos c->dnscrypt_buffer = c->buffer; 45670cd9f4ecSchristos #endif 45683b6c3722Schristos c->callback = callback; 45693b6c3722Schristos c->cb_arg = callback_arg; 4570*14b2fa6eSchristos c->pp2_enabled = 0; 4571*14b2fa6eSchristos c->pp2_header_state = pp2_header_none; 45723b6c3722Schristos /* ub_event stuff */ 45733b6c3722Schristos evbits = UB_EV_PERSIST | UB_EV_READ; 45743b6c3722Schristos c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits, 45753b6c3722Schristos comm_point_local_handle_callback, c); 45763b6c3722Schristos if(c->ev->ev == NULL) { 45773b6c3722Schristos log_err("could not baseset localhdl event"); 45783b6c3722Schristos free(c->ev); 45793b6c3722Schristos free(c); 45803b6c3722Schristos return NULL; 45813b6c3722Schristos } 45823b6c3722Schristos if (ub_event_add(c->ev->ev, c->timeout) != 0) { 45833b6c3722Schristos log_err("could not add localhdl event"); 45843b6c3722Schristos ub_event_free(c->ev->ev); 45853b6c3722Schristos free(c->ev); 45863b6c3722Schristos free(c); 45873b6c3722Schristos return NULL; 45883b6c3722Schristos } 458916776186Schristos c->event_added = 1; 45903b6c3722Schristos return c; 45913b6c3722Schristos } 45923b6c3722Schristos 45933b6c3722Schristos struct comm_point* 45943b6c3722Schristos comm_point_create_raw(struct comm_base* base, int fd, int writing, 45950cd9f4ecSchristos comm_point_callback_type* callback, void* callback_arg) 45963b6c3722Schristos { 45973b6c3722Schristos struct comm_point* c = (struct comm_point*)calloc(1, 45983b6c3722Schristos sizeof(struct comm_point)); 45993b6c3722Schristos short evbits; 46003b6c3722Schristos if(!c) 46013b6c3722Schristos return NULL; 46023b6c3722Schristos c->ev = (struct internal_event*)calloc(1, 46033b6c3722Schristos sizeof(struct internal_event)); 46043b6c3722Schristos if(!c->ev) { 46053b6c3722Schristos free(c); 46063b6c3722Schristos return NULL; 46073b6c3722Schristos } 46083b6c3722Schristos c->ev->base = base; 46093b6c3722Schristos c->fd = fd; 46103b6c3722Schristos c->buffer = NULL; 46113b6c3722Schristos c->timeout = NULL; 46123b6c3722Schristos c->tcp_is_reading = 0; 46133b6c3722Schristos c->tcp_byte_count = 0; 46143b6c3722Schristos c->tcp_parent = NULL; 46153b6c3722Schristos c->max_tcp_count = 0; 46163b6c3722Schristos c->cur_tcp_count = 0; 46173b6c3722Schristos c->tcp_handlers = NULL; 46183b6c3722Schristos c->tcp_free = NULL; 46193b6c3722Schristos c->type = comm_raw; 46203b6c3722Schristos c->tcp_do_close = 0; 46213b6c3722Schristos c->do_not_close = 1; 46223b6c3722Schristos c->tcp_do_toggle_rw = 0; 46233b6c3722Schristos c->tcp_check_nb_connect = 0; 46240cd9f4ecSchristos #ifdef USE_MSG_FASTOPEN 46250cd9f4ecSchristos c->tcp_do_fastopen = 0; 46260cd9f4ecSchristos #endif 46270cd9f4ecSchristos #ifdef USE_DNSCRYPT 46280cd9f4ecSchristos c->dnscrypt = 0; 46290cd9f4ecSchristos c->dnscrypt_buffer = c->buffer; 46300cd9f4ecSchristos #endif 46313b6c3722Schristos c->callback = callback; 46323b6c3722Schristos c->cb_arg = callback_arg; 4633*14b2fa6eSchristos c->pp2_enabled = 0; 4634*14b2fa6eSchristos c->pp2_header_state = pp2_header_none; 46353b6c3722Schristos /* ub_event stuff */ 46363b6c3722Schristos if(writing) 46373b6c3722Schristos evbits = UB_EV_PERSIST | UB_EV_WRITE; 46383b6c3722Schristos else evbits = UB_EV_PERSIST | UB_EV_READ; 46393b6c3722Schristos c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits, 46403b6c3722Schristos comm_point_raw_handle_callback, c); 46413b6c3722Schristos if(c->ev->ev == NULL) { 46423b6c3722Schristos log_err("could not baseset rawhdl event"); 46433b6c3722Schristos free(c->ev); 46443b6c3722Schristos free(c); 46453b6c3722Schristos return NULL; 46463b6c3722Schristos } 46473b6c3722Schristos if (ub_event_add(c->ev->ev, c->timeout) != 0) { 46483b6c3722Schristos log_err("could not add rawhdl event"); 46493b6c3722Schristos ub_event_free(c->ev->ev); 46503b6c3722Schristos free(c->ev); 46513b6c3722Schristos free(c); 46523b6c3722Schristos return NULL; 46533b6c3722Schristos } 465416776186Schristos c->event_added = 1; 46553b6c3722Schristos return c; 46563b6c3722Schristos } 46573b6c3722Schristos 46583b6c3722Schristos void 46593b6c3722Schristos comm_point_close(struct comm_point* c) 46603b6c3722Schristos { 46613b6c3722Schristos if(!c) 46623b6c3722Schristos return; 46637cd94d69Schristos if(c->fd != -1) { 466416776186Schristos verbose(5, "comm_point_close of %d: event_del", c->fd); 466516776186Schristos if(c->event_added) { 46663b6c3722Schristos if(ub_event_del(c->ev->ev) != 0) { 46673b6c3722Schristos log_err("could not event_del on close"); 46683b6c3722Schristos } 466916776186Schristos c->event_added = 0; 467016776186Schristos } 46717cd94d69Schristos } 4672f42d8de7Schristos tcl_close_connection(c->tcl_addr); 4673f42d8de7Schristos if(c->tcp_req_info) 4674f42d8de7Schristos tcp_req_info_clear(c->tcp_req_info); 467516776186Schristos if(c->h2_session) 467616776186Schristos http2_session_server_delete(c->h2_session); 4677*14b2fa6eSchristos /* stop the comm point from reading or writing after it is closed. */ 4678*14b2fa6eSchristos if(c->tcp_more_read_again && *c->tcp_more_read_again) 4679*14b2fa6eSchristos *c->tcp_more_read_again = 0; 4680*14b2fa6eSchristos if(c->tcp_more_write_again && *c->tcp_more_write_again) 4681*14b2fa6eSchristos *c->tcp_more_write_again = 0; 468216776186Schristos 46833b6c3722Schristos /* close fd after removing from event lists, or epoll.. is messed up */ 46843b6c3722Schristos if(c->fd != -1 && !c->do_not_close) { 46851481e2a9Schristos #ifdef USE_WINSOCK 46867cd94d69Schristos if(c->type == comm_tcp || c->type == comm_http) { 46877cd94d69Schristos /* delete sticky events for the fd, it gets closed */ 46887cd94d69Schristos ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_READ); 46897cd94d69Schristos ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE); 46907cd94d69Schristos } 46911481e2a9Schristos #endif 46923b6c3722Schristos verbose(VERB_ALGO, "close fd %d", c->fd); 469316776186Schristos sock_close(c->fd); 46943b6c3722Schristos } 46953b6c3722Schristos c->fd = -1; 46963b6c3722Schristos } 46973b6c3722Schristos 46983b6c3722Schristos void 46993b6c3722Schristos comm_point_delete(struct comm_point* c) 47003b6c3722Schristos { 47013b6c3722Schristos if(!c) 47023b6c3722Schristos return; 47037cd94d69Schristos if((c->type == comm_tcp || c->type == comm_http) && c->ssl) { 47043b6c3722Schristos #ifdef HAVE_SSL 47053b6c3722Schristos SSL_shutdown(c->ssl); 47063b6c3722Schristos SSL_free(c->ssl); 47073b6c3722Schristos #endif 47083b6c3722Schristos } 470916776186Schristos if(c->type == comm_http && c->http_endpoint) { 471016776186Schristos free(c->http_endpoint); 471116776186Schristos c->http_endpoint = NULL; 471216776186Schristos } 47133b6c3722Schristos comm_point_close(c); 47143b6c3722Schristos if(c->tcp_handlers) { 47153b6c3722Schristos int i; 47163b6c3722Schristos for(i=0; i<c->max_tcp_count; i++) 47173b6c3722Schristos comm_point_delete(c->tcp_handlers[i]); 47183b6c3722Schristos free(c->tcp_handlers); 47193b6c3722Schristos } 47203b6c3722Schristos free(c->timeout); 47217cd94d69Schristos if(c->type == comm_tcp || c->type == comm_local || c->type == comm_http) { 47223b6c3722Schristos sldns_buffer_free(c->buffer); 47230cd9f4ecSchristos #ifdef USE_DNSCRYPT 47240cd9f4ecSchristos if(c->dnscrypt && c->dnscrypt_buffer != c->buffer) { 47250cd9f4ecSchristos sldns_buffer_free(c->dnscrypt_buffer); 47260cd9f4ecSchristos } 47270cd9f4ecSchristos #endif 4728f42d8de7Schristos if(c->tcp_req_info) { 4729f42d8de7Schristos tcp_req_info_delete(c->tcp_req_info); 4730f42d8de7Schristos } 473116776186Schristos if(c->h2_session) { 473216776186Schristos http2_session_delete(c->h2_session); 473316776186Schristos } 47340cd9f4ecSchristos } 47353b6c3722Schristos ub_event_free(c->ev->ev); 47363b6c3722Schristos free(c->ev); 47373b6c3722Schristos free(c); 47383b6c3722Schristos } 47393b6c3722Schristos 47403b6c3722Schristos void 47413b6c3722Schristos comm_point_send_reply(struct comm_reply *repinfo) 47423b6c3722Schristos { 47430cd9f4ecSchristos struct sldns_buffer* buffer; 47443b6c3722Schristos log_assert(repinfo && repinfo->c); 47450cd9f4ecSchristos #ifdef USE_DNSCRYPT 47460cd9f4ecSchristos buffer = repinfo->c->dnscrypt_buffer; 47470cd9f4ecSchristos if(!dnsc_handle_uncurved_request(repinfo)) { 47480cd9f4ecSchristos return; 47490cd9f4ecSchristos } 47500cd9f4ecSchristos #else 47510cd9f4ecSchristos buffer = repinfo->c->buffer; 47520cd9f4ecSchristos #endif 47533b6c3722Schristos if(repinfo->c->type == comm_udp) { 47543b6c3722Schristos if(repinfo->srctype) 4755*14b2fa6eSchristos comm_point_send_udp_msg_if(repinfo->c, buffer, 4756*14b2fa6eSchristos (struct sockaddr*)&repinfo->remote_addr, 4757*14b2fa6eSchristos repinfo->remote_addrlen, repinfo); 47583b6c3722Schristos else 47590cd9f4ecSchristos comm_point_send_udp_msg(repinfo->c, buffer, 4760*14b2fa6eSchristos (struct sockaddr*)&repinfo->remote_addr, 4761*14b2fa6eSchristos repinfo->remote_addrlen, 0); 47623b6c3722Schristos #ifdef USE_DNSTAP 47631481e2a9Schristos /* 47641481e2a9Schristos * sending src (client)/dst (local service) addresses over DNSTAP from udp callback 47651481e2a9Schristos */ 47661481e2a9Schristos if(repinfo->c->dtenv != NULL && repinfo->c->dtenv->log_client_response_messages) { 47671481e2a9Schristos log_addr(VERB_ALGO, "from local addr", (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->socket->addr->ai_addrlen); 4768*14b2fa6eSchristos log_addr(VERB_ALGO, "response to client", &repinfo->client_addr, repinfo->client_addrlen); 4769*14b2fa6eSchristos dt_msg_send_client_response(repinfo->c->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->type, repinfo->c->buffer); 47701481e2a9Schristos } 47713b6c3722Schristos #endif 47723b6c3722Schristos } else { 47733b6c3722Schristos #ifdef USE_DNSTAP 47741481e2a9Schristos /* 47751481e2a9Schristos * sending src (client)/dst (local service) addresses over DNSTAP from TCP callback 47761481e2a9Schristos */ 47771481e2a9Schristos if(repinfo->c->tcp_parent->dtenv != NULL && repinfo->c->tcp_parent->dtenv->log_client_response_messages) { 47781481e2a9Schristos log_addr(VERB_ALGO, "from local addr", (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->socket->addr->ai_addrlen); 4779*14b2fa6eSchristos log_addr(VERB_ALGO, "response to client", &repinfo->client_addr, repinfo->client_addrlen); 4780*14b2fa6eSchristos dt_msg_send_client_response(repinfo->c->tcp_parent->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->type, 47811481e2a9Schristos ( repinfo->c->tcp_req_info? repinfo->c->tcp_req_info->spool_buffer: repinfo->c->buffer )); 47821481e2a9Schristos } 47833b6c3722Schristos #endif 4784f42d8de7Schristos if(repinfo->c->tcp_req_info) { 4785f42d8de7Schristos tcp_req_info_send_reply(repinfo->c->tcp_req_info); 478616776186Schristos } else if(repinfo->c->use_h2) { 478716776186Schristos if(!http2_submit_dns_response(repinfo->c->h2_session)) { 478816776186Schristos comm_point_drop_reply(repinfo); 478916776186Schristos return; 479016776186Schristos } 479116776186Schristos repinfo->c->h2_stream = NULL; 479216776186Schristos repinfo->c->tcp_is_reading = 0; 479316776186Schristos comm_point_stop_listening(repinfo->c); 479416776186Schristos comm_point_start_listening(repinfo->c, -1, 479516776186Schristos adjusted_tcp_timeout(repinfo->c)); 479616776186Schristos return; 4797f42d8de7Schristos } else { 47980cd9f4ecSchristos comm_point_start_listening(repinfo->c, -1, 479916776186Schristos adjusted_tcp_timeout(repinfo->c)); 48003b6c3722Schristos } 48013b6c3722Schristos } 4802f42d8de7Schristos } 48033b6c3722Schristos 48043b6c3722Schristos void 48053b6c3722Schristos comm_point_drop_reply(struct comm_reply* repinfo) 48063b6c3722Schristos { 48073b6c3722Schristos if(!repinfo) 48083b6c3722Schristos return; 480987edd195Schristos log_assert(repinfo->c); 48103b6c3722Schristos log_assert(repinfo->c->type != comm_tcp_accept); 48113b6c3722Schristos if(repinfo->c->type == comm_udp) 48123b6c3722Schristos return; 4813f42d8de7Schristos if(repinfo->c->tcp_req_info) 4814f42d8de7Schristos repinfo->c->tcp_req_info->is_drop = 1; 481516776186Schristos if(repinfo->c->type == comm_http) { 481616776186Schristos if(repinfo->c->h2_session) { 481716776186Schristos repinfo->c->h2_session->is_drop = 1; 481816776186Schristos if(!repinfo->c->h2_session->postpone_drop) 481916776186Schristos reclaim_http_handler(repinfo->c); 482016776186Schristos return; 482116776186Schristos } 482216776186Schristos reclaim_http_handler(repinfo->c); 482316776186Schristos return; 482416776186Schristos } 48253b6c3722Schristos reclaim_tcp_handler(repinfo->c); 48263b6c3722Schristos } 48273b6c3722Schristos 48283b6c3722Schristos void 48293b6c3722Schristos comm_point_stop_listening(struct comm_point* c) 48303b6c3722Schristos { 48313b6c3722Schristos verbose(VERB_ALGO, "comm point stop listening %d", c->fd); 483216776186Schristos if(c->event_added) { 48333b6c3722Schristos if(ub_event_del(c->ev->ev) != 0) { 48343b6c3722Schristos log_err("event_del error to stoplisten"); 48353b6c3722Schristos } 483616776186Schristos c->event_added = 0; 483716776186Schristos } 48383b6c3722Schristos } 48393b6c3722Schristos 48403b6c3722Schristos void 48410cd9f4ecSchristos comm_point_start_listening(struct comm_point* c, int newfd, int msec) 48423b6c3722Schristos { 484387edd195Schristos verbose(VERB_ALGO, "comm point start listening %d (%d msec)", 484487edd195Schristos c->fd==-1?newfd:c->fd, msec); 48453b6c3722Schristos if(c->type == comm_tcp_accept && !c->tcp_free) { 48463b6c3722Schristos /* no use to start listening no free slots. */ 48473b6c3722Schristos return; 48483b6c3722Schristos } 484916776186Schristos if(c->event_added) { 485016776186Schristos if(ub_event_del(c->ev->ev) != 0) { 485116776186Schristos log_err("event_del error to startlisten"); 485216776186Schristos } 485316776186Schristos c->event_added = 0; 485416776186Schristos } 48550cd9f4ecSchristos if(msec != -1 && msec != 0) { 48563b6c3722Schristos if(!c->timeout) { 48573b6c3722Schristos c->timeout = (struct timeval*)malloc(sizeof( 48583b6c3722Schristos struct timeval)); 48593b6c3722Schristos if(!c->timeout) { 48603b6c3722Schristos log_err("cpsl: malloc failed. No net read."); 48613b6c3722Schristos return; 48623b6c3722Schristos } 48633b6c3722Schristos } 48643b6c3722Schristos ub_event_add_bits(c->ev->ev, UB_EV_TIMEOUT); 48653b6c3722Schristos #ifndef S_SPLINT_S /* splint fails on struct timeval. */ 48660cd9f4ecSchristos c->timeout->tv_sec = msec/1000; 48670cd9f4ecSchristos c->timeout->tv_usec = (msec%1000)*1000; 48683b6c3722Schristos #endif /* S_SPLINT_S */ 48691481e2a9Schristos } else { 48701481e2a9Schristos if(msec == 0 || !c->timeout) { 48711481e2a9Schristos ub_event_del_bits(c->ev->ev, UB_EV_TIMEOUT); 48721481e2a9Schristos } 48733b6c3722Schristos } 48747cd94d69Schristos if(c->type == comm_tcp || c->type == comm_http) { 48753b6c3722Schristos ub_event_del_bits(c->ev->ev, UB_EV_READ|UB_EV_WRITE); 487616776186Schristos if(c->tcp_write_and_read) { 487716776186Schristos verbose(5, "startlistening %d mode rw", (newfd==-1?c->fd:newfd)); 487816776186Schristos ub_event_add_bits(c->ev->ev, UB_EV_READ|UB_EV_WRITE); 487916776186Schristos } else if(c->tcp_is_reading) { 488016776186Schristos verbose(5, "startlistening %d mode r", (newfd==-1?c->fd:newfd)); 48813b6c3722Schristos ub_event_add_bits(c->ev->ev, UB_EV_READ); 488216776186Schristos } else { 488316776186Schristos verbose(5, "startlistening %d mode w", (newfd==-1?c->fd:newfd)); 488416776186Schristos ub_event_add_bits(c->ev->ev, UB_EV_WRITE); 488516776186Schristos } 48863b6c3722Schristos } 48873b6c3722Schristos if(newfd != -1) { 488816776186Schristos if(c->fd != -1 && c->fd != newfd) { 488916776186Schristos verbose(5, "cpsl close of fd %d for %d", c->fd, newfd); 489016776186Schristos sock_close(c->fd); 48913b6c3722Schristos } 48923b6c3722Schristos c->fd = newfd; 48933b6c3722Schristos ub_event_set_fd(c->ev->ev, c->fd); 48943b6c3722Schristos } 48950cd9f4ecSchristos if(ub_event_add(c->ev->ev, msec==0?NULL:c->timeout) != 0) { 48963b6c3722Schristos log_err("event_add failed. in cpsl."); 48971481e2a9Schristos return; 48983b6c3722Schristos } 489916776186Schristos c->event_added = 1; 49003b6c3722Schristos } 49013b6c3722Schristos 49023b6c3722Schristos void comm_point_listen_for_rw(struct comm_point* c, int rd, int wr) 49033b6c3722Schristos { 49043b6c3722Schristos verbose(VERB_ALGO, "comm point listen_for_rw %d %d", c->fd, wr); 490516776186Schristos if(c->event_added) { 49063b6c3722Schristos if(ub_event_del(c->ev->ev) != 0) { 49073b6c3722Schristos log_err("event_del error to cplf"); 49083b6c3722Schristos } 490916776186Schristos c->event_added = 0; 491016776186Schristos } 49111481e2a9Schristos if(!c->timeout) { 49121481e2a9Schristos ub_event_del_bits(c->ev->ev, UB_EV_TIMEOUT); 49131481e2a9Schristos } 49143b6c3722Schristos ub_event_del_bits(c->ev->ev, UB_EV_READ|UB_EV_WRITE); 49153b6c3722Schristos if(rd) ub_event_add_bits(c->ev->ev, UB_EV_READ); 49163b6c3722Schristos if(wr) ub_event_add_bits(c->ev->ev, UB_EV_WRITE); 49173b6c3722Schristos if(ub_event_add(c->ev->ev, c->timeout) != 0) { 49183b6c3722Schristos log_err("event_add failed. in cplf."); 49191481e2a9Schristos return; 49203b6c3722Schristos } 492116776186Schristos c->event_added = 1; 49223b6c3722Schristos } 49233b6c3722Schristos 49243b6c3722Schristos size_t comm_point_get_mem(struct comm_point* c) 49253b6c3722Schristos { 49263b6c3722Schristos size_t s; 49273b6c3722Schristos if(!c) 49283b6c3722Schristos return 0; 49293b6c3722Schristos s = sizeof(*c) + sizeof(*c->ev); 49303b6c3722Schristos if(c->timeout) 49313b6c3722Schristos s += sizeof(*c->timeout); 49320cd9f4ecSchristos if(c->type == comm_tcp || c->type == comm_local) { 49333b6c3722Schristos s += sizeof(*c->buffer) + sldns_buffer_capacity(c->buffer); 49340cd9f4ecSchristos #ifdef USE_DNSCRYPT 49350cd9f4ecSchristos s += sizeof(*c->dnscrypt_buffer); 49360cd9f4ecSchristos if(c->buffer != c->dnscrypt_buffer) { 49370cd9f4ecSchristos s += sldns_buffer_capacity(c->dnscrypt_buffer); 49380cd9f4ecSchristos } 49390cd9f4ecSchristos #endif 49400cd9f4ecSchristos } 49413b6c3722Schristos if(c->type == comm_tcp_accept) { 49423b6c3722Schristos int i; 49433b6c3722Schristos for(i=0; i<c->max_tcp_count; i++) 49443b6c3722Schristos s += comm_point_get_mem(c->tcp_handlers[i]); 49453b6c3722Schristos } 49463b6c3722Schristos return s; 49473b6c3722Schristos } 49483b6c3722Schristos 49493b6c3722Schristos struct comm_timer* 49503b6c3722Schristos comm_timer_create(struct comm_base* base, void (*cb)(void*), void* cb_arg) 49513b6c3722Schristos { 49523b6c3722Schristos struct internal_timer *tm = (struct internal_timer*)calloc(1, 49533b6c3722Schristos sizeof(struct internal_timer)); 49543b6c3722Schristos if(!tm) { 49553b6c3722Schristos log_err("malloc failed"); 49563b6c3722Schristos return NULL; 49573b6c3722Schristos } 49583b6c3722Schristos tm->super.ev_timer = tm; 49593b6c3722Schristos tm->base = base; 49603b6c3722Schristos tm->super.callback = cb; 49613b6c3722Schristos tm->super.cb_arg = cb_arg; 49623b6c3722Schristos tm->ev = ub_event_new(base->eb->base, -1, UB_EV_TIMEOUT, 49633b6c3722Schristos comm_timer_callback, &tm->super); 49643b6c3722Schristos if(tm->ev == NULL) { 49653b6c3722Schristos log_err("timer_create: event_base_set failed."); 49663b6c3722Schristos free(tm); 49673b6c3722Schristos return NULL; 49683b6c3722Schristos } 49693b6c3722Schristos return &tm->super; 49703b6c3722Schristos } 49713b6c3722Schristos 49723b6c3722Schristos void 49733b6c3722Schristos comm_timer_disable(struct comm_timer* timer) 49743b6c3722Schristos { 49753b6c3722Schristos if(!timer) 49763b6c3722Schristos return; 49773b6c3722Schristos ub_timer_del(timer->ev_timer->ev); 49783b6c3722Schristos timer->ev_timer->enabled = 0; 49793b6c3722Schristos } 49803b6c3722Schristos 49813b6c3722Schristos void 49823b6c3722Schristos comm_timer_set(struct comm_timer* timer, struct timeval* tv) 49833b6c3722Schristos { 49843b6c3722Schristos log_assert(tv); 49853b6c3722Schristos if(timer->ev_timer->enabled) 49863b6c3722Schristos comm_timer_disable(timer); 49873b6c3722Schristos if(ub_timer_add(timer->ev_timer->ev, timer->ev_timer->base->eb->base, 49883b6c3722Schristos comm_timer_callback, timer, tv) != 0) 49893b6c3722Schristos log_err("comm_timer_set: evtimer_add failed."); 49903b6c3722Schristos timer->ev_timer->enabled = 1; 49913b6c3722Schristos } 49923b6c3722Schristos 49933b6c3722Schristos void 49943b6c3722Schristos comm_timer_delete(struct comm_timer* timer) 49953b6c3722Schristos { 49963b6c3722Schristos if(!timer) 49973b6c3722Schristos return; 49983b6c3722Schristos comm_timer_disable(timer); 49993b6c3722Schristos /* Free the sub struct timer->ev_timer derived from the super struct timer. 50003b6c3722Schristos * i.e. assert(timer == timer->ev_timer) 50013b6c3722Schristos */ 50023b6c3722Schristos ub_event_free(timer->ev_timer->ev); 50033b6c3722Schristos free(timer->ev_timer); 50043b6c3722Schristos } 50053b6c3722Schristos 50063b6c3722Schristos void 50073b6c3722Schristos comm_timer_callback(int ATTR_UNUSED(fd), short event, void* arg) 50083b6c3722Schristos { 50093b6c3722Schristos struct comm_timer* tm = (struct comm_timer*)arg; 50103b6c3722Schristos if(!(event&UB_EV_TIMEOUT)) 50113b6c3722Schristos return; 50123b6c3722Schristos ub_comm_base_now(tm->ev_timer->base); 50133b6c3722Schristos tm->ev_timer->enabled = 0; 50143b6c3722Schristos fptr_ok(fptr_whitelist_comm_timer(tm->callback)); 50153b6c3722Schristos (*tm->callback)(tm->cb_arg); 50163b6c3722Schristos } 50173b6c3722Schristos 50183b6c3722Schristos int 50193b6c3722Schristos comm_timer_is_set(struct comm_timer* timer) 50203b6c3722Schristos { 50213b6c3722Schristos return (int)timer->ev_timer->enabled; 50223b6c3722Schristos } 50233b6c3722Schristos 50243b6c3722Schristos size_t 50253b6c3722Schristos comm_timer_get_mem(struct comm_timer* ATTR_UNUSED(timer)) 50263b6c3722Schristos { 50273b6c3722Schristos return sizeof(struct internal_timer); 50283b6c3722Schristos } 50293b6c3722Schristos 50303b6c3722Schristos struct comm_signal* 50313b6c3722Schristos comm_signal_create(struct comm_base* base, 50323b6c3722Schristos void (*callback)(int, void*), void* cb_arg) 50333b6c3722Schristos { 50343b6c3722Schristos struct comm_signal* com = (struct comm_signal*)malloc( 50353b6c3722Schristos sizeof(struct comm_signal)); 50363b6c3722Schristos if(!com) { 50373b6c3722Schristos log_err("malloc failed"); 50383b6c3722Schristos return NULL; 50393b6c3722Schristos } 50403b6c3722Schristos com->base = base; 50413b6c3722Schristos com->callback = callback; 50423b6c3722Schristos com->cb_arg = cb_arg; 50433b6c3722Schristos com->ev_signal = NULL; 50443b6c3722Schristos return com; 50453b6c3722Schristos } 50463b6c3722Schristos 50473b6c3722Schristos void 50483b6c3722Schristos comm_signal_callback(int sig, short event, void* arg) 50493b6c3722Schristos { 50503b6c3722Schristos struct comm_signal* comsig = (struct comm_signal*)arg; 50513b6c3722Schristos if(!(event & UB_EV_SIGNAL)) 50523b6c3722Schristos return; 50533b6c3722Schristos ub_comm_base_now(comsig->base); 50543b6c3722Schristos fptr_ok(fptr_whitelist_comm_signal(comsig->callback)); 50553b6c3722Schristos (*comsig->callback)(sig, comsig->cb_arg); 50563b6c3722Schristos } 50573b6c3722Schristos 50583b6c3722Schristos int 50593b6c3722Schristos comm_signal_bind(struct comm_signal* comsig, int sig) 50603b6c3722Schristos { 50613b6c3722Schristos struct internal_signal* entry = (struct internal_signal*)calloc(1, 50623b6c3722Schristos sizeof(struct internal_signal)); 50633b6c3722Schristos if(!entry) { 50643b6c3722Schristos log_err("malloc failed"); 50653b6c3722Schristos return 0; 50663b6c3722Schristos } 50673b6c3722Schristos log_assert(comsig); 50683b6c3722Schristos /* add signal event */ 50693b6c3722Schristos entry->ev = ub_signal_new(comsig->base->eb->base, sig, 50703b6c3722Schristos comm_signal_callback, comsig); 50713b6c3722Schristos if(entry->ev == NULL) { 50723b6c3722Schristos log_err("Could not create signal event"); 50733b6c3722Schristos free(entry); 50743b6c3722Schristos return 0; 50753b6c3722Schristos } 50763b6c3722Schristos if(ub_signal_add(entry->ev, NULL) != 0) { 50773b6c3722Schristos log_err("Could not add signal handler"); 50783b6c3722Schristos ub_event_free(entry->ev); 50793b6c3722Schristos free(entry); 50803b6c3722Schristos return 0; 50813b6c3722Schristos } 50823b6c3722Schristos /* link into list */ 50833b6c3722Schristos entry->next = comsig->ev_signal; 50843b6c3722Schristos comsig->ev_signal = entry; 50853b6c3722Schristos return 1; 50863b6c3722Schristos } 50873b6c3722Schristos 50883b6c3722Schristos void 50893b6c3722Schristos comm_signal_delete(struct comm_signal* comsig) 50903b6c3722Schristos { 50913b6c3722Schristos struct internal_signal* p, *np; 50923b6c3722Schristos if(!comsig) 50933b6c3722Schristos return; 50943b6c3722Schristos p=comsig->ev_signal; 50953b6c3722Schristos while(p) { 50963b6c3722Schristos np = p->next; 50973b6c3722Schristos ub_signal_del(p->ev); 50983b6c3722Schristos ub_event_free(p->ev); 50993b6c3722Schristos free(p); 51003b6c3722Schristos p = np; 51013b6c3722Schristos } 51023b6c3722Schristos free(comsig); 51033b6c3722Schristos } 5104