├── .gitignore ├── README.md ├── SharpDHCPServer.sln ├── SharpDHCPServerLib ├── DHCPMsgType.cs ├── DHCPOption.cs ├── DHCPReplyOptions.cs ├── DHCPRequest.cs ├── DHCPServer.cs ├── NetworkRoute.cs ├── Properties │ └── .svn │ │ ├── all-wcprops │ │ ├── entries │ │ └── text-base │ │ └── AssemblyInfo.cs.svn-base ├── RelayInfo.cs └── SharpDHCPServerLib.csproj ├── SharpDHCPServer_Sample ├── Program.cs ├── Properties │ └── .svn │ │ ├── all-wcprops │ │ ├── entries │ │ └── text-base │ │ └── AssemblyInfo.cs.svn-base └── SharpDHCPServer_Sample.csproj └── appveyor.yml /.gitignore: -------------------------------------------------------------------------------- 1 | # Build Folders (you can keep bin if you'd like, to store dlls and pdbs) 2 | [Bb]in/ 3 | [Oo]bj/ 4 | 5 | # mstest test results 6 | TestResults 7 | 8 | ## Ignore Visual Studio temporary files, build results, and 9 | ## files generated by popular Visual Studio add-ons. 10 | 11 | # User-specific files 12 | *.suo 13 | *.user 14 | *.sln.docstates 15 | 16 | # Build results 17 | [Dd]ebug/ 18 | [Rr]elease/ 19 | x64/ 20 | *_i.c 21 | *_p.c 22 | *.ilk 23 | *.meta 24 | *.obj 25 | *.pch 26 | *.pdb 27 | *.pgc 28 | *.pgd 29 | *.rsp 30 | *.sbr 31 | *.tlb 32 | *.tli 33 | *.tlh 34 | *.tmp 35 | *.log 36 | *.vspscc 37 | *.vssscc 38 | .builds 39 | 40 | # Visual C++ cache files 41 | ipch/ 42 | *.aps 43 | *.ncb 44 | *.opensdf 45 | *.sdf 46 | 47 | # Visual Studio Code 48 | *.vs/ 49 | 50 | # Visual Studio profiler 51 | *.psess 52 | *.vsp 53 | *.vspx 54 | 55 | # Guidance Automation Toolkit 56 | *.gpState 57 | 58 | # ReSharper is a .NET coding add-in 59 | _ReSharper* 60 | 61 | # NCrunch 62 | *.ncrunch* 63 | .*crunch*.local.xml 64 | 65 | # Installshield output folder 66 | [Ee]xpress 67 | 68 | # DocProject is a documentation generator add-in 69 | DocProject/buildhelp/ 70 | DocProject/Help/*.HxT 71 | DocProject/Help/*.HxC 72 | DocProject/Help/*.hhc 73 | DocProject/Help/*.hhk 74 | DocProject/Help/*.hhp 75 | DocProject/Help/Html2 76 | DocProject/Help/html 77 | 78 | # Click-Once directory 79 | publish 80 | 81 | # Publish Web Output 82 | *.Publish.xml 83 | 84 | # NuGet Packages Directory 85 | packages 86 | 87 | # Windows Azure Build Output 88 | csx 89 | *.build.csdef 90 | 91 | # Windows Store app package directory 92 | AppPackages/ 93 | 94 | # Others 95 | [Bb]in 96 | [Oo]bj 97 | sql 98 | TestResults 99 | [Tt]est[Rr]esult* 100 | *.Cache 101 | ClientBin 102 | [Ss]tyle[Cc]op.* 103 | ~$* 104 | *.dbmdl 105 | Generated_Code #added for RIA/Silverlight projects 106 | 107 | # Backup & report files from converting an old project file to a newer 108 | # Visual Studio version. Backup files are not needed, because we have git ;-) 109 | _UpgradeReport_Files/ 110 | Backup*/ 111 | UpgradeLog*.XML 112 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | A full amanged DHCP Server Library 2 | 3 | Caution ! In C# Sending Broadcast Messaged over a Interface is only possible if gateway is set! 4 | -------------------------------------------------------------------------------- /SharpDHCPServer.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29519.87 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharpDHCPServerLib", "SharpDHCPServerLib\SharpDHCPServerLib.csproj", "{B7FCD134-E2B2-43A9-96C5-3DEDB5669F37}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpDHCPServer_Sample", "SharpDHCPServer_Sample\SharpDHCPServer_Sample.csproj", "{E0A4A539-681E-45E1-84A8-C530BA129856}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Debug|Mixed Platforms = Debug|Mixed Platforms 14 | Debug|x86 = Debug|x86 15 | Release|Any CPU = Release|Any CPU 16 | Release|Mixed Platforms = Release|Mixed Platforms 17 | Release|x86 = Release|x86 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {B7FCD134-E2B2-43A9-96C5-3DEDB5669F37}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {B7FCD134-E2B2-43A9-96C5-3DEDB5669F37}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {B7FCD134-E2B2-43A9-96C5-3DEDB5669F37}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 23 | {B7FCD134-E2B2-43A9-96C5-3DEDB5669F37}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 24 | {B7FCD134-E2B2-43A9-96C5-3DEDB5669F37}.Debug|x86.ActiveCfg = Debug|Any CPU 25 | {B7FCD134-E2B2-43A9-96C5-3DEDB5669F37}.Release|Any CPU.ActiveCfg = Release|Any CPU 26 | {B7FCD134-E2B2-43A9-96C5-3DEDB5669F37}.Release|Any CPU.Build.0 = Release|Any CPU 27 | {B7FCD134-E2B2-43A9-96C5-3DEDB5669F37}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 28 | {B7FCD134-E2B2-43A9-96C5-3DEDB5669F37}.Release|Mixed Platforms.Build.0 = Release|Any CPU 29 | {B7FCD134-E2B2-43A9-96C5-3DEDB5669F37}.Release|x86.ActiveCfg = Release|Any CPU 30 | {E0A4A539-681E-45E1-84A8-C530BA129856}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 31 | {E0A4A539-681E-45E1-84A8-C530BA129856}.Debug|Any CPU.Build.0 = Debug|Any CPU 32 | {E0A4A539-681E-45E1-84A8-C530BA129856}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 33 | {E0A4A539-681E-45E1-84A8-C530BA129856}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 34 | {E0A4A539-681E-45E1-84A8-C530BA129856}.Debug|x86.ActiveCfg = Debug|Any CPU 35 | {E0A4A539-681E-45E1-84A8-C530BA129856}.Debug|x86.Build.0 = Debug|Any CPU 36 | {E0A4A539-681E-45E1-84A8-C530BA129856}.Release|Any CPU.ActiveCfg = Release|Any CPU 37 | {E0A4A539-681E-45E1-84A8-C530BA129856}.Release|Any CPU.Build.0 = Release|Any CPU 38 | {E0A4A539-681E-45E1-84A8-C530BA129856}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 39 | {E0A4A539-681E-45E1-84A8-C530BA129856}.Release|Mixed Platforms.Build.0 = Release|Any CPU 40 | {E0A4A539-681E-45E1-84A8-C530BA129856}.Release|x86.ActiveCfg = Release|Any CPU 41 | {E0A4A539-681E-45E1-84A8-C530BA129856}.Release|x86.Build.0 = Release|Any CPU 42 | EndGlobalSection 43 | GlobalSection(SolutionProperties) = preSolution 44 | HideSolutionNode = FALSE 45 | EndGlobalSection 46 | GlobalSection(ExtensibilityGlobals) = postSolution 47 | SolutionGuid = {C1E1858F-6B92-4A3B-8BB3-4009D4243F67} 48 | EndGlobalSection 49 | GlobalSection(SubversionScc) = preSolution 50 | Svn-Managed = True 51 | Manager = AnkhSVN - Subversion Support for Visual Studio 52 | EndGlobalSection 53 | EndGlobal 54 | -------------------------------------------------------------------------------- /SharpDHCPServerLib/DHCPMsgType.cs: -------------------------------------------------------------------------------- 1 | namespace DotNetProjects.DhcpServer 2 | { 3 | /// DHCP message type 4 | public enum DHCPMsgType 5 | { 6 | /// DHCP DISCOVER message 7 | DHCPDISCOVER = 1, 8 | /// DHCP OFFER message 9 | DHCPOFFER = 2, 10 | /// DHCP REQUEST message 11 | DHCPREQUEST = 3, 12 | /// DHCP DECLINE message 13 | DHCPDECLINE = 4, 14 | /// DHCP ACK message 15 | DHCPACK = 5, 16 | /// DHCP NAK message 17 | DHCPNAK = 6, 18 | /// DHCP RELEASE message 19 | DHCPRELEASE = 7, 20 | /// DHCP INFORM message 21 | DHCPINFORM = 8 22 | } 23 | } -------------------------------------------------------------------------------- /SharpDHCPServerLib/DHCPOption.cs: -------------------------------------------------------------------------------- 1 | namespace DotNetProjects.DhcpServer 2 | { 3 | /// DHCP option enum 4 | public enum DHCPOption 5 | { 6 | /// Option 1 7 | SubnetMask = 1, 8 | /// Option 2 9 | TimeOffset = 2, 10 | /// Option 3 11 | Router = 3, 12 | /// Option 4 13 | TimeServer = 4, 14 | /// Option 5 15 | NameServer = 5, 16 | /// Option 6 17 | DomainNameServers = 6, 18 | /// Option 7 19 | LogServer = 7, 20 | /// Option 8 21 | CookieServer = 8, 22 | /// Option 9 23 | LPRServer = 9, 24 | /// Option 10 25 | ImpressServer = 10, 26 | /// Option 11 27 | ResourceLocServer = 11, 28 | /// Option 12 29 | HostName = 12, 30 | /// Option 13 31 | BootFileSize = 13, 32 | /// Option 14 33 | MeritDump = 14, 34 | /// Option 15 35 | DomainName = 15, 36 | /// Option 16 37 | SwapServer = 16, 38 | /// Option 17 39 | RootPath = 17, 40 | /// Option 18 41 | ExtensionsPath = 18, 42 | /// Option 19 43 | IpForwarding = 19, 44 | /// Option 20 45 | NonLocalSourceRouting = 20, 46 | /// Option 21 47 | PolicyFilter = 21, 48 | /// Option 22 49 | MaximumDatagramReAssemblySize = 22, 50 | /// Option 23 51 | DefaultIPTimeToLive = 23, 52 | /// Option 24 53 | PathMTUAgingTimeout = 24, 54 | /// Option 25 55 | PathMTUPlateauTable = 25, 56 | /// Option 26 57 | InterfaceMTU = 26, 58 | /// Option 27 59 | AllSubnetsAreLocal = 27, 60 | /// Option 28 61 | BroadcastAddress = 28, 62 | /// Option 29 63 | PerformMaskDiscovery = 29, 64 | /// Option 30 65 | MaskSupplier = 30, 66 | /// Option 31 67 | PerformRouterDiscovery = 31, 68 | /// Option 32 69 | RouterSolicitationAddress = 32, 70 | /// Option 33 71 | StaticRoute = 33, 72 | /// Option 34 73 | TrailerEncapsulation = 34, 74 | /// Option 35 75 | ARPCacheTimeout = 35, 76 | /// Option 36 77 | EthernetEncapsulation = 36, 78 | /// Option 37 79 | TCPDefaultTTL = 37, 80 | /// Option 38 81 | TCPKeepaliveInterval = 38, 82 | /// Option 39 83 | TCPKeepaliveGarbage = 39, 84 | /// Option 40 85 | NetworkInformationServiceDomain = 40, 86 | /// Option 41 87 | NetworkInformationServers = 41, 88 | /// Option 42 89 | NetworkTimeProtocolServers = 42, 90 | /// Option 43 91 | VendorSpecificInformation = 43, 92 | /// Option 44 93 | NetBIOSoverTCPIPNameServer = 44, 94 | /// Option 45 95 | NetBIOSoverTCPIPDatagramDistributionServer = 45, 96 | /// Option 46 97 | NetBIOSoverTCPIPNodeType = 46, 98 | /// Option 47 99 | NetBIOSoverTCPIPScope = 47, 100 | /// Option 48 101 | XWindowSystemFontServer = 48, 102 | /// Option 49 103 | XWindowSystemDisplayManager = 49, 104 | /// Option 50 105 | RequestedIPAddress = 50, 106 | /// Option 51 107 | IPAddressLeaseTime = 51, 108 | /// Option 52 109 | OptionOverload = 52, 110 | /// Option 53 111 | DHCPMessageTYPE = 53, 112 | /// Option 54 113 | ServerIdentifier = 54, 114 | /// Option 55 115 | ParameterRequestList = 55, 116 | /// Option 56 117 | Message = 56, 118 | /// Option 57 119 | MaximumDHCPMessageSize = 57, 120 | /// Option 58 121 | RenewalTimeValue_T1 = 58, 122 | /// Option 59 123 | RebindingTimeValue_T2 = 59, 124 | /// Option 60 125 | Vendorclassidentifier = 60, 126 | /// Option 61 127 | ClientIdentifier = 61, 128 | /// Option 62 129 | NetWateIPDomainName = 62, 130 | /// Option 63 131 | NetWateIPInformation = 63, 132 | /// Option 64 133 | NetworkInformationServicePlusDomain = 64, 134 | /// Option 65 135 | NetworkInformationServicePlusServers = 65, 136 | /// Option 66 137 | TFTPServerName = 66, 138 | /// Option 67 139 | BootfileName = 67, 140 | /// Option 68 141 | MobileIPHomeAgent = 68, 142 | /// Option 69 143 | SMTPServer = 69, 144 | /// Option 70 145 | POP3Server = 70, 146 | /// Option 71 147 | NNTPServer = 71, 148 | /// Option 72 149 | DefaultWWWServer = 72, 150 | /// Option 73 151 | DefaultFingerServer = 73, 152 | /// Option 74 153 | DefaultIRCServer = 74, 154 | /// Option 75 155 | StreetTalkServer = 75, 156 | /// Option 76 157 | STDAServer = 76, 158 | /// Option 82 159 | RelayInfo = 82, 160 | /// Option 121 161 | StaticRoutes = 121, 162 | /// Option 249 163 | StaticRoutesWin = 249, 164 | /// Option 252 165 | Wpad = 252, 166 | /// Option 255 (END option) 167 | END_Option = 255 168 | } 169 | } -------------------------------------------------------------------------------- /SharpDHCPServerLib/DHCPReplyOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Net; 4 | 5 | namespace DotNetProjects.DhcpServer 6 | { 7 | /// Reply options 8 | public class DHCPReplyOptions 9 | { 10 | /// IP address 11 | public IPAddress SubnetMask = null; 12 | /// Next Server IP address (bootp) 13 | public IPAddress ServerIpAddress = null; 14 | /// IP address lease time (seconds) 15 | public UInt32 IPAddressLeaseTime = 60 * 60 * 24; 16 | /// Renewal time (seconds) 17 | public UInt32? RenewalTimeValue_T1 = 60 * 60 * 24; 18 | /// Rebinding time (seconds) 19 | public UInt32? RebindingTimeValue_T2 = 60 * 60 * 24; 20 | /// Domain name 21 | public string DomainName = null; 22 | /// IP address of DHCP server 23 | public IPAddress ServerIdentifier = null; 24 | /// Router (gateway) IP 25 | public IPAddress RouterIP = null; 26 | /// Domain name servers (DNS) 27 | public IPAddress[] DomainNameServers = null; 28 | /// Log server IP 29 | public IPAddress LogServerIP = null; 30 | /// Static routes 31 | public NetworkRoute[] StaticRoutes = null; 32 | /// Other options which will be sent on request 33 | public Dictionary OtherRequestedOptions = new Dictionary(); 34 | } 35 | } -------------------------------------------------------------------------------- /SharpDHCPServerLib/DHCPRequest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net; 5 | using System.Net.Sockets; 6 | using System.Text; 7 | 8 | namespace DotNetProjects.DhcpServer 9 | { 10 | /// 11 | /// DHCP request 12 | /// 13 | public class DHCPRequest 14 | { 15 | private readonly DHCPServer dhcpServer; 16 | private readonly DHCPPacket requestData; 17 | private Socket requestSocket; 18 | private const int OPTION_OFFSET = 240; 19 | private const int PORT_TO_SEND_TO_CLIENT = 68; 20 | private const int PORT_TO_SEND_TO_RELAY = 67; 21 | 22 | /// 23 | /// Raw DHCP packet 24 | /// 25 | public struct DHCPPacket 26 | { 27 | /// Op code: 1 = boot request, 2 = boot reply 28 | public byte op; 29 | /// Hardware address type 30 | public byte htype; 31 | /// Hardware address length: length of MACID 32 | public byte hlen; 33 | /// Hardware options 34 | public byte hops; 35 | /// Transaction id 36 | public byte[] xid; 37 | /// Elapsed time from trying to boot 38 | public byte[] secs; 39 | /// Flags 40 | public byte[] flags; 41 | /// Client IP 42 | public byte[] ciaddr; 43 | /// Your client IP 44 | public byte[] yiaddr; 45 | /// Server IP 46 | public byte[] siaddr; 47 | /// Relay agent IP 48 | public byte[] giaddr; 49 | /// Client HW address 50 | public byte[] chaddr; 51 | /// Optional server host name 52 | public byte[] sname; 53 | /// Boot file name 54 | public byte[] file; 55 | /// Magic cookie 56 | public byte[] mcookie; 57 | /// Options (rest) 58 | public byte[] options; 59 | } 60 | 61 | internal DHCPRequest(byte[] data, Socket socket, DHCPServer server) 62 | { 63 | dhcpServer = server; 64 | System.IO.BinaryReader rdr; 65 | System.IO.MemoryStream stm = new System.IO.MemoryStream(data, 0, data.Length); 66 | rdr = new System.IO.BinaryReader(stm); 67 | // Reading data 68 | requestData.op = rdr.ReadByte(); 69 | requestData.htype = rdr.ReadByte(); 70 | requestData.hlen = rdr.ReadByte(); 71 | requestData.hops = rdr.ReadByte(); 72 | requestData.xid = rdr.ReadBytes(4); 73 | requestData.secs = rdr.ReadBytes(2); 74 | requestData.flags = rdr.ReadBytes(2); 75 | requestData.ciaddr = rdr.ReadBytes(4); 76 | requestData.yiaddr = rdr.ReadBytes(4); 77 | requestData.siaddr = rdr.ReadBytes(4); 78 | requestData.giaddr = rdr.ReadBytes(4); 79 | requestData.chaddr = rdr.ReadBytes(16); 80 | requestData.sname = rdr.ReadBytes(64); 81 | requestData.file = rdr.ReadBytes(128); 82 | requestData.mcookie = rdr.ReadBytes(4); 83 | requestData.options = rdr.ReadBytes(data.Length - OPTION_OFFSET); 84 | requestSocket = socket; 85 | } 86 | 87 | /// 88 | /// Returns array of requested by client options 89 | /// 90 | /// Array of requested by client options 91 | public DHCPOption[] GetRequestedOptionsList() 92 | { 93 | var reqList = this.GetOptionData(DHCPOption.ParameterRequestList); 94 | var optList = new List(); 95 | if (reqList != null) foreach (var option in reqList) optList.Add((DHCPOption)option); else return null; 96 | return optList.ToArray(); 97 | } 98 | 99 | private byte[] CreateOptionStruct(DHCPMsgType msgType, DHCPReplyOptions replyOptions, Dictionary otherForceOptions, IEnumerable forceOptions) 100 | { 101 | Dictionary options = new Dictionary(); 102 | 103 | byte[] resultOptions = null; 104 | // Requested options 105 | var reqList = GetRequestedOptionsList(); 106 | // Option82? 107 | var relayInfo = this.GetOptionData(DHCPOption.RelayInfo); 108 | CreateOptionElement(ref resultOptions, DHCPOption.DHCPMessageTYPE, new byte[] { (byte)msgType }); 109 | // Server identifier - our IP address 110 | if ((replyOptions != null) && (replyOptions.ServerIdentifier != null)) 111 | options[DHCPOption.ServerIdentifier] = replyOptions.ServerIdentifier.GetAddressBytes(); 112 | 113 | if (reqList == null && forceOptions != null) 114 | reqList = new DHCPOption[0]; 115 | 116 | if (forceOptions == null) 117 | forceOptions = new DHCPOption[0]; 118 | 119 | // Requested options 120 | if ((reqList != null) && (replyOptions != null)) 121 | foreach (DHCPOption i in reqList.Union(forceOptions).Distinct().OrderBy(x=>(int)x)) 122 | { 123 | byte[] optionData = null; 124 | // If it's force option - ignore it. We'll send it later. 125 | if ((otherForceOptions != null) && (otherForceOptions.TryGetValue(i, out optionData))) 126 | continue; 127 | switch (i) 128 | { 129 | case DHCPOption.SubnetMask: 130 | if (replyOptions.SubnetMask != null) 131 | optionData = replyOptions.SubnetMask.GetAddressBytes(); 132 | break; 133 | case DHCPOption.Router: 134 | if (replyOptions.RouterIP != null) 135 | optionData = replyOptions.RouterIP.GetAddressBytes(); 136 | break; 137 | case DHCPOption.DomainNameServers: 138 | if (replyOptions.DomainNameServers != null) 139 | { 140 | optionData = new byte[] { }; 141 | foreach (var dns in replyOptions.DomainNameServers) 142 | { 143 | var dnsserv = dns.GetAddressBytes(); 144 | Array.Resize(ref optionData, optionData.Length + 4); 145 | Array.Copy(dnsserv, 0, optionData, optionData.Length - 4, 4); 146 | } 147 | } 148 | break; 149 | case DHCPOption.DomainName: 150 | if (!string.IsNullOrEmpty(replyOptions.DomainName)) 151 | optionData = System.Text.Encoding.ASCII.GetBytes(replyOptions.DomainName); 152 | break; 153 | case DHCPOption.ServerIdentifier: 154 | if (replyOptions.ServerIdentifier != null) 155 | optionData = replyOptions.ServerIdentifier.GetAddressBytes(); 156 | break; 157 | case DHCPOption.LogServer: 158 | if (replyOptions.LogServerIP != null) 159 | optionData = replyOptions.LogServerIP.GetAddressBytes(); 160 | break; 161 | case DHCPOption.StaticRoutes: 162 | case DHCPOption.StaticRoutesWin: 163 | if (replyOptions.StaticRoutes != null) 164 | { 165 | optionData = new byte[] { }; 166 | foreach (var route in replyOptions.StaticRoutes) 167 | { 168 | var routeData = route.BuildRouteData(); 169 | Array.Resize(ref optionData, optionData.Length + routeData.Length); 170 | Array.Copy(routeData, 0, optionData, optionData.Length - routeData.Length, routeData.Length); 171 | } 172 | } 173 | break; 174 | default: 175 | replyOptions.OtherRequestedOptions.TryGetValue(i, out optionData); 176 | break; 177 | } 178 | if (optionData != null) 179 | { 180 | options[i] = optionData; 181 | } 182 | } 183 | 184 | if (GetMsgType() != DHCPMsgType.DHCPINFORM) 185 | { 186 | // Lease time 187 | if (replyOptions != null) 188 | { 189 | options[DHCPOption.IPAddressLeaseTime] = EncodeTimeOption(replyOptions.IPAddressLeaseTime); 190 | if (replyOptions.RenewalTimeValue_T1.HasValue) 191 | { 192 | options[DHCPOption.RenewalTimeValue_T1] = EncodeTimeOption(replyOptions.RenewalTimeValue_T1.Value); 193 | } 194 | if (replyOptions.RebindingTimeValue_T2.HasValue) 195 | { 196 | options[DHCPOption.RebindingTimeValue_T2] = EncodeTimeOption(replyOptions.RebindingTimeValue_T2.Value); 197 | } 198 | } 199 | } 200 | // Other requested options 201 | if (otherForceOptions != null) 202 | foreach (var option in otherForceOptions.Keys) 203 | { 204 | options[option] = otherForceOptions[option]; 205 | if (option == DHCPOption.RelayInfo) 206 | relayInfo = null; 207 | } 208 | 209 | // Option 82? Send it back! 210 | if (relayInfo != null) 211 | { 212 | options[DHCPOption.RelayInfo] = relayInfo; 213 | } 214 | 215 | foreach (var option in options.OrderBy(x=>(int)x.Key)) 216 | { 217 | CreateOptionElement(ref resultOptions, option.Key, option.Value); 218 | } 219 | 220 | // Create the end option 221 | Array.Resize(ref resultOptions, resultOptions.Length + 1); 222 | Array.Copy(new byte[] { 255 }, 0, resultOptions, resultOptions.Length - 1, 1); 223 | return resultOptions; 224 | } 225 | 226 | private static byte[] EncodeTimeOption(uint seconds) 227 | { 228 | var leaseTime = new byte[4]; 229 | leaseTime[3] = (byte)seconds; 230 | leaseTime[2] = (byte)(seconds >> 8); 231 | leaseTime[1] = (byte)(seconds >> 16); 232 | leaseTime[0] = (byte)(seconds >> 24); 233 | return leaseTime; 234 | } 235 | 236 | static private void CreateOptionElement(ref byte[] options, DHCPOption option, byte[] data) 237 | { 238 | byte[] optionData; 239 | 240 | optionData = new byte[data.Length + 2]; 241 | optionData[0] = (byte)option; 242 | optionData[1] = (byte)data.Length; 243 | Array.Copy(data, 0, optionData, 2, data.Length); 244 | if (options == null) 245 | Array.Resize(ref options, (int)optionData.Length); 246 | else 247 | Array.Resize(ref options, options.Length + optionData.Length); 248 | Array.Copy(optionData, 0, options, options.Length - optionData.Length, optionData.Length); 249 | } 250 | 251 | /// 252 | /// Sends DHCP reply 253 | /// 254 | /// Type of DHCP message to send 255 | /// IP for client 256 | /// Reply options (will be sent if requested) 257 | public void SendDHCPReply(DHCPMsgType msgType, IPAddress ip, DHCPReplyOptions replyData) 258 | { 259 | SendDHCPReply(msgType, ip, replyData, null, null); 260 | } 261 | 262 | 263 | 264 | /// 265 | /// Sends DHCP reply 266 | /// 267 | /// Type of DHCP message to send 268 | /// IP for client 269 | /// Reply options (will be sent if requested) 270 | /// Force reply options (will be sent anyway) 271 | public void SendDHCPReply(DHCPMsgType msgType, IPAddress ip, DHCPReplyOptions replyData, 272 | Dictionary otherForceOptions) 273 | { 274 | SendDHCPReply(msgType, ip, replyData, otherForceOptions, null); 275 | } 276 | 277 | /// 278 | /// Sends DHCP reply 279 | /// 280 | /// Type of DHCP message to send 281 | /// IP for client 282 | /// Reply options (will be sent if requested) 283 | /// Force reply options (will be sent anyway) 284 | public void SendDHCPReply(DHCPMsgType msgType, IPAddress ip, DHCPReplyOptions replyData, 285 | IEnumerable forceOptions) 286 | { 287 | SendDHCPReply(msgType, ip, replyData, null, forceOptions); 288 | } 289 | 290 | /// 291 | /// Sends DHCP reply 292 | /// 293 | /// Type of DHCP message to send 294 | /// IP for client 295 | /// Reply options (will be sent if requested) 296 | /// Force reply options (will be sent anyway) 297 | private void SendDHCPReply(DHCPMsgType msgType, IPAddress ip, DHCPReplyOptions replyData, Dictionary otherForceOptions, IEnumerable forceOptions) 298 | { 299 | var replyBuffer = requestData; 300 | replyBuffer.op = 2; // Reply 301 | replyBuffer.yiaddr = ip.GetAddressBytes(); // Client's IP 302 | if (replyData.ServerIpAddress != null) 303 | { 304 | replyBuffer.siaddr = replyData.ServerIpAddress.GetAddressBytes(); 305 | } 306 | replyBuffer.options = CreateOptionStruct(msgType, replyData, otherForceOptions, forceOptions); // Options 307 | if (!string.IsNullOrEmpty(dhcpServer.ServerName)) 308 | { 309 | var serverNameBytes = Encoding.ASCII.GetBytes(dhcpServer.ServerName); 310 | int len = (serverNameBytes.Length > 63) ? 63 : serverNameBytes.Length; 311 | Array.Copy(serverNameBytes, replyBuffer.sname, len); 312 | replyBuffer.sname[len] = 0; 313 | } 314 | lock (requestSocket) 315 | { 316 | var DataToSend = BuildDataStructure(replyBuffer); 317 | if (DataToSend.Length < 300) 318 | { 319 | var sendArray = new byte[300]; 320 | Array.Copy(DataToSend, 0, sendArray, 0, DataToSend.Length); 321 | DataToSend = sendArray; 322 | } 323 | 324 | IPEndPoint endPoint; 325 | if ((replyBuffer.giaddr[0] == 0) && (replyBuffer.giaddr[1] == 0) && 326 | (replyBuffer.giaddr[2] == 0) && (replyBuffer.giaddr[3] == 0)) 327 | { 328 | requestSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true); 329 | endPoint = new IPEndPoint(dhcpServer.BroadcastAddress, PORT_TO_SEND_TO_CLIENT); 330 | if (dhcpServer.SendDhcpAnswerNetworkInterface != null) 331 | { 332 | requestSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, (int)IPAddress.HostToNetworkOrder(dhcpServer.SendDhcpAnswerNetworkInterface.GetIPProperties().GetIPv4Properties().Index)); 333 | } 334 | requestSocket.SendTo(DataToSend, endPoint); 335 | } 336 | else 337 | { 338 | requestSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, false); 339 | endPoint = new IPEndPoint(new IPAddress(replyBuffer.giaddr), PORT_TO_SEND_TO_RELAY); 340 | if (dhcpServer.SendDhcpAnswerNetworkInterface != null) 341 | { 342 | requestSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, (int)IPAddress.HostToNetworkOrder(dhcpServer.SendDhcpAnswerNetworkInterface.GetIPProperties().GetIPv4Properties().Index)); 343 | } 344 | requestSocket.SendTo(DataToSend, endPoint); 345 | } 346 | } 347 | } 348 | 349 | private static byte[] BuildDataStructure(DHCPPacket packet) 350 | { 351 | byte[] mArray; 352 | 353 | try 354 | { 355 | mArray = new byte[0]; 356 | AddOptionElement(new byte[] { packet.op }, ref mArray); 357 | AddOptionElement(new byte[] { packet.htype }, ref mArray); 358 | AddOptionElement(new byte[] { packet.hlen }, ref mArray); 359 | AddOptionElement(new byte[] { packet.hops }, ref mArray); 360 | AddOptionElement(packet.xid, ref mArray); 361 | AddOptionElement(packet.secs, ref mArray); 362 | AddOptionElement(packet.flags, ref mArray); 363 | AddOptionElement(packet.ciaddr, ref mArray); 364 | AddOptionElement(packet.yiaddr, ref mArray); 365 | AddOptionElement(packet.siaddr, ref mArray); 366 | AddOptionElement(packet.giaddr, ref mArray); 367 | AddOptionElement(packet.chaddr, ref mArray); 368 | AddOptionElement(packet.sname, ref mArray); 369 | AddOptionElement(packet.file, ref mArray); 370 | 371 | AddOptionElement(packet.mcookie, ref mArray); 372 | AddOptionElement(packet.options, ref mArray); 373 | return mArray; 374 | } 375 | finally 376 | { 377 | mArray = null; 378 | } 379 | } 380 | 381 | private static void AddOptionElement(byte[] fromValue, ref byte[] targetArray) 382 | { 383 | if (targetArray != null) 384 | Array.Resize(ref targetArray, targetArray.Length + fromValue.Length); 385 | else 386 | Array.Resize(ref targetArray, fromValue.Length); 387 | Array.Copy(fromValue, 0, targetArray, targetArray.Length - fromValue.Length, fromValue.Length); 388 | } 389 | 390 | /// 391 | /// Returns option content 392 | /// 393 | /// Option to retrieve 394 | /// Option content 395 | public byte[] GetOptionData(DHCPOption option) 396 | { 397 | int DHCPId = 0; 398 | byte DDataID, DataLength = 0; 399 | byte[] dumpData; 400 | 401 | DHCPId = (int)option; 402 | for (int i = 0; i < requestData.options.Length; i++) 403 | { 404 | DDataID = requestData.options[i]; 405 | if (DDataID == (byte)DHCPOption.END_Option) break; 406 | if (DDataID == DHCPId) 407 | { 408 | DataLength = requestData.options[i + 1]; 409 | dumpData = new byte[DataLength]; 410 | Array.Copy(requestData.options, i + 2, dumpData, 0, DataLength); 411 | return dumpData; 412 | } 413 | else if (DDataID == 0) 414 | { 415 | } 416 | else 417 | { 418 | DataLength = requestData.options[i + 1]; 419 | i += 1 + DataLength; 420 | } 421 | } 422 | 423 | return null; 424 | } 425 | 426 | /// 427 | /// Returns all options 428 | /// 429 | /// Options dictionary 430 | public Dictionary GetAllOptions() 431 | { 432 | var result = new Dictionary(); 433 | DHCPOption DDataID; 434 | byte DataLength = 0; 435 | 436 | for (int i = 0; i < requestData.options.Length; i++) 437 | { 438 | DDataID = (DHCPOption)requestData.options[i]; 439 | if (DDataID == DHCPOption.END_Option) break; 440 | DataLength = requestData.options[i + 1]; 441 | byte[] dumpData = new byte[DataLength]; 442 | Array.Copy(requestData.options, i + 2, dumpData, 0, DataLength); 443 | result[DDataID] = dumpData; 444 | 445 | DataLength = requestData.options[i + 1]; 446 | i += 1 + DataLength; 447 | } 448 | 449 | return result; 450 | } 451 | 452 | /// 453 | /// Returns ciaddr (client IP address) 454 | /// 455 | /// ciaddr 456 | public IPAddress GetCiaddr() 457 | { 458 | if ((requestData.ciaddr[0] == 0) && 459 | (requestData.ciaddr[1] == 0) && 460 | (requestData.ciaddr[2] == 0) && 461 | (requestData.ciaddr[3] == 0) 462 | ) return null; 463 | return new IPAddress(requestData.ciaddr); 464 | } 465 | /// 466 | /// Returns giaddr (gateway IP address switched by relay) 467 | /// 468 | /// giaddr 469 | public IPAddress GetGiaddr() 470 | { 471 | if ((requestData.giaddr[0] == 0) && 472 | (requestData.giaddr[1] == 0) && 473 | (requestData.giaddr[2] == 0) && 474 | (requestData.giaddr[3] == 0) 475 | ) return null; 476 | return new IPAddress(requestData.giaddr); 477 | } 478 | /// 479 | /// Returns chaddr (client hardware address) 480 | /// 481 | /// chaddr 482 | public byte[] GetChaddr() 483 | { 484 | var res = new byte[requestData.hlen]; 485 | Array.Copy(requestData.chaddr, res, requestData.hlen); 486 | return res; 487 | } 488 | /// 489 | /// Returns requested IP (option 50) 490 | /// 491 | /// Requested IP 492 | public IPAddress GetRequestedIP() 493 | { 494 | var ipBytes = GetOptionData(DHCPOption.RequestedIPAddress); 495 | if (ipBytes == null) return null; 496 | return new IPAddress(ipBytes); 497 | } 498 | /// 499 | /// Returns type of DHCP request 500 | /// 501 | /// DHCP message type 502 | public DHCPMsgType GetMsgType() 503 | { 504 | byte[] DData; 505 | DData = GetOptionData(DHCPOption.DHCPMessageTYPE); 506 | if (DData != null) 507 | return (DHCPMsgType)DData[0]; 508 | return 0; 509 | } 510 | /// 511 | /// Returns entire content of DHCP packet 512 | /// 513 | /// DHCP packet 514 | public DHCPPacket GetRawPacket() 515 | { 516 | return requestData; 517 | } 518 | /// 519 | /// Returns relay info (option 82) 520 | /// 521 | /// Relay info 522 | public RelayInfo? GetRelayInfo() 523 | { 524 | var result = new RelayInfo(); 525 | var relayInfo = GetOptionData(DHCPOption.RelayInfo); 526 | if (relayInfo != null) 527 | { 528 | int i = 0; 529 | while (i < relayInfo.Length) 530 | { 531 | var subOptID = relayInfo[i]; 532 | if (subOptID == 1) 533 | { 534 | result.AgentCircuitID = new byte[relayInfo[i + 1]]; 535 | Array.Copy(relayInfo, i + 2, result.AgentCircuitID, 0, relayInfo[i + 1]); 536 | } 537 | else if (subOptID == 2) 538 | { 539 | result.AgentRemoteID = new byte[relayInfo[i + 1]]; 540 | Array.Copy(relayInfo, i + 2, result.AgentRemoteID, 0, relayInfo[i + 1]); 541 | } 542 | i += 2 + relayInfo[i + 1]; 543 | } 544 | return result; 545 | } 546 | return null; 547 | } 548 | } 549 | } -------------------------------------------------------------------------------- /SharpDHCPServerLib/DHCPServer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Net.NetworkInformation; 4 | using System.Net.Sockets; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | 8 | namespace DotNetProjects.DhcpServer 9 | { 10 | /// 11 | /// DHCP Server 12 | /// 13 | public class DHCPServer : IDisposable 14 | { 15 | /// Delegate for DHCP message 16 | public delegate void DHCPDataReceivedEventHandler(DHCPRequest dhcpRequest); 17 | 18 | /// Will be called on any DHCP message 19 | public event DHCPDataReceivedEventHandler OnDataReceived = delegate { }; 20 | /// Will be called on any DISCOVER message 21 | public event DHCPDataReceivedEventHandler OnDiscover = delegate { }; 22 | /// Will be called on any REQUEST message 23 | public event DHCPDataReceivedEventHandler OnRequest = delegate { }; 24 | /// Will be called on any DECLINE message 25 | public event DHCPDataReceivedEventHandler OnDecline = delegate { }; 26 | /// Will be called on any DECLINE released 27 | public event DHCPDataReceivedEventHandler OnReleased = delegate { }; 28 | /// Will be called on any DECLINE inform 29 | public event DHCPDataReceivedEventHandler OnInform = delegate { }; 30 | 31 | /// Server name (optional) 32 | public string ServerName { get; set; } 33 | 34 | private Socket socket = null; 35 | private Task receiveDataTask = null; 36 | private const int PORT_TO_LISTEN_TO = 67; 37 | private IPAddress _bindIp; 38 | private CancellationTokenSource _cancellationTokenSource; 39 | 40 | public event Action UnhandledException; 41 | 42 | public IPAddress BroadcastAddress { get; set; } 43 | 44 | public NetworkInterface SendDhcpAnswerNetworkInterface { get; set; } 45 | 46 | /// 47 | /// Creates DHCP server, it will be started instantly 48 | /// 49 | /// IP address to bind 50 | public DHCPServer(IPAddress bindIp) 51 | { 52 | _bindIp = bindIp; 53 | } 54 | 55 | /// Creates DHCP server, it will be started instantly 56 | public DHCPServer() : this(IPAddress.Any) 57 | { 58 | BroadcastAddress = IPAddress.Broadcast; 59 | } 60 | 61 | /// Starts the DHCP server. 62 | /// Invalid Socket or error while accessing the socket. 63 | /// No permission for requested operation. 64 | public void Start() 65 | { 66 | var ipLocalEndPoint = new IPEndPoint(_bindIp, PORT_TO_LISTEN_TO); 67 | socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); 68 | socket.Bind(ipLocalEndPoint); 69 | _cancellationTokenSource = new CancellationTokenSource(); 70 | receiveDataTask = new Task(ReceiveDataThread, _cancellationTokenSource.Token, TaskCreationOptions.LongRunning); 71 | receiveDataTask.Start(); 72 | } 73 | 74 | /// Disposes DHCP server 75 | public void Dispose() 76 | { 77 | if (socket != null) 78 | { 79 | socket.Close(); 80 | socket = null; 81 | } 82 | if (receiveDataTask != null) 83 | { 84 | _cancellationTokenSource.Cancel(); 85 | receiveDataTask.Wait(); 86 | receiveDataTask = null; 87 | _cancellationTokenSource.Dispose(); 88 | _cancellationTokenSource = null; 89 | } 90 | } 91 | 92 | private void ReceiveDataThread() 93 | { 94 | while (!_cancellationTokenSource.IsCancellationRequested) 95 | { 96 | try 97 | { 98 | IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0); 99 | EndPoint remote = (EndPoint)(sender); var buffer = new byte[1024]; 100 | int len = socket.ReceiveFrom(buffer, ref remote); 101 | if (len > 0) 102 | { 103 | Array.Resize(ref buffer, len); 104 | Task.Factory.StartNew(() => DataReceived(buffer)); 105 | } 106 | } 107 | catch (Exception ex) 108 | { 109 | if (UnhandledException != null) 110 | UnhandledException(ex); 111 | } 112 | } 113 | } 114 | 115 | private void DataReceived(object o) 116 | { 117 | var data = (byte[])o; 118 | try 119 | { 120 | var dhcpRequest = new DHCPRequest(data, socket, this); 121 | //ccDHCP = new clsDHCP(); 122 | 123 | 124 | //data is now in the structure 125 | //get the msg type 126 | OnDataReceived(dhcpRequest); 127 | var msgType = dhcpRequest.GetMsgType(); 128 | switch (msgType) 129 | { 130 | case DHCPMsgType.DHCPDISCOVER: 131 | OnDiscover(dhcpRequest); 132 | break; 133 | case DHCPMsgType.DHCPREQUEST: 134 | OnRequest(dhcpRequest); 135 | break; 136 | case DHCPMsgType.DHCPDECLINE: 137 | OnDecline(dhcpRequest); 138 | break; 139 | case DHCPMsgType.DHCPRELEASE: 140 | OnReleased(dhcpRequest); 141 | break; 142 | case DHCPMsgType.DHCPINFORM: 143 | OnInform(dhcpRequest); 144 | break; 145 | //default: 146 | // Console.WriteLine("Unknown DHCP message: " + (int)MsgTyp + " (" + MsgTyp.ToString() + ")"); 147 | // break; 148 | } 149 | } 150 | catch (Exception ex) 151 | { 152 | if (UnhandledException != null) 153 | UnhandledException(ex); 154 | } 155 | } 156 | } 157 | } -------------------------------------------------------------------------------- /SharpDHCPServerLib/NetworkRoute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | 4 | namespace DotNetProjects.DhcpServer 5 | { 6 | /// Network route 7 | public struct NetworkRoute 8 | { 9 | /// IP address of destination network 10 | public IPAddress Network; 11 | /// Subnet mask length 12 | public byte NetMaskLength; 13 | /// Gateway 14 | public IPAddress Gateway; 15 | 16 | /// Creates network route 17 | /// IP address to bind 18 | /// Subnet mask length 19 | /// Gateway 20 | public NetworkRoute(IPAddress network, byte netMaskLength, IPAddress gateway) 21 | { 22 | Network = network; 23 | NetMaskLength = netMaskLength; 24 | Gateway = gateway; 25 | } 26 | 27 | /// Creates network route 28 | /// IP address to bind 29 | /// Subnet mask 30 | /// Gateway 31 | public NetworkRoute(IPAddress network, IPAddress netMask, IPAddress gateway) 32 | { 33 | byte length = 0; 34 | var mask = netMask.GetAddressBytes(); 35 | for (byte x = 0; x < 4; x++) 36 | { 37 | for (byte b = 0; b < 8; b++) 38 | if (((mask[x] >> (7 - b)) & 1) == 1) 39 | length++; 40 | else break; 41 | } 42 | Network = network; 43 | NetMaskLength = length; 44 | Gateway = gateway; 45 | } 46 | 47 | internal byte[] BuildRouteData() 48 | { 49 | int ipLength; 50 | if (NetMaskLength <= 8) ipLength = 1; 51 | else if (NetMaskLength <= 16) ipLength = 2; 52 | else if (NetMaskLength <= 24) ipLength = 3; 53 | else ipLength = 4; 54 | var res = new byte[1 + ipLength + 4]; 55 | res[0] = NetMaskLength; 56 | Array.Copy(Network.GetAddressBytes(), 0, res, 1, ipLength); 57 | Array.Copy(Gateway.GetAddressBytes(), 0, res, 1 + ipLength, 4); 58 | return res; 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /SharpDHCPServerLib/Properties/.svn/all-wcprops: -------------------------------------------------------------------------------- 1 | K 25 2 | svn:wc:ra_dav:version-url 3 | V 51 4 | /svn/!svn/ver/2/trunk/SharpDHCPServerLib/Properties 5 | END 6 | AssemblyInfo.cs 7 | K 25 8 | svn:wc:ra_dav:version-url 9 | V 67 10 | /svn/!svn/ver/2/trunk/SharpDHCPServerLib/Properties/AssemblyInfo.cs 11 | END 12 | -------------------------------------------------------------------------------- /SharpDHCPServerLib/Properties/.svn/entries: -------------------------------------------------------------------------------- 1 | 10 2 | 3 | dir 4 | 2 5 | https://sharpdhcpserver.googlecode.com/svn/trunk/SharpDHCPServerLib/Properties 6 | https://sharpdhcpserver.googlecode.com/svn 7 | 8 | 9 | 10 | 2010-12-06T13:59:04.594212Z 11 | 2 12 | Avdyukhin@gmail.com 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 3d45f574-0380-fa68-85f7-e44bac00989b 28 | 29 | AssemblyInfo.cs 30 | file 31 | 32 | 33 | 34 | 35 | 2010-12-06T13:51:30.709049Z 36 | c131f1daf5dad472d15168f3252a5ad3 37 | 2010-12-06T13:59:04.594212Z 38 | 2 39 | Avdyukhin@gmail.com 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 2060 62 | 63 | -------------------------------------------------------------------------------- /SharpDHCPServerLib/Properties/.svn/text-base/AssemblyInfo.cs.svn-base: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // Управление общими сведениями о сборке осуществляется с помощью 6 | // набора атрибутов. Измените значения этих атрибутов, чтобы изменить сведения, 7 | // связанные со сборкой. 8 | [assembly: AssemblyTitle("SharpDHCPServerLib")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Cluster")] 12 | [assembly: AssemblyProduct("SharpDHCPServerLib")] 13 | [assembly: AssemblyCopyright("Copyright © Cluster 2010")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Параметр ComVisible со значением FALSE делает типы в сборке невидимыми 18 | // для COM-компонентов. Если требуется обратиться к типу в этой сборке через 19 | // COM, задайте атрибуту ComVisible значение TRUE для этого типа. 20 | [assembly: ComVisible(false)] 21 | 22 | // Следующий GUID служит для идентификации библиотеки типов, если этот проект будет видимым для COM 23 | [assembly: Guid("5b90d8af-c01f-4d81-9b8f-2e06c98aac49")] 24 | 25 | // Сведения о версии сборки состоят из следующих четырех значений: 26 | // 27 | // Основной номер версии 28 | // Дополнительный номер версии 29 | // Номер построения 30 | // Редакция 31 | // 32 | // Можно задать все значения или принять номер построения и номер редакции по умолчанию, 33 | // используя "*", как показано ниже: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /SharpDHCPServerLib/RelayInfo.cs: -------------------------------------------------------------------------------- 1 | namespace DotNetProjects.DhcpServer 2 | { 3 | /// DHCP relay information (option 82) 4 | public struct RelayInfo 5 | { 6 | /// Agent circuit ID 7 | public byte[] AgentCircuitID; 8 | /// Agent remote ID 9 | public byte[] AgentRemoteID; 10 | } 11 | } -------------------------------------------------------------------------------- /SharpDHCPServerLib/SharpDHCPServerLib.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | netstandard2.0;net40 4 | DotNetProjects.DhcpServer 5 | DotNetProjects 6 | DotNetProjects 7 | DotNetProjects.DhcpServer 8 | https://github.com/dotnetprojects/sharp-dhcp-server-lib 9 | MIT 10 | 1.0.0.0 11 | 1.0.0.0 12 | a fully managed DhcpServer 13 | 2019 14 | true 15 | DotNetProjects.DhcpServer 16 | DotNetProjects.DhcpServer 17 | 1.0.0 18 | 19 | true 20 | true 21 | snupkg 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /SharpDHCPServer_Sample/Program.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * ShapDHCPServer (C) 2010, Cluster 3 | * http://clusterrr.com 4 | * http://code.google.com/p/sharpdhcpserver/ 5 | * 6 | * DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 7 | * Version 2, December 2004 8 | * 9 | * Copyright (C) 2004 Sam Hocevar 10 | * 14 rue de Plaisance, 75014 Paris, France 11 | * Everyone is permitted to copy and distribute verbatim or modified 12 | * copies of this license document, and changing it is allowed as long 13 | * as the name is changed. 14 | * 15 | * DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 16 | * TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 17 | * 18 | * 0. You just DO WHAT THE FUCK YOU WANT TO. 19 | * 20 | */ 21 | 22 | using System; 23 | using System.Collections.Generic; 24 | using System.Linq; 25 | using System.Text; 26 | using System.Net; 27 | using System.Net.NetworkInformation; 28 | using DotNetProjects.DhcpServer; 29 | 30 | namespace Cluster.SharpDHCPServer_Sample 31 | { 32 | class Program 33 | { 34 | const string LOCAL_INTERFACE = "0.0.0.0"; 35 | static byte nextIP = 10; 36 | static Dictionary leases = new Dictionary(); 37 | static void Main(string[] args) 38 | { 39 | var lst = NetworkInterface.GetAllNetworkInterfaces(); 40 | 41 | var eth0If = NetworkInterface.GetAllNetworkInterfaces().FirstOrDefault(x => x.Name == "USB_ETH"); 42 | var server = new DHCPServer(); 43 | server.ServerName = "SharpDHCPServer"; 44 | server.OnDataReceived += Request; 45 | server.BroadcastAddress = IPAddress.Broadcast; 46 | server.SendDhcpAnswerNetworkInterface = eth0If; 47 | server.Start(); 48 | Console.WriteLine("Running DHCP server. Press enter to stop it."); 49 | Console.ReadLine(); 50 | server.Dispose(); 51 | } 52 | 53 | static void Request(DHCPRequest dhcpRequest) 54 | { 55 | try 56 | { 57 | var type = dhcpRequest.GetMsgType(); 58 | var mac = ByteArrayToString(dhcpRequest.GetChaddr()); 59 | // IP for client 60 | IPAddress ip; 61 | if (!leases.TryGetValue(mac, out ip)) 62 | { 63 | ip = new IPAddress(new byte[] {192, 168, 1, nextIP++}); 64 | leases[mac] = ip; 65 | } 66 | Console.WriteLine(type.ToString() + " request from " + mac + ", it will be " + ip.ToString()); 67 | 68 | var options = dhcpRequest.GetAllOptions(); 69 | Console.Write("Options:"); 70 | foreach (DHCPOption option in options.Keys) 71 | { 72 | Console.WriteLine(option.ToString() + ": " + ByteArrayToString(options[option])); 73 | } 74 | // Lets show some request info 75 | var requestedOptions = dhcpRequest.GetRequestedOptionsList(); 76 | if (requestedOptions != null) 77 | { 78 | Console.Write("Requested options:"); 79 | foreach (DHCPOption option in requestedOptions) Console.Write(" " + option.ToString()); 80 | Console.WriteLine(); 81 | } 82 | // Option 82 info 83 | var relayInfoN = dhcpRequest.GetRelayInfo(); 84 | if (relayInfoN != null) 85 | { 86 | var relayInfo = (RelayInfo) relayInfoN; 87 | if (relayInfo.AgentCircuitID != null) 88 | Console.WriteLine("Relay agent circuit ID: " + ByteArrayToString(relayInfo.AgentCircuitID)); 89 | if (relayInfo.AgentRemoteID != null) 90 | Console.WriteLine("Relay agent remote ID: " + ByteArrayToString(relayInfo.AgentRemoteID)); 91 | } 92 | Console.WriteLine(); 93 | 94 | var replyOptions = new DHCPReplyOptions(); 95 | // Options should be filled with valid data. Only requested options will be sent. 96 | replyOptions.SubnetMask = IPAddress.Parse("255.255.255.0"); 97 | replyOptions.DomainName = "SharpDHCPServer"; 98 | replyOptions.ServerIdentifier = IPAddress.Parse("10.0.0.1"); 99 | replyOptions.RouterIP = IPAddress.Parse("10.0.0.1"); 100 | replyOptions.DomainNameServers = new IPAddress[] 101 | {IPAddress.Parse("192.168.100.2"), IPAddress.Parse("192.168.100.3")}; 102 | // Some static routes 103 | replyOptions.StaticRoutes = new NetworkRoute[] 104 | { 105 | new NetworkRoute(IPAddress.Parse("10.0.0.0"), IPAddress.Parse("255.0.0.0"), 106 | IPAddress.Parse("10.0.0.1")), 107 | new NetworkRoute(IPAddress.Parse("192.168.0.0"), IPAddress.Parse("255.255.0.0"), 108 | IPAddress.Parse("10.0.0.1")), 109 | new NetworkRoute(IPAddress.Parse("172.16.0.0"), IPAddress.Parse("255.240.0.0"), 110 | IPAddress.Parse("10.0.0.1")), 111 | new NetworkRoute(IPAddress.Parse("80.252.130.248"), IPAddress.Parse("255.255.255.248"), 112 | IPAddress.Parse("10.0.0.1")), 113 | new NetworkRoute(IPAddress.Parse("80.252.128.88"), IPAddress.Parse("255.255.255.248"), 114 | IPAddress.Parse("10.0.0.1")), 115 | }; 116 | 117 | // Lets send reply to client! 118 | if (type == DHCPMsgType.DHCPDISCOVER) 119 | dhcpRequest.SendDHCPReply(DHCPMsgType.DHCPOFFER, ip, replyOptions); 120 | if (type == DHCPMsgType.DHCPREQUEST) 121 | dhcpRequest.SendDHCPReply(DHCPMsgType.DHCPACK, ip, replyOptions); 122 | } 123 | catch (Exception ex) 124 | { 125 | Console.WriteLine(ex); 126 | } 127 | } 128 | 129 | static string ByteArrayToString(byte[] ar) 130 | { 131 | var res = new StringBuilder(); 132 | foreach (var b in ar) 133 | { 134 | res.Append(b.ToString("X2")); 135 | } 136 | res.Append(" ("); 137 | foreach (var b in ar) 138 | { 139 | if ((b >= 32) && (b <127)) 140 | res.Append(Encoding.ASCII.GetString(new byte[] { b })); 141 | else res.Append(" "); 142 | } 143 | res.Append(")"); 144 | return res.ToString(); 145 | } 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /SharpDHCPServer_Sample/Properties/.svn/all-wcprops: -------------------------------------------------------------------------------- 1 | K 25 2 | svn:wc:ra_dav:version-url 3 | V 55 4 | /svn/!svn/ver/2/trunk/SharpDHCPServer_Sample/Properties 5 | END 6 | AssemblyInfo.cs 7 | K 25 8 | svn:wc:ra_dav:version-url 9 | V 71 10 | /svn/!svn/ver/2/trunk/SharpDHCPServer_Sample/Properties/AssemblyInfo.cs 11 | END 12 | -------------------------------------------------------------------------------- /SharpDHCPServer_Sample/Properties/.svn/entries: -------------------------------------------------------------------------------- 1 | 10 2 | 3 | dir 4 | 2 5 | https://sharpdhcpserver.googlecode.com/svn/trunk/SharpDHCPServer_Sample/Properties 6 | https://sharpdhcpserver.googlecode.com/svn 7 | 8 | 9 | 10 | 2010-12-06T13:59:04.594212Z 11 | 2 12 | Avdyukhin@gmail.com 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 3d45f574-0380-fa68-85f7-e44bac00989b 28 | 29 | AssemblyInfo.cs 30 | file 31 | 32 | 33 | 34 | 35 | 2010-12-06T13:51:30.753049Z 36 | ab4507a3a785b28cd58c3d387576aeb7 37 | 2010-12-06T13:59:04.594212Z 38 | 2 39 | Avdyukhin@gmail.com 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 2068 62 | 63 | -------------------------------------------------------------------------------- /SharpDHCPServer_Sample/Properties/.svn/text-base/AssemblyInfo.cs.svn-base: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // Управление общими сведениями о сборке осуществляется с помощью 6 | // набора атрибутов. Измените значения этих атрибутов, чтобы изменить сведения, 7 | // связанные со сборкой. 8 | [assembly: AssemblyTitle("SharpDHCPServer_Sample")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Cluster")] 12 | [assembly: AssemblyProduct("SharpDHCPServer_Sample")] 13 | [assembly: AssemblyCopyright("Copyright © Cluster 2010")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Параметр ComVisible со значением FALSE делает типы в сборке невидимыми 18 | // для COM-компонентов. Если требуется обратиться к типу в этой сборке через 19 | // COM, задайте атрибуту ComVisible значение TRUE для этого типа. 20 | [assembly: ComVisible(false)] 21 | 22 | // Следующий GUID служит для идентификации библиотеки типов, если этот проект будет видимым для COM 23 | [assembly: Guid("b0578828-11d1-4197-8af2-f029410d1672")] 24 | 25 | // Сведения о версии сборки состоят из следующих четырех значений: 26 | // 27 | // Основной номер версии 28 | // Дополнительный номер версии 29 | // Номер построения 30 | // Редакция 31 | // 32 | // Можно задать все значения или принять номер построения и номер редакции по умолчанию, 33 | // используя "*", как показано ниже: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /SharpDHCPServer_Sample/SharpDHCPServer_Sample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | netcoreapp3.0 4 | 5 | 6 | Debug 7 | x86 8 | 8.0.30703 9 | 2.0 10 | {E0A4A539-681E-45E1-84A8-C530BA129856} 11 | Exe 12 | Properties 13 | Cluster.SharpDHCPServer_Sample 14 | SharpDHCPServer_Sample 15 | 512 16 | true 17 | true 18 | snupkg 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | AnyCPU 27 | true 28 | full 29 | false 30 | bin\Debug\ 31 | DEBUG;TRACE 32 | prompt 33 | 4 34 | false 35 | 36 | 37 | x86 38 | pdbonly 39 | true 40 | bin\Release\ 41 | TRACE 42 | prompt 43 | 4 44 | false 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 2.0.{build} 2 | 3 | branches: 4 | only: 5 | - master 6 | 7 | dotnet_csproj: 8 | patch: true 9 | file: '**\*.csproj' 10 | version: '{version}' 11 | package_version: '{version}' 12 | assembly_version: '{version}' 13 | file_version: '{version}' 14 | informational_version: '{version}' 15 | 16 | configuration: Debug 17 | 18 | image: Visual Studio 2019 19 | 20 | before_build: 21 | - nuget restore 22 | 23 | build: 24 | project: SharpDHCPServer.sln 25 | 26 | test: off 27 | 28 | artifacts: 29 | - path: '**\DotNetProjects.DhcpServer*.nupkg' 30 | 31 | #uncomment to publish to NuGet 32 | deploy: 33 | provider: NuGet 34 | api_key: 35 | secure: 88aMSx9ONm6ZEyZHiWughpXbF3QGPuYy7yjQxQSt69pDc89aKMBYm8KPOaCIUX9s 36 | artifact: /.*\.nupkg/ 37 | 38 | 39 | 40 | --------------------------------------------------------------------------------