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