summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Leech <leech@pobox.com>2018-06-18 14:04:21 -0700
committerGitHub <noreply@github.com>2018-06-18 14:04:21 -0700
commit92a7cfea36592b434725fa59daa8dacd52aaf45c (patch)
tree17485c831b5fc5a60966a3035e5daf2a0448918a
parent0cfebb10d29382ac1058c950a60a946c28b01e53 (diff)
parent4f9ca4a6ae635ac26be761780f8ceb54ea90ec96 (diff)
downloadopen-iscsi-92a7cfea36592b434725fa59daa8dacd52aaf45c.tar.gz
Merge pull request #110 from cleech/libopeniscsiusr_fixes
Libopeniscsiusr fixes
-rw-r--r--libopeniscsiusr/idbm.c22
-rw-r--r--libopeniscsiusr/idbm_fields.h1
-rw-r--r--libopeniscsiusr/iface.c126
-rw-r--r--libopeniscsiusr/iface.h7
-rw-r--r--libopeniscsiusr/misc.h12
-rw-r--r--libopeniscsiusr/node.c23
-rw-r--r--libopeniscsiusr/session.c20
-rw-r--r--libopeniscsiusr/sysfs.c154
-rw-r--r--libopeniscsiusr/sysfs.h10
9 files changed, 233 insertions, 142 deletions
diff --git a/libopeniscsiusr/idbm.c b/libopeniscsiusr/idbm.c
index b881eab..2639430 100644
--- a/libopeniscsiusr/idbm.c
+++ b/libopeniscsiusr/idbm.c
@@ -370,6 +370,8 @@ static int _idbm_iface_rec_link(struct iscsi_iface *iface,
_CAN_MODIFY);
_rec_str(IFACE_IPADDR, recs, iface, ipaddress, IDBM_SHOW, num,
_CAN_MODIFY);
+ _rec_uint8(IFACE_PREFIX_LEN, recs, iface, prefix_len, IDBM_SHOW, num,
+ _CAN_MODIFY);
_rec_str(IFACE_HWADDR, recs, iface, hwaddress, IDBM_SHOW, num,
_CAN_MODIFY);
_rec_str(IFACE_TRANSPORTNAME, recs, iface, transport_name, IDBM_SHOW,
@@ -820,7 +822,7 @@ int _idbm_iface_get(struct iscsi_context *ctx, const char *iface_name, struct
iscsi_iface **iface)
{
int rc = LIBISCSI_OK;
- char conf_path[PATH_MAX];
+ char *conf_path = NULL;
struct idbm_rec *recs = NULL;
assert(iface != NULL);
@@ -831,7 +833,8 @@ int _idbm_iface_get(struct iscsi_context *ctx, const char *iface_name, struct
if (iface_name == NULL)
goto out;
- snprintf(conf_path, PATH_MAX, "%s/%s", IFACE_CONFIG_DIR, iface_name);
+ _good(_asprintf(&conf_path, "%s/%s", IFACE_CONFIG_DIR, iface_name),
+ rc, out);
*iface = calloc(1, sizeof(struct iscsi_iface));
_alloc_null_check(ctx, *iface, rc, out);
@@ -839,6 +842,9 @@ int _idbm_iface_get(struct iscsi_context *ctx, const char *iface_name, struct
snprintf((*iface)->name, sizeof((*iface)->name)/sizeof(char),
"%s", iface_name);
+ if (strstr(iface_name, "ipv6"))
+ (*iface)->is_ipv6 = true;
+
recs = _idbm_recs_alloc();
_alloc_null_check(ctx, recs, rc, out);
@@ -859,6 +865,7 @@ out:
iscsi_iface_free(*iface);
*iface = NULL;
}
+ free(conf_path);
_idbm_recs_free(recs);
return rc;
}
@@ -1018,7 +1025,7 @@ int _idbm_node_get(struct iscsi_context *ctx, const char *target_name,
struct iscsi_node **node)
{
int rc = LIBISCSI_OK;
- char conf_path[PATH_MAX];
+ char *conf_path = NULL;
struct idbm_rec *recs = NULL;
assert(node != NULL);
@@ -1030,11 +1037,11 @@ int _idbm_node_get(struct iscsi_context *ctx, const char *target_name,
goto out;
if (iface_name == NULL) // old style of config
- snprintf(conf_path, PATH_MAX, "%s/%s/%s", NODE_CONFIG_DIR,
- target_name, portal);
+ _good(_asprintf(&conf_path, "%s/%s/%s", NODE_CONFIG_DIR,
+ target_name, portal), rc, out);
else
- snprintf(conf_path, PATH_MAX, "%s/%s/%s/%s", NODE_CONFIG_DIR,
- target_name, portal, iface_name);
+ _good(_asprintf(&conf_path, "%s/%s/%s/%s", NODE_CONFIG_DIR,
+ target_name, portal, iface_name), rc, out);
*node = calloc(1, sizeof(struct iscsi_node));
_alloc_null_check(ctx, *node, rc, out);
@@ -1078,6 +1085,7 @@ out:
iscsi_node_free(*node);
*node = NULL;
}
+ free(conf_path);
_idbm_recs_free(recs);
return rc;
}
diff --git a/libopeniscsiusr/idbm_fields.h b/libopeniscsiusr/idbm_fields.h
index 090c4f9..3b28089 100644
--- a/libopeniscsiusr/idbm_fields.h
+++ b/libopeniscsiusr/idbm_fields.h
@@ -29,6 +29,7 @@
#define IFACE_ISID "iface.isid"
#define IFACE_BOOT_PROTO "iface.bootproto"
#define IFACE_IPADDR "iface.ipaddress"
+#define IFACE_PREFIX_LEN "iface.prefix_len"
#define IFACE_SUBNET_MASK "iface.subnet_mask"
#define IFACE_GATEWAY "iface.gateway"
#define IFACE_PRIMARY_DNS "iface.primary_dns"
diff --git a/libopeniscsiusr/iface.c b/libopeniscsiusr/iface.c
index 955395d..e2355bc 100644
--- a/libopeniscsiusr/iface.c
+++ b/libopeniscsiusr/iface.c
@@ -89,14 +89,13 @@ _iscsi_getter_func_gen(iscsi_iface, port_speed, const char *);
_iscsi_getter_func_gen(iscsi_iface, name, const char *);
int _iscsi_iface_get_from_sysfs(struct iscsi_context *ctx, uint32_t host_id,
- uint32_t sid, struct iscsi_iface **iface)
+ uint32_t sid, char *iface_kern_id,
+ struct iscsi_iface **iface)
{
int rc = LIBISCSI_OK;
char *sysfs_se_dir_path = NULL;
char *sysfs_sh_dir_path = NULL;
char *sysfs_scsi_host_dir_path = NULL;
- char *sysfs_iface_dir_path = NULL;
- char iface_kern_id[PATH_MAX];
char proc_name[ISCSI_TRANSPORT_NAME_MAXLEN];
struct iscsi_iface **ifaces = NULL;
uint32_t iface_count = 0;
@@ -112,21 +111,15 @@ int _iscsi_iface_get_from_sysfs(struct iscsi_context *ctx, uint32_t host_id,
*iface = NULL;
if (sid != 0) {
- sysfs_se_dir_path = malloc(PATH_MAX);
- _alloc_null_check(ctx, sysfs_se_dir_path, rc, out);
- snprintf(sysfs_se_dir_path, PATH_MAX, "%s/session%" PRIu32,
- _ISCSI_SYS_SESSION_DIR, sid);
+ _good(_asprintf(&sysfs_se_dir_path, "%s/session%" PRIu32,
+ _ISCSI_SYS_SESSION_DIR, sid), rc, out);
}
- sysfs_sh_dir_path = malloc(PATH_MAX);
- _alloc_null_check(ctx, sysfs_sh_dir_path, rc, out);
- snprintf(sysfs_sh_dir_path, PATH_MAX, "%s/host%" PRIu32,
- _ISCSI_SYS_HOST_DIR, host_id);
+ _good(_asprintf(&sysfs_sh_dir_path, "%s/host%" PRIu32,
+ _ISCSI_SYS_HOST_DIR, host_id),rc, out);
- sysfs_scsi_host_dir_path = malloc(PATH_MAX);
- _alloc_null_check(ctx, sysfs_scsi_host_dir_path, rc, out);
- snprintf(sysfs_scsi_host_dir_path, PATH_MAX, "%s/host%" PRIu32,
- _SCSI_SYS_HOST_DIR, host_id);
+ _good(_asprintf(&sysfs_scsi_host_dir_path, "%s/host%" PRIu32,
+ _SCSI_SYS_HOST_DIR, host_id), rc, out);
*iface = (struct iscsi_iface *) calloc(1, sizeof(struct iscsi_iface));
_alloc_null_check(ctx, *iface, rc, out);
@@ -195,8 +188,7 @@ int _iscsi_iface_get_from_sysfs(struct iscsi_context *ctx, uint32_t host_id,
(*iface)->name,
sizeof((*iface)->name)/sizeof(char), "");
- rc = _iscsi_iface_kern_id_of_host_id(ctx, host_id, iface_kern_id);
- if (rc == LIBISCSI_OK) {
+ if (iface_kern_id != NULL) {
_good(_fill_hw_iface_from_sys(ctx, *iface, iface_kern_id),
rc, out);
} else {
@@ -263,11 +255,57 @@ out:
free(sysfs_se_dir_path);
free(sysfs_sh_dir_path);
free(sysfs_scsi_host_dir_path);
- free(sysfs_iface_dir_path);
iscsi_ifaces_free(ifaces, iface_count);
return rc;
}
+/* create all ifaces for a host from sysfs */
+int _iscsi_ifaces_get_from_sysfs(struct iscsi_context *ctx, uint32_t host_id,
+ struct iscsi_iface ***ifaces, uint32_t *iface_count)
+{
+ int rc = LIBISCSI_OK;
+ char **iface_kern_ids = NULL;
+ uint32_t i = 0;
+
+ assert(ctx != NULL);
+ assert(ifaces != NULL);
+
+ *ifaces = NULL;
+ *iface_count = 0;
+
+ _good(_iscsi_iface_kern_ids_of_host_id(ctx, host_id, &iface_kern_ids, iface_count),
+ rc, out);
+ if (*iface_count > 0) {
+ *ifaces = (struct iscsi_iface **) calloc(*iface_count,
+ sizeof(struct iscsi_iface *));
+ _alloc_null_check(ctx, *ifaces, rc, out);
+ for (i = 0; i < *iface_count; i++) {
+ _good(_iscsi_iface_get_from_sysfs(ctx, host_id, 0,
+ iface_kern_ids[i], &(*ifaces)[i]), rc, out);
+ }
+ } else {
+ /* if there's no iface exported in sysfs,
+ * we should still be able to create one record per host */
+ *ifaces = (struct iscsi_iface **) calloc(1, sizeof(struct iscsi_iface *));
+ _alloc_null_check(ctx, *ifaces, rc, out);
+ *iface_count = 1;
+ _good(_iscsi_iface_get_from_sysfs(ctx, host_id, 0, NULL, &(*ifaces)[0]), rc, out);
+ }
+out:
+ if (iface_kern_ids != NULL) {
+ for (i = 0; i < *iface_count; i++) {
+ free(iface_kern_ids[i]);
+ }
+ free(iface_kern_ids);
+ }
+ if (rc != LIBISCSI_OK) {
+ iscsi_ifaces_free(*ifaces, *iface_count);
+ *ifaces = NULL;
+ *iface_count = 0;
+ }
+ return rc;
+}
+
int iscsi_default_iface_setup(struct iscsi_context *ctx)
{
int rc = LIBISCSI_OK;
@@ -276,12 +314,14 @@ int iscsi_default_iface_setup(struct iscsi_context *ctx)
struct _eth_if **eifs = NULL;
uint32_t eif_count = 0;
uint32_t i = 0;
+ uint32_t n = 0;
size_t j = 0;
struct _iscsi_net_drv *ind = NULL;
uint32_t *hids = NULL;
uint32_t hid_count = 0;
- struct iscsi_iface *iface = NULL;
- char path[PATH_MAX];
+ struct iscsi_iface **ifaces = NULL;
+ uint32_t iface_count = 0;
+ char *path = NULL;
assert(ctx != NULL);
@@ -345,21 +385,34 @@ int iscsi_default_iface_setup(struct iscsi_context *ctx)
for (i = 0; i < hid_count; ++i) {
/* Create /etc/iscsi/ifaces/<iface_name> file if not found
*/
- _good(_iscsi_iface_get_from_sysfs(ctx, hids[i], 0, &iface),
- rc, out);
- if ( ! iscsi_is_default_iface(iface)) {
- snprintf(path, PATH_MAX, "%s/%s", IFACE_CONFIG_DIR,
- iface->name);
- if (access(path, F_OK) != 0)
- rc = _iface_conf_write(ctx, iface);
+ _good(_iscsi_ifaces_get_from_sysfs(ctx, hids[i], &ifaces, &iface_count),
+ rc, out);
+ for (n = 0; n < iface_count; n++) {
+ if ( ! iscsi_is_default_iface(ifaces[n])) {
+ _good(_asprintf(&path, "%s/%s", IFACE_CONFIG_DIR,
+ ifaces[n]->name), rc, out);
+ if (access(path, F_OK) != 0)
+ rc = _iface_conf_write(ctx, ifaces[n]);
+ free(path);
+ path = NULL;
+ }
+ iscsi_iface_free(ifaces[n]);
+ ifaces[n] = NULL;
+ if (rc != LIBISCSI_OK)
+ goto out;
}
- iscsi_iface_free(iface);
- if (rc != LIBISCSI_OK)
- goto out;
+ free(ifaces);
+ ifaces = NULL;
}
out:
+ if (ifaces != NULL) {
+ for (i = 0; i < iface_count; i++)
+ free(ifaces[i]);
+ free(ifaces);
+ }
_eth_ifs_free(eifs, eif_count);
+ free(path);
free(hids);
return rc;
}
@@ -434,7 +487,7 @@ out:
static int _iface_conf_write(struct iscsi_context *ctx,
struct iscsi_iface *iface)
{
- char conf_path[PATH_MAX];
+ char *conf_path = NULL;
char strerr_buff[_STRERR_BUFF_LEN];
int errno_save = 0;
FILE *f = NULL;
@@ -448,7 +501,8 @@ static int _iface_conf_write(struct iscsi_context *ctx,
_good(_idbm_lock(ctx), rc, out);
- snprintf(conf_path, PATH_MAX, "%s/%s", IFACE_CONFIG_DIR, iface->name);
+ _good(_asprintf(&conf_path, "%s/%s", IFACE_CONFIG_DIR,
+ iface->name), rc, out);
_debug(ctx, "Creating iSCSI interface configuration file '%s' "
"using kernel information", conf_path);
f = fopen(conf_path, "w");
@@ -466,6 +520,7 @@ static int _iface_conf_write(struct iscsi_context *ctx,
_idbm_unlock(ctx);
out:
+ free(conf_path);
if (f != NULL)
fclose(f);
return rc;
@@ -482,15 +537,12 @@ static int _fill_hw_iface_from_sys(struct iscsi_context *ctx,
uint32_t iface_num = 0;
int iface_type = 0;
-
assert(ctx != NULL);
assert(iface != NULL);
assert(iface_kern_id != NULL);
- sysfs_iface_dir_path = malloc(PATH_MAX);
- _alloc_null_check(ctx, sysfs_iface_dir_path, rc, out);
- snprintf(sysfs_iface_dir_path, PATH_MAX, "%s/%s",
- _ISCSI_SYS_IFACE_DIR, iface_kern_id);
+ _good(_asprintf(&sysfs_iface_dir_path, "%s/%s", _ISCSI_SYS_IFACE_DIR,
+ iface_kern_id), rc, out);
_good(_sysfs_prop_get_str(ctx, sysfs_iface_dir_path,
"ipaddress",
diff --git a/libopeniscsiusr/iface.h b/libopeniscsiusr/iface.h
index af3d9c7..f20ea13 100644
--- a/libopeniscsiusr/iface.h
+++ b/libopeniscsiusr/iface.h
@@ -57,9 +57,13 @@ struct iscsi_iface {
char ipv6_autocfg[NI_MAXHOST];
char linklocal_autocfg[NI_MAXHOST];
char router_autocfg[NI_MAXHOST];
-// uint8_t prefix_len;
+ uint8_t prefix_len;
/* ^ prefix_len is removed, as linux kernel has no such sysfs property
* and there is no actual code in usr/ folder set this property
+ *
+ * Added back, we need to be backward compatible with iface records
+ * created by older tools. Look at fixing code to ignore in record
+ * files instead? - cleech
*/
uint16_t vlan_id;
uint8_t vlan_priority;
@@ -135,6 +139,7 @@ struct iscsi_iface {
__DLL_LOCAL int _iscsi_iface_get_from_sysfs(struct iscsi_context *ctx,
uint32_t host_id, uint32_t sid,
+ char *iface_kern_id,
struct iscsi_iface **iface);
__DLL_LOCAL bool _iface_is_valid(struct iscsi_iface *iface);
diff --git a/libopeniscsiusr/misc.h b/libopeniscsiusr/misc.h
index 9208bbd..ca46726 100644
--- a/libopeniscsiusr/misc.h
+++ b/libopeniscsiusr/misc.h
@@ -35,6 +35,9 @@
goto out; \
} while(0)
+#define _asprintf(...) \
+ (asprintf(__VA_ARGS__) == -1 ? LIBISCSI_ERR_NOMEM : LIBISCSI_OK)
+
__DLL_LOCAL void _iscsi_log(struct iscsi_context *ctx, int priority,
const char *file, int line, const char *func_name,
const char *format, ...);
@@ -84,10 +87,15 @@ __DLL_LOCAL void _iscsi_log_stderr(struct iscsi_context *ctx, int priority,
#define _strerror(err_no, buff) \
strerror_r(err_no, buff, _STRERR_BUFF_LEN)
+/* Workaround for suppress GCC 8 `stringop-truncation` warnings. */
#define _strncpy(dst, src, size) \
do { \
- strncpy(dst, src, size); \
- * (char *) (dst + (size - 1)) = '\0'; \
+ memcpy(dst, src, \
+ (size_t) size > strlen(src) ? \
+ strlen(src) : (size_t) size); \
+ * (char *) (dst + \
+ ((size_t) size - 1 > strlen(src) ? \
+ strlen(src) : (size_t) (size - 1))) = '\0'; \
} while(0)
__DLL_LOCAL int _scan_filter_skip_dot(const struct dirent *dir);
diff --git a/libopeniscsiusr/node.c b/libopeniscsiusr/node.c
index e82bb0d..6bec201 100644
--- a/libopeniscsiusr/node.c
+++ b/libopeniscsiusr/node.c
@@ -93,7 +93,8 @@ int iscsi_nodes_get(struct iscsi_context *ctx, struct iscsi_node ***nodes,
int p = 0;
struct dirent **namelist_ifaces = NULL;
int f = 0;
- char path[PATH_MAX];
+ char *target_path = NULL;
+ char *path = NULL;
struct stat path_stat;
char strerr_buff[_STRERR_BUFF_LEN];
@@ -120,15 +121,17 @@ int iscsi_nodes_get(struct iscsi_context *ctx, struct iscsi_node ***nodes,
for (i = 0; i < n; ++i) {
target_name = namelist[i]->d_name;
- snprintf(path, sizeof(path)/sizeof(char),
- "%s/%s", NODE_CONFIG_DIR, target_name);
- _good(_scandir(ctx, path, &namelist_portals, &p), rc, out);
- _debug(ctx, "Got %d portals from %s folder", p, path);
+ _good(_asprintf(&target_path, "%s/%s", NODE_CONFIG_DIR,
+ target_name), rc, out);
+ _good(_scandir(ctx, target_path, &namelist_portals, &p),
+ rc, out);
+ _debug(ctx, "Got %d portals from %s folder", p, target_path);
+ free(target_path);
+ target_path = NULL;
for (j = 0; j < p; ++j) {
portal = namelist_portals[j]->d_name;
- snprintf(path, sizeof(path)/sizeof(char),
- "%s/%s/%s", NODE_CONFIG_DIR, target_name,
- portal);
+ _good(_asprintf(&path, "%s/%s/%s", NODE_CONFIG_DIR,
+ target_name, portal), rc, out);
if (stat(path, &path_stat) != 0) {
_warn(ctx, "Cannot stat path '%s': %d, %s",
path, errno,
@@ -166,6 +169,8 @@ int iscsi_nodes_get(struct iscsi_context *ctx, struct iscsi_node ***nodes,
node_count, node),
rc, out);
}
+ free(path);
+ path = NULL;
_scandir_free(namelist_ifaces, f);
namelist_ifaces = NULL;
f = 0;
@@ -178,6 +183,8 @@ int iscsi_nodes_get(struct iscsi_context *ctx, struct iscsi_node ***nodes,
*node_count = real_node_count;
out:
+ free(path);
+ free(target_path);
_scandir_free(namelist, n);
_scandir_free(namelist_portals, p);
_scandir_free(namelist_ifaces, f);
diff --git a/libopeniscsiusr/session.c b/libopeniscsiusr/session.c
index 4d9c57c..a833939 100644
--- a/libopeniscsiusr/session.c
+++ b/libopeniscsiusr/session.c
@@ -105,8 +105,8 @@ int iscsi_session_get(struct iscsi_context *ctx, uint32_t sid,
struct iscsi_session **se)
{
int rc = LIBISCSI_OK;
- char sysfs_se_dir_path[PATH_MAX];
- char sysfs_con_dir_path[PATH_MAX];
+ char *sysfs_se_dir_path = NULL;
+ char *sysfs_con_dir_path = NULL;
uint32_t host_id = 0;
assert(ctx != NULL);
@@ -114,17 +114,16 @@ int iscsi_session_get(struct iscsi_context *ctx, uint32_t sid,
_debug(ctx, "Querying iSCSI session for sid %" PRIu32, sid);
- snprintf(sysfs_se_dir_path, PATH_MAX, "%s/session%" PRIu32,
- _ISCSI_SYS_SESSION_DIR, sid);
- snprintf(sysfs_con_dir_path, PATH_MAX, "%s/connection%" PRIu32 ":0",
- _ISCSI_SYS_CONNECTION_DIR, sid);
+ _good(_asprintf(&sysfs_se_dir_path, "%s/session%" PRIu32,
+ _ISCSI_SYS_SESSION_DIR, sid), rc, out);
+ _good(_asprintf(&sysfs_con_dir_path, "%s/connection%" PRIu32 ":0",
+ _ISCSI_SYS_CONNECTION_DIR, sid), rc, out);
/* ^ BUG(Gris Ge): ':0' here in kernel is referred as connection id.
* but the open-iscsi assuming it's always 0, need
* investigation.
*/
- *se = (struct iscsi_session *)
- calloc(sizeof(struct iscsi_session), 1);
+ *se = (struct iscsi_session *) calloc(1, sizeof(struct iscsi_session));
_alloc_null_check(ctx, *se , rc, out);
if (! _file_exists(sysfs_se_dir_path)) {
@@ -229,7 +228,8 @@ int iscsi_session_get(struct iscsi_context *ctx, uint32_t sid,
_good(_iscsi_host_id_of_session(ctx, sid, &host_id), rc, out);
- _good(_iscsi_iface_get_from_sysfs(ctx, host_id, sid, &((*se)->iface)),
+ /* does this need to the correct iface_kern_id for the session? */
+ _good(_iscsi_iface_get_from_sysfs(ctx, host_id, sid, NULL, &((*se)->iface)),
rc, out);
out:
@@ -237,6 +237,8 @@ out:
iscsi_session_free(*se);
*se = NULL;
}
+ free(sysfs_se_dir_path);
+ free(sysfs_con_dir_path);
return rc;
}
diff --git a/libopeniscsiusr/sysfs.c b/libopeniscsiusr/sysfs.c
index 22eaf44..08f71b3 100644
--- a/libopeniscsiusr/sysfs.c
+++ b/libopeniscsiusr/sysfs.c
@@ -17,6 +17,10 @@
* Author: Gris Ge <fge@redhat.com>
*/
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
@@ -73,19 +77,16 @@ static int iscsi_sysfs_prop_get_ll(struct iscsi_context *ctx,
bool ignore_error);
/*
- * dev_path should be char[PATH_MAX]
+ * dev_path needs to be freed by the caller on success
*/
static int sysfs_get_dev_path(struct iscsi_context *ctx, const char *path,
- enum _sysfs_dev_class class, char *dev_path);
+ enum _sysfs_dev_class class, char **dev_path);
_sysfs_prop_get_int_func_gen(_sysfs_prop_get_u8, uint8_t, UINT8_MAX);
_sysfs_prop_get_int_func_gen(_sysfs_prop_get_u16, uint16_t, UINT16_MAX);
_sysfs_prop_get_int_func_gen(_sysfs_prop_get_i32, int32_t, INT32_MAX);
_sysfs_prop_get_int_func_gen(_sysfs_prop_get_u32, uint32_t, UINT32_MAX);
-/*
- * dev_path should be char[PATH_MAX].
- */
static int sysfs_read_file(const char *path, uint8_t *buff, size_t buff_size)
{
int fd = -1;
@@ -130,7 +131,7 @@ int _sysfs_prop_get_str(struct iscsi_context *ctx, const char *dir_path,
const char *prop_name, char *buff, size_t buff_size,
const char *default_value)
{
- char file_path[PATH_MAX];
+ char *file_path = NULL;
int rc = LIBISCSI_OK;
int errno_save = 0;
@@ -138,7 +139,7 @@ int _sysfs_prop_get_str(struct iscsi_context *ctx, const char *dir_path,
assert(prop_name != NULL);
assert(buff != NULL);
- snprintf(file_path, PATH_MAX, "%s/%s", dir_path, prop_name);
+ _good(_asprintf(&file_path, "%s/%s", dir_path, prop_name), rc, out);
errno_save = sysfs_read_file(file_path, (uint8_t *) buff, buff_size);
if (errno_save != 0) {
@@ -176,6 +177,8 @@ int _sysfs_prop_get_str(struct iscsi_context *ctx, const char *dir_path,
} else
_debug(ctx, "Open '%s', got '%s'", file_path, buff);
}
+out:
+ free(file_path);
return rc;
}
@@ -184,7 +187,7 @@ static int iscsi_sysfs_prop_get_ll(struct iscsi_context *ctx,
long long int *val,
long long int default_value, bool ignore_error)
{
- char file_path[PATH_MAX];
+ char *file_path = NULL;
int rc = LIBISCSI_OK;
int errno_save = 0;
uint8_t buff[_INT32_STR_MAX_LEN];
@@ -196,7 +199,7 @@ static int iscsi_sysfs_prop_get_ll(struct iscsi_context *ctx,
*val = 0;
- snprintf(file_path, PATH_MAX, "%s/%s", dir_path, prop_name);
+ _good(_asprintf(&file_path, "%s/%s", dir_path, prop_name), rc, out);
errno_save = sysfs_read_file(file_path, buff, _INT32_STR_MAX_LEN);
if (errno_save != 0) {
@@ -206,7 +209,7 @@ static int iscsi_sysfs_prop_get_ll(struct iscsi_context *ctx,
_error(ctx, "Failed to read '%s': "
"file '%s' does not exists",
prop_name, file_path);
- return rc;
+ goto out;
} else {
_info(ctx,
"Failed to read '%s': "
@@ -214,39 +217,41 @@ static int iscsi_sysfs_prop_get_ll(struct iscsi_context *ctx,
"default value %lld",
file_path, default_value);
*val = default_value;
- return rc;
+ goto out;
}
} else if (errno_save == EACCES) {
rc = LIBISCSI_ERR_ACCESS;
_error(ctx, "Permission deny when reading '%s'",
file_path);
- return rc;
+ goto out;
} else {
rc = LIBISCSI_ERR_BUG;
_error(ctx, "Error when reading '%s': %d", file_path,
errno_save);
- return rc;
+ goto out;
}
}
+ errno = 0;
tmp_val = strtoll((const char *) buff, NULL, 10 /* base */);
errno_save = errno;
if ((errno_save != 0) && (! ignore_error)) {
rc = LIBISCSI_ERR_BUG;
_error(ctx, "Sysfs: %s: Error when converting '%s' "
"to number", file_path, (char *) buff, errno_save);
- return rc;
+ goto out;
}
*val = tmp_val;
_debug(ctx, "Open '%s', got %lld", file_path, tmp_val);
-
+out:
+ free(file_path);
return rc;
}
static int sysfs_get_dev_path(struct iscsi_context *ctx, const char *path,
- enum _sysfs_dev_class class, char *dev_path)
+ enum _sysfs_dev_class class, char **dev_path)
{
int rc = LIBISCSI_OK;
int errno_save = 0;
@@ -259,9 +264,8 @@ static int sysfs_get_dev_path(struct iscsi_context *ctx, const char *path,
assert(path != NULL);
assert(dev_path != NULL);
- memset(dev_path, 0, PATH_MAX);
-
- if (realpath(path, dev_path) == NULL) {
+ *dev_path = realpath(path, NULL);
+ if (*dev_path == NULL) {
errno_save = errno;
rc = LIBISCSI_ERR_SYSFS_LOOKUP;
_error(ctx, "realpath() failed on %s with error %d", path,
@@ -296,22 +300,24 @@ static int sysfs_get_dev_path(struct iscsi_context *ctx, const char *path,
goto out;
}
need_free_reg = 1;
- if (regexec(&regex, dev_path, 2 /* count of max matches */,
+ if (regexec(&regex, *dev_path, 2 /* count of max matches */,
reg_match, 0 /* no flags */) != 0) {
rc = LIBISCSI_ERR_SYSFS_LOOKUP;
- _error(ctx, "regexec() not match for %s", dev_path);
+ _error(ctx, "regexec() not match for %s", *dev_path);
goto out;
}
- *(dev_path + reg_match[1].rm_eo ) = '\0';
+ *(*dev_path + reg_match[1].rm_eo ) = '\0';
- _debug(ctx, "Got dev path of '%s': '%s'", path, dev_path);
+ _debug(ctx, "Got dev path of '%s': '%s'", path, *dev_path);
out:
if (need_free_reg)
regfree(&regex);
- if (rc != LIBISCSI_OK)
- memset(dev_path, 0, PATH_MAX);
+ if (rc != LIBISCSI_OK) {
+ free(*dev_path);
+ *dev_path = NULL;
+ }
return rc;
}
@@ -319,38 +325,29 @@ int _iscsi_host_id_of_session(struct iscsi_context *ctx, uint32_t sid,
uint32_t *host_id)
{
int rc = LIBISCSI_OK;
- char sys_se_dir_path[PATH_MAX];
- char sys_dev_path[PATH_MAX];
- char sys_scsi_host_dir_path[PATH_MAX];
+ char *sys_se_dir_path = NULL;
+ char *sys_dev_path = NULL;
+ char *sys_scsi_host_dir_path = NULL;
struct dirent **namelist = NULL;
int n = 0;
const char *host_id_str = NULL;
const char iscsi_host_dir_str[] = "/iscsi_host/";
- const unsigned int iscsi_host_dir_strlen = strlen(iscsi_host_dir_str);
assert(ctx != NULL);
assert(sid != 0);
assert(host_id != NULL);
- snprintf(sys_se_dir_path, PATH_MAX, "%s/session%" PRIu32,
- _ISCSI_SYS_SESSION_DIR, sid);
+ _good(_asprintf(&sys_se_dir_path, "%s/session%" PRIu32,
+ _ISCSI_SYS_SESSION_DIR, sid), rc, out);
*host_id = 0;
_good(sysfs_get_dev_path(ctx, sys_se_dir_path,
- _SYSFS_DEV_CLASS_ISCSI_SESSION, sys_dev_path),
+ _SYSFS_DEV_CLASS_ISCSI_SESSION, &sys_dev_path),
rc, out);
- if ((strlen(sys_dev_path) + iscsi_host_dir_strlen) >= PATH_MAX) {
- rc = LIBISCSI_ERR_SYSFS_LOOKUP;
- _error(ctx, "Pathname too long: %s%s",
- sys_dev_path, iscsi_host_dir_str);
- goto out;
- }
-
- strncpy(sys_scsi_host_dir_path, sys_dev_path, PATH_MAX);
- strncat(sys_scsi_host_dir_path, iscsi_host_dir_str,
- PATH_MAX - iscsi_host_dir_strlen);
+ _good(_asprintf(&sys_scsi_host_dir_path, "%s%s",
+ sys_dev_path, iscsi_host_dir_str), rc, out);
_good(_scandir(ctx, sys_scsi_host_dir_path, &namelist, &n), rc, out);
@@ -370,7 +367,9 @@ int _iscsi_host_id_of_session(struct iscsi_context *ctx, uint32_t sid,
out:
_scandir_free(namelist, n);
-
+ free(sys_se_dir_path);
+ free(sys_dev_path);
+ free(sys_scsi_host_dir_path);
return rc;
}
@@ -440,22 +439,28 @@ int _iscsi_hids_get(struct iscsi_context *ctx, uint32_t **hids,
bool _iscsi_transport_is_loaded(const char *transport_name)
{
- char path[PATH_MAX];
+ int rc = LIBISCSI_OK;
+ char *path = NULL;
if (transport_name == NULL)
return false;
- snprintf(path, PATH_MAX, "%s/%s", _ISCSI_SYS_TRANSPORT_DIR,
- transport_name);
+ _good(_asprintf(&path, "%s/%s", _ISCSI_SYS_TRANSPORT_DIR,
+ transport_name), rc, out);
- if (access(path, F_OK) == 0)
+ if (access(path, F_OK) == 0) {
+ free(path);
return true;
-
+ }
+out:
+ free(path);
return false;
}
-int _iscsi_iface_kern_id_of_host_id(struct iscsi_context *ctx,
- uint32_t host_id, char *iface_kern_id)
+int _iscsi_iface_kern_ids_of_host_id(struct iscsi_context *ctx,
+ uint32_t host_id,
+ char ***iface_kern_ids,
+ uint32_t *iface_count)
{
char *sysfs_sh_path = NULL;
char *dev_path = NULL;
@@ -463,46 +468,47 @@ int _iscsi_iface_kern_id_of_host_id(struct iscsi_context *ctx,
int rc = LIBISCSI_OK;
struct dirent **namelist = NULL;
int n = 0;
+ uint32_t i = 0;
- sysfs_sh_path = malloc(PATH_MAX);
- _alloc_null_check(ctx, sysfs_sh_path, rc, out);
-
- dev_path = malloc(PATH_MAX);
- _alloc_null_check(ctx, dev_path, rc, out);
-
- sysfs_iface_path = malloc(PATH_MAX);
- _alloc_null_check(ctx, sysfs_iface_path, rc, out);
-
- snprintf(sysfs_sh_path, PATH_MAX, "%s/host%" PRIu32,
- _ISCSI_SYS_HOST_DIR, host_id);
+ _good(_asprintf(&sysfs_sh_path, "%s/host%" PRIu32,
+ _ISCSI_SYS_HOST_DIR, host_id), rc, out);
_good(sysfs_get_dev_path(ctx, sysfs_sh_path,
- _SYSFS_DEV_CLASS_ISCSI_HOST, dev_path),
+ _SYSFS_DEV_CLASS_ISCSI_HOST, &dev_path),
rc, out);
- snprintf(sysfs_iface_path, PATH_MAX, "%s/iscsi_iface", dev_path);
+ _good(_asprintf(&sysfs_iface_path, "%s/iscsi_iface", dev_path),
+ rc, out);
_good(_scandir(ctx, sysfs_iface_path, &namelist, &n), rc, out);
if (n == 0) {
- rc = LIBISCSI_ERR_SYSFS_LOOKUP;
+ /* this is OK, and needed for transport drivers like
+ * bnx2i and qedi */
+ rc = LIBISCSI_OK;
_debug(ctx, "No iSCSI interface for iSCSI host %" PRIu32,
host_id);
goto out;
}
- if (n != 1) {
- rc = LIBISCSI_ERR_SYSFS_LOOKUP;
- _debug(ctx, "Got unexpected(got %d, should be 1) file in "
- "folder %s", n, sysfs_iface_path);
- goto out;
+ *iface_count = n;
+ *iface_kern_ids = calloc(*iface_count, sizeof(char *));
+ _alloc_null_check(ctx, *iface_kern_ids, rc, out);
+ for (i = 0; i < *iface_count; i++) {
+ (*iface_kern_ids)[i] = strdup(namelist[i]->d_name);
+ _alloc_null_check(ctx, (*iface_kern_ids)[i], rc, out);
+ _debug(ctx, "Found iSCSI iface '%s' for iSCSI host %" PRIu32,
+ (*iface_kern_ids)[i], host_id);
}
-
- snprintf(iface_kern_id, PATH_MAX, "%s", namelist[0]->d_name);
- _debug(ctx, "Found iSCSI iface '%s' for iSCSI host %" PRIu32,
- iface_kern_id, host_id);
-
out:
+ if (rc != LIBISCSI_OK) {
+ for (i = 0; i < *iface_count; i++ ) {
+ free((*iface_kern_ids)[i]);
+ }
+ free(*iface_kern_ids);
+ *iface_kern_ids = NULL;
+ *iface_count = 0;
+ }
_scandir_free(namelist, n);
free(sysfs_sh_path);
free(dev_path);
diff --git a/libopeniscsiusr/sysfs.h b/libopeniscsiusr/sysfs.h
index e285537..768b989 100644
--- a/libopeniscsiusr/sysfs.h
+++ b/libopeniscsiusr/sysfs.h
@@ -67,11 +67,13 @@ __DLL_LOCAL int _iscsi_host_id_of_session(struct iscsi_context *ctx,
uint32_t sid, uint32_t *host_id);
/*
- * iface_kern_id should be char[PATH_MAX]
+ * iface_kern_id returns an allocated (char *)[iface_count]
+ * that needs to be freed by the caller
*/
-__DLL_LOCAL int _iscsi_iface_kern_id_of_host_id(struct iscsi_context *ctx,
- uint32_t host_id,
- char *iface_kern_id);
+__DLL_LOCAL int _iscsi_iface_kern_ids_of_host_id(struct iscsi_context *ctx,
+ uint32_t host_id,
+ char ***iface_kern_ids,
+ uint32_t *iface_count);
/*
* The memory of (uint32_t *sids) should be freed by free().