1238438Sdteske/*	$OpenBSD: ypwhich.c,v 1.23 2015/02/08 23:40:35 deraadt Exp $	*/
2238438Sdteske/*	$NetBSD: ypwhich.c,v 1.6 1996/05/13 02:43:48 thorpej Exp $	*/
3238438Sdteske
4238438Sdteske/*-
5238438Sdteske * SPDX-License-Identifier: BSD-2-Clause
6238438Sdteske *
7238438Sdteske * Copyright (c) 1992, 1993 Theo de Raadt <deraadt@theos.com>
8238438Sdteske * All rights reserved.
9238438Sdteske *
10238438Sdteske * Redistribution and use in source and binary forms, with or without
11238438Sdteske * modification, are permitted provided that the following conditions
12238438Sdteske * are met:
13238438Sdteske * 1. Redistributions of source code must retain the above copyright
14238438Sdteske *    notice, this list of conditions and the following disclaimer.
15238438Sdteske * 2. Redistributions in binary form must reproduce the above copyright
16238438Sdteske *    notice, this list of conditions and the following disclaimer in the
17238438Sdteske *    documentation and/or other materials provided with the distribution.
18238438Sdteske *
19238438Sdteske * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
20238438Sdteske * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21238438Sdteske * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22238438Sdteske * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
23238438Sdteske * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24238438Sdteske * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25238438Sdteske * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26238438Sdteske * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27238438Sdteske * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28238438Sdteske * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29238438Sdteske * SUCH DAMAGE.
30238438Sdteske */
31238438Sdteske
32238438Sdteske#include <sys/param.h>
33238438Sdteske#include <sys/types.h>
34238438Sdteske#include <sys/socket.h>
35238438Sdteske
36238438Sdteske#include <netinet/in.h>
37238438Sdteske#include <arpa/inet.h>
38238438Sdteske
39238438Sdteske#include <ctype.h>
40238438Sdteske#include <err.h>
41238438Sdteske#include <netdb.h>
42238438Sdteske#include <stdio.h>
43238438Sdteske#include <stdlib.h>
44238438Sdteske#include <string.h>
45238438Sdteske#include <unistd.h>
46238438Sdteske
47238438Sdteske#include <rpc/rpc.h>
48238438Sdteske#include <rpc/xdr.h>
49238438Sdteske#include <rpcsvc/yp.h>
50238438Sdteske#include <rpcsvc/ypclnt.h>
51238438Sdteske
52238438Sdteske#include "yplib_host.h"
53238438Sdteske
54static const struct ypalias {
55	char *alias, *name;
56} ypaliases[] = {
57	{ "passwd", "passwd.byname" },
58	{ "master.passwd", "master.passwd.byname" },
59	{ "shadow", "shadow.byname" },
60	{ "group", "group.byname" },
61	{ "networks", "networks.byaddr" },
62	{ "hosts", "hosts.byaddr" },
63	{ "protocols", "protocols.bynumber" },
64	{ "services", "services.byname" },
65	{ "aliases", "mail.aliases" },
66	{ "ethers", "ethers.byname" },
67};
68
69static void
70usage(void)
71{
72	fprintf(stderr,
73	    "usage: ypwhich [-t] [-d domain] [[-h] host]\n"
74	    "       ypwhich [-t] [-d domain] [-h host] -m [mname]\n"
75	    "       ypwhich -x\n");
76	exit(1);
77}
78
79
80/*
81 * Like yp_bind except can query a specific host
82 */
83static int
84bind_host(char *dom, struct sockaddr_in *sin)
85{
86	struct hostent *hent = NULL;
87	struct ypbind_resp ypbr;
88	struct in_addr ss_addr;
89	struct timeval tv;
90	CLIENT *client;
91	int sock, r;
92
93	sock = RPC_ANYSOCK;
94	tv.tv_sec = 15;
95	tv.tv_usec = 0;
96	client = clntudp_create(sin, YPBINDPROG, YPBINDVERS, tv, &sock);
97
98	if (client == NULL) {
99		warnx("host is not bound to a ypmaster");
100		return (YPERR_YPBIND);
101	}
102
103	tv.tv_sec = 5;
104	tv.tv_usec = 0;
105
106	r = clnt_call(client, YPBINDPROC_DOMAIN,
107		(xdrproc_t)xdr_domainname, &dom,
108		(xdrproc_t)xdr_ypbind_resp, &ypbr, tv);
109	if (r != RPC_SUCCESS) {
110		warnx("can't clnt_call: %s", yperr_string(YPERR_YPBIND));
111		clnt_destroy(client);
112		return (YPERR_YPBIND);
113	} else {
114		if (ypbr.ypbind_status != YPBIND_SUCC_VAL) {
115			warnx("can't yp_bind: reason: %s",
116			    yperr_string(ypbr.ypbind_status));
117			clnt_destroy(client);
118			return (r);
119		}
120	}
121	clnt_destroy(client);
122
123	memmove(&ss_addr.s_addr, &ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
124	    sizeof (ss_addr));
125
126	hent = gethostbyaddr((char *)&ss_addr.s_addr, sizeof(ss_addr.s_addr),
127	    AF_INET);
128	if (hent != NULL)
129		printf("%s\n", hent->h_name);
130	else
131		printf("%s\n", inet_ntoa(ss_addr));
132
133	return (0);
134}
135
136int
137main(int argc, char *argv[])
138{
139	char *domain, *master, *map = NULL, *host = NULL;
140	int notrans = 0, mode = 0, c, r, i;
141	struct ypmaplist *ypml, *y;
142	struct sockaddr_in sin;
143	struct hostent *hent;
144	CLIENT *client = NULL;
145
146	yp_get_default_domain(&domain);
147	if (domain == NULL)
148		errx(1, "YP domain name not set");
149
150	while ((c = getopt(argc, argv, "xd:h:mt")) != -1)
151		switch (c) {
152		case 'x':
153			for (i = 0; i < nitems(ypaliases); i++)
154				printf("\"%s\" is an alias for \"%s\"\n",
155					ypaliases[i].alias,
156					ypaliases[i].name);
157			exit(0);
158		case 'h':
159			host = optarg;
160			break;
161		case 'd':
162			domain = optarg;
163			break;
164		case 't':
165			notrans = 1;
166			break;
167		case 'm':
168			mode = 1;
169			break;
170		default:
171			usage();
172		}
173	argc -= optind;
174	argv += optind;
175
176	if (mode == 0) {
177		switch (argc) {
178		case 0:
179			memset(&sin, 0, sizeof sin);
180			sin.sin_family = AF_INET;
181			sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
182
183			if (bind_host(domain, &sin))
184				exit(1);
185			break;
186		case 1:
187			bzero(&sin, sizeof sin);
188			sin.sin_family = AF_INET;
189			if (inet_aton(argv[0], &sin.sin_addr) == 0) {
190				hent = gethostbyname(argv[0]);
191				if (!hent) {
192					errx(1, "host %s unknown",
193					    argv[0]);
194				}
195			}
196			if (bind_host(domain, &sin))
197				exit(1);
198			break;
199		default:
200			usage();
201		}
202		exit(0);
203	}
204
205	if (argc > 1)
206		usage();
207
208	if (host != NULL)
209		client = yp_bind_host(host, YPPROG, YPVERS, 0, 1);
210
211	if (argv[0]) {
212		map = argv[0];
213		if (notrans == 0) {
214			for (i = 0; i < nitems(ypaliases); i++)
215				if (strcmp(map, ypaliases[i].alias) == 0)
216					map = ypaliases[i].name;
217		}
218
219		if (host != NULL)
220			r = yp_master_host(client, domain, map, &master);
221		else
222			r = yp_master(domain, map, &master);
223
224		switch (r) {
225		case 0:
226			printf("%s\n", master);
227			free(master);
228			break;
229		case YPERR_YPBIND:
230			errx(1, "not running ypbind");
231		default:
232			errx(1, "can't find master for map %s: reason: %s",
233			    map, yperr_string(r));
234		}
235		exit(0);
236	}
237
238	ypml = NULL;
239	if (host != NULL)
240		r = yp_maplist_host(client, domain, &ypml);
241	else
242		r = yp_maplist(domain, &ypml);
243
244	r = 0;
245	switch (r) {
246	case 0:
247		for (y = ypml; y; ) {
248			ypml = y;
249			if (host != NULL) {
250				r = yp_master_host(client,
251						   domain, ypml->map, &master);
252			} else {
253				r = yp_master(domain, ypml->map, &master);
254			}
255			switch (r) {
256			case 0:
257				printf("%s %s\n", ypml->map, master);
258				free(master);
259				break;
260			default:
261				warnx("can't find the master of %s: reason: %s",
262				    ypml->map, yperr_string(r));
263				break;
264			}
265			y = ypml->next;
266			free(ypml);
267		}
268		break;
269	case YPERR_YPBIND:
270		errx(1, "not running ypbind");
271	default:
272		errx(1, "can't get map list for domain %s: reason: %s",
273		    domain, yperr_string(r));
274	}
275	exit(0);
276}
277