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 int (*ypresp_allfn)(u_long, char *, int, char *, int, void *);
58 extern void *ypresp_data;
59 extern bool_t xdr_ypreq_key(), xdr_ypresp_val();
60 extern bool_t xdr_ypresp_all_seq();
61
62 static int _yplib_host_timeout = 10;
63
64 CLIENT *
yp_bind_host(char * server,u_long program,u_long version,u_short port,int usetcp)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 *
yp_bind_local(u_long program,u_long version)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
yp_match_host(CLIENT * client,char * indomain,char * inmap,const char * inkey,int inkeylen,char ** outval,int * outvallen)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
yp_first_host(CLIENT * client,char * indomain,char * inmap,char ** outkey,int * outkeylen,char ** outval,int * outvallen)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
yp_next_host(CLIENT * client,char * indomain,char * inmap,char * inkey,int inkeylen,char ** outkey,int * outkeylen,char ** outval,int * outvallen)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
yp_all_host(CLIENT * client,char * indomain,char * inmap,struct ypall_callback * incallback)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
yp_order_host(CLIENT * client,char * indomain,char * inmap,u_int32_t * outorder)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
yp_master_host(CLIENT * client,char * indomain,char * inmap,char ** outname)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
yp_maplist_host(CLIENT * client,char * indomain,struct ypmaplist ** outmaplist)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