From:	CRDGW2::CRDGW2::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX"  2-SEP-1989 18:32
To:	MRGATE::"ARISIA::EVERHART"
Subj:	How to Get VAX HostID

Received: From KL.SRI.COM by CRVAX.SRI.COM with TCP; Sat,  2 SEP 89 13:47:41 PDT
Received: from ucbvax.Berkeley.EDU by KL.SRI.COM with TCP; Sat, 2 Sep 89 13:45:23 PDT
Received: by ucbvax.Berkeley.EDU (5.61/1.37)
	id AA29447; Sat, 2 Sep 89 13:37:12 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews
	for info-vax@kl.sri.com (info-vax@kl.sri.com)
	(contact usenet@ucbvax.Berkeley.EDU if you have questions)
Date: 1 Sep 89 17:39:41 GMT
From: zephyr.ens.tek.com!tektronix!percy!parsely!bucket!servio!penneyj@uunet.uu.net  (D. Jason Penney)
Organization: Servio Logic Development Corp.; Beaverton, OR
Subject: How to Get VAX HostID
Message-Id: <167@servio.UUCP>
Sender: info-vax-request@kl.sri.com
To: info-vax@kl.sri.com

This is a followup to my own question, where I asked how to get the
serial number of a VAX under VMS.

$ SET FLAME/ON

It's clear that DEC has a decent hostid buried inside of their system,
otherwise LMF would not be possible.  It is unspeakably rude of them not
to make that ID available by a simple SYS$GETSYI call.

$ SET FLAME/OFF

I received a nice example program that shows how one can read the
raw ethernet address off of a DEC-supported ethernet card and how to
interpret what little serial number is available from the SID of the
machine (MicroVAX-II's have none, and even the top of the line 8800 only has
16 bits, if you can believe that!)

This program has probably gone by Info-VAX before, but I thought I'd return
the magic karma of the net by posting my derivative of the original program.

This program will print both the ethernet card physical address and a
"fake id" that can be used if the ethernet card address is not available.

Perhaps one day DEC will realize that other people sell software besides
themselves.  But until then...

/* Many thanks for the following code; credit goes to...
 * 21-DEC-88 George Carrette, Mitech Corporation, 508-371-2002
   74 Junction Square, Concord MA 01742
 */
#include <stdio.h>
typedef unsigned char BoolType;
typedef unsigned char ByteType;

#include <descrip.h>
#include <ssdef.h>
#include <iodef.h>
#include <syidef.h>
#include <string.h>

/* NMA codes from
 $lib/extract=$nmadef sys$library:lib.mlb
*/
#define NMA$C_PCLI_HWA 1160
#define NMA$C_PCLI_PHA 2820

#if 0
/* DC and DT codes from
 $lib/extract=$dcdef sys$library:starlet.mlb
*/
#define DC$_SCOM	32
#define DT$_DEUNA	14
#define DT$_DEQNA	22
#define DT$_ES_LANCE	24
#define DT$_DELUA	25
#define DT$_ET_DEBNA	29
#define DT$_XQ_DELQA	33
#endif
#include <dcdef.h>

#if 0
/* lib/extract=$prdef sys$library:starlet.mlb */
#define	PR$_SID_TYP780	1
#define	PR$_SID_TYP750	2
#define	PR$_SID_TYP730	3
#define	PR$_SID_TYP790	4
#define	PR$_SID_TYP8SS	5
#define	PR$_SID_TYP8NN	6
#define	PR$_SID_TYPUV1	7
#define	PR$_SID_TYPUV2	8
#define	PR$_SID_TYP009	9
#define	PR$_SID_TYP650	10
#define	PR$_SID_TYP9RR	11
#define PR$_SID_TYP8PS	17
#endif
#include <prdef.h>

typedef unsigned char HostIdAType[6];

/* Kludge to make a vax id when all else fails... */
static void HostIdMakeVaxId(BoolType * status, char msg[], 
    HostIdAType resultId)
{
struct { 
  short  len;
  short code; 
  unsigned long * buf; 
  short * ret; 
  long  term; 
  } theList; 
short len; 
unsigned long cpuResult; 
unsigned short hwResult;
long syiresult; 
long cpu; 

*status = FALSE; 
theList.code = SYI$_SID; 
theList.len = 4; 
theList.buf = &cpuResult; 
theList.ret = &len; 
theList.term = 0L; 
syiresult = SYS$GETSYIW(0, 0, 0, (ByteType *)&theList, 0, 0, 0); 
if (syiresult != SS$_NORMAL) { 
  sprintf(msg, "SYS$GETSYIW SYI$_SID failure, code = %d", syiresult); 
  return;
  } 
theList.code = SYI$_HW_MODEL; 
theList.len = 2; 
theList.buf = &hwResult; 
theList.ret = &len; 
theList.term = 0L; 
syiresult = SYS$GETSYIW(0, 0, 0, (ByteType *)&theList, 0, 0, 0); 
if (syiresult != SS$_NORMAL) { 
  sprintf(msg, "SYS$GETSYIW SYI$_HW_MODEL failure, code = %d", syiresult); 
  return;
  } 
memset(resultId, 0, sizeof (HostIdAType));
cpu = ((cpuResult >> 24) & 0xFF); 
resultId[0] = cpu; /* salt with CPU type */
resultId[1] = hwResult >> 8; /* and with hardware model */
resultId[2] = hwResult & 0xFF;
switch (cpu) { 
  case PR$_SID_TYP780: /* 780 */ 
    cpuResult = cpuResult & 0x7FFF; 
    resultId[4] = cpuResult >> 8;
    resultId[5] = cpuResult & 0xFF;
    break; 
  case PR$_SID_TYP790: /* 8600 */ 
  case PR$_SID_TYP8NN: /* 8800 */
    cpuResult = cpuResult & 0xFFFF; 
    resultId[4] = cpuResult >> 8;
    resultId[5] = cpuResult & 0xFF;
    break; 
  default: { /* build a fake id */
    resultId[3] = 0x98;
    resultId[4] = 0x48;
    resultId[5] = 0x4c;
    break;
    }
  }
*status = TRUE; 
}

#define HOSTID_READ(status, msg, theId) VmsHostIdRead(&status, msg, theId)

static void VmsHostIdRead(BoolType *status, char msg[], HostIdAType theId)
{
int retval, dn, opcode, clength, litem;
short chan;
struct {
  unsigned short cstatus;
  unsigned short tsize;
  ByteType unused1;
  ByteType status;
  ByteType errors;
  ByteType unused2;
  } iosb;
struct {
  ByteType class;
  ByteType type;
  unsigned short max_message_size;
  ByteType unused1;
  ByteType status;
  ByteType error_summary;
  ByteType unused2;
  char extra_safe[100];
  } p1;
struct dsc$descriptor devnam,p2;
ByteType buffer[512];
ByteType *cp,*citem,*devst;

for (devst="XEA0:ESA0:XQA0:ETA0:"; *devst; devst += 5) {
  devnam.dsc$w_length = 5;
  devnam.dsc$a_pointer = devst;
  devnam.dsc$b_class = DSC$K_CLASS_S;
  devnam.dsc$b_dtype = DSC$K_DTYPE_T;
  retval = SYS$ASSIGN(&devnam, &chan, 0, 0);
  strcpy(msg, "Could not find ethernet board");
  if ((retval != SS$_NORMAL) && (retval != SS$_REMOTE)) 
    continue;
  p2.dsc$w_length = sizeof(buffer);
  p2.dsc$a_pointer = &buffer;
  p2.dsc$b_class = 0;
  p2.dsc$b_dtype = 0;
  retval = SYS$QIOW(0,chan,IO$_SENSEMODE | IO$M_CTRL, &iosb,
      0, 0, &p1, &p2, 0, 0, 0, 0);
  if (retval == SS$_NORMAL) 
    retval = iosb.cstatus;
  if (retval != SS$_NORMAL) {
    sprintf(msg, "Could not do IO$_SENSEMODE on %c%c%c%c:, error = %d",
      devst[0], devst[1], devst[2], devst[3], devst[4], retval);
    SYS$DASSGN(chan); 
    continue;
    }
  if ((p1.class != DC$_SCOM) ||
      ((p1.type != DT$_DEUNA) && (p1.type != DT$_DEQNA) &&
      (p1.type != DT$_ES_LANCE) && (p1.type != DT$_DELUA) &&
      (p1.type != DT$_ET_DEBNA) && (p1.type != DT$_XQ_DELQA))) {
    sprintf(msg, "Peculiar ethernet board, class = %d, type = %d",
      p1.class, p1.type);
    SYS$DASSGN(chan); 
    continue;
    }
  SYS$DASSGN(chan);
  cp = buffer;
  dn = 0;
  while (dn < iosb.tsize) {
    opcode = *((short *)cp);
    cp += sizeof(short);
    dn += sizeof(short);
    if (opcode & 0x1000) {
      clength = *((short *)cp);
      cp += sizeof(short);
      dn += sizeof(short);
      citem = cp;
      cp += clength;
      dn += clength;
      }
    else {
      litem = *((long *)cp);
      cp += sizeof(long);
      dn += sizeof(long);
      }
    strcpy(msg, "Could not find NMA$C_PCLI_HWA");
    switch (opcode & 0xFFF) {
      case NMA$C_PCLI_PHA:
	break;
      case NMA$C_PCLI_HWA:
        memcpy(theId, citem, sizeof (HostIdAType));
	*status = TRUE;
        return;
      default:
        break;
      }
    }
  }
 *status = FALSE;
 return;
}

main()
{
 BoolType status;
 char msg[100];
 HostIdAType theId;

 HOSTID_READ(status, msg, theId);
 if (status)
   printf("   Ethernet ID: %02x-%02x-%02x-%02x-%02x-%02x\n",
       theId[0], theId[1], theId[2], theId[3], theId[4], theId[5]);
 else
   printf("Ethernet error: %s\n", msg);
 HostIdMakeVaxId(&status, msg, theId);
 if (status)
   printf("       Fake ID: %02x-%02x-%02x-%02x-%02x-%02x\n",
       theId[0], theId[1], theId[2], theId[3], theId[4], theId[5]);
 else
   printf(" Fake ID error: %s\n", msg);
}
-- 
D. Jason Penney                  Ph: (503) 629-8383
Beaverton, OR 97006              uucp: ...uunet!servio!penneyj
STANDARD DISCLAIMER:  Should I or my opinions be caught or killed, the
company will disavow any knowledge of my actions...

