xref: /titanic_44/usr/src/cmd/avs/dscfglockd/dscfglockd.c (revision fcf3ce441efd61da9bb2884968af01cb7c1452cc)
1*fcf3ce44SJohn Forte /*
2*fcf3ce44SJohn Forte  * CDDL HEADER START
3*fcf3ce44SJohn Forte  *
4*fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5*fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6*fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7*fcf3ce44SJohn Forte  *
8*fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10*fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11*fcf3ce44SJohn Forte  * and limitations under the License.
12*fcf3ce44SJohn Forte  *
13*fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14*fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16*fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17*fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18*fcf3ce44SJohn Forte  *
19*fcf3ce44SJohn Forte  * CDDL HEADER END
20*fcf3ce44SJohn Forte  */
21*fcf3ce44SJohn Forte /*
22*fcf3ce44SJohn Forte  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*fcf3ce44SJohn Forte  * Use is subject to license terms.
24*fcf3ce44SJohn Forte  */
25*fcf3ce44SJohn Forte 
26*fcf3ce44SJohn Forte #include <signal.h>
27*fcf3ce44SJohn Forte #include <sys/types.h>
28*fcf3ce44SJohn Forte #include <sys/time.h>
29*fcf3ce44SJohn Forte #include <sys/socket.h>
30*fcf3ce44SJohn Forte #include <netinet/in.h>
31*fcf3ce44SJohn Forte #include <netinet/tcp.h>
32*fcf3ce44SJohn Forte #include <arpa/inet.h>
33*fcf3ce44SJohn Forte #include <netdb.h>
34*fcf3ce44SJohn Forte #include <fcntl.h>
35*fcf3ce44SJohn Forte #include <string.h>
36*fcf3ce44SJohn Forte #include <memory.h>
37*fcf3ce44SJohn Forte #include <sys/param.h>
38*fcf3ce44SJohn Forte #include <sys/pathconf.h>
39*fcf3ce44SJohn Forte #include <netdir.h>
40*fcf3ce44SJohn Forte #include <netconfig.h>
41*fcf3ce44SJohn Forte #include <sys/sockio.h>
42*fcf3ce44SJohn Forte #include <net/if.h>
43*fcf3ce44SJohn Forte #include <sys/resource.h>
44*fcf3ce44SJohn Forte #include <stdio.h>
45*fcf3ce44SJohn Forte #include <errno.h>
46*fcf3ce44SJohn Forte #include <assert.h>
47*fcf3ce44SJohn Forte #include <locale.h>
48*fcf3ce44SJohn Forte #include <unistd.h>
49*fcf3ce44SJohn Forte #include <stdlib.h>
50*fcf3ce44SJohn Forte #include <string.h>
51*fcf3ce44SJohn Forte #include <strings.h>
52*fcf3ce44SJohn Forte #include <sys/unistat/spcs_s.h>
53*fcf3ce44SJohn Forte #include <sys/unistat/spcs_s_u.h>
54*fcf3ce44SJohn Forte #include <sys/unistat/spcs_errors.h>
55*fcf3ce44SJohn Forte 
56*fcf3ce44SJohn Forte #include <sys/nsctl/cfg.h>
57*fcf3ce44SJohn Forte #include <sys/nsctl/cfg_lockd.h>
58*fcf3ce44SJohn Forte 
59*fcf3ce44SJohn Forte #ifdef DEBUG
60*fcf3ce44SJohn Forte #define	DPF(m)		if (debug) (void) fprintf m
61*fcf3ce44SJohn Forte #else
62*fcf3ce44SJohn Forte #define	DPF(m)
63*fcf3ce44SJohn Forte #endif
64*fcf3ce44SJohn Forte 
65*fcf3ce44SJohn Forte #ifdef	TTY_MESSAGES
66*fcf3ce44SJohn Forte #define	CLOSE_FD	3
67*fcf3ce44SJohn Forte #else
68*fcf3ce44SJohn Forte #define	CLOSE_FD	0
69*fcf3ce44SJohn Forte #endif
70*fcf3ce44SJohn Forte 
71*fcf3ce44SJohn Forte #define	MAX_LOCKQ	1024
72*fcf3ce44SJohn Forte #define	MAX_DAEMONS	1024
73*fcf3ce44SJohn Forte #define	MAX_LOCAL	1024
74*fcf3ce44SJohn Forte #define	MAX_UNLOCK	32
75*fcf3ce44SJohn Forte #define	MAX_TIMEOUTS	3
76*fcf3ce44SJohn Forte #define	TIMEOUT_SECS	5
77*fcf3ce44SJohn Forte 
78*fcf3ce44SJohn Forte static char program[] = "dscfglockd";
79*fcf3ce44SJohn Forte static int debug;
80*fcf3ce44SJohn Forte static int lstate;
81*fcf3ce44SJohn Forte static int msgtrace;
82*fcf3ce44SJohn Forte static FILE *debugfile = NULL;
83*fcf3ce44SJohn Forte 
84*fcf3ce44SJohn Forte struct lock_req {
85*fcf3ce44SJohn Forte 	cfglockd_t	type;	/* read or write */
86*fcf3ce44SJohn Forte 	pid_t	pid;		/* pid of read locker or local writer */
87*fcf3ce44SJohn Forte 	daemonaddr_t	remote;	/* remote machine requesting write lock */
88*fcf3ce44SJohn Forte 	int		state;	/* for write locks */
89*fcf3ce44SJohn Forte 	int32_t		order;	/* who gets priority? */
90*fcf3ce44SJohn Forte } lock_queue[MAX_LOCKQ];
91*fcf3ce44SJohn Forte 
92*fcf3ce44SJohn Forte struct unlock_s {
93*fcf3ce44SJohn Forte 	pid_t	pid;		/* pid of locker */
94*fcf3ce44SJohn Forte 	uint8_t seq;		/* seq number of last lock request */
95*fcf3ce44SJohn Forte } unlock_buf[MAX_UNLOCK];
96*fcf3ce44SJohn Forte 
97*fcf3ce44SJohn Forte int next_req;
98*fcf3ce44SJohn Forte int32_t order;
99*fcf3ce44SJohn Forte 
100*fcf3ce44SJohn Forte #define	lock_wanted	lock_queue[0]
101*fcf3ce44SJohn Forte long	ticker	= 1l;
102*fcf3ce44SJohn Forte 
103*fcf3ce44SJohn Forte #define	ALIVE		0x10
104*fcf3ce44SJohn Forte #define	READ_LOCK	0x11
105*fcf3ce44SJohn Forte #define	WRITE_LOCK	0x12
106*fcf3ce44SJohn Forte #define	UNLOCK		0x13
107*fcf3ce44SJohn Forte #define	GRANTED		0x14
108*fcf3ce44SJohn Forte 
109*fcf3ce44SJohn Forte int next_q;
110*fcf3ce44SJohn Forte 
111*fcf3ce44SJohn Forte struct {
112*fcf3ce44SJohn Forte 	cfglockd_t	type;
113*fcf3ce44SJohn Forte 	int		nholders;
114*fcf3ce44SJohn Forte 	int		state;
115*fcf3ce44SJohn Forte 	daemonaddr_t	holder;
116*fcf3ce44SJohn Forte 	struct lockdaemon	*remote_daemon;
117*fcf3ce44SJohn Forte 	pid_t		holding_pid[MAX_LOCAL];
118*fcf3ce44SJohn Forte } the_lock;
119*fcf3ce44SJohn Forte 
120*fcf3ce44SJohn Forte daemonaddr_t	thishost;
121*fcf3ce44SJohn Forte daemonaddr_t	localhost;
122*fcf3ce44SJohn Forte 
123*fcf3ce44SJohn Forte #define	STATE_CLEAR	0
124*fcf3ce44SJohn Forte #define	STATE_ASKED	1
125*fcf3ce44SJohn Forte #define	STATE_OKAYED	2
126*fcf3ce44SJohn Forte #define	STATE_WANTS	3
127*fcf3ce44SJohn Forte #define	lockdaemon_dead(ldp)	((ticker - (ldp)->timeout) > MAX_TIMEOUTS)
128*fcf3ce44SJohn Forte #define	CRIT_BEGIN()	sighold(SIGALRM)
129*fcf3ce44SJohn Forte #define	CRIT_END()	sigrelse(SIGALRM)
130*fcf3ce44SJohn Forte 
131*fcf3ce44SJohn Forte #define	NORMAL_UNLOCK	0
132*fcf3ce44SJohn Forte #define	FORCE_UNLOCK	1
133*fcf3ce44SJohn Forte 
134*fcf3ce44SJohn Forte struct lockdaemon {
135*fcf3ce44SJohn Forte 	daemonaddr_t	host;
136*fcf3ce44SJohn Forte 	int	up;
137*fcf3ce44SJohn Forte 	long	timeout;
138*fcf3ce44SJohn Forte 	int	inuse;
139*fcf3ce44SJohn Forte 	int	state;
140*fcf3ce44SJohn Forte 	int32_t	order;
141*fcf3ce44SJohn Forte } daemon_list[MAX_DAEMONS];
142*fcf3ce44SJohn Forte 
143*fcf3ce44SJohn Forte unsigned short	lock_port = CFG_SERVER_PORT;
144*fcf3ce44SJohn Forte int	lock_soc = 0;
145*fcf3ce44SJohn Forte int	pf_inet = PF_INET;
146*fcf3ce44SJohn Forte #define	dp_addr(p)	inet_ntoa(((struct sockaddr_in *)p)->sin_addr)
147*fcf3ce44SJohn Forte 
148*fcf3ce44SJohn Forte #define	MAXIFS 32
149*fcf3ce44SJohn Forte 
150*fcf3ce44SJohn Forte static char *
151*fcf3ce44SJohn Forte lockd_type(cfglockd_t type)
152*fcf3ce44SJohn Forte {
153*fcf3ce44SJohn Forte 	switch (type) {
154*fcf3ce44SJohn Forte 	case LOCK_NOTLOCKED:	return "NotLocked";
155*fcf3ce44SJohn Forte 	case LOCK_READ:		return "Read";
156*fcf3ce44SJohn Forte 	case LOCK_WRITE:	return "Write";
157*fcf3ce44SJohn Forte 	case LOCK_LOCKED:	return "Locked";
158*fcf3ce44SJohn Forte 	case LOCK_LOCKEDBY:	return "LockedBy";
159*fcf3ce44SJohn Forte 	case LOCK_STAT:		return "Stat";
160*fcf3ce44SJohn Forte 	case LOCK_ACK:		return "Ack";
161*fcf3ce44SJohn Forte 	default:		return "*unknown*";
162*fcf3ce44SJohn Forte 	}
163*fcf3ce44SJohn Forte }
164*fcf3ce44SJohn Forte 
165*fcf3ce44SJohn Forte static char *
166*fcf3ce44SJohn Forte lockd_state(int state)
167*fcf3ce44SJohn Forte {
168*fcf3ce44SJohn Forte 	switch (state) {
169*fcf3ce44SJohn Forte 	case STATE_CLEAR:	return "Clear";
170*fcf3ce44SJohn Forte 	case STATE_ASKED:	return "Asked";
171*fcf3ce44SJohn Forte 	case STATE_OKAYED:	return "Okayed";
172*fcf3ce44SJohn Forte 	case STATE_WANTS:	return "Wants";
173*fcf3ce44SJohn Forte 	default:		return "*unknown*";
174*fcf3ce44SJohn Forte 	}
175*fcf3ce44SJohn Forte }
176*fcf3ce44SJohn Forte 
177*fcf3ce44SJohn Forte static char *
178*fcf3ce44SJohn Forte lockd_msg(int message)
179*fcf3ce44SJohn Forte {
180*fcf3ce44SJohn Forte 	switch (message) {
181*fcf3ce44SJohn Forte 	case ALIVE:		return "Alive";
182*fcf3ce44SJohn Forte 	case READ_LOCK:		return "ReadLock";
183*fcf3ce44SJohn Forte 	case WRITE_LOCK:	return "WriteLock";
184*fcf3ce44SJohn Forte 	case UNLOCK:		return "Unlock";
185*fcf3ce44SJohn Forte 	case GRANTED:		return "Granted";
186*fcf3ce44SJohn Forte 	default:		return lockd_type((cfglockd_t)message);
187*fcf3ce44SJohn Forte 	}
188*fcf3ce44SJohn Forte }
189*fcf3ce44SJohn Forte 
190*fcf3ce44SJohn Forte /*
191*fcf3ce44SJohn Forte  * The following is stolen from autod_nfs.c
192*fcf3ce44SJohn Forte  */
193*fcf3ce44SJohn Forte static void
194*fcf3ce44SJohn Forte getmyaddrs(struct ifconf *ifc)
195*fcf3ce44SJohn Forte {
196*fcf3ce44SJohn Forte 	int sock;
197*fcf3ce44SJohn Forte 	int numifs;
198*fcf3ce44SJohn Forte 	char *buf;
199*fcf3ce44SJohn Forte 	int family;
200*fcf3ce44SJohn Forte 
201*fcf3ce44SJohn Forte 	ifc->ifc_buf = NULL;
202*fcf3ce44SJohn Forte 	ifc->ifc_len = 0;
203*fcf3ce44SJohn Forte 
204*fcf3ce44SJohn Forte #ifdef AF_INET6
205*fcf3ce44SJohn Forte 	family = AF_INET6;
206*fcf3ce44SJohn Forte #else
207*fcf3ce44SJohn Forte 	family = AF_INET;
208*fcf3ce44SJohn Forte #endif
209*fcf3ce44SJohn Forte 	if ((sock = socket(family, SOCK_DGRAM, 0)) < 0) {
210*fcf3ce44SJohn Forte #ifdef DEBUG
211*fcf3ce44SJohn Forte 		perror("getmyaddrs(): socket");
212*fcf3ce44SJohn Forte #endif
213*fcf3ce44SJohn Forte 		return;
214*fcf3ce44SJohn Forte 	}
215*fcf3ce44SJohn Forte 
216*fcf3ce44SJohn Forte 	if (ioctl(sock, SIOCGIFNUM, (char *)&numifs) < 0) {
217*fcf3ce44SJohn Forte #ifdef DEBUG
218*fcf3ce44SJohn Forte 		perror("getmyaddrs(): SIOCGIFNUM");
219*fcf3ce44SJohn Forte #endif
220*fcf3ce44SJohn Forte 		numifs = MAXIFS;
221*fcf3ce44SJohn Forte 	}
222*fcf3ce44SJohn Forte 
223*fcf3ce44SJohn Forte 	buf = (char *)malloc(numifs * sizeof (struct ifreq));
224*fcf3ce44SJohn Forte 	if (buf == NULL) {
225*fcf3ce44SJohn Forte #ifdef DEBUG
226*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "getmyaddrs(): malloc failed\n");
227*fcf3ce44SJohn Forte #endif
228*fcf3ce44SJohn Forte 		(void) close(sock);
229*fcf3ce44SJohn Forte 		return;
230*fcf3ce44SJohn Forte 	}
231*fcf3ce44SJohn Forte 
232*fcf3ce44SJohn Forte 	ifc->ifc_buf = buf;
233*fcf3ce44SJohn Forte 	ifc->ifc_len = numifs * sizeof (struct ifreq);
234*fcf3ce44SJohn Forte 
235*fcf3ce44SJohn Forte 	if (ioctl(sock, SIOCGIFCONF, (char *)ifc) < 0) {
236*fcf3ce44SJohn Forte #ifdef DEBUG
237*fcf3ce44SJohn Forte 		perror("getmyaddrs(): SIOCGIFCONF");
238*fcf3ce44SJohn Forte #endif
239*fcf3ce44SJohn Forte 	}
240*fcf3ce44SJohn Forte 
241*fcf3ce44SJohn Forte 	(void) close(sock);
242*fcf3ce44SJohn Forte }
243*fcf3ce44SJohn Forte 
244*fcf3ce44SJohn Forte struct ifconf *ifc;
245*fcf3ce44SJohn Forte 
246*fcf3ce44SJohn Forte static int
247*fcf3ce44SJohn Forte cmp_addr(daemonaddr_t *a, daemonaddr_t *b)
248*fcf3ce44SJohn Forte {
249*fcf3ce44SJohn Forte 	int rc;
250*fcf3ce44SJohn Forte 	rc = memcmp(&(a->sin_addr), &(b->sin_addr), sizeof (a->sin_addr));
251*fcf3ce44SJohn Forte 	DPF((stderr, "compare %s %hu with", dp_addr(a), a->sin_port));
252*fcf3ce44SJohn Forte 	DPF((stderr, " %s %hu = %d\n", dp_addr(b), b->sin_port, rc));
253*fcf3ce44SJohn Forte 	return (rc);
254*fcf3ce44SJohn Forte }
255*fcf3ce44SJohn Forte 
256*fcf3ce44SJohn Forte static int
257*fcf3ce44SJohn Forte addr_is_holder(int32_t order)
258*fcf3ce44SJohn Forte {
259*fcf3ce44SJohn Forte 	return ((the_lock.nholders > 0) && the_lock.remote_daemon != NULL &&
260*fcf3ce44SJohn Forte 	    (order == the_lock.remote_daemon->order));
261*fcf3ce44SJohn Forte }
262*fcf3ce44SJohn Forte 
263*fcf3ce44SJohn Forte static int
264*fcf3ce44SJohn Forte islocalhost(daemonaddr_t *host)
265*fcf3ce44SJohn Forte {
266*fcf3ce44SJohn Forte 	int n;
267*fcf3ce44SJohn Forte 	struct sockaddr_in *s1, *s2;
268*fcf3ce44SJohn Forte 	struct ifreq *ifr;
269*fcf3ce44SJohn Forte 	int retval = 0;
270*fcf3ce44SJohn Forte 
271*fcf3ce44SJohn Forte 	ifr = ifc->ifc_req;
272*fcf3ce44SJohn Forte 	n = ifc->ifc_len / sizeof (struct ifreq);
273*fcf3ce44SJohn Forte 	s1 = host;
274*fcf3ce44SJohn Forte 	s2 = NULL;
275*fcf3ce44SJohn Forte 	for (; n > 0; n--, ifr++) {
276*fcf3ce44SJohn Forte 		if (ifr->ifr_addr.sa_family != AF_INET)
277*fcf3ce44SJohn Forte 			continue;
278*fcf3ce44SJohn Forte 
279*fcf3ce44SJohn Forte 		/* LINTED pointer alignment */
280*fcf3ce44SJohn Forte 		s2 = (struct sockaddr_in *)&ifr->ifr_addr;
281*fcf3ce44SJohn Forte 
282*fcf3ce44SJohn Forte 		if (memcmp((char *)&s2->sin_addr,
283*fcf3ce44SJohn Forte 			(char *)&s1->sin_addr, sizeof (s1->sin_addr)) == 0) {
284*fcf3ce44SJohn Forte 			retval = 1;
285*fcf3ce44SJohn Forte 			/* it's me */
286*fcf3ce44SJohn Forte 			break;
287*fcf3ce44SJohn Forte 		}
288*fcf3ce44SJohn Forte 	}
289*fcf3ce44SJohn Forte 	return (retval);
290*fcf3ce44SJohn Forte }
291*fcf3ce44SJohn Forte 
292*fcf3ce44SJohn Forte static void
293*fcf3ce44SJohn Forte send_lockmsg(int cmd, pid_t pid, daemonaddr_t *dp, uint8_t seq)
294*fcf3ce44SJohn Forte {
295*fcf3ce44SJohn Forte 	struct lock_msg message_buf;
296*fcf3ce44SJohn Forte 	int rc;
297*fcf3ce44SJohn Forte 
298*fcf3ce44SJohn Forte 	if (msgtrace && debugfile) {
299*fcf3ce44SJohn Forte 		time_t t = time(0);
300*fcf3ce44SJohn Forte 		(void) fprintf(debugfile, "%19.19s send %-9.9s to   %s\n",
301*fcf3ce44SJohn Forte 		    ctime(&t), lockd_msg(cmd), dp_addr(dp));
302*fcf3ce44SJohn Forte 	}
303*fcf3ce44SJohn Forte 	DPF((stderr, "send %d to %s port %hu\n", cmd,
304*fcf3ce44SJohn Forte 			dp_addr(dp), dp->sin_port));
305*fcf3ce44SJohn Forte 	message_buf.message = cmd;
306*fcf3ce44SJohn Forte 	message_buf.pid = pid;
307*fcf3ce44SJohn Forte 	message_buf.order = order;
308*fcf3ce44SJohn Forte 	message_buf.seq = seq;
309*fcf3ce44SJohn Forte 	do {
310*fcf3ce44SJohn Forte 		rc = sendto(lock_soc, &message_buf, sizeof (message_buf), 0,
311*fcf3ce44SJohn Forte 		    (struct sockaddr *)dp, sizeof (struct sockaddr));
312*fcf3ce44SJohn Forte 	} while (rc == -1 && errno == EINTR);
313*fcf3ce44SJohn Forte 	if (rc == -1)
314*fcf3ce44SJohn Forte 		spcs_log("cfglockd", NULL, "sendto rc -1 errno %d", errno);
315*fcf3ce44SJohn Forte }
316*fcf3ce44SJohn Forte 
317*fcf3ce44SJohn Forte /*
318*fcf3ce44SJohn Forte  * send an alive message to all configured daemons so that they can tell
319*fcf3ce44SJohn Forte  * us if they are holding a write lock.
320*fcf3ce44SJohn Forte  */
321*fcf3ce44SJohn Forte 
322*fcf3ce44SJohn Forte static void
323*fcf3ce44SJohn Forte send_aliveall()
324*fcf3ce44SJohn Forte {
325*fcf3ce44SJohn Forte 	struct lockdaemon *ldp;
326*fcf3ce44SJohn Forte 	int i;
327*fcf3ce44SJohn Forte 	for (i = 0, ldp = daemon_list; i < MAX_DAEMONS; i++, ldp++) {
328*fcf3ce44SJohn Forte 		if (ldp->inuse == 0)
329*fcf3ce44SJohn Forte 			break;
330*fcf3ce44SJohn Forte 		send_lockmsg(ALIVE, (pid_t)0, &(ldp->host), 0);
331*fcf3ce44SJohn Forte 	}
332*fcf3ce44SJohn Forte }
333*fcf3ce44SJohn Forte 
334*fcf3ce44SJohn Forte /* find the lock daemon structure for a give daemon address */
335*fcf3ce44SJohn Forte 
336*fcf3ce44SJohn Forte static struct lockdaemon *
337*fcf3ce44SJohn Forte find_lockdaemon(daemonaddr_t *d)
338*fcf3ce44SJohn Forte {
339*fcf3ce44SJohn Forte 	struct lockdaemon *ldp;
340*fcf3ce44SJohn Forte 	int i;
341*fcf3ce44SJohn Forte 	for (i = 0, ldp = daemon_list; i < MAX_DAEMONS; i++, ldp++) {
342*fcf3ce44SJohn Forte 		if (ldp->inuse == 0)
343*fcf3ce44SJohn Forte 			break;
344*fcf3ce44SJohn Forte 		if (cmp_addr(&(ldp->host), d) == 0)
345*fcf3ce44SJohn Forte 			return (ldp);
346*fcf3ce44SJohn Forte 	}
347*fcf3ce44SJohn Forte 	return (NULL);
348*fcf3ce44SJohn Forte }
349*fcf3ce44SJohn Forte 
350*fcf3ce44SJohn Forte /*
351*fcf3ce44SJohn Forte  * a messge has been received from daemon, note this and if the daemon
352*fcf3ce44SJohn Forte  * was previously dead  and we have the write lock tell it that we do.
353*fcf3ce44SJohn Forte  */
354*fcf3ce44SJohn Forte 
355*fcf3ce44SJohn Forte static void
356*fcf3ce44SJohn Forte daemon_alive(daemonaddr_t *daemon, int32_t order)
357*fcf3ce44SJohn Forte {
358*fcf3ce44SJohn Forte 	struct lockdaemon *ldp;
359*fcf3ce44SJohn Forte 	int i;
360*fcf3ce44SJohn Forte 
361*fcf3ce44SJohn Forte 	for (i = 0, ldp = daemon_list; i < MAX_DAEMONS; i++, ldp++) {
362*fcf3ce44SJohn Forte 		if (ldp->inuse == 0)
363*fcf3ce44SJohn Forte 			break;
364*fcf3ce44SJohn Forte 		if (cmp_addr(&(ldp->host), daemon) == 0) {
365*fcf3ce44SJohn Forte 			ldp->order = order;
366*fcf3ce44SJohn Forte 			ldp->timeout = ticker;
367*fcf3ce44SJohn Forte 			if (ldp->up == 0) {
368*fcf3ce44SJohn Forte 				spcs_log("cfglockd", NULL,
369*fcf3ce44SJohn Forte 				    "daemon restarted on %s\n",
370*fcf3ce44SJohn Forte 				    dp_addr(daemon));
371*fcf3ce44SJohn Forte 				DPF((stderr, "daemon restarted on %s\n",
372*fcf3ce44SJohn Forte 				    dp_addr(daemon)));
373*fcf3ce44SJohn Forte 				ldp->up = 1;
374*fcf3ce44SJohn Forte 				goto come_up;
375*fcf3ce44SJohn Forte 			}
376*fcf3ce44SJohn Forte 			return;
377*fcf3ce44SJohn Forte 		}
378*fcf3ce44SJohn Forte 	}
379*fcf3ce44SJohn Forte 	/* new daemon has announced itself */
380*fcf3ce44SJohn Forte 	if (i < MAX_DAEMONS) {
381*fcf3ce44SJohn Forte 		DPF((stderr, "new daemon on %s\n", dp_addr(daemon)));
382*fcf3ce44SJohn Forte 		spcs_log("cfglockd", NULL,
383*fcf3ce44SJohn Forte 		    "new daemon on %s\n", dp_addr(daemon));
384*fcf3ce44SJohn Forte 		ldp->host = *daemon;
385*fcf3ce44SJohn Forte 		ldp->inuse = 1;
386*fcf3ce44SJohn Forte 		ldp->timeout = ticker;
387*fcf3ce44SJohn Forte 		ldp->order = order;
388*fcf3ce44SJohn Forte 	} else {
389*fcf3ce44SJohn Forte 		/* problem, more daemons than expected */
390*fcf3ce44SJohn Forte 		i++;
391*fcf3ce44SJohn Forte 	}
392*fcf3ce44SJohn Forte come_up:
393*fcf3ce44SJohn Forte 	if (the_lock.type == LOCK_WRITE && the_lock.remote_daemon == NULL)
394*fcf3ce44SJohn Forte 		send_lockmsg(WRITE_LOCK, (pid_t)0, daemon, 0);
395*fcf3ce44SJohn Forte }
396*fcf3ce44SJohn Forte 
397*fcf3ce44SJohn Forte static void
398*fcf3ce44SJohn Forte delete_queue_entry(struct  lock_req *req)
399*fcf3ce44SJohn Forte {
400*fcf3ce44SJohn Forte 	int i;
401*fcf3ce44SJohn Forte 
402*fcf3ce44SJohn Forte 	for (i = (req - lock_queue); i++ < next_req; req++)
403*fcf3ce44SJohn Forte 		*req = *(req+1);
404*fcf3ce44SJohn Forte 	next_req--;
405*fcf3ce44SJohn Forte }
406*fcf3ce44SJohn Forte 
407*fcf3ce44SJohn Forte static void
408*fcf3ce44SJohn Forte take_lock(int ackmessage)
409*fcf3ce44SJohn Forte {
410*fcf3ce44SJohn Forte 	send_lockmsg(ackmessage, (pid_t)0, &lock_wanted.remote, 0);
411*fcf3ce44SJohn Forte 	delete_queue_entry(lock_queue);
412*fcf3ce44SJohn Forte }
413*fcf3ce44SJohn Forte 
414*fcf3ce44SJohn Forte static void
415*fcf3ce44SJohn Forte check_for_write_lock()
416*fcf3ce44SJohn Forte {
417*fcf3ce44SJohn Forte 	struct lockdaemon *ldp;
418*fcf3ce44SJohn Forte 	int i;
419*fcf3ce44SJohn Forte 	int	wait = 0;
420*fcf3ce44SJohn Forte 
421*fcf3ce44SJohn Forte 	DPF((stderr, "check for lock\n"));
422*fcf3ce44SJohn Forte 	if (lock_wanted.state != STATE_ASKED)
423*fcf3ce44SJohn Forte 		return;
424*fcf3ce44SJohn Forte 	for (i = 0, ldp = daemon_list; i < MAX_DAEMONS; i++, ldp++) {
425*fcf3ce44SJohn Forte 		if (ldp->inuse == 0)
426*fcf3ce44SJohn Forte 			break;
427*fcf3ce44SJohn Forte 		if (ldp->up && ldp->state != STATE_OKAYED) {
428*fcf3ce44SJohn Forte 			wait = 1;
429*fcf3ce44SJohn Forte 			break;
430*fcf3ce44SJohn Forte 		}
431*fcf3ce44SJohn Forte 	}
432*fcf3ce44SJohn Forte 	if (wait == 0 && lock_wanted.type == LOCK_WRITE) {
433*fcf3ce44SJohn Forte 		the_lock.type = LOCK_WRITE;
434*fcf3ce44SJohn Forte 		the_lock.holding_pid[0] = lock_wanted.pid;
435*fcf3ce44SJohn Forte 		the_lock.nholders = 1;
436*fcf3ce44SJohn Forte 		the_lock.state = STATE_CLEAR;
437*fcf3ce44SJohn Forte 		take_lock(LOCK_LOCKED);
438*fcf3ce44SJohn Forte 	}
439*fcf3ce44SJohn Forte }
440*fcf3ce44SJohn Forte 
441*fcf3ce44SJohn Forte static void
442*fcf3ce44SJohn Forte lock_granted(daemonaddr_t *da)
443*fcf3ce44SJohn Forte {
444*fcf3ce44SJohn Forte 	struct lockdaemon *ldp;
445*fcf3ce44SJohn Forte 
446*fcf3ce44SJohn Forte 	if ((ldp = find_lockdaemon(da)) != NULL) {
447*fcf3ce44SJohn Forte 		/* if we already own the lock, throw the msg away */
448*fcf3ce44SJohn Forte 		if (the_lock.remote_daemon == NULL &&
449*fcf3ce44SJohn Forte 		    the_lock.type == LOCK_WRITE) {
450*fcf3ce44SJohn Forte 			return;
451*fcf3ce44SJohn Forte 		}
452*fcf3ce44SJohn Forte 
453*fcf3ce44SJohn Forte 		/*
454*fcf3ce44SJohn Forte 		 * If the current lock isn't a write lock and we're not
455*fcf3ce44SJohn Forte 		 * asking for one
456*fcf3ce44SJohn Forte 		 * -OR-
457*fcf3ce44SJohn Forte 		 * The current lock is a write lock and it's not owned by us
458*fcf3ce44SJohn Forte 		 * -THEN-
459*fcf3ce44SJohn Forte 		 * send back an unlocked message.
460*fcf3ce44SJohn Forte 		 */
461*fcf3ce44SJohn Forte 		if ((the_lock.type != LOCK_WRITE &&
462*fcf3ce44SJohn Forte 		    the_lock.state != STATE_ASKED) ||
463*fcf3ce44SJohn Forte 		    (the_lock.type == LOCK_WRITE &&
464*fcf3ce44SJohn Forte 		    the_lock.remote_daemon != NULL)) {
465*fcf3ce44SJohn Forte 			send_lockmsg(UNLOCK, (pid_t)0, &(ldp->host), 0);
466*fcf3ce44SJohn Forte 			return;
467*fcf3ce44SJohn Forte 		}
468*fcf3ce44SJohn Forte 		ldp->state = STATE_OKAYED;
469*fcf3ce44SJohn Forte 	}
470*fcf3ce44SJohn Forte 	check_for_write_lock();
471*fcf3ce44SJohn Forte }
472*fcf3ce44SJohn Forte 
473*fcf3ce44SJohn Forte static int
474*fcf3ce44SJohn Forte try_lock()
475*fcf3ce44SJohn Forte {
476*fcf3ce44SJohn Forte 	struct lockdaemon *ldp;
477*fcf3ce44SJohn Forte 	int i;
478*fcf3ce44SJohn Forte 
479*fcf3ce44SJohn Forte 	switch (the_lock.type) {
480*fcf3ce44SJohn Forte 	case LOCK_READ:
481*fcf3ce44SJohn Forte 		if (lock_wanted.type == LOCK_READ) {
482*fcf3ce44SJohn Forte 			i = the_lock.nholders++;
483*fcf3ce44SJohn Forte 			the_lock.holding_pid[i] = lock_wanted.pid;
484*fcf3ce44SJohn Forte 			the_lock.state = STATE_CLEAR;
485*fcf3ce44SJohn Forte 			DPF((stderr, "increment read lockers to %d\n",
486*fcf3ce44SJohn Forte 			    the_lock.nholders));
487*fcf3ce44SJohn Forte 			take_lock(LOCK_LOCKED);
488*fcf3ce44SJohn Forte 			break;
489*fcf3ce44SJohn Forte 		}
490*fcf3ce44SJohn Forte 		/* write lock has to wait */
491*fcf3ce44SJohn Forte 		break;
492*fcf3ce44SJohn Forte 	case LOCK_WRITE:
493*fcf3ce44SJohn Forte 		/* lock has to wait until write lock is cleared */
494*fcf3ce44SJohn Forte 		break;
495*fcf3ce44SJohn Forte 	case LOCK_NOTLOCKED:
496*fcf3ce44SJohn Forte 		if (lock_wanted.type == LOCK_READ) {
497*fcf3ce44SJohn Forte 			DPF((stderr, "local locker, 1 lock holder\n"));
498*fcf3ce44SJohn Forte 			the_lock.holding_pid[0] = lock_wanted.pid;
499*fcf3ce44SJohn Forte 			the_lock.nholders = 1;
500*fcf3ce44SJohn Forte 			the_lock.type = LOCK_READ;
501*fcf3ce44SJohn Forte 			the_lock.state = STATE_CLEAR;
502*fcf3ce44SJohn Forte 			the_lock.remote_daemon = NULL;
503*fcf3ce44SJohn Forte 			take_lock(LOCK_LOCKED);
504*fcf3ce44SJohn Forte 			return (1);
505*fcf3ce44SJohn Forte 		}
506*fcf3ce44SJohn Forte 		if (islocalhost(&lock_wanted.remote)) {
507*fcf3ce44SJohn Forte 			DPF((stderr, "local locker, take write lock\n"));
508*fcf3ce44SJohn Forte 			/* tell everyone I'm locking */
509*fcf3ce44SJohn Forte 			if (lock_wanted.state != STATE_ASKED) {
510*fcf3ce44SJohn Forte 				for (i = 0, ldp = daemon_list; i < MAX_DAEMONS;
511*fcf3ce44SJohn Forte 				    i++, ldp++) {
512*fcf3ce44SJohn Forte 					if (ldp->inuse == 0)
513*fcf3ce44SJohn Forte 						break;
514*fcf3ce44SJohn Forte 					ldp->state = STATE_ASKED;
515*fcf3ce44SJohn Forte 					send_lockmsg(WRITE_LOCK, (pid_t)0,
516*fcf3ce44SJohn Forte 					    &(ldp->host), 0);
517*fcf3ce44SJohn Forte 				}
518*fcf3ce44SJohn Forte 			}
519*fcf3ce44SJohn Forte 			lock_wanted.state = STATE_ASKED;
520*fcf3ce44SJohn Forte 			check_for_write_lock();
521*fcf3ce44SJohn Forte 			the_lock.remote_daemon = NULL;
522*fcf3ce44SJohn Forte 			the_lock.state = STATE_ASKED;
523*fcf3ce44SJohn Forte 			return (0);
524*fcf3ce44SJohn Forte 		} else {
525*fcf3ce44SJohn Forte 			DPF((stderr, "remote locker, take write lock\n"));
526*fcf3ce44SJohn Forte 			the_lock.type = LOCK_WRITE;
527*fcf3ce44SJohn Forte 			the_lock.holder = lock_wanted.remote;
528*fcf3ce44SJohn Forte 			the_lock.nholders = 1;
529*fcf3ce44SJohn Forte 			the_lock.remote_daemon =
530*fcf3ce44SJohn Forte 			    find_lockdaemon(&the_lock.holder);
531*fcf3ce44SJohn Forte 			the_lock.state = STATE_CLEAR;
532*fcf3ce44SJohn Forte 			/* okay to remote */
533*fcf3ce44SJohn Forte 			take_lock(GRANTED);
534*fcf3ce44SJohn Forte 		}
535*fcf3ce44SJohn Forte 		break;
536*fcf3ce44SJohn Forte 	default:
537*fcf3ce44SJohn Forte 		DPF((stderr, "weird lock type held - %d\n", the_lock.type));
538*fcf3ce44SJohn Forte 		the_lock.type = LOCK_NOTLOCKED;
539*fcf3ce44SJohn Forte 		break;
540*fcf3ce44SJohn Forte 	}
541*fcf3ce44SJohn Forte 	return (0);
542*fcf3ce44SJohn Forte }
543*fcf3ce44SJohn Forte 
544*fcf3ce44SJohn Forte static void
545*fcf3ce44SJohn Forte process_queue()
546*fcf3ce44SJohn Forte {
547*fcf3ce44SJohn Forte 	if (next_req < 1)
548*fcf3ce44SJohn Forte 		return;		/* no locks queued */
549*fcf3ce44SJohn Forte 	while (try_lock())
550*fcf3ce44SJohn Forte 		;
551*fcf3ce44SJohn Forte }
552*fcf3ce44SJohn Forte 
553*fcf3ce44SJohn Forte static int
554*fcf3ce44SJohn Forte lock_sort(const void *a, const void *b)
555*fcf3ce44SJohn Forte {
556*fcf3ce44SJohn Forte 	struct lock_req *left = (struct lock_req *)a;
557*fcf3ce44SJohn Forte 	struct lock_req *right = (struct lock_req *)b;
558*fcf3ce44SJohn Forte 
559*fcf3ce44SJohn Forte 	return (left->order - right->order);
560*fcf3ce44SJohn Forte }
561*fcf3ce44SJohn Forte 
562*fcf3ce44SJohn Forte static void
563*fcf3ce44SJohn Forte queue_lock(cfglockd_t type, struct lock_msg *msg, daemonaddr_t *addr)
564*fcf3ce44SJohn Forte {
565*fcf3ce44SJohn Forte 	int	i;
566*fcf3ce44SJohn Forte 	struct lock_req *lrp;
567*fcf3ce44SJohn Forte 	struct lockdaemon *ldp;
568*fcf3ce44SJohn Forte 
569*fcf3ce44SJohn Forte 	/* first check if new lock matches current lock */
570*fcf3ce44SJohn Forte 	if (the_lock.type == type && addr_is_holder(msg->order)) {
571*fcf3ce44SJohn Forte 		/* remote daemon missed locked message */
572*fcf3ce44SJohn Forte 		send_lockmsg(GRANTED, (pid_t)0, addr, msg->seq);
573*fcf3ce44SJohn Forte 		return;
574*fcf3ce44SJohn Forte 	}
575*fcf3ce44SJohn Forte 
576*fcf3ce44SJohn Forte 	/* next search queue to check for duplicate */
577*fcf3ce44SJohn Forte 	for (i = 0, lrp = lock_queue; i++ < next_req; lrp++) {
578*fcf3ce44SJohn Forte 		if (lrp->type == type && lrp->pid == msg->pid &&
579*fcf3ce44SJohn Forte 		    cmp_addr(addr, &(lrp->remote)) == 0)
580*fcf3ce44SJohn Forte 			return;
581*fcf3ce44SJohn Forte 
582*fcf3ce44SJohn Forte 	}
583*fcf3ce44SJohn Forte 
584*fcf3ce44SJohn Forte 	/*
585*fcf3ce44SJohn Forte 	 * It's a new lock request.  Are we in the middle of
586*fcf3ce44SJohn Forte 	 * obtaining one for ourselves?
587*fcf3ce44SJohn Forte 	 */
588*fcf3ce44SJohn Forte 
589*fcf3ce44SJohn Forte 	if (the_lock.type == LOCK_NOTLOCKED && the_lock.state == STATE_ASKED) {
590*fcf3ce44SJohn Forte 		/* did a higher priority request just come in? */
591*fcf3ce44SJohn Forte 		if (msg->order < order) {
592*fcf3ce44SJohn Forte 			/* requeue our request */
593*fcf3ce44SJohn Forte 			the_lock.state = STATE_CLEAR;
594*fcf3ce44SJohn Forte 			lock_wanted.state = STATE_CLEAR;
595*fcf3ce44SJohn Forte 
596*fcf3ce44SJohn Forte 			/* let the other lockds know */
597*fcf3ce44SJohn Forte 			for (i = 0, ldp = daemon_list; i < MAX_DAEMONS;
598*fcf3ce44SJohn Forte 			    i++, ldp++) {
599*fcf3ce44SJohn Forte 				if (ldp->inuse == 0)
600*fcf3ce44SJohn Forte 					break;
601*fcf3ce44SJohn Forte 				if (ldp->up && ldp->state == STATE_OKAYED) {
602*fcf3ce44SJohn Forte 					send_lockmsg(UNLOCK, (pid_t)0,
603*fcf3ce44SJohn Forte 					    &(ldp->host), 0);
604*fcf3ce44SJohn Forte 				}
605*fcf3ce44SJohn Forte 			}
606*fcf3ce44SJohn Forte 		}
607*fcf3ce44SJohn Forte 	}
608*fcf3ce44SJohn Forte 
609*fcf3ce44SJohn Forte 
610*fcf3ce44SJohn Forte 	lrp = lock_queue;
611*fcf3ce44SJohn Forte 	lrp += (next_req++);
612*fcf3ce44SJohn Forte 	lrp->type = type;
613*fcf3ce44SJohn Forte 	lrp->pid = msg->pid;
614*fcf3ce44SJohn Forte 	lrp->state = STATE_CLEAR;
615*fcf3ce44SJohn Forte 	lrp->order = msg->order;
616*fcf3ce44SJohn Forte 	if (addr) {
617*fcf3ce44SJohn Forte 		lrp->remote = *addr;
618*fcf3ce44SJohn Forte 	}
619*fcf3ce44SJohn Forte 
620*fcf3ce44SJohn Forte 	if (next_req > 1)
621*fcf3ce44SJohn Forte 		qsort(lock_queue, next_req, sizeof (lock_queue[0]), lock_sort);
622*fcf3ce44SJohn Forte 
623*fcf3ce44SJohn Forte 	if (the_lock.type != LOCK_WRITE)
624*fcf3ce44SJohn Forte 		process_queue();
625*fcf3ce44SJohn Forte }
626*fcf3ce44SJohn Forte 
627*fcf3ce44SJohn Forte static void
628*fcf3ce44SJohn Forte lock_stat()
629*fcf3ce44SJohn Forte {
630*fcf3ce44SJohn Forte 	char *lt = "Unknown";
631*fcf3ce44SJohn Forte 	struct lockdaemon *ldp;
632*fcf3ce44SJohn Forte 	int i;
633*fcf3ce44SJohn Forte 
634*fcf3ce44SJohn Forte 	spcs_log("cfglockd", NULL,
635*fcf3ce44SJohn Forte 	    "%s, Lock daemon built %s **********", program, __DATE__);
636*fcf3ce44SJohn Forte 	switch (the_lock.type) {
637*fcf3ce44SJohn Forte 	case LOCK_NOTLOCKED:
638*fcf3ce44SJohn Forte 		lt = "not locked";
639*fcf3ce44SJohn Forte 		break;
640*fcf3ce44SJohn Forte 	case LOCK_READ:
641*fcf3ce44SJohn Forte 		lt = "read locked";
642*fcf3ce44SJohn Forte 		break;
643*fcf3ce44SJohn Forte 	case LOCK_WRITE:
644*fcf3ce44SJohn Forte 		lt = "write locked";
645*fcf3ce44SJohn Forte 		break;
646*fcf3ce44SJohn Forte 	}
647*fcf3ce44SJohn Forte 	spcs_log("cfglockd", NULL, "Lock is %s (%d)", lt, the_lock.type);
648*fcf3ce44SJohn Forte 	spcs_log("cfglockd", NULL, "There are %d holders of the lock",
649*fcf3ce44SJohn Forte 	    the_lock.nholders);
650*fcf3ce44SJohn Forte 	if (the_lock.nholders > 0) {
651*fcf3ce44SJohn Forte 		for (i = 0; i < the_lock.nholders; i++)
652*fcf3ce44SJohn Forte 			spcs_log("cfglockd", NULL, "holding_pid[%d] = %6d", i,
653*fcf3ce44SJohn Forte 			    the_lock.holding_pid[i]);
654*fcf3ce44SJohn Forte 	}
655*fcf3ce44SJohn Forte 	spcs_log("cfglockd", NULL, "holder daemon was %s port %hu, remote %x",
656*fcf3ce44SJohn Forte 	    dp_addr(&the_lock.holder), the_lock.holder.sin_port,
657*fcf3ce44SJohn Forte 	    the_lock.remote_daemon);
658*fcf3ce44SJohn Forte 	spcs_log("cfglockd", NULL, "Lock queue, %d requests", next_req);
659*fcf3ce44SJohn Forte 	for (i = 0; i < next_req; i++) {
660*fcf3ce44SJohn Forte 		spcs_log("cfglockd", NULL, "request %d type %d order %d", i,
661*fcf3ce44SJohn Forte 		    lock_queue[i].type, lock_queue[i].order);
662*fcf3ce44SJohn Forte 		spcs_log("cfglockd", NULL, "  client %s port %hu, pid %d",
663*fcf3ce44SJohn Forte 		    dp_addr(&lock_queue[i].remote),
664*fcf3ce44SJohn Forte 		    lock_queue[i].remote.sin_port, lock_queue[i].pid);
665*fcf3ce44SJohn Forte 	}
666*fcf3ce44SJohn Forte 	spcs_log("cfglockd", NULL, "Daemon list");
667*fcf3ce44SJohn Forte 
668*fcf3ce44SJohn Forte 	for (i = 0, ldp = daemon_list; i < MAX_DAEMONS; i++, ldp++) {
669*fcf3ce44SJohn Forte 		if (ldp->inuse == 0)
670*fcf3ce44SJohn Forte 			break;
671*fcf3ce44SJohn Forte 		spcs_log("cfglockd", NULL, "daemon %d, %s port %hu", i,
672*fcf3ce44SJohn Forte 		    dp_addr(&ldp->host), ldp->host.sin_port);
673*fcf3ce44SJohn Forte 		spcs_log("cfglockd", NULL,
674*fcf3ce44SJohn Forte 		    "  up %d timeout %ld missed %d state %d\n", ldp->up,
675*fcf3ce44SJohn Forte 		    ldp->timeout, ticker - ldp->timeout, ldp->state);
676*fcf3ce44SJohn Forte 	}
677*fcf3ce44SJohn Forte }
678*fcf3ce44SJohn Forte 
679*fcf3ce44SJohn Forte static int
680*fcf3ce44SJohn Forte is_duplicate(cfglockd_t type, pid_t pid, uint8_t seq)
681*fcf3ce44SJohn Forte {
682*fcf3ce44SJohn Forte 	struct unlock_s *bufp;
683*fcf3ce44SJohn Forte 	int i;
684*fcf3ce44SJohn Forte 
685*fcf3ce44SJohn Forte 	if (!pid) {
686*fcf3ce44SJohn Forte 		return (0);
687*fcf3ce44SJohn Forte 	}
688*fcf3ce44SJohn Forte 
689*fcf3ce44SJohn Forte 	for (i = 0, bufp = unlock_buf; bufp->pid && i < MAX_UNLOCK;
690*fcf3ce44SJohn Forte 	    i++, bufp++) {
691*fcf3ce44SJohn Forte 		if (bufp->pid == pid && bufp->seq == seq) {
692*fcf3ce44SJohn Forte 			/* throw message away */
693*fcf3ce44SJohn Forte #ifdef DEBUG
694*fcf3ce44SJohn Forte 			spcs_log("cfglockd", NULL,
695*fcf3ce44SJohn Forte 			    "duplicate '%d' request received from %d",
696*fcf3ce44SJohn Forte 			    type, pid);
697*fcf3ce44SJohn Forte #endif
698*fcf3ce44SJohn Forte 			return (1);
699*fcf3ce44SJohn Forte 		}
700*fcf3ce44SJohn Forte 	}
701*fcf3ce44SJohn Forte 
702*fcf3ce44SJohn Forte 	/* add it to the list */
703*fcf3ce44SJohn Forte 	bcopy(unlock_buf, &unlock_buf[ 1 ],
704*fcf3ce44SJohn Forte 	    sizeof (unlock_buf) - sizeof (struct unlock_s));
705*fcf3ce44SJohn Forte 	(*unlock_buf).pid = pid;
706*fcf3ce44SJohn Forte 	(*unlock_buf).seq = seq;
707*fcf3ce44SJohn Forte 
708*fcf3ce44SJohn Forte 	return (0);
709*fcf3ce44SJohn Forte }
710*fcf3ce44SJohn Forte 
711*fcf3ce44SJohn Forte static void
712*fcf3ce44SJohn Forte local_lock(cfglockd_t type, struct lock_msg *msg, daemonaddr_t *client)
713*fcf3ce44SJohn Forte {
714*fcf3ce44SJohn Forte 	if (is_duplicate(type, msg->pid, msg->seq)) {
715*fcf3ce44SJohn Forte 		if (the_lock.remote_daemon == NULL &&
716*fcf3ce44SJohn Forte 		    (the_lock.type == LOCK_WRITE ||
717*fcf3ce44SJohn Forte 		    the_lock.type == LOCK_READ) &&
718*fcf3ce44SJohn Forte 		    the_lock.holding_pid[0] == msg->pid) {
719*fcf3ce44SJohn Forte 			send_lockmsg(LOCK_LOCKED, (pid_t)0, client, msg->seq);
720*fcf3ce44SJohn Forte 		}
721*fcf3ce44SJohn Forte 	} else {
722*fcf3ce44SJohn Forte 		queue_lock(type, msg, client);
723*fcf3ce44SJohn Forte 	}
724*fcf3ce44SJohn Forte }
725*fcf3ce44SJohn Forte 
726*fcf3ce44SJohn Forte static void
727*fcf3ce44SJohn Forte remote_lock(struct sockaddr_in *remote, struct lock_msg *msg)
728*fcf3ce44SJohn Forte {
729*fcf3ce44SJohn Forte 	/* make sure remote knows we are alive */
730*fcf3ce44SJohn Forte 	send_lockmsg(ALIVE, (pid_t)0, remote, 0);
731*fcf3ce44SJohn Forte 
732*fcf3ce44SJohn Forte 	/* clear out pid as it is meaningless on this node */
733*fcf3ce44SJohn Forte 	msg->pid = (pid_t)0;
734*fcf3ce44SJohn Forte 
735*fcf3ce44SJohn Forte 	queue_lock(LOCK_WRITE, msg, (daemonaddr_t *)remote);
736*fcf3ce44SJohn Forte }
737*fcf3ce44SJohn Forte 
738*fcf3ce44SJohn Forte static void
739*fcf3ce44SJohn Forte unqueue_lock(daemonaddr_t *d, pid_t pid)
740*fcf3ce44SJohn Forte {
741*fcf3ce44SJohn Forte 	int	i;
742*fcf3ce44SJohn Forte 	struct lock_req *lrp, *xrp;
743*fcf3ce44SJohn Forte 	int diff;
744*fcf3ce44SJohn Forte 
745*fcf3ce44SJohn Forte 	/* search queue to delete ungranted locks */
746*fcf3ce44SJohn Forte 	for (i = 0, xrp = lrp = lock_queue; i++ < next_req; lrp++) {
747*fcf3ce44SJohn Forte 		*xrp = *lrp;
748*fcf3ce44SJohn Forte 		diff = 0;
749*fcf3ce44SJohn Forte 		if (pid != (pid_t)0 && lrp->pid != pid)
750*fcf3ce44SJohn Forte 			diff = 1;
751*fcf3ce44SJohn Forte 		if (d != NULL && cmp_addr(d, &(lrp->remote)) != 0)
752*fcf3ce44SJohn Forte 			diff = 1;
753*fcf3ce44SJohn Forte 		if (!diff)
754*fcf3ce44SJohn Forte 			continue;
755*fcf3ce44SJohn Forte 
756*fcf3ce44SJohn Forte 		xrp++;
757*fcf3ce44SJohn Forte 	}
758*fcf3ce44SJohn Forte 	next_req = xrp - lock_queue;
759*fcf3ce44SJohn Forte }
760*fcf3ce44SJohn Forte 
761*fcf3ce44SJohn Forte static void
762*fcf3ce44SJohn Forte xxunlock()
763*fcf3ce44SJohn Forte {
764*fcf3ce44SJohn Forte 	DPF((stderr, "** UNLOCK **\n"));
765*fcf3ce44SJohn Forte 	the_lock.remote_daemon = NULL;
766*fcf3ce44SJohn Forte 	the_lock.type = LOCK_NOTLOCKED;
767*fcf3ce44SJohn Forte 	the_lock.nholders = 0;
768*fcf3ce44SJohn Forte 	the_lock.state = STATE_CLEAR;
769*fcf3ce44SJohn Forte 	process_queue();
770*fcf3ce44SJohn Forte }
771*fcf3ce44SJohn Forte 
772*fcf3ce44SJohn Forte 
773*fcf3ce44SJohn Forte static void
774*fcf3ce44SJohn Forte local_unlock(pid_t pid, uint8_t seq, int method)
775*fcf3ce44SJohn Forte {
776*fcf3ce44SJohn Forte 	struct lockdaemon *ldp;
777*fcf3ce44SJohn Forte 	int i;
778*fcf3ce44SJohn Forte 
779*fcf3ce44SJohn Forte 	if (method == NORMAL_UNLOCK && is_duplicate(LOCK_NOTLOCKED, pid, seq)) {
780*fcf3ce44SJohn Forte 		return;
781*fcf3ce44SJohn Forte 	}
782*fcf3ce44SJohn Forte 
783*fcf3ce44SJohn Forte 	if (the_lock.type == LOCK_READ) {
784*fcf3ce44SJohn Forte 		/* delete reference to pid of reading process */
785*fcf3ce44SJohn Forte 		for (i = 0; i < the_lock.nholders; i++) {
786*fcf3ce44SJohn Forte 			if (the_lock.holding_pid[i] == pid) {
787*fcf3ce44SJohn Forte 				DPF((stderr, "decrement lockers from %d\n",
788*fcf3ce44SJohn Forte 				    the_lock.nholders));
789*fcf3ce44SJohn Forte 				--the_lock.nholders;
790*fcf3ce44SJohn Forte 				break;
791*fcf3ce44SJohn Forte 			}
792*fcf3ce44SJohn Forte 		}
793*fcf3ce44SJohn Forte 		for (; i < the_lock.nholders; i++) {
794*fcf3ce44SJohn Forte 			the_lock.holding_pid[i] = the_lock.holding_pid[i+1];
795*fcf3ce44SJohn Forte 		}
796*fcf3ce44SJohn Forte 		if (the_lock.nholders > 0)
797*fcf3ce44SJohn Forte 			return;
798*fcf3ce44SJohn Forte 	} else {
799*fcf3ce44SJohn Forte 		/* LOCK_WRITE */
800*fcf3ce44SJohn Forte 		if (pid != the_lock.holding_pid[0])
801*fcf3ce44SJohn Forte 			return;
802*fcf3ce44SJohn Forte 		the_lock.holding_pid[0] = (pid_t)0;
803*fcf3ce44SJohn Forte 		for (i = 0, ldp = daemon_list; i < MAX_DAEMONS; i++, ldp++) {
804*fcf3ce44SJohn Forte 			if (ldp->inuse == 0)
805*fcf3ce44SJohn Forte 				break;
806*fcf3ce44SJohn Forte 			if (ldp->up)
807*fcf3ce44SJohn Forte 				send_lockmsg(UNLOCK, (pid_t)0, &(ldp->host), 0);
808*fcf3ce44SJohn Forte 		}
809*fcf3ce44SJohn Forte 	}
810*fcf3ce44SJohn Forte 	xxunlock();
811*fcf3ce44SJohn Forte }
812*fcf3ce44SJohn Forte 
813*fcf3ce44SJohn Forte static void
814*fcf3ce44SJohn Forte remote_unlock(int32_t order, daemonaddr_t *d)
815*fcf3ce44SJohn Forte {
816*fcf3ce44SJohn Forte 	int	i;
817*fcf3ce44SJohn Forte 	struct lock_req *lrp;
818*fcf3ce44SJohn Forte 
819*fcf3ce44SJohn Forte 	DPF((stderr, "remote unlock from %s ", dp_addr(d)));
820*fcf3ce44SJohn Forte 	DPF((stderr, "when %s holds lock\n", dp_addr(&the_lock.holder)));
821*fcf3ce44SJohn Forte 
822*fcf3ce44SJohn Forte 	/* search queue to check for ungranted lock */
823*fcf3ce44SJohn Forte 	for (i = 0, lrp = lock_queue; i++ < next_req; lrp++) {
824*fcf3ce44SJohn Forte 		if (lrp->type == LOCK_WRITE &&
825*fcf3ce44SJohn Forte 		    cmp_addr(d, &(lrp->remote)) == 0) {
826*fcf3ce44SJohn Forte 			delete_queue_entry(lrp);
827*fcf3ce44SJohn Forte 			return;
828*fcf3ce44SJohn Forte 		}
829*fcf3ce44SJohn Forte 
830*fcf3ce44SJohn Forte 	}
831*fcf3ce44SJohn Forte 	if (addr_is_holder(order)) {
832*fcf3ce44SJohn Forte 		xxunlock();
833*fcf3ce44SJohn Forte 	}
834*fcf3ce44SJohn Forte }
835*fcf3ce44SJohn Forte 
836*fcf3ce44SJohn Forte static void
837*fcf3ce44SJohn Forte lockedby(daemonaddr_t *d, uint8_t seq)
838*fcf3ce44SJohn Forte {
839*fcf3ce44SJohn Forte 	DPF((stderr, "lockby enquiry from %s ", dp_addr(d)));
840*fcf3ce44SJohn Forte 	switch (the_lock.type) {
841*fcf3ce44SJohn Forte 	case LOCK_NOTLOCKED:
842*fcf3ce44SJohn Forte 		send_lockmsg(LOCK_NOTLOCKED, (pid_t)0, d, seq);
843*fcf3ce44SJohn Forte 		break;
844*fcf3ce44SJohn Forte 	case LOCK_READ:
845*fcf3ce44SJohn Forte 		send_lockmsg(LOCK_READ, the_lock.holding_pid[0], d, seq);
846*fcf3ce44SJohn Forte 		break;
847*fcf3ce44SJohn Forte 	case LOCK_WRITE:
848*fcf3ce44SJohn Forte 		send_lockmsg(LOCK_WRITE, the_lock.holding_pid[0], d, seq);
849*fcf3ce44SJohn Forte 		break;
850*fcf3ce44SJohn Forte 	}
851*fcf3ce44SJohn Forte }
852*fcf3ce44SJohn Forte 
853*fcf3ce44SJohn Forte /* ARGSUSED */
854*fcf3ce44SJohn Forte static void
855*fcf3ce44SJohn Forte keepalive(int signo)
856*fcf3ce44SJohn Forte {
857*fcf3ce44SJohn Forte 	int i;
858*fcf3ce44SJohn Forte 	struct lock_req *locker;
859*fcf3ce44SJohn Forte 	struct lockdaemon *ldp;
860*fcf3ce44SJohn Forte 
861*fcf3ce44SJohn Forte 	DPF((stderr, "keepalive...\n"));
862*fcf3ce44SJohn Forte 	ticker++;
863*fcf3ce44SJohn Forte 
864*fcf3ce44SJohn Forte 	/*
865*fcf3ce44SJohn Forte 	 * tell any other daemon that has a lock request in our queue that
866*fcf3ce44SJohn Forte 	 * this daemon is still alive.
867*fcf3ce44SJohn Forte 	 */
868*fcf3ce44SJohn Forte 
869*fcf3ce44SJohn Forte 	for (i = 0, locker = lock_queue; i < next_req; i++, locker++) {
870*fcf3ce44SJohn Forte 		if (locker->pid == 0)	/* remote lock request */
871*fcf3ce44SJohn Forte 			send_lockmsg(ALIVE, (pid_t)0, &(locker->remote), 0);
872*fcf3ce44SJohn Forte 	}
873*fcf3ce44SJohn Forte 
874*fcf3ce44SJohn Forte 	/*
875*fcf3ce44SJohn Forte 	 * if a remote daemon holds the lock, check it is still alive and
876*fcf3ce44SJohn Forte 	 * if the remote daemon is sent it a grant message in case the
877*fcf3ce44SJohn Forte 	 * remote daemon missed our original grant.
878*fcf3ce44SJohn Forte 	 */
879*fcf3ce44SJohn Forte 
880*fcf3ce44SJohn Forte 	if (the_lock.remote_daemon) {
881*fcf3ce44SJohn Forte 		if (lockdaemon_dead(the_lock.remote_daemon)) {
882*fcf3ce44SJohn Forte 			DPF((stderr, "lock owner died\n"));
883*fcf3ce44SJohn Forte 			the_lock.remote_daemon->up = 0;
884*fcf3ce44SJohn Forte 			xxunlock();
885*fcf3ce44SJohn Forte 		} else {
886*fcf3ce44SJohn Forte 			send_lockmsg(GRANTED, (pid_t)0, &the_lock.holder, 0);
887*fcf3ce44SJohn Forte 		}
888*fcf3ce44SJohn Forte 	}
889*fcf3ce44SJohn Forte 
890*fcf3ce44SJohn Forte 	/*
891*fcf3ce44SJohn Forte 	 * check for response from daemons preventing this daemon
892*fcf3ce44SJohn Forte 	 * from taking a write lock by not sending a grant message.
893*fcf3ce44SJohn Forte 	 * if the remote daemon is alive send another lock request,
894*fcf3ce44SJohn Forte 	 * otherwise mark it as dead.
895*fcf3ce44SJohn Forte 	 * send alive message to any live remote daemons if this
896*fcf3ce44SJohn Forte 	 * daemon has the write lock.
897*fcf3ce44SJohn Forte 	 */
898*fcf3ce44SJohn Forte 	if (lstate) {
899*fcf3ce44SJohn Forte 		(void) printf("\nlock: %s\n", lockd_type(the_lock.type));
900*fcf3ce44SJohn Forte 		(void) printf("    no. holders: %d\n", the_lock.nholders);
901*fcf3ce44SJohn Forte 		(void) printf("    hold addr  : %s\n", the_lock.remote_daemon?
902*fcf3ce44SJohn Forte 		    dp_addr(the_lock.remote_daemon): "0.0.0.0");
903*fcf3ce44SJohn Forte 		(void) printf("    holding pid:");
904*fcf3ce44SJohn Forte 		for (i = 0; i < the_lock.nholders; i++) {
905*fcf3ce44SJohn Forte 			(void) printf(" %ld", the_lock.holding_pid[ i ]);
906*fcf3ce44SJohn Forte 		}
907*fcf3ce44SJohn Forte 		(void) printf("\n");
908*fcf3ce44SJohn Forte 	}
909*fcf3ce44SJohn Forte 	for (i = 0, ldp = daemon_list; i < MAX_DAEMONS; i++, ldp++) {
910*fcf3ce44SJohn Forte 		if (ldp->inuse == 0)
911*fcf3ce44SJohn Forte 			break;
912*fcf3ce44SJohn Forte 
913*fcf3ce44SJohn Forte 		if (lstate) {
914*fcf3ce44SJohn Forte 			(void) printf("%-15.15s ", dp_addr(&ldp->host));
915*fcf3ce44SJohn Forte 			(void) printf("%-4.4s ", ldp->up? "up" : "down");
916*fcf3ce44SJohn Forte 			(void) printf("%5ld ", ldp->timeout);
917*fcf3ce44SJohn Forte 			(void) printf("%-10.10s ", lockd_state(ldp->state));
918*fcf3ce44SJohn Forte 			(void) printf("%6d\n", ldp->order);
919*fcf3ce44SJohn Forte 		}
920*fcf3ce44SJohn Forte 
921*fcf3ce44SJohn Forte 		if (ldp->state == STATE_ASKED) {
922*fcf3ce44SJohn Forte 			if (lockdaemon_dead(ldp)) {
923*fcf3ce44SJohn Forte 				ldp->up = 0;
924*fcf3ce44SJohn Forte 				ldp->state = STATE_CLEAR;
925*fcf3ce44SJohn Forte 				continue;
926*fcf3ce44SJohn Forte 			}
927*fcf3ce44SJohn Forte 			send_lockmsg(WRITE_LOCK, (pid_t)0, &(ldp->host), 0);
928*fcf3ce44SJohn Forte 			continue;
929*fcf3ce44SJohn Forte 		}
930*fcf3ce44SJohn Forte 		if (the_lock.type == LOCK_WRITE &&
931*fcf3ce44SJohn Forte 		    the_lock.remote_daemon == NULL)
932*fcf3ce44SJohn Forte 			send_lockmsg(ALIVE, (pid_t)0, &(ldp->host), 0);
933*fcf3ce44SJohn Forte 	}
934*fcf3ce44SJohn Forte }
935*fcf3ce44SJohn Forte 
936*fcf3ce44SJohn Forte static void
937*fcf3ce44SJohn Forte dispatch(struct lock_msg *mp, daemonaddr_t *host)
938*fcf3ce44SJohn Forte {
939*fcf3ce44SJohn Forte 	int message = mp->message;
940*fcf3ce44SJohn Forte 	int localhost;
941*fcf3ce44SJohn Forte 
942*fcf3ce44SJohn Forte 	localhost = islocalhost(host);
943*fcf3ce44SJohn Forte 	if (msgtrace && debugfile) {
944*fcf3ce44SJohn Forte 		time_t t = time(0);
945*fcf3ce44SJohn Forte 		if (localhost) {
946*fcf3ce44SJohn Forte 			(void) fprintf(debugfile,
947*fcf3ce44SJohn Forte 			    "%19.19s recv %-9.9s from %s (%ld)\n", ctime(&t),
948*fcf3ce44SJohn Forte 			    lockd_msg(message), dp_addr(host), mp->pid);
949*fcf3ce44SJohn Forte 		} else {
950*fcf3ce44SJohn Forte 			(void) fprintf(debugfile,
951*fcf3ce44SJohn Forte 			    "%19.19s recv %-9.9s from %s order %d (%ld)\n",
952*fcf3ce44SJohn Forte 			    ctime(&t), lockd_msg(message), dp_addr(host),
953*fcf3ce44SJohn Forte 			    mp->order, mp->pid);
954*fcf3ce44SJohn Forte 		}
955*fcf3ce44SJohn Forte 	}
956*fcf3ce44SJohn Forte 	DPF((stderr, "received message %d\n", message));
957*fcf3ce44SJohn Forte 	DPF((stderr, "from %s port %hu\n", dp_addr(host), host->sin_port));
958*fcf3ce44SJohn Forte 	if (!localhost)
959*fcf3ce44SJohn Forte 		daemon_alive(host, mp->order);
960*fcf3ce44SJohn Forte 	else
961*fcf3ce44SJohn Forte 		mp->order = order;
962*fcf3ce44SJohn Forte 	switch (message) {
963*fcf3ce44SJohn Forte 	case ALIVE:
964*fcf3ce44SJohn Forte 		DPF((stderr, "received ALIVE %s\n", dp_addr(host)));
965*fcf3ce44SJohn Forte 		/* do nothing, general "not localhost" code above does this */
966*fcf3ce44SJohn Forte 		break;
967*fcf3ce44SJohn Forte 	case UNLOCK:
968*fcf3ce44SJohn Forte 		DPF((stderr, "received UNLOCK\n"));
969*fcf3ce44SJohn Forte 		remote_unlock(mp->order, host);
970*fcf3ce44SJohn Forte 		break;
971*fcf3ce44SJohn Forte 	case GRANTED:
972*fcf3ce44SJohn Forte 		DPF((stderr, "received GRANTED\n"));
973*fcf3ce44SJohn Forte 		lock_granted(host);
974*fcf3ce44SJohn Forte 		break;
975*fcf3ce44SJohn Forte 	case WRITE_LOCK:
976*fcf3ce44SJohn Forte 		DPF((stderr, "received WRITE_LOCK\n"));
977*fcf3ce44SJohn Forte 		assert(!localhost);
978*fcf3ce44SJohn Forte 		remote_lock(host, mp);
979*fcf3ce44SJohn Forte 		break;
980*fcf3ce44SJohn Forte 	case READ_LOCK:
981*fcf3ce44SJohn Forte 	case LOCK_READ:
982*fcf3ce44SJohn Forte 		DPF((stderr, "received READ_LOCK\n"));
983*fcf3ce44SJohn Forte 		assert(localhost);
984*fcf3ce44SJohn Forte 		local_lock(LOCK_READ, mp, host);
985*fcf3ce44SJohn Forte 		break;
986*fcf3ce44SJohn Forte 	case LOCK_WRITE:
987*fcf3ce44SJohn Forte 		DPF((stderr, "received LOCK_WRITE\n"));
988*fcf3ce44SJohn Forte 		assert(localhost);
989*fcf3ce44SJohn Forte 		local_lock(LOCK_WRITE, mp, host);
990*fcf3ce44SJohn Forte 		break;
991*fcf3ce44SJohn Forte 	case LOCK_NOTLOCKED:
992*fcf3ce44SJohn Forte 		DPF((stderr, "received LOCK_NOTLOCKED\n"));
993*fcf3ce44SJohn Forte 		send_lockmsg(LOCK_ACK, (pid_t)0, host, mp->seq);
994*fcf3ce44SJohn Forte 		if (the_lock.type != LOCK_NOTLOCKED) {
995*fcf3ce44SJohn Forte 			local_unlock(mp->pid, mp->seq, NORMAL_UNLOCK);
996*fcf3ce44SJohn Forte 		}
997*fcf3ce44SJohn Forte 		break;
998*fcf3ce44SJohn Forte 	case LOCK_LOCKEDBY:
999*fcf3ce44SJohn Forte 		lockedby(host, mp->seq);
1000*fcf3ce44SJohn Forte 		break;
1001*fcf3ce44SJohn Forte 	case LOCK_STAT:
1002*fcf3ce44SJohn Forte 		lock_stat();
1003*fcf3ce44SJohn Forte 		break;
1004*fcf3ce44SJohn Forte 	case LOCK_ACK:
1005*fcf3ce44SJohn Forte 		/* throw message away -- this is an error to receive */
1006*fcf3ce44SJohn Forte 		break;
1007*fcf3ce44SJohn Forte 	}
1008*fcf3ce44SJohn Forte }
1009*fcf3ce44SJohn Forte 
1010*fcf3ce44SJohn Forte /*
1011*fcf3ce44SJohn Forte  * unqueue any locks asked for by pid and unlock any locks held by pid.
1012*fcf3ce44SJohn Forte  */
1013*fcf3ce44SJohn Forte 
1014*fcf3ce44SJohn Forte static void
1015*fcf3ce44SJohn Forte purge_pid(pid_t pid)
1016*fcf3ce44SJohn Forte {
1017*fcf3ce44SJohn Forte 	DPF((stderr, "purge locks for %ld\n", pid));
1018*fcf3ce44SJohn Forte 	unqueue_lock(NULL, pid);
1019*fcf3ce44SJohn Forte 	if (the_lock.type != LOCK_NOTLOCKED)
1020*fcf3ce44SJohn Forte 		local_unlock(pid, 0, FORCE_UNLOCK);
1021*fcf3ce44SJohn Forte }
1022*fcf3ce44SJohn Forte 
1023*fcf3ce44SJohn Forte /*
1024*fcf3ce44SJohn Forte  * Check for exit or exec of client processes.
1025*fcf3ce44SJohn Forte  * The lock protecting the processes pid in the lockfile will
1026*fcf3ce44SJohn Forte  * be removed by the kernel when a client exits or execs.
1027*fcf3ce44SJohn Forte  */
1028*fcf3ce44SJohn Forte 
1029*fcf3ce44SJohn Forte static void
1030*fcf3ce44SJohn Forte check_for_dead()
1031*fcf3ce44SJohn Forte {
1032*fcf3ce44SJohn Forte 	int i, x;
1033*fcf3ce44SJohn Forte 	pid_t pid;
1034*fcf3ce44SJohn Forte 
1035*fcf3ce44SJohn Forte 	for (i = 0; (x = cfg_filelock(i, 0)) != CFG_LF_EOF; i++) {
1036*fcf3ce44SJohn Forte 		if (x == CFG_LF_AGAIN)
1037*fcf3ce44SJohn Forte 			continue; /* can't take lock, must be still alive */
1038*fcf3ce44SJohn Forte 		cfg_readpid(i, &pid);
1039*fcf3ce44SJohn Forte 		cfg_writepid(i, (pid_t)0);
1040*fcf3ce44SJohn Forte 		cfg_fileunlock(i);
1041*fcf3ce44SJohn Forte 		if (pid != (pid_t)0)
1042*fcf3ce44SJohn Forte 			purge_pid(pid);
1043*fcf3ce44SJohn Forte 	}
1044*fcf3ce44SJohn Forte }
1045*fcf3ce44SJohn Forte 
1046*fcf3ce44SJohn Forte static void
1047*fcf3ce44SJohn Forte build_daemon_list(char *cf_file, int exe)
1048*fcf3ce44SJohn Forte {
1049*fcf3ce44SJohn Forte 	FILE *fp;
1050*fcf3ce44SJohn Forte 	char	host[1024];
1051*fcf3ce44SJohn Forte 	int	port;
1052*fcf3ce44SJohn Forte 	int	i;
1053*fcf3ce44SJohn Forte 	struct	hostent *hp;
1054*fcf3ce44SJohn Forte 	struct lockdaemon *ldp;
1055*fcf3ce44SJohn Forte 
1056*fcf3ce44SJohn Forte 	if ((hp = gethostbyname("localhost")) == NULL) {
1057*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "%s: Can't find hostent for %s\n",
1058*fcf3ce44SJohn Forte 		    program, "localhost");
1059*fcf3ce44SJohn Forte 		spcs_log("cfglockd", NULL, "couldn't find localhost");
1060*fcf3ce44SJohn Forte 		exit(1);
1061*fcf3ce44SJohn Forte 	}
1062*fcf3ce44SJohn Forte 
1063*fcf3ce44SJohn Forte 	(void) memcpy(&(localhost.sin_addr.s_addr), *(hp->h_addr_list),
1064*fcf3ce44SJohn Forte 			sizeof (localhost.sin_addr));
1065*fcf3ce44SJohn Forte 	if (cf_file == NULL) {
1066*fcf3ce44SJohn Forte 		(void) endhostent();
1067*fcf3ce44SJohn Forte 		return;
1068*fcf3ce44SJohn Forte 	}
1069*fcf3ce44SJohn Forte 	if (exe) {
1070*fcf3ce44SJohn Forte 		if ((fp = popen(cf_file, "r")) == NULL) {
1071*fcf3ce44SJohn Forte 			perror(cf_file);
1072*fcf3ce44SJohn Forte 			(void) fprintf(stderr,
1073*fcf3ce44SJohn Forte 			    "%s: Can't open config program\n", program);
1074*fcf3ce44SJohn Forte 			spcs_log("cfglockd", NULL, "couldn't read config");
1075*fcf3ce44SJohn Forte 			exit(1);
1076*fcf3ce44SJohn Forte 		}
1077*fcf3ce44SJohn Forte 	} else {
1078*fcf3ce44SJohn Forte 		if ((fp = fopen(cf_file, "r")) == NULL) {
1079*fcf3ce44SJohn Forte 			perror(cf_file);
1080*fcf3ce44SJohn Forte 			(void) fprintf(stderr, "%s: Can't open config file\n",
1081*fcf3ce44SJohn Forte 			    program);
1082*fcf3ce44SJohn Forte 			spcs_log("cfglockd", NULL, "couldn't read config");
1083*fcf3ce44SJohn Forte 			exit(1);
1084*fcf3ce44SJohn Forte 		}
1085*fcf3ce44SJohn Forte 	}
1086*fcf3ce44SJohn Forte 	ldp = daemon_list;
1087*fcf3ce44SJohn Forte 	while ((i = fscanf(fp, "%s %d\n", host, &port)) != EOF) {
1088*fcf3ce44SJohn Forte 		if (host[0] == '#')	/* line starting with # are comments */
1089*fcf3ce44SJohn Forte 			continue;
1090*fcf3ce44SJohn Forte 		if (i == 1) {
1091*fcf3ce44SJohn Forte 			port = lock_port;
1092*fcf3ce44SJohn Forte 		} else {
1093*fcf3ce44SJohn Forte 			if (strcmp(host, "localhost") == 0) {
1094*fcf3ce44SJohn Forte 				lock_port = port;
1095*fcf3ce44SJohn Forte 				continue;
1096*fcf3ce44SJohn Forte 			}
1097*fcf3ce44SJohn Forte 		}
1098*fcf3ce44SJohn Forte 
1099*fcf3ce44SJohn Forte 		if ((hp = gethostbyname(host)) == NULL) {
1100*fcf3ce44SJohn Forte 			(void) fprintf(stderr,
1101*fcf3ce44SJohn Forte 			    "%s: Can't find hostent for %s\n", program, host);
1102*fcf3ce44SJohn Forte 			continue;
1103*fcf3ce44SJohn Forte 		}
1104*fcf3ce44SJohn Forte 
1105*fcf3ce44SJohn Forte 		(void) memcpy(&(ldp->host.sin_addr.s_addr), *(hp->h_addr_list),
1106*fcf3ce44SJohn Forte 		    sizeof (ldp->host.sin_addr));
1107*fcf3ce44SJohn Forte 		DPF((stderr, "daemon: %s\t%s\n",
1108*fcf3ce44SJohn Forte 				inet_ntoa(ldp->host.sin_addr), hp->h_name));
1109*fcf3ce44SJohn Forte 		if (islocalhost(&(ldp->host))) {
1110*fcf3ce44SJohn Forte 			DPF((stderr, "is an alias for this host, skipping\n"));
1111*fcf3ce44SJohn Forte 			continue;
1112*fcf3ce44SJohn Forte 		}
1113*fcf3ce44SJohn Forte 		ldp->host.sin_port = htons((short)port);
1114*fcf3ce44SJohn Forte 		ldp->host.sin_family = hp->h_addrtype;
1115*fcf3ce44SJohn Forte 		ldp->inuse = 1;
1116*fcf3ce44SJohn Forte 		ldp->up = 1;
1117*fcf3ce44SJohn Forte 		ldp++;
1118*fcf3ce44SJohn Forte 	}
1119*fcf3ce44SJohn Forte 	if (exe)
1120*fcf3ce44SJohn Forte 		(void) pclose(fp);
1121*fcf3ce44SJohn Forte 	else
1122*fcf3ce44SJohn Forte 		(void) fclose(fp);
1123*fcf3ce44SJohn Forte 	(void) endhostent();
1124*fcf3ce44SJohn Forte }
1125*fcf3ce44SJohn Forte 
1126*fcf3ce44SJohn Forte static void
1127*fcf3ce44SJohn Forte usage()
1128*fcf3ce44SJohn Forte {
1129*fcf3ce44SJohn Forte 	(void) fprintf(stderr,
1130*fcf3ce44SJohn Forte 	    gettext("usage: %s [-d] [-f file]|[-e program]\n"), program);
1131*fcf3ce44SJohn Forte 	exit(1);
1132*fcf3ce44SJohn Forte }
1133*fcf3ce44SJohn Forte 
1134*fcf3ce44SJohn Forte static void
1135*fcf3ce44SJohn Forte unexpected(int sig)
1136*fcf3ce44SJohn Forte {
1137*fcf3ce44SJohn Forte 	spcs_log("cfglockd", NULL, "pid %d unexpected signal %d, ignoring",
1138*fcf3ce44SJohn Forte 	    getpid(), sig);
1139*fcf3ce44SJohn Forte }
1140*fcf3ce44SJohn Forte 
1141*fcf3ce44SJohn Forte static void
1142*fcf3ce44SJohn Forte term(int sig)
1143*fcf3ce44SJohn Forte {
1144*fcf3ce44SJohn Forte 	(void) unlink(CFG_PIDFILE);
1145*fcf3ce44SJohn Forte 	spcs_log("cfglockd", NULL, "pid %d terminate on signal %d", getpid(),
1146*fcf3ce44SJohn Forte 	    sig);
1147*fcf3ce44SJohn Forte 	exit(0);
1148*fcf3ce44SJohn Forte }
1149*fcf3ce44SJohn Forte 
1150*fcf3ce44SJohn Forte static void
1151*fcf3ce44SJohn Forte init(int argc, char *argv[])
1152*fcf3ce44SJohn Forte {
1153*fcf3ce44SJohn Forte #if defined(_SunOS_5_6) || defined(_SunOS_5_7) || defined(_SunOS_5_8)
1154*fcf3ce44SJohn Forte 	struct rlimit rl;
1155*fcf3ce44SJohn Forte #endif
1156*fcf3ce44SJohn Forte 	int	c, i, x;
1157*fcf3ce44SJohn Forte 	int	rc;
1158*fcf3ce44SJohn Forte 	char	*cp = NULL;
1159*fcf3ce44SJohn Forte 	struct	itimerval	tv;
1160*fcf3ce44SJohn Forte 	struct	timeval		tp;
1161*fcf3ce44SJohn Forte 	socklen_t len = sizeof (thishost);
1162*fcf3ce44SJohn Forte 	int	exe = 0;
1163*fcf3ce44SJohn Forte 	pid_t	pid;
1164*fcf3ce44SJohn Forte 	FILE	*fp;
1165*fcf3ce44SJohn Forte 
1166*fcf3ce44SJohn Forte 	lstate = (getenv("LOCKD_STATE") != NULL);
1167*fcf3ce44SJohn Forte 	msgtrace = (getenv("LOCKD_MSG") != NULL);
1168*fcf3ce44SJohn Forte 
1169*fcf3ce44SJohn Forte 	/*
1170*fcf3ce44SJohn Forte 	 * Fork off a child that becomes the daemon.
1171*fcf3ce44SJohn Forte 	 */
1172*fcf3ce44SJohn Forte 
1173*fcf3ce44SJohn Forte #ifndef TTY_MESSAGES
1174*fcf3ce44SJohn Forte 	if ((rc = fork()) > 0)
1175*fcf3ce44SJohn Forte 		exit(0);
1176*fcf3ce44SJohn Forte 	else if (rc < 0) {
1177*fcf3ce44SJohn Forte 		spcs_log("cfglockd", NULL, "can't fork %d", errno);
1178*fcf3ce44SJohn Forte 		(void) fprintf(stderr, gettext("dscfglockd: cannot fork: %s\n"),
1179*fcf3ce44SJohn Forte 		    strerror(errno));
1180*fcf3ce44SJohn Forte 		exit(1);
1181*fcf3ce44SJohn Forte 	}
1182*fcf3ce44SJohn Forte #endif
1183*fcf3ce44SJohn Forte 
1184*fcf3ce44SJohn Forte 	/*
1185*fcf3ce44SJohn Forte 	 * In child - become daemon.
1186*fcf3ce44SJohn Forte 	 */
1187*fcf3ce44SJohn Forte 
1188*fcf3ce44SJohn Forte #if !defined(_SunOS_5_6) && !defined(_SunOS_5_7) && !defined(_SunOS_5_8)
1189*fcf3ce44SJohn Forte 	/* use closefrom(3C) from PSARC/2000/193 when possible */
1190*fcf3ce44SJohn Forte 	closefrom(CLOSE_FD);
1191*fcf3ce44SJohn Forte #else
1192*fcf3ce44SJohn Forte 	(void) getrlimit(RLIMIT_NOFILE, &rl);
1193*fcf3ce44SJohn Forte 	for (i = CLOSE_FD; i < rl.rlim_max; i++)
1194*fcf3ce44SJohn Forte 		(void) close(i);
1195*fcf3ce44SJohn Forte #endif
1196*fcf3ce44SJohn Forte 
1197*fcf3ce44SJohn Forte #ifdef DEBUG
1198*fcf3ce44SJohn Forte #ifndef	TTY_MESSAGES
1199*fcf3ce44SJohn Forte 	(void) open("/dev/console", O_WRONLY|O_APPEND);
1200*fcf3ce44SJohn Forte 	(void) dup(0);
1201*fcf3ce44SJohn Forte 	(void) dup(0);
1202*fcf3ce44SJohn Forte #endif
1203*fcf3ce44SJohn Forte #endif
1204*fcf3ce44SJohn Forte 	(void) close(0);
1205*fcf3ce44SJohn Forte 
1206*fcf3ce44SJohn Forte 	if (msgtrace || lstate) {
1207*fcf3ce44SJohn Forte 		debugfile = fopen("/var/tmp/dscfglockd.out", "a");
1208*fcf3ce44SJohn Forte 		if (debugfile) {
1209*fcf3ce44SJohn Forte 			time_t t = time(0);
1210*fcf3ce44SJohn Forte 			setbuf(debugfile, (char *)0);
1211*fcf3ce44SJohn Forte 			(void) fprintf(debugfile, "%19.19s dscfglockd start\n",
1212*fcf3ce44SJohn Forte 			    ctime(&t));
1213*fcf3ce44SJohn Forte 		}
1214*fcf3ce44SJohn Forte 	}
1215*fcf3ce44SJohn Forte 
1216*fcf3ce44SJohn Forte 	(void) setpgrp();
1217*fcf3ce44SJohn Forte 	spcs_log("cfglockd", NULL, "new lock daemon, pid %d", getpid());
1218*fcf3ce44SJohn Forte 
1219*fcf3ce44SJohn Forte 	/*
1220*fcf3ce44SJohn Forte 	 * Catch as unexpected all signals apart from SIGTERM.
1221*fcf3ce44SJohn Forte 	 */
1222*fcf3ce44SJohn Forte 
1223*fcf3ce44SJohn Forte 	for (i = 1; i < _sys_nsig; i++)
1224*fcf3ce44SJohn Forte 		(void) sigset(i, unexpected);
1225*fcf3ce44SJohn Forte 	(void) sigset(SIGTERM, term);
1226*fcf3ce44SJohn Forte 
1227*fcf3ce44SJohn Forte 	for (i = 0; (c = getopt(argc, argv, "df:e:")) != EOF; i++) {
1228*fcf3ce44SJohn Forte 		switch (c) {
1229*fcf3ce44SJohn Forte 		case 'd':
1230*fcf3ce44SJohn Forte 			debug = 1;
1231*fcf3ce44SJohn Forte 			break;
1232*fcf3ce44SJohn Forte 		case 'e':
1233*fcf3ce44SJohn Forte 			exe = 1;
1234*fcf3ce44SJohn Forte 			if (cp) {
1235*fcf3ce44SJohn Forte 				usage();
1236*fcf3ce44SJohn Forte 			}
1237*fcf3ce44SJohn Forte 			cp = optarg;
1238*fcf3ce44SJohn Forte 			break;
1239*fcf3ce44SJohn Forte 		case 'f':
1240*fcf3ce44SJohn Forte 			if (cp) {
1241*fcf3ce44SJohn Forte 				usage();
1242*fcf3ce44SJohn Forte 			}
1243*fcf3ce44SJohn Forte 			cp = optarg;
1244*fcf3ce44SJohn Forte 			break;
1245*fcf3ce44SJohn Forte 		default:
1246*fcf3ce44SJohn Forte 			usage();
1247*fcf3ce44SJohn Forte 			break;
1248*fcf3ce44SJohn Forte 		}
1249*fcf3ce44SJohn Forte 	}
1250*fcf3ce44SJohn Forte 
1251*fcf3ce44SJohn Forte 	ifc = (struct ifconf *)malloc(sizeof (struct ifconf));
1252*fcf3ce44SJohn Forte 	if (ifc == NULL) {
1253*fcf3ce44SJohn Forte 		perror(CFG_PIDFILE);
1254*fcf3ce44SJohn Forte 		DPF((stderr, "Can't open pid file\n"));
1255*fcf3ce44SJohn Forte 		exit(1);
1256*fcf3ce44SJohn Forte 	}
1257*fcf3ce44SJohn Forte 	(void) memset((char *)ifc, 0, sizeof (struct ifconf));
1258*fcf3ce44SJohn Forte 	getmyaddrs(ifc);
1259*fcf3ce44SJohn Forte 
1260*fcf3ce44SJohn Forte 	/*
1261*fcf3ce44SJohn Forte 	 * if (lockdaemonalive()) {
1262*fcf3ce44SJohn Forte 	 *	(void) fprintf(stderr, "%s: %s\n", program,
1263*fcf3ce44SJohn Forte 	 *		gettext("There is already a live lockdaemon"));
1264*fcf3ce44SJohn Forte 	 *	exit(1);
1265*fcf3ce44SJohn Forte 	 * }
1266*fcf3ce44SJohn Forte 	 */
1267*fcf3ce44SJohn Forte 	if ((fp = fopen(CFG_PIDFILE, "w")) == NULL) {
1268*fcf3ce44SJohn Forte 		perror(CFG_PIDFILE);
1269*fcf3ce44SJohn Forte 		DPF((stderr, "Can't open pid file\n"));
1270*fcf3ce44SJohn Forte 		exit(1);
1271*fcf3ce44SJohn Forte 	}
1272*fcf3ce44SJohn Forte 	(void) fprintf(fp, "%ld\n", getpid());
1273*fcf3ce44SJohn Forte 	(void) fclose(fp);
1274*fcf3ce44SJohn Forte 
1275*fcf3ce44SJohn Forte 	/* order should be set to node number within cluster */
1276*fcf3ce44SJohn Forte 	order = cfg_iscluster();
1277*fcf3ce44SJohn Forte 	cfg_lfinit();
1278*fcf3ce44SJohn Forte 
1279*fcf3ce44SJohn Forte 	if (!order) {
1280*fcf3ce44SJohn Forte 		(void) gettimeofday(&tp, NULL);
1281*fcf3ce44SJohn Forte 		srand48(tp.tv_usec);
1282*fcf3ce44SJohn Forte 		order = lrand48();
1283*fcf3ce44SJohn Forte 		if (debugfile) {
1284*fcf3ce44SJohn Forte 			(void) fprintf(debugfile, "WARNING: order number "
1285*fcf3ce44SJohn Forte 			    "is 0 -- changing randomly to %d\n", order);
1286*fcf3ce44SJohn Forte 		}
1287*fcf3ce44SJohn Forte 	}
1288*fcf3ce44SJohn Forte 	c = 0;
1289*fcf3ce44SJohn Forte 	for (i = 0; (x = cfg_filelock(i, 0)) != CFG_LF_EOF; i++) {
1290*fcf3ce44SJohn Forte 		if (x == CFG_LF_AGAIN) {
1291*fcf3ce44SJohn Forte 			cfg_readpid(i, &pid);
1292*fcf3ce44SJohn Forte 			if (c++ == 0)
1293*fcf3ce44SJohn Forte 				spcs_log("cfglockd", NULL,
1294*fcf3ce44SJohn Forte 				    "init .dscfg.lck slot %d pid %d locked",
1295*fcf3ce44SJohn Forte 				    i, pid);
1296*fcf3ce44SJohn Forte 			DPF((stderr, "client process %ld still alive\n", pid));
1297*fcf3ce44SJohn Forte 			continue; /* can't take lock, must be still alive */
1298*fcf3ce44SJohn Forte 		}
1299*fcf3ce44SJohn Forte 		cfg_writepid(i, 0);
1300*fcf3ce44SJohn Forte 		cfg_fileunlock(i);
1301*fcf3ce44SJohn Forte 	}
1302*fcf3ce44SJohn Forte 
1303*fcf3ce44SJohn Forte 	tv.it_interval.tv_sec = TIMEOUT_SECS;
1304*fcf3ce44SJohn Forte 	tv.it_interval.tv_usec = 0;
1305*fcf3ce44SJohn Forte 	tv.it_value = tv.it_interval;
1306*fcf3ce44SJohn Forte 
1307*fcf3ce44SJohn Forte 	bzero(unlock_buf, sizeof (unlock_buf));
1308*fcf3ce44SJohn Forte 	next_q = 0;
1309*fcf3ce44SJohn Forte 	build_daemon_list(cp, exe);
1310*fcf3ce44SJohn Forte 	if ((lock_soc = socket(pf_inet, SOCK_DGRAM, 0)) < 0) {
1311*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "%s: %s\n", program,
1312*fcf3ce44SJohn Forte 		    gettext("failed to create socket"));
1313*fcf3ce44SJohn Forte 		perror("socket");
1314*fcf3ce44SJohn Forte 		spcs_log("cfglockd", NULL, "couldn't create socket");
1315*fcf3ce44SJohn Forte 		exit(1);
1316*fcf3ce44SJohn Forte 	}
1317*fcf3ce44SJohn Forte 	thishost.sin_family = AF_INET;
1318*fcf3ce44SJohn Forte 	thishost.sin_addr.s_addr = INADDR_ANY;
1319*fcf3ce44SJohn Forte 	thishost.sin_port = htons(lock_port);
1320*fcf3ce44SJohn Forte 	rc = bind(lock_soc, (struct sockaddr *)&thishost, sizeof (thishost));
1321*fcf3ce44SJohn Forte 	if (rc < 0) {
1322*fcf3ce44SJohn Forte 		perror("bind");
1323*fcf3ce44SJohn Forte 		spcs_log("cfglockd", NULL, "couldn't bind");
1324*fcf3ce44SJohn Forte 		exit(1);
1325*fcf3ce44SJohn Forte 	}
1326*fcf3ce44SJohn Forte 	if (getsockname(lock_soc, (struct sockaddr *)&thishost, &len) < 0)
1327*fcf3ce44SJohn Forte 		perror("getsockname");
1328*fcf3ce44SJohn Forte 	send_aliveall();
1329*fcf3ce44SJohn Forte 	sigset(SIGALRM, keepalive);
1330*fcf3ce44SJohn Forte 	(void) setitimer(ITIMER_REAL, &tv, NULL);
1331*fcf3ce44SJohn Forte 	/*
1332*fcf3ce44SJohn Forte 	 * wait 2 time outs before allowing a lock to find if someone else
1333*fcf3ce44SJohn Forte 	 * currently has the lock.
1334*fcf3ce44SJohn Forte 	 */
1335*fcf3ce44SJohn Forte }
1336*fcf3ce44SJohn Forte 
1337*fcf3ce44SJohn Forte #ifdef lint
1338*fcf3ce44SJohn Forte int
1339*fcf3ce44SJohn Forte lintmain(int argc, char *argv[])
1340*fcf3ce44SJohn Forte #else
1341*fcf3ce44SJohn Forte int
1342*fcf3ce44SJohn Forte main(int argc, char *argv[])
1343*fcf3ce44SJohn Forte #endif
1344*fcf3ce44SJohn Forte {
1345*fcf3ce44SJohn Forte 	struct lock_msg message_buf;
1346*fcf3ce44SJohn Forte 	daemonaddr_t from;
1347*fcf3ce44SJohn Forte 	int addrlen;
1348*fcf3ce44SJohn Forte 	int rc;
1349*fcf3ce44SJohn Forte 	int x = 1;		/* kludge to stop warnings from compiler */
1350*fcf3ce44SJohn Forte 
1351*fcf3ce44SJohn Forte 	init(argc, argv);
1352*fcf3ce44SJohn Forte 	CRIT_BEGIN();
1353*fcf3ce44SJohn Forte 	while (x) {
1354*fcf3ce44SJohn Forte 		CRIT_END();
1355*fcf3ce44SJohn Forte 		addrlen = sizeof (from);
1356*fcf3ce44SJohn Forte 		DPF((stderr, "begin recvfrom\n"));
1357*fcf3ce44SJohn Forte 		rc = recvfrom(lock_soc, &message_buf, sizeof (message_buf),
1358*fcf3ce44SJohn Forte 		    0, (struct sockaddr *)&from, &addrlen);
1359*fcf3ce44SJohn Forte 		DPF((stderr, "end recvfrom rc = %d\n", rc));
1360*fcf3ce44SJohn Forte 		CRIT_BEGIN();
1361*fcf3ce44SJohn Forte 		if (rc == sizeof (message_buf))
1362*fcf3ce44SJohn Forte 			dispatch(&message_buf, &from);
1363*fcf3ce44SJohn Forte 		else
1364*fcf3ce44SJohn Forte 			check_for_write_lock();
1365*fcf3ce44SJohn Forte 
1366*fcf3ce44SJohn Forte 		/* if we own the lock, check to see if the process died */
1367*fcf3ce44SJohn Forte 		if (the_lock.type != LOCK_NOTLOCKED &&
1368*fcf3ce44SJohn Forte 		    the_lock.remote_daemon == NULL)
1369*fcf3ce44SJohn Forte 			check_for_dead();
1370*fcf3ce44SJohn Forte 	}
1371*fcf3ce44SJohn Forte 	CRIT_END();
1372*fcf3ce44SJohn Forte 	return (0);
1373*fcf3ce44SJohn Forte }
1374