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