Пример #1
0
        private void ProcessUdpRequestAsync(object parameter)
        {
            object[] parameters = parameter as object[];

            Socket              udpListener         = parameters[0] as Socket;
            EndPoint            remoteEP            = parameters[1] as EndPoint;
            IPPacketInformation ipPacketInformation = (IPPacketInformation)parameters[2];
            DhcpMessage         request             = parameters[3] as DhcpMessage;

            try
            {
                DhcpMessage response = ProcessDhcpMessage(request, remoteEP as IPEndPoint, ipPacketInformation);

                //send response
                if (response != null)
                {
                    byte[]       sendBuffer       = new byte[1024];
                    MemoryStream sendBufferStream = new MemoryStream(sendBuffer);

                    response.WriteTo(sendBufferStream);

                    //send dns datagram
                    if (!request.RelayAgentIpAddress.Equals(IPAddress.Any))
                    {
                        //received request via relay agent so send unicast response to relay agent on port 67
                        udpListener.SendTo(sendBuffer, 0, (int)sendBufferStream.Position, SocketFlags.None, new IPEndPoint(request.RelayAgentIpAddress, 67));
                    }
                    else if (!request.ClientIpAddress.Equals(IPAddress.Any))
                    {
                        //client is already configured and renewing lease so send unicast response on port 68
                        udpListener.SendTo(sendBuffer, 0, (int)sendBufferStream.Position, SocketFlags.None, new IPEndPoint(request.ClientIpAddress, 68));
                    }
                    else
                    {
                        //send response as broadcast on port 68 on appropriate interface bound socket
                        if (!_udpListeners.TryGetValue(response.NextServerIpAddress, out Socket udpSocket))
                        {
                            udpSocket = udpListener;                                                                                                     //no appropriate socket found so use default socket
                        }
                        udpSocket.SendTo(sendBuffer, 0, (int)sendBufferStream.Position, SocketFlags.DontRoute, new IPEndPoint(IPAddress.Broadcast, 68)); //no routing for broadcast
                    }
                }
            }
            catch (ObjectDisposedException)
            {
                //socket disposed
            }
            catch (Exception ex)
            {
                if ((_state == ServiceState.Stopping) || (_state == ServiceState.Stopped))
                {
                    return; //server stopping
                }
                LogManager log = _log;
                if (log != null)
                {
                    log.Write(remoteEP as IPEndPoint, ex);
                }
            }
        }
Пример #2
0
        private async Task ProcessDhcpRequestAsync(DhcpMessage request, IPEndPoint remoteEP, IPPacketInformation ipPacketInformation, Socket udpListener)
        {
            try
            {
                DhcpMessage response = await ProcessDhcpMessageAsync(request, remoteEP, ipPacketInformation);

                //send response
                if (response != null)
                {
                    byte[]       sendBuffer       = new byte[1024];
                    MemoryStream sendBufferStream = new MemoryStream(sendBuffer);

                    response.WriteTo(sendBufferStream);

                    //send dns datagram
                    if (!request.RelayAgentIpAddress.Equals(IPAddress.Any))
                    {
                        //received request via relay agent so send unicast response to relay agent on port 67
                        await udpListener.SendToAsync(sendBuffer, 0, (int)sendBufferStream.Position, new IPEndPoint(request.RelayAgentIpAddress, 67));
                    }
                    else if (!request.ClientIpAddress.Equals(IPAddress.Any))
                    {
                        //client is already configured and renewing lease so send unicast response on port 68
                        await udpListener.SendToAsync(sendBuffer, 0, (int)sendBufferStream.Position, new IPEndPoint(request.ClientIpAddress, 68));
                    }
                    else
                    {
                        Socket udpSocket;

                        //send response as broadcast on port 68 on appropriate interface bound socket
                        if (_udpListeners.TryGetValue(response.NextServerIpAddress, out UdpListener listener))
                        {
                            udpSocket = listener.Socket; //found scope specific socket
                        }
                        else
                        {
                            udpSocket = udpListener;                                                                                                                //no appropriate socket found so use default socket
                        }
                        await udpSocket.SendToAsync(sendBuffer, 0, (int)sendBufferStream.Position, new IPEndPoint(IPAddress.Broadcast, 68), SocketFlags.DontRoute); //no routing for broadcast
                    }
                }
            }
            catch (ObjectDisposedException)
            {
                //socket disposed
            }
            catch (Exception ex)
            {
                if ((_state == ServiceState.Stopping) || (_state == ServiceState.Stopped))
                {
                    return; //server stopping
                }
                LogManager log = _log;
                if (log != null)
                {
                    log.Write(remoteEP, ex);
                }
            }
        }
Пример #3
0
        private Scope FindScope(DhcpMessage request, IPAddress remoteAddress, IPPacketInformation ipPacketInformation)
        {
            bool broadcast;

            if (request.RelayAgentIpAddress.Equals(IPAddress.Any))
            {
                //no relay agent
                if (request.ClientIpAddress.Equals(IPAddress.Any))
                {
                    if (!ipPacketInformation.Address.Equals(IPAddress.Broadcast))
                    {
                        return(null); //message destination address must be broadcast address
                    }
                    broadcast = true; //broadcast request
                }
                else
                {
                    if (!remoteAddress.Equals(request.ClientIpAddress))
                    {
                        return(null);  //client ip must match udp src addr
                    }
                    broadcast = false; //unicast request
                }
            }
            else
            {
                //relay agent unicast

                if (!remoteAddress.Equals(request.RelayAgentIpAddress))
                {
                    return(null);  //relay ip must match udp src addr
                }
                broadcast = false; //unicast request
            }

            if (broadcast)
            {
                foreach (KeyValuePair <string, Scope> scope in _scopes)
                {
                    if (scope.Value.Enabled && (scope.Value.InterfaceIndex == ipPacketInformation.Interface))
                    {
                        return(scope.Value);
                    }
                }
            }
            else
            {
                foreach (KeyValuePair <string, Scope> scope in _scopes)
                {
                    if (scope.Value.Enabled && (scope.Value.IsAddressInRange(remoteAddress)))
                    {
                        return(scope.Value);
                    }
                }
            }

            return(null);
        }
Пример #4
0
        internal Lease GetExistingLeaseOrOffer(DhcpMessage request)
        {
            if (_leases.TryGetValue(request.ClientIdentifier, out Lease existingLease))
            {
                return(existingLease);
            }

            if (_offers.TryGetValue(request.ClientIdentifier, out Lease existingOffer))
            {
                return(existingOffer);
            }

            return(null);
        }
Пример #5
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);
            }
        }
Пример #6
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);
        }
Пример #7
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;
            }));
        }
Пример #8
0
        private ClientFullyQualifiedDomainNameOption GetClientFullyQualifiedDomainNameOption(DhcpMessage request)
        {
            ClientFullyQualifiedDomainNameFlags responseFlags = ClientFullyQualifiedDomainNameFlags.None;

            if (request.ClientFullyQualifiedDomainName.Flags.HasFlag(ClientFullyQualifiedDomainNameFlags.EncodeUsingCanonicalWireFormat))
            {
                responseFlags |= ClientFullyQualifiedDomainNameFlags.EncodeUsingCanonicalWireFormat;
            }

            if (request.ClientFullyQualifiedDomainName.Flags.HasFlag(ClientFullyQualifiedDomainNameFlags.NoDnsUpdate))
            {
                responseFlags |= ClientFullyQualifiedDomainNameFlags.ShouldUpdateDns;
                responseFlags |= ClientFullyQualifiedDomainNameFlags.OverrideByServer;
            }
            else if (request.ClientFullyQualifiedDomainName.Flags.HasFlag(ClientFullyQualifiedDomainNameFlags.ShouldUpdateDns))
            {
                responseFlags |= ClientFullyQualifiedDomainNameFlags.ShouldUpdateDns;
            }
            else
            {
                responseFlags |= ClientFullyQualifiedDomainNameFlags.ShouldUpdateDns;
                responseFlags |= ClientFullyQualifiedDomainNameFlags.OverrideByServer;
            }

            string clientDomainName;

            if (string.IsNullOrWhiteSpace(request.ClientFullyQualifiedDomainName.DomainName))
            {
                //client domain empty and expects server for a fqdn domain name
                if (request.HostName == null)
                {
                    return(null); //server unable to decide a name for client
                }
                clientDomainName = request.HostName.HostName + "." + _domainName;
            }
            else if (request.ClientFullyQualifiedDomainName.DomainName.Contains("."))
            {
                //client domain is fqdn
                if (request.ClientFullyQualifiedDomainName.DomainName.EndsWith("." + _domainName, StringComparison.OrdinalIgnoreCase))
                {
                    clientDomainName = request.ClientFullyQualifiedDomainName.DomainName;
                }
                else
                {
                    string[] parts = request.ClientFullyQualifiedDomainName.DomainName.Split('.');
                    clientDomainName = parts[0] + "." + _domainName;
                }
            }
            else
            {
                //client domain is just hostname
                clientDomainName = request.ClientFullyQualifiedDomainName.DomainName + "." + _domainName;
            }

            return(new ClientFullyQualifiedDomainNameOption(responseFlags, 255, 255, clientDomainName));
        }
Пример #9
0
        private Scope FindScope(DhcpMessage request, IPAddress remoteAddress, IPPacketInformation ipPacketInformation)
        {
            if (request.RelayAgentIpAddress.Equals(IPAddress.Any))
            {
                //no relay agent
                if (request.ClientIpAddress.Equals(IPAddress.Any))
                {
                    if (!ipPacketInformation.Address.Equals(IPAddress.Broadcast))
                    {
                        return(null); //message destination address must be broadcast address
                    }
                    //broadcast request
                    Scope foundScope = null;

                    foreach (Scope scope in _scopes.Values)
                    {
                        if (scope.Enabled && (scope.InterfaceIndex == ipPacketInformation.Interface))
                        {
                            if (scope.GetReservedLease(request) != null)
                            {
                                return(scope); //found reserved lease on this scope
                            }
                            if ((foundScope == null) && !scope.AllowOnlyReservedLeases)
                            {
                                foundScope = scope;
                            }
                        }
                    }

                    return(foundScope);
                }
                else
                {
                    if (!remoteAddress.Equals(request.ClientIpAddress))
                    {
                        return(null); //client ip must match udp src addr
                    }
                    //unicast request
                    foreach (Scope scope in _scopes.Values)
                    {
                        if (scope.Enabled && scope.IsAddressInRange(remoteAddress))
                        {
                            return(scope);
                        }
                    }

                    return(null);
                }
            }
            else
            {
                //relay agent unicast
                Scope foundScope = null;

                foreach (Scope scope in _scopes.Values)
                {
                    if (scope.Enabled && scope.InterfaceAddress.Equals(IPAddress.Any))
                    {
                        if (scope.GetReservedLease(request) != null)
                        {
                            return(scope); //found reserved lease on this scope
                        }
                        if (!request.ClientIpAddress.Equals(IPAddress.Any) && scope.IsAddressInRange(request.ClientIpAddress))
                        {
                            foundScope = scope; //client IP address is in scope range
                        }
                        else if ((foundScope == null) && scope.IsAddressInRange(request.RelayAgentIpAddress))
                        {
                            foundScope = scope; //relay agent IP address is in scope range
                        }
                    }
                }

                return(foundScope);
            }
        }
Пример #10
0
        private void ReadUdpRequestAsync(object parameter)
        {
            Socket   udpListener = parameter as Socket;
            EndPoint remoteEP    = new IPEndPoint(IPAddress.Any, 0);

            byte[] recvBuffer = new byte[576];
            int    bytesRecv;

            try
            {
                bool processOnlyUnicastMessages = !(udpListener.LocalEndPoint as IPEndPoint).Address.Equals(IPAddress.Any); //only 0.0.0.0 ip should process broadcast to avoid duplicate offers on Windows

                while (true)
                {
                    SocketFlags         flags = SocketFlags.None;
                    IPPacketInformation ipPacketInformation;

                    try
                    {
                        bytesRecv = udpListener.ReceiveMessageFrom(recvBuffer, 0, recvBuffer.Length, ref flags, ref remoteEP, out ipPacketInformation);
                    }
                    catch (SocketException ex)
                    {
                        switch (ex.SocketErrorCode)
                        {
                        case SocketError.ConnectionReset:
                        case SocketError.HostUnreachable:
                        case SocketError.MessageSize:
                        case SocketError.NetworkReset:
                            bytesRecv = 0;
                            break;

                        default:
                            throw;
                        }
                    }

                    if (bytesRecv > 0)
                    {
                        if (processOnlyUnicastMessages && ipPacketInformation.Address.Equals(IPAddress.Broadcast))
                        {
                            continue;
                        }

                        try
                        {
                            DhcpMessage request = new DhcpMessage(new MemoryStream(recvBuffer, 0, bytesRecv, false));
                            _ = ProcessDhcpRequestAsync(request, remoteEP as IPEndPoint, ipPacketInformation, udpListener);
                        }
                        catch (Exception ex)
                        {
                            LogManager log = _log;
                            if (log != null)
                            {
                                log.Write(remoteEP as IPEndPoint, ex);
                            }
                        }
                    }
                }
            }
            catch (ObjectDisposedException)
            {
                //socket disposed
            }
            catch (SocketException ex)
            {
                switch (ex.SocketErrorCode)
                {
                case SocketError.Interrupted:
                    break;     //server stopping

                default:
                    LogManager log = _log;
                    if (log != null)
                    {
                        log.Write(remoteEP as IPEndPoint, ex);
                    }

                    throw;
                }
            }
            catch (Exception ex)
            {
                if ((_state == ServiceState.Stopping) || (_state == ServiceState.Stopped))
                {
                    return; //server stopping
                }
                LogManager log = _log;
                if (log != null)
                {
                    log.Write(remoteEP as IPEndPoint, ex);
                }

                throw;
            }
        }
Пример #11
0
 public DhcpMessage(DhcpMessage request, IPAddress yiaddr, IPAddress siaddr, IReadOnlyCollection <DhcpOption> options)
     : this(DhcpMessageOpCode.BootReply, request.TransactionId, request.SecondsElapsed, request.Flags, request.ClientIpAddress, yiaddr, siaddr, request.RelayAgentIpAddress, request.ClientHardwareAddress, options)
 {
 }
Пример #12
0
 public static DhcpMessage CreateReply(DhcpMessage request, IPAddress yiaddr, IPAddress siaddr, string sname, string file, IReadOnlyCollection <DhcpOption> options)
 {
     return(new DhcpMessage(DhcpMessageOpCode.BootReply, request.HardwareAddressType, request.TransactionId, request.SecondsElapsed, request.Flags, request.ClientIpAddress, yiaddr, siaddr, request.RelayAgentIpAddress, request.ClientHardwareAddress, sname, file, options));
 }
Пример #13
0
 internal Lease GetReservedLease(DhcpMessage request)
 {
     return(GetReservedLease(new ClientIdentifierOption((byte)request.HardwareAddressType, request.ClientHardwareAddress)));
 }