Add support to convert snmp hex strings to integers (#8426)

This commit is contained in:
Wiard van Rij 2020-12-07 22:45:06 +01:00 committed by GitHub
parent 97469f6d85
commit 139498937a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 62 additions and 15 deletions

View File

@ -113,15 +113,21 @@ option operate similar to the `snmpget` utility.
# is_tag = false # is_tag = false
## Apply one of the following conversions to the variable value: ## Apply one of the following conversions to the variable value:
## float(X) Convert the input value into a float and divides by the ## float(X): Convert the input value into a float and divides by the
## Xth power of 10. Effectively just moves the decimal left ## Xth power of 10. Effectively just moves the decimal left
## X places. For example a value of `123` with `float(2)` ## X places. For example a value of `123` with `float(2)`
## will result in `1.23`. ## will result in `1.23`.
## float: Convert the value into a float with no adjustment. Same ## float: Convert the value into a float with no adjustment. Same
## as `float(0)`. ## as `float(0)`.
## int: Convert the value into an integer. ## int: Convert the value into an integer.
## hwaddr: Convert the value to a MAC address. ## hwaddr: Convert the value to a MAC address.
## ipaddr: Convert the value to an IP address. ## ipaddr: Convert the value to an IP address.
## hextoint:X:Y Convert a hex string value to integer. Where X is the Endian
## and Y the bit size. For example: hextoint:LittleEndian:uint64
## or hextoint:BigEndian:uint32. Valid options for the Endian are:
## BigEndian and LittleEndian. For the bit size: uint16, uint32
## and uint64.
##
# conversion = "" # conversion = ""
``` ```

View File

@ -3,6 +3,7 @@ package snmp
import ( import (
"bufio" "bufio"
"bytes" "bytes"
"encoding/binary"
"fmt" "fmt"
"log" "log"
"math" "math"
@ -574,12 +575,6 @@ func (s *Snmp) getConnection(idx int) (snmpConnection, error) {
} }
// fieldConvert converts from any type according to the conv specification // fieldConvert converts from any type according to the conv specification
// "float"/"float(0)" will convert the value into a float.
// "float(X)" will convert the value into a float, and then move the decimal before Xth right-most digit.
// "int" will convert the value into an integer.
// "hwaddr" will convert the value into a MAC address.
// "ipaddr" will convert the value into into an IP address.
// "" will convert a byte slice into a string.
func fieldConvert(conv string, v interface{}) (interface{}, error) { func fieldConvert(conv string, v interface{}) (interface{}, error) {
if conv == "" { if conv == "" {
if bs, ok := v.([]byte); ok { if bs, ok := v.([]byte); ok {
@ -671,6 +666,46 @@ func fieldConvert(conv string, v interface{}) (interface{}, error) {
return v, nil return v, nil
} }
split := strings.Split(conv, ":")
if split[0] == "hextoint" && len(split) == 3 {
endian := split[1]
bit := split[2]
bv, ok := v.([]byte)
if !ok {
return v, nil
}
if endian == "LittleEndian" {
switch bit {
case "uint64":
v = binary.LittleEndian.Uint64(bv)
case "uint32":
v = binary.LittleEndian.Uint32(bv)
case "uint16":
v = binary.LittleEndian.Uint16(bv)
default:
return nil, fmt.Errorf("invalid bit value (%s) for hex to int conversion", bit)
}
} else if endian == "BigEndian" {
switch bit {
case "uint64":
v = binary.BigEndian.Uint64(bv)
case "uint32":
v = binary.BigEndian.Uint32(bv)
case "uint16":
v = binary.BigEndian.Uint16(bv)
default:
return nil, fmt.Errorf("invalid bit value (%s) for hex to int conversion", bit)
}
} else {
return nil, fmt.Errorf("invalid Endian value (%s) for hex to int conversion", endian)
}
return v, nil
}
if conv == "ipaddr" { if conv == "ipaddr" {
var ipbs []byte var ipbs []byte

View File

@ -739,6 +739,12 @@ func TestFieldConvert(t *testing.T) {
{[]byte("abcd"), "ipaddr", "97.98.99.100"}, {[]byte("abcd"), "ipaddr", "97.98.99.100"},
{"abcd", "ipaddr", "97.98.99.100"}, {"abcd", "ipaddr", "97.98.99.100"},
{[]byte("abcdefghijklmnop"), "ipaddr", "6162:6364:6566:6768:696a:6b6c:6d6e:6f70"}, {[]byte("abcdefghijklmnop"), "ipaddr", "6162:6364:6566:6768:696a:6b6c:6d6e:6f70"},
{[]byte{0x00, 0x09, 0x3E, 0xE3, 0xF6, 0xD5, 0x3B, 0x60}, "hextoint:BigEndian:uint64", uint64(2602423610063712)},
{[]byte{0x00, 0x09, 0x3E, 0xE3}, "hextoint:BigEndian:uint32", uint32(605923)},
{[]byte{0x00, 0x09}, "hextoint:BigEndian:uint16", uint16(9)},
{[]byte{0x00, 0x09, 0x3E, 0xE3, 0xF6, 0xD5, 0x3B, 0x60}, "hextoint:LittleEndian:uint64", uint64(6934371307618175232)},
{[]byte{0x00, 0x09, 0x3E, 0xE3}, "hextoint:LittleEndian:uint32", uint32(3812493568)},
{[]byte{0x00, 0x09}, "hextoint:LittleEndian:uint16", uint16(2304)},
} }
for _, tc := range testTable { for _, tc := range testTable {