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