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