1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 1991-2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 #include <sys/types.h>
30 #include <sys/errno.h>
31 #include <sys/tiuser.h>
32 #include <setjmp.h>
33
34 #include <rpc/types.h>
35 #include <rpc/xdr.h>
36 #include <rpc/auth.h>
37 #include <rpc/clnt.h>
38 #include <rpc/rpc_msg.h>
39 #include <string.h>
40 #include "snoop.h"
41 #include "snoop_nfs.h"
42
43 #include <sys/stat.h>
44 #include <rpcsvc/nfs_prot.h>
45
46 static char *perms(int);
47 static char *filetype(int);
48 static char *sum_readdirres(void);
49 static void detail_readdirres(void);
50 static void detail_diroparg(void);
51 static void nfscall2(int);
52 static void nfsreply2(int);
53 static void detail_mode(int);
54 static void detail_sattr(void);
55 static void interpret_nfs2(int, int, int, int, int, char *, int);
56
57 extern jmp_buf xdr_err;
58
59 static char *procnames_short[] = {
60 "NULL2", /* 0 */
61 "GETATTR2", /* 1 */
62 "SETATTR2", /* 2 */
63 "ROOT2", /* 3 */
64 "LOOKUP2", /* 4 */
65 "READLINK2", /* 5 */
66 "READ2", /* 6 */
67 "WRITECACHE2", /* 7 */
68 "WRITE2", /* 8 */
69 "CREATE2", /* 9 */
70 "REMOVE2", /* 10 */
71 "RENAME2", /* 11 */
72 "LINK2", /* 12 */
73 "SYMLINK2", /* 13 */
74 "MKDIR2", /* 14 */
75 "RMDIR2", /* 15 */
76 "READDIR2", /* 16 */
77 "STATFS2", /* 17 */
78 };
79
80 static char *procnames_long[] = {
81 "Null procedure", /* 0 */
82 "Get file attributes", /* 1 */
83 "Set file attributes", /* 2 */
84 "Get root filehandle", /* 3 */
85 "Look up file name", /* 4 */
86 "Read from symbolic link", /* 5 */
87 "Read from file", /* 6 */
88 "Write to cache", /* 7 */
89 "Write to file", /* 8 */
90 "Create file", /* 9 */
91 "Remove file", /* 10 */
92 "Rename", /* 11 */
93 "Link", /* 12 */
94 "Make symbolic link", /* 13 */
95 "Make directory", /* 14 */
96 "Remove directory", /* 15 */
97 "Read from directory", /* 16 */
98 "Get filesystem attributes", /* 17 */
99 };
100
101 #define MAXPROC 17
102
103 /* ARGSUSED */
104 void
interpret_nfs(flags,type,xid,vers,proc,data,len)105 interpret_nfs(flags, type, xid, vers, proc, data, len)
106 int flags, type, xid, vers, proc;
107 char *data;
108 int len;
109 {
110
111 if (vers == 2) {
112 interpret_nfs2(flags, type, xid, vers, proc, data, len);
113 return;
114 }
115
116 if (vers == 3) {
117 interpret_nfs3(flags, type, xid, vers, proc, data, len);
118 return;
119 }
120
121 if (vers == 4) {
122 interpret_nfs4(flags, type, xid, vers, proc, data, len);
123 return;
124 }
125 }
126
127 static void
interpret_nfs2(flags,type,xid,vers,proc,data,len)128 interpret_nfs2(flags, type, xid, vers, proc, data, len)
129 int flags, type, xid, vers, proc;
130 char *data;
131 int len;
132 {
133 char *line;
134 char buff[NFS_MAXPATHLEN + 1];
135 int off, sz;
136 char *fh;
137
138 if (proc < 0 || proc > MAXPROC)
139 return;
140
141 if (flags & F_SUM) {
142 line = get_sum_line();
143
144 if (type == CALL) {
145 (void) sprintf(line,
146 "NFS C %s",
147 procnames_short[proc]);
148 line += strlen(line);
149 switch (proc) {
150 case NFSPROC_GETATTR:
151 case NFSPROC_READLINK:
152 case NFSPROC_STATFS:
153 case NFSPROC_SETATTR:
154 (void) sprintf(line, sum_nfsfh());
155 break;
156 case NFSPROC_LOOKUP:
157 case NFSPROC_REMOVE:
158 case NFSPROC_RMDIR:
159 case NFSPROC_CREATE:
160 case NFSPROC_MKDIR:
161 fh = sum_nfsfh();
162 (void) sprintf(line, "%s %s",
163 fh,
164 getxdr_string(buff, NFS_MAXNAMLEN));
165 break;
166 case NFSPROC_WRITE:
167 fh = sum_nfsfh();
168 (void) getxdr_long(); /* beginoff */
169 off = getxdr_long();
170 (void) getxdr_long(); /* totalcount */
171 sz = getxdr_long();
172 (void) sprintf(line, "%s at %d for %d",
173 fh, off, sz);
174 break;
175 case NFSPROC_RENAME:
176 fh = sum_nfsfh();
177 (void) sprintf(line, "%s %s",
178 fh,
179 getxdr_string(buff, NFS_MAXNAMLEN));
180 line += strlen(line);
181 fh = sum_nfsfh();
182 (void) sprintf(line, " to%s %s",
183 fh,
184 getxdr_string(buff, NFS_MAXNAMLEN));
185 break;
186 case NFSPROC_LINK:
187 fh = sum_nfsfh();
188 (void) sprintf(line, "%s", fh);
189 line += strlen(line);
190 fh = sum_nfsfh();
191 (void) sprintf(line, " to%s %s",
192 fh,
193 getxdr_string(buff, NFS_MAXNAMLEN));
194 break;
195 case NFSPROC_SYMLINK:
196 fh = sum_nfsfh();
197 (void) sprintf(line, "%s %s",
198 fh,
199 getxdr_string(buff, NFS_MAXNAMLEN));
200 line += strlen(line);
201 (void) sprintf(line, " to %s",
202 getxdr_string(buff, NFS_MAXPATHLEN));
203 break;
204 case NFSPROC_READDIR:
205 fh = sum_nfsfh();
206 (void) sprintf(line, "%s Cookie=%lu",
207 fh, getxdr_u_long());
208 break;
209 case NFSPROC_READ:
210 fh = sum_nfsfh();
211 off = getxdr_long();
212 sz = getxdr_long();
213 (void) sprintf(line, "%s at %d for %d",
214 fh, off, sz);
215 break;
216 default:
217 break;
218 }
219
220 check_retransmit(line, (ulong_t)xid);
221 } else {
222 (void) sprintf(line, "NFS R %s ",
223 procnames_short[proc]);
224 line += strlen(line);
225 switch (proc) {
226 case NFSPROC_CREATE:
227 case NFSPROC_MKDIR:
228 case NFSPROC_LOOKUP:
229 if (sum_nfsstat(line) == 0) {
230 line += strlen(line);
231 (void) sprintf(line, sum_nfsfh());
232 }
233 break;
234 case NFSPROC_READLINK:
235 if (sum_nfsstat(line) == 0) {
236 line += strlen(line);
237 (void) sprintf(line, " (Path=%s)",
238 getxdr_string(buff,
239 NFS_MAXPATHLEN));
240 }
241 break;
242 case NFSPROC_GETATTR:
243 case NFSPROC_SYMLINK:
244 case NFSPROC_STATFS:
245 case NFSPROC_SETATTR:
246 case NFSPROC_REMOVE:
247 case NFSPROC_RMDIR:
248 case NFSPROC_WRITE:
249 case NFSPROC_RENAME:
250 case NFSPROC_LINK:
251 (void) sum_nfsstat(line);
252 break;
253 case NFSPROC_READDIR:
254 if (sum_nfsstat(line) == 0) {
255 line += strlen(line);
256 (void) strcat(line, sum_readdirres());
257 }
258 break;
259 case NFSPROC_READ:
260 if (sum_nfsstat(line) == 0) {
261 line += strlen(line);
262 xdr_skip(68); /* fattrs */
263 (void) sprintf(line, " (%ld bytes)",
264 getxdr_long());
265 }
266 break;
267 default:
268 break;
269 }
270 }
271 }
272
273 if (flags & F_DTAIL) {
274 show_header("NFS: ", "Sun NFS", len);
275 show_space();
276 (void) sprintf(get_line(0, 0), "Proc = %d (%s)",
277 proc, procnames_long[proc]);
278 if (type == CALL)
279 nfscall2(proc);
280 else
281 nfsreply2(proc);
282 show_trailer();
283 }
284 }
285
286 /*
287 * Print out version 2 NFS call packets
288 */
289 static void
nfscall2(proc)290 nfscall2(proc)
291 int proc;
292 {
293 switch (proc) {
294 case NFSPROC_GETATTR:
295 case NFSPROC_READLINK:
296 case NFSPROC_STATFS:
297 detail_nfsfh();
298 break;
299 case NFSPROC_SETATTR:
300 detail_nfsfh();
301 detail_sattr();
302 break;
303 case NFSPROC_LOOKUP:
304 case NFSPROC_REMOVE:
305 case NFSPROC_RMDIR:
306 detail_diroparg();
307 break;
308 case NFSPROC_MKDIR:
309 case NFSPROC_CREATE:
310 detail_diroparg();
311 detail_sattr();
312 break;
313 case NFSPROC_WRITE:
314 detail_nfsfh();
315 (void) getxdr_long(); /* begoff */
316 (void) showxdr_long("Offset = %d");
317 (void) getxdr_long(); /* totalcount */
318 (void) showxdr_long("(%d bytes(s) of data)");
319 break;
320 case NFSPROC_RENAME:
321 detail_diroparg();
322 detail_diroparg();
323 break;
324 case NFSPROC_LINK:
325 detail_nfsfh();
326 detail_diroparg();
327 break;
328 case NFSPROC_SYMLINK:
329 detail_diroparg();
330 (void) showxdr_string(NFS_MAXPATHLEN, "Path = %s");
331 detail_sattr();
332 break;
333 case NFSPROC_READDIR:
334 detail_nfsfh();
335 (void) showxdr_u_long("Cookie = %lu");
336 (void) showxdr_long("Count = %d");
337 break;
338 case NFSPROC_READ:
339 detail_nfsfh();
340 (void) showxdr_long("Offset = %d");
341 (void) showxdr_long("Count = %d");
342 break;
343 default:
344 break;
345 }
346 }
347
348 /*
349 * Print out version 2 NFS reply packets
350 */
351 static void
nfsreply2(proc)352 nfsreply2(proc)
353 int proc;
354 {
355 switch (proc) {
356 case NFSPROC_GETATTR:
357 case NFSPROC_SETATTR:
358 case NFSPROC_WRITE:
359 /* attrstat */
360 if (detail_nfsstat() == 0) {
361 detail_fattr();
362 }
363 break;
364 case NFSPROC_LOOKUP:
365 case NFSPROC_CREATE:
366 case NFSPROC_MKDIR:
367 /* diropres */
368 if (detail_nfsstat() == 0) {
369 detail_nfsfh();
370 detail_fattr();
371 }
372 break;
373 case NFSPROC_READLINK:
374 /* readlinkres */
375 if (detail_nfsstat() == 0) {
376 (void) showxdr_string(NFS_MAXPATHLEN, "Path = %s");
377 }
378 break;
379 case NFSPROC_READ:
380 /* readres */
381 if (detail_nfsstat() == 0) {
382 detail_fattr();
383 (void) showxdr_long("(%d byte(s) of data)");
384 }
385 break;
386 case NFSPROC_REMOVE:
387 case NFSPROC_RENAME:
388 case NFSPROC_LINK:
389 case NFSPROC_SYMLINK:
390 case NFSPROC_RMDIR:
391 /* stat */
392 detail_nfsstat();
393 break;
394 case NFSPROC_READDIR:
395 /* readdirres */
396 if (detail_nfsstat() == 0)
397 detail_readdirres();
398 break;
399 case NFSPROC_STATFS:
400 /* statfsres */
401 if (detail_nfsstat() == 0) {
402 (void) showxdr_long("Transfer size = %d");
403 (void) showxdr_long("Block size = %d");
404 (void) showxdr_long("Total blocks = %d");
405 (void) showxdr_long("Free blocks = %d");
406 (void) showxdr_long("Available blocks = %d");
407 }
408 break;
409 default:
410 break;
411 }
412 }
413
414 static void
detail_diroparg()415 detail_diroparg()
416 {
417 detail_nfsfh();
418 (void) showxdr_string(NFS_MAXPATHLEN, "File name = %s");
419 }
420
421 /*
422 * V2 NFS protocol was implicitly linked with SunOS errnos.
423 * Some of the errno values changed in SVr4.
424 * Need to map errno value so that SVr4 snoop will interpret
425 * them correctly.
426 */
427 static char *
statusmsg(status)428 statusmsg(status)
429 ulong_t status;
430 {
431 switch (status) {
432 case NFS_OK: return ("OK");
433 case NFSERR_PERM: return ("Not owner");
434 case NFSERR_NOENT: return ("No such file or directory");
435 case NFSERR_IO: return ("I/O error");
436 case NFSERR_NXIO: return ("No such device or address");
437 case NFSERR_ACCES: return ("Permission denied");
438 case NFSERR_EXIST: return ("File exists");
439 case NFSERR_XDEV: return ("Cross-device link");
440 case NFSERR_NODEV: return ("No such device");
441 case NFSERR_NOTDIR: return ("Not a directory");
442 case NFSERR_ISDIR: return ("Is a directory");
443 case NFSERR_INVAL: return ("Invalid argument");
444 case NFSERR_FBIG: return ("File too large");
445 case NFSERR_NOSPC: return ("No space left on device");
446 case NFSERR_ROFS: return ("Read-only file system");
447 case NFSERR_OPNOTSUPP: return ("Operation not supported");
448 case NFSERR_NAMETOOLONG: return ("File name too long");
449 case NFSERR_NOTEMPTY: return ("Directory not empty");
450 case NFSERR_DQUOT: return ("Disc quota exceeded");
451 case NFSERR_STALE: return ("Stale NFS file handle");
452 case NFSERR_REMOTE: return ("Object is remote");
453 case NFSERR_WFLUSH: return ("write cache flushed");
454 default: return ("(unknown error)");
455 }
456 /* NOTREACHED */
457 }
458
459 int
sum_nfsstat(line)460 sum_nfsstat(line)
461 char *line;
462 {
463 ulong_t status;
464
465 status = getxdr_long();
466 (void) strcpy(line, statusmsg(status));
467 return (status);
468 }
469
470 int
detail_nfsstat()471 detail_nfsstat()
472 {
473 ulong_t status;
474 int pos;
475
476 pos = getxdr_pos();
477 status = getxdr_long();
478 (void) sprintf(get_line(pos, getxdr_pos()),
479 "Status = %lu (%s)",
480 status, statusmsg(status));
481
482 return ((int)status);
483 }
484
485 int
sum_filehandle(len)486 sum_filehandle(len)
487 int len;
488 {
489 int i, l;
490 int fh = 0;
491
492 for (i = 0; i < len; i += 4) {
493 l = getxdr_long();
494 fh ^= (l >> 16) ^ l;
495 }
496
497 return (fh);
498 }
499
500 char *
sum_nfsfh()501 sum_nfsfh()
502 {
503 int fh;
504 static char buff[16];
505
506 fh = sum_filehandle(NFS_FHSIZE);
507 (void) sprintf(buff, " FH=%04X", fh & 0xFFFF);
508 return (buff);
509 }
510
511 void
detail_nfsfh()512 detail_nfsfh()
513 {
514 int pos;
515 int fh;
516
517 pos = getxdr_pos();
518 fh = sum_filehandle(NFS_FHSIZE);
519 setxdr_pos(pos);
520 (void) sprintf(get_line(0, 0), "File handle = [%04X]", fh & 0xFFFF);
521 (void) showxdr_hex(NFS_FHSIZE, " %s");
522 }
523
524 static void
detail_mode(mode)525 detail_mode(mode)
526 int mode;
527 {
528 char *str;
529
530 switch (mode & S_IFMT) {
531 case S_IFDIR: str = "Directory"; break;
532 case S_IFCHR: str = "Character"; break;
533 case S_IFBLK: str = "Block"; break;
534 case S_IFREG: str = "Regular file"; break;
535 case S_IFLNK: str = "Link"; break;
536 case S_IFSOCK: str = "Socket"; break;
537 case S_IFIFO: str = "Fifo"; break;
538 default: str = "?"; break;
539 }
540
541 (void) sprintf(get_line(0, 0), "Mode = 0%o", mode);
542 (void) sprintf(get_line(0, 0), " Type = %s", str);
543 (void) sprintf(get_line(0, 0),
544 " Setuid = %d, Setgid = %d, Sticky = %d",
545 (mode & S_ISUID) != 0,
546 (mode & S_ISGID) != 0,
547 (mode & S_ISVTX) != 0);
548 (void) sprintf(get_line(0, 0), " Owner's permissions = %s",
549 perms(mode >> 6 & 0x7));
550 (void) sprintf(get_line(0, 0), " Group's permissions = %s",
551 perms(mode >> 3 & 0x7));
552 (void) sprintf(get_line(0, 0), " Other's permissions = %s",
553 perms(mode & 0x7));
554 }
555
556 void
detail_fattr()557 detail_fattr()
558 {
559 int fltype, mode, nlinks, uid, gid, size, blksz;
560 int rdev, blocks, fsid, fileid;
561
562 fltype = getxdr_long();
563 mode = getxdr_long();
564 nlinks = getxdr_long();
565 uid = getxdr_long();
566 gid = getxdr_long();
567 size = getxdr_long();
568 blksz = getxdr_long();
569 rdev = getxdr_long();
570 blocks = getxdr_long();
571 fsid = getxdr_long();
572 fileid = getxdr_long();
573
574 (void) sprintf(get_line(0, 0),
575 "File type = %d (%s)",
576 fltype, filetype(fltype));
577 detail_mode(mode);
578 (void) sprintf(get_line(0, 0),
579 "Link count = %d, UID = %d, GID = %d, Rdev = 0x%x",
580 nlinks, uid, gid, rdev);
581 (void) sprintf(get_line(0, 0),
582 "File size = %d, Block size = %d, No. of blocks = %d",
583 size, blksz, blocks);
584 (void) sprintf(get_line(0, 0),
585 "File system id = %d, File id = %d",
586 fsid, fileid);
587 (void) showxdr_date("Access time = %s");
588 (void) showxdr_date("Modification time = %s");
589 (void) showxdr_date("Inode change time = %s");
590 }
591
592 static void
detail_sattr()593 detail_sattr()
594 {
595 int mode;
596
597 mode = getxdr_long();
598 detail_mode(mode);
599 (void) showxdr_long("UID = %d");
600 (void) showxdr_long("GID = %d");
601 (void) showxdr_long("Size = %d");
602 (void) showxdr_date("Access time = %s");
603 (void) showxdr_date("Modification time = %s");
604 }
605
606 static char *
filetype(n)607 filetype(n)
608 int n;
609 {
610 switch (n) {
611 case NFREG: return ("Regular File");
612 case NFDIR: return ("Directory");
613 case NFBLK: return ("Block special");
614 case NFCHR: return ("Character special");
615 case NFLNK: return ("Symbolic Link");
616 default: return ("?");
617 }
618 }
619
620 static char *
perms(n)621 perms(n)
622 int n;
623 {
624 static char buff[4];
625
626 buff[0] = n & 4 ? 'r' : '-';
627 buff[1] = n & 2 ? 'w' : '-';
628 buff[2] = n & 1 ? 'x' : '-';
629 buff[3] = '\0';
630 return (buff);
631 }
632
633 static char *
sum_readdirres()634 sum_readdirres()
635 {
636 static char buff[NFS_MAXNAMLEN + 1];
637 int entries = 0;
638
639 if (setjmp(xdr_err)) {
640 (void) sprintf(buff, " %d+ entries (incomplete)", entries);
641 return (buff);
642 }
643 while (getxdr_long()) {
644 entries++;
645 (void) getxdr_long(); /* fileid */
646 (void) getxdr_string(buff, NFS_MAXNAMLEN); /* name */
647 (void) getxdr_u_long(); /* cookie */
648 }
649
650 (void) sprintf(buff, " %d entries (%s)",
651 entries,
652 getxdr_long() ? "No more" : "More");
653 return (buff);
654 }
655
656 static void
detail_readdirres()657 detail_readdirres()
658 {
659 ulong_t fileid, cookie;
660 int entries = 0;
661 char *name;
662 char buff[NFS_MAXNAMLEN + 1];
663
664 (void) sprintf(get_line(0, 0), " File id Cookie Name");
665
666 if (setjmp(xdr_err)) {
667 (void) sprintf(get_line(0, 0),
668 " %d+ entries. (Frame is incomplete)",
669 entries);
670 return;
671 }
672 while (getxdr_long()) {
673 entries++;
674 fileid = getxdr_long();
675 name = (char *)getxdr_string(buff, NFS_MAXNAMLEN);
676 cookie = getxdr_u_long();
677 (void) sprintf(get_line(0, 0),
678 " %7lu %7lu %s",
679 fileid, cookie, name);
680 }
681
682 (void) sprintf(get_line(0, 0), " %d entries", entries);
683 (void) showxdr_long("EOF = %d");
684 }
685
686 void
skip_fattr()687 skip_fattr()
688 {
689
690 xdr_skip(17 * 4); /* XDR sizeof nfsfattr */
691 }
692