static void Request(DHCPRequest dhcpRequest) { var type = dhcpRequest.GetMsgType(); var mac = ByteArrayToString(dhcpRequest.GetChaddr()); // IP for client IPAddress ip; if (!leases.TryGetValue(mac, out ip)) { ip = new IPAddress(new byte[] { 10, 0, 0, nextIP++ }); leases[mac] = ip; } Console.WriteLine(type.ToString() + " request from " + mac + ", it will be " + ip.ToString()); var options = dhcpRequest.GetAllOptions(); Console.Write("Options:"); foreach (DHCPOption option in options.Keys) { Console.WriteLine(option.ToString() + ": " + ByteArrayToString(options[option])); } // Lets show some request info var requestedOptions = dhcpRequest.GetRequestedOptionsList(); if (requestedOptions != null) { Console.Write("Requested options:"); foreach (DHCPOption option in requestedOptions) Console.Write(" " + option.ToString()); Console.WriteLine(); } // Option 82 info var relayInfoN = dhcpRequest.GetRelayInfo(); if (relayInfoN != null) { var relayInfo = (RelayInfo)relayInfoN; if (relayInfo.AgentCircuitID != null) Console.WriteLine("Relay agent circuit ID: " + ByteArrayToString(relayInfo.AgentCircuitID)); if (relayInfo.AgentRemoteID != null) Console.WriteLine("Relay agent remote ID: " + ByteArrayToString(relayInfo.AgentRemoteID)); } Console.WriteLine(); var replyOptions = new DHCPReplyOptions(); // Options should be filled with valid data. Only requested options will be sent. replyOptions.SubnetMask = IPAddress.Parse("255.255.255.0"); replyOptions.DomainName = "SharpDHCPServer"; replyOptions.ServerIdentifier = IPAddress.Parse("10.0.0.1"); replyOptions.RouterIP = IPAddress.Parse("10.0.0.1"); replyOptions.DomainNameServers = new IPAddress[] { IPAddress.Parse("192.168.100.2"), IPAddress.Parse("192.168.100.3") }; // Some static routes replyOptions.StaticRoutes = new NetworkRoute[] { new NetworkRoute(IPAddress.Parse("10.0.0.0"), IPAddress.Parse("255.0.0.0"), IPAddress.Parse("10.0.0.1")), new NetworkRoute(IPAddress.Parse("192.168.0.0"), IPAddress.Parse("255.255.0.0"), IPAddress.Parse("10.0.0.1")), new NetworkRoute(IPAddress.Parse("172.16.0.0"), IPAddress.Parse("255.240.0.0"), IPAddress.Parse("10.0.0.1")), new NetworkRoute(IPAddress.Parse("80.252.130.248"), IPAddress.Parse("255.255.255.248"), IPAddress.Parse("10.0.0.1")), new NetworkRoute(IPAddress.Parse("80.252.128.88"), IPAddress.Parse("255.255.255.248"), IPAddress.Parse("10.0.0.1")), }; // Lets send reply to client! if (type == DHCPMsgType.DHCPDISCOVER) dhcpRequest.SendDHCPReply(DHCPMsgType.DHCPOFFER, ip, replyOptions); if (type == DHCPMsgType.DHCPREQUEST) dhcpRequest.SendDHCPReply(DHCPMsgType.DHCPACK, ip, replyOptions); }
/// <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> public void SendDHCPReply(DHCPMsgType msgType, IPAddress ip, DHCPReplyOptions replyData, Dictionary<DHCPOption, byte[]> otherForceOptions) { var replyBuffer = requestData; replyBuffer.op = 2; // Reply replyBuffer.yiaddr = ip.GetAddressBytes(); // Client's IP replyBuffer.options = CreateOptionStruct(msgType, replyData, otherForceOptions); // 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) { IPEndPoint endPoint; 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(IPAddress.Broadcast, PORT_TO_SEND_TO_CLIENT); } else { requestSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, false); endPoint = new IPEndPoint(new IPAddress(replyBuffer.giaddr), PORT_TO_SEND_TO_RELAY); } var DataToSend = BuildDataStructure(replyBuffer); requestSocket.SendTo(DataToSend, endPoint); } }
/// <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> public void SendDHCPReply(DHCPMsgType msgType, IPAddress ip, DHCPReplyOptions replyData) { SendDHCPReply(msgType, ip, replyData, null); }
private byte[] CreateOptionStruct(DHCPMsgType msgType, DHCPReplyOptions replyOptions, Dictionary<DHCPOption, byte[]> otherForceOptions) { 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)) CreateOptionElement(ref resultOptions, DHCPOption.ServerIdentifier, replyOptions.ServerIdentifier.GetAddressBytes()); // Requested options if ((reqList != null) && (replyOptions != null)) foreach (DHCPOption i in reqList) { 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) CreateOptionElement(ref resultOptions, 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); CreateOptionElement(ref resultOptions, DHCPOption.IPAddressLeaseTime, leaseTime); 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); CreateOptionElement(ref resultOptions, DHCPOption.RenewalTimeValue_T1, leaseTime); 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); CreateOptionElement(ref resultOptions, DHCPOption.RebindingTimeValue_T2, leaseTime); } } // Other requested options if (otherForceOptions != null) foreach (var option in otherForceOptions.Keys) { CreateOptionElement(ref resultOptions, option, otherForceOptions[option]); if (option == DHCPOption.RelayInfo) relayInfo = null; } // Option 82? Send it back! if (relayInfo != null) CreateOptionElement(ref resultOptions, DHCPOption.RelayInfo, relayInfo); // Create the end option Array.Resize(ref resultOptions, resultOptions.Length + 1); Array.Copy(new byte[] { 255 }, 0, resultOptions, resultOptions.Length - 1, 1); return resultOptions; }
private byte[] CreateOptionStruct(DHCPMsgType msgType, DHCPReplyOptions replyOptions, Dictionary <DHCPOption, byte[]> otherForceOptions) { 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)) { CreateOptionElement(ref resultOptions, DHCPOption.ServerIdentifier, replyOptions.ServerIdentifier.GetAddressBytes()); } // Requested options if ((reqList != null) && (replyOptions != null)) { foreach (DHCPOption i in reqList) { 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) { CreateOptionElement(ref resultOptions, 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); CreateOptionElement(ref resultOptions, DHCPOption.IPAddressLeaseTime, leaseTime); 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); CreateOptionElement(ref resultOptions, DHCPOption.RenewalTimeValue_T1, leaseTime); 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); CreateOptionElement(ref resultOptions, DHCPOption.RebindingTimeValue_T2, leaseTime); } } // Other requested options if (otherForceOptions != null) { foreach (var option in otherForceOptions.Keys) { CreateOptionElement(ref resultOptions, option, otherForceOptions[option]); if (option == DHCPOption.RelayInfo) { relayInfo = null; } } } // Option 82? Send it back! if (relayInfo != null) { CreateOptionElement(ref resultOptions, DHCPOption.RelayInfo, relayInfo); } // Create the end option Array.Resize(ref resultOptions, resultOptions.Length + 1); Array.Copy(new byte[] { 255 }, 0, resultOptions, resultOptions.Length - 1, 1); return(resultOptions); }