Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 284119
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 12, 20262026-05-12T05:25:52+00:00 2026-05-12T05:25:52+00:00

A few weeks ago I wrote an SNMP relayer for our ops group. They

  • 0

A few weeks ago I wrote an SNMP relayer for our ops group. They have some dumb devices that can only send traps to a single IP, and we have a monitoring system that listens on multiple IPs for availability. The code’s dead simple, and essentially:

while (recv($packet)) {
  foreach $target (@targets) {
    send($target, $packet);
  }
}

It’s worked, basically, but now the obvious short coming that it doesn’t include the originator IP is an issue (apparently the first class of device included the info as a varbind and some new class does not).

What I would like to do is change my code to something like this:

while ($server->recv($packet)) {
  my $obj = decompile($packet)
  if (!$obj->{varbind}{snmpTrapAddress}) {
    $obj->{varbind}{snmpTrapAddress} = inet_ntoa($server->peeraddr());
  }
  $packet = compile($obj);
  foreach $target (@targets) {
    send($target, $packet);
  }
}

In other words, if my sender isn’t including snmpTrapAddress, add it. The problem is that every SNMP package I’ve looked at for Perl seems very heavily focused on the infrastructure of receiving traps and performing gets.

So: Is there a simple Perl module that will allow me to say “here’s a blob of data representing an snmp trap. decode it into something I can easily manipulate, then recompile it back into a blob I can throw over the network”?

If the answer you give is “use SNMP dummy”, can you provide examples of this? I may just be blind, but from the output of perldoc SNMP it’s not obvious to me how to use it in this manner.

EDIT:

Turns out after looking around a bit that “SNMP encoding” is really ASN.1 BER (Basic Encoding Rules). Based on this I’m having a go with Convert::BER. I would still welcome any easy break down/edit/rebuild tips for SNMP.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-12T05:25:53+00:00Added an answer on May 12, 2026 at 5:25 am

    I never found a perfect solution to this. Net::SNMP::Message (part of Net::SNMP) might allow this but doesn’t seem to have a publicly defined interface, and none of the Net::SNMP interface seemed especially relevant. NSNMP is closest to the spirit of what I was looking for, but it’s brittle and didn’t work for my packet out of the box and if I’m going to support brittle code, it’s going to be my own brittle code =).

    Mon::SNMP also got close to what I was looking for, but it too was broken out of the box. It appears to be abandoned, with the last release in 2001 and the developer’s last CPAN release in 2002. I didn’t realize it at the time but I now think that it’s broken because of a change in the interface to the Convert::BER module it uses.

    Mon::SNMP got me pointed toward Convert::BER. A few thousand reads of the Convert::BER POD, the Mon::SNMP source, and RFC 1157 (esp. 4.1.6, “The Trap-PDU”) later and I came up with this code as a proof of concept to do what I wanted. This is just proof of concept (for reasons I’ll detail after the code) so it may not be perfect, but I thought it might provide useful reference for future Perl people working in this area, so here it is:

    #!/usr/bin/perl
    
    use Convert::BER;
    use Convert::BER qw(/^(\$|BER_)/);
    
    my $ber = Convert::BER->new();
    
    # OID I want to add to the trap if not already present
    my $snmpTrapAddress = '1.3.6.1.6.3.18.1.3';
    
    # this would be from the incoming socket in production
    my $source_ip = '10.137.54.253';
    
    # convert the octets into chars to match SNMP standard for IPs
    my $source_ip_str = join('', map { chr($_); } split(/\./, $source_ip));
    
    # Read the binary trap data from STDIN or ARGV.  Normally this would
    # come from the UDP receiver
    my $d = join('', <>);
    
    # Stuff my trap data into $ber
    $ber->buffer($d);
    
    print STDERR "Original packet:\n";
    $ber->dump();
    
    # Just decode the first two fields so we can tell what version we're dealing with
    $ber->decode(
                    SEQUENCE => [
                        INTEGER => \$version,
                        STRING => \$community,
                        BER => \$rest_of_trap,
                    ],
    ) || die "Couldn't decode packet: ".$ber->error()."\n";
    
    if ($version == 0) {
      #print STDERR "This is a version 1 trap, proceeding\n";
    
      # decode the PDU up to but not including the VARBINDS
      $rest_of_trap->decode(
        [ SEQUENCE => BER_CONTEXT | BER_CONSTRUCTOR | 0x04 ] =>
          [
            OBJECT_ID => \$enterprise_oid,
            [ STRING => BER_APPLICATION | 0x00 ] => \$agentaddr,
            INTEGER => \$generic,
            INTEGER => \$specific,
            [ INTEGER => BER_APPLICATION | 0x03 ] => \$timeticks,
            SEQUENCE => [ BER => \$varbind_ber, ],
          ],
      ) || die "Couldn't decode packet: ".$extra->error()."\n";;
    
      # now decode the actual VARBINDS (just the OIDs really, to decode the values
      # We'd have to go to the MIBs, which I neither want nor need to do
      my($r, $t_oid, $t_val, %varbinds);
      while ($r = $varbind_ber->decode(
        SEQUENCE => [
          OBJECT_ID => \$t_oid,
          ANY       => \$t_val,
        ], ))
      {
        if (!$r) {
          die "Couldn't decode SEQUENCE: ".$extra->error()."\n";
        }
        $varbinds{$t_oid} = $t_val;
      }
    
      if ($varbinds{$snmpTrapAddress} || $varbinds{"$snmpTrapAddress.0"}) {
        # the original trap already had the data, just print it back out
        print $d;
      } else {
        # snmpTrapAddress isn't present, create a new object and rebuild the packet
        my $new_trap = new Convert::BER;
        $new_trap->encode(
          SEQUENCE => [
            INTEGER => $version,
            STRING => $community,
            [ SEQUENCE => BER_CONTEXT | BER_CONSTRUCTOR | 0x04 ] =>
              [
                OBJECT_ID => $enterprise_oid,
                [ STRING => BER_APPLICATION | 0x00 ] => $agentaddr,
                INTEGER => $generic,
                INTEGER => $specific,
                [ INTEGER => BER_APPLICATION | 0x03 ] => $timeticks,
                SEQUENCE => [
                  BER => $varbind_ber,
                  # this next oid/val is the only mod we should be making
                  SEQUENCE => [
                    OBJECT_ID => "$snmpTrapAddress.0",
                    [ STRING => BER_APPLICATION | 0x00 ] => $source_ip_str,
                  ],
                ],
              ],
          ],
        );
        print STDERR "New packet:\n";
        $new_trap->dump();
        print $new_trap->buffer;
      }
    } else {
      print STDERR "I don't know how to decode non-v1 packets yet\n";
      # send back the original packet
      print $d;  
    }
    

    So, that’s it. Here’s the kicker. I took ops at their word that they weren’t getting the IP of the original sender in the trap. While working through this example, I found that, at least in the example they gave me, the original IP was in the agent-addr field in the trap. After showing them this and where in the API of the tool their using this is exposed they went off to try to make the change on their end. I’m daving the code above against the time they ask me for something I actually need to muck in the packet for, but for now the above will remain non-rigorously-tested proof of concept code. Hope it helps someone someday.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

i have a bit of code that i wrote a few weeks ago (the
I remember few weeks ago when I reorgnized our code and created some namespaces
A few weeks ago I started noticing that my VS displays some warnings twice.
I started using symfony a few weeks ago, and there are some things that
I have started programming a few weeks ago in java/android. I want to write
we started a paper on Haskell a few weeks ago and just received our
A few weeks ago I asked about Application Servers. It happens that my bosses
A few weeks ago I wrote a wrapper for the ServiceController control to enhance
A few weeks ago I wrote a CSV parser in python and it was
A few weeks ago, I checked out our whole SVN repo in --non-recursive mode.

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.