/*
 *	This file implements /dev/route. It is intended for controlling
 *	the behavior of the IP router and getting information
 *	about it.
 *
 *	02/28/94, kay roemer.
 */

#include "config.h"
#include "kerbind.h"
#include "file.h"
#include "atarierr.h"
#include "socket.h"
#include "net.h"
#include "util.h"
#include "in.h"
#include "if.h"
#include "route.h"
#include "dummydev.h"

#define SIN(x)		((struct sockaddr_in *)x)

/*
 * read() obtains this structure for every route
 */
struct route_info {
	char		nif[IF_NAMSIZ];	/* name of the interface */
	struct rtentry	rt;		/* route info */
};

static long	routedev_read	(FILEPTR *, char *, long);

static DEVDRV routedev = {
	dummydev_open, dummydev_write, routedev_read,
	dummydev_lseek, dummydev_ioctl, dummydev_datime,
	dummydev_close, dummydev_select, dummydev_unselect
};

static struct dev_descr routedev_descr = {
	&routedev, 0, 0, 0
};

static char routedev_name[] = "u:\\dev\\route";

extern struct route *allroutes[RT_HASH_SIZE];
extern struct route *defroute;


long
routedev_init (void)
{
	return dummydev_init (routedev_name, &routedev_descr);
}	

static long
routedev_read (fp, buf, nbytes)
	FILEPTR *fp;
	char *buf;
	long nbytes;
{
	struct route *rt = 0;	/* to keep gcc happy */
	struct route_info info, *infop = (struct route_info *)buf;
	int i, j;
	long space;
	extern void *memset (void *, int, unsigned long);

	for (space = nbytes; space >= sizeof (info); ++fp->pos) {
		rt = defroute;
		i = rt ? fp->pos-1 : fp->pos;
		for (j = 0; j < RT_HASH_SIZE && i >= 0; ++j) {
			rt = allroutes[j];
			for (; rt && --i >= 0; rt = rt->next);
		}
		if (j >= RT_HASH_SIZE) break;
		memset (&info, 0, sizeof (info));
		SIN (&info.rt.rt_dst)->sin_family = AF_INET;
		SIN (&info.rt.rt_dst)->sin_addr.s_addr = rt->net;
		if (rt->flags & RTF_GATEWAY) {
			SIN (&info.rt.rt_gateway)->sin_family = AF_INET;
			SIN (&info.rt.rt_gateway)->sin_addr.s_addr = rt->gway;
		}
		info.rt.rt_flags  = rt->flags;
		info.rt.rt_metric = rt->metric;
		info.rt.rt_refcnt = rt->refcnt;
		info.rt.rt_use    = rt->usecnt;
		sprintf (info.nif, "%s%d", rt->nif->name, rt->nif->unit);

		*infop++ = info;
		space -= sizeof (info);
	}
	return (nbytes - space);
}
