using Insight.Agent.Interfaces; using Insight.Agent.Messages; using System.Management; using System.Net; using System.Net.NetworkInformation; using System.Runtime.InteropServices; using System.Runtime.Versioning; using Route = Insight.Agent.Messages.Route; namespace Insight.Agent.Network.Handlers { [SupportedOSPlatform("windows")] public class InterfaceHandler : IAgentMessageHandler { public async ValueTask HandleAsync(AgentSession sender, TMessage message, CancellationToken cancellationToken) where TMessage : IAgentMessage { if (message is GetInventory) { var result = new InterfaceList(); result.AddRange(GetInterfaces()); await sender.SendAsync(result, cancellationToken); } } private static List GetInterfaces() { if (NetworkInterface.GetIsNetworkAvailable() is false) return null; if (NetworkInterface.GetAllNetworkInterfaces().Any() is false) return null; var interfaces = new List(); foreach (var ni in NetworkInterface.GetAllNetworkInterfaces()) { var ipProperties = ni.GetIPProperties(); var ipStatistics = ni.GetIPStatistics(); var @interface = new Interface { Mac = ni.GetPhysicalAddress().ToString(), Name = ni.Name, Description = ni.Description, Type = ni.NetworkInterfaceType, Speed = ni.Speed, Status = ni.OperationalStatus, Suffix = ipProperties.DnsSuffix, Sent = ipStatistics.BytesSent, Received = ipStatistics.BytesReceived, IncomingPacketsDiscarded = ipStatistics.IncomingPacketsDiscarded, IncomingPacketsWithErrors = ipStatistics.IncomingPacketsWithErrors, IncomingUnknownProtocolPackets = ipStatistics.IncomingUnknownProtocolPackets, OutgoingPacketsDiscarded = ipStatistics.OutgoingPacketsDiscarded, OutgoingPacketsWithErrors = ipStatistics.OutgoingPacketsWithErrors }; try { var propertiesV4 = ipProperties.GetIPv4Properties(); @interface.Index = uint.Parse(propertiesV4.Index.ToString()); @interface.Ipv4Mtu = propertiesV4.Mtu; @interface.Ipv4Dhcp = propertiesV4.IsDhcpEnabled; @interface.Ipv4Forwarding = propertiesV4.IsForwardingEnabled; } catch (Exception) { } try { var propertiesV6 = ipProperties.GetIPv6Properties(); @interface.Index = uint.Parse(propertiesV6.Index.ToString()); @interface.Ipv6Mtu = propertiesV6.Mtu; } catch (Exception) { } @interface.Gateways = GetAddresses(ipProperties.GatewayAddresses); @interface.Addresses = GetAddresses(ipProperties.UnicastAddresses); @interface.Dns = GetAddresses(ipProperties.DnsAddresses); @interface.Dhcp = GetAddresses(ipProperties.DhcpServerAddresses); if (@interface.Index.HasValue) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { using var searcher = new ManagementObjectSearcher { Scope = new ManagementScope(@"root\cimv2"), Query = new ObjectQuery($"select interfaceindex, guid, physicaladapter, manufacturer from win32_networkadapter where interfaceindex = {@interface.Index}") }; if (searcher.TryGet(out var collection) is false) { searcher.Query = new ObjectQuery($"select * from win32_networkadapter where interfaceindex = {@interface.Index}"); if (searcher.TryGet(out collection) is false) throw new InvalidOperationException("WMI Collection NULL"); } using (collection) { foreach (ManagementObject @object in collection) { var properties = @object.GetPropertyHashes(); @interface.Manufacturer = @object.GetValue(properties, "manufacturer")?.Trim(); @interface.Guid = @object.GetValue(properties, "guid"); @interface.Physical = @object.GetValue(properties, "physicaladapter"); break; } } @interface.Routes = QueryInterfaceRoutes(@interface.Index.Value); } } interfaces.Add(@interface); } return interfaces; } private static List QueryInterfaceRoutes(uint interfaceIndex) { using var searcher = new ManagementObjectSearcher { Scope = new ManagementScope(@"root\standardcimv2"), Query = new ObjectQuery($"select addressFamily, state, interfaceindex, routemetric, nexthop, destinationprefix from msft_netroute where interfaceindex = {interfaceIndex}") }; if (searcher.TryGet(out var collection) is false) { searcher.Query = new ObjectQuery($"select * from msft_netroute where interfaceindex = {interfaceIndex}"); if (searcher.TryGet(out collection) is false) throw new InvalidOperationException("WMI Collection NULL"); } var routes = new List(); using (collection) { foreach (var @object in collection) { var route = new Route { InterfaceIndex = interfaceIndex }; var properties = @object.GetPropertyHashes(); if (@object.TryGetValue(properties, "routemetric", out var routemetric)) { if (int.TryParse(routemetric?.ToString(), out var metric)) route.Metric = metric; } if (@object.TryGetValue(properties, "nexthop", out var nexthop)) { if (IPAddress.TryParse(nexthop?.ToString(), out var gateway)) route.Gateway = new IPAddress2(gateway); } if (@object.TryGetValue(properties, "destinationprefix", out var destinationprefix)) { var split = destinationprefix?.ToString()?.Split('/'); var cidrData = split?[1]; if (IPAddress.TryParse(split?[0], out var destination)) route.Destination = new IPAddress2(destination); if (int.TryParse(cidrData, out var cidr)) { var mask = ConvertCidr(cidr); route.Mask = mask; } } routes.Add(route); } } return routes; } private static List GetAddresses(UnicastIPAddressInformationCollection unicastCollection) { var addresses = new List(); if (unicastCollection.Any() is false) return addresses; foreach (var unicast in unicastCollection) { addresses.Add(new Unicast { IpAddress = new IPAddress2(unicast.Address), AddressPreferredLifetime = unicast.AddressPreferredLifetime, AddressValidLifetime = unicast.AddressValidLifetime, DuplicateAddressDetectionState = unicast.DuplicateAddressDetectionState, Ipv4Mask = new IPAddress2(unicast.IPv4Mask), PrefixLength = unicast.PrefixLength, PrefixOrigin = unicast.PrefixOrigin, SuffixOrigin = unicast.SuffixOrigin, DhcpLeaseLifetime = unicast.DhcpLeaseLifetime, }); } return addresses; } private static List GetAddresses(IPAddressCollection addressCollection) { var addresses = new List(); if (addressCollection.Any() is false) return addresses; foreach (var address in addressCollection) { addresses.Add(new IPAddress2(address)); } return addresses; } private static List GetAddresses(GatewayIPAddressInformationCollection addressCollection) { var addresses = new List(); if (addressCollection.Any() is false) return addresses; foreach (var address in addressCollection) { addresses.Add(new IPAddress2(address.Address)); } return addresses; } private static string? ConvertCidr(int cidr) { return cidr switch { 0 => "0.0.0.0", 1 => "128.0.0.0", 2 => "192.0.0.0", 3 => "224.0.0.0", 4 => "240.0.0.0", 5 => "248.0.0.0", 6 => "252.0.0.0", 7 => "254.0.0.0", 8 => "255.0.0.0", 9 => "255.128.0.0", 10 => "255.192.0.0", 11 => "255.224.0.0", 12 => "255.240.0.0", 13 => "255.248.0.0", 14 => "255.252.0.0", 15 => "255.254.0.0", 16 => "255.255.0.0", 17 => "255.255.128.0", 18 => "255.255.192.0", 19 => "255.255.224.0", 20 => "255.255.240.0", 21 => "255.255.248.0", 22 => "255.255.252.0", 23 => "255.255.254.0", 24 => "255.255.255.0", 25 => "255.255.255.128", 26 => "255.255.255.192", 27 => "255.255.255.224", 28 => "255.255.255.240", 29 => "255.255.255.248", 30 => "255.255.255.252", 31 => "255.255.255.254", 32 => "255.255.255.255", _ => null, }; } } }