summaryrefslogtreecommitdiff
path: root/lib/libc
diff options
context:
space:
mode:
authorBill Paul <wpaul@FreeBSD.org>1996-06-01 05:08:31 +0000
committerBill Paul <wpaul@FreeBSD.org>1996-06-01 05:08:31 +0000
commita230877213de04795c58907240b3a581b29fcfc9 (patch)
tree4505541c7cc1de082ab04bbd514233878626d5cf /lib/libc
parent217ae63218d8980902670cd89cacaa7c9ad81b0a (diff)
Notes
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/yp/yplib.c45
1 files changed, 43 insertions, 2 deletions
diff --git a/lib/libc/yp/yplib.c b/lib/libc/yp/yplib.c
index da4d3b77b2cd..99e76939dfc8 100644
--- a/lib/libc/yp/yplib.c
+++ b/lib/libc/yp/yplib.c
@@ -58,7 +58,7 @@ struct dom_binding {
u_short dom_server_port;
int dom_socket;
CLIENT *dom_client;
- u_short dom_local_port;
+ u_short dom_local_port; /* now I finally know what this is for. */
long dom_vers;
};
@@ -221,6 +221,8 @@ _yp_dobind(dom, ypdb)
CLIENT *client;
int new = 0, r;
int retries = 0;
+ struct sockaddr_in check;
+ int checklen = sizeof(struct sockaddr_in);
gpid = getpid();
if( !(pid==-1 || pid==gpid) ) {
@@ -246,12 +248,29 @@ _yp_dobind(dom, ypdb)
if( strcmp(dom, ysd->dom_domain) == 0)
break;
+
if(ysd==NULL) {
ysd = (struct dom_binding *)malloc(sizeof *ysd);
bzero((char *)ysd, sizeof *ysd);
ysd->dom_socket = -1;
ysd->dom_vers = 0;
new = 1;
+ } else {
+ /* Check the socket -- may have been hosed by the caller. */
+ if (getsockname(ysd->dom_socket, (struct sockaddr *)&check,
+ &checklen) == -1 || check.sin_family != AF_INET ||
+ check.sin_port != ysd->dom_local_port) {
+ /* Socket became bogus somehow... need to rebind. */
+ int save, sock;
+
+ sock = ysd->dom_socket;
+ save = dup(ysd->dom_socket);
+ clnt_destroy(ysd->dom_client);
+ ysd->dom_vers = 0;
+ ysd->dom_client = NULL;
+ sock = dup2(save, sock);
+ close(save);
+ }
}
again:
@@ -270,6 +289,7 @@ again:
if(ysd->dom_client) {
clnt_destroy(ysd->dom_client);
ysd->dom_client = NULL;
+ ysd->dom_socket = -1;
}
sprintf(path, "%s/%s.%d", BINDINGDIR, dom, 2);
if( (fd=open(path, O_RDONLY)) == -1) {
@@ -323,6 +343,7 @@ skipit:
if(ysd->dom_client) {
clnt_destroy(ysd->dom_client);
ysd->dom_client = NULL;
+ ysd->dom_socket = -1;
}
bzero((char *)&clnt_sin, sizeof clnt_sin);
clnt_sin.sin_family = AF_INET;
@@ -354,8 +375,11 @@ skipit:
if(r != RPC_SUCCESS) {
clnt_destroy(client);
ysd->dom_vers = -1;
- if (r == RPC_PROGUNAVAIL || r == RPC_PROCUNAVAIL)
+ if (r == RPC_PROGUNAVAIL || r == RPC_PROCUNAVAIL) {
+ if (new)
+ free(ysd);
return(YPERR_YPBIND);
+ }
fprintf(stderr,
"YP: server for domain %s not responding, retrying\n", dom);
goto again;
@@ -396,6 +420,23 @@ gotit:
}
if( fcntl(ysd->dom_socket, F_SETFD, 1) == -1)
perror("fcntl: F_SETFD");
+ /*
+ * We want a port number associated with this socket
+ * so that we can check its authenticity later.
+ */
+ checklen = sizeof(struct sockaddr_in);
+ bzero((char *)&check, checklen);
+ bind(ysd->dom_socket, (struct sockaddr *)&check, checklen);
+ check.sin_family = AF_INET;
+ if (!getsockname(ysd->dom_socket,
+ (struct sockaddr *)&check, &checklen)) {
+ ysd->dom_local_port = check.sin_port;
+ } else {
+ clnt_destroy(ysd->dom_client);
+ if (new)
+ free(ysd);
+ return(YPERR_YPBIND);
+ }
}
if(new) {