mirror of
https://git.gnunet.org/libmicrohttpd.git
synced 2026-09-27 04:09:31 +03:00
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.
This commit is contained in:
+8
-2
@@ -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
|
||||
])
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
+310
-117
@@ -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 */
|
||||
struct sockaddr_in servaddr4;
|
||||
#ifdef HAVE_INET6
|
||||
struct sockaddr_in6 servaddr6;
|
||||
const bool use_ipv6 = (0 != (*pflags & MHD_USE_IPv6));
|
||||
#else /* ! HAVE_INET6 */
|
||||
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
|
||||
domain = (*pflags & MHD_USE_IPv6) ? PF_INET6 : PF_INET;
|
||||
#else /* ! HAVE_INET6 */
|
||||
if (*pflags & MHD_USE_IPv6)
|
||||
goto free_and_fail;
|
||||
domain = PF_INET;
|
||||
#endif /* ! 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,
|
||||
|
||||
@@ -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);
|
||||
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_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;
|
||||
|
||||
MHD_stop_daemon (d);
|
||||
#endif
|
||||
dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT);
|
||||
if (NULL == dinfo)
|
||||
ret |= 1 << 1;
|
||||
else
|
||||
port6 = dinfo->port;
|
||||
|
||||
return 0;
|
||||
MHD_stop_daemon (d);
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user