gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[libmicrohttpd] branch master updated (b6737ab3 -> 6cb3cc34)


From: gnunet
Subject: [libmicrohttpd] branch master updated (b6737ab3 -> 6cb3cc34)
Date: Thu, 16 Nov 2023 07:13:12 +0100

This is an automated email from the git hooks/post-receive script.

karlson2k pushed a change to branch master
in repository libmicrohttpd.

    from b6737ab3 Added check for signed socket type
     new dc4bbb0c Additional corrections for MHD_OPTION_APP_FD_SETSIZE
     new 6ee00803 Moved check for listen socket to fit fd_set
     new f73ab438 microhttpd.h: minor clarification for doxy
     new f5a72d27 Implemented new option MHD_OPTION_SOCK_ADDR_LEN
     new 6cb3cc34 Fixed (again) and improved detection of application-provided 
socket type

The 5 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 configure.ac                  |  10 +-
 src/include/microhttpd.h      |  24 +-
 src/microhttpd/daemon.c       | 527 ++++++++++++++++++++++++++++++------------
 src/microhttpd/test_options.c | 176 +++++++++++++-
 4 files changed, 576 insertions(+), 161 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 9d54ddee..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,
 
@@ -1825,7 +1827,7 @@ enum MHD_OPTION
    *                           MHD_OPTION_END);
    *
    * For options that expect a single pointer argument, the
-   * second member of the `struct MHD_OptionItem` is ignored.
+   * 'value' member of the `struct MHD_OptionItem` is ignored.
    * For options that expect two pointer arguments, the first
    * argument must be cast to `intptr_t`.
    */
@@ -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 b2420ca8..e97ddb91 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)
@@ -7382,7 +7410,6 @@ process_interim_params (struct MHD_Daemon *d,
     }
     else
     { /* The daemon without internal threads, external sockets polling */
-#ifdef MHD_POSIX_SOCKETS
 #ifndef HAS_FD_SETSIZE_OVERRIDABLE
       if (((int) FD_SETSIZE) != params->fdset_size)
       {
@@ -7399,7 +7426,6 @@ process_interim_params (struct MHD_Daemon *d,
       d->fdset_size = params->fdset_size;
       d->fdset_size_set_by_app = true;
 #endif /* HAS_FD_SETSIZE_OVERRIDABLE */
-#endif /* MHD_POSIX_SOCKETS */
     }
   }
 
@@ -7432,29 +7458,58 @@ process_interim_params (struct MHD_Daemon *d,
     }
     else
     {
-#if defined(SO_DOMAIN) && defined(AF_UNIX)
-      int af;
-      socklen_t len = sizeof (af);
-
-      if (0 == getsockopt (d->listen_fd,
-                           SOL_SOCKET,
-                           SO_DOMAIN,
-                           &af,
-                           &len))
-      {
-        d->listen_is_unix = (AF_UNIX == af) ? _MHD_YES : _MHD_NO;
-      }
-      else
-        d->listen_is_unix = _MHD_UNKNOWN;
-#else  /* ! SO_DOMAIN || ! AF_UNIX */
-      d->listen_is_unix = _MHD_UNKNOWN;
-#endif /* ! SO_DOMAIN || ! AF_UNIX */
       d->listen_fd = params->listen_fd;
+      d->listen_is_unix = _MHD_UNKNOWN;
 #ifdef MHD_USE_GETSOCKNAME
       d->port = 0;  /* Force use of autodetection */
 #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;
 }
 
@@ -7492,11 +7547,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;
@@ -7668,9 +7719,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))
   {
@@ -7683,7 +7737,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);
@@ -7855,19 +7912,215 @@ 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 */
+        }
+        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)
@@ -7879,7 +8132,19 @@ MHD_start_daemon_va (unsigned int flags,
 #endif
       goto free_and_fail;
     }
-    daemon->listen_is_unix = _MHD_NO;
+    if (MHD_D_IS_USING_SELECT_ (daemon) &&
+        (! MHD_D_DOES_SCKT_FIT_FDSET_ (listen_fd, daemon)) )
+    {
+#ifdef HAVE_MESSAGES
+      MHD_DLOG (daemon,
+                _ ("Listen socket descriptor (%d) is not " \
+                   "less than daemon FD_SETSIZE value (%d).\n"),
+                (int) listen_fd,
+                (int) MHD_D_GET_FD_SETSIZE_ (daemon));
+#endif
+      MHD_socket_close_chk_ (listen_fd);
+      goto free_and_fail;
+    }
 
     /* Apply the socket options according to listening_address_reuse. */
     if (0 == daemon->listening_address_reuse)
@@ -7992,87 +8257,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
@@ -8097,7 +8283,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,
@@ -8141,12 +8327,68 @@ MHD_start_daemon_va (unsigned int flags,
   }
   else
   {
+#if defined(SOL_SOCKET) && (defined(SO_DOMAIN) || defined(SO_PROTOCOL_INFOW))
+    int af;
+    int opt_name;
+    void *poptval;
+    socklen_t optval_size;
+#ifdef SO_DOMAIN
+    opt_name = SO_DOMAIN;
+    poptval = &af;
+    optval_size = (socklen_t) sizeof (af);
+#else  /* SO_PROTOCOL_INFOW */
+    WSAPROTOCOL_INFOW prot_info;
+    opt_name = SO_PROTOCOL_INFOW;
+    poptval = &prot_info;
+    optval_size = (socklen_t) sizeof (prot_info);
+#endif /* SO_PROTOCOL_INFOW */
+
+    if (0 == getsockopt (daemon->listen_fd,
+                         SOL_SOCKET,
+                         opt_name,
+                         poptval,
+                         &optval_size))
+    {
+#ifndef SO_DOMAIN
+      af = prot_info.iAddressFamily;
+#endif /* SO_DOMAIN */
+      switch (af)
+      {
+      case AF_INET:
+        daemon->listen_is_unix = _MHD_NO;
+        break;
+#ifdef HAVE_INET6
+      case AF_INET6:
+        *pflags |= MHD_USE_IPv6;
+        daemon->listen_is_unix = _MHD_NO;
+        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 /* AF_UNIX */
+      default:
+        daemon->port = 0;     /* ugh */
+        daemon->listen_is_unix = _MHD_UNKNOWN;
+        break;
+      }
+    }
+    else
+#endif /* SOL_SOCKET && (SO_DOMAIN || SO_PROTOCOL_INFOW)) */
+    daemon->listen_is_unix = _MHD_UNKNOWN;
+
     listen_fd = daemon->listen_fd;
+#ifdef MHD_USE_GETSOCKNAME
+    daemon->port = 0;  /* Force use of autodetection */
+#endif /* MHD_USE_GETSOCKNAME */
   }
 
 #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;
 
@@ -8155,7 +8397,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,
@@ -8256,19 +8498,6 @@ MHD_start_daemon_va (unsigned int flags,
     }
     else
       daemon->listen_nonblk = true;
-    if (MHD_D_IS_USING_SELECT_ (daemon) &&
-        (! MHD_D_DOES_SCKT_FIT_FDSET_ (listen_fd, daemon)) )
-    {
-#ifdef HAVE_MESSAGES
-      MHD_DLOG (daemon,
-                _ ("Listen socket descriptor (%d) is not " \
-                   "less than daemon FD_SETSIZE value (%d).\n"),
-                (int) listen_fd,
-                (int) MHD_D_GET_FD_SETSIZE_ (daemon));
-#endif
-      MHD_socket_close_chk_ (listen_fd);
-      goto free_and_fail;
-    }
   }
   else
   {
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.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]