parsenfsfh.c revision 56896
110015Speter/*
212496Speter * parsenfsfh.c - portable parser for NFS file handles
310015Speter *			uses all sorts of heuristics
434832Speter *
510015Speter * Jeffrey C. Mogul
634832Speter * Digital Equipment Corporation
710015Speter * Western Research Laboratory
810015Speter *
910015Speter * $FreeBSD: head/contrib/tcpdump/parsenfsfh.c 56896 2000-01-30 01:05:24Z fenner $
1010015Speter */
1110015Speter
1210015Speter#ifndef lint
1310015Speterstatic const char rcsid[] =
1410015Speter    "@(#) $Header: /tcpdump/master/tcpdump/parsenfsfh.c,v 1.16 1999/11/21 09:36:47 fenner Exp $ (LBL)";
1510015Speter#endif
1610015Speter
1710015Speter#ifdef HAVE_CONFIG_H
1810015Speter#include "config.h"
1910015Speter#endif
2010015Speter
2110015Speter#include <sys/types.h>
2210015Speter#include <sys/time.h>
2310015Speter
2410015Speter#include <ctype.h>
2510015Speter#ifdef HAVE_MEMORY_H
2610015Speter#include <memory.h>
2710015Speter#endif
2810015Speter#include <stdio.h>
2910015Speter#include <string.h>
3010015Speter
3110015Speter#include "interface.h"
3210015Speter#include "nfsfh.h"
3338485Sbde
3410015Speter/*
3510015Speter * This routine attempts to parse a file handle (in network byte order),
3610015Speter * using heuristics to guess what kind of format it is in.  See the
3734832Speter * file "fhandle_layouts" for a detailed description of the various
3834832Speter * patterns we know about.
3934832Speter *
4010015Speter * The file handle is parsed into our internal representation of a
4110015Speter * file-system id, and an internal representation of an inode-number.
4231778Seivind */
4332929Seivind
4432726Seivind#define	FHT_UNKNOWN	0
4531778Seivind#define	FHT_AUSPEX	1
4610015Speter#define	FHT_DECOSF	2
4710015Speter#define	FHT_IRIX4	3
4824207Sbde#define	FHT_IRIX5	4
4924207Sbde#define	FHT_SUNOS3	5
5024207Sbde#define	FHT_SUNOS4	6
5110015Speter#define	FHT_ULTRIX	7
5210015Speter#define	FHT_VMSUCX	8
5310015Speter#define	FHT_SUNOS5	9
5424131Sbde#define	FHT_AIX32	10
5510015Speter#define	FHT_HPUX9	11
5610015Speter
5710015Speter#ifdef	ultrix
5815683Speter/* Nasty hack to keep the Ultrix C compiler from emitting bogus warnings */
5912675Sjulian#define	XFF(x)	((u_int32_t)(x))
6012675Sjulian#else
6112675Sjulian#define	XFF(x)	(x)
6210015Speter#endif
6310015Speter
6410015Speter#define	make_uint32(msb,b,c,lsb)\
6512659Sbde	(XFF(lsb) + (XFF(c)<<8) + (XFF(b)<<16) + (XFF(msb)<<24))
6612662Sdg
6712659Sbde#define	make_uint24(msb,b, lsb)\
6810015Speter	(XFF(lsb) + (XFF(b)<<8) + (XFF(msb)<<16))
6910015Speter
7010015Speter#define	make_uint16(msb,lsb)\
7110015Speter	(XFF(lsb) + (XFF(msb)<<8))
7210015Speter
7310015Speter#ifdef	__alpha
7413353Speter	/* or other 64-bit systems */
7510015Speter#define	make_uint48(msb,b,c,d,e,lsb)\
7633395Speter	((lsb) + ((e)<<8) + ((d)<<16) + ((c)<<24) + ((b)<<32) + ((msb)<<40))
7733395Speter#else
7833395Speter	/* on 32-bit systems ignore high-order bits */
7933395Speter#define	make_uint48(msb,b,c,d,e,lsb)\
8033395Speter	((lsb) + ((e)<<8) + ((d)<<16) + ((c)<<24))
8134832Speter#endif
8234832Speter
8334832Speterstatic int is_UCX(unsigned char *);
8434832Speter
8534832Spetervoid
8634832SpeterParse_fh(fh, len, fsidp, inop, osnamep, fsnamep, ourself)
8710015Speterregister caddr_t *fh;
8810015Speterint len;
8910015Spetermy_fsid *fsidp;
9010015Speterino_t *inop;
9134832Speterchar **osnamep;		/* if non-NULL, return OS name here */
9234832Speterchar **fsnamep;		/* if non-NULL, return server fs name here (for VMS) */
9310015Speterint ourself;		/* true if file handle was generated on this host */
9434832Speter{
9534832Speter	register unsigned char *fhp = (unsigned char *)fh;
9633395Speter	u_int32_t temp;
9734832Speter	int fhtype = FHT_UNKNOWN;
9810015Speter
9910015Speter	if (ourself) {
10017547Speter	    /* File handle generated on this host, no need for guessing */
10117547Speter#if	defined(IRIX40)
10217547Speter	    fhtype = FHT_IRIX4;
10312496Speter#endif
10434832Speter#if	defined(IRIX50)
10534832Speter	    fhtype = FHT_IRIX5;
10615639Speter#endif
10710015Speter#if	defined(IRIX51)
10810015Speter	    fhtype = FHT_IRIX5;
10910015Speter#endif
11010015Speter#if	defined(SUNOS4)
11110015Speter	    fhtype = FHT_SUNOS4;
11210015Speter#endif
11338351Sbde#if	defined(SUNOS5)
11410015Speter	    fhtype = FHT_SUNOS5;
11525047Sbde#endif
11610015Speter#if	defined(ultrix)
11710015Speter	    fhtype = FHT_ULTRIX;
11810015Speter#endif
11910015Speter#if	defined(__osf__)
12010015Speter	    fhtype = FHT_DECOSF;
12112724Sphk#endif
12210015Speter	}
12312724Sphk	/*
12412724Sphk	 * This is basically a big decision tree
12510708Speter	 */
12634735Speter	else if ((fhp[0] == 0) && (fhp[1] == 0)) {
12734832Speter	    /* bytes[0,1] == (0,0); rules out Ultrix, IRIX5, SUNOS5 */
12810708Speter	    /* probably rules out HP-UX, AIX unless they allow major=0 */
12912675Sjulian	    if ((fhp[2] == 0) && (fhp[3] == 0)) {
13012675Sjulian		/* bytes[2,3] == (0,0); must be Auspex */
13112675Sjulian		/* XXX or could be Ultrix+MASSBUS "hp" disk? */
13234832Speter		fhtype = FHT_AUSPEX;
13334832Speter	    }
13433395Speter	    else {
13512675Sjulian		/*
13633395Speter		 * bytes[2,3] != (0,0); rules out Auspex, could be
13733395Speter		 * DECOSF, SUNOS4, or IRIX4
13833395Speter		 */
13933395Speter		if ((fhp[4] != 0) && (fhp[5] == 0) &&
14033395Speter			(fhp[8] == 12) && (fhp[9] == 0)) {
14133395Speter		    /* seems to be DECOSF, with minor == 0 */
14233395Speter		    fhtype = FHT_DECOSF;
14334832Speter		}
14433395Speter		else {
14533395Speter		    /* could be SUNOS4 or IRIX4 */
14633395Speter		    /* XXX the test of fhp[5] == 8 could be wrong */
14733395Speter		    if ((fhp[4] == 0) && (fhp[5] == 8) && (fhp[6] == 0) &&
14833395Speter			(fhp[7] == 0)) {
14933395Speter			/* looks like a length, not a file system typecode */
15033395Speter			fhtype = FHT_IRIX4;
15134832Speter		    }
15234832Speter		    else {
15334832Speter			/* by elimination */
15434832Speter			fhtype = FHT_SUNOS4;
15534832Speter		    }
15634832Speter		}
15734832Speter	    }
15834832Speter	}
15934832Speter	else {
16034832Speter	    /*
16134832Speter	     * bytes[0,1] != (0,0); rules out Auspex, IRIX4, SUNOS4
16234832Speter	     * could be IRIX5, DECOSF, UCX, Ultrix, SUNOS5
16334832Speter	     * could be AIX, HP-UX
16434832Speter	     */
16534832Speter	    if ((fhp[2] == 0) && (fhp[3] == 0)) {
16634832Speter		/*
16734832Speter		 * bytes[2,3] == (0,0); rules out OSF, probably not UCX
16812675Sjulian		 * (unless the exported device name is just one letter!),
16912675Sjulian		 * could be Ultrix, IRIX5, AIX, or SUNOS5
17012675Sjulian		 * might be HP-UX (depends on their values for minor devs)
17112675Sjulian		 */
17212675Sjulian		/*XXX we probably only need to test of these two bytes */
17312675Sjulian		if ((fhp[21] == 0) && (fhp[23] == 0)) {
17412731Sbde		    fhtype = FHT_ULTRIX;
17512675Sjulian		}
17638485Sbde		else {
17738485Sbde		    /* Could be SUNOS5/IRIX5, maybe AIX */
17838485Sbde		    /* XXX no obvious difference between SUNOS5 and IRIX5 */
17938485Sbde		    if (fhp[9] == 10)
18038485Sbde			fhtype = FHT_SUNOS5;
18138485Sbde		    /* XXX what about AIX? */
18238485Sbde		}
18338485Sbde	    }
18412675Sjulian	    else {
18512174Speter		/*
18613353Speter		 * bytes[2,3] != (0,0); rules out Ultrix, could be
18713353Speter		 * DECOSF, SUNOS5, IRIX5, AIX, HP-UX, or UCX
18813353Speter		 */
18910708Speter		if ((fhp[8] == 12) && (fhp[9] == 0)) {
19013353Speter		    fhtype = FHT_DECOSF;
19110708Speter		}
19213353Speter		else if ((fhp[8] == 0) && (fhp[9] == 10)) {
19310708Speter		    /* could be SUNOS5/IRIX5, AIX, HP-UX */
19410708Speter		    if ((fhp[7] == 0) && (fhp[6] == 0) &&
19510708Speter			(fhp[5] == 0) && (fhp[4] == 0)) {
19610708Speter			/* XXX is this always true of HP-UX? */
19710962Speter			fhtype = FHT_HPUX9;
19810962Speter		    }
19910962Speter		    else if (fhp[7] == 2) {
20010015Speter			/* This would be MNT_NFS on AIX, which is impossible */
20134832Speter			fhtype = FHT_SUNOS5;	/* or maybe IRIX5 */
20234832Speter		    }
20310962Speter		    else {
20410962Speter			/*
20534832Speter			 * XXX Could be SUNOS5/IRIX5 or AIX.  I don't
20634832Speter			 * XXX see any way to disambiguate these, so
20734832Speter			 * XXX I'm going with the more likely guess.
20834832Speter			 * XXX Sorry, Big Blue.
20934832Speter			 */
21034832Speter			fhtype = FHT_SUNOS5;	/* or maybe IRIX5 */
21134832Speter		    }
21234832Speter	        }
21334832Speter		else {
21434832Speter		    if (is_UCX(fhp)) {
21534832Speter			fhtype = FHT_VMSUCX;
21634832Speter		    }
21710015Speter		    else {
21833395Speter			fhtype = FHT_UNKNOWN;
21910044Speter		    }
22010044Speter		}
22110044Speter	    }
22210044Speter	}
22310044Speter
22410044Speter	/* XXX still needs to handle SUNOS3 */
22510044Speter
22610044Speter	switch (fhtype) {
22710044Speter	case FHT_AUSPEX:
22810044Speter	    fsidp->Fsid_dev.Minor = fhp[7];
22934832Speter	    fsidp->Fsid_dev.Major = fhp[6];
23010044Speter	    fsidp->fsid_code = 0;
23134832Speter
23234832Speter	    temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]);
23312675Sjulian	    *inop = temp;
23412675Sjulian
23534735Speter	    if (osnamep)
23612826Speter		*osnamep = "Auspex";
23712675Sjulian	    break;
23834735Speter
23912675Sjulian	case FHT_DECOSF:
24034735Speter	    fsidp->fsid_code = make_uint32(fhp[7], fhp[6], fhp[5], fhp[4]);
24112675Sjulian			/* XXX could ignore 3 high-order bytes */
24213165Speter
24312675Sjulian	    temp = make_uint32(fhp[3], fhp[2], fhp[1], fhp[0]);
24410044Speter	    fsidp->Fsid_dev.Minor = temp & 0xFFFFF;
24512724Sphk	    fsidp->Fsid_dev.Major = (temp>>20) & 0xFFF;
24610044Speter
24712174Speter	    temp = make_uint32(fhp[15], fhp[14], fhp[13], fhp[12]);
24810015Speter	    *inop = temp;
24910015Speter	    if (osnamep)
25010015Speter		*osnamep = "OSF";
25110015Speter	    break;
25210015Speter
25310015Speter	case FHT_IRIX4:
25410015Speter	    fsidp->Fsid_dev.Minor = fhp[3];
25510015Speter	    fsidp->Fsid_dev.Major = fhp[2];
25610015Speter	    fsidp->fsid_code = 0;
25710015Speter
25810015Speter	    temp = make_uint32(fhp[8], fhp[9], fhp[10], fhp[11]);
25910015Speter	    *inop = temp;
26010015Speter
26110015Speter	    if (osnamep)
26210015Speter		*osnamep = "IRIX4";
26310015Speter	    break;
26410015Speter
26510015Speter	case FHT_IRIX5:
26610015Speter	    fsidp->Fsid_dev.Minor = make_uint16(fhp[2], fhp[3]);
26710015Speter	    fsidp->Fsid_dev.Major = make_uint16(fhp[0], fhp[1]);
26810015Speter	    fsidp->fsid_code = make_uint32(fhp[4], fhp[5], fhp[6], fhp[7]);
26910015Speter
27010015Speter	    temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]);
27110015Speter	    *inop = temp;
27210015Speter
27310015Speter	    if (osnamep)
27410015Speter		*osnamep = "IRIX5";
27510015Speter	    break;
27610015Speter
27710015Speter	case FHT_SUNOS3:
27810015Speter	    if (osnamep)
27910015Speter		*osnamep = "SUNOS3";
28010015Speter	    break;
28110015Speter
28210015Speter	case FHT_SUNOS4:
28310015Speter	    fsidp->Fsid_dev.Minor = fhp[3];
28410015Speter	    fsidp->Fsid_dev.Major = fhp[2];
28510015Speter	    fsidp->fsid_code = make_uint32(fhp[4], fhp[5], fhp[6], fhp[7]);
28610015Speter
28710015Speter	    temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]);
28810015Speter	    *inop = temp;
28910015Speter
29010015Speter	    if (osnamep)
29110015Speter		*osnamep = "SUNOS4";
29215683Speter	    break;
29317547Speter
29415639Speter	case FHT_SUNOS5:
29516403Speter	    temp = make_uint16(fhp[0], fhp[1]);
29617547Speter	    fsidp->Fsid_dev.Major = (temp>>2) &  0x3FFF;
29715639Speter	    temp = make_uint24(fhp[1], fhp[2], fhp[3]);
29810015Speter	    fsidp->Fsid_dev.Minor = temp & 0x3FFFF;
29910015Speter	    fsidp->fsid_code = make_uint32(fhp[4], fhp[5], fhp[6], fhp[7]);
30010015Speter
30110015Speter	    temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]);
30210015Speter	    *inop = temp;
30310015Speter
30410015Speter	    if (osnamep)
30510015Speter		*osnamep = "SUNOS5";
30610015Speter	    break;
30710015Speter
30810015Speter	case FHT_ULTRIX:
30934832Speter	    fsidp->fsid_code = 0;
31010015Speter	    fsidp->Fsid_dev.Minor = fhp[0];
31110015Speter	    fsidp->Fsid_dev.Major = fhp[1];
31233395Speter
31333395Speter	    temp = make_uint32(fhp[7], fhp[6], fhp[5], fhp[4]);
31433395Speter	    *inop = temp;
31510015Speter	    if (osnamep)
31610015Speter		*osnamep = "Ultrix";
31733395Speter	    break;
31833395Speter
31933395Speter	case FHT_VMSUCX:
32033395Speter	    /* No numeric file system ID, so hash on the device-name */
32133395Speter	    if (sizeof(*fsidp) >= 14) {
32233395Speter		if (sizeof(*fsidp) > 14)
32333395Speter		    memset((char *)fsidp, 0, sizeof(*fsidp));
32433395Speter		/* just use the whole thing */
32533395Speter		memcpy((char *)fsidp, (char *)fh, 14);
32633395Speter	    }
32733395Speter	    else {
32833395Speter		u_int32_t tempa[4];	/* at least 16 bytes, maybe more */
32933395Speter
33033395Speter		memset((char *)tempa, 0, sizeof(tempa));
33133395Speter		memcpy((char *)tempa, (char *)fh, 14); /* ensure alignment */
33233395Speter		fsidp->Fsid_dev.Minor = tempa[0] + (tempa[1]<<1);
33333395Speter		fsidp->Fsid_dev.Major = tempa[2] + (tempa[3]<<1);
33433395Speter		fsidp->fsid_code = 0;
33533395Speter	    }
33633395Speter
33733395Speter	    /* VMS file ID is: (RVN, FidHi, FidLo) */
33833395Speter	    *inop = make_uint32(fhp[26], fhp[27], fhp[23], fhp[22]);
33933395Speter
34033395Speter	    /* Caller must save (and null-terminate?) this value */
34133395Speter	    if (fsnamep)
34233395Speter		*fsnamep = (char *)&(fhp[1]);
34333395Speter
34433395Speter	    if (osnamep)
34533395Speter		*osnamep = "VMS";
34633395Speter	    break;
34733395Speter
34833395Speter	case FHT_AIX32:
34933395Speter	    fsidp->Fsid_dev.Minor = make_uint16(fhp[2], fhp[3]);
35033395Speter	    fsidp->Fsid_dev.Major = make_uint16(fhp[0], fhp[1]);
35133395Speter	    fsidp->fsid_code = make_uint32(fhp[4], fhp[5], fhp[6], fhp[7]);
35233395Speter
35333395Speter	    temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]);
35433395Speter	    *inop = temp;
35534832Speter
35633395Speter	    if (osnamep)
35733395Speter		*osnamep = "AIX32";
35833395Speter	    break;
35934832Speter
36033395Speter	case FHT_HPUX9:
36133395Speter	    fsidp->Fsid_dev.Major = fhp[0];
36233395Speter	    temp = make_uint24(fhp[1], fhp[2], fhp[3]);
36333395Speter	    fsidp->Fsid_dev.Minor = temp;
36433395Speter	    fsidp->fsid_code = make_uint32(fhp[4], fhp[5], fhp[6], fhp[7]);
36533395Speter
36633395Speter	    temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]);
36733395Speter	    *inop = temp;
36833395Speter
36933395Speter	    if (osnamep)
37033395Speter		*osnamep = "HPUX9";
37133395Speter	    break;
37234735Speter
37333395Speter	case FHT_UNKNOWN:
37433395Speter#ifdef DEBUG
37533395Speter	    {
37633395Speter		/* XXX debugging */
37733395Speter		int i;
37833395Speter		for (i = 0; i < 32; i++)
37933395Speter			(void)fprintf(stderr, "%x.", fhp[i]);
38033395Speter		(void)fprintf(stderr, "\n");
38133395Speter	    }
38233395Speter#endif
38334735Speter	    /* XXX for now, give "bogus" values to aid debugging */
38434735Speter	    fsidp->fsid_code = 0;
38533395Speter	    fsidp->Fsid_dev.Minor = 257;
38633395Speter	    fsidp->Fsid_dev.Major = 257;
38733395Speter	    *inop = 1;
38833395Speter
38933395Speter	    /* display will show this string instead of (257,257) */
39034832Speter	    if (fsnamep)
39134832Speter		*fsnamep = "Unknown";
39234832Speter
39334832Speter	    if (osnamep)
39434832Speter		*osnamep = "Unknown";
39534832Speter	    break;
39634832Speter
39734832Speter	}
39834832Speter}
39934832Speter
40034832Speter/*
40134832Speter * Is this a VMS UCX file handle?
40234832Speter *	Check for:
40334832Speter *	(1) leading code byte	[XXX not yet]
40434832Speter *	(2) followed by string of printing chars & spaces
40534832Speter *	(3) followed by string of nulls
40634832Speter */
40734832Speterstatic int
40834832Speteris_UCX(fhp)
40934832Speterunsigned char *fhp;
41034832Speter{
41134832Speter	register int i;
41234832Speter	int seen_null = 0;
41334832Speter
41434832Speter	for (i = 1; i < 14; i++) {
41534832Speter	    if (isprint(fhp[i])) {
41634832Speter		if (seen_null)
41734832Speter		   return(0);
41834832Speter		else
41934832Speter		   continue;
42034832Speter	    }
42134832Speter	    else if (fhp[i] == 0) {
42234832Speter		seen_null = 1;
42334832Speter		continue;
42434832Speter	    }
42534832Speter	    else
42634832Speter		return(0);
42734832Speter	}
42834832Speter
42934832Speter	return(1);
43034832Speter}
43134832Speter