From cb5ec30b99ebf07632aecfe75a4159095a9dcae9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20B=C3=B6rchers?= Date: Fri, 4 Apr 2025 10:26:08 +0200 Subject: [PATCH] Add support for aggressiv ip address scanning. --- src/CidrHelper.cs | 47 ++++++++++++++++++++++++ src/DiscoveredDeviceViewModel.cs | 8 +++- src/IpRangeHelper.cs | 40 ++++++++++++++++++++ src/MainWindow.axaml | 1 + src/MainWindowViewModel.cs | 63 +++++++++++++++++++++++++++++++- src/NetworkAdapter.cs | 4 +- 6 files changed, 158 insertions(+), 5 deletions(-) create mode 100644 src/CidrHelper.cs create mode 100644 src/IpRangeHelper.cs diff --git a/src/CidrHelper.cs b/src/CidrHelper.cs new file mode 100644 index 0000000..289ba7f --- /dev/null +++ b/src/CidrHelper.cs @@ -0,0 +1,47 @@ +using System.Net; + +namespace SddpViewer; + +public class CidrHelper +{ + public static (IPAddress Start, IPAddress End) GetIpRangeFromCidr(string cidr) + { + string[] parts = cidr.Split('/'); + if (parts.Length != 2) + throw new FormatException("Ungültiges CIDR-Format."); + + IPAddress ip = IPAddress.Parse(parts[0]); + int prefixLength = int.Parse(parts[1]); + + if (prefixLength < 0 || prefixLength > 32) + throw new ArgumentException("Ungültige Präfixlänge."); + + byte[] ipBytes = ip.GetAddressBytes(); + byte[] maskBytes = new byte[4]; + int remainingBits = prefixLength; + + for (int i = 0; i < maskBytes.Length; i++) + { + if (remainingBits >= 8) + { + maskBytes[i] = 0xFF; + remainingBits -= 8; + } + else if (remainingBits > 0) + { + maskBytes[i] = (byte)(0xFF << (8 - remainingBits)); + remainingBits = 0; + } + } + + byte[] startBytes = new byte[4]; + byte[] endBytes = new byte[4]; + for (int i = 0; i < 4; i++) + { + startBytes[i] = (byte)(ipBytes[i] & maskBytes[i]); + endBytes[i] = (byte)(ipBytes[i] | ~maskBytes[i]); + } + + return (new IPAddress(startBytes), new IPAddress(endBytes)); + } +} diff --git a/src/DiscoveredDeviceViewModel.cs b/src/DiscoveredDeviceViewModel.cs index 179a250..7e787ad 100644 --- a/src/DiscoveredDeviceViewModel.cs +++ b/src/DiscoveredDeviceViewModel.cs @@ -118,8 +118,12 @@ public partial class DiscoveredDeviceViewModel : ObservableObject, IDisposable private string EvaluateHostName() => Dns.GetHostEntry(IpAddress).HostName; - private string GetResponseHeader() => - string.Join("," + Environment.NewLine, _device.ResponseHeaders.Select(x => $"{{{x.Key} : {string.Join(";", x.Value)}}}")); + private string GetResponseHeader() + { + return _device.ResponseHeaders is null + ? "" + : string.Join("," + Environment.NewLine, _device.ResponseHeaders.Select(x => $"{{{x.Key} : {string.Join(";", x.Value)}}}")); + } private IPAddress EvaluateIpAddress(DiscoveredSsdpDevice device) => IPAddress.TryParse(device.DescriptionLocation.Host, out var value) ? value : IPAddress.Any; diff --git a/src/IpRangeHelper.cs b/src/IpRangeHelper.cs new file mode 100644 index 0000000..c0aa90b --- /dev/null +++ b/src/IpRangeHelper.cs @@ -0,0 +1,40 @@ +using System.Net; + +namespace SddpViewer; + +public class IpRangeHelper +{ + public static IEnumerable GetIPRange(IPAddress startIp, IPAddress endIp) + { + uint start = IpToUint(startIp); + uint end = IpToUint(endIp); + + if (start > end) + { + (start, end) = (end, start); + } + + for (uint current = start; current <= end; current++) + { + yield return UintToIp(current); + } + } + + private static uint IpToUint(IPAddress ip) + { + byte[] bytes = ip.GetAddressBytes(); + if (bytes.Length != 4) + throw new ArgumentException("Nur IPv4 wird unterstützt."); + return (uint)((bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]); + } + + private static IPAddress UintToIp(uint ip) + { + byte[] bytes = new byte[4]; + bytes[0] = (byte)((ip >> 24) & 0xFF); + bytes[1] = (byte)((ip >> 16) & 0xFF); + bytes[2] = (byte)((ip >> 8) & 0xFF); + bytes[3] = (byte)(ip & 0xFF); + return new IPAddress(bytes); + } +} diff --git a/src/MainWindow.axaml b/src/MainWindow.axaml index 6e9cfc4..3fd0694 100644 --- a/src/MainWindow.axaml +++ b/src/MainWindow.axaml @@ -28,6 +28,7 @@