xref: /titanic_41/usr/src/lib/libdscfg/common/cfg_lockdmsg.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 <netdb.h>
33*fcf3ce44SJohn Forte #include <stdio.h>
34*fcf3ce44SJohn Forte #include <string.h>
35*fcf3ce44SJohn Forte #include <unistd.h>
36*fcf3ce44SJohn Forte #include <stdlib.h>
37*fcf3ce44SJohn Forte #include <errno.h>
38*fcf3ce44SJohn Forte 
39*fcf3ce44SJohn Forte #include "cfg_lockd.h"
40*fcf3ce44SJohn Forte 
41*fcf3ce44SJohn Forte static daemonaddr_t	clientaddr;
42*fcf3ce44SJohn Forte static daemonaddr_t	server;
43*fcf3ce44SJohn Forte 
44*fcf3ce44SJohn Forte static unsigned short	server_port = CFG_SERVER_PORT;
45*fcf3ce44SJohn Forte static int	lock_soc = 0;
46*fcf3ce44SJohn Forte static int	pf_inet = AF_INET;
47*fcf3ce44SJohn Forte static int	locked;
48*fcf3ce44SJohn Forte static int	initdone;
49*fcf3ce44SJohn Forte static int	initresult;
50*fcf3ce44SJohn Forte static pid_t	socket_pid;
51*fcf3ce44SJohn Forte 
52*fcf3ce44SJohn Forte static void	cfg_lockd_reinit();
53*fcf3ce44SJohn Forte 
54*fcf3ce44SJohn Forte static int last_cmd = -1;
55*fcf3ce44SJohn Forte static uint8_t seq = 0;
56*fcf3ce44SJohn Forte 
57*fcf3ce44SJohn Forte static void
send_cmd(int cmd)58*fcf3ce44SJohn Forte send_cmd(int cmd)
59*fcf3ce44SJohn Forte {
60*fcf3ce44SJohn Forte 	struct lock_msg message_buf;
61*fcf3ce44SJohn Forte 	int rc;
62*fcf3ce44SJohn Forte 
63*fcf3ce44SJohn Forte 	if (last_cmd == cmd) {
64*fcf3ce44SJohn Forte 		message_buf.seq = seq;
65*fcf3ce44SJohn Forte 	} else {
66*fcf3ce44SJohn Forte 		message_buf.seq = ++seq;
67*fcf3ce44SJohn Forte 		last_cmd = cmd;
68*fcf3ce44SJohn Forte 	}
69*fcf3ce44SJohn Forte 	message_buf.message = cmd;
70*fcf3ce44SJohn Forte 	if ((message_buf.pid = getpid()) != socket_pid)
71*fcf3ce44SJohn Forte 		cfg_lockd_reinit();
72*fcf3ce44SJohn Forte 
73*fcf3ce44SJohn Forte 	do {
74*fcf3ce44SJohn Forte 		rc = sendto(lock_soc, &message_buf, sizeof (message_buf), 0,
75*fcf3ce44SJohn Forte 			(struct sockaddr *)&server, sizeof (server));
76*fcf3ce44SJohn Forte 	} while (rc == -1 && errno == EINTR);
77*fcf3ce44SJohn Forte #ifdef CFG_LOCKD_DEBUG
78*fcf3ce44SJohn Forte 	if (rc < 0) {
79*fcf3ce44SJohn Forte 		perror("send");
80*fcf3ce44SJohn Forte 	}
81*fcf3ce44SJohn Forte #endif
82*fcf3ce44SJohn Forte }
83*fcf3ce44SJohn Forte 
84*fcf3ce44SJohn Forte static void
read_msg(struct lock_msg * mp)85*fcf3ce44SJohn Forte read_msg(struct lock_msg *mp)
86*fcf3ce44SJohn Forte {
87*fcf3ce44SJohn Forte 	struct sockaddr from;
88*fcf3ce44SJohn Forte 	int rc, len;
89*fcf3ce44SJohn Forte 
90*fcf3ce44SJohn Forte 	/* wait for response */
91*fcf3ce44SJohn Forte 	do {
92*fcf3ce44SJohn Forte 		struct pollfd fds;
93*fcf3ce44SJohn Forte 
94*fcf3ce44SJohn Forte 		fds.fd = lock_soc;
95*fcf3ce44SJohn Forte 		fds.events = POLLIN;
96*fcf3ce44SJohn Forte 		fds.revents = 0;
97*fcf3ce44SJohn Forte 
98*fcf3ce44SJohn Forte 		rc = poll(&fds, 1, 500);
99*fcf3ce44SJohn Forte 		if (!rc) {
100*fcf3ce44SJohn Forte #ifdef CFG_LOCKD_DEBUG
101*fcf3ce44SJohn Forte 			fprintf(stderr, "LOCKD: resending last command (%d)\n",
102*fcf3ce44SJohn Forte 			    last_cmd);
103*fcf3ce44SJohn Forte #endif
104*fcf3ce44SJohn Forte 			send_cmd(last_cmd);
105*fcf3ce44SJohn Forte 		}
106*fcf3ce44SJohn Forte 	} while (rc == 0 ||
107*fcf3ce44SJohn Forte 		(rc == -1 && errno == EINTR));
108*fcf3ce44SJohn Forte 
109*fcf3ce44SJohn Forte 	do {
110*fcf3ce44SJohn Forte 		len = sizeof (from);
111*fcf3ce44SJohn Forte 		rc = recvfrom(lock_soc, mp, sizeof (*mp), 0,
112*fcf3ce44SJohn Forte 			&from, &len);
113*fcf3ce44SJohn Forte 	} while (rc == -1 && errno == EINTR);
114*fcf3ce44SJohn Forte #ifdef CFG_LOCKD_DEBUG
115*fcf3ce44SJohn Forte 	if (rc < 0) {
116*fcf3ce44SJohn Forte 		perror("revcfrom");
117*fcf3ce44SJohn Forte 	}
118*fcf3ce44SJohn Forte #endif
119*fcf3ce44SJohn Forte }
120*fcf3ce44SJohn Forte 
121*fcf3ce44SJohn Forte static void
read_reply()122*fcf3ce44SJohn Forte read_reply()
123*fcf3ce44SJohn Forte {
124*fcf3ce44SJohn Forte 	struct lock_msg message_buf;
125*fcf3ce44SJohn Forte 
126*fcf3ce44SJohn Forte 	do {
127*fcf3ce44SJohn Forte 		read_msg(&message_buf);
128*fcf3ce44SJohn Forte 	} while (message_buf.seq != seq || message_buf.message != LOCK_LOCKED);
129*fcf3ce44SJohn Forte }
130*fcf3ce44SJohn Forte 
131*fcf3ce44SJohn Forte static void
read_ack()132*fcf3ce44SJohn Forte read_ack()
133*fcf3ce44SJohn Forte {
134*fcf3ce44SJohn Forte 	struct lock_msg message_buf;
135*fcf3ce44SJohn Forte 
136*fcf3ce44SJohn Forte 	do {
137*fcf3ce44SJohn Forte 		read_msg(&message_buf);
138*fcf3ce44SJohn Forte 	} while (message_buf.seq != seq || message_buf.message != LOCK_ACK);
139*fcf3ce44SJohn Forte }
140*fcf3ce44SJohn Forte 
141*fcf3ce44SJohn Forte void
cfg_lockd_rdlock()142*fcf3ce44SJohn Forte cfg_lockd_rdlock()
143*fcf3ce44SJohn Forte {
144*fcf3ce44SJohn Forte #ifdef CFG_LOCKD_DEBUG
145*fcf3ce44SJohn Forte 	FILE *fp;
146*fcf3ce44SJohn Forte #endif
147*fcf3ce44SJohn Forte 
148*fcf3ce44SJohn Forte 	send_cmd(LOCK_READ);
149*fcf3ce44SJohn Forte 	locked = 1;
150*fcf3ce44SJohn Forte 	read_reply();
151*fcf3ce44SJohn Forte 
152*fcf3ce44SJohn Forte #ifdef CFG_LOCKD_DEBUG
153*fcf3ce44SJohn Forte 	fp = fopen("/tmp/locktag", "a");
154*fcf3ce44SJohn Forte 	if (fp) {
155*fcf3ce44SJohn Forte 		time_t t = time(0);
156*fcf3ce44SJohn Forte 		fprintf(fp, "%19.19s read  lock acquired\n", ctime(&t));
157*fcf3ce44SJohn Forte 		fclose(fp);
158*fcf3ce44SJohn Forte 	}
159*fcf3ce44SJohn Forte 	sleep(3);
160*fcf3ce44SJohn Forte #endif
161*fcf3ce44SJohn Forte }
162*fcf3ce44SJohn Forte 
163*fcf3ce44SJohn Forte void
cfg_lockd_wrlock()164*fcf3ce44SJohn Forte cfg_lockd_wrlock()
165*fcf3ce44SJohn Forte {
166*fcf3ce44SJohn Forte #ifdef CFG_LOCKD_DEBUG
167*fcf3ce44SJohn Forte 	FILE *fp;
168*fcf3ce44SJohn Forte #endif
169*fcf3ce44SJohn Forte 
170*fcf3ce44SJohn Forte 	send_cmd(LOCK_WRITE);
171*fcf3ce44SJohn Forte 	locked = 1;
172*fcf3ce44SJohn Forte 	read_reply();
173*fcf3ce44SJohn Forte 
174*fcf3ce44SJohn Forte #ifdef CFG_LOCKD_DEBUG
175*fcf3ce44SJohn Forte 	fp = fopen("/tmp/locktag", "a");
176*fcf3ce44SJohn Forte 	if (fp) {
177*fcf3ce44SJohn Forte 		time_t t = time(0);
178*fcf3ce44SJohn Forte 		fprintf(fp, "%19.19s write lock acquired\n", ctime(&t));
179*fcf3ce44SJohn Forte 		fclose(fp);
180*fcf3ce44SJohn Forte 	}
181*fcf3ce44SJohn Forte 	sleep(3);
182*fcf3ce44SJohn Forte #endif
183*fcf3ce44SJohn Forte }
184*fcf3ce44SJohn Forte 
185*fcf3ce44SJohn Forte void
cfg_lockd_unlock()186*fcf3ce44SJohn Forte cfg_lockd_unlock()
187*fcf3ce44SJohn Forte {
188*fcf3ce44SJohn Forte #ifdef CFG_LOCKD_DEBUG
189*fcf3ce44SJohn Forte 	FILE *fp;
190*fcf3ce44SJohn Forte #endif
191*fcf3ce44SJohn Forte 
192*fcf3ce44SJohn Forte 	send_cmd(LOCK_NOTLOCKED);
193*fcf3ce44SJohn Forte 	read_ack();
194*fcf3ce44SJohn Forte 	locked = 0;
195*fcf3ce44SJohn Forte 
196*fcf3ce44SJohn Forte #ifdef CFG_LOCKD_DEBUG
197*fcf3ce44SJohn Forte 	fp = fopen("/tmp/locktag", "a");
198*fcf3ce44SJohn Forte 	if (fp) {
199*fcf3ce44SJohn Forte 		time_t t = time(0);
200*fcf3ce44SJohn Forte 		fprintf(fp, "%19.19s ----- lock released\n", ctime(&t));
201*fcf3ce44SJohn Forte 		fclose(fp);
202*fcf3ce44SJohn Forte 	}
203*fcf3ce44SJohn Forte 	sleep(3);
204*fcf3ce44SJohn Forte #endif
205*fcf3ce44SJohn Forte }
206*fcf3ce44SJohn Forte 
207*fcf3ce44SJohn Forte void
cfg_lockd_stat()208*fcf3ce44SJohn Forte cfg_lockd_stat()
209*fcf3ce44SJohn Forte {
210*fcf3ce44SJohn Forte 	send_cmd(LOCK_STAT);
211*fcf3ce44SJohn Forte }
212*fcf3ce44SJohn Forte 
213*fcf3ce44SJohn Forte cfglockd_t
cfg_lockedby(pid_t * pidp)214*fcf3ce44SJohn Forte cfg_lockedby(pid_t *pidp)
215*fcf3ce44SJohn Forte {
216*fcf3ce44SJohn Forte 	struct lock_msg message_buf;
217*fcf3ce44SJohn Forte 	send_cmd(LOCK_LOCKEDBY);
218*fcf3ce44SJohn Forte 	read_msg(&message_buf);
219*fcf3ce44SJohn Forte 	*pidp = message_buf.pid;
220*fcf3ce44SJohn Forte 	return ((cfglockd_t)message_buf.message);
221*fcf3ce44SJohn Forte }
222*fcf3ce44SJohn Forte 
223*fcf3ce44SJohn Forte static void
cfg_atexit()224*fcf3ce44SJohn Forte cfg_atexit()
225*fcf3ce44SJohn Forte {
226*fcf3ce44SJohn Forte 	if (locked)
227*fcf3ce44SJohn Forte 		cfg_lockd_unlock();
228*fcf3ce44SJohn Forte }
229*fcf3ce44SJohn Forte 
230*fcf3ce44SJohn Forte static int
cfg_lockd_socket()231*fcf3ce44SJohn Forte cfg_lockd_socket()
232*fcf3ce44SJohn Forte {
233*fcf3ce44SJohn Forte 	if ((lock_soc = socket(pf_inet, SOCK_DGRAM, 0)) < 0) {
234*fcf3ce44SJohn Forte #ifdef CFG_LOCKD_DEBUG
235*fcf3ce44SJohn Forte 		fprintf(stderr, "libcfg: failed to create socket\n");
236*fcf3ce44SJohn Forte 		perror("socket");
237*fcf3ce44SJohn Forte #endif
238*fcf3ce44SJohn Forte 		return (-1);
239*fcf3ce44SJohn Forte 	}
240*fcf3ce44SJohn Forte 	clientaddr.sin_family = AF_INET;
241*fcf3ce44SJohn Forte 	clientaddr.sin_addr.s_addr = INADDR_ANY;
242*fcf3ce44SJohn Forte 	clientaddr.sin_port = htons(0);
243*fcf3ce44SJohn Forte 	if (bind(lock_soc, (struct sockaddr *)&clientaddr,
244*fcf3ce44SJohn Forte 	    sizeof (clientaddr)) < 0) {
245*fcf3ce44SJohn Forte #ifdef CFG_LOCKD_DEBUG
246*fcf3ce44SJohn Forte 		perror("bind");
247*fcf3ce44SJohn Forte #endif
248*fcf3ce44SJohn Forte 		return (-1);
249*fcf3ce44SJohn Forte 	}
250*fcf3ce44SJohn Forte 	socket_pid = getpid();
251*fcf3ce44SJohn Forte 	return (0);
252*fcf3ce44SJohn Forte }
253*fcf3ce44SJohn Forte 
254*fcf3ce44SJohn Forte /*
255*fcf3ce44SJohn Forte  * Re-initialise after a fork has been detected.
256*fcf3ce44SJohn Forte  *
257*fcf3ce44SJohn Forte  * Needs to create a new socket for new process to receive messages
258*fcf3ce44SJohn Forte  * from the lock daemon and enter pid into lock file so that the daemon
259*fcf3ce44SJohn Forte  * can detect new processes exit if it doesn't call unlock first.
260*fcf3ce44SJohn Forte  */
261*fcf3ce44SJohn Forte 
262*fcf3ce44SJohn Forte static void
cfg_lockd_reinit()263*fcf3ce44SJohn Forte cfg_lockd_reinit()
264*fcf3ce44SJohn Forte {
265*fcf3ce44SJohn Forte 	if (lock_soc)
266*fcf3ce44SJohn Forte 		close(lock_soc);
267*fcf3ce44SJohn Forte 	lock_soc = 0;
268*fcf3ce44SJohn Forte 	if (cfg_lockd_socket()) {
269*fcf3ce44SJohn Forte 		initresult = 0;
270*fcf3ce44SJohn Forte 		return;
271*fcf3ce44SJohn Forte 	}
272*fcf3ce44SJohn Forte 	cfg_enterpid();
273*fcf3ce44SJohn Forte 	initresult = 1;
274*fcf3ce44SJohn Forte }
275*fcf3ce44SJohn Forte 
276*fcf3ce44SJohn Forte int
cfg_lockd_init()277*fcf3ce44SJohn Forte cfg_lockd_init()
278*fcf3ce44SJohn Forte {
279*fcf3ce44SJohn Forte 	struct	hostent *hp;
280*fcf3ce44SJohn Forte 	FILE	*fp;
281*fcf3ce44SJohn Forte 	int	pid = 0x12345678;
282*fcf3ce44SJohn Forte 
283*fcf3ce44SJohn Forte 	if (initdone) {
284*fcf3ce44SJohn Forte 		/* only perform reinit if init worked first time */
285*fcf3ce44SJohn Forte 		if (getpid() != socket_pid && initresult != 0)
286*fcf3ce44SJohn Forte 			cfg_lockd_reinit();
287*fcf3ce44SJohn Forte 		return (initresult);
288*fcf3ce44SJohn Forte 	}
289*fcf3ce44SJohn Forte 
290*fcf3ce44SJohn Forte 	initdone = 1;
291*fcf3ce44SJohn Forte 	initresult = 0;
292*fcf3ce44SJohn Forte 
293*fcf3ce44SJohn Forte 	/* check if there's a lock daemon out there */
294*fcf3ce44SJohn Forte 	if ((fp = fopen(CFG_PIDFILE, "r")) == NULL)
295*fcf3ce44SJohn Forte 		return (0);
296*fcf3ce44SJohn Forte 	if (fscanf(fp, "%d\n", &pid) != 1) {
297*fcf3ce44SJohn Forte 		fclose(fp);
298*fcf3ce44SJohn Forte 		return (0);
299*fcf3ce44SJohn Forte 	}
300*fcf3ce44SJohn Forte 	fclose(fp);
301*fcf3ce44SJohn Forte 	if (kill((pid_t)pid, 0) != 0)
302*fcf3ce44SJohn Forte 		return (0);
303*fcf3ce44SJohn Forte 
304*fcf3ce44SJohn Forte 	/* there is a lock daemon */
305*fcf3ce44SJohn Forte 	cfg_lfinit();
306*fcf3ce44SJohn Forte 	cfg_enterpid();
307*fcf3ce44SJohn Forte 	if (cfg_lockd_socket())
308*fcf3ce44SJohn Forte 		return (0);
309*fcf3ce44SJohn Forte 
310*fcf3ce44SJohn Forte 	if ((hp = gethostbyname("localhost")) == NULL) {
311*fcf3ce44SJohn Forte #ifdef CFG_LOCKD_DEBUG
312*fcf3ce44SJohn Forte 		fprintf(stderr, "Can't find hostent for %s\n", "localhost");
313*fcf3ce44SJohn Forte #endif
314*fcf3ce44SJohn Forte 		return (0);
315*fcf3ce44SJohn Forte 	}
316*fcf3ce44SJohn Forte 	(void) memcpy(&(server.sin_addr.s_addr), *(hp->h_addr_list),
317*fcf3ce44SJohn Forte 				sizeof (server.sin_addr));
318*fcf3ce44SJohn Forte 	server.sin_port = htons(server_port);
319*fcf3ce44SJohn Forte 	server.sin_family = hp->h_addrtype;
320*fcf3ce44SJohn Forte 	endhostent();
321*fcf3ce44SJohn Forte 	atexit(cfg_atexit);
322*fcf3ce44SJohn Forte 	initresult = 1;
323*fcf3ce44SJohn Forte 	return (1);
324*fcf3ce44SJohn Forte }
325