diff options
Diffstat (limited to 'src/daemon/daemon.c')
-rw-r--r-- | src/daemon/daemon.c | 95 |
1 files changed, 90 insertions, 5 deletions
diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c index 451bb39a..6db7ec10 100644 --- a/src/daemon/daemon.c +++ b/src/daemon/daemon.c | |||
@@ -77,6 +77,11 @@ | |||
77 | #endif | 77 | #endif |
78 | #endif | 78 | #endif |
79 | 79 | ||
80 | #ifndef SOCK_CLOEXEC | ||
81 | #define SOCK_CLOEXEC 0 | ||
82 | #endif | ||
83 | |||
84 | |||
80 | /** | 85 | /** |
81 | * Default implementation of the panic function | 86 | * Default implementation of the panic function |
82 | */ | 87 | */ |
@@ -961,7 +966,8 @@ MHD_add_connection (struct MHD_Daemon *daemon, | |||
961 | (0 != fcntl (connection->socket_fd, F_SETFL, flags | O_NONBLOCK)) ) | 966 | (0 != fcntl (connection->socket_fd, F_SETFL, flags | O_NONBLOCK)) ) |
962 | { | 967 | { |
963 | #if HAVE_MESSAGES | 968 | #if HAVE_MESSAGES |
964 | FPRINTF(stderr, "Failed to make socket non-blocking: %s\n", | 969 | FPRINTF(stderr, "Failed to make socket %d non-blocking: %s\n", |
970 | connection->socket_fd, | ||
965 | STRERROR (errno)); | 971 | STRERROR (errno)); |
966 | #endif | 972 | #endif |
967 | } | 973 | } |
@@ -1108,10 +1114,23 @@ MHD_accept_connection (struct MHD_Daemon *daemon) | |||
1108 | struct sockaddr *addr = (struct sockaddr *) &addrstorage; | 1114 | struct sockaddr *addr = (struct sockaddr *) &addrstorage; |
1109 | socklen_t addrlen; | 1115 | socklen_t addrlen; |
1110 | int s; | 1116 | int s; |
1117 | int flags; | ||
1118 | int need_fcntl; | ||
1111 | 1119 | ||
1112 | addrlen = sizeof (addrstorage); | 1120 | addrlen = sizeof (addrstorage); |
1113 | memset (addr, 0, sizeof (addrstorage)); | 1121 | memset (addr, 0, sizeof (addrstorage)); |
1114 | s = ACCEPT (daemon->socket_fd, addr, &addrlen); | 1122 | #if HAVE_ACCEPT4 |
1123 | s = accept4 (daemon->socket_fd, addr, &addrlen, SOCK_CLOEXEC); | ||
1124 | need_fcntl = MHD_NO; | ||
1125 | #else | ||
1126 | s = -1; | ||
1127 | need_fcntl = MHD_YES; | ||
1128 | #endif | ||
1129 | if (-1 == s) | ||
1130 | { | ||
1131 | s = ACCEPT (daemon->socket_fd, addr, &addrlen); | ||
1132 | need_fcntl = MHD_YES; | ||
1133 | } | ||
1115 | if ((s == -1) || (addrlen <= 0)) | 1134 | if ((s == -1) || (addrlen <= 0)) |
1116 | { | 1135 | { |
1117 | #if HAVE_MESSAGES | 1136 | #if HAVE_MESSAGES |
@@ -1127,6 +1146,20 @@ MHD_accept_connection (struct MHD_Daemon *daemon) | |||
1127 | } | 1146 | } |
1128 | return MHD_NO; | 1147 | return MHD_NO; |
1129 | } | 1148 | } |
1149 | if (MHD_YES == need_fcntl) | ||
1150 | { | ||
1151 | /* make socket non-inheritable */ | ||
1152 | flags = fcntl (s, F_GETFD); | ||
1153 | if ( ( (-1 == flags) || | ||
1154 | ( (flags != (flags | FD_CLOEXEC)) && | ||
1155 | (0 != fcntl (s, F_SETFD, flags | FD_CLOEXEC)) ) ) ) | ||
1156 | { | ||
1157 | #if HAVE_MESSAGES | ||
1158 | FPRINTF(stderr, "Failed to make socket non-inheritable: %s\n", | ||
1159 | STRERROR (errno)); | ||
1160 | #endif | ||
1161 | } | ||
1162 | } | ||
1130 | #if HAVE_MESSAGES | 1163 | #if HAVE_MESSAGES |
1131 | #if DEBUG_CONNECT | 1164 | #if DEBUG_CONNECT |
1132 | MHD_DLOG (daemon, "Accepted connection on socket %d\n", s); | 1165 | MHD_DLOG (daemon, "Accepted connection on socket %d\n", s); |
@@ -1947,6 +1980,58 @@ parse_options_va (struct MHD_Daemon *daemon, | |||
1947 | 1980 | ||
1948 | 1981 | ||
1949 | /** | 1982 | /** |
1983 | * Create a listen socket, if possible with CLOEXEC flag set. | ||
1984 | * | ||
1985 | * @param domain socket domain (i.e. PF_INET) | ||
1986 | * @param type socket type (usually SOCK_STREAM) | ||
1987 | * @param protocol desired protocol, 0 for default | ||
1988 | */ | ||
1989 | static int | ||
1990 | create_socket (int domain, int type, int protocol) | ||
1991 | { | ||
1992 | static int sock_cloexec = SOCK_CLOEXEC; | ||
1993 | int ctype = SOCK_STREAM | sock_cloexec; | ||
1994 | int fd; | ||
1995 | int flags; | ||
1996 | |||
1997 | /* use SOCK_STREAM rather than ai_socktype: some getaddrinfo | ||
1998 | * implementations do not set ai_socktype, e.g. RHL6.2. */ | ||
1999 | fd = socket(domain, ctype, protocol); | ||
2000 | if ( (-1 == fd) && (EINVAL == errno) && (0 != sock_cloexec) ) | ||
2001 | { | ||
2002 | sock_cloexec = 0; | ||
2003 | fd = socket(domain, type, protocol); | ||
2004 | } | ||
2005 | if (-1 == fd) | ||
2006 | return -1; | ||
2007 | if (0 != sock_cloexec) | ||
2008 | return fd; /* this is it */ | ||
2009 | /* flag was not set during 'socket' call, let's try setting it manually */ | ||
2010 | flags = fcntl (fd, F_GETFD); | ||
2011 | if (flags < 0) | ||
2012 | { | ||
2013 | #if HAVE_MESSAGES | ||
2014 | FPRINTF(stderr, "Failed to get socket options to make socket non-inheritable: %s\n", | ||
2015 | STRERROR (errno)); | ||
2016 | #endif | ||
2017 | return fd; /* good luck */ | ||
2018 | } | ||
2019 | if (flags == (flags | FD_CLOEXEC)) | ||
2020 | return fd; /* already set */ | ||
2021 | flags |= FD_CLOEXEC; | ||
2022 | if (0 != fcntl (fd, F_SETFD, flags)) | ||
2023 | { | ||
2024 | #if HAVE_MESSAGES | ||
2025 | FPRINTF(stderr, "Failed to make socket non-inheritable: %s\n", | ||
2026 | STRERROR (errno)); | ||
2027 | #endif | ||
2028 | return fd; /* good luck */ | ||
2029 | } | ||
2030 | return fd; | ||
2031 | } | ||
2032 | |||
2033 | |||
2034 | /** | ||
1950 | * Start a webserver on the given port. | 2035 | * Start a webserver on the given port. |
1951 | * | 2036 | * |
1952 | * @param port port to bind to | 2037 | * @param port port to bind to |
@@ -2148,7 +2233,7 @@ MHD_start_daemon_va (unsigned int options, | |||
2148 | { | 2233 | { |
2149 | if ((options & MHD_USE_IPv6) != 0) | 2234 | if ((options & MHD_USE_IPv6) != 0) |
2150 | #if HAVE_INET6 | 2235 | #if HAVE_INET6 |
2151 | socket_fd = SOCKET (PF_INET6, SOCK_STREAM, 0); | 2236 | socket_fd = create_socket (PF_INET6, SOCK_STREAM, 0); |
2152 | #else | 2237 | #else |
2153 | { | 2238 | { |
2154 | #if HAVE_MESSAGES | 2239 | #if HAVE_MESSAGES |
@@ -2159,7 +2244,7 @@ MHD_start_daemon_va (unsigned int options, | |||
2159 | } | 2244 | } |
2160 | #endif | 2245 | #endif |
2161 | else | 2246 | else |
2162 | socket_fd = SOCKET (PF_INET, SOCK_STREAM, 0); | 2247 | socket_fd = create_socket (PF_INET, SOCK_STREAM, 0); |
2163 | if (socket_fd == -1) | 2248 | if (socket_fd == -1) |
2164 | { | 2249 | { |
2165 | #if HAVE_MESSAGES | 2250 | #if HAVE_MESSAGES |
@@ -2358,7 +2443,7 @@ MHD_start_daemon_va (unsigned int options, | |||
2358 | sk_flags = fcntl (socket_fd, F_GETFL); | 2443 | sk_flags = fcntl (socket_fd, F_GETFL); |
2359 | if (sk_flags < 0) | 2444 | if (sk_flags < 0) |
2360 | goto thread_failed; | 2445 | goto thread_failed; |
2361 | if (fcntl (socket_fd, F_SETFL, sk_flags | O_NONBLOCK) < 0) | 2446 | if (0 != fcntl (socket_fd, F_SETFL, sk_flags | O_NONBLOCK)) |
2362 | goto thread_failed; | 2447 | goto thread_failed; |
2363 | #else | 2448 | #else |
2364 | sk_flags = 1; | 2449 | sk_flags = 1; |