]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Split-Stack enable DNS and http(s)_port sockets.
authorAmos Jeffries <amosjeffries@squid-cache.org>
Sun, 25 Jul 2010 08:04:41 +0000 (02:04 -0600)
committerAmos Jeffries <amosjeffries@squid-cache.org>
Sun, 25 Jul 2010 08:04:41 +0000 (02:04 -0600)
This breaks the DNS sockets into two when split-stack mode is used.
DnsSocketA becomes IPv4-only and DnsSocketB becomes used as IPv6-only.
Without Split-stack mode DnsSocketA is the only one actually used.

NP: comm outgoing socket support is still a blocker on split-stack support.
However this update is required for the upcoming run-time support.

src/cache_cf.cc
src/comm.cc
src/comm_poll.cc
src/comm_select.cc
src/comm_select_win32.cc
src/dns_internal.cc
src/globals.h

index 639efb1eda4556c3ae1d953818772e31c4ddc779..29c9dd5b7be6781de25a0d955546c7b1e01074d2 100644 (file)
@@ -2969,7 +2969,7 @@ parse_http_port_specification(http_port_list * s, char *token)
     if (NULL == host) {
         s->s.SetAnyAddr();
         s->s.SetPort(port);
-        debugs(3, 3, "http(s)_port: found Listen on wildcard address: " << s->s);
+        debugs(3, 3, "http(s)_port: found Listen on wildcard address: *:" << s->s.GetPort() );
     } else if ( s->s = host ) { /* check/parse numeric IPA */
         s->s.SetPort(port);
         debugs(3, 3, "http(s)_port: Listen on Host/IP: " << host << " --> " << s->s);
@@ -3155,10 +3155,64 @@ void
 add_http_port(char *portspec)
 {
     http_port_list *s = create_http_port(portspec);
+    // we may need to merge better of the above returns a list with clones
+    assert(s->next == NULL);
     s->next = Config.Sockaddr.http;
     Config.Sockaddr.http = s;
 }
 
+#if IPV6_SPECIAL_SPLITSTACK
+http_port_list *
+clone_http_port_list(http_port_list *a)
+{
+    http_port_list *b = new http_port_list(a->protocol);
+
+    b->s = a->s;
+    if (a->name)
+        b->name = xstrdup(a->name);
+    if (a->defaultsite)
+        b->defaultsite = xstrdup(a->defaultsite);
+
+    b->intercepted = a->intercepted;
+    b->spoof_client_ip = a->spoof_client_ip;
+    b->accel = a->accel;
+    b->allow_direct = a->allow_direct;
+    b->vhost = a->vhost;
+    b->sslBump = a->sslBump;
+    b->vport = a->vport;
+    b->connection_auth_disabled = a->connection_auth_disabled;
+    b->disable_pmtu_discovery = a->disable_pmtu_discovery;
+
+    memcpy( &(b->tcp_keepalive), &(a->tcp_keepalive), sizeof(a->tcp_keepalive));
+
+#if 0
+    // AYJ: 2009-07-18: for now SSL does not clone. Configure separate ports with IPs and SSL settings
+
+#if USE_SSL
+    // XXX: temporary hack to ease move of SSL options to http_port
+    http_port_list &http;
+
+    char *cert;
+    char *key;
+    int version;
+    char *cipher;
+    char *options;
+    char *clientca;
+    char *cafile;
+    char *capath;
+    char *crlfile;
+    char *dhfile;
+    char *sslflags;
+    char *sslcontext;
+    SSL_CTX *sslContext;
+#endif
+
+#endif /*0*/
+
+    return b;
+}
+#endif
+
 static void
 parse_http_port_list(http_port_list ** head)
 {
@@ -3176,6 +3230,15 @@ parse_http_port_list(http_port_list ** head)
         parse_http_port_option(s, token);
     }
 
+#if IPV6_SPECIAL_SPLITSTACK
+    if (s->s.IsAnyAddr()) {
+        // clone the port options from *s to *(s->next)
+        s->next = clone_http_port_list(s);
+        s->next->s.SetIPv4();
+        debugs(3, 3, "http(s)_port: clone wildcard address for split-stack: " << s->s << " and " << s->next->s);
+    }
+#endif
+
     while (*head)
         head = &(*head)->next;
 
index 5d91eacbd60b10025243f11217b1c316f1c7db83..4459e85c1c93a1edfa564080697d57d2c8daaae2 100644 (file)
@@ -562,6 +562,11 @@ comm_local_port(int fd)
     if (F->local_addr.GetPort())
         return F->local_addr.GetPort();
 
+#if USE_IPV6
+    if (F->sock_family == AF_INET)
+        temp.SetIPv4();
+#endif
+
     temp.InitAddrInfo(addr);
 
     if (getsockname(fd, addr->ai_addr, &(addr->ai_addrlen)) ) {
@@ -575,14 +580,16 @@ comm_local_port(int fd)
 
     F->local_addr.SetPort(temp.GetPort());
 
+#if 0 // seems to undo comm_open actions on the FD ...
     // grab default socket information for this address
     temp.GetAddrInfo(addr);
 
     F->sock_family = addr->ai_family;
 
     temp.FreeAddrInfo(addr);
+#endif
 
-    debugs(5, 6, "comm_local_port: FD " << fd << ": port " << F->local_addr.GetPort());
+    debugs(5, 6, "comm_local_port: FD " << fd << ": port " << F->local_addr.GetPort() << "(family=" << F->sock_family << ")");
     return F->local_addr.GetPort();
 }
 
@@ -658,7 +665,7 @@ comm_set_v6only(int fd, int tos)
 {
 #ifdef IPV6_V6ONLY
     if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &tos, sizeof(int)) < 0) {
-        debugs(50, 1, "comm_open: setsockopt(IPV6_V6ONLY) on FD " << fd << ": " << xstrerror());
+        debugs(50, 1, "comm_open: setsockopt(IPV6_V6ONLY) " << (tos?"ON":"OFF") << " for FD " << fd << ": " << xstrerror());
     }
 #else
     debugs(50, 0, "WARNING: comm_open: setsockopt(IPV6_V6ONLY) not supported on this platform");
@@ -759,7 +766,7 @@ comm_openex(int sock_type,
 #if IPV6_SPECIAL_SPLITSTACK
 
     if ( addr.IsIPv6() )
-        comm_set_v6only(new_socket, tos);
+        comm_set_v6only(new_socket, 1);
 
 #endif
 
@@ -1026,6 +1033,8 @@ ConnectStateData::commResetFD()
 
     debugs(50, 3, "commResetFD: Reset socket FD " << fd << "->" << fd2 << " : family=" << new_family );
 
+    debugs(50, 3, "commResetFD: Reset socket FD " << fd << "->" << fd2 << " : family=" << new_family );
+
     /* INET6: copy the new sockets family type to the FDE table */
     F->sock_family = new_family;
 
@@ -1052,10 +1061,8 @@ ConnectStateData::commResetFD()
         comm_set_tos(fd, F->tos);
 
 #if IPV6_SPECIAL_SPLITSTACK
-
     if ( F->local_addr.IsIPv6() )
-        comm_set_v6only(fd, F->tos);
-
+        comm_set_v6only(fd, 1);
 #endif
 
     copyFDFlags(fd, F);
index c6a1931e0343a999e7fe54f3b43e3ee6e46e1c4f..2b9639b0348a8774ebdc355df3e1a27e927fb190 100644 (file)
@@ -165,7 +165,10 @@ fdIsIcp(int fd)
 static int
 fdIsDns(int fd)
 {
-    if (fd == DnsSocket)
+    if (fd == DnsSocketA)
+        return 1;
+
+    if (fd == DnsSocketB)
         return 1;
 
     return 0;
@@ -577,10 +580,15 @@ comm_poll_dns_incoming(void)
     int nevents;
     dns_io_events = 0;
 
-    if (DnsSocket < 0)
+    if (DnsSocketA < 0)
         return;
 
-    fds[nfds++] = DnsSocket;
+    fds[nfds++] = DnsSocketA;
+
+#if IPV6_SPECIAL_SPLITSTACK
+    if (DnsSocketB > 0)
+        fds[nfds++] = DnsSocketB;
+#endif
 
     nevents = comm_check_incoming_poll_handlers(nfds, fds);
 
index e82c945793f5b01ddd271725a6175482c456e483..95500c7af36bf734677ef80f70be3f064a84105d 100644 (file)
@@ -175,7 +175,10 @@ fdIsIcp(int fd)
 static int
 fdIsDns(int fd)
 {
-    if (fd == DnsSocket)
+    if (fd == DnsSocketA)
+        return 1;
+
+    if (fd == DnsSocketB)
         return 1;
 
     return 0;
@@ -625,14 +628,19 @@ static void
 comm_select_dns_incoming(void)
 {
     int nfds = 0;
-    int fds[2];
+    int fds[3];
     int nevents;
     dns_io_events = 0;
 
-    if (DnsSocket < 0)
+    if (DnsSocketA < 0)
         return;
 
-    fds[nfds++] = DnsSocket;
+    fds[nfds++] = DnsSocketA;
+
+#if IPV6_SPECIAL_SPLITSTACK
+    if (DnsSocketB > 0)
+        fds[nfds++] = DnsSocketB;
+#endif
 
     nevents = comm_check_incoming_select_handlers(nfds, fds);
 
index 1d280ec552f367de6f296364ea1b874ab1e2bdf8..cdb572589f6fce6fd909fd06f1b704d0e20b6302 100644 (file)
@@ -175,7 +175,10 @@ fdIsIcp(int fd)
 static int
 fdIsDns(int fd)
 {
-    if (fd == DnsSocket)
+    if (fd == DnsSocketA)
+        return 1;
+
+    if (fd == DnsSocketB)
         return 1;
 
     return 0;
@@ -647,14 +650,19 @@ static void
 comm_select_dns_incoming(void)
 {
     int nfds = 0;
-    int fds[2];
+    int fds[3];
     int nevents;
     dns_io_events = 0;
 
-    if (DnsSocket < 0)
+    if (DnsSocketA < 0)
         return;
 
-    fds[nfds++] = DnsSocket;
+    fds[nfds++] = DnsSocketA;
+
+#if IPV6_SPECIAL_SPLITSTACK
+    if (DnsSocketB > 0)
+        fds[nfds++] = DnsSocketB;
+#endif
 
     nevents = comm_check_incoming_select_handlers(nfds, fds);
 
index 3a1d25493403680c761a5224319836ce26ee58c8..f2c4f1e6660dbc5d019ccd636b738eb739a270be 100644 (file)
@@ -790,10 +790,7 @@ idnsSendQueryVC(idns_query * q, int ns)
 static void
 idnsSendQuery(idns_query * q)
 {
-    int x;
-    int ns;
-
-    if (DnsSocket < 0) {
+    if (DnsSocketA < 0 && DnsSocketB < 0) {
         debugs(78, 1, "WARNING: idnsSendQuery: Can't send query, no DNS socket!");
         return;
     }
@@ -807,28 +804,49 @@ idnsSendQuery(idns_query * q)
 
     assert(q->lru.prev == NULL);
 
+    int x = -1, y = -1;
+    int ns;
+
     do {
         ns = q->nsends % nns;
 
         if (q->need_vc) {
             idnsSendQueryVC(q, ns);
-            x = 0;
+            x = y = 0;
         } else {
-            x = comm_udp_sendto(DnsSocket, nameservers[ns].S, q->buf, q->sz);
+#if IPV6_SPECIAL_SPLITSTACK
+            if (nameservers[ns].S.IsIPv6() && DnsSocketB > 0)
+                y = comm_udp_sendto(DnsSocketB, nameservers[ns].S, q->buf, q->sz);
+            else
+#endif
+                x = comm_udp_sendto(DnsSocketA, nameservers[ns].S, q->buf, q->sz);
         }
 
         q->nsends++;
 
         q->queue_t = q->sent_t = current_time;
 
+#if IPV6_SPECIAL_SPLITSTACK
+        if (y < 0 && nameservers[ns].S.IsIPv6())
+            debugs(50, 1, "idnsSendQuery: FD " << DnsSocketB << ": sendto: " << xstrerror());
+        if (x < 0 && nameservers[ns].S.IsIPv4())
+#else
         if (x < 0)
-            debugs(50, 1, "idnsSendQuery: FD " << DnsSocket << ": sendto: " << xstrerror());
+#endif
+            debugs(50, 1, "idnsSendQuery: FD " << DnsSocketA << ": sendto: " << xstrerror());
 
-    } while ( x<0 && q->nsends % nns != 0);
+    } while ( (x<0 && y<0) && q->nsends % nns != 0);
+
+#if IPV6_SPECIAL_SPLITSTACK
+    if (y >= 0) {
+        fd_bytes(DnsSocketB, y, FD_WRITE);
+        commSetSelect(DnsSocketB, COMM_SELECT_READ, idnsRead, NULL, 0);
+    }
+#endif
 
     if (x >= 0) {
-        fd_bytes(DnsSocket, x, FD_WRITE);
-        commSetSelect(DnsSocket, COMM_SELECT_READ, idnsRead, NULL, 0);
+        fd_bytes(DnsSocketA, x, FD_WRITE);
+        commSetSelect(DnsSocketA, COMM_SELECT_READ, idnsRead, NULL, 0);
     }
 
     nameservers[ns].nqueries++;
@@ -1154,7 +1172,13 @@ idnsRead(int fd, void *data)
             break;
         }
 
-        fd_bytes(DnsSocket, len, FD_READ);
+#if IPV6_SPECIAL_SPLITSTACK
+        if ( from.IsIPv6() )
+            fd_bytes(DnsSocketB, len, FD_READ);
+        else
+#endif
+            fd_bytes(DnsSocketA, len, FD_READ);
+
         assert(N);
         (*N)++;
 
@@ -1180,8 +1204,14 @@ idnsRead(int fd, void *data)
         idnsGrokReply(rbuf, len);
     }
 
-    if (lru_list.head)
-        commSetSelect(DnsSocket, COMM_SELECT_READ, idnsRead, NULL, 0);
+    if (lru_list.head) {
+#if IPV6_SPECIAL_SPLITSTACK
+        if ( from.IsIPv6() )
+            commSetSelect(DnsSocketB, COMM_SELECT_READ, idnsRead, NULL, 0);
+        else
+#endif
+            commSetSelect(DnsSocketA, COMM_SELECT_READ, idnsRead, NULL, 0);
+    }
 }
 
 static void
@@ -1328,7 +1358,7 @@ idnsInit(void)
     CBDATA_INIT_TYPE(nsvc);
     CBDATA_INIT_TYPE(idns_query);
 
-    if (DnsSocket < 0) {
+    if (DnsSocketA < 0 && DnsSocketB < 0) {
         int port;
 
         IpAddress addr; // since we don't want to alter Config.Addrs.udp_* and dont have one of our own.
@@ -1338,22 +1368,56 @@ idnsInit(void)
         else
             addr = Config.Addrs.udp_incoming;
 
+#if IPV6_SPECIAL_SPLITSTACK
+        IpAddress addr4 = addr;
+
+        if ( addr.IsAnyAddr() || addr.IsIPv6() ) {
+            debugs(78, 2, "idnsInit: attempt open DNS socket to: " << addr);
+            DnsSocketB = comm_open_listener(SOCK_DGRAM,
+                                            IPPROTO_UDP,
+                                            addr,
+                                            COMM_NONBLOCKING,
+                                            "DNS Socket v6");
+        }
+
+        if ( addr.IsAnyAddr() || addr.IsIPv4() ) {
+            addr4.SetIPv4();
+            debugs(78, 2, "idnsInit: attempt open DNS socket to: " << addr4);
+            DnsSocketA = comm_open_listener(SOCK_DGRAM,
+                                            IPPROTO_UDP,
+                                            addr4,
+                                            COMM_NONBLOCKING,
+                                            "DNS Socket v4");
+        }
+#else
+        DnsSocketA = comm_open_listener(SOCK_DGRAM,
+                                        IPPROTO_UDP,
+                                        addr,
+                                        COMM_NONBLOCKING,
+                                        "DNS Socket");
         debugs(78, 2, "idnsInit: attempt open DNS socket to: " << addr);
-        DnsSocket = comm_open_listener(SOCK_DGRAM,
-                                       IPPROTO_UDP,
-                                       addr,
-                                       COMM_NONBLOCKING,
-                                       "DNS Socket");
+#endif
 
-        if (DnsSocket < 0)
+        if (DnsSocketA < 0 && DnsSocketB < 0)
             fatal("Could not create a DNS socket");
 
         /* Ouch... we can't call functions using debug from a debug
          * statement. Doing so messes up the internal Debug::level
          */
-        port = comm_local_port(DnsSocket);
-
-        debugs(78, 1, "DNS Socket created at " << addr << ", FD " << DnsSocket);
+#if IPV6_SPECIAL_SPLITSTACK
+        if (DnsSocketB >= 0) {
+            port = comm_local_port(DnsSocketB);
+            debugs(78, 1, "DNS Socket created at " << addr << ", FD " << DnsSocketB);
+        }
+#endif
+        if (DnsSocketA >= 0) {
+            port = comm_local_port(DnsSocketA);
+#if IPV6_SPECIAL_SPLITSTACK
+            debugs(78, 1, "DNS Socket created at " << addr4 << ", FD " << DnsSocketA);
+#else
+            debugs(78, 1, "DNS Socket created at " << addr << ", FD " << DnsSocketA);
+#endif
+        }
     }
 
     assert(0 == nns);
@@ -1398,12 +1462,20 @@ idnsInit(void)
 void
 idnsShutdown(void)
 {
-    if (DnsSocket < 0)
+    if (DnsSocketA < 0 && DnsSocketB < 0)
         return;
 
-    comm_close(DnsSocket);
+    if (DnsSocketA >= 0 ) {
+        comm_close(DnsSocketA);
+        DnsSocketA = -1;
+    }
 
-    DnsSocket = -1;
+#if IPV6_SPECIAL_SPLITSTACK
+    if (DnsSocketA >= 0 ) {
+        comm_close(DnsSocketB);
+        DnsSocketB = -1;
+    }
+#endif
 
     for (int i = 0; i < nns; i++) {
         if (nsvc *vc = nameservers[i].vc) {
@@ -1413,7 +1485,6 @@ idnsShutdown(void)
     }
 
     idnsFreeNameservers();
-
     idnsFreeSearchpath();
 }
 
index 06c98c688217e94f9794acdaf2aa6f9340c37b70..2250063573ac71cbd165da5e8c1dd34d7cbf8c4c 100644 (file)
@@ -100,7 +100,8 @@ extern "C" {
     extern int syslog_enable;  /* 0 */
     extern int theInIcpConnection;     /* -1 */
     extern int theOutIcpConnection;    /* -1 */
-    extern int DnsSocket;              /* -1 */
+    extern int DnsSocketA;             /* -1 */
+    extern int DnsSocketB;             /* -1 */
 #ifdef SQUID_SNMP
 
     extern int theInSnmpConnection;    /* -1 */