Пример #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)
	}
}
Пример #2
0
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
}
Пример #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
}
Пример #4
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)
}