-
Notifications
You must be signed in to change notification settings - Fork 1
/
union.go
151 lines (136 loc) · 4.63 KB
/
union.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
149
150
151
package gsnmpgo
// gsnmpgo is a go/cgo wrapper around gsnmp.
//
// Copyright (C) 2012-2013 Sonia Hamilton [email protected].
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// union.go contains functions for extracting values from the union
// in the following struct. Go will read the struct as a byte sequence
// as long as the longest field in the struct ie [8]byte. Hence these
// functions take "cbytes [8]byte" as a parameter.
//
// struct _GNetSnmpVarBind {
// guint32 *oid; /* name of the variable */
// gsize oid_len; /* length of the name */
// GNetSnmpVarBindType type; /* variable type / exception */
// union {
// gint32 i32; /* 32 bit signed */
// guint32 ui32; /* 32 bit unsigned */
// gint64 i64; /* 64 bit signed */
// guint64 ui64; /* 64 bit unsigned */
// guint8 *ui8v; /* 8 bit unsigned vector */
// guint32 *ui32v; /* 32 bit unsigned vector */
// } value; /* value of the variable */
// gsize value_len; /* length of a vector in bytes */
// };
/*
// no C code
*/
import "C"
import (
"bytes"
"encoding/binary"
"fmt"
"strconv"
"unsafe"
)
// return i32 field
func union_i32(cbytes [8]byte) (result int32) {
buf := bytes.NewBuffer(cbytes[:])
if err := binary.Read(buf, binary.LittleEndian, &result); err == nil { // read bytes as int32
return result
}
return 0
}
// return ui32 field
func union_ui32(cbytes [8]byte) (result uint32) {
buf := bytes.NewBuffer(cbytes[:])
if err := binary.Read(buf, binary.LittleEndian, &result); err == nil { // read bytes as uint32
return result
}
return 0
}
// i64 field isn't used (??)
// return ui64 field
func union_ui64(cbytes [8]byte) (result uint64) {
buf := bytes.NewBuffer(cbytes[:])
if err := binary.Read(buf, binary.LittleEndian, &result); err == nil { // read bytes as uint64
return result
}
return 0
}
// return ui8v field as an ip address
func union_ui8v_ipaddress(cbytes [8]byte, value_len _Ctype_gsize) (result string) {
if int(value_len) != 4 { // an ip4 address must have 4 bytes
return
}
buf := bytes.NewBuffer(cbytes[:])
var ptr uint64
if err := binary.Read(buf, binary.LittleEndian, &ptr); err == nil { // read bytes as uint64
up := (unsafe.Pointer(uintptr(ptr))) // convert the uint64 into a pointer
gobytes := C.GoBytes(up, 4)
for i := 0; i < 4; i++ {
result += fmt.Sprintf(".%d", gobytes[i])
}
return result[1:] // strip leading dot
}
return
}
// return ui8v field as a string
func union_ui8v_string(cbytes [8]byte, value_len _Ctype_gsize) (result string) {
var ptr uint64
var err error
buf := bytes.NewBuffer(cbytes[:])
if err = binary.Read(buf, binary.LittleEndian, &ptr); err != nil { // read bytes as uint64
return
}
up := (unsafe.Pointer(uintptr(ptr))) // convert the uint64 into a pointer
length := (_Ctype_int)(value_len)
gobytes := C.GoBytes(up, length)
for i := 0; i < int(length); i++ {
if !strconv.IsPrint(rune(gobytes[i])) {
// can't pass gobytes & length to union_ui8v_hexstring() -
// it's also used for TYPE_OPAQUE
return union_ui8v_hexstring(cbytes, value_len)
}
}
return string(gobytes)
}
// the ui8v field contains unprintable characters - convert to "hex string"
//
// eg 00 25 89 27 56 1B
func union_ui8v_hexstring(cbytes [8]byte, value_len _Ctype_gsize) (result string) {
var ptr uint64
var err error
buf := bytes.NewBuffer(cbytes[:])
if err = binary.Read(buf, binary.LittleEndian, &ptr); err != nil { // read bytes as uint64
return
}
up := (unsafe.Pointer(uintptr(ptr))) // convert the uint64 into a pointer
length := (_Ctype_int)(value_len)
gobytes := C.GoBytes(up, length)
for i := 0; i < int(length); i++ {
result += fmt.Sprintf(" %02X", gobytes[i])
}
return result[1:] // strip leading space
}
// return ui32v field
func union_ui32v(cbytes [8]byte) (result *_Ctype_guint32) {
buf := bytes.NewBuffer(cbytes[:])
var ptr uint64
if err := binary.Read(buf, binary.LittleEndian, &ptr); err == nil { // read bytes as uint64
return (*_Ctype_guint32)(unsafe.Pointer(uintptr(ptr))) // convert the uint64 into a pointer
}
return nil
}