summaryrefslogtreecommitdiffstats
path: root/usr.sbin/ypbind/ypbind.c
diff options
context:
space:
mode:
authorwpaul <wpaul@FreeBSD.org>1995-02-16 01:21:44 +0000
committerwpaul <wpaul@FreeBSD.org>1995-02-16 01:21:44 +0000
commit2d9bdef5534f858e9f5c0b38d45d3278cdfc3c2c (patch)
treeb5b50221179825e94075448be6f305998d1a834c /usr.sbin/ypbind/ypbind.c
parent4326ce34b6197aeee660ccb96e5544108f570494 (diff)
downloadFreeBSD-src-2d9bdef5534f858e9f5c0b38d45d3278cdfc3c2c.zip
FreeBSD-src-2d9bdef5534f858e9f5c0b38d45d3278cdfc3c2c.tar.gz
ypbind jumbo patch :)
The existing ypbind exhibits some truly anti-social behavior. After initially establishing a binding with an NIS server, the following events take place: - ypbind waits for 60 seconds before trying to broadcast a ping again - after the 60 seconds expires, ypbind sends out broadcasts every 5 seconds come hell or high water. These broadcasts travel far and wide, even to NIS servers in other domains which dutifully log the packets even though they don't respond to them. This leads to lots of unnecessary traffic and bloated log files. This behavior has been fixed/changed. Here's what happens now: - We still broadcast every 5 seconds at startup, just like before. - Once bound, we send out packets once every 60 seconds to the server we're bound to AND NO ONE ELSE. - If we fail to receive a reply from our server within FAIL_THRESHOLD seconds, we assume our server has croaked and go back to broadcasting everywhere every 5 seconds again until somebody answers. FAIL_THRESHOLD is currently set to 20 seconds. Other fixes/improvements: - ypbind now logs 'server not responding' and 'server OK' messages where appropriate. Thanks to Thomas Graichen <graichen@omega.physik.fu-berlin.de> for reporting the problem and guilt-tripping me into fixing it. :)
Diffstat (limited to 'usr.sbin/ypbind/ypbind.c')
-rw-r--r--usr.sbin/ypbind/ypbind.c168
1 files changed, 118 insertions, 50 deletions
diff --git a/usr.sbin/ypbind/ypbind.c b/usr.sbin/ypbind/ypbind.c
index 73ddcaa..63fa7f8 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.1 1994/08/08 01:03:58 wollman Exp $";
+static char rcsid[] = "$Id: ypbind.c,v 1.2 1994/09/23 10:25:38 davidg Exp $";
#endif
#include <sys/param.h>
@@ -39,7 +39,7 @@ static char rcsid[] = "$Id: ypbind.c,v 1.1 1994/08/08 01:03:58 wollman Exp $";
#include <sys/file.h>
#include <sys/fcntl.h>
#include <sys/uio.h>
-#include <sys/syslog.h>
+#include <syslog.h>
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
@@ -61,6 +61,14 @@ static char rcsid[] = "$Id: ypbind.c,v 1.1 1994/08/08 01:03:58 wollman Exp $";
#define BINDINGDIR "/var/yp/binding"
#endif
+/*
+ * Number of seconds to wait before for ping replies before we
+ * decide that our server is dead.
+ */
+#ifndef FAIL_THRESHOLD
+#define FAIL_THRESHOLD 20
+#endif
+
struct _dom_binding {
struct _dom_binding *dom_pnext;
char dom_domain[YPMAXDOMAIN + 1];
@@ -72,6 +80,8 @@ struct _dom_binding {
time_t dom_check_t;
int dom_lockfd;
int dom_alive;
+ int dom_answered;
+ int dom_interval;
};
extern bool_t xdr_domainname(), xdr_ypbind_resp();
@@ -135,7 +145,6 @@ CLIENT *clnt;
unlink(path);
ypdb->dom_pnext = ypbindlist;
ypbindlist = ypdb;
- check++;
return NULL;
}
@@ -158,7 +167,6 @@ CLIENT *clnt;
ypdb->dom_lockfd = -1;
sprintf(path, "%s/%s.%d", BINDINGDIR, ypdb->dom_domain, ypdb->dom_vers);
unlink(path);
- check++;
return NULL;
}
#endif
@@ -363,13 +371,18 @@ char **argv;
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->dom_vers);
(void)unlink(path);
+ openlog(argv[0], LOG_PID, LOG_AUTH);
width = getdtablesize();
+
while(1) {
fdsr = svc_fdset;
FD_SET(rpcsock, &fdsr);
@@ -389,8 +402,6 @@ char **argv;
handle_replies();
}
svc_getreqset(&fdsr);
- if(check)
- checkwork();
break;
}
}
@@ -404,25 +415,54 @@ char **argv;
* 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.
+ */
+
checkwork()
{
struct _dom_binding *ypdb;
time_t t;
- check = 0;
-
- time(&t);
for(ypdb=ypbindlist; ypdb; ypdb=ypdb->dom_pnext) {
- if(ypdb->dom_alive==0 || ypdb->dom_check_t < t) {
- broadcast(ypdb->dom_domain);
- time(&t);
- ypdb->dom_check_t = t + 5;
+ 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;
+ if (ypdb->dom_vers == 0)
+ syslog (LOG_NOTICE,
+ "NIS server [%s] for domain %s not responding.",
+ inet_ntoa(ypdb->dom_server_addr.sin_addr),
+ ypdb->dom_domain);
+ } 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;
}
}
}
-broadcast(dom)
+broadcast(dom, saddr, direct)
char *dom;
+struct sockaddr_in saddr;
+int direct;
{
struct rpc_msg rpcmsg;
char buf[1400], inbuf[8192];
@@ -487,51 +527,64 @@ char *dom;
return -1;
}
- 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)) {
+ /*
+ * It's impolite to blast broadcast packets all over the place
+ * when we don't really have to.
+ */
+ 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;
+ len = sizeof ifr->ifr_name + ifr->ifr_addr.sa_len;
#else
- len = sizeof ifc.ifc_len / sizeof(struct ifreq);
+ 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)");
+ ifreq = *ifr;
+ if( ifreq.ifr_addr.sa_family != AF_INET)
continue;
- }
- } else if( ifreq.ifr_flags==IFF_LOOPBACK ) {
- if( ioctl(sock, SIOCGIFADDR, &ifreq) < 0 ) {
- perror("ioctl(SIOCGIFADDR)");
+ if( ioctl(sock, SIOCGIFFLAGS, &ifreq) < 0) {
+ perror("ioctl(SIOCGIFFLAGS)");
continue;
}
- } else
- 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;
+ 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");
+ }
+ } 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");
}
+
close(sock);
return 0;
}
@@ -617,15 +670,30 @@ int force;
ypbindlist = ypdb;
}
- /* soft update, alive, less than 30 seconds old */
- if(ypdb->dom_alive==1 && force==0 && ypdb->dom_check_t<time(NULL)+30)
+ /* 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_answered = 1;
+ ypdb->dom_interval = 60;
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(ypdb->dom_server_addr.sin_addr),
+ ypdb->dom_domain);
bcopy((char *)raddrp, (char *)&ypdb->dom_server_addr,
sizeof ypdb->dom_server_addr);
- ypdb->dom_check_t = time(NULL) + 60; /* recheck binding in 60 seconds */
+
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;
if(ypdb->dom_lockfd != -1)
close(ypdb->dom_lockfd);
OpenPOWER on IntegriCloud