]>
git.ipfire.org Git - thirdparty/squid.git/blob - scripts/icpserver.pl
3 ## Copyright (C) 1996-2014 The Squid Software Foundation and contributors
5 ## Squid software is distributed under GPLv2+ license and includes
6 ## contributions from numerous individuals and organizations.
7 ## Please see the COPYING and CONTRIBUTORS files for details.
10 # parse and answer ICP type 1 requests via unicast/multicast UDP
11 # cf. <URL:http://excalibur.usc.edu/icpdoc/icp.html>
13 # returns ICP response code, e.g. 2 == HIT, 3 == MISS, 4 == ERROR
14 # by looking at CERN or Netscape style cache directory $cachedir
16 # martin hamilton <m.t.hamilton@lut.ac.uk>
17 # Id: icpserver,v 1.11 1995/11/24 16:20:13 martin Exp martin
19 # usage: icpserver [-c cachedir] [-n] [-p port] [multicast_group]
21 # -c -> set cache directory
22 # -n -> use Netscape cache format (default is CERN)
23 # -p -> port number to listen on (default 3130)
24 # -v -> verbose - writes activitiy log to stderr
26 # group -> multicast group to listen on
31 @CODES=("xxx", "QUERY", "HIT", "MISS", "ERROR");
33 $CACHEDIR=$opt_c||"/usr/local/www/cache";
35 $SERVER=$ARGV[0]||"0.0.0.0";
36 $SERVERIP= ($SERVER =~ m!\d+.\d+.\d+.\d+!) ?
37 pack("C4", split(/\./, $SERVER)) : (gethostbyname($SERVER))[4]; # lazy!
39 $SOCKADDR = 'S n a4 x8';
41 socket(S
, 2, 2, 17) || socket(S
, 2, 1, 17) || die "Couldn't get socket: $!";
42 $us1 = pack($SOCKADDR, 2, $PORT, $SERVERIP);
43 $us2 = pack($SOCKADDR, 2, $PORT, pack("C4", 0,0,0,0));
44 bind(S
, $us1) || bind(S
, $us2) || die "Couldn't bind socket: $!";
45 #bind(S, $us2) || die "Couldn't bind socket: $!";
47 if ($SERVER ne "0.0.0.0") { # i.e. multicast
48 $whoami = (`uname -a`)[0];
50 $whoami =~ /SunOS [^\s]+ 5/ && ($IP_MULTICAST_TTL=19);
51 $whoami =~ /IRIX [^\s]+ 5/ && ($IP_MULTICAST_TTL=23);
52 $whoami =~ /OSF1/ && ($IP_MULTICAST_TTL=12);
55 setsockopt(S
, 0, $IP_ADD_MEMBERSHIP, $SERVERIP."\0\0\0\0")
56 || die "Couldn't join multicast group $SERVER: $!";
59 # Common header for ICP datagrams ... (size in bytes - total 20)
60 # opcode 1 Numeric code indicating type of message
61 # version 1 Version of the protocol being used
62 # length 2 Total length of packet
63 # reqnum 4 Request number assigned by client
64 # authenticator 8 Authentication information (future)
65 # senderid 4 Identification (host id) of sender
68 # requester 4 Host id of original requester URL
69 # url variable URL whose status is to be checked
71 # Type 2 and 3 responses just contain URL, don't return anything else
73 # Might be fast enough to get away without forking or non-blocking I/O ... ?
75 $theiraddr = recv(S
, $ICP_request, 1024, 0);
76 ($junk, $junk, $sourceaddr, $junk) = unpack($SOCKADDR, $theiraddr);
77 @theirip = unpack('C4', $sourceaddr);
79 $URL_length = length($ICP_request) - 24;
80 $request_template = 'CCnx4x8x4a4a' . $URL_length;
81 ($type, $version, $length, $requester, $URL) =
82 unpack($request_template, $ICP_request);
84 $URL =~ s/\.\.\///g
; # be cautious - any others to watch out for ?
86 # lookup object in cache
88 if ($type eq 1 && $URL =~ m!^([^:]+):/?/?([^/]+)/(.*)!) {
89 $scheme = $1; $hostport = $2; $path = $3;
90 if ($path eq "") { $path = "index.html"; }
93 ($host, $port) = split(/:/, $hostport); # strip off port number
94 $port = ":$port" if ($port);
96 foreach (split(/\./, $hostport)) {
97 $match = "$_/$match"; # little-endian -> big-endian conversion
99 $match = "$CACHEDIR/hosts/$match$scheme$port.urls"; # full path
102 open(IN
, "$match") && do {
103 while(<IN
>) { /^$URL / && ($hitmisserr = 2, last); }
108 $hitmisserr = 2 if -f
"$CACHEDIR/$scheme/$hostport/$path";
112 print "$type $hitmisserr ", join(".", @theirip), " $URL\n" if $opt_v;
114 $response_template = 'CCnx4x8x4A' . length($URL);
116 pack($response_template, $hitmisserr, 2, 20 + length($URL), $URL);
117 send(S
, $ICP_response, 0, $theiraddr) || die "Couldn't send request: $!";