]> git.ipfire.org Git - thirdparty/squid.git/blame - src/wccp.cc
url checksum debugging; sometimes URL memory gets trashed
[thirdparty/squid.git] / src / wccp.cc
CommitLineData
320e9f36 1
2/*
1f38f50a 3 * $Id: wccp.cc,v 1.9 1999/08/02 06:18:51 wessels Exp $
320e9f36 4 *
f6308664 5 * DEBUG: section 80 WCCP Support
320e9f36 6 * AUTHOR: Glenn Chisholm
7 *
8 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
9 * ----------------------------------------------------------
10 *
11 * Squid is the result of efforts by numerous individuals from the
12 * Internet community. Development is led by Duane Wessels of the
13 * National Laboratory for Applied Network Research and funded by the
14 * National Science Foundation. Squid is Copyrighted (C) 1998 by
15 * Duane Wessels and the University of California San Diego. Please
16 * see the COPYRIGHT file for full details. Squid incorporates
17 * software developed and/or copyrighted by other sources. Please see
18 * the CREDITS file for full details.
19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
33 *
34 */
35#include "squid.h"
36
eb824054 37#if USE_WCCP
38
320e9f36 39#define WCCP_PORT 2048
40#define WCCP_VERSION 4
41#define WCCP_REVISION 0
42#define WCCP_RESPONSE_SIZE 12448
43#define WCCP_ACTIVE_CACHES 32
44#define WCCP_HASH_SIZE 32
45#define WCCP_BUCKETS 256
46
47#define WCCP_HERE_I_AM 7
48#define WCCP_I_SEE_YOU 8
49#define WCCP_ASSIGN_BUCKET 9
50
51struct wccp_here_i_am_t {
52 int type;
53 int version;
54 int revision;
55 char hash[WCCP_HASH_SIZE];
56 int reserved;
57 int id;
58};
59
60struct wccp_cache_entry_t {
1f38f50a 61 struct in_addr ip_addr;
320e9f36 62 int revision;
ede4c165 63 char hash[WCCP_HASH_SIZE];
320e9f36 64 int reserved;
65};
66
67struct wccp_i_see_you_t {
68 int type;
69 int version;
70 int change;
71 int id;
72 int number;
73 struct wccp_cache_entry_t wccp_cache_entry[WCCP_ACTIVE_CACHES];
74};
75
76struct wccp_assign_bucket_t {
f6308664 77 int type;
78 int id;
79 int number;
320e9f36 80};
81
eb824054 82static int theInWccpConnection = -1;
83static int theOutWccpConnection = -1;
320e9f36 84static struct wccp_here_i_am_t wccp_here_i_am;
b5b86e2c 85static struct wccp_i_see_you_t wccp_i_see_you;
1f38f50a 86static int change;
87static struct in_addr local_ip;
b5b86e2c 88
1f38f50a 89static PF wccpHandleUdp;
90static int wccpLowestIP(void);
91static EVH wccpHereIam;
92static EVH wccpAssignBuckets;
320e9f36 93
320e9f36 94/*
95 * The functions used during startup:
96 * wccpInit
97 * wccpConnectionOpen
98 * wccpConnectionShutdown
99 * wccpConnectionClose
100 */
101
102void
103wccpInit(void)
104{
105 debug(80, 5) ("wccpInit: Called\n");
1f38f50a 106 if (eventFind(wccpHereIam, NULL))
107 return;
320e9f36 108 memset(&wccp_here_i_am, '\0', sizeof(wccp_here_i_am));
109 wccp_here_i_am.type = htonl(WCCP_HERE_I_AM);
110 wccp_here_i_am.version = htonl(WCCP_VERSION);
f6308664 111 wccp_here_i_am.revision = htonl(WCCP_REVISION);
b5b86e2c 112 change = 1;
1f38f50a 113 if (Config.Wccp.router.s_addr != any_addr.s_addr)
114 if (!eventFind(wccpHereIam, NULL))
115 eventAdd("wccpHereIam", wccpHereIam, NULL, 10.0, 1);
320e9f36 116}
117
118void
119wccpConnectionOpen(void)
120{
121 u_short port = WCCP_PORT;
b5b86e2c 122 struct sockaddr_in router, local;
ede4c165 123 int local_len, router_len;
320e9f36 124 debug(80, 5) ("wccpConnectionOpen: Called\n");
1f38f50a 125 if (Config.Wccp.router.s_addr == any_addr.s_addr) {
126 debug(1, 1) ("WCCP Disabled.\n");
127 return;
128 }
129 theInWccpConnection = comm_open(SOCK_DGRAM,
130 0,
131 Config.Wccp.incoming,
132 port,
133 COMM_NONBLOCKING,
134 "WCCP Socket");
135 if (theInWccpConnection < 0)
136 fatal("Cannot open WCCP Port");
137 commSetSelect(theInWccpConnection,
138 COMM_SELECT_READ,
139 wccpHandleUdp,
140 NULL,
141 0);
142 debug(1, 1) ("Accepting WCCP messages on port %d, FD %d.\n",
143 (int) port, theInWccpConnection);
144 if (Config.Wccp.outgoing.s_addr != no_addr.s_addr) {
145 theOutWccpConnection = comm_open(SOCK_DGRAM,
320e9f36 146 0,
1f38f50a 147 Config.Wccp.outgoing,
320e9f36 148 port,
149 COMM_NONBLOCKING,
1f38f50a 150 "WCCP Socket");
151 if (theOutWccpConnection < 0)
152 fatal("Cannot open Outgoing WCCP Port");
153 commSetSelect(theOutWccpConnection,
154 COMM_SELECT_READ,
155 wccpHandleUdp,
156 NULL, 0);
157 debug(1, 1) ("Outgoing WCCP messages on port %d, FD %d.\n",
158 (int) port, theOutWccpConnection);
159 fd_note(theOutWccpConnection, "Outgoing WCCP socket");
160 fd_note(theInWccpConnection, "Incoming WCCP socket");
f6308664 161 } else {
1f38f50a 162 theOutWccpConnection = theInWccpConnection;
320e9f36 163 }
b5b86e2c 164 router_len = sizeof(router);
165 memset(&router, '\0', router_len);
166 router.sin_family = AF_INET;
1f38f50a 167 router.sin_port = htons(port);
ede4c165 168 router.sin_addr = Config.Wccp.router;
169 if (connect(theOutWccpConnection, (struct sockaddr *) &router, router_len))
170 fatal("Unable to connect WCCP out socket");
ede4c165 171 local_len = sizeof(local);
b5b86e2c 172 memset(&local, '\0', local_len);
ede4c165 173 if (getsockname(theOutWccpConnection, (struct sockaddr *) &local, &local_len))
b5b86e2c 174 fatal("Unable to getsockname on WCCP out socket");
1f38f50a 175 local_ip.s_addr = local.sin_addr.s_addr;
320e9f36 176}
177
178void
179wccpConnectionShutdown(void)
180{
181 if (theInWccpConnection < 0)
182 return;
183 if (theInWccpConnection != theOutWccpConnection) {
184 debug(80, 1) ("FD %d Closing WCCP socket\n", theInWccpConnection);
185 comm_close(theInWccpConnection);
186 }
320e9f36 187 assert(theOutWccpConnection > -1);
188 commSetSelect(theOutWccpConnection, COMM_SELECT_READ, NULL, NULL, 0);
189}
190
191void
192wccpConnectionClose(void)
193{
194 wccpConnectionShutdown();
195 if (theOutWccpConnection > -1) {
196 debug(80, 1) ("FD %d Closing WCCP socket\n", theOutWccpConnection);
197 comm_close(theOutWccpConnection);
198 }
199}
200
201/*
202 * Functions for handling the requests.
203 */
204
320e9f36 205/*
206 * Accept the UDP packet
f6308664 207 */
1f38f50a 208static void
320e9f36 209wccpHandleUdp(int sock, void *not_used)
f6308664 210{
320e9f36 211 struct sockaddr_in from;
f6308664 212 socklen_t from_len;
213 int len;
320e9f36 214
215 debug(80, 6) ("wccpHandleUdp: Called.\n");
f6308664 216
320e9f36 217 commSetSelect(sock, COMM_SELECT_READ, wccpHandleUdp, NULL, 0);
218 from_len = sizeof(struct sockaddr_in);
219 memset(&from, '\0', from_len);
b5b86e2c 220 memset(&wccp_i_see_you, '\0', sizeof(wccp_i_see_you));
f6308664 221
320e9f36 222 Counter.syscalls.sock.recvfroms++;
f6308664 223
320e9f36 224 len = recvfrom(sock,
f6308664 225 &wccp_i_see_you,
226 WCCP_RESPONSE_SIZE,
227 0,
228 (struct sockaddr *) &from,
229 &from_len);
b5b86e2c 230 if (len < 0)
231 return;
ede4c165 232 if (Config.Wccp.router.s_addr != from.sin_addr.s_addr)
b5b86e2c 233 return;
234 if (ntohl(wccp_i_see_you.version) != WCCP_VERSION)
235 return;
236 if (ntohl(wccp_i_see_you.type) != WCCP_I_SEE_YOU)
237 return;
ede4c165 238 if (!change) {
b5b86e2c 239 change = wccp_i_see_you.change;
240 return;
241 }
242 if (change != wccp_i_see_you.change) {
243 change = wccp_i_see_you.change;
1f38f50a 244 if (wccpLowestIP())
b5b86e2c 245 if (!eventFind(wccpAssignBuckets, NULL))
ede4c165 246 eventAdd("wccpAssignBuckets", wccpAssignBuckets, NULL, 30.0, 1);
b5b86e2c 247 }
248}
f6308664 249
1f38f50a 250static int
251wccpLowestIP(void)
b5b86e2c 252{
253 int loop;
254 for (loop = 0; loop < ntohl(wccp_i_see_you.number); loop++) {
1f38f50a 255 if (wccp_i_see_you.wccp_cache_entry[loop].ip_addr.s_addr < local_ip.s_addr)
256 return 0;
f6308664 257 }
1f38f50a 258 return 1;
f6308664 259}
320e9f36 260
1f38f50a 261static void
320e9f36 262wccpHereIam(void *voidnotused)
263{
f6308664 264 debug(80, 6) ("wccpHereIam: Called\n");
320e9f36 265
b5b86e2c 266 wccp_here_i_am.id = wccp_i_see_you.id;
267 send(theOutWccpConnection,
f6308664 268 &wccp_here_i_am,
269 sizeof(wccp_here_i_am),
b5b86e2c 270 0);
320e9f36 271
1f38f50a 272 if (!eventFind(wccpHereIam, NULL))
273 eventAdd("wccpHereIam", wccpHereIam, NULL, 10.0, 1);
320e9f36 274}
275
1f38f50a 276static void
b5b86e2c 277wccpAssignBuckets(void *voidnotused)
320e9f36 278{
279 struct wccp_assign_bucket_t wccp_assign_bucket;
1f38f50a 280 int number_buckets;
281 int loop_buckets;
282 int loop;
283 int number_caches;
284 int bucket = 0;
285 int *caches;
286 int offset;
f20d9f17 287 char buckets[WCCP_BUCKETS];
1f38f50a 288 char *buf;
320e9f36 289
290 debug(80, 6) ("wccpAssignBuckets: Called\n");
291 memset(&wccp_assign_bucket, '\0', sizeof(wccp_assign_bucket));
f20d9f17 292 memset(buckets, 0xFF, WCCP_BUCKETS);
320e9f36 293
b5b86e2c 294 number_caches = ntohl(wccp_i_see_you.number);
f6308664 295 if (number_caches > WCCP_ACTIVE_CACHES)
320e9f36 296 number_caches = WCCP_ACTIVE_CACHES;
f20d9f17 297 caches = xmalloc(sizeof(int) * number_caches);
320e9f36 298
f6308664 299 number_buckets = WCCP_BUCKETS / number_caches;
f6308664 300 for (loop = 0; loop < number_caches; loop++) {
1f38f50a 301 xmemcpy(&caches[loop],
302 &wccp_i_see_you.wccp_cache_entry[loop].ip_addr.s_addr,
303 sizeof(*caches));
f6308664 304 for (loop_buckets = 0; loop_buckets < number_buckets; loop_buckets++) {
f20d9f17 305 buckets[bucket++] = loop;
320e9f36 306 }
307 }
f20d9f17 308 offset = sizeof(wccp_assign_bucket);
309 buf = xmalloc(offset + WCCP_BUCKETS + (sizeof(*caches) * number_caches));
ede4c165 310 wccp_assign_bucket.type = htonl(WCCP_ASSIGN_BUCKET);
b5b86e2c 311 wccp_assign_bucket.id = wccp_i_see_you.id;
ede4c165 312 wccp_assign_bucket.number = wccp_i_see_you.number;
f20d9f17 313
1f38f50a 314 xmemcpy(buf, &wccp_assign_bucket, offset);
315 xmemcpy(buf + offset, caches, (sizeof(*caches) * number_caches));
f20d9f17 316 offset += (sizeof(*caches) * number_caches);
1f38f50a 317 xmemcpy(buf + offset, buckets, WCCP_BUCKETS);
f20d9f17 318 offset += WCCP_BUCKETS;
b5b86e2c 319 send(theOutWccpConnection,
f20d9f17 320 buf,
321 offset,
b5b86e2c 322 0);
323 change = 0;
1f38f50a 324 xfree(caches);
325 xfree(buf);
320e9f36 326}
eb824054 327
328#endif /* USE_WCCP */