summaryrefslogtreecommitdiffstats
path: root/usr.sbin/ypbind/ypbind.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/ypbind/ypbind.c')
-rw-r--r--usr.sbin/ypbind/ypbind.c572
1 files changed, 273 insertions, 299 deletions
diff --git a/usr.sbin/ypbind/ypbind.c b/usr.sbin/ypbind/ypbind.c
index 43c719f..9aaf1e6 100644
--- a/usr.sbin/ypbind/ypbind.c
+++ b/usr.sbin/ypbind/ypbind.c
@@ -28,16 +28,18 @@
*/
#ifndef LINT
-static char rcsid[] = "$Id: ypbind.c,v 1.6 1995/04/15 23:35:46 wpaul Exp $";
+static char rcsid[] = "$Id: ypbind.c,v 1.7 1995/04/21 18:04:36 wpaul Exp $";
#endif
#include <sys/param.h>
#include <sys/types.h>
+#include <sys/wait.h>
#include <sys/ioctl.h>
#include <sys/signal.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/fcntl.h>
+#include <sys/stat.h>
#include <sys/uio.h>
#include <syslog.h>
#include <stdio.h>
@@ -55,6 +57,7 @@ static char rcsid[] = "$Id: ypbind.c,v 1.6 1995/04/15 23:35:46 wpaul Exp $";
#include <rpc/pmap_prot.h>
#include <rpc/pmap_rmt.h>
#include <unistd.h>
+#include <stdlib.h>
#include <rpcsvc/yp_prot.h>
#include <rpcsvc/ypclnt.h>
@@ -63,9 +66,12 @@ static char rcsid[] = "$Id: ypbind.c,v 1.6 1995/04/15 23:35:46 wpaul Exp $";
#endif
/*
- * Number of seconds to wait before for ping replies before we
- * decide that our server is dead.
+ * Ping the server once every PING_INTERVAL seconds to make sure it's
+ * still there.
*/
+#ifndef PING_INTERVAL
+#define PING_INTERVAL 60
+#endif
#ifndef FAIL_THRESHOLD
#define FAIL_THRESHOLD 20
#endif
@@ -74,38 +80,43 @@ struct _dom_binding {
struct _dom_binding *dom_pnext;
char dom_domain[YPMAXDOMAIN + 1];
struct sockaddr_in dom_server_addr;
- unsigned short int dom_server_port;
- int dom_socket;
- CLIENT *dom_client;
+ CLIENT *client_handle;
long int dom_vers;
- time_t dom_check_t;
int dom_lockfd;
int dom_alive;
- int dom_answered;
- int dom_interval;
+ int dom_broadcasting;
+ int dom_default;
+ time_t dom_check;
};
extern bool_t xdr_domainname(), xdr_ypbind_resp();
extern bool_t xdr_ypreq_key(), xdr_ypresp_val();
extern bool_t xdr_ypbind_setdom();
-char *domainname;
+void checkwork __P((void));
+void *ypbindproc_null_2 __P((SVCXPRT *, void *, CLIENT *));
+bool_t *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));
+void handle_children __P(( int ));
+static char *broad_domain;
+char *domainname;
struct _dom_binding *ypbindlist;
-int check;
#define YPSET_NO 0
#define YPSET_LOCAL 1
#define YPSET_ALL 2
int ypsetmode = YPSET_NO;
-
int ypsecuremode = 0;
-int rpcsock;
-struct rmtcallargs rmtca;
-struct rmtcallres rmtcr;
-char rmtcr_outval;
-u_long rmtcr_port;
+/* No more than MAX_CHILDREN child broadcasters at a time. */
+#define MAX_CHILDREN 5
+int child_fds[FD_SETSIZE];
+static int fd[2];
+int children = 0;
+
SVCXPRT *udptransp, *tcptransp;
void *
@@ -144,8 +155,9 @@ CLIENT *clnt;
strncpy(ypdb->dom_domain, argp, sizeof ypdb->dom_domain);
ypdb->dom_vers = YPVERS;
ypdb->dom_alive = 0;
+ ypdb->dom_default = 0;
ypdb->dom_lockfd = -1;
- sprintf(path, "%s/%s.%d", BINDINGDIR, ypdb->dom_domain, ypdb->dom_vers);
+ sprintf(path, "%s/%s.%ld", BINDINGDIR, ypdb->dom_domain, ypdb->dom_vers);
unlink(path);
ypdb->dom_pnext = ypbindlist;
ypbindlist = ypdb;
@@ -155,32 +167,14 @@ CLIENT *clnt;
if(ypdb->dom_alive==0)
return &res;
-#if 0
- delta = ypdb->dom_check_t - ypdb->dom_ask_t;
- if( !(ypdb->dom_ask_t==0 || delta > 5)) {
- ypdb->dom_ask_t = time(NULL);
- /*
- * Hmm. More than 2 requests in 5 seconds have indicated that my
- * binding is possibly incorrect. Ok, make myself unalive, and
- * find out what the actual state is.
- */
- if(ypdb->dom_lockfd!=-1)
- close(ypdb->dom_lockfd);
- ypdb->dom_lockfd = -1;
- ypdb->dom_alive = 0;
- ypdb->dom_lockfd = -1;
- sprintf(path, "%s/%s.%d", BINDINGDIR, ypdb->dom_domain, ypdb->dom_vers);
- unlink(path);
- return NULL;
- }
-#endif
+ if (ping(ypdb, 1))
+ return &res;
-answer:
res.ypbind_status = YPBIND_SUCC_VAL;
res.ypbind_respbody.ypbind_bindinfo.ypbind_binding_addr.s_addr =
ypdb->dom_server_addr.sin_addr.s_addr;
res.ypbind_respbody.ypbind_bindinfo.ypbind_binding_port =
- ypdb->dom_server_port;
+ ypdb->dom_server_addr.sin_port;
/*printf("domain %s at %s/%d\n", ypdb->dom_domain,
inet_ntoa(ypdb->dom_server_addr.sin_addr),
ntohs(ypdb->dom_server_addr.sin_port));*/
@@ -289,13 +283,23 @@ register SVCXPRT *transp;
return;
}
+/* Jack the reaper */
+void reaper(sig)
+int sig;
+{
+ int st;
+
+ wait3(&st, WNOHANG, NULL);
+}
+
+void
main(argc, argv)
+int argc;
char **argv;
{
char path[MAXPATHLEN];
struct timeval tv;
fd_set fdsr;
- int width;
int i;
yp_get_default_domain(&domainname);
@@ -355,57 +359,54 @@ char **argv;
exit(1);
}
- if( (rpcsock=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
- perror("socket");
- return -1;
- }
-
- fcntl(rpcsock, F_SETFL, fcntl(rpcsock, F_GETFL, 0) | FNDELAY);
- i = 1;
- setsockopt(rpcsock, SOL_SOCKET, SO_BROADCAST, &i, sizeof(i));
- rmtca.prog = YPPROG;
- rmtca.vers = YPVERS;
- rmtca.proc = YPPROC_DOMAIN_NONACK;
- rmtca.xdr_args = NULL; /* set at call time */
- rmtca.args_ptr = NULL; /* set at call time */
- rmtcr.port_ptr = &rmtcr_port;
- rmtcr.xdr_results = xdr_bool;
- rmtcr.results_ptr = (caddr_t)&rmtcr_outval;
-
/* build initial domain binding, make it "unsuccessful" */
ypbindlist = (struct _dom_binding *)malloc(sizeof *ypbindlist);
bzero((char *)ypbindlist, sizeof *ypbindlist);
strncpy(ypbindlist->dom_domain, domainname, sizeof ypbindlist->dom_domain);
ypbindlist->dom_vers = YPVERS;
- ypbindlist->dom_interval = 0;
ypbindlist->dom_alive = 0;
- ypbindlist->dom_answered = 0;
ypbindlist->dom_lockfd = -1;
- ypbindlist->dom_check_t = time(NULL) + ypbindlist->dom_interval;
- sprintf(path, "%s/%s.%d", BINDINGDIR, ypbindlist->dom_domain,
+ ypbindlist->client_handle = NULL;
+ ypbindlist->dom_default = 1;
+ sprintf(path, "%s/%s.%ld", BINDINGDIR, ypbindlist->dom_domain,
ypbindlist->dom_vers);
(void)unlink(path);
+ /* Initialize children fds. */
+ for (i = 0; i < FD_SETSIZE; i++)
+ child_fds[i] = -1;
+
openlog(argv[0], LOG_PID, LOG_AUTH);
- width = getdtablesize();
while(1) {
fdsr = svc_fdset;
- FD_SET(rpcsock, &fdsr);
+
+ for (i = 0; i < FD_SETSIZE; i++)
+ if (child_fds[i] > 0 )
+ FD_SET(child_fds[i], &fdsr);
+
tv.tv_sec = 1;
tv.tv_usec = 0;
- switch(select(width, &fdsr, NULL, NULL, &tv)) {
+ switch(select(_rpc_dtablesize(), &fdsr, NULL, NULL, &tv)) {
case 0:
checkwork();
+ reaper();
break;
case -1:
- perror("select\n");
+ perror("select");
+ exit(0);
break;
default:
- if(FD_ISSET(rpcsock, &fdsr)) {
- FD_CLR(rpcsock, &fdsr);
- handle_replies();
+ 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;
+ children--;
+
+ }
}
svc_getreqset(&fdsr);
break;
@@ -413,237 +414,224 @@ char **argv;
}
}
-/*
- * change to do something like this:
- *
- * STATE TIME ACTION NEWTIME NEWSTATE
- * no binding t==* broadcast t=2 no binding
- * binding t==60 check server t=10 binding
- * binding t=10 broadcast t=2 no binding
- */
-
-/*
- * The above comment makes no sense whatsoever. This is what should
- * be happening:
- *
- * - If we have any servers in our binding list marked alive, ping
- * them _and them alone_ only once every 60 seconds to make sure
- * they haven't crapped out on us (i.e. bother only the servers
- * we know about: *DON'T* continually bother everybody with broadcast
- * packets every 5 seconds like we used to).
- * - If they don't respond within FAIL_THRESHOLD seconds after the ping,
- * they're toast: mark them unalive and start to scream and shout.
- * - If we don't have any servers marked alive, then we're in desperate
- * trouble and we need to broadcast a cry for help every 5 seconds
- * until somebody answers us.
- */
-
+void
checkwork()
{
struct _dom_binding *ypdb;
time_t t;
+ time(&t);
for(ypdb=ypbindlist; ypdb; ypdb=ypdb->dom_pnext) {
- time(&t);
- if (ypdb->dom_check_t < t) {
- broadcast(ypdb->dom_domain,
- ypdb->dom_server_addr, ypdb->dom_alive);
- ypdb->dom_check_t = t + ypdb->dom_interval;
- ypdb->dom_answered = 0;
- } else
- if (!ypdb->dom_answered && ypdb->dom_alive &&
- ypdb->dom_check_t < (t + FAIL_THRESHOLD)) {
- ypdb->dom_check_t = ypdb->dom_alive =
- ypdb->dom_vers = 0;
- ypdb->dom_interval = 5;
- syslog (LOG_NOTICE,
- "NIS server [%s] for domain %s not responding.",
- inet_ntoa(ypdb->dom_server_addr.sin_addr),
- ypdb->dom_domain);
+ if (!ypdb->dom_alive && !ypdb->dom_broadcasting) {
+ if (!ypdb->dom_default)
+ ypdb->dom_alive = 1;
+ ypdb->dom_broadcasting = 1;
+ broadcast(ypdb);
}
+ if (ypdb->dom_alive && ypdb->dom_check < t)
+ ping(ypdb, 0);
}
}
-broadcast(dom, saddr, direct)
+/* The clnt_broadcast() callback mechanism sucks. */
+
+/*
+ * Receive results from broadcaster. Don't worry about passing
+ * bogus info to rpc_received() -- it can handle it.
+ */
+void handle_children(i)
+int i;
+{
+ char buf[YPMAXDOMAIN + 1];
+ struct sockaddr_in addr;
+
+ if (read(i, &buf, sizeof(buf)) < 0)
+ syslog(LOG_WARNING, "could not read from child");
+ if (read(i, &addr, sizeof(struct sockaddr_in)) < 0)
+ syslog(LOG_WARNING, "could not read from child");
+ rpc_received((char *)&buf, &addr, 0);
+}
+
+/*
+ * Send our dying words back to our parent before we perish.
+ */
+int
+tell_parent(dom, addr)
char *dom;
-struct sockaddr_in saddr;
-int direct;
+struct sockaddr_in *addr;
{
- struct rpc_msg rpcmsg;
- char buf[1400], inbuf[8192];
- enum clnt_stat st;
- struct timeval tv;
- int outlen, i, sock, len;
- struct sockaddr_in bsin;
- struct ifconf ifc;
- struct ifreq ifreq, *ifr;
- struct in_addr in;
- AUTH *rpcua;
- XDR rpcxdr;
-
- rmtca.xdr_args = xdr_domainname;
- rmtca.args_ptr = dom;
-
- bzero((char *)&bsin, sizeof bsin);
- bsin.sin_family = AF_INET;
- bsin.sin_port = htons(PMAPPORT);
-
- bzero((char *)&rpcxdr, sizeof rpcxdr);
- bzero((char *)&rpcmsg, sizeof rpcmsg);
-
- rpcua = authunix_create_default();
- if( rpcua == (AUTH *)NULL) {
- /*printf("cannot get unix auth\n");*/
- return RPC_SYSTEMERROR;
- }
- rpcmsg.rm_direction = CALL;
- rpcmsg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
- rpcmsg.rm_call.cb_prog = PMAPPROG;
- rpcmsg.rm_call.cb_vers = PMAPVERS;
- rpcmsg.rm_call.cb_proc = PMAPPROC_CALLIT;
- rpcmsg.rm_call.cb_cred = rpcua->ah_cred;
- rpcmsg.rm_call.cb_verf = rpcua->ah_verf;
-
- gettimeofday(&tv, (struct timezone *)0);
- rpcmsg.rm_xid = (int)dom;
- tv.tv_usec = 0;
- xdrmem_create(&rpcxdr, buf, sizeof buf, XDR_ENCODE);
- if( (!xdr_callmsg(&rpcxdr, &rpcmsg)) ) {
- st = RPC_CANTENCODEARGS;
- AUTH_DESTROY(rpcua);
- return st;
- }
- if( (!xdr_rmtcall_args(&rpcxdr, &rmtca)) ) {
- st = RPC_CANTENCODEARGS;
- AUTH_DESTROY(rpcua);
- return st;
- }
- outlen = (int)xdr_getpos(&rpcxdr);
- xdr_destroy(&rpcxdr);
- if(outlen<1) {
- AUTH_DESTROY(rpcua);
- return st;
- }
- AUTH_DESTROY(rpcua);
+ char buf[YPMAXDOMAIN + 1];
+ struct timeval timeout;
+ fd_set fds;
- /* find all networks and send the RPC packet out them all */
- if( (sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
- perror("socket");
- return -1;
- }
+ timeout.tv_sec = 5;
+ timeout.tv_usec = 0;
+
+ sprintf (buf, "%s", broad_domain);
+ if (write(fd[1], &buf, sizeof(buf)) < 0)
+ return(1);
/*
- * It's impolite to blast broadcast packets all over the place
- * when we don't really have to.
+ * Stay in sync with parent: wait for it to read our first
+ * message before sending the second.
*/
- if (!direct) {
- ifc.ifc_len = sizeof inbuf;
- ifc.ifc_buf = inbuf;
- if( ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
- close(sock);
- perror("ioctl(SIOCGIFCONF)");
- return -1;
- }
- ifr = ifc.ifc_req;
- ifreq.ifr_name[0] = '\0';
- for(i=0; i<ifc.ifc_len; i+=len, ifr=(struct ifreq *)((caddr_t)ifr+len)) {
-#if defined(BSD) && BSD >= 199103
- len = sizeof ifr->ifr_name + ifr->ifr_addr.sa_len;
-#else
- len = sizeof ifc.ifc_len / sizeof(struct ifreq);
-#endif
- ifreq = *ifr;
- if( ifreq.ifr_addr.sa_family != AF_INET)
- continue;
- if( ioctl(sock, SIOCGIFFLAGS, &ifreq) < 0) {
- perror("ioctl(SIOCGIFFLAGS)");
- continue;
- }
- if( (ifreq.ifr_flags & IFF_UP) == 0)
- continue;
-
- ifreq.ifr_flags &= (IFF_LOOPBACK | IFF_BROADCAST);
- if( ifreq.ifr_flags==IFF_BROADCAST ) {
- if( ioctl(sock, SIOCGIFBRDADDR, &ifreq) < 0 ) {
- perror("ioctl(SIOCGIFBRDADDR)");
- continue;
- }
- } else if( ifreq.ifr_flags==IFF_LOOPBACK ) {
- if( ioctl(sock, SIOCGIFADDR, &ifreq) < 0 ) {
- perror("ioctl(SIOCGIFADDR)");
- continue;
- }
- } else
- continue;
- in = ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr;
- bsin.sin_addr = in;
- if( sendto(rpcsock, buf, outlen, 0,
- (struct sockaddr *)&bsin, sizeof bsin) < 0 )
- perror("sendto");
- }
+
+ FD_ZERO(&fds);
+ FD_SET(fd[1], &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)
+ return(1);
} else {
- in = ((struct sockaddr_in *)&saddr)->sin_addr;
- bsin.sin_addr = in;
- if( sendto(rpcsock, buf, outlen, 0, (struct sockaddr *)&bsin,
- sizeof bsin) < 0 )
- perror("sendto");
+ return(1);
}
- close(sock);
- return 0;
+ close(fd[1]);
+ return (0);
}
-/*enum clnt_stat*/
-handle_replies()
+bool_t broadcast_result(out, addr)
+bool_t *out;
+struct sockaddr_in *addr;
+{
+ if (tell_parent(&broad_domain, addr))
+ syslog(LOG_WARNING, "lost connection to parent");
+ return TRUE;
+}
+
+/*
+ * The right way to send RPC broadcasts.
+ * Use the clnt_broadcast() RPC service. Unfortunately, clnt_broadcast()
+ * blocks while waiting for replies, so we have to fork off seperate
+ * broadcaster processes that do the waiting and then transmit their
+ * results back to the parent for processing. We also have to remember
+ * to save the name of the domain we're trying to bind in a global
+ * variable since clnt_broadcast() provides no way to pass things to
+ * the 'eachresult' callback function.
+ */
+void
+broadcast(ypdb)
+struct _dom_binding *ypdb;
{
- char buf[1400];
- int fromlen, inlen;
- struct sockaddr_in raddr;
- struct rpc_msg msg;
- XDR xdr;
-
-recv_again:
- bzero((char *)&xdr, sizeof(xdr));
- bzero((char *)&msg, sizeof(msg));
- msg.acpted_rply.ar_verf = _null_auth;
- msg.acpted_rply.ar_results.where = (caddr_t)&rmtcr;
- msg.acpted_rply.ar_results.proc = xdr_rmtcallres;
-
-try_again:
- fromlen = sizeof (struct sockaddr);
- inlen = recvfrom(rpcsock, buf, sizeof buf, 0,
- (struct sockaddr *)&raddr, &fromlen);
- if(inlen<0) {
- if(errno==EINTR)
- goto try_again;
- return RPC_CANTRECV;
+ bool_t out = FALSE;
+ enum clnt_stat stat;
+ int i;
+
+ if (children > MAX_CHILDREN)
+ return;
+
+ broad_domain = ypdb->dom_domain;
+
+ if (pipe(fd) < 0) {
+ syslog(LOG_WARNING, "pipe: %s",strerror(errno));
+ return;
}
- if(inlen<sizeof(u_long))
- goto recv_again;
- /*
- * see if reply transaction id matches sent id.
- * If so, decode the results.
- */
- xdrmem_create(&xdr, buf, (u_int)inlen, XDR_DECODE);
- if( xdr_replymsg(&xdr, &msg)) {
- if( (msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
- (msg.acpted_rply.ar_stat == SUCCESS)) {
- raddr.sin_port = htons((u_short)rmtcr_port);
- rpc_received(msg.rm_xid, &raddr, 0);
+ switch(fork()) {
+ case 0:
+ close(fd[0]);
+ break;
+ case -1:
+ syslog(LOG_WARNING, "fork: %s", strerror(errno));
+ close(fd[1]);
+ close(fd[0]);
+ return;
+ default:
+ for (i = 0; i < FD_SETSIZE; i++) {
+ if (child_fds[i] < 0) {
+ child_fds[i] = fd[0];
+ break;
+ }
}
+ close(fd[1]);
+ children++;
+ return;
}
- xdr.x_op = XDR_FREE;
- msg.acpted_rply.ar_results.proc = xdr_void;
- xdr_destroy(&xdr);
- return RPC_SUCCESS;
+ close(ypdb->dom_lockfd);
+ stat = clnt_broadcast(YPPROG, YPVERS, YPPROC_DOMAIN_NONACK,
+ xdr_domainname, (char *)ypdb->dom_domain, xdr_bool, (char *)&out,
+ broadcast_result);
+
+ if (stat != RPC_SUCCESS) {
+ syslog(LOG_WARNING, "NIS server for domain %s not responding",
+ ypdb->dom_domain);
+ bzero((char *)&ypdb->dom_server_addr,
+ sizeof(struct sockaddr_in));
+ if (tell_parent(&ypdb->dom_domain, &ypdb->dom_server_addr))
+ syslog(LOG_WARNING, "lost connection to parent");
+ }
+ exit(0);
}
/*
- * LOOPBACK IS MORE IMPORTANT: PUT IN HACK
+ * 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, which will cause checkwork() to dispatch a
+ * broadcaster process. 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
+ * every effort to keep our default domain bound, however, since we
+ * need it to keep the system on its feet.
*/
-rpc_received(dom, raddrp, force)
+int
+ping(ypdb, force)
+struct _dom_binding *ypdb;
+int force;
+{
+ bool_t out;
+ struct timeval interval, timeout;
+ enum clnt_stat stat;
+ int rpcsock = RPC_ANYSOCK;
+ time_t t;
+
+ interval.tv_sec = 5;
+ interval.tv_usec = 0;
+ timeout.tv_sec = FAIL_THRESHOLD;
+ timeout.tv_usec = 0;
+
+ if (ypdb->dom_broadcasting)
+ return(1);
+
+ if (!ypdb->dom_default && ypdb->dom_vers == -1 && !force)
+ 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;
+ flock(ypdb->dom_lockfd, LOCK_UN);
+ 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;
+ ypdb->dom_alive = 0;
+ ypdb->dom_vers = -1;
+ flock(ypdb->dom_lockfd, LOCK_UN);
+ return(1);
+ }
+ /*
+ * We pinged successfully. Reset the timer.
+ */
+ time(&t);
+ ypdb->dom_check = t + PING_INTERVAL;
+
+ return(0);
+}
+
+void rpc_received(dom, raddrp, force)
char *dom;
struct sockaddr_in *raddrp;
int force;
@@ -660,28 +648,21 @@ int force;
if(dom==NULL)
return;
+
+ for(ypdb=ypbindlist; ypdb; ypdb=ypdb->dom_pnext)
+ if( strcmp(ypdb->dom_domain, dom) == 0)
+ break;
+
/* 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_alive = -1;
return;
}
- for(ypdb=ypbindlist; ypdb; ypdb=ypdb->dom_pnext)
- if( strcmp(ypdb->dom_domain, dom) == 0)
- break;
-
- if (ypdb != NULL && ypdb->dom_vers == YPVERS && ypdb->dom_alive == 1 &&
- ypdb->dom_server_addr.sin_addr.s_addr != raddrp->sin_addr.s_addr)
- /*
- * We're received a second response to one of our broadcasts
- * from another server, and we've already bound: drop
- * the response on the floor. No sense changing servers
- * for no reason.
- */
- return;
-
if(ypdb==NULL) {
if(force==0)
return;
@@ -689,39 +670,32 @@ int force;
bzero((char *)ypdb, sizeof *ypdb);
strncpy(ypdb->dom_domain, dom, sizeof ypdb->dom_domain);
ypdb->dom_lockfd = -1;
+ ypdb->dom_default = 0;
ypdb->dom_pnext = ypbindlist;
ypbindlist = ypdb;
}
- /* soft update, alive, less than FAIL_THRESHOLD seconds old */
- if(ypdb->dom_alive==1 && (force==0 || ypdb->dom_answered == 0)
- && (ypdb->dom_check_t - FAIL_THRESHOLD) > time(NULL)
- && (ypdb->dom_server_addr.sin_port == raddrp->sin_port)) {
- ypdb->dom_answered = 1;
- ypdb->dom_interval = 60;
+ if (raddrp->sin_addr.s_addr == (long)0) {
+ ypdb->dom_broadcasting = 0;
return;
}
- /*
- * We've recovered from a crash: inform the world.
- */
- if (ypdb->dom_vers == 0)
- syslog(LOG_NOTICE, "NIS server [%s] for domain %s OK.",
- inet_ntoa(raddrp->sin_addr), ypdb->dom_domain);
+ /* 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 for domain %s OK",
+ 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_answered = 1;
- ypdb->dom_interval = 60;
- ypdb->dom_check_t = time(NULL) + ypdb->dom_interval;
+ ypdb->dom_broadcasting = 0;
if(ypdb->dom_lockfd != -1)
close(ypdb->dom_lockfd);
- sprintf(path, "%s/%s.%d", BINDINGDIR,
+ sprintf(path, "%s/%s.%ld", BINDINGDIR,
ypdb->dom_domain, ypdb->dom_vers);
#ifdef O_SHLOCK
if( (fd=open(path, O_CREAT|O_SHLOCK|O_RDWR|O_TRUNC, 0644)) == -1) {
@@ -755,7 +729,7 @@ int force;
ybr.ypbind_respbody.ypbind_bindinfo.ypbind_binding_port = raddrp->sin_port;
if( writev(ypdb->dom_lockfd, iov, 2) != iov[0].iov_len + iov[1].iov_len) {
- perror("write");
+ syslog(LOG_WARNING, "write: %s", strerror(errno));
close(ypdb->dom_lockfd);
ypdb->dom_lockfd = -1;
return;
OpenPOWER on IntegriCloud