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
41extern char *dlc_header;
42extern jmp_buf xdr_err;
43
44extern void check_retransmit();
45static void interpret_nlm_1();
46static void interpret_nlm_3();
47static void interpret_nlm_4();
48static char *nameof_access();
49static char *nameof_mode();
50static char *nameof_stat();
51static char *nameof_stat4();
52static void show_cancargs();
53static void show_cancargs4();
54static void show_lock();
55static void show_lock4();
56static void show_lockargs();
57static void show_lockargs4();
58static void show_netobj();
59static void show_nlm_access();
60static void show_nlm_mode();
61static void show_notify();
62static void show_res();
63static void show_res4();
64static void show_share();
65static void show_shareargs();
66static void show_shareres();
67static void show_shareres4();
68static enum nlm_stats show_stat();
69static enum nlm4_stats show_stat4();
70static void show_testargs();
71static void show_testargs4();
72static void show_testres();
73static void show_testres4();
74static void show_unlockargs();
75static void show_unlockargs4();
76static void skip_netobj();
77static char *sum_lock();
78static char *sum_lock4();
79static char *sum_netobj();
80static char *sum_notify();
81static char *sum_share();
82
83void
84interpret_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
102static 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
121static 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 */
144static void
145interpret_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 */
318static void
319skip_netobj()
320{
321	int sz = getxdr_u_long();
322
323	xdr_skip(roundup(sz));
324}
325
326static char *
327sum_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
343static void
344show_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
375static char *
376sum_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
394static void
395show_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
405static void
406show_cancargs()
407{
408	show_netobj("Cookie = %s");
409	showxdr_bool("Block = %s");
410	showxdr_bool("Exclusive = %s");
411	show_lock();
412}
413
414static void
415show_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
425static void
426show_unlockargs()
427{
428	show_netobj("Cookie = %s");
429	show_lock();
430}
431
432static void
433show_testargs()
434{
435	show_netobj("Cookie = %s");
436	showxdr_bool("Exclusive = %s");
437	show_lock();
438}
439
440static void
441show_res()
442{
443	show_netobj("Cookie = %s");
444	(void) show_stat();
445}
446
447static char *
448nameof_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
462static enum nlm_stats
463show_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
475static void
476show_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
491static char *procnames_short_3[] = {
492	"SHARE3",	/* 20 */
493	"UNSHARE3",	/* 21 */
494	"NM_LOCK3",	/* 22 */
495	"FREEALL3",	/* 23 */
496};
497
498static 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
508static void
509interpret_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
623static char *
624nameof_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
636static char *
637nameof_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
649static void
650show_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
660static void
661show_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
671static char *
672sum_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
688static void
689show_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
698static void
699show_shareargs()
700{
701	show_netobj("Cookie = %s");
702	show_share();
703	showxdr_bool("Reclaim = %s");
704}
705
706static void
707show_shareres()
708{
709	show_netobj("Cookie = %s");
710	(void) show_stat();
711	showxdr_long("Sequence = %d");
712}
713
714static void
715show_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
723static char *
724sum_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
739static 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
766static 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 */
797static void
798interpret_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
1010static char *
1011sum_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
1029static void
1030show_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
1040static void
1041show_cancargs4()
1042{
1043	show_netobj("Cookie = %s");
1044	showxdr_bool("Block = %s");
1045	showxdr_bool("Exclusive = %s");
1046	show_lock4();
1047}
1048
1049static void
1050show_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
1060static void
1061show_unlockargs4()
1062{
1063	show_netobj("Cookie = %s");
1064	show_lock4();
1065}
1066
1067static void
1068show_testargs4()
1069{
1070	show_netobj("Cookie = %s");
1071	showxdr_bool("Exclusive = %s");
1072	show_lock4();
1073}
1074
1075static void
1076show_res4()
1077{
1078	show_netobj("Cookie = %s");
1079	(void) show_stat4();
1080}
1081
1082static char *
1083nameof_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
1101static enum nlm4_stats
1102show_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
1114static void
1115show_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
1127static void
1128show_shareres4()
1129{
1130	show_netobj("Cookie = %s");
1131	(void) show_stat4();
1132	showxdr_long("Sequence = %d");
1133}
1134