1ae8c6e27Sflorian /* 2ae8c6e27Sflorian * util/netevent.c - event notification 3ae8c6e27Sflorian * 4ae8c6e27Sflorian * Copyright (c) 2007, NLnet Labs. All rights reserved. 5ae8c6e27Sflorian * 6ae8c6e27Sflorian * This software is open source. 7ae8c6e27Sflorian * 8ae8c6e27Sflorian * Redistribution and use in source and binary forms, with or without 9ae8c6e27Sflorian * modification, are permitted provided that the following conditions 10ae8c6e27Sflorian * are met: 11ae8c6e27Sflorian * 12ae8c6e27Sflorian * Redistributions of source code must retain the above copyright notice, 13ae8c6e27Sflorian * this list of conditions and the following disclaimer. 14ae8c6e27Sflorian * 15ae8c6e27Sflorian * Redistributions in binary form must reproduce the above copyright notice, 16ae8c6e27Sflorian * this list of conditions and the following disclaimer in the documentation 17ae8c6e27Sflorian * and/or other materials provided with the distribution. 18ae8c6e27Sflorian * 19ae8c6e27Sflorian * Neither the name of the NLNET LABS nor the names of its contributors may 20ae8c6e27Sflorian * be used to endorse or promote products derived from this software without 21ae8c6e27Sflorian * specific prior written permission. 22ae8c6e27Sflorian * 23ae8c6e27Sflorian * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24ae8c6e27Sflorian * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25ae8c6e27Sflorian * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26ae8c6e27Sflorian * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27ae8c6e27Sflorian * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28ae8c6e27Sflorian * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29ae8c6e27Sflorian * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30ae8c6e27Sflorian * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31ae8c6e27Sflorian * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32ae8c6e27Sflorian * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33ae8c6e27Sflorian * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34ae8c6e27Sflorian */ 35ae8c6e27Sflorian 36ae8c6e27Sflorian /** 37ae8c6e27Sflorian * \file 38ae8c6e27Sflorian * 39ae8c6e27Sflorian * This file contains event notification functions. 40ae8c6e27Sflorian */ 41ae8c6e27Sflorian #include "config.h" 42ae8c6e27Sflorian #include "util/netevent.h" 43ae8c6e27Sflorian #include "util/ub_event.h" 44ae8c6e27Sflorian #include "util/log.h" 45ae8c6e27Sflorian #include "util/net_help.h" 46ae8c6e27Sflorian #include "util/tcp_conn_limit.h" 47ae8c6e27Sflorian #include "util/fptr_wlist.h" 485c45b740Sflorian #include "util/proxy_protocol.h" 49d500c338Sflorian #include "util/timeval_func.h" 50ae8c6e27Sflorian #include "sldns/pkthdr.h" 51ae8c6e27Sflorian #include "sldns/sbuffer.h" 52ae8c6e27Sflorian #include "sldns/str2wire.h" 53ae8c6e27Sflorian #include "dnstap/dnstap.h" 54ae8c6e27Sflorian #include "dnscrypt/dnscrypt.h" 55e97c6e54Ssthen #include "services/listen_dnsport.h" 56411c5950Sflorian #ifdef HAVE_SYS_TYPES_H 57411c5950Sflorian #include <sys/types.h> 58411c5950Sflorian #endif 59411c5950Sflorian #ifdef HAVE_SYS_SOCKET_H 60411c5950Sflorian #include <sys/socket.h> 61411c5950Sflorian #endif 62411c5950Sflorian #ifdef HAVE_NETDB_H 63411c5950Sflorian #include <netdb.h> 64411c5950Sflorian #endif 655c45b740Sflorian #ifdef HAVE_POLL_H 665c45b740Sflorian #include <poll.h> 675c45b740Sflorian #endif 68411c5950Sflorian 69ae8c6e27Sflorian #ifdef HAVE_OPENSSL_SSL_H 70ae8c6e27Sflorian #include <openssl/ssl.h> 71ae8c6e27Sflorian #endif 72ae8c6e27Sflorian #ifdef HAVE_OPENSSL_ERR_H 73ae8c6e27Sflorian #include <openssl/err.h> 74ae8c6e27Sflorian #endif 75d500c338Sflorian #ifdef HAVE_LINUX_NET_TSTAMP_H 76d500c338Sflorian #include <linux/net_tstamp.h> 77d500c338Sflorian #endif 78ae8c6e27Sflorian /* -------- Start of local definitions -------- */ 79ae8c6e27Sflorian /** if CMSG_ALIGN is not defined on this platform, a workaround */ 80ae8c6e27Sflorian #ifndef CMSG_ALIGN 81ae8c6e27Sflorian # ifdef __CMSG_ALIGN 82ae8c6e27Sflorian # define CMSG_ALIGN(n) __CMSG_ALIGN(n) 83ae8c6e27Sflorian # elif defined(CMSG_DATA_ALIGN) 84ae8c6e27Sflorian # define CMSG_ALIGN _CMSG_DATA_ALIGN 85ae8c6e27Sflorian # else 86ae8c6e27Sflorian # define CMSG_ALIGN(len) (((len)+sizeof(long)-1) & ~(sizeof(long)-1)) 87ae8c6e27Sflorian # endif 88ae8c6e27Sflorian #endif 89ae8c6e27Sflorian 90ae8c6e27Sflorian /** if CMSG_LEN is not defined on this platform, a workaround */ 91ae8c6e27Sflorian #ifndef CMSG_LEN 92ae8c6e27Sflorian # define CMSG_LEN(len) (CMSG_ALIGN(sizeof(struct cmsghdr))+(len)) 93ae8c6e27Sflorian #endif 94ae8c6e27Sflorian 95ae8c6e27Sflorian /** if CMSG_SPACE is not defined on this platform, a workaround */ 96ae8c6e27Sflorian #ifndef CMSG_SPACE 97ae8c6e27Sflorian # ifdef _CMSG_HDR_ALIGN 98ae8c6e27Sflorian # define CMSG_SPACE(l) (CMSG_ALIGN(l)+_CMSG_HDR_ALIGN(sizeof(struct cmsghdr))) 99ae8c6e27Sflorian # else 100ae8c6e27Sflorian # define CMSG_SPACE(l) (CMSG_ALIGN(l)+CMSG_ALIGN(sizeof(struct cmsghdr))) 101ae8c6e27Sflorian # endif 102ae8c6e27Sflorian #endif 103ae8c6e27Sflorian 104ae8c6e27Sflorian /** The TCP writing query timeout in milliseconds */ 105ae8c6e27Sflorian #define TCP_QUERY_TIMEOUT 120000 106ae8c6e27Sflorian /** The minimum actual TCP timeout to use, regardless of what we advertise, 107ae8c6e27Sflorian * in msec */ 108ae8c6e27Sflorian #define TCP_QUERY_TIMEOUT_MINIMUM 200 109ae8c6e27Sflorian 110ae8c6e27Sflorian #ifndef NONBLOCKING_IS_BROKEN 111ae8c6e27Sflorian /** number of UDP reads to perform per read indication from select */ 112ae8c6e27Sflorian #define NUM_UDP_PER_SELECT 100 113ae8c6e27Sflorian #else 114ae8c6e27Sflorian #define NUM_UDP_PER_SELECT 1 115ae8c6e27Sflorian #endif 116ae8c6e27Sflorian 1175c45b740Sflorian /** timeout in millisec to wait for write to unblock, packets dropped after.*/ 1185c45b740Sflorian #define SEND_BLOCKED_WAIT_TIMEOUT 200 119cece5eebSflorian /** max number of times to wait for write to unblock, packets dropped after.*/ 120cece5eebSflorian #define SEND_BLOCKED_MAX_RETRY 5 1215c45b740Sflorian 122d500c338Sflorian /** Let's make timestamping code cleaner and redefine SO_TIMESTAMP* */ 123d500c338Sflorian #ifndef SO_TIMESTAMP 124d500c338Sflorian #define SO_TIMESTAMP 29 125d500c338Sflorian #endif 126d500c338Sflorian #ifndef SO_TIMESTAMPNS 127d500c338Sflorian #define SO_TIMESTAMPNS 35 128d500c338Sflorian #endif 129d500c338Sflorian #ifndef SO_TIMESTAMPING 130d500c338Sflorian #define SO_TIMESTAMPING 37 131d500c338Sflorian #endif 132ae8c6e27Sflorian /** 133ae8c6e27Sflorian * The internal event structure for keeping ub_event info for the event. 134ae8c6e27Sflorian * Possibly other structures (list, tree) this is part of. 135ae8c6e27Sflorian */ 136ae8c6e27Sflorian struct internal_event { 137ae8c6e27Sflorian /** the comm base */ 138ae8c6e27Sflorian struct comm_base* base; 139ae8c6e27Sflorian /** ub_event event type */ 140ae8c6e27Sflorian struct ub_event* ev; 141ae8c6e27Sflorian }; 142ae8c6e27Sflorian 143ae8c6e27Sflorian /** 144ae8c6e27Sflorian * Internal base structure, so that every thread has its own events. 145ae8c6e27Sflorian */ 146ae8c6e27Sflorian struct internal_base { 147ae8c6e27Sflorian /** ub_event event_base type. */ 148ae8c6e27Sflorian struct ub_event_base* base; 149ae8c6e27Sflorian /** seconds time pointer points here */ 150ae8c6e27Sflorian time_t secs; 151ae8c6e27Sflorian /** timeval with current time */ 152ae8c6e27Sflorian struct timeval now; 153ae8c6e27Sflorian /** the event used for slow_accept timeouts */ 154ae8c6e27Sflorian struct ub_event* slow_accept; 155ae8c6e27Sflorian /** true if slow_accept is enabled */ 156ae8c6e27Sflorian int slow_accept_enabled; 1575c45b740Sflorian /** last log time for slow logging of file descriptor errors */ 1585c45b740Sflorian time_t last_slow_log; 1595c45b740Sflorian /** last log time for slow logging of write wait failures */ 1605c45b740Sflorian time_t last_writewait_log; 161ae8c6e27Sflorian }; 162ae8c6e27Sflorian 163ae8c6e27Sflorian /** 164ae8c6e27Sflorian * Internal timer structure, to store timer event in. 165ae8c6e27Sflorian */ 166ae8c6e27Sflorian struct internal_timer { 167ae8c6e27Sflorian /** the super struct from which derived */ 168ae8c6e27Sflorian struct comm_timer super; 169ae8c6e27Sflorian /** the comm base */ 170ae8c6e27Sflorian struct comm_base* base; 171ae8c6e27Sflorian /** ub_event event type */ 172ae8c6e27Sflorian struct ub_event* ev; 173ae8c6e27Sflorian /** is timer enabled */ 174ae8c6e27Sflorian uint8_t enabled; 175ae8c6e27Sflorian }; 176ae8c6e27Sflorian 177ae8c6e27Sflorian /** 178ae8c6e27Sflorian * Internal signal structure, to store signal event in. 179ae8c6e27Sflorian */ 180ae8c6e27Sflorian struct internal_signal { 181ae8c6e27Sflorian /** ub_event event type */ 182ae8c6e27Sflorian struct ub_event* ev; 183ae8c6e27Sflorian /** next in signal list */ 184ae8c6e27Sflorian struct internal_signal* next; 185ae8c6e27Sflorian }; 186ae8c6e27Sflorian 187ae8c6e27Sflorian /** create a tcp handler with a parent */ 188ae8c6e27Sflorian static struct comm_point* comm_point_create_tcp_handler( 189ae8c6e27Sflorian struct comm_base *base, struct comm_point* parent, size_t bufsize, 190e97c6e54Ssthen struct sldns_buffer* spoolbuf, comm_point_callback_type* callback, 191411c5950Sflorian void* callback_arg, struct unbound_socket* socket); 192ae8c6e27Sflorian 193ae8c6e27Sflorian /* -------- End of local definitions -------- */ 194ae8c6e27Sflorian 195ae8c6e27Sflorian struct comm_base* 196ae8c6e27Sflorian comm_base_create(int sigs) 197ae8c6e27Sflorian { 198ae8c6e27Sflorian struct comm_base* b = (struct comm_base*)calloc(1, 199ae8c6e27Sflorian sizeof(struct comm_base)); 200ae8c6e27Sflorian const char *evnm="event", *evsys="", *evmethod=""; 201ae8c6e27Sflorian 202ae8c6e27Sflorian if(!b) 203ae8c6e27Sflorian return NULL; 204ae8c6e27Sflorian b->eb = (struct internal_base*)calloc(1, sizeof(struct internal_base)); 205ae8c6e27Sflorian if(!b->eb) { 206ae8c6e27Sflorian free(b); 207ae8c6e27Sflorian return NULL; 208ae8c6e27Sflorian } 209ae8c6e27Sflorian b->eb->base = ub_default_event_base(sigs, &b->eb->secs, &b->eb->now); 210ae8c6e27Sflorian if(!b->eb->base) { 211ae8c6e27Sflorian free(b->eb); 212ae8c6e27Sflorian free(b); 213ae8c6e27Sflorian return NULL; 214ae8c6e27Sflorian } 215ae8c6e27Sflorian ub_comm_base_now(b); 216ae8c6e27Sflorian ub_get_event_sys(b->eb->base, &evnm, &evsys, &evmethod); 2179b465e50Sflorian verbose(VERB_ALGO, "%s %s uses %s method.", evnm, evsys, evmethod); 218ae8c6e27Sflorian return b; 219ae8c6e27Sflorian } 220ae8c6e27Sflorian 221ae8c6e27Sflorian struct comm_base* 222ae8c6e27Sflorian comm_base_create_event(struct ub_event_base* base) 223ae8c6e27Sflorian { 224ae8c6e27Sflorian struct comm_base* b = (struct comm_base*)calloc(1, 225ae8c6e27Sflorian sizeof(struct comm_base)); 226ae8c6e27Sflorian if(!b) 227ae8c6e27Sflorian return NULL; 228ae8c6e27Sflorian b->eb = (struct internal_base*)calloc(1, sizeof(struct internal_base)); 229ae8c6e27Sflorian if(!b->eb) { 230ae8c6e27Sflorian free(b); 231ae8c6e27Sflorian return NULL; 232ae8c6e27Sflorian } 233ae8c6e27Sflorian b->eb->base = base; 234ae8c6e27Sflorian ub_comm_base_now(b); 235ae8c6e27Sflorian return b; 236ae8c6e27Sflorian } 237ae8c6e27Sflorian 238ae8c6e27Sflorian void 239ae8c6e27Sflorian comm_base_delete(struct comm_base* b) 240ae8c6e27Sflorian { 241ae8c6e27Sflorian if(!b) 242ae8c6e27Sflorian return; 243ae8c6e27Sflorian if(b->eb->slow_accept_enabled) { 244ae8c6e27Sflorian if(ub_event_del(b->eb->slow_accept) != 0) { 245ae8c6e27Sflorian log_err("could not event_del slow_accept"); 246ae8c6e27Sflorian } 247ae8c6e27Sflorian ub_event_free(b->eb->slow_accept); 248ae8c6e27Sflorian } 249ae8c6e27Sflorian ub_event_base_free(b->eb->base); 250ae8c6e27Sflorian b->eb->base = NULL; 251ae8c6e27Sflorian free(b->eb); 252ae8c6e27Sflorian free(b); 253ae8c6e27Sflorian } 254ae8c6e27Sflorian 255ae8c6e27Sflorian void 256ae8c6e27Sflorian comm_base_delete_no_base(struct comm_base* b) 257ae8c6e27Sflorian { 258ae8c6e27Sflorian if(!b) 259ae8c6e27Sflorian return; 260ae8c6e27Sflorian if(b->eb->slow_accept_enabled) { 261ae8c6e27Sflorian if(ub_event_del(b->eb->slow_accept) != 0) { 262ae8c6e27Sflorian log_err("could not event_del slow_accept"); 263ae8c6e27Sflorian } 264ae8c6e27Sflorian ub_event_free(b->eb->slow_accept); 265ae8c6e27Sflorian } 266ae8c6e27Sflorian b->eb->base = NULL; 267ae8c6e27Sflorian free(b->eb); 268ae8c6e27Sflorian free(b); 269ae8c6e27Sflorian } 270ae8c6e27Sflorian 271ae8c6e27Sflorian void 272ae8c6e27Sflorian comm_base_timept(struct comm_base* b, time_t** tt, struct timeval** tv) 273ae8c6e27Sflorian { 274ae8c6e27Sflorian *tt = &b->eb->secs; 275ae8c6e27Sflorian *tv = &b->eb->now; 276ae8c6e27Sflorian } 277ae8c6e27Sflorian 278ae8c6e27Sflorian void 279ae8c6e27Sflorian comm_base_dispatch(struct comm_base* b) 280ae8c6e27Sflorian { 281ae8c6e27Sflorian int retval; 282ae8c6e27Sflorian retval = ub_event_base_dispatch(b->eb->base); 283ae8c6e27Sflorian if(retval < 0) { 284ae8c6e27Sflorian fatal_exit("event_dispatch returned error %d, " 285ae8c6e27Sflorian "errno is %s", retval, strerror(errno)); 286ae8c6e27Sflorian } 287ae8c6e27Sflorian } 288ae8c6e27Sflorian 289ae8c6e27Sflorian void comm_base_exit(struct comm_base* b) 290ae8c6e27Sflorian { 291ae8c6e27Sflorian if(ub_event_base_loopexit(b->eb->base) != 0) { 292ae8c6e27Sflorian log_err("Could not loopexit"); 293ae8c6e27Sflorian } 294ae8c6e27Sflorian } 295ae8c6e27Sflorian 296ae8c6e27Sflorian void comm_base_set_slow_accept_handlers(struct comm_base* b, 297ae8c6e27Sflorian void (*stop_acc)(void*), void (*start_acc)(void*), void* arg) 298ae8c6e27Sflorian { 299ae8c6e27Sflorian b->stop_accept = stop_acc; 300ae8c6e27Sflorian b->start_accept = start_acc; 301ae8c6e27Sflorian b->cb_arg = arg; 302ae8c6e27Sflorian } 303ae8c6e27Sflorian 304ae8c6e27Sflorian struct ub_event_base* comm_base_internal(struct comm_base* b) 305ae8c6e27Sflorian { 306ae8c6e27Sflorian return b->eb->base; 307ae8c6e27Sflorian } 308ae8c6e27Sflorian 309ae8c6e27Sflorian /** see if errno for udp has to be logged or not uses globals */ 310ae8c6e27Sflorian static int 311ae8c6e27Sflorian udp_send_errno_needs_log(struct sockaddr* addr, socklen_t addrlen) 312ae8c6e27Sflorian { 313ae8c6e27Sflorian /* do not log transient errors (unless high verbosity) */ 314ae8c6e27Sflorian #if defined(ENETUNREACH) || defined(EHOSTDOWN) || defined(EHOSTUNREACH) || defined(ENETDOWN) 315ae8c6e27Sflorian switch(errno) { 316ae8c6e27Sflorian # ifdef ENETUNREACH 317ae8c6e27Sflorian case ENETUNREACH: 318ae8c6e27Sflorian # endif 319ae8c6e27Sflorian # ifdef EHOSTDOWN 320ae8c6e27Sflorian case EHOSTDOWN: 321ae8c6e27Sflorian # endif 322ae8c6e27Sflorian # ifdef EHOSTUNREACH 323ae8c6e27Sflorian case EHOSTUNREACH: 324ae8c6e27Sflorian # endif 325ae8c6e27Sflorian # ifdef ENETDOWN 326ae8c6e27Sflorian case ENETDOWN: 327ae8c6e27Sflorian # endif 328411c5950Sflorian case EPERM: 329a1a7ba80Sflorian case EACCES: 330ae8c6e27Sflorian if(verbosity < VERB_ALGO) 331ae8c6e27Sflorian return 0; 332*7037e34cSflorian break; 333ae8c6e27Sflorian default: 334ae8c6e27Sflorian break; 335ae8c6e27Sflorian } 336ae8c6e27Sflorian #endif 337ae8c6e27Sflorian /* permission denied is gotten for every send if the 338ae8c6e27Sflorian * network is disconnected (on some OS), squelch it */ 339ae8c6e27Sflorian if( ((errno == EPERM) 340ae8c6e27Sflorian # ifdef EADDRNOTAVAIL 341ae8c6e27Sflorian /* 'Cannot assign requested address' also when disconnected */ 342ae8c6e27Sflorian || (errno == EADDRNOTAVAIL) 343ae8c6e27Sflorian # endif 344411c5950Sflorian ) && verbosity < VERB_ALGO) 345ae8c6e27Sflorian return 0; 346ae8c6e27Sflorian # ifdef EADDRINUSE 347ae8c6e27Sflorian /* If SO_REUSEADDR is set, we could try to connect to the same server 348ae8c6e27Sflorian * from the same source port twice. */ 349ae8c6e27Sflorian if(errno == EADDRINUSE && verbosity < VERB_DETAIL) 350ae8c6e27Sflorian return 0; 351ae8c6e27Sflorian # endif 352ae8c6e27Sflorian /* squelch errors where people deploy AAAA ::ffff:bla for 353ae8c6e27Sflorian * authority servers, which we try for intranets. */ 354ae8c6e27Sflorian if(errno == EINVAL && addr_is_ip4mapped( 355ae8c6e27Sflorian (struct sockaddr_storage*)addr, addrlen) && 356ae8c6e27Sflorian verbosity < VERB_DETAIL) 357ae8c6e27Sflorian return 0; 358ae8c6e27Sflorian /* SO_BROADCAST sockopt can give access to 255.255.255.255, 359ae8c6e27Sflorian * but a dns cache does not need it. */ 360ae8c6e27Sflorian if(errno == EACCES && addr_is_broadcast( 361ae8c6e27Sflorian (struct sockaddr_storage*)addr, addrlen) && 362ae8c6e27Sflorian verbosity < VERB_DETAIL) 363ae8c6e27Sflorian return 0; 364ae8c6e27Sflorian return 1; 365ae8c6e27Sflorian } 366ae8c6e27Sflorian 367ae8c6e27Sflorian int tcp_connect_errno_needs_log(struct sockaddr* addr, socklen_t addrlen) 368ae8c6e27Sflorian { 369ae8c6e27Sflorian return udp_send_errno_needs_log(addr, addrlen); 370ae8c6e27Sflorian } 371ae8c6e27Sflorian 372ae8c6e27Sflorian /* send a UDP reply */ 373ae8c6e27Sflorian int 374ae8c6e27Sflorian comm_point_send_udp_msg(struct comm_point *c, sldns_buffer* packet, 375a8eaceedSflorian struct sockaddr* addr, socklen_t addrlen, int is_connected) 376ae8c6e27Sflorian { 377ae8c6e27Sflorian ssize_t sent; 378ae8c6e27Sflorian log_assert(c->fd != -1); 379ae8c6e27Sflorian #ifdef UNBOUND_DEBUG 380ae8c6e27Sflorian if(sldns_buffer_remaining(packet) == 0) 381ae8c6e27Sflorian log_err("error: send empty UDP packet"); 382ae8c6e27Sflorian #endif 383ae8c6e27Sflorian log_assert(addr && addrlen > 0); 384a8eaceedSflorian if(!is_connected) { 385ae8c6e27Sflorian sent = sendto(c->fd, (void*)sldns_buffer_begin(packet), 386ae8c6e27Sflorian sldns_buffer_remaining(packet), 0, 387ae8c6e27Sflorian addr, addrlen); 388853e076fSflorian } else { 389853e076fSflorian sent = send(c->fd, (void*)sldns_buffer_begin(packet), 390853e076fSflorian sldns_buffer_remaining(packet), 0); 391853e076fSflorian } 392ae8c6e27Sflorian if(sent == -1) { 393ae8c6e27Sflorian /* try again and block, waiting for IO to complete, 394ae8c6e27Sflorian * we want to send the answer, and we will wait for 395ae8c6e27Sflorian * the ethernet interface buffer to have space. */ 396ae8c6e27Sflorian #ifndef USE_WINSOCK 3975c45b740Sflorian if(errno == EAGAIN || errno == EINTR || 398ae8c6e27Sflorian # ifdef EWOULDBLOCK 399ae8c6e27Sflorian errno == EWOULDBLOCK || 400ae8c6e27Sflorian # endif 401ae8c6e27Sflorian errno == ENOBUFS) { 402ae8c6e27Sflorian #else 403ae8c6e27Sflorian if(WSAGetLastError() == WSAEINPROGRESS || 4045c45b740Sflorian WSAGetLastError() == WSAEINTR || 405ae8c6e27Sflorian WSAGetLastError() == WSAENOBUFS || 406ae8c6e27Sflorian WSAGetLastError() == WSAEWOULDBLOCK) { 407ae8c6e27Sflorian #endif 408cece5eebSflorian int retries = 0; 4095c45b740Sflorian /* if we set the fd blocking, other threads suddenly 4105c45b740Sflorian * have a blocking fd that they operate on */ 411cece5eebSflorian while(sent == -1 && retries < SEND_BLOCKED_MAX_RETRY && ( 4125c45b740Sflorian #ifndef USE_WINSOCK 4135c45b740Sflorian errno == EAGAIN || errno == EINTR || 4145c45b740Sflorian # ifdef EWOULDBLOCK 4155c45b740Sflorian errno == EWOULDBLOCK || 4165c45b740Sflorian # endif 4175c45b740Sflorian errno == ENOBUFS 4185c45b740Sflorian #else 4195c45b740Sflorian WSAGetLastError() == WSAEINPROGRESS || 4205c45b740Sflorian WSAGetLastError() == WSAEINTR || 4215c45b740Sflorian WSAGetLastError() == WSAENOBUFS || 4225c45b740Sflorian WSAGetLastError() == WSAEWOULDBLOCK 4235c45b740Sflorian #endif 4245c45b740Sflorian )) { 4255c45b740Sflorian #if defined(HAVE_POLL) || defined(USE_WINSOCK) 426cece5eebSflorian int send_nobufs = ( 427cece5eebSflorian #ifndef USE_WINSOCK 428cece5eebSflorian errno == ENOBUFS 429cece5eebSflorian #else 430cece5eebSflorian WSAGetLastError() == WSAENOBUFS 431cece5eebSflorian #endif 432cece5eebSflorian ); 4335c45b740Sflorian struct pollfd p; 4345c45b740Sflorian int pret; 4355c45b740Sflorian memset(&p, 0, sizeof(p)); 4365c45b740Sflorian p.fd = c->fd; 4375c45b740Sflorian p.events = POLLOUT | POLLERR | POLLHUP; 4385c45b740Sflorian # ifndef USE_WINSOCK 4395c45b740Sflorian pret = poll(&p, 1, SEND_BLOCKED_WAIT_TIMEOUT); 4405c45b740Sflorian # else 4415c45b740Sflorian pret = WSAPoll(&p, 1, 4425c45b740Sflorian SEND_BLOCKED_WAIT_TIMEOUT); 4435c45b740Sflorian # endif 4445c45b740Sflorian if(pret == 0) { 4455c45b740Sflorian /* timer expired */ 4465c45b740Sflorian struct comm_base* b = c->ev->base; 4475c45b740Sflorian if(b->eb->last_writewait_log+SLOW_LOG_TIME <= 4485c45b740Sflorian b->eb->secs) { 4495c45b740Sflorian b->eb->last_writewait_log = b->eb->secs; 4505c45b740Sflorian verbose(VERB_OPS, "send udp blocked " 4515c45b740Sflorian "for long, dropping packet."); 4525c45b740Sflorian } 4535c45b740Sflorian return 0; 4545c45b740Sflorian } else if(pret < 0 && 4555c45b740Sflorian #ifndef USE_WINSOCK 4565c45b740Sflorian errno != EAGAIN && errno != EINTR && 4575c45b740Sflorian # ifdef EWOULDBLOCK 4585c45b740Sflorian errno != EWOULDBLOCK && 4595c45b740Sflorian # endif 4605c45b740Sflorian errno != ENOBUFS 4615c45b740Sflorian #else 4625c45b740Sflorian WSAGetLastError() != WSAEINPROGRESS && 4635c45b740Sflorian WSAGetLastError() != WSAEINTR && 4645c45b740Sflorian WSAGetLastError() != WSAENOBUFS && 4655c45b740Sflorian WSAGetLastError() != WSAEWOULDBLOCK 4665c45b740Sflorian #endif 4675c45b740Sflorian ) { 4685c45b740Sflorian log_err("poll udp out failed: %s", 4695c45b740Sflorian sock_strerror(errno)); 4705c45b740Sflorian return 0; 471cece5eebSflorian } else if((pret < 0 && 472cece5eebSflorian #ifndef USE_WINSOCK 473cece5eebSflorian errno == ENOBUFS 474cece5eebSflorian #else 475cece5eebSflorian WSAGetLastError() == WSAENOBUFS 476cece5eebSflorian #endif 477cece5eebSflorian ) || (send_nobufs && retries > 0)) { 478cece5eebSflorian /* ENOBUFS, and poll returned without 479cece5eebSflorian * a timeout. Or the retried send call 480cece5eebSflorian * returned ENOBUFS. It is good to 481cece5eebSflorian * wait a bit for the error to clear. */ 482cece5eebSflorian /* The timeout is 20*(2^(retries+1)), 483cece5eebSflorian * it increases exponentially, starting 484cece5eebSflorian * at 40 msec. After 5 tries, 1240 msec 485cece5eebSflorian * have passed in total, when poll 486cece5eebSflorian * returned the error, and 1200 msec 487cece5eebSflorian * when send returned the errors. */ 488cece5eebSflorian #ifndef USE_WINSOCK 489cece5eebSflorian pret = poll(NULL, 0, (SEND_BLOCKED_WAIT_TIMEOUT/10)<<(retries+1)); 490cece5eebSflorian #else 491cece5eebSflorian pret = WSAPoll(NULL, 0, (SEND_BLOCKED_WAIT_TIMEOUT/10)<<(retries+1)); 492cece5eebSflorian #endif 493cece5eebSflorian if(pret < 0 && 494cece5eebSflorian #ifndef USE_WINSOCK 495cece5eebSflorian errno != EAGAIN && errno != EINTR && 496cece5eebSflorian # ifdef EWOULDBLOCK 497cece5eebSflorian errno != EWOULDBLOCK && 498cece5eebSflorian # endif 499cece5eebSflorian errno != ENOBUFS 500cece5eebSflorian #else 501cece5eebSflorian WSAGetLastError() != WSAEINPROGRESS && 502cece5eebSflorian WSAGetLastError() != WSAEINTR && 503cece5eebSflorian WSAGetLastError() != WSAENOBUFS && 504cece5eebSflorian WSAGetLastError() != WSAEWOULDBLOCK 505cece5eebSflorian #endif 506cece5eebSflorian ) { 507cece5eebSflorian log_err("poll udp out timer failed: %s", 508cece5eebSflorian sock_strerror(errno)); 509cece5eebSflorian } 5105c45b740Sflorian } 5115c45b740Sflorian #endif /* defined(HAVE_POLL) || defined(USE_WINSOCK) */ 512cece5eebSflorian retries++; 513a8eaceedSflorian if (!is_connected) { 514ae8c6e27Sflorian sent = sendto(c->fd, (void*)sldns_buffer_begin(packet), 515ae8c6e27Sflorian sldns_buffer_remaining(packet), 0, 516ae8c6e27Sflorian addr, addrlen); 517a8eaceedSflorian } else { 518a8eaceedSflorian sent = send(c->fd, (void*)sldns_buffer_begin(packet), 519a8eaceedSflorian sldns_buffer_remaining(packet), 0); 520a8eaceedSflorian } 5215c45b740Sflorian } 522ae8c6e27Sflorian } 523ae8c6e27Sflorian } 524ae8c6e27Sflorian if(sent == -1) { 525ae8c6e27Sflorian if(!udp_send_errno_needs_log(addr, addrlen)) 526ae8c6e27Sflorian return 0; 527a8eaceedSflorian if (!is_connected) { 528f4f0f0ceSflorian verbose(VERB_OPS, "sendto failed: %s", sock_strerror(errno)); 529a8eaceedSflorian } else { 530a8eaceedSflorian verbose(VERB_OPS, "send failed: %s", sock_strerror(errno)); 531a8eaceedSflorian } 532523cba49Santon if(addr) 533ae8c6e27Sflorian log_addr(VERB_OPS, "remote address is", 534ae8c6e27Sflorian (struct sockaddr_storage*)addr, addrlen); 535ae8c6e27Sflorian return 0; 536ae8c6e27Sflorian } else if((size_t)sent != sldns_buffer_remaining(packet)) { 537ae8c6e27Sflorian log_err("sent %d in place of %d bytes", 538ae8c6e27Sflorian (int)sent, (int)sldns_buffer_remaining(packet)); 539ae8c6e27Sflorian return 0; 540ae8c6e27Sflorian } 541ae8c6e27Sflorian return 1; 542ae8c6e27Sflorian } 543ae8c6e27Sflorian 544ae8c6e27Sflorian #if defined(AF_INET6) && defined(IPV6_PKTINFO) && (defined(HAVE_RECVMSG) || defined(HAVE_SENDMSG)) 545ae8c6e27Sflorian /** print debug ancillary info */ 546ae8c6e27Sflorian static void p_ancil(const char* str, struct comm_reply* r) 547ae8c6e27Sflorian { 548ae8c6e27Sflorian if(r->srctype != 4 && r->srctype != 6) { 549ae8c6e27Sflorian log_info("%s: unknown srctype %d", str, r->srctype); 550ae8c6e27Sflorian return; 551ae8c6e27Sflorian } 552411c5950Sflorian 553ae8c6e27Sflorian if(r->srctype == 6) { 554411c5950Sflorian #ifdef IPV6_PKTINFO 555ae8c6e27Sflorian char buf[1024]; 556ae8c6e27Sflorian if(inet_ntop(AF_INET6, &r->pktinfo.v6info.ipi6_addr, 557ae8c6e27Sflorian buf, (socklen_t)sizeof(buf)) == 0) { 558ae8c6e27Sflorian (void)strlcpy(buf, "(inet_ntop error)", sizeof(buf)); 559ae8c6e27Sflorian } 560ae8c6e27Sflorian buf[sizeof(buf)-1]=0; 561ae8c6e27Sflorian log_info("%s: %s %d", str, buf, r->pktinfo.v6info.ipi6_ifindex); 562411c5950Sflorian #endif 563ae8c6e27Sflorian } else if(r->srctype == 4) { 564ae8c6e27Sflorian #ifdef IP_PKTINFO 565ae8c6e27Sflorian char buf1[1024], buf2[1024]; 566ae8c6e27Sflorian if(inet_ntop(AF_INET, &r->pktinfo.v4info.ipi_addr, 567ae8c6e27Sflorian buf1, (socklen_t)sizeof(buf1)) == 0) { 568ae8c6e27Sflorian (void)strlcpy(buf1, "(inet_ntop error)", sizeof(buf1)); 569ae8c6e27Sflorian } 570ae8c6e27Sflorian buf1[sizeof(buf1)-1]=0; 571ae8c6e27Sflorian #ifdef HAVE_STRUCT_IN_PKTINFO_IPI_SPEC_DST 572ae8c6e27Sflorian if(inet_ntop(AF_INET, &r->pktinfo.v4info.ipi_spec_dst, 573ae8c6e27Sflorian buf2, (socklen_t)sizeof(buf2)) == 0) { 574ae8c6e27Sflorian (void)strlcpy(buf2, "(inet_ntop error)", sizeof(buf2)); 575ae8c6e27Sflorian } 576ae8c6e27Sflorian buf2[sizeof(buf2)-1]=0; 577ae8c6e27Sflorian #else 578ae8c6e27Sflorian buf2[0]=0; 579ae8c6e27Sflorian #endif 580ae8c6e27Sflorian log_info("%s: %d %s %s", str, r->pktinfo.v4info.ipi_ifindex, 581ae8c6e27Sflorian buf1, buf2); 582ae8c6e27Sflorian #elif defined(IP_RECVDSTADDR) 583ae8c6e27Sflorian char buf1[1024]; 584ae8c6e27Sflorian if(inet_ntop(AF_INET, &r->pktinfo.v4addr, 585ae8c6e27Sflorian buf1, (socklen_t)sizeof(buf1)) == 0) { 586ae8c6e27Sflorian (void)strlcpy(buf1, "(inet_ntop error)", sizeof(buf1)); 587ae8c6e27Sflorian } 588ae8c6e27Sflorian buf1[sizeof(buf1)-1]=0; 589ae8c6e27Sflorian log_info("%s: %s", str, buf1); 590ae8c6e27Sflorian #endif /* IP_PKTINFO or PI_RECVDSTDADDR */ 591ae8c6e27Sflorian } 592ae8c6e27Sflorian } 593ae8c6e27Sflorian #endif /* AF_INET6 && IPV6_PKTINFO && HAVE_RECVMSG||HAVE_SENDMSG */ 594ae8c6e27Sflorian 595ae8c6e27Sflorian /** send a UDP reply over specified interface*/ 596ae8c6e27Sflorian static int 597ae8c6e27Sflorian comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet, 598ae8c6e27Sflorian struct sockaddr* addr, socklen_t addrlen, struct comm_reply* r) 599ae8c6e27Sflorian { 600ae8c6e27Sflorian #if defined(AF_INET6) && defined(IPV6_PKTINFO) && defined(HAVE_SENDMSG) 601ae8c6e27Sflorian ssize_t sent; 602ae8c6e27Sflorian struct msghdr msg; 603ae8c6e27Sflorian struct iovec iov[1]; 6043d4dbd37Sjca union { 6053d4dbd37Sjca struct cmsghdr hdr; 6063d4dbd37Sjca char buf[256]; 6073d4dbd37Sjca } control; 608ae8c6e27Sflorian #ifndef S_SPLINT_S 609ae8c6e27Sflorian struct cmsghdr *cmsg; 610ae8c6e27Sflorian #endif /* S_SPLINT_S */ 611ae8c6e27Sflorian 612ae8c6e27Sflorian log_assert(c->fd != -1); 613ae8c6e27Sflorian #ifdef UNBOUND_DEBUG 614ae8c6e27Sflorian if(sldns_buffer_remaining(packet) == 0) 615ae8c6e27Sflorian log_err("error: send empty UDP packet"); 616ae8c6e27Sflorian #endif 617ae8c6e27Sflorian log_assert(addr && addrlen > 0); 618ae8c6e27Sflorian 619ae8c6e27Sflorian msg.msg_name = addr; 620ae8c6e27Sflorian msg.msg_namelen = addrlen; 621ae8c6e27Sflorian iov[0].iov_base = sldns_buffer_begin(packet); 622ae8c6e27Sflorian iov[0].iov_len = sldns_buffer_remaining(packet); 623ae8c6e27Sflorian msg.msg_iov = iov; 624ae8c6e27Sflorian msg.msg_iovlen = 1; 6253d4dbd37Sjca msg.msg_control = control.buf; 626ae8c6e27Sflorian #ifndef S_SPLINT_S 627e47fef9eSflorian msg.msg_controllen = sizeof(control.buf); 628ae8c6e27Sflorian #endif /* S_SPLINT_S */ 629ae8c6e27Sflorian msg.msg_flags = 0; 630ae8c6e27Sflorian 631ae8c6e27Sflorian #ifndef S_SPLINT_S 632ae8c6e27Sflorian cmsg = CMSG_FIRSTHDR(&msg); 633ae8c6e27Sflorian if(r->srctype == 4) { 634ae8c6e27Sflorian #ifdef IP_PKTINFO 635ae8c6e27Sflorian void* cmsg_data; 636ae8c6e27Sflorian msg.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo)); 637e47fef9eSflorian log_assert(msg.msg_controllen <= sizeof(control.buf)); 638ae8c6e27Sflorian cmsg->cmsg_level = IPPROTO_IP; 639ae8c6e27Sflorian cmsg->cmsg_type = IP_PKTINFO; 640ae8c6e27Sflorian memmove(CMSG_DATA(cmsg), &r->pktinfo.v4info, 641ae8c6e27Sflorian sizeof(struct in_pktinfo)); 642ae8c6e27Sflorian /* unset the ifindex to not bypass the routing tables */ 643ae8c6e27Sflorian cmsg_data = CMSG_DATA(cmsg); 644ae8c6e27Sflorian ((struct in_pktinfo *) cmsg_data)->ipi_ifindex = 0; 645ae8c6e27Sflorian cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); 646d500c338Sflorian /* zero the padding bytes inserted by the CMSG_LEN */ 647d500c338Sflorian if(sizeof(struct in_pktinfo) < cmsg->cmsg_len) 648d500c338Sflorian memset(((uint8_t*)(CMSG_DATA(cmsg))) + 649d500c338Sflorian sizeof(struct in_pktinfo), 0, cmsg->cmsg_len 650d500c338Sflorian - sizeof(struct in_pktinfo)); 651ae8c6e27Sflorian #elif defined(IP_SENDSRCADDR) 652ae8c6e27Sflorian msg.msg_controllen = CMSG_SPACE(sizeof(struct in_addr)); 653e47fef9eSflorian log_assert(msg.msg_controllen <= sizeof(control.buf)); 654ae8c6e27Sflorian cmsg->cmsg_level = IPPROTO_IP; 655ae8c6e27Sflorian cmsg->cmsg_type = IP_SENDSRCADDR; 656ae8c6e27Sflorian memmove(CMSG_DATA(cmsg), &r->pktinfo.v4addr, 657ae8c6e27Sflorian sizeof(struct in_addr)); 658ae8c6e27Sflorian cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr)); 659d500c338Sflorian /* zero the padding bytes inserted by the CMSG_LEN */ 660d500c338Sflorian if(sizeof(struct in_addr) < cmsg->cmsg_len) 661d500c338Sflorian memset(((uint8_t*)(CMSG_DATA(cmsg))) + 662d500c338Sflorian sizeof(struct in_addr), 0, cmsg->cmsg_len 663d500c338Sflorian - sizeof(struct in_addr)); 664ae8c6e27Sflorian #else 665ae8c6e27Sflorian verbose(VERB_ALGO, "no IP_PKTINFO or IP_SENDSRCADDR"); 666ae8c6e27Sflorian msg.msg_control = NULL; 667ae8c6e27Sflorian #endif /* IP_PKTINFO or IP_SENDSRCADDR */ 668ae8c6e27Sflorian } else if(r->srctype == 6) { 669ae8c6e27Sflorian void* cmsg_data; 670ae8c6e27Sflorian msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); 671e47fef9eSflorian log_assert(msg.msg_controllen <= sizeof(control.buf)); 672ae8c6e27Sflorian cmsg->cmsg_level = IPPROTO_IPV6; 673ae8c6e27Sflorian cmsg->cmsg_type = IPV6_PKTINFO; 674ae8c6e27Sflorian memmove(CMSG_DATA(cmsg), &r->pktinfo.v6info, 675ae8c6e27Sflorian sizeof(struct in6_pktinfo)); 676ae8c6e27Sflorian /* unset the ifindex to not bypass the routing tables */ 677ae8c6e27Sflorian cmsg_data = CMSG_DATA(cmsg); 678ae8c6e27Sflorian ((struct in6_pktinfo *) cmsg_data)->ipi6_ifindex = 0; 679ae8c6e27Sflorian cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 680d500c338Sflorian /* zero the padding bytes inserted by the CMSG_LEN */ 681d500c338Sflorian if(sizeof(struct in6_pktinfo) < cmsg->cmsg_len) 682d500c338Sflorian memset(((uint8_t*)(CMSG_DATA(cmsg))) + 683d500c338Sflorian sizeof(struct in6_pktinfo), 0, cmsg->cmsg_len 684d500c338Sflorian - sizeof(struct in6_pktinfo)); 685ae8c6e27Sflorian } else { 686ae8c6e27Sflorian /* try to pass all 0 to use default route */ 687ae8c6e27Sflorian msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); 688e47fef9eSflorian log_assert(msg.msg_controllen <= sizeof(control.buf)); 689ae8c6e27Sflorian cmsg->cmsg_level = IPPROTO_IPV6; 690ae8c6e27Sflorian cmsg->cmsg_type = IPV6_PKTINFO; 691ae8c6e27Sflorian memset(CMSG_DATA(cmsg), 0, sizeof(struct in6_pktinfo)); 692ae8c6e27Sflorian cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 693d500c338Sflorian /* zero the padding bytes inserted by the CMSG_LEN */ 694d500c338Sflorian if(sizeof(struct in6_pktinfo) < cmsg->cmsg_len) 695d500c338Sflorian memset(((uint8_t*)(CMSG_DATA(cmsg))) + 696d500c338Sflorian sizeof(struct in6_pktinfo), 0, cmsg->cmsg_len 697d500c338Sflorian - sizeof(struct in6_pktinfo)); 698ae8c6e27Sflorian } 699ae8c6e27Sflorian #endif /* S_SPLINT_S */ 700d500c338Sflorian if(verbosity >= VERB_ALGO && r->srctype != 0) 701ae8c6e27Sflorian p_ancil("send_udp over interface", r); 702ae8c6e27Sflorian sent = sendmsg(c->fd, &msg, 0); 703ae8c6e27Sflorian if(sent == -1) { 704ae8c6e27Sflorian /* try again and block, waiting for IO to complete, 705ae8c6e27Sflorian * we want to send the answer, and we will wait for 706ae8c6e27Sflorian * the ethernet interface buffer to have space. */ 707ae8c6e27Sflorian #ifndef USE_WINSOCK 7085c45b740Sflorian if(errno == EAGAIN || errno == EINTR || 709ae8c6e27Sflorian # ifdef EWOULDBLOCK 710ae8c6e27Sflorian errno == EWOULDBLOCK || 711ae8c6e27Sflorian # endif 712ae8c6e27Sflorian errno == ENOBUFS) { 713ae8c6e27Sflorian #else 714ae8c6e27Sflorian if(WSAGetLastError() == WSAEINPROGRESS || 7155c45b740Sflorian WSAGetLastError() == WSAEINTR || 716ae8c6e27Sflorian WSAGetLastError() == WSAENOBUFS || 717ae8c6e27Sflorian WSAGetLastError() == WSAEWOULDBLOCK) { 718ae8c6e27Sflorian #endif 719cece5eebSflorian int retries = 0; 720cece5eebSflorian while(sent == -1 && retries < SEND_BLOCKED_MAX_RETRY && ( 7215c45b740Sflorian #ifndef USE_WINSOCK 7225c45b740Sflorian errno == EAGAIN || errno == EINTR || 7235c45b740Sflorian # ifdef EWOULDBLOCK 7245c45b740Sflorian errno == EWOULDBLOCK || 7255c45b740Sflorian # endif 7265c45b740Sflorian errno == ENOBUFS 7275c45b740Sflorian #else 7285c45b740Sflorian WSAGetLastError() == WSAEINPROGRESS || 7295c45b740Sflorian WSAGetLastError() == WSAEINTR || 7305c45b740Sflorian WSAGetLastError() == WSAENOBUFS || 7315c45b740Sflorian WSAGetLastError() == WSAEWOULDBLOCK 7325c45b740Sflorian #endif 7335c45b740Sflorian )) { 7345c45b740Sflorian #if defined(HAVE_POLL) || defined(USE_WINSOCK) 735cece5eebSflorian int send_nobufs = ( 736cece5eebSflorian #ifndef USE_WINSOCK 737cece5eebSflorian errno == ENOBUFS 738cece5eebSflorian #else 739cece5eebSflorian WSAGetLastError() == WSAENOBUFS 740cece5eebSflorian #endif 741cece5eebSflorian ); 7425c45b740Sflorian struct pollfd p; 7435c45b740Sflorian int pret; 7445c45b740Sflorian memset(&p, 0, sizeof(p)); 7455c45b740Sflorian p.fd = c->fd; 7465c45b740Sflorian p.events = POLLOUT | POLLERR | POLLHUP; 7475c45b740Sflorian # ifndef USE_WINSOCK 7485c45b740Sflorian pret = poll(&p, 1, SEND_BLOCKED_WAIT_TIMEOUT); 7495c45b740Sflorian # else 7505c45b740Sflorian pret = WSAPoll(&p, 1, 7515c45b740Sflorian SEND_BLOCKED_WAIT_TIMEOUT); 7525c45b740Sflorian # endif 7535c45b740Sflorian if(pret == 0) { 7545c45b740Sflorian /* timer expired */ 7555c45b740Sflorian struct comm_base* b = c->ev->base; 7565c45b740Sflorian if(b->eb->last_writewait_log+SLOW_LOG_TIME <= 7575c45b740Sflorian b->eb->secs) { 7585c45b740Sflorian b->eb->last_writewait_log = b->eb->secs; 7595c45b740Sflorian verbose(VERB_OPS, "send udp blocked " 7605c45b740Sflorian "for long, dropping packet."); 7615c45b740Sflorian } 7625c45b740Sflorian return 0; 7635c45b740Sflorian } else if(pret < 0 && 7645c45b740Sflorian #ifndef USE_WINSOCK 7655c45b740Sflorian errno != EAGAIN && errno != EINTR && 7665c45b740Sflorian # ifdef EWOULDBLOCK 7675c45b740Sflorian errno != EWOULDBLOCK && 7685c45b740Sflorian # endif 7695c45b740Sflorian errno != ENOBUFS 7705c45b740Sflorian #else 7715c45b740Sflorian WSAGetLastError() != WSAEINPROGRESS && 7725c45b740Sflorian WSAGetLastError() != WSAEINTR && 7735c45b740Sflorian WSAGetLastError() != WSAENOBUFS && 7745c45b740Sflorian WSAGetLastError() != WSAEWOULDBLOCK 7755c45b740Sflorian #endif 7765c45b740Sflorian ) { 7775c45b740Sflorian log_err("poll udp out failed: %s", 7785c45b740Sflorian sock_strerror(errno)); 7795c45b740Sflorian return 0; 780cece5eebSflorian } else if((pret < 0 && 781cece5eebSflorian #ifndef USE_WINSOCK 782cece5eebSflorian errno == ENOBUFS 783cece5eebSflorian #else 784cece5eebSflorian WSAGetLastError() == WSAENOBUFS 785cece5eebSflorian #endif 786cece5eebSflorian ) || (send_nobufs && retries > 0)) { 787cece5eebSflorian /* ENOBUFS, and poll returned without 788cece5eebSflorian * a timeout. Or the retried send call 789cece5eebSflorian * returned ENOBUFS. It is good to 790cece5eebSflorian * wait a bit for the error to clear. */ 791cece5eebSflorian /* The timeout is 20*(2^(retries+1)), 792cece5eebSflorian * it increases exponentially, starting 793cece5eebSflorian * at 40 msec. After 5 tries, 1240 msec 794cece5eebSflorian * have passed in total, when poll 795cece5eebSflorian * returned the error, and 1200 msec 796cece5eebSflorian * when send returned the errors. */ 797cece5eebSflorian #ifndef USE_WINSOCK 798cece5eebSflorian pret = poll(NULL, 0, (SEND_BLOCKED_WAIT_TIMEOUT/10)<<(retries+1)); 799cece5eebSflorian #else 800cece5eebSflorian pret = WSAPoll(NULL, 0, (SEND_BLOCKED_WAIT_TIMEOUT/10)<<(retries+1)); 801cece5eebSflorian #endif 802cece5eebSflorian if(pret < 0 && 803cece5eebSflorian #ifndef USE_WINSOCK 804cece5eebSflorian errno != EAGAIN && errno != EINTR && 805cece5eebSflorian # ifdef EWOULDBLOCK 806cece5eebSflorian errno != EWOULDBLOCK && 807cece5eebSflorian # endif 808cece5eebSflorian errno != ENOBUFS 809cece5eebSflorian #else 810cece5eebSflorian WSAGetLastError() != WSAEINPROGRESS && 811cece5eebSflorian WSAGetLastError() != WSAEINTR && 812cece5eebSflorian WSAGetLastError() != WSAENOBUFS && 813cece5eebSflorian WSAGetLastError() != WSAEWOULDBLOCK 814cece5eebSflorian #endif 815cece5eebSflorian ) { 816cece5eebSflorian log_err("poll udp out timer failed: %s", 817cece5eebSflorian sock_strerror(errno)); 818cece5eebSflorian } 8195c45b740Sflorian } 8205c45b740Sflorian #endif /* defined(HAVE_POLL) || defined(USE_WINSOCK) */ 821cece5eebSflorian retries++; 822ae8c6e27Sflorian sent = sendmsg(c->fd, &msg, 0); 8235c45b740Sflorian } 824ae8c6e27Sflorian } 825ae8c6e27Sflorian } 826ae8c6e27Sflorian if(sent == -1) { 827ae8c6e27Sflorian if(!udp_send_errno_needs_log(addr, addrlen)) 828ae8c6e27Sflorian return 0; 829ae8c6e27Sflorian verbose(VERB_OPS, "sendmsg failed: %s", strerror(errno)); 830ae8c6e27Sflorian log_addr(VERB_OPS, "remote address is", 831ae8c6e27Sflorian (struct sockaddr_storage*)addr, addrlen); 832ae8c6e27Sflorian #ifdef __NetBSD__ 833ae8c6e27Sflorian /* netbsd 7 has IP_PKTINFO for recv but not send */ 834ae8c6e27Sflorian if(errno == EINVAL && r->srctype == 4) 835ae8c6e27Sflorian log_err("sendmsg: No support for sendmsg(IP_PKTINFO). " 836ae8c6e27Sflorian "Please disable interface-automatic"); 837ae8c6e27Sflorian #endif 838ae8c6e27Sflorian return 0; 839ae8c6e27Sflorian } else if((size_t)sent != sldns_buffer_remaining(packet)) { 840ae8c6e27Sflorian log_err("sent %d in place of %d bytes", 841ae8c6e27Sflorian (int)sent, (int)sldns_buffer_remaining(packet)); 842ae8c6e27Sflorian return 0; 843ae8c6e27Sflorian } 844ae8c6e27Sflorian return 1; 845ae8c6e27Sflorian #else 846ae8c6e27Sflorian (void)c; 847ae8c6e27Sflorian (void)packet; 848ae8c6e27Sflorian (void)addr; 849ae8c6e27Sflorian (void)addrlen; 850ae8c6e27Sflorian (void)r; 851ae8c6e27Sflorian log_err("sendmsg: IPV6_PKTINFO not supported"); 852ae8c6e27Sflorian return 0; 853ae8c6e27Sflorian #endif /* AF_INET6 && IPV6_PKTINFO && HAVE_SENDMSG */ 854ae8c6e27Sflorian } 855ae8c6e27Sflorian 856853e076fSflorian /** return true is UDP receive error needs to be logged */ 857853e076fSflorian static int udp_recv_needs_log(int err) 858853e076fSflorian { 859853e076fSflorian switch(err) { 860a8eaceedSflorian case EACCES: /* some hosts send ICMP 'Permission Denied' */ 861a8eaceedSflorian #ifndef USE_WINSOCK 862853e076fSflorian case ECONNREFUSED: 863853e076fSflorian # ifdef ENETUNREACH 864853e076fSflorian case ENETUNREACH: 865853e076fSflorian # endif 866853e076fSflorian # ifdef EHOSTDOWN 867853e076fSflorian case EHOSTDOWN: 868853e076fSflorian # endif 869853e076fSflorian # ifdef EHOSTUNREACH 870853e076fSflorian case EHOSTUNREACH: 871853e076fSflorian # endif 872853e076fSflorian # ifdef ENETDOWN 873853e076fSflorian case ENETDOWN: 874853e076fSflorian # endif 875a8eaceedSflorian #else /* USE_WINSOCK */ 876a8eaceedSflorian case WSAECONNREFUSED: 877a8eaceedSflorian case WSAENETUNREACH: 878a8eaceedSflorian case WSAEHOSTDOWN: 879a8eaceedSflorian case WSAEHOSTUNREACH: 880a8eaceedSflorian case WSAENETDOWN: 881a8eaceedSflorian #endif 882853e076fSflorian if(verbosity >= VERB_ALGO) 883853e076fSflorian return 1; 884853e076fSflorian return 0; 885853e076fSflorian default: 886853e076fSflorian break; 887853e076fSflorian } 888853e076fSflorian return 1; 889853e076fSflorian } 890853e076fSflorian 8915c45b740Sflorian /** Parses the PROXYv2 header from buf and updates the comm_reply struct. 8925c45b740Sflorian * Returns 1 on success, 0 on failure. */ 8935c45b740Sflorian static int consume_pp2_header(struct sldns_buffer* buf, struct comm_reply* rep, 8945c45b740Sflorian int stream) { 8955c45b740Sflorian size_t size; 89654cc57acSflorian struct pp2_header *header; 89754cc57acSflorian int err = pp2_read_header(sldns_buffer_begin(buf), 89854cc57acSflorian sldns_buffer_remaining(buf)); 89954cc57acSflorian if(err) return 0; 90054cc57acSflorian header = (struct pp2_header*)sldns_buffer_begin(buf); 9015c45b740Sflorian size = PP2_HEADER_SIZE + ntohs(header->len); 9025c45b740Sflorian if((header->ver_cmd & 0xF) == PP2_CMD_LOCAL) { 9035c45b740Sflorian /* A connection from the proxy itself. 9045c45b740Sflorian * No need to do anything with addresses. */ 9055c45b740Sflorian goto done; 9065c45b740Sflorian } 90754cc57acSflorian if(header->fam_prot == PP2_UNSPEC_UNSPEC) { 9085c45b740Sflorian /* Unspecified family and protocol. This could be used for 9095c45b740Sflorian * health checks by proxies. 9105c45b740Sflorian * No need to do anything with addresses. */ 9115c45b740Sflorian goto done; 9125c45b740Sflorian } 9135c45b740Sflorian /* Read the proxied address */ 9145c45b740Sflorian switch(header->fam_prot) { 91554cc57acSflorian case PP2_INET_STREAM: 91654cc57acSflorian case PP2_INET_DGRAM: 9175c45b740Sflorian { 9185c45b740Sflorian struct sockaddr_in* addr = 9195c45b740Sflorian (struct sockaddr_in*)&rep->client_addr; 9205c45b740Sflorian addr->sin_family = AF_INET; 9215c45b740Sflorian addr->sin_addr.s_addr = header->addr.addr4.src_addr; 9225c45b740Sflorian addr->sin_port = header->addr.addr4.src_port; 9235c45b740Sflorian rep->client_addrlen = (socklen_t)sizeof(struct sockaddr_in); 9245c45b740Sflorian } 9255c45b740Sflorian /* Ignore the destination address; it should be us. */ 9265c45b740Sflorian break; 92754cc57acSflorian case PP2_INET6_STREAM: 92854cc57acSflorian case PP2_INET6_DGRAM: 9295c45b740Sflorian { 9305c45b740Sflorian struct sockaddr_in6* addr = 9315c45b740Sflorian (struct sockaddr_in6*)&rep->client_addr; 9325c45b740Sflorian memset(addr, 0, sizeof(*addr)); 9335c45b740Sflorian addr->sin6_family = AF_INET6; 9345c45b740Sflorian memcpy(&addr->sin6_addr, 9355c45b740Sflorian header->addr.addr6.src_addr, 16); 9365c45b740Sflorian addr->sin6_port = header->addr.addr6.src_port; 9375c45b740Sflorian rep->client_addrlen = (socklen_t)sizeof(struct sockaddr_in6); 9385c45b740Sflorian } 9395c45b740Sflorian /* Ignore the destination address; it should be us. */ 9405c45b740Sflorian break; 94154cc57acSflorian default: 94254cc57acSflorian log_err("proxy_protocol: unsupported family and " 94354cc57acSflorian "protocol 0x%x", (int)header->fam_prot); 94454cc57acSflorian return 0; 9455c45b740Sflorian } 9465c45b740Sflorian rep->is_proxied = 1; 9475c45b740Sflorian done: 9485c45b740Sflorian if(!stream) { 9495c45b740Sflorian /* We are reading a whole packet; 9505c45b740Sflorian * Move the rest of the data to overwrite the PROXYv2 header */ 9515c45b740Sflorian /* XXX can we do better to avoid memmove? */ 9525c45b740Sflorian memmove(header, ((char*)header)+size, 9535c45b740Sflorian sldns_buffer_limit(buf)-size); 9545c45b740Sflorian sldns_buffer_set_limit(buf, sldns_buffer_limit(buf)-size); 9555c45b740Sflorian } 9565c45b740Sflorian return 1; 9575c45b740Sflorian } 9585c45b740Sflorian 95954cc57acSflorian #if defined(AF_INET6) && defined(IPV6_PKTINFO) && defined(HAVE_RECVMSG) 960ae8c6e27Sflorian void 961ae8c6e27Sflorian comm_point_udp_ancil_callback(int fd, short event, void* arg) 962ae8c6e27Sflorian { 963ae8c6e27Sflorian struct comm_reply rep; 964ae8c6e27Sflorian struct msghdr msg; 965ae8c6e27Sflorian struct iovec iov[1]; 966ae8c6e27Sflorian ssize_t rcv; 9673d4dbd37Sjca union { 9683d4dbd37Sjca struct cmsghdr hdr; 9693d4dbd37Sjca char buf[256]; 9703d4dbd37Sjca } ancil; 971ae8c6e27Sflorian int i; 972ae8c6e27Sflorian #ifndef S_SPLINT_S 973ae8c6e27Sflorian struct cmsghdr* cmsg; 974ae8c6e27Sflorian #endif /* S_SPLINT_S */ 975d500c338Sflorian #ifdef HAVE_LINUX_NET_TSTAMP_H 976d500c338Sflorian struct timespec *ts; 977d500c338Sflorian #endif /* HAVE_LINUX_NET_TSTAMP_H */ 978ae8c6e27Sflorian 979ae8c6e27Sflorian rep.c = (struct comm_point*)arg; 980ae8c6e27Sflorian log_assert(rep.c->type == comm_udp); 981ae8c6e27Sflorian 982ae8c6e27Sflorian if(!(event&UB_EV_READ)) 983ae8c6e27Sflorian return; 984ae8c6e27Sflorian log_assert(rep.c && rep.c->buffer && rep.c->fd == fd); 985ae8c6e27Sflorian ub_comm_base_now(rep.c->ev->base); 986ae8c6e27Sflorian for(i=0; i<NUM_UDP_PER_SELECT; i++) { 987ae8c6e27Sflorian sldns_buffer_clear(rep.c->buffer); 988d500c338Sflorian timeval_clear(&rep.c->recv_tv); 9895c45b740Sflorian rep.remote_addrlen = (socklen_t)sizeof(rep.remote_addr); 990ae8c6e27Sflorian log_assert(fd != -1); 991ae8c6e27Sflorian log_assert(sldns_buffer_remaining(rep.c->buffer) > 0); 9925c45b740Sflorian msg.msg_name = &rep.remote_addr; 9935c45b740Sflorian msg.msg_namelen = (socklen_t)sizeof(rep.remote_addr); 994ae8c6e27Sflorian iov[0].iov_base = sldns_buffer_begin(rep.c->buffer); 995ae8c6e27Sflorian iov[0].iov_len = sldns_buffer_remaining(rep.c->buffer); 996ae8c6e27Sflorian msg.msg_iov = iov; 997ae8c6e27Sflorian msg.msg_iovlen = 1; 9983d4dbd37Sjca msg.msg_control = ancil.buf; 999ae8c6e27Sflorian #ifndef S_SPLINT_S 1000e47fef9eSflorian msg.msg_controllen = sizeof(ancil.buf); 1001ae8c6e27Sflorian #endif /* S_SPLINT_S */ 1002ae8c6e27Sflorian msg.msg_flags = 0; 10035c45b740Sflorian rcv = recvmsg(fd, &msg, MSG_DONTWAIT); 1004ae8c6e27Sflorian if(rcv == -1) { 1005853e076fSflorian if(errno != EAGAIN && errno != EINTR 1006853e076fSflorian && udp_recv_needs_log(errno)) { 1007ae8c6e27Sflorian log_err("recvmsg failed: %s", strerror(errno)); 1008ae8c6e27Sflorian } 1009ae8c6e27Sflorian return; 1010ae8c6e27Sflorian } 10115c45b740Sflorian rep.remote_addrlen = msg.msg_namelen; 1012ae8c6e27Sflorian sldns_buffer_skip(rep.c->buffer, rcv); 1013ae8c6e27Sflorian sldns_buffer_flip(rep.c->buffer); 1014ae8c6e27Sflorian rep.srctype = 0; 10155c45b740Sflorian rep.is_proxied = 0; 1016ae8c6e27Sflorian #ifndef S_SPLINT_S 1017ae8c6e27Sflorian for(cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; 1018ae8c6e27Sflorian cmsg = CMSG_NXTHDR(&msg, cmsg)) { 1019ae8c6e27Sflorian if( cmsg->cmsg_level == IPPROTO_IPV6 && 1020ae8c6e27Sflorian cmsg->cmsg_type == IPV6_PKTINFO) { 1021ae8c6e27Sflorian rep.srctype = 6; 1022ae8c6e27Sflorian memmove(&rep.pktinfo.v6info, CMSG_DATA(cmsg), 1023ae8c6e27Sflorian sizeof(struct in6_pktinfo)); 1024ae8c6e27Sflorian break; 1025ae8c6e27Sflorian #ifdef IP_PKTINFO 1026ae8c6e27Sflorian } else if( cmsg->cmsg_level == IPPROTO_IP && 1027ae8c6e27Sflorian cmsg->cmsg_type == IP_PKTINFO) { 1028ae8c6e27Sflorian rep.srctype = 4; 1029ae8c6e27Sflorian memmove(&rep.pktinfo.v4info, CMSG_DATA(cmsg), 1030ae8c6e27Sflorian sizeof(struct in_pktinfo)); 1031ae8c6e27Sflorian break; 1032ae8c6e27Sflorian #elif defined(IP_RECVDSTADDR) 1033ae8c6e27Sflorian } else if( cmsg->cmsg_level == IPPROTO_IP && 1034ae8c6e27Sflorian cmsg->cmsg_type == IP_RECVDSTADDR) { 1035ae8c6e27Sflorian rep.srctype = 4; 1036ae8c6e27Sflorian memmove(&rep.pktinfo.v4addr, CMSG_DATA(cmsg), 1037ae8c6e27Sflorian sizeof(struct in_addr)); 1038ae8c6e27Sflorian break; 1039ae8c6e27Sflorian #endif /* IP_PKTINFO or IP_RECVDSTADDR */ 1040d500c338Sflorian #ifdef HAVE_LINUX_NET_TSTAMP_H 1041d500c338Sflorian } else if( cmsg->cmsg_level == SOL_SOCKET && 1042d500c338Sflorian cmsg->cmsg_type == SO_TIMESTAMPNS) { 1043d500c338Sflorian ts = (struct timespec *)CMSG_DATA(cmsg); 1044d500c338Sflorian TIMESPEC_TO_TIMEVAL(&rep.c->recv_tv, ts); 1045d500c338Sflorian } else if( cmsg->cmsg_level == SOL_SOCKET && 1046d500c338Sflorian cmsg->cmsg_type == SO_TIMESTAMPING) { 1047d500c338Sflorian ts = (struct timespec *)CMSG_DATA(cmsg); 1048d500c338Sflorian TIMESPEC_TO_TIMEVAL(&rep.c->recv_tv, ts); 1049d500c338Sflorian } else if( cmsg->cmsg_level == SOL_SOCKET && 1050d500c338Sflorian cmsg->cmsg_type == SO_TIMESTAMP) { 1051d500c338Sflorian memmove(&rep.c->recv_tv, CMSG_DATA(cmsg), sizeof(struct timeval)); 1052d500c338Sflorian #endif /* HAVE_LINUX_NET_TSTAMP_H */ 1053ae8c6e27Sflorian } 1054ae8c6e27Sflorian } 1055d500c338Sflorian 1056d500c338Sflorian if(verbosity >= VERB_ALGO && rep.srctype != 0) 1057ae8c6e27Sflorian p_ancil("receive_udp on interface", &rep); 1058ae8c6e27Sflorian #endif /* S_SPLINT_S */ 10595c45b740Sflorian 10605c45b740Sflorian if(rep.c->pp2_enabled && !consume_pp2_header(rep.c->buffer, 10615c45b740Sflorian &rep, 0)) { 10625c45b740Sflorian log_err("proxy_protocol: could not consume PROXYv2 header"); 10635c45b740Sflorian return; 10645c45b740Sflorian } 10655c45b740Sflorian if(!rep.is_proxied) { 10665c45b740Sflorian rep.client_addrlen = rep.remote_addrlen; 10675c45b740Sflorian memmove(&rep.client_addr, &rep.remote_addr, 10685c45b740Sflorian rep.remote_addrlen); 10695c45b740Sflorian } 10705c45b740Sflorian 1071ae8c6e27Sflorian fptr_ok(fptr_whitelist_comm_point(rep.c->callback)); 1072ae8c6e27Sflorian if((*rep.c->callback)(rep.c, rep.c->cb_arg, NETEVENT_NOERROR, &rep)) { 1073ae8c6e27Sflorian /* send back immediate reply */ 107454cc57acSflorian struct sldns_buffer *buffer; 107554cc57acSflorian #ifdef USE_DNSCRYPT 107654cc57acSflorian buffer = rep.c->dnscrypt_buffer; 107754cc57acSflorian #else 107854cc57acSflorian buffer = rep.c->buffer; 107954cc57acSflorian #endif 108054cc57acSflorian (void)comm_point_send_udp_msg_if(rep.c, buffer, 10815c45b740Sflorian (struct sockaddr*)&rep.remote_addr, 10825c45b740Sflorian rep.remote_addrlen, &rep); 1083ae8c6e27Sflorian } 1084ae8c6e27Sflorian if(!rep.c || rep.c->fd == -1) /* commpoint closed */ 1085ae8c6e27Sflorian break; 1086ae8c6e27Sflorian } 1087ae8c6e27Sflorian } 108854cc57acSflorian #endif /* AF_INET6 && IPV6_PKTINFO && HAVE_RECVMSG */ 1089ae8c6e27Sflorian 1090ae8c6e27Sflorian void 1091ae8c6e27Sflorian comm_point_udp_callback(int fd, short event, void* arg) 1092ae8c6e27Sflorian { 1093ae8c6e27Sflorian struct comm_reply rep; 1094ae8c6e27Sflorian ssize_t rcv; 1095ae8c6e27Sflorian int i; 1096ae8c6e27Sflorian struct sldns_buffer *buffer; 1097ae8c6e27Sflorian 1098ae8c6e27Sflorian rep.c = (struct comm_point*)arg; 1099ae8c6e27Sflorian log_assert(rep.c->type == comm_udp); 1100ae8c6e27Sflorian 1101ae8c6e27Sflorian if(!(event&UB_EV_READ)) 1102ae8c6e27Sflorian return; 1103ae8c6e27Sflorian log_assert(rep.c && rep.c->buffer && rep.c->fd == fd); 1104ae8c6e27Sflorian ub_comm_base_now(rep.c->ev->base); 1105ae8c6e27Sflorian for(i=0; i<NUM_UDP_PER_SELECT; i++) { 1106ae8c6e27Sflorian sldns_buffer_clear(rep.c->buffer); 11075c45b740Sflorian rep.remote_addrlen = (socklen_t)sizeof(rep.remote_addr); 1108ae8c6e27Sflorian log_assert(fd != -1); 1109ae8c6e27Sflorian log_assert(sldns_buffer_remaining(rep.c->buffer) > 0); 1110ae8c6e27Sflorian rcv = recvfrom(fd, (void*)sldns_buffer_begin(rep.c->buffer), 11115c45b740Sflorian sldns_buffer_remaining(rep.c->buffer), MSG_DONTWAIT, 11125c45b740Sflorian (struct sockaddr*)&rep.remote_addr, &rep.remote_addrlen); 1113ae8c6e27Sflorian if(rcv == -1) { 1114ae8c6e27Sflorian #ifndef USE_WINSOCK 1115853e076fSflorian if(errno != EAGAIN && errno != EINTR 1116853e076fSflorian && udp_recv_needs_log(errno)) 1117ae8c6e27Sflorian log_err("recvfrom %d failed: %s", 1118ae8c6e27Sflorian fd, strerror(errno)); 1119ae8c6e27Sflorian #else 1120ae8c6e27Sflorian if(WSAGetLastError() != WSAEINPROGRESS && 1121ae8c6e27Sflorian WSAGetLastError() != WSAECONNRESET && 1122a8eaceedSflorian WSAGetLastError()!= WSAEWOULDBLOCK && 1123a8eaceedSflorian udp_recv_needs_log(WSAGetLastError())) 1124ae8c6e27Sflorian log_err("recvfrom failed: %s", 1125ae8c6e27Sflorian wsa_strerror(WSAGetLastError())); 1126ae8c6e27Sflorian #endif 1127ae8c6e27Sflorian return; 1128ae8c6e27Sflorian } 1129ae8c6e27Sflorian sldns_buffer_skip(rep.c->buffer, rcv); 1130ae8c6e27Sflorian sldns_buffer_flip(rep.c->buffer); 1131ae8c6e27Sflorian rep.srctype = 0; 11325c45b740Sflorian rep.is_proxied = 0; 11335c45b740Sflorian 11345c45b740Sflorian if(rep.c->pp2_enabled && !consume_pp2_header(rep.c->buffer, 11355c45b740Sflorian &rep, 0)) { 11365c45b740Sflorian log_err("proxy_protocol: could not consume PROXYv2 header"); 11375c45b740Sflorian return; 11385c45b740Sflorian } 11395c45b740Sflorian if(!rep.is_proxied) { 11405c45b740Sflorian rep.client_addrlen = rep.remote_addrlen; 11415c45b740Sflorian memmove(&rep.client_addr, &rep.remote_addr, 11425c45b740Sflorian rep.remote_addrlen); 11435c45b740Sflorian } 11445c45b740Sflorian 1145ae8c6e27Sflorian fptr_ok(fptr_whitelist_comm_point(rep.c->callback)); 1146ae8c6e27Sflorian if((*rep.c->callback)(rep.c, rep.c->cb_arg, NETEVENT_NOERROR, &rep)) { 1147ae8c6e27Sflorian /* send back immediate reply */ 1148ae8c6e27Sflorian #ifdef USE_DNSCRYPT 1149ae8c6e27Sflorian buffer = rep.c->dnscrypt_buffer; 1150ae8c6e27Sflorian #else 1151ae8c6e27Sflorian buffer = rep.c->buffer; 1152ae8c6e27Sflorian #endif 1153ae8c6e27Sflorian (void)comm_point_send_udp_msg(rep.c, buffer, 11545c45b740Sflorian (struct sockaddr*)&rep.remote_addr, 11555c45b740Sflorian rep.remote_addrlen, 0); 1156ae8c6e27Sflorian } 1157ae8c6e27Sflorian if(!rep.c || rep.c->fd != fd) /* commpoint closed to -1 or reused for 1158ae8c6e27Sflorian another UDP port. Note rep.c cannot be reused with TCP fd. */ 1159ae8c6e27Sflorian break; 1160ae8c6e27Sflorian } 1161ae8c6e27Sflorian } 1162ae8c6e27Sflorian 1163a8eaceedSflorian int adjusted_tcp_timeout(struct comm_point* c) 1164a8eaceedSflorian { 1165a8eaceedSflorian if(c->tcp_timeout_msec < TCP_QUERY_TIMEOUT_MINIMUM) 1166a8eaceedSflorian return TCP_QUERY_TIMEOUT_MINIMUM; 1167a8eaceedSflorian return c->tcp_timeout_msec; 1168a8eaceedSflorian } 1169a8eaceedSflorian 1170ae8c6e27Sflorian /** Use a new tcp handler for new query fd, set to read query */ 1171ae8c6e27Sflorian static void 1172ae8c6e27Sflorian setup_tcp_handler(struct comm_point* c, int fd, int cur, int max) 1173ae8c6e27Sflorian { 1174ae8c6e27Sflorian int handler_usage; 1175f4f0f0ceSflorian log_assert(c->type == comm_tcp || c->type == comm_http); 1176ae8c6e27Sflorian log_assert(c->fd == -1); 1177ae8c6e27Sflorian sldns_buffer_clear(c->buffer); 1178ae8c6e27Sflorian #ifdef USE_DNSCRYPT 1179ae8c6e27Sflorian if (c->dnscrypt) 1180ae8c6e27Sflorian sldns_buffer_clear(c->dnscrypt_buffer); 1181ae8c6e27Sflorian #endif 1182ae8c6e27Sflorian c->tcp_is_reading = 1; 1183ae8c6e27Sflorian c->tcp_byte_count = 0; 1184a1a7ba80Sflorian c->tcp_keepalive = 0; 1185ae8c6e27Sflorian /* if more than half the tcp handlers are in use, use a shorter 1186ae8c6e27Sflorian * timeout for this TCP connection, we need to make space for 1187ae8c6e27Sflorian * other connections to be able to get attention */ 1188ae8c6e27Sflorian /* If > 50% TCP handler structures in use, set timeout to 1/100th 1189ae8c6e27Sflorian * configured value. 1190ae8c6e27Sflorian * If > 65%TCP handler structures in use, set to 1/500th configured 1191ae8c6e27Sflorian * value. 1192ae8c6e27Sflorian * If > 80% TCP handler structures in use, set to 0. 1193ae8c6e27Sflorian * 1194ae8c6e27Sflorian * If the timeout to use falls below 200 milliseconds, an actual 1195ae8c6e27Sflorian * timeout of 200ms is used. 1196ae8c6e27Sflorian */ 1197ae8c6e27Sflorian handler_usage = (cur * 100) / max; 1198ae8c6e27Sflorian if(handler_usage > 50 && handler_usage <= 65) 1199ae8c6e27Sflorian c->tcp_timeout_msec /= 100; 1200ae8c6e27Sflorian else if (handler_usage > 65 && handler_usage <= 80) 1201ae8c6e27Sflorian c->tcp_timeout_msec /= 500; 1202ae8c6e27Sflorian else if (handler_usage > 80) 1203ae8c6e27Sflorian c->tcp_timeout_msec = 0; 1204a8eaceedSflorian comm_point_start_listening(c, fd, adjusted_tcp_timeout(c)); 1205ae8c6e27Sflorian } 1206ae8c6e27Sflorian 1207ae8c6e27Sflorian void comm_base_handle_slow_accept(int ATTR_UNUSED(fd), 1208ae8c6e27Sflorian short ATTR_UNUSED(event), void* arg) 1209ae8c6e27Sflorian { 1210ae8c6e27Sflorian struct comm_base* b = (struct comm_base*)arg; 1211ae8c6e27Sflorian /* timeout for the slow accept, re-enable accepts again */ 1212ae8c6e27Sflorian if(b->start_accept) { 1213ae8c6e27Sflorian verbose(VERB_ALGO, "wait is over, slow accept disabled"); 1214ae8c6e27Sflorian fptr_ok(fptr_whitelist_start_accept(b->start_accept)); 1215ae8c6e27Sflorian (*b->start_accept)(b->cb_arg); 1216ae8c6e27Sflorian b->eb->slow_accept_enabled = 0; 1217ae8c6e27Sflorian } 1218ae8c6e27Sflorian } 1219ae8c6e27Sflorian 1220ae8c6e27Sflorian int comm_point_perform_accept(struct comm_point* c, 1221ae8c6e27Sflorian struct sockaddr_storage* addr, socklen_t* addrlen) 1222ae8c6e27Sflorian { 1223ae8c6e27Sflorian int new_fd; 1224ae8c6e27Sflorian *addrlen = (socklen_t)sizeof(*addr); 1225ae8c6e27Sflorian #ifndef HAVE_ACCEPT4 1226ae8c6e27Sflorian new_fd = accept(c->fd, (struct sockaddr*)addr, addrlen); 1227ae8c6e27Sflorian #else 1228ae8c6e27Sflorian /* SOCK_NONBLOCK saves extra calls to fcntl for the same result */ 1229ae8c6e27Sflorian new_fd = accept4(c->fd, (struct sockaddr*)addr, addrlen, SOCK_NONBLOCK); 1230ae8c6e27Sflorian #endif 1231ae8c6e27Sflorian if(new_fd == -1) { 1232ae8c6e27Sflorian #ifndef USE_WINSOCK 1233ae8c6e27Sflorian /* EINTR is signal interrupt. others are closed connection. */ 1234ae8c6e27Sflorian if( errno == EINTR || errno == EAGAIN 1235ae8c6e27Sflorian #ifdef EWOULDBLOCK 1236ae8c6e27Sflorian || errno == EWOULDBLOCK 1237ae8c6e27Sflorian #endif 1238ae8c6e27Sflorian #ifdef ECONNABORTED 1239ae8c6e27Sflorian || errno == ECONNABORTED 1240ae8c6e27Sflorian #endif 1241ae8c6e27Sflorian #ifdef EPROTO 1242ae8c6e27Sflorian || errno == EPROTO 1243ae8c6e27Sflorian #endif /* EPROTO */ 1244ae8c6e27Sflorian ) 1245ae8c6e27Sflorian return -1; 1246ae8c6e27Sflorian #if defined(ENFILE) && defined(EMFILE) 1247ae8c6e27Sflorian if(errno == ENFILE || errno == EMFILE) { 1248ae8c6e27Sflorian /* out of file descriptors, likely outside of our 1249ae8c6e27Sflorian * control. stop accept() calls for some time */ 1250ae8c6e27Sflorian if(c->ev->base->stop_accept) { 1251ae8c6e27Sflorian struct comm_base* b = c->ev->base; 1252ae8c6e27Sflorian struct timeval tv; 1253ae8c6e27Sflorian verbose(VERB_ALGO, "out of file descriptors: " 1254ae8c6e27Sflorian "slow accept"); 12555c45b740Sflorian ub_comm_base_now(b); 12565c45b740Sflorian if(b->eb->last_slow_log+SLOW_LOG_TIME <= 12575c45b740Sflorian b->eb->secs) { 12585c45b740Sflorian b->eb->last_slow_log = b->eb->secs; 12595c45b740Sflorian verbose(VERB_OPS, "accept failed, " 12605c45b740Sflorian "slow down accept for %d " 12615c45b740Sflorian "msec: %s", 12625c45b740Sflorian NETEVENT_SLOW_ACCEPT_TIME, 12635c45b740Sflorian sock_strerror(errno)); 12645c45b740Sflorian } 1265ae8c6e27Sflorian b->eb->slow_accept_enabled = 1; 1266ae8c6e27Sflorian fptr_ok(fptr_whitelist_stop_accept( 1267ae8c6e27Sflorian b->stop_accept)); 1268ae8c6e27Sflorian (*b->stop_accept)(b->cb_arg); 1269ae8c6e27Sflorian /* set timeout, no mallocs */ 1270ae8c6e27Sflorian tv.tv_sec = NETEVENT_SLOW_ACCEPT_TIME/1000; 1271ae8c6e27Sflorian tv.tv_usec = (NETEVENT_SLOW_ACCEPT_TIME%1000)*1000; 1272ae8c6e27Sflorian b->eb->slow_accept = ub_event_new(b->eb->base, 1273ae8c6e27Sflorian -1, UB_EV_TIMEOUT, 1274ae8c6e27Sflorian comm_base_handle_slow_accept, b); 1275ae8c6e27Sflorian if(b->eb->slow_accept == NULL) { 1276ae8c6e27Sflorian /* we do not want to log here, because 1277ae8c6e27Sflorian * that would spam the logfiles. 1278ae8c6e27Sflorian * error: "event_base_set failed." */ 1279ae8c6e27Sflorian } 1280ae8c6e27Sflorian else if(ub_event_add(b->eb->slow_accept, &tv) 1281ae8c6e27Sflorian != 0) { 1282ae8c6e27Sflorian /* we do not want to log here, 1283ae8c6e27Sflorian * error: "event_add failed." */ 1284ae8c6e27Sflorian } 12855c45b740Sflorian } else { 12865c45b740Sflorian log_err("accept, with no slow down, " 12875c45b740Sflorian "failed: %s", sock_strerror(errno)); 1288ae8c6e27Sflorian } 1289ae8c6e27Sflorian return -1; 1290ae8c6e27Sflorian } 1291ae8c6e27Sflorian #endif 1292ae8c6e27Sflorian #else /* USE_WINSOCK */ 1293ae8c6e27Sflorian if(WSAGetLastError() == WSAEINPROGRESS || 1294ae8c6e27Sflorian WSAGetLastError() == WSAECONNRESET) 1295ae8c6e27Sflorian return -1; 1296ae8c6e27Sflorian if(WSAGetLastError() == WSAEWOULDBLOCK) { 1297ae8c6e27Sflorian ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_READ); 1298ae8c6e27Sflorian return -1; 1299ae8c6e27Sflorian } 1300ae8c6e27Sflorian #endif 1301f4f0f0ceSflorian log_err_addr("accept failed", sock_strerror(errno), addr, 1302f4f0f0ceSflorian *addrlen); 1303ae8c6e27Sflorian return -1; 1304ae8c6e27Sflorian } 1305ae8c6e27Sflorian if(c->tcp_conn_limit && c->type == comm_tcp_accept) { 1306ae8c6e27Sflorian c->tcl_addr = tcl_addr_lookup(c->tcp_conn_limit, addr, *addrlen); 1307ae8c6e27Sflorian if(!tcl_new_connection(c->tcl_addr)) { 1308ae8c6e27Sflorian if(verbosity >= 3) 1309ae8c6e27Sflorian log_err_addr("accept rejected", 1310ae8c6e27Sflorian "connection limit exceeded", addr, *addrlen); 1311ae8c6e27Sflorian close(new_fd); 1312ae8c6e27Sflorian return -1; 1313ae8c6e27Sflorian } 1314ae8c6e27Sflorian } 1315ae8c6e27Sflorian #ifndef HAVE_ACCEPT4 1316ae8c6e27Sflorian fd_set_nonblock(new_fd); 1317ae8c6e27Sflorian #endif 1318ae8c6e27Sflorian return new_fd; 1319ae8c6e27Sflorian } 1320ae8c6e27Sflorian 1321ae8c6e27Sflorian #ifdef USE_WINSOCK 1322ae8c6e27Sflorian static long win_bio_cb(BIO *b, int oper, const char* ATTR_UNUSED(argp), 1323a1a7ba80Sflorian #ifdef HAVE_BIO_SET_CALLBACK_EX 1324a1a7ba80Sflorian size_t ATTR_UNUSED(len), 1325a1a7ba80Sflorian #endif 1326a1a7ba80Sflorian int ATTR_UNUSED(argi), long argl, 1327a1a7ba80Sflorian #ifndef HAVE_BIO_SET_CALLBACK_EX 1328a1a7ba80Sflorian long retvalue 1329a1a7ba80Sflorian #else 1330a1a7ba80Sflorian int retvalue, size_t* ATTR_UNUSED(processed) 1331a1a7ba80Sflorian #endif 1332a1a7ba80Sflorian ) 1333ae8c6e27Sflorian { 1334ae8c6e27Sflorian int wsa_err = WSAGetLastError(); /* store errcode before it is gone */ 1335ae8c6e27Sflorian verbose(VERB_ALGO, "bio_cb %d, %s %s %s", oper, 1336ae8c6e27Sflorian (oper&BIO_CB_RETURN)?"return":"before", 1337ae8c6e27Sflorian (oper&BIO_CB_READ)?"read":((oper&BIO_CB_WRITE)?"write":"other"), 1338ae8c6e27Sflorian wsa_err==WSAEWOULDBLOCK?"wsawb":""); 1339ae8c6e27Sflorian /* on windows, check if previous operation caused EWOULDBLOCK */ 1340ae8c6e27Sflorian if( (oper == (BIO_CB_READ|BIO_CB_RETURN) && argl == 0) || 1341ae8c6e27Sflorian (oper == (BIO_CB_GETS|BIO_CB_RETURN) && argl == 0)) { 1342ae8c6e27Sflorian if(wsa_err == WSAEWOULDBLOCK) 1343ae8c6e27Sflorian ub_winsock_tcp_wouldblock((struct ub_event*) 1344ae8c6e27Sflorian BIO_get_callback_arg(b), UB_EV_READ); 1345ae8c6e27Sflorian } 1346ae8c6e27Sflorian if( (oper == (BIO_CB_WRITE|BIO_CB_RETURN) && argl == 0) || 1347ae8c6e27Sflorian (oper == (BIO_CB_PUTS|BIO_CB_RETURN) && argl == 0)) { 1348ae8c6e27Sflorian if(wsa_err == WSAEWOULDBLOCK) 1349ae8c6e27Sflorian ub_winsock_tcp_wouldblock((struct ub_event*) 1350ae8c6e27Sflorian BIO_get_callback_arg(b), UB_EV_WRITE); 1351ae8c6e27Sflorian } 1352ae8c6e27Sflorian /* return original return value */ 1353ae8c6e27Sflorian return retvalue; 1354ae8c6e27Sflorian } 1355ae8c6e27Sflorian 1356ae8c6e27Sflorian /** set win bio callbacks for nonblocking operations */ 1357ae8c6e27Sflorian void 1358ae8c6e27Sflorian comm_point_tcp_win_bio_cb(struct comm_point* c, void* thessl) 1359ae8c6e27Sflorian { 1360ae8c6e27Sflorian SSL* ssl = (SSL*)thessl; 1361ae8c6e27Sflorian /* set them both just in case, but usually they are the same BIO */ 1362a1a7ba80Sflorian #ifdef HAVE_BIO_SET_CALLBACK_EX 1363a1a7ba80Sflorian BIO_set_callback_ex(SSL_get_rbio(ssl), &win_bio_cb); 1364a1a7ba80Sflorian #else 1365ae8c6e27Sflorian BIO_set_callback(SSL_get_rbio(ssl), &win_bio_cb); 1366a1a7ba80Sflorian #endif 1367ae8c6e27Sflorian BIO_set_callback_arg(SSL_get_rbio(ssl), (char*)c->ev->ev); 1368a1a7ba80Sflorian #ifdef HAVE_BIO_SET_CALLBACK_EX 1369a1a7ba80Sflorian BIO_set_callback_ex(SSL_get_wbio(ssl), &win_bio_cb); 1370a1a7ba80Sflorian #else 1371ae8c6e27Sflorian BIO_set_callback(SSL_get_wbio(ssl), &win_bio_cb); 1372a1a7ba80Sflorian #endif 1373ae8c6e27Sflorian BIO_set_callback_arg(SSL_get_wbio(ssl), (char*)c->ev->ev); 1374ae8c6e27Sflorian } 1375ae8c6e27Sflorian #endif 1376ae8c6e27Sflorian 1377f4f0f0ceSflorian #ifdef HAVE_NGHTTP2 1378f4f0f0ceSflorian /** Create http2 session server. Per connection, after TCP accepted.*/ 1379f4f0f0ceSflorian static int http2_session_server_create(struct http2_session* h2_session) 1380f4f0f0ceSflorian { 1381f4f0f0ceSflorian log_assert(h2_session->callbacks); 1382f4f0f0ceSflorian h2_session->is_drop = 0; 1383f4f0f0ceSflorian if(nghttp2_session_server_new(&h2_session->session, 1384f4f0f0ceSflorian h2_session->callbacks, 1385f4f0f0ceSflorian h2_session) == NGHTTP2_ERR_NOMEM) { 1386f4f0f0ceSflorian log_err("failed to create nghttp2 session server"); 1387f4f0f0ceSflorian return 0; 1388f4f0f0ceSflorian } 1389f4f0f0ceSflorian 1390f4f0f0ceSflorian return 1; 1391f4f0f0ceSflorian } 1392f4f0f0ceSflorian 1393f4f0f0ceSflorian /** Submit http2 setting to session. Once per session. */ 1394f4f0f0ceSflorian static int http2_submit_settings(struct http2_session* h2_session) 1395f4f0f0ceSflorian { 1396f4f0f0ceSflorian int ret; 1397f4f0f0ceSflorian nghttp2_settings_entry settings[1] = { 1398f4f0f0ceSflorian {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 1399f4f0f0ceSflorian h2_session->c->http2_max_streams}}; 1400f4f0f0ceSflorian 1401f4f0f0ceSflorian ret = nghttp2_submit_settings(h2_session->session, NGHTTP2_FLAG_NONE, 1402f4f0f0ceSflorian settings, 1); 1403f4f0f0ceSflorian if(ret) { 1404f4f0f0ceSflorian verbose(VERB_QUERY, "http2: submit_settings failed, " 1405f4f0f0ceSflorian "error: %s", nghttp2_strerror(ret)); 1406f4f0f0ceSflorian return 0; 1407f4f0f0ceSflorian } 1408f4f0f0ceSflorian return 1; 1409f4f0f0ceSflorian } 1410f4f0f0ceSflorian #endif /* HAVE_NGHTTP2 */ 1411f4f0f0ceSflorian 1412f4f0f0ceSflorian 1413ae8c6e27Sflorian void 1414ae8c6e27Sflorian comm_point_tcp_accept_callback(int fd, short event, void* arg) 1415ae8c6e27Sflorian { 1416ae8c6e27Sflorian struct comm_point* c = (struct comm_point*)arg, *c_hdl; 1417ae8c6e27Sflorian int new_fd; 1418ae8c6e27Sflorian log_assert(c->type == comm_tcp_accept); 1419ae8c6e27Sflorian if(!(event & UB_EV_READ)) { 1420ae8c6e27Sflorian log_info("ignoring tcp accept event %d", (int)event); 1421ae8c6e27Sflorian return; 1422ae8c6e27Sflorian } 1423ae8c6e27Sflorian ub_comm_base_now(c->ev->base); 1424ae8c6e27Sflorian /* find free tcp handler. */ 1425ae8c6e27Sflorian if(!c->tcp_free) { 1426ae8c6e27Sflorian log_warn("accepted too many tcp, connections full"); 1427ae8c6e27Sflorian return; 1428ae8c6e27Sflorian } 1429ae8c6e27Sflorian /* accept incoming connection. */ 1430ae8c6e27Sflorian c_hdl = c->tcp_free; 14319b465e50Sflorian /* clear leftover flags from previous use, and then set the 14329b465e50Sflorian * correct event base for the event structure for libevent */ 14339b465e50Sflorian ub_event_free(c_hdl->ev->ev); 1434a1a7ba80Sflorian c_hdl->ev->ev = NULL; 1435853e076fSflorian if((c_hdl->type == comm_tcp && c_hdl->tcp_req_info) || 1436853e076fSflorian c_hdl->type == comm_local || c_hdl->type == comm_raw) 1437853e076fSflorian c_hdl->tcp_do_toggle_rw = 0; 1438853e076fSflorian else c_hdl->tcp_do_toggle_rw = 1; 1439f4f0f0ceSflorian 1440f4f0f0ceSflorian if(c_hdl->type == comm_http) { 1441f4f0f0ceSflorian #ifdef HAVE_NGHTTP2 1442f4f0f0ceSflorian if(!c_hdl->h2_session || 1443f4f0f0ceSflorian !http2_session_server_create(c_hdl->h2_session)) { 1444f4f0f0ceSflorian log_warn("failed to create nghttp2"); 1445f4f0f0ceSflorian return; 1446f4f0f0ceSflorian } 1447f4f0f0ceSflorian if(!c_hdl->h2_session || 1448f4f0f0ceSflorian !http2_submit_settings(c_hdl->h2_session)) { 1449f4f0f0ceSflorian log_warn("failed to submit http2 settings"); 1450f4f0f0ceSflorian return; 1451f4f0f0ceSflorian } 1452853e076fSflorian if(!c->ssl) { 1453853e076fSflorian c_hdl->tcp_do_toggle_rw = 0; 1454853e076fSflorian c_hdl->use_h2 = 1; 1455853e076fSflorian } 1456f4f0f0ceSflorian #endif 1457f4f0f0ceSflorian c_hdl->ev->ev = ub_event_new(c_hdl->ev->base->eb->base, -1, 1458f4f0f0ceSflorian UB_EV_PERSIST | UB_EV_READ | UB_EV_TIMEOUT, 1459f4f0f0ceSflorian comm_point_http_handle_callback, c_hdl); 1460f4f0f0ceSflorian } else { 1461f4f0f0ceSflorian c_hdl->ev->ev = ub_event_new(c_hdl->ev->base->eb->base, -1, 1462f4f0f0ceSflorian UB_EV_PERSIST | UB_EV_READ | UB_EV_TIMEOUT, 1463f4f0f0ceSflorian comm_point_tcp_handle_callback, c_hdl); 1464f4f0f0ceSflorian } 14659b465e50Sflorian if(!c_hdl->ev->ev) { 14669b465e50Sflorian log_warn("could not ub_event_new, dropped tcp"); 14679b465e50Sflorian return; 14689b465e50Sflorian } 1469ae8c6e27Sflorian log_assert(fd != -1); 1470ae8c6e27Sflorian (void)fd; 14715c45b740Sflorian new_fd = comm_point_perform_accept(c, &c_hdl->repinfo.remote_addr, 14725c45b740Sflorian &c_hdl->repinfo.remote_addrlen); 1473ae8c6e27Sflorian if(new_fd == -1) 1474ae8c6e27Sflorian return; 14755c45b740Sflorian /* Copy remote_address to client_address. 14765c45b740Sflorian * Simplest way/time for streams to do that. */ 14775c45b740Sflorian c_hdl->repinfo.client_addrlen = c_hdl->repinfo.remote_addrlen; 14785c45b740Sflorian memmove(&c_hdl->repinfo.client_addr, 14795c45b740Sflorian &c_hdl->repinfo.remote_addr, 14805c45b740Sflorian c_hdl->repinfo.remote_addrlen); 1481ae8c6e27Sflorian if(c->ssl) { 1482ae8c6e27Sflorian c_hdl->ssl = incoming_ssl_fd(c->ssl, new_fd); 1483ae8c6e27Sflorian if(!c_hdl->ssl) { 1484ae8c6e27Sflorian c_hdl->fd = new_fd; 1485ae8c6e27Sflorian comm_point_close(c_hdl); 1486ae8c6e27Sflorian return; 1487ae8c6e27Sflorian } 1488ae8c6e27Sflorian c_hdl->ssl_shake_state = comm_ssl_shake_read; 1489ae8c6e27Sflorian #ifdef USE_WINSOCK 1490ae8c6e27Sflorian comm_point_tcp_win_bio_cb(c_hdl, c_hdl->ssl); 1491ae8c6e27Sflorian #endif 1492ae8c6e27Sflorian } 1493ae8c6e27Sflorian 1494ae8c6e27Sflorian /* grab the tcp handler buffers */ 1495ae8c6e27Sflorian c->cur_tcp_count++; 1496ae8c6e27Sflorian c->tcp_free = c_hdl->tcp_free; 1497a1a7ba80Sflorian c_hdl->tcp_free = NULL; 1498ae8c6e27Sflorian if(!c->tcp_free) { 1499ae8c6e27Sflorian /* stop accepting incoming queries for now. */ 1500ae8c6e27Sflorian comm_point_stop_listening(c); 1501ae8c6e27Sflorian } 1502ae8c6e27Sflorian setup_tcp_handler(c_hdl, new_fd, c->cur_tcp_count, c->max_tcp_count); 1503ae8c6e27Sflorian } 1504ae8c6e27Sflorian 1505ae8c6e27Sflorian /** Make tcp handler free for next assignment */ 1506ae8c6e27Sflorian static void 1507ae8c6e27Sflorian reclaim_tcp_handler(struct comm_point* c) 1508ae8c6e27Sflorian { 1509ae8c6e27Sflorian log_assert(c->type == comm_tcp); 1510ae8c6e27Sflorian if(c->ssl) { 1511ae8c6e27Sflorian #ifdef HAVE_SSL 1512ae8c6e27Sflorian SSL_shutdown(c->ssl); 1513ae8c6e27Sflorian SSL_free(c->ssl); 1514ae8c6e27Sflorian c->ssl = NULL; 1515ae8c6e27Sflorian #endif 1516ae8c6e27Sflorian } 1517ae8c6e27Sflorian comm_point_close(c); 1518ae8c6e27Sflorian if(c->tcp_parent) { 1519a1a7ba80Sflorian if(c != c->tcp_parent->tcp_free) { 1520ae8c6e27Sflorian c->tcp_parent->cur_tcp_count--; 1521ae8c6e27Sflorian c->tcp_free = c->tcp_parent->tcp_free; 1522ae8c6e27Sflorian c->tcp_parent->tcp_free = c; 1523a1a7ba80Sflorian } 1524ae8c6e27Sflorian if(!c->tcp_free) { 1525ae8c6e27Sflorian /* re-enable listening on accept socket */ 1526ae8c6e27Sflorian comm_point_start_listening(c->tcp_parent, -1, -1); 1527ae8c6e27Sflorian } 1528ae8c6e27Sflorian } 1529853e076fSflorian c->tcp_more_read_again = NULL; 1530853e076fSflorian c->tcp_more_write_again = NULL; 1531a1a7ba80Sflorian c->tcp_byte_count = 0; 15325c45b740Sflorian c->pp2_header_state = pp2_header_none; 1533a1a7ba80Sflorian sldns_buffer_clear(c->buffer); 1534ae8c6e27Sflorian } 1535ae8c6e27Sflorian 1536ae8c6e27Sflorian /** do the callback when writing is done */ 1537ae8c6e27Sflorian static void 1538ae8c6e27Sflorian tcp_callback_writer(struct comm_point* c) 1539ae8c6e27Sflorian { 1540ae8c6e27Sflorian log_assert(c->type == comm_tcp); 1541853e076fSflorian if(!c->tcp_write_and_read) { 1542ae8c6e27Sflorian sldns_buffer_clear(c->buffer); 1543853e076fSflorian c->tcp_byte_count = 0; 1544853e076fSflorian } 1545ae8c6e27Sflorian if(c->tcp_do_toggle_rw) 1546ae8c6e27Sflorian c->tcp_is_reading = 1; 1547ae8c6e27Sflorian /* switch from listening(write) to listening(read) */ 1548e97c6e54Ssthen if(c->tcp_req_info) { 1549e97c6e54Ssthen tcp_req_info_handle_writedone(c->tcp_req_info); 1550e97c6e54Ssthen } else { 1551988ebc2dSflorian comm_point_stop_listening(c); 1552853e076fSflorian if(c->tcp_write_and_read) { 1553853e076fSflorian fptr_ok(fptr_whitelist_comm_point(c->callback)); 1554853e076fSflorian if( (*c->callback)(c, c->cb_arg, NETEVENT_PKT_WRITTEN, 1555853e076fSflorian &c->repinfo) ) { 1556853e076fSflorian comm_point_start_listening(c, -1, 1557a8eaceedSflorian adjusted_tcp_timeout(c)); 1558853e076fSflorian } 1559853e076fSflorian } else { 1560a8eaceedSflorian comm_point_start_listening(c, -1, 1561a8eaceedSflorian adjusted_tcp_timeout(c)); 1562ae8c6e27Sflorian } 1563e97c6e54Ssthen } 1564853e076fSflorian } 1565ae8c6e27Sflorian 1566ae8c6e27Sflorian /** do the callback when reading is done */ 1567ae8c6e27Sflorian static void 1568ae8c6e27Sflorian tcp_callback_reader(struct comm_point* c) 1569ae8c6e27Sflorian { 1570ae8c6e27Sflorian log_assert(c->type == comm_tcp || c->type == comm_local); 1571ae8c6e27Sflorian sldns_buffer_flip(c->buffer); 1572ae8c6e27Sflorian if(c->tcp_do_toggle_rw) 1573ae8c6e27Sflorian c->tcp_is_reading = 0; 1574ae8c6e27Sflorian c->tcp_byte_count = 0; 1575e97c6e54Ssthen if(c->tcp_req_info) { 1576e97c6e54Ssthen tcp_req_info_handle_readdone(c->tcp_req_info); 1577e97c6e54Ssthen } else { 1578988ebc2dSflorian if(c->type == comm_tcp) 1579988ebc2dSflorian comm_point_stop_listening(c); 1580ae8c6e27Sflorian fptr_ok(fptr_whitelist_comm_point(c->callback)); 1581ae8c6e27Sflorian if( (*c->callback)(c, c->cb_arg, NETEVENT_NOERROR, &c->repinfo) ) { 1582a8eaceedSflorian comm_point_start_listening(c, -1, 1583a8eaceedSflorian adjusted_tcp_timeout(c)); 1584ae8c6e27Sflorian } 1585ae8c6e27Sflorian } 1586e97c6e54Ssthen } 1587ae8c6e27Sflorian 1588ae8c6e27Sflorian #ifdef HAVE_SSL 158957403691Sflorian /** true if the ssl handshake error has to be squelched from the logs */ 1590e47fef9eSflorian int 159157403691Sflorian squelch_err_ssl_handshake(unsigned long err) 159257403691Sflorian { 159357403691Sflorian if(verbosity >= VERB_QUERY) 159457403691Sflorian return 0; /* only squelch on low verbosity */ 15957a05b9dfSflorian if(ERR_GET_LIB(err) == ERR_LIB_SSL && 15967a05b9dfSflorian (ERR_GET_REASON(err) == SSL_R_HTTPS_PROXY_REQUEST || 15977a05b9dfSflorian ERR_GET_REASON(err) == SSL_R_HTTP_REQUEST || 15987a05b9dfSflorian ERR_GET_REASON(err) == SSL_R_WRONG_VERSION_NUMBER || 15997a05b9dfSflorian ERR_GET_REASON(err) == SSL_R_SSLV3_ALERT_BAD_CERTIFICATE 160057403691Sflorian #ifdef SSL_F_TLS_POST_PROCESS_CLIENT_HELLO 16017a05b9dfSflorian || ERR_GET_REASON(err) == SSL_R_NO_SHARED_CIPHER 160257403691Sflorian #endif 160357403691Sflorian #ifdef SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO 16047a05b9dfSflorian || ERR_GET_REASON(err) == SSL_R_UNKNOWN_PROTOCOL 16057a05b9dfSflorian || ERR_GET_REASON(err) == SSL_R_UNSUPPORTED_PROTOCOL 160657403691Sflorian # ifdef SSL_R_VERSION_TOO_LOW 16077a05b9dfSflorian || ERR_GET_REASON(err) == SSL_R_VERSION_TOO_LOW 160857403691Sflorian # endif 160957403691Sflorian #endif 16107a05b9dfSflorian )) 161157403691Sflorian return 1; 161257403691Sflorian return 0; 161357403691Sflorian } 161457403691Sflorian #endif /* HAVE_SSL */ 161557403691Sflorian 1616ae8c6e27Sflorian /** continue ssl handshake */ 1617ae8c6e27Sflorian #ifdef HAVE_SSL 1618ae8c6e27Sflorian static int 1619ae8c6e27Sflorian ssl_handshake(struct comm_point* c) 1620ae8c6e27Sflorian { 1621ae8c6e27Sflorian int r; 1622ae8c6e27Sflorian if(c->ssl_shake_state == comm_ssl_shake_hs_read) { 1623ae8c6e27Sflorian /* read condition satisfied back to writing */ 1624411c5950Sflorian comm_point_listen_for_rw(c, 0, 1); 1625ae8c6e27Sflorian c->ssl_shake_state = comm_ssl_shake_none; 1626ae8c6e27Sflorian return 1; 1627ae8c6e27Sflorian } 1628ae8c6e27Sflorian if(c->ssl_shake_state == comm_ssl_shake_hs_write) { 1629ae8c6e27Sflorian /* write condition satisfied, back to reading */ 1630ae8c6e27Sflorian comm_point_listen_for_rw(c, 1, 0); 1631ae8c6e27Sflorian c->ssl_shake_state = comm_ssl_shake_none; 1632ae8c6e27Sflorian return 1; 1633ae8c6e27Sflorian } 1634ae8c6e27Sflorian 1635ae8c6e27Sflorian ERR_clear_error(); 1636ae8c6e27Sflorian r = SSL_do_handshake(c->ssl); 1637ae8c6e27Sflorian if(r != 1) { 1638ae8c6e27Sflorian int want = SSL_get_error(c->ssl, r); 1639ae8c6e27Sflorian if(want == SSL_ERROR_WANT_READ) { 1640ae8c6e27Sflorian if(c->ssl_shake_state == comm_ssl_shake_read) 1641ae8c6e27Sflorian return 1; 1642ae8c6e27Sflorian c->ssl_shake_state = comm_ssl_shake_read; 1643ae8c6e27Sflorian comm_point_listen_for_rw(c, 1, 0); 1644ae8c6e27Sflorian return 1; 1645ae8c6e27Sflorian } else if(want == SSL_ERROR_WANT_WRITE) { 1646ae8c6e27Sflorian if(c->ssl_shake_state == comm_ssl_shake_write) 1647ae8c6e27Sflorian return 1; 1648ae8c6e27Sflorian c->ssl_shake_state = comm_ssl_shake_write; 1649ae8c6e27Sflorian comm_point_listen_for_rw(c, 0, 1); 1650ae8c6e27Sflorian return 1; 1651ae8c6e27Sflorian } else if(r == 0) { 1652ae8c6e27Sflorian return 0; /* closed */ 1653ae8c6e27Sflorian } else if(want == SSL_ERROR_SYSCALL) { 1654ae8c6e27Sflorian /* SYSCALL and errno==0 means closed uncleanly */ 1655d32eb43cSflorian #ifdef EPIPE 1656d32eb43cSflorian if(errno == EPIPE && verbosity < 2) 1657d32eb43cSflorian return 0; /* silence 'broken pipe' */ 1658d32eb43cSflorian #endif 1659d32eb43cSflorian #ifdef ECONNRESET 1660d32eb43cSflorian if(errno == ECONNRESET && verbosity < 2) 1661d32eb43cSflorian return 0; /* silence reset by peer */ 1662d32eb43cSflorian #endif 16637a05b9dfSflorian if(!tcp_connect_errno_needs_log( 16645c45b740Sflorian (struct sockaddr*)&c->repinfo.remote_addr, 16655c45b740Sflorian c->repinfo.remote_addrlen)) 16667a05b9dfSflorian return 0; /* silence connect failures that 16677a05b9dfSflorian show up because after connect this is the 16687a05b9dfSflorian first system call that accesses the socket */ 1669ae8c6e27Sflorian if(errno != 0) 1670ae8c6e27Sflorian log_err("SSL_handshake syscall: %s", 1671ae8c6e27Sflorian strerror(errno)); 1672ae8c6e27Sflorian return 0; 1673ae8c6e27Sflorian } else { 167457403691Sflorian unsigned long err = ERR_get_error(); 167557403691Sflorian if(!squelch_err_ssl_handshake(err)) { 167654cc57acSflorian long vr; 167754cc57acSflorian log_crypto_err_io_code("ssl handshake failed", 167854cc57acSflorian want, err); 167954cc57acSflorian if((vr=SSL_get_verify_result(c->ssl)) != 0) 168054cc57acSflorian log_err("ssl handshake cert error: %s", 168154cc57acSflorian X509_verify_cert_error_string( 168254cc57acSflorian vr)); 16835c45b740Sflorian log_addr(VERB_OPS, "ssl handshake failed", 16845c45b740Sflorian &c->repinfo.remote_addr, 16855c45b740Sflorian c->repinfo.remote_addrlen); 168657403691Sflorian } 1687ae8c6e27Sflorian return 0; 1688ae8c6e27Sflorian } 1689ae8c6e27Sflorian } 1690ae8c6e27Sflorian /* this is where peer verification could take place */ 1691ae8c6e27Sflorian if((SSL_get_verify_mode(c->ssl)&SSL_VERIFY_PEER)) { 1692ae8c6e27Sflorian /* verification */ 1693ae8c6e27Sflorian if(SSL_get_verify_result(c->ssl) == X509_V_OK) { 1694411c5950Sflorian #ifdef HAVE_SSL_GET1_PEER_CERTIFICATE 1695411c5950Sflorian X509* x = SSL_get1_peer_certificate(c->ssl); 1696411c5950Sflorian #else 1697ae8c6e27Sflorian X509* x = SSL_get_peer_certificate(c->ssl); 1698411c5950Sflorian #endif 1699ae8c6e27Sflorian if(!x) { 1700ae8c6e27Sflorian log_addr(VERB_ALGO, "SSL connection failed: " 1701ae8c6e27Sflorian "no certificate", 17025c45b740Sflorian &c->repinfo.remote_addr, 17035c45b740Sflorian c->repinfo.remote_addrlen); 1704ae8c6e27Sflorian return 0; 1705ae8c6e27Sflorian } 1706ae8c6e27Sflorian log_cert(VERB_ALGO, "peer certificate", x); 1707ae8c6e27Sflorian #ifdef HAVE_SSL_GET0_PEERNAME 1708ae8c6e27Sflorian if(SSL_get0_peername(c->ssl)) { 1709ae8c6e27Sflorian char buf[255]; 1710ae8c6e27Sflorian snprintf(buf, sizeof(buf), "SSL connection " 1711ae8c6e27Sflorian "to %s authenticated", 1712ae8c6e27Sflorian SSL_get0_peername(c->ssl)); 17135c45b740Sflorian log_addr(VERB_ALGO, buf, &c->repinfo.remote_addr, 17145c45b740Sflorian c->repinfo.remote_addrlen); 1715ae8c6e27Sflorian } else { 1716ae8c6e27Sflorian #endif 1717ae8c6e27Sflorian log_addr(VERB_ALGO, "SSL connection " 17185c45b740Sflorian "authenticated", &c->repinfo.remote_addr, 17195c45b740Sflorian c->repinfo.remote_addrlen); 1720ae8c6e27Sflorian #ifdef HAVE_SSL_GET0_PEERNAME 1721ae8c6e27Sflorian } 1722ae8c6e27Sflorian #endif 1723ae8c6e27Sflorian X509_free(x); 1724ae8c6e27Sflorian } else { 1725411c5950Sflorian #ifdef HAVE_SSL_GET1_PEER_CERTIFICATE 1726411c5950Sflorian X509* x = SSL_get1_peer_certificate(c->ssl); 1727411c5950Sflorian #else 1728ae8c6e27Sflorian X509* x = SSL_get_peer_certificate(c->ssl); 1729411c5950Sflorian #endif 1730ae8c6e27Sflorian if(x) { 1731ae8c6e27Sflorian log_cert(VERB_ALGO, "peer certificate", x); 1732ae8c6e27Sflorian X509_free(x); 1733ae8c6e27Sflorian } 1734ae8c6e27Sflorian log_addr(VERB_ALGO, "SSL connection failed: " 1735ae8c6e27Sflorian "failed to authenticate", 17365c45b740Sflorian &c->repinfo.remote_addr, 17375c45b740Sflorian c->repinfo.remote_addrlen); 1738ae8c6e27Sflorian return 0; 1739ae8c6e27Sflorian } 1740ae8c6e27Sflorian } else { 1741ae8c6e27Sflorian /* unauthenticated, the verify peer flag was not set 1742ae8c6e27Sflorian * in c->ssl when the ssl object was created from ssl_ctx */ 17435c45b740Sflorian log_addr(VERB_ALGO, "SSL connection", &c->repinfo.remote_addr, 17445c45b740Sflorian c->repinfo.remote_addrlen); 1745ae8c6e27Sflorian } 1746ae8c6e27Sflorian 1747411c5950Sflorian #ifdef HAVE_SSL_GET0_ALPN_SELECTED 1748f4f0f0ceSflorian /* check if http2 use is negotiated */ 1749f4f0f0ceSflorian if(c->type == comm_http && c->h2_session) { 1750f4f0f0ceSflorian const unsigned char *alpn; 1751f4f0f0ceSflorian unsigned int alpnlen = 0; 1752f4f0f0ceSflorian SSL_get0_alpn_selected(c->ssl, &alpn, &alpnlen); 1753f4f0f0ceSflorian if(alpnlen == 2 && memcmp("h2", alpn, 2) == 0) { 1754f4f0f0ceSflorian /* connection upgraded to HTTP2 */ 1755f4f0f0ceSflorian c->tcp_do_toggle_rw = 0; 1756f4f0f0ceSflorian c->use_h2 = 1; 175754cc57acSflorian } else { 175854cc57acSflorian verbose(VERB_ALGO, "client doesn't support HTTP/2"); 175954cc57acSflorian return 0; 1760f4f0f0ceSflorian } 1761f4f0f0ceSflorian } 1762411c5950Sflorian #endif 1763f4f0f0ceSflorian 1764ae8c6e27Sflorian /* setup listen rw correctly */ 1765ae8c6e27Sflorian if(c->tcp_is_reading) { 1766ae8c6e27Sflorian if(c->ssl_shake_state != comm_ssl_shake_read) 1767ae8c6e27Sflorian comm_point_listen_for_rw(c, 1, 0); 1768ae8c6e27Sflorian } else { 1769411c5950Sflorian comm_point_listen_for_rw(c, 0, 1); 1770ae8c6e27Sflorian } 1771ae8c6e27Sflorian c->ssl_shake_state = comm_ssl_shake_none; 1772ae8c6e27Sflorian return 1; 1773ae8c6e27Sflorian } 1774ae8c6e27Sflorian #endif /* HAVE_SSL */ 1775ae8c6e27Sflorian 1776ae8c6e27Sflorian /** ssl read callback on TCP */ 1777ae8c6e27Sflorian static int 1778ae8c6e27Sflorian ssl_handle_read(struct comm_point* c) 1779ae8c6e27Sflorian { 1780ae8c6e27Sflorian #ifdef HAVE_SSL 1781ae8c6e27Sflorian int r; 1782ae8c6e27Sflorian if(c->ssl_shake_state != comm_ssl_shake_none) { 1783ae8c6e27Sflorian if(!ssl_handshake(c)) 1784ae8c6e27Sflorian return 0; 1785ae8c6e27Sflorian if(c->ssl_shake_state != comm_ssl_shake_none) 1786ae8c6e27Sflorian return 1; 1787ae8c6e27Sflorian } 17885c45b740Sflorian if(c->pp2_enabled && c->pp2_header_state != pp2_header_done) { 17895c45b740Sflorian struct pp2_header* header = NULL; 17905c45b740Sflorian size_t want_read_size = 0; 17915c45b740Sflorian size_t current_read_size = 0; 17925c45b740Sflorian if(c->pp2_header_state == pp2_header_none) { 17935c45b740Sflorian want_read_size = PP2_HEADER_SIZE; 17945c45b740Sflorian if(sldns_buffer_remaining(c->buffer)<want_read_size) { 17955c45b740Sflorian log_err_addr("proxy_protocol: not enough " 17965c45b740Sflorian "buffer size to read PROXYv2 header", "", 17975c45b740Sflorian &c->repinfo.remote_addr, 17985c45b740Sflorian c->repinfo.remote_addrlen); 17995c45b740Sflorian return 0; 18005c45b740Sflorian } 18015c45b740Sflorian verbose(VERB_ALGO, "proxy_protocol: reading fixed " 18025c45b740Sflorian "part of PROXYv2 header (len %lu)", 18035c45b740Sflorian (unsigned long)want_read_size); 18045c45b740Sflorian current_read_size = want_read_size; 18055c45b740Sflorian if(c->tcp_byte_count < current_read_size) { 18065c45b740Sflorian ERR_clear_error(); 18075c45b740Sflorian if((r=SSL_read(c->ssl, (void*)sldns_buffer_at( 18085c45b740Sflorian c->buffer, c->tcp_byte_count), 18095c45b740Sflorian current_read_size - 18105c45b740Sflorian c->tcp_byte_count)) <= 0) { 18115c45b740Sflorian int want = SSL_get_error(c->ssl, r); 18125c45b740Sflorian if(want == SSL_ERROR_ZERO_RETURN) { 18135c45b740Sflorian if(c->tcp_req_info) 18145c45b740Sflorian return tcp_req_info_handle_read_close(c->tcp_req_info); 18155c45b740Sflorian return 0; /* shutdown, closed */ 18165c45b740Sflorian } else if(want == SSL_ERROR_WANT_READ) { 18175c45b740Sflorian #ifdef USE_WINSOCK 18185c45b740Sflorian ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_READ); 18195c45b740Sflorian #endif 18205c45b740Sflorian return 1; /* read more later */ 18215c45b740Sflorian } else if(want == SSL_ERROR_WANT_WRITE) { 18225c45b740Sflorian c->ssl_shake_state = comm_ssl_shake_hs_write; 18235c45b740Sflorian comm_point_listen_for_rw(c, 0, 1); 18245c45b740Sflorian return 1; 18255c45b740Sflorian } else if(want == SSL_ERROR_SYSCALL) { 18265c45b740Sflorian #ifdef ECONNRESET 18275c45b740Sflorian if(errno == ECONNRESET && verbosity < 2) 18285c45b740Sflorian return 0; /* silence reset by peer */ 18295c45b740Sflorian #endif 18305c45b740Sflorian if(errno != 0) 18315c45b740Sflorian log_err("SSL_read syscall: %s", 18325c45b740Sflorian strerror(errno)); 18335c45b740Sflorian return 0; 18345c45b740Sflorian } 183554cc57acSflorian log_crypto_err_io("could not SSL_read", 183654cc57acSflorian want); 18375c45b740Sflorian return 0; 18385c45b740Sflorian } 18395c45b740Sflorian c->tcp_byte_count += r; 184054cc57acSflorian sldns_buffer_skip(c->buffer, r); 18415c45b740Sflorian if(c->tcp_byte_count != current_read_size) return 1; 18425c45b740Sflorian c->pp2_header_state = pp2_header_init; 18435c45b740Sflorian } 18445c45b740Sflorian } 18455c45b740Sflorian if(c->pp2_header_state == pp2_header_init) { 184654cc57acSflorian int err; 184754cc57acSflorian err = pp2_read_header( 184854cc57acSflorian sldns_buffer_begin(c->buffer), 184954cc57acSflorian sldns_buffer_limit(c->buffer)); 185054cc57acSflorian if(err) { 18515c45b740Sflorian log_err("proxy_protocol: could not parse " 185254cc57acSflorian "PROXYv2 header (%s)", 185354cc57acSflorian pp_lookup_error(err)); 18545c45b740Sflorian return 0; 18555c45b740Sflorian } 185654cc57acSflorian header = (struct pp2_header*)sldns_buffer_begin(c->buffer); 18575c45b740Sflorian want_read_size = ntohs(header->len); 185854cc57acSflorian if(sldns_buffer_limit(c->buffer) < 18595c45b740Sflorian PP2_HEADER_SIZE + want_read_size) { 18605c45b740Sflorian log_err_addr("proxy_protocol: not enough " 18615c45b740Sflorian "buffer size to read PROXYv2 header", "", 18625c45b740Sflorian &c->repinfo.remote_addr, 18635c45b740Sflorian c->repinfo.remote_addrlen); 18645c45b740Sflorian return 0; 18655c45b740Sflorian } 18665c45b740Sflorian verbose(VERB_ALGO, "proxy_protocol: reading variable " 18675c45b740Sflorian "part of PROXYv2 header (len %lu)", 18685c45b740Sflorian (unsigned long)want_read_size); 18695c45b740Sflorian current_read_size = PP2_HEADER_SIZE + want_read_size; 18705c45b740Sflorian if(want_read_size == 0) { 18715c45b740Sflorian /* nothing more to read; header is complete */ 18725c45b740Sflorian c->pp2_header_state = pp2_header_done; 18735c45b740Sflorian } else if(c->tcp_byte_count < current_read_size) { 18745c45b740Sflorian ERR_clear_error(); 18755c45b740Sflorian if((r=SSL_read(c->ssl, (void*)sldns_buffer_at( 18765c45b740Sflorian c->buffer, c->tcp_byte_count), 18775c45b740Sflorian current_read_size - 18785c45b740Sflorian c->tcp_byte_count)) <= 0) { 18795c45b740Sflorian int want = SSL_get_error(c->ssl, r); 18805c45b740Sflorian if(want == SSL_ERROR_ZERO_RETURN) { 18815c45b740Sflorian if(c->tcp_req_info) 18825c45b740Sflorian return tcp_req_info_handle_read_close(c->tcp_req_info); 18835c45b740Sflorian return 0; /* shutdown, closed */ 18845c45b740Sflorian } else if(want == SSL_ERROR_WANT_READ) { 18855c45b740Sflorian #ifdef USE_WINSOCK 18865c45b740Sflorian ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_READ); 18875c45b740Sflorian #endif 18885c45b740Sflorian return 1; /* read more later */ 18895c45b740Sflorian } else if(want == SSL_ERROR_WANT_WRITE) { 18905c45b740Sflorian c->ssl_shake_state = comm_ssl_shake_hs_write; 18915c45b740Sflorian comm_point_listen_for_rw(c, 0, 1); 18925c45b740Sflorian return 1; 18935c45b740Sflorian } else if(want == SSL_ERROR_SYSCALL) { 18945c45b740Sflorian #ifdef ECONNRESET 18955c45b740Sflorian if(errno == ECONNRESET && verbosity < 2) 18965c45b740Sflorian return 0; /* silence reset by peer */ 18975c45b740Sflorian #endif 18985c45b740Sflorian if(errno != 0) 18995c45b740Sflorian log_err("SSL_read syscall: %s", 19005c45b740Sflorian strerror(errno)); 19015c45b740Sflorian return 0; 19025c45b740Sflorian } 190354cc57acSflorian log_crypto_err_io("could not SSL_read", 190454cc57acSflorian want); 19055c45b740Sflorian return 0; 19065c45b740Sflorian } 19075c45b740Sflorian c->tcp_byte_count += r; 190854cc57acSflorian sldns_buffer_skip(c->buffer, r); 19095c45b740Sflorian if(c->tcp_byte_count != current_read_size) return 1; 19105c45b740Sflorian c->pp2_header_state = pp2_header_done; 19115c45b740Sflorian } 19125c45b740Sflorian } 19135c45b740Sflorian if(c->pp2_header_state != pp2_header_done || !header) { 19145c45b740Sflorian log_err_addr("proxy_protocol: wrong state for the " 19155c45b740Sflorian "PROXYv2 header", "", &c->repinfo.remote_addr, 19165c45b740Sflorian c->repinfo.remote_addrlen); 19175c45b740Sflorian return 0; 19185c45b740Sflorian } 191954cc57acSflorian sldns_buffer_flip(c->buffer); 19205c45b740Sflorian if(!consume_pp2_header(c->buffer, &c->repinfo, 1)) { 19215c45b740Sflorian log_err_addr("proxy_protocol: could not consume " 19225c45b740Sflorian "PROXYv2 header", "", &c->repinfo.remote_addr, 19235c45b740Sflorian c->repinfo.remote_addrlen); 19245c45b740Sflorian return 0; 19255c45b740Sflorian } 19265c45b740Sflorian verbose(VERB_ALGO, "proxy_protocol: successful read of " 19275c45b740Sflorian "PROXYv2 header"); 19285c45b740Sflorian /* Clear and reset the buffer to read the following 19295c45b740Sflorian * DNS packet(s). */ 19305c45b740Sflorian sldns_buffer_clear(c->buffer); 19315c45b740Sflorian c->tcp_byte_count = 0; 19325c45b740Sflorian return 1; 19335c45b740Sflorian } 1934ae8c6e27Sflorian if(c->tcp_byte_count < sizeof(uint16_t)) { 1935ae8c6e27Sflorian /* read length bytes */ 1936ae8c6e27Sflorian ERR_clear_error(); 1937ae8c6e27Sflorian if((r=SSL_read(c->ssl, (void*)sldns_buffer_at(c->buffer, 1938ae8c6e27Sflorian c->tcp_byte_count), (int)(sizeof(uint16_t) - 1939ae8c6e27Sflorian c->tcp_byte_count))) <= 0) { 1940ae8c6e27Sflorian int want = SSL_get_error(c->ssl, r); 1941ae8c6e27Sflorian if(want == SSL_ERROR_ZERO_RETURN) { 1942e97c6e54Ssthen if(c->tcp_req_info) 1943e97c6e54Ssthen return tcp_req_info_handle_read_close(c->tcp_req_info); 1944ae8c6e27Sflorian return 0; /* shutdown, closed */ 1945ae8c6e27Sflorian } else if(want == SSL_ERROR_WANT_READ) { 1946411c5950Sflorian #ifdef USE_WINSOCK 1947ae8c6e27Sflorian ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_READ); 1948411c5950Sflorian #endif 1949ae8c6e27Sflorian return 1; /* read more later */ 1950ae8c6e27Sflorian } else if(want == SSL_ERROR_WANT_WRITE) { 1951ae8c6e27Sflorian c->ssl_shake_state = comm_ssl_shake_hs_write; 1952ae8c6e27Sflorian comm_point_listen_for_rw(c, 0, 1); 1953ae8c6e27Sflorian return 1; 1954ae8c6e27Sflorian } else if(want == SSL_ERROR_SYSCALL) { 19559b465e50Sflorian #ifdef ECONNRESET 19569b465e50Sflorian if(errno == ECONNRESET && verbosity < 2) 19579b465e50Sflorian return 0; /* silence reset by peer */ 19589b465e50Sflorian #endif 1959ae8c6e27Sflorian if(errno != 0) 1960ae8c6e27Sflorian log_err("SSL_read syscall: %s", 1961ae8c6e27Sflorian strerror(errno)); 1962ae8c6e27Sflorian return 0; 1963ae8c6e27Sflorian } 196454cc57acSflorian log_crypto_err_io("could not SSL_read", want); 1965ae8c6e27Sflorian return 0; 1966ae8c6e27Sflorian } 1967ae8c6e27Sflorian c->tcp_byte_count += r; 1968ae8c6e27Sflorian if(c->tcp_byte_count < sizeof(uint16_t)) 1969ae8c6e27Sflorian return 1; 1970ae8c6e27Sflorian if(sldns_buffer_read_u16_at(c->buffer, 0) > 1971ae8c6e27Sflorian sldns_buffer_capacity(c->buffer)) { 1972ae8c6e27Sflorian verbose(VERB_QUERY, "ssl: dropped larger than buffer"); 1973ae8c6e27Sflorian return 0; 1974ae8c6e27Sflorian } 1975ae8c6e27Sflorian sldns_buffer_set_limit(c->buffer, 1976ae8c6e27Sflorian sldns_buffer_read_u16_at(c->buffer, 0)); 1977ae8c6e27Sflorian if(sldns_buffer_limit(c->buffer) < LDNS_HEADER_SIZE) { 1978ae8c6e27Sflorian verbose(VERB_QUERY, "ssl: dropped bogus too short."); 1979ae8c6e27Sflorian return 0; 1980ae8c6e27Sflorian } 1981ae8c6e27Sflorian sldns_buffer_skip(c->buffer, (ssize_t)(c->tcp_byte_count-sizeof(uint16_t))); 1982ae8c6e27Sflorian verbose(VERB_ALGO, "Reading ssl tcp query of length %d", 1983ae8c6e27Sflorian (int)sldns_buffer_limit(c->buffer)); 1984ae8c6e27Sflorian } 1985ae8c6e27Sflorian if(sldns_buffer_remaining(c->buffer) > 0) { 1986ae8c6e27Sflorian ERR_clear_error(); 1987ae8c6e27Sflorian r = SSL_read(c->ssl, (void*)sldns_buffer_current(c->buffer), 1988ae8c6e27Sflorian (int)sldns_buffer_remaining(c->buffer)); 1989ae8c6e27Sflorian if(r <= 0) { 1990ae8c6e27Sflorian int want = SSL_get_error(c->ssl, r); 1991ae8c6e27Sflorian if(want == SSL_ERROR_ZERO_RETURN) { 1992e97c6e54Ssthen if(c->tcp_req_info) 1993e97c6e54Ssthen return tcp_req_info_handle_read_close(c->tcp_req_info); 1994ae8c6e27Sflorian return 0; /* shutdown, closed */ 1995ae8c6e27Sflorian } else if(want == SSL_ERROR_WANT_READ) { 1996411c5950Sflorian #ifdef USE_WINSOCK 1997ae8c6e27Sflorian ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_READ); 1998411c5950Sflorian #endif 1999ae8c6e27Sflorian return 1; /* read more later */ 2000ae8c6e27Sflorian } else if(want == SSL_ERROR_WANT_WRITE) { 2001ae8c6e27Sflorian c->ssl_shake_state = comm_ssl_shake_hs_write; 2002ae8c6e27Sflorian comm_point_listen_for_rw(c, 0, 1); 2003ae8c6e27Sflorian return 1; 2004ae8c6e27Sflorian } else if(want == SSL_ERROR_SYSCALL) { 20059b465e50Sflorian #ifdef ECONNRESET 20069b465e50Sflorian if(errno == ECONNRESET && verbosity < 2) 20079b465e50Sflorian return 0; /* silence reset by peer */ 20089b465e50Sflorian #endif 2009ae8c6e27Sflorian if(errno != 0) 2010ae8c6e27Sflorian log_err("SSL_read syscall: %s", 2011ae8c6e27Sflorian strerror(errno)); 2012ae8c6e27Sflorian return 0; 2013ae8c6e27Sflorian } 201454cc57acSflorian log_crypto_err_io("could not SSL_read", want); 2015ae8c6e27Sflorian return 0; 2016ae8c6e27Sflorian } 2017ae8c6e27Sflorian sldns_buffer_skip(c->buffer, (ssize_t)r); 2018ae8c6e27Sflorian } 2019ae8c6e27Sflorian if(sldns_buffer_remaining(c->buffer) <= 0) { 2020ae8c6e27Sflorian tcp_callback_reader(c); 2021ae8c6e27Sflorian } 2022ae8c6e27Sflorian return 1; 2023ae8c6e27Sflorian #else 2024ae8c6e27Sflorian (void)c; 2025ae8c6e27Sflorian return 0; 2026ae8c6e27Sflorian #endif /* HAVE_SSL */ 2027ae8c6e27Sflorian } 2028ae8c6e27Sflorian 2029ae8c6e27Sflorian /** ssl write callback on TCP */ 2030ae8c6e27Sflorian static int 2031ae8c6e27Sflorian ssl_handle_write(struct comm_point* c) 2032ae8c6e27Sflorian { 2033ae8c6e27Sflorian #ifdef HAVE_SSL 2034ae8c6e27Sflorian int r; 2035ae8c6e27Sflorian if(c->ssl_shake_state != comm_ssl_shake_none) { 2036ae8c6e27Sflorian if(!ssl_handshake(c)) 2037ae8c6e27Sflorian return 0; 2038ae8c6e27Sflorian if(c->ssl_shake_state != comm_ssl_shake_none) 2039ae8c6e27Sflorian return 1; 2040ae8c6e27Sflorian } 2041ae8c6e27Sflorian /* ignore return, if fails we may simply block */ 204257403691Sflorian (void)SSL_set_mode(c->ssl, (long)SSL_MODE_ENABLE_PARTIAL_WRITE); 2043853e076fSflorian if((c->tcp_write_and_read?c->tcp_write_byte_count:c->tcp_byte_count) < sizeof(uint16_t)) { 2044853e076fSflorian uint16_t len = htons(c->tcp_write_and_read?c->tcp_write_pkt_len:sldns_buffer_limit(c->buffer)); 2045ae8c6e27Sflorian ERR_clear_error(); 2046853e076fSflorian if(c->tcp_write_and_read) { 2047853e076fSflorian if(c->tcp_write_pkt_len + 2 < LDNS_RR_BUF_SIZE) { 2048853e076fSflorian /* combine the tcp length and the query for 2049853e076fSflorian * write, this emulates writev */ 2050853e076fSflorian uint8_t buf[LDNS_RR_BUF_SIZE]; 2051853e076fSflorian memmove(buf, &len, sizeof(uint16_t)); 2052853e076fSflorian memmove(buf+sizeof(uint16_t), 2053853e076fSflorian c->tcp_write_pkt, 2054853e076fSflorian c->tcp_write_pkt_len); 2055853e076fSflorian r = SSL_write(c->ssl, 2056853e076fSflorian (void*)(buf+c->tcp_write_byte_count), 2057853e076fSflorian c->tcp_write_pkt_len + 2 - 2058853e076fSflorian c->tcp_write_byte_count); 2059853e076fSflorian } else { 2060853e076fSflorian r = SSL_write(c->ssl, 2061853e076fSflorian (void*)(((uint8_t*)&len)+c->tcp_write_byte_count), 2062853e076fSflorian (int)(sizeof(uint16_t)-c->tcp_write_byte_count)); 2063853e076fSflorian } 2064853e076fSflorian } else if(sizeof(uint16_t)+sldns_buffer_remaining(c->buffer) < 2065ae8c6e27Sflorian LDNS_RR_BUF_SIZE) { 2066ae8c6e27Sflorian /* combine the tcp length and the query for write, 2067ae8c6e27Sflorian * this emulates writev */ 2068ae8c6e27Sflorian uint8_t buf[LDNS_RR_BUF_SIZE]; 2069ae8c6e27Sflorian memmove(buf, &len, sizeof(uint16_t)); 2070ae8c6e27Sflorian memmove(buf+sizeof(uint16_t), 2071ae8c6e27Sflorian sldns_buffer_current(c->buffer), 2072ae8c6e27Sflorian sldns_buffer_remaining(c->buffer)); 2073ae8c6e27Sflorian r = SSL_write(c->ssl, (void*)(buf+c->tcp_byte_count), 2074ae8c6e27Sflorian (int)(sizeof(uint16_t)+ 2075ae8c6e27Sflorian sldns_buffer_remaining(c->buffer) 2076ae8c6e27Sflorian - c->tcp_byte_count)); 2077ae8c6e27Sflorian } else { 2078ae8c6e27Sflorian r = SSL_write(c->ssl, 2079ae8c6e27Sflorian (void*)(((uint8_t*)&len)+c->tcp_byte_count), 2080ae8c6e27Sflorian (int)(sizeof(uint16_t)-c->tcp_byte_count)); 2081ae8c6e27Sflorian } 2082ae8c6e27Sflorian if(r <= 0) { 2083ae8c6e27Sflorian int want = SSL_get_error(c->ssl, r); 2084ae8c6e27Sflorian if(want == SSL_ERROR_ZERO_RETURN) { 2085ae8c6e27Sflorian return 0; /* closed */ 2086ae8c6e27Sflorian } else if(want == SSL_ERROR_WANT_READ) { 20879b465e50Sflorian c->ssl_shake_state = comm_ssl_shake_hs_read; 2088ae8c6e27Sflorian comm_point_listen_for_rw(c, 1, 0); 2089ae8c6e27Sflorian return 1; /* wait for read condition */ 2090ae8c6e27Sflorian } else if(want == SSL_ERROR_WANT_WRITE) { 2091411c5950Sflorian #ifdef USE_WINSOCK 2092ae8c6e27Sflorian ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE); 2093411c5950Sflorian #endif 2094ae8c6e27Sflorian return 1; /* write more later */ 2095ae8c6e27Sflorian } else if(want == SSL_ERROR_SYSCALL) { 20969b465e50Sflorian #ifdef EPIPE 20979b465e50Sflorian if(errno == EPIPE && verbosity < 2) 20989b465e50Sflorian return 0; /* silence 'broken pipe' */ 20999b465e50Sflorian #endif 2100ae8c6e27Sflorian if(errno != 0) 2101ae8c6e27Sflorian log_err("SSL_write syscall: %s", 2102ae8c6e27Sflorian strerror(errno)); 2103ae8c6e27Sflorian return 0; 2104ae8c6e27Sflorian } 210554cc57acSflorian log_crypto_err_io("could not SSL_write", want); 2106ae8c6e27Sflorian return 0; 2107ae8c6e27Sflorian } 2108853e076fSflorian if(c->tcp_write_and_read) { 2109853e076fSflorian c->tcp_write_byte_count += r; 2110853e076fSflorian if(c->tcp_write_byte_count < sizeof(uint16_t)) 2111853e076fSflorian return 1; 2112853e076fSflorian } else { 2113ae8c6e27Sflorian c->tcp_byte_count += r; 2114ae8c6e27Sflorian if(c->tcp_byte_count < sizeof(uint16_t)) 2115ae8c6e27Sflorian return 1; 2116ae8c6e27Sflorian sldns_buffer_set_position(c->buffer, c->tcp_byte_count - 2117ae8c6e27Sflorian sizeof(uint16_t)); 2118853e076fSflorian } 2119853e076fSflorian 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)) { 2120ae8c6e27Sflorian tcp_callback_writer(c); 2121ae8c6e27Sflorian return 1; 2122ae8c6e27Sflorian } 2123ae8c6e27Sflorian } 2124853e076fSflorian log_assert(c->tcp_write_and_read || sldns_buffer_remaining(c->buffer) > 0); 2125853e076fSflorian log_assert(!c->tcp_write_and_read || c->tcp_write_byte_count < c->tcp_write_pkt_len + 2); 2126ae8c6e27Sflorian ERR_clear_error(); 2127853e076fSflorian if(c->tcp_write_and_read) { 2128853e076fSflorian r = SSL_write(c->ssl, (void*)(c->tcp_write_pkt + c->tcp_write_byte_count - 2), 2129853e076fSflorian (int)(c->tcp_write_pkt_len + 2 - c->tcp_write_byte_count)); 2130853e076fSflorian } else { 2131ae8c6e27Sflorian r = SSL_write(c->ssl, (void*)sldns_buffer_current(c->buffer), 2132ae8c6e27Sflorian (int)sldns_buffer_remaining(c->buffer)); 2133853e076fSflorian } 2134ae8c6e27Sflorian if(r <= 0) { 2135ae8c6e27Sflorian int want = SSL_get_error(c->ssl, r); 2136ae8c6e27Sflorian if(want == SSL_ERROR_ZERO_RETURN) { 2137ae8c6e27Sflorian return 0; /* closed */ 2138ae8c6e27Sflorian } else if(want == SSL_ERROR_WANT_READ) { 21399b465e50Sflorian c->ssl_shake_state = comm_ssl_shake_hs_read; 2140ae8c6e27Sflorian comm_point_listen_for_rw(c, 1, 0); 2141ae8c6e27Sflorian return 1; /* wait for read condition */ 2142ae8c6e27Sflorian } else if(want == SSL_ERROR_WANT_WRITE) { 2143411c5950Sflorian #ifdef USE_WINSOCK 2144ae8c6e27Sflorian ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE); 2145411c5950Sflorian #endif 2146ae8c6e27Sflorian return 1; /* write more later */ 2147ae8c6e27Sflorian } else if(want == SSL_ERROR_SYSCALL) { 21489b465e50Sflorian #ifdef EPIPE 21499b465e50Sflorian if(errno == EPIPE && verbosity < 2) 21509b465e50Sflorian return 0; /* silence 'broken pipe' */ 21519b465e50Sflorian #endif 2152ae8c6e27Sflorian if(errno != 0) 2153ae8c6e27Sflorian log_err("SSL_write syscall: %s", 2154ae8c6e27Sflorian strerror(errno)); 2155ae8c6e27Sflorian return 0; 2156ae8c6e27Sflorian } 215754cc57acSflorian log_crypto_err_io("could not SSL_write", want); 2158ae8c6e27Sflorian return 0; 2159ae8c6e27Sflorian } 2160853e076fSflorian if(c->tcp_write_and_read) { 2161853e076fSflorian c->tcp_write_byte_count += r; 2162853e076fSflorian } else { 2163ae8c6e27Sflorian sldns_buffer_skip(c->buffer, (ssize_t)r); 2164853e076fSflorian } 2165ae8c6e27Sflorian 2166853e076fSflorian 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)) { 2167ae8c6e27Sflorian tcp_callback_writer(c); 2168ae8c6e27Sflorian } 2169ae8c6e27Sflorian return 1; 2170ae8c6e27Sflorian #else 2171ae8c6e27Sflorian (void)c; 2172ae8c6e27Sflorian return 0; 2173ae8c6e27Sflorian #endif /* HAVE_SSL */ 2174ae8c6e27Sflorian } 2175ae8c6e27Sflorian 2176ae8c6e27Sflorian /** handle ssl tcp connection with dns contents */ 2177ae8c6e27Sflorian static int 2178853e076fSflorian ssl_handle_it(struct comm_point* c, int is_write) 2179ae8c6e27Sflorian { 2180853e076fSflorian /* handle case where renegotiation wants read during write call 2181853e076fSflorian * or write during read calls */ 2182853e076fSflorian if(is_write && c->ssl_shake_state == comm_ssl_shake_hs_write) 2183853e076fSflorian return ssl_handle_read(c); 2184853e076fSflorian else if(!is_write && c->ssl_shake_state == comm_ssl_shake_hs_read) 2185853e076fSflorian return ssl_handle_write(c); 2186853e076fSflorian /* handle read events for read operation and write events for a 2187853e076fSflorian * write operation */ 2188853e076fSflorian else if(!is_write) 2189ae8c6e27Sflorian return ssl_handle_read(c); 2190ae8c6e27Sflorian return ssl_handle_write(c); 2191ae8c6e27Sflorian } 2192ae8c6e27Sflorian 21935c45b740Sflorian /** 21945c45b740Sflorian * Handle tcp reading callback. 2195ae8c6e27Sflorian * @param fd: file descriptor of socket. 2196ae8c6e27Sflorian * @param c: comm point to read from into buffer. 2197ae8c6e27Sflorian * @param short_ok: if true, very short packets are OK (for comm_local). 2198ae8c6e27Sflorian * @return: 0 on error 2199ae8c6e27Sflorian */ 2200ae8c6e27Sflorian static int 2201ae8c6e27Sflorian comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok) 2202ae8c6e27Sflorian { 2203ae8c6e27Sflorian ssize_t r; 22045c45b740Sflorian int recv_initial = 0; 2205ae8c6e27Sflorian log_assert(c->type == comm_tcp || c->type == comm_local); 2206ae8c6e27Sflorian if(c->ssl) 2207853e076fSflorian return ssl_handle_it(c, 0); 2208853e076fSflorian if(!c->tcp_is_reading && !c->tcp_write_and_read) 2209ae8c6e27Sflorian return 0; 2210ae8c6e27Sflorian 2211ae8c6e27Sflorian log_assert(fd != -1); 22125c45b740Sflorian if(c->pp2_enabled && c->pp2_header_state != pp2_header_done) { 22135c45b740Sflorian struct pp2_header* header = NULL; 22145c45b740Sflorian size_t want_read_size = 0; 22155c45b740Sflorian size_t current_read_size = 0; 22165c45b740Sflorian if(c->pp2_header_state == pp2_header_none) { 22175c45b740Sflorian want_read_size = PP2_HEADER_SIZE; 22185c45b740Sflorian if(sldns_buffer_remaining(c->buffer)<want_read_size) { 22195c45b740Sflorian log_err_addr("proxy_protocol: not enough " 22205c45b740Sflorian "buffer size to read PROXYv2 header", "", 22215c45b740Sflorian &c->repinfo.remote_addr, 22225c45b740Sflorian c->repinfo.remote_addrlen); 22235c45b740Sflorian return 0; 22245c45b740Sflorian } 22255c45b740Sflorian verbose(VERB_ALGO, "proxy_protocol: reading fixed " 22265c45b740Sflorian "part of PROXYv2 header (len %lu)", 22275c45b740Sflorian (unsigned long)want_read_size); 22285c45b740Sflorian current_read_size = want_read_size; 22295c45b740Sflorian if(c->tcp_byte_count < current_read_size) { 22305c45b740Sflorian r = recv(fd, (void*)sldns_buffer_at(c->buffer, 22315c45b740Sflorian c->tcp_byte_count), 22325c45b740Sflorian current_read_size-c->tcp_byte_count, MSG_DONTWAIT); 2233e97c6e54Ssthen if(r == 0) { 2234e97c6e54Ssthen if(c->tcp_req_info) 2235e97c6e54Ssthen return tcp_req_info_handle_read_close(c->tcp_req_info); 2236ae8c6e27Sflorian return 0; 2237e97c6e54Ssthen } else if(r == -1) { 22385c45b740Sflorian goto recv_error_initial; 22395c45b740Sflorian } 22405c45b740Sflorian c->tcp_byte_count += r; 224154cc57acSflorian sldns_buffer_skip(c->buffer, r); 22425c45b740Sflorian if(c->tcp_byte_count != current_read_size) return 1; 22435c45b740Sflorian c->pp2_header_state = pp2_header_init; 22445c45b740Sflorian } 22455c45b740Sflorian } 22465c45b740Sflorian if(c->pp2_header_state == pp2_header_init) { 224754cc57acSflorian int err; 224854cc57acSflorian err = pp2_read_header( 224954cc57acSflorian sldns_buffer_begin(c->buffer), 225054cc57acSflorian sldns_buffer_limit(c->buffer)); 225154cc57acSflorian if(err) { 22525c45b740Sflorian log_err("proxy_protocol: could not parse " 225354cc57acSflorian "PROXYv2 header (%s)", 225454cc57acSflorian pp_lookup_error(err)); 22555c45b740Sflorian return 0; 22565c45b740Sflorian } 225754cc57acSflorian header = (struct pp2_header*)sldns_buffer_begin(c->buffer); 22585c45b740Sflorian want_read_size = ntohs(header->len); 225954cc57acSflorian if(sldns_buffer_limit(c->buffer) < 22605c45b740Sflorian PP2_HEADER_SIZE + want_read_size) { 22615c45b740Sflorian log_err_addr("proxy_protocol: not enough " 22625c45b740Sflorian "buffer size to read PROXYv2 header", "", 22635c45b740Sflorian &c->repinfo.remote_addr, 22645c45b740Sflorian c->repinfo.remote_addrlen); 22655c45b740Sflorian return 0; 22665c45b740Sflorian } 22675c45b740Sflorian verbose(VERB_ALGO, "proxy_protocol: reading variable " 22685c45b740Sflorian "part of PROXYv2 header (len %lu)", 22695c45b740Sflorian (unsigned long)want_read_size); 22705c45b740Sflorian current_read_size = PP2_HEADER_SIZE + want_read_size; 22715c45b740Sflorian if(want_read_size == 0) { 22725c45b740Sflorian /* nothing more to read; header is complete */ 22735c45b740Sflorian c->pp2_header_state = pp2_header_done; 22745c45b740Sflorian } else if(c->tcp_byte_count < current_read_size) { 22755c45b740Sflorian r = recv(fd, (void*)sldns_buffer_at(c->buffer, 22765c45b740Sflorian c->tcp_byte_count), 22775c45b740Sflorian current_read_size-c->tcp_byte_count, MSG_DONTWAIT); 22785c45b740Sflorian if(r == 0) { 22795c45b740Sflorian if(c->tcp_req_info) 22805c45b740Sflorian return tcp_req_info_handle_read_close(c->tcp_req_info); 22815c45b740Sflorian return 0; 22825c45b740Sflorian } else if(r == -1) { 22835c45b740Sflorian goto recv_error; 22845c45b740Sflorian } 22855c45b740Sflorian c->tcp_byte_count += r; 228654cc57acSflorian sldns_buffer_skip(c->buffer, r); 22875c45b740Sflorian if(c->tcp_byte_count != current_read_size) return 1; 22885c45b740Sflorian c->pp2_header_state = pp2_header_done; 22895c45b740Sflorian } 22905c45b740Sflorian } 22915c45b740Sflorian if(c->pp2_header_state != pp2_header_done || !header) { 22925c45b740Sflorian log_err_addr("proxy_protocol: wrong state for the " 22935c45b740Sflorian "PROXYv2 header", "", &c->repinfo.remote_addr, 22945c45b740Sflorian c->repinfo.remote_addrlen); 22955c45b740Sflorian return 0; 22965c45b740Sflorian } 229754cc57acSflorian sldns_buffer_flip(c->buffer); 22985c45b740Sflorian if(!consume_pp2_header(c->buffer, &c->repinfo, 1)) { 22995c45b740Sflorian log_err_addr("proxy_protocol: could not consume " 23005c45b740Sflorian "PROXYv2 header", "", &c->repinfo.remote_addr, 23015c45b740Sflorian c->repinfo.remote_addrlen); 23025c45b740Sflorian return 0; 23035c45b740Sflorian } 23045c45b740Sflorian verbose(VERB_ALGO, "proxy_protocol: successful read of " 23055c45b740Sflorian "PROXYv2 header"); 23065c45b740Sflorian /* Clear and reset the buffer to read the following 23075c45b740Sflorian * DNS packet(s). */ 23085c45b740Sflorian sldns_buffer_clear(c->buffer); 23095c45b740Sflorian c->tcp_byte_count = 0; 23105c45b740Sflorian return 1; 23115c45b740Sflorian } 23125c45b740Sflorian 23135c45b740Sflorian if(c->tcp_byte_count < sizeof(uint16_t)) { 23145c45b740Sflorian /* read length bytes */ 23155c45b740Sflorian r = recv(fd,(void*)sldns_buffer_at(c->buffer,c->tcp_byte_count), 23165c45b740Sflorian sizeof(uint16_t)-c->tcp_byte_count, MSG_DONTWAIT); 23175c45b740Sflorian if(r == 0) { 23185c45b740Sflorian if(c->tcp_req_info) 23195c45b740Sflorian return tcp_req_info_handle_read_close(c->tcp_req_info); 23205c45b740Sflorian return 0; 23215c45b740Sflorian } else if(r == -1) { 23225c45b740Sflorian if(c->pp2_enabled) goto recv_error; 23235c45b740Sflorian goto recv_error_initial; 23245c45b740Sflorian } 23255c45b740Sflorian c->tcp_byte_count += r; 23265c45b740Sflorian if(c->tcp_byte_count != sizeof(uint16_t)) 23275c45b740Sflorian return 1; 23285c45b740Sflorian if(sldns_buffer_read_u16_at(c->buffer, 0) > 23295c45b740Sflorian sldns_buffer_capacity(c->buffer)) { 23305c45b740Sflorian verbose(VERB_QUERY, "tcp: dropped larger than buffer"); 23315c45b740Sflorian return 0; 23325c45b740Sflorian } 23335c45b740Sflorian sldns_buffer_set_limit(c->buffer, 23345c45b740Sflorian sldns_buffer_read_u16_at(c->buffer, 0)); 23355c45b740Sflorian if(!short_ok && 23365c45b740Sflorian sldns_buffer_limit(c->buffer) < LDNS_HEADER_SIZE) { 23375c45b740Sflorian verbose(VERB_QUERY, "tcp: dropped bogus too short."); 23385c45b740Sflorian return 0; 23395c45b740Sflorian } 23405c45b740Sflorian verbose(VERB_ALGO, "Reading tcp query of length %d", 23415c45b740Sflorian (int)sldns_buffer_limit(c->buffer)); 23425c45b740Sflorian } 23435c45b740Sflorian 23445c45b740Sflorian if(sldns_buffer_remaining(c->buffer) == 0) 23455c45b740Sflorian log_err("in comm_point_tcp_handle_read buffer_remaining is " 23465c45b740Sflorian "not > 0 as expected, continuing with (harmless) 0 " 23475c45b740Sflorian "length recv"); 23485c45b740Sflorian r = recv(fd, (void*)sldns_buffer_current(c->buffer), 23495c45b740Sflorian sldns_buffer_remaining(c->buffer), MSG_DONTWAIT); 23505c45b740Sflorian if(r == 0) { 23515c45b740Sflorian if(c->tcp_req_info) 23525c45b740Sflorian return tcp_req_info_handle_read_close(c->tcp_req_info); 23535c45b740Sflorian return 0; 23545c45b740Sflorian } else if(r == -1) { 23555c45b740Sflorian goto recv_error; 23565c45b740Sflorian } 23575c45b740Sflorian sldns_buffer_skip(c->buffer, r); 23585c45b740Sflorian if(sldns_buffer_remaining(c->buffer) <= 0) { 23595c45b740Sflorian tcp_callback_reader(c); 23605c45b740Sflorian } 23615c45b740Sflorian return 1; 23625c45b740Sflorian 23635c45b740Sflorian recv_error_initial: 23645c45b740Sflorian recv_initial = 1; 23655c45b740Sflorian recv_error: 2366ae8c6e27Sflorian #ifndef USE_WINSOCK 2367ae8c6e27Sflorian if(errno == EINTR || errno == EAGAIN) 2368ae8c6e27Sflorian return 1; 2369ae8c6e27Sflorian #ifdef ECONNRESET 2370ae8c6e27Sflorian if(errno == ECONNRESET && verbosity < 2) 2371ae8c6e27Sflorian return 0; /* silence reset by peer */ 2372ae8c6e27Sflorian #endif 2373*7037e34cSflorian if(recv_initial) { 2374411c5950Sflorian #ifdef ECONNREFUSED 2375411c5950Sflorian if(errno == ECONNREFUSED && verbosity < 2) 2376411c5950Sflorian return 0; /* silence reset by peer */ 2377411c5950Sflorian #endif 2378a8eaceedSflorian #ifdef ENETUNREACH 2379a8eaceedSflorian if(errno == ENETUNREACH && verbosity < 2) 2380a8eaceedSflorian return 0; /* silence it */ 2381a8eaceedSflorian #endif 2382a8eaceedSflorian #ifdef EHOSTDOWN 2383a8eaceedSflorian if(errno == EHOSTDOWN && verbosity < 2) 2384a8eaceedSflorian return 0; /* silence it */ 2385a8eaceedSflorian #endif 2386a8eaceedSflorian #ifdef EHOSTUNREACH 2387a8eaceedSflorian if(errno == EHOSTUNREACH && verbosity < 2) 2388a8eaceedSflorian return 0; /* silence it */ 2389a8eaceedSflorian #endif 2390a8eaceedSflorian #ifdef ENETDOWN 2391a8eaceedSflorian if(errno == ENETDOWN && verbosity < 2) 2392a8eaceedSflorian return 0; /* silence it */ 2393a8eaceedSflorian #endif 2394a8eaceedSflorian #ifdef EACCES 2395a8eaceedSflorian if(errno == EACCES && verbosity < 2) 2396a8eaceedSflorian return 0; /* silence it */ 2397a8eaceedSflorian #endif 2398a8eaceedSflorian #ifdef ENOTCONN 2399a8eaceedSflorian if(errno == ENOTCONN) { 2400*7037e34cSflorian log_err_addr("read (in tcp initial) failed and this " 24015c45b740Sflorian "could be because TCP Fast Open is " 24025c45b740Sflorian "enabled [--disable-tfo-client " 24035c45b740Sflorian "--disable-tfo-server] but does not " 24045c45b740Sflorian "work", sock_strerror(errno), 24055c45b740Sflorian &c->repinfo.remote_addr, 24065c45b740Sflorian c->repinfo.remote_addrlen); 2407a8eaceedSflorian return 0; 2408a8eaceedSflorian } 2409a8eaceedSflorian #endif 24105c45b740Sflorian } 2411ae8c6e27Sflorian #else /* USE_WINSOCK */ 24125c45b740Sflorian if(recv_initial) { 2413411c5950Sflorian if(WSAGetLastError() == WSAECONNREFUSED && verbosity < 2) 2414411c5950Sflorian return 0; 2415411c5950Sflorian if(WSAGetLastError() == WSAEHOSTDOWN && verbosity < 2) 2416411c5950Sflorian return 0; 2417411c5950Sflorian if(WSAGetLastError() == WSAEHOSTUNREACH && verbosity < 2) 2418411c5950Sflorian return 0; 2419411c5950Sflorian if(WSAGetLastError() == WSAENETDOWN && verbosity < 2) 2420411c5950Sflorian return 0; 2421411c5950Sflorian if(WSAGetLastError() == WSAENETUNREACH && verbosity < 2) 2422411c5950Sflorian return 0; 24235c45b740Sflorian } 2424ae8c6e27Sflorian if(WSAGetLastError() == WSAECONNRESET) 2425ae8c6e27Sflorian return 0; 2426ae8c6e27Sflorian if(WSAGetLastError() == WSAEINPROGRESS) 2427ae8c6e27Sflorian return 1; 2428ae8c6e27Sflorian if(WSAGetLastError() == WSAEWOULDBLOCK) { 2429ae8c6e27Sflorian ub_winsock_tcp_wouldblock(c->ev->ev, 2430ae8c6e27Sflorian UB_EV_READ); 2431ae8c6e27Sflorian return 1; 2432ae8c6e27Sflorian } 2433ae8c6e27Sflorian #endif 2434*7037e34cSflorian log_err_addr((recv_initial?"read (in tcp initial)":"read (in tcp)"), 2435*7037e34cSflorian sock_strerror(errno), &c->repinfo.remote_addr, 2436*7037e34cSflorian c->repinfo.remote_addrlen); 2437ae8c6e27Sflorian return 0; 2438ae8c6e27Sflorian } 2439ae8c6e27Sflorian 2440ae8c6e27Sflorian /** 2441ae8c6e27Sflorian * Handle tcp writing callback. 2442ae8c6e27Sflorian * @param fd: file descriptor of socket. 2443ae8c6e27Sflorian * @param c: comm point to write buffer out of. 2444ae8c6e27Sflorian * @return: 0 on error 2445ae8c6e27Sflorian */ 2446ae8c6e27Sflorian static int 2447ae8c6e27Sflorian comm_point_tcp_handle_write(int fd, struct comm_point* c) 2448ae8c6e27Sflorian { 2449ae8c6e27Sflorian ssize_t r; 2450ae8c6e27Sflorian struct sldns_buffer *buffer; 2451ae8c6e27Sflorian log_assert(c->type == comm_tcp); 2452ae8c6e27Sflorian #ifdef USE_DNSCRYPT 2453ae8c6e27Sflorian buffer = c->dnscrypt_buffer; 2454ae8c6e27Sflorian #else 2455ae8c6e27Sflorian buffer = c->buffer; 2456ae8c6e27Sflorian #endif 2457853e076fSflorian if(c->tcp_is_reading && !c->ssl && !c->tcp_write_and_read) 2458ae8c6e27Sflorian return 0; 2459ae8c6e27Sflorian log_assert(fd != -1); 2460853e076fSflorian 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) { 2461ae8c6e27Sflorian /* check for pending error from nonblocking connect */ 2462ae8c6e27Sflorian /* from Stevens, unix network programming, vol1, 3rd ed, p450*/ 2463ae8c6e27Sflorian int error = 0; 2464ae8c6e27Sflorian socklen_t len = (socklen_t)sizeof(error); 2465ae8c6e27Sflorian if(getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&error, 2466ae8c6e27Sflorian &len) < 0){ 2467ae8c6e27Sflorian #ifndef USE_WINSOCK 2468ae8c6e27Sflorian error = errno; /* on solaris errno is error */ 2469ae8c6e27Sflorian #else /* USE_WINSOCK */ 2470ae8c6e27Sflorian error = WSAGetLastError(); 2471ae8c6e27Sflorian #endif 2472ae8c6e27Sflorian } 2473ae8c6e27Sflorian #ifndef USE_WINSOCK 2474ae8c6e27Sflorian #if defined(EINPROGRESS) && defined(EWOULDBLOCK) 2475ae8c6e27Sflorian if(error == EINPROGRESS || error == EWOULDBLOCK) 2476ae8c6e27Sflorian return 1; /* try again later */ 2477ae8c6e27Sflorian else 2478ae8c6e27Sflorian #endif 2479ae8c6e27Sflorian if(error != 0 && verbosity < 2) 2480ae8c6e27Sflorian return 0; /* silence lots of chatter in the logs */ 2481ae8c6e27Sflorian else if(error != 0) { 2482ae8c6e27Sflorian log_err_addr("tcp connect", strerror(error), 24835c45b740Sflorian &c->repinfo.remote_addr, 24845c45b740Sflorian c->repinfo.remote_addrlen); 2485ae8c6e27Sflorian #else /* USE_WINSOCK */ 2486ae8c6e27Sflorian /* examine error */ 2487ae8c6e27Sflorian if(error == WSAEINPROGRESS) 2488ae8c6e27Sflorian return 1; 2489ae8c6e27Sflorian else if(error == WSAEWOULDBLOCK) { 2490ae8c6e27Sflorian ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE); 2491ae8c6e27Sflorian return 1; 2492ae8c6e27Sflorian } else if(error != 0 && verbosity < 2) 2493ae8c6e27Sflorian return 0; 2494ae8c6e27Sflorian else if(error != 0) { 2495ae8c6e27Sflorian log_err_addr("tcp connect", wsa_strerror(error), 24965c45b740Sflorian &c->repinfo.remote_addr, 24975c45b740Sflorian c->repinfo.remote_addrlen); 2498ae8c6e27Sflorian #endif /* USE_WINSOCK */ 2499ae8c6e27Sflorian return 0; 2500ae8c6e27Sflorian } 2501ae8c6e27Sflorian } 2502ae8c6e27Sflorian if(c->ssl) 2503853e076fSflorian return ssl_handle_it(c, 1); 2504ae8c6e27Sflorian 2505ae8c6e27Sflorian #ifdef USE_MSG_FASTOPEN 2506ae8c6e27Sflorian /* Only try this on first use of a connection that uses tfo, 2507ae8c6e27Sflorian otherwise fall through to normal write */ 2508ae8c6e27Sflorian /* Also, TFO support on WINDOWS not implemented at the moment */ 2509ae8c6e27Sflorian if(c->tcp_do_fastopen == 1) { 2510ae8c6e27Sflorian /* this form of sendmsg() does both a connect() and send() so need to 2511ae8c6e27Sflorian look for various flavours of error*/ 2512853e076fSflorian uint16_t len = htons(c->tcp_write_and_read?c->tcp_write_pkt_len:sldns_buffer_limit(buffer)); 2513ae8c6e27Sflorian struct msghdr msg; 2514ae8c6e27Sflorian struct iovec iov[2]; 2515ae8c6e27Sflorian c->tcp_do_fastopen = 0; 2516ae8c6e27Sflorian memset(&msg, 0, sizeof(msg)); 2517853e076fSflorian if(c->tcp_write_and_read) { 2518853e076fSflorian iov[0].iov_base = (uint8_t*)&len + c->tcp_write_byte_count; 2519853e076fSflorian iov[0].iov_len = sizeof(uint16_t) - c->tcp_write_byte_count; 2520853e076fSflorian iov[1].iov_base = c->tcp_write_pkt; 2521853e076fSflorian iov[1].iov_len = c->tcp_write_pkt_len; 2522853e076fSflorian } else { 2523ae8c6e27Sflorian iov[0].iov_base = (uint8_t*)&len + c->tcp_byte_count; 2524ae8c6e27Sflorian iov[0].iov_len = sizeof(uint16_t) - c->tcp_byte_count; 2525ae8c6e27Sflorian iov[1].iov_base = sldns_buffer_begin(buffer); 2526ae8c6e27Sflorian iov[1].iov_len = sldns_buffer_limit(buffer); 2527853e076fSflorian } 2528ae8c6e27Sflorian log_assert(iov[0].iov_len > 0); 25295c45b740Sflorian msg.msg_name = &c->repinfo.remote_addr; 25305c45b740Sflorian msg.msg_namelen = c->repinfo.remote_addrlen; 2531ae8c6e27Sflorian msg.msg_iov = iov; 2532ae8c6e27Sflorian msg.msg_iovlen = 2; 2533ae8c6e27Sflorian r = sendmsg(fd, &msg, MSG_FASTOPEN); 2534ae8c6e27Sflorian if (r == -1) { 2535ae8c6e27Sflorian #if defined(EINPROGRESS) && defined(EWOULDBLOCK) 2536ae8c6e27Sflorian /* Handshake is underway, maybe because no TFO cookie available. 2537ae8c6e27Sflorian Come back to write the message*/ 2538ae8c6e27Sflorian if(errno == EINPROGRESS || errno == EWOULDBLOCK) 2539ae8c6e27Sflorian return 1; 2540ae8c6e27Sflorian #endif 2541ae8c6e27Sflorian if(errno == EINTR || errno == EAGAIN) 2542ae8c6e27Sflorian return 1; 2543ae8c6e27Sflorian /* Not handling EISCONN here as shouldn't ever hit that case.*/ 2544a1a7ba80Sflorian if(errno != EPIPE 2545a1a7ba80Sflorian #ifdef EOPNOTSUPP 2546a1a7ba80Sflorian /* if /proc/sys/net/ipv4/tcp_fastopen is 2547a1a7ba80Sflorian * disabled on Linux, sendmsg may return 2548a1a7ba80Sflorian * 'Operation not supported', if so 2549a1a7ba80Sflorian * fallthrough to ordinary connect. */ 2550a1a7ba80Sflorian && errno != EOPNOTSUPP 2551a1a7ba80Sflorian #endif 2552a1a7ba80Sflorian && errno != 0) { 2553a1a7ba80Sflorian if(verbosity < 2) 2554ae8c6e27Sflorian return 0; /* silence lots of chatter in the logs */ 2555ae8c6e27Sflorian log_err_addr("tcp sendmsg", strerror(errno), 25565c45b740Sflorian &c->repinfo.remote_addr, 25575c45b740Sflorian c->repinfo.remote_addrlen); 2558ae8c6e27Sflorian return 0; 2559ae8c6e27Sflorian } 2560a1a7ba80Sflorian verbose(VERB_ALGO, "tcp sendmsg for fastopen failed (with %s), try normal connect", strerror(errno)); 2561ae8c6e27Sflorian /* fallthrough to nonFASTOPEN 2562ae8c6e27Sflorian * (MSG_FASTOPEN on Linux 3 produces EPIPE) 2563ae8c6e27Sflorian * we need to perform connect() */ 25645c45b740Sflorian if(connect(fd, (struct sockaddr *)&c->repinfo.remote_addr, 25655c45b740Sflorian c->repinfo.remote_addrlen) == -1) { 2566ae8c6e27Sflorian #ifdef EINPROGRESS 2567ae8c6e27Sflorian if(errno == EINPROGRESS) 2568ae8c6e27Sflorian return 1; /* wait until connect done*/ 2569ae8c6e27Sflorian #endif 2570ae8c6e27Sflorian #ifdef USE_WINSOCK 2571ae8c6e27Sflorian if(WSAGetLastError() == WSAEINPROGRESS || 2572ae8c6e27Sflorian WSAGetLastError() == WSAEWOULDBLOCK) 2573ae8c6e27Sflorian return 1; /* wait until connect done*/ 2574ae8c6e27Sflorian #endif 2575ae8c6e27Sflorian if(tcp_connect_errno_needs_log( 25765c45b740Sflorian (struct sockaddr *)&c->repinfo.remote_addr, 25775c45b740Sflorian c->repinfo.remote_addrlen)) { 2578ae8c6e27Sflorian log_err_addr("outgoing tcp: connect after EPIPE for fastopen", 25795c45b740Sflorian strerror(errno), 25805c45b740Sflorian &c->repinfo.remote_addr, 25815c45b740Sflorian c->repinfo.remote_addrlen); 2582ae8c6e27Sflorian } 2583ae8c6e27Sflorian return 0; 2584ae8c6e27Sflorian } 2585ae8c6e27Sflorian 2586ae8c6e27Sflorian } else { 2587853e076fSflorian if(c->tcp_write_and_read) { 2588853e076fSflorian c->tcp_write_byte_count += r; 2589853e076fSflorian if(c->tcp_write_byte_count < sizeof(uint16_t)) 2590853e076fSflorian return 1; 2591853e076fSflorian } else { 2592ae8c6e27Sflorian c->tcp_byte_count += r; 2593ae8c6e27Sflorian if(c->tcp_byte_count < sizeof(uint16_t)) 2594ae8c6e27Sflorian return 1; 2595ae8c6e27Sflorian sldns_buffer_set_position(buffer, c->tcp_byte_count - 2596ae8c6e27Sflorian sizeof(uint16_t)); 2597853e076fSflorian } 2598853e076fSflorian 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)) { 2599ae8c6e27Sflorian tcp_callback_writer(c); 2600ae8c6e27Sflorian return 1; 2601ae8c6e27Sflorian } 2602ae8c6e27Sflorian } 2603ae8c6e27Sflorian } 2604ae8c6e27Sflorian #endif /* USE_MSG_FASTOPEN */ 2605ae8c6e27Sflorian 2606853e076fSflorian if((c->tcp_write_and_read?c->tcp_write_byte_count:c->tcp_byte_count) < sizeof(uint16_t)) { 2607853e076fSflorian uint16_t len = htons(c->tcp_write_and_read?c->tcp_write_pkt_len:sldns_buffer_limit(buffer)); 2608ae8c6e27Sflorian #ifdef HAVE_WRITEV 2609ae8c6e27Sflorian struct iovec iov[2]; 2610853e076fSflorian if(c->tcp_write_and_read) { 2611853e076fSflorian iov[0].iov_base = (uint8_t*)&len + c->tcp_write_byte_count; 2612853e076fSflorian iov[0].iov_len = sizeof(uint16_t) - c->tcp_write_byte_count; 2613853e076fSflorian iov[1].iov_base = c->tcp_write_pkt; 2614853e076fSflorian iov[1].iov_len = c->tcp_write_pkt_len; 2615853e076fSflorian } else { 2616ae8c6e27Sflorian iov[0].iov_base = (uint8_t*)&len + c->tcp_byte_count; 2617ae8c6e27Sflorian iov[0].iov_len = sizeof(uint16_t) - c->tcp_byte_count; 2618ae8c6e27Sflorian iov[1].iov_base = sldns_buffer_begin(buffer); 2619ae8c6e27Sflorian iov[1].iov_len = sldns_buffer_limit(buffer); 2620853e076fSflorian } 2621ae8c6e27Sflorian log_assert(iov[0].iov_len > 0); 2622ae8c6e27Sflorian r = writev(fd, iov, 2); 2623ae8c6e27Sflorian #else /* HAVE_WRITEV */ 2624853e076fSflorian if(c->tcp_write_and_read) { 2625853e076fSflorian r = send(fd, (void*)(((uint8_t*)&len)+c->tcp_write_byte_count), 2626853e076fSflorian sizeof(uint16_t)-c->tcp_write_byte_count, 0); 2627853e076fSflorian } else { 2628ae8c6e27Sflorian r = send(fd, (void*)(((uint8_t*)&len)+c->tcp_byte_count), 2629ae8c6e27Sflorian sizeof(uint16_t)-c->tcp_byte_count, 0); 2630853e076fSflorian } 2631ae8c6e27Sflorian #endif /* HAVE_WRITEV */ 2632ae8c6e27Sflorian if(r == -1) { 2633ae8c6e27Sflorian #ifndef USE_WINSOCK 2634ae8c6e27Sflorian # ifdef EPIPE 2635ae8c6e27Sflorian if(errno == EPIPE && verbosity < 2) 2636ae8c6e27Sflorian return 0; /* silence 'broken pipe' */ 2637ae8c6e27Sflorian #endif 2638ae8c6e27Sflorian if(errno == EINTR || errno == EAGAIN) 2639ae8c6e27Sflorian return 1; 26409b465e50Sflorian #ifdef ECONNRESET 26419b465e50Sflorian if(errno == ECONNRESET && verbosity < 2) 26429b465e50Sflorian return 0; /* silence reset by peer */ 26439b465e50Sflorian #endif 2644ae8c6e27Sflorian # ifdef HAVE_WRITEV 2645ae8c6e27Sflorian log_err_addr("tcp writev", strerror(errno), 26465c45b740Sflorian &c->repinfo.remote_addr, 26475c45b740Sflorian c->repinfo.remote_addrlen); 2648ae8c6e27Sflorian # else /* HAVE_WRITEV */ 2649ae8c6e27Sflorian log_err_addr("tcp send s", strerror(errno), 26505c45b740Sflorian &c->repinfo.remote_addr, 26515c45b740Sflorian c->repinfo.remote_addrlen); 2652ae8c6e27Sflorian # endif /* HAVE_WRITEV */ 2653ae8c6e27Sflorian #else 2654ae8c6e27Sflorian if(WSAGetLastError() == WSAENOTCONN) 2655ae8c6e27Sflorian return 1; 2656ae8c6e27Sflorian if(WSAGetLastError() == WSAEINPROGRESS) 2657ae8c6e27Sflorian return 1; 2658ae8c6e27Sflorian if(WSAGetLastError() == WSAEWOULDBLOCK) { 2659ae8c6e27Sflorian ub_winsock_tcp_wouldblock(c->ev->ev, 2660ae8c6e27Sflorian UB_EV_WRITE); 2661ae8c6e27Sflorian return 1; 2662ae8c6e27Sflorian } 26639b465e50Sflorian if(WSAGetLastError() == WSAECONNRESET && verbosity < 2) 26649b465e50Sflorian return 0; /* silence reset by peer */ 2665ae8c6e27Sflorian log_err_addr("tcp send s", 2666ae8c6e27Sflorian wsa_strerror(WSAGetLastError()), 26675c45b740Sflorian &c->repinfo.remote_addr, 26685c45b740Sflorian c->repinfo.remote_addrlen); 2669ae8c6e27Sflorian #endif 2670ae8c6e27Sflorian return 0; 2671ae8c6e27Sflorian } 2672853e076fSflorian if(c->tcp_write_and_read) { 2673853e076fSflorian c->tcp_write_byte_count += r; 2674853e076fSflorian if(c->tcp_write_byte_count < sizeof(uint16_t)) 2675853e076fSflorian return 1; 2676853e076fSflorian } else { 2677ae8c6e27Sflorian c->tcp_byte_count += r; 2678ae8c6e27Sflorian if(c->tcp_byte_count < sizeof(uint16_t)) 2679ae8c6e27Sflorian return 1; 2680ae8c6e27Sflorian sldns_buffer_set_position(buffer, c->tcp_byte_count - 2681ae8c6e27Sflorian sizeof(uint16_t)); 2682853e076fSflorian } 2683853e076fSflorian 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)) { 2684ae8c6e27Sflorian tcp_callback_writer(c); 2685ae8c6e27Sflorian return 1; 2686ae8c6e27Sflorian } 2687ae8c6e27Sflorian } 2688853e076fSflorian log_assert(c->tcp_write_and_read || sldns_buffer_remaining(buffer) > 0); 2689853e076fSflorian log_assert(!c->tcp_write_and_read || c->tcp_write_byte_count < c->tcp_write_pkt_len + 2); 2690853e076fSflorian if(c->tcp_write_and_read) { 2691b9b6f203Sflorian r = send(fd, (void*)(c->tcp_write_pkt + c->tcp_write_byte_count - 2), 2692853e076fSflorian c->tcp_write_pkt_len + 2 - c->tcp_write_byte_count, 0); 2693853e076fSflorian } else { 2694ae8c6e27Sflorian r = send(fd, (void*)sldns_buffer_current(buffer), 2695ae8c6e27Sflorian sldns_buffer_remaining(buffer), 0); 2696853e076fSflorian } 2697ae8c6e27Sflorian if(r == -1) { 2698ae8c6e27Sflorian #ifndef USE_WINSOCK 2699ae8c6e27Sflorian if(errno == EINTR || errno == EAGAIN) 2700ae8c6e27Sflorian return 1; 27019b465e50Sflorian #ifdef ECONNRESET 27029b465e50Sflorian if(errno == ECONNRESET && verbosity < 2) 27039b465e50Sflorian return 0; /* silence reset by peer */ 27049b465e50Sflorian #endif 2705ae8c6e27Sflorian #else 2706ae8c6e27Sflorian if(WSAGetLastError() == WSAEINPROGRESS) 2707ae8c6e27Sflorian return 1; 2708ae8c6e27Sflorian if(WSAGetLastError() == WSAEWOULDBLOCK) { 2709ae8c6e27Sflorian ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE); 2710ae8c6e27Sflorian return 1; 2711ae8c6e27Sflorian } 27129b465e50Sflorian if(WSAGetLastError() == WSAECONNRESET && verbosity < 2) 27139b465e50Sflorian return 0; /* silence reset by peer */ 2714ae8c6e27Sflorian #endif 2715f4f0f0ceSflorian log_err_addr("tcp send r", sock_strerror(errno), 27165c45b740Sflorian &c->repinfo.remote_addr, 27175c45b740Sflorian c->repinfo.remote_addrlen); 2718ae8c6e27Sflorian return 0; 2719ae8c6e27Sflorian } 2720853e076fSflorian if(c->tcp_write_and_read) { 2721853e076fSflorian c->tcp_write_byte_count += r; 2722853e076fSflorian } else { 2723ae8c6e27Sflorian sldns_buffer_skip(buffer, r); 2724853e076fSflorian } 2725ae8c6e27Sflorian 2726853e076fSflorian 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)) { 2727ae8c6e27Sflorian tcp_callback_writer(c); 2728ae8c6e27Sflorian } 2729ae8c6e27Sflorian 2730ae8c6e27Sflorian return 1; 2731ae8c6e27Sflorian } 2732ae8c6e27Sflorian 2733d500c338Sflorian /** read again to drain buffers when there could be more to read, returns 0 2734d500c338Sflorian * on failure which means the comm point is closed. */ 2735d500c338Sflorian static int 2736e97c6e54Ssthen tcp_req_info_read_again(int fd, struct comm_point* c) 2737e97c6e54Ssthen { 2738e97c6e54Ssthen while(c->tcp_req_info->read_again) { 2739e97c6e54Ssthen int r; 2740e97c6e54Ssthen c->tcp_req_info->read_again = 0; 2741e97c6e54Ssthen if(c->tcp_is_reading) 2742e97c6e54Ssthen r = comm_point_tcp_handle_read(fd, c, 0); 2743e97c6e54Ssthen else r = comm_point_tcp_handle_write(fd, c); 2744e97c6e54Ssthen if(!r) { 2745e97c6e54Ssthen reclaim_tcp_handler(c); 2746e97c6e54Ssthen if(!c->tcp_do_close) { 2747e97c6e54Ssthen fptr_ok(fptr_whitelist_comm_point( 2748e97c6e54Ssthen c->callback)); 2749e97c6e54Ssthen (void)(*c->callback)(c, c->cb_arg, 2750e97c6e54Ssthen NETEVENT_CLOSED, NULL); 2751e97c6e54Ssthen } 2752d500c338Sflorian return 0; 2753e97c6e54Ssthen } 2754e97c6e54Ssthen } 2755d500c338Sflorian return 1; 2756e97c6e54Ssthen } 2757e97c6e54Ssthen 2758853e076fSflorian /** read again to drain buffers when there could be more to read */ 2759853e076fSflorian static void 2760853e076fSflorian tcp_more_read_again(int fd, struct comm_point* c) 2761853e076fSflorian { 2762853e076fSflorian /* if the packet is done, but another one could be waiting on 2763853e076fSflorian * the connection, the callback signals this, and we try again */ 2764853e076fSflorian /* this continues until the read routines get EAGAIN or so, 2765853e076fSflorian * and thus does not call the callback, and the bool is 0 */ 2766853e076fSflorian int* moreread = c->tcp_more_read_again; 2767853e076fSflorian while(moreread && *moreread) { 2768853e076fSflorian *moreread = 0; 2769853e076fSflorian if(!comm_point_tcp_handle_read(fd, c, 0)) { 2770853e076fSflorian reclaim_tcp_handler(c); 2771853e076fSflorian if(!c->tcp_do_close) { 2772853e076fSflorian fptr_ok(fptr_whitelist_comm_point( 2773853e076fSflorian c->callback)); 2774853e076fSflorian (void)(*c->callback)(c, c->cb_arg, 2775853e076fSflorian NETEVENT_CLOSED, NULL); 2776853e076fSflorian } 2777853e076fSflorian return; 2778853e076fSflorian } 2779853e076fSflorian } 2780853e076fSflorian } 2781853e076fSflorian 2782853e076fSflorian /** write again to fill up when there could be more to write */ 2783853e076fSflorian static void 2784853e076fSflorian tcp_more_write_again(int fd, struct comm_point* c) 2785853e076fSflorian { 2786853e076fSflorian /* if the packet is done, but another is waiting to be written, 2787853e076fSflorian * the callback signals it and we try again. */ 2788853e076fSflorian /* this continues until the write routines get EAGAIN or so, 2789853e076fSflorian * and thus does not call the callback, and the bool is 0 */ 2790853e076fSflorian int* morewrite = c->tcp_more_write_again; 2791853e076fSflorian while(morewrite && *morewrite) { 2792853e076fSflorian *morewrite = 0; 2793853e076fSflorian if(!comm_point_tcp_handle_write(fd, c)) { 2794853e076fSflorian reclaim_tcp_handler(c); 2795853e076fSflorian if(!c->tcp_do_close) { 2796853e076fSflorian fptr_ok(fptr_whitelist_comm_point( 2797853e076fSflorian c->callback)); 2798853e076fSflorian (void)(*c->callback)(c, c->cb_arg, 2799853e076fSflorian NETEVENT_CLOSED, NULL); 2800853e076fSflorian } 2801853e076fSflorian return; 2802853e076fSflorian } 2803853e076fSflorian } 2804853e076fSflorian } 2805853e076fSflorian 2806ae8c6e27Sflorian void 2807ae8c6e27Sflorian comm_point_tcp_handle_callback(int fd, short event, void* arg) 2808ae8c6e27Sflorian { 2809ae8c6e27Sflorian struct comm_point* c = (struct comm_point*)arg; 2810ae8c6e27Sflorian log_assert(c->type == comm_tcp); 2811ae8c6e27Sflorian ub_comm_base_now(c->ev->base); 2812ae8c6e27Sflorian 2813d500c338Sflorian if(c->fd == -1 || c->fd != fd) 2814d500c338Sflorian return; /* duplicate event, but commpoint closed. */ 2815d500c338Sflorian 2816ae8c6e27Sflorian #ifdef USE_DNSCRYPT 2817ae8c6e27Sflorian /* Initialize if this is a dnscrypt socket */ 2818ae8c6e27Sflorian if(c->tcp_parent) { 2819ae8c6e27Sflorian c->dnscrypt = c->tcp_parent->dnscrypt; 2820ae8c6e27Sflorian } 2821ae8c6e27Sflorian if(c->dnscrypt && c->dnscrypt_buffer == c->buffer) { 2822ae8c6e27Sflorian c->dnscrypt_buffer = sldns_buffer_new(sldns_buffer_capacity(c->buffer)); 2823ae8c6e27Sflorian if(!c->dnscrypt_buffer) { 2824ae8c6e27Sflorian log_err("Could not allocate dnscrypt buffer"); 2825ae8c6e27Sflorian reclaim_tcp_handler(c); 2826ae8c6e27Sflorian if(!c->tcp_do_close) { 2827ae8c6e27Sflorian fptr_ok(fptr_whitelist_comm_point( 2828ae8c6e27Sflorian c->callback)); 2829ae8c6e27Sflorian (void)(*c->callback)(c, c->cb_arg, 2830ae8c6e27Sflorian NETEVENT_CLOSED, NULL); 2831ae8c6e27Sflorian } 2832ae8c6e27Sflorian return; 2833ae8c6e27Sflorian } 2834ae8c6e27Sflorian } 2835ae8c6e27Sflorian #endif 2836ae8c6e27Sflorian 28379b465e50Sflorian if(event&UB_EV_TIMEOUT) { 28389b465e50Sflorian verbose(VERB_QUERY, "tcp took too long, dropped"); 28399b465e50Sflorian reclaim_tcp_handler(c); 28409b465e50Sflorian if(!c->tcp_do_close) { 28419b465e50Sflorian fptr_ok(fptr_whitelist_comm_point(c->callback)); 28429b465e50Sflorian (void)(*c->callback)(c, c->cb_arg, 28439b465e50Sflorian NETEVENT_TIMEOUT, NULL); 28449b465e50Sflorian } 28459b465e50Sflorian return; 28469b465e50Sflorian } 2847853e076fSflorian if(event&UB_EV_READ 2848853e076fSflorian #ifdef USE_MSG_FASTOPEN 2849853e076fSflorian && !(c->tcp_do_fastopen && (event&UB_EV_WRITE)) 2850853e076fSflorian #endif 2851853e076fSflorian ) { 2852e97c6e54Ssthen int has_tcpq = (c->tcp_req_info != NULL); 2853853e076fSflorian int* moreread = c->tcp_more_read_again; 2854ae8c6e27Sflorian if(!comm_point_tcp_handle_read(fd, c, 0)) { 2855ae8c6e27Sflorian reclaim_tcp_handler(c); 2856ae8c6e27Sflorian if(!c->tcp_do_close) { 2857ae8c6e27Sflorian fptr_ok(fptr_whitelist_comm_point( 2858ae8c6e27Sflorian c->callback)); 2859ae8c6e27Sflorian (void)(*c->callback)(c, c->cb_arg, 2860ae8c6e27Sflorian NETEVENT_CLOSED, NULL); 2861ae8c6e27Sflorian } 2862853e076fSflorian return; 2863ae8c6e27Sflorian } 2864d500c338Sflorian if(has_tcpq && c->tcp_req_info && c->tcp_req_info->read_again) { 2865d500c338Sflorian if(!tcp_req_info_read_again(fd, c)) 2866d500c338Sflorian return; 2867d500c338Sflorian } 2868853e076fSflorian if(moreread && *moreread) 2869853e076fSflorian tcp_more_read_again(fd, c); 2870ae8c6e27Sflorian return; 2871ae8c6e27Sflorian } 2872ae8c6e27Sflorian if(event&UB_EV_WRITE) { 2873e97c6e54Ssthen int has_tcpq = (c->tcp_req_info != NULL); 2874853e076fSflorian int* morewrite = c->tcp_more_write_again; 2875ae8c6e27Sflorian if(!comm_point_tcp_handle_write(fd, c)) { 2876ae8c6e27Sflorian reclaim_tcp_handler(c); 2877ae8c6e27Sflorian if(!c->tcp_do_close) { 2878ae8c6e27Sflorian fptr_ok(fptr_whitelist_comm_point( 2879ae8c6e27Sflorian c->callback)); 2880ae8c6e27Sflorian (void)(*c->callback)(c, c->cb_arg, 2881ae8c6e27Sflorian NETEVENT_CLOSED, NULL); 2882ae8c6e27Sflorian } 2883853e076fSflorian return; 2884ae8c6e27Sflorian } 2885d500c338Sflorian if(has_tcpq && c->tcp_req_info && c->tcp_req_info->read_again) { 2886d500c338Sflorian if(!tcp_req_info_read_again(fd, c)) 2887d500c338Sflorian return; 2888d500c338Sflorian } 2889853e076fSflorian if(morewrite && *morewrite) 2890853e076fSflorian tcp_more_write_again(fd, c); 2891ae8c6e27Sflorian return; 2892ae8c6e27Sflorian } 2893ae8c6e27Sflorian log_err("Ignored event %d for tcphdl.", event); 2894ae8c6e27Sflorian } 2895ae8c6e27Sflorian 2896ae8c6e27Sflorian /** Make http handler free for next assignment */ 2897ae8c6e27Sflorian static void 2898ae8c6e27Sflorian reclaim_http_handler(struct comm_point* c) 2899ae8c6e27Sflorian { 2900ae8c6e27Sflorian log_assert(c->type == comm_http); 2901ae8c6e27Sflorian if(c->ssl) { 2902ae8c6e27Sflorian #ifdef HAVE_SSL 2903ae8c6e27Sflorian SSL_shutdown(c->ssl); 2904ae8c6e27Sflorian SSL_free(c->ssl); 2905ae8c6e27Sflorian c->ssl = NULL; 2906ae8c6e27Sflorian #endif 2907ae8c6e27Sflorian } 2908ae8c6e27Sflorian comm_point_close(c); 2909ae8c6e27Sflorian if(c->tcp_parent) { 2910a1a7ba80Sflorian if(c != c->tcp_parent->tcp_free) { 2911ae8c6e27Sflorian c->tcp_parent->cur_tcp_count--; 2912ae8c6e27Sflorian c->tcp_free = c->tcp_parent->tcp_free; 2913ae8c6e27Sflorian c->tcp_parent->tcp_free = c; 2914a1a7ba80Sflorian } 2915ae8c6e27Sflorian if(!c->tcp_free) { 2916ae8c6e27Sflorian /* re-enable listening on accept socket */ 2917ae8c6e27Sflorian comm_point_start_listening(c->tcp_parent, -1, -1); 2918ae8c6e27Sflorian } 2919ae8c6e27Sflorian } 2920ae8c6e27Sflorian } 2921ae8c6e27Sflorian 2922ae8c6e27Sflorian /** read more data for http (with ssl) */ 2923ae8c6e27Sflorian static int 2924ae8c6e27Sflorian ssl_http_read_more(struct comm_point* c) 2925ae8c6e27Sflorian { 2926ae8c6e27Sflorian #ifdef HAVE_SSL 2927ae8c6e27Sflorian int r; 2928ae8c6e27Sflorian log_assert(sldns_buffer_remaining(c->buffer) > 0); 2929ae8c6e27Sflorian ERR_clear_error(); 2930ae8c6e27Sflorian r = SSL_read(c->ssl, (void*)sldns_buffer_current(c->buffer), 2931ae8c6e27Sflorian (int)sldns_buffer_remaining(c->buffer)); 2932ae8c6e27Sflorian if(r <= 0) { 2933ae8c6e27Sflorian int want = SSL_get_error(c->ssl, r); 2934ae8c6e27Sflorian if(want == SSL_ERROR_ZERO_RETURN) { 2935ae8c6e27Sflorian return 0; /* shutdown, closed */ 2936ae8c6e27Sflorian } else if(want == SSL_ERROR_WANT_READ) { 2937ae8c6e27Sflorian return 1; /* read more later */ 2938ae8c6e27Sflorian } else if(want == SSL_ERROR_WANT_WRITE) { 2939ae8c6e27Sflorian c->ssl_shake_state = comm_ssl_shake_hs_write; 2940ae8c6e27Sflorian comm_point_listen_for_rw(c, 0, 1); 2941ae8c6e27Sflorian return 1; 2942ae8c6e27Sflorian } else if(want == SSL_ERROR_SYSCALL) { 29439b465e50Sflorian #ifdef ECONNRESET 29449b465e50Sflorian if(errno == ECONNRESET && verbosity < 2) 29459b465e50Sflorian return 0; /* silence reset by peer */ 29469b465e50Sflorian #endif 2947ae8c6e27Sflorian if(errno != 0) 2948ae8c6e27Sflorian log_err("SSL_read syscall: %s", 2949ae8c6e27Sflorian strerror(errno)); 2950ae8c6e27Sflorian return 0; 2951ae8c6e27Sflorian } 295254cc57acSflorian log_crypto_err_io("could not SSL_read", want); 2953ae8c6e27Sflorian return 0; 2954ae8c6e27Sflorian } 2955411c5950Sflorian verbose(VERB_ALGO, "ssl http read more skip to %d + %d", 2956411c5950Sflorian (int)sldns_buffer_position(c->buffer), (int)r); 2957ae8c6e27Sflorian sldns_buffer_skip(c->buffer, (ssize_t)r); 2958ae8c6e27Sflorian return 1; 2959ae8c6e27Sflorian #else 2960ae8c6e27Sflorian (void)c; 2961ae8c6e27Sflorian return 0; 2962ae8c6e27Sflorian #endif /* HAVE_SSL */ 2963ae8c6e27Sflorian } 2964ae8c6e27Sflorian 2965ae8c6e27Sflorian /** read more data for http */ 2966ae8c6e27Sflorian static int 2967ae8c6e27Sflorian http_read_more(int fd, struct comm_point* c) 2968ae8c6e27Sflorian { 2969ae8c6e27Sflorian ssize_t r; 2970ae8c6e27Sflorian log_assert(sldns_buffer_remaining(c->buffer) > 0); 2971ae8c6e27Sflorian r = recv(fd, (void*)sldns_buffer_current(c->buffer), 29725c45b740Sflorian sldns_buffer_remaining(c->buffer), MSG_DONTWAIT); 2973ae8c6e27Sflorian if(r == 0) { 2974ae8c6e27Sflorian return 0; 2975ae8c6e27Sflorian } else if(r == -1) { 2976ae8c6e27Sflorian #ifndef USE_WINSOCK 2977ae8c6e27Sflorian if(errno == EINTR || errno == EAGAIN) 2978ae8c6e27Sflorian return 1; 2979ae8c6e27Sflorian #else /* USE_WINSOCK */ 2980ae8c6e27Sflorian if(WSAGetLastError() == WSAECONNRESET) 2981ae8c6e27Sflorian return 0; 2982ae8c6e27Sflorian if(WSAGetLastError() == WSAEINPROGRESS) 2983ae8c6e27Sflorian return 1; 2984ae8c6e27Sflorian if(WSAGetLastError() == WSAEWOULDBLOCK) { 2985ae8c6e27Sflorian ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_READ); 2986ae8c6e27Sflorian return 1; 2987ae8c6e27Sflorian } 2988ae8c6e27Sflorian #endif 2989f4f0f0ceSflorian log_err_addr("read (in http r)", sock_strerror(errno), 29905c45b740Sflorian &c->repinfo.remote_addr, c->repinfo.remote_addrlen); 2991ae8c6e27Sflorian return 0; 2992ae8c6e27Sflorian } 2993411c5950Sflorian verbose(VERB_ALGO, "http read more skip to %d + %d", 2994411c5950Sflorian (int)sldns_buffer_position(c->buffer), (int)r); 2995ae8c6e27Sflorian sldns_buffer_skip(c->buffer, r); 2996ae8c6e27Sflorian return 1; 2997ae8c6e27Sflorian } 2998ae8c6e27Sflorian 2999ae8c6e27Sflorian /** return true if http header has been read (one line complete) */ 3000ae8c6e27Sflorian static int 3001ae8c6e27Sflorian http_header_done(sldns_buffer* buf) 3002ae8c6e27Sflorian { 3003ae8c6e27Sflorian size_t i; 3004ae8c6e27Sflorian for(i=sldns_buffer_position(buf); i<sldns_buffer_limit(buf); i++) { 3005ae8c6e27Sflorian /* there was a \r before the \n, but we ignore that */ 3006ae8c6e27Sflorian if((char)sldns_buffer_read_u8_at(buf, i) == '\n') 3007ae8c6e27Sflorian return 1; 3008ae8c6e27Sflorian } 3009ae8c6e27Sflorian return 0; 3010ae8c6e27Sflorian } 3011ae8c6e27Sflorian 3012ae8c6e27Sflorian /** return character string into buffer for header line, moves buffer 3013ae8c6e27Sflorian * past that line and puts zero terminator into linefeed-newline */ 3014ae8c6e27Sflorian static char* 3015ae8c6e27Sflorian http_header_line(sldns_buffer* buf) 3016ae8c6e27Sflorian { 3017ae8c6e27Sflorian char* result = (char*)sldns_buffer_current(buf); 3018ae8c6e27Sflorian size_t i; 3019ae8c6e27Sflorian for(i=sldns_buffer_position(buf); i<sldns_buffer_limit(buf); i++) { 3020ae8c6e27Sflorian /* terminate the string on the \r */ 3021ae8c6e27Sflorian if((char)sldns_buffer_read_u8_at(buf, i) == '\r') 3022ae8c6e27Sflorian sldns_buffer_write_u8_at(buf, i, 0); 3023ae8c6e27Sflorian /* terminate on the \n and skip past the it and done */ 3024ae8c6e27Sflorian if((char)sldns_buffer_read_u8_at(buf, i) == '\n') { 3025ae8c6e27Sflorian sldns_buffer_write_u8_at(buf, i, 0); 3026ae8c6e27Sflorian sldns_buffer_set_position(buf, i+1); 3027ae8c6e27Sflorian return result; 3028ae8c6e27Sflorian } 3029ae8c6e27Sflorian } 3030ae8c6e27Sflorian return NULL; 3031ae8c6e27Sflorian } 3032ae8c6e27Sflorian 3033ae8c6e27Sflorian /** move unread buffer to start and clear rest for putting the rest into it */ 3034ae8c6e27Sflorian static void 3035ae8c6e27Sflorian http_moveover_buffer(sldns_buffer* buf) 3036ae8c6e27Sflorian { 3037ae8c6e27Sflorian size_t pos = sldns_buffer_position(buf); 3038ae8c6e27Sflorian size_t len = sldns_buffer_remaining(buf); 3039ae8c6e27Sflorian sldns_buffer_clear(buf); 3040ae8c6e27Sflorian memmove(sldns_buffer_begin(buf), sldns_buffer_at(buf, pos), len); 3041ae8c6e27Sflorian sldns_buffer_set_position(buf, len); 3042ae8c6e27Sflorian } 3043ae8c6e27Sflorian 3044ae8c6e27Sflorian /** a http header is complete, process it */ 3045ae8c6e27Sflorian static int 3046ae8c6e27Sflorian http_process_initial_header(struct comm_point* c) 3047ae8c6e27Sflorian { 3048ae8c6e27Sflorian char* line = http_header_line(c->buffer); 3049ae8c6e27Sflorian if(!line) return 1; 3050ae8c6e27Sflorian verbose(VERB_ALGO, "http header: %s", line); 3051ae8c6e27Sflorian if(strncasecmp(line, "HTTP/1.1 ", 9) == 0) { 3052ae8c6e27Sflorian /* check returncode */ 3053ae8c6e27Sflorian if(line[9] != '2') { 3054ae8c6e27Sflorian verbose(VERB_ALGO, "http bad status %s", line+9); 3055ae8c6e27Sflorian return 0; 3056ae8c6e27Sflorian } 3057ae8c6e27Sflorian } else if(strncasecmp(line, "Content-Length: ", 16) == 0) { 3058ae8c6e27Sflorian if(!c->http_is_chunked) 3059ae8c6e27Sflorian c->tcp_byte_count = (size_t)atoi(line+16); 3060ae8c6e27Sflorian } else if(strncasecmp(line, "Transfer-Encoding: chunked", 19+7) == 0) { 3061ae8c6e27Sflorian c->tcp_byte_count = 0; 3062ae8c6e27Sflorian c->http_is_chunked = 1; 3063ae8c6e27Sflorian } else if(line[0] == 0) { 3064ae8c6e27Sflorian /* end of initial headers */ 3065ae8c6e27Sflorian c->http_in_headers = 0; 3066ae8c6e27Sflorian if(c->http_is_chunked) 3067ae8c6e27Sflorian c->http_in_chunk_headers = 1; 3068ae8c6e27Sflorian /* remove header text from front of buffer 3069ae8c6e27Sflorian * the buffer is going to be used to return the data segment 3070ae8c6e27Sflorian * itself and we don't want the header to get returned 3071ae8c6e27Sflorian * prepended with it */ 3072ae8c6e27Sflorian http_moveover_buffer(c->buffer); 3073ae8c6e27Sflorian sldns_buffer_flip(c->buffer); 3074ae8c6e27Sflorian return 1; 3075ae8c6e27Sflorian } 3076ae8c6e27Sflorian /* ignore other headers */ 3077ae8c6e27Sflorian return 1; 3078ae8c6e27Sflorian } 3079ae8c6e27Sflorian 3080ae8c6e27Sflorian /** a chunk header is complete, process it, return 0=fail, 1=continue next 3081ae8c6e27Sflorian * header line, 2=done with chunked transfer*/ 3082ae8c6e27Sflorian static int 3083ae8c6e27Sflorian http_process_chunk_header(struct comm_point* c) 3084ae8c6e27Sflorian { 3085ae8c6e27Sflorian char* line = http_header_line(c->buffer); 3086ae8c6e27Sflorian if(!line) return 1; 3087ae8c6e27Sflorian if(c->http_in_chunk_headers == 3) { 3088ae8c6e27Sflorian verbose(VERB_ALGO, "http chunk trailer: %s", line); 3089ae8c6e27Sflorian /* are we done ? */ 3090ae8c6e27Sflorian if(line[0] == 0 && c->tcp_byte_count == 0) { 3091ae8c6e27Sflorian /* callback of http reader when NETEVENT_DONE, 3092ae8c6e27Sflorian * end of data, with no data in buffer */ 3093ae8c6e27Sflorian sldns_buffer_set_position(c->buffer, 0); 3094ae8c6e27Sflorian sldns_buffer_set_limit(c->buffer, 0); 3095ae8c6e27Sflorian fptr_ok(fptr_whitelist_comm_point(c->callback)); 3096ae8c6e27Sflorian (void)(*c->callback)(c, c->cb_arg, NETEVENT_DONE, NULL); 3097ae8c6e27Sflorian /* return that we are done */ 3098ae8c6e27Sflorian return 2; 3099ae8c6e27Sflorian } 3100ae8c6e27Sflorian if(line[0] == 0) { 3101ae8c6e27Sflorian /* continue with header of the next chunk */ 3102ae8c6e27Sflorian c->http_in_chunk_headers = 1; 3103ae8c6e27Sflorian /* remove header text from front of buffer */ 3104ae8c6e27Sflorian http_moveover_buffer(c->buffer); 3105ae8c6e27Sflorian sldns_buffer_flip(c->buffer); 3106ae8c6e27Sflorian return 1; 3107ae8c6e27Sflorian } 3108ae8c6e27Sflorian /* ignore further trail headers */ 3109ae8c6e27Sflorian return 1; 3110ae8c6e27Sflorian } 3111ae8c6e27Sflorian verbose(VERB_ALGO, "http chunk header: %s", line); 3112ae8c6e27Sflorian if(c->http_in_chunk_headers == 1) { 3113ae8c6e27Sflorian /* read chunked start line */ 3114ae8c6e27Sflorian char* end = NULL; 3115ae8c6e27Sflorian c->tcp_byte_count = (size_t)strtol(line, &end, 16); 3116ae8c6e27Sflorian if(end == line) 3117ae8c6e27Sflorian return 0; 3118ae8c6e27Sflorian c->http_in_chunk_headers = 0; 3119ae8c6e27Sflorian /* remove header text from front of buffer */ 3120ae8c6e27Sflorian http_moveover_buffer(c->buffer); 3121ae8c6e27Sflorian sldns_buffer_flip(c->buffer); 3122ae8c6e27Sflorian if(c->tcp_byte_count == 0) { 3123ae8c6e27Sflorian /* done with chunks, process chunk_trailer lines */ 3124ae8c6e27Sflorian c->http_in_chunk_headers = 3; 3125ae8c6e27Sflorian } 3126ae8c6e27Sflorian return 1; 3127ae8c6e27Sflorian } 3128ae8c6e27Sflorian /* ignore other headers */ 3129ae8c6e27Sflorian return 1; 3130ae8c6e27Sflorian } 3131ae8c6e27Sflorian 3132411c5950Sflorian /** handle nonchunked data segment, 0=fail, 1=wait */ 3133ae8c6e27Sflorian static int 3134ae8c6e27Sflorian http_nonchunk_segment(struct comm_point* c) 3135ae8c6e27Sflorian { 3136ae8c6e27Sflorian /* c->buffer at position..limit has new data we read in. 3137ae8c6e27Sflorian * the buffer itself is full of nonchunked data. 3138ae8c6e27Sflorian * we are looking to read tcp_byte_count more data 3139ae8c6e27Sflorian * and then the transfer is done. */ 3140ae8c6e27Sflorian size_t remainbufferlen; 3141411c5950Sflorian size_t got_now = sldns_buffer_limit(c->buffer); 3142ae8c6e27Sflorian if(c->tcp_byte_count <= got_now) { 3143ae8c6e27Sflorian /* done, this is the last data fragment */ 3144ae8c6e27Sflorian c->http_stored = 0; 3145ae8c6e27Sflorian sldns_buffer_set_position(c->buffer, 0); 3146ae8c6e27Sflorian fptr_ok(fptr_whitelist_comm_point(c->callback)); 3147ae8c6e27Sflorian (void)(*c->callback)(c, c->cb_arg, NETEVENT_DONE, NULL); 3148ae8c6e27Sflorian return 1; 3149ae8c6e27Sflorian } 3150ae8c6e27Sflorian /* if we have the buffer space, 3151ae8c6e27Sflorian * read more data collected into the buffer */ 3152ae8c6e27Sflorian remainbufferlen = sldns_buffer_capacity(c->buffer) - 3153ae8c6e27Sflorian sldns_buffer_limit(c->buffer); 3154411c5950Sflorian if(remainbufferlen+got_now >= c->tcp_byte_count || 31557a05b9dfSflorian remainbufferlen >= (size_t)(c->ssl?16384:2048)) { 3156ae8c6e27Sflorian size_t total = sldns_buffer_limit(c->buffer); 3157ae8c6e27Sflorian sldns_buffer_clear(c->buffer); 3158ae8c6e27Sflorian sldns_buffer_set_position(c->buffer, total); 3159ae8c6e27Sflorian c->http_stored = total; 3160ae8c6e27Sflorian /* return and wait to read more */ 3161ae8c6e27Sflorian return 1; 3162ae8c6e27Sflorian } 3163ae8c6e27Sflorian /* call callback with this data amount, then 3164ae8c6e27Sflorian * wait for more */ 3165411c5950Sflorian c->tcp_byte_count -= got_now; 3166ae8c6e27Sflorian c->http_stored = 0; 3167ae8c6e27Sflorian sldns_buffer_set_position(c->buffer, 0); 3168ae8c6e27Sflorian fptr_ok(fptr_whitelist_comm_point(c->callback)); 3169ae8c6e27Sflorian (void)(*c->callback)(c, c->cb_arg, NETEVENT_NOERROR, NULL); 3170ae8c6e27Sflorian /* c->callback has to buffer_clear(c->buffer). */ 3171ae8c6e27Sflorian /* return and wait to read more */ 3172ae8c6e27Sflorian return 1; 3173ae8c6e27Sflorian } 3174ae8c6e27Sflorian 3175a8eaceedSflorian /** handle chunked data segment, return 0=fail, 1=wait, 2=process more */ 3176ae8c6e27Sflorian static int 3177ae8c6e27Sflorian http_chunked_segment(struct comm_point* c) 3178ae8c6e27Sflorian { 3179ae8c6e27Sflorian /* the c->buffer has from position..limit new data we read. */ 3180ae8c6e27Sflorian /* the current chunk has length tcp_byte_count. 3181ae8c6e27Sflorian * once we read that read more chunk headers. 3182ae8c6e27Sflorian */ 3183ae8c6e27Sflorian size_t remainbufferlen; 3184ae8c6e27Sflorian size_t got_now = sldns_buffer_limit(c->buffer) - c->http_stored; 3185a8eaceedSflorian 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)); 3186ae8c6e27Sflorian if(c->tcp_byte_count <= got_now) { 3187ae8c6e27Sflorian /* the chunk has completed (with perhaps some extra data 3188ae8c6e27Sflorian * from next chunk header and next chunk) */ 3189ae8c6e27Sflorian /* save too much info into temp buffer */ 3190ae8c6e27Sflorian size_t fraglen; 3191ae8c6e27Sflorian struct comm_reply repinfo; 3192ae8c6e27Sflorian c->http_stored = 0; 3193ae8c6e27Sflorian sldns_buffer_skip(c->buffer, (ssize_t)c->tcp_byte_count); 3194ae8c6e27Sflorian sldns_buffer_clear(c->http_temp); 3195ae8c6e27Sflorian sldns_buffer_write(c->http_temp, 3196ae8c6e27Sflorian sldns_buffer_current(c->buffer), 3197ae8c6e27Sflorian sldns_buffer_remaining(c->buffer)); 3198ae8c6e27Sflorian sldns_buffer_flip(c->http_temp); 3199ae8c6e27Sflorian 3200ae8c6e27Sflorian /* callback with this fragment */ 3201ae8c6e27Sflorian fraglen = sldns_buffer_position(c->buffer); 3202ae8c6e27Sflorian sldns_buffer_set_position(c->buffer, 0); 3203ae8c6e27Sflorian sldns_buffer_set_limit(c->buffer, fraglen); 3204ae8c6e27Sflorian repinfo = c->repinfo; 3205ae8c6e27Sflorian fptr_ok(fptr_whitelist_comm_point(c->callback)); 3206ae8c6e27Sflorian (void)(*c->callback)(c, c->cb_arg, NETEVENT_NOERROR, &repinfo); 3207ae8c6e27Sflorian /* c->callback has to buffer_clear(). */ 3208ae8c6e27Sflorian 3209ae8c6e27Sflorian /* is commpoint deleted? */ 3210ae8c6e27Sflorian if(!repinfo.c) { 3211ae8c6e27Sflorian return 1; 3212ae8c6e27Sflorian } 3213ae8c6e27Sflorian /* copy waiting info */ 3214ae8c6e27Sflorian sldns_buffer_clear(c->buffer); 3215ae8c6e27Sflorian sldns_buffer_write(c->buffer, 3216ae8c6e27Sflorian sldns_buffer_begin(c->http_temp), 3217ae8c6e27Sflorian sldns_buffer_remaining(c->http_temp)); 3218ae8c6e27Sflorian sldns_buffer_flip(c->buffer); 3219ae8c6e27Sflorian /* process end of chunk trailer header lines, until 3220ae8c6e27Sflorian * an empty line */ 3221ae8c6e27Sflorian c->http_in_chunk_headers = 3; 3222ae8c6e27Sflorian /* process more data in buffer (if any) */ 3223ae8c6e27Sflorian return 2; 3224ae8c6e27Sflorian } 3225ae8c6e27Sflorian c->tcp_byte_count -= got_now; 3226ae8c6e27Sflorian 3227ae8c6e27Sflorian /* if we have the buffer space, 3228ae8c6e27Sflorian * read more data collected into the buffer */ 3229ae8c6e27Sflorian remainbufferlen = sldns_buffer_capacity(c->buffer) - 3230ae8c6e27Sflorian sldns_buffer_limit(c->buffer); 3231ae8c6e27Sflorian if(remainbufferlen >= c->tcp_byte_count || 3232ae8c6e27Sflorian remainbufferlen >= 2048) { 3233ae8c6e27Sflorian size_t total = sldns_buffer_limit(c->buffer); 3234ae8c6e27Sflorian sldns_buffer_clear(c->buffer); 3235ae8c6e27Sflorian sldns_buffer_set_position(c->buffer, total); 3236ae8c6e27Sflorian c->http_stored = total; 3237ae8c6e27Sflorian /* return and wait to read more */ 3238ae8c6e27Sflorian return 1; 3239ae8c6e27Sflorian } 3240ae8c6e27Sflorian 3241ae8c6e27Sflorian /* callback of http reader for a new part of the data */ 3242ae8c6e27Sflorian c->http_stored = 0; 3243ae8c6e27Sflorian sldns_buffer_set_position(c->buffer, 0); 3244ae8c6e27Sflorian fptr_ok(fptr_whitelist_comm_point(c->callback)); 3245ae8c6e27Sflorian (void)(*c->callback)(c, c->cb_arg, NETEVENT_NOERROR, NULL); 3246ae8c6e27Sflorian /* c->callback has to buffer_clear(c->buffer). */ 3247ae8c6e27Sflorian /* return and wait to read more */ 3248ae8c6e27Sflorian return 1; 3249ae8c6e27Sflorian } 3250ae8c6e27Sflorian 3251f4f0f0ceSflorian #ifdef HAVE_NGHTTP2 3252f4f0f0ceSflorian /** Create new http2 session. Called when creating handling comm point. */ 325377c7a55cSflorian static struct http2_session* http2_session_create(struct comm_point* c) 3254f4f0f0ceSflorian { 3255f4f0f0ceSflorian struct http2_session* session = calloc(1, sizeof(*session)); 3256f4f0f0ceSflorian if(!session) { 3257f4f0f0ceSflorian log_err("malloc failure while creating http2 session"); 3258f4f0f0ceSflorian return NULL; 3259f4f0f0ceSflorian } 3260f4f0f0ceSflorian session->c = c; 3261f4f0f0ceSflorian 3262f4f0f0ceSflorian return session; 3263f4f0f0ceSflorian } 3264f4f0f0ceSflorian #endif 3265f4f0f0ceSflorian 3266f4f0f0ceSflorian /** Delete http2 session. After closing connection or on error */ 326777c7a55cSflorian static void http2_session_delete(struct http2_session* h2_session) 3268f4f0f0ceSflorian { 3269f4f0f0ceSflorian #ifdef HAVE_NGHTTP2 3270f4f0f0ceSflorian if(h2_session->callbacks) 3271f4f0f0ceSflorian nghttp2_session_callbacks_del(h2_session->callbacks); 3272f4f0f0ceSflorian free(h2_session); 3273f4f0f0ceSflorian #else 3274f4f0f0ceSflorian (void)h2_session; 3275f4f0f0ceSflorian #endif 3276f4f0f0ceSflorian } 3277f4f0f0ceSflorian 3278f4f0f0ceSflorian #ifdef HAVE_NGHTTP2 3279f4f0f0ceSflorian struct http2_stream* http2_stream_create(int32_t stream_id) 3280f4f0f0ceSflorian { 3281f4f0f0ceSflorian struct http2_stream* h2_stream = calloc(1, sizeof(*h2_stream)); 3282f4f0f0ceSflorian if(!h2_stream) { 3283f4f0f0ceSflorian log_err("malloc failure while creating http2 stream"); 3284f4f0f0ceSflorian return NULL; 3285f4f0f0ceSflorian } 3286f4f0f0ceSflorian h2_stream->stream_id = stream_id; 3287f4f0f0ceSflorian return h2_stream; 3288f4f0f0ceSflorian } 3289f4f0f0ceSflorian 3290f4f0f0ceSflorian /** Delete http2 stream. After session delete or stream close callback */ 3291f4f0f0ceSflorian static void http2_stream_delete(struct http2_session* h2_session, 3292f4f0f0ceSflorian struct http2_stream* h2_stream) 3293f4f0f0ceSflorian { 3294f4f0f0ceSflorian if(h2_stream->mesh_state) { 3295f4f0f0ceSflorian mesh_state_remove_reply(h2_stream->mesh, h2_stream->mesh_state, 3296f4f0f0ceSflorian h2_session->c); 3297f4f0f0ceSflorian h2_stream->mesh_state = NULL; 3298f4f0f0ceSflorian } 3299f4f0f0ceSflorian http2_req_stream_clear(h2_stream); 3300f4f0f0ceSflorian free(h2_stream); 3301f4f0f0ceSflorian } 3302f4f0f0ceSflorian #endif 3303f4f0f0ceSflorian 3304f4f0f0ceSflorian void http2_stream_add_meshstate(struct http2_stream* h2_stream, 3305f4f0f0ceSflorian struct mesh_area* mesh, struct mesh_state* m) 3306f4f0f0ceSflorian { 3307f4f0f0ceSflorian h2_stream->mesh = mesh; 3308f4f0f0ceSflorian h2_stream->mesh_state = m; 3309f4f0f0ceSflorian } 3310f4f0f0ceSflorian 3311*7037e34cSflorian void http2_stream_remove_mesh_state(struct http2_stream* h2_stream) 3312*7037e34cSflorian { 3313*7037e34cSflorian if(!h2_stream) 3314*7037e34cSflorian return; 3315*7037e34cSflorian h2_stream->mesh_state = NULL; 3316*7037e34cSflorian } 3317*7037e34cSflorian 3318f4f0f0ceSflorian /** delete http2 session server. After closing connection. */ 3319f4f0f0ceSflorian static void http2_session_server_delete(struct http2_session* h2_session) 3320f4f0f0ceSflorian { 3321f4f0f0ceSflorian #ifdef HAVE_NGHTTP2 3322f4f0f0ceSflorian struct http2_stream* h2_stream, *next; 3323f4f0f0ceSflorian nghttp2_session_del(h2_session->session); /* NULL input is fine */ 3324f4f0f0ceSflorian h2_session->session = NULL; 3325f4f0f0ceSflorian for(h2_stream = h2_session->first_stream; h2_stream;) { 3326f4f0f0ceSflorian next = h2_stream->next; 3327f4f0f0ceSflorian http2_stream_delete(h2_session, h2_stream); 3328f4f0f0ceSflorian h2_stream = next; 3329f4f0f0ceSflorian } 3330f4f0f0ceSflorian h2_session->first_stream = NULL; 3331f4f0f0ceSflorian h2_session->is_drop = 0; 3332f4f0f0ceSflorian h2_session->postpone_drop = 0; 3333f4f0f0ceSflorian h2_session->c->h2_stream = NULL; 3334f4f0f0ceSflorian #endif 3335f4f0f0ceSflorian (void)h2_session; 3336f4f0f0ceSflorian } 3337f4f0f0ceSflorian 3338f4f0f0ceSflorian #ifdef HAVE_NGHTTP2 3339f4f0f0ceSflorian void http2_session_add_stream(struct http2_session* h2_session, 3340f4f0f0ceSflorian struct http2_stream* h2_stream) 3341f4f0f0ceSflorian { 3342f4f0f0ceSflorian if(h2_session->first_stream) 3343f4f0f0ceSflorian h2_session->first_stream->prev = h2_stream; 3344f4f0f0ceSflorian h2_stream->next = h2_session->first_stream; 3345f4f0f0ceSflorian h2_session->first_stream = h2_stream; 3346f4f0f0ceSflorian } 3347f4f0f0ceSflorian 3348f4f0f0ceSflorian /** remove stream from session linked list. After stream close callback or 3349f4f0f0ceSflorian * closing connection */ 335077c7a55cSflorian static void http2_session_remove_stream(struct http2_session* h2_session, 3351f4f0f0ceSflorian struct http2_stream* h2_stream) 3352f4f0f0ceSflorian { 3353f4f0f0ceSflorian if(h2_stream->prev) 3354f4f0f0ceSflorian h2_stream->prev->next = h2_stream->next; 3355f4f0f0ceSflorian else 3356f4f0f0ceSflorian h2_session->first_stream = h2_stream->next; 3357f4f0f0ceSflorian if(h2_stream->next) 3358f4f0f0ceSflorian h2_stream->next->prev = h2_stream->prev; 3359f4f0f0ceSflorian 3360f4f0f0ceSflorian } 3361f4f0f0ceSflorian 3362f4f0f0ceSflorian int http2_stream_close_cb(nghttp2_session* ATTR_UNUSED(session), 3363f4f0f0ceSflorian int32_t stream_id, uint32_t ATTR_UNUSED(error_code), void* cb_arg) 3364f4f0f0ceSflorian { 3365f4f0f0ceSflorian struct http2_stream* h2_stream; 3366f4f0f0ceSflorian struct http2_session* h2_session = (struct http2_session*)cb_arg; 3367f4f0f0ceSflorian if(!(h2_stream = nghttp2_session_get_stream_user_data( 3368f4f0f0ceSflorian h2_session->session, stream_id))) { 3369f4f0f0ceSflorian return 0; 3370f4f0f0ceSflorian } 3371f4f0f0ceSflorian http2_session_remove_stream(h2_session, h2_stream); 3372f4f0f0ceSflorian http2_stream_delete(h2_session, h2_stream); 3373f4f0f0ceSflorian return 0; 3374f4f0f0ceSflorian } 3375f4f0f0ceSflorian 3376f4f0f0ceSflorian ssize_t http2_recv_cb(nghttp2_session* ATTR_UNUSED(session), uint8_t* buf, 3377f4f0f0ceSflorian size_t len, int ATTR_UNUSED(flags), void* cb_arg) 3378f4f0f0ceSflorian { 3379f4f0f0ceSflorian struct http2_session* h2_session = (struct http2_session*)cb_arg; 3380853e076fSflorian ssize_t ret; 3381f4f0f0ceSflorian 3382f4f0f0ceSflorian log_assert(h2_session->c->type == comm_http); 3383f4f0f0ceSflorian log_assert(h2_session->c->h2_session); 3384f4f0f0ceSflorian 3385853e076fSflorian #ifdef HAVE_SSL 3386853e076fSflorian if(h2_session->c->ssl) { 3387853e076fSflorian int r; 3388f4f0f0ceSflorian ERR_clear_error(); 3389f4f0f0ceSflorian r = SSL_read(h2_session->c->ssl, buf, len); 3390f4f0f0ceSflorian if(r <= 0) { 3391f4f0f0ceSflorian int want = SSL_get_error(h2_session->c->ssl, r); 3392f4f0f0ceSflorian if(want == SSL_ERROR_ZERO_RETURN) { 3393f4f0f0ceSflorian return NGHTTP2_ERR_EOF; 3394f4f0f0ceSflorian } else if(want == SSL_ERROR_WANT_READ) { 3395f4f0f0ceSflorian return NGHTTP2_ERR_WOULDBLOCK; 3396f4f0f0ceSflorian } else if(want == SSL_ERROR_WANT_WRITE) { 3397f4f0f0ceSflorian h2_session->c->ssl_shake_state = comm_ssl_shake_hs_write; 3398f4f0f0ceSflorian comm_point_listen_for_rw(h2_session->c, 0, 1); 3399f4f0f0ceSflorian return NGHTTP2_ERR_WOULDBLOCK; 3400f4f0f0ceSflorian } else if(want == SSL_ERROR_SYSCALL) { 3401f4f0f0ceSflorian #ifdef ECONNRESET 3402f4f0f0ceSflorian if(errno == ECONNRESET && verbosity < 2) 3403f4f0f0ceSflorian return NGHTTP2_ERR_CALLBACK_FAILURE; 3404f4f0f0ceSflorian #endif 3405f4f0f0ceSflorian if(errno != 0) 3406f4f0f0ceSflorian log_err("SSL_read syscall: %s", 3407f4f0f0ceSflorian strerror(errno)); 3408f4f0f0ceSflorian return NGHTTP2_ERR_CALLBACK_FAILURE; 3409f4f0f0ceSflorian } 341054cc57acSflorian log_crypto_err_io("could not SSL_read", want); 3411f4f0f0ceSflorian return NGHTTP2_ERR_CALLBACK_FAILURE; 3412f4f0f0ceSflorian } 3413f4f0f0ceSflorian return r; 3414853e076fSflorian } 3415853e076fSflorian #endif /* HAVE_SSL */ 3416853e076fSflorian 34175c45b740Sflorian ret = recv(h2_session->c->fd, buf, len, MSG_DONTWAIT); 3418853e076fSflorian if(ret == 0) { 3419853e076fSflorian return NGHTTP2_ERR_EOF; 3420853e076fSflorian } else if(ret < 0) { 3421853e076fSflorian #ifndef USE_WINSOCK 3422853e076fSflorian if(errno == EINTR || errno == EAGAIN) 3423853e076fSflorian return NGHTTP2_ERR_WOULDBLOCK; 3424853e076fSflorian #ifdef ECONNRESET 3425853e076fSflorian if(errno == ECONNRESET && verbosity < 2) 3426853e076fSflorian return NGHTTP2_ERR_CALLBACK_FAILURE; 3427f4f0f0ceSflorian #endif 3428853e076fSflorian log_err_addr("could not http2 recv: %s", strerror(errno), 34295c45b740Sflorian &h2_session->c->repinfo.remote_addr, 34305c45b740Sflorian h2_session->c->repinfo.remote_addrlen); 3431853e076fSflorian #else /* USE_WINSOCK */ 3432853e076fSflorian if(WSAGetLastError() == WSAECONNRESET) 3433853e076fSflorian return NGHTTP2_ERR_CALLBACK_FAILURE; 3434853e076fSflorian if(WSAGetLastError() == WSAEINPROGRESS) 3435853e076fSflorian return NGHTTP2_ERR_WOULDBLOCK; 3436853e076fSflorian if(WSAGetLastError() == WSAEWOULDBLOCK) { 3437853e076fSflorian ub_winsock_tcp_wouldblock(h2_session->c->ev->ev, 3438853e076fSflorian UB_EV_READ); 3439853e076fSflorian return NGHTTP2_ERR_WOULDBLOCK; 3440853e076fSflorian } 3441853e076fSflorian log_err_addr("could not http2 recv: %s", 3442853e076fSflorian wsa_strerror(WSAGetLastError()), 34435c45b740Sflorian &h2_session->c->repinfo.remote_addr, 34445c45b740Sflorian h2_session->c->repinfo.remote_addrlen); 3445853e076fSflorian #endif 3446853e076fSflorian return NGHTTP2_ERR_CALLBACK_FAILURE; 3447853e076fSflorian } 3448853e076fSflorian return ret; 3449f4f0f0ceSflorian } 3450f4f0f0ceSflorian #endif /* HAVE_NGHTTP2 */ 3451f4f0f0ceSflorian 3452f4f0f0ceSflorian /** Handle http2 read */ 3453f4f0f0ceSflorian static int 3454f4f0f0ceSflorian comm_point_http2_handle_read(int ATTR_UNUSED(fd), struct comm_point* c) 3455f4f0f0ceSflorian { 3456f4f0f0ceSflorian #ifdef HAVE_NGHTTP2 3457f4f0f0ceSflorian int ret; 3458f4f0f0ceSflorian log_assert(c->h2_session); 3459f4f0f0ceSflorian 3460f4f0f0ceSflorian /* reading until recv cb returns NGHTTP2_ERR_WOULDBLOCK */ 3461f4f0f0ceSflorian ret = nghttp2_session_recv(c->h2_session->session); 3462f4f0f0ceSflorian if(ret) { 3463f4f0f0ceSflorian if(ret != NGHTTP2_ERR_EOF && 3464f4f0f0ceSflorian ret != NGHTTP2_ERR_CALLBACK_FAILURE) { 3465853e076fSflorian char a[256]; 34665c45b740Sflorian addr_to_str(&c->repinfo.remote_addr, 34675c45b740Sflorian c->repinfo.remote_addrlen, a, sizeof(a)); 3468853e076fSflorian verbose(VERB_QUERY, "http2: session_recv from %s failed, " 3469853e076fSflorian "error: %s", a, nghttp2_strerror(ret)); 3470f4f0f0ceSflorian } 3471f4f0f0ceSflorian return 0; 3472f4f0f0ceSflorian } 3473f4f0f0ceSflorian if(nghttp2_session_want_write(c->h2_session->session)) { 3474f4f0f0ceSflorian c->tcp_is_reading = 0; 3475f4f0f0ceSflorian comm_point_stop_listening(c); 3476a8eaceedSflorian comm_point_start_listening(c, -1, adjusted_tcp_timeout(c)); 3477f4f0f0ceSflorian } else if(!nghttp2_session_want_read(c->h2_session->session)) 3478f4f0f0ceSflorian return 0; /* connection can be closed */ 3479f4f0f0ceSflorian return 1; 3480f4f0f0ceSflorian #else 3481f4f0f0ceSflorian (void)c; 3482f4f0f0ceSflorian return 0; 3483f4f0f0ceSflorian #endif 3484f4f0f0ceSflorian } 3485f4f0f0ceSflorian 3486ae8c6e27Sflorian /** 3487ae8c6e27Sflorian * Handle http reading callback. 3488ae8c6e27Sflorian * @param fd: file descriptor of socket. 3489ae8c6e27Sflorian * @param c: comm point to read from into buffer. 3490ae8c6e27Sflorian * @return: 0 on error 3491ae8c6e27Sflorian */ 3492ae8c6e27Sflorian static int 3493ae8c6e27Sflorian comm_point_http_handle_read(int fd, struct comm_point* c) 3494ae8c6e27Sflorian { 3495ae8c6e27Sflorian log_assert(c->type == comm_http); 3496ae8c6e27Sflorian log_assert(fd != -1); 3497ae8c6e27Sflorian 3498ae8c6e27Sflorian /* if we are in ssl handshake, handle SSL handshake */ 3499ae8c6e27Sflorian #ifdef HAVE_SSL 3500ae8c6e27Sflorian if(c->ssl && c->ssl_shake_state != comm_ssl_shake_none) { 3501ae8c6e27Sflorian if(!ssl_handshake(c)) 3502ae8c6e27Sflorian return 0; 3503ae8c6e27Sflorian if(c->ssl_shake_state != comm_ssl_shake_none) 3504ae8c6e27Sflorian return 1; 3505ae8c6e27Sflorian } 3506ae8c6e27Sflorian #endif /* HAVE_SSL */ 3507ae8c6e27Sflorian 3508ae8c6e27Sflorian if(!c->tcp_is_reading) 3509ae8c6e27Sflorian return 1; 3510f4f0f0ceSflorian 3511f4f0f0ceSflorian if(c->use_h2) { 3512f4f0f0ceSflorian return comm_point_http2_handle_read(fd, c); 3513f4f0f0ceSflorian } 3514f4f0f0ceSflorian 3515f4f0f0ceSflorian /* http version is <= http/1.1 */ 3516f4f0f0ceSflorian 3517f4f0f0ceSflorian if(c->http_min_version >= http_version_2) { 3518f4f0f0ceSflorian /* HTTP/2 failed, not allowed to use lower version. */ 3519f4f0f0ceSflorian return 0; 3520f4f0f0ceSflorian } 3521f4f0f0ceSflorian 3522ae8c6e27Sflorian /* read more data */ 3523ae8c6e27Sflorian if(c->ssl) { 3524ae8c6e27Sflorian if(!ssl_http_read_more(c)) 3525ae8c6e27Sflorian return 0; 3526ae8c6e27Sflorian } else { 3527ae8c6e27Sflorian if(!http_read_more(fd, c)) 3528ae8c6e27Sflorian return 0; 3529ae8c6e27Sflorian } 3530ae8c6e27Sflorian 3531411c5950Sflorian if(c->http_stored >= sldns_buffer_position(c->buffer)) { 3532411c5950Sflorian /* read did not work but we wanted more data, there is 3533411c5950Sflorian * no bytes to process now. */ 3534411c5950Sflorian return 1; 3535411c5950Sflorian } 3536ae8c6e27Sflorian sldns_buffer_flip(c->buffer); 3537a8eaceedSflorian /* if we are partway in a segment of data, position us at the point 3538a8eaceedSflorian * where we left off previously */ 3539a8eaceedSflorian if(c->http_stored < sldns_buffer_limit(c->buffer)) 3540a8eaceedSflorian sldns_buffer_set_position(c->buffer, c->http_stored); 3541a8eaceedSflorian else sldns_buffer_set_position(c->buffer, sldns_buffer_limit(c->buffer)); 3542f4f0f0ceSflorian 3543ae8c6e27Sflorian while(sldns_buffer_remaining(c->buffer) > 0) { 3544f4f0f0ceSflorian /* Handle HTTP/1.x data */ 3545ae8c6e27Sflorian /* if we are reading headers, read more headers */ 3546ae8c6e27Sflorian if(c->http_in_headers || c->http_in_chunk_headers) { 3547ae8c6e27Sflorian /* if header is done, process the header */ 3548ae8c6e27Sflorian if(!http_header_done(c->buffer)) { 3549ae8c6e27Sflorian /* copy remaining data to front of buffer 3550ae8c6e27Sflorian * and set rest for writing into it */ 3551ae8c6e27Sflorian http_moveover_buffer(c->buffer); 3552ae8c6e27Sflorian /* return and wait to read more */ 3553ae8c6e27Sflorian return 1; 3554ae8c6e27Sflorian } 3555ae8c6e27Sflorian if(!c->http_in_chunk_headers) { 3556ae8c6e27Sflorian /* process initial headers */ 3557ae8c6e27Sflorian if(!http_process_initial_header(c)) 3558ae8c6e27Sflorian return 0; 3559ae8c6e27Sflorian } else { 3560ae8c6e27Sflorian /* process chunk headers */ 3561ae8c6e27Sflorian int r = http_process_chunk_header(c); 3562ae8c6e27Sflorian if(r == 0) return 0; 3563ae8c6e27Sflorian if(r == 2) return 1; /* done */ 3564ae8c6e27Sflorian /* r == 1, continue */ 3565ae8c6e27Sflorian } 3566ae8c6e27Sflorian /* see if we have more to process */ 3567ae8c6e27Sflorian continue; 3568ae8c6e27Sflorian } 3569ae8c6e27Sflorian 3570ae8c6e27Sflorian if(!c->http_is_chunked) { 3571ae8c6e27Sflorian /* if we are reading nonchunks, process that*/ 3572ae8c6e27Sflorian return http_nonchunk_segment(c); 3573ae8c6e27Sflorian } else { 3574ae8c6e27Sflorian /* if we are reading chunks, read the chunk */ 3575ae8c6e27Sflorian int r = http_chunked_segment(c); 3576ae8c6e27Sflorian if(r == 0) return 0; 3577ae8c6e27Sflorian if(r == 1) return 1; 3578ae8c6e27Sflorian continue; 3579ae8c6e27Sflorian } 3580ae8c6e27Sflorian } 3581ae8c6e27Sflorian /* broke out of the loop; could not process header instead need 3582ae8c6e27Sflorian * to read more */ 3583ae8c6e27Sflorian /* moveover any remaining data and read more data */ 3584ae8c6e27Sflorian http_moveover_buffer(c->buffer); 3585ae8c6e27Sflorian /* return and wait to read more */ 3586ae8c6e27Sflorian return 1; 3587ae8c6e27Sflorian } 3588ae8c6e27Sflorian 3589ae8c6e27Sflorian /** check pending connect for http */ 3590ae8c6e27Sflorian static int 3591ae8c6e27Sflorian http_check_connect(int fd, struct comm_point* c) 3592ae8c6e27Sflorian { 3593ae8c6e27Sflorian /* check for pending error from nonblocking connect */ 3594ae8c6e27Sflorian /* from Stevens, unix network programming, vol1, 3rd ed, p450*/ 3595ae8c6e27Sflorian int error = 0; 3596ae8c6e27Sflorian socklen_t len = (socklen_t)sizeof(error); 3597ae8c6e27Sflorian if(getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&error, 3598ae8c6e27Sflorian &len) < 0){ 3599ae8c6e27Sflorian #ifndef USE_WINSOCK 3600ae8c6e27Sflorian error = errno; /* on solaris errno is error */ 3601ae8c6e27Sflorian #else /* USE_WINSOCK */ 3602ae8c6e27Sflorian error = WSAGetLastError(); 3603ae8c6e27Sflorian #endif 3604ae8c6e27Sflorian } 3605ae8c6e27Sflorian #ifndef USE_WINSOCK 3606ae8c6e27Sflorian #if defined(EINPROGRESS) && defined(EWOULDBLOCK) 3607ae8c6e27Sflorian if(error == EINPROGRESS || error == EWOULDBLOCK) 3608ae8c6e27Sflorian return 1; /* try again later */ 3609ae8c6e27Sflorian else 3610ae8c6e27Sflorian #endif 3611ae8c6e27Sflorian if(error != 0 && verbosity < 2) 3612ae8c6e27Sflorian return 0; /* silence lots of chatter in the logs */ 3613ae8c6e27Sflorian else if(error != 0) { 3614ae8c6e27Sflorian log_err_addr("http connect", strerror(error), 36155c45b740Sflorian &c->repinfo.remote_addr, c->repinfo.remote_addrlen); 3616ae8c6e27Sflorian #else /* USE_WINSOCK */ 3617ae8c6e27Sflorian /* examine error */ 3618ae8c6e27Sflorian if(error == WSAEINPROGRESS) 3619ae8c6e27Sflorian return 1; 3620ae8c6e27Sflorian else if(error == WSAEWOULDBLOCK) { 3621ae8c6e27Sflorian ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE); 3622ae8c6e27Sflorian return 1; 3623ae8c6e27Sflorian } else if(error != 0 && verbosity < 2) 3624ae8c6e27Sflorian return 0; 3625ae8c6e27Sflorian else if(error != 0) { 3626ae8c6e27Sflorian log_err_addr("http connect", wsa_strerror(error), 36275c45b740Sflorian &c->repinfo.remote_addr, c->repinfo.remote_addrlen); 3628ae8c6e27Sflorian #endif /* USE_WINSOCK */ 3629ae8c6e27Sflorian return 0; 3630ae8c6e27Sflorian } 3631ae8c6e27Sflorian /* keep on processing this socket */ 3632ae8c6e27Sflorian return 2; 3633ae8c6e27Sflorian } 3634ae8c6e27Sflorian 3635ae8c6e27Sflorian /** write more data for http (with ssl) */ 3636ae8c6e27Sflorian static int 3637ae8c6e27Sflorian ssl_http_write_more(struct comm_point* c) 3638ae8c6e27Sflorian { 3639ae8c6e27Sflorian #ifdef HAVE_SSL 3640ae8c6e27Sflorian int r; 3641ae8c6e27Sflorian log_assert(sldns_buffer_remaining(c->buffer) > 0); 3642ae8c6e27Sflorian ERR_clear_error(); 3643ae8c6e27Sflorian r = SSL_write(c->ssl, (void*)sldns_buffer_current(c->buffer), 3644ae8c6e27Sflorian (int)sldns_buffer_remaining(c->buffer)); 3645ae8c6e27Sflorian if(r <= 0) { 3646ae8c6e27Sflorian int want = SSL_get_error(c->ssl, r); 3647ae8c6e27Sflorian if(want == SSL_ERROR_ZERO_RETURN) { 3648ae8c6e27Sflorian return 0; /* closed */ 3649ae8c6e27Sflorian } else if(want == SSL_ERROR_WANT_READ) { 36509b465e50Sflorian c->ssl_shake_state = comm_ssl_shake_hs_read; 3651ae8c6e27Sflorian comm_point_listen_for_rw(c, 1, 0); 3652ae8c6e27Sflorian return 1; /* wait for read condition */ 3653ae8c6e27Sflorian } else if(want == SSL_ERROR_WANT_WRITE) { 3654ae8c6e27Sflorian return 1; /* write more later */ 3655ae8c6e27Sflorian } else if(want == SSL_ERROR_SYSCALL) { 36569b465e50Sflorian #ifdef EPIPE 36579b465e50Sflorian if(errno == EPIPE && verbosity < 2) 36589b465e50Sflorian return 0; /* silence 'broken pipe' */ 36599b465e50Sflorian #endif 3660ae8c6e27Sflorian if(errno != 0) 3661ae8c6e27Sflorian log_err("SSL_write syscall: %s", 3662ae8c6e27Sflorian strerror(errno)); 3663ae8c6e27Sflorian return 0; 3664ae8c6e27Sflorian } 366554cc57acSflorian log_crypto_err_io("could not SSL_write", want); 3666ae8c6e27Sflorian return 0; 3667ae8c6e27Sflorian } 3668ae8c6e27Sflorian sldns_buffer_skip(c->buffer, (ssize_t)r); 3669ae8c6e27Sflorian return 1; 3670ae8c6e27Sflorian #else 3671ae8c6e27Sflorian (void)c; 3672ae8c6e27Sflorian return 0; 3673ae8c6e27Sflorian #endif /* HAVE_SSL */ 3674ae8c6e27Sflorian } 3675ae8c6e27Sflorian 3676ae8c6e27Sflorian /** write more data for http */ 3677ae8c6e27Sflorian static int 3678ae8c6e27Sflorian http_write_more(int fd, struct comm_point* c) 3679ae8c6e27Sflorian { 3680ae8c6e27Sflorian ssize_t r; 3681ae8c6e27Sflorian log_assert(sldns_buffer_remaining(c->buffer) > 0); 3682ae8c6e27Sflorian r = send(fd, (void*)sldns_buffer_current(c->buffer), 3683ae8c6e27Sflorian sldns_buffer_remaining(c->buffer), 0); 3684ae8c6e27Sflorian if(r == -1) { 3685ae8c6e27Sflorian #ifndef USE_WINSOCK 3686ae8c6e27Sflorian if(errno == EINTR || errno == EAGAIN) 3687ae8c6e27Sflorian return 1; 3688ae8c6e27Sflorian #else 3689ae8c6e27Sflorian if(WSAGetLastError() == WSAEINPROGRESS) 3690ae8c6e27Sflorian return 1; 3691ae8c6e27Sflorian if(WSAGetLastError() == WSAEWOULDBLOCK) { 3692ae8c6e27Sflorian ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE); 3693ae8c6e27Sflorian return 1; 3694ae8c6e27Sflorian } 3695ae8c6e27Sflorian #endif 3696f4f0f0ceSflorian log_err_addr("http send r", sock_strerror(errno), 36975c45b740Sflorian &c->repinfo.remote_addr, c->repinfo.remote_addrlen); 3698ae8c6e27Sflorian return 0; 3699ae8c6e27Sflorian } 3700ae8c6e27Sflorian sldns_buffer_skip(c->buffer, r); 3701ae8c6e27Sflorian return 1; 3702ae8c6e27Sflorian } 3703ae8c6e27Sflorian 3704f4f0f0ceSflorian #ifdef HAVE_NGHTTP2 3705f4f0f0ceSflorian ssize_t http2_send_cb(nghttp2_session* ATTR_UNUSED(session), const uint8_t* buf, 3706f4f0f0ceSflorian size_t len, int ATTR_UNUSED(flags), void* cb_arg) 3707f4f0f0ceSflorian { 3708853e076fSflorian ssize_t ret; 3709f4f0f0ceSflorian struct http2_session* h2_session = (struct http2_session*)cb_arg; 3710f4f0f0ceSflorian log_assert(h2_session->c->type == comm_http); 3711f4f0f0ceSflorian log_assert(h2_session->c->h2_session); 3712f4f0f0ceSflorian 3713853e076fSflorian #ifdef HAVE_SSL 3714853e076fSflorian if(h2_session->c->ssl) { 3715853e076fSflorian int r; 3716f4f0f0ceSflorian ERR_clear_error(); 3717f4f0f0ceSflorian r = SSL_write(h2_session->c->ssl, buf, len); 3718f4f0f0ceSflorian if(r <= 0) { 3719f4f0f0ceSflorian int want = SSL_get_error(h2_session->c->ssl, r); 3720f4f0f0ceSflorian if(want == SSL_ERROR_ZERO_RETURN) { 3721f4f0f0ceSflorian return NGHTTP2_ERR_CALLBACK_FAILURE; 3722f4f0f0ceSflorian } else if(want == SSL_ERROR_WANT_READ) { 3723f4f0f0ceSflorian h2_session->c->ssl_shake_state = comm_ssl_shake_hs_read; 3724f4f0f0ceSflorian comm_point_listen_for_rw(h2_session->c, 1, 0); 3725f4f0f0ceSflorian return NGHTTP2_ERR_WOULDBLOCK; 3726f4f0f0ceSflorian } else if(want == SSL_ERROR_WANT_WRITE) { 3727f4f0f0ceSflorian return NGHTTP2_ERR_WOULDBLOCK; 3728f4f0f0ceSflorian } else if(want == SSL_ERROR_SYSCALL) { 3729f4f0f0ceSflorian #ifdef EPIPE 3730f4f0f0ceSflorian if(errno == EPIPE && verbosity < 2) 3731f4f0f0ceSflorian return NGHTTP2_ERR_CALLBACK_FAILURE; 3732f4f0f0ceSflorian #endif 3733f4f0f0ceSflorian if(errno != 0) 3734f4f0f0ceSflorian log_err("SSL_write syscall: %s", 3735f4f0f0ceSflorian strerror(errno)); 3736f4f0f0ceSflorian return NGHTTP2_ERR_CALLBACK_FAILURE; 3737f4f0f0ceSflorian } 373854cc57acSflorian log_crypto_err_io("could not SSL_write", want); 3739f4f0f0ceSflorian return NGHTTP2_ERR_CALLBACK_FAILURE; 3740f4f0f0ceSflorian } 3741f4f0f0ceSflorian return r; 3742853e076fSflorian } 3743853e076fSflorian #endif /* HAVE_SSL */ 3744853e076fSflorian 3745853e076fSflorian ret = send(h2_session->c->fd, buf, len, 0); 3746853e076fSflorian if(ret == 0) { 3747853e076fSflorian return NGHTTP2_ERR_CALLBACK_FAILURE; 3748853e076fSflorian } else if(ret < 0) { 3749853e076fSflorian #ifndef USE_WINSOCK 3750853e076fSflorian if(errno == EINTR || errno == EAGAIN) 3751853e076fSflorian return NGHTTP2_ERR_WOULDBLOCK; 3752853e076fSflorian #ifdef EPIPE 3753853e076fSflorian if(errno == EPIPE && verbosity < 2) 3754853e076fSflorian return NGHTTP2_ERR_CALLBACK_FAILURE; 3755f4f0f0ceSflorian #endif 3756853e076fSflorian #ifdef ECONNRESET 3757853e076fSflorian if(errno == ECONNRESET && verbosity < 2) 3758853e076fSflorian return NGHTTP2_ERR_CALLBACK_FAILURE; 3759853e076fSflorian #endif 3760853e076fSflorian log_err_addr("could not http2 write: %s", strerror(errno), 37615c45b740Sflorian &h2_session->c->repinfo.remote_addr, 37625c45b740Sflorian h2_session->c->repinfo.remote_addrlen); 3763853e076fSflorian #else /* USE_WINSOCK */ 3764853e076fSflorian if(WSAGetLastError() == WSAENOTCONN) 3765853e076fSflorian return NGHTTP2_ERR_WOULDBLOCK; 3766853e076fSflorian if(WSAGetLastError() == WSAEINPROGRESS) 3767853e076fSflorian return NGHTTP2_ERR_WOULDBLOCK; 3768853e076fSflorian if(WSAGetLastError() == WSAEWOULDBLOCK) { 3769853e076fSflorian ub_winsock_tcp_wouldblock(h2_session->c->ev->ev, 3770853e076fSflorian UB_EV_WRITE); 3771853e076fSflorian return NGHTTP2_ERR_WOULDBLOCK; 3772853e076fSflorian } 3773853e076fSflorian if(WSAGetLastError() == WSAECONNRESET && verbosity < 2) 3774853e076fSflorian return NGHTTP2_ERR_CALLBACK_FAILURE; 3775853e076fSflorian log_err_addr("could not http2 write: %s", 3776853e076fSflorian wsa_strerror(WSAGetLastError()), 37775c45b740Sflorian &h2_session->c->repinfo.remote_addr, 37785c45b740Sflorian h2_session->c->repinfo.remote_addrlen); 3779853e076fSflorian #endif 3780853e076fSflorian return NGHTTP2_ERR_CALLBACK_FAILURE; 3781853e076fSflorian } 3782853e076fSflorian return ret; 3783f4f0f0ceSflorian } 3784f4f0f0ceSflorian #endif /* HAVE_NGHTTP2 */ 3785f4f0f0ceSflorian 3786f4f0f0ceSflorian /** Handle http2 writing */ 3787f4f0f0ceSflorian static int 3788f4f0f0ceSflorian comm_point_http2_handle_write(int ATTR_UNUSED(fd), struct comm_point* c) 3789f4f0f0ceSflorian { 3790f4f0f0ceSflorian #ifdef HAVE_NGHTTP2 3791f4f0f0ceSflorian int ret; 3792f4f0f0ceSflorian log_assert(c->h2_session); 3793f4f0f0ceSflorian 3794f4f0f0ceSflorian ret = nghttp2_session_send(c->h2_session->session); 3795f4f0f0ceSflorian if(ret) { 3796f4f0f0ceSflorian verbose(VERB_QUERY, "http2: session_send failed, " 3797f4f0f0ceSflorian "error: %s", nghttp2_strerror(ret)); 3798f4f0f0ceSflorian return 0; 3799f4f0f0ceSflorian } 3800f4f0f0ceSflorian 3801f4f0f0ceSflorian if(nghttp2_session_want_read(c->h2_session->session)) { 3802f4f0f0ceSflorian c->tcp_is_reading = 1; 3803f4f0f0ceSflorian comm_point_stop_listening(c); 3804a8eaceedSflorian comm_point_start_listening(c, -1, adjusted_tcp_timeout(c)); 3805f4f0f0ceSflorian } else if(!nghttp2_session_want_write(c->h2_session->session)) 3806f4f0f0ceSflorian return 0; /* connection can be closed */ 3807f4f0f0ceSflorian return 1; 3808f4f0f0ceSflorian #else 3809f4f0f0ceSflorian (void)c; 3810f4f0f0ceSflorian return 0; 3811f4f0f0ceSflorian #endif 3812f4f0f0ceSflorian } 3813f4f0f0ceSflorian 3814ae8c6e27Sflorian /** 3815ae8c6e27Sflorian * Handle http writing callback. 3816ae8c6e27Sflorian * @param fd: file descriptor of socket. 3817ae8c6e27Sflorian * @param c: comm point to write buffer out of. 3818ae8c6e27Sflorian * @return: 0 on error 3819ae8c6e27Sflorian */ 3820ae8c6e27Sflorian static int 3821ae8c6e27Sflorian comm_point_http_handle_write(int fd, struct comm_point* c) 3822ae8c6e27Sflorian { 3823ae8c6e27Sflorian log_assert(c->type == comm_http); 3824ae8c6e27Sflorian log_assert(fd != -1); 3825ae8c6e27Sflorian 3826ae8c6e27Sflorian /* check pending connect errors, if that fails, we wait for more, 3827ae8c6e27Sflorian * or we can continue to write contents */ 3828ae8c6e27Sflorian if(c->tcp_check_nb_connect) { 3829ae8c6e27Sflorian int r = http_check_connect(fd, c); 3830ae8c6e27Sflorian if(r == 0) return 0; 3831ae8c6e27Sflorian if(r == 1) return 1; 3832ae8c6e27Sflorian c->tcp_check_nb_connect = 0; 3833ae8c6e27Sflorian } 3834ae8c6e27Sflorian /* if we are in ssl handshake, handle SSL handshake */ 3835ae8c6e27Sflorian #ifdef HAVE_SSL 3836ae8c6e27Sflorian if(c->ssl && c->ssl_shake_state != comm_ssl_shake_none) { 3837ae8c6e27Sflorian if(!ssl_handshake(c)) 3838ae8c6e27Sflorian return 0; 3839ae8c6e27Sflorian if(c->ssl_shake_state != comm_ssl_shake_none) 3840ae8c6e27Sflorian return 1; 3841ae8c6e27Sflorian } 3842ae8c6e27Sflorian #endif /* HAVE_SSL */ 3843ae8c6e27Sflorian if(c->tcp_is_reading) 3844ae8c6e27Sflorian return 1; 3845f4f0f0ceSflorian 3846f4f0f0ceSflorian if(c->use_h2) { 3847f4f0f0ceSflorian return comm_point_http2_handle_write(fd, c); 3848f4f0f0ceSflorian } 3849f4f0f0ceSflorian 3850f4f0f0ceSflorian /* http version is <= http/1.1 */ 3851f4f0f0ceSflorian 3852f4f0f0ceSflorian if(c->http_min_version >= http_version_2) { 3853f4f0f0ceSflorian /* HTTP/2 failed, not allowed to use lower version. */ 3854f4f0f0ceSflorian return 0; 3855f4f0f0ceSflorian } 3856f4f0f0ceSflorian 3857ae8c6e27Sflorian /* if we are writing, write more */ 3858ae8c6e27Sflorian if(c->ssl) { 3859ae8c6e27Sflorian if(!ssl_http_write_more(c)) 3860ae8c6e27Sflorian return 0; 3861ae8c6e27Sflorian } else { 3862ae8c6e27Sflorian if(!http_write_more(fd, c)) 3863ae8c6e27Sflorian return 0; 3864ae8c6e27Sflorian } 3865ae8c6e27Sflorian 3866ae8c6e27Sflorian /* we write a single buffer contents, that can contain 3867ae8c6e27Sflorian * the http request, and then flip to read the results */ 3868ae8c6e27Sflorian /* see if write is done */ 3869ae8c6e27Sflorian if(sldns_buffer_remaining(c->buffer) == 0) { 3870ae8c6e27Sflorian sldns_buffer_clear(c->buffer); 3871ae8c6e27Sflorian if(c->tcp_do_toggle_rw) 3872ae8c6e27Sflorian c->tcp_is_reading = 1; 3873ae8c6e27Sflorian c->tcp_byte_count = 0; 3874ae8c6e27Sflorian /* switch from listening(write) to listening(read) */ 3875ae8c6e27Sflorian comm_point_stop_listening(c); 3876ae8c6e27Sflorian comm_point_start_listening(c, -1, -1); 3877ae8c6e27Sflorian } 3878ae8c6e27Sflorian return 1; 3879ae8c6e27Sflorian } 3880ae8c6e27Sflorian 3881ae8c6e27Sflorian void 3882ae8c6e27Sflorian comm_point_http_handle_callback(int fd, short event, void* arg) 3883ae8c6e27Sflorian { 3884ae8c6e27Sflorian struct comm_point* c = (struct comm_point*)arg; 3885ae8c6e27Sflorian log_assert(c->type == comm_http); 3886ae8c6e27Sflorian ub_comm_base_now(c->ev->base); 3887ae8c6e27Sflorian 38889b465e50Sflorian if(event&UB_EV_TIMEOUT) { 38899b465e50Sflorian verbose(VERB_QUERY, "http took too long, dropped"); 38909b465e50Sflorian reclaim_http_handler(c); 38919b465e50Sflorian if(!c->tcp_do_close) { 38929b465e50Sflorian fptr_ok(fptr_whitelist_comm_point(c->callback)); 38939b465e50Sflorian (void)(*c->callback)(c, c->cb_arg, 38949b465e50Sflorian NETEVENT_TIMEOUT, NULL); 38959b465e50Sflorian } 38969b465e50Sflorian return; 38979b465e50Sflorian } 3898ae8c6e27Sflorian if(event&UB_EV_READ) { 3899ae8c6e27Sflorian if(!comm_point_http_handle_read(fd, c)) { 3900ae8c6e27Sflorian reclaim_http_handler(c); 3901ae8c6e27Sflorian if(!c->tcp_do_close) { 3902ae8c6e27Sflorian fptr_ok(fptr_whitelist_comm_point( 3903ae8c6e27Sflorian c->callback)); 3904ae8c6e27Sflorian (void)(*c->callback)(c, c->cb_arg, 3905ae8c6e27Sflorian NETEVENT_CLOSED, NULL); 3906ae8c6e27Sflorian } 3907ae8c6e27Sflorian } 3908ae8c6e27Sflorian return; 3909ae8c6e27Sflorian } 3910ae8c6e27Sflorian if(event&UB_EV_WRITE) { 3911ae8c6e27Sflorian if(!comm_point_http_handle_write(fd, c)) { 3912ae8c6e27Sflorian reclaim_http_handler(c); 3913ae8c6e27Sflorian if(!c->tcp_do_close) { 3914ae8c6e27Sflorian fptr_ok(fptr_whitelist_comm_point( 3915ae8c6e27Sflorian c->callback)); 3916ae8c6e27Sflorian (void)(*c->callback)(c, c->cb_arg, 3917ae8c6e27Sflorian NETEVENT_CLOSED, NULL); 3918ae8c6e27Sflorian } 3919ae8c6e27Sflorian } 3920ae8c6e27Sflorian return; 3921ae8c6e27Sflorian } 3922ae8c6e27Sflorian log_err("Ignored event %d for httphdl.", event); 3923ae8c6e27Sflorian } 3924ae8c6e27Sflorian 3925ae8c6e27Sflorian void comm_point_local_handle_callback(int fd, short event, void* arg) 3926ae8c6e27Sflorian { 3927ae8c6e27Sflorian struct comm_point* c = (struct comm_point*)arg; 3928ae8c6e27Sflorian log_assert(c->type == comm_local); 3929ae8c6e27Sflorian ub_comm_base_now(c->ev->base); 3930ae8c6e27Sflorian 3931ae8c6e27Sflorian if(event&UB_EV_READ) { 3932ae8c6e27Sflorian if(!comm_point_tcp_handle_read(fd, c, 1)) { 3933ae8c6e27Sflorian fptr_ok(fptr_whitelist_comm_point(c->callback)); 3934ae8c6e27Sflorian (void)(*c->callback)(c, c->cb_arg, NETEVENT_CLOSED, 3935ae8c6e27Sflorian NULL); 3936ae8c6e27Sflorian } 3937ae8c6e27Sflorian return; 3938ae8c6e27Sflorian } 3939ae8c6e27Sflorian log_err("Ignored event %d for localhdl.", event); 3940ae8c6e27Sflorian } 3941ae8c6e27Sflorian 3942ae8c6e27Sflorian void comm_point_raw_handle_callback(int ATTR_UNUSED(fd), 3943ae8c6e27Sflorian short event, void* arg) 3944ae8c6e27Sflorian { 3945ae8c6e27Sflorian struct comm_point* c = (struct comm_point*)arg; 3946ae8c6e27Sflorian int err = NETEVENT_NOERROR; 3947ae8c6e27Sflorian log_assert(c->type == comm_raw); 3948ae8c6e27Sflorian ub_comm_base_now(c->ev->base); 3949ae8c6e27Sflorian 3950ae8c6e27Sflorian if(event&UB_EV_TIMEOUT) 3951ae8c6e27Sflorian err = NETEVENT_TIMEOUT; 3952ae8c6e27Sflorian fptr_ok(fptr_whitelist_comm_point_raw(c->callback)); 3953ae8c6e27Sflorian (void)(*c->callback)(c, c->cb_arg, err, NULL); 3954ae8c6e27Sflorian } 3955ae8c6e27Sflorian 3956ae8c6e27Sflorian struct comm_point* 3957ae8c6e27Sflorian comm_point_create_udp(struct comm_base *base, int fd, sldns_buffer* buffer, 39585c45b740Sflorian int pp2_enabled, comm_point_callback_type* callback, 39595c45b740Sflorian void* callback_arg, struct unbound_socket* socket) 3960ae8c6e27Sflorian { 3961ae8c6e27Sflorian struct comm_point* c = (struct comm_point*)calloc(1, 3962ae8c6e27Sflorian sizeof(struct comm_point)); 3963ae8c6e27Sflorian short evbits; 3964ae8c6e27Sflorian if(!c) 3965ae8c6e27Sflorian return NULL; 3966ae8c6e27Sflorian c->ev = (struct internal_event*)calloc(1, 3967ae8c6e27Sflorian sizeof(struct internal_event)); 3968ae8c6e27Sflorian if(!c->ev) { 3969ae8c6e27Sflorian free(c); 3970ae8c6e27Sflorian return NULL; 3971ae8c6e27Sflorian } 3972ae8c6e27Sflorian c->ev->base = base; 3973ae8c6e27Sflorian c->fd = fd; 3974ae8c6e27Sflorian c->buffer = buffer; 3975ae8c6e27Sflorian c->timeout = NULL; 3976ae8c6e27Sflorian c->tcp_is_reading = 0; 3977ae8c6e27Sflorian c->tcp_byte_count = 0; 3978ae8c6e27Sflorian c->tcp_parent = NULL; 3979ae8c6e27Sflorian c->max_tcp_count = 0; 3980ae8c6e27Sflorian c->cur_tcp_count = 0; 3981ae8c6e27Sflorian c->tcp_handlers = NULL; 3982ae8c6e27Sflorian c->tcp_free = NULL; 3983ae8c6e27Sflorian c->type = comm_udp; 3984ae8c6e27Sflorian c->tcp_do_close = 0; 3985ae8c6e27Sflorian c->do_not_close = 0; 3986ae8c6e27Sflorian c->tcp_do_toggle_rw = 0; 3987ae8c6e27Sflorian c->tcp_check_nb_connect = 0; 3988ae8c6e27Sflorian #ifdef USE_MSG_FASTOPEN 3989ae8c6e27Sflorian c->tcp_do_fastopen = 0; 3990ae8c6e27Sflorian #endif 3991ae8c6e27Sflorian #ifdef USE_DNSCRYPT 3992ae8c6e27Sflorian c->dnscrypt = 0; 3993ae8c6e27Sflorian c->dnscrypt_buffer = buffer; 3994ae8c6e27Sflorian #endif 3995ae8c6e27Sflorian c->inuse = 0; 3996ae8c6e27Sflorian c->callback = callback; 3997ae8c6e27Sflorian c->cb_arg = callback_arg; 3998411c5950Sflorian c->socket = socket; 39995c45b740Sflorian c->pp2_enabled = pp2_enabled; 40005c45b740Sflorian c->pp2_header_state = pp2_header_none; 4001ae8c6e27Sflorian evbits = UB_EV_READ | UB_EV_PERSIST; 4002ae8c6e27Sflorian /* ub_event stuff */ 4003ae8c6e27Sflorian c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits, 4004ae8c6e27Sflorian comm_point_udp_callback, c); 4005ae8c6e27Sflorian if(c->ev->ev == NULL) { 4006ae8c6e27Sflorian log_err("could not baseset udp event"); 4007ae8c6e27Sflorian comm_point_delete(c); 4008ae8c6e27Sflorian return NULL; 4009ae8c6e27Sflorian } 4010ae8c6e27Sflorian if(fd!=-1 && ub_event_add(c->ev->ev, c->timeout) != 0 ) { 4011ae8c6e27Sflorian log_err("could not add udp event"); 4012ae8c6e27Sflorian comm_point_delete(c); 4013ae8c6e27Sflorian return NULL; 4014ae8c6e27Sflorian } 4015a8eaceedSflorian c->event_added = 1; 4016ae8c6e27Sflorian return c; 4017ae8c6e27Sflorian } 4018ae8c6e27Sflorian 401954cc57acSflorian #if defined(AF_INET6) && defined(IPV6_PKTINFO) && defined(HAVE_RECVMSG) 4020ae8c6e27Sflorian struct comm_point* 4021ae8c6e27Sflorian comm_point_create_udp_ancil(struct comm_base *base, int fd, 40225c45b740Sflorian sldns_buffer* buffer, int pp2_enabled, 4023411c5950Sflorian comm_point_callback_type* callback, void* callback_arg, struct unbound_socket* socket) 4024ae8c6e27Sflorian { 4025ae8c6e27Sflorian struct comm_point* c = (struct comm_point*)calloc(1, 4026ae8c6e27Sflorian sizeof(struct comm_point)); 4027ae8c6e27Sflorian short evbits; 4028ae8c6e27Sflorian if(!c) 4029ae8c6e27Sflorian return NULL; 4030ae8c6e27Sflorian c->ev = (struct internal_event*)calloc(1, 4031ae8c6e27Sflorian sizeof(struct internal_event)); 4032ae8c6e27Sflorian if(!c->ev) { 4033ae8c6e27Sflorian free(c); 4034ae8c6e27Sflorian return NULL; 4035ae8c6e27Sflorian } 4036ae8c6e27Sflorian c->ev->base = base; 4037ae8c6e27Sflorian c->fd = fd; 4038ae8c6e27Sflorian c->buffer = buffer; 4039ae8c6e27Sflorian c->timeout = NULL; 4040ae8c6e27Sflorian c->tcp_is_reading = 0; 4041ae8c6e27Sflorian c->tcp_byte_count = 0; 4042ae8c6e27Sflorian c->tcp_parent = NULL; 4043ae8c6e27Sflorian c->max_tcp_count = 0; 4044ae8c6e27Sflorian c->cur_tcp_count = 0; 4045ae8c6e27Sflorian c->tcp_handlers = NULL; 4046ae8c6e27Sflorian c->tcp_free = NULL; 4047ae8c6e27Sflorian c->type = comm_udp; 4048ae8c6e27Sflorian c->tcp_do_close = 0; 4049ae8c6e27Sflorian c->do_not_close = 0; 4050ae8c6e27Sflorian #ifdef USE_DNSCRYPT 4051ae8c6e27Sflorian c->dnscrypt = 0; 4052ae8c6e27Sflorian c->dnscrypt_buffer = buffer; 4053ae8c6e27Sflorian #endif 4054ae8c6e27Sflorian c->inuse = 0; 4055ae8c6e27Sflorian c->tcp_do_toggle_rw = 0; 4056ae8c6e27Sflorian c->tcp_check_nb_connect = 0; 4057ae8c6e27Sflorian #ifdef USE_MSG_FASTOPEN 4058ae8c6e27Sflorian c->tcp_do_fastopen = 0; 4059ae8c6e27Sflorian #endif 4060ae8c6e27Sflorian c->callback = callback; 4061ae8c6e27Sflorian c->cb_arg = callback_arg; 4062411c5950Sflorian c->socket = socket; 40635c45b740Sflorian c->pp2_enabled = pp2_enabled; 40645c45b740Sflorian c->pp2_header_state = pp2_header_none; 4065ae8c6e27Sflorian evbits = UB_EV_READ | UB_EV_PERSIST; 4066ae8c6e27Sflorian /* ub_event stuff */ 4067ae8c6e27Sflorian c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits, 4068ae8c6e27Sflorian comm_point_udp_ancil_callback, c); 4069ae8c6e27Sflorian if(c->ev->ev == NULL) { 4070ae8c6e27Sflorian log_err("could not baseset udp event"); 4071ae8c6e27Sflorian comm_point_delete(c); 4072ae8c6e27Sflorian return NULL; 4073ae8c6e27Sflorian } 4074ae8c6e27Sflorian if(fd!=-1 && ub_event_add(c->ev->ev, c->timeout) != 0 ) { 4075ae8c6e27Sflorian log_err("could not add udp event"); 4076ae8c6e27Sflorian comm_point_delete(c); 4077ae8c6e27Sflorian return NULL; 4078ae8c6e27Sflorian } 4079a8eaceedSflorian c->event_added = 1; 4080ae8c6e27Sflorian return c; 4081ae8c6e27Sflorian } 408254cc57acSflorian #endif 4083ae8c6e27Sflorian 4084ae8c6e27Sflorian static struct comm_point* 4085ae8c6e27Sflorian comm_point_create_tcp_handler(struct comm_base *base, 4086ae8c6e27Sflorian struct comm_point* parent, size_t bufsize, 4087e97c6e54Ssthen struct sldns_buffer* spoolbuf, comm_point_callback_type* callback, 4088411c5950Sflorian void* callback_arg, struct unbound_socket* socket) 4089ae8c6e27Sflorian { 4090ae8c6e27Sflorian struct comm_point* c = (struct comm_point*)calloc(1, 4091ae8c6e27Sflorian sizeof(struct comm_point)); 4092ae8c6e27Sflorian short evbits; 4093ae8c6e27Sflorian if(!c) 4094ae8c6e27Sflorian return NULL; 4095ae8c6e27Sflorian c->ev = (struct internal_event*)calloc(1, 4096ae8c6e27Sflorian sizeof(struct internal_event)); 4097ae8c6e27Sflorian if(!c->ev) { 4098ae8c6e27Sflorian free(c); 4099ae8c6e27Sflorian return NULL; 4100ae8c6e27Sflorian } 4101ae8c6e27Sflorian c->ev->base = base; 4102ae8c6e27Sflorian c->fd = -1; 4103ae8c6e27Sflorian c->buffer = sldns_buffer_new(bufsize); 4104ae8c6e27Sflorian if(!c->buffer) { 4105ae8c6e27Sflorian free(c->ev); 4106ae8c6e27Sflorian free(c); 4107ae8c6e27Sflorian return NULL; 4108ae8c6e27Sflorian } 4109ae8c6e27Sflorian c->timeout = (struct timeval*)malloc(sizeof(struct timeval)); 4110ae8c6e27Sflorian if(!c->timeout) { 4111ae8c6e27Sflorian sldns_buffer_free(c->buffer); 4112ae8c6e27Sflorian free(c->ev); 4113ae8c6e27Sflorian free(c); 4114ae8c6e27Sflorian return NULL; 4115ae8c6e27Sflorian } 4116ae8c6e27Sflorian c->tcp_is_reading = 0; 4117ae8c6e27Sflorian c->tcp_byte_count = 0; 4118ae8c6e27Sflorian c->tcp_parent = parent; 4119ae8c6e27Sflorian c->tcp_timeout_msec = parent->tcp_timeout_msec; 4120ae8c6e27Sflorian c->tcp_conn_limit = parent->tcp_conn_limit; 4121ae8c6e27Sflorian c->tcl_addr = NULL; 4122ae8c6e27Sflorian c->tcp_keepalive = 0; 4123ae8c6e27Sflorian c->max_tcp_count = 0; 4124ae8c6e27Sflorian c->cur_tcp_count = 0; 4125ae8c6e27Sflorian c->tcp_handlers = NULL; 4126ae8c6e27Sflorian c->tcp_free = NULL; 4127ae8c6e27Sflorian c->type = comm_tcp; 4128ae8c6e27Sflorian c->tcp_do_close = 0; 4129ae8c6e27Sflorian c->do_not_close = 0; 4130ae8c6e27Sflorian c->tcp_do_toggle_rw = 1; 4131ae8c6e27Sflorian c->tcp_check_nb_connect = 0; 4132ae8c6e27Sflorian #ifdef USE_MSG_FASTOPEN 4133ae8c6e27Sflorian c->tcp_do_fastopen = 0; 4134ae8c6e27Sflorian #endif 4135ae8c6e27Sflorian #ifdef USE_DNSCRYPT 4136ae8c6e27Sflorian c->dnscrypt = 0; 4137ae8c6e27Sflorian /* We don't know just yet if this is a dnscrypt channel. Allocation 4138ae8c6e27Sflorian * will be done when handling the callback. */ 4139ae8c6e27Sflorian c->dnscrypt_buffer = c->buffer; 4140ae8c6e27Sflorian #endif 4141ae8c6e27Sflorian c->repinfo.c = c; 4142ae8c6e27Sflorian c->callback = callback; 4143ae8c6e27Sflorian c->cb_arg = callback_arg; 4144411c5950Sflorian c->socket = socket; 41455c45b740Sflorian c->pp2_enabled = parent->pp2_enabled; 41465c45b740Sflorian c->pp2_header_state = pp2_header_none; 4147e97c6e54Ssthen if(spoolbuf) { 4148e97c6e54Ssthen c->tcp_req_info = tcp_req_info_create(spoolbuf); 4149e97c6e54Ssthen if(!c->tcp_req_info) { 4150e97c6e54Ssthen log_err("could not create tcp commpoint"); 4151e97c6e54Ssthen sldns_buffer_free(c->buffer); 4152e97c6e54Ssthen free(c->timeout); 4153e97c6e54Ssthen free(c->ev); 4154e97c6e54Ssthen free(c); 4155e97c6e54Ssthen return NULL; 4156e97c6e54Ssthen } 4157e97c6e54Ssthen c->tcp_req_info->cp = c; 4158e97c6e54Ssthen c->tcp_do_close = 1; 4159e97c6e54Ssthen c->tcp_do_toggle_rw = 0; 4160e97c6e54Ssthen } 4161ae8c6e27Sflorian /* add to parent free list */ 4162ae8c6e27Sflorian c->tcp_free = parent->tcp_free; 4163ae8c6e27Sflorian parent->tcp_free = c; 4164ae8c6e27Sflorian /* ub_event stuff */ 4165ae8c6e27Sflorian evbits = UB_EV_PERSIST | UB_EV_READ | UB_EV_TIMEOUT; 4166ae8c6e27Sflorian c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits, 4167ae8c6e27Sflorian comm_point_tcp_handle_callback, c); 4168ae8c6e27Sflorian if(c->ev->ev == NULL) 4169ae8c6e27Sflorian { 4170ae8c6e27Sflorian log_err("could not basetset tcphdl event"); 4171ae8c6e27Sflorian parent->tcp_free = c->tcp_free; 4172e97c6e54Ssthen tcp_req_info_delete(c->tcp_req_info); 4173e97c6e54Ssthen sldns_buffer_free(c->buffer); 4174e97c6e54Ssthen free(c->timeout); 4175ae8c6e27Sflorian free(c->ev); 4176ae8c6e27Sflorian free(c); 4177ae8c6e27Sflorian return NULL; 4178ae8c6e27Sflorian } 4179ae8c6e27Sflorian return c; 4180ae8c6e27Sflorian } 4181ae8c6e27Sflorian 4182f4f0f0ceSflorian static struct comm_point* 4183f4f0f0ceSflorian comm_point_create_http_handler(struct comm_base *base, 4184f4f0f0ceSflorian struct comm_point* parent, size_t bufsize, int harden_large_queries, 4185f4f0f0ceSflorian uint32_t http_max_streams, char* http_endpoint, 4186411c5950Sflorian comm_point_callback_type* callback, void* callback_arg, 4187411c5950Sflorian struct unbound_socket* socket) 4188f4f0f0ceSflorian { 4189f4f0f0ceSflorian struct comm_point* c = (struct comm_point*)calloc(1, 4190f4f0f0ceSflorian sizeof(struct comm_point)); 4191f4f0f0ceSflorian short evbits; 4192f4f0f0ceSflorian if(!c) 4193f4f0f0ceSflorian return NULL; 4194f4f0f0ceSflorian c->ev = (struct internal_event*)calloc(1, 4195f4f0f0ceSflorian sizeof(struct internal_event)); 4196f4f0f0ceSflorian if(!c->ev) { 4197f4f0f0ceSflorian free(c); 4198f4f0f0ceSflorian return NULL; 4199f4f0f0ceSflorian } 4200f4f0f0ceSflorian c->ev->base = base; 4201f4f0f0ceSflorian c->fd = -1; 4202f4f0f0ceSflorian c->buffer = sldns_buffer_new(bufsize); 4203f4f0f0ceSflorian if(!c->buffer) { 4204f4f0f0ceSflorian free(c->ev); 4205f4f0f0ceSflorian free(c); 4206f4f0f0ceSflorian return NULL; 4207f4f0f0ceSflorian } 4208f4f0f0ceSflorian c->timeout = (struct timeval*)malloc(sizeof(struct timeval)); 4209f4f0f0ceSflorian if(!c->timeout) { 4210f4f0f0ceSflorian sldns_buffer_free(c->buffer); 4211f4f0f0ceSflorian free(c->ev); 4212f4f0f0ceSflorian free(c); 4213f4f0f0ceSflorian return NULL; 4214f4f0f0ceSflorian } 4215f4f0f0ceSflorian c->tcp_is_reading = 0; 4216f4f0f0ceSflorian c->tcp_byte_count = 0; 4217f4f0f0ceSflorian c->tcp_parent = parent; 4218f4f0f0ceSflorian c->tcp_timeout_msec = parent->tcp_timeout_msec; 4219f4f0f0ceSflorian c->tcp_conn_limit = parent->tcp_conn_limit; 4220f4f0f0ceSflorian c->tcl_addr = NULL; 4221f4f0f0ceSflorian c->tcp_keepalive = 0; 4222f4f0f0ceSflorian c->max_tcp_count = 0; 4223f4f0f0ceSflorian c->cur_tcp_count = 0; 4224f4f0f0ceSflorian c->tcp_handlers = NULL; 4225f4f0f0ceSflorian c->tcp_free = NULL; 4226f4f0f0ceSflorian c->type = comm_http; 4227f4f0f0ceSflorian c->tcp_do_close = 1; 4228f4f0f0ceSflorian c->do_not_close = 0; 4229f4f0f0ceSflorian c->tcp_do_toggle_rw = 1; /* will be set to 0 after http2 upgrade */ 4230f4f0f0ceSflorian c->tcp_check_nb_connect = 0; 4231f4f0f0ceSflorian #ifdef USE_MSG_FASTOPEN 4232f4f0f0ceSflorian c->tcp_do_fastopen = 0; 4233f4f0f0ceSflorian #endif 4234f4f0f0ceSflorian #ifdef USE_DNSCRYPT 4235f4f0f0ceSflorian c->dnscrypt = 0; 4236f4f0f0ceSflorian c->dnscrypt_buffer = NULL; 4237f4f0f0ceSflorian #endif 4238f4f0f0ceSflorian c->repinfo.c = c; 4239f4f0f0ceSflorian c->callback = callback; 4240f4f0f0ceSflorian c->cb_arg = callback_arg; 4241411c5950Sflorian c->socket = socket; 42425c45b740Sflorian c->pp2_enabled = 0; 42435c45b740Sflorian c->pp2_header_state = pp2_header_none; 4244f4f0f0ceSflorian 4245f4f0f0ceSflorian c->http_min_version = http_version_2; 4246f4f0f0ceSflorian c->http2_stream_max_qbuffer_size = bufsize; 4247f4f0f0ceSflorian if(harden_large_queries && bufsize > 512) 4248f4f0f0ceSflorian c->http2_stream_max_qbuffer_size = 512; 4249f4f0f0ceSflorian c->http2_max_streams = http_max_streams; 4250f4f0f0ceSflorian if(!(c->http_endpoint = strdup(http_endpoint))) { 4251f4f0f0ceSflorian log_err("could not strdup http_endpoint"); 4252f4f0f0ceSflorian sldns_buffer_free(c->buffer); 4253f4f0f0ceSflorian free(c->timeout); 4254f4f0f0ceSflorian free(c->ev); 4255f4f0f0ceSflorian free(c); 4256f4f0f0ceSflorian return NULL; 4257f4f0f0ceSflorian } 4258f4f0f0ceSflorian c->use_h2 = 0; 4259f4f0f0ceSflorian #ifdef HAVE_NGHTTP2 4260f4f0f0ceSflorian if(!(c->h2_session = http2_session_create(c))) { 4261f4f0f0ceSflorian log_err("could not create http2 session"); 4262f4f0f0ceSflorian free(c->http_endpoint); 4263f4f0f0ceSflorian sldns_buffer_free(c->buffer); 4264f4f0f0ceSflorian free(c->timeout); 4265f4f0f0ceSflorian free(c->ev); 4266f4f0f0ceSflorian free(c); 4267f4f0f0ceSflorian return NULL; 4268f4f0f0ceSflorian } 4269f4f0f0ceSflorian if(!(c->h2_session->callbacks = http2_req_callbacks_create())) { 4270f4f0f0ceSflorian log_err("could not create http2 callbacks"); 4271f4f0f0ceSflorian http2_session_delete(c->h2_session); 4272f4f0f0ceSflorian free(c->http_endpoint); 4273f4f0f0ceSflorian sldns_buffer_free(c->buffer); 4274f4f0f0ceSflorian free(c->timeout); 4275f4f0f0ceSflorian free(c->ev); 4276f4f0f0ceSflorian free(c); 4277f4f0f0ceSflorian return NULL; 4278f4f0f0ceSflorian } 4279f4f0f0ceSflorian #endif 4280f4f0f0ceSflorian 4281f4f0f0ceSflorian /* add to parent free list */ 4282f4f0f0ceSflorian c->tcp_free = parent->tcp_free; 4283f4f0f0ceSflorian parent->tcp_free = c; 4284f4f0f0ceSflorian /* ub_event stuff */ 4285f4f0f0ceSflorian evbits = UB_EV_PERSIST | UB_EV_READ | UB_EV_TIMEOUT; 4286f4f0f0ceSflorian c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits, 4287f4f0f0ceSflorian comm_point_http_handle_callback, c); 4288f4f0f0ceSflorian if(c->ev->ev == NULL) 4289f4f0f0ceSflorian { 4290f4f0f0ceSflorian log_err("could not set http handler event"); 4291f4f0f0ceSflorian parent->tcp_free = c->tcp_free; 4292f4f0f0ceSflorian http2_session_delete(c->h2_session); 4293f4f0f0ceSflorian sldns_buffer_free(c->buffer); 4294f4f0f0ceSflorian free(c->timeout); 4295f4f0f0ceSflorian free(c->ev); 4296f4f0f0ceSflorian free(c); 4297f4f0f0ceSflorian return NULL; 4298f4f0f0ceSflorian } 4299f4f0f0ceSflorian return c; 4300f4f0f0ceSflorian } 4301f4f0f0ceSflorian 4302ae8c6e27Sflorian struct comm_point* 4303ae8c6e27Sflorian comm_point_create_tcp(struct comm_base *base, int fd, int num, 4304f4f0f0ceSflorian int idle_timeout, int harden_large_queries, 4305f4f0f0ceSflorian uint32_t http_max_streams, char* http_endpoint, 4306f4f0f0ceSflorian struct tcl_list* tcp_conn_limit, size_t bufsize, 4307f4f0f0ceSflorian struct sldns_buffer* spoolbuf, enum listen_type port_type, 43085c45b740Sflorian int pp2_enabled, comm_point_callback_type* callback, 43095c45b740Sflorian void* callback_arg, struct unbound_socket* socket) 4310ae8c6e27Sflorian { 4311ae8c6e27Sflorian struct comm_point* c = (struct comm_point*)calloc(1, 4312ae8c6e27Sflorian sizeof(struct comm_point)); 4313ae8c6e27Sflorian short evbits; 4314ae8c6e27Sflorian int i; 4315ae8c6e27Sflorian /* first allocate the TCP accept listener */ 4316ae8c6e27Sflorian if(!c) 4317ae8c6e27Sflorian return NULL; 4318ae8c6e27Sflorian c->ev = (struct internal_event*)calloc(1, 4319ae8c6e27Sflorian sizeof(struct internal_event)); 4320ae8c6e27Sflorian if(!c->ev) { 4321ae8c6e27Sflorian free(c); 4322ae8c6e27Sflorian return NULL; 4323ae8c6e27Sflorian } 4324ae8c6e27Sflorian c->ev->base = base; 4325ae8c6e27Sflorian c->fd = fd; 4326ae8c6e27Sflorian c->buffer = NULL; 4327ae8c6e27Sflorian c->timeout = NULL; 4328ae8c6e27Sflorian c->tcp_is_reading = 0; 4329ae8c6e27Sflorian c->tcp_byte_count = 0; 4330ae8c6e27Sflorian c->tcp_timeout_msec = idle_timeout; 4331ae8c6e27Sflorian c->tcp_conn_limit = tcp_conn_limit; 4332ae8c6e27Sflorian c->tcl_addr = NULL; 4333ae8c6e27Sflorian c->tcp_keepalive = 0; 4334ae8c6e27Sflorian c->tcp_parent = NULL; 4335ae8c6e27Sflorian c->max_tcp_count = num; 4336ae8c6e27Sflorian c->cur_tcp_count = 0; 4337ae8c6e27Sflorian c->tcp_handlers = (struct comm_point**)calloc((size_t)num, 4338ae8c6e27Sflorian sizeof(struct comm_point*)); 4339ae8c6e27Sflorian if(!c->tcp_handlers) { 4340ae8c6e27Sflorian free(c->ev); 4341ae8c6e27Sflorian free(c); 4342ae8c6e27Sflorian return NULL; 4343ae8c6e27Sflorian } 4344ae8c6e27Sflorian c->tcp_free = NULL; 4345ae8c6e27Sflorian c->type = comm_tcp_accept; 4346ae8c6e27Sflorian c->tcp_do_close = 0; 4347ae8c6e27Sflorian c->do_not_close = 0; 4348ae8c6e27Sflorian c->tcp_do_toggle_rw = 0; 4349ae8c6e27Sflorian c->tcp_check_nb_connect = 0; 4350ae8c6e27Sflorian #ifdef USE_MSG_FASTOPEN 4351ae8c6e27Sflorian c->tcp_do_fastopen = 0; 4352ae8c6e27Sflorian #endif 4353ae8c6e27Sflorian #ifdef USE_DNSCRYPT 4354ae8c6e27Sflorian c->dnscrypt = 0; 4355ae8c6e27Sflorian c->dnscrypt_buffer = NULL; 4356ae8c6e27Sflorian #endif 4357ae8c6e27Sflorian c->callback = NULL; 4358ae8c6e27Sflorian c->cb_arg = NULL; 4359411c5950Sflorian c->socket = socket; 43605c45b740Sflorian c->pp2_enabled = (port_type==listen_type_http?0:pp2_enabled); 43615c45b740Sflorian c->pp2_header_state = pp2_header_none; 4362ae8c6e27Sflorian evbits = UB_EV_READ | UB_EV_PERSIST; 4363ae8c6e27Sflorian /* ub_event stuff */ 4364ae8c6e27Sflorian c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits, 4365ae8c6e27Sflorian comm_point_tcp_accept_callback, c); 4366ae8c6e27Sflorian if(c->ev->ev == NULL) { 4367ae8c6e27Sflorian log_err("could not baseset tcpacc event"); 4368ae8c6e27Sflorian comm_point_delete(c); 4369ae8c6e27Sflorian return NULL; 4370ae8c6e27Sflorian } 4371ae8c6e27Sflorian if (ub_event_add(c->ev->ev, c->timeout) != 0) { 4372ae8c6e27Sflorian log_err("could not add tcpacc event"); 4373ae8c6e27Sflorian comm_point_delete(c); 4374ae8c6e27Sflorian return NULL; 4375ae8c6e27Sflorian } 4376a8eaceedSflorian c->event_added = 1; 4377f4f0f0ceSflorian /* now prealloc the handlers */ 4378ae8c6e27Sflorian for(i=0; i<num; i++) { 4379f4f0f0ceSflorian if(port_type == listen_type_tcp || 4380f4f0f0ceSflorian port_type == listen_type_ssl || 4381f4f0f0ceSflorian port_type == listen_type_tcp_dnscrypt) { 4382ae8c6e27Sflorian c->tcp_handlers[i] = comm_point_create_tcp_handler(base, 4383411c5950Sflorian c, bufsize, spoolbuf, callback, callback_arg, socket); 4384f4f0f0ceSflorian } else if(port_type == listen_type_http) { 4385f4f0f0ceSflorian c->tcp_handlers[i] = comm_point_create_http_handler( 4386f4f0f0ceSflorian base, c, bufsize, harden_large_queries, 4387f4f0f0ceSflorian http_max_streams, http_endpoint, 4388411c5950Sflorian callback, callback_arg, socket); 4389f4f0f0ceSflorian } 4390f4f0f0ceSflorian else { 4391f4f0f0ceSflorian log_err("could not create tcp handler, unknown listen " 4392f4f0f0ceSflorian "type"); 4393f4f0f0ceSflorian return NULL; 4394f4f0f0ceSflorian } 4395ae8c6e27Sflorian if(!c->tcp_handlers[i]) { 4396ae8c6e27Sflorian comm_point_delete(c); 4397ae8c6e27Sflorian return NULL; 4398ae8c6e27Sflorian } 4399ae8c6e27Sflorian } 4400ae8c6e27Sflorian 4401ae8c6e27Sflorian return c; 4402ae8c6e27Sflorian } 4403ae8c6e27Sflorian 4404ae8c6e27Sflorian struct comm_point* 4405ae8c6e27Sflorian comm_point_create_tcp_out(struct comm_base *base, size_t bufsize, 4406ae8c6e27Sflorian comm_point_callback_type* callback, void* callback_arg) 4407ae8c6e27Sflorian { 4408ae8c6e27Sflorian struct comm_point* c = (struct comm_point*)calloc(1, 4409ae8c6e27Sflorian sizeof(struct comm_point)); 4410ae8c6e27Sflorian short evbits; 4411ae8c6e27Sflorian if(!c) 4412ae8c6e27Sflorian return NULL; 4413ae8c6e27Sflorian c->ev = (struct internal_event*)calloc(1, 4414ae8c6e27Sflorian sizeof(struct internal_event)); 4415ae8c6e27Sflorian if(!c->ev) { 4416ae8c6e27Sflorian free(c); 4417ae8c6e27Sflorian return NULL; 4418ae8c6e27Sflorian } 4419ae8c6e27Sflorian c->ev->base = base; 4420ae8c6e27Sflorian c->fd = -1; 4421ae8c6e27Sflorian c->buffer = sldns_buffer_new(bufsize); 4422ae8c6e27Sflorian if(!c->buffer) { 4423ae8c6e27Sflorian free(c->ev); 4424ae8c6e27Sflorian free(c); 4425ae8c6e27Sflorian return NULL; 4426ae8c6e27Sflorian } 4427ae8c6e27Sflorian c->timeout = NULL; 4428ae8c6e27Sflorian c->tcp_is_reading = 0; 4429ae8c6e27Sflorian c->tcp_byte_count = 0; 4430ae8c6e27Sflorian c->tcp_timeout_msec = TCP_QUERY_TIMEOUT; 4431ae8c6e27Sflorian c->tcp_conn_limit = NULL; 4432ae8c6e27Sflorian c->tcl_addr = NULL; 4433ae8c6e27Sflorian c->tcp_keepalive = 0; 4434ae8c6e27Sflorian c->tcp_parent = NULL; 4435ae8c6e27Sflorian c->max_tcp_count = 0; 4436ae8c6e27Sflorian c->cur_tcp_count = 0; 4437ae8c6e27Sflorian c->tcp_handlers = NULL; 4438ae8c6e27Sflorian c->tcp_free = NULL; 4439ae8c6e27Sflorian c->type = comm_tcp; 4440ae8c6e27Sflorian c->tcp_do_close = 0; 4441ae8c6e27Sflorian c->do_not_close = 0; 4442ae8c6e27Sflorian c->tcp_do_toggle_rw = 1; 4443ae8c6e27Sflorian c->tcp_check_nb_connect = 1; 4444ae8c6e27Sflorian #ifdef USE_MSG_FASTOPEN 4445ae8c6e27Sflorian c->tcp_do_fastopen = 1; 4446ae8c6e27Sflorian #endif 4447ae8c6e27Sflorian #ifdef USE_DNSCRYPT 4448ae8c6e27Sflorian c->dnscrypt = 0; 4449ae8c6e27Sflorian c->dnscrypt_buffer = c->buffer; 4450ae8c6e27Sflorian #endif 4451ae8c6e27Sflorian c->repinfo.c = c; 4452ae8c6e27Sflorian c->callback = callback; 4453ae8c6e27Sflorian c->cb_arg = callback_arg; 44545c45b740Sflorian c->pp2_enabled = 0; 44555c45b740Sflorian c->pp2_header_state = pp2_header_none; 4456ae8c6e27Sflorian evbits = UB_EV_PERSIST | UB_EV_WRITE; 4457ae8c6e27Sflorian c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits, 4458ae8c6e27Sflorian comm_point_tcp_handle_callback, c); 4459ae8c6e27Sflorian if(c->ev->ev == NULL) 4460ae8c6e27Sflorian { 4461ae8c6e27Sflorian log_err("could not baseset tcpout event"); 4462ae8c6e27Sflorian sldns_buffer_free(c->buffer); 4463ae8c6e27Sflorian free(c->ev); 4464ae8c6e27Sflorian free(c); 4465ae8c6e27Sflorian return NULL; 4466ae8c6e27Sflorian } 4467ae8c6e27Sflorian 4468ae8c6e27Sflorian return c; 4469ae8c6e27Sflorian } 4470ae8c6e27Sflorian 4471ae8c6e27Sflorian struct comm_point* 4472ae8c6e27Sflorian comm_point_create_http_out(struct comm_base *base, size_t bufsize, 4473ae8c6e27Sflorian comm_point_callback_type* callback, void* callback_arg, 4474ae8c6e27Sflorian sldns_buffer* temp) 4475ae8c6e27Sflorian { 4476ae8c6e27Sflorian struct comm_point* c = (struct comm_point*)calloc(1, 4477ae8c6e27Sflorian sizeof(struct comm_point)); 4478ae8c6e27Sflorian short evbits; 4479ae8c6e27Sflorian if(!c) 4480ae8c6e27Sflorian return NULL; 4481ae8c6e27Sflorian c->ev = (struct internal_event*)calloc(1, 4482ae8c6e27Sflorian sizeof(struct internal_event)); 4483ae8c6e27Sflorian if(!c->ev) { 4484ae8c6e27Sflorian free(c); 4485ae8c6e27Sflorian return NULL; 4486ae8c6e27Sflorian } 4487ae8c6e27Sflorian c->ev->base = base; 4488ae8c6e27Sflorian c->fd = -1; 4489ae8c6e27Sflorian c->buffer = sldns_buffer_new(bufsize); 4490ae8c6e27Sflorian if(!c->buffer) { 4491ae8c6e27Sflorian free(c->ev); 4492ae8c6e27Sflorian free(c); 4493ae8c6e27Sflorian return NULL; 4494ae8c6e27Sflorian } 4495ae8c6e27Sflorian c->timeout = NULL; 4496ae8c6e27Sflorian c->tcp_is_reading = 0; 4497ae8c6e27Sflorian c->tcp_byte_count = 0; 4498ae8c6e27Sflorian c->tcp_parent = NULL; 4499ae8c6e27Sflorian c->max_tcp_count = 0; 4500ae8c6e27Sflorian c->cur_tcp_count = 0; 4501ae8c6e27Sflorian c->tcp_handlers = NULL; 4502ae8c6e27Sflorian c->tcp_free = NULL; 4503ae8c6e27Sflorian c->type = comm_http; 4504ae8c6e27Sflorian c->tcp_do_close = 0; 4505ae8c6e27Sflorian c->do_not_close = 0; 4506ae8c6e27Sflorian c->tcp_do_toggle_rw = 1; 4507ae8c6e27Sflorian c->tcp_check_nb_connect = 1; 4508ae8c6e27Sflorian c->http_in_headers = 1; 4509ae8c6e27Sflorian c->http_in_chunk_headers = 0; 4510ae8c6e27Sflorian c->http_is_chunked = 0; 4511ae8c6e27Sflorian c->http_temp = temp; 4512ae8c6e27Sflorian #ifdef USE_MSG_FASTOPEN 4513ae8c6e27Sflorian c->tcp_do_fastopen = 1; 4514ae8c6e27Sflorian #endif 4515ae8c6e27Sflorian #ifdef USE_DNSCRYPT 4516ae8c6e27Sflorian c->dnscrypt = 0; 4517ae8c6e27Sflorian c->dnscrypt_buffer = c->buffer; 4518ae8c6e27Sflorian #endif 4519ae8c6e27Sflorian c->repinfo.c = c; 4520ae8c6e27Sflorian c->callback = callback; 4521ae8c6e27Sflorian c->cb_arg = callback_arg; 45225c45b740Sflorian c->pp2_enabled = 0; 45235c45b740Sflorian c->pp2_header_state = pp2_header_none; 4524ae8c6e27Sflorian evbits = UB_EV_PERSIST | UB_EV_WRITE; 4525ae8c6e27Sflorian c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits, 4526ae8c6e27Sflorian comm_point_http_handle_callback, c); 4527ae8c6e27Sflorian if(c->ev->ev == NULL) 4528ae8c6e27Sflorian { 4529ae8c6e27Sflorian log_err("could not baseset tcpout event"); 4530ae8c6e27Sflorian #ifdef HAVE_SSL 4531ae8c6e27Sflorian SSL_free(c->ssl); 4532ae8c6e27Sflorian #endif 4533ae8c6e27Sflorian sldns_buffer_free(c->buffer); 4534ae8c6e27Sflorian free(c->ev); 4535ae8c6e27Sflorian free(c); 4536ae8c6e27Sflorian return NULL; 4537ae8c6e27Sflorian } 4538ae8c6e27Sflorian 4539ae8c6e27Sflorian return c; 4540ae8c6e27Sflorian } 4541ae8c6e27Sflorian 4542ae8c6e27Sflorian struct comm_point* 4543ae8c6e27Sflorian comm_point_create_local(struct comm_base *base, int fd, size_t bufsize, 4544ae8c6e27Sflorian comm_point_callback_type* callback, void* callback_arg) 4545ae8c6e27Sflorian { 4546ae8c6e27Sflorian struct comm_point* c = (struct comm_point*)calloc(1, 4547ae8c6e27Sflorian sizeof(struct comm_point)); 4548ae8c6e27Sflorian short evbits; 4549ae8c6e27Sflorian if(!c) 4550ae8c6e27Sflorian return NULL; 4551ae8c6e27Sflorian c->ev = (struct internal_event*)calloc(1, 4552ae8c6e27Sflorian sizeof(struct internal_event)); 4553ae8c6e27Sflorian if(!c->ev) { 4554ae8c6e27Sflorian free(c); 4555ae8c6e27Sflorian return NULL; 4556ae8c6e27Sflorian } 4557ae8c6e27Sflorian c->ev->base = base; 4558ae8c6e27Sflorian c->fd = fd; 4559ae8c6e27Sflorian c->buffer = sldns_buffer_new(bufsize); 4560ae8c6e27Sflorian if(!c->buffer) { 4561ae8c6e27Sflorian free(c->ev); 4562ae8c6e27Sflorian free(c); 4563ae8c6e27Sflorian return NULL; 4564ae8c6e27Sflorian } 4565ae8c6e27Sflorian c->timeout = NULL; 4566ae8c6e27Sflorian c->tcp_is_reading = 1; 4567ae8c6e27Sflorian c->tcp_byte_count = 0; 4568ae8c6e27Sflorian c->tcp_parent = NULL; 4569ae8c6e27Sflorian c->max_tcp_count = 0; 4570ae8c6e27Sflorian c->cur_tcp_count = 0; 4571ae8c6e27Sflorian c->tcp_handlers = NULL; 4572ae8c6e27Sflorian c->tcp_free = NULL; 4573ae8c6e27Sflorian c->type = comm_local; 4574ae8c6e27Sflorian c->tcp_do_close = 0; 4575ae8c6e27Sflorian c->do_not_close = 1; 4576ae8c6e27Sflorian c->tcp_do_toggle_rw = 0; 4577ae8c6e27Sflorian c->tcp_check_nb_connect = 0; 4578ae8c6e27Sflorian #ifdef USE_MSG_FASTOPEN 4579ae8c6e27Sflorian c->tcp_do_fastopen = 0; 4580ae8c6e27Sflorian #endif 4581ae8c6e27Sflorian #ifdef USE_DNSCRYPT 4582ae8c6e27Sflorian c->dnscrypt = 0; 4583ae8c6e27Sflorian c->dnscrypt_buffer = c->buffer; 4584ae8c6e27Sflorian #endif 4585ae8c6e27Sflorian c->callback = callback; 4586ae8c6e27Sflorian c->cb_arg = callback_arg; 45875c45b740Sflorian c->pp2_enabled = 0; 45885c45b740Sflorian c->pp2_header_state = pp2_header_none; 4589ae8c6e27Sflorian /* ub_event stuff */ 4590ae8c6e27Sflorian evbits = UB_EV_PERSIST | UB_EV_READ; 4591ae8c6e27Sflorian c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits, 4592ae8c6e27Sflorian comm_point_local_handle_callback, c); 4593ae8c6e27Sflorian if(c->ev->ev == NULL) { 4594ae8c6e27Sflorian log_err("could not baseset localhdl event"); 4595ae8c6e27Sflorian free(c->ev); 4596ae8c6e27Sflorian free(c); 4597ae8c6e27Sflorian return NULL; 4598ae8c6e27Sflorian } 4599ae8c6e27Sflorian if (ub_event_add(c->ev->ev, c->timeout) != 0) { 4600ae8c6e27Sflorian log_err("could not add localhdl event"); 4601ae8c6e27Sflorian ub_event_free(c->ev->ev); 4602ae8c6e27Sflorian free(c->ev); 4603ae8c6e27Sflorian free(c); 4604ae8c6e27Sflorian return NULL; 4605ae8c6e27Sflorian } 4606a8eaceedSflorian c->event_added = 1; 4607ae8c6e27Sflorian return c; 4608ae8c6e27Sflorian } 4609ae8c6e27Sflorian 4610ae8c6e27Sflorian struct comm_point* 4611ae8c6e27Sflorian comm_point_create_raw(struct comm_base* base, int fd, int writing, 4612ae8c6e27Sflorian comm_point_callback_type* callback, void* callback_arg) 4613ae8c6e27Sflorian { 4614ae8c6e27Sflorian struct comm_point* c = (struct comm_point*)calloc(1, 4615ae8c6e27Sflorian sizeof(struct comm_point)); 4616ae8c6e27Sflorian short evbits; 4617ae8c6e27Sflorian if(!c) 4618ae8c6e27Sflorian return NULL; 4619ae8c6e27Sflorian c->ev = (struct internal_event*)calloc(1, 4620ae8c6e27Sflorian sizeof(struct internal_event)); 4621ae8c6e27Sflorian if(!c->ev) { 4622ae8c6e27Sflorian free(c); 4623ae8c6e27Sflorian return NULL; 4624ae8c6e27Sflorian } 4625ae8c6e27Sflorian c->ev->base = base; 4626ae8c6e27Sflorian c->fd = fd; 4627ae8c6e27Sflorian c->buffer = NULL; 4628ae8c6e27Sflorian c->timeout = NULL; 4629ae8c6e27Sflorian c->tcp_is_reading = 0; 4630ae8c6e27Sflorian c->tcp_byte_count = 0; 4631ae8c6e27Sflorian c->tcp_parent = NULL; 4632ae8c6e27Sflorian c->max_tcp_count = 0; 4633ae8c6e27Sflorian c->cur_tcp_count = 0; 4634ae8c6e27Sflorian c->tcp_handlers = NULL; 4635ae8c6e27Sflorian c->tcp_free = NULL; 4636ae8c6e27Sflorian c->type = comm_raw; 4637ae8c6e27Sflorian c->tcp_do_close = 0; 4638ae8c6e27Sflorian c->do_not_close = 1; 4639ae8c6e27Sflorian c->tcp_do_toggle_rw = 0; 4640ae8c6e27Sflorian c->tcp_check_nb_connect = 0; 4641ae8c6e27Sflorian #ifdef USE_MSG_FASTOPEN 4642ae8c6e27Sflorian c->tcp_do_fastopen = 0; 4643ae8c6e27Sflorian #endif 4644ae8c6e27Sflorian #ifdef USE_DNSCRYPT 4645ae8c6e27Sflorian c->dnscrypt = 0; 4646ae8c6e27Sflorian c->dnscrypt_buffer = c->buffer; 4647ae8c6e27Sflorian #endif 4648ae8c6e27Sflorian c->callback = callback; 4649ae8c6e27Sflorian c->cb_arg = callback_arg; 46505c45b740Sflorian c->pp2_enabled = 0; 46515c45b740Sflorian c->pp2_header_state = pp2_header_none; 4652ae8c6e27Sflorian /* ub_event stuff */ 4653ae8c6e27Sflorian if(writing) 4654ae8c6e27Sflorian evbits = UB_EV_PERSIST | UB_EV_WRITE; 4655ae8c6e27Sflorian else evbits = UB_EV_PERSIST | UB_EV_READ; 4656ae8c6e27Sflorian c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits, 4657ae8c6e27Sflorian comm_point_raw_handle_callback, c); 4658ae8c6e27Sflorian if(c->ev->ev == NULL) { 4659ae8c6e27Sflorian log_err("could not baseset rawhdl event"); 4660ae8c6e27Sflorian free(c->ev); 4661ae8c6e27Sflorian free(c); 4662ae8c6e27Sflorian return NULL; 4663ae8c6e27Sflorian } 4664ae8c6e27Sflorian if (ub_event_add(c->ev->ev, c->timeout) != 0) { 4665ae8c6e27Sflorian log_err("could not add rawhdl event"); 4666ae8c6e27Sflorian ub_event_free(c->ev->ev); 4667ae8c6e27Sflorian free(c->ev); 4668ae8c6e27Sflorian free(c); 4669ae8c6e27Sflorian return NULL; 4670ae8c6e27Sflorian } 4671a8eaceedSflorian c->event_added = 1; 4672ae8c6e27Sflorian return c; 4673ae8c6e27Sflorian } 4674ae8c6e27Sflorian 4675ae8c6e27Sflorian void 4676ae8c6e27Sflorian comm_point_close(struct comm_point* c) 4677ae8c6e27Sflorian { 4678ae8c6e27Sflorian if(!c) 4679ae8c6e27Sflorian return; 4680ae8c6e27Sflorian if(c->fd != -1) { 4681853e076fSflorian verbose(5, "comm_point_close of %d: event_del", c->fd); 4682a8eaceedSflorian if(c->event_added) { 4683ae8c6e27Sflorian if(ub_event_del(c->ev->ev) != 0) { 4684ae8c6e27Sflorian log_err("could not event_del on close"); 4685ae8c6e27Sflorian } 4686a8eaceedSflorian c->event_added = 0; 4687a8eaceedSflorian } 4688ae8c6e27Sflorian } 4689ae8c6e27Sflorian tcl_close_connection(c->tcl_addr); 4690e97c6e54Ssthen if(c->tcp_req_info) 4691e97c6e54Ssthen tcp_req_info_clear(c->tcp_req_info); 4692f4f0f0ceSflorian if(c->h2_session) 4693f4f0f0ceSflorian http2_session_server_delete(c->h2_session); 4694d500c338Sflorian /* stop the comm point from reading or writing after it is closed. */ 4695d500c338Sflorian if(c->tcp_more_read_again && *c->tcp_more_read_again) 4696d500c338Sflorian *c->tcp_more_read_again = 0; 4697d500c338Sflorian if(c->tcp_more_write_again && *c->tcp_more_write_again) 4698d500c338Sflorian *c->tcp_more_write_again = 0; 4699f4f0f0ceSflorian 4700ae8c6e27Sflorian /* close fd after removing from event lists, or epoll.. is messed up */ 4701ae8c6e27Sflorian if(c->fd != -1 && !c->do_not_close) { 4702411c5950Sflorian #ifdef USE_WINSOCK 4703ae8c6e27Sflorian if(c->type == comm_tcp || c->type == comm_http) { 4704ae8c6e27Sflorian /* delete sticky events for the fd, it gets closed */ 4705ae8c6e27Sflorian ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_READ); 4706ae8c6e27Sflorian ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE); 4707ae8c6e27Sflorian } 4708411c5950Sflorian #endif 4709ae8c6e27Sflorian verbose(VERB_ALGO, "close fd %d", c->fd); 4710f4f0f0ceSflorian sock_close(c->fd); 4711ae8c6e27Sflorian } 4712ae8c6e27Sflorian c->fd = -1; 4713ae8c6e27Sflorian } 4714ae8c6e27Sflorian 4715ae8c6e27Sflorian void 4716ae8c6e27Sflorian comm_point_delete(struct comm_point* c) 4717ae8c6e27Sflorian { 4718ae8c6e27Sflorian if(!c) 4719ae8c6e27Sflorian return; 4720ae8c6e27Sflorian if((c->type == comm_tcp || c->type == comm_http) && c->ssl) { 4721ae8c6e27Sflorian #ifdef HAVE_SSL 4722ae8c6e27Sflorian SSL_shutdown(c->ssl); 4723ae8c6e27Sflorian SSL_free(c->ssl); 4724ae8c6e27Sflorian #endif 4725ae8c6e27Sflorian } 4726f4f0f0ceSflorian if(c->type == comm_http && c->http_endpoint) { 4727f4f0f0ceSflorian free(c->http_endpoint); 4728f4f0f0ceSflorian c->http_endpoint = NULL; 4729f4f0f0ceSflorian } 4730ae8c6e27Sflorian comm_point_close(c); 4731ae8c6e27Sflorian if(c->tcp_handlers) { 4732ae8c6e27Sflorian int i; 4733ae8c6e27Sflorian for(i=0; i<c->max_tcp_count; i++) 4734ae8c6e27Sflorian comm_point_delete(c->tcp_handlers[i]); 4735ae8c6e27Sflorian free(c->tcp_handlers); 4736ae8c6e27Sflorian } 4737ae8c6e27Sflorian free(c->timeout); 4738ae8c6e27Sflorian if(c->type == comm_tcp || c->type == comm_local || c->type == comm_http) { 4739ae8c6e27Sflorian sldns_buffer_free(c->buffer); 4740ae8c6e27Sflorian #ifdef USE_DNSCRYPT 4741ae8c6e27Sflorian if(c->dnscrypt && c->dnscrypt_buffer != c->buffer) { 4742ae8c6e27Sflorian sldns_buffer_free(c->dnscrypt_buffer); 4743ae8c6e27Sflorian } 4744ae8c6e27Sflorian #endif 4745e97c6e54Ssthen if(c->tcp_req_info) { 4746e97c6e54Ssthen tcp_req_info_delete(c->tcp_req_info); 4747e97c6e54Ssthen } 4748f4f0f0ceSflorian if(c->h2_session) { 4749f4f0f0ceSflorian http2_session_delete(c->h2_session); 4750f4f0f0ceSflorian } 4751ae8c6e27Sflorian } 4752ae8c6e27Sflorian ub_event_free(c->ev->ev); 4753ae8c6e27Sflorian free(c->ev); 4754ae8c6e27Sflorian free(c); 4755ae8c6e27Sflorian } 4756ae8c6e27Sflorian 4757ae8c6e27Sflorian void 4758ae8c6e27Sflorian comm_point_send_reply(struct comm_reply *repinfo) 4759ae8c6e27Sflorian { 4760ae8c6e27Sflorian struct sldns_buffer* buffer; 4761ae8c6e27Sflorian log_assert(repinfo && repinfo->c); 4762ae8c6e27Sflorian #ifdef USE_DNSCRYPT 4763ae8c6e27Sflorian buffer = repinfo->c->dnscrypt_buffer; 4764ae8c6e27Sflorian if(!dnsc_handle_uncurved_request(repinfo)) { 4765ae8c6e27Sflorian return; 4766ae8c6e27Sflorian } 4767ae8c6e27Sflorian #else 4768ae8c6e27Sflorian buffer = repinfo->c->buffer; 4769ae8c6e27Sflorian #endif 4770ae8c6e27Sflorian if(repinfo->c->type == comm_udp) { 4771ae8c6e27Sflorian if(repinfo->srctype) 47725c45b740Sflorian comm_point_send_udp_msg_if(repinfo->c, buffer, 47735c45b740Sflorian (struct sockaddr*)&repinfo->remote_addr, 47745c45b740Sflorian repinfo->remote_addrlen, repinfo); 4775ae8c6e27Sflorian else 4776ae8c6e27Sflorian comm_point_send_udp_msg(repinfo->c, buffer, 47775c45b740Sflorian (struct sockaddr*)&repinfo->remote_addr, 47785c45b740Sflorian repinfo->remote_addrlen, 0); 4779ae8c6e27Sflorian #ifdef USE_DNSTAP 4780411c5950Sflorian /* 4781411c5950Sflorian * sending src (client)/dst (local service) addresses over DNSTAP from udp callback 4782411c5950Sflorian */ 4783411c5950Sflorian if(repinfo->c->dtenv != NULL && repinfo->c->dtenv->log_client_response_messages) { 4784096314feSflorian log_addr(VERB_ALGO, "from local addr", (void*)repinfo->c->socket->addr, repinfo->c->socket->addrlen); 47855c45b740Sflorian log_addr(VERB_ALGO, "response to client", &repinfo->client_addr, repinfo->client_addrlen); 4786096314feSflorian dt_msg_send_client_response(repinfo->c->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr, repinfo->c->type, repinfo->c->ssl, repinfo->c->buffer); 4787411c5950Sflorian } 4788ae8c6e27Sflorian #endif 4789ae8c6e27Sflorian } else { 4790ae8c6e27Sflorian #ifdef USE_DNSTAP 4791411c5950Sflorian /* 4792411c5950Sflorian * sending src (client)/dst (local service) addresses over DNSTAP from TCP callback 4793411c5950Sflorian */ 4794411c5950Sflorian if(repinfo->c->tcp_parent->dtenv != NULL && repinfo->c->tcp_parent->dtenv->log_client_response_messages) { 4795096314feSflorian log_addr(VERB_ALGO, "from local addr", (void*)repinfo->c->socket->addr, repinfo->c->socket->addrlen); 47965c45b740Sflorian log_addr(VERB_ALGO, "response to client", &repinfo->client_addr, repinfo->client_addrlen); 4797096314feSflorian dt_msg_send_client_response(repinfo->c->tcp_parent->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr, repinfo->c->type, repinfo->c->ssl, 4798411c5950Sflorian ( repinfo->c->tcp_req_info? repinfo->c->tcp_req_info->spool_buffer: repinfo->c->buffer )); 4799411c5950Sflorian } 4800ae8c6e27Sflorian #endif 4801e97c6e54Ssthen if(repinfo->c->tcp_req_info) { 4802e97c6e54Ssthen tcp_req_info_send_reply(repinfo->c->tcp_req_info); 4803f4f0f0ceSflorian } else if(repinfo->c->use_h2) { 4804f4f0f0ceSflorian if(!http2_submit_dns_response(repinfo->c->h2_session)) { 4805f4f0f0ceSflorian comm_point_drop_reply(repinfo); 4806f4f0f0ceSflorian return; 4807f4f0f0ceSflorian } 4808f4f0f0ceSflorian repinfo->c->h2_stream = NULL; 4809f4f0f0ceSflorian repinfo->c->tcp_is_reading = 0; 4810f4f0f0ceSflorian comm_point_stop_listening(repinfo->c); 4811f4f0f0ceSflorian comm_point_start_listening(repinfo->c, -1, 4812a8eaceedSflorian adjusted_tcp_timeout(repinfo->c)); 4813f4f0f0ceSflorian return; 4814e97c6e54Ssthen } else { 4815ae8c6e27Sflorian comm_point_start_listening(repinfo->c, -1, 4816a8eaceedSflorian adjusted_tcp_timeout(repinfo->c)); 4817ae8c6e27Sflorian } 4818ae8c6e27Sflorian } 4819e97c6e54Ssthen } 4820ae8c6e27Sflorian 4821ae8c6e27Sflorian void 4822ae8c6e27Sflorian comm_point_drop_reply(struct comm_reply* repinfo) 4823ae8c6e27Sflorian { 4824ae8c6e27Sflorian if(!repinfo) 4825ae8c6e27Sflorian return; 482657403691Sflorian log_assert(repinfo->c); 4827ae8c6e27Sflorian log_assert(repinfo->c->type != comm_tcp_accept); 4828ae8c6e27Sflorian if(repinfo->c->type == comm_udp) 4829ae8c6e27Sflorian return; 4830e97c6e54Ssthen if(repinfo->c->tcp_req_info) 4831e97c6e54Ssthen repinfo->c->tcp_req_info->is_drop = 1; 4832f4f0f0ceSflorian if(repinfo->c->type == comm_http) { 4833f4f0f0ceSflorian if(repinfo->c->h2_session) { 4834f4f0f0ceSflorian repinfo->c->h2_session->is_drop = 1; 4835f4f0f0ceSflorian if(!repinfo->c->h2_session->postpone_drop) 4836f4f0f0ceSflorian reclaim_http_handler(repinfo->c); 4837f4f0f0ceSflorian return; 4838f4f0f0ceSflorian } 4839f4f0f0ceSflorian reclaim_http_handler(repinfo->c); 4840f4f0f0ceSflorian return; 4841f4f0f0ceSflorian } 4842ae8c6e27Sflorian reclaim_tcp_handler(repinfo->c); 4843ae8c6e27Sflorian } 4844ae8c6e27Sflorian 4845ae8c6e27Sflorian void 4846ae8c6e27Sflorian comm_point_stop_listening(struct comm_point* c) 4847ae8c6e27Sflorian { 4848ae8c6e27Sflorian verbose(VERB_ALGO, "comm point stop listening %d", c->fd); 4849a8eaceedSflorian if(c->event_added) { 4850ae8c6e27Sflorian if(ub_event_del(c->ev->ev) != 0) { 4851ae8c6e27Sflorian log_err("event_del error to stoplisten"); 4852ae8c6e27Sflorian } 4853a8eaceedSflorian c->event_added = 0; 4854a8eaceedSflorian } 4855ae8c6e27Sflorian } 4856ae8c6e27Sflorian 4857ae8c6e27Sflorian void 4858ae8c6e27Sflorian comm_point_start_listening(struct comm_point* c, int newfd, int msec) 4859ae8c6e27Sflorian { 48609b465e50Sflorian verbose(VERB_ALGO, "comm point start listening %d (%d msec)", 48619b465e50Sflorian c->fd==-1?newfd:c->fd, msec); 4862ae8c6e27Sflorian if(c->type == comm_tcp_accept && !c->tcp_free) { 4863ae8c6e27Sflorian /* no use to start listening no free slots. */ 4864ae8c6e27Sflorian return; 4865ae8c6e27Sflorian } 4866a8eaceedSflorian if(c->event_added) { 4867a8eaceedSflorian if(ub_event_del(c->ev->ev) != 0) { 4868a8eaceedSflorian log_err("event_del error to startlisten"); 4869a8eaceedSflorian } 4870a8eaceedSflorian c->event_added = 0; 4871a8eaceedSflorian } 4872ae8c6e27Sflorian if(msec != -1 && msec != 0) { 4873ae8c6e27Sflorian if(!c->timeout) { 4874ae8c6e27Sflorian c->timeout = (struct timeval*)malloc(sizeof( 4875ae8c6e27Sflorian struct timeval)); 4876ae8c6e27Sflorian if(!c->timeout) { 4877ae8c6e27Sflorian log_err("cpsl: malloc failed. No net read."); 4878ae8c6e27Sflorian return; 4879ae8c6e27Sflorian } 4880ae8c6e27Sflorian } 4881ae8c6e27Sflorian ub_event_add_bits(c->ev->ev, UB_EV_TIMEOUT); 4882ae8c6e27Sflorian #ifndef S_SPLINT_S /* splint fails on struct timeval. */ 4883ae8c6e27Sflorian c->timeout->tv_sec = msec/1000; 4884ae8c6e27Sflorian c->timeout->tv_usec = (msec%1000)*1000; 4885ae8c6e27Sflorian #endif /* S_SPLINT_S */ 4886a1a7ba80Sflorian } else { 4887a1a7ba80Sflorian if(msec == 0 || !c->timeout) { 4888a1a7ba80Sflorian ub_event_del_bits(c->ev->ev, UB_EV_TIMEOUT); 4889a1a7ba80Sflorian } 4890ae8c6e27Sflorian } 4891ae8c6e27Sflorian if(c->type == comm_tcp || c->type == comm_http) { 4892ae8c6e27Sflorian ub_event_del_bits(c->ev->ev, UB_EV_READ|UB_EV_WRITE); 4893853e076fSflorian if(c->tcp_write_and_read) { 4894853e076fSflorian verbose(5, "startlistening %d mode rw", (newfd==-1?c->fd:newfd)); 4895853e076fSflorian ub_event_add_bits(c->ev->ev, UB_EV_READ|UB_EV_WRITE); 4896853e076fSflorian } else if(c->tcp_is_reading) { 4897853e076fSflorian verbose(5, "startlistening %d mode r", (newfd==-1?c->fd:newfd)); 4898ae8c6e27Sflorian ub_event_add_bits(c->ev->ev, UB_EV_READ); 4899853e076fSflorian } else { 4900853e076fSflorian verbose(5, "startlistening %d mode w", (newfd==-1?c->fd:newfd)); 4901853e076fSflorian ub_event_add_bits(c->ev->ev, UB_EV_WRITE); 4902853e076fSflorian } 4903ae8c6e27Sflorian } 4904ae8c6e27Sflorian if(newfd != -1) { 4905853e076fSflorian if(c->fd != -1 && c->fd != newfd) { 4906853e076fSflorian verbose(5, "cpsl close of fd %d for %d", c->fd, newfd); 4907f4f0f0ceSflorian sock_close(c->fd); 4908ae8c6e27Sflorian } 4909ae8c6e27Sflorian c->fd = newfd; 4910ae8c6e27Sflorian ub_event_set_fd(c->ev->ev, c->fd); 4911ae8c6e27Sflorian } 4912ae8c6e27Sflorian if(ub_event_add(c->ev->ev, msec==0?NULL:c->timeout) != 0) { 4913ae8c6e27Sflorian log_err("event_add failed. in cpsl."); 4914a1a7ba80Sflorian return; 4915ae8c6e27Sflorian } 4916a8eaceedSflorian c->event_added = 1; 4917ae8c6e27Sflorian } 4918ae8c6e27Sflorian 4919ae8c6e27Sflorian void comm_point_listen_for_rw(struct comm_point* c, int rd, int wr) 4920ae8c6e27Sflorian { 4921ae8c6e27Sflorian verbose(VERB_ALGO, "comm point listen_for_rw %d %d", c->fd, wr); 4922a8eaceedSflorian if(c->event_added) { 4923ae8c6e27Sflorian if(ub_event_del(c->ev->ev) != 0) { 4924ae8c6e27Sflorian log_err("event_del error to cplf"); 4925ae8c6e27Sflorian } 4926a8eaceedSflorian c->event_added = 0; 4927a8eaceedSflorian } 4928a1a7ba80Sflorian if(!c->timeout) { 4929a1a7ba80Sflorian ub_event_del_bits(c->ev->ev, UB_EV_TIMEOUT); 4930a1a7ba80Sflorian } 4931ae8c6e27Sflorian ub_event_del_bits(c->ev->ev, UB_EV_READ|UB_EV_WRITE); 4932ae8c6e27Sflorian if(rd) ub_event_add_bits(c->ev->ev, UB_EV_READ); 4933ae8c6e27Sflorian if(wr) ub_event_add_bits(c->ev->ev, UB_EV_WRITE); 4934ae8c6e27Sflorian if(ub_event_add(c->ev->ev, c->timeout) != 0) { 4935ae8c6e27Sflorian log_err("event_add failed. in cplf."); 4936a1a7ba80Sflorian return; 4937ae8c6e27Sflorian } 4938a8eaceedSflorian c->event_added = 1; 4939ae8c6e27Sflorian } 4940ae8c6e27Sflorian 4941ae8c6e27Sflorian size_t comm_point_get_mem(struct comm_point* c) 4942ae8c6e27Sflorian { 4943ae8c6e27Sflorian size_t s; 4944ae8c6e27Sflorian if(!c) 4945ae8c6e27Sflorian return 0; 4946ae8c6e27Sflorian s = sizeof(*c) + sizeof(*c->ev); 4947ae8c6e27Sflorian if(c->timeout) 4948ae8c6e27Sflorian s += sizeof(*c->timeout); 4949ae8c6e27Sflorian if(c->type == comm_tcp || c->type == comm_local) { 4950ae8c6e27Sflorian s += sizeof(*c->buffer) + sldns_buffer_capacity(c->buffer); 4951ae8c6e27Sflorian #ifdef USE_DNSCRYPT 4952ae8c6e27Sflorian s += sizeof(*c->dnscrypt_buffer); 4953ae8c6e27Sflorian if(c->buffer != c->dnscrypt_buffer) { 4954ae8c6e27Sflorian s += sldns_buffer_capacity(c->dnscrypt_buffer); 4955ae8c6e27Sflorian } 4956ae8c6e27Sflorian #endif 4957ae8c6e27Sflorian } 4958ae8c6e27Sflorian if(c->type == comm_tcp_accept) { 4959ae8c6e27Sflorian int i; 4960ae8c6e27Sflorian for(i=0; i<c->max_tcp_count; i++) 4961ae8c6e27Sflorian s += comm_point_get_mem(c->tcp_handlers[i]); 4962ae8c6e27Sflorian } 4963ae8c6e27Sflorian return s; 4964ae8c6e27Sflorian } 4965ae8c6e27Sflorian 4966ae8c6e27Sflorian struct comm_timer* 4967ae8c6e27Sflorian comm_timer_create(struct comm_base* base, void (*cb)(void*), void* cb_arg) 4968ae8c6e27Sflorian { 4969ae8c6e27Sflorian struct internal_timer *tm = (struct internal_timer*)calloc(1, 4970ae8c6e27Sflorian sizeof(struct internal_timer)); 4971ae8c6e27Sflorian if(!tm) { 4972ae8c6e27Sflorian log_err("malloc failed"); 4973ae8c6e27Sflorian return NULL; 4974ae8c6e27Sflorian } 4975ae8c6e27Sflorian tm->super.ev_timer = tm; 4976ae8c6e27Sflorian tm->base = base; 4977ae8c6e27Sflorian tm->super.callback = cb; 4978ae8c6e27Sflorian tm->super.cb_arg = cb_arg; 4979ae8c6e27Sflorian tm->ev = ub_event_new(base->eb->base, -1, UB_EV_TIMEOUT, 4980ae8c6e27Sflorian comm_timer_callback, &tm->super); 4981ae8c6e27Sflorian if(tm->ev == NULL) { 4982ae8c6e27Sflorian log_err("timer_create: event_base_set failed."); 4983ae8c6e27Sflorian free(tm); 4984ae8c6e27Sflorian return NULL; 4985ae8c6e27Sflorian } 4986ae8c6e27Sflorian return &tm->super; 4987ae8c6e27Sflorian } 4988ae8c6e27Sflorian 4989ae8c6e27Sflorian void 4990ae8c6e27Sflorian comm_timer_disable(struct comm_timer* timer) 4991ae8c6e27Sflorian { 4992ae8c6e27Sflorian if(!timer) 4993ae8c6e27Sflorian return; 4994ae8c6e27Sflorian ub_timer_del(timer->ev_timer->ev); 4995ae8c6e27Sflorian timer->ev_timer->enabled = 0; 4996ae8c6e27Sflorian } 4997ae8c6e27Sflorian 4998ae8c6e27Sflorian void 4999ae8c6e27Sflorian comm_timer_set(struct comm_timer* timer, struct timeval* tv) 5000ae8c6e27Sflorian { 5001ae8c6e27Sflorian log_assert(tv); 5002ae8c6e27Sflorian if(timer->ev_timer->enabled) 5003ae8c6e27Sflorian comm_timer_disable(timer); 5004ae8c6e27Sflorian if(ub_timer_add(timer->ev_timer->ev, timer->ev_timer->base->eb->base, 5005ae8c6e27Sflorian comm_timer_callback, timer, tv) != 0) 5006ae8c6e27Sflorian log_err("comm_timer_set: evtimer_add failed."); 5007ae8c6e27Sflorian timer->ev_timer->enabled = 1; 5008ae8c6e27Sflorian } 5009ae8c6e27Sflorian 5010ae8c6e27Sflorian void 5011ae8c6e27Sflorian comm_timer_delete(struct comm_timer* timer) 5012ae8c6e27Sflorian { 5013ae8c6e27Sflorian if(!timer) 5014ae8c6e27Sflorian return; 5015ae8c6e27Sflorian comm_timer_disable(timer); 5016ae8c6e27Sflorian /* Free the sub struct timer->ev_timer derived from the super struct timer. 5017ae8c6e27Sflorian * i.e. assert(timer == timer->ev_timer) 5018ae8c6e27Sflorian */ 5019ae8c6e27Sflorian ub_event_free(timer->ev_timer->ev); 5020ae8c6e27Sflorian free(timer->ev_timer); 5021ae8c6e27Sflorian } 5022ae8c6e27Sflorian 5023ae8c6e27Sflorian void 5024ae8c6e27Sflorian comm_timer_callback(int ATTR_UNUSED(fd), short event, void* arg) 5025ae8c6e27Sflorian { 5026ae8c6e27Sflorian struct comm_timer* tm = (struct comm_timer*)arg; 5027ae8c6e27Sflorian if(!(event&UB_EV_TIMEOUT)) 5028ae8c6e27Sflorian return; 5029ae8c6e27Sflorian ub_comm_base_now(tm->ev_timer->base); 5030ae8c6e27Sflorian tm->ev_timer->enabled = 0; 5031ae8c6e27Sflorian fptr_ok(fptr_whitelist_comm_timer(tm->callback)); 5032ae8c6e27Sflorian (*tm->callback)(tm->cb_arg); 5033ae8c6e27Sflorian } 5034ae8c6e27Sflorian 5035ae8c6e27Sflorian int 5036ae8c6e27Sflorian comm_timer_is_set(struct comm_timer* timer) 5037ae8c6e27Sflorian { 5038ae8c6e27Sflorian return (int)timer->ev_timer->enabled; 5039ae8c6e27Sflorian } 5040ae8c6e27Sflorian 5041ae8c6e27Sflorian size_t 5042ae8c6e27Sflorian comm_timer_get_mem(struct comm_timer* ATTR_UNUSED(timer)) 5043ae8c6e27Sflorian { 5044ae8c6e27Sflorian return sizeof(struct internal_timer); 5045ae8c6e27Sflorian } 5046ae8c6e27Sflorian 5047ae8c6e27Sflorian struct comm_signal* 5048ae8c6e27Sflorian comm_signal_create(struct comm_base* base, 5049ae8c6e27Sflorian void (*callback)(int, void*), void* cb_arg) 5050ae8c6e27Sflorian { 5051ae8c6e27Sflorian struct comm_signal* com = (struct comm_signal*)malloc( 5052ae8c6e27Sflorian sizeof(struct comm_signal)); 5053ae8c6e27Sflorian if(!com) { 5054ae8c6e27Sflorian log_err("malloc failed"); 5055ae8c6e27Sflorian return NULL; 5056ae8c6e27Sflorian } 5057ae8c6e27Sflorian com->base = base; 5058ae8c6e27Sflorian com->callback = callback; 5059ae8c6e27Sflorian com->cb_arg = cb_arg; 5060ae8c6e27Sflorian com->ev_signal = NULL; 5061ae8c6e27Sflorian return com; 5062ae8c6e27Sflorian } 5063ae8c6e27Sflorian 5064ae8c6e27Sflorian void 5065ae8c6e27Sflorian comm_signal_callback(int sig, short event, void* arg) 5066ae8c6e27Sflorian { 5067ae8c6e27Sflorian struct comm_signal* comsig = (struct comm_signal*)arg; 5068ae8c6e27Sflorian if(!(event & UB_EV_SIGNAL)) 5069ae8c6e27Sflorian return; 5070ae8c6e27Sflorian ub_comm_base_now(comsig->base); 5071ae8c6e27Sflorian fptr_ok(fptr_whitelist_comm_signal(comsig->callback)); 5072ae8c6e27Sflorian (*comsig->callback)(sig, comsig->cb_arg); 5073ae8c6e27Sflorian } 5074ae8c6e27Sflorian 5075ae8c6e27Sflorian int 5076ae8c6e27Sflorian comm_signal_bind(struct comm_signal* comsig, int sig) 5077ae8c6e27Sflorian { 5078ae8c6e27Sflorian struct internal_signal* entry = (struct internal_signal*)calloc(1, 5079ae8c6e27Sflorian sizeof(struct internal_signal)); 5080ae8c6e27Sflorian if(!entry) { 5081ae8c6e27Sflorian log_err("malloc failed"); 5082ae8c6e27Sflorian return 0; 5083ae8c6e27Sflorian } 5084ae8c6e27Sflorian log_assert(comsig); 5085ae8c6e27Sflorian /* add signal event */ 5086ae8c6e27Sflorian entry->ev = ub_signal_new(comsig->base->eb->base, sig, 5087ae8c6e27Sflorian comm_signal_callback, comsig); 5088ae8c6e27Sflorian if(entry->ev == NULL) { 5089ae8c6e27Sflorian log_err("Could not create signal event"); 5090ae8c6e27Sflorian free(entry); 5091ae8c6e27Sflorian return 0; 5092ae8c6e27Sflorian } 5093ae8c6e27Sflorian if(ub_signal_add(entry->ev, NULL) != 0) { 5094ae8c6e27Sflorian log_err("Could not add signal handler"); 5095ae8c6e27Sflorian ub_event_free(entry->ev); 5096ae8c6e27Sflorian free(entry); 5097ae8c6e27Sflorian return 0; 5098ae8c6e27Sflorian } 5099ae8c6e27Sflorian /* link into list */ 5100ae8c6e27Sflorian entry->next = comsig->ev_signal; 5101ae8c6e27Sflorian comsig->ev_signal = entry; 5102ae8c6e27Sflorian return 1; 5103ae8c6e27Sflorian } 5104ae8c6e27Sflorian 5105ae8c6e27Sflorian void 5106ae8c6e27Sflorian comm_signal_delete(struct comm_signal* comsig) 5107ae8c6e27Sflorian { 5108ae8c6e27Sflorian struct internal_signal* p, *np; 5109ae8c6e27Sflorian if(!comsig) 5110ae8c6e27Sflorian return; 5111ae8c6e27Sflorian p=comsig->ev_signal; 5112ae8c6e27Sflorian while(p) { 5113ae8c6e27Sflorian np = p->next; 5114ae8c6e27Sflorian ub_signal_del(p->ev); 5115ae8c6e27Sflorian ub_event_free(p->ev); 5116ae8c6e27Sflorian free(p); 5117ae8c6e27Sflorian p = np; 5118ae8c6e27Sflorian } 5119ae8c6e27Sflorian free(comsig); 5120ae8c6e27Sflorian } 5121