Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Preventing Exception when resolving Hostname

I'm trying to make a app that scans a network for ARP requests and list all existing network devices. Currently I use SharpPcap and PacketDoNet.

When resolving the hostname according to the given IP, I get a SocketException when resolving a "unknown" host. So I've put this in a try/catch. Since I think this is bad style (to ignore exceptions), I'm searching for a different solution.

Here is some code:

// Button for scanning the network
private void btnStartScanningForClients_Click(object sender, RoutedEventArgs e)
{
    // Check for correct interface
    // [...]

    // Start scanning process
    if (!this.netWorkItOut.Startet)
    {
        // Dis-/Enable visual controls
        // [...]

        // Start scanning
        var index = this.cbNetworkInterface.SelectedIndex
        this.netWorkItOut.StartDevice(index);
        this.netWorkItOut.Scanner.StartScanningNetwork(resolveHostnames);
    }
}

This is the controlling object, that holds the scanner, takes care for events, accepts the packets and puts them into a queue

public void StartDevice(int deviceIndex)
{
    this.Startet = true;
    // [...]
    this.Device = WinPcapDeviceList.Instance[deviceIndex];

    // Activate Scanner
    this.Scanner = new Scanner(this.DeviceInfo);

    // Subscribe Events
    // [...]

    this.Device.Open(DeviceMode.Promiscuous, 1);
    this.Device.Filter = "(arp || ip || ip6)";

    this.Device.OnPacketArrival += device_OnPacketArrival;
    this.Device.StartCapture();
}

private void device_OnPacketArrival(object sender, CaptureEventArgs e)
{
    //PacketDoNet
    Packet packet;

    try
    { packet = Packet.ParsePacket(LinkLayers.Ethernet, e.Packet.Data); }
    catch (Exception)
    { return;  }

    if (packet is EthernetPacket)
    {
        var arp = ARPPacket.GetEncapsulated(packet);

        if (arp != null)
        {
            if (this.Scanner.Started)
            {
                lock (this.Scanner.PacketQueueARP)
                {
                    this.Scanner.PacketQueueARP.Add(arp);
                }
            }
        }
    }
}

This is Controlling object and Scanner class. The scanner class works the ARP requests and resolves the hostnames

public void StartScanningNetwork(bool resolveHostnames)
{
    // [...]
    this.ResolveHostnames = resolveHostnames;

    // start worker to listen for ARP packets
    this.workerARP = new Thread(WorkerARP);
    this.workerARP.Name = "Scanner thread (ARP)";
    this.workerARP.Start();

    this.Started = true;
}

private void WorkerARP()
{
    List<IPAddress> processedIps = new List<IPAddress>();

    // copy packets from storage queue to thread queue for processing
    while (Started)
    {
        // [...]

        if (this.threadQueueARP.Count > 0)
        {
            foreach (var packet in this.threadQueueARP)
            {
                // [...]

                if (!processedIps.Contains(ip))
                {
                    // [...]

                    if (this.ResolveHostnames)
                    {
                        var resolveHostnamesTask = Task.Factory.StartNew(ResolveHostnamesWorker, ip);
                    }
                }
                // [...]
            }

            // [...]
        }
        // [...]
    }

}

private void ResolveHostnamesWorker(object data)
{
    if (data is IPAddress)
    {
        var ip = (IPAddress)data;
        var hostname = "";

        try
        {
            hostname = Dns.GetHostEntry(ip).HostName;
        }
        catch { }

        // Raise Event for hostname resolved
    }
}

Its all about the line hostname = Dns.GetHostEntry(ip).HostName

So: How can I avoid using a try/catch when resolving a HostEntry via Dns.GetHostEntry()? Is there a function that return just null if there is no known host?

Thanks in advance!

like image 696
Radinator Avatar asked Sep 10 '26 09:09

Radinator


1 Answers

As far as I know there is no method like TryGetHostName() that would not throw an exception.

But in my opinion it is legible to catch exceptions as far as you expect them. So you should limit catching exceptions to the ones you expect:

private void ResolveHostnamesWorker(object data)
{
    if (data is IPAddress)
    {
        var ip = (IPAddress)data;
        var hostname = "";

        try
        {
            hostname = Dns.GetHostEntry(ip).HostName;
        }
        catch(SocketException socketException)
        {
            // maybe limit handling based on data in socketException and
            // call throw; to rethrow exception if not the expected one
        }

    // Raise Event for hostname resolved
}

}

like image 91
Roland Bär Avatar answered Sep 12 '26 23:09

Roland Bär