2019-10-04 16:36:17 +02:00
|
|
|
|
using System;
|
|
|
|
|
using ln.application;
|
|
|
|
|
using ln.application.service;
|
|
|
|
|
using System.Threading;
|
|
|
|
|
using ln.types.odb.ng;
|
|
|
|
|
using ln.types;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using ln.json;
|
|
|
|
|
using ln.types.odb.ng.storage.session;
|
2020-01-07 08:53:53 +01:00
|
|
|
|
using ln.types.net;
|
2019-10-04 16:36:17 +02:00
|
|
|
|
namespace ln.provider
|
|
|
|
|
{
|
|
|
|
|
public class IPPoolService : ApplicationServiceBase
|
|
|
|
|
{
|
|
|
|
|
CoreService CoreService { get; set; }
|
2020-01-07 08:53:53 +01:00
|
|
|
|
ProviderApplication Application => base.CurrentApplication as ProviderApplication;
|
2019-10-04 16:36:17 +02:00
|
|
|
|
|
2020-01-07 08:53:53 +01:00
|
|
|
|
|
|
|
|
|
RPC rpc;
|
2019-10-04 16:36:17 +02:00
|
|
|
|
|
|
|
|
|
SessionStorageContainer mapperSession;
|
|
|
|
|
Mapper mapper;
|
|
|
|
|
|
|
|
|
|
IPAllocation v6Root;
|
|
|
|
|
IPAllocation v4Root;
|
|
|
|
|
|
|
|
|
|
public IPPoolService()
|
|
|
|
|
:base("IPPoolService")
|
|
|
|
|
{
|
|
|
|
|
DependOnService<CoreService>();
|
|
|
|
|
|
|
|
|
|
rpc = new RPC(this);
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-07 08:53:53 +01:00
|
|
|
|
public override void ServiceMain(Application applicationInterface)
|
2019-10-04 16:36:17 +02:00
|
|
|
|
{
|
|
|
|
|
CoreService = Dependency<CoreService>();
|
|
|
|
|
|
|
|
|
|
using (mapperSession = new SessionStorageContainer(CoreService.CoreStorageContainer))
|
|
|
|
|
{
|
|
|
|
|
mapper = new Mapper(mapperSession);
|
|
|
|
|
|
|
|
|
|
mapper.EnsureIndex<IPAllocation>("CIDR");
|
|
|
|
|
mapper.EnsureIndex<IPAllocation>("Pool");
|
|
|
|
|
|
|
|
|
|
Application.RPCContainer.Add("ippool", rpc);
|
|
|
|
|
|
|
|
|
|
v6Root = mapper.Load<IPAllocation>(Query.Equals<IPAllocation>("CIDR",IPv6.ANY)).FirstOrDefault();
|
|
|
|
|
v4Root = mapper.Load<IPAllocation>(Query.Equals<IPAllocation>("CIDR", IPv6.V4Space)).FirstOrDefault();
|
|
|
|
|
|
|
|
|
|
if (v6Root == null)
|
|
|
|
|
{
|
|
|
|
|
v6Root = new IPAllocation(IPv6.ANY, "Global IPv6 Space", null);
|
|
|
|
|
mapper.Save(v6Root);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (v4Root == null)
|
|
|
|
|
{
|
|
|
|
|
v4Root = new IPAllocation(IPv6.V4Space, "Global IPv4 Space", v6Root.CIDR);
|
|
|
|
|
mapper.Save(v4Root);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ready();
|
|
|
|
|
|
|
|
|
|
while (!StopRequested)
|
|
|
|
|
{
|
|
|
|
|
lock (Thread.CurrentThread)
|
|
|
|
|
{
|
|
|
|
|
Monitor.Wait(Thread.CurrentThread);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mapper = null;
|
|
|
|
|
|
|
|
|
|
Application.RPCContainer.Remove("ippool");
|
|
|
|
|
CoreService = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public IPAllocation[] GetAllocations()
|
|
|
|
|
{
|
|
|
|
|
return mapper.Load<IPAllocation>().ToArray();
|
|
|
|
|
}
|
|
|
|
|
public IPAllocation GetAllocation(IPv6 cidr)
|
|
|
|
|
{
|
|
|
|
|
return mapper.Load<IPAllocation>(Query.Equals<IPAllocation>("CIDR", cidr)).FirstOrDefault();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public IPAllocation[] GetPoolAllocations(IPv6 pool)
|
|
|
|
|
{
|
|
|
|
|
return mapper.Load<IPAllocation>(Query.Equals<IPAllocation>("Pool", pool)).ToArray();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public IPAllocation AllocateAny(IPv6 zone,int width,string usage)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
public IPAllocation AllocateCIDR(IPv6 zone,IPv6 cidr,string usage,bool splitZones)
|
|
|
|
|
{
|
|
|
|
|
IPAllocation pool = GetAllocation(zone);
|
|
|
|
|
if (pool == null)
|
|
|
|
|
throw new KeyNotFoundException();
|
|
|
|
|
|
|
|
|
|
if (!pool.CIDR.Contains(cidr))
|
|
|
|
|
throw new ArgumentException(String.Format("{0} doesn't contain {1}", pool.CIDR.ToCIDR(), cidr.ToCIDR()));
|
|
|
|
|
|
|
|
|
|
if (splitZones)
|
|
|
|
|
{
|
|
|
|
|
IPAllocation allocation = pool;
|
|
|
|
|
while (!allocation.CIDR.Equals(cidr))
|
|
|
|
|
{
|
2020-01-07 08:53:53 +01:00
|
|
|
|
IPAllocation split = null;
|
|
|
|
|
|
|
|
|
|
foreach (IPv6 splitCIDR in allocation.CIDR.Split(1))
|
2019-10-04 16:36:17 +02:00
|
|
|
|
{
|
|
|
|
|
if (splitCIDR.Contains(cidr))
|
|
|
|
|
{
|
2020-01-07 08:53:53 +01:00
|
|
|
|
split = GetAllocation(splitCIDR);
|
2019-10-04 16:36:17 +02:00
|
|
|
|
if (split == null)
|
|
|
|
|
{
|
|
|
|
|
split = new IPAllocation(splitCIDR,allocation.CIDR);
|
|
|
|
|
mapper.Save(split);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-01-07 08:53:53 +01:00
|
|
|
|
else if (Equals(String.Empty,split.AllocatedTo))
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
throw new ArgumentOutOfRangeException(String.Format("No subnet available below {0}",allocation.CIDR.ToCIDR()));
|
|
|
|
|
}
|
2019-10-04 16:36:17 +02:00
|
|
|
|
}
|
2020-01-07 08:53:53 +01:00
|
|
|
|
allocation = split;
|
2019-10-04 16:36:17 +02:00
|
|
|
|
}
|
2020-01-07 08:53:53 +01:00
|
|
|
|
allocation.AllocatedTo = usage;
|
|
|
|
|
mapper.Save(allocation);
|
2019-10-04 16:36:17 +02:00
|
|
|
|
return allocation;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
IPAllocation allocation = GetAllocation(cidr);
|
|
|
|
|
if (allocation != null)
|
|
|
|
|
throw new Exception("Allocation already present");
|
|
|
|
|
|
|
|
|
|
allocation = new IPAllocation(cidr, cidr.ToCIDR(), pool.CIDR);
|
|
|
|
|
allocation.AllocatedTo = usage;
|
|
|
|
|
|
|
|
|
|
mapper.Save(allocation);
|
|
|
|
|
|
|
|
|
|
return allocation;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class RPC
|
|
|
|
|
{
|
|
|
|
|
IPPoolService poolService;
|
|
|
|
|
|
|
|
|
|
public RPC(IPPoolService poolService)
|
|
|
|
|
{
|
|
|
|
|
this.poolService = poolService;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public IPAllocation[] GetAllocations() => poolService.GetAllocations();
|
|
|
|
|
public IPAllocation GetAllocation(IPv6 cidr) => poolService.GetAllocation(cidr);
|
|
|
|
|
public IPAllocation[] GetPoolAllocations(IPv6 pool) => poolService.GetPoolAllocations(pool);
|
|
|
|
|
|
|
|
|
|
public IPAllocation AllocateAny(IPv6 zone, int width, string usage) => poolService.AllocateAny(zone, width, usage);
|
|
|
|
|
public IPAllocation AllocateCIDR(IPv6 zone, IPv6 cidr, string usage, bool splitZones) => poolService.AllocateCIDR(zone, cidr, usage,splitZones);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class IPAllocation
|
|
|
|
|
{
|
|
|
|
|
public IPv6 CIDR { get; }
|
|
|
|
|
public string Name { get; set; } = String.Empty;
|
|
|
|
|
|
|
|
|
|
public string AllocatedTo { get; set; } = String.Empty;
|
|
|
|
|
|
|
|
|
|
public IPv6 Pool { get; }
|
|
|
|
|
|
|
|
|
|
private IPAllocation(){}
|
|
|
|
|
public IPAllocation(IPv6 cidr): this(cidr, cidr.ToCIDR(), IPv6.ANY) { }
|
|
|
|
|
public IPAllocation(IPv6 cidr, IPv6 pool) : this(cidr, cidr.ToCIDR(), pool) { }
|
|
|
|
|
public IPAllocation(IPv6 cidr,String name,IPv6 pool)
|
|
|
|
|
{
|
|
|
|
|
Pool = pool;
|
|
|
|
|
CIDR = cidr;
|
|
|
|
|
Name = name;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|