perldecimalasciibig-ipnagiosxi

Perl ASCII variable to Decimal with "." after every letter


I'm making a Perl plugin for Nagios for the F5 load balancer. I have to convert the pool name to a decimal format that matches the OID for SNMP.

my ( $PoolName )         = $ARGV[1];
my ( $rootOIDPoolStatus ) = '1.3.6.1.4.1.3375.2.2.5.5.2.1.2';

For example, $PoolName is "/Common/Atlassian" and I need to convert that to /.C.o.m.m.o.n./.A.t.l.a.s.s.i.a.n and then to 47.67.111.109.109.111.110.47.65.116.108.97.115.115.105.97.110

Once that has been converted they would get pulled into one variable

my ( $PoolStatus ) = "$rootOIDPoolStatus.$OIDPoolName"

I have been backwards-engineering other people's Perl plugins for Nagios and this is what someone else is doing, but I couldn't make it work no matter what kind of combinations I was doing. Their $name would be my $PoolName

sub to_oid($) {
    my $oid;
    my ($name) = $_[0];
    return "" if ( ! $name );
    $oid = ( length $name ) . '.' . ( join '.', ( map { unpack 'C', $ } ( split '',$name ) ) );
    return $oid;
}

Could someone help me to build or understand the Perl logic in order to convert $PoolName to the decimal format I need for the OID?


Solution

  • You seem to be using a string as an index to an SNMP table. The index of a table can be thought of as the row number or row id for that table. Often the index for a table is just a number starting from 1 and increasing with each row the table has. Such a number is encoded in the OID as is, i.e. if the table has 3 columns and two rows, they would have these OIDs:

    $base.1         # table
    $base.1.1       # table entry
    $base.1.1.1.1   # col1, row1
    $base.1.1.1.2   # col1, row2
    $base.1.1.2.1   # col2, row1
    $base.1.1.2.2   # col2, row2
    $base.1.1.3.1   # col3, row1
    $base.1.1.3.2   # col3, row2
                ^---index
    

    Sometimes the index is an IP address, a combination of IP:port, or a combination of two IP addresses, especially for IP related tables. An IP address as index would look like this:

    $base.1                 # table
    $base.1.1               # table entry
    $base.1.1.1.1.0.0.127   # col1, row "127.0.0.1"
    $base.1.1.1.0.0.0.0     # col1, row "0.0.0.0"
    $base.1.1.2.1.0.0.127   # col2, row "127.0.0.1"
    $base.1.1.2.0.0.0.0     # col2, row "0.0.0.0"
    $base.1.1.3.1.0.0.127   # col3, row "127.0.0.1"
    $base.1.1.3.0.0.0.0     # col3, row "0.0.0.0"
                ^^^^^^^---- index
    

    As you can see, the length of the index varies depending on its datatype (there's a dedicated IPV4 datatype).

    Sometimes the index is a string (as in your case). When a string is used it must as well be somehow encoded to make up a "row number" for the table. Strings as indexes are encoded character-wise and preceeded by their length, i.e.:

    $base.1                     # table
    $base.1.1                   # table entry
    $base.1.1.1.2.65.66         # col1, row "AB"
    $base.1.1.1.3.120.121.122   # col1, row "xyz"
    $base.1.1.2.2.65.66         # col2, row "AB"
    $base.1.1.2.3.120.121.122   # col2, row "xyz"
    $base.1.1.3.2.65.66         # col3, row "AB"
    $base.1.1.3.3.120.121.122   # col3, row "xyz"
                ^^^^^^^^^^^^^---- index
    

    So "AB" becomes "2.65.66" because length('AB')==2 and ord('A')==65, ord('B')==66. Likewise "xyz" becomes "3.120.121.122".

    Your function to_oid does exactly that, although I'd simplify it as follows:

    #!/usr/bin/env perl
    
    use strict;
    use warnings;
    
    sub to_oid
    {
        my $string = shift;
        return sprintf('%d.%s', length($string), join('.', unpack('C*', $string)));
    }
    
    my $rootOIDPoolStatus = '1.3.6.1.4.1.3375.2.2.5.5.2.1.2';
    my $PoolName = '/Common/Atlassian';
    
    my $poolname_oid = to_oid($PoolName);
    my $complete_oid = "$rootOIDPoolStatus.$poolname_oid";
    
    print $complete_oid, "\n";
    

    Output:

    1.3.6.1.4.1.3375.2.2.5.5.2.1.2.17.47.67.111.109.109.111.110.47.65.116.108.97.115.115.105.97.110
    |<------- rootOID ----------->|<------------ poolname_oid ----...--->|