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 by Sun Microsystems, Inc.
24 * All rights reserved.
25 */
26
27#include <sys/types.h>
28#include <sys/errno.h>
29#include <setjmp.h>
30#include <string.h>
31
32#include <sys/socket.h>
33#include <sys/sockio.h>
34#include <sys/tiuser.h>
35#include <net/if.h>
36#include <netinet/in_systm.h>
37#include <netinet/in.h>
38#include <rpc/types.h>
39#include <rpc/xdr.h>
40#include <rpc/auth.h>
41#include <rpc/clnt.h>
42#include <rpc/rpc_msg.h>
43#include <rpcsvc/yp_prot.h>
44#include "snoop.h"
45
46extern char *dlc_header;
47extern jmp_buf xdr_err;
48char *ypbind_error();
49char *sum_ypxfrstat();
50char *sum_ypmaplist();
51void detail_ypmaplist();
52
53static void niscall(int);
54static void nisreply(int);
55static int detail_ypstat(void);
56static int sum_ypstat(char *);
57
58/*
59 * Defines missing from 5.0 yp_prot.h
60 */
61#define	YPBINDPROG		((ulong_t)100007)
62#define	YPBINDVERS		((ulong_t)2)
63#define	YPBINDVERS_ORIG		((ulong_t)1)
64
65/* Procedure symbols */
66
67#define	YPBINDPROC_NULL		((ulong_t)0)
68#define	YPBINDPROC_DOMAIN	((ulong_t)1)
69#define	YPBINDPROC_SETDOM	((ulong_t)2)
70
71#define	YPBIND_ERR_ERR 1		/* Internal error */
72#define	YPBIND_ERR_NOSERV 2		/* No bound server for passed domain */
73#define	YPBIND_ERR_RESC 3		/* System resource allocation failure */
74
75
76static char *procnames_bind_short[] = {
77	"NULL",			/*  0 */
78	"DOMAIN",		/*  1 */
79	"SETDOMAIN",		/*  2 */
80};
81
82static char *procnames_bind_long[] = {
83	"Null procedure",		/*  0 */
84	"Get domain name",		/*  1 */
85	"Set domain name",		/*  2 */
86};
87
88static char *procnames_short[] = {
89	"NULL",			/*  0 */
90	"DOMAIN",		/*  1 */
91	"DOMAIN_NONACK",	/*  2 */
92	"MATCH",		/*  3 */
93	"FIRST",		/*  4 */
94	"NEXT",			/*  5 */
95	"XFR",			/*  6 */
96	"CLEAR",		/*  7 */
97	"ALL",			/*  8 */
98	"MASTER",		/*  9 */
99	"ORDER",		/* 10 */
100	"MAPLIST",		/* 11 */
101	"NEWXFR",		/* 12 */
102};
103
104#define	MAXPROC_BIND	2
105#define	MAXPROC		12
106
107static char *procnames_long[] = {
108	"Null procedure",			/*  0 */
109	"Verify domain support",		/*  1 */
110	"Verify domain support (broadcast)",	/*  2 */
111	"Return value of a key",		/*  3 */
112	"Return first key-value pair in map",	/*  4 */
113	"Return next key-value pair in map",	/*  5 */
114	"Request map update (old)",		/*  6 */
115	"Close current map on server",		/*  7 */
116	"Get all key-value pairs in map",	/*  8 */
117	"Get master server",			/*  9 */
118	"Get order",				/* 10 */
119	"Return list of supported maps",	/* 11 */
120	"Request map update",			/* 12 */
121};
122
123void
124interpret_nisbind(int flags, int type, int xid, int vers, int proc, char *data,
125    int len)
126{
127	char *line;
128	char buff[YPMAXDOMAIN + 1];
129	unsigned int status;
130
131	if (proc < 0 || proc > MAXPROC_BIND)
132		return;
133
134	if (flags & F_SUM) {
135		if (setjmp(xdr_err)) {
136			return;
137		}
138
139		line = get_sum_line();
140
141		if (type == CALL) {
142			(void) sprintf(line, "NISBIND C %s",
143			    procnames_bind_short[proc]);
144			line += strlen(line);
145			switch (proc) {
146			case YPBINDPROC_NULL:
147				break;
148			case YPBINDPROC_DOMAIN:
149				(void) sprintf(line, " %s",
150				    getxdr_string(buff, YPMAXDOMAIN));
151				break;
152			case YPBINDPROC_SETDOM:
153				(void) sprintf(line, " %s",
154				    getxdr_string(buff, YPMAXDOMAIN));
155				break;
156			default:
157				break;
158			}
159			check_retransmit(line, xid);
160		} else {
161			(void) sprintf(line, "NISBIND R %s ",
162			    procnames_bind_short[proc]);
163			line += strlen(line);
164			switch (proc) {
165			case YPBINDPROC_NULL:
166				break;
167			case YPBINDPROC_DOMAIN:
168				status = getxdr_long();
169				if (status == 1) {	/* success */
170					(void) strcat(line, "OK");
171				} else {		/* failure */
172					status = getxdr_long();
173					(void) sprintf(line, "ERROR=%s",
174					    ypbind_error(status));
175				}
176				break;
177			case YPBINDPROC_SETDOM:
178				break;
179			default:
180				break;
181			}
182		}
183	}
184
185	if (flags & F_DTAIL) {
186		show_header("NISBIND:",
187		    "Network Information Service Bind", len);
188		show_space();
189		if (setjmp(xdr_err)) {
190			return;
191		}
192		(void) sprintf(get_line(0, 0), "Proc = %d (%s)",
193		    proc, procnames_bind_long[proc]);
194		if (type == CALL) {
195			switch (proc) {
196			case YPBINDPROC_NULL:
197				break;
198			case YPBINDPROC_DOMAIN:
199				(void) showxdr_string(YPMAXDOMAIN,
200				    "Domain = %s");
201				break;
202			case YPBINDPROC_SETDOM:
203				(void) showxdr_string(YPMAXDOMAIN,
204				    "Domain = %s");
205				(void) showxdr_hex(4, "Address=%s");
206				(void) showxdr_hex(2, "Port=%s");
207				(void) showxdr_u_long("Version=%lu");
208				break;
209			default:
210				break;
211			}
212		} else {
213			switch (proc) {
214			case YPBINDPROC_NULL:
215				break;
216			case YPBINDPROC_DOMAIN:
217				status = getxdr_u_long();
218				(void) sprintf(get_line(0, 0),
219				    "Status = %lu (%s)",
220				    status,
221				    status == 1 ? "OK":"Fail");
222				if (status == 1) {
223					(void) showxdr_hex(4, "Address=%s");
224					(void) showxdr_hex(2, "Port=%s");
225				} else {
226					status = getxdr_u_long();
227					(void) sprintf(get_line(0, 0),
228					    "Error = %lu (%s)", status,
229					    ypbind_error(status));
230				}
231				break;
232			case YPBINDPROC_SETDOM:
233				break;
234			default:
235				break;
236			}
237		}
238		show_trailer();
239	}
240}
241
242void
243interpret_nis(int flags, int type, int xid, int vers, int proc, char *data,
244    int len)
245{
246	char *line;
247	char *dom, *map, *key;
248	int transid, status;
249	/* buffers are all the same size so we don't have to keep track */
250	char buff1[YPMAXRECORD + 1], buff2[YPMAXRECORD + 1];
251	char buff3[YPMAXRECORD + 1];
252
253	if (flags & F_SUM) {
254		if (setjmp(xdr_err)) {
255			return;
256		}
257
258		line = get_sum_line();
259
260		if (type == CALL) {
261			if (proc > MAXPROC)
262				(void) sprintf(line, "NIS C %d", proc);
263			else
264				(void) sprintf(line, "NIS C %s",
265				    procnames_short[proc]);
266			line += strlen(line);
267			switch (proc) {
268			case YPPROC_NULL:
269				break;
270			case YPPROC_DOMAIN:
271			case YPPROC_DOMAIN_NONACK:
272			case YPPROC_MAPLIST:
273				/* YPMAXDOMAIN > YPMAXMAP */
274				(void) sprintf(line, " %s",
275				    getxdr_string(buff1, YPMAXDOMAIN));
276				break;
277			case YPPROC_FIRST:
278				dom = getxdr_string(buff1, YPMAXDOMAIN);
279				map = getxdr_string(buff2, YPMAXMAP);
280				(void) sprintf(line, " %s", map);
281				break;
282			case YPPROC_MATCH:
283			case YPPROC_NEXT:
284				dom = getxdr_string(buff1, YPMAXDOMAIN);
285				map = getxdr_string(buff2, YPMAXMAP);
286				key = getxdr_string(buff3, YPMAXRECORD);
287				(void) sprintf(line, " %s in %s", key, map);
288				break;
289			case YPPROC_NEWXFR:
290			case YPPROC_XFR:
291				dom = getxdr_string(buff1, YPMAXDOMAIN);
292				map = getxdr_string(buff2, YPMAXMAP);
293				(void) sprintf(line, " map %s in %s", map, dom);
294				break;
295			case YPPROC_CLEAR:
296				break;
297			case YPPROC_ALL:
298			case YPPROC_MASTER:
299			case YPPROC_ORDER:
300				dom = getxdr_string(buff1, YPMAXDOMAIN);
301				map = getxdr_string(buff2, YPMAXMAP);
302				(void) sprintf(line, " map %s in %s", map, dom);
303				break;
304			default:
305				break;
306			}
307			check_retransmit(line, xid);
308		} else {
309			if (proc > MAXPROC)
310				(void) sprintf(line, "NIS R %d ", proc);
311			else
312				(void) sprintf(line, "NIS R %s ",
313				    procnames_short[proc]);
314			line += strlen(line);
315			switch (proc) {
316			case YPPROC_NULL:
317				break;
318			case YPPROC_DOMAIN:
319			case YPPROC_DOMAIN_NONACK:
320				(void) sprintf(line, "%s",
321				    getxdr_long() ? "OK":"Fail");
322				break;
323			case YPPROC_MATCH:
324				(void) sum_ypstat(line);
325				break;
326			case YPPROC_FIRST:
327			case YPPROC_NEXT:
328				if (sum_ypstat(line) == YP_TRUE) {
329					line += strlen(line);
330					(void) getxdr_string(buff1,
331					    YPMAXRECORD);
332					(void) sprintf(line, " key=%s",
333					    getxdr_string(buff1,
334					    YPMAXRECORD));
335				}
336				break;
337			case YPPROC_NEWXFR:
338			case YPPROC_XFR:
339				transid = getxdr_u_long();
340				status  = getxdr_long();
341				(void) sprintf(line, "transid=%lu %s", transid,
342				    sum_ypxfrstat(status));
343				break;
344			case YPPROC_CLEAR:
345				break;
346			case YPPROC_ALL:
347				if (getxdr_u_long()) {
348					(void) sum_ypstat(line);
349					line += strlen(line);
350					(void) sprintf(line, " key=%s",
351					    getxdr_string(buff1, YPMAXRECORD));
352				} else {
353					(void) sprintf(line, "No more");
354				}
355				break;
356			case YPPROC_MASTER:
357				if (sum_ypstat(line) == YP_TRUE) {
358					line += strlen(line);
359					(void) sprintf(line, " peer=%s",
360					    getxdr_string(buff1, YPMAXPEER));
361				}
362				break;
363			case YPPROC_ORDER:
364				if (sum_ypstat(line) == YP_TRUE) {
365					line += strlen(line);
366					(void) sprintf(line, " order=%lu",
367					    getxdr_u_long());
368				}
369				break;
370			case YPPROC_MAPLIST:
371				if (sum_ypstat(line) == YP_TRUE) {
372					line += strlen(line);
373					(void) sprintf(line, " %s",
374					    sum_ypmaplist());
375				}
376				break;
377			default:
378				break;
379			}
380		}
381	}
382
383	if (flags & F_DTAIL) {
384		show_header("NIS:  ", "Network Information Service", len);
385		show_space();
386		if (setjmp(xdr_err)) {
387			return;
388		}
389		(void) sprintf(get_line(0, 0), "Proc = %d (%s)", proc,
390		    proc > MAXPROC ? "unknown" : procnames_long[proc]);
391		if (type == CALL)
392			niscall(proc);
393		else
394			nisreply(proc);
395		show_trailer();
396	}
397}
398
399/*
400 *  Print out version 2 NIS call packets
401 */
402
403static void
404niscall(int proc)
405{
406	switch (proc) {
407	case YPPROC_NULL:
408		break;
409	case YPPROC_DOMAIN:
410	case YPPROC_DOMAIN_NONACK:
411	case YPPROC_MAPLIST:
412		(void) showxdr_string(YPMAXDOMAIN, "Domain = %s");
413		break;
414	case YPPROC_FIRST:
415		(void) showxdr_string(YPMAXDOMAIN, "Domain = %s");
416		(void) showxdr_string(YPMAXMAP, "Map = %s");
417		break;
418	case YPPROC_MATCH:
419	case YPPROC_NEXT:
420		(void) showxdr_string(YPMAXDOMAIN, "Domain = %s");
421		(void) showxdr_string(YPMAXMAP, "Map = %s");
422		(void) showxdr_string(YPMAXRECORD, "Key = %s");
423		break;
424	case YPPROC_NEWXFR:
425		(void) showxdr_string(YPMAXDOMAIN, "Domain = %s");
426		(void) showxdr_string(YPMAXMAP, "Map = %s");
427		(void) showxdr_u_long("Order = %lu");
428		(void) showxdr_string(YPMAXPEER, "Peer = %s");
429		(void) showxdr_u_long("Transid = %lu");
430		(void) showxdr_u_long("Prog = %lu");
431		(void) showxdr_string(YPMAXPEER, "Name = %s");
432		break;
433	case YPPROC_XFR:
434		(void) showxdr_string(YPMAXDOMAIN, "Domain = %s");
435		(void) showxdr_string(YPMAXMAP, "Map = %s");
436		(void) showxdr_u_long("Order = %lu");
437		(void) showxdr_string(YPMAXPEER, "Peer = %s");
438		(void) showxdr_u_long("Transid = %lu");
439		(void) showxdr_u_long("Prog = %lu");
440		(void) showxdr_u_long("Port = %lu");
441		break;
442	case YPPROC_CLEAR:
443		break;
444	case YPPROC_ALL:
445	case YPPROC_MASTER:
446	case YPPROC_ORDER:
447		(void) showxdr_string(YPMAXDOMAIN, "Domain = %s");
448		(void) showxdr_string(YPMAXMAP, "Map = %s");
449		break;
450	default:
451		break;
452	}
453}
454
455/*
456 *  Print out version 2 NIS reply packets
457 */
458
459void
460nisreply(int proc)
461{
462	unsigned int xfrstat, more;
463
464	switch (proc) {
465	case YPPROC_NULL:
466		break;
467	case YPPROC_DOMAIN:
468	case YPPROC_DOMAIN_NONACK:
469		(void) sprintf(get_line(0, 0), "Result=%s",
470		    getxdr_u_long() ? "OK":"Fail");
471		break;
472	case YPPROC_MATCH:
473		(void) detail_ypstat();
474		(void) showxdr_string(YPMAXRECORD, "Value = %s");
475		break;
476	case YPPROC_FIRST:
477	case YPPROC_NEXT:
478		(void) detail_ypstat();
479		(void) showxdr_string(YPMAXRECORD, "Value = %s");
480		(void) showxdr_string(YPMAXRECORD, "Key = %s");
481		break;
482	case YPPROC_NEWXFR:
483	case YPPROC_XFR:
484		(void) showxdr_u_long("Transid = %lu");
485		xfrstat = getxdr_u_long();
486		(void) sprintf(get_line(0, 0), "Transfer status = %lu (%s)",
487		    xfrstat, sum_ypxfrstat(xfrstat));
488		break;
489	case YPPROC_CLEAR:
490		break;
491	case YPPROC_ALL:
492		more = getxdr_u_long();
493		(void) sprintf(get_line(0, 0), "More = %s",
494		    more ? "true" : "false");
495		if (more) {
496			(void) detail_ypstat();
497			(void) showxdr_string(YPMAXRECORD, "Value = %s");
498			(void) showxdr_string(YPMAXRECORD, "Key = %s");
499		}
500		break;
501	case YPPROC_MASTER:
502		(void) detail_ypstat();
503		(void) showxdr_string(YPMAXPEER, "Peer = %s");
504		break;
505	case YPPROC_ORDER:
506		(void) detail_ypstat();
507		(void) showxdr_u_long("Order=%lu");
508		break;
509	case YPPROC_MAPLIST:
510		(void) detail_ypstat();
511		detail_ypmaplist();
512		break;
513	default:
514		break;
515	}
516}
517
518char *
519sum_ypxfrstat(int status)
520{
521	static char buff [16];
522
523	switch (status) {
524	case   1:	return ("Success");
525	case   2:	return ("Master's version not newer");
526	case  -1:	return ("Can't find server for map");
527	case  -2:	return ("No such domain");
528	case  -3:	return ("Resource allocation failure");
529	case  -4:	return ("RPC failure talking to server");
530	case  -5:	return ("Can't get master address");
531	case  -6:	return ("NIS server/map db error");
532	case  -7:	return ("Bad arguments");
533	case  -8:	return ("Local dbm operation failed");
534	case  -9:	return ("Local file I/O operation failed");
535	case -10:	return ("Map version skew during transfer");
536	case -11:	return ("Can't send clear req to local ypserv");
537	case -12:	return ("No local order number in map");
538	case -13:	return ("Transfer error");
539	case -14:	return ("Transfer request refused");
540	default:
541		(void) sprintf(buff, "(%d)", status);
542		return (buff);
543	}
544	/* NOTREACHED */
545}
546
547static int
548sum_ypstat(char *line)
549{
550	ulong_t status;
551	char *str;
552	char buff[16];
553
554	status = getxdr_u_long();
555	switch (status) {
556	case YP_TRUE:	str = "OK";			break;
557	case YP_NOMORE:	str = "No more entries";	break;
558	case YP_FALSE:	str = "Fail";			break;
559	case YP_NOMAP:	str = "No such map";		break;
560	case YP_NODOM:	str = "No such domain";		break;
561	case YP_NOKEY:	str = "No such key";		break;
562	case YP_BADOP:	str = "Invalid operation";	break;
563	case YP_BADDB:	str = "Bad database";		break;
564	case YP_YPERR:	str = "Server error";		break;
565	case YP_BADARGS:str = "Bad args";		break;
566	case YP_VERS:	str = "Version mismatch";	break;
567	default:	(void) sprintf(buff, "(%lu)", status);
568			str = buff;
569			break;
570	}
571	(void) strcpy(line, str);
572	return ((int)status);
573}
574
575static int
576detail_ypstat(void)
577{
578	ulong_t status;
579	char buff[32];
580
581
582	status = sum_ypstat(buff);
583	(void) sprintf(get_line(0, 0), "Status = %d (%s)", status, buff);
584
585	return ((int)status);
586}
587
588char *
589sum_ypmaplist(void)
590{
591	static char buff[YPMAXMAP + 1];
592	int maps = 0;
593
594	if (setjmp(xdr_err)) {
595		(void) sprintf(buff, "%d+ maps", maps);
596		return (buff);
597	}
598
599	while (getxdr_long()) {
600		(void) getxdr_string(buff, YPMAXMAP);
601		maps++;
602	}
603
604	(void) sprintf(buff, "%d maps", maps);
605	return (buff);
606}
607
608void
609detail_ypmaplist(void)
610{
611	int maps = 0;
612
613	if (setjmp(xdr_err)) {
614		(void) sprintf(get_line(0, 0),
615		    " %d+ maps. (Frame is incomplete)", maps);
616		return;
617	}
618
619	(void) sprintf(get_line(0, 0), "Map list");
620
621	while (getxdr_long()) {
622		(void) showxdr_string(YPMAXMAP, "  %s");
623		maps++;
624	}
625
626	(void) sprintf(get_line(0, 0), "%d maps", maps);
627}
628
629char *
630ypbind_error(int err)
631{
632	static char buff[16];
633
634	switch (err) {
635	case YPBIND_ERR_ERR:	return ("Internal error");
636	case YPBIND_ERR_NOSERV:	return ("Internal error");
637	case YPBIND_ERR_RESC:	return ("Resource allocation fail");
638	default:
639		(void) sprintf(buff, "(%d)", err);
640		return (buff);
641	}
642	/* NOTREACHED */
643}
644