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.
#include "Store.h"
#include "icmp/net_db.h"
#include "ip/IpIntercept.h"
+#include "ip/tools.h"
static PSC fwdStartCompleteWrapper;
static PF fwdServerClosedWrapper;
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);
#include "htcp.h"
#include "acl/FilledChecklist.h"
#include "acl/Acl.h"
+#include "ip/tools.h"
#include "SquidTime.h"
#include "Store.h"
#include "StoreClient.h"
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,
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,
#include "SwapDir.h"
#include "icmp/net_db.h"
#include "ip/IpAddress.h"
+#include "ip/tools.h"
#include "rfc1738.h"
/// \ingroup ServerProtocolICPInternal2
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,
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,
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);
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,
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,