2

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?

Daniel Oliveira
  • 8,053
  • 11
  • 40
  • 76

1 Answers1

0

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).