summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'net-dialup/pptpclient/files/pptp_fe.pl')
-rw-r--r--net-dialup/pptpclient/files/pptp_fe.pl370
1 files changed, 370 insertions, 0 deletions
diff --git a/net-dialup/pptpclient/files/pptp_fe.pl b/net-dialup/pptpclient/files/pptp_fe.pl
new file mode 100644
index 000000000000..01d291c9ade1
--- /dev/null
+++ b/net-dialup/pptpclient/files/pptp_fe.pl
@@ -0,0 +1,370 @@
+#!/usr/bin/perl
+#
+# $Id$
+#
+# pptp_fe.pl, privileged portion of xpptp_fe.pl
+# Copyright (C) 2001 Smoot Carl-Mitchell (smoot@tic.com)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+use strict;
+use Getopt::Std;
+use Time::localtime;
+use IO::Handle;
+
+my $Usage = "usage: pptp_fe [-c config_file] [-d] [-h] [-k] [-n network]
+ [-p] [-r routes] [-t timeout] [host]
+ where:
+ -c - configuration file (default is ~/.pptp_fe.conf)
+ -d - pppd debug flag
+ -h - this help message
+ -k - kill pppd daemon with route to network
+ -n - network number of remote private network in x.x.x.x/n notation
+ -r - routes to add to routing table separated by commas
+ -p - suppress prompting
+ -t - connection timeout retry interval in seconds (default 60 seconds)
+ host - remote PPTP server name
+";
+
+my %Opt;
+getopts("c:dhkn:pr:t:", \%Opt);
+
+my $Config_File = $Opt{'c'};
+$Config_File = "$ENV{'HOME'}/.pptp_fe.conf" unless $Opt{'c'};
+my $Config;
+my $Debug = $Opt{'d'};
+$Debug = 0 unless $Debug;
+my $Debug_Flag = "debug" if $Debug;
+my $Help = $Opt{'h'};
+my $Kill = $Opt{'k'};
+my $Net = $Opt{'n'};
+my $No_Prompt = $Opt{'p'};
+my $Route = $Opt{'r'};
+my $Timeout = $Opt{'t'}; $Timeout = 60 unless $Timeout;
+
+print($Usage), exit(1) if $Help;
+
+my $Server = $ARGV[0];
+
+my $State = "disconnected";
+
+system("modprobe ppp-compress-18");
+
+$Config = cmd_read_config_file($Config_File);
+for my $cmd (@$Config) {
+ cmd_set($cmd, 1);
+}
+
+print "($State) > " unless $No_Prompt;
+STDOUT->flush;
+for (;;) {
+ my $rin = '';
+ my $rout = '';
+ vec($rin, fileno(STDIN), 1) = 1;
+ command() if select($rout=$rin, undef, undef, 5);
+
+ my $interface = "";
+ if ($State eq "connected" && ! ($interface = net_interface_up($Net))) {
+ print "\n";
+ print "interface $interface for $Net not up - restarting\n";
+ cmd_connect();
+ print "($State) > " unless $No_Prompt;;
+ }
+}
+
+sub command {
+
+ my $input;
+ sysread(STDIN, $input, 1024);
+
+ for my $line1 (split("\n", $input)) {
+ my $line = $line1;
+ $line =~ s/\s*$//;
+ $line =~ s/^\s*//;
+ my ($command, $arguments) = split(" ", $line, 2);
+
+ if ($command eq "c") {
+ cmd_connect();
+ }
+ elsif ($command eq "d") {
+ cmd_disconnect();
+ }
+ elsif ($command eq "h") {
+ cmd_help();
+ }
+ elsif ($command eq "l") {
+ cmd_list();
+ }
+ elsif ($command eq "q") {
+ cmd_disconnect();
+ exit 0;
+ }
+ elsif ($command eq "r") {
+ $Config = cmd_read_config_file($arguments);
+ }
+ elsif ($command eq "s") {
+ cmd_set($arguments, 0);
+ }
+ elsif ($command eq "w") {
+ cmd_write_config_file($arguments);
+ }
+ elsif ($command ne "") {
+ print "unknown command\n";
+ }
+ }
+ print "($State) > " unless $No_Prompt;
+ STDOUT->flush;
+}
+
+sub cmd_connect {
+
+ cmd_disconnect() if $State eq "connected";
+
+ my $start_time = time();
+ my $date_string = ctime($start_time);
+ print "$date_string Running pptp $Server $Debug_Flag";
+ system("pptp $Server $Debug_Flag");
+
+ my $interface = "";
+
+ do {
+ sleep 1;
+ $interface = net_interface_up($Net);
+ print ".";
+ } until ($interface || time() > $start_time + $Timeout);
+
+ if (time() > $start_time + $Timeout) {
+ print "timed out after $Timeout sec\n";
+ $State = "disconnected";
+ return 0;
+ }
+
+ print "\n";
+
+ my $ifcfg = `ifconfig $interface`;
+ $ifcfg =~ /P-t-P:(.*) Mask/;
+ my $ip = $1;
+ print "setting route to network $Net to interface $interface\n";
+ system("route add -net $Net dev $interface metric 2");
+
+ # Routes are separated by commas
+ my @route = split(/,/, $Route);
+ for my $route (@route) {
+ my $net_flag = "";
+ $net_flag = "-net" if $route =~ /\//;
+
+ print "setting route to $route to interface $interface\n";
+ system("route add $net_flag $route dev $interface");
+ }
+
+ $State = "connected";
+ print "connected\n";
+ return 1;
+}
+
+sub cmd_disconnect {
+
+ return 1 if $State eq "disconnected";
+
+ my $interface = net_interface_up($Net);
+ my $pid_file = "/var/run/$interface.pid";
+
+ # delete the named pipes - XXX this is a bit crude
+ system("rm -f /var/run/pptp/*");
+
+ $State = "disconnected", return 1 unless $interface && -f $pid_file;
+
+ my $pid = `cat $pid_file`;
+ chomp $pid;
+ print "killing pppd($pid)\n";
+ kill("HUP", $pid);
+ print "waiting for pppd to die";
+ do {
+ sleep 1;
+ print ".";
+ }
+ until (kill(0, $pid));
+
+ print "\n";
+ $State = "disconnected";
+ print "disconnected\n";
+ return 1;
+}
+
+sub cmd_list {
+
+ print "Server = $Server\n";
+ print "Network = $Net\n";
+ print "Routes = $Route\n";
+ print "Debug = $Debug_Flag\n";
+ print "No_Prompt = $No_Prompt\n";
+ print "Timeout = $Timeout\n";
+ print "\n";
+}
+
+sub cmd_help {
+
+ print "Commands are:\n";
+ print "c - initiate PPTP connection\n";
+ print "d - disconnect PPTP\n";
+ print "h - this help message\n";
+ print "l - list current configuration\n";
+ print "q - quite the program\n";
+ print "r - read configuration file\n";
+ print "s - set configuration variable (l for a list)\n";
+ print "w - write the configuration file\n";
+
+}
+
+sub cmd_set {
+ my $input = shift;
+ my $no_replace = shift;
+
+ my ($variable, $value) = split(/\s*=\s*/, $input);
+
+ $variable = "\L$variable";
+ if (! $variable) {
+ print "syntax: s variable = value\n";
+ return 0;
+ }
+
+ if ($variable eq "server") {
+ $Server = $value unless $no_replace && $Server;
+ }
+ elsif ($variable eq "network") {
+ $Net = $value unless $no_replace && $Net;
+ }
+ elsif ($variable eq "routes") {
+ $Route = $value unless $no_replace && $Route;
+ }
+ elsif ($variable eq "debug") {
+ $Debug_Flag = $value unless $no_replace && $Debug_Flag;
+ }
+ elsif ($variable eq "no_prompt") {
+ $No_Prompt = $value unless $no_replace && $No_Prompt;
+ }
+ elsif ($variable eq "timeout") {
+ $Timeout = $value unless $no_replace && $Timeout;
+ }
+ elsif ($variable eq "config_file") {
+ $Config_File = $value unless $no_replace && $Config_File;
+ }
+ else {
+ print "unknown variable\n";
+ }
+}
+
+sub cmd_read_config_file {
+ my $file = shift;
+
+ my $config = [];
+ $file = $Config_File unless $file;
+ local *IN;
+ if (!open(IN, $file)) {
+ print "cannot open $file\n";
+ return $config;
+ }
+
+ my @config_file = <IN>;
+ close IN;
+ push @config_file, "\n";
+ chomp @config_file;
+
+ for my $line (@config_file) {
+ next if /\s*#/;
+
+ if ($line =~ /\S/) {
+ $line =~ s/^\s*//;
+ $line =~ s/\s*$//;
+ push @$config, $line;
+ next;
+ }
+ }
+ return $config;
+}
+
+sub cmd_write_config_file {
+ my $file = shift;
+
+ $file = $Config_File unless $file;
+ local *OUT;
+ if (!open(OUT, ">$file")) {
+ print "cannot open $file\n";
+ return 0;
+ }
+
+ my $oldfh = select OUT;
+ cmd_list();
+ close OUT;
+ select $oldfh;
+
+ return 1;
+}
+
+sub net_interface_up {
+ my $cidr = shift;
+
+ # cidr is net/bits
+ my($net, $nbits) = split(/\//, $cidr);
+
+ # compute the network number
+ my $netnum = netnum($net, $nbits);
+ local(*INTERFACE);
+ open(INTERFACE, "ifconfig|") || die "cannot run ifconfig - $!\n";
+
+ my $interface = "";
+ my @interface = <INTERFACE>;
+ close INTERFACE;
+ for (@interface) {
+ chomp;
+
+ # new interface
+ if (/^[a-zA-Z]/) {
+ if ($interface =~ /(.*) Link.*P-t-P:(.*) Mask/) {
+ my $interface_name = $1;
+ my $ip = $2;
+ return $interface_name
+ if netnum($ip, $nbits) == $netnum;
+ }
+ $interface = "";
+ }
+ $interface .= $_;
+ }
+ return "";
+}
+
+sub netnum {
+ my $net = shift;
+ my $bits = shift;
+
+ my @octets = split(/\./, $net);
+ my $netnum = 0;
+ for my $octet (@octets) {
+ $netnum <<= 8;
+ $netnum |= $octet;
+ }
+
+ my $mask = 0;
+ for (1..$bits) {
+ $mask <<= 1;
+ $mask |= 1;
+ }
+ $mask = $mask << (32-$bits);
+
+ $netnum &= $mask;
+
+ return $netnum;
+}