xref: /minix3/external/bsd/tcpdump/dist/print-nfs.c (revision b636d99d91c3d54204248f643c14627405d4afd1)
1*b636d99dSDavid van Moolenbroek /*
2*b636d99dSDavid van Moolenbroek  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
3*b636d99dSDavid van Moolenbroek  *	The Regents of the University of California.  All rights reserved.
4*b636d99dSDavid van Moolenbroek  *
5*b636d99dSDavid van Moolenbroek  * Redistribution and use in source and binary forms, with or without
6*b636d99dSDavid van Moolenbroek  * modification, are permitted provided that: (1) source code distributions
7*b636d99dSDavid van Moolenbroek  * retain the above copyright notice and this paragraph in its entirety, (2)
8*b636d99dSDavid van Moolenbroek  * distributions including binary code include the above copyright notice and
9*b636d99dSDavid van Moolenbroek  * this paragraph in its entirety in the documentation or other materials
10*b636d99dSDavid van Moolenbroek  * provided with the distribution, and (3) all advertising materials mentioning
11*b636d99dSDavid van Moolenbroek  * features or use of this software display the following acknowledgement:
12*b636d99dSDavid van Moolenbroek  * ``This product includes software developed by the University of California,
13*b636d99dSDavid van Moolenbroek  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14*b636d99dSDavid van Moolenbroek  * the University nor the names of its contributors may be used to endorse
15*b636d99dSDavid van Moolenbroek  * or promote products derived from this software without specific prior
16*b636d99dSDavid van Moolenbroek  * written permission.
17*b636d99dSDavid van Moolenbroek  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18*b636d99dSDavid van Moolenbroek  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19*b636d99dSDavid van Moolenbroek  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20*b636d99dSDavid van Moolenbroek  */
21*b636d99dSDavid van Moolenbroek 
22*b636d99dSDavid van Moolenbroek #include <sys/cdefs.h>
23*b636d99dSDavid van Moolenbroek #ifndef lint
24*b636d99dSDavid van Moolenbroek __RCSID("$NetBSD: print-nfs.c,v 1.5 2014/11/20 03:05:03 christos Exp $");
25*b636d99dSDavid van Moolenbroek #endif
26*b636d99dSDavid van Moolenbroek 
27*b636d99dSDavid van Moolenbroek #define NETDISSECT_REWORKED
28*b636d99dSDavid van Moolenbroek #ifdef HAVE_CONFIG_H
29*b636d99dSDavid van Moolenbroek #include "config.h"
30*b636d99dSDavid van Moolenbroek #endif
31*b636d99dSDavid van Moolenbroek 
32*b636d99dSDavid van Moolenbroek #include <tcpdump-stdinc.h>
33*b636d99dSDavid van Moolenbroek 
34*b636d99dSDavid van Moolenbroek #include <stdio.h>
35*b636d99dSDavid van Moolenbroek #include <string.h>
36*b636d99dSDavid van Moolenbroek 
37*b636d99dSDavid van Moolenbroek #include "interface.h"
38*b636d99dSDavid van Moolenbroek #include "addrtoname.h"
39*b636d99dSDavid van Moolenbroek #include "extract.h"
40*b636d99dSDavid van Moolenbroek 
41*b636d99dSDavid van Moolenbroek #include "nfs.h"
42*b636d99dSDavid van Moolenbroek #include "nfsfh.h"
43*b636d99dSDavid van Moolenbroek 
44*b636d99dSDavid van Moolenbroek #include "ip.h"
45*b636d99dSDavid van Moolenbroek #ifdef INET6
46*b636d99dSDavid van Moolenbroek #include "ip6.h"
47*b636d99dSDavid van Moolenbroek #endif
48*b636d99dSDavid van Moolenbroek #include "rpc_auth.h"
49*b636d99dSDavid van Moolenbroek #include "rpc_msg.h"
50*b636d99dSDavid van Moolenbroek 
51*b636d99dSDavid van Moolenbroek static const char tstr[] = " [|nfs]";
52*b636d99dSDavid van Moolenbroek 
53*b636d99dSDavid van Moolenbroek static void nfs_printfh(netdissect_options *, const uint32_t *, const u_int);
54*b636d99dSDavid van Moolenbroek static int xid_map_enter(netdissect_options *, const struct sunrpc_msg *, const u_char *);
55*b636d99dSDavid van Moolenbroek static int xid_map_find(const struct sunrpc_msg *, const u_char *,
56*b636d99dSDavid van Moolenbroek 			    uint32_t *, uint32_t *);
57*b636d99dSDavid van Moolenbroek static void interp_reply(netdissect_options *, const struct sunrpc_msg *, uint32_t, uint32_t, int);
58*b636d99dSDavid van Moolenbroek static const uint32_t *parse_post_op_attr(netdissect_options *, const uint32_t *, int);
59*b636d99dSDavid van Moolenbroek 
60*b636d99dSDavid van Moolenbroek /*
61*b636d99dSDavid van Moolenbroek  * Mapping of old NFS Version 2 RPC numbers to generic numbers.
62*b636d99dSDavid van Moolenbroek  */
63*b636d99dSDavid van Moolenbroek uint32_t nfsv3_procid[NFS_NPROCS] = {
64*b636d99dSDavid van Moolenbroek 	NFSPROC_NULL,
65*b636d99dSDavid van Moolenbroek 	NFSPROC_GETATTR,
66*b636d99dSDavid van Moolenbroek 	NFSPROC_SETATTR,
67*b636d99dSDavid van Moolenbroek 	NFSPROC_NOOP,
68*b636d99dSDavid van Moolenbroek 	NFSPROC_LOOKUP,
69*b636d99dSDavid van Moolenbroek 	NFSPROC_READLINK,
70*b636d99dSDavid van Moolenbroek 	NFSPROC_READ,
71*b636d99dSDavid van Moolenbroek 	NFSPROC_NOOP,
72*b636d99dSDavid van Moolenbroek 	NFSPROC_WRITE,
73*b636d99dSDavid van Moolenbroek 	NFSPROC_CREATE,
74*b636d99dSDavid van Moolenbroek 	NFSPROC_REMOVE,
75*b636d99dSDavid van Moolenbroek 	NFSPROC_RENAME,
76*b636d99dSDavid van Moolenbroek 	NFSPROC_LINK,
77*b636d99dSDavid van Moolenbroek 	NFSPROC_SYMLINK,
78*b636d99dSDavid van Moolenbroek 	NFSPROC_MKDIR,
79*b636d99dSDavid van Moolenbroek 	NFSPROC_RMDIR,
80*b636d99dSDavid van Moolenbroek 	NFSPROC_READDIR,
81*b636d99dSDavid van Moolenbroek 	NFSPROC_FSSTAT,
82*b636d99dSDavid van Moolenbroek 	NFSPROC_NOOP,
83*b636d99dSDavid van Moolenbroek 	NFSPROC_NOOP,
84*b636d99dSDavid van Moolenbroek 	NFSPROC_NOOP,
85*b636d99dSDavid van Moolenbroek 	NFSPROC_NOOP,
86*b636d99dSDavid van Moolenbroek 	NFSPROC_NOOP,
87*b636d99dSDavid van Moolenbroek 	NFSPROC_NOOP,
88*b636d99dSDavid van Moolenbroek 	NFSPROC_NOOP,
89*b636d99dSDavid van Moolenbroek 	NFSPROC_NOOP
90*b636d99dSDavid van Moolenbroek };
91*b636d99dSDavid van Moolenbroek 
92*b636d99dSDavid van Moolenbroek static const struct tok nfsproc_str[] = {
93*b636d99dSDavid van Moolenbroek 	{ NFSPROC_NOOP,        "nop"         },
94*b636d99dSDavid van Moolenbroek 	{ NFSPROC_NULL,        "null"        },
95*b636d99dSDavid van Moolenbroek 	{ NFSPROC_GETATTR,     "getattr"     },
96*b636d99dSDavid van Moolenbroek 	{ NFSPROC_SETATTR,     "setattr"     },
97*b636d99dSDavid van Moolenbroek 	{ NFSPROC_LOOKUP,      "lookup"      },
98*b636d99dSDavid van Moolenbroek 	{ NFSPROC_ACCESS,      "access"      },
99*b636d99dSDavid van Moolenbroek 	{ NFSPROC_READLINK,    "readlink"    },
100*b636d99dSDavid van Moolenbroek 	{ NFSPROC_READ,        "read"        },
101*b636d99dSDavid van Moolenbroek 	{ NFSPROC_WRITE,       "write"       },
102*b636d99dSDavid van Moolenbroek 	{ NFSPROC_CREATE,      "create"      },
103*b636d99dSDavid van Moolenbroek 	{ NFSPROC_MKDIR,       "mkdir"       },
104*b636d99dSDavid van Moolenbroek 	{ NFSPROC_SYMLINK,     "symlink"     },
105*b636d99dSDavid van Moolenbroek 	{ NFSPROC_MKNOD,       "mknod"       },
106*b636d99dSDavid van Moolenbroek 	{ NFSPROC_REMOVE,      "remove"      },
107*b636d99dSDavid van Moolenbroek 	{ NFSPROC_RMDIR,       "rmdir"       },
108*b636d99dSDavid van Moolenbroek 	{ NFSPROC_RENAME,      "rename"      },
109*b636d99dSDavid van Moolenbroek 	{ NFSPROC_LINK,        "link"        },
110*b636d99dSDavid van Moolenbroek 	{ NFSPROC_READDIR,     "readdir"     },
111*b636d99dSDavid van Moolenbroek 	{ NFSPROC_READDIRPLUS, "readdirplus" },
112*b636d99dSDavid van Moolenbroek 	{ NFSPROC_FSSTAT,      "fsstat"      },
113*b636d99dSDavid van Moolenbroek 	{ NFSPROC_FSINFO,      "fsinfo"      },
114*b636d99dSDavid van Moolenbroek 	{ NFSPROC_PATHCONF,    "pathconf"    },
115*b636d99dSDavid van Moolenbroek 	{ NFSPROC_COMMIT,      "commit"      },
116*b636d99dSDavid van Moolenbroek 	{ 0, NULL }
117*b636d99dSDavid van Moolenbroek };
118*b636d99dSDavid van Moolenbroek 
119*b636d99dSDavid van Moolenbroek /*
120*b636d99dSDavid van Moolenbroek  * NFS V2 and V3 status values.
121*b636d99dSDavid van Moolenbroek  *
122*b636d99dSDavid van Moolenbroek  * Some of these come from the RFCs for NFS V2 and V3, with the message
123*b636d99dSDavid van Moolenbroek  * strings taken from the FreeBSD C library "errlst.c".
124*b636d99dSDavid van Moolenbroek  *
125*b636d99dSDavid van Moolenbroek  * Others are errors that are not in the RFC but that I suspect some
126*b636d99dSDavid van Moolenbroek  * NFS servers could return; the values are FreeBSD errno values, as
127*b636d99dSDavid van Moolenbroek  * the first NFS server was the SunOS 2.0 one, and until 5.0 SunOS
128*b636d99dSDavid van Moolenbroek  * was primarily BSD-derived.
129*b636d99dSDavid van Moolenbroek  */
130*b636d99dSDavid van Moolenbroek static const struct tok status2str[] = {
131*b636d99dSDavid van Moolenbroek 	{ 1,     "Operation not permitted" },	/* EPERM */
132*b636d99dSDavid van Moolenbroek 	{ 2,     "No such file or directory" },	/* ENOENT */
133*b636d99dSDavid van Moolenbroek 	{ 5,     "Input/output error" },	/* EIO */
134*b636d99dSDavid van Moolenbroek 	{ 6,     "Device not configured" },	/* ENXIO */
135*b636d99dSDavid van Moolenbroek 	{ 11,    "Resource deadlock avoided" },	/* EDEADLK */
136*b636d99dSDavid van Moolenbroek 	{ 12,    "Cannot allocate memory" },	/* ENOMEM */
137*b636d99dSDavid van Moolenbroek 	{ 13,    "Permission denied" },		/* EACCES */
138*b636d99dSDavid van Moolenbroek 	{ 17,    "File exists" },		/* EEXIST */
139*b636d99dSDavid van Moolenbroek 	{ 18,    "Cross-device link" },		/* EXDEV */
140*b636d99dSDavid van Moolenbroek 	{ 19,    "Operation not supported by device" }, /* ENODEV */
141*b636d99dSDavid van Moolenbroek 	{ 20,    "Not a directory" },		/* ENOTDIR */
142*b636d99dSDavid van Moolenbroek 	{ 21,    "Is a directory" },		/* EISDIR */
143*b636d99dSDavid van Moolenbroek 	{ 22,    "Invalid argument" },		/* EINVAL */
144*b636d99dSDavid van Moolenbroek 	{ 26,    "Text file busy" },		/* ETXTBSY */
145*b636d99dSDavid van Moolenbroek 	{ 27,    "File too large" },		/* EFBIG */
146*b636d99dSDavid van Moolenbroek 	{ 28,    "No space left on device" },	/* ENOSPC */
147*b636d99dSDavid van Moolenbroek 	{ 30,    "Read-only file system" },	/* EROFS */
148*b636d99dSDavid van Moolenbroek 	{ 31,    "Too many links" },		/* EMLINK */
149*b636d99dSDavid van Moolenbroek 	{ 45,    "Operation not supported" },	/* EOPNOTSUPP */
150*b636d99dSDavid van Moolenbroek 	{ 62,    "Too many levels of symbolic links" }, /* ELOOP */
151*b636d99dSDavid van Moolenbroek 	{ 63,    "File name too long" },	/* ENAMETOOLONG */
152*b636d99dSDavid van Moolenbroek 	{ 66,    "Directory not empty" },	/* ENOTEMPTY */
153*b636d99dSDavid van Moolenbroek 	{ 69,    "Disc quota exceeded" },	/* EDQUOT */
154*b636d99dSDavid van Moolenbroek 	{ 70,    "Stale NFS file handle" },	/* ESTALE */
155*b636d99dSDavid van Moolenbroek 	{ 71,    "Too many levels of remote in path" }, /* EREMOTE */
156*b636d99dSDavid van Moolenbroek 	{ 99,    "Write cache flushed to disk" }, /* NFSERR_WFLUSH (not used) */
157*b636d99dSDavid van Moolenbroek 	{ 10001, "Illegal NFS file handle" },	/* NFS3ERR_BADHANDLE */
158*b636d99dSDavid van Moolenbroek 	{ 10002, "Update synchronization mismatch" }, /* NFS3ERR_NOT_SYNC */
159*b636d99dSDavid van Moolenbroek 	{ 10003, "READDIR/READDIRPLUS cookie is stale" }, /* NFS3ERR_BAD_COOKIE */
160*b636d99dSDavid van Moolenbroek 	{ 10004, "Operation not supported" },	/* NFS3ERR_NOTSUPP */
161*b636d99dSDavid van Moolenbroek 	{ 10005, "Buffer or request is too small" }, /* NFS3ERR_TOOSMALL */
162*b636d99dSDavid van Moolenbroek 	{ 10006, "Unspecified error on server" }, /* NFS3ERR_SERVERFAULT */
163*b636d99dSDavid van Moolenbroek 	{ 10007, "Object of that type not supported" }, /* NFS3ERR_BADTYPE */
164*b636d99dSDavid van Moolenbroek 	{ 10008, "Request couldn't be completed in time" }, /* NFS3ERR_JUKEBOX */
165*b636d99dSDavid van Moolenbroek 	{ 0,     NULL }
166*b636d99dSDavid van Moolenbroek };
167*b636d99dSDavid van Moolenbroek 
168*b636d99dSDavid van Moolenbroek static const struct tok nfsv3_writemodes[] = {
169*b636d99dSDavid van Moolenbroek 	{ 0,		"unstable" },
170*b636d99dSDavid van Moolenbroek 	{ 1,		"datasync" },
171*b636d99dSDavid van Moolenbroek 	{ 2,		"filesync" },
172*b636d99dSDavid van Moolenbroek 	{ 0,		NULL }
173*b636d99dSDavid van Moolenbroek };
174*b636d99dSDavid van Moolenbroek 
175*b636d99dSDavid van Moolenbroek static const struct tok type2str[] = {
176*b636d99dSDavid van Moolenbroek 	{ NFNON,	"NON" },
177*b636d99dSDavid van Moolenbroek 	{ NFREG,	"REG" },
178*b636d99dSDavid van Moolenbroek 	{ NFDIR,	"DIR" },
179*b636d99dSDavid van Moolenbroek 	{ NFBLK,	"BLK" },
180*b636d99dSDavid van Moolenbroek 	{ NFCHR,	"CHR" },
181*b636d99dSDavid van Moolenbroek 	{ NFLNK,	"LNK" },
182*b636d99dSDavid van Moolenbroek 	{ NFFIFO,	"FIFO" },
183*b636d99dSDavid van Moolenbroek 	{ 0,		NULL }
184*b636d99dSDavid van Moolenbroek };
185*b636d99dSDavid van Moolenbroek 
186*b636d99dSDavid van Moolenbroek static const struct tok sunrpc_auth_str[] = {
187*b636d99dSDavid van Moolenbroek 	{ SUNRPC_AUTH_OK,           "OK"                                                     },
188*b636d99dSDavid van Moolenbroek 	{ SUNRPC_AUTH_BADCRED,      "Bogus Credentials (seal broken)"                        },
189*b636d99dSDavid van Moolenbroek 	{ SUNRPC_AUTH_REJECTEDCRED, "Rejected Credentials (client should begin new session)" },
190*b636d99dSDavid van Moolenbroek 	{ SUNRPC_AUTH_BADVERF,      "Bogus Verifier (seal broken)"                           },
191*b636d99dSDavid van Moolenbroek 	{ SUNRPC_AUTH_REJECTEDVERF, "Verifier expired or was replayed"                       },
192*b636d99dSDavid van Moolenbroek 	{ SUNRPC_AUTH_TOOWEAK,      "Credentials are too weak"                               },
193*b636d99dSDavid van Moolenbroek 	{ SUNRPC_AUTH_INVALIDRESP,  "Bogus response verifier"                                },
194*b636d99dSDavid van Moolenbroek 	{ SUNRPC_AUTH_FAILED,       "Unknown failure"                                        },
195*b636d99dSDavid van Moolenbroek 	{ 0, NULL }
196*b636d99dSDavid van Moolenbroek };
197*b636d99dSDavid van Moolenbroek 
198*b636d99dSDavid van Moolenbroek static const struct tok sunrpc_str[] = {
199*b636d99dSDavid van Moolenbroek 	{ SUNRPC_PROG_UNAVAIL,  "PROG_UNAVAIL"  },
200*b636d99dSDavid van Moolenbroek 	{ SUNRPC_PROG_MISMATCH, "PROG_MISMATCH" },
201*b636d99dSDavid van Moolenbroek 	{ SUNRPC_PROC_UNAVAIL,  "PROC_UNAVAIL"  },
202*b636d99dSDavid van Moolenbroek 	{ SUNRPC_GARBAGE_ARGS,  "GARBAGE_ARGS"  },
203*b636d99dSDavid van Moolenbroek 	{ SUNRPC_SYSTEM_ERR,    "SYSTEM_ERR"    },
204*b636d99dSDavid van Moolenbroek 	{ 0, NULL }
205*b636d99dSDavid van Moolenbroek };
206*b636d99dSDavid van Moolenbroek 
207*b636d99dSDavid van Moolenbroek static void
print_nfsaddr(netdissect_options * ndo,const u_char * bp,const char * s,const char * d)208*b636d99dSDavid van Moolenbroek print_nfsaddr(netdissect_options *ndo,
209*b636d99dSDavid van Moolenbroek               const u_char *bp, const char *s, const char *d)
210*b636d99dSDavid van Moolenbroek {
211*b636d99dSDavid van Moolenbroek 	struct ip *ip;
212*b636d99dSDavid van Moolenbroek #ifdef INET6
213*b636d99dSDavid van Moolenbroek 	struct ip6_hdr *ip6;
214*b636d99dSDavid van Moolenbroek 	char srcaddr[INET6_ADDRSTRLEN], dstaddr[INET6_ADDRSTRLEN];
215*b636d99dSDavid van Moolenbroek #else
216*b636d99dSDavid van Moolenbroek #ifndef INET_ADDRSTRLEN
217*b636d99dSDavid van Moolenbroek #define INET_ADDRSTRLEN	16
218*b636d99dSDavid van Moolenbroek #endif
219*b636d99dSDavid van Moolenbroek 	char srcaddr[INET_ADDRSTRLEN], dstaddr[INET_ADDRSTRLEN];
220*b636d99dSDavid van Moolenbroek #endif
221*b636d99dSDavid van Moolenbroek 
222*b636d99dSDavid van Moolenbroek 	srcaddr[0] = dstaddr[0] = '\0';
223*b636d99dSDavid van Moolenbroek 	switch (IP_V((struct ip *)bp)) {
224*b636d99dSDavid van Moolenbroek 	case 4:
225*b636d99dSDavid van Moolenbroek 		ip = (struct ip *)bp;
226*b636d99dSDavid van Moolenbroek 		strlcpy(srcaddr, ipaddr_string(ndo, &ip->ip_src), sizeof(srcaddr));
227*b636d99dSDavid van Moolenbroek 		strlcpy(dstaddr, ipaddr_string(ndo, &ip->ip_dst), sizeof(dstaddr));
228*b636d99dSDavid van Moolenbroek 		break;
229*b636d99dSDavid van Moolenbroek #ifdef INET6
230*b636d99dSDavid van Moolenbroek 	case 6:
231*b636d99dSDavid van Moolenbroek 		ip6 = (struct ip6_hdr *)bp;
232*b636d99dSDavid van Moolenbroek 		strlcpy(srcaddr, ip6addr_string(ndo, &ip6->ip6_src),
233*b636d99dSDavid van Moolenbroek 		    sizeof(srcaddr));
234*b636d99dSDavid van Moolenbroek 		strlcpy(dstaddr, ip6addr_string(ndo, &ip6->ip6_dst),
235*b636d99dSDavid van Moolenbroek 		    sizeof(dstaddr));
236*b636d99dSDavid van Moolenbroek 		break;
237*b636d99dSDavid van Moolenbroek #endif
238*b636d99dSDavid van Moolenbroek 	default:
239*b636d99dSDavid van Moolenbroek 		strlcpy(srcaddr, "?", sizeof(srcaddr));
240*b636d99dSDavid van Moolenbroek 		strlcpy(dstaddr, "?", sizeof(dstaddr));
241*b636d99dSDavid van Moolenbroek 		break;
242*b636d99dSDavid van Moolenbroek 	}
243*b636d99dSDavid van Moolenbroek 
244*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, "%s.%s > %s.%s: ", srcaddr, s, dstaddr, d));
245*b636d99dSDavid van Moolenbroek }
246*b636d99dSDavid van Moolenbroek 
247*b636d99dSDavid van Moolenbroek static const uint32_t *
parse_sattr3(netdissect_options * ndo,const uint32_t * dp,struct nfsv3_sattr * sa3)248*b636d99dSDavid van Moolenbroek parse_sattr3(netdissect_options *ndo,
249*b636d99dSDavid van Moolenbroek              const uint32_t *dp, struct nfsv3_sattr *sa3)
250*b636d99dSDavid van Moolenbroek {
251*b636d99dSDavid van Moolenbroek 	ND_TCHECK(dp[0]);
252*b636d99dSDavid van Moolenbroek 	sa3->sa_modeset = EXTRACT_32BITS(dp);
253*b636d99dSDavid van Moolenbroek 	dp++;
254*b636d99dSDavid van Moolenbroek 	if (sa3->sa_modeset) {
255*b636d99dSDavid van Moolenbroek 		ND_TCHECK(dp[0]);
256*b636d99dSDavid van Moolenbroek 		sa3->sa_mode = EXTRACT_32BITS(dp);
257*b636d99dSDavid van Moolenbroek 		dp++;
258*b636d99dSDavid van Moolenbroek 	}
259*b636d99dSDavid van Moolenbroek 
260*b636d99dSDavid van Moolenbroek 	ND_TCHECK(dp[0]);
261*b636d99dSDavid van Moolenbroek 	sa3->sa_uidset = EXTRACT_32BITS(dp);
262*b636d99dSDavid van Moolenbroek 	dp++;
263*b636d99dSDavid van Moolenbroek 	if (sa3->sa_uidset) {
264*b636d99dSDavid van Moolenbroek 		ND_TCHECK(dp[0]);
265*b636d99dSDavid van Moolenbroek 		sa3->sa_uid = EXTRACT_32BITS(dp);
266*b636d99dSDavid van Moolenbroek 		dp++;
267*b636d99dSDavid van Moolenbroek 	}
268*b636d99dSDavid van Moolenbroek 
269*b636d99dSDavid van Moolenbroek 	ND_TCHECK(dp[0]);
270*b636d99dSDavid van Moolenbroek 	sa3->sa_gidset = EXTRACT_32BITS(dp);
271*b636d99dSDavid van Moolenbroek 	dp++;
272*b636d99dSDavid van Moolenbroek 	if (sa3->sa_gidset) {
273*b636d99dSDavid van Moolenbroek 		ND_TCHECK(dp[0]);
274*b636d99dSDavid van Moolenbroek 		sa3->sa_gid = EXTRACT_32BITS(dp);
275*b636d99dSDavid van Moolenbroek 		dp++;
276*b636d99dSDavid van Moolenbroek 	}
277*b636d99dSDavid van Moolenbroek 
278*b636d99dSDavid van Moolenbroek 	ND_TCHECK(dp[0]);
279*b636d99dSDavid van Moolenbroek 	sa3->sa_sizeset = EXTRACT_32BITS(dp);
280*b636d99dSDavid van Moolenbroek 	dp++;
281*b636d99dSDavid van Moolenbroek 	if (sa3->sa_sizeset) {
282*b636d99dSDavid van Moolenbroek 		ND_TCHECK(dp[0]);
283*b636d99dSDavid van Moolenbroek 		sa3->sa_size = EXTRACT_32BITS(dp);
284*b636d99dSDavid van Moolenbroek 		dp++;
285*b636d99dSDavid van Moolenbroek 	}
286*b636d99dSDavid van Moolenbroek 
287*b636d99dSDavid van Moolenbroek 	ND_TCHECK(dp[0]);
288*b636d99dSDavid van Moolenbroek 	sa3->sa_atimetype = EXTRACT_32BITS(dp);
289*b636d99dSDavid van Moolenbroek 	dp++;
290*b636d99dSDavid van Moolenbroek 	if (sa3->sa_atimetype == NFSV3SATTRTIME_TOCLIENT) {
291*b636d99dSDavid van Moolenbroek 		ND_TCHECK(dp[1]);
292*b636d99dSDavid van Moolenbroek 		sa3->sa_atime.nfsv3_sec = EXTRACT_32BITS(dp);
293*b636d99dSDavid van Moolenbroek 		dp++;
294*b636d99dSDavid van Moolenbroek 		sa3->sa_atime.nfsv3_nsec = EXTRACT_32BITS(dp);
295*b636d99dSDavid van Moolenbroek 		dp++;
296*b636d99dSDavid van Moolenbroek 	}
297*b636d99dSDavid van Moolenbroek 
298*b636d99dSDavid van Moolenbroek 	ND_TCHECK(dp[0]);
299*b636d99dSDavid van Moolenbroek 	sa3->sa_mtimetype = EXTRACT_32BITS(dp);
300*b636d99dSDavid van Moolenbroek 	dp++;
301*b636d99dSDavid van Moolenbroek 	if (sa3->sa_mtimetype == NFSV3SATTRTIME_TOCLIENT) {
302*b636d99dSDavid van Moolenbroek 		ND_TCHECK(dp[1]);
303*b636d99dSDavid van Moolenbroek 		sa3->sa_mtime.nfsv3_sec = EXTRACT_32BITS(dp);
304*b636d99dSDavid van Moolenbroek 		dp++;
305*b636d99dSDavid van Moolenbroek 		sa3->sa_mtime.nfsv3_nsec = EXTRACT_32BITS(dp);
306*b636d99dSDavid van Moolenbroek 		dp++;
307*b636d99dSDavid van Moolenbroek 	}
308*b636d99dSDavid van Moolenbroek 
309*b636d99dSDavid van Moolenbroek 	return dp;
310*b636d99dSDavid van Moolenbroek trunc:
311*b636d99dSDavid van Moolenbroek 	return NULL;
312*b636d99dSDavid van Moolenbroek }
313*b636d99dSDavid van Moolenbroek 
314*b636d99dSDavid van Moolenbroek static int nfserr;		/* true if we error rather than trunc */
315*b636d99dSDavid van Moolenbroek 
316*b636d99dSDavid van Moolenbroek static void
print_sattr3(netdissect_options * ndo,const struct nfsv3_sattr * sa3,int verbose)317*b636d99dSDavid van Moolenbroek print_sattr3(netdissect_options *ndo,
318*b636d99dSDavid van Moolenbroek              const struct nfsv3_sattr *sa3, int verbose)
319*b636d99dSDavid van Moolenbroek {
320*b636d99dSDavid van Moolenbroek 	if (sa3->sa_modeset)
321*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " mode %o", sa3->sa_mode));
322*b636d99dSDavid van Moolenbroek 	if (sa3->sa_uidset)
323*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " uid %u", sa3->sa_uid));
324*b636d99dSDavid van Moolenbroek 	if (sa3->sa_gidset)
325*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " gid %u", sa3->sa_gid));
326*b636d99dSDavid van Moolenbroek 	if (verbose > 1) {
327*b636d99dSDavid van Moolenbroek 		if (sa3->sa_atimetype == NFSV3SATTRTIME_TOCLIENT)
328*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, " atime %u.%06u", sa3->sa_atime.nfsv3_sec,
329*b636d99dSDavid van Moolenbroek 			       sa3->sa_atime.nfsv3_nsec));
330*b636d99dSDavid van Moolenbroek 		if (sa3->sa_mtimetype == NFSV3SATTRTIME_TOCLIENT)
331*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, " mtime %u.%06u", sa3->sa_mtime.nfsv3_sec,
332*b636d99dSDavid van Moolenbroek 			       sa3->sa_mtime.nfsv3_nsec));
333*b636d99dSDavid van Moolenbroek 	}
334*b636d99dSDavid van Moolenbroek }
335*b636d99dSDavid van Moolenbroek 
336*b636d99dSDavid van Moolenbroek void
nfsreply_print(netdissect_options * ndo,register const u_char * bp,u_int length,register const u_char * bp2)337*b636d99dSDavid van Moolenbroek nfsreply_print(netdissect_options *ndo,
338*b636d99dSDavid van Moolenbroek                register const u_char *bp, u_int length,
339*b636d99dSDavid van Moolenbroek                register const u_char *bp2)
340*b636d99dSDavid van Moolenbroek {
341*b636d99dSDavid van Moolenbroek 	register const struct sunrpc_msg *rp;
342*b636d99dSDavid van Moolenbroek 	char srcid[20], dstid[20];	/*fits 32bit*/
343*b636d99dSDavid van Moolenbroek 
344*b636d99dSDavid van Moolenbroek 	nfserr = 0;		/* assume no error */
345*b636d99dSDavid van Moolenbroek 	rp = (const struct sunrpc_msg *)bp;
346*b636d99dSDavid van Moolenbroek 
347*b636d99dSDavid van Moolenbroek 	ND_TCHECK(rp->rm_xid);
348*b636d99dSDavid van Moolenbroek 	if (!ndo->ndo_nflag) {
349*b636d99dSDavid van Moolenbroek 		strlcpy(srcid, "nfs", sizeof(srcid));
350*b636d99dSDavid van Moolenbroek 		snprintf(dstid, sizeof(dstid), "%u",
351*b636d99dSDavid van Moolenbroek 		    EXTRACT_32BITS(&rp->rm_xid));
352*b636d99dSDavid van Moolenbroek 	} else {
353*b636d99dSDavid van Moolenbroek 		snprintf(srcid, sizeof(srcid), "%u", NFS_PORT);
354*b636d99dSDavid van Moolenbroek 		snprintf(dstid, sizeof(dstid), "%u",
355*b636d99dSDavid van Moolenbroek 		    EXTRACT_32BITS(&rp->rm_xid));
356*b636d99dSDavid van Moolenbroek 	}
357*b636d99dSDavid van Moolenbroek 	print_nfsaddr(ndo, bp2, srcid, dstid);
358*b636d99dSDavid van Moolenbroek 
359*b636d99dSDavid van Moolenbroek 	nfsreply_print_noaddr(ndo, bp, length, bp2);
360*b636d99dSDavid van Moolenbroek 	return;
361*b636d99dSDavid van Moolenbroek 
362*b636d99dSDavid van Moolenbroek trunc:
363*b636d99dSDavid van Moolenbroek 	if (!nfserr)
364*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "%s", tstr));
365*b636d99dSDavid van Moolenbroek }
366*b636d99dSDavid van Moolenbroek 
367*b636d99dSDavid van Moolenbroek void
nfsreply_print_noaddr(netdissect_options * ndo,register const u_char * bp,u_int length,register const u_char * bp2)368*b636d99dSDavid van Moolenbroek nfsreply_print_noaddr(netdissect_options *ndo,
369*b636d99dSDavid van Moolenbroek                       register const u_char *bp, u_int length,
370*b636d99dSDavid van Moolenbroek                       register const u_char *bp2)
371*b636d99dSDavid van Moolenbroek {
372*b636d99dSDavid van Moolenbroek 	register const struct sunrpc_msg *rp;
373*b636d99dSDavid van Moolenbroek 	uint32_t proc, vers, reply_stat;
374*b636d99dSDavid van Moolenbroek 	enum sunrpc_reject_stat rstat;
375*b636d99dSDavid van Moolenbroek 	uint32_t rlow;
376*b636d99dSDavid van Moolenbroek 	uint32_t rhigh;
377*b636d99dSDavid van Moolenbroek 	enum sunrpc_auth_stat rwhy;
378*b636d99dSDavid van Moolenbroek 
379*b636d99dSDavid van Moolenbroek 	nfserr = 0;		/* assume no error */
380*b636d99dSDavid van Moolenbroek 	rp = (const struct sunrpc_msg *)bp;
381*b636d99dSDavid van Moolenbroek 
382*b636d99dSDavid van Moolenbroek 	ND_TCHECK(rp->rm_reply.rp_stat);
383*b636d99dSDavid van Moolenbroek 	reply_stat = EXTRACT_32BITS(&rp->rm_reply.rp_stat);
384*b636d99dSDavid van Moolenbroek 	switch (reply_stat) {
385*b636d99dSDavid van Moolenbroek 
386*b636d99dSDavid van Moolenbroek 	case SUNRPC_MSG_ACCEPTED:
387*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "reply ok %u", length));
388*b636d99dSDavid van Moolenbroek 		if (xid_map_find(rp, bp2, &proc, &vers) >= 0)
389*b636d99dSDavid van Moolenbroek 			interp_reply(ndo, rp, proc, vers, length);
390*b636d99dSDavid van Moolenbroek 		break;
391*b636d99dSDavid van Moolenbroek 
392*b636d99dSDavid van Moolenbroek 	case SUNRPC_MSG_DENIED:
393*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "reply ERR %u: ", length));
394*b636d99dSDavid van Moolenbroek 		ND_TCHECK(rp->rm_reply.rp_reject.rj_stat);
395*b636d99dSDavid van Moolenbroek 		rstat = EXTRACT_32BITS(&rp->rm_reply.rp_reject.rj_stat);
396*b636d99dSDavid van Moolenbroek 		switch (rstat) {
397*b636d99dSDavid van Moolenbroek 
398*b636d99dSDavid van Moolenbroek 		case SUNRPC_RPC_MISMATCH:
399*b636d99dSDavid van Moolenbroek 			ND_TCHECK(rp->rm_reply.rp_reject.rj_vers.high);
400*b636d99dSDavid van Moolenbroek 			rlow = EXTRACT_32BITS(&rp->rm_reply.rp_reject.rj_vers.low);
401*b636d99dSDavid van Moolenbroek 			rhigh = EXTRACT_32BITS(&rp->rm_reply.rp_reject.rj_vers.high);
402*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, "RPC Version mismatch (%u-%u)", rlow, rhigh));
403*b636d99dSDavid van Moolenbroek 			break;
404*b636d99dSDavid van Moolenbroek 
405*b636d99dSDavid van Moolenbroek 		case SUNRPC_AUTH_ERROR:
406*b636d99dSDavid van Moolenbroek 			ND_TCHECK(rp->rm_reply.rp_reject.rj_why);
407*b636d99dSDavid van Moolenbroek 			rwhy = EXTRACT_32BITS(&rp->rm_reply.rp_reject.rj_why);
408*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, "Auth %s", tok2str(sunrpc_auth_str, "Invalid failure code %u", rwhy)));
409*b636d99dSDavid van Moolenbroek 			break;
410*b636d99dSDavid van Moolenbroek 
411*b636d99dSDavid van Moolenbroek 		default:
412*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, "Unknown reason for rejecting rpc message %u", (unsigned int)rstat));
413*b636d99dSDavid van Moolenbroek 			break;
414*b636d99dSDavid van Moolenbroek 		}
415*b636d99dSDavid van Moolenbroek 		break;
416*b636d99dSDavid van Moolenbroek 
417*b636d99dSDavid van Moolenbroek 	default:
418*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "reply Unknown rpc response code=%u %u", reply_stat, length));
419*b636d99dSDavid van Moolenbroek 		break;
420*b636d99dSDavid van Moolenbroek 	}
421*b636d99dSDavid van Moolenbroek 	return;
422*b636d99dSDavid van Moolenbroek 
423*b636d99dSDavid van Moolenbroek trunc:
424*b636d99dSDavid van Moolenbroek 	if (!nfserr)
425*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "%s", tstr));
426*b636d99dSDavid van Moolenbroek }
427*b636d99dSDavid van Moolenbroek 
428*b636d99dSDavid van Moolenbroek /*
429*b636d99dSDavid van Moolenbroek  * Return a pointer to the first file handle in the packet.
430*b636d99dSDavid van Moolenbroek  * If the packet was truncated, return 0.
431*b636d99dSDavid van Moolenbroek  */
432*b636d99dSDavid van Moolenbroek static const uint32_t *
parsereq(netdissect_options * ndo,register const struct sunrpc_msg * rp,register u_int length)433*b636d99dSDavid van Moolenbroek parsereq(netdissect_options *ndo,
434*b636d99dSDavid van Moolenbroek          register const struct sunrpc_msg *rp, register u_int length)
435*b636d99dSDavid van Moolenbroek {
436*b636d99dSDavid van Moolenbroek 	register const uint32_t *dp;
437*b636d99dSDavid van Moolenbroek 	register u_int len;
438*b636d99dSDavid van Moolenbroek 
439*b636d99dSDavid van Moolenbroek 	/*
440*b636d99dSDavid van Moolenbroek 	 * find the start of the req data (if we captured it)
441*b636d99dSDavid van Moolenbroek 	 */
442*b636d99dSDavid van Moolenbroek 	dp = (uint32_t *)&rp->rm_call.cb_cred;
443*b636d99dSDavid van Moolenbroek 	ND_TCHECK(dp[1]);
444*b636d99dSDavid van Moolenbroek 	len = EXTRACT_32BITS(&dp[1]);
445*b636d99dSDavid van Moolenbroek 	if (len < length) {
446*b636d99dSDavid van Moolenbroek 		dp += (len + (2 * sizeof(*dp) + 3)) / sizeof(*dp);
447*b636d99dSDavid van Moolenbroek 		ND_TCHECK(dp[1]);
448*b636d99dSDavid van Moolenbroek 		len = EXTRACT_32BITS(&dp[1]);
449*b636d99dSDavid van Moolenbroek 		if (len < length) {
450*b636d99dSDavid van Moolenbroek 			dp += (len + (2 * sizeof(*dp) + 3)) / sizeof(*dp);
451*b636d99dSDavid van Moolenbroek 			ND_TCHECK2(dp[0], 0);
452*b636d99dSDavid van Moolenbroek 			return (dp);
453*b636d99dSDavid van Moolenbroek 		}
454*b636d99dSDavid van Moolenbroek 	}
455*b636d99dSDavid van Moolenbroek trunc:
456*b636d99dSDavid van Moolenbroek 	return (NULL);
457*b636d99dSDavid van Moolenbroek }
458*b636d99dSDavid van Moolenbroek 
459*b636d99dSDavid van Moolenbroek /*
460*b636d99dSDavid van Moolenbroek  * Print out an NFS file handle and return a pointer to following word.
461*b636d99dSDavid van Moolenbroek  * If packet was truncated, return 0.
462*b636d99dSDavid van Moolenbroek  */
463*b636d99dSDavid van Moolenbroek static const uint32_t *
parsefh(netdissect_options * ndo,register const uint32_t * dp,int v3)464*b636d99dSDavid van Moolenbroek parsefh(netdissect_options *ndo,
465*b636d99dSDavid van Moolenbroek         register const uint32_t *dp, int v3)
466*b636d99dSDavid van Moolenbroek {
467*b636d99dSDavid van Moolenbroek 	u_int len;
468*b636d99dSDavid van Moolenbroek 
469*b636d99dSDavid van Moolenbroek 	if (v3) {
470*b636d99dSDavid van Moolenbroek 		ND_TCHECK(dp[0]);
471*b636d99dSDavid van Moolenbroek 		len = EXTRACT_32BITS(dp) / 4;
472*b636d99dSDavid van Moolenbroek 		dp++;
473*b636d99dSDavid van Moolenbroek 	} else
474*b636d99dSDavid van Moolenbroek 		len = NFSX_V2FH / 4;
475*b636d99dSDavid van Moolenbroek 
476*b636d99dSDavid van Moolenbroek 	if (ND_TTEST2(*dp, len * sizeof(*dp))) {
477*b636d99dSDavid van Moolenbroek 		nfs_printfh(ndo, dp, len);
478*b636d99dSDavid van Moolenbroek 		return (dp + len);
479*b636d99dSDavid van Moolenbroek 	}
480*b636d99dSDavid van Moolenbroek trunc:
481*b636d99dSDavid van Moolenbroek 	return (NULL);
482*b636d99dSDavid van Moolenbroek }
483*b636d99dSDavid van Moolenbroek 
484*b636d99dSDavid van Moolenbroek /*
485*b636d99dSDavid van Moolenbroek  * Print out a file name and return pointer to 32-bit word past it.
486*b636d99dSDavid van Moolenbroek  * If packet was truncated, return 0.
487*b636d99dSDavid van Moolenbroek  */
488*b636d99dSDavid van Moolenbroek static const uint32_t *
parsefn(netdissect_options * ndo,register const uint32_t * dp)489*b636d99dSDavid van Moolenbroek parsefn(netdissect_options *ndo,
490*b636d99dSDavid van Moolenbroek         register const uint32_t *dp)
491*b636d99dSDavid van Moolenbroek {
492*b636d99dSDavid van Moolenbroek 	register uint32_t len;
493*b636d99dSDavid van Moolenbroek 	register const u_char *cp;
494*b636d99dSDavid van Moolenbroek 
495*b636d99dSDavid van Moolenbroek 	/* Bail if we don't have the string length */
496*b636d99dSDavid van Moolenbroek 	ND_TCHECK(*dp);
497*b636d99dSDavid van Moolenbroek 
498*b636d99dSDavid van Moolenbroek 	/* Fetch string length; convert to host order */
499*b636d99dSDavid van Moolenbroek 	len = *dp++;
500*b636d99dSDavid van Moolenbroek 	NTOHL(len);
501*b636d99dSDavid van Moolenbroek 
502*b636d99dSDavid van Moolenbroek 	ND_TCHECK2(*dp, ((len + 3) & ~3));
503*b636d99dSDavid van Moolenbroek 
504*b636d99dSDavid van Moolenbroek 	cp = (u_char *)dp;
505*b636d99dSDavid van Moolenbroek 	/* Update 32-bit pointer (NFS filenames padded to 32-bit boundaries) */
506*b636d99dSDavid van Moolenbroek 	dp += ((len + 3) & ~3) / sizeof(*dp);
507*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, "\""));
508*b636d99dSDavid van Moolenbroek 	if (fn_printn(ndo, cp, len, ndo->ndo_snapend)) {
509*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "\""));
510*b636d99dSDavid van Moolenbroek 		goto trunc;
511*b636d99dSDavid van Moolenbroek 	}
512*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, "\""));
513*b636d99dSDavid van Moolenbroek 
514*b636d99dSDavid van Moolenbroek 	return (dp);
515*b636d99dSDavid van Moolenbroek trunc:
516*b636d99dSDavid van Moolenbroek 	return NULL;
517*b636d99dSDavid van Moolenbroek }
518*b636d99dSDavid van Moolenbroek 
519*b636d99dSDavid van Moolenbroek /*
520*b636d99dSDavid van Moolenbroek  * Print out file handle and file name.
521*b636d99dSDavid van Moolenbroek  * Return pointer to 32-bit word past file name.
522*b636d99dSDavid van Moolenbroek  * If packet was truncated (or there was some other error), return 0.
523*b636d99dSDavid van Moolenbroek  */
524*b636d99dSDavid van Moolenbroek static const uint32_t *
parsefhn(netdissect_options * ndo,register const uint32_t * dp,int v3)525*b636d99dSDavid van Moolenbroek parsefhn(netdissect_options *ndo,
526*b636d99dSDavid van Moolenbroek          register const uint32_t *dp, int v3)
527*b636d99dSDavid van Moolenbroek {
528*b636d99dSDavid van Moolenbroek 	dp = parsefh(ndo, dp, v3);
529*b636d99dSDavid van Moolenbroek 	if (dp == NULL)
530*b636d99dSDavid van Moolenbroek 		return (NULL);
531*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, " "));
532*b636d99dSDavid van Moolenbroek 	return (parsefn(ndo, dp));
533*b636d99dSDavid van Moolenbroek }
534*b636d99dSDavid van Moolenbroek 
535*b636d99dSDavid van Moolenbroek void
nfsreq_print_noaddr(netdissect_options * ndo,register const u_char * bp,u_int length,register const u_char * bp2)536*b636d99dSDavid van Moolenbroek nfsreq_print_noaddr(netdissect_options *ndo,
537*b636d99dSDavid van Moolenbroek                     register const u_char *bp, u_int length,
538*b636d99dSDavid van Moolenbroek                     register const u_char *bp2)
539*b636d99dSDavid van Moolenbroek {
540*b636d99dSDavid van Moolenbroek 	register const struct sunrpc_msg *rp;
541*b636d99dSDavid van Moolenbroek 	register const uint32_t *dp;
542*b636d99dSDavid van Moolenbroek 	nfs_type type;
543*b636d99dSDavid van Moolenbroek 	int v3;
544*b636d99dSDavid van Moolenbroek 	uint32_t proc;
545*b636d99dSDavid van Moolenbroek 	uint32_t access_flags;
546*b636d99dSDavid van Moolenbroek 	struct nfsv3_sattr sa3;
547*b636d99dSDavid van Moolenbroek 
548*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, "%d", length));
549*b636d99dSDavid van Moolenbroek 	nfserr = 0;		/* assume no error */
550*b636d99dSDavid van Moolenbroek 	rp = (const struct sunrpc_msg *)bp;
551*b636d99dSDavid van Moolenbroek 
552*b636d99dSDavid van Moolenbroek 	if (!xid_map_enter(ndo, rp, bp2))	/* record proc number for later on */
553*b636d99dSDavid van Moolenbroek 		goto trunc;
554*b636d99dSDavid van Moolenbroek 
555*b636d99dSDavid van Moolenbroek 	v3 = (EXTRACT_32BITS(&rp->rm_call.cb_vers) == NFS_VER3);
556*b636d99dSDavid van Moolenbroek 	proc = EXTRACT_32BITS(&rp->rm_call.cb_proc);
557*b636d99dSDavid van Moolenbroek 
558*b636d99dSDavid van Moolenbroek 	if (!v3 && proc < NFS_NPROCS)
559*b636d99dSDavid van Moolenbroek 		proc =  nfsv3_procid[proc];
560*b636d99dSDavid van Moolenbroek 
561*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, " %s", tok2str(nfsproc_str, "proc-%u", proc)));
562*b636d99dSDavid van Moolenbroek 	switch (proc) {
563*b636d99dSDavid van Moolenbroek 
564*b636d99dSDavid van Moolenbroek 	case NFSPROC_GETATTR:
565*b636d99dSDavid van Moolenbroek 	case NFSPROC_SETATTR:
566*b636d99dSDavid van Moolenbroek 	case NFSPROC_READLINK:
567*b636d99dSDavid van Moolenbroek 	case NFSPROC_FSSTAT:
568*b636d99dSDavid van Moolenbroek 	case NFSPROC_FSINFO:
569*b636d99dSDavid van Moolenbroek 	case NFSPROC_PATHCONF:
570*b636d99dSDavid van Moolenbroek 		if ((dp = parsereq(ndo, rp, length)) != NULL &&
571*b636d99dSDavid van Moolenbroek 		    parsefh(ndo, dp, v3) != NULL)
572*b636d99dSDavid van Moolenbroek 			return;
573*b636d99dSDavid van Moolenbroek 		break;
574*b636d99dSDavid van Moolenbroek 
575*b636d99dSDavid van Moolenbroek 	case NFSPROC_LOOKUP:
576*b636d99dSDavid van Moolenbroek 	case NFSPROC_CREATE:
577*b636d99dSDavid van Moolenbroek 	case NFSPROC_MKDIR:
578*b636d99dSDavid van Moolenbroek 	case NFSPROC_REMOVE:
579*b636d99dSDavid van Moolenbroek 	case NFSPROC_RMDIR:
580*b636d99dSDavid van Moolenbroek 		if ((dp = parsereq(ndo, rp, length)) != NULL &&
581*b636d99dSDavid van Moolenbroek 		    parsefhn(ndo, dp, v3) != NULL)
582*b636d99dSDavid van Moolenbroek 			return;
583*b636d99dSDavid van Moolenbroek 		break;
584*b636d99dSDavid van Moolenbroek 
585*b636d99dSDavid van Moolenbroek 	case NFSPROC_ACCESS:
586*b636d99dSDavid van Moolenbroek 		if ((dp = parsereq(ndo, rp, length)) != NULL &&
587*b636d99dSDavid van Moolenbroek 		    (dp = parsefh(ndo, dp, v3)) != NULL) {
588*b636d99dSDavid van Moolenbroek 			ND_TCHECK(dp[0]);
589*b636d99dSDavid van Moolenbroek 			access_flags = EXTRACT_32BITS(&dp[0]);
590*b636d99dSDavid van Moolenbroek 			if (access_flags & ~NFSV3ACCESS_FULL) {
591*b636d99dSDavid van Moolenbroek 				/* NFSV3ACCESS definitions aren't up to date */
592*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, " %04x", access_flags));
593*b636d99dSDavid van Moolenbroek 			} else if ((access_flags & NFSV3ACCESS_FULL) == NFSV3ACCESS_FULL) {
594*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, " NFS_ACCESS_FULL"));
595*b636d99dSDavid van Moolenbroek 			} else {
596*b636d99dSDavid van Moolenbroek 				char separator = ' ';
597*b636d99dSDavid van Moolenbroek 				if (access_flags & NFSV3ACCESS_READ) {
598*b636d99dSDavid van Moolenbroek 					ND_PRINT((ndo, " NFS_ACCESS_READ"));
599*b636d99dSDavid van Moolenbroek 					separator = '|';
600*b636d99dSDavid van Moolenbroek 				}
601*b636d99dSDavid van Moolenbroek 				if (access_flags & NFSV3ACCESS_LOOKUP) {
602*b636d99dSDavid van Moolenbroek 					ND_PRINT((ndo, "%cNFS_ACCESS_LOOKUP", separator));
603*b636d99dSDavid van Moolenbroek 					separator = '|';
604*b636d99dSDavid van Moolenbroek 				}
605*b636d99dSDavid van Moolenbroek 				if (access_flags & NFSV3ACCESS_MODIFY) {
606*b636d99dSDavid van Moolenbroek 					ND_PRINT((ndo, "%cNFS_ACCESS_MODIFY", separator));
607*b636d99dSDavid van Moolenbroek 					separator = '|';
608*b636d99dSDavid van Moolenbroek 				}
609*b636d99dSDavid van Moolenbroek 				if (access_flags & NFSV3ACCESS_EXTEND) {
610*b636d99dSDavid van Moolenbroek 					ND_PRINT((ndo, "%cNFS_ACCESS_EXTEND", separator));
611*b636d99dSDavid van Moolenbroek 					separator = '|';
612*b636d99dSDavid van Moolenbroek 				}
613*b636d99dSDavid van Moolenbroek 				if (access_flags & NFSV3ACCESS_DELETE) {
614*b636d99dSDavid van Moolenbroek 					ND_PRINT((ndo, "%cNFS_ACCESS_DELETE", separator));
615*b636d99dSDavid van Moolenbroek 					separator = '|';
616*b636d99dSDavid van Moolenbroek 				}
617*b636d99dSDavid van Moolenbroek 				if (access_flags & NFSV3ACCESS_EXECUTE)
618*b636d99dSDavid van Moolenbroek 					ND_PRINT((ndo, "%cNFS_ACCESS_EXECUTE", separator));
619*b636d99dSDavid van Moolenbroek 			}
620*b636d99dSDavid van Moolenbroek 			return;
621*b636d99dSDavid van Moolenbroek 		}
622*b636d99dSDavid van Moolenbroek 		break;
623*b636d99dSDavid van Moolenbroek 
624*b636d99dSDavid van Moolenbroek 	case NFSPROC_READ:
625*b636d99dSDavid van Moolenbroek 		if ((dp = parsereq(ndo, rp, length)) != NULL &&
626*b636d99dSDavid van Moolenbroek 		    (dp = parsefh(ndo, dp, v3)) != NULL) {
627*b636d99dSDavid van Moolenbroek 			if (v3) {
628*b636d99dSDavid van Moolenbroek 				ND_TCHECK(dp[2]);
629*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, " %u bytes @ %" PRIu64,
630*b636d99dSDavid van Moolenbroek 				       EXTRACT_32BITS(&dp[2]),
631*b636d99dSDavid van Moolenbroek 				       EXTRACT_64BITS(&dp[0])));
632*b636d99dSDavid van Moolenbroek 			} else {
633*b636d99dSDavid van Moolenbroek 				ND_TCHECK(dp[1]);
634*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, " %u bytes @ %u",
635*b636d99dSDavid van Moolenbroek 				    EXTRACT_32BITS(&dp[1]),
636*b636d99dSDavid van Moolenbroek 				    EXTRACT_32BITS(&dp[0])));
637*b636d99dSDavid van Moolenbroek 			}
638*b636d99dSDavid van Moolenbroek 			return;
639*b636d99dSDavid van Moolenbroek 		}
640*b636d99dSDavid van Moolenbroek 		break;
641*b636d99dSDavid van Moolenbroek 
642*b636d99dSDavid van Moolenbroek 	case NFSPROC_WRITE:
643*b636d99dSDavid van Moolenbroek 		if ((dp = parsereq(ndo, rp, length)) != NULL &&
644*b636d99dSDavid van Moolenbroek 		    (dp = parsefh(ndo, dp, v3)) != NULL) {
645*b636d99dSDavid van Moolenbroek 			if (v3) {
646*b636d99dSDavid van Moolenbroek 				ND_TCHECK(dp[2]);
647*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, " %u (%u) bytes @ %" PRIu64,
648*b636d99dSDavid van Moolenbroek 						EXTRACT_32BITS(&dp[4]),
649*b636d99dSDavid van Moolenbroek 						EXTRACT_32BITS(&dp[2]),
650*b636d99dSDavid van Moolenbroek 						EXTRACT_64BITS(&dp[0])));
651*b636d99dSDavid van Moolenbroek 				if (ndo->ndo_vflag) {
652*b636d99dSDavid van Moolenbroek 					dp += 3;
653*b636d99dSDavid van Moolenbroek 					ND_TCHECK(dp[0]);
654*b636d99dSDavid van Moolenbroek 					ND_PRINT((ndo, " <%s>",
655*b636d99dSDavid van Moolenbroek 						tok2str(nfsv3_writemodes,
656*b636d99dSDavid van Moolenbroek 							NULL, EXTRACT_32BITS(dp))));
657*b636d99dSDavid van Moolenbroek 				}
658*b636d99dSDavid van Moolenbroek 			} else {
659*b636d99dSDavid van Moolenbroek 				ND_TCHECK(dp[3]);
660*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, " %u (%u) bytes @ %u (%u)",
661*b636d99dSDavid van Moolenbroek 						EXTRACT_32BITS(&dp[3]),
662*b636d99dSDavid van Moolenbroek 						EXTRACT_32BITS(&dp[2]),
663*b636d99dSDavid van Moolenbroek 						EXTRACT_32BITS(&dp[1]),
664*b636d99dSDavid van Moolenbroek 						EXTRACT_32BITS(&dp[0])));
665*b636d99dSDavid van Moolenbroek 			}
666*b636d99dSDavid van Moolenbroek 			return;
667*b636d99dSDavid van Moolenbroek 		}
668*b636d99dSDavid van Moolenbroek 		break;
669*b636d99dSDavid van Moolenbroek 
670*b636d99dSDavid van Moolenbroek 	case NFSPROC_SYMLINK:
671*b636d99dSDavid van Moolenbroek 		if ((dp = parsereq(ndo, rp, length)) != 0 &&
672*b636d99dSDavid van Moolenbroek 		    (dp = parsefhn(ndo, dp, v3)) != 0) {
673*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, " ->"));
674*b636d99dSDavid van Moolenbroek 			if (v3 && (dp = parse_sattr3(ndo, dp, &sa3)) == 0)
675*b636d99dSDavid van Moolenbroek 				break;
676*b636d99dSDavid van Moolenbroek 			if (parsefn(ndo, dp) == 0)
677*b636d99dSDavid van Moolenbroek 				break;
678*b636d99dSDavid van Moolenbroek 			if (v3 && ndo->ndo_vflag)
679*b636d99dSDavid van Moolenbroek 				print_sattr3(ndo, &sa3, ndo->ndo_vflag);
680*b636d99dSDavid van Moolenbroek 			return;
681*b636d99dSDavid van Moolenbroek 		}
682*b636d99dSDavid van Moolenbroek 		break;
683*b636d99dSDavid van Moolenbroek 
684*b636d99dSDavid van Moolenbroek 	case NFSPROC_MKNOD:
685*b636d99dSDavid van Moolenbroek 		if ((dp = parsereq(ndo, rp, length)) != 0 &&
686*b636d99dSDavid van Moolenbroek 		    (dp = parsefhn(ndo, dp, v3)) != 0) {
687*b636d99dSDavid van Moolenbroek 			ND_TCHECK(*dp);
688*b636d99dSDavid van Moolenbroek 			type = (nfs_type)EXTRACT_32BITS(dp);
689*b636d99dSDavid van Moolenbroek 			dp++;
690*b636d99dSDavid van Moolenbroek 			if ((dp = parse_sattr3(ndo, dp, &sa3)) == 0)
691*b636d99dSDavid van Moolenbroek 				break;
692*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, " %s", tok2str(type2str, "unk-ft %d", type)));
693*b636d99dSDavid van Moolenbroek 			if (ndo->ndo_vflag && (type == NFCHR || type == NFBLK)) {
694*b636d99dSDavid van Moolenbroek 				ND_TCHECK(dp[1]);
695*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, " %u/%u",
696*b636d99dSDavid van Moolenbroek 				       EXTRACT_32BITS(&dp[0]),
697*b636d99dSDavid van Moolenbroek 				       EXTRACT_32BITS(&dp[1])));
698*b636d99dSDavid van Moolenbroek 				dp += 2;
699*b636d99dSDavid van Moolenbroek 			}
700*b636d99dSDavid van Moolenbroek 			if (ndo->ndo_vflag)
701*b636d99dSDavid van Moolenbroek 				print_sattr3(ndo, &sa3, ndo->ndo_vflag);
702*b636d99dSDavid van Moolenbroek 			return;
703*b636d99dSDavid van Moolenbroek 		}
704*b636d99dSDavid van Moolenbroek 		break;
705*b636d99dSDavid van Moolenbroek 
706*b636d99dSDavid van Moolenbroek 	case NFSPROC_RENAME:
707*b636d99dSDavid van Moolenbroek 		if ((dp = parsereq(ndo, rp, length)) != NULL &&
708*b636d99dSDavid van Moolenbroek 		    (dp = parsefhn(ndo, dp, v3)) != NULL) {
709*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, " ->"));
710*b636d99dSDavid van Moolenbroek 			if (parsefhn(ndo, dp, v3) != NULL)
711*b636d99dSDavid van Moolenbroek 				return;
712*b636d99dSDavid van Moolenbroek 		}
713*b636d99dSDavid van Moolenbroek 		break;
714*b636d99dSDavid van Moolenbroek 
715*b636d99dSDavid van Moolenbroek 	case NFSPROC_LINK:
716*b636d99dSDavid van Moolenbroek 		if ((dp = parsereq(ndo, rp, length)) != NULL &&
717*b636d99dSDavid van Moolenbroek 		    (dp = parsefh(ndo, dp, v3)) != NULL) {
718*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, " ->"));
719*b636d99dSDavid van Moolenbroek 			if (parsefhn(ndo, dp, v3) != NULL)
720*b636d99dSDavid van Moolenbroek 				return;
721*b636d99dSDavid van Moolenbroek 		}
722*b636d99dSDavid van Moolenbroek 		break;
723*b636d99dSDavid van Moolenbroek 
724*b636d99dSDavid van Moolenbroek 	case NFSPROC_READDIR:
725*b636d99dSDavid van Moolenbroek 		if ((dp = parsereq(ndo, rp, length)) != NULL &&
726*b636d99dSDavid van Moolenbroek 		    (dp = parsefh(ndo, dp, v3)) != NULL) {
727*b636d99dSDavid van Moolenbroek 			if (v3) {
728*b636d99dSDavid van Moolenbroek 				ND_TCHECK(dp[4]);
729*b636d99dSDavid van Moolenbroek 				/*
730*b636d99dSDavid van Moolenbroek 				 * We shouldn't really try to interpret the
731*b636d99dSDavid van Moolenbroek 				 * offset cookie here.
732*b636d99dSDavid van Moolenbroek 				 */
733*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, " %u bytes @ %" PRId64,
734*b636d99dSDavid van Moolenbroek 				    EXTRACT_32BITS(&dp[4]),
735*b636d99dSDavid van Moolenbroek 				    EXTRACT_64BITS(&dp[0])));
736*b636d99dSDavid van Moolenbroek 				if (ndo->ndo_vflag)
737*b636d99dSDavid van Moolenbroek 					ND_PRINT((ndo, " verf %08x%08x", dp[2], dp[3]));
738*b636d99dSDavid van Moolenbroek 			} else {
739*b636d99dSDavid van Moolenbroek 				ND_TCHECK(dp[1]);
740*b636d99dSDavid van Moolenbroek 				/*
741*b636d99dSDavid van Moolenbroek 				 * Print the offset as signed, since -1 is
742*b636d99dSDavid van Moolenbroek 				 * common, but offsets > 2^31 aren't.
743*b636d99dSDavid van Moolenbroek 				 */
744*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, " %u bytes @ %d",
745*b636d99dSDavid van Moolenbroek 				    EXTRACT_32BITS(&dp[1]),
746*b636d99dSDavid van Moolenbroek 				    EXTRACT_32BITS(&dp[0])));
747*b636d99dSDavid van Moolenbroek 			}
748*b636d99dSDavid van Moolenbroek 			return;
749*b636d99dSDavid van Moolenbroek 		}
750*b636d99dSDavid van Moolenbroek 		break;
751*b636d99dSDavid van Moolenbroek 
752*b636d99dSDavid van Moolenbroek 	case NFSPROC_READDIRPLUS:
753*b636d99dSDavid van Moolenbroek 		if ((dp = parsereq(ndo, rp, length)) != NULL &&
754*b636d99dSDavid van Moolenbroek 		    (dp = parsefh(ndo, dp, v3)) != NULL) {
755*b636d99dSDavid van Moolenbroek 			ND_TCHECK(dp[4]);
756*b636d99dSDavid van Moolenbroek 			/*
757*b636d99dSDavid van Moolenbroek 			 * We don't try to interpret the offset
758*b636d99dSDavid van Moolenbroek 			 * cookie here.
759*b636d99dSDavid van Moolenbroek 			 */
760*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, " %u bytes @ %" PRId64,
761*b636d99dSDavid van Moolenbroek 				EXTRACT_32BITS(&dp[4]),
762*b636d99dSDavid van Moolenbroek 				EXTRACT_64BITS(&dp[0])));
763*b636d99dSDavid van Moolenbroek 			if (ndo->ndo_vflag) {
764*b636d99dSDavid van Moolenbroek 				ND_TCHECK(dp[5]);
765*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, " max %u verf %08x%08x",
766*b636d99dSDavid van Moolenbroek 				       EXTRACT_32BITS(&dp[5]), dp[2], dp[3]));
767*b636d99dSDavid van Moolenbroek 			}
768*b636d99dSDavid van Moolenbroek 			return;
769*b636d99dSDavid van Moolenbroek 		}
770*b636d99dSDavid van Moolenbroek 		break;
771*b636d99dSDavid van Moolenbroek 
772*b636d99dSDavid van Moolenbroek 	case NFSPROC_COMMIT:
773*b636d99dSDavid van Moolenbroek 		if ((dp = parsereq(ndo, rp, length)) != NULL &&
774*b636d99dSDavid van Moolenbroek 		    (dp = parsefh(ndo, dp, v3)) != NULL) {
775*b636d99dSDavid van Moolenbroek 			ND_TCHECK(dp[2]);
776*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, " %u bytes @ %" PRIu64,
777*b636d99dSDavid van Moolenbroek 				EXTRACT_32BITS(&dp[2]),
778*b636d99dSDavid van Moolenbroek 				EXTRACT_64BITS(&dp[0])));
779*b636d99dSDavid van Moolenbroek 			return;
780*b636d99dSDavid van Moolenbroek 		}
781*b636d99dSDavid van Moolenbroek 		break;
782*b636d99dSDavid van Moolenbroek 
783*b636d99dSDavid van Moolenbroek 	default:
784*b636d99dSDavid van Moolenbroek 		return;
785*b636d99dSDavid van Moolenbroek 	}
786*b636d99dSDavid van Moolenbroek 
787*b636d99dSDavid van Moolenbroek trunc:
788*b636d99dSDavid van Moolenbroek 	if (!nfserr)
789*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "%s", tstr));
790*b636d99dSDavid van Moolenbroek }
791*b636d99dSDavid van Moolenbroek 
792*b636d99dSDavid van Moolenbroek /*
793*b636d99dSDavid van Moolenbroek  * Print out an NFS file handle.
794*b636d99dSDavid van Moolenbroek  * We assume packet was not truncated before the end of the
795*b636d99dSDavid van Moolenbroek  * file handle pointed to by dp.
796*b636d99dSDavid van Moolenbroek  *
797*b636d99dSDavid van Moolenbroek  * Note: new version (using portable file-handle parser) doesn't produce
798*b636d99dSDavid van Moolenbroek  * generation number.  It probably could be made to do that, with some
799*b636d99dSDavid van Moolenbroek  * additional hacking on the parser code.
800*b636d99dSDavid van Moolenbroek  */
801*b636d99dSDavid van Moolenbroek static void
nfs_printfh(netdissect_options * ndo,register const uint32_t * dp,const u_int len)802*b636d99dSDavid van Moolenbroek nfs_printfh(netdissect_options *ndo,
803*b636d99dSDavid van Moolenbroek             register const uint32_t *dp, const u_int len)
804*b636d99dSDavid van Moolenbroek {
805*b636d99dSDavid van Moolenbroek 	my_fsid fsid;
806*b636d99dSDavid van Moolenbroek 	uint32_t ino;
807*b636d99dSDavid van Moolenbroek 	const char *sfsname = NULL;
808*b636d99dSDavid van Moolenbroek 	char *spacep;
809*b636d99dSDavid van Moolenbroek 
810*b636d99dSDavid van Moolenbroek 	if (ndo->ndo_uflag) {
811*b636d99dSDavid van Moolenbroek 		u_int i;
812*b636d99dSDavid van Moolenbroek 		char const *sep = "";
813*b636d99dSDavid van Moolenbroek 
814*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " fh["));
815*b636d99dSDavid van Moolenbroek 		for (i=0; i<len; i++) {
816*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, "%s%x", sep, dp[i]));
817*b636d99dSDavid van Moolenbroek 			sep = ":";
818*b636d99dSDavid van Moolenbroek 		}
819*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "]"));
820*b636d99dSDavid van Moolenbroek 		return;
821*b636d99dSDavid van Moolenbroek 	}
822*b636d99dSDavid van Moolenbroek 
823*b636d99dSDavid van Moolenbroek 	Parse_fh((const u_char *)dp, len, &fsid, &ino, NULL, &sfsname, 0);
824*b636d99dSDavid van Moolenbroek 
825*b636d99dSDavid van Moolenbroek 	if (sfsname) {
826*b636d99dSDavid van Moolenbroek 		/* file system ID is ASCII, not numeric, for this server OS */
827*b636d99dSDavid van Moolenbroek 		static char temp[NFSX_V3FHMAX+1];
828*b636d99dSDavid van Moolenbroek 
829*b636d99dSDavid van Moolenbroek 		/* Make sure string is null-terminated */
830*b636d99dSDavid van Moolenbroek 		strncpy(temp, sfsname, NFSX_V3FHMAX);
831*b636d99dSDavid van Moolenbroek 		temp[sizeof(temp) - 1] = '\0';
832*b636d99dSDavid van Moolenbroek 		/* Remove trailing spaces */
833*b636d99dSDavid van Moolenbroek 		spacep = strchr(temp, ' ');
834*b636d99dSDavid van Moolenbroek 		if (spacep)
835*b636d99dSDavid van Moolenbroek 			*spacep = '\0';
836*b636d99dSDavid van Moolenbroek 
837*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " fh %s/", temp));
838*b636d99dSDavid van Moolenbroek 	} else {
839*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " fh %d,%d/",
840*b636d99dSDavid van Moolenbroek 			     fsid.Fsid_dev.Major, fsid.Fsid_dev.Minor));
841*b636d99dSDavid van Moolenbroek 	}
842*b636d99dSDavid van Moolenbroek 
843*b636d99dSDavid van Moolenbroek 	if(fsid.Fsid_dev.Minor == 257)
844*b636d99dSDavid van Moolenbroek 		/* Print the undecoded handle */
845*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "%s", fsid.Opaque_Handle));
846*b636d99dSDavid van Moolenbroek 	else
847*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "%ld", (long) ino));
848*b636d99dSDavid van Moolenbroek }
849*b636d99dSDavid van Moolenbroek 
850*b636d99dSDavid van Moolenbroek /*
851*b636d99dSDavid van Moolenbroek  * Maintain a small cache of recent client.XID.server/proc pairs, to allow
852*b636d99dSDavid van Moolenbroek  * us to match up replies with requests and thus to know how to parse
853*b636d99dSDavid van Moolenbroek  * the reply.
854*b636d99dSDavid van Moolenbroek  */
855*b636d99dSDavid van Moolenbroek 
856*b636d99dSDavid van Moolenbroek struct xid_map_entry {
857*b636d99dSDavid van Moolenbroek 	uint32_t	xid;		/* transaction ID (net order) */
858*b636d99dSDavid van Moolenbroek 	int ipver;			/* IP version (4 or 6) */
859*b636d99dSDavid van Moolenbroek #ifdef INET6
860*b636d99dSDavid van Moolenbroek 	struct in6_addr	client;		/* client IP address (net order) */
861*b636d99dSDavid van Moolenbroek 	struct in6_addr	server;		/* server IP address (net order) */
862*b636d99dSDavid van Moolenbroek #else
863*b636d99dSDavid van Moolenbroek 	struct in_addr	client;		/* client IP address (net order) */
864*b636d99dSDavid van Moolenbroek 	struct in_addr	server;		/* server IP address (net order) */
865*b636d99dSDavid van Moolenbroek #endif
866*b636d99dSDavid van Moolenbroek 	uint32_t	proc;		/* call proc number (host order) */
867*b636d99dSDavid van Moolenbroek 	uint32_t	vers;		/* program version (host order) */
868*b636d99dSDavid van Moolenbroek };
869*b636d99dSDavid van Moolenbroek 
870*b636d99dSDavid van Moolenbroek /*
871*b636d99dSDavid van Moolenbroek  * Map entries are kept in an array that we manage as a ring;
872*b636d99dSDavid van Moolenbroek  * new entries are always added at the tail of the ring.  Initially,
873*b636d99dSDavid van Moolenbroek  * all the entries are zero and hence don't match anything.
874*b636d99dSDavid van Moolenbroek  */
875*b636d99dSDavid van Moolenbroek 
876*b636d99dSDavid van Moolenbroek #define	XIDMAPSIZE	64
877*b636d99dSDavid van Moolenbroek 
878*b636d99dSDavid van Moolenbroek struct xid_map_entry xid_map[XIDMAPSIZE];
879*b636d99dSDavid van Moolenbroek 
880*b636d99dSDavid van Moolenbroek int	xid_map_next = 0;
881*b636d99dSDavid van Moolenbroek int	xid_map_hint = 0;
882*b636d99dSDavid van Moolenbroek 
883*b636d99dSDavid van Moolenbroek static int
xid_map_enter(netdissect_options * ndo,const struct sunrpc_msg * rp,const u_char * bp)884*b636d99dSDavid van Moolenbroek xid_map_enter(netdissect_options *ndo,
885*b636d99dSDavid van Moolenbroek               const struct sunrpc_msg *rp, const u_char *bp)
886*b636d99dSDavid van Moolenbroek {
887*b636d99dSDavid van Moolenbroek 	struct ip *ip = NULL;
888*b636d99dSDavid van Moolenbroek #ifdef INET6
889*b636d99dSDavid van Moolenbroek 	struct ip6_hdr *ip6 = NULL;
890*b636d99dSDavid van Moolenbroek #endif
891*b636d99dSDavid van Moolenbroek 	struct xid_map_entry *xmep;
892*b636d99dSDavid van Moolenbroek 
893*b636d99dSDavid van Moolenbroek 	if (!ND_TTEST(rp->rm_call.cb_vers))
894*b636d99dSDavid van Moolenbroek 		return (0);
895*b636d99dSDavid van Moolenbroek 	switch (IP_V((struct ip *)bp)) {
896*b636d99dSDavid van Moolenbroek 	case 4:
897*b636d99dSDavid van Moolenbroek 		ip = (struct ip *)bp;
898*b636d99dSDavid van Moolenbroek 		break;
899*b636d99dSDavid van Moolenbroek #ifdef INET6
900*b636d99dSDavid van Moolenbroek 	case 6:
901*b636d99dSDavid van Moolenbroek 		ip6 = (struct ip6_hdr *)bp;
902*b636d99dSDavid van Moolenbroek 		break;
903*b636d99dSDavid van Moolenbroek #endif
904*b636d99dSDavid van Moolenbroek 	default:
905*b636d99dSDavid van Moolenbroek 		return (1);
906*b636d99dSDavid van Moolenbroek 	}
907*b636d99dSDavid van Moolenbroek 
908*b636d99dSDavid van Moolenbroek 	xmep = &xid_map[xid_map_next];
909*b636d99dSDavid van Moolenbroek 
910*b636d99dSDavid van Moolenbroek 	if (++xid_map_next >= XIDMAPSIZE)
911*b636d99dSDavid van Moolenbroek 		xid_map_next = 0;
912*b636d99dSDavid van Moolenbroek 
913*b636d99dSDavid van Moolenbroek 	UNALIGNED_MEMCPY(&xmep->xid, &rp->rm_xid, sizeof(xmep->xid));
914*b636d99dSDavid van Moolenbroek 	if (ip) {
915*b636d99dSDavid van Moolenbroek 		xmep->ipver = 4;
916*b636d99dSDavid van Moolenbroek 		UNALIGNED_MEMCPY(&xmep->client, &ip->ip_src, sizeof(ip->ip_src));
917*b636d99dSDavid van Moolenbroek 		UNALIGNED_MEMCPY(&xmep->server, &ip->ip_dst, sizeof(ip->ip_dst));
918*b636d99dSDavid van Moolenbroek 	}
919*b636d99dSDavid van Moolenbroek #ifdef INET6
920*b636d99dSDavid van Moolenbroek 	else if (ip6) {
921*b636d99dSDavid van Moolenbroek 		xmep->ipver = 6;
922*b636d99dSDavid van Moolenbroek 		UNALIGNED_MEMCPY(&xmep->client, &ip6->ip6_src, sizeof(ip6->ip6_src));
923*b636d99dSDavid van Moolenbroek 		UNALIGNED_MEMCPY(&xmep->server, &ip6->ip6_dst, sizeof(ip6->ip6_dst));
924*b636d99dSDavid van Moolenbroek 	}
925*b636d99dSDavid van Moolenbroek #endif
926*b636d99dSDavid van Moolenbroek 	xmep->proc = EXTRACT_32BITS(&rp->rm_call.cb_proc);
927*b636d99dSDavid van Moolenbroek 	xmep->vers = EXTRACT_32BITS(&rp->rm_call.cb_vers);
928*b636d99dSDavid van Moolenbroek 	return (1);
929*b636d99dSDavid van Moolenbroek }
930*b636d99dSDavid van Moolenbroek 
931*b636d99dSDavid van Moolenbroek /*
932*b636d99dSDavid van Moolenbroek  * Returns 0 and puts NFSPROC_xxx in proc return and
933*b636d99dSDavid van Moolenbroek  * version in vers return, or returns -1 on failure
934*b636d99dSDavid van Moolenbroek  */
935*b636d99dSDavid van Moolenbroek static int
xid_map_find(const struct sunrpc_msg * rp,const u_char * bp,uint32_t * proc,uint32_t * vers)936*b636d99dSDavid van Moolenbroek xid_map_find(const struct sunrpc_msg *rp, const u_char *bp, uint32_t *proc,
937*b636d99dSDavid van Moolenbroek 	     uint32_t *vers)
938*b636d99dSDavid van Moolenbroek {
939*b636d99dSDavid van Moolenbroek 	int i;
940*b636d99dSDavid van Moolenbroek 	struct xid_map_entry *xmep;
941*b636d99dSDavid van Moolenbroek 	uint32_t xid = rp->rm_xid;
942*b636d99dSDavid van Moolenbroek 	struct ip *ip = (struct ip *)bp;
943*b636d99dSDavid van Moolenbroek #ifdef INET6
944*b636d99dSDavid van Moolenbroek 	struct ip6_hdr *ip6 = (struct ip6_hdr *)bp;
945*b636d99dSDavid van Moolenbroek #endif
946*b636d99dSDavid van Moolenbroek 	int cmp;
947*b636d99dSDavid van Moolenbroek 
948*b636d99dSDavid van Moolenbroek 	/* Start searching from where we last left off */
949*b636d99dSDavid van Moolenbroek 	i = xid_map_hint;
950*b636d99dSDavid van Moolenbroek 	do {
951*b636d99dSDavid van Moolenbroek 		xmep = &xid_map[i];
952*b636d99dSDavid van Moolenbroek 		cmp = 1;
953*b636d99dSDavid van Moolenbroek 		if (xmep->ipver != IP_V(ip) || xmep->xid != xid)
954*b636d99dSDavid van Moolenbroek 			goto nextitem;
955*b636d99dSDavid van Moolenbroek 		switch (xmep->ipver) {
956*b636d99dSDavid van Moolenbroek 		case 4:
957*b636d99dSDavid van Moolenbroek 			if (UNALIGNED_MEMCMP(&ip->ip_src, &xmep->server,
958*b636d99dSDavid van Moolenbroek 				   sizeof(ip->ip_src)) != 0 ||
959*b636d99dSDavid van Moolenbroek 			    UNALIGNED_MEMCMP(&ip->ip_dst, &xmep->client,
960*b636d99dSDavid van Moolenbroek 				   sizeof(ip->ip_dst)) != 0) {
961*b636d99dSDavid van Moolenbroek 				cmp = 0;
962*b636d99dSDavid van Moolenbroek 			}
963*b636d99dSDavid van Moolenbroek 			break;
964*b636d99dSDavid van Moolenbroek #ifdef INET6
965*b636d99dSDavid van Moolenbroek 		case 6:
966*b636d99dSDavid van Moolenbroek 			if (UNALIGNED_MEMCMP(&ip6->ip6_src, &xmep->server,
967*b636d99dSDavid van Moolenbroek 				   sizeof(ip6->ip6_src)) != 0 ||
968*b636d99dSDavid van Moolenbroek 			    UNALIGNED_MEMCMP(&ip6->ip6_dst, &xmep->client,
969*b636d99dSDavid van Moolenbroek 				   sizeof(ip6->ip6_dst)) != 0) {
970*b636d99dSDavid van Moolenbroek 				cmp = 0;
971*b636d99dSDavid van Moolenbroek 			}
972*b636d99dSDavid van Moolenbroek 			break;
973*b636d99dSDavid van Moolenbroek #endif
974*b636d99dSDavid van Moolenbroek 		default:
975*b636d99dSDavid van Moolenbroek 			cmp = 0;
976*b636d99dSDavid van Moolenbroek 			break;
977*b636d99dSDavid van Moolenbroek 		}
978*b636d99dSDavid van Moolenbroek 		if (cmp) {
979*b636d99dSDavid van Moolenbroek 			/* match */
980*b636d99dSDavid van Moolenbroek 			xid_map_hint = i;
981*b636d99dSDavid van Moolenbroek 			*proc = xmep->proc;
982*b636d99dSDavid van Moolenbroek 			*vers = xmep->vers;
983*b636d99dSDavid van Moolenbroek 			return 0;
984*b636d99dSDavid van Moolenbroek 		}
985*b636d99dSDavid van Moolenbroek 	nextitem:
986*b636d99dSDavid van Moolenbroek 		if (++i >= XIDMAPSIZE)
987*b636d99dSDavid van Moolenbroek 			i = 0;
988*b636d99dSDavid van Moolenbroek 	} while (i != xid_map_hint);
989*b636d99dSDavid van Moolenbroek 
990*b636d99dSDavid van Moolenbroek 	/* search failed */
991*b636d99dSDavid van Moolenbroek 	return (-1);
992*b636d99dSDavid van Moolenbroek }
993*b636d99dSDavid van Moolenbroek 
994*b636d99dSDavid van Moolenbroek /*
995*b636d99dSDavid van Moolenbroek  * Routines for parsing reply packets
996*b636d99dSDavid van Moolenbroek  */
997*b636d99dSDavid van Moolenbroek 
998*b636d99dSDavid van Moolenbroek /*
999*b636d99dSDavid van Moolenbroek  * Return a pointer to the beginning of the actual results.
1000*b636d99dSDavid van Moolenbroek  * If the packet was truncated, return 0.
1001*b636d99dSDavid van Moolenbroek  */
1002*b636d99dSDavid van Moolenbroek static const uint32_t *
parserep(netdissect_options * ndo,register const struct sunrpc_msg * rp,register u_int length)1003*b636d99dSDavid van Moolenbroek parserep(netdissect_options *ndo,
1004*b636d99dSDavid van Moolenbroek          register const struct sunrpc_msg *rp, register u_int length)
1005*b636d99dSDavid van Moolenbroek {
1006*b636d99dSDavid van Moolenbroek 	register const uint32_t *dp;
1007*b636d99dSDavid van Moolenbroek 	u_int len;
1008*b636d99dSDavid van Moolenbroek 	enum sunrpc_accept_stat astat;
1009*b636d99dSDavid van Moolenbroek 
1010*b636d99dSDavid van Moolenbroek 	/*
1011*b636d99dSDavid van Moolenbroek 	 * Portability note:
1012*b636d99dSDavid van Moolenbroek 	 * Here we find the address of the ar_verf credentials.
1013*b636d99dSDavid van Moolenbroek 	 * Originally, this calculation was
1014*b636d99dSDavid van Moolenbroek 	 *	dp = (uint32_t *)&rp->rm_reply.rp_acpt.ar_verf
1015*b636d99dSDavid van Moolenbroek 	 * On the wire, the rp_acpt field starts immediately after
1016*b636d99dSDavid van Moolenbroek 	 * the (32 bit) rp_stat field.  However, rp_acpt (which is a
1017*b636d99dSDavid van Moolenbroek 	 * "struct accepted_reply") contains a "struct opaque_auth",
1018*b636d99dSDavid van Moolenbroek 	 * whose internal representation contains a pointer, so on a
1019*b636d99dSDavid van Moolenbroek 	 * 64-bit machine the compiler inserts 32 bits of padding
1020*b636d99dSDavid van Moolenbroek 	 * before rp->rm_reply.rp_acpt.ar_verf.  So, we cannot use
1021*b636d99dSDavid van Moolenbroek 	 * the internal representation to parse the on-the-wire
1022*b636d99dSDavid van Moolenbroek 	 * representation.  Instead, we skip past the rp_stat field,
1023*b636d99dSDavid van Moolenbroek 	 * which is an "enum" and so occupies one 32-bit word.
1024*b636d99dSDavid van Moolenbroek 	 */
1025*b636d99dSDavid van Moolenbroek 	dp = ((const uint32_t *)&rp->rm_reply) + 1;
1026*b636d99dSDavid van Moolenbroek 	ND_TCHECK(dp[1]);
1027*b636d99dSDavid van Moolenbroek 	len = EXTRACT_32BITS(&dp[1]);
1028*b636d99dSDavid van Moolenbroek 	if (len >= length)
1029*b636d99dSDavid van Moolenbroek 		return (NULL);
1030*b636d99dSDavid van Moolenbroek 	/*
1031*b636d99dSDavid van Moolenbroek 	 * skip past the ar_verf credentials.
1032*b636d99dSDavid van Moolenbroek 	 */
1033*b636d99dSDavid van Moolenbroek 	dp += (len + (2*sizeof(uint32_t) + 3)) / sizeof(uint32_t);
1034*b636d99dSDavid van Moolenbroek 	ND_TCHECK2(dp[0], 0);
1035*b636d99dSDavid van Moolenbroek 
1036*b636d99dSDavid van Moolenbroek 	/*
1037*b636d99dSDavid van Moolenbroek 	 * now we can check the ar_stat field
1038*b636d99dSDavid van Moolenbroek 	 */
1039*b636d99dSDavid van Moolenbroek 	astat = (enum sunrpc_accept_stat) EXTRACT_32BITS(dp);
1040*b636d99dSDavid van Moolenbroek 	if (astat != SUNRPC_SUCCESS) {
1041*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " %s", tok2str(sunrpc_str, "ar_stat %d", astat)));
1042*b636d99dSDavid van Moolenbroek 		nfserr = 1;		/* suppress trunc string */
1043*b636d99dSDavid van Moolenbroek 		return (NULL);
1044*b636d99dSDavid van Moolenbroek 	}
1045*b636d99dSDavid van Moolenbroek 	/* successful return */
1046*b636d99dSDavid van Moolenbroek 	ND_TCHECK2(*dp, sizeof(astat));
1047*b636d99dSDavid van Moolenbroek 	return ((uint32_t *) (sizeof(astat) + ((char *)dp)));
1048*b636d99dSDavid van Moolenbroek trunc:
1049*b636d99dSDavid van Moolenbroek 	return (0);
1050*b636d99dSDavid van Moolenbroek }
1051*b636d99dSDavid van Moolenbroek 
1052*b636d99dSDavid van Moolenbroek static const uint32_t *
parsestatus(netdissect_options * ndo,const uint32_t * dp,int * er)1053*b636d99dSDavid van Moolenbroek parsestatus(netdissect_options *ndo,
1054*b636d99dSDavid van Moolenbroek             const uint32_t *dp, int *er)
1055*b636d99dSDavid van Moolenbroek {
1056*b636d99dSDavid van Moolenbroek 	int errnum;
1057*b636d99dSDavid van Moolenbroek 
1058*b636d99dSDavid van Moolenbroek 	ND_TCHECK(dp[0]);
1059*b636d99dSDavid van Moolenbroek 
1060*b636d99dSDavid van Moolenbroek 	errnum = EXTRACT_32BITS(&dp[0]);
1061*b636d99dSDavid van Moolenbroek 	if (er)
1062*b636d99dSDavid van Moolenbroek 		*er = errnum;
1063*b636d99dSDavid van Moolenbroek 	if (errnum != 0) {
1064*b636d99dSDavid van Moolenbroek 		if (!ndo->ndo_qflag)
1065*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, " ERROR: %s",
1066*b636d99dSDavid van Moolenbroek 			    tok2str(status2str, "unk %d", errnum)));
1067*b636d99dSDavid van Moolenbroek 		nfserr = 1;
1068*b636d99dSDavid van Moolenbroek 	}
1069*b636d99dSDavid van Moolenbroek 	return (dp + 1);
1070*b636d99dSDavid van Moolenbroek trunc:
1071*b636d99dSDavid van Moolenbroek 	return NULL;
1072*b636d99dSDavid van Moolenbroek }
1073*b636d99dSDavid van Moolenbroek 
1074*b636d99dSDavid van Moolenbroek static const uint32_t *
parsefattr(netdissect_options * ndo,const uint32_t * dp,int verbose,int v3)1075*b636d99dSDavid van Moolenbroek parsefattr(netdissect_options *ndo,
1076*b636d99dSDavid van Moolenbroek            const uint32_t *dp, int verbose, int v3)
1077*b636d99dSDavid van Moolenbroek {
1078*b636d99dSDavid van Moolenbroek 	const struct nfs_fattr *fap;
1079*b636d99dSDavid van Moolenbroek 
1080*b636d99dSDavid van Moolenbroek 	fap = (const struct nfs_fattr *)dp;
1081*b636d99dSDavid van Moolenbroek 	ND_TCHECK(fap->fa_gid);
1082*b636d99dSDavid van Moolenbroek 	if (verbose) {
1083*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " %s %o ids %d/%d",
1084*b636d99dSDavid van Moolenbroek 		    tok2str(type2str, "unk-ft %d ",
1085*b636d99dSDavid van Moolenbroek 		    EXTRACT_32BITS(&fap->fa_type)),
1086*b636d99dSDavid van Moolenbroek 		    EXTRACT_32BITS(&fap->fa_mode),
1087*b636d99dSDavid van Moolenbroek 		    EXTRACT_32BITS(&fap->fa_uid),
1088*b636d99dSDavid van Moolenbroek 		    EXTRACT_32BITS(&fap->fa_gid)));
1089*b636d99dSDavid van Moolenbroek 		if (v3) {
1090*b636d99dSDavid van Moolenbroek 			ND_TCHECK(fap->fa3_size);
1091*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, " sz %" PRIu64,
1092*b636d99dSDavid van Moolenbroek 				EXTRACT_64BITS((uint32_t *)&fap->fa3_size)));
1093*b636d99dSDavid van Moolenbroek 		} else {
1094*b636d99dSDavid van Moolenbroek 			ND_TCHECK(fap->fa2_size);
1095*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, " sz %d", EXTRACT_32BITS(&fap->fa2_size)));
1096*b636d99dSDavid van Moolenbroek 		}
1097*b636d99dSDavid van Moolenbroek 	}
1098*b636d99dSDavid van Moolenbroek 	/* print lots more stuff */
1099*b636d99dSDavid van Moolenbroek 	if (verbose > 1) {
1100*b636d99dSDavid van Moolenbroek 		if (v3) {
1101*b636d99dSDavid van Moolenbroek 			ND_TCHECK(fap->fa3_ctime);
1102*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, " nlink %d rdev %d/%d",
1103*b636d99dSDavid van Moolenbroek 			       EXTRACT_32BITS(&fap->fa_nlink),
1104*b636d99dSDavid van Moolenbroek 			       EXTRACT_32BITS(&fap->fa3_rdev.specdata1),
1105*b636d99dSDavid van Moolenbroek 			       EXTRACT_32BITS(&fap->fa3_rdev.specdata2)));
1106*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, " fsid %" PRIx64,
1107*b636d99dSDavid van Moolenbroek 				EXTRACT_64BITS((uint32_t *)&fap->fa3_fsid)));
1108*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, " fileid %" PRIx64,
1109*b636d99dSDavid van Moolenbroek 				EXTRACT_64BITS((uint32_t *)&fap->fa3_fileid)));
1110*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, " a/m/ctime %u.%06u",
1111*b636d99dSDavid van Moolenbroek 			       EXTRACT_32BITS(&fap->fa3_atime.nfsv3_sec),
1112*b636d99dSDavid van Moolenbroek 			       EXTRACT_32BITS(&fap->fa3_atime.nfsv3_nsec)));
1113*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, " %u.%06u",
1114*b636d99dSDavid van Moolenbroek 			       EXTRACT_32BITS(&fap->fa3_mtime.nfsv3_sec),
1115*b636d99dSDavid van Moolenbroek 			       EXTRACT_32BITS(&fap->fa3_mtime.nfsv3_nsec)));
1116*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, " %u.%06u",
1117*b636d99dSDavid van Moolenbroek 			       EXTRACT_32BITS(&fap->fa3_ctime.nfsv3_sec),
1118*b636d99dSDavid van Moolenbroek 			       EXTRACT_32BITS(&fap->fa3_ctime.nfsv3_nsec)));
1119*b636d99dSDavid van Moolenbroek 		} else {
1120*b636d99dSDavid van Moolenbroek 			ND_TCHECK(fap->fa2_ctime);
1121*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, " nlink %d rdev 0x%x fsid 0x%x nodeid 0x%x a/m/ctime",
1122*b636d99dSDavid van Moolenbroek 			       EXTRACT_32BITS(&fap->fa_nlink),
1123*b636d99dSDavid van Moolenbroek 			       EXTRACT_32BITS(&fap->fa2_rdev),
1124*b636d99dSDavid van Moolenbroek 			       EXTRACT_32BITS(&fap->fa2_fsid),
1125*b636d99dSDavid van Moolenbroek 			       EXTRACT_32BITS(&fap->fa2_fileid)));
1126*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, " %u.%06u",
1127*b636d99dSDavid van Moolenbroek 			       EXTRACT_32BITS(&fap->fa2_atime.nfsv2_sec),
1128*b636d99dSDavid van Moolenbroek 			       EXTRACT_32BITS(&fap->fa2_atime.nfsv2_usec)));
1129*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, " %u.%06u",
1130*b636d99dSDavid van Moolenbroek 			       EXTRACT_32BITS(&fap->fa2_mtime.nfsv2_sec),
1131*b636d99dSDavid van Moolenbroek 			       EXTRACT_32BITS(&fap->fa2_mtime.nfsv2_usec)));
1132*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, " %u.%06u",
1133*b636d99dSDavid van Moolenbroek 			       EXTRACT_32BITS(&fap->fa2_ctime.nfsv2_sec),
1134*b636d99dSDavid van Moolenbroek 			       EXTRACT_32BITS(&fap->fa2_ctime.nfsv2_usec)));
1135*b636d99dSDavid van Moolenbroek 		}
1136*b636d99dSDavid van Moolenbroek 	}
1137*b636d99dSDavid van Moolenbroek 	return ((const uint32_t *)((unsigned char *)dp +
1138*b636d99dSDavid van Moolenbroek 		(v3 ? NFSX_V3FATTR : NFSX_V2FATTR)));
1139*b636d99dSDavid van Moolenbroek trunc:
1140*b636d99dSDavid van Moolenbroek 	return (NULL);
1141*b636d99dSDavid van Moolenbroek }
1142*b636d99dSDavid van Moolenbroek 
1143*b636d99dSDavid van Moolenbroek static int
parseattrstat(netdissect_options * ndo,const uint32_t * dp,int verbose,int v3)1144*b636d99dSDavid van Moolenbroek parseattrstat(netdissect_options *ndo,
1145*b636d99dSDavid van Moolenbroek               const uint32_t *dp, int verbose, int v3)
1146*b636d99dSDavid van Moolenbroek {
1147*b636d99dSDavid van Moolenbroek 	int er;
1148*b636d99dSDavid van Moolenbroek 
1149*b636d99dSDavid van Moolenbroek 	dp = parsestatus(ndo, dp, &er);
1150*b636d99dSDavid van Moolenbroek 	if (dp == NULL)
1151*b636d99dSDavid van Moolenbroek 		return (0);
1152*b636d99dSDavid van Moolenbroek 	if (er)
1153*b636d99dSDavid van Moolenbroek 		return (1);
1154*b636d99dSDavid van Moolenbroek 
1155*b636d99dSDavid van Moolenbroek 	return (parsefattr(ndo, dp, verbose, v3) != NULL);
1156*b636d99dSDavid van Moolenbroek }
1157*b636d99dSDavid van Moolenbroek 
1158*b636d99dSDavid van Moolenbroek static int
parsediropres(netdissect_options * ndo,const uint32_t * dp)1159*b636d99dSDavid van Moolenbroek parsediropres(netdissect_options *ndo,
1160*b636d99dSDavid van Moolenbroek               const uint32_t *dp)
1161*b636d99dSDavid van Moolenbroek {
1162*b636d99dSDavid van Moolenbroek 	int er;
1163*b636d99dSDavid van Moolenbroek 
1164*b636d99dSDavid van Moolenbroek 	if (!(dp = parsestatus(ndo, dp, &er)))
1165*b636d99dSDavid van Moolenbroek 		return (0);
1166*b636d99dSDavid van Moolenbroek 	if (er)
1167*b636d99dSDavid van Moolenbroek 		return (1);
1168*b636d99dSDavid van Moolenbroek 
1169*b636d99dSDavid van Moolenbroek 	dp = parsefh(ndo, dp, 0);
1170*b636d99dSDavid van Moolenbroek 	if (dp == NULL)
1171*b636d99dSDavid van Moolenbroek 		return (0);
1172*b636d99dSDavid van Moolenbroek 
1173*b636d99dSDavid van Moolenbroek 	return (parsefattr(ndo, dp, ndo->ndo_vflag, 0) != NULL);
1174*b636d99dSDavid van Moolenbroek }
1175*b636d99dSDavid van Moolenbroek 
1176*b636d99dSDavid van Moolenbroek static int
parselinkres(netdissect_options * ndo,const uint32_t * dp,int v3)1177*b636d99dSDavid van Moolenbroek parselinkres(netdissect_options *ndo,
1178*b636d99dSDavid van Moolenbroek              const uint32_t *dp, int v3)
1179*b636d99dSDavid van Moolenbroek {
1180*b636d99dSDavid van Moolenbroek 	int er;
1181*b636d99dSDavid van Moolenbroek 
1182*b636d99dSDavid van Moolenbroek 	dp = parsestatus(ndo, dp, &er);
1183*b636d99dSDavid van Moolenbroek 	if (dp == NULL)
1184*b636d99dSDavid van Moolenbroek 		return(0);
1185*b636d99dSDavid van Moolenbroek 	if (er)
1186*b636d99dSDavid van Moolenbroek 		return(1);
1187*b636d99dSDavid van Moolenbroek 	if (v3 && !(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)))
1188*b636d99dSDavid van Moolenbroek 		return (0);
1189*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, " "));
1190*b636d99dSDavid van Moolenbroek 	return (parsefn(ndo, dp) != NULL);
1191*b636d99dSDavid van Moolenbroek }
1192*b636d99dSDavid van Moolenbroek 
1193*b636d99dSDavid van Moolenbroek static int
parsestatfs(netdissect_options * ndo,const uint32_t * dp,int v3)1194*b636d99dSDavid van Moolenbroek parsestatfs(netdissect_options *ndo,
1195*b636d99dSDavid van Moolenbroek             const uint32_t *dp, int v3)
1196*b636d99dSDavid van Moolenbroek {
1197*b636d99dSDavid van Moolenbroek 	const struct nfs_statfs *sfsp;
1198*b636d99dSDavid van Moolenbroek 	int er;
1199*b636d99dSDavid van Moolenbroek 
1200*b636d99dSDavid van Moolenbroek 	dp = parsestatus(ndo, dp, &er);
1201*b636d99dSDavid van Moolenbroek 	if (dp == NULL)
1202*b636d99dSDavid van Moolenbroek 		return (0);
1203*b636d99dSDavid van Moolenbroek 	if (!v3 && er)
1204*b636d99dSDavid van Moolenbroek 		return (1);
1205*b636d99dSDavid van Moolenbroek 
1206*b636d99dSDavid van Moolenbroek 	if (ndo->ndo_qflag)
1207*b636d99dSDavid van Moolenbroek 		return(1);
1208*b636d99dSDavid van Moolenbroek 
1209*b636d99dSDavid van Moolenbroek 	if (v3) {
1210*b636d99dSDavid van Moolenbroek 		if (ndo->ndo_vflag)
1211*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, " POST:"));
1212*b636d99dSDavid van Moolenbroek 		if (!(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)))
1213*b636d99dSDavid van Moolenbroek 			return (0);
1214*b636d99dSDavid van Moolenbroek 	}
1215*b636d99dSDavid van Moolenbroek 
1216*b636d99dSDavid van Moolenbroek 	ND_TCHECK2(*dp, (v3 ? NFSX_V3STATFS : NFSX_V2STATFS));
1217*b636d99dSDavid van Moolenbroek 
1218*b636d99dSDavid van Moolenbroek 	sfsp = (const struct nfs_statfs *)dp;
1219*b636d99dSDavid van Moolenbroek 
1220*b636d99dSDavid van Moolenbroek 	if (v3) {
1221*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " tbytes %" PRIu64 " fbytes %" PRIu64 " abytes %" PRIu64,
1222*b636d99dSDavid van Moolenbroek 			EXTRACT_64BITS((uint32_t *)&sfsp->sf_tbytes),
1223*b636d99dSDavid van Moolenbroek 			EXTRACT_64BITS((uint32_t *)&sfsp->sf_fbytes),
1224*b636d99dSDavid van Moolenbroek 			EXTRACT_64BITS((uint32_t *)&sfsp->sf_abytes)));
1225*b636d99dSDavid van Moolenbroek 		if (ndo->ndo_vflag) {
1226*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, " tfiles %" PRIu64 " ffiles %" PRIu64 " afiles %" PRIu64 " invar %u",
1227*b636d99dSDavid van Moolenbroek 			       EXTRACT_64BITS((uint32_t *)&sfsp->sf_tfiles),
1228*b636d99dSDavid van Moolenbroek 			       EXTRACT_64BITS((uint32_t *)&sfsp->sf_ffiles),
1229*b636d99dSDavid van Moolenbroek 			       EXTRACT_64BITS((uint32_t *)&sfsp->sf_afiles),
1230*b636d99dSDavid van Moolenbroek 			       EXTRACT_32BITS(&sfsp->sf_invarsec)));
1231*b636d99dSDavid van Moolenbroek 		}
1232*b636d99dSDavid van Moolenbroek 	} else {
1233*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " tsize %d bsize %d blocks %d bfree %d bavail %d",
1234*b636d99dSDavid van Moolenbroek 			EXTRACT_32BITS(&sfsp->sf_tsize),
1235*b636d99dSDavid van Moolenbroek 			EXTRACT_32BITS(&sfsp->sf_bsize),
1236*b636d99dSDavid van Moolenbroek 			EXTRACT_32BITS(&sfsp->sf_blocks),
1237*b636d99dSDavid van Moolenbroek 			EXTRACT_32BITS(&sfsp->sf_bfree),
1238*b636d99dSDavid van Moolenbroek 			EXTRACT_32BITS(&sfsp->sf_bavail)));
1239*b636d99dSDavid van Moolenbroek 	}
1240*b636d99dSDavid van Moolenbroek 
1241*b636d99dSDavid van Moolenbroek 	return (1);
1242*b636d99dSDavid van Moolenbroek trunc:
1243*b636d99dSDavid van Moolenbroek 	return (0);
1244*b636d99dSDavid van Moolenbroek }
1245*b636d99dSDavid van Moolenbroek 
1246*b636d99dSDavid van Moolenbroek static int
parserddires(netdissect_options * ndo,const uint32_t * dp)1247*b636d99dSDavid van Moolenbroek parserddires(netdissect_options *ndo,
1248*b636d99dSDavid van Moolenbroek              const uint32_t *dp)
1249*b636d99dSDavid van Moolenbroek {
1250*b636d99dSDavid van Moolenbroek 	int er;
1251*b636d99dSDavid van Moolenbroek 
1252*b636d99dSDavid van Moolenbroek 	dp = parsestatus(ndo, dp, &er);
1253*b636d99dSDavid van Moolenbroek 	if (dp == NULL)
1254*b636d99dSDavid van Moolenbroek 		return (0);
1255*b636d99dSDavid van Moolenbroek 	if (er)
1256*b636d99dSDavid van Moolenbroek 		return (1);
1257*b636d99dSDavid van Moolenbroek 	if (ndo->ndo_qflag)
1258*b636d99dSDavid van Moolenbroek 		return (1);
1259*b636d99dSDavid van Moolenbroek 
1260*b636d99dSDavid van Moolenbroek 	ND_TCHECK(dp[2]);
1261*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, " offset 0x%x size %d ",
1262*b636d99dSDavid van Moolenbroek 	       EXTRACT_32BITS(&dp[0]), EXTRACT_32BITS(&dp[1])));
1263*b636d99dSDavid van Moolenbroek 	if (dp[2] != 0)
1264*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " eof"));
1265*b636d99dSDavid van Moolenbroek 
1266*b636d99dSDavid van Moolenbroek 	return (1);
1267*b636d99dSDavid van Moolenbroek trunc:
1268*b636d99dSDavid van Moolenbroek 	return (0);
1269*b636d99dSDavid van Moolenbroek }
1270*b636d99dSDavid van Moolenbroek 
1271*b636d99dSDavid van Moolenbroek static const uint32_t *
parse_wcc_attr(netdissect_options * ndo,const uint32_t * dp)1272*b636d99dSDavid van Moolenbroek parse_wcc_attr(netdissect_options *ndo,
1273*b636d99dSDavid van Moolenbroek                const uint32_t *dp)
1274*b636d99dSDavid van Moolenbroek {
1275*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, " sz %" PRIu64, EXTRACT_64BITS(&dp[0])));
1276*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, " mtime %u.%06u ctime %u.%06u",
1277*b636d99dSDavid van Moolenbroek 	       EXTRACT_32BITS(&dp[2]), EXTRACT_32BITS(&dp[3]),
1278*b636d99dSDavid van Moolenbroek 	       EXTRACT_32BITS(&dp[4]), EXTRACT_32BITS(&dp[5])));
1279*b636d99dSDavid van Moolenbroek 	return (dp + 6);
1280*b636d99dSDavid van Moolenbroek }
1281*b636d99dSDavid van Moolenbroek 
1282*b636d99dSDavid van Moolenbroek /*
1283*b636d99dSDavid van Moolenbroek  * Pre operation attributes. Print only if vflag > 1.
1284*b636d99dSDavid van Moolenbroek  */
1285*b636d99dSDavid van Moolenbroek static const uint32_t *
parse_pre_op_attr(netdissect_options * ndo,const uint32_t * dp,int verbose)1286*b636d99dSDavid van Moolenbroek parse_pre_op_attr(netdissect_options *ndo,
1287*b636d99dSDavid van Moolenbroek                   const uint32_t *dp, int verbose)
1288*b636d99dSDavid van Moolenbroek {
1289*b636d99dSDavid van Moolenbroek 	ND_TCHECK(dp[0]);
1290*b636d99dSDavid van Moolenbroek 	if (!EXTRACT_32BITS(&dp[0]))
1291*b636d99dSDavid van Moolenbroek 		return (dp + 1);
1292*b636d99dSDavid van Moolenbroek 	dp++;
1293*b636d99dSDavid van Moolenbroek 	ND_TCHECK2(*dp, 24);
1294*b636d99dSDavid van Moolenbroek 	if (verbose > 1) {
1295*b636d99dSDavid van Moolenbroek 		return parse_wcc_attr(ndo, dp);
1296*b636d99dSDavid van Moolenbroek 	} else {
1297*b636d99dSDavid van Moolenbroek 		/* If not verbose enough, just skip over wcc_attr */
1298*b636d99dSDavid van Moolenbroek 		return (dp + 6);
1299*b636d99dSDavid van Moolenbroek 	}
1300*b636d99dSDavid van Moolenbroek trunc:
1301*b636d99dSDavid van Moolenbroek 	return (NULL);
1302*b636d99dSDavid van Moolenbroek }
1303*b636d99dSDavid van Moolenbroek 
1304*b636d99dSDavid van Moolenbroek /*
1305*b636d99dSDavid van Moolenbroek  * Post operation attributes are printed if vflag >= 1
1306*b636d99dSDavid van Moolenbroek  */
1307*b636d99dSDavid van Moolenbroek static const uint32_t *
parse_post_op_attr(netdissect_options * ndo,const uint32_t * dp,int verbose)1308*b636d99dSDavid van Moolenbroek parse_post_op_attr(netdissect_options *ndo,
1309*b636d99dSDavid van Moolenbroek                    const uint32_t *dp, int verbose)
1310*b636d99dSDavid van Moolenbroek {
1311*b636d99dSDavid van Moolenbroek 	ND_TCHECK(dp[0]);
1312*b636d99dSDavid van Moolenbroek 	if (!EXTRACT_32BITS(&dp[0]))
1313*b636d99dSDavid van Moolenbroek 		return (dp + 1);
1314*b636d99dSDavid van Moolenbroek 	dp++;
1315*b636d99dSDavid van Moolenbroek 	if (verbose) {
1316*b636d99dSDavid van Moolenbroek 		return parsefattr(ndo, dp, verbose, 1);
1317*b636d99dSDavid van Moolenbroek 	} else
1318*b636d99dSDavid van Moolenbroek 		return (dp + (NFSX_V3FATTR / sizeof (uint32_t)));
1319*b636d99dSDavid van Moolenbroek trunc:
1320*b636d99dSDavid van Moolenbroek 	return (NULL);
1321*b636d99dSDavid van Moolenbroek }
1322*b636d99dSDavid van Moolenbroek 
1323*b636d99dSDavid van Moolenbroek static const uint32_t *
parse_wcc_data(netdissect_options * ndo,const uint32_t * dp,int verbose)1324*b636d99dSDavid van Moolenbroek parse_wcc_data(netdissect_options *ndo,
1325*b636d99dSDavid van Moolenbroek                const uint32_t *dp, int verbose)
1326*b636d99dSDavid van Moolenbroek {
1327*b636d99dSDavid van Moolenbroek 	if (verbose > 1)
1328*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " PRE:"));
1329*b636d99dSDavid van Moolenbroek 	if (!(dp = parse_pre_op_attr(ndo, dp, verbose)))
1330*b636d99dSDavid van Moolenbroek 		return (0);
1331*b636d99dSDavid van Moolenbroek 
1332*b636d99dSDavid van Moolenbroek 	if (verbose)
1333*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " POST:"));
1334*b636d99dSDavid van Moolenbroek 	return parse_post_op_attr(ndo, dp, verbose);
1335*b636d99dSDavid van Moolenbroek }
1336*b636d99dSDavid van Moolenbroek 
1337*b636d99dSDavid van Moolenbroek static const uint32_t *
parsecreateopres(netdissect_options * ndo,const uint32_t * dp,int verbose)1338*b636d99dSDavid van Moolenbroek parsecreateopres(netdissect_options *ndo,
1339*b636d99dSDavid van Moolenbroek                  const uint32_t *dp, int verbose)
1340*b636d99dSDavid van Moolenbroek {
1341*b636d99dSDavid van Moolenbroek 	int er;
1342*b636d99dSDavid van Moolenbroek 
1343*b636d99dSDavid van Moolenbroek 	if (!(dp = parsestatus(ndo, dp, &er)))
1344*b636d99dSDavid van Moolenbroek 		return (0);
1345*b636d99dSDavid van Moolenbroek 	if (er)
1346*b636d99dSDavid van Moolenbroek 		dp = parse_wcc_data(ndo, dp, verbose);
1347*b636d99dSDavid van Moolenbroek 	else {
1348*b636d99dSDavid van Moolenbroek 		ND_TCHECK(dp[0]);
1349*b636d99dSDavid van Moolenbroek 		if (!EXTRACT_32BITS(&dp[0]))
1350*b636d99dSDavid van Moolenbroek 			return (dp + 1);
1351*b636d99dSDavid van Moolenbroek 		dp++;
1352*b636d99dSDavid van Moolenbroek 		if (!(dp = parsefh(ndo, dp, 1)))
1353*b636d99dSDavid van Moolenbroek 			return (0);
1354*b636d99dSDavid van Moolenbroek 		if (verbose) {
1355*b636d99dSDavid van Moolenbroek 			if (!(dp = parse_post_op_attr(ndo, dp, verbose)))
1356*b636d99dSDavid van Moolenbroek 				return (0);
1357*b636d99dSDavid van Moolenbroek 			if (ndo->ndo_vflag > 1) {
1358*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, " dir attr:"));
1359*b636d99dSDavid van Moolenbroek 				dp = parse_wcc_data(ndo, dp, verbose);
1360*b636d99dSDavid van Moolenbroek 			}
1361*b636d99dSDavid van Moolenbroek 		}
1362*b636d99dSDavid van Moolenbroek 	}
1363*b636d99dSDavid van Moolenbroek 	return (dp);
1364*b636d99dSDavid van Moolenbroek trunc:
1365*b636d99dSDavid van Moolenbroek 	return (NULL);
1366*b636d99dSDavid van Moolenbroek }
1367*b636d99dSDavid van Moolenbroek 
1368*b636d99dSDavid van Moolenbroek static int
parsewccres(netdissect_options * ndo,const uint32_t * dp,int verbose)1369*b636d99dSDavid van Moolenbroek parsewccres(netdissect_options *ndo,
1370*b636d99dSDavid van Moolenbroek             const uint32_t *dp, int verbose)
1371*b636d99dSDavid van Moolenbroek {
1372*b636d99dSDavid van Moolenbroek 	int er;
1373*b636d99dSDavid van Moolenbroek 
1374*b636d99dSDavid van Moolenbroek 	if (!(dp = parsestatus(ndo, dp, &er)))
1375*b636d99dSDavid van Moolenbroek 		return (0);
1376*b636d99dSDavid van Moolenbroek 	return parse_wcc_data(ndo, dp, verbose) != 0;
1377*b636d99dSDavid van Moolenbroek }
1378*b636d99dSDavid van Moolenbroek 
1379*b636d99dSDavid van Moolenbroek static const uint32_t *
parsev3rddirres(netdissect_options * ndo,const uint32_t * dp,int verbose)1380*b636d99dSDavid van Moolenbroek parsev3rddirres(netdissect_options *ndo,
1381*b636d99dSDavid van Moolenbroek                 const uint32_t *dp, int verbose)
1382*b636d99dSDavid van Moolenbroek {
1383*b636d99dSDavid van Moolenbroek 	int er;
1384*b636d99dSDavid van Moolenbroek 
1385*b636d99dSDavid van Moolenbroek 	if (!(dp = parsestatus(ndo, dp, &er)))
1386*b636d99dSDavid van Moolenbroek 		return (0);
1387*b636d99dSDavid van Moolenbroek 	if (ndo->ndo_vflag)
1388*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " POST:"));
1389*b636d99dSDavid van Moolenbroek 	if (!(dp = parse_post_op_attr(ndo, dp, verbose)))
1390*b636d99dSDavid van Moolenbroek 		return (0);
1391*b636d99dSDavid van Moolenbroek 	if (er)
1392*b636d99dSDavid van Moolenbroek 		return dp;
1393*b636d99dSDavid van Moolenbroek 	if (ndo->ndo_vflag) {
1394*b636d99dSDavid van Moolenbroek 		ND_TCHECK(dp[1]);
1395*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " verf %08x%08x", dp[0], dp[1]));
1396*b636d99dSDavid van Moolenbroek 		dp += 2;
1397*b636d99dSDavid van Moolenbroek 	}
1398*b636d99dSDavid van Moolenbroek 	return dp;
1399*b636d99dSDavid van Moolenbroek trunc:
1400*b636d99dSDavid van Moolenbroek 	return (NULL);
1401*b636d99dSDavid van Moolenbroek }
1402*b636d99dSDavid van Moolenbroek 
1403*b636d99dSDavid van Moolenbroek static int
parsefsinfo(netdissect_options * ndo,const uint32_t * dp)1404*b636d99dSDavid van Moolenbroek parsefsinfo(netdissect_options *ndo,
1405*b636d99dSDavid van Moolenbroek             const uint32_t *dp)
1406*b636d99dSDavid van Moolenbroek {
1407*b636d99dSDavid van Moolenbroek 	struct nfsv3_fsinfo *sfp;
1408*b636d99dSDavid van Moolenbroek 	int er;
1409*b636d99dSDavid van Moolenbroek 
1410*b636d99dSDavid van Moolenbroek 	if (!(dp = parsestatus(ndo, dp, &er)))
1411*b636d99dSDavid van Moolenbroek 		return (0);
1412*b636d99dSDavid van Moolenbroek 	if (ndo->ndo_vflag)
1413*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " POST:"));
1414*b636d99dSDavid van Moolenbroek 	if (!(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)))
1415*b636d99dSDavid van Moolenbroek 		return (0);
1416*b636d99dSDavid van Moolenbroek 	if (er)
1417*b636d99dSDavid van Moolenbroek 		return (1);
1418*b636d99dSDavid van Moolenbroek 
1419*b636d99dSDavid van Moolenbroek 	sfp = (struct nfsv3_fsinfo *)dp;
1420*b636d99dSDavid van Moolenbroek 	ND_TCHECK(*sfp);
1421*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, " rtmax %u rtpref %u wtmax %u wtpref %u dtpref %u",
1422*b636d99dSDavid van Moolenbroek 	       EXTRACT_32BITS(&sfp->fs_rtmax),
1423*b636d99dSDavid van Moolenbroek 	       EXTRACT_32BITS(&sfp->fs_rtpref),
1424*b636d99dSDavid van Moolenbroek 	       EXTRACT_32BITS(&sfp->fs_wtmax),
1425*b636d99dSDavid van Moolenbroek 	       EXTRACT_32BITS(&sfp->fs_wtpref),
1426*b636d99dSDavid van Moolenbroek 	       EXTRACT_32BITS(&sfp->fs_dtpref)));
1427*b636d99dSDavid van Moolenbroek 	if (ndo->ndo_vflag) {
1428*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " rtmult %u wtmult %u maxfsz %" PRIu64,
1429*b636d99dSDavid van Moolenbroek 		       EXTRACT_32BITS(&sfp->fs_rtmult),
1430*b636d99dSDavid van Moolenbroek 		       EXTRACT_32BITS(&sfp->fs_wtmult),
1431*b636d99dSDavid van Moolenbroek 		       EXTRACT_64BITS((uint32_t *)&sfp->fs_maxfilesize)));
1432*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " delta %u.%06u ",
1433*b636d99dSDavid van Moolenbroek 		       EXTRACT_32BITS(&sfp->fs_timedelta.nfsv3_sec),
1434*b636d99dSDavid van Moolenbroek 		       EXTRACT_32BITS(&sfp->fs_timedelta.nfsv3_nsec)));
1435*b636d99dSDavid van Moolenbroek 	}
1436*b636d99dSDavid van Moolenbroek 	return (1);
1437*b636d99dSDavid van Moolenbroek trunc:
1438*b636d99dSDavid van Moolenbroek 	return (0);
1439*b636d99dSDavid van Moolenbroek }
1440*b636d99dSDavid van Moolenbroek 
1441*b636d99dSDavid van Moolenbroek static int
parsepathconf(netdissect_options * ndo,const uint32_t * dp)1442*b636d99dSDavid van Moolenbroek parsepathconf(netdissect_options *ndo,
1443*b636d99dSDavid van Moolenbroek               const uint32_t *dp)
1444*b636d99dSDavid van Moolenbroek {
1445*b636d99dSDavid van Moolenbroek 	int er;
1446*b636d99dSDavid van Moolenbroek 	struct nfsv3_pathconf *spp;
1447*b636d99dSDavid van Moolenbroek 
1448*b636d99dSDavid van Moolenbroek 	if (!(dp = parsestatus(ndo, dp, &er)))
1449*b636d99dSDavid van Moolenbroek 		return (0);
1450*b636d99dSDavid van Moolenbroek 	if (ndo->ndo_vflag)
1451*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, " POST:"));
1452*b636d99dSDavid van Moolenbroek 	if (!(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)))
1453*b636d99dSDavid van Moolenbroek 		return (0);
1454*b636d99dSDavid van Moolenbroek 	if (er)
1455*b636d99dSDavid van Moolenbroek 		return (1);
1456*b636d99dSDavid van Moolenbroek 
1457*b636d99dSDavid van Moolenbroek 	spp = (struct nfsv3_pathconf *)dp;
1458*b636d99dSDavid van Moolenbroek 	ND_TCHECK(*spp);
1459*b636d99dSDavid van Moolenbroek 
1460*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, " linkmax %u namemax %u %s %s %s %s",
1461*b636d99dSDavid van Moolenbroek 	       EXTRACT_32BITS(&spp->pc_linkmax),
1462*b636d99dSDavid van Moolenbroek 	       EXTRACT_32BITS(&spp->pc_namemax),
1463*b636d99dSDavid van Moolenbroek 	       EXTRACT_32BITS(&spp->pc_notrunc) ? "notrunc" : "",
1464*b636d99dSDavid van Moolenbroek 	       EXTRACT_32BITS(&spp->pc_chownrestricted) ? "chownres" : "",
1465*b636d99dSDavid van Moolenbroek 	       EXTRACT_32BITS(&spp->pc_caseinsensitive) ? "igncase" : "",
1466*b636d99dSDavid van Moolenbroek 	       EXTRACT_32BITS(&spp->pc_casepreserving) ? "keepcase" : ""));
1467*b636d99dSDavid van Moolenbroek 	return (1);
1468*b636d99dSDavid van Moolenbroek trunc:
1469*b636d99dSDavid van Moolenbroek 	return (0);
1470*b636d99dSDavid van Moolenbroek }
1471*b636d99dSDavid van Moolenbroek 
1472*b636d99dSDavid van Moolenbroek static void
interp_reply(netdissect_options * ndo,const struct sunrpc_msg * rp,uint32_t proc,uint32_t vers,int length)1473*b636d99dSDavid van Moolenbroek interp_reply(netdissect_options *ndo,
1474*b636d99dSDavid van Moolenbroek              const struct sunrpc_msg *rp, uint32_t proc, uint32_t vers, int length)
1475*b636d99dSDavid van Moolenbroek {
1476*b636d99dSDavid van Moolenbroek 	register const uint32_t *dp;
1477*b636d99dSDavid van Moolenbroek 	register int v3;
1478*b636d99dSDavid van Moolenbroek 	int er;
1479*b636d99dSDavid van Moolenbroek 
1480*b636d99dSDavid van Moolenbroek 	v3 = (vers == NFS_VER3);
1481*b636d99dSDavid van Moolenbroek 
1482*b636d99dSDavid van Moolenbroek 	if (!v3 && proc < NFS_NPROCS)
1483*b636d99dSDavid van Moolenbroek 		proc = nfsv3_procid[proc];
1484*b636d99dSDavid van Moolenbroek 
1485*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, " %s", tok2str(nfsproc_str, "proc-%u", proc)));
1486*b636d99dSDavid van Moolenbroek 	switch (proc) {
1487*b636d99dSDavid van Moolenbroek 
1488*b636d99dSDavid van Moolenbroek 	case NFSPROC_GETATTR:
1489*b636d99dSDavid van Moolenbroek 		dp = parserep(ndo, rp, length);
1490*b636d99dSDavid van Moolenbroek 		if (dp != NULL && parseattrstat(ndo, dp, !ndo->ndo_qflag, v3) != 0)
1491*b636d99dSDavid van Moolenbroek 			return;
1492*b636d99dSDavid van Moolenbroek 		break;
1493*b636d99dSDavid van Moolenbroek 
1494*b636d99dSDavid van Moolenbroek 	case NFSPROC_SETATTR:
1495*b636d99dSDavid van Moolenbroek 		if (!(dp = parserep(ndo, rp, length)))
1496*b636d99dSDavid van Moolenbroek 			return;
1497*b636d99dSDavid van Moolenbroek 		if (v3) {
1498*b636d99dSDavid van Moolenbroek 			if (parsewccres(ndo, dp, ndo->ndo_vflag))
1499*b636d99dSDavid van Moolenbroek 				return;
1500*b636d99dSDavid van Moolenbroek 		} else {
1501*b636d99dSDavid van Moolenbroek 			if (parseattrstat(ndo, dp, !ndo->ndo_qflag, 0) != 0)
1502*b636d99dSDavid van Moolenbroek 				return;
1503*b636d99dSDavid van Moolenbroek 		}
1504*b636d99dSDavid van Moolenbroek 		break;
1505*b636d99dSDavid van Moolenbroek 
1506*b636d99dSDavid van Moolenbroek 	case NFSPROC_LOOKUP:
1507*b636d99dSDavid van Moolenbroek 		if (!(dp = parserep(ndo, rp, length)))
1508*b636d99dSDavid van Moolenbroek 			break;
1509*b636d99dSDavid van Moolenbroek 		if (v3) {
1510*b636d99dSDavid van Moolenbroek 			if (!(dp = parsestatus(ndo, dp, &er)))
1511*b636d99dSDavid van Moolenbroek 				break;
1512*b636d99dSDavid van Moolenbroek 			if (er) {
1513*b636d99dSDavid van Moolenbroek 				if (ndo->ndo_vflag > 1) {
1514*b636d99dSDavid van Moolenbroek 					ND_PRINT((ndo, " post dattr:"));
1515*b636d99dSDavid van Moolenbroek 					dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag);
1516*b636d99dSDavid van Moolenbroek 				}
1517*b636d99dSDavid van Moolenbroek 			} else {
1518*b636d99dSDavid van Moolenbroek 				if (!(dp = parsefh(ndo, dp, v3)))
1519*b636d99dSDavid van Moolenbroek 					break;
1520*b636d99dSDavid van Moolenbroek 				if ((dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)) &&
1521*b636d99dSDavid van Moolenbroek 				    ndo->ndo_vflag > 1) {
1522*b636d99dSDavid van Moolenbroek 					ND_PRINT((ndo, " post dattr:"));
1523*b636d99dSDavid van Moolenbroek 					dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag);
1524*b636d99dSDavid van Moolenbroek 				}
1525*b636d99dSDavid van Moolenbroek 			}
1526*b636d99dSDavid van Moolenbroek 			if (dp)
1527*b636d99dSDavid van Moolenbroek 				return;
1528*b636d99dSDavid van Moolenbroek 		} else {
1529*b636d99dSDavid van Moolenbroek 			if (parsediropres(ndo, dp) != 0)
1530*b636d99dSDavid van Moolenbroek 				return;
1531*b636d99dSDavid van Moolenbroek 		}
1532*b636d99dSDavid van Moolenbroek 		break;
1533*b636d99dSDavid van Moolenbroek 
1534*b636d99dSDavid van Moolenbroek 	case NFSPROC_ACCESS:
1535*b636d99dSDavid van Moolenbroek 		if (!(dp = parserep(ndo, rp, length)))
1536*b636d99dSDavid van Moolenbroek 			break;
1537*b636d99dSDavid van Moolenbroek 		if (!(dp = parsestatus(ndo, dp, &er)))
1538*b636d99dSDavid van Moolenbroek 			break;
1539*b636d99dSDavid van Moolenbroek 		if (ndo->ndo_vflag)
1540*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, " attr:"));
1541*b636d99dSDavid van Moolenbroek 		if (!(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)))
1542*b636d99dSDavid van Moolenbroek 			break;
1543*b636d99dSDavid van Moolenbroek 		if (!er)
1544*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, " c %04x", EXTRACT_32BITS(&dp[0])));
1545*b636d99dSDavid van Moolenbroek 		return;
1546*b636d99dSDavid van Moolenbroek 
1547*b636d99dSDavid van Moolenbroek 	case NFSPROC_READLINK:
1548*b636d99dSDavid van Moolenbroek 		dp = parserep(ndo, rp, length);
1549*b636d99dSDavid van Moolenbroek 		if (dp != NULL && parselinkres(ndo, dp, v3) != 0)
1550*b636d99dSDavid van Moolenbroek 			return;
1551*b636d99dSDavid van Moolenbroek 		break;
1552*b636d99dSDavid van Moolenbroek 
1553*b636d99dSDavid van Moolenbroek 	case NFSPROC_READ:
1554*b636d99dSDavid van Moolenbroek 		if (!(dp = parserep(ndo, rp, length)))
1555*b636d99dSDavid van Moolenbroek 			break;
1556*b636d99dSDavid van Moolenbroek 		if (v3) {
1557*b636d99dSDavid van Moolenbroek 			if (!(dp = parsestatus(ndo, dp, &er)))
1558*b636d99dSDavid van Moolenbroek 				break;
1559*b636d99dSDavid van Moolenbroek 			if (!(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)))
1560*b636d99dSDavid van Moolenbroek 				break;
1561*b636d99dSDavid van Moolenbroek 			if (er)
1562*b636d99dSDavid van Moolenbroek 				return;
1563*b636d99dSDavid van Moolenbroek 			if (ndo->ndo_vflag) {
1564*b636d99dSDavid van Moolenbroek 				ND_TCHECK(dp[1]);
1565*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, " %u bytes", EXTRACT_32BITS(&dp[0])));
1566*b636d99dSDavid van Moolenbroek 				if (EXTRACT_32BITS(&dp[1]))
1567*b636d99dSDavid van Moolenbroek 					ND_PRINT((ndo, " EOF"));
1568*b636d99dSDavid van Moolenbroek 			}
1569*b636d99dSDavid van Moolenbroek 			return;
1570*b636d99dSDavid van Moolenbroek 		} else {
1571*b636d99dSDavid van Moolenbroek 			if (parseattrstat(ndo, dp, ndo->ndo_vflag, 0) != 0)
1572*b636d99dSDavid van Moolenbroek 				return;
1573*b636d99dSDavid van Moolenbroek 		}
1574*b636d99dSDavid van Moolenbroek 		break;
1575*b636d99dSDavid van Moolenbroek 
1576*b636d99dSDavid van Moolenbroek 	case NFSPROC_WRITE:
1577*b636d99dSDavid van Moolenbroek 		if (!(dp = parserep(ndo, rp, length)))
1578*b636d99dSDavid van Moolenbroek 			break;
1579*b636d99dSDavid van Moolenbroek 		if (v3) {
1580*b636d99dSDavid van Moolenbroek 			if (!(dp = parsestatus(ndo, dp, &er)))
1581*b636d99dSDavid van Moolenbroek 				break;
1582*b636d99dSDavid van Moolenbroek 			if (!(dp = parse_wcc_data(ndo, dp, ndo->ndo_vflag)))
1583*b636d99dSDavid van Moolenbroek 				break;
1584*b636d99dSDavid van Moolenbroek 			if (er)
1585*b636d99dSDavid van Moolenbroek 				return;
1586*b636d99dSDavid van Moolenbroek 			if (ndo->ndo_vflag) {
1587*b636d99dSDavid van Moolenbroek 				ND_TCHECK(dp[0]);
1588*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, " %u bytes", EXTRACT_32BITS(&dp[0])));
1589*b636d99dSDavid van Moolenbroek 				if (ndo->ndo_vflag > 1) {
1590*b636d99dSDavid van Moolenbroek 					ND_TCHECK(dp[1]);
1591*b636d99dSDavid van Moolenbroek 					ND_PRINT((ndo, " <%s>",
1592*b636d99dSDavid van Moolenbroek 						tok2str(nfsv3_writemodes,
1593*b636d99dSDavid van Moolenbroek 							NULL, EXTRACT_32BITS(&dp[1]))));
1594*b636d99dSDavid van Moolenbroek 				}
1595*b636d99dSDavid van Moolenbroek 				return;
1596*b636d99dSDavid van Moolenbroek 			}
1597*b636d99dSDavid van Moolenbroek 		} else {
1598*b636d99dSDavid van Moolenbroek 			if (parseattrstat(ndo, dp, ndo->ndo_vflag, v3) != 0)
1599*b636d99dSDavid van Moolenbroek 				return;
1600*b636d99dSDavid van Moolenbroek 		}
1601*b636d99dSDavid van Moolenbroek 		break;
1602*b636d99dSDavid van Moolenbroek 
1603*b636d99dSDavid van Moolenbroek 	case NFSPROC_CREATE:
1604*b636d99dSDavid van Moolenbroek 	case NFSPROC_MKDIR:
1605*b636d99dSDavid van Moolenbroek 		if (!(dp = parserep(ndo, rp, length)))
1606*b636d99dSDavid van Moolenbroek 			break;
1607*b636d99dSDavid van Moolenbroek 		if (v3) {
1608*b636d99dSDavid van Moolenbroek 			if (parsecreateopres(ndo, dp, ndo->ndo_vflag) != 0)
1609*b636d99dSDavid van Moolenbroek 				return;
1610*b636d99dSDavid van Moolenbroek 		} else {
1611*b636d99dSDavid van Moolenbroek 			if (parsediropres(ndo, dp) != 0)
1612*b636d99dSDavid van Moolenbroek 				return;
1613*b636d99dSDavid van Moolenbroek 		}
1614*b636d99dSDavid van Moolenbroek 		break;
1615*b636d99dSDavid van Moolenbroek 
1616*b636d99dSDavid van Moolenbroek 	case NFSPROC_SYMLINK:
1617*b636d99dSDavid van Moolenbroek 		if (!(dp = parserep(ndo, rp, length)))
1618*b636d99dSDavid van Moolenbroek 			break;
1619*b636d99dSDavid van Moolenbroek 		if (v3) {
1620*b636d99dSDavid van Moolenbroek 			if (parsecreateopres(ndo, dp, ndo->ndo_vflag) != 0)
1621*b636d99dSDavid van Moolenbroek 				return;
1622*b636d99dSDavid van Moolenbroek 		} else {
1623*b636d99dSDavid van Moolenbroek 			if (parsestatus(ndo, dp, &er) != 0)
1624*b636d99dSDavid van Moolenbroek 				return;
1625*b636d99dSDavid van Moolenbroek 		}
1626*b636d99dSDavid van Moolenbroek 		break;
1627*b636d99dSDavid van Moolenbroek 
1628*b636d99dSDavid van Moolenbroek 	case NFSPROC_MKNOD:
1629*b636d99dSDavid van Moolenbroek 		if (!(dp = parserep(ndo, rp, length)))
1630*b636d99dSDavid van Moolenbroek 			break;
1631*b636d99dSDavid van Moolenbroek 		if (parsecreateopres(ndo, dp, ndo->ndo_vflag) != 0)
1632*b636d99dSDavid van Moolenbroek 			return;
1633*b636d99dSDavid van Moolenbroek 		break;
1634*b636d99dSDavid van Moolenbroek 
1635*b636d99dSDavid van Moolenbroek 	case NFSPROC_REMOVE:
1636*b636d99dSDavid van Moolenbroek 	case NFSPROC_RMDIR:
1637*b636d99dSDavid van Moolenbroek 		if (!(dp = parserep(ndo, rp, length)))
1638*b636d99dSDavid van Moolenbroek 			break;
1639*b636d99dSDavid van Moolenbroek 		if (v3) {
1640*b636d99dSDavid van Moolenbroek 			if (parsewccres(ndo, dp, ndo->ndo_vflag))
1641*b636d99dSDavid van Moolenbroek 				return;
1642*b636d99dSDavid van Moolenbroek 		} else {
1643*b636d99dSDavid van Moolenbroek 			if (parsestatus(ndo, dp, &er) != 0)
1644*b636d99dSDavid van Moolenbroek 				return;
1645*b636d99dSDavid van Moolenbroek 		}
1646*b636d99dSDavid van Moolenbroek 		break;
1647*b636d99dSDavid van Moolenbroek 
1648*b636d99dSDavid van Moolenbroek 	case NFSPROC_RENAME:
1649*b636d99dSDavid van Moolenbroek 		if (!(dp = parserep(ndo, rp, length)))
1650*b636d99dSDavid van Moolenbroek 			break;
1651*b636d99dSDavid van Moolenbroek 		if (v3) {
1652*b636d99dSDavid van Moolenbroek 			if (!(dp = parsestatus(ndo, dp, &er)))
1653*b636d99dSDavid van Moolenbroek 				break;
1654*b636d99dSDavid van Moolenbroek 			if (ndo->ndo_vflag) {
1655*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, " from:"));
1656*b636d99dSDavid van Moolenbroek 				if (!(dp = parse_wcc_data(ndo, dp, ndo->ndo_vflag)))
1657*b636d99dSDavid van Moolenbroek 					break;
1658*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, " to:"));
1659*b636d99dSDavid van Moolenbroek 				if (!(dp = parse_wcc_data(ndo, dp, ndo->ndo_vflag)))
1660*b636d99dSDavid van Moolenbroek 					break;
1661*b636d99dSDavid van Moolenbroek 			}
1662*b636d99dSDavid van Moolenbroek 			return;
1663*b636d99dSDavid van Moolenbroek 		} else {
1664*b636d99dSDavid van Moolenbroek 			if (parsestatus(ndo, dp, &er) != 0)
1665*b636d99dSDavid van Moolenbroek 				return;
1666*b636d99dSDavid van Moolenbroek 		}
1667*b636d99dSDavid van Moolenbroek 		break;
1668*b636d99dSDavid van Moolenbroek 
1669*b636d99dSDavid van Moolenbroek 	case NFSPROC_LINK:
1670*b636d99dSDavid van Moolenbroek 		if (!(dp = parserep(ndo, rp, length)))
1671*b636d99dSDavid van Moolenbroek 			break;
1672*b636d99dSDavid van Moolenbroek 		if (v3) {
1673*b636d99dSDavid van Moolenbroek 			if (!(dp = parsestatus(ndo, dp, &er)))
1674*b636d99dSDavid van Moolenbroek 				break;
1675*b636d99dSDavid van Moolenbroek 			if (ndo->ndo_vflag) {
1676*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, " file POST:"));
1677*b636d99dSDavid van Moolenbroek 				if (!(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)))
1678*b636d99dSDavid van Moolenbroek 					break;
1679*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, " dir:"));
1680*b636d99dSDavid van Moolenbroek 				if (!(dp = parse_wcc_data(ndo, dp, ndo->ndo_vflag)))
1681*b636d99dSDavid van Moolenbroek 					break;
1682*b636d99dSDavid van Moolenbroek 				return;
1683*b636d99dSDavid van Moolenbroek 			}
1684*b636d99dSDavid van Moolenbroek 		} else {
1685*b636d99dSDavid van Moolenbroek 			if (parsestatus(ndo, dp, &er) != 0)
1686*b636d99dSDavid van Moolenbroek 				return;
1687*b636d99dSDavid van Moolenbroek 		}
1688*b636d99dSDavid van Moolenbroek 		break;
1689*b636d99dSDavid van Moolenbroek 
1690*b636d99dSDavid van Moolenbroek 	case NFSPROC_READDIR:
1691*b636d99dSDavid van Moolenbroek 		if (!(dp = parserep(ndo, rp, length)))
1692*b636d99dSDavid van Moolenbroek 			break;
1693*b636d99dSDavid van Moolenbroek 		if (v3) {
1694*b636d99dSDavid van Moolenbroek 			if (parsev3rddirres(ndo, dp, ndo->ndo_vflag))
1695*b636d99dSDavid van Moolenbroek 				return;
1696*b636d99dSDavid van Moolenbroek 		} else {
1697*b636d99dSDavid van Moolenbroek 			if (parserddires(ndo, dp) != 0)
1698*b636d99dSDavid van Moolenbroek 				return;
1699*b636d99dSDavid van Moolenbroek 		}
1700*b636d99dSDavid van Moolenbroek 		break;
1701*b636d99dSDavid van Moolenbroek 
1702*b636d99dSDavid van Moolenbroek 	case NFSPROC_READDIRPLUS:
1703*b636d99dSDavid van Moolenbroek 		if (!(dp = parserep(ndo, rp, length)))
1704*b636d99dSDavid van Moolenbroek 			break;
1705*b636d99dSDavid van Moolenbroek 		if (parsev3rddirres(ndo, dp, ndo->ndo_vflag))
1706*b636d99dSDavid van Moolenbroek 			return;
1707*b636d99dSDavid van Moolenbroek 		break;
1708*b636d99dSDavid van Moolenbroek 
1709*b636d99dSDavid van Moolenbroek 	case NFSPROC_FSSTAT:
1710*b636d99dSDavid van Moolenbroek 		dp = parserep(ndo, rp, length);
1711*b636d99dSDavid van Moolenbroek 		if (dp != NULL && parsestatfs(ndo, dp, v3) != 0)
1712*b636d99dSDavid van Moolenbroek 			return;
1713*b636d99dSDavid van Moolenbroek 		break;
1714*b636d99dSDavid van Moolenbroek 
1715*b636d99dSDavid van Moolenbroek 	case NFSPROC_FSINFO:
1716*b636d99dSDavid van Moolenbroek 		dp = parserep(ndo, rp, length);
1717*b636d99dSDavid van Moolenbroek 		if (dp != NULL && parsefsinfo(ndo, dp) != 0)
1718*b636d99dSDavid van Moolenbroek 			return;
1719*b636d99dSDavid van Moolenbroek 		break;
1720*b636d99dSDavid van Moolenbroek 
1721*b636d99dSDavid van Moolenbroek 	case NFSPROC_PATHCONF:
1722*b636d99dSDavid van Moolenbroek 		dp = parserep(ndo, rp, length);
1723*b636d99dSDavid van Moolenbroek 		if (dp != NULL && parsepathconf(ndo, dp) != 0)
1724*b636d99dSDavid van Moolenbroek 			return;
1725*b636d99dSDavid van Moolenbroek 		break;
1726*b636d99dSDavid van Moolenbroek 
1727*b636d99dSDavid van Moolenbroek 	case NFSPROC_COMMIT:
1728*b636d99dSDavid van Moolenbroek 		dp = parserep(ndo, rp, length);
1729*b636d99dSDavid van Moolenbroek 		if (dp != NULL && parsewccres(ndo, dp, ndo->ndo_vflag) != 0)
1730*b636d99dSDavid van Moolenbroek 			return;
1731*b636d99dSDavid van Moolenbroek 		break;
1732*b636d99dSDavid van Moolenbroek 
1733*b636d99dSDavid van Moolenbroek 	default:
1734*b636d99dSDavid van Moolenbroek 		return;
1735*b636d99dSDavid van Moolenbroek 	}
1736*b636d99dSDavid van Moolenbroek trunc:
1737*b636d99dSDavid van Moolenbroek 	if (!nfserr)
1738*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "%s", tstr));
1739*b636d99dSDavid van Moolenbroek }
1740