/* Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
 * Portions Copyright © 1997-1999 Vita Nuova Limited
 * Portions Copyright © 2000-2007 Vita Nuova Holdings Limited
 *                                (www.vitanuova.com)
 * Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
 *
 * Modified for the Akaros operating system:
 * Copyright (c) 2013-2014 The Regents of the University of California
 * Copyright (c) 2013-2015 Google Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE. */

#include <slab.h>
#include <kmalloc.h>
#include <kref.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <error.h>
#include <cpio.h>
#include <pmap.h>
#include <smp.h>
#include <net/ip.h>

enum {
	Nlog = 4 * 1024,
};

/*
 *  action log
 */
struct Netlog {
	spinlock_t lock;
	int opens;
	char *buf;
	char *end;
	char *rptr;
	int len;

	int logmask;				/* mask of things to debug */
	uint8_t iponly[IPaddrlen];	/* ip address to print debugging for */
	int iponlyset;

	qlock_t qlock;
	struct rendez r;
};

typedef struct Netlogflag {
	char *name;
	int mask;
} Netlogflag;

static Netlogflag flags[] = {
	{"ppp", Logppp,},
	{"ip", Logip,},
	{"fs", Logfs,},
	{"tcp", Logtcp,},
	{"il", Logil,},
	{"icmp", Logicmp,},
	{"udp", Logudp,},
	{"compress", Logcompress,},
	{"ilmsg", Logil | Logilmsg,},
	{"gre", Loggre,},
	{"tcpreset", Logtcp | Logtcpreset,},
	{"tcprxmt", Logtcp | Logtcprxmt,},
	{"tcpall", Logtcp | Logtcpreset | Logtcprxmt | Logtcpverbose,},
	{"udpmsg", Logudp | Logudpmsg,},
	{"ipmsg", Logip | Logipmsg,},
	{"esp", Logesp,},
	{NULL, 0,},
};

enum {
	CMset,
	CMclear,
	CMonly,
};

static
struct cmdtab routecmd[] = {
	{CMset, "set", 0},
	{CMclear, "clear", 0},
	{CMonly, "only", 0},
};

void netloginit(struct Fs *f)
{
	f->alog = kzmalloc(sizeof(struct Netlog), 0);
	spinlock_init(&f->alog->lock);
	qlock_init(&f->alog->qlock);
	rendez_init(&f->alog->r);
}

void netlogopen(struct Fs *f)
{
	ERRSTACK(1);
	spin_lock(&f->alog->lock);
	if (waserror()) {
		spin_unlock(&f->alog->lock);
		nexterror();
	}
	if (f->alog->opens == 0) {
		if (f->alog->buf == NULL)
			f->alog->buf = kzmalloc(Nlog, 0);
		f->alog->rptr = f->alog->buf;
		f->alog->end = f->alog->buf + Nlog;
	}
	f->alog->opens++;
	spin_unlock(&f->alog->lock);
	poperror();
}

void netlogclose(struct Fs *f)
{
	ERRSTACK(1);
	spin_lock(&f->alog->lock);
	if (waserror()) {
		spin_unlock(&f->alog->lock);
		nexterror();
	}
	f->alog->opens--;
	if (f->alog->opens == 0) {
		kfree(f->alog->buf);
		f->alog->buf = NULL;
	}
	spin_unlock(&f->alog->lock);
	poperror();
}

static int netlogready(void *a)
{
	struct Fs *f = a;

	return f->alog->len;
}

long netlogread(struct Fs *f, void *a, uint32_t unused, long n)
{
	ERRSTACK(1);
	int i, d;
	char *p, *rptr;

	qlock(&f->alog->qlock);
	if (waserror()) {
		qunlock(&f->alog->qlock);
		nexterror();
	}

	for (;;) {
		spin_lock(&f->alog->lock);
		if (f->alog->len) {
			if (n > f->alog->len)
				n = f->alog->len;
			d = 0;
			rptr = f->alog->rptr;
			f->alog->rptr += n;
			if (f->alog->rptr >= f->alog->end) {
				d = f->alog->rptr - f->alog->end;
				f->alog->rptr = f->alog->buf + d;
			}
			f->alog->len -= n;
			spin_unlock(&f->alog->lock);

			i = n - d;
			p = a;
			memmove(p, rptr, i);
			memmove(p + i, f->alog->buf, d);
			break;
		} else
			spin_unlock(&f->alog->lock);

		rendez_sleep(&f->alog->r, netlogready, f);
	}

	qunlock(&f->alog->qlock);
	poperror();

	return n;
}

void netlogctl(struct Fs *f, char *s, int n)
{
	ERRSTACK(1);
	int i, set = 0;
	Netlogflag *fp;
	struct cmdbuf *cb;
	struct cmdtab *ct;

	cb = parsecmd(s, n);
	if (waserror()) {
		kfree(cb);
		nexterror();
	}

	if (cb->nf < 2)
		error(EINVAL, ERROR_FIXME);

	ct = lookupcmd(cb, routecmd, ARRAY_SIZE(routecmd));

	switch (ct->index) {
		case CMset:
			set = 1;
			break;

		case CMclear:
			set = 0;
			break;

		case CMonly:
			parseip(f->alog->iponly, cb->f[1]);
			if (ipcmp(f->alog->iponly, IPnoaddr) == 0)
				f->alog->iponlyset = 0;
			else
				f->alog->iponlyset = 1;
			kfree(cb);
			poperror();
			return;

		default:
			cmderror(cb, "unknown ip control message");
	}

	for (i = 1; i < cb->nf; i++) {
		for (fp = flags; fp->name; fp++)
			if (strcmp(fp->name, cb->f[i]) == 0)
				break;
		if (fp->name == NULL)
			continue;
		if (set)
			f->alog->logmask |= fp->mask;
		else
			f->alog->logmask &= ~fp->mask;
	}

	kfree(cb);
	poperror();
}

void netlog(struct Fs *f, int mask, char *fmt, ...)
{
	char buf[256], *t, *fp;
	int i, n;
	va_list arg;
	struct timespec ts_now;

	if (!(f->alog->logmask & mask))
		return;

	if (f->alog->opens == 0)
		return;

	/* Same style as trace_printk */
	if (likely(__proc_global_info.tsc_freq))
		ts_now = tsc2timespec(read_tsc());
	n = snprintf(buf, sizeof(buf), "[%lu.%09lu]: ",
	             ts_now.tv_sec, ts_now.tv_nsec);

	va_start(arg, fmt);
	n += vsnprintf(buf + n, sizeof(buf) - n, fmt, arg);
	va_end(arg);

	spin_lock(&f->alog->lock);
	i = f->alog->len + n - Nlog;
	if (i > 0) {
		f->alog->len -= i;
		f->alog->rptr += i;
		if (f->alog->rptr >= f->alog->end)
			f->alog->rptr = f->alog->buf + (f->alog->rptr - f->alog->end);
	}
	t = f->alog->rptr + f->alog->len;
	fp = buf;
	f->alog->len += n;
	while (n-- > 0) {
		if (t >= f->alog->end)
			t = f->alog->buf + (t - f->alog->end);
		*t++ = *fp++;
	}
	spin_unlock(&f->alog->lock);

	rendez_wakeup(&f->alog->r);
}
