parsing-packets/Helpers/HelperPhysicalAddress.cs
2024-02-03 20:07:23 -07:00

192 lines
9.4 KiB
C#

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 WriteAllText(ILogger<Worker> logger, string file, string physicalAddress, string ipv4Address, List<string> collection, Dictionary<string, List<string>> keyValuePairs)
{
logger.LogInformation("");
if (collection.Count == 2)
collection[1] = DateTime.Now.ToString("yyyy-MM-dd_HH-mm");
else if (collection.Count == 0)
{
collection.Add($"block-{physicalAddress[^2..]}");
collection.Add(DateTime.Now.ToString("yyyy-MM-dd_HH-mm"));
}
if (collection.Count > 1)
{
logger.LogInformation(collection[0]);
logger.LogInformation(collection[1]);
}
if (collection.Remove(ipv4Address))
collection[1] = DateTime.Now.ToString("yyyy-MM-dd_HH-mm");
collection.Add(ipv4Address);
logger.LogInformation(ipv4Address);
logger.LogInformation(physicalAddress);
string json = JsonSerializer.Serialize(keyValuePairs, HelperPhysicalAddressDictionarySourceGenerationContext.Default.DictionaryStringListString);
File.WriteAllText(file, json);
}
private static void AddPacket(PhysicalAddressConfiguration physicalAddressConfiguration, ILogger<Worker> logger, string file, List<string> history, string physicalAddress, string ipv4Address, bool isSuggestion)
{
List<string>? collection;
string key = $"{physicalAddress} - {ipv4Address}";
if (!history.Contains(key))
{
Dictionary<string, List<string>> 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)))
WriteAllText(logger, file, physicalAddress, ipv4Address, collection, keyValuePairs);
}
history.Add(key);
if (history.Count > physicalAddressConfiguration.RemoveHistoryAfter)
history.RemoveAt(0);
}
private static void AddArpPacket(PhysicalAddressConfiguration physicalAddressConfiguration, ILogger<Worker> logger, string file, List<string> history, EthernetPacket ethernetPacket, ArpPacket arpPacket)
{
string ipv4Address = arpPacket.SenderProtocolAddress.ToString();
string physicalAddress = GetPhysicalAddress(ethernetPacket.SourceHardwareAddress);
AddPacket(physicalAddressConfiguration, logger, file, history, physicalAddress, ipv4Address, isSuggestion: false);
}
private static void AddDhcpPacket(PhysicalAddressConfiguration physicalAddressConfiguration, ILogger<Worker> logger, string file, List<string> history, 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, history, physicalAddress, ipv4Address, isSuggestion);
}
else
{
ipv4Address = dhcpV4Packet.ClientAddress.ToString();
physicalAddress = GetPhysicalAddress(dhcpV4Packet.ClientHardwareAddress);
AddPacket(physicalAddressConfiguration, logger, file, history, physicalAddress, ipv4Address, isSuggestion: true);
}
}
private static void AddIpv4Packet(PhysicalAddressConfiguration physicalAddressConfiguration, ILogger<Worker> logger, string file, List<string> history, EthernetPacket ethernetPacket, IPv4Packet ipv4Packet)
{
string ipv4Address = ipv4Packet.SourceAddress.ToString();
string physicalAddress = GetPhysicalAddress(ethernetPacket.SourceHardwareAddress);
AddPacket(physicalAddressConfiguration, logger, file, history, physicalAddress, ipv4Address, isSuggestion: true);
}
private static void ParseEthernetPacket(PhysicalAddressConfiguration physicalAddressConfiguration, ILogger<Worker> logger, string file, List<string> history, 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, history, 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, history, dhcpV4Packet);
else
AddIpv4Packet(physicalAddressConfiguration, logger, file, history, ethernetPacket, ipv4Packet);
}
}
}
private static Dictionary<string, List<string>> GetKeyValuePairs(string file)
{
Dictionary<string, List<string>> 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<Worker> logger, CancellationToken stoppingToken)
{
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;
List<string> history = [];
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 (!stoppingToken.IsCancellationRequested)
{
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, history, ethernetPacket);
}
}
}
return true;
}
}