TCP/IP Server
The Towers of Hanoi as a TCP/IP Server.
#! /usr/bin/perl -w
#
# The Towers Of Hanoi
# Network Server (TCP/IP) Implementation
# Copyright (C) 1998 Amit Singh. All Rights Reserved.
# http://hanoi.kernelthread.com
#
# Tested on Linux
#
# Check against $PATH `tricks'
#
BEGIN { $ENV{PATH} = '/sbin:/bin' }
# --- configurable section ---
my $TRUSTED_USER = "root"; # only this username trusted
my $TRUSTED_HOST = "localhost"; # requests from this hostname only
my $TRUSTED_ADDR = "127.0.0.1"; # requests from this IP addr only
my $HANOID_LOG = "/tmp/hanoid.log"; # path to the logfile
my $HANOID_PORT = "1234"; # port to listen on
# --- end of configurable section ---
use strict;
use Socket;
use Carp;
# Setup and start
#
my $port = $HANOID_PORT;
my $proto = getprotobyname('tcp');
$port = $1 if $port =~ /(\d+)/;
socket(S, PF_INET, SOCK_STREAM, $proto) || die "socket: $!";
setsockopt(S, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)) || die "setsockopt: $!";
bind(S, sockaddr_in($port, INADDR_ANY)) || die "bind: $!";
listen(S, SOMAXCONN) || die "listen: $!";
logmsg("server started on port $port\n");
$SIG{CHLD} = \&REAPER;
my ($t_paddr, $t_port, $t_iaddr, $t_host, $t_addr, $t_user);
for ( ; $t_paddr = accept(Client, S); close Client) {
($t_port, $t_iaddr) = sockaddr_in($t_paddr);
$t_host = gethostbyaddr($t_iaddr, AF_INET);
$t_addr = inet_ntoa($t_iaddr);
logmsg("query $t_port, $port, $t_host\n");
$t_user = auth_rfc931($t_port, $port, $t_host);
if ( ($t_addr eq $TRUSTED_ADDR) &&
($t_host eq $TRUSTED_HOST) #&&
#($t_user eq $TRUSTED_USER)
) {
print Client "Trusted username/hostname/IP combination: OK\n";
my $N = <Client>;
chomp($N);
if (($N < 1) || ($N > 9)) {
print Client "*** Illegal number of disks\n";
print Client "*** Only an integer N (0 < N < 10) permitted\n\n";
} else {
hanoi($N, 3, 1, 2);
}
} else {
print Client "Untrusted username/hostname/IP combination: sorry\n";
}
}
sub
auth_rfc931
{
my $PORT_IDENTD = 113;
my ($local_port, $remote_port, $check_host) = @_;
my ($remote, $port, $iaddr, $paddr, $proto, $line);
my ($f1, $f2, @rest);
$port = $PORT_IDENTD;
$remote = $check_host;
if ($port =~ /\D/) {
$port = getservbyname($port, 'tcp');
}
$iaddr = inet_aton($remote) || return(undef);
$paddr = sockaddr_in($port, $iaddr);
$proto = getprotobyname("tcp");
socket(SOCK, PF_INET, SOCK_STREAM, $proto) || return(undef);
connect(SOCK, $paddr) || return(undef);
my $request = "$local_port, $remote_port\r\n";
syswrite SOCK, $request, length($request);
my $n = sysread SOCK, $line, 128;
close (SOCK) || return(undef);
chomp($line);
logmsg("identd reply $line\n");
($f1, $f2, @rest) = split(/:/, $line);
if (not($f2 =~ /[ \t]*USERID[ \t]*/)) {
return(undef);
}
my $user = $rest[-1];
return($user);
exit;
}
sub
logmsg
{
$|=1;
open(LOG, ">>$HANOID_LOG") || die "open: $!";
my $ctime = localtime();
print LOG "$0 $$: at $ctime @_";
close(LOG);
}
sub
hanoi
{
my ($n, $to, $from, $using) = @_;
if ($n > 0) {
hanoi($n-1, $using, $from, $to);
print Client "move $from --> $to\n";
hanoi($n-1, $to, $using, $from);
}
}
#__END__