#!/usr/bin/perl use Net::POP3; use Digest::MD5; use Getopt::Std; $ConfFile = "/etc/ppp/dtcp.conf"; $AddrFile = "/var/run/dtcp.addr"; $StopFile = "/tmp/dtcp.stop"; $LogFile = "/var/log/dtcp.log"; $ENV{'PATH'} = "/sbin:/usr/sbin:/bin:/usr/bin"; $U_ID = 65534; $G_ID = 65534; getopts('rxd') || &help; $Repeat = $opt_r; $Debug = $opt_d; if ($opt_x) { open(OUT, ">$StopFile") || die; chown $U_ID, $G_ID, $StopFile; close(OUT); exit 0; } if (-f $AddrFile) { unlink $AddrFile; } open(CONF, $ConfFile) || die; while () { chop; next if /^#/ || /^$/; last; } die unless /^(\S+)\s+(\d+)\s+(\S+)\s+(\S+)$/; $host = $1; $port = $2; $user = $3; $pass = $4; close(CONF); open(LOG, ">>$LogFile") || open(LOG, ">&STDERR"); select(LOG); $| = 1; select(stdout); print LOG &strtime(time), " host=$host port=$port user=$user\n"; if (!open(DTCP, "-|")) { $| = 1; ($(,$)) = ($G_ID, $G_ID); # gid: nogroup ($<,$>) = ($U_ID, $U_ID); # uid: nobody while (! &dtcp($host, $port, $user, $pass) && $Repeat) { sleep 10; print STDERR "reconnecting...\n" if $Debug; } exit 0; } $ret = 1; while () { s/[\r\n]*$//; last unless /^\d+\.\d+\.\d+\.\d+$/; $remote = $_; system "ip -6 tunnel del sit1"; if (open(OUT, ">$AddrFile")) { print OUT "$remote\n"; close(OUT); } print STDERR "execute: ifconfig sit0 up tunnel ::$remote\n" if $Debug; system "ifconfig sit0 up tunnel ::$remote"; exit 0 unless $Repeat; $ret = 0; } if (-f $AddrFile) { unlink $AddrFile; } exit $ret; sub help { print < opt: -r ; reconnect -x ; stop -d ; debug EOF exit 1; } sub dtcp { my ($host, $port, $user, $pass) = @_; my $pop = Net::POP3->new($host, Port => $port, Debug => $Debug); return undef unless $pop; my $banner = ${*$pop}{'net_pop3_banner'}; if ($banner =~ /^(\S+)\s/) { $banner = $1; } else { print LOG &strtime(time), " Unknown banner: $banner\n"; $pop->close(); return undef; } my $md = Digest::MD5->new(); $md->add($user, $banner, $pass); my $cmd = $pop->command('tunnel', $user, $md->hexdigest, 'network'); my $response = $cmd->getline(); $pop->debug_print(0, $response) if $Debug; if ($response =~ /^\+OK\s+(\d+\.\d+\.\d+\.\d+)\s+(\d+\.\d+\.\d+\.\d+)\s+([\d\:a-fA-F]+)\/(\d+)/) { ($local, $remote, $prefix, $nbits) = ($1, $2, $3, $4); } else { $response =~ s/[\r\n]*$//; print LOG &strtime(time), " Unknown response: $response\n"; $pop->close(); return undef; } print LOG &strtime(time), " local=$local remote=$remote network=$prefix/$nbits\n"; print "$remote\n"; while (1) { sleep 30; my $cmd = $pop->command('ping'); my $pong = $cmd->getline(); $pop->debug_print(0, $pong) if $Debug; unless ($pong =~ /^\+OK pong/) { $pong =~ s/[\r\n]*$//; print LOG &strtime(time), " Unknown pong: $pong\n"; $pop->close(); return undef; } if (-f $StopFile) { my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blocks) = stat($StopFile); if ($uid == $U_ID) { print LOG &strtime(time), " found $StopFile, terminating\n"; unlink $StopFile; last; } } } $response = $pop->command('quit')->getline(); $pop->debug_print(0, $response) if $Debug; $pop->close(); return 1; } sub strtime { my ($time) = @_; my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time); sprintf("%4d-%02d-%02d %02d:%02d:%02d", $year+1900, $mon+1, $mday, $hour, $min, $sec); }