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); 334228828Sghelmer if (ysd == NULL) 335228828Sghelmer return (YPERR_RESRC); 3361919Swollman bzero((char *)ysd, sizeof *ysd); 3371919Swollman ysd->dom_socket = -1; 3381919Swollman ysd->dom_vers = 0; 3391919Swollman new = 1; 34016051Swpaul } else { 34116051Swpaul /* Check the socket -- may have been hosed by the caller. */ 34271579Sdeischen if (_getsockname(ysd->dom_socket, (struct sockaddr *)&check, 34316051Swpaul &checklen) == -1 || check.sin_family != AF_INET || 34416051Swpaul check.sin_port != ysd->dom_local_port) { 34516051Swpaul /* Socket became bogus somehow... need to rebind. */ 34616051Swpaul int save, sock; 34716051Swpaul 34816051Swpaul sock = ysd->dom_socket; 34971579Sdeischen save = _dup(ysd->dom_socket); 35019520Swpaul if (ysd->dom_client != NULL) 35119520Swpaul clnt_destroy(ysd->dom_client); 35216051Swpaul ysd->dom_vers = 0; 35316051Swpaul ysd->dom_client = NULL; 35471579Sdeischen sock = _dup2(save, sock); 35556698Sjasone _close(save); 35616051Swpaul } 3571919Swollman } 35812095Swpaul 3591919Swollmanagain: 3608091Swpaul retries++; 3618091Swpaul if (retries > MAX_RETRIES) { 3628091Swpaul if (new) 3638091Swpaul free(ysd); 3648091Swpaul return(YPERR_YPBIND); 3658091Swpaul } 3661919Swollman#ifdef BINDINGDIR 36790297Sdes if (ysd->dom_vers == 0) { 36815547Swpaul /* 36915547Swpaul * We're trying to make a new binding: zorch the 37015547Swpaul * existing handle now (if any). 37115547Swpaul */ 37290297Sdes if (ysd->dom_client != NULL) { 37315547Swpaul clnt_destroy(ysd->dom_client); 37415547Swpaul ysd->dom_client = NULL; 37516051Swpaul ysd->dom_socket = -1; 37615547Swpaul } 37754167Skris snprintf(path, sizeof(path), "%s/%s.%d", BINDINGDIR, dom, 2); 378241046Sjilles if ((fd = _open(path, O_RDONLY | O_CLOEXEC)) == -1) { 3791919Swollman /* no binding file, YP is dead. */ 3808091Swpaul /* Try to bring it back to life. */ 38156698Sjasone _close(fd); 3828091Swpaul goto skipit; 3831919Swollman } 38490297Sdes if (_flock(fd, LOCK_EX|LOCK_NB) == -1 && errno == EWOULDBLOCK) { 3851919Swollman struct iovec iov[2]; 38612859Swpaul struct ypbind_resp ybr; 3871919Swollman u_short ypb_port; 3881919Swollman 3891919Swollman iov[0].iov_base = (caddr_t)&ypb_port; 3901919Swollman iov[0].iov_len = sizeof ypb_port; 3911919Swollman iov[1].iov_base = (caddr_t)&ybr; 3921919Swollman iov[1].iov_len = sizeof ybr; 3931919Swollman 39471579Sdeischen r = _readv(fd, iov, 2); 39590297Sdes if (r != iov[0].iov_len + iov[1].iov_len) { 39656698Sjasone _close(fd); 3971919Swollman ysd->dom_vers = -1; 3981919Swollman goto again; 3991919Swollman } 4001919Swollman 4011919Swollman bzero(&ysd->dom_server_addr, sizeof ysd->dom_server_addr); 4021919Swollman ysd->dom_server_addr.sin_family = AF_INET; 4031919Swollman ysd->dom_server_addr.sin_len = sizeof(struct sockaddr_in); 40489084Sjhb bcopy(&ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr, 40589084Sjhb &ysd->dom_server_addr.sin_addr.s_addr, 40689084Sjhb sizeof(ysd->dom_server_addr.sin_addr.s_addr)); 40789084Sjhb bcopy(&ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port, 40889084Sjhb &ysd->dom_server_addr.sin_port, 40989084Sjhb sizeof(ysd->dom_server_addr.sin_port)); 4101919Swollman 4111919Swollman ysd->dom_server_port = ysd->dom_server_addr.sin_port; 41256698Sjasone _close(fd); 4131919Swollman goto gotit; 4141919Swollman } else { 4151919Swollman /* no lock on binding file, YP is dead. */ 4168091Swpaul /* Try to bring it back to life. */ 41756698Sjasone _close(fd); 4188091Swpaul goto skipit; 4191919Swollman } 4201919Swollman } 4217722Swpaulskipit: 4221919Swollman#endif 42390297Sdes if (ysd->dom_vers == -1 || ysd->dom_vers == 0) { 42415547Swpaul /* 42515547Swpaul * We're trying to make a new binding: zorch the 42615547Swpaul * existing handle now (if any). 42715547Swpaul */ 42890297Sdes if (ysd->dom_client != NULL) { 42915547Swpaul clnt_destroy(ysd->dom_client); 43015547Swpaul ysd->dom_client = NULL; 43116051Swpaul ysd->dom_socket = -1; 43215547Swpaul } 4331919Swollman bzero((char *)&clnt_sin, sizeof clnt_sin); 4341919Swollman clnt_sin.sin_family = AF_INET; 4351919Swollman clnt_sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 4368870Srgrimes 4371919Swollman clnt_sock = RPC_ANYSOCK; 4381919Swollman client = clnttcp_create(&clnt_sin, YPBINDPROG, YPBINDVERS, &clnt_sock, 4391919Swollman 0, 0); 44090297Sdes if (client == NULL) { 44114776Swpaul /* 44214776Swpaul * These conditions indicate ypbind just isn't 44314776Swpaul * alive -- we probably don't want to shoot our 44415547Swpaul * mouth off in this case; instead generate error 44514776Swpaul * messages only for really exotic problems. 44614776Swpaul */ 44714776Swpaul if (rpc_createerr.cf_stat != RPC_PROGNOTREGISTERED && 44814776Swpaul (rpc_createerr.cf_stat != RPC_SYSTEMERROR && 44915547Swpaul rpc_createerr.cf_error.re_errno == ECONNREFUSED)) 45015547Swpaul clnt_pcreateerror("clnttcp_create"); 45190297Sdes if (new) 4521919Swollman free(ysd); 4538091Swpaul return (YPERR_YPBIND); 4541919Swollman } 4551919Swollman 45617162Swpaul /* 45717162Swpaul * Check the port number -- should be < IPPORT_RESERVED. 45817162Swpaul * If not, it's possible someone has registered a bogus 45917162Swpaul * ypbind with the portmapper and is trying to trick us. 46017162Swpaul */ 46117162Swpaul if (ntohs(clnt_sin.sin_port) >= IPPORT_RESERVED) { 46219520Swpaul if (client != NULL) 46319520Swpaul clnt_destroy(client); 46417162Swpaul if (new) 46517162Swpaul free(ysd); 46617162Swpaul return(YPERR_YPBIND); 46717162Swpaul } 4688091Swpaul tv.tv_sec = _yplib_timeout/2; 4691919Swollman tv.tv_usec = 0; 4701919Swollman r = clnt_call(client, YPBINDPROC_DOMAIN, 47195658Sdes (xdrproc_t)xdr_domainname, &dom, 47295658Sdes (xdrproc_t)xdr_ypbind_resp, &ypbr, tv); 47390297Sdes if (r != RPC_SUCCESS) { 47414776Swpaul clnt_destroy(client); 47514776Swpaul ysd->dom_vers = -1; 47616051Swpaul if (r == RPC_PROGUNAVAIL || r == RPC_PROCUNAVAIL) { 47716051Swpaul if (new) 47816051Swpaul free(ysd); 47914776Swpaul return(YPERR_YPBIND); 48016051Swpaul } 4811919Swollman fprintf(stderr, 4827721Swpaul "YP: server for domain %s not responding, retrying\n", dom); 4831919Swollman goto again; 4847982Swpaul } else { 4857982Swpaul if (ypbr.ypbind_status != YPBIND_SUCC_VAL) { 48656698Sjasone struct timespec time_to_sleep, time_remaining; 48790297Sdes 4888091Swpaul clnt_destroy(client); 4898091Swpaul ysd->dom_vers = -1; 49056698Sjasone 49156698Sjasone time_to_sleep.tv_sec = _yplib_timeout/2; 49256698Sjasone time_to_sleep.tv_nsec = 0; 49356698Sjasone _nanosleep(&time_to_sleep, 49456698Sjasone &time_remaining); 4958091Swpaul goto again; 4967982Swpaul } 4971919Swollman } 4981919Swollman clnt_destroy(client); 4991919Swollman 5001919Swollman bzero((char *)&ysd->dom_server_addr, sizeof ysd->dom_server_addr); 5011919Swollman ysd->dom_server_addr.sin_family = AF_INET; 50289084Sjhb bcopy(&ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port, 50389084Sjhb &ysd->dom_server_addr.sin_port, 50489084Sjhb sizeof(ysd->dom_server_addr.sin_port)); 50589084Sjhb bcopy(&ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr, 50689084Sjhb &ysd->dom_server_addr.sin_addr.s_addr, 50789084Sjhb sizeof(ysd->dom_server_addr.sin_addr.s_addr)); 50817162Swpaul 50917162Swpaul /* 51017162Swpaul * We could do a reserved port check here too, but this 51117162Swpaul * could pose compatibility problems. The local ypbind is 51217162Swpaul * supposed to decide whether or not to trust yp servers 51317162Swpaul * on insecure ports. For now, we trust its judgement. 51417162Swpaul */ 5151919Swollman ysd->dom_server_port = 51612859Swpaul *(u_short *)&ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port; 5171919Swollmangotit: 5181919Swollman ysd->dom_vers = YPVERS; 519114443Snectar strlcpy(ysd->dom_domain, dom, sizeof(ysd->dom_domain)); 5201919Swollman } 5211919Swollman 52215547Swpaul /* Don't rebuild the connection to the server unless we have to. */ 52315547Swpaul if (ysd->dom_client == NULL) { 52415547Swpaul tv.tv_sec = _yplib_timeout/2; 52515547Swpaul tv.tv_usec = 0; 52615547Swpaul ysd->dom_socket = RPC_ANYSOCK; 52734146Swpaul ysd->dom_client = clntudp_bufcreate(&ysd->dom_server_addr, 52834146Swpaul YPPROG, YPVERS, tv, &ysd->dom_socket, 1280, 2304); 52990297Sdes if (ysd->dom_client == NULL) { 53015547Swpaul clnt_pcreateerror("clntudp_create"); 53115547Swpaul ysd->dom_vers = -1; 53215547Swpaul goto again; 53315547Swpaul } 53490297Sdes if (_fcntl(ysd->dom_socket, F_SETFD, 1) == -1) 53515547Swpaul perror("fcntl: F_SETFD"); 53616051Swpaul /* 53716051Swpaul * We want a port number associated with this socket 53816051Swpaul * so that we can check its authenticity later. 53916051Swpaul */ 54016051Swpaul checklen = sizeof(struct sockaddr_in); 54116051Swpaul bzero((char *)&check, checklen); 54271579Sdeischen _bind(ysd->dom_socket, (struct sockaddr *)&check, checklen); 54316051Swpaul check.sin_family = AF_INET; 54471579Sdeischen if (!_getsockname(ysd->dom_socket, 54516051Swpaul (struct sockaddr *)&check, &checklen)) { 54616051Swpaul ysd->dom_local_port = check.sin_port; 54716051Swpaul } else { 54816051Swpaul clnt_destroy(ysd->dom_client); 54916051Swpaul if (new) 55016051Swpaul free(ysd); 55116051Swpaul return(YPERR_YPBIND); 55216051Swpaul } 5531919Swollman } 5541919Swollman 55590297Sdes if (new) { 5561919Swollman ysd->dom_pnext = _ypbindlist; 5571919Swollman _ypbindlist = ysd; 5581919Swollman } 5591919Swollman 560171563Ssimon /* 561171563Ssimon * Set low retry timeout to realistically handle UDP packet 562171563Ssimon * loss for YP packet bursts. 563171563Ssimon */ 564171563Ssimon tv.tv_sec = 1; 565171563Ssimon tv.tv_usec = 0; 566171563Ssimon clnt_control(ysd->dom_client, CLSET_RETRY_TIMEOUT, (char*)&tv); 567171563Ssimon 56890297Sdes if (ypdb != NULL) 5691919Swollman *ypdb = ysd; 57090297Sdes return (0); 5711919Swollman} 5721919Swollman 5731919Swollmanstatic void 57490298Sdes_yp_unbind(struct dom_binding *ypb) 5751919Swollman{ 57619520Swpaul struct sockaddr_in check; 577143415Sstefanf socklen_t checklen = sizeof(struct sockaddr_in); 57819520Swpaul 57919520Swpaul if (ypb->dom_client != NULL) { 58019520Swpaul /* Check the socket -- may have been hosed by the caller. */ 58171579Sdeischen if (_getsockname(ypb->dom_socket, (struct sockaddr *)&check, 58219520Swpaul &checklen) == -1 || check.sin_family != AF_INET || 58319520Swpaul check.sin_port != ypb->dom_local_port) { 58419520Swpaul int save, sock; 58519520Swpaul 58619520Swpaul sock = ypb->dom_socket; 58771579Sdeischen save = _dup(ypb->dom_socket); 58819520Swpaul clnt_destroy(ypb->dom_client); 58971579Sdeischen sock = _dup2(save, sock); 59056698Sjasone _close(save); 59119520Swpaul } else 59219520Swpaul clnt_destroy(ypb->dom_client); 59319520Swpaul } 59419520Swpaul 5951919Swollman ypb->dom_client = NULL; 5961919Swollman ypb->dom_socket = -1; 59715793Swpaul ypb->dom_vers = -1; 59834146Swpaul#ifdef YPMATCHCACHE 59934146Swpaul ypmatch_cache_flush(ypb); 60034146Swpaul#endif 6011919Swollman} 6021919Swollman 603145849Sumestatic int 604145849Sumeyp_bind_locked(char *dom) 605145849Sume{ 606145849Sume return (_yp_dobind(dom, NULL)); 607145849Sume} 608145849Sume 6091919Swollmanint 61090298Sdesyp_bind(char *dom) 6111919Swollman{ 612145849Sume int r; 613145849Sume 614145849Sume YPLOCK(); 615145849Sume r = yp_bind_locked(dom); 616145849Sume YPUNLOCK(); 617145849Sume return (r); 6181919Swollman} 6191919Swollman 620145849Sumestatic void 621145849Sumeyp_unbind_locked(char *dom) 6221919Swollman{ 6231919Swollman struct dom_binding *ypb, *ypbp; 6241919Swollman 6251919Swollman ypbp = NULL; 62690297Sdes for (ypb = _ypbindlist; ypb; ypb = ypb->dom_pnext) { 62790297Sdes if (strcmp(dom, ypb->dom_domain) == 0) { 62815793Swpaul _yp_unbind(ypb); 62990297Sdes if (ypbp) 6301919Swollman ypbp->dom_pnext = ypb->dom_pnext; 6311919Swollman else 6321919Swollman _ypbindlist = ypb->dom_pnext; 6331919Swollman free(ypb); 6341919Swollman return; 6351919Swollman } 6361919Swollman ypbp = ypb; 6371919Swollman } 6381919Swollman return; 6391919Swollman} 6401919Swollman 641145849Sumevoid 642145849Sumeyp_unbind(char *dom) 643145849Sume{ 644145849Sume YPLOCK(); 645145849Sume yp_unbind_locked(dom); 646145849Sume YPUNLOCK(); 647145849Sume} 648145849Sume 6491919Swollmanint 65090298Sdesyp_match(char *indomain, char *inmap, const char *inkey, int inkeylen, 65190298Sdes char **outval, int *outvallen) 6521919Swollman{ 6531919Swollman struct dom_binding *ysd; 6541919Swollman struct ypresp_val yprv; 6551919Swollman struct timeval tv; 6561919Swollman struct ypreq_key yprk; 6571919Swollman int r; 6581919Swollman 6591919Swollman *outval = NULL; 6601919Swollman *outvallen = 0; 6611919Swollman 6627337Swpaul /* Sanity check */ 6637290Swpaul 6647337Swpaul if (inkey == NULL || !strlen(inkey) || inkeylen <= 0 || 6657337Swpaul inmap == NULL || !strlen(inmap) || 6667337Swpaul indomain == NULL || !strlen(indomain)) 66790297Sdes return (YPERR_BADARGS); 6687290Swpaul 669145849Sume YPLOCK(); 670145849Sume if (_yp_dobind(indomain, &ysd) != 0) { 671145849Sume YPUNLOCK(); 67234146Swpaul return(YPERR_DOMAIN); 673145849Sume } 67434146Swpaul 67534146Swpaul yprk.domain = indomain; 67634146Swpaul yprk.map = inmap; 67734146Swpaul yprk.key.keydat_val = (char *)inkey; 67834146Swpaul yprk.key.keydat_len = inkeylen; 67934146Swpaul 6801919Swollman#ifdef YPMATCHCACHE 68134146Swpaul if (ypmatch_cache_lookup(ysd, yprk.map, &yprk.key, &yprv.val) == TRUE) { 68234146Swpaul/* 68390297Sdes if (!strcmp(_yp_domain, indomain) && ypmatch_find(inmap, inkey, 68412816Swpaul inkeylen, &yprv.val.valdat_val, &yprv.val.valdat_len)) { 68534146Swpaul*/ 68612816Swpaul *outvallen = yprv.val.valdat_len; 6871919Swollman *outval = (char *)malloc(*outvallen+1); 688228828Sghelmer if (*outval == NULL) { 689228828Sghelmer _yp_unbind(ysd); 690228828Sghelmer *outvallen = 0; 691228828Sghelmer YPUNLOCK(); 692228828Sghelmer return (YPERR_RESRC); 693228828Sghelmer } 69412816Swpaul bcopy(yprv.val.valdat_val, *outval, *outvallen); 6951919Swollman (*outval)[*outvallen] = '\0'; 696145849Sume YPUNLOCK(); 69790297Sdes return (0); 6981919Swollman } 699228828Sghelmer _yp_unbind(ysd); 7001919Swollman#endif 7011919Swollman 70210522Swpaulagain: 703145849Sume if (_yp_dobind(indomain, &ysd) != 0) { 704145849Sume YPUNLOCK(); 70590297Sdes return (YPERR_DOMAIN); 706145849Sume } 70710522Swpaul 7081919Swollman tv.tv_sec = _yplib_timeout; 7091919Swollman tv.tv_usec = 0; 7101919Swollman 7111919Swollman bzero((char *)&yprv, sizeof yprv); 7121919Swollman 7131919Swollman r = clnt_call(ysd->dom_client, YPPROC_MATCH, 71495658Sdes (xdrproc_t)xdr_ypreq_key, &yprk, 71595658Sdes (xdrproc_t)xdr_ypresp_val, &yprv, tv); 71690297Sdes if (r != RPC_SUCCESS) { 7171919Swollman clnt_perror(ysd->dom_client, "yp_match: clnt_call"); 71815793Swpaul _yp_unbind(ysd); 7191919Swollman goto again; 7201919Swollman } 72115547Swpaul 72290297Sdes if (!(r = ypprot_err(yprv.stat))) { 72312816Swpaul *outvallen = yprv.val.valdat_len; 7241919Swollman *outval = (char *)malloc(*outvallen+1); 725228828Sghelmer if (*outval == NULL) { 726228828Sghelmer _yp_unbind(ysd); 727228828Sghelmer *outvallen = 0; 728228828Sghelmer xdr_free((xdrproc_t)xdr_ypresp_val, &yprv); 729228828Sghelmer YPUNLOCK(); 730228828Sghelmer return (YPERR_RESRC); 731228828Sghelmer } 73212816Swpaul bcopy(yprv.val.valdat_val, *outval, *outvallen); 7331919Swollman (*outval)[*outvallen] = '\0'; 7341919Swollman#ifdef YPMATCHCACHE 73534146Swpaul ypmatch_cache_insert(ysd, yprk.map, &yprk.key, &yprv.val); 7361919Swollman#endif 73715793Swpaul } 73815547Swpaul 73995658Sdes xdr_free((xdrproc_t)xdr_ypresp_val, &yprv); 740145849Sume YPUNLOCK(); 74190297Sdes return (r); 7421919Swollman} 7431919Swollman 744144678Sumestatic int 745144678Sumeyp_get_default_domain_locked(char **domp) 7461919Swollman{ 7471919Swollman *domp = NULL; 74890297Sdes if (_yp_domain[0] == '\0') 74990297Sdes if (getdomainname(_yp_domain, sizeof _yp_domain)) 75090297Sdes return (YPERR_NODOM); 7511919Swollman *domp = _yp_domain; 75290297Sdes return (0); 7531919Swollman} 7541919Swollman 7551919Swollmanint 756144678Sumeyp_get_default_domain(char **domp) 757144678Sume{ 758144678Sume int r; 759144678Sume 760144678Sume YPLOCK(); 761144678Sume r = yp_get_default_domain_locked(domp); 762144678Sume YPUNLOCK(); 763144678Sume return (r); 764144678Sume} 765144678Sume 766144678Sumeint 76790298Sdesyp_first(char *indomain, char *inmap, char **outkey, int *outkeylen, 76890298Sdes char **outval, int *outvallen) 7691919Swollman{ 7701919Swollman struct ypresp_key_val yprkv; 7711919Swollman struct ypreq_nokey yprnk; 7721919Swollman struct dom_binding *ysd; 7731919Swollman struct timeval tv; 7741919Swollman int r; 7751919Swollman 7767337Swpaul /* Sanity check */ 7777337Swpaul 7787337Swpaul if (indomain == NULL || !strlen(indomain) || 7797337Swpaul inmap == NULL || !strlen(inmap)) 78090297Sdes return (YPERR_BADARGS); 7817337Swpaul 7821919Swollman *outkey = *outval = NULL; 7831919Swollman *outkeylen = *outvallen = 0; 7841919Swollman 785145849Sume YPLOCK(); 7861919Swollmanagain: 787145849Sume if (_yp_dobind(indomain, &ysd) != 0) { 788145849Sume YPUNLOCK(); 78990297Sdes return (YPERR_DOMAIN); 790145849Sume } 7911919Swollman 7921919Swollman tv.tv_sec = _yplib_timeout; 7931919Swollman tv.tv_usec = 0; 7941919Swollman 7951919Swollman yprnk.domain = indomain; 7961919Swollman yprnk.map = inmap; 7971919Swollman bzero((char *)&yprkv, sizeof yprkv); 7981919Swollman 7991919Swollman r = clnt_call(ysd->dom_client, YPPROC_FIRST, 80095658Sdes (xdrproc_t)xdr_ypreq_nokey, &yprnk, 80195658Sdes (xdrproc_t)xdr_ypresp_key_val, &yprkv, tv); 80290297Sdes if (r != RPC_SUCCESS) { 8031919Swollman clnt_perror(ysd->dom_client, "yp_first: clnt_call"); 80415793Swpaul _yp_unbind(ysd); 8051919Swollman goto again; 8061919Swollman } 80790297Sdes if (!(r = ypprot_err(yprkv.stat))) { 80812816Swpaul *outkeylen = yprkv.key.keydat_len; 8091919Swollman *outkey = (char *)malloc(*outkeylen+1); 810228828Sghelmer if (*outkey == NULL) { 811228828Sghelmer _yp_unbind(ysd); 812228828Sghelmer *outkeylen = 0; 813228828Sghelmer xdr_free((xdrproc_t)xdr_ypresp_key_val, &yprkv); 814228828Sghelmer YPUNLOCK(); 815228828Sghelmer return (YPERR_RESRC); 816228828Sghelmer } 81712816Swpaul bcopy(yprkv.key.keydat_val, *outkey, *outkeylen); 8181919Swollman (*outkey)[*outkeylen] = '\0'; 81912816Swpaul *outvallen = yprkv.val.valdat_len; 8201919Swollman *outval = (char *)malloc(*outvallen+1); 821228828Sghelmer if (*outval == NULL) { 822228828Sghelmer free(*outkey); 823228828Sghelmer _yp_unbind(ysd); 824228828Sghelmer *outkeylen = *outvallen = 0; 825228828Sghelmer xdr_free((xdrproc_t)xdr_ypresp_key_val, &yprkv); 826228828Sghelmer YPUNLOCK(); 827228828Sghelmer return (YPERR_RESRC); 828228828Sghelmer } 82912816Swpaul bcopy(yprkv.val.valdat_val, *outval, *outvallen); 8301919Swollman (*outval)[*outvallen] = '\0'; 83115793Swpaul } 83215547Swpaul 83395658Sdes xdr_free((xdrproc_t)xdr_ypresp_key_val, &yprkv); 834145849Sume YPUNLOCK(); 83590297Sdes return (r); 8361919Swollman} 8371919Swollman 8381919Swollmanint 83990298Sdesyp_next(char *indomain, char *inmap, char *inkey, int inkeylen, 84090298Sdes char **outkey, int *outkeylen, char **outval, int *outvallen) 8411919Swollman{ 8421919Swollman struct ypresp_key_val yprkv; 8431919Swollman struct ypreq_key yprk; 8441919Swollman struct dom_binding *ysd; 8451919Swollman struct timeval tv; 8461919Swollman int r; 8471919Swollman 8487337Swpaul /* Sanity check */ 8497337Swpaul 8507337Swpaul if (inkey == NULL || !strlen(inkey) || inkeylen <= 0 || 8517337Swpaul inmap == NULL || !strlen(inmap) || 8527337Swpaul indomain == NULL || !strlen(indomain)) 85390297Sdes return (YPERR_BADARGS); 8547337Swpaul 8551919Swollman *outkey = *outval = NULL; 8561919Swollman *outkeylen = *outvallen = 0; 8571919Swollman 858145849Sume YPLOCK(); 8591919Swollmanagain: 860145849Sume if (_yp_dobind(indomain, &ysd) != 0) { 861145849Sume YPUNLOCK(); 86290297Sdes return (YPERR_DOMAIN); 863145849Sume } 8641919Swollman 8651919Swollman tv.tv_sec = _yplib_timeout; 8661919Swollman tv.tv_usec = 0; 8671919Swollman 8681919Swollman yprk.domain = indomain; 8691919Swollman yprk.map = inmap; 87012816Swpaul yprk.key.keydat_val = inkey; 87112816Swpaul yprk.key.keydat_len = inkeylen; 8721919Swollman bzero((char *)&yprkv, sizeof yprkv); 8731919Swollman 8741919Swollman r = clnt_call(ysd->dom_client, YPPROC_NEXT, 87595658Sdes (xdrproc_t)xdr_ypreq_key, &yprk, 87695658Sdes (xdrproc_t)xdr_ypresp_key_val, &yprkv, tv); 87790297Sdes if (r != RPC_SUCCESS) { 8781919Swollman clnt_perror(ysd->dom_client, "yp_next: clnt_call"); 87915793Swpaul _yp_unbind(ysd); 8801919Swollman goto again; 8811919Swollman } 88290297Sdes if (!(r = ypprot_err(yprkv.stat))) { 88312816Swpaul *outkeylen = yprkv.key.keydat_len; 8841919Swollman *outkey = (char *)malloc(*outkeylen+1); 885228828Sghelmer if (*outkey == NULL) { 886228828Sghelmer _yp_unbind(ysd); 887228828Sghelmer *outkeylen = 0; 888228828Sghelmer xdr_free((xdrproc_t)xdr_ypresp_key_val, &yprkv); 889228828Sghelmer YPUNLOCK(); 890228828Sghelmer return (YPERR_RESRC); 891228828Sghelmer } 89212816Swpaul bcopy(yprkv.key.keydat_val, *outkey, *outkeylen); 8931919Swollman (*outkey)[*outkeylen] = '\0'; 89412816Swpaul *outvallen = yprkv.val.valdat_len; 8951919Swollman *outval = (char *)malloc(*outvallen+1); 896228828Sghelmer if (*outval == NULL) { 897228828Sghelmer free(*outkey); 898228828Sghelmer _yp_unbind(ysd); 899228828Sghelmer *outkeylen = *outvallen = 0; 900228828Sghelmer xdr_free((xdrproc_t)xdr_ypresp_key_val, &yprkv); 901228828Sghelmer YPUNLOCK(); 902228828Sghelmer return (YPERR_RESRC); 903228828Sghelmer } 90412816Swpaul bcopy(yprkv.val.valdat_val, *outval, *outvallen); 9051919Swollman (*outval)[*outvallen] = '\0'; 90615793Swpaul } 90715547Swpaul 90895658Sdes xdr_free((xdrproc_t)xdr_ypresp_key_val, &yprkv); 909145849Sume YPUNLOCK(); 91090297Sdes return (r); 9111919Swollman} 9121919Swollman 9131919Swollmanint 91490298Sdesyp_all(char *indomain, char *inmap, struct ypall_callback *incallback) 9151919Swollman{ 9161919Swollman struct ypreq_nokey yprnk; 9171919Swollman struct dom_binding *ysd; 9181919Swollman struct timeval tv; 9191919Swollman struct sockaddr_in clnt_sin; 9201919Swollman CLIENT *clnt; 92114719Swpaul u_long status, savstat; 9221919Swollman int clnt_sock; 9231919Swollman 9247337Swpaul /* Sanity check */ 9257337Swpaul 9267337Swpaul if (indomain == NULL || !strlen(indomain) || 9277337Swpaul inmap == NULL || !strlen(inmap)) 92890297Sdes return (YPERR_BADARGS); 9297337Swpaul 930145849Sume YPLOCK(); 93115793Swpaulagain: 93215793Swpaul 933145849Sume if (_yp_dobind(indomain, &ysd) != 0) { 934145849Sume YPUNLOCK(); 93590297Sdes return (YPERR_DOMAIN); 936145849Sume } 9371919Swollman 9381919Swollman tv.tv_sec = _yplib_timeout; 9391919Swollman tv.tv_usec = 0; 94015793Swpaul 94115793Swpaul /* YPPROC_ALL manufactures its own channel to ypserv using TCP */ 94215793Swpaul 9431919Swollman clnt_sock = RPC_ANYSOCK; 9441919Swollman clnt_sin = ysd->dom_server_addr; 9451919Swollman clnt_sin.sin_port = 0; 9461919Swollman clnt = clnttcp_create(&clnt_sin, YPPROG, YPVERS, &clnt_sock, 0, 0); 94790297Sdes if (clnt == NULL) { 948145849Sume YPUNLOCK(); 9491919Swollman printf("clnttcp_create failed\n"); 95090297Sdes return (YPERR_PMAP); 9511919Swollman } 9521919Swollman 9531919Swollman yprnk.domain = indomain; 9541919Swollman yprnk.map = inmap; 9551919Swollman ypresp_allfn = incallback->foreach; 9561919Swollman ypresp_data = (void *)incallback->data; 9571919Swollman 95815793Swpaul if (clnt_call(clnt, YPPROC_ALL, 95995658Sdes (xdrproc_t)xdr_ypreq_nokey, &yprnk, 96095658Sdes (xdrproc_t)xdr_ypresp_all_seq, &status, tv) != RPC_SUCCESS) { 96177044Spirzyk clnt_perror(ysd->dom_client, "yp_all: clnt_call"); 96215793Swpaul clnt_destroy(clnt); 96315793Swpaul _yp_unbind(ysd); 96415793Swpaul goto again; 96515793Swpaul } 96615793Swpaul 9671919Swollman clnt_destroy(clnt); 96814719Swpaul savstat = status; 96995658Sdes xdr_free((xdrproc_t)xdr_ypresp_all_seq, &status); /* not really needed... */ 970145849Sume YPUNLOCK(); 97190297Sdes if (savstat != YP_NOMORE) 97290297Sdes return (ypprot_err(savstat)); 97390297Sdes return (0); 9741919Swollman} 9751919Swollman 9761919Swollmanint 97790298Sdesyp_order(char *indomain, char *inmap, int *outorder) 9781919Swollman{ 9791919Swollman struct dom_binding *ysd; 9801919Swollman struct ypresp_order ypro; 9811919Swollman struct ypreq_nokey yprnk; 9821919Swollman struct timeval tv; 9831919Swollman int r; 9841919Swollman 9857337Swpaul /* Sanity check */ 9867337Swpaul 9877337Swpaul if (indomain == NULL || !strlen(indomain) || 9887337Swpaul inmap == NULL || !strlen(inmap)) 98990297Sdes return (YPERR_BADARGS); 9907337Swpaul 991145849Sume YPLOCK(); 9921919Swollmanagain: 993145849Sume if (_yp_dobind(indomain, &ysd) != 0) { 994145849Sume YPUNLOCK(); 99590297Sdes return (YPERR_DOMAIN); 996145849Sume } 9971919Swollman 9981919Swollman tv.tv_sec = _yplib_timeout; 9991919Swollman tv.tv_usec = 0; 10001919Swollman 10011919Swollman yprnk.domain = indomain; 10021919Swollman yprnk.map = inmap; 10031919Swollman 10041919Swollman bzero((char *)(char *)&ypro, sizeof ypro); 10051919Swollman 10061919Swollman r = clnt_call(ysd->dom_client, YPPROC_ORDER, 100795658Sdes (xdrproc_t)xdr_ypreq_nokey, &yprnk, 100895658Sdes (xdrproc_t)xdr_ypresp_order, &ypro, tv); 100919520Swpaul 101019520Swpaul /* 101119520Swpaul * NIS+ in YP compat mode doesn't support the YPPROC_ORDER 101219520Swpaul * procedure. 101319520Swpaul */ 101419520Swpaul if (r == RPC_PROCUNAVAIL) { 1015145849Sume YPUNLOCK(); 101619520Swpaul return(YPERR_YPERR); 101719520Swpaul } 101890297Sdes 101990297Sdes if (r != RPC_SUCCESS) { 10201919Swollman clnt_perror(ysd->dom_client, "yp_order: clnt_call"); 102115793Swpaul _yp_unbind(ysd); 10221919Swollman goto again; 10231919Swollman } 10241919Swollman 102590297Sdes if (!(r = ypprot_err(ypro.stat))) { 102615547Swpaul *outorder = ypro.ordernum; 102715793Swpaul } 102815547Swpaul 102995658Sdes xdr_free((xdrproc_t)xdr_ypresp_order, &ypro); 1030145849Sume YPUNLOCK(); 103115793Swpaul return (r); 10321919Swollman} 10331919Swollman 10341919Swollmanint 103590298Sdesyp_master(char *indomain, char *inmap, char **outname) 10361919Swollman{ 10371919Swollman struct dom_binding *ysd; 10381919Swollman struct ypresp_master yprm; 10391919Swollman struct ypreq_nokey yprnk; 10401919Swollman struct timeval tv; 10411919Swollman int r; 10421919Swollman 10437337Swpaul /* Sanity check */ 10447337Swpaul 10457337Swpaul if (indomain == NULL || !strlen(indomain) || 10467337Swpaul inmap == NULL || !strlen(inmap)) 104790297Sdes return (YPERR_BADARGS); 1048145849Sume YPLOCK(); 10491919Swollmanagain: 1050145849Sume if (_yp_dobind(indomain, &ysd) != 0) { 1051145849Sume YPUNLOCK(); 105290297Sdes return (YPERR_DOMAIN); 1053145849Sume } 10541919Swollman 10551919Swollman tv.tv_sec = _yplib_timeout; 10561919Swollman tv.tv_usec = 0; 10571919Swollman 10581919Swollman yprnk.domain = indomain; 10591919Swollman yprnk.map = inmap; 10601919Swollman 10611919Swollman bzero((char *)&yprm, sizeof yprm); 10621919Swollman 10631919Swollman r = clnt_call(ysd->dom_client, YPPROC_MASTER, 106495658Sdes (xdrproc_t)xdr_ypreq_nokey, &yprnk, 106595658Sdes (xdrproc_t)xdr_ypresp_master, &yprm, tv); 106690297Sdes if (r != RPC_SUCCESS) { 10671919Swollman clnt_perror(ysd->dom_client, "yp_master: clnt_call"); 106815793Swpaul _yp_unbind(ysd); 10691919Swollman goto again; 10701919Swollman } 107115793Swpaul 107290297Sdes if (!(r = ypprot_err(yprm.stat))) { 107312816Swpaul *outname = (char *)strdup(yprm.peer); 107415793Swpaul } 107515547Swpaul 107695658Sdes xdr_free((xdrproc_t)xdr_ypresp_master, &yprm); 1077145849Sume YPUNLOCK(); 107815793Swpaul return (r); 10791919Swollman} 108090298Sdes 10817722Swpaulint 108290298Sdesyp_maplist(char *indomain, struct ypmaplist **outmaplist) 10831919Swollman{ 10841919Swollman struct dom_binding *ysd; 10851919Swollman struct ypresp_maplist ypml; 10861919Swollman struct timeval tv; 10871919Swollman int r; 10881919Swollman 10897337Swpaul /* Sanity check */ 10907337Swpaul 10917337Swpaul if (indomain == NULL || !strlen(indomain)) 109290297Sdes return (YPERR_BADARGS); 10937337Swpaul 1094145849Sume YPLOCK(); 10951919Swollmanagain: 1096145849Sume if (_yp_dobind(indomain, &ysd) != 0) { 1097145849Sume YPUNLOCK(); 109890297Sdes return (YPERR_DOMAIN); 1099145849Sume } 11001919Swollman 11011919Swollman tv.tv_sec = _yplib_timeout; 11021919Swollman tv.tv_usec = 0; 11031919Swollman 11041919Swollman bzero((char *)&ypml, sizeof ypml); 11051919Swollman 11061919Swollman r = clnt_call(ysd->dom_client, YPPROC_MAPLIST, 110795658Sdes (xdrproc_t)xdr_domainname, &indomain, 110895658Sdes (xdrproc_t)xdr_ypresp_maplist, &ypml,tv); 11091919Swollman if (r != RPC_SUCCESS) { 11101919Swollman clnt_perror(ysd->dom_client, "yp_maplist: clnt_call"); 111115793Swpaul _yp_unbind(ysd); 11121919Swollman goto again; 11131919Swollman } 111490297Sdes if (!(r = ypprot_err(ypml.stat))) { 111515547Swpaul *outmaplist = ypml.maps; 111615793Swpaul } 111715793Swpaul 111895658Sdes /* NO: xdr_free((xdrproc_t)xdr_ypresp_maplist, &ypml);*/ 1119145849Sume YPUNLOCK(); 112015793Swpaul return (r); 11211919Swollman} 11221919Swollman 112395658Sdesconst char * 112490298Sdesyperr_string(int incode) 11251919Swollman{ 11261919Swollman static char err[80]; 11271919Swollman 112890297Sdes switch (incode) { 11291919Swollman case 0: 113090297Sdes return ("Success"); 11311919Swollman case YPERR_BADARGS: 113290297Sdes return ("Request arguments bad"); 11331919Swollman case YPERR_RPC: 113490297Sdes return ("RPC failure"); 11351919Swollman case YPERR_DOMAIN: 113690297Sdes return ("Can't bind to server which serves this domain"); 11371919Swollman case YPERR_MAP: 113890297Sdes return ("No such map in server's domain"); 11391919Swollman case YPERR_KEY: 114090297Sdes return ("No such key in map"); 11411919Swollman case YPERR_YPERR: 114290297Sdes return ("YP server error"); 11431919Swollman case YPERR_RESRC: 114490297Sdes return ("Local resource allocation failure"); 11451919Swollman case YPERR_NOMORE: 114690297Sdes return ("No more records in map database"); 11471919Swollman case YPERR_PMAP: 114890297Sdes return ("Can't communicate with portmapper"); 11491919Swollman case YPERR_YPBIND: 115090297Sdes return ("Can't communicate with ypbind"); 11511919Swollman case YPERR_YPSERV: 115290297Sdes return ("Can't communicate with ypserv"); 11531919Swollman case YPERR_NODOM: 115490297Sdes return ("Local domain name not set"); 11551919Swollman case YPERR_BADDB: 115690297Sdes return ("Server data base is bad"); 11571919Swollman case YPERR_VERS: 115890297Sdes return ("YP server version mismatch - server can't supply service."); 11591919Swollman case YPERR_ACCESS: 116090297Sdes return ("Access violation"); 11611919Swollman case YPERR_BUSY: 116290297Sdes return ("Database is busy"); 11631919Swollman } 11641919Swollman sprintf(err, "YP unknown error %d\n", incode); 116590297Sdes return (err); 11661919Swollman} 11671919Swollman 11681919Swollmanint 116990298Sdesypprot_err(unsigned int incode) 11701919Swollman{ 117190297Sdes switch (incode) { 11721919Swollman case YP_TRUE: 117390297Sdes return (0); 11741919Swollman case YP_FALSE: 117590297Sdes return (YPERR_YPBIND); 11761919Swollman case YP_NOMORE: 117790297Sdes return (YPERR_NOMORE); 11781919Swollman case YP_NOMAP: 117990297Sdes return (YPERR_MAP); 11801919Swollman case YP_NODOM: 118190297Sdes return (YPERR_DOMAIN); 11821919Swollman case YP_NOKEY: 118390297Sdes return (YPERR_KEY); 11841919Swollman case YP_BADOP: 118590297Sdes return (YPERR_YPERR); 11861919Swollman case YP_BADDB: 118790297Sdes return (YPERR_BADDB); 11881919Swollman case YP_YPERR: 118990297Sdes return (YPERR_YPERR); 11901919Swollman case YP_BADARGS: 119190297Sdes return (YPERR_BADARGS); 11921919Swollman case YP_VERS: 119390297Sdes return (YPERR_VERS); 11941919Swollman } 119590297Sdes return (YPERR_YPERR); 11961919Swollman} 11971919Swollman 11981919Swollmanint 119990298Sdes_yp_check(char **dom) 12001919Swollman{ 12011919Swollman char *unused; 12021919Swollman 1203144678Sume YPLOCK(); 120490297Sdes if (_yp_domain[0]=='\0') 1205144678Sume if (yp_get_default_domain_locked(&unused)) { 1206144678Sume YPUNLOCK(); 120790297Sdes return (0); 1208144678Sume } 12091919Swollman 121090297Sdes if (dom) 12111919Swollman *dom = _yp_domain; 12121919Swollman 1213145849Sume if (yp_bind_locked(_yp_domain) == 0) { 1214145849Sume yp_unbind_locked(_yp_domain); 1215144678Sume YPUNLOCK(); 121690297Sdes return (1); 121712095Swpaul } 1218144678Sume YPUNLOCK(); 121990297Sdes return (0); 12201919Swollman} 1221