3 /* Currently Harvest cached-2.x uses ICP_VERSION_3 */
5 icpHandleIcpV3(int fd
, struct sockaddr_in from
, char *buf
, int len
)
9 icp_common_t
*headerp
= (icp_common_t
*) (void *) buf
;
10 StoreEntry
*entry
= NULL
;
13 request_t
*icp_request
= NULL
;
20 header
.opcode
= headerp
->opcode
;
21 header
.version
= headerp
->version
;
22 header
.length
= ntohs(headerp
->length
);
23 header
.reqnum
= ntohl(headerp
->reqnum
);
24 header
.flags
= ntohl(headerp
->flags
);
25 header
.shostid
= ntohl(headerp
->shostid
);
27 switch (header
.opcode
) {
29 /* We have a valid packet */
30 url
= buf
+ sizeof(header
) + sizeof(u_num32
);
31 if ((icp_request
= urlParse(METHOD_GET
, url
)) == NULL
) {
32 reply
= icpCreateMessage(ICP_OP_ERR
, 0, url
, header
.reqnum
, 0);
33 icpUdpSend(fd
, &from
, reply
, LOG_UDP_INVALID
, PROTO_NONE
);
36 checklist
.src_addr
= from
.sin_addr
;
37 checklist
.request
= icp_request
;
38 allow
= aclCheckFast(Config
.accessList
.icp
, &checklist
);
40 debug(12, 2) ("icpHandleIcpV3: Access Denied for %s by %s.\n",
41 inet_ntoa(from
.sin_addr
), AclMatchedName
);
42 if (clientdbDeniedPercent(from
.sin_addr
) < 95) {
43 reply
= icpCreateMessage(ICP_OP_DENIED
, 0, url
, header
.reqnum
, 0);
44 icpUdpSend(fd
, &from
, reply
, LOG_UDP_DENIED
, icp_request
->protocol
);
48 /* The peer is allowed to use this cache */
49 key
= storeKeyPublic(url
, METHOD_GET
);
50 entry
= storeGet(key
);
51 debug(12, 5) ("icpHandleIcpV3: OPCODE %s\n",
52 IcpOpcodeStr
[header
.opcode
]);
53 if (icpCheckUdpHit(entry
, icp_request
)) {
54 reply
= icpCreateMessage(ICP_OP_HIT
, 0, url
, header
.reqnum
, 0);
55 icpUdpSend(fd
, &from
, reply
, LOG_UDP_HIT
, icp_request
->protocol
);
58 /* if store is rebuilding, return a UDP_HIT, but not a MISS */
59 if (opt_reload_hit_only
&& store_rebuilding
) {
60 reply
= icpCreateMessage(ICP_OP_MISS_NOFETCH
, 0, url
, header
.reqnum
, 0);
61 icpUdpSend(fd
, &from
, reply
, LOG_UDP_MISS_NOFETCH
, icp_request
->protocol
);
62 } else if (hit_only_mode_until
> squid_curtime
) {
63 reply
= icpCreateMessage(ICP_OP_MISS_NOFETCH
, 0, url
, header
.reqnum
, 0);
64 icpUdpSend(fd
, &from
, reply
, LOG_UDP_MISS_NOFETCH
, icp_request
->protocol
);
66 reply
= icpCreateMessage(ICP_OP_MISS
, 0, url
, header
.reqnum
, 0);
67 icpUdpSend(fd
, &from
, reply
, LOG_UDP_MISS
, icp_request
->protocol
);
77 case ICP_OP_MISS_NOFETCH
:
78 if (neighbors_do_private_keys
&& header
.reqnum
== 0) {
79 debug(12, 0) ("icpHandleIcpV3: Neighbor %s returned reqnum = 0\n",
80 inet_ntoa(from
.sin_addr
));
81 debug(12, 0) ("icpHandleIcpV3: Disabling use of private keys\n");
82 neighbors_do_private_keys
= 0;
84 url
= buf
+ sizeof(header
);
85 if (header
.opcode
== ICP_OP_HIT_OBJ
) {
86 data
= url
+ strlen(url
) + 1;
87 xmemcpy((char *) &u
, data
, sizeof(u_short
));
88 data
+= sizeof(u_short
);
90 if ((int) data_sz
> (len
- (data
- buf
))) {
91 debug(12, 0) ("icpHandleIcpV3: ICP_OP_HIT_OBJ object too small\n");
95 debug(12, 3) ("icpHandleIcpV3: %s from %s for '%s'\n",
96 IcpOpcodeStr
[header
.opcode
],
97 inet_ntoa(from
.sin_addr
),
99 if (neighbors_do_private_keys
&& header
.reqnum
)
100 key
= storeKeyPrivate(url
, METHOD_GET
, header
.reqnum
);
102 key
= storeKeyPublic(url
, METHOD_GET
);
103 debug(12, 3) ("icpHandleIcpV3: Looking for key '%s'\n",
105 if ((entry
= storeGet(key
)) == NULL
) {
106 debug(12, 3) ("icpHandleIcpV3: Ignoring %s for NULL Entry.\n",
107 IcpOpcodeStr
[header
.opcode
]);
109 /* call neighborsUdpAck even if ping_status != PING_WAITING */
110 neighborsUdpAck(url
, &header
, &from
, entry
);
119 debug(12, 0) ("icpHandleIcpV3: UNKNOWN OPCODE: %d from %s\n",
120 header
.opcode
, inet_ntoa(from
.sin_addr
));
124 put_free_request_t(icp_request
);