xref: /illumos-gate/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_nis.c (revision 66582b606a8194f7f3ba5b3a3a6dca5b0d346361)
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 
46 extern char *dlc_header;
47 extern jmp_buf xdr_err;
48 char *ypbind_error();
49 char *sum_ypxfrstat();
50 char *sum_ypmaplist();
51 void detail_ypmaplist();
52 
53 static void niscall(int);
54 static void nisreply(int);
55 static int detail_ypstat(void);
56 static 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 
76 static char *procnames_bind_short[] = {
77 	"NULL",			/*  0 */
78 	"DOMAIN",		/*  1 */
79 	"SETDOMAIN",		/*  2 */
80 };
81 
82 static char *procnames_bind_long[] = {
83 	"Null procedure",		/*  0 */
84 	"Get domain name",		/*  1 */
85 	"Set domain name",		/*  2 */
86 };
87 
88 static 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 
107 static 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 
123 void
124 interpret_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 
242 void
243 interpret_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 
403 static void
404 niscall(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 
459 void
460 nisreply(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 
518 char *
519 sum_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 
547 static int
548 sum_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 
575 static int
576 detail_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 
588 char *
589 sum_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 
608 void
609 detail_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 
629 char *
630 ypbind_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