I write a simple C program that prints all the usable host addresses in a network.
Input
We provide the IP address
of our network and the subnet mask
.
Output
We print all the usable ip addresses that corresponds to the network.
Example
If we give the Ip 192.168.3.0
and the subnet 255.255.255.0
(/24
at CIDR) we get the following output:
192.168.3.1
192.168.3.2
192.168.3.3
192.168.3.4
...etc until 254
Problem
I don't get the results correctly.
Suppose we provide 192.168.3.0
and 255.255.255.0
. I currently use bpf_u_int32
type from pcap
lib to save both the ip
and the subnet mask
variables.
If I run the bellow code this is what I get as output:
0.3.168.193
0.3.168.194
0.3.168.195
0.3.168.196
0.3.168.197
0.3.168.198
0.3.168.199
0.3.168.200
0.3.168.201
0.3.168.202
0.3.168.203
0.3.168.204
0.3.168.205
0.3.168.206
0.3.168.207
0.3.168.208
0.3.168.209
0.3.168.210
0.3.168.211
0.3.168.212
0.3.168.213
0.3.168.214
0.3.168.215
0.3.168.216
0.3.168.217
0.3.168.218
0.3.168.219
0.3.168.220
0.3.168.221
0.3.168.222
0.3.168.223
0.3.168.224
0.3.168.225
0.3.168.226
0.3.168.227
0.3.168.228
0.3.168.229
0.3.168.230
...etc
Actual code
// suppose we have declare ip and subnet mask variables and passed values to it.
// bpf_u_int32 subnet_mask;
// bpf_u_int32 ip_address;
bpf_u_int32 x = subnet_mask;
int numbits; // get the CIDR Prefix
for (numbits = 0; x != 0; x >>= 1) {
if (x & 0x01) {
numbits++;
}
}
// determine maximum and minimum host values.
// we exclude the host and the broadcast (should we?)
unsigned long hoststart;
unsigned long hostend;
hoststart = 1;
hostend = (1 << (32 - numbits)) - 1;
// mask off the network
uint32_t network = ip_address & subnet_mask;
// Calculate all host addresses in the range
for (unsigned i = hoststart; i <= hostend; i++) {
uint32_t hostip;
int b1, b2, b3, b4;
char ipstr[16];
hostip = network + i;
b1 = (hostip & 0xff000000) >> 24;
b2 = (hostip & 0x00ff0000) >> 16;
b3 = (hostip & 0x0000ff00) >> 8;
b4 = (hostip & 0x000000ff);
snprintf(ipstr, sizeof(ipstr), "%d.%d.%d.%d", b1, b2, b3, b4);
printf("%s\n", ipstr);
}
Looks like an endianness issue.
The IP address and subnet mask are being stored in little endian format, which means the least significant byte is first. You need to swap the bytes using
htonl
.Then the bytes will be in the correct order.