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