aboutsummaryrefslogtreecommitdiff
path: root/src/lib/net
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/net')
-rw-r--r--src/lib/net/.may_include6
-rw-r--r--src/lib/net/address.c26
-rw-r--r--src/lib/net/alertsock.h2
-rw-r--r--src/lib/net/buffers_net.c136
-rw-r--r--src/lib/net/buffers_net.h9
-rw-r--r--src/lib/net/gethostname.h2
-rw-r--r--src/lib/net/inaddr.c8
-rw-r--r--src/lib/net/inaddr.h2
-rw-r--r--src/lib/net/inaddr_st.h2
-rw-r--r--src/lib/net/include.am4
-rw-r--r--src/lib/net/nettypes.h2
-rw-r--r--src/lib/net/network_sys.c44
-rw-r--r--src/lib/net/network_sys.h14
-rw-r--r--src/lib/net/resolve.c15
-rw-r--r--src/lib/net/resolve.h4
-rw-r--r--src/lib/net/socket.c37
-rw-r--r--src/lib/net/socket.h3
-rw-r--r--src/lib/net/socketpair.c11
-rw-r--r--src/lib/net/socketpair.h2
-rw-r--r--src/lib/net/socks5_status.h2
20 files changed, 270 insertions, 61 deletions
diff --git a/src/lib/net/.may_include b/src/lib/net/.may_include
index 13b209bbed..e4368f799b 100644
--- a/src/lib/net/.may_include
+++ b/src/lib/net/.may_include
@@ -1,8 +1,9 @@
orconfig.h
-siphash.h
-ht.h
+ext/siphash.h
+ext/ht.h
lib/arch/*.h
+lib/buf/*.h
lib/cc/*.h
lib/container/*.h
lib/ctime/*.h
@@ -11,5 +12,6 @@ lib/lock/*.h
lib/log/*.h
lib/net/*.h
lib/string/*.h
+lib/subsys/*.h
lib/testsupport/*.h
lib/malloc/*.h \ No newline at end of file
diff --git a/src/lib/net/address.c b/src/lib/net/address.c
index 076ca3eb34..2cd193cf1b 100644
--- a/src/lib/net/address.c
+++ b/src/lib/net/address.c
@@ -40,6 +40,7 @@
#include "lib/net/address.h"
#include "lib/net/socket.h"
+#include "lib/cc/ctassert.h"
#include "lib/container/smartlist.h"
#include "lib/ctime/di_ops.h"
#include "lib/log/log.h"
@@ -52,7 +53,7 @@
#include "lib/string/printf.h"
#include "lib/string/util_string.h"
-#include "siphash.h"
+#include "ext/siphash.h"
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
@@ -98,6 +99,7 @@
#if AF_UNSPEC != 0
#error We rely on AF_UNSPEC being 0. Let us know about your platform, please!
#endif
+CTASSERT(AF_UNSPEC == 0);
/** Convert the tor_addr_t in <b>a</b>, with port in <b>port</b>, into a
* sockaddr object in *<b>sa_out</b> of object size <b>len</b>. If not enough
@@ -337,7 +339,7 @@ tor_addr_to_str(char *dest, const tor_addr_t *addr, size_t len, int decorate)
break;
case AF_INET6:
/* Shortest addr [ :: ] + \0 */
- if (len < (3 + (decorate ? 2 : 0)))
+ if (len < (3u + (decorate ? 2 : 0)))
return NULL;
if (decorate)
@@ -1199,14 +1201,22 @@ tor_addr_parse(tor_addr_t *addr, const char *src)
int result;
struct in_addr in_tmp;
struct in6_addr in6_tmp;
+ int brackets_detected = 0;
+
tor_assert(addr && src);
- if (src[0] == '[' && src[1])
+
+ size_t len = strlen(src);
+
+ if (len && src[0] == '[' && src[len - 1] == ']') {
+ brackets_detected = 1;
src = tmp = tor_strndup(src+1, strlen(src)-2);
+ }
if (tor_inet_pton(AF_INET6, src, &in6_tmp) > 0) {
result = AF_INET6;
tor_addr_from_in6(addr, &in6_tmp);
- } else if (tor_inet_pton(AF_INET, src, &in_tmp) > 0) {
+ } else if (!brackets_detected &&
+ tor_inet_pton(AF_INET, src, &in_tmp) > 0) {
result = AF_INET;
tor_addr_from_in(addr, &in_tmp);
} else {
@@ -2018,8 +2028,12 @@ string_is_valid_nonrfc_hostname(const char *string)
smartlist_split_string(components,string,".",0,0);
- if (BUG(smartlist_len(components) == 0))
- return 0; // LCOV_EXCL_LINE should be impossible given the earlier checks.
+ if (BUG(smartlist_len(components) == 0)) {
+ // LCOV_EXCL_START should be impossible given the earlier checks.
+ smartlist_free(components);
+ return 0;
+ // LCOV_EXCL_STOP
+ }
/* Allow a single terminating '.' used rarely to indicate domains
* are FQDNs rather than relative. */
diff --git a/src/lib/net/alertsock.h b/src/lib/net/alertsock.h
index c45f42be81..4d0d0dd57c 100644
--- a/src/lib/net/alertsock.h
+++ b/src/lib/net/alertsock.h
@@ -42,4 +42,4 @@ typedef struct alert_sockets_t {
int alert_sockets_create(alert_sockets_t *socks_out, uint32_t flags);
void alert_sockets_close(alert_sockets_t *socks);
-#endif
+#endif /* !defined(TOR_ALERTSOCK_H) */
diff --git a/src/lib/net/buffers_net.c b/src/lib/net/buffers_net.c
index 3eb0a033d5..cfe1a7dc26 100644
--- a/src/lib/net/buffers_net.c
+++ b/src/lib/net/buffers_net.c
@@ -11,7 +11,7 @@
#define BUFFERS_PRIVATE
#include "lib/net/buffers_net.h"
-#include "lib/container/buffers.h"
+#include "lib/buf/buffers.h"
#include "lib/log/log.h"
#include "lib/log/util_bug.h"
#include "lib/net/nettypes.h"
@@ -22,6 +22,10 @@
#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
#ifdef PARANOIA
/** Helper: If PARANOIA is defined, assert that the buffer in local variable
* <b>buf</b> is well-formed. */
@@ -30,27 +34,36 @@
#define check() STMT_NIL
#endif /* defined(PARANOIA) */
-/** Read up to <b>at_most</b> bytes from the socket <b>fd</b> into
+/** Read up to <b>at_most</b> bytes from the file descriptor <b>fd</b> into
* <b>chunk</b> (which must be on <b>buf</b>). If we get an EOF, set
- * *<b>reached_eof</b> to 1. Return -1 on error, 0 on eof or blocking,
- * and the number of bytes read otherwise. */
+ * *<b>reached_eof</b> to 1. Uses <b>tor_socket_recv()</b> iff <b>is_socket</b>
+ * is true, otherwise it uses <b>read()</b>. Return -1 on error (and sets
+ * *<b>error</b> to errno), 0 on eof or blocking, and the number of bytes read
+ * otherwise. */
static inline int
read_to_chunk(buf_t *buf, chunk_t *chunk, tor_socket_t fd, size_t at_most,
- int *reached_eof, int *socket_error)
+ int *reached_eof, int *error, bool is_socket)
{
ssize_t read_result;
if (at_most > CHUNK_REMAINING_CAPACITY(chunk))
at_most = CHUNK_REMAINING_CAPACITY(chunk);
- read_result = tor_socket_recv(fd, CHUNK_WRITE_PTR(chunk), at_most, 0);
+
+ if (is_socket)
+ read_result = tor_socket_recv(fd, CHUNK_WRITE_PTR(chunk), at_most, 0);
+ else
+ read_result = read(fd, CHUNK_WRITE_PTR(chunk), at_most);
if (read_result < 0) {
- int e = tor_socket_errno(fd);
+ int e = is_socket ? tor_socket_errno(fd) : errno;
+
if (!ERRNO_IS_EAGAIN(e)) { /* it's a real error */
#ifdef _WIN32
if (e == WSAENOBUFS)
- log_warn(LD_NET,"recv() failed: WSAENOBUFS. Not enough ram?");
+ log_warn(LD_NET, "%s() failed: WSAENOBUFS. Not enough ram?",
+ is_socket ? "recv" : "read");
#endif
- *socket_error = e;
+ if (error)
+ *error = e;
return -1;
}
return 0; /* would block. */
@@ -68,16 +81,17 @@ read_to_chunk(buf_t *buf, chunk_t *chunk, tor_socket_t fd, size_t at_most,
}
}
-/** Read from socket <b>s</b>, writing onto end of <b>buf</b>. Read at most
- * <b>at_most</b> bytes, growing the buffer as necessary. If recv() returns 0
- * (because of EOF), set *<b>reached_eof</b> to 1 and return 0. Return -1 on
- * error; else return the number of bytes read.
+/** Read from file descriptor <b>fd</b>, writing onto end of <b>buf</b>. Read
+ * at most <b>at_most</b> bytes, growing the buffer as necessary. If recv()
+ * returns 0 (because of EOF), set *<b>reached_eof</b> to 1 and return 0.
+ * Return -1 on error; else return the number of bytes read.
*/
/* XXXX indicate "read blocked" somehow? */
-int
-buf_read_from_socket(buf_t *buf, tor_socket_t s, size_t at_most,
- int *reached_eof,
- int *socket_error)
+static int
+buf_read_from_fd(buf_t *buf, int fd, size_t at_most,
+ int *reached_eof,
+ int *socket_error,
+ bool is_socket)
{
/* XXXX It's stupid to overload the return values for these functions:
* "error status" and "number of bytes read" are not mutually exclusive.
@@ -87,7 +101,7 @@ buf_read_from_socket(buf_t *buf, tor_socket_t s, size_t at_most,
check();
tor_assert(reached_eof);
- tor_assert(SOCKET_OK(s));
+ tor_assert(SOCKET_OK(fd));
if (BUG(buf->datalen >= INT_MAX))
return -1;
@@ -108,7 +122,8 @@ buf_read_from_socket(buf_t *buf, tor_socket_t s, size_t at_most,
readlen = cap;
}
- r = read_to_chunk(buf, chunk, s, readlen, reached_eof, socket_error);
+ r = read_to_chunk(buf, chunk, fd, readlen,
+ reached_eof, socket_error, is_socket);
check();
if (r < 0)
return r; /* Error */
@@ -122,22 +137,27 @@ buf_read_from_socket(buf_t *buf, tor_socket_t s, size_t at_most,
}
/** Helper for buf_flush_to_socket(): try to write <b>sz</b> bytes from chunk
- * <b>chunk</b> of buffer <b>buf</b> onto socket <b>s</b>. On success, deduct
- * the bytes written from *<b>buf_flushlen</b>. Return the number of bytes
- * written on success, 0 on blocking, -1 on failure.
+ * <b>chunk</b> of buffer <b>buf</b> onto file descriptor <b>fd</b>. On
+ * success, deduct the bytes written from *<b>buf_flushlen</b>. Return the
+ * number of bytes written on success, 0 on blocking, -1 on failure.
*/
static inline int
-flush_chunk(tor_socket_t s, buf_t *buf, chunk_t *chunk, size_t sz,
- size_t *buf_flushlen)
+flush_chunk(tor_socket_t fd, buf_t *buf, chunk_t *chunk, size_t sz,
+ size_t *buf_flushlen, bool is_socket)
{
ssize_t write_result;
if (sz > chunk->datalen)
sz = chunk->datalen;
- write_result = tor_socket_send(s, chunk->data, sz, 0);
+
+ if (is_socket)
+ write_result = tor_socket_send(fd, chunk->data, sz, 0);
+ else
+ write_result = write(fd, chunk->data, sz);
if (write_result < 0) {
- int e = tor_socket_errno(s);
+ int e = is_socket ? tor_socket_errno(fd) : errno;
+
if (!ERRNO_IS_EAGAIN(e)) { /* it's a real error */
#ifdef _WIN32
if (e == WSAENOBUFS)
@@ -155,15 +175,15 @@ flush_chunk(tor_socket_t s, buf_t *buf, chunk_t *chunk, size_t sz,
}
}
-/** Write data from <b>buf</b> to the socket <b>s</b>. Write at most
+/** Write data from <b>buf</b> to the file descriptor <b>fd</b>. Write at most
* <b>sz</b> bytes, decrement *<b>buf_flushlen</b> by
* the number of bytes actually written, and remove the written bytes
* from the buffer. Return the number of bytes written on success,
* -1 on failure. Return 0 if write() would block.
*/
-int
-buf_flush_to_socket(buf_t *buf, tor_socket_t s, size_t sz,
- size_t *buf_flushlen)
+static int
+buf_flush_to_fd(buf_t *buf, int fd, size_t sz,
+ size_t *buf_flushlen, bool is_socket)
{
/* XXXX It's stupid to overload the return values for these functions:
* "error status" and "number of bytes flushed" are not mutually exclusive.
@@ -171,7 +191,7 @@ buf_flush_to_socket(buf_t *buf, tor_socket_t s, size_t sz,
int r;
size_t flushed = 0;
tor_assert(buf_flushlen);
- tor_assert(SOCKET_OK(s));
+ tor_assert(SOCKET_OK(fd));
if (BUG(*buf_flushlen > buf->datalen)) {
*buf_flushlen = buf->datalen;
}
@@ -188,7 +208,7 @@ buf_flush_to_socket(buf_t *buf, tor_socket_t s, size_t sz,
else
flushlen0 = buf->head->datalen;
- r = flush_chunk(s, buf, buf->head, flushlen0, buf_flushlen);
+ r = flush_chunk(fd, buf, buf->head, flushlen0, buf_flushlen, is_socket);
check();
if (r < 0)
return r;
@@ -200,3 +220,55 @@ buf_flush_to_socket(buf_t *buf, tor_socket_t s, size_t sz,
tor_assert(flushed < INT_MAX);
return (int)flushed;
}
+
+/** Write data from <b>buf</b> to the socket <b>s</b>. Write at most
+ * <b>sz</b> bytes, decrement *<b>buf_flushlen</b> by
+ * the number of bytes actually written, and remove the written bytes
+ * from the buffer. Return the number of bytes written on success,
+ * -1 on failure. Return 0 if write() would block.
+ */
+int
+buf_flush_to_socket(buf_t *buf, tor_socket_t s, size_t sz,
+ size_t *buf_flushlen)
+{
+ return buf_flush_to_fd(buf, s, sz, buf_flushlen, true);
+}
+
+/** Read from socket <b>s</b>, writing onto end of <b>buf</b>. Read at most
+ * <b>at_most</b> bytes, growing the buffer as necessary. If recv() returns 0
+ * (because of EOF), set *<b>reached_eof</b> to 1 and return 0. Return -1 on
+ * error; else return the number of bytes read.
+ */
+int
+buf_read_from_socket(buf_t *buf, tor_socket_t s, size_t at_most,
+ int *reached_eof,
+ int *socket_error)
+{
+ return buf_read_from_fd(buf, s, at_most, reached_eof, socket_error, true);
+}
+
+/** Write data from <b>buf</b> to the pipe <b>fd</b>. Write at most
+ * <b>sz</b> bytes, decrement *<b>buf_flushlen</b> by
+ * the number of bytes actually written, and remove the written bytes
+ * from the buffer. Return the number of bytes written on success,
+ * -1 on failure. Return 0 if write() would block.
+ */
+int
+buf_flush_to_pipe(buf_t *buf, int fd, size_t sz,
+ size_t *buf_flushlen)
+{
+ return buf_flush_to_fd(buf, fd, sz, buf_flushlen, false);
+}
+
+/** Read from pipe <b>fd</b>, writing onto end of <b>buf</b>. Read at most
+ * <b>at_most</b> bytes, growing the buffer as necessary. If read() returns 0
+ * (because of EOF), set *<b>reached_eof</b> to 1 and return 0. Return -1 on
+ * error; else return the number of bytes read.
+ */
+int
+buf_read_from_pipe(buf_t *buf, int fd, size_t at_most,
+ int *reached_eof,
+ int *socket_error)
+{
+ return buf_read_from_fd(buf, fd, at_most, reached_eof, socket_error, false);
+}
diff --git a/src/lib/net/buffers_net.h b/src/lib/net/buffers_net.h
index 5f69bebedf..5058dd0a26 100644
--- a/src/lib/net/buffers_net.h
+++ b/src/lib/net/buffers_net.h
@@ -24,4 +24,11 @@ int buf_read_from_socket(struct buf_t *buf, tor_socket_t s, size_t at_most,
int buf_flush_to_socket(struct buf_t *buf, tor_socket_t s, size_t sz,
size_t *buf_flushlen);
-#endif /* !defined(TOR_BUFFERS_H) */
+int buf_read_from_pipe(struct buf_t *buf, int fd, size_t at_most,
+ int *reached_eof,
+ int *socket_error);
+
+int buf_flush_to_pipe(struct buf_t *buf, int fd, size_t sz,
+ size_t *buf_flushlen);
+
+#endif /* !defined(TOR_BUFFERS_NET_H) */
diff --git a/src/lib/net/gethostname.h b/src/lib/net/gethostname.h
index 69b0528bc0..b3b77b0589 100644
--- a/src/lib/net/gethostname.h
+++ b/src/lib/net/gethostname.h
@@ -16,4 +16,4 @@
MOCK_DECL(int,tor_gethostname,(char *name, size_t namelen));
-#endif
+#endif /* !defined(TOR_GETHOSTNAME_H) */
diff --git a/src/lib/net/inaddr.c b/src/lib/net/inaddr.c
index 1a2406ce5f..d9ae7cd562 100644
--- a/src/lib/net/inaddr.c
+++ b/src/lib/net/inaddr.c
@@ -168,6 +168,13 @@ tor_inet_pton(int af, const char *src, void *dst)
if (af == AF_INET) {
return tor_inet_aton(src, dst);
} else if (af == AF_INET6) {
+ ssize_t len = strlen(src);
+
+ /* Reject if src has needless trailing ':'. */
+ if (len > 2 && src[len - 1] == ':' && src[len - 2] != ':') {
+ return 0;
+ }
+
struct in6_addr *out = dst;
uint16_t words[8];
int gapPos = -1, i, setWords=0;
@@ -207,7 +214,6 @@ tor_inet_pton(int af, const char *src, void *dst)
return 0;
if (TOR_ISXDIGIT(*src)) {
char *next;
- ssize_t len;
long r = strtol(src, &next, 16);
if (next == NULL || next == src) {
/* The 'next == src' error case can happen on versions of openbsd
diff --git a/src/lib/net/inaddr.h b/src/lib/net/inaddr.h
index 36352b65ea..602573944c 100644
--- a/src/lib/net/inaddr.h
+++ b/src/lib/net/inaddr.h
@@ -24,4 +24,4 @@ int tor_inet_ntoa(const struct in_addr *in, char *buf, size_t buf_len);
const char *tor_inet_ntop(int af, const void *src, char *dst, size_t len);
int tor_inet_pton(int af, const char *src, void *dst);
-#endif
+#endif /* !defined(TOR_INADDR_H) */
diff --git a/src/lib/net/inaddr_st.h b/src/lib/net/inaddr_st.h
index 806f2c096a..230f29a63a 100644
--- a/src/lib/net/inaddr_st.h
+++ b/src/lib/net/inaddr_st.h
@@ -104,4 +104,4 @@ struct sockaddr_in6 {
};
#endif /* !defined(HAVE_STRUCT_SOCKADDR_IN6) */
-#endif /* TOR_INADDR_ST_H */
+#endif /* !defined(TOR_INADDR_ST_H) */
diff --git a/src/lib/net/include.am b/src/lib/net/include.am
index ff0967e786..485019f4b7 100644
--- a/src/lib/net/include.am
+++ b/src/lib/net/include.am
@@ -5,12 +5,14 @@ if UNITTESTS_ENABLED
noinst_LIBRARIES += src/lib/libtor-net-testing.a
endif
+# ADD_C_FILE: INSERT SOURCES HERE.
src_lib_libtor_net_a_SOURCES = \
src/lib/net/address.c \
src/lib/net/alertsock.c \
src/lib/net/buffers_net.c \
src/lib/net/gethostname.c \
src/lib/net/inaddr.c \
+ src/lib/net/network_sys.c \
src/lib/net/resolve.c \
src/lib/net/socket.c \
src/lib/net/socketpair.c
@@ -20,6 +22,7 @@ src_lib_libtor_net_testing_a_SOURCES = \
src_lib_libtor_net_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS)
src_lib_libtor_net_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+# ADD_C_FILE: INSERT HEADERS HERE.
noinst_HEADERS += \
src/lib/net/address.h \
src/lib/net/alertsock.h \
@@ -28,6 +31,7 @@ noinst_HEADERS += \
src/lib/net/inaddr.h \
src/lib/net/inaddr_st.h \
src/lib/net/nettypes.h \
+ src/lib/net/network_sys.h \
src/lib/net/resolve.h \
src/lib/net/socket.h \
src/lib/net/socketpair.h \
diff --git a/src/lib/net/nettypes.h b/src/lib/net/nettypes.h
index 6209bbe18a..0eb352c657 100644
--- a/src/lib/net/nettypes.h
+++ b/src/lib/net/nettypes.h
@@ -41,4 +41,4 @@ typedef int socklen_t;
#define TOR_INVALID_SOCKET (-1)
#endif /* defined(_WIN32) */
-#endif
+#endif /* !defined(TOR_NET_TYPES_H) */
diff --git a/src/lib/net/network_sys.c b/src/lib/net/network_sys.c
new file mode 100644
index 0000000000..9dfdb2b45a
--- /dev/null
+++ b/src/lib/net/network_sys.c
@@ -0,0 +1,44 @@
+/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file network_sys.c
+ * \brief Subsystem object for networking setup.
+ **/
+
+#include "orconfig.h"
+#include "lib/subsys/subsys.h"
+#include "lib/net/network_sys.h"
+#include "lib/net/resolve.h"
+#include "lib/net/socket.h"
+
+#ifdef _WIN32
+#include <winsock2.h>
+#include <windows.h>
+#endif
+
+static int
+subsys_network_initialize(void)
+{
+ if (network_init() < 0)
+ return -1;
+
+ return 0;
+}
+
+static void
+subsys_network_shutdown(void)
+{
+#ifdef _WIN32
+ WSACleanup();
+#endif
+ tor_free_getaddrinfo_cache();
+}
+
+const subsys_fns_t sys_network = {
+ .name = "network",
+ .level = -90,
+ .supported = true,
+ .initialize = subsys_network_initialize,
+ .shutdown = subsys_network_shutdown,
+};
diff --git a/src/lib/net/network_sys.h b/src/lib/net/network_sys.h
new file mode 100644
index 0000000000..43e62592ca
--- /dev/null
+++ b/src/lib/net/network_sys.h
@@ -0,0 +1,14 @@
+/* Copyright (c) 2018-2019, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file log_network.h
+ * \brief Declare subsystem object for the network module.
+ **/
+
+#ifndef TOR_NETWORK_SYS_H
+#define TOR_NETWORK_SYS_H
+
+extern const struct subsys_fns_t sys_network;
+
+#endif /* !defined(TOR_NETWORK_SYS_H) */
diff --git a/src/lib/net/resolve.c b/src/lib/net/resolve.c
index 8cee29df37..2dda491d14 100644
--- a/src/lib/net/resolve.c
+++ b/src/lib/net/resolve.c
@@ -16,8 +16,8 @@
#include "lib/string/parse_int.h"
#include "lib/string/util_string.h"
-#include "siphash.h"
-#include "ht.h"
+#include "ext/siphash.h"
+#include "ext/ht.h"
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
@@ -421,4 +421,13 @@ tor_make_getaddrinfo_cache_active(void)
{
sandbox_getaddrinfo_is_active = 1;
}
-#endif
+#else /* !(defined(USE_SANDBOX_GETADDRINFO)) */
+void
+sandbox_disable_getaddrinfo_cache(void)
+{
+}
+void
+tor_make_getaddrinfo_cache_active(void)
+{
+}
+#endif /* defined(USE_SANDBOX_GETADDRINFO) */
diff --git a/src/lib/net/resolve.h b/src/lib/net/resolve.h
index 47a283c81c..d11c902a91 100644
--- a/src/lib/net/resolve.h
+++ b/src/lib/net/resolve.h
@@ -42,7 +42,6 @@ int tor_getaddrinfo(const char *name, const char *servname,
struct addrinfo **res);
void tor_freeaddrinfo(struct addrinfo *addrinfo);
void tor_free_getaddrinfo_cache(void);
-void tor_make_getaddrinfo_cache_active(void);
#else /* !(defined(USE_SANDBOX_GETADDRINFO)) */
#define tor_getaddrinfo(name, servname, hints, res) \
getaddrinfo((name),(servname), (hints),(res))
@@ -54,5 +53,6 @@ void tor_make_getaddrinfo_cache_active(void);
#endif /* defined(USE_SANDBOX_GETADDRINFO) */
void sandbox_disable_getaddrinfo_cache(void);
+void tor_make_getaddrinfo_cache_active(void);
-#endif
+#endif /* !defined(TOR_RESOLVE_H) */
diff --git a/src/lib/net/socket.c b/src/lib/net/socket.c
index fba90b7506..e824a05045 100644
--- a/src/lib/net/socket.c
+++ b/src/lib/net/socket.c
@@ -31,6 +31,9 @@
#endif
#include <stddef.h>
#include <string.h>
+#ifdef __FreeBSD__
+#include <sys/sysctl.h>
+#endif
/** Called before we make any calls to network-related functions.
* (Some operating systems require their network libraries to be
@@ -60,6 +63,32 @@ network_init(void)
return 0;
}
+/**
+ * Warn the user if any system network parameters should be changed.
+ */
+void
+check_network_configuration(bool server_mode)
+{
+#ifdef __FreeBSD__
+ if (server_mode) {
+ int random_id_state;
+ size_t state_size = sizeof(random_id_state);
+
+ if (sysctlbyname("net.inet.ip.random_id", &random_id_state,
+ &state_size, NULL, 0)) {
+ log_warn(LD_CONFIG,
+ "Failed to figure out if IP ids are randomized.");
+ } else if (random_id_state == 0) {
+ log_warn(LD_CONFIG, "Looks like IP ids are not randomized. "
+ "Please consider setting the net.inet.ip.random_id sysctl, "
+ "so your relay makes it harder to figure out how busy it is.");
+ }
+ }
+#else /* !(defined(__FreeBSD__)) */
+ (void) server_mode;
+#endif /* defined(__FreeBSD__) */
+}
+
/* When set_max_file_sockets() is called, update this with the max file
* descriptor value so we can use it to check the limit when opening a new
* socket. Default value is what Debian sets as the default hard limit. */
@@ -429,7 +458,9 @@ get_n_open_sockets(void)
* localhost is inaccessible (for example, if the networking
* stack is down). And even if it succeeds, the socket pair will not
* be able to read while localhost is down later (the socket pair may
- * even close, depending on OS-specific timeouts).
+ * even close, depending on OS-specific timeouts). The socket pair
+ * should work on IPv4-only, IPv6-only, and dual-stack systems, as long
+ * as they have the standard localhost addresses.
*
* Returns 0 on success and -errno on failure; do not rely on the value
* of errno or WSAGetLastError().
@@ -456,11 +487,11 @@ tor_socketpair(int family, int type, int protocol, tor_socket_t fd[2])
r = socketpair(family, type, protocol, fd);
if (r < 0)
return -errno;
-#else
+#else /* !(defined(HAVE_SOCKETPAIR) && !defined(_WIN32)) */
r = tor_ersatz_socketpair(family, type, protocol, fd);
if (r < 0)
return -r;
-#endif
+#endif /* defined(HAVE_SOCKETPAIR) && !defined(_WIN32) */
#if defined(FD_CLOEXEC)
if (SOCKET_OK(fd[0])) {
diff --git a/src/lib/net/socket.h b/src/lib/net/socket.h
index 0909619510..193ad91e4c 100644
--- a/src/lib/net/socket.h
+++ b/src/lib/net/socket.h
@@ -54,6 +54,7 @@ int tor_addr_from_getsockname(struct tor_addr_t *addr_out, tor_socket_t sock);
int set_socket_nonblocking(tor_socket_t socket);
int tor_socketpair(int family, int type, int protocol, tor_socket_t fd[2]);
int network_init(void);
+void check_network_configuration(bool server_mode);
int get_max_sockets(void);
void set_max_sockets(int);
@@ -115,4 +116,4 @@ const char *tor_socket_strerror(int e);
#define SIO_IDEAL_SEND_BACKLOG_QUERY 0x4004747b
#endif
-#endif
+#endif /* !defined(TOR_SOCKET_H) */
diff --git a/src/lib/net/socketpair.c b/src/lib/net/socketpair.c
index 10eb749735..3be7b26f7f 100644
--- a/src/lib/net/socketpair.c
+++ b/src/lib/net/socketpair.c
@@ -22,11 +22,11 @@
#include <windows.h>
#define socket_errno() (WSAGetLastError())
#define SOCKET_EPROTONOSUPPORT WSAEPROTONOSUPPORT
-#else
+#else /* !(defined(_WIN32)) */
#define closesocket(x) close(x)
#define socket_errno() (errno)
#define SOCKET_EPROTONOSUPPORT EPROTONOSUPPORT
-#endif
+#endif /* defined(_WIN32) */
#ifdef NEED_ERSATZ_SOCKETPAIR
@@ -105,7 +105,12 @@ sockaddr_eq(struct sockaddr *sa1, struct sockaddr *sa2)
/**
* Helper used to implement socketpair on systems that lack it, by
* making a direct connection to localhost.
- */
+ *
+ * See tor_socketpair() for details.
+ *
+ * The direct connection defaults to IPv4, but falls back to IPv6 if
+ * IPv4 is not supported.
+ **/
int
tor_ersatz_socketpair(int family, int type, int protocol, tor_socket_t fd[2])
{
diff --git a/src/lib/net/socketpair.h b/src/lib/net/socketpair.h
index 6be0803881..5820606973 100644
--- a/src/lib/net/socketpair.h
+++ b/src/lib/net/socketpair.h
@@ -16,4 +16,4 @@ int tor_ersatz_socketpair(int family, int type, int protocol,
tor_socket_t fd[2]);
#endif
-#endif
+#endif /* !defined(TOR_SOCKETPAIR_H) */
diff --git a/src/lib/net/socks5_status.h b/src/lib/net/socks5_status.h
index e55242ce66..e55119e0b0 100644
--- a/src/lib/net/socks5_status.h
+++ b/src/lib/net/socks5_status.h
@@ -29,4 +29,4 @@ typedef enum {
SOCKS5_ADDRESS_TYPE_NOT_SUPPORTED = 0x08,
} socks5_reply_status_t;
-#endif
+#endif /* !defined(TOR_SOCKS5_STATUS_H) */