internal DHCPv6Packet HandleRelease(DHCPv6Packet packet, IDHCPv6ServerPropertiesResolver properyResolver) { var innerPacket = packet.GetInnerPacket(); DUID clientIdentifier = innerPacket.GetClientIdentifer(); UInt32?identityAssociationId = innerPacket.GetNonTemporaryIdentityAssocationId(); UInt32?prefixIdentityAssociationId = innerPacket.GetPrefixDelegationIdentityAssocationId(); DHCPv6Lease lease = DHCPv6Lease.NotFound; if (identityAssociationId.HasValue == true) { lease = Leases.GetLeaseAssociationIdAndDuid(identityAssociationId.Value, clientIdentifier); } else { var tempLease = Leases.GetLeaseByClientDuid(clientIdentifier); if (tempLease.PrefixDelegation != DHCPv6PrefixDelegation.None && tempLease.PrefixDelegation.IdentityAssociation == prefixIdentityAssociationId.Value ) { lease = tempLease; } } DHCPv6Packet response; var error = DHCPv6ReleaseHandledEvent.ReleaseError.NoError; if (lease == DHCPv6Lease.NotFound) { response = DHCPv6Packet.AsError(packet, DHCPv6StatusCodes.NoBinding, properyResolver.GetServerDuid()); error = DHCPv6ReleaseHandledEvent.ReleaseError.NoLeaseFound; } else { if (lease.IsActive() == false) { response = DHCPv6Packet.AsError(packet, DHCPv6StatusCodes.NoBinding, properyResolver.GetServerDuid()); } else { PrefixBinding prefixBinding = lease.PrefixDelegation != DHCPv6PrefixDelegation.None ? PrefixBinding.FromLease(lease) : null; lease.Release(identityAssociationId.HasValue == false); Leases.Remove(lease); response = DHCPv6Packet.AsReleaseResponse(packet, lease.IdentityAssocicationId, lease.PrefixDelegation.IdentityAssociation, properyResolver.GetServerDuid()); if (prefixBinding != null) { AddNotificationTrigger(PrefixEdgeRouterBindingUpdatedTrigger.WithOldBinding( Id, prefixBinding)); } } } base.Apply(new DHCPv6ReleaseHandledEvent(this.Id, packet, response, error)); return(response); }
public void GetTypeIdentifier() { var trigger = PrefixEdgeRouterBindingUpdatedTrigger.NoChanges(Guid.Empty); var identifier = trigger.GetTypeIdentifier(); Assert.Equal("PrefixEdgeRouterBindingUpdatedTrigger", identifier); }
public async Task IsValid_False_NoDirectMeber_AndNotChild() { Random random = new Random(); var condition = GetConditionWithScopeTree(random, out Guid _); var trigger = PrefixEdgeRouterBindingUpdatedTrigger.NoChanges(random.NextGuid()); Boolean actual = await condition.IsValid(trigger); Assert.False(actual); }
public async Task IsValid_True_NoDirectMeber_ButFoundAsChild() { Random random = new Random(); var condition = GetConditionWithScopeTree(random, out Guid childId); var trigger = PrefixEdgeRouterBindingUpdatedTrigger.NoChanges(childId); Boolean actual = await condition.IsValid(trigger); Assert.True(actual); }
public async Task IsValid_False_NoChildScopes() { Random random = new Random(); var condition = GetCondition(random, false, out _); var trigger = PrefixEdgeRouterBindingUpdatedTrigger.NoChanges(random.NextGuid()); Boolean actual = await condition.IsValid(trigger); Assert.False(actual); }
public void NoChanges() { Random random = new Random(); Guid guid = random.NextGuid(); var trigger = PrefixEdgeRouterBindingUpdatedTrigger.NoChanges(guid); Assert.NotNull(trigger); Assert.Equal(guid, trigger.ScopeId); Assert.Null(trigger.NewBinding); Assert.Null(trigger.OldBinding); }
public async Task IsValid_True_IdIsDirectMember() { Random random = new Random(); var condition = GetCondition(random, false, out IEnumerable <Guid> scopeIds); Guid scopeId = scopeIds.ElementAt(random.Next(0, scopeIds.Count())); var trigger = PrefixEdgeRouterBindingUpdatedTrigger.NoChanges(scopeId); Boolean actual = await condition.IsValid(trigger); Assert.True(actual); }
protected internal override void ProcessExpiredLeases(IEnumerable <DHCPv6Lease> expiredLeases) { foreach (var item in expiredLeases) { if (item.PrefixDelegation != DHCPv6PrefixDelegation.None) { AddNotificationTrigger(PrefixEdgeRouterBindingUpdatedTrigger.WithOldBinding( Id, PrefixBinding.FromLease(item))); } } base.ProcessExpiredLeases(expiredLeases); }
public void WithOldBinding() { Random random = new Random(); Guid guid = random.NextGuid(); PrefixBinding prefixBinding = new PrefixBinding( IPv6Address.FromString("fe80:1:2::0"), new IPv6SubnetMask(new IPv6SubnetMaskIdentifier(62)), IPv6Address.FromString("fe80:FF:2::3")); var trigger = PrefixEdgeRouterBindingUpdatedTrigger.WithOldBinding(guid, prefixBinding); Assert.NotNull(trigger); Assert.Equal(guid, trigger.ScopeId); Assert.Equal(prefixBinding, trigger.OldBinding); Assert.Null(trigger.NewBinding); }
public override Boolean UpdateAddressProperties(Guid id, DHCPv6ScopeAddressProperties addressProperties) { CheckUpdateAddressProperties(id, addressProperties); var leases = GetScopeById(id).Leases.GetAllLeasesNotInRange(addressProperties.Start, addressProperties.End); base.Apply(new DHCPv6ScopeAddressPropertiesUpdatedEvent(id, addressProperties)); foreach (var item in leases) { if (item.PrefixDelegation != DHCPv6PrefixDelegation.None) { AddTrigger(PrefixEdgeRouterBindingUpdatedTrigger.WithOldBinding(id, PrefixBinding.FromLease(item))); } base.Apply(new DHCPv6LeaseCanceledEvent(item.Id, id, LeaseCancelReasons.AddressRangeChanged)); } return(true); }
public async Task FullCycle() { Random random = new Random(); String dbName = $"{random.Next()}"; String eventStorePrefix = random.GetAlphanumericString(); var serviceInteractions = GetTestClient(dbName, eventStorePrefix); Guid scopeId = Guid.Parse("7ec8da2e-73a8-4205-9dd8-9bde4be5434a"); try { var firstResponse = await serviceInteractions.Client.PostAsync("/api/notifications/pipelines/", GetContent(new { name = "my first pipeline", description = "my first pipeline description", triggerName = "PrefixEdgeRouterBindingUpdatedTrigger", condtionName = "DHCPv6ScopeIdNotificationCondition", conditionProperties = new Dictionary <String, String> { { "includesChildren", JsonConvert.SerializeObject(true) }, { "scopeIds", JsonConvert.SerializeObject(new[] { scopeId }) } }, actorName = "NxOsStaticRouteUpdaterNotificationActor", actorProperties = new Dictionary <String, String> { { "url", "https://192.168.1.1" }, { "username", "5353535" }, { "password", "36363636" } }, })); Guid firstId = await IsObjectResult <Guid>(firstResponse); Assert.NotEqual(Guid.Empty, firstId); var secondResponse = await serviceInteractions.Client.PostAsync("/api/notifications/pipelines/", GetContent(new { name = "my second pipeline", description = "my second pipeline description", triggerName = "PrefixEdgeRouterBindingUpdatedTrigger", condtionName = "DHCPv6ScopeIdNotificationCondition", conditionProperties = new Dictionary <String, String> { { "includesChildren", JsonConvert.SerializeObject(true) }, { "scopeIds", JsonConvert.SerializeObject(new[] { scopeId }) } }, actorName = "NxOsStaticRouteUpdaterNotificationActor", actorProperties = new Dictionary <String, String> { { "url", "https://192.168.1.1" }, { "username", "5353535" }, { "password", "36363636" } }, })); Guid secondId = await IsObjectResult <Guid>(secondResponse); Assert.NotEqual(Guid.Empty, secondId); var thirdresponse = await serviceInteractions.Client.DeleteAsync($"/api/notifications/pipelines/{firstId}"); await IsEmptyResult(thirdresponse); serviceInteractions.Client.Dispose(); serviceInteractions = GetTestClient(dbName, eventStorePrefix); var resultResponse = await serviceInteractions.Client.GetAsync("/api/notifications/pipelines/"); var result = await IsObjectResult <IEnumerable <NotificationPipelineReadModel> >(resultResponse); Assert.Single(result); Assert.Equal(secondId, result.First().Id); var newPrefix = new PrefixBinding(IPv6Address.FromString("fe80:1000::"), new IPv6SubnetMaskIdentifier(32), IPv6Address.FromString("fe80::2")); var actorServiceMock = serviceInteractions.ActorServiceMock; Int32 actorFired = 0;; actorServiceMock.Setup(x => x.Connect("https://192.168.1.1", "5353535", "36363636")).ReturnsAsync(true).Verifiable(); actorServiceMock.Setup(x => x.AddIPv6StaticRoute(newPrefix.Prefix, newPrefix.Mask.Identifier, newPrefix.Host)).ReturnsAsync(true).Callback(() => actorFired++).Verifiable(); await serviceInteractions.ServiceBus.Publish(new NewTriggerHappendMessage(new[] { PrefixEdgeRouterBindingUpdatedTrigger.WithNewBinding(scopeId, newPrefix) })); Int32 triesLeft = 10; while (triesLeft-- > 0) { await Task.Delay(1000); if (actorFired > 0) { break; } } actorServiceMock.Verify(); } finally { await EventStoreClientDisposer.CleanUp(eventStorePrefix, null); await DatabaseTestingUtility.DeleteDatabase(dbName); } }
public async Task Handle(Boolean oldPrefixHasValue, Boolean newPrefixHasValue) { Random random = new Random(); String address = "https://" + random.GetIPv4Address().ToString() + ":8081"; String username = random.GetAlphanumericString(); String password = random.GetAlphanumericString(); PrefixBinding oldPrefix = new PrefixBinding(IPv6Address.FromString("2cff:34::0"), new IPv6SubnetMask(new IPv6SubnetMaskIdentifier(38)), IPv6Address.FromString("fe80::2")); PrefixBinding newPrefix = new PrefixBinding(IPv6Address.FromString("1cff:50::0"), new IPv6SubnetMask(new IPv6SubnetMaskIdentifier(38)), IPv6Address.FromString("fe80::CC")); Guid scopeId = random.NextGuid(); PrefixEdgeRouterBindingUpdatedTrigger trigger; if (newPrefixHasValue == true && oldPrefixHasValue == true) { trigger = PrefixEdgeRouterBindingUpdatedTrigger.WithOldAndNewBinding(scopeId, oldPrefix, newPrefix); } else if (newPrefixHasValue == true && oldPrefixHasValue == false) { trigger = PrefixEdgeRouterBindingUpdatedTrigger.WithNewBinding(scopeId, newPrefix); } else if (newPrefixHasValue == false && oldPrefixHasValue == true) { trigger = PrefixEdgeRouterBindingUpdatedTrigger.WithOldBinding(scopeId, oldPrefix); } else { trigger = PrefixEdgeRouterBindingUpdatedTrigger.NoChanges(scopeId); } Mock <INxOsDeviceConfigurationService> deviceServiceMock = new Mock <INxOsDeviceConfigurationService>(MockBehavior.Strict); deviceServiceMock.Setup(x => x.Connect(address, username, password)).ReturnsAsync(true).Verifiable(); if (oldPrefixHasValue == true) { deviceServiceMock.Setup(x => x.RemoveIPv6StaticRoute(oldPrefix.Prefix, oldPrefix.Mask.Identifier, oldPrefix.Host)).ReturnsAsync(true).Verifiable(); } if (newPrefixHasValue == true) { deviceServiceMock.Setup(x => x.AddIPv6StaticRoute(newPrefix.Prefix, newPrefix.Mask.Identifier, newPrefix.Host)).ReturnsAsync(true).Verifiable(); } var actor = new NxOsStaticRouteUpdaterNotificationActor(deviceServiceMock.Object, Mock.Of <ILogger <NxOsStaticRouteUpdaterNotificationActor> >()); actor.ApplyValues(new Dictionary <String, String> { { "Url", "\"" + address + "\"" }, { "Password", "\"" + password + "\"" }, { "Username", "\"" + username + "\"" }, }); var pipeline = NotificationPipelineTester.CreatePipleline(random, trigger.GetTypeIdentifier(), NotificationCondition.True, actor); var pipelineResult = await pipeline.Execute(trigger); Assert.Equal(NotifactionPipelineExecutionResults.Success, pipelineResult); deviceServiceMock.Verify(); }
internal DHCPv6Packet HandleSolicitWithPrefixDelegation(DHCPv6Packet packet, IDHCPv6ServerPropertiesResolver properyResolver) { DHCPv6Packet innerPacket = packet.GetInnerPacket(); var addressProperties = GetAddressProperties(); Boolean rapitCommit = addressProperties.IsRapitCommitEnabled() && innerPacket.HasRapitCommitOption(); DUID clientDuid = innerPacket.GetClientIdentifer(); DHCPv6Lease currentLease = Leases.GetLeaseByClientDuid(clientDuid); DHCPv6Packet response = null; Boolean responseNeeded = false; Int32 waitingForLease = 15; // In some client implementations like Cisco IOS XE, two solicit packets are sent, one for an address and a second for a prefix, which would be handled without this loop. // Unfortunately, the PD is sent first and as long as the router received an answer for the address the PD packet is not sent again. Hence, progressing is delayed for a small amount of time. while ((currentLease == DHCPv6Lease.NotFound || currentLease.IsActive() == false) && --waitingForLease > 0) { Task.Delay(100).GetAwaiter().GetResult(); currentLease = Leases.GetLeaseByClientDuid(clientDuid); } if (currentLease == DHCPv6Lease.NotFound) { _logger.LogDebug("no lease for client duid {duid} found", clientDuid); base.Apply(new DHCPv6SolicitHandledEvent(this.Id, packet, DHCPv6SolicitHandledEvent.SolicitErros.LeaseNotFound)); } else if (currentLease.IsActive() == false) { _logger.LogDebug("lease with {address} for client duid {duid} found but not active. state is {state}", currentLease.Address, clientDuid, currentLease.State); base.Apply(new DHCPv6SolicitHandledEvent(this.Id, packet, DHCPv6SolicitHandledEvent.SolicitErros.LeaseNotActive)); } else if (addressProperties.PrefixDelgationInfo == null) { _logger.LogDebug("prefix delegation for {name} is not enabled", Name); base.Apply(new DHCPv6SolicitHandledEvent(this.Id, packet, DHCPv6SolicitHandledEvent.SolicitErros.PrefixDelegationNotAvailable)); } else { if (IsFreshPrefix(currentLease) == false) { responseNeeded = true; } else { _logger.LogInformation("a fresh leased prefix found. Skipping creating of a new prefix"); } } if (responseNeeded == true) { UInt32 prefixIdentityAsscocationId = packet.GetInnerPacket().GetPrefixDelegationIdentityAssocationId().Value; var prefix = addressProperties.GetValidPrefix(Leases.GetUsedPrefixes(), prefixIdentityAsscocationId); currentLease.UpdateAddressPrefix(prefix, false); _logger.LogDebug("prefix {prefix}/{lenth} for id {id} is generated", currentLease.PrefixDelegation.NetworkAddress, currentLease.PrefixDelegation.Mask.Identifier.Value, currentLease.PrefixDelegation.IdentityAssociation); if (rapitCommit == true) { _logger.LogDebug("rapit commit is enabled. sending packet as reply"); response = DHCPv6Packet.AsPrefixReplyWithRapitCommit( packet, addressProperties, DHCPv6ScopeProperties.Empty, currentLease, properyResolver.GetServerDuid()); base.AddNotificationTrigger( PrefixEdgeRouterBindingUpdatedTrigger.WithNewBinding(Id, PrefixBinding.FromLease(currentLease) )); } else { _logger.LogDebug("rapit commit is not enabled. sending packet as advertise"); response = DHCPv6Packet.AsPrefixAdvertise( packet, addressProperties, DHCPv6ScopeProperties.Empty, currentLease, properyResolver.GetServerDuid()); } base.Apply(new DHCPv6SolicitHandledEvent(this.Id, packet, response, rapitCommit)); } return(response); }
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); }