Fix snmp tools output parsing when they contain Windows eols (#3396)
This commit is contained in:
parent
662e2df779
commit
f9ded8fdd8
|
@ -1,6 +1,7 @@
|
||||||
package snmp
|
package snmp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
|
@ -88,7 +89,7 @@ func execCmd(arg0 string, args ...string) ([]byte, error) {
|
||||||
if err, ok := err.(*exec.ExitError); ok {
|
if err, ok := err.(*exec.ExitError); ok {
|
||||||
return nil, NestedError{
|
return nil, NestedError{
|
||||||
Err: err,
|
Err: err,
|
||||||
NestedErr: fmt.Errorf("%s", bytes.TrimRight(err.Stderr, "\n")),
|
NestedErr: fmt.Errorf("%s", bytes.TrimRight(err.Stderr, "\r\n")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -856,24 +857,26 @@ func snmpTableCall(oid string) (mibName string, oidNum string, oidText string, f
|
||||||
tagOids := map[string]struct{}{}
|
tagOids := map[string]struct{}{}
|
||||||
// We have to guess that the "entry" oid is `oid+".1"`. snmptable and snmptranslate don't seem to have a way to provide the info.
|
// We have to guess that the "entry" oid is `oid+".1"`. snmptable and snmptranslate don't seem to have a way to provide the info.
|
||||||
if out, err := execCmd("snmptranslate", "-Td", oidFullName+".1"); err == nil {
|
if out, err := execCmd("snmptranslate", "-Td", oidFullName+".1"); err == nil {
|
||||||
lines := bytes.Split(out, []byte{'\n'})
|
scanner := bufio.NewScanner(bytes.NewBuffer(out))
|
||||||
for _, line := range lines {
|
for scanner.Scan() {
|
||||||
if !bytes.HasPrefix(line, []byte(" INDEX")) {
|
line := scanner.Text()
|
||||||
|
|
||||||
|
if !strings.HasPrefix(line, " INDEX") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
i := bytes.Index(line, []byte("{ "))
|
i := strings.Index(line, "{ ")
|
||||||
if i == -1 { // parse error
|
if i == -1 { // parse error
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
line = line[i+2:]
|
line = line[i+2:]
|
||||||
i = bytes.Index(line, []byte(" }"))
|
i = strings.Index(line, " }")
|
||||||
if i == -1 { // parse error
|
if i == -1 { // parse error
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
line = line[:i]
|
line = line[:i]
|
||||||
for _, col := range bytes.Split(line, []byte(", ")) {
|
for _, col := range strings.Split(line, ", ") {
|
||||||
tagOids[mibPrefix+string(col)] = struct{}{}
|
tagOids[mibPrefix+col] = struct{}{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -883,15 +886,16 @@ func snmpTableCall(oid string) (mibName string, oidNum string, oidText string, f
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", "", nil, Errorf(err, "getting table columns")
|
return "", "", "", nil, Errorf(err, "getting table columns")
|
||||||
}
|
}
|
||||||
cols := bytes.SplitN(out, []byte{'\n'}, 2)[0]
|
scanner := bufio.NewScanner(bytes.NewBuffer(out))
|
||||||
|
scanner.Scan()
|
||||||
|
cols := scanner.Text()
|
||||||
if len(cols) == 0 {
|
if len(cols) == 0 {
|
||||||
return "", "", "", nil, fmt.Errorf("could not find any columns in table")
|
return "", "", "", nil, fmt.Errorf("could not find any columns in table")
|
||||||
}
|
}
|
||||||
for _, col := range bytes.Split(cols, []byte{' '}) {
|
for _, col := range strings.Split(cols, " ") {
|
||||||
if len(col) == 0 {
|
if len(col) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
col := string(col)
|
|
||||||
_, isTag := tagOids[mibPrefix+col]
|
_, isTag := tagOids[mibPrefix+col]
|
||||||
fields = append(fields, Field{Name: col, Oid: mibPrefix + col, IsTag: isTag})
|
fields = append(fields, Field{Name: col, Oid: mibPrefix + col, IsTag: isTag})
|
||||||
}
|
}
|
||||||
|
@ -953,18 +957,18 @@ func snmpTranslateCall(oid string) (mibName string, oidNum string, oidText strin
|
||||||
return "", "", "", "", err
|
return "", "", "", "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
bb := bytes.NewBuffer(out)
|
scanner := bufio.NewScanner(bytes.NewBuffer(out))
|
||||||
|
ok := scanner.Scan()
|
||||||
oidText, err = bb.ReadString('\n')
|
if !ok && scanner.Err() != nil {
|
||||||
if err != nil {
|
return "", "", "", "", Errorf(scanner.Err(), "getting OID text")
|
||||||
return "", "", "", "", Errorf(err, "getting OID text")
|
|
||||||
}
|
}
|
||||||
oidText = oidText[:len(oidText)-1]
|
|
||||||
|
oidText = scanner.Text()
|
||||||
|
|
||||||
i := strings.Index(oidText, "::")
|
i := strings.Index(oidText, "::")
|
||||||
if i == -1 {
|
if i == -1 {
|
||||||
// was not found in MIB.
|
// was not found in MIB.
|
||||||
if bytes.Index(bb.Bytes(), []byte(" [TRUNCATED]")) >= 0 {
|
if bytes.Contains(out, []byte("[TRUNCATED]")) {
|
||||||
return "", oid, oid, "", nil
|
return "", oid, oid, "", nil
|
||||||
}
|
}
|
||||||
// not truncated, but not fully found. We still need to parse out numeric OID, so keep going
|
// not truncated, but not fully found. We still need to parse out numeric OID, so keep going
|
||||||
|
@ -974,37 +978,33 @@ func snmpTranslateCall(oid string) (mibName string, oidNum string, oidText strin
|
||||||
oidText = oidText[i+2:]
|
oidText = oidText[i+2:]
|
||||||
}
|
}
|
||||||
|
|
||||||
if i := bytes.Index(bb.Bytes(), []byte(" -- TEXTUAL CONVENTION ")); i != -1 {
|
for scanner.Scan() {
|
||||||
bb.Next(i + len(" -- TEXTUAL CONVENTION "))
|
line := scanner.Text()
|
||||||
tc, err := bb.ReadString('\n')
|
|
||||||
if err != nil {
|
|
||||||
return "", "", "", "", Errorf(err, "getting textual convention")
|
|
||||||
}
|
|
||||||
tc = tc[:len(tc)-1]
|
|
||||||
switch tc {
|
|
||||||
case "MacAddress", "PhysAddress":
|
|
||||||
conversion = "hwaddr"
|
|
||||||
case "InetAddressIPv4", "InetAddressIPv6", "InetAddress":
|
|
||||||
conversion = "ipaddr"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
i = bytes.Index(bb.Bytes(), []byte("::= { "))
|
if strings.HasPrefix(line, " -- TEXTUAL CONVENTION ") {
|
||||||
bb.Next(i + len("::= { "))
|
tc := strings.TrimPrefix(line, " -- TEXTUAL CONVENTION ")
|
||||||
objs, err := bb.ReadString('}')
|
switch tc {
|
||||||
if err != nil {
|
case "MacAddress", "PhysAddress":
|
||||||
return "", "", "", "", Errorf(err, "getting numeric oid")
|
conversion = "hwaddr"
|
||||||
}
|
case "InetAddressIPv4", "InetAddressIPv6", "InetAddress":
|
||||||
objs = objs[:len(objs)-1]
|
conversion = "ipaddr"
|
||||||
for _, obj := range strings.Split(objs, " ") {
|
}
|
||||||
if len(obj) == 0 {
|
} else if strings.HasPrefix(line, "::= { ") {
|
||||||
continue
|
objs := strings.TrimPrefix(line, "::= { ")
|
||||||
}
|
objs = strings.TrimSuffix(objs, " }")
|
||||||
if i := strings.Index(obj, "("); i != -1 {
|
|
||||||
obj = obj[i+1:]
|
for _, obj := range strings.Split(objs, " ") {
|
||||||
oidNum += "." + obj[:strings.Index(obj, ")")]
|
if len(obj) == 0 {
|
||||||
} else {
|
continue
|
||||||
oidNum += "." + obj
|
}
|
||||||
|
if i := strings.Index(obj, "("); i != -1 {
|
||||||
|
obj = obj[i+1:]
|
||||||
|
oidNum += "." + obj[:strings.Index(obj, ")")]
|
||||||
|
} else {
|
||||||
|
oidNum += "." + obj
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue