Warn if system capped requested socket buffer sizes.
[tinc] / src / net_socket.c
index a696127..afe349d 100644 (file)
@@ -289,10 +289,44 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
                logger(DEBUG_ALWAYS, LOG_WARNING, "Can't set UDP SO_RCVBUF to %i: %s", udp_rcvbuf, sockstrerror(sockerrno));
        }
 
+       {
+               // The system may cap the requested buffer size.
+               // Read back the value and check if it is now as requested.
+               int udp_rcvbuf_actual = -1;
+               socklen_t optlen = sizeof(udp_rcvbuf_actual);
+
+               if(getsockopt(nfd, SOL_SOCKET, SO_RCVBUF, (void *)&udp_rcvbuf_actual, &optlen)) {
+                       logger(DEBUG_ALWAYS, LOG_WARNING, "Can't read back UDP SO_RCVBUF: %s", sockstrerror(sockerrno));
+               } else if(optlen != sizeof(udp_rcvbuf_actual)) {
+                       logger(DEBUG_ALWAYS, LOG_WARNING, "Can't read back UDP SO_RCVBUF: Unexpected returned optlen %jd", (intmax_t) optlen);
+               } else {
+                       if(udp_rcvbuf_actual != udp_rcvbuf) {
+                               logger(DEBUG_ALWAYS, LOG_WARNING, "Can't set UDP SO_RCVBUF to %i, the system set it to %i instead", udp_rcvbuf, udp_rcvbuf_actual);
+                       }
+               }
+       }
+
        if(udp_sndbuf && setsockopt(nfd, SOL_SOCKET, SO_SNDBUF, (void *)&udp_sndbuf, sizeof(udp_sndbuf))) {
                logger(DEBUG_ALWAYS, LOG_WARNING, "Can't set UDP SO_SNDBUF to %i: %s", udp_sndbuf, sockstrerror(sockerrno));
        }
 
+       {
+               // The system may cap the requested buffer size.
+               // Read back the value and check if it is now as requested.
+               int udp_sndbuf_actual = -1;
+               socklen_t optlen = sizeof(udp_sndbuf_actual);
+
+               if(getsockopt(nfd, SOL_SOCKET, SO_SNDBUF, (void *)&udp_sndbuf_actual, &optlen)) {
+                       logger(DEBUG_ALWAYS, LOG_WARNING, "Can't read back UDP SO_SNDBUF: %s", sockstrerror(sockerrno));
+               } else if(optlen != sizeof(udp_sndbuf_actual)) {
+                       logger(DEBUG_ALWAYS, LOG_WARNING, "Can't read back UDP SO_SNDBUF: Unexpected returned optlen %jd", (intmax_t) optlen);
+               } else {
+                       if(udp_sndbuf_actual != udp_sndbuf) {
+                               logger(DEBUG_ALWAYS, LOG_WARNING, "Can't set UDP SO_SNDBUF to %i, the system set it to %i instead", udp_sndbuf, udp_sndbuf_actual);
+                       }
+               }
+       }
+
 #if defined(IPV6_V6ONLY)
 
        if(sa->sa.sa_family == AF_INET6) {
@@ -527,7 +561,7 @@ bool do_outgoing_connection(outgoing_t *outgoing) {
        int result;
 
 begin:
-       sa = get_recent_address(outgoing->address_cache);
+       sa = get_recent_address(outgoing->node->address_cache);
 
        if(!sa) {
                logger(DEBUG_CONNECTIONS, LOG_ERR, "Could not set up a meta connection to %s", outgoing->node->name);
@@ -632,6 +666,10 @@ void setup_outgoing_connection(outgoing_t *outgoing, bool verbose) {
 
        node_t *n = outgoing->node;
 
+       if(!n->address_cache) {
+               n->address_cache = open_address_cache(n);
+       }
+
        if(n->connection) {
                logger(DEBUG_CONNECTIONS, LOG_INFO, "Already connected to %s", n->name);
 
@@ -643,10 +681,6 @@ void setup_outgoing_connection(outgoing_t *outgoing, bool verbose) {
                }
        }
 
-       if(!outgoing->address_cache) {
-               outgoing->address_cache = open_address_cache(n);
-       }
-
        do_outgoing_connection(outgoing);
        return;
 
@@ -787,11 +821,6 @@ void handle_new_unix_connection(void *data, int flags) {
 
 static void free_outgoing(outgoing_t *outgoing) {
        timeout_del(&outgoing->ev);
-
-       if(outgoing->address_cache) {
-               close_address_cache(outgoing->address_cache);
-       }
-
        free(outgoing);
 }