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
);
26 if (header
.reqnum
== 0)
27 header
.reqnum
= 0xFFFFFFFF;
29 switch (header
.opcode
) {
32 /* We have a valid packet */
33 url
= buf
+ sizeof(header
) + sizeof(u_num32
);
34 if ((icp_request
= urlParse(METHOD_GET
, url
)) == NULL
) {
35 reply
= icpCreateMessage(ICP_OP_ERR
, 0, url
, header
.reqnum
, 0);
36 icpUdpSend(fd
, &from
, reply
, LOG_UDP_INVALID
, PROTO_NONE
);
39 checklist
.src_addr
= from
.sin_addr
;
40 checklist
.request
= icp_request
;
41 allow
= aclCheckFast(Config
.accessList
.icp
, &checklist
);
43 debug(12, 2) ("icpHandleIcpV3: Access Denied for %s by %s.\n",
44 inet_ntoa(from
.sin_addr
), AclMatchedName
);
45 if (clientdbDeniedPercent(from
.sin_addr
) < 95) {
46 reply
= icpCreateMessage(ICP_OP_DENIED
, 0, url
, header
.reqnum
, 0);
47 icpUdpSend(fd
, &from
, reply
, LOG_UDP_DENIED
, icp_request
->protocol
);
51 /* The peer is allowed to use this cache */
52 key
= storeKeyPublic(url
, METHOD_GET
);
53 entry
= storeGet(key
);
54 debug(12, 5) ("icpHandleIcpV3: OPCODE %s\n",
55 IcpOpcodeStr
[header
.opcode
]);
56 if (icpCheckUdpHit(entry
, icp_request
)) {
57 reply
= icpCreateMessage(ICP_OP_HIT
, 0, url
, header
.reqnum
, 0);
58 icpUdpSend(fd
, &from
, reply
, LOG_UDP_HIT
, icp_request
->protocol
);
61 /* if store is rebuilding, return a UDP_HIT, but not a MISS */
62 if (opt_reload_hit_only
&& store_rebuilding
) {
63 reply
= icpCreateMessage(ICP_OP_MISS_NOFETCH
, 0, url
, header
.reqnum
, 0);
64 icpUdpSend(fd
, &from
, reply
, LOG_UDP_MISS_NOFETCH
, icp_request
->protocol
);
65 } else if (hit_only_mode_until
> squid_curtime
) {
66 reply
= icpCreateMessage(ICP_OP_MISS_NOFETCH
, 0, url
, header
.reqnum
, 0);
67 icpUdpSend(fd
, &from
, reply
, LOG_UDP_MISS_NOFETCH
, icp_request
->protocol
);
69 reply
= icpCreateMessage(ICP_OP_MISS
, 0, url
, header
.reqnum
, 0);
70 icpUdpSend(fd
, &from
, reply
, LOG_UDP_MISS
, icp_request
->protocol
);
80 case ICP_OP_MISS_NOFETCH
:
81 if (neighbors_do_private_keys
&& header
.reqnum
== 0) {
82 debug(12, 0) ("icpHandleIcpV3: Neighbor %s returned reqnum = 0\n",
83 inet_ntoa(from
.sin_addr
));
84 debug(12, 0) ("icpHandleIcpV3: Disabling use of private keys\n");
85 neighbors_do_private_keys
= 0;
87 url
= buf
+ sizeof(header
);
88 if (header
.opcode
== ICP_OP_HIT_OBJ
) {
89 data
= url
+ strlen(url
) + 1;
90 xmemcpy((char *) &u
, data
, sizeof(u_short
));
91 data
+= sizeof(u_short
);
93 if ((int) data_sz
> (len
- (data
- buf
))) {
94 debug(12, 0) ("icpHandleIcpV3: ICP_OP_HIT_OBJ object too small\n");
98 debug(12, 3) ("icpHandleIcpV3: %s from %s for '%s'\n",
99 IcpOpcodeStr
[header
.opcode
],
100 inet_ntoa(from
.sin_addr
),
102 if (neighbors_do_private_keys
&& header
.reqnum
)
103 key
= storeKeyPrivate(url
, METHOD_GET
, header
.reqnum
);
105 key
= storeKeyPublic(url
, METHOD_GET
);
106 debug(12, 3) ("icpHandleIcpV3: Looking for key '%s'\n",
108 if ((entry
= storeGet(key
)) == NULL
) {
109 debug(12, 3) ("icpHandleIcpV3: Ignoring %s for NULL Entry.\n",
110 IcpOpcodeStr
[header
.opcode
]);
112 /* call neighborsUdpAck even if ping_status != PING_WAITING */
113 neighborsUdpAck(url
, &header
, &from
, entry
);
122 debug(12, 0) ("icpHandleIcpV3: UNKNOWN OPCODE: %d from %s\n",
123 header
.opcode
, inet_ntoa(from
.sin_addr
));
127 put_free_request_t(icp_request
);