This repository has been archived by the owner. It is now read-only.
Permalink
Browse files

unix: disable linger for tcp loopback connections

Prevent ephemeral port exhaustion, disable SO_LINGER.
  • Loading branch information...
bnoordhuis committed Dec 10, 2012
1 parent 52c8a86 commit 0e38494aff2b6ef33ddde1e719204d96d0f5def8
Showing with 46 additions and 0 deletions.
  1. +46 −0 src/unix/tcp.c
View
@@ -22,6 +22,7 @@
#include "uv.h"
#include "internal.h"
+#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
@@ -34,6 +35,46 @@ int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* tcp) {
}
+static int is_local_addr4(const struct sockaddr_in* addr) {
+ /* 127.0.0.0/8 */
+ return (ntohl(addr->sin_addr.s_addr) & 0xff000000) == 0x7f000000;
+}
+
+
+static int is_local_addr6(const struct sockaddr_in6* addr) {
+ uint32_t a = ntohl(addr->sin6_addr.s6_addr32[0]);
+ uint32_t b = ntohl(addr->sin6_addr.s6_addr32[1]);
+ uint32_t c = ntohl(addr->sin6_addr.s6_addr32[2]);
+ uint32_t d = ntohl(addr->sin6_addr.s6_addr32[3]);
+
+ /* ::1/128, loopback. */
+ if (a == 0 && b == 0 && c == 0 && d == 1)
+ return 1;
+
+ /* ::ffff:127.0.0.0/104, IPv4-to-IPv6 range. */
+ if (a == 0 && b == 0 && c == 0xffff && (d & 0xff000000) == 0x7f000000)
+ return 1;
+
+ /* fe80::/10, link-local address range. Effectively fe80::/64. */
+ if (a == 0xfe800000 && b == 0)
+ return 1;
+
+ return 0;
+}
+
+
+static int is_local_addr(const struct sockaddr* addr) {
+ if (addr->sa_family == AF_INET)
+ return is_local_addr4((const struct sockaddr_in*) addr);
+
+ if (addr->sa_family == AF_INET6)
+ return is_local_addr6((const struct sockaddr_in6*) addr);
+
+ assert(0);
+ return 0;
+}
+
+
static int maybe_new_socket(uv_tcp_t* handle, int domain, int flags) {
int sockfd;
@@ -113,6 +154,11 @@ static int uv__connect(uv_connect_t* req,
return uv__set_sys_error(handle->loop, errno);
}
+ if (is_local_addr(addr)) {
+ struct linger ll = { 1, 1 };
+ setsockopt(handle->io_watcher.fd, SOL_SOCKET, SO_LINGER, &ll, sizeof(ll));
+ }
+
uv__req_init(handle->loop, req, UV_CONNECT);
req->cb = cb;
req->handle = (uv_stream_t*) handle;

0 comments on commit 0e38494

Please sign in to comment.