ypwhich.c revision 36914
1303231Sdim/*
2303231Sdim * Copyright (c) 1992/3 Theo de Raadt <deraadt@fsa.ca>
3353358Sdim * All rights reserved.
4353358Sdim *
5353358Sdim * Redistribution and use in source and binary forms, with or without
6303231Sdim * modification, are permitted provided that the following conditions
7303231Sdim * are met:
8303231Sdim * 1. Redistributions of source code must retain the above copyright
9303231Sdim *    notice, this list of conditions and the following disclaimer.
10303231Sdim * 2. Redistributions in binary form must reproduce the above copyright
11303231Sdim *    notice, this list of conditions and the following disclaimer in the
12303231Sdim *    documentation and/or other materials provided with the distribution.
13353358Sdim * 3. The name of the author may not be used to endorse or promote
14303231Sdim *    products derived from this software without specific prior written
15303231Sdim *    permission.
16303231Sdim *
17303231Sdim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
18303231Sdim * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19303231Sdim * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20303231Sdim * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
21303231Sdim * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22303231Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23303231Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24303231Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25303231Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26303231Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27303231Sdim * SUCH DAMAGE.
28303231Sdim */
29303231Sdim
30303231Sdim#ifndef lint
31303231Sdimstatic const char rcsid[] =
32303231Sdim	"$Id: ypwhich.c,v 1.9 1997/08/29 11:56:51 charnier Exp $";
33303231Sdim#endif /* not lint */
34303231Sdim
35303231Sdim#include <sys/param.h>
36303231Sdim#include <sys/types.h>
37303231Sdim#include <sys/socket.h>
38303231Sdim#include <netinet/in.h>
39303231Sdim#include <arpa/inet.h>
40303231Sdim#include <ctype.h>
41303231Sdim#include <err.h>
42303231Sdim#include <netdb.h>
43303231Sdim#include <stdio.h>
44303231Sdim#include <stdlib.h>
45303231Sdim#include <string.h>
46303231Sdim#include <unistd.h>
47303231Sdim#include <rpc/rpc.h>
48303231Sdim#include <rpc/xdr.h>
49303231Sdim#include <rpcsvc/yp.h>
50303231Sdimstruct dom_binding{};
51303231Sdim#include <rpcsvc/ypclnt.h>
52303231Sdim
53303231Sdim#define ERR_USAGE	1	/* bad arguments - display 'usage' message */
54303231Sdim#define ERR_NOSUCHHOST	2	/* no such host */
55303231Sdim#define ERR_NOBINDING	3	/* error from ypbind -- domain not bound */
56303231Sdim#define ERR_NOYPBIND	4	/* ypbind not running */
57303231Sdim#define ERR_NOMASTER	5	/* could not find master server */
58314564Sdim
59303231Sdimextern bool_t xdr_domainname();
60303231Sdim
61303231Sdimstruct ypalias {
62303231Sdim	char *alias, *name;
63303231Sdim} ypaliases[] = {
64303231Sdim	{ "passwd", "passwd.byname" },
65303231Sdim	{ "master.passwd", "master.passwd.byname" },
66303231Sdim	{ "group", "group.byname" },
67303231Sdim	{ "networks", "networks.byaddr" },
68303231Sdim	{ "hosts", "hosts.byaddr" },
69303231Sdim	{ "protocols", "protocols.bynumber" },
70303231Sdim	{ "services", "services.byname" },
71303231Sdim	{ "aliases", "mail.aliases" },
72303231Sdim	{ "ethers", "ethers.byname" },
73303231Sdim};
74303231Sdim
75303231Sdimstatic void
76303231Sdimusage()
77303231Sdim{
78303231Sdim	fprintf(stderr, "%s\n%s\n",
79303231Sdim		"usage: ypwhich [-d domain] [[-t] -m [mname] | host]",
80303231Sdim		"       ypwhich -x");
81303231Sdim	exit(ERR_USAGE);
82303231Sdim}
83303231Sdim
84303231Sdim
85303231Sdim/*
86303231Sdim * Like yp_bind except can query a specific host
87303231Sdim */
88303231Sdimint
89303231Sdimbind_host(dom, sin)
90303231Sdimchar *dom;
91303231Sdimstruct sockaddr_in *sin;
92303231Sdim{
93303231Sdim	struct hostent *hent = NULL;
94303231Sdim	struct ypbind_resp ypbr;
95303231Sdim	struct timeval tv;
96303231Sdim	CLIENT *client;
97303231Sdim	int sock, r;
98303231Sdim	struct in_addr ss_addr;
99303231Sdim
100303231Sdim	sock = RPC_ANYSOCK;
101303231Sdim	tv.tv_sec = 15;
102303231Sdim	tv.tv_usec = 0;
103303231Sdim	client = clntudp_create(sin, YPBINDPROG, YPBINDVERS, tv, &sock);
104303231Sdim	if(client==NULL) {
105303231Sdim		warnx("can't clntudp_create: %s", yperr_string(YPERR_YPBIND));
106303231Sdim		return YPERR_YPBIND;
107303231Sdim	}
108303231Sdim
109303231Sdim	tv.tv_sec = 5;
110303231Sdim	tv.tv_usec = 0;
111303231Sdim	r = clnt_call(client, YPBINDPROC_DOMAIN,
112303231Sdim		xdr_domainname, &dom, xdr_ypbind_resp, &ypbr, tv);
113303231Sdim	if( r != RPC_SUCCESS) {
114303231Sdim		warnx("can't clnt_call: %s", yperr_string(YPERR_YPBIND));
115303231Sdim		clnt_destroy(client);
116303231Sdim		return YPERR_YPBIND;
117303231Sdim	} else {
118303231Sdim		if (ypbr.ypbind_status != YPBIND_SUCC_VAL) {
119303231Sdim			warnx("can't yp_bind: reason: %s",
120303231Sdim				ypbinderr_string(ypbr.ypbind_resp_u.ypbind_error));
121303231Sdim			clnt_destroy(client);
122303231Sdim			return r;
123303231Sdim		}
124303231Sdim	}
125303231Sdim	clnt_destroy(client);
126303231Sdim
127303231Sdim	ss_addr = *(struct in_addr *)ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr;
128303231Sdim	/*printf("%08x\n", ss_addr);*/
129303231Sdim	hent = gethostbyaddr((char *)&ss_addr, sizeof(ss_addr), AF_INET);
130303231Sdim	if (hent)
131303231Sdim		printf("%s\n", hent->h_name);
132303231Sdim	else
133303231Sdim		printf("%s\n", inet_ntoa(ss_addr));
134303231Sdim	return 0;
135303231Sdim}
136303231Sdim
137303231Sdimint
138303231Sdimmain(argc, argv)
139303231Sdimchar **argv;
140303231Sdim{
141303231Sdim	char *domainname = NULL, *master, *map = NULL;
142303231Sdim	struct ypmaplist *ypml, *y;
143303231Sdim	struct hostent *hent;
144303231Sdim	struct sockaddr_in sin;
145303231Sdim	int notrans, mode, getmap;
146303231Sdim	int c, r, i;
147303231Sdim
148303231Sdim	getmap = notrans = mode = 0;
149303231Sdim	while( (c=getopt(argc, argv, "xd:mt")) != -1)
150303231Sdim		switch(c) {
151303231Sdim		case 'x':
152303231Sdim			for(i=0; i<sizeof ypaliases/sizeof ypaliases[0]; i++)
153303231Sdim				printf("\"%s\" is an alias for \"%s\"\n",
154303231Sdim					ypaliases[i].alias,
155303231Sdim					ypaliases[i].name);
156303231Sdim			exit(0);
157303231Sdim		case 'd':
158303231Sdim			domainname = optarg;
159303231Sdim			break;
160303231Sdim		case 't':
161303231Sdim			notrans++;
162303231Sdim			break;
163303231Sdim		case 'm':
164303231Sdim			mode++;
165303231Sdim			break;
166303231Sdim		default:
167303231Sdim			usage();
168303231Sdim		}
169303231Sdim
170303231Sdim	if(!domainname)
171303231Sdim		yp_get_default_domain(&domainname);
172303231Sdim
173303231Sdim	if(mode==0) {
174303231Sdim		switch(argc-optind) {
175303231Sdim		case 0:
176303231Sdim			bzero(&sin, sizeof sin);
177303231Sdim			sin.sin_family = AF_INET;
178303231Sdim			sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
179303231Sdim
180303231Sdim			if(bind_host(domainname, &sin))
181303231Sdim				exit(ERR_NOBINDING);
182303231Sdim			break;
183303231Sdim		case 1:
184303231Sdim			bzero(&sin, sizeof sin);
185303231Sdim			sin.sin_family = AF_INET;
186303231Sdim			if( (sin.sin_addr.s_addr=inet_addr(argv[optind]))==-1) {
187303231Sdim				hent = gethostbyname(argv[optind]);
188303231Sdim				if(!hent)
189303231Sdim					errx(ERR_NOSUCHHOST, "host %s unknown", argv[optind]);
190303231Sdim				bcopy((char *)hent->h_addr_list[0],
191303231Sdim					(char *)&sin.sin_addr, sizeof sin.sin_addr);
192303231Sdim			}
193303231Sdim			if(bind_host(domainname, &sin))
194303231Sdim				exit(ERR_NOBINDING);
195303231Sdim			break;
196303231Sdim		default:
197303231Sdim			usage();
198303231Sdim		}
199303231Sdim		exit(0);
200303231Sdim	}
201303231Sdim
202303231Sdim	if( argc-optind > 1)
203303231Sdim		usage();
204303231Sdim
205303231Sdim	if(argv[optind]) {
206303231Sdim		map = argv[optind];
207303231Sdim		for(i=0; (!notrans) && i<sizeof ypaliases/sizeof ypaliases[0]; i++)
208303231Sdim			if( strcmp(map, ypaliases[i].alias) == 0)
209303231Sdim				map = ypaliases[i].name;
210303231Sdim		r = yp_master(domainname, map, &master);
211303231Sdim		switch(r) {
212303231Sdim		case 0:
213303231Sdim			printf("%s\n", master);
214303231Sdim			free(master);
215303231Sdim			break;
216303231Sdim		case YPERR_YPBIND:
217303231Sdim			errx(ERR_NOYPBIND, "not running ypbind");
218303231Sdim		default:
219303231Sdim			errx(ERR_NOMASTER, "can't find master for map %s. reason: %s",
220303231Sdim				map, yperr_string(r));
221303231Sdim		}
222303231Sdim		exit(0);
223303231Sdim	}
224303231Sdim
225303231Sdim	ypml = NULL;
226303231Sdim	r = yp_maplist(domainname, &ypml);
227303231Sdim	switch(r) {
228303231Sdim	case 0:
229303231Sdim		for(y=ypml; y; ) {
230303231Sdim			ypml = y;
231303231Sdim			r = yp_master(domainname, ypml->map, &master);
232303231Sdim			switch(r) {
233303231Sdim			case 0:
234303231Sdim				printf("%s %s\n", ypml->map, master);
235303231Sdim				free(master);
236303231Sdim				break;
237303231Sdim			default:
238303231Sdim				warnx("can't find the master of %s: reason: %s",
239303231Sdim					ypml->map, yperr_string(r));
240303231Sdim				break;
241303231Sdim			}
242303231Sdim			y = ypml->next;
243303231Sdim			free(ypml);
244303231Sdim		}
245303231Sdim		break;
246303231Sdim	case YPERR_YPBIND:
247303231Sdim		errx(ERR_NOYPBIND, "not running ypbind");
248303231Sdim	default:
249303231Sdim		errx(ERR_NOMASTER, "can't get map list for domain %s. reason: %s",
250303231Sdim			domainname, yperr_string(r));
251303231Sdim	}
252303231Sdim	exit(0);
253303231Sdim}
254303231Sdim