[BACK]Return to yplib.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libc / yp

Annotation of src/lib/libc/yp/yplib.c, Revision 1.42

1.42    ! lukem       1: /*     $NetBSD: yplib.c,v 1.41 2004/05/27 18:41:11 christos Exp $       */
1.14      cgd         2:
1.3       deraadt     3: /*
1.8       deraadt     4:  * Copyright (c) 1992, 1993 Theo de Raadt <deraadt@fsa.ca>
1.3       deraadt     5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
                     17:  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     18:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     19:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
                     20:  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     21:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     22:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     23:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     24:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     25:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     26:  * SUCH DAMAGE.
                     27:  */
                     28:
1.29      christos   29: #include <sys/cdefs.h>
1.17      jtc        30: #if defined(LIBC_SCCS) && !defined(lint)
1.42    ! lukem      31: __RCSID("$NetBSD: yplib.c,v 1.41 2004/05/27 18:41:11 christos Exp $");
1.3       deraadt    32: #endif
                     33:
1.30      jtc        34: #include "namespace.h"
1.42    ! lukem      35: #include "reentrant.h"
        !            36:
1.1       deraadt    37: #include <sys/param.h>
                     38: #include <sys/socket.h>
                     39: #include <sys/file.h>
1.7       deraadt    40: #include <sys/uio.h>
1.34      lukem      41:
1.28      lukem      42: #include <arpa/nameser.h>
1.34      lukem      43:
                     44: #include <assert.h>
1.1       deraadt    45: #include <errno.h>
                     46: #include <stdio.h>
1.9       jtc        47: #include <stdlib.h>
1.1       deraadt    48: #include <string.h>
1.9       jtc        49: #include <unistd.h>
1.34      lukem      50:
1.1       deraadt    51: #include <rpc/rpc.h>
                     52: #include <rpc/xdr.h>
                     53: #include <rpcsvc/yp_prot.h>
                     54: #include <rpcsvc/ypclnt.h>
1.29      christos   55: #include "local.h"
1.1       deraadt    56:
1.13      deraadt    57: #define BINDINGDIR     "/var/yp/binding"
                     58: #define YPBINDLOCK     "/var/run/ypbind.lock"
1.1       deraadt    59:
                     60: struct dom_binding *_ypbindlist;
1.21      jtc        61: char _yp_domain[MAXHOSTNAMELEN];
1.1       deraadt    62:
1.26      thorpej    63: #define YPLIB_TIMEOUT          10
                     64: #define YPLIB_RPC_RETRIES      4
                     65:
                     66: struct timeval _yplib_timeout = { YPLIB_TIMEOUT, 0 };
                     67: struct timeval _yplib_rpc_timeout = { YPLIB_TIMEOUT / YPLIB_RPC_RETRIES,
                     68:        1000000 * (YPLIB_TIMEOUT % YPLIB_RPC_RETRIES) / YPLIB_RPC_RETRIES };
1.23      christos   69: int _yplib_nerrs = 5;
1.16      christos   70:
1.30      jtc        71: #ifdef __weak_alias
1.36      mycroft    72: __weak_alias(yp_bind, _yp_bind)
                     73: __weak_alias(yp_unbind, _yp_unbind)
                     74: __weak_alias(yp_get_default_domain, _yp_get_default_domain)
1.30      jtc        75: #endif
                     76:
1.41      christos   77: #ifdef _REENTRANT
                     78: static         mutex_t                 _ypmutex = MUTEX_INITIALIZER;
                     79: #define YPLOCK()               mutex_lock(&_ypmutex)
                     80: #define YPUNLOCK()             mutex_unlock(&_ypmutex)
                     81: #else
                     82: #define YPLOCK()
                     83: #define YPUNLOCK()
                     84: #endif
                     85:
1.1       deraadt    86: int
                     87: _yp_dobind(dom, ypdb)
1.16      christos   88:        const char     *dom;
                     89:        struct dom_binding **ypdb;
1.1       deraadt    90: {
1.16      christos   91:        static int      pid = -1;
                     92:        char            path[MAXPATHLEN];
1.1       deraadt    93:        struct dom_binding *ysd, *ysd2;
                     94:        struct ypbind_resp ypbr;
                     95:        struct sockaddr_in clnt_sin;
1.16      christos   96:        int             clnt_sock, fd, gpid;
                     97:        CLIENT         *client;
1.38      thorpej    98:        int             new = 0;
1.25      christos   99:        int             nerrs = 0;
1.38      thorpej   100:        ssize_t         r;
1.1       deraadt   101:
1.28      lukem     102:        if (dom == NULL || *dom == '\0')
1.22      jtc       103:                return YPERR_BADARGS;
                    104:
1.13      deraadt   105:        /*
                    106:         * test if YP is running or not
                    107:         */
1.16      christos  108:        if ((fd = open(YPBINDLOCK, O_RDONLY)) == -1)
1.13      deraadt   109:                return YPERR_YPBIND;
1.16      christos  110:        if (!(flock(fd, LOCK_EX | LOCK_NB) == -1 && errno == EWOULDBLOCK)) {
                    111:                (void)close(fd);
1.13      deraadt   112:                return YPERR_YPBIND;
                    113:        }
1.16      christos  114:        (void)close(fd);
1.13      deraadt   115:
1.1       deraadt   116:        gpid = getpid();
1.16      christos  117:        if (!(pid == -1 || pid == gpid)) {
1.1       deraadt   118:                ysd = _ypbindlist;
1.16      christos  119:                while (ysd) {
                    120:                        if (ysd->dom_client)
1.1       deraadt   121:                                clnt_destroy(ysd->dom_client);
                    122:                        ysd2 = ysd->dom_pnext;
                    123:                        free(ysd);
                    124:                        ysd = ysd2;
                    125:                }
                    126:                _ypbindlist = NULL;
                    127:        }
                    128:        pid = gpid;
                    129:
1.16      christos  130:        if (ypdb != NULL)
1.1       deraadt   131:                *ypdb = NULL;
                    132:
1.16      christos  133:        for (ysd = _ypbindlist; ysd; ysd = ysd->dom_pnext)
                    134:                if (strcmp(dom, ysd->dom_domain) == 0)
1.1       deraadt   135:                        break;
1.16      christos  136:        if (ysd == NULL) {
                    137:                if ((ysd = malloc(sizeof *ysd)) == NULL)
                    138:                        return YPERR_YPERR;
                    139:                (void)memset(ysd, 0, sizeof *ysd);
1.1       deraadt   140:                ysd->dom_socket = -1;
                    141:                ysd->dom_vers = 0;
                    142:                new = 1;
                    143:        }
                    144: again:
1.16      christos  145:        if (ysd->dom_vers == 0) {
                    146:                (void) snprintf(path, sizeof(path), "%s/%s.%d",
                    147:                                BINDINGDIR, dom, 2);
                    148:                if ((fd = open(path, O_RDONLY)) == -1) {
                    149:                        /*
                    150:                         * no binding file, YP is dead, or not yet fully
                    151:                         * alive.
                    152:                         */
1.11      deraadt   153:                        goto trynet;
1.1       deraadt   154:                }
1.16      christos  155:                if (flock(fd, LOCK_EX | LOCK_NB) == -1 &&
                    156:                    errno == EWOULDBLOCK) {
                    157:                        struct iovec    iov[2];
1.7       deraadt   158:                        struct ypbind_resp ybr;
1.16      christos  159:                        u_short         ypb_port;
                    160:                        struct ypbind_binding *bn;
1.7       deraadt   161:
1.32      mycroft   162:                        iov[0].iov_base = &ypb_port;
1.7       deraadt   163:                        iov[0].iov_len = sizeof ypb_port;
1.32      mycroft   164:                        iov[1].iov_base = &ybr;
1.7       deraadt   165:                        iov[1].iov_len = sizeof ybr;
                    166:
                    167:                        r = readv(fd, iov, 2);
1.38      thorpej   168:                        if (r != (ssize_t)(iov[0].iov_len + iov[1].iov_len)) {
1.16      christos  169:                                (void)close(fd);
1.1       deraadt   170:                                ysd->dom_vers = -1;
                    171:                                goto again;
                    172:                        }
1.16      christos  173:                        (void)memset(&ysd->dom_server_addr, 0,
                    174:                                     sizeof ysd->dom_server_addr);
                    175:                        ysd->dom_server_addr.sin_len =
                    176:                                sizeof(struct sockaddr_in);
1.7       deraadt   177:                        ysd->dom_server_addr.sin_family = AF_INET;
1.16      christos  178:                        bn = &ybr.ypbind_respbody.ypbind_bindinfo;
1.15      mycroft   179:                        ysd->dom_server_addr.sin_port =
1.16      christos  180:                                bn->ypbind_binding_port;
                    181:
1.7       deraadt   182:                        ysd->dom_server_addr.sin_addr =
1.16      christos  183:                                bn->ypbind_binding_addr;
1.7       deraadt   184:
1.1       deraadt   185:                        ysd->dom_server_port = ysd->dom_server_addr.sin_port;
1.16      christos  186:                        (void)close(fd);
1.1       deraadt   187:                        goto gotit;
                    188:                } else {
                    189:                        /* no lock on binding file, YP is dead. */
1.16      christos  190:                        (void)close(fd);
                    191:                        if (new)
1.1       deraadt   192:                                free(ysd);
                    193:                        return YPERR_YPBIND;
                    194:                }
                    195:        }
1.11      deraadt   196: trynet:
1.16      christos  197:        if (ysd->dom_vers == -1 || ysd->dom_vers == 0) {
                    198:                struct ypbind_binding *bn;
                    199:                (void)memset(&clnt_sin, 0, sizeof clnt_sin);
1.15      mycroft   200:                clnt_sin.sin_len = sizeof(struct sockaddr_in);
1.1       deraadt   201:                clnt_sin.sin_family = AF_INET;
                    202:                clnt_sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
                    203:
                    204:                clnt_sock = RPC_ANYSOCK;
1.16      christos  205:                client = clnttcp_create(&clnt_sin, YPBINDPROG, YPBINDVERS,
                    206:                                        &clnt_sock, 0, 0);
                    207:                if (client == NULL) {
1.1       deraadt   208:                        clnt_pcreateerror("clnttcp_create");
1.16      christos  209:                        if (new)
1.1       deraadt   210:                                free(ysd);
                    211:                        return YPERR_YPBIND;
                    212:                }
1.37      christos  213:                r = clnt_call(client, (rpcproc_t)YPBINDPROC_DOMAIN,
1.33      christos  214:                    (xdrproc_t)xdr_ypdomain_wrap_string, &dom,
                    215:                    (xdrproc_t)xdr_ypbind_resp, &ypbr, _yplib_timeout);
1.16      christos  216:                if (r != RPC_SUCCESS) {
1.25      christos  217:                        if (new == 0 && ++nerrs == _yplib_nerrs) {
                    218:                                nerrs = 0;
1.12      deraadt   219:                                fprintf(stderr,
1.16      christos  220:                    "YP server for domain %s not responding, still trying\n",
1.25      christos  221:                                    dom);
                    222:                        }
1.1       deraadt   223:                        clnt_destroy(client);
                    224:                        ysd->dom_vers = -1;
                    225:                        goto again;
                    226:                }
                    227:                clnt_destroy(client);
                    228:
1.16      christos  229:                (void)memset(&ysd->dom_server_addr, 0,
                    230:                             sizeof ysd->dom_server_addr);
1.15      mycroft   231:                ysd->dom_server_addr.sin_len = sizeof(struct sockaddr_in);
1.1       deraadt   232:                ysd->dom_server_addr.sin_family = AF_INET;
1.16      christos  233:                bn = &ypbr.ypbind_respbody.ypbind_bindinfo;
1.1       deraadt   234:                ysd->dom_server_addr.sin_port =
1.16      christos  235:                        bn->ypbind_binding_port;
1.1       deraadt   236:                ysd->dom_server_addr.sin_addr.s_addr =
1.16      christos  237:                        bn->ypbind_binding_addr.s_addr;
1.1       deraadt   238:                ysd->dom_server_port =
1.16      christos  239:                        bn->ypbind_binding_port;
1.1       deraadt   240: gotit:
                    241:                ysd->dom_vers = YPVERS;
1.39      itojun    242:                (void)strlcpy(ysd->dom_domain, dom, sizeof(ysd->dom_domain));
1.1       deraadt   243:        }
1.16      christos  244:        if (ysd->dom_client)
1.1       deraadt   245:                clnt_destroy(ysd->dom_client);
                    246:        ysd->dom_socket = RPC_ANYSOCK;
                    247:        ysd->dom_client = clntudp_create(&ysd->dom_server_addr,
1.26      thorpej   248:            YPPROG, YPVERS, _yplib_rpc_timeout, &ysd->dom_socket);
1.16      christos  249:        if (ysd->dom_client == NULL) {
1.1       deraadt   250:                clnt_pcreateerror("clntudp_create");
                    251:                ysd->dom_vers = -1;
                    252:                goto again;
                    253:        }
1.16      christos  254:        if (fcntl(ysd->dom_socket, F_SETFD, 1) == -1)
1.1       deraadt   255:                perror("fcntl: F_SETFD");
                    256:
1.16      christos  257:        if (new) {
1.1       deraadt   258:                ysd->dom_pnext = _ypbindlist;
                    259:                _ypbindlist = ysd;
                    260:        }
1.16      christos  261:        if (ypdb != NULL)
1.1       deraadt   262:                *ypdb = ysd;
                    263:        return 0;
                    264: }
                    265:
1.20      jtc       266: void
1.30      jtc       267: __yp_unbind(ypb)
1.16      christos  268:        struct dom_binding *ypb;
1.1       deraadt   269: {
1.34      lukem     270:
                    271:        _DIAGASSERT(ypb != NULL);
                    272:
1.1       deraadt   273:        clnt_destroy(ypb->dom_client);
                    274:        ypb->dom_client = NULL;
                    275:        ypb->dom_socket = -1;
                    276: }
                    277:
                    278: int
                    279: yp_bind(dom)
1.16      christos  280:        const char     *dom;
1.1       deraadt   281: {
1.28      lukem     282:        if (_yp_invalid_domain(dom))
                    283:                return YPERR_BADARGS;
                    284:
1.1       deraadt   285:        return _yp_dobind(dom, NULL);
                    286: }
                    287:
                    288: void
                    289: yp_unbind(dom)
1.16      christos  290:        const char     *dom;
1.1       deraadt   291: {
                    292:        struct dom_binding *ypb, *ypbp;
                    293:
1.28      lukem     294:        if (_yp_invalid_domain(dom))
                    295:                return;
                    296:
1.1       deraadt   297:        ypbp = NULL;
1.16      christos  298:        for (ypb = _ypbindlist; ypb; ypb = ypb->dom_pnext) {
                    299:                if (strcmp(dom, ypb->dom_domain) == 0) {
1.1       deraadt   300:                        clnt_destroy(ypb->dom_client);
1.16      christos  301:                        if (ypbp)
1.1       deraadt   302:                                ypbp->dom_pnext = ypb->dom_pnext;
                    303:                        else
                    304:                                _ypbindlist = ypb->dom_pnext;
                    305:                        free(ypb);
                    306:                        return;
                    307:                }
                    308:                ypbp = ypb;
                    309:        }
                    310:        return;
                    311: }
                    312:
                    313: int
                    314: yp_get_default_domain(domp)
1.16      christos  315:        char          **domp;
1.1       deraadt   316: {
1.34      lukem     317:        if (domp == NULL)
                    318:                return YPERR_BADARGS;
1.1       deraadt   319:        *domp = NULL;
1.16      christos  320:        if (_yp_domain[0] == '\0')
                    321:                if (getdomainname(_yp_domain, sizeof _yp_domain))
1.1       deraadt   322:                        return YPERR_NODOM;
                    323:        *domp = _yp_domain;
                    324:        return 0;
                    325: }
                    326:
                    327: int
                    328: _yp_check(dom)
1.16      christos  329:        char          **dom;
1.1       deraadt   330: {
1.16      christos  331:        char           *unused;
1.41      christos  332:        int             good;
                    333:
                    334:        YPLOCK();
1.1       deraadt   335:
1.16      christos  336:        if (_yp_domain[0] == '\0')
1.41      christos  337:                if (yp_get_default_domain(&unused)) {
                    338:                        good = 0;
                    339:                        goto done;
                    340:                }
1.16      christos  341:        if (dom)
1.1       deraadt   342:                *dom = _yp_domain;
                    343:
1.41      christos  344:        good = yp_bind(_yp_domain) == 0;
                    345: done:
                    346:        YPUNLOCK();
                    347:        return good;
1.28      lukem     348: }
                    349:
                    350: /*
1.31      lukem     351:  * _yp_invalid_domain: check if given domainname isn't legal.
1.28      lukem     352:  * returns non-zero if invalid
                    353:  */
                    354: int
                    355: _yp_invalid_domain(dom)
                    356:        const char *dom;
                    357: {
                    358:        if (dom == NULL || *dom == '\0')
                    359:                return 1;
                    360:
1.31      lukem     361:        if (strlen(dom) > YPMAXDOMAIN)
                    362:                return 1;
1.28      lukem     363:
1.31      lukem     364:        if (strchr(dom, '/') != NULL)
1.1       deraadt   365:                return 1;
1.31      lukem     366:
1.1       deraadt   367:        return 0;
                    368: }

CVSweb <webmaster@jp.NetBSD.org>