forked from isidroamv/WapSNMP
-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathoid.go
148 lines (132 loc) · 2.99 KB
/
oid.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package snmplib
/* Encode decode OIDs.
References : http://rane.com/note161.html
*/
import (
"errors"
"fmt"
"math"
"strconv"
"strings"
)
// The SNMP object identifier type.
type Oid []int
// String returns the string representation for this oid object.
func (o Oid) String() string {
/* A zero-length Oid has to be valid as it's often used as the start of a
Walk. */
if len(o) == 0 {
return "."
}
var result string
for _, val := range o {
result += fmt.Sprintf(".%d", val)
}
return result
}
// MustParseOid parses a string oid to an Oid instance. Panics on error.
func MustParseOid(o string) Oid {
result, err := ParseOid(o)
if err != nil {
panic(err)
}
return result
}
// ParseOid a text format oid into an Oid instance.
func ParseOid(oid string) (Oid, error) {
// Special case "." = [], "" = []
if oid == "." || oid == "" {
return Oid{}, nil
}
if oid[0] == '.' {
oid = oid[1:]
}
oidParts := strings.Split(oid, ".")
res := make([]int, len(oidParts))
for idx, val := range oidParts {
parsedVal, err := strconv.Atoi(val)
if err != nil {
return nil, err
}
res[idx] = parsedVal
}
result := Oid(res)
return result, nil
}
// DecodeOid decodes a ASN.1 BER raw oid into an Oid instance.
func DecodeOid(raw []byte) (*Oid, error) {
if len(raw) < 1 {
return nil, errors.New("oid is at least 1 byte long")
}
result := make([]int, 2)
val := 0
for idx, b := range raw {
if idx == 0 {
result[0] = int(math.Floor(float64(b) / 40))
result[1] = int(math.Mod(float64(b), 40))
continue
}
if b < 128 {
val = val*128 + int(b)
result = append(result, val)
val = 0
} else {
val = val*128 + int(b%128)
}
}
r := Oid(result)
return &r, nil
}
// Encode encodes the oid into an ASN.1 BER byte array.
func (o Oid) Encode() ([]byte, error) {
if len(o) < 3 {
return nil, errors.New("oid needs to be at least 3 long")
}
var result []byte
if o[0] != 1 || o[1] != 3 {
return nil, errors.New("oid didn't start with .1.3")
}
/* Every o is supposed to start with .1.3, which is encoded as
40 * first_byte + second byte. First_byte is ALWAYS 1, second
byte is always 3, so it's 43, or hex 0x2b */
result = append(result, 0x2b)
for i := 2; i < len(o); i++ {
val := o[i]
toadd := make([]int, 0)
if val == 0 {
toadd = append(toadd, 0)
}
for val > 0 {
toadd = append(toadd, val%128)
val /= 128
}
for i := len(toadd) - 1; i >= 0; i-- {
sevenbits := toadd[i]
if i != 0 {
result = append(result, 128+byte(sevenbits))
} else {
result = append(result, byte(sevenbits))
}
}
}
return result, nil
}
// Copy copies an oid into a new object instance.
func (o Oid) Copy() Oid {
dest := make([]int, len(o))
copy(dest, o)
return Oid(dest)
}
/* Within determines if an oid has this oid instance as a prefix.
E.g. MustParseOid("1.2.3").Within("1.2") => true. */
func (o Oid) Within(other Oid) bool {
if len(other) > len(o) {
return false
}
for idx, val := range other {
if o[idx] != val {
return false
}
}
return true
}