diff options
author | Chris Leech <leech@pobox.com> | 2018-06-18 14:04:21 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-06-18 14:04:21 -0700 |
commit | 92a7cfea36592b434725fa59daa8dacd52aaf45c (patch) | |
tree | 17485c831b5fc5a60966a3035e5daf2a0448918a | |
parent | 0cfebb10d29382ac1058c950a60a946c28b01e53 (diff) | |
parent | 4f9ca4a6ae635ac26be761780f8ceb54ea90ec96 (diff) | |
download | open-iscsi-92a7cfea36592b434725fa59daa8dacd52aaf45c.tar.gz |
Merge pull request #110 from cleech/libopeniscsiusr_fixes
Libopeniscsiusr fixes
-rw-r--r-- | libopeniscsiusr/idbm.c | 22 | ||||
-rw-r--r-- | libopeniscsiusr/idbm_fields.h | 1 | ||||
-rw-r--r-- | libopeniscsiusr/iface.c | 126 | ||||
-rw-r--r-- | libopeniscsiusr/iface.h | 7 | ||||
-rw-r--r-- | libopeniscsiusr/misc.h | 12 | ||||
-rw-r--r-- | libopeniscsiusr/node.c | 23 | ||||
-rw-r--r-- | libopeniscsiusr/session.c | 20 | ||||
-rw-r--r-- | libopeniscsiusr/sysfs.c | 154 | ||||
-rw-r--r-- | libopeniscsiusr/sysfs.h | 10 |
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(®ex, dev_path, 2 /* count of max matches */, + if (regexec(®ex, *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(®ex); - 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(). |