Beispiel #1
0
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)
	}
}
Beispiel #2
0
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)
}
Beispiel #3
0
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
}
Beispiel #4
0
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)
}
Beispiel #5
0
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)
}