Search code examples
c#snmp

What is the the Correct way of sending DateTime data for SNMPV2 using SNMPSHARPNET?


What is the correct way to send DateTime in UTC to a SNMPV2 event using SNMPSHARPNET ?

We have been using TimeTicks AsnType but have run into issues of data over 29 and half days.

This is the code for reference :

    AsnType newMIBValue = null;
if (!string.IsNullOrEmpty(MIBValueString))
{
    switch (DataType)
    {
        case MIBDataType.DateAndTime:
            //newMIBValue = new TimeTicks(MIBValueString);
            newMIBValue = ConvertDateTimeToOctetString(MIBValueString);
            break;
        case MIBDataType.SnmpAdminString:
            newMIBValue = new OctetString(MIBValueString);
            break;
        case MIBDataType.TimeTicks:
            newMIBValue = new TimeTicks(MIBValueString);
            break;
        case MIBDataType.IPAddress:
            newMIBValue = new IpAddress(MIBValueString);
            break;
        case MIBDataType.Integer:
            newMIBValue = new Integer32(MIBValueString);
            break;
        default:
            break;
    }
}

Solution

  • A colleague of mine helped me put this code. Apparently we have send a byte array of hex values per SNMP specification.

    private OctetString ConvertStringToOctetString(DateTime dateTimeValueInUTCDateAndTime)
        {
            var yearInString = dateTimeValueInUTCDateAndTime.Year.ToString("X");            
            byte[] bytesArray = ConvertToByteArray(string.Format("{0}{1}{2}{3}{4}{5}{6}", 
                yearInString,
                dateTimeValueInUTCDateAndTime.Month.ToString("X").PadLeft(2, '0'),
                dateTimeValueInUTCDateAndTime.Day.ToString("X").PadLeft(2, '0'),
                dateTimeValueInUTCDateAndTime.Hour.ToString("X").PadLeft(2, '0'),
                dateTimeValueInUTCDateAndTime.Minute.ToString("X").PadLeft(2, '0'),
                dateTimeValueInUTCDateAndTime.Second.ToString("X").PadLeft(2, '0'),
                "00"
                ));         
            return new OctetString(bytesArray);
        }
        public byte[] ConvertToByteArray(string value)
        {
            byte[] bytes = null;
            if (String.IsNullOrEmpty(value))
                bytes = null;
            else
            {
                int string_length = value.Length;
                int character_index = (value.StartsWith("0x", StringComparison.Ordinal)) ? 2 : 0; // Does the string define leading HEX indicator '0x'. Adjust starting index accordingly.               
                int number_of_characters = string_length - character_index;
    
                bool add_leading_zero = false;
                if (0 != (number_of_characters % 2))
                {
                    add_leading_zero = true;
    
                    number_of_characters += 1;  // Leading '0' has been striped from the string presentation.
                }
    
                bytes = new byte[number_of_characters / 2]; // Initialize our byte array to hold the converted string.
    
                int write_index = 0;
                if (add_leading_zero)
                {
                    bytes[write_index++] = FromCharacterToByte(value[character_index], character_index);
                    character_index += 1;
                }
    
                for (int read_index = character_index; read_index < value.Length; read_index += 2)
                {
                    byte upper = FromCharacterToByte(value[read_index], read_index, 4);
                    byte lower = FromCharacterToByte(value[read_index + 1], read_index + 1);
    
                    bytes[write_index++] = (byte)(upper | lower);
                }
            }
    
            return bytes;
        }
        private byte FromCharacterToByte(char character, int index, int shift = 0)
        {
            byte value = (byte)character;
            if (((0x40 < value) && (0x47 > value)) || ((0x60 < value) && (0x67 > value)))
            {
                if (0x40 == (0x40 & value))
                {
                    if (0x20 == (0x20 & value))
                        value = (byte)(((value + 0xA) - 0x61) << shift);
                    else
                        value = (byte)(((value + 0xA) - 0x41) << shift);
                }
            }
            else if ((0x29 < value) && (0x40 > value))
                value = (byte)((value - 0x30) << shift);
            else
                throw new InvalidOperationException(String.Format("Character '{0}' at index '{1}' is not valid alphanumeric character.", character, index));
    
            return value;
        }