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