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