在构建基本的Windows映像部署解决方案(使用WinPE和C#内置的自定义应用程序)时,我遇到了2台计算机不在同一子网/ IP网段(没有静态IP地址或DHCP服务器和DNS /路由表)的问题。为了解决这个问题,我编写了一个基本但成功的DHCP解决方案,并将其扩展到TFTP,以便在C#中进行远程启动。
此应用程序是使用RFC 1350,4578中的指南实现的,并且在RFC 2347中引用了协商的开始。我已设法编写一个例程,将请求的文件发送到远程应用程序。
我使用Wireshark应用程序检查我的传出消息,发现DHCPOFFER和DHCPACK响应格式错误。这些已得到纠正,但让我遇到TFTP实施的问题。
客户端计算机正在请求提供的引导文件名,但在0字节之前将额外的字节附加到名称,表示文件名字符串的结尾。请参阅以下摘录自我的代码,用于从TFTP读取请求(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)
}
}
其中'datagram'是使用UDP Socket接收的字节数组。
将字符串转换为字节数组以传递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;
}
}
在console.WriteLine()中使用Encoding.ASCII.getString(tmpbytes [])时,我使用'pxeboot.n12?'来表示。 Pre Wireshark和消息传递更正,我能够从TFTP RRQ正确提取引导文件名(在本例中为pxeboot.n12),但是对于BCD文件(位于“Boot \ BCD”)的TFTP请求它将失败。
当我能够正确提取文件名(每个文件,每次)时,是否还有其他任何我应该传回的选项(即选项93,94和97(系统架构,网络ID版本,UUID / GUID)或选项253(在Wireshark中注意到使用另一个DHCP / TFTP解决方案)?
我不得不使用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实现现在都按预期工作。