/*
 * $Id: cidr.c,v 1.1 2003/05/08 17:59:34 raptor Exp $
 *
 * cidr.c - quick parser for classless inter domain routing
 * Copyright (c) 2003 Marco Ivaldi <raptor@0xdeadbeef.info>
 *
 * root@voodoo:~# ./cidr 192.168.1.0/30
 * 192.168.1.0
 * 192.168.1.1
 * 192.168.1.2
 * 192.168.1.3
 *
 * Thanks to megat0n <megat0n@mediaservice.net>.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main(int argc, char **argv)
{
	struct in_addr in;
	unsigned long mask = 0xffffffff, val = 0x0, ip;
	unsigned int maskval = 32;
	char *iparg, *maskarg = (char *)NULL;

	if (argc < 2) {
		fprintf(stderr, "Usage: %s <ip/cidr>\n", argv[0]);
		exit(1);
	}

	/* get command line argument */
	iparg = (char *)strdup(argv[1]);

	/* get netmask and ip address */
	if ( (maskarg = strchr(iparg, '/')) ) {
		*maskarg = 0;
		maskarg++;
	}

	/* check the ip address */
	if ( ( ip = (unsigned long)(inet_addr(iparg)) ) == 0xffffffff ) {
		fprintf(stderr, "Error: must specify a valid ip\n");
		exit(-1);
	}

	/* check the netmask */
	if ( maskarg )
		maskval = (unsigned long)atol(maskarg);

	if ( (!maskval) || (maskval > 32) ) {
		fprintf(stderr, "Error: cidr must be in 1-32 range\n");
		exit(-1);
	}

	mask = (mask << ((unsigned long)(32 - maskval)));

	/* normalize the ip address */
	ip = ntohl(ip) & mask;

	while ( maskarg && (maskval != 32) ) {

		/* netid + hosts */
		if (val^(~mask)) {
			in.s_addr = ntohl(ip|val);
			fprintf(stderr, "%s\n", inet_ntoa(in));
		} else
			break;

		++val;
	}

	/* broadcast (or host/32) */
	in.s_addr = ntohl(ip|val);
	fprintf(stderr, "%s\n", inet_ntoa(in));

	free(iparg);

	exit(0);
}
