From: Ronnie Sahlberg <ronniesahlb...@gmail.com> iscsi client library : init.c This file contains functions to create a iscsi context, destroy a context, error reporting api, as well as basic functions to manipulate properties of an iscsi context.
... ./block/iscsi/ contains a copy of a general purpose iscsi client library which is aimed at providing a clientside api for iscsi for both qemu/kvm as well as otther scsi related utilities. As such, there is need to make merging across various consumers, qemu/kvm being one of many here, as easy as possible when features are added to the library. As such, no consumer/qemu specific code is used in this library as well as coding guidelined might not be adhered to 100% It is the intention that this library will be useful for many and that iscsi use spawned from this will flourish. Signed-off-by: Ronnie Sahlberg <ronniesahlb...@gmail.com> --- block/iscsi/init.c | 215 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 215 insertions(+), 0 deletions(-) create mode 100644 block/iscsi/init.c diff --git a/block/iscsi/init.c b/block/iscsi/init.c new file mode 100644 index 0000000..c6ed347 --- /dev/null +++ b/block/iscsi/init.c @@ -0,0 +1,215 @@ +/* + Copyright (C) 2010 by Ronnie Sahlberg <ronniesahlb...@gmail.com> + + 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, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <stdlib.h> +#include <stdarg.h> +#include <sys/types.h> +#include <unistd.h> +#include <time.h> +#include "iscsi.h" +#include "iscsi-private.h" +#include "slist.h" + + +struct iscsi_context * +iscsi_create_context(const char *initiator_name) +{ + struct iscsi_context *iscsi; + + iscsi = malloc(sizeof(struct iscsi_context)); + if (iscsi == NULL) { + return NULL; + } + + bzero(iscsi, sizeof(struct iscsi_context)); + + iscsi->initiator_name = strdup(initiator_name); + if (iscsi->initiator_name == NULL) { + free(iscsi); + return NULL; + } + + iscsi->fd = -1; + + /* use a "random" isid */ + srandom(getpid() ^ time(NULL)); + iscsi_set_random_isid(iscsi); + + return iscsi; +} + +int +iscsi_set_random_isid(struct iscsi_context *iscsi) +{ + iscsi->isid[0] = 0x80; + iscsi->isid[1] = random()&0xff; + iscsi->isid[2] = random()&0xff; + iscsi->isid[3] = random()&0xff; + iscsi->isid[4] = 0; + iscsi->isid[5] = 0; + + return 0; +} + +int +iscsi_set_alias(struct iscsi_context *iscsi, const char *alias) +{ + if (iscsi->is_loggedin != 0) { + iscsi_set_error(iscsi, "Already logged in when adding alias\n"); + return -2; + } + + if (iscsi->alias != NULL) { + free(discard_const(iscsi->alias)); + iscsi->alias = NULL; + } + + iscsi->alias = strdup(alias); + if (iscsi->alias == NULL) { + iscsi_set_error(iscsi, "Failed to allocate alias name\n"); + return -3; + } + + return 0; +} + +int +iscsi_set_targetname(struct iscsi_context *iscsi, const char *target_name) +{ + if (iscsi->is_loggedin != 0) { + iscsi_set_error(iscsi, "Already logged in when adding " + "targetname\n"); + return -2; + } + + if (iscsi->target_name != NULL) { + free(discard_const(iscsi->target_name)); + iscsi->target_name = NULL; + } + + iscsi->target_name = strdup(target_name); + if (iscsi->target_name == NULL) { + iscsi_set_error(iscsi, "Failed to allocate target name\n"); + return -3; + } + + return 0; +} + +int +iscsi_destroy_context(struct iscsi_context *iscsi) +{ + struct iscsi_pdu *pdu; + + if (iscsi == NULL) { + return 0; + } + if (iscsi->initiator_name != NULL) { + free(discard_const(iscsi->initiator_name)); + iscsi->initiator_name = NULL; + } + if (iscsi->target_name != NULL) { + free(discard_const(iscsi->target_name)); + iscsi->target_name = NULL; + } + if (iscsi->alias != NULL) { + free(discard_const(iscsi->alias)); + iscsi->alias = NULL; + } + if (iscsi->fd != -1) { + iscsi_disconnect(iscsi); + } + + if (iscsi->inbuf != NULL) { + free(iscsi->inbuf); + iscsi->inbuf = NULL; + iscsi->insize = 0; + iscsi->inpos = 0; + } + + while ((pdu = iscsi->outqueue)) { + SLIST_REMOVE(&iscsi->outqueue, pdu); + pdu->callback(iscsi, SCSI_STATUS_CANCELLED, NULL, + pdu->private_data); + iscsi_free_pdu(iscsi, pdu); + } + while ((pdu = iscsi->waitpdu)) { + SLIST_REMOVE(&iscsi->waitpdu, pdu); + pdu->callback(iscsi, SCSI_STATUS_CANCELLED, NULL, + pdu->private_data); + iscsi_free_pdu(iscsi, pdu); + } + + if (iscsi->error_string != NULL) { + free(iscsi->error_string); + } + + free(iscsi); + + return 0; +} + + + +void +iscsi_set_error(struct iscsi_context *iscsi, const char *error_string, ...) +{ + va_list ap; + char *str; + + va_start(ap, error_string); + if (vasprintf(&str, error_string, ap) < 0) { + /* not much we can do here */ + } + if (iscsi->error_string != NULL) { + free(iscsi->error_string); + } + iscsi->error_string = str; + va_end(ap); +} + + +char * +iscsi_get_error(struct iscsi_context *iscsi) +{ + return iscsi->error_string; +} + +int +iscsi_set_header_digest(struct iscsi_context *iscsi, + enum iscsi_header_digest header_digest) +{ + if (iscsi->is_loggedin) { + iscsi_set_error(iscsi, "trying to set header digest while " + "logged in\n"); + return -2; + } + + iscsi->want_header_digest = header_digest; + + return 0; +} + +int +iscsi_is_logged_in(struct iscsi_context *iscsi) +{ + return iscsi->is_loggedin; +} -- 1.7.3.1