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 (pdu *V2CPDU) encodePDU(bs []byte, is_dump bool) ([]byte, SnmpError) { internal := newNativePdu() C.snmp_pdu_init(internal) defer func() { C.snmp_pdu_free(internal) releaseNativePdu(internal) }() internal.error_status = C.int32_t(pdu.error_status) if SNMP_PDU_GETBULK == pdu.op { if pdu.variableBindings.Len() < pdu.non_repeaters { internal.error_status = C.int32_t(pdu.variableBindings.Len()) } else { internal.error_status = C.int32_t(pdu.non_repeaters) } if pdu.max_repetitions > 0 { internal.error_index = C.int32_t(pdu.max_repetitions) } else { internal.error_index = C.int32_t(1) } } err := strcpy(&internal.community[0], MAX_COMMUNITY_LEN, pdu.community) if nil != err { return nil, newError(SNMP_CODE_FAILED, err, "copy community") } internal.engine.max_msg_size = C.int32_t(pdu.maxMsgSize) internal.request_id = C.int32_t(pdu.requestId) internal.pdu_type = C.u_int(pdu.op) internal.version = uint32(pdu.version) err = encodeBindings(internal, pdu.GetVariableBindings()) if nil != err { return nil, newError(SNMP_CODE_FAILED, err, "encode bindings") } if is_test { debug_init_secparams(internal) } else { C.snmp_pdu_init_secparams(internal) } if is_dump { C.snmp_pdu_dump(internal) } return encodeNativePdu(bs, internal) }
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 (pdu *V3PDU) encodePDU(bs []byte, is_dump bool) ([]byte, SnmpError) { internal := newNativePdu() C.snmp_pdu_init(internal) defer func() { C.snmp_pdu_free(internal) releaseNativePdu(internal) }() internal.request_id = C.int32_t(pdu.requestId) internal.pdu_type = C.u_int(pdu.op) internal.version = uint32(SNMP_V3) internal.error_status = C.int32_t(pdu.error_status) if SNMP_PDU_GETBULK == pdu.op { if pdu.variableBindings.Len() < pdu.non_repeaters { internal.error_status = C.int32_t(pdu.variableBindings.Len()) } else { internal.error_status = C.int32_t(pdu.non_repeaters) } if pdu.max_repetitions > 0 { internal.error_index = C.int32_t(pdu.max_repetitions) } else { internal.error_index = C.int32_t(1) } } if pdu.identifier < 0 { internal.identifier = C.int32_t(pdu.requestId) } else { internal.identifier = C.int32_t(pdu.identifier) } internal.flags = 0 if nil == pdu.contextEngine { internal.context_engine_len = C.uint32_t(0) } else { err := memcpy(&internal.context_engine[0], SNMP_ENGINE_ID_LEN, pdu.contextEngine) if nil != err { return nil, context_engine_failed //newError(SNMP_CODE_FAILED, err, "copy context_engine failed") } internal.context_engine_len = C.uint32_t(len(pdu.contextEngine)) } err := strcpy(&internal.context_name[0], SNMP_CONTEXT_NAME_LEN, pdu.contextName) if nil != err { return nil, context_name_failed //newError(SNMP_CODE_FAILED, err, "copy context_name failed") } if nil != pdu.engine { err = memcpy(&internal.engine.engine_id[0], SNMP_ENGINE_ID_LEN, pdu.engine.engine_id) if nil != err { return nil, engine_id_failed //newError(SNMP_CODE_FAILED, err, "copy engine_id failed") } internal.engine.engine_len = C.uint32_t(len(pdu.engine.engine_id)) internal.engine.engine_boots = C.int32_t(pdu.engine.engine_boots) internal.engine.engine_time = C.int32_t(pdu.engine.engine_time) } if 0 == pdu.maxMsgSize { pdu.maxMsgSize = *maxPDUSize } internal.engine.max_msg_size = C.int32_t(pdu.maxMsgSize) internal.security_model = SNMP_SECMODEL_USM if nil == pdu.securityModel { return nil, security_model_is_nil //newError(SNMP_CODE_FAILED, nil, "security model is nil") } err = pdu.securityModel.Write(&internal.user) if nil != err { return nil, newError(SNMP_CODE_FAILED, err, "fill security model failed") } err = encodeBindings(internal, pdu.GetVariableBindings()) if nil != err { return nil, newError(SNMP_CODE_FAILED, err, "fill encode bindings failed") } if is_test { debug_init_secparams(internal) } else { C.snmp_pdu_init_secparams(internal) } if is_dump { C.snmp_pdu_dump(internal) } return encodeNativePdu(bs, internal) }
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) }