#include <string.h>
#include "config.h"
#include "kerbind.h"
#include "atarierr.h"
#include "sockios.h"
#include "buf.h"
#include "if.h"
#include "bpf.h"

static struct netif if_loopback;

static long	loop_open	(struct netif *);
static long	loop_close	(struct netif *);
static long	loop_output	(struct netif *, BUF *, char *, short, short);
static long	loop_ioctl	(struct netif *, short, long);

static long
loop_open (nif)
	struct netif *nif;
{
	return 0;
}

static long
loop_close (nif)
	struct netif *nif;
{
	return 0;
}

static long
loop_output (nif, buf, hwaddr, hwlen, pktype)
	struct netif *nif;
	BUF *buf;
	char *hwaddr;
	short hwlen, pktype;
{
	long r;

	++nif->out_packets;
	if (nif->bpf && BUF_LEAD_SPACE (buf) >= 4) {
		/*
		 * Add 4 byte dummy header containing the address
		 * family for the packet type.
		 */
		long af = (pktype == PKTYPE_IP) ? AF_INET : AF_UNSPEC;

		buf->dstart -= 4;
		*(long *)buf->dstart = af;
		bpf_input (nif, buf);
		buf->dstart += 4;
	}
	if ((r = if_input (&if_loopback, buf, 0, pktype))) {
		++nif->in_errors;
		return r;
	} else {
		++nif->in_packets;
		return 0;
	}
}

static long
loop_ioctl (nif, cmd, arg)
	struct netif *nif;
	short cmd;
	long arg;
{
	switch (cmd) {
	case SIOCSIFFLAGS:
		return 0;
		
	case SIOCSIFADDR:
		nif->flags |= (IFF_UP|IFF_RUNNING);
		return 0;

	case SIOCSIFNETMASK:
		return 0;
	}
	return EINVFN;
}

void
loopback_init (void)
{
	strcpy (if_loopback.name, "lo");
	if_loopback.unit = 0;
	if_loopback.metric = 0;
	if_loopback.flags = IFF_LOOPBACK|IFF_BROADCAST;
	if_loopback.mtu = 2*8192;
	if_loopback.timer = 0;
	if_loopback.hwtype = HWTYPE_NONE;

	if_loopback.rcv.maxqlen = IF_MAXQ;
	if_loopback.snd.maxqlen = IF_MAXQ;
	if_loopback.open = loop_open;
	if_loopback.close = loop_close;
	if_loopback.output = loop_output;
	if_loopback.ioctl = loop_ioctl;
	if_loopback.timeout = 0;

	if_loopback.data = 0;

	/*
	 * Rest of initialization is done in if_register
	 */
	if_register (&if_loopback);
}
