blob: 1893cd417bddc34458615b2cc1b264e196d11b14 [file] [log] [blame]
Constantin Ziesche857c7ab2020-02-25 11:24:51 +01001/*******************************************************************************
2* Copyright (c) 2020 Robert Bosch GmbH
3* Author: Constantin Ziesche (constantin.ziesche@bosch.com)
4*
5* This program and the accompanying materials are made available under the
6* terms of the Eclipse Public License 2.0 which is available at
7* http://www.eclipse.org/legal/epl-2.0
8*
9* SPDX-License-Identifier: EPL-2.0
10*******************************************************************************/
Constantin Ziescheeb927682020-03-03 11:11:31 +010011using NLog;
12using System;
Constantin Ziesche857c7ab2020-02-25 11:24:51 +010013using System.Collections.Generic;
14using System.Linq;
15using System.Net;
Constantin Ziescheeb927682020-03-03 11:11:31 +010016using System.Net.NetworkInformation;
17using System.Net.Sockets;
18using System.Threading.Tasks;
Constantin Ziesche857c7ab2020-02-25 11:24:51 +010019
20namespace BaSyx.Utils.Network
21{
22 public static class NetworkUtils
23 {
Constantin Ziescheeb927682020-03-03 11:11:31 +010024 private static readonly ILogger logger = LogManager.GetCurrentClassLogger();
25
Constantin Ziesche857c7ab2020-02-25 11:24:51 +010026 /// <summary>
27 /// This method returns the closest source IP address relative to the the target IP address.
28 /// The probality of being able to call the target IP hence increases.
29 /// </summary>
30 /// <param name="target">Target IP address to call</param>
31 /// <param name="sources">Source IP address from where to cal the target</param>
32 /// <returns>The closest source IP address to the the target IP address or the Loopback Address</returns>
33 public static IPAddress GetClosestIPAddress(IPAddress target, List<IPAddress> sources)
34 {
35 Dictionary<int, IPAddress> scoredSourceIPAddresses = new Dictionary<int, IPAddress>();
36 byte[] targetBytes = target.GetAddressBytes();
37 foreach (var source in sources)
38 {
39 byte[] sourceBytes = source.GetAddressBytes();
40 int score = CompareIPByteArray(targetBytes, sourceBytes);
41
42 if(!scoredSourceIPAddresses.ContainsKey(score) && score != 0)
43 scoredSourceIPAddresses.Add(score, source);
44 }
45
46 if(scoredSourceIPAddresses.Count > 0)
47 return scoredSourceIPAddresses[scoredSourceIPAddresses.Keys.Max()];
48
49 return IPAddress.Loopback;
50 }
51
52 private static int CompareIPByteArray(byte[] target, byte[] source)
53 {
54 if (target.Length != source.Length)
55 return 0;
56
57 int score = 0;
58 for (int i = 0; i < source.Length; i++)
59 {
60 if (target[i] == source[i])
61 score++;
62 else
63 return score;
64 }
65 return score;
66 }
Constantin Ziescheeb927682020-03-03 11:11:31 +010067 /// <summary>
68 /// Returns a sequence of network interfaces which are up and running.
69 /// If there is no other than the loopback interface available, the loopback interface is returned
70 /// </summary>
71 /// <returns>Sequence of network interfaces</returns>
72 public static IEnumerable<NetworkInterface> GetOperationalNetworkInterfaces()
73 {
74 NetworkInterface[] networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
75 IEnumerable<NetworkInterface> selectedInterfaces = networkInterfaces?.Where(n => n.OperationalStatus == OperationalStatus.Up && n.NetworkInterfaceType != NetworkInterfaceType.Loopback);
76 if(selectedInterfaces?.Count() > 0)
77 return selectedInterfaces;
78 else
79 return networkInterfaces?.Where(n => n.OperationalStatus == OperationalStatus.Up);
80 }
Constantin Ziesche857c7ab2020-02-25 11:24:51 +010081
Constantin Ziescheeb927682020-03-03 11:11:31 +010082 /// <summary>
83 /// Returns all IP addresses of all network interfaces without loopback
84 /// </summary>
85 /// <returns>Sequence of IP addresses</returns>
86 public static IEnumerable<IPAddress> GetIPAddresses()
87 {
88 IEnumerable<NetworkInterface> networkInterfaces = GetOperationalNetworkInterfaces();
89 return networkInterfaces?.SelectMany(n => n.GetIPProperties().UnicastAddresses)?.Select(s => s.Address);
90 }
91
92 /// <summary>
93 /// Returns all link local IP addresses
94 /// </summary>
95 /// <returns>Sequence of link local IP addresses</returns>
96 public static List<IPAddress> GetLinkLocalIPAddresses()
Constantin Ziesche857c7ab2020-02-25 11:24:51 +010097 {
98 IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());
99 List<IPAddress> ipAddresses = new List<IPAddress>();
100 foreach (var ip in host.AddressList)
101 {
Constantin Ziescheeb927682020-03-03 11:11:31 +0100102 if (ip.AddressFamily == AddressFamily.InterNetwork || ip.AddressFamily == AddressFamily.InterNetworkV6 && ip.IsIPv6LinkLocal)
Constantin Ziesche857c7ab2020-02-25 11:24:51 +0100103 ipAddresses.Add(ip);
104 }
105 return ipAddresses;
106 }
Constantin Ziescheeb927682020-03-03 11:11:31 +0100107
108 /// <summary>
109 /// Pings a host and returns true if ping was successfull otherwise false
110 /// </summary>
111 /// <param name="hostNameOrAddress">IP-address or host name</param>
112 /// <returns>true if pingable, false otherwise</returns>
113 public static async Task<bool> PingHostAsync(string hostNameOrAddress)
114 {
115 if (string.IsNullOrEmpty(hostNameOrAddress))
116 throw new ArgumentNullException(nameof(hostNameOrAddress));
117
118 try
119 {
120 using (Ping pinger = new Ping())
121 {
122 PingReply reply = await pinger.SendPingAsync(hostNameOrAddress);
123 if (reply.Status == IPStatus.Success)
124 {
125 return true;
126 }
127 else
128 {
Constantin Ziesche310d2aa2020-03-25 11:48:26 +0100129 logger.Warn($"Pinging {hostNameOrAddress} PingReply-Status: " + Enum.GetName(typeof(IPStatus), reply.Status));
Constantin Ziescheeb927682020-03-03 11:11:31 +0100130 return false;
131 }
132 }
133 }
134 catch (PingException e)
135 {
136 logger.Error(e, "Ping-Exception");
137 return false;
138 }
139 }
Constantin Ziesche857c7ab2020-02-25 11:24:51 +0100140 }
141}