private byte[] CreateOptionStruct(DHCPMsgType msgType, DHCPReplyOptions replyOptions, Dictionary <DHCPOption, byte[]> otherForceOptions, IEnumerable <DHCPOption> forceOptions) { Dictionary <DHCPOption, byte[]> options = new Dictionary <DHCPOption, byte[]>(); byte[] resultOptions = null; // Requested options var reqList = GetRequestedOptionsList(); // Option82? var relayInfo = this.GetOptionData(DHCPOption.RelayInfo); CreateOptionElement(ref resultOptions, DHCPOption.DHCPMessageTYPE, new byte[] { (byte)msgType }); // Server identifier - our IP address if ((replyOptions != null) && (replyOptions.ServerIdentifier != null)) { options[DHCPOption.ServerIdentifier] = replyOptions.ServerIdentifier.GetAddressBytes(); } if (reqList == null && forceOptions != null) { reqList = new DHCPOption[0]; } // Requested options if ((reqList != null) && (replyOptions != null)) { if (forceOptions == null) { forceOptions = new List <DHCPOption>(); } } foreach (DHCPOption i in reqList.Union(forceOptions).Distinct().OrderBy(x => (int)x)) { byte[] optionData = null; // If it's force option - ignore it. We'll send it later. if ((otherForceOptions != null) && (otherForceOptions.TryGetValue(i, out optionData))) { continue; } switch (i) { case DHCPOption.SubnetMask: if (replyOptions.SubnetMask != null) { optionData = replyOptions.SubnetMask.GetAddressBytes(); } break; case DHCPOption.Router: if (replyOptions.RouterIP != null) { optionData = replyOptions.RouterIP.GetAddressBytes(); } break; case DHCPOption.DomainNameServers: if (replyOptions.DomainNameServers != null) { optionData = new byte[] { }; foreach (var dns in replyOptions.DomainNameServers) { var dnsserv = dns.GetAddressBytes(); Array.Resize(ref optionData, optionData.Length + 4); Array.Copy(dnsserv, 0, optionData, optionData.Length - 4, 4); } } break; case DHCPOption.DomainName: if (!string.IsNullOrEmpty(replyOptions.DomainName)) { optionData = System.Text.Encoding.ASCII.GetBytes(replyOptions.DomainName); } break; case DHCPOption.ServerIdentifier: if (replyOptions.ServerIdentifier != null) { optionData = replyOptions.ServerIdentifier.GetAddressBytes(); } break; case DHCPOption.LogServer: if (replyOptions.LogServerIP != null) { optionData = replyOptions.LogServerIP.GetAddressBytes(); } break; case DHCPOption.StaticRoutes: case DHCPOption.StaticRoutesWin: if (replyOptions.StaticRoutes != null) { optionData = new byte[] { }; foreach (var route in replyOptions.StaticRoutes) { var routeData = route.BuildRouteData(); Array.Resize(ref optionData, optionData.Length + routeData.Length); Array.Copy(routeData, 0, optionData, optionData.Length - routeData.Length, routeData.Length); } } break; default: replyOptions.OtherRequestedOptions.TryGetValue(i, out optionData); break; } if (optionData != null) { options[i] = optionData; } } if (GetMsgType() != DHCPMsgType.DHCPINFORM) { // Lease time if (replyOptions != null) { var leaseTime = new byte[4]; leaseTime[3] = (byte)(replyOptions.IPAddressLeaseTime); leaseTime[2] = (byte)(replyOptions.IPAddressLeaseTime >> 8); leaseTime[1] = (byte)(replyOptions.IPAddressLeaseTime >> 16); leaseTime[0] = (byte)(replyOptions.IPAddressLeaseTime >> 24); options[DHCPOption.IPAddressLeaseTime] = leaseTime; if (replyOptions.RenewalTimeValue_T1.HasValue) { leaseTime[3] = (byte)(replyOptions.RenewalTimeValue_T1); leaseTime[2] = (byte)(replyOptions.RenewalTimeValue_T1 >> 8); leaseTime[1] = (byte)(replyOptions.RenewalTimeValue_T1 >> 16); leaseTime[0] = (byte)(replyOptions.RenewalTimeValue_T1 >> 24); options[DHCPOption.RenewalTimeValue_T1] = leaseTime; } if (replyOptions.RebindingTimeValue_T2.HasValue) { leaseTime[3] = (byte)(replyOptions.RebindingTimeValue_T2); leaseTime[2] = (byte)(replyOptions.RebindingTimeValue_T2 >> 8); leaseTime[1] = (byte)(replyOptions.RebindingTimeValue_T2 >> 16); leaseTime[0] = (byte)(replyOptions.RebindingTimeValue_T2 >> 24); options[DHCPOption.RebindingTimeValue_T2] = leaseTime; } } } // Other requested options if (otherForceOptions != null) { foreach (var option in otherForceOptions.Keys) { options[option] = otherForceOptions[option]; if (option == DHCPOption.RelayInfo) { relayInfo = null; } } } // Option 82? Send it back! if (relayInfo != null) { options[DHCPOption.RelayInfo] = relayInfo; } foreach (var option in options.OrderBy(x => (int)x.Key)) { CreateOptionElement(ref resultOptions, option.Key, option.Value); } // Create the end option Array.Resize(ref resultOptions, resultOptions.Length + 1); Array.Copy(new byte[] { 255 }, 0, resultOptions, resultOptions.Length - 1, 1); return(resultOptions); }
/// <summary> /// Sends DHCP reply /// </summary> /// <param name="msgType">Type of DHCP message to send</param> /// <param name="ip">IP for client</param> /// <param name="replyData">Reply options (will be sent if requested)</param> /// <param name="otherForceOptions">Force reply options (will be sent anyway)</param> private async void SendDHCPReply(DHCPMsgType msgType, IPAddress ip, DHCPReplyOptions replyData, Dictionary <DHCPOption, byte[]> otherForceOptions, IEnumerable <DHCPOption> forceOptions) { var replyBuffer = requestData; replyBuffer.op = 2; // Reply replyBuffer.yiaddr = ip.GetAddressBytes(); // Client's IP if (replyData.ServerIpAddress != null) { replyBuffer.siaddr = replyData.ServerIpAddress.GetAddressBytes(); } replyBuffer.options = CreateOptionStruct(msgType, replyData, otherForceOptions, forceOptions); // Options if (!string.IsNullOrEmpty(dhcpServer.ServerName)) { var serverNameBytes = Encoding.ASCII.GetBytes(dhcpServer.ServerName); int len = (serverNameBytes.Length > 63) ? 63 : serverNameBytes.Length; Array.Copy(serverNameBytes, replyBuffer.sname, len); replyBuffer.sname[len] = 0; } //lock (requestSocket) { var DataToSend = BuildDataStructure(replyBuffer); if (DataToSend.Length < 300) { var sendArray = new byte[300]; Array.Copy(DataToSend, 0, sendArray, 0, DataToSend.Length); DataToSend = sendArray; } if ((replyBuffer.giaddr[0] == 0) && (replyBuffer.giaddr[1] == 0) && (replyBuffer.giaddr[2] == 0) && (replyBuffer.giaddr[3] == 0)) { //requestSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true); //endPoint = new IPEndPoint(dhcpServer.BroadcastAddress, PORT_TO_SEND_TO_CLIENT); //var udp = new UdpClient(); //udp.EnableBroadcast = true; //udp.Send(DataToSend, DataToSend.Length, new IPEndPoint(dhcpServer.BroadcastAddress, 68)); //udp.Close(); var datagramsocket = new Windows.Networking.Sockets.DatagramSocket(); using (var stream = await datagramsocket.GetOutputStreamAsync(new Windows.Networking.HostName(dhcpServer.BroadcastAddress), PORT_TO_SEND_TO_CLIENT.ToString())) { using (var datawriter = new Windows.Storage.Streams.DataWriter(stream)) { datawriter.WriteBytes(DataToSend); await datawriter.StoreAsync(); } } } else { //requestSocket .SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, false); //endPoint = new IPEndPoint(new IPAddress(replyBuffer.giaddr), PORT_TO_SEND_TO_RELAY); //requestSocket.SendTo(DataToSend, endPoint); using (var stream = await requestSocket.GetOutputStreamAsync(new Windows.Networking.HostName(new IPAddress(replyBuffer.giaddr).ToString()), PORT_TO_SEND_TO_RELAY.ToString())) { using (var datawriter = new Windows.Storage.Streams.DataWriter(stream)) { datawriter.WriteBytes(DataToSend); await datawriter.StoreAsync(); } } } } }
/// <summary> /// Sends DHCP reply /// </summary> /// <param name="msgType">Type of DHCP message to send</param> /// <param name="ip">IP for client</param> /// <param name="replyData">Reply options (will be sent if requested)</param> /// <param name="otherForceOptions">Force reply options (will be sent anyway)</param> internal void SendDHCPReply(DHCPMsgType msgType, IPAddress ip, DHCPReplyOptions replyData, Dictionary <DHCPOption, byte[]> otherForceOptions) { SendDHCPReply(msgType, ip, replyData, otherForceOptions, null); }
/// <summary> /// Sends DHCP reply /// </summary> /// <param name="msgType">Type of DHCP message to send</param> /// <param name="ip">IP for client</param> /// <param name="replyData">Reply options (will be sent if requested)</param> /// <param name="forceOptions">Force reply options (will be sent anyway)</param> internal void SendDHCPReply(DHCPMsgType msgType, IPAddress ip, DHCPReplyOptions replyData, IEnumerable <DHCPOption> forceOptions) { SendDHCPReply(msgType, ip, replyData, null, forceOptions); }
/// <summary> /// Sends DHCP reply /// </summary> /// <param name="msgType">Type of DHCP message to send</param> /// <param name="ip">IP for client</param> /// <param name="replyData">Reply options (will be sent if requested)</param> internal void SendDHCPReply(DHCPMsgType msgType, IPAddress ip, DHCPReplyOptions replyData) { SendDHCPReply(msgType, ip, replyData, null, null); }