Home | History | Annotate | Download | only in yp
      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