Hello again,
a few days ago I described the following situation and problem,
where I am now able to provide a solution for:
> At least I would like a configurable option for the outgoing address
> in dependence of the destination sibling, to suite the following
> scenario:
>
> At two locations are running two (or even more) proxies with the
> following (sample) configuration:
>
> Interface Location A Location B
>
> le0 192.168.1.2 192.168.1.130
> le0:1 192.168.1.4 (192.168.1.4)
> le0:2 (192.168.1.132) 192.168.1.132
>
> The official proxy addresses are .4 and .132 and they are load balanced
> by DNS Round Robin.
> In the normal case the load is also balanced over the two machines. But
> in case of a failure of one machine (or location) the other location
> will become active and responsible for the failed IP-address.
>
> Because we don't want to announce the hard adresses to our customers,
> the proxies have to be configured with udp_outgoing_address
> .4 for location A and .132 for location B to be usefull two other
> proxies as parents or siblings. (Otherwise the siblings running with
> older squid versions will not receive or ignore the response, coming
> from an unexpected ip-address).
>
To express in other words: a neighbor/peer request from Location A will
always have the source address 192.168.1.4. So the response from
Location B will go to this address, which itself is configured there.
So the response will never go to Location A :-(
To fix this problem I created a new option: udp_outgoing_peer
If you're using this option, every neighbor requests are routed over this
IP-address instead of the default one (udp_outgoing_address).
For this I created a new fd 'thePeerIcpConnection' within the source,
and changed all relevant calls to use this fd.
(The fd is copied from 'theOutIcpConnection' if you're not using the
new option and would then cause no behavioral changes.)
The patch is included below; It should be usefull for others with an
equal redundant setup as we have and maybe so for similar ones.
If so, it may/should go into the distribution.
Enjoy,
Jan
Only in squid-2.2.peer/src: Makefile
Only in squid-2.2.peer/src: TAGS
diff -cr squid-2.2.DEVEL3/src/cf.data.pre squid-2.2.peer/src/cf.data.pre
*** squid-2.2.DEVEL3/src/cf.data.pre Wed Feb 10 00:10:31 1999
--- squid-2.2.peer/src/cf.data.pre Sun Apr 4 10:50:34 1999
***************
*** 151,159 ****
--- 151,166 ----
TYPE: address
LOC: Config.Addrs.udp_outgoing
DEFAULT: 255.255.255.255
+ DOC_NONE
+
+ NAME: udp_outgoing_peer
+ TYPE: address
+ LOC: Config.Addrs.udp_out_peer
+ DEFAULT: 255.255.255.255
DOC_START
Usage: tcp_incoming_address 10.20.30.40
udp_outgoing_address fully.qualified.domain.name
+ udp_outgoing_peer 10.20.30.33
tcp_incoming_address is used for the HTTP socket which accepts
connections from clients and other caches.
***************
*** 163,168 ****
--- 170,177 ----
from other caches.
udp_outgoing_address is used for ICP packets sent out to other
caches.
+ udp_outgoing_peer is used for ICP packets sent to configured
+ peers. (usually hard interface eth0 or le0)
The default behaviour is to not bind to any specific address.
***************
*** 174,179 ****
--- 183,189 ----
tcp_outgoing_address 0.0.0.0
udp_incoming_address 0.0.0.0
udp_outgoing_address 0.0.0.0
+ udp_outgoing_peer 0.0.0.0
DOC_END
COMMENT_START
diff -cr squid-2.2.DEVEL3/src/comm_select.c squid-2.2.peer/src/comm_select.c
*** squid-2.2.DEVEL3/src/comm_select.c Mon Jan 18 23:23:33 1999
--- squid-2.2.peer/src/comm_select.c Sun Apr 4 11:12:45 1999
***************
*** 144,149 ****
--- 144,151 ----
return 1;
if (fd == theOutIcpConnection)
return 1;
+ if (fd == thePeerIcpConnection)
+ return 1;
return 0;
}
***************
*** 223,230 ****
if (theInIcpConnection >= 0)
fds[nfds++] = theInIcpConnection;
if (theInIcpConnection != theOutIcpConnection)
! if (theOutIcpConnection >= 0)
fds[nfds++] = theOutIcpConnection;
if (nfds == 0)
return;
nevents = comm_check_incoming_poll_handlers(nfds, fds);
--- 225,235 ----
if (theInIcpConnection >= 0)
fds[nfds++] = theInIcpConnection;
if (theInIcpConnection != theOutIcpConnection)
! if (theOutIcpConnection >= 0) {
fds[nfds++] = theOutIcpConnection;
+ if (thePeerIcpConnection != theOutIcpConnection)
+ fds[nfds++] = thePeerIcpConnection;
+ }
if (nfds == 0)
return;
nevents = comm_check_incoming_poll_handlers(nfds, fds);
***************
*** 487,494 ****
if (theInIcpConnection >= 0)
fds[nfds++] = theInIcpConnection;
if (theInIcpConnection != theOutIcpConnection)
! if (theOutIcpConnection >= 0)
fds[nfds++] = theOutIcpConnection;
if (nfds == 0)
return;
nevents = comm_check_incoming_select_handlers(nfds, fds);
--- 492,502 ----
if (theInIcpConnection >= 0)
fds[nfds++] = theInIcpConnection;
if (theInIcpConnection != theOutIcpConnection)
! if (theOutIcpConnection >= 0) {
fds[nfds++] = theOutIcpConnection;
+ if (thePeerIcpConnection != theOutIcpConnection)
+ fds[nfds++] = thePeerIcpConnection;
+ }
if (nfds == 0)
return;
nevents = comm_check_incoming_select_handlers(nfds, fds);
diff -cr squid-2.2.DEVEL3/src/globals.h squid-2.2.peer/src/globals.h
*** squid-2.2.DEVEL3/src/globals.h Fri Feb 12 23:32:17 1999
--- squid-2.2.peer/src/globals.h Sat Apr 3 20:33:34 1999
***************
*** 92,97 ****
--- 92,98 ----
extern int syslog_enable; /* 0 */
extern int theInIcpConnection; /* -1 */
extern int theOutIcpConnection; /* -1 */
+ extern int thePeerIcpConnection; /* -1 */
#ifdef SQUID_SNMP
extern int theInSnmpConnection; /* -1 */
extern int theOutSnmpConnection; /* -1 */
***************
*** 105,110 ****
--- 106,112 ----
extern struct in_addr local_addr;
extern struct in_addr no_addr;
extern struct in_addr theOutICPAddr;
+ extern struct in_addr thePeerICPAddr;
extern struct in_addr theOutSNMPAddr;
extern struct timeval current_time;
extern struct timeval squid_start;
diff -cr squid-2.2.DEVEL3/src/icp_v2.c squid-2.2.peer/src/icp_v2.c
*** squid-2.2.DEVEL3/src/icp_v2.c Fri Jan 29 22:28:13 1999
--- squid-2.2.peer/src/icp_v2.c Sun Apr 4 11:30:12 1999
***************
*** 114,119 ****
--- 114,150 ----
return buf;
}
+ void *
+ icpPeerCreateMessage(
+ icp_opcode opcode,
+ int flags,
+ const char *url,
+ int reqnum,
+ int pad)
+ {
+ char *buf = NULL;
+ icp_common_t *headerp = NULL;
+ char *urloffset = NULL;
+ int buf_len;
+ buf_len = sizeof(icp_common_t) + strlen(url) + 1;
+ if (opcode == ICP_QUERY)
+ buf_len += sizeof(u_num32);
+ buf = xcalloc(buf_len, 1);
+ headerp = (icp_common_t *) (void *) buf;
+ headerp->opcode = (char) opcode;
+ headerp->version = ICP_VERSION_CURRENT;
+ headerp->length = (u_short) htons(buf_len);
+ headerp->reqnum = htonl(reqnum);
+ headerp->flags = htonl(flags);
+ headerp->pad = htonl(pad);
+ headerp->shostid = thePeerICPAddr.s_addr;
+ urloffset = buf + sizeof(icp_common_t);
+ if (opcode == ICP_QUERY)
+ urloffset += sizeof(u_num32);
+ xmemcpy(urloffset, url, strlen(url));
+ return buf;
+ }
+
int
icpUdpSend(int fd,
const struct sockaddr_in *to,
***************
*** 456,461 ****
--- 487,526 ----
theOutIcpConnection, xstrerror());
else
theOutICPAddr = xaddr.sin_addr;
+
+ if ( (addr = Config.Addrs.udp_out_peer).s_addr != no_addr.s_addr
+ && addr.s_addr != Config.Addrs.udp_outgoing.s_addr) {
+ enter_suid();
+ thePeerIcpConnection = comm_open(SOCK_DGRAM,
+ 0,
+ addr,
+ port,
+ COMM_NONBLOCKING,
+ "ICP Port");
+ leave_suid();
+ if (thePeerIcpConnection < 0)
+ fatal("Cannot open Outgoing Peer ICP Port");
+ commSetSelect(thePeerIcpConnection,
+ COMM_SELECT_READ,
+ icpHandleUdp,
+ NULL,
+ 0);
+ debug(12, 1) ("Outgoing Peer ICP messages on port %d, FD %d.\n",
+ (int) port, thePeerIcpConnection);
+ fd_note(thePeerIcpConnection, "Outgoing Peer ICP socket");
+ } else {
+ thePeerIcpConnection = theOutIcpConnection;
+ }
+ memset(&thePeerICPAddr, '\0', sizeof(struct in_addr));
+ len = sizeof(struct sockaddr_in);
+ memset(&xaddr, '\0', len);
+ x = getsockname(thePeerIcpConnection,
+ (struct sockaddr *) &xaddr, &len);
+ if (x < 0)
+ debug(50, 1) ("thePeerIcpConnection FD %d: getsockname: %s\n",
+ thePeerIcpConnection, xstrerror());
+ else
+ thePeerICPAddr = xaddr.sin_addr;
}
/*
***************
*** 486,491 ****
--- 551,558 ----
*/
assert(theOutIcpConnection > -1);
commSetSelect(theOutIcpConnection, COMM_SELECT_READ, NULL, NULL, 0);
+ assert(thePeerIcpConnection > -1);
+ commSetSelect(thePeerIcpConnection, COMM_SELECT_READ, NULL, NULL, 0);
}
void
***************
*** 495,500 ****
--- 562,573 ----
if (theOutIcpConnection > -1) {
debug(12, 1) ("FD %d Closing ICP connection\n", theOutIcpConnection);
comm_close(theOutIcpConnection);
+ if (thePeerIcpConnection != theOutIcpConnection) {
+ debug(12, 1) ("FD %d Closing Peer ICP connection\n",
+ thePeerIcpConnection);
+ comm_close(thePeerIcpConnection);
+ thePeerIcpConnection = -1;
+ }
theOutIcpConnection = -1;
}
}
diff -cr squid-2.2.DEVEL3/src/main.c squid-2.2.peer/src/main.c
*** squid-2.2.DEVEL3/src/main.c Sun Jan 24 05:03:52 1999
--- squid-2.2.peer/src/main.c Sat Apr 3 22:59:39 1999
***************
*** 333,341 ****
redirectInit();
authenticateInit();
serverConnectionsOpen();
! if (theOutIcpConnection >= 0) {
if (!Config2.Accel.on || Config.onoff.accel_with_proxy)
! neighbors_open(theOutIcpConnection);
else
debug(1, 1) ("ICP port disabled in httpd_accelerator mode\n");
}
--- 333,341 ----
redirectInit();
authenticateInit();
serverConnectionsOpen();
! if (thePeerIcpConnection >= 0) {
if (!Config2.Accel.on || Config.onoff.accel_with_proxy)
! neighbors_open(thePeerIcpConnection);
else
debug(1, 1) ("ICP port disabled in httpd_accelerator mode\n");
}
***************
*** 450,458 ****
fwdInit();
}
serverConnectionsOpen();
! if (theOutIcpConnection >= 0) {
if (!Config2.Accel.on || Config.onoff.accel_with_proxy)
! neighbors_open(theOutIcpConnection);
else
debug(1, 1) ("ICP port disabled in httpd_accelerator mode\n");
}
--- 450,458 ----
fwdInit();
}
serverConnectionsOpen();
! if (thePeerIcpConnection >= 0) {
if (!Config2.Accel.on || Config.onoff.accel_with_proxy)
! neighbors_open(thePeerIcpConnection);
else
debug(1, 1) ("ICP port disabled in httpd_accelerator mode\n");
}
diff -cr squid-2.2.DEVEL3/src/neighbors.c squid-2.2.peer/src/neighbors.c
*** squid-2.2.DEVEL3/src/neighbors.c Fri Feb 12 22:41:51 1999
--- squid-2.2.peer/src/neighbors.c Sun Apr 4 11:02:36 1999
***************
*** 374,380 ****
if (Config.peers == NULL)
return 0;
! if (theOutIcpConnection < 0)
fatal("neighborsUdpPing: There is no ICP socket!");
assert(entry->swap_status == SWAPOUT_NONE);
mem->start_ping = current_time;
--- 374,380 ----
if (Config.peers == NULL)
return 0;
! if (thePeerIcpConnection < 0)
fatal("neighborsUdpPing: There is no ICP socket!");
assert(entry->swap_status == SWAPOUT_NONE);
mem->start_ping = current_time;
***************
*** 392,398 ****
debug(15, 4) ("neighborsUdpPing: pinging peer %s for '%s'\n",
p->host, url);
if (p->type == PEER_MULTICAST)
! mcastSetTtl(theOutIcpConnection, p->mcast.ttl);
debug(15, 3) ("neighborsUdpPing: key = '%s'\n", storeKeyText(entry->key));
debug(15, 3) ("neighborsUdpPing: reqnum = %d\n", reqnum);
--- 392,398 ----
debug(15, 4) ("neighborsUdpPing: pinging peer %s for '%s'\n",
p->host, url);
if (p->type == PEER_MULTICAST)
! mcastSetTtl(thePeerIcpConnection, p->mcast.ttl);
debug(15, 3) ("neighborsUdpPing: key = '%s'\n", storeKeyText(entry->key));
debug(15, 3) ("neighborsUdpPing: reqnum = %d\n", reqnum);
***************
*** 405,412 ****
if (p->icp.port == echo_port) {
debug(15, 4) ("neighborsUdpPing: Looks like a dumb cache, send DECHO ping\n");
echo_hdr.reqnum = reqnum;
! query = icpCreateMessage(ICP_DECHO, 0, url, reqnum, 0);
! icpUdpSend(theOutIcpConnection,
&p->in_addr,
query,
LOG_ICP_QUERY,
--- 405,412 ----
if (p->icp.port == echo_port) {
debug(15, 4) ("neighborsUdpPing: Looks like a dumb cache, send DECHO ping\n");
echo_hdr.reqnum = reqnum;
! query = icpPeerCreateMessage(ICP_DECHO, 0, url, reqnum, 0);
! icpUdpSend(thePeerIcpConnection,
&p->in_addr,
query,
LOG_ICP_QUERY,
***************
*** 416,423 ****
if (Config.onoff.query_icmp)
if (p->icp.version == ICP_VERSION_2)
flags |= ICP_FLAG_SRC_RTT;
! query = icpCreateMessage(ICP_QUERY, flags, url, reqnum, 0);
! icpUdpSend(theOutIcpConnection,
&p->in_addr,
query,
LOG_ICP_QUERY,
--- 416,423 ----
if (Config.onoff.query_icmp)
if (p->icp.version == ICP_VERSION_2)
flags |= ICP_FLAG_SRC_RTT;
! query = icpPeerCreateMessage(ICP_QUERY, flags, url, reqnum, 0);
! icpUdpSend(thePeerIcpConnection,
&p->in_addr,
query,
LOG_ICP_QUERY,
***************
*** 488,495 ****
to_addr.sin_family = AF_INET;
to_addr.sin_addr = ia->in_addrs[ia->cur];
to_addr.sin_port = htons(echo_port);
! query = icpCreateMessage(ICP_SECHO, 0, url, reqnum, 0);
! icpUdpSend(theOutIcpConnection,
&to_addr,
query,
LOG_ICP_QUERY,
--- 488,495 ----
to_addr.sin_family = AF_INET;
to_addr.sin_addr = ia->in_addrs[ia->cur];
to_addr.sin_port = htons(echo_port);
! query = icpPeerCreateMessage(ICP_SECHO, 0, url, reqnum, 0);
! icpUdpSend(thePeerIcpConnection,
&to_addr,
query,
LOG_ICP_QUERY,
***************
*** 1061,1071 ****
mem->start_ping = current_time;
mem->ping_reply_callback = peerCountHandleIcpReply;
mem->ircb_data = psstate;
! mcastSetTtl(theOutIcpConnection, p->mcast.ttl);
p->mcast.id = mem->id;
reqnum = icpSetCacheKey(fake->key);
! query = icpCreateMessage(ICP_QUERY, 0, url, reqnum, 0);
! icpUdpSend(theOutIcpConnection,
&p->in_addr,
query,
LOG_ICP_QUERY,
--- 1061,1071 ----
mem->start_ping = current_time;
mem->ping_reply_callback = peerCountHandleIcpReply;
mem->ircb_data = psstate;
! mcastSetTtl(thePeerIcpConnection, p->mcast.ttl);
p->mcast.id = mem->id;
reqnum = icpSetCacheKey(fake->key);
! query = icpPeerCreateMessage(ICP_QUERY, 0, url, reqnum, 0);
! icpUdpSend(thePeerIcpConnection,
&p->in_addr,
query,
LOG_ICP_QUERY,
diff -cr squid-2.2.DEVEL3/src/protos.h squid-2.2.peer/src/protos.h
*** squid-2.2.DEVEL3/src/protos.h Sat Jan 30 00:39:21 1999
--- squid-2.2.peer/src/protos.h Sat Apr 3 21:02:18 1999
***************
*** 482,487 ****
--- 482,492 ----
const char *url,
int reqnum,
int pad);
+ extern void *icpPeerCreateMessage(icp_opcode opcode,
+ int flags,
+ const char *url,
+ int reqnum,
+ int pad);
extern int icpUdpSend(int, const struct sockaddr_in *, icp_common_t *, log_type, int);
extern PF icpHandleUdp;
extern PF icpUdpSendQueue;
diff -cr squid-2.2.DEVEL3/src/send-announce.c squid-2.2.peer/src/send-announce.c
*** squid-2.2.DEVEL3/src/send-announce.c Sat Dec 5 01:54:38 1998
--- squid-2.2.peer/src/send-announce.c Sun Apr 4 11:08:00 1999
***************
*** 43,49 ****
void *junk;
if (0 == Config.onoff.announce)
return;
! if (theOutIcpConnection < 0)
return;
cbdataAdd(junk = xmalloc(1), cbdataXfree, 0);
ipcache_nbgethostbyname(Config.Announce.host, send_announce, junk);
--- 43,49 ----
void *junk;
if (0 == Config.onoff.announce)
return;
! if (thePeerIcpConnection < 0)
return;
cbdataAdd(junk = xmalloc(1), cbdataXfree, 0);
ipcache_nbgethostbyname(Config.Announce.host, send_announce, junk);
***************
*** 102,112 ****
S.sin_family = AF_INET;
S.sin_port = htons(port);
S.sin_addr = ia->in_addrs[0];
! assert(theOutIcpConnection > 0);
! x = comm_udp_sendto(theOutIcpConnection,
&S, sizeof(S),
sndbuf, strlen(sndbuf) + 1);
if (x < 0)
! debug(27, 1) ("send_announce: FD %d: %s\n", theOutIcpConnection,
xstrerror());
}
--- 102,112 ----
S.sin_family = AF_INET;
S.sin_port = htons(port);
S.sin_addr = ia->in_addrs[0];
! assert(thePeerIcpConnection > 0);
! x = comm_udp_sendto(thePeerIcpConnection,
&S, sizeof(S),
sndbuf, strlen(sndbuf) + 1);
if (x < 0)
! debug(27, 1) ("send_announce: FD %d: %s\n", thePeerIcpConnection,
xstrerror());
}
diff -cr squid-2.2.DEVEL3/src/structs.h squid-2.2.peer/src/structs.h
*** squid-2.2.DEVEL3/src/structs.h Sun Feb 14 09:35:02 1999
--- squid-2.2.peer/src/structs.h Sat Apr 3 18:48:38 1999
***************
*** 314,319 ****
--- 314,320 ----
struct in_addr tcp_outgoing;
struct in_addr udp_incoming;
struct in_addr udp_outgoing;
+ struct in_addr udp_out_peer;
#if SQUID_SNMP
struct in_addr snmp_incoming;
struct in_addr snmp_outgoing;
diff -cr squid-2.2.DEVEL3/src/tools.c squid-2.2.peer/src/tools.c
*** squid-2.2.DEVEL3/src/tools.c Mon Jan 11 22:55:44 1999
--- squid-2.2.peer/src/tools.c Sun Apr 4 10:57:17 1999
***************
*** 68,74 ****
--- 68,78 ----
if (theInIcpConnection >= 0)
close(theInIcpConnection);
if (theOutIcpConnection >= 0 && theOutIcpConnection != theInIcpConnection)
+ {
close(theOutIcpConnection);
+ if (thePeerIcpConnection != theOutIcpConnection)
+ close(thePeerIcpConnection);
+ }
}
static char *