17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 2161961e0fSrobinson */ 2261961e0fSrobinson 2361961e0fSrobinson /* 24*e8031f0aSraf * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 257c478bd9Sstevel@tonic-gate * Use is subject to license terms. 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 297c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate /* 327c478bd9Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 337c478bd9Sstevel@tonic-gate * under license from the Regents of the University of 347c478bd9Sstevel@tonic-gate * California. 357c478bd9Sstevel@tonic-gate */ 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 387c478bd9Sstevel@tonic-gate 39*e8031f0aSraf #include "mt.h" 4061961e0fSrobinson #include <stdlib.h> 4161961e0fSrobinson #include <unistd.h> 427c478bd9Sstevel@tonic-gate #include "../rpc/rpc_mt.h" 437c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> 447c478bd9Sstevel@tonic-gate #include <sys/types.h> 457c478bd9Sstevel@tonic-gate #include "yp_b.h" 467c478bd9Sstevel@tonic-gate #include <rpcsvc/yp_prot.h> 477c478bd9Sstevel@tonic-gate #include <rpcsvc/ypclnt.h> 487c478bd9Sstevel@tonic-gate #include <malloc.h> 497c478bd9Sstevel@tonic-gate #include <string.h> 507c478bd9Sstevel@tonic-gate #include <sys/time.h> 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate extern int __yp_dobind_cflookup(char *, struct dom_binding **, int); 537c478bd9Sstevel@tonic-gate extern int __yp_dobind_rsvdport_cflookup(char *, struct dom_binding **, int); 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate static int domatch(char *, char *, char *, int, struct dom_binding *, 567c478bd9Sstevel@tonic-gate struct timeval *, char **, int *); 577c478bd9Sstevel@tonic-gate int yp_match_rsvdport(); 587c478bd9Sstevel@tonic-gate int yp_match_rsvdport_cflookup(); 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate struct cache { 617c478bd9Sstevel@tonic-gate struct cache *next; 627c478bd9Sstevel@tonic-gate unsigned int birth; 637c478bd9Sstevel@tonic-gate char *domain; 647c478bd9Sstevel@tonic-gate char *map; 657c478bd9Sstevel@tonic-gate char *key; 667c478bd9Sstevel@tonic-gate int keylen; 677c478bd9Sstevel@tonic-gate char *val; 687c478bd9Sstevel@tonic-gate int vallen; 697c478bd9Sstevel@tonic-gate }; 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate static mutex_t cache_lock = DEFAULTMUTEX; 727c478bd9Sstevel@tonic-gate static int generation; /* Incremented when we add to cache */ 737c478bd9Sstevel@tonic-gate static struct cache *head; 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate #define CACHESZ 16 767c478bd9Sstevel@tonic-gate #define CACHETO 600 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate static void 7961961e0fSrobinson freenode(struct cache *n) 807c478bd9Sstevel@tonic-gate { 817c478bd9Sstevel@tonic-gate if (n->val != 0) 827c478bd9Sstevel@tonic-gate free(n->val); 837c478bd9Sstevel@tonic-gate if (n->key != 0) 847c478bd9Sstevel@tonic-gate free(n->key); 857c478bd9Sstevel@tonic-gate if (n->map != 0) 867c478bd9Sstevel@tonic-gate free(n->map); 877c478bd9Sstevel@tonic-gate if (n->domain != 0) 887c478bd9Sstevel@tonic-gate free(n->domain); 8961961e0fSrobinson free(n); 907c478bd9Sstevel@tonic-gate } 917c478bd9Sstevel@tonic-gate 927de476d1Ssm26363 /* 937de476d1Ssm26363 * Attempt to Add item to cache 947de476d1Ssm26363 */ 957c478bd9Sstevel@tonic-gate static struct cache * 9661961e0fSrobinson makenode(char *domain, char *map, int keylen, int vallen) 977c478bd9Sstevel@tonic-gate { 987c478bd9Sstevel@tonic-gate struct cache *n; 997c478bd9Sstevel@tonic-gate 1007de476d1Ssm26363 /* Do not cache 'passwd' values i.e. passwd.byname or passwd.byuid. */ 1017de476d1Ssm26363 if (strncmp(map, "passwd", 6) == 0) 1027de476d1Ssm26363 return (0); 1037de476d1Ssm26363 10461961e0fSrobinson if ((n = calloc(1, sizeof (*n))) == 0) 1057c478bd9Sstevel@tonic-gate return (0); 1067c478bd9Sstevel@tonic-gate if (((n->domain = strdup(domain)) == 0) || 1077c478bd9Sstevel@tonic-gate ((n->map = strdup(map)) == 0) || 1087c478bd9Sstevel@tonic-gate ((n->key = malloc(keylen)) == 0) || 1097c478bd9Sstevel@tonic-gate ((n->val = malloc(vallen)) == 0)) { 1107c478bd9Sstevel@tonic-gate freenode(n); 1117c478bd9Sstevel@tonic-gate return (0); 1127c478bd9Sstevel@tonic-gate } 1137c478bd9Sstevel@tonic-gate return (n); 1147c478bd9Sstevel@tonic-gate } 1157c478bd9Sstevel@tonic-gate 1167de476d1Ssm26363 /* 1177de476d1Ssm26363 * Look for a matching result in the per-process cache. 1187de476d1Ssm26363 * Upon finding a match set the passed in 'val' and 'vallen' 1197de476d1Ssm26363 * parameters and return 1. Otherwise return 0. 1207de476d1Ssm26363 */ 1217c478bd9Sstevel@tonic-gate static int 12261961e0fSrobinson in_cache(char *domain, char *map, char *key, int keylen, char **val, 12361961e0fSrobinson int *vallen) 1247c478bd9Sstevel@tonic-gate { 1257c478bd9Sstevel@tonic-gate struct cache *c, **pp; 1267c478bd9Sstevel@tonic-gate int cnt; 1277c478bd9Sstevel@tonic-gate struct timeval now; 1287c478bd9Sstevel@tonic-gate struct timezone tz; 1297c478bd9Sstevel@tonic-gate 1307de476d1Ssm26363 /* The 'passwd' data is not cached. */ 1317de476d1Ssm26363 if (strncmp(map, "passwd", 6) == 0) 1327de476d1Ssm26363 return (0); 1337de476d1Ssm26363 1347c478bd9Sstevel@tonic-gate /* 1357c478bd9Sstevel@tonic-gate * Assumes that caller (yp_match) has locked the cache 1367c478bd9Sstevel@tonic-gate */ 1377c478bd9Sstevel@tonic-gate for (pp = &head, cnt = 0; (c = *pp) != 0; pp = &c->next, cnt++) { 1387c478bd9Sstevel@tonic-gate if ((c->keylen == keylen) && 1397c478bd9Sstevel@tonic-gate (memcmp(key, c->key, (size_t)keylen) == 0) && 1407c478bd9Sstevel@tonic-gate (strcmp(map, c->map) == 0) && 1417c478bd9Sstevel@tonic-gate (strcmp(domain, c->domain) == 0)) { 1427c478bd9Sstevel@tonic-gate /* cache hit */ 1437c478bd9Sstevel@tonic-gate (void) gettimeofday(&now, &tz); 1447c478bd9Sstevel@tonic-gate if ((now.tv_sec - c->birth) > CACHETO) { 1457c478bd9Sstevel@tonic-gate /* rats. it is too old to use */ 1467c478bd9Sstevel@tonic-gate *pp = c->next; 1477c478bd9Sstevel@tonic-gate freenode(c); 1487c478bd9Sstevel@tonic-gate break; 1497c478bd9Sstevel@tonic-gate } else { 1507c478bd9Sstevel@tonic-gate *val = c->val; 1517c478bd9Sstevel@tonic-gate *vallen = c->vallen; 1527c478bd9Sstevel@tonic-gate 1537c478bd9Sstevel@tonic-gate /* Ersatz LRU: Move this entry to the front */ 1547c478bd9Sstevel@tonic-gate *pp = c->next; 1557c478bd9Sstevel@tonic-gate c->next = head; 1567c478bd9Sstevel@tonic-gate head = c; 1577c478bd9Sstevel@tonic-gate return (1); 1587c478bd9Sstevel@tonic-gate } 1597c478bd9Sstevel@tonic-gate } 1607c478bd9Sstevel@tonic-gate if (cnt >= CACHESZ) { 1617c478bd9Sstevel@tonic-gate *pp = c->next; 1627c478bd9Sstevel@tonic-gate freenode(c); 1637c478bd9Sstevel@tonic-gate break; 1647c478bd9Sstevel@tonic-gate } 1657c478bd9Sstevel@tonic-gate } 1667c478bd9Sstevel@tonic-gate return (0); 1677c478bd9Sstevel@tonic-gate } 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate /* 1707c478bd9Sstevel@tonic-gate * Requests the yp server associated with a given domain to attempt to match 1717c478bd9Sstevel@tonic-gate * the passed key datum in the named map, and to return the associated value 1727c478bd9Sstevel@tonic-gate * datum. This part does parameter checking, and implements the "infinite" 1737c478bd9Sstevel@tonic-gate * (until success) sleep loop if 'hardlookup' parameter is set. 1747c478bd9Sstevel@tonic-gate */ 1757c478bd9Sstevel@tonic-gate int 17661961e0fSrobinson __yp_match_cflookup(char *domain, char *map, char *key, int keylen, char **val, 17761961e0fSrobinson int *vallen, int hardlookup) 1787c478bd9Sstevel@tonic-gate { 1797c478bd9Sstevel@tonic-gate size_t domlen; 1807c478bd9Sstevel@tonic-gate size_t maplen; 1817c478bd9Sstevel@tonic-gate int reason; 1827c478bd9Sstevel@tonic-gate struct dom_binding *pdomb; 1837c478bd9Sstevel@tonic-gate int savesize; 1847c478bd9Sstevel@tonic-gate struct timeval now; 1857c478bd9Sstevel@tonic-gate struct timezone tz; 1867c478bd9Sstevel@tonic-gate char *my_val; 1877c478bd9Sstevel@tonic-gate int my_vallen; 1887c478bd9Sstevel@tonic-gate int found_it; 1897c478bd9Sstevel@tonic-gate int cachegen; 1907c478bd9Sstevel@tonic-gate 19161961e0fSrobinson if ((map == NULL) || (domain == NULL)) 1927c478bd9Sstevel@tonic-gate return (YPERR_BADARGS); 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate domlen = strlen(domain); 1957c478bd9Sstevel@tonic-gate maplen = strlen(map); 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate if ((domlen == 0) || (domlen > YPMAXDOMAIN) || 1987c478bd9Sstevel@tonic-gate (maplen == 0) || (maplen > YPMAXMAP) || 19961961e0fSrobinson (key == NULL) || (keylen == 0)) 2007c478bd9Sstevel@tonic-gate return (YPERR_BADARGS); 2017c478bd9Sstevel@tonic-gate 20261961e0fSrobinson (void) mutex_lock(&cache_lock); 2037c478bd9Sstevel@tonic-gate found_it = in_cache(domain, map, key, keylen, &my_val, &my_vallen); 2047c478bd9Sstevel@tonic-gate cachegen = generation; 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate if (found_it) { 2077c478bd9Sstevel@tonic-gate /* NB: Copy two extra bytes; see below */ 2087c478bd9Sstevel@tonic-gate savesize = my_vallen + 2; 2097c478bd9Sstevel@tonic-gate if ((*val = malloc((size_t)savesize)) == 0) { 21061961e0fSrobinson (void) mutex_unlock(&cache_lock); 2117c478bd9Sstevel@tonic-gate return (YPERR_RESRC); 2127c478bd9Sstevel@tonic-gate } 2137c478bd9Sstevel@tonic-gate (void) memcpy(*val, my_val, (size_t)savesize); 2147c478bd9Sstevel@tonic-gate *vallen = my_vallen; 21561961e0fSrobinson (void) mutex_unlock(&cache_lock); 2167c478bd9Sstevel@tonic-gate return (0); /* Success */ 2177c478bd9Sstevel@tonic-gate } 21861961e0fSrobinson (void) mutex_unlock(&cache_lock); 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate for (;;) { 2217c478bd9Sstevel@tonic-gate 22261961e0fSrobinson if (reason = __yp_dobind_cflookup(domain, &pdomb, hardlookup)) 2237c478bd9Sstevel@tonic-gate return (reason); 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate if (pdomb->dom_binding->ypbind_hi_vers >= YPVERS) { 2267c478bd9Sstevel@tonic-gate 2277c478bd9Sstevel@tonic-gate reason = domatch(domain, map, key, keylen, pdomb, 2287c478bd9Sstevel@tonic-gate &_ypserv_timeout, val, vallen); 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate __yp_rel_binding(pdomb); 2317c478bd9Sstevel@tonic-gate if (reason == YPERR_RPC || reason == YPERR_YPSERV || 2327c478bd9Sstevel@tonic-gate reason == YPERR_BUSY /* as if */) { 2337c478bd9Sstevel@tonic-gate yp_unbind(domain); 2347c478bd9Sstevel@tonic-gate if (hardlookup) 235*e8031f0aSraf (void) sleep(_ypsleeptime); /* retry */ 23661961e0fSrobinson else 2377c478bd9Sstevel@tonic-gate return (reason); 2387c478bd9Sstevel@tonic-gate } else 2397c478bd9Sstevel@tonic-gate break; 2407c478bd9Sstevel@tonic-gate } else { 2417c478bd9Sstevel@tonic-gate __yp_rel_binding(pdomb); 2427c478bd9Sstevel@tonic-gate return (YPERR_VERS); 2437c478bd9Sstevel@tonic-gate } 2447c478bd9Sstevel@tonic-gate } 2457c478bd9Sstevel@tonic-gate 2467c478bd9Sstevel@tonic-gate /* add to our cache */ 2477c478bd9Sstevel@tonic-gate if (reason == 0) { 24861961e0fSrobinson (void) mutex_lock(&cache_lock); 2497c478bd9Sstevel@tonic-gate /* 2507c478bd9Sstevel@tonic-gate * Check whether some other annoying thread did the same 2517c478bd9Sstevel@tonic-gate * thing in parallel with us. I hate it when that happens... 2527c478bd9Sstevel@tonic-gate */ 2537c478bd9Sstevel@tonic-gate if (generation != cachegen && 2547c478bd9Sstevel@tonic-gate in_cache(domain, map, key, keylen, &my_val, &my_vallen)) { 2557c478bd9Sstevel@tonic-gate /* 2567c478bd9Sstevel@tonic-gate * Could get cute and update the birth time, but it's 2577c478bd9Sstevel@tonic-gate * not worth the bother. 2587c478bd9Sstevel@tonic-gate * It looks strange that we return one val[] array 2597c478bd9Sstevel@tonic-gate * to the caller and have a different copy of the 2607c478bd9Sstevel@tonic-gate * val[] array in the cache (presumably with the 2617c478bd9Sstevel@tonic-gate * same contents), but it should work just fine. 2627c478bd9Sstevel@tonic-gate * So, do absolutely nothing... 2637c478bd9Sstevel@tonic-gate */ 2647c478bd9Sstevel@tonic-gate /* EMPTY */ 2657c478bd9Sstevel@tonic-gate } else { 2667c478bd9Sstevel@tonic-gate struct cache *c; 2677c478bd9Sstevel@tonic-gate /* 2687c478bd9Sstevel@tonic-gate * NB: allocate and copy extract two bytes of the 2697c478bd9Sstevel@tonic-gate * value; these are mandatory CR and NULL bytes. 2707c478bd9Sstevel@tonic-gate */ 2717c478bd9Sstevel@tonic-gate savesize = *vallen + 2; 2727c478bd9Sstevel@tonic-gate c = makenode(domain, map, keylen, savesize); 2737c478bd9Sstevel@tonic-gate if (c != 0) { 2747c478bd9Sstevel@tonic-gate (void) gettimeofday(&now, &tz); 2757c478bd9Sstevel@tonic-gate c->birth = now.tv_sec; 2767c478bd9Sstevel@tonic-gate c->keylen = keylen; 2777c478bd9Sstevel@tonic-gate c->vallen = *vallen; 2787c478bd9Sstevel@tonic-gate (void) memcpy(c->key, key, (size_t)keylen); 2797c478bd9Sstevel@tonic-gate (void) memcpy(c->val, *val, (size_t)savesize); 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate c->next = head; 2827c478bd9Sstevel@tonic-gate head = c; 2837c478bd9Sstevel@tonic-gate ++generation; 2847c478bd9Sstevel@tonic-gate } 2857c478bd9Sstevel@tonic-gate } 28661961e0fSrobinson (void) mutex_unlock(&cache_lock); 2877c478bd9Sstevel@tonic-gate } else if (reason == YPERR_MAP && geteuid() == 0) { 2887c478bd9Sstevel@tonic-gate /* 2897c478bd9Sstevel@tonic-gate * Lookup could be for a secure map; fail over to retry 2907c478bd9Sstevel@tonic-gate * from a reserved port. Only useful to try this if we're 2917c478bd9Sstevel@tonic-gate * the super user. 2927c478bd9Sstevel@tonic-gate */ 2937c478bd9Sstevel@tonic-gate int rsvdreason; 2947c478bd9Sstevel@tonic-gate rsvdreason = yp_match_rsvdport(domain, map, key, keylen, val, 2957c478bd9Sstevel@tonic-gate vallen); 2967c478bd9Sstevel@tonic-gate if (rsvdreason == 0) 2977c478bd9Sstevel@tonic-gate reason = rsvdreason; 2987c478bd9Sstevel@tonic-gate } 2997c478bd9Sstevel@tonic-gate return (reason); 3007c478bd9Sstevel@tonic-gate } 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate int 3037c478bd9Sstevel@tonic-gate yp_match( 3047c478bd9Sstevel@tonic-gate char *domain, 3057c478bd9Sstevel@tonic-gate char *map, 3067c478bd9Sstevel@tonic-gate char *key, 3077c478bd9Sstevel@tonic-gate int keylen, 3087c478bd9Sstevel@tonic-gate char **val, /* returns value array */ 3097c478bd9Sstevel@tonic-gate int *vallen) /* returns bytes in val */ 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate { 3127c478bd9Sstevel@tonic-gate /* the traditional yp_match loops forever thus hardlookup is set */ 3137c478bd9Sstevel@tonic-gate return (__yp_match_cflookup(domain, map, key, keylen, val, vallen, 1)); 3147c478bd9Sstevel@tonic-gate } 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate extern void 31761961e0fSrobinson __empty_yp_cache(void) 3187c478bd9Sstevel@tonic-gate { 3197c478bd9Sstevel@tonic-gate struct cache *p, *n; 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate /* Copy the cache pointer and make it ZERO */ 32261961e0fSrobinson (void) mutex_lock(&cache_lock); 3237c478bd9Sstevel@tonic-gate p = head; 3247c478bd9Sstevel@tonic-gate head = 0; 32561961e0fSrobinson (void) mutex_unlock(&cache_lock); 3267c478bd9Sstevel@tonic-gate 3277c478bd9Sstevel@tonic-gate if (p == 0) 3287c478bd9Sstevel@tonic-gate return; 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate /* Empty the cache */ 3317c478bd9Sstevel@tonic-gate n = p->next; 3327c478bd9Sstevel@tonic-gate while (p) { 3337c478bd9Sstevel@tonic-gate freenode(p); 3347c478bd9Sstevel@tonic-gate p = n; 3357c478bd9Sstevel@tonic-gate if (p) 3367c478bd9Sstevel@tonic-gate n = p->next; 3377c478bd9Sstevel@tonic-gate } 3387c478bd9Sstevel@tonic-gate } 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate /* 3417c478bd9Sstevel@tonic-gate * Requests the yp server associated with a given domain to attempt to match 3427c478bd9Sstevel@tonic-gate * the passed key datum in the named map, and to return the associated value 3437c478bd9Sstevel@tonic-gate * datum. This part does parameter checking, and implements the "infinite" 3447c478bd9Sstevel@tonic-gate * (until success) sleep loop. 3457c478bd9Sstevel@tonic-gate * 3467c478bd9Sstevel@tonic-gate * XXX special version for handling C2 (passwd.adjunct) lookups when we need 3477c478bd9Sstevel@tonic-gate * a reserved port. 3487c478bd9Sstevel@tonic-gate * Only difference against yp_match is that this function uses 3497c478bd9Sstevel@tonic-gate * __yp_dobind_rsvdport(). 3507c478bd9Sstevel@tonic-gate * 3517c478bd9Sstevel@tonic-gate * Only called from NIS switch backend. 3527c478bd9Sstevel@tonic-gate */ 3537c478bd9Sstevel@tonic-gate int 3547c478bd9Sstevel@tonic-gate __yp_match_rsvdport_cflookup( 3557c478bd9Sstevel@tonic-gate char *domain, 3567c478bd9Sstevel@tonic-gate char *map, 3577c478bd9Sstevel@tonic-gate char *key, 3587c478bd9Sstevel@tonic-gate int keylen, 3597c478bd9Sstevel@tonic-gate char **val, /* returns value array */ 3607c478bd9Sstevel@tonic-gate int *vallen, /* returns bytes in val */ 3617c478bd9Sstevel@tonic-gate int hardlookup) /* retry until we can an answer */ 3627c478bd9Sstevel@tonic-gate { 3637c478bd9Sstevel@tonic-gate size_t domlen; 3647c478bd9Sstevel@tonic-gate size_t maplen; 3657c478bd9Sstevel@tonic-gate int reason; 3667c478bd9Sstevel@tonic-gate struct dom_binding *pdomb; 3677c478bd9Sstevel@tonic-gate int savesize; 3687c478bd9Sstevel@tonic-gate struct timeval now; 3697c478bd9Sstevel@tonic-gate struct timezone tz; 3707c478bd9Sstevel@tonic-gate char *my_val; 3717c478bd9Sstevel@tonic-gate int my_vallen; 3727c478bd9Sstevel@tonic-gate int found_it; 3737c478bd9Sstevel@tonic-gate int cachegen; 3747c478bd9Sstevel@tonic-gate 37561961e0fSrobinson if ((map == NULL) || (domain == NULL)) 3767c478bd9Sstevel@tonic-gate return (YPERR_BADARGS); 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate domlen = strlen(domain); 3797c478bd9Sstevel@tonic-gate maplen = strlen(map); 3807c478bd9Sstevel@tonic-gate 3817c478bd9Sstevel@tonic-gate if ((domlen == 0) || (domlen > YPMAXDOMAIN) || 3827c478bd9Sstevel@tonic-gate (maplen == 0) || (maplen > YPMAXMAP) || 38361961e0fSrobinson (key == NULL) || (keylen == 0)) 3847c478bd9Sstevel@tonic-gate return (YPERR_BADARGS); 3857c478bd9Sstevel@tonic-gate 38661961e0fSrobinson (void) mutex_lock(&cache_lock); 3877c478bd9Sstevel@tonic-gate found_it = in_cache(domain, map, key, keylen, &my_val, &my_vallen); 3887c478bd9Sstevel@tonic-gate cachegen = generation; 3897c478bd9Sstevel@tonic-gate if (found_it) { 3907c478bd9Sstevel@tonic-gate /* NB: Copy two extra bytes; see below */ 3917c478bd9Sstevel@tonic-gate savesize = my_vallen + 2; 3927c478bd9Sstevel@tonic-gate if ((*val = malloc((size_t)savesize)) == 0) { 39361961e0fSrobinson (void) mutex_unlock(&cache_lock); 3947c478bd9Sstevel@tonic-gate return (YPERR_RESRC); 3957c478bd9Sstevel@tonic-gate } 3967c478bd9Sstevel@tonic-gate (void) memcpy(*val, my_val, (size_t)savesize); 3977c478bd9Sstevel@tonic-gate *vallen = my_vallen; 39861961e0fSrobinson (void) mutex_unlock(&cache_lock); 3997c478bd9Sstevel@tonic-gate return (0); /* Success */ 4007c478bd9Sstevel@tonic-gate } 40161961e0fSrobinson (void) mutex_unlock(&cache_lock); 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate for (;;) { 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate if (reason = __yp_dobind_rsvdport_cflookup(domain, &pdomb, 40661961e0fSrobinson hardlookup)) 4077c478bd9Sstevel@tonic-gate return (reason); 4087c478bd9Sstevel@tonic-gate 4097c478bd9Sstevel@tonic-gate if (pdomb->dom_binding->ypbind_hi_vers >= YPVERS) { 4107c478bd9Sstevel@tonic-gate 4117c478bd9Sstevel@tonic-gate reason = domatch(domain, map, key, keylen, 4127c478bd9Sstevel@tonic-gate pdomb, &_ypserv_timeout, val, vallen); 4137c478bd9Sstevel@tonic-gate 4147c478bd9Sstevel@tonic-gate /* 4157c478bd9Sstevel@tonic-gate * Have to free the binding since the reserved 4167c478bd9Sstevel@tonic-gate * port bindings are not cached. 4177c478bd9Sstevel@tonic-gate */ 4187c478bd9Sstevel@tonic-gate __yp_rel_binding(pdomb); 4197c478bd9Sstevel@tonic-gate free_dom_binding(pdomb); 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate if (reason == YPERR_RPC || reason == YPERR_YPSERV || 4227c478bd9Sstevel@tonic-gate reason == YPERR_BUSY /* as if */) { 4237c478bd9Sstevel@tonic-gate yp_unbind(domain); 4247c478bd9Sstevel@tonic-gate if (hardlookup) 425*e8031f0aSraf (void) sleep(_ypsleeptime); /* retry */ 42661961e0fSrobinson else 4277c478bd9Sstevel@tonic-gate return (reason); 4287c478bd9Sstevel@tonic-gate } else 4297c478bd9Sstevel@tonic-gate break; 4307c478bd9Sstevel@tonic-gate } else { 4317c478bd9Sstevel@tonic-gate /* 4327c478bd9Sstevel@tonic-gate * Have to free the binding since the reserved 4337c478bd9Sstevel@tonic-gate * port bindings are not cached. 4347c478bd9Sstevel@tonic-gate */ 4357c478bd9Sstevel@tonic-gate __yp_rel_binding(pdomb); 4367c478bd9Sstevel@tonic-gate free_dom_binding(pdomb); 4377c478bd9Sstevel@tonic-gate return (YPERR_VERS); 4387c478bd9Sstevel@tonic-gate } 4397c478bd9Sstevel@tonic-gate } 4407c478bd9Sstevel@tonic-gate 4417c478bd9Sstevel@tonic-gate /* add to our cache */ 4427c478bd9Sstevel@tonic-gate if (reason == 0) { 44361961e0fSrobinson (void) mutex_lock(&cache_lock); 4447c478bd9Sstevel@tonic-gate /* 4457c478bd9Sstevel@tonic-gate * Check whether some other annoying thread did the same 4467c478bd9Sstevel@tonic-gate * thing in parallel with us. I hate it when that happens... 4477c478bd9Sstevel@tonic-gate */ 4487c478bd9Sstevel@tonic-gate if (generation != cachegen && 4497c478bd9Sstevel@tonic-gate in_cache(domain, map, key, keylen, &my_val, &my_vallen)) { 4507c478bd9Sstevel@tonic-gate /* 4517c478bd9Sstevel@tonic-gate * Could get cute and update the birth time, but it's 4527c478bd9Sstevel@tonic-gate * not worth the bother. 4537c478bd9Sstevel@tonic-gate * It looks strange that we return one val[] array 4547c478bd9Sstevel@tonic-gate * to the caller and have a different copy of the 4557c478bd9Sstevel@tonic-gate * val[] array in the cache (presumably with the 4567c478bd9Sstevel@tonic-gate * same contents), but it should work just fine. 4577c478bd9Sstevel@tonic-gate * So, do absolutely nothing... 4587c478bd9Sstevel@tonic-gate */ 4597c478bd9Sstevel@tonic-gate /* EMPTY */ 4607c478bd9Sstevel@tonic-gate } else { 4617c478bd9Sstevel@tonic-gate struct cache *c; 4627c478bd9Sstevel@tonic-gate /* 4637c478bd9Sstevel@tonic-gate * NB: allocate and copy extract two bytes of the 4647c478bd9Sstevel@tonic-gate * value; these are mandatory CR and NULL bytes. 4657c478bd9Sstevel@tonic-gate */ 4667c478bd9Sstevel@tonic-gate savesize = *vallen + 2; 4677c478bd9Sstevel@tonic-gate c = makenode(domain, map, keylen, savesize); 4687c478bd9Sstevel@tonic-gate if (c != 0) { 4697c478bd9Sstevel@tonic-gate (void) gettimeofday(&now, &tz); 4707c478bd9Sstevel@tonic-gate c->birth = now.tv_sec; 4717c478bd9Sstevel@tonic-gate c->keylen = keylen; 4727c478bd9Sstevel@tonic-gate c->vallen = *vallen; 4737c478bd9Sstevel@tonic-gate (void) memcpy(c->key, key, (size_t)keylen); 4747c478bd9Sstevel@tonic-gate (void) memcpy(c->val, *val, (size_t)savesize); 4757c478bd9Sstevel@tonic-gate 4767c478bd9Sstevel@tonic-gate c->next = head; 4777c478bd9Sstevel@tonic-gate head = c; 4787c478bd9Sstevel@tonic-gate ++generation; 4797c478bd9Sstevel@tonic-gate } 4807c478bd9Sstevel@tonic-gate } 48161961e0fSrobinson (void) mutex_unlock(&cache_lock); 4827c478bd9Sstevel@tonic-gate } 4837c478bd9Sstevel@tonic-gate return (reason); 4847c478bd9Sstevel@tonic-gate } 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate 4877c478bd9Sstevel@tonic-gate int 4887c478bd9Sstevel@tonic-gate yp_match_rsvdport( 4897c478bd9Sstevel@tonic-gate char *domain, 4907c478bd9Sstevel@tonic-gate char *map, 4917c478bd9Sstevel@tonic-gate char *key, 4927c478bd9Sstevel@tonic-gate int keylen, 4937c478bd9Sstevel@tonic-gate char **val, /* returns value array */ 4947c478bd9Sstevel@tonic-gate int *vallen) /* returns bytes in val */ 4957c478bd9Sstevel@tonic-gate { 4967c478bd9Sstevel@tonic-gate /* traditional yp_match retries forever so set hardlookup */ 4977c478bd9Sstevel@tonic-gate return (__yp_match_rsvdport_cflookup(domain, map, key, keylen, val, 4987c478bd9Sstevel@tonic-gate vallen, 1)); 4997c478bd9Sstevel@tonic-gate } 5007c478bd9Sstevel@tonic-gate 5017c478bd9Sstevel@tonic-gate 5027c478bd9Sstevel@tonic-gate /* 5037c478bd9Sstevel@tonic-gate * This talks v3 protocol to ypserv 5047c478bd9Sstevel@tonic-gate */ 5057c478bd9Sstevel@tonic-gate static int 5067c478bd9Sstevel@tonic-gate domatch(char *domain, char *map, char *key, int keylen, 5077c478bd9Sstevel@tonic-gate struct dom_binding *pdomb, struct timeval *timeoutp, char **val, 5087c478bd9Sstevel@tonic-gate int *vallen) 5097c478bd9Sstevel@tonic-gate { 5107c478bd9Sstevel@tonic-gate struct ypreq_key req; 5117c478bd9Sstevel@tonic-gate struct ypresp_val resp; 5127c478bd9Sstevel@tonic-gate unsigned int retval = 0; 5137c478bd9Sstevel@tonic-gate 5147c478bd9Sstevel@tonic-gate req.domain = domain; 5157c478bd9Sstevel@tonic-gate req.map = map; 5167c478bd9Sstevel@tonic-gate req.keydat.dptr = key; 5177c478bd9Sstevel@tonic-gate req.keydat.dsize = keylen; 5187c478bd9Sstevel@tonic-gate 5197c478bd9Sstevel@tonic-gate resp.valdat.dptr = NULL; 5207c478bd9Sstevel@tonic-gate resp.valdat.dsize = 0; 5217c478bd9Sstevel@tonic-gate (void) memset((char *)&resp, 0, sizeof (struct ypresp_val)); 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate /* 5247c478bd9Sstevel@tonic-gate * Do the match request. If the rpc call failed, return with status 5257c478bd9Sstevel@tonic-gate * from this point. 5267c478bd9Sstevel@tonic-gate */ 5277c478bd9Sstevel@tonic-gate 5287c478bd9Sstevel@tonic-gate switch (clnt_call(pdomb->dom_client, YPPROC_MATCH, 5297c478bd9Sstevel@tonic-gate (xdrproc_t)xdr_ypreq_key, (char *)&req, 5307c478bd9Sstevel@tonic-gate (xdrproc_t)xdr_ypresp_val, (char *)&resp, 5317c478bd9Sstevel@tonic-gate *timeoutp)) { 5327c478bd9Sstevel@tonic-gate case RPC_SUCCESS: 5337c478bd9Sstevel@tonic-gate break; 5347c478bd9Sstevel@tonic-gate case RPC_TIMEDOUT: 5357c478bd9Sstevel@tonic-gate return (YPERR_YPSERV); 5367c478bd9Sstevel@tonic-gate default: 5377c478bd9Sstevel@tonic-gate return (YPERR_RPC); 5387c478bd9Sstevel@tonic-gate } 5397c478bd9Sstevel@tonic-gate 5407c478bd9Sstevel@tonic-gate /* See if the request succeeded */ 5417c478bd9Sstevel@tonic-gate 5427c478bd9Sstevel@tonic-gate if (resp.status != YP_TRUE) { 5437c478bd9Sstevel@tonic-gate retval = ypprot_err(resp.status); 5447c478bd9Sstevel@tonic-gate } 5457c478bd9Sstevel@tonic-gate 5467c478bd9Sstevel@tonic-gate /* Get some memory which the user can get rid of as he likes */ 5477c478bd9Sstevel@tonic-gate 5487c478bd9Sstevel@tonic-gate if (!retval && ((*val = malloc((size_t) 5497c478bd9Sstevel@tonic-gate resp.valdat.dsize + 2)) == NULL)) { 5507c478bd9Sstevel@tonic-gate retval = YPERR_RESRC; 5517c478bd9Sstevel@tonic-gate } 5527c478bd9Sstevel@tonic-gate 5537c478bd9Sstevel@tonic-gate /* Copy the returned value byte string into the new memory */ 5547c478bd9Sstevel@tonic-gate 5557c478bd9Sstevel@tonic-gate if (!retval) { 5567c478bd9Sstevel@tonic-gate *vallen = (int)resp.valdat.dsize; 5577c478bd9Sstevel@tonic-gate (void) memcpy(*val, resp.valdat.dptr, 5587c478bd9Sstevel@tonic-gate (size_t)resp.valdat.dsize); 5597c478bd9Sstevel@tonic-gate (*val)[resp.valdat.dsize] = '\n'; 5607c478bd9Sstevel@tonic-gate (*val)[resp.valdat.dsize + 1] = '\0'; 5617c478bd9Sstevel@tonic-gate } 5627c478bd9Sstevel@tonic-gate 5637c478bd9Sstevel@tonic-gate CLNT_FREERES(pdomb->dom_client, 5647c478bd9Sstevel@tonic-gate (xdrproc_t)xdr_ypresp_val, (char *)&resp); 5657c478bd9Sstevel@tonic-gate return (retval); 5667c478bd9Sstevel@tonic-gate } 567