]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Bug 2571: Squid with IPv6 fails to start on kernel without IPv6
authorAmos Jeffries <squid3@treenet.co.nz>
Sun, 12 Apr 2009 13:44:59 +0000 (01:44 +1200)
committerAmos Jeffries <squid3@treenet.co.nz>
Sun, 12 Apr 2009 13:44:59 +0000 (01:44 +1200)
Adds comm_open_listener() wrapper to perform IPv6/IPv4 failover on sockets
intended for listening only. Uses the wrapper in all places I can be sure of.

Open a port specially bound for listening or sending through a specific port.
This is a wrapper providing IPv4/IPv6 failover around comm_openex().
Please use for all listening sockets and bind() outbound sockets.

It will open a socket bound for:
  - IPv4 if IPv6 is disabled or address is IPv4-native.
  - IPv6 if address is IPv6-native
  - IPv6 dual-stack mode if able to open [::]

When an open performs failover it update the given address to feedback
the new IPv4-only status of the socket. Further displays of the IP
(in debugs or cachemgr) will occur in Native IPv4 format.
A reconfigure is needed to reset the stored IP in most cases and attempt
a port re-open.

src/client_side.cc
src/comm.cc
src/comm.h
src/dns_internal.cc
src/htcp.cc
src/icp_v2.cc
src/ident.cc
src/snmp_core.cc
src/wccp.cc
src/wccp2.cc

index e9bb5fd1a133785e403cfc12eb19fe8ee9b7a485..0d212f52db2e36945109d475b0f812f3ae448b51 100644 (file)
@@ -3171,9 +3171,9 @@ clientHttpConnectionsOpen(void)
         enter_suid();
 
         if (s->spoof_client_ip) {
-            fd = comm_openex(SOCK_STREAM, IPPROTO_TCP, s->s, (COMM_NONBLOCKING|COMM_TRANSPARENT), 0, "HTTP Socket");
+            fd = comm_open_listener(SOCK_STREAM, IPPROTO_TCP, s->s, (COMM_NONBLOCKING|COMM_TRANSPARENT), "HTTP Socket");
         } else {
-            fd = comm_open(SOCK_STREAM, IPPROTO_TCP, s->s, COMM_NONBLOCKING, "HTTP Socket");
+            fd = comm_open_listener(SOCK_STREAM, IPPROTO_TCP, s->s, COMM_NONBLOCKING, "HTTP Socket");
         }
 
         leave_suid();
@@ -3225,7 +3225,7 @@ clientHttpsConnectionsOpen(void)
         }
 
         enter_suid();
-        fd = comm_open(SOCK_STREAM,
+        fd = comm_open_listener(SOCK_STREAM,
                        IPPROTO_TCP,
                        s->http.s,
                        COMM_NONBLOCKING, "HTTPS Socket");
index d0529ba5d03eb5c769efca2c779a825ad5395463..949a6d46aeed158f215e7f5df581034baab79d5f 100644 (file)
@@ -611,6 +611,31 @@ comm_open(int sock_type,
     return comm_openex(sock_type, proto, addr, flags, 0, note);
 }
 
+int
+comm_open_listener(int sock_type,
+          int proto,
+          IpAddress &addr,
+          int flags,
+          const char *note)
+{
+    int sock = -1;
+
+    /* attempt native enabled port. */
+    sock = comm_openex(sock_type, proto, addr, flags, 0, note);
+
+#if USE_IPV6
+    /* under IPv6 there is the possibility IPv6 is present but disabled. */
+    /* try again as IPv4-native */
+    if ( sock < 0 && addr.IsIPv6() && addr.SetIPv4() ) {
+        /* attempt to open this IPv4-only. */
+        sock = comm_openex(sock_type, proto, addr, flags, 0, note);
+        debugs(50, 2, HERE << "attempt open " << note << " socket on: " << addr);
+    }
+#endif
+
+    return sock;
+}
+
 static bool
 limitError(int const anErrno)
 {
index a44938e2df2e659a4b3845745b15cff5d02e58bf..730fba81e45455636cd7788ad16877e8f4cf37dd 100644 (file)
@@ -55,6 +55,23 @@ SQUIDCEXTERN void comm_exit(void);
 
 SQUIDCEXTERN int comm_open(int, int, IpAddress &, int, const char *note);
 
+/**
+ * Open a port specially bound for listening or sending through a specific port.
+ * This is a wrapper providing IPv4/IPv6 failover around comm_openex().
+ * Please use for all listening sockets and bind() outbound sockets.
+ *
+ * It will open a socket bound for:
+ *  - IPv4 if IPv6 is disabled or address is IPv4-native.
+ *  - IPv6 if address is IPv6-native
+ *  - IPv6 dual-stack mode if able to open [::]
+ *
+ * When an open performs failover it update the given address to feedback
+ * the new IPv4-only status of the socket. Further displays of the IP
+ * (in debugs or cachemgr) will occur in Native IPv4 format.
+ * A reconfigure is needed to reset the stored IP in most cases and attempt a port re-open.
+ */
+SQUIDCEXTERN int comm_open_listener(int sock_type, int proto, IpAddress &addr, int flags, const char *note);
+
 SQUIDCEXTERN int comm_openex(int, int, IpAddress &, int, unsigned char TOS, const char *);
 SQUIDCEXTERN u_short comm_local_port(int fd);
 SQUIDCEXTERN int comm_set_tos(int fd, int tos);
index 91afc58357b4e7deec976bc074360c43b005bdb1..a6ea91e480eabf2086d4a11e220f81324b4962dd 100644 (file)
@@ -1345,34 +1345,20 @@ idnsInit(void)
     if (DnsSocket < 0) {
         int port;
 
-        IpAddress addr;
+        IpAddress addr; // since we don't want to alter Config.Addrs.udp_* and dont have one of our own.
 
         if (!Config.Addrs.udp_outgoing.IsNoAddr())
             addr = Config.Addrs.udp_outgoing;
         else
             addr = Config.Addrs.udp_incoming;
 
-        DnsSocket = comm_open(SOCK_DGRAM,
+        debugs(78, 2, "idnsInit: attempt open DNS socket to: " << addr);
+        DnsSocket = comm_open_listener(SOCK_DGRAM,
                               IPPROTO_UDP,
                               addr,
                               COMM_NONBLOCKING,
                               "DNS Socket");
 
-        debugs(78, 2, "idnsInit: attempt open DNS socket to: " << addr);
-
-#if USE_IPV6
-        if ( DnsSocket < 0 && addr.IsIPv6() && addr.SetIPv4() ) {
-            /* attempt to open this IPv4-only. */
-            DnsSocket = comm_open(SOCK_DGRAM,
-                                  IPPROTO_UDP,
-                                  addr,
-                                  COMM_NONBLOCKING,
-                                  "DNS Socket");
-
-            debugs(78, 2, "idnsInit: attempt open DNS socket to: " << addr);
-        }
-#endif
-
         if (DnsSocket < 0)
             fatal("Could not create a DNS socket");
 
index ab1efb581c4c6c2e0b4d5e9b955450fe4031343a..8e16c6716fd1e50f2add2c0c566b17d1ec0557ab 100644 (file)
@@ -1474,7 +1474,7 @@ htcpInit(void)
     incomingAddr.SetPort(Config.Port.htcp);
 
     enter_suid();
-    htcpInSocket = comm_open(SOCK_DGRAM,
+    htcpInSocket = comm_open_listener(SOCK_DGRAM,
                              IPPROTO_UDP,
                              incomingAddr,
                              COMM_NONBLOCKING,
@@ -1493,7 +1493,7 @@ htcpInit(void)
         outgoingAddr.SetPort(Config.Port.htcp);
 
         enter_suid();
-        htcpOutSocket = comm_open(SOCK_DGRAM,
+        htcpOutSocket = comm_open_listener(SOCK_DGRAM,
                                   IPPROTO_UDP,
                                   outgoingAddr,
                                   COMM_NONBLOCKING,
index 350c8f68f852b318c970d75dc9fa7235f6765753..e41c78594c8a5f3672095adab5ef2f5e70599c10 100644 (file)
@@ -664,7 +664,7 @@ icpConnectionsOpen(void)
 
     addr = Config.Addrs.udp_incoming;
     addr.SetPort(port);
-    theInIcpConnection = comm_open(SOCK_DGRAM,
+    theInIcpConnection = comm_open_listener(SOCK_DGRAM,
                                    IPPROTO_UDP,
                                    addr,
                                    COMM_NONBLOCKING,
@@ -690,7 +690,7 @@ icpConnectionsOpen(void)
     if ( !addr.IsNoAddr() ) {
         enter_suid();
         addr.SetPort(port);
-        theOutIcpConnection = comm_open(SOCK_DGRAM,
+        theOutIcpConnection = comm_open_listener(SOCK_DGRAM,
                                         IPPROTO_UDP,
                                         addr,
                                         COMM_NONBLOCKING,
index dad1a5daf1fbac4a841e7e3d7657099678858c6b..f8d942344d371d443ffd4fa468ff9cda783d0f9a 100644 (file)
@@ -220,7 +220,7 @@ identStart(IpAddress &me, IpAddress &my_peer, IDCB * callback, void *data)
         return;
     }
 
-    fd = comm_open(SOCK_STREAM,
+    fd = comm_open_listener(SOCK_STREAM,
                    IPPROTO_TCP,
                    me,
                    COMM_NONBLOCKING,
index e46cd49504ebae24177811fc3d325405c8e62868..ebff8727351e4fd9ca8e2977b72259af90673e86 100644 (file)
@@ -365,7 +365,7 @@ snmpConnectionOpen(void)
     if (Config.Port.snmp > 0) {
         Config.Addrs.snmp_incoming.SetPort(Config.Port.snmp);
         enter_suid();
-        theInSnmpConnection = comm_open(SOCK_DGRAM,
+        theInSnmpConnection = comm_open_listener(SOCK_DGRAM,
                                         IPPROTO_UDP,
                                         Config.Addrs.snmp_incoming,
                                         COMM_NONBLOCKING,
@@ -373,7 +373,7 @@ snmpConnectionOpen(void)
         leave_suid();
 
         if (theInSnmpConnection < 0)
-            fatal("Cannot open snmp Port");
+            fatal("Cannot open SNMP Port");
 
         commSetSelect(theInSnmpConnection, COMM_SELECT_READ, snmpHandleUdp, NULL, 0);
 
@@ -382,7 +382,7 @@ snmpConnectionOpen(void)
         if (!Config.Addrs.snmp_outgoing.IsNoAddr()) {
             Config.Addrs.snmp_outgoing.SetPort(Config.Port.snmp);
             enter_suid();
-            theOutSnmpConnection = comm_open(SOCK_DGRAM,
+            theOutSnmpConnection = comm_open_listener(SOCK_DGRAM,
                                              IPPROTO_UDP,
                                              Config.Addrs.snmp_outgoing,
                                              COMM_NONBLOCKING,
index b24b371aa90258b394e7fc3676545b25de054b43..6b993126403da7fb97f42e141a049bca38dbfd0b 100644 (file)
@@ -147,7 +147,7 @@ wccpConnectionOpen(void)
 
     Config.Wccp.address.SetPort(WCCP_PORT);
 
-    theWccpConnection = comm_open(SOCK_DGRAM,
+    theWccpConnection = comm_open_listener(SOCK_DGRAM,
                                   IPPROTO_UDP,
                                   Config.Wccp.address,
                                   COMM_NONBLOCKING,
index 8acc052ede07936a2a7ffe910896c696b616e149..7d5f66cc4ff8ad78c51a53707d34ac03cc88c7dd 100644 (file)
@@ -995,7 +995,7 @@ wccp2ConnectionOpen(void)
     }
 
     Config.Wccp2.address.SetPort(WCCP_PORT);
-    theWccp2Connection = comm_open(SOCK_DGRAM,
+    theWccp2Connection = comm_open_listener(SOCK_DGRAM,
                                    0,
                                    Config.Wccp2.address,
                                    COMM_NONBLOCKING,