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 /* 24e8031f0aSraf * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 257c478bd9Sstevel@tonic-gate * Use is subject to license terms. 26*48bbca81SDaniel Hoffman * Copyright (c) 2016 by Delphix. All rights reserved. 277c478bd9Sstevel@tonic-gate */ 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 307c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate /* 337c478bd9Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 347c478bd9Sstevel@tonic-gate * under license from the Regents of the University of 357c478bd9Sstevel@tonic-gate * California. 367c478bd9Sstevel@tonic-gate */ 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 397c478bd9Sstevel@tonic-gate 40e8031f0aSraf #include "mt.h" 4161961e0fSrobinson #include <stdlib.h> 4261961e0fSrobinson #include <unistd.h> 437c478bd9Sstevel@tonic-gate #include "../rpc/rpc_mt.h" 447c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> 457c478bd9Sstevel@tonic-gate #include <sys/types.h> 467c478bd9Sstevel@tonic-gate #include "yp_b.h" 477c478bd9Sstevel@tonic-gate #include <rpcsvc/yp_prot.h> 487c478bd9Sstevel@tonic-gate #include <rpcsvc/ypclnt.h> 497c478bd9Sstevel@tonic-gate #include <malloc.h> 507c478bd9Sstevel@tonic-gate #include <string.h> 517c478bd9Sstevel@tonic-gate #include <sys/time.h> 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate extern int __yp_dobind_cflookup(char *, struct dom_binding **, int); 547c478bd9Sstevel@tonic-gate extern int __yp_dobind_rsvdport_cflookup(char *, struct dom_binding **, int); 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate static int domatch(char *, char *, char *, int, struct dom_binding *, 577c478bd9Sstevel@tonic-gate struct timeval *, char **, int *); 587c478bd9Sstevel@tonic-gate int yp_match_rsvdport(); 597c478bd9Sstevel@tonic-gate int yp_match_rsvdport_cflookup(); 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate struct cache { 627c478bd9Sstevel@tonic-gate struct cache *next; 637c478bd9Sstevel@tonic-gate unsigned int birth; 647c478bd9Sstevel@tonic-gate char *domain; 657c478bd9Sstevel@tonic-gate char *map; 667c478bd9Sstevel@tonic-gate char *key; 677c478bd9Sstevel@tonic-gate int keylen; 687c478bd9Sstevel@tonic-gate char *val; 697c478bd9Sstevel@tonic-gate int vallen; 707c478bd9Sstevel@tonic-gate }; 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate static mutex_t cache_lock = DEFAULTMUTEX; 737c478bd9Sstevel@tonic-gate static int generation; /* Incremented when we add to cache */ 747c478bd9Sstevel@tonic-gate static struct cache *head; 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate #define CACHESZ 16 777c478bd9Sstevel@tonic-gate #define CACHETO 600 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate static void 8061961e0fSrobinson freenode(struct cache *n) 817c478bd9Sstevel@tonic-gate { 827c478bd9Sstevel@tonic-gate if (n->val != 0) 8361961e0fSrobinson free(n->val); 847c478bd9Sstevel@tonic-gate if (n->key != 0) 8561961e0fSrobinson free(n->key); 867c478bd9Sstevel@tonic-gate if (n->map != 0) 8761961e0fSrobinson free(n->map); 887c478bd9Sstevel@tonic-gate if (n->domain != 0) 8961961e0fSrobinson free(n->domain); 9061961e0fSrobinson free(n); 917c478bd9Sstevel@tonic-gate } 927c478bd9Sstevel@tonic-gate 937de476d1Ssm /* 947de476d1Ssm * Attempt to Add item to cache 957de476d1Ssm */ 967c478bd9Sstevel@tonic-gate static struct cache * 9761961e0fSrobinson makenode(char *domain, char *map, int keylen, int vallen) 987c478bd9Sstevel@tonic-gate { 997c478bd9Sstevel@tonic-gate struct cache *n; 1007c478bd9Sstevel@tonic-gate 1017de476d1Ssm /* Do not cache 'passwd' values i.e. passwd.byname or passwd.byuid. */ 1027de476d1Ssm if (strncmp(map, "passwd", 6) == 0) 1037de476d1Ssm return (0); 1047de476d1Ssm 10561961e0fSrobinson if ((n = calloc(1, sizeof (*n))) == 0) 1067c478bd9Sstevel@tonic-gate return (0); 1077c478bd9Sstevel@tonic-gate if (((n->domain = strdup(domain)) == 0) || 1087c478bd9Sstevel@tonic-gate ((n->map = strdup(map)) == 0) || 1097c478bd9Sstevel@tonic-gate ((n->key = malloc(keylen)) == 0) || 1107c478bd9Sstevel@tonic-gate ((n->val = malloc(vallen)) == 0)) { 1117c478bd9Sstevel@tonic-gate freenode(n); 1127c478bd9Sstevel@tonic-gate return (0); 1137c478bd9Sstevel@tonic-gate } 1147c478bd9Sstevel@tonic-gate return (n); 1157c478bd9Sstevel@tonic-gate } 1167c478bd9Sstevel@tonic-gate 1177de476d1Ssm /* 1187de476d1Ssm * Look for a matching result in the per-process cache. 1197de476d1Ssm * Upon finding a match set the passed in 'val' and 'vallen' 1207de476d1Ssm * parameters and return 1. Otherwise return 0. 1217de476d1Ssm */ 1227c478bd9Sstevel@tonic-gate static int 12361961e0fSrobinson in_cache(char *domain, char *map, char *key, int keylen, char **val, 12461961e0fSrobinson int *vallen) 1257c478bd9Sstevel@tonic-gate { 1267c478bd9Sstevel@tonic-gate struct cache *c, **pp; 1277c478bd9Sstevel@tonic-gate int cnt; 1287c478bd9Sstevel@tonic-gate struct timeval now; 1297c478bd9Sstevel@tonic-gate struct timezone tz; 1307c478bd9Sstevel@tonic-gate 1317de476d1Ssm /* The 'passwd' data is not cached. */ 1327de476d1Ssm if (strncmp(map, "passwd", 6) == 0) 1337de476d1Ssm return (0); 1347de476d1Ssm 1357c478bd9Sstevel@tonic-gate /* 1367c478bd9Sstevel@tonic-gate * Assumes that caller (yp_match) has locked the cache 1377c478bd9Sstevel@tonic-gate */ 1387c478bd9Sstevel@tonic-gate for (pp = &head, cnt = 0; (c = *pp) != 0; pp = &c->next, cnt++) { 1397c478bd9Sstevel@tonic-gate if ((c->keylen == keylen) && 1407c478bd9Sstevel@tonic-gate (memcmp(key, c->key, (size_t)keylen) == 0) && 1417c478bd9Sstevel@tonic-gate (strcmp(map, c->map) == 0) && 1427c478bd9Sstevel@tonic-gate (strcmp(domain, c->domain) == 0)) { 1437c478bd9Sstevel@tonic-gate /* cache hit */ 1447c478bd9Sstevel@tonic-gate (void) gettimeofday(&now, &tz); 1457c478bd9Sstevel@tonic-gate if ((now.tv_sec - c->birth) > CACHETO) { 1467c478bd9Sstevel@tonic-gate /* rats. it is too old to use */ 1477c478bd9Sstevel@tonic-gate *pp = c->next; 1487c478bd9Sstevel@tonic-gate freenode(c); 1497c478bd9Sstevel@tonic-gate break; 1507c478bd9Sstevel@tonic-gate } else { 1517c478bd9Sstevel@tonic-gate *val = c->val; 1527c478bd9Sstevel@tonic-gate *vallen = c->vallen; 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate /* Ersatz LRU: Move this entry to the front */ 1557c478bd9Sstevel@tonic-gate *pp = c->next; 1567c478bd9Sstevel@tonic-gate c->next = head; 1577c478bd9Sstevel@tonic-gate head = c; 1587c478bd9Sstevel@tonic-gate return (1); 1597c478bd9Sstevel@tonic-gate } 1607c478bd9Sstevel@tonic-gate } 1617c478bd9Sstevel@tonic-gate if (cnt >= CACHESZ) { 1627c478bd9Sstevel@tonic-gate *pp = c->next; 1637c478bd9Sstevel@tonic-gate freenode(c); 1647c478bd9Sstevel@tonic-gate break; 1657c478bd9Sstevel@tonic-gate } 1667c478bd9Sstevel@tonic-gate } 1677c478bd9Sstevel@tonic-gate return (0); 1687c478bd9Sstevel@tonic-gate } 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate /* 1717c478bd9Sstevel@tonic-gate * Requests the yp server associated with a given domain to attempt to match 1727c478bd9Sstevel@tonic-gate * the passed key datum in the named map, and to return the associated value 1737c478bd9Sstevel@tonic-gate * datum. This part does parameter checking, and implements the "infinite" 1747c478bd9Sstevel@tonic-gate * (until success) sleep loop if 'hardlookup' parameter is set. 1757c478bd9Sstevel@tonic-gate */ 1767c478bd9Sstevel@tonic-gate int 17761961e0fSrobinson __yp_match_cflookup(char *domain, char *map, char *key, int keylen, char **val, 17861961e0fSrobinson int *vallen, int hardlookup) 1797c478bd9Sstevel@tonic-gate { 1807c478bd9Sstevel@tonic-gate size_t domlen; 1817c478bd9Sstevel@tonic-gate size_t maplen; 1827c478bd9Sstevel@tonic-gate int reason; 1837c478bd9Sstevel@tonic-gate struct dom_binding *pdomb; 1847c478bd9Sstevel@tonic-gate int savesize; 1857c478bd9Sstevel@tonic-gate struct timeval now; 1867c478bd9Sstevel@tonic-gate struct timezone tz; 1877c478bd9Sstevel@tonic-gate char *my_val; 1887c478bd9Sstevel@tonic-gate int my_vallen; 1897c478bd9Sstevel@tonic-gate int found_it; 1907c478bd9Sstevel@tonic-gate int cachegen; 1917c478bd9Sstevel@tonic-gate 19261961e0fSrobinson if ((map == NULL) || (domain == NULL)) 1937c478bd9Sstevel@tonic-gate return (YPERR_BADARGS); 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate domlen = strlen(domain); 1967c478bd9Sstevel@tonic-gate maplen = strlen(map); 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate if ((domlen == 0) || (domlen > YPMAXDOMAIN) || 1997c478bd9Sstevel@tonic-gate (maplen == 0) || (maplen > YPMAXMAP) || 20061961e0fSrobinson (key == NULL) || (keylen == 0)) 2017c478bd9Sstevel@tonic-gate return (YPERR_BADARGS); 2027c478bd9Sstevel@tonic-gate 20361961e0fSrobinson (void) mutex_lock(&cache_lock); 2047c478bd9Sstevel@tonic-gate found_it = in_cache(domain, map, key, keylen, &my_val, &my_vallen); 2057c478bd9Sstevel@tonic-gate cachegen = generation; 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate if (found_it) { 2087c478bd9Sstevel@tonic-gate /* NB: Copy two extra bytes; see below */ 2097c478bd9Sstevel@tonic-gate savesize = my_vallen + 2; 2107c478bd9Sstevel@tonic-gate if ((*val = malloc((size_t)savesize)) == 0) { 21161961e0fSrobinson (void) mutex_unlock(&cache_lock); 2127c478bd9Sstevel@tonic-gate return (YPERR_RESRC); 2137c478bd9Sstevel@tonic-gate } 2147c478bd9Sstevel@tonic-gate (void) memcpy(*val, my_val, (size_t)savesize); 2157c478bd9Sstevel@tonic-gate *vallen = my_vallen; 21661961e0fSrobinson (void) mutex_unlock(&cache_lock); 2177c478bd9Sstevel@tonic-gate return (0); /* Success */ 2187c478bd9Sstevel@tonic-gate } 21961961e0fSrobinson (void) mutex_unlock(&cache_lock); 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate for (;;) { 2227c478bd9Sstevel@tonic-gate 22361961e0fSrobinson if (reason = __yp_dobind_cflookup(domain, &pdomb, hardlookup)) 2247c478bd9Sstevel@tonic-gate return (reason); 2257c478bd9Sstevel@tonic-gate 2267c478bd9Sstevel@tonic-gate if (pdomb->dom_binding->ypbind_hi_vers >= YPVERS) { 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate reason = domatch(domain, map, key, keylen, pdomb, 2297c478bd9Sstevel@tonic-gate &_ypserv_timeout, val, vallen); 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate __yp_rel_binding(pdomb); 2327c478bd9Sstevel@tonic-gate if (reason == YPERR_RPC || reason == YPERR_YPSERV || 2337c478bd9Sstevel@tonic-gate reason == YPERR_BUSY /* as if */) { 2347c478bd9Sstevel@tonic-gate yp_unbind(domain); 2357c478bd9Sstevel@tonic-gate if (hardlookup) 236e8031f0aSraf (void) sleep(_ypsleeptime); /* retry */ 23761961e0fSrobinson else 2387c478bd9Sstevel@tonic-gate return (reason); 2397c478bd9Sstevel@tonic-gate } else 2407c478bd9Sstevel@tonic-gate break; 2417c478bd9Sstevel@tonic-gate } else { 2427c478bd9Sstevel@tonic-gate __yp_rel_binding(pdomb); 2437c478bd9Sstevel@tonic-gate return (YPERR_VERS); 2447c478bd9Sstevel@tonic-gate } 2457c478bd9Sstevel@tonic-gate } 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate /* add to our cache */ 2487c478bd9Sstevel@tonic-gate if (reason == 0) { 24961961e0fSrobinson (void) mutex_lock(&cache_lock); 2507c478bd9Sstevel@tonic-gate /* 2517c478bd9Sstevel@tonic-gate * Check whether some other annoying thread did the same 2527c478bd9Sstevel@tonic-gate * thing in parallel with us. I hate it when that happens... 2537c478bd9Sstevel@tonic-gate */ 2547c478bd9Sstevel@tonic-gate if (generation != cachegen && 2557c478bd9Sstevel@tonic-gate in_cache(domain, map, key, keylen, &my_val, &my_vallen)) { 2567c478bd9Sstevel@tonic-gate /* 2577c478bd9Sstevel@tonic-gate * Could get cute and update the birth time, but it's 2587c478bd9Sstevel@tonic-gate * not worth the bother. 2597c478bd9Sstevel@tonic-gate * It looks strange that we return one val[] array 2607c478bd9Sstevel@tonic-gate * to the caller and have a different copy of the 2617c478bd9Sstevel@tonic-gate * val[] array in the cache (presumably with the 2627c478bd9Sstevel@tonic-gate * same contents), but it should work just fine. 2637c478bd9Sstevel@tonic-gate * So, do absolutely nothing... 2647c478bd9Sstevel@tonic-gate */ 2657c478bd9Sstevel@tonic-gate /* EMPTY */ 2667c478bd9Sstevel@tonic-gate } else { 2677c478bd9Sstevel@tonic-gate struct cache *c; 2687c478bd9Sstevel@tonic-gate /* 2697c478bd9Sstevel@tonic-gate * NB: allocate and copy extract two bytes of the 2707c478bd9Sstevel@tonic-gate * value; these are mandatory CR and NULL bytes. 2717c478bd9Sstevel@tonic-gate */ 2727c478bd9Sstevel@tonic-gate savesize = *vallen + 2; 2737c478bd9Sstevel@tonic-gate c = makenode(domain, map, keylen, savesize); 2747c478bd9Sstevel@tonic-gate if (c != 0) { 2757c478bd9Sstevel@tonic-gate (void) gettimeofday(&now, &tz); 2767c478bd9Sstevel@tonic-gate c->birth = now.tv_sec; 2777c478bd9Sstevel@tonic-gate c->keylen = keylen; 2787c478bd9Sstevel@tonic-gate c->vallen = *vallen; 2797c478bd9Sstevel@tonic-gate (void) memcpy(c->key, key, (size_t)keylen); 2807c478bd9Sstevel@tonic-gate (void) memcpy(c->val, *val, (size_t)savesize); 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate c->next = head; 2837c478bd9Sstevel@tonic-gate head = c; 2847c478bd9Sstevel@tonic-gate ++generation; 2857c478bd9Sstevel@tonic-gate } 2867c478bd9Sstevel@tonic-gate } 28761961e0fSrobinson (void) mutex_unlock(&cache_lock); 2887c478bd9Sstevel@tonic-gate } else if (reason == YPERR_MAP && geteuid() == 0) { 2897c478bd9Sstevel@tonic-gate /* 2907c478bd9Sstevel@tonic-gate * Lookup could be for a secure map; fail over to retry 2917c478bd9Sstevel@tonic-gate * from a reserved port. Only useful to try this if we're 2927c478bd9Sstevel@tonic-gate * the super user. 2937c478bd9Sstevel@tonic-gate */ 2947c478bd9Sstevel@tonic-gate int rsvdreason; 2957c478bd9Sstevel@tonic-gate rsvdreason = yp_match_rsvdport(domain, map, key, keylen, val, 2967c478bd9Sstevel@tonic-gate vallen); 2977c478bd9Sstevel@tonic-gate if (rsvdreason == 0) 2987c478bd9Sstevel@tonic-gate reason = rsvdreason; 2997c478bd9Sstevel@tonic-gate } 3007c478bd9Sstevel@tonic-gate return (reason); 3017c478bd9Sstevel@tonic-gate } 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate int 3047c478bd9Sstevel@tonic-gate yp_match( 3057c478bd9Sstevel@tonic-gate char *domain, 3067c478bd9Sstevel@tonic-gate char *map, 3077c478bd9Sstevel@tonic-gate char *key, 3087c478bd9Sstevel@tonic-gate int keylen, 3097c478bd9Sstevel@tonic-gate char **val, /* returns value array */ 3107c478bd9Sstevel@tonic-gate int *vallen) /* returns bytes in val */ 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate { 3137c478bd9Sstevel@tonic-gate /* the traditional yp_match loops forever thus hardlookup is set */ 3147c478bd9Sstevel@tonic-gate return (__yp_match_cflookup(domain, map, key, keylen, val, vallen, 1)); 3157c478bd9Sstevel@tonic-gate } 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate extern void 31861961e0fSrobinson __empty_yp_cache(void) 3197c478bd9Sstevel@tonic-gate { 3207c478bd9Sstevel@tonic-gate struct cache *p, *n; 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate /* Copy the cache pointer and make it ZERO */ 32361961e0fSrobinson (void) mutex_lock(&cache_lock); 3247c478bd9Sstevel@tonic-gate p = head; 3257c478bd9Sstevel@tonic-gate head = 0; 32661961e0fSrobinson (void) mutex_unlock(&cache_lock); 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate if (p == 0) 3297c478bd9Sstevel@tonic-gate return; 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate /* Empty the cache */ 3327c478bd9Sstevel@tonic-gate n = p->next; 3337c478bd9Sstevel@tonic-gate while (p) { 3347c478bd9Sstevel@tonic-gate freenode(p); 3357c478bd9Sstevel@tonic-gate p = n; 3367c478bd9Sstevel@tonic-gate if (p) 3377c478bd9Sstevel@tonic-gate n = p->next; 3387c478bd9Sstevel@tonic-gate } 3397c478bd9Sstevel@tonic-gate } 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate /* 3427c478bd9Sstevel@tonic-gate * Requests the yp server associated with a given domain to attempt to match 3437c478bd9Sstevel@tonic-gate * the passed key datum in the named map, and to return the associated value 3447c478bd9Sstevel@tonic-gate * datum. This part does parameter checking, and implements the "infinite" 3457c478bd9Sstevel@tonic-gate * (until success) sleep loop. 3467c478bd9Sstevel@tonic-gate * 3477c478bd9Sstevel@tonic-gate * XXX special version for handling C2 (passwd.adjunct) lookups when we need 3487c478bd9Sstevel@tonic-gate * a reserved port. 3497c478bd9Sstevel@tonic-gate * Only difference against yp_match is that this function uses 3507c478bd9Sstevel@tonic-gate * __yp_dobind_rsvdport(). 3517c478bd9Sstevel@tonic-gate * 3527c478bd9Sstevel@tonic-gate * Only called from NIS switch backend. 3537c478bd9Sstevel@tonic-gate */ 3547c478bd9Sstevel@tonic-gate int 3557c478bd9Sstevel@tonic-gate __yp_match_rsvdport_cflookup( 3567c478bd9Sstevel@tonic-gate char *domain, 3577c478bd9Sstevel@tonic-gate char *map, 3587c478bd9Sstevel@tonic-gate char *key, 3597c478bd9Sstevel@tonic-gate int keylen, 3607c478bd9Sstevel@tonic-gate char **val, /* returns value array */ 3617c478bd9Sstevel@tonic-gate int *vallen, /* returns bytes in val */ 3627c478bd9Sstevel@tonic-gate int hardlookup) /* retry until we can an answer */ 3637c478bd9Sstevel@tonic-gate { 3647c478bd9Sstevel@tonic-gate size_t domlen; 3657c478bd9Sstevel@tonic-gate size_t maplen; 3667c478bd9Sstevel@tonic-gate int reason; 3677c478bd9Sstevel@tonic-gate struct dom_binding *pdomb; 3687c478bd9Sstevel@tonic-gate int savesize; 3697c478bd9Sstevel@tonic-gate struct timeval now; 3707c478bd9Sstevel@tonic-gate struct timezone tz; 3717c478bd9Sstevel@tonic-gate char *my_val; 3727c478bd9Sstevel@tonic-gate int my_vallen; 3737c478bd9Sstevel@tonic-gate int found_it; 3747c478bd9Sstevel@tonic-gate int cachegen; 3757c478bd9Sstevel@tonic-gate 37661961e0fSrobinson if ((map == NULL) || (domain == NULL)) 3777c478bd9Sstevel@tonic-gate return (YPERR_BADARGS); 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate domlen = strlen(domain); 3807c478bd9Sstevel@tonic-gate maplen = strlen(map); 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate if ((domlen == 0) || (domlen > YPMAXDOMAIN) || 3837c478bd9Sstevel@tonic-gate (maplen == 0) || (maplen > YPMAXMAP) || 38461961e0fSrobinson (key == NULL) || (keylen == 0)) 3857c478bd9Sstevel@tonic-gate return (YPERR_BADARGS); 3867c478bd9Sstevel@tonic-gate 38761961e0fSrobinson (void) mutex_lock(&cache_lock); 3887c478bd9Sstevel@tonic-gate found_it = in_cache(domain, map, key, keylen, &my_val, &my_vallen); 3897c478bd9Sstevel@tonic-gate cachegen = generation; 3907c478bd9Sstevel@tonic-gate if (found_it) { 3917c478bd9Sstevel@tonic-gate /* NB: Copy two extra bytes; see below */ 3927c478bd9Sstevel@tonic-gate savesize = my_vallen + 2; 3937c478bd9Sstevel@tonic-gate if ((*val = malloc((size_t)savesize)) == 0) { 39461961e0fSrobinson (void) mutex_unlock(&cache_lock); 3957c478bd9Sstevel@tonic-gate return (YPERR_RESRC); 3967c478bd9Sstevel@tonic-gate } 3977c478bd9Sstevel@tonic-gate (void) memcpy(*val, my_val, (size_t)savesize); 3987c478bd9Sstevel@tonic-gate *vallen = my_vallen; 39961961e0fSrobinson (void) mutex_unlock(&cache_lock); 4007c478bd9Sstevel@tonic-gate return (0); /* Success */ 4017c478bd9Sstevel@tonic-gate } 40261961e0fSrobinson (void) mutex_unlock(&cache_lock); 4037c478bd9Sstevel@tonic-gate 4047c478bd9Sstevel@tonic-gate for (;;) { 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate if (reason = __yp_dobind_rsvdport_cflookup(domain, &pdomb, 40761961e0fSrobinson hardlookup)) 4087c478bd9Sstevel@tonic-gate return (reason); 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate if (pdomb->dom_binding->ypbind_hi_vers >= YPVERS) { 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate reason = domatch(domain, map, key, keylen, 4137c478bd9Sstevel@tonic-gate pdomb, &_ypserv_timeout, val, vallen); 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate /* 4167c478bd9Sstevel@tonic-gate * Have to free the binding since the reserved 4177c478bd9Sstevel@tonic-gate * port bindings are not cached. 4187c478bd9Sstevel@tonic-gate */ 4197c478bd9Sstevel@tonic-gate __yp_rel_binding(pdomb); 4207c478bd9Sstevel@tonic-gate free_dom_binding(pdomb); 4217c478bd9Sstevel@tonic-gate 4227c478bd9Sstevel@tonic-gate if (reason == YPERR_RPC || reason == YPERR_YPSERV || 4237c478bd9Sstevel@tonic-gate reason == YPERR_BUSY /* as if */) { 4247c478bd9Sstevel@tonic-gate yp_unbind(domain); 4257c478bd9Sstevel@tonic-gate if (hardlookup) 426e8031f0aSraf (void) sleep(_ypsleeptime); /* retry */ 42761961e0fSrobinson else 4287c478bd9Sstevel@tonic-gate return (reason); 4297c478bd9Sstevel@tonic-gate } else 4307c478bd9Sstevel@tonic-gate break; 4317c478bd9Sstevel@tonic-gate } else { 4327c478bd9Sstevel@tonic-gate /* 4337c478bd9Sstevel@tonic-gate * Have to free the binding since the reserved 4347c478bd9Sstevel@tonic-gate * port bindings are not cached. 4357c478bd9Sstevel@tonic-gate */ 4367c478bd9Sstevel@tonic-gate __yp_rel_binding(pdomb); 4377c478bd9Sstevel@tonic-gate free_dom_binding(pdomb); 4387c478bd9Sstevel@tonic-gate return (YPERR_VERS); 4397c478bd9Sstevel@tonic-gate } 4407c478bd9Sstevel@tonic-gate } 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate /* add to our cache */ 4437c478bd9Sstevel@tonic-gate if (reason == 0) { 44461961e0fSrobinson (void) mutex_lock(&cache_lock); 4457c478bd9Sstevel@tonic-gate /* 4467c478bd9Sstevel@tonic-gate * Check whether some other annoying thread did the same 4477c478bd9Sstevel@tonic-gate * thing in parallel with us. I hate it when that happens... 4487c478bd9Sstevel@tonic-gate */ 4497c478bd9Sstevel@tonic-gate if (generation != cachegen && 4507c478bd9Sstevel@tonic-gate in_cache(domain, map, key, keylen, &my_val, &my_vallen)) { 4517c478bd9Sstevel@tonic-gate /* 4527c478bd9Sstevel@tonic-gate * Could get cute and update the birth time, but it's 4537c478bd9Sstevel@tonic-gate * not worth the bother. 4547c478bd9Sstevel@tonic-gate * It looks strange that we return one val[] array 4557c478bd9Sstevel@tonic-gate * to the caller and have a different copy of the 4567c478bd9Sstevel@tonic-gate * val[] array in the cache (presumably with the 4577c478bd9Sstevel@tonic-gate * same contents), but it should work just fine. 4587c478bd9Sstevel@tonic-gate * So, do absolutely nothing... 4597c478bd9Sstevel@tonic-gate */ 4607c478bd9Sstevel@tonic-gate /* EMPTY */ 4617c478bd9Sstevel@tonic-gate } else { 4627c478bd9Sstevel@tonic-gate struct cache *c; 4637c478bd9Sstevel@tonic-gate /* 4647c478bd9Sstevel@tonic-gate * NB: allocate and copy extract two bytes of the 4657c478bd9Sstevel@tonic-gate * value; these are mandatory CR and NULL bytes. 4667c478bd9Sstevel@tonic-gate */ 4677c478bd9Sstevel@tonic-gate savesize = *vallen + 2; 4687c478bd9Sstevel@tonic-gate c = makenode(domain, map, keylen, savesize); 4697c478bd9Sstevel@tonic-gate if (c != 0) { 4707c478bd9Sstevel@tonic-gate (void) gettimeofday(&now, &tz); 4717c478bd9Sstevel@tonic-gate c->birth = now.tv_sec; 4727c478bd9Sstevel@tonic-gate c->keylen = keylen; 4737c478bd9Sstevel@tonic-gate c->vallen = *vallen; 4747c478bd9Sstevel@tonic-gate (void) memcpy(c->key, key, (size_t)keylen); 4757c478bd9Sstevel@tonic-gate (void) memcpy(c->val, *val, (size_t)savesize); 4767c478bd9Sstevel@tonic-gate 4777c478bd9Sstevel@tonic-gate c->next = head; 4787c478bd9Sstevel@tonic-gate head = c; 4797c478bd9Sstevel@tonic-gate ++generation; 4807c478bd9Sstevel@tonic-gate } 4817c478bd9Sstevel@tonic-gate } 48261961e0fSrobinson (void) mutex_unlock(&cache_lock); 4837c478bd9Sstevel@tonic-gate } 4847c478bd9Sstevel@tonic-gate return (reason); 4857c478bd9Sstevel@tonic-gate } 4867c478bd9Sstevel@tonic-gate 4877c478bd9Sstevel@tonic-gate 4887c478bd9Sstevel@tonic-gate int 4897c478bd9Sstevel@tonic-gate yp_match_rsvdport( 4907c478bd9Sstevel@tonic-gate char *domain, 4917c478bd9Sstevel@tonic-gate char *map, 4927c478bd9Sstevel@tonic-gate char *key, 4937c478bd9Sstevel@tonic-gate int keylen, 4947c478bd9Sstevel@tonic-gate char **val, /* returns value array */ 4957c478bd9Sstevel@tonic-gate int *vallen) /* returns bytes in val */ 4967c478bd9Sstevel@tonic-gate { 4977c478bd9Sstevel@tonic-gate /* traditional yp_match retries forever so set hardlookup */ 4987c478bd9Sstevel@tonic-gate return (__yp_match_rsvdport_cflookup(domain, map, key, keylen, val, 4997c478bd9Sstevel@tonic-gate vallen, 1)); 5007c478bd9Sstevel@tonic-gate } 5017c478bd9Sstevel@tonic-gate 5027c478bd9Sstevel@tonic-gate 5037c478bd9Sstevel@tonic-gate /* 5047c478bd9Sstevel@tonic-gate * This talks v3 protocol to ypserv 5057c478bd9Sstevel@tonic-gate */ 5067c478bd9Sstevel@tonic-gate static int 5077c478bd9Sstevel@tonic-gate domatch(char *domain, char *map, char *key, int keylen, 5087c478bd9Sstevel@tonic-gate struct dom_binding *pdomb, struct timeval *timeoutp, char **val, 5097c478bd9Sstevel@tonic-gate int *vallen) 5107c478bd9Sstevel@tonic-gate { 5117c478bd9Sstevel@tonic-gate struct ypreq_key req; 5127c478bd9Sstevel@tonic-gate struct ypresp_val resp; 5137c478bd9Sstevel@tonic-gate unsigned int retval = 0; 5147c478bd9Sstevel@tonic-gate 5157c478bd9Sstevel@tonic-gate req.domain = domain; 5167c478bd9Sstevel@tonic-gate req.map = map; 5177c478bd9Sstevel@tonic-gate req.keydat.dptr = key; 5187c478bd9Sstevel@tonic-gate req.keydat.dsize = keylen; 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate resp.valdat.dptr = NULL; 5217c478bd9Sstevel@tonic-gate resp.valdat.dsize = 0; 5227c478bd9Sstevel@tonic-gate (void) memset((char *)&resp, 0, sizeof (struct ypresp_val)); 5237c478bd9Sstevel@tonic-gate 5247c478bd9Sstevel@tonic-gate /* 5257c478bd9Sstevel@tonic-gate * Do the match request. If the rpc call failed, return with status 5267c478bd9Sstevel@tonic-gate * from this point. 5277c478bd9Sstevel@tonic-gate */ 5287c478bd9Sstevel@tonic-gate 5297c478bd9Sstevel@tonic-gate switch (clnt_call(pdomb->dom_client, YPPROC_MATCH, 5307c478bd9Sstevel@tonic-gate (xdrproc_t)xdr_ypreq_key, (char *)&req, 5317c478bd9Sstevel@tonic-gate (xdrproc_t)xdr_ypresp_val, (char *)&resp, 5327c478bd9Sstevel@tonic-gate *timeoutp)) { 5337c478bd9Sstevel@tonic-gate case RPC_SUCCESS: 5347c478bd9Sstevel@tonic-gate break; 5357c478bd9Sstevel@tonic-gate case RPC_TIMEDOUT: 5367c478bd9Sstevel@tonic-gate return (YPERR_YPSERV); 5377c478bd9Sstevel@tonic-gate default: 5387c478bd9Sstevel@tonic-gate return (YPERR_RPC); 5397c478bd9Sstevel@tonic-gate } 5407c478bd9Sstevel@tonic-gate 5417c478bd9Sstevel@tonic-gate /* See if the request succeeded */ 5427c478bd9Sstevel@tonic-gate 5437c478bd9Sstevel@tonic-gate if (resp.status != YP_TRUE) { 5447c478bd9Sstevel@tonic-gate retval = ypprot_err(resp.status); 5457c478bd9Sstevel@tonic-gate } 5467c478bd9Sstevel@tonic-gate 547*48bbca81SDaniel Hoffman /* Get some memory which the user can get rid of as they likes */ 5487c478bd9Sstevel@tonic-gate 5497c478bd9Sstevel@tonic-gate if (!retval && ((*val = malloc((size_t) 5507c478bd9Sstevel@tonic-gate resp.valdat.dsize + 2)) == NULL)) { 5517c478bd9Sstevel@tonic-gate retval = YPERR_RESRC; 5527c478bd9Sstevel@tonic-gate } 5537c478bd9Sstevel@tonic-gate 5547c478bd9Sstevel@tonic-gate /* Copy the returned value byte string into the new memory */ 5557c478bd9Sstevel@tonic-gate 5567c478bd9Sstevel@tonic-gate if (!retval) { 5577c478bd9Sstevel@tonic-gate *vallen = (int)resp.valdat.dsize; 5587c478bd9Sstevel@tonic-gate (void) memcpy(*val, resp.valdat.dptr, 5597c478bd9Sstevel@tonic-gate (size_t)resp.valdat.dsize); 5607c478bd9Sstevel@tonic-gate (*val)[resp.valdat.dsize] = '\n'; 5617c478bd9Sstevel@tonic-gate (*val)[resp.valdat.dsize + 1] = '\0'; 5627c478bd9Sstevel@tonic-gate } 5637c478bd9Sstevel@tonic-gate 5647c478bd9Sstevel@tonic-gate CLNT_FREERES(pdomb->dom_client, 5657c478bd9Sstevel@tonic-gate (xdrproc_t)xdr_ypresp_val, (char *)&resp); 5667c478bd9Sstevel@tonic-gate return (retval); 5677c478bd9Sstevel@tonic-gate } 568