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