/// <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);
        }