From 60a6970f4d004a3bdaedc5af4e1581890ab9b462 Mon Sep 17 00:00:00 2001 From: Sander Vrijders Date: Tue, 29 Nov 2016 11:48:17 +0100 Subject: ipcpd: normal: Complete flat address policy This will add a check in the flat address policy to see if the address is in use or not. --- src/ipcpd/normal/pol/flat.c | 261 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 261 insertions(+) create mode 100644 src/ipcpd/normal/pol/flat.c (limited to 'src/ipcpd/normal/pol/flat.c') diff --git a/src/ipcpd/normal/pol/flat.c b/src/ipcpd/normal/pol/flat.c new file mode 100644 index 00000000..4946d538 --- /dev/null +++ b/src/ipcpd/normal/pol/flat.c @@ -0,0 +1,261 @@ +/* + * Ouroboros - Copyright (C) 2016 + * + * Policy for flat addresses in a distributed way + * + * Sander Vrijders + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#define OUROBOROS_PREFIX "flat-addr-auth" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "shm_pci.h" +#include "ribmgr.h" +#include "ro.h" + +#define POL_RO_ROOT "/flat_addr" + +#define TIMEOUT 100 /* ms */ +#define STR_SIZE 100 + +#define FLAT_ADDR_REQ 0 +#define FLAT_ADDR_REPLY 1 + +struct flat_addr_msg { + uint8_t code; + uint64_t addr; +}; + +struct { + int sid; + uint64_t addr; + bool addr_in_use; + + pthread_cond_t cond; + pthread_mutex_t lock; +} flat; + +static char * my_name(void) +{ + char * name; + char addr_name[100]; + + name = malloc(STR_SIZE); + if (name == NULL) + return NULL; + + sprintf(addr_name, "%lu", (unsigned long) flat.addr); + strcpy(name, POL_RO_ROOT); + strcat(name, "/"); + strcat(name, addr_name); + + return name; +} + +/* FIXME: We should return void */ +static int ro_created(const char * name, + uint8_t * data, + size_t len) +{ + struct flat_addr_msg * msg; + + assert(name); + assert(data); + assert(len >= sizeof(*msg)); + + msg = (struct flat_addr_msg *) data; + if (msg->code == FLAT_ADDR_REQ && + msg->addr == flat.addr) { + msg->code = FLAT_ADDR_REPLY; + ro_write(name, data, len); + } + + return 0; +} + +static int ro_updated(const char * name, + uint8_t * data, + size_t len) +{ + struct flat_addr_msg * msg; + char * ro_name; + + assert(name); + assert(data); + assert(len >= sizeof(*msg)); + + ro_name = my_name(); + if (ro_name == NULL) + return -1; + + msg = (struct flat_addr_msg *) data; + if (msg->code == FLAT_ADDR_REPLY && + strcmp(name, ro_name) == 0) { + pthread_mutex_lock(&flat.lock); + flat.addr_in_use = true; + pthread_cond_broadcast(&flat.cond); + pthread_mutex_unlock(&flat.lock); + } + + free(data); + free(ro_name); + + return 0; +} + +static struct ro_sub_ops flat_sub_ops = { + .ro_created = ro_created, + .ro_updated = ro_updated, + .ro_deleted = NULL +}; + +int flat_init(void) +{ + struct ro_props * props; + pthread_condattr_t cattr; + + srand(time(NULL)); + flat.addr_in_use = false; + + props = malloc(sizeof(*props)); + if (props == NULL) + return -ENOMEM; + + pthread_mutex_init(&flat.lock, NULL); + pthread_condattr_init(&cattr); +#ifndef __APPLE__ + pthread_condattr_setclock(&cattr, PTHREAD_COND_CLOCK); +#endif + pthread_cond_init(&flat.cond, &cattr); + + flat.sid = ro_subscribe(POL_RO_ROOT, + &flat_sub_ops); + if (flat.sid < 0) { + LOG_ERR("Could not subscribe to RIB."); + pthread_cond_destroy(&flat.cond); + pthread_mutex_destroy(&flat.lock); + free(props); + return -1; + } + + props->enrol_sync = false; + props->recv_set = NO_SYNC; + props->expiry.tv_sec = 0; + props->expiry.tv_nsec = 0; + + if (ro_create(POL_RO_ROOT, props, NULL, 0)) { + LOG_ERR("Could not create RO."); + pthread_cond_destroy(&flat.cond); + pthread_mutex_destroy(&flat.lock); + free(props); + ro_unsubscribe(flat.sid); + return -1; + } + + return 0; +} + +int flat_fini(void) +{ + pthread_cond_destroy(&flat.cond); + pthread_mutex_destroy(&flat.lock); + ro_unsubscribe(flat.sid); + return 0; +} + +uint64_t flat_address(void) +{ + int ret = 0; + uint64_t max_addr; + struct dt_const * dtc; + struct timespec timeout = {(TIMEOUT / 1000), + (TIMEOUT % 1000) * MILLION}; + struct timespec abstime; + struct ro_props * props; + struct flat_addr_msg * msg; + uint8_t * buf; + char * ro_name; + + dtc = ribmgr_dt_const(); + if (dtc == NULL) + return INVALID_ADDR; + + while (ret != -ETIMEDOUT) { + clock_gettime(PTHREAD_COND_CLOCK, &abstime); + ts_add(&abstime, &timeout, &abstime); + + max_addr = (1 << (8 * dtc->addr_size)) - 1; + flat.addr = (rand() % (max_addr - 1)) + 1; + + /* FIXME: We must change this to stack memory */ + props = malloc(sizeof(*props)); + if (props == NULL) + return INVALID_ADDR; + + props->enrol_sync = false; + props->recv_set = ALL_MEMBERS; + props->expiry.tv_sec = TIMEOUT / 1000; + props->expiry.tv_nsec = (TIMEOUT % 1000) * MILLION; + + buf = malloc(sizeof(*msg)); + if (buf == NULL) { + free(props); + return INVALID_ADDR; + } + + msg = (struct flat_addr_msg *) buf; + msg->code = FLAT_ADDR_REQ; + msg->addr = flat.addr; + + /* FIXME: We may require functions to construct pathnames */ + ro_name = my_name(); + if (ro_name == NULL) { + free(props); + return INVALID_ADDR; + } + + pthread_mutex_lock(&flat.lock); + if (ro_create(ro_name, props, buf, sizeof(*msg))) { + pthread_mutex_unlock(&flat.lock); + free(props); + free(ro_name); + return INVALID_ADDR; + } + free(ro_name); + + while (flat.addr_in_use == false) { + ret = -pthread_cond_timedwait(&flat.cond, + &flat.lock, + &abstime); + if (ret == -ETIMEDOUT) + break; + } + pthread_mutex_unlock(&flat.lock); + } + + return flat.addr; +} -- cgit v1.2.3