Errata

First Printing: February 2002.

Here's the current list:


Problems installing the Net::Pcap module

The installation of the Net::Pcap module can fail if the pcap.h header file is not installed in /usr/local/include/pcap (which is where Net::Pcap expects to find it). To see where your pcap.h file is installed, use this command:
    locate pcap.h
Use the directory location returned from locate as the value for the INC I- argument to the perl Makefile.PL command. That is, if the directory location returned is /usr/include/pcap, use the following command to build the makefile:
    perl Makefile.PL INC=-I/usr/include/pcap LIBS='-L/usr/lib/pcap -lpcap'
Then proceed with the usual make, make test and make install commands as described in the book. See the README file that comes with Net::Pcap for more details. [Be sure to issue both make test and make install as root.]

"Use of uninitialized value ... " warning messages

Some of the example programs (especially those in Chapter 3) assume that every IP address has an associated IP name. This is an incorrect assumption. When the following line executes and the IP address does NOT have an IP name, a run-time error message is generated:
    my $remote_name = gethostbyaddr( $the_ip, AF_INET );
There are two fixes. The first is to change the line to read:
    my $remote_name = inet_ntoa( $the_ip );
which avoids the problem by only reporting dotted-decimal IP addresses. The second fix it to add an OR to the original statement which has the effect of reporting the IP name if one exists and reporting the IP address is one doesn't:
    my $remote_name = gethostbyaddr( $the_ip, AF_INET ) || inet_ntoa( $the_ip );

Problems running tcp_s1 on Release 2.4 of the Linux Kernel

When writing the book, I tested the programs on a number of operating systems including Release 7.0 and 7.1 of RedHat Linux, as well as LinuxPPC 2000 (a RedHat 6.2 derivative for Macs). I also ran as much of the code as possible through the recent versions of ActivePerl for Windows (from ActiveState). A number of my students have also independently verified the correct behaviour of the programs on Release 7.1 and 7.2 of Mandrake Linux. All the code works as described in the book on these systems and operating systems. Testing used release 5.6.0 and 5.6.1 of Perl, and on Linux, the kernel release was the pre-2.4 release.

Unfortunately, a problem has surfaced with Release 2.4 of the Linux kernel. I first noticed this when demonstrating the tcp_c1 and tcp_s1 programs (from Chapter 3, Sockets) to some of my students (on RedHat Linux 7.2). When the server (tcp_s1) is started and the client (tcp_c1) is then invoked, communication fails and the following error message is generated by the server (which promptly 'dies'):

Bad arg length for Socket::unpack_sockaddr_in, length is 4095, 
should be 16 at /usr/local/lib/perl5/5.6.1/i686-linux/Socket.pm line 312.
To the best of my knowledge, the code which causes this error in tcp_s1 is the call to the recv subroutine, as follows:
    while ( $from_who = accept( CLIENT_SOCK, TCP_SOCK ) )
    {
        my $data;

        $from_who = recv( CLIENT_SOCK, $data, MAX_RECV_LEN, 0 );

        if ( $from_who )
        {
            my ( $the_port, $the_ip ) = sockaddr_in( $from_who );
The code needs to be amended to remove the assignment to the $from_who scalar as a result of the call to recv, as follows:
    while ( $from_who = accept( CLIENT_SOCK, TCP_SOCK ) )
    {
        my $data;

        recv( CLIENT_SOCK, $data, MAX_RECV_LEN, 0 );  # <---- Line changed.

        if ( $from_who )
        {
            my ( $the_port, $the_ip ) = sockaddr_in( $from_who );

Further discussion of this issue can be found on the use.perl.org website.

Chip Turner at RedHat has tracked down the problem for me. As was suspected, my code incorrectly assigned the result from recv to the $from_who variable. Here's the contents of the e-mail from Chip:

Hey Paul,

I've traced down the problem. recvfrom isn't required by the UNIX98 spec to populate the from fields for connection-oriented sockets (in this case, TCP). I've confirmed that this is standard behavior in the default Linux 2.4 kernel.

The man page for recvfrom (which is what Perl's recv ends up using, as can be seen from strace) states:

    If from is not NULL, and the socket is not connection-oriented,
    the source address of the message is filled in.  The argument
    fromlen is a value-result parameter, initialized to the size of
    the buffer associated with from, and modified on return to
    indicate the actual size of the address stored there.
So ... it's a change from the 2.2 kernel to the 2.4 kernel, and is within UNIX98 specifications (and documented in the man page). From a Perl perspective, just don't use the return value of recv when not using a connection-oriented socket (TCP, UNIX domain socket, etc).

Chip.

And here's my reply (I believe this is called 'eating some crow' in North America):

Thanks for this. Great to have the issue resolved.

I need to be more careful. I'd written a client/server pair using UDP, then re-written it to use TCP (and, being lazy, copied/pasted from the UDP code into the TCP programs). That assignment as a result of the call to recv should never have stayed in the TCP code. I'll pay more attention to these details in future.

Thanks for taking the time to devote to this problem. I very much appreciate it.

It's a case of RTFM for me.

Source code for Chapter 3 updated on Saturday, March 9th, 2002.


Incorrect explanation of TELNET network capture in Appendix D

On page 346 in Appendix D, the explanation of how the network capture can be used to determine the login-id and password used by a TELNET user is incorrect. Specifically, when referring to the password, note that the TELNET server does NOT echo the characters typed by the user, so the 'ppaasssswwoorrddhheerree' text should be 'passwordhere'. This behaviour is clearly visible by referring to the network capture from page 338 onwards.

In addition, the opening description on page 333 fails to mention that in addition to issuing the ls command, the user also issues the whoami command immediately before logging-out (see pages 343 through 345 of the network capture).


Extra warnings generated by Perl 5.8.0

The recent 5.8.0 release of Perl gives the following warning message on programs that use the "use 5.6.0;" directive (assuming a 'perl -c test.pl' command-line):
   v-string in use/require non-portable at test.pl line 3.
   test.pl syntax OK
According to the 5.8.0 perldiag documentation, such statements have been designated 'non-portable' (refer to the manpage for more details).

To remove the warning message, change:

    use 5.6.0;
to:
    use 5.006_000;
which does the same thing. (Remember: TMTOWTDI).

Incorrect expansion of the TCP acronym

There are two locations within the text where the TCP acronym is incorrectly expanded to Transport Control Protocol, as opposed to the correct Transmission Control Protocol. The incorrect expansion appears near the bottom of page 69 and at the start of section 3.2.2 on page 103.

My thanks to the 2002/2003 class of undergraduate software engineers for bringing this to my attention.


A corrected SimpleHTTPD from Chapter 4

Here's a re-written (and -- hopefully -- correct) version of the SimpleHTTPD server from Chapter 4 (page 190ff). The original version of this server bombed-out after servicing a single client. Here's the fix.

Error in EtherSnooper 0.06, page 67

The curly braces around the list of items used to initialise the %ip_type_desc hash (at the bottom of the page) should in fact be "(" and ")". Note that the code you can download from this site has this fix applied - it's the book that's wrong. [Thanks for Nick Garfield (of CERN) for pointing this out].

Comment incorrect on page 78: code to process ports

The comment is wrong at the top of the source code. Obviously, "well-known-udp" refers to ports for UDP and "well-known-tcp" refers to ports for TCP. Sorry for the confusion. Code fixed on web-site. [Thanks, again, to Nick Garfield (of CERN) for pointing this out].

Small bug in tcp_c1 (TCP client code)

Ten lines from the bottom of page 135, the
        if ( $from_who )
line should read:
        if ( !$from_who )
as the call to recv behaves differently when called on a TCP socket (as opposed to a socket using UDP).

Return to the Programming the Network with Perl website.