/* For terms of usage/redistribution/modification see the LICENSE file */
/* For authors and contributors see the AUTHORS file */

#include "iptraf-ng-compat.h"

// TODO: full rewrite

/*
 * Returns a binary subnet mask based on the number of mask bits.  The
 * dotted-decimal notation may be obtained with inet_ntoa.
 */
unsigned long cidr_get_mask(unsigned int maskbits)
{
	struct in_addr mask;

	if (maskbits == 0)
		return 0;

	inet_aton("255.255.255.255", &mask);
	mask.s_addr = htonl(mask.s_addr << (32 - maskbits));

	return mask.s_addr;
}

/*
 * Returns a subnet mask in dotted-decimal notation given the number of
 * 1-bits in the mask.
 */
char *cidr_get_quad_mask(unsigned int maskbits)
{
	struct in_addr addr;

	addr.s_addr = cidr_get_mask(maskbits);
	return inet_ntoa(addr);
}

/*
 * Returns the number of 1-bits in the given binary subnet mask in
 * network byte order.
 */
unsigned int cidr_get_maskbits(unsigned long mask)
{
	unsigned int i = 32;

	if (mask == 0)
		return 0;

	mask = ntohl(mask);
	while (mask % 2 == 0) {
		mask >>= 1;
		i--;
	}

	return i;
}

/*
 * Splits a CIDR-style address/mask string into its constituent address and
 * mask parts.  In case of absent or invalid input in the mask part, 255 is
 * returned in *maskbits (255 is invalid for an IPv4 address).
 */
void cidr_split_address(char *cidr_addr, char *addresspart,
			unsigned int *maskbits)
{
	char maskpart[4];
	char *endptr;
	char *slashptr;

	char address_buffer[80];

	if (strchr(cidr_addr, '/') == NULL) {
		strncpy(addresspart, cidr_addr, 80);
		*maskbits = 255;
		return;
	}

	memset(address_buffer, 0, 80);
	memset(addresspart, 0, 80);
	memset(maskpart, 0, 4);

	strncpy(address_buffer, cidr_addr, 80);
	slashptr = strchr(address_buffer, '/');

	/*
	 * Cut out the mask part and move past the slash
	 */
	*slashptr = '\0';
	slashptr++;

	/*
	 * Copy out the address and mask parts into their buffers.
	 */
	strncpy(addresspart, address_buffer, 80);
	strncpy(maskpart, slashptr, 4);

	if (maskpart[0] != '\0') {
		*maskbits = strtoul(maskpart, &endptr, 10);
		if (*endptr != '\0')
			*maskbits = 255;
	} else
		*maskbits = 255;

	return;
}
