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