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?
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";
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 ----...--->|