Exemple #1
0
        internal Lease(BinaryReader bR)
        {
            switch (bR.ReadByte())
            {
            case 1:
                _type             = (LeaseType)bR.ReadByte();
                _clientIdentifier = DhcpOption.Parse(bR.BaseStream) as ClientIdentifierOption;
                _clientIdentifier.ParseOptionValue();

                _hostName = bR.ReadShortString();
                if (_hostName == "")
                {
                    _hostName = null;
                }

                _hardwareAddress = bR.ReadBuffer();
                _address         = IPAddressExtension.Parse(bR);
                _leaseObtained   = bR.ReadDate();
                _leaseExpires    = bR.ReadDate();
                break;

            default:
                throw new InvalidDataException("Lease data format version not supported.");
            }
        }
Exemple #2
0
        internal void AppendOptionValue(DhcpOption option)
        {
            byte[] value = new byte[_value.Length + option._value.Length];

            Buffer.BlockCopy(_value, 0, value, 0, _value.Length);
            Buffer.BlockCopy(option._value, 0, value, _value.Length, option._value.Length);

            _value = value;
        }
Exemple #3
0
        internal Lease(BinaryReader bR)
        {
            byte version = bR.ReadByte();

            switch (version)
            {
            case 1:
            case 2:
                _type             = (LeaseType)bR.ReadByte();
                _clientIdentifier = DhcpOption.Parse(bR.BaseStream) as ClientIdentifierOption;
                _clientIdentifier.ParseOptionValue();

                _hostName = bR.ReadShortString();
                if (string.IsNullOrWhiteSpace(_hostName))
                {
                    _hostName = null;
                }

                _hardwareAddress = bR.ReadBuffer();
                _address         = IPAddressExtension.Parse(bR);

                if (version >= 2)
                {
                    _comments = bR.ReadShortString();
                    if (string.IsNullOrWhiteSpace(_comments))
                    {
                        _comments = null;
                    }
                }

                _leaseObtained = bR.ReadDateTime();
                _leaseExpires  = bR.ReadDateTime();
                break;

            default:
                throw new InvalidDataException("Lease data format version not supported.");
            }
        }
Exemple #4
0
        private DhcpMessage ProcessDhcpMessage(DhcpMessage request, IPEndPoint remoteEP, IPPacketInformation ipPacketInformation)
        {
            if (request.OpCode != DhcpMessageOpCode.BootRequest)
            {
                return(null);
            }

            switch (request.DhcpMessageType?.Type)
            {
            case DhcpMessageType.Discover:
            {
                Scope scope = FindScope(request, remoteEP.Address, ipPacketInformation);
                if (scope == null)
                {
                    return(null);        //no scope available; do nothing
                }
                if (scope.OfferDelayTime > 0)
                {
                    Thread.Sleep(scope.OfferDelayTime);         //delay sending offer
                }
                Lease offer = scope.GetOffer(request);
                if (offer == null)
                {
                    throw new DhcpServerException("DHCP Server failed to offer address: address unavailable due to address pool exhaustion.");
                }

                List <DhcpOption> options = scope.GetOptions(request, scope.InterfaceAddress);
                if (options == null)
                {
                    return(null);
                }

                //log ip offer
                LogManager log = _log;
                if (log != null)
                {
                    log.Write(remoteEP as IPEndPoint, "DHCP Server offered IP address [" + offer.Address.ToString() + "] to " + request.GetClientFullIdentifier() + ".");
                }

                return(new DhcpMessage(request, offer.Address, scope.InterfaceAddress, options));
            }

            case DhcpMessageType.Request:
            {
                //request ip address lease or extend existing lease
                Scope scope = FindScope(request, remoteEP.Address, ipPacketInformation);
                if (scope == null)
                {
                    return(null);        //no scope available; do nothing
                }
                Lease leaseOffer;

                if (request.ServerIdentifier == null)
                {
                    if (request.RequestedIpAddress == null)
                    {
                        //renewing or rebinding

                        if (request.ClientIpAddress.Equals(IPAddress.Any))
                        {
                            return(null);        //client must set IP address in ciaddr; do nothing
                        }
                        leaseOffer = scope.GetExistingLeaseOrOffer(request);
                        if (leaseOffer == null)
                        {
                            //no existing lease or offer available for client
                            //send nak
                            return(new DhcpMessage(request, IPAddress.Any, scope.InterfaceAddress, new DhcpOption[] { new DhcpMessageTypeOption(DhcpMessageType.Nak), new ServerIdentifierOption(scope.InterfaceAddress), DhcpOption.CreateEndOption() }));
                        }

                        if (!request.ClientIpAddress.Equals(leaseOffer.Address))
                        {
                            //client ip is incorrect
                            //send nak
                            return(new DhcpMessage(request, IPAddress.Any, scope.InterfaceAddress, new DhcpOption[] { new DhcpMessageTypeOption(DhcpMessageType.Nak), new ServerIdentifierOption(scope.InterfaceAddress), DhcpOption.CreateEndOption() }));
                        }
                    }
                    else
                    {
                        //init-reboot

                        leaseOffer = scope.GetExistingLeaseOrOffer(request);
                        if (leaseOffer == null)
                        {
                            //no existing lease or offer available for client
                            //send nak
                            return(new DhcpMessage(request, IPAddress.Any, scope.InterfaceAddress, new DhcpOption[] { new DhcpMessageTypeOption(DhcpMessageType.Nak), new ServerIdentifierOption(scope.InterfaceAddress), DhcpOption.CreateEndOption() }));
                        }

                        if (!request.RequestedIpAddress.Address.Equals(leaseOffer.Address))
                        {
                            //the client's notion of its IP address is not correct - RFC 2131
                            //send nak
                            return(new DhcpMessage(request, IPAddress.Any, scope.InterfaceAddress, new DhcpOption[] { new DhcpMessageTypeOption(DhcpMessageType.Nak), new ServerIdentifierOption(scope.InterfaceAddress), DhcpOption.CreateEndOption() }));
                        }
                    }
                }
                else
                {
                    //selecting offer

                    if (request.RequestedIpAddress == null)
                    {
                        return(null);        //client MUST include this option; do nothing
                    }
                    if (!request.ServerIdentifier.Address.Equals(scope.InterfaceAddress))
                    {
                        return(null);        //offer declined by client; do nothing
                    }
                    leaseOffer = scope.GetExistingLeaseOrOffer(request);
                    if (leaseOffer == null)
                    {
                        //no existing lease or offer available for client
                        //send nak
                        return(new DhcpMessage(request, IPAddress.Any, scope.InterfaceAddress, new DhcpOption[] { new DhcpMessageTypeOption(DhcpMessageType.Nak), new ServerIdentifierOption(scope.InterfaceAddress), DhcpOption.CreateEndOption() }));
                    }

                    if (!request.RequestedIpAddress.Address.Equals(leaseOffer.Address))
                    {
                        //requested ip is incorrect
                        //send nak
                        return(new DhcpMessage(request, IPAddress.Any, scope.InterfaceAddress, new DhcpOption[] { new DhcpMessageTypeOption(DhcpMessageType.Nak), new ServerIdentifierOption(scope.InterfaceAddress), DhcpOption.CreateEndOption() }));
                    }
                }

                List <DhcpOption> options = scope.GetOptions(request, scope.InterfaceAddress);
                if (options == null)
                {
                    return(null);
                }

                scope.CommitLease(leaseOffer);

                //log ip lease
                LogManager log = _log;
                if (log != null)
                {
                    log.Write(remoteEP as IPEndPoint, "DHCP Server leased IP address [" + leaseOffer.Address.ToString() + "] to " + request.GetClientFullIdentifier() + ".");
                }

                if (!string.IsNullOrEmpty(scope.DomainName))
                {
                    //update dns
                    string clientDomainName = null;

                    foreach (DhcpOption option in options)
                    {
                        if (option.Code == DhcpOptionCode.ClientFullyQualifiedDomainName)
                        {
                            clientDomainName = (option as ClientFullyQualifiedDomainNameOption).DomainName;
                            break;
                        }
                    }

                    if (clientDomainName == null)
                    {
                        if (request.HostName != null)
                        {
                            clientDomainName = request.HostName.HostName + "." + scope.DomainName;
                        }
                        else if ((leaseOffer.Type == LeaseType.Reserved) && !string.IsNullOrEmpty(leaseOffer.HostName) && !leaseOffer.HostName.EndsWith("." + scope.DomainName, StringComparison.OrdinalIgnoreCase))
                        {
                            clientDomainName = leaseOffer.HostName + "." + scope.DomainName;         //use hostname from reserved lease
                        }
                    }

                    if (clientDomainName != null)
                    {
                        leaseOffer.SetHostName(clientDomainName.ToLower());
                        UpdateDnsAuthZone(true, scope, leaseOffer);
                    }
                }

                return(new DhcpMessage(request, leaseOffer.Address, scope.InterfaceAddress, options));
            }

            case DhcpMessageType.Decline:
            {
                //ip address is already in use as detected by client via ARP

                if ((request.ServerIdentifier == null) || (request.RequestedIpAddress == null))
                {
                    return(null);        //client MUST include these option; do nothing
                }
                Scope scope = FindScope(request, remoteEP.Address, ipPacketInformation);
                if (scope == null)
                {
                    return(null);        //no scope available; do nothing
                }
                if (!request.ServerIdentifier.Address.Equals(scope.InterfaceAddress))
                {
                    return(null);        //request not for this server; do nothing
                }
                Lease lease = scope.GetExistingLeaseOrOffer(request);
                if (lease == null)
                {
                    return(null);        //no existing lease or offer available for client; do nothing
                }
                if (!lease.Address.Equals(request.RequestedIpAddress.Address))
                {
                    return(null);        //the client's notion of its IP address is not correct; do nothing
                }
                //remove lease since the IP address is used by someone else
                scope.ReleaseLease(lease);

                //log issue
                LogManager log = _log;
                if (log != null)
                {
                    log.Write(remoteEP as IPEndPoint, "DHCP Server received DECLINE message: " + lease.GetClientFullIdentifier() + " detected that IP address [" + lease.Address + "] is already in use.");
                }

                //update dns
                UpdateDnsAuthZone(false, scope, lease);

                //do nothing
                return(null);
            }

            case DhcpMessageType.Release:
            {
                //cancel ip address lease

                if (request.ServerIdentifier == null)
                {
                    return(null);        //client MUST include this option; do nothing
                }
                Scope scope = FindScope(request, remoteEP.Address, ipPacketInformation);
                if (scope == null)
                {
                    return(null);        //no scope available; do nothing
                }
                if (!request.ServerIdentifier.Address.Equals(scope.InterfaceAddress))
                {
                    return(null);        //request not for this server; do nothing
                }
                Lease lease = scope.GetExistingLeaseOrOffer(request);
                if (lease == null)
                {
                    return(null);        //no existing lease or offer available for client; do nothing
                }
                if (!lease.Address.Equals(request.ClientIpAddress))
                {
                    return(null);        //the client's notion of its IP address is not correct; do nothing
                }
                //release lease
                scope.ReleaseLease(lease);

                //log ip lease release
                LogManager log = _log;
                if (log != null)
                {
                    log.Write(remoteEP as IPEndPoint, "DHCP Server released IP address [" + lease.Address.ToString() + "] that was leased to " + lease.GetClientFullIdentifier() + ".");
                }

                //update dns
                UpdateDnsAuthZone(false, scope, lease);

                //do nothing
                return(null);
            }

            case DhcpMessageType.Inform:
            {
                //need only local config; already has ip address assigned externally/manually

                Scope scope = FindScope(request, remoteEP.Address, ipPacketInformation);
                if (scope == null)
                {
                    return(null);        //no scope available; do nothing
                }
                List <DhcpOption> options = scope.GetOptions(request, scope.InterfaceAddress);
                if (options == null)
                {
                    return(null);
                }

                //log inform
                LogManager log = _log;
                if (log != null)
                {
                    log.Write(remoteEP as IPEndPoint, "DHCP Server received INFORM message from " + request.GetClientFullIdentifier() + ".");
                }

                return(new DhcpMessage(request, IPAddress.Any, scope.InterfaceAddress, options));
            }

            default:
                return(null);
            }
        }
Exemple #5
0
        internal List <DhcpOption> GetOptions(DhcpMessage request, IPAddress serverIdentifierAddress)
        {
            List <DhcpOption> options = new List <DhcpOption>();

            switch (request.DhcpMessageType.Type)
            {
            case DhcpMessageType.Discover:
                options.Add(new DhcpMessageTypeOption(DhcpMessageType.Offer));
                break;

            case DhcpMessageType.Request:
            case DhcpMessageType.Inform:
                options.Add(new DhcpMessageTypeOption(DhcpMessageType.Ack));
                break;

            default:
                return(null);
            }

            options.Add(new ServerIdentifierOption(serverIdentifierAddress));

            switch (request.DhcpMessageType.Type)
            {
            case DhcpMessageType.Discover:
            case DhcpMessageType.Request:
                uint leaseTime = GetLeaseTime();

                options.Add(new IpAddressLeaseTimeOption(leaseTime));
                options.Add(new RenewalTimeValueOption(leaseTime / 2));
                options.Add(new RebindingTimeValueOption(Convert.ToUInt32(leaseTime * 0.875)));
                break;
            }

            if (request.ParameterRequestList == null)
            {
                options.Add(new SubnetMaskOption(_subnetMask));
                options.Add(new BroadcastAddressOption(_broadcastAddress));

                if (!string.IsNullOrEmpty(_domainName))
                {
                    options.Add(new DomainNameOption(_domainName));

                    if (request.ClientFullyQualifiedDomainName != null)
                    {
                        options.Add(GetClientFullyQualifiedDomainNameOption(request));
                    }
                }

                if (_routerAddress != null)
                {
                    options.Add(new RouterOption(new IPAddress[] { _routerAddress }));
                }

                if (_dnsServers != null)
                {
                    options.Add(new DomainNameServerOption(_dnsServers));
                }

                if (_winsServers != null)
                {
                    options.Add(new NetBiosNameServerOption(_winsServers));
                }

                if (_ntpServers != null)
                {
                    options.Add(new NetworkTimeProtocolServersOption(_ntpServers));
                }

                if (_staticRoutes != null)
                {
                    options.Add(new ClasslessStaticRouteOption(_staticRoutes));
                }
            }
            else
            {
                foreach (DhcpOptionCode optionCode in request.ParameterRequestList.OptionCodes)
                {
                    switch (optionCode)
                    {
                    case DhcpOptionCode.SubnetMask:
                        options.Add(new SubnetMaskOption(_subnetMask));
                        options.Add(new BroadcastAddressOption(_broadcastAddress));
                        break;

                    case DhcpOptionCode.DomainName:
                        if (!string.IsNullOrEmpty(_domainName))
                        {
                            options.Add(new DomainNameOption(_domainName));

                            if (request.ClientFullyQualifiedDomainName != null)
                            {
                                options.Add(GetClientFullyQualifiedDomainNameOption(request));
                            }
                        }

                        break;

                    case DhcpOptionCode.Router:
                        if (_routerAddress != null)
                        {
                            options.Add(new RouterOption(new IPAddress[] { _routerAddress }));
                        }

                        break;

                    case DhcpOptionCode.DomainNameServer:
                        if (_dnsServers != null)
                        {
                            options.Add(new DomainNameServerOption(_dnsServers));
                        }

                        break;

                    case DhcpOptionCode.NetBiosOverTcpIpNameServer:
                        if (_winsServers != null)
                        {
                            options.Add(new NetBiosNameServerOption(_winsServers));
                        }

                        break;

                    case DhcpOptionCode.NetworkTimeProtocolServers:
                        if (_ntpServers != null)
                        {
                            options.Add(new NetworkTimeProtocolServersOption(_ntpServers));
                        }

                        break;

                    case DhcpOptionCode.ClasslessStaticRoute:
                        if (_staticRoutes != null)
                        {
                            options.Add(new ClasslessStaticRouteOption(_staticRoutes));
                        }

                        break;
                    }
                }
            }

            options.Add(DhcpOption.CreateEndOption());

            return(options);
        }
Exemple #6
0
        private void ParseOptions(Stream s, List <DhcpOption> options)
        {
            while (true)
            {
                DhcpOption option = DhcpOption.Parse(s);
                if (option.Code == DhcpOptionCode.End)
                {
                    break;
                }

                if (option.Code == DhcpOptionCode.Pad)
                {
                    continue;
                }

                bool optionExists = false;

                foreach (DhcpOption existingOption in options)
                {
                    if (existingOption.Code == option.Code)
                    {
                        //option already exists so append current option value into existing option
                        existingOption.AppendOptionValue(option);
                        optionExists = true;
                        break;
                    }
                }

                if (optionExists)
                {
                    continue;
                }

                //add option to list
                options.Add(option);

                switch (option.Code)
                {
                case DhcpOptionCode.DhcpMessageType:
                    _dhcpMessageType = option as DhcpMessageTypeOption;
                    break;

                case DhcpOptionCode.ClientIdentifier:
                    _clientIdentifier = option as ClientIdentifierOption;
                    break;

                case DhcpOptionCode.HostName:
                    _hostName = option as HostNameOption;
                    break;

                case DhcpOptionCode.ClientFullyQualifiedDomainName:
                    _clientFullyQualifiedDomainName = option as ClientFullyQualifiedDomainNameOption;
                    break;

                case DhcpOptionCode.ParameterRequestList:
                    _parameterRequestList = option as ParameterRequestListOption;
                    break;

                case DhcpOptionCode.MaximumDhcpMessageSize:
                    _maximumDhcpMessageSize = option as MaximumDhcpMessageSizeOption;
                    break;

                case DhcpOptionCode.ServerIdentifier:
                    _serverIdentifier = option as ServerIdentifierOption;
                    break;

                case DhcpOptionCode.RequestedIpAddress:
                    _requestedIpAddress = option as RequestedIpAddressOption;
                    break;

                case DhcpOptionCode.OptionOverload:
                    _optionOverload = option as OptionOverloadOption;
                    break;
                }
            }
        }