bosun.org@v0.0.0-20210513094433-e25bc3e69a1f/snmp/mib/mib.go (about) 1 // Package mib parses modules of the virtual management information store. 2 package mib 3 4 import ( 5 "bytes" 6 "fmt" 7 "os/exec" 8 "strconv" 9 "strings" 10 "sync" 11 12 "bosun.org/snmp/asn1" 13 ) 14 15 var mibDir = "" 16 17 // Load registers an additional directory with MIB files. The standard 18 // system MIBs are always pre-loaded. 19 func Load(dir string) { 20 if mibDir == "" { 21 mibDir = dir 22 } else { 23 mibDir += ":" + dir 24 } 25 } 26 27 // Lookup looks up the given object prefix using the snmptranslate utility. 28 func Lookup(prefix string) (asn1.ObjectIdentifier, error) { 29 cache.Lock() 30 if oid, ok := cache.lookup[prefix]; ok { 31 cache.Unlock() 32 return oid, nil 33 } 34 cache.Unlock() 35 if oid, err := parseOID(prefix); err == nil { 36 cache.Lock() 37 cache.lookup[prefix] = oid 38 cache.Unlock() 39 return oid, nil 40 } 41 cmd := exec.Command( 42 "snmptranslate", 43 "-Le", 44 "-M", "+"+mibDir, 45 "-m", "all", 46 "-On", 47 prefix, 48 ) 49 stdout := new(bytes.Buffer) 50 stderr := new(bytes.Buffer) 51 cmd.Stdout = stdout 52 cmd.Stderr = stderr 53 if err := cmd.Run(); err != nil { 54 return nil, fmt.Errorf("snmp: Lookup(%q): %q: %s", prefix, cmd.Args, err) 55 } 56 if stderr.Len() != 0 { 57 return nil, fmt.Errorf("snmp: Lookup(%q): %q: %s", prefix, cmd.Args, stderr) 58 } 59 oid, err := parseOID(strings.TrimSpace(stdout.String())) 60 if err != nil { 61 return nil, err 62 } 63 cache.Lock() 64 cache.lookup[prefix] = oid 65 cache.Unlock() 66 return oid, nil 67 } 68 69 func init() { 70 cache.lookup = make(map[string]asn1.ObjectIdentifier) 71 } 72 73 // cache avoids excessive use of snmptranslate. 74 var cache struct { 75 lookup map[string]asn1.ObjectIdentifier 76 sync.Mutex 77 } 78 79 // parseOID parses the string-encoded OID, for example the 80 // string "1.3.6.1.2.1.1.5.0" becomes sysName.0 81 func parseOID(s string) (oid asn1.ObjectIdentifier, err error) { 82 if s[0] == '.' { 83 s = s[1:] 84 } 85 var n int 86 for _, elem := range strings.Split(s, ".") { 87 n, err = strconv.Atoi(elem) 88 if err != nil { 89 return 90 } 91 oid = append(oid, n) 92 } 93 return 94 }