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 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 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 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 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 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 * 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 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 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 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 * 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 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 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 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 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 * 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 * 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 * 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 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 687 skip_fattr() 688 { 689 690 xdr_skip(17 * 4); /* XDR sizeof nfsfattr */ 691 } 692