ypbind.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,033 行 · 第 1/2 页

C
1,033
字号
	struct ypbind_resp response;	bool true;	char outstring[YPMAXDOMAIN + 256];	int broadcaster_pid;	struct domain *v1binding;	if (!svc_getargs(transp, xdr_ypdomain_wrap_string, &pdomain_name) ) {		svcerr_decode(transp);		return;	}	if ( (current_domain = ypbind_point_to_domain(pdomain_name, vers) ) !=	    (struct domain *) NULL) {		/*		 * Ping the server to make sure it is up.		 */		 		if (current_domain->dom_boundp) {			ypbind_ping(current_domain);		}		/*		 * Bound or not, return the current state of the binding.		 */		if (current_domain->dom_boundp) {			response.ypbind_status = YPBIND_SUCC_VAL;			response.ypbind_respbody.ypbind_bindinfo.ypbind_binding_addr =			    current_domain->dom_serv_addr;			response.ypbind_respbody.ypbind_bindinfo.ypbind_binding_port = 			    current_domain->dom_serv_port;		} else {			response.ypbind_status = YPBIND_FAIL_VAL;			response.ypbind_respbody.ypbind_error =			    YPBIND_ERR_NOSERV;		}		    	} else {		response.ypbind_status = YPBIND_FAIL_VAL;		response.ypbind_respbody.ypbind_error = YPBIND_ERR_RESC;	}	if (!svc_sendreply(transp, xdr_ypbind_resp, &response) ) {		(void) fprintf(stderr,		    "ypbind:  Can't respond to rpc request.\n");	}	if (!svc_freeargs(transp, xdr_ypdomain_wrap_string, &pdomain_name) ) {		(void) fprintf(stderr,		    "ypbind:  ypbind_get_binding can't free args.\n");	}	if(locked && (!current_domain->dom_boundp))		ypbind_locked(preflock,vers);	else 	if ((current_domain) && (!current_domain->dom_boundp) &&	    	(!current_domain->dom_broadcaster_pid)) {		/* The current domain is unbound, and there is no broadcaster 		 * process active now.  Fork off a child who will yell out on 		 * the net.  Because of the flavor of request we're making of 		 * the server, we only expect positive ("I do serve this		 * domain") responses.		 */		broadcast_domain = current_domain;		broadcast_domain->dom_report_success++;		pname = current_domain->dom_name;					if ( (broadcaster_pid = fork() ) == 0) {			(void) clnt_broadcast(YPPROG, vers,			    YPPROC_DOMAIN_NONACK, xdr_ypdomain_wrap_string,			    &pname, xdr_int, &true, ypbind_broadcast_ack);			    			if (current_domain->dom_boundp) {								/*				 * Send out a set domain request to our parent				 */				ypbind_send_setdom(pname,				    current_domain->dom_serv_addr,				    current_domain->dom_serv_port, vers);				    				if (current_domain->dom_report_success > 0) {					(void) sprintf(outstring,					 "ypbind: server for domain \"%s\" OK",					    pname);					writeit(outstring);				}									exit(0);			} else {				/*				 * Hack time.  If we're looking for a current-				 * version server and can't find one, but we				 * do have a previous-version server bound, then				 * suppress the console message.				 */				if (vers == YPVERS && ((v1binding =				   ypbind_point_to_domain(pname, YPOLDVERS) ) !=				    (struct domain *) NULL) &&				    v1binding->dom_boundp) {					    exit(1);				}								(void) sprintf(outstring,	      "\nypbind: server not responding for domain \"%s\"; still trying", pname);				writeit(outstring);				exit(1);			}		} else if (broadcaster_pid == -1) {			(void) fprintf(stderr,			    "ypbind:  broadcaster fork failure.\n");		} else {			current_domain->dom_broadcaster_pid = broadcaster_pid;		}	}}static intwriteit(s)	char *s;{	FILE *f;	if ((f = fopen("/dev/console", "w")) != NULL) {		(void) fprintf(f, "%s.\n", s);		(void) fclose(f);	}	}/* * This sends a (current version) ypbind "Set domain" message back to our * parent.  The version embedded in the protocol message is that which is passed * to us as a parameter. */voidypbind_send_setdom(dom, addr, port, vers)	char *dom;	struct in_addr addr;	unsigned short int port;	unsigned short int vers;{	struct ypbind_setdom req;	int socket;	struct timeval timeout;	struct timeval intertry;	CLIENT *client;	strcpy(req.ypsetdom_domain, dom);	req.ypsetdom_addr = addr;	req.ypsetdom_port = port;	req.ypsetdom_vers = vers;	myaddr.sin_port = htons(udphandle->xp_port);	socket = RPC_ANYSOCK;	timeout.tv_sec = SETDOMTOTTIM;	intertry.tv_sec = SETDOMINTERTRY;	timeout.tv_usec = intertry.tv_usec = 0;	if ((client = clntudp_bufcreate (&myaddr, YPBINDPROG, YPBINDVERS,	    intertry, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE) ) != NULL) {	        client->cl_auth = authunix_create_default();		clnt_call(client, YPBINDPROC_SETDOM, xdr_ypbind_setdom,		    &req, xdr_void, 0, timeout);		auth_destroy(client->cl_auth);		clnt_destroy(client);		close(socket);	} else {		clnt_pcreateerror(		    "ypbind(ypbind_send_setdom): clntudp_create error");	}}/* * This sets the internet address and port for the passed domain to the * passed values, and marks the domain as supported.  This accepts both the * old style message (in which case the version is assumed to be that of the * requestor) or the new one, in which case the protocol version is included * in the protocol message.  This allows our child process (which speaks the * current protocol) to look for yp servers on behalf old-style clients. */voidypbind_set_binding(rqstp, transp, vers)	struct svc_req *rqstp;	register SVCXPRT *transp;	unsigned short vers;{	struct ypbind_setdom req;	struct ypbind_oldsetdom oldreq;	unsigned short version;	struct in_addr addr;        struct sockaddr_in *who;	unsigned short int port;	char *domain;	int i;	if (vers == YPVERS) {		if (!svc_getargs(transp, xdr_ypbind_setdom, &req) ) {			svcerr_decode(transp);			return;		}		version = req.ypsetdom_vers;		addr = req.ypsetdom_addr;		port = req.ypsetdom_port;		domain = req.ypsetdom_domain;	} else {		if (!svc_getargs(transp, _xdr_ypbind_oldsetdom, &oldreq) ) {			svcerr_decode(transp);			return;		}		version = vers;		addr = oldreq.ypoldsetdom_addr;		port = oldreq.ypoldsetdom_port;		domain = oldreq.ypoldsetdom_domain;	}        /* find out who originated the request */        who = svc_getcaller(transp);        /* Now check the credentials */        if (rqstp->rq_cred.oa_flavor == AUTH_UNIX) {                if (((struct authunix_parms *)rqstp->rq_clntcred)->aup_uid != 0) {                        fprintf(stderr,"ypbind: Set domain request to host %s,",                                        inet_ntoa(addr));                        fprintf(stderr," from host %s, failed (not root).\n",                                        inet_ntoa(who->sin_addr));                              svcerr_systemerr(transp);                        return;                }         } else {                fprintf(stderr, "ypbind: Set domain request to host %s,",                                inet_ntoa(addr));                fprintf(stderr," from host %s, failed (credentials).\n",                                inet_ntoa(who->sin_addr));                svcerr_weakauth(transp);                return;        }	if (!svc_sendreply(transp, xdr_void, 0) ) {		fprintf(stderr, "ypbind:  Can't reply to rpc call.\n");	}	if(locked)		{		if(strcmp(setdomain,domain) == 0)			{			if((current_domain = ypbind_point_to_domain(domain,version)) != (struct domain *) NULL) 			for (i=0;i<locked;i++)				{        			sin = &sock[i];				if(sin->sin_addr.s_addr == addr.s_addr)					{					ypbind_locked(i,version);					}				}			}		}	else if ( (current_domain = ypbind_point_to_domain(domain,	    version) ) != (struct domain *) NULL) {		current_domain->dom_serv_addr = addr;		current_domain->dom_serv_port = port;		current_domain->dom_boundp = TRUE;		current_domain->ping_clnt = (CLIENT *)NULL;	}}/* * This returns a pointer to a domain entry.  If no such domain existed on * the list previously, an entry will be allocated, initialized, and linked * to the list.  Note:  If no memory can be malloc-ed for the domain structure, * the functional value will be (struct domain *) NULL. */static struct domain *ypbind_point_to_domain(pname, vers)	register char *pname;	unsigned short vers;{	register struct domain *pdom;		for (pdom = known_domains; pdom != (struct domain *)NULL;	    pdom = pdom->dom_pnext) {		if (!strcmp(pname, pdom->dom_name) && vers == pdom->dom_vers)			return (pdom);	}		/* Not found.  Add it to the list */		if (pdom = (struct domain *)malloc(sizeof (struct domain))) {		pdom->dom_pnext = known_domains;		known_domains = pdom;		strcpy(pdom->dom_name, pname);		pdom->dom_vers = vers;		pdom->dom_boundp = FALSE;		pdom->ping_clnt = (CLIENT *)NULL;		pdom->dom_report_success = -1;		pdom->dom_broadcaster_pid = 0;	}		return (pdom);}/* * This is called by the broadcast rpc routines to process the responses  * coming back from the broadcast request. Since the form of the request  * which is used in ypbind_broadcast_bind is "respond only in the positive   * case", the internet address of the responding server will be picked up  * from the saddr parameter, and stuffed into the domain.  The domain's * boundp field will be set TRUE.  Because this function returns TRUE,  * the first responding server will be the bound server for the domain. */boolypbind_broadcast_ack(ptrue, saddr)	bool *ptrue;	struct sockaddr_in *saddr;{	int i;	/* if ypbind is in locked mode only bind to the selected servers */	/* This code should never be hit but just in case its here  */	if(locked)		{		if ( (current_domain = ypbind_point_to_domain(setdomain,YPVERS) ) !=	    (struct domain *) NULL)			exit;		for (i=0;i<locked;i++)			{        		sin = &sock[i];			if(sin->sin_addr.s_addr == saddr->sin_addr.s_addr)				{				ypbind_locked(i,YPVERS);				}			}		}	else	{		current_domain->dom_boundp = TRUE;		current_domain->dom_serv_addr = saddr->sin_addr;		current_domain->dom_serv_port = saddr->sin_port;		current_domain->ping_clnt = (CLIENT *)NULL;		}	return(TRUE);}/* * This checks to see if a server bound to a named domain is still alive and * well.  If he's not, boundp in the domain structure is set to FALSE. */voidypbind_ping(pdom)	struct domain *pdom;{	struct sockaddr_in addr;	enum clnt_stat clnt_stat;	struct timeval timeout;	struct timeval intertry;		timeout.tv_sec = PINGTOTTIM;	timeout.tv_usec = intertry.tv_usec = 0;	if (pdom->ping_clnt == (CLIENT *)NULL) {		bzero(&addr, sizeof(struct sockaddr_in));		intertry.tv_sec = PINGINTERTRY;		addr.sin_addr = pdom->dom_serv_addr;		addr.sin_family = AF_INET;		addr.sin_port = pdom->dom_serv_port;		ping_sock = RPC_ANYSOCK;		if ((pdom->ping_clnt = clntudp_bufcreate(&addr, YPPROG,		    pdom->dom_vers, intertry, &ping_sock,		    RPCSMALLMSGSIZE, RPCSMALLMSGSIZE)) == (CLIENT *)NULL) {			clnt_pcreateerror("ypbind_ping) clntudp_create error");			pdom->dom_boundp = FALSE;			return;		}	}	if ((clnt_stat = (enum clnt_stat) clnt_call(pdom->ping_clnt,	    YPPROC_NULL, xdr_void, 0, xdr_void, 0, timeout)) != RPC_SUCCESS) {		pdom->dom_boundp = FALSE;		clnt_destroy(pdom->ping_clnt);			pdom->ping_clnt = (CLIENT *)NULL;		close(ping_sock);	}}/* * Preloads the default domain's domain binding. Domain binding for the * local node's default domain for both the current version, and the * previous version will be set up.  Bindings to servers which serve the * domain for both versions may additionally be made.   *  * Ypbind_init_default returns after binding or after BINDING_TRIES attempts * to bind for each version.   */static voidypbind_init_default(){	char domain[256];	char *pname = domain;	int true;	int binding_tries;	if (getdomainname(domain, 256) == 0) {		/* Exit if the default domainname is unspecified */	  	if (strcmp(domain,"") == 0) {      			(void) fprintf(stderr,"ypbind exiting: default domainname not specified\n");      			(void) fflush(stderr);      			exit(1);    		}  		current_domain = ypbind_point_to_domain(domain, YPVERS);		current_domain->dom_boundp = FALSE;		if (current_domain == (struct domain *) NULL) {			abort();		}				for (binding_tries = 0;		    ((!current_domain->dom_boundp) &&		    (binding_tries < BINDING_TRIES) ); binding_tries++) {			(void) clnt_broadcast(YPPROG, current_domain->dom_vers,			    YPPROC_DOMAIN_NONACK, xdr_ypdomain_wrap_string,			    &pname, xdr_int, &true, ypbind_broadcast_ack);					}				current_domain = ypbind_point_to_domain(domain, YPOLDVERS);		if (current_domain == (struct domain *) NULL) {			abort();		}				for (binding_tries = 0;		    ((!current_domain->dom_boundp) &&		    (binding_tries < BINDING_TRIES) ); binding_tries++) {			(void) clnt_broadcast(YPPROG, current_domain->dom_vers,			    YPPROC_DOMAIN_NONACK, xdr_ypdomain_wrap_string,			    &pname, xdr_int, &true, ypbind_broadcast_ack);					}	}}ypbind_locked(srvpref,version)int srvpref;unsigned short version;{	struct dom_binding domb;	enum clnt_stat clnt_stat;	int i,j,done,true;	char domain[256];	char *pname = setdomain;	int count;	if (getdomainname(domain, 256) == 0) {	 			/* Exit if the default domainname is unspecified */	  	if (strcmp(domain,"") == 0) {      			(void) fprintf(stderr,"ypbind exiting: default domainname not specified\n");      			(void) fflush(stderr);      			exit(1);    		}  		current_domain = ypbind_point_to_domain(domain, version);		current_domain->dom_boundp = FALSE;	}	/* check if there is a preferred local server */	if(srvpref != -1)		i=srvpref;	else i=0;	/* Loop until we find a server to bind to.	 * If the Initial Binding option (-X) is set and this is the initial	 * attempt to bind, return after binding or after BINDING_TRIES 	 * attempts to bind to each server. 	 */	done=0;	true=0;	count=BINDING_TRIES * locked;   /* For Initial Bind only */	while(!done)	{  		if (x_init_bind) {      			count--;      			if (count == 0) {				done = 1;      			}    		}        sin = &sock[i];	i = (i+1) % locked;        domb.dom_server_addr.sin_addr = sin->sin_addr;        domb.dom_server_addr.sin_family = AF_INET;        domb.dom_server_addr.sin_port = htons((u_short) 0);        domb.dom_server_port = htons((u_short) 0);        domb.dom_socket = RPC_ANYSOCK;        if (domb.dom_client = clntudp_create(&(domb.dom_server_addr),            YPPROG, version, udp_intertry, &(domb.dom_socket))) 		{                if((clnt_stat = (enum clnt_stat) clnt_call(domb.dom_client, YPPROC_DOMAIN,xdr_ypdomain_wrap_string,&pname,xdr_int,&true,udp_timeout)) == RPC_SUCCESS)						if(true)				{                    		done=1;				current_domain->dom_boundp = TRUE;				current_domain->dom_serv_addr = sin->sin_addr;				current_domain->dom_serv_port = sin->sin_port;				current_domain->ping_clnt = (CLIENT *)NULL;				}                clnt_destroy(domb.dom_client);                close(domb.dom_socket);		}	}}

⌨️ 快捷键说明

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