OpenDNSSEC-signer  2.0.4
sock.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011 NLNet Labs. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
19  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
21  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
22  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
23  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  */
26 
32 #include "config.h"
33 #include "daemon/engine.h"
34 #include "log.h"
35 #include "signer/zone.h"
36 #include "wire/axfr.h"
37 #include "wire/netio.h"
38 #include "wire/sock.h"
39 #include "wire/xfrd.h"
40 
41 #include <errno.h>
42 #include <fcntl.h>
43 #include <ldns/ldns.h>
44 #include <unistd.h>
45 
46 #define SOCK_TCP_BACKLOG 5
47 
48 static const char* sock_str = "socket";
49 
50 
55 static ods_status
56 sock_fcntl_and_bind(sock_type* sock, const char* node, const char* port,
57  const char* stype, const char* fam)
58 {
59  ods_log_assert(sock);
60  ods_log_assert(port);
61  ods_log_assert(stype);
62  ods_log_assert(fam);
63  if (fcntl(sock->s, F_SETFL, O_NONBLOCK) == -1) {
64  ods_log_error("[%s] unable to set %s/%s socket '%s:%s' to "
65  "non-blocking: fcntl() failed (%s)", sock_str, stype, fam,
66  node?node:"localhost", port, strerror(errno));
67  return ODS_STATUS_SOCK_FCNTL_NONBLOCK;
68  }
69  ods_log_debug("[%s] bind %s/%s socket '%s:%s': %s", sock_str, stype, fam,
70  node?node:"localhost", port, strerror(errno));
71  if (bind(sock->s, (struct sockaddr *) sock->addr->ai_addr,
72  sock->addr->ai_addrlen) != 0) {
73  ods_log_error("[%s] unable to bind %s/%s socket '%s:%s': bind() "
74  "failed (%s)", sock_str, stype, fam, node?node:"localhost",
75  port, strerror(errno));
76  return ODS_STATUS_SOCK_BIND;
77  }
78  return ODS_STATUS_OK;
79 }
80 
81 
86 static ods_status
87 sock_v6only(sock_type* sock, const char* node, const char* port, int on,
88  const char* stype)
89 {
90  ods_log_assert(sock);
91  ods_log_assert(port);
92  ods_log_assert(stype);
93 #ifdef IPV6_V6ONLY
94 #if defined(IPPROTO_IPV6)
95  ods_log_debug("[%s] set %s/ipv6 socket '%s:%s' v6only", sock_str,
96  stype, node?node:"localhost", port);
97  if (setsockopt(sock->s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) {
98  ods_log_error("[%s] unable to set %s/ipv6 socket '%s:%s' to "
99  "ipv6-only: setsockopt() failed (%s)", sock_str, stype,
100  node?node:"localhost", port, strerror(errno));
101  return ODS_STATUS_SOCK_SETSOCKOPT_V6ONLY;
102  }
103 #endif
104 #endif /* IPV6_V6ONLY */
105  return ODS_STATUS_OK;
106 }
107 
108 
113 static void
114 sock_tcp_reuseaddr(sock_type* sock, const char* node, const char* port,
115  int on, const char* fam)
116 {
117  ods_log_assert(sock);
118  ods_log_assert(port);
119  ods_log_assert(fam);
120  if (setsockopt(sock->s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
121  ods_log_error("[%s] unable to set tcp/%s socket '%s:%s' to "
122  "reuse-addr: setsockopt() failed (%s)", sock_str, fam,
123  node?node:"localhost", port, strerror(errno));
124  }
125 }
126 
127 
132 static ods_status
133 sock_tcp_listen(sock_type* sock, const char* node, const char* port,
134  const char* fam)
135 {
136  ods_log_assert(sock);
137  ods_log_assert(port);
138  ods_log_assert(fam);
139  if (listen(sock->s, SOCK_TCP_BACKLOG) == -1) {
140  ods_log_error("[%s] unable to listen on tcp/%s socket '%s:%s': "
141  "listen() failed (%s)", sock_str, fam, node?node:"localhost",
142  port, strerror(errno));
143  return ODS_STATUS_SOCK_LISTEN;
144  }
145  return ODS_STATUS_OK;
146 }
147 
148 
153 static ods_status
154 sock_server_udp(sock_type* sock, const char* node, const char* port,
155  unsigned* ip6_support)
156 {
157  int on = 0;
158  ods_status status = ODS_STATUS_OK;
159  ods_log_assert(sock);
160  ods_log_assert(port);
161 #if defined(SO_REUSEADDR) || defined(IPV6_V6ONLY)
162  on = 1;
163 #endif
164  *ip6_support = 1;
165  /* socket */
166  ods_log_debug("[%s] create udp socket '%s:%s': %s", sock_str,
167  node?node:"localhost", port, strerror(errno));
168  if ((sock->s = socket(sock->addr->ai_family, SOCK_DGRAM, 0))== -1) {
169  ods_log_error("[%s] unable to create udp/ipv4 socket '%s:%s': "
170  "socket() failed (%s)", sock_str, node?node:"localhost", port,
171  strerror(errno));
172  if (sock->addr->ai_family == AF_INET6 && errno == EAFNOSUPPORT) {
173  *ip6_support = 0;
174  }
175  return ODS_STATUS_SOCK_SOCKET_UDP;
176  }
177  /* ipv4 */
178  if (sock->addr->ai_family == AF_INET) {
179  status = sock_fcntl_and_bind(sock, node, port, "udp", "ipv4");
180  }
181  /* ipv6 */
182  else if (sock->addr->ai_family == AF_INET6) {
183  status = sock_v6only(sock, node, port, on, "udp");
184  if (status != ODS_STATUS_OK) {
185  return status;
186  }
187  status = sock_fcntl_and_bind(sock, node, port, "udp", "ipv6");
188  }
189  return status;
190 }
191 
192 
197 static ods_status
198 sock_server_tcp(sock_type* sock, const char* node, const char* port,
199  unsigned* ip6_support)
200 {
201  int on = 0;
202  ods_status status = ODS_STATUS_OK;
203  ods_log_assert(sock);
204  ods_log_assert(port);
205 #if defined(SO_REUSEADDR) || defined(IPV6_V6ONLY)
206  on = 1;
207 #endif
208  *ip6_support = 1;
209  /* socket */
210  ods_log_debug("[%s] create tcp socket '%s:%s': %s", sock_str,
211  node?node:"localhost", port, strerror(errno));
212  if ((sock->s = socket(sock->addr->ai_family, SOCK_STREAM, 0))== -1) {
213  ods_log_error("[%s] unable to create tcp/ipv4 socket '%s:%s': "
214  "socket() failed (%s)", sock_str, node?node:"localhost", port,
215  strerror(errno));
216  if (sock->addr->ai_family == AF_INET6 && errno == EAFNOSUPPORT) {
217  *ip6_support = 0;
218  }
219  return ODS_STATUS_SOCK_SOCKET_TCP;
220  }
221  /* ipv4 */
222  if (sock->addr->ai_family == AF_INET) {
223  sock_tcp_reuseaddr(sock, node, port, on, "ipv4");
224  status = sock_fcntl_and_bind(sock, node, port, "tcp", "ipv4");
225  if (status == ODS_STATUS_OK) {
226  status = sock_tcp_listen(sock, node, port, "ipv4");
227  }
228  }
229  /* ipv6 */
230  else if (sock->addr->ai_family == AF_INET6) {
231  status = sock_v6only(sock, node, port, on, "tcp");
232  if (status != ODS_STATUS_OK) {
233  return status;
234  }
235  sock_tcp_reuseaddr(sock, node, port, on, "ipv6");
236  status = sock_fcntl_and_bind(sock, node, port, "tcp", "ipv6");
237  if (status == ODS_STATUS_OK) {
238  status = sock_tcp_listen(sock, node, port, "ipv6");
239  }
240  }
241  return status;
242 }
243 
244 
249 static ods_status
250 socket_listen(sock_type* sock, struct addrinfo hints, int socktype,
251  const char* node, const char* port, unsigned* ip6_support)
252 {
253  ods_status status = ODS_STATUS_OK;
254  int r = 0;
255  ods_log_assert(sock);
256  ods_log_assert(port);
257  *ip6_support = 1;
258  hints.ai_socktype = socktype;
259  /* getaddrinfo */
260  if ((r = getaddrinfo(node, port, &hints, &sock->addr)) != 0 ||
261  !sock->addr) {
262  ods_log_error("[%s] unable to parse address '%s:%s': getaddrinfo() "
263  "failed (%s %s)", sock_str, node?node:"localhost", port,
264  gai_strerror(r),
265 #ifdef EAI_SYSTEM
266  r==EAI_SYSTEM?(char*)strerror(errno):"");
267 #else
268  "");
269 #endif
270  if (hints.ai_family == AF_INET6 && r==EAFNOSUPPORT) {
271  *ip6_support = 0;
272  }
273  return ODS_STATUS_SOCK_GETADDRINFO;
274  }
275  /* socket */
276  if (socktype == SOCK_DGRAM) {
277  status = sock_server_udp(sock, node, port, ip6_support);
278  } else if (socktype == SOCK_STREAM) {
279  status = sock_server_tcp(sock, node, port, ip6_support);
280  }
281  ods_log_debug("[%s] socket listening to %s:%s", sock_str,
282  node?node:"localhost", port);
283  return status;
284 }
285 
286 
291 ods_status
293 {
294  ods_status status = ODS_STATUS_OK;
295  struct addrinfo hints[MAX_INTERFACES];
296  const char* node = NULL;
297  const char* port = NULL;
298  size_t i = 0;
299  unsigned ip6_support = 1;
300 
301  if (!sockets || !listener) {
302  return ODS_STATUS_ASSERT_ERR;
303  }
304  /* Initialize values */
305  for (i = 0; i < MAX_INTERFACES; i++) {
306  memset(&hints[i], 0, sizeof(hints[i]));
307  hints[i].ai_family = AF_UNSPEC;
308  hints[i].ai_flags = AI_PASSIVE;
309  sockets->udp[i].s = -1;
310  sockets->tcp[i].s = -1;
311  }
312  /* Walk interfaces */
313  for (i=0; i < listener->count; i++) {
314  node = NULL;
315  if (strlen(listener->interfaces[i].address) > 0) {
316  node = listener->interfaces[i].address;
317  }
318  port = DNS_PORT_STRING;
319  if (listener->interfaces[i].port) {
320  port = listener->interfaces[i].port;
321  }
322  if (node != NULL) {
323  hints[i].ai_flags |= AI_NUMERICHOST;
324  } else {
325  hints[i].ai_family = listener->interfaces[i].family;
326  }
327  /* udp */
328  status = socket_listen(&sockets->udp[i], hints[i], SOCK_DGRAM,
329  node, port, &ip6_support);
330  if (status != ODS_STATUS_OK) {
331  if (!ip6_support) {
332  ods_log_warning("[%s] fallback to udp/ipv4, no udp/ipv6: "
333  "not supported", sock_str);
334  status = ODS_STATUS_OK;
335  } else {
336  return status;
337  }
338  }
339  /* tcp */
340  status = socket_listen(&sockets->tcp[i], hints[i], SOCK_STREAM,
341  node, port, &ip6_support);
342  if (status != ODS_STATUS_OK) {
343  if (!ip6_support) {
344  ods_log_warning("[%s] fallback to udp/ipv4, no udp/ipv6: "
345  "not supported", sock_str);
346  status = ODS_STATUS_OK;
347  } else {
348  return status;
349  }
350  }
351 
352  }
353  /* All ok */
354  return ODS_STATUS_OK;
355 }
356 
357 
362 static void
363 send_udp(struct udp_data* data, query_type* q)
364 {
365  ssize_t nb;
366  ods_log_deeebug("[%s] sending %d bytes over udp", sock_str,
367  (int)buffer_remaining(q->buffer));
368  nb = sendto(data->socket->s, buffer_begin(q->buffer),
369  buffer_remaining(q->buffer), 0,
370  (struct sockaddr*) &q->addr, q->addrlen);
371  if (nb == -1) {
372  ods_log_error("[%s] unable to send data over udp: sendto() failed "
373  "(%s)", sock_str, strerror(errno));
374  ods_log_debug("[%s] len=%lu", sock_str, (unsigned long)buffer_remaining(q->buffer));
375  } else if ((size_t) nb != buffer_remaining(q->buffer)) {
376  ods_log_error("[%s] unable to send data over udp: only sent %d of %d "
377  "octets", sock_str, (int)nb,
378  (int)buffer_remaining(q->buffer));
379  }
380 }
381 
382 
387 void
388 sock_handle_udp(netio_type* ATTR_UNUSED(netio), netio_handler_type* handler,
389  netio_events_type event_types)
390 {
391  struct udp_data* data = (struct udp_data*) handler->user_data;
392  int received = 0;
393  query_type* q = data->query;
394  query_state qstate = QUERY_PROCESSED;
395 
396  if (!(event_types & NETIO_EVENT_READ)) {
397  return;
398  }
399  ods_log_debug("[%s] incoming udp message", sock_str);
401  received = recvfrom(handler->fd, buffer_begin(q->buffer),
402  buffer_remaining(q->buffer), 0, (struct sockaddr*) &q->addr,
403  &q->addrlen);
404  if (received < 1) {
405  if (errno != EAGAIN && errno != EINTR) {
406  ods_log_error("[%s] recvfrom() failed: %s", sock_str,
407  strerror(errno));
408  }
409  return;
410  }
411  buffer_skip(q->buffer, received);
412  buffer_flip(q->buffer);
413  qstate = query_process(q, data->engine);
414  if (qstate != QUERY_DISCARDED) {
415  ods_log_debug("[%s] query processed qstate=%d", sock_str, qstate);
416  query_add_optional(q, data->engine);
417  buffer_flip(q->buffer);
418  send_udp(data, q);
419  }
420 }
421 
422 
427 static void
428 cleanup_tcp_handler(netio_type* netio, netio_handler_type* handler)
429 {
430  struct tcp_data* data = (struct tcp_data*) handler->user_data;
431  netio_remove_handler(netio, handler);
432  close(handler->fd);
433  free(handler->timeout);
434  free(handler);
435  query_cleanup(data->query);
436  free(data);
437 }
438 
439 
444 void
446  netio_events_type event_types)
447 {
448  struct tcp_accept_data* accept_data = (struct tcp_accept_data*)
449  handler->user_data;
450  int s = 0;
451  struct tcp_data* tcp_data = NULL;
452  netio_handler_type* tcp_handler = NULL;
453  struct sockaddr_storage addr;
454  socklen_t addrlen = 0;
455  if (!(event_types & NETIO_EVENT_READ)) {
456  return;
457  }
458  ods_log_debug("[%s] handle incoming tcp connection", sock_str);
459  addrlen = sizeof(addr);
460  s = accept(handler->fd, (struct sockaddr *) &addr, &addrlen);
461  if (s == -1) {
462  if (errno != EINTR && errno != EWOULDBLOCK) {
463  ods_log_error("[%s] unable to handle incoming tcp connection: "
464  "accept() failed (%s)", sock_str, strerror(errno));
465  }
466  return;
467  }
468  if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) {
469  ods_log_error("[%s] unable to handle incoming tcp connection: "
470  "fcntl() failed: %s", sock_str, strerror(errno));
471  close(s);
472  return;
473  }
474  /* create tcp handler data */
475  CHECKALLOC(tcp_data = (struct tcp_data*) malloc(sizeof(struct tcp_data)));
477  if (!tcp_data->query) {
478  ods_log_error("[%s] unable to handle incoming tcp connection: "
479  "query_create() failed", sock_str);
480  free(tcp_data);
481  close(s);
482  return;
483  }
484  tcp_data->engine = accept_data->engine;
486  accept_data->tcp_accept_handler_count;
490  memcpy(&tcp_data->query->addr, &addr, addrlen);
491  tcp_data->query->addrlen = addrlen;
492  CHECKALLOC(tcp_handler = (netio_handler_type*) malloc(sizeof(netio_handler_type)));
493  tcp_handler->fd = s;
494  CHECKALLOC(tcp_handler->timeout = (struct timespec*) malloc(sizeof(struct timespec)));
495  if (!tcp_handler->timeout) {
496  ods_log_error("[%s] unable to handle incoming tcp connection: "
497  "allocator_alloc() timeout failed", sock_str);
498  free(tcp_handler);
500  free(tcp_data);
501  close(s);
502  return;
503  }
504  tcp_handler->timeout->tv_sec = XFRD_TCP_TIMEOUT;
505  tcp_handler->timeout->tv_nsec = 0L;
506  timespec_add(tcp_handler->timeout, netio_current_time(netio));
507  tcp_handler->user_data = tcp_data;
508  tcp_handler->event_types = NETIO_EVENT_READ | NETIO_EVENT_TIMEOUT;
509  tcp_handler->event_handler = sock_handle_tcp_read;
510  netio_add_handler(netio, tcp_handler);
511 }
512 
513 
518 void
520  netio_events_type event_types)
521 {
522  struct tcp_data* data = (struct tcp_data *) handler->user_data;
523  ssize_t received = 0;
525 
526  if (event_types & NETIO_EVENT_TIMEOUT) {
527  cleanup_tcp_handler(netio, handler);
528  return;
529  }
530  ods_log_assert(event_types & NETIO_EVENT_READ);
531  ods_log_debug("[%s] incoming tcp message", sock_str);
532  if (data->bytes_transmitted == 0) {
533  ods_log_debug("[%s] TCP_READ: reset query", sock_str);
535  }
536  /* check if we received the leading packet length bytes yet. */
537  if (data->bytes_transmitted < sizeof(uint16_t)) {
538  received = read(handler->fd,
539  (char *) &data->query->tcplen + data->bytes_transmitted,
540  sizeof(uint16_t) - data->bytes_transmitted);
541  if (received == -1) {
542  if (errno == EAGAIN || errno == EINTR) {
543  /* read would block, wait until more data is available. */
544  return;
545  } else {
546  ods_log_error("[%s] unable to handle incoming tcp query: "
547  "read() failed (%s)", sock_str, strerror(errno));
548  cleanup_tcp_handler(netio, handler);
549  return;
550  }
551  } else if (received == 0) {
552  cleanup_tcp_handler(netio, handler);
553  return;
554  }
555  data->bytes_transmitted += received;
556  ods_log_debug("[%s] TCP_READ: bytes transmitted %lu (received %lu)",
557  sock_str, (unsigned long)data->bytes_transmitted, (unsigned long)received);
558  if (data->bytes_transmitted < sizeof(uint16_t)) {
559  /* not done with the tcplen yet, wait for more. */
560  ods_log_debug("[%s] TCP_READ: bytes transmitted %lu, while "
561  "sizeof uint16_t %lu", sock_str, (unsigned long)data->bytes_transmitted,
562  (unsigned long)sizeof(uint16_t));
563  return;
564  }
565  ods_log_assert(data->bytes_transmitted == sizeof(uint16_t));
566  data->query->tcplen = ntohs(data->query->tcplen);
567  /* minimum query size is: 12 + 1 + 2 + 2:
568  * header size + root dname + qclass + qtype */
569  if (data->query->tcplen < 17) {
570  ods_log_warning("[%s] unable to handle incoming tcp query: "
571  "packet too small", sock_str);
572  cleanup_tcp_handler(netio, handler);
573  return;
574  }
575  if (data->query->tcplen > data->query->maxlen) {
576  ods_log_warning("[%s] unable to handle incoming tcp query: "
577  "insufficient tcp buffer", sock_str);
578  cleanup_tcp_handler(netio, handler);
579  return;
580  }
581  buffer_set_limit(data->query->buffer, data->query->tcplen);
582  }
583  ods_log_assert(buffer_remaining(data->query->buffer) > 0);
584  /* read the (remaining) query data. */
585  received = read(handler->fd, buffer_current(data->query->buffer),
586  buffer_remaining(data->query->buffer));
587  if (received == -1) {
588  if (errno == EAGAIN || errno == EINTR) {
589  /* read would block, wait until more data is available. */
590  return;
591  } else {
592  ods_log_error("[%s] unable to handle incoming tcp query: "
593  "read() failed (%s)", sock_str, strerror(errno));
594  cleanup_tcp_handler(netio, handler);
595  return;
596  }
597  } else if (received == 0) {
598  cleanup_tcp_handler(netio, handler);
599  return;
600  }
601  data->bytes_transmitted += received;
602  ods_log_debug("[%s] TCP_READ: bytes transmitted %lu (received %lu)",
603  sock_str, (unsigned long)data->bytes_transmitted, (unsigned long)received);
604 
605  buffer_skip(data->query->buffer, received);
606  if (buffer_remaining(data->query->buffer) > 0) {
607  /* not done with message yet, wait for more. */
608  ods_log_debug("[%s] TCP_READ: remaining %lu", sock_str,
609  (unsigned long)buffer_remaining(data->query->buffer));
610  return;
611  }
612  ods_log_assert(buffer_position(data->query->buffer) ==
613  data->query->tcplen);
614  /* we have a complete query, process it. */
615  buffer_flip(data->query->buffer);
616  qstate = query_process(data->query, data->engine);
617  if (qstate == QUERY_DISCARDED) {
618  cleanup_tcp_handler(netio, handler);
619  return;
620  }
621  ods_log_debug("[%s] query processed qstate=%d", sock_str, qstate);
622  data->qstate = qstate;
623  /* edns, tsig */
624  query_add_optional(data->query, data->engine);
625  /* switch to tcp write handler. */
626  buffer_flip(data->query->buffer);
627  data->query->tcplen = buffer_remaining(data->query->buffer);
628  ods_log_debug("[%s] TCP_READ: new tcplen %u", sock_str,
629  data->query->tcplen);
630  data->bytes_transmitted = 0;
631  handler->timeout->tv_sec = XFRD_TCP_TIMEOUT;
632  handler->timeout->tv_nsec = 0L;
633  timespec_add(handler->timeout, netio_current_time(netio));
636 }
637 
638 
643 void
645  netio_events_type event_types)
646 {
647  struct tcp_data* data = (struct tcp_data *) handler->user_data;
648  ssize_t sent = 0;
649  query_type* q = data->query;
650 
651  if (event_types & NETIO_EVENT_TIMEOUT) {
652  cleanup_tcp_handler(netio, handler);
653  return;
654  }
655  ods_log_assert(event_types & NETIO_EVENT_WRITE);
656 
657  if (data->bytes_transmitted < sizeof(q->tcplen)) {
658  uint16_t n_tcplen = htons(q->tcplen);
659  sent = write(handler->fd,
660  (const char*) &n_tcplen + data->bytes_transmitted,
661  sizeof(n_tcplen) - data->bytes_transmitted);
662  if (sent == -1) {
663  if (errno == EAGAIN || errno == EINTR) {
664  /* write would block, wait until socket becomes writeable. */
665  return;
666  } else {
667  ods_log_error("[%s] unable to handle outgoing tcp response: "
668  "write() failed (%s)", sock_str, strerror(errno));
669  cleanup_tcp_handler(netio, handler);
670  return;
671  }
672  } else if (sent == 0) {
673  cleanup_tcp_handler(netio, handler);
674  return;
675  }
676  data->bytes_transmitted += sent;
677  ods_log_debug("[%s] TCP_WRITE: bytes transmitted %lu (sent %ld)",
678  sock_str, (unsigned long)data->bytes_transmitted, (long)sent);
679  if (data->bytes_transmitted < sizeof(q->tcplen)) {
680  /* writing not complete, wait until socket becomes writable. */
681  ods_log_debug("[%s] TCP_WRITE: bytes transmitted %lu, while "
682  "sizeof tcplen %lu", sock_str, (unsigned long)data->bytes_transmitted,
683  (unsigned long)sizeof(q->tcplen));
684  return;
685  }
686  ods_log_assert(data->bytes_transmitted == sizeof(q->tcplen));
687  }
688  ods_log_assert(data->bytes_transmitted < q->tcplen + sizeof(q->tcplen));
689 
690  sent = write(handler->fd, buffer_current(q->buffer),
692  if (sent == -1) {
693  if (errno == EAGAIN || errno == EINTR) {
694  /* write would block, wait until socket becomes writeable. */
695  return;
696  } else {
697  ods_log_error("[%s] unable to handle outgoing tcp response: "
698  "write() failed (%s)", sock_str, strerror(errno));
699  cleanup_tcp_handler(netio, handler);
700  return;
701  }
702  } else if (sent == 0) {
703  cleanup_tcp_handler(netio, handler);
704  return;
705  }
706 
707  buffer_skip(q->buffer, sent);
708  data->bytes_transmitted += sent;
709  if (data->bytes_transmitted < q->tcplen + sizeof(q->tcplen)) {
710  /* still more data to write when socket becomes writable. */
711  ods_log_debug("[%s] TCP_WRITE: bytes transmitted %lu, while tcplen "
712  "%u and sizeof tcplen %lu", sock_str, (unsigned long) data->bytes_transmitted,
713  q->tcplen, (unsigned long)sizeof(q->tcplen));
714  return;
715  }
716 
717  ods_log_debug("[%s] TCP_WRITE: bytes transmitted %lu",
718  sock_str, (unsigned long)data->bytes_transmitted);
719  ods_log_debug("[%s] TCP_WRITE: tcplen %u", sock_str, q->tcplen);
720  ods_log_debug("[%s] TCP_WRITE: sizeof tcplen %lu", sock_str,
721  (unsigned long)sizeof(q->tcplen));
722  ods_log_assert(data->bytes_transmitted == q->tcplen + sizeof(q->tcplen));
723  if (data->qstate == QUERY_AXFR || data->qstate == QUERY_IXFR) {
724  /* continue processing AXFR and writing back results. */
725  buffer_clear(q->buffer);
726  if (data->qstate == QUERY_IXFR) {
727  data->qstate = ixfr(q, data->engine);
728  } else {
729  data->qstate = axfr(q, data->engine, 0);
730  }
731  if (data->qstate != QUERY_PROCESSED) {
732  /* edns, tsig */
733  query_add_optional(q, data->engine);
734  buffer_flip(q->buffer);
735  q->tcplen = buffer_remaining(q->buffer);
736  data->bytes_transmitted = 0;
737  handler->timeout->tv_sec = XFRD_TCP_TIMEOUT;
738  handler->timeout->tv_nsec = 0L;
739  timespec_add(handler->timeout, netio_current_time(netio));
740  return;
741  }
742  }
743  /* done sending, wait for the next request. */
744  data->bytes_transmitted = 0;
745  handler->timeout->tv_sec = XFRD_TCP_TIMEOUT;
746  handler->timeout->tv_nsec = 0L;
747  timespec_add(handler->timeout, netio_current_time(netio));
750 }
int s
Definition: sock.h:48
query_type * query_create(void)
Definition: query.c:48
size_t maxlen
Definition: query.h:64
uint16_t tcplen
Definition: query.h:72
#define DNS_PORT_STRING
Definition: listener.h:51
void query_cleanup(query_type *q)
Definition: query.c:1094
#define SOCK_TCP_BACKLOG
Definition: sock.c:46
#define UDP_MAX_MESSAGE_LEN
Definition: query.h:42
#define XFRD_TCP_TIMEOUT
Definition: xfrd.h:68
void sock_handle_tcp_write(netio_type *netio, netio_handler_type *handler, netio_events_type event_types)
Definition: sock.c:644
Definition: sock.h:86
void buffer_skip(buffer_type *buffer, ssize_t count)
Definition: buffer.c:150
void timespec_add(struct timespec *left, const struct timespec *right)
Definition: netio.c:137
void buffer_flip(buffer_type *buffer)
Definition: buffer.c:112
engine_type * engine
Definition: sock.h:87
void buffer_clear(buffer_type *buffer)
Definition: buffer.c:99
query_type * query
Definition: sock.h:68
#define MAX_INTERFACES
Definition: listener.h:53
enum netio_events_enum netio_events_type
Definition: netio.h:76
void sock_handle_udp(netio_type *ATTR_UNUSED(netio), netio_handler_type *handler, netio_events_type event_types)
Definition: sock.c:388
void query_reset(query_type *q, size_t maxlen, int is_tcp)
Definition: query.c:80
void sock_handle_tcp_accept(netio_type *netio, netio_handler_type *handler, netio_events_type event_types)
Definition: sock.c:445
sock_type udp[MAX_INTERFACES]
Definition: sock.h:58
struct sockaddr_storage addr
Definition: query.h:61
uint8_t * buffer_current(buffer_type *buffer)
Definition: buffer.c:438
void * user_data
Definition: netio.h:119
void netio_add_handler(netio_type *netio, netio_handler_type *handler)
Definition: netio.c:54
sock_type tcp[MAX_INTERFACES]
Definition: sock.h:57
void buffer_set_limit(buffer_type *buffer, size_t limit)
Definition: buffer.c:385
netio_handler_type * tcp_accept_handlers
Definition: sock.h:79
size_t count
Definition: listener.h:83
const struct timespec * netio_current_time(netio_type *netio)
Definition: netio.c:169
size_t tcp_accept_handler_count
Definition: sock.h:78
query_state qstate
Definition: sock.h:91
netio_event_handler_type event_handler
Definition: netio.h:131
query_state axfr(query_type *q, engine_type *engine, int fallback)
Definition: axfr.c:152
void sock_handle_tcp_read(netio_type *netio, netio_handler_type *handler, netio_events_type event_types)
Definition: sock.c:519
query_type * query
Definition: sock.h:88
engine_type * engine
Definition: sock.h:76
void query_add_optional(query_type *q, engine_type *engine)
Definition: query.c:958
ods_status sock_listen(socklist_type *sockets, listener_type *listener)
Definition: sock.c:292
enum query_enum query_state
Definition: query.h:52
buffer_type * buffer
Definition: query.h:73
sock_type * socket
Definition: sock.h:67
struct addrinfo * addr
Definition: sock.h:47
void netio_remove_handler(netio_type *netio, netio_handler_type *handler)
Definition: netio.c:77
char * address
Definition: listener.h:71
query_state query_process(query_type *q, engine_type *engine)
Definition: query.c:840
Definition: sock.h:65
engine_type * engine
Definition: sock.h:66
query_state ixfr(query_type *q, engine_type *engine)
Definition: axfr.c:389
socklen_t addrlen
Definition: query.h:62
netio_events_type event_types
Definition: netio.h:124
interface_type * interfaces
Definition: listener.h:82
netio_handler_type * tcp_accept_handlers
Definition: sock.h:90
size_t buffer_remaining(buffer_type *buffer)
Definition: buffer.c:463
size_t tcp_accept_handler_count
Definition: sock.h:89
size_t buffer_position(buffer_type *buffer)
Definition: buffer.c:125
#define TCP_MAX_MESSAGE_LEN
Definition: query.h:43
struct timespec * timeout
Definition: netio.h:115
uint8_t * buffer_begin(buffer_type *buffer)
Definition: buffer.c:426
size_t bytes_transmitted
Definition: sock.h:92