Строка имени файла в запросе чтения DHCP/BOOTP/TFTP с дополнительными символами

При создании базового решения для развертывания образа Windows (с использованием WinPE и пользовательских приложений, созданных на C#), я столкнулся с проблемой двух компьютеров, не находящихся в одном сегменте подсети/IP (без статического IP-адреса или DHCP-серверов и DNS/таблиц маршрутизации) . Чтобы бороться с этим, я написал простое, но успешное решение DHCP и расширил его до TFTP для удаленной загрузки на C#.

Это приложение было реализовано с использованием указаний в RFC 1350, 4578, а начало согласования упоминается в RFC 2347. Мне удалось написать процедуру, которая отправляет запрошенные файлы удаленному приложению.

Я использовал приложение Wireshark для проверки исходящих сообщений и обнаружил, что ответы DHCPOFFER и DHCPACK были искажены. Они были исправлены, но у меня осталась проблема с реализацией TFTP.

Клиентский компьютер запрашивает предоставленное имя загрузочного файла, но добавляет дополнительные байты к имени перед 0 байтом, обозначающим конец строки имени файла. См. ниже отрывок из моего кода для извлечения имени файла из сообщения TFTP Read Request (RRQ):

switch(datagram[1]) //position of OpCode Indicator
{
        case (byte)TFTP_OpCode.RRQ
        {
            TidPort = new Random();
            var port = TidPort.New(65200, 65350); // Server TX ID & Port
            offset = offset + 1;
            int strlength = 0;
            while (datagram[offset] != (byte)0)
            {
                strlengeth++;
                offset++
            }
            byte[] tmpbytes = new byte[strlength -1];
            Array.Copy(datagram, 2, tmpbytes, 0, strlength -1)
        }
}

Где «датаграмма» — это массив байтов, полученный с использованием сокета UDP.

Код для преобразования строки в массив байтов для передачи в сообщении DHCPOFFER/ACK:

switch (option)
    {
        case BOOTFILE:
            {
            byte[] tmpbytes = new byte[Encoding.ASCII.GetByteCount("pxeboot.n12")];
            tmpbytes = Encoding.ASCII.GetBytes("pxeboot.n12");
            _totalLength = tmpbytes.Length + 2;
            _option = new byte[_totalLength];
            _option[0] = (byte)BOOTFILE;
            _option[1] = (byte)tmpbytes.Length;
            Array.Copy(tmpbytes, 0, _option, 2, tmpbytes.Length);
            Array.Copy(_option, 0, result, optionPosition, _option.Length);
            optionPosition = optionPosition + _totalLength;
            break;
            }
    }

при использовании Encoding.ASCII.getString(tmpbytes[]) в console.WriteLine() мне представляется «pxeboot.n12?». До исправления Wireshark и обмена сообщениями мне удалось правильно извлечь имя загрузочного файла (в данном случае pxeboot.n12) из ​​TFTP RRQ, но при запросе TFTP для файла BCD (находящегося в «Boot\BCD») это не удалось.

Когда я могу правильно извлечь имя файла (каждый файл, каждый раз), есть ли какие-либо другие параметры, которые я должен передать обратно (например, параметры 93, 94 и 97 (архитектура системы, версия идентификатора сети, UUID/GUID) или вариант 253 (замечено в Wireshark при использовании другого решения DHCP/TFTP)?


person R.McInnes-Piper    schedule 21.02.2019    source источник
comment
FTP имеет текстовый и бинарный режим. Убедитесь, что при отправке двоичного файла вы используете двоичный режим. Единственный раз, когда вам нужно использовать текстовый режим, это когда вы передаете данные между системами, которые используют другой символ возврата. В текстовом режиме он автоматически исправит возвращаемый символ для вашей операционной системы.   -  person jdweng    schedule 21.02.2019
comment
Можете ли вы расширить/объяснить немного больше, пожалуйста? Я использую ASCII как для кодирования, так и для байтов и из байтов. Из RFC 1350 имя файла возвращается в NVTASCII (подмножество ASCII?), оканчивающееся нулем (0).   -  person R.McInnes-Piper    schedule 21.02.2019
comment
Первый RFC 1350 использует строку Base 64 (в unix/ultrix используется uuencode и uudecode). В зависимости от языка кодировка ASCII может не работать. Возможно, вам потребуется использовать одну из кодировок Windows, например 1252. Ascii предназначена для символов от 0 до 127. Символы от 127 до 255 могут отображаться по-разному в зависимости от языка, например латинского или русского. Я бы не назвал NVTASCII подмножеством ascii, а скорее типом ascii, поскольку различаются только символы со 127 по 255. Я бы использовал кодировку UTF8 вместо ASCII. Кодировка Ascii удаляет непечатаемые символы.   -  person jdweng    schedule 21.02.2019
comment
@jdweng, я пробовал и UTF-8, и UTF-7 в нескольких комбинациях между ASCII и UTF-8/7. Все равно провал. Если i Encoding.ASCII для всего массива байтов, имя файла представляет собой true без лишних символов.   -  person R.McInnes-Piper    schedule 21.02.2019
comment
Вы не должны использовать какую-либо кодировку для двоичных данных. Вы должны использовать: string Convert.ToBase64String(byte[]). Имя файла вам может понадобиться кодировка.   -  person jdweng    schedule 21.02.2019
comment
@jdweng, извините за поздний ответ - ночная смена может быть неприятной. Я попытался использовать Convert.ToBase64String() - он не вернул ничего полезного. Я использовал метод ниже, чтобы удалить нежелательный символ.   -  person R.McInnes-Piper    schedule 01.03.2019
comment
Я должен сказать, что FTP автоматически конвертирует. Вам не нужно раздевать персонажей. Если у вас есть двоичные данные, это повредит данные, внося такие изменения. Вы должны иметь возможность указать режим BINARY, чтобы вам не нужно было изменять данные.   -  person jdweng    schedule 01.03.2019


Ответы (1)


Мне пришлось использовать метод string.SubString():

string filestring = Encoding.ASCII.GetString(tmpbytes); int pos = filestring.IndexOf("?"); filestring = filstring.SubString(0, pos-1);

чтобы удалить нежелательный символ из массива tmpbytes.

Параметры 93, 94 и 97 теперь передаются обратно в запрошенных параметрах поста сообщения DHCPOFFER. Реализации DHCP и TFTP теперь работают должным образом.

person R.McInnes-Piper    schedule 01.03.2019