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