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 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 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 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 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 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 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 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 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 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 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 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 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 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