private const ushort DELAY = 0x1388; // 5 s public void Run(IPAddress iPAddress, string dns, string subnetMask, string serverIdentifier, string routerIP) { UpdateStatus($"IP address:\t{iPAddress}"); UpdateStatus($"DNS:\t{dns}"); UpdateStatus($"SUBMASK:\t{subnetMask}"); UpdateStatus($"SERVER IDENTIFIER:\t{serverIdentifier}"); UpdateStatus($"ROUTER IP:\t{routerIP}"); var server = new Dhcp(iPAddress); UpdateStatus("SETTATO L'IP DEL SERVER"); server.ServerName = dns; UpdateStatus("SETTATO IL DNS DEL SERVER"); server.BroadcastAddress = IPAddress.Broadcast.ToString(); UpdateStatus("SETTATO IN BROADCAST IL SERVER"); server.OnDataReceived += (sender, dhcpRequest) => { UpdateStatus("GENERATO NUOVO EVENTO NEL SERVER"); try { var type = dhcpRequest.GetMsgType(); UpdateStatus($"TIPO DI RICHIESTA RICEVUTA DAL SERVER:\t{type}"); var ip = iPAddress; var replyOptions = new DhcpReplyOptions(); UpdateStatus("SETTAGGIO DELLA RISPOSTA DAL SERVER IN CORSO..."); replyOptions.SubnetMask = IPAddress.Parse(subnetMask); UpdateStatus($"SUBNETMASK:\t{replyOptions.SubnetMask}"); replyOptions.DomainName = server.ServerName; UpdateStatus($"DOMAIN NAME:\t{replyOptions.DomainName}"); replyOptions.ServerIdentifier = IPAddress.Parse(serverIdentifier); UpdateStatus($"SERVER IDENTIFIER:\t{replyOptions.ServerIdentifier}"); replyOptions.RouterIP = IPAddress.Parse(routerIP); UpdateStatus($"IP ROUTER:\t{replyOptions.RouterIP}"); replyOptions.DomainNameServers = new IPAddress[] { IPAddress.Parse("8.8.8.8"), IPAddress.Parse("8.8.4.4") }; UpdateStatus("CONFIGURAZIONE DEL DOMINIO DEL SERVER"); if (type == DhcpMsgType.DHCPDISCOVER) { UpdateStatus($"RISPOSTA\t->\tTIPO MESSAGGIO:{DhcpMsgType.DHCPOFFER}"); UpdateStatus($"RISPOSTA\t->\tIP:{ip}"); dhcpRequest.SendDHCPReply(DhcpMsgType.DHCPOFFER, ip, replyOptions); } if (type == DhcpMsgType.DHCPREQUEST) { UpdateStatus($"RISPOSTA\t->\tTIPO MESSAGGIO:{DhcpMsgType.DHCPACK}"); UpdateStatus($"RISPOSTA\t->\tIP:{ip}"); dhcpRequest.SendDHCPReply(DhcpMsgType.DHCPACK, ip, replyOptions); } } catch (Exception e) { UpdateStatus($"EXCEPTION IN SERVER:\t{e.Message}"); } }; UpdateStatus("ESECUZIONE DEL SERVER DHCP IN CORSO..."); server.Start(); }
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="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> /// <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> internal void SendDHCPReply(DhcpMsgType msgType, IPAddress ip, DhcpReplyOptions replyData) { SendDHCPReply(msgType, ip, replyData, null, null); }