File: System\Net\NetworkInformation\StringParsingHelpers.Addresses.cs
Web Access
Project: src\src\libraries\System.Net.NetworkInformation\src\System.Net.NetworkInformation.csproj (System.Net.NetworkInformation)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Collections.Generic;
using System.IO;
 
namespace System.Net.NetworkInformation
{
    internal static partial class StringParsingHelpers
    {
        // /proc/net/route contains some information about gateway addresses,
        // and separates the information about by each interface.
        internal static List<GatewayIPAddressInformation> ParseIPv4GatewayAddressesFromRouteFile(List<GatewayIPAddressInformation> collection, string[] fileLines, string interfaceName)
        {
            // Columns are as follows (first-line header):
            // Iface  Destination  Gateway  Flags  RefCnt  Use  Metric  Mask  MTU  Window  IRTT
            foreach (string line in fileLines)
            {
                if (line.StartsWith(interfaceName, StringComparison.Ordinal))
                {
                    StringParser parser = new StringParser(line, '\t', skipEmpty: true);
                    parser.MoveNext();
                    parser.MoveNextOrFail();
                    string gatewayIPHex = parser.MoveAndExtractNext();
                    long addressValue = Convert.ToInt64(gatewayIPHex, 16);
                    if (addressValue != 0)
                    {
                        // Skip device routes without valid NextHop IP address.
                        IPAddress address = new IPAddress(addressValue);
                        collection.Add(new SimpleGatewayIPAddressInformation(address));
                    }
                }
            }
 
            return collection;
        }
 
        internal static void ParseIPv6GatewayAddressesFromRouteFile(List<GatewayIPAddressInformation> collection, string[] fileLines, string interfaceName, long scopeId)
        {
            // Columns are as follows (first-line header):
            // 00000000000000000000000000000000 00 00000000000000000000000000000000 00 00000000000000000000000000000000 ffffffff 00000001 00000001 00200200 lo
            // +------------------------------+ ++ +------------------------------+ ++ +------------------------------+ +------+ +------+ +------+ +------+ ++
            // |                                |  |                                |  |                                |        |        |        |        |
            // 0                                1  2                                3  4                                5        6        7        8        9
            //
            // 0. IPv6 destination network displayed in 32 hexadecimal chars without colons as separator
            // 1. IPv6 destination prefix length in hexadecimal
            // 2. IPv6 source network displayed in 32 hexadecimal chars without colons as separator
            // 3. IPv6 source prefix length in hexadecimal
            // 4. IPv6 next hop displayed in 32 hexadecimal chars without colons as separator
            // 5. Metric in hexadecimal
            // 6. Reference counter
            // 7. Use counter
            // 8. Flags
            // 9. Interface name
            foreach (string line in fileLines)
            {
                if (line.StartsWith("00000000000000000000000000000000", StringComparison.Ordinal))
                {
                    string[] token = line.Split(' ', StringSplitOptions.RemoveEmptyEntries);
                    if (token.Length > 9 && token[4] != "00000000000000000000000000000000")
                    {
                        if (!string.IsNullOrEmpty(interfaceName) && interfaceName != token[9])
                        {
                            continue;
                        }
 
                        IPAddress address = ParseIPv6HexString(token[4], isNetworkOrder: true);
                        if (address.IsIPv6LinkLocal)
                        {
                            // For Link-Local addresses add ScopeId as that is not part of the route entry.
                            address.ScopeId = scopeId;
                        }
                        collection.Add(new SimpleGatewayIPAddressInformation(address));
                    }
                }
            }
        }
 
        internal static void ParseDhcpServerAddressesFromLeasesFile(List<IPAddress> collection, string filePath, string name)
        {
            // Parse the /var/lib/dhcp/dhclient.leases file, if it exists.
            // If any errors occur, like the file not existing or being
            // improperly formatted, just bail and return an empty collection.
            try
            {
                if (File.Exists(filePath)) // avoid an exception in most cases if path doesn't already exist
                {
                    string fileContents = ReadAllText(filePath);
                    int leaseIndex = -1;
                    int secondBrace = -1;
                    while ((leaseIndex = fileContents.IndexOf("lease", leaseIndex + 1, StringComparison.Ordinal)) != -1)
                    {
                        int firstBrace = fileContents.IndexOf('{', leaseIndex);
                        secondBrace = fileContents.IndexOf('}', leaseIndex);
                        int blockLength = secondBrace - firstBrace;
 
                        int interfaceIndex = fileContents.IndexOf("interface", firstBrace, blockLength, StringComparison.Ordinal);
                        int afterName = fileContents.IndexOf(';', interfaceIndex);
                        int beforeName = fileContents.LastIndexOf(' ', afterName);
                        ReadOnlySpan<char> interfaceName = fileContents.AsSpan(beforeName + 2, afterName - beforeName - 3);
                        if (!interfaceName.SequenceEqual(name))
                        {
                            continue;
                        }
 
                        int indexOfDhcp = fileContents.IndexOf("dhcp-server-identifier", firstBrace, blockLength, StringComparison.Ordinal);
                        int afterAddress = fileContents.IndexOf(';', indexOfDhcp);
                        int beforeAddress = fileContents.LastIndexOf(' ', afterAddress);
                        ReadOnlySpan<char> dhcpAddressSpan = fileContents.AsSpan(beforeAddress + 1, afterAddress - beforeAddress - 1);
                        if (IPAddress.TryParse(dhcpAddressSpan, out IPAddress? dhcpAddress))
                        {
                            collection.Add(dhcpAddress);
                        }
                    }
                }
            }
            catch
            {
                // If any parsing or file reading exception occurs, just ignore it and return the collection.
            }
        }
 
        internal static List<IPAddress> ParseWinsServerAddressesFromSmbConfFile(string smbConfFilePath)
        {
            List<IPAddress> collection = new List<IPAddress>();
            try
            {
                if (File.Exists(smbConfFilePath)) // avoid an exception in most cases if path doesn't already exist
                {
                    string fileContents = ReadAllText(smbConfFilePath);
                    string label = "wins server = ";
                    int labelIndex = fileContents.IndexOf(label);
                    int labelLineStart = fileContents.LastIndexOf(Environment.NewLine, labelIndex, StringComparison.Ordinal);
                    if (labelLineStart < labelIndex)
                    {
                        int commentIndex = fileContents.IndexOf(';', labelLineStart, labelIndex - labelLineStart);
                        if (commentIndex != -1)
                        {
                            return collection;
                        }
                    }
                    int endOfLine = fileContents.IndexOf(Environment.NewLine, labelIndex, StringComparison.Ordinal);
                    ReadOnlySpan<char> addressSpan = fileContents.AsSpan(labelIndex + label.Length, endOfLine - (labelIndex + label.Length));
                    IPAddress address = IPAddress.Parse(addressSpan);
                    collection.Add(address);
                }
            }
            catch
            {
                // If any parsing or file reading exception occurs, just ignore it and return the collection.
            }
 
            return collection;
        }
 
    }
}