/*
 * Andreas Henriksson <andreas@fatal.se>, 2005-07-22.
 *
 * Converts dotted-quad netmasks into number of bits.
 */

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

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

/* this table stolen from:
 * http://lists.debian.org/debian-security/2003/03/msg00239.html
 */
static const uint32_t tab[] = {
  0x00000000,			/* 0 */
  0x80000000,			/* 1 */
  0xC0000000,			/* 2 */
  0xE0000000,			/* 3 */
  0xF0000000,			/* 4 */
  0xF8000000,			/* 5 */
  0xFC000000,			/* 6 */
  0xFE000000,			/* 7 */
  0xFF000000,			/* 8 */
  0xFF800000,			/* 9 */
  0xFFC00000,			/* 10 */
  0xFFE00000,			/* 11 */
  0xFFF00000,			/* 12 */
  0xFFF80000,			/* 13 */
  0xFFFC0000,			/* 14 */
  0xFFFE0000,			/* 15 */
  0xFFFF0000,			/* 16 */
  0xFFFF8000,			/* 17 */
  0xFFFFC000,			/* 18 */
  0xFFFFE000,			/* 19 */
  0xFFFFF000,			/* 20 */
  0xFFFFF800,			/* 21 */
  0xFFFFFC00,			/* 22 */
  0xFFFFFE00,			/* 23 */
  0xFFFFFF00,			/* 24 */
  0xFFFFFF80,			/* 25 */
  0xFFFFFFC0,			/* 26 */
  0xFFFFFFE0,			/* 27 */
  0xFFFFFFF0,			/* 28 */
  0xFFFFFFF8,			/* 29 */
  0xFFFFFFFC,			/* 30 */
  0xFFFFFFFE,			/* 31 */
  0xFFFFFFFF			/* 32 */
};



int main(int argc, char *argv[])
{
	char *netmask, *tmp;
	long int bits;
	int nmparts[4];
	int err, i;
	struct in_addr in;
	unsigned long mask;
	
	if (argc < 2) {
		fprintf(stderr, "Usage: %s <netmask>\nExample: %s 255.255.128.0\n", argv[0], argv[0]);
		exit(1);
	}

	netmask = argv[1];
	
	bits = strtol(netmask, &tmp, 10);
	if (tmp == NULL && bits >= 0 && bits < LONG_MAX) {
		printf("Netmask given in bits (no conversion): %d\n", bits);
		exit(0);
	}

	err = inet_pton(AF_INET, netmask, &in);
	mask = ntohl(in.s_addr);

	printf("sizeof(tab):%d", sizeof(tab));
	
	for (i=32; i >= 0; i--) {
		if (mask == tab[i]) {
			printf("Netmask in bits (converted): %d\n", i);
			exit(0);
		}
	}

	fprintf(stderr, "Invalid netmask specified.\n");
	
	return 2;
}

