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