11919Swollman/* 21919Swollman * Copyright (c) 1992/3 Theo de Raadt <deraadt@fsa.ca> 334146Swpaul * Copyright (c) 1998 Bill Paul <wpaul@ctr.columbia.edu> 41919Swollman * All rights reserved. 51919Swollman * 61919Swollman * Redistribution and use in source and binary forms, with or without 71919Swollman * modification, are permitted provided that the following conditions 81919Swollman * are met: 91919Swollman * 1. Redistributions of source code must retain the above copyright 101919Swollman * notice, this list of conditions and the following disclaimer. 111919Swollman * 2. Redistributions in binary form must reproduce the above copyright 121919Swollman * notice, this list of conditions and the following disclaimer in the 131919Swollman * documentation and/or other materials provided with the distribution. 141919Swollman * 3. The name of the author may not be used to endorse or promote 151919Swollman * products derived from this software without specific prior written 161919Swollman * permission. 171919Swollman * 181919Swollman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 191919Swollman * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 201919Swollman * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 211919Swollman * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 221919Swollman * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 231919Swollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 241919Swollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 251919Swollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 261919Swollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 271919Swollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 281919Swollman * SUCH DAMAGE. 291919Swollman */ 301919Swollman 3192986Sobrien#include <sys/cdefs.h> 3292986Sobrien__FBSDID("$FreeBSD$"); 331919Swollman 3471579Sdeischen#include "namespace.h" 35144678Sume#include "reentrant.h" 361919Swollman#include <sys/param.h> 371919Swollman#include <sys/types.h> 381919Swollman#include <sys/socket.h> 391919Swollman#include <sys/file.h> 401919Swollman#include <sys/uio.h> 4190868Smike#include <arpa/inet.h> 421919Swollman#include <errno.h> 431919Swollman#include <stdio.h> 441919Swollman#include <string.h> 457722Swpaul#include <stdlib.h> 467722Swpaul#include <unistd.h> 471919Swollman#include <rpc/rpc.h> 481919Swollman#include <rpc/xdr.h> 4912816Swpaul#include <rpcsvc/yp.h> 5071579Sdeischen#include "un-namespace.h" 5171579Sdeischen#include "libc_private.h" 5212816Swpaul 5312816Swpaul/* 5412816Swpaul * We have to define these here due to clashes between yp_prot.h and 5512816Swpaul * yp.h. 5612816Swpaul */ 5712816Swpaul 5834146Swpaul#define YPMATCHCACHE 5934146Swpaul 6034146Swpaul#ifdef YPMATCHCACHE 6134146Swpaulstruct ypmatch_ent { 6234146Swpaul char *ypc_map; 6334146Swpaul keydat ypc_key; 6434146Swpaul valdat ypc_val; 6534146Swpaul time_t ypc_expire_t; 6634146Swpaul struct ypmatch_ent *ypc_next; 6734146Swpaul}; 6834146Swpaul#define YPLIB_MAXCACHE 5 /* At most 5 entries */ 6934146Swpaul#define YPLIB_EXPIRE 5 /* Expire after 5 seconds */ 7034146Swpaul#endif 7134146Swpaul 7212816Swpaulstruct dom_binding { 7334146Swpaul struct dom_binding *dom_pnext; 7434146Swpaul char dom_domain[YPMAXDOMAIN + 1]; 7534146Swpaul struct sockaddr_in dom_server_addr; 7634146Swpaul u_short dom_server_port; 7734146Swpaul int dom_socket; 7834146Swpaul CLIENT *dom_client; 7934146Swpaul u_short dom_local_port; /* now I finally know what this is for. */ 8034146Swpaul long dom_vers; 8134146Swpaul#ifdef YPMATCHCACHE 8234146Swpaul struct ypmatch_ent *cache; 8334146Swpaul int ypmatch_cachecnt; 8434146Swpaul#endif 8512816Swpaul}; 8612816Swpaul 871919Swollman#include <rpcsvc/ypclnt.h> 881919Swollman 891919Swollman#ifndef BINDINGDIR 901919Swollman#define BINDINGDIR "/var/yp/binding" 911919Swollman#endif 928091Swpaul#define MAX_RETRIES 20 931919Swollman 941919Swollmanextern bool_t xdr_domainname(), xdr_ypbind_resp(); 951919Swollmanextern bool_t xdr_ypreq_key(), xdr_ypresp_val(); 961919Swollmanextern bool_t xdr_ypreq_nokey(), xdr_ypresp_key_val(); 971919Swollmanextern bool_t xdr_ypresp_all(), xdr_ypresp_all_seq(); 981919Swollmanextern bool_t xdr_ypresp_master(); 991919Swollman 1001919Swollmanint (*ypresp_allfn)(); 1011919Swollmanvoid *ypresp_data; 1021919Swollman 10390297Sdesstatic void _yp_unbind(struct dom_binding *); 1041919Swollmanstruct dom_binding *_ypbindlist; 1051919Swollmanstatic char _yp_domain[MAXHOSTNAMELEN]; 106167197Ssimonint _yplib_timeout = 20; 1071919Swollman 108144714Sumestatic mutex_t _ypmutex = MUTEX_INITIALIZER; 109144678Sume#define YPLOCK() mutex_lock(&_ypmutex); 110144678Sume#define YPUNLOCK() mutex_unlock(&_ypmutex); 111144678Sume 1121919Swollman#ifdef YPMATCHCACHE 11390298Sdesstatic void 11490298Sdesypmatch_cache_delete(struct dom_binding *ypdb, struct ypmatch_ent *prev, 11590298Sdes struct ypmatch_ent *cur) 11634146Swpaul{ 11734146Swpaul if (prev == NULL) 11834146Swpaul ypdb->cache = cur->ypc_next; 11934146Swpaul else 12034146Swpaul prev->ypc_next = cur->ypc_next; 1211919Swollman 12234146Swpaul free(cur->ypc_map); 12334146Swpaul free(cur->ypc_key.keydat_val); 12434146Swpaul free(cur->ypc_val.valdat_val); 12534146Swpaul free(cur); 1261919Swollman 12734146Swpaul ypdb->ypmatch_cachecnt--; 12834146Swpaul 12934146Swpaul return; 13034146Swpaul} 13134146Swpaul 13290298Sdesstatic void 13390298Sdesypmatch_cache_flush(struct dom_binding *ypdb) 1341919Swollman{ 13534146Swpaul struct ypmatch_ent *n, *c = ypdb->cache; 1361919Swollman 13734146Swpaul while (c != NULL) { 13834146Swpaul n = c->ypc_next; 13934146Swpaul ypmatch_cache_delete(ypdb, NULL, c); 14034146Swpaul c = n; 14134146Swpaul } 14234146Swpaul 14334146Swpaul return; 14434146Swpaul} 14534146Swpaul 14690298Sdesstatic void 14790298Sdesypmatch_cache_expire(struct dom_binding *ypdb) 14834146Swpaul{ 14934146Swpaul struct ypmatch_ent *c = ypdb->cache; 15034146Swpaul struct ypmatch_ent *n, *p = NULL; 15134146Swpaul time_t t; 15234146Swpaul 1531919Swollman time(&t); 1541919Swollman 15534146Swpaul while (c != NULL) { 15634146Swpaul if (t >= c->ypc_expire_t) { 15734146Swpaul n = c->ypc_next; 15834146Swpaul ypmatch_cache_delete(ypdb, p, c); 15934146Swpaul c = n; 16034146Swpaul } else { 16134146Swpaul p = c; 16234146Swpaul c = c->ypc_next; 16334146Swpaul } 1641919Swollman } 1651919Swollman 16634146Swpaul return; 16734146Swpaul} 1681919Swollman 16990298Sdesstatic void 17090298Sdesypmatch_cache_insert(struct dom_binding *ypdb, char *map, keydat *key, 17190298Sdes valdat *val) 17234146Swpaul{ 17334146Swpaul struct ypmatch_ent *new; 1741919Swollman 17534146Swpaul /* Do an expire run to maybe open up a slot. */ 17634146Swpaul if (ypdb->ypmatch_cachecnt) 17734146Swpaul ypmatch_cache_expire(ypdb); 17834146Swpaul 17934146Swpaul /* 18034146Swpaul * If there are no slots free, then force an expire of 18134146Swpaul * the least recently used entry. 18234146Swpaul */ 18334146Swpaul if (ypdb->ypmatch_cachecnt >= YPLIB_MAXCACHE) { 18434146Swpaul struct ypmatch_ent *o = NULL, *c = ypdb->cache; 18534146Swpaul time_t oldest = 0; 18634146Swpaul 18734146Swpaul oldest = ~oldest; 18834146Swpaul 18990297Sdes while (c != NULL) { 19034146Swpaul if (c->ypc_expire_t < oldest) { 19134146Swpaul oldest = c->ypc_expire_t; 19234146Swpaul o = c; 19334146Swpaul } 19434146Swpaul c = c->ypc_next; 19534146Swpaul } 19634146Swpaul 19734146Swpaul if (o == NULL) 19834146Swpaul return; 19934146Swpaul o->ypc_expire_t = 0; 20034146Swpaul ypmatch_cache_expire(ypdb); 20134146Swpaul } 20234146Swpaul 20334146Swpaul new = malloc(sizeof(struct ypmatch_ent)); 20434146Swpaul if (new == NULL) 2051919Swollman return; 2061919Swollman 20734146Swpaul new->ypc_map = strdup(map); 20834146Swpaul if (new->ypc_map == NULL) { 20934146Swpaul free(new); 2101919Swollman return; 2111919Swollman } 21234146Swpaul new->ypc_key.keydat_val = malloc(key->keydat_len); 21334146Swpaul if (new->ypc_key.keydat_val == NULL) { 21434146Swpaul free(new->ypc_map); 21534146Swpaul free(new); 21634146Swpaul return; 21734146Swpaul } 21834146Swpaul new->ypc_val.valdat_val = malloc(val->valdat_len); 21934146Swpaul if (new->ypc_val.valdat_val == NULL) { 22034146Swpaul free(new->ypc_val.valdat_val); 22134146Swpaul free(new->ypc_map); 22234146Swpaul free(new); 22334146Swpaul return; 22434146Swpaul } 2251919Swollman 22634146Swpaul new->ypc_expire_t = time(NULL) + YPLIB_EXPIRE; 22734146Swpaul new->ypc_key.keydat_len = key->keydat_len; 22834146Swpaul new->ypc_val.valdat_len = val->valdat_len; 22934146Swpaul bcopy(key->keydat_val, new->ypc_key.keydat_val, key->keydat_len); 23034146Swpaul bcopy(val->valdat_val, new->ypc_val.valdat_val, val->valdat_len); 2311919Swollman 23234146Swpaul new->ypc_next = ypdb->cache; 23334146Swpaul ypdb->cache = new; 2341919Swollman 23534146Swpaul ypdb->ypmatch_cachecnt++; 23634146Swpaul 23734146Swpaul return; 2381919Swollman} 2391919Swollman 24090298Sdesstatic bool_t 24190298Sdesypmatch_cache_lookup(struct dom_binding *ypdb, char *map, keydat *key, 24290298Sdes valdat *val) 2431919Swollman{ 244199784Swollman struct ypmatch_ent *c; 2451919Swollman 24634146Swpaul ypmatch_cache_expire(ypdb); 2471919Swollman 24834146Swpaul for (c = ypdb->cache; c != NULL; c = c->ypc_next) { 24934146Swpaul if (strcmp(map, c->ypc_map)) 2501919Swollman continue; 25134146Swpaul if (key->keydat_len != c->ypc_key.keydat_len) 2521919Swollman continue; 25334146Swpaul if (bcmp(key->keydat_val, c->ypc_key.keydat_val, 25434146Swpaul key->keydat_len)) 2551919Swollman continue; 25634146Swpaul } 2571919Swollman 25834146Swpaul if (c == NULL) 25934146Swpaul return(FALSE); 26034146Swpaul 26134146Swpaul val->valdat_len = c->ypc_val.valdat_len; 26234146Swpaul val->valdat_val = c->ypc_val.valdat_val; 26334146Swpaul 26434146Swpaul return(TRUE); 2651919Swollman} 2661919Swollman#endif 2671919Swollman 26895658Sdesconst char * 26990298Sdesypbinderr_string(int incode) 2707982Swpaul{ 2717982Swpaul static char err[80]; 27290297Sdes switch (incode) { 2737982Swpaul case 0: 27490297Sdes return ("Success"); 2758245Swpaul case YPBIND_ERR_ERR: 27690297Sdes return ("Internal ypbind error"); 2778245Swpaul case YPBIND_ERR_NOSERV: 27890297Sdes return ("Domain not bound"); 2798245Swpaul case YPBIND_ERR_RESC: 28090297Sdes return ("System resource allocation failure"); 2817982Swpaul } 2828245Swpaul sprintf(err, "Unknown ypbind error: #%d\n", incode); 28390297Sdes return (err); 2847982Swpaul} 2857982Swpaul 2861919Swollmanint 28790298Sdes_yp_dobind(char *dom, struct dom_binding **ypdb) 2881919Swollman{ 28916096Sjraynard static pid_t pid = -1; 2901919Swollman char path[MAXPATHLEN]; 2911919Swollman struct dom_binding *ysd, *ysd2; 29212859Swpaul struct ypbind_resp ypbr; 2931919Swollman struct timeval tv; 2941919Swollman struct sockaddr_in clnt_sin; 29517141Sjkh int clnt_sock, fd; 29616106Sjraynard pid_t gpid; 2971919Swollman CLIENT *client; 2988091Swpaul int new = 0, r; 2998091Swpaul int retries = 0; 30016051Swpaul struct sockaddr_in check; 301143415Sstefanf socklen_t checklen = sizeof(struct sockaddr_in); 3021919Swollman 30324797Swpaul /* Not allowed; bad doggie. Bad. */ 30424797Swpaul if (strchr(dom, '/') != NULL) 30524797Swpaul return(YPERR_BADARGS); 30624797Swpaul 3071919Swollman gpid = getpid(); 30890297Sdes if (!(pid == -1 || pid == gpid)) { 3091919Swollman ysd = _ypbindlist; 31090297Sdes while (ysd) { 31190297Sdes if (ysd->dom_client != NULL) 31220716Swpaul _yp_unbind(ysd); 3131919Swollman ysd2 = ysd->dom_pnext; 3141919Swollman free(ysd); 3151919Swollman ysd = ysd2; 3161919Swollman } 3171919Swollman _ypbindlist = NULL; 3181919Swollman } 3191919Swollman pid = gpid; 3201919Swollman 32190297Sdes if (ypdb != NULL) 3221919Swollman *ypdb = NULL; 3231919Swollman 32490297Sdes if (dom == NULL || strlen(dom) == 0) 32590297Sdes return (YPERR_BADARGS); 3261919Swollman 32790297Sdes for (ysd = _ypbindlist; ysd; ysd = ysd->dom_pnext) 32890297Sdes if (strcmp(dom, ysd->dom_domain) == 0) 3291919Swollman break; 33015547Swpaul 33116051Swpaul 33290297Sdes if (ysd == NULL) { 3331919Swollman ysd = (struct dom_binding *)malloc(sizeof *ysd); 3341919Swollman bzero((char *)ysd, sizeof *ysd); 3351919Swollman ysd->dom_socket = -1; 3361919Swollman ysd->dom_vers = 0; 3371919Swollman new = 1; 33816051Swpaul } else { 33916051Swpaul /* Check the socket -- may have been hosed by the caller. */ 34071579Sdeischen if (_getsockname(ysd->dom_socket, (struct sockaddr *)&check, 34116051Swpaul &checklen) == -1 || check.sin_family != AF_INET || 34216051Swpaul check.sin_port != ysd->dom_local_port) { 34316051Swpaul /* Socket became bogus somehow... need to rebind. */ 34416051Swpaul int save, sock; 34516051Swpaul 34616051Swpaul sock = ysd->dom_socket; 34771579Sdeischen save = _dup(ysd->dom_socket); 34819520Swpaul if (ysd->dom_client != NULL) 34919520Swpaul clnt_destroy(ysd->dom_client); 35016051Swpaul ysd->dom_vers = 0; 35116051Swpaul ysd->dom_client = NULL; 35271579Sdeischen sock = _dup2(save, sock); 35356698Sjasone _close(save); 35416051Swpaul } 3551919Swollman } 35612095Swpaul 3571919Swollmanagain: 3588091Swpaul retries++; 3598091Swpaul if (retries > MAX_RETRIES) { 3608091Swpaul if (new) 3618091Swpaul free(ysd); 3628091Swpaul return(YPERR_YPBIND); 3638091Swpaul } 3641919Swollman#ifdef BINDINGDIR 36590297Sdes if (ysd->dom_vers == 0) { 36615547Swpaul /* 36715547Swpaul * We're trying to make a new binding: zorch the 36815547Swpaul * existing handle now (if any). 36915547Swpaul */ 37090297Sdes if (ysd->dom_client != NULL) { 37115547Swpaul clnt_destroy(ysd->dom_client); 37215547Swpaul ysd->dom_client = NULL; 37316051Swpaul ysd->dom_socket = -1; 37415547Swpaul } 37554167Skris snprintf(path, sizeof(path), "%s/%s.%d", BINDINGDIR, dom, 2); 376261813Sjilles if ((fd = _open(path, O_RDONLY | O_CLOEXEC)) == -1) { 3771919Swollman /* no binding file, YP is dead. */ 3788091Swpaul /* Try to bring it back to life. */ 37956698Sjasone _close(fd); 3808091Swpaul goto skipit; 3811919Swollman } 38290297Sdes if (_flock(fd, LOCK_EX|LOCK_NB) == -1 && errno == EWOULDBLOCK) { 3831919Swollman struct iovec iov[2]; 38412859Swpaul struct ypbind_resp ybr; 3851919Swollman u_short ypb_port; 3861919Swollman 3871919Swollman iov[0].iov_base = (caddr_t)&ypb_port; 3881919Swollman iov[0].iov_len = sizeof ypb_port; 3891919Swollman iov[1].iov_base = (caddr_t)&ybr; 3901919Swollman iov[1].iov_len = sizeof ybr; 3911919Swollman 39271579Sdeischen r = _readv(fd, iov, 2); 39390297Sdes if (r != iov[0].iov_len + iov[1].iov_len) { 39456698Sjasone _close(fd); 3951919Swollman ysd->dom_vers = -1; 3961919Swollman goto again; 3971919Swollman } 3981919Swollman 3991919Swollman bzero(&ysd->dom_server_addr, sizeof ysd->dom_server_addr); 4001919Swollman ysd->dom_server_addr.sin_family = AF_INET; 4011919Swollman ysd->dom_server_addr.sin_len = sizeof(struct sockaddr_in); 40289084Sjhb bcopy(&ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr, 40389084Sjhb &ysd->dom_server_addr.sin_addr.s_addr, 40489084Sjhb sizeof(ysd->dom_server_addr.sin_addr.s_addr)); 40589084Sjhb bcopy(&ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port, 40689084Sjhb &ysd->dom_server_addr.sin_port, 40789084Sjhb sizeof(ysd->dom_server_addr.sin_port)); 4081919Swollman 4091919Swollman ysd->dom_server_port = ysd->dom_server_addr.sin_port; 41056698Sjasone _close(fd); 4111919Swollman goto gotit; 4121919Swollman } else { 4131919Swollman /* no lock on binding file, YP is dead. */ 4148091Swpaul /* Try to bring it back to life. */ 41556698Sjasone _close(fd); 4168091Swpaul goto skipit; 4171919Swollman } 4181919Swollman } 4197722Swpaulskipit: 4201919Swollman#endif 42190297Sdes if (ysd->dom_vers == -1 || ysd->dom_vers == 0) { 42215547Swpaul /* 42315547Swpaul * We're trying to make a new binding: zorch the 42415547Swpaul * existing handle now (if any). 42515547Swpaul */ 42690297Sdes if (ysd->dom_client != NULL) { 42715547Swpaul clnt_destroy(ysd->dom_client); 42815547Swpaul ysd->dom_client = NULL; 42916051Swpaul ysd->dom_socket = -1; 43015547Swpaul } 4311919Swollman bzero((char *)&clnt_sin, sizeof clnt_sin); 4321919Swollman clnt_sin.sin_family = AF_INET; 4331919Swollman clnt_sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 4348870Srgrimes 4351919Swollman clnt_sock = RPC_ANYSOCK; 4361919Swollman client = clnttcp_create(&clnt_sin, YPBINDPROG, YPBINDVERS, &clnt_sock, 4371919Swollman 0, 0); 43890297Sdes if (client == NULL) { 43914776Swpaul /* 44014776Swpaul * These conditions indicate ypbind just isn't 44114776Swpaul * alive -- we probably don't want to shoot our 44215547Swpaul * mouth off in this case; instead generate error 44314776Swpaul * messages only for really exotic problems. 44414776Swpaul */ 44514776Swpaul if (rpc_createerr.cf_stat != RPC_PROGNOTREGISTERED && 44614776Swpaul (rpc_createerr.cf_stat != RPC_SYSTEMERROR && 44715547Swpaul rpc_createerr.cf_error.re_errno == ECONNREFUSED)) 44815547Swpaul clnt_pcreateerror("clnttcp_create"); 44990297Sdes if (new) 4501919Swollman free(ysd); 4518091Swpaul return (YPERR_YPBIND); 4521919Swollman } 4531919Swollman 45417162Swpaul /* 45517162Swpaul * Check the port number -- should be < IPPORT_RESERVED. 45617162Swpaul * If not, it's possible someone has registered a bogus 45717162Swpaul * ypbind with the portmapper and is trying to trick us. 45817162Swpaul */ 45917162Swpaul if (ntohs(clnt_sin.sin_port) >= IPPORT_RESERVED) { 46019520Swpaul if (client != NULL) 46119520Swpaul clnt_destroy(client); 46217162Swpaul if (new) 46317162Swpaul free(ysd); 46417162Swpaul return(YPERR_YPBIND); 46517162Swpaul } 4668091Swpaul tv.tv_sec = _yplib_timeout/2; 4671919Swollman tv.tv_usec = 0; 4681919Swollman r = clnt_call(client, YPBINDPROC_DOMAIN, 46995658Sdes (xdrproc_t)xdr_domainname, &dom, 47095658Sdes (xdrproc_t)xdr_ypbind_resp, &ypbr, tv); 47190297Sdes if (r != RPC_SUCCESS) { 47214776Swpaul clnt_destroy(client); 47314776Swpaul ysd->dom_vers = -1; 47416051Swpaul if (r == RPC_PROGUNAVAIL || r == RPC_PROCUNAVAIL) { 47516051Swpaul if (new) 47616051Swpaul free(ysd); 47714776Swpaul return(YPERR_YPBIND); 47816051Swpaul } 4791919Swollman fprintf(stderr, 4807721Swpaul "YP: server for domain %s not responding, retrying\n", dom); 4811919Swollman goto again; 4827982Swpaul } else { 4837982Swpaul if (ypbr.ypbind_status != YPBIND_SUCC_VAL) { 48456698Sjasone struct timespec time_to_sleep, time_remaining; 48590297Sdes 4868091Swpaul clnt_destroy(client); 4878091Swpaul ysd->dom_vers = -1; 48856698Sjasone 48956698Sjasone time_to_sleep.tv_sec = _yplib_timeout/2; 49056698Sjasone time_to_sleep.tv_nsec = 0; 49156698Sjasone _nanosleep(&time_to_sleep, 49256698Sjasone &time_remaining); 4938091Swpaul goto again; 4947982Swpaul } 4951919Swollman } 4961919Swollman clnt_destroy(client); 4971919Swollman 4981919Swollman bzero((char *)&ysd->dom_server_addr, sizeof ysd->dom_server_addr); 4991919Swollman ysd->dom_server_addr.sin_family = AF_INET; 50089084Sjhb bcopy(&ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port, 50189084Sjhb &ysd->dom_server_addr.sin_port, 50289084Sjhb sizeof(ysd->dom_server_addr.sin_port)); 50389084Sjhb bcopy(&ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr, 50489084Sjhb &ysd->dom_server_addr.sin_addr.s_addr, 50589084Sjhb sizeof(ysd->dom_server_addr.sin_addr.s_addr)); 50617162Swpaul 50717162Swpaul /* 50817162Swpaul * We could do a reserved port check here too, but this 50917162Swpaul * could pose compatibility problems. The local ypbind is 51017162Swpaul * supposed to decide whether or not to trust yp servers 51117162Swpaul * on insecure ports. For now, we trust its judgement. 51217162Swpaul */ 5131919Swollman ysd->dom_server_port = 51412859Swpaul *(u_short *)&ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port; 5151919Swollmangotit: 5161919Swollman ysd->dom_vers = YPVERS; 517114443Snectar strlcpy(ysd->dom_domain, dom, sizeof(ysd->dom_domain)); 5181919Swollman } 5191919Swollman 52015547Swpaul /* Don't rebuild the connection to the server unless we have to. */ 52115547Swpaul if (ysd->dom_client == NULL) { 52215547Swpaul tv.tv_sec = _yplib_timeout/2; 52315547Swpaul tv.tv_usec = 0; 52415547Swpaul ysd->dom_socket = RPC_ANYSOCK; 52534146Swpaul ysd->dom_client = clntudp_bufcreate(&ysd->dom_server_addr, 52634146Swpaul YPPROG, YPVERS, tv, &ysd->dom_socket, 1280, 2304); 52790297Sdes if (ysd->dom_client == NULL) { 52815547Swpaul clnt_pcreateerror("clntudp_create"); 52915547Swpaul ysd->dom_vers = -1; 53015547Swpaul goto again; 53115547Swpaul } 53290297Sdes if (_fcntl(ysd->dom_socket, F_SETFD, 1) == -1) 53315547Swpaul perror("fcntl: F_SETFD"); 53416051Swpaul /* 53516051Swpaul * We want a port number associated with this socket 53616051Swpaul * so that we can check its authenticity later. 53716051Swpaul */ 53816051Swpaul checklen = sizeof(struct sockaddr_in); 53916051Swpaul bzero((char *)&check, checklen); 54071579Sdeischen _bind(ysd->dom_socket, (struct sockaddr *)&check, checklen); 54116051Swpaul check.sin_family = AF_INET; 54271579Sdeischen if (!_getsockname(ysd->dom_socket, 54316051Swpaul (struct sockaddr *)&check, &checklen)) { 54416051Swpaul ysd->dom_local_port = check.sin_port; 54516051Swpaul } else { 54616051Swpaul clnt_destroy(ysd->dom_client); 54716051Swpaul if (new) 54816051Swpaul free(ysd); 54916051Swpaul return(YPERR_YPBIND); 55016051Swpaul } 5511919Swollman } 5521919Swollman 55390297Sdes if (new) { 5541919Swollman ysd->dom_pnext = _ypbindlist; 5551919Swollman _ypbindlist = ysd; 5561919Swollman } 5571919Swollman 558171563Ssimon /* 559171563Ssimon * Set low retry timeout to realistically handle UDP packet 560171563Ssimon * loss for YP packet bursts. 561171563Ssimon */ 562171563Ssimon tv.tv_sec = 1; 563171563Ssimon tv.tv_usec = 0; 564171563Ssimon clnt_control(ysd->dom_client, CLSET_RETRY_TIMEOUT, (char*)&tv); 565171563Ssimon 56690297Sdes if (ypdb != NULL) 5671919Swollman *ypdb = ysd; 56890297Sdes return (0); 5691919Swollman} 5701919Swollman 5711919Swollmanstatic void 57290298Sdes_yp_unbind(struct dom_binding *ypb) 5731919Swollman{ 57419520Swpaul struct sockaddr_in check; 575143415Sstefanf socklen_t checklen = sizeof(struct sockaddr_in); 57619520Swpaul 57719520Swpaul if (ypb->dom_client != NULL) { 57819520Swpaul /* Check the socket -- may have been hosed by the caller. */ 57971579Sdeischen if (_getsockname(ypb->dom_socket, (struct sockaddr *)&check, 58019520Swpaul &checklen) == -1 || check.sin_family != AF_INET || 58119520Swpaul check.sin_port != ypb->dom_local_port) { 58219520Swpaul int save, sock; 58319520Swpaul 58419520Swpaul sock = ypb->dom_socket; 58571579Sdeischen save = _dup(ypb->dom_socket); 58619520Swpaul clnt_destroy(ypb->dom_client); 58771579Sdeischen sock = _dup2(save, sock); 58856698Sjasone _close(save); 58919520Swpaul } else 59019520Swpaul clnt_destroy(ypb->dom_client); 59119520Swpaul } 59219520Swpaul 5931919Swollman ypb->dom_client = NULL; 5941919Swollman ypb->dom_socket = -1; 59515793Swpaul ypb->dom_vers = -1; 59634146Swpaul#ifdef YPMATCHCACHE 59734146Swpaul ypmatch_cache_flush(ypb); 59834146Swpaul#endif 5991919Swollman} 6001919Swollman 601145849Sumestatic int 602145849Sumeyp_bind_locked(char *dom) 603145849Sume{ 604145849Sume return (_yp_dobind(dom, NULL)); 605145849Sume} 606145849Sume 6071919Swollmanint 60890298Sdesyp_bind(char *dom) 6091919Swollman{ 610145849Sume int r; 611145849Sume 612145849Sume YPLOCK(); 613145849Sume r = yp_bind_locked(dom); 614145849Sume YPUNLOCK(); 615145849Sume return (r); 6161919Swollman} 6171919Swollman 618145849Sumestatic void 619145849Sumeyp_unbind_locked(char *dom) 6201919Swollman{ 6211919Swollman struct dom_binding *ypb, *ypbp; 6221919Swollman 6231919Swollman ypbp = NULL; 62490297Sdes for (ypb = _ypbindlist; ypb; ypb = ypb->dom_pnext) { 62590297Sdes if (strcmp(dom, ypb->dom_domain) == 0) { 62615793Swpaul _yp_unbind(ypb); 62790297Sdes if (ypbp) 6281919Swollman ypbp->dom_pnext = ypb->dom_pnext; 6291919Swollman else 6301919Swollman _ypbindlist = ypb->dom_pnext; 6311919Swollman free(ypb); 6321919Swollman return; 6331919Swollman } 6341919Swollman ypbp = ypb; 6351919Swollman } 6361919Swollman return; 6371919Swollman} 6381919Swollman 639145849Sumevoid 640145849Sumeyp_unbind(char *dom) 641145849Sume{ 642145849Sume YPLOCK(); 643145849Sume yp_unbind_locked(dom); 644145849Sume YPUNLOCK(); 645145849Sume} 646145849Sume 6471919Swollmanint 64890298Sdesyp_match(char *indomain, char *inmap, const char *inkey, int inkeylen, 64990298Sdes char **outval, int *outvallen) 6501919Swollman{ 6511919Swollman struct dom_binding *ysd; 6521919Swollman struct ypresp_val yprv; 6531919Swollman struct timeval tv; 6541919Swollman struct ypreq_key yprk; 6551919Swollman int r; 656293896Sglebius int retries = 0; 6571919Swollman *outval = NULL; 6581919Swollman *outvallen = 0; 6591919Swollman 6607337Swpaul /* Sanity check */ 6617290Swpaul 6627337Swpaul if (inkey == NULL || !strlen(inkey) || inkeylen <= 0 || 6637337Swpaul inmap == NULL || !strlen(inmap) || 6647337Swpaul indomain == NULL || !strlen(indomain)) 66590297Sdes return (YPERR_BADARGS); 6667290Swpaul 667145849Sume YPLOCK(); 668145849Sume if (_yp_dobind(indomain, &ysd) != 0) { 669145849Sume YPUNLOCK(); 67034146Swpaul return(YPERR_DOMAIN); 671145849Sume } 67234146Swpaul 67334146Swpaul yprk.domain = indomain; 67434146Swpaul yprk.map = inmap; 67534146Swpaul yprk.key.keydat_val = (char *)inkey; 67634146Swpaul yprk.key.keydat_len = inkeylen; 67734146Swpaul 6781919Swollman#ifdef YPMATCHCACHE 67934146Swpaul if (ypmatch_cache_lookup(ysd, yprk.map, &yprk.key, &yprv.val) == TRUE) { 68034146Swpaul/* 68190297Sdes if (!strcmp(_yp_domain, indomain) && ypmatch_find(inmap, inkey, 68212816Swpaul inkeylen, &yprv.val.valdat_val, &yprv.val.valdat_len)) { 68334146Swpaul*/ 68412816Swpaul *outvallen = yprv.val.valdat_len; 6851919Swollman *outval = (char *)malloc(*outvallen+1); 68612816Swpaul bcopy(yprv.val.valdat_val, *outval, *outvallen); 6871919Swollman (*outval)[*outvallen] = '\0'; 688145849Sume YPUNLOCK(); 68990297Sdes return (0); 6901919Swollman } 6911919Swollman#endif 6921919Swollman 69310522Swpaulagain: 694293896Sglebius if (retries > MAX_RETRIES) { 695293896Sglebius YPUNLOCK(); 696293896Sglebius return (YPERR_RPC); 697293896Sglebius } 698293896Sglebius 699145849Sume if (_yp_dobind(indomain, &ysd) != 0) { 700145849Sume YPUNLOCK(); 70190297Sdes return (YPERR_DOMAIN); 702145849Sume } 70310522Swpaul 7041919Swollman tv.tv_sec = _yplib_timeout; 7051919Swollman tv.tv_usec = 0; 7061919Swollman 7071919Swollman bzero((char *)&yprv, sizeof yprv); 7081919Swollman 7091919Swollman r = clnt_call(ysd->dom_client, YPPROC_MATCH, 71095658Sdes (xdrproc_t)xdr_ypreq_key, &yprk, 71195658Sdes (xdrproc_t)xdr_ypresp_val, &yprv, tv); 71290297Sdes if (r != RPC_SUCCESS) { 7131919Swollman clnt_perror(ysd->dom_client, "yp_match: clnt_call"); 71415793Swpaul _yp_unbind(ysd); 715293896Sglebius retries++; 7161919Swollman goto again; 7171919Swollman } 71815547Swpaul 71990297Sdes if (!(r = ypprot_err(yprv.stat))) { 72012816Swpaul *outvallen = yprv.val.valdat_len; 7211919Swollman *outval = (char *)malloc(*outvallen+1); 72212816Swpaul bcopy(yprv.val.valdat_val, *outval, *outvallen); 7231919Swollman (*outval)[*outvallen] = '\0'; 7241919Swollman#ifdef YPMATCHCACHE 72534146Swpaul ypmatch_cache_insert(ysd, yprk.map, &yprk.key, &yprv.val); 7261919Swollman#endif 72715793Swpaul } 72815547Swpaul 72995658Sdes xdr_free((xdrproc_t)xdr_ypresp_val, &yprv); 730145849Sume YPUNLOCK(); 73190297Sdes return (r); 7321919Swollman} 7331919Swollman 734144678Sumestatic int 735144678Sumeyp_get_default_domain_locked(char **domp) 7361919Swollman{ 7371919Swollman *domp = NULL; 73890297Sdes if (_yp_domain[0] == '\0') 73990297Sdes if (getdomainname(_yp_domain, sizeof _yp_domain)) 74090297Sdes return (YPERR_NODOM); 7411919Swollman *domp = _yp_domain; 74290297Sdes return (0); 7431919Swollman} 7441919Swollman 7451919Swollmanint 746144678Sumeyp_get_default_domain(char **domp) 747144678Sume{ 748144678Sume int r; 749144678Sume 750144678Sume YPLOCK(); 751144678Sume r = yp_get_default_domain_locked(domp); 752144678Sume YPUNLOCK(); 753144678Sume return (r); 754144678Sume} 755144678Sume 756144678Sumeint 75790298Sdesyp_first(char *indomain, char *inmap, char **outkey, int *outkeylen, 75890298Sdes char **outval, int *outvallen) 7591919Swollman{ 7601919Swollman struct ypresp_key_val yprkv; 7611919Swollman struct ypreq_nokey yprnk; 7621919Swollman struct dom_binding *ysd; 7631919Swollman struct timeval tv; 7641919Swollman int r; 765293896Sglebius int retries = 0; 7667337Swpaul /* Sanity check */ 7677337Swpaul 7687337Swpaul if (indomain == NULL || !strlen(indomain) || 7697337Swpaul inmap == NULL || !strlen(inmap)) 77090297Sdes return (YPERR_BADARGS); 7717337Swpaul 7721919Swollman *outkey = *outval = NULL; 7731919Swollman *outkeylen = *outvallen = 0; 7741919Swollman 775145849Sume YPLOCK(); 7761919Swollmanagain: 777293896Sglebius if (retries > MAX_RETRIES) { 778293896Sglebius YPUNLOCK(); 779293896Sglebius return (YPERR_RPC); 780293896Sglebius } 781293896Sglebius 782145849Sume if (_yp_dobind(indomain, &ysd) != 0) { 783145849Sume YPUNLOCK(); 78490297Sdes return (YPERR_DOMAIN); 785145849Sume } 7861919Swollman 7871919Swollman tv.tv_sec = _yplib_timeout; 7881919Swollman tv.tv_usec = 0; 7891919Swollman 7901919Swollman yprnk.domain = indomain; 7911919Swollman yprnk.map = inmap; 7921919Swollman bzero((char *)&yprkv, sizeof yprkv); 7931919Swollman 7941919Swollman r = clnt_call(ysd->dom_client, YPPROC_FIRST, 79595658Sdes (xdrproc_t)xdr_ypreq_nokey, &yprnk, 79695658Sdes (xdrproc_t)xdr_ypresp_key_val, &yprkv, tv); 79790297Sdes if (r != RPC_SUCCESS) { 7981919Swollman clnt_perror(ysd->dom_client, "yp_first: clnt_call"); 79915793Swpaul _yp_unbind(ysd); 800293896Sglebius retries++; 8011919Swollman goto again; 8021919Swollman } 80390297Sdes if (!(r = ypprot_err(yprkv.stat))) { 80412816Swpaul *outkeylen = yprkv.key.keydat_len; 8051919Swollman *outkey = (char *)malloc(*outkeylen+1); 80612816Swpaul bcopy(yprkv.key.keydat_val, *outkey, *outkeylen); 8071919Swollman (*outkey)[*outkeylen] = '\0'; 80812816Swpaul *outvallen = yprkv.val.valdat_len; 8091919Swollman *outval = (char *)malloc(*outvallen+1); 81012816Swpaul bcopy(yprkv.val.valdat_val, *outval, *outvallen); 8111919Swollman (*outval)[*outvallen] = '\0'; 81215793Swpaul } 81315547Swpaul 81495658Sdes xdr_free((xdrproc_t)xdr_ypresp_key_val, &yprkv); 815145849Sume YPUNLOCK(); 81690297Sdes return (r); 8171919Swollman} 8181919Swollman 8191919Swollmanint 82090298Sdesyp_next(char *indomain, char *inmap, char *inkey, int inkeylen, 82190298Sdes char **outkey, int *outkeylen, char **outval, int *outvallen) 8221919Swollman{ 8231919Swollman struct ypresp_key_val yprkv; 8241919Swollman struct ypreq_key yprk; 8251919Swollman struct dom_binding *ysd; 8261919Swollman struct timeval tv; 8271919Swollman int r; 828293896Sglebius int retries = 0; 8297337Swpaul /* Sanity check */ 8307337Swpaul 8317337Swpaul if (inkey == NULL || !strlen(inkey) || inkeylen <= 0 || 8327337Swpaul inmap == NULL || !strlen(inmap) || 8337337Swpaul indomain == NULL || !strlen(indomain)) 83490297Sdes return (YPERR_BADARGS); 8357337Swpaul 8361919Swollman *outkey = *outval = NULL; 8371919Swollman *outkeylen = *outvallen = 0; 8381919Swollman 839145849Sume YPLOCK(); 8401919Swollmanagain: 841293896Sglebius if (retries > MAX_RETRIES) { 842293896Sglebius YPUNLOCK(); 843293896Sglebius return (YPERR_RPC); 844293896Sglebius } 845293896Sglebius 846145849Sume if (_yp_dobind(indomain, &ysd) != 0) { 847145849Sume YPUNLOCK(); 84890297Sdes return (YPERR_DOMAIN); 849145849Sume } 8501919Swollman 8511919Swollman tv.tv_sec = _yplib_timeout; 8521919Swollman tv.tv_usec = 0; 8531919Swollman 8541919Swollman yprk.domain = indomain; 8551919Swollman yprk.map = inmap; 85612816Swpaul yprk.key.keydat_val = inkey; 85712816Swpaul yprk.key.keydat_len = inkeylen; 8581919Swollman bzero((char *)&yprkv, sizeof yprkv); 8591919Swollman 8601919Swollman r = clnt_call(ysd->dom_client, YPPROC_NEXT, 86195658Sdes (xdrproc_t)xdr_ypreq_key, &yprk, 86295658Sdes (xdrproc_t)xdr_ypresp_key_val, &yprkv, tv); 86390297Sdes if (r != RPC_SUCCESS) { 8641919Swollman clnt_perror(ysd->dom_client, "yp_next: clnt_call"); 86515793Swpaul _yp_unbind(ysd); 866293896Sglebius retries++; 8671919Swollman goto again; 8681919Swollman } 86990297Sdes if (!(r = ypprot_err(yprkv.stat))) { 87012816Swpaul *outkeylen = yprkv.key.keydat_len; 8711919Swollman *outkey = (char *)malloc(*outkeylen+1); 87212816Swpaul bcopy(yprkv.key.keydat_val, *outkey, *outkeylen); 8731919Swollman (*outkey)[*outkeylen] = '\0'; 87412816Swpaul *outvallen = yprkv.val.valdat_len; 8751919Swollman *outval = (char *)malloc(*outvallen+1); 87612816Swpaul bcopy(yprkv.val.valdat_val, *outval, *outvallen); 8771919Swollman (*outval)[*outvallen] = '\0'; 87815793Swpaul } 87915547Swpaul 88095658Sdes xdr_free((xdrproc_t)xdr_ypresp_key_val, &yprkv); 881145849Sume YPUNLOCK(); 88290297Sdes return (r); 8831919Swollman} 8841919Swollman 8851919Swollmanint 88690298Sdesyp_all(char *indomain, char *inmap, struct ypall_callback *incallback) 8871919Swollman{ 8881919Swollman struct ypreq_nokey yprnk; 8891919Swollman struct dom_binding *ysd; 8901919Swollman struct timeval tv; 8911919Swollman struct sockaddr_in clnt_sin; 8921919Swollman CLIENT *clnt; 89314719Swpaul u_long status, savstat; 8941919Swollman int clnt_sock; 895293896Sglebius int retries = 0; 8967337Swpaul /* Sanity check */ 8977337Swpaul 8987337Swpaul if (indomain == NULL || !strlen(indomain) || 8997337Swpaul inmap == NULL || !strlen(inmap)) 90090297Sdes return (YPERR_BADARGS); 9017337Swpaul 902145849Sume YPLOCK(); 90315793Swpaulagain: 904293896Sglebius if (retries > MAX_RETRIES) { 905293896Sglebius YPUNLOCK(); 906293896Sglebius return (YPERR_RPC); 907293896Sglebius } 90815793Swpaul 909145849Sume if (_yp_dobind(indomain, &ysd) != 0) { 910145849Sume YPUNLOCK(); 91190297Sdes return (YPERR_DOMAIN); 912145849Sume } 9131919Swollman 9141919Swollman tv.tv_sec = _yplib_timeout; 9151919Swollman tv.tv_usec = 0; 91615793Swpaul 91715793Swpaul /* YPPROC_ALL manufactures its own channel to ypserv using TCP */ 91815793Swpaul 9191919Swollman clnt_sock = RPC_ANYSOCK; 9201919Swollman clnt_sin = ysd->dom_server_addr; 9211919Swollman clnt_sin.sin_port = 0; 9221919Swollman clnt = clnttcp_create(&clnt_sin, YPPROG, YPVERS, &clnt_sock, 0, 0); 92390297Sdes if (clnt == NULL) { 924145849Sume YPUNLOCK(); 9251919Swollman printf("clnttcp_create failed\n"); 92690297Sdes return (YPERR_PMAP); 9271919Swollman } 9281919Swollman 9291919Swollman yprnk.domain = indomain; 9301919Swollman yprnk.map = inmap; 9311919Swollman ypresp_allfn = incallback->foreach; 9321919Swollman ypresp_data = (void *)incallback->data; 9331919Swollman 93415793Swpaul if (clnt_call(clnt, YPPROC_ALL, 93595658Sdes (xdrproc_t)xdr_ypreq_nokey, &yprnk, 93695658Sdes (xdrproc_t)xdr_ypresp_all_seq, &status, tv) != RPC_SUCCESS) { 937293896Sglebius clnt_perror(clnt, "yp_all: clnt_call"); 93815793Swpaul clnt_destroy(clnt); 93915793Swpaul _yp_unbind(ysd); 940293896Sglebius retries++; 94115793Swpaul goto again; 94215793Swpaul } 94315793Swpaul 9441919Swollman clnt_destroy(clnt); 94514719Swpaul savstat = status; 94695658Sdes xdr_free((xdrproc_t)xdr_ypresp_all_seq, &status); /* not really needed... */ 947145849Sume YPUNLOCK(); 94890297Sdes if (savstat != YP_NOMORE) 94990297Sdes return (ypprot_err(savstat)); 95090297Sdes return (0); 9511919Swollman} 9521919Swollman 9531919Swollmanint 95490298Sdesyp_order(char *indomain, char *inmap, int *outorder) 9551919Swollman{ 9561919Swollman struct dom_binding *ysd; 9571919Swollman struct ypresp_order ypro; 9581919Swollman struct ypreq_nokey yprnk; 9591919Swollman struct timeval tv; 9601919Swollman int r; 9611919Swollman 9627337Swpaul /* Sanity check */ 9637337Swpaul 9647337Swpaul if (indomain == NULL || !strlen(indomain) || 9657337Swpaul inmap == NULL || !strlen(inmap)) 96690297Sdes return (YPERR_BADARGS); 9677337Swpaul 968145849Sume YPLOCK(); 9691919Swollmanagain: 970145849Sume if (_yp_dobind(indomain, &ysd) != 0) { 971145849Sume YPUNLOCK(); 97290297Sdes return (YPERR_DOMAIN); 973145849Sume } 9741919Swollman 9751919Swollman tv.tv_sec = _yplib_timeout; 9761919Swollman tv.tv_usec = 0; 9771919Swollman 9781919Swollman yprnk.domain = indomain; 9791919Swollman yprnk.map = inmap; 9801919Swollman 9811919Swollman bzero((char *)(char *)&ypro, sizeof ypro); 9821919Swollman 9831919Swollman r = clnt_call(ysd->dom_client, YPPROC_ORDER, 98495658Sdes (xdrproc_t)xdr_ypreq_nokey, &yprnk, 98595658Sdes (xdrproc_t)xdr_ypresp_order, &ypro, tv); 98619520Swpaul 98719520Swpaul /* 98819520Swpaul * NIS+ in YP compat mode doesn't support the YPPROC_ORDER 98919520Swpaul * procedure. 99019520Swpaul */ 99119520Swpaul if (r == RPC_PROCUNAVAIL) { 992145849Sume YPUNLOCK(); 99319520Swpaul return(YPERR_YPERR); 99419520Swpaul } 99590297Sdes 99690297Sdes if (r != RPC_SUCCESS) { 9971919Swollman clnt_perror(ysd->dom_client, "yp_order: clnt_call"); 99815793Swpaul _yp_unbind(ysd); 9991919Swollman goto again; 10001919Swollman } 10011919Swollman 100290297Sdes if (!(r = ypprot_err(ypro.stat))) { 100315547Swpaul *outorder = ypro.ordernum; 100415793Swpaul } 100515547Swpaul 100695658Sdes xdr_free((xdrproc_t)xdr_ypresp_order, &ypro); 1007145849Sume YPUNLOCK(); 100815793Swpaul return (r); 10091919Swollman} 10101919Swollman 10111919Swollmanint 101290298Sdesyp_master(char *indomain, char *inmap, char **outname) 10131919Swollman{ 10141919Swollman struct dom_binding *ysd; 10151919Swollman struct ypresp_master yprm; 10161919Swollman struct ypreq_nokey yprnk; 10171919Swollman struct timeval tv; 10181919Swollman int r; 10191919Swollman 10207337Swpaul /* Sanity check */ 10217337Swpaul 10227337Swpaul if (indomain == NULL || !strlen(indomain) || 10237337Swpaul inmap == NULL || !strlen(inmap)) 102490297Sdes return (YPERR_BADARGS); 1025145849Sume YPLOCK(); 10261919Swollmanagain: 1027145849Sume if (_yp_dobind(indomain, &ysd) != 0) { 1028145849Sume YPUNLOCK(); 102990297Sdes return (YPERR_DOMAIN); 1030145849Sume } 10311919Swollman 10321919Swollman tv.tv_sec = _yplib_timeout; 10331919Swollman tv.tv_usec = 0; 10341919Swollman 10351919Swollman yprnk.domain = indomain; 10361919Swollman yprnk.map = inmap; 10371919Swollman 10381919Swollman bzero((char *)&yprm, sizeof yprm); 10391919Swollman 10401919Swollman r = clnt_call(ysd->dom_client, YPPROC_MASTER, 104195658Sdes (xdrproc_t)xdr_ypreq_nokey, &yprnk, 104295658Sdes (xdrproc_t)xdr_ypresp_master, &yprm, tv); 104390297Sdes if (r != RPC_SUCCESS) { 10441919Swollman clnt_perror(ysd->dom_client, "yp_master: clnt_call"); 104515793Swpaul _yp_unbind(ysd); 10461919Swollman goto again; 10471919Swollman } 104815793Swpaul 104990297Sdes if (!(r = ypprot_err(yprm.stat))) { 105012816Swpaul *outname = (char *)strdup(yprm.peer); 105115793Swpaul } 105215547Swpaul 105395658Sdes xdr_free((xdrproc_t)xdr_ypresp_master, &yprm); 1054145849Sume YPUNLOCK(); 105515793Swpaul return (r); 10561919Swollman} 105790298Sdes 10587722Swpaulint 105990298Sdesyp_maplist(char *indomain, struct ypmaplist **outmaplist) 10601919Swollman{ 10611919Swollman struct dom_binding *ysd; 10621919Swollman struct ypresp_maplist ypml; 10631919Swollman struct timeval tv; 10641919Swollman int r; 10651919Swollman 10667337Swpaul /* Sanity check */ 10677337Swpaul 10687337Swpaul if (indomain == NULL || !strlen(indomain)) 106990297Sdes return (YPERR_BADARGS); 10707337Swpaul 1071145849Sume YPLOCK(); 10721919Swollmanagain: 1073145849Sume if (_yp_dobind(indomain, &ysd) != 0) { 1074145849Sume YPUNLOCK(); 107590297Sdes return (YPERR_DOMAIN); 1076145849Sume } 10771919Swollman 10781919Swollman tv.tv_sec = _yplib_timeout; 10791919Swollman tv.tv_usec = 0; 10801919Swollman 10811919Swollman bzero((char *)&ypml, sizeof ypml); 10821919Swollman 10831919Swollman r = clnt_call(ysd->dom_client, YPPROC_MAPLIST, 108495658Sdes (xdrproc_t)xdr_domainname, &indomain, 108595658Sdes (xdrproc_t)xdr_ypresp_maplist, &ypml,tv); 10861919Swollman if (r != RPC_SUCCESS) { 10871919Swollman clnt_perror(ysd->dom_client, "yp_maplist: clnt_call"); 108815793Swpaul _yp_unbind(ysd); 10891919Swollman goto again; 10901919Swollman } 109190297Sdes if (!(r = ypprot_err(ypml.stat))) { 109215547Swpaul *outmaplist = ypml.maps; 109315793Swpaul } 109415793Swpaul 109595658Sdes /* NO: xdr_free((xdrproc_t)xdr_ypresp_maplist, &ypml);*/ 1096145849Sume YPUNLOCK(); 109715793Swpaul return (r); 10981919Swollman} 10991919Swollman 110095658Sdesconst char * 110190298Sdesyperr_string(int incode) 11021919Swollman{ 11031919Swollman static char err[80]; 11041919Swollman 110590297Sdes switch (incode) { 11061919Swollman case 0: 110790297Sdes return ("Success"); 11081919Swollman case YPERR_BADARGS: 110990297Sdes return ("Request arguments bad"); 11101919Swollman case YPERR_RPC: 111190297Sdes return ("RPC failure"); 11121919Swollman case YPERR_DOMAIN: 111390297Sdes return ("Can't bind to server which serves this domain"); 11141919Swollman case YPERR_MAP: 111590297Sdes return ("No such map in server's domain"); 11161919Swollman case YPERR_KEY: 111790297Sdes return ("No such key in map"); 11181919Swollman case YPERR_YPERR: 111990297Sdes return ("YP server error"); 11201919Swollman case YPERR_RESRC: 112190297Sdes return ("Local resource allocation failure"); 11221919Swollman case YPERR_NOMORE: 112390297Sdes return ("No more records in map database"); 11241919Swollman case YPERR_PMAP: 112590297Sdes return ("Can't communicate with portmapper"); 11261919Swollman case YPERR_YPBIND: 112790297Sdes return ("Can't communicate with ypbind"); 11281919Swollman case YPERR_YPSERV: 112990297Sdes return ("Can't communicate with ypserv"); 11301919Swollman case YPERR_NODOM: 113190297Sdes return ("Local domain name not set"); 11321919Swollman case YPERR_BADDB: 113390297Sdes return ("Server data base is bad"); 11341919Swollman case YPERR_VERS: 113590297Sdes return ("YP server version mismatch - server can't supply service."); 11361919Swollman case YPERR_ACCESS: 113790297Sdes return ("Access violation"); 11381919Swollman case YPERR_BUSY: 113990297Sdes return ("Database is busy"); 11401919Swollman } 11411919Swollman sprintf(err, "YP unknown error %d\n", incode); 114290297Sdes return (err); 11431919Swollman} 11441919Swollman 11451919Swollmanint 114690298Sdesypprot_err(unsigned int incode) 11471919Swollman{ 114890297Sdes switch (incode) { 11491919Swollman case YP_TRUE: 115090297Sdes return (0); 11511919Swollman case YP_FALSE: 115290297Sdes return (YPERR_YPBIND); 11531919Swollman case YP_NOMORE: 115490297Sdes return (YPERR_NOMORE); 11551919Swollman case YP_NOMAP: 115690297Sdes return (YPERR_MAP); 11571919Swollman case YP_NODOM: 115890297Sdes return (YPERR_DOMAIN); 11591919Swollman case YP_NOKEY: 116090297Sdes return (YPERR_KEY); 11611919Swollman case YP_BADOP: 116290297Sdes return (YPERR_YPERR); 11631919Swollman case YP_BADDB: 116490297Sdes return (YPERR_BADDB); 11651919Swollman case YP_YPERR: 116690297Sdes return (YPERR_YPERR); 11671919Swollman case YP_BADARGS: 116890297Sdes return (YPERR_BADARGS); 11691919Swollman case YP_VERS: 117090297Sdes return (YPERR_VERS); 11711919Swollman } 117290297Sdes return (YPERR_YPERR); 11731919Swollman} 11741919Swollman 11751919Swollmanint 117690298Sdes_yp_check(char **dom) 11771919Swollman{ 11781919Swollman char *unused; 11791919Swollman 1180144678Sume YPLOCK(); 118190297Sdes if (_yp_domain[0]=='\0') 1182144678Sume if (yp_get_default_domain_locked(&unused)) { 1183144678Sume YPUNLOCK(); 118490297Sdes return (0); 1185144678Sume } 11861919Swollman 118790297Sdes if (dom) 11881919Swollman *dom = _yp_domain; 11891919Swollman 1190145849Sume if (yp_bind_locked(_yp_domain) == 0) { 1191145849Sume yp_unbind_locked(_yp_domain); 1192144678Sume YPUNLOCK(); 119390297Sdes return (1); 119412095Swpaul } 1195144678Sume YPUNLOCK(); 119690297Sdes return (0); 11971919Swollman} 1198