static char rcsid[] = "$Header: efs_ioctl.c,v 820.1 86/12/04 19:47:40 root Exp $";
static char sccsid[]="%W% %Y% %Q% %G%";

/************************************************************************
*									*
*				Copyright 1984, 1985			*
*			VALID LOGIC SYSTEMS INCORPORATED		*
*									*
*	This listing contains confidential proprietary information	*
*	which is not to be disclosed to unauthorized persons without	*
*	written consent of an officer of Valid Logic Systems 		*
*	Incorporated.							*
*									*
*	The copyright notice appearing above is included to provide	*
*	statutory protection in the event of unauthorized or 		*
*	unintentional public disclosure.				*
*									*
************************************************************************/

/*
 * I/O control interface for the Extended
 * File System.  This allows a server or any
 * other process to manipulate tables, etc.
 *
 * jam 840207-21-28-0305
 * jht 850426	Give unnamed bit in p_rpcflags a name: RPCFLAG_EFS_VCD
 * jht 850514	Add sas's code to support interface configuration.
 * jht 850601	Cleanup support for virtual chdir() in EFS.
 * smj 850813	Remove all refs (disable) for BCAST.
 *		Remove all refs (enable) for NET_SUPER_USER, NEWRPC.
 */

#include "../h/param.h"
#include "../h/ioctl.h"
#include "../h/dir.h"
#include "../h/user.h"
#include "../h/socket.h"
#include "../h/kernel.h"
#include "../net/if.h"
#include "../h/mbuf.h"
#ifdef EFS_VCD
#include "../h/proc.h"
#endif EFS_VCD

#include "../vnet/vnet.h"
#include "../conn/conn.h"
#include "../rpc/rpc.h"
#include "../efs/efs.h"
#include "../efs/efs_ioctl.h"

efs_ioctl(dev, com, data, flag)
   dev_t dev;
   register caddr_t data;
{
	register connection_t *conn;
	register int error = 0;

	switch (com)
	{

	case CONN_IOCLISTEN:
		conn_listen();
		break;

	case CONN_IOCNOLISTEN:
		conn_noListen();
		break;

	case CONN_IOCENABLE:
	{
		char hostname[20];
		register char *cp = &hostname[0];

		u.u_dirp = *(caddr_t *)data;
		hostname[20 - 1] = '\0';
		while (cp != &hostname[20-1] && (*cp++ = uchar()))
			;
		if (conn_enable(hostname) == 0)
			return(EIO);
		break;
	}

	case CONN_IOCDISABLE:
		conn_disable();
		break;

	case CONN_IOCENUMERATE:
	{
		register connection_t *c;
		extern connection_t *conn_enumerate();

		c = conn_enumerate(*(int *)data);
		if (c == NULL)
			return(ENFILE);
		bcopy((caddr_t)c, data, sizeof(*c));
		((connection_t *)data)->time = UPTIME() -
						   ((connection_t *)data)->time;
		break;
	}

	case CONN_IOCNAME:
	{
		register connection_t *c;
		extern connection_t *conn_enumerate();

		c = conn_enumerate(*(int *)data);
		if (c == NULL)
			return(ENFILE);
		bcopy((caddr_t)c->name, data, strlen(c->name)+1);
		break;
	}

	case CONN_IOCSHUTDOWN:
		conn_shutdown(*(long *)data);
		break;

	case CONN_IOCREMOVE:
	{
		char hostname[20];
		register char *cp = &hostname[0];

		u.u_dirp = *(caddr_t *)data;
		hostname[20 - 1] = '\0';
		while (cp != &hostname[20-1] && (*cp++ = uchar()))
			;
		if (conn_remove(hostname) == 0)
			return(EIO);
		break;
	}

	case CONN_IOCSUSPECT:
	{
		char hostname[20];
		register char *cp = &hostname[0];

		u.u_dirp = *(caddr_t *)data;
		hostname[20 - 1] = '\0';
		while (cp != &hostname[20-1] && (*cp++ = uchar()))
			;
		if (conn_suspect(hostname) == 0)
			return(EIO);
		break;
	}
#ifdef	CONN_GROUPS
	
	case CONN_IOCADDGROUP:
		if (!conn_addgroup(*(int *)data))
			u.u_error = EIO;
		break;

	case CONN_IOCDELGROUP:
		if (!conn_delgroup(*(int *)data))
			u.u_error = EIO;
		break;
#endif	CONN_GROUPS

#ifdef notyet
	case CONN_IOCWAITNEW:
		/* BUG make sure interruptible */
		sleep((caddr_t)&conn_waitnew, PZERO);
		break;

	case CONN_ADDPART:
		u.u_error = conn_addpart(*(long *)data);
		break;

	case CONN_RMPART:
		u.u_error = conn_rmpart(*(long *)data);
		break;
#endif notyet

#ifdef notdef
/* Re-enable when rpc_stats definition is found again */
	case RPC_IOCGETSTATS:
		bcopy((caddr_t)&rpc_stats, data, sizeof(rpc_stats));
		break;
#endif notdef

	case RPC_IOCNULLNULL:
		u.u_dirp = *(caddr_t *)data;
		if ((conn = efs_uhostLookup()) == NULL)
			return(EHOSTUNREACH);
		break;

	case RPC_IOCGETTIME:
		u.u_dirp = *(caddr_t *)data;
		if ((conn = efs_uhostLookup()) == NULL)
			return(EHOSTUNREACH);
		error = timeClient_get(conn, (long)data + 4);
		break;

	case RPC_IOCSETTIME:
		u.u_dirp = *(caddr_t *)data;
		if ((conn = efs_uhostLookup()) == NULL)
			return(EHOSTUNREACH);
		error = timeClient_set(conn, (long)data + 4);
		break;

	case RPC_IOCSETLOCALTIME:
		u.u_dirp = *(caddr_t *)data;
		if ((conn = efs_uhostLookup()) == NULL)
			return(EHOSTUNREACH);
		error = timeClient_setlocal(conn, (long)data + 4);
		break;

	case RPC_IOCSERVER:
		prpc_serverMain();
		break;

	case EFS_IOCENABLE:
		if (!efs_enable())
			u.u_error = EIO;
		break;

	case EFS_IOCDISABLE:
		if (!efs_disable())
			u.u_error = EIO;
		break;

	case EFS_IOCGETSTATS:
		bcopy((caddr_t)&efs_stats, data, sizeof(efs_stats));
		break;

	case EFS_IOCNULLCALL:
		u.u_dirp = *(caddr_t *)data;
		if ((conn = efs_uhostLookup()) == NULL)
			return(EHOSTUNREACH);
		u.u_dirp = *(caddr_t *)data;
		efs_uhostLookup();
		error = efs_nullCall(conn);
		break;

	case EFS_IOCSUMOST:
		efs_netsutype = EFS_SU_MOST;
		break;

	case EFS_IOCSUFEW:
		efs_netsutype = EFS_SU_FEW;
		break;

	case EFS_IOCSUUID:
		efs_netsuuid = *(int *)data;
		break;

	/* BUG need EFS_IOCSUADD and EFS_IOCSURM */

#ifdef EFS_VCD
	case EFS_IOCVCD:
	{
		register int mode = *(int *)data;
		register struct proc *p;

		p = (mode & 2) ? u.u_procp->p_pptr : u.u_procp;
		if (u.u_procp->p_uid != p->p_uid)
			error = EPERM;
		else
		{
			if (mode & 1)
				p->p_rpcflags |= RPCFLAG_EFS_VCD;
			else
				p->p_rpcflags &= ~RPCFLAG_EFS_VCD;
		}
		break;
	}
#endif EFS_VCD

#ifdef VALID_BULK
	case BULK_IOCCREATE:
	case BULK_IOCDESTROY:
	case BULK_IOCSEND:
		return(bulk_ioctl(dev, com, data, flag));
		break;
#endif VALID_BULK

	default:
#define	cmdbyte(x)	(((x) >> 8) & 0xff)
		if (cmdbyte(com) == _IO_VNET)
			return (vnetioctl(com, data));
		error = EBADIOCTL;
		break;
	}
	return(error);
}
