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