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