gosnmp

package module
v1.6.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 15, 2014 License: BSD-2-Clause, BSD-3-Clause Imports: 16 Imported by: 0

README

gosnmp

Build Status Coverage GoDoc

GoSNMP is an SNMP client library written fully in Go. Currently it supports GetRequest, GetNext, GetBulk, Walk (beta, see below), and SetRequest (beta, see below).

About

soniah/gosnmp is based on alouca/gosnmp - many thanks to Andreas Louca for starting the project. Thanks also to the following who have contributed:

  • Chris Dance (@codedance) - Fixes, SNMP Walk functionality and examples, Retry Support
  • Nathan Owens (@virtuallynathan) - Fixes / Changes
  • Jacob Dubinsky (@jdubinsky) - All of GetNext and GetBulk
  • Jon Auer (@jda) - Data truncation fix
  • Andreas Louca (@alouca) - Original library

Overview

GoSNMP has the following SNMP functions:

  • Get (single or multiple OIDs)
  • GetNext
  • GetBulk
  • Walk - retrieves a subtree of values using GETNEXT.
  • BulkWalk - retrieves a subtree of values using GETBULK.
  • Set (beta - only supports setting one integer OID)

GoSNMP also has the following helper functions:

  • ToBigInt - treat returned values as *big.Int
  • Partition - facilitates dividing up large slices of OIDs

soniah/gosnmp has diverged from alouca/gosnmp - your existing code will require slight modification:

  • the Get function has a different method signature
  • the NewGoSNMP function has been removed, use Connect instead (see Usage below)
  • GoSNMP no longer relies on alouca/gologger - you can use your logger if it conforms to the simple interface (Print and Printf). Otherwise debugging will be discarded (/dev/null).

gosnmp is still under development, therefore API's may change and bugs will be squashed. Test Driven Development is used - you can help by sending packet captures (see Packet Captures below). There may be more than one branch on github. master is safe to pull from, other branches unsafe as history may be rewritten.

Sonia Hamilton, sonia@snowfrog.net, http://blog.snowfrog.net.

Installation

Install via go get:

go get github.com/soniah/gosnmp

Documentation

See http://godoc.org/github.com/soniah/gosnmp or your local go doc server for full documentation, as well as the examples.

cd $GOPATH
godoc -http=:6060 &
$preferred_browser http://localhost:6060/pkg &

Usage

Here is code from example/example.go, demonstrating how to use GoSNMP:

    // Default is a pointer to a GoSNMP struct that contains sensible defaults
    // eg port 161, community public, etc
    g.Default.Target = "192.168.1.10"
    err := g.Default.Connect()
    if err != nil {
        log.Fatalf("Connect() err: %v", err)
    }
    defer g.Default.Conn.Close()

    oids := []string{"1.3.6.1.2.1.1.4.0", "1.3.6.1.2.1.1.7.0"}
    result, err2 := g.Default.Get(oids) // Get() accepts up to g.MAX_OIDS
    if err2 != nil {
        log.Fatalf("Get() err: %v", err2)
    }

    for i, variable := range result.Variables {
        fmt.Printf("%d: oid: %s ", i, variable.Name)

        // the Value of each variable returned by Get() implements
        // interface{}. You could do a type switch...
        switch variable.Type {
        case g.OctetString:
            fmt.Printf("string: %s\n", variable.Value.(string))
        default:
            // ... or often you're just interested in numeric values.
            // ToBigInt() will return the Value as a BigInt, for plugging
            // into your calculations.
            fmt.Printf("number: %d\n", g.ToBigInt(variable.Value))
        }
    }

Running this example gives the following output (from my printer):

% go run example.go
0: oid: 1.3.6.1.2.1.1.4.0 string: Administrator
1: oid: 1.3.6.1.2.1.1.7.0 number: 104

example/example2.go is similar to example.go, however is uses a custom &GoSNMP rather than g.Default.

example/walkexample.go demonstrates using BulkWalk.

Bugs

The following BER types have been implemented:

  • 0x02 Integer
  • 0x04 OctetString
  • 0x06 ObjectIdentifier
  • 0x40 IPAddress (IPv4 & IPv6)
  • 0x41 Counter32
  • 0x42 Gauge32
  • 0x43 TimeTicks
  • 0x46 Counter64
  • 0x80 NoSuchObject
  • 0x81 NoSuchInstance
  • 0x82 EndOfMibView

The following (less common) BER types haven't been implemented, as I ran out of time or haven't been able to find example devices to query:

  • 0x00 EndOfContents
  • 0x01 Boolean
  • 0x03 BitString
  • 0x07 ObjectDescription
  • 0x44 Opaque
  • 0x45 NsapAddress
  • 0x47 Uinteger32

Packet Captures

Please create an issue on GitHub with packet captures (upload them somewhere) containing samples of the missing BER types, or of any other bugs you find. Please include 2 or 3 examples of the missing/faulty BER type, interspersed with a couple of other common BER's eg an Integer, a Counter32 ie about 6-8 OIDs.

Create your packet captures in the following way:

Expected output, obtained via an snmp command. For example:

% snmpget -On -v2c -c public 203.50.251.17 1.3.6.1.2.1.1.7.0 \
  1.3.6.1.2.1.2.2.1.2.6 1.3.6.1.2.1.2.2.1.5.3
.1.3.6.1.2.1.1.7.0 = INTEGER: 78
.1.3.6.1.2.1.2.2.1.2.6 = STRING: GigabitEthernet0
.1.3.6.1.2.1.2.2.1.5.3 = Gauge32: 4294967295

A packet capture, obtained while running the snmpget. For example:

sudo tcpdump -s 0 -i eth0 -w foo.pcap host 203.50.251.17 and port 161

Running the Tests

Tests are grouped as follows:

  • Unit tests (validating data packing and marshalling):
    • marshal_test.go
    • misc_test.go
  • Public API consistency tests:
    • gosnmp_api_test.go
  • End-to-end integration tests:
    • generic_e2e_test.go
    • verax_test.go

The generic end-to-end integration test generic_e2e_test.go should work against any SNMP MIB-2 compliant host (e.g. a router, NAS box, printer). To use, edit your host file so gosnmp-test-host resolves to the system's IP.

The other integration test uses the Verax Snmp Simulator [1]: download, install and run it with the default configuration. Then, in the gosnmp directory, run these commands (or equivalents for your system):

cd ~/go/src/github.com/soniah/gosnmp
ln -s /usr/local/vxsnmpsimulator/device device

# remove randomising elements from Verax device files
cd device/cisco
sed -i -e 's!\/\/\$.*!!' -e 's!^M!!' cisco_router.txt
sed -i -e 's/\/\/\^int.unq()\^\/\//2/' cisco_router.txt
cd ../os
sed -i -e 's!\/\/\$.*!!' -e 's!^M!!' os-linux-std.txt
sed -i -e 's/\/\/\^int.unq()\^\/\//2/' os-linux-std.txt
cd ~/go/src/github.com/soniah/gosnmp
go test

To run only the Verax tests:

go test -run TestVeraxGet 2>&1 | less

I have noticed that the Verax tests randomly fail when using multi-OID Get() requests. I believe these bugs come from Verax not GoSNMP. To run non-Verax tests:

% grep -h '^func.*Test' *test.go
func TestEnmarshalVarbind(t *testing.T) {
func TestEnmarshalVBL(t *testing.T) {
... <snip>

# for example
go test -run TestEnmarshalMsg

# or use the helpful shell script
./non-verax-tests.sh

To profile cpu usage:

go test -cpuprofile cpu.out
go test -c
go tool pprof gosnmp.test cpu.out

To profile memory usage:

go test -memprofile mem.out
go test -c
go tool pprof gosnmp.test mem.out

To check test coverage:

go get github.com/axw/gocov/gocov
go get github.com/matm/gocov-html
gocov test github.com/soniah/gosnmp | gocov-html > gosnmp.html && firefox gosnmp.html &

[1] http://www.veraxsystems.com/en/products/snmpsimulator

License

Some parts of the code are borrowed by the Golang project (specifically some functions for unmarshaling BER responses), which are under the same terms and conditions as the Go language. The rest of the code is under a BSD license.

See the LICENSE file for more details.

The remaining code is Copyright 2012-2014 the GoSNMP Authors - see AUTHORS.md for a list of authors.

Documentation

Index

Constants

View Source
const (
	EndOfContents     Asn1BER = 0x00
	UnknownType               = 0x00 // TODO these should all be type Asn1BER, however
	Boolean                   = 0x01 // tests fail if implemented. See for example
	Integer                   = 0x02 /// http://stackoverflow.com/questions/5037610/typed-constant-declaration-list.
	BitString                 = 0x03
	OctetString               = 0x04
	Null                      = 0x05
	ObjectIdentifier          = 0x06
	ObjectDescription         = 0x07
	IPAddress                 = 0x40
	Counter32                 = 0x41
	Gauge32                   = 0x42
	TimeTicks                 = 0x43
	Opaque                    = 0x44
	NsapAddress               = 0x45
	Counter64                 = 0x46
	Uinteger32                = 0x47
	NoSuchObject              = 0x80
	NoSuchInstance            = 0x81
	EndOfMibView              = 0x82
)

Asn1BER's - http://www.ietf.org/rfc/rfc1442.txt

Variables

View Source
var Default = &GoSNMP{
	Port:      161,
	Community: "public",
	Version:   Version2c,
	Timeout:   time.Duration(2) * time.Second,
	Retries:   3,
}

The default connection settings

View Source
var LoggingDisabled bool

LoggingDisabled is set if the Logger is nil, short circuits any 'slog' calls

Functions

func Partition added in v1.2.0

func Partition(currentPosition, partitionSize, sliceLength int) bool

Partition - returns true when dividing a slice into partitionSize lengths, including last partition which may be smaller than partitionSize. This is useful when you have a large array of OIDs to run Get() on. See the tests for example usage.

For example for a slice of 8 items to be broken into partitions of length 3, Partition returns true for the currentPosition having the following values:

0 1 2 3 4 5 6 7

T        T     T

func ToBigInt

func ToBigInt(value interface{}) *big.Int

ToBigInt converts SnmpPDU.Value to big.Int, or returns a zero big.Int for non int-like types (eg strings).

This is a convenience function to make working with SnmpPDU's easier - it reduces the need for type assertions. A big.Int is convenient, as SNMP can return int32, uint32, and uint64.

Types

type Asn1BER

type Asn1BER byte

Asn1BER is the type of the SNMP PDU

type BitStringValue

type BitStringValue struct {
	Bytes     []byte // bits packed into bytes.
	BitLength int    // length in bits.
}

BitStringValue is the structure to use when you want an ASN.1 BIT STRING type. A bit string is padded up to the nearest byte in memory and the number of valid bits is recorded. Padding bits will be zero.

func (BitStringValue) At

func (b BitStringValue) At(i int) int

At returns the bit at the given index. If the index is out of range it returns false.

func (BitStringValue) RightAlign

func (b BitStringValue) RightAlign() []byte

RightAlign returns a slice where the padding bits are at the beginning. The slice may share memory with the BitString.

type GoSNMP

type GoSNMP struct {

	// Target is an ipv4 address
	Target string

	// Port is a udp port
	Port uint16

	// Community is an SNMP Community string
	Community string

	// Version is an SNMP Version
	Version SnmpVersion

	// Timeout is the timeout for the SNMP Query
	Timeout time.Duration

	// Set the number of retries to attempt within timeout.
	Retries int

	// Conn is net connection to use, typically establised using GoSNMP.Connect()
	Conn net.Conn

	// Logger is the GoSNMP.Logger to use for debugging. If nil, debugging
	// output will be discarded (/dev/null). For verbose logging to stdout:
	// x.Logger = log.New(os.Stdout, "", 0)
	Logger Logger
	// contains filtered or unexported fields
}

GoSNMP represents GoSNMP library state

func (*GoSNMP) BulkWalk added in v1.3.0

func (x *GoSNMP) BulkWalk(rootOid string, walkFn WalkFunc) error

BulkWalk retrieves a subtree of values using GETBULK. As the tree is walked walkFn is called for each new value. The function immediately returns an error if either there is an underlaying SNMP error (e.g. GetBulk fails), or if walkFn returns an error.

func (*GoSNMP) BulkWalkAll added in v1.3.0

func (x *GoSNMP) BulkWalkAll(rootOid string) (results []SnmpPDU, err error)

BulkWalkAll is similar to BulkWalk but returns a filled array of all values rather than using a callback function to stream results.

func (*GoSNMP) Connect added in v1.2.0

func (x *GoSNMP) Connect() error

Connect initiates a connection to the target host

func (*GoSNMP) Get

func (x *GoSNMP) Get(oids []string) (result *SnmpPacket, err error)

Get sends an SNMP GET request

func (*GoSNMP) GetBulk added in v1.2.0

func (x *GoSNMP) GetBulk(oids []string, nonRepeaters uint8, maxRepetitions uint8) (result *SnmpPacket, err error)

GetBulk sends an SNMP GETBULK request

func (*GoSNMP) GetNext added in v1.2.0

func (x *GoSNMP) GetNext(oids []string) (result *SnmpPacket, err error)

GetNext sends an SNMP GETNEXT request

func (*GoSNMP) Set added in v1.2.0

func (x *GoSNMP) Set(pdus []SnmpPDU) (result *SnmpPacket, err error)

Set sends an SNMP SET request

func (*GoSNMP) Walk

func (x *GoSNMP) Walk(rootOid string, walkFn WalkFunc) error

Walk retrieves a subtree of values using GETNEXT - a request is made for each value, unlike BulkWalk which does this operation in batches. As the tree is walked walkFn is called for each new value. The function immediately returns an error if either there is an underlaying SNMP error (e.g. GetNext fails), or if walkFn returns an error.

func (*GoSNMP) WalkAll added in v1.3.0

func (x *GoSNMP) WalkAll(rootOid string) (results []SnmpPDU, err error)

WalkAll is similar to Walk but returns a filled array of all values rather than using a callback function to stream results.

type Logger added in v1.2.0

type Logger interface {
	Print(v ...interface{})
	Printf(format string, v ...interface{})
}

Logger is an interface used for debugging. Both Print and Printf have the same interfaces as Package Log in the std library. The Logger interface is small to give you flexibility in how you do your debugging.

For verbose logging to stdout:

gosnmp_logger = log.New(os.Stdout, "", 0)

type PDUType added in v1.2.0

type PDUType byte

PDUType describes which SNMP Protocol Data Unit is being sent.

const (
	Sequence       PDUType = 0x30
	GetRequest     PDUType = 0xa0
	GetNextRequest PDUType = 0xa1
	GetResponse    PDUType = 0xa2
	SetRequest     PDUType = 0xa3
	Trap           PDUType = 0xa4
	GetBulkRequest PDUType = 0xa5
)

The currently supported PDUType's

type SnmpPDU

type SnmpPDU struct {

	// Name is an oid in string format eg ".1.3.6.1.4.9.27"
	Name string

	// The type of the value eg Integer
	Type Asn1BER

	// The value to be set by the SNMP set
	Value interface{}
}

SnmpPDU will be used when doing SNMP Set's

type SnmpPacket

type SnmpPacket struct {
	Version        SnmpVersion
	Community      string
	PDUType        PDUType
	RequestID      uint32
	Error          uint8
	ErrorIndex     uint8
	NonRepeaters   uint8
	MaxRepetitions uint8
	Variables      []SnmpPDU
}

SnmpPacket struct represents the entire SNMP Message or Sequence at the application layer.

type SnmpVersion

type SnmpVersion uint8

SnmpVersion 1 and 2c implemented, 3 planned

const (
	Version1  SnmpVersion = 0x0
	Version2c SnmpVersion = 0x1
)

SnmpVersion 1 and 2c implemented, 3 planned

func (SnmpVersion) String

func (s SnmpVersion) String() string

type VarBind

type VarBind struct {
	Name  asn1.ObjectIdentifier
	Value asn1.RawValue
}

VarBind struct represents an SNMP Varbind.

type WalkFunc added in v1.3.0

type WalkFunc func(dataUnit SnmpPDU) error

WalkFunc is the type of the function called for each data unit visited by the Walk function. If an error is returned processing stops.

Directories

Path Synopsis
This program demonstrates BulkWalk.
This program demonstrates BulkWalk.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL