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