using PacketDotNet; using Parsing_Packets.Models; using SharpPcap; using System.Net.NetworkInformation; using System.Text; using System.Text.Json; namespace Parsing_Packets.Helpers; internal static class HelperPhysicalAddress { private static string GetPhysicalAddress(PhysicalAddress physicalAddress, char c) { StringBuilder results = new(); string d = physicalAddress.ToString().ToLower(); for (int i = 0; i < d.Length; i += 2) _ = results.Append(d[i]).Append(d[i + 1]).Append(c); results = results.Remove(results.Length - 1, 1); return results.ToString(); } private static string GetPhysicalAddress(PhysicalAddress physicalAddress) => $"{GetPhysicalAddress(physicalAddress, '-')} | {GetPhysicalAddress(physicalAddress, ':')}"; private static void AddPacket(PhysicalAddressConfiguration physicalAddressConfiguration, ILogger logger, string file, string physicalAddress, string ipv4Address, bool isSuggestion) { List? collection; Dictionary> keyValuePairs = GetKeyValuePairs(file); if (!keyValuePairs.TryGetValue(physicalAddress, out collection)) { keyValuePairs.Add(physicalAddress, []); if (!keyValuePairs.TryGetValue(physicalAddress, out collection)) throw new Exception(); } if (ipv4Address.StartsWith(physicalAddressConfiguration.IPV4Filter) && (collection.Count < 2 || (!isSuggestion && collection[^1] != ipv4Address))) { logger.LogInformation(""); if (collection.Count == 0) collection.Add($"block-{physicalAddress[^2..]}"); else logger.LogInformation(collection[0]); if (collection.Count < 2) collection.Add(DateTime.Now.ToString("yyyy-MM-dd_HH-mm")); else { logger.LogInformation(collection[1]); _ = collection.Remove(ipv4Address); } collection.Add(ipv4Address); logger.LogInformation(ipv4Address); logger.LogInformation(physicalAddress); string json = JsonSerializer.Serialize(keyValuePairs, HelperPhysicalAddressDictionarySourceGenerationContext.Default.DictionaryStringListString); File.WriteAllText(file, json); } } private static void AddArpPacket(PhysicalAddressConfiguration physicalAddressConfiguration, ILogger logger, string file, EthernetPacket ethernetPacket, ArpPacket arpPacket) { string ipv4Address = arpPacket.SenderProtocolAddress.ToString(); string physicalAddress = GetPhysicalAddress(ethernetPacket.SourceHardwareAddress); AddPacket(physicalAddressConfiguration, logger, file, physicalAddress, ipv4Address, isSuggestion: false); } private static void AddDhcpPacket(PhysicalAddressConfiguration physicalAddressConfiguration, ILogger logger, string file, DhcpV4Packet dhcpV4Packet) { string ipv4Address; string physicalAddress; if (dhcpV4Packet.MessageType is DhcpV4MessageType.Request or DhcpV4MessageType.Ack) { ipv4Address = dhcpV4Packet.ClientAddress.ToString(); physicalAddress = GetPhysicalAddress(dhcpV4Packet.ClientHardwareAddress); bool isSuggestion = dhcpV4Packet.MessageType is DhcpV4MessageType.Request; AddPacket(physicalAddressConfiguration, logger, file, physicalAddress, ipv4Address, isSuggestion); } else { ipv4Address = dhcpV4Packet.ClientAddress.ToString(); physicalAddress = GetPhysicalAddress(dhcpV4Packet.ClientHardwareAddress); AddPacket(physicalAddressConfiguration, logger, file, physicalAddress, ipv4Address, isSuggestion: true); } } private static void AddIpv4Packet(PhysicalAddressConfiguration physicalAddressConfiguration, ILogger logger, string file, EthernetPacket ethernetPacket, IPv4Packet ipv4Packet) { string ipv4Address = ipv4Packet.SourceAddress.ToString(); string physicalAddress = GetPhysicalAddress(ethernetPacket.SourceHardwareAddress); AddPacket(physicalAddressConfiguration, logger, file, physicalAddress, ipv4Address, isSuggestion: true); } private static void ParseEthernetPacket(PhysicalAddressConfiguration physicalAddressConfiguration, ILogger logger, string file, EthernetPacket ethernetPacket) { for (int i = 0; i < 1; i++) { if (physicalAddressConfiguration.UseARP && ethernetPacket?.PayloadPacket is ArpPacket arpPacket) { if (arpPacket.Operation != ArpOperation.Response) continue; AddArpPacket(physicalAddressConfiguration, logger, file, ethernetPacket, arpPacket); } else if (ethernetPacket?.PayloadPacket is IPv4Packet ipv4Packet) { if (ipv4Packet.SourceAddress.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork) continue; if (!ipv4Packet.SourceAddress.ToString().StartsWith(physicalAddressConfiguration.IPV4Filter)) continue; if (ipv4Packet.PayloadPacket is UdpPacket udpPacket && udpPacket.PayloadPacket is DhcpV4Packet dhcpV4Packet) AddDhcpPacket(physicalAddressConfiguration, logger, file, dhcpV4Packet); else AddIpv4Packet(physicalAddressConfiguration, logger, file, ethernetPacket, ipv4Packet); } } } private static Dictionary> GetKeyValuePairs(string file) { Dictionary> keyValuePairs; if (!File.Exists(file)) keyValuePairs = []; else { string json = File.ReadAllText(file); keyValuePairs = JsonSerializer.Deserialize(json, HelperPhysicalAddressDictionarySourceGenerationContext.Default.DictionaryStringListString) ?? []; } return keyValuePairs; } internal static bool ParsePackets(AppSettings appSettings, ILogger logger) { ILiveDevice? liveDevice = null; Version version = Pcap.SharpPcapVersion; CaptureDeviceList devices = CaptureDeviceList.Instance; logger.LogInformation("PacketDotNet example using SharpPcap {version}", version); if (devices.Count < 1) logger.LogInformation("No devices were found on this machine"); else { Packet packet; RawCapture rawCapture; GetPacketStatus status; if (!Directory.Exists(appSettings.PhysicalAddressConfiguration.Directory)) _ = Directory.CreateDirectory(appSettings.PhysicalAddressConfiguration.Directory); string file = Path.Combine(appSettings.PhysicalAddressConfiguration.Directory, ".json"); logger.LogInformation(""); logger.LogInformation("The following devices are available on this machine:"); logger.LogInformation("----------------------------------------------------"); logger.LogInformation(""); foreach (ILiveDevice? device in devices) { logger.LogInformation("{Name} {Description}", device.Name, device.Description); if (device.Name != appSettings.PhysicalAddressConfiguration.DeviceName) continue; liveDevice = device; } if (liveDevice is null) logger.LogInformation("No devices matched {DeviceName}", appSettings.PhysicalAddressConfiguration.DeviceName); else { logger.LogInformation(""); liveDevice.Open(DeviceModes.Promiscuous, appSettings.PhysicalAddressConfiguration.ReadTimeoutMilliseconds); logger.LogInformation("-- Listening on {Name} {Description}", liveDevice.Name, liveDevice.Description); while (true) { status = liveDevice.GetNextPacket(out PacketCapture e); if (status != GetPacketStatus.PacketRead) continue; rawCapture = e.GetPacket(); packet = Packet.ParsePacket(rawCapture.GetLinkLayers(), rawCapture.Data); if (packet is not EthernetPacket ethernetPacket) continue; ParseEthernetPacket(appSettings.PhysicalAddressConfiguration, logger, file, ethernetPacket); } } } return true; } }