diff options
Diffstat (limited to 'src/microhttpd/daemon.c')
-rw-r--r-- | src/microhttpd/daemon.c | 427 |
1 files changed, 310 insertions, 117 deletions
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_ | |||
6181 | * Application-provided listen socket. | 6181 | * Application-provided listen socket. |
6182 | */ | 6182 | */ |
6183 | MHD_socket listen_fd; | 6183 | MHD_socket listen_fd; |
6184 | 6184 | /** | |
6185 | * Set to 'true' if @a server_addr is set by application. | ||
6186 | */ | ||
6187 | bool pserver_addr_set; | ||
6188 | /** | ||
6189 | * Application-provided struct sockaddr to bind server to. | ||
6190 | */ | ||
6191 | const struct sockaddr *pserver_addr; | ||
6192 | /** | ||
6193 | * Set to 'true' if @a server_addr_len is set by application. | ||
6194 | */ | ||
6195 | bool server_addr_len_set; | ||
6196 | /** | ||
6197 | * Applicaiton-provided the size of the memory pointed by @a server_addr. | ||
6198 | */ | ||
6199 | socklen_t server_addr_len; | ||
6185 | }; | 6200 | }; |
6186 | 6201 | ||
6187 | /** | 6202 | /** |
@@ -6208,7 +6223,6 @@ typedef void | |||
6208 | */ | 6223 | */ |
6209 | static enum MHD_Result | 6224 | static enum MHD_Result |
6210 | parse_options_va (struct MHD_Daemon *daemon, | 6225 | parse_options_va (struct MHD_Daemon *daemon, |
6211 | const struct sockaddr **servaddr, | ||
6212 | struct MHD_InterimParams_ *params, | 6226 | struct MHD_InterimParams_ *params, |
6213 | va_list ap); | 6227 | va_list ap); |
6214 | 6228 | ||
@@ -6224,7 +6238,6 @@ parse_options_va (struct MHD_Daemon *daemon, | |||
6224 | */ | 6238 | */ |
6225 | static enum MHD_Result | 6239 | static enum MHD_Result |
6226 | parse_options (struct MHD_Daemon *daemon, | 6240 | parse_options (struct MHD_Daemon *daemon, |
6227 | const struct sockaddr **servaddr, | ||
6228 | struct MHD_InterimParams_ *params, | 6241 | struct MHD_InterimParams_ *params, |
6229 | ...) | 6242 | ...) |
6230 | { | 6243 | { |
@@ -6233,7 +6246,6 @@ parse_options (struct MHD_Daemon *daemon, | |||
6233 | 6246 | ||
6234 | va_start (ap, params); | 6247 | va_start (ap, params); |
6235 | ret = parse_options_va (daemon, | 6248 | ret = parse_options_va (daemon, |
6236 | servaddr, | ||
6237 | params, | 6249 | params, |
6238 | ap); | 6250 | ap); |
6239 | va_end (ap); | 6251 | va_end (ap); |
@@ -6507,15 +6519,13 @@ daemon_tls_priorities_init_append (struct MHD_Daemon *daemon, const char *prio) | |||
6507 | /** | 6519 | /** |
6508 | * Parse a list of options given as varargs. | 6520 | * Parse a list of options given as varargs. |
6509 | * | 6521 | * |
6510 | * @param daemon the daemon to initialize | 6522 | * @param[in,out] daemon the daemon to initialize |
6511 | * @param servaddr where to store the server's listen address | 6523 | * @param[out] params the interim parameters to be assigned to |
6512 | * @param params the interim parameters to be assigned to | ||
6513 | * @param ap the options | 6524 | * @param ap the options |
6514 | * @return #MHD_YES on success, #MHD_NO on error | 6525 | * @return #MHD_YES on success, #MHD_NO on error |
6515 | */ | 6526 | */ |
6516 | static enum MHD_Result | 6527 | static enum MHD_Result |
6517 | parse_options_va (struct MHD_Daemon *daemon, | 6528 | parse_options_va (struct MHD_Daemon *daemon, |
6518 | const struct sockaddr **servaddr, | ||
6519 | struct MHD_InterimParams_ *params, | 6529 | struct MHD_InterimParams_ *params, |
6520 | va_list ap) | 6530 | va_list ap) |
6521 | { | 6531 | { |
@@ -6618,9 +6628,19 @@ parse_options_va (struct MHD_Daemon *daemon, | |||
6618 | daemon->per_ip_connection_limit = va_arg (ap, | 6628 | daemon->per_ip_connection_limit = va_arg (ap, |
6619 | unsigned int); | 6629 | unsigned int); |
6620 | break; | 6630 | break; |
6631 | case MHD_OPTION_SOCK_ADDR_LEN: | ||
6632 | params->server_addr_len = va_arg (ap, | ||
6633 | socklen_t); | ||
6634 | params->server_addr_len_set = true; | ||
6635 | params->pserver_addr = va_arg (ap, | ||
6636 | const struct sockaddr *); | ||
6637 | params->pserver_addr_set = true; | ||
6638 | break; | ||
6621 | case MHD_OPTION_SOCK_ADDR: | 6639 | case MHD_OPTION_SOCK_ADDR: |
6622 | *servaddr = va_arg (ap, | 6640 | params->server_addr_len_set = false; |
6623 | const struct sockaddr *); | 6641 | params->pserver_addr = va_arg (ap, |
6642 | const struct sockaddr *); | ||
6643 | params->pserver_addr_set = true; | ||
6624 | break; | 6644 | break; |
6625 | case MHD_OPTION_URI_LOG_CALLBACK: | 6645 | case MHD_OPTION_URI_LOG_CALLBACK: |
6626 | daemon->uri_log_callback = va_arg (ap, | 6646 | daemon->uri_log_callback = va_arg (ap, |
@@ -7006,7 +7026,6 @@ parse_options_va (struct MHD_Daemon *daemon, | |||
7006 | case MHD_OPTION_CONNECTION_MEMORY_INCREMENT: | 7026 | case MHD_OPTION_CONNECTION_MEMORY_INCREMENT: |
7007 | case MHD_OPTION_THREAD_STACK_SIZE: | 7027 | case MHD_OPTION_THREAD_STACK_SIZE: |
7008 | if (MHD_NO == parse_options (daemon, | 7028 | if (MHD_NO == parse_options (daemon, |
7009 | servaddr, | ||
7010 | params, | 7029 | params, |
7011 | opt, | 7030 | opt, |
7012 | (size_t) oa[i].value, | 7031 | (size_t) oa[i].value, |
@@ -7025,7 +7044,6 @@ parse_options_va (struct MHD_Daemon *daemon, | |||
7025 | case MHD_OPTION_SERVER_INSANITY: | 7044 | case MHD_OPTION_SERVER_INSANITY: |
7026 | case MHD_OPTION_DIGEST_AUTH_NONCE_BIND_TYPE: | 7045 | case MHD_OPTION_DIGEST_AUTH_NONCE_BIND_TYPE: |
7027 | if (MHD_NO == parse_options (daemon, | 7046 | if (MHD_NO == parse_options (daemon, |
7028 | servaddr, | ||
7029 | params, | 7047 | params, |
7030 | opt, | 7048 | opt, |
7031 | (unsigned int) oa[i].value, | 7049 | (unsigned int) oa[i].value, |
@@ -7036,7 +7054,6 @@ parse_options_va (struct MHD_Daemon *daemon, | |||
7036 | case MHD_OPTION_HTTPS_CRED_TYPE: | 7054 | case MHD_OPTION_HTTPS_CRED_TYPE: |
7037 | #ifdef HTTPS_SUPPORT | 7055 | #ifdef HTTPS_SUPPORT |
7038 | if (MHD_NO == parse_options (daemon, | 7056 | if (MHD_NO == parse_options (daemon, |
7039 | servaddr, | ||
7040 | params, | 7057 | params, |
7041 | opt, | 7058 | opt, |
7042 | (gnutls_credentials_type_t) oa[i].value, | 7059 | (gnutls_credentials_type_t) oa[i].value, |
@@ -7047,7 +7064,6 @@ parse_options_va (struct MHD_Daemon *daemon, | |||
7047 | /* all options taking 'MHD_socket' */ | 7064 | /* all options taking 'MHD_socket' */ |
7048 | case MHD_OPTION_LISTEN_SOCKET: | 7065 | case MHD_OPTION_LISTEN_SOCKET: |
7049 | if (MHD_NO == parse_options (daemon, | 7066 | if (MHD_NO == parse_options (daemon, |
7050 | servaddr, | ||
7051 | params, | 7067 | params, |
7052 | opt, | 7068 | opt, |
7053 | (MHD_socket) oa[i].value, | 7069 | (MHD_socket) oa[i].value, |
@@ -7061,7 +7077,6 @@ parse_options_va (struct MHD_Daemon *daemon, | |||
7061 | case MHD_OPTION_TLS_NO_ALPN: | 7077 | case MHD_OPTION_TLS_NO_ALPN: |
7062 | case MHD_OPTION_APP_FD_SETSIZE: | 7078 | case MHD_OPTION_APP_FD_SETSIZE: |
7063 | if (MHD_NO == parse_options (daemon, | 7079 | if (MHD_NO == parse_options (daemon, |
7064 | servaddr, | ||
7065 | params, | 7080 | params, |
7066 | opt, | 7081 | opt, |
7067 | (int) oa[i].value, | 7082 | (int) oa[i].value, |
@@ -7081,7 +7096,6 @@ parse_options_va (struct MHD_Daemon *daemon, | |||
7081 | case MHD_OPTION_HTTPS_CERT_CALLBACK: | 7096 | case MHD_OPTION_HTTPS_CERT_CALLBACK: |
7082 | case MHD_OPTION_HTTPS_CERT_CALLBACK2: | 7097 | case MHD_OPTION_HTTPS_CERT_CALLBACK2: |
7083 | if (MHD_NO == parse_options (daemon, | 7098 | if (MHD_NO == parse_options (daemon, |
7084 | servaddr, | ||
7085 | params, | 7099 | params, |
7086 | opt, | 7100 | opt, |
7087 | oa[i].ptr_value, | 7101 | oa[i].ptr_value, |
@@ -7096,7 +7110,6 @@ parse_options_va (struct MHD_Daemon *daemon, | |||
7096 | case MHD_OPTION_UNESCAPE_CALLBACK: | 7110 | case MHD_OPTION_UNESCAPE_CALLBACK: |
7097 | case MHD_OPTION_GNUTLS_PSK_CRED_HANDLER: | 7111 | case MHD_OPTION_GNUTLS_PSK_CRED_HANDLER: |
7098 | if (MHD_NO == parse_options (daemon, | 7112 | if (MHD_NO == parse_options (daemon, |
7099 | servaddr, | ||
7100 | params, | 7113 | params, |
7101 | opt, | 7114 | opt, |
7102 | (void *) oa[i].value, | 7115 | (void *) oa[i].value, |
@@ -7108,7 +7121,6 @@ parse_options_va (struct MHD_Daemon *daemon, | |||
7108 | case MHD_OPTION_DIGEST_AUTH_RANDOM: | 7121 | case MHD_OPTION_DIGEST_AUTH_RANDOM: |
7109 | case MHD_OPTION_DIGEST_AUTH_RANDOM_COPY: | 7122 | case MHD_OPTION_DIGEST_AUTH_RANDOM_COPY: |
7110 | if (MHD_NO == parse_options (daemon, | 7123 | if (MHD_NO == parse_options (daemon, |
7111 | servaddr, | ||
7112 | params, | 7124 | params, |
7113 | opt, | 7125 | opt, |
7114 | (size_t) oa[i].value, | 7126 | (size_t) oa[i].value, |
@@ -7116,6 +7128,16 @@ parse_options_va (struct MHD_Daemon *daemon, | |||
7116 | MHD_OPTION_END)) | 7128 | MHD_OPTION_END)) |
7117 | return MHD_NO; | 7129 | return MHD_NO; |
7118 | break; | 7130 | break; |
7131 | /* options taking socklen_t-number followed by pointer */ | ||
7132 | case MHD_OPTION_SOCK_ADDR_LEN: | ||
7133 | if (MHD_NO == parse_options (daemon, | ||
7134 | params, | ||
7135 | opt, | ||
7136 | (socklen_t) oa[i].value, | ||
7137 | oa[i].ptr_value, | ||
7138 | MHD_OPTION_END)) | ||
7139 | return MHD_NO; | ||
7140 | break; | ||
7119 | case MHD_OPTION_END: /* Not possible */ | 7141 | case MHD_OPTION_END: /* Not possible */ |
7120 | default: | 7142 | default: |
7121 | return MHD_NO; | 7143 | return MHD_NO; |
@@ -7342,13 +7364,19 @@ setup_epoll_to_listen (struct MHD_Daemon *daemon) | |||
7342 | 7364 | ||
7343 | /** | 7365 | /** |
7344 | * Apply interim parameters | 7366 | * Apply interim parameters |
7345 | * @param d the daemon to use | 7367 | * @param[in,out] d the daemon to use |
7346 | * @param params the interim parameters to process | 7368 | * @param[out] ppsockaddr the pointer to store the pointer to 'struct sockaddr' |
7369 | * if provided by application | ||
7370 | * @param[out] psockaddr_len the size memory area pointed by 'struct sockaddr' | ||
7371 | * if provided by application | ||
7372 | * @param[in] params the interim parameters to process | ||
7347 | * @return true in case of success, | 7373 | * @return true in case of success, |
7348 | * false in case of critical error (the daemon must be closed). | 7374 | * false in case of critical error (the daemon must be closed). |
7349 | */ | 7375 | */ |
7350 | static bool | 7376 | static bool |
7351 | process_interim_params (struct MHD_Daemon *d, | 7377 | process_interim_params (struct MHD_Daemon *d, |
7378 | const struct sockaddr **ppsockaddr, | ||
7379 | socklen_t *psockaddr_len, | ||
7352 | struct MHD_InterimParams_ *params) | 7380 | struct MHD_InterimParams_ *params) |
7353 | { | 7381 | { |
7354 | if (params->fdset_size_set) | 7382 | if (params->fdset_size_set) |
@@ -7453,6 +7481,51 @@ process_interim_params (struct MHD_Daemon *d, | |||
7453 | #endif /* MHD_USE_GETSOCKNAME */ | 7481 | #endif /* MHD_USE_GETSOCKNAME */ |
7454 | } | 7482 | } |
7455 | } | 7483 | } |
7484 | |||
7485 | mhd_assert (! params->server_addr_len_set || params->pserver_addr_set); | ||
7486 | if (params->pserver_addr_set) | ||
7487 | { | ||
7488 | if (NULL == params->pserver_addr) | ||
7489 | { | ||
7490 | /* The size must be zero if set */ | ||
7491 | if (params->server_addr_len_set && (0 != params->server_addr_len)) | ||
7492 | return false; | ||
7493 | /* Ignore parameter if it is NULL */ | ||
7494 | } | ||
7495 | else if (MHD_INVALID_SOCKET != d->listen_fd) | ||
7496 | { | ||
7497 | #ifdef HAVE_MESSAGES | ||
7498 | MHD_DLOG (d, | ||
7499 | _ ("MHD_OPTION_LISTEN_SOCKET cannot be used together with " \ | ||
7500 | "MHD_OPTION_SOCK_ADDR_LEN or MHD_OPTION_SOCK_ADDR.\n")); | ||
7501 | #endif /* HAVE_MESSAGES */ | ||
7502 | return false; | ||
7503 | } | ||
7504 | else if (0 != (d->options & MHD_USE_NO_LISTEN_SOCKET)) | ||
7505 | { | ||
7506 | #ifdef HAVE_MESSAGES | ||
7507 | MHD_DLOG (d, | ||
7508 | _ ("MHD_OPTION_SOCK_ADDR_LEN or MHD_OPTION_SOCK_ADDR " \ | ||
7509 | "specified for daemon with MHD_USE_NO_LISTEN_SOCKET " \ | ||
7510 | "flag set.\n")); | ||
7511 | #endif /* HAVE_MESSAGES */ | ||
7512 | (void) MHD_socket_close_ (params->listen_fd); | ||
7513 | return false; | ||
7514 | } | ||
7515 | else | ||
7516 | { | ||
7517 | *ppsockaddr = params->pserver_addr; | ||
7518 | if (params->server_addr_len_set) | ||
7519 | { | ||
7520 | /* The size must be non-zero if set */ | ||
7521 | if (0 == params->server_addr_len) | ||
7522 | return false; | ||
7523 | *psockaddr_len = params->server_addr_len; | ||
7524 | } | ||
7525 | else | ||
7526 | *psockaddr_len = 0; | ||
7527 | } | ||
7528 | } | ||
7456 | return true; | 7529 | return true; |
7457 | } | 7530 | } |
7458 | 7531 | ||
@@ -7490,11 +7563,7 @@ MHD_start_daemon_va (unsigned int flags, | |||
7490 | const MHD_SCKT_OPT_BOOL_ on = 1; | 7563 | const MHD_SCKT_OPT_BOOL_ on = 1; |
7491 | struct MHD_Daemon *daemon; | 7564 | struct MHD_Daemon *daemon; |
7492 | MHD_socket listen_fd; | 7565 | MHD_socket listen_fd; |
7493 | struct sockaddr_in servaddr4; | 7566 | const struct sockaddr *pservaddr = NULL; |
7494 | #ifdef HAVE_INET6 | ||
7495 | struct sockaddr_in6 servaddr6; | ||
7496 | #endif | ||
7497 | const struct sockaddr *servaddr = NULL; | ||
7498 | socklen_t addrlen; | 7567 | socklen_t addrlen; |
7499 | #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) | 7568 | #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) |
7500 | unsigned int i; | 7569 | unsigned int i; |
@@ -7666,9 +7735,12 @@ MHD_start_daemon_va (unsigned int flags, | |||
7666 | interim_params->fdset_size = 0; | 7735 | interim_params->fdset_size = 0; |
7667 | interim_params->listen_fd_set = false; | 7736 | interim_params->listen_fd_set = false; |
7668 | interim_params->listen_fd = MHD_INVALID_SOCKET; | 7737 | interim_params->listen_fd = MHD_INVALID_SOCKET; |
7738 | interim_params->pserver_addr_set = false; | ||
7739 | interim_params->pserver_addr = NULL; | ||
7740 | interim_params->server_addr_len_set = false; | ||
7741 | interim_params->server_addr_len = 0; | ||
7669 | 7742 | ||
7670 | if (MHD_NO == parse_options_va (daemon, | 7743 | if (MHD_NO == parse_options_va (daemon, |
7671 | &servaddr, | ||
7672 | interim_params, | 7744 | interim_params, |
7673 | ap)) | 7745 | ap)) |
7674 | { | 7746 | { |
@@ -7681,7 +7753,10 @@ MHD_start_daemon_va (unsigned int flags, | |||
7681 | free (daemon); | 7753 | free (daemon); |
7682 | return NULL; | 7754 | return NULL; |
7683 | } | 7755 | } |
7684 | if (! process_interim_params (daemon, interim_params)) | 7756 | if (! process_interim_params (daemon, |
7757 | &pservaddr, | ||
7758 | &addrlen, | ||
7759 | interim_params)) | ||
7685 | { | 7760 | { |
7686 | free (interim_params); | 7761 | free (interim_params); |
7687 | free (daemon); | 7762 | free (daemon); |
@@ -7853,19 +7928,216 @@ MHD_start_daemon_va (unsigned int flags, | |||
7853 | goto free_and_fail; | 7928 | goto free_and_fail; |
7854 | } | 7929 | } |
7855 | #endif | 7930 | #endif |
7931 | |||
7856 | if ( (MHD_INVALID_SOCKET == daemon->listen_fd) && | 7932 | if ( (MHD_INVALID_SOCKET == daemon->listen_fd) && |
7857 | (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) ) | 7933 | (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) ) |
7858 | { | 7934 | { |
7859 | /* try to open listen socket */ | 7935 | /* try to open listen socket */ |
7860 | int domain; | 7936 | struct sockaddr_in servaddr4; |
7861 | |||
7862 | #ifdef HAVE_INET6 | 7937 | #ifdef HAVE_INET6 |
7863 | domain = (*pflags & MHD_USE_IPv6) ? PF_INET6 : PF_INET; | 7938 | struct sockaddr_in6 servaddr6; |
7939 | const bool use_ipv6 = (0 != (*pflags & MHD_USE_IPv6)); | ||
7864 | #else /* ! HAVE_INET6 */ | 7940 | #else /* ! HAVE_INET6 */ |
7865 | if (*pflags & MHD_USE_IPv6) | 7941 | const bool use_ipv6 = false; |
7866 | goto free_and_fail; | ||
7867 | domain = PF_INET; | ||
7868 | #endif /* ! HAVE_INET6 */ | 7942 | #endif /* ! HAVE_INET6 */ |
7943 | int domain; | ||
7944 | |||
7945 | if (NULL != pservaddr) | ||
7946 | { | ||
7947 | #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN | ||
7948 | const socklen_t sa_len = pservaddr->sa_len; | ||
7949 | #endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */ | ||
7950 | #ifdef HAVE_INET6 | ||
7951 | if (use_ipv6 && (AF_INET6 != pservaddr->sa_family)) | ||
7952 | { | ||
7953 | #ifdef HAVE_MESSAGES | ||
7954 | MHD_DLOG (daemon, | ||
7955 | _ ("MHD_USE_IPv6 is enabled, but 'struct sockaddr *' " \ | ||
7956 | "specified for MHD_OPTION_SOCK_ADDR_LEN or " \ | ||
7957 | "MHD_OPTION_SOCK_ADDR is not IPv6 address.\n")); | ||
7958 | #endif /* HAVE_MESSAGES */ | ||
7959 | goto free_and_fail; | ||
7960 | } | ||
7961 | #endif /* HAVE_INET6 */ | ||
7962 | switch (pservaddr->sa_family) | ||
7963 | { | ||
7964 | case AF_INET: | ||
7965 | if (1) | ||
7966 | { | ||
7967 | struct sockaddr_in sa4; | ||
7968 | uint16_t sa4_port; | ||
7969 | if ((0 != addrlen) | ||
7970 | && (((socklen_t) sizeof(sa4)) > addrlen)) | ||
7971 | { | ||
7972 | #ifdef HAVE_MESSAGES | ||
7973 | MHD_DLOG (daemon, | ||
7974 | _ ("The size specified for MHD_OPTION_SOCK_ADDR_LEN " \ | ||
7975 | "option is wrong.\n")); | ||
7976 | #endif /* HAVE_MESSAGES */ | ||
7977 | goto free_and_fail; | ||
7978 | } | ||
7979 | #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN | ||
7980 | if (0 != sa_len) | ||
7981 | { | ||
7982 | if (((socklen_t) sizeof(sa4)) > sa_len) | ||
7983 | { | ||
7984 | #ifdef HAVE_MESSAGES | ||
7985 | MHD_DLOG (daemon, | ||
7986 | _ ("The value of 'struct sockaddr.sa_len' provided " \ | ||
7987 | "via MHD_OPTION_SOCK_ADDR_LEN option is not zero " \ | ||
7988 | "and does not match 'sa_family' value of the " \ | ||
7989 | "same structure.\n")); | ||
7990 | #endif /* HAVE_MESSAGES */ | ||
7991 | goto free_and_fail; | ||
7992 | } | ||
7993 | if ((0 == addrlen) || (sa_len < addrlen)) | ||
7994 | addrlen = sa_len; /* Use smaller value for safety */ | ||
7995 | } | ||
7996 | #endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */ | ||
7997 | if (0 == addrlen) | ||
7998 | addrlen = sizeof(sa4); | ||
7999 | memcpy (&sa4, pservaddr, sizeof(sa4)); /* Required due to stronger alignment */ | ||
8000 | sa4_port = (uint16_t) ntohs (sa4.sin_port); | ||
8001 | #ifndef MHD_USE_GETSOCKNAME | ||
8002 | if (0 != sa4_port) | ||
8003 | #endif /* ! MHD_USE_GETSOCKNAME */ | ||
8004 | daemon->port = sa4_port; | ||
8005 | domain = PF_INET; | ||
8006 | } | ||
8007 | break; | ||
8008 | #ifdef HAVE_INET6 | ||
8009 | case AF_INET6: | ||
8010 | if (1) | ||
8011 | { | ||
8012 | struct sockaddr_in6 sa6; | ||
8013 | uint16_t sa6_port; | ||
8014 | if ((0 != addrlen) | ||
8015 | && (((socklen_t) sizeof(sa6)) > addrlen)) | ||
8016 | { | ||
8017 | #ifdef HAVE_MESSAGES | ||
8018 | MHD_DLOG (daemon, | ||
8019 | _ ("The size specified for MHD_OPTION_SOCK_ADDR_LEN " \ | ||
8020 | "option is wrong.\n")); | ||
8021 | #endif /* HAVE_MESSAGES */ | ||
8022 | goto free_and_fail; | ||
8023 | } | ||
8024 | #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN | ||
8025 | if (0 != sa_len) | ||
8026 | { | ||
8027 | if (((socklen_t) sizeof(sa6)) > sa_len) | ||
8028 | { | ||
8029 | #ifdef HAVE_MESSAGES | ||
8030 | MHD_DLOG (daemon, | ||
8031 | _ ("The value of 'struct sockaddr.sa_len' provided " \ | ||
8032 | "via MHD_OPTION_SOCK_ADDR_LEN option is not zero " \ | ||
8033 | "and does not match 'sa_family' value of the " \ | ||
8034 | "same structure.\n")); | ||
8035 | #endif /* HAVE_MESSAGES */ | ||
8036 | goto free_and_fail; | ||
8037 | } | ||
8038 | if ((0 == addrlen) || (sa_len < addrlen)) | ||
8039 | addrlen = sa_len; /* Use smaller value for safety */ | ||
8040 | } | ||
8041 | #endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */ | ||
8042 | if (0 == addrlen) | ||
8043 | addrlen = sizeof(sa6); | ||
8044 | memcpy (&sa6, pservaddr, sizeof(sa6)); /* Required due to stronger alignment */ | ||
8045 | sa6_port = (uint16_t) ntohs (sa6.sin6_port); | ||
8046 | #ifndef MHD_USE_GETSOCKNAME | ||
8047 | if (0 != sa6_port) | ||
8048 | #endif /* ! MHD_USE_GETSOCKNAME */ | ||
8049 | daemon->port = sa6_port; | ||
8050 | domain = PF_INET6; | ||
8051 | *pflags |= ((enum MHD_FLAG) MHD_USE_IPv6); | ||
8052 | } | ||
8053 | break; | ||
8054 | #endif /* HAVE_INET6 */ | ||
8055 | #ifdef AF_UNIX | ||
8056 | case AF_UNIX: | ||
8057 | #endif /* AF_UNIX */ | ||
8058 | default: | ||
8059 | #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN | ||
8060 | if (0 == addrlen) | ||
8061 | addrlen = sa_len; | ||
8062 | else if ((0 != sa_len) && (sa_len < addrlen)) | ||
8063 | addrlen = sa_len; /* Use smaller value for safety */ | ||
8064 | #endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */ | ||
8065 | if (0 >= addrlen) | ||
8066 | { | ||
8067 | #ifdef HAVE_MESSAGES | ||
8068 | MHD_DLOG (daemon, | ||
8069 | _ ("The 'sa_family' of the 'struct sockaddr' provided " \ | ||
8070 | "via MHD_OPTION_SOCK_ADDR option is not supported.\n")); | ||
8071 | #endif /* HAVE_MESSAGES */ | ||
8072 | goto free_and_fail; | ||
8073 | } | ||
8074 | #ifdef AF_UNIX | ||
8075 | if (AF_UNIX == pservaddr->sa_family) | ||
8076 | { | ||
8077 | daemon->port = 0; /* special value for UNIX domain sockets */ | ||
8078 | daemon->listen_is_unix = _MHD_YES; | ||
8079 | #ifdef PF_UNIX | ||
8080 | domain = PF_UNIX; | ||
8081 | #else /* ! PF_UNIX */ | ||
8082 | domain = AF_UNIX; | ||
8083 | #endif /* ! PF_UNIX */ | ||
8084 | domain = PF_UNIX; | ||
8085 | } | ||
8086 | else /* combined with the next 'if' */ | ||
8087 | #endif /* AF_UNIX */ | ||
8088 | if (1) | ||
8089 | { | ||
8090 | daemon->port = 0; /* ugh */ | ||
8091 | daemon->listen_is_unix = _MHD_UNKNOWN; | ||
8092 | /* Assumed the same values for AF_* and PF_* */ | ||
8093 | domain = pservaddr->sa_family; | ||
8094 | } | ||
8095 | break; | ||
8096 | } | ||
8097 | } | ||
8098 | else | ||
8099 | { | ||
8100 | if (! use_ipv6) | ||
8101 | { | ||
8102 | memset (&servaddr4, | ||
8103 | 0, | ||
8104 | sizeof (struct sockaddr_in)); | ||
8105 | servaddr4.sin_family = AF_INET; | ||
8106 | servaddr4.sin_port = htons (port); | ||
8107 | if (0 != INADDR_ANY) | ||
8108 | servaddr4.sin_addr.s_addr = htonl (INADDR_ANY); | ||
8109 | #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN | ||
8110 | servaddr4.sin_len = sizeof (struct sockaddr_in); | ||
8111 | #endif | ||
8112 | pservaddr = (struct sockaddr *) &servaddr4; | ||
8113 | addrlen = (socklen_t) sizeof(servaddr4); | ||
8114 | daemon->listen_is_unix = _MHD_NO; | ||
8115 | domain = PF_INET; | ||
8116 | } | ||
8117 | #ifdef HAVE_INET6 | ||
8118 | else | ||
8119 | { | ||
8120 | #ifdef IN6ADDR_ANY_INIT | ||
8121 | static const struct in6_addr static_in6any = IN6ADDR_ANY_INIT; | ||
8122 | #endif | ||
8123 | memset (&servaddr6, | ||
8124 | 0, | ||
8125 | sizeof (struct sockaddr_in6)); | ||
8126 | servaddr6.sin6_family = AF_INET6; | ||
8127 | servaddr6.sin6_port = htons (port); | ||
8128 | #ifdef IN6ADDR_ANY_INIT | ||
8129 | servaddr6.sin6_addr = static_in6any; | ||
8130 | #endif | ||
8131 | #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN | ||
8132 | servaddr6.sin6_len = sizeof (struct sockaddr_in6); | ||
8133 | #endif | ||
8134 | pservaddr = (struct sockaddr *) &servaddr6; | ||
8135 | addrlen = (socklen_t) sizeof (servaddr6); | ||
8136 | daemon->listen_is_unix = _MHD_NO; | ||
8137 | domain = PF_INET6; | ||
8138 | } | ||
8139 | #endif /* HAVE_INET6 */ | ||
8140 | } | ||
7869 | 8141 | ||
7870 | listen_fd = MHD_socket_create_listen_ (domain); | 8142 | listen_fd = MHD_socket_create_listen_ (domain); |
7871 | if (MHD_INVALID_SOCKET == listen_fd) | 8143 | if (MHD_INVALID_SOCKET == listen_fd) |
@@ -7890,7 +8162,6 @@ MHD_start_daemon_va (unsigned int flags, | |||
7890 | MHD_socket_close_chk_ (listen_fd); | 8162 | MHD_socket_close_chk_ (listen_fd); |
7891 | goto free_and_fail; | 8163 | goto free_and_fail; |
7892 | } | 8164 | } |
7893 | daemon->listen_is_unix = _MHD_NO; | ||
7894 | 8165 | ||
7895 | /* Apply the socket options according to listening_address_reuse. */ | 8166 | /* Apply the socket options according to listening_address_reuse. */ |
7896 | if (0 == daemon->listening_address_reuse) | 8167 | if (0 == daemon->listening_address_reuse) |
@@ -8003,87 +8274,8 @@ MHD_start_daemon_va (unsigned int flags, | |||
8003 | } | 8274 | } |
8004 | 8275 | ||
8005 | /* check for user supplied sockaddr */ | 8276 | /* check for user supplied sockaddr */ |
8006 | #ifdef HAVE_INET6 | ||
8007 | if (0 != (*pflags & MHD_USE_IPv6)) | ||
8008 | addrlen = sizeof (struct sockaddr_in6); | ||
8009 | else | ||
8010 | #endif | ||
8011 | addrlen = sizeof (struct sockaddr_in); | ||
8012 | if (NULL == servaddr) | ||
8013 | { | ||
8014 | #ifdef HAVE_INET6 | ||
8015 | if (0 != (*pflags & MHD_USE_IPv6)) | ||
8016 | { | ||
8017 | #ifdef IN6ADDR_ANY_INIT | ||
8018 | static const struct in6_addr static_in6any = IN6ADDR_ANY_INIT; | ||
8019 | #endif | ||
8020 | memset (&servaddr6, | ||
8021 | 0, | ||
8022 | sizeof (struct sockaddr_in6)); | ||
8023 | servaddr6.sin6_family = AF_INET6; | ||
8024 | servaddr6.sin6_port = htons (port); | ||
8025 | #ifdef IN6ADDR_ANY_INIT | ||
8026 | servaddr6.sin6_addr = static_in6any; | ||
8027 | #endif | ||
8028 | #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN | ||
8029 | servaddr6.sin6_len = sizeof (struct sockaddr_in6); | ||
8030 | #endif | ||
8031 | servaddr = (struct sockaddr *) &servaddr6; | ||
8032 | } | ||
8033 | else | ||
8034 | #endif | ||
8035 | { | ||
8036 | memset (&servaddr4, | ||
8037 | 0, | ||
8038 | sizeof (struct sockaddr_in)); | ||
8039 | servaddr4.sin_family = AF_INET; | ||
8040 | servaddr4.sin_port = htons (port); | ||
8041 | if (0 != INADDR_ANY) | ||
8042 | servaddr4.sin_addr.s_addr = htonl (INADDR_ANY); | ||
8043 | #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN | ||
8044 | servaddr4.sin_len = sizeof (struct sockaddr_in); | ||
8045 | #endif | ||
8046 | servaddr = (struct sockaddr *) &servaddr4; | ||
8047 | } | ||
8048 | } | ||
8049 | else | ||
8050 | { | ||
8051 | #ifdef MHD_USE_GETSOCKNAME | ||
8052 | daemon->port = 0; /* Force use of autodetection */ | ||
8053 | #else /* ! MHD_USE_GETSOCKNAME */ | ||
8054 | switch (servaddr->sa_family) | ||
8055 | { | ||
8056 | case AF_INET: | ||
8057 | { | ||
8058 | struct sockaddr_in sa4; | ||
8059 | memcpy (&sa4, servaddr, sizeof(sa4)); /* Required due to stronger alignment */ | ||
8060 | daemon->port = ntohs (sa4.sin_port); | ||
8061 | break; | ||
8062 | } | ||
8063 | #ifdef HAVE_INET6 | ||
8064 | case AF_INET6: | ||
8065 | { | ||
8066 | struct sockaddr_in6 sa6; | ||
8067 | memcpy (&sa6, servaddr, sizeof(sa6)); /* Required due to stronger alignment */ | ||
8068 | daemon->port = ntohs (sa6.sin6_port); | ||
8069 | mhd_assert (0 != (*pflags & MHD_USE_IPv6)); | ||
8070 | break; | ||
8071 | } | ||
8072 | #endif /* HAVE_INET6 */ | ||
8073 | #ifdef AF_UNIX | ||
8074 | case AF_UNIX: | ||
8075 | daemon->port = 0; /* special value for UNIX domain sockets */ | ||
8076 | daemon->listen_is_unix = _MHD_YES; | ||
8077 | break; | ||
8078 | #endif | ||
8079 | default: | ||
8080 | daemon->port = 0; /* ugh */ | ||
8081 | daemon->listen_is_unix = _MHD_UNKNOWN; | ||
8082 | break; | ||
8083 | } | ||
8084 | #endif /* ! MHD_USE_GETSOCKNAME */ | ||
8085 | } | ||
8086 | daemon->listen_fd = listen_fd; | 8277 | daemon->listen_fd = listen_fd; |
8278 | |||
8087 | if (0 != (*pflags & MHD_USE_IPv6)) | 8279 | if (0 != (*pflags & MHD_USE_IPv6)) |
8088 | { | 8280 | { |
8089 | #ifdef IPPROTO_IPV6 | 8281 | #ifdef IPPROTO_IPV6 |
@@ -8108,7 +8300,7 @@ MHD_start_daemon_va (unsigned int flags, | |||
8108 | #endif | 8300 | #endif |
8109 | #endif | 8301 | #endif |
8110 | } | 8302 | } |
8111 | if (0 != bind (listen_fd, servaddr, addrlen)) | 8303 | if (0 != bind (listen_fd, pservaddr, addrlen)) |
8112 | { | 8304 | { |
8113 | #ifdef HAVE_MESSAGES | 8305 | #ifdef HAVE_MESSAGES |
8114 | MHD_DLOG (daemon, | 8306 | MHD_DLOG (daemon, |
@@ -8157,7 +8349,8 @@ MHD_start_daemon_va (unsigned int flags, | |||
8157 | 8349 | ||
8158 | #ifdef MHD_USE_GETSOCKNAME | 8350 | #ifdef MHD_USE_GETSOCKNAME |
8159 | if ( (0 == daemon->port) && | 8351 | if ( (0 == daemon->port) && |
8160 | (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) ) | 8352 | (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) && |
8353 | (_MHD_YES != daemon->listen_is_unix) ) | ||
8161 | { /* Get port number. */ | 8354 | { /* Get port number. */ |
8162 | struct sockaddr_storage bindaddr; | 8355 | struct sockaddr_storage bindaddr; |
8163 | 8356 | ||
@@ -8166,7 +8359,7 @@ MHD_start_daemon_va (unsigned int flags, | |||
8166 | sizeof (struct sockaddr_storage)); | 8359 | sizeof (struct sockaddr_storage)); |
8167 | addrlen = sizeof (struct sockaddr_storage); | 8360 | addrlen = sizeof (struct sockaddr_storage); |
8168 | #ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN | 8361 | #ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN |
8169 | bindaddr.ss_len = addrlen; | 8362 | bindaddr.ss_len = (socklen_t) addrlen; |
8170 | #endif | 8363 | #endif |
8171 | if (0 != getsockname (listen_fd, | 8364 | if (0 != getsockname (listen_fd, |
8172 | (struct sockaddr *) &bindaddr, | 8365 | (struct sockaddr *) &bindaddr, |