📄 yp_bind.c
字号:
} else { rebind = TRUE; } if (rebind) { cu_sock = (int *)pdomb->dom_client->cl_private; *cu_sock = -1; pdomb->dom_socket = -1; yp_unbind(domain); pdomb = (struct dom_binding *) NULL; break; } else { *binding = pdomb; return (TRUE); } } } return (FALSE);}/* * This check whether the portmapper is up. If the connect succeeds, the * portmapper is dead. As a side effect, the pmapper sockaddr_in is * initialized. */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 = htons(PMAPPORT); bzero(pmapper->sin_zero, 8); 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 check whether ypbind is up. If the bind fails, ypbind is dead. * 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; 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); 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); } *err = YPERR_DOMAIN; return (BS_RETRY); } } else { 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) fprintf(stderr, "load_dom_binding: malloc failure.\n"); *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; if (bind (pdomb->dom_socket, (struct sockaddr *) &dummy, sizeof(dummy) ) != 0) { /*(void) close (pdomb->dom_socket); free((char *) pdomb); fprintf(stderr,"bind errno=%x\n",errno); *err = YPERR_YPERR; return (struct dom_binding *) (NULL); */ } /* * 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 { (void) close (pdomb->dom_socket); 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 YP program number * also speaks v2 version. This makes the assumption that the yp 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); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -