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