43 #include <ldns/ldns.h>
46 #define SOCK_TCP_BACKLOG 5
48 static const char* sock_str =
"socket";
56 sock_fcntl_and_bind(
sock_type* sock,
const char* node,
const char* port,
57 const char* stype,
const char* fam)
63 if (fcntl(sock->
s, F_SETFL, O_NONBLOCK) == -1) {
65 "non-blocking: fcntl() failed (%s)", sock_str, stype, fam,
66 node?node:
"localhost", port, strerror(errno));
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));
87 sock_v6only(
sock_type* sock,
const char* node,
const char* port,
int on,
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) {
99 "ipv6-only: setsockopt() failed (%s)", sock_str, stype,
100 node?node:
"localhost", port, strerror(errno));
114 sock_tcp_reuseaddr(
sock_type* sock,
const char* node,
const char* port,
115 int on,
const char* fam)
120 if (setsockopt(sock->
s, SOL_SOCKET, SO_REUSEADDR, &on,
sizeof(on)) < 0) {
122 "reuse-addr: setsockopt() failed (%s)", sock_str, fam,
123 node?node:
"localhost", port, strerror(errno));
134 sock_tcp_listen(
sock_type* sock,
const char* node,
const char* port,
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));
155 sock_server_udp(
sock_type* sock,
const char* node,
const char* port,
156 unsigned* ip6_support)
162 #if defined(SO_REUSEADDR) || defined(IPV6_V6ONLY)
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,
173 if (sock->
addr->ai_family == AF_INET6 && errno == EAFNOSUPPORT) {
179 if (sock->
addr->ai_family == AF_INET) {
180 status = sock_fcntl_and_bind(sock, node, port,
"udp",
"ipv4");
183 else if (sock->
addr->ai_family == AF_INET6) {
184 status = sock_v6only(sock, node, port, on,
"udp");
188 status = sock_fcntl_and_bind(sock, node, port,
"udp",
"ipv6");
199 sock_server_tcp(
sock_type* sock,
const char* node,
const char* port,
200 unsigned* ip6_support)
206 #if defined(SO_REUSEADDR) || defined(IPV6_V6ONLY)
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,
217 if (sock->
addr->ai_family == AF_INET6 && errno == EAFNOSUPPORT) {
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");
227 status = sock_tcp_listen(sock, node, port,
"ipv4");
231 else if (sock->
addr->ai_family == AF_INET6) {
232 status = sock_v6only(sock, node, port, on,
"tcp");
236 sock_tcp_reuseaddr(sock, node, port, on,
"ipv6");
237 status = sock_fcntl_and_bind(sock, node, port,
"tcp",
"ipv6");
239 status = sock_tcp_listen(sock, node, port,
"ipv6");
251 socket_listen(
sock_type* sock,
struct addrinfo hints,
int socktype,
252 const char* node,
const char* port,
unsigned* ip6_support)
259 hints.ai_socktype = socktype;
261 if ((r = getaddrinfo(node, port, &hints, &sock->
addr)) != 0 ||
263 ods_log_error(
"[%s] unable to parse address '%s:%s': getaddrinfo() "
264 "failed (%s %s)", sock_str, node?node:
"localhost", port,
267 r==EAI_SYSTEM?(
char*)strerror(errno):
"");
271 if (hints.ai_family == AF_INET6 && r==EAFNOSUPPORT) {
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);
283 node?node:
"localhost", port);
296 struct addrinfo hints[MAX_INTERFACES];
297 const char* node = NULL;
298 const char* port = NULL;
300 unsigned ip6_support = 1;
302 if (!sockets || !listener) {
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;
314 for (i=0; i < listener->
count; i++) {
324 hints[i].ai_flags |= AI_NUMERICHOST;
329 status = socket_listen(&sockets->
udp[i], hints[i], SOCK_DGRAM,
330 node, port, &ip6_support);
334 "not supported", sock_str);
341 status = socket_listen(&sockets->
tcp[i], hints[i], SOCK_STREAM,
342 node, port, &ip6_support);
346 "not supported", sock_str);
373 ods_log_error(
"[%s] unable to send data over udp: sendto() failed "
374 "(%s)", sock_str, strerror(errno));
377 ods_log_error(
"[%s] unable to send data over udp: only sent %d of %d "
378 "octets", sock_str, (
int)nb,
407 if (errno != EAGAIN && errno != EINTR) {
417 ods_log_debug(
"[%s] query processed qstate=%d", sock_str, qstate);
460 struct sockaddr_storage addr;
461 socklen_t addrlen = 0;
465 ods_log_debug(
"[%s] handle incoming tcp connection", sock_str);
466 addrlen =
sizeof(addr);
467 s = accept(handler->
fd, (
struct sockaddr *) &addr, &addrlen);
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));
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));
484 ods_log_error(
"[%s] unable to handle incoming tcp connection: "
485 "allocator_create() failed", sock_str);
492 ods_log_error(
"[%s] unable to handle incoming tcp connection: "
493 "allocator_alloc() data failed", sock_str);
501 ods_log_error(
"[%s] unable to handle incoming tcp connection: "
502 "query_create() failed", sock_str);
519 ods_log_error(
"[%s] unable to handle incoming tcp connection: "
520 "allocator_alloc() handler failed", sock_str);
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);
541 tcp_handler->timeout->tv_nsec = 0L;
560 ssize_t received = 0;
564 cleanup_tcp_handler(netio, handler);
575 received = read(handler->
fd,
578 if (received == -1) {
579 if (errno == EAGAIN || errno == EINTR) {
584 "read() failed (%s)", sock_str, strerror(errno));
585 cleanup_tcp_handler(netio, handler);
588 }
else if (received == 0) {
589 cleanup_tcp_handler(netio, handler);
593 ods_log_debug(
"[%s] TCP_READ: bytes transmitted %u (received %u)",
608 "packet too small", sock_str);
609 cleanup_tcp_handler(netio, handler);
614 "insufficient tcp buffer", sock_str);
615 cleanup_tcp_handler(netio, handler);
624 if (received == -1) {
625 if (errno == EAGAIN || errno == EINTR) {
630 "read() failed (%s)", sock_str, strerror(errno));
631 cleanup_tcp_handler(netio, handler);
634 }
else if (received == 0) {
635 cleanup_tcp_handler(netio, handler);
639 ods_log_debug(
"[%s] TCP_READ: bytes transmitted %u (received %u)",
655 cleanup_tcp_handler(netio, handler);
669 handler->
timeout->tv_nsec = 0L;
690 cleanup_tcp_handler(netio, handler);
696 uint16_t n_tcplen = htons(q->
tcplen);
697 sent = write(handler->
fd,
701 if (errno == EAGAIN || errno == EINTR) {
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);
710 }
else if (sent == 0) {
711 cleanup_tcp_handler(netio, handler);
715 ods_log_debug(
"[%s] TCP_WRITE: bytes transmitted %u (sent %u)",
719 ods_log_debug(
"[%s] TCP_WRITE: bytes transmitted %u, while ",
731 if (errno == EAGAIN || errno == EINTR) {
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);
740 }
else if (sent == 0) {
741 cleanup_tcp_handler(netio, handler);
749 ods_log_debug(
"[%s] TCP_WRITE: bytes transmitted %u, while tcplen "
776 handler->
timeout->tv_nsec = 0L;
784 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)