Subject: bin/1759: forcing specific servers for ypbind(8) to bind to
To: None <gnats-bugs@gnats.netbsd.org>
From: Luke Mewburn <lukem@supp.cpr.itg.telecom.com.au>
List: netbsd-bugs
Date: 11/13/1995 18:11:11
>Number:         1759
>Category:       bin
>Synopsis:       ypbind needs ability to bind to specific servers
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    bin-bug-people (Utility Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Nov 13 02:35:00 1995
>Last-Modified:
>Originator:     Luke Mewburn
>Organization:
Werj
>Release:        951112
>Environment:
	
System: ULTRIX balrog 4.4 0 RISC
Machine: mips
>Description:
	NetBSD's ypbind only supports broadcast/ypset/ypsetme modes
	of operation. There is no way to explicitly force a binding
	to server(s) of your choice. This is a security issue.
	(YP has security problems, but if you can force a specific
	ypserver, then some of the issues are resolved.)

>How-To-Repeat:
	run ypbind and without using ypset (a problem anyway), try and
	get ypbind to bind to your preferred server.

>Fix:
	apply this patch. it's a bit "quick and dirty", but then again,
	the ypbind code leaves a lot to be desired about being ``clean
	code'' anyway... This patch fixes the complaints that
	"gcc -Wall" has as well.

	To take advantage of this code, create a file called
		/var/yp/`domainname`/.ypservers
	that contains one line per ypserver that you wish to connect to.


diff -cbr /ftp/pub/NetBSD/NetBSD-current/src/usr.sbin/ypbind/Makefile ypbind/Makefile
*** /ftp/pub/NetBSD/NetBSD-current/src/usr.sbin/ypbind/Makefile	Sat Oct 14 15:07:00 1995
--- ypbind/Makefile	Mon Nov 13 18:04:15 1995
***************
*** 3,8 ****
  
  PROG=	ypbind
  MAN=	ypbind.8
! CFLAGS+=-DDAEMON -DHEURISTIC
  
  .include <bsd.prog.mk>
--- 3,8 ----
  
  PROG=	ypbind
  MAN=	ypbind.8
! CFLAGS+=-DHEURISTIC
  
  .include <bsd.prog.mk>
diff -cbr /ftp/pub/NetBSD/NetBSD-current/src/usr.sbin/ypbind/ypbind.8 ypbind/ypbind.8
*** /ftp/pub/NetBSD/NetBSD-current/src/usr.sbin/ypbind/ypbind.8	Sat Oct 14 15:07:00 1995
--- ypbind/ypbind.8	Mon Nov 13 18:01:06 1995
***************
*** 38,49 ****
  .Nm ypbind
  .Nd create and maintain a binding to a YP server
  .Sh SYNOPSIS
! .Nm ypbind
  .Op Fl ypset
! .Nm ypbind
  .Op Fl ypsetme
  .Sh DESCRIPTION
! .Nm Ypbind
  finds the server for a particular YP domain and stores information about it
  in a
  .Pa binding file.
--- 38,51 ----
  .Nm ypbind
  .Nd create and maintain a binding to a YP server
  .Sh SYNOPSIS
! .Nm
  .Op Fl ypset
! .Nm
  .Op Fl ypsetme
+ .Nm
+ .Op Fl broadcast
  .Sh DESCRIPTION
! .Nm
  finds the server for a particular YP domain and stores information about it
  in a
  .Pa binding file.
***************
*** 55,75 ****
  .Pa domainname.version.
  (The YP system only supplies information on version 2.)
  .Pp
! When
! .Nm ypbind
! starts, it broadcasts looking for a process willing to serve maps for the
! client's domain.  Once a binding is established,
! .Nm ypbind
  maintains this binding by periodically communicating with the server to which
! it is bound.  If the binding is somehow lost, e.g by server reboot,
! .Nm ypbind
  marks the domain as unbound and attempts to re-establish the binding.
  When the binding is once again successful,
! .Nm ypbind
  marks the domain as bound and resumes its periodic check.
  .Pp
  The options are as follows:
! .Bl -tag -width indent
  .It Fl ypset
  .Xr ypset 8
  may be used to change the server to which a domain is bound.
--- 57,95 ----
  .Pa domainname.version.
  (The YP system only supplies information on version 2.)
  .Pp
! If
! .Nm
! is started with the
! .Fl broadcast
! option, it broadcasts looking for a process willing to serve maps for the
! client's domain.
! .Pp
! If
! .NM
! is started without the
! .Fl broadcast
! option,
! .Nm
! steps through the list of YP servers specified in
! .Pa /var/yp/domainname/.ypservers
! and contacts each in turn attempting to bind to that server. 
! It is strongly recommended that these hosts are in the local
! hosts file, and that hosts are looked up in local files before
! the YP hosts map.
! .Pp
! Once a binding is established,
! .Nm
  maintains this binding by periodically communicating with the server to which
! it is bound.
! If the binding is somehow lost, e.g by server reboot,
! .Nm
  marks the domain as unbound and attempts to re-establish the binding.
  When the binding is once again successful,
! .Nm
  marks the domain as bound and resumes its periodic check.
  .Pp
  The options are as follows:
! .Bl -tag -width "-broadcast"
  .It Fl ypset
  .Xr ypset 8
  may be used to change the server to which a domain is bound.
***************
*** 77,89 ****
  .Xr ypset 8
  may be used only from this machine to change the server
  to which a domain is bound.
  .El
  .Pp
  The
  .Fl ypset
! and
  .Fl ypsetme
! options are dangerous and should be avoided.
  .Pp
  If the directory
  .Pa /var/yp
--- 97,113 ----
  .Xr ypset 8
  may be used only from this machine to change the server
  to which a domain is bound.
+ .It Fl broadcast
+ sends a broadcast requesting for a YP server to bind to.
  .El
  .Pp
  The
  .Fl ypset
! ,
  .Fl ypsetme
! and
! .Fl broadcast
! options are inherently insecure and should be avoided.
  .Pp
  If the directory
  .Pa /var/yp
***************
*** 92,97 ****
--- 116,123 ----
  .Sh FILES
  .Pa /var/yp/bindings/domainname.version
  - binding file for domainname
+ .Pa /var/yp/domainname/.ypservers
+ - explicit servers to bind to.
  .Sh SEE ALSO
  .Xr domainname 1 ,
  .Xr ypcat 1 ,
diff -cbr /ftp/pub/NetBSD/NetBSD-current/src/usr.sbin/ypbind/ypbind.c ypbind/ypbind.c
*** /ftp/pub/NetBSD/NetBSD-current/src/usr.sbin/ypbind/ypbind.c	Sat Oct 14 15:07:00 1995
--- ypbind/ypbind.c	Mon Nov 13 18:03:56 1995
***************
*** 31,40 ****
   */
  
  #ifndef LINT
! static char rcsid[] = "$Id: ypbind.c,v 1.19 1995/04/21 04:40:36 cgd Exp $";
  #endif
  
  #include <sys/param.h>
  #include <sys/types.h>
  #include <sys/ioctl.h>
  #include <sys/signal.h>
--- 31,41 ----
   */
  
  #ifndef LINT
! static char rcsid[] = "$NetBSD: ypbind.c,v 1.19 1995/04/21 04:40:36 cgd Exp $";
  #endif
  
  #include <sys/param.h>
+ #include <sys/stat.h>
  #include <sys/types.h>
  #include <sys/ioctl.h>
  #include <sys/signal.h>
***************
*** 61,67 ****
  #include <rpcsvc/yp_prot.h>
  #include <rpcsvc/ypclnt.h>
  
! #define BINDINGDIR	"/var/yp/binding"
  #define YPBINDLOCK	"/var/run/ypbind.lock"
  
  struct _dom_binding {
--- 62,70 ----
  #include <rpcsvc/yp_prot.h>
  #include <rpcsvc/ypclnt.h>
  
! #define VARYPDIR	"/var/yp/"
! #define SERVERSFILE	".ypservers"
! #define BINDINGDIR	__CONCAT(VARYPDIR, "binding")
  #define YPBINDLOCK	"/var/run/ypbind.lock"
  
  struct _dom_binding {
***************
*** 87,96 ****
  struct _dom_binding *ypbindlist;
  int check;
  
! #define YPSET_NO	0
! #define YPSET_LOCAL	1
! #define YPSET_ALL	2
! int ypsetmode = YPSET_NO;
  
  int rpcsock, pingsock;
  struct rmtcallargs rmtca;
--- 90,99 ----
  struct _dom_binding *ypbindlist;
  int check;
  
! enum _ypbindmode {
! 	YPBIND_DIRECT, YPBIND_BROADCAST, YPBIND_SETLOCAL, YPBIND_SETALL
! };
! static enum _ypbindmode ypbindmode;
  
  int rpcsock, pingsock;
  struct rmtcallargs rmtca;
***************
*** 99,104 ****
--- 102,117 ----
  u_long rmtcr_port;
  SVCXPRT *udptransp, *tcptransp;
  
+ void	checkwork	__P((void));
+ void	rpc_received	__P((char *, struct sockaddr_in *, int));
+ int	handle_replies	__P((void));
+ int	handle_ping	__P((void));
+ int	ping		__P((struct _dom_binding *));
+ int	nag_servers	__P((struct _dom_binding *));
+ int	broadcast	__P((char *, int));
+ int	direct		__P((char *, int));
+ 
+ 
  void *
  ypbindproc_null_2(transp, argp, clnt)
  	SVCXPRT *transp;
***************
*** 136,142 ****
  		ypdb->dom_vers = YPVERS;
  		ypdb->dom_alive = 0;
  		ypdb->dom_lockfd = -1;
! 		sprintf(path, "%s/%s.%d", BINDINGDIR, ypdb->dom_domain, ypdb->dom_vers);
  		unlink(path);
  		ypdb->dom_pnext = ypbindlist;
  		ypbindlist = ypdb;
--- 149,156 ----
  		ypdb->dom_vers = YPVERS;
  		ypdb->dom_alive = 0;
  		ypdb->dom_lockfd = -1;
! 		sprintf(path, "%s/%s.%d", BINDINGDIR, ypdb->dom_domain, 
! 				(int)ypdb->dom_vers);
  		unlink(path);
  		ypdb->dom_pnext = ypbindlist;
  		ypbindlist = ypdb;
***************
*** 164,170 ****
  	ypdb->dom_ask_t = now;
  #endif
  
- 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;
--- 178,183 ----
***************
*** 188,201 ****
  	memset(&res, 0, sizeof(res));
  	fromsin = svc_getcaller(transp);
  
! 	switch (ypsetmode) {
! 	case YPSET_LOCAL:
  		if (fromsin->sin_addr.s_addr != htonl(INADDR_LOOPBACK))
  			return (bool_t *)NULL;
  		break;
! 	case YPSET_ALL:
  		break;
! 	case YPSET_NO:
  	default:
  		return (bool_t *)NULL;
  	}
--- 201,215 ----
  	memset(&res, 0, sizeof(res));
  	fromsin = svc_getcaller(transp);
  
! 	switch (ypbindmode) {
! 	case YPBIND_SETLOCAL:
  		if (fromsin->sin_addr.s_addr != htonl(INADDR_LOOPBACK))
  			return (bool_t *)NULL;
  		break;
! 	case YPBIND_SETALL:
  		break;
! 	case YPBIND_DIRECT:
! 	case YPBIND_BROADCAST:
  	default:
  		return (bool_t *)NULL;
  	}
***************
*** 279,284 ****
--- 293,299 ----
  	return;
  }
  
+ int
  main(argc, argv)
  	int argc;
  	char *argv[];
***************
*** 298,306 ****
  	while (--argc) {
  		++argv;
  		if (!strcmp("-ypset", *argv))
! 			ypsetmode = YPSET_ALL;
  		else if (!strcmp("-ypsetme", *argv))
! 			ypsetmode = YPSET_LOCAL;
  	}
  
  	/* blow away everything in BINDINGDIR */
--- 313,323 ----
  	while (--argc) {
  		++argv;
  		if (!strcmp("-ypset", *argv))
! 			ypbindmode = YPBIND_SETALL;
  		else if (!strcmp("-ypsetme", *argv))
! 			ypbindmode = YPBIND_SETLOCAL;
! 		else if (!strcmp("-broadcast", *argv))
! 			ypbindmode = YPBIND_BROADCAST;
  	}
  
  	/* blow away everything in BINDINGDIR */
***************
*** 342,347 ****
--- 359,365 ----
  		exit(1);
  	}
  
+ 		/* XXX: use SOCK_STREAM for direct queries? */
  	if ((rpcsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
  		perror("socket");
  		return -1;
***************
*** 372,390 ****
  	ypbindlist->dom_alive = 0;
  	ypbindlist->dom_lockfd = -1;
  	sprintf(path, "%s/%s.%d", BINDINGDIR, ypbindlist->dom_domain,
! 		ypbindlist->dom_vers);
  	(void)unlink(path);
  
  	checkwork();
  
- 	while (1) {
  		width = svc_maxfd;
  		if (rpcsock > width)
  			width = rpcsock;
  		if (pingsock > width)
  			width = pingsock;
  		width++;
! 
  		fdsr = svc_fdset;
  		FD_SET(rpcsock, &fdsr);
  		FD_SET(pingsock, &fdsr);
--- 390,407 ----
  	ypbindlist->dom_alive = 0;
  	ypbindlist->dom_lockfd = -1;
  	sprintf(path, "%s/%s.%d", BINDINGDIR, ypbindlist->dom_domain,
! 		(int)ypbindlist->dom_vers);
  	(void)unlink(path);
  
  	checkwork();
  
  	width = svc_maxfd;
  	if (rpcsock > width)
  		width = rpcsock;
  	if (pingsock > width)
  		width = pingsock;
  	width++;
! 	while (1) {
  		fdsr = svc_fdset;
  		FD_SET(rpcsock, &fdsr);
  		FD_SET(pingsock, &fdsr);
***************
*** 400,408 ****
  			break;
  		default:
  			if (FD_ISSET(rpcsock, &fdsr))
! 				handle_replies();
  			if (FD_ISSET(pingsock, &fdsr))
! 				handle_ping();
  			svc_getreqset(&fdsr);
  			if (check)
  				checkwork();
--- 417,425 ----
  			break;
  		default:
  			if (FD_ISSET(rpcsock, &fdsr))
! 				(void)handle_replies();
  			if (FD_ISSET(pingsock, &fdsr))
! 				(void)handle_ping();
  			svc_getreqset(&fdsr);
  			if (check)
  				checkwork();
***************
*** 426,431 ****
--- 443,449 ----
   * checking	timeout		ping server + broadcast	checking	5 sec
   * checking	answer		--			binding		60 sec
   */
+ void
  checkwork()
  {
  	struct _dom_binding *ypdb;
***************
*** 439,451 ****
  			if (ypdb->dom_alive == 1)
  				ping(ypdb);
  			else
! 				broadcast(ypdb);
  			time(&t);
  			ypdb->dom_check_t = t + 5;
  		}
  	}
  }
  
  ping(ypdb)
  	struct _dom_binding *ypdb;
  {
--- 457,470 ----
  			if (ypdb->dom_alive == 1)
  				ping(ypdb);
  			else
! 				nag_servers(ypdb);
  			time(&t);
  			ypdb->dom_check_t = t + 5;
  		}
  	}
  }
  
+ int
  ping(ypdb)
  	struct _dom_binding *ypdb;
  {
***************
*** 503,521 ****
  
  }
  
! broadcast(ypdb)
  	struct _dom_binding *ypdb;
  {
  	char *dom = ypdb->dom_domain;
  	struct rpc_msg msg;
! 	char buf[1400], inbuf[8192];
  	char path[MAXPATHLEN];
  	enum clnt_stat st;
! 	int outlen, i, sock, len;
! 	struct sockaddr_in bindsin;
! 	struct ifconf ifc;
! 	struct ifreq ifreq, *ifr;
! 	struct in_addr in;
  	AUTH *rpcua;
  	XDR xdr;
  
--- 522,537 ----
  
  }
  
! int
! nag_servers(ypdb)
  	struct _dom_binding *ypdb;
  {
  	char *dom = ypdb->dom_domain;
  	struct rpc_msg msg;
! 	char buf[1400];
  	char path[MAXPATHLEN];
  	enum clnt_stat st;
! 	int outlen;
  	AUTH *rpcua;
  	XDR xdr;
  
***************
*** 563,576 ****
  		close(ypdb->dom_lockfd);
  		ypdb->dom_lockfd = -1;
  		sprintf(path, "%s/%s.%d", BINDINGDIR,
! 			ypdb->dom_domain, ypdb->dom_vers);
  		unlink(path);
  	}
  
- 	memset(&bindsin, 0, sizeof bindsin);
- 	bindsin.sin_family = AF_INET;
- 	bindsin.sin_len = sizeof(bindsin);
- 	bindsin.sin_port = htons(PMAPPORT);
  
  	if (ypdb->dom_alive == 2) {
  		/*
--- 579,588 ----
  		close(ypdb->dom_lockfd);
  		ypdb->dom_lockfd = -1;
  		sprintf(path, "%s/%s.%d", BINDINGDIR,
! 			ypdb->dom_domain, (int)ypdb->dom_vers);
  		unlink(path);
  	}
  
  
  	if (ypdb->dom_alive == 2) {
  		/*
***************
*** 578,594 ****
--- 590,635 ----
  		 * ypserver on other subnet was once bound,
  		 * but rebooted and is now using a different port
  		 */
+ 		struct sockaddr_in bindsin;
+ 
+ 		memset(&bindsin, 0, sizeof bindsin);
+ 		bindsin.sin_family = AF_INET;
+ 		bindsin.sin_len = sizeof(bindsin);
+ 		bindsin.sin_port = htons(PMAPPORT);
  		bindsin.sin_addr = ypdb->dom_server_addr.sin_addr;
  		if (sendto(rpcsock, buf, outlen, 0, (struct sockaddr *)&bindsin,
  			   sizeof bindsin) < 0)
  			perror("sendto");
  	}
+ 	if (ypbindmode == YPBIND_BROADCAST)
+ 		return broadcast(buf, outlen);
+ 	else
+ 		return direct(buf, outlen);
+ }
+ 
+ int
+ broadcast(buf, outlen)
+ 	char *buf;
+ 	int outlen;
+ {
+ 	struct ifconf ifc;
+ 	struct ifreq ifreq, *ifr;
+ 	struct in_addr in;
+ 	int i, sock, len;
+ 	char inbuf[8192];
+ 	struct sockaddr_in bindsin;
+ 
  	/* 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;
  	}
  	
+ 	memset(&bindsin, 0, sizeof bindsin);
+ 	bindsin.sin_family = AF_INET;
+ 	bindsin.sin_len = sizeof(bindsin);
+ 	bindsin.sin_port = htons(PMAPPORT);
+ 
  	ifc.ifc_len = sizeof inbuf;
  	ifc.ifc_buf = inbuf;
  	if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
***************
*** 638,644 ****
  	return 0;
  }
  
! /*enum clnt_stat*/
  handle_replies()
  {
  	char buf[1400];
--- 679,758 ----
  	return 0;
  }
  
! int
! direct(buf, outlen)
! 	char *buf;
! 	int outlen;
! {
! 	static FILE *df;
! #define MAXLINELEN 1024
! 	char line[MAXLINELEN];
! 	char *p;
! 	struct hostent *hp;
! 	struct sockaddr_in bindsin;
! 	int i, count = 0;
! 
! 	if (df)
! 		rewind(df);
! 	else {
! 		char path[MAXPATHLEN];
! 
! 		sprintf(path, "%s%s/%s", VARYPDIR, domainname, SERVERSFILE);
! 		df = fopen(path, "r");
! 		if (df == NULL) {
! 			perror(path);
! 			exit(1);
! 		}
! 	}
! 	memset(&bindsin, 0, sizeof bindsin);
! 	bindsin.sin_family = AF_INET;
! 	bindsin.sin_len = sizeof(bindsin);
! 	bindsin.sin_port = htons(PMAPPORT);
! 
! 	while(fgets(line, sizeof(line), df) != NULL) {
! 		/* skip lines that are too big */
! 		p = strchr(line, '\n');
! 		if (p == NULL) {
! 			int c;
! 
! 			while ((c = getc(df)) != '\n' && c != EOF)
! 				;
! 			continue;
! 		}
! 		*p = '\0';
! 		p = line;
! 		while (isspace(*p))
! 			p++;
! 		if (*p == '#')
! 			continue;
! 		hp = gethostbyname(p);
! 		if (!hp) {
! 			herror(p);
! 			continue;
! 		}
! 		/* step through all addresses in case first is unavailable */
! 		for (i = 0; hp->h_addr_list[i]; i++) {
! 			memmove(&bindsin.sin_addr, hp->h_addr_list[0],
! 				hp->h_length);
! 			if (sendto(rpcsock, buf, outlen, 0,
! 					(struct sockaddr *)&bindsin,
! 					sizeof bindsin) < 0) {
! 				perror("sendto");
! 				continue;
! 			}
! 			else
! 				count++;
! 		}
! 	}
! 	if (!count) {
! 		fprintf(stderr, "no contactable servers found in %s\n",
! 					SERVERSFILE);
! 		exit(1);
! 	}
! 	return 0;
! }
! 
! int
  handle_replies()
  {
  	char buf[1400];
***************
*** 675,681 ****
  		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);
  		}
  	}
  	xdr.x_op = XDR_FREE;
--- 789,795 ----
  		if ((msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
  		    (msg.acpted_rply.ar_stat == SUCCESS)) {
  			raddr.sin_port = htons((u_short)rmtcr_port);
! 			rpc_received((char *)msg.rm_xid, &raddr, 0);
  		}
  	}
  	xdr.x_op = XDR_FREE;
***************
*** 685,691 ****
  	return RPC_SUCCESS;
  }
  
! /*enum clnt_stat*/
  handle_ping()
  {
  	char buf[1400];
--- 799,805 ----
  	return RPC_SUCCESS;
  }
  
! int
  handle_ping()
  {
  	char buf[1400];
***************
*** 722,728 ****
  	if (xdr_replymsg(&xdr, &msg)) {
  		if ((msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
  		    (msg.acpted_rply.ar_stat == SUCCESS)) {
! 			rpc_received(msg.rm_xid, &raddr, 0);
  		}
  	}
  	xdr.x_op = XDR_FREE;
--- 836,842 ----
  	if (xdr_replymsg(&xdr, &msg)) {
  		if ((msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
  		    (msg.acpted_rply.ar_stat == SUCCESS)) {
! 			rpc_received((char *)msg.rm_xid, &raddr, 0);
  		}
  	}
  	xdr.x_op = XDR_FREE;
***************
*** 735,744 ****
  /*
   * LOOPBACK IS MORE IMPORTANT: PUT IN HACK
   */
  rpc_received(dom, raddrp, force)
! char *dom;
! struct sockaddr_in *raddrp;
! int force;
  {
  	struct _dom_binding *ypdb;
  	struct iovec iov[2];
--- 849,859 ----
  /*
   * LOOPBACK IS MORE IMPORTANT: PUT IN HACK
   */
+ void
  rpc_received(dom, raddrp, force)
! 	char *dom;
! 	struct sockaddr_in *raddrp;
! 	int force;
  {
  	struct _dom_binding *ypdb;
  	struct iovec iov[2];
***************
*** 792,798 ****
  		close(ypdb->dom_lockfd);
  
  	sprintf(path, "%s/%s.%d", BINDINGDIR,
! 		ypdb->dom_domain, ypdb->dom_vers);
  #ifdef O_SHLOCK
  	if ((fd = open(path, O_CREAT|O_SHLOCK|O_RDWR|O_TRUNC, 0644)) == -1) {
  		(void)mkdir(BINDINGDIR, 0755);
--- 907,913 ----
  		close(ypdb->dom_lockfd);
  
  	sprintf(path, "%s/%s.%d", BINDINGDIR,
! 		ypdb->dom_domain, (int)ypdb->dom_vers);
  #ifdef O_SHLOCK
  	if ((fd = open(path, O_CREAT|O_SHLOCK|O_RDWR|O_TRUNC, 0644)) == -1) {
  		(void)mkdir(BINDINGDIR, 0755);
>Audit-Trail:
>Unformatted: