OpenDNSSEC-signer  1.4.7
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 "shared/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));
68  }
69  ods_log_debug("[%s] bind %s/%s socket '%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));
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  return;
126 }
127 
128 
133 static ods_status
134 sock_tcp_listen(sock_type* sock, const char* node, const char* port,
135  const char* fam)
136 {
137  ods_log_assert(sock);
138  ods_log_assert(port);
139  ods_log_assert(fam);
140  if (listen(sock->s, SOCK_TCP_BACKLOG) == -1) {
141  ods_log_error("[%s] unable to listen on tcp/%s socket '%s:%s': "
142  "listen() failed (%s)", sock_str, fam, node?node:"localhost",
143  port, strerror(errno));
144  return ODS_STATUS_SOCK_LISTEN;
145  }
146  return ODS_STATUS_OK;
147 }
148 
149 
154 static ods_status
155 sock_server_udp(sock_type* sock, const char* node, const char* port,
156  unsigned* ip6_support)
157 {
158  int on = 0;
159  ods_status status = ODS_STATUS_OK;
160  ods_log_assert(sock);
161  ods_log_assert(port);
162 #if defined(SO_REUSEADDR) || defined(IPV6_V6ONLY)
163  on = 1;
164 #endif
165  *ip6_support = 1;
166  /* socket */
167  ods_log_debug("[%s] create udp socket '%s:%s'", sock_str,
168  node?node:"localhost", port, strerror(errno));
169  if ((sock->s = socket(sock->addr->ai_family, SOCK_DGRAM, 0))== -1) {
170  ods_log_error("[%s] unable to create udp/ipv4 socket '%s:%s': "
171  "socket() failed (%s)", sock_str, node?node:"localhost", port,
172  strerror(errno));
173  if (sock->addr->ai_family == AF_INET6 && errno == EAFNOSUPPORT) {
174  *ip6_support = 0;
175  }
177  }
178  /* ipv4 */
179  if (sock->addr->ai_family == AF_INET) {
180  status = sock_fcntl_and_bind(sock, node, port, "udp", "ipv4");
181  }
182  /* ipv6 */
183  else if (sock->addr->ai_family == AF_INET6) {
184  status = sock_v6only(sock, node, port, on, "udp");
185  if (status != ODS_STATUS_OK) {
186  return status;
187  }
188  status = sock_fcntl_and_bind(sock, node, port, "udp", "ipv6");
189  }
190  return status;
191 }
192 
193 
198 static ods_status
199 sock_server_tcp(sock_type* sock, const char* node, const char* port,
200  unsigned* ip6_support)
201 {
202  int on = 0;
203  ods_status status = ODS_STATUS_OK;
204  ods_log_assert(sock);
205  ods_log_assert(port);
206 #if defined(SO_REUSEADDR) || defined(IPV6_V6ONLY)
207  on = 1;
208 #endif
209  *ip6_support = 1;
210  /* socket */
211  ods_log_debug("[%s] create tcp socket '%s:%s'", sock_str,
212  node?node:"localhost", port, strerror(errno));
213  if ((sock->s = socket(sock->addr->ai_family, SOCK_STREAM, 0))== -1) {
214  ods_log_error("[%s] unable to create tcp/ipv4 socket '%s:%s': "
215  "socket() failed (%s)", sock_str, node?node:"localhost", port,
216  strerror(errno));
217  if (sock->addr->ai_family == AF_INET6 && errno == EAFNOSUPPORT) {
218  *ip6_support = 0;
219  }
221  }
222  /* ipv4 */
223  if (sock->addr->ai_family == AF_INET) {
224  sock_tcp_reuseaddr(sock, node, port, on, "ipv4");
225  status = sock_fcntl_and_bind(sock, node, port, "tcp", "ipv4");
226  if (status == ODS_STATUS_OK) {
227  status = sock_tcp_listen(sock, node, port, "ipv4");
228  }
229  }
230  /* ipv6 */
231  else if (sock->addr->ai_family == AF_INET6) {
232  status = sock_v6only(sock, node, port, on, "tcp");
233  if (status != ODS_STATUS_OK) {
234  return status;
235  }
236  sock_tcp_reuseaddr(sock, node, port, on, "ipv6");
237  status = sock_fcntl_and_bind(sock, node, port, "tcp", "ipv6");
238  if (status == ODS_STATUS_OK) {
239  status = sock_tcp_listen(sock, node, port, "ipv6");
240  }
241  }
242  return status;
243 }
244 
245 
250 static ods_status
251 socket_listen(sock_type* sock, struct addrinfo hints, int socktype,
252  const char* node, const char* port, unsigned* ip6_support)
253 {
254  ods_status status = ODS_STATUS_OK;
255  int r = 0;
256  ods_log_assert(sock);
257  ods_log_assert(port);
258  *ip6_support = 1;
259  hints.ai_socktype = socktype;
260  /* getaddrinfo */
261  if ((r = getaddrinfo(node, port, &hints, &sock->addr)) != 0 ||
262  !sock->addr) {
263  ods_log_error("[%s] unable to parse address '%s:%s': getaddrinfo() "
264  "failed (%s %s)", sock_str, node?node:"localhost", port,
265  gai_strerror(r),
266 #ifdef EAI_SYSTEM
267  r==EAI_SYSTEM?(char*)strerror(errno):"");
268 #else
269  "");
270 #endif
271  if (hints.ai_family == AF_INET6 && r==EAFNOSUPPORT) {
272  *ip6_support = 0;
273  }
275  }
276  /* socket */
277  if (socktype == SOCK_DGRAM) {
278  status = sock_server_udp(sock, node, port, ip6_support);
279  } else if (socktype == SOCK_STREAM) {
280  status = sock_server_tcp(sock, node, port, ip6_support);
281  }
282  ods_log_debug("[%s] socket listening to %s:%s", sock_str,
283  node?node:"localhost", port);
284  return status;
285 }
286 
287 
294 {
295  ods_status status = ODS_STATUS_OK;
296  struct addrinfo hints[MAX_INTERFACES];
297  const char* node = NULL;
298  const char* port = NULL;
299  size_t i = 0;
300  unsigned ip6_support = 1;
301 
302  if (!sockets || !listener) {
303  return ODS_STATUS_ASSERT_ERR;
304  }
305  /* Initialize values */
306  for (i = 0; i < MAX_INTERFACES; i++) {
307  memset(&hints[i], 0, sizeof(hints[i]));
308  hints[i].ai_family = AF_UNSPEC;
309  hints[i].ai_flags = AI_PASSIVE;
310  sockets->udp[i].s = -1;
311  sockets->tcp[i].s = -1;
312  }
313  /* Walk interfaces */
314  for (i=0; i < listener->count; i++) {
315  node = NULL;
316  if (strlen(listener->interfaces[i].address) > 0) {
317  node = listener->interfaces[i].address;
318  }
319  port = DNS_PORT_STRING;
320  if (listener->interfaces[i].port) {
321  port = listener->interfaces[i].port;
322  }
323  if (node != NULL) {
324  hints[i].ai_flags |= AI_NUMERICHOST;
325  } else {
326  hints[i].ai_family = listener->interfaces[i].family;
327  }
328  /* udp */
329  status = socket_listen(&sockets->udp[i], hints[i], SOCK_DGRAM,
330  node, port, &ip6_support);
331  if (status != ODS_STATUS_OK) {
332  if (!ip6_support) {
333  ods_log_warning("[%s] fallback to udp/ipv4, no udp/ipv6: "
334  "not supported", sock_str);
335  status = ODS_STATUS_OK;
336  } else {
337  return status;
338  }
339  }
340  /* tcp */
341  status = socket_listen(&sockets->tcp[i], hints[i], SOCK_STREAM,
342  node, port, &ip6_support);
343  if (status != ODS_STATUS_OK) {
344  if (!ip6_support) {
345  ods_log_warning("[%s] fallback to udp/ipv4, no udp/ipv6: "
346  "not supported", sock_str);
347  status = ODS_STATUS_OK;
348  } else {
349  return status;
350  }
351  }
352 
353  }
354  /* All ok */
355  return ODS_STATUS_OK;
356 }
357 
358 
363 static void
364 send_udp(struct udp_data* data, query_type* q)
365 {
366  ssize_t nb;
367  ods_log_deeebug("[%s] sending %d bytes over udp", sock_str,
368  (int)buffer_remaining(q->buffer));
369  nb = sendto(data->socket->s, buffer_begin(q->buffer),
370  buffer_remaining(q->buffer), 0,
371  (struct sockaddr*) &q->addr, q->addrlen);
372  if (nb == -1) {
373  ods_log_error("[%s] unable to send data over udp: sendto() failed "
374  "(%s)", sock_str, strerror(errno));
375  ods_log_debug("[%s] len=%u", sock_str, buffer_remaining(q->buffer));
376  } else if ((size_t) nb != buffer_remaining(q->buffer)) {
377  ods_log_error("[%s] unable to send data over udp: only sent %d of %d "
378  "octets", sock_str, (int)nb,
379  (int)buffer_remaining(q->buffer));
380  }
381  return;
382 }
383 
384 
389 void
390 sock_handle_udp(netio_type* ATTR_UNUSED(netio), netio_handler_type* handler,
391  netio_events_type event_types)
392 {
393  struct udp_data* data = (struct udp_data*) handler->user_data;
394  int received = 0;
395  query_type* q = data->query;
396  query_state qstate = QUERY_PROCESSED;
397 
398  if (!(event_types & NETIO_EVENT_READ)) {
399  return;
400  }
401  ods_log_debug("[%s] incoming udp message", sock_str);
403  received = recvfrom(handler->fd, buffer_begin(q->buffer),
404  buffer_remaining(q->buffer), 0, (struct sockaddr*) &q->addr,
405  &q->addrlen);
406  if (received < 1) {
407  if (errno != EAGAIN && errno != EINTR) {
408  ods_log_error("[%s] recvfrom() failed: %s", sock_str,
409  strerror(errno));
410  }
411  return;
412  }
413  buffer_skip(q->buffer, received);
414  buffer_flip(q->buffer);
415  qstate = query_process(q, data->engine);
416  if (qstate != QUERY_DISCARDED) {
417  ods_log_debug("[%s] query processed qstate=%d", sock_str, qstate);
418  query_add_optional(q, data->engine);
419  buffer_flip(q->buffer);
420  send_udp(data, q);
421  }
422  return;
423 }
424 
425 
430 static void
431 cleanup_tcp_handler(netio_type* netio, netio_handler_type* handler)
432 {
433  struct tcp_data* data = (struct tcp_data*) handler->user_data;
435  netio_remove_handler(netio, handler);
436  close(handler->fd);
437  allocator_deallocate(allocator, (void*) handler->timeout);
438  allocator_deallocate(allocator, (void*) handler);
439  query_cleanup(data->query);
440  allocator_deallocate(allocator, (void*) data);
442  return;
443 }
444 
445 
450 void
452  netio_events_type event_types)
453 {
454  allocator_type* allocator = NULL;
455  struct tcp_accept_data* accept_data = (struct tcp_accept_data*)
456  handler->user_data;
457  int s = 0;
458  struct tcp_data* tcp_data = NULL;
459  netio_handler_type* tcp_handler = NULL;
460  struct sockaddr_storage addr;
461  socklen_t addrlen = 0;
462  if (!(event_types & NETIO_EVENT_READ)) {
463  return;
464  }
465  ods_log_debug("[%s] handle incoming tcp connection", sock_str);
466  addrlen = sizeof(addr);
467  s = accept(handler->fd, (struct sockaddr *) &addr, &addrlen);
468  if (s == -1) {
469  if (errno != EINTR && errno != EWOULDBLOCK) {
470  ods_log_error("[%s] unable to handle incoming tcp connection: "
471  "accept() failed (%s)", sock_str, strerror(errno));
472  }
473  return;
474  }
475  if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) {
476  ods_log_error("[%s] unable to handle incoming tcp connection: "
477  "fcntl() failed: %s", sock_str, strerror(errno));
478  close(s);
479  return;
480  }
481  /* create tcp handler data */
482  allocator = allocator_create(malloc, free);
483  if (!allocator) {
484  ods_log_error("[%s] unable to handle incoming tcp connection: "
485  "allocator_create() failed", sock_str);
486  close(s);
487  return;
488  }
489  tcp_data = (struct tcp_data*) allocator_alloc(allocator,
490  sizeof(struct tcp_data));
491  if (!tcp_data) {
492  ods_log_error("[%s] unable to handle incoming tcp connection: "
493  "allocator_alloc() data failed", sock_str);
494  allocator_cleanup(allocator);
495  close(s);
496  return;
497  }
500  if (!tcp_data->query) {
501  ods_log_error("[%s] unable to handle incoming tcp connection: "
502  "query_create() failed", sock_str);
503  allocator_deallocate(allocator, (void*) tcp_data);
504  allocator_cleanup(allocator);
505  close(s);
506  return;
507  }
508  tcp_data->engine = accept_data->engine;
510  accept_data->tcp_accept_handler_count;
514  memcpy(&tcp_data->query->addr, &addr, addrlen);
515  tcp_data->query->addrlen = addrlen;
516  tcp_handler = (netio_handler_type*) allocator_alloc(allocator,
517  sizeof(netio_handler_type));
518  if (!tcp_handler) {
519  ods_log_error("[%s] unable to handle incoming tcp connection: "
520  "allocator_alloc() handler failed", sock_str);
522  allocator_deallocate(allocator, (void*) tcp_data);
523  allocator_cleanup(allocator);
524  close(s);
525  return;
526  }
527  tcp_handler->fd = s;
528  tcp_handler->timeout = (struct timespec*) allocator_alloc(allocator,
529  sizeof(struct timespec));
530  if (!tcp_handler->timeout) {
531  ods_log_error("[%s] unable to handle incoming tcp connection: "
532  "allocator_alloc() timeout failed", sock_str);
533  allocator_deallocate(allocator, (void*) tcp_handler);
535  allocator_deallocate(allocator, (void*) tcp_data);
536  allocator_cleanup(allocator);
537  close(s);
538  return;
539  }
540  tcp_handler->timeout->tv_sec = XFRD_TCP_TIMEOUT;
541  tcp_handler->timeout->tv_nsec = 0L;
542  timespec_add(tcp_handler->timeout, netio_current_time(netio));
543  tcp_handler->user_data = tcp_data;
544  tcp_handler->event_types = NETIO_EVENT_READ | NETIO_EVENT_TIMEOUT;
545  tcp_handler->event_handler = sock_handle_tcp_read;
546  netio_add_handler(netio, tcp_handler);
547  return;
548 }
549 
550 
555 void
557  netio_events_type event_types)
558 {
559  struct tcp_data* data = (struct tcp_data *) handler->user_data;
560  ssize_t received = 0;
562 
563  if (event_types & NETIO_EVENT_TIMEOUT) {
564  cleanup_tcp_handler(netio, handler);
565  return;
566  }
567  ods_log_assert(event_types & NETIO_EVENT_READ);
568  ods_log_debug("[%s] incoming tcp message", sock_str);
569  if (data->bytes_transmitted == 0) {
570  ods_log_debug("[%s] TCP_READ: reset query", sock_str);
572  }
573  /* check if we received the leading packet length bytes yet. */
574  if (data->bytes_transmitted < sizeof(uint16_t)) {
575  received = read(handler->fd,
576  (char *) &data->query->tcplen + data->bytes_transmitted,
577  sizeof(uint16_t) - data->bytes_transmitted);
578  if (received == -1) {
579  if (errno == EAGAIN || errno == EINTR) {
580  /* read would block, wait until more data is available. */
581  return;
582  } else {
583  ods_log_error("[%s] unable to handle incoming tcp query: "
584  "read() failed (%s)", sock_str, strerror(errno));
585  cleanup_tcp_handler(netio, handler);
586  return;
587  }
588  } else if (received == 0) {
589  cleanup_tcp_handler(netio, handler);
590  return;
591  }
592  data->bytes_transmitted += received;
593  ods_log_debug("[%s] TCP_READ: bytes transmitted %u (received %u)",
594  sock_str, data->bytes_transmitted, received);
595  if (data->bytes_transmitted < sizeof(uint16_t)) {
596  /* not done with the tcplen yet, wait for more. */
597  ods_log_debug("[%s] TCP_READ: bytes transmitted %u, while ",
598  "sizeof uint16_t %u", sock_str, data->bytes_transmitted,
599  sizeof(uint16_t));
600  return;
601  }
602  ods_log_assert(data->bytes_transmitted == sizeof(uint16_t));
603  data->query->tcplen = ntohs(data->query->tcplen);
604  /* minimum query size is: 12 + 1 + 2 + 2:
605  * header size + root dname + qclass + qtype */
606  if (data->query->tcplen < 17) {
607  ods_log_warning("[%s] unable to handle incoming tcp query: "
608  "packet too small", sock_str);
609  cleanup_tcp_handler(netio, handler);
610  return;
611  }
612  if (data->query->tcplen > data->query->maxlen) {
613  ods_log_warning("[%s] unable to handle incoming tcp query: "
614  "insufficient tcp buffer", sock_str);
615  cleanup_tcp_handler(netio, handler);
616  return;
617  }
618  buffer_set_limit(data->query->buffer, data->query->tcplen);
619  }
621  /* read the (remaining) query data. */
622  received = read(handler->fd, buffer_current(data->query->buffer),
623  buffer_remaining(data->query->buffer));
624  if (received == -1) {
625  if (errno == EAGAIN || errno == EINTR) {
626  /* read would block, wait until more data is available. */
627  return;
628  } else {
629  ods_log_error("[%s] unable to handle incoming tcp query: "
630  "read() failed (%s)", sock_str, strerror(errno));
631  cleanup_tcp_handler(netio, handler);
632  return;
633  }
634  } else if (received == 0) {
635  cleanup_tcp_handler(netio, handler);
636  return;
637  }
638  data->bytes_transmitted += received;
639  ods_log_debug("[%s] TCP_READ: bytes transmitted %u (received %u)",
640  sock_str, data->bytes_transmitted, received);
641 
642  buffer_skip(data->query->buffer, received);
643  if (buffer_remaining(data->query->buffer) > 0) {
644  /* not done with message yet, wait for more. */
645  ods_log_debug("[%s] TCP_READ: remaining %u", sock_str,
646  buffer_remaining(data->query->buffer));
647  return;
648  }
650  data->query->tcplen);
651  /* we have a complete query, process it. */
652  buffer_flip(data->query->buffer);
653  qstate = query_process(data->query, data->engine);
654  if (qstate == QUERY_DISCARDED) {
655  cleanup_tcp_handler(netio, handler);
656  return;
657  }
658  ods_log_debug("[%s] query processed qstate=%d", sock_str, qstate);
659  data->qstate = qstate;
660  /* edns, tsig */
661  query_add_optional(data->query, data->engine);
662  /* switch to tcp write handler. */
663  buffer_flip(data->query->buffer);
664  data->query->tcplen = buffer_remaining(data->query->buffer);
665  ods_log_debug("[%s] TCP_READ: new tcplen %u", sock_str,
666  data->query->tcplen);
667  data->bytes_transmitted = 0;
668  handler->timeout->tv_sec = XFRD_TCP_TIMEOUT;
669  handler->timeout->tv_nsec = 0L;
670  timespec_add(handler->timeout, netio_current_time(netio));
673  return;
674 }
675 
676 
681 void
683  netio_events_type event_types)
684 {
685  struct tcp_data* data = (struct tcp_data *) handler->user_data;
686  ssize_t sent = 0;
687  query_type* q = data->query;
688 
689  if (event_types & NETIO_EVENT_TIMEOUT) {
690  cleanup_tcp_handler(netio, handler);
691  return;
692  }
693  ods_log_assert(event_types & NETIO_EVENT_WRITE);
694 
695  if (data->bytes_transmitted < sizeof(q->tcplen)) {
696  uint16_t n_tcplen = htons(q->tcplen);
697  sent = write(handler->fd,
698  (const char*) &n_tcplen + data->bytes_transmitted,
699  sizeof(n_tcplen) - data->bytes_transmitted);
700  if (sent == -1) {
701  if (errno == EAGAIN || errno == EINTR) {
702  /* write would block, wait until socket becomes writeable. */
703  return;
704  } else {
705  ods_log_error("[%s] unable to handle outgoing tcp response: "
706  "write() failed (%s)", sock_str, strerror(errno));
707  cleanup_tcp_handler(netio, handler);
708  return;
709  }
710  } else if (sent == 0) {
711  cleanup_tcp_handler(netio, handler);
712  return;
713  }
714  data->bytes_transmitted += sent;
715  ods_log_debug("[%s] TCP_WRITE: bytes transmitted %u (sent %u)",
716  sock_str, data->bytes_transmitted, sent);
717  if (data->bytes_transmitted < sizeof(q->tcplen)) {
718  /* writing not complete, wait until socket becomes writable. */
719  ods_log_debug("[%s] TCP_WRITE: bytes transmitted %u, while ",
720  "sizeof tcplen %u", sock_str, data->bytes_transmitted,
721  sizeof(q->tcplen));
722  return;
723  }
724  ods_log_assert(data->bytes_transmitted == sizeof(q->tcplen));
725  }
726  ods_log_assert(data->bytes_transmitted < q->tcplen + sizeof(q->tcplen));
727 
728  sent = write(handler->fd, buffer_current(q->buffer),
730  if (sent == -1) {
731  if (errno == EAGAIN || errno == EINTR) {
732  /* write would block, wait until socket becomes writeable. */
733  return;
734  } else {
735  ods_log_error("[%s] unable to handle outgoing tcp response: "
736  "write() failed (%s)", sock_str, strerror(errno));
737  cleanup_tcp_handler(netio, handler);
738  return;
739  }
740  } else if (sent == 0) {
741  cleanup_tcp_handler(netio, handler);
742  return;
743  }
744 
745  buffer_skip(q->buffer, sent);
746  data->bytes_transmitted += sent;
747  if (data->bytes_transmitted < q->tcplen + sizeof(q->tcplen)) {
748  /* still more data to write when socket becomes writable. */
749  ods_log_debug("[%s] TCP_WRITE: bytes transmitted %u, while tcplen "
750  "%u and sizeof tcplen %u", sock_str, data->bytes_transmitted,
751  q->tcplen, sizeof(q->tcplen));
752  return;
753  }
754 
755  ods_log_debug("[%s] TCP_WRITE: bytes transmitted %u",
756  sock_str, data->bytes_transmitted);
757  ods_log_debug("[%s] TCP_WRITE: tcplen %u", sock_str, q->tcplen);
758  ods_log_debug("[%s] TCP_WRITE: sizeof tcplen %u", sock_str,
759  sizeof(q->tcplen));
760  ods_log_assert(data->bytes_transmitted == q->tcplen + sizeof(q->tcplen));
761  if (data->qstate == QUERY_AXFR || data->qstate == QUERY_IXFR) {
762  /* continue processing AXFR and writing back results. */
763  buffer_clear(q->buffer);
764  if (data->qstate == QUERY_IXFR) {
765  data->qstate = ixfr(q, data->engine);
766  } else {
767  data->qstate = axfr(q, data->engine, 0);
768  }
769  if (data->qstate != QUERY_PROCESSED) {
770  /* edns, tsig */
771  query_add_optional(q, data->engine);
772  buffer_flip(q->buffer);
773  q->tcplen = buffer_remaining(q->buffer);
774  data->bytes_transmitted = 0;
775  handler->timeout->tv_sec = XFRD_TCP_TIMEOUT;
776  handler->timeout->tv_nsec = 0L;
777  timespec_add(handler->timeout, netio_current_time(netio));
778  return;
779  }
780  }
781  /* done sending, wait for the next request. */
782  data->bytes_transmitted = 0;
783  handler->timeout->tv_sec = XFRD_TCP_TIMEOUT;
784  handler->timeout->tv_nsec = 0L;
785  timespec_add(handler->timeout, netio_current_time(netio));
788  return;
789 }
int s
Definition: sock.h:49
query_type * query_create(void)
Definition: query.c:48
size_t maxlen
Definition: query.h:66
uint16_t tcplen
Definition: query.h:74
#define DNS_PORT_STRING
Definition: listener.h:51
void query_cleanup(query_type *q)
Definition: query.c:1098
#define SOCK_TCP_BACKLOG
Definition: sock.c:46
void ods_log_debug(const char *format,...)
Definition: log.c:270
#define UDP_MAX_MESSAGE_LEN
Definition: query.h:42
#define XFRD_TCP_TIMEOUT
Definition: xfrd.h:50
void sock_handle_tcp_write(netio_type *netio, netio_handler_type *handler, netio_events_type event_types)
Definition: sock.c:682
void * allocator_alloc(allocator_type *allocator, size_t size)
Definition: allocator.c:66
Definition: sock.h:87
void buffer_skip(buffer_type *buffer, ssize_t count)
Definition: buffer.c:186
void timespec_add(struct timespec *left, const struct timespec *right)
Definition: netio.c:145
void buffer_flip(buffer_type *buffer)
Definition: buffer.c:133
void buffer_clear(buffer_type *buffer)
Definition: buffer.c:119
query_type * query
Definition: sock.h:69
#define MAX_INTERFACES
Definition: listener.h:53
enum ods_enum_status ods_status
Definition: status.h:90
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:390
void ods_log_error(const char *format,...)
Definition: log.c:334
void query_reset(query_type *q, size_t maxlen, int is_tcp)
Definition: query.c:90
allocator_type * allocator
Definition: sock.h:88
void sock_handle_tcp_accept(netio_type *netio, netio_handler_type *handler, netio_events_type event_types)
Definition: sock.c:451
sock_type udp[MAX_INTERFACES]
Definition: sock.h:59
struct sockaddr_storage addr
Definition: query.h:63
uint8_t * buffer_current(buffer_type *buffer)
Definition: buffer.c:489
void * user_data
Definition: netio.h:119
void netio_add_handler(netio_type *netio, netio_handler_type *handler)
Definition: netio.c:58
sock_type tcp[MAX_INTERFACES]
Definition: sock.h:58
void buffer_set_limit(buffer_type *buffer, size_t limit)
Definition: buffer.c:423
allocator_type * allocator_create(void *(*allocator)(size_t size), void(*deallocator)(void *))
Definition: allocator.c:47
netio_handler_type * tcp_accept_handlers
Definition: sock.h:80
size_t count
Definition: listener.h:84
const struct timespec * netio_current_time(netio_type *netio)
Definition: netio.c:179
size_t tcp_accept_handler_count
Definition: sock.h:79
query_state qstate
Definition: sock.h:93
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:556
query_state query_process(query_type *q, void *engine)
Definition: query.c:845
query_type * query
Definition: sock.h:90
ods_status sock_listen(socklist_type *sockets, listener_type *listener)
Definition: sock.c:293
enum query_enum query_state
Definition: query.h:52
buffer_type * buffer
Definition: query.h:75
sock_type * socket
Definition: sock.h:68
struct addrinfo * addr
Definition: sock.h:48
void netio_remove_handler(netio_type *netio, netio_handler_type *handler)
Definition: netio.c:84
char * address
Definition: listener.h:71
Definition: sock.h:66
query_state ixfr(query_type *q, engine_type *engine)
Definition: axfr.c:387
socklen_t addrlen
Definition: query.h:64
netio_events_type event_types
Definition: netio.h:124
void allocator_cleanup(allocator_type *allocator)
Definition: allocator.c:151
interface_type * interfaces
Definition: listener.h:83
netio_handler_type * tcp_accept_handlers
Definition: sock.h:92
size_t buffer_remaining(buffer_type *buffer)
Definition: buffer.c:514
void ods_log_deeebug(const char *format,...)
Definition: log.c:254
size_t tcp_accept_handler_count
Definition: sock.h:91
void * engine
Definition: sock.h:77
void allocator_deallocate(allocator_type *allocator, void *data)
Definition: allocator.c:135
size_t buffer_position(buffer_type *buffer)
Definition: buffer.c:160
#define TCP_MAX_MESSAGE_LEN
Definition: query.h:43
struct timespec * timeout
Definition: netio.h:115
#define ods_log_assert(x)
Definition: log.h:154
void * engine
Definition: sock.h:89
void ods_log_warning(const char *format,...)
Definition: log.c:318
uint8_t * buffer_begin(buffer_type *buffer)
Definition: buffer.c:465
size_t bytes_transmitted
Definition: sock.h:94
void * engine
Definition: sock.h:67
void query_add_optional(query_type *q, void *engine)
Definition: query.c:960