]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - util/netevent.c
Vendor import of Unbound 1.6.6.
[FreeBSD/FreeBSD.git] / util / netevent.c
1 /*
2  * util/netevent.c - event notification
3  *
4  * Copyright (c) 2007, NLnet Labs. All rights reserved.
5  *
6  * This software is open source.
7  * 
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 
12  * Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  * 
15  * Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  * 
19  * Neither the name of the NLNET LABS nor the names of its contributors may
20  * be used to endorse or promote products derived from this software without
21  * specific prior written permission.
22  * 
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35
36 /**
37  * \file
38  *
39  * This file contains event notification functions.
40  */
41 #include "config.h"
42 #include "util/netevent.h"
43 #include "util/ub_event.h"
44 #include "util/log.h"
45 #include "util/net_help.h"
46 #include "util/fptr_wlist.h"
47 #include "sldns/pkthdr.h"
48 #include "sldns/sbuffer.h"
49 #include "dnstap/dnstap.h"
50 #include "dnscrypt/dnscrypt.h"
51 #ifdef HAVE_OPENSSL_SSL_H
52 #include <openssl/ssl.h>
53 #endif
54 #ifdef HAVE_OPENSSL_ERR_H
55 #include <openssl/err.h>
56 #endif
57
58 /* -------- Start of local definitions -------- */
59 /** if CMSG_ALIGN is not defined on this platform, a workaround */
60 #ifndef CMSG_ALIGN
61 #  ifdef __CMSG_ALIGN
62 #    define CMSG_ALIGN(n) __CMSG_ALIGN(n)
63 #  elif defined(CMSG_DATA_ALIGN)
64 #    define CMSG_ALIGN _CMSG_DATA_ALIGN
65 #  else
66 #    define CMSG_ALIGN(len) (((len)+sizeof(long)-1) & ~(sizeof(long)-1))
67 #  endif
68 #endif
69
70 /** if CMSG_LEN is not defined on this platform, a workaround */
71 #ifndef CMSG_LEN
72 #  define CMSG_LEN(len) (CMSG_ALIGN(sizeof(struct cmsghdr))+(len))
73 #endif
74
75 /** if CMSG_SPACE is not defined on this platform, a workaround */
76 #ifndef CMSG_SPACE
77 #  ifdef _CMSG_HDR_ALIGN
78 #    define CMSG_SPACE(l) (CMSG_ALIGN(l)+_CMSG_HDR_ALIGN(sizeof(struct cmsghdr)))
79 #  else
80 #    define CMSG_SPACE(l) (CMSG_ALIGN(l)+CMSG_ALIGN(sizeof(struct cmsghdr)))
81 #  endif
82 #endif
83
84 /** The TCP reading or writing query timeout in milliseconds */
85 #define TCP_QUERY_TIMEOUT 120000
86 /** The TCP timeout in msec for fast queries, above half are used */
87 #define TCP_QUERY_TIMEOUT_FAST 200
88
89 #ifndef NONBLOCKING_IS_BROKEN
90 /** number of UDP reads to perform per read indication from select */
91 #define NUM_UDP_PER_SELECT 100
92 #else
93 #define NUM_UDP_PER_SELECT 1
94 #endif
95
96 /**
97  * The internal event structure for keeping ub_event info for the event.
98  * Possibly other structures (list, tree) this is part of.
99  */
100 struct internal_event {
101         /** the comm base */
102         struct comm_base* base;
103         /** ub_event event type */
104         struct ub_event* ev;
105 };
106
107 /**
108  * Internal base structure, so that every thread has its own events.
109  */
110 struct internal_base {
111         /** ub_event event_base type. */
112         struct ub_event_base* base;
113         /** seconds time pointer points here */
114         time_t secs;
115         /** timeval with current time */
116         struct timeval now;
117         /** the event used for slow_accept timeouts */
118         struct ub_event* slow_accept;
119         /** true if slow_accept is enabled */
120         int slow_accept_enabled;
121 };
122
123 /**
124  * Internal timer structure, to store timer event in.
125  */
126 struct internal_timer {
127         /** the super struct from which derived */
128         struct comm_timer super;
129         /** the comm base */
130         struct comm_base* base;
131         /** ub_event event type */
132         struct ub_event* ev;
133         /** is timer enabled */
134         uint8_t enabled;
135 };
136
137 /**
138  * Internal signal structure, to store signal event in.
139  */
140 struct internal_signal {
141         /** ub_event event type */
142         struct ub_event* ev;
143         /** next in signal list */
144         struct internal_signal* next;
145 };
146
147 /** create a tcp handler with a parent */
148 static struct comm_point* comm_point_create_tcp_handler(
149         struct comm_base *base, struct comm_point* parent, size_t bufsize,
150         comm_point_callback_type* callback, void* callback_arg);
151
152 /* -------- End of local definitions -------- */
153
154 struct comm_base* 
155 comm_base_create(int sigs)
156 {
157         struct comm_base* b = (struct comm_base*)calloc(1,
158                 sizeof(struct comm_base));
159         const char *evnm="event", *evsys="", *evmethod="";
160
161         if(!b)
162                 return NULL;
163         b->eb = (struct internal_base*)calloc(1, sizeof(struct internal_base));
164         if(!b->eb) {
165                 free(b);
166                 return NULL;
167         }
168         b->eb->base = ub_default_event_base(sigs, &b->eb->secs, &b->eb->now);
169         if(!b->eb->base) {
170                 free(b->eb);
171                 free(b);
172                 return NULL;
173         }
174         ub_comm_base_now(b);
175         ub_get_event_sys(b->eb->base, &evnm, &evsys, &evmethod);
176         verbose(VERB_ALGO, "%s %s user %s method.", evnm, evsys, evmethod);
177         return b;
178 }
179
180 struct comm_base*
181 comm_base_create_event(struct ub_event_base* base)
182 {
183         struct comm_base* b = (struct comm_base*)calloc(1,
184                 sizeof(struct comm_base));
185         if(!b)
186                 return NULL;
187         b->eb = (struct internal_base*)calloc(1, sizeof(struct internal_base));
188         if(!b->eb) {
189                 free(b);
190                 return NULL;
191         }
192         b->eb->base = base;
193         ub_comm_base_now(b);
194         return b;
195 }
196
197 void 
198 comm_base_delete(struct comm_base* b)
199 {
200         if(!b)
201                 return;
202         if(b->eb->slow_accept_enabled) {
203                 if(ub_event_del(b->eb->slow_accept) != 0) {
204                         log_err("could not event_del slow_accept");
205                 }
206                 ub_event_free(b->eb->slow_accept);
207         }
208         ub_event_base_free(b->eb->base);
209         b->eb->base = NULL;
210         free(b->eb);
211         free(b);
212 }
213
214 void 
215 comm_base_delete_no_base(struct comm_base* b)
216 {
217         if(!b)
218                 return;
219         if(b->eb->slow_accept_enabled) {
220                 if(ub_event_del(b->eb->slow_accept) != 0) {
221                         log_err("could not event_del slow_accept");
222                 }
223                 ub_event_free(b->eb->slow_accept);
224         }
225         b->eb->base = NULL;
226         free(b->eb);
227         free(b);
228 }
229
230 void 
231 comm_base_timept(struct comm_base* b, time_t** tt, struct timeval** tv)
232 {
233         *tt = &b->eb->secs;
234         *tv = &b->eb->now;
235 }
236
237 void 
238 comm_base_dispatch(struct comm_base* b)
239 {
240         int retval;
241         retval = ub_event_base_dispatch(b->eb->base);
242         if(retval < 0) {
243                 fatal_exit("event_dispatch returned error %d, "
244                         "errno is %s", retval, strerror(errno));
245         }
246 }
247
248 void comm_base_exit(struct comm_base* b)
249 {
250         if(ub_event_base_loopexit(b->eb->base) != 0) {
251                 log_err("Could not loopexit");
252         }
253 }
254
255 void comm_base_set_slow_accept_handlers(struct comm_base* b,
256         void (*stop_acc)(void*), void (*start_acc)(void*), void* arg)
257 {
258         b->stop_accept = stop_acc;
259         b->start_accept = start_acc;
260         b->cb_arg = arg;
261 }
262
263 struct ub_event_base* comm_base_internal(struct comm_base* b)
264 {
265         return b->eb->base;
266 }
267
268 /** see if errno for udp has to be logged or not uses globals */
269 static int
270 udp_send_errno_needs_log(struct sockaddr* addr, socklen_t addrlen)
271 {
272         /* do not log transient errors (unless high verbosity) */
273 #if defined(ENETUNREACH) || defined(EHOSTDOWN) || defined(EHOSTUNREACH) || defined(ENETDOWN)
274         switch(errno) {
275 #  ifdef ENETUNREACH
276                 case ENETUNREACH:
277 #  endif
278 #  ifdef EHOSTDOWN
279                 case EHOSTDOWN:
280 #  endif
281 #  ifdef EHOSTUNREACH
282                 case EHOSTUNREACH:
283 #  endif
284 #  ifdef ENETDOWN
285                 case ENETDOWN:
286 #  endif
287                         if(verbosity < VERB_ALGO)
288                                 return 0;
289                 default:
290                         break;
291         }
292 #endif
293         /* permission denied is gotten for every send if the
294          * network is disconnected (on some OS), squelch it */
295         if( ((errno == EPERM)
296 #  ifdef EADDRNOTAVAIL
297                 /* 'Cannot assign requested address' also when disconnected */
298                 || (errno == EADDRNOTAVAIL)
299 #  endif
300                 ) && verbosity < VERB_DETAIL)
301                 return 0;
302         /* squelch errors where people deploy AAAA ::ffff:bla for
303          * authority servers, which we try for intranets. */
304         if(errno == EINVAL && addr_is_ip4mapped(
305                 (struct sockaddr_storage*)addr, addrlen) &&
306                 verbosity < VERB_DETAIL)
307                 return 0;
308         /* SO_BROADCAST sockopt can give access to 255.255.255.255,
309          * but a dns cache does not need it. */
310         if(errno == EACCES && addr_is_broadcast(
311                 (struct sockaddr_storage*)addr, addrlen) &&
312                 verbosity < VERB_DETAIL)
313                 return 0;
314         return 1;
315 }
316
317 int tcp_connect_errno_needs_log(struct sockaddr* addr, socklen_t addrlen)
318 {
319         return udp_send_errno_needs_log(addr, addrlen);
320 }
321
322 /* send a UDP reply */
323 int
324 comm_point_send_udp_msg(struct comm_point *c, sldns_buffer* packet,
325         struct sockaddr* addr, socklen_t addrlen) 
326 {
327         ssize_t sent;
328         log_assert(c->fd != -1);
329 #ifdef UNBOUND_DEBUG
330         if(sldns_buffer_remaining(packet) == 0)
331                 log_err("error: send empty UDP packet");
332 #endif
333         log_assert(addr && addrlen > 0);
334         sent = sendto(c->fd, (void*)sldns_buffer_begin(packet), 
335                 sldns_buffer_remaining(packet), 0,
336                 addr, addrlen);
337         if(sent == -1) {
338                 /* try again and block, waiting for IO to complete,
339                  * we want to send the answer, and we will wait for
340                  * the ethernet interface buffer to have space. */
341 #ifndef USE_WINSOCK
342                 if(errno == EAGAIN || 
343 #  ifdef EWOULDBLOCK
344                         errno == EWOULDBLOCK ||
345 #  endif
346                         errno == ENOBUFS) {
347 #else
348                 if(WSAGetLastError() == WSAEINPROGRESS ||
349                         WSAGetLastError() == WSAENOBUFS ||
350                         WSAGetLastError() == WSAEWOULDBLOCK) {
351 #endif
352                         int e;
353                         fd_set_block(c->fd);
354                         sent = sendto(c->fd, (void*)sldns_buffer_begin(packet), 
355                                 sldns_buffer_remaining(packet), 0,
356                                 addr, addrlen);
357                         e = errno;
358                         fd_set_nonblock(c->fd);
359                         errno = e;
360                 }
361         }
362         if(sent == -1) {
363                 if(!udp_send_errno_needs_log(addr, addrlen))
364                         return 0;
365 #ifndef USE_WINSOCK
366                 verbose(VERB_OPS, "sendto failed: %s", strerror(errno));
367 #else
368                 verbose(VERB_OPS, "sendto failed: %s", 
369                         wsa_strerror(WSAGetLastError()));
370 #endif
371                 log_addr(VERB_OPS, "remote address is", 
372                         (struct sockaddr_storage*)addr, addrlen);
373                 return 0;
374         } else if((size_t)sent != sldns_buffer_remaining(packet)) {
375                 log_err("sent %d in place of %d bytes", 
376                         (int)sent, (int)sldns_buffer_remaining(packet));
377                 return 0;
378         }
379         return 1;
380 }
381
382 #if defined(AF_INET6) && defined(IPV6_PKTINFO) && (defined(HAVE_RECVMSG) || defined(HAVE_SENDMSG))
383 /** print debug ancillary info */
384 static void p_ancil(const char* str, struct comm_reply* r)
385 {
386         if(r->srctype != 4 && r->srctype != 6) {
387                 log_info("%s: unknown srctype %d", str, r->srctype);
388                 return;
389         }
390         if(r->srctype == 6) {
391                 char buf[1024];
392                 if(inet_ntop(AF_INET6, &r->pktinfo.v6info.ipi6_addr, 
393                         buf, (socklen_t)sizeof(buf)) == 0) {
394                         (void)strlcpy(buf, "(inet_ntop error)", sizeof(buf));
395                 }
396                 buf[sizeof(buf)-1]=0;
397                 log_info("%s: %s %d", str, buf, r->pktinfo.v6info.ipi6_ifindex);
398         } else if(r->srctype == 4) {
399 #ifdef IP_PKTINFO
400                 char buf1[1024], buf2[1024];
401                 if(inet_ntop(AF_INET, &r->pktinfo.v4info.ipi_addr, 
402                         buf1, (socklen_t)sizeof(buf1)) == 0) {
403                         (void)strlcpy(buf1, "(inet_ntop error)", sizeof(buf1));
404                 }
405                 buf1[sizeof(buf1)-1]=0;
406 #ifdef HAVE_STRUCT_IN_PKTINFO_IPI_SPEC_DST
407                 if(inet_ntop(AF_INET, &r->pktinfo.v4info.ipi_spec_dst, 
408                         buf2, (socklen_t)sizeof(buf2)) == 0) {
409                         (void)strlcpy(buf2, "(inet_ntop error)", sizeof(buf2));
410                 }
411                 buf2[sizeof(buf2)-1]=0;
412 #else
413                 buf2[0]=0;
414 #endif
415                 log_info("%s: %d %s %s", str, r->pktinfo.v4info.ipi_ifindex,
416                         buf1, buf2);
417 #elif defined(IP_RECVDSTADDR)
418                 char buf1[1024];
419                 if(inet_ntop(AF_INET, &r->pktinfo.v4addr, 
420                         buf1, (socklen_t)sizeof(buf1)) == 0) {
421                         (void)strlcpy(buf1, "(inet_ntop error)", sizeof(buf1));
422                 }
423                 buf1[sizeof(buf1)-1]=0;
424                 log_info("%s: %s", str, buf1);
425 #endif /* IP_PKTINFO or PI_RECVDSTDADDR */
426         }
427 }
428 #endif /* AF_INET6 && IPV6_PKTINFO && HAVE_RECVMSG||HAVE_SENDMSG */
429
430 /** send a UDP reply over specified interface*/
431 static int
432 comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet,
433         struct sockaddr* addr, socklen_t addrlen, struct comm_reply* r) 
434 {
435 #if defined(AF_INET6) && defined(IPV6_PKTINFO) && defined(HAVE_SENDMSG)
436         ssize_t sent;
437         struct msghdr msg;
438         struct iovec iov[1];
439         char control[256];
440 #ifndef S_SPLINT_S
441         struct cmsghdr *cmsg;
442 #endif /* S_SPLINT_S */
443
444         log_assert(c->fd != -1);
445 #ifdef UNBOUND_DEBUG
446         if(sldns_buffer_remaining(packet) == 0)
447                 log_err("error: send empty UDP packet");
448 #endif
449         log_assert(addr && addrlen > 0);
450
451         msg.msg_name = addr;
452         msg.msg_namelen = addrlen;
453         iov[0].iov_base = sldns_buffer_begin(packet);
454         iov[0].iov_len = sldns_buffer_remaining(packet);
455         msg.msg_iov = iov;
456         msg.msg_iovlen = 1;
457         msg.msg_control = control;
458 #ifndef S_SPLINT_S
459         msg.msg_controllen = sizeof(control);
460 #endif /* S_SPLINT_S */
461         msg.msg_flags = 0;
462
463 #ifndef S_SPLINT_S
464         cmsg = CMSG_FIRSTHDR(&msg);
465         if(r->srctype == 4) {
466 #ifdef IP_PKTINFO
467                 void* cmsg_data;
468                 msg.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));
469                 log_assert(msg.msg_controllen <= sizeof(control));
470                 cmsg->cmsg_level = IPPROTO_IP;
471                 cmsg->cmsg_type = IP_PKTINFO;
472                 memmove(CMSG_DATA(cmsg), &r->pktinfo.v4info,
473                         sizeof(struct in_pktinfo));
474                 /* unset the ifindex to not bypass the routing tables */
475                 cmsg_data = CMSG_DATA(cmsg);
476                 ((struct in_pktinfo *) cmsg_data)->ipi_ifindex = 0;
477                 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
478 #elif defined(IP_SENDSRCADDR)
479                 msg.msg_controllen = CMSG_SPACE(sizeof(struct in_addr));
480                 log_assert(msg.msg_controllen <= sizeof(control));
481                 cmsg->cmsg_level = IPPROTO_IP;
482                 cmsg->cmsg_type = IP_SENDSRCADDR;
483                 memmove(CMSG_DATA(cmsg), &r->pktinfo.v4addr,
484                         sizeof(struct in_addr));
485                 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
486 #else
487                 verbose(VERB_ALGO, "no IP_PKTINFO or IP_SENDSRCADDR");
488                 msg.msg_control = NULL;
489 #endif /* IP_PKTINFO or IP_SENDSRCADDR */
490         } else if(r->srctype == 6) {
491                 void* cmsg_data;
492                 msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
493                 log_assert(msg.msg_controllen <= sizeof(control));
494                 cmsg->cmsg_level = IPPROTO_IPV6;
495                 cmsg->cmsg_type = IPV6_PKTINFO;
496                 memmove(CMSG_DATA(cmsg), &r->pktinfo.v6info,
497                         sizeof(struct in6_pktinfo));
498                 /* unset the ifindex to not bypass the routing tables */
499                 cmsg_data = CMSG_DATA(cmsg);
500                 ((struct in6_pktinfo *) cmsg_data)->ipi6_ifindex = 0;
501                 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
502         } else {
503                 /* try to pass all 0 to use default route */
504                 msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
505                 log_assert(msg.msg_controllen <= sizeof(control));
506                 cmsg->cmsg_level = IPPROTO_IPV6;
507                 cmsg->cmsg_type = IPV6_PKTINFO;
508                 memset(CMSG_DATA(cmsg), 0, sizeof(struct in6_pktinfo));
509                 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
510         }
511 #endif /* S_SPLINT_S */
512         if(verbosity >= VERB_ALGO)
513                 p_ancil("send_udp over interface", r);
514         sent = sendmsg(c->fd, &msg, 0);
515         if(sent == -1) {
516                 /* try again and block, waiting for IO to complete,
517                  * we want to send the answer, and we will wait for
518                  * the ethernet interface buffer to have space. */
519 #ifndef USE_WINSOCK
520                 if(errno == EAGAIN || 
521 #  ifdef EWOULDBLOCK
522                         errno == EWOULDBLOCK ||
523 #  endif
524                         errno == ENOBUFS) {
525 #else
526                 if(WSAGetLastError() == WSAEINPROGRESS ||
527                         WSAGetLastError() == WSAENOBUFS ||
528                         WSAGetLastError() == WSAEWOULDBLOCK) {
529 #endif
530                         int e;
531                         fd_set_block(c->fd);
532                         sent = sendmsg(c->fd, &msg, 0);
533                         e = errno;
534                         fd_set_nonblock(c->fd);
535                         errno = e;
536                 }
537         }
538         if(sent == -1) {
539                 if(!udp_send_errno_needs_log(addr, addrlen))
540                         return 0;
541                 verbose(VERB_OPS, "sendmsg failed: %s", strerror(errno));
542                 log_addr(VERB_OPS, "remote address is", 
543                         (struct sockaddr_storage*)addr, addrlen);
544 #ifdef __NetBSD__
545                 /* netbsd 7 has IP_PKTINFO for recv but not send */
546                 if(errno == EINVAL && r->srctype == 4)
547                         log_err("sendmsg: No support for sendmsg(IP_PKTINFO). "
548                                 "Please disable interface-automatic");
549 #endif
550                 return 0;
551         } else if((size_t)sent != sldns_buffer_remaining(packet)) {
552                 log_err("sent %d in place of %d bytes", 
553                         (int)sent, (int)sldns_buffer_remaining(packet));
554                 return 0;
555         }
556         return 1;
557 #else
558         (void)c;
559         (void)packet;
560         (void)addr;
561         (void)addrlen;
562         (void)r;
563         log_err("sendmsg: IPV6_PKTINFO not supported");
564         return 0;
565 #endif /* AF_INET6 && IPV6_PKTINFO && HAVE_SENDMSG */
566 }
567
568 void 
569 comm_point_udp_ancil_callback(int fd, short event, void* arg)
570 {
571 #if defined(AF_INET6) && defined(IPV6_PKTINFO) && defined(HAVE_RECVMSG)
572         struct comm_reply rep;
573         struct msghdr msg;
574         struct iovec iov[1];
575         ssize_t rcv;
576         char ancil[256];
577         int i;
578 #ifndef S_SPLINT_S
579         struct cmsghdr* cmsg;
580 #endif /* S_SPLINT_S */
581
582         rep.c = (struct comm_point*)arg;
583         log_assert(rep.c->type == comm_udp);
584
585         if(!(event&UB_EV_READ))
586                 return;
587         log_assert(rep.c && rep.c->buffer && rep.c->fd == fd);
588         ub_comm_base_now(rep.c->ev->base);
589         for(i=0; i<NUM_UDP_PER_SELECT; i++) {
590                 sldns_buffer_clear(rep.c->buffer);
591                 rep.addrlen = (socklen_t)sizeof(rep.addr);
592                 log_assert(fd != -1);
593                 log_assert(sldns_buffer_remaining(rep.c->buffer) > 0);
594                 msg.msg_name = &rep.addr;
595                 msg.msg_namelen = (socklen_t)sizeof(rep.addr);
596                 iov[0].iov_base = sldns_buffer_begin(rep.c->buffer);
597                 iov[0].iov_len = sldns_buffer_remaining(rep.c->buffer);
598                 msg.msg_iov = iov;
599                 msg.msg_iovlen = 1;
600                 msg.msg_control = ancil;
601 #ifndef S_SPLINT_S
602                 msg.msg_controllen = sizeof(ancil);
603 #endif /* S_SPLINT_S */
604                 msg.msg_flags = 0;
605                 rcv = recvmsg(fd, &msg, 0);
606                 if(rcv == -1) {
607                         if(errno != EAGAIN && errno != EINTR) {
608                                 log_err("recvmsg failed: %s", strerror(errno));
609                         }
610                         return;
611                 }
612                 rep.addrlen = msg.msg_namelen;
613                 sldns_buffer_skip(rep.c->buffer, rcv);
614                 sldns_buffer_flip(rep.c->buffer);
615                 rep.srctype = 0;
616 #ifndef S_SPLINT_S
617                 for(cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
618                         cmsg = CMSG_NXTHDR(&msg, cmsg)) {
619                         if( cmsg->cmsg_level == IPPROTO_IPV6 &&
620                                 cmsg->cmsg_type == IPV6_PKTINFO) {
621                                 rep.srctype = 6;
622                                 memmove(&rep.pktinfo.v6info, CMSG_DATA(cmsg),
623                                         sizeof(struct in6_pktinfo));
624                                 break;
625 #ifdef IP_PKTINFO
626                         } else if( cmsg->cmsg_level == IPPROTO_IP &&
627                                 cmsg->cmsg_type == IP_PKTINFO) {
628                                 rep.srctype = 4;
629                                 memmove(&rep.pktinfo.v4info, CMSG_DATA(cmsg),
630                                         sizeof(struct in_pktinfo));
631                                 break;
632 #elif defined(IP_RECVDSTADDR)
633                         } else if( cmsg->cmsg_level == IPPROTO_IP &&
634                                 cmsg->cmsg_type == IP_RECVDSTADDR) {
635                                 rep.srctype = 4;
636                                 memmove(&rep.pktinfo.v4addr, CMSG_DATA(cmsg),
637                                         sizeof(struct in_addr));
638                                 break;
639 #endif /* IP_PKTINFO or IP_RECVDSTADDR */
640                         }
641                 }
642                 if(verbosity >= VERB_ALGO)
643                         p_ancil("receive_udp on interface", &rep);
644 #endif /* S_SPLINT_S */
645                 fptr_ok(fptr_whitelist_comm_point(rep.c->callback));
646                 if((*rep.c->callback)(rep.c, rep.c->cb_arg, NETEVENT_NOERROR, &rep)) {
647                         /* send back immediate reply */
648                         (void)comm_point_send_udp_msg_if(rep.c, rep.c->buffer,
649                                 (struct sockaddr*)&rep.addr, rep.addrlen, &rep);
650                 }
651                 if(rep.c->fd == -1) /* commpoint closed */
652                         break;
653         }
654 #else
655         (void)fd;
656         (void)event;
657         (void)arg;
658         fatal_exit("recvmsg: No support for IPV6_PKTINFO; IP_PKTINFO or IP_RECVDSTADDR. "
659                 "Please disable interface-automatic");
660 #endif /* AF_INET6 && IPV6_PKTINFO && HAVE_RECVMSG */
661 }
662
663 void 
664 comm_point_udp_callback(int fd, short event, void* arg)
665 {
666         struct comm_reply rep;
667         ssize_t rcv;
668         int i;
669         struct sldns_buffer *buffer;
670
671         rep.c = (struct comm_point*)arg;
672         log_assert(rep.c->type == comm_udp);
673
674         if(!(event&UB_EV_READ))
675                 return;
676         log_assert(rep.c && rep.c->buffer && rep.c->fd == fd);
677         ub_comm_base_now(rep.c->ev->base);
678         for(i=0; i<NUM_UDP_PER_SELECT; i++) {
679                 sldns_buffer_clear(rep.c->buffer);
680                 rep.addrlen = (socklen_t)sizeof(rep.addr);
681                 log_assert(fd != -1);
682                 log_assert(sldns_buffer_remaining(rep.c->buffer) > 0);
683                 rcv = recvfrom(fd, (void*)sldns_buffer_begin(rep.c->buffer), 
684                         sldns_buffer_remaining(rep.c->buffer), 0, 
685                         (struct sockaddr*)&rep.addr, &rep.addrlen);
686                 if(rcv == -1) {
687 #ifndef USE_WINSOCK
688                         if(errno != EAGAIN && errno != EINTR)
689                                 log_err("recvfrom %d failed: %s", 
690                                         fd, strerror(errno));
691 #else
692                         if(WSAGetLastError() != WSAEINPROGRESS &&
693                                 WSAGetLastError() != WSAECONNRESET &&
694                                 WSAGetLastError()!= WSAEWOULDBLOCK)
695                                 log_err("recvfrom failed: %s",
696                                         wsa_strerror(WSAGetLastError()));
697 #endif
698                         return;
699                 }
700                 sldns_buffer_skip(rep.c->buffer, rcv);
701                 sldns_buffer_flip(rep.c->buffer);
702                 rep.srctype = 0;
703                 fptr_ok(fptr_whitelist_comm_point(rep.c->callback));
704                 if((*rep.c->callback)(rep.c, rep.c->cb_arg, NETEVENT_NOERROR, &rep)) {
705                         /* send back immediate reply */
706 #ifdef USE_DNSCRYPT
707                         buffer = rep.c->dnscrypt_buffer;
708 #else
709                         buffer = rep.c->buffer;
710 #endif
711                         (void)comm_point_send_udp_msg(rep.c, buffer,
712                                 (struct sockaddr*)&rep.addr, rep.addrlen);
713                 }
714                 if(rep.c->fd != fd) /* commpoint closed to -1 or reused for
715                 another UDP port. Note rep.c cannot be reused with TCP fd. */
716                         break;
717         }
718 }
719
720 /** Use a new tcp handler for new query fd, set to read query */
721 static void
722 setup_tcp_handler(struct comm_point* c, int fd, int cur, int max) 
723 {
724         log_assert(c->type == comm_tcp);
725         log_assert(c->fd == -1);
726         sldns_buffer_clear(c->buffer);
727 #ifdef USE_DNSCRYPT
728         if (c->dnscrypt)
729                 sldns_buffer_clear(c->dnscrypt_buffer);
730 #endif
731         c->tcp_is_reading = 1;
732         c->tcp_byte_count = 0;
733         c->tcp_timeout_msec = TCP_QUERY_TIMEOUT;
734         /* if more than half the tcp handlers are in use, use a shorter
735          * timeout for this TCP connection, we need to make space for
736          * other connections to be able to get attention */
737         if(cur > max/2)
738                 c->tcp_timeout_msec = TCP_QUERY_TIMEOUT_FAST;
739         comm_point_start_listening(c, fd, c->tcp_timeout_msec);
740 }
741
742 void comm_base_handle_slow_accept(int ATTR_UNUSED(fd),
743         short ATTR_UNUSED(event), void* arg)
744 {
745         struct comm_base* b = (struct comm_base*)arg;
746         /* timeout for the slow accept, re-enable accepts again */
747         if(b->start_accept) {
748                 verbose(VERB_ALGO, "wait is over, slow accept disabled");
749                 fptr_ok(fptr_whitelist_start_accept(b->start_accept));
750                 (*b->start_accept)(b->cb_arg);
751                 b->eb->slow_accept_enabled = 0;
752         }
753 }
754
755 int comm_point_perform_accept(struct comm_point* c,
756         struct sockaddr_storage* addr, socklen_t* addrlen)
757 {
758         int new_fd;
759         *addrlen = (socklen_t)sizeof(*addr);
760         new_fd = accept(c->fd, (struct sockaddr*)addr, addrlen);
761         if(new_fd == -1) {
762 #ifndef USE_WINSOCK
763                 /* EINTR is signal interrupt. others are closed connection. */
764                 if(     errno == EINTR || errno == EAGAIN
765 #ifdef EWOULDBLOCK
766                         || errno == EWOULDBLOCK 
767 #endif
768 #ifdef ECONNABORTED
769                         || errno == ECONNABORTED 
770 #endif
771 #ifdef EPROTO
772                         || errno == EPROTO
773 #endif /* EPROTO */
774                         )
775                         return -1;
776 #if defined(ENFILE) && defined(EMFILE)
777                 if(errno == ENFILE || errno == EMFILE) {
778                         /* out of file descriptors, likely outside of our
779                          * control. stop accept() calls for some time */
780                         if(c->ev->base->stop_accept) {
781                                 struct comm_base* b = c->ev->base;
782                                 struct timeval tv;
783                                 verbose(VERB_ALGO, "out of file descriptors: "
784                                         "slow accept");
785                                 b->eb->slow_accept_enabled = 1;
786                                 fptr_ok(fptr_whitelist_stop_accept(
787                                         b->stop_accept));
788                                 (*b->stop_accept)(b->cb_arg);
789                                 /* set timeout, no mallocs */
790                                 tv.tv_sec = NETEVENT_SLOW_ACCEPT_TIME/1000;
791                                 tv.tv_usec = (NETEVENT_SLOW_ACCEPT_TIME%1000)*1000;
792                                 b->eb->slow_accept = ub_event_new(b->eb->base,
793                                         -1, UB_EV_TIMEOUT,
794                                         comm_base_handle_slow_accept, b);
795                                 if(b->eb->slow_accept == NULL) {
796                                         /* we do not want to log here, because
797                                          * that would spam the logfiles.
798                                          * error: "event_base_set failed." */
799                                 }
800                                 else if(ub_event_add(b->eb->slow_accept, &tv)
801                                         != 0) {
802                                         /* we do not want to log here,
803                                          * error: "event_add failed." */
804                                 }
805                         }
806                         return -1;
807                 }
808 #endif
809                 log_err_addr("accept failed", strerror(errno), addr, *addrlen);
810 #else /* USE_WINSOCK */
811                 if(WSAGetLastError() == WSAEINPROGRESS ||
812                         WSAGetLastError() == WSAECONNRESET)
813                         return -1;
814                 if(WSAGetLastError() == WSAEWOULDBLOCK) {
815                         ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_READ);
816                         return -1;
817                 }
818                 log_err_addr("accept failed", wsa_strerror(WSAGetLastError()),
819                         addr, *addrlen);
820 #endif
821                 return -1;
822         }
823         fd_set_nonblock(new_fd);
824         return new_fd;
825 }
826
827 #ifdef USE_WINSOCK
828 static long win_bio_cb(BIO *b, int oper, const char* ATTR_UNUSED(argp),
829         int ATTR_UNUSED(argi), long argl, long retvalue)
830 {
831         verbose(VERB_ALGO, "bio_cb %d, %s %s %s", oper,
832                 (oper&BIO_CB_RETURN)?"return":"before",
833                 (oper&BIO_CB_READ)?"read":((oper&BIO_CB_WRITE)?"write":"other"),
834                 WSAGetLastError()==WSAEWOULDBLOCK?"wsawb":"");
835         /* on windows, check if previous operation caused EWOULDBLOCK */
836         if( (oper == (BIO_CB_READ|BIO_CB_RETURN) && argl == 0) ||
837                 (oper == (BIO_CB_GETS|BIO_CB_RETURN) && argl == 0)) {
838                 if(WSAGetLastError() == WSAEWOULDBLOCK)
839                         ub_winsock_tcp_wouldblock((struct ub_event*)
840                                 BIO_get_callback_arg(b), UB_EV_READ);
841         }
842         if( (oper == (BIO_CB_WRITE|BIO_CB_RETURN) && argl == 0) ||
843                 (oper == (BIO_CB_PUTS|BIO_CB_RETURN) && argl == 0)) {
844                 if(WSAGetLastError() == WSAEWOULDBLOCK)
845                         ub_winsock_tcp_wouldblock((struct ub_event*)
846                                 BIO_get_callback_arg(b), UB_EV_WRITE);
847         }
848         /* return original return value */
849         return retvalue;
850 }
851
852 /** set win bio callbacks for nonblocking operations */
853 void
854 comm_point_tcp_win_bio_cb(struct comm_point* c, void* thessl)
855 {
856         SSL* ssl = (SSL*)thessl;
857         /* set them both just in case, but usually they are the same BIO */
858         BIO_set_callback(SSL_get_rbio(ssl), &win_bio_cb);
859         BIO_set_callback_arg(SSL_get_rbio(ssl), (char*)c->ev->ev);
860         BIO_set_callback(SSL_get_wbio(ssl), &win_bio_cb);
861         BIO_set_callback_arg(SSL_get_wbio(ssl), (char*)c->ev->ev);
862 }
863 #endif
864
865 void 
866 comm_point_tcp_accept_callback(int fd, short event, void* arg)
867 {
868         struct comm_point* c = (struct comm_point*)arg, *c_hdl;
869         int new_fd;
870         log_assert(c->type == comm_tcp_accept);
871         if(!(event & UB_EV_READ)) {
872                 log_info("ignoring tcp accept event %d", (int)event);
873                 return;
874         }
875         ub_comm_base_now(c->ev->base);
876         /* find free tcp handler. */
877         if(!c->tcp_free) {
878                 log_warn("accepted too many tcp, connections full");
879                 return;
880         }
881         /* accept incoming connection. */
882         c_hdl = c->tcp_free;
883         log_assert(fd != -1);
884         (void)fd;
885         new_fd = comm_point_perform_accept(c, &c_hdl->repinfo.addr,
886                 &c_hdl->repinfo.addrlen);
887         if(new_fd == -1)
888                 return;
889         if(c->ssl) {
890                 c_hdl->ssl = incoming_ssl_fd(c->ssl, new_fd);
891                 if(!c_hdl->ssl) {
892                         c_hdl->fd = new_fd;
893                         comm_point_close(c_hdl);
894                         return;
895                 }
896                 c_hdl->ssl_shake_state = comm_ssl_shake_read;
897 #ifdef USE_WINSOCK
898                 comm_point_tcp_win_bio_cb(c_hdl, c_hdl->ssl);
899 #endif
900         }
901
902         /* grab the tcp handler buffers */
903         c->cur_tcp_count++;
904         c->tcp_free = c_hdl->tcp_free;
905         if(!c->tcp_free) {
906                 /* stop accepting incoming queries for now. */
907                 comm_point_stop_listening(c);
908         }
909         setup_tcp_handler(c_hdl, new_fd, c->cur_tcp_count, c->max_tcp_count);
910 }
911
912 /** Make tcp handler free for next assignment */
913 static void
914 reclaim_tcp_handler(struct comm_point* c)
915 {
916         log_assert(c->type == comm_tcp);
917         if(c->ssl) {
918 #ifdef HAVE_SSL
919                 SSL_shutdown(c->ssl);
920                 SSL_free(c->ssl);
921                 c->ssl = NULL;
922 #endif
923         }
924         comm_point_close(c);
925         if(c->tcp_parent) {
926                 c->tcp_parent->cur_tcp_count--;
927                 c->tcp_free = c->tcp_parent->tcp_free;
928                 c->tcp_parent->tcp_free = c;
929                 if(!c->tcp_free) {
930                         /* re-enable listening on accept socket */
931                         comm_point_start_listening(c->tcp_parent, -1, -1);
932                 }
933         }
934 }
935
936 /** do the callback when writing is done */
937 static void
938 tcp_callback_writer(struct comm_point* c)
939 {
940         log_assert(c->type == comm_tcp);
941         sldns_buffer_clear(c->buffer);
942         if(c->tcp_do_toggle_rw)
943                 c->tcp_is_reading = 1;
944         c->tcp_byte_count = 0;
945         /* switch from listening(write) to listening(read) */
946         comm_point_stop_listening(c);
947         comm_point_start_listening(c, -1, -1);
948 }
949
950 /** do the callback when reading is done */
951 static void
952 tcp_callback_reader(struct comm_point* c)
953 {
954         log_assert(c->type == comm_tcp || c->type == comm_local);
955         sldns_buffer_flip(c->buffer);
956         if(c->tcp_do_toggle_rw)
957                 c->tcp_is_reading = 0;
958         c->tcp_byte_count = 0;
959         if(c->type == comm_tcp)
960                 comm_point_stop_listening(c);
961         fptr_ok(fptr_whitelist_comm_point(c->callback));
962         if( (*c->callback)(c, c->cb_arg, NETEVENT_NOERROR, &c->repinfo) ) {
963                 comm_point_start_listening(c, -1, c->tcp_timeout_msec);
964         }
965 }
966
967 /** continue ssl handshake */
968 #ifdef HAVE_SSL
969 static int
970 ssl_handshake(struct comm_point* c)
971 {
972         int r;
973         if(c->ssl_shake_state == comm_ssl_shake_hs_read) {
974                 /* read condition satisfied back to writing */
975                 comm_point_listen_for_rw(c, 1, 1);
976                 c->ssl_shake_state = comm_ssl_shake_none;
977                 return 1;
978         }
979         if(c->ssl_shake_state == comm_ssl_shake_hs_write) {
980                 /* write condition satisfied, back to reading */
981                 comm_point_listen_for_rw(c, 1, 0);
982                 c->ssl_shake_state = comm_ssl_shake_none;
983                 return 1;
984         }
985
986         ERR_clear_error();
987         r = SSL_do_handshake(c->ssl);
988         if(r != 1) {
989                 int want = SSL_get_error(c->ssl, r);
990                 if(want == SSL_ERROR_WANT_READ) {
991                         if(c->ssl_shake_state == comm_ssl_shake_read)
992                                 return 1;
993                         c->ssl_shake_state = comm_ssl_shake_read;
994                         comm_point_listen_for_rw(c, 1, 0);
995                         return 1;
996                 } else if(want == SSL_ERROR_WANT_WRITE) {
997                         if(c->ssl_shake_state == comm_ssl_shake_write)
998                                 return 1;
999                         c->ssl_shake_state = comm_ssl_shake_write;
1000                         comm_point_listen_for_rw(c, 0, 1);
1001                         return 1;
1002                 } else if(r == 0) {
1003                         return 0; /* closed */
1004                 } else if(want == SSL_ERROR_SYSCALL) {
1005                         /* SYSCALL and errno==0 means closed uncleanly */
1006                         if(errno != 0)
1007                                 log_err("SSL_handshake syscall: %s",
1008                                         strerror(errno));
1009                         return 0;
1010                 } else {
1011                         log_crypto_err("ssl handshake failed");
1012                         log_addr(1, "ssl handshake failed", &c->repinfo.addr,
1013                                 c->repinfo.addrlen);
1014                         return 0;
1015                 }
1016         }
1017         /* this is where peer verification could take place */
1018         log_addr(VERB_ALGO, "SSL DNS connection", &c->repinfo.addr,
1019                 c->repinfo.addrlen);
1020
1021         /* setup listen rw correctly */
1022         if(c->tcp_is_reading) {
1023                 if(c->ssl_shake_state != comm_ssl_shake_read)
1024                         comm_point_listen_for_rw(c, 1, 0);
1025         } else {
1026                 comm_point_listen_for_rw(c, 1, 1);
1027         }
1028         c->ssl_shake_state = comm_ssl_shake_none;
1029         return 1;
1030 }
1031 #endif /* HAVE_SSL */
1032
1033 /** ssl read callback on TCP */
1034 static int
1035 ssl_handle_read(struct comm_point* c)
1036 {
1037 #ifdef HAVE_SSL
1038         int r;
1039         if(c->ssl_shake_state != comm_ssl_shake_none) {
1040                 if(!ssl_handshake(c))
1041                         return 0;
1042                 if(c->ssl_shake_state != comm_ssl_shake_none)
1043                         return 1;
1044         }
1045         if(c->tcp_byte_count < sizeof(uint16_t)) {
1046                 /* read length bytes */
1047                 ERR_clear_error();
1048                 if((r=SSL_read(c->ssl, (void*)sldns_buffer_at(c->buffer,
1049                         c->tcp_byte_count), (int)(sizeof(uint16_t) -
1050                         c->tcp_byte_count))) <= 0) {
1051                         int want = SSL_get_error(c->ssl, r);
1052                         if(want == SSL_ERROR_ZERO_RETURN) {
1053                                 return 0; /* shutdown, closed */
1054                         } else if(want == SSL_ERROR_WANT_READ) {
1055                                 return 1; /* read more later */
1056                         } else if(want == SSL_ERROR_WANT_WRITE) {
1057                                 c->ssl_shake_state = comm_ssl_shake_hs_write;
1058                                 comm_point_listen_for_rw(c, 0, 1);
1059                                 return 1;
1060                         } else if(want == SSL_ERROR_SYSCALL) {
1061                                 if(errno != 0)
1062                                         log_err("SSL_read syscall: %s",
1063                                                 strerror(errno));
1064                                 return 0;
1065                         }
1066                         log_crypto_err("could not SSL_read");
1067                         return 0;
1068                 }
1069                 c->tcp_byte_count += r;
1070                 if(c->tcp_byte_count != sizeof(uint16_t))
1071                         return 1;
1072                 if(sldns_buffer_read_u16_at(c->buffer, 0) >
1073                         sldns_buffer_capacity(c->buffer)) {
1074                         verbose(VERB_QUERY, "ssl: dropped larger than buffer");
1075                         return 0;
1076                 }
1077                 sldns_buffer_set_limit(c->buffer,
1078                         sldns_buffer_read_u16_at(c->buffer, 0));
1079                 if(sldns_buffer_limit(c->buffer) < LDNS_HEADER_SIZE) {
1080                         verbose(VERB_QUERY, "ssl: dropped bogus too short.");
1081                         return 0;
1082                 }
1083                 verbose(VERB_ALGO, "Reading ssl tcp query of length %d",
1084                         (int)sldns_buffer_limit(c->buffer));
1085         }
1086         log_assert(sldns_buffer_remaining(c->buffer) > 0);
1087         ERR_clear_error();
1088         r = SSL_read(c->ssl, (void*)sldns_buffer_current(c->buffer),
1089                 (int)sldns_buffer_remaining(c->buffer));
1090         if(r <= 0) {
1091                 int want = SSL_get_error(c->ssl, r);
1092                 if(want == SSL_ERROR_ZERO_RETURN) {
1093                         return 0; /* shutdown, closed */
1094                 } else if(want == SSL_ERROR_WANT_READ) {
1095                         return 1; /* read more later */
1096                 } else if(want == SSL_ERROR_WANT_WRITE) {
1097                         c->ssl_shake_state = comm_ssl_shake_hs_write;
1098                         comm_point_listen_for_rw(c, 0, 1);
1099                         return 1;
1100                 } else if(want == SSL_ERROR_SYSCALL) {
1101                         if(errno != 0)
1102                                 log_err("SSL_read syscall: %s",
1103                                         strerror(errno));
1104                         return 0;
1105                 }
1106                 log_crypto_err("could not SSL_read");
1107                 return 0;
1108         }
1109         sldns_buffer_skip(c->buffer, (ssize_t)r);
1110         if(sldns_buffer_remaining(c->buffer) <= 0) {
1111                 tcp_callback_reader(c);
1112         }
1113         return 1;
1114 #else
1115         (void)c;
1116         return 0;
1117 #endif /* HAVE_SSL */
1118 }
1119
1120 /** ssl write callback on TCP */
1121 static int
1122 ssl_handle_write(struct comm_point* c)
1123 {
1124 #ifdef HAVE_SSL
1125         int r;
1126         if(c->ssl_shake_state != comm_ssl_shake_none) {
1127                 if(!ssl_handshake(c))
1128                         return 0;
1129                 if(c->ssl_shake_state != comm_ssl_shake_none)
1130                         return 1;
1131         }
1132         /* ignore return, if fails we may simply block */
1133         (void)SSL_set_mode(c->ssl, SSL_MODE_ENABLE_PARTIAL_WRITE);
1134         if(c->tcp_byte_count < sizeof(uint16_t)) {
1135                 uint16_t len = htons(sldns_buffer_limit(c->buffer));
1136                 ERR_clear_error();
1137                 r = SSL_write(c->ssl,
1138                         (void*)(((uint8_t*)&len)+c->tcp_byte_count),
1139                         (int)(sizeof(uint16_t)-c->tcp_byte_count));
1140                 if(r <= 0) {
1141                         int want = SSL_get_error(c->ssl, r);
1142                         if(want == SSL_ERROR_ZERO_RETURN) {
1143                                 return 0; /* closed */
1144                         } else if(want == SSL_ERROR_WANT_READ) {
1145                                 c->ssl_shake_state = comm_ssl_shake_read;
1146                                 comm_point_listen_for_rw(c, 1, 0);
1147                                 return 1; /* wait for read condition */
1148                         } else if(want == SSL_ERROR_WANT_WRITE) {
1149                                 return 1; /* write more later */
1150                         } else if(want == SSL_ERROR_SYSCALL) {
1151                                 if(errno != 0)
1152                                         log_err("SSL_write syscall: %s",
1153                                                 strerror(errno));
1154                                 return 0;
1155                         }
1156                         log_crypto_err("could not SSL_write");
1157                         return 0;
1158                 }
1159                 c->tcp_byte_count += r;
1160                 if(c->tcp_byte_count < sizeof(uint16_t))
1161                         return 1;
1162                 sldns_buffer_set_position(c->buffer, c->tcp_byte_count -
1163                         sizeof(uint16_t));
1164                 if(sldns_buffer_remaining(c->buffer) == 0) {
1165                         tcp_callback_writer(c);
1166                         return 1;
1167                 }
1168         }
1169         log_assert(sldns_buffer_remaining(c->buffer) > 0);
1170         ERR_clear_error();
1171         r = SSL_write(c->ssl, (void*)sldns_buffer_current(c->buffer),
1172                 (int)sldns_buffer_remaining(c->buffer));
1173         if(r <= 0) {
1174                 int want = SSL_get_error(c->ssl, r);
1175                 if(want == SSL_ERROR_ZERO_RETURN) {
1176                         return 0; /* closed */
1177                 } else if(want == SSL_ERROR_WANT_READ) {
1178                         c->ssl_shake_state = comm_ssl_shake_read;
1179                         comm_point_listen_for_rw(c, 1, 0);
1180                         return 1; /* wait for read condition */
1181                 } else if(want == SSL_ERROR_WANT_WRITE) {
1182                         return 1; /* write more later */
1183                 } else if(want == SSL_ERROR_SYSCALL) {
1184                         if(errno != 0)
1185                                 log_err("SSL_write syscall: %s",
1186                                         strerror(errno));
1187                         return 0;
1188                 }
1189                 log_crypto_err("could not SSL_write");
1190                 return 0;
1191         }
1192         sldns_buffer_skip(c->buffer, (ssize_t)r);
1193
1194         if(sldns_buffer_remaining(c->buffer) == 0) {
1195                 tcp_callback_writer(c);
1196         }
1197         return 1;
1198 #else
1199         (void)c;
1200         return 0;
1201 #endif /* HAVE_SSL */
1202 }
1203
1204 /** handle ssl tcp connection with dns contents */
1205 static int
1206 ssl_handle_it(struct comm_point* c)
1207 {
1208         if(c->tcp_is_reading)
1209                 return ssl_handle_read(c);
1210         return ssl_handle_write(c);
1211 }
1212
1213 /** Handle tcp reading callback. 
1214  * @param fd: file descriptor of socket.
1215  * @param c: comm point to read from into buffer.
1216  * @param short_ok: if true, very short packets are OK (for comm_local).
1217  * @return: 0 on error 
1218  */
1219 static int
1220 comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok)
1221 {
1222         ssize_t r;
1223         log_assert(c->type == comm_tcp || c->type == comm_local);
1224         if(c->ssl)
1225                 return ssl_handle_it(c);
1226         if(!c->tcp_is_reading)
1227                 return 0;
1228
1229         log_assert(fd != -1);
1230         if(c->tcp_byte_count < sizeof(uint16_t)) {
1231                 /* read length bytes */
1232                 r = recv(fd,(void*)sldns_buffer_at(c->buffer,c->tcp_byte_count),
1233                         sizeof(uint16_t)-c->tcp_byte_count, 0);
1234                 if(r == 0)
1235                         return 0;
1236                 else if(r == -1) {
1237 #ifndef USE_WINSOCK
1238                         if(errno == EINTR || errno == EAGAIN)
1239                                 return 1;
1240 #ifdef ECONNRESET
1241                         if(errno == ECONNRESET && verbosity < 2)
1242                                 return 0; /* silence reset by peer */
1243 #endif
1244                         log_err_addr("read (in tcp s)", strerror(errno),
1245                                 &c->repinfo.addr, c->repinfo.addrlen);
1246 #else /* USE_WINSOCK */
1247                         if(WSAGetLastError() == WSAECONNRESET)
1248                                 return 0;
1249                         if(WSAGetLastError() == WSAEINPROGRESS)
1250                                 return 1;
1251                         if(WSAGetLastError() == WSAEWOULDBLOCK) {
1252                                 ub_winsock_tcp_wouldblock(c->ev->ev,
1253                                         UB_EV_READ);
1254                                 return 1;
1255                         }
1256                         log_err_addr("read (in tcp s)", 
1257                                 wsa_strerror(WSAGetLastError()),
1258                                 &c->repinfo.addr, c->repinfo.addrlen);
1259 #endif
1260                         return 0;
1261                 } 
1262                 c->tcp_byte_count += r;
1263                 if(c->tcp_byte_count != sizeof(uint16_t))
1264                         return 1;
1265                 if(sldns_buffer_read_u16_at(c->buffer, 0) >
1266                         sldns_buffer_capacity(c->buffer)) {
1267                         verbose(VERB_QUERY, "tcp: dropped larger than buffer");
1268                         return 0;
1269                 }
1270                 sldns_buffer_set_limit(c->buffer, 
1271                         sldns_buffer_read_u16_at(c->buffer, 0));
1272                 if(!short_ok && 
1273                         sldns_buffer_limit(c->buffer) < LDNS_HEADER_SIZE) {
1274                         verbose(VERB_QUERY, "tcp: dropped bogus too short.");
1275                         return 0;
1276                 }
1277                 verbose(VERB_ALGO, "Reading tcp query of length %d", 
1278                         (int)sldns_buffer_limit(c->buffer));
1279         }
1280
1281         log_assert(sldns_buffer_remaining(c->buffer) > 0);
1282         r = recv(fd, (void*)sldns_buffer_current(c->buffer), 
1283                 sldns_buffer_remaining(c->buffer), 0);
1284         if(r == 0) {
1285                 return 0;
1286         } else if(r == -1) {
1287 #ifndef USE_WINSOCK
1288                 if(errno == EINTR || errno == EAGAIN)
1289                         return 1;
1290                 log_err_addr("read (in tcp r)", strerror(errno),
1291                         &c->repinfo.addr, c->repinfo.addrlen);
1292 #else /* USE_WINSOCK */
1293                 if(WSAGetLastError() == WSAECONNRESET)
1294                         return 0;
1295                 if(WSAGetLastError() == WSAEINPROGRESS)
1296                         return 1;
1297                 if(WSAGetLastError() == WSAEWOULDBLOCK) {
1298                         ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_READ);
1299                         return 1;
1300                 }
1301                 log_err_addr("read (in tcp r)",
1302                         wsa_strerror(WSAGetLastError()),
1303                         &c->repinfo.addr, c->repinfo.addrlen);
1304 #endif
1305                 return 0;
1306         }
1307         sldns_buffer_skip(c->buffer, r);
1308         if(sldns_buffer_remaining(c->buffer) <= 0) {
1309                 tcp_callback_reader(c);
1310         }
1311         return 1;
1312 }
1313
1314 /** 
1315  * Handle tcp writing callback. 
1316  * @param fd: file descriptor of socket.
1317  * @param c: comm point to write buffer out of.
1318  * @return: 0 on error
1319  */
1320 static int
1321 comm_point_tcp_handle_write(int fd, struct comm_point* c)
1322 {
1323         ssize_t r;
1324         struct sldns_buffer *buffer;
1325         log_assert(c->type == comm_tcp);
1326 #ifdef USE_DNSCRYPT
1327         buffer = c->dnscrypt_buffer;
1328 #else
1329         buffer = c->buffer;
1330 #endif
1331         if(c->tcp_is_reading && !c->ssl)
1332                 return 0;
1333         log_assert(fd != -1);
1334         if(c->tcp_byte_count == 0 && c->tcp_check_nb_connect) {
1335                 /* check for pending error from nonblocking connect */
1336                 /* from Stevens, unix network programming, vol1, 3rd ed, p450*/
1337                 int error = 0;
1338                 socklen_t len = (socklen_t)sizeof(error);
1339                 if(getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&error, 
1340                         &len) < 0){
1341 #ifndef USE_WINSOCK
1342                         error = errno; /* on solaris errno is error */
1343 #else /* USE_WINSOCK */
1344                         error = WSAGetLastError();
1345 #endif
1346                 }
1347 #ifndef USE_WINSOCK
1348 #if defined(EINPROGRESS) && defined(EWOULDBLOCK)
1349                 if(error == EINPROGRESS || error == EWOULDBLOCK)
1350                         return 1; /* try again later */
1351                 else
1352 #endif
1353                 if(error != 0 && verbosity < 2)
1354                         return 0; /* silence lots of chatter in the logs */
1355                 else if(error != 0) {
1356                         log_err_addr("tcp connect", strerror(error),
1357                                 &c->repinfo.addr, c->repinfo.addrlen);
1358 #else /* USE_WINSOCK */
1359                 /* examine error */
1360                 if(error == WSAEINPROGRESS)
1361                         return 1;
1362                 else if(error == WSAEWOULDBLOCK) {
1363                         ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE);
1364                         return 1;
1365                 } else if(error != 0 && verbosity < 2)
1366                         return 0;
1367                 else if(error != 0) {
1368                         log_err_addr("tcp connect", wsa_strerror(error),
1369                                 &c->repinfo.addr, c->repinfo.addrlen);
1370 #endif /* USE_WINSOCK */
1371                         return 0;
1372                 }
1373         }
1374         if(c->ssl)
1375                 return ssl_handle_it(c);
1376
1377 #ifdef USE_MSG_FASTOPEN
1378         /* Only try this on first use of a connection that uses tfo, 
1379            otherwise fall through to normal write */
1380         /* Also, TFO support on WINDOWS not implemented at the moment */
1381         if(c->tcp_do_fastopen == 1) {
1382                 /* this form of sendmsg() does both a connect() and send() so need to
1383                    look for various flavours of error*/
1384                 uint16_t len = htons(sldns_buffer_limit(buffer));
1385                 struct msghdr msg;
1386                 struct iovec iov[2];
1387                 c->tcp_do_fastopen = 0;
1388                 memset(&msg, 0, sizeof(msg));
1389                 iov[0].iov_base = (uint8_t*)&len + c->tcp_byte_count;
1390                 iov[0].iov_len = sizeof(uint16_t) - c->tcp_byte_count;
1391                 iov[1].iov_base = sldns_buffer_begin(buffer);
1392                 iov[1].iov_len = sldns_buffer_limit(buffer);
1393                 log_assert(iov[0].iov_len > 0);
1394                 log_assert(iov[1].iov_len > 0);
1395                 msg.msg_name = &c->repinfo.addr;
1396                 msg.msg_namelen = c->repinfo.addrlen;
1397                 msg.msg_iov = iov;
1398                 msg.msg_iovlen = 2;
1399                 r = sendmsg(fd, &msg, MSG_FASTOPEN);
1400                 if (r == -1) {
1401 #if defined(EINPROGRESS) && defined(EWOULDBLOCK)
1402                         /* Handshake is underway, maybe because no TFO cookie available.
1403                            Come back to write the messsage*/
1404                         if(errno == EINPROGRESS || errno == EWOULDBLOCK)
1405                                 return 1;
1406 #endif
1407                         if(errno == EINTR || errno == EAGAIN)
1408                                 return 1;
1409                         /* Not handling EISCONN here as shouldn't ever hit that case.*/
1410                         if(errno != EPIPE && errno != 0 && verbosity < 2)
1411                                 return 0; /* silence lots of chatter in the logs */
1412                         if(errno != EPIPE && errno != 0) {
1413                                 log_err_addr("tcp sendmsg", strerror(errno),
1414                                         &c->repinfo.addr, c->repinfo.addrlen);
1415                                 return 0;
1416                         }
1417                         /* fallthrough to nonFASTOPEN
1418                          * (MSG_FASTOPEN on Linux 3 produces EPIPE)
1419                          * we need to perform connect() */
1420                         if(connect(fd, (struct sockaddr *)&c->repinfo.addr, c->repinfo.addrlen) == -1) {
1421 #ifdef EINPROGRESS
1422                                 if(errno == EINPROGRESS)
1423                                         return 1; /* wait until connect done*/
1424 #endif
1425 #ifdef USE_WINSOCK
1426                                 if(WSAGetLastError() == WSAEINPROGRESS ||
1427                                         WSAGetLastError() == WSAEWOULDBLOCK)
1428                                         return 1; /* wait until connect done*/
1429 #endif
1430                                 if(tcp_connect_errno_needs_log(
1431                                         (struct sockaddr *)&c->repinfo.addr, c->repinfo.addrlen)) {
1432                                         log_err_addr("outgoing tcp: connect after EPIPE for fastopen",
1433                                                 strerror(errno), &c->repinfo.addr, c->repinfo.addrlen);
1434                                 }
1435                                 return 0;
1436                         }
1437
1438                 } else {
1439                         c->tcp_byte_count += r;
1440                         if(c->tcp_byte_count < sizeof(uint16_t))
1441                                 return 1;
1442                         sldns_buffer_set_position(buffer, c->tcp_byte_count - 
1443                                 sizeof(uint16_t));
1444                         if(sldns_buffer_remaining(buffer) == 0) {
1445                                 tcp_callback_writer(c);
1446                                 return 1;
1447                         }
1448                 }
1449         }
1450 #endif /* USE_MSG_FASTOPEN */
1451
1452         if(c->tcp_byte_count < sizeof(uint16_t)) {
1453                 uint16_t len = htons(sldns_buffer_limit(buffer));
1454 #ifdef HAVE_WRITEV
1455                 struct iovec iov[2];
1456                 iov[0].iov_base = (uint8_t*)&len + c->tcp_byte_count;
1457                 iov[0].iov_len = sizeof(uint16_t) - c->tcp_byte_count;
1458                 iov[1].iov_base = sldns_buffer_begin(buffer);
1459                 iov[1].iov_len = sldns_buffer_limit(buffer);
1460                 log_assert(iov[0].iov_len > 0);
1461                 log_assert(iov[1].iov_len > 0);
1462                 r = writev(fd, iov, 2);
1463 #else /* HAVE_WRITEV */
1464                 r = send(fd, (void*)(((uint8_t*)&len)+c->tcp_byte_count),
1465                         sizeof(uint16_t)-c->tcp_byte_count, 0);
1466 #endif /* HAVE_WRITEV */
1467                 if(r == -1) {
1468 #ifndef USE_WINSOCK
1469 #  ifdef EPIPE
1470                         if(errno == EPIPE && verbosity < 2)
1471                                 return 0; /* silence 'broken pipe' */
1472   #endif
1473                         if(errno == EINTR || errno == EAGAIN)
1474                                 return 1;
1475 #  ifdef HAVE_WRITEV
1476                         log_err_addr("tcp writev", strerror(errno),
1477                                 &c->repinfo.addr, c->repinfo.addrlen);
1478 #  else /* HAVE_WRITEV */
1479                         log_err_addr("tcp send s", strerror(errno),
1480                                 &c->repinfo.addr, c->repinfo.addrlen);
1481 #  endif /* HAVE_WRITEV */
1482 #else
1483                         if(WSAGetLastError() == WSAENOTCONN)
1484                                 return 1;
1485                         if(WSAGetLastError() == WSAEINPROGRESS)
1486                                 return 1;
1487                         if(WSAGetLastError() == WSAEWOULDBLOCK) {
1488                                 ub_winsock_tcp_wouldblock(c->ev->ev,
1489                                         UB_EV_WRITE);
1490                                 return 1; 
1491                         }
1492                         log_err_addr("tcp send s",
1493                                 wsa_strerror(WSAGetLastError()),
1494                                 &c->repinfo.addr, c->repinfo.addrlen);
1495 #endif
1496                         return 0;
1497                 }
1498                 c->tcp_byte_count += r;
1499                 if(c->tcp_byte_count < sizeof(uint16_t))
1500                         return 1;
1501                 sldns_buffer_set_position(buffer, c->tcp_byte_count - 
1502                         sizeof(uint16_t));
1503                 if(sldns_buffer_remaining(buffer) == 0) {
1504                         tcp_callback_writer(c);
1505                         return 1;
1506                 }
1507         }
1508         log_assert(sldns_buffer_remaining(buffer) > 0);
1509         r = send(fd, (void*)sldns_buffer_current(buffer), 
1510                 sldns_buffer_remaining(buffer), 0);
1511         if(r == -1) {
1512 #ifndef USE_WINSOCK
1513                 if(errno == EINTR || errno == EAGAIN)
1514                         return 1;
1515                 log_err_addr("tcp send r", strerror(errno),
1516                         &c->repinfo.addr, c->repinfo.addrlen);
1517 #else
1518                 if(WSAGetLastError() == WSAEINPROGRESS)
1519                         return 1;
1520                 if(WSAGetLastError() == WSAEWOULDBLOCK) {
1521                         ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE);
1522                         return 1; 
1523                 }
1524                 log_err_addr("tcp send r", wsa_strerror(WSAGetLastError()),
1525                         &c->repinfo.addr, c->repinfo.addrlen);
1526 #endif
1527                 return 0;
1528         }
1529         sldns_buffer_skip(buffer, r);
1530
1531         if(sldns_buffer_remaining(buffer) == 0) {
1532                 tcp_callback_writer(c);
1533         }
1534         
1535         return 1;
1536 }
1537
1538 void 
1539 comm_point_tcp_handle_callback(int fd, short event, void* arg)
1540 {
1541         struct comm_point* c = (struct comm_point*)arg;
1542         log_assert(c->type == comm_tcp);
1543         ub_comm_base_now(c->ev->base);
1544
1545 #ifdef USE_DNSCRYPT
1546         /* Initialize if this is a dnscrypt socket */
1547         if(c->tcp_parent) {
1548                 c->dnscrypt = c->tcp_parent->dnscrypt;
1549         }
1550         if(c->dnscrypt && c->dnscrypt_buffer == c->buffer) {
1551                 c->dnscrypt_buffer = sldns_buffer_new(sldns_buffer_capacity(c->buffer));
1552                 if(!c->dnscrypt_buffer) {
1553                         log_err("Could not allocate dnscrypt buffer");
1554                         reclaim_tcp_handler(c);
1555                         if(!c->tcp_do_close) {
1556                                 fptr_ok(fptr_whitelist_comm_point(
1557                                         c->callback));
1558                                 (void)(*c->callback)(c, c->cb_arg, 
1559                                         NETEVENT_CLOSED, NULL);
1560                         }
1561                         return;
1562                 }
1563         }
1564 #endif
1565
1566         if(event&UB_EV_READ) {
1567                 if(!comm_point_tcp_handle_read(fd, c, 0)) {
1568                         reclaim_tcp_handler(c);
1569                         if(!c->tcp_do_close) {
1570                                 fptr_ok(fptr_whitelist_comm_point(
1571                                         c->callback));
1572                                 (void)(*c->callback)(c, c->cb_arg, 
1573                                         NETEVENT_CLOSED, NULL);
1574                         }
1575                 }
1576                 return;
1577         }
1578         if(event&UB_EV_WRITE) {
1579                 if(!comm_point_tcp_handle_write(fd, c)) {
1580                         reclaim_tcp_handler(c);
1581                         if(!c->tcp_do_close) {
1582                                 fptr_ok(fptr_whitelist_comm_point(
1583                                         c->callback));
1584                                 (void)(*c->callback)(c, c->cb_arg, 
1585                                         NETEVENT_CLOSED, NULL);
1586                         }
1587                 }
1588                 return;
1589         }
1590         if(event&UB_EV_TIMEOUT) {
1591                 verbose(VERB_QUERY, "tcp took too long, dropped");
1592                 reclaim_tcp_handler(c);
1593                 if(!c->tcp_do_close) {
1594                         fptr_ok(fptr_whitelist_comm_point(c->callback));
1595                         (void)(*c->callback)(c, c->cb_arg,
1596                                 NETEVENT_TIMEOUT, NULL);
1597                 }
1598                 return;
1599         }
1600         log_err("Ignored event %d for tcphdl.", event);
1601 }
1602
1603 void comm_point_local_handle_callback(int fd, short event, void* arg)
1604 {
1605         struct comm_point* c = (struct comm_point*)arg;
1606         log_assert(c->type == comm_local);
1607         ub_comm_base_now(c->ev->base);
1608
1609         if(event&UB_EV_READ) {
1610                 if(!comm_point_tcp_handle_read(fd, c, 1)) {
1611                         fptr_ok(fptr_whitelist_comm_point(c->callback));
1612                         (void)(*c->callback)(c, c->cb_arg, NETEVENT_CLOSED, 
1613                                 NULL);
1614                 }
1615                 return;
1616         }
1617         log_err("Ignored event %d for localhdl.", event);
1618 }
1619
1620 void comm_point_raw_handle_callback(int ATTR_UNUSED(fd), 
1621         short event, void* arg)
1622 {
1623         struct comm_point* c = (struct comm_point*)arg;
1624         int err = NETEVENT_NOERROR;
1625         log_assert(c->type == comm_raw);
1626         ub_comm_base_now(c->ev->base);
1627         
1628         if(event&UB_EV_TIMEOUT)
1629                 err = NETEVENT_TIMEOUT;
1630         fptr_ok(fptr_whitelist_comm_point_raw(c->callback));
1631         (void)(*c->callback)(c, c->cb_arg, err, NULL);
1632 }
1633
1634 struct comm_point* 
1635 comm_point_create_udp(struct comm_base *base, int fd, sldns_buffer* buffer,
1636         comm_point_callback_type* callback, void* callback_arg)
1637 {
1638         struct comm_point* c = (struct comm_point*)calloc(1,
1639                 sizeof(struct comm_point));
1640         short evbits;
1641         if(!c)
1642                 return NULL;
1643         c->ev = (struct internal_event*)calloc(1,
1644                 sizeof(struct internal_event));
1645         if(!c->ev) {
1646                 free(c);
1647                 return NULL;
1648         }
1649         c->ev->base = base;
1650         c->fd = fd;
1651         c->buffer = buffer;
1652         c->timeout = NULL;
1653         c->tcp_is_reading = 0;
1654         c->tcp_byte_count = 0;
1655         c->tcp_parent = NULL;
1656         c->max_tcp_count = 0;
1657         c->cur_tcp_count = 0;
1658         c->tcp_handlers = NULL;
1659         c->tcp_free = NULL;
1660         c->type = comm_udp;
1661         c->tcp_do_close = 0;
1662         c->do_not_close = 0;
1663         c->tcp_do_toggle_rw = 0;
1664         c->tcp_check_nb_connect = 0;
1665 #ifdef USE_MSG_FASTOPEN
1666         c->tcp_do_fastopen = 0;
1667 #endif
1668 #ifdef USE_DNSCRYPT
1669         c->dnscrypt = 0;
1670         c->dnscrypt_buffer = buffer;
1671 #endif
1672         c->inuse = 0;
1673         c->callback = callback;
1674         c->cb_arg = callback_arg;
1675         evbits = UB_EV_READ | UB_EV_PERSIST;
1676         /* ub_event stuff */
1677         c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits,
1678                 comm_point_udp_callback, c);
1679         if(c->ev->ev == NULL) {
1680                 log_err("could not baseset udp event");
1681                 comm_point_delete(c);
1682                 return NULL;
1683         }
1684         if(fd!=-1 && ub_event_add(c->ev->ev, c->timeout) != 0 ) {
1685                 log_err("could not add udp event");
1686                 comm_point_delete(c);
1687                 return NULL;
1688         }
1689         return c;
1690 }
1691
1692 struct comm_point* 
1693 comm_point_create_udp_ancil(struct comm_base *base, int fd, 
1694         sldns_buffer* buffer, 
1695         comm_point_callback_type* callback, void* callback_arg)
1696 {
1697         struct comm_point* c = (struct comm_point*)calloc(1,
1698                 sizeof(struct comm_point));
1699         short evbits;
1700         if(!c)
1701                 return NULL;
1702         c->ev = (struct internal_event*)calloc(1,
1703                 sizeof(struct internal_event));
1704         if(!c->ev) {
1705                 free(c);
1706                 return NULL;
1707         }
1708         c->ev->base = base;
1709         c->fd = fd;
1710         c->buffer = buffer;
1711         c->timeout = NULL;
1712         c->tcp_is_reading = 0;
1713         c->tcp_byte_count = 0;
1714         c->tcp_parent = NULL;
1715         c->max_tcp_count = 0;
1716         c->cur_tcp_count = 0;
1717         c->tcp_handlers = NULL;
1718         c->tcp_free = NULL;
1719         c->type = comm_udp;
1720         c->tcp_do_close = 0;
1721         c->do_not_close = 0;
1722 #ifdef USE_DNSCRYPT
1723         c->dnscrypt = 0;
1724         c->dnscrypt_buffer = buffer;
1725 #endif
1726         c->inuse = 0;
1727         c->tcp_do_toggle_rw = 0;
1728         c->tcp_check_nb_connect = 0;
1729 #ifdef USE_MSG_FASTOPEN
1730         c->tcp_do_fastopen = 0;
1731 #endif
1732         c->callback = callback;
1733         c->cb_arg = callback_arg;
1734         evbits = UB_EV_READ | UB_EV_PERSIST;
1735         /* ub_event stuff */
1736         c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits,
1737                 comm_point_udp_ancil_callback, c);
1738         if(c->ev->ev == NULL) {
1739                 log_err("could not baseset udp event");
1740                 comm_point_delete(c);
1741                 return NULL;
1742         }
1743         if(fd!=-1 && ub_event_add(c->ev->ev, c->timeout) != 0 ) {
1744                 log_err("could not add udp event");
1745                 comm_point_delete(c);
1746                 return NULL;
1747         }
1748         return c;
1749 }
1750
1751 static struct comm_point* 
1752 comm_point_create_tcp_handler(struct comm_base *base, 
1753         struct comm_point* parent, size_t bufsize,
1754         comm_point_callback_type* callback, void* callback_arg)
1755 {
1756         struct comm_point* c = (struct comm_point*)calloc(1,
1757                 sizeof(struct comm_point));
1758         short evbits;
1759         if(!c)
1760                 return NULL;
1761         c->ev = (struct internal_event*)calloc(1,
1762                 sizeof(struct internal_event));
1763         if(!c->ev) {
1764                 free(c);
1765                 return NULL;
1766         }
1767         c->ev->base = base;
1768         c->fd = -1;
1769         c->buffer = sldns_buffer_new(bufsize);
1770         if(!c->buffer) {
1771                 free(c->ev);
1772                 free(c);
1773                 return NULL;
1774         }
1775         c->timeout = (struct timeval*)malloc(sizeof(struct timeval));
1776         if(!c->timeout) {
1777                 sldns_buffer_free(c->buffer);
1778                 free(c->ev);
1779                 free(c);
1780                 return NULL;
1781         }
1782         c->tcp_is_reading = 0;
1783         c->tcp_byte_count = 0;
1784         c->tcp_parent = parent;
1785         c->max_tcp_count = 0;
1786         c->cur_tcp_count = 0;
1787         c->tcp_handlers = NULL;
1788         c->tcp_free = NULL;
1789         c->type = comm_tcp;
1790         c->tcp_do_close = 0;
1791         c->do_not_close = 0;
1792         c->tcp_do_toggle_rw = 1;
1793         c->tcp_check_nb_connect = 0;
1794 #ifdef USE_MSG_FASTOPEN
1795         c->tcp_do_fastopen = 0;
1796 #endif
1797 #ifdef USE_DNSCRYPT
1798         c->dnscrypt = 0;
1799         /* We don't know just yet if this is a dnscrypt channel. Allocation
1800          * will be done when handling the callback. */
1801         c->dnscrypt_buffer = c->buffer;
1802 #endif
1803         c->repinfo.c = c;
1804         c->callback = callback;
1805         c->cb_arg = callback_arg;
1806         /* add to parent free list */
1807         c->tcp_free = parent->tcp_free;
1808         parent->tcp_free = c;
1809         /* ub_event stuff */
1810         evbits = UB_EV_PERSIST | UB_EV_READ | UB_EV_TIMEOUT;
1811         c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits,
1812                 comm_point_tcp_handle_callback, c);
1813         if(c->ev->ev == NULL)
1814         {
1815                 log_err("could not basetset tcphdl event");
1816                 parent->tcp_free = c->tcp_free;
1817                 free(c->ev);
1818                 free(c);
1819                 return NULL;
1820         }
1821         return c;
1822 }
1823
1824 struct comm_point* 
1825 comm_point_create_tcp(struct comm_base *base, int fd, int num, size_t bufsize,
1826         comm_point_callback_type* callback, void* callback_arg)
1827 {
1828         struct comm_point* c = (struct comm_point*)calloc(1,
1829                 sizeof(struct comm_point));
1830         short evbits;
1831         int i;
1832         /* first allocate the TCP accept listener */
1833         if(!c)
1834                 return NULL;
1835         c->ev = (struct internal_event*)calloc(1,
1836                 sizeof(struct internal_event));
1837         if(!c->ev) {
1838                 free(c);
1839                 return NULL;
1840         }
1841         c->ev->base = base;
1842         c->fd = fd;
1843         c->buffer = NULL;
1844         c->timeout = NULL;
1845         c->tcp_is_reading = 0;
1846         c->tcp_byte_count = 0;
1847         c->tcp_parent = NULL;
1848         c->max_tcp_count = num;
1849         c->cur_tcp_count = 0;
1850         c->tcp_handlers = (struct comm_point**)calloc((size_t)num,
1851                 sizeof(struct comm_point*));
1852         if(!c->tcp_handlers) {
1853                 free(c->ev);
1854                 free(c);
1855                 return NULL;
1856         }
1857         c->tcp_free = NULL;
1858         c->type = comm_tcp_accept;
1859         c->tcp_do_close = 0;
1860         c->do_not_close = 0;
1861         c->tcp_do_toggle_rw = 0;
1862         c->tcp_check_nb_connect = 0;
1863 #ifdef USE_MSG_FASTOPEN
1864         c->tcp_do_fastopen = 0;
1865 #endif
1866 #ifdef USE_DNSCRYPT
1867         c->dnscrypt = 0;
1868         c->dnscrypt_buffer = NULL;
1869 #endif
1870         c->callback = NULL;
1871         c->cb_arg = NULL;
1872         evbits = UB_EV_READ | UB_EV_PERSIST;
1873         /* ub_event stuff */
1874         c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits,
1875                 comm_point_tcp_accept_callback, c);
1876         if(c->ev->ev == NULL) {
1877                 log_err("could not baseset tcpacc event");
1878                 comm_point_delete(c);
1879                 return NULL;
1880         }
1881         if (ub_event_add(c->ev->ev, c->timeout) != 0) {
1882                 log_err("could not add tcpacc event");
1883                 comm_point_delete(c);
1884                 return NULL;
1885         }
1886         /* now prealloc the tcp handlers */
1887         for(i=0; i<num; i++) {
1888                 c->tcp_handlers[i] = comm_point_create_tcp_handler(base,
1889                         c, bufsize, callback, callback_arg);
1890                 if(!c->tcp_handlers[i]) {
1891                         comm_point_delete(c);
1892                         return NULL;
1893                 }
1894         }
1895         
1896         return c;
1897 }
1898
1899 struct comm_point* 
1900 comm_point_create_tcp_out(struct comm_base *base, size_t bufsize,
1901         comm_point_callback_type* callback, void* callback_arg)
1902 {
1903         struct comm_point* c = (struct comm_point*)calloc(1,
1904                 sizeof(struct comm_point));
1905         short evbits;
1906         if(!c)
1907                 return NULL;
1908         c->ev = (struct internal_event*)calloc(1,
1909                 sizeof(struct internal_event));
1910         if(!c->ev) {
1911                 free(c);
1912                 return NULL;
1913         }
1914         c->ev->base = base;
1915         c->fd = -1;
1916         c->buffer = sldns_buffer_new(bufsize);
1917         if(!c->buffer) {
1918                 free(c->ev);
1919                 free(c);
1920                 return NULL;
1921         }
1922         c->timeout = NULL;
1923         c->tcp_is_reading = 0;
1924         c->tcp_byte_count = 0;
1925         c->tcp_parent = NULL;
1926         c->max_tcp_count = 0;
1927         c->cur_tcp_count = 0;
1928         c->tcp_handlers = NULL;
1929         c->tcp_free = NULL;
1930         c->type = comm_tcp;
1931         c->tcp_do_close = 0;
1932         c->do_not_close = 0;
1933         c->tcp_do_toggle_rw = 1;
1934         c->tcp_check_nb_connect = 1;
1935 #ifdef USE_MSG_FASTOPEN
1936         c->tcp_do_fastopen = 1;
1937 #endif
1938 #ifdef USE_DNSCRYPT
1939         c->dnscrypt = 0;
1940         c->dnscrypt_buffer = c->buffer;
1941 #endif
1942         c->repinfo.c = c;
1943         c->callback = callback;
1944         c->cb_arg = callback_arg;
1945         evbits = UB_EV_PERSIST | UB_EV_WRITE;
1946         c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits,
1947                 comm_point_tcp_handle_callback, c);
1948         if(c->ev->ev == NULL)
1949         {
1950                 log_err("could not baseset tcpout event");
1951                 sldns_buffer_free(c->buffer);
1952                 free(c->ev);
1953                 free(c);
1954                 return NULL;
1955         }
1956
1957         return c;
1958 }
1959
1960 struct comm_point* 
1961 comm_point_create_local(struct comm_base *base, int fd, size_t bufsize,
1962         comm_point_callback_type* callback, void* callback_arg)
1963 {
1964         struct comm_point* c = (struct comm_point*)calloc(1,
1965                 sizeof(struct comm_point));
1966         short evbits;
1967         if(!c)
1968                 return NULL;
1969         c->ev = (struct internal_event*)calloc(1,
1970                 sizeof(struct internal_event));
1971         if(!c->ev) {
1972                 free(c);
1973                 return NULL;
1974         }
1975         c->ev->base = base;
1976         c->fd = fd;
1977         c->buffer = sldns_buffer_new(bufsize);
1978         if(!c->buffer) {
1979                 free(c->ev);
1980                 free(c);
1981                 return NULL;
1982         }
1983         c->timeout = NULL;
1984         c->tcp_is_reading = 1;
1985         c->tcp_byte_count = 0;
1986         c->tcp_parent = NULL;
1987         c->max_tcp_count = 0;
1988         c->cur_tcp_count = 0;
1989         c->tcp_handlers = NULL;
1990         c->tcp_free = NULL;
1991         c->type = comm_local;
1992         c->tcp_do_close = 0;
1993         c->do_not_close = 1;
1994         c->tcp_do_toggle_rw = 0;
1995         c->tcp_check_nb_connect = 0;
1996 #ifdef USE_MSG_FASTOPEN
1997         c->tcp_do_fastopen = 0;
1998 #endif
1999 #ifdef USE_DNSCRYPT
2000         c->dnscrypt = 0;
2001         c->dnscrypt_buffer = c->buffer;
2002 #endif
2003         c->callback = callback;
2004         c->cb_arg = callback_arg;
2005         /* ub_event stuff */
2006         evbits = UB_EV_PERSIST | UB_EV_READ;
2007         c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits,
2008                 comm_point_local_handle_callback, c);
2009         if(c->ev->ev == NULL) {
2010                 log_err("could not baseset localhdl event");
2011                 free(c->ev);
2012                 free(c);
2013                 return NULL;
2014         }
2015         if (ub_event_add(c->ev->ev, c->timeout) != 0) {
2016                 log_err("could not add localhdl event");
2017                 ub_event_free(c->ev->ev);
2018                 free(c->ev);
2019                 free(c);
2020                 return NULL;
2021         }
2022         return c;
2023 }
2024
2025 struct comm_point* 
2026 comm_point_create_raw(struct comm_base* base, int fd, int writing, 
2027         comm_point_callback_type* callback, void* callback_arg)
2028 {
2029         struct comm_point* c = (struct comm_point*)calloc(1,
2030                 sizeof(struct comm_point));
2031         short evbits;
2032         if(!c)
2033                 return NULL;
2034         c->ev = (struct internal_event*)calloc(1,
2035                 sizeof(struct internal_event));
2036         if(!c->ev) {
2037                 free(c);
2038                 return NULL;
2039         }
2040         c->ev->base = base;
2041         c->fd = fd;
2042         c->buffer = NULL;
2043         c->timeout = NULL;
2044         c->tcp_is_reading = 0;
2045         c->tcp_byte_count = 0;
2046         c->tcp_parent = NULL;
2047         c->max_tcp_count = 0;
2048         c->cur_tcp_count = 0;
2049         c->tcp_handlers = NULL;
2050         c->tcp_free = NULL;
2051         c->type = comm_raw;
2052         c->tcp_do_close = 0;
2053         c->do_not_close = 1;
2054         c->tcp_do_toggle_rw = 0;
2055         c->tcp_check_nb_connect = 0;
2056 #ifdef USE_MSG_FASTOPEN
2057         c->tcp_do_fastopen = 0;
2058 #endif
2059 #ifdef USE_DNSCRYPT
2060         c->dnscrypt = 0;
2061         c->dnscrypt_buffer = c->buffer;
2062 #endif
2063         c->callback = callback;
2064         c->cb_arg = callback_arg;
2065         /* ub_event stuff */
2066         if(writing)
2067                 evbits = UB_EV_PERSIST | UB_EV_WRITE;
2068         else    evbits = UB_EV_PERSIST | UB_EV_READ;
2069         c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits,
2070                 comm_point_raw_handle_callback, c);
2071         if(c->ev->ev == NULL) {
2072                 log_err("could not baseset rawhdl event");
2073                 free(c->ev);
2074                 free(c);
2075                 return NULL;
2076         }
2077         if (ub_event_add(c->ev->ev, c->timeout) != 0) {
2078                 log_err("could not add rawhdl event");
2079                 ub_event_free(c->ev->ev);
2080                 free(c->ev);
2081                 free(c);
2082                 return NULL;
2083         }
2084         return c;
2085 }
2086
2087 void 
2088 comm_point_close(struct comm_point* c)
2089 {
2090         if(!c)
2091                 return;
2092         if(c->fd != -1)
2093                 if(ub_event_del(c->ev->ev) != 0) {
2094                         log_err("could not event_del on close");
2095                 }
2096         /* close fd after removing from event lists, or epoll.. is messed up */
2097         if(c->fd != -1 && !c->do_not_close) {
2098                 verbose(VERB_ALGO, "close fd %d", c->fd);
2099 #ifndef USE_WINSOCK
2100                 close(c->fd);
2101 #else
2102                 closesocket(c->fd);
2103 #endif
2104         }
2105         c->fd = -1;
2106 }
2107
2108 void 
2109 comm_point_delete(struct comm_point* c)
2110 {
2111         if(!c) 
2112                 return;
2113         if(c->type == comm_tcp && c->ssl) {
2114 #ifdef HAVE_SSL
2115                 SSL_shutdown(c->ssl);
2116                 SSL_free(c->ssl);
2117 #endif
2118         }
2119         comm_point_close(c);
2120         if(c->tcp_handlers) {
2121                 int i;
2122                 for(i=0; i<c->max_tcp_count; i++)
2123                         comm_point_delete(c->tcp_handlers[i]);
2124                 free(c->tcp_handlers);
2125         }
2126         free(c->timeout);
2127         if(c->type == comm_tcp || c->type == comm_local) {
2128                 sldns_buffer_free(c->buffer);
2129 #ifdef USE_DNSCRYPT
2130                 if(c->dnscrypt && c->dnscrypt_buffer != c->buffer) {
2131                         sldns_buffer_free(c->dnscrypt_buffer);
2132                 }
2133 #endif
2134         }
2135         ub_event_free(c->ev->ev);
2136         free(c->ev);
2137         free(c);
2138 }
2139
2140 void 
2141 comm_point_send_reply(struct comm_reply *repinfo)
2142 {
2143         struct sldns_buffer* buffer;
2144         log_assert(repinfo && repinfo->c);
2145 #ifdef USE_DNSCRYPT
2146         buffer = repinfo->c->dnscrypt_buffer;
2147         if(!dnsc_handle_uncurved_request(repinfo)) {
2148                 return;
2149         }
2150 #else
2151         buffer = repinfo->c->buffer;
2152 #endif
2153         if(repinfo->c->type == comm_udp) {
2154                 if(repinfo->srctype)
2155                         comm_point_send_udp_msg_if(repinfo->c, 
2156                         buffer, (struct sockaddr*)&repinfo->addr, 
2157                         repinfo->addrlen, repinfo);
2158                 else
2159                         comm_point_send_udp_msg(repinfo->c, buffer,
2160                         (struct sockaddr*)&repinfo->addr, repinfo->addrlen);
2161 #ifdef USE_DNSTAP
2162                 if(repinfo->c->dtenv != NULL &&
2163                    repinfo->c->dtenv->log_client_response_messages)
2164                         dt_msg_send_client_response(repinfo->c->dtenv,
2165                         &repinfo->addr, repinfo->c->type, repinfo->c->buffer);
2166 #endif
2167         } else {
2168 #ifdef USE_DNSTAP
2169                 if(repinfo->c->tcp_parent->dtenv != NULL &&
2170                    repinfo->c->tcp_parent->dtenv->log_client_response_messages)
2171                         dt_msg_send_client_response(repinfo->c->tcp_parent->dtenv,
2172                         &repinfo->addr, repinfo->c->type, repinfo->c->buffer);
2173 #endif
2174                 comm_point_start_listening(repinfo->c, -1,
2175                         repinfo->c->tcp_timeout_msec);
2176         }
2177 }
2178
2179 void 
2180 comm_point_drop_reply(struct comm_reply* repinfo)
2181 {
2182         if(!repinfo)
2183                 return;
2184         log_assert(repinfo && repinfo->c);
2185         log_assert(repinfo->c->type != comm_tcp_accept);
2186         if(repinfo->c->type == comm_udp)
2187                 return;
2188         reclaim_tcp_handler(repinfo->c);
2189 }
2190
2191 void 
2192 comm_point_stop_listening(struct comm_point* c)
2193 {
2194         verbose(VERB_ALGO, "comm point stop listening %d", c->fd);
2195         if(ub_event_del(c->ev->ev) != 0) {
2196                 log_err("event_del error to stoplisten");
2197         }
2198 }
2199
2200 void 
2201 comm_point_start_listening(struct comm_point* c, int newfd, int msec)
2202 {
2203         verbose(VERB_ALGO, "comm point start listening %d", 
2204                 c->fd==-1?newfd:c->fd);
2205         if(c->type == comm_tcp_accept && !c->tcp_free) {
2206                 /* no use to start listening no free slots. */
2207                 return;
2208         }
2209         if(msec != -1 && msec != 0) {
2210                 if(!c->timeout) {
2211                         c->timeout = (struct timeval*)malloc(sizeof(
2212                                 struct timeval));
2213                         if(!c->timeout) {
2214                                 log_err("cpsl: malloc failed. No net read.");
2215                                 return;
2216                         }
2217                 }
2218                 ub_event_add_bits(c->ev->ev, UB_EV_TIMEOUT);
2219 #ifndef S_SPLINT_S /* splint fails on struct timeval. */
2220                 c->timeout->tv_sec = msec/1000;
2221                 c->timeout->tv_usec = (msec%1000)*1000;
2222 #endif /* S_SPLINT_S */
2223         }
2224         if(c->type == comm_tcp) {
2225                 ub_event_del_bits(c->ev->ev, UB_EV_READ|UB_EV_WRITE);
2226                 if(c->tcp_is_reading)
2227                         ub_event_add_bits(c->ev->ev, UB_EV_READ);
2228                 else    ub_event_add_bits(c->ev->ev, UB_EV_WRITE);
2229         }
2230         if(newfd != -1) {
2231                 if(c->fd != -1) {
2232 #ifndef USE_WINSOCK
2233                         close(c->fd);
2234 #else
2235                         closesocket(c->fd);
2236 #endif
2237                 }
2238                 c->fd = newfd;
2239                 ub_event_set_fd(c->ev->ev, c->fd);
2240         }
2241         if(ub_event_add(c->ev->ev, msec==0?NULL:c->timeout) != 0) {
2242                 log_err("event_add failed. in cpsl.");
2243         }
2244 }
2245
2246 void comm_point_listen_for_rw(struct comm_point* c, int rd, int wr)
2247 {
2248         verbose(VERB_ALGO, "comm point listen_for_rw %d %d", c->fd, wr);
2249         if(ub_event_del(c->ev->ev) != 0) {
2250                 log_err("event_del error to cplf");
2251         }
2252         ub_event_del_bits(c->ev->ev, UB_EV_READ|UB_EV_WRITE);
2253         if(rd) ub_event_add_bits(c->ev->ev, UB_EV_READ);
2254         if(wr) ub_event_add_bits(c->ev->ev, UB_EV_WRITE);
2255         if(ub_event_add(c->ev->ev, c->timeout) != 0) {
2256                 log_err("event_add failed. in cplf.");
2257         }
2258 }
2259
2260 size_t comm_point_get_mem(struct comm_point* c)
2261 {
2262         size_t s;
2263         if(!c) 
2264                 return 0;
2265         s = sizeof(*c) + sizeof(*c->ev);
2266         if(c->timeout) 
2267                 s += sizeof(*c->timeout);
2268         if(c->type == comm_tcp || c->type == comm_local) {
2269                 s += sizeof(*c->buffer) + sldns_buffer_capacity(c->buffer);
2270 #ifdef USE_DNSCRYPT
2271                 s += sizeof(*c->dnscrypt_buffer);
2272                 if(c->buffer != c->dnscrypt_buffer) {
2273                         s += sldns_buffer_capacity(c->dnscrypt_buffer);
2274                 }
2275 #endif
2276         }
2277         if(c->type == comm_tcp_accept) {
2278                 int i;
2279                 for(i=0; i<c->max_tcp_count; i++)
2280                         s += comm_point_get_mem(c->tcp_handlers[i]);
2281         }
2282         return s;
2283 }
2284
2285 struct comm_timer* 
2286 comm_timer_create(struct comm_base* base, void (*cb)(void*), void* cb_arg)
2287 {
2288         struct internal_timer *tm = (struct internal_timer*)calloc(1,
2289                 sizeof(struct internal_timer));
2290         if(!tm) {
2291                 log_err("malloc failed");
2292                 return NULL;
2293         }
2294         tm->super.ev_timer = tm;
2295         tm->base = base;
2296         tm->super.callback = cb;
2297         tm->super.cb_arg = cb_arg;
2298         tm->ev = ub_event_new(base->eb->base, -1, UB_EV_TIMEOUT, 
2299                 comm_timer_callback, &tm->super);
2300         if(tm->ev == NULL) {
2301                 log_err("timer_create: event_base_set failed.");
2302                 free(tm);
2303                 return NULL;
2304         }
2305         return &tm->super;
2306 }
2307
2308 void 
2309 comm_timer_disable(struct comm_timer* timer)
2310 {
2311         if(!timer)
2312                 return;
2313         ub_timer_del(timer->ev_timer->ev);
2314         timer->ev_timer->enabled = 0;
2315 }
2316
2317 void 
2318 comm_timer_set(struct comm_timer* timer, struct timeval* tv)
2319 {
2320         log_assert(tv);
2321         if(timer->ev_timer->enabled)
2322                 comm_timer_disable(timer);
2323         if(ub_timer_add(timer->ev_timer->ev, timer->ev_timer->base->eb->base,
2324                 comm_timer_callback, timer, tv) != 0)
2325                 log_err("comm_timer_set: evtimer_add failed.");
2326         timer->ev_timer->enabled = 1;
2327 }
2328
2329 void 
2330 comm_timer_delete(struct comm_timer* timer)
2331 {
2332         if(!timer)
2333                 return;
2334         comm_timer_disable(timer);
2335         /* Free the sub struct timer->ev_timer derived from the super struct timer.
2336          * i.e. assert(timer == timer->ev_timer)
2337          */
2338         ub_event_free(timer->ev_timer->ev);
2339         free(timer->ev_timer);
2340 }
2341
2342 void 
2343 comm_timer_callback(int ATTR_UNUSED(fd), short event, void* arg)
2344 {
2345         struct comm_timer* tm = (struct comm_timer*)arg;
2346         if(!(event&UB_EV_TIMEOUT))
2347                 return;
2348         ub_comm_base_now(tm->ev_timer->base);
2349         tm->ev_timer->enabled = 0;
2350         fptr_ok(fptr_whitelist_comm_timer(tm->callback));
2351         (*tm->callback)(tm->cb_arg);
2352 }
2353
2354 int 
2355 comm_timer_is_set(struct comm_timer* timer)
2356 {
2357         return (int)timer->ev_timer->enabled;
2358 }
2359
2360 size_t 
2361 comm_timer_get_mem(struct comm_timer* ATTR_UNUSED(timer))
2362 {
2363         return sizeof(struct internal_timer);
2364 }
2365
2366 struct comm_signal* 
2367 comm_signal_create(struct comm_base* base,
2368         void (*callback)(int, void*), void* cb_arg)
2369 {
2370         struct comm_signal* com = (struct comm_signal*)malloc(
2371                 sizeof(struct comm_signal));
2372         if(!com) {
2373                 log_err("malloc failed");
2374                 return NULL;
2375         }
2376         com->base = base;
2377         com->callback = callback;
2378         com->cb_arg = cb_arg;
2379         com->ev_signal = NULL;
2380         return com;
2381 }
2382
2383 void 
2384 comm_signal_callback(int sig, short event, void* arg)
2385 {
2386         struct comm_signal* comsig = (struct comm_signal*)arg;
2387         if(!(event & UB_EV_SIGNAL))
2388                 return;
2389         ub_comm_base_now(comsig->base);
2390         fptr_ok(fptr_whitelist_comm_signal(comsig->callback));
2391         (*comsig->callback)(sig, comsig->cb_arg);
2392 }
2393
2394 int 
2395 comm_signal_bind(struct comm_signal* comsig, int sig)
2396 {
2397         struct internal_signal* entry = (struct internal_signal*)calloc(1, 
2398                 sizeof(struct internal_signal));
2399         if(!entry) {
2400                 log_err("malloc failed");
2401                 return 0;
2402         }
2403         log_assert(comsig);
2404         /* add signal event */
2405         entry->ev = ub_signal_new(comsig->base->eb->base, sig,
2406                 comm_signal_callback, comsig);
2407         if(entry->ev == NULL) {
2408                 log_err("Could not create signal event");
2409                 free(entry);
2410                 return 0;
2411         }
2412         if(ub_signal_add(entry->ev, NULL) != 0) {
2413                 log_err("Could not add signal handler");
2414                 ub_event_free(entry->ev);
2415                 free(entry);
2416                 return 0;
2417         }
2418         /* link into list */
2419         entry->next = comsig->ev_signal;
2420         comsig->ev_signal = entry;
2421         return 1;
2422 }
2423
2424 void 
2425 comm_signal_delete(struct comm_signal* comsig)
2426 {
2427         struct internal_signal* p, *np;
2428         if(!comsig)
2429                 return;
2430         p=comsig->ev_signal;
2431         while(p) {
2432                 np = p->next;
2433                 ub_signal_del(p->ev);
2434                 ub_event_free(p->ev);
2435                 free(p);
2436                 p = np;
2437         }
2438         free(comsig);
2439 }