gosnmp

Форк
0
/
gosnmp_netsnmp.go 
222 строки · 4.6 Кб
1
// Copyright 2012 The GoSNMP Authors. All rights reserved.  Use of this
2
// source code is governed by a BSD-style license that can be found in the
3
// LICENSE file.
4

5
//go:build netsnmp
6

7
package netsnmp
8

9
/*
10
#cgo LDFLAGS: -lnetsnmp
11
#include <stdint.h>
12
#include <stdlib.h>
13
#include <net-snmp/net-snmp-config.h>
14
#include <net-snmp/output_api.h>
15
#include <net-snmp/config_api.h>
16

17
u_char* getPktStart(u_char* pkt, ulong len, ulong off){
18
	return pkt+len-off;
19
}
20
*/
21
import "C"
22
import (
23
	"errors"
24
	"fmt"
25
	"strconv"
26
	"strings"
27
	"unsafe"
28

29
	"github.com/gosnmp/gosnmp"
30
)
31

32
func isPlayback() bool {
33
	return false
34
}
35

36
type netSnmpValType int
37

38
/*
39
case TYPE_INTEGER:
40

41
	case TYPE_INTEGER32:
42
	    type = 'i';
43
	    break;
44
	case TYPE_GAUGE:
45
	case TYPE_UNSIGNED32:
46
	    type = 'u';
47
	    break;
48
	case TYPE_UINTEGER:
49
	    type = '3';
50
	    break;
51
	case TYPE_COUNTER:
52
	    type = 'c';
53
	    break;
54
	case TYPE_COUNTER64:
55
	    type = 'C';
56
	    break;
57
	case TYPE_TIMETICKS:
58
	    type = 't';
59
	    break;
60
	case TYPE_OCTETSTR:
61
	    type = 's';
62
	    break;
63
	case TYPE_BITSTRING:
64
	    type = 'b';
65
	    break;
66
	case TYPE_IPADDR:
67
	    type = 'a';
68
	    break;
69
	case TYPE_OBJID:
70
	    type = 'o';
71
	    break;
72
*/
73
func berToSnmpValType(in gosnmp.Asn1BER) (C.char, error) {
74
	switch in {
75
	case gosnmp.Gauge32:
76
		return 'u', nil
77
	case gosnmp.Integer:
78
		return 'i', nil
79
	case gosnmp.OctetString:
80
		return 's', nil
81
	case gosnmp.IPAddress:
82
		return 'a', nil
83
	case gosnmp.ObjectIdentifier:
84
		return 'o', nil
85
	case gosnmp.Counter32:
86
		return 'c', nil
87
	case gosnmp.Counter64:
88
		return 'C', nil
89
	case gosnmp.OpaqueFloat:
90
		return 'F', nil
91
	case gosnmp.OpaqueDouble:
92
		return 'D', nil
93
	case gosnmp.TimeTicks:
94
		return 't', nil
95
	case gosnmp.Uinteger32:
96
		return '3', nil
97
	default:
98
		return 0, errors.New("unhandled asn1 ber type" + in.String())
99
	}
100
}
101

102
func verToSnmpVer(in gosnmp.SnmpVersion) (C.int, error) {
103
	switch in {
104
	case gosnmp.Version1:
105
		return C.SNMP_VERSION_1, nil
106
	case gosnmp.Version2c:
107
		return C.SNMP_VERSION_2c, nil
108
	case gosnmp.Version3:
109
		return C.SNMP_VERSION_3, nil
110
	default:
111
		return 0, errors.New("handled snmp version " + in.String())
112
	}
113
}
114

115
func netSnmpPduPkt(fname string, gopdu gosnmp.SnmpPDU, gosess *gosnmp.GoSNMP, reqid uint32, verbose bool) ([]byte, error) {
116

117
	var errout *C.char
118
	var err error
119

120
	oid := oidStringToInts(gopdu.Name)
121

122
	if verbose {
123
		netSnmpEnableLogging()
124
	}
125

126
	//enable reverse encode
127
	C.netsnmp_ds_set_boolean(C.NETSNMP_DS_LIBRARY_ID,
128
		C.NETSNMP_DS_LIB_REVERSE_ENCODE,
129
		C.NETSNMP_DEFAULT_ASNENCODING_DIRECTION)
130

131
	//create session
132
	sess := &C.struct_snmp_session{
133
		version:       C.SNMP_DEFAULT_VERSION,
134
		community:     (*C.uchar)((unsafe.Pointer)(C.CString(gosess.Community))),
135
		community_len: C.size_t(len(gosess.Community)),
136
	}
137
	defer C.free(unsafe.Pointer(sess.community))
138

139
	//create pdu
140
	pdu := C.snmp_pdu_create(C.SNMP_MSG_SET)
141
	defer C.free(unsafe.Pointer(pdu))
142
	tmp, err := verToSnmpVer(gosess.Version)
143
	if err != nil {
144
		return nil, err
145
	}
146
	pdu.version = C.long(tmp)
147
	pdu.reqid = C.long(reqid)
148

149
	tstoid := [1024]C.oid{}
150
	tstoidcnt := C.size_t(0)
151
	for i := range oid {
152
		tstoid[i] = C.oid(oid[i])
153
		tstoidcnt++
154
	}
155
	cval := C.CString(valToString(gopdu))
156
	defer C.free(unsafe.Pointer(cval))
157
	ctype, err := berToSnmpValType(gopdu.Type)
158
	if err != nil {
159
		return nil, err
160
	}
161
	rv := C.snmp_add_var(pdu, (*C.oid)(unsafe.Pointer(&tstoid)), tstoidcnt, ctype, cval)
162
	if rv < 0 {
163
		C.snmp_perror(errout)
164
		err = fmt.Errorf("net-snmp error: snmp_add_var: %s", C.GoString(errout))
165
		return nil, err
166
	}
167

168
	//render packet
169
	sz := 2048
170
	pktout := (*C.uchar)(C.malloc(C.size_t(sz)))
171
	pktoutlen := C.size_t(sz)
172
	var pktoutoffset C.size_t
173

174
	rv = C.snmp_build(&pktout, &pktoutlen, &pktoutoffset, sess, pdu)
175
	if rv < C.int(0) {
176
		C.snmp_error(sess, nil, nil, &errout)
177
		err = fmt.Errorf("net-snmp error: snmp_build: %s", C.GoString(errout))
178
		return nil, err
179
	}
180
	defer C.free(unsafe.Pointer(pktout))
181

182
	return C.GoBytes(unsafe.Pointer(C.getPktStart(pktout, pktoutlen, pktoutoffset)), C.int(pktoutoffset)), nil
183

184
}
185

186
func netSnmpEnableLogging() {
187
	C.snmp_enable_stderrlog()
188
	C.snmp_set_do_debugging(1)
189
	C.snmp_set_dump_packet(1)
190
	tmp := C.CString("")
191
	C.debug_register_tokens(tmp)
192
	C.free(unsafe.Pointer(tmp))
193
}
194

195
func oidStringToInts(in string) []int {
196
	out := make([]int, 0, len(in))
197

198
	for _, oi := range strings.Split(in, ".") {
199
		tmp, err := strconv.Atoi(oi)
200
		if err == nil {
201
			out = append(out, tmp)
202
		}
203
	}
204
	return out
205
}
206

207
func valToString(gopdu gosnmp.SnmpPDU) string {
208
	var val any
209
	switch gopdu.Type {
210
	case gosnmp.OctetString:
211
		b, ok := gopdu.Value.([]byte)
212
		if ok {
213
			val = string(b)
214
		} else {
215
			val = gopdu.Value
216
		}
217
	default:
218
		val = gopdu.Value
219

220
	}
221
	return fmt.Sprintf("%v", val)
222
}
223

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.