#include <stdint.h>
#include <stdio.h>
#include <string.h>

typedef /*u*/int32_t ip;
typedef char ips[17];

ip atoip(char *s) {
	ip ip = 0;
	while (*s) {
		if (*s == '.')
			ip <<= 8;
		else
			ip += (ip & 255) * 10 + *s - '0' - (ip & 255);
		++s;
	}
	return ip;
}

void spip(ips s, ip ip) {
	memset(s, ' ', sizeof (ips));
	s += sizeof (ips);
	char b;
	for (b = 0; b < 32; b += 8) {
		*--s = b ? '.' : 0;
		unsigned char c = ip >> b & 255;
		do {
			*--s = '0' + c % 10;
			c = (c - c % 10) / 10;
		} while (c > 0);
	}
	/*sprintf(s, "%.3u.%.3u.%.3u.%.3u",
		   ip >> 24 & 255,
		   ip >> 16 & 255,
		   ip >>  8 & 255,
		   ip >>  0 & 255);//*/
}

void putip(ip ip) {
	ips ips; spip(ips, ip); puts(ips);
}

// Subnet the network, one bit at a time
int subnet(ip network, ip netmask, char ***nv) {
	network &= netmask;
	if (!~netmask)
		return 0;
	
	ip length = ~netmask + 1;
	printf("length1 : %u %u\n", length, network & length);
	
	int n = 0, o = 0;
	if (**nv) {
		o = atoi(**nv) + 2;
		if (length >= o) {
			if (length >> 1 > o) {
				subnet(network, netmask >> 1, nv);
				subnet(network + (length >> 1), netmask >> 1, nv);
				return;
			} else
				n = o;
		}
	}
	
	printf("length2 : %u %u\n", length, network & length);
	ips nws, nwf, nwl, nwb, nms;
	spip(nws, network);
	spip(nwf, network + 1);
	spip(nwl, network | ~netmask - 1);
	spip(nwb, network | ~netmask);
	spip(nms, netmask);
	printf("%s | %s | %s | %s | %s | %u/%u hosts\n",
		   nws, nwf, nwl, nwb, nms, n ? n - 2 : 0, length - 2);
	
	if (n)
		*nv += 1;
	
	return n;
}

int main(int argc, char *argv[]) {
	if (argc < 4) {
		puts("Usage : vlsm network netmask N...\n"
			 " network : IPv4 address (N.N.N.N)\n"
			 " network : IPv4 address (N.N.N.N)\n"
			 " N : Number of hosts in a network.");
		return 1;
	}
	
	//putip(atoip("1.22.255.23"));
	
	/*putip(atoip("255.255.255.0") >> 1);
	putip(~(atoip("255.255.255.0") >> 1));*/
	
	char **nv = argv + 3;
	
	subnet(atoip(argv[1]), atoip(argv[2]), &nv);
	
	return 0;
}
