Conversion of IP address to integer [duplicate]

2019-01-26 12:31发布

Possible Duplicate:
IP Address to Integer - C

How do I convert an IP address to integer which has the following form: A.B.. or A.B.C.* or A...* or ... I want to write a C program which can determine if an IP address is a subset of another. e.g the IP address 192.168.125.5 is a subset of 192.168... Now I want to convert both the IP addresses to unique integers and subsequently check if one is a subset of the other. Is there a way to achieve this?

标签: c networking
4条回答
甜甜的少女心
2楼-- · 2019-01-26 12:40

The easy and non-general way is to use sscanf (with int a, b, c, d): sscanf(ip, "%d.%d.%d.%d", &a, &b, &c, &d); But it works only if you have ip with with all the sections: 10.47.100.1

If this is not the case, you can still use the returned value of sscanf, which will tell you how many matching it succeeded to find (or EOF).

After havin the 4 numbers you can check for subset relationship.

查看更多
Emotional °昔
3楼-- · 2019-01-26 12:44

What you want is to determine if an IP address is in a subnet, and to do that you want to apply a netmask. There are probably (certainly) libraries already out there to do what you want. This is if you want to roll your own.

If this IP address comes from a trusted source (ie, not a user), then you can simply extract the IP address from a standard C-string by doing something like:

char ipAddressString[16] = "192.168.125.5"
char netMaskString[16] = "255.255.0.0"
char subnetString[16] = "192.168.0.0"

uint32_t ipAddress = parseIPV4string(ipAddressString);
uint32_t netmask = parseIPV4string(netmaskString);
uint32_t subnet = parseIPV4string(subnetString);

if (ipAddress & netmask == subnet) {
  return true;
}

uint32_t parseIPV4string(char* ipAddress) {
  char ipbytes[4];
  sscanf(ipAddress, "%uhh.%uhh.%uhh.%uhh", &ipbytes[3], &ipbytes[2], &ipbytes[1], &ipbytes[0]);
  return ipbytes[0] | ipbytes[1] << 8 | ipbytes[2] << 16 | ipbytes[3] << 24;
}
查看更多
趁早两清
4楼-- · 2019-01-26 12:47

An IP address, e.g. 192.168.0.1 can be written as an integer easily by writing it in hex which becomes 0xC0 0xA8 0x00 0x01 or just 0xC0A80001

Then it's just a case of bit matching, so you construct a corresponding subnet mask, 255.255.0.0 which is just 0xFFFF0000 and you can test that both match by doing:

0xC0A80001 & 0xFFFF0000 == 0xC0A80000 & 0xFFFF0000

where one side of the equality test is the "base stuff you care about" and the other side is a real address, with a given mask being the same on both sides.

In general you can construct a suitable mask by setting things which are '*' to be 0 and things which are actual numbers to be 0xFF, if you want finer grain masks it's hard to express with '*'.

查看更多
一纸荒年 Trace。
5楼-- · 2019-01-26 12:56

A single integer (assuming 32-bit) is not enough to represent what you're outlining. You need more information in order to be able to express the asterisks.

For instance, you could have a pair of (address,netmask), where the netmask either is a single small integer representing the number of valid high-order bits, so that for instance a network address such as "10.0.0.0" could be represented by the pair (0x0a000000, 8). If you really want to be able to have wildcards "wherever" in the address for some reason, you need a full set of one flag bit per address bit, so two 32-bit integers. Then you could represent something like "192.168.." as the pair (0xc0a80000, 0xffff0000).

查看更多
登录 后发表回答