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