[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libmicrohttpd] 04/05: Implemented new option MHD_OPTION_SOCK_ADDR_LEN
From: |
gnunet |
Subject: |
[libmicrohttpd] 04/05: Implemented new option MHD_OPTION_SOCK_ADDR_LEN |
Date: |
Thu, 16 Nov 2023 07:13:16 +0100 |
This is an automated email from the git hooks/post-receive script.
karlson2k pushed a commit to branch master
in repository libmicrohttpd.
commit f5a72d27f36cdcd9958298e77aa85c2d7ee1d714
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
AuthorDate: Wed Nov 15 15:33:33 2023 +0300
Implemented new option MHD_OPTION_SOCK_ADDR_LEN
Improved detection of TCP/IP port in application-provided sockaddr.
Added automatic detection of used address facility (sockets type).
Improved support of platforms with sa_len, ss_len, sin_len and sin6_len.
---
configure.ac | 10 +-
src/include/microhttpd.h | 22 ++-
src/microhttpd/daemon.c | 427 ++++++++++++++++++++++++++++++------------
src/microhttpd/test_options.c | 176 ++++++++++++++++-
4 files changed, 507 insertions(+), 128 deletions(-)
diff --git a/configure.ac b/configure.ac
index e3cfba07..32f038bc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2552,8 +2552,8 @@ AC_INCLUDES_DEFAULT
]
)
-AC_CHECK_MEMBERS([struct sockaddr_in.sin_len, struct sockaddr_in6.sin6_len,
- struct sockaddr_storage.ss_len],
+AC_CHECK_MEMBERS([struct sockaddr.sa_len, struct sockaddr_storage.ss_len,
+ struct sockaddr_in.sin_len, struct sockaddr_in6.sin6_len],
[], [],
[
#ifdef HAVE_SYS_TYPES_H
@@ -2564,6 +2564,12 @@ AC_CHECK_MEMBERS([struct sockaddr_in.sin_len, struct
sockaddr_in6.sin6_len,
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
+#endif
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+#endif
+#ifdef HAVE_WS2TCPIP_H
+#include <ws2tcpip.h>
#endif
])
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h
index 6026e803..e1d12645 100644
--- a/src/include/microhttpd.h
+++ b/src/include/microhttpd.h
@@ -96,7 +96,7 @@ extern "C"
* they are parsed as decimal numbers.
* Example: 0x01093001 = 1.9.30-1.
*/
-#define MHD_VERSION 0x00097705
+#define MHD_VERSION 0x00097706
/* If generic headers don't work on your platform, include headers
which define 'va_list', 'size_t', 'ssize_t', 'intptr_t', 'off_t',
@@ -1704,6 +1704,8 @@ enum MHD_OPTION
* be followed by a `struct sockaddr *`. If #MHD_USE_IPv6 is
* specified, the `struct sockaddr*` should point to a `struct
* sockaddr_in6`, otherwise to a `struct sockaddr_in`.
+ * Silently ignored if followed by NULL pointer.
+ * @deprecated Use #MHD_OPTION_SOCK_ADDR_LEN
*/
MHD_OPTION_SOCK_ADDR = 6,
@@ -2142,7 +2144,23 @@ enum MHD_OPTION
* This option should be followed by a positive 'int' argument.
* @note Available since #MHD_VERSION 0x00097705
*/
- MHD_OPTION_APP_FD_SETSIZE = 39
+ MHD_OPTION_APP_FD_SETSIZE = 39,
+
+ /**
+ * Bind daemon to the supplied 'struct sockaddr'. This option should
+ * be followed by two parameters: 'socklen_t' the size of memory at the next
+ * pointer and the pointer 'const struct sockaddr *'.
+ * Note: the order of the arguments is not the same as for system bind() and
+ * other network functions.
+ * If #MHD_USE_IPv6 is specified, the 'struct sockaddr*' should
+ * point to a 'struct sockaddr_in6'.
+ * The socket domain (protocol family) is detected from provided
+ * 'struct sockaddr'. IP, IPv6 and UNIX sockets are supported (if supported
+ * by the platform). Other types may work occasionally.
+ * Silently ignored if followed by zero size and NULL pointer.
+ * @note Available since #MHD_VERSION 0x00097706
+ */
+ MHD_OPTION_SOCK_ADDR_LEN = 40
} _MHD_FIXED_ENUM;
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index 0b7902e7..b55b7feb 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -6181,7 +6181,22 @@ struct MHD_InterimParams_
* Application-provided listen socket.
*/
MHD_socket listen_fd;
-
+ /**
+ * Set to 'true' if @a server_addr is set by application.
+ */
+ bool pserver_addr_set;
+ /**
+ * Application-provided struct sockaddr to bind server to.
+ */
+ const struct sockaddr *pserver_addr;
+ /**
+ * Set to 'true' if @a server_addr_len is set by application.
+ */
+ bool server_addr_len_set;
+ /**
+ * Applicaiton-provided the size of the memory pointed by @a server_addr.
+ */
+ socklen_t server_addr_len;
};
/**
@@ -6208,7 +6223,6 @@ typedef void
*/
static enum MHD_Result
parse_options_va (struct MHD_Daemon *daemon,
- const struct sockaddr **servaddr,
struct MHD_InterimParams_ *params,
va_list ap);
@@ -6224,7 +6238,6 @@ parse_options_va (struct MHD_Daemon *daemon,
*/
static enum MHD_Result
parse_options (struct MHD_Daemon *daemon,
- const struct sockaddr **servaddr,
struct MHD_InterimParams_ *params,
...)
{
@@ -6233,7 +6246,6 @@ parse_options (struct MHD_Daemon *daemon,
va_start (ap, params);
ret = parse_options_va (daemon,
- servaddr,
params,
ap);
va_end (ap);
@@ -6507,15 +6519,13 @@ daemon_tls_priorities_init_append (struct MHD_Daemon
*daemon, const char *prio)
/**
* Parse a list of options given as varargs.
*
- * @param daemon the daemon to initialize
- * @param servaddr where to store the server's listen address
- * @param params the interim parameters to be assigned to
+ * @param[in,out] daemon the daemon to initialize
+ * @param[out] params the interim parameters to be assigned to
* @param ap the options
* @return #MHD_YES on success, #MHD_NO on error
*/
static enum MHD_Result
parse_options_va (struct MHD_Daemon *daemon,
- const struct sockaddr **servaddr,
struct MHD_InterimParams_ *params,
va_list ap)
{
@@ -6618,9 +6628,19 @@ parse_options_va (struct MHD_Daemon *daemon,
daemon->per_ip_connection_limit = va_arg (ap,
unsigned int);
break;
+ case MHD_OPTION_SOCK_ADDR_LEN:
+ params->server_addr_len = va_arg (ap,
+ socklen_t);
+ params->server_addr_len_set = true;
+ params->pserver_addr = va_arg (ap,
+ const struct sockaddr *);
+ params->pserver_addr_set = true;
+ break;
case MHD_OPTION_SOCK_ADDR:
- *servaddr = va_arg (ap,
- const struct sockaddr *);
+ params->server_addr_len_set = false;
+ params->pserver_addr = va_arg (ap,
+ const struct sockaddr *);
+ params->pserver_addr_set = true;
break;
case MHD_OPTION_URI_LOG_CALLBACK:
daemon->uri_log_callback = va_arg (ap,
@@ -7006,7 +7026,6 @@ parse_options_va (struct MHD_Daemon *daemon,
case MHD_OPTION_CONNECTION_MEMORY_INCREMENT:
case MHD_OPTION_THREAD_STACK_SIZE:
if (MHD_NO == parse_options (daemon,
- servaddr,
params,
opt,
(size_t) oa[i].value,
@@ -7025,7 +7044,6 @@ parse_options_va (struct MHD_Daemon *daemon,
case MHD_OPTION_SERVER_INSANITY:
case MHD_OPTION_DIGEST_AUTH_NONCE_BIND_TYPE:
if (MHD_NO == parse_options (daemon,
- servaddr,
params,
opt,
(unsigned int) oa[i].value,
@@ -7036,7 +7054,6 @@ parse_options_va (struct MHD_Daemon *daemon,
case MHD_OPTION_HTTPS_CRED_TYPE:
#ifdef HTTPS_SUPPORT
if (MHD_NO == parse_options (daemon,
- servaddr,
params,
opt,
(gnutls_credentials_type_t) oa[i].value,
@@ -7047,7 +7064,6 @@ parse_options_va (struct MHD_Daemon *daemon,
/* all options taking 'MHD_socket' */
case MHD_OPTION_LISTEN_SOCKET:
if (MHD_NO == parse_options (daemon,
- servaddr,
params,
opt,
(MHD_socket) oa[i].value,
@@ -7061,7 +7077,6 @@ parse_options_va (struct MHD_Daemon *daemon,
case MHD_OPTION_TLS_NO_ALPN:
case MHD_OPTION_APP_FD_SETSIZE:
if (MHD_NO == parse_options (daemon,
- servaddr,
params,
opt,
(int) oa[i].value,
@@ -7081,7 +7096,6 @@ parse_options_va (struct MHD_Daemon *daemon,
case MHD_OPTION_HTTPS_CERT_CALLBACK:
case MHD_OPTION_HTTPS_CERT_CALLBACK2:
if (MHD_NO == parse_options (daemon,
- servaddr,
params,
opt,
oa[i].ptr_value,
@@ -7096,7 +7110,6 @@ parse_options_va (struct MHD_Daemon *daemon,
case MHD_OPTION_UNESCAPE_CALLBACK:
case MHD_OPTION_GNUTLS_PSK_CRED_HANDLER:
if (MHD_NO == parse_options (daemon,
- servaddr,
params,
opt,
(void *) oa[i].value,
@@ -7108,7 +7121,6 @@ parse_options_va (struct MHD_Daemon *daemon,
case MHD_OPTION_DIGEST_AUTH_RANDOM:
case MHD_OPTION_DIGEST_AUTH_RANDOM_COPY:
if (MHD_NO == parse_options (daemon,
- servaddr,
params,
opt,
(size_t) oa[i].value,
@@ -7116,6 +7128,16 @@ parse_options_va (struct MHD_Daemon *daemon,
MHD_OPTION_END))
return MHD_NO;
break;
+ /* options taking socklen_t-number followed by pointer */
+ case MHD_OPTION_SOCK_ADDR_LEN:
+ if (MHD_NO == parse_options (daemon,
+ params,
+ opt,
+ (socklen_t) oa[i].value,
+ oa[i].ptr_value,
+ MHD_OPTION_END))
+ return MHD_NO;
+ break;
case MHD_OPTION_END: /* Not possible */
default:
return MHD_NO;
@@ -7342,13 +7364,19 @@ setup_epoll_to_listen (struct MHD_Daemon *daemon)
/**
* Apply interim parameters
- * @param d the daemon to use
- * @param params the interim parameters to process
+ * @param[in,out] d the daemon to use
+ * @param[out] ppsockaddr the pointer to store the pointer to 'struct sockaddr'
+ * if provided by application
+ * @param[out] psockaddr_len the size memory area pointed by 'struct sockaddr'
+ * if provided by application
+ * @param[in] params the interim parameters to process
* @return true in case of success,
* false in case of critical error (the daemon must be closed).
*/
static bool
process_interim_params (struct MHD_Daemon *d,
+ const struct sockaddr **ppsockaddr,
+ socklen_t *psockaddr_len,
struct MHD_InterimParams_ *params)
{
if (params->fdset_size_set)
@@ -7453,6 +7481,51 @@ process_interim_params (struct MHD_Daemon *d,
#endif /* MHD_USE_GETSOCKNAME */
}
}
+
+ mhd_assert (! params->server_addr_len_set || params->pserver_addr_set);
+ if (params->pserver_addr_set)
+ {
+ if (NULL == params->pserver_addr)
+ {
+ /* The size must be zero if set */
+ if (params->server_addr_len_set && (0 != params->server_addr_len))
+ return false;
+ /* Ignore parameter if it is NULL */
+ }
+ else if (MHD_INVALID_SOCKET != d->listen_fd)
+ {
+#ifdef HAVE_MESSAGES
+ MHD_DLOG (d,
+ _ ("MHD_OPTION_LISTEN_SOCKET cannot be used together with " \
+ "MHD_OPTION_SOCK_ADDR_LEN or MHD_OPTION_SOCK_ADDR.\n"));
+#endif /* HAVE_MESSAGES */
+ return false;
+ }
+ else if (0 != (d->options & MHD_USE_NO_LISTEN_SOCKET))
+ {
+#ifdef HAVE_MESSAGES
+ MHD_DLOG (d,
+ _ ("MHD_OPTION_SOCK_ADDR_LEN or MHD_OPTION_SOCK_ADDR " \
+ "specified for daemon with MHD_USE_NO_LISTEN_SOCKET " \
+ "flag set.\n"));
+#endif /* HAVE_MESSAGES */
+ (void) MHD_socket_close_ (params->listen_fd);
+ return false;
+ }
+ else
+ {
+ *ppsockaddr = params->pserver_addr;
+ if (params->server_addr_len_set)
+ {
+ /* The size must be non-zero if set */
+ if (0 == params->server_addr_len)
+ return false;
+ *psockaddr_len = params->server_addr_len;
+ }
+ else
+ *psockaddr_len = 0;
+ }
+ }
return true;
}
@@ -7490,11 +7563,7 @@ MHD_start_daemon_va (unsigned int flags,
const MHD_SCKT_OPT_BOOL_ on = 1;
struct MHD_Daemon *daemon;
MHD_socket listen_fd;
- struct sockaddr_in servaddr4;
-#ifdef HAVE_INET6
- struct sockaddr_in6 servaddr6;
-#endif
- const struct sockaddr *servaddr = NULL;
+ const struct sockaddr *pservaddr = NULL;
socklen_t addrlen;
#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
unsigned int i;
@@ -7666,9 +7735,12 @@ MHD_start_daemon_va (unsigned int flags,
interim_params->fdset_size = 0;
interim_params->listen_fd_set = false;
interim_params->listen_fd = MHD_INVALID_SOCKET;
+ interim_params->pserver_addr_set = false;
+ interim_params->pserver_addr = NULL;
+ interim_params->server_addr_len_set = false;
+ interim_params->server_addr_len = 0;
if (MHD_NO == parse_options_va (daemon,
- &servaddr,
interim_params,
ap))
{
@@ -7681,7 +7753,10 @@ MHD_start_daemon_va (unsigned int flags,
free (daemon);
return NULL;
}
- if (! process_interim_params (daemon, interim_params))
+ if (! process_interim_params (daemon,
+ &pservaddr,
+ &addrlen,
+ interim_params))
{
free (interim_params);
free (daemon);
@@ -7853,19 +7928,216 @@ MHD_start_daemon_va (unsigned int flags,
goto free_and_fail;
}
#endif
+
if ( (MHD_INVALID_SOCKET == daemon->listen_fd) &&
(0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
{
/* try to open listen socket */
- int domain;
-
+ struct sockaddr_in servaddr4;
#ifdef HAVE_INET6
- domain = (*pflags & MHD_USE_IPv6) ? PF_INET6 : PF_INET;
+ struct sockaddr_in6 servaddr6;
+ const bool use_ipv6 = (0 != (*pflags & MHD_USE_IPv6));
#else /* ! HAVE_INET6 */
- if (*pflags & MHD_USE_IPv6)
- goto free_and_fail;
- domain = PF_INET;
+ const bool use_ipv6 = false;
#endif /* ! HAVE_INET6 */
+ int domain;
+
+ if (NULL != pservaddr)
+ {
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+ const socklen_t sa_len = pservaddr->sa_len;
+#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
+#ifdef HAVE_INET6
+ if (use_ipv6 && (AF_INET6 != pservaddr->sa_family))
+ {
+#ifdef HAVE_MESSAGES
+ MHD_DLOG (daemon,
+ _ ("MHD_USE_IPv6 is enabled, but 'struct sockaddr *' " \
+ "specified for MHD_OPTION_SOCK_ADDR_LEN or " \
+ "MHD_OPTION_SOCK_ADDR is not IPv6 address.\n"));
+#endif /* HAVE_MESSAGES */
+ goto free_and_fail;
+ }
+#endif /* HAVE_INET6 */
+ switch (pservaddr->sa_family)
+ {
+ case AF_INET:
+ if (1)
+ {
+ struct sockaddr_in sa4;
+ uint16_t sa4_port;
+ if ((0 != addrlen)
+ && (((socklen_t) sizeof(sa4)) > addrlen))
+ {
+#ifdef HAVE_MESSAGES
+ MHD_DLOG (daemon,
+ _ ("The size specified for MHD_OPTION_SOCK_ADDR_LEN " \
+ "option is wrong.\n"));
+#endif /* HAVE_MESSAGES */
+ goto free_and_fail;
+ }
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+ if (0 != sa_len)
+ {
+ if (((socklen_t) sizeof(sa4)) > sa_len)
+ {
+#ifdef HAVE_MESSAGES
+ MHD_DLOG (daemon,
+ _ ("The value of 'struct sockaddr.sa_len' provided " \
+ "via MHD_OPTION_SOCK_ADDR_LEN option is not zero " \
+ "and does not match 'sa_family' value of the " \
+ "same structure.\n"));
+#endif /* HAVE_MESSAGES */
+ goto free_and_fail;
+ }
+ if ((0 == addrlen) || (sa_len < addrlen))
+ addrlen = sa_len; /* Use smaller value for safety */
+ }
+#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
+ if (0 == addrlen)
+ addrlen = sizeof(sa4);
+ memcpy (&sa4, pservaddr, sizeof(sa4)); /* Required due to stronger
alignment */
+ sa4_port = (uint16_t) ntohs (sa4.sin_port);
+#ifndef MHD_USE_GETSOCKNAME
+ if (0 != sa4_port)
+#endif /* ! MHD_USE_GETSOCKNAME */
+ daemon->port = sa4_port;
+ domain = PF_INET;
+ }
+ break;
+#ifdef HAVE_INET6
+ case AF_INET6:
+ if (1)
+ {
+ struct sockaddr_in6 sa6;
+ uint16_t sa6_port;
+ if ((0 != addrlen)
+ && (((socklen_t) sizeof(sa6)) > addrlen))
+ {
+#ifdef HAVE_MESSAGES
+ MHD_DLOG (daemon,
+ _ ("The size specified for MHD_OPTION_SOCK_ADDR_LEN " \
+ "option is wrong.\n"));
+#endif /* HAVE_MESSAGES */
+ goto free_and_fail;
+ }
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+ if (0 != sa_len)
+ {
+ if (((socklen_t) sizeof(sa6)) > sa_len)
+ {
+#ifdef HAVE_MESSAGES
+ MHD_DLOG (daemon,
+ _ ("The value of 'struct sockaddr.sa_len' provided " \
+ "via MHD_OPTION_SOCK_ADDR_LEN option is not zero " \
+ "and does not match 'sa_family' value of the " \
+ "same structure.\n"));
+#endif /* HAVE_MESSAGES */
+ goto free_and_fail;
+ }
+ if ((0 == addrlen) || (sa_len < addrlen))
+ addrlen = sa_len; /* Use smaller value for safety */
+ }
+#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
+ if (0 == addrlen)
+ addrlen = sizeof(sa6);
+ memcpy (&sa6, pservaddr, sizeof(sa6)); /* Required due to stronger
alignment */
+ sa6_port = (uint16_t) ntohs (sa6.sin6_port);
+#ifndef MHD_USE_GETSOCKNAME
+ if (0 != sa6_port)
+#endif /* ! MHD_USE_GETSOCKNAME */
+ daemon->port = sa6_port;
+ domain = PF_INET6;
+ *pflags |= ((enum MHD_FLAG) MHD_USE_IPv6);
+ }
+ break;
+#endif /* HAVE_INET6 */
+#ifdef AF_UNIX
+ case AF_UNIX:
+#endif /* AF_UNIX */
+ default:
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+ if (0 == addrlen)
+ addrlen = sa_len;
+ else if ((0 != sa_len) && (sa_len < addrlen))
+ addrlen = sa_len; /* Use smaller value for safety */
+#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
+ if (0 >= addrlen)
+ {
+#ifdef HAVE_MESSAGES
+ MHD_DLOG (daemon,
+ _ ("The 'sa_family' of the 'struct sockaddr' provided " \
+ "via MHD_OPTION_SOCK_ADDR option is not supported.\n"));
+#endif /* HAVE_MESSAGES */
+ goto free_and_fail;
+ }
+#ifdef AF_UNIX
+ if (AF_UNIX == pservaddr->sa_family)
+ {
+ daemon->port = 0; /* special value for UNIX domain sockets */
+ daemon->listen_is_unix = _MHD_YES;
+#ifdef PF_UNIX
+ domain = PF_UNIX;
+#else /* ! PF_UNIX */
+ domain = AF_UNIX;
+#endif /* ! PF_UNIX */
+ domain = PF_UNIX;
+ }
+ else /* combined with the next 'if' */
+#endif /* AF_UNIX */
+ if (1)
+ {
+ daemon->port = 0; /* ugh */
+ daemon->listen_is_unix = _MHD_UNKNOWN;
+ /* Assumed the same values for AF_* and PF_* */
+ domain = pservaddr->sa_family;
+ }
+ break;
+ }
+ }
+ else
+ {
+ if (! use_ipv6)
+ {
+ memset (&servaddr4,
+ 0,
+ sizeof (struct sockaddr_in));
+ servaddr4.sin_family = AF_INET;
+ servaddr4.sin_port = htons (port);
+ if (0 != INADDR_ANY)
+ servaddr4.sin_addr.s_addr = htonl (INADDR_ANY);
+#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
+ servaddr4.sin_len = sizeof (struct sockaddr_in);
+#endif
+ pservaddr = (struct sockaddr *) &servaddr4;
+ addrlen = (socklen_t) sizeof(servaddr4);
+ daemon->listen_is_unix = _MHD_NO;
+ domain = PF_INET;
+ }
+#ifdef HAVE_INET6
+ else
+ {
+#ifdef IN6ADDR_ANY_INIT
+ static const struct in6_addr static_in6any = IN6ADDR_ANY_INIT;
+#endif
+ memset (&servaddr6,
+ 0,
+ sizeof (struct sockaddr_in6));
+ servaddr6.sin6_family = AF_INET6;
+ servaddr6.sin6_port = htons (port);
+#ifdef IN6ADDR_ANY_INIT
+ servaddr6.sin6_addr = static_in6any;
+#endif
+#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
+ servaddr6.sin6_len = sizeof (struct sockaddr_in6);
+#endif
+ pservaddr = (struct sockaddr *) &servaddr6;
+ addrlen = (socklen_t) sizeof (servaddr6);
+ daemon->listen_is_unix = _MHD_NO;
+ domain = PF_INET6;
+ }
+#endif /* HAVE_INET6 */
+ }
listen_fd = MHD_socket_create_listen_ (domain);
if (MHD_INVALID_SOCKET == listen_fd)
@@ -7890,7 +8162,6 @@ MHD_start_daemon_va (unsigned int flags,
MHD_socket_close_chk_ (listen_fd);
goto free_and_fail;
}
- daemon->listen_is_unix = _MHD_NO;
/* Apply the socket options according to listening_address_reuse. */
if (0 == daemon->listening_address_reuse)
@@ -8003,87 +8274,8 @@ MHD_start_daemon_va (unsigned int flags,
}
/* check for user supplied sockaddr */
-#ifdef HAVE_INET6
- if (0 != (*pflags & MHD_USE_IPv6))
- addrlen = sizeof (struct sockaddr_in6);
- else
-#endif
- addrlen = sizeof (struct sockaddr_in);
- if (NULL == servaddr)
- {
-#ifdef HAVE_INET6
- if (0 != (*pflags & MHD_USE_IPv6))
- {
-#ifdef IN6ADDR_ANY_INIT
- static const struct in6_addr static_in6any = IN6ADDR_ANY_INIT;
-#endif
- memset (&servaddr6,
- 0,
- sizeof (struct sockaddr_in6));
- servaddr6.sin6_family = AF_INET6;
- servaddr6.sin6_port = htons (port);
-#ifdef IN6ADDR_ANY_INIT
- servaddr6.sin6_addr = static_in6any;
-#endif
-#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
- servaddr6.sin6_len = sizeof (struct sockaddr_in6);
-#endif
- servaddr = (struct sockaddr *) &servaddr6;
- }
- else
-#endif
- {
- memset (&servaddr4,
- 0,
- sizeof (struct sockaddr_in));
- servaddr4.sin_family = AF_INET;
- servaddr4.sin_port = htons (port);
- if (0 != INADDR_ANY)
- servaddr4.sin_addr.s_addr = htonl (INADDR_ANY);
-#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
- servaddr4.sin_len = sizeof (struct sockaddr_in);
-#endif
- servaddr = (struct sockaddr *) &servaddr4;
- }
- }
- else
- {
-#ifdef MHD_USE_GETSOCKNAME
- daemon->port = 0; /* Force use of autodetection */
-#else /* ! MHD_USE_GETSOCKNAME */
- switch (servaddr->sa_family)
- {
- case AF_INET:
- {
- struct sockaddr_in sa4;
- memcpy (&sa4, servaddr, sizeof(sa4)); /* Required due to stronger
alignment */
- daemon->port = ntohs (sa4.sin_port);
- break;
- }
-#ifdef HAVE_INET6
- case AF_INET6:
- {
- struct sockaddr_in6 sa6;
- memcpy (&sa6, servaddr, sizeof(sa6)); /* Required due to stronger
alignment */
- daemon->port = ntohs (sa6.sin6_port);
- mhd_assert (0 != (*pflags & MHD_USE_IPv6));
- break;
- }
-#endif /* HAVE_INET6 */
-#ifdef AF_UNIX
- case AF_UNIX:
- daemon->port = 0; /* special value for UNIX domain sockets */
- daemon->listen_is_unix = _MHD_YES;
- break;
-#endif
- default:
- daemon->port = 0; /* ugh */
- daemon->listen_is_unix = _MHD_UNKNOWN;
- break;
- }
-#endif /* ! MHD_USE_GETSOCKNAME */
- }
daemon->listen_fd = listen_fd;
+
if (0 != (*pflags & MHD_USE_IPv6))
{
#ifdef IPPROTO_IPV6
@@ -8108,7 +8300,7 @@ MHD_start_daemon_va (unsigned int flags,
#endif
#endif
}
- if (0 != bind (listen_fd, servaddr, addrlen))
+ if (0 != bind (listen_fd, pservaddr, addrlen))
{
#ifdef HAVE_MESSAGES
MHD_DLOG (daemon,
@@ -8157,7 +8349,8 @@ MHD_start_daemon_va (unsigned int flags,
#ifdef MHD_USE_GETSOCKNAME
if ( (0 == daemon->port) &&
- (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
+ (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) &&
+ (_MHD_YES != daemon->listen_is_unix) )
{ /* Get port number. */
struct sockaddr_storage bindaddr;
@@ -8166,7 +8359,7 @@ MHD_start_daemon_va (unsigned int flags,
sizeof (struct sockaddr_storage));
addrlen = sizeof (struct sockaddr_storage);
#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN
- bindaddr.ss_len = addrlen;
+ bindaddr.ss_len = (socklen_t) addrlen;
#endif
if (0 != getsockname (listen_fd,
(struct sockaddr *) &bindaddr,
diff --git a/src/microhttpd/test_options.c b/src/microhttpd/test_options.c
index deff9b92..7be7666d 100644
--- a/src/microhttpd/test_options.c
+++ b/src/microhttpd/test_options.c
@@ -70,50 +70,212 @@ test_wrap_loc (const char *test_name, unsigned int
(*test)(void))
/**
- * Test daemon initialization with the MHD_OPTION_SOCK_ADDR option
+ * Test daemon initialization with the MHD_OPTION_SOCK_ADDR or
+ * the MHD_OPTION_SOCK_ADDR_LEN options
*/
static unsigned int
test_ip_addr_option (void)
{
struct MHD_Daemon *d;
+ const union MHD_DaemonInfo *dinfo;
struct sockaddr_in daemon_ip_addr;
+ uint16_t port4;
#if defined(HAVE_INET6) && defined(USE_IPV6_TESTING)
struct sockaddr_in6 daemon_ip_addr6;
+ uint16_t port6;
#endif
+ unsigned int ret;
memset (&daemon_ip_addr, 0, sizeof (struct sockaddr_in));
daemon_ip_addr.sin_family = AF_INET;
daemon_ip_addr.sin_port = 0;
daemon_ip_addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+ port4 = 0;
#if defined(HAVE_INET6) && defined(USE_IPV6_TESTING)
memset (&daemon_ip_addr6, 0, sizeof (struct sockaddr_in6));
daemon_ip_addr6.sin6_family = AF_INET6;
daemon_ip_addr6.sin6_port = 0;
daemon_ip_addr6.sin6_addr = in6addr_loopback;
+ port6 = 0;
#endif
+ ret = 0;
+
+ d = MHD_start_daemon (MHD_USE_ERROR_LOG, 0,
+ NULL, NULL, &ahc_echo, NULL,
+ MHD_OPTION_SOCK_ADDR, &daemon_ip_addr,
+ MHD_OPTION_END);
+
+ if (d == 0)
+ return 1;
+
+ dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT);
+ if (NULL == dinfo)
+ ret |= 1 << 1;
+ else
+ port4 = dinfo->port;
+
+ MHD_stop_daemon (d);
+
+
+ daemon_ip_addr.sin_port = htons (port4);
+ d = MHD_start_daemon (MHD_USE_ERROR_LOG, 0,
+ NULL, NULL, &ahc_echo, NULL,
+ MHD_OPTION_SOCK_ADDR_LEN,
+ (socklen_t) sizeof(daemon_ip_addr), &daemon_ip_addr,
+ MHD_OPTION_END);
+
+ if (d == 0)
+ return 1;
+
+ dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT);
+ if (NULL == dinfo)
+ ret |= 1 << 1;
+ else if (port4 != dinfo->port)
+ ret |= 1 << 2;
+
+ MHD_stop_daemon (d);
+
+
+ d = MHD_start_daemon (MHD_USE_ERROR_LOG, 0,
+ NULL, NULL, &ahc_echo, NULL,
+ MHD_OPTION_SOCK_ADDR_LEN,
+ (socklen_t) (sizeof(daemon_ip_addr) / 2),
+ &daemon_ip_addr,
+ MHD_OPTION_END);
+
+ if (NULL != d)
+ {
+ MHD_stop_daemon (d);
+ return 1 << 3;
+ }
+
+#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
+
+ daemon_ip_addr.sin_len = (socklen_t) sizeof(daemon_ip_addr);
d = MHD_start_daemon (MHD_USE_ERROR_LOG, 0,
- NULL, NULL, &ahc_echo, NULL, MHD_OPTION_SOCK_ADDR,
- &daemon_ip_addr, MHD_OPTION_END);
+ NULL, NULL, &ahc_echo, NULL,
+ MHD_OPTION_SOCK_ADDR_LEN,
+ (socklen_t) sizeof(daemon_ip_addr), &daemon_ip_addr,
+ MHD_OPTION_END);
if (d == 0)
return 1;
+ dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT);
+ if (NULL == dinfo)
+ ret |= 1 << 1;
+ else if (port4 != dinfo->port)
+ ret |= 1 << 2;
+
MHD_stop_daemon (d);
+
+ daemon_ip_addr.sin_len = (socklen_t) (sizeof(daemon_ip_addr) / 2);
+ d = MHD_start_daemon (MHD_USE_ERROR_LOG, 0,
+ NULL, NULL, &ahc_echo, NULL,
+ MHD_OPTION_SOCK_ADDR_LEN,
+ (socklen_t) sizeof(daemon_ip_addr), &daemon_ip_addr,
+ MHD_OPTION_END);
+
+ if (NULL != d)
+ {
+ MHD_stop_daemon (d);
+ return 1 << 3;
+ }
+
+#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
+
+
#if defined(HAVE_INET6) && defined(USE_IPV6_TESTING)
d = MHD_start_daemon (MHD_USE_ERROR_LOG | MHD_USE_IPv6, 0,
- NULL, NULL, &ahc_echo, NULL, MHD_OPTION_SOCK_ADDR,
- &daemon_ip_addr6, MHD_OPTION_END);
+ NULL, NULL, &ahc_echo, NULL,
+ MHD_OPTION_SOCK_ADDR, &daemon_ip_addr6,
+ MHD_OPTION_END);
if (d == 0)
return 1;
+ dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT);
+ if (NULL == dinfo)
+ ret |= 1 << 1;
+ else
+ port6 = dinfo->port;
+
MHD_stop_daemon (d);
-#endif
- return 0;
+
+ daemon_ip_addr6.sin6_port = htons (port6);
+ d = MHD_start_daemon (MHD_USE_ERROR_LOG, 0,
+ NULL, NULL, &ahc_echo, NULL,
+ MHD_OPTION_SOCK_ADDR_LEN,
+ (socklen_t) sizeof(daemon_ip_addr6), &daemon_ip_addr6,
+ MHD_OPTION_END);
+
+ if (d == 0)
+ return 1;
+
+ dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT);
+ if (NULL == dinfo)
+ ret |= 1 << 1;
+ else if (port6 != dinfo->port)
+ ret |= 1 << 2;
+
+ MHD_stop_daemon (d);
+
+
+ d = MHD_start_daemon (MHD_USE_ERROR_LOG, 0,
+ NULL, NULL, &ahc_echo, NULL,
+ MHD_OPTION_SOCK_ADDR_LEN,
+ (socklen_t) (sizeof(daemon_ip_addr6) / 2),
+ &daemon_ip_addr6,
+ MHD_OPTION_END);
+
+ if (NULL != d)
+ {
+ MHD_stop_daemon (d);
+ return 1 << 3;
+ }
+
+#if defined(HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN)
+
+ daemon_ip_addr6.sin6_len = (socklen_t) sizeof(daemon_ip_addr6);
+ d = MHD_start_daemon (MHD_USE_ERROR_LOG, 0,
+ NULL, NULL, &ahc_echo, NULL,
+ MHD_OPTION_SOCK_ADDR_LEN,
+ (socklen_t) sizeof(daemon_ip_addr6), &daemon_ip_addr6,
+ MHD_OPTION_END);
+
+ if (d == 0)
+ return 1;
+
+ dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT);
+ if (NULL == dinfo)
+ ret |= 1 << 1;
+ else if (port6 != dinfo->port)
+ ret |= 1 << 2;
+
+ MHD_stop_daemon (d);
+
+
+ daemon_ip_addr6.sin6_len = (socklen_t) (sizeof(daemon_ip_addr6) / 2);
+ d = MHD_start_daemon (MHD_USE_ERROR_LOG, 0,
+ NULL, NULL, &ahc_echo, NULL,
+ MHD_OPTION_SOCK_ADDR_LEN,
+ (socklen_t) sizeof(daemon_ip_addr6), &daemon_ip_addr6,
+ MHD_OPTION_END);
+
+ if (NULL != d)
+ {
+ MHD_stop_daemon (d);
+ return 1 << 3;
+ }
+
+#endif /* HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN */
+#endif /* HAVE_INET6 && USE_IPV6_TESTING */
+
+ return ret;
}
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.