}
/**
+ * lease enumerator
+ */
+typedef struct {
+ /** implemented enumerator interface */
+ enumerator_t public;
+ /** inner hash-table enumerator */
+ enumerator_t *inner;
+ /** enumerated pool */
+ pool_t *pool;
+ /** mutex to unlock on destruction */
+ mutex_t *mutex;
+ /** currently enumerated lease address */
+ host_t *current;
+} lease_enumerator_t;
+
+/**
+ * Implementation of lease_enumerator_t.enumerate
+ */
+static bool lease_enumerate(lease_enumerator_t *this, identification_t **id_out,
+ host_t **addr_out, bool *online)
+{
+ identification_t *id;
+ uintptr_t offset;
+
+ DESTROY_IF(this->current);
+ this->current = NULL;
+
+ if (this->inner->enumerate(this->inner, &id, NULL))
+ {
+ offset = (uintptr_t)this->pool->online->get(this->pool->online, id);
+ if (offset)
+ {
+ *id_out = id;
+ *addr_out = this->current = offset2host(this->pool, offset);
+ *online = TRUE;
+ return TRUE;
+ }
+ offset = (uintptr_t)this->pool->offline->get(this->pool->offline, id);
+ if (offset)
+ {
+ *id_out = id;
+ *addr_out = this->current = offset2host(this->pool, offset);
+ *online = FALSE;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * Implementation of lease_enumerator_t.destroy
+ */
+static void lease_enumerator_destroy(lease_enumerator_t *this)
+{
+ DESTROY_IF(this->current);
+ this->inner->destroy(this->inner);
+ this->mutex->unlock(this->mutex);
+ free(this);
+}
+
+/**
+ * Implementation of stroke_attribute_t.create_lease_enumerator
+ */
+static enumerator_t* create_lease_enumerator(private_stroke_attribute_t *this,
+ char *pool)
+{
+ lease_enumerator_t *enumerator;
+
+ this->mutex->lock(this->mutex);
+ enumerator = malloc_thing(lease_enumerator_t);
+ enumerator->pool = find_pool(this, pool);
+ if (!enumerator->pool)
+ {
+ this->mutex->unlock(this->mutex);
+ free(enumerator);
+ return NULL;
+ }
+ enumerator->public.enumerate = (void*)lease_enumerate;
+ enumerator->public.destroy = (void*)lease_enumerator_destroy;
+ enumerator->inner = enumerator->pool->ids->create_enumerator(enumerator->pool->ids);
+ enumerator->mutex = this->mutex;
+ enumerator->current = NULL;
+ return &enumerator->public;
+}
+
+/**
* Implementation of stroke_attribute_t.destroy
*/
static void destroy(private_stroke_attribute_t *this)
this->public.add_pool = (void(*)(stroke_attribute_t*, stroke_msg_t *msg))add_pool;
this->public.del_pool = (void(*)(stroke_attribute_t*, stroke_msg_t *msg))del_pool;
this->public.create_pool_enumerator = (enumerator_t*(*)(stroke_attribute_t*))create_pool_enumerator;
+ this->public.create_lease_enumerator = (enumerator_t*(*)(stroke_attribute_t*, char *pool))create_lease_enumerator;
this->public.destroy = (void(*)(stroke_attribute_t*))destroy;
this->pools = linked_list_create();
- this->mutex = mutex_create(MUTEX_DEFAULT);
+ this->mutex = mutex_create(MUTEX_RECURSIVE);
return &this->public;
}
enumerator_t* (*create_pool_enumerator)(stroke_attribute_t *this);
/**
+ * Create an enumerator over the leases of a pool.
+ *
+ * Enumerator enumerates over
+ * identification_t *id, host_t *address, bool online
+ *
+ * @param pool name of the pool to enumerate
+ * @return enumerator, NULL if pool not found
+ */
+ enumerator_t* (*create_lease_enumerator)(stroke_attribute_t *this,
+ char *pool);
+ /**
* Destroy a stroke_attribute instance.
*/
void (*destroy)(stroke_attribute_t *this);
}
/**
+ * Print leases of a single pool
+ */
+static void pool_leases(private_stroke_list_t *this, FILE *out, char *pool,
+ host_t *address, u_int size, u_int online, u_int offline)
+{
+ enumerator_t *enumerator;
+ identification_t *id;
+ host_t *lease;
+ bool on;
+ int found = 0;
+
+ fprintf(out, "Leases in pool '%s', usage: %lu/%lu, %lu online\n",
+ pool, online + offline, size, online);
+ enumerator = this->attribute->create_lease_enumerator(this->attribute, pool);
+ while (enumerator && enumerator->enumerate(enumerator, &id, &lease, &on))
+ {
+ if (!address || address->ip_equals(address, lease))
+ {
+ fprintf(out, " %15H %s '%D'\n",
+ lease, on ? "online" : "offline", id);
+ found++;
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (!found)
+ {
+ fprintf(out, " no matching leases found\n");
+ }
+}
+
+/**
+ * Implementation of stroke_list_t.leases
+ */
+static void leases(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out)
+{
+ enumerator_t *enumerator;
+ u_int size, offline, online;
+ host_t *address = NULL;
+ char *pool;
+ int found = 0;
+
+ if (msg->leases.address)
+ {
+ address = host_create_from_string(msg->leases.address, 0);
+ }
+
+ enumerator = this->attribute->create_pool_enumerator(this->attribute);
+ while (enumerator->enumerate(enumerator, &pool, &size, &online, &offline))
+ {
+ if (!msg->leases.pool || streq(msg->leases.pool, pool))
+ {
+ pool_leases(this, out, pool, address, size, online, offline);
+ found++;
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (!found)
+ {
+ if (msg->leases.pool)
+ {
+ fprintf(out, "pool '%s' not found\n", msg->leases.pool);
+ }
+ else
+ {
+ fprintf(out, "no pools found\n");
+ }
+ }
+ DESTROY_IF(address);
+}
+
+/**
* Implementation of stroke_list_t.destroy
*/
static void destroy(private_stroke_list_t *this)
this->public.list = (void(*)(stroke_list_t*, stroke_msg_t *msg, FILE *out))list;
this->public.status = (void(*)(stroke_list_t*, stroke_msg_t *msg, FILE *out,bool))status;
+ this->public.leases = (void(*)(stroke_list_t*, stroke_msg_t *msg, FILE *out))leases;
this->public.destroy = (void(*)(stroke_list_t*))destroy;
this->uptime = time(NULL);
void (*status)(stroke_list_t *this, stroke_msg_t *msg, FILE *out, bool all);
/**
- * Destroy a stroke_list instance.
- */
- void (*destroy)(stroke_list_t *this);
+ * Log pool leases to stroke console.
+ *
+ * @param msg stroke message
+ * @param out stroke console stream
+ */
+ void (*leases)(stroke_list_t *this, stroke_msg_t *msg, FILE *out);
+
+ /**
+ * Destroy a stroke_list instance.
+ */
+ void (*destroy)(stroke_list_t *this);
};
/**
CERT_X509_OCSP_RESPONSE);
}
+/**
+ * list pool leases
+ */
+static void stroke_leases(private_stroke_socket_t *this,
+ stroke_msg_t *msg, FILE *out)
+{
+ pop_string(msg, &msg->leases.pool);
+ pop_string(msg, &msg->leases.address);
+
+ this->list->leases(this->list, msg, out);
+}
+
debug_t get_group_from_name(char *type)
{
if (strcasecmp(type, "any") == 0) return DBG_ANY;
case STR_PURGE:
stroke_purge(this, msg, out);
break;
+ case STR_LEASES:
+ stroke_leases(this, msg, out);
+ break;
default:
DBG1(DBG_CFG, "received unknown stroke");
break;
echo " listcacerts|listaacerts|listocspcerts [--utc]"
echo " listacerts|listgroups|listcainfos [--utc]"
echo " listcrls|listocsp|listcards|listall [--utc]"
+ echo " listpool [<poolname> [<address>]]"
echo " rereadsecrets|rereadgroups"
echo " rereadcacerts|rereadaacerts|rereadocspcerts"
echo " rereadacerts|rereadcrls|rereadall"
exit 7
fi
;;
+leases)
+ op="$1"
+ rc=7
+ shift
+ if [ -e $IPSEC_CHARON_PID ]
+ then
+ case "$#" in
+ 0) $IPSEC_STROKE "$op" ;;
+ 1) $IPSEC_STROKE "$op" "$1" ;;
+ *) $IPSEC_STROKE "$op" "$1" "$2" ;;
+ esac
+ rc="$?"
+ fi
+ exit "$rc"
+ ;;
listalgs|\listpubkeys|\
listcerts|listcacerts|listaacerts|\
listacerts|listgroups|listocspcerts|\
return send_stroke_msg(&msg);
}
+static int leases(stroke_keyword_t kw, char *pool, char *address)
+{
+
+ stroke_msg_t msg;
+
+ msg.type = STR_LEASES;
+ msg.length = offsetof(stroke_msg_t, buffer);
+ msg.leases.pool = push_string(&msg, pool);
+ msg.leases.address = push_string(&msg, address);
+ return send_stroke_msg(&msg);
+}
+
static int set_loglevel(char *type, u_int level)
{
stroke_msg_t msg;
printf(" stroke rereadsecrets|rereadcrls|rereadall\n");
printf(" Purge ocsp cache entries:\n");
printf(" stroke purgeocsp\n");
+ printf(" Show leases of a pool:\n");
+ printf(" stroke leases [POOL [ADDRESS]]\n");
exit_error(error);
}
case STROKE_PURGE_OCSP:
res = purge(token->kw);
break;
+ case STROKE_LEASES:
+ res = leases(token->kw, argc > 2 ? argv[2] : NULL,
+ argc > 3 ? argv[3] : NULL);
+ break;
default:
exit_usage(NULL);
}
STROKE_REREAD_ACERTS,
STROKE_REREAD_CRLS,
STROKE_REREAD_ALL,
- STROKE_PURGE_OCSP
+ STROKE_PURGE_OCSP,
+ STROKE_LEASES
} stroke_keyword_t;
#define STROKE_LIST_FIRST STROKE_LIST_PUBKEYS
rereadsecrets, STROKE_REREAD_SECRETS
rereadcacerts, STROKE_REREAD_CACERTS
rereadocspcerts, STROKE_REREAD_OCSPCERTS
-rereadaacerts, STROKE_REREAD_AACERTS,
-rereadacerts, STROKE_REREAD_ACERTS,
+rereadaacerts, STROKE_REREAD_AACERTS
+rereadacerts, STROKE_REREAD_ACERTS
rereadcrls, STROKE_REREAD_CRLS
rereadall, STROKE_REREAD_ALL
purgeocsp, STROKE_PURGE_OCSP
+leases, STROKE_LEASES
/* reread various objects */
STR_REREAD,
/* purge various objects */
- STR_PURGE
+ STR_PURGE,
+ /* show pool leases */
+ STR_LEASES,
/* more to come */
} type;
struct {
purge_flag_t flags;
} purge;
+
+ /* data for STR_LEASES */
+ struct {
+ char *pool;
+ char *address;
+ } leases;
};
char buffer[STROKE_BUF_LEN];
};