using System; using System.Collections.Generic; using System.Collections; using System.Security; using ln.types; using System.Linq; using System.Threading; using ln.skyscanner.crawl; using ln.snmp.rfc1213; using ln.types.odb; using ln.types.sync; using ln.logging; using System.Globalization; using ln.types.threads; using ln.types.odb.values; namespace ln.skyscanner.entities { public class GlobalNetwork : Persistent { [Unsynced] public SkyScanner SkyScanner => SkyScanner.Instance; [Unsynced] public SkyEntities SkyEntities { get; private set; } public IEnumerable Subnets => SkyEntities.subnetCollection; public IEnumerable Nodes => SkyEntities.nodeCollection; public HopMap DefaultHopMap { get; private set; } = new HopMap(); private object _updateLock = new object(); public GlobalNetwork() { } public GlobalNetwork(SkyEntities skyEntities) { SkyEntities = skyEntities; } public void EnsureSubnet(CIDR network) { SkyScanner.Crawler.EnsureSubnet(network); Subnet subnet = SkyEntities.subnetCollection.Where(s => s.Network.Equals(network)).FirstOrDefault(); if (subnet == null) { subnet = new Subnet(network); SkyEntities.subnetCollection.Upsert(subnet); } } public Node GetNode(Guid id) { return SkyEntities.nodeCollection.Select(id); } public Subnet FindSubnetForHost(CIDR host) { return SkyEntities.subnetCollection.Select(net => net.Network.Contains(host)).FirstOrDefault(); } public IEnumerable FindHostsInSubnet(CIDR network) { IntfIP[] intfIPs = SkyEntities.intfIPCollection.Select((ip) => ip.IP.In(network)).ToArray(); NetworkInterface[] networkInterfaces = intfIPs.Select((iip) => iip.NetworkInterface).Distinct().ToArray(); Node[] nodes = SkyEntities.nodeCollection.Select(networkInterfaces.Select((ni) => (ODBValue)ni.NodeID).Distinct()).ToArray(); return nodes; } public IEnumerable FindNeighbors(Node node) { return node.IPAdresses.SelectMany((ip) => Timing.Meassure("FindHostsInSubnet", () => FindHostsInSubnet(ip)).Distinct().ToArray()); } public Node FindNodeByIP(IEnumerable ips) { foreach (CIDR ip in ips) { Node node = FindNodeByIP(ip); if (node != null) return node; } return null; } public Node FindNodeByIP(CIDR ip) { ip = ip.Host; IntfIP _iip = SkyEntities.intfIPCollection.Where((iip) => iip.IP.Host.Equals(ip)).FirstOrDefault(); return _iip?.NetworkInterface?.Node; } [Unsynced] private Queue updateQueue = new Queue(); public void EnqueueUpdate(CrawledHost crawledHost) { lock (updateQueue) { if (!updateQueue.Contains(crawledHost)) updateQueue.Enqueue(crawledHost); } } public void Update() { lock (updateQueue) { if (updateQueue.Count == 0) return; } while (true) { CrawledHost crawledHost = null; lock (updateQueue) { if (updateQueue.Count > 0) crawledHost = updateQueue.Dequeue(); else break; } Update(crawledHost); } //SkyScanner.Entities.DBGlobalNetwork.SavePersistent(SkyScanner.Entities.DBGlobalNetwork.Root); } private void Update(CrawledHost crawledHost) { Logging.Log(LogLevel.DEBUG, "Entity: update {0}", crawledHost.PrimaryIP); Node node = FindNodeByIP(crawledHost.PrimaryIP); if (node == null) node = FindNodeByIP(crawledHost.IPAddresses); if (node == null) { node = new Node(crawledHost.PrimaryIP); node.Name = crawledHost.Name; node.PrimaryMac = crawledHost.PrimaryHWAddr; } foreach (String si in crawledHost.GetHint("rfc1213.interfaces",new string[0])) { String[] fields = si.Split(';'); NetworkInterface networkInterface = node.GetInterface(fields[0]); if (networkInterface == null) networkInterface = new NetworkInterface(node, fields[0]); networkInterface.HWAddress = fields[1]; SkyEntities.interfaceCollection.Upsert(networkInterface); CIDR[] crawledIPs = fields[2].Split(',').Where((sip) => !String.Empty.Equals(sip)).Select((sip) => CIDR.Parse(sip)).ToArray(); IntfIP[] currentIPs = networkInterface.IPs.ToArray(); foreach (CIDR crawledIP in crawledIPs) { int n; for (n=0; n < currentIPs.Length; n++) if (currentIPs[n].IP.Equals(crawledIP)) break; if (n == currentIPs.Length) { IntfIP miss = new IntfIP(networkInterface, crawledIP); SkyEntities.intfIPCollection.Upsert(miss); } } foreach (IntfIP iip in currentIPs) { CIDR ip = iip.IP; if (crawledIPs.Contains(ip)) { EnsureSubnet(ip.Network); } else { SkyEntities.intfIPCollection.Delete(iip); } } } node.RemoveURI("ssh"); if (crawledHost.GetHint("ssh.port", -1) != -1) { node.AddURI( new URI( String.Format("ssh://{0}:{1}@{2}:{3}", crawledHost.GetHint("ssh.login"), crawledHost.GetHint("ssh.password"), crawledHost.GetHint("ssh.ip"), crawledHost.GetHint("ssh.port") ) ) ); } node.LastUpdate = DateTime.Now; SkyEntities.nodeCollection.Upsert(node); } } }