Skip to content

Commit

Permalink
ARP Data for Linux and Macos
Browse files Browse the repository at this point in the history
  • Loading branch information
git-elliot committed Sep 5, 2023
1 parent 25e92f9 commit 0825b7e
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 14 deletions.
1 change: 1 addition & 0 deletions lib/src/host_scanner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ class HostScanner {
final activeHostFound =
ActiveHost.fromSendableActiveHost(sendableActiveHost: message);
await activeHostFound.resolveInfo();
log.fine("Found host: ${await activeHostFound.toStringFull()}");
yield activeHostFound;
} else if (message is String && message == 'Done') {
isolate.kill();
Expand Down
28 changes: 21 additions & 7 deletions lib/src/models/active_host.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import 'package:dart_ping/dart_ping.dart';
import 'package:network_tools/src/models/arp_data.dart';
import 'package:network_tools/src/models/arp_table.dart';
import 'package:network_tools/src/models/mdns_info.dart';
import 'package:network_tools/src/models/open_port.dart';
import 'package:network_tools/src/models/sendable_active_host.dart';
Expand Down Expand Up @@ -46,6 +48,8 @@ class ActiveHost extends Comparable<ActiveHost> {
}

deviceName = setDeviceName();
// fetch entry from in memory arp table
arpData = setARPData();
}
factory ActiveHost.buildWithAddress({
required String address,
Expand Down Expand Up @@ -84,13 +88,8 @@ class ActiveHost extends Comparable<ActiveHost> {
);
}

Future<void> resolveInfo() async {
await deviceName;
await mdnsInfo;
await hostName;
}

static const generic = 'Generic Device';

InternetAddress internetAddress;

/// The device specific number in the ip address. In IPv4 numbers after the
Expand All @@ -106,6 +105,10 @@ class ActiveHost extends Comparable<ActiveHost> {
/// Mdns information of this device
late Future<MdnsInfo?> mdnsInfo;

/// Resolve ARP data for this host.
/// only supported on Linux, Macos and Windows otherwise null
late Future<ARPData?> arpData;

/// List of all the open port of this device
List<OpenPort> openPorts;

Expand Down Expand Up @@ -165,6 +168,17 @@ class ActiveHost extends Comparable<ActiveHost> {
return null;
}

Future<void> resolveInfo() async {
await deviceName;
await mdnsInfo;
await hostName;
await arpData;
}

Future<ARPData?> setARPData() async {
return ARPTable.entryFor(address);
}

/// Try to find the mdns name of this device, if not exist mdns name will
/// be null
/// TODO: search mdns name for each device
Expand Down Expand Up @@ -204,6 +218,6 @@ class ActiveHost extends Comparable<ActiveHost> {
}

Future<String> toStringFull() async {
return 'Address: $address, HostId: $hostId Time: ${responseTime?.inMilliseconds}ms, DeviceName: ${await deviceName}, HostName: ${await hostName}, MdnsInfo: ${await mdnsInfo}';
return 'Address: $address, MAC: ${(await arpData)!.macAddress}, HostId: $hostId Time: ${responseTime?.inMilliseconds}ms, DeviceName: ${await deviceName}, HostName: ${await hostName}, MdnsInfo: ${await mdnsInfo}';
}
}
26 changes: 26 additions & 0 deletions lib/src/models/arp_data.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import 'dart:io';

class ARPData {
ARPData({
required this.host,
required this.iPAddress,
required this.macAddress,
required this.interfaceName,
required this.interfaceType,
});

final String? host;
final String? iPAddress;
final String? macAddress;
final String? interfaceName;
final String? interfaceType;

@override
String toString() {
//TODO: add platform specific format
if (Platform.isMacOS) {
return '$host ($iPAddress) at $macAddress on $interfaceName ifscope [$interfaceType]';
}
return '$host ($iPAddress) at $macAddress on $interfaceName ifscope [$interfaceType]';
}
}
46 changes: 46 additions & 0 deletions lib/src/models/arp_table.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import 'dart:convert';
import 'dart:io';

import 'package:network_tools/src/models/arp_data.dart';

class ARPTable {
static final arpTable = <String, ARPData>{};
static bool resolved = false;

static Future<ARPData?> entryFor(String address) async {
if (resolved) return arpTable[address];
final result = await Process.run('arp', ['-a']);
final entries = const LineSplitter().convert(result.stdout.toString());
RegExp? pattern;
if (Platform.isMacOS) {
pattern = RegExp(
r'(?<host>[\w.?]*)\s\((?<ip>.*)\)\sat\s(?<mac>.*)\son\s(?<intf>\w+)\sifscope\s*(\w*)\s*\[(?<typ>.*)\]',
);
} else if (Platform.isLinux) {
pattern = RegExp(
r'(?<host>[\w.?]*)\s\((?<ip>.*)\)\sat\s(?<mac>.*)\s\[(?<typ>.*)\]\son\s(?<intf>\w+)',
);
} else {
//todo: implement windows regex
return null;
}
for (final entry in entries) {
final match = pattern.firstMatch(entry);
if (match != null) {
final arpData = ARPData(
host: match.namedGroup("host"),
iPAddress: match.namedGroup("ip"),
macAddress: match.namedGroup("mac"),
interfaceName: match.namedGroup("intf"),
interfaceType: match.namedGroup("typ"),
);
final key = arpData.iPAddress;
if (key != null) {
arpTable[key] = arpData;
}
}
}
resolved = true;
return arpTable[address];
}
}
14 changes: 7 additions & 7 deletions test/network_tools_test.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import 'dart:async';

import 'package:intl/intl.dart';
import 'package:logging/logging.dart';
import 'package:network_tools/network_tools.dart';
import 'package:test/test.dart';
Expand All @@ -8,12 +8,12 @@ import 'package:universal_io/io.dart';
void main() {
final log = Logger("host_scan_test");

// Logger.root.level = Level.FINE;
// Logger.root.onRecord.listen((record) {
// print(
// '${DateFormat.Hms().format(record.time)}: ${record.level.name}: ${record.loggerName}: ${record.message}',
// );
// });
Logger.root.level = Level.FINE;
Logger.root.onRecord.listen((record) {
print(
'${DateFormat.Hms().format(record.time)}: ${record.level.name}: ${record.loggerName}: ${record.message}',
);
});

int port = 0;
int firstHostId = 0;
Expand Down

0 comments on commit 0825b7e

Please sign in to comment.