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