/*
 * cidr_get - Get and return various semi-raw bits of info
 */
#include "config.h"

#include <errno.h>
#include <stdlib.h>
#include <string.h>

#include "cidr.h"
#include "abstract_mem.h"

/* Get the prefix length */
int cidr_get_pflen(const CIDR * block)
{
	int i, j;
	int foundnmh;
	int pflen;

	/* Where do we start? */
	if (block->proto == CIDR_IPV4)
		i = 12;
	else if (block->proto == CIDR_IPV6)
		i = 0;
	else {
		errno = ENOENT;	/* Bad errno */
		return (-1);	/* Unknown */
	}

	/*
	 * We're intentionally not supporting non-contiguous netmasks.  So,
	 * if we find one, bomb out.
	 */
	foundnmh = 0;
	pflen = 0;
	for ( /* i */ ; i <= 15; i++) {
		for (j = 7; j >= 0; j--) {
			if ((block->mask)[i] & (1 << j)) {
				/*
				 * This is a network bit (1).  If we've already seen a
				 * host bit (0), we need to bomb.
				 */
				if (foundnmh == 1) {
					errno = EINVAL;
					return (-1);
				}

				pflen++;
			} else
				foundnmh = 1;	/* A host bit */
		}
	}

	/* If we get here, return the length */
	return (pflen);
}

/* Get the address bits */
uint8_t *cidr_get_addr(const CIDR * addr)
{
	uint8_t *toret;

	toret = gsh_calloc(16, sizeof(uint8_t));

	/* Copy 'em in */
	memcpy(toret, addr->addr, sizeof(addr->addr));

	return (toret);
}

/* Get the netmask bits */
uint8_t *cidr_get_mask(const CIDR * addr)
{
	uint8_t *toret;

	toret = gsh_calloc(16, sizeof(uint8_t));

	/* Copy 'em in */
	memcpy(toret, addr->mask, sizeof(addr->mask));

	return (toret);
}

/* Get the protocol */
int cidr_get_proto(const CIDR * addr)
{
	return (addr->proto);
}
