aboutsummaryrefslogtreecommitdiff
path: root/usr.sbin/ypbind/ypbind.c
diff options
context:
space:
mode:
authorBill Paul <wpaul@FreeBSD.org>1995-05-26 05:28:00 +0000
committerBill Paul <wpaul@FreeBSD.org>1995-05-26 05:28:00 +0000
commita7acf629b6a1a575e81968be19b9226790d246f9 (patch)
tree2e23c65155526a39dea769845a3d1640c14ee23e /usr.sbin/ypbind/ypbind.c
parent0063696232f8b38de8ef6d976bef71323404268e (diff)
Notes
Diffstat (limited to 'usr.sbin/ypbind/ypbind.c')
-rw-r--r--usr.sbin/ypbind/ypbind.c247
1 files changed, 128 insertions, 119 deletions
diff --git a/usr.sbin/ypbind/ypbind.c b/usr.sbin/ypbind/ypbind.c
index 21cd202455ba..9ca76186ae6d 100644
--- a/usr.sbin/ypbind/ypbind.c
+++ b/usr.sbin/ypbind/ypbind.c
@@ -28,7 +28,7 @@
*/
#ifndef LINT
-static char rcsid[] = "$Id: ypbind.c,v 1.11 1995/05/11 00:16:54 wpaul Exp $";
+static char rcsid[] = "$Id: ypbind.c,v 1.12 1995/05/12 16:52:58 wpaul Exp $";
#endif
#include <sys/param.h>
@@ -73,31 +73,36 @@ struct _dom_binding {
struct _dom_binding *dom_pnext;
char dom_domain[YPMAXDOMAIN + 1];
struct sockaddr_in dom_server_addr;
- CLIENT *client_handle;
long int dom_vers;
int dom_lockfd;
int dom_alive;
- int dom_broadcasting;
+ int dom_broadcast_pid;
+ int dom_pipe_fds[2];
int dom_default;
};
+#define READFD ypdb->dom_pipe_fds[0]
+#define WRITEFD ypdb->dom_pipe_fds[1]
+#define BROADFD broad_domain->dom_pipe_fds[1]
+
extern bool_t xdr_domainname(), xdr_ypbind_resp();
extern bool_t xdr_ypreq_key(), xdr_ypresp_val();
extern bool_t xdr_ypbind_setdom();
void checkwork __P((void));
void *ypbindproc_null_2 __P((SVCXPRT *, void *, CLIENT *));
-bool_t *ypbindproc_setdom_2 __P((SVCXPRT *, struct ypbind_setdom *, CLIENT *));
+void *ypbindproc_setdom_2 __P((SVCXPRT *, struct ypbind_setdom *, CLIENT *));
void rpc_received __P((char *, struct sockaddr_in *, int ));
void broadcast __P((struct _dom_binding *));
int ping __P((struct _dom_binding *));
+int tell_parent __P((char *, struct sockaddr_in *));
void handle_children __P(( int ));
void reaper __P((int));
void terminate __P((int));
-static char *broad_domain;
char *domainname;
struct _dom_binding *ypbindlist;
+static struct _dom_binding *broad_domain;
#define YPSET_NO 0
#define YPSET_LOCAL 1
@@ -106,20 +111,22 @@ int ypsetmode = YPSET_NO;
int ypsecuremode = 0;
/* No more than MAX_CHILDREN child broadcasters at a time. */
+#ifndef MAX_CHILDREN
#define MAX_CHILDREN 5
+#endif
/* No more than MAX_DOMAINS simultaneous domains */
+#ifndef MAX_DOMAINS
#define MAX_DOMAINS 200
+#endif
+/* RPC timeout value */
#ifndef FAIL_THRESHOLD
-#define FAIL_THRESHOLD 20
+#define FAIL_THRESHOLD 10
#endif
-#define KILLME_MAGIC 0xdeaddead
-
-int child_fds[FD_SETSIZE];
-static int fd[2];
int children = 0;
int domains = 0;
int yplockfd;
+fd_set fdsr;
SVCXPRT *udptransp, *tcptransp;
@@ -149,9 +156,10 @@ CLIENT *clnt;
res.ypbind_status = YPBIND_FAIL_VAL;
res.ypbind_respbody.ypbind_error = YPBIND_ERR_NOSERV;
- for(ypdb=ypbindlist; ypdb; ypdb=ypdb->dom_pnext)
+ for(ypdb=ypbindlist; ypdb; ypdb=ypdb->dom_pnext) {
if( strcmp(ypdb->dom_domain, argp) == 0)
break;
+ }
if(ypdb==NULL) {
if (domains >= MAX_DOMAINS) {
@@ -180,8 +188,9 @@ CLIENT *clnt;
domains++;
}
- if (ping(ypdb))
+ if (ping(ypdb)) {
return &res;
+ }
res.ypbind_status = YPBIND_SUCC_VAL;
res.ypbind_respbody.ypbind_error = 0; /* Success */
@@ -195,35 +204,40 @@ CLIENT *clnt;
return &res;
}
-bool_t *
+void *
ypbindproc_setdom_2(transp, argp, clnt)
SVCXPRT *transp;
struct ypbind_setdom *argp;
CLIENT *clnt;
{
struct sockaddr_in *fromsin, bindsin;
- static char res;
- bzero((char *)&res, sizeof(res));
fromsin = svc_getcaller(transp);
switch(ypsetmode) {
case YPSET_LOCAL:
- if( fromsin->sin_addr.s_addr != htonl(INADDR_LOOPBACK))
- return (void *)NULL;
+ if( fromsin->sin_addr.s_addr != htonl(INADDR_LOOPBACK)) {
+ svcerr_noprog(transp);
+ return;
+ }
break;
case YPSET_ALL:
break;
case YPSET_NO:
default:
- return (void *)NULL;
+ svcerr_noprog(transp);
+ return;
}
- if(ntohs(fromsin->sin_port) >= IPPORT_RESERVED)
- return (void *)&res;
+ if(ntohs(fromsin->sin_port) >= IPPORT_RESERVED) {
+ svcerr_noprog(transp);
+ return;
+ }
- if(argp->ypsetdom_vers != YPVERS)
- return (void *)&res;
+ if(argp->ypsetdom_vers != YPVERS) {
+ svcerr_noprog(transp);
+ return;
+ }
bzero((char *)&bindsin, sizeof bindsin);
bindsin.sin_family = AF_INET;
@@ -231,8 +245,7 @@ CLIENT *clnt;
bindsin.sin_port = argp->ypsetdom_port;
rpc_received(argp->ypsetdom_domain, &bindsin, 1);
- res = 1;
- return (void *)&res;
+ return;
}
static void
@@ -314,6 +327,8 @@ int sig;
for(ypdb=ypbindlist; ypdb; ypdb=ypdb->dom_pnext) {
close(ypdb->dom_lockfd);
+ if (ypdb->dom_broadcast_pid)
+ kill(ypdb->dom_broadcast_pid, SIGINT);
sprintf(path, "%s/%s.%ld", BINDINGDIR,
ypdb->dom_domain, ypdb->dom_vers);
unlink(path);
@@ -331,10 +346,10 @@ char **argv;
{
char path[MAXPATHLEN];
struct timeval tv;
- fd_set fdsr;
int i;
DIR *dird;
struct dirent *dirp;
+ struct _dom_binding *ypdb;
/* Check that another ypbind isn't already running. */
if ((yplockfd = (open(YPBINDLOCK, O_RDONLY|O_CREAT, 0444))) == -1) {
@@ -418,17 +433,12 @@ char **argv;
ypbindlist->dom_vers = YPVERS;
ypbindlist->dom_alive = 0;
ypbindlist->dom_lockfd = -1;
- ypbindlist->client_handle = NULL;
ypbindlist->dom_default = 1;
domains++;
signal(SIGCHLD, reaper);
signal(SIGTERM, terminate);
- /* Initialize children fds. */
- for (i = 0; i < FD_SETSIZE; i++)
- child_fds[i] = -1;
-
openlog(argv[0], LOG_PID, LOG_DAEMON);
/* Kick off the default domain */
@@ -437,10 +447,6 @@ char **argv;
while(1) {
fdsr = svc_fdset;
- for (i = 0; i < FD_SETSIZE; i++)
- if (child_fds[i] > 0 )
- FD_SET(child_fds[i], &fdsr);
-
tv.tv_sec = 60;
tv.tv_usec = 0;
@@ -449,21 +455,16 @@ char **argv;
checkwork();
break;
case -1:
- if (errno == EINTR)
- continue;
- else {
+ if (errno != EINTR)
syslog(LOG_WARNING, "select: %s", strerror(errno));
- break;
- }
+ break;
default:
- for(i = 0; i < FD_SETSIZE; i++) {
- if (child_fds[i] > 0 && FD_ISSET(child_fds[i],&fdsr)) {
- handle_children(child_fds[i]);
- close(child_fds[i]);
- FD_CLR(child_fds[i], &fdsr);
- child_fds[i] = -1;
+ for(ypdb=ypbindlist; ypdb; ypdb=ypdb->dom_pnext) {
+ if (READFD > 0 && FD_ISSET(READFD, &fdsr)) {
+ handle_children(READFD);
children--;
-
+ if (children == (MAX_CHILDREN - 1))
+ checkwork();
}
}
svc_getreqset(&fdsr);
@@ -497,6 +498,10 @@ int i;
syslog(LOG_WARNING, "could not read from child: %s", strerror(errno));
if (read(i, &addr, sizeof(struct sockaddr_in)) < 0)
syslog(LOG_WARNING, "could not read from child: %s", strerror(errno));
+
+ close(i);
+ FD_CLR(i, &fdsr);
+ FD_CLR(i, &svc_fdset);
rpc_received((char *)&buf, &addr, 0);
}
@@ -515,8 +520,8 @@ struct sockaddr_in *addr;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
- sprintf (buf, "%s", broad_domain);
- if (write(fd[1], &buf, sizeof(buf)) < 0)
+ sprintf(buf, "%s", broad_domain->dom_domain);
+ if (write(BROADFD, &buf, sizeof(buf)) < 0)
return(1);
/*
@@ -525,17 +530,17 @@ struct sockaddr_in *addr;
*/
FD_ZERO(&fds);
- FD_SET(fd[1], &fds);
+ FD_SET(BROADFD, &fds);
if (select(FD_SETSIZE, NULL, &fds, NULL, &timeout) == -1)
return(1);
- if (FD_ISSET(fd[1], &fds)) {
- if (write(fd[1], addr, sizeof(struct sockaddr_in)) < 0)
+ if (FD_ISSET(BROADFD, &fds)) {
+ if (write(BROADFD, addr, sizeof(struct sockaddr_in)) < 0)
return(1);
} else {
return(1);
}
- close(fd[1]);
+ close(BROADFD);
return (0);
}
@@ -543,7 +548,7 @@ bool_t broadcast_result(out, addr)
bool_t *out;
struct sockaddr_in *addr;
{
- if (tell_parent(&broad_domain, addr))
+ if (tell_parent(broad_domain->dom_domain, addr))
syslog(LOG_WARNING, "lost connection to parent");
return TRUE;
}
@@ -564,46 +569,45 @@ struct _dom_binding *ypdb;
{
bool_t out = FALSE;
enum clnt_stat stat;
- int i;
- if (children > MAX_CHILDREN || ypdb->dom_broadcasting)
+ if (children >= MAX_CHILDREN || ypdb->dom_broadcast_pid)
return;
- if (pipe(fd) < 0) {
+ if (pipe(ypdb->dom_pipe_fds) < 0) {
syslog(LOG_WARNING, "pipe: %s",strerror(errno));
return;
}
if (ypdb->dom_vers = -1 && (long)ypdb->dom_server_addr.sin_addr.s_addr)
- syslog(LOG_WARNING, "NIS server [%s] for domain %s not responding",
+ syslog(LOG_WARNING, "NIS server [%s] for domain \"%s\" not responding",
inet_ntoa(ypdb->dom_server_addr.sin_addr), ypdb->dom_domain);
- broad_domain = ypdb->dom_domain;
- ypdb->dom_broadcasting = 1;
+ broad_domain = ypdb;
flock(ypdb->dom_lockfd, LOCK_UN);
- switch(fork()) {
+ switch((ypdb->dom_broadcast_pid = fork())) {
case 0:
- close(fd[0]);
+ close(READFD);
break;
case -1:
syslog(LOG_WARNING, "fork: %s", strerror(errno));
- close(fd[1]);
- close(fd[0]);
+ close(READFD);
+ close(WRITEFD);
return;
default:
- for (i = 0; i < FD_SETSIZE; i++) {
- if (child_fds[i] < 0) {
- child_fds[i] = fd[0];
- break;
- }
- }
- close(fd[1]);
+ close(WRITEFD);
+ FD_SET(READFD, &svc_fdset);
children++;
return;
}
- close(ypdb->dom_lockfd);
+ /* Release all locks before doing anything else. */
+ while(ypbindlist) {
+ close(ypbindlist->dom_lockfd);
+ ypbindlist = ypbindlist->dom_pnext;
+ }
+ close(yplockfd);
+
stat = clnt_broadcast(YPPROG, YPVERS, YPPROC_DOMAIN_NONACK,
xdr_domainname, (char *)ypdb->dom_domain, xdr_bool, (char *)&out,
broadcast_result);
@@ -611,20 +615,19 @@ struct _dom_binding *ypdb;
if (stat != RPC_SUCCESS) {
bzero((char *)&ypdb->dom_server_addr,
sizeof(struct sockaddr_in));
- if (!ypdb->dom_default)
- ypdb->dom_server_addr.sin_addr.s_addr = KILLME_MAGIC;
- if (tell_parent(&ypdb->dom_domain, &ypdb->dom_server_addr))
+ if (tell_parent(ypdb->dom_domain, &ypdb->dom_server_addr))
syslog(LOG_WARNING, "lost connection to parent");
}
+
exit(0);
}
/*
* The right way to check if a server is alive.
* Attempt to get a client handle pointing to the server and send a
- * YPPROC_DOMAIN_NONACK. If we don't get a response, we invalidate
- * this binding entry and send out a broadcast to try to establish
- * a new binding. Note that we treat non-default domains
+ * YPPROC_DOMAIN. If we can't get a handle or we get a reply of FALSE,
+ * we invalidate this binding entry and send out a broadcast to try to
+ * establish a new binding. Note that we treat non-default domains
* specially: once bound, we keep tabs on our server, but if it
* goes away and fails to respond after one round of broadcasting, we
* abandon it until a client specifically references it again. We make
@@ -639,40 +642,38 @@ struct _dom_binding *ypdb;
struct timeval interval, timeout;
enum clnt_stat stat;
int rpcsock = RPC_ANYSOCK;
+ CLIENT *client_handle;
time_t t;
- interval.tv_sec = 5;
+ interval.tv_sec = FAIL_THRESHOLD;
interval.tv_usec = 0;
timeout.tv_sec = FAIL_THRESHOLD;
timeout.tv_usec = 0;
- if (ypdb->dom_broadcasting)
+ if (ypdb->dom_broadcast_pid)
return(1);
- if (ypdb->client_handle == NULL) {
- if ((ypdb->client_handle = clntudp_bufcreate(
- &ypdb->dom_server_addr, YPPROG, YPVERS,
- interval, &rpcsock, RPCSMALLMSGSIZE,
- RPCSMALLMSGSIZE)) == (CLIENT *)NULL) {
- /* Can't get a handle: we're dead. */
- ypdb->client_handle = NULL;
- ypdb->dom_alive = 0;
- ypdb->dom_vers = -1;
- broadcast(ypdb);
- return(1);
- }
+ if ((client_handle = clntudp_bufcreate(&ypdb->dom_server_addr,
+ YPPROG, YPVERS, interval, &rpcsock, RPCSMALLMSGSIZE,
+ RPCSMALLMSGSIZE)) == (CLIENT *)NULL) {
+ /* Can't get a handle: we're dead. */
+ ypdb->dom_alive = 0;
+ ypdb->dom_vers = -1;
+ broadcast(ypdb);
+ return(1);
}
- if ((stat = clnt_call(ypdb->client_handle, YPPROC_DOMAIN_NONACK,
- xdr_domainname, (char *)ypdb->dom_domain,
- xdr_bool, (char *)&out, timeout)) != RPC_SUCCESS) {
- ypdb->client_handle = NULL;
+ if ((stat = clnt_call(client_handle, YPPROC_DOMAIN,
+ xdr_domainname, (char *)ypdb->dom_domain, xdr_bool,
+ (char *)&out, timeout)) != RPC_SUCCESS || out == FALSE) {
ypdb->dom_alive = 0;
ypdb->dom_vers = -1;
+ clnt_destroy(client_handle);
broadcast(ypdb);
return(1);
}
+ clnt_destroy(client_handle);
return(0);
}
@@ -699,37 +700,47 @@ int force;
prev = ypdb;
}
+ if (ypdb && force) {
+ if (ypdb->dom_broadcast_pid) {
+ kill(ypdb->dom_broadcast_pid, SIGINT);
+ close(READFD);
+ }
+ }
+
/* if in securemode, check originating port number */
if (ypsecuremode && (ntohs(raddrp->sin_port) >= IPPORT_RESERVED)) {
syslog(LOG_WARNING, "Rejected NIS server on [%s/%d] for domain %s.",
inet_ntoa(raddrp->sin_addr), ntohs(raddrp->sin_port),
dom);
if (ypdb != NULL) {
- ypdb->dom_broadcasting = 0;
+ ypdb->dom_broadcast_pid = 0;
ypdb->dom_alive = 0;
}
return;
}
if (raddrp->sin_addr.s_addr == (long)0) {
- ypdb->dom_broadcasting = 0;
- ypdb->dom_alive = 0;
- broadcast(ypdb);
- return;
- }
-
- if (raddrp->sin_addr.s_addr == KILLME_MAGIC) {
- if (prev == NULL)
- ypbindlist = ypdb->dom_pnext;
- else
- prev->dom_pnext = ypdb->dom_pnext;
- sprintf(path, "%s/%s.%ld", BINDINGDIR,
- ypdb->dom_domain, YPVERS); /* XXX dom_vers can't */
- close(ypdb->dom_lockfd); /* be trusted here */
- unlink(path);
- free(ypdb);
- domains--;
- return;
+ switch(ypdb->dom_default) {
+ case 0:
+ if (prev == NULL)
+ ypbindlist = ypdb->dom_pnext;
+ else
+ prev->dom_pnext = ypdb->dom_pnext;
+ sprintf(path, "%s/%s.%ld", BINDINGDIR,
+ ypdb->dom_domain, YPVERS);
+ close(ypdb->dom_lockfd);
+ unlink(path);
+ free(ypdb);
+ domains--;
+ return;
+ case 1:
+ ypdb->dom_broadcast_pid = 0;
+ ypdb->dom_alive = 0;
+ broadcast(ypdb);
+ return;
+ default:
+ break;
+ }
}
if(ypdb==NULL) {
@@ -744,23 +755,21 @@ int force;
strncpy(ypdb->dom_domain, dom, sizeof ypdb->dom_domain);
ypdb->dom_lockfd = -1;
ypdb->dom_default = 0;
- ypdb->dom_alive = 0;
- ypdb->dom_broadcasting = 0;
ypdb->dom_pnext = ypbindlist;
ypbindlist = ypdb;
}
/* We've recovered from a crash: inform the world. */
if (ypdb->dom_vers = -1 && ypdb->dom_server_addr.sin_addr.s_addr)
- syslog(LOG_WARNING, "NIS server [%s] for domain %s OK",
- inet_ntoa(ypdb->dom_server_addr.sin_addr), ypdb->dom_domain);
+ syslog(LOG_WARNING, "NIS server [%s] for domain \"%s\" OK",
+ inet_ntoa(raddrp->sin_addr), ypdb->dom_domain);
bcopy((char *)raddrp, (char *)&ypdb->dom_server_addr,
sizeof ypdb->dom_server_addr);
ypdb->dom_vers = YPVERS;
ypdb->dom_alive = 1;
- ypdb->dom_broadcasting = 0;
+ ypdb->dom_broadcast_pid = 0;
if(ypdb->dom_lockfd != -1)
close(ypdb->dom_lockfd);