summaryrefslogtreecommitdiff
path: root/utils/open-isns/esi.c
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2015-08-24 20:31:06 -0500
committerMike Christie <michaelc@cs.wisc.edu>2015-08-24 20:31:06 -0500
commitc6d1117bb6fc85d505b815c23a0190376354c3f2 (patch)
tree8ed087d4b95ccb31c231c27fc0333d14a71ed207 /utils/open-isns/esi.c
parent768326624de9be7229980ceb7a35943b6fba1a6b (diff)
downloadopen-iscsi-c6d1117bb6fc85d505b815c23a0190376354c3f2.tar.gz
iscsi: remove local copy of open-isns
This has open-iscsi stop shipping a copy of open-isns. You can get the open-isns from the new isns maintainer, Lee Duncan, from his github tree here: https://github.com/gonzoleeman/open-isns/releases Thanks to Lee and SUSE for taking this work on!
Diffstat (limited to 'utils/open-isns/esi.c')
-rw-r--r--utils/open-isns/esi.c576
1 files changed, 0 insertions, 576 deletions
diff --git a/utils/open-isns/esi.c b/utils/open-isns/esi.c
deleted file mode 100644
index 47d52c6..0000000
--- a/utils/open-isns/esi.c
+++ /dev/null
@@ -1,576 +0,0 @@
-/*
- * Handle ESI events
- *
- * Copyright (C) 2007 Olaf Kirch <olaf.kirch@oracle.com>
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include "isns.h"
-#include "attrs.h"
-#include "objects.h"
-#include "message.h"
-#include "security.h"
-#include "util.h"
-#include "db.h"
-
-#define ESI_RETRANS_TIMEOUT 60
-
-typedef struct isns_esi isns_esi_t;
-typedef struct isns_esi_portal isns_esi_portal_t;
-
-struct isns_esi {
- isns_list_t esi_list;
- isns_object_t * esi_object;
- isns_list_t esi_portals;
-
- unsigned int esi_update : 1;
-};
-
-struct isns_esi_portal {
- isns_list_t esp_list;
- isns_object_t * esp_object;
- isns_portal_info_t esp_portal;
- unsigned int esp_interval;
- isns_portal_info_t esp_dest;
-
- isns_socket_t * esp_socket;
- unsigned int esp_retries;
- unsigned int esp_timeout;
- time_t esp_start;
- time_t esp_next_xmit;
- uint32_t esp_xid;
-};
-
-int isns_esi_enabled = 0;
-static isns_server_t * isns_esi_server = NULL;
-static ISNS_LIST_DECLARE(isns_esi_list);
-
-static void isns_esi_transmit(void *);
-static void isns_esi_sendto(isns_esi_t *, isns_esi_portal_t *);
-static void isns_process_esi_response(uint32_t, int,
- isns_simple_t *);
-static void isns_esi_disconnect(isns_esi_portal_t *);
-static void isns_esi_restart(isns_esi_portal_t *);
-static void isns_esi_drop_portal(isns_esi_portal_t *, isns_db_t *, int);
-static void isns_esi_drop_entity(isns_esi_t *, isns_db_t *, int);
-static int isns_esi_update(isns_esi_t *);
-static void isns_esi_schedule(int);
-static void isns_esi_callback(const isns_db_event_t *, void *);
-
-void
-isns_esi_init(isns_server_t *srv)
-{
- if (isns_config.ic_esi_retries == 0) {
- isns_debug_esi("ESI disabled by administrator\n");
- } else {
- unsigned int max_interval;
-
- isns_register_callback(isns_esi_callback, NULL);
- isns_esi_schedule(0);
-
- max_interval = isns_config.ic_registration_period / 2;
- if (isns_config.ic_esi_max_interval > max_interval) {
- isns_warning("Max ESI interval adjusted to %u sec "
- "to match registration period\n",
- max_interval);
- isns_config.ic_esi_max_interval = max_interval;
- if (isns_config.ic_esi_min_interval > max_interval)
- isns_config.ic_esi_min_interval = max_interval;
- }
- isns_esi_server = srv;
- isns_esi_enabled = 1;
- }
-}
-
-/*
- * Timer callback to send out ESI messages.
- */
-void
-isns_esi_transmit(void *ptr)
-{
- isns_db_t *db = isns_esi_server->is_db;
- isns_list_t *esi_pos, *esi_next;
- time_t now;
- isns_object_t *obj;
- time_t next_timeout;
-
- now = time(NULL);
- next_timeout = now + 3600;
-
- isns_list_foreach(&isns_esi_list, esi_pos, esi_next) {
- isns_list_t *esp_pos, *esp_next;
- isns_esi_t *esi = isns_list_item(isns_esi_t, esi_list, esi_pos);
-
- if (esi->esi_update) {
- esi->esi_update = 0;
- if (!isns_esi_update(esi))
- continue;
- }
-
- isns_list_foreach(&esi->esi_portals, esp_pos, esp_next) {
- isns_esi_portal_t *esp = isns_list_item(isns_esi_portal_t,
- esp_list, esp_pos);
-
- /* Check whether the portal object still exist */
- obj = esp->esp_object;
- if (obj->ie_state != ISNS_OBJECT_STATE_MATURE) {
- isns_esi_drop_portal(esp, db, 0);
- continue;
- }
-
- if (esp->esp_next_xmit <= now) {
- if (esp->esp_retries == 0) {
- isns_debug_esi("No ESI response from %s - dropping\n",
- isns_portal_string(&esp->esp_dest));
- isns_esi_drop_portal(esp, db, 1);
- continue;
- }
-
- esp->esp_retries -= 1;
- esp->esp_next_xmit = now + esp->esp_timeout;
- isns_esi_sendto(esi, esp);
- }
- if (esp->esp_next_xmit < next_timeout)
- next_timeout = esp->esp_next_xmit;
- }
-
- if (isns_list_empty(&esi->esi_portals))
- isns_esi_drop_entity(esi, db, 1);
- }
-
- isns_debug_esi("Next ESI message in %d seconds\n", next_timeout - now);
- isns_esi_schedule(next_timeout - now);
-}
-
-/*
- * Send an ESI message
- */
-void
-isns_esi_sendto(isns_esi_t *esi, isns_esi_portal_t *esp)
-{
- isns_attr_list_t attrs = ISNS_ATTR_LIST_INIT;
- isns_socket_t *sock;
- isns_simple_t *msg;
-
- /* For TCP portals, kill the TCP socket every time. */
- if (esp->esp_dest.proto == IPPROTO_TCP)
- isns_esi_disconnect(esp);
-
- if (esp->esp_socket == NULL) {
- sock = isns_connect_to_portal(&esp->esp_dest);
- if (sock == NULL)
- return;
-
- isns_socket_set_security_ctx(sock,
- isns_default_security_context(0));
- /* sock->is_disconnect_fatal = 1; */
- esp->esp_socket = sock;
- }
-
- isns_attr_list_append_uint64(&attrs,
- ISNS_TAG_TIMESTAMP,
- time(NULL));
- /* The following will extract the ENTITY IDENTIFIER */
- isns_object_extract_keys(esi->esi_object, &attrs);
- isns_portal_to_attr_list(&esp->esp_portal,
- ISNS_TAG_PORTAL_IP_ADDRESS,
- ISNS_TAG_PORTAL_TCP_UDP_PORT,
- &attrs);
-
- msg = isns_simple_create(ISNS_ENTITY_STATUS_INQUIRY,
- NULL, &attrs);
- if (msg == NULL)
- return;
-
- isns_debug_esi("*** Sending ESI message to %s (xid=0x%x); %u retries left\n",
- isns_portal_string(&esp->esp_dest),
- msg->is_xid, esp->esp_retries);
- isns_simple_transmit(esp->esp_socket, msg,
- NULL, esp->esp_timeout - 1,
- isns_process_esi_response);
- esp->esp_xid = msg->is_xid;
- isns_simple_free(msg);
-}
-
-/*
- * A new entity was added. See if it uses ESI, and create
- * portals and such.
- */
-static void
-isns_esi_add_entity(isns_object_t *obj)
-{
- isns_esi_t *esi;
-
- isns_debug_esi("Enable ESI monitoring for entity %u\n", obj->ie_index);
- esi = isns_calloc(1, sizeof(*esi));
- esi->esi_object = isns_object_get(obj);
- esi->esi_update = 1;
- isns_list_init(&esi->esi_list);
- isns_list_init(&esi->esi_portals);
-
- isns_list_append(&isns_esi_list, &esi->esi_list);
-}
-
-/*
- * Given an entity, see if we can find ESI state for it.
- */
-static isns_esi_t *
-isns_esi_find(isns_object_t *obj)
-{
- isns_list_t *pos, *next;
-
- isns_list_foreach(&isns_esi_list, pos, next) {
- isns_esi_t *esi = isns_list_item(isns_esi_t, esi_list, pos);
-
- if (esi->esi_object == obj)
- return esi;
- }
- return NULL;
-}
-
-/*
- * Update the ESI state after an entity has changed
- */
-static int
-isns_esi_update(isns_esi_t *esi)
-{
- isns_object_t *entity = esi->esi_object;
- ISNS_LIST_DECLARE(hold);
- isns_esi_portal_t *esp;
- unsigned int i;
-
- isns_debug_esi("Updating ESI state for entity %u\n", entity->ie_index);
-
- isns_list_move(&hold, &esi->esi_portals);
- for (i = 0; i < entity->ie_children.iol_count; ++i) {
- isns_object_t *child = entity->ie_children.iol_data[i];
- isns_portal_info_t esi_portal, portal_info;
- uint32_t esi_interval;
- isns_list_t *pos, *next;
- int changed = 0;
-
- if (!ISNS_IS_PORTAL(child))
- continue;
-
- if (!isns_portal_from_object(&portal_info,
- ISNS_TAG_PORTAL_IP_ADDRESS,
- ISNS_TAG_PORTAL_TCP_UDP_PORT,
- child)
- || !isns_portal_from_object(&esi_portal,
- ISNS_TAG_PORTAL_IP_ADDRESS,
- ISNS_TAG_ESI_PORT,
- child)
- || !isns_object_get_uint32(child,
- ISNS_TAG_ESI_INTERVAL,
- &esi_interval))
- continue;
-
- isns_list_foreach(&hold, pos, next) {
- esp = isns_list_item(isns_esi_portal_t, esp_list, pos);
-
- if (esp->esp_object == child) {
- isns_debug_esi("Updating ESI state for %s\n",
- isns_portal_string(&portal_info));
- isns_list_del(&esp->esp_list);
- goto update;
- }
- }
-
- isns_debug_esi("Creating ESI state for %s\n",
- isns_portal_string(&portal_info));
- esp = isns_calloc(1, sizeof(*esp));
- esp->esp_object = isns_object_get(child);
- isns_list_init(&esp->esp_list);
- changed = 1;
-
-update:
- if (!isns_portal_equal(&esp->esp_portal, &portal_info)) {
- esp->esp_portal = portal_info;
- changed++;
- }
- if (!isns_portal_equal(&esp->esp_dest, &esi_portal)) {
- isns_esi_disconnect(esp);
- esp->esp_dest = esi_portal;
- changed++;
- }
- if (esp->esp_interval != esi_interval) {
- esp->esp_interval = esi_interval;
- changed++;
- }
-
- isns_esi_restart(esp);
-
- isns_list_append(&esi->esi_portals, &esp->esp_list);
- }
-
- /* Destroy any old ESI portals */
- while (!isns_list_empty(&hold)) {
- esp = isns_list_item(isns_esi_portal_t, esp_list, hold.next);
-
- isns_esi_drop_portal(esp, NULL, 0);
- }
-
- /* If the client explicitly unregistered all ESI portals,
- * stop monitoring it but *without* destroying the entity. */
- if (isns_list_empty(&esi->esi_portals)) {
- isns_esi_drop_entity(esi, NULL, 0);
- return 0;
- }
-
- return 1;
-}
-
-void
-isns_esi_restart(isns_esi_portal_t *esp)
-{
- unsigned int timeo;
-
- isns_esi_disconnect(esp);
-
- esp->esp_start = time(NULL);
- esp->esp_retries = isns_config.ic_esi_retries;
- esp->esp_next_xmit = esp->esp_start + esp->esp_interval;
- esp->esp_xid = 0;
-
- timeo = esp->esp_interval / esp->esp_retries;
- if (timeo == 0)
- timeo = 1;
- else if (timeo > ESI_RETRANS_TIMEOUT)
- timeo = ESI_RETRANS_TIMEOUT;
- esp->esp_timeout = timeo;
-}
-
-void
-isns_esi_disconnect(isns_esi_portal_t *esp)
-{
- if (esp->esp_socket)
- isns_socket_free(esp->esp_socket);
- esp->esp_socket = NULL;
-}
-
-/*
- * Generic wrapper to dropping an object
- */
-static inline void
-__isns_esi_drop_object(isns_db_t *db, isns_object_t *obj, unsigned int dead)
-{
- if (db && obj && obj->ie_state == ISNS_OBJECT_STATE_MATURE && dead)
- isns_db_remove(db, obj);
- isns_object_release(obj);
-}
-
-/*
- * Portal did not respond in time. Drop it
- */
-void
-isns_esi_drop_portal(isns_esi_portal_t *esp, isns_db_t *db, int dead)
-{
- isns_debug_esi("ESI: dropping portal %s\n",
- isns_portal_string(&esp->esp_portal));
-
- isns_list_del(&esp->esp_list);
- isns_esi_disconnect(esp);
- __isns_esi_drop_object(db, esp->esp_object, dead);
- isns_free(esp);
-}
-
-/*
- * We ran out of ESI portals for this entity.
- */
-void
-isns_esi_drop_entity(isns_esi_t *esi, isns_db_t *db, int dead)
-{
- isns_debug_esi("ESI: dropping entity %u\n",
- esi->esi_object->ie_index);
-
- isns_list_del(&esi->esi_list);
- __isns_esi_drop_object(db, esi->esi_object, dead);
-
- while (!isns_list_empty(&esi->esi_portals)) {
- isns_esi_portal_t *esp;
-
- esp = isns_list_item(isns_esi_portal_t, esp_list,
- esi->esi_portals.next);
- isns_esi_drop_portal(esp, db, dead);
- }
- isns_free(esi);
-}
-
-/*
- * When receiving an ESI response, find the portal we sent the
- * original message to.
- */
-static isns_esi_portal_t *
-isns_esi_get_msg_portal(uint32_t xid, isns_esi_t **esip)
-{
- isns_list_t *esi_pos, *esi_next;
-
- isns_list_foreach(&isns_esi_list, esi_pos, esi_next) {
- isns_esi_t *esi = isns_list_item(isns_esi_t, esi_list, esi_pos);
- isns_list_t *esp_pos, *esp_next;
-
- isns_list_foreach(&esi->esi_portals, esp_pos, esp_next) {
- isns_esi_portal_t *esp = isns_list_item(isns_esi_portal_t,
- esp_list, esp_pos);
-
- if (esp->esp_xid == xid) {
- *esip = esi;
- return esp;
- }
- }
- }
-
- return NULL;
-}
-
-/*
- * Handle incoming ESI request
- */
-int
-isns_process_esi(isns_server_t *srv, isns_simple_t *call, isns_simple_t **reply)
-{
- const isns_attr_list_t *attrs = &call->is_message_attrs;
- isns_object_t *portal = NULL;
-
- /* We just echo back the attributes sent to us by the server,
- * without further checking. */
- *reply = isns_simple_create(ISNS_ENTITY_STATUS_INQUIRY,
- srv->is_source, attrs);
-
- /* Look up the portal and update its mtime.
- * This can help the application find out if a portal has
- * seen ESIs recently, and react.
- */
- if (srv->is_db && attrs->ial_count == 4) {
- const isns_attr_t *addr_attr, *port_attr;
-
- addr_attr = attrs->ial_data[2];
- port_attr = attrs->ial_data[3];
- if (addr_attr->ia_tag_id == ISNS_TAG_PORTAL_IP_ADDRESS
- && port_attr->ia_tag_id == ISNS_TAG_PORTAL_TCP_UDP_PORT) {
- isns_attr_list_t key;
-
- key.ial_count = 2;
- key.ial_data = attrs->ial_data + 2;
- portal = isns_db_lookup(srv->is_db,
- &isns_portal_template,
- &key);
- }
-
- if (portal)
- portal->ie_mtime = time(NULL);
- }
- return ISNS_SUCCESS;
-}
-
-void
-isns_process_esi_response(uint32_t xid, int status, isns_simple_t *msg)
-{
- isns_portal_info_t portal_info;
- isns_esi_portal_t *esp;
- isns_esi_t *esi;
-
- if (msg == NULL) {
- isns_debug_esi("ESI call 0x%x timed out\n", xid);
- return;
- }
-
- /* FIXME: As a matter of security, we should probably
- * verify that the ESI response originated from the
- * portal we sent it to; or at least that it was authenticated
- * by the client we think we're talking to. */
-
- /* Get the portal */
- if (!isns_portal_from_attr_list(&portal_info,
- ISNS_TAG_PORTAL_IP_ADDRESS,
- ISNS_TAG_PORTAL_TCP_UDP_PORT,
- &msg->is_message_attrs)) {
- isns_debug_esi("Ignoring unintelligible ESI response\n");
- return;
- }
-
- if (!(esp = isns_esi_get_msg_portal(xid, &esi))) {
- isns_debug_esi("Ignoring unmatched ESI reply\n");
- return;
- }
-
- if (!isns_portal_equal(&esp->esp_portal, &portal_info)) {
- isns_warning("Faked ESI response for portal %s\n",
- isns_portal_string(&portal_info));
- return;
- }
-
- isns_debug_esi("Good ESI response from %s\n",
- isns_portal_string(&portal_info));
- isns_esi_restart(esp);
-
- /* Refresh the entity's registration timestamp */
- isns_object_set_uint64(esi->esi_object,
- ISNS_TAG_TIMESTAMP,
- time(NULL));
- isns_db_sync(isns_esi_server->is_db);
-}
-
-/*
- * Helper function to schedule the next timeout
- */
-static void
-isns_esi_schedule(int timeout)
-{
- isns_cancel_timer(isns_esi_transmit, NULL);
- isns_add_oneshot_timer(timeout, isns_esi_transmit, NULL);
-}
-
-/*
- * Register an entity for ESI monitoring.
- * This is called when reloading the database.
- */
-void
-isns_esi_register(isns_object_t *obj)
-{
- if (!isns_esi_find(obj))
- isns_esi_add_entity(obj);
- /* We do not call esi_schedule(0) here; that happens in
- * isns_esi_init already. */
-}
-
-/*
- * This callback is invoked whenever an object is added/removed/modified.
- * We use this to keep track of ESI portals and such.
- */
-void
-isns_esi_callback(const isns_db_event_t *ev, void *ptr)
-{
- isns_object_t *obj, *entity;
- isns_esi_t *esi;
- uint32_t event;
-
- obj = ev->ie_object;
- event = ev->ie_bits;
-
- if (obj->ie_flags & ISNS_OBJECT_PRIVATE)
- return;
-
- isns_debug_esi("isns_esi_callback(%p, 0x%x)\n", obj, event);
-
- if (ISNS_IS_ENTITY(obj)
- && (event & ISNS_SCN_OBJECT_ADDED_MASK)) {
- if (!isns_esi_find(obj))
- isns_esi_add_entity(obj);
- /* Schedule an immediate ESI timer run */
- isns_esi_schedule(0);
- return;
- }
-
- if (!(entity = isns_object_get_entity(obj)))
- return;
-
- esi = isns_esi_find(entity);
- if (esi != NULL)
- esi->esi_update = 1;
-
- /* Schedule an immediate ESI timer run */
- isns_esi_schedule(0);
-}