1/*	$NetBSD: yplib_host.c,v 1.8 2009/04/19 06:06:39 lukem Exp $	*/
2
3/*
4 * Copyright (c) 1992, 1993 Theo de Raadt <deraadt@theos.com>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
17 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30#ifndef lint
31__RCSID("$NetBSD: yplib_host.c,v 1.8 2009/04/19 06:06:39 lukem Exp $");
32#endif
33
34#include <sys/param.h>
35#include <sys/types.h>
36#include <sys/socket.h>
37#include <sys/file.h>
38#include <sys/uio.h>
39
40#include <netinet/in.h>
41#include <arpa/inet.h>
42
43#include <ctype.h>
44#include <err.h>
45#include <errno.h>
46#include <stdio.h>
47#include <stdlib.h>
48#include <string.h>
49#include <netdb.h>
50#include <unistd.h>
51
52#include <rpc/rpc.h>
53#include <rpc/xdr.h>
54#include <rpcsvc/yp_prot.h>
55#include <rpcsvc/ypclnt.h>
56
57#include "yplib_host.h"
58
59struct timeval _yplib_host_timeout = { 10, 0 };
60
61CLIENT *
62yp_bind_host(char *server, u_int program, u_int version, u_short port,
63	     int usetcp)
64{
65	struct sockaddr_in rsrv_sin;
66	int rsrv_sock;
67	struct hostent *h;
68	static CLIENT *client;
69
70	memset(&rsrv_sin, 0, sizeof rsrv_sin);
71	rsrv_sin.sin_len = sizeof rsrv_sin;
72	rsrv_sin.sin_family = AF_INET;
73	rsrv_sock = RPC_ANYSOCK;
74	if (port != 0) {
75		rsrv_sin.sin_port = htons(port);
76	}
77
78	if (isdigit((unsigned char)*server)) {
79		if (inet_aton(server,&rsrv_sin.sin_addr) == 0) {
80			errx(1, "invalid IP address `%s'", server);
81		}
82	} else {
83		h = gethostbyname(server);
84		if(h == NULL) {
85			errx(1, "unknown host `%s'", server);
86		}
87		memcpy(&rsrv_sin.sin_addr.s_addr, h->h_addr_list[0],
88		    h->h_length);
89	}
90
91	if (usetcp)
92		client = clnttcp_create(&rsrv_sin, program, version,
93		    &rsrv_sock, 0, 0);
94	else
95		client = clntudp_create(&rsrv_sin, program, version,
96		    _yplib_host_timeout, &rsrv_sock);
97
98	if (client == NULL)
99		errx(1, "%s: no contact with host `%s'",
100		    usetcp ? "clnttcp_create" : "clntudp_create", server);
101
102	return(client);
103}
104
105CLIENT *
106yp_bind_local(u_int program, u_int version)
107{
108	struct sockaddr_in rsrv_sin;
109	int rsrv_sock;
110	static CLIENT *client;
111
112	memset(&rsrv_sin, 0, sizeof rsrv_sin);
113	rsrv_sin.sin_len = sizeof rsrv_sin;
114	rsrv_sin.sin_family = AF_INET;
115	rsrv_sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
116	rsrv_sock = RPC_ANYSOCK;
117
118	client = clntudp_create(&rsrv_sin, program, version,
119	    _yplib_host_timeout, &rsrv_sock);
120	if (client == NULL)
121		errx(1, "clntudp_create: no contact with localhost");
122
123	return(client);
124}
125
126int
127yp_match_host(CLIENT *client, char *indomain, char *inmap, const char *inkey,
128	      int inkeylen, char **outval, int *outvallen)
129{
130	struct ypresp_val yprv;
131	struct ypreq_key yprk;
132	int r;
133
134	*outval = NULL;
135	*outvallen = 0;
136
137	yprk.domain = indomain;
138	yprk.map = inmap;
139	yprk.keydat.dptr = __UNCONST(inkey);
140	yprk.keydat.dsize = inkeylen;
141
142	memset(&yprv, 0, sizeof yprv);
143
144	r = clnt_call(client, YPPROC_MATCH, xdr_ypreq_key, &yprk,
145	    xdr_ypresp_val, &yprv, _yplib_host_timeout);
146	if(r != RPC_SUCCESS)
147		clnt_perror(client, "yp_match_host: clnt_call");
148
149	if(!(r=ypprot_err(yprv.status)) ) {
150		*outvallen = yprv.valdat.dsize;
151		*outval = (char *)malloc(*outvallen+1);
152		memcpy(*outval, yprv.valdat.dptr, *outvallen);
153		(*outval)[*outvallen] = '\0';
154	}
155	xdr_free((xdrproc_t)xdr_ypresp_val, (char *)&yprv);
156	return r;
157}
158
159int
160yp_first_host(CLIENT *client, char *indomain, char *inmap, char **outkey,
161	      int *outkeylen, char **outval, int *outvallen)
162{
163	struct ypresp_key_val yprkv;
164	struct ypreq_nokey yprnk;
165	int r;
166
167	*outkey = *outval = NULL;
168	*outkeylen = *outvallen = 0;
169
170	yprnk.domain = indomain;
171	yprnk.map = inmap;
172	memset(&yprkv, 0, sizeof yprkv);
173
174	r = clnt_call(client, YPPROC_FIRST, xdr_ypreq_nokey, &yprnk,
175	    xdr_ypresp_key_val, &yprkv, _yplib_host_timeout);
176	if (r != RPC_SUCCESS)
177		clnt_perror(client, "yp_first_host: clnt_call");
178
179	if(!(r=ypprot_err(yprkv.status)) ) {
180		*outkeylen = yprkv.keydat.dsize;
181		*outkey = (char *)malloc(*outkeylen+1);
182		memcpy(*outkey, yprkv.keydat.dptr, *outkeylen);
183		(*outkey)[*outkeylen] = '\0';
184		*outvallen = yprkv.valdat.dsize;
185		*outval = (char *)malloc(*outvallen+1);
186		memcpy(*outval, yprkv.valdat.dptr, *outvallen);
187		(*outval)[*outvallen] = '\0';
188	}
189	xdr_free((xdrproc_t)xdr_ypresp_key_val, (char *)&yprkv);
190	return r;
191}
192
193int
194yp_next_host(CLIENT *client, char *indomain, char *inmap, char *inkey,
195	     int inkeylen, char **outkey, int *outkeylen, char **outval,
196	     int *outvallen)
197{
198	struct ypresp_key_val yprkv;
199	struct ypreq_key yprk;
200	int r;
201
202	*outkey = *outval = NULL;
203	*outkeylen = *outvallen = 0;
204
205	yprk.domain = indomain;
206	yprk.map = inmap;
207	yprk.keydat.dptr = inkey;
208	yprk.keydat.dsize = inkeylen;
209	memset(&yprkv, 0, sizeof yprkv);
210
211	r = clnt_call(client, YPPROC_NEXT, xdr_ypreq_key, &yprk,
212	    xdr_ypresp_key_val, &yprkv, _yplib_host_timeout);
213	if (r != RPC_SUCCESS)
214		clnt_perror(client, "yp_next_host: clnt_call");
215
216	if(!(r=ypprot_err(yprkv.status)) ) {
217		*outkeylen = yprkv.keydat.dsize;
218		*outkey = (char *)malloc(*outkeylen+1);
219		memcpy(*outkey, yprkv.keydat.dptr, *outkeylen);
220		(*outkey)[*outkeylen] = '\0';
221		*outvallen = yprkv.valdat.dsize;
222		*outval = (char *)malloc(*outvallen+1);
223		memcpy(*outval, yprkv.valdat.dptr, *outvallen);
224		(*outval)[*outvallen] = '\0';
225	}
226	xdr_free((xdrproc_t)xdr_ypresp_key_val, (char *)&yprkv);
227	return r;
228}
229
230int
231yp_all_host(CLIENT *client, const char *indomain, const char *inmap,
232	    struct ypall_callback *incallback)
233{
234	struct ypreq_nokey yprnk;
235	int status;
236
237	yprnk.domain = indomain;
238	yprnk.map = inmap;
239
240	status = clnt_call(client, YPPROC_ALL, xdr_ypreq_nokey, &yprnk,
241	    xdr_ypall, (char *)incallback, _yplib_host_timeout);
242
243	if (status != RPC_SUCCESS)
244		return YPERR_RPC;
245
246	return 0;
247}
248
249int
250yp_order_host(CLIENT *client, char *indomain, char *inmap, int *outorder)
251{
252	struct ypresp_order ypro;
253	struct ypreq_nokey yprnk;
254	int r;
255
256	yprnk.domain = indomain;
257	yprnk.map = inmap;
258
259	memset(&ypro, 0, sizeof ypro);
260
261	r = clnt_call(client, YPPROC_ORDER, xdr_ypreq_nokey, &yprnk,
262	    xdr_ypresp_order, &ypro, _yplib_host_timeout);
263	if (r != RPC_SUCCESS)
264		clnt_perror(client, "yp_order_host: clnt_call");
265
266	*outorder = ypro.ordernum;
267	xdr_free((xdrproc_t)xdr_ypresp_order, (char *)&ypro);
268	return ypprot_err(ypro.status);
269}
270
271int
272yp_master_host(CLIENT *client, char *indomain, char *inmap, char **outname)
273{
274	struct ypresp_master yprm;
275	struct ypreq_nokey yprnk;
276	int r;
277
278	yprnk.domain = indomain;
279	yprnk.map = inmap;
280
281	memset(&yprm, 0, sizeof yprm);
282
283	r = clnt_call(client, YPPROC_MASTER, xdr_ypreq_nokey, &yprnk,
284	    xdr_ypresp_master, &yprm, _yplib_host_timeout);
285	if (r != RPC_SUCCESS)
286		clnt_perror(client, "yp_master: clnt_call");
287
288	if (!(r = ypprot_err(yprm.status))) {
289		*outname = (char *)strdup(yprm.master);
290	}
291	xdr_free((xdrproc_t)xdr_ypresp_master, (char *)&yprm);
292	return r;
293}
294
295int
296yp_maplist_host(CLIENT *client, char *indomain, struct ypmaplist **outmaplist)
297{
298	struct ypresp_maplist ypml;
299	int r;
300
301	memset(&ypml, 0, sizeof ypml);
302
303	r = clnt_call(client, YPPROC_MAPLIST, xdr_ypdomain_wrap_string,
304	    indomain, xdr_ypresp_maplist, &ypml, _yplib_host_timeout);
305	if (r != RPC_SUCCESS)
306		clnt_perror(client, "yp_maplist: clnt_call");
307
308	*outmaplist = ypml.list;
309	/* NO: xdr_free(xdr_ypresp_maplist, &ypml);*/
310	return ypprot_err(ypml.status);
311}
312