Return to ha_ctl.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libcharon / plugins / ha |
1.1 misho 1: /* 2: * Copyright (C) 2015 Tobias Brunner 3: * Copyright (C) 2008 Martin Willi 4: * HSR Hochschule fuer Technik Rapperswil 5: * 6: * This program is free software; you can redistribute it and/or modify it 7: * under the terms of the GNU General Public License as published by the 8: * Free Software Foundation; either version 2 of the License, or (at your 9: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. 10: * 11: * This program is distributed in the hope that it will be useful, but 12: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14: * for more details. 15: */ 16: 17: #include "ha_ctl.h" 18: 19: #include <sys/types.h> 20: #include <sys/stat.h> 21: #include <sys/select.h> 22: #include <fcntl.h> 23: #include <unistd.h> 24: #include <errno.h> 25: 26: #include <threading/thread.h> 27: #include <processing/jobs/callback_job.h> 28: 29: #define HA_FIFO IPSEC_PIDDIR "/charon.ha" 30: 31: typedef struct private_ha_ctl_t private_ha_ctl_t; 32: 33: /** 34: * Private data of an ha_ctl_t object. 35: */ 36: struct private_ha_ctl_t { 37: 38: /** 39: * Public ha_ctl_t interface. 40: */ 41: ha_ctl_t public; 42: 43: /** 44: * Segments to control 45: */ 46: ha_segments_t *segments; 47: 48: /** 49: * Resynchronization message cache 50: */ 51: ha_cache_t *cache; 52: }; 53: 54: /** 55: * Change the permissions of the control FIFO, returns TRUE on success 56: */ 57: static bool change_fifo_permissions() 58: { 59: if (chown(HA_FIFO, lib->caps->get_uid(lib->caps), 60: lib->caps->get_gid(lib->caps)) != 0) 61: { 62: DBG1(DBG_CFG, "changing HA FIFO permissions failed: %s", 63: strerror(errno)); 64: return FALSE; 65: } 66: return TRUE; 67: } 68: 69: /** 70: * Deletes and creates the control FIFO, returns TRUE on success 71: */ 72: static bool recreate_fifo() 73: { 74: mode_t old; 75: bool success = TRUE; 76: 77: unlink(HA_FIFO); 78: old = umask(S_IRWXO); 79: if (mkfifo(HA_FIFO, S_IRUSR | S_IWUSR) != 0) 80: { 81: DBG1(DBG_CFG, "creating HA FIFO %s failed: %s", HA_FIFO, 82: strerror(errno)); 83: success = FALSE; 84: } 85: umask(old); 86: return success && change_fifo_permissions(); 87: } 88: 89: /** 90: * FIFO dispatching function 91: */ 92: static job_requeue_t dispatch_fifo(private_ha_ctl_t *this) 93: { 94: int fifo; 95: bool oldstate; 96: char buf[8]; 97: u_int segment; 98: struct stat sb; 99: 100: oldstate = thread_cancelability(TRUE); 101: fifo = open(HA_FIFO, O_RDONLY); 102: thread_cancelability(oldstate); 103: if (fifo == -1 || fstat(fifo, &sb) != 0 || !S_ISFIFO(sb.st_mode)) 104: { 105: if (fifo == -1 && errno != ENOENT) 106: { 107: DBG1(DBG_CFG, "opening HA FIFO failed: %s", strerror(errno)); 108: } 109: else 110: { 111: DBG1(DBG_CFG, "%s is not a FIFO, recreate it", HA_FIFO); 112: recreate_fifo(); 113: } 114: if (fifo != -1) 115: { 116: close(fifo); 117: } 118: sleep(1); 119: return JOB_REQUEUE_FAIR; 120: } 121: 122: memset(buf, 0, sizeof(buf)); 123: if (read(fifo, buf, sizeof(buf)-1) > 1) 124: { 125: segment = atoi(&buf[1]); 126: if (segment) 127: { 128: switch (buf[0]) 129: { 130: case '+': 131: this->segments->activate(this->segments, segment, TRUE); 132: break; 133: case '-': 134: this->segments->deactivate(this->segments, segment, TRUE); 135: break; 136: case '*': 137: this->cache->resync(this->cache, segment); 138: break; 139: default: 140: break; 141: } 142: } 143: } 144: close(fifo); 145: 146: return JOB_REQUEUE_DIRECT; 147: } 148: 149: METHOD(ha_ctl_t, destroy, void, 150: private_ha_ctl_t *this) 151: { 152: unlink(HA_FIFO); 153: free(this); 154: } 155: 156: /** 157: * See header 158: */ 159: ha_ctl_t *ha_ctl_create(ha_segments_t *segments, ha_cache_t *cache) 160: { 161: private_ha_ctl_t *this; 162: struct stat sb; 163: 164: INIT(this, 165: .public = { 166: .destroy = _destroy, 167: }, 168: .segments = segments, 169: .cache = cache, 170: ); 171: 172: if (stat(HA_FIFO, &sb) == 0) 173: { 174: if (!S_ISFIFO(sb.st_mode)) 175: { 176: DBG1(DBG_CFG, "%s is not a FIFO, recreate it", HA_FIFO); 177: recreate_fifo(); 178: } 179: else if (access(HA_FIFO, R_OK|W_OK) != 0) 180: { 181: DBG1(DBG_CFG, "accessing HA FIFO %s denied, recreate it", HA_FIFO); 182: recreate_fifo(); 183: } 184: else 185: { 186: change_fifo_permissions(); 187: } 188: } 189: else if (errno == ENOENT) 190: { 191: recreate_fifo(); 192: } 193: else 194: { 195: DBG1(DBG_CFG, "accessing HA FIFO %s failed: %s", HA_FIFO, 196: strerror(errno)); 197: } 198: 199: lib->processor->queue_job(lib->processor, 200: (job_t*)callback_job_create_with_prio((callback_job_cb_t)dispatch_fifo, 201: this, NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL)); 202: return &this->public; 203: }