Example #1
0
        internal DHCPv6Packet HandleConfirm(DHCPv6Packet packet, IDHCPv6ServerPropertiesResolver properyResolver)
        {
            var addressProperties = GetAddressProperties();
            var innerPacket       = packet.GetInnerPacket();

            DUID   clientIdentifier            = innerPacket.GetClientIdentifer();
            UInt32?identityAssociationId       = innerPacket.GetNonTemporaryIdentityAssocationId();
            UInt32?prefixIdentityAsscocationId = innerPacket.GetPrefixDelegationIdentityAssocationId();

            DHCPv6Lease lease;

            if (identityAssociationId.HasValue == true)
            {
                lease = Leases.GetLeaseAssociationIdAndDuid(identityAssociationId.Value, clientIdentifier);
            }
            else
            {
                lease = Leases.GetLeaseByClientDuid(clientIdentifier);
            }

            if (lease == DHCPv6Lease.NotFound)
            {
                base.Apply(new DHCPv6ConfirmHandledEvent(this.Id, packet, DHCPv6ConfirmHandledEvent.ConfirmErrors.LeaseNotFound));
                return(DHCPv6Packet.Empty);
            }

            DHCPv6Packet response;

            if (lease.IsActive() == false)
            {
                response = DHCPv6Packet.AsError(packet, DHCPv6StatusCodes.NotOnLink, properyResolver.GetServerDuid());
                base.Apply(new DHCPv6ConfirmHandledEvent(this.Id, packet, response, DHCPv6ConfirmHandledEvent.ConfirmErrors.LeaseNotActive));
            }
            else
            {
                Boolean bindingVerified = true;
                if (identityAssociationId.HasValue == true)
                {
                    IPv6Address requestedAddress = innerPacket.GetNonTemporaryIdentiyAssocation(identityAssociationId.Value).GetAddress();
                    if (requestedAddress != lease.Address)
                    {
                        bindingVerified = false;
                    }
                }

                if (prefixIdentityAsscocationId.HasValue == true && bindingVerified == true)
                {
                    if ((prefixIdentityAsscocationId != lease.PrefixDelegation.IdentityAssociation))
                    {
                        bindingVerified = false;
                    }
                    else
                    {
                        DHCPv6PrefixDelegation requestedPrefix = innerPacket.GetPrefixDelegationIdentiyAssocation(prefixIdentityAsscocationId.Value).GetPrefixDelegation();
                        bindingVerified = requestedPrefix.AreValuesEqual(lease.PrefixDelegation);
                    }
                }

                if (bindingVerified == true)
                {
                    response = DHCPv6Packet.AsReply(packet, addressProperties, DHCPv6ScopeProperties.Empty, lease, true, properyResolver.GetServerDuid(), false);
                    base.Apply(new DHCPv6ConfirmHandledEvent(this.Id, packet, response));
                }
                else
                {
                    response = DHCPv6Packet.AsError(packet, DHCPv6StatusCodes.NotOnLink, properyResolver.GetServerDuid());
                    base.Apply(new DHCPv6ConfirmHandledEvent(this.Id, packet, response, DHCPv6ConfirmHandledEvent.ConfirmErrors.AddressMismtach));
                }
            }

            return(response);
        }
Example #2
0
        private DHCPv6Lease AddLease(DHCPv6Packet packet, DHCPv6ScopeAddressProperties addressProperties, DUID clientIdentifier, uint identityAssociationId, uint?prefixIdentityAsscocationId, DHCPv6Lease currentLease, IPv6Address leaseAddress, DHCPv6PrefixDelegation leasedPrefix)
        {
            LeaseTimeValues timers = GetLeaseTimers(addressProperties);

            currentLease = Leases.AddLease(
                Guid.NewGuid(),
                leaseAddress,
                timers.Lifespan,
                timers.RenewTime,
                timers.ReboundTime,
                identityAssociationId,
                clientIdentifier,
                Resolver.HasUniqueIdentifier == true ? Resolver.GetUniqueIdentifier(packet) : null,
                prefixIdentityAsscocationId.HasValue == false ? DHCPv6PrefixDelegation.None : leasedPrefix,
                currentLease);
            return(currentLease);
        }
Example #3
0
        private DHCPv6Packet HandleLeaseExtentions(DHCPv6Packet packet, IDHCPv6ServerPropertiesResolver properyResolver, out LeaseExtentionsErros extentionError)
        {
            var innerPacket       = packet.GetInnerPacket();
            var addressProperties = GetAddressProperties();

            DUID        clientIdentifier            = innerPacket.GetClientIdentifer();
            UInt32?     identityAssociationId       = innerPacket.GetNonTemporaryIdentityAssocationId();
            UInt32?     prefixIdentityAsscocationId = innerPacket.GetPrefixDelegationIdentityAssocationId();
            DHCPv6Lease lease;

            if (identityAssociationId.HasValue == false && prefixIdentityAsscocationId.HasValue == true)
            {
                DHCPv6Lease belongingLease = Leases.GetLeaseByClientDuid(clientIdentifier);
                if (belongingLease == DHCPv6Lease.NotFound)
                {
                    extentionError = LeaseExtentionsErros.OnlyPrefixIsNotAllowed;
                    return(DHCPv6Packet.AsError(packet, DHCPv6StatusCodes.NoBinding, properyResolver.GetServerDuid()));
                }

                // In some client implementations like Cisco IOS XE, two renew packets are sent, one for an address and a second for a prefix.
                // Unfortunately, if the PD is sent first, the lease is not extented. So... we just wait a second and hopefully than the lease is ready
                Task.Delay(1000).GetAwaiter().GetResult();
                lease = Leases.GetLeaseByClientDuid(clientIdentifier);
            }
            else
            {
                lease = Leases.GetLeaseAssociationIdAndDuid(identityAssociationId.Value, clientIdentifier);
            }

            DHCPv6Packet response = null;

            extentionError = LeaseExtentionsErros.NoError;
            if (lease == DHCPv6Lease.NotFound)
            {
                response       = DHCPv6Packet.AsError(packet, DHCPv6StatusCodes.NoBinding, properyResolver.GetServerDuid());
                extentionError = LeaseExtentionsErros.LeaseNotFound;
            }
            else
            {
                DHCPv6Lease leaseUsedToGenerateResponse = null;
                if (addressProperties.ReuseAddressIfPossible == true && lease.CanBeExtended() == true)
                {
                    var     tempDelegation = lease.PrefixDelegation;
                    Boolean resetPrefix    = false;
                    if (prefixIdentityAsscocationId.HasValue == false && tempDelegation != DHCPv6PrefixDelegation.None)
                    {
                        resetPrefix = true;
                        AddNotificationTrigger(
                            PrefixEdgeRouterBindingUpdatedTrigger.WithOldBinding(Id,
                                                                                 PrefixBinding.FromLease(lease)));
                    }
                    else if (tempDelegation == DHCPv6PrefixDelegation.None && prefixIdentityAsscocationId.HasValue == true)
                    {
                        var prefix = addressProperties.GetValidPrefix(Leases.GetUsedPrefixes(), prefixIdentityAsscocationId.Value, lease.PrefixDelegation.NetworkAddress);
                        lease.UpdateAddressPrefix(prefix, false);
                        AddNotificationTrigger(
                            PrefixEdgeRouterBindingUpdatedTrigger.WithNewBinding(Id,
                                                                                 PrefixBinding.FromLease(lease)));
                    }

                    if (identityAssociationId.HasValue == true)
                    {
                        var timers = GetLeaseTimers(addressProperties);

                        lease.Renew(timers.Lifespan, timers.RenewTime, timers.ReboundTime, false, resetPrefix);
                    }

                    leaseUsedToGenerateResponse = lease;
                }
                else
                {
                    if ((identityAssociationId.HasValue == true && IsFreshLease(lease) == true) ||
                        (prefixIdentityAsscocationId.HasValue == true && IsFreshPrefix(lease) == true))
                    {
                        leaseUsedToGenerateResponse = lease;
                    }
                    else
                    {
                        PrefixBinding oldBinding = null;
                        PrefixBinding newBinding = null;

                        if (lease.PrefixDelegation != DHCPv6PrefixDelegation.None)
                        {
                            oldBinding = PrefixBinding.FromLease(lease);
                        }

                        if (lease.AddressIsInUse() == true && identityAssociationId.HasValue == true)
                        {
                            Leases.Revoke(lease);
                        }

                        IPv6Address leaseAddress = identityAssociationId.HasValue == true?GetLeasedAddress(addressProperties, lease.Address) : lease.Address;

                        DHCPv6PrefixDelegation leasedPrefix = DHCPv6PrefixDelegation.None;
                        if (prefixIdentityAsscocationId.HasValue == true)
                        {
                            leasedPrefix = addressProperties.GetValidPrefix(Leases.GetUsedPrefixes(), prefixIdentityAsscocationId.Value, lease.PrefixDelegation.NetworkAddress);
                            newBinding   = new PrefixBinding(leasedPrefix.NetworkAddress, leasedPrefix.Mask, leaseAddress);
                            if (identityAssociationId.HasValue == false)
                            {
                                lease.UpdateAddressPrefix(leasedPrefix, false);
                            }
                        }

                        if (leaseAddress == IPv6Address.Empty)
                        {
                            base.Apply(new DHCPv6ScopeAddressesAreExhaustedEvent(Id));
                            AddNotificationTrigger(PrefixEdgeRouterBindingUpdatedTrigger.WithOldBinding(Id, oldBinding));
                            response       = DHCPv6Packet.AsError(packet, DHCPv6StatusCodes.NoAddrsAvail, properyResolver.GetServerDuid());
                            extentionError = LeaseExtentionsErros.NoAddressAvailaibe;
                        }
                        else
                        {
                            leaseUsedToGenerateResponse = identityAssociationId.HasValue == false ? lease :
                                                          AddLease(packet, addressProperties, clientIdentifier, identityAssociationId.Value, prefixIdentityAsscocationId, lease, leaseAddress, leasedPrefix);

                            /*
                             *  Leases.AddLease(
                             * Guid.NewGuid(),
                             * leaseAddress,
                             * addressProperties.ValidLeaseTime.Value,
                             * addressProperties.T1.Value * addressProperties.ValidLeaseTime.Value,
                             * addressProperties.T2.Value * addressProperties.ValidLeaseTime.Value,
                             * identityAssociationId.Value,
                             * clientIdentifier,
                             * Resolver.HasUniqueIdentifier == true ? Resolver.GetUniqueIdentifier(packet) : null,
                             * prefixIdentityAsscocationId.HasValue == false ? DHCPv6PrefixDelegation.None : leasedPrefix,
                             * lease
                             * )
                             */

                            if (identityAssociationId.HasValue == true)
                            {
                                leaseUsedToGenerateResponse.RemovePendingState();
                            }

                            if (newBinding != null || oldBinding != null && oldBinding != newBinding)
                            {
                                AddNotificationTrigger(new PrefixEdgeRouterBindingUpdatedTrigger(oldBinding, newBinding, Id));
                            }
                        }
                    }
                }

                if (extentionError == LeaseExtentionsErros.NoError)
                {
                    response = DHCPv6Packet.AsReply(packet, addressProperties, GetScopeProperties(), leaseUsedToGenerateResponse, false, properyResolver.GetServerDuid(), false);
                }
            }

            return(response);
        }
Example #4
0
        internal DHCPv6Packet HandleSolicit(DHCPv6Packet packet, IDHCPv6ServerPropertiesResolver properyResolver)
        {
            DHCPv6Packet innerPacket = packet.GetInnerPacket();

            var     addressProperties = GetAddressProperties();
            Boolean rapitCommit       = addressProperties.IsRapitCommitEnabled() && innerPacket.HasRapitCommitOption();

            DUID   clientIdentifier            = innerPacket.GetClientIdentifer();
            UInt32 identityAssociationId       = innerPacket.GetNonTemporaryIdentityAssocationId().Value;
            UInt32?prefixIdentityAsscocationId = innerPacket.GetPrefixDelegationIdentityAssocationId();

            DHCPv6Lease currentLease = Leases.GetLeaseAssociationIdAndDuid(identityAssociationId, clientIdentifier);

            if (currentLease == null && Resolver.HasUniqueIdentifier)
            {
                currentLease = Leases.GetLeaseByUniqueIdentifier(Resolver.GetUniqueIdentifier(packet));
            }

            IPv6Address excludeFromLease  = IPv6Address.Empty;
            IPv6Address excludeFromPrefix = IPv6Address.Empty;

            IPv6Address            leaseAddress = IPv6Address.Empty;
            DHCPv6PrefixDelegation leasedPrefix = DHCPv6PrefixDelegation.None;

            Boolean skipLeaseCreation = false;

            if (currentLease != DHCPv6Lease.NotFound)
            {
                _logger.LogDebug("active lease found for client {duid} and {iaid}", clientIdentifier, identityAssociationId);

                if (IsFreshLease(currentLease) == true)
                {
                    _logger.LogInformation("a fresh lease found.  Skipping creating of a new lease");
                    skipLeaseCreation = true;
                }
                else
                {
                    if (addressProperties.ReuseAddressIfPossible == true && currentLease.CanBeExtended() == true)
                    {
                        leaseAddress = currentLease.Address;
                        leasedPrefix = currentLease.PrefixDelegation;
                    }
                    else
                    {
                        if (currentLease.IsActive() == true || currentLease.IsPending() == true)
                        {
                            excludeFromLease  = IPv6Address.FromByteArray(currentLease.Address.GetBytes());
                            excludeFromPrefix = currentLease.PrefixDelegation.NetworkAddress;
                        }
                    }
                }
            }

            if (skipLeaseCreation == false)
            {
                if (leaseAddress == IPv6Address.Empty)
                {
                    leaseAddress = GetLeasedAddress(addressProperties, excludeFromLease);

                    if (leaseAddress == IPv6Address.Empty)
                    {
                        _logger.LogError("{scope} has no ip addresses left", Name);
                        base.Apply(new DHCPv6ScopeAddressesAreExhaustedEvent(Id));
                        base.Apply(new DHCPv6SolicitHandledEvent(this.Id, packet, DHCPv6SolicitHandledEvent.SolicitErros.NoAddressesLeft));
                        return(DHCPv6Packet.Empty);
                    }
                }

                if (prefixIdentityAsscocationId.HasValue == true && leasedPrefix == DHCPv6PrefixDelegation.None)
                {
                    leasedPrefix = addressProperties.GetValidPrefix(Leases.GetUsedPrefixes(), prefixIdentityAsscocationId.Value, excludeFromPrefix);
                }

                currentLease = AddLease(packet, addressProperties, clientIdentifier, identityAssociationId, prefixIdentityAsscocationId, currentLease, leaseAddress, leasedPrefix);
            }

            DHCPv6Packet response;

            if (rapitCommit == true)
            {
                response = HandleRequestInternal(packet, properyResolver, true, out DHCPv6RequestHandledEvent.RequestErrors _, skipLeaseCreation);
            }
            else
            {
                response = DHCPv6Packet.AsAdvertise(
                    packet,
                    currentLease,
                    prefixIdentityAsscocationId.HasValue == false ? DHCPv6PrefixDelegation.None : leasedPrefix,
                    addressProperties,
                    GetScopeProperties(),
                    properyResolver.GetServerDuid());
            }

            base.Apply(new DHCPv6SolicitHandledEvent(this.Id, packet, response, rapitCommit));
            return(response);
        }