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
44extern char *dlc_header;
45extern jmp_buf xdr_err;
46
47extern void check_retransmit();
48static void interpret_nlm_1();
49static void interpret_nlm_3();
50static void interpret_nlm_4();
51static char *nameof_access();
52static char *nameof_mode();
53static char *nameof_stat();
54static char *nameof_stat4();
55static void show_cancargs();
56static void show_cancargs4();
57static void show_lock();
58static void show_lock4();
59static void show_lockargs();
60static void show_lockargs4();
61static void show_netobj();
62static void show_nlm_access();
63static void show_nlm_mode();
64static void show_notify();
65static void show_res();
66static void show_res4();
67static void show_share();
68static void show_shareargs();
69static void show_shareres();
70static void show_shareres4();
71static enum nlm_stats show_stat();
72static enum nlm4_stats show_stat4();
73static void show_testargs();
74static void show_testargs4();
75static void show_testres();
76static void show_testres4();
77static void show_unlockargs();
78static void show_unlockargs4();
79static void skip_netobj();
80static char *sum_lock();
81static char *sum_lock4();
82static char *sum_netobj();
83static char *sum_notify();
84static char *sum_share();
85
86void
87interpret_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
105static 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
124static 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 */
147static void
148interpret_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 */
321static void
322skip_netobj()
323{
324	int sz = getxdr_u_long();
325
326	xdr_skip(roundup(sz));
327}
328
329static char *
330sum_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
346static void
347show_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
378static char *
379sum_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
397static void
398show_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
408static void
409show_cancargs()
410{
411	show_netobj("Cookie = %s");
412	showxdr_bool("Block = %s");
413	showxdr_bool("Exclusive = %s");
414	show_lock();
415}
416
417static void
418show_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
428static void
429show_unlockargs()
430{
431	show_netobj("Cookie = %s");
432	show_lock();
433}
434
435static void
436show_testargs()
437{
438	show_netobj("Cookie = %s");
439	showxdr_bool("Exclusive = %s");
440	show_lock();
441}
442
443static void
444show_res()
445{
446	show_netobj("Cookie = %s");
447	(void) show_stat();
448}
449
450static char *
451nameof_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
465static enum nlm_stats
466show_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
478static void
479show_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
494static char *procnames_short_3[] = {
495	"SHARE3",	/* 20 */
496	"UNSHARE3",	/* 21 */
497	"NM_LOCK3",	/* 22 */
498	"FREEALL3",	/* 23 */
499};
500
501static 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
511static void
512interpret_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
626static char *
627nameof_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
639static char *
640nameof_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
652static void
653show_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
663static void
664show_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
674static char *
675sum_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
691static void
692show_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
701static void
702show_shareargs()
703{
704	show_netobj("Cookie = %s");
705	show_share();
706	showxdr_bool("Reclaim = %s");
707}
708
709static void
710show_shareres()
711{
712	show_netobj("Cookie = %s");
713	(void) show_stat();
714	showxdr_long("Sequence = %d");
715}
716
717static void
718show_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
726static char *
727sum_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
742static 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
769static 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 */
800static void
801interpret_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
1013static char *
1014sum_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
1032static void
1033show_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
1043static void
1044show_cancargs4()
1045{
1046	show_netobj("Cookie = %s");
1047	showxdr_bool("Block = %s");
1048	showxdr_bool("Exclusive = %s");
1049	show_lock4();
1050}
1051
1052static void
1053show_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
1063static void
1064show_unlockargs4()
1065{
1066	show_netobj("Cookie = %s");
1067	show_lock4();
1068}
1069
1070static void
1071show_testargs4()
1072{
1073	show_netobj("Cookie = %s");
1074	showxdr_bool("Exclusive = %s");
1075	show_lock4();
1076}
1077
1078static void
1079show_res4()
1080{
1081	show_netobj("Cookie = %s");
1082	(void) show_stat4();
1083}
1084
1085static char *
1086nameof_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
1104static enum nlm4_stats
1105show_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
1117static void
1118show_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
1130static void
1131show_shareres4()
1132{
1133	show_netobj("Cookie = %s");
1134	(void) show_stat4();
1135	showxdr_long("Sequence = %d");
1136}
1137