From: Amos Jeffries Date: Sun, 25 Jul 2010 08:04:41 +0000 (-0600) Subject: Split-Stack enable DNS and http(s)_port sockets. X-Git-Tag: SQUID_3_1_5_1~6 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=fa617da774e4977ceec26749ec98f882fdac7ba3;p=thirdparty%2Fsquid.git Split-Stack enable DNS and http(s)_port sockets. 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. --- diff --git a/src/cache_cf.cc b/src/cache_cf.cc index 639efb1eda..29c9dd5b7b 100644 --- a/src/cache_cf.cc +++ b/src/cache_cf.cc @@ -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; diff --git a/src/comm.cc b/src/comm.cc index 5d91eacbd6..4459e85c1c 100644 --- a/src/comm.cc +++ b/src/comm.cc @@ -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); diff --git a/src/comm_poll.cc b/src/comm_poll.cc index c6a1931e03..2b9639b034 100644 --- a/src/comm_poll.cc +++ b/src/comm_poll.cc @@ -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); diff --git a/src/comm_select.cc b/src/comm_select.cc index e82c945793..95500c7af3 100644 --- a/src/comm_select.cc +++ b/src/comm_select.cc @@ -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); diff --git a/src/comm_select_win32.cc b/src/comm_select_win32.cc index 1d280ec552..cdb572589f 100644 --- a/src/comm_select_win32.cc +++ b/src/comm_select_win32.cc @@ -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); diff --git a/src/dns_internal.cc b/src/dns_internal.cc index 3a1d254934..f2c4f1e666 100644 --- a/src/dns_internal.cc +++ b/src/dns_internal.cc @@ -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(); } diff --git a/src/globals.h b/src/globals.h index 06c98c6882..2250063573 100644 --- a/src/globals.h +++ b/src/globals.h @@ -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 */