Beispiel #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.");
            }
        }
Beispiel #2
0
        internal Lease(LeaseType type, ClientIdentifierOption clientIdentifier, string hostName, byte[] hardwareAddress, IPAddress address, uint leaseTime)
        {
            _type             = type;
            _clientIdentifier = clientIdentifier;
            _hostName         = hostName;
            _hardwareAddress  = hardwareAddress;
            _address          = address;
            _leaseObtained    = DateTime.UtcNow;

            ExtendLease(leaseTime);
        }
Beispiel #3
0
        internal Lease GetReservedLease(ClientIdentifierOption clientIdentifier)
        {
            if (_reservedLeases.TryGetValue(clientIdentifier, out Lease reservedLease))
            {
                //reserved address exists
                if (IsAddressAlreadyAllocated(reservedLease))
                {
                    return(null); //reserved lease address is already allocated so ignore reserved lease
                }
                return(reservedLease);
            }

            return(null);
        }
Beispiel #4
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.");
            }
        }
Beispiel #5
0
        public void ConvertToDynamicLease(HttpListenerRequest request)
        {
            string scopeName = request.QueryString["name"];

            if (string.IsNullOrEmpty(scopeName))
            {
                throw new DnsWebServiceException("Parameter 'name' missing.");
            }

            Scope scope = _dnsWebService.DhcpServer.GetScope(scopeName);

            if (scope == null)
            {
                throw new DnsWebServiceException("DHCP scope does not exists: " + scopeName);
            }

            string strClientIdentifier = request.QueryString["clientIdentifier"];
            string strHardwareAddress  = request.QueryString["hardwareAddress"];

            if (!string.IsNullOrEmpty(strClientIdentifier))
            {
                scope.ConvertToDynamicLease(ClientIdentifierOption.Parse(strClientIdentifier));
            }
            else if (!string.IsNullOrEmpty(strHardwareAddress))
            {
                scope.ConvertToDynamicLease(strHardwareAddress);
            }
            else
            {
                throw new DnsWebServiceException("Parameter 'hardwareAddress' or 'clientIdentifier' missing. At least one of them must be specified.");
            }

            _dnsWebService.DhcpServer.SaveScope(scopeName);

            _dnsWebService.Log.Write(DnsWebService.GetRequestRemoteEndPoint(request), "[" + _dnsWebService.GetSession(request).Username + "] DHCP scope's lease was unreserved successfully: " + scopeName);
        }
Beispiel #6
0
        internal Lease GetOffer(DhcpMessage request)
        {
            if (_leases.TryGetValue(request.ClientIdentifier, out Lease existingLease))
            {
                //lease already exists
                return(existingLease);
            }

            if (_reservedLeases != null)
            {
                ClientIdentifierOption clientIdentifierKey = new ClientIdentifierOption(1, request.ClientHardwareAddress);
                foreach (Lease reservedLease in _reservedLeases)
                {
                    if (reservedLease.ClientIdentifier.Equals(clientIdentifierKey))
                    {
                        //reserved address exists
                        IPAddress reservedLeaseAddress = reservedLease.Address;

                        if (!IsAddressAvailable(ref reservedLeaseAddress))
                        {
                            break; //reserved lease address is already allocated so ignore reserved lease
                        }
                        Lease reservedOffer = new Lease(LeaseType.Reserved, request.ClientIdentifier, request.HostName?.HostName, request.ClientHardwareAddress, reservedLease.Address, null, GetLeaseTime());

                        return(_offers.AddOrUpdate(request.ClientIdentifier, reservedOffer, delegate(ClientIdentifierOption key, Lease existingValue)
                        {
                            return reservedOffer;
                        }));
                    }
                }
            }

            if (_allowOnlyReservedLeases)
            {
                throw new DhcpServerException("DHCP Server failed to offer IP address to " + request.GetClientFullIdentifier() + ": scope allows only reserved lease allocations.");
            }

            Lease dummyOffer    = new Lease(LeaseType.None, null, null, null, null, null, 0);
            Lease existingOffer = _offers.GetOrAdd(request.ClientIdentifier, dummyOffer);

            if (dummyOffer != existingOffer)
            {
                if (existingOffer.Type == LeaseType.None)
                {
                    return(null); //dummy offer so another thread is handling offer; do nothing
                }
                //offer already exists
                existingOffer.ExtendLease(GetLeaseTime());

                return(existingOffer);
            }

            //find offer ip address
            IPAddress offerAddress = null;

            if (request.RequestedIpAddress != null)
            {
                //client wish to get this address
                IPAddress requestedAddress = request.RequestedIpAddress.Address;

                if (IsAddressInRange(requestedAddress) && IsAddressAvailable(ref requestedAddress))
                {
                    offerAddress = requestedAddress;
                }
            }

            if (offerAddress == null)
            {
                lock (_lastAddressOfferedLock)
                {
                    //find free address from scope
                    offerAddress = _lastAddressOffered;
                    uint endingAddressNumber         = _endingAddress.ConvertIpToNumber();
                    bool offerAddressWasResetFromEnd = false;

                    while (true)
                    {
                        uint nextOfferAddressNumber = offerAddress.ConvertIpToNumber() + 1u;

                        if (nextOfferAddressNumber > endingAddressNumber)
                        {
                            if (offerAddressWasResetFromEnd)
                            {
                                throw new DhcpServerException("DHCP Server failed to offer IP address to " + request.GetClientFullIdentifier() + ": address unavailable due to address pool exhaustion.");
                            }

                            offerAddress = IPAddressExtension.ConvertNumberToIp(_startingAddress.ConvertIpToNumber() - 1u);
                            offerAddressWasResetFromEnd = true;
                            continue;
                        }

                        offerAddress = IPAddressExtension.ConvertNumberToIp(nextOfferAddressNumber);

                        if (IsAddressAvailable(ref offerAddress))
                        {
                            break;
                        }
                    }

                    _lastAddressOffered = offerAddress;
                }
            }

            Lease offerLease = new Lease(LeaseType.Dynamic, request.ClientIdentifier, request.HostName?.HostName, request.ClientHardwareAddress, offerAddress, null, GetLeaseTime());

            return(_offers.AddOrUpdate(request.ClientIdentifier, offerLease, delegate(ClientIdentifierOption key, Lease existingValue)
            {
                return offerLease;
            }));
        }
Beispiel #7
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;
                }
            }
        }
Beispiel #8
0
        public DhcpMessage(Stream s)
        {
            byte[] buffer = new byte[4];

            s.ReadBytes(buffer, 0, 4);
            _op    = (DhcpMessageOpCode)buffer[0];
            _htype = (DhcpMessageHardwareAddressType)buffer[1];
            _hlen  = buffer[2];
            _hops  = buffer[3];

            _xid = s.ReadBytes(4);

            s.ReadBytes(buffer, 0, 4);
            _secs = new byte[2];
            Buffer.BlockCopy(buffer, 0, _secs, 0, 2);
            Array.Reverse(buffer);
            _flags = (DhcpMessageFlags)BitConverter.ToUInt16(buffer, 0);

            s.ReadBytes(buffer, 0, 4);
            _ciaddr = new IPAddress(buffer);

            s.ReadBytes(buffer, 0, 4);
            _yiaddr = new IPAddress(buffer);

            s.ReadBytes(buffer, 0, 4);
            _siaddr = new IPAddress(buffer);

            s.ReadBytes(buffer, 0, 4);
            _giaddr = new IPAddress(buffer);

            _chaddr = s.ReadBytes(16);
            _clientHardwareAddress = new byte[_hlen];
            Buffer.BlockCopy(_chaddr, 0, _clientHardwareAddress, 0, _hlen);

            _sname = s.ReadBytes(64);
            _file  = s.ReadBytes(128);

            //read options
            List <DhcpOption> options = new List <DhcpOption>();

            _options = options;

            s.ReadBytes(buffer, 0, 4);
            uint magicCookie = BitConverter.ToUInt32(buffer, 0);

            if (magicCookie == MAGIC_COOKIE)
            {
                ParseOptions(s, options);

                if (_optionOverload != null)
                {
                    if (_optionOverload.Value.HasFlag(OptionOverloadValue.FileFieldUsed))
                    {
                        using (MemoryStream mS = new MemoryStream(_file))
                        {
                            ParseOptions(mS, options);
                        }
                    }

                    if (_optionOverload.Value.HasFlag(OptionOverloadValue.SnameFieldUsed))
                    {
                        using (MemoryStream mS = new MemoryStream(_sname))
                        {
                            ParseOptions(mS, options);
                        }
                    }
                }

                //parse all option values
                foreach (DhcpOption option in options)
                {
                    option.ParseOptionValue();
                }
            }

            if (_clientIdentifier == null)
            {
                _clientIdentifier = new ClientIdentifierOption((byte)_htype, _clientHardwareAddress);
            }

            if (_maximumDhcpMessageSize != null)
            {
                _maximumDhcpMessageSize = new MaximumDhcpMessageSizeOption(576);
            }
        }