xref: /onnv-gate/usr/src/cmd/avs/dscfglockd/dscfglockd.c (revision 11576:b23c42c0c9d6)
17836SJohn.Forte@Sun.COM /*
27836SJohn.Forte@Sun.COM  * CDDL HEADER START
37836SJohn.Forte@Sun.COM  *
47836SJohn.Forte@Sun.COM  * The contents of this file are subject to the terms of the
57836SJohn.Forte@Sun.COM  * Common Development and Distribution License (the "License").
67836SJohn.Forte@Sun.COM  * You may not use this file except in compliance with the License.
77836SJohn.Forte@Sun.COM  *
87836SJohn.Forte@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97836SJohn.Forte@Sun.COM  * or http://www.opensolaris.org/os/licensing.
107836SJohn.Forte@Sun.COM  * See the License for the specific language governing permissions
117836SJohn.Forte@Sun.COM  * and limitations under the License.
127836SJohn.Forte@Sun.COM  *
137836SJohn.Forte@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
147836SJohn.Forte@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157836SJohn.Forte@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
167836SJohn.Forte@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
177836SJohn.Forte@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
187836SJohn.Forte@Sun.COM  *
197836SJohn.Forte@Sun.COM  * CDDL HEADER END
207836SJohn.Forte@Sun.COM  */
217836SJohn.Forte@Sun.COM /*
22*11576SSurya.Prakki@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
237836SJohn.Forte@Sun.COM  * Use is subject to license terms.
247836SJohn.Forte@Sun.COM  */
257836SJohn.Forte@Sun.COM 
267836SJohn.Forte@Sun.COM #include <signal.h>
277836SJohn.Forte@Sun.COM #include <sys/types.h>
287836SJohn.Forte@Sun.COM #include <sys/time.h>
297836SJohn.Forte@Sun.COM #include <sys/socket.h>
307836SJohn.Forte@Sun.COM #include <netinet/in.h>
317836SJohn.Forte@Sun.COM #include <netinet/tcp.h>
327836SJohn.Forte@Sun.COM #include <arpa/inet.h>
337836SJohn.Forte@Sun.COM #include <netdb.h>
347836SJohn.Forte@Sun.COM #include <fcntl.h>
357836SJohn.Forte@Sun.COM #include <string.h>
367836SJohn.Forte@Sun.COM #include <memory.h>
377836SJohn.Forte@Sun.COM #include <sys/param.h>
387836SJohn.Forte@Sun.COM #include <sys/pathconf.h>
397836SJohn.Forte@Sun.COM #include <netdir.h>
407836SJohn.Forte@Sun.COM #include <netconfig.h>
417836SJohn.Forte@Sun.COM #include <sys/sockio.h>
427836SJohn.Forte@Sun.COM #include <net/if.h>
437836SJohn.Forte@Sun.COM #include <sys/resource.h>
447836SJohn.Forte@Sun.COM #include <stdio.h>
457836SJohn.Forte@Sun.COM #include <errno.h>
467836SJohn.Forte@Sun.COM #include <assert.h>
477836SJohn.Forte@Sun.COM #include <locale.h>
487836SJohn.Forte@Sun.COM #include <unistd.h>
497836SJohn.Forte@Sun.COM #include <stdlib.h>
507836SJohn.Forte@Sun.COM #include <string.h>
517836SJohn.Forte@Sun.COM #include <strings.h>
527836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_s.h>
537836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_s_u.h>
547836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_errors.h>
557836SJohn.Forte@Sun.COM 
567836SJohn.Forte@Sun.COM #include <sys/nsctl/cfg.h>
577836SJohn.Forte@Sun.COM #include <sys/nsctl/cfg_lockd.h>
587836SJohn.Forte@Sun.COM 
597836SJohn.Forte@Sun.COM #ifdef DEBUG
607836SJohn.Forte@Sun.COM #define	DPF(m)		if (debug) (void) fprintf m
617836SJohn.Forte@Sun.COM #else
627836SJohn.Forte@Sun.COM #define	DPF(m)
637836SJohn.Forte@Sun.COM #endif
647836SJohn.Forte@Sun.COM 
657836SJohn.Forte@Sun.COM #ifdef	TTY_MESSAGES
667836SJohn.Forte@Sun.COM #define	CLOSE_FD	3
677836SJohn.Forte@Sun.COM #else
687836SJohn.Forte@Sun.COM #define	CLOSE_FD	0
697836SJohn.Forte@Sun.COM #endif
707836SJohn.Forte@Sun.COM 
717836SJohn.Forte@Sun.COM #define	MAX_LOCKQ	1024
727836SJohn.Forte@Sun.COM #define	MAX_DAEMONS	1024
737836SJohn.Forte@Sun.COM #define	MAX_LOCAL	1024
747836SJohn.Forte@Sun.COM #define	MAX_UNLOCK	32
757836SJohn.Forte@Sun.COM #define	MAX_TIMEOUTS	3
767836SJohn.Forte@Sun.COM #define	TIMEOUT_SECS	5
777836SJohn.Forte@Sun.COM 
787836SJohn.Forte@Sun.COM static char program[] = "dscfglockd";
797836SJohn.Forte@Sun.COM static int debug;
807836SJohn.Forte@Sun.COM static int lstate;
817836SJohn.Forte@Sun.COM static int msgtrace;
827836SJohn.Forte@Sun.COM static FILE *debugfile = NULL;
837836SJohn.Forte@Sun.COM 
847836SJohn.Forte@Sun.COM struct lock_req {
857836SJohn.Forte@Sun.COM 	cfglockd_t	type;	/* read or write */
867836SJohn.Forte@Sun.COM 	pid_t	pid;		/* pid of read locker or local writer */
877836SJohn.Forte@Sun.COM 	daemonaddr_t	remote;	/* remote machine requesting write lock */
887836SJohn.Forte@Sun.COM 	int		state;	/* for write locks */
897836SJohn.Forte@Sun.COM 	int32_t		order;	/* who gets priority? */
907836SJohn.Forte@Sun.COM } lock_queue[MAX_LOCKQ];
917836SJohn.Forte@Sun.COM 
927836SJohn.Forte@Sun.COM struct unlock_s {
937836SJohn.Forte@Sun.COM 	pid_t	pid;		/* pid of locker */
947836SJohn.Forte@Sun.COM 	uint8_t seq;		/* seq number of last lock request */
957836SJohn.Forte@Sun.COM } unlock_buf[MAX_UNLOCK];
967836SJohn.Forte@Sun.COM 
977836SJohn.Forte@Sun.COM int next_req;
987836SJohn.Forte@Sun.COM int32_t order;
997836SJohn.Forte@Sun.COM 
1007836SJohn.Forte@Sun.COM #define	lock_wanted	lock_queue[0]
1017836SJohn.Forte@Sun.COM long	ticker	= 1l;
1027836SJohn.Forte@Sun.COM 
1037836SJohn.Forte@Sun.COM #define	ALIVE		0x10
1047836SJohn.Forte@Sun.COM #define	READ_LOCK	0x11
1057836SJohn.Forte@Sun.COM #define	WRITE_LOCK	0x12
1067836SJohn.Forte@Sun.COM #define	UNLOCK		0x13
1077836SJohn.Forte@Sun.COM #define	GRANTED		0x14
1087836SJohn.Forte@Sun.COM 
1097836SJohn.Forte@Sun.COM int next_q;
1107836SJohn.Forte@Sun.COM 
1117836SJohn.Forte@Sun.COM struct {
1127836SJohn.Forte@Sun.COM 	cfglockd_t	type;
1137836SJohn.Forte@Sun.COM 	int		nholders;
1147836SJohn.Forte@Sun.COM 	int		state;
1157836SJohn.Forte@Sun.COM 	daemonaddr_t	holder;
1167836SJohn.Forte@Sun.COM 	struct lockdaemon	*remote_daemon;
1177836SJohn.Forte@Sun.COM 	pid_t		holding_pid[MAX_LOCAL];
1187836SJohn.Forte@Sun.COM } the_lock;
1197836SJohn.Forte@Sun.COM 
1207836SJohn.Forte@Sun.COM daemonaddr_t	thishost;
1217836SJohn.Forte@Sun.COM daemonaddr_t	localhost;
1227836SJohn.Forte@Sun.COM 
1237836SJohn.Forte@Sun.COM #define	STATE_CLEAR	0
1247836SJohn.Forte@Sun.COM #define	STATE_ASKED	1
1257836SJohn.Forte@Sun.COM #define	STATE_OKAYED	2
1267836SJohn.Forte@Sun.COM #define	STATE_WANTS	3
1277836SJohn.Forte@Sun.COM #define	lockdaemon_dead(ldp)	((ticker - (ldp)->timeout) > MAX_TIMEOUTS)
128*11576SSurya.Prakki@Sun.COM #define	CRIT_BEGIN()	(void) sighold(SIGALRM)
129*11576SSurya.Prakki@Sun.COM #define	CRIT_END()	(void) sigrelse(SIGALRM)
1307836SJohn.Forte@Sun.COM 
1317836SJohn.Forte@Sun.COM #define	NORMAL_UNLOCK	0
1327836SJohn.Forte@Sun.COM #define	FORCE_UNLOCK	1
1337836SJohn.Forte@Sun.COM 
1347836SJohn.Forte@Sun.COM struct lockdaemon {
1357836SJohn.Forte@Sun.COM 	daemonaddr_t	host;
1367836SJohn.Forte@Sun.COM 	int	up;
1377836SJohn.Forte@Sun.COM 	long	timeout;
1387836SJohn.Forte@Sun.COM 	int	inuse;
1397836SJohn.Forte@Sun.COM 	int	state;
1407836SJohn.Forte@Sun.COM 	int32_t	order;
1417836SJohn.Forte@Sun.COM } daemon_list[MAX_DAEMONS];
1427836SJohn.Forte@Sun.COM 
1437836SJohn.Forte@Sun.COM unsigned short	lock_port = CFG_SERVER_PORT;
1447836SJohn.Forte@Sun.COM int	lock_soc = 0;
1457836SJohn.Forte@Sun.COM int	pf_inet = PF_INET;
1467836SJohn.Forte@Sun.COM #define	dp_addr(p)	inet_ntoa(((struct sockaddr_in *)p)->sin_addr)
1477836SJohn.Forte@Sun.COM 
1487836SJohn.Forte@Sun.COM #define	MAXIFS 32
1497836SJohn.Forte@Sun.COM 
1507836SJohn.Forte@Sun.COM static char *
lockd_type(cfglockd_t type)1517836SJohn.Forte@Sun.COM lockd_type(cfglockd_t type)
1527836SJohn.Forte@Sun.COM {
1537836SJohn.Forte@Sun.COM 	switch (type) {
1547836SJohn.Forte@Sun.COM 	case LOCK_NOTLOCKED:	return "NotLocked";
1557836SJohn.Forte@Sun.COM 	case LOCK_READ:		return "Read";
1567836SJohn.Forte@Sun.COM 	case LOCK_WRITE:	return "Write";
1577836SJohn.Forte@Sun.COM 	case LOCK_LOCKED:	return "Locked";
1587836SJohn.Forte@Sun.COM 	case LOCK_LOCKEDBY:	return "LockedBy";
1597836SJohn.Forte@Sun.COM 	case LOCK_STAT:		return "Stat";
1607836SJohn.Forte@Sun.COM 	case LOCK_ACK:		return "Ack";
1617836SJohn.Forte@Sun.COM 	default:		return "*unknown*";
1627836SJohn.Forte@Sun.COM 	}
1637836SJohn.Forte@Sun.COM }
1647836SJohn.Forte@Sun.COM 
1657836SJohn.Forte@Sun.COM static char *
lockd_state(int state)1667836SJohn.Forte@Sun.COM lockd_state(int state)
1677836SJohn.Forte@Sun.COM {
1687836SJohn.Forte@Sun.COM 	switch (state) {
1697836SJohn.Forte@Sun.COM 	case STATE_CLEAR:	return "Clear";
1707836SJohn.Forte@Sun.COM 	case STATE_ASKED:	return "Asked";
1717836SJohn.Forte@Sun.COM 	case STATE_OKAYED:	return "Okayed";
1727836SJohn.Forte@Sun.COM 	case STATE_WANTS:	return "Wants";
1737836SJohn.Forte@Sun.COM 	default:		return "*unknown*";
1747836SJohn.Forte@Sun.COM 	}
1757836SJohn.Forte@Sun.COM }
1767836SJohn.Forte@Sun.COM 
1777836SJohn.Forte@Sun.COM static char *
lockd_msg(int message)1787836SJohn.Forte@Sun.COM lockd_msg(int message)
1797836SJohn.Forte@Sun.COM {
1807836SJohn.Forte@Sun.COM 	switch (message) {
1817836SJohn.Forte@Sun.COM 	case ALIVE:		return "Alive";
1827836SJohn.Forte@Sun.COM 	case READ_LOCK:		return "ReadLock";
1837836SJohn.Forte@Sun.COM 	case WRITE_LOCK:	return "WriteLock";
1847836SJohn.Forte@Sun.COM 	case UNLOCK:		return "Unlock";
1857836SJohn.Forte@Sun.COM 	case GRANTED:		return "Granted";
1867836SJohn.Forte@Sun.COM 	default:		return lockd_type((cfglockd_t)message);
1877836SJohn.Forte@Sun.COM 	}
1887836SJohn.Forte@Sun.COM }
1897836SJohn.Forte@Sun.COM 
1907836SJohn.Forte@Sun.COM /*
1917836SJohn.Forte@Sun.COM  * The following is stolen from autod_nfs.c
1927836SJohn.Forte@Sun.COM  */
1937836SJohn.Forte@Sun.COM static void
getmyaddrs(struct ifconf * ifc)1947836SJohn.Forte@Sun.COM getmyaddrs(struct ifconf *ifc)
1957836SJohn.Forte@Sun.COM {
1967836SJohn.Forte@Sun.COM 	int sock;
1977836SJohn.Forte@Sun.COM 	int numifs;
1987836SJohn.Forte@Sun.COM 	char *buf;
1997836SJohn.Forte@Sun.COM 	int family;
2007836SJohn.Forte@Sun.COM 
2017836SJohn.Forte@Sun.COM 	ifc->ifc_buf = NULL;
2027836SJohn.Forte@Sun.COM 	ifc->ifc_len = 0;
2037836SJohn.Forte@Sun.COM 
2047836SJohn.Forte@Sun.COM #ifdef AF_INET6
2057836SJohn.Forte@Sun.COM 	family = AF_INET6;
2067836SJohn.Forte@Sun.COM #else
2077836SJohn.Forte@Sun.COM 	family = AF_INET;
2087836SJohn.Forte@Sun.COM #endif
2097836SJohn.Forte@Sun.COM 	if ((sock = socket(family, SOCK_DGRAM, 0)) < 0) {
2107836SJohn.Forte@Sun.COM #ifdef DEBUG
2117836SJohn.Forte@Sun.COM 		perror("getmyaddrs(): socket");
2127836SJohn.Forte@Sun.COM #endif
2137836SJohn.Forte@Sun.COM 		return;
2147836SJohn.Forte@Sun.COM 	}
2157836SJohn.Forte@Sun.COM 
2167836SJohn.Forte@Sun.COM 	if (ioctl(sock, SIOCGIFNUM, (char *)&numifs) < 0) {
2177836SJohn.Forte@Sun.COM #ifdef DEBUG
2187836SJohn.Forte@Sun.COM 		perror("getmyaddrs(): SIOCGIFNUM");
2197836SJohn.Forte@Sun.COM #endif
2207836SJohn.Forte@Sun.COM 		numifs = MAXIFS;
2217836SJohn.Forte@Sun.COM 	}
2227836SJohn.Forte@Sun.COM 
2237836SJohn.Forte@Sun.COM 	buf = (char *)malloc(numifs * sizeof (struct ifreq));
2247836SJohn.Forte@Sun.COM 	if (buf == NULL) {
2257836SJohn.Forte@Sun.COM #ifdef DEBUG
2267836SJohn.Forte@Sun.COM 		(void) fprintf(stderr, "getmyaddrs(): malloc failed\n");
2277836SJohn.Forte@Sun.COM #endif
2287836SJohn.Forte@Sun.COM 		(void) close(sock);
2297836SJohn.Forte@Sun.COM 		return;
2307836SJohn.Forte@Sun.COM 	}
2317836SJohn.Forte@Sun.COM 
2327836SJohn.Forte@Sun.COM 	ifc->ifc_buf = buf;
2337836SJohn.Forte@Sun.COM 	ifc->ifc_len = numifs * sizeof (struct ifreq);
2347836SJohn.Forte@Sun.COM 
2357836SJohn.Forte@Sun.COM 	if (ioctl(sock, SIOCGIFCONF, (char *)ifc) < 0) {
2367836SJohn.Forte@Sun.COM #ifdef DEBUG
2377836SJohn.Forte@Sun.COM 		perror("getmyaddrs(): SIOCGIFCONF");
2387836SJohn.Forte@Sun.COM #endif
2397836SJohn.Forte@Sun.COM 	}
2407836SJohn.Forte@Sun.COM 
2417836SJohn.Forte@Sun.COM 	(void) close(sock);
2427836SJohn.Forte@Sun.COM }
2437836SJohn.Forte@Sun.COM 
2447836SJohn.Forte@Sun.COM struct ifconf *ifc;
2457836SJohn.Forte@Sun.COM 
2467836SJohn.Forte@Sun.COM static int
cmp_addr(daemonaddr_t * a,daemonaddr_t * b)2477836SJohn.Forte@Sun.COM cmp_addr(daemonaddr_t *a, daemonaddr_t *b)
2487836SJohn.Forte@Sun.COM {
2497836SJohn.Forte@Sun.COM 	int rc;
2507836SJohn.Forte@Sun.COM 	rc = memcmp(&(a->sin_addr), &(b->sin_addr), sizeof (a->sin_addr));
2517836SJohn.Forte@Sun.COM 	DPF((stderr, "compare %s %hu with", dp_addr(a), a->sin_port));
2527836SJohn.Forte@Sun.COM 	DPF((stderr, " %s %hu = %d\n", dp_addr(b), b->sin_port, rc));
2537836SJohn.Forte@Sun.COM 	return (rc);
2547836SJohn.Forte@Sun.COM }
2557836SJohn.Forte@Sun.COM 
2567836SJohn.Forte@Sun.COM static int
addr_is_holder(int32_t order)2577836SJohn.Forte@Sun.COM addr_is_holder(int32_t order)
2587836SJohn.Forte@Sun.COM {
2597836SJohn.Forte@Sun.COM 	return ((the_lock.nholders > 0) && the_lock.remote_daemon != NULL &&
2607836SJohn.Forte@Sun.COM 	    (order == the_lock.remote_daemon->order));
2617836SJohn.Forte@Sun.COM }
2627836SJohn.Forte@Sun.COM 
2637836SJohn.Forte@Sun.COM static int
islocalhost(daemonaddr_t * host)2647836SJohn.Forte@Sun.COM islocalhost(daemonaddr_t *host)
2657836SJohn.Forte@Sun.COM {
2667836SJohn.Forte@Sun.COM 	int n;
2677836SJohn.Forte@Sun.COM 	struct sockaddr_in *s1, *s2;
2687836SJohn.Forte@Sun.COM 	struct ifreq *ifr;
2697836SJohn.Forte@Sun.COM 	int retval = 0;
2707836SJohn.Forte@Sun.COM 
2717836SJohn.Forte@Sun.COM 	ifr = ifc->ifc_req;
2727836SJohn.Forte@Sun.COM 	n = ifc->ifc_len / sizeof (struct ifreq);
2737836SJohn.Forte@Sun.COM 	s1 = host;
2747836SJohn.Forte@Sun.COM 	s2 = NULL;
2757836SJohn.Forte@Sun.COM 	for (; n > 0; n--, ifr++) {
2767836SJohn.Forte@Sun.COM 		if (ifr->ifr_addr.sa_family != AF_INET)
2777836SJohn.Forte@Sun.COM 			continue;
2787836SJohn.Forte@Sun.COM 
2797836SJohn.Forte@Sun.COM 		/* LINTED pointer alignment */
2807836SJohn.Forte@Sun.COM 		s2 = (struct sockaddr_in *)&ifr->ifr_addr;
2817836SJohn.Forte@Sun.COM 
2827836SJohn.Forte@Sun.COM 		if (memcmp((char *)&s2->sin_addr,
283*11576SSurya.Prakki@Sun.COM 		    (char *)&s1->sin_addr, sizeof (s1->sin_addr)) == 0) {
2847836SJohn.Forte@Sun.COM 			retval = 1;
2857836SJohn.Forte@Sun.COM 			/* it's me */
2867836SJohn.Forte@Sun.COM 			break;
2877836SJohn.Forte@Sun.COM 		}
2887836SJohn.Forte@Sun.COM 	}
2897836SJohn.Forte@Sun.COM 	return (retval);
2907836SJohn.Forte@Sun.COM }
2917836SJohn.Forte@Sun.COM 
2927836SJohn.Forte@Sun.COM static void
send_lockmsg(int cmd,pid_t pid,daemonaddr_t * dp,uint8_t seq)2937836SJohn.Forte@Sun.COM send_lockmsg(int cmd, pid_t pid, daemonaddr_t *dp, uint8_t seq)
2947836SJohn.Forte@Sun.COM {
2957836SJohn.Forte@Sun.COM 	struct lock_msg message_buf;
2967836SJohn.Forte@Sun.COM 	int rc;
2977836SJohn.Forte@Sun.COM 
2987836SJohn.Forte@Sun.COM 	if (msgtrace && debugfile) {
2997836SJohn.Forte@Sun.COM 		time_t t = time(0);
3007836SJohn.Forte@Sun.COM 		(void) fprintf(debugfile, "%19.19s send %-9.9s to   %s\n",
3017836SJohn.Forte@Sun.COM 		    ctime(&t), lockd_msg(cmd), dp_addr(dp));
3027836SJohn.Forte@Sun.COM 	}
3037836SJohn.Forte@Sun.COM 	DPF((stderr, "send %d to %s port %hu\n", cmd,
304*11576SSurya.Prakki@Sun.COM 	    dp_addr(dp), dp->sin_port));
3057836SJohn.Forte@Sun.COM 	message_buf.message = cmd;
3067836SJohn.Forte@Sun.COM 	message_buf.pid = pid;
3077836SJohn.Forte@Sun.COM 	message_buf.order = order;
3087836SJohn.Forte@Sun.COM 	message_buf.seq = seq;
3097836SJohn.Forte@Sun.COM 	do {
3107836SJohn.Forte@Sun.COM 		rc = sendto(lock_soc, &message_buf, sizeof (message_buf), 0,
3117836SJohn.Forte@Sun.COM 		    (struct sockaddr *)dp, sizeof (struct sockaddr));
3127836SJohn.Forte@Sun.COM 	} while (rc == -1 && errno == EINTR);
3137836SJohn.Forte@Sun.COM 	if (rc == -1)
3147836SJohn.Forte@Sun.COM 		spcs_log("cfglockd", NULL, "sendto rc -1 errno %d", errno);
3157836SJohn.Forte@Sun.COM }
3167836SJohn.Forte@Sun.COM 
3177836SJohn.Forte@Sun.COM /*
3187836SJohn.Forte@Sun.COM  * send an alive message to all configured daemons so that they can tell
3197836SJohn.Forte@Sun.COM  * us if they are holding a write lock.
3207836SJohn.Forte@Sun.COM  */
3217836SJohn.Forte@Sun.COM 
3227836SJohn.Forte@Sun.COM static void
send_aliveall()3237836SJohn.Forte@Sun.COM send_aliveall()
3247836SJohn.Forte@Sun.COM {
3257836SJohn.Forte@Sun.COM 	struct lockdaemon *ldp;
3267836SJohn.Forte@Sun.COM 	int i;
3277836SJohn.Forte@Sun.COM 	for (i = 0, ldp = daemon_list; i < MAX_DAEMONS; i++, ldp++) {
3287836SJohn.Forte@Sun.COM 		if (ldp->inuse == 0)
3297836SJohn.Forte@Sun.COM 			break;
3307836SJohn.Forte@Sun.COM 		send_lockmsg(ALIVE, (pid_t)0, &(ldp->host), 0);
3317836SJohn.Forte@Sun.COM 	}
3327836SJohn.Forte@Sun.COM }
3337836SJohn.Forte@Sun.COM 
3347836SJohn.Forte@Sun.COM /* find the lock daemon structure for a give daemon address */
3357836SJohn.Forte@Sun.COM 
3367836SJohn.Forte@Sun.COM static struct lockdaemon *
find_lockdaemon(daemonaddr_t * d)3377836SJohn.Forte@Sun.COM find_lockdaemon(daemonaddr_t *d)
3387836SJohn.Forte@Sun.COM {
3397836SJohn.Forte@Sun.COM 	struct lockdaemon *ldp;
3407836SJohn.Forte@Sun.COM 	int i;
3417836SJohn.Forte@Sun.COM 	for (i = 0, ldp = daemon_list; i < MAX_DAEMONS; i++, ldp++) {
3427836SJohn.Forte@Sun.COM 		if (ldp->inuse == 0)
3437836SJohn.Forte@Sun.COM 			break;
3447836SJohn.Forte@Sun.COM 		if (cmp_addr(&(ldp->host), d) == 0)
3457836SJohn.Forte@Sun.COM 			return (ldp);
3467836SJohn.Forte@Sun.COM 	}
3477836SJohn.Forte@Sun.COM 	return (NULL);
3487836SJohn.Forte@Sun.COM }
3497836SJohn.Forte@Sun.COM 
3507836SJohn.Forte@Sun.COM /*
3517836SJohn.Forte@Sun.COM  * a messge has been received from daemon, note this and if the daemon
3527836SJohn.Forte@Sun.COM  * was previously dead  and we have the write lock tell it that we do.
3537836SJohn.Forte@Sun.COM  */
3547836SJohn.Forte@Sun.COM 
3557836SJohn.Forte@Sun.COM static void
daemon_alive(daemonaddr_t * daemon,int32_t order)3567836SJohn.Forte@Sun.COM daemon_alive(daemonaddr_t *daemon, int32_t order)
3577836SJohn.Forte@Sun.COM {
3587836SJohn.Forte@Sun.COM 	struct lockdaemon *ldp;
3597836SJohn.Forte@Sun.COM 	int i;
3607836SJohn.Forte@Sun.COM 
3617836SJohn.Forte@Sun.COM 	for (i = 0, ldp = daemon_list; i < MAX_DAEMONS; i++, ldp++) {
3627836SJohn.Forte@Sun.COM 		if (ldp->inuse == 0)
3637836SJohn.Forte@Sun.COM 			break;
3647836SJohn.Forte@Sun.COM 		if (cmp_addr(&(ldp->host), daemon) == 0) {
3657836SJohn.Forte@Sun.COM 			ldp->order = order;
3667836SJohn.Forte@Sun.COM 			ldp->timeout = ticker;
3677836SJohn.Forte@Sun.COM 			if (ldp->up == 0) {
3687836SJohn.Forte@Sun.COM 				spcs_log("cfglockd", NULL,
3697836SJohn.Forte@Sun.COM 				    "daemon restarted on %s\n",
3707836SJohn.Forte@Sun.COM 				    dp_addr(daemon));
3717836SJohn.Forte@Sun.COM 				DPF((stderr, "daemon restarted on %s\n",
3727836SJohn.Forte@Sun.COM 				    dp_addr(daemon)));
3737836SJohn.Forte@Sun.COM 				ldp->up = 1;
3747836SJohn.Forte@Sun.COM 				goto come_up;
3757836SJohn.Forte@Sun.COM 			}
3767836SJohn.Forte@Sun.COM 			return;
3777836SJohn.Forte@Sun.COM 		}
3787836SJohn.Forte@Sun.COM 	}
3797836SJohn.Forte@Sun.COM 	/* new daemon has announced itself */
3807836SJohn.Forte@Sun.COM 	if (i < MAX_DAEMONS) {
3817836SJohn.Forte@Sun.COM 		DPF((stderr, "new daemon on %s\n", dp_addr(daemon)));
3827836SJohn.Forte@Sun.COM 		spcs_log("cfglockd", NULL,
3837836SJohn.Forte@Sun.COM 		    "new daemon on %s\n", dp_addr(daemon));
3847836SJohn.Forte@Sun.COM 		ldp->host = *daemon;
3857836SJohn.Forte@Sun.COM 		ldp->inuse = 1;
3867836SJohn.Forte@Sun.COM 		ldp->timeout = ticker;
3877836SJohn.Forte@Sun.COM 		ldp->order = order;
3887836SJohn.Forte@Sun.COM 	} else {
3897836SJohn.Forte@Sun.COM 		/* problem, more daemons than expected */
3907836SJohn.Forte@Sun.COM 		i++;
3917836SJohn.Forte@Sun.COM 	}
3927836SJohn.Forte@Sun.COM come_up:
3937836SJohn.Forte@Sun.COM 	if (the_lock.type == LOCK_WRITE && the_lock.remote_daemon == NULL)
3947836SJohn.Forte@Sun.COM 		send_lockmsg(WRITE_LOCK, (pid_t)0, daemon, 0);
3957836SJohn.Forte@Sun.COM }
3967836SJohn.Forte@Sun.COM 
3977836SJohn.Forte@Sun.COM static void
delete_queue_entry(struct lock_req * req)3987836SJohn.Forte@Sun.COM delete_queue_entry(struct  lock_req *req)
3997836SJohn.Forte@Sun.COM {
4007836SJohn.Forte@Sun.COM 	int i;
4017836SJohn.Forte@Sun.COM 
4027836SJohn.Forte@Sun.COM 	for (i = (req - lock_queue); i++ < next_req; req++)
4037836SJohn.Forte@Sun.COM 		*req = *(req+1);
4047836SJohn.Forte@Sun.COM 	next_req--;
4057836SJohn.Forte@Sun.COM }
4067836SJohn.Forte@Sun.COM 
4077836SJohn.Forte@Sun.COM static void
take_lock(int ackmessage)4087836SJohn.Forte@Sun.COM take_lock(int ackmessage)
4097836SJohn.Forte@Sun.COM {
4107836SJohn.Forte@Sun.COM 	send_lockmsg(ackmessage, (pid_t)0, &lock_wanted.remote, 0);
4117836SJohn.Forte@Sun.COM 	delete_queue_entry(lock_queue);
4127836SJohn.Forte@Sun.COM }
4137836SJohn.Forte@Sun.COM 
4147836SJohn.Forte@Sun.COM static void
check_for_write_lock()4157836SJohn.Forte@Sun.COM check_for_write_lock()
4167836SJohn.Forte@Sun.COM {
4177836SJohn.Forte@Sun.COM 	struct lockdaemon *ldp;
4187836SJohn.Forte@Sun.COM 	int i;
4197836SJohn.Forte@Sun.COM 	int	wait = 0;
4207836SJohn.Forte@Sun.COM 
4217836SJohn.Forte@Sun.COM 	DPF((stderr, "check for lock\n"));
4227836SJohn.Forte@Sun.COM 	if (lock_wanted.state != STATE_ASKED)
4237836SJohn.Forte@Sun.COM 		return;
4247836SJohn.Forte@Sun.COM 	for (i = 0, ldp = daemon_list; i < MAX_DAEMONS; i++, ldp++) {
4257836SJohn.Forte@Sun.COM 		if (ldp->inuse == 0)
4267836SJohn.Forte@Sun.COM 			break;
4277836SJohn.Forte@Sun.COM 		if (ldp->up && ldp->state != STATE_OKAYED) {
4287836SJohn.Forte@Sun.COM 			wait = 1;
4297836SJohn.Forte@Sun.COM 			break;
4307836SJohn.Forte@Sun.COM 		}
4317836SJohn.Forte@Sun.COM 	}
4327836SJohn.Forte@Sun.COM 	if (wait == 0 && lock_wanted.type == LOCK_WRITE) {
4337836SJohn.Forte@Sun.COM 		the_lock.type = LOCK_WRITE;
4347836SJohn.Forte@Sun.COM 		the_lock.holding_pid[0] = lock_wanted.pid;
4357836SJohn.Forte@Sun.COM 		the_lock.nholders = 1;
4367836SJohn.Forte@Sun.COM 		the_lock.state = STATE_CLEAR;
4377836SJohn.Forte@Sun.COM 		take_lock(LOCK_LOCKED);
4387836SJohn.Forte@Sun.COM 	}
4397836SJohn.Forte@Sun.COM }
4407836SJohn.Forte@Sun.COM 
4417836SJohn.Forte@Sun.COM static void
lock_granted(daemonaddr_t * da)4427836SJohn.Forte@Sun.COM lock_granted(daemonaddr_t *da)
4437836SJohn.Forte@Sun.COM {
4447836SJohn.Forte@Sun.COM 	struct lockdaemon *ldp;
4457836SJohn.Forte@Sun.COM 
4467836SJohn.Forte@Sun.COM 	if ((ldp = find_lockdaemon(da)) != NULL) {
4477836SJohn.Forte@Sun.COM 		/* if we already own the lock, throw the msg away */
4487836SJohn.Forte@Sun.COM 		if (the_lock.remote_daemon == NULL &&
4497836SJohn.Forte@Sun.COM 		    the_lock.type == LOCK_WRITE) {
4507836SJohn.Forte@Sun.COM 			return;
4517836SJohn.Forte@Sun.COM 		}
4527836SJohn.Forte@Sun.COM 
4537836SJohn.Forte@Sun.COM 		/*
4547836SJohn.Forte@Sun.COM 		 * If the current lock isn't a write lock and we're not
4557836SJohn.Forte@Sun.COM 		 * asking for one
4567836SJohn.Forte@Sun.COM 		 * -OR-
4577836SJohn.Forte@Sun.COM 		 * The current lock is a write lock and it's not owned by us
4587836SJohn.Forte@Sun.COM 		 * -THEN-
4597836SJohn.Forte@Sun.COM 		 * send back an unlocked message.
4607836SJohn.Forte@Sun.COM 		 */
4617836SJohn.Forte@Sun.COM 		if ((the_lock.type != LOCK_WRITE &&
4627836SJohn.Forte@Sun.COM 		    the_lock.state != STATE_ASKED) ||
4637836SJohn.Forte@Sun.COM 		    (the_lock.type == LOCK_WRITE &&
4647836SJohn.Forte@Sun.COM 		    the_lock.remote_daemon != NULL)) {
4657836SJohn.Forte@Sun.COM 			send_lockmsg(UNLOCK, (pid_t)0, &(ldp->host), 0);
4667836SJohn.Forte@Sun.COM 			return;
4677836SJohn.Forte@Sun.COM 		}
4687836SJohn.Forte@Sun.COM 		ldp->state = STATE_OKAYED;
4697836SJohn.Forte@Sun.COM 	}
4707836SJohn.Forte@Sun.COM 	check_for_write_lock();
4717836SJohn.Forte@Sun.COM }
4727836SJohn.Forte@Sun.COM 
4737836SJohn.Forte@Sun.COM static int
try_lock()4747836SJohn.Forte@Sun.COM try_lock()
4757836SJohn.Forte@Sun.COM {
4767836SJohn.Forte@Sun.COM 	struct lockdaemon *ldp;
4777836SJohn.Forte@Sun.COM 	int i;
4787836SJohn.Forte@Sun.COM 
4797836SJohn.Forte@Sun.COM 	switch (the_lock.type) {
4807836SJohn.Forte@Sun.COM 	case LOCK_READ:
4817836SJohn.Forte@Sun.COM 		if (lock_wanted.type == LOCK_READ) {
4827836SJohn.Forte@Sun.COM 			i = the_lock.nholders++;
4837836SJohn.Forte@Sun.COM 			the_lock.holding_pid[i] = lock_wanted.pid;
4847836SJohn.Forte@Sun.COM 			the_lock.state = STATE_CLEAR;
4857836SJohn.Forte@Sun.COM 			DPF((stderr, "increment read lockers to %d\n",
4867836SJohn.Forte@Sun.COM 			    the_lock.nholders));
4877836SJohn.Forte@Sun.COM 			take_lock(LOCK_LOCKED);
4887836SJohn.Forte@Sun.COM 			break;
4897836SJohn.Forte@Sun.COM 		}
4907836SJohn.Forte@Sun.COM 		/* write lock has to wait */
4917836SJohn.Forte@Sun.COM 		break;
4927836SJohn.Forte@Sun.COM 	case LOCK_WRITE:
4937836SJohn.Forte@Sun.COM 		/* lock has to wait until write lock is cleared */
4947836SJohn.Forte@Sun.COM 		break;
4957836SJohn.Forte@Sun.COM 	case LOCK_NOTLOCKED:
4967836SJohn.Forte@Sun.COM 		if (lock_wanted.type == LOCK_READ) {
4977836SJohn.Forte@Sun.COM 			DPF((stderr, "local locker, 1 lock holder\n"));
4987836SJohn.Forte@Sun.COM 			the_lock.holding_pid[0] = lock_wanted.pid;
4997836SJohn.Forte@Sun.COM 			the_lock.nholders = 1;
5007836SJohn.Forte@Sun.COM 			the_lock.type = LOCK_READ;
5017836SJohn.Forte@Sun.COM 			the_lock.state = STATE_CLEAR;
5027836SJohn.Forte@Sun.COM 			the_lock.remote_daemon = NULL;
5037836SJohn.Forte@Sun.COM 			take_lock(LOCK_LOCKED);
5047836SJohn.Forte@Sun.COM 			return (1);
5057836SJohn.Forte@Sun.COM 		}
5067836SJohn.Forte@Sun.COM 		if (islocalhost(&lock_wanted.remote)) {
5077836SJohn.Forte@Sun.COM 			DPF((stderr, "local locker, take write lock\n"));
5087836SJohn.Forte@Sun.COM 			/* tell everyone I'm locking */
5097836SJohn.Forte@Sun.COM 			if (lock_wanted.state != STATE_ASKED) {
5107836SJohn.Forte@Sun.COM 				for (i = 0, ldp = daemon_list; i < MAX_DAEMONS;
5117836SJohn.Forte@Sun.COM 				    i++, ldp++) {
5127836SJohn.Forte@Sun.COM 					if (ldp->inuse == 0)
5137836SJohn.Forte@Sun.COM 						break;
5147836SJohn.Forte@Sun.COM 					ldp->state = STATE_ASKED;
5157836SJohn.Forte@Sun.COM 					send_lockmsg(WRITE_LOCK, (pid_t)0,
5167836SJohn.Forte@Sun.COM 					    &(ldp->host), 0);
5177836SJohn.Forte@Sun.COM 				}
5187836SJohn.Forte@Sun.COM 			}
5197836SJohn.Forte@Sun.COM 			lock_wanted.state = STATE_ASKED;
5207836SJohn.Forte@Sun.COM 			check_for_write_lock();
5217836SJohn.Forte@Sun.COM 			the_lock.remote_daemon = NULL;
5227836SJohn.Forte@Sun.COM 			the_lock.state = STATE_ASKED;
5237836SJohn.Forte@Sun.COM 			return (0);
5247836SJohn.Forte@Sun.COM 		} else {
5257836SJohn.Forte@Sun.COM 			DPF((stderr, "remote locker, take write lock\n"));
5267836SJohn.Forte@Sun.COM 			the_lock.type = LOCK_WRITE;
5277836SJohn.Forte@Sun.COM 			the_lock.holder = lock_wanted.remote;
5287836SJohn.Forte@Sun.COM 			the_lock.nholders = 1;
5297836SJohn.Forte@Sun.COM 			the_lock.remote_daemon =
5307836SJohn.Forte@Sun.COM 			    find_lockdaemon(&the_lock.holder);
5317836SJohn.Forte@Sun.COM 			the_lock.state = STATE_CLEAR;
5327836SJohn.Forte@Sun.COM 			/* okay to remote */
5337836SJohn.Forte@Sun.COM 			take_lock(GRANTED);
5347836SJohn.Forte@Sun.COM 		}
5357836SJohn.Forte@Sun.COM 		break;
5367836SJohn.Forte@Sun.COM 	default:
5377836SJohn.Forte@Sun.COM 		DPF((stderr, "weird lock type held - %d\n", the_lock.type));
5387836SJohn.Forte@Sun.COM 		the_lock.type = LOCK_NOTLOCKED;
5397836SJohn.Forte@Sun.COM 		break;
5407836SJohn.Forte@Sun.COM 	}
5417836SJohn.Forte@Sun.COM 	return (0);
5427836SJohn.Forte@Sun.COM }
5437836SJohn.Forte@Sun.COM 
5447836SJohn.Forte@Sun.COM static void
process_queue()5457836SJohn.Forte@Sun.COM process_queue()
5467836SJohn.Forte@Sun.COM {
5477836SJohn.Forte@Sun.COM 	if (next_req < 1)
5487836SJohn.Forte@Sun.COM 		return;		/* no locks queued */
5497836SJohn.Forte@Sun.COM 	while (try_lock())
5507836SJohn.Forte@Sun.COM 		;
5517836SJohn.Forte@Sun.COM }
5527836SJohn.Forte@Sun.COM 
5537836SJohn.Forte@Sun.COM static int
lock_sort(const void * a,const void * b)5547836SJohn.Forte@Sun.COM lock_sort(const void *a, const void *b)
5557836SJohn.Forte@Sun.COM {
5567836SJohn.Forte@Sun.COM 	struct lock_req *left = (struct lock_req *)a;
5577836SJohn.Forte@Sun.COM 	struct lock_req *right = (struct lock_req *)b;
5587836SJohn.Forte@Sun.COM 
5597836SJohn.Forte@Sun.COM 	return (left->order - right->order);
5607836SJohn.Forte@Sun.COM }
5617836SJohn.Forte@Sun.COM 
5627836SJohn.Forte@Sun.COM static void
queue_lock(cfglockd_t type,struct lock_msg * msg,daemonaddr_t * addr)5637836SJohn.Forte@Sun.COM queue_lock(cfglockd_t type, struct lock_msg *msg, daemonaddr_t *addr)
5647836SJohn.Forte@Sun.COM {
5657836SJohn.Forte@Sun.COM 	int	i;
5667836SJohn.Forte@Sun.COM 	struct lock_req *lrp;
5677836SJohn.Forte@Sun.COM 	struct lockdaemon *ldp;
5687836SJohn.Forte@Sun.COM 
5697836SJohn.Forte@Sun.COM 	/* first check if new lock matches current lock */
5707836SJohn.Forte@Sun.COM 	if (the_lock.type == type && addr_is_holder(msg->order)) {
5717836SJohn.Forte@Sun.COM 		/* remote daemon missed locked message */
5727836SJohn.Forte@Sun.COM 		send_lockmsg(GRANTED, (pid_t)0, addr, msg->seq);
5737836SJohn.Forte@Sun.COM 		return;
5747836SJohn.Forte@Sun.COM 	}
5757836SJohn.Forte@Sun.COM 
5767836SJohn.Forte@Sun.COM 	/* next search queue to check for duplicate */
5777836SJohn.Forte@Sun.COM 	for (i = 0, lrp = lock_queue; i++ < next_req; lrp++) {
5787836SJohn.Forte@Sun.COM 		if (lrp->type == type && lrp->pid == msg->pid &&
5797836SJohn.Forte@Sun.COM 		    cmp_addr(addr, &(lrp->remote)) == 0)
5807836SJohn.Forte@Sun.COM 			return;
5817836SJohn.Forte@Sun.COM 
5827836SJohn.Forte@Sun.COM 	}
5837836SJohn.Forte@Sun.COM 
5847836SJohn.Forte@Sun.COM 	/*
5857836SJohn.Forte@Sun.COM 	 * It's a new lock request.  Are we in the middle of
5867836SJohn.Forte@Sun.COM 	 * obtaining one for ourselves?
5877836SJohn.Forte@Sun.COM 	 */
5887836SJohn.Forte@Sun.COM 
5897836SJohn.Forte@Sun.COM 	if (the_lock.type == LOCK_NOTLOCKED && the_lock.state == STATE_ASKED) {
5907836SJohn.Forte@Sun.COM 		/* did a higher priority request just come in? */
5917836SJohn.Forte@Sun.COM 		if (msg->order < order) {
5927836SJohn.Forte@Sun.COM 			/* requeue our request */
5937836SJohn.Forte@Sun.COM 			the_lock.state = STATE_CLEAR;
5947836SJohn.Forte@Sun.COM 			lock_wanted.state = STATE_CLEAR;
5957836SJohn.Forte@Sun.COM 
5967836SJohn.Forte@Sun.COM 			/* let the other lockds know */
5977836SJohn.Forte@Sun.COM 			for (i = 0, ldp = daemon_list; i < MAX_DAEMONS;
5987836SJohn.Forte@Sun.COM 			    i++, ldp++) {
5997836SJohn.Forte@Sun.COM 				if (ldp->inuse == 0)
6007836SJohn.Forte@Sun.COM 					break;
6017836SJohn.Forte@Sun.COM 				if (ldp->up && ldp->state == STATE_OKAYED) {
6027836SJohn.Forte@Sun.COM 					send_lockmsg(UNLOCK, (pid_t)0,
6037836SJohn.Forte@Sun.COM 					    &(ldp->host), 0);
6047836SJohn.Forte@Sun.COM 				}
6057836SJohn.Forte@Sun.COM 			}
6067836SJohn.Forte@Sun.COM 		}
6077836SJohn.Forte@Sun.COM 	}
6087836SJohn.Forte@Sun.COM 
6097836SJohn.Forte@Sun.COM 
6107836SJohn.Forte@Sun.COM 	lrp = lock_queue;
6117836SJohn.Forte@Sun.COM 	lrp += (next_req++);
6127836SJohn.Forte@Sun.COM 	lrp->type = type;
6137836SJohn.Forte@Sun.COM 	lrp->pid = msg->pid;
6147836SJohn.Forte@Sun.COM 	lrp->state = STATE_CLEAR;
6157836SJohn.Forte@Sun.COM 	lrp->order = msg->order;
6167836SJohn.Forte@Sun.COM 	if (addr) {
6177836SJohn.Forte@Sun.COM 		lrp->remote = *addr;
6187836SJohn.Forte@Sun.COM 	}
6197836SJohn.Forte@Sun.COM 
6207836SJohn.Forte@Sun.COM 	if (next_req > 1)
6217836SJohn.Forte@Sun.COM 		qsort(lock_queue, next_req, sizeof (lock_queue[0]), lock_sort);
6227836SJohn.Forte@Sun.COM 
6237836SJohn.Forte@Sun.COM 	if (the_lock.type != LOCK_WRITE)
6247836SJohn.Forte@Sun.COM 		process_queue();
6257836SJohn.Forte@Sun.COM }
6267836SJohn.Forte@Sun.COM 
6277836SJohn.Forte@Sun.COM static void
lock_stat()6287836SJohn.Forte@Sun.COM lock_stat()
6297836SJohn.Forte@Sun.COM {
6307836SJohn.Forte@Sun.COM 	char *lt = "Unknown";
6317836SJohn.Forte@Sun.COM 	struct lockdaemon *ldp;
6327836SJohn.Forte@Sun.COM 	int i;
6337836SJohn.Forte@Sun.COM 
6347836SJohn.Forte@Sun.COM 	spcs_log("cfglockd", NULL,
6357836SJohn.Forte@Sun.COM 	    "%s, Lock daemon built %s **********", program, __DATE__);
6367836SJohn.Forte@Sun.COM 	switch (the_lock.type) {
6377836SJohn.Forte@Sun.COM 	case LOCK_NOTLOCKED:
6387836SJohn.Forte@Sun.COM 		lt = "not locked";
6397836SJohn.Forte@Sun.COM 		break;
6407836SJohn.Forte@Sun.COM 	case LOCK_READ:
6417836SJohn.Forte@Sun.COM 		lt = "read locked";
6427836SJohn.Forte@Sun.COM 		break;
6437836SJohn.Forte@Sun.COM 	case LOCK_WRITE:
6447836SJohn.Forte@Sun.COM 		lt = "write locked";
6457836SJohn.Forte@Sun.COM 		break;
6467836SJohn.Forte@Sun.COM 	}
6477836SJohn.Forte@Sun.COM 	spcs_log("cfglockd", NULL, "Lock is %s (%d)", lt, the_lock.type);
6487836SJohn.Forte@Sun.COM 	spcs_log("cfglockd", NULL, "There are %d holders of the lock",
6497836SJohn.Forte@Sun.COM 	    the_lock.nholders);
6507836SJohn.Forte@Sun.COM 	if (the_lock.nholders > 0) {
6517836SJohn.Forte@Sun.COM 		for (i = 0; i < the_lock.nholders; i++)
6527836SJohn.Forte@Sun.COM 			spcs_log("cfglockd", NULL, "holding_pid[%d] = %6d", i,
6537836SJohn.Forte@Sun.COM 			    the_lock.holding_pid[i]);
6547836SJohn.Forte@Sun.COM 	}
6557836SJohn.Forte@Sun.COM 	spcs_log("cfglockd", NULL, "holder daemon was %s port %hu, remote %x",
6567836SJohn.Forte@Sun.COM 	    dp_addr(&the_lock.holder), the_lock.holder.sin_port,
6577836SJohn.Forte@Sun.COM 	    the_lock.remote_daemon);
6587836SJohn.Forte@Sun.COM 	spcs_log("cfglockd", NULL, "Lock queue, %d requests", next_req);
6597836SJohn.Forte@Sun.COM 	for (i = 0; i < next_req; i++) {
6607836SJohn.Forte@Sun.COM 		spcs_log("cfglockd", NULL, "request %d type %d order %d", i,
6617836SJohn.Forte@Sun.COM 		    lock_queue[i].type, lock_queue[i].order);
6627836SJohn.Forte@Sun.COM 		spcs_log("cfglockd", NULL, "  client %s port %hu, pid %d",
6637836SJohn.Forte@Sun.COM 		    dp_addr(&lock_queue[i].remote),
6647836SJohn.Forte@Sun.COM 		    lock_queue[i].remote.sin_port, lock_queue[i].pid);
6657836SJohn.Forte@Sun.COM 	}
6667836SJohn.Forte@Sun.COM 	spcs_log("cfglockd", NULL, "Daemon list");
6677836SJohn.Forte@Sun.COM 
6687836SJohn.Forte@Sun.COM 	for (i = 0, ldp = daemon_list; i < MAX_DAEMONS; i++, ldp++) {
6697836SJohn.Forte@Sun.COM 		if (ldp->inuse == 0)
6707836SJohn.Forte@Sun.COM 			break;
6717836SJohn.Forte@Sun.COM 		spcs_log("cfglockd", NULL, "daemon %d, %s port %hu", i,
6727836SJohn.Forte@Sun.COM 		    dp_addr(&ldp->host), ldp->host.sin_port);
6737836SJohn.Forte@Sun.COM 		spcs_log("cfglockd", NULL,
6747836SJohn.Forte@Sun.COM 		    "  up %d timeout %ld missed %d state %d\n", ldp->up,
6757836SJohn.Forte@Sun.COM 		    ldp->timeout, ticker - ldp->timeout, ldp->state);
6767836SJohn.Forte@Sun.COM 	}
6777836SJohn.Forte@Sun.COM }
6787836SJohn.Forte@Sun.COM 
6797836SJohn.Forte@Sun.COM static int
is_duplicate(cfglockd_t type,pid_t pid,uint8_t seq)6807836SJohn.Forte@Sun.COM is_duplicate(cfglockd_t type, pid_t pid, uint8_t seq)
6817836SJohn.Forte@Sun.COM {
6827836SJohn.Forte@Sun.COM 	struct unlock_s *bufp;
6837836SJohn.Forte@Sun.COM 	int i;
6847836SJohn.Forte@Sun.COM 
6857836SJohn.Forte@Sun.COM 	if (!pid) {
6867836SJohn.Forte@Sun.COM 		return (0);
6877836SJohn.Forte@Sun.COM 	}
6887836SJohn.Forte@Sun.COM 
6897836SJohn.Forte@Sun.COM 	for (i = 0, bufp = unlock_buf; bufp->pid && i < MAX_UNLOCK;
6907836SJohn.Forte@Sun.COM 	    i++, bufp++) {
6917836SJohn.Forte@Sun.COM 		if (bufp->pid == pid && bufp->seq == seq) {
6927836SJohn.Forte@Sun.COM 			/* throw message away */
6937836SJohn.Forte@Sun.COM #ifdef DEBUG
6947836SJohn.Forte@Sun.COM 			spcs_log("cfglockd", NULL,
6957836SJohn.Forte@Sun.COM 			    "duplicate '%d' request received from %d",
6967836SJohn.Forte@Sun.COM 			    type, pid);
6977836SJohn.Forte@Sun.COM #endif
6987836SJohn.Forte@Sun.COM 			return (1);
6997836SJohn.Forte@Sun.COM 		}
7007836SJohn.Forte@Sun.COM 	}
7017836SJohn.Forte@Sun.COM 
7027836SJohn.Forte@Sun.COM 	/* add it to the list */
7037836SJohn.Forte@Sun.COM 	bcopy(unlock_buf, &unlock_buf[ 1 ],
7047836SJohn.Forte@Sun.COM 	    sizeof (unlock_buf) - sizeof (struct unlock_s));
7057836SJohn.Forte@Sun.COM 	(*unlock_buf).pid = pid;
7067836SJohn.Forte@Sun.COM 	(*unlock_buf).seq = seq;
7077836SJohn.Forte@Sun.COM 
7087836SJohn.Forte@Sun.COM 	return (0);
7097836SJohn.Forte@Sun.COM }
7107836SJohn.Forte@Sun.COM 
7117836SJohn.Forte@Sun.COM static void
local_lock(cfglockd_t type,struct lock_msg * msg,daemonaddr_t * client)7127836SJohn.Forte@Sun.COM local_lock(cfglockd_t type, struct lock_msg *msg, daemonaddr_t *client)
7137836SJohn.Forte@Sun.COM {
7147836SJohn.Forte@Sun.COM 	if (is_duplicate(type, msg->pid, msg->seq)) {
7157836SJohn.Forte@Sun.COM 		if (the_lock.remote_daemon == NULL &&
7167836SJohn.Forte@Sun.COM 		    (the_lock.type == LOCK_WRITE ||
7177836SJohn.Forte@Sun.COM 		    the_lock.type == LOCK_READ) &&
7187836SJohn.Forte@Sun.COM 		    the_lock.holding_pid[0] == msg->pid) {
7197836SJohn.Forte@Sun.COM 			send_lockmsg(LOCK_LOCKED, (pid_t)0, client, msg->seq);
7207836SJohn.Forte@Sun.COM 		}
7217836SJohn.Forte@Sun.COM 	} else {
7227836SJohn.Forte@Sun.COM 		queue_lock(type, msg, client);
7237836SJohn.Forte@Sun.COM 	}
7247836SJohn.Forte@Sun.COM }
7257836SJohn.Forte@Sun.COM 
7267836SJohn.Forte@Sun.COM static void
remote_lock(struct sockaddr_in * remote,struct lock_msg * msg)7277836SJohn.Forte@Sun.COM remote_lock(struct sockaddr_in *remote, struct lock_msg *msg)
7287836SJohn.Forte@Sun.COM {
7297836SJohn.Forte@Sun.COM 	/* make sure remote knows we are alive */
7307836SJohn.Forte@Sun.COM 	send_lockmsg(ALIVE, (pid_t)0, remote, 0);
7317836SJohn.Forte@Sun.COM 
7327836SJohn.Forte@Sun.COM 	/* clear out pid as it is meaningless on this node */
7337836SJohn.Forte@Sun.COM 	msg->pid = (pid_t)0;
7347836SJohn.Forte@Sun.COM 
7357836SJohn.Forte@Sun.COM 	queue_lock(LOCK_WRITE, msg, (daemonaddr_t *)remote);
7367836SJohn.Forte@Sun.COM }
7377836SJohn.Forte@Sun.COM 
7387836SJohn.Forte@Sun.COM static void
unqueue_lock(daemonaddr_t * d,pid_t pid)7397836SJohn.Forte@Sun.COM unqueue_lock(daemonaddr_t *d, pid_t pid)
7407836SJohn.Forte@Sun.COM {
7417836SJohn.Forte@Sun.COM 	int	i;
7427836SJohn.Forte@Sun.COM 	struct lock_req *lrp, *xrp;
7437836SJohn.Forte@Sun.COM 	int diff;
7447836SJohn.Forte@Sun.COM 
7457836SJohn.Forte@Sun.COM 	/* search queue to delete ungranted locks */
7467836SJohn.Forte@Sun.COM 	for (i = 0, xrp = lrp = lock_queue; i++ < next_req; lrp++) {
7477836SJohn.Forte@Sun.COM 		*xrp = *lrp;
7487836SJohn.Forte@Sun.COM 		diff = 0;
7497836SJohn.Forte@Sun.COM 		if (pid != (pid_t)0 && lrp->pid != pid)
7507836SJohn.Forte@Sun.COM 			diff = 1;
7517836SJohn.Forte@Sun.COM 		if (d != NULL && cmp_addr(d, &(lrp->remote)) != 0)
7527836SJohn.Forte@Sun.COM 			diff = 1;
7537836SJohn.Forte@Sun.COM 		if (!diff)
7547836SJohn.Forte@Sun.COM 			continue;
7557836SJohn.Forte@Sun.COM 
7567836SJohn.Forte@Sun.COM 		xrp++;
7577836SJohn.Forte@Sun.COM 	}
7587836SJohn.Forte@Sun.COM 	next_req = xrp - lock_queue;
7597836SJohn.Forte@Sun.COM }
7607836SJohn.Forte@Sun.COM 
7617836SJohn.Forte@Sun.COM static void
xxunlock()7627836SJohn.Forte@Sun.COM xxunlock()
7637836SJohn.Forte@Sun.COM {
7647836SJohn.Forte@Sun.COM 	DPF((stderr, "** UNLOCK **\n"));
7657836SJohn.Forte@Sun.COM 	the_lock.remote_daemon = NULL;
7667836SJohn.Forte@Sun.COM 	the_lock.type = LOCK_NOTLOCKED;
7677836SJohn.Forte@Sun.COM 	the_lock.nholders = 0;
7687836SJohn.Forte@Sun.COM 	the_lock.state = STATE_CLEAR;
7697836SJohn.Forte@Sun.COM 	process_queue();
7707836SJohn.Forte@Sun.COM }
7717836SJohn.Forte@Sun.COM 
7727836SJohn.Forte@Sun.COM 
7737836SJohn.Forte@Sun.COM static void
local_unlock(pid_t pid,uint8_t seq,int method)7747836SJohn.Forte@Sun.COM local_unlock(pid_t pid, uint8_t seq, int method)
7757836SJohn.Forte@Sun.COM {
7767836SJohn.Forte@Sun.COM 	struct lockdaemon *ldp;
7777836SJohn.Forte@Sun.COM 	int i;
7787836SJohn.Forte@Sun.COM 
7797836SJohn.Forte@Sun.COM 	if (method == NORMAL_UNLOCK && is_duplicate(LOCK_NOTLOCKED, pid, seq)) {
7807836SJohn.Forte@Sun.COM 		return;
7817836SJohn.Forte@Sun.COM 	}
7827836SJohn.Forte@Sun.COM 
7837836SJohn.Forte@Sun.COM 	if (the_lock.type == LOCK_READ) {
7847836SJohn.Forte@Sun.COM 		/* delete reference to pid of reading process */
7857836SJohn.Forte@Sun.COM 		for (i = 0; i < the_lock.nholders; i++) {
7867836SJohn.Forte@Sun.COM 			if (the_lock.holding_pid[i] == pid) {
7877836SJohn.Forte@Sun.COM 				DPF((stderr, "decrement lockers from %d\n",
7887836SJohn.Forte@Sun.COM 				    the_lock.nholders));
7897836SJohn.Forte@Sun.COM 				--the_lock.nholders;
7907836SJohn.Forte@Sun.COM 				break;
7917836SJohn.Forte@Sun.COM 			}
7927836SJohn.Forte@Sun.COM 		}
7937836SJohn.Forte@Sun.COM 		for (; i < the_lock.nholders; i++) {
7947836SJohn.Forte@Sun.COM 			the_lock.holding_pid[i] = the_lock.holding_pid[i+1];
7957836SJohn.Forte@Sun.COM 		}
7967836SJohn.Forte@Sun.COM 		if (the_lock.nholders > 0)
7977836SJohn.Forte@Sun.COM 			return;
7987836SJohn.Forte@Sun.COM 	} else {
7997836SJohn.Forte@Sun.COM 		/* LOCK_WRITE */
8007836SJohn.Forte@Sun.COM 		if (pid != the_lock.holding_pid[0])
8017836SJohn.Forte@Sun.COM 			return;
8027836SJohn.Forte@Sun.COM 		the_lock.holding_pid[0] = (pid_t)0;
8037836SJohn.Forte@Sun.COM 		for (i = 0, ldp = daemon_list; i < MAX_DAEMONS; i++, ldp++) {
8047836SJohn.Forte@Sun.COM 			if (ldp->inuse == 0)
8057836SJohn.Forte@Sun.COM 				break;
8067836SJohn.Forte@Sun.COM 			if (ldp->up)
8077836SJohn.Forte@Sun.COM 				send_lockmsg(UNLOCK, (pid_t)0, &(ldp->host), 0);
8087836SJohn.Forte@Sun.COM 		}
8097836SJohn.Forte@Sun.COM 	}
8107836SJohn.Forte@Sun.COM 	xxunlock();
8117836SJohn.Forte@Sun.COM }
8127836SJohn.Forte@Sun.COM 
8137836SJohn.Forte@Sun.COM static void
remote_unlock(int32_t order,daemonaddr_t * d)8147836SJohn.Forte@Sun.COM remote_unlock(int32_t order, daemonaddr_t *d)
8157836SJohn.Forte@Sun.COM {
8167836SJohn.Forte@Sun.COM 	int	i;
8177836SJohn.Forte@Sun.COM 	struct lock_req *lrp;
8187836SJohn.Forte@Sun.COM 
8197836SJohn.Forte@Sun.COM 	DPF((stderr, "remote unlock from %s ", dp_addr(d)));
8207836SJohn.Forte@Sun.COM 	DPF((stderr, "when %s holds lock\n", dp_addr(&the_lock.holder)));
8217836SJohn.Forte@Sun.COM 
8227836SJohn.Forte@Sun.COM 	/* search queue to check for ungranted lock */
8237836SJohn.Forte@Sun.COM 	for (i = 0, lrp = lock_queue; i++ < next_req; lrp++) {
8247836SJohn.Forte@Sun.COM 		if (lrp->type == LOCK_WRITE &&
8257836SJohn.Forte@Sun.COM 		    cmp_addr(d, &(lrp->remote)) == 0) {
8267836SJohn.Forte@Sun.COM 			delete_queue_entry(lrp);
8277836SJohn.Forte@Sun.COM 			return;
8287836SJohn.Forte@Sun.COM 		}
8297836SJohn.Forte@Sun.COM 
8307836SJohn.Forte@Sun.COM 	}
8317836SJohn.Forte@Sun.COM 	if (addr_is_holder(order)) {
8327836SJohn.Forte@Sun.COM 		xxunlock();
8337836SJohn.Forte@Sun.COM 	}
8347836SJohn.Forte@Sun.COM }
8357836SJohn.Forte@Sun.COM 
8367836SJohn.Forte@Sun.COM static void
lockedby(daemonaddr_t * d,uint8_t seq)8377836SJohn.Forte@Sun.COM lockedby(daemonaddr_t *d, uint8_t seq)
8387836SJohn.Forte@Sun.COM {
8397836SJohn.Forte@Sun.COM 	DPF((stderr, "lockby enquiry from %s ", dp_addr(d)));
8407836SJohn.Forte@Sun.COM 	switch (the_lock.type) {
8417836SJohn.Forte@Sun.COM 	case LOCK_NOTLOCKED:
8427836SJohn.Forte@Sun.COM 		send_lockmsg(LOCK_NOTLOCKED, (pid_t)0, d, seq);
8437836SJohn.Forte@Sun.COM 		break;
8447836SJohn.Forte@Sun.COM 	case LOCK_READ:
8457836SJohn.Forte@Sun.COM 		send_lockmsg(LOCK_READ, the_lock.holding_pid[0], d, seq);
8467836SJohn.Forte@Sun.COM 		break;
8477836SJohn.Forte@Sun.COM 	case LOCK_WRITE:
8487836SJohn.Forte@Sun.COM 		send_lockmsg(LOCK_WRITE, the_lock.holding_pid[0], d, seq);
8497836SJohn.Forte@Sun.COM 		break;
8507836SJohn.Forte@Sun.COM 	}
8517836SJohn.Forte@Sun.COM }
8527836SJohn.Forte@Sun.COM 
8537836SJohn.Forte@Sun.COM /* ARGSUSED */
8547836SJohn.Forte@Sun.COM static void
keepalive(int signo)8557836SJohn.Forte@Sun.COM keepalive(int signo)
8567836SJohn.Forte@Sun.COM {
8577836SJohn.Forte@Sun.COM 	int i;
8587836SJohn.Forte@Sun.COM 	struct lock_req *locker;
8597836SJohn.Forte@Sun.COM 	struct lockdaemon *ldp;
8607836SJohn.Forte@Sun.COM 
8617836SJohn.Forte@Sun.COM 	DPF((stderr, "keepalive...\n"));
8627836SJohn.Forte@Sun.COM 	ticker++;
8637836SJohn.Forte@Sun.COM 
8647836SJohn.Forte@Sun.COM 	/*
8657836SJohn.Forte@Sun.COM 	 * tell any other daemon that has a lock request in our queue that
8667836SJohn.Forte@Sun.COM 	 * this daemon is still alive.
8677836SJohn.Forte@Sun.COM 	 */
8687836SJohn.Forte@Sun.COM 
8697836SJohn.Forte@Sun.COM 	for (i = 0, locker = lock_queue; i < next_req; i++, locker++) {
8707836SJohn.Forte@Sun.COM 		if (locker->pid == 0)	/* remote lock request */
8717836SJohn.Forte@Sun.COM 			send_lockmsg(ALIVE, (pid_t)0, &(locker->remote), 0);
8727836SJohn.Forte@Sun.COM 	}
8737836SJohn.Forte@Sun.COM 
8747836SJohn.Forte@Sun.COM 	/*
8757836SJohn.Forte@Sun.COM 	 * if a remote daemon holds the lock, check it is still alive and
8767836SJohn.Forte@Sun.COM 	 * if the remote daemon is sent it a grant message in case the
8777836SJohn.Forte@Sun.COM 	 * remote daemon missed our original grant.
8787836SJohn.Forte@Sun.COM 	 */
8797836SJohn.Forte@Sun.COM 
8807836SJohn.Forte@Sun.COM 	if (the_lock.remote_daemon) {
8817836SJohn.Forte@Sun.COM 		if (lockdaemon_dead(the_lock.remote_daemon)) {
8827836SJohn.Forte@Sun.COM 			DPF((stderr, "lock owner died\n"));
8837836SJohn.Forte@Sun.COM 			the_lock.remote_daemon->up = 0;
8847836SJohn.Forte@Sun.COM 			xxunlock();
8857836SJohn.Forte@Sun.COM 		} else {
8867836SJohn.Forte@Sun.COM 			send_lockmsg(GRANTED, (pid_t)0, &the_lock.holder, 0);
8877836SJohn.Forte@Sun.COM 		}
8887836SJohn.Forte@Sun.COM 	}
8897836SJohn.Forte@Sun.COM 
8907836SJohn.Forte@Sun.COM 	/*
8917836SJohn.Forte@Sun.COM 	 * check for response from daemons preventing this daemon
8927836SJohn.Forte@Sun.COM 	 * from taking a write lock by not sending a grant message.
8937836SJohn.Forte@Sun.COM 	 * if the remote daemon is alive send another lock request,
8947836SJohn.Forte@Sun.COM 	 * otherwise mark it as dead.
8957836SJohn.Forte@Sun.COM 	 * send alive message to any live remote daemons if this
8967836SJohn.Forte@Sun.COM 	 * daemon has the write lock.
8977836SJohn.Forte@Sun.COM 	 */
8987836SJohn.Forte@Sun.COM 	if (lstate) {
8997836SJohn.Forte@Sun.COM 		(void) printf("\nlock: %s\n", lockd_type(the_lock.type));
9007836SJohn.Forte@Sun.COM 		(void) printf("    no. holders: %d\n", the_lock.nholders);
9017836SJohn.Forte@Sun.COM 		(void) printf("    hold addr  : %s\n", the_lock.remote_daemon?
9027836SJohn.Forte@Sun.COM 		    dp_addr(the_lock.remote_daemon): "0.0.0.0");
9037836SJohn.Forte@Sun.COM 		(void) printf("    holding pid:");
9047836SJohn.Forte@Sun.COM 		for (i = 0; i < the_lock.nholders; i++) {
9057836SJohn.Forte@Sun.COM 			(void) printf(" %ld", the_lock.holding_pid[ i ]);
9067836SJohn.Forte@Sun.COM 		}
9077836SJohn.Forte@Sun.COM 		(void) printf("\n");
9087836SJohn.Forte@Sun.COM 	}
9097836SJohn.Forte@Sun.COM 	for (i = 0, ldp = daemon_list; i < MAX_DAEMONS; i++, ldp++) {
9107836SJohn.Forte@Sun.COM 		if (ldp->inuse == 0)
9117836SJohn.Forte@Sun.COM 			break;
9127836SJohn.Forte@Sun.COM 
9137836SJohn.Forte@Sun.COM 		if (lstate) {
9147836SJohn.Forte@Sun.COM 			(void) printf("%-15.15s ", dp_addr(&ldp->host));
9157836SJohn.Forte@Sun.COM 			(void) printf("%-4.4s ", ldp->up? "up" : "down");
9167836SJohn.Forte@Sun.COM 			(void) printf("%5ld ", ldp->timeout);
9177836SJohn.Forte@Sun.COM 			(void) printf("%-10.10s ", lockd_state(ldp->state));
9187836SJohn.Forte@Sun.COM 			(void) printf("%6d\n", ldp->order);
9197836SJohn.Forte@Sun.COM 		}
9207836SJohn.Forte@Sun.COM 
9217836SJohn.Forte@Sun.COM 		if (ldp->state == STATE_ASKED) {
9227836SJohn.Forte@Sun.COM 			if (lockdaemon_dead(ldp)) {
9237836SJohn.Forte@Sun.COM 				ldp->up = 0;
9247836SJohn.Forte@Sun.COM 				ldp->state = STATE_CLEAR;
9257836SJohn.Forte@Sun.COM 				continue;
9267836SJohn.Forte@Sun.COM 			}
9277836SJohn.Forte@Sun.COM 			send_lockmsg(WRITE_LOCK, (pid_t)0, &(ldp->host), 0);
9287836SJohn.Forte@Sun.COM 			continue;
9297836SJohn.Forte@Sun.COM 		}
9307836SJohn.Forte@Sun.COM 		if (the_lock.type == LOCK_WRITE &&
9317836SJohn.Forte@Sun.COM 		    the_lock.remote_daemon == NULL)
9327836SJohn.Forte@Sun.COM 			send_lockmsg(ALIVE, (pid_t)0, &(ldp->host), 0);
9337836SJohn.Forte@Sun.COM 	}
9347836SJohn.Forte@Sun.COM }
9357836SJohn.Forte@Sun.COM 
9367836SJohn.Forte@Sun.COM static void
dispatch(struct lock_msg * mp,daemonaddr_t * host)9377836SJohn.Forte@Sun.COM dispatch(struct lock_msg *mp, daemonaddr_t *host)
9387836SJohn.Forte@Sun.COM {
9397836SJohn.Forte@Sun.COM 	int message = mp->message;
9407836SJohn.Forte@Sun.COM 	int localhost;
9417836SJohn.Forte@Sun.COM 
9427836SJohn.Forte@Sun.COM 	localhost = islocalhost(host);
9437836SJohn.Forte@Sun.COM 	if (msgtrace && debugfile) {
9447836SJohn.Forte@Sun.COM 		time_t t = time(0);
9457836SJohn.Forte@Sun.COM 		if (localhost) {
9467836SJohn.Forte@Sun.COM 			(void) fprintf(debugfile,
9477836SJohn.Forte@Sun.COM 			    "%19.19s recv %-9.9s from %s (%ld)\n", ctime(&t),
9487836SJohn.Forte@Sun.COM 			    lockd_msg(message), dp_addr(host), mp->pid);
9497836SJohn.Forte@Sun.COM 		} else {
9507836SJohn.Forte@Sun.COM 			(void) fprintf(debugfile,
9517836SJohn.Forte@Sun.COM 			    "%19.19s recv %-9.9s from %s order %d (%ld)\n",
9527836SJohn.Forte@Sun.COM 			    ctime(&t), lockd_msg(message), dp_addr(host),
9537836SJohn.Forte@Sun.COM 			    mp->order, mp->pid);
9547836SJohn.Forte@Sun.COM 		}
9557836SJohn.Forte@Sun.COM 	}
9567836SJohn.Forte@Sun.COM 	DPF((stderr, "received message %d\n", message));
9577836SJohn.Forte@Sun.COM 	DPF((stderr, "from %s port %hu\n", dp_addr(host), host->sin_port));
9587836SJohn.Forte@Sun.COM 	if (!localhost)
9597836SJohn.Forte@Sun.COM 		daemon_alive(host, mp->order);
9607836SJohn.Forte@Sun.COM 	else
9617836SJohn.Forte@Sun.COM 		mp->order = order;
9627836SJohn.Forte@Sun.COM 	switch (message) {
9637836SJohn.Forte@Sun.COM 	case ALIVE:
9647836SJohn.Forte@Sun.COM 		DPF((stderr, "received ALIVE %s\n", dp_addr(host)));
9657836SJohn.Forte@Sun.COM 		/* do nothing, general "not localhost" code above does this */
9667836SJohn.Forte@Sun.COM 		break;
9677836SJohn.Forte@Sun.COM 	case UNLOCK:
9687836SJohn.Forte@Sun.COM 		DPF((stderr, "received UNLOCK\n"));
9697836SJohn.Forte@Sun.COM 		remote_unlock(mp->order, host);
9707836SJohn.Forte@Sun.COM 		break;
9717836SJohn.Forte@Sun.COM 	case GRANTED:
9727836SJohn.Forte@Sun.COM 		DPF((stderr, "received GRANTED\n"));
9737836SJohn.Forte@Sun.COM 		lock_granted(host);
9747836SJohn.Forte@Sun.COM 		break;
9757836SJohn.Forte@Sun.COM 	case WRITE_LOCK:
9767836SJohn.Forte@Sun.COM 		DPF((stderr, "received WRITE_LOCK\n"));
9777836SJohn.Forte@Sun.COM 		assert(!localhost);
9787836SJohn.Forte@Sun.COM 		remote_lock(host, mp);
9797836SJohn.Forte@Sun.COM 		break;
9807836SJohn.Forte@Sun.COM 	case READ_LOCK:
9817836SJohn.Forte@Sun.COM 	case LOCK_READ:
9827836SJohn.Forte@Sun.COM 		DPF((stderr, "received READ_LOCK\n"));
9837836SJohn.Forte@Sun.COM 		assert(localhost);
9847836SJohn.Forte@Sun.COM 		local_lock(LOCK_READ, mp, host);
9857836SJohn.Forte@Sun.COM 		break;
9867836SJohn.Forte@Sun.COM 	case LOCK_WRITE:
9877836SJohn.Forte@Sun.COM 		DPF((stderr, "received LOCK_WRITE\n"));
9887836SJohn.Forte@Sun.COM 		assert(localhost);
9897836SJohn.Forte@Sun.COM 		local_lock(LOCK_WRITE, mp, host);
9907836SJohn.Forte@Sun.COM 		break;
9917836SJohn.Forte@Sun.COM 	case LOCK_NOTLOCKED:
9927836SJohn.Forte@Sun.COM 		DPF((stderr, "received LOCK_NOTLOCKED\n"));
9937836SJohn.Forte@Sun.COM 		send_lockmsg(LOCK_ACK, (pid_t)0, host, mp->seq);
9947836SJohn.Forte@Sun.COM 		if (the_lock.type != LOCK_NOTLOCKED) {
9957836SJohn.Forte@Sun.COM 			local_unlock(mp->pid, mp->seq, NORMAL_UNLOCK);
9967836SJohn.Forte@Sun.COM 		}
9977836SJohn.Forte@Sun.COM 		break;
9987836SJohn.Forte@Sun.COM 	case LOCK_LOCKEDBY:
9997836SJohn.Forte@Sun.COM 		lockedby(host, mp->seq);
10007836SJohn.Forte@Sun.COM 		break;
10017836SJohn.Forte@Sun.COM 	case LOCK_STAT:
10027836SJohn.Forte@Sun.COM 		lock_stat();
10037836SJohn.Forte@Sun.COM 		break;
10047836SJohn.Forte@Sun.COM 	case LOCK_ACK:
10057836SJohn.Forte@Sun.COM 		/* throw message away -- this is an error to receive */
10067836SJohn.Forte@Sun.COM 		break;
10077836SJohn.Forte@Sun.COM 	}
10087836SJohn.Forte@Sun.COM }
10097836SJohn.Forte@Sun.COM 
10107836SJohn.Forte@Sun.COM /*
10117836SJohn.Forte@Sun.COM  * unqueue any locks asked for by pid and unlock any locks held by pid.
10127836SJohn.Forte@Sun.COM  */
10137836SJohn.Forte@Sun.COM 
10147836SJohn.Forte@Sun.COM static void
purge_pid(pid_t pid)10157836SJohn.Forte@Sun.COM purge_pid(pid_t pid)
10167836SJohn.Forte@Sun.COM {
10177836SJohn.Forte@Sun.COM 	DPF((stderr, "purge locks for %ld\n", pid));
10187836SJohn.Forte@Sun.COM 	unqueue_lock(NULL, pid);
10197836SJohn.Forte@Sun.COM 	if (the_lock.type != LOCK_NOTLOCKED)
10207836SJohn.Forte@Sun.COM 		local_unlock(pid, 0, FORCE_UNLOCK);
10217836SJohn.Forte@Sun.COM }
10227836SJohn.Forte@Sun.COM 
10237836SJohn.Forte@Sun.COM /*
10247836SJohn.Forte@Sun.COM  * Check for exit or exec of client processes.
10257836SJohn.Forte@Sun.COM  * The lock protecting the processes pid in the lockfile will
10267836SJohn.Forte@Sun.COM  * be removed by the kernel when a client exits or execs.
10277836SJohn.Forte@Sun.COM  */
10287836SJohn.Forte@Sun.COM 
10297836SJohn.Forte@Sun.COM static void
check_for_dead()10307836SJohn.Forte@Sun.COM check_for_dead()
10317836SJohn.Forte@Sun.COM {
10327836SJohn.Forte@Sun.COM 	int i, x;
10337836SJohn.Forte@Sun.COM 	pid_t pid;
10347836SJohn.Forte@Sun.COM 
10357836SJohn.Forte@Sun.COM 	for (i = 0; (x = cfg_filelock(i, 0)) != CFG_LF_EOF; i++) {
10367836SJohn.Forte@Sun.COM 		if (x == CFG_LF_AGAIN)
10377836SJohn.Forte@Sun.COM 			continue; /* can't take lock, must be still alive */
10387836SJohn.Forte@Sun.COM 		cfg_readpid(i, &pid);
10397836SJohn.Forte@Sun.COM 		cfg_writepid(i, (pid_t)0);
1040*11576SSurya.Prakki@Sun.COM 		(void) cfg_fileunlock(i);
10417836SJohn.Forte@Sun.COM 		if (pid != (pid_t)0)
10427836SJohn.Forte@Sun.COM 			purge_pid(pid);
10437836SJohn.Forte@Sun.COM 	}
10447836SJohn.Forte@Sun.COM }
10457836SJohn.Forte@Sun.COM 
10467836SJohn.Forte@Sun.COM static void
build_daemon_list(char * cf_file,int exe)10477836SJohn.Forte@Sun.COM build_daemon_list(char *cf_file, int exe)
10487836SJohn.Forte@Sun.COM {
10497836SJohn.Forte@Sun.COM 	FILE *fp;
10507836SJohn.Forte@Sun.COM 	char	host[1024];
10517836SJohn.Forte@Sun.COM 	int	port;
10527836SJohn.Forte@Sun.COM 	int	i;
10537836SJohn.Forte@Sun.COM 	struct	hostent *hp;
10547836SJohn.Forte@Sun.COM 	struct lockdaemon *ldp;
10557836SJohn.Forte@Sun.COM 
10567836SJohn.Forte@Sun.COM 	if ((hp = gethostbyname("localhost")) == NULL) {
10577836SJohn.Forte@Sun.COM 		(void) fprintf(stderr, "%s: Can't find hostent for %s\n",
10587836SJohn.Forte@Sun.COM 		    program, "localhost");
10597836SJohn.Forte@Sun.COM 		spcs_log("cfglockd", NULL, "couldn't find localhost");
10607836SJohn.Forte@Sun.COM 		exit(1);
10617836SJohn.Forte@Sun.COM 	}
10627836SJohn.Forte@Sun.COM 
10637836SJohn.Forte@Sun.COM 	(void) memcpy(&(localhost.sin_addr.s_addr), *(hp->h_addr_list),
1064*11576SSurya.Prakki@Sun.COM 	    sizeof (localhost.sin_addr));
10657836SJohn.Forte@Sun.COM 	if (cf_file == NULL) {
10667836SJohn.Forte@Sun.COM 		(void) endhostent();
10677836SJohn.Forte@Sun.COM 		return;
10687836SJohn.Forte@Sun.COM 	}
10697836SJohn.Forte@Sun.COM 	if (exe) {
10707836SJohn.Forte@Sun.COM 		if ((fp = popen(cf_file, "r")) == NULL) {
10717836SJohn.Forte@Sun.COM 			perror(cf_file);
10727836SJohn.Forte@Sun.COM 			(void) fprintf(stderr,
10737836SJohn.Forte@Sun.COM 			    "%s: Can't open config program\n", program);
10747836SJohn.Forte@Sun.COM 			spcs_log("cfglockd", NULL, "couldn't read config");
10757836SJohn.Forte@Sun.COM 			exit(1);
10767836SJohn.Forte@Sun.COM 		}
10777836SJohn.Forte@Sun.COM 	} else {
10787836SJohn.Forte@Sun.COM 		if ((fp = fopen(cf_file, "r")) == NULL) {
10797836SJohn.Forte@Sun.COM 			perror(cf_file);
10807836SJohn.Forte@Sun.COM 			(void) fprintf(stderr, "%s: Can't open config file\n",
10817836SJohn.Forte@Sun.COM 			    program);
10827836SJohn.Forte@Sun.COM 			spcs_log("cfglockd", NULL, "couldn't read config");
10837836SJohn.Forte@Sun.COM 			exit(1);
10847836SJohn.Forte@Sun.COM 		}
10857836SJohn.Forte@Sun.COM 	}
10867836SJohn.Forte@Sun.COM 	ldp = daemon_list;
10877836SJohn.Forte@Sun.COM 	while ((i = fscanf(fp, "%s %d\n", host, &port)) != EOF) {
10887836SJohn.Forte@Sun.COM 		if (host[0] == '#')	/* line starting with # are comments */
10897836SJohn.Forte@Sun.COM 			continue;
10907836SJohn.Forte@Sun.COM 		if (i == 1) {
10917836SJohn.Forte@Sun.COM 			port = lock_port;
10927836SJohn.Forte@Sun.COM 		} else {
10937836SJohn.Forte@Sun.COM 			if (strcmp(host, "localhost") == 0) {
10947836SJohn.Forte@Sun.COM 				lock_port = port;
10957836SJohn.Forte@Sun.COM 				continue;
10967836SJohn.Forte@Sun.COM 			}
10977836SJohn.Forte@Sun.COM 		}
10987836SJohn.Forte@Sun.COM 
10997836SJohn.Forte@Sun.COM 		if ((hp = gethostbyname(host)) == NULL) {
11007836SJohn.Forte@Sun.COM 			(void) fprintf(stderr,
11017836SJohn.Forte@Sun.COM 			    "%s: Can't find hostent for %s\n", program, host);
11027836SJohn.Forte@Sun.COM 			continue;
11037836SJohn.Forte@Sun.COM 		}
11047836SJohn.Forte@Sun.COM 
11057836SJohn.Forte@Sun.COM 		(void) memcpy(&(ldp->host.sin_addr.s_addr), *(hp->h_addr_list),
11067836SJohn.Forte@Sun.COM 		    sizeof (ldp->host.sin_addr));
11077836SJohn.Forte@Sun.COM 		DPF((stderr, "daemon: %s\t%s\n",
1108*11576SSurya.Prakki@Sun.COM 		    inet_ntoa(ldp->host.sin_addr), hp->h_name));
11097836SJohn.Forte@Sun.COM 		if (islocalhost(&(ldp->host))) {
11107836SJohn.Forte@Sun.COM 			DPF((stderr, "is an alias for this host, skipping\n"));
11117836SJohn.Forte@Sun.COM 			continue;
11127836SJohn.Forte@Sun.COM 		}
11137836SJohn.Forte@Sun.COM 		ldp->host.sin_port = htons((short)port);
11147836SJohn.Forte@Sun.COM 		ldp->host.sin_family = hp->h_addrtype;
11157836SJohn.Forte@Sun.COM 		ldp->inuse = 1;
11167836SJohn.Forte@Sun.COM 		ldp->up = 1;
11177836SJohn.Forte@Sun.COM 		ldp++;
11187836SJohn.Forte@Sun.COM 	}
11197836SJohn.Forte@Sun.COM 	if (exe)
11207836SJohn.Forte@Sun.COM 		(void) pclose(fp);
11217836SJohn.Forte@Sun.COM 	else
11227836SJohn.Forte@Sun.COM 		(void) fclose(fp);
11237836SJohn.Forte@Sun.COM 	(void) endhostent();
11247836SJohn.Forte@Sun.COM }
11257836SJohn.Forte@Sun.COM 
11267836SJohn.Forte@Sun.COM static void
usage()11277836SJohn.Forte@Sun.COM usage()
11287836SJohn.Forte@Sun.COM {
11297836SJohn.Forte@Sun.COM 	(void) fprintf(stderr,
11307836SJohn.Forte@Sun.COM 	    gettext("usage: %s [-d] [-f file]|[-e program]\n"), program);
11317836SJohn.Forte@Sun.COM 	exit(1);
11327836SJohn.Forte@Sun.COM }
11337836SJohn.Forte@Sun.COM 
11347836SJohn.Forte@Sun.COM static void
unexpected(int sig)11357836SJohn.Forte@Sun.COM unexpected(int sig)
11367836SJohn.Forte@Sun.COM {
11377836SJohn.Forte@Sun.COM 	spcs_log("cfglockd", NULL, "pid %d unexpected signal %d, ignoring",
11387836SJohn.Forte@Sun.COM 	    getpid(), sig);
11397836SJohn.Forte@Sun.COM }
11407836SJohn.Forte@Sun.COM 
11417836SJohn.Forte@Sun.COM static void
term(int sig)11427836SJohn.Forte@Sun.COM term(int sig)
11437836SJohn.Forte@Sun.COM {
11447836SJohn.Forte@Sun.COM 	(void) unlink(CFG_PIDFILE);
11457836SJohn.Forte@Sun.COM 	spcs_log("cfglockd", NULL, "pid %d terminate on signal %d", getpid(),
11467836SJohn.Forte@Sun.COM 	    sig);
11477836SJohn.Forte@Sun.COM 	exit(0);
11487836SJohn.Forte@Sun.COM }
11497836SJohn.Forte@Sun.COM 
11507836SJohn.Forte@Sun.COM static void
init(int argc,char * argv[])11517836SJohn.Forte@Sun.COM init(int argc, char *argv[])
11527836SJohn.Forte@Sun.COM {
11537836SJohn.Forte@Sun.COM #if defined(_SunOS_5_6) || defined(_SunOS_5_7) || defined(_SunOS_5_8)
11547836SJohn.Forte@Sun.COM 	struct rlimit rl;
11557836SJohn.Forte@Sun.COM #endif
11567836SJohn.Forte@Sun.COM 	int	c, i, x;
11577836SJohn.Forte@Sun.COM 	int	rc;
11587836SJohn.Forte@Sun.COM 	char	*cp = NULL;
11597836SJohn.Forte@Sun.COM 	struct	itimerval	tv;
11607836SJohn.Forte@Sun.COM 	struct	timeval		tp;
11617836SJohn.Forte@Sun.COM 	socklen_t len = sizeof (thishost);
11627836SJohn.Forte@Sun.COM 	int	exe = 0;
11637836SJohn.Forte@Sun.COM 	pid_t	pid;
11647836SJohn.Forte@Sun.COM 	FILE	*fp;
11657836SJohn.Forte@Sun.COM 
11667836SJohn.Forte@Sun.COM 	lstate = (getenv("LOCKD_STATE") != NULL);
11677836SJohn.Forte@Sun.COM 	msgtrace = (getenv("LOCKD_MSG") != NULL);
11687836SJohn.Forte@Sun.COM 
11697836SJohn.Forte@Sun.COM 	/*
11707836SJohn.Forte@Sun.COM 	 * Fork off a child that becomes the daemon.
11717836SJohn.Forte@Sun.COM 	 */
11727836SJohn.Forte@Sun.COM 
11737836SJohn.Forte@Sun.COM #ifndef TTY_MESSAGES
11747836SJohn.Forte@Sun.COM 	if ((rc = fork()) > 0)
11757836SJohn.Forte@Sun.COM 		exit(0);
11767836SJohn.Forte@Sun.COM 	else if (rc < 0) {
11777836SJohn.Forte@Sun.COM 		spcs_log("cfglockd", NULL, "can't fork %d", errno);
11787836SJohn.Forte@Sun.COM 		(void) fprintf(stderr, gettext("dscfglockd: cannot fork: %s\n"),
11797836SJohn.Forte@Sun.COM 		    strerror(errno));
11807836SJohn.Forte@Sun.COM 		exit(1);
11817836SJohn.Forte@Sun.COM 	}
11827836SJohn.Forte@Sun.COM #endif
11837836SJohn.Forte@Sun.COM 
11847836SJohn.Forte@Sun.COM 	/*
11857836SJohn.Forte@Sun.COM 	 * In child - become daemon.
11867836SJohn.Forte@Sun.COM 	 */
11877836SJohn.Forte@Sun.COM 
11887836SJohn.Forte@Sun.COM #if !defined(_SunOS_5_6) && !defined(_SunOS_5_7) && !defined(_SunOS_5_8)
11897836SJohn.Forte@Sun.COM 	/* use closefrom(3C) from PSARC/2000/193 when possible */
11907836SJohn.Forte@Sun.COM 	closefrom(CLOSE_FD);
11917836SJohn.Forte@Sun.COM #else
11927836SJohn.Forte@Sun.COM 	(void) getrlimit(RLIMIT_NOFILE, &rl);
11937836SJohn.Forte@Sun.COM 	for (i = CLOSE_FD; i < rl.rlim_max; i++)
11947836SJohn.Forte@Sun.COM 		(void) close(i);
11957836SJohn.Forte@Sun.COM #endif
11967836SJohn.Forte@Sun.COM 
11977836SJohn.Forte@Sun.COM #ifdef DEBUG
11987836SJohn.Forte@Sun.COM #ifndef	TTY_MESSAGES
11997836SJohn.Forte@Sun.COM 	(void) open("/dev/console", O_WRONLY|O_APPEND);
12007836SJohn.Forte@Sun.COM 	(void) dup(0);
12017836SJohn.Forte@Sun.COM 	(void) dup(0);
12027836SJohn.Forte@Sun.COM #endif
12037836SJohn.Forte@Sun.COM #endif
12047836SJohn.Forte@Sun.COM 	(void) close(0);
12057836SJohn.Forte@Sun.COM 
12067836SJohn.Forte@Sun.COM 	if (msgtrace || lstate) {
12077836SJohn.Forte@Sun.COM 		debugfile = fopen("/var/tmp/dscfglockd.out", "a");
12087836SJohn.Forte@Sun.COM 		if (debugfile) {
12097836SJohn.Forte@Sun.COM 			time_t t = time(0);
12107836SJohn.Forte@Sun.COM 			setbuf(debugfile, (char *)0);
12117836SJohn.Forte@Sun.COM 			(void) fprintf(debugfile, "%19.19s dscfglockd start\n",
12127836SJohn.Forte@Sun.COM 			    ctime(&t));
12137836SJohn.Forte@Sun.COM 		}
12147836SJohn.Forte@Sun.COM 	}
12157836SJohn.Forte@Sun.COM 
12167836SJohn.Forte@Sun.COM 	(void) setpgrp();
12177836SJohn.Forte@Sun.COM 	spcs_log("cfglockd", NULL, "new lock daemon, pid %d", getpid());
12187836SJohn.Forte@Sun.COM 
12197836SJohn.Forte@Sun.COM 	/*
12207836SJohn.Forte@Sun.COM 	 * Catch as unexpected all signals apart from SIGTERM.
12217836SJohn.Forte@Sun.COM 	 */
12227836SJohn.Forte@Sun.COM 
12237836SJohn.Forte@Sun.COM 	for (i = 1; i < _sys_nsig; i++)
12247836SJohn.Forte@Sun.COM 		(void) sigset(i, unexpected);
12257836SJohn.Forte@Sun.COM 	(void) sigset(SIGTERM, term);
12267836SJohn.Forte@Sun.COM 
12277836SJohn.Forte@Sun.COM 	for (i = 0; (c = getopt(argc, argv, "df:e:")) != EOF; i++) {
12287836SJohn.Forte@Sun.COM 		switch (c) {
12297836SJohn.Forte@Sun.COM 		case 'd':
12307836SJohn.Forte@Sun.COM 			debug = 1;
12317836SJohn.Forte@Sun.COM 			break;
12327836SJohn.Forte@Sun.COM 		case 'e':
12337836SJohn.Forte@Sun.COM 			exe = 1;
12347836SJohn.Forte@Sun.COM 			if (cp) {
12357836SJohn.Forte@Sun.COM 				usage();
12367836SJohn.Forte@Sun.COM 			}
12377836SJohn.Forte@Sun.COM 			cp = optarg;
12387836SJohn.Forte@Sun.COM 			break;
12397836SJohn.Forte@Sun.COM 		case 'f':
12407836SJohn.Forte@Sun.COM 			if (cp) {
12417836SJohn.Forte@Sun.COM 				usage();
12427836SJohn.Forte@Sun.COM 			}
12437836SJohn.Forte@Sun.COM 			cp = optarg;
12447836SJohn.Forte@Sun.COM 			break;
12457836SJohn.Forte@Sun.COM 		default:
12467836SJohn.Forte@Sun.COM 			usage();
12477836SJohn.Forte@Sun.COM 			break;
12487836SJohn.Forte@Sun.COM 		}
12497836SJohn.Forte@Sun.COM 	}
12507836SJohn.Forte@Sun.COM 
12517836SJohn.Forte@Sun.COM 	ifc = (struct ifconf *)malloc(sizeof (struct ifconf));
12527836SJohn.Forte@Sun.COM 	if (ifc == NULL) {
12537836SJohn.Forte@Sun.COM 		perror(CFG_PIDFILE);
12547836SJohn.Forte@Sun.COM 		DPF((stderr, "Can't open pid file\n"));
12557836SJohn.Forte@Sun.COM 		exit(1);
12567836SJohn.Forte@Sun.COM 	}
12577836SJohn.Forte@Sun.COM 	(void) memset((char *)ifc, 0, sizeof (struct ifconf));
12587836SJohn.Forte@Sun.COM 	getmyaddrs(ifc);
12597836SJohn.Forte@Sun.COM 
12607836SJohn.Forte@Sun.COM 	/*
12617836SJohn.Forte@Sun.COM 	 * if (lockdaemonalive()) {
12627836SJohn.Forte@Sun.COM 	 *	(void) fprintf(stderr, "%s: %s\n", program,
12637836SJohn.Forte@Sun.COM 	 *		gettext("There is already a live lockdaemon"));
12647836SJohn.Forte@Sun.COM 	 *	exit(1);
12657836SJohn.Forte@Sun.COM 	 * }
12667836SJohn.Forte@Sun.COM 	 */
12677836SJohn.Forte@Sun.COM 	if ((fp = fopen(CFG_PIDFILE, "w")) == NULL) {
12687836SJohn.Forte@Sun.COM 		perror(CFG_PIDFILE);
12697836SJohn.Forte@Sun.COM 		DPF((stderr, "Can't open pid file\n"));
12707836SJohn.Forte@Sun.COM 		exit(1);
12717836SJohn.Forte@Sun.COM 	}
12727836SJohn.Forte@Sun.COM 	(void) fprintf(fp, "%ld\n", getpid());
12737836SJohn.Forte@Sun.COM 	(void) fclose(fp);
12747836SJohn.Forte@Sun.COM 
12757836SJohn.Forte@Sun.COM 	/* order should be set to node number within cluster */
12767836SJohn.Forte@Sun.COM 	order = cfg_iscluster();
12777836SJohn.Forte@Sun.COM 	cfg_lfinit();
12787836SJohn.Forte@Sun.COM 
12797836SJohn.Forte@Sun.COM 	if (!order) {
12807836SJohn.Forte@Sun.COM 		(void) gettimeofday(&tp, NULL);
12817836SJohn.Forte@Sun.COM 		srand48(tp.tv_usec);
12827836SJohn.Forte@Sun.COM 		order = lrand48();
12837836SJohn.Forte@Sun.COM 		if (debugfile) {
12847836SJohn.Forte@Sun.COM 			(void) fprintf(debugfile, "WARNING: order number "
12857836SJohn.Forte@Sun.COM 			    "is 0 -- changing randomly to %d\n", order);
12867836SJohn.Forte@Sun.COM 		}
12877836SJohn.Forte@Sun.COM 	}
12887836SJohn.Forte@Sun.COM 	c = 0;
12897836SJohn.Forte@Sun.COM 	for (i = 0; (x = cfg_filelock(i, 0)) != CFG_LF_EOF; i++) {
12907836SJohn.Forte@Sun.COM 		if (x == CFG_LF_AGAIN) {
12917836SJohn.Forte@Sun.COM 			cfg_readpid(i, &pid);
12927836SJohn.Forte@Sun.COM 			if (c++ == 0)
12937836SJohn.Forte@Sun.COM 				spcs_log("cfglockd", NULL,
12947836SJohn.Forte@Sun.COM 				    "init .dscfg.lck slot %d pid %d locked",
12957836SJohn.Forte@Sun.COM 				    i, pid);
12967836SJohn.Forte@Sun.COM 			DPF((stderr, "client process %ld still alive\n", pid));
12977836SJohn.Forte@Sun.COM 			continue; /* can't take lock, must be still alive */
12987836SJohn.Forte@Sun.COM 		}
12997836SJohn.Forte@Sun.COM 		cfg_writepid(i, 0);
1300*11576SSurya.Prakki@Sun.COM 		(void) cfg_fileunlock(i);
13017836SJohn.Forte@Sun.COM 	}
13027836SJohn.Forte@Sun.COM 
13037836SJohn.Forte@Sun.COM 	tv.it_interval.tv_sec = TIMEOUT_SECS;
13047836SJohn.Forte@Sun.COM 	tv.it_interval.tv_usec = 0;
13057836SJohn.Forte@Sun.COM 	tv.it_value = tv.it_interval;
13067836SJohn.Forte@Sun.COM 
13077836SJohn.Forte@Sun.COM 	bzero(unlock_buf, sizeof (unlock_buf));
13087836SJohn.Forte@Sun.COM 	next_q = 0;
13097836SJohn.Forte@Sun.COM 	build_daemon_list(cp, exe);
13107836SJohn.Forte@Sun.COM 	if ((lock_soc = socket(pf_inet, SOCK_DGRAM, 0)) < 0) {
13117836SJohn.Forte@Sun.COM 		(void) fprintf(stderr, "%s: %s\n", program,
13127836SJohn.Forte@Sun.COM 		    gettext("failed to create socket"));
13137836SJohn.Forte@Sun.COM 		perror("socket");
13147836SJohn.Forte@Sun.COM 		spcs_log("cfglockd", NULL, "couldn't create socket");
13157836SJohn.Forte@Sun.COM 		exit(1);
13167836SJohn.Forte@Sun.COM 	}
13177836SJohn.Forte@Sun.COM 	thishost.sin_family = AF_INET;
13187836SJohn.Forte@Sun.COM 	thishost.sin_addr.s_addr = INADDR_ANY;
13197836SJohn.Forte@Sun.COM 	thishost.sin_port = htons(lock_port);
13207836SJohn.Forte@Sun.COM 	rc = bind(lock_soc, (struct sockaddr *)&thishost, sizeof (thishost));
13217836SJohn.Forte@Sun.COM 	if (rc < 0) {
13227836SJohn.Forte@Sun.COM 		perror("bind");
13237836SJohn.Forte@Sun.COM 		spcs_log("cfglockd", NULL, "couldn't bind");
13247836SJohn.Forte@Sun.COM 		exit(1);
13257836SJohn.Forte@Sun.COM 	}
13267836SJohn.Forte@Sun.COM 	if (getsockname(lock_soc, (struct sockaddr *)&thishost, &len) < 0)
13277836SJohn.Forte@Sun.COM 		perror("getsockname");
13287836SJohn.Forte@Sun.COM 	send_aliveall();
1329*11576SSurya.Prakki@Sun.COM 	(void) sigset(SIGALRM, keepalive);
13307836SJohn.Forte@Sun.COM 	(void) setitimer(ITIMER_REAL, &tv, NULL);
13317836SJohn.Forte@Sun.COM 	/*
13327836SJohn.Forte@Sun.COM 	 * wait 2 time outs before allowing a lock to find if someone else
13337836SJohn.Forte@Sun.COM 	 * currently has the lock.
13347836SJohn.Forte@Sun.COM 	 */
13357836SJohn.Forte@Sun.COM }
13367836SJohn.Forte@Sun.COM 
13377836SJohn.Forte@Sun.COM #ifdef lint
13387836SJohn.Forte@Sun.COM int
lintmain(int argc,char * argv[])13397836SJohn.Forte@Sun.COM lintmain(int argc, char *argv[])
13407836SJohn.Forte@Sun.COM #else
13417836SJohn.Forte@Sun.COM int
13427836SJohn.Forte@Sun.COM main(int argc, char *argv[])
13437836SJohn.Forte@Sun.COM #endif
13447836SJohn.Forte@Sun.COM {
13457836SJohn.Forte@Sun.COM 	struct lock_msg message_buf;
13467836SJohn.Forte@Sun.COM 	daemonaddr_t from;
13477836SJohn.Forte@Sun.COM 	int addrlen;
13487836SJohn.Forte@Sun.COM 	int rc;
13497836SJohn.Forte@Sun.COM 	int x = 1;		/* kludge to stop warnings from compiler */
13507836SJohn.Forte@Sun.COM 
13517836SJohn.Forte@Sun.COM 	init(argc, argv);
13527836SJohn.Forte@Sun.COM 	CRIT_BEGIN();
13537836SJohn.Forte@Sun.COM 	while (x) {
13547836SJohn.Forte@Sun.COM 		CRIT_END();
13557836SJohn.Forte@Sun.COM 		addrlen = sizeof (from);
13567836SJohn.Forte@Sun.COM 		DPF((stderr, "begin recvfrom\n"));
13577836SJohn.Forte@Sun.COM 		rc = recvfrom(lock_soc, &message_buf, sizeof (message_buf),
13587836SJohn.Forte@Sun.COM 		    0, (struct sockaddr *)&from, &addrlen);
13597836SJohn.Forte@Sun.COM 		DPF((stderr, "end recvfrom rc = %d\n", rc));
13607836SJohn.Forte@Sun.COM 		CRIT_BEGIN();
13617836SJohn.Forte@Sun.COM 		if (rc == sizeof (message_buf))
13627836SJohn.Forte@Sun.COM 			dispatch(&message_buf, &from);
13637836SJohn.Forte@Sun.COM 		else
13647836SJohn.Forte@Sun.COM 			check_for_write_lock();
13657836SJohn.Forte@Sun.COM 
13667836SJohn.Forte@Sun.COM 		/* if we own the lock, check to see if the process died */
13677836SJohn.Forte@Sun.COM 		if (the_lock.type != LOCK_NOTLOCKED &&
13687836SJohn.Forte@Sun.COM 		    the_lock.remote_daemon == NULL)
13697836SJohn.Forte@Sun.COM 			check_for_dead();
13707836SJohn.Forte@Sun.COM 	}
13717836SJohn.Forte@Sun.COM 	CRIT_END();
13727836SJohn.Forte@Sun.COM 	return (0);
13737836SJohn.Forte@Sun.COM }
1374