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