0

I am attempting to set up a small test environment (homelab) using CentOS 6.6, Rancid 3.1, Looking Glass, and some Cisco Switches/Routers, with httpd acting as the handler. I have picked up a little perl by means of this endeavor, but python (more 2 than 3) is my background. Right now, everything on the rancid side of things works without issue: bin/clogin successfully logs into all of the equipment in the router.db file, and logging of the configs is working as expected. All switches/routers to be accessed are available and online, verified by ssh connection to devices as well as using bin/clogin.

Right now, I have placed the lg.cgi and lgform.cgi files into var/www/cgi-bin/ which allows the forms to be run as cgi scripts. I had to modify the files to split on ';' instead of ':' due to the change in the .db file in Rancid 3.1:@record = split('\:', $_); was replaced with: @record = split('\;', $_); etc. Once that change was made, I was able to load the lgform.cgi with the proper router.db parsing. At this point, it seemed like everything should be good to go. When I attempt to ping from one of those devices out to 8.8.8.8, the file correctly redirects to lg.cgi, and the page loads, but with

main is unavailable. Try again later.

as the error, where 'main' is the router hostname. Using this output, I was able to find the function responsible for this output. Here it is before I added anything:

sub DoRsh
{
    my ($router, $mfg, $cmd, $arg) = @_;
    my($ctime) = time();
    my($val);

    my($lckobj) = LockFile::Simple->make(-delay => $lock_int,
                -max => $max_lock_wait, -hold => $max_lock_hold);
    if ($pingcmd =~ /\d$/) {
        `$pingcmd $router`;
    } else {
        `$pingcmd $router 56 1`;
    }
    if ($?) {
        print "$router is unreachable.  Try again later.\n"; 
        return(-1);
    }
    if ($LG_SINGLE) {
        if (! $lckobj->lock("$cache_dir/$router")) {
            print "$router is busy.  Try again later.\n";
            return(-1);
        }
    }
    $val = &DoCmd($router, $mfg, $cmd, $arg);
    if ($LG_SINGLE) {
        $lckobj->unlock("$cache_dir/$router");
    }
    return($val);
}

In order to dig in a little deeper, I peppered that function with several print statements. Here is the modified function, followed by the output from the loaded lg.cgi page:

sub DoRsh
{
    my ($router, $mfg, $cmd, $arg) = @_;
    my($ctime) = time();
    my($val);

    my($lckobj) = LockFile::Simple->make(-delay => $lock_int,
                -max => $max_lock_wait, -hold => $max_lock_hold);
    if ($pingcmd =~ /\d$/) {
        `$pingcmd $router`;
    } else {
        `$pingcmd $router 56 1`;
    }
    print "About to test the ($?) branch.\n";
    print "Also who is the remote_user?:' $remote_user'\n";
    print "What about the ENV{REMOTE_USER} '$ENV{REMOTE_USER}'\n";
    print "Here is the ENV{HOME}:  '$ENV{HOME}'\n";
    if ($?) {
        print "$lckobj  is the lock object.\n";
        print "@_ something else to look at.\n";
        print "$? whatever this is suppose to be....\n";
        print "Some variables:\n";
        print "$mfg is the mfg.\n";
        print "$cmd was the command passed in with $arg as the argument.\n";
        print "$pingcmd $router\n";
        print "$cloginrc - Is the cloginrc pointing correctly?\n";
        print "$LG_SINGLE  the next value to be tested.\n";
        print "$router is unreachable.  Try again later.\n"; 
        return(-1);
    }
    if ($LG_SINGLE) {
        if (! $lckobj->lock("$cache_dir/$router")) {
            print "$router is busy.  Try again later.\n";
            return(-1);
        }
    }
    $val = &DoCmd($router, $mfg, $cmd, $arg);
    if ($LG_SINGLE) {
        $lckobj->unlock("$cache_dir/$router");
    }
    return($val);
}

OUTPUT:

About to test the (512) branch.

Also who is the remote_user?:' '

What about the ENV{REMOTE_USER} ''

Here is the ENV{HOME}: '.'

LockFile::Simple=HASH(0x1a13650) is the lock object.

main cisco ping 8.8.8.8 something else to look at.

512 whatever this is suppose to be....

Some variables:

cisco is the mfg.

ping was the command passed in with 8.8.8.8 as the argument.

/bin/ping -c 1 main

./.cloginrc - Is the cloginrc pointing correctly?

1 the next value to be tested.

main is unreachable. Try again later.

I can provide the code for when DoRsh is called, if necessary, but it looks mostly like this:&DoRsh($router, $mfg, $cmd, $arg);.

From what I can tell the '$?' special variable (or at least according to this reference it is a special var) is returning the 512 value, which is causing that fork to test true. The problem is I don't know what that 512 means, nor where it is coming from. Using the ref site's description ("The status returned by the last pipe close, backtick (``) command, or system operator.") and the formation of the conditional tree above, I can see that it is some error of some kind, but I don't know how else to proceed with this inspection. I'm wondering if maybe it is in response to some permission issue, since the remote_user variable is null, when I didn't expect it to be. Any guidance anyone may be able to provide would be helpful. Furthermore, if there is any information that I may have skipped over, that I didn't think to include, or that may prove helpful, please ask, and I will provide to the best of my ability

Community
  • 1
  • 1
  • `$?` is a piece of magic perl, that's losely the 'status of the last command'. So in this case - that ping you did. Can you try printing what the value of that `$pingcmd $router` and try running it? I suspect it's either: invalid or the name isn't resolving. – Sobrique Feb 07 '15 at 21:40
  • `$pingcmd $router` resolves to /bin/ping -c 1 main, which when run from the command line returns no errors: --- main ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 4ms rtt min/avg/max/mdev = 3.811/3.811/3.811/0.000 ms Is this what you meant? – Jonathan Lucas Feb 07 '15 at 22:09
  • Yep. But the fact that `$?` is 512 after running it implies something is going wrong within the script. – Sobrique Feb 07 '15 at 22:35
  • @Sobrique - - Are the ticks around $pingcmd $router after `if ($pingcmd =~ /\d$/) {` shorthand for system() in perl? Is there a quick/efficient way to determine what that error code means for the input command, i.e. ping? – Jonathan Lucas Feb 08 '15 at 00:23
  • http://stackoverflow.com/questions/799968/whats-the-difference-between-perls-backticks-system-and-exec – Sobrique Feb 08 '15 at 13:43
  • You can probably capture the output of the ping command by changing it to: `my $result = \`$pingcmd $router 2>&1\`; print $result;` – Sobrique Feb 08 '15 at 16:02
  • @Sobrique - this returned the output that actually makes sense to me. Looks like there is an issue with the permissions, as I suspected. The output from `print $result;` is `ping: icmp open socket: Permission denied`. – Jonathan Lucas Feb 10 '15 at 14:24
  • Ah so the ping is failing, and the return code reflects that? Yes. That suggests you need a privilege to ping - perhaps the `ping` command isn't setuid – Sobrique Feb 10 '15 at 14:42
  • @Sobrique - after verifying that the ping command was not working for the apache user, using `su -s /bin/bash apache`, I applied `chmod +a /bin/ping`. I then was able to use the ping command with the apache user. I also came across some SELinux-y related issues with ping permissions, so I disabled that for testing as well. However, I still receive the same 'Permission denied' output. – Jonathan Lucas Feb 10 '15 at 20:10
  • Sorry, meant `chmod a+x /bin/ping` – Jonathan Lucas Feb 10 '15 at 20:35
  • I have also tried a few other options, e.g. `chown root:root /bin/ping` + `chmod u+s /bin/ping`. However, even though the apache user is allowed to run the ping command, I get the same error when trying to run the $pingcmd in the perl script. Perhaps the permission issue is not with the ping command itself, but with something else? – Jonathan Lucas Feb 10 '15 at 20:45

1 Answers1

1

May be you put in something like

my $pingret=$pingcmd ...; print 'Ping result was:'.$pingret;

And check the returned strings?

mickvav
  • 310
  • 2
  • 6
  • 1
    Unfortunately, `print $pingret` returns the same 512 that `$?` returned, which was the original problem. But this was on the right track. I was able to get a comprehensible return when using `$pingcmd $router 2>&1`, which returns `ping: icmp open socket: Permission denied`. – Jonathan Lucas Feb 10 '15 at 14:45