Documentation ¶
Overview ¶
Package gsnmpgo is an snmp library for Go; it uses Go/CGo to wrap gsnmp.
gsnmpgo is pre 1.0, therefore API's may change, and tests are minimal.
ISSUES ¶
Snmp walks aren't being done as "GETBULK" when using snmp v2c, rather repeated getnexts are being done ie like snmp v1. The gsnmp C library doesn't implement GETBULK directly, my intention is to write the C code to do it.
Threading: either gsnmp isn't totally thread safe, or I'm making errors with my C calls from Go (more likely). I'm getting aborts with this message:
GLib-WARNING **: g_main_context_prepare(): main loop already active in another thread
My current workaround is to force Query() calls to be synchronous:
var mu sync.Mutex mu.Lock() _, _ = gsnmpgo.Query(params) mu.Unlock()
INSTALLATION ¶
gsnmpgo requires the following libraries, as well as library header files:
glib2.0, gsnmp, gnet-2.0
Here is an example of installation on Ubuntu Precise 12.04.1:
# setup Go sudo aptitude install golang git cat >> ~/.bashrc export GOPATH="${HOME}/go" ^D mkdir ~/go && source ~/.bashrc && cd ~/go # install GoLLRB; ignore error about "no Go source files" - GoLLRB has a # non-standard layout go get -d github.com/petar/GoLLRB go install github.com/petar/GoLLRB/llrb # install tcgl/applog go get code.google.com/p/tcgl/applog # install gsnmpgo go get -d github.com/soniah/gsnmpgo sudo aptitude install libglib2.0-dev libgsnmp0-dev libgnet-dev go install github.com/soniah/gsnmpgo # test working (you will need to edit example.go and # provide different uris) cd src/github.com/soniah/gsnmpgo/examples go run example.go
Builds ok with these C libs (Ubuntu versions shown):
libglib2.0-dev 2.32.3-0ubuntu1 libgsnmp0-dev 0.3.0-1.1 libgnet-dev 2.0.8-2.1
SUMMARY ¶
(most of this code is in examples/example.go)
// do an snmp get; RFC 4088 is used for uris uri := `snmp://public@192.168.1.10//(1.3.6.1.2.1.1.1.0)` params := gsnmpgo.NewDefaultParams(uri) results, err := gsnmpgo.Query(params) if err != nil { fmt.Println(err) os.Exit(1) } // check your results gsnmpgo.Dump(results) // turn on debugging gsnmpgo.Debug = true
SPECIFYING URIS ¶
http://tools.ietf.org/html/rfc4088 is used for specifying snmp uris; as well as doing an snmp get you can also do a snmp getnext or snmp walk:
// GET - notice you can have multiple OIDs uri := `snmp://public@192.168.1.10//(1.3.6.1.2.1.1.1.0,1.3.6.1.2.1.1.2.0)` // NEXT - notice the plus sign at the end uri := `snmp://public@192.168.1.10//1.3.6.1.2.1+` // WALK - notice the star at the end // uri := `snmp://public@192.168.1.10//1.3.6.1.2.1.*`
RESULTS ¶
The results are returned as an LLRB tree to provide "ordered map" functionality (ie finding items by "key", and iterating "in order"). Items in the tree are of type QueryResult:
type QueryResult struct { Oid string Value Varbinder }
See http://github.com/petar/GoLLRB for more documentation on using the LLRB tree.
SNMP types are represented by Go types that implement the Varbinder interface (eg "Octet String" is VBT_OctetString, "IP Address" is VBT_IPAddress). Use a type switch to make decisions based on the SNMP type:
ch := results.IterAscend() for { r := <-ch if r == nil { break } result := r.(gsnmpgo.QueryResult) switch result.Value.(type) { case gsnmpgo.VBT_OctetString: fmt.Printf("OID %s is an octet string: %s\n", result.Oid, result.Value) default: fmt.Printf("OID %s is some other type\n", result.Oid) } }
The Varbinder interface has two convenience functions Integer() and String() that allow you to get all your results "as a string" or "as a number":
type Varbinder interface { Integer() *big.Int fmt.Stringer } ch2 := results.IterAscend() for { r := <-ch2 if r == nil { break } result := r.(gsnmpgo.QueryResult) fmt.Printf("OID %s type: %T\n", result.Oid, result.Value) fmt.Printf("OID %s as a number: %d\n", result.Oid, result.Value.Integer()) fmt.Printf("OID %s as a string: %s\n\n", result.Oid, result.Value) }
Some of the Stringers are smart, for example gsnmpgo.VBT_Timeticks will be formatted as days, hours, etc when returned as a string:
OID 1.3.6.1.2.1.1.3.0 as a number: 4381200 OID 1.3.6.1.2.1.1.3.0 as a string: 0 days, 12:10:12.00
TESTS ¶
The tests use the Verax Snmp Simulator [1]; setup Verax before running "go test":
* download, install and run Verax with the default configuration
* in the gsnmpgo/testing directory, setup these symlinks (or equivalents for your system):
ln -s /usr/local/vxsnmpsimulator/device device ln -s /usr/local/vxsnmpsimulator/conf/devices.conf.xml devices.conf.xml
* remove randomising elements from Verax device files:
cd testing/device/cisco sed -i -e 's!\/\/\$.*!!' -e 's!^M!!' cisco_router.txt cd ../os sed -i -e 's!\/\/\$.*!!' -e 's!^M!!' os-linux-std.txt
[1] http://www.veraxsystems.com/en/products/snmpsimulator
HELPER FUNCTIONS ¶
There are a number of helper functions. Many of these have tests that serve as example usage.
PartitionAllP()
If you have a many oids to retrieve for a single device, you could:
- send all the oids in one SNMP Get - could cause network problems
- do an SNMP BulkWalk - but that isn't implemented yet, and maybe your target device only supports SNMP v1 anyway
Instead, use PartitionAllP() to break up your large list of OIDs into partitions of n.
Sonia Hamilton, sonia@snowfrog.net, http://www.snowfrog.net.
Index ¶
- Constants
- Variables
- func CompareVerax(t *testing.T, gresults, vresults *llrb.Tree)
- func Dump(results *llrb.Tree)
- func LessOID(astruct, bstruct interface{}) bool
- func OidAsString(o []int) string
- func PartitionAllP(current_position, partition_size, slice_length int) bool
- func Query(params *QueryParams) (results *llrb.Tree, err error)
- func ReadVeraxResults(filename string) (results *llrb.Tree, err error)
- type PduError
- type QueryParams
- type QueryResult
- type SecLevel
- type SecModel
- type SnmpVersion
- type UriType
- type VBT_Counter32
- type VBT_Counter64
- type VBT_EndOfMibView
- type VBT_IPAddress
- type VBT_Integer32
- type VBT_NoSuchInstance
- type VBT_NoSuchObject
- type VBT_Null
- type VBT_ObjectID
- type VBT_OctetString
- type VBT_Opaque
- type VBT_Timeticks
- type VBT_Unsigned32
- type VarBindType
- type Varbinder
Constants ¶
const MAX_URI_COUNT = 50
the maximum number of paths that can be in a single uri
Variables ¶
var Debug bool // global debugging flag
Functions ¶
func LessOID ¶
func LessOID(astruct, bstruct interface{}) bool
LessOID is the LessFunc for GoLLRB
It returns true if oid a is less than oid b.
func OidAsString ¶
Converts an OID in a slice of int format (eg []int{1, 3, 6, 1} to a string.
func PartitionAllP ¶
PartitionAllP - returns true when dividing a slice into partition_size lengths, including last partition which may be smaller than partition_size.
For example for a slice of 8 items to be broken into partitions of length 3, PartitionAllP returns true for the current_position having the following values:
0 1 2 3 4 5 6 7
T T T
'P' stands for Predicate (like foo? in Ruby, foop in Lisp)
Types ¶
type PduError ¶
type PduError int
type and values for _Ctype_gint32
const ( GNET_SNMP_PDU_ERR_DONE PduError = iota - 4 GNET_SNMP_PDU_ERR_PROCEDURE GNET_SNMP_PDU_ERR_INTERNAL GNET_SNMP_PDU_ERR_NORESPONSE GNET_SNMP_PDU_ERR_NOERROR GNET_SNMP_PDU_ERR_TOOBIG GNET_SNMP_PDU_ERR_NOSUCHNAME GNET_SNMP_PDU_ERR_BADVALUE GNET_SNMP_PDU_ERR_READONLY GNET_SNMP_PDU_ERR_GENERROR GNET_SNMP_PDU_ERR_NOACCESS GNET_SNMP_PDU_ERR_WRONGTYPE GNET_SNMP_PDU_ERR_WRONGLENGTH GNET_SNMP_PDU_ERR_WRONGENCODING GNET_SNMP_PDU_ERR_WRONGVALUE GNET_SNMP_PDU_ERR_NOCREATION GNET_SNMP_PDU_ERR_INCONSISTENTVALUE GNET_SNMP_PDU_ERR_RESOURCEUNAVAILABLE GNET_SNMP_PDU_ERR_COMMITFAILED GNET_SNMP_PDU_ERR_UNDOFAILED GNET_SNMP_PDU_ERR_AUTHORIZATIONERROR GNET_SNMP_PDU_ERR_NOTWRITABLE GNET_SNMP_PDU_ERR_INCONSISTENTNAME )
type QueryParams ¶
type QueryParams struct { Uri string Version SnmpVersion Timeout int // timeout in milliseconds Retries int // number of retries // Nonrep and Maxrep will be used by v2c BULK GETs. // From O'Reilly "Essential SNMP": "nonrep is the number of scalar // objects that this command will return; rep is the number of // instances of each nonscalar object that the command will return." Nonrep int Maxrep int // if Tree is non-nil, it will be used for appending Query() // results eg when doing two GETs in a row Tree *llrb.Tree }
Struct of parameters to pass to Query
func NewDefaultParams ¶
func NewDefaultParams(uri string) *QueryParams
NewDefaultParams returns QueryParams with sensible default values
type QueryResult ¶
A single result, used as an Item in the llrb tree
type SnmpVersion ¶
type SnmpVersion int
type and values for _Ctype_GNetSnmpVersion
const ( GNET_SNMP_V1 SnmpVersion = iota GNET_SNMP_V2C GNET_SNMP_V2P GNET_SNMP_V3 )
type VBT_Counter32 ¶
type VBT_Counter32 uint32
GNET_SNMP_VARBIND_TYPE_COUNTER32
func (VBT_Counter32) Integer ¶
func (r VBT_Counter32) Integer() *big.Int
func (VBT_Counter32) String ¶
func (r VBT_Counter32) String() string
type VBT_Counter64 ¶
type VBT_Counter64 uint64
GNET_SNMP_VARBIND_TYPE_COUNTER64
func (VBT_Counter64) Integer ¶
func (r VBT_Counter64) Integer() *big.Int
func (VBT_Counter64) String ¶
func (r VBT_Counter64) String() string
type VBT_EndOfMibView ¶
type VBT_EndOfMibView struct{}
GNET_SNMP_VARBIND_TYPE_ENDOFMIBVIEW
func (VBT_EndOfMibView) Integer ¶
func (r VBT_EndOfMibView) Integer() *big.Int
func (VBT_EndOfMibView) String ¶
func (r VBT_EndOfMibView) String() string
type VBT_IPAddress ¶
type VBT_IPAddress string
GNET_SNMP_VARBIND_TYPE_IPADDRESS
func (VBT_IPAddress) Integer ¶
func (r VBT_IPAddress) Integer() *big.Int
func (VBT_IPAddress) String ¶
func (r VBT_IPAddress) String() string
type VBT_Integer32 ¶
type VBT_Integer32 int32
GNET_SNMP_VARBIND_TYPE_INTEGER32
func (VBT_Integer32) Integer ¶
func (r VBT_Integer32) Integer() *big.Int
func (VBT_Integer32) String ¶
func (r VBT_Integer32) String() string
type VBT_NoSuchInstance ¶
type VBT_NoSuchInstance struct{}
GNET_SNMP_VARBIND_TYPE_NOSUCHINSTANCE
func (VBT_NoSuchInstance) Integer ¶
func (r VBT_NoSuchInstance) Integer() *big.Int
func (VBT_NoSuchInstance) String ¶
func (r VBT_NoSuchInstance) String() string
type VBT_NoSuchObject ¶
type VBT_NoSuchObject struct{}
GNET_SNMP_VARBIND_TYPE_NOSUCHOBJECT
func (VBT_NoSuchObject) Integer ¶
func (r VBT_NoSuchObject) Integer() *big.Int
func (VBT_NoSuchObject) String ¶
func (r VBT_NoSuchObject) String() string
type VBT_ObjectID ¶
type VBT_ObjectID string
GNET_SNMP_VARBIND_TYPE_OBJECTID
func (VBT_ObjectID) Integer ¶
func (r VBT_ObjectID) Integer() *big.Int
func (VBT_ObjectID) String ¶
func (r VBT_ObjectID) String() string
type VBT_OctetString ¶
type VBT_OctetString string
GNET_SNMP_VARBIND_TYPE_OCTETSTRING
func (VBT_OctetString) Integer ¶
func (r VBT_OctetString) Integer() *big.Int
func (VBT_OctetString) String ¶
func (r VBT_OctetString) String() string
type VBT_Opaque ¶
type VBT_Opaque string
GNET_SNMP_VARBIND_TYPE_OPAQUE
func (VBT_Opaque) Integer ¶
func (r VBT_Opaque) Integer() *big.Int
func (VBT_Opaque) String ¶
func (r VBT_Opaque) String() string
type VBT_Timeticks ¶
type VBT_Timeticks uint32
GNET_SNMP_VARBIND_TYPE_TIMETICKS
func (VBT_Timeticks) Integer ¶
func (r VBT_Timeticks) Integer() *big.Int
func (VBT_Timeticks) String ¶
func (r VBT_Timeticks) String() string
type VBT_Unsigned32 ¶
type VBT_Unsigned32 uint32
GNET_SNMP_VARBIND_TYPE_UNSIGNED32
func (VBT_Unsigned32) Integer ¶
func (r VBT_Unsigned32) Integer() *big.Int
func (VBT_Unsigned32) String ¶
func (r VBT_Unsigned32) String() string
type VarBindType ¶
type VarBindType int
type and values for _Ctype_GNetSnmpVarBindType
const ( GNET_SNMP_VARBIND_TYPE_NULL VarBindType = iota GNET_SNMP_VARBIND_TYPE_OCTETSTRING GNET_SNMP_VARBIND_TYPE_OBJECTID GNET_SNMP_VARBIND_TYPE_IPADDRESS GNET_SNMP_VARBIND_TYPE_INTEGER32 GNET_SNMP_VARBIND_TYPE_UNSIGNED32 GNET_SNMP_VARBIND_TYPE_COUNTER32 GNET_SNMP_VARBIND_TYPE_TIMETICKS GNET_SNMP_VARBIND_TYPE_OPAQUE GNET_SNMP_VARBIND_TYPE_COUNTER64 GNET_SNMP_VARBIND_TYPE_NOSUCHOBJECT GNET_SNMP_VARBIND_TYPE_NOSUCHINSTANCE GNET_SNMP_VARBIND_TYPE_ENDOFMIBVIEW )