Skip to content
This repository has been archived by the owner on Jun 30, 2021. It is now read-only.

issue#6: fix various potential socket leaks. #8

Merged
merged 3 commits into from
May 23, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 80 additions & 37 deletions evhtp.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,6 @@ htp_log_connection(evhtp_connection_t * c)

#endif




static int htp__request_parse_start_(htparser * p);
static int htp__request_parse_host_(htparser * p, const char * data, size_t len);
static int htp__request_parse_port_(htparser * p, const char * data, size_t len);
Expand Down Expand Up @@ -3571,11 +3568,9 @@ int
evhtp_accept_socket(evhtp_t * htp, evutil_socket_t sock, int backlog)
{
int on = 1;
int res = 0;
int err = 1;

evhtp_assert(htp != NULL);

if (sock == -1)
if (htp == NULL || sock == -1)
{
return -1;
}
Expand All @@ -3584,7 +3579,7 @@ evhtp_accept_socket(evhtp_t * htp, evutil_socket_t sock, int backlog)
#if defined SO_REUSEPORT
if (htp->enable_reuseport)
{
if ((res = setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (void *)&on, sizeof(on)) != 0))
if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (void *)&on, sizeof(on)) == -1)
{
break;
}
Expand All @@ -3594,7 +3589,7 @@ evhtp_accept_socket(evhtp_t * htp, evutil_socket_t sock, int backlog)
#if defined TCP_NODELAY
if (htp->enable_nodelay == 1)
{
if ((res = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void *)&on, sizeof(on))) != 0)
if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void *)&on, sizeof(on)) == -1)
{
break;
}
Expand All @@ -3604,7 +3599,7 @@ evhtp_accept_socket(evhtp_t * htp, evutil_socket_t sock, int backlog)
#if defined TCP_DEFER_ACCEPT
if (htp->enable_defer_accept == 1)
{
if ((res = setsockopt(sock, IPPROTO_TCP, TCP_DEFER_ACCEPT, (void *)&on, sizeof(on))) != 0)
if (setsockopt(sock, IPPROTO_TCP, TCP_DEFER_ACCEPT, (void *)&on, sizeof(on)) == -1)
{
break;
}
Expand All @@ -3617,7 +3612,7 @@ evhtp_accept_socket(evhtp_t * htp, evutil_socket_t sock, int backlog)

if (htp->server == NULL)
{
return -1;
break;
}

#ifndef EVHTP_DISABLE_SSL
Expand All @@ -3635,61 +3630,112 @@ evhtp_accept_socket(evhtp_t * htp, evutil_socket_t sock, int backlog)
}
}
#endif
err = 0;
} while (0);
return res;

if (err == 1)
{
if (htp->server != NULL)
{
evhtp_safe_free(htp->server, evconnlistener_free);
}

return -1;
}

return 0;
} /* evhtp_accept_socket */

int
evhtp_bind_sockaddr(evhtp_t * htp, struct sockaddr * sa, size_t sin_len, int backlog)
{
evutil_socket_t fd = -1;
int on = 1;
int error = 1;

if (htp == NULL)
{
return -1;
}

/* XXX: API's should not set signals */
#ifndef WIN32
signal(SIGPIPE, SIG_IGN);
#endif
evutil_socket_t fd;
int on = 1;

fd = socket(sa->sa_family, SOCK_STREAM, 0);
evhtp_errno_assert(fd != -1);
do {
if ((fd = socket(sa->sa_family, SOCK_STREAM, 0)) == -1)
{
return -1;
}


evutil_make_socket_closeonexec(fd);
evutil_make_socket_nonblocking(fd);
evutil_make_socket_closeonexec(fd);
evutil_make_socket_nonblocking(fd);

setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on));
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on));
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on)) == -1)
{
break;
}

if (sa->sa_family == AF_INET6)
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)) == -1)
{
break;
}

if (sa->sa_family == AF_INET6)
{
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) == -1)
{
break;
}
}

if (bind(fd, sa, sin_len) == -1)
{
break;
}

error = 0;
} while (0);


if (error == 1)
{
int rc;
if (fd != -1)
{
evutil_closesocket(fd);
}

rc = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
evhtp_errno_assert(rc != -1);
return -1;
}

if (bind(fd, sa, sin_len) == -1)
if (evhtp_accept_socket(htp, fd, backlog) == -1)
{
/* accept_socket() does not close the descriptor
* on error, but this function does.
*/
evutil_closesocket(fd);

return -1;
}

return evhtp_accept_socket(htp, fd, backlog);
return 0;
} /* evhtp_bind_sockaddr */

int
evhtp_bind_socket(evhtp_t * htp, const char * baddr, uint16_t port, int backlog)
{
#ifndef NO_SYS_UN
struct sockaddr_un sun;
struct sockaddr_un sun = { 0 };
#endif
struct sockaddr_in6 sin6;
struct sockaddr_in sin;
struct sockaddr * sa;
struct sockaddr_in6 sin6 = { 0 };
struct sockaddr_in sin = { 0 };
size_t sin_len;

memset(&sin, 0, sizeof(sin));

if (!strncmp(baddr, "ipv6:", 5))
{
memset(&sin6, 0, sizeof(sin6));

baddr += 5;
sin_len = sizeof(struct sockaddr_in6);
sin6.sin6_port = htons(port);
Expand All @@ -3707,8 +3753,6 @@ evhtp_bind_socket(evhtp_t * htp, const char * baddr, uint16_t port, int backlog)
return -1;
}

memset(&sun, 0, sizeof(sun));

sin_len = sizeof(struct sockaddr_un);
sun.sun_family = AF_UNIX;

Expand All @@ -3726,7 +3770,6 @@ evhtp_bind_socket(evhtp_t * htp, const char * baddr, uint16_t port, int backlog)
}

sin_len = sizeof(struct sockaddr_in);

sin.sin_family = AF_INET;
sin.sin_port = htons(port);
sin.sin_addr.s_addr = inet_addr(baddr);
Expand Down Expand Up @@ -4996,6 +5039,7 @@ evhtp_make_request(evhtp_connection_t * c, evhtp_request_t * r,

evhtp_headers_for_each(r->headers_out, htp__create_headers_, obuf);
evbuffer_add_reference(obuf, "\r\n", 2, NULL, NULL);

if (evbuffer_get_length(r->buffer_out))
{
evbuffer_add_buffer(obuf, r->buffer_out);
Expand All @@ -5009,4 +5053,3 @@ evhtp_request_status(evhtp_request_t * r)
{
return htparser_get_status(r->conn->parser);
}

3 changes: 3 additions & 0 deletions evhtp.h
Original file line number Diff line number Diff line change
Expand Up @@ -845,6 +845,9 @@ EVHTP_EXPORT void evhtp_unbind_socket(evhtp_t * htp);
* @brief create the listener plus setup various options with an already-bound
* socket.
*
* @note Since the file descriptor is passed to the function, it will not
* attempt to close it if an error occurs.
*
* @param htp
* @param sock
* @param backlog
Expand Down