DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T s

⟦cfad8e9b3⟧ TextFile

    Length: 25317 (0x62e5)
    Types: TextFile
    Names: »sunlink.c«

Derivation

└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0
    └─⟦35176feda⟧ »EurOpenD22/isode/isode-6.tar.Z« 
        └─⟦de7628f85⟧ 
            └─⟦this⟧ »isode-6.0/compat/sunlink.c« 

TextFile

/* sunlink.c - X.25 abstractions for SunLink X25 */

#ifndef lint
static char *rcsid = "$Header: /f/osi/compat/RCS/sunlink.c,v 7.0 89/11/23 21:23:42 mrose Rel $";
#endif

/*
 * $Header: /f/osi/compat/RCS/sunlink.c,v 7.0 89/11/23 21:23:42 mrose Rel $
 *
 * Contributed by John Pavel, Department of Trade and Industry/National
 * Physical Laboratory in the UK
 *
 *
 * $Log:	sunlink.c,v $
 * Revision 7.0  89/11/23  21:23:42  mrose
 * Release 6.0
 * 
 */

/*
 *                                NOTICE
 *
 *    Acquisition, use, and distribution of this module and related
 *    materials are subject to the restrictions of a license agreement.
 *    Consult the Preface in the User's Manual for the full terms of
 *    this agreement.
 *
 */


/* LINTLIBRARY */

#include <stdio.h>
#include "general.h"
#include "manifest.h"
#include "tailor.h"

/* \f

   SUN UNIX: SunLink X25 */

#ifdef  X25

#include "x25.h"
#include "isoaddrs.h"

#ifdef  SUN_X25

#define CALLING 0
#define CALLED  1
#define	PROBE	(-1)

/* \f

 */

#ifdef  DEBUG
void    print_x25_facilities ();
#endif

/* \f

 */

/* ARGSUSED */

int     start_x25_client (local, priv)
struct  NSAPaddr *local;
int     priv;
{
    int     sd;

    if ((sd = socket (AF_X25, SOCK_STREAM, 0)) == NOTOK) {
	SLOG (compat_log, LLOG_EXCEPTIONS, "failed", ("socket"));
	return NOTOK;
    }

    return sd;
}

/* \f

 */

int     start_x25_server (local, backlog, opt1, opt2)
struct  NSAPaddr *local;
int     backlog,
	opt1,
	opt2;
{
    CONN_DB     sbuf,
		xbuf;
    CONN_DB     *sock = &sbuf,
		*xs = &xbuf;
    int     sd, onoff;

    if ((sd = socket (AF_X25, SOCK_STREAM, 0)) == NOTOK) {
	SLOG (compat_log, LLOG_EXCEPTIONS, "failed", ("socket"));
	return NOTOK;
    }

    onoff = 0;
    if (ioctl (sd, X25_CALL_ACPT_APPROVAL, (char *) &onoff) == NOTOK) {
	SLOG (compat_log, LLOG_EXCEPTIONS, "failed",
	      ("X25_CALL_ACPT_APPROVAL"));
	(void) close_x25_socket (sd);
	return NOTOK;
    }

    if (ioctl (sd, X25_RD_HOSTADR, (char *) xs) == NOTOK) {
	SLOG (compat_log, LLOG_EXCEPTIONS, "failed", ("X25_RD_HOSTADR"));
	(void) close_x25_socket (sd);
	return NOTOK;
    }
					/* if null DTE in /etc/x25params
					   then ALWAYS use null DTE for
					   listen if PID is specified */
    if (xs -> hostlen == 0 && local -> na_pidlen > 0) {
	if (local -> na_pidlen > NPSIZE)
	    local -> na_pidlen = NPSIZE;
	*sock = *xs;    /* struct copy */
	bzero((char *) sock -> data, NPSIZE);
	bcopy (local -> na_pid, (char *) sock -> data, local -> na_pidlen);
	bcopy (local -> na_cudf, (char *) sock -> data + NPSIZE,
	       local -> na_cudflen);
	sock -> datalen = local -> na_pidlen + local -> na_cudflen;
    }
    else
	sock = gen2if(local, sock, ADDR_LISTEN);

    /* Adopt the convention that if a null DTE is given,
       we should get the one from /etc/x25params */
    if(!local->na_dtelen) {
	/* Now set the generic local address */
	local = if2gen(local, xs, ADDR_LOCAL);
	/* Modified by INRIA to avoid a null local address */
	if (!local->na_dtelen) {
		local->na_dtelen = 1;
		local->na_dte[0] = '0';
	}
    }

    if (bind (sd, (struct sockaddr *) sock, sizeof(CONN_DB)) == NOTOK) {
	SLOG (compat_log, LLOG_EXCEPTIONS, "failed", ("bind"));
	(void) close_x25_socket (sd);
	return NOTOK;
    }

#ifndef	BSD43
    if (opt1)
	(void) setsockopt (sd, SOL_SOCKET, opt1, NULLCP, 0);
    if (opt2)
	(void) setsockopt (sd, SOL_SOCKET, opt2, NULLCP, 0);
#else
    onoff = 1;
    if (opt1)
	(void) setsockopt (sd, SOL_SOCKET, opt1, (char *)&onoff, sizeof onoff);
    if (opt2)
	(void) setsockopt (sd, SOL_SOCKET, opt2, (char *)&onoff, sizeof onoff);
#endif

    if (set_x25_facilities(sd, CALLED, "Acceptable") == NOTOK) {
	(void) close_x25_socket (sd);
	return NOTOK;
    }

    (void) listen (sd, backlog);

    return sd;
}

/* \f

 */

int     join_x25_server (fd, remote)
register int fd;
register struct NSAPaddr *remote;
{
    CONN_DB sbuf;
    CONN_DB *sock = &sbuf;
    register int nfd;

    sock = gen2if (remote, sock, ADDR_REMOTE);

    if (set_x25_facilities(fd, CALLING, "Proposed") == NOTOK)
	return NOTOK;

    if ((nfd = connect (fd, (struct sockaddr *)sock, sizeof (CONN_DB)))
	    == NOTOK) {
	if (compat_log -> ll_events & LLOG_EXCEPTIONS)
	    (void) log_cause_and_diag(fd);      /* Sun's documentation throwns
						   no light as to whether, or
						   not this will result in any
						   useful information */
    }
#ifdef  DEBUG
    else
	if (compat_log -> ll_events & LLOG_DEBUG)
	    (void) log_x25_facilities(fd, CALLING, "Effective Calling");
#endif

    remote = if2gen (remote, sock, ADDR_REMOTE);

    return nfd;
}

/* \f

 */

int     join_x25_client (fd, remote)
int     fd;
struct  NSAPaddr *remote;
{
    CONN_DB     sbuf;
    CONN_DB     *sock = &sbuf;
    int     len = sizeof *sock;
    int     nfd;

    if ((nfd = accept (fd, (struct sockaddr *) sock, &len)) == NOTOK) {
	if (compat_log -> ll_events & LLOG_EXCEPTIONS)
	    (void) log_cause_and_diag(fd);      /* Sun's documentation throwns
						   no light as to whether, or
						   not this will result in any
						   useful information */
    }
#ifdef  DEBUG
     else
	 if (compat_log -> ll_events & LLOG_DEBUG)
	     (void) log_x25_facilities(fd, CALLED, "Effective Called");
#endif
    if (nfd < 0) return nfd;

    /* May also need to send call accept packet if using
     * FAST_ACPT_CLR, or X25_CALL_ACPT_APPROVAL
     * there was a SUNLINK bug in this area
     *
     * May as well try it -- if it fails, so what ??
     */
    if (ioctl(nfd,X25_SEND_CALL_ACPT, NULLCP) < 0)
	SLOG (compat_log, LLOG_EXCEPTIONS, "failed", ("X25_SEND_CALL_ACPT"));

    remote = if2gen (remote, sock, ADDR_REMOTE);

    return nfd;
}

/* \f

 */

/* There is a bug whereby if the thruput is set, calls fail. pb@cl.cam.ac.uk */

int	sun_fixed_thruput = 0;

/* Set up X.25 Facilities.  Note that setting even one value causes
   the default (/etc/x25params) values to be set explicitly on the
   call request (and probably also call accept).  This can screw
   things up, if your /etc/x25params has not been properly
   localised as is normally the case.  */

int     set_x25_facilities(sd, coc, caption)
int     sd, coc;
char *caption;
{
    FACILITY_DB facilities;

    bzero ((char *) &facilities, sizeof facilities);

    if (coc != CALLED
	    && ioctl (sd, X25_RD_FACILITY, (char *) &facilities) == NOTOK) {
	SLOG (compat_log, LLOG_EXCEPTIONS, "failed", ("X25_RD_FACILITY"));
	return NOTOK;
    }

    if (coc == PROBE
	    || !(coc == CALLED
		    || reverse_charge   || recvpktsize || sendpktsize
		    || recvwndsize      || sendwndsize || recvthruput
		    || sendthruput      || cug_req  /* || cug_index */
		    || fast_select_type || rpoa_req /* || rpoa */)) {
	if (facilities.recvpktsize)
	    recvpktsize = facilities.recvpktsize;
	if (facilities.sendpktsize)
	    sendpktsize = facilities.sendpktsize;

	return OK;
    }

    if (reverse_charge)
	facilities.reverse_charge = reverse_charge;
    if (recvpktsize)
	facilities.recvpktsize = recvpktsize;
    if (sendpktsize)
	facilities.sendpktsize = sendpktsize;
    if (recvwndsize)
	facilities.recvwndsize = recvwndsize;
    if (sendwndsize)
	facilities.sendwndsize = sendwndsize;
    if (sun_fixed_thruput) {	/* get round Sun bug */
	if (recvthruput)
	    facilities.recvthruput = recvthruput;
	if (sendthruput)
	    facilities.sendthruput = sendthruput;
    }
    else
	facilities.recvthruput = facilities.sendthruput = 0;
    if (cug_req)
	facilities.cug_req = cug_req;
    if (cug_index)
	facilities.cug_index = cug_index;
    if (fast_select_type)
	facilities.fast_select_type = fast_select_type;
      /* May as well accept FCS calls */
    else
	if (coc == CALLED)
	    facilities.fast_select_type = FAST_ACPT_CLR;
    if (rpoa_req)
	facilities.rpoa_req = rpoa_req;
    if (rpoa)
	facilities.rpoa = rpoa;

#ifdef  DEBUG
    if (compat_log -> ll_events & LLOG_DEBUG)
	print_x25_facilities (facilities, coc, caption);
#endif

    if (ioctl (sd, X25_WR_FACILITY, (char *) &facilities) == NOTOK) {
	SLOG (compat_log, LLOG_EXCEPTIONS, "failed", ("X25_WR_FACILITY"));
	return NOTOK;
    }

    if (facilities.recvpktsize)
	recvpktsize = facilities.recvpktsize;
    if (facilities.sendpktsize)
	sendpktsize = facilities.sendpktsize;

    return OK;
}

/* \f

 */

int     log_cause_and_diag(fd)
int fd;
{
    X25_CAUSE_DIAG      diag;

    if (ioctl(fd, X25_RD_CAUSE_DIAG, (char *) &diag) == NOTOK) {
	SLOG (compat_log, LLOG_EXCEPTIONS, "failed", ("X25_RD_CAUSE_DIAG"));
	return NOTOK;
    }

    return elucidate_x25_err ((int) diag.flags, (char *) diag.data);

}

/* \f

 */

#ifdef  DEBUG

static int  log_x25_facilities (fd, coc, caption)
int     fd;
int     coc;
char   *caption;
{
    FACILITY_DB f;

    if (ioctl (fd, X25_RD_FACILITY, (char *) &f) == NOTOK) {
	SLOG (compat_log, LLOG_EXCEPTIONS, "failed", ("X25_RD_FACILITY"));
	return NOTOK;
    }

    print_x25_facilities (f, coc, caption);

    return OK;
}

/* \f

 */

static void  print_x25_facilities (f, coc, caption)
FACILITY_DB f;
int     coc;
char   *caption;
{
    int     baud;

    DLOG (compat_log, LLOG_DEBUG, ("%s X.25 Facilities:", caption));

    switch (f.reverse_charge) {
	case 0:
	    DLOG (compat_log, LLOG_DEBUG, ((coc == CALLED)
		      ? "reverse charging not requested"
		      : "reverse charging not allowed"));
	    break;

	case 1:
	    DLOG (compat_log, LLOG_DEBUG, ((coc == CALLING)
		      ? "reverse charging requested"
		      : "reverse charging allowed"));
	    break;

	default:
	    DLOG (compat_log, LLOG_DEBUG, ("invalid reverse_charge: %d",
		      f.reverse_charge));
	    break;
    }

    switch (f.recvpktsize) {
	case 0:
	    DLOG (compat_log, LLOG_DEBUG, ("default recv packet size"));
	    break;

	case 16:
	case 32:
	case 64:
	case 128:
	case 256:
	case 512:
	case 1024:
	    DLOG (compat_log, LLOG_DEBUG, ("recv packet size %d",
		      f.recvpktsize));
	    break;

	default:
	    DLOG (compat_log, LLOG_DEBUG, ("invalid recv packet size %d",
		      f.recvpktsize));
	    break;
    }

    switch (f.sendpktsize) {
	case 0:
	    DLOG (compat_log, LLOG_DEBUG, ("default send packet size"));
	    break;

	case 16:
	case 32:
	case 64:
	case 128:
	case 256:
	case 512:
	case 1024:
	    DLOG (compat_log, LLOG_DEBUG, ("send packet size %d",
		      f.sendpktsize));
	    break;

	default:
	    DLOG (compat_log, LLOG_DEBUG, ("invalid send packet size %d",
		      f.sendpktsize));
	    break;
    }

    DLOG (compat_log, LLOG_DEBUG,
	  (f.recvwndsize == 0 ? "default recv window size"
		  : 1 <= f.recvwndsize && f.recvwndsize <= 127
		      ? "recv window size %d"
		      : "invalid recv window size %d",
	      f.recvwndsize));

    DLOG (compat_log, LLOG_DEBUG,
	  (f.sendwndsize == 0 ? "default send window size"
		  : 1 <= f.sendwndsize && f.sendwndsize <= 127
		      ? "send window size %d"
		      : "invalid send window size %d",
	      f.sendwndsize));

    switch (f.recvthruput) {
	case 0:
	    DLOG (compat_log, LLOG_DEBUG, ("default recv throughput"));
	    break;

	case 3:
	    baud = 75;
print_recv: ;
	    DLOG (compat_log, LLOG_DEBUG, ("recv throughput %dbps", baud));
	    break;

	case 4:
	    baud = 150;
	    goto print_recv;

	case 5:
	    baud = 300;
	    goto print_recv;

	case 6:
	    baud = 600;
	    goto print_recv;

	case 7:
	    baud = 1200;
	    goto print_recv;

	case 8:
	    baud = 2400;
	    goto print_recv;

	case 9:
	    baud = 4800;
	    goto print_recv;

	case 10:
	    baud = 9600;
	    goto print_recv;

	case 11:
	    baud = 19200;
	    goto print_recv;

	case 12:
	    baud = 48000;
	    goto print_recv;

	default:
	    DLOG (compat_log, LLOG_DEBUG, ("invalid recv throughput %d",
		      f.recvthruput));
	    break;
    }

    switch (f.sendthruput) {
	case 0:
	    DLOG (compat_log, LLOG_DEBUG, ("default send throughput"));
	    break;

	case 3:
	    baud = 75;
print_send: ;
	    DLOG (compat_log, LLOG_DEBUG, ("send throughput %dbps", baud));
	    break;

	case 4:
	    baud = 150;
	    goto print_send;

	case 5:
	    baud = 300;
	    goto print_send;

	case 6:
	    baud = 600;
	    goto print_send;

	case 7:
	    baud = 1200;
	    goto print_send;

	case 8:
	    baud = 2400;
	    goto print_send;

	case 9:
	    baud = 4800;
	    goto print_send;

	case 10:
	    baud = 9600;
	    goto print_send;

	case 11:
	    baud = 19200;
	    goto print_send;

	case 12:
	    baud = 48000;
	    goto print_send;

	default:
	    DLOG (compat_log, LLOG_DEBUG, ("invalid send throughput %d",
		      f.sendthruput));
	    break;
    }

    switch (f.cug_req) {
	case 0:
	    DLOG (compat_log, LLOG_DEBUG, ("no closed user group"));
	    break;

	case 1:
	    DLOG (compat_log, LLOG_DEBUG, ("closed user group 0x%x (BCD)",
		      f.cug_req));
	    break;

	default:
	    DLOG (compat_log, LLOG_DEBUG, ("invalid closed user group %d",
		      f.cug_req));
	    break;
    }

    switch (f.fast_select_type) {
	case FAST_OFF:
	    DLOG (compat_log, LLOG_DEBUG, ("don't use fast select"));
	    break;

	case FAST_CLR_ONLY:
	    DLOG (compat_log, LLOG_DEBUG, ("clear is fast select response"));
	    break;

	case FAST_ACPT_CLR:
	    DLOG (compat_log, LLOG_DEBUG,
		  ("clear or call accepted is fast select response"));
	    break;

	default:
	    DLOG (compat_log, LLOG_DEBUG, ("invalid fast select type %d",
		      f.fast_select_type));
	    break;
    }

    switch (f.rpoa_req) {
	case 0:
	    DLOG (compat_log, LLOG_DEBUG, ("no RPOA transit request"));
	    break;

	case 1:
	    DLOG (compat_log, LLOG_DEBUG, ("RPOA transit request 0x%x",
		      f.rpoa_req));
	    break;

	default:
	    DLOG (compat_log, LLOG_DEBUG, ("invalid RPOA transit request %d",
		      f.rpoa_req));
    }
}
#endif
#endif

elucidate_x25_err (flags, pkt)
int flags;
char * pkt;
{
    char * cp;

    if (flags & (1 << RECV_DIAG)) {
	SLOG (compat_log, LLOG_EXCEPTIONS, NULLCP,
	      (( flags & (1 << DIAG_TYPE) ) ? "cleared 0x%02x" : "reset 0x%02x",
	       pkt[0] ));

	if ((flags) & (1 << DIAG_TYPE)) /* cleared */
	    switch(pkt[0]) {
		case 0x00:
		    cp = "DTE Clearing";
		    break;

		case 0x01:
		    cp = "Number Busy";
		    break;

		case 0x09:
		    cp = "Out of Order";
		    break;

		case 0x11:
		    cp = "Remote Procedure Error";
		    break;

		case 0x19:
		    cp = "Reverse Charging not subscribed";
		    break;

		case 0x03:
		    cp = "Invalid Facility Request";
		    break;

		case 0x0B:
		    cp = "Access Barred";
		    break;

		case 0x13:
		    cp = "Local Procedure Error";
		    break;

		case 0x05:
		    cp = "Network Congestion";
		    break;

		case 0x0D:
		    cp = "Not Obtainable";
		    break;

		case 0x21:
		    cp = "DTE Incompatible Call";
		    break;

		case 0x29:
		    cp = "Fast Select Acceptance not Subscribed";
		    break;

		default:
		    SLOG (compat_log, LLOG_EXCEPTIONS, NULLCP,
			  ("clearing cause 0x2%x", pkt[0]));
		    goto next;
	    }
	else /* reset */
	    switch(pkt[0]) {
		case 0x00:
		    cp = "DTE Reset";
		    break;

		case 0x01:
		    cp = "Out of Order (PVC Only)";
		    break;

		case 0x03:
		    cp = "Remote Procedure Error";
		    break;

		case 0x05:
		    cp = "Local Procedure Error";
		    break;

		case 0x07:
		    cp = "Network Congestion";
		    break;

		case 0x09:
		    cp = "Remote DTE Operational (PVC Only)";
		    break;

		case 0x0F:
		    cp = "Network Operational (PVC Only";
		    break;

		default:
		    SLOG (compat_log, LLOG_EXCEPTIONS, NULLCP,
			  ("resetting cause 0x%2x", pkt[0]));
		    goto next;

	    }
	SLOG (compat_log, LLOG_EXCEPTIONS, NULLCP, ("%s%s",
	    ( flags & (1 << DIAG_TYPE) ) ? "clearing cause " :
	    "resetting cause ", cp));

next: ;
	/* The following may only be applicable to PSS in the UK */
	/* In any case, if someone is keen, they can stuff it all
	   into a text file and read it out */

	switch (pkt[1]) {
	    case 0x00:
		cp = "NO ADDITIONAL INFORMATION";
		break;

	    case 0x01:
		cp = "INVALID P(S)\tRESET";
		break;

	    case 0x02:
		cp = "INVALID P(R)\tRESET";
		break;

	    case 0x11:
		cp = "PACKET TYPE INVALID FOR STATE r1\tRESTART";
		break;

	    case 0x12:
		cp = "PACKET TYPE INVALID FOR STATE r2\tRESTART";
		break;

	    case 0x13:
		cp = "PACKET TYPE INVALID FOR STATE r3\tRESTART";
		break;

	    case 0x14:
		cp = "PACKET TYPE INVALID FOR STATE p1\tCLEAR";
		break;

	    case 0x15:
		cp = "PACKET TYPE INVALID FOR STATE p2\tCLEAR";
		break;

	    case 0x16:
		cp = "PACKET TYPE INVALID FOR STATE p3\tCLEAR";
		break;

	    case 0x17:
		cp = "PACKET TYPE INVALID FOR STATE p4\tCLEAR";
		break;

	    case 0x18:
		cp = "PACKET TYPE INVALID FOR STATE p5\tRESET";
		break;

	    case 0x19:
		cp = "PACKET TYPE INVALID FOR STATE p6\tCLEAR";
		break;

	    case 0x1A:
		cp = "PACKET TYPE INVALID FOR STATE p7\tCLEAR";
		break;

	    case 0x1B:
		cp = "PACKET TYPE INVALID FOR STATE d1\tRESET";
		break;

	    case 0x1C:
		cp = "PACKET TYPE INVALID FOR STATE d2\tRESET";
		break;

	    case 0x1D:
		cp = "PACKET TYPE INVALID FOR STATE d3\tRESET";
		break;

	    case 0x20:
		cp = "PACKET NOT ALLOWED";
		break;

	    case 0x21:
		cp = "UNIDENTIFIABLE PACKET";
		break;

	    case 0x22:
		cp = "CALL ON ONE-WAY LOGICAL CHANNEL\tCLEAR";
		break;

	    case 0x23:
		cp = "INVALID PACKET TYPE ON PVC\tRESET";
		break;

	    case 0x24:
		cp = "PACKET ON UNASSIGNED LCN\tCLEAR";
		break;

	    case 0x25:
		cp = "REJECT NOT SUBSCRIBED TO\tRESET";
		break;

	    case 0x26:
		cp = "PACKET TOO SHORT\tRESET";
		break;

	    case 0x27:
		cp = "PACKET TOO LONG\tRESET";
		break;

	    case 0x28:
		cp = "INVALID GFI\tCLEAR";
		break;

	    case 0x29:
		cp = "RESTART WITH NON-ZERO BITS 5-16";
		break;

	    case 0x2A:
		cp = "PACKET TYPE NOT COMPATIBLE WITH FACILITY\tCLEAR";
		break;

	    case 0x2B:
		cp = "UNAUTHORISED INTERRUPT CONF\tRESET";
		break;

	    case 0x2C:
		cp = "UNAUTHORISED INTERRUPT\tRESET";
		break;

	    case 0x31:
		cp = "TIMER EXPIRED;  INCOMING CALL";
		break;

	    case 0x32:
		cp = "TIMER EXPIRED;\tCLEAR INDICATION";
		break;

	    case 0x33:
		cp = "TIMER EXPIRED;\tRESET INDICATION";
		break;

	    case 0x34:
		cp = "TIMER EXPIRED;\tRESTART IND";
		break;

	    case 0x40:
		cp = "UNSPECIFIED CALL SET-UP PROBLEM CLEAR";
		break;

	    case 0x41:
		cp = "FACILITY CODE NOT ALLOWED\tCLEAR";
		break;

	    case 0x42:
		cp = "FACILITY PARAMETER NOT ALLOWED\tCLEAR";
		break;

	    case 0x43:
		cp = "INVALID CALLED ADDRESS\tCLEAR";
		break;

	    case 0x44:
		cp = "INVALID CALLING ADDRESS\tCLEAR";
		break;

	    case 0x90:
		cp = "DTE/DCE CONGESTION\tRESET";
		break;

	    case 0x91:
		cp = "RECEIVED FAST SELECT CLEAR REQUEST";
		break;

	    case 0x92:
		cp = "LINE RESTARTING BY INMC COMMAND\tRESTART";
		break;

	    case 0xA0:
		cp = "NON-ZERO RESET CAUSE FROM DTE\tRESET";
		break;

	    case 0xA1:
		cp = "DATA PACKET TOO LONG\tRESET";
		break;

	    case 0xA2:
		cp = "INTERRUPT PACKET TOO LONG\tRESET";
		break;

	    case 0xA3:
		cp = "INT PACKET TOO SHORT; NO USER DATA\tRESET";
		break;

	    case 0xA4:
		cp = "INT CONFIRMATION PACKET TOO LONG\tRESET";
		break;

	    case 0xA5:
		cp = "RR PACKET TOO LONG\tRESET";
		break;

	    case 0xA6:
		cp = "RNR PACKET TOO LONG\tRESET";
		break;

	    case 0xA7:
		cp = "RESET PACKET TOO LONG\tRESET";
		break;

	    case 0xA8:
		cp = "RESET CONF PACKET TOO LONG\tRESET";
		break;

	    case 0xA9:
		cp = "INVALID `Q' BIT IN DATA PACKET\tRESET";
		break;

	    case 0xAA:
		cp = "PACKET WINDOW RANGE EXCEEDED\tRESET";
		break;

	    case 0xAB:
		cp = "UNABLE TO TRANSMIT PACKET\tRESET";
		break;

	    case 0xAC:
		cp = "diagnostic `Q' BIT SET IN NON-DATA PACKET\tRESET";
		break;

	    case 0xAD:
		cp = "OUTSTANDING PACKET COUNT LESS THAN ZERO\tRESET";
		break;

	    case 0xAE:
		cp = "RETRANSMISSION ERROR\tRESET";
		break;

	    case 0xAF:
		cp = "RESET PACKET TOO SHORT (NO CAUSE)\tRESET";
		break;

	    case 0xB0:
		cp = "REJECT PACKET TOO LONG\tRESET";
		break;

	    case 0xB1:
		cp = "INVALID 1D PACKET\tRESET";
		break;

	    case 0xB2:
		cp = "UNSUCCESSFUL RECONNECTION RESNC\tCLEAR";
		break;

	    case 0xB3:
		cp = "NON-RECONNECT CALL IN STATE C1\tCLEAR";
		break;

	    case 0xB4:
		cp = "SECOND 1D PACKET FROM DTE\tCLEAR";
		break;

	    case 0xB5:
		cp = "BAD DATA TRANSFER STATE IN RECONNECT\tCLEAR";
		break;

	    case 0xB6:
		cp = "PACKET FORMAT INVALID\tCLEAR";
		break;

	    case 0xB7:
		cp = "FACILITY BYTE COUNT TOO LARGE\tCLEAR";
		break;

	    case 0xB8:
		cp = "INVALID PACKET DETECTED\tCLEAR";
		break;

	    case 0xB9:
		cp = "FACILITY/UTILITY FIELD BYTE COUNT > 63\tCLEAR";
		break;

	    case 0xBA:
		cp = "OUTGOING CALLS BARRED\tCLEAR";
		break;

	    case 0xBB:
		cp = "INCOMING CALLS BARRED\tCLEAR";
		break;

	    case 0xBC:
		cp = "CLEARING OF PVC\tCLEAR";
		break;

	    case 0xBD:
		cp = "CALLED ADDRESS TOO LONG\tCLEAR";
		break;

	    case 0xBE:
		cp = "CALLED ADDRESS TOO SHORT\tCLEAR";
		break;

	    case 0xBF:
		cp = "CALLING ADDRESS TOO LONG\tCLEAR";
		break;

	    case 0xC0:
		cp = "CALLING ADDRESS TOO SHORT\tCLEAR";
		break;

	    case 0xC1:
		cp = "BCD ERROR IN CALL ADDRESS\tCLEAR";
		break;

	    case 0xC2:
		cp = "BCD ERROR IN CALLING ADDRESS\tCLEAR";
		break;

	    case 0xC3:
		cp = "USER DATA FIELD TOO LONG\tCLEAR";
		break;

	    case 0xC4:
		cp = "NO BUFFER AVAILABLE\tCLEAR";
		break;

	    case 0xC5:
		cp = "LOCAL DTE IS NOT ENHANCED\tCLEAR";
		break;

	    case 0xC6:
		cp = "FACILITY NEGOTIATION INVALID\tCLEAR";
		break;

	    case 0xC7:
		cp = "MANDATORY UTILITY NOT INPUT\tCLEAR";
		break;

	    case 0xC8:
		cp = "BUFFER NO AVAILABLE FOR TNIC\tCLEAR";
		break;

	    case 0xC9:
		cp = "OVERFLOW OF TNIC IN BUFFER\tCLEAR";
		break;

	    case 0xCA:
		cp = "DTE LINE CONGESTED\tCLEAR";
		break;

	    case 0xCB:
		cp = "TABLE ERROR IN PACKET PROCEDURES";
		break;

	    case 0xCC:
		cp = "INSERT TABLE OVERFLOW";
		break;

	    case 0xCD:
		cp = "DELETE TABLE OVERFLOW";
		break;

	    case 0xD0:
		cp = "TRUNK LINE RESTART\tRESTART";
		break;

	    case 0xD1:
		cp = "INVALID EVENT IN STATE p2";
		break;

	    case 0xD2:
		cp = "INVALID EVENT IN STATE p3";
		break;

	    case 0xD3:
		cp = "INVALID 1D EVENT IN STATE d1";
		break;

	    case 0xD4:
		cp = "CALL COLLISION ON TRUNK LINE";
		break;

	    case 0xD5:
		cp = "NO BUFFER AVAILABLE";
		break;

	    case 0xD6:

		cp = "CALL COLLISION ON DTE LINE";
		break;

	    case 0xD7:
		cp = "DTE RESTART";
		break;

	    case 0xD8:
		cp = "CALL REQUEST TO TRUNK LINE TIMEOUT";
		break;

	    case 0xD9:
		cp = "RECONNECT SET-UP TIMED OUT";
		break;

	    case 0xDA:
		cp = "INVALID OUTPUT SIDE STATE";
		break;

	    case 0xDB:
		cp = "ERROR DETECTED IN BLINK PACKET QUEUE PROCEDURE";
		break;

	    case 0xDC:
		cp = "RESET INDICATION RETRANSMISSION COUNT EXPIRED";
		break;

	    case 0xDD:
		cp = "INVALID OUTPUT SIDE STATE";
		break;

	    case 0xDE:
		cp = "BLIND BUFFER QUEUE OVERFLOW IN STATE d4";
		break;

	    case 0xDF:
		cp = "BLIND BUFFER QUEUE OVERFLOW IN STATE c1";
		break;

	    case 0xE0:
		cp = "BLIND BUFFER QUEUE OVERFLOW IN STATE c2";
		break;

	    case 0xE1:
		cp = "CLEAR PACKET BYTE COUNT TOO LARGE OR TOO SMALL";
		break;

	    case 0xE2:
		cp = "NON-ZERO\tCLEAR CAUSE";
		break;

	    case 0xE3:
		cp = "CLEAR CONF PACKET BYTE COUNT TOO SMALL OR TOO LARGE";
		break;

	    case 0xE4:
		cp = "CALL COLLISION";
		break;

	    case 0xE5:
		cp = "INVALID TP LOAD REQUEST CALL PKT";
		break;

	    case 0xE6:
		cp = "MAXIMUM HOPCOUNT EXCEEDED";
		break;

	    case 0xE7:
		cp = "ROUTING LOOP DETECTED";
		break;

	    case 0xE8:
		cp = "PVC CALL REQUEST FAILURE";
		break;

	    case 0xE9:
		cp = "RECONNECT CALL REQUEST FAILED";
		break;

	    case 0xEA:
		cp = "NO LC AVAILABLE ON OUTPUT SIDE";
		break;

	    case 0xEB:
		cp = "NO BUFFER AVAILABLE";
		break;

	    case 0xEC:
		cp = "CALL REDIRECTION CLEAR";
		break;

	    case 0xED:
		cp = "NO PATH ROUTE CALL";
		break;

	    case 0xEE:
		cp = "CALL ROUTED TO DTE LINE";
		break;

	    case 0xEF:
		cp = "CALL CANNOT BE REROUTED";
		break;

	    case 0xF0:
		cp = "ADDRESS NOT IN ROUTING TABLES";
		break;

	    case 0xF1:
		cp = "ROUTING TABLE CHANGE DURING CALL ROUTING";
		break;

	    case 0xF2:
		cp = "NO LC AVAILABLE ON FAKE TRUNK";
		break;

	    case 0xF3:
		cp = "REMOTE DTE DOWN ON A PVC";
		break;

	    case 0xF4:
		cp = "INVALID EVENT DETECTED";
		break;

	    case 0xF5:
		cp = "INVALID PACKET RECEIVED; STATE d4";
		break;

	    case 0xF6:
		cp = "INVALID PACKET RECEIVED; STATE d5";
		break;

	    case 0xF7:
		cp = "INVALID PACKET RECEIVED; STATE p8";
		break;

	    case 0xF8:
		cp = "INTERNAL PROCESSING FAILURE";
		break;

	    case 0xF9:
		cp = "INVALID RESTART INDICATION";
		break;

	    case 0xFA:
		cp = "LINE STATUS CHANGE IN STATE r4";
		break;

	    case 0xFB:
		cp = "INVALID PACKET RECEIVED; STATE r4";
		break;

	    case 0xFC:
		cp = "INVALID PACKET RECEIVED; STATE r3";
		break;

	    case 0xFD:
		cp = "LINE STATUS CHANGE IN STATE r2";
		break;

	    case 0xFE:
		cp = "LINE STATUS CHANGE IN STATE r1";
		break;

	    case 0xFF:
		cp = "LINE STATUS CHANGE IN STATE r0";
		break;

	    default:
		SLOG (compat_log, LLOG_EXCEPTIONS, NULLCP,
		      ("diagnostic: 0x%2x", pkt[1]));
		goto done;
	}
	SLOG (compat_log, LLOG_EXCEPTIONS, NULLCP, ("diagnostic %s", cp));
    }
    else        /* Not RECV_DIAG */
	if (flags)
	    SLOG (compat_log, LLOG_EXCEPTIONS, NULLCP,
		  ("diag flags: 0x%02x", flags));

done: ;
    return OK;
}

#endif