#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 .