/*
 * IP address pool functions.
 * Copyright (C) 2003, 2004 Mondru AB.
 * Copyright (C) 2017 by Harald Welte <laforge@gnumonks.org>
 *
 * The contents of this file may be used under the terms of the GNU
 * General Public License Version 2, provided that the above copyright
 * notice and this permission notice is included in all copies or
 * substantial portions of the software.
 * 
 */

#include <sys/types.h>
#include <netinet/in.h>		/* in_addr */
#include <stdlib.h>		/* calloc */
#include <stdio.h>		/* sscanf */
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include "syserr.h"
#include "ippool.h"
#include "lookup.h"

int ippool_printaddr(struct ippool_t *this)
{
	unsigned int n;
	printf("ippool_printaddr\n");
	printf("Firstdyn %d\n", this->firstdyn - this->member);
	printf("Lastdyn %d\n", this->lastdyn - this->member);
	printf("Firststat %d\n", this->firststat - this->member);
	printf("Laststat %d\n", this->laststat - this->member);
	printf("Listsize %d\n", this->listsize);

	for (n = 0; n < this->listsize; n++) {
		char s[256];
		in46a_ntop(&this->member[n].addr, s, sizeof(s));
		printf("Unit %d inuse %d prev %d next %d addr %s\n",
		       n,
		       this->member[n].inuse,
		       this->member[n].prev - this->member,
		       this->member[n].next - this->member,
		       s);
	}
	return 0;
}

int ippool_hashadd(struct ippool_t *this, struct ippoolm_t *member)
{
	uint32_t hash;
	struct ippoolm_t *p;
	struct ippoolm_t *p_prev = NULL;

	/* Insert into hash table */
	hash = ippool_hash(&member->addr) & this->hashmask;
	for (p = this->hash[hash]; p; p = p->nexthash)
		p_prev = p;
	if (!p_prev)
		this->hash[hash] = member;
	else
		p_prev->nexthash = member;
	return 0;		/* Always OK to insert */
}

int ippool_hashdel(struct ippool_t *this, struct ippoolm_t *member)
{
	uint32_t hash;
	struct ippoolm_t *p;
	struct ippoolm_t *p_prev = NULL;

	/* Find in hash table */
	hash = ippool_hash(&member->addr) & this->hashmask;
	for (p = this->hash[hash]; p; p = p->nexthash) {
		if (p == member) {
			break;
		}
		p_prev = p;
	}

	if (p != member) {
		SYS_ERR(DIP, LOGL_ERROR, 0,
			"ippool_hashdel: Tried to delete member not in hash table");
		return -1;
	}

	if (!p_prev)
		this->hash[hash] = p->nexthash;
	else
		p_prev->nexthash = p->nexthash;

	return 0;
}

static unsigned long int ippool_hash4(struct in_addr *addr)
{
	return lookup((unsigned char *)&addr->s_addr, sizeof(addr->s_addr), 0);
}

static unsigned long int ippool_hash6(struct in6_addr *addr, unsigned int len)
{
	/* TODO: Review hash spread for IPv6 */
	return lookup((unsigned char *)addr->s6_addr, len, 0);
}

unsigned long int ippool_hash(struct in46_addr *addr)
{
	if (addr->len == 4)
		return ippool_hash4(&addr->v4);
	else
		return ippool_hash6(&addr->v6, addr->len);
}

/* Get IP address and mask */
int ippool_aton(struct in46_addr *addr, size_t *prefixlen, const char *pool_in, int number)
{
	struct addrinfo *ai;
	struct addrinfo hints = {
		.ai_family = AF_UNSPEC,
		.ai_socktype = SOCK_DGRAM,
		.ai_flags = 0,
		.ai_protocol = 0
	};
	char pool[strlen(pool_in)+1];

	strcpy(pool, pool_in);

	int err;

	/* Find '/' and point to first char after it */
	char *prefixlen_str = strchr(pool, '/');
	if (prefixlen_str) {
		*prefixlen_str = '\0';
		prefixlen_str++;
		if (*prefixlen_str == '\0') {
			SYS_ERR(DIP, LOGL_ERROR, 0, "Empty prefix length specified");
			return -1;
		}
	}

	/* convert address */
	if ((err = getaddrinfo(pool, NULL, &hints, &ai))) {
		SYS_ERR(DIP, LOGL_ERROR, 0, "Bad address");
		return -1;
	}

	/* Copy address, set lengths */
	if (ai->ai_family == AF_INET) {
		*prefixlen = 32;
		addr->len = sizeof(struct in_addr);
		addr->v4 = ((struct sockaddr_in*)ai->ai_addr)->sin_addr;
	} else {
		*prefixlen = 128;
		addr->len = sizeof(struct in6_addr);
		addr->v6 = ((struct sockaddr_in6*)ai->ai_addr)->sin6_addr;
	}
	freeaddrinfo(ai);

	/* parse prefixlen */
	if (prefixlen_str) {
		char *e;
		*prefixlen = strtol(prefixlen_str, &e, 10);
		if (*e != '\0') {
			SYS_ERR(DIP, LOGL_ERROR, 0, "Prefixlen is not an int");
			return -1;
		}
	}

	if (*prefixlen > (addr->len * 8)) {
		SYS_ERR(DIP, LOGL_ERROR, 0, "Perfixlen too big");
		return -1;
	}

	return 0;
}

/* Increase IPv4/IPv6 address by 1 */
void in46a_inc(struct in46_addr *addr)
{
	size_t addrlen;
	uint8_t *a = (uint8_t *)&addr->v6;
	for (addrlen = addr->len; addrlen > 0; addrlen--) {
		if (++a[addrlen-1])
			break;
	}
}

/* Create new address pool */
int ippool_new(struct ippool_t **this, const char *dyn, const char *stat,
	       int allowdyn, int allowstat, int flags)
{

	/* Parse only first instance of pool for now */

	int i;
	struct in46_addr addr;
	size_t addrprefixlen;
	struct in46_addr stataddr;
	size_t stataddrprefixlen;
	int listsize;
	int dynsize;
	unsigned int statsize;

	if (!allowdyn) {
		dynsize = 0;
	} else {
		if (ippool_aton(&addr, &addrprefixlen, dyn, 0)) {
			SYS_ERR(DIP, LOGL_ERROR, 0,
				"Failed to parse dynamic pool");
			return -1;
		}
		/* we want to work with /64 prefixes, i.e. allocate /64 prefixes rather
		 * than /128 (single IPv6 addresses) */
		if (addr.len == sizeof(struct in6_addr))
			addr.len = 64/8;

		/* Set IPPOOL_NONETWORK if IPPOOL_NOGATEWAY is set */
		if (flags & IPPOOL_NOGATEWAY) {
			flags |= IPPOOL_NONETWORK;
		}

		dynsize = (1 << (addr.len*8 - addrprefixlen)) -1;
		if (flags & IPPOOL_NONETWORK)	/* Exclude network address from pool */
			dynsize--;
		if (flags & IPPOOL_NOGATEWAY)	/* Exclude gateway address from pool */
			dynsize--;
		if (flags & IPPOOL_NOBROADCAST)	/* Exclude broadcast address from pool */
			dynsize--;
	}

	if (!allowstat) {
		statsize = 0;
		stataddr.len = 0;
		stataddrprefixlen = 0;
	} else {
		if (ippool_aton(&stataddr, &stataddrprefixlen, stat, 0)) {
			SYS_ERR(DIP, LOGL_ERROR, 0,
				"Failed to parse static range");
			return -1;
		}

		statsize = (1 << (addr.len - addrprefixlen + 1)) -1;
		if (statsize > IPPOOL_STATSIZE)
			statsize = IPPOOL_STATSIZE;
	}

	listsize = dynsize + statsize;	/* Allocate space for static IP addresses */

	if (!(*this = calloc(sizeof(struct ippool_t), 1))) {
		SYS_ERR(DIP, LOGL_ERROR, 0,
			"Failed to allocate memory for ippool");
		return -1;
	}

	(*this)->allowdyn = allowdyn;
	(*this)->allowstat = allowstat;
	if (stataddr.len > 0)
		(*this)->stataddr = stataddr;
	(*this)->stataddrprefixlen = stataddrprefixlen;

	(*this)->listsize += listsize;
	if (!((*this)->member = calloc(sizeof(struct ippoolm_t), listsize))) {
		SYS_ERR(DIP, LOGL_ERROR, 0,
			"Failed to allocate memory for members in ippool");
		return -1;
	}

	for ((*this)->hashlog = 0;
	     ((1 << (*this)->hashlog) < listsize); (*this)->hashlog++) ;

	/*   printf ("Hashlog %d %d %d\n", (*this)->hashlog, listsize, (1 << (*this)->hashlog)); */

	/* Determine hashsize */
	(*this)->hashsize = 1 << (*this)->hashlog;	/* Fails if mask=0: All Internet */
	(*this)->hashmask = (*this)->hashsize - 1;

	/* Allocate hash table */
	if (!
	    ((*this)->hash =
	     calloc(sizeof(struct ippoolm_t), (*this)->hashsize))) {
		SYS_ERR(DIP, LOGL_ERROR, 0,
			"Failed to allocate memory for hash members in ippool");
		return -1;
	}

	(*this)->firstdyn = NULL;
	(*this)->lastdyn = NULL;
	if (flags & IPPOOL_NOGATEWAY) {
		in46a_inc(&addr);
		in46a_inc(&addr);
	} else if (flags & IPPOOL_NONETWORK) {
		in46a_inc(&addr);
	}
	for (i = 0; i < dynsize; i++) {
		(*this)->member[i].addr = addr;
		in46a_inc(&addr);

		(*this)->member[i].inuse = 0;

		/* Insert into list of unused */
		(*this)->member[i].prev = (*this)->lastdyn;
		if ((*this)->lastdyn) {
			(*this)->lastdyn->next = &((*this)->member[i]);
		} else {
			(*this)->firstdyn = &((*this)->member[i]);
		}
		(*this)->lastdyn = &((*this)->member[i]);
		(*this)->member[i].next = NULL;	/* Redundant */

		(void)ippool_hashadd(*this, &(*this)->member[i]);
	}

	(*this)->firststat = NULL;
	(*this)->laststat = NULL;
	for (i = dynsize; i < listsize; i++) {
		struct in46_addr *i6al = &(*this)->member[i].addr;
		memset(i6al, 0, sizeof(*i6al));
		(*this)->member[i].inuse = 0;

		/* Insert into list of unused */
		(*this)->member[i].prev = (*this)->laststat;
		if ((*this)->laststat) {
			(*this)->laststat->next = &((*this)->member[i]);
		} else {
			(*this)->firststat = &((*this)->member[i]);
		}
		(*this)->laststat = &((*this)->member[i]);
		(*this)->member[i].next = NULL;	/* Redundant */
	}

	if (0)
		(void)ippool_printaddr(*this);
	return 0;
}

/* Delete existing address pool */
int ippool_free(struct ippool_t *this)
{
	free(this->hash);
	free(this->member);
	free(this);
	return 0;		/* Always OK */
}

/* Find an IP address in the pool */
int ippool_getip(struct ippool_t *this, struct ippoolm_t **member,
		 struct in46_addr *addr)
{
	struct ippoolm_t *p;
	uint32_t hash;

	/* Find in hash table */
	hash = ippool_hash(addr) & this->hashmask;
	for (p = this->hash[hash]; p; p = p->nexthash) {
		if (in46a_prefix_equal(&p->addr, addr)) {
			if (member)
				*member = p;
			return 0;
		}
	}
	if (member)
		*member = NULL;
	/*SYS_ERR(DIP, LOGL_ERROR, 0, "Address could not be found"); */
	return -1;
}

/**
 * ippool_newip
 * Get an IP address. If addr = 0.0.0.0 get a dynamic IP address. Otherwise
 * check to see if the given address is available. If available within
 * dynamic address space allocate it there, otherwise allocate within static
 * address space.
**/
int ippool_newip(struct ippool_t *this, struct ippoolm_t **member,
		 struct in46_addr *addr, int statip)
{
	struct ippoolm_t *p;
	struct ippoolm_t *p2 = NULL;
	uint32_t hash;

	/* If static:
	 *   Look in dynaddr. 
	 *     If found remove from firstdyn/lastdyn linked list.
	 *   Else allocate from stataddr.
	 *    Remove from firststat/laststat linked list.
	 *    Insert into hash table.
	 *
	 * If dynamic
	 *   Remove from firstdyn/lastdyn linked list.
	 *
	 */

	if (0)
		(void)ippool_printaddr(this);

	int specified = 0;
	if (addr) {
		if (addr->len == 4 && addr->v4.s_addr)
			specified = 1;
		if (addr->len == 16 && !IN6_IS_ADDR_UNSPECIFIED(&addr->v6))
			specified = 1;
	}

	/* First check to see if this type of address is allowed */
	if (specified && statip) {	/* IP address given */
		if (!this->allowstat) {
			SYS_ERR(DIP, LOGL_ERROR, 0,
				"Static IP address not allowed");
			return -GTPCAUSE_NOT_SUPPORTED;
		}
		if (!in46a_within_mask(addr, &this->stataddr, this->stataddrprefixlen)) {
			SYS_ERR(DIP, LOGL_ERROR, 0, "Static out of range");
			return -1;
		}
	} else {
		if (!this->allowdyn) {
			SYS_ERR(DIP, LOGL_ERROR, 0,
				"Dynamic IP address not allowed");
			return -GTPCAUSE_NOT_SUPPORTED;
		}
	}

	/* If IP address given try to find it in dynamic address pool */
	if (specified) {	/* IP address given */
		/* Find in hash table */
		hash = ippool_hash(addr) & this->hashmask;
		for (p = this->hash[hash]; p; p = p->nexthash) {
			if (in46a_prefix_equal(&p->addr, addr)) {
				p2 = p;
				break;
			}
		}
	}

	/* If IP was already allocated we can not use it */
	if ((!statip) && (p2) && (p2->inuse)) {
		p2 = NULL;
	}

	/* If not found yet and dynamic IP then allocate dynamic IP */
	if ((!p2) && (!statip)) {
		if (!this->firstdyn) {
			SYS_ERR(DIP, LOGL_ERROR, 0,
				"No more IP addresses available");
			return -GTPCAUSE_ADDR_OCCUPIED;
		} else
			p2 = this->firstdyn;
	}

	if (p2) {		/* Was allocated from dynamic address pool */
		if (p2->inuse) {
			SYS_ERR(DIP, LOGL_ERROR, 0,
				"IP address allready in use");
			return -GTPCAUSE_SYS_FAIL;	/* Allready in use / Should not happen */
		}

		if (p2->addr.len != addr->len && !(addr->len == 16 && p2->addr.len == 8)) {
			SYS_ERR(DIP, LOGL_ERROR, 0, "MS requested unsupported PDP context type");
			return -GTPCAUSE_UNKNOWN_PDP;
		}

		/* Remove from linked list of free dynamic addresses */
		if (p2->prev)
			p2->prev->next = p2->next;
		else
			this->firstdyn = p2->next;
		if (p2->next)
			p2->next->prev = p2->prev;
		else
			this->lastdyn = p2->prev;
		p2->next = NULL;
		p2->prev = NULL;
		p2->inuse = 1;	/* Dynamic address in use */

		*member = p2;
		if (0)
			(void)ippool_printaddr(this);
		return 0;	/* Success */
	}

	/* It was not possible to allocate from dynamic address pool */
	/* Try to allocate from static address space */

	if (specified  && (statip)) {	/* IP address given */
		if (!this->firststat) {
			SYS_ERR(DIP, LOGL_ERROR, 0,
				"No more IP addresses available");
			return -GTPCAUSE_ADDR_OCCUPIED;	/* No more available */
		} else
			p2 = this->firststat;

		if (p2->addr.len != addr->len) {
			SYS_ERR(DIP, LOGL_ERROR, 0, "MS requested unsupported PDP context type");
			return -GTPCAUSE_UNKNOWN_PDP;
		}

		/* Remove from linked list of free static addresses */
		if (p2->prev)
			p2->prev->next = p2->next;
		else
			this->firststat = p2->next;
		if (p2->next)
			p2->next->prev = p2->prev;
		else
			this->laststat = p2->prev;
		p2->next = NULL;
		p2->prev = NULL;
		p2->inuse = 2;	/* Static address in use */
		memcpy(&p2->addr, addr, sizeof(addr));
		*member = p2;
		(void)ippool_hashadd(this, *member);
		if (0)
			(void)ippool_printaddr(this);
		return 0;	/* Success */
	}

	SYS_ERR(DIP, LOGL_ERROR, 0,
		"Could not allocate IP address");
	return -GTPCAUSE_SYS_FAIL;		/* Should never get here. TODO: Bad code */
}

int ippool_freeip(struct ippool_t *this, struct ippoolm_t *member)
{

	if (0)
		(void)ippool_printaddr(this);

	if (!member->inuse) {
		SYS_ERR(DIP, LOGL_ERROR, 0, "Address not in use");
		return -1;	/* Not in use: Should not happen */
	}

	switch (member->inuse) {
	case 0:		/* Not in use: Should not happen */
		SYS_ERR(DIP, LOGL_ERROR, 0, "Address not in use");
		return -1;
	case 1:		/* Allocated from dynamic address space */
		/* Insert into list of unused */
		member->prev = this->lastdyn;
		if (this->lastdyn) {
			this->lastdyn->next = member;
		} else {
			this->firstdyn = member;
		}
		this->lastdyn = member;

		member->inuse = 0;
		member->peer = NULL;
		if (0)
			(void)ippool_printaddr(this);
		return 0;
	case 2:		/* Allocated from static address space */
		if (ippool_hashdel(this, member))
			return -1;
		/* Insert into list of unused */
		member->prev = this->laststat;
		if (this->laststat) {
			this->laststat->next = member;
		} else {
			this->firststat = member;
		}
		this->laststat = member;

		member->inuse = 0;
		memset(&member->addr, 0, sizeof(member->addr));
		member->peer = NULL;
		member->nexthash = NULL;
		if (0)
			(void)ippool_printaddr(this);
		return 0;
	default:		/* Should not happen */
		SYS_ERR(DIP, LOGL_ERROR, 0,
			"Could not free IP address");
		return -1;
	}
}
