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