1 /* 2 * parsenfsfh.c - portable parser for NFS file handles 3 * uses all sorts of heuristics 4 * 5 * Jeffrey C. Mogul 6 * Digital Equipment Corporation 7 * Western Research Laboratory 8 * 9 * $FreeBSD$ 10 */ 11 12 #ifndef lint 13 static const char rcsid[] = 14 "@(#) $Header: /tcpdump/master/tcpdump/parsenfsfh.c,v 1.16 1999/11/21 09:36:47 fenner Exp $ (LBL)"; 15 #endif 16 17 #ifdef HAVE_CONFIG_H 18 #include "config.h" 19 #endif 20 21 #include <sys/types.h> 22 #include <sys/time.h> 23 24 #include <ctype.h> 25 #ifdef HAVE_MEMORY_H 26 #include <memory.h> 27 #endif 28 #include <stdio.h> 29 #include <string.h> 30 31 #include "interface.h" 32 #include "nfsfh.h" 33 34 /* 35 * This routine attempts to parse a file handle (in network byte order), 36 * using heuristics to guess what kind of format it is in. See the 37 * file "fhandle_layouts" for a detailed description of the various 38 * patterns we know about. 39 * 40 * The file handle is parsed into our internal representation of a 41 * file-system id, and an internal representation of an inode-number. 42 */ 43 44 #define FHT_UNKNOWN 0 45 #define FHT_AUSPEX 1 46 #define FHT_DECOSF 2 47 #define FHT_IRIX4 3 48 #define FHT_IRIX5 4 49 #define FHT_SUNOS3 5 50 #define FHT_SUNOS4 6 51 #define FHT_ULTRIX 7 52 #define FHT_VMSUCX 8 53 #define FHT_SUNOS5 9 54 #define FHT_AIX32 10 55 #define FHT_HPUX9 11 56 57 #ifdef ultrix 58 /* Nasty hack to keep the Ultrix C compiler from emitting bogus warnings */ 59 #define XFF(x) ((u_int32_t)(x)) 60 #else 61 #define XFF(x) (x) 62 #endif 63 64 #define make_uint32(msb,b,c,lsb)\ 65 (XFF(lsb) + (XFF(c)<<8) + (XFF(b)<<16) + (XFF(msb)<<24)) 66 67 #define make_uint24(msb,b, lsb)\ 68 (XFF(lsb) + (XFF(b)<<8) + (XFF(msb)<<16)) 69 70 #define make_uint16(msb,lsb)\ 71 (XFF(lsb) + (XFF(msb)<<8)) 72 73 #ifdef __alpha 74 /* or other 64-bit systems */ 75 #define make_uint48(msb,b,c,d,e,lsb)\ 76 ((lsb) + ((e)<<8) + ((d)<<16) + ((c)<<24) + ((b)<<32) + ((msb)<<40)) 77 #else 78 /* on 32-bit systems ignore high-order bits */ 79 #define make_uint48(msb,b,c,d,e,lsb)\ 80 ((lsb) + ((e)<<8) + ((d)<<16) + ((c)<<24)) 81 #endif 82 83 static int is_UCX(unsigned char *); 84 85 void 86 Parse_fh(fh, len, fsidp, inop, osnamep, fsnamep, ourself) 87 register caddr_t *fh; 88 int len; 89 my_fsid *fsidp; 90 ino_t *inop; 91 char **osnamep; /* if non-NULL, return OS name here */ 92 char **fsnamep; /* if non-NULL, return server fs name here (for VMS) */ 93 int ourself; /* true if file handle was generated on this host */ 94 { 95 register unsigned char *fhp = (unsigned char *)fh; 96 u_int32_t temp; 97 int fhtype = FHT_UNKNOWN; 98 99 if (ourself) { 100 /* File handle generated on this host, no need for guessing */ 101 #if defined(IRIX40) 102 fhtype = FHT_IRIX4; 103 #endif 104 #if defined(IRIX50) 105 fhtype = FHT_IRIX5; 106 #endif 107 #if defined(IRIX51) 108 fhtype = FHT_IRIX5; 109 #endif 110 #if defined(SUNOS4) 111 fhtype = FHT_SUNOS4; 112 #endif 113 #if defined(SUNOS5) 114 fhtype = FHT_SUNOS5; 115 #endif 116 #if defined(ultrix) 117 fhtype = FHT_ULTRIX; 118 #endif 119 #if defined(__osf__) 120 fhtype = FHT_DECOSF; 121 #endif 122 } 123 /* 124 * This is basically a big decision tree 125 */ 126 else if ((fhp[0] == 0) && (fhp[1] == 0)) { 127 /* bytes[0,1] == (0,0); rules out Ultrix, IRIX5, SUNOS5 */ 128 /* probably rules out HP-UX, AIX unless they allow major=0 */ 129 if ((fhp[2] == 0) && (fhp[3] == 0)) { 130 /* bytes[2,3] == (0,0); must be Auspex */ 131 /* XXX or could be Ultrix+MASSBUS "hp" disk? */ 132 fhtype = FHT_AUSPEX; 133 } 134 else { 135 /* 136 * bytes[2,3] != (0,0); rules out Auspex, could be 137 * DECOSF, SUNOS4, or IRIX4 138 */ 139 if ((fhp[4] != 0) && (fhp[5] == 0) && 140 (fhp[8] == 12) && (fhp[9] == 0)) { 141 /* seems to be DECOSF, with minor == 0 */ 142 fhtype = FHT_DECOSF; 143 } 144 else { 145 /* could be SUNOS4 or IRIX4 */ 146 /* XXX the test of fhp[5] == 8 could be wrong */ 147 if ((fhp[4] == 0) && (fhp[5] == 8) && (fhp[6] == 0) && 148 (fhp[7] == 0)) { 149 /* looks like a length, not a file system typecode */ 150 fhtype = FHT_IRIX4; 151 } 152 else { 153 /* by elimination */ 154 fhtype = FHT_SUNOS4; 155 } 156 } 157 } 158 } 159 else { 160 /* 161 * bytes[0,1] != (0,0); rules out Auspex, IRIX4, SUNOS4 162 * could be IRIX5, DECOSF, UCX, Ultrix, SUNOS5 163 * could be AIX, HP-UX 164 */ 165 if ((fhp[2] == 0) && (fhp[3] == 0)) { 166 /* 167 * bytes[2,3] == (0,0); rules out OSF, probably not UCX 168 * (unless the exported device name is just one letter!), 169 * could be Ultrix, IRIX5, AIX, or SUNOS5 170 * might be HP-UX (depends on their values for minor devs) 171 */ 172 /*XXX we probably only need to test of these two bytes */ 173 if ((fhp[21] == 0) && (fhp[23] == 0)) { 174 fhtype = FHT_ULTRIX; 175 } 176 else { 177 /* Could be SUNOS5/IRIX5, maybe AIX */ 178 /* XXX no obvious difference between SUNOS5 and IRIX5 */ 179 if (fhp[9] == 10) 180 fhtype = FHT_SUNOS5; 181 /* XXX what about AIX? */ 182 } 183 } 184 else { 185 /* 186 * bytes[2,3] != (0,0); rules out Ultrix, could be 187 * DECOSF, SUNOS5, IRIX5, AIX, HP-UX, or UCX 188 */ 189 if ((fhp[8] == 12) && (fhp[9] == 0)) { 190 fhtype = FHT_DECOSF; 191 } 192 else if ((fhp[8] == 0) && (fhp[9] == 10)) { 193 /* could be SUNOS5/IRIX5, AIX, HP-UX */ 194 if ((fhp[7] == 0) && (fhp[6] == 0) && 195 (fhp[5] == 0) && (fhp[4] == 0)) { 196 /* XXX is this always true of HP-UX? */ 197 fhtype = FHT_HPUX9; 198 } 199 else if (fhp[7] == 2) { 200 /* This would be MNT_NFS on AIX, which is impossible */ 201 fhtype = FHT_SUNOS5; /* or maybe IRIX5 */ 202 } 203 else { 204 /* 205 * XXX Could be SUNOS5/IRIX5 or AIX. I don't 206 * XXX see any way to disambiguate these, so 207 * XXX I'm going with the more likely guess. 208 * XXX Sorry, Big Blue. 209 */ 210 fhtype = FHT_SUNOS5; /* or maybe IRIX5 */ 211 } 212 } 213 else { 214 if (is_UCX(fhp)) { 215 fhtype = FHT_VMSUCX; 216 } 217 else { 218 fhtype = FHT_UNKNOWN; 219 } 220 } 221 } 222 } 223 224 /* XXX still needs to handle SUNOS3 */ 225 226 switch (fhtype) { 227 case FHT_AUSPEX: 228 fsidp->Fsid_dev.Minor = fhp[7]; 229 fsidp->Fsid_dev.Major = fhp[6]; 230 fsidp->fsid_code = 0; 231 232 temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]); 233 *inop = temp; 234 235 if (osnamep) 236 *osnamep = "Auspex"; 237 break; 238 239 case FHT_DECOSF: 240 fsidp->fsid_code = make_uint32(fhp[7], fhp[6], fhp[5], fhp[4]); 241 /* XXX could ignore 3 high-order bytes */ 242 243 temp = make_uint32(fhp[3], fhp[2], fhp[1], fhp[0]); 244 fsidp->Fsid_dev.Minor = temp & 0xFFFFF; 245 fsidp->Fsid_dev.Major = (temp>>20) & 0xFFF; 246 247 temp = make_uint32(fhp[15], fhp[14], fhp[13], fhp[12]); 248 *inop = temp; 249 if (osnamep) 250 *osnamep = "OSF"; 251 break; 252 253 case FHT_IRIX4: 254 fsidp->Fsid_dev.Minor = fhp[3]; 255 fsidp->Fsid_dev.Major = fhp[2]; 256 fsidp->fsid_code = 0; 257 258 temp = make_uint32(fhp[8], fhp[9], fhp[10], fhp[11]); 259 *inop = temp; 260 261 if (osnamep) 262 *osnamep = "IRIX4"; 263 break; 264 265 case FHT_IRIX5: 266 fsidp->Fsid_dev.Minor = make_uint16(fhp[2], fhp[3]); 267 fsidp->Fsid_dev.Major = make_uint16(fhp[0], fhp[1]); 268 fsidp->fsid_code = make_uint32(fhp[4], fhp[5], fhp[6], fhp[7]); 269 270 temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]); 271 *inop = temp; 272 273 if (osnamep) 274 *osnamep = "IRIX5"; 275 break; 276 277 case FHT_SUNOS3: 278 if (osnamep) 279 *osnamep = "SUNOS3"; 280 break; 281 282 case FHT_SUNOS4: 283 fsidp->Fsid_dev.Minor = fhp[3]; 284 fsidp->Fsid_dev.Major = fhp[2]; 285 fsidp->fsid_code = make_uint32(fhp[4], fhp[5], fhp[6], fhp[7]); 286 287 temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]); 288 *inop = temp; 289 290 if (osnamep) 291 *osnamep = "SUNOS4"; 292 break; 293 294 case FHT_SUNOS5: 295 temp = make_uint16(fhp[0], fhp[1]); 296 fsidp->Fsid_dev.Major = (temp>>2) & 0x3FFF; 297 temp = make_uint24(fhp[1], fhp[2], fhp[3]); 298 fsidp->Fsid_dev.Minor = temp & 0x3FFFF; 299 fsidp->fsid_code = make_uint32(fhp[4], fhp[5], fhp[6], fhp[7]); 300 301 temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]); 302 *inop = temp; 303 304 if (osnamep) 305 *osnamep = "SUNOS5"; 306 break; 307 308 case FHT_ULTRIX: 309 fsidp->fsid_code = 0; 310 fsidp->Fsid_dev.Minor = fhp[0]; 311 fsidp->Fsid_dev.Major = fhp[1]; 312 313 temp = make_uint32(fhp[7], fhp[6], fhp[5], fhp[4]); 314 *inop = temp; 315 if (osnamep) 316 *osnamep = "Ultrix"; 317 break; 318 319 case FHT_VMSUCX: 320 /* No numeric file system ID, so hash on the device-name */ 321 if (sizeof(*fsidp) >= 14) { 322 if (sizeof(*fsidp) > 14) 323 memset((char *)fsidp, 0, sizeof(*fsidp)); 324 /* just use the whole thing */ 325 memcpy((char *)fsidp, (char *)fh, 14); 326 } 327 else { 328 u_int32_t tempa[4]; /* at least 16 bytes, maybe more */ 329 330 memset((char *)tempa, 0, sizeof(tempa)); 331 memcpy((char *)tempa, (char *)fh, 14); /* ensure alignment */ 332 fsidp->Fsid_dev.Minor = tempa[0] + (tempa[1]<<1); 333 fsidp->Fsid_dev.Major = tempa[2] + (tempa[3]<<1); 334 fsidp->fsid_code = 0; 335 } 336 337 /* VMS file ID is: (RVN, FidHi, FidLo) */ 338 *inop = make_uint32(fhp[26], fhp[27], fhp[23], fhp[22]); 339 340 /* Caller must save (and null-terminate?) this value */ 341 if (fsnamep) 342 *fsnamep = (char *)&(fhp[1]); 343 344 if (osnamep) 345 *osnamep = "VMS"; 346 break; 347 348 case FHT_AIX32: 349 fsidp->Fsid_dev.Minor = make_uint16(fhp[2], fhp[3]); 350 fsidp->Fsid_dev.Major = make_uint16(fhp[0], fhp[1]); 351 fsidp->fsid_code = make_uint32(fhp[4], fhp[5], fhp[6], fhp[7]); 352 353 temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]); 354 *inop = temp; 355 356 if (osnamep) 357 *osnamep = "AIX32"; 358 break; 359 360 case FHT_HPUX9: 361 fsidp->Fsid_dev.Major = fhp[0]; 362 temp = make_uint24(fhp[1], fhp[2], fhp[3]); 363 fsidp->Fsid_dev.Minor = temp; 364 fsidp->fsid_code = make_uint32(fhp[4], fhp[5], fhp[6], fhp[7]); 365 366 temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]); 367 *inop = temp; 368 369 if (osnamep) 370 *osnamep = "HPUX9"; 371 break; 372 373 case FHT_UNKNOWN: 374 #ifdef DEBUG 375 { 376 /* XXX debugging */ 377 int i; 378 for (i = 0; i < 32; i++) 379 (void)fprintf(stderr, "%x.", fhp[i]); 380 (void)fprintf(stderr, "\n"); 381 } 382 #endif 383 /* XXX for now, give "bogus" values to aid debugging */ 384 fsidp->fsid_code = 0; 385 fsidp->Fsid_dev.Minor = 257; 386 fsidp->Fsid_dev.Major = 257; 387 *inop = 1; 388 389 /* display will show this string instead of (257,257) */ 390 if (fsnamep) 391 *fsnamep = "Unknown"; 392 393 if (osnamep) 394 *osnamep = "Unknown"; 395 break; 396 397 } 398 } 399 400 /* 401 * Is this a VMS UCX file handle? 402 * Check for: 403 * (1) leading code byte [XXX not yet] 404 * (2) followed by string of printing chars & spaces 405 * (3) followed by string of nulls 406 */ 407 static int 408 is_UCX(fhp) 409 unsigned char *fhp; 410 { 411 register int i; 412 int seen_null = 0; 413 414 for (i = 1; i < 14; i++) { 415 if (isprint(fhp[i])) { 416 if (seen_null) 417 return(0); 418 else 419 continue; 420 } 421 else if (fhp[i] == 0) { 422 seen_null = 1; 423 continue; 424 } 425 else 426 return(0); 427 } 428 429 return(1); 430 } 431