|
Packit Service |
646995 |
/*
|
|
Packit Service |
646995 |
* Copyright (C) 2018 Red Hat, Inc.
|
|
Packit Service |
646995 |
*
|
|
Packit Service |
646995 |
* This program is free software: you can redistribute it and/or modify
|
|
Packit Service |
646995 |
* it under the terms of the GNU General Public License as published by
|
|
Packit Service |
646995 |
* the Free Software Foundation, either version 3 of the License, or
|
|
Packit Service |
646995 |
* (at your option) any later version.
|
|
Packit Service |
646995 |
*
|
|
Packit Service |
646995 |
* This program is distributed in the hope that it will be useful,
|
|
Packit Service |
646995 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
646995 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
646995 |
* GNU General Public License for more details.
|
|
Packit Service |
646995 |
*
|
|
Packit Service |
646995 |
* You should have received a copy of the GNU General Public License
|
|
Packit Service |
646995 |
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
Packit Service |
646995 |
*
|
|
Packit Service |
646995 |
* Author: Gris Ge <fge@redhat.com>
|
|
Packit Service |
646995 |
*/
|
|
Packit Service |
646995 |
#ifndef _GNU_SOURCE
|
|
Packit Service |
646995 |
#define _GNU_SOURCE
|
|
Packit Service |
646995 |
/* ^ For strerror_r() */
|
|
Packit Service |
646995 |
#endif
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
#include <stdlib.h>
|
|
Packit Service |
646995 |
#include <stdbool.h>
|
|
Packit Service |
646995 |
#include <inttypes.h>
|
|
Packit Service |
646995 |
#include <sys/types.h>
|
|
Packit Service |
646995 |
#include <sys/stat.h>
|
|
Packit Service |
646995 |
#include <unistd.h>
|
|
Packit Service |
646995 |
#include <errno.h>
|
|
Packit Service |
646995 |
#include <string.h>
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
#include "libopeniscsiusr/libopeniscsiusr.h"
|
|
Packit Service |
646995 |
#include "misc.h"
|
|
Packit Service |
646995 |
#include "node.h"
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
/* ptr is both input and output pointer.
|
|
Packit Service |
646995 |
* count is both input and output pointer.
|
|
Packit Service |
646995 |
* When success, both count and ptr will be updated.
|
|
Packit Service |
646995 |
* If fail, return LIBISCSI_ERR_NOMEM and no touch to old memory.
|
|
Packit Service |
646995 |
*/
|
|
Packit Service |
646995 |
static int _grow_node_array(struct iscsi_context *ctx,
|
|
Packit Service |
646995 |
struct iscsi_node ***nodes, uint32_t *count)
|
|
Packit Service |
646995 |
{
|
|
Packit Service |
646995 |
int rc = LIBISCSI_OK;
|
|
Packit Service |
646995 |
struct iscsi_node **tmp = NULL;
|
|
Packit Service |
646995 |
uint32_t i = 0;
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
_debug(ctx, "Growing node array from size %" PRIu32 " to %" PRIu32,
|
|
Packit Service |
646995 |
*count, *count * 2);
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
tmp = realloc(*nodes, *count * 2 * sizeof(struct iscsi_node *));
|
|
Packit Service |
646995 |
_alloc_null_check(ctx, tmp, rc, out);
|
|
Packit Service |
646995 |
for (i = *count; i < *count * 2; ++i)
|
|
Packit Service |
646995 |
tmp[i] = NULL;
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
*count *= 2;
|
|
Packit Service |
646995 |
*nodes = tmp;
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
out:
|
|
Packit Service |
646995 |
return rc;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
static int nodes_append(struct iscsi_context *ctx, struct iscsi_node ***nodes,
|
|
Packit Service |
646995 |
uint32_t *real_node_count, uint32_t *array_size,
|
|
Packit Service |
646995 |
struct iscsi_node *node)
|
|
Packit Service |
646995 |
{
|
|
Packit Service |
646995 |
int rc = LIBISCSI_OK;
|
|
Packit Service |
646995 |
if (*real_node_count >= *array_size)
|
|
Packit Service |
646995 |
_good(_grow_node_array(ctx, nodes, array_size), rc, out);
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
(*nodes)[(*real_node_count)++] = node;
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
out:
|
|
Packit Service |
646995 |
return rc;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
int iscsi_nodes_get(struct iscsi_context *ctx, struct iscsi_node ***nodes,
|
|
Packit Service |
646995 |
uint32_t *node_count)
|
|
Packit Service |
646995 |
{
|
|
Packit Service |
646995 |
int rc = LIBISCSI_OK;
|
|
Packit Service |
646995 |
struct dirent **namelist = NULL;
|
|
Packit Service |
646995 |
int n = 0;
|
|
Packit Service |
646995 |
int i = 0;
|
|
Packit Service |
646995 |
int j = 0;
|
|
Packit Service |
646995 |
int k = 0;
|
|
Packit Service |
646995 |
struct iscsi_node *node = NULL;
|
|
Packit Service |
646995 |
uint32_t real_node_count = 0;
|
|
Packit Service |
646995 |
const char *target_name = NULL;
|
|
Packit Service |
646995 |
const char *portal = NULL;
|
|
Packit Service |
646995 |
const char *iface_name = NULL;
|
|
Packit Service |
646995 |
struct dirent **namelist_portals = NULL;
|
|
Packit Service |
646995 |
int p = 0;
|
|
Packit Service |
646995 |
struct dirent **namelist_ifaces = NULL;
|
|
Packit Service |
646995 |
int f = 0;
|
|
Packit Service |
646995 |
char *target_path = NULL;
|
|
Packit Service |
646995 |
char *path = NULL;
|
|
Packit Service |
646995 |
struct stat path_stat;
|
|
Packit Service |
646995 |
char strerr_buff[_STRERR_BUFF_LEN];
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
assert(ctx != NULL);
|
|
Packit Service |
646995 |
assert(nodes != NULL);
|
|
Packit Service |
646995 |
assert(node_count != NULL);
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
*nodes = NULL;
|
|
Packit Service |
646995 |
*node_count = 0;
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
_good(_idbm_lock(ctx), rc, out);
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
_good(_scandir(ctx, NODE_CONFIG_DIR, &namelist, &n), rc, out);
|
|
Packit Service |
646995 |
_debug(ctx, "Got %d target from %s nodes folder", n, NODE_CONFIG_DIR);
|
|
Packit Service |
646995 |
*node_count = n & UINT32_MAX;
|
|
Packit Service |
646995 |
*nodes = (struct iscsi_node **) calloc(*node_count,
|
|
Packit Service |
646995 |
sizeof(struct iscsi_node *));
|
|
Packit Service |
646995 |
_alloc_null_check(ctx, *nodes, rc, out);
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
// New style of nodes folder:
|
|
Packit Service |
646995 |
// <target_name>/<address>,<port>,<tpgt>/<iface_name>
|
|
Packit Service |
646995 |
// Old style of nodes folder:
|
|
Packit Service |
646995 |
// <target_name>/<address>,<port>
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
for (i = 0; i < n; ++i) {
|
|
Packit Service |
646995 |
target_name = namelist[i]->d_name;
|
|
Packit Service |
646995 |
_good(_asprintf(&target_path, "%s/%s", NODE_CONFIG_DIR,
|
|
Packit Service |
646995 |
target_name), rc, out);
|
|
Packit Service |
646995 |
_good(_scandir(ctx, target_path, &namelist_portals, &p),
|
|
Packit Service |
646995 |
rc, out);
|
|
Packit Service |
646995 |
_debug(ctx, "Got %d portals from %s folder", p, target_path);
|
|
Packit Service |
646995 |
free(target_path);
|
|
Packit Service |
646995 |
target_path = NULL;
|
|
Packit Service |
646995 |
for (j = 0; j < p; ++j) {
|
|
Packit Service |
646995 |
portal = namelist_portals[j]->d_name;
|
|
Packit Service |
646995 |
_good(_asprintf(&path, "%s/%s/%s", NODE_CONFIG_DIR,
|
|
Packit Service |
646995 |
target_name, portal), rc, out);
|
|
Packit Service |
646995 |
if (stat(path, &path_stat) != 0) {
|
|
Packit Service |
646995 |
_warn(ctx, "Cannot stat path '%s': %d, %s",
|
|
Packit Service |
646995 |
path, errno,
|
|
Packit Service |
646995 |
_strerror(errno, strerr_buff));
|
|
Packit Service |
646995 |
continue;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
if (S_ISREG(path_stat.st_mode)) {
|
|
Packit Service |
646995 |
// Old style of node
|
|
Packit Service |
646995 |
_good(_idbm_node_get(ctx, target_name, portal,
|
|
Packit Service |
646995 |
NULL, &node),
|
|
Packit Service |
646995 |
rc, out);
|
|
Packit Service |
646995 |
_good(nodes_append(ctx, nodes,
|
|
Packit Service |
646995 |
&real_node_count,
|
|
Packit Service |
646995 |
node_count, node),
|
|
Packit Service |
646995 |
rc, out);
|
|
Packit Service |
646995 |
continue;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
if (! S_ISDIR(path_stat.st_mode)) {
|
|
Packit Service |
646995 |
_warn(ctx, "Invalid iSCSI node configuration "
|
|
Packit Service |
646995 |
"file %s, it should be a file or "
|
|
Packit Service |
646995 |
"directory.", path);
|
|
Packit Service |
646995 |
rc = LIBISCSI_ERR_IDBM;
|
|
Packit Service |
646995 |
goto out;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
_good(_scandir(ctx, path, &namelist_ifaces, &f), rc,
|
|
Packit Service |
646995 |
out);
|
|
Packit Service |
646995 |
_debug(ctx, "Got %d ifaces from %s folder", f, path);
|
|
Packit Service |
646995 |
for (k = 0; k < f; ++k) {
|
|
Packit Service |
646995 |
iface_name = namelist_ifaces[k]->d_name;
|
|
Packit Service |
646995 |
_good(_idbm_node_get(ctx, target_name, portal,
|
|
Packit Service |
646995 |
iface_name, &node),
|
|
Packit Service |
646995 |
rc, out);
|
|
Packit Service |
646995 |
_good(nodes_append(ctx, nodes,
|
|
Packit Service |
646995 |
&real_node_count,
|
|
Packit Service |
646995 |
node_count, node),
|
|
Packit Service |
646995 |
rc, out);
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
free(path);
|
|
Packit Service |
646995 |
path = NULL;
|
|
Packit Service |
646995 |
_scandir_free(namelist_ifaces, f);
|
|
Packit Service |
646995 |
namelist_ifaces = NULL;
|
|
Packit Service |
646995 |
f = 0;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
_scandir_free(namelist_portals, p);
|
|
Packit Service |
646995 |
namelist_portals = NULL;
|
|
Packit Service |
646995 |
p = 0;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
*node_count = real_node_count;
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
out:
|
|
Packit Service |
646995 |
free(path);
|
|
Packit Service |
646995 |
free(target_path);
|
|
Packit Service |
646995 |
_scandir_free(namelist, n);
|
|
Packit Service |
646995 |
_scandir_free(namelist_portals, p);
|
|
Packit Service |
646995 |
_scandir_free(namelist_ifaces, f);
|
|
Packit Service |
646995 |
_idbm_unlock(ctx);
|
|
Packit Service |
646995 |
if (rc != LIBISCSI_OK) {
|
|
Packit Service |
646995 |
iscsi_nodes_free(*nodes, *node_count);
|
|
Packit Service |
646995 |
*nodes = NULL;
|
|
Packit Service |
646995 |
*node_count = 0;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
return rc;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
void iscsi_nodes_free(struct iscsi_node **nodes, uint32_t node_count)
|
|
Packit Service |
646995 |
{
|
|
Packit Service |
646995 |
uint32_t i = 0;
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
if ((nodes == NULL) || (node_count == 0))
|
|
Packit Service |
646995 |
return;
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
for (i = 0; i < node_count; ++i)
|
|
Packit Service |
646995 |
iscsi_node_free(nodes[i]);
|
|
Packit Service |
646995 |
free (nodes);
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
void iscsi_node_free(struct iscsi_node *node)
|
|
Packit Service |
646995 |
{
|
|
Packit Service |
646995 |
free(node);
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
const char *iscsi_node_dump_config(struct iscsi_node *node, bool show_secret)
|
|
Packit Service |
646995 |
{
|
|
Packit Service |
646995 |
FILE *f = NULL;
|
|
Packit Service |
646995 |
char *buff = NULL;
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
assert(node != NULL);
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
buff = calloc(1, IDBM_DUMP_SIZE);
|
|
Packit Service |
646995 |
if (buff == NULL)
|
|
Packit Service |
646995 |
return NULL;
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
f = fmemopen(buff, IDBM_DUMP_SIZE - 1, "w");
|
|
Packit Service |
646995 |
if (f == NULL) {
|
|
Packit Service |
646995 |
free(buff);
|
|
Packit Service |
646995 |
return NULL;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
_idbm_node_print(node, f, show_secret);
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
fclose(f);
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
return buff;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
void iscsi_node_print_config(struct iscsi_node *node, bool show_secret)
|
|
Packit Service |
646995 |
{
|
|
Packit Service |
646995 |
assert(node != NULL);
|
|
Packit Service |
646995 |
_idbm_node_print(node, stdout, show_secret);
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
// TODO(Gris Ge): Convert below duplicated codes to macros.
|
|
Packit Service |
646995 |
bool iscsi_node_conn_is_ipv6(struct iscsi_node *node)
|
|
Packit Service |
646995 |
{
|
|
Packit Service |
646995 |
assert(node != NULL);
|
|
Packit Service |
646995 |
return node->conn.is_ipv6;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
const char *iscsi_node_conn_address_get(struct iscsi_node *node)
|
|
Packit Service |
646995 |
{
|
|
Packit Service |
646995 |
assert(node != NULL);
|
|
Packit Service |
646995 |
return node->conn.address;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
uint32_t iscsi_node_conn_port_get(struct iscsi_node *node)
|
|
Packit Service |
646995 |
{
|
|
Packit Service |
646995 |
assert(node != NULL);
|
|
Packit Service |
646995 |
return node->conn.port;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
int32_t iscsi_node_tpgt_get(struct iscsi_node *node)
|
|
Packit Service |
646995 |
{
|
|
Packit Service |
646995 |
assert(node != NULL);
|
|
Packit Service |
646995 |
return node->tpgt;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
const char *iscsi_node_target_name_get(struct iscsi_node *node)
|
|
Packit Service |
646995 |
{
|
|
Packit Service |
646995 |
assert(node != NULL);
|
|
Packit Service |
646995 |
return node->target_name;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
const char *iscsi_node_iface_name_get(struct iscsi_node *node)
|
|
Packit Service |
646995 |
{
|
|
Packit Service |
646995 |
assert(node != NULL);
|
|
Packit Service |
646995 |
return node->iface.name;
|
|
Packit Service |
646995 |
}
|
|
Packit Service |
646995 |
|
|
Packit Service |
646995 |
const char *iscsi_node_portal_get(struct iscsi_node *node)
|
|
Packit Service |
646995 |
{
|
|
Packit Service |
646995 |
assert(node != NULL);
|
|
Packit Service |
646995 |
return node->portal;
|
|
Packit Service |
646995 |
}
|