Temporarily add go-agentx (w/ fixes to lexico ordering)
This commit is contained in:
185
go-agentx/pdu/variable.go
Normal file
185
go-agentx/pdu/variable.go
Normal file
@ -0,0 +1,185 @@
|
||||
// Copyright 2018 The agentx authors
|
||||
// Licensed under the LGPLv3 with static-linking exception.
|
||||
// See LICENCE file for details.
|
||||
|
||||
package pdu
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/posteo/go-agentx/value"
|
||||
)
|
||||
|
||||
// Variable defines the pdu varbind packet.
|
||||
type Variable struct {
|
||||
Type VariableType
|
||||
Name ObjectIdentifier
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
// Set sets the variable.
|
||||
func (v *Variable) Set(oid value.OID, t VariableType, value interface{}) {
|
||||
v.Name.SetIdentifier(oid)
|
||||
v.Type = t
|
||||
v.Value = value
|
||||
}
|
||||
|
||||
// ByteSize returns the number of bytes, the binding would need in the encoded version.
|
||||
func (v *Variable) ByteSize() int {
|
||||
bytes, err := v.MarshalBinary()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return len(bytes)
|
||||
}
|
||||
|
||||
// MarshalBinary returns the pdu packet as a slice of bytes.
|
||||
func (v *Variable) MarshalBinary() ([]byte, error) {
|
||||
buffer := &bytes.Buffer{}
|
||||
|
||||
binary.Write(buffer, binary.LittleEndian, &v.Type)
|
||||
buffer.WriteByte(0x00)
|
||||
buffer.WriteByte(0x00)
|
||||
|
||||
nameBytes, err := v.Name.MarshalBinary()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buffer.Write(nameBytes)
|
||||
|
||||
switch v.Type {
|
||||
case VariableTypeInteger:
|
||||
value := v.Value.(int32)
|
||||
binary.Write(buffer, binary.LittleEndian, &value)
|
||||
case VariableTypeOctetString:
|
||||
octetString := &OctetString{Text: v.Value.(string)}
|
||||
octetStringBytes, err := octetString.MarshalBinary()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buffer.Write(octetStringBytes)
|
||||
case VariableTypeNull, VariableTypeNoSuchObject, VariableTypeNoSuchInstance, VariableTypeEndOfMIBView:
|
||||
break
|
||||
case VariableTypeObjectIdentifier:
|
||||
targetOID, err := value.ParseOID(v.Value.(string))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
oi := &ObjectIdentifier{}
|
||||
oi.SetIdentifier(targetOID)
|
||||
oiBytes, err := oi.MarshalBinary()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buffer.Write(oiBytes)
|
||||
case VariableTypeIPAddress:
|
||||
ip := v.Value.(net.IP)
|
||||
octetString := &OctetString{Text: string(ip)}
|
||||
octetStringBytes, err := octetString.MarshalBinary()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buffer.Write(octetStringBytes)
|
||||
case VariableTypeCounter32, VariableTypeGauge32:
|
||||
value := v.Value.(uint32)
|
||||
binary.Write(buffer, binary.LittleEndian, &value)
|
||||
case VariableTypeTimeTicks:
|
||||
value := uint32(v.Value.(time.Duration).Seconds() * 100)
|
||||
binary.Write(buffer, binary.LittleEndian, &value)
|
||||
case VariableTypeOpaque:
|
||||
octetString := &OctetString{Text: string(v.Value.([]byte))}
|
||||
octetStringBytes, err := octetString.MarshalBinary()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buffer.Write(octetStringBytes)
|
||||
case VariableTypeCounter64:
|
||||
value := v.Value.(uint64)
|
||||
binary.Write(buffer, binary.LittleEndian, &value)
|
||||
default:
|
||||
return nil, fmt.Errorf("unhandled variable type %s", v.Type)
|
||||
}
|
||||
|
||||
return buffer.Bytes(), nil
|
||||
}
|
||||
|
||||
// UnmarshalBinary sets the packet structure from the provided slice of bytes.
|
||||
func (v *Variable) UnmarshalBinary(data []byte) error {
|
||||
buffer := bytes.NewBuffer(data)
|
||||
|
||||
if err := binary.Read(buffer, binary.LittleEndian, &v.Type); err != nil {
|
||||
return err
|
||||
}
|
||||
offset := 4
|
||||
|
||||
if err := v.Name.UnmarshalBinary(data[offset:]); err != nil {
|
||||
return err
|
||||
}
|
||||
offset += v.Name.ByteSize()
|
||||
|
||||
switch v.Type {
|
||||
case VariableTypeInteger:
|
||||
value := int32(0)
|
||||
if err := binary.Read(buffer, binary.LittleEndian, &value); err != nil {
|
||||
return err
|
||||
}
|
||||
v.Value = value
|
||||
case VariableTypeOctetString:
|
||||
octetString := &OctetString{}
|
||||
if err := octetString.UnmarshalBinary(data[offset:]); err != nil {
|
||||
return err
|
||||
}
|
||||
v.Value = octetString.Text
|
||||
case VariableTypeNull, VariableTypeNoSuchObject, VariableTypeNoSuchInstance, VariableTypeEndOfMIBView:
|
||||
v.Value = nil
|
||||
case VariableTypeObjectIdentifier:
|
||||
oid := &ObjectIdentifier{}
|
||||
if err := oid.UnmarshalBinary(data[offset:]); err != nil {
|
||||
return err
|
||||
}
|
||||
v.Value = oid.GetIdentifier()
|
||||
case VariableTypeIPAddress:
|
||||
octetString := &OctetString{}
|
||||
if err := octetString.UnmarshalBinary(data[offset:]); err != nil {
|
||||
return err
|
||||
}
|
||||
v.Value = net.IP(octetString.Text)
|
||||
case VariableTypeCounter32, VariableTypeGauge32:
|
||||
value := uint32(0)
|
||||
if err := binary.Read(buffer, binary.LittleEndian, &value); err != nil {
|
||||
return err
|
||||
}
|
||||
v.Value = value
|
||||
case VariableTypeTimeTicks:
|
||||
value := uint32(0)
|
||||
if err := binary.Read(buffer, binary.LittleEndian, &value); err != nil {
|
||||
return err
|
||||
}
|
||||
v.Value = time.Duration(value) * time.Second / 100
|
||||
case VariableTypeOpaque:
|
||||
octetString := &OctetString{}
|
||||
if err := octetString.UnmarshalBinary(data[offset:]); err != nil {
|
||||
return err
|
||||
}
|
||||
v.Value = []byte(octetString.Text)
|
||||
case VariableTypeCounter64:
|
||||
value := uint64(0)
|
||||
if err := binary.Read(buffer, binary.LittleEndian, &value); err != nil {
|
||||
return err
|
||||
}
|
||||
v.Value = value
|
||||
default:
|
||||
return fmt.Errorf("unhandled variable type %s", v.Type)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *Variable) String() string {
|
||||
return fmt.Sprintf("(variable %s = %v)", v.Type, v.Value)
|
||||
}
|
Reference in New Issue
Block a user