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 + -
显示快捷键?