xref: /openbsd/usr.sbin/ypserv/common/yplib_host.c (revision f4147939)
1 /*	$OpenBSD: yplib_host.c,v 1.20 2018/04/26 12:42:51 guenther 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/socket.h>
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <netinet/in.h>
35 #include <arpa/inet.h>
36 #include <netdb.h>
37 #include <rpc/rpc.h>
38 #include <rpc/xdr.h>
39 #include <rpcsvc/yp.h>
40 #include <rpcsvc/ypclnt.h>
41 #include "yplib_host.h"
42 
43 int _yplib_host_timeout = 10;
44 
45 CLIENT *
yp_bind_host(char * server,u_long program,u_long version,u_short port,int usetcp)46 yp_bind_host(char *server, u_long program, u_long version, u_short port,
47     int usetcp)
48 {
49 	struct sockaddr_in rsrv_sin;
50 	static CLIENT *client;
51 	struct hostent *h;
52 	struct timeval tv;
53 	int rsrv_sock;
54 
55 	memset(&rsrv_sin, 0, sizeof rsrv_sin);
56 	rsrv_sin.sin_len = sizeof rsrv_sin;
57 	rsrv_sin.sin_family = AF_INET;
58 	rsrv_sock = RPC_ANYSOCK;
59 	if (port != 0)
60 		rsrv_sin.sin_port = htons(port);
61 
62 	if (*server >= '0' && *server <= '9') {
63 		if (inet_aton(server, &rsrv_sin.sin_addr) == 0) {
64 			fprintf(stderr, "inet_aton: invalid address %s.\n",
65 			    server);
66 			exit(1);
67 		}
68 	} else {
69 		h = gethostbyname(server);
70 		if (h == NULL) {
71 			fprintf(stderr, "gethostbyname: unknown host %s.\n",
72 			    server);
73 			exit(1);
74 		}
75 		rsrv_sin.sin_addr.s_addr = *(u_int32_t *)h->h_addr;
76 	}
77 
78 	tv.tv_sec = 10;
79 	tv.tv_usec = 0;
80 
81 	if (usetcp)
82 		client = clnttcp_create(&rsrv_sin, program, version,
83 		    &rsrv_sock, 0, 0);
84 	else
85 		client = clntudp_create(&rsrv_sin, program, version, tv,
86 		    &rsrv_sock);
87 
88 	if (client == NULL) {
89 		fprintf(stderr, "clntudp_create: no contact with host %s.\n",
90 		    server);
91 		exit(1);
92 	}
93 	return(client);
94 }
95 
96 CLIENT *
yp_bind_local(u_long program,u_long version)97 yp_bind_local(u_long program, u_long version)
98 {
99 	struct sockaddr_in rsrv_sin;
100 	static CLIENT *client;
101 	struct timeval tv;
102 	int rsrv_sock;
103 
104 	memset(&rsrv_sin, 0, sizeof rsrv_sin);
105 	rsrv_sin.sin_len = sizeof rsrv_sin;
106 	rsrv_sin.sin_family = AF_INET;
107 	rsrv_sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
108 	rsrv_sock = RPC_ANYSOCK;
109 
110 	tv.tv_sec = 10;
111 	tv.tv_usec = 0;
112 
113 	client = clntudp_create(&rsrv_sin, program, version, tv, &rsrv_sock);
114 	if (client == NULL) {
115 		fprintf(stderr,"clntudp_create: no contact with localhost.\n");
116 		exit(1);
117 	}
118 	return(client);
119 }
120 
121 int
yp_match_host(CLIENT * client,char * indomain,char * inmap,const char * inkey,int inkeylen,char ** outval,int * outvallen)122 yp_match_host(CLIENT *client, char *indomain, char *inmap, const char *inkey,
123     int inkeylen, char **outval, int *outvallen)
124 {
125 	struct ypresp_val yprv;
126 	struct ypreq_key yprk;
127 	struct timeval tv;
128 	int r;
129 
130 	*outval = NULL;
131 	*outvallen = 0;
132 
133 	tv.tv_sec = _yplib_host_timeout;
134 	tv.tv_usec = 0;
135 
136 	yprk.domain = indomain;
137 	yprk.map = inmap;
138 	yprk.key.keydat_val = (char *)inkey;
139 	yprk.key.keydat_len = inkeylen;
140 
141 	memset(&yprv, 0, sizeof yprv);
142 
143 	r = clnt_call(client, YPPROC_MATCH,
144 	    xdr_ypreq_key, &yprk, xdr_ypresp_val, &yprv, tv);
145 	if (r != RPC_SUCCESS)
146 		clnt_perror(client, "yp_match_host: clnt_call");
147 	if ( !(r = ypprot_err(yprv.stat)) ) {
148 		*outvallen = yprv.val.valdat_len;
149 		*outval = malloc(*outvallen+1);
150 		memcpy(*outval, yprv.val.valdat_val, *outvallen);
151 		(*outval)[*outvallen] = '\0';
152 	}
153 	xdr_free(xdr_ypresp_val, (char *)&yprv);
154 	return r;
155 }
156 
157 int
yp_first_host(CLIENT * client,char * indomain,char * inmap,char ** outkey,int * outkeylen,char ** outval,int * outvallen)158 yp_first_host(CLIENT *client, char *indomain, char *inmap, char **outkey,
159     int *outkeylen, char **outval, int *outvallen)
160 {
161 	struct ypresp_key_val yprkv;
162 	struct ypreq_nokey yprnk;
163 	struct timeval tv;
164 	int r;
165 
166 	*outkey = *outval = NULL;
167 	*outkeylen = *outvallen = 0;
168 
169 	tv.tv_sec = _yplib_host_timeout;
170 	tv.tv_usec = 0;
171 
172 	yprnk.domain = indomain;
173 	yprnk.map = inmap;
174 	memset(&yprkv, 0, sizeof yprkv);
175 
176 	r = clnt_call(client, YPPROC_FIRST,
177 	    xdr_ypreq_nokey, &yprnk, xdr_ypresp_key_val, &yprkv, tv);
178 	if (r != RPC_SUCCESS)
179 		clnt_perror(client, "yp_first_host: clnt_call");
180 	if ( !(r = ypprot_err(yprkv.stat)) ) {
181 		*outkeylen = yprkv.key.keydat_len;
182 		*outkey = malloc(*outkeylen+1);
183 		memcpy(*outkey, yprkv.key.keydat_val, *outkeylen);
184 		(*outkey)[*outkeylen] = '\0';
185 		*outvallen = yprkv.val.valdat_len;
186 		*outval = malloc(*outvallen+1);
187 		memcpy(*outval, yprkv.val.valdat_val, *outvallen);
188 		(*outval)[*outvallen] = '\0';
189 	}
190 	xdr_free(xdr_ypresp_key_val, (char *)&yprkv);
191 	return r;
192 }
193 
194 int
yp_next_host(CLIENT * client,char * indomain,char * inmap,char * inkey,int inkeylen,char ** outkey,int * outkeylen,char ** outval,int * outvallen)195 yp_next_host(CLIENT *client, char *indomain, char *inmap, char *inkey,
196     int inkeylen, char **outkey, int *outkeylen, char **outval, int *outvallen)
197 {
198 	struct ypresp_key_val yprkv;
199 	struct ypreq_key yprk;
200 	struct timeval tv;
201 	int r;
202 
203 	*outkey = *outval = NULL;
204 	*outkeylen = *outvallen = 0;
205 
206 	tv.tv_sec = _yplib_host_timeout;
207 	tv.tv_usec = 0;
208 
209 	yprk.domain = indomain;
210 	yprk.map = inmap;
211 	yprk.key.keydat_val = inkey;
212 	yprk.key.keydat_len = inkeylen;
213 	memset(&yprkv, 0, sizeof yprkv);
214 
215 	r = clnt_call(client, YPPROC_NEXT,
216 	    xdr_ypreq_key, &yprk, xdr_ypresp_key_val, &yprkv, tv);
217 	if (r != RPC_SUCCESS)
218 		clnt_perror(client, "yp_next_host: clnt_call");
219 	if ( !(r = ypprot_err(yprkv.stat)) ) {
220 		*outkeylen = yprkv.key.keydat_len;
221 		*outkey = malloc(*outkeylen+1);
222 		memcpy(*outkey, yprkv.key.keydat_val, *outkeylen);
223 		(*outkey)[*outkeylen] = '\0';
224 		*outvallen = yprkv.val.valdat_len;
225 		*outval = malloc(*outvallen+1);
226 		memcpy(*outval, yprkv.val.valdat_val, *outvallen);
227 		(*outval)[*outvallen] = '\0';
228 	}
229 	xdr_free(xdr_ypresp_key_val, (char *)&yprkv);
230 	return r;
231 }
232 
233 int (*ypserv_ypresp_allfn)(u_long, char *, int, char *, int, void *);
234 void *ypserv_ypresp_data;
235 
236 bool_t
ypserv_xdr_ypresp_all_seq(XDR * xdrs,u_long * objp)237 ypserv_xdr_ypresp_all_seq(XDR *xdrs, u_long *objp)
238 {
239 	struct ypresp_all out;
240 	u_long status;
241 	char *key, *val;
242 	int size;
243 	int done = 0;  /* set to 1 when the user does not want more data */
244 	bool_t rc = TRUE;  /* FALSE at the end of loop signals failure */
245 
246 	memset(&out, 0, sizeof out);
247 	while (rc && !done) {
248 		rc = FALSE;
249 		if (!xdr_ypresp_all(xdrs, &out)) {
250 			*objp = (u_long)YP_YPERR;
251 			goto fail;
252 		}
253 		if (out.more == 0)
254 			goto fail;
255 		status = out.ypresp_all_u.val.stat;
256 		if (status == YP_TRUE) {
257 			size = out.ypresp_all_u.val.key.keydat_len;
258 			if ((key = malloc(size + 1)) == NULL) {
259 				*objp = (u_long)YP_YPERR;
260 				goto fail;
261 			}
262 			(void)memcpy(key, out.ypresp_all_u.val.key.keydat_val,
263 			    size);
264 			key[size] = '\0';
265 
266 			size = out.ypresp_all_u.val.val.valdat_len;
267 			if ((val = malloc(size + 1)) == NULL) {
268 				free(key);
269 				*objp = (u_long)YP_YPERR;
270 				goto fail;
271 			}
272 			(void)memcpy(val, out.ypresp_all_u.val.val.valdat_val,
273 			    size);
274 			val[size] = '\0';
275 
276 			done = (*ypserv_ypresp_allfn)(status, key,
277 			    out.ypresp_all_u.val.key.keydat_len, val,
278 			    out.ypresp_all_u.val.val.valdat_len, ypserv_ypresp_data);
279 			free(key);
280 			free(val);
281 		} else
282 			done = 1;
283 		if (status != YP_NOMORE)
284 			*objp = status;
285 		rc = TRUE;
286 fail:
287 		xdr_free(xdr_ypresp_all, (char *)&out);
288 	}
289 	return rc;
290 }
291 
292 int
yp_all_host(CLIENT * client,char * indomain,char * inmap,struct ypall_callback * incallback)293 yp_all_host(CLIENT *client, char *indomain, char *inmap,
294     struct ypall_callback *incallback)
295 {
296 	struct ypreq_nokey yprnk;
297 	struct timeval tv;
298 	u_long status;
299 
300 	tv.tv_sec = _yplib_host_timeout;
301 	tv.tv_usec = 0;
302 
303 	yprnk.domain = indomain;
304 	yprnk.map = inmap;
305 	ypserv_ypresp_allfn = incallback->foreach;
306 	ypserv_ypresp_data = (void *)incallback->data;
307 
308 	(void) clnt_call(client, YPPROC_ALL,
309 	    xdr_ypreq_nokey, &yprnk, ypserv_xdr_ypresp_all_seq, &status, tv);
310 	if (status != YP_FALSE)
311 		return ypprot_err(status);
312 	return 0;
313 }
314 
315 int
yp_order_host(CLIENT * client,char * indomain,char * inmap,u_int32_t * outorder)316 yp_order_host(CLIENT *client, char *indomain, char *inmap, u_int32_t *outorder)
317 {
318 	struct ypresp_order ypro;
319 	struct ypreq_nokey yprnk;
320 	struct timeval tv;
321 	int r;
322 
323 	tv.tv_sec = _yplib_host_timeout;
324 	tv.tv_usec = 0;
325 
326 	yprnk.domain = indomain;
327 	yprnk.map = inmap;
328 
329 	memset(&ypro, 0, sizeof ypro);
330 
331 	r = clnt_call(client, YPPROC_ORDER,
332 	    xdr_ypreq_nokey, &yprnk, xdr_ypresp_order, &ypro, tv);
333 	if (r != RPC_SUCCESS)
334 		clnt_perror(client, "yp_order_host: clnt_call");
335 	*outorder = ypro.ordernum;
336 	xdr_free(xdr_ypresp_order, (char *)&ypro);
337 	return ypprot_err(ypro.stat);
338 }
339 
340 int
yp_master_host(CLIENT * client,char * indomain,char * inmap,char ** outname)341 yp_master_host(CLIENT *client, char *indomain, char *inmap, char **outname)
342 {
343 	struct ypresp_master yprm;
344 	struct ypreq_nokey yprnk;
345 	struct timeval tv;
346 	int r;
347 
348 	tv.tv_sec = _yplib_host_timeout;
349 	tv.tv_usec = 0;
350 	yprnk.domain = indomain;
351 	yprnk.map = inmap;
352 
353 	memset(&yprm, 0, sizeof yprm);
354 
355 	r = clnt_call(client, YPPROC_MASTER,
356 	    xdr_ypreq_nokey, &yprnk, xdr_ypresp_master, &yprm, tv);
357 	if (r != RPC_SUCCESS)
358 		clnt_perror(client, "yp_master: clnt_call");
359 	if (!(r = ypprot_err(yprm.stat)))
360 		*outname = strdup(yprm.peer);
361 	xdr_free(xdr_ypresp_master, (char *)&yprm);
362 	return r;
363 }
364 
365 int
yp_maplist_host(CLIENT * client,char * indomain,struct ypmaplist ** outmaplist)366 yp_maplist_host(CLIENT *client, char *indomain, struct ypmaplist **outmaplist)
367 {
368 	struct ypresp_maplist ypml;
369 	struct timeval tv;
370 	int r;
371 
372 	tv.tv_sec = _yplib_host_timeout;
373 	tv.tv_usec = 0;
374 
375 	memset(&ypml, 0, sizeof ypml);
376 
377 	r = clnt_call(client, YPPROC_MAPLIST,
378 	    xdr_domainname, &indomain, xdr_ypresp_maplist, &ypml, tv);
379 	if (r != RPC_SUCCESS)
380 		clnt_perror(client, "yp_maplist: clnt_call");
381 	*outmaplist = ypml.maps;
382 	/* NO: xdr_free(xdr_ypresp_maplist, &ypml);*/
383 	return ypprot_err(ypml.stat);
384 }
385