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, 1999-2000 by Sun Microsystems, Inc.
24 * All rights reserved.
25 */
26
27#ident	"%Z%%M%	%I%	%E% SMI"	/* SunOS	*/
28
29#include <sys/types.h>
30#include <sys/errno.h>
31#include <setjmp.h>
32#include <sys/tiuser.h>
33
34#include <rpc/types.h>
35#include <rpc/xdr.h>
36#include <rpc/auth.h>
37#include <rpc/clnt.h>
38#include <rpc/rpc_msg.h>
39#include <nfs/nfs.h>
40#include <rpcsvc/mount.h>
41#include <string.h>
42#include "snoop.h"
43#include "snoop_nfs.h"
44
45#ifndef MIN
46#define	MIN(a, b) ((a) < (b) ? (a) : (b))
47#endif
48
49extern char *dlc_header;
50extern jmp_buf xdr_err;
51
52static void mountcall(int, int);
53static void mountreply(int, int);
54
55static void sum_mountstat(char *);
56static void sum_mountstat3(char *);
57static char *sum_mountfh(void);
58static char *sum_mountfh3(void);
59static char *sum_exports(void);
60static char *sum_mounts(void);
61
62static int detail_mountstat(void);
63static void detail_mountstat3(void);
64static void detail_mountfh(void);
65static void detail_mountfh3(void);
66static void detail_exports(void);
67static void detail_mounts(void);
68
69static char *statusmsg3(ulong_t);
70
71static char *procnames_short[] = {
72	"Null",			/*  0 */
73	"Mount",		/*  1 */
74	"Get mount list",	/*  2 */
75	"Unmount",		/*  3 */
76	"Unmountall",		/*  4 */
77	"Get export list",	/*  5 */
78	"Get export list",	/*  6 */
79	"PATHCONF",		/*  7 */
80};
81
82static char *procnames_long[] = {
83	"Null procedure",		/*  0 */
84	"Add mount entry",		/*  1 */
85	"Return mount entries",		/*  2 */
86	"Remove mount entry",		/*  3 */
87	"Remove all mount entries",	/*  4 */
88	"Return export list",		/*  5 */
89	"Return export list",		/*  6 */
90	"Get POSIX Pathconf info",	/*  7 */
91};
92
93#define	MAXPROC	7
94
95void
96interpret_mount(flags, type, xid, vers, proc, data, len)
97	int flags, type, xid, vers, proc;
98	char *data;
99	int len;
100{
101	char *line;
102	char buff[MNTPATHLEN + 1];
103
104	if (proc < 0 || proc > MAXPROC)
105		return;
106
107	if (flags & F_SUM) {
108		if (setjmp(xdr_err)) {
109			return;
110		}
111
112		line = get_sum_line();
113
114		if (type == CALL) {
115			(void) sprintf(line, "MOUNT%d C %s",
116				vers, procnames_short[proc]);
117			line += strlen(line);
118			switch (proc) {
119			case MOUNTPROC_MNT:
120			case MOUNTPROC_UMNT:
121				(void) sprintf(line, " %s",
122					getxdr_string(buff, MNTPATHLEN));
123				break;
124			case MOUNTPROC_DUMP:
125			case MOUNTPROC_UMNTALL:
126			case MOUNTPROC_EXPORT:
127			case MOUNTPROC_EXPORTALL:
128#ifdef MOUNTPROC_PATHCONF
129			case MOUNTPROC_PATHCONF:
130				if (vers != 3)
131					(void) sprintf(line, " %s",
132						getxdr_string(buff,
133						    MNTPATHLEN));
134#endif
135				break;
136			default:
137				break;
138			}
139
140			check_retransmit(line, xid);
141		} else {
142			(void) sprintf(line, "MOUNT%d R %s ",
143				vers, procnames_short[proc]);
144			line += strlen(line);
145			switch (proc) {
146			case MOUNTPROC_MNT:
147				if (vers == 3)
148					sum_mountstat3(line);
149				else
150					sum_mountstat(line);
151				break;
152			case MOUNTPROC_DUMP:
153				(void) sprintf(line, sum_mounts());
154				break;
155			case MOUNTPROC_UMNT:
156			case MOUNTPROC_UMNTALL:
157				(void) sprintf(line, "reply");
158				break;
159			case MOUNTPROC_EXPORTALL:
160				/*
161				 * EXPORTALL is the same as EXPORT in v1
162				 * and v2, and it doesn't exist in v3.
163				 */
164				if (vers == 3)
165					break;
166				/*FALLTHROUGH*/
167			case MOUNTPROC_EXPORT:
168				(void) sprintf(line, sum_exports());
169				break;
170#ifdef MOUNTPROC_PATHCONF
171			case MOUNTPROC_PATHCONF:
172				if (vers != 2)
173					break;
174#ifdef notyet
175				(void) sprintf(line, sum_ppathcnf());
176#endif
177				break;
178#endif
179			default:
180				break;
181			}
182		}
183	}
184
185	if (flags & F_DTAIL) {
186		show_header("MOUNT:", "NFS MOUNT", len);
187		show_space();
188		if (setjmp(xdr_err)) {
189			return;
190		}
191		(void) sprintf(get_line(0, 0),
192			"Proc = %d (%s)",
193			proc, procnames_long[proc]);
194		if (type == CALL)
195			mountcall(proc, vers);
196		else
197			mountreply(proc, vers);
198		show_trailer();
199	}
200}
201
202/*
203 *  Interpret call packets in detail
204 */
205
206static void
207mountcall(proc, vers)
208	int proc, vers;
209{
210
211	switch (proc) {
212	case MOUNTPROC_MNT:
213	case MOUNTPROC_UMNT:
214		(void) showxdr_string(MNTPATHLEN, "Directory = %s");
215		break;
216	case MOUNTPROC_DUMP:
217		break;
218	case MOUNTPROC_UMNTALL:
219		break;
220	case MOUNTPROC_EXPORTALL:
221		if (vers == 3)
222			break;
223		break;
224	case MOUNTPROC_EXPORT:
225		break;
226#ifdef MOUNTPROC_PATHCONF
227	case MOUNTPROC_PATHCONF:
228		if (vers != 2)
229			break;
230		(void) showxdr_string(MNTPATHLEN, "File = %s");
231#endif
232		break;
233	default:
234		break;
235	}
236}
237
238/*
239 *  Interpret reply packets in detail
240 */
241
242static void
243mountreply(proc, vers)
244	int proc, vers;
245{
246
247	switch (proc) {
248	case MOUNTPROC_MNT:
249		if (vers == 3) {
250			detail_mountstat3();
251		} else {
252			if (detail_mountstat() == 0) {
253				detail_mountfh();
254			}
255		}
256		break;
257	case MOUNTPROC_DUMP:
258		detail_mounts();
259		break;
260	case MOUNTPROC_UMNT:
261	case MOUNTPROC_UMNTALL:
262		(void) detail_mountstat();
263		break;
264	case MOUNTPROC_EXPORTALL:
265		if (vers == 3)
266			break;
267		/*FALLTHROUGH*/
268	case MOUNTPROC_EXPORT:
269		detail_exports();
270		break;
271#ifdef MOUNTPROC_PATHCONF
272	case MOUNTPROC_PATHCONF:
273#ifdef notyet
274		(void) detail_ppathcnf();
275#endif
276		break;
277#endif
278	default:
279		break;
280	}
281}
282
283static void
284sum_mountstat(line)
285	char *line;
286{
287	ulong_t status;
288	char *str;
289
290	status = getxdr_u_long();
291	if (status == 0)
292		str = "OK";
293	else if ((str = strerror(status)) == (char *)NULL)
294		str = "";
295	(void) strcpy(line, str);
296	if (status == 0) {
297		(void) strcat(line, sum_mountfh());
298	}
299}
300
301static int
302detail_mountstat()
303{
304	ulong_t status;
305	char *str;
306
307	status = getxdr_u_long();
308	if (status == 0)
309		str = "OK";
310	else if ((str = strerror(status)) == (char *)NULL)
311		str = "";
312
313	(void) sprintf(get_line(0, 0), "Status = %d (%s)", status, str);
314
315	return ((int)status);
316}
317
318char *
319sum_mountfh()
320{
321	int fh;
322	static char buff[8];
323
324	fh = sum_filehandle(NFS_FHSIZE);
325	(void) sprintf(buff, " FH=%04X", fh & 0xFFFF);
326	return (buff);
327}
328
329static void
330detail_mountfh()
331{
332	int pos;
333	int fh;
334
335	pos = getxdr_pos();
336	fh = sum_filehandle(NFS_FHSIZE);
337	setxdr_pos(pos);
338	(void) sprintf(get_line(0, 0), "File handle = [%04X]", fh & 0xFFFF);
339	(void) showxdr_hex(NFS_FHSIZE, " %s");
340}
341
342static char *
343print_auth()
344{
345	int i, auth, flavors;
346	char *p;
347	static char buff[64];
348
349	buff[0] = '\0';
350	flavors = getxdr_long();
351	for (i = 0; i < flavors; i++) {
352		if (i > 0)
353			(void) strlcat(buff, ",", sizeof (buff));
354		switch (auth = getxdr_u_long()) {
355		case AUTH_NONE:
356			(void) strlcat(buff, "none", sizeof (buff));
357			break;
358		case AUTH_UNIX:
359			(void) strlcat(buff, "unix", sizeof (buff));
360			break;
361		case AUTH_SHORT:
362			(void) strlcat(buff, "short", sizeof (buff));
363			break;
364		case AUTH_DES:
365			(void) strlcat(buff, "des", sizeof (buff));
366			break;
367		default:
368			p = buff + strlen(buff);
369			if (p < &buff[sizeof (buff)])
370				(void) snprintf(p, sizeof (buff) - strlen(buff),
371					"%d", auth);
372			break;
373		}
374	}
375	return (buff);
376}
377
378static void
379sum_mountstat3(line)
380	char *line;
381{
382	ulong_t status;
383
384	status = getxdr_u_long();
385	(void) strcpy(line, statusmsg3(status));
386	if (status == 0) {
387		(void) strcat(line, sum_mountfh3());
388		(void) strcat(line, " Auth=");
389		(void) strcat(line, print_auth());
390	}
391}
392
393static void
394detail_mountstat3()
395{
396	ulong_t status;
397
398	status = getxdr_u_long();
399	(void) sprintf(get_line(0, 0), "Status = %d (%s)", status,
400			statusmsg3(status));
401	if (status == 0) {
402		detail_mountfh3();
403		(void) sprintf(get_line(0, 0), "Authentication flavor = %s",
404				print_auth());
405	}
406}
407
408char *
409sum_mountfh3()
410{
411	int len;
412	int fh;
413	static char buff[8];
414
415	len = getxdr_long();
416	fh = sum_filehandle(len);
417	(void) sprintf(buff, " FH=%04X", fh & 0xFFFF);
418	return (buff);
419}
420
421static void
422detail_mountfh3()
423{
424	int pos;
425	int i, l, len;
426	int fh;
427
428	len = getxdr_long();
429	pos = getxdr_pos();
430	fh = sum_filehandle(len);
431	setxdr_pos(pos);
432	(void) sprintf(get_line(0, 0), "File handle = [%04X]", fh & 0xFFFF);
433	i = 0;
434	while (i < len) {
435		l = MIN(len - i, 32);
436		(void) showxdr_hex(l, " %s");
437		i += l;
438	}
439}
440
441static char *
442sum_exports()
443{
444	static char buff[MNTPATHLEN + 1];
445	int entries = 0;
446
447	if (setjmp(xdr_err)) {
448		(void) sprintf(buff, "%d+ entries", entries);
449		return (buff);
450	}
451
452	while (getxdr_long()) {
453		(void) getxdr_string(buff, MNTPATHLEN);
454		while (getxdr_long()) {
455			(void) getxdr_string(buff, MNTNAMLEN);
456		}
457		entries++;
458	}
459
460	(void) sprintf(buff, "%d entries", entries);
461	return (buff);
462}
463
464static void
465detail_exports()
466{
467	int entries = 0;
468	char *dirpath, *grpname;
469	char buff[MNTPATHLEN + 1];
470
471	if (setjmp(xdr_err)) {
472		(void) sprintf(get_line(0, 0),
473			" %d+ entries. (Frame is incomplete)",
474			entries);
475		return;
476	}
477
478	while (getxdr_long()) {
479		dirpath = (char *)getxdr_string(buff, MNTPATHLEN);
480		(void) sprintf(get_line(0, 0), "Directory = %s", dirpath);
481		entries++;
482		while (getxdr_long()) {
483			grpname = (char *)getxdr_string(buff, MNTNAMLEN);
484			(void) sprintf(get_line(0, 0), " Group = %s", grpname);
485		}
486	}
487}
488
489static char *
490sum_mounts()
491{
492	int entries = 0;
493	static char buff[MNTPATHLEN + 1];
494
495	if (setjmp(xdr_err)) {
496		(void) sprintf(buff, "%d+ entries", entries);
497		return (buff);
498	}
499
500	while (getxdr_long()) {
501		(void) getxdr_string(buff, MNTNAMLEN);
502		(void) getxdr_string(buff, MNTPATHLEN);
503		entries++;
504	}
505
506	(void) sprintf(buff, "%d entries", entries);
507	return (buff);
508}
509
510static void
511detail_mounts()
512{
513	int entries = 0;
514	char *hostname, *directory;
515	char buff1[MNTNAMLEN + 1], buff2[MNTPATHLEN + 1];
516
517	if (setjmp(xdr_err)) {
518		(void) sprintf(get_line(0, 0),
519			" %d+ entries. (Frame is incomplete)",
520			entries);
521		return;
522	}
523
524	(void) sprintf(get_line(0, 0), "Mount list");
525
526	while (getxdr_long()) {
527		hostname  = (char *)getxdr_string(buff1, MNTNAMLEN);
528		directory = (char *)getxdr_string(buff2, MNTPATHLEN);
529		(void) sprintf(get_line(0, 0), "   %s:%s", hostname, directory);
530		entries++;
531	}
532}
533
534char *
535statusmsg3(status)
536	ulong_t status;
537{
538
539	switch (status) {
540	case MNT_OK:
541		return ("OK");
542	case MNT3ERR_PERM:
543		return ("Not owner");
544	case MNT3ERR_NOENT:
545		return ("No such file or directory");
546	case MNT3ERR_IO:
547		return ("I/O error");
548	case MNT3ERR_ACCES:
549		return ("Permission denied");
550	case MNT3ERR_NOTDIR:
551		return ("Not a directory");
552	case MNT3ERR_INVAL:
553		return ("Invalid argument");
554	case MNT3ERR_NAMETOOLONG:
555		return ("File name too long");
556	case MNT3ERR_NOTSUPP:
557		return ("Operation not supported");
558	case MNT3ERR_SERVERFAULT:
559		return ("Server error");
560	default:
561		return ("(unknown error)");
562	}
563}
564