Создайте любое количество объектов из массива байтов. Пакет Dhcp C#

#c# #parsing #byte #dhcp #payload

#c# #синтаксический анализ #байт #dhcp #полезная нагрузка

Вопрос:

В настоящее время я работаю над общедоступной библиотекой, которая позволит вам создать пакет dhcp со всеми видами опций, такими как параметры dhcp. При его создании создается массив байтов, который вы можете отправить в качестве полезной нагрузки через UdpSocket. Для этого я создал два класса: 1. dhcppacket, 2. dhcpoption. До сих пор создание пакета Dhcp с любыми DhcpOptions уже работает.

Теперь я хочу проанализировать входящие пакеты DhcpPackets, которые передаются в виде массива байтов, обратно в объект DhcpPacket, чтобы иметь возможность считывать важную информацию, такую как тип сообщения, или из переданных параметров DhcpOptions, таких как маска подсети. Фиксированную часть (начало) пакета DhcpPacket я уже согласовал. Но теперь я терплю неудачу с DhcpOptions, потому что они являются переменными. Как создать X объектов из массива байтов.

Задан байтовый массив с не заданной длиной

 dhcpOptions = pPayload.Skip(240).ToArray();
 

Из этой полезной нагрузки я теперь хочу создать объекты класса «DhcpOption». Каждая опция Dhcp начинается с уникального байта, например, 0x01 = DhcpOption, содержащего маску подсети. Затем следует байт, который указывает длину DhcpOption, включая следующие значения. Если, например, DNS-сервер передается через опцию Dhcp, длина равна 0x04, поскольку адрес IPv4 передается как значение. Таким образом, общая длина опции Dhcp в полезной нагрузке составляет 6 байт. Но поскольку все параметры не имеют одинаковой длины, я не знаю, как именно я доберусь до начала следующего параметра DHCP.

Пример создания опции dhcp из ByteArray:

 DhcpOption option = new DhcpOption{
    optionId = byteArray[0],
    optionLength = byteArray[1],
    optionValue = byteArray.Skip(2).Take(optionLength).ToArray(),
};
 

Ищутся X-объекты класса:

 public class DhcpOption
    {
        /// <summary>
        /// Define the DHCP options to be created by name
        /// </summary>
        public dhcpOptionIds optionId { get; set; } = new dhcpOptionIds();
        private byte[] optionIdBytes = new byte[] { };

        /// <summary>
        /// Define the required length for the optionValue
        /// </summary>
        public byte[] optionLength { get; set; } = new byte[] { };

        /// <summary>
        /// Define the value for the option e.g. subnet mask
        /// </summary>
        public byte[] optionValue { get; set; } = new byte[] { };

        /// <summary>
        /// Create the DHCP option as byte array. Is then specified as an option in the DhcpPacket.
        /// </summary>
        /// <returns></returns>
        public byte[] buildDhcpOption()
        {
            object selected = Convert.ChangeType(optionId, optionId.GetTypeCode());
            optionIdBytes = new byte[] { Convert.ToByte(selected, null) };

            return optionIdBytes.Concat(optionLength).Concat(optionValue).ToArray();
        }
    }
 

Вместо чистого массива байтов я хотел бы получить список параметров dhcp. So List<DhcpOption> можно использовать для поиска желаемой Dhcp-опции с помощью for или foreach, а затем считывать значение.

Вот репозиторий GitHub, поэтому мне не нужно копировать код.

https://github.com/Marschall-dev/DhcpDotNet/blob/main/DhcpDotNet/DhcpDotNet/DhcpPacket.cs

Комментарии:

1. Управляемый код C # не разрешает доступ ко всем битам. Либо напишите cpp-проект, либо используйте dhcpsapi.dll . См. pinvoke.net/default.aspx/dhcpsapi . DhcpGetClientInfo

2. Я использую PacketDotNet для получения полной полезной нагрузки Dhcp

3. Я посмотрел на dll и не уверен, что она действительно работает. Я не думаю, что вы можете напрямую из c # получить байты в пакете. Получаете ли вы байты с ненулевыми значениями с помощью кода?

4. @jdweng да, он возвращает полную полезную нагрузку с уровня udp. Поэтому, если есть полезная нагрузка Udp, она возвращает нулевые значения. С помощью Pcap. Net вы можете сделать так: Дейтаграмма дейтаграмма = udpDatagram. Полезная нагрузка; Источник: репозиторий GitHub

5. Новая ссылка показывает библиотеку c , оригинал не включал эту библиотеку.

Ответ №1:

Если у вас есть фиксированный протокол, которому вам нужно следовать, типичный подход, который я использую, — это BinaryReader / BinaryWriter .

Создайте поток памяти из массива байтов и передайте его в программу чтения двоичных файлов. Если у вас есть список из нескольких разных опций, данные для каждой опции должны иметь префикс типа опции и, при необходимости, длины. Таким образом, вы можете сначала прочитать тип параметра, а затем иметь переключатель, который обрабатывает каждый конкретный тип параметра. Повторяйте это до тех пор, пока не будут прочитаны все параметры.

Сериализация и десериализация обычно должны быть обратными друг другу, поэтому вы можете использовать BinaryWriter для сериализации. Модульные тесты очень полезны для обеспечения возможности сериализации и десериализации сообщений без какого-либо сетевого подключения. Если вам не нужно следовать существующему протоколу, я бы порекомендовал библиотеку сериализации, например protobuf.net .