45 #include <ldns/ldns.h>
48 #define SOCK_TCP_BACKLOG 5
50 static const char* sock_str =
"socket";
58 sock_fcntl_and_bind(
sock_type* sock,
const char* node,
const char* port,
59 const char* stype,
const char* fam)
65 if (fcntl(sock->
s, F_SETFL, O_NONBLOCK) == -1) {
67 "non-blocking: fcntl() failed (%s)", sock_str, stype, fam,
68 node?node:
"localhost", port, strerror(errno));
71 ods_log_debug(
"[%s] bind %s/%s socket '%s:%s'", sock_str, stype, fam,
72 node?node:
"localhost", port, strerror(errno));
73 if (bind(sock->
s, (
struct sockaddr *) sock->
addr->ai_addr,
74 sock->
addr->ai_addrlen) != 0) {
75 ods_log_error(
"[%s] unable to bind %s/%s socket '%s:%s': bind() "
76 "failed (%s)", sock_str, stype, fam, node?node:
"localhost",
77 port, strerror(errno));
89 sock_v6only(
sock_type* sock,
const char* node,
const char* port,
int on,
96 #if defined(IPPROTO_IPV6)
97 ods_log_debug(
"[%s] set %s/ipv6 socket '%s:%s' v6only", sock_str,
98 stype, node?node:
"localhost", port);
99 if (setsockopt(sock->
s, IPPROTO_IPV6, IPV6_V6ONLY, &on,
sizeof(on)) < 0) {
100 ods_log_error(
"[%s] unable to set %s/ipv6 socket '%s:%s' to "
101 "ipv6-only: setsockopt() failed (%s)", sock_str, stype,
102 node?node:
"localhost", port, strerror(errno));
116 sock_tcp_reuseaddr(
sock_type* sock,
const char* node,
const char* port,
117 int on,
const char* fam)
122 if (setsockopt(sock->
s, SOL_SOCKET, SO_REUSEADDR, &on,
sizeof(on)) < 0) {
124 "reuse-addr: setsockopt() failed (%s)", sock_str, fam,
125 node?node:
"localhost", port, strerror(errno));
136 sock_tcp_listen(
sock_type* sock,
const char* node,
const char* port,
143 ods_log_error(
"[%s] unable to listen on tcp/%s socket '%s:%s': "
144 "listen() failed (%s)", sock_str, fam, node?node:
"localhost",
145 port, strerror(errno));
157 sock_server_udp(
sock_type* sock,
const char* node,
const char* port,
158 unsigned* ip6_support)
164 #if defined(SO_REUSEADDR) || defined(IPV6_V6ONLY)
170 node?node:
"localhost", port, strerror(errno));
171 if ((sock->
s = socket(sock->
addr->ai_family, SOCK_DGRAM, 0))== -1) {
172 ods_log_error(
"[%s] unable to create udp/ipv4 socket '%s:%s': "
173 "socket() failed (%s)", sock_str, node?node:
"localhost", port,
175 if (sock->
addr->ai_family == AF_INET6 && errno == EAFNOSUPPORT) {
181 if (sock->
addr->ai_family == AF_INET) {
182 status = sock_fcntl_and_bind(sock, node, port,
"udp",
"ipv4");
185 else if (sock->
addr->ai_family == AF_INET6) {
186 status = sock_v6only(sock, node, port, on,
"udp");
190 status = sock_fcntl_and_bind(sock, node, port,
"udp",
"ipv6");
201 sock_server_tcp(
sock_type* sock,
const char* node,
const char* port,
202 unsigned* ip6_support)
208 #if defined(SO_REUSEADDR) || defined(IPV6_V6ONLY)
214 node?node:
"localhost", port, strerror(errno));
215 if ((sock->
s = socket(sock->
addr->ai_family, SOCK_STREAM, 0))== -1) {
216 ods_log_error(
"[%s] unable to create tcp/ipv4 socket '%s:%s': "
217 "socket() failed (%s)", sock_str, node?node:
"localhost", port,
219 if (sock->
addr->ai_family == AF_INET6 && errno == EAFNOSUPPORT) {
225 if (sock->
addr->ai_family == AF_INET) {
226 sock_tcp_reuseaddr(sock, node, port, on,
"ipv4");
227 status = sock_fcntl_and_bind(sock, node, port,
"tcp",
"ipv4");
229 status = sock_tcp_listen(sock, node, port,
"ipv4");
233 else if (sock->
addr->ai_family == AF_INET6) {
234 status = sock_v6only(sock, node, port, on,
"tcp");
238 sock_tcp_reuseaddr(sock, node, port, on,
"ipv6");
239 status = sock_fcntl_and_bind(sock, node, port,
"tcp",
"ipv6");
241 status = sock_tcp_listen(sock, node, port,
"ipv6");
253 socket_listen(
sock_type* sock,
struct addrinfo hints,
int socktype,
254 const char* node,
const char* port,
unsigned* ip6_support)
261 hints.ai_socktype = socktype;
263 if ((r = getaddrinfo(node, port, &hints, &sock->
addr)) != 0 ||
265 ods_log_error(
"[%s] unable to parse address '%s:%s': getaddrinfo() "
266 "failed (%s %s)", sock_str, node?node:
"localhost", port,
269 r==EAI_SYSTEM?(
char*)strerror(errno):
"");
273 if (hints.ai_family == AF_INET6 && r==EAFNOSUPPORT) {
279 if (socktype == SOCK_DGRAM) {
280 status = sock_server_udp(sock, node, port, ip6_support);
281 }
else if (socktype == SOCK_STREAM) {
282 status = sock_server_tcp(sock, node, port, ip6_support);
285 node?node:
"localhost", port);
298 struct addrinfo hints[MAX_INTERFACES];
299 const char* node = NULL;
300 const char* port = NULL;
302 unsigned ip6_support = 1;
304 if (!sockets || !listener) {
309 memset(&hints[i], 0,
sizeof(hints[i]));
310 hints[i].ai_family = AF_UNSPEC;
311 hints[i].ai_flags = AI_PASSIVE;
312 sockets->
udp[i].
s = -1;
313 sockets->
tcp[i].
s = -1;
316 for (i=0; i < listener->
count; i++) {
326 hints[i].ai_flags |= AI_NUMERICHOST;
331 status = socket_listen(&sockets->
udp[i], hints[i], SOCK_DGRAM,
332 node, port, &ip6_support);
336 "not supported", sock_str);
343 status = socket_listen(&sockets->
tcp[i], hints[i], SOCK_STREAM,
344 node, port, &ip6_support);
348 "not supported", sock_str);
375 ods_log_error(
"[%s] unable to send data over udp: sendto() failed "
376 "(%s)", sock_str, strerror(errno));
379 ods_log_error(
"[%s] unable to send data over udp: only sent %d of %d "
380 "octets", sock_str, (
int)nb,
409 if (errno != EAGAIN && errno != EINTR) {
419 ods_log_debug(
"[%s] query processed qstate=%d", sock_str, qstate);
462 struct sockaddr_storage addr;
463 socklen_t addrlen = 0;
467 ods_log_debug(
"[%s] handle incoming tcp connection", sock_str);
468 addrlen =
sizeof(addr);
469 s = accept(handler->
fd, (
struct sockaddr *) &addr, &addrlen);
471 if (errno != EINTR && errno != EWOULDBLOCK) {
472 ods_log_error(
"[%s] unable to handle incoming tcp connection: "
473 "accept() failed (%s)", sock_str, strerror(errno));
477 if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) {
478 ods_log_error(
"[%s] unable to handle incoming tcp connection: "
479 "fcntl() failed: %s", sock_str, strerror(errno));
486 ods_log_error(
"[%s] unable to handle incoming tcp connection: "
487 "allocator_create() failed", sock_str);
494 ods_log_error(
"[%s] unable to handle incoming tcp connection: "
495 "allocator_alloc() data failed", sock_str);
503 ods_log_error(
"[%s] unable to handle incoming tcp connection: "
504 "query_create() failed", sock_str);
521 ods_log_error(
"[%s] unable to handle incoming tcp connection: "
522 "allocator_alloc() handler failed", sock_str);
531 sizeof(
struct timespec));
532 if (!tcp_handler->timeout) {
533 ods_log_error(
"[%s] unable to handle incoming tcp connection: "
534 "allocator_alloc() timeout failed", sock_str);
543 tcp_handler->timeout->tv_nsec = 0L;
562 ssize_t received = 0;
566 cleanup_tcp_handler(netio, handler);
577 received = read(handler->
fd,
580 if (received == -1) {
581 if (errno == EAGAIN || errno == EINTR) {
586 "read() failed (%s)", sock_str, strerror(errno));
587 cleanup_tcp_handler(netio, handler);
590 }
else if (received == 0) {
591 cleanup_tcp_handler(netio, handler);
595 ods_log_debug(
"[%s] TCP_READ: bytes transmitted %u (received %u)",
610 "packet too small", sock_str);
611 cleanup_tcp_handler(netio, handler);
616 "insufficient tcp buffer", sock_str);
617 cleanup_tcp_handler(netio, handler);
626 if (received == -1) {
627 if (errno == EAGAIN || errno == EINTR) {
632 "read() failed (%s)", sock_str, strerror(errno));
633 cleanup_tcp_handler(netio, handler);
636 }
else if (received == 0) {
637 cleanup_tcp_handler(netio, handler);
641 ods_log_debug(
"[%s] TCP_READ: bytes transmitted %u (received %u)",
657 cleanup_tcp_handler(netio, handler);
671 handler->
timeout->tv_nsec = 0L;
692 cleanup_tcp_handler(netio, handler);
698 uint16_t n_tcplen = htons(q->
tcplen);
699 sent = write(handler->
fd,
703 if (errno == EAGAIN || errno == EINTR) {
707 ods_log_error(
"[%s] unable to handle outgoing tcp response: "
708 "write() failed (%s)", sock_str, strerror(errno));
709 cleanup_tcp_handler(netio, handler);
712 }
else if (sent == 0) {
713 cleanup_tcp_handler(netio, handler);
717 ods_log_debug(
"[%s] TCP_WRITE: bytes transmitted %u (sent %u)",
721 ods_log_debug(
"[%s] TCP_WRITE: bytes transmitted %u, while ",
733 if (errno == EAGAIN || errno == EINTR) {
737 ods_log_error(
"[%s] unable to handle outgoing tcp response: "
738 "write() failed (%s)", sock_str, strerror(errno));
739 cleanup_tcp_handler(netio, handler);
742 }
else if (sent == 0) {
743 cleanup_tcp_handler(netio, handler);
751 ods_log_debug(
"[%s] TCP_WRITE: bytes transmitted %u, while tcplen "
778 handler->
timeout->tv_nsec = 0L;
786 handler->
timeout->tv_nsec = 0L;
query_type * query_create(void)
void query_cleanup(query_type *q)
void ods_log_debug(const char *format,...)
#define UDP_MAX_MESSAGE_LEN
void sock_handle_tcp_write(netio_type *netio, netio_handler_type *handler, netio_events_type event_types)
void * allocator_alloc(allocator_type *allocator, size_t size)
void buffer_skip(buffer_type *buffer, ssize_t count)
void timespec_add(struct timespec *left, const struct timespec *right)
void buffer_flip(buffer_type *buffer)
void buffer_clear(buffer_type *buffer)
enum ods_enum_status ods_status
enum netio_events_enum netio_events_type
void sock_handle_udp(netio_type *ATTR_UNUSED(netio), netio_handler_type *handler, netio_events_type event_types)
void ods_log_error(const char *format,...)
void query_reset(query_type *q, size_t maxlen, int is_tcp)
allocator_type * allocator
void sock_handle_tcp_accept(netio_type *netio, netio_handler_type *handler, netio_events_type event_types)
sock_type udp[MAX_INTERFACES]
struct sockaddr_storage addr
uint8_t * buffer_current(buffer_type *buffer)
void netio_add_handler(netio_type *netio, netio_handler_type *handler)
sock_type tcp[MAX_INTERFACES]
void buffer_set_limit(buffer_type *buffer, size_t limit)
allocator_type * allocator_create(void *(*allocator)(size_t size), void(*deallocator)(void *))
netio_handler_type * tcp_accept_handlers
const struct timespec * netio_current_time(netio_type *netio)
size_t tcp_accept_handler_count
netio_event_handler_type event_handler
query_state axfr(query_type *q, engine_type *engine, int fallback)
void sock_handle_tcp_read(netio_type *netio, netio_handler_type *handler, netio_events_type event_types)
query_state query_process(query_type *q, void *engine)
ods_status sock_listen(socklist_type *sockets, listener_type *listener)
enum query_enum query_state
void netio_remove_handler(netio_type *netio, netio_handler_type *handler)
query_state ixfr(query_type *q, engine_type *engine)
netio_events_type event_types
void allocator_cleanup(allocator_type *allocator)
interface_type * interfaces
netio_handler_type * tcp_accept_handlers
size_t buffer_remaining(buffer_type *buffer)
void ods_log_deeebug(const char *format,...)
size_t tcp_accept_handler_count
void allocator_deallocate(allocator_type *allocator, void *data)
size_t buffer_position(buffer_type *buffer)
#define TCP_MAX_MESSAGE_LEN
struct timespec * timeout
#define ods_log_assert(x)
void ods_log_warning(const char *format,...)
uint8_t * buffer_begin(buffer_type *buffer)
void query_add_optional(query_type *q, void *engine)