1 /*- 2 * Copyright (c) 2009, Sun Microsystems, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * - Redistributions of source code must retain the above copyright notice, 8 * this list of conditions and the following disclaimer. 9 * - Redistributions in binary form must reproduce the above copyright notice, 10 * this list of conditions and the following disclaimer in the documentation 11 * and/or other materials provided with the distribution. 12 * - Neither the name of Sun Microsystems, Inc. nor the names of its 13 * contributors may be used to endorse or promote products derived 14 * from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 * 28 * @(#)getrpcent.c 1.14 91/03/11 Copyr 1984 Sun Micro 29 * $NetBSD: getrpcent.c,v 1.17 2000/01/22 22:19:17 mycroft Exp $ 30 * $FreeBSD: src/lib/libc/rpc/getrpcent.c,v 1.16 2007/05/17 03:34:33 jon Exp $ 31 */ 32 33 /* 34 * Copyright (c) 1984 by Sun Microsystems, Inc. 35 */ 36 37 #include <sys/param.h> 38 #include <sys/types.h> 39 #include <sys/socket.h> 40 #include <arpa/inet.h> 41 #include <assert.h> 42 #include <errno.h> 43 #include <nsswitch.h> 44 #include <netinet/in.h> 45 #include <stdio.h> 46 #include <string.h> 47 #include <stdarg.h> 48 #include <stdlib.h> 49 #include <rpc/rpc.h> 50 #ifdef YP 51 #include <rpcsvc/yp_prot.h> 52 #include <rpcsvc/ypclnt.h> 53 #endif 54 #include <unistd.h> 55 #include "namespace.h" 56 #include "reentrant.h" 57 #include "un-namespace.h" 58 #include "libc_private.h" 59 #include "nss_tls.h" 60 #ifdef NS_CACHING 61 #include "nscache.h" 62 #endif 63 64 #define RPCDB "/etc/rpc" 65 66 /* nsswitch declarations */ 67 enum constants 68 { 69 SETRPCENT = 1, 70 ENDRPCENT = 2, 71 RPCENT_STORAGE_INITIAL = 1 << 10, /* 1 KByte */ 72 RPCENT_STORAGE_MAX = 1 << 20, /* 1 MByte */ 73 }; 74 75 static const ns_src defaultsrc[] = { 76 { NSSRC_FILES, NS_SUCCESS }, 77 #ifdef YP 78 { NSSRC_NIS, NS_SUCCESS }, 79 #endif 80 { NULL, 0 } 81 }; 82 83 /* files backend declarations */ 84 struct files_state { 85 FILE *fp; 86 int stayopen; 87 }; 88 89 static int files_rpcent(void *, void *, va_list); 90 static int files_setrpcent(void *, void *, va_list); 91 92 static void files_endstate(void *); 93 NSS_TLS_HANDLING(files); 94 95 /* nis backend declarations */ 96 #ifdef YP 97 struct nis_state { 98 char domain[MAXHOSTNAMELEN]; 99 char *current; 100 int currentlen; 101 int stepping; 102 int no_name_map; 103 }; 104 105 static int nis_rpcent(void *, void *, va_list); 106 static int nis_setrpcent(void *, void *, va_list); 107 108 static void nis_endstate(void *); 109 NSS_TLS_HANDLING(nis); 110 #endif 111 112 /* get** wrappers for get**_r functions declarations */ 113 struct rpcent_state { 114 struct rpcent rpc; 115 char *buffer; 116 size_t bufsize; 117 }; 118 static void rpcent_endstate(void *); 119 NSS_TLS_HANDLING(rpcent); 120 121 union key { 122 const char *name; 123 int number; 124 }; 125 126 static int wrap_getrpcbyname_r(union key, struct rpcent *, char *, 127 size_t, struct rpcent **); 128 static int wrap_getrpcbynumber_r(union key, struct rpcent *, char *, 129 size_t, struct rpcent **); 130 static int wrap_getrpcent_r(union key, struct rpcent *, char *, 131 size_t, struct rpcent **); 132 static struct rpcent *getrpc(int (*fn)(union key, struct rpcent *, char *, 133 size_t, struct rpcent **), union key); 134 135 #ifdef NS_CACHING 136 static int rpc_id_func(char *, size_t *, va_list, void *); 137 static int rpc_marshal_func(char *, size_t *, void *, va_list, void *); 138 static int rpc_unmarshal_func(char *, size_t, void *, va_list, void *); 139 #endif 140 141 static int 142 rpcent_unpack(char *p, struct rpcent *rpc, char **r_aliases, 143 size_t aliases_size, int *errnop) 144 { 145 char *cp, **q; 146 147 assert(p != NULL); 148 149 if (*p == '#') 150 return (-1); 151 cp = strpbrk(p, "#\n"); 152 if (cp == NULL) 153 return (-1); 154 *cp = '\0'; 155 cp = strpbrk(p, " \t"); 156 if (cp == NULL) 157 return (-1); 158 *cp++ = '\0'; 159 /* THIS STUFF IS INTERNET SPECIFIC */ 160 rpc->r_name = p; 161 while (*cp == ' ' || *cp == '\t') 162 cp++; 163 rpc->r_number = atoi(cp); 164 q = rpc->r_aliases = r_aliases; 165 cp = strpbrk(cp, " \t"); 166 if (cp != NULL) 167 *cp++ = '\0'; 168 while (cp && *cp) { 169 if (*cp == ' ' || *cp == '\t') { 170 cp++; 171 continue; 172 } 173 if (q < &(r_aliases[aliases_size - 1])) 174 *q++ = cp; 175 else { 176 *errnop = ERANGE; 177 return -1; 178 } 179 180 cp = strpbrk(cp, " \t"); 181 if (cp != NULL) 182 *cp++ = '\0'; 183 } 184 *q = NULL; 185 return 0; 186 } 187 188 /* files backend implementation */ 189 static void 190 files_endstate(void *p) 191 { 192 FILE * f; 193 194 if (p == NULL) 195 return; 196 197 f = ((struct files_state *)p)->fp; 198 if (f != NULL) 199 fclose(f); 200 201 free(p); 202 } 203 204 static int 205 files_rpcent(void *retval, void *mdata, va_list ap) 206 { 207 char *name; 208 int number; 209 struct rpcent *rpc; 210 char *buffer; 211 size_t bufsize; 212 int *errnop; 213 214 char *line; 215 size_t linesize; 216 char **aliases; 217 int aliases_size; 218 char **rp; 219 220 struct files_state *st; 221 int rv; 222 int stayopen; 223 enum nss_lookup_type how; 224 225 how = (enum nss_lookup_type)mdata; 226 switch (how) 227 { 228 case nss_lt_name: 229 name = va_arg(ap, char *); 230 break; 231 case nss_lt_id: 232 number = va_arg(ap, int); 233 break; 234 case nss_lt_all: 235 break; 236 default: 237 return (NS_NOTFOUND); 238 } 239 240 rpc = va_arg(ap, struct rpcent *); 241 buffer = va_arg(ap, char *); 242 bufsize = va_arg(ap, size_t); 243 errnop = va_arg(ap, int *); 244 245 *errnop = files_getstate(&st); 246 if (*errnop != 0) 247 return (NS_UNAVAIL); 248 249 if (st->fp == NULL && (st->fp = fopen(RPCDB, "r")) == NULL) { 250 *errnop = errno; 251 return (NS_UNAVAIL); 252 } 253 254 if (how == nss_lt_all) 255 stayopen = 1; 256 else { 257 rewind(st->fp); 258 stayopen = st->stayopen; 259 } 260 261 do { 262 if ((line = fgetln(st->fp, &linesize)) == NULL) { 263 *errnop = errno; 264 rv = NS_RETURN; 265 break; 266 } 267 268 if (bufsize <= linesize + _ALIGNBYTES + sizeof(char *)) { 269 *errnop = ERANGE; 270 rv = NS_RETURN; 271 break; 272 } 273 274 aliases = (char **)_ALIGN(&buffer[linesize+1]); 275 aliases_size = (buffer + bufsize - 276 (char *)aliases)/sizeof(char *); 277 if (aliases_size < 1) { 278 *errnop = ERANGE; 279 rv = NS_RETURN; 280 break; 281 } 282 283 memcpy(buffer, line, linesize); 284 buffer[linesize] = '\0'; 285 286 rv = rpcent_unpack(buffer, rpc, aliases, aliases_size, errnop); 287 if (rv != 0) { 288 if (*errnop == 0) { 289 rv = NS_NOTFOUND; 290 continue; 291 } 292 else { 293 rv = NS_RETURN; 294 break; 295 } 296 } 297 298 switch (how) 299 { 300 case nss_lt_name: 301 if (strcmp(rpc->r_name, name) == 0) 302 goto done; 303 for (rp = rpc->r_aliases; *rp != NULL; rp++) { 304 if (strcmp(*rp, name) == 0) 305 goto done; 306 } 307 rv = NS_NOTFOUND; 308 continue; 309 done: 310 rv = NS_SUCCESS; 311 break; 312 case nss_lt_id: 313 rv = (rpc->r_number == number) ? NS_SUCCESS : 314 NS_NOTFOUND; 315 break; 316 case nss_lt_all: 317 rv = NS_SUCCESS; 318 break; 319 } 320 321 } while (!(rv & NS_TERMINATE)); 322 323 if (!stayopen && st->fp!=NULL) { 324 fclose(st->fp); 325 st->fp = NULL; 326 } 327 328 if ((rv == NS_SUCCESS) && (retval != NULL)) 329 *((struct rpcent **)retval) = rpc; 330 331 return (rv); 332 } 333 334 static int 335 files_setrpcent(void *retval __unused, void *mdata, va_list ap) 336 { 337 struct files_state *st; 338 int rv; 339 int f; 340 341 rv = files_getstate(&st); 342 if (rv != 0) 343 return (NS_UNAVAIL); 344 345 switch ((enum constants)mdata) 346 { 347 case SETRPCENT: 348 f = va_arg(ap,int); 349 if (st->fp == NULL) 350 st->fp = fopen(RPCDB, "r"); 351 else 352 rewind(st->fp); 353 st->stayopen |= f; 354 break; 355 case ENDRPCENT: 356 if (st->fp != NULL) { 357 fclose(st->fp); 358 st->fp = NULL; 359 } 360 st->stayopen = 0; 361 break; 362 default: 363 break; 364 } 365 366 return (NS_UNAVAIL); 367 } 368 369 /* nis backend implementation */ 370 #ifdef YP 371 static void 372 nis_endstate(void *p) 373 { 374 if (p == NULL) 375 return; 376 377 free(((struct nis_state *)p)->current); 378 free(p); 379 } 380 381 static int 382 nis_rpcent(void *retval, void *mdata, va_list ap) 383 { 384 char *name; 385 int number; 386 struct rpcent *rpc; 387 char *buffer; 388 size_t bufsize; 389 int *errnop; 390 391 char **rp; 392 char **aliases; 393 int aliases_size; 394 395 char *lastkey; 396 char *resultbuf; 397 int resultbuflen; 398 char buf[YPMAXRECORD + 2]; 399 400 struct nis_state *st; 401 int rv; 402 enum nss_lookup_type how; 403 int no_name_active; 404 405 how = (enum nss_lookup_type)mdata; 406 switch (how) 407 { 408 case nss_lt_name: 409 name = va_arg(ap, char *); 410 break; 411 case nss_lt_id: 412 number = va_arg(ap, int); 413 break; 414 case nss_lt_all: 415 break; 416 default: 417 return (NS_NOTFOUND); 418 } 419 420 rpc = va_arg(ap, struct rpcent *); 421 buffer = va_arg(ap, char *); 422 bufsize = va_arg(ap, size_t); 423 errnop = va_arg(ap, int *); 424 425 *errnop = nis_getstate(&st); 426 if (*errnop != 0) 427 return (NS_UNAVAIL); 428 429 if (st->domain[0] == '\0') { 430 if (getdomainname(st->domain, sizeof(st->domain)) != 0) { 431 *errnop = errno; 432 return (NS_UNAVAIL); 433 } 434 } 435 436 no_name_active = 0; 437 do { 438 switch (how) 439 { 440 case nss_lt_name: 441 if (!st->no_name_map) 442 { 443 snprintf(buf, sizeof buf, "%s", name); 444 rv = yp_match(st->domain, "rpc.byname", buf, 445 strlen(buf), &resultbuf, &resultbuflen); 446 447 switch (rv) { 448 case 0: 449 break; 450 case YPERR_MAP: 451 st->stepping = 0; 452 no_name_active = 1; 453 how = nss_lt_all; 454 455 rv = NS_NOTFOUND; 456 continue; 457 default: 458 rv = NS_NOTFOUND; 459 goto fin; 460 } 461 } else { 462 st->stepping = 0; 463 no_name_active = 1; 464 how = nss_lt_all; 465 466 rv = NS_NOTFOUND; 467 continue; 468 } 469 break; 470 case nss_lt_id: 471 snprintf(buf, sizeof buf, "%d", number); 472 if (yp_match(st->domain, "rpc.bynumber", buf, 473 strlen(buf), &resultbuf, &resultbuflen)) { 474 rv = NS_NOTFOUND; 475 goto fin; 476 } 477 break; 478 case nss_lt_all: 479 if (!st->stepping) { 480 rv = yp_first(st->domain, "rpc.bynumber", 481 &st->current, 482 &st->currentlen, &resultbuf, 483 &resultbuflen); 484 if (rv) { 485 rv = NS_NOTFOUND; 486 goto fin; 487 } 488 st->stepping = 1; 489 } else { 490 lastkey = st->current; 491 rv = yp_next(st->domain, "rpc.bynumber", 492 st->current, 493 st->currentlen, &st->current, 494 &st->currentlen, 495 &resultbuf, &resultbuflen); 496 free(lastkey); 497 if (rv) { 498 st->stepping = 0; 499 rv = NS_NOTFOUND; 500 goto fin; 501 } 502 } 503 break; 504 } 505 506 /* we need a room for additional \n symbol */ 507 if (bufsize <= resultbuflen + 1 + _ALIGNBYTES + 508 sizeof(char *)) { 509 *errnop = ERANGE; 510 rv = NS_RETURN; 511 break; 512 } 513 514 aliases=(char **)_ALIGN(&buffer[resultbuflen+2]); 515 aliases_size = (buffer + bufsize - (char *)aliases) / 516 sizeof(char *); 517 if (aliases_size < 1) { 518 *errnop = ERANGE; 519 rv = NS_RETURN; 520 break; 521 } 522 523 /* 524 * rpcent_unpack expects lines terminated with \n -- make it happy 525 */ 526 memcpy(buffer, resultbuf, resultbuflen); 527 buffer[resultbuflen] = '\n'; 528 buffer[resultbuflen+1] = '\0'; 529 free(resultbuf); 530 531 if (rpcent_unpack(buffer, rpc, aliases, aliases_size, 532 errnop) != 0) { 533 if (*errnop == 0) 534 rv = NS_NOTFOUND; 535 else 536 rv = NS_RETURN; 537 } else { 538 if ((how == nss_lt_all) && (no_name_active != 0)) { 539 if (strcmp(rpc->r_name, name) == 0) 540 goto done; 541 for (rp = rpc->r_aliases; *rp != NULL; rp++) { 542 if (strcmp(*rp, name) == 0) 543 goto done; 544 } 545 rv = NS_NOTFOUND; 546 continue; 547 done: 548 rv = NS_SUCCESS; 549 } else 550 rv = NS_SUCCESS; 551 } 552 553 } while (!(rv & NS_TERMINATE) && (how == nss_lt_all)); 554 555 fin: 556 if ((rv == NS_SUCCESS) && (retval != NULL)) 557 *((struct rpcent **)retval) = rpc; 558 559 return (rv); 560 } 561 562 static int 563 nis_setrpcent(void *retval __unused, void *mdata, va_list ap __unused) 564 { 565 struct nis_state *st; 566 int rv; 567 568 rv = nis_getstate(&st); 569 if (rv != 0) 570 return (NS_UNAVAIL); 571 572 switch ((enum constants)mdata) 573 { 574 case SETRPCENT: 575 case ENDRPCENT: 576 free(st->current); 577 st->current = NULL; 578 st->stepping = 0; 579 break; 580 default: 581 break; 582 } 583 584 return (NS_UNAVAIL); 585 } 586 #endif 587 588 #ifdef NS_CACHING 589 static int 590 rpc_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata) 591 { 592 char *name; 593 int rpc; 594 595 size_t desired_size, size; 596 enum nss_lookup_type lookup_type; 597 int res = NS_UNAVAIL; 598 599 lookup_type = (enum nss_lookup_type)cache_mdata; 600 switch (lookup_type) { 601 case nss_lt_name: 602 name = va_arg(ap, char *); 603 604 size = strlen(name); 605 desired_size = sizeof(enum nss_lookup_type) + size + 1; 606 if (desired_size > *buffer_size) { 607 res = NS_RETURN; 608 goto fin; 609 } 610 611 memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type)); 612 memcpy(buffer + sizeof(enum nss_lookup_type), name, size + 1); 613 614 res = NS_SUCCESS; 615 break; 616 case nss_lt_id: 617 rpc = va_arg(ap, int); 618 619 desired_size = sizeof(enum nss_lookup_type) + sizeof(int); 620 if (desired_size > *buffer_size) { 621 res = NS_RETURN; 622 goto fin; 623 } 624 625 memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type)); 626 memcpy(buffer + sizeof(enum nss_lookup_type), &rpc, 627 sizeof(int)); 628 629 res = NS_SUCCESS; 630 break; 631 default: 632 /* should be unreachable */ 633 return (NS_UNAVAIL); 634 } 635 636 fin: 637 *buffer_size = desired_size; 638 return (res); 639 } 640 641 static int 642 rpc_marshal_func(char *buffer, size_t *buffer_size, void *retval __unused, 643 va_list ap, void *cache_mdata) 644 { 645 char *name __unused; 646 int num __unused; 647 struct rpcent *rpc; 648 char *orig_buf __unused; 649 size_t orig_buf_size __unused; 650 651 struct rpcent new_rpc; 652 size_t desired_size, size, aliases_size; 653 char *p; 654 char **alias; 655 656 switch ((enum nss_lookup_type)cache_mdata) { 657 case nss_lt_name: 658 name = va_arg(ap, char *); 659 break; 660 case nss_lt_id: 661 num = va_arg(ap, int); 662 break; 663 case nss_lt_all: 664 break; 665 default: 666 /* should be unreachable */ 667 return (NS_UNAVAIL); 668 } 669 670 rpc = va_arg(ap, struct rpcent *); 671 orig_buf = va_arg(ap, char *); 672 orig_buf_size = va_arg(ap, size_t); 673 674 desired_size = _ALIGNBYTES + sizeof(struct rpcent) + sizeof(char *); 675 if (rpc->r_name != NULL) 676 desired_size += strlen(rpc->r_name) + 1; 677 678 if (rpc->r_aliases != NULL) { 679 aliases_size = 0; 680 for (alias = rpc->r_aliases; *alias; ++alias) { 681 desired_size += strlen(*alias) + 1; 682 ++aliases_size; 683 } 684 685 desired_size += _ALIGNBYTES + (aliases_size + 1) * 686 sizeof(char *); 687 } 688 689 if (*buffer_size < desired_size) { 690 /* this assignment is here for future use */ 691 *buffer_size = desired_size; 692 return (NS_RETURN); 693 } 694 695 memcpy(&new_rpc, rpc, sizeof(struct rpcent)); 696 697 *buffer_size = desired_size; 698 memset(buffer, 0, desired_size); 699 p = buffer + sizeof(struct rpcent) + sizeof(char *); 700 memcpy(buffer + sizeof(struct rpcent), &p, sizeof(char *)); 701 p = (char *)_ALIGN(p); 702 703 if (new_rpc.r_name != NULL) { 704 size = strlen(new_rpc.r_name); 705 memcpy(p, new_rpc.r_name, size); 706 new_rpc.r_name = p; 707 p += size + 1; 708 } 709 710 if (new_rpc.r_aliases != NULL) { 711 p = (char *)_ALIGN(p); 712 memcpy(p, new_rpc.r_aliases, sizeof(char *) * aliases_size); 713 new_rpc.r_aliases = (char **)p; 714 p += sizeof(char *) * (aliases_size + 1); 715 716 for (alias = new_rpc.r_aliases; *alias; ++alias) { 717 size = strlen(*alias); 718 memcpy(p, *alias, size); 719 *alias = p; 720 p += size + 1; 721 } 722 } 723 724 memcpy(buffer, &new_rpc, sizeof(struct rpcent)); 725 return (NS_SUCCESS); 726 } 727 728 static int 729 rpc_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap, 730 void *cache_mdata) 731 { 732 char *name __unused; 733 int num __unused; 734 struct rpcent *rpc; 735 char *orig_buf; 736 size_t orig_buf_size; 737 int *ret_errno; 738 739 char *p; 740 char **alias; 741 742 switch ((enum nss_lookup_type)cache_mdata) { 743 case nss_lt_name: 744 name = va_arg(ap, char *); 745 break; 746 case nss_lt_id: 747 num = va_arg(ap, int); 748 break; 749 case nss_lt_all: 750 break; 751 default: 752 /* should be unreachable */ 753 return (NS_UNAVAIL); 754 } 755 756 rpc = va_arg(ap, struct rpcent *); 757 orig_buf = va_arg(ap, char *); 758 orig_buf_size = va_arg(ap, size_t); 759 ret_errno = va_arg(ap, int *); 760 761 if (orig_buf_size < 762 buffer_size - sizeof(struct rpcent) - sizeof(char *)) { 763 *ret_errno = ERANGE; 764 return (NS_RETURN); 765 } 766 767 memcpy(rpc, buffer, sizeof(struct rpcent)); 768 memcpy(&p, buffer + sizeof(struct rpcent), sizeof(char *)); 769 770 orig_buf = (char *)_ALIGN(orig_buf); 771 memcpy(orig_buf, buffer + sizeof(struct rpcent) + sizeof(char *) + 772 _ALIGN(p) - (size_t)p, 773 buffer_size - sizeof(struct rpcent) - sizeof(char *) - 774 _ALIGN(p) + (size_t)p); 775 p = (char *)_ALIGN(p); 776 777 NS_APPLY_OFFSET(rpc->r_name, orig_buf, p, char *); 778 if (rpc->r_aliases != NULL) { 779 NS_APPLY_OFFSET(rpc->r_aliases, orig_buf, p, char **); 780 781 for (alias = rpc->r_aliases ; *alias; ++alias) 782 NS_APPLY_OFFSET(*alias, orig_buf, p, char *); 783 } 784 785 if (retval != NULL) 786 *((struct rpcent **)retval) = rpc; 787 788 return (NS_SUCCESS); 789 } 790 791 NSS_MP_CACHE_HANDLING(rpc); 792 #endif /* NS_CACHING */ 793 794 795 /* get**_r functions implementation */ 796 static int 797 getrpcbyname_r(const char *name, struct rpcent *rpc, char *buffer, 798 size_t bufsize, struct rpcent **result) 799 { 800 #ifdef NS_CACHING 801 static const nss_cache_info cache_info = 802 NS_COMMON_CACHE_INFO_INITIALIZER( 803 rpc, (void *)nss_lt_name, 804 rpc_id_func, rpc_marshal_func, rpc_unmarshal_func); 805 #endif 806 static const ns_dtab dtab[] = { 807 { NSSRC_FILES, files_rpcent, (void *)nss_lt_name }, 808 #ifdef YP 809 { NSSRC_NIS, nis_rpcent, (void *)nss_lt_name }, 810 #endif 811 #ifdef NS_CACHING 812 NS_CACHE_CB(&cache_info) 813 #endif 814 { NULL, NULL, NULL } 815 }; 816 int rv, ret_errno; 817 818 ret_errno = 0; 819 *result = NULL; 820 rv = nsdispatch(result, dtab, NSDB_RPC, "getrpcbyname_r", defaultsrc, 821 name, rpc, buffer, bufsize, &ret_errno); 822 823 if (rv == NS_SUCCESS) 824 return (0); 825 else 826 return (ret_errno); 827 } 828 829 static int 830 getrpcbynumber_r(int number, struct rpcent *rpc, char *buffer, 831 size_t bufsize, struct rpcent **result) 832 { 833 #ifdef NS_CACHING 834 static const nss_cache_info cache_info = 835 NS_COMMON_CACHE_INFO_INITIALIZER( 836 rpc, (void *)nss_lt_id, 837 rpc_id_func, rpc_marshal_func, rpc_unmarshal_func); 838 #endif 839 static const ns_dtab dtab[] = { 840 { NSSRC_FILES, files_rpcent, (void *)nss_lt_id }, 841 #ifdef YP 842 { NSSRC_NIS, nis_rpcent, (void *)nss_lt_id }, 843 #endif 844 #ifdef NS_CACHING 845 NS_CACHE_CB(&cache_info) 846 #endif 847 { NULL, NULL, NULL } 848 }; 849 int rv, ret_errno; 850 851 ret_errno = 0; 852 *result = NULL; 853 rv = nsdispatch(result, dtab, NSDB_RPC, "getrpcbynumber_r", defaultsrc, 854 number, rpc, buffer, bufsize, &ret_errno); 855 856 if (rv == NS_SUCCESS) 857 return (0); 858 else 859 return (ret_errno); 860 } 861 862 static int 863 getrpcent_r(struct rpcent *rpc, char *buffer, size_t bufsize, 864 struct rpcent **result) 865 { 866 #ifdef NS_CACHING 867 static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER( 868 rpc, (void *)nss_lt_all, 869 rpc_marshal_func, rpc_unmarshal_func); 870 #endif 871 static const ns_dtab dtab[] = { 872 { NSSRC_FILES, files_rpcent, (void *)nss_lt_all }, 873 #ifdef YP 874 { NSSRC_NIS, nis_rpcent, (void *)nss_lt_all }, 875 #endif 876 #ifdef NS_CACHING 877 NS_CACHE_CB(&cache_info) 878 #endif 879 { NULL, NULL, NULL } 880 }; 881 int rv, ret_errno; 882 883 ret_errno = 0; 884 *result = NULL; 885 rv = nsdispatch(result, dtab, NSDB_RPC, "getrpcent_r", defaultsrc, 886 rpc, buffer, bufsize, &ret_errno); 887 888 if (rv == NS_SUCCESS) 889 return (0); 890 else 891 return (ret_errno); 892 } 893 894 /* get** wrappers for get**_r functions implementation */ 895 static void 896 rpcent_endstate(void *p) 897 { 898 if (p == NULL) 899 return; 900 901 free(((struct rpcent_state *)p)->buffer); 902 free(p); 903 } 904 905 static int 906 wrap_getrpcbyname_r(union key key, struct rpcent *rpc, char *buffer, 907 size_t bufsize, struct rpcent **res) 908 { 909 return (getrpcbyname_r(key.name, rpc, buffer, bufsize, res)); 910 } 911 912 static int 913 wrap_getrpcbynumber_r(union key key, struct rpcent *rpc, char *buffer, 914 size_t bufsize, struct rpcent **res) 915 { 916 return (getrpcbynumber_r(key.number, rpc, buffer, bufsize, res)); 917 } 918 919 static int 920 wrap_getrpcent_r(union key key __unused, struct rpcent *rpc, char *buffer, 921 size_t bufsize, struct rpcent **res) 922 { 923 return (getrpcent_r(rpc, buffer, bufsize, res)); 924 } 925 926 static struct rpcent * 927 getrpc(int (*fn)(union key, struct rpcent *, char *, size_t, struct rpcent **), 928 union key key) 929 { 930 int rv; 931 struct rpcent *res; 932 struct rpcent_state * st; 933 934 rv=rpcent_getstate(&st); 935 if (rv != 0) { 936 errno = rv; 937 return NULL; 938 } 939 940 if (st->buffer == NULL) { 941 st->buffer = malloc(RPCENT_STORAGE_INITIAL); 942 if (st->buffer == NULL) 943 return (NULL); 944 st->bufsize = RPCENT_STORAGE_INITIAL; 945 } 946 do { 947 rv = fn(key, &st->rpc, st->buffer, st->bufsize, &res); 948 if (res == NULL && rv == ERANGE) { 949 free(st->buffer); 950 if ((st->bufsize << 1) > RPCENT_STORAGE_MAX) { 951 st->buffer = NULL; 952 errno = ERANGE; 953 return (NULL); 954 } 955 st->bufsize <<= 1; 956 st->buffer = malloc(st->bufsize); 957 if (st->buffer == NULL) 958 return (NULL); 959 } 960 } while (res == NULL && rv == ERANGE); 961 if (rv != 0) 962 errno = rv; 963 964 return (res); 965 } 966 967 struct rpcent * 968 getrpcbyname(char *name) 969 { 970 union key key; 971 972 key.name = name; 973 974 return (getrpc(wrap_getrpcbyname_r, key)); 975 } 976 977 struct rpcent * 978 getrpcbynumber(int number) 979 { 980 union key key; 981 982 key.number = number; 983 984 return (getrpc(wrap_getrpcbynumber_r, key)); 985 } 986 987 struct rpcent * 988 getrpcent(void) 989 { 990 union key key; 991 992 key.number = 0; /* not used */ 993 994 return (getrpc(wrap_getrpcent_r, key)); 995 } 996 997 void 998 setrpcent(int stayopen) 999 { 1000 #ifdef NS_CACHING 1001 static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER( 1002 rpc, (void *)nss_lt_all, 1003 NULL, NULL); 1004 #endif 1005 1006 static const ns_dtab dtab[] = { 1007 { NSSRC_FILES, files_setrpcent, (void *)SETRPCENT }, 1008 #ifdef YP 1009 { NSSRC_NIS, nis_setrpcent, (void *)SETRPCENT }, 1010 #endif 1011 #ifdef NS_CACHING 1012 NS_CACHE_CB(&cache_info) 1013 #endif 1014 { NULL, NULL, NULL } 1015 }; 1016 1017 nsdispatch(NULL, dtab, NSDB_RPC, "setrpcent", defaultsrc, stayopen); 1018 } 1019 1020 void 1021 endrpcent(void) 1022 { 1023 #ifdef NS_CACHING 1024 static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER( 1025 rpc, (void *)nss_lt_all, 1026 NULL, NULL); 1027 #endif 1028 1029 static const ns_dtab dtab[] = { 1030 { NSSRC_FILES, files_setrpcent, (void *)ENDRPCENT }, 1031 #ifdef YP 1032 { NSSRC_NIS, nis_setrpcent, (void *)ENDRPCENT }, 1033 #endif 1034 #ifdef NS_CACHING 1035 NS_CACHE_CB(&cache_info) 1036 #endif 1037 { NULL, NULL, NULL } 1038 }; 1039 1040 nsdispatch(NULL, dtab, NSDB_RPC, "endrpcent", defaultsrc); 1041 } 1042