]>
Commit | Line | Data |
---|---|---|
3841dd46 | 1 | /* |
4ac4a490 | 2 | * Copyright (C) 1996-2017 The Squid Software Foundation and contributors |
3841dd46 | 3 | * |
bbc27441 AJ |
4 | * Squid software is distributed under GPLv2+ license and includes |
5 | * contributions from numerous individuals and organizations. | |
6 | * Please see the COPYING and CONTRIBUTORS files for details. | |
3841dd46 | 7 | */ |
8 | ||
bbc27441 AJ |
9 | /* DEBUG: section 53 AS Number handling */ |
10 | ||
582c2af2 | 11 | #include "squid.h" |
445d18a4 | 12 | #include "acl/Acl.h" |
3ad63615 AR |
13 | #include "acl/Asn.h" |
14 | #include "acl/Checklist.h" | |
445d18a4 AJ |
15 | #include "acl/DestinationAsn.h" |
16 | #include "acl/DestinationIp.h" | |
f206b652 | 17 | #include "acl/SourceAsn.h" |
4eac3407 | 18 | #include "acl/Strategised.h" |
eb13c21e | 19 | #include "FwdState.h" |
445d18a4 | 20 | #include "HttpReply.h" |
f206b652 | 21 | #include "HttpRequest.h" |
714e68b7 | 22 | #include "ipcache.h" |
5ceaee75 | 23 | #include "MasterXaction.h" |
f206b652 FC |
24 | #include "mgr/Registration.h" |
25 | #include "radix.h" | |
26 | #include "RequestFlags.h" | |
4d5904f7 | 27 | #include "SquidConfig.h" |
f206b652 FC |
28 | #include "Store.h" |
29 | #include "StoreClient.h" | |
445d18a4 AJ |
30 | |
31 | #define WHOIS_PORT 43 | |
f53969cc | 32 | #define AS_REQBUF_SZ 4096 |
445d18a4 AJ |
33 | |
34 | /* BEGIN of definitions for radix tree entries */ | |
35 | ||
445d18a4 AJ |
36 | /* 32/128 bits address in memory with length */ |
37 | class m_ADDR | |
38 | { | |
39 | public: | |
40 | uint8_t len; | |
b7ac5457 | 41 | Ip::Address addr; |
445d18a4 | 42 | |
b7ac5457 | 43 | m_ADDR() : len(sizeof(Ip::Address)) {}; |
445d18a4 AJ |
44 | }; |
45 | ||
46 | /* END of definitions for radix tree entries */ | |
47 | ||
48 | /* Head for ip to asn radix tree */ | |
49 | ||
50 | struct squid_radix_node_head *AS_tree_head; | |
51 | ||
52 | /* explicit instantiation required for some systems */ | |
53 | ||
d6d0eb11 | 54 | /// \cond AUTODOCS_IGNORE |
445d18a4 AJ |
55 | template cbdata_type CbDataList<int>::CBDATA_CbDataList; |
56 | /// \endcond | |
57 | ||
58 | /** | |
59 | * Structure for as number information. it could be simply | |
60 | * a list but it's coded as a structure for future | |
61 | * enhancements (e.g. expires) | |
62 | */ | |
63 | struct as_info { | |
64 | CbDataList<int> *as_number; | |
f53969cc | 65 | time_t expires; /* NOTUSED */ |
445d18a4 AJ |
66 | }; |
67 | ||
e2e3d39b AJ |
68 | class ASState |
69 | { | |
5c2f68b7 AJ |
70 | CBDATA_CLASS(ASState); |
71 | ||
e2e3d39b AJ |
72 | public: |
73 | ASState(); | |
74 | ~ASState(); | |
75 | ||
445d18a4 AJ |
76 | StoreEntry *entry; |
77 | store_client *sc; | |
e2e3d39b | 78 | HttpRequest::Pointer request; |
445d18a4 AJ |
79 | int as_number; |
80 | int64_t offset; | |
81 | int reqofs; | |
82 | char reqbuf[AS_REQBUF_SZ]; | |
83 | bool dataRead; | |
84 | }; | |
85 | ||
e2e3d39b AJ |
86 | CBDATA_CLASS_INIT(ASState); |
87 | ||
88 | ASState::ASState() : | |
f53969cc SM |
89 | entry(NULL), |
90 | sc(NULL), | |
91 | request(NULL), | |
92 | as_number(0), | |
93 | offset(0), | |
94 | reqofs(0), | |
95 | dataRead(false) | |
e2e3d39b AJ |
96 | { |
97 | memset(reqbuf, 0, AS_REQBUF_SZ); | |
98 | } | |
99 | ||
100 | ASState::~ASState() | |
101 | { | |
102 | debugs(53, 3, entry->url()); | |
103 | storeUnregister(sc, entry, this); | |
dcd84f80 | 104 | entry->unlock("~ASState"); |
e2e3d39b AJ |
105 | } |
106 | ||
445d18a4 AJ |
107 | /** entry into the radix tree */ |
108 | struct rtentry_t { | |
109 | struct squid_radix_node e_nodes[2]; | |
110 | as_info *e_info; | |
111 | m_ADDR e_addr; | |
112 | m_ADDR e_mask; | |
113 | }; | |
114 | ||
115 | static int asnAddNet(char *, int); | |
116 | ||
117 | static void asnCacheStart(int as); | |
118 | ||
119 | static STCB asHandleReply; | |
120 | ||
062e0b16 FC |
121 | #if defined(__cplusplus) |
122 | extern "C" { | |
123 | #endif | |
124 | ||
f53969cc SM |
125 | static int destroyRadixNode(struct squid_radix_node *rn, void *w); |
126 | static int printRadixNode(struct squid_radix_node *rn, void *sentry); | |
445d18a4 | 127 | |
062e0b16 FC |
128 | #if defined(__cplusplus) |
129 | } | |
130 | #endif | |
131 | ||
445d18a4 AJ |
132 | void asnAclInitialize(ACL * acls); |
133 | ||
445d18a4 AJ |
134 | static void destroyRadixNodeInfo(as_info *); |
135 | ||
136 | static OBJH asnStats; | |
137 | ||
138 | /* PUBLIC */ | |
139 | ||
140 | int | |
b7ac5457 | 141 | asnMatchIp(CbDataList<int> *data, Ip::Address &addr) |
445d18a4 AJ |
142 | { |
143 | struct squid_radix_node *rn; | |
144 | as_info *e; | |
145 | m_ADDR m_addr; | |
146 | CbDataList<int> *a = NULL; | |
147 | CbDataList<int> *b = NULL; | |
148 | ||
149 | debugs(53, 3, "asnMatchIp: Called for " << addr ); | |
150 | ||
151 | if (AS_tree_head == NULL) | |
152 | return 0; | |
153 | ||
4dd643d5 | 154 | if (addr.isNoAddr()) |
445d18a4 AJ |
155 | return 0; |
156 | ||
4dd643d5 | 157 | if (addr.isAnyAddr()) |
445d18a4 AJ |
158 | return 0; |
159 | ||
160 | m_addr.addr = addr; | |
161 | ||
162 | rn = squid_rn_match(&m_addr, AS_tree_head); | |
163 | ||
164 | if (rn == NULL) { | |
165 | debugs(53, 3, "asnMatchIp: Address not in as db."); | |
166 | return 0; | |
167 | } | |
168 | ||
169 | debugs(53, 3, "asnMatchIp: Found in db!"); | |
170 | e = ((rtentry_t *) rn)->e_info; | |
171 | assert(e); | |
172 | ||
173 | for (a = data; a; a = a->next) | |
174 | for (b = e->as_number; b; b = b->next) | |
175 | if (a->element == b->element) { | |
176 | debugs(53, 5, "asnMatchIp: Found a match!"); | |
177 | return 1; | |
178 | } | |
179 | ||
180 | debugs(53, 5, "asnMatchIp: AS not in as db."); | |
181 | return 0; | |
182 | } | |
183 | ||
184 | void | |
185 | ACLASN::prepareForUse() | |
186 | { | |
187 | for (CbDataList<int> *i = data; i; i = i-> | |
188 | next) | |
189 | asnCacheStart(i->element); | |
190 | } | |
191 | ||
192 | static void | |
193 | asnRegisterWithCacheManager(void) | |
194 | { | |
8822ebee | 195 | Mgr::RegisterAction("asndb", "AS Number Database", asnStats, 0, 1); |
445d18a4 AJ |
196 | } |
197 | ||
198 | /* initialize the radix tree structure */ | |
199 | ||
f53969cc | 200 | SQUIDCEXTERN int squid_max_keylen; /* yuck.. this is in lib/radix.c */ |
445d18a4 | 201 | |
445d18a4 AJ |
202 | void |
203 | asnInit(void) | |
204 | { | |
742a021b | 205 | static bool inited = false; |
445d18a4 | 206 | squid_max_keylen = 40; |
445d18a4 | 207 | |
742a021b FC |
208 | if (!inited) { |
209 | inited = true; | |
445d18a4 | 210 | squid_rn_init(); |
742a021b | 211 | } |
445d18a4 AJ |
212 | |
213 | squid_rn_inithead(&AS_tree_head, 8); | |
214 | ||
215 | asnRegisterWithCacheManager(); | |
216 | } | |
217 | ||
218 | void | |
219 | asnFreeMemory(void) | |
220 | { | |
221 | squid_rn_walktree(AS_tree_head, destroyRadixNode, AS_tree_head); | |
222 | ||
223 | destroyRadixNode((struct squid_radix_node *) 0, (void *) AS_tree_head); | |
224 | } | |
225 | ||
226 | static void | |
227 | asnStats(StoreEntry * sentry) | |
228 | { | |
229 | storeAppendPrintf(sentry, "Address \tAS Numbers\n"); | |
230 | squid_rn_walktree(AS_tree_head, printRadixNode, sentry); | |
231 | } | |
232 | ||
233 | /* PRIVATE */ | |
234 | ||
445d18a4 AJ |
235 | static void |
236 | asnCacheStart(int as) | |
237 | { | |
238 | LOCAL_ARRAY(char, asres, 4096); | |
239 | StoreEntry *e; | |
e2e3d39b AJ |
240 | ASState *asState = new ASState; |
241 | debugs(53, 3, "AS " << as); | |
445d18a4 AJ |
242 | snprintf(asres, 4096, "whois://%s/!gAS%d", Config.as_whois_server, as); |
243 | asState->as_number = as; | |
5ceaee75 CT |
244 | const MasterXaction::Pointer mx = new MasterXaction(XactionInitiator::initAsn); |
245 | asState->request = HttpRequest::FromUrl(asres, mx); | |
e2e3d39b | 246 | assert(asState->request != NULL); |
445d18a4 | 247 | |
c2a7cefd AJ |
248 | if ((e = storeGetPublic(asres, Http::METHOD_GET)) == NULL) { |
249 | e = storeCreateEntry(asres, asres, RequestFlags(), Http::METHOD_GET); | |
445d18a4 | 250 | asState->sc = storeClientListAdd(e, asState); |
e2e3d39b | 251 | FwdState::fwdStart(Comm::ConnectionPointer(), e, asState->request.getRaw()); |
445d18a4 | 252 | } else { |
1bfe9ade | 253 | e->lock("Asn"); |
445d18a4 AJ |
254 | asState->sc = storeClientListAdd(e, asState); |
255 | } | |
256 | ||
257 | asState->entry = e; | |
445d18a4 | 258 | StoreIOBuffer readBuffer (AS_REQBUF_SZ, asState->offset, asState->reqbuf); |
e2e3d39b | 259 | storeClientCopy(asState->sc, e, readBuffer, asHandleReply, asState); |
445d18a4 AJ |
260 | } |
261 | ||
262 | static void | |
263 | asHandleReply(void *data, StoreIOBuffer result) | |
264 | { | |
265 | ASState *asState = (ASState *)data; | |
266 | StoreEntry *e = asState->entry; | |
267 | char *s; | |
268 | char *t; | |
269 | char *buf = asState->reqbuf; | |
270 | int leftoversz = -1; | |
271 | ||
272 | debugs(53, 3, "asHandleReply: Called with size=" << (unsigned int)result.length); | |
273 | debugs(53, 3, "asHandleReply: buffer='" << buf << "'"); | |
274 | ||
275 | /* First figure out whether we should abort the request */ | |
276 | ||
277 | if (EBIT_TEST(e->flags, ENTRY_ABORTED)) { | |
e2e3d39b | 278 | delete asState; |
445d18a4 AJ |
279 | return; |
280 | } | |
281 | ||
282 | if (result.length == 0 && asState->dataRead) { | |
e2e3d39b AJ |
283 | debugs(53, 3, "asHandleReply: Done: " << e->url()); |
284 | delete asState; | |
445d18a4 AJ |
285 | return; |
286 | } else if (result.flags.error) { | |
e0236918 | 287 | debugs(53, DBG_IMPORTANT, "asHandleReply: Called with Error set and size=" << (unsigned int) result.length); |
e2e3d39b | 288 | delete asState; |
445d18a4 | 289 | return; |
9b769c67 | 290 | } else if (e->getReply()->sline.status() != Http::scOkay) { |
e0236918 | 291 | debugs(53, DBG_IMPORTANT, "WARNING: AS " << asState->as_number << " whois request failed"); |
e2e3d39b | 292 | delete asState; |
445d18a4 AJ |
293 | return; |
294 | } | |
295 | ||
296 | /* | |
297 | * Next, attempt to parse our request | |
298 | * Remembering that the actual buffer size is retsize + reqofs! | |
299 | */ | |
300 | s = buf; | |
301 | ||
302 | while ((size_t)(s - buf) < result.length + asState->reqofs && *s != '\0') { | |
303 | while (*s && xisspace(*s)) | |
742a021b | 304 | ++s; |
445d18a4 | 305 | |
742a021b | 306 | for (t = s; *t; ++t) { |
445d18a4 AJ |
307 | if (xisspace(*t)) |
308 | break; | |
309 | } | |
310 | ||
311 | if (*t == '\0') { | |
312 | /* oof, word should continue on next block */ | |
313 | break; | |
314 | } | |
315 | ||
316 | *t = '\0'; | |
317 | debugs(53, 3, "asHandleReply: AS# " << s << " (" << asState->as_number << ")"); | |
318 | asnAddNet(s, asState->as_number); | |
319 | s = t + 1; | |
e2e3d39b | 320 | asState->dataRead = true; |
445d18a4 AJ |
321 | } |
322 | ||
323 | /* | |
324 | * Next, grab the end of the 'valid data' in the buffer, and figure | |
325 | * out how much data is left in our buffer, which we need to keep | |
326 | * around for the next request | |
327 | */ | |
328 | leftoversz = (asState->reqofs + result.length) - (s - buf); | |
329 | ||
330 | assert(leftoversz >= 0); | |
331 | ||
332 | /* | |
333 | * Next, copy the left over data, from s to s + leftoversz to the | |
334 | * beginning of the buffer | |
335 | */ | |
41d00cd3 | 336 | memmove(buf, s, leftoversz); |
445d18a4 AJ |
337 | |
338 | /* | |
339 | * Next, update our offset and reqofs, and kick off a copy if required | |
340 | */ | |
341 | asState->offset += result.length; | |
342 | ||
343 | asState->reqofs = leftoversz; | |
344 | ||
345 | debugs(53, 3, "asState->offset = " << asState->offset); | |
346 | ||
347 | if (e->store_status == STORE_PENDING) { | |
348 | debugs(53, 3, "asHandleReply: store_status == STORE_PENDING: " << e->url() ); | |
349 | StoreIOBuffer tempBuffer (AS_REQBUF_SZ - asState->reqofs, | |
350 | asState->offset, | |
351 | asState->reqbuf + asState->reqofs); | |
352 | storeClientCopy(asState->sc, | |
353 | e, | |
354 | tempBuffer, | |
355 | asHandleReply, | |
356 | asState); | |
357 | } else { | |
358 | StoreIOBuffer tempBuffer; | |
359 | debugs(53, 3, "asHandleReply: store complete, but data received " << e->url() ); | |
360 | tempBuffer.offset = asState->offset; | |
361 | tempBuffer.length = AS_REQBUF_SZ - asState->reqofs; | |
362 | tempBuffer.data = asState->reqbuf + asState->reqofs; | |
363 | storeClientCopy(asState->sc, | |
364 | e, | |
365 | tempBuffer, | |
366 | asHandleReply, | |
367 | asState); | |
368 | } | |
369 | } | |
370 | ||
445d18a4 AJ |
371 | /** |
372 | * add a network (addr, mask) to the radix tree, with matching AS number | |
373 | */ | |
374 | static int | |
375 | asnAddNet(char *as_string, int as_number) | |
376 | { | |
445d18a4 AJ |
377 | struct squid_radix_node *rn; |
378 | CbDataList<int> **Tail = NULL; | |
379 | CbDataList<int> *q = NULL; | |
380 | as_info *asinfo = NULL; | |
381 | ||
b7ac5457 AJ |
382 | Ip::Address mask; |
383 | Ip::Address addr; | |
445d18a4 AJ |
384 | char *t; |
385 | int bitl; | |
386 | ||
387 | t = strchr(as_string, '/'); | |
388 | ||
389 | if (t == NULL) { | |
390 | debugs(53, 3, "asnAddNet: failed, invalid response from whois server."); | |
391 | return 0; | |
392 | } | |
393 | ||
394 | *t = '\0'; | |
395 | addr = as_string; | |
396 | bitl = atoi(t + 1); | |
397 | ||
398 | if (bitl < 0) | |
399 | bitl = 0; | |
400 | ||
401 | // INET6 TODO : find a better way of identifying the base IPA family for mask than this. | |
402 | t = strchr(as_string, '.'); | |
403 | ||
404 | // generate Netbits Format Mask | |
4dd643d5 AJ |
405 | mask.setNoAddr(); |
406 | mask.applyMask(bitl, (t!=NULL?AF_INET:AF_INET6) ); | |
445d18a4 AJ |
407 | |
408 | debugs(53, 3, "asnAddNet: called for " << addr << "/" << mask ); | |
409 | ||
726904ad | 410 | rtentry_t *e = (rtentry_t *)xcalloc(1, sizeof(rtentry_t)); |
445d18a4 AJ |
411 | |
412 | e->e_addr.addr = addr; | |
413 | ||
414 | e->e_mask.addr = mask; | |
415 | ||
416 | rn = squid_rn_lookup(&e->e_addr, &e->e_mask, AS_tree_head); | |
417 | ||
418 | if (rn != NULL) { | |
419 | asinfo = ((rtentry_t *) rn)->e_info; | |
420 | ||
421 | if (asinfo->as_number->find(as_number)) { | |
422 | debugs(53, 3, "asnAddNet: Ignoring repeated network '" << addr << "/" << bitl << "' for AS " << as_number); | |
423 | } else { | |
424 | debugs(53, 3, "asnAddNet: Warning: Found a network with multiple AS numbers!"); | |
425 | ||
426 | for (Tail = &asinfo->as_number; *Tail; Tail = &(*Tail)->next); | |
427 | q = new CbDataList<int> (as_number); | |
428 | ||
429 | *(Tail) = q; | |
430 | ||
431 | e->e_info = asinfo; | |
432 | } | |
433 | } else { | |
434 | q = new CbDataList<int> (as_number); | |
435 | asinfo = (as_info *)xmalloc(sizeof(as_info)); | |
436 | asinfo->as_number = q; | |
58ff1033 | 437 | squid_rn_addroute(&e->e_addr, &e->e_mask, AS_tree_head, e->e_nodes); |
445d18a4 AJ |
438 | rn = squid_rn_match(&e->e_addr, AS_tree_head); |
439 | assert(rn != NULL); | |
440 | e->e_info = asinfo; | |
441 | } | |
442 | ||
f53969cc | 443 | if (rn == 0) { /* assert might expand to nothing */ |
445d18a4 AJ |
444 | xfree(asinfo); |
445 | delete q; | |
446 | xfree(e); | |
447 | debugs(53, 3, "asnAddNet: Could not add entry."); | |
448 | return 0; | |
449 | } | |
450 | ||
451 | e->e_info = asinfo; | |
452 | return 1; | |
453 | } | |
454 | ||
455 | static int | |
456 | destroyRadixNode(struct squid_radix_node *rn, void *w) | |
457 | { | |
458 | ||
459 | struct squid_radix_node_head *rnh = (struct squid_radix_node_head *) w; | |
460 | ||
461 | if (rn && !(rn->rn_flags & RNF_ROOT)) { | |
462 | rtentry_t *e = (rtentry_t *) rn; | |
463 | rn = squid_rn_delete(rn->rn_key, rn->rn_mask, rnh); | |
464 | ||
465 | if (rn == 0) | |
466 | debugs(53, 3, "destroyRadixNode: internal screwup"); | |
467 | ||
468 | destroyRadixNodeInfo(e->e_info); | |
469 | ||
470 | xfree(rn); | |
471 | } | |
472 | ||
473 | return 1; | |
474 | } | |
475 | ||
476 | static void | |
477 | destroyRadixNodeInfo(as_info * e_info) | |
478 | { | |
479 | CbDataList<int> *prev = NULL; | |
480 | CbDataList<int> *data = e_info->as_number; | |
481 | ||
482 | while (data) { | |
483 | prev = data; | |
484 | data = data->next; | |
485 | delete prev; | |
486 | } | |
445d18a4 AJ |
487 | } |
488 | ||
489 | static int | |
490 | printRadixNode(struct squid_radix_node *rn, void *_sentry) | |
491 | { | |
492 | StoreEntry *sentry = (StoreEntry *)_sentry; | |
493 | rtentry_t *e = (rtentry_t *) rn; | |
494 | CbDataList<int> *q; | |
495 | as_info *asinfo; | |
496 | char buf[MAX_IPSTRLEN]; | |
b7ac5457 AJ |
497 | Ip::Address addr; |
498 | Ip::Address mask; | |
445d18a4 AJ |
499 | |
500 | assert(e); | |
501 | assert(e->e_info); | |
502 | addr = e->e_addr.addr; | |
503 | mask = e->e_mask.addr; | |
504 | storeAppendPrintf(sentry, "%s/%d\t", | |
4dd643d5 AJ |
505 | addr.toStr(buf, MAX_IPSTRLEN), |
506 | mask.cidr() ); | |
445d18a4 AJ |
507 | asinfo = e->e_info; |
508 | assert(asinfo->as_number); | |
509 | ||
510 | for (q = asinfo->as_number; q; q = q->next) | |
511 | storeAppendPrintf(sentry, " %d", q->element); | |
512 | ||
513 | storeAppendPrintf(sentry, "\n"); | |
514 | ||
515 | return 0; | |
516 | } | |
517 | ||
518 | ACLASN::~ACLASN() | |
519 | { | |
520 | if (data) | |
521 | delete data; | |
522 | } | |
523 | ||
524 | bool | |
525 | ||
b7ac5457 | 526 | ACLASN::match(Ip::Address toMatch) |
445d18a4 AJ |
527 | { |
528 | return asnMatchIp(data, toMatch); | |
529 | } | |
530 | ||
8966008b | 531 | SBufList |
4f8ca96e | 532 | ACLASN::dump() const |
445d18a4 | 533 | { |
8966008b FC |
534 | SBufList sl; |
535 | ||
445d18a4 AJ |
536 | CbDataList<int> *ldata = data; |
537 | ||
538 | while (ldata != NULL) { | |
8966008b FC |
539 | SBuf s; |
540 | s.Printf("%d", ldata->element); | |
541 | sl.push_back(s); | |
445d18a4 AJ |
542 | ldata = ldata->next; |
543 | } | |
544 | ||
8966008b | 545 | return sl; |
445d18a4 AJ |
546 | } |
547 | ||
548 | bool | |
549 | ACLASN::empty () const | |
550 | { | |
551 | return data == NULL; | |
552 | } | |
553 | ||
554 | void | |
555 | ACLASN::parse() | |
556 | { | |
557 | CbDataList<int> **curlist = &data; | |
558 | CbDataList<int> **Tail; | |
559 | CbDataList<int> *q = NULL; | |
560 | char *t = NULL; | |
561 | ||
562 | for (Tail = curlist; *Tail; Tail = &((*Tail)->next)); | |
16c5ad96 | 563 | while ((t = ConfigParser::strtokFile())) { |
445d18a4 AJ |
564 | q = new CbDataList<int> (atoi(t)); |
565 | *(Tail) = q; | |
566 | Tail = &q->next; | |
567 | } | |
568 | } | |
569 | ||
b7ac5457 | 570 | ACLData<Ip::Address> * |
445d18a4 AJ |
571 | ACLASN::clone() const |
572 | { | |
573 | if (data) | |
574 | fatal ("cloning of ACLASN not implemented"); | |
575 | ||
576 | return new ACLASN(*this); | |
577 | } | |
578 | ||
579 | /* explicit template instantiation required for some systems */ | |
580 | ||
b7ac5457 | 581 | template class ACLStrategised<Ip::Address>; |
445d18a4 | 582 | |
445d18a4 | 583 | int |
4eac3407 | 584 | ACLSourceASNStrategy::match (ACLData<Ip::Address> * &data, ACLFilledChecklist *checklist) |
445d18a4 AJ |
585 | { |
586 | return data->match(checklist->src_addr); | |
587 | } | |
588 | ||
445d18a4 | 589 | int |
4eac3407 | 590 | ACLDestinationASNStrategy::match (ACLData<MatchType> * &data, ACLFilledChecklist *checklist) |
445d18a4 | 591 | { |
5c51bffb | 592 | const ipcache_addrs *ia = ipcache_gethostbyname(checklist->request->url.host(), IP_LOOKUP_IF_MISS); |
445d18a4 AJ |
593 | |
594 | if (ia) { | |
742a021b | 595 | for (int k = 0; k < (int) ia->count; ++k) { |
445d18a4 AJ |
596 | if (data->match(ia->in_addrs[k])) |
597 | return 1; | |
598 | } | |
599 | ||
600 | return 0; | |
601 | ||
450fe1cb | 602 | } else if (!checklist->request->flags.destinationIpLookedUp) { |
445d18a4 | 603 | /* No entry in cache, lookup not attempted */ |
5c51bffb | 604 | debugs(28, 3, "can't yet compare '" << AclMatchedName << "' ACL for " << checklist->request->url.host()); |
6f58d7d7 AR |
605 | if (checklist->goAsync(DestinationIPLookup::Instance())) |
606 | return -1; | |
607 | // else fall through to noaddr match, hiding the lookup failure (XXX) | |
445d18a4 | 608 | } |
e936c41c | 609 | Ip::Address noaddr; |
4dd643d5 | 610 | noaddr.setNoAddr(); |
e936c41c | 611 | return data->match(noaddr); |
445d18a4 AJ |
612 | } |
613 |