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