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