xref: /titanic_51/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_nlm.c (revision b453864f3587ccc3324d7a3b0438a1e542dcfde7)
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