xref: /illumos-gate/usr/src/lib/libnsl/yp/yp_enum.c (revision e8031f0a8ed0e45c6d8847c5e09424e66fd34a4b)
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
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
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
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
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
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
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