|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
namespace System.Net.NetworkInformation
{
internal sealed class LinuxIPGlobalStatistics : IPGlobalStatistics
{
// MIB-II statistics data.
private readonly IPGlobalStatisticsTable _table;
// Miscellaneous IP information, not defined in MIB-II.
private readonly int _numRoutes;
private readonly int _numInterfaces;
private readonly int _numIPAddresses;
public LinuxIPGlobalStatistics(bool ipv4)
{
if (ipv4)
{
_table = StringParsingHelpers.ParseIPv4GlobalStatisticsFromSnmpFile(NetworkFiles.SnmpV4StatsFile);
_numRoutes = StringParsingHelpers.ParseNumRoutesFromRouteFile(NetworkFiles.Ipv4RouteFile);
_numInterfaces = StringParsingHelpers.ParseNumIPInterfaces(NetworkFiles.Ipv4ConfigFolder);
}
else
{
_table = StringParsingHelpers.ParseIPv6GlobalStatisticsFromSnmp6File(NetworkFiles.SnmpV6StatsFile);
_numRoutes = StringParsingHelpers.ParseNumRoutesFromRouteFile(NetworkFiles.Ipv6RouteFile);
_numInterfaces = StringParsingHelpers.ParseNumIPInterfaces(NetworkFiles.Ipv6ConfigFolder);
// /proc/sys/net/ipv6/conf/default/forwarding
string forwardingConfigFile = Path.Combine(NetworkFiles.Ipv6ConfigFolder,
NetworkFiles.DefaultNetworkInterfaceFileName,
NetworkFiles.ForwardingFileName);
_table.Forwarding = StringParsingHelpers.ParseRawIntFile(forwardingConfigFile) == 1;
// snmp6 does not include Default TTL info. Read it from snmp.
_table.DefaultTtl = StringParsingHelpers.ParseDefaultTtlFromFile(NetworkFiles.SnmpV4StatsFile);
}
_numIPAddresses = GetNumIPAddresses();
}
public override int DefaultTtl { get { return _table.DefaultTtl; } }
public override bool ForwardingEnabled { get { return _table.Forwarding; } }
public override int NumberOfInterfaces { get { return _numInterfaces; } }
public override int NumberOfIPAddresses { get { return _numIPAddresses; } }
public override int NumberOfRoutes { get { return _numRoutes; } }
public override long OutputPacketRequests { get { return _table.OutRequests; } }
[UnsupportedOSPlatform("linux")]
public override long OutputPacketRoutingDiscards { get { throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); } }
public override long OutputPacketsDiscarded { get { return _table.OutDiscards; } }
public override long OutputPacketsWithNoRoute { get { return _table.OutNoRoutes; } }
public override long PacketFragmentFailures { get { return _table.FragmentFails; } }
public override long PacketReassembliesRequired { get { return _table.ReassemblyRequireds; } }
public override long PacketReassemblyFailures { get { return _table.ReassemblyFails; } }
public override long PacketReassemblyTimeout { get { return _table.ReassemblyTimeout; } }
public override long PacketsFragmented { get { return _table.FragmentCreates; } }
public override long PacketsReassembled { get { return _table.ReassemblyOKs; } }
public override long ReceivedPackets { get { return _table.InReceives; } }
public override long ReceivedPacketsDelivered { get { return _table.InDelivers; } }
public override long ReceivedPacketsDiscarded { get { return _table.InDiscards; } }
public override long ReceivedPacketsForwarded { get { return _table.ForwardedDatagrams; } }
public override long ReceivedPacketsWithAddressErrors { get { return _table.InAddressErrors; } }
public override long ReceivedPacketsWithHeadersErrors { get { return _table.InHeaderErrors; } }
public override long ReceivedPacketsWithUnknownProtocol { get { return _table.InUnknownProtocols; } }
[UnmanagedCallersOnly]
private static unsafe void ProcessIpv4Address(void* pContext, byte* ifaceName, Interop.Sys.IpAddressInfo* ipAddr)
{
(*(int*)pContext)++;
}
[UnmanagedCallersOnly]
private static unsafe void ProcessIpv6Address(void* pContext, byte* ifaceName, Interop.Sys.IpAddressInfo* ipAddr, uint* scopeId)
{
(*(int*)pContext)++;
}
private static unsafe int GetNumIPAddresses()
{
int count = 0;
Interop.Sys.EnumerateInterfaceAddresses(&count,
&ProcessIpv4Address,
&ProcessIpv6Address,
// Ignore link-layer addresses that are discovered; don't create a callback.
null);
return count;
}
}
}
|