Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Standard/safe way to check if IP address is in range/subnet

I have a small piece of code that converts a 32-bit unsigned integer (ie: uint32_t) into a set of four 8-bit fields, treats it like an IP address, and then reports to the client if it falls within a predetermined range of IP addresses.

I've already found a few different examples of code in C that shows me how to get the IP address of a client from the struct sockaddr_in that contains it, along with a C# answer. However, I would like to break down the address a bit further, keep it in pure C, and wanted to know a few quick things:

  1. Is the internal representation consistent from system to system, or do I ever need to do Endian-ness checks/correction on the s_addr field?
  2. Are there standard macros along the lines of CLASS_C_NETMASK, CLASS_B_NETMASK, etc, that would be more appropriate than using manually generated masks (ie: 0xFF000000, 0x00FF0000, etc).
  3. Are there any existing functions in the sockets library that will do checks if an IP address is in a range of IP addresses or matches a subnet mask?

Thanks.

like image 423
Cloud Avatar asked Jun 25 '15 02:06

Cloud


1 Answers

Is the internal representation consistent from system to system, or do I ever need to do Endian-ness checks/correction on the s_addr field?

s_addr is always in network (big endian) byte order on all platforms.

Are there standard macros along the lines of CLASS_C_NETMASK, CLASS_B_NETMASK, etc, that would be more appropriate than using manually generated masks (ie: 0xFF000000, 0x00FF0000, etc).

No, nor would it make sense to use such macros, as subnet masks are not fixed from one network to another. You need to provide your code with an actual network IP and its subnet mask (prompt the user, query the OS, etc). You can then calculate the subnet's starting and ending IPs to compare against your target IP:

uint32_t ip = ...; // value to check
uint32_t netip = ...; // network ip to compare with
uint32_t netmask = ...; // network ip subnet mask
uint32_t netstart = (netip & netmask); // first ip in subnet
uint32_t netend = (netstart | ~netmask); // last ip in subnet
if ((ip >= netstart) && (ip <= netend))
    // is in subnet range...
else
    // not in subnet range...

Or simpler, mask both network IP and target IP with the subnet mask and see if the resulting values are the same (ie, they are the same subnet):

uint32_t ip = ...; // value to check
uint32_t netip = ...; // network ip to compare with
uint32_t netmask = ...; // network ip subnet mask
if ((netip & netmask) == (ip & netmask))
    // is on same subnet...
else
    // not on same subnet...

Are there any existing functions in the sockets library that will do checks if an IP address is in a range of IP addresses or matches a subnet mask?

No. But it is trivial to implement manually, it only takes a few lines of code, as shown above.

like image 125
Remy Lebeau Avatar answered Nov 17 '22 19:11

Remy Lebeau