I have an app in Flutter that needs to check if 2 different IPs (for ex, 170.16.1.1 and 170.16.1.2) and want to check if they belong to the same network. I believe I also need the network mask for that, right?
How to achieve this in Dart language?
I have an app in Flutter that needs to check if 2 different IPs (for ex, 170.16.1.1 and 170.16.1.2) and want to check if they belong to the same network. I believe I also need the network mask for that, right?
How to achieve this in Dart language?
I think this code might work for IPv4:
void main() {
print('192.168.0.1 is ${checkSameSubnet('192.168.0.1','192.168.9.2', 12)?' ':'NOT'} in the same /12 subnet as 192.168.9.2');
print('192.168.0.1 is ${checkSameSubnet('192.168.0.1','192.168.9.2', 24)?' ':'NOT'} in the same /24 subnet as 192.168.9.2');
}
bool checkSameSubnet(String ip1, String ip2, int netmask){
String ipv4Pattern =
r"^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$"; // https://stackoverflow.com/a/36760050/4062341
assert(RegExp(ipv4Pattern).hasMatch(ip1),'ip1 must be a valid IPv4 address');
assert(RegExp(ipv4Pattern).hasMatch(ip2),'ip2 must be a valid IPv4 address');
// print(Uri.parseIPv4Address(ip1)); // [192, 168, 0, 1]
// print(Uri.parseIPv4Address(ip1)
// .map((e) => e.toRadixString(2))); // ('11000000', '10101000', '0', '1')
// print(Uri.parseIPv4Address(ip1)
// .map((e) => e.toRadixString(2).padLeft(8, '0'))); // ('11000000', '10101000', '00000000', '00000001') fill them up with leading 0s
// print(Uri.parseIPv4Address(ip1).fold(
// '', (prev, e) => '$prev${e.toRadixString(2).padLeft(8, '0')}')); // 11000000101010000000000000000001 merge them all
String firstIp = Uri.parseIPv4Address(ip1).fold(
'', (prev, e) => '$prev${e.toRadixString(2).padLeft(8, '0')}');
String secondIp = Uri.parseIPv4Address(ip2).fold(
'', (prev, e) => '$prev${e.toRadixString(2).padLeft(8, '0')}');
// check match length of the subnet mask
return firstIp.substring(0,netmask) == secondIp.substring(0,netmask);
}
First I make sure both IPs really are Ipv4 format using assert()
. For IPv6 you would need a different regex pattern.
Then convert them to [int] using Uri.parseIPv4Address()
.
Now I convert them each to binary notation and add the implicit leading zeros to get them all to 8 bit length.
In the return
statement I check if both treated IPs are matching for the netmask length.
This works for the private networks (10.0.0.0/8
, 172.16.0.0/12
and 192.168.0.0/16
).