Skip to content

Instantly share code, notes, and snippets.

@citrin
Created December 4, 2012 11:28
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save citrin/4202877 to your computer and use it in GitHub Desktop.
Save citrin/4202877 to your computer and use it in GitHub Desktop.
Convert IPv4 range to list of CIDR prefixes
#include <arpa/inet.h>
#include <assert.h>
#include <err.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#define IPv4_BITS 32
static inline int min(int a, int b)
{
return (a < b ? a : b);
}
static void
print_cidr(const char *start_ip, const char *end_ip)
{
struct in_addr ip;
uint32_t start, end;
int zero_bits, bits;
if (!inet_aton(start_ip, &ip))
err(1, "inet_aton() for %s failed", start_ip);
start = ntohl(ip.s_addr);
if (!inet_aton(end_ip, &ip))
err(1, "inet_aton() for %s failed", end_ip);
end = ntohl(ip.s_addr);
if(start > end)
errx(1, "bad IP order: %s - %s", start_ip, end_ip);
while (start <= end) {
/* trailing zeros in IP determine max possible
* prefix size for this IP
*/
zero_bits = start == 0 ? IPv4_BITS : ffs(start) - 1;
/* ip count in this prefix: 2^bits */
bits = min(fls(end - start + 1) - 1, zero_bits);
ip.s_addr = htonl(start);
printf("%s/%d\n", inet_ntoa(ip), IPv4_BITS - bits);
start += 1 << bits;
}
return;
}
int
main(int argc, char *argv[])
{
/* check, that IP address fits into int */
assert(sizeof(int) >= sizeof(uint32_t));
printf("CIDR ranges for 192.168.0.1-192.168.255.254:\n");
print_cidr("192.168.0.1", "192.168.255.254");
printf("\n");
printf("CIDR ranges for 0.0.0.1-255.255.255.254:\n");
print_cidr("0.0.0.1", "255.255.255.254");
exit(0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment