parsenfsfh.c revision 75118
117680Spst/* 217680Spst * parsenfsfh.c - portable parser for NFS file handles 317680Spst * uses all sorts of heuristics 417680Spst * 517680Spst * Jeffrey C. Mogul 617680Spst * Digital Equipment Corporation 717680Spst * Western Research Laboratory 856896Sfenner * 956896Sfenner * $FreeBSD: head/contrib/tcpdump/parsenfsfh.c 75118 2001-04-03 07:50:46Z fenner $ 1017680Spst */ 1117680Spst 1226183Sfenner#ifndef lint 1326183Sfennerstatic const char rcsid[] = 1475118Sfenner "@(#) $Header: /tcpdump/master/tcpdump/parsenfsfh.c,v 1.18 2000/07/01 03:39:00 assar Exp $ (LBL)"; 1526183Sfenner#endif 1626183Sfenner 1756896Sfenner#ifdef HAVE_CONFIG_H 1856896Sfenner#include "config.h" 1956896Sfenner#endif 2056896Sfenner 2117680Spst#include <sys/types.h> 2217680Spst#include <sys/time.h> 2317680Spst 2417680Spst#include <ctype.h> 2517680Spst#include <stdio.h> 2617680Spst#include <string.h> 2717680Spst 2817680Spst#include "interface.h" 2917680Spst#include "nfsfh.h" 3017680Spst 3117680Spst/* 3217680Spst * This routine attempts to parse a file handle (in network byte order), 3317680Spst * using heuristics to guess what kind of format it is in. See the 3417680Spst * file "fhandle_layouts" for a detailed description of the various 3517680Spst * patterns we know about. 3617680Spst * 3717680Spst * The file handle is parsed into our internal representation of a 3817680Spst * file-system id, and an internal representation of an inode-number. 3917680Spst */ 4017680Spst 4117680Spst#define FHT_UNKNOWN 0 4217680Spst#define FHT_AUSPEX 1 4317680Spst#define FHT_DECOSF 2 4417680Spst#define FHT_IRIX4 3 4517680Spst#define FHT_IRIX5 4 4617680Spst#define FHT_SUNOS3 5 4717680Spst#define FHT_SUNOS4 6 4817680Spst#define FHT_ULTRIX 7 4917680Spst#define FHT_VMSUCX 8 5017680Spst#define FHT_SUNOS5 9 5117680Spst#define FHT_AIX32 10 5217680Spst#define FHT_HPUX9 11 5317680Spst 5417680Spst#ifdef ultrix 5517680Spst/* Nasty hack to keep the Ultrix C compiler from emitting bogus warnings */ 5617680Spst#define XFF(x) ((u_int32_t)(x)) 5717680Spst#else 5817680Spst#define XFF(x) (x) 5917680Spst#endif 6017680Spst 6117680Spst#define make_uint32(msb,b,c,lsb)\ 6217680Spst (XFF(lsb) + (XFF(c)<<8) + (XFF(b)<<16) + (XFF(msb)<<24)) 6317680Spst 6417680Spst#define make_uint24(msb,b, lsb)\ 6517680Spst (XFF(lsb) + (XFF(b)<<8) + (XFF(msb)<<16)) 6617680Spst 6717680Spst#define make_uint16(msb,lsb)\ 6817680Spst (XFF(lsb) + (XFF(msb)<<8)) 6917680Spst 7017680Spst#ifdef __alpha 7117680Spst /* or other 64-bit systems */ 7217680Spst#define make_uint48(msb,b,c,d,e,lsb)\ 7317680Spst ((lsb) + ((e)<<8) + ((d)<<16) + ((c)<<24) + ((b)<<32) + ((msb)<<40)) 7417680Spst#else 7517680Spst /* on 32-bit systems ignore high-order bits */ 7617680Spst#define make_uint48(msb,b,c,d,e,lsb)\ 7717680Spst ((lsb) + ((e)<<8) + ((d)<<16) + ((c)<<24)) 7817680Spst#endif 7917680Spst 8017680Spststatic int is_UCX(unsigned char *); 8117680Spst 8217680Spstvoid 8318976SdfrParse_fh(fh, len, fsidp, inop, osnamep, fsnamep, ourself) 8417680Spstregister caddr_t *fh; 8518976Sdfrint len; 8617680Spstmy_fsid *fsidp; 8717680Spstino_t *inop; 8817680Spstchar **osnamep; /* if non-NULL, return OS name here */ 8917680Spstchar **fsnamep; /* if non-NULL, return server fs name here (for VMS) */ 9017680Spstint ourself; /* true if file handle was generated on this host */ 9117680Spst{ 9217680Spst register unsigned char *fhp = (unsigned char *)fh; 9317680Spst u_int32_t temp; 9417680Spst int fhtype = FHT_UNKNOWN; 9575118Sfenner int i; 9617680Spst 9717680Spst if (ourself) { 9817680Spst /* File handle generated on this host, no need for guessing */ 9917680Spst#if defined(IRIX40) 10017680Spst fhtype = FHT_IRIX4; 10117680Spst#endif 10217680Spst#if defined(IRIX50) 10317680Spst fhtype = FHT_IRIX5; 10417680Spst#endif 10517680Spst#if defined(IRIX51) 10617680Spst fhtype = FHT_IRIX5; 10717680Spst#endif 10817680Spst#if defined(SUNOS4) 10917680Spst fhtype = FHT_SUNOS4; 11017680Spst#endif 11117680Spst#if defined(SUNOS5) 11217680Spst fhtype = FHT_SUNOS5; 11317680Spst#endif 11417680Spst#if defined(ultrix) 11517680Spst fhtype = FHT_ULTRIX; 11617680Spst#endif 11717680Spst#if defined(__osf__) 11817680Spst fhtype = FHT_DECOSF; 11917680Spst#endif 12017680Spst } 12117680Spst /* 12217680Spst * This is basically a big decision tree 12317680Spst */ 12417680Spst else if ((fhp[0] == 0) && (fhp[1] == 0)) { 12517680Spst /* bytes[0,1] == (0,0); rules out Ultrix, IRIX5, SUNOS5 */ 12617680Spst /* probably rules out HP-UX, AIX unless they allow major=0 */ 12717680Spst if ((fhp[2] == 0) && (fhp[3] == 0)) { 12817680Spst /* bytes[2,3] == (0,0); must be Auspex */ 12917680Spst /* XXX or could be Ultrix+MASSBUS "hp" disk? */ 13017680Spst fhtype = FHT_AUSPEX; 13117680Spst } 13217680Spst else { 13317680Spst /* 13417680Spst * bytes[2,3] != (0,0); rules out Auspex, could be 13517680Spst * DECOSF, SUNOS4, or IRIX4 13617680Spst */ 13717680Spst if ((fhp[4] != 0) && (fhp[5] == 0) && 13817680Spst (fhp[8] == 12) && (fhp[9] == 0)) { 13917680Spst /* seems to be DECOSF, with minor == 0 */ 14017680Spst fhtype = FHT_DECOSF; 14117680Spst } 14217680Spst else { 14317680Spst /* could be SUNOS4 or IRIX4 */ 14417680Spst /* XXX the test of fhp[5] == 8 could be wrong */ 14517680Spst if ((fhp[4] == 0) && (fhp[5] == 8) && (fhp[6] == 0) && 14617680Spst (fhp[7] == 0)) { 14717680Spst /* looks like a length, not a file system typecode */ 14817680Spst fhtype = FHT_IRIX4; 14917680Spst } 15017680Spst else { 15117680Spst /* by elimination */ 15217680Spst fhtype = FHT_SUNOS4; 15317680Spst } 15417680Spst } 15517680Spst } 15617680Spst } 15717680Spst else { 15817680Spst /* 15917680Spst * bytes[0,1] != (0,0); rules out Auspex, IRIX4, SUNOS4 16017680Spst * could be IRIX5, DECOSF, UCX, Ultrix, SUNOS5 16117680Spst * could be AIX, HP-UX 16217680Spst */ 16317680Spst if ((fhp[2] == 0) && (fhp[3] == 0)) { 16417680Spst /* 16517680Spst * bytes[2,3] == (0,0); rules out OSF, probably not UCX 16617680Spst * (unless the exported device name is just one letter!), 16717680Spst * could be Ultrix, IRIX5, AIX, or SUNOS5 16817680Spst * might be HP-UX (depends on their values for minor devs) 16917680Spst */ 17017680Spst /*XXX we probably only need to test of these two bytes */ 17117680Spst if ((fhp[21] == 0) && (fhp[23] == 0)) { 17217680Spst fhtype = FHT_ULTRIX; 17317680Spst } 17417680Spst else { 17517680Spst /* Could be SUNOS5/IRIX5, maybe AIX */ 17617680Spst /* XXX no obvious difference between SUNOS5 and IRIX5 */ 17717680Spst if (fhp[9] == 10) 17817680Spst fhtype = FHT_SUNOS5; 17917680Spst /* XXX what about AIX? */ 18017680Spst } 18117680Spst } 18217680Spst else { 18317680Spst /* 18417680Spst * bytes[2,3] != (0,0); rules out Ultrix, could be 18517680Spst * DECOSF, SUNOS5, IRIX5, AIX, HP-UX, or UCX 18617680Spst */ 18717680Spst if ((fhp[8] == 12) && (fhp[9] == 0)) { 18817680Spst fhtype = FHT_DECOSF; 18917680Spst } 19017680Spst else if ((fhp[8] == 0) && (fhp[9] == 10)) { 19117680Spst /* could be SUNOS5/IRIX5, AIX, HP-UX */ 19217680Spst if ((fhp[7] == 0) && (fhp[6] == 0) && 19317680Spst (fhp[5] == 0) && (fhp[4] == 0)) { 19417680Spst /* XXX is this always true of HP-UX? */ 19517680Spst fhtype = FHT_HPUX9; 19617680Spst } 19717680Spst else if (fhp[7] == 2) { 19817680Spst /* This would be MNT_NFS on AIX, which is impossible */ 19917680Spst fhtype = FHT_SUNOS5; /* or maybe IRIX5 */ 20017680Spst } 20117680Spst else { 20217680Spst /* 20317680Spst * XXX Could be SUNOS5/IRIX5 or AIX. I don't 20417680Spst * XXX see any way to disambiguate these, so 20517680Spst * XXX I'm going with the more likely guess. 20617680Spst * XXX Sorry, Big Blue. 20717680Spst */ 20817680Spst fhtype = FHT_SUNOS5; /* or maybe IRIX5 */ 20917680Spst } 21017680Spst } 21117680Spst else { 21217680Spst if (is_UCX(fhp)) { 21317680Spst fhtype = FHT_VMSUCX; 21417680Spst } 21517680Spst else { 21617680Spst fhtype = FHT_UNKNOWN; 21717680Spst } 21817680Spst } 21917680Spst } 22017680Spst } 22117680Spst 22217680Spst /* XXX still needs to handle SUNOS3 */ 22317680Spst 22417680Spst switch (fhtype) { 22517680Spst case FHT_AUSPEX: 22626183Sfenner fsidp->Fsid_dev.Minor = fhp[7]; 22726183Sfenner fsidp->Fsid_dev.Major = fhp[6]; 22817680Spst fsidp->fsid_code = 0; 22917680Spst 23017680Spst temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]); 23117680Spst *inop = temp; 23217680Spst 23317680Spst if (osnamep) 23417680Spst *osnamep = "Auspex"; 23517680Spst break; 23617680Spst 23717680Spst case FHT_DECOSF: 23817680Spst fsidp->fsid_code = make_uint32(fhp[7], fhp[6], fhp[5], fhp[4]); 23917680Spst /* XXX could ignore 3 high-order bytes */ 24017680Spst 24117680Spst temp = make_uint32(fhp[3], fhp[2], fhp[1], fhp[0]); 24226183Sfenner fsidp->Fsid_dev.Minor = temp & 0xFFFFF; 24326183Sfenner fsidp->Fsid_dev.Major = (temp>>20) & 0xFFF; 24417680Spst 24517680Spst temp = make_uint32(fhp[15], fhp[14], fhp[13], fhp[12]); 24617680Spst *inop = temp; 24717680Spst if (osnamep) 24817680Spst *osnamep = "OSF"; 24917680Spst break; 25017680Spst 25117680Spst case FHT_IRIX4: 25226183Sfenner fsidp->Fsid_dev.Minor = fhp[3]; 25326183Sfenner fsidp->Fsid_dev.Major = fhp[2]; 25417680Spst fsidp->fsid_code = 0; 25517680Spst 25617680Spst temp = make_uint32(fhp[8], fhp[9], fhp[10], fhp[11]); 25717680Spst *inop = temp; 25817680Spst 25917680Spst if (osnamep) 26017680Spst *osnamep = "IRIX4"; 26117680Spst break; 26217680Spst 26317680Spst case FHT_IRIX5: 26426183Sfenner fsidp->Fsid_dev.Minor = make_uint16(fhp[2], fhp[3]); 26526183Sfenner fsidp->Fsid_dev.Major = make_uint16(fhp[0], fhp[1]); 26617680Spst fsidp->fsid_code = make_uint32(fhp[4], fhp[5], fhp[6], fhp[7]); 26717680Spst 26817680Spst temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]); 26917680Spst *inop = temp; 27017680Spst 27117680Spst if (osnamep) 27217680Spst *osnamep = "IRIX5"; 27317680Spst break; 27417680Spst 27517680Spst case FHT_SUNOS3: 27617680Spst if (osnamep) 27717680Spst *osnamep = "SUNOS3"; 27817680Spst break; 27917680Spst 28017680Spst case FHT_SUNOS4: 28126183Sfenner fsidp->Fsid_dev.Minor = fhp[3]; 28226183Sfenner fsidp->Fsid_dev.Major = fhp[2]; 28317680Spst fsidp->fsid_code = make_uint32(fhp[4], fhp[5], fhp[6], fhp[7]); 28417680Spst 28517680Spst temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]); 28617680Spst *inop = temp; 28717680Spst 28817680Spst if (osnamep) 28917680Spst *osnamep = "SUNOS4"; 29017680Spst break; 29117680Spst 29217680Spst case FHT_SUNOS5: 29317680Spst temp = make_uint16(fhp[0], fhp[1]); 29426183Sfenner fsidp->Fsid_dev.Major = (temp>>2) & 0x3FFF; 29517680Spst temp = make_uint24(fhp[1], fhp[2], fhp[3]); 29626183Sfenner fsidp->Fsid_dev.Minor = temp & 0x3FFFF; 29717680Spst fsidp->fsid_code = make_uint32(fhp[4], fhp[5], fhp[6], fhp[7]); 29817680Spst 29917680Spst temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]); 30017680Spst *inop = temp; 30117680Spst 30217680Spst if (osnamep) 30317680Spst *osnamep = "SUNOS5"; 30417680Spst break; 30517680Spst 30617680Spst case FHT_ULTRIX: 30717680Spst fsidp->fsid_code = 0; 30826183Sfenner fsidp->Fsid_dev.Minor = fhp[0]; 30926183Sfenner fsidp->Fsid_dev.Major = fhp[1]; 31017680Spst 31117680Spst temp = make_uint32(fhp[7], fhp[6], fhp[5], fhp[4]); 31217680Spst *inop = temp; 31317680Spst if (osnamep) 31417680Spst *osnamep = "Ultrix"; 31517680Spst break; 31617680Spst 31717680Spst case FHT_VMSUCX: 31817680Spst /* No numeric file system ID, so hash on the device-name */ 31917680Spst if (sizeof(*fsidp) >= 14) { 32017680Spst if (sizeof(*fsidp) > 14) 32117680Spst memset((char *)fsidp, 0, sizeof(*fsidp)); 32239300Sfenner /* just use the whole thing */ 32339300Sfenner memcpy((char *)fsidp, (char *)fh, 14); 32417680Spst } 32517680Spst else { 32617680Spst u_int32_t tempa[4]; /* at least 16 bytes, maybe more */ 32717680Spst 32817680Spst memset((char *)tempa, 0, sizeof(tempa)); 32939300Sfenner memcpy((char *)tempa, (char *)fh, 14); /* ensure alignment */ 33026183Sfenner fsidp->Fsid_dev.Minor = tempa[0] + (tempa[1]<<1); 33126183Sfenner fsidp->Fsid_dev.Major = tempa[2] + (tempa[3]<<1); 33217680Spst fsidp->fsid_code = 0; 33317680Spst } 33417680Spst 33517680Spst /* VMS file ID is: (RVN, FidHi, FidLo) */ 33617680Spst *inop = make_uint32(fhp[26], fhp[27], fhp[23], fhp[22]); 33717680Spst 33817680Spst /* Caller must save (and null-terminate?) this value */ 33917680Spst if (fsnamep) 34017680Spst *fsnamep = (char *)&(fhp[1]); 34117680Spst 34217680Spst if (osnamep) 34317680Spst *osnamep = "VMS"; 34417680Spst break; 34517680Spst 34617680Spst case FHT_AIX32: 34726183Sfenner fsidp->Fsid_dev.Minor = make_uint16(fhp[2], fhp[3]); 34826183Sfenner fsidp->Fsid_dev.Major = make_uint16(fhp[0], fhp[1]); 34917680Spst fsidp->fsid_code = make_uint32(fhp[4], fhp[5], fhp[6], fhp[7]); 35017680Spst 35117680Spst temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]); 35217680Spst *inop = temp; 35317680Spst 35417680Spst if (osnamep) 35517680Spst *osnamep = "AIX32"; 35617680Spst break; 35717680Spst 35817680Spst case FHT_HPUX9: 35926183Sfenner fsidp->Fsid_dev.Major = fhp[0]; 36017680Spst temp = make_uint24(fhp[1], fhp[2], fhp[3]); 36126183Sfenner fsidp->Fsid_dev.Minor = temp; 36217680Spst fsidp->fsid_code = make_uint32(fhp[4], fhp[5], fhp[6], fhp[7]); 36317680Spst 36417680Spst temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]); 36517680Spst *inop = temp; 36617680Spst 36717680Spst if (osnamep) 36817680Spst *osnamep = "HPUX9"; 36917680Spst break; 37017680Spst 37117680Spst case FHT_UNKNOWN: 37217680Spst#ifdef DEBUG 37375118Sfenner /* XXX debugging */ 37475118Sfenner int i; 37575118Sfenner for (i = 0; i < 32; i++) 37675118Sfenner (void)fprintf(stderr, "%x.", fhp[i]); 37775118Sfenner (void)fprintf(stderr, "\n"); 37817680Spst#endif 37917680Spst /* XXX for now, give "bogus" values to aid debugging */ 38075118Sfenner 38175118Sfenner /* Save the actual handle, so it can be display with -u */ 38275118Sfenner for (i = 0; i < 32; i++) 38375118Sfenner (void)sprintf(&(fsidp->Opaque_Handle[i*2]), "%.2X", fhp[i]); 38475118Sfenner 38517680Spst fsidp->fsid_code = 0; 38626183Sfenner fsidp->Fsid_dev.Minor = 257; 38726183Sfenner fsidp->Fsid_dev.Major = 257; 38817680Spst *inop = 1; 38917680Spst 39017680Spst /* display will show this string instead of (257,257) */ 39117680Spst if (fsnamep) 39217680Spst *fsnamep = "Unknown"; 39317680Spst 39417680Spst if (osnamep) 39517680Spst *osnamep = "Unknown"; 39617680Spst break; 39717680Spst 39817680Spst } 39917680Spst} 40017680Spst 40117680Spst/* 40217680Spst * Is this a VMS UCX file handle? 40317680Spst * Check for: 40417680Spst * (1) leading code byte [XXX not yet] 40517680Spst * (2) followed by string of printing chars & spaces 40617680Spst * (3) followed by string of nulls 40717680Spst */ 40817680Spststatic int 40917680Spstis_UCX(fhp) 41017680Spstunsigned char *fhp; 41117680Spst{ 41217680Spst register int i; 41317680Spst int seen_null = 0; 41417680Spst 41517680Spst for (i = 1; i < 14; i++) { 41617680Spst if (isprint(fhp[i])) { 41717680Spst if (seen_null) 41817680Spst return(0); 41917680Spst else 42017680Spst continue; 42117680Spst } 42217680Spst else if (fhp[i] == 0) { 42317680Spst seen_null = 1; 42417680Spst continue; 42517680Spst } 42617680Spst else 42717680Spst return(0); 42817680Spst } 42917680Spst 43017680Spst return(1); 43117680Spst} 432