/*
 * 5799-WZQ (C) COPYRIGHT = NONE
 * LICENSED MATERIALS - PROPERTY OF IBM
 */
/* $Header:trace.c 12.0$ */
/* $ACIS:trace.c 12.0$ */
/* $Source: /ibm/acis/usr/src/ibm/rvd/server/RCS/trace.c,v $ */

#ifndef lint
static char *rcsid = "$Header:trace.c 12.0$";
#endif


#ifndef lint
static char rcsid_trace_c[] = "$Header:trace.c 12.0$";
#endif lint

/* Copyright 1984 by the Massachusetts Institute of Technology */
/* See permission and disclaimer notice in the file "notice.h" */
#include "notice.h"

/* Packet tracing for RVD protocol.
 */

#include	<stdio.h>
#include	<errno.h>
#include	<syslog.h>
#include	<sys/types.h>
#include	<sys/param.h>
#include	<netinet/in.h>
#include	<netinet/in_systm.h>
#include	<netinet/ip.h>
#include	<netinet/rvd.h>

#include	"rvd_types.h"
#include	"rvdadd.h"
#include	"custom.h"
#include	"obj.h"
#include	"queue.h"
#include	"packet.h"

char	*types[] = {			/* packet type names */
	0,
	"spinup",
	"spindown",
	"read",
	"write",
	"srvr status req",
	"host status",
	"respinup",
	0,0,0,0,0,0,0,0,0,
	"spin ack",
	"error",
	"spindown ack",
	"block",
	"write ack",
	"srvr status",
	"host status req",
};
int	ntypes = (sizeof types) / (sizeof (char *));

char	*codes[] = {
	0,
	"non-existent drive",
	"bad password",
	"open in different mode",
	"bad checksum",
	"bad index",
	"non-existent pack",
	"already spun up",
	"bad mode",
	"unknown packet rcvd",
	"non-active host",
	"drive spun up in exclusive mode",
	"zero blocks requested",
	"too many blocks requested",
	"pack not mounted",
	"too many total connections",
	"too many connections this host",
	"disallowed opening mode",
	"identical pack already spun up",
};
int	ncodes = (sizeof codes) / (sizeof (char *));


trace(pkt, dir)

/* Trace the specified RVD packet to the standard output.  The direction
 * tells whether this is an input or output packet.
 *
 * Arguments:
 */

register struct	rvd_pkt	*pkt;		/* pointer to rvd packet */
int	dir;				/* direction: 0 = input, 1 = output */
{
	char	unknown[32];
	u_char	type;
	char	*ctype;
	u_char	code;
	char	*ccode;

	type = pkt->rp_rvd.hdrun.allpkt.rvd_type;
	if (type >= ntypes || ((ctype = types[type]) == 0)) {
		(void)sprintf(unknown, "unknown type %U", type);
		ctype = unknown;
	}

	syslog(LOG_INFO, 
	       "%s %s %s %X len %D vers %D", (dir ? "Output" : "Input"),
	       ctype, (dir ? "to" : "from"), pkt->rp_fhost.s_addr, pkt->rp_len,
	       pkt->rp_rvd.hdrun.allpkt.version);
	switch (type) {

case RVDSPIN:
		syslog(LOG_INFO, "mode 0x%X", pkt->rp_rvd.hdrun.spinhdr.mode);
		break;

case RVDRESPIN:
		syslog(LOG_INFO, "mode 0x%X uid = %D",
			pkt->rp_rvd.hdrun.spinhdr.mode,
			pkt->rp_rvd.res_un.vd_uid);
		break;

case RVDERROR:
		code = pkt->rp_rvd.hdrun.errhdr.etype;
		if (code >= ncodes || ((ccode=codes[code]) == 0)) {
			(void)sprintf(unknown, "unknown code %U", code);
			ccode = unknown;
		}
		syslog(LOG_INFO, ccode);
		break;
default:
		break;
	}

	syslog(LOG_INFO, 
	       "drive %D  nonce 0x%X  index %D  csum %X", pkt->rp_rvd.drive,
	       (unsigned long)pkt->rp_rvd.nonce, pkt->rp_rvd.index,
	       pkt->rp_rvd.cksum);

	switch (type) {

case RVDERROR:
		if (pkt->rp_rvd.hdrun.errhdr.etype != RVDEIDA)
			break;			/* kludge */

/* Else fall through to... */
		
case RVDSPACK:
		syslog(LOG_INFO, 
		       "nblocks %D  burst %D  qlen %D  bfactor %D",
		       ntohl(pkt->rp_rvd.pkt_dpnd.spinack.nblocks),
		       ntohs(pkt->rp_rvd.pkt_dpnd.spinack.burst),
		       ntohs(pkt->rp_rvd.pkt_dpnd.spinack.qlen),
		       pkt->rp_rvd.pkt_dpnd.spinack.wb_factor);
		break;
		
case RVDREAD:
		syslog(LOG_INFO, 
		       "block %D  count %D",
		       ntohl(pkt->rp_rvd.pkt_dpnd.read.blockn),
		       ntohl(pkt->rp_rvd.pkt_dpnd.read.blockc) );
		break;

case RVDWRITE:
		syslog(LOG_INFO, 
		       "block %D  (%d  of  %d)", 
		       ntohl(pkt->rp_rvd.pkt_dpnd.write.blockn),
		       ntohs(pkt->rp_rvd.pkt_dpnd.write.bindex),
		       ntohs(pkt->rp_rvd.pkt_dpnd.write.blockc) );
		break;

case RVDBLOCK:
		syslog(LOG_INFO, 
		       "block %D  status 0x%X",
		       ntohl(pkt->rp_rvd.pkt_dpnd.block.blockn),
		       ntohl(pkt->rp_rvd.pkt_dpnd.block.status) );
		break;

case RVDWACK:
		syslog(LOG_INFO,
		       "block %D  status 0x%X  count %D", 
		       ntohl(pkt->rp_rvd.pkt_dpnd.writeack.blockn),
		       ntohl(pkt->rp_rvd.pkt_dpnd.writeack.status),
		       ntohl(pkt->rp_rvd.pkt_dpnd.writeack.bcount) );
		break;
default:
		break;
	}
}
