js1 has asked for the wisdom of the Perl Monks concerning the following question:

Monks,

I'm struggling with a small piece of code which sends an ICAP header, and some HTTP headers to an ICAP server (Antivirus scanner).

If I telnet to the ICAP server and enter the text, it works fine, but if I send the text via IO::Socket, I get back an error 400.

#!/opt/perl-5.8.0/bin/perl use IO::Socket::INET; $|=1; $remote_host="biavl01.baplc.com"; $remote_port=1344; $socket = IO::Socket::INET->new(PeerAddr => $remote_host, PeerPort => $remote_port, Proto => "tcp", Type => SOCK_STREAM) or die "Couldn't connect to $remote_host:$remote_port : $!\n"; die "no socket" if ! defined $socket; # get text of respmod open(FH,"/home/u752359/respmod.txt"); undef $/; $respmod=<FH>; # send respmod over the socket, print $socket $respmod; # get response $|=1; @resp=<$socket>; print @resp; close($socket);

This is the ICAP request I'm sending:

RESPMOD icap://biavl01.baplc.com/avscan ICAP/1.0 Host: biavl01.baplc.com X-Scan-Progress-Interval: 3 X-Client-IP: 161.2.124.27 X-Server-IP: 161.2.66.50 Allow: 204 Encapsulated: req-hdr=0, res-hdr=142, res-body=460 GET /EICAR.COM HTTP/1.0 Host: ebiztools.baplc.com User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .N +ET CLR 1.1.4322) HTTP/1.1 200 OK Date: Mon, 17 Oct 2005 10:22:01 GMT Server: Apache/2.0.54 (Unix) PHP/4.3.11 mod_jk/1.2.8 mod_perl/1.99_19 +Perl/v5.8.3 Last-Modified: Fri, 14 Oct 2005 10:28:23 GMT ETag: "4260-45-512d5fc0" Accept-Ranges: bytes Content-Length: 68 Connection: close Content-Type: text/plain; charset=ISO-8859-1 44 X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H* 0

Any ideas where my code might be going wrong?
Thanks,
js.

Replies are listed 'Best First'.
Re: IO::Socket problem
by BrowserUk (Patriarch) on Oct 18, 2005 at 10:27 UTC

    Is it possible that when you send the text via telnet, the "\n"s, in the text are probably being converted to full CRLFs, but when you slurp the file they are being sent as just LFs?


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    The "good enough" maybe good enough for the now, and perfection maybe unobtainable, but that should not preclude us from striving for perfection, when time, circumstance or desire allow.
      Spot on! That was the problem. Thanks for solving that for me.
      js.
Re: IO::Socket problem
by tirwhan (Abbot) on Oct 18, 2005 at 11:39 UTC

    Try using ethereal or tcpdump to catch the network traffic generated when you connect manually and connect via the script and then compare the output. It should be possible to spot differences relatively easily.

    Command line for catching the traffic with tcpdump and dumping it in a file:

    tcpdump -w dumpfile host biavl01.baplc.com and port 1344

    You can then view this file with

    tcpdump -r dumpfile -xX -s1500

    (Note you need to be root to run the capture)

    Another possibility to find out what's going on (which produces output that's easier to parse for humans) is to use the fantastically useful socat and proxy the connection via that. For example:

    socat -vv tcp4-listen:4000,reuseaddr,fork tcp4:biavl01.baplc.com:1344
    wil create a proxy between your local host's port 4000 and the remote destination. Now just connect to the local port (via telnet and/or your script) and socat will print out the data transferred.

Re: IO::Socket problem
by castaway (Parson) on Oct 18, 2005 at 09:30 UTC
    Is it maybe because you are only reading one line from the file, and then sending it? Try outputting the line you read from the file, and see what it is you are sending. Also, is that really all the contents of the file you want to send, or is some of it the response you are looking for?

    C.

      undef $/;

      turns off the line separator, so the whole file goes into variable $respmod.

      If I print this it is exactly the same as the file contents. And yes, I do want to include those response headers (these are used in the ICAP response modification.)

        Oops, I missed that bit! /me hides.

        C.