diff --git a/include/iscsi.h b/include/iscsi.h index a197d37..30917a0 100644 --- a/include/iscsi.h +++ b/include/iscsi.h @@ -547,6 +547,17 @@ EXTERN int iscsi_logout_async(struct iscsi_context *iscsi, iscsi_command_cb cb, EXTERN int iscsi_logout_sync(struct iscsi_context *iscsi); +struct iscsi_target_portal { + struct iscsi_target_portal *next; + const char *portal; +}; + +struct iscsi_discovery_address { + struct iscsi_discovery_address *next; + const char *target_name; + struct iscsi_target_portal *portals; +}; + /* * Asynchronous call to perform an ISCSI discovery. * @@ -570,16 +581,23 @@ EXTERN int iscsi_logout_sync(struct iscsi_context *iscsi); EXTERN int iscsi_discovery_async(struct iscsi_context *iscsi, iscsi_command_cb cb, void *private_data); -struct iscsi_target_portal { - struct iscsi_target_portal *next; - const char *portal; -}; +/* + * Synchronous call to perform an ISCSI discovery. + * + * discoveries can only be done on connected and logged in discovery sessions. + * + * Returns: + * NULL if there was an error. + * struct iscsi_discovery_address* if the discovery was successfull. + * The data returned must be released by calling iscsi_free_discovery_data. + */ +EXTERN struct iscsi_discovery_address *iscsi_discovery_sync( + struct iscsi_context *iscsi); -struct iscsi_discovery_address { - struct iscsi_discovery_address *next; - const char *target_name; - struct iscsi_target_portal *portals; -}; +/* Free the discovery data structures returned by iscsi_discovery_sync + */ +EXTERN void iscsi_free_discovery_data(struct iscsi_context *iscsi, + struct iscsi_discovery_address *da); /* * Asynchronous call to perform an ISCSI NOP-OUT call diff --git a/lib/libiscsi.def b/lib/libiscsi.def index 1bc3318..81ebe60 100644 --- a/lib/libiscsi.def +++ b/lib/libiscsi.def @@ -8,6 +8,8 @@ iscsi_destroy_context iscsi_destroy_url iscsi_disconnect iscsi_discovery_async +iscsi_discovery_sync +iscsi_free_discovery_data iscsi_full_connect_async iscsi_full_connect_sync iscsi_get_error diff --git a/lib/libiscsi.syms b/lib/libiscsi.syms index 2fd83de..b3f3cac 100644 --- a/lib/libiscsi.syms +++ b/lib/libiscsi.syms @@ -6,6 +6,8 @@ iscsi_destroy_context iscsi_destroy_url iscsi_disconnect iscsi_discovery_async +iscsi_discovery_sync +iscsi_free_discovery_data iscsi_full_connect_async iscsi_full_connect_sync iscsi_get_error diff --git a/lib/sync.c b/lib/sync.c index d7342fa..9fb78e7 100644 --- a/lib/sync.c +++ b/lib/sync.c @@ -42,15 +42,16 @@ #include "scsi-lowlevel.h" struct iscsi_sync_state { - int finished; - int status; - struct scsi_task *task; + int finished; + int status; + void *ptr; + struct scsi_task *task; }; static void event_loop(struct iscsi_context *iscsi, struct iscsi_sync_state *state) { - struct pollfd pfd; + struct pollfd pfd; int ret; while (state->finished == 0) { @@ -1768,3 +1769,77 @@ iscsi_modesense10_sync(struct iscsi_context *iscsi, int lun, int llbaa, int dbd, return state.task; } + +void iscsi_free_discovery_data(struct iscsi_context *iscsi _U_, + struct iscsi_discovery_address *da) +{ + while (da) { + struct iscsi_discovery_address *danext = da->next; + + while (da->portals) { + struct iscsi_target_portal *ponext = da->portals->next; + free(discard_const(da->portals->portal)); + free(da->portals); + da->portals = ponext; + } + free(discard_const(da->target_name)); + free(da); + da = danext; + } +} + +static void +iscsi_discovery_cb(struct iscsi_context *iscsi _U_, int status, + void *command_data, void *private_data) +{ + struct iscsi_sync_state *state = private_data; + struct iscsi_discovery_address *da; + struct iscsi_discovery_address *dahead = NULL; + struct iscsi_target_portal *po; + + for (da = command_data; da != NULL; da = da->next) { + struct iscsi_discovery_address *datmp; + + datmp = malloc(sizeof(struct iscsi_discovery_address)); + memset(datmp, 0, sizeof(struct iscsi_discovery_address)); + datmp->target_name = strdup(da->target_name); + datmp->next = dahead; + dahead = datmp; + + for (po = da->portals; po != NULL; po = po->next) { + struct iscsi_target_portal *potmp; + + potmp = malloc(sizeof(struct iscsi_target_portal)); + memset(potmp, 0, sizeof(struct iscsi_target_portal)); + potmp->portal = strdup(po->portal); + + potmp->next = dahead->portals; + dahead->portals = potmp; + } + } + + if (state != NULL) { + state->status = status; + state->finished = 1; + state->ptr = dahead; + } +} + +struct iscsi_discovery_address * +iscsi_discovery_sync(struct iscsi_context *iscsi) +{ + struct iscsi_sync_state state; + + memset(&state, 0, sizeof(state)); + + if (iscsi_discovery_async(iscsi, iscsi_discovery_cb, &state) != 0) { + iscsi_set_error(iscsi, "Failed to run discovery. %s", + iscsi_get_error(iscsi)); + printf("async discovery call failed\n"); + return NULL; + } + + event_loop(iscsi, &state); + + return state.ptr; +}