]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Bug 2994: Basic split-stack functionality
authorAmos Jeffries <amosjeffries@squid-cache.org>
Sun, 1 Aug 2010 13:29:09 +0000 (07:29 -0600)
committerAmos Jeffries <amosjeffries@squid-cache.org>
Sun, 1 Aug 2010 13:29:09 +0000 (07:29 -0600)
Enable split-stack detection by default.

There is now enough split-stack support to enable accepting IPv6 client
connections on systems with separate IPv4/IPv6 stacks. Also some limited
server connection capabilities (see tcp_outgoing_addr config hacks).

SNMP, ICP, HTCP listeners and outbound connections currently default to
IPv4-only on these systems to retain backward-compatibility.
But may be explicity configured to IPv6-only. There is no support as yet
for dual-protocol behaviour in the sockets of these three protocols.

src/forward.cc
src/htcp.cc
src/icp_v2.cc
src/ip/tools.cc
src/snmp_core.cc

index 92c6c5588600a883c1a7dd929b546a7dc91bc6f3..2559b1aab29710d3607729c8ef48ce2b84a7bcbd 100644 (file)
@@ -47,6 +47,7 @@
 #include "Store.h"
 #include "icmp/net_db.h"
 #include "ip/IpIntercept.h"
+#include "ip/tools.h"
 
 static PSC fwdStartCompleteWrapper;
 static PF fwdServerClosedWrapper;
@@ -867,6 +868,24 @@ FwdState::connectStart()
 
     outgoing = getOutgoingAddr(request, fs->_peer);
 
+    // if IPv6 is disabled try to force IPv4-only outgoing.
+    if (!Ip::EnableIpv6 && !outgoing.SetIPv4()) {
+        debugs(50, 4, "fwdConnectStart: " << xstrerror());
+        ErrorState *anErr = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE, request);
+        anErr->xerrno = errno;
+        fail(anErr);
+        self = NULL;   // refcounted
+        return;
+    }
+
+    // if IPv6 is split-stack, prefer IPv4
+    if (Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK) {
+        // NP: This is not a great choice of default,
+        // but with the current Internet being IPv4-majority has a higher success rate.
+        // if setting to IPv4 fails we dont care, that just means to use IPv6 outgoing.
+        outgoing.SetIPv4();
+    }
+
     tos = getOutgoingTOS(request);
 
     debugs(17, 3, "fwdConnectStart: got outgoing addr " << outgoing << ", tos " << tos);
index 900110c33a010d24e92c6b85be4aae41adc50ca8..93ff7e933841c884a6d33ac1a7270d1be3face73 100644 (file)
@@ -37,6 +37,7 @@
 #include "htcp.h"
 #include "acl/FilledChecklist.h"
 #include "acl/Acl.h"
+#include "ip/tools.h"
 #include "SquidTime.h"
 #include "Store.h"
 #include "StoreClient.h"
@@ -1493,6 +1494,15 @@ htcpInit(void)
     IpAddress incomingAddr = Config.Addrs.udp_incoming;
     incomingAddr.SetPort(Config.Port.htcp);
 
+    if (!Ip::EnableIpv6 && !incomingAddr.SetIPv4()) {
+        debugs(31, DBG_CRITICAL, "ERROR: IPv6 is disabled. " << incomingAddr << " is not an IPv4 address.");
+        fatal("HTCP port cannot be opened.");
+    }
+    /* split-stack for now requires default IPv4-only HTCP */
+    if (Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK && incomingAddr.IsAnyAddr()) {
+        incomingAddr.SetIPv4();
+    }
+
     enter_suid();
     htcpInSocket = comm_open_listener(SOCK_DGRAM,
                                       IPPROTO_UDP,
@@ -1512,6 +1522,15 @@ htcpInit(void)
         IpAddress outgoingAddr = Config.Addrs.udp_outgoing;
         outgoingAddr.SetPort(Config.Port.htcp);
 
+        if (!Ip::EnableIpv6 && !outgoingAddr.SetIPv4()) {
+            debugs(31, DBG_CRITICAL, "ERROR: IPv6 is disabled. " << outgoingAddr << " is not an IPv4 address.");
+            fatal("HTCP port cannot be opened.");
+        }
+        /* split-stack for now requires default IPv4-only HTCP */
+        if (Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK && outgoingAddr.IsAnyAddr()) {
+            outgoingAddr.SetIPv4();
+        }
+
         enter_suid();
         htcpOutSocket = comm_open_listener(SOCK_DGRAM,
                                            IPPROTO_UDP,
index cbfed7a3597e09aefb9cecd58949e6d3a5f2d2cd..bb8143bece26d6f0e2803add24a40835143ad9ad 100644 (file)
@@ -48,6 +48,7 @@
 #include "SwapDir.h"
 #include "icmp/net_db.h"
 #include "ip/IpAddress.h"
+#include "ip/tools.h"
 #include "rfc1738.h"
 
 /// \ingroup ServerProtocolICPInternal2
@@ -665,6 +666,16 @@ icpConnectionsOpen(void)
 
     addr = Config.Addrs.udp_incoming;
     addr.SetPort(port);
+
+    if (!Ip::EnableIpv6 && !addr.SetIPv4()) {
+        debugs(12, DBG_CRITICAL, "ERROR: IPv6 is disabled. " << addr << " is not an IPv4 address.");
+        fatal("ICP port cannot be opened.");
+    }
+    /* split-stack for now requires default IPv4-only ICP */
+    if (Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK && addr.IsAnyAddr()) {
+        addr.SetIPv4();
+    }
+
     theInIcpConnection = comm_open_listener(SOCK_DGRAM,
                                             IPPROTO_UDP,
                                             addr,
@@ -691,6 +702,16 @@ icpConnectionsOpen(void)
     if ( !addr.IsNoAddr() ) {
         enter_suid();
         addr.SetPort(port);
+
+        if (!Ip::EnableIpv6 && !addr.SetIPv4()) {
+            debugs(49, DBG_CRITICAL, "ERROR: IPv6 is disabled. " << addr << " is not an IPv4 address.");
+            fatal("ICP port cannot be opened.");
+        }
+        /* split-stack for now requires default IPv4-only ICP */
+        if (Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK && addr.IsAnyAddr()) {
+            addr.SetIPv4();
+        }
+
         theOutIcpConnection = comm_open_listener(SOCK_DGRAM,
                               IPPROTO_UDP,
                               addr,
index 2c4daa19b41ad26aae2fa03583a3f3860ebef91c..d8ddf51efea1e648c4bbfad5e81079c694280b2d 100644 (file)
@@ -65,9 +65,7 @@ Ip::ProbeTransport()
         EnableIpv6 |= IPV6_SPECIAL_V4MAPPING;
     } else {
         debugs(3, 2, "Detected split IPv4 and IPv6 stacks ...");
-        // EnableIpv6 |= IPV6_SPECIAL_SPLITSTACK;
-        // TODO: remove death when split-stack is supported.
-        EnableIpv6 = IPV6_OFF;
+        EnableIpv6 |= IPV6_SPECIAL_SPLITSTACK;
     }
     close(s);
 
index 4fec167c6cda66263e754533cfef0184cf2812bf..b491342073d46140c8f6e76c2471800bd7d59d64 100644 (file)
@@ -286,6 +286,17 @@ snmpConnectionOpen(void)
 
     if (Config.Port.snmp > 0) {
         Config.Addrs.snmp_incoming.SetPort(Config.Port.snmp);
+
+        if (!Ip::EnableIpv6 && !Config.Addrs.snmp_incoming.SetIPv4()) {
+            debugs(49, DBG_CRITICAL, "ERROR: IPv6 is disabled. " << Config.Addrs.snmp_incoming << " is not an IPv4 address.");
+            fatal("SNMP port cannot be opened.");
+        }
+
+        /* split-stack for now requires IPv4-only SNMP */
+        if (Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK && Config.Addrs.snmp_incoming.IsAnyAddr()) {
+            Config.Addrs.snmp_incoming.SetIPv4();
+        }
+
         enter_suid();
         theInSnmpConnection = comm_open_listener(SOCK_DGRAM,
                               IPPROTO_UDP,
@@ -303,6 +314,17 @@ snmpConnectionOpen(void)
 
         if (!Config.Addrs.snmp_outgoing.IsNoAddr()) {
             Config.Addrs.snmp_outgoing.SetPort(Config.Port.snmp);
+
+            if (!Ip::EnableIpv6 && !Config.Addrs.snmp_outgoing.SetIPv4()) {
+                debugs(49, DBG_CRITICAL, "ERROR: IPv6 is disabled. " << Config.Addrs.snmp_outgoing << " is not an IPv4 address.");
+                fatal("SNMP port cannot be opened.");
+            }
+
+            /* split-stack for now requires IPv4-only SNMP */
+            if (Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK && Config.Addrs.snmp_outgoing.IsAnyAddr()) {
+                Config.Addrs.snmp_outgoing.SetIPv4();
+            }
+
             enter_suid();
             theOutSnmpConnection = comm_open_listener(SOCK_DGRAM,
                                    IPPROTO_UDP,