xref: /titanic_44/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_nlm.c (revision 87308b749adb04ab3f564c765b089962af3edb4d)
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 }
1137