def decode_OpenPDU(data, header): flags = header["flags"] temp, data = slicedata(data, 4) timeout = struct.unpack("Bxxx", ntp.poly.polybytes(temp))[0] oid, data = decode_OID(data, header) description = decode_octetstr(data, header)[0] result = OpenPDU(flags["bigEndian"], header["session_id"], header["transaction_id"], header["packet_id"], timeout, oid, description) return result
def decode_octetstr(data, header): flags = header["flags"] header, data = slicedata(data, 4) endianToken = getendian(flags["bigEndian"]) numoctets = struct.unpack(endianToken + "I", ntp.poly.polybytes(header))[0] if len(data) < numoctets: raise ValueError("Octet string shorter than length") pad = numoctets % 4 if pad > 0: # Pad out the data to word boundary pad = 4 - pad return ntp.poly.polystr(data[:numoctets]), data[numoctets + pad:]
def decode_GetBulkPDU(data, header): flags = header["flags"] endianToken = getendian(flags["bigEndian"]) context, data = decode_context(data, header) temp, data = slicedata(data, 4) nonReps, maxReps = struct.unpack(endianToken + "HH", polybytes(temp)) oidranges = decode_searchrange_list(data, header) result = GetBulkPDU(flags["bigEndian"], header["session_id"], header["transaction_id"], header["packet_id"], nonReps, maxReps, oidranges, context) return result
def decode_pduheader(data): # Endianness is controlled from the PDU header lineone, data = slicedata(data, 4) version, pduType, flags = struct.unpack(">BBBx", polybytes(lineone)) # Slice up the flags flagDict = decode_flagbyte(flags) # Chop the remaining parts of the header from the rest of the datastream # then parse them fmt = getendian(flagDict["bigEndian"]) + "IIII" linen, data = slicedata(data, 16) # 4 x 4-byte variables sID, tactionID, pktID, dataLen = struct.unpack(fmt, polybytes(linen)) result = { "version": version, "type": pduType, "flags": flagDict, "session_id": sID, "transaction_id": tactionID, "packet_id": pktID, "length": dataLen } return result
def decode_OID(data, header): flags = header["flags"] # Need to split off the header to get the subid count header, data = slicedata(data, 4) n_subid, prefix, include = struct.unpack("BBBx", polybytes(header)) if prefix != 0: subids = internetPrefix + (prefix, ) else: subids = () totalLen = len(subids) + n_subid if not (0 <= totalLen <= 128): raise ValueError("OID has too many subids") include = bool(include) # could be anything, force bool # Now have the count, need to split the subids from the rest of the packet byteCount = n_subid * 4 data, rest = slicedata(data, byteCount) endianToken = getendian(flags["bigEndian"]) formatString = endianToken + ("I" * n_subid) subids += struct.unpack(formatString, polybytes(data)) result = OID(subids, include) return (result, rest)
def decode_Varbind(data, header): flags = header["flags"] bindheader, data = slicedata(data, 4) endianToken = getendian(flags["bigEndian"]) valType = struct.unpack(endianToken + "Hxx", polybytes(bindheader))[0] name, data = decode_OID(data, header) if valType not in definedValueTypes.keys(): raise ValueError("Value type %s not in defined types" % valType) handlers = definedValueTypes[valType] payload, data = handlers[2](data, header) result = Varbind(valType, name, payload) return result, data
def decode_ResponsePDU(data, header): flags = header["flags"] endianToken = getendian(flags["bigEndian"]) temp, data = slicedata(data, 8) sysUptime, resError, resIndex = struct.unpack(endianToken + "IHH", ntp.poly.polybytes(temp)) if data: varbinds = decode_varbindlist(data, header) else: varbinds = None result = ResponsePDU(flags["bigEndian"], header["session_id"], header["transaction_id"], header["packet_id"], sysUptime, resError, resIndex, varbinds) return result
def decode_packet(data): if len(data) < 20: raise ParseDataLengthError("Data too short for header") header, newData = slicedata(data, 20) header = decode_pduheader(header) if header["length"] > len(newData): return None, False, data # pkt, isFull?, buffer packetSlice, newData = slicedata(newData, header["length"]) if header["version"] != 1: raise ParseVersionError( "Unknown packet version %i" % header["version"], header, packetSlice, newData) pktType = header["type"] if pktType not in definedPDUTypes.keys(): raise ParsePDUTypeError("PDU type %s not in defined types" % pktType, header, packetSlice, newData) decoder = definedPDUTypes[pktType] try: parsedPkt = decoder(packetSlice, header) except Exception: # pragma: no cover err = ParseError("Body parsing error", header, packetSlice, newData) raise err return parsedPkt, True, newData # pkt, isFull?, buffer
def decode_xRegisterPDU(data, header): flags = header["flags"] endianToken = getendian(flags["bigEndian"]) context, data = decode_context(data, header) temp, data = slicedata(data, 4) timeout, priority, rangeSubid = struct.unpack(endianToken + "BBBx", polybytes(temp)) oid, data = decode_OID(data, header) if rangeSubid != 0: temp, data = slicedata(data, 4) upperBound = struct.unpack(endianToken + "I", polybytes(temp))[0] else: upperBound = None if header["type"] == PDU_REGISTER: result = RegisterPDU(flags["bigEndian"], header["session_id"], header["transaction_id"], header["packet_id"], timeout, priority, oid, rangeSubid, upperBound, context) else: result = UnregisterPDU(flags["bigEndian"], header["session_id"], header["transaction_id"], header["packet_id"], priority, oid, rangeSubid, upperBound, context) return result
def decode_integer64(data, header): flags = header["flags"] endianToken = getendian(flags["bigEndian"]) num, data = slicedata(data, 8) num = struct.unpack(endianToken + "Q", ntp.poly.polybytes(num))[0] return (num, data)
def decode_unsigned32(data, header): flags = header["flags"] endianToken = getendian(flags["bigEndian"]) num, data = slicedata(data, 4) num = struct.unpack(endianToken + "I", num)[0] return (num, data)