Thanks Harald Jenny
* bugfix #680: ldns fails to reject invalidly formatted
RFC 7553 URI RRs. Thanks Robert Edmonds
+ * bugfix #678: Use poll i.s.o. select to support > 1024 fds
+ Thanks William King
1.6.17 2014-01-10
* Fix ldns_dnssec_zone_new_frm_fp_l to allow the last parsed line of a
;;
esac
+AX_HAVE_POLL(
+ [AX_CONFIG_FEATURE_ENABLE(poll)],
+ [AX_CONFIG_FEATURE_DISABLE(poll)])
+AX_CONFIG_FEATURE(
+ [poll], [This platform supports poll(7)],
+ [HAVE_POLL], [This platform supports poll(7).])
+
# check for python
PYTHON_X_CFLAGS=""
ldns_with_pyldns=no
#ifndef HAVE_STRLCPY
size_t strlcpy(char *dst, const char *src, size_t siz);
#endif
+
+#ifdef USE_WINSOCK
+#define SOCK_INVALID INVALID_SOCKET
+#define close_socket(_s) if (_s > SOCK_INVALID) {closesocket(_s); _s = SOCK_INVALID;}
+#else
+#define SOCK_INVALID -1
+#define close_socket(_s) if (_s > SOCK_INVALID) {close(_s); _s = SOCK_INVALID;}
+#endif
+
#ifdef __cplusplus
}
#endif
--- /dev/null
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_config_feature.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_CONFIG_FEATURE(FEATURE-NAME, FEATURE-DESCRIPTION, DEFINE, DEFINE-DESCRIPTION, [ACTION-IF-ENABLED [, ACTION-IF-NOT-ENABLED]])
+#
+# DESCRIPTION
+#
+# AX_CONFIG_FEATURE is a simple wrapper for AC_ARG_ENABLE, it enables the
+# feature FEATURE-NAME and AC_DEFINEs the passed DEFINE, depending on the
+# user choice. DESCRIPTION will be used for AC_DEFINEs. ACTION-IF-ENABLED
+# and ACTION-IF-NOT-ENABLED are the actions that will be run. A feature is
+# enabled by default, in order to change this behaviour use the
+# AX_CONFIG_FEATURE_DEFAULT_ENABLED and AX_CONFIG_FEATURE_DEFAULT_DISABLED
+# macros.
+#
+# A simple example:
+#
+# AX_CONFIG_FEATURE_DEFAULT_ENABLED
+# AX_CONFIG_FEATURE(feature_xxxxx, [turns on/off XXXXX support],
+# HAVE_XXXXX, [Define if you want XXXXX support])
+#
+# ...
+#
+# AX_CONFIG_FEATURE_DEFAULT_DISABLED
+# AX_CONFIG_FEATURE(feature_yyyyy, [turns on/off YYYYY support],
+# HAVE_YYYYY, [Define if you want YYYYY support],
+# [enable_yyyyy="yes"], [enable_yyyyy="no"])
+# AM_CONDITIONAL(YYYYY, [test "$enable_yyyyy" = "yes"])
+#
+# AX_CONFIG_FEATURE_DEFAULT_ENABLED
+# AX_CONFIG_FEATURE(...)
+#
+# ...
+#
+# If you have lot of features and you want a verbose dumping of each user
+# selection use AX_CONFIG_FEATURE_VERBOSE. Use AX_CONFIG_FEATURE_SILENT in
+# order to remove a previously AX_CONFIG_FEATURE_VERBOSE. By default
+# features are silent.
+#
+# Use AX_CONFIG_FEATURE_ENABLE or AX_CONFIG_FEATURE_DISABLE in order to
+# enable or disable a specific feature.
+#
+# Another simple example:
+#
+# AS_IF([some_test_here],[AX_CONFIG_FEATURE_ENABLE(feature_xxxxx)],[])
+#
+# AX_CONFIG_FEATURE(feature_xxxxx, [turns on/off XXXXX support],
+# HAVE_XXXXX, [Define if you want XXXXX support])
+# AX_CONFIG_FEATURE(feature_yyyyy, [turns on/off YYYYY support],
+# HAVE_YYYYY, [Define if you want YYYYY support],
+# [enable_yyyyy="yes"], [enable_yyyyy="no"])
+#
+# ...
+#
+# NOTE: AX_CONFIG_FEATURE_ENABLE() must be placed first of the relative
+# AX_CONFIG_FEATURE() macro ...
+#
+# LICENSE
+#
+# Copyright (c) 2008 Francesco Salvestrini <salvestrini@users.sourceforge.net>
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 10
+
+AC_DEFUN([AX_CONFIG_FEATURE],[ dnl
+m4_pushdef([FEATURE], patsubst([$1], -, _))dnl
+
+AC_ARG_ENABLE([$1],AS_HELP_STRING([--enable-$1],[$2]),[
+case "${enableval}" in
+ yes)
+ ax_config_feature_[]FEATURE[]="yes"
+ ;;
+ no)
+ ax_config_feature_[]FEATURE[]="no"
+ ;;
+ *)
+ AC_MSG_ERROR([bad value ${enableval} for feature --$1])
+ ;;
+esac
+])
+
+AS_IF([test "$ax_config_feature_[]FEATURE[]" = yes],[ dnl
+ AC_DEFINE([$3])
+ $5
+ AS_IF([test "$ax_config_feature_verbose" = yes],[ dnl
+ AC_MSG_NOTICE([Feature $1 is enabled])
+ ])
+],[ dnl
+ $6
+ AS_IF([test "$ax_config_feature_verbose" = yes],[ dnl
+ AC_MSG_NOTICE([Feature $1 is disabled])
+ ])
+])
+
+AH_TEMPLATE([$3],[$4])
+
+m4_popdef([FEATURE])dnl
+])
+
+dnl Feature global
+AC_DEFUN([AX_CONFIG_FEATURE_VERBOSE],[ dnl
+ ax_config_feature_verbose=yes
+])
+
+dnl Feature global
+AC_DEFUN([AX_CONFIG_FEATURE_SILENT],[ dnl
+ ax_config_feature_verbose=no
+])
+
+dnl Feature specific
+AC_DEFUN([AX_CONFIG_FEATURE_DEFAULT_ENABLED], [
+ ax_config_feature_[]FEATURE[]_default=yes
+])
+
+dnl Feature specific
+AC_DEFUN([AX_CONFIG_FEATURE_DEFAULT_DISABLED], [
+ ax_config_feature_[]FEATURE[]_default=no
+])
+
+dnl Feature specific
+AC_DEFUN([AX_CONFIG_FEATURE_ENABLE],[ dnl
+ ax_config_feature_[]patsubst([$1], -, _)[]=yes
+])
+
+dnl Feature specific
+AC_DEFUN([AX_CONFIG_FEATURE_DISABLE],[ dnl
+ ax_config_feature_[]patsubst([$1], -, _)[]=no
+])
--- /dev/null
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_have_poll.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_HAVE_POLL([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+# AX_HAVE_PPOLL([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+#
+# DESCRIPTION
+#
+# This macro determines whether the system supports the poll I/O event
+# interface. A neat usage example would be:
+#
+# AX_HAVE_POLL(
+# [AX_CONFIG_FEATURE_ENABLE(poll)],
+# [AX_CONFIG_FEATURE_DISABLE(poll)])
+# AX_CONFIG_FEATURE(
+# [poll], [This platform supports poll(7)],
+# [HAVE_POLL], [This platform supports poll(7).])
+#
+# Some systems -- most notably Linux kernel 2.6.16 and later -- also have
+# the variant ppoll(). The availability of that function can be tested
+# with the second macro. Generally speaking, it is safe to assume that
+# AX_HAVE_POLL would succeed if AX_HAVE_PPOLL has, but not the other way
+# round.
+#
+# LICENSE
+#
+# Copyright (c) 2009 Peter Simons <simons@cryp.to>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 7
+
+AC_DEFUN([AX_HAVE_POLL], [dnl
+ AC_MSG_CHECKING([for poll(2)])
+ AC_CACHE_VAL([ax_cv_have_poll], [dnl
+ AC_LINK_IFELSE([dnl
+ AC_LANG_PROGRAM(
+ [#include <poll.h>],
+ [int rc; rc = poll((struct pollfd *)(0), 0, 0);])],
+ [ax_cv_have_poll=yes],
+ [ax_cv_have_poll=no])])
+ AS_IF([test "${ax_cv_have_poll}" = "yes"],
+ [AC_MSG_RESULT([yes])
+$1],[AC_MSG_RESULT([no])
+$2])
+])dnl
+
+AC_DEFUN([AX_HAVE_PPOLL], [dnl
+ AC_MSG_CHECKING([for ppoll(2)])
+ AC_CACHE_VAL([ax_cv_have_ppoll], [dnl
+ AC_LINK_IFELSE([dnl
+ AC_LANG_PROGRAM(
+ [dnl
+#include <poll.h>
+#include <signal.h>],
+ [dnl
+int rc;
+rc = poll((struct pollfd *)(0), 0, 0);
+rc = ppoll((struct pollfd *)(0), 0, (struct timespec const *)(0), (sigset_t const *)(0));])],
+ [ax_cv_have_ppoll=yes],
+ [ax_cv_have_ppoll=no])])
+ AS_IF([test "${ax_cv_have_ppoll}" = "yes"],
+ [AC_MSG_RESULT([yes])
+$1],[AC_MSG_RESULT([no])
+$2])
+])
#include <sys/time.h>
#include <errno.h>
#include <fcntl.h>
+#ifdef HAVE_POLL
+#include <poll.h>
+#endif
ldns_status
ldns_send(ldns_pkt **result_packet, ldns_resolver *r, const ldns_pkt *query_pkt)
ldns_sock_wait(int sockfd, struct timeval timeout, int write)
{
int ret;
+#ifndef HAVE_POLL
#ifndef S_SPLINT_S
fd_set fds;
FD_ZERO(&fds);
ret = select(sockfd+1, NULL, &fds, NULL, &timeout);
else
ret = select(sockfd+1, &fds, NULL, NULL, &timeout);
+#endif
+#else
+ struct pollfd pfds[2];
+
+ memset(&pfds[0], 0, sizeof(pfds[0]) * 2);
+
+ pfds[0].fd = sockfd;
+ pfds[0].events = POLLIN|POLLERR;
+
+ if (write) {
+ pfds[0].events |= POLLOUT;
+ }
+
+ ret = poll(pfds, 1, timeout.tv_sec * 1000 + timeout.tv_usec / 1000);
#endif
if(ret == 0)
/* timeout expired */
#ifndef S_SPLINT_S
if ((sockfd = socket((int)((struct sockaddr*)to)->sa_family, SOCK_STREAM,
- IPPROTO_TCP)) == -1) {
+ IPPROTO_TCP)) == SOCK_INVALID) {
return 0;
}
#endif
- if (from && bind(sockfd, (const struct sockaddr*)from, fromlen) == -1){
+ if (from && bind(sockfd, (const struct sockaddr*)from, fromlen) == SOCK_INVALID){
return 0;
}
/* perform nonblocking connect, to be able to wait with select() */
ldns_sock_nonblock(sockfd);
- if (connect(sockfd, (struct sockaddr*)to, tolen) == -1) {
+ if (connect(sockfd, (struct sockaddr*)to, tolen) == SOCK_INVALID) {
#ifndef USE_WINSOCK
#ifdef EINPROGRESS
if(errno != EINPROGRESS) {
#else
if(1) {
#endif
- close(sockfd);
+ close_socket(sockfd);
return 0;
}
#else /* USE_WINSOCK */
if(WSAGetLastError() != WSAEINPROGRESS &&
WSAGetLastError() != WSAEWOULDBLOCK) {
- closesocket(sockfd);
+ close_socket(sockfd);
return 0;
}
#endif
socklen_t len = (socklen_t)sizeof(error);
if(!ldns_sock_wait(sockfd, timeout, 1)) {
-#ifndef USE_WINSOCK
- close(sockfd);
-#else
- closesocket(sockfd);
-#endif
+ close_socket(sockfd);
return 0;
}
continue; /* try again */
#endif
else if(error != 0) {
- close(sockfd);
+ close_socket(sockfd);
/* error in errno for our user */
errno = error;
return 0;
else if(error == WSAEWOULDBLOCK)
continue;
else if(error != 0) {
- closesocket(sockfd);
+ close_socket(sockfd);
errno = error;
return 0;
}
}
if (ldns_tcp_send_query(qbin, sockfd, to, tolen) == 0) {
-#ifndef USE_WINSOCK
- close(sockfd);
-#else
- closesocket(sockfd);
-#endif
+ close_socket(sockfd);
return 0;
}
}
answer = ldns_tcp_read_wire_timeout(sockfd, answer_size, timeout);
-#ifndef USE_WINSOCK
- close(sockfd);
-#else
- closesocket(sockfd);
-#endif
+ close_socket(sockfd);
if (*answer_size == 0) {
/* oops */
}
if (ldns_udp_send_query(qbin, sockfd, to, tolen) == 0) {
-#ifndef USE_WINSOCK
- close(sockfd);
-#else
- closesocket(sockfd);
-#endif
+ close_socket(sockfd);
return 0;
}
return sockfd;
/* wait for an response*/
if(!ldns_sock_wait(sockfd, timeout, 0)) {
-#ifndef USE_WINSOCK
- close(sockfd);
-#else
- closesocket(sockfd);
-#endif
+ close_socket(sockfd);
return LDNS_STATUS_NETWORK_ERR;
}
ldns_sock_nonblock(sockfd);
answer = ldns_udp_read_wire(sockfd, answer_size, NULL, NULL);
-#ifndef USE_WINSOCK
- close(sockfd);
-#else
- closesocket(sockfd);
-#endif
+ close_socket(sockfd);
if (*answer_size == 0) {
/* oops */
* @hostname is used */
for (ns_i = 0;
ns_i < ldns_resolver_nameserver_count(resolver) &&
- resolver->_socket == 0;
+ resolver->_socket == SOCK_INVALID;
ns_i++) {
if (ns != NULL) {
LDNS_FREE(ns);
ldns_resolver_timeout(resolver));
}
- if (resolver->_socket == 0) {
+ if (resolver->_socket == SOCK_INVALID) {
ldns_pkt_free(query);
LDNS_FREE(ns);
return LDNS_STATUS_NETWORK_ERR;
if (status != LDNS_STATUS_OK) {
/* to prevent problems on subsequent calls to
* ldns_axfr_start we have to close the socket here! */
-#ifndef USE_WINSOCK
- close(resolver->_socket);
-#else
- closesocket(resolver->_socket);
-#endif
+ close_socket(resolver->_socket);
resolver->_socket = 0;
ldns_pkt_free(query);
if(!query_wire) {
ldns_pkt_free(query);
LDNS_FREE(ns);
-#ifndef USE_WINSOCK
- close(resolver->_socket);
-#else
- closesocket(resolver->_socket);
-#endif
- resolver->_socket = 0;
+
+ close_socket(resolver->_socket);
return LDNS_STATUS_MEM_ERR;
}
/* to prevent problems on subsequent calls to ldns_axfr_start
* we have to close the socket here! */
-#ifndef USE_WINSOCK
- close(resolver->_socket);
-#else
- closesocket(resolver->_socket);
-#endif
+ close_socket(resolver->_socket);
resolver->_socket = 0;
return status;
/* to prevent problems on subsequent calls to ldns_axfr_start
* we have to close the socket here! */
-#ifndef USE_WINSOCK
- close(resolver->_socket);
-#else
- closesocket(resolver->_socket);
-#endif
- resolver->_socket = 0;
+
+ close_socket(resolver->_socket);
return LDNS_STATUS_NETWORK_ERR;
}
r->_timeout.tv_sec = LDNS_DEFAULT_TIMEOUT_SEC;
r->_timeout.tv_usec = LDNS_DEFAULT_TIMEOUT_USEC;
- /* TODO: fd=0 is actually a valid socket (stdin),
- replace with -1 */
- r->_socket = 0;
+ r->_socket = -1;
r->_axfr_soa_count = 0;
r->_axfr_i = 0;
r->_cur_axfr_pkt = NULL;
size_t i;
if (res) {
+ close_socket(res->_socket);
+
if (res->_searchlist) {
for (i = 0; i < ldns_resolver_searchlist_count(res); i++) {
ldns_rdf_deep_free(res->_searchlist[i]);
ldns_status status;
/* check if start() has been called */
- if (!resolver || resolver->_socket == 0) {
+ if (!resolver || resolver->_socket == -1) {
return NULL;
}
if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SOA) {
resolver->_axfr_soa_count++;
if (resolver->_axfr_soa_count >= 2) {
-#ifndef USE_WINSOCK
- close(resolver->_socket);
-#else
- closesocket(resolver->_socket);
-#endif
- resolver->_socket = 0;
+
+ close_socket(resolver->_socket);
+
ldns_pkt_free(resolver->_cur_axfr_pkt);
resolver->_cur_axfr_pkt = NULL;
}
/* we must now also close the socket, otherwise subsequent uses of the
same resolver structure will fail because the link is still open or
in an undefined state */
-#ifndef USE_WINSOCK
- close(resolver->_socket);
-#else
- closesocket(resolver->_socket);
-#endif
- resolver->_socket = 0;
+
+ close_socket(resolver->_socket);
return NULL;
} else if (ldns_pkt_get_rcode(resolver->_cur_axfr_pkt) != 0) {
/* we must now also close the socket, otherwise subsequent uses of the
same resolver structure will fail because the link is still open or
in an undefined state */
-#ifndef USE_WINSOCK
- close(resolver->_socket);
-#else
- closesocket(resolver->_socket);
-#endif
- resolver->_socket = 0;
+
+ close_socket(resolver->_socket);
return NULL;
} else {