1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22
23 /*
24 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 * Copyright (c) 2016 by Delphix. All rights reserved.
27 */
28
29 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
30 /* All Rights Reserved */
31
32 /*
33 * Portions of this source code were derived from Berkeley
34 * under license from the Regents of the University of
35 * California.
36 */
37
38 #include "mt.h"
39 #include <stdlib.h>
40 #include <unistd.h>
41 #include <rpc/rpc.h>
42 #include <sys/types.h>
43 #include "yp_b.h"
44 #include <rpcsvc/yp_prot.h>
45 #include <rpcsvc/ypclnt.h>
46 #include <string.h>
47
48 extern int __yp_dobind_cflookup(char *, struct dom_binding **, int);
49
50 static int dofirst(char *, char *, struct dom_binding *, struct timeval,
51 char **, int *, char **, int *);
52
53 static int donext(char *, char *, char *, int, struct dom_binding *,
54 struct timeval, char **, int *, char **val, int *);
55
56 /*
57 * This requests the yp server associated with a given domain to return the
58 * first key/value pair from the map data base. The returned key should be
59 * used as an input to the call to ypclnt_next. This part does the parameter
60 * checking, and the do-until-success loop if 'hardlookup' is set.
61 */
62 int
__yp_first_cflookup(char * domain,char * map,char ** key,int * keylen,char ** val,int * vallen,int hardlookup)63 __yp_first_cflookup(
64 char *domain,
65 char *map,
66 char **key, /* return: key array */
67 int *keylen, /* return: bytes in key */
68 char **val, /* return: value array */
69 int *vallen, /* return: bytes in val */
70 int hardlookup)
71 {
72 size_t domlen;
73 size_t maplen;
74 struct dom_binding *pdomb;
75 int reason;
76
77 if ((map == NULL) || (domain == NULL))
78 return (YPERR_BADARGS);
79
80 domlen = strlen(domain);
81 maplen = strlen(map);
82
83 if ((domlen == 0) || (domlen > YPMAXDOMAIN) ||
84 (maplen == 0) || (maplen > YPMAXMAP))
85 return (YPERR_BADARGS);
86
87 for (;;) {
88
89 if (reason = __yp_dobind_cflookup(domain, &pdomb, hardlookup))
90 return (reason);
91
92 if (pdomb->dom_binding->ypbind_hi_vers == YPVERS) {
93
94 reason = dofirst(domain, map, pdomb, _ypserv_timeout,
95 key, keylen, val, vallen);
96
97 __yp_rel_binding(pdomb);
98 if (reason == YPERR_RPC || reason == YPERR_YPSERV ||
99 reason == YPERR_BUSY /* as if */) {
100 yp_unbind(domain);
101 if (hardlookup)
102 (void) sleep(_ypsleeptime); /* retry */
103 else
104 return (reason);
105 } else
106 break;
107 } else {
108 __yp_rel_binding(pdomb);
109 return (YPERR_VERS);
110 }
111 }
112 return (reason);
113 }
114
115 int
yp_first(char * domain,char * map,char ** key,int * keylen,char ** val,int * vallen)116 yp_first(
117 char *domain,
118 char *map,
119 char **key, /* return: key array */
120 int *keylen, /* return: bytes in key */
121 char **val, /* return: value array */
122 int *vallen) /* return: bytes in val */
123 {
124 /* traditional yp_firs loops forever until success */
125 return (__yp_first_cflookup(domain, map, key, keylen, val, vallen, 1));
126 }
127
128 /*
129 * This part of the "get first" interface talks to ypserv.
130 */
131
132 static int
dofirst(domain,map,pdomb,timeout,key,keylen,val,vallen)133 dofirst(domain, map, pdomb, timeout, key, keylen, val, vallen)
134 char *domain;
135 char *map;
136 struct dom_binding *pdomb;
137 struct timeval timeout;
138 char **key;
139 int *keylen;
140 char **val;
141 int *vallen;
142
143 {
144 struct ypreq_nokey req;
145 struct ypresp_key_val resp;
146 unsigned int retval = 0;
147
148 req.domain = domain;
149 req.map = map;
150 resp.keydat.dptr = resp.valdat.dptr = NULL;
151 resp.keydat.dsize = resp.valdat.dsize = 0;
152
153 /*
154 * Do the get first request. If the rpc call failed, return with status
155 * from this point.
156 */
157
158 (void) memset((char *)&resp, 0, sizeof (struct ypresp_key_val));
159
160 switch (clnt_call(pdomb->dom_client, YPPROC_FIRST,
161 (xdrproc_t)xdr_ypreq_nokey,
162 (char *)&req, (xdrproc_t)xdr_ypresp_key_val,
163 (char *)&resp, timeout)) {
164 case RPC_SUCCESS:
165 break;
166 case RPC_TIMEDOUT:
167 return (YPERR_YPSERV);
168 default:
169 return (YPERR_RPC);
170 }
171
172 /* See if the request succeeded */
173
174 if (resp.status != YP_TRUE) {
175 retval = ypprot_err(resp.status);
176 }
177
178 /* Get some memory which the user can get rid of as they like */
179
180 if (!retval) {
181
182 if ((*key = malloc((size_t)resp.keydat.dsize + 2)) != NULL) {
183
184 if ((*val = malloc(
185 (size_t)resp.valdat.dsize + 2)) == NULL) {
186 free(*key);
187 retval = YPERR_RESRC;
188 }
189
190 } else {
191 retval = YPERR_RESRC;
192 }
193 }
194
195 /* Copy the returned key and value byte strings into the new memory */
196
197 if (!retval) {
198 *keylen = (int)resp.keydat.dsize;
199 (void) memcpy(*key, resp.keydat.dptr,
200 (size_t)resp.keydat.dsize);
201 (*key)[resp.keydat.dsize] = '\n';
202 (*key)[resp.keydat.dsize + 1] = '\0';
203
204 *vallen = (int)resp.valdat.dsize;
205 (void) memcpy(*val, resp.valdat.dptr,
206 (size_t)resp.valdat.dsize);
207 (*val)[resp.valdat.dsize] = '\n';
208 (*val)[resp.valdat.dsize + 1] = '\0';
209 }
210
211 CLNT_FREERES(pdomb->dom_client,
212 (xdrproc_t)xdr_ypresp_key_val, (char *)&resp);
213 return (retval);
214 }
215
216 /*
217 * This requests the yp server associated with a given domain to return the
218 * "next" key/value pair from the map data base. The input key should be
219 * one returned by ypclnt_first or a previous call to ypclnt_next. The
220 * returned key should be used as an input to the next call to ypclnt_next.
221 * This part does the parameter checking, and the do-until-success loop.
222 * if 'hardlookup' is set.
223 */
224 int
__yp_next_cflookup(char * domain,char * map,char * inkey,int inkeylen,char ** outkey,int * outkeylen,char ** val,int * vallen,int hardlookup)225 __yp_next_cflookup(
226 char *domain,
227 char *map,
228 char *inkey,
229 int inkeylen,
230 char **outkey, /* return: key array associated with val */
231 int *outkeylen, /* return: bytes in key */
232 char **val, /* return: value array associated with outkey */
233 int *vallen, /* return: bytes in val */
234 int hardlookup)
235 {
236 size_t domlen;
237 size_t maplen;
238 struct dom_binding *pdomb;
239 int reason;
240
241
242 if ((map == NULL) || (domain == NULL) || (inkey == NULL))
243 return (YPERR_BADARGS);
244
245 domlen = strlen(domain);
246 maplen = strlen(map);
247
248 if ((domlen == 0) || (domlen > YPMAXDOMAIN) ||
249 (maplen == 0) || (maplen > YPMAXMAP))
250 return (YPERR_BADARGS);
251
252 for (;;) {
253 if (reason = __yp_dobind_cflookup(domain, &pdomb, hardlookup))
254 return (reason);
255
256 if (pdomb->dom_binding->ypbind_hi_vers == YPVERS) {
257
258 reason = donext(domain, map, inkey, inkeylen, pdomb,
259 _ypserv_timeout, outkey, outkeylen, val, vallen);
260
261 __yp_rel_binding(pdomb);
262
263 if (reason == YPERR_RPC || reason == YPERR_YPSERV ||
264 reason == YPERR_BUSY /* as if */) {
265 yp_unbind(domain);
266 if (hardlookup)
267 (void) sleep(_ypsleeptime); /* retry */
268 else
269 return (reason);
270 } else
271 break;
272 } else {
273 __yp_rel_binding(pdomb);
274 return (YPERR_VERS);
275 }
276 }
277
278 return (reason);
279 }
280
281 int
yp_next(char * domain,char * map,char * inkey,int inkeylen,char ** outkey,int * outkeylen,char ** val,int * vallen)282 yp_next(
283 char *domain,
284 char *map,
285 char *inkey,
286 int inkeylen,
287 char **outkey, /* return: key array associated with val */
288 int *outkeylen, /* return: bytes in key */
289 char **val, /* return: value array associated with outkey */
290 int *vallen) /* return: bytes in val */
291 {
292 /* traditional yp_next loops forever until success */
293 return (__yp_next_cflookup(domain, map, inkey, inkeylen, outkey,
294 outkeylen, val, vallen, 1));
295 }
296
297
298 /*
299 * This part of the "get next" interface talks to ypserv.
300 */
301 static int
donext(domain,map,inkey,inkeylen,pdomb,timeout,outkey,outkeylen,val,vallen)302 donext(domain, map, inkey, inkeylen, pdomb, timeout, outkey, outkeylen,
303 val, vallen)
304 char *domain;
305 char *map;
306 char *inkey;
307 int inkeylen;
308 struct dom_binding *pdomb;
309 struct timeval timeout;
310 char **outkey; /* return: key array associated with val */
311 int *outkeylen; /* return: bytes in key */
312 char **val; /* return: value array associated with outkey */
313 int *vallen; /* return: bytes in val */
314
315 {
316 struct ypreq_key req;
317 struct ypresp_key_val resp;
318 unsigned int retval = 0;
319
320 req.domain = domain;
321 req.map = map;
322 req.keydat.dptr = inkey;
323 req.keydat.dsize = inkeylen;
324
325 resp.keydat.dptr = resp.valdat.dptr = NULL;
326 resp.keydat.dsize = resp.valdat.dsize = 0;
327
328 /*
329 * Do the get next request. If the rpc call failed, return with status
330 * from this point.
331 */
332
333 switch (clnt_call(pdomb->dom_client,
334 YPPROC_NEXT, (xdrproc_t)xdr_ypreq_key, (char *)&req,
335 (xdrproc_t)xdr_ypresp_key_val, (char *)&resp,
336 timeout)) {
337 case RPC_SUCCESS:
338 break;
339 case RPC_TIMEDOUT:
340 return (YPERR_YPSERV);
341 default:
342 return (YPERR_RPC);
343 }
344
345 /* See if the request succeeded */
346
347 if (resp.status != YP_TRUE) {
348 retval = ypprot_err(resp.status);
349 }
350
351 /* Get some memory which the user can get rid of as they like */
352
353 if (!retval) {
354 if ((*outkey = malloc((size_t)
355 resp.keydat.dsize + 2)) != NULL) {
356
357 if ((*val = malloc((size_t)
358 resp.valdat.dsize + 2)) == NULL) {
359 free(*outkey);
360 retval = YPERR_RESRC;
361 }
362
363 } else {
364 retval = YPERR_RESRC;
365 }
366 }
367
368 /* Copy the returned key and value byte strings into the new memory */
369
370 if (!retval) {
371 *outkeylen = (int)resp.keydat.dsize;
372 (void) memcpy(*outkey, resp.keydat.dptr,
373 (size_t)resp.keydat.dsize);
374 (*outkey)[resp.keydat.dsize] = '\n';
375 (*outkey)[resp.keydat.dsize + 1] = '\0';
376
377 *vallen = (int)resp.valdat.dsize;
378 (void) memcpy(*val, resp.valdat.dptr,
379 (size_t)resp.valdat.dsize);
380 (*val)[resp.valdat.dsize] = '\n';
381 (*val)[resp.valdat.dsize + 1] = '\0';
382 }
383
384 CLNT_FREERES(pdomb->dom_client, (xdrproc_t)xdr_ypresp_key_val,
385 (char *)&resp);
386 return (retval);
387 }
388