/*
 * This file is part of the UCB release of Plan 9. It is subject to the license
 * terms in the LICENSE file found in the top-level directory of this
 * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
 * part of the UCB release of Plan 9, including this file, may be copied,
 * modified, propagated, or distributed except according to the terms contained
 * in the LICENSE file.
 */
#include <stdlib.h>

#include <iplib/iplib.h>
#include <parlib/parlib.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>

#include <dirent.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>

static uint8_t loopbacknet[IPaddrlen] = {
	0, 0, 0, 0,
	0, 0, 0, 0,
	0, 0, 0xff, 0xff,
	127, 0, 0, 0
};
static uint8_t loopbackmask[IPaddrlen] = {
	0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff,
	0xff, 0xff, 0xff, 0xff,
	0xff, 0, 0, 0
};

#define NFIELD 200
#define nelem(x) (sizeof(x) / sizeof(x[0]))
static struct ipifc **_readoldipifc(char *buf, struct ipifc **l, int index)
{
	char *f[NFIELD];
	int i, n;
	struct ipifc *ifc;
	struct iplifc *lifc, **ll;

	/* allocate new interface */
	*l = ifc = calloc(sizeof(struct ipifc), 1);
	if (ifc == NULL)
		return l;
	l = &ifc->next;
	ifc->index = index;

	n = tokenize(buf, f, NFIELD);
	if (n < 2)
		return l;

	strncpy(ifc->dev, f[0], sizeof ifc->dev);
	ifc->dev[sizeof(ifc->dev) - 1] = 0;
	ifc->mtu = strtoul(f[1], NULL, 10);

	ll = &ifc->lifc;
	for (i = 2; n - i >= 7; i += 7) {
		/* allocate new local address */
		*ll = lifc = calloc(sizeof(struct iplifc), 1);
		ll = &lifc->next;

		parseip(lifc->ip, f[i]);
		parseipmask(lifc->mask, f[i + 1]);
		parseip(lifc->net, f[i + 2]);
		ifc->pktin = strtoul(f[i + 3], NULL, 10);
		ifc->pktout = strtoul(f[i + 4], NULL, 10);
		ifc->errin = strtoul(f[i + 5], NULL, 10);
		ifc->errout = strtoul(f[i + 6], NULL, 10);
	}
	return l;
}

static char *findfield(char *name, char **f, int n)
{
	int i;

	for (i = 0; i < n - 1; i++)
		if (strcmp(f[i], name) == 0)
			return f[i + 1];
	return "";
}

static struct ipifc **_readipifc(char *file, struct ipifc **l, int index)
{
	int i, n, fd, lines;
	char buf[4 * 1024];
	char *line[32];
	char *f[64];
	struct ipifc *ifc, **l0;
	struct iplifc *lifc, **ll;

	/* read the file */
	fd = open(file, O_RDONLY);
	if (fd < 0)
		return l;
	n = 0;
	while ((i = read(fd, buf + n, sizeof(buf) - 1 - n)) > 0 &&
	       n < sizeof(buf) - 1)
		n += i;
	buf[n] = 0;
	close(fd);

	if (strncmp(buf, "device", 6) != 0)
		return _readoldipifc(buf, l, index);
	/* ignore ifcs with no associated device */
	if (strncmp(buf + 6, "  ", 2) == 0)
		return l;
	/* allocate new interface */
	*l = ifc = calloc(sizeof(struct ipifc), 1);
	if (ifc == NULL)
		return l;
	l0 = l;
	l = &ifc->next;
	ifc->index = index;

	lines = getfields(buf, line, nelem(line), 1, "\n");

	/* pick off device specific info(first line) */
	n = tokenize(line[0], f, nelem(f));
	if (n % 2 != 0)
		goto lose;
	strncpy(ifc->dev, findfield("device", f, n), sizeof(ifc->dev));
	ifc->dev[sizeof(ifc->dev) - 1] = 0;
	if (ifc->dev[0] == 0) {
	lose:
		free(ifc);
		*l0 = NULL;
		return l;
	}
	ifc->mtu = strtoul(findfield("maxtu", f, n), NULL, 10);
	ifc->sendra6 = atoi(findfield("sendra", f, n));
	ifc->recvra6 = atoi(findfield("recvra", f, n));
	ifc->rp.mflag = atoi(findfield("mflag", f, n));
	ifc->rp.oflag = atoi(findfield("oflag", f, n));
	ifc->rp.maxraint = atoi(findfield("maxraint", f, n));
	ifc->rp.minraint = atoi(findfield("minraint", f, n));
	ifc->rp.linkmtu = atoi(findfield("linkmtu", f, n));
	ifc->rp.reachtime = atoi(findfield("reachtime", f, n));
	ifc->rp.rxmitra = atoi(findfield("rxmitra", f, n));
	ifc->rp.ttl = atoi(findfield("ttl", f, n));
	ifc->rp.routerlt = atoi(findfield("routerlt", f, n));
	ifc->pktin = strtoul(findfield("pktin", f, n), NULL, 10);
	ifc->pktout = strtoul(findfield("pktout", f, n), NULL, 10);
	ifc->errin = strtoul(findfield("errin", f, n), NULL, 10);
	ifc->errout = strtoul(findfield("errout", f, n), NULL, 10);

	/* now read the addresses */
	ll = &ifc->lifc;
	for (i = 1; i < lines; i++) {
		n = tokenize(line[i], f, nelem(f));
		if (n < 5)
			break;

		/* allocate new local address */
		*ll = lifc = calloc(sizeof(struct iplifc), 1);
		ll = &lifc->next;

		parseip(lifc->ip, f[0]);
		parseipmask(lifc->mask, f[1]);
		parseip(lifc->net, f[2]);

		lifc->validlt = strtoul(f[3], NULL, 10);
		lifc->preflt = strtoul(f[4], NULL, 10);
	}

	return l;
}

void free_ipifc(struct ipifc *ifc)
{
	struct ipifc *next;
	struct iplifc *lnext, *lifc;

	if (ifc == NULL)
		return;
	for (; ifc; ifc = next) {
		next = ifc->next;
		for (lifc = ifc->lifc; lifc; lifc = lnext) {
			lnext = lifc->next;
			free(lifc);
		}
		free(ifc);
	}
}

/* This will free @ifc when passed in.  Some old Plan 9 programs might rely on
 * it still (like our ping, netstat, ipconfig).  It usually ends up be a
 * thread-unsafe disaster. */
struct ipifc *readipifc(char *net, struct ipifc *ifc, int index)
{
	int fd, i, n;
	struct dir *dir;
	char directory[128];
	char buf[128];
	struct ipifc **l;

	free_ipifc(ifc);

	l = &ifc;
	ifc = NULL;

	if (net == 0)
		net = "/net";
	snprintf(directory, sizeof(directory), "%s/ipifc", net);

	if (index >= 0) {
		snprintf(buf, sizeof(buf), "%s/%d/status", directory, index);
		_readipifc(buf, l, index);
	} else {
		DIR *d;
		struct dirent *de;
		d = opendir(directory);
		if (!d)
			return NULL;

		while (de = readdir(d)) {
			if (strcmp(de->d_name, "clone") == 0)
				continue;
			if (strcmp(de->d_name, "stats") == 0)
				continue;
			snprintf(buf, sizeof(buf), "%s/%s/status", directory,
				 de->d_name);
			l = _readipifc(buf, l, atoi(de->d_name));
		}
		closedir(d);
	}

	return ifc;
}

/* Gets the local interface that isn't the friggin' loopback address.  When
 * you're done, free_ipifc(ifc).  Returns 0 on failure. */
struct iplifc *get_first_noloop_iplifc(char *net, struct ipifc **ifc)
{
	struct ipifc *nifc;
	struct iplifc *lifc;
	uint8_t mynet[IPaddrlen];

	*ifc = readipifc(net, NULL, -1);
	for (nifc = *ifc; nifc; nifc = nifc->next) {
		for (lifc = nifc->lifc; lifc; lifc = lifc->next) {
			maskip(lifc->ip, loopbackmask, mynet);
			if (ipcmp(mynet, loopbacknet) == 0)
				continue;
			if (ipcmp(lifc->ip, IPnoaddr) != 0)
				return lifc;
		}
	}
	free_ipifc(*ifc);
	return 0;
}
