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 (c) 1991, 1998, 2001 by Sun Microsystems, Inc.
  24  * All rights reserved.
  25  */
  26 
  27 #include <sys/types.h>
  28 #include <setjmp.h>
  29 #include <string.h>
  30 
  31 #ifdef notdef
  32 #include <rpc/xdr.h>
  33 #include <rpc/auth.h>
  34 #include <rpc/rpc_msg.h>
  35 #endif /* notdef */
  36 #include <rpcsvc/nlm_prot.h>
  37 #include "snoop.h"
  38 
  39 extern char *dlc_header;
  40 extern jmp_buf xdr_err;
  41 
  42 extern void check_retransmit();
  43 static void interpret_nlm_1();
  44 static void interpret_nlm_3();
  45 static void interpret_nlm_4();
  46 static char *nameof_access();
  47 static char *nameof_mode();
  48 static char *nameof_stat();
  49 static char *nameof_stat4();
  50 static void show_cancargs();
  51 static void show_cancargs4();
  52 static void show_lock();
  53 static void show_lock4();
  54 static void show_lockargs();
  55 static void show_lockargs4();
  56 static void show_netobj();
  57 static void show_nlm_access();
  58 static void show_nlm_mode();
  59 static void show_notify();
  60 static void show_res();
  61 static void show_res4();
  62 static void show_share();
  63 static void show_shareargs();
  64 static void show_shareres();
  65 static void show_shareres4();
  66 static enum nlm_stats show_stat();
  67 static enum nlm4_stats show_stat4();
  68 static void show_testargs();
  69 static void show_testargs4();
  70 static void show_testres();
  71 static void show_testres4();
  72 static void show_unlockargs();
  73 static void show_unlockargs4();
  74 static void skip_netobj();
  75 static char *sum_lock();
  76 static char *sum_lock4();
  77 static char *sum_netobj();
  78 static char *sum_notify();
  79 static char *sum_share();
  80 
  81 void
  82 interpret_nlm(flags, type, xid, vers, proc, data, len)
  83         int flags, type, xid, vers, proc;
  84         char *data;
  85         int len;
  86 {
  87         switch (vers) {
  88         case 1: interpret_nlm_1(flags, type, xid, vers, proc, data, len);
  89                 break;
  90         case 3: interpret_nlm_3(flags, type, xid, vers, proc, data, len);
  91                 break;
  92         case 4: interpret_nlm_4(flags, type, xid, vers, proc, data, len);
  93                 break;
  94         }
  95 }
  96 
  97 
  98 /* ------------  V E R S I O N   1  ---------------------------------- */
  99 
 100 static char *procnames_short_1[] = {
 101         "Null1",        /* 0 */
 102         "TEST1",        /* 1 */
 103         "LOCK1",        /* 2 */
 104         "CANCEL1",      /* 3 */
 105         "UNLOCK1",      /* 4 */
 106         "GRANTED1",     /* 5 */
 107         "TEST MSG1",    /* 6 */
 108         "LOCK MSG1",    /* 7 */
 109         "CANCEL MSG1",  /* 8 */
 110         "UNLOCK MSG1",  /* 9 */
 111         "GRANTED MSG1", /* 10 */
 112         "TEST RES1",    /* 11 */
 113         "LOCK RES1",    /* 12 */
 114         "CANCEL RES1",  /* 13 */
 115         "UNLOCK RES1",  /* 14 */
 116         "GRANTED RES1", /* 15 */
 117 };
 118 
 119 static char *procnames_long_1[] = {
 120         "Null procedure",       /* 0 */
 121         "Test",                 /* 1 */
 122         "Lock",                 /* 2 */
 123         "Cancel",               /* 3 */
 124         "Unlock",               /* 4 */
 125         "Granted",              /* 5 */
 126         "Test message",         /* 6 */
 127         "Lock message",         /* 7 */
 128         "Cancel message",       /* 8 */
 129         "Unlock message",       /* 9 */
 130         "Granted message",      /* 10 */
 131         "Test result",          /* 11 */
 132         "Lock result",          /* 12 */
 133         "Cancel result",        /* 13 */
 134         "Unlock result",        /* 14 */
 135         "Granted result",       /* 15 */
 136 };
 137 
 138 /* Highest procedure number that officially belongs to version 1. */
 139 #define MAXPROC_1       15
 140 
 141 /* ARGSUSED */
 142 static void
 143 interpret_nlm_1(flags, type, xid, vers, proc, data, len)
 144         int flags, type, xid, vers, proc;
 145         char *data;
 146         int len;
 147 {
 148         char *line;
 149 
 150         if (proc < 0 || proc > MAXPROC_1)
 151                 return;
 152 
 153         if (flags & F_SUM) {
 154                 if (setjmp(xdr_err)) {
 155                         return;
 156                 }
 157 
 158                 line = get_sum_line();
 159 
 160                 if (type == CALL) {
 161                         (void) sprintf(line,
 162                                 "NLM C %s",
 163                                 procnames_short_1[proc]);
 164                         line += strlen(line);
 165                         switch (proc) {
 166                         case NLM_TEST:
 167                         case NLM_GRANTED:
 168                         case NLM_TEST_MSG:
 169                         case NLM_GRANTED_MSG:
 170                                 /* testargs */
 171                                 (void) strcat(line, sum_netobj("OH"));
 172                                 (void) getxdr_bool();   /* Excl */
 173                                 (void) strcat(line, sum_lock());
 174                                 break;
 175                         case NLM_LOCK:
 176                         case NLM_LOCK_MSG:
 177                                 /* lockargs */
 178                                 (void) strcat(line, sum_netobj("OH"));
 179                                 (void) getxdr_bool();   /* Block */
 180                                 (void) getxdr_bool();   /* Excl */
 181                                 (void) strcat(line, sum_lock());
 182                                 break;
 183                         case NLM_CANCEL:
 184                         case NLM_CANCEL_MSG:
 185                                 /* cancargs */
 186                                 (void) strcat(line, sum_netobj("OH"));
 187                                 (void) getxdr_bool();   /* Block */
 188                                 (void) getxdr_bool();   /* Excl */
 189                                 (void) strcat(line, sum_lock());
 190                                 break;
 191                         case NLM_UNLOCK:
 192                         case NLM_UNLOCK_MSG:
 193                                 /* unlockargs */
 194                                 (void) strcat(line, sum_netobj("OH"));
 195                                 (void) strcat(line, sum_lock());
 196                                 break;
 197                         case NLM_TEST_RES:
 198                                 /* testres */
 199                                 (void) strcat(line, sum_netobj("OH"));
 200                                 (void) strcat(line, " ");
 201                                 (void) strcat(line,
 202                                     nameof_stat(getxdr_u_long()));
 203                                 break;
 204                         case NLM_LOCK_RES:
 205                         case NLM_CANCEL_RES:
 206                         case NLM_UNLOCK_RES:
 207                         case NLM_GRANTED_RES:
 208                                 /* res */
 209                                 (void) strcat(line, sum_netobj("OH"));
 210                                 (void) strcat(line, " ");
 211                                 (void) strcat(line,
 212                                         nameof_stat(getxdr_u_long()));
 213                                 break;
 214                         }
 215                         check_retransmit(line, (ulong_t)xid);
 216                 } else {
 217                         (void) sprintf(line, "NLM R %s",
 218                                 procnames_short_1[proc]);
 219                         line += strlen(line);
 220                         switch (proc) {
 221                         case NLM_TEST:
 222                                 /* testres */
 223                                 (void) strcat(line, sum_netobj("OH"));
 224                                 (void) strcat(line, " ");
 225                                 (void) strcat(line,
 226                                     nameof_stat(getxdr_u_long()));
 227                                 break;
 228                         case NLM_LOCK:
 229                         case NLM_CANCEL:
 230                         case NLM_UNLOCK:
 231                         case NLM_GRANTED:
 232                                 /* res */
 233                                 (void) strcat(line, sum_netobj("OH"));
 234                                 (void) strcat(line, " ");
 235                                 (void) strcat(line,
 236                                         nameof_stat(getxdr_u_long()));
 237                                 break;
 238                         }
 239                 }
 240         }
 241 
 242         if (flags & F_DTAIL) {
 243                 show_header("NLM:  ", "Network Lock Manager", len);
 244                 show_space();
 245                 if (setjmp(xdr_err)) {
 246                         return;
 247                 }
 248                 (void) sprintf(get_line(0, 0),
 249                         "Proc = %d (%s)",
 250                         proc, procnames_long_1[proc]);
 251                 if (type == CALL) {
 252                         switch (proc) {
 253                         case NLM_TEST:
 254                         case NLM_GRANTED:
 255                         case NLM_TEST_MSG:
 256                         case NLM_GRANTED_MSG:
 257                                 show_testargs();
 258                                 break;
 259                         case NLM_LOCK:
 260                         case NLM_LOCK_MSG:
 261                                 show_lockargs();
 262                                 break;
 263                         case NLM_CANCEL:
 264                         case NLM_CANCEL_MSG:
 265                                 show_cancargs();
 266                                 break;
 267                         case NLM_UNLOCK:
 268                         case NLM_UNLOCK_MSG:
 269                                 show_unlockargs();
 270                                 break;
 271                         case NLM_TEST_RES:
 272                                 show_testres();
 273                                 break;
 274                         case NLM_LOCK_RES:
 275                         case NLM_CANCEL_RES:
 276                         case NLM_UNLOCK_RES:
 277                         case NLM_GRANTED_RES:
 278                                 show_res();
 279                                 break;
 280                         }
 281                 } else {
 282                         switch (proc) {
 283                         case NLM_TEST:
 284                                 show_testres();
 285                                 break;
 286                         case NLM_LOCK:
 287                         case NLM_CANCEL:
 288                         case NLM_UNLOCK:
 289                         case NLM_GRANTED:
 290                                 show_res();
 291                                 break;
 292                         case NLM_TEST_MSG:
 293                         case NLM_LOCK_MSG:
 294                         case NLM_CANCEL_MSG:
 295                         case NLM_UNLOCK_MSG:
 296                         case NLM_GRANTED_MSG:
 297                         case NLM_TEST_RES:
 298                         case NLM_LOCK_RES:
 299                         case NLM_CANCEL_RES:
 300                         case NLM_UNLOCK_RES:
 301                         case NLM_GRANTED_RES:
 302                                 break;
 303                         }
 304                 }
 305                 show_trailer();
 306         }
 307 }
 308 
 309 #define roundup(sz) ((sz / 4 + (sz % 4 > 0)) * 4)
 310 
 311 /*
 312  * Skip a netobj.
 313  * Make sure an integral number of words
 314  * are skipped.
 315  */
 316 static void
 317 skip_netobj()
 318 {
 319         int sz = getxdr_u_long();
 320 
 321         xdr_skip(roundup(sz));
 322 }
 323 
 324 static char *
 325 sum_netobj(handle)
 326         char *handle;
 327 {
 328         int i, l, sz;
 329         int sum = 0;
 330         static char buff[32];
 331 
 332         sz = getxdr_u_long();
 333         for (i = 0; i < sz; i += 4) {
 334                 l =  getxdr_long();
 335                 sum ^= (l >> 16) ^ l;
 336         }
 337         (void) sprintf(buff, " %s=%04X", handle, sum & 0xFFFF);
 338         return (buff);
 339 }
 340 
 341 static void
 342 show_netobj(fmt)
 343         char *fmt;
 344 {
 345         int sz, chunk;
 346         char *p;
 347         char buff[64];
 348         int needspace;
 349 
 350         sz = getxdr_u_long();           /* size of the netobj */
 351 
 352         if (sz == 0) {
 353                 (void) sprintf(get_line(0, 0), fmt, "<null>");
 354         } else {
 355                 needspace = sz > 16;
 356                 (void) strcpy(buff, fmt);
 357                 while (sz > 0) {
 358                         chunk = sz > 16 ? 16 : sz;
 359                         sz -= 16;
 360                         (void) showxdr_hex(chunk, buff);
 361                         /*
 362                          * For every line after the first, blank out
 363                          * everything in the format string before the "%s".
 364                          */
 365                         for (p = buff; *p != '%'; p++)
 366                                 *p = ' ';
 367                 }
 368                 if (needspace)
 369                         show_space();
 370         }
 371 }
 372 
 373 static char *
 374 sum_lock()
 375 {
 376         static char buff[LM_MAXSTRLEN + 1];
 377         char *cp = buff;
 378         long id;
 379         ulong_t off, len;
 380 
 381         (void) getxdr_string(buff, LM_MAXSTRLEN);       /* Caller */
 382         (void) strcpy(buff, sum_netobj("FH"));          /* Fh */
 383         cp += strlen(buff);
 384         skip_netobj();                                  /* Owner */
 385         id  = getxdr_long();
 386         off = getxdr_u_long();
 387         len = getxdr_u_long();
 388         (void) sprintf(cp, " PID=%ld Region=%lu:%lu", id, off, len);
 389         return (buff);
 390 }
 391 
 392 static void
 393 show_lock()
 394 {
 395         showxdr_string(LM_MAXSTRLEN, "Caller = %s");
 396         show_netobj("Filehandle = %s");
 397         show_netobj("Lock owner = %s");
 398         showxdr_long("Svid = %ld (process id)");
 399         showxdr_u_long("Offset = %lu bytes");
 400         showxdr_u_long("Length = %lu bytes");
 401 }
 402 
 403 static void
 404 show_cancargs()
 405 {
 406         show_netobj("Cookie = %s");
 407         showxdr_bool("Block = %s");
 408         showxdr_bool("Exclusive = %s");
 409         show_lock();
 410 }
 411 
 412 static void
 413 show_lockargs()
 414 {
 415         show_netobj("Cookie = %s");
 416         showxdr_bool("Block = %s");
 417         showxdr_bool("Exclusive = %s");
 418         show_lock();
 419         showxdr_bool("Reclaim = %s");
 420         showxdr_long("State = %ld");
 421 }
 422 
 423 static void
 424 show_unlockargs()
 425 {
 426         show_netobj("Cookie = %s");
 427         show_lock();
 428 }
 429 
 430 static void
 431 show_testargs()
 432 {
 433         show_netobj("Cookie = %s");
 434         showxdr_bool("Exclusive = %s");
 435         show_lock();
 436 }
 437 
 438 static void
 439 show_res()
 440 {
 441         show_netobj("Cookie = %s");
 442         (void) show_stat();
 443 }
 444 
 445 static char *
 446 nameof_stat(s)
 447         ulong_t s;
 448 {
 449         switch ((enum nlm_stats) s) {
 450         case nlm_granted:       return ("granted");
 451         case nlm_denied:        return ("denied");
 452         case nlm_denied_nolocks:return ("denied (no locks)");
 453         case nlm_blocked:       return ("blocked");
 454         case nlm_denied_grace_period: return ("denied (grace period)");
 455         case nlm_deadlck:       return ("deadlock");
 456         default:                return ("?");
 457         }
 458 }
 459 
 460 static enum nlm_stats
 461 show_stat()
 462 {
 463         enum nlm_stats s;
 464 
 465         s = (enum nlm_stats) getxdr_u_long();
 466         (void) sprintf(get_line(0, 0),
 467             "Status = %d (%s)",
 468             s, nameof_stat((ulong_t)s));
 469 
 470         return (s);
 471 }
 472 
 473 static void
 474 show_testres()
 475 {
 476         show_netobj("Cookie = %s");
 477         if (show_stat() == nlm_denied) {
 478                 showxdr_bool("Exclusive = %s");
 479                 showxdr_long("Svid = %ld (process id)");
 480                 show_netobj("Owner handle = %s");
 481                 showxdr_u_long("Offset = %lu bytes");
 482                 showxdr_u_long("Length = %lu bytes");
 483         }
 484 }
 485 
 486 
 487 /* ------------  V E R S I O N   3  ---------------------------------- */
 488 
 489 static char *procnames_short_3[] = {
 490         "SHARE3",       /* 20 */
 491         "UNSHARE3",     /* 21 */
 492         "NM_LOCK3",     /* 22 */
 493         "FREEALL3",     /* 23 */
 494 };
 495 
 496 static char *procnames_long_3[] = {
 497         "Share",                /* 20 */
 498         "Unshare",              /* 21 */
 499         "Unmonitored lock",     /* 22 */
 500         "Free all",             /* 23 */
 501 };
 502 
 503 /* Maximum procedure number for version 3. */
 504 #define MAXPROC_3       23
 505 
 506 static void
 507 interpret_nlm_3(flags, type, xid, vers, proc, data, len)
 508         int flags, type, xid, vers, proc;
 509         char *data;
 510         int len;
 511 {
 512         char *line, *pl;
 513         ulong_t i;
 514 
 515         if (proc < 0 || proc > MAXPROC_3)
 516                 return;
 517 
 518         /*
 519          * Version 3 is a superset of version 1
 520          */
 521         if (proc >= 0 && proc <= MAXPROC_1) {
 522                 interpret_nlm_1(flags, type, xid, vers, proc, data, len);
 523                 return;
 524         }
 525 
 526         if (flags & F_SUM) {
 527                 if (setjmp(xdr_err)) {
 528                         return;
 529                 }
 530 
 531                 line = get_sum_line();
 532 
 533                 if (type == CALL) {
 534                         (void) sprintf(line,
 535                                 "NLM C %s",
 536                                 procnames_short_3[proc-20]);
 537                         line += strlen(line);
 538                         switch (proc) {
 539                         case NLM_SHARE:
 540                         case NLM_UNSHARE:
 541                                 (void) strcat(line, sum_netobj("OH"));
 542                                 (void) strcat(line, sum_share());
 543                                 break;
 544                         case NLM_NM_LOCK:
 545                                 /* lockargs */
 546                                 skip_netobj();
 547                                 (void) getxdr_u_long(); /* Block */
 548                                 (void) getxdr_u_long(); /* Excl */
 549                                 (void) strcat(line, sum_lock());
 550                                 break;
 551                         case NLM_FREE_ALL:
 552                                 (void) sprintf(line,
 553                                         " %s", sum_notify());
 554                                 break;
 555                         }
 556                         check_retransmit(line, (ulong_t)xid);
 557                 } else {
 558                         (void) sprintf(line, "NLM R %s",
 559                                 procnames_short_3[proc-20]);
 560                         line += strlen(line);
 561                         switch (proc) {
 562                         case NLM_SHARE:
 563                         case NLM_UNSHARE:
 564                                 pl = sum_netobj("OH");
 565                                 i = getxdr_u_long();
 566                                 sprintf(line, "%s %s %ld",
 567                                         pl, nameof_stat(i), getxdr_long());
 568                                 break;
 569                         case NLM_NM_LOCK:
 570                                 /* res */
 571                                 (void) strcat(line, sum_netobj("OH"));
 572                                 (void) strcat(line, " ");
 573                                 (void) strcat(line,
 574                                         nameof_stat(getxdr_u_long()));
 575                                 break;
 576                         case NLM_FREE_ALL:
 577                                 break;
 578                         }
 579                 }
 580         }
 581 
 582         if (flags & F_DTAIL) {
 583                 show_header("NLM:  ", "Network Lock Manager", len);
 584                 show_space();
 585                 if (setjmp(xdr_err)) {
 586                         return;
 587                 }
 588                 (void) sprintf(get_line(0, 0),
 589                         "Proc = %d (%s)",
 590                         proc, procnames_long_3[proc-20]);
 591                 if (type == CALL) {
 592                         switch (proc) {
 593                         case NLM_SHARE:
 594                         case NLM_UNSHARE:
 595                                 show_shareargs();
 596                                 break;
 597                         case NLM_NM_LOCK:
 598                                 show_lockargs();
 599                                 break;
 600                         case NLM_FREE_ALL:
 601                                 show_notify();
 602                                 break;
 603                         }
 604                 } else {
 605                         switch (proc) {
 606                         case NLM_SHARE:
 607                         case NLM_UNSHARE:
 608                                 show_shareres();
 609                                 break;
 610                         case NLM_NM_LOCK:
 611                                 show_res();
 612                                 break;
 613                         case NLM_FREE_ALL:
 614                                 break;
 615                         }
 616                 }
 617                 show_trailer();
 618         }
 619 }
 620 
 621 static char *
 622 nameof_mode(m)
 623         uint_t m;
 624 {
 625         switch ((enum fsh_mode) m) {
 626         case fsm_DN:    return ("deny none");
 627         case fsm_DR:    return ("deny read");
 628         case fsm_DW:    return ("deny write");
 629         case fsm_DRW:   return ("deny read/write");
 630         default:        return ("?");
 631         }
 632 }
 633 
 634 static char *
 635 nameof_access(a)
 636         uint_t a;
 637 {
 638         switch ((enum fsh_access) a) {
 639         case fsa_NONE:  return ("?");
 640         case fsa_R:     return ("read only");
 641         case fsa_W:     return ("write only");
 642         case fsa_RW:    return ("read/write");
 643         default:        return ("?");
 644         }
 645 }
 646 
 647 static void
 648 show_nlm_mode()
 649 {
 650         enum fsh_mode m;
 651 
 652         m = (enum fsh_mode) getxdr_u_long();
 653         (void) sprintf(get_line(0, 0),
 654             "Mode = %d (%s)",
 655             m, nameof_mode((uint_t)m));
 656 }
 657 
 658 static void
 659 show_nlm_access()
 660 {
 661         enum fsh_access a;
 662 
 663         a = (enum fsh_access) getxdr_u_long();
 664         (void) sprintf(get_line(0, 0),
 665             "Access = %d (%s)",
 666             a, nameof_access((uint_t)a));
 667 }
 668 
 669 static char *
 670 sum_share()
 671 {
 672         static char buff[LM_MAXSTRLEN + 1];
 673         char *cp = buff;
 674         ulong_t mode, access;
 675 
 676         (void) getxdr_string(buff, LM_MAXSTRLEN);       /* Caller */
 677         (void) strcpy(buff, sum_netobj("FH"));          /* Fh */
 678         cp += strlen(buff);
 679         skip_netobj();                                  /* Owner */
 680         mode = getxdr_u_long();
 681         access = getxdr_u_long();
 682         (void) sprintf(cp, " Mode=%lu Access=%lu", mode, access);
 683         return (buff);
 684 }
 685 
 686 static void
 687 show_share()
 688 {
 689         showxdr_string(LM_MAXSTRLEN, "Caller = %s");
 690         show_netobj("Filehandle = %s");
 691         show_netobj("Lock owner = %s");
 692         show_nlm_mode();
 693         show_nlm_access();
 694 }
 695 
 696 static void
 697 show_shareargs()
 698 {
 699         show_netobj("Cookie = %s");
 700         show_share();
 701         showxdr_bool("Reclaim = %s");
 702 }
 703 
 704 static void
 705 show_shareres()
 706 {
 707         show_netobj("Cookie = %s");
 708         (void) show_stat();
 709         showxdr_long("Sequence = %d");
 710 }
 711 
 712 static void
 713 show_notify()
 714 {
 715         showxdr_string(LM_MAXNAMELEN, "Name = %s");
 716         showxdr_long("State = %d");
 717 }
 718 
 719 #define NOTIFY_PAD      (sizeof (" State=-2147483648") + 1)
 720 
 721 static char *
 722 sum_notify()
 723 {
 724         static char buff[LM_MAXNAMELEN + NOTIFY_PAD];
 725         char *cp = buff;
 726         long state;
 727 
 728         (void) getxdr_string(buff, LM_MAXNAMELEN);
 729         cp += strlen(buff);
 730         state  = getxdr_long();
 731         (void) sprintf(cp, " State=%ld", state);
 732         return (buff);
 733 }
 734 
 735 /* ------------  V E R S I O N   4  ---------------------------------- */
 736 
 737 static char *procnames_short_4[] = {
 738         "Null4",        /* 0 */
 739         "TEST4",        /* 1 */
 740         "LOCK4",        /* 2 */
 741         "CANCEL4",      /* 3 */
 742         "UNLOCK4",      /* 4 */
 743         "GRANTED4",     /* 5 */
 744         "TEST MSG4",    /* 6 */
 745         "LOCK MSG4",    /* 7 */
 746         "CANCEL MSG4",  /* 8 */
 747         "UNLOCK MSG4",  /* 9 */
 748         "GRANTED MSG4", /* 10 */
 749         "TEST RES4",    /* 11 */
 750         "LOCK RES4",    /* 12 */
 751         "CANCEL RES4",  /* 13 */
 752         "UNLOCK RES4",  /* 14 */
 753         "GRANTED RES4", /* 15 */
 754         "PROC 16 v4",   /* 16 */
 755         "PROC 17 v4",   /* 17 */
 756         "PROC 18 v4",   /* 18 */
 757         "PROC 19 v4",   /* 19 */
 758         "SHARE4",       /* 20 */
 759         "UNSHARE4",     /* 21 */
 760         "NM_LOCK4",     /* 22 */
 761         "FREEALL4",     /* 23 */
 762 };
 763 
 764 static char *procnames_long_4[] = {
 765         "Null procedure",       /* 0 */
 766         "Test",                 /* 1 */
 767         "Lock",                 /* 2 */
 768         "Cancel",               /* 3 */
 769         "Unlock",               /* 4 */
 770         "Granted",              /* 5 */
 771         "Test message",         /* 6 */
 772         "Lock message",         /* 7 */
 773         "Cancel message",       /* 8 */
 774         "Unlock message",       /* 9 */
 775         "Granted message",      /* 10 */
 776         "Test result",          /* 11 */
 777         "Lock result",          /* 12 */
 778         "Cancel result",        /* 13 */
 779         "Unlock result",        /* 14 */
 780         "Granted result",       /* 15 */
 781         "Procedure 16",         /* 16 */
 782         "Procedure 17",         /* 17 */
 783         "Procedure 18",         /* 18 */
 784         "Procedure 19",         /* 19 */
 785         "Share",                /* 20 */
 786         "Unshare",              /* 21 */
 787         "Unmonitored lock",     /* 22 */
 788         "Free all",             /* 23 */
 789 };
 790 
 791 /* Maximum procedure number for version 4. */
 792 #define MAXPROC_4       23
 793 
 794 /* ARGSUSED */
 795 static void
 796 interpret_nlm_4(flags, type, xid, vers, proc, data, len)
 797         int flags, type, xid, vers, proc;
 798         char *data;
 799         int len;
 800 {
 801         char *line;
 802         char *pl;
 803         ulong_t i;
 804 
 805         if (proc < 0 || proc > MAXPROC_4)
 806                 return;
 807 
 808         if (flags & F_SUM) {
 809                 if (setjmp(xdr_err)) {
 810                         return;
 811                 }
 812 
 813                 line = get_sum_line();
 814 
 815                 if (type == CALL) {
 816                         (void) sprintf(line,
 817                                 "NLM C %s",
 818                                 procnames_short_4[proc]);
 819                         line += strlen(line);
 820                         switch (proc) {
 821                         case NLMPROC4_TEST:
 822                         case NLMPROC4_GRANTED:
 823                         case NLMPROC4_TEST_MSG:
 824                         case NLMPROC4_GRANTED_MSG:
 825                                 /* testargs */
 826                                 (void) strcat(line, sum_netobj("OH"));
 827                                 (void) getxdr_bool();   /* Excl */
 828                                 (void) strcat(line, sum_lock4());
 829                                 break;
 830                         case NLMPROC4_LOCK:
 831                         case NLMPROC4_LOCK_MSG:
 832                                 /* lockargs */
 833                                 (void) strcat(line, sum_netobj("OH"));
 834                                 (void) getxdr_bool();   /* Block */
 835                                 (void) getxdr_bool();   /* Excl */
 836                                 (void) strcat(line, sum_lock4());
 837                                 /* ignore reclaim, state fields */
 838                                 break;
 839                         case NLMPROC4_CANCEL:
 840                         case NLMPROC4_CANCEL_MSG:
 841                                 /* cancargs */
 842                                 (void) strcat(line, sum_netobj("OH"));
 843                                 (void) getxdr_bool();   /* Block */
 844                                 (void) getxdr_bool();   /* Excl */
 845                                 (void) strcat(line, sum_lock4());
 846                                 break;
 847                         case NLMPROC4_UNLOCK:
 848                         case NLMPROC4_UNLOCK_MSG:
 849                                 /* unlockargs */
 850                                 (void) strcat(line, sum_netobj("OH"));
 851                                 (void) strcat(line, sum_lock4());
 852                                 break;
 853                         case NLMPROC4_TEST_RES:
 854                                 /* testres */
 855                                 (void) strcat(line, sum_netobj("OH"));
 856                                 (void) strcat(line, " ");
 857                                 (void) strcat(line,
 858                                     nameof_stat4(getxdr_u_long()));
 859                                 break;
 860                         case NLMPROC4_LOCK_RES:
 861                         case NLMPROC4_CANCEL_RES:
 862                         case NLMPROC4_UNLOCK_RES:
 863                         case NLMPROC4_GRANTED_RES:
 864                                 /* res */
 865                                 (void) strcat(line, sum_netobj("OH"));
 866                                 (void) strcat(line, " ");
 867                                 (void) strcat(line,
 868                                         nameof_stat4(getxdr_u_long()));
 869                                 break;
 870                         case NLMPROC4_SHARE:
 871                         case NLMPROC4_UNSHARE:
 872                                 (void) strcat(line, sum_netobj("OH"));
 873                                 (void) strcat(line, sum_share());
 874                                 break;
 875                         case NLMPROC4_NM_LOCK:
 876                                 /* lockargs */
 877                                 skip_netobj();          /* Cookie */
 878                                 (void) getxdr_bool();   /* Block */
 879                                 (void) getxdr_bool();   /* Excl */
 880                                 (void) strcat(line, sum_lock4());
 881                                 /* skip reclaim & state fields */
 882                                 break;
 883                         case NLMPROC4_FREE_ALL:
 884                                 (void) sprintf(line,
 885                                         " %s", sum_notify());
 886                                 break;
 887                         }
 888                         check_retransmit(line, (ulong_t)xid);
 889                 } else {
 890                         (void) sprintf(line, "NLM R %s",
 891                                 procnames_short_4[proc]);
 892                         line += strlen(line);
 893                         switch (proc) {
 894                         case NLMPROC4_TEST:
 895                                 /* testres */
 896                                 (void) strcat(line, sum_netobj("OH"));
 897                                 (void) strcat(line, " ");
 898                                 (void) strcat(line,
 899                                     nameof_stat4(getxdr_u_long()));
 900                                 break;
 901                         case NLMPROC4_LOCK:
 902                         case NLMPROC4_CANCEL:
 903                         case NLMPROC4_UNLOCK:
 904                         case NLMPROC4_GRANTED:
 905                         case NLMPROC4_NM_LOCK:
 906                                 /* res */
 907                                 (void) strcat(line, sum_netobj("OH"));
 908                                 (void) strcat(line, " ");
 909                                 (void) strcat(line,
 910                                         nameof_stat4(getxdr_u_long()));
 911                                 break;
 912                         case NLMPROC4_SHARE:
 913                         case NLMPROC4_UNSHARE:
 914                                 /* shareres */
 915                                 pl = sum_netobj("OH");
 916                                 i = getxdr_u_long();
 917                                 sprintf(line, "%s %s %ld",
 918                                         pl, nameof_stat4(i), getxdr_long());
 919                                 break;
 920                         case NLMPROC4_FREE_ALL:
 921                                 break;
 922                         }
 923                 }
 924         }
 925 
 926         if (flags & F_DTAIL) {
 927                 show_header("NLM:  ", "Network Lock Manager", len);
 928                 show_space();
 929                 if (setjmp(xdr_err)) {
 930                         return;
 931                 }
 932                 (void) sprintf(get_line(0, 0),
 933                         "Proc = %d (%s)",
 934                         proc, procnames_long_4[proc]);
 935                 if (type == CALL) {
 936                         switch (proc) {
 937                         case NLMPROC4_TEST:
 938                         case NLMPROC4_GRANTED:
 939                         case NLMPROC4_TEST_MSG:
 940                         case NLMPROC4_GRANTED_MSG:
 941                                 show_testargs4();
 942                                 break;
 943                         case NLMPROC4_LOCK:
 944                         case NLMPROC4_LOCK_MSG:
 945                         case NLMPROC4_NM_LOCK:
 946                                 show_lockargs4();
 947                                 break;
 948                         case NLMPROC4_CANCEL:
 949                         case NLMPROC4_CANCEL_MSG:
 950                                 show_cancargs4();
 951                                 break;
 952                         case NLMPROC4_UNLOCK:
 953                         case NLMPROC4_UNLOCK_MSG:
 954                                 show_unlockargs4();
 955                                 break;
 956                         case NLMPROC4_TEST_RES:
 957                                 show_testres4();
 958                                 break;
 959                         case NLMPROC4_LOCK_RES:
 960                         case NLMPROC4_CANCEL_RES:
 961                         case NLMPROC4_UNLOCK_RES:
 962                         case NLMPROC4_GRANTED_RES:
 963                                 show_res4();
 964                                 break;
 965                         case NLMPROC4_SHARE:
 966                         case NLMPROC4_UNSHARE:
 967                                 show_shareargs();
 968                                 break;
 969                         case NLMPROC4_FREE_ALL:
 970                                 show_notify();
 971                                 break;
 972                         }
 973                 } else {
 974                         switch (proc) {
 975                         case NLMPROC4_TEST:
 976                                 show_testres4();
 977                                 break;
 978                         case NLMPROC4_LOCK:
 979                         case NLMPROC4_CANCEL:
 980                         case NLMPROC4_UNLOCK:
 981                         case NLMPROC4_GRANTED:
 982                         case NLM_NM_LOCK:
 983                                 show_res4();
 984                                 break;
 985                         case NLMPROC4_TEST_MSG:
 986                         case NLMPROC4_LOCK_MSG:
 987                         case NLMPROC4_CANCEL_MSG:
 988                         case NLMPROC4_UNLOCK_MSG:
 989                         case NLMPROC4_GRANTED_MSG:
 990                         case NLMPROC4_TEST_RES:
 991                         case NLMPROC4_LOCK_RES:
 992                         case NLMPROC4_CANCEL_RES:
 993                         case NLMPROC4_UNLOCK_RES:
 994                         case NLMPROC4_GRANTED_RES:
 995                                 break;
 996                         case NLM_SHARE:
 997                         case NLM_UNSHARE:
 998                                 show_shareres4();
 999                                 break;
1000                         case NLM_FREE_ALL:
1001                                 break;
1002                         }
1003                 }
1004                 show_trailer();
1005         }
1006 }
1007 
1008 static char *
1009 sum_lock4()
1010 {
1011         static char buff[LM_MAXSTRLEN + 1];
1012         char *cp = buff;
1013         long id;
1014         u_longlong_t off, len;
1015 
1016         (void) getxdr_string(buff, LM_MAXSTRLEN);       /* Caller */
1017         (void) strcpy(buff, sum_netobj("FH"));          /* Fh */
1018         cp += strlen(buff);
1019         skip_netobj();                                  /* Owner */
1020         id  = getxdr_long();
1021         off = getxdr_u_longlong();
1022         len = getxdr_u_longlong();
1023         (void) sprintf(cp, " PID=%ld Region=%llu:%llu", id, off, len);
1024         return (buff);
1025 }
1026 
1027 static void
1028 show_lock4()
1029 {
1030         showxdr_string(LM_MAXSTRLEN, "Caller = %s");
1031         show_netobj("Filehandle = %s");
1032         show_netobj("Lock owner = %s");
1033         showxdr_long("Svid = %ld (process id)");
1034         showxdr_u_longlong("Offset = %llu bytes");
1035         showxdr_u_longlong("Length = %llu bytes");
1036 }
1037 
1038 static void
1039 show_cancargs4()
1040 {
1041         show_netobj("Cookie = %s");
1042         showxdr_bool("Block = %s");
1043         showxdr_bool("Exclusive = %s");
1044         show_lock4();
1045 }
1046 
1047 static void
1048 show_lockargs4()
1049 {
1050         show_netobj("Cookie = %s");
1051         showxdr_bool("Block = %s");
1052         showxdr_bool("Exclusive = %s");
1053         show_lock4();
1054         showxdr_bool("Reclaim = %s");
1055         showxdr_long("State = %ld");
1056 }
1057 
1058 static void
1059 show_unlockargs4()
1060 {
1061         show_netobj("Cookie = %s");
1062         show_lock4();
1063 }
1064 
1065 static void
1066 show_testargs4()
1067 {
1068         show_netobj("Cookie = %s");
1069         showxdr_bool("Exclusive = %s");
1070         show_lock4();
1071 }
1072 
1073 static void
1074 show_res4()
1075 {
1076         show_netobj("Cookie = %s");
1077         (void) show_stat4();
1078 }
1079 
1080 static char *
1081 nameof_stat4(s)
1082         ulong_t s;
1083 {
1084         switch ((enum nlm4_stats) s) {
1085         case NLM4_GRANTED:      return ("granted");
1086         case NLM4_DENIED:       return ("denied");
1087         case NLM4_DENIED_NOLOCKS:return ("denied (no locks)");
1088         case NLM4_BLOCKED:      return ("blocked");
1089         case NLM4_DENIED_GRACE_PERIOD: return ("denied (grace period)");
1090         case NLM4_DEADLCK:      return ("deadlock");
1091         case NLM4_ROFS:         return ("read-only fs");
1092         case NLM4_STALE_FH:     return ("stale fh");
1093         case NLM4_FBIG:         return ("file too big");
1094         case NLM4_FAILED:       return ("failed");
1095         default:                return ("?");
1096         }
1097 }
1098 
1099 static enum nlm4_stats
1100 show_stat4()
1101 {
1102         enum nlm4_stats s;
1103 
1104         s = (enum nlm4_stats) getxdr_u_long();
1105         (void) sprintf(get_line(0, 0),
1106             "Status = %d (%s)",
1107             s, nameof_stat4((ulong_t)s));
1108 
1109         return (s);
1110 }
1111 
1112 static void
1113 show_testres4()
1114 {
1115         show_netobj("Cookie = %s");
1116         if (show_stat() == nlm_denied) {
1117                 showxdr_bool("Exclusive = %s");
1118                 showxdr_long("Svid = %ld (process id)");
1119                 show_netobj("Owner handle = %s");
1120                 showxdr_u_longlong("Offset = %llu bytes");
1121                 showxdr_u_longlong("Length = %llu bytes");
1122         }
1123 }
1124 
1125 static void
1126 show_shareres4()
1127 {
1128         show_netobj("Cookie = %s");
1129         (void) show_stat4();
1130         showxdr_long("Sequence = %d");
1131 }