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