Deleted Added
full compact
print-nfs.c (17681) print-nfs.c (18976)
1/*
2 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and

--- 14 unchanged lines hidden (view full) ---

23static char rcsid[] =
24 "@(#) $Header: print-nfs.c,v 1.56 96/07/23 14:17:25 leres Exp $ (LBL)";
25#endif
26
27#include <sys/param.h>
28#include <sys/time.h>
29#include <sys/socket.h>
30
1/*
2 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and

--- 14 unchanged lines hidden (view full) ---

23static char rcsid[] =
24 "@(#) $Header: print-nfs.c,v 1.56 96/07/23 14:17:25 leres Exp $ (LBL)";
25#endif
26
27#include <sys/param.h>
28#include <sys/time.h>
29#include <sys/socket.h>
30
31#if __STDC__
32struct mbuf;
33struct rtentry;
34#endif
35#include <net/if.h>
36
37#include <netinet/in.h>
38#include <netinet/if_ether.h>
39#include <netinet/in_systm.h>
40#include <netinet/ip.h>
41#include <netinet/ip_var.h>
42
31#include <net/if.h>
32
33#include <netinet/in.h>
34#include <netinet/if_ether.h>
35#include <netinet/in_systm.h>
36#include <netinet/ip.h>
37#include <netinet/ip_var.h>
38
39#ifdef SOLARIS
40#include <tiuser.h>
41#endif
43#include <rpc/rpc.h>
42#include <rpc/rpc.h>
43#include <rpc/pmap_prot.h>
44
45#include <ctype.h>
44
45#include <ctype.h>
46#include <pcap.h>
47#include <stdio.h>
46#include <stdio.h>
47#include <errno.h>
48#include <string.h>
49
50#include "interface.h"
51#include "addrtoname.h"
48#include <string.h>
49
50#include "interface.h"
51#include "addrtoname.h"
52#include "extract.h" /* must come after interface.h */
52
53
53#include "nfsv2.h"
54#include "nfs.h"
54#include "nfsfh.h"
55
55#include "nfsfh.h"
56
56static void nfs_printfh(const u_int32_t *);
57static void nfs_printfh(const u_int32_t *, const int);
57static void xid_map_enter(const struct rpc_msg *, const struct ip *);
58static void xid_map_enter(const struct rpc_msg *, const struct ip *);
58static int32_t xid_map_find(const struct rpc_msg *, const struct ip *);
59static void interp_reply(const struct rpc_msg *, u_int32_t, u_int);
59static int32_t xid_map_find(const struct rpc_msg *, const struct ip *, u_int32_t *,
60 u_int32_t *);
61static void interp_reply(const struct rpc_msg *, u_int32_t, u_int32_t, int);
62static const u_int32_t *parse_post_op_attr(const u_int32_t *, int);
60
63
64/*
65 * Mapping of old NFS Version 2 RPC numbers to generic numbers.
66 */
67u_int32_t nfsv3_procid[NFS_NPROCS] = {
68 NFSPROC_NULL,
69 NFSPROC_GETATTR,
70 NFSPROC_SETATTR,
71 NFSPROC_NOOP,
72 NFSPROC_LOOKUP,
73 NFSPROC_READLINK,
74 NFSPROC_READ,
75 NFSPROC_NOOP,
76 NFSPROC_WRITE,
77 NFSPROC_CREATE,
78 NFSPROC_REMOVE,
79 NFSPROC_RENAME,
80 NFSPROC_LINK,
81 NFSPROC_SYMLINK,
82 NFSPROC_MKDIR,
83 NFSPROC_RMDIR,
84 NFSPROC_READDIR,
85 NFSPROC_FSSTAT,
86 NFSPROC_NOOP,
87 NFSPROC_NOOP,
88 NFSPROC_NOOP,
89 NFSPROC_NOOP,
90 NFSPROC_NOOP,
91 NFSPROC_NOOP,
92 NFSPROC_NOOP,
93 NFSPROC_NOOP
94};
95
96const char *nfsv3_writemodes[NFSV3WRITE_NMODES] = {
97 "unstable",
98 "datasync",
99 "filesync"
100};
101
102static struct tok type2str[] = {
103 { NFNON, "NON" },
104 { NFREG, "REG" },
105 { NFDIR, "DIR" },
106 { NFBLK, "BLK" },
107 { NFCHR, "CHR" },
108 { NFLNK, "LNK" },
109 { NFFIFO, "FIFO" },
110 { 0, NULL }
111};
112
113/*
114 * Print out a 64-bit integer. This appears to be different on each system,
115 * try to make the best of it. The integer stored as 2 consecutive XDR
116 * encoded 32-bit integers, to which a pointer is passed.
117 *
118 * Assume that a system that has INT64_FORMAT defined, has a 64-bit
119 * integer datatype and can print it.
120 */
121
122#define UNSIGNED 0
123#define SIGNED 1
124#define HEX 2
125
126#define INT64_FORMAT "%qd"
127#define U_INT64_FORMAT "%qu"
128#define HEX_INT64_FORMAT "%qx"
129
130int print_int64(const u_int32_t *dp, int how)
131{
132 static char buf[32];
133#ifdef INT64_FORMAT
134 u_int64_t res;
135
136 res = ((u_int64_t)ntohl(dp[0]) << 32) | (u_int64_t)ntohl(dp[1]);
137 switch (how) {
138 case SIGNED:
139 printf(INT64_FORMAT, res);
140 break;
141 case UNSIGNED:
142 printf(U_INT64_FORMAT, res);
143 break;
144 case HEX:
145 printf(HEX_INT64_FORMAT, res);
146 break;
147 default:
148 return (0);
149 }
150#else
151 /*
152 * XXX - throw upper 32 bits away.
153 * Could also go for hex: printf("0x%x%x", dp[0], dp[1]);
154 */
155 if (how == SIGNED)
156 printf("%ld", (int)dp[1]);
157 else
158 printf("%lu", (unsigned int)dp[1]);
159#endif
160 return 1;
161}
162
163static const u_int32_t *
164parse_sattr3(const u_int32_t *dp, struct nfsv3_sattr *sa3)
165{
166 register const u_int32_t *ep = (u_int32_t *)snapend;
167
168 if (dp + 1 > ep)
169 return (0);
170 if ((sa3->sa_modeset = ntohl(*dp++))) {
171 if (dp + 1 > ep)
172 return (0);
173 sa3->sa_mode = ntohl(*dp++);
174 }
175
176 if (dp + 1 > ep)
177 return (0);
178 if ((sa3->sa_uidset = ntohl(*dp++))) {
179 if (dp + 1 > ep)
180 return (0);
181 sa3->sa_uid = ntohl(*dp++);
182 }
183
184 if (dp + 1 > ep)
185 return (0);
186 if ((sa3->sa_gidset = ntohl(*dp++))) {
187 if (dp + 1 > ep)
188 return (0);
189 sa3->sa_gid = ntohl(*dp++);
190 }
191
192 if (dp + 1 > ep)
193 return (0);
194 if ((sa3->sa_sizeset = ntohl(*dp++))) {
195 if (dp + 1 > ep)
196 return (0);
197 sa3->sa_size = ntohl(*dp++);
198 }
199
200 if (dp + 1 > ep)
201 return (0);
202 if ((sa3->sa_atimetype = ntohl(*dp++)) == NFSV3SATTRTIME_TOCLIENT) {
203 if (dp + 2 > ep)
204 return (0);
205 sa3->sa_atime.nfsv3_sec = ntohl(*dp++);
206 sa3->sa_atime.nfsv3_nsec = ntohl(*dp++);
207 }
208
209 if (dp + 1 > ep)
210 return (0);
211 if ((sa3->sa_mtimetype = ntohl(*dp++)) == NFSV3SATTRTIME_TOCLIENT) {
212 if (dp + 2 > ep)
213 return (0);
214 sa3->sa_mtime.nfsv3_sec = ntohl(*dp++);
215 sa3->sa_mtime.nfsv3_nsec = ntohl(*dp++);
216 }
217
218 return dp;
219}
220
61void
221void
222print_sattr3(const struct nfsv3_sattr *sa3, int verbose)
223{
224 if (sa3->sa_modeset)
225 printf(" mode %o", sa3->sa_mode);
226 if (sa3->sa_uidset)
227 printf(" uid %u", sa3->sa_uid);
228 if (sa3->sa_gidset)
229 printf(" gid %u", sa3->sa_gid);
230 if (verbose > 1) {
231 if (sa3->sa_atimetype == NFSV3SATTRTIME_TOCLIENT)
232 printf(" atime %u.%06u", sa3->sa_atime.nfsv3_sec,
233 sa3->sa_atime.nfsv3_nsec);
234 if (sa3->sa_mtimetype == NFSV3SATTRTIME_TOCLIENT)
235 printf(" mtime %u.%06u", sa3->sa_mtime.nfsv3_sec,
236 sa3->sa_mtime.nfsv3_nsec);
237 }
238}
239
240void
62nfsreply_print(register const u_char *bp, u_int length,
63 register const u_char *bp2)
64{
65 register const struct rpc_msg *rp;
66 register const struct ip *ip;
241nfsreply_print(register const u_char *bp, u_int length,
242 register const u_char *bp2)
243{
244 register const struct rpc_msg *rp;
245 register const struct ip *ip;
67 int32_t proc;
246 u_int32_t proc, vers;
68
69 rp = (const struct rpc_msg *)bp;
70 ip = (const struct ip *)bp2;
71
72 if (!nflag)
73 (void)printf("%s.nfs > %s.%x: reply %s %d",
74 ipaddr_string(&ip->ip_src),
75 ipaddr_string(&ip->ip_dst),

--- 6 unchanged lines hidden (view full) ---

82 ipaddr_string(&ip->ip_src),
83 NFS_PORT,
84 ipaddr_string(&ip->ip_dst),
85 (u_int32_t)ntohl(rp->rm_xid),
86 ntohl(rp->rm_reply.rp_stat) == MSG_ACCEPTED?
87 "ok":"ERR",
88 length);
89
247
248 rp = (const struct rpc_msg *)bp;
249 ip = (const struct ip *)bp2;
250
251 if (!nflag)
252 (void)printf("%s.nfs > %s.%x: reply %s %d",
253 ipaddr_string(&ip->ip_src),
254 ipaddr_string(&ip->ip_dst),

--- 6 unchanged lines hidden (view full) ---

261 ipaddr_string(&ip->ip_src),
262 NFS_PORT,
263 ipaddr_string(&ip->ip_dst),
264 (u_int32_t)ntohl(rp->rm_xid),
265 ntohl(rp->rm_reply.rp_stat) == MSG_ACCEPTED?
266 "ok":"ERR",
267 length);
268
90 proc = xid_map_find(rp, ip);
91 if (proc >= 0)
92 interp_reply(rp, (u_int32_t)proc, length);
269 if (xid_map_find(rp, ip, &proc, &vers) >= 0)
270 interp_reply(rp, proc, vers, length);
93}
94
95/*
96 * Return a pointer to the first file handle in the packet.
97 * If the packet was truncated, return 0.
98 */
99static const u_int32_t *
271}
272
273/*
274 * Return a pointer to the first file handle in the packet.
275 * If the packet was truncated, return 0.
276 */
277static const u_int32_t *
100parsereq(register const struct rpc_msg *rp, register u_int length)
278parsereq(register const struct rpc_msg *rp, register int length)
101{
279{
102 register const u_int32_t *dp;
280 register const u_int32_t *dp = (u_int32_t *)&rp->rm_call.cb_cred;
281 register const u_int32_t *ep = (u_int32_t *)snapend;
103 register u_int len;
104
282 register u_int len;
283
284 if (&dp[2] >= ep)
285 return (0);
105 /*
106 * find the start of the req data (if we captured it)
107 */
286 /*
287 * find the start of the req data (if we captured it)
288 */
108 dp = (u_int32_t *)&rp->rm_call.cb_cred;
109 TCHECK(dp[1]);
110 len = ntohl(dp[1]);
111 if (len < length) {
112 dp += (len + (2 * sizeof(*dp) + 3)) / sizeof(*dp);
113 TCHECK(dp[1]);
289 len = ntohl(dp[1]);
290 if (dp < ep && len < length) {
291 dp += (len + (2 * sizeof(u_int32_t) + 3)) / sizeof(u_int32_t);
114 len = ntohl(dp[1]);
292 len = ntohl(dp[1]);
115 if (len < length) {
116 dp += (len + (2 * sizeof(*dp) + 3)) / sizeof(*dp);
117 TCHECK2(dp[0], 0);
118 return (dp);
293 if ((dp < ep) && (len < length)) {
294 dp += (len + (2 * sizeof(u_int32_t) + 3)) /
295 sizeof(u_int32_t);
296 if (dp < ep)
297 return (dp);
119 }
120 }
298 }
299 }
121trunc:
122 return (0);
123}
124
125/*
126 * Print out an NFS file handle and return a pointer to following word.
127 * If packet was truncated, return 0.
128 */
129static const u_int32_t *
300 return (0);
301}
302
303/*
304 * Print out an NFS file handle and return a pointer to following word.
305 * If packet was truncated, return 0.
306 */
307static const u_int32_t *
130parsefh(register const u_int32_t *dp)
308parsefh(register const u_int32_t *dp, int v3)
131{
309{
132 if (dp + 8 <= (u_int32_t *)snapend) {
133 nfs_printfh(dp);
134 return (dp + 8);
310 int len;
311
312 if (v3) {
313 if (dp + 1 > (u_int32_t *)snapend)
314 return (0);
315 len = (int)ntohl(*dp) / 4;
316 dp++;
317 } else
318 len = NFSX_V2FH / 4;
319
320 if (dp + len <= (u_int32_t *)snapend) {
321 nfs_printfh(dp, len);
322 return (dp + len);
135 }
136 return (0);
137}
138
139/*
140 * Print out a file name and return pointer to 32-bit word past it.
141 * If packet was truncated, return 0.
142 */

--- 12 unchanged lines hidden (view full) ---

155 NTOHL(len);
156
157 cp = (u_char *)dp;
158 /* Update 32-bit pointer (NFS filenames padded to 32-bit boundaries) */
159 dp += ((len + 3) & ~3) / sizeof(*dp);
160 if ((u_char *)dp > snapend)
161 return (0);
162 /* XXX seems like we should be checking the length */
323 }
324 return (0);
325}
326
327/*
328 * Print out a file name and return pointer to 32-bit word past it.
329 * If packet was truncated, return 0.
330 */

--- 12 unchanged lines hidden (view full) ---

343 NTOHL(len);
344
345 cp = (u_char *)dp;
346 /* Update 32-bit pointer (NFS filenames padded to 32-bit boundaries) */
347 dp += ((len + 3) & ~3) / sizeof(*dp);
348 if ((u_char *)dp > snapend)
349 return (0);
350 /* XXX seems like we should be checking the length */
163 putchar('"');
164 (void) fn_printn(cp, len, NULL);
351 (void) fn_printn(cp, len, NULL);
165 putchar('"');
166
167 return (dp);
168}
169
170/*
171 * Print out file handle and file name.
172 * Return pointer to 32-bit word past file name.
173 * If packet was truncated (or there was some other error), return 0.
174 */
175static const u_int32_t *
352
353 return (dp);
354}
355
356/*
357 * Print out file handle and file name.
358 * Return pointer to 32-bit word past file name.
359 * If packet was truncated (or there was some other error), return 0.
360 */
361static const u_int32_t *
176parsefhn(register const u_int32_t *dp)
362parsefhn(register const u_int32_t *dp, int v3)
177{
363{
178 dp = parsefh(dp);
364 dp = parsefh(dp, v3);
179 if (dp == 0)
180 return (0);
181 putchar(' ');
182 return (parsefn(dp));
183}
184
185void
186nfsreq_print(register const u_char *bp, u_int length,
187 register const u_char *bp2)
188{
189 register const struct rpc_msg *rp;
190 register const struct ip *ip;
191 register const u_int32_t *dp;
365 if (dp == 0)
366 return (0);
367 putchar(' ');
368 return (parsefn(dp));
369}
370
371void
372nfsreq_print(register const u_char *bp, u_int length,
373 register const u_char *bp2)
374{
375 register const struct rpc_msg *rp;
376 register const struct ip *ip;
377 register const u_int32_t *dp;
378 register const u_char *ep;
379 nfstype type;
380 int proc, v3;
381 struct nfsv3_sattr sa3;
192
193 rp = (const struct rpc_msg *)bp;
194 ip = (const struct ip *)bp2;
382
383 rp = (const struct rpc_msg *)bp;
384 ip = (const struct ip *)bp2;
385 ep = snapend;
195 if (!nflag)
196 (void)printf("%s.%x > %s.nfs: %d",
197 ipaddr_string(&ip->ip_src),
198 (u_int32_t)ntohl(rp->rm_xid),
199 ipaddr_string(&ip->ip_dst),
200 length);
201 else
202 (void)printf("%s.%x > %s.%x: %d",
203 ipaddr_string(&ip->ip_src),
204 (u_int32_t)ntohl(rp->rm_xid),
205 ipaddr_string(&ip->ip_dst),
206 NFS_PORT,
207 length);
208
209 xid_map_enter(rp, ip); /* record proc number for later on */
210
386 if (!nflag)
387 (void)printf("%s.%x > %s.nfs: %d",
388 ipaddr_string(&ip->ip_src),
389 (u_int32_t)ntohl(rp->rm_xid),
390 ipaddr_string(&ip->ip_dst),
391 length);
392 else
393 (void)printf("%s.%x > %s.%x: %d",
394 ipaddr_string(&ip->ip_src),
395 (u_int32_t)ntohl(rp->rm_xid),
396 ipaddr_string(&ip->ip_dst),
397 NFS_PORT,
398 length);
399
400 xid_map_enter(rp, ip); /* record proc number for later on */
401
211 switch (ntohl(rp->rm_call.cb_proc)) {
212#ifdef NFSPROC_NOOP
402 v3 = (ntohl(rp->rm_call.cb_vers) == NFS_VER3);
403 proc = ntohl(rp->rm_call.cb_proc);
404
405 if (!v3 && proc < NFS_NPROCS)
406 proc = nfsv3_procid[proc];
407
408 switch (proc) {
213 case NFSPROC_NOOP:
214 printf(" nop");
215 return;
409 case NFSPROC_NOOP:
410 printf(" nop");
411 return;
216#else
217#define NFSPROC_NOOP -1
218#endif
219 case NFSPROC_NULL:
220 printf(" null");
221 return;
222
223 case NFSPROC_GETATTR:
224 printf(" getattr");
412 case NFSPROC_NULL:
413 printf(" null");
414 return;
415
416 case NFSPROC_GETATTR:
417 printf(" getattr");
225 if ((dp = parsereq(rp, length)) != 0 && parsefh(dp) != 0)
418 if ((dp = parsereq(rp, length)) != 0 && parsefh(dp, v3) != 0)
226 return;
227 break;
228
229 case NFSPROC_SETATTR:
230 printf(" setattr");
419 return;
420 break;
421
422 case NFSPROC_SETATTR:
423 printf(" setattr");
231 if ((dp = parsereq(rp, length)) != 0 && parsefh(dp) != 0)
424 if ((dp = parsereq(rp, length)) != 0 && parsefh(dp, v3) != 0)
232 return;
233 break;
234
425 return;
426 break;
427
235#if NFSPROC_ROOT != NFSPROC_NOOP
236 case NFSPROC_ROOT:
237 printf(" root");
238 break;
239#endif
240 case NFSPROC_LOOKUP:
241 printf(" lookup");
428 case NFSPROC_LOOKUP:
429 printf(" lookup");
242 if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp) != 0)
430 if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp, v3) != 0)
243 return;
244 break;
245
431 return;
432 break;
433
434 case NFSPROC_ACCESS:
435 printf(" access");
436 if ((dp = parsereq(rp, length)) != 0 &&
437 (dp = parsefh(dp, v3)) != 0) {
438 TCHECK(*dp);
439 printf(" %04x", ntohl(dp[0]));
440 return;
441 }
442 break;
443
246 case NFSPROC_READLINK:
247 printf(" readlink");
444 case NFSPROC_READLINK:
445 printf(" readlink");
248 if ((dp = parsereq(rp, length)) != 0 && parsefh(dp) != 0)
446 if ((dp = parsereq(rp, length)) != 0 && parsefh(dp, v3) != 0)
249 return;
250 break;
251
252 case NFSPROC_READ:
253 printf(" read");
254 if ((dp = parsereq(rp, length)) != 0 &&
447 return;
448 break;
449
450 case NFSPROC_READ:
451 printf(" read");
452 if ((dp = parsereq(rp, length)) != 0 &&
255 (dp = parsefh(dp)) != 0) {
256 TCHECK2(dp[0], 3 * sizeof(*dp));
257 printf(" %u bytes @ %u",
258 (u_int32_t)ntohl(dp[1]),
259 (u_int32_t)ntohl(dp[0]));
453 (dp = parsefh(dp, v3)) != 0) {
454 if (v3) {
455 TCHECK2(*dp, 3 * sizeof(*dp));
456 printf(" %lu bytes @ ", ntohl(dp[2]));
457 print_int64(dp, UNSIGNED);
458 } else {
459 TCHECK2(*dp, 2 * sizeof(*dp));
460 printf(" %lu bytes @ %lu",
461 ntohl(dp[1]), ntohl(dp[0]));
462 }
260 return;
261 }
262 break;
263
463 return;
464 }
465 break;
466
264#if NFSPROC_WRITECACHE != NFSPROC_NOOP
265 case NFSPROC_WRITECACHE:
266 printf(" writecache");
267 if ((dp = parsereq(rp, length)) != 0 &&
268 (dp = parsefh(dp)) != 0) {
269 TCHECK2(dp[0], 4 * sizeof(*dp));
270 printf(" %u (%u) bytes @ %u (%u)",
271 (u_int32_t)ntohl(dp[3]),
272 (u_int32_t)ntohl(dp[2]),
273 (u_int32_t)ntohl(dp[1]),
274 (u_int32_t)ntohl(dp[0]));
275 return;
276 }
277 break;
278#endif
279 case NFSPROC_WRITE:
280 printf(" write");
281 if ((dp = parsereq(rp, length)) != 0 &&
467 case NFSPROC_WRITE:
468 printf(" write");
469 if ((dp = parsereq(rp, length)) != 0 &&
282 (dp = parsefh(dp)) != 0) {
283 TCHECK2(dp[0], 4 * sizeof(*dp));
284 printf(" %u (%u) bytes @ %u (%u)",
285 (u_int32_t)ntohl(dp[3]),
286 (u_int32_t)ntohl(dp[2]),
287 (u_int32_t)ntohl(dp[1]),
288 (u_int32_t)ntohl(dp[0]));
470 (dp = parsefh(dp, v3)) != 0) {
471 if (v3) {
472 TCHECK2(*dp, 3 * sizeof(*dp));
473 printf(" %lu bytes @ ", ntohl(dp[4]));
474 print_int64(dp, UNSIGNED);
475 if (vflag) {
476 dp += 3;
477 TCHECK2(*dp, sizeof(*dp));
478 printf(" <%s>",
479 nfsv3_writemodes[ntohl(*dp)]);
480 }
481 } else {
482 TCHECK2(*dp, 4 * sizeof(*dp));
483 printf(" %lu (%lu) bytes @ %lu (%lu)",
484 ntohl(dp[3]), ntohl(dp[2]),
485 ntohl(dp[1]), ntohl(dp[0]));
486 }
289 return;
290 }
291 break;
292
293 case NFSPROC_CREATE:
294 printf(" create");
487 return;
488 }
489 break;
490
491 case NFSPROC_CREATE:
492 printf(" create");
295 if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp) != 0)
493 if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp, v3) != 0)
296 return;
297 break;
298
494 return;
495 break;
496
497 case NFSPROC_MKDIR:
498 printf(" mkdir");
499 if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp, v3) != 0)
500 return;
501 break;
502
503 case NFSPROC_SYMLINK:
504 printf(" symlink");
505 if ((dp = parsereq(rp, length)) != 0 &&
506 (dp = parsefhn(dp, v3)) != 0) {
507 fputs(" -> ", stdout);
508 if (v3 && (dp = parse_sattr3(dp, &sa3)) == 0)
509 break;
510 if (parsefn(dp) == 0)
511 break;
512 if (v3 && vflag)
513 print_sattr3(&sa3, vflag);
514 return;
515 }
516 break;
517
518 case NFSPROC_MKNOD:
519 printf(" mknod");
520 if ((dp = parsereq(rp, length)) != 0 &&
521 (dp = parsefhn(dp, v3)) != 0) {
522 if (dp + 1 > (u_int32_t *)snapend)
523 break;
524 type = (nfstype)ntohl(*dp++);
525 if ((dp = parse_sattr3(dp, &sa3)) == 0)
526 break;
527 printf(" %s", tok2str(type2str, "unk-ft %d", type));
528 if (vflag && (type == NFCHR || type == NFBLK)) {
529 if (dp + 2 > (u_int32_t *)snapend)
530 break;
531 printf(" %u/%u", ntohl(dp[0]), ntohl(dp[1]));
532 dp += 2;
533 }
534 if (vflag)
535 print_sattr3(&sa3, vflag);
536 return;
537 }
538 break;
539
299 case NFSPROC_REMOVE:
300 printf(" remove");
540 case NFSPROC_REMOVE:
541 printf(" remove");
301 if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp) != 0)
542 if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp, v3) != 0)
302 return;
303 break;
304
543 return;
544 break;
545
546 case NFSPROC_RMDIR:
547 printf(" rmdir");
548 if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp, v3) != 0)
549 return;
550 break;
551
305 case NFSPROC_RENAME:
306 printf(" rename");
307 if ((dp = parsereq(rp, length)) != 0 &&
552 case NFSPROC_RENAME:
553 printf(" rename");
554 if ((dp = parsereq(rp, length)) != 0 &&
308 (dp = parsefhn(dp)) != 0) {
555 (dp = parsefhn(dp, v3)) != 0) {
309 fputs(" ->", stdout);
556 fputs(" ->", stdout);
310 if (parsefhn(dp) != 0)
557 if (parsefhn(dp, v3) != 0)
311 return;
312 }
313 break;
314
315 case NFSPROC_LINK:
316 printf(" link");
317 if ((dp = parsereq(rp, length)) != 0 &&
558 return;
559 }
560 break;
561
562 case NFSPROC_LINK:
563 printf(" link");
564 if ((dp = parsereq(rp, length)) != 0 &&
318 (dp = parsefh(dp)) != 0) {
565 (dp = parsefh(dp, v3)) != 0) {
319 fputs(" ->", stdout);
566 fputs(" ->", stdout);
320 if (parsefhn(dp) != 0)
567 if (parsefhn(dp, v3) != 0)
321 return;
322 }
323 break;
324
568 return;
569 }
570 break;
571
325 case NFSPROC_SYMLINK:
326 printf(" symlink");
572 case NFSPROC_READDIR:
573 printf(" readdir");
327 if ((dp = parsereq(rp, length)) != 0 &&
574 if ((dp = parsereq(rp, length)) != 0 &&
328 (dp = parsefhn(dp)) != 0) {
329 fputs(" -> ", stdout);
330 if (parsefn(dp) != 0)
331 return;
575 (dp = parsefh(dp, v3)) != 0) {
576 if (v3) {
577 TCHECK2(*dp, 20);
578 /*
579 * We shouldn't really try to interpret the
580 * offset cookie here.
581 */
582 printf(" %lu bytes @ ", ntohl(dp[4]));
583 print_int64(dp, SIGNED);
584 if (vflag)
585 printf(" verf %08lx%08lx", dp[2],
586 dp[3]);
587 } else {
588 TCHECK2(*dp, 2 * sizeof(*dp));
589 /*
590 * Print the offset as signed, since -1 is
591 * common, but offsets > 2^31 aren't.
592 */
593 printf(" %lu bytes @ %ld", ntohl(dp[1]),
594 ntohl(dp[0]));
595 }
596 return;
332 }
333 break;
334
597 }
598 break;
599
335 case NFSPROC_MKDIR:
336 printf(" mkdir");
337 if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp) != 0)
600 case NFSPROC_READDIRPLUS:
601 printf(" readdirplus");
602 if ((dp = parsereq(rp, length)) != 0 &&
603 (dp = parsefh(dp, v3)) != 0) {
604 TCHECK2(*dp, 20);
605 /*
606 * We don't try to interpret the offset
607 * cookie here.
608 */
609 printf(" %lu bytes @ ", ntohl(dp[4]));
610 print_int64(dp, SIGNED);
611 if (vflag)
612 printf(" max %lu verf %08lx%08lx",
613 ntohl(dp[5]), dp[2], dp[3]);
338 return;
614 return;
615 }
339 break;
340
616 break;
617
341 case NFSPROC_RMDIR:
342 printf(" rmdir");
343 if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp) != 0)
618 case NFSPROC_FSSTAT:
619 printf(" fsstat");
620 if ((dp = parsereq(rp, length)) != 0 && parsefh(dp, v3) != 0)
344 return;
345 break;
346
621 return;
622 break;
623
347 case NFSPROC_READDIR:
348 printf(" readdir");
624 case NFSPROC_FSINFO:
625 printf(" fsinfo");
626 break;
627
628 case NFSPROC_PATHCONF:
629 printf(" pathconf");
630 break;
631
632 case NFSPROC_COMMIT:
633 printf(" commit");
349 if ((dp = parsereq(rp, length)) != 0 &&
634 if ((dp = parsereq(rp, length)) != 0 &&
350 (dp = parsefh(dp)) != 0) {
351 TCHECK2(dp[0], 2 * sizeof(*dp));
352 /*
353 * Print the offset as signed, since -1 is common,
354 * but offsets > 2^31 aren't.
355 */
356 printf(" %u bytes @ %d",
357 (u_int32_t)ntohl(dp[1]),
358 (u_int32_t)ntohl(dp[0]));
635 (dp = parsefh(dp, v3)) != 0) {
636 printf(" %lu bytes @ ", ntohl(dp[2]));
637 print_int64(dp, UNSIGNED);
359 return;
360 }
361 break;
362
638 return;
639 }
640 break;
641
363 case NFSPROC_STATFS:
364 printf(" statfs");
365 if ((dp = parsereq(rp, length)) != 0 && parsefh(dp) != 0)
366 return;
367 break;
368
369 default:
642 default:
370 printf(" proc-%u", (u_int32_t)ntohl(rp->rm_call.cb_proc));
643 printf(" proc-%lu", ntohl(rp->rm_call.cb_proc));
371 return;
372 }
373trunc:
374 fputs(" [|nfs]", stdout);
375}
376
377/*
378 * Print out an NFS file handle.
379 * We assume packet was not truncated before the end of the
380 * file handle pointed to by dp.
381 *
382 * Note: new version (using portable file-handle parser) doesn't produce
383 * generation number. It probably could be made to do that, with some
384 * additional hacking on the parser code.
385 */
386static void
644 return;
645 }
646trunc:
647 fputs(" [|nfs]", stdout);
648}
649
650/*
651 * Print out an NFS file handle.
652 * We assume packet was not truncated before the end of the
653 * file handle pointed to by dp.
654 *
655 * Note: new version (using portable file-handle parser) doesn't produce
656 * generation number. It probably could be made to do that, with some
657 * additional hacking on the parser code.
658 */
659static void
387nfs_printfh(register const u_int32_t *dp)
660nfs_printfh(register const u_int32_t *dp, const int len)
388{
389 my_fsid fsid;
390 ino_t ino;
391 char *sfsname = NULL;
392
661{
662 my_fsid fsid;
663 ino_t ino;
664 char *sfsname = NULL;
665
393 Parse_fh((caddr_t*)dp, &fsid, &ino, NULL, &sfsname, 0);
666 Parse_fh((caddr_t*)dp, len, &fsid, &ino, NULL, &sfsname, 0);
394
395 if (sfsname) {
396 /* file system ID is ASCII, not numeric, for this server OS */
667
668 if (sfsname) {
669 /* file system ID is ASCII, not numeric, for this server OS */
397 static char temp[NFS_FHSIZE+1];
670 static char temp[NFSX_V3FHMAX+1];
398
399 /* Make sure string is null-terminated */
671
672 /* Make sure string is null-terminated */
400 strncpy(temp, sfsname, NFS_FHSIZE);
673 strncpy(temp, sfsname, NFSX_V3FHMAX);
401 /* Remove trailing spaces */
402 sfsname = strchr(temp, ' ');
403 if (sfsname)
404 *sfsname = 0;
405
406 (void)printf(" fh %s/%u", temp, (u_int32_t)ino);
407 }
408 else {

--- 10 unchanged lines hidden (view full) ---

419 * the reply.
420 */
421
422struct xid_map_entry {
423 u_int32_t xid; /* transaction ID (net order) */
424 struct in_addr client; /* client IP address (net order) */
425 struct in_addr server; /* server IP address (net order) */
426 u_int32_t proc; /* call proc number (host order) */
674 /* Remove trailing spaces */
675 sfsname = strchr(temp, ' ');
676 if (sfsname)
677 *sfsname = 0;
678
679 (void)printf(" fh %s/%u", temp, (u_int32_t)ino);
680 }
681 else {

--- 10 unchanged lines hidden (view full) ---

692 * the reply.
693 */
694
695struct xid_map_entry {
696 u_int32_t xid; /* transaction ID (net order) */
697 struct in_addr client; /* client IP address (net order) */
698 struct in_addr server; /* server IP address (net order) */
699 u_int32_t proc; /* call proc number (host order) */
700 u_int32_t vers; /* program version (host order) */
427};
428
429/*
430 * Map entries are kept in an array that we manage as a ring;
431 * new entries are always added at the tail of the ring. Initially,
432 * all the entries are zero and hence don't match anything.
433 */
434

--- 13 unchanged lines hidden (view full) ---

448
449 if (++xid_map_next >= XIDMAPSIZE)
450 xid_map_next = 0;
451
452 xmep->xid = rp->rm_xid;
453 xmep->client = ip->ip_src;
454 xmep->server = ip->ip_dst;
455 xmep->proc = ntohl(rp->rm_call.cb_proc);
701};
702
703/*
704 * Map entries are kept in an array that we manage as a ring;
705 * new entries are always added at the tail of the ring. Initially,
706 * all the entries are zero and hence don't match anything.
707 */
708

--- 13 unchanged lines hidden (view full) ---

722
723 if (++xid_map_next >= XIDMAPSIZE)
724 xid_map_next = 0;
725
726 xmep->xid = rp->rm_xid;
727 xmep->client = ip->ip_src;
728 xmep->server = ip->ip_dst;
729 xmep->proc = ntohl(rp->rm_call.cb_proc);
730 xmep->vers = ntohl(rp->rm_call.cb_vers);
456}
457
458/* Returns NFSPROC_xxx or -1 on failure */
731}
732
733/* Returns NFSPROC_xxx or -1 on failure */
459static int32_t
460xid_map_find(const struct rpc_msg *rp, const struct ip *ip)
734static int
735xid_map_find(const struct rpc_msg *rp, const struct ip *ip, u_int32_t *proc,
736 u_int32_t *vers)
461{
462 int i;
463 struct xid_map_entry *xmep;
464 u_int32_t xid = rp->rm_xid;
465 u_int32_t clip = ip->ip_dst.s_addr;
466 u_int32_t sip = ip->ip_src.s_addr;
467
468 /* Start searching from where we last left off */
469 i = xid_map_hint;
470 do {
471 xmep = &xid_map[i];
472 if (xmep->xid == xid && xmep->client.s_addr == clip &&
473 xmep->server.s_addr == sip) {
474 /* match */
475 xid_map_hint = i;
737{
738 int i;
739 struct xid_map_entry *xmep;
740 u_int32_t xid = rp->rm_xid;
741 u_int32_t clip = ip->ip_dst.s_addr;
742 u_int32_t sip = ip->ip_src.s_addr;
743
744 /* Start searching from where we last left off */
745 i = xid_map_hint;
746 do {
747 xmep = &xid_map[i];
748 if (xmep->xid == xid && xmep->client.s_addr == clip &&
749 xmep->server.s_addr == sip) {
750 /* match */
751 xid_map_hint = i;
476 return ((int32_t)xmep->proc);
752 *proc = xmep->proc;
753 *vers = xmep->vers;
754 return 0;
477 }
478 if (++i >= XIDMAPSIZE)
479 i = 0;
480 } while (i != xid_map_hint);
481
482 /* search failed */
483 return(-1);
484}
485
486/*
487 * Routines for parsing reply packets
488 */
489
490/*
491 * Return a pointer to the beginning of the actual results.
492 * If the packet was truncated, return 0.
493 */
494static const u_int32_t *
755 }
756 if (++i >= XIDMAPSIZE)
757 i = 0;
758 } while (i != xid_map_hint);
759
760 /* search failed */
761 return(-1);
762}
763
764/*
765 * Routines for parsing reply packets
766 */
767
768/*
769 * Return a pointer to the beginning of the actual results.
770 * If the packet was truncated, return 0.
771 */
772static const u_int32_t *
495parserep(register const struct rpc_msg *rp, register u_int length)
773parserep(register const struct rpc_msg *rp, register int length)
496{
497 register const u_int32_t *dp;
774{
775 register const u_int32_t *dp;
498 u_int len;
776 register const u_int32_t *ep = (const u_int32_t *)snapend;
777 int len;
499 enum accept_stat astat;
500
501 /*
502 * Portability note:
503 * Here we find the address of the ar_verf credentials.
504 * Originally, this calculation was
505 * dp = (u_int32_t *)&rp->rm_reply.rp_acpt.ar_verf
506 * On the wire, the rp_acpt field starts immediately after
507 * the (32 bit) rp_stat field. However, rp_acpt (which is a
508 * "struct accepted_reply") contains a "struct opaque_auth",
509 * whose internal representation contains a pointer, so on a
510 * 64-bit machine the compiler inserts 32 bits of padding
511 * before rp->rm_reply.rp_acpt.ar_verf. So, we cannot use
512 * the internal representation to parse the on-the-wire
513 * representation. Instead, we skip past the rp_stat field,
514 * which is an "enum" and so occupies one 32-bit word.
515 */
516 dp = ((const u_int32_t *)&rp->rm_reply) + 1;
778 enum accept_stat astat;
779
780 /*
781 * Portability note:
782 * Here we find the address of the ar_verf credentials.
783 * Originally, this calculation was
784 * dp = (u_int32_t *)&rp->rm_reply.rp_acpt.ar_verf
785 * On the wire, the rp_acpt field starts immediately after
786 * the (32 bit) rp_stat field. However, rp_acpt (which is a
787 * "struct accepted_reply") contains a "struct opaque_auth",
788 * whose internal representation contains a pointer, so on a
789 * 64-bit machine the compiler inserts 32 bits of padding
790 * before rp->rm_reply.rp_acpt.ar_verf. So, we cannot use
791 * the internal representation to parse the on-the-wire
792 * representation. Instead, we skip past the rp_stat field,
793 * which is an "enum" and so occupies one 32-bit word.
794 */
795 dp = ((const u_int32_t *)&rp->rm_reply) + 1;
517 TCHECK2(dp[0], 1);
796 if (&dp[1] >= ep)
518 return(0);
519 len = ntohl(dp[1]);
520 if (len >= length)
521 return(0);
522 /*
523 * skip past the ar_verf credentials.
524 */
525 dp += (len + (2*sizeof(u_int32_t) + 3)) / sizeof(u_int32_t);
797 return(0);
798 len = ntohl(dp[1]);
799 if (len >= length)
800 return(0);
801 /*
802 * skip past the ar_verf credentials.
803 */
804 dp += (len + (2*sizeof(u_int32_t) + 3)) / sizeof(u_int32_t);
526 TCHECK2(dp[0], 0);
805 if (dp >= ep)
806 return(0);
527
528 /*
529 * now we can check the ar_stat field
530 */
531 astat = ntohl(*(enum accept_stat *)dp);
532 switch (astat) {
533
534 case SUCCESS:

--- 19 unchanged lines hidden (view full) ---

554 printf(" SYSTEM_ERR");
555 return(0);
556
557 default:
558 printf(" ar_stat %d", astat);
559 return(0);
560 }
561 /* successful return */
807
808 /*
809 * now we can check the ar_stat field
810 */
811 astat = ntohl(*(enum accept_stat *)dp);
812 switch (astat) {
813
814 case SUCCESS:

--- 19 unchanged lines hidden (view full) ---

834 printf(" SYSTEM_ERR");
835 return(0);
836
837 default:
838 printf(" ar_stat %d", astat);
839 return(0);
840 }
841 /* successful return */
562 if ((sizeof(astat) + ((u_char *)dp)) < snapend)
842 if ((sizeof(astat) + ((char *)dp)) < (char *)ep)
563 return((u_int32_t *) (sizeof(astat) + ((char *)dp)));
564
843 return((u_int32_t *) (sizeof(astat) + ((char *)dp)));
844
565trunc:
566 return (0);
567}
568
845 return (0);
846}
847
848#define T2CHECK(p, l) if ((u_char *)(p) > ((u_char *)snapend) - l) return(0)
849
850/*
851 * Not all systems have strerror().
852 */
853static char *
854strerr(int errno)
855{
856
857 return (strerror(errno));
858}
859
569static const u_int32_t *
860static const u_int32_t *
570parsestatus(const u_int32_t *dp)
861parsestatus(const u_int32_t *dp, int *er)
571{
862{
572 int errnum;
863 int errno;
864 T2CHECK(dp, 4);
573
865
574 TCHECK(dp[0]);
575 errnum = ntohl(dp[0]);
576 if (errnum != 0) {
866 errno = ntohl(dp[0]);
867 if (er)
868 *er = errno;
869 if (errno != 0 && !qflag) {
577 char *errmsg;
578
870 char *errmsg;
871
579 if (qflag)
580 return(0);
581
582 errmsg = pcap_strerror(errnum);
583 printf(" ERROR: %s", errmsg);
584 return(0);
872 errmsg = strerr(errno);
873 if (errmsg)
874 printf(" ERROR: '%s'", errmsg);
875 else
876 printf(" ERROR: %d", errno);
585 }
586 return (dp + 1);
877 }
878 return (dp + 1);
587trunc:
588 return (0);
589}
590
879}
880
591static struct tok type2str[] = {
592 { NFNON, "NON" },
593 { NFREG, "REG" },
594 { NFDIR, "DIR" },
595 { NFBLK, "BLK" },
596 { NFCHR, "CHR" },
597 { NFLNK, "LNK" },
598 { 0, NULL }
599};
600
601static const u_int32_t *
881static const u_int32_t *
602parsefattr(const u_int32_t *dp, int verbose)
882parsefattr(const u_int32_t *dp, int verbose, int v3)
603{
883{
604 const struct nfsv2_fattr *fap;
884 const struct nfs_fattr *fap;
605
885
606 fap = (const struct nfsv2_fattr *)dp;
886 T2CHECK(dp, 5 * sizeof(*dp));
887
888 fap = (const struct nfs_fattr *)dp;
607 if (verbose) {
889 if (verbose) {
608 TCHECK(fap->fa_nfssize);
609 printf(" %s %o ids %u/%u sz %u ",
610 tok2str(type2str, "unk-ft %d ",
611 (u_int32_t)ntohl(fap->fa_type)),
612 (u_int32_t)ntohl(fap->fa_mode),
613 (u_int32_t)ntohl(fap->fa_uid),
614 (u_int32_t)ntohl(fap->fa_gid),
615 (u_int32_t)ntohl(fap->fa_nfssize));
890 printf(" %s %o ids %d/%d",
891 tok2str(type2str, "unk-ft %d ", ntohl(fap->fa_type)),
892 ntohl(fap->fa_mode), ntohl(fap->fa_uid),
893 ntohl(fap->fa_gid));
894 if (v3) {
895 T2CHECK(dp, 7 * sizeof(*dp));
896 printf(" sz ");
897 print_int64((u_int32_t *)&fap->fa3_size, UNSIGNED);
898 putchar(' ');
899 }
900 else {
901 T2CHECK(dp, 6 * sizeof(*dp));
902 printf(" sz %d ", ntohl(fap->fa2_size));
903 }
616 }
617 /* print lots more stuff */
618 if (verbose > 1) {
904 }
905 /* print lots more stuff */
906 if (verbose > 1) {
619 TCHECK(fap->fa_nfsfileid);
620 printf("nlink %u rdev %x fsid %x nodeid %x a/m/ctime ",
621 (u_int32_t)ntohl(fap->fa_nlink),
622 (u_int32_t)ntohl(fap->fa_nfsrdev),
623 (u_int32_t)ntohl(fap->fa_nfsfsid),
624 (u_int32_t)ntohl(fap->fa_nfsfileid));
625 TCHECK(fap->fa_nfsatime);
626 printf("%u.%06u ",
627 (u_int32_t)ntohl(fap->fa_nfsatime.nfs_sec),
628 (u_int32_t)ntohl(fap->fa_nfsatime.nfs_usec));
629 TCHECK(fap->fa_nfsmtime);
630 printf("%u.%06u ",
631 (u_int32_t)ntohl(fap->fa_nfsmtime.nfs_sec),
632 (u_int32_t)ntohl(fap->fa_nfsmtime.nfs_usec));
633 TCHECK(fap->fa_nfsctime);
634 printf("%u.%06u ",
635 (u_int32_t)ntohl(fap->fa_nfsctime.nfs_sec),
636 (u_int32_t)ntohl(fap->fa_nfsctime.nfs_usec));
907 if (v3) {
908 T2CHECK(dp, 64);
909 printf("nlink %d rdev %d/%d ",
910 ntohl(fap->fa_nlink),
911 ntohl(fap->fa3_rdev.specdata1),
912 ntohl(fap->fa3_rdev.specdata2));
913 printf("fsid ");
914 print_int64((u_int32_t *)&fap->fa2_fsid, HEX);
915 printf(" nodeid ");
916 print_int64((u_int32_t *)&fap->fa2_fileid, HEX);
917 printf(" a/m/ctime %u.%06u ",
918 ntohl(fap->fa3_atime.nfsv3_sec),
919 ntohl(fap->fa3_atime.nfsv3_nsec));
920 printf("%u.%06u ",
921 ntohl(fap->fa3_mtime.nfsv3_sec),
922 ntohl(fap->fa3_mtime.nfsv3_nsec));
923 printf("%u.%06u ",
924 ntohl(fap->fa3_ctime.nfsv3_sec),
925 ntohl(fap->fa3_ctime.nfsv3_nsec));
926 } else {
927 T2CHECK(dp, 48);
928 printf("nlink %d rdev %x fsid %x nodeid %x a/m/ctime ",
929 ntohl(fap->fa_nlink), ntohl(fap->fa2_rdev),
930 ntohl(fap->fa2_fsid), ntohl(fap->fa2_fileid));
931 printf("%u.%06u ",
932 ntohl(fap->fa2_atime.nfsv2_sec),
933 ntohl(fap->fa2_atime.nfsv2_usec));
934 printf("%u.%06u ",
935 ntohl(fap->fa2_mtime.nfsv2_sec),
936 ntohl(fap->fa2_mtime.nfsv2_usec));
937 printf("%u.%06u ",
938 ntohl(fap->fa2_ctime.nfsv2_sec),
939 ntohl(fap->fa2_ctime.nfsv2_usec));
940 }
637 }
941 }
638 return ((const u_int32_t *)&fap[1]);
639trunc:
640 return (NULL);
942 return ((const u_int32_t *)((unsigned char *)dp +
943 (v3 ? NFSX_V3FATTR : NFSX_V2FATTR)));
641}
642
643static int
944}
945
946static int
644parseattrstat(const u_int32_t *dp, int verbose)
947parseattrstat(const u_int32_t *dp, int verbose, int v3)
645{
948{
646 dp = parsestatus(dp);
647 if (dp == NULL)
949 int er;
950
951 dp = parsestatus(dp, &er);
952 if (dp == NULL || er)
648 return (0);
649
953 return (0);
954
650 return (parsefattr(dp, verbose) != NULL);
955 return ((long)parsefattr(dp, verbose, v3));
651}
652
653static int
654parsediropres(const u_int32_t *dp)
655{
956}
957
958static int
959parsediropres(const u_int32_t *dp)
960{
656 dp = parsestatus(dp);
657 if (dp == NULL)
961 int er;
962
963 if (!(dp = parsestatus(dp, &er)) || er)
658 return (0);
659
964 return (0);
965
660 dp = parsefh(dp);
966 dp = parsefh(dp, 0);
661 if (dp == NULL)
662 return (0);
663
967 if (dp == NULL)
968 return (0);
969
664 return (parsefattr(dp, vflag) != NULL);
970 return (parsefattr(dp, vflag, 0) != NULL);
665}
666
667static int
971}
972
973static int
668parselinkres(const u_int32_t *dp)
974parselinkres(const u_int32_t *dp, int v3)
669{
975{
670 dp = parsestatus(dp);
671 if (dp == NULL)
672 return(0);
976 int er;
673
977
978 dp = parsestatus(dp, &er);
979 if (dp == NULL || er)
980 return(0);
981 if (v3 && !(dp = parse_post_op_attr(dp, vflag)))
982 return (0);
674 putchar(' ');
675 return (parsefn(dp) != NULL);
676}
677
678static int
983 putchar(' ');
984 return (parsefn(dp) != NULL);
985}
986
987static int
679parsestatfs(const u_int32_t *dp)
988parsestatfs(const u_int32_t *dp, int v3)
680{
989{
681 const struct nfsv2_statfs *sfsp;
990 const struct nfs_statfs *sfsp;
991 int er;
682
992
683 dp = parsestatus(dp);
684 if (dp == NULL)
993 dp = parsestatus(dp, &er);
994 if (dp == NULL || (!v3 && er))
685 return(0);
686
995 return(0);
996
687 if (!qflag) {
688 sfsp = (const struct nfsv2_statfs *)dp;
689 TCHECK(sfsp->sf_bavail);
690 printf(" tsize %u bsize %u blocks %u bfree %u bavail %u",
691 (u_int32_t)ntohl(sfsp->sf_tsize),
692 (u_int32_t)ntohl(sfsp->sf_bsize),
693 (u_int32_t)ntohl(sfsp->sf_blocks),
694 (u_int32_t)ntohl(sfsp->sf_bfree),
695 (u_int32_t)ntohl(sfsp->sf_bavail));
997 if (qflag)
998 return(1);
999
1000 if (v3) {
1001 if (vflag)
1002 printf(" POST:");
1003 if (!(dp = parse_post_op_attr(dp, vflag)))
1004 return (0);
696 }
697
1005 }
1006
1007 T2CHECK(dp, (v3 ? NFSX_V3STATFS : NFSX_V2STATFS));
1008
1009 sfsp = (const struct nfs_statfs *)dp;
1010
1011 if (v3) {
1012 printf(" tbytes ");
1013 print_int64((u_int32_t *)&sfsp->sf_tbytes, UNSIGNED);
1014 printf(" fbytes ");
1015 print_int64((u_int32_t *)&sfsp->sf_fbytes, UNSIGNED);
1016 printf(" abytes ");
1017 print_int64((u_int32_t *)&sfsp->sf_abytes, UNSIGNED);
1018 if (vflag) {
1019 printf(" tfiles ");
1020 print_int64((u_int32_t *)&sfsp->sf_tfiles, UNSIGNED);
1021 printf(" ffiles ");
1022 print_int64((u_int32_t *)&sfsp->sf_ffiles, UNSIGNED);
1023 printf(" afiles ");
1024 print_int64((u_int32_t *)&sfsp->sf_afiles, UNSIGNED);
1025 printf(" invar %lu", ntohl(sfsp->sf_invarsec));
1026 }
1027 } else {
1028 printf(" tsize %d bsize %d blocks %d bfree %d bavail %d",
1029 ntohl(sfsp->sf_tsize), ntohl(sfsp->sf_bsize),
1030 ntohl(sfsp->sf_blocks), ntohl(sfsp->sf_bfree),
1031 ntohl(sfsp->sf_bavail));
1032 }
1033
698 return (1);
1034 return (1);
699trunc:
700 return (0);
701}
702
703static int
704parserddires(const u_int32_t *dp)
705{
1035}
1036
1037static int
1038parserddires(const u_int32_t *dp)
1039{
706 dp = parsestatus(dp);
707 if (dp == 0)
1040 int er;
1041
1042 dp = parsestatus(dp, &er);
1043 if (dp == 0 || er)
708 return (0);
1044 return (0);
709 if (!qflag) {
710 TCHECK(dp[0]);
711 printf(" offset %x", (u_int32_t)ntohl(dp[0]));
712 TCHECK(dp[1]);
713 printf(" size %u", (u_int32_t)ntohl(dp[1]));
714 TCHECK(dp[2]);
715 if (dp[2] != 0)
716 printf(" eof");
1045 if (qflag)
1046 return (1);
1047
1048 T2CHECK(dp, 12);
1049 printf(" offset %x size %d ", ntohl(dp[0]), ntohl(dp[1]));
1050 if (dp[2] != 0)
1051 printf("eof");
1052
1053 return (1);
1054}
1055
1056static const u_int32_t *
1057parse_wcc_attr(const u_int32_t *dp)
1058{
1059 printf(" sz ");
1060 print_int64(dp, UNSIGNED);
1061 printf(" mtime %u.%06u ctime %u.%06u", ntohl(dp[2]), ntohl(dp[3]),
1062 ntohl(dp[4]), ntohl(dp[5]));
1063 return (dp + 6);
1064}
1065
1066/*
1067 * Pre operation attributes. Print only if vflag > 1.
1068 */
1069static const u_int32_t *
1070parse_pre_op_attr(const u_int32_t *dp, int verbose)
1071{
1072 T2CHECK(dp, 4);
1073 if (!ntohl(dp[0]))
1074 return (dp + 1);
1075 dp++;
1076 T2CHECK(dp, 24);
1077 if (verbose > 1) {
1078 return parse_wcc_attr(dp);
1079 } else {
1080 /* If not verbose enough, just skip over wcc_attr */
1081 return (dp + 6);
717 }
1082 }
1083}
718
1084
1085/*
1086 * Post operation attributes are printed if vflag >= 1
1087 */
1088static const u_int32_t *
1089parse_post_op_attr(const u_int32_t *dp, int verbose)
1090{
1091 T2CHECK(dp, 4);
1092 if (!ntohl(dp[0]))
1093 return (dp + 1);
1094 dp++;
1095 if (verbose) {
1096 return parsefattr(dp, verbose, 1);
1097 } else
1098 return (dp + (NFSX_V3FATTR / sizeof (u_int32_t)));
1099}
1100
1101static const u_int32_t *
1102parse_wcc_data(const u_int32_t *dp, int verbose)
1103{
1104 if (verbose > 1)
1105 printf(" PRE:");
1106 if (!(dp = parse_pre_op_attr(dp, verbose)))
1107 return (0);
1108
1109 if (verbose)
1110 printf(" POST:");
1111 return parse_post_op_attr(dp, verbose);
1112}
1113
1114static const u_int32_t *
1115parsecreateopres(const u_int32_t *dp, int verbose)
1116{
1117 int er;
1118
1119 if (!(dp = parsestatus(dp, &er)))
1120 return (0);
1121 if (er)
1122 dp = parse_wcc_data(dp, verbose);
1123 else {
1124 T2CHECK(dp, 4);
1125 if (!ntohl(dp[0]))
1126 return (dp + 1);
1127 dp++;
1128 if (!(dp = parsefh(dp, 1)))
1129 return (0);
1130 if (verbose) {
1131 if (!(dp = parse_post_op_attr(dp, verbose)))
1132 return (0);
1133 if (vflag > 1) {
1134 printf("dir attr:");
1135 dp = parse_wcc_data(dp, verbose);
1136 }
1137 }
1138 }
1139 return (dp);
1140}
1141
1142static int
1143parsewccres(const u_int32_t *dp, int verbose)
1144{
1145 int er;
1146
1147 if (!(dp = parsestatus(dp, &er)))
1148 return (0);
1149 return parse_wcc_data(dp, verbose) != 0;
1150}
1151
1152static const u_int32_t *
1153parsev3rddirres(const u_int32_t *dp, int verbose)
1154{
1155 int er;
1156
1157 if (!(dp = parsestatus(dp, &er)))
1158 return (0);
1159 if (vflag)
1160 printf(" POST:");
1161 if (!(dp = parse_post_op_attr(dp, verbose)))
1162 return (0);
1163 if (er)
1164 return dp;
1165 if (vflag) {
1166 T2CHECK(dp, 8);
1167 printf(" verf %08lx%08lx", dp[0], dp[1]);
1168 dp += 2;
1169 }
1170 return dp;
1171}
1172
1173static int
1174parsefsinfo(const u_int32_t *dp)
1175{
1176 struct nfsv3_fsinfo *sfp;
1177 int er;
1178
1179 if (!(dp = parsestatus(dp, &er)))
1180 return (0);
1181 if (vflag)
1182 printf(" POST:");
1183 if (!(dp = parse_post_op_attr(dp, vflag)))
1184 return (0);
1185 if (er)
1186 return (1);
1187
1188 T2CHECK(dp, sizeof (struct nfsv3_fsinfo));
1189
1190 sfp = (struct nfsv3_fsinfo *)dp;
1191 printf(" rtmax %lu rtpref %lu wtmax %lu wtpref %lu dtpref %lu",
1192 ntohl(sfp->fs_rtmax), ntohl(sfp->fs_rtpref),
1193 ntohl(sfp->fs_wtmax), ntohl(sfp->fs_wtpref),
1194 ntohl(sfp->fs_dtpref));
1195 if (vflag) {
1196 printf(" rtmult %lu wtmult %lu maxfsz ",
1197 ntohl(sfp->fs_rtmult), ntohl(sfp->fs_wtmult));
1198 print_int64((u_int32_t *)&sfp->fs_maxfilesize, UNSIGNED);
1199 printf(" delta %u.%06u ", ntohl(sfp->fs_timedelta.nfsv3_sec),
1200 ntohl(sfp->fs_timedelta.nfsv3_nsec));
1201 }
719 return (1);
1202 return (1);
720trunc:
721 return (0);
722}
723
1203}
1204
1205static int
1206parsepathconf(const u_int32_t *dp)
1207{
1208 int er;
1209 struct nfsv3_pathconf *spp;
1210
1211 if (!(dp = parsestatus(dp, &er)))
1212 return (0);
1213 if (vflag)
1214 printf(" POST:");
1215 if (!(dp = parse_post_op_attr(dp, vflag)))
1216 return (0);
1217 if (er)
1218 return (1);
1219
1220 T2CHECK(dp, sizeof (struct nfsv3_pathconf));
1221
1222 spp = (struct nfsv3_pathconf *)dp;
1223
1224 printf(" linkmax %lu namemax %lu %s %s %s %s",
1225 ntohl(spp->pc_linkmax),
1226 ntohl(spp->pc_namemax),
1227 ntohl(spp->pc_notrunc) ? "notrunc" : "",
1228 ntohl(spp->pc_chownrestricted) ? "chownres" : "",
1229 ntohl(spp->pc_caseinsensitive) ? "igncase" : "",
1230 ntohl(spp->pc_casepreserving) ? "keepcase" : "");
1231 return (0);
1232}
1233
724static void
1234static void
725interp_reply(const struct rpc_msg *rp, u_int32_t proc, u_int length)
1235interp_reply(const struct rpc_msg *rp, u_int32_t proc, u_int32_t vers, int length)
726{
727 register const u_int32_t *dp;
1236{
1237 register const u_int32_t *dp;
1238 register int v3;
1239 register const u_char *ep = snapend;
1240 int er;
728
1241
1242 v3 = (vers == NFS_VER3);
1243
1244 if (!v3 && proc < NFS_NPROCS)
1245 proc = nfsv3_procid[proc];
1246
729 switch (proc) {
730
1247 switch (proc) {
1248
731#ifdef NFSPROC_NOOP
732 case NFSPROC_NOOP:
733 printf(" nop");
734 return;
1249 case NFSPROC_NOOP:
1250 printf(" nop");
1251 return;
735#else
736#define NFSPROC_NOOP -1
737#endif
1252
738 case NFSPROC_NULL:
739 printf(" null");
740 return;
741
742 case NFSPROC_GETATTR:
743 printf(" getattr");
744 dp = parserep(rp, length);
1253 case NFSPROC_NULL:
1254 printf(" null");
1255 return;
1256
1257 case NFSPROC_GETATTR:
1258 printf(" getattr");
1259 dp = parserep(rp, length);
745 if (dp != 0 && parseattrstat(dp, !qflag) != 0)
1260 if (dp != 0 && parseattrstat(dp, !qflag, v3) != 0)
746 return;
747 break;
748
749 case NFSPROC_SETATTR:
750 printf(" setattr");
1261 return;
1262 break;
1263
1264 case NFSPROC_SETATTR:
1265 printf(" setattr");
751 dp = parserep(rp, length);
752 if (dp != 0 && parseattrstat(dp, !qflag) != 0)
1266 if (!(dp = parserep(rp, length)))
753 return;
1267 return;
1268 if (v3) {
1269 if (parsewccres(dp, vflag))
1270 return;
1271 } else {
1272 if (parseattrstat(dp, !qflag, 0) != 0)
1273 return;
1274 }
754 break;
755
1275 break;
1276
756#if NFSPROC_ROOT != NFSPROC_NOOP
757 case NFSPROC_ROOT:
758 printf(" root");
759 break;
760#endif
761 case NFSPROC_LOOKUP:
762 printf(" lookup");
1277 case NFSPROC_LOOKUP:
1278 printf(" lookup");
763 dp = parserep(rp, length);
764 if (dp != 0 && parsediropres(dp) != 0)
765 return;
1279 if (!(dp = parserep(rp, length)))
1280 break;
1281 if (v3) {
1282 if (!(dp = parsestatus(dp, &er)))
1283 break;
1284 if (er) {
1285 if (vflag > 1) {
1286 printf(" post dattr:");
1287 dp = parse_post_op_attr(dp, vflag);
1288 }
1289 } else {
1290 if (!(dp = parsefh(dp, v3)))
1291 break;
1292 if ((dp = parse_post_op_attr(dp, vflag)) &&
1293 vflag > 1) {
1294 printf(" post dattr:");
1295 dp = parse_post_op_attr(dp, vflag);
1296 }
1297 }
1298 if (dp)
1299 return;
1300 } else {
1301 if (parsediropres(dp) != 0)
1302 return;
1303 }
766 break;
767
1304 break;
1305
1306 case NFSPROC_ACCESS:
1307 printf(" access");
1308 dp = parserep(rp, length);
1309 if (!(dp = parsestatus(dp, &er)))
1310 break;
1311 if (vflag)
1312 printf(" attr:");
1313 if (!(dp = parse_post_op_attr(dp, vflag)))
1314 break;
1315 if (!er)
1316 printf(" c %04x", ntohl(dp[0]));
1317 return;
1318
768 case NFSPROC_READLINK:
769 printf(" readlink");
770 dp = parserep(rp, length);
1319 case NFSPROC_READLINK:
1320 printf(" readlink");
1321 dp = parserep(rp, length);
771 if (dp != 0 && parselinkres(dp) != 0)
1322 if (dp != 0 && parselinkres(dp, v3) != 0)
772 return;
773 break;
774
775 case NFSPROC_READ:
776 printf(" read");
1323 return;
1324 break;
1325
1326 case NFSPROC_READ:
1327 printf(" read");
777 dp = parserep(rp, length);
778 if (dp != 0 && parseattrstat(dp, vflag) != 0)
1328 if (!(dp = parserep(rp, length)))
1329 break;
1330 if (v3) {
1331 if (!(dp = parsestatus(dp, &er)))
1332 break;
1333 if (!(dp = parse_post_op_attr(dp, vflag)))
1334 break;
1335 if (er)
1336 return;
1337 if (vflag) {
1338 TCHECK2(*dp, 8);
1339 printf("%lu bytes", ntohl(dp[0]));
1340 if (ntohl(dp[1]))
1341 printf(" EOF");
1342 }
779 return;
1343 return;
1344 } else {
1345 if (parseattrstat(dp, vflag, 0) != 0)
1346 return;
1347 }
780 break;
781
1348 break;
1349
782#if NFSPROC_WRITECACHE != NFSPROC_NOOP
783 case NFSPROC_WRITECACHE:
784 printf(" writecache");
785 break;
786#endif
787 case NFSPROC_WRITE:
788 printf(" write");
1350 case NFSPROC_WRITE:
1351 printf(" write");
789 dp = parserep(rp, length);
790 if (dp != 0 && parseattrstat(dp, vflag) != 0)
791 return;
1352 if (!(dp = parserep(rp, length)))
1353 break;
1354 if (v3) {
1355 if (!(dp = parsestatus(dp, &er)))
1356 break;
1357 if (!(dp = parse_wcc_data(dp, vflag)))
1358 break;
1359 if (er)
1360 return;
1361 if (vflag) {
1362 TCHECK2(*dp, 4);
1363 printf("%lu bytes", ntohl(dp[0]));
1364 if (vflag > 1) {
1365 TCHECK2(*dp, 4);
1366 printf(" <%s>",
1367 nfsv3_writemodes[ntohl(dp[1])]);
1368 }
1369 return;
1370 }
1371 } else {
1372 if (parseattrstat(dp, vflag, v3) != 0)
1373 return;
1374 }
792 break;
793
794 case NFSPROC_CREATE:
795 printf(" create");
1375 break;
1376
1377 case NFSPROC_CREATE:
1378 printf(" create");
796 dp = parserep(rp, length);
797 if (dp != 0 && parsediropres(dp) != 0)
1379 if (!(dp = parserep(rp, length)))
1380 break;
1381 if (v3) {
1382 if (parsecreateopres(dp, vflag) != 0)
1383 return;
1384 } else {
1385 if (parsediropres(dp) != 0)
1386 return;
1387 }
1388 break;
1389
1390 case NFSPROC_MKDIR:
1391 printf(" mkdir");
1392 if (!(dp = parserep(rp, length)))
1393 break;
1394 if (v3) {
1395 if (parsecreateopres(dp, vflag) != 0)
1396 return;
1397 } else {
1398 if (parsediropres(dp) != 0)
1399 return;
1400 }
1401 break;
1402
1403 case NFSPROC_SYMLINK:
1404 printf(" symlink");
1405 if (!(dp = parserep(rp, length)))
1406 break;
1407 if (v3) {
1408 if (parsecreateopres(dp, vflag) != 0)
1409 return;
1410 } else {
1411 if (parsestatus(dp, &er) != 0)
1412 return;
1413 }
1414 break;
1415
1416 case NFSPROC_MKNOD:
1417 printf(" mknod");
1418 if (!(dp = parserep(rp, length)))
1419 break;
1420 if (parsecreateopres(dp, vflag) != 0)
798 return;
799 break;
800
801 case NFSPROC_REMOVE:
802 printf(" remove");
1421 return;
1422 break;
1423
1424 case NFSPROC_REMOVE:
1425 printf(" remove");
803 dp = parserep(rp, length);
804 if (dp != 0 && parsestatus(dp) != 0)
805 return;
1426 if (!(dp = parserep(rp, length)))
1427 break;
1428 if (v3) {
1429 if (parsewccres(dp, vflag))
1430 return;
1431 } else {
1432 if (parsestatus(dp, &er) != 0)
1433 return;
1434 }
806 break;
807
1435 break;
1436
1437 case NFSPROC_RMDIR:
1438 printf(" rmdir");
1439 if (!(dp = parserep(rp, length)))
1440 break;
1441 if (v3) {
1442 if (parsewccres(dp, vflag))
1443 return;
1444 } else {
1445 if (parsestatus(dp, &er) != 0)
1446 return;
1447 }
1448 break;
1449
808 case NFSPROC_RENAME:
809 printf(" rename");
1450 case NFSPROC_RENAME:
1451 printf(" rename");
810 dp = parserep(rp, length);
811 if (dp != 0 && parsestatus(dp) != 0)
1452 if (!(dp = parserep(rp, length)))
1453 break;
1454 if (v3) {
1455 if (!(dp = parsestatus(dp, &er)))
1456 break;
1457 if (vflag) {
1458 printf(" from:");
1459 if (!(dp = parse_wcc_data(dp, vflag)))
1460 break;
1461 printf(" to:");
1462 if (!(dp = parse_wcc_data(dp, vflag)))
1463 break;
1464 }
812 return;
1465 return;
1466 } else {
1467 if (parsestatus(dp, &er) != 0)
1468 return;
1469 }
813 break;
814
815 case NFSPROC_LINK:
816 printf(" link");
1470 break;
1471
1472 case NFSPROC_LINK:
1473 printf(" link");
817 dp = parserep(rp, length);
818 if (dp != 0 && parsestatus(dp) != 0)
819 return;
1474 if (!(dp = parserep(rp, length)))
1475 break;
1476 if (v3) {
1477 if (!(dp = parsestatus(dp, &er)))
1478 break;
1479 if (vflag) {
1480 printf(" file POST:");
1481 if (!(dp = parse_post_op_attr(dp, vflag)))
1482 break;
1483 printf(" dir:");
1484 if (!(dp = parse_wcc_data(dp, vflag)))
1485 break;
1486 return;
1487 }
1488 } else {
1489 if (parsestatus(dp, &er) != 0)
1490 return;
1491 }
820 break;
821
1492 break;
1493
822 case NFSPROC_SYMLINK:
823 printf(" symlink");
824 dp = parserep(rp, length);
825 if (dp != 0 && parsestatus(dp) != 0)
1494 case NFSPROC_READDIR:
1495 printf(" readdir");
1496 if (!(dp = parserep(rp, length)))
1497 break;
1498 if (v3) {
1499 if (parsev3rddirres(dp, vflag))
1500 return;
1501 } else {
1502 if (parserddires(dp) != 0)
1503 return;
1504 }
1505 break;
1506
1507 case NFSPROC_READDIRPLUS:
1508 printf(" readdirplus");
1509 if (!(dp = parserep(rp, length)))
1510 break;
1511 if (parsev3rddirres(dp, vflag))
826 return;
827 break;
828
1512 return;
1513 break;
1514
829 case NFSPROC_MKDIR:
830 printf(" mkdir");
1515 case NFSPROC_FSSTAT:
1516 printf(" fsstat");
831 dp = parserep(rp, length);
1517 dp = parserep(rp, length);
832 if (dp != 0 && parsediropres(dp) != 0)
1518 if (dp != 0 && parsestatfs(dp, v3) != 0)
833 return;
834 break;
835
1519 return;
1520 break;
1521
836 case NFSPROC_RMDIR:
837 printf(" rmdir");
1522 case NFSPROC_FSINFO:
1523 printf(" fsinfo");
838 dp = parserep(rp, length);
1524 dp = parserep(rp, length);
839 if (dp != 0 && parsestatus(dp) != 0)
1525 if (dp != 0 && parsefsinfo(dp) != 0)
840 return;
841 break;
842
1526 return;
1527 break;
1528
843 case NFSPROC_READDIR:
844 printf(" readdir");
1529 case NFSPROC_PATHCONF:
1530 printf(" pathconf");
845 dp = parserep(rp, length);
1531 dp = parserep(rp, length);
846 if (dp != 0 && parserddires(dp) != 0)
1532 if (dp != 0 && parsepathconf(dp) != 0)
847 return;
848 break;
849
1533 return;
1534 break;
1535
850 case NFSPROC_STATFS:
851 printf(" statfs");
1536 case NFSPROC_COMMIT:
1537 printf(" commit");
852 dp = parserep(rp, length);
1538 dp = parserep(rp, length);
853 if (dp != 0 && parsestatfs(dp) != 0)
1539 if (dp != 0 && parsewccres(dp, vflag) != 0)
854 return;
855 break;
856
857 default:
1540 return;
1541 break;
1542
1543 default:
858 printf(" proc-%u", proc);
1544 printf(" proc-%lu", proc);
859 return;
860 }
1545 return;
1546 }
1547
1548trunc:
861 fputs(" [|nfs]", stdout);
862}
1549 fputs(" [|nfs]", stdout);
1550}