#!/usr/bin/perl # Make sure the above line correctly points to Perl on your workstation. Use # "which perl" to find it. ############################################################################### # ppps v1.0 # 1999 Digital Objects Software (http://mrdo.com) # Created 04/24/99 # GNU copyright rules apply. ############################################################################### # # This program scans your /var/log/messages file for the latest successful # ppp connection and reports the negotiated connection speed and assigned # IP address. # # Only the last successful connection is reported. It does not determine # whether the workstation is currently connected. A useful place to use # this script is in the ip-up.local script so that the connection rate is # reported every time a connection is made. # ############################################################################### # # INSTALLATION # # You may simply execute this script anytime you want to see the last # successfully negotiated connection speed and IP address. Or you can # automate the report by following these steps. # # 1. Copy this script to a convenient directory that users will be able to # access. For instance, /usr/local/ppps/ppps.pl. Grant execution # priveledges to the script (chmod 755 ppps.pl). # # 2. Create a symbolic link to the script that users will use to execute # the script. # For instance, ln -s /usr/local/ppps/ppps.pl /usr/local/bin/ppps # Grant execution priveledges to the link if necessary. # # 3. Read permission to /var/log/messages must be given to users that # will be using this script, otherwise this script cannot extract the # modem log data. -rw-r--r-- is recommended (chmod 644 /var/log/messages). # # 4. To report the connection speed every time a connection is made, execute # this script from the /etc/ppp/ip-up.local file. If creating the # ip-up.local file, grant execution priveledges. # Add this line to ip-up.local: # /usr/local/bin/ppps > /dev/console & # ############################################################################### # You may need to adjust several script constants to conform to your # specific system. The script scans to the last occurrence of the modem # string "CONNECT" then skips past certain strings that you identify in # the $IGNORE lists. # # The default logic of the script is based on this example case: # # Apr 24 09:34:05 p166 ifup-ppp: pppd started for ppp0 on /dev/cua0 at 115200 # Apr 24 09:34:06 p166 pppd[2113]: pppd 2.3.5 started by root, uid 0 # Apr 24 09:34:07 p166 chat[2115]: abort on (BUSY) # Apr 24 09:34:07 p166 chat[2115]: abort on (ERROR) # Apr 24 09:34:07 p166 chat[2115]: abort on (NO CARRIER) # Apr 24 09:34:07 p166 chat[2115]: abort on (NO DIALTONE) # Apr 24 09:34:07 p166 chat[2115]: abort on (Invalid Login) # Apr 24 09:34:07 p166 chat[2115]: abort on (Login incorrect) # Apr 24 09:34:07 p166 chat[2115]: send (ATZ^M) # Apr 24 09:34:07 p166 chat[2115]: expect (OK) # Apr 24 09:34:07 p166 chat[2115]: ATZ^M^M # Apr 24 09:34:07 p166 chat[2115]: OK # Apr 24 09:34:07 p166 chat[2115]: -- got it # Apr 24 09:34:07 p166 chat[2115]: send (ATDT3263000^M) # Apr 24 09:34:07 p166 chat[2115]: expect (CONNECT) # Apr 24 09:34:07 p166 chat[2115]: ^M # Apr 24 09:34:26 p166 chat[2115]: ATDT3263000^M^M # Apr 24 09:34:26 p166 chat[2115]: CONNECT # Apr 24 09:34:26 p166 chat[2115]: -- got it # Apr 24 09:34:26 p166 chat[2115]: send (^M) # Apr 24 09:34:26 p166 chat[2115]: timeout set to 5 seconds # Apr 24 09:34:26 p166 chat[2115]: expect (~) # Apr 24 09:34:26 p166 chat[2115]: 49333/ARQ/V90/LAPM/V42BIS^M # Apr 24 09:34:28 p166 chat[2115]: ^M # Apr 24 09:34:31 p166 chat[2115]: alarm # Apr 24 09:34:31 p166 chat[2115]: send (^M) # Apr 24 09:34:31 p166 pppd[2113]: Serial connection established. # Apr 24 09:34:31 p166 chat[2115]: send (^M) # Apr 24 09:34:32 p166 pppd[2113]: Using interface ppp0 # Apr 24 09:34:32 p166 pppd[2113]: Connect: ppp0 <--> /dev/cua0 # Apr 24 09:34:36 p166 pppd[2113]: Remote message: Login Succeeded # Apr 24 09:34:36 p166 pppd[2113]: local IP address 209.113.185.150 # Apr 24 09:34:36 p166 pppd[2113]: remote IP address 209.150.4.3 # # # With this output: # 49333/ARQ/V90/LAPM/V42BIS # local IP address 209.113.185.150 use strict; # Typically '/var/log/messages' my $MESSAGES_LOG = '/var/log/messages'; # If non-zero, only those portions of strings after this many ':' will be # output. A value of 0 will output the whole string. my $SHIFT_COLUMNS = 3; # Modem response string identifying successful connection. # Case sensitive, literal, and bounded by whitespace. my $CONNECT = 'CONNECT'; # Substrings after $CONNECT to ignore. my @CONNECT_IGNORE = ('got it', 'send', 'timeout', 'expect'); # Number of lines after ignored lines to output my $CONNECT_LINES = 1; # Additional lines will be output if non-zero my $MORE = 1; # Substrings after last output to ignore. my @MORE_IGNORE = ('^M', 'alarm', 'send', 'established', 'interface', 'onnect', 'message'); # Number of lines after ignored lines to output my $MORE_LINES = 1; ############################################################################### sub ignore { # Test given string for existence within strings in given list my($str, @lst) = @_; my $ignore; foreach $ignore (@lst) { # '^M' requires a special case. The '^' will be intrepreted as a # regular expression term. Escape it. if ( $ignore =~ /^\^/ ) { $ignore = '\\' . $ignore; } if ( $str =~ /$ignore/ ) { return 1; } } return 0; } ############################################################################### sub clean { # chomp \n and remove all '^M' my($str) = @_; chomp($str); $str =~ s/\^M//g; return($str); } ############################################################################### sub shiftColumns { ## Shift off beginning of string up to the number of ':' specified my($str) = @_; my @lst; my $i; @lst = split(/:/, $str); for ($i = 0; $i < $SHIFT_COLUMNS; $i++) { shift(@lst); } $str = join('', @lst); return($str); } ############################################################################### my @messages; my $line; my $ignore; my @lst1; my $i; my @report; # Make sure the file exists where expected unless ( -e $MESSAGES_LOG ) { die("$MESSAGES_LOG does not exist\n"); } # $MESSAGES_LOG is normally -rw-------, but must be -rw-r--r-- (644) in order # for normal users to access it. unless ( open(MESSAGES, $MESSAGES_LOG) ) { warn("Could not access $MESSAGES_LOG: $!\n"); warn("This file should have -rw-r--r-- access for non-priveleged users.\n"); die("As root, type 'chmod 644 $MESSAGES_LOG'\n"); } # Let's not read the whole file into memory, it could be very large. # Instead, find each occurrence of $CONNECT, then read each line thereafter # into memory. Each time $CONNECT is found, reset the buffer before reading # the following lines. That way, when the last $CONNECT has been passed and # EOF reached, the buffer will contain the latest data pertaining to the # latest session. # First, find the first occurrence of the whitespace bounded $CONNECT while ( $line = ) { if ( $line =~ /\s$CONNECT\s/ ) { last; } } unless ( $line =~ /\s$CONNECT\s/ ) { close(MESSAGES); die("String token $CONNECT was not found\n"); } # Now find each successive $CONNECT, resetting the buffer each time, until # end of file. @messages = (); while ( $line = ) { push(@messages, $line); # If $CONNECT is found, clear the buffer and continue with the next line if ( $line =~ /\s$CONNECT\s/ ) { @messages = (); } } # EOF close(MESSAGES); # @messages now contains all lines after last $CONNECT, if any. # Parse through @messages, ignoring specified lines until the connection # rate is found. # @messages is shifted for each line processed to make it more efficient to # parse subsequent lines. A working copy of @messages is made for parsing # because you cannot shift an array as you're iterating it (an internal copy # must be made for the foreach iteration). @report = (); @lst1 = @messages; foreach $line (@lst1) { unless ( ignore($line, @CONNECT_IGNORE) ) { # Get the number of $CONNECT_LINES wanted for ($i = 0; $i < $CONNECT_LINES && @messages > 0; $i++) { $line = clean($line); push(@report, $line); # Continue shifting off each line shift(@messages); } # Go on to $MORE last; } # Shift off each ignored line. Shrinking the list like this will allow # us to start from the top when finding more lines after $CONNECT shift(@messages); } # Do $MORE if enabled if ($MORE) { @lst1 = @messages; foreach $line (@lst1) { unless ( ignore($line, @MORE_IGNORE) ) { # Get the number of $MORE_LINES wanted for ($i = 0; $i < $CONNECT_LINES && @messages > 0; $i++) { $line = clean($line); push(@report, $line); # Continue shifting off each line shift(@messages); } # Done parsing log file last; } } # Shift off each ignored line shift(@messages); } # Output results if (@report) { foreach $line (@report) { # Shift number of columns specified. # Example: # 'Apr 24 09:34:26 p166 chat[2115]: 49333/ARQ/V90/LAPM/V42BIS' # ' 49333/ARQ/V90/LAPM/V42BIS' if ($SHIFT_COLUMNS) { $line = shiftColumns($line); } # Trim whitespace from beginning of string # Example: # ' 49333/ARQ/V90/LAPM/V42BIS' # '49333/ARQ/V90/LAPM/V42BIS' $line =~ s/^\s+//; # Replace multiple whitespace with single space # Example: # 'local IP address 209.113.185.150' # 'local IP address 209.113.185.150' $line =~ s/\s+/ /g; print "$line\n"; } } else { die("No successful PPP connections were found\n"); }