static int peerCheckNetdbDirect(ps_state * psstate) { peer *p; int myrtt; int myhops; if (psstate->direct == DIRECT_NO) return 0; myrtt = netdbHostRtt(psstate->request->host); debug(44, 3) ("peerCheckNetdbDirect: MY RTT = %d msec\n", myrtt); debug(44, 3) ("peerCheckNetdbDirect: minimum_direct_rtt = %d msec\n", Config.minDirectRtt); if (myrtt && myrtt <= Config.minDirectRtt) return 1; myhops = netdbHostHops(psstate->request->host); debug(44, 3) ("peerCheckNetdbDirect: MY hops = %d\n", myhops); debug(44, 3) ("peerCheckNetdbDirect: minimum_direct_hops = %d\n", Config.minDirectHops); if (myhops && myhops <= Config.minDirectHops) return 1; p = whichPeer(&psstate->closest_parent_miss); if (p == NULL) return 0; debug(44, 3) ("peerCheckNetdbDirect: closest_parent_miss RTT = %d msec\n", psstate->ping.p_rtt); if (myrtt && myrtt <= psstate->ping.p_rtt) return 1; return 0; }
static void icpHandleIcpV2(int fd, struct sockaddr_in from, char *buf, int len) { icp_common_t header; StoreEntry *entry = NULL; char *url = NULL; const cache_key *key; request_t *icp_request = NULL; int allow = 0; aclCheck_t checklist; icp_common_t *reply; int src_rtt = 0; u_num32 flags = 0; int rtt = 0; int hops = 0; xmemcpy(&header, buf, sizeof(icp_common_t)); /* * Only these fields need to be converted */ header.length = ntohs(header.length); header.reqnum = ntohl(header.reqnum); header.flags = ntohl(header.flags); header.pad = ntohl(header.pad); /* * Length field should match the number of bytes read */ if (len != header.length) { debug(12, 3) ("icpHandleIcpV2: ICP message is too small\n"); return; } switch (header.opcode) { case ICP_QUERY: /* We have a valid packet */ url = buf + sizeof(icp_common_t) + sizeof(u_num32); if (strpbrk(url, w_space)) { url = rfc1738_escape(url); reply = icpCreateMessage(ICP_ERR, 0, url, header.reqnum, 0); icpUdpSend(fd, &from, reply, LOG_UDP_INVALID, 0); break; } if ((icp_request = urlParse(METHOD_GET, url)) == NULL) { reply = icpCreateMessage(ICP_ERR, 0, url, header.reqnum, 0); icpUdpSend(fd, &from, reply, LOG_UDP_INVALID, 0); break; } memset(&checklist, '\0', sizeof(checklist)); checklist.src_addr = from.sin_addr; checklist.my_addr = no_addr; checklist.request = icp_request; allow = aclCheckFast(Config.accessList.icp, &checklist); if (!allow) { debug(12, 2) ("icpHandleIcpV2: Access Denied for %s by %s.\n", inet_ntoa(from.sin_addr), AclMatchedName); if (clientdbCutoffDenied(from.sin_addr)) { /* * count this DENIED query in the clientdb, even though * we're not sending an ICP reply... */ clientdbUpdate(from.sin_addr, LOG_UDP_DENIED, PROTO_ICP, 0); } else { reply = icpCreateMessage(ICP_DENIED, 0, url, header.reqnum, 0); icpUdpSend(fd, &from, reply, LOG_UDP_DENIED, 0); } break; } if (header.flags & ICP_FLAG_SRC_RTT) { rtt = netdbHostRtt(icp_request->host); hops = netdbHostHops(icp_request->host); src_rtt = ((hops & 0xFFFF) << 16) | (rtt & 0xFFFF); if (rtt) flags |= ICP_FLAG_SRC_RTT; } /* The peer is allowed to use this cache */ entry = storeGetPublic(url, METHOD_GET); debug(12, 5) ("icpHandleIcpV2: OPCODE %s\n", icp_opcode_str[header.opcode]); if (icpCheckUdpHit(entry, icp_request)) { reply = icpCreateMessage(ICP_HIT, flags, url, header.reqnum, src_rtt); icpUdpSend(fd, &from, reply, LOG_UDP_HIT, 0); break; } if (Config.onoff.test_reachability && rtt == 0) { if ((rtt = netdbHostRtt(icp_request->host)) == 0) netdbPingSite(icp_request->host); } /* if store is rebuilding, return a UDP_HIT, but not a MISS */ if (store_dirs_rebuilding && opt_reload_hit_only) { reply = icpCreateMessage(ICP_MISS_NOFETCH, flags, url, header.reqnum, src_rtt); icpUdpSend(fd, &from, reply, LOG_UDP_MISS_NOFETCH, 0); } else if (hit_only_mode_until > squid_curtime) { reply = icpCreateMessage(ICP_MISS_NOFETCH, flags, url, header.reqnum, src_rtt); icpUdpSend(fd, &from, reply, LOG_UDP_MISS_NOFETCH, 0); } else if (Config.onoff.test_reachability && rtt == 0) { reply = icpCreateMessage(ICP_MISS_NOFETCH, flags, url, header.reqnum, src_rtt); icpUdpSend(fd, &from, reply, LOG_UDP_MISS_NOFETCH, 0); } else { reply = icpCreateMessage(ICP_MISS, flags, url, header.reqnum, src_rtt); icpUdpSend(fd, &from, reply, LOG_UDP_MISS, 0); } break; case ICP_HIT: #if ALLOW_SOURCE_PING case ICP_SECHO: #endif case ICP_DECHO: case ICP_MISS: case ICP_DENIED: case ICP_MISS_NOFETCH: if (neighbors_do_private_keys && header.reqnum == 0) { debug(12, 0) ("icpHandleIcpV2: Neighbor %s returned reqnum = 0\n", inet_ntoa(from.sin_addr)); debug(12, 0) ("icpHandleIcpV2: Disabling use of private keys\n"); neighbors_do_private_keys = 0; } url = buf + sizeof(icp_common_t); debug(12, 3) ("icpHandleIcpV2: %s from %s for '%s'\n", icp_opcode_str[header.opcode], inet_ntoa(from.sin_addr), url); key = icpGetCacheKey(url, (int) header.reqnum); /* call neighborsUdpAck even if ping_status != PING_WAITING */ neighborsUdpAck(key, &header, &from); break; case ICP_INVALID: case ICP_ERR: break; default: debug(12, 0) ("icpHandleIcpV2: UNKNOWN OPCODE: %d from %s\n", header.opcode, inet_ntoa(from.sin_addr)); break; } if (icp_request) requestDestroy(icp_request); }