// returns offset of varbind list public UInt32 Deserialize(Byte[] packet, UInt32 offset) { this.packetBytes = packet; UInt32 initialOffset = offset; // // SNMP Message Type // if (packet[offset] != Asn1.TYPE_SEQUENCE) { throw new FormatException(String.Format( "Expected snmp packet to be of type Sequence but is {0}", Asn1.GetTypeOrNumberString(packet[offset]))); } offset++; UInt32 sequenceLength = Asn1.ParseDefiniteLength(packet, ref offset); UInt32 sequenceOffsetLimit = offset + sequenceLength; if (packet.Length - offset < sequenceLength) { throw new FormatException(String.Format( "Failed to parse snmp packet because it was truncated from {0} bytes to {1}", sequenceLength + (offset - initialOffset), packet.Length - initialOffset)); } // // Version // if (packet[offset] != Asn1.TYPE_INTEGER) { throw new FormatException(String.Format( "Expected snmp version to be of type Integer but is {0}", Asn1.GetTypeOrNumberString(packet[offset]))); } offset++; this.version = Asn1.ParseIntegerToByte(packet, ref offset); if (this.version != 0) { throw new NotImplementedException(String.Format("Snmp version {0} (binary code {1}) is not implemented yet", this.version + 1, this.version)); } // // Community // if (packet[offset] != Asn1.TYPE_OCTET_STRING) { throw new FormatException(String.Format( "Expected snmp community to be of type OctetString but is '{0}'", Asn1.GetTypeOrNumberString(packet[offset]))); } offset++; Int32 communityLength = (Byte)Asn1.ParseDefiniteLength(packet, ref offset); if (communityLength < 0) { throw new FormatException(String.Format("Expected community octet string length to be positive but is {0}", communityLength)); } offset += (UInt32)communityLength; // // PDU Type // Byte pduTypeByte = packet[offset]; offset++; if (pduTypeByte < 0xA0) { throw new FormatException(String.Format("Expected SNMP pdu type to be >= 0xA0 but is {0:2X}", pduTypeByte)); } // // Use similar logic to parse similar types // Get, GetNext, GetResponse, Set if (pduTypeByte <= 0xA3) { SnmpPduType pduType = (SnmpPduType)(pduTypeByte - 0xA0); UInt32 pduLength = Asn1.ParseDefiniteLength(packet, ref offset); if (offset + pduLength != sequenceOffsetLimit) { throw new FormatException(String.Format( "Snmp packet is malformed, the pdu which ends at {0} does not end at the same place as the sequence at {1}", offset + pduLength, sequenceOffsetLimit)); } // // Request ID // if (packet[offset] != Asn1.TYPE_INTEGER) { throw new FormatException(String.Format( "Expected Snmp{0}Pdu to start with the Integer type but started with '{1}'", pduType, Asn1.GetTypeOrNumberString(packet[offset]))); } offset++; this.requestID = Asn1.ParseIntegerToInt32(packet, ref offset); // // Error Status // if (packet[offset] != Asn1.TYPE_INTEGER) { throw new FormatException(String.Format( "Expected Snmp{0}Pdu ErrorStatus to be an Integer type but is '{1}'", pduType, Asn1.GetTypeOrNumberString(packet[offset]))); } offset++; this.errorStatus = (SnmpErrorStatus)Asn1.ParseIntegerToInt32(packet, ref offset); // // Error Index // if (packet[offset] != Asn1.TYPE_INTEGER) { throw new FormatException(String.Format( "Expected Snmp{0}Pdu ErrorIndex to be an Integer type but is '{1}'", pduType, Asn1.GetTypeOrNumberString(packet[offset]))); } offset++; this.errorIndex = Asn1.ParseIntegerToInt32(packet, ref offset); // // Varbind List // if (packet[offset] != Asn1.TYPE_SEQUENCE) { throw new FormatException(String.Format( "Expected varbind list to be of type Sequence but is {0}", Asn1.GetTypeOrNumberString(packet[offset]))); } offset++; UInt32 varbindListLength = Asn1.ParseDefiniteLength(packet, ref offset); if (offset + varbindListLength != sequenceOffsetLimit) { throw new FormatException(String.Format( "Snmp packet is malformed, the varbind list which ends at {0} does not end at the same place as the sequence at {1}", offset + varbindListLength, sequenceOffsetLimit)); } return(offset); // return the offset to the varbind variables } else { throw new NotImplementedException(String.Format("Snmp pdu type {0} is not implemented yet", pduTypeByte)); } }
public static Int32 ParsePduInt32(Byte[] packet, UInt32 offset, UInt32 length) { UInt32 initialOffset = offset; // // Varbind // if (packet[offset] != Asn1.TYPE_SEQUENCE) { throw new FormatException(String.Format( "Expected varbind to be of type Sequence but is {0}", Asn1.GetTypeOrNumberString(packet[offset]))); } offset++; UInt32 varbindLength = Asn1.ParseDefiniteLength(packet, ref offset); if (packet.Length - offset < varbindLength) { throw new FormatException(String.Format( "Failed to parse snmp packet because it was truncated from {0} bytes to {1}", varbindLength + (offset - initialOffset), packet.Length - initialOffset)); } // // Skip the bound variable // offset++; // Skip the type UInt32 boundVariableLength = Asn1.ParseDefiniteLength(packet, ref offset); offset += boundVariableLength; // // Parse the integer // if (packet[offset] != Asn1.TYPE_INTEGER) { throw new FormatException(String.Format( "Expected value to be of type Integer but is {0}", Asn1.GetTypeOrNumberString(packet[offset]))); } offset++; return(Asn1.ParseIntegerToInt32(packet, ref offset)); }