]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
use REUSEPORT only for NOLISTEN dispatchers
authorWitold Kręcicki <wpk@isc.org>
Thu, 11 Oct 2018 07:50:31 +0000 (07:50 +0000)
committerWitold Kręcicki <wpk@isc.org>
Tue, 6 Nov 2018 11:25:09 +0000 (11:25 +0000)
lib/dns/dispatch.c
lib/dns/include/dns/dispatch.h
lib/ns/interfacemgr.c

index a3e27e62c30edb9ae36f56c2a7ce60622909ddd7..208d39aa4c8b298a8bebbbf5630e9d0d758f5ca6 100644 (file)
@@ -299,7 +299,8 @@ static isc_result_t get_udpsocket(dns_dispatchmgr_t *mgr,
                                  isc_socketmgr_t *sockmgr,
                                  const isc_sockaddr_t *localaddr,
                                  isc_socket_t **sockp,
-                                 isc_socket_t *dup_socket);
+                                 isc_socket_t *dup_socket,
+                                 bool duponly);
 static isc_result_t dispatch_createudp(dns_dispatchmgr_t *mgr,
                                       isc_socketmgr_t *sockmgr,
                                       isc_taskmgr_t *taskmgr,
@@ -317,7 +318,7 @@ static void qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp);
 static isc_result_t open_socket(isc_socketmgr_t *mgr,
                                const isc_sockaddr_t *local,
                                unsigned int options, isc_socket_t **sockp,
-                               isc_socket_t *dup_socket);
+                               isc_socket_t *dup_socket, bool duponly);
 static bool portavailable(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
                                   isc_sockaddr_t *sockaddrp);
 
@@ -728,7 +729,7 @@ get_dispsocket(dns_dispatch_t *disp, const isc_sockaddr_t *dest,
                if (portentry != NULL)
                        bindoptions |= ISC_SOCKET_REUSEADDRESS;
                result = open_socket(sockmgr, &localaddr, bindoptions, &sock,
-                                    NULL);
+                                    NULL, false);
                if (result == ISC_R_SUCCESS) {
                        if (portentry == NULL) {
                                portentry = new_portentry(disp, port);
@@ -1667,7 +1668,7 @@ destroy_mgr(dns_dispatchmgr_t **mgrp) {
 static isc_result_t
 open_socket(isc_socketmgr_t *mgr, const isc_sockaddr_t *local,
            unsigned int options, isc_socket_t **sockp,
-           isc_socket_t *dup_socket)
+           isc_socket_t *dup_socket, bool duponly)
 {
        isc_socket_t *sock;
        isc_result_t result;
@@ -1677,7 +1678,7 @@ open_socket(isc_socketmgr_t *mgr, const isc_sockaddr_t *local,
                result = isc_socket_open(sock);
                if (result != ISC_R_SUCCESS)
                        return (result);
-       } else if (dup_socket != NULL && !isc_socket_hasreuseport()) {
+       } else if (dup_socket != NULL && (!isc_socket_hasreuseport() || duponly)) {
                result = isc_socket_dup(dup_socket, &sock);
                if (result != ISC_R_SUCCESS)
                        return (result);
@@ -2757,7 +2758,7 @@ dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
 static isc_result_t
 get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp,
              isc_socketmgr_t *sockmgr, const isc_sockaddr_t *localaddr,
-             isc_socket_t **sockp, isc_socket_t *dup_socket)
+             isc_socket_t **sockp, isc_socket_t *dup_socket, bool duponly)
 {
        unsigned int i, j;
        isc_socket_t *held[DNS_DISPATCH_HELD];
@@ -2795,7 +2796,7 @@ get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp,
                        prt = ports[isc_random_uniform(nports)];
                        isc_sockaddr_setport(&localaddr_bound, prt);
                        result = open_socket(sockmgr, &localaddr_bound,
-                                            0, &sock, NULL);
+                                            0, &sock, NULL, false);
                        /*
                         * Continue if the port choosen is already in use
                         * or the OS has reserved it.
@@ -2816,7 +2817,7 @@ get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp,
                /* Allow to reuse address for non-random ports. */
                result = open_socket(sockmgr, localaddr,
                                     ISC_SOCKET_REUSEADDRESS, &sock,
-                                    dup_socket);
+                                    dup_socket, duponly);
 
                if (result == ISC_R_SUCCESS)
                        *sockp = sock;
@@ -2828,7 +2829,7 @@ get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp,
        i = 0;
 
        for (j = 0; j < 0xffffU; j++) {
-               result = open_socket(sockmgr, localaddr, 0, &sock, NULL);
+               result = open_socket(sockmgr, localaddr, 0, &sock, NULL, false);
                if (result != ISC_R_SUCCESS)
                        goto end;
                else if (portavailable(mgr, sock, NULL))
@@ -2873,6 +2874,9 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
        isc_socket_t *sock = NULL;
        int i = 0;
 
+       bool duponly = ((attributes & DNS_DISPATCHATTR_CANREUSE) == 0);
+       /* This is an attribute needed only at creation time */
+       attributes &= ~DNS_DISPATCHATTR_CANREUSE;
        /*
         * dispatch_allocate() checks mgr for us.
         */
@@ -2885,7 +2889,7 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
 
        if ((attributes & DNS_DISPATCHATTR_EXCLUSIVE) == 0) {
                result = get_udpsocket(mgr, disp, sockmgr, localaddr, &sock,
-                                      dup_socket);
+                                      dup_socket, duponly);
                if (result != ISC_R_SUCCESS)
                        goto deallocate_dispatch;
 
@@ -2910,7 +2914,7 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
                 */
                isc_sockaddr_anyofpf(&sa_any, isc_sockaddr_pf(localaddr));
                if (!isc_sockaddr_eqaddr(&sa_any, localaddr)) {
-                       result = open_socket(sockmgr, localaddr, 0, &sock, NULL);
+                       result = open_socket(sockmgr, localaddr, 0, &sock, NULL, false);
                        if (sock != NULL)
                                isc_socket_detach(&sock);
                        if (result != ISC_R_SUCCESS)
index c6293121cd6d3257d8ca36769d27a3410da3954f..56e4ba76a65871934be4bd53820abb3e26814736 100644 (file)
@@ -140,6 +140,7 @@ struct dns_dispatchset {
 #define DNS_DISPATCHATTR_CONNECTED     0x00000080U
 #define DNS_DISPATCHATTR_FIXEDID       0x00000100U
 #define DNS_DISPATCHATTR_EXCLUSIVE     0x00000200U
+#define DNS_DISPATCHATTR_CANREUSE      0x00000400U
 /*@}*/
 
 /*
index 6f1b0d591a6507db253c12bcfd8cc426be9bbd06..adba622d096826d6ff62f1bc33b524a13674a051 100644 (file)
@@ -470,6 +470,7 @@ ns_interface_listenudp(ns_interface_t *ifp) {
        else
                attrs |= DNS_DISPATCHATTR_IPV6;
        attrs |= DNS_DISPATCHATTR_NOLISTEN;
+       attrs |= DNS_DISPATCHATTR_CANREUSE;
        attrmask = 0;
        attrmask |= DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP;
        attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6;