⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 yp_bind.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
 * otherwise. */static boolcheck_binding(domain, binding)	char *domain;	struct dom_binding **binding;{	struct dom_binding *pdomb;	struct sockaddr_in local_name;	int local_name_len;	for (pdomb = bound_domains; pdomb != NULL; pdomb = pdomb->dom_pnext) {		if (strcmp(domain, pdomb->dom_domain) == 0) {			local_name_len = sizeof(local_name);			if ((getsockname(pdomb->dom_socket,			    (struct sockaddr *) &local_name,			    &local_name_len) != 0)  ||			    (local_name.sin_family != AF_INET) ||			    (local_name.sin_port != pdomb->dom_local_port) ) {				yp_unbind(domain);				break;			} else {				*binding = pdomb;				return (TRUE);			}		}	}	return (FALSE);}/* * This checks whether the portmapper is up.  If the connect fails, the * portmapper is dead.  As a side effect, the pmapper sockaddr_in is * initialized. The connection is not used for anything else, so it is * immediately closed. * * If there is a valid binding file we assume pmap is up. */static boolcheck_pmap_up(pmapper, err)	struct sockaddr_in *pmapper;	int *err;{	int sokt;	int status;	pmapper->sin_addr = my_addr;	pmapper->sin_family = AF_INET;	pmapper->sin_port = PMAPPORT;	bzero(pmapper->sin_zero, 8);	if (bf == -1) { /* No valid binding */		sokt =  socket(AF_INET, SOCK_STREAM, 0);		if (sokt == -1) {			*err = YPERR_RESRC;			return (FALSE);		}		if ((status = connect(sokt, (struct sockaddr *) pmapper,		    sizeof(struct sockaddr_in))) < 0) {			(void) close(sokt);			*err = YPERR_PMAP;			return (FALSE);		}		(void) close(sokt);	}	return (TRUE);}/* * This checks whether ypbind is up.  If the bind succeeds, ypbind is dead, * because the binder port returned from portmap should already be in use. * There are two side effects.  The ypbind sockaddr_in is initialized. If * the function returns FALSE, the global binder_port will be set to 0. */static boolcheck_binder_up(ypbinder, err)	struct sockaddr_in *ypbinder;	int *err;{	int sokt;	int status;	if (binder_port == 0) {		return (FALSE);	}	ypbinder->sin_addr = my_addr;	ypbinder->sin_family = AF_INET;	ypbinder->sin_port = htons(binder_port);	bzero(ypbinder->sin_zero, 8);	sokt =  socket(AF_INET, SOCK_DGRAM, 0); /* Throw-away socket */	if (sokt == -1) {		binder_port = 0;		*err = YPERR_RESRC;		return (FALSE);	}	errno = 0;	status = bind(sokt, (struct sockaddr *) ypbinder,	    sizeof(struct sockaddr_in));	(void) close(sokt);	if (status == -1) {		if (errno == EADDRINUSE) {			/*			 * since we cannot grab the port, ypbind must be			 * up and healthy.			 */			return (TRUE);		}		if ((errno == EACCES) &&		    (binder_port < IPPORT_RESERVED) &&		    (geteuid() != 0)) {			/*			 * The port is priviledged.  This must be "secure"			 * unix where have to use the yelow pages.			 */			return (TRUE);		}	}	binder_port = 0;	*err = YPERR_YPBIND;	return (FALSE);}/* * This asks the portmapper for addressing info for ypbind speaking a passed * program version number.  If it gets that info, the port number is stashed * in binder_port, but binder_port will be set to 0 when talk2_pmap returns * anything except BS_OK.  If the RPC call to the portmapper failed, the * current process will be put to sleep for _ypsleeptime seconds before * this function returns. */static enum bind_statustalk2_pmap(pmapper, vers, err)	struct sockaddr_in *pmapper;	int vers;	int *err;{	int sokt;	CLIENT *client;	struct pmap portmap;	enum clnt_stat clnt_stat;	binder_port = 0;	portmap.pm_prog = YPBINDPROG;	portmap.pm_vers = vers;	portmap.pm_prot = IPPROTO_UDP;	portmap.pm_port = 0;		/* Don't care */	sokt = RPC_ANYSOCK;	if ((client = clntudp_bufcreate(pmapper, PMAPPROG, PMAPVERS,	    bind_intertry, &sokt, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE))  == NULL) {		*err = YPERR_RPC;		return (BS_BAGIT);	}	clnt_stat = (enum clnt_stat) clnt_call(client, PMAPPROC_GETPORT,	    xdr_pmap, &portmap, xdr_u_long, &binder_port, bind_timeout);	clnt_destroy(client);	(void) close(sokt);	if (clnt_stat  == RPC_SUCCESS) {		if (binder_port != 0) {			return (BS_OK);		} else {			*err = YPERR_YPBIND;			return (BS_BAGIT);		}	} else {		(void) sleep(_ypsleeptime);		*err = YPERR_RPC;		return (BS_RETRY);	}}/* * This talks to the local ypbind process, and asks for a binding for the * passed domain.  As a side effect, if a version mismatch is detected, the * ypbind program version number may be changed to the old version.  In the * success case, the ypbind response will be returned as it was loaded by * ypbind - that is, containing a valid binding.  If the RPC call to ypbind * failed, the current process will be put to sleep for _ypsleeptime seconds * before this function returns. */static enum bind_statustalk2_binder(ypbinder, vers, tries, ppdomain, ypbind_resp, err)	struct sockaddr_in *ypbinder;	int *vers;	int tries;	char **ppdomain;	struct ypbind_resp *ypbind_resp;	int *err;{	int sokt;	CLIENT *client;	enum clnt_stat clnt_stat;	if (bfname==0) bfinvalid=TRUE;	if ((bf != -1) && !bfinvalid) {		/* this should work but we check anyway */#ifdef	MAP_STUFF			if (binderfilemap){			bcopy( &binderfilemap[1],ypbind_resp,sizeof(struct ypbind_resp));			clnt_stat = RPC_SUCCESS;			}	       else{#endif		bf = open(bfname,O_RDONLY);		if (bf != -1) {			if (flock(bf,LOCK_EX+LOCK_NB) != 0) {				lseek(bf,(long)(sizeof(u_short)),L_SET);	    			read(bf,ypbind_resp,sizeof(struct ypbind_resp));		    		close(bf);       		     		clnt_stat = RPC_SUCCESS;			}	  	}#ifdef		MAP_STUFF		}#endif	} else {		sokt = RPC_ANYSOCK;		if ((*vers == YPBINDVERS) && (tries > MAX_TRIES_FOR_NEW_YP) )			*vers = YPBINDOLDVERS;		if ((client = clntudp_bufcreate(ypbinder, YPBINDPROG, *vers,		    bind_intertry, &sokt, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE))  == NULL) {			*err = YPERR_RPC;			return (BS_BAGIT);		}		clnt_stat = (enum clnt_stat)clnt_call(client, YPBINDPROC_DOMAIN,		    xdr_ypdomain_wrap_string, ppdomain, xdr_ypbind_resp,		    ypbind_resp, bind_timeout);		clnt_destroy(client);		(void) close(sokt);		bfinvalid = !(clnt_stat == RPC_SUCCESS);	}	if (clnt_stat == RPC_SUCCESS) {		if (ypbind_resp->ypbind_status == YPBIND_SUCC_VAL) {			/* Binding successfully returned from ypbind */			return (BS_OK);		} else {			if ( ((*vers == YPBINDVERS) &&			    (tries < MAX_TRIES_FOR_NEW_YP)) ||			    (*vers == YPBINDOLDVERS) ) {				(void) sleep(_ypsleeptime);			}			bfinvalid = TRUE;			*err = YPERR_DOMAIN;			return (BS_RETRY);		}	} else {		bfinvalid = TRUE;		if (clnt_stat == RPC_PROGVERSMISMATCH) {			if (*vers == YPBINDOLDVERS) {				*err = YPERR_YPBIND;				return (BS_BAGIT);			} else {				*vers = YPBINDOLDVERS;			}		} else {			(void) sleep(_ypsleeptime);			binder_port = 0;		}		*err = YPERR_RPC;		return (BS_RETRY);	}}/* * This handles all the conversation with the portmapper to find the port * ypbind is listening on.  If binder_port is already non-zero, this returns * BS_OK immediately without changing anything. */static enum bind_statusget_binder_port(vers, err)	int vers;			/* !ypbind! program version number */	int *err;{	struct sockaddr_in pmapper;	if (binder_port) {		return (BS_OK);	}	if (!check_pmap_up(&pmapper, err) ) {		return (BS_BAGIT);	}	return (talk2_pmap(&pmapper, vers, err) );}/* * This allocates some memory for a domain binding, initialize it, and * returns a pointer to it.  Based on the program version we ended up * talking to ypbind with, fill out an opvector of appropriate protocol * modules. */static struct dom_binding *load_dom_binding(ypbind_resp, vers, domain, err)	struct ypbind_resp *ypbind_resp;	int vers;	char *domain;	int *err;{	struct dom_binding *pdomb;	struct sockaddr_in dummy;	/* To get a port bound to socket */	struct sockaddr_in local_name;	int local_name_len = sizeof(struct sockaddr_in);	pdomb = (struct dom_binding *) NULL;	if ((pdomb = (struct dom_binding *) malloc(sizeof(struct dom_binding)))		== NULL) {		(void) syslog(LOG_ERR, "load_dom_binding:  malloc failure.");		*err = YPERR_RESRC;		return (struct dom_binding *) (NULL);	}	pdomb->dom_server_addr.sin_addr =	    ypbind_resp->ypbind_respbody.ypbind_bindinfo.ypbind_binding_addr;	pdomb->dom_server_addr.sin_family = AF_INET;	pdomb->dom_server_addr.sin_port =	    ypbind_resp->ypbind_respbody.ypbind_bindinfo.ypbind_binding_port;	bzero(pdomb->dom_server_addr.sin_zero, 8);	pdomb->dom_server_port =	    ypbind_resp->ypbind_respbody.ypbind_bindinfo.ypbind_binding_port;	pdomb->dom_socket = RPC_ANYSOCK;	pdomb->dom_vers = (vers == YPBINDOLDVERS) ? YPOLDVERS : YPVERS;	/*	 * Open up a udp path to the server, which will remain active globally.	 */	if ((pdomb->dom_client = clntudp_bufcreate(&(pdomb->dom_server_addr),	    YPPROG, ((vers == YPBINDVERS) ? YPVERS : YPOLDVERS) ,	    ypserv_intertry, &(pdomb->dom_socket), RPCSMALLMSGSIZE, YPMSGSZ))	    == NULL) {		free((char *) pdomb);		*err = YPERR_RPC;		return (struct dom_binding *) (NULL);	}	/*	 * Bind the socket to a bogus address so a port gets allocated for	 * the socket, but so that sendto will still work.	 */	(void) fcntl(pdomb->dom_socket, F_SETFD, 1);	bzero((char *)&dummy, sizeof (dummy));	dummy.sin_family = AF_INET;	(void)bind(pdomb->dom_socket, (struct sockaddr *)&dummy, sizeof(dummy));	/*	 * Remember the bound port number	 */	if (getsockname(pdomb->dom_socket, (struct sockaddr *) &local_name,	    &local_name_len) == 0) {		pdomb->dom_local_port = local_name.sin_port;	} else {		free((char *) pdomb);		*err = YPERR_YPERR;		return (struct dom_binding *) (NULL);	}	(void) strcpy(pdomb->dom_domain, domain);/* Remember the domain name */	pdomb->dom_pnext = bound_domains;	/* Link this to the list as */	bound_domains = pdomb;			/* ... the head entry */	return (pdomb);}/* * This checks to see if a ypserv which we know speaks v1 NIS program number * also speaks v2 version.  This makes the assumption that the NIS service at * the node is supplied by a single process, and that RPC will deliver a * message for a different program version number than that which the server * regestered. */static voidtalk2_server(pdomb)	struct dom_binding *pdomb;{	int sokt;	CLIENT *client;	enum clnt_stat clnt_stat;	sokt = RPC_ANYSOCK;	if ((client = clntudp_bufcreate(&(pdomb->dom_server_addr),	    YPPROG, YPVERS, ypserv_intertry, &sokt, RPCSMALLMSGSIZE, YPMSGSZ))	    == NULL) {		return;	}	clnt_stat = (enum clnt_stat) clnt_call(client, YPBINDPROC_NULL,	    xdr_void, 0, xdr_void, 0, _ypserv_timeout);	if (clnt_stat == RPC_SUCCESS) {		clnt_destroy(pdomb->dom_client);		(void) close(pdomb->dom_socket);		pdomb->dom_client = client;		pdomb->dom_socket = sokt;		pdomb->dom_vers = YPVERS;	} else {		clnt_destroy(client);		(void) close(sokt);	}}/* * Awful utility function that other libc routines no longer call to * see that are getting data from a NIS map. * using it tends to double the NIS traffic on the average * changed to not call yp_match any more. */intusingypmap(ddn, map)	char **ddn;  /* the default domainname set by this routine */	char *map;  /* the map we are interested in. */{	char *key = NULL, *outval = NULL;	int keylen, outvallen, stat;	if (_default_domain() == 0) return (FALSE);	/* does the map exist ? */	stat = yp_first(*ddn=default_domain, map, &key, &keylen, &outval, &outvallen);	if (outval != NULL)		free(outval);	if (key != NULL)		free(key);	return (yp_ismapthere(stat));}/* * Handy utility function that other libc routines can call to * see that are getting data from a NIS map. * e.g. if a yp_match fails and the stat is checked by this * routine FALSE is a fatal error and you should stop using NIS * TRUE means that the map exists and you should return * the error. */intyp_ismapthere(stat)	int stat;{	switch (stat) {	case 0:  /* it actually succeeded! */	case YPERR_KEY:  /* no such key in map */	case YPERR_NOMORE:	case YPERR_BUSY:		return (TRUE);	}	return (FALSE);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -