/// <summary> /// Returns the offset of the specified DHCP option in the Packet. /// </summary> /// <param name="packet">The DHCP Packet</param> /// <param name="option">The DHCP Option</param> /// <returns>This function returns 0 if the DHCP option is not in the packet.</returns> public static int GetOptionOffset(ref DHCPPacket packet, Definitions.DHCPOptionEnum option) { for (var i = 0; i < packet.Data.Length; i++) if (packet.Data[i] == Convert.ToInt32(option)) return i; return 0; }
internal void Send(ref DHCPPacket packet, IPEndPoint endpoint) { switch (packet.Type) { case SocketType.DHCP: this.DHCPsocket.Send(endpoint, packet.Data, packet.Offset); break; case SocketType.BINL: this.BINLsocket.Send(endpoint, packet.Data, packet.Offset); break; default: break; } }
internal override void DataReceived(object sender, DataReceivedEventArgs e) { switch (int.Parse(Exts.GetDataAsString(e.Data, 0, 1))) { case (int)BootMessageType.Request: #region "BOTP - Request" using (var request = new DHCPPacket(e.Data)) { request.Type = e.Type; var optvalue = Exts.GetOptionValue(e.Data, DHCPOptionEnum.Vendorclassidentifier); if (optvalue.Length < 1 || optvalue[0] == byte.MaxValue || e.Data[0] != (byte)BootMessageType.Request) return; var cguid = Exts.GetOptionValue(request.Data, DHCPOptionEnum.GUID); if (cguid.Length == 1) return; var guid = Guid.Parse(Exts.GetGuidAsString(cguid, cguid.Length, true)); var clientMAC = Exts.GetDataAsString(request.MacAddress, 0, request.MACAddresslength); var clientTag = "{0}-{1}".F(guid, clientMAC); if (!Clients.ContainsKey(clientTag)) Clients.Add(clientTag, new DHCPClient(guid, clientMAC, request.Type, e.RemoteEndpoint)); else { Clients[clientTag].Type = request.Type; Clients[clientTag].EndPoint = e.RemoteEndpoint; } var c = Clients[clientTag]; switch (request.MessageType) { case DHCPMsgType.Request: if (e.RemoteEndpoint.Address != IPAddress.None) this.Handle_DHCP_Request(request, ref c); break; case DHCPMsgType.Discover: this.Handle_DHCP_Request(request, ref c); break; case DHCPMsgType.Release: if (Clients.ContainsKey(clientTag)) Clients.Remove(clientTag); break; default: return; } } #endregion break; case (int)BootMessageType.RISRequest: #region "RIS - Request" var packet = new RISPacket(e.Data); var client = new RISClient(e.RemoteEndpoint); switch (packet.RequestType) { case "RQU": case "REQ": packet.OPCode = packet.RequestType == "REQ" ? RISOPCodes.REQ : RISOPCodes.RQU; this.Handle_RIS_Request(packet, ref client, packet.RequestType == "REQ" ? true : false); break; case "NEG": case "AUT": packet.OPCode = packet.RequestType == "NEG" ? RISOPCodes.NEG : RISOPCodes.AUT; this.Handle_RIS_Request(packet, ref client); break; case "NCQ": packet.OPCode = RISOPCodes.NCQ; this.Handle_RIS_Request(packet, ref client); break; default: Errorhandler.Report(LogTypes.Info, "Got Unknown RIS Packet ({0})".F(packet.RequestType)); break; } #endregion break; case (int)BootMessageType.RISReply: default: break; } }
public void Handle_DHCP_Request(DHCPPacket packet, ref DHCPClient client) { var parameterlist_offset = Functions.GetOptionOffset(ref packet, DHCPOptionEnum.ParameterRequestList); var parameterlistLength = packet.Data[(parameterlist_offset + 1)]; var bootitem = (short)0; var pktlength = (ushort)1024; if (parameterlist_offset != 0) Array.Clear(packet.Data, parameterlist_offset, parameterlistLength); var vendoroffset = Functions.GetOptionOffset(ref packet, DHCPOptionEnum.Vendorclassidentifier); if (vendoroffset == 0) return; var vendor_str = Encoding.ASCII.GetString(packet.Data, vendoroffset + 2, packet.Data[vendoroffset + 1]); if (vendor_str.Contains("PXEClient")) { client.VendorIdent = "PXEClient"; // Option contains additional Informations! if (vendor_str.Contains(":")) { var vendor_parts = vendor_str.Split(':'); if (vendor_parts.Length > 1) { client.PXEFramework = PXEFrameworks.UNDI; if (vendor_parts[1] == "ARCH") client.Arch = (Architecture)short.Parse(vendor_parts[2]); if (vendor_parts[3] == "UNDI") { client.UNDI_Major = short.Parse(vendor_parts[4].Substring(0, 3).Replace("00", string.Empty)); client.UNDI_Minor = short.Parse(vendor_parts[4].Substring(3, 3).Replace("00", string.Empty)); } } } } else return; var response = new DHCPPacket(new byte[pktlength]); Array.Copy(packet.Data, 0, response.Data, 0, 242); response.BootpType = BootMessageType.Reply; response.ServerName = Settings.ServerName; response.NextServer = Settings.ServerIP; response.Type = client.Type; response.Offset += 243; if (Functions.GetOptionOffset(ref packet, DHCPOptionEnum.WDSNBP) != 0) client.IsWDSClient = true; else client.IsWDSClient = false; switch (packet.Type) { case SocketType.DHCP: client.MsgType = DHCPMsgType.Offer; break; case SocketType.BINL: client.MsgType = DHCPMsgType.Ack; break; default: Clients.Remove(client.ID); return; } // Option 53 response.MessageType = client.MsgType; // Option 60 var opt = Exts.SetDHCPOption(DHCPOptionEnum.Vendorclassidentifier, Exts.StringToByte(client.VendorIdent)); Array.Copy(opt, 0, response.Data, response.Offset, opt.Length); response.Offset += opt.Length; // Option 54 var dhcpident = Exts.SetDHCPOption(DHCPOptionEnum.ServerIdentifier, Settings.ServerIP.GetAddressBytes()); Array.Copy(dhcpident, 0, response.Data, response.Offset, dhcpident.Length); response.Offset += dhcpident.Length; // Option 97 var guidopt = Exts.SetDHCPOption(DHCPOptionEnum.GUID, Exts.GetOptionValue(packet.Data, DHCPOptionEnum.GUID)); Array.Copy(guidopt, 0, response.Data, response.Offset, guidopt.Length); response.Offset += guidopt.Length; // Bootfile response.Bootfile = client.BootFile; Functions.SelectBootFile(ref client, client.IsWDSClient, client.NextAction); // Option 53 response.MessageType = client.MsgType; if (Settings.Servermode == ServerMode.AllowAll) client.ActionDone = true; // Option 94 var cii = new byte[3]; cii[0] = Convert.ToByte(client.PXEFramework); cii[1] = Convert.ToByte(client.UNDI_Major); cii[2] = Convert.ToByte(client.UNDI_Minor); var clientIFIdent = Exts.SetDHCPOption(DHCPOptionEnum.ClientInterfaceIdent, cii); Array.Copy(clientIFIdent, 0, response.Data, response.Offset, clientIFIdent.Length); response.Offset += clientIFIdent.Length; if (Settings.DHCP_DEFAULT_BOOTFILE.ToLowerInvariant().Contains("pxelinux")) { var magicstring = Exts.SetDHCPOption(DHCPOptionEnum.MAGICOption, BitConverter.GetBytes(0xf100747e)); Array.Copy(magicstring, 0, response.Data, response.Offset, magicstring.Length); response.Offset += magicstring.Length; } // Option 252 - BCDStore if (client.BCDPath != null && client.ActionDone && client.IsWDSClient) { var bcdstore = Exts.SetDHCPOption(DHCPOptionEnum.BCDPath, Exts.StringToByte(client.BCDPath)); Array.Copy(bcdstore, 0, response.Data, response.Offset, bcdstore.Length); response.Offset += bcdstore.Length; } if (Settings.AdvertPXEServerList && Servers.Count > 0 && client.UNDI_Major > 1) { var optionoffset = Functions.GetOptionOffset(ref packet, DHCPOptionEnum.VendorSpecificInformation); if (optionoffset != 0) { var data = new byte[packet.Data[optionoffset + 1]]; Array.Copy(packet.Data, optionoffset + 2, data, 0, packet.Data[optionoffset + 1]); switch (data[0]) { case (byte)Definitions.PXEVendorEncOptions.BootItem: bootitem = BitConverter.ToInt16(data, 2); break; default: break; } } // Option 43:8 var pxeservers = Functions.GenerateServerList(ref Servers, bootitem); if (pxeservers != null) { var vendoropt = Exts.SetDHCPOption(DHCPOptionEnum.VendorSpecificInformation, pxeservers, true); Array.Copy(vendoropt, 0, response.Data, response.Offset, vendoropt.Length); response.Offset += vendoropt.Length; response.Data[response.Offset] = Convert.ToByte(DHCPOptionEnum.End); response.Offset += 1; } if (bootitem != 254 && bootitem != 0) { var server = (from s in Servers where s.Value.Ident == bootitem select s.Value.Hostname).FirstOrDefault(); if (Clients.ContainsKey(client.ID)) Clients.Remove(client.ID); response.NextServer = Servers[server].IPAddress; response.Bootfile = Servers[server].Bootfile; response.ServerName = Servers[server].Hostname; } } // Windows Deployment Server (WDSNBP Options) var wdsnbp = Exts.SetDHCPOption(DHCPOptionEnum.WDSNBP, this.Handle_WDS_Options(client.AdminMessage, ref client)); Array.Copy(wdsnbp, 0, response.Data, response.Offset, wdsnbp.Length); response.Offset += wdsnbp.Length; // End of Packet (255) var endopt = new byte[1]; endopt[0] = Convert.ToByte(DHCPOptionEnum.End); Array.Copy(endopt, 0, response.Data, response.Offset, endopt.Length); response.Offset += endopt.Length; switch (packet.Type) { case SocketType.DHCP: this.Send(ref response, client.EndPoint); break; case SocketType.BINL: if (client.IsWDSClient) if (client.ActionDone) { this.Send(ref response, client.EndPoint); Clients.Remove(client.ID); client = null; requestid += 1; } else break; else this.Send(ref response, client.EndPoint); break; default: break; } }