parsenfsfh.c 13 KB

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