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