SUMMARY: NIS fails to respond after server reboot

From: Larry Augustin (lma@dayton.Stanford.EDU)
Date: Tue Mar 10 1992 - 21:32:38 CST


Thanks to all those who responded. To give credit where credit is due
their responses are appended. Most of this summary comes from John
DiMarco's response.

This is a standard problem with NIS. ypbind on the client caches the
address and port number of the ypserv on the server in
/var/yp/binding. When ypserv is restarted, it gets assigned a
different port number, so the old binding no longer works. But the
clients don't know this, so they keep trying the old binding until it
times out (a few minutes), then they broadcast for a new ypserv, at
which point the restarted ypserv replies, and things carry on as
usual.

Sun patch number 100342-01 makes ypbind ignore /var/yp/binding, and go
right away to the broadcast. This fixes the problem, but increases the
amount of broadcast traffic.

Casper Dik has posted a patch (appended) which causes ypbind to rebind
after a 10 second timeout.

Larry

========================================================================

From: Greg Higgins <higgins@math.niu.edu>
Newsgroups: comp.sys.sun.admin
Organization: Northern Illinois University

Do you have slave NIS servers? My experience has been that it takes about
15 minutes to switch from one NIS server to another. I don't know why,
and intend to investigate only if it gets to be a problem - which it
hasn't been so far.

========================================================================

From: casper@fwi.uva.nl (Casper H.S. Dik)
X-Organisation: Faculty of Mathematics & Computer Science
                University of Amsterdam
                Kruislaan 403
                NL-1098 SJ Amsterdam
                The Netherlands
X-Phone: +31 20 525 7463
X-Telex: 10262 hef nl
X-Fax: +31 20 525 7490
Subject: Re: HELP: clients slow to respond after NIS server reboot
Newsgroups: comp.sys.sun.admin

This is a well known problem with NIS. It should take approx. 3 minutes
after the first NIS request after a server reboot before a clients responds.

I've posted a fix sometime ago that rebinds in 10 seconds. The
problem was that it didn't work right for environments with multi-homed
hosts. Replacing ``clnt_udp.o'' in your shared library with
the appended version should help. (cc -c -pic -O clnt_udp.c; remake
shared library). When remaking a shared library, always install
a libc.sa.x.x.x with exactly the same revision as linc.so.x.x.x.
Just make it a hardlink to the highest numbered libc.sa.x.x.x

Casper

#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of shell archive."
# Contents: clnt_udp.c
# Wrapped by casper@fwi.uva.nl on Tue Mar 10 09:49:45 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'clnt_udp.c' -a "${1}" != "-c" ; then
  echo shar: Will not clobber existing file \"'clnt_udp.c'\"
else
echo shar: Extracting \"'clnt_udp.c'\" \(15661 characters\)
sed "s/^X//" >'clnt_udp.c' <<'END_OF_FILE'
X/* @(#)clnt_udp.c 2.2 88/08/01 4.0 RPCSRC */
X/*
X * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
X * unrestricted use provided that this legend is included on all tape
X * media and as a part of the software program in whole or part. Users
X * may copy or modify Sun RPC without charge, but are not authorized
X * to license or distribute it to anyone else except as part of a product or
X * program developed by the user.
X *
X * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
X * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
X * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
X *
X * Sun RPC is provided with no support and without any obligation on the
X * part of Sun Microsystems, Inc. to assist in its use, correction,
X * modification or enhancement.
X *
X * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
X * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
X * OR ANY PART THEREOF.
X *
X * In no event will Sun Microsystems, Inc. be liable for any lost revenue
X * or profits or other special, indirect and consequential damages, even if
X * Sun has been advised of the possibility of such damages.
X *
X * Sun Microsystems, Inc.
X * 2550 Garcia Avenue
X * Mountain View, California 94043
X */
X/*
X * Casper Dik (casper@fwi.uva.nl)
X * changed sendto in clntudp_call to connect/send.
X * This enables the caller to receive ICMP messages as Host or port unreachable
X * I thought that this would be a pretty straight forward solution.
X * However, connecting to multihomed hosts turned out not to be possible.
X * With TCP, you specify the remote address, this address will then be used
X * in all subsequent communications. In UDP, the remote address will be not
X * the address that you sepcified, but the address of the interface
X * ``closest'' to your host.
X * Because we don't want to lose all the benefits of connecting with
X * UDP the code has become pretty awkward.
X */
X#if !defined(lint) && defined(SCCSIDS)
Xstatic char sccsid[] = "@(#)clnt_udp.c 1.39 87/08/11 Copyr 1984 Sun Micro";
X#endif
X
X/*
X * clnt_udp.c, Implements a UDP/IP based, client side RPC.
X *
X * Copyright (C) 1984, Sun Microsystems, Inc.
X */
X
X#include <stdio.h>
X#include <rpc/rpc.h>
X#include <sys/socket.h>
X#include <sys/ioctl.h>
X#include <netdb.h>
X#include <errno.h>
X#include <rpc/pmap_prot.h>
X#include <rpc/pmap_clnt.h>
X
Xextern int errno;
X
X/*
X * UDP bases client side rpc operations
X */
Xstatic enum clnt_stat clntudp_call();
Xstatic void clntudp_abort();
Xstatic void clntudp_geterr();
Xstatic bool_t clntudp_freeres();
Xstatic bool_t clntudp_control();
Xstatic void clntudp_destroy();
X
Xstatic struct clnt_ops udp_ops = {
X clntudp_call,
X clntudp_abort,
X clntudp_geterr,
X clntudp_freeres,
X clntudp_destroy,
X clntudp_control
X};
X
X/*
X * Indication of the connection state of a UDP socket.
X * UDPCON_ALT - alternate between connected and unconnected.
X * UDPCON_DIS - not connected to specified raddr. (sw to alt after # tries)
X * UDPCON_CON - connected to specified raddr. (switch to alt after # tries)
X * UDPCON_RECV - connected to address from reply. (sw to alt after # tries)
X */
X
Xtypedef enum udpcon_t {
X UDPCON_ALT, UDPCON_DIS, UDPCON_CON, UDPCON_RECV
X} udpcon_t;
X
X/*
X * disassociate connection after number of tries. (switch to ALT)
X */
X#define UDPCON_DC_TIMEO 2
X#define UDPCON_RECV_TIMEO 5
X
X/*
X * The length of the period when alternating between connected and unconnected
X */
X#define UDPCON_PERIOD 2
X
X/*
X * Private data kept per client handle
X */
Xstruct cu_data {
X int cu_sock;
X bool_t cu_closeit;
X struct sockaddr_in cu_raddr;
X int cu_rlen;
X struct timeval cu_wait;
X struct timeval cu_total;
X struct rpc_err cu_error;
X XDR cu_outxdrs;
X u_int cu_xdrpos;
X u_int cu_sendsz;
X char *cu_outbuf;
X u_int cu_recvsz;
X char cu_inbuf[1];
X udpcon_t cu_constat;
X};
X
X/*
X * Create a UDP based client handle.
X * If *sockp<0, *sockp is set to a newly created UDP socket.
X * If raddr->sin_port is 0 a binder on the remote machine
X * is consulted for the correct port number.
X * NB: It is the clients responsibility to close *sockp.
X * NB: The rpch->cl_auth is initialized to null authentication.
X * Caller may wish to set this something more useful.
X *
X * wait is the amount of time used between retransmitting a call if
X * no response has been heard; retransmition occurs until the actual
X * rpc call times out.
X *
X * sendsz and recvsz are the maximum allowable packet sizes that can be
X * sent and received.
X */
XCLIENT *
Xclntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz)
X struct sockaddr_in *raddr;
X u_long program;
X u_long version;
X struct timeval wait;
X register int *sockp;
X u_int sendsz;
X u_int recvsz;
X{
X CLIENT *cl;
X register struct cu_data *cu;
X struct timeval now;
X struct rpc_msg call_msg;
X
X cl = (CLIENT *)mem_alloc(sizeof(CLIENT));
X if (cl == NULL) {
X (void) fprintf(stderr, "clntudp_create: out of memory\n");
X rpc_createerr.cf_stat = RPC_SYSTEMERROR;
X rpc_createerr.cf_error.re_errno = errno;
X goto fooy;
X }
X sendsz = ((sendsz + 3) / 4) * 4;
X recvsz = ((recvsz + 3) / 4) * 4;
X cu = (struct cu_data *)mem_alloc(sizeof(*cu) + sendsz + recvsz);
X if (cu == NULL) {
X (void) fprintf(stderr, "clntudp_create: out of memory\n");
X rpc_createerr.cf_stat = RPC_SYSTEMERROR;
X rpc_createerr.cf_error.re_errno = errno;
X goto fooy;
X }
X cu->cu_outbuf = &cu->cu_inbuf[recvsz];
X
X (void)gettimeofday(&now, (struct timezone *)0);
X if (raddr->sin_port == 0) {
X u_short port;
X if ((port =
X pmap_getport(raddr, program, version, IPPROTO_UDP)) == 0) {
X goto fooy;
X }
X cu->cu_constat = UDPCON_ALT;
X raddr->sin_port = htons(port);
X } else if (raddr->sin_port == htons(PMAPPORT)) {
X cu->cu_constat = UDPCON_DIS;
X } else
X cu->cu_constat = UDPCON_CON;
X cl->cl_ops = &udp_ops;
X cl->cl_private = (caddr_t)cu;
X cu->cu_raddr = *raddr;
X cu->cu_rlen = sizeof (cu->cu_raddr);
X cu->cu_wait = wait;
X cu->cu_total.tv_sec = -1;
X cu->cu_total.tv_usec = -1;
X cu->cu_sendsz = sendsz;
X cu->cu_recvsz = recvsz;
X call_msg.rm_xid = getpid() ^ now.tv_sec ^ now.tv_usec;
X call_msg.rm_direction = CALL;
X call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
X call_msg.rm_call.cb_prog = program;
X call_msg.rm_call.cb_vers = version;
X xdrmem_create(&(cu->cu_outxdrs), cu->cu_outbuf,
X sendsz, XDR_ENCODE);
X if (! xdr_callhdr(&(cu->cu_outxdrs), &call_msg)) {
X goto fooy;
X }
X cu->cu_xdrpos = XDR_GETPOS(&(cu->cu_outxdrs));
X if (*sockp < 0) {
X int dontblock = 1;
X
X *sockp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
X if (*sockp < 0) {
X rpc_createerr.cf_stat = RPC_SYSTEMERROR;
X rpc_createerr.cf_error.re_errno = errno;
X goto fooy;
X }
X /* attempt to bind to prov port */
X (void)bindresvport(*sockp, (struct sockaddr_in *)0);
X /* the sockets rpc controls are non-blocking */
X (void)ioctl(*sockp, FIONBIO, (char *) &dontblock);
X cu->cu_closeit = TRUE;
X } else {
X cu->cu_closeit = FALSE;
X }
X cu->cu_sock = *sockp;
X cl->cl_auth = authnone_create();
X return (cl);
Xfooy:
X if (cu)
X mem_free((caddr_t)cu, sizeof(*cu) + sendsz + recvsz);
X if (cl)
X mem_free((caddr_t)cl, sizeof(CLIENT));
X return ((CLIENT *)NULL);
X}
X
XCLIENT *
Xclntudp_create(raddr, program, version, wait, sockp)
X struct sockaddr_in *raddr;
X u_long program;
X u_long version;
X struct timeval wait;
X register int *sockp;
X{
X
X return(clntudp_bufcreate(raddr, program, version, wait, sockp,
X UDPMSGSIZE, UDPMSGSIZE));
X}
X
Xstatic enum clnt_stat
Xclntudp_call(cl, proc, xargs, argsp, xresults, resultsp, utimeout)
X register CLIENT *cl; /* client handle */
X u_long proc; /* procedure number */
X xdrproc_t xargs; /* xdr routine for args */
X caddr_t argsp; /* pointer to args */
X xdrproc_t xresults; /* xdr routine for results */
X caddr_t resultsp; /* pointer to results */
X struct timeval utimeout; /* seconds to wait before giving up */
X{
X register struct cu_data *cu = (struct cu_data *)cl->cl_private;
X register XDR *xdrs;
X register int outlen;
X register int inlen;
X int fromlen;
X#ifdef FD_SETSIZE
X fd_set readfds;
X fd_set mask;
X#else
X int readfds;
X register int mask;
X#endif /* def FD_SETSIZE */
X struct sockaddr_in from;
X struct rpc_msg reply_msg;
X XDR reply_xdrs;
X struct timeval time_waited;
X bool_t ok;
X int nrefreshes = 2; /* number of times to refresh cred */
X struct timeval timeout;
X int ntries;
X udpcon_t udphow;
X
X if (cu->cu_total.tv_usec == -1) {
X timeout = utimeout; /* use supplied timeout */
X } else {
X timeout = cu->cu_total; /* use default timeout */
X }
X
X time_waited.tv_sec = 0;
X time_waited.tv_usec = 0;
Xcall_again:
X xdrs = &(cu->cu_outxdrs);
X xdrs->x_op = XDR_ENCODE;
X XDR_SETPOS(xdrs, cu->cu_xdrpos);
X /*
X * the transaction is the first thing in the out buffer
X */
X (*(u_short *)(cu->cu_outbuf))++;
X if ((! XDR_PUTLONG(xdrs, (long *)&proc)) ||
X (! AUTH_MARSHALL(cl->cl_auth, xdrs)) ||
X (! (*xargs)(xdrs, argsp)))
X return (cu->cu_error.re_status = RPC_CANTENCODEARGS);
X outlen = (int)XDR_GETPOS(xdrs);
X
X /*
X * Give error (ECONNREFUSED/EHOSTUNREACH) instead of timeout.
X * Gives much faster NIS rebinding.
X * Errors are not detected here, but in the recvfrom()
X * following the select().
X */
X
X udphow = UDPCON_DIS;
X ntries = 0;
X if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
X cu->cu_constat = UDPCON_DIS;
X }
X
Xsend_again:
X ntries++;
X
X switch (cu->cu_constat) {
X case UDPCON_CON:
X if (ntries > UDPCON_DC_TIMEO) {
X udphow = UDPCON_DIS;
X cu->cu_constat = UDPCON_ALT;
X } else {
X udphow = UDPCON_CON;
X }
X break;
X case UDPCON_DIS:
X if (ntries > UDPCON_DC_TIMEO) {
X udphow = UDPCON_CON;
X cu->cu_constat = UDPCON_ALT;
X } else {
X udphow = UDPCON_DIS;
X }
X break;
X case UDPCON_RECV:
X if (ntries > UDPCON_RECV_TIMEO) {
X udphow = UDPCON_DIS;
X cu->cu_constat = UDPCON_ALT;
X } else {
X udphow = UDPCON_CON;
X }
X break;
X case UDPCON_ALT:
X /* switch udphow from CON <-> DIS */
X if ((ntries % UDPCON_PERIOD) == 0) {
X udphow = UDPCON_DIS + UDPCON_CON - udphow;
X }
X break;
X }
X
X if (udphow == UDPCON_CON && cu->cu_constat != UDPCON_RECV) {
X if (connect(cu->cu_sock, (struct sockaddr *) &cu->cu_raddr,
X cu->cu_rlen) != 0)
X udphow = cu->cu_constat = UDPCON_DIS;
X }
X if (udphow != UDPCON_CON) {
X /* disconnect */
X connect(cu->cu_sock,(struct sockaddr *) 0, 0);
X if (sendto(cu->cu_sock, cu->cu_outbuf, outlen, 0,
X (struct sockaddr *) &cu->cu_raddr, cu->cu_rlen) != outlen) {
X cu->cu_error.re_errno = errno;
X return (cu->cu_error.re_status = RPC_CANTSEND);
X }
X } else {
X if (send(cu->cu_sock, cu->cu_outbuf, outlen, 0) != outlen) {
X cu->cu_error.re_errno = errno;
X return (cu->cu_error.re_status = RPC_CANTSEND);
X }
X }
X
X /*
X * Hack to provide rpc-based message passing
X */
X if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
X return (cu->cu_error.re_status = RPC_TIMEDOUT);
X }
X /*
X * sub-optimal code appears here because we have
X * some clock time to spare while the packets are in flight.
X * (We assume that this is actually only executed once.)
X */
X reply_msg.acpted_rply.ar_verf = _null_auth;
X reply_msg.acpted_rply.ar_results.where = resultsp;
X reply_msg.acpted_rply.ar_results.proc = xresults;
X#ifdef FD_SETSIZE
X FD_ZERO(&mask);
X FD_SET(cu->cu_sock, &mask);
X#else
X mask = 1 << cu->cu_sock;
X#endif /* def FD_SETSIZE */
X for (;;) {
X readfds = mask;
X switch (select(_rpc_dtablesize(), &readfds, (int *)NULL,
X (int *)NULL, &(cu->cu_wait))) {
X
X case 0:
X time_waited.tv_sec += cu->cu_wait.tv_sec;
X time_waited.tv_usec += cu->cu_wait.tv_usec;
X while (time_waited.tv_usec >= 1000000) {
X time_waited.tv_sec++;
X time_waited.tv_usec -= 1000000;
X }
X if ((time_waited.tv_sec < timeout.tv_sec) ||
X ((time_waited.tv_sec == timeout.tv_sec) &&
X (time_waited.tv_usec < timeout.tv_usec)))
X goto send_again;
X cu->cu_constat = UDPCON_ALT;
X return (cu->cu_error.re_status = RPC_TIMEDOUT);
X
X /*
X * buggy in other cases because time_waited is not being
X * updated.
X */
X case -1:
X if (errno == EINTR)
X continue;
X cu->cu_error.re_errno = errno;
X return (cu->cu_error.re_status = RPC_CANTRECV);
X }
X do {
X fromlen = sizeof(struct sockaddr);
X inlen = recvfrom(cu->cu_sock, cu->cu_inbuf,
X (int) cu->cu_recvsz, 0,
X (struct sockaddr *)&from, &fromlen);
X } while (inlen < 0 && errno == EINTR);
X if (inlen < 0) {
X if (errno == EWOULDBLOCK)
X continue;
X cu->cu_error.re_errno = errno;
X if (errno == EHOSTUNREACH || errno == ECONNREFUSED)
X return (cu->cu_error.re_status = RPC_SYSTEMERROR);
X else
X return (cu->cu_error.re_status = RPC_CANTRECV);
X }
X if (inlen < sizeof(u_long))
X continue;
X /* see if reply transaction id matches sent id */
X if (*((u_long *)(cu->cu_inbuf)) != *((u_long *)(cu->cu_outbuf)))
X continue;
X /* we now assume we have the proper reply */
X break;
X }
X
X /*
X * now decode and validate the response
X */
X xdrmem_create(&reply_xdrs, cu->cu_inbuf, (u_int)inlen, XDR_DECODE);
X ok = xdr_replymsg(&reply_xdrs, &reply_msg);
X /* XDR_DESTROY(&reply_xdrs); save a few cycles on noop destroy */
X if (ok) {
X /*
X * Valid response. Let's connect. Must connect to from
X * address. The address we use as destination might be
X * on another interface. If the server replies from a
X * different socket, we can't use connect at all.
X */
X
X if (cu->cu_constat != UDPCON_RECV &&
X from.sin_port == cu->cu_raddr.sin_port &&
X connect(cu->cu_sock, (struct sockaddr *)&from,
X fromlen) == 0) {
X cu->cu_constat = UDPCON_RECV;
X }
X
X _seterr_reply(&reply_msg, &(cu->cu_error));
X if (cu->cu_error.re_status == RPC_SUCCESS) {
X if (! AUTH_VALIDATE(cl->cl_auth,
X &reply_msg.acpted_rply.ar_verf)) {
X cu->cu_error.re_status = RPC_AUTHERROR;
X cu->cu_error.re_why = AUTH_INVALIDRESP;
X }
X if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) {
X xdrs->x_op = XDR_FREE;
X (void)xdr_opaque_auth(xdrs,
X &(reply_msg.acpted_rply.ar_verf));
X }
X } /* end successful completion */
X else {
X /* maybe our credentials need to be refreshed ... */
X if (nrefreshes > 0 && AUTH_REFRESH(cl->cl_auth)) {
X nrefreshes--;
X goto call_again;
X }
X } /* end of unsuccessful completion */
X } /* end of valid reply message */
X else {
X cu->cu_error.re_status = RPC_CANTDECODERES;
X }
X return (cu->cu_error.re_status);
X}
X
Xstatic void
Xclntudp_geterr(cl, errp)
X CLIENT *cl;
X struct rpc_err *errp;
X{
X register struct cu_data *cu = (struct cu_data *)cl->cl_private;
X
X *errp = cu->cu_error;
X}
X
X
Xstatic bool_t
Xclntudp_freeres(cl, xdr_res, res_ptr)
X CLIENT *cl;
X xdrproc_t xdr_res;
X caddr_t res_ptr;
X{
X register struct cu_data *cu = (struct cu_data *)cl->cl_private;
X register XDR *xdrs = &(cu->cu_outxdrs);
X
X xdrs->x_op = XDR_FREE;
X return ((*xdr_res)(xdrs, res_ptr));
X}
X
Xstatic void
Xclntudp_abort(/*h*/)
X /*CLIENT *h;*/
X{
X}
X
Xstatic bool_t
Xclntudp_control(cl, request, info)
X CLIENT *cl;
X int request;
X char *info;
X{
X register struct cu_data *cu = (struct cu_data *)cl->cl_private;
X
X switch (request) {
X case CLSET_TIMEOUT:
X cu->cu_total = *(struct timeval *)info;
X break;
X case CLGET_TIMEOUT:
X *(struct timeval *)info = cu->cu_total;
X break;
X case CLSET_RETRY_TIMEOUT:
X cu->cu_wait = *(struct timeval *)info;
X break;
X case CLGET_RETRY_TIMEOUT:
X *(struct timeval *)info = cu->cu_wait;
X break;
X case CLGET_SERVER_ADDR:
X *(struct sockaddr_in *)info = cu->cu_raddr;
X break;
X default:
X return (FALSE);
X }
X return (TRUE);
X}
X
Xstatic void
Xclntudp_destroy(cl)
X CLIENT *cl;
X{
X register struct cu_data *cu = (struct cu_data *)cl->cl_private;
X
X if (cu->cu_closeit) {
X (void)close(cu->cu_sock);
X }
X XDR_DESTROY(&(cu->cu_outxdrs));
X mem_free((caddr_t)cu, (sizeof(*cu) + cu->cu_sendsz + cu->cu_recvsz));
X mem_free((caddr_t)cl, sizeof(CLIENT));
X}
END_OF_FILE
if test 15661 -ne `wc -c <'clnt_udp.c'`; then
    echo shar: \"'clnt_udp.c'\" unpacked with wrong size!
fi
# end of 'clnt_udp.c'
fi
echo shar: End of shell archive.
exit 0

========================================================================

From: stas@cbnewsh.att.com (Stanley J Ciesielski)
Subject: Re: HELP: clients slow to respond after NIS server reboot
Newsgroups: comp.sys.sun.admin

The problem you descibed is a bug with the Sun OS. I was looking at the
patches available at 1-800-477-4768, and that was one of them. The patch
#100342-02 Supposedly fixes this. Call SUN or use the 1-800 number
and log in as guest.

========================================================================

From: John DiMarco <jdd@db.toronto.edu>
To: lma@dayton.Stanford.EDU
Subject: Re: HELP: clients slow to respond after NIS server reboot
Newsgroups: comp.sys.sun.admin

This is a standard problem with NIS. Basically, all the ypbinds on the clients
cache the address and port number of the ypserv on the server in
/var/yp/binding. When ypserv is restarted, it gets assigned a different
port number, and the old binding won't work anymore. But the clients don't
know this, so they keep trying the old binding until it times out (a few
minutes), then they broadcast for a new ypserv, at which point the
restarted ypserv replies, and things carry on as usual.

Sun has a "patch" for this which makes the ypbinds ignore /var/yp/binding,
and go right away to the broadcast. This fixes the problem, but increases
the amount of broadcast traffic.

If you want the patch, it's patch number 100342-01. We haven't bothered.

When it happens, just be patient. No need to reboot the client.

========================================================================



This archive was generated by hypermail 2.1.2 : Fri Sep 28 2001 - 23:06:37 CDT