14415cd19SGarrett Wollman /* 24415cd19SGarrett Wollman * Copyright (c) 1992/3 Theo de Raadt <deraadt@fsa.ca> 34e6ace08SBill Paul * Copyright (c) 1998 Bill Paul <wpaul@ctr.columbia.edu> 44415cd19SGarrett Wollman * All rights reserved. 54415cd19SGarrett Wollman * 64415cd19SGarrett Wollman * Redistribution and use in source and binary forms, with or without 74415cd19SGarrett Wollman * modification, are permitted provided that the following conditions 84415cd19SGarrett Wollman * are met: 94415cd19SGarrett Wollman * 1. Redistributions of source code must retain the above copyright 104415cd19SGarrett Wollman * notice, this list of conditions and the following disclaimer. 114415cd19SGarrett Wollman * 2. Redistributions in binary form must reproduce the above copyright 124415cd19SGarrett Wollman * notice, this list of conditions and the following disclaimer in the 134415cd19SGarrett Wollman * documentation and/or other materials provided with the distribution. 144415cd19SGarrett Wollman * 3. The name of the author may not be used to endorse or promote 154415cd19SGarrett Wollman * products derived from this software without specific prior written 164415cd19SGarrett Wollman * permission. 174415cd19SGarrett Wollman * 184415cd19SGarrett Wollman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 194415cd19SGarrett Wollman * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 204415cd19SGarrett Wollman * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 214415cd19SGarrett Wollman * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 224415cd19SGarrett Wollman * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 234415cd19SGarrett Wollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 244415cd19SGarrett Wollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 254415cd19SGarrett Wollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 264415cd19SGarrett Wollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 274415cd19SGarrett Wollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 284415cd19SGarrett Wollman * SUCH DAMAGE. 294415cd19SGarrett Wollman */ 304415cd19SGarrett Wollman 314415cd19SGarrett Wollman #ifndef LINT 327f3dea24SPeter Wemm static char *rcsid = "$FreeBSD$"; 334415cd19SGarrett Wollman #endif 344415cd19SGarrett Wollman 35d201fe46SDaniel Eischen #include "namespace.h" 364415cd19SGarrett Wollman #include <sys/param.h> 374415cd19SGarrett Wollman #include <sys/types.h> 384415cd19SGarrett Wollman #include <sys/socket.h> 394415cd19SGarrett Wollman #include <sys/file.h> 404415cd19SGarrett Wollman #include <sys/uio.h> 414415cd19SGarrett Wollman #include <errno.h> 424415cd19SGarrett Wollman #include <stdio.h> 434415cd19SGarrett Wollman #include <string.h> 44b9729ac2SBill Paul #include <stdlib.h> 45b9729ac2SBill Paul #include <unistd.h> 464415cd19SGarrett Wollman #include <rpc/rpc.h> 474415cd19SGarrett Wollman #include <rpc/xdr.h> 480e276383SBill Paul #include <rpcsvc/yp.h> 49d201fe46SDaniel Eischen #include "un-namespace.h" 50d201fe46SDaniel Eischen #include "libc_private.h" 510e276383SBill Paul 520e276383SBill Paul /* 530e276383SBill Paul * We have to define these here due to clashes between yp_prot.h and 540e276383SBill Paul * yp.h. 550e276383SBill Paul */ 560e276383SBill Paul 574e6ace08SBill Paul #define YPMATCHCACHE 584e6ace08SBill Paul 594e6ace08SBill Paul #ifdef YPMATCHCACHE 604e6ace08SBill Paul struct ypmatch_ent { 614e6ace08SBill Paul char *ypc_map; 624e6ace08SBill Paul keydat ypc_key; 634e6ace08SBill Paul valdat ypc_val; 644e6ace08SBill Paul time_t ypc_expire_t; 654e6ace08SBill Paul struct ypmatch_ent *ypc_next; 664e6ace08SBill Paul }; 674e6ace08SBill Paul #define YPLIB_MAXCACHE 5 /* At most 5 entries */ 684e6ace08SBill Paul #define YPLIB_EXPIRE 5 /* Expire after 5 seconds */ 694e6ace08SBill Paul #endif 704e6ace08SBill Paul 710e276383SBill Paul struct dom_binding { 720e276383SBill Paul struct dom_binding *dom_pnext; 730e276383SBill Paul char dom_domain[YPMAXDOMAIN + 1]; 740e276383SBill Paul struct sockaddr_in dom_server_addr; 750e276383SBill Paul u_short dom_server_port; 760e276383SBill Paul int dom_socket; 770e276383SBill Paul CLIENT *dom_client; 78a2308772SBill Paul u_short dom_local_port; /* now I finally know what this is for. */ 790e276383SBill Paul long dom_vers; 804e6ace08SBill Paul #ifdef YPMATCHCACHE 814e6ace08SBill Paul struct ypmatch_ent *cache; 824e6ace08SBill Paul int ypmatch_cachecnt; 834e6ace08SBill Paul #endif 840e276383SBill Paul }; 850e276383SBill Paul 864415cd19SGarrett Wollman #include <rpcsvc/ypclnt.h> 874415cd19SGarrett Wollman 884415cd19SGarrett Wollman #ifndef BINDINGDIR 894415cd19SGarrett Wollman #define BINDINGDIR "/var/yp/binding" 904415cd19SGarrett Wollman #endif 91456ebbf8SBill Paul #define MAX_RETRIES 20 924415cd19SGarrett Wollman 934415cd19SGarrett Wollman extern bool_t xdr_domainname(), xdr_ypbind_resp(); 944415cd19SGarrett Wollman extern bool_t xdr_ypreq_key(), xdr_ypresp_val(); 954415cd19SGarrett Wollman extern bool_t xdr_ypreq_nokey(), xdr_ypresp_key_val(); 964415cd19SGarrett Wollman extern bool_t xdr_ypresp_all(), xdr_ypresp_all_seq(); 974415cd19SGarrett Wollman extern bool_t xdr_ypresp_master(); 984415cd19SGarrett Wollman 994415cd19SGarrett Wollman int (*ypresp_allfn)(); 1004415cd19SGarrett Wollman void *ypresp_data; 1014415cd19SGarrett Wollman 102cc64a2bfSBill Paul static void _yp_unbind __P(( struct dom_binding * )); 1034415cd19SGarrett Wollman struct dom_binding *_ypbindlist; 1044415cd19SGarrett Wollman static char _yp_domain[MAXHOSTNAMELEN]; 1054415cd19SGarrett Wollman int _yplib_timeout = 10; 1064415cd19SGarrett Wollman 1074415cd19SGarrett Wollman #ifdef YPMATCHCACHE 1084e6ace08SBill Paul static void ypmatch_cache_delete(ypdb, prev, cur) 1094e6ace08SBill Paul struct dom_binding *ypdb; 1104e6ace08SBill Paul struct ypmatch_ent *prev; 1114e6ace08SBill Paul struct ypmatch_ent *cur; 1124415cd19SGarrett Wollman { 1134e6ace08SBill Paul if (prev == NULL) 1144e6ace08SBill Paul ypdb->cache = cur->ypc_next; 1154e6ace08SBill Paul else 1164e6ace08SBill Paul prev->ypc_next = cur->ypc_next; 1174e6ace08SBill Paul 1184e6ace08SBill Paul free(cur->ypc_map); 1194e6ace08SBill Paul free(cur->ypc_key.keydat_val); 1204e6ace08SBill Paul free(cur->ypc_val.valdat_val); 1214e6ace08SBill Paul free(cur); 1224e6ace08SBill Paul 1234e6ace08SBill Paul ypdb->ypmatch_cachecnt--; 1244e6ace08SBill Paul 1254e6ace08SBill Paul return; 1264e6ace08SBill Paul } 1274e6ace08SBill Paul 1284e6ace08SBill Paul static void ypmatch_cache_flush(ypdb) 1294e6ace08SBill Paul struct dom_binding *ypdb; 1304e6ace08SBill Paul { 1314e6ace08SBill Paul struct ypmatch_ent *n, *c = ypdb->cache; 1324e6ace08SBill Paul 1334e6ace08SBill Paul while (c != NULL) { 1344e6ace08SBill Paul n = c->ypc_next; 1354e6ace08SBill Paul ypmatch_cache_delete(ypdb, NULL, c); 1364e6ace08SBill Paul c = n; 1374e6ace08SBill Paul } 1384e6ace08SBill Paul 1394e6ace08SBill Paul return; 1404e6ace08SBill Paul } 1414e6ace08SBill Paul 1424e6ace08SBill Paul static void ypmatch_cache_expire(ypdb) 1434e6ace08SBill Paul struct dom_binding *ypdb; 1444e6ace08SBill Paul { 1454e6ace08SBill Paul struct ypmatch_ent *c = ypdb->cache; 1464e6ace08SBill Paul struct ypmatch_ent *n, *p = NULL; 1474415cd19SGarrett Wollman time_t t; 1484415cd19SGarrett Wollman 1494415cd19SGarrett Wollman time(&t); 1504415cd19SGarrett Wollman 1514e6ace08SBill Paul while (c != NULL) { 1524e6ace08SBill Paul if (t >= c->ypc_expire_t) { 1534e6ace08SBill Paul n = c->ypc_next; 1544e6ace08SBill Paul ypmatch_cache_delete(ypdb, p, c); 1554e6ace08SBill Paul c = n; 1564415cd19SGarrett Wollman } else { 1574e6ace08SBill Paul p = c; 1584e6ace08SBill Paul c = c->ypc_next; 1594e6ace08SBill Paul } 1604415cd19SGarrett Wollman } 1614415cd19SGarrett Wollman 1624e6ace08SBill Paul return; 1634415cd19SGarrett Wollman } 1644415cd19SGarrett Wollman 1654e6ace08SBill Paul static void ypmatch_cache_insert(ypdb, map, key, val) 1664e6ace08SBill Paul struct dom_binding *ypdb; 1674415cd19SGarrett Wollman char *map; 1684e6ace08SBill Paul keydat *key; 1694e6ace08SBill Paul valdat *val; 1704415cd19SGarrett Wollman { 1714e6ace08SBill Paul struct ypmatch_ent *new; 1724415cd19SGarrett Wollman 1734e6ace08SBill Paul /* Do an expire run to maybe open up a slot. */ 1744e6ace08SBill Paul if (ypdb->ypmatch_cachecnt) 1754e6ace08SBill Paul ypmatch_cache_expire(ypdb); 1764415cd19SGarrett Wollman 1774e6ace08SBill Paul /* 1784e6ace08SBill Paul * If there are no slots free, then force an expire of 1794e6ace08SBill Paul * the least recently used entry. 1804e6ace08SBill Paul */ 1814e6ace08SBill Paul if (ypdb->ypmatch_cachecnt >= YPLIB_MAXCACHE) { 1824e6ace08SBill Paul struct ypmatch_ent *o = NULL, *c = ypdb->cache; 1834e6ace08SBill Paul time_t oldest = 0; 1844415cd19SGarrett Wollman 1854e6ace08SBill Paul oldest = ~oldest; 1864415cd19SGarrett Wollman 1874e6ace08SBill Paul while(c != NULL) { 1884e6ace08SBill Paul if (c->ypc_expire_t < oldest) { 1894e6ace08SBill Paul oldest = c->ypc_expire_t; 1904e6ace08SBill Paul o = c; 1914415cd19SGarrett Wollman } 1924e6ace08SBill Paul c = c->ypc_next; 1934e6ace08SBill Paul } 1944e6ace08SBill Paul 1954e6ace08SBill Paul if (o == NULL) 1964e6ace08SBill Paul return; 1974e6ace08SBill Paul o->ypc_expire_t = 0; 1984e6ace08SBill Paul ypmatch_cache_expire(ypdb); 1994e6ace08SBill Paul } 2004e6ace08SBill Paul 2014e6ace08SBill Paul new = malloc(sizeof(struct ypmatch_ent)); 2024e6ace08SBill Paul if (new == NULL) 2034e6ace08SBill Paul return; 2044e6ace08SBill Paul 2054e6ace08SBill Paul new->ypc_map = strdup(map); 2064e6ace08SBill Paul if (new->ypc_map == NULL) { 2074e6ace08SBill Paul free(new); 2084e6ace08SBill Paul return; 2094e6ace08SBill Paul } 2104e6ace08SBill Paul new->ypc_key.keydat_val = malloc(key->keydat_len); 2114e6ace08SBill Paul if (new->ypc_key.keydat_val == NULL) { 2124e6ace08SBill Paul free(new->ypc_map); 2134e6ace08SBill Paul free(new); 2144e6ace08SBill Paul return; 2154e6ace08SBill Paul } 2164e6ace08SBill Paul new->ypc_val.valdat_val = malloc(val->valdat_len); 2174e6ace08SBill Paul if (new->ypc_val.valdat_val == NULL) { 2184e6ace08SBill Paul free(new->ypc_val.valdat_val); 2194e6ace08SBill Paul free(new->ypc_map); 2204e6ace08SBill Paul free(new); 2214e6ace08SBill Paul return; 2224e6ace08SBill Paul } 2234e6ace08SBill Paul 2244e6ace08SBill Paul new->ypc_expire_t = time(NULL) + YPLIB_EXPIRE; 2254e6ace08SBill Paul new->ypc_key.keydat_len = key->keydat_len; 2264e6ace08SBill Paul new->ypc_val.valdat_len = val->valdat_len; 2274e6ace08SBill Paul bcopy(key->keydat_val, new->ypc_key.keydat_val, key->keydat_len); 2284e6ace08SBill Paul bcopy(val->valdat_val, new->ypc_val.valdat_val, val->valdat_len); 2294e6ace08SBill Paul 2304e6ace08SBill Paul new->ypc_next = ypdb->cache; 2314e6ace08SBill Paul ypdb->cache = new; 2324e6ace08SBill Paul 2334e6ace08SBill Paul ypdb->ypmatch_cachecnt++; 2344e6ace08SBill Paul 2354e6ace08SBill Paul return; 2364e6ace08SBill Paul } 2374e6ace08SBill Paul 2384e6ace08SBill Paul static bool_t ypmatch_cache_lookup(ypdb, map, key, val) 2394e6ace08SBill Paul struct dom_binding *ypdb; 2404e6ace08SBill Paul char *map; 2414e6ace08SBill Paul keydat *key; 2424e6ace08SBill Paul valdat *val; 2434e6ace08SBill Paul { 2444e6ace08SBill Paul struct ypmatch_ent *c = ypdb->cache; 2454e6ace08SBill Paul 2464e6ace08SBill Paul ypmatch_cache_expire(ypdb); 2474e6ace08SBill Paul 2484e6ace08SBill Paul for (c = ypdb->cache; c != NULL; c = c->ypc_next) { 2494e6ace08SBill Paul if (strcmp(map, c->ypc_map)) 2504e6ace08SBill Paul continue; 2514e6ace08SBill Paul if (key->keydat_len != c->ypc_key.keydat_len) 2524e6ace08SBill Paul continue; 2534e6ace08SBill Paul if (bcmp(key->keydat_val, c->ypc_key.keydat_val, 2544e6ace08SBill Paul key->keydat_len)) 2554e6ace08SBill Paul continue; 2564e6ace08SBill Paul } 2574e6ace08SBill Paul 2584e6ace08SBill Paul if (c == NULL) 2594e6ace08SBill Paul return(FALSE); 2604e6ace08SBill Paul 2614e6ace08SBill Paul val->valdat_len = c->ypc_val.valdat_len; 2624e6ace08SBill Paul val->valdat_val = c->ypc_val.valdat_val; 2634e6ace08SBill Paul 2644e6ace08SBill Paul return(TRUE); 2654415cd19SGarrett Wollman } 2664415cd19SGarrett Wollman #endif 2674415cd19SGarrett Wollman 26864416168SBill Paul char * 26964416168SBill Paul ypbinderr_string(incode) 27064416168SBill Paul int incode; 27164416168SBill Paul { 27264416168SBill Paul static char err[80]; 27364416168SBill Paul switch(incode) { 27464416168SBill Paul case 0: 27564416168SBill Paul return "Success"; 27662967ca2SBill Paul case YPBIND_ERR_ERR: 27764416168SBill Paul return "Internal ypbind error"; 27862967ca2SBill Paul case YPBIND_ERR_NOSERV: 27964416168SBill Paul return "Domain not bound"; 28062967ca2SBill Paul case YPBIND_ERR_RESC: 28164416168SBill Paul return "System resource allocation failure"; 28264416168SBill Paul } 28362967ca2SBill Paul sprintf(err, "Unknown ypbind error: #%d\n", incode); 28464416168SBill Paul return err; 28564416168SBill Paul } 28664416168SBill Paul 2874415cd19SGarrett Wollman int 2884415cd19SGarrett Wollman _yp_dobind(dom, ypdb) 2894415cd19SGarrett Wollman char *dom; 2904415cd19SGarrett Wollman struct dom_binding **ypdb; 2914415cd19SGarrett Wollman { 292e75ad74aSJames Raynard static pid_t pid = -1; 2934415cd19SGarrett Wollman char path[MAXPATHLEN]; 2944415cd19SGarrett Wollman struct dom_binding *ysd, *ysd2; 2959d80b1ddSBill Paul struct ypbind_resp ypbr; 2964415cd19SGarrett Wollman struct timeval tv; 2974415cd19SGarrett Wollman struct sockaddr_in clnt_sin; 29851295a4dSJordan K. Hubbard int clnt_sock, fd; 299ccbcef60SJames Raynard pid_t gpid; 3004415cd19SGarrett Wollman CLIENT *client; 3014415cd19SGarrett Wollman int new = 0, r; 302456ebbf8SBill Paul int retries = 0; 303a2308772SBill Paul struct sockaddr_in check; 304a2308772SBill Paul int checklen = sizeof(struct sockaddr_in); 3054415cd19SGarrett Wollman 3066e8caff7SBill Paul /* Not allowed; bad doggie. Bad. */ 3076e8caff7SBill Paul if (strchr(dom, '/') != NULL) 3086e8caff7SBill Paul return(YPERR_BADARGS); 3096e8caff7SBill Paul 3104415cd19SGarrett Wollman gpid = getpid(); 3114415cd19SGarrett Wollman if( !(pid==-1 || pid==gpid) ) { 3124415cd19SGarrett Wollman ysd = _ypbindlist; 3134415cd19SGarrett Wollman while(ysd) { 3149fa75c15SBill Paul if(ysd->dom_client != NULL) 315cc64a2bfSBill Paul _yp_unbind(ysd); 3164415cd19SGarrett Wollman ysd2 = ysd->dom_pnext; 3174415cd19SGarrett Wollman free(ysd); 3184415cd19SGarrett Wollman ysd = ysd2; 3194415cd19SGarrett Wollman } 3204415cd19SGarrett Wollman _ypbindlist = NULL; 3214415cd19SGarrett Wollman } 3224415cd19SGarrett Wollman pid = gpid; 3234415cd19SGarrett Wollman 3244415cd19SGarrett Wollman if(ypdb!=NULL) 3254415cd19SGarrett Wollman *ypdb = NULL; 3264415cd19SGarrett Wollman 3274415cd19SGarrett Wollman if(dom==NULL || strlen(dom)==0) 3284415cd19SGarrett Wollman return YPERR_BADARGS; 3294415cd19SGarrett Wollman 3304415cd19SGarrett Wollman for(ysd = _ypbindlist; ysd; ysd = ysd->dom_pnext) 3314415cd19SGarrett Wollman if( strcmp(dom, ysd->dom_domain) == 0) 3324415cd19SGarrett Wollman break; 333a169c9b1SBill Paul 334a2308772SBill Paul 3354415cd19SGarrett Wollman if(ysd==NULL) { 3364415cd19SGarrett Wollman ysd = (struct dom_binding *)malloc(sizeof *ysd); 3374415cd19SGarrett Wollman bzero((char *)ysd, sizeof *ysd); 3384415cd19SGarrett Wollman ysd->dom_socket = -1; 3394415cd19SGarrett Wollman ysd->dom_vers = 0; 3404415cd19SGarrett Wollman new = 1; 341a2308772SBill Paul } else { 342a2308772SBill Paul /* Check the socket -- may have been hosed by the caller. */ 343d201fe46SDaniel Eischen if (_getsockname(ysd->dom_socket, (struct sockaddr *)&check, 344a2308772SBill Paul &checklen) == -1 || check.sin_family != AF_INET || 345a2308772SBill Paul check.sin_port != ysd->dom_local_port) { 346a2308772SBill Paul /* Socket became bogus somehow... need to rebind. */ 347a2308772SBill Paul int save, sock; 348a2308772SBill Paul 349a2308772SBill Paul sock = ysd->dom_socket; 350d201fe46SDaniel Eischen save = _dup(ysd->dom_socket); 3519fa75c15SBill Paul if (ysd->dom_client != NULL) 352a2308772SBill Paul clnt_destroy(ysd->dom_client); 353a2308772SBill Paul ysd->dom_vers = 0; 354a2308772SBill Paul ysd->dom_client = NULL; 355d201fe46SDaniel Eischen sock = _dup2(save, sock); 3569233c4d9SJason Evans _close(save); 357a2308772SBill Paul } 3584415cd19SGarrett Wollman } 3590f98415eSBill Paul 3604415cd19SGarrett Wollman again: 361456ebbf8SBill Paul retries++; 362456ebbf8SBill Paul if (retries > MAX_RETRIES) { 363456ebbf8SBill Paul if (new) 364456ebbf8SBill Paul free(ysd); 365456ebbf8SBill Paul return(YPERR_YPBIND); 366456ebbf8SBill Paul } 3674415cd19SGarrett Wollman #ifdef BINDINGDIR 3684415cd19SGarrett Wollman if(ysd->dom_vers==0) { 369a169c9b1SBill Paul /* 370a169c9b1SBill Paul * We're trying to make a new binding: zorch the 371a169c9b1SBill Paul * existing handle now (if any). 372a169c9b1SBill Paul */ 3739fa75c15SBill Paul if(ysd->dom_client != NULL) { 374a169c9b1SBill Paul clnt_destroy(ysd->dom_client); 375a169c9b1SBill Paul ysd->dom_client = NULL; 376a2308772SBill Paul ysd->dom_socket = -1; 377a169c9b1SBill Paul } 37883ac6cdcSKris Kennaway snprintf(path, sizeof(path), "%s/%s.%d", BINDINGDIR, dom, 2); 3799233c4d9SJason Evans if((fd = _open(path, O_RDONLY)) == -1) { 3804415cd19SGarrett Wollman /* no binding file, YP is dead. */ 381456ebbf8SBill Paul /* Try to bring it back to life. */ 3829233c4d9SJason Evans _close(fd); 383b9729ac2SBill Paul goto skipit; 3844415cd19SGarrett Wollman } 385d201fe46SDaniel Eischen if(_flock(fd, LOCK_EX|LOCK_NB) == -1 && errno==EWOULDBLOCK) { 3864415cd19SGarrett Wollman struct iovec iov[2]; 3879d80b1ddSBill Paul struct ypbind_resp ybr; 3884415cd19SGarrett Wollman u_short ypb_port; 3894415cd19SGarrett Wollman 3904415cd19SGarrett Wollman iov[0].iov_base = (caddr_t)&ypb_port; 3914415cd19SGarrett Wollman iov[0].iov_len = sizeof ypb_port; 3924415cd19SGarrett Wollman iov[1].iov_base = (caddr_t)&ybr; 3934415cd19SGarrett Wollman iov[1].iov_len = sizeof ybr; 3944415cd19SGarrett Wollman 395d201fe46SDaniel Eischen r = _readv(fd, iov, 2); 3964415cd19SGarrett Wollman if(r != iov[0].iov_len + iov[1].iov_len) { 3979233c4d9SJason Evans _close(fd); 3984415cd19SGarrett Wollman ysd->dom_vers = -1; 3994415cd19SGarrett Wollman goto again; 4004415cd19SGarrett Wollman } 4014415cd19SGarrett Wollman 4024415cd19SGarrett Wollman bzero(&ysd->dom_server_addr, sizeof ysd->dom_server_addr); 4034415cd19SGarrett Wollman ysd->dom_server_addr.sin_family = AF_INET; 4044415cd19SGarrett Wollman ysd->dom_server_addr.sin_len = sizeof(struct sockaddr_in); 4059d80b1ddSBill Paul ysd->dom_server_addr.sin_addr.s_addr = 4069d80b1ddSBill Paul *(u_long *)&ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr; 4074415cd19SGarrett Wollman ysd->dom_server_addr.sin_port = 4089d80b1ddSBill Paul *(u_short *)&ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port; 4094415cd19SGarrett Wollman 4104415cd19SGarrett Wollman ysd->dom_server_port = ysd->dom_server_addr.sin_port; 4119233c4d9SJason Evans _close(fd); 4124415cd19SGarrett Wollman goto gotit; 4134415cd19SGarrett Wollman } else { 4144415cd19SGarrett Wollman /* no lock on binding file, YP is dead. */ 415456ebbf8SBill Paul /* Try to bring it back to life. */ 4169233c4d9SJason Evans _close(fd); 417456ebbf8SBill Paul goto skipit; 418f067dfeaSBill Paul } 419f067dfeaSBill Paul } 420b9729ac2SBill Paul skipit: 4214415cd19SGarrett Wollman #endif 4224415cd19SGarrett Wollman if(ysd->dom_vers==-1 || ysd->dom_vers==0) { 423a169c9b1SBill Paul /* 424a169c9b1SBill Paul * We're trying to make a new binding: zorch the 425a169c9b1SBill Paul * existing handle now (if any). 426a169c9b1SBill Paul */ 4279fa75c15SBill Paul if(ysd->dom_client != NULL) { 428a169c9b1SBill Paul clnt_destroy(ysd->dom_client); 429a169c9b1SBill Paul ysd->dom_client = NULL; 430a2308772SBill Paul ysd->dom_socket = -1; 431a169c9b1SBill Paul } 4324415cd19SGarrett Wollman bzero((char *)&clnt_sin, sizeof clnt_sin); 4334415cd19SGarrett Wollman clnt_sin.sin_family = AF_INET; 4344415cd19SGarrett Wollman clnt_sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 4354415cd19SGarrett Wollman 4364415cd19SGarrett Wollman clnt_sock = RPC_ANYSOCK; 4374415cd19SGarrett Wollman client = clnttcp_create(&clnt_sin, YPBINDPROG, YPBINDVERS, &clnt_sock, 4384415cd19SGarrett Wollman 0, 0); 4394415cd19SGarrett Wollman if(client==NULL) { 44020e4b00aSBill Paul /* 44120e4b00aSBill Paul * These conditions indicate ypbind just isn't 44220e4b00aSBill Paul * alive -- we probably don't want to shoot our 443a169c9b1SBill Paul * mouth off in this case; instead generate error 44420e4b00aSBill Paul * messages only for really exotic problems. 44520e4b00aSBill Paul */ 44620e4b00aSBill Paul if (rpc_createerr.cf_stat != RPC_PROGNOTREGISTERED && 44720e4b00aSBill Paul (rpc_createerr.cf_stat != RPC_SYSTEMERROR && 44820e4b00aSBill Paul rpc_createerr.cf_error.re_errno == ECONNREFUSED)) 4494415cd19SGarrett Wollman clnt_pcreateerror("clnttcp_create"); 4504415cd19SGarrett Wollman if(new) 4514415cd19SGarrett Wollman free(ysd); 452456ebbf8SBill Paul return (YPERR_YPBIND); 4534415cd19SGarrett Wollman } 4544415cd19SGarrett Wollman 45556d18edaSBill Paul /* 45656d18edaSBill Paul * Check the port number -- should be < IPPORT_RESERVED. 45756d18edaSBill Paul * If not, it's possible someone has registered a bogus 45856d18edaSBill Paul * ypbind with the portmapper and is trying to trick us. 45956d18edaSBill Paul */ 46056d18edaSBill Paul if (ntohs(clnt_sin.sin_port) >= IPPORT_RESERVED) { 4619fa75c15SBill Paul if (client != NULL) 46256d18edaSBill Paul clnt_destroy(client); 46356d18edaSBill Paul if (new) 46456d18edaSBill Paul free(ysd); 46556d18edaSBill Paul return(YPERR_YPBIND); 46656d18edaSBill Paul } 467456ebbf8SBill Paul tv.tv_sec = _yplib_timeout/2; 4684415cd19SGarrett Wollman tv.tv_usec = 0; 4694415cd19SGarrett Wollman r = clnt_call(client, YPBINDPROC_DOMAIN, 4709d80b1ddSBill Paul xdr_domainname, (char *)&dom, xdr_ypbind_resp, &ypbr, tv); 4714415cd19SGarrett Wollman if(r != RPC_SUCCESS) { 4724415cd19SGarrett Wollman clnt_destroy(client); 4734415cd19SGarrett Wollman ysd->dom_vers = -1; 474a2308772SBill Paul if (r == RPC_PROGUNAVAIL || r == RPC_PROCUNAVAIL) { 475a2308772SBill Paul if (new) 476a2308772SBill Paul free(ysd); 47720e4b00aSBill Paul return(YPERR_YPBIND); 478a2308772SBill Paul } 47920e4b00aSBill Paul fprintf(stderr, 48020e4b00aSBill Paul "YP: server for domain %s not responding, retrying\n", dom); 4814415cd19SGarrett Wollman goto again; 48264416168SBill Paul } else { 48364416168SBill Paul if (ypbr.ypbind_status != YPBIND_SUCC_VAL) { 4849233c4d9SJason Evans struct timespec time_to_sleep, time_remaining; 4859233c4d9SJason Evans 486456ebbf8SBill Paul clnt_destroy(client); 487456ebbf8SBill Paul ysd->dom_vers = -1; 4889233c4d9SJason Evans 4899233c4d9SJason Evans time_to_sleep.tv_sec = _yplib_timeout/2; 4909233c4d9SJason Evans time_to_sleep.tv_nsec = 0; 4919233c4d9SJason Evans _nanosleep(&time_to_sleep, 4929233c4d9SJason Evans &time_remaining); 493456ebbf8SBill Paul goto again; 49464416168SBill Paul } 4954415cd19SGarrett Wollman } 4964415cd19SGarrett Wollman clnt_destroy(client); 4974415cd19SGarrett Wollman 4984415cd19SGarrett Wollman bzero((char *)&ysd->dom_server_addr, sizeof ysd->dom_server_addr); 4994415cd19SGarrett Wollman ysd->dom_server_addr.sin_family = AF_INET; 5004415cd19SGarrett Wollman ysd->dom_server_addr.sin_port = 5019d80b1ddSBill Paul *(u_short *)&ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port; 5024415cd19SGarrett Wollman ysd->dom_server_addr.sin_addr.s_addr = 5039d80b1ddSBill Paul *(u_long *)&ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr; 50456d18edaSBill Paul 50556d18edaSBill Paul /* 50656d18edaSBill Paul * We could do a reserved port check here too, but this 50756d18edaSBill Paul * could pose compatibility problems. The local ypbind is 50856d18edaSBill Paul * supposed to decide whether or not to trust yp servers 50956d18edaSBill Paul * on insecure ports. For now, we trust its judgement. 51056d18edaSBill Paul */ 5114415cd19SGarrett Wollman ysd->dom_server_port = 5129d80b1ddSBill Paul *(u_short *)&ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port; 5134415cd19SGarrett Wollman gotit: 5144415cd19SGarrett Wollman ysd->dom_vers = YPVERS; 51583ac6cdcSKris Kennaway strlcpy(ysd->dom_domain, dom, sizeof(ysd->dom_domain)); 5164415cd19SGarrett Wollman } 5174415cd19SGarrett Wollman 518a169c9b1SBill Paul /* Don't rebuild the connection to the server unless we have to. */ 519a169c9b1SBill Paul if (ysd->dom_client == NULL) { 5204415cd19SGarrett Wollman tv.tv_sec = _yplib_timeout/2; 5214415cd19SGarrett Wollman tv.tv_usec = 0; 5224415cd19SGarrett Wollman ysd->dom_socket = RPC_ANYSOCK; 5234e6ace08SBill Paul ysd->dom_client = clntudp_bufcreate(&ysd->dom_server_addr, 5244e6ace08SBill Paul YPPROG, YPVERS, tv, &ysd->dom_socket, 1280, 2304); 5254415cd19SGarrett Wollman if(ysd->dom_client==NULL) { 5264415cd19SGarrett Wollman clnt_pcreateerror("clntudp_create"); 5274415cd19SGarrett Wollman ysd->dom_vers = -1; 5284415cd19SGarrett Wollman goto again; 5294415cd19SGarrett Wollman } 5309233c4d9SJason Evans if(_fcntl(ysd->dom_socket, F_SETFD, 1) == -1) 5314415cd19SGarrett Wollman perror("fcntl: F_SETFD"); 532a2308772SBill Paul /* 533a2308772SBill Paul * We want a port number associated with this socket 534a2308772SBill Paul * so that we can check its authenticity later. 535a2308772SBill Paul */ 536a2308772SBill Paul checklen = sizeof(struct sockaddr_in); 537a2308772SBill Paul bzero((char *)&check, checklen); 538d201fe46SDaniel Eischen _bind(ysd->dom_socket, (struct sockaddr *)&check, checklen); 539a2308772SBill Paul check.sin_family = AF_INET; 540d201fe46SDaniel Eischen if (!_getsockname(ysd->dom_socket, 541a2308772SBill Paul (struct sockaddr *)&check, &checklen)) { 542a2308772SBill Paul ysd->dom_local_port = check.sin_port; 543a2308772SBill Paul } else { 544a2308772SBill Paul clnt_destroy(ysd->dom_client); 545a2308772SBill Paul if (new) 546a2308772SBill Paul free(ysd); 547a2308772SBill Paul return(YPERR_YPBIND); 548a2308772SBill Paul } 549a169c9b1SBill Paul } 5504415cd19SGarrett Wollman 5514415cd19SGarrett Wollman if(new) { 5524415cd19SGarrett Wollman ysd->dom_pnext = _ypbindlist; 5534415cd19SGarrett Wollman _ypbindlist = ysd; 5544415cd19SGarrett Wollman } 5554415cd19SGarrett Wollman 5564415cd19SGarrett Wollman if(ypdb!=NULL) 5574415cd19SGarrett Wollman *ypdb = ysd; 5584415cd19SGarrett Wollman return 0; 5594415cd19SGarrett Wollman } 5604415cd19SGarrett Wollman 5614415cd19SGarrett Wollman static void 5624415cd19SGarrett Wollman _yp_unbind(ypb) 5634415cd19SGarrett Wollman struct dom_binding *ypb; 5644415cd19SGarrett Wollman { 5659fa75c15SBill Paul struct sockaddr_in check; 5669fa75c15SBill Paul int checklen = sizeof(struct sockaddr_in); 5679fa75c15SBill Paul 5689fa75c15SBill Paul if (ypb->dom_client != NULL) { 5699fa75c15SBill Paul /* Check the socket -- may have been hosed by the caller. */ 570d201fe46SDaniel Eischen if (_getsockname(ypb->dom_socket, (struct sockaddr *)&check, 5719fa75c15SBill Paul &checklen) == -1 || check.sin_family != AF_INET || 5729fa75c15SBill Paul check.sin_port != ypb->dom_local_port) { 5739fa75c15SBill Paul int save, sock; 5749fa75c15SBill Paul 5759fa75c15SBill Paul sock = ypb->dom_socket; 576d201fe46SDaniel Eischen save = _dup(ypb->dom_socket); 5774415cd19SGarrett Wollman clnt_destroy(ypb->dom_client); 578d201fe46SDaniel Eischen sock = _dup2(save, sock); 5799233c4d9SJason Evans _close(save); 5809fa75c15SBill Paul } else 5819fa75c15SBill Paul clnt_destroy(ypb->dom_client); 5829fa75c15SBill Paul } 5839fa75c15SBill Paul 5844415cd19SGarrett Wollman ypb->dom_client = NULL; 5854415cd19SGarrett Wollman ypb->dom_socket = -1; 5862694f9b9SBill Paul ypb->dom_vers = -1; 5874e6ace08SBill Paul #ifdef YPMATCHCACHE 5884e6ace08SBill Paul ypmatch_cache_flush(ypb); 5894e6ace08SBill Paul #endif 5904415cd19SGarrett Wollman } 5914415cd19SGarrett Wollman 5924415cd19SGarrett Wollman int 5934415cd19SGarrett Wollman yp_bind(dom) 5944415cd19SGarrett Wollman char *dom; 5954415cd19SGarrett Wollman { 5964415cd19SGarrett Wollman return _yp_dobind(dom, NULL); 5974415cd19SGarrett Wollman } 5984415cd19SGarrett Wollman 5994415cd19SGarrett Wollman void 6004415cd19SGarrett Wollman yp_unbind(dom) 6014415cd19SGarrett Wollman char *dom; 6024415cd19SGarrett Wollman { 6034415cd19SGarrett Wollman struct dom_binding *ypb, *ypbp; 6044415cd19SGarrett Wollman 6054415cd19SGarrett Wollman ypbp = NULL; 6064415cd19SGarrett Wollman for(ypb=_ypbindlist; ypb; ypb=ypb->dom_pnext) { 6074415cd19SGarrett Wollman if( strcmp(dom, ypb->dom_domain) == 0) { 6082694f9b9SBill Paul _yp_unbind(ypb); 6094415cd19SGarrett Wollman if(ypbp) 6104415cd19SGarrett Wollman ypbp->dom_pnext = ypb->dom_pnext; 6114415cd19SGarrett Wollman else 6124415cd19SGarrett Wollman _ypbindlist = ypb->dom_pnext; 6134415cd19SGarrett Wollman free(ypb); 6144415cd19SGarrett Wollman return; 6154415cd19SGarrett Wollman } 6164415cd19SGarrett Wollman ypbp = ypb; 6174415cd19SGarrett Wollman } 6184415cd19SGarrett Wollman return; 6194415cd19SGarrett Wollman } 6204415cd19SGarrett Wollman 6214415cd19SGarrett Wollman int 6224415cd19SGarrett Wollman yp_match(indomain, inmap, inkey, inkeylen, outval, outvallen) 6234415cd19SGarrett Wollman char *indomain; 6244415cd19SGarrett Wollman char *inmap; 6254415cd19SGarrett Wollman const char *inkey; 6264415cd19SGarrett Wollman int inkeylen; 6274415cd19SGarrett Wollman char **outval; 6284415cd19SGarrett Wollman int *outvallen; 6294415cd19SGarrett Wollman { 6304415cd19SGarrett Wollman struct dom_binding *ysd; 6314415cd19SGarrett Wollman struct ypresp_val yprv; 6324415cd19SGarrett Wollman struct timeval tv; 6334415cd19SGarrett Wollman struct ypreq_key yprk; 6344415cd19SGarrett Wollman int r; 6354415cd19SGarrett Wollman 6364415cd19SGarrett Wollman *outval = NULL; 6374415cd19SGarrett Wollman *outvallen = 0; 6384415cd19SGarrett Wollman 63906643071SBill Paul /* Sanity check */ 640e17334c3SBill Paul 64106643071SBill Paul if (inkey == NULL || !strlen(inkey) || inkeylen <= 0 || 64206643071SBill Paul inmap == NULL || !strlen(inmap) || 64306643071SBill Paul indomain == NULL || !strlen(indomain)) 64406643071SBill Paul return YPERR_BADARGS; 645e17334c3SBill Paul 6464e6ace08SBill Paul if (_yp_dobind(indomain, &ysd) != 0) 6474e6ace08SBill Paul return(YPERR_DOMAIN); 6484e6ace08SBill Paul 6494e6ace08SBill Paul yprk.domain = indomain; 6504e6ace08SBill Paul yprk.map = inmap; 6514e6ace08SBill Paul yprk.key.keydat_val = (char *)inkey; 6524e6ace08SBill Paul yprk.key.keydat_len = inkeylen; 6534e6ace08SBill Paul 6544415cd19SGarrett Wollman #ifdef YPMATCHCACHE 6554e6ace08SBill Paul if (ypmatch_cache_lookup(ysd, yprk.map, &yprk.key, &yprv.val) == TRUE) { 6564e6ace08SBill Paul /* 6574415cd19SGarrett Wollman if( !strcmp(_yp_domain, indomain) && ypmatch_find(inmap, inkey, 6580e276383SBill Paul inkeylen, &yprv.val.valdat_val, &yprv.val.valdat_len)) { 6594e6ace08SBill Paul */ 6600e276383SBill Paul *outvallen = yprv.val.valdat_len; 6614415cd19SGarrett Wollman *outval = (char *)malloc(*outvallen+1); 6620e276383SBill Paul bcopy(yprv.val.valdat_val, *outval, *outvallen); 6634415cd19SGarrett Wollman (*outval)[*outvallen] = '\0'; 6644415cd19SGarrett Wollman return 0; 6654415cd19SGarrett Wollman } 6664415cd19SGarrett Wollman #endif 6674415cd19SGarrett Wollman 6684cc738f7SBill Paul again: 6694cc738f7SBill Paul if( _yp_dobind(indomain, &ysd) != 0) 6704cc738f7SBill Paul return YPERR_DOMAIN; 6714cc738f7SBill Paul 6724415cd19SGarrett Wollman tv.tv_sec = _yplib_timeout; 6734415cd19SGarrett Wollman tv.tv_usec = 0; 6744415cd19SGarrett Wollman 6754415cd19SGarrett Wollman bzero((char *)&yprv, sizeof yprv); 6764415cd19SGarrett Wollman 6774415cd19SGarrett Wollman r = clnt_call(ysd->dom_client, YPPROC_MATCH, 6784415cd19SGarrett Wollman xdr_ypreq_key, &yprk, xdr_ypresp_val, &yprv, tv); 6794415cd19SGarrett Wollman if(r != RPC_SUCCESS) { 6804415cd19SGarrett Wollman clnt_perror(ysd->dom_client, "yp_match: clnt_call"); 6812694f9b9SBill Paul _yp_unbind(ysd); 6824415cd19SGarrett Wollman goto again; 6834415cd19SGarrett Wollman } 684a169c9b1SBill Paul 6850e276383SBill Paul if( !(r=ypprot_err(yprv.stat)) ) { 6860e276383SBill Paul *outvallen = yprv.val.valdat_len; 6874415cd19SGarrett Wollman *outval = (char *)malloc(*outvallen+1); 6880e276383SBill Paul bcopy(yprv.val.valdat_val, *outval, *outvallen); 6894415cd19SGarrett Wollman (*outval)[*outvallen] = '\0'; 6904415cd19SGarrett Wollman #ifdef YPMATCHCACHE 6914e6ace08SBill Paul ypmatch_cache_insert(ysd, yprk.map, &yprk.key, &yprv.val); 6924415cd19SGarrett Wollman #endif 6932694f9b9SBill Paul } 694a169c9b1SBill Paul 695a169c9b1SBill Paul xdr_free(xdr_ypresp_val, (char *)&yprv); 6964415cd19SGarrett Wollman return r; 6974415cd19SGarrett Wollman } 6984415cd19SGarrett Wollman 6994415cd19SGarrett Wollman int 7004415cd19SGarrett Wollman yp_get_default_domain(domp) 7014415cd19SGarrett Wollman char **domp; 7024415cd19SGarrett Wollman { 7034415cd19SGarrett Wollman *domp = NULL; 7044415cd19SGarrett Wollman if(_yp_domain[0] == '\0') 7054415cd19SGarrett Wollman if( getdomainname(_yp_domain, sizeof _yp_domain)) 7064415cd19SGarrett Wollman return YPERR_NODOM; 7074415cd19SGarrett Wollman *domp = _yp_domain; 7084415cd19SGarrett Wollman return 0; 7094415cd19SGarrett Wollman } 7104415cd19SGarrett Wollman 7114415cd19SGarrett Wollman int 7124415cd19SGarrett Wollman yp_first(indomain, inmap, outkey, outkeylen, outval, outvallen) 7134415cd19SGarrett Wollman char *indomain; 7144415cd19SGarrett Wollman char *inmap; 7154415cd19SGarrett Wollman char **outkey; 7164415cd19SGarrett Wollman int *outkeylen; 7174415cd19SGarrett Wollman char **outval; 7184415cd19SGarrett Wollman int *outvallen; 7194415cd19SGarrett Wollman { 7204415cd19SGarrett Wollman struct ypresp_key_val yprkv; 7214415cd19SGarrett Wollman struct ypreq_nokey yprnk; 7224415cd19SGarrett Wollman struct dom_binding *ysd; 7234415cd19SGarrett Wollman struct timeval tv; 7244415cd19SGarrett Wollman int r; 7254415cd19SGarrett Wollman 72606643071SBill Paul /* Sanity check */ 72706643071SBill Paul 72806643071SBill Paul if (indomain == NULL || !strlen(indomain) || 72906643071SBill Paul inmap == NULL || !strlen(inmap)) 73006643071SBill Paul return YPERR_BADARGS; 73106643071SBill Paul 7324415cd19SGarrett Wollman *outkey = *outval = NULL; 7334415cd19SGarrett Wollman *outkeylen = *outvallen = 0; 7344415cd19SGarrett Wollman 7354415cd19SGarrett Wollman again: 7364415cd19SGarrett Wollman if( _yp_dobind(indomain, &ysd) != 0) 7374415cd19SGarrett Wollman return YPERR_DOMAIN; 7384415cd19SGarrett Wollman 7394415cd19SGarrett Wollman tv.tv_sec = _yplib_timeout; 7404415cd19SGarrett Wollman tv.tv_usec = 0; 7414415cd19SGarrett Wollman 7424415cd19SGarrett Wollman yprnk.domain = indomain; 7434415cd19SGarrett Wollman yprnk.map = inmap; 7444415cd19SGarrett Wollman bzero((char *)&yprkv, sizeof yprkv); 7454415cd19SGarrett Wollman 7464415cd19SGarrett Wollman r = clnt_call(ysd->dom_client, YPPROC_FIRST, 7474415cd19SGarrett Wollman xdr_ypreq_nokey, &yprnk, xdr_ypresp_key_val, &yprkv, tv); 7484415cd19SGarrett Wollman if(r != RPC_SUCCESS) { 7494415cd19SGarrett Wollman clnt_perror(ysd->dom_client, "yp_first: clnt_call"); 7502694f9b9SBill Paul _yp_unbind(ysd); 7514415cd19SGarrett Wollman goto again; 7524415cd19SGarrett Wollman } 7530e276383SBill Paul if( !(r=ypprot_err(yprkv.stat)) ) { 7540e276383SBill Paul *outkeylen = yprkv.key.keydat_len; 7554415cd19SGarrett Wollman *outkey = (char *)malloc(*outkeylen+1); 7560e276383SBill Paul bcopy(yprkv.key.keydat_val, *outkey, *outkeylen); 7574415cd19SGarrett Wollman (*outkey)[*outkeylen] = '\0'; 7580e276383SBill Paul *outvallen = yprkv.val.valdat_len; 7594415cd19SGarrett Wollman *outval = (char *)malloc(*outvallen+1); 7600e276383SBill Paul bcopy(yprkv.val.valdat_val, *outval, *outvallen); 7614415cd19SGarrett Wollman (*outval)[*outvallen] = '\0'; 7622694f9b9SBill Paul } 763a169c9b1SBill Paul 764a169c9b1SBill Paul xdr_free(xdr_ypresp_key_val, (char *)&yprkv); 7654415cd19SGarrett Wollman return r; 7664415cd19SGarrett Wollman } 7674415cd19SGarrett Wollman 7684415cd19SGarrett Wollman int 7694415cd19SGarrett Wollman yp_next(indomain, inmap, inkey, inkeylen, outkey, outkeylen, outval, outvallen) 7704415cd19SGarrett Wollman char *indomain; 7714415cd19SGarrett Wollman char *inmap; 7724415cd19SGarrett Wollman char *inkey; 7734415cd19SGarrett Wollman int inkeylen; 7744415cd19SGarrett Wollman char **outkey; 7754415cd19SGarrett Wollman int *outkeylen; 7764415cd19SGarrett Wollman char **outval; 7774415cd19SGarrett Wollman int *outvallen; 7784415cd19SGarrett Wollman { 7794415cd19SGarrett Wollman struct ypresp_key_val yprkv; 7804415cd19SGarrett Wollman struct ypreq_key yprk; 7814415cd19SGarrett Wollman struct dom_binding *ysd; 7824415cd19SGarrett Wollman struct timeval tv; 7834415cd19SGarrett Wollman int r; 7844415cd19SGarrett Wollman 78506643071SBill Paul /* Sanity check */ 78606643071SBill Paul 78706643071SBill Paul if (inkey == NULL || !strlen(inkey) || inkeylen <= 0 || 78806643071SBill Paul inmap == NULL || !strlen(inmap) || 78906643071SBill Paul indomain == NULL || !strlen(indomain)) 79006643071SBill Paul return YPERR_BADARGS; 79106643071SBill Paul 7924415cd19SGarrett Wollman *outkey = *outval = NULL; 7934415cd19SGarrett Wollman *outkeylen = *outvallen = 0; 7944415cd19SGarrett Wollman 7954415cd19SGarrett Wollman again: 7964415cd19SGarrett Wollman if( _yp_dobind(indomain, &ysd) != 0) 7974415cd19SGarrett Wollman return YPERR_DOMAIN; 7984415cd19SGarrett Wollman 7994415cd19SGarrett Wollman tv.tv_sec = _yplib_timeout; 8004415cd19SGarrett Wollman tv.tv_usec = 0; 8014415cd19SGarrett Wollman 8024415cd19SGarrett Wollman yprk.domain = indomain; 8034415cd19SGarrett Wollman yprk.map = inmap; 8040e276383SBill Paul yprk.key.keydat_val = inkey; 8050e276383SBill Paul yprk.key.keydat_len = inkeylen; 8064415cd19SGarrett Wollman bzero((char *)&yprkv, sizeof yprkv); 8074415cd19SGarrett Wollman 8084415cd19SGarrett Wollman r = clnt_call(ysd->dom_client, YPPROC_NEXT, 8094415cd19SGarrett Wollman xdr_ypreq_key, &yprk, xdr_ypresp_key_val, &yprkv, tv); 8104415cd19SGarrett Wollman if(r != RPC_SUCCESS) { 8114415cd19SGarrett Wollman clnt_perror(ysd->dom_client, "yp_next: clnt_call"); 8122694f9b9SBill Paul _yp_unbind(ysd); 8134415cd19SGarrett Wollman goto again; 8144415cd19SGarrett Wollman } 8150e276383SBill Paul if( !(r=ypprot_err(yprkv.stat)) ) { 8160e276383SBill Paul *outkeylen = yprkv.key.keydat_len; 8174415cd19SGarrett Wollman *outkey = (char *)malloc(*outkeylen+1); 8180e276383SBill Paul bcopy(yprkv.key.keydat_val, *outkey, *outkeylen); 8194415cd19SGarrett Wollman (*outkey)[*outkeylen] = '\0'; 8200e276383SBill Paul *outvallen = yprkv.val.valdat_len; 8214415cd19SGarrett Wollman *outval = (char *)malloc(*outvallen+1); 8220e276383SBill Paul bcopy(yprkv.val.valdat_val, *outval, *outvallen); 8234415cd19SGarrett Wollman (*outval)[*outvallen] = '\0'; 8242694f9b9SBill Paul } 825a169c9b1SBill Paul 826a169c9b1SBill Paul xdr_free(xdr_ypresp_key_val, (char *)&yprkv); 8274415cd19SGarrett Wollman return r; 8284415cd19SGarrett Wollman } 8294415cd19SGarrett Wollman 8304415cd19SGarrett Wollman int 8314415cd19SGarrett Wollman yp_all(indomain, inmap, incallback) 8324415cd19SGarrett Wollman char *indomain; 8334415cd19SGarrett Wollman char *inmap; 8344415cd19SGarrett Wollman struct ypall_callback *incallback; 8354415cd19SGarrett Wollman { 8364415cd19SGarrett Wollman struct ypreq_nokey yprnk; 8374415cd19SGarrett Wollman struct dom_binding *ysd; 8384415cd19SGarrett Wollman struct timeval tv; 8394415cd19SGarrett Wollman struct sockaddr_in clnt_sin; 8404415cd19SGarrett Wollman CLIENT *clnt; 84108aff01bSBill Paul u_long status, savstat; 8424415cd19SGarrett Wollman int clnt_sock; 8434415cd19SGarrett Wollman 84406643071SBill Paul /* Sanity check */ 84506643071SBill Paul 84606643071SBill Paul if (indomain == NULL || !strlen(indomain) || 84706643071SBill Paul inmap == NULL || !strlen(inmap)) 84806643071SBill Paul return YPERR_BADARGS; 84906643071SBill Paul 8502694f9b9SBill Paul again: 8512694f9b9SBill Paul 8524415cd19SGarrett Wollman if( _yp_dobind(indomain, &ysd) != 0) 8534415cd19SGarrett Wollman return YPERR_DOMAIN; 8544415cd19SGarrett Wollman 8554415cd19SGarrett Wollman tv.tv_sec = _yplib_timeout; 8564415cd19SGarrett Wollman tv.tv_usec = 0; 8572694f9b9SBill Paul 8582694f9b9SBill Paul /* YPPROC_ALL manufactures its own channel to ypserv using TCP */ 8592694f9b9SBill Paul 8604415cd19SGarrett Wollman clnt_sock = RPC_ANYSOCK; 8614415cd19SGarrett Wollman clnt_sin = ysd->dom_server_addr; 8624415cd19SGarrett Wollman clnt_sin.sin_port = 0; 8634415cd19SGarrett Wollman clnt = clnttcp_create(&clnt_sin, YPPROG, YPVERS, &clnt_sock, 0, 0); 8644415cd19SGarrett Wollman if(clnt==NULL) { 8654415cd19SGarrett Wollman printf("clnttcp_create failed\n"); 8664415cd19SGarrett Wollman return YPERR_PMAP; 8674415cd19SGarrett Wollman } 8684415cd19SGarrett Wollman 8694415cd19SGarrett Wollman yprnk.domain = indomain; 8704415cd19SGarrett Wollman yprnk.map = inmap; 8714415cd19SGarrett Wollman ypresp_allfn = incallback->foreach; 8724415cd19SGarrett Wollman ypresp_data = (void *)incallback->data; 8734415cd19SGarrett Wollman 8742694f9b9SBill Paul if (clnt_call(clnt, YPPROC_ALL, 8752694f9b9SBill Paul xdr_ypreq_nokey, &yprnk, 8762694f9b9SBill Paul xdr_ypresp_all_seq, &status, tv) != RPC_SUCCESS) { 8772694f9b9SBill Paul clnt_perror(ysd->dom_client, "yp_next: clnt_call"); 8782694f9b9SBill Paul clnt_destroy(clnt); 8792694f9b9SBill Paul _yp_unbind(ysd); 8802694f9b9SBill Paul goto again; 8812694f9b9SBill Paul } 8822694f9b9SBill Paul 8834415cd19SGarrett Wollman clnt_destroy(clnt); 88408aff01bSBill Paul savstat = status; 8854415cd19SGarrett Wollman xdr_free(xdr_ypresp_all_seq, (char *)&status); /* not really needed... */ 88608aff01bSBill Paul if(savstat != YP_NOMORE) 88708aff01bSBill Paul return ypprot_err(savstat); 8884415cd19SGarrett Wollman return 0; 8894415cd19SGarrett Wollman } 8904415cd19SGarrett Wollman 8914415cd19SGarrett Wollman int 8924415cd19SGarrett Wollman yp_order(indomain, inmap, outorder) 8934415cd19SGarrett Wollman char *indomain; 8944415cd19SGarrett Wollman char *inmap; 8954415cd19SGarrett Wollman int *outorder; 8964415cd19SGarrett Wollman { 8974415cd19SGarrett Wollman struct dom_binding *ysd; 8984415cd19SGarrett Wollman struct ypresp_order ypro; 8994415cd19SGarrett Wollman struct ypreq_nokey yprnk; 9004415cd19SGarrett Wollman struct timeval tv; 9014415cd19SGarrett Wollman int r; 9024415cd19SGarrett Wollman 90306643071SBill Paul /* Sanity check */ 90406643071SBill Paul 90506643071SBill Paul if (indomain == NULL || !strlen(indomain) || 90606643071SBill Paul inmap == NULL || !strlen(inmap)) 90706643071SBill Paul return YPERR_BADARGS; 90806643071SBill Paul 9094415cd19SGarrett Wollman again: 9104415cd19SGarrett Wollman if( _yp_dobind(indomain, &ysd) != 0) 9114415cd19SGarrett Wollman return YPERR_DOMAIN; 9124415cd19SGarrett Wollman 9134415cd19SGarrett Wollman tv.tv_sec = _yplib_timeout; 9144415cd19SGarrett Wollman tv.tv_usec = 0; 9154415cd19SGarrett Wollman 9164415cd19SGarrett Wollman yprnk.domain = indomain; 9174415cd19SGarrett Wollman yprnk.map = inmap; 9184415cd19SGarrett Wollman 9194415cd19SGarrett Wollman bzero((char *)(char *)&ypro, sizeof ypro); 9204415cd19SGarrett Wollman 9214415cd19SGarrett Wollman r = clnt_call(ysd->dom_client, YPPROC_ORDER, 9224415cd19SGarrett Wollman xdr_ypreq_nokey, &yprnk, xdr_ypresp_order, &ypro, tv); 9239fa75c15SBill Paul 9249fa75c15SBill Paul /* 9259fa75c15SBill Paul * NIS+ in YP compat mode doesn't support the YPPROC_ORDER 9269fa75c15SBill Paul * procedure. 9279fa75c15SBill Paul */ 9289fa75c15SBill Paul if (r == RPC_PROCUNAVAIL) { 9299fa75c15SBill Paul return(YPERR_YPERR); 9309fa75c15SBill Paul } 9319fa75c15SBill Paul 9324415cd19SGarrett Wollman if(r != RPC_SUCCESS) { 9334415cd19SGarrett Wollman clnt_perror(ysd->dom_client, "yp_order: clnt_call"); 9342694f9b9SBill Paul _yp_unbind(ysd); 9354415cd19SGarrett Wollman goto again; 9364415cd19SGarrett Wollman } 9374415cd19SGarrett Wollman 938a169c9b1SBill Paul if( !(r=ypprot_err(ypro.stat)) ) { 9394415cd19SGarrett Wollman *outorder = ypro.ordernum; 9402694f9b9SBill Paul } 941a169c9b1SBill Paul 9424415cd19SGarrett Wollman xdr_free(xdr_ypresp_order, (char *)&ypro); 9432694f9b9SBill Paul return (r); 9444415cd19SGarrett Wollman } 9454415cd19SGarrett Wollman 9464415cd19SGarrett Wollman int 9474415cd19SGarrett Wollman yp_master(indomain, inmap, outname) 9484415cd19SGarrett Wollman char *indomain; 9494415cd19SGarrett Wollman char *inmap; 9504415cd19SGarrett Wollman char **outname; 9514415cd19SGarrett Wollman { 9524415cd19SGarrett Wollman struct dom_binding *ysd; 9534415cd19SGarrett Wollman struct ypresp_master yprm; 9544415cd19SGarrett Wollman struct ypreq_nokey yprnk; 9554415cd19SGarrett Wollman struct timeval tv; 9564415cd19SGarrett Wollman int r; 9574415cd19SGarrett Wollman 95806643071SBill Paul /* Sanity check */ 95906643071SBill Paul 96006643071SBill Paul if (indomain == NULL || !strlen(indomain) || 96106643071SBill Paul inmap == NULL || !strlen(inmap)) 96206643071SBill Paul return YPERR_BADARGS; 9634415cd19SGarrett Wollman again: 9644415cd19SGarrett Wollman if( _yp_dobind(indomain, &ysd) != 0) 9654415cd19SGarrett Wollman return YPERR_DOMAIN; 9664415cd19SGarrett Wollman 9674415cd19SGarrett Wollman tv.tv_sec = _yplib_timeout; 9684415cd19SGarrett Wollman tv.tv_usec = 0; 9694415cd19SGarrett Wollman 9704415cd19SGarrett Wollman yprnk.domain = indomain; 9714415cd19SGarrett Wollman yprnk.map = inmap; 9724415cd19SGarrett Wollman 9734415cd19SGarrett Wollman bzero((char *)&yprm, sizeof yprm); 9744415cd19SGarrett Wollman 9754415cd19SGarrett Wollman r = clnt_call(ysd->dom_client, YPPROC_MASTER, 9764415cd19SGarrett Wollman xdr_ypreq_nokey, &yprnk, xdr_ypresp_master, &yprm, tv); 9774415cd19SGarrett Wollman if(r != RPC_SUCCESS) { 9784415cd19SGarrett Wollman clnt_perror(ysd->dom_client, "yp_master: clnt_call"); 9792694f9b9SBill Paul _yp_unbind(ysd); 9804415cd19SGarrett Wollman goto again; 9814415cd19SGarrett Wollman } 9822694f9b9SBill Paul 9830e276383SBill Paul if( !(r=ypprot_err(yprm.stat)) ) { 9840e276383SBill Paul *outname = (char *)strdup(yprm.peer); 9852694f9b9SBill Paul } 986a169c9b1SBill Paul 987a169c9b1SBill Paul xdr_free(xdr_ypresp_master, (char *)&yprm); 9882694f9b9SBill Paul return (r); 9894415cd19SGarrett Wollman } 990b9729ac2SBill Paul int 9914415cd19SGarrett Wollman yp_maplist(indomain, outmaplist) 9924415cd19SGarrett Wollman char *indomain; 9934415cd19SGarrett Wollman struct ypmaplist **outmaplist; 9944415cd19SGarrett Wollman { 9954415cd19SGarrett Wollman struct dom_binding *ysd; 9964415cd19SGarrett Wollman struct ypresp_maplist ypml; 9974415cd19SGarrett Wollman struct timeval tv; 9984415cd19SGarrett Wollman int r; 9994415cd19SGarrett Wollman 100006643071SBill Paul /* Sanity check */ 100106643071SBill Paul 100206643071SBill Paul if (indomain == NULL || !strlen(indomain)) 100306643071SBill Paul return YPERR_BADARGS; 100406643071SBill Paul 10054415cd19SGarrett Wollman again: 10064415cd19SGarrett Wollman if( _yp_dobind(indomain, &ysd) != 0) 10074415cd19SGarrett Wollman return YPERR_DOMAIN; 10084415cd19SGarrett Wollman 10094415cd19SGarrett Wollman tv.tv_sec = _yplib_timeout; 10104415cd19SGarrett Wollman tv.tv_usec = 0; 10114415cd19SGarrett Wollman 10124415cd19SGarrett Wollman bzero((char *)&ypml, sizeof ypml); 10134415cd19SGarrett Wollman 10144415cd19SGarrett Wollman r = clnt_call(ysd->dom_client, YPPROC_MAPLIST, 10159d80b1ddSBill Paul xdr_domainname,(char *)&indomain,xdr_ypresp_maplist,&ypml,tv); 10164415cd19SGarrett Wollman if (r != RPC_SUCCESS) { 10174415cd19SGarrett Wollman clnt_perror(ysd->dom_client, "yp_maplist: clnt_call"); 10182694f9b9SBill Paul _yp_unbind(ysd); 10194415cd19SGarrett Wollman goto again; 10204415cd19SGarrett Wollman } 1021a169c9b1SBill Paul if( !(r=ypprot_err(ypml.stat)) ) { 10220e276383SBill Paul *outmaplist = ypml.maps; 10232694f9b9SBill Paul } 10242694f9b9SBill Paul 1025a169c9b1SBill Paul /* NO: xdr_free(xdr_ypresp_maplist, &ypml);*/ 10262694f9b9SBill Paul return (r); 10274415cd19SGarrett Wollman } 10284415cd19SGarrett Wollman 10294415cd19SGarrett Wollman char * 10304415cd19SGarrett Wollman yperr_string(incode) 10314415cd19SGarrett Wollman int incode; 10324415cd19SGarrett Wollman { 10334415cd19SGarrett Wollman static char err[80]; 10344415cd19SGarrett Wollman 10354415cd19SGarrett Wollman switch(incode) { 10364415cd19SGarrett Wollman case 0: 10374415cd19SGarrett Wollman return "Success"; 10384415cd19SGarrett Wollman case YPERR_BADARGS: 10394415cd19SGarrett Wollman return "Request arguments bad"; 10404415cd19SGarrett Wollman case YPERR_RPC: 10414415cd19SGarrett Wollman return "RPC failure"; 10424415cd19SGarrett Wollman case YPERR_DOMAIN: 10434415cd19SGarrett Wollman return "Can't bind to server which serves this domain"; 10444415cd19SGarrett Wollman case YPERR_MAP: 10454415cd19SGarrett Wollman return "No such map in server's domain"; 10464415cd19SGarrett Wollman case YPERR_KEY: 10474415cd19SGarrett Wollman return "No such key in map"; 10484415cd19SGarrett Wollman case YPERR_YPERR: 10494415cd19SGarrett Wollman return "YP server error"; 10504415cd19SGarrett Wollman case YPERR_RESRC: 10514415cd19SGarrett Wollman return "Local resource allocation failure"; 10524415cd19SGarrett Wollman case YPERR_NOMORE: 10534415cd19SGarrett Wollman return "No more records in map database"; 10544415cd19SGarrett Wollman case YPERR_PMAP: 10554415cd19SGarrett Wollman return "Can't communicate with portmapper"; 10564415cd19SGarrett Wollman case YPERR_YPBIND: 10574415cd19SGarrett Wollman return "Can't communicate with ypbind"; 10584415cd19SGarrett Wollman case YPERR_YPSERV: 10594415cd19SGarrett Wollman return "Can't communicate with ypserv"; 10604415cd19SGarrett Wollman case YPERR_NODOM: 10614415cd19SGarrett Wollman return "Local domain name not set"; 10624415cd19SGarrett Wollman case YPERR_BADDB: 10634415cd19SGarrett Wollman return "Server data base is bad"; 10644415cd19SGarrett Wollman case YPERR_VERS: 10654415cd19SGarrett Wollman return "YP server version mismatch - server can't supply service."; 10664415cd19SGarrett Wollman case YPERR_ACCESS: 10674415cd19SGarrett Wollman return "Access violation"; 10684415cd19SGarrett Wollman case YPERR_BUSY: 10694415cd19SGarrett Wollman return "Database is busy"; 10704415cd19SGarrett Wollman } 10714415cd19SGarrett Wollman sprintf(err, "YP unknown error %d\n", incode); 10724415cd19SGarrett Wollman return err; 10734415cd19SGarrett Wollman } 10744415cd19SGarrett Wollman 10754415cd19SGarrett Wollman int 10764415cd19SGarrett Wollman ypprot_err(incode) 10774415cd19SGarrett Wollman unsigned int incode; 10784415cd19SGarrett Wollman { 10794415cd19SGarrett Wollman switch(incode) { 10804415cd19SGarrett Wollman case YP_TRUE: 10814415cd19SGarrett Wollman return 0; 10824415cd19SGarrett Wollman case YP_FALSE: 10834415cd19SGarrett Wollman return YPERR_YPBIND; 10844415cd19SGarrett Wollman case YP_NOMORE: 10854415cd19SGarrett Wollman return YPERR_NOMORE; 10864415cd19SGarrett Wollman case YP_NOMAP: 10874415cd19SGarrett Wollman return YPERR_MAP; 10884415cd19SGarrett Wollman case YP_NODOM: 1089bc8e373cSBill Paul return YPERR_DOMAIN; 10904415cd19SGarrett Wollman case YP_NOKEY: 10914415cd19SGarrett Wollman return YPERR_KEY; 10924415cd19SGarrett Wollman case YP_BADOP: 10934415cd19SGarrett Wollman return YPERR_YPERR; 10944415cd19SGarrett Wollman case YP_BADDB: 10954415cd19SGarrett Wollman return YPERR_BADDB; 10964415cd19SGarrett Wollman case YP_YPERR: 10974415cd19SGarrett Wollman return YPERR_YPERR; 10984415cd19SGarrett Wollman case YP_BADARGS: 10994415cd19SGarrett Wollman return YPERR_BADARGS; 11004415cd19SGarrett Wollman case YP_VERS: 11014415cd19SGarrett Wollman return YPERR_VERS; 11024415cd19SGarrett Wollman } 11034415cd19SGarrett Wollman return YPERR_YPERR; 11044415cd19SGarrett Wollman } 11054415cd19SGarrett Wollman 11064415cd19SGarrett Wollman int 11074415cd19SGarrett Wollman _yp_check(dom) 11084415cd19SGarrett Wollman char **dom; 11094415cd19SGarrett Wollman { 11104415cd19SGarrett Wollman char *unused; 11114415cd19SGarrett Wollman 11124415cd19SGarrett Wollman if( _yp_domain[0]=='\0' ) 11134415cd19SGarrett Wollman if( yp_get_default_domain(&unused) ) 11144415cd19SGarrett Wollman return 0; 11154415cd19SGarrett Wollman 11164415cd19SGarrett Wollman if(dom) 11174415cd19SGarrett Wollman *dom = _yp_domain; 11184415cd19SGarrett Wollman 11190f98415eSBill Paul if( yp_bind(_yp_domain)==0 ) { 11200f98415eSBill Paul yp_unbind(_yp_domain); 11214415cd19SGarrett Wollman return 1; 11220f98415eSBill Paul } 11234415cd19SGarrett Wollman return 0; 11244415cd19SGarrett Wollman } 1125