func (self *internal_pinger) serve() { defer self.wait.Done() reply := make([]byte, 2048) var buffer C.asn_buf_t var pdu C.snmp_pdu_t for 1 == atomic.LoadInt32(&self.is_running) { l, ra, err := self.conn.ReadFrom(reply) if err != nil { if strings.Contains(err.Error(), "No service is operating") { //Port Unreachable continue } if strings.Contains(err.Error(), "forcibly closed by the remote host") { //Port Unreachable continue } self.ch <- &PingResult{Error: fmt.Errorf("ReadFrom failed: %v, %v", ra, err)} continue } C.set_asn_u_ptr(&buffer.asn_u, (*C.char)(unsafe.Pointer(&reply[0]))) buffer.asn_len = C.size_t(l) err = DecodePDUHeader(&buffer, &pdu) if nil != err { self.ch <- &PingResult{Error: fmt.Errorf("Parse Data failed: %s %v", ra.String(), err)} continue } ver := SNMP_Verr id := 0 //community := "" switch pdu.version { case uint32(SNMP_V3): ver = SNMP_V3 id = int(pdu.identifier) case uint32(SNMP_V2C): ver = SNMP_V2C err = DecodePDUBody(&buffer, &pdu) if nil == err { id = int(pdu.request_id) } //community = C.GoString(pdu.community) case uint32(SNMP_V1): ver = SNMP_V1 err = DecodePDUBody(&buffer, &pdu) if nil == err { id = int(pdu.request_id) } //community = C.GoString(pdu.community) } // if 0 == len(community) { // community = self.community // } self.ch <- &PingResult{Id: id, Addr: ra, Version: ver, Community: self.community, SecurityParams: self.securityParams, Timestamp: time.Now()} C.snmp_pdu_free(&pdu) } }
func encodeNativePdu(bs []byte, pdu *C.snmp_pdu_t) ([]byte, SnmpError) { if pdu.engine.max_msg_size == 0 { pdu.engine.max_msg_size = C.int32_t(*maxPDUSize) } var buffer C.asn_buf_t C.set_asn_u_ptr(&buffer.asn_u, (*C.char)(unsafe.Pointer(&bs[0]))) buffer.asn_len = C.size_t(len(bs)) ret_code := C.snmp_pdu_encode(pdu, &buffer) if 0 != ret_code { err := Error(SnmpResult(ret_code), C.GoString(C.snmp_pdu_get_error(pdu, ret_code))) return nil, err } length := C.get_buffer_length(&buffer, (*C.u_char)(unsafe.Pointer(&bs[0]))) return bs[0:length], nil }
func DecodePDU(send_bytes []byte, priv_type PrivType, priv_key []byte, is_dump bool) (PDU, SnmpError) { var buffer C.asn_buf_t var pdu C.snmp_pdu_t C.set_asn_u_ptr(&buffer.asn_u, (*C.char)(unsafe.Pointer(&send_bytes[0]))) buffer.asn_len = C.size_t(len(send_bytes)) err := DecodePDUHeader(&buffer, &pdu) if nil != err { return nil, err } defer C.snmp_pdu_free(&pdu) err = FillUser(&pdu, SNMP_AUTH_NOAUTH, nil, priv_type, priv_key) if nil != err { return nil, err } err = DecodePDUBody(&buffer, &pdu) if nil != err { return nil, err } if is_dump { C.snmp_pdu_dump(&pdu) } var ok bool = false if uint32(SNMP_V3) == pdu.version { var v3 V3PDU ok, err = v3.decodePDU(&pdu) if ok { return &v3, err } return nil, err } var v2 V2CPDU ok, err = v2.decodePDU(&pdu) if ok { return &v2, err } return nil, err }
func (client *UdpClient) handleRecv(recv_bytes []byte) { defer func() { if e := recover(); nil != e { var buffer bytes.Buffer buffer.WriteString(fmt.Sprintf("[panic]%v", e)) for i := 1; ; i += 1 { _, file, line, ok := runtime.Caller(i) if !ok { break } buffer.WriteString(fmt.Sprintf(" %s:%d\r\n", file, line)) } client.ERROR.Print(client.logCtx, buffer.String()) } }() var buffer C.asn_buf_t var result PDU var req *clientRequest var ok bool internal := newNativePdu() C.snmp_pdu_init(internal) defer releaseNativePdu(internal) C.set_asn_u_ptr(&buffer.asn_u, (*C.char)(unsafe.Pointer(&recv_bytes[0]))) buffer.asn_len = C.size_t(len(recv_bytes)) err := DecodePDUHeader(&buffer, internal) if nil != err { client.ERROR.Print(client.logCtx, "decode head of pdu failed", err) return } defer C.snmp_pdu_free(internal) if uint32(SNMP_V3) == internal.version { req, ok = client.pendings[int(internal.identifier)] if !ok { client.ERROR.Print(client.logCtx, "request with requestId was ", int(internal.identifier), " or ", int(internal.request_id), " is not exists.") // for i, _ := range client.pendings { // client.ERROR.Print(i) // } return } delete(client.pendings, int(internal.identifier)) v3old, ok := req.request.(*V3PDU) if !ok { err = Error(SNMP_CODE_FAILED, "receive pdu is a v3 pdu.") goto complete } usm, ok := v3old.securityModel.(*USM) if !ok { err = Error(SNMP_CODE_FAILED, "receive pdu is not usm.") goto complete } err = FillUser(internal, usm.auth_proto, usm.localization_auth_key, usm.priv_proto, usm.localization_priv_key) if nil != err { client.ERROR.Print(client.logCtx, "fill user information failed,", err.Error()) goto complete } err, ok = DecodePDUBody2(&buffer, internal) if nil != err { client.ERROR.Print(client.logCtx, "decode body of pdu failed", err.Error()) goto complete } if ok { client.ERROR.Print(client.logCtx, "ignored some error", hex.EncodeToString(recv_bytes)) } if client.DEBUG.IsEnabled() { C.snmp_pdu_dump(internal) } var v3 V3PDU _, err = v3.decodePDU(internal) result = &v3 } else { err, ok = DecodePDUBody2(&buffer, internal) if nil != err { client.ERROR.Print(client.logCtx, "decode body of pdu failed", err.Error()) return } if ok { client.ERROR.Print(client.logCtx, "ignored some error", hex.EncodeToString(recv_bytes)) } req, ok = client.pendings[int(internal.request_id)] if !ok { client.ERROR.Print(client.logCtx, "request with requestId was", int(internal.request_id), "is not exists.") return } delete(client.pendings, int(internal.request_id)) if client.DEBUG.IsEnabled() { C.snmp_pdu_dump(internal) } v2 := &V2CPDU{} _, err = v2.decodePDU(internal) result = v2 } complete: req.reply(result, err) }