summaryrefslogtreecommitdiff
path: root/usr/discovery.c
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2010-02-19 19:19:22 -0600
committerMike Christie <michaelc@cs.wisc.edu>2010-03-22 17:32:08 -0500
commit22610b42dea26f17d9be3f5bd23fed0f32436932 (patch)
tree93f5d9f26e9a9ee0d1476984e83734be7e7e24aa /usr/discovery.c
parent7fef761e193dc3a1ff3c65b7eb9f8d3942d69bbb (diff)
downloadopen-iscsi-22610b42dea26f17d9be3f5bd23fed0f32436932.tar.gz
iscsi tools: use open-isns services
This replaces the native isns code with open-isns's libisns. I included the open-isns code in the open-iscsi tarball to make distribution easier since some distros use different isns clients and may not want to carry open-isns. This is based on open-isns commit 5e09f36d3446e41de0b8361601ffec4cd140d513. Changes in iSNS behavior/use: - To do discovery you must pass the ip and optionally the port to iscsiadm: iscsiadm -m discovery -t st -p 10.15.0.9 This command accepts the same ops as sendtargets so you can add/remove/update the node records that are created. It also supports ifaces properly now. - isns.address and isns.port in iscsid.conf are no longer used. - ESI is temporarily not supported. This will be fixed in the next patch when SCNs support is added. - The iscsiadm isns discovery command is not marked as stable. Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Diffstat (limited to 'usr/discovery.c')
-rw-r--r--usr/discovery.c244
1 files changed, 210 insertions, 34 deletions
diff --git a/usr/discovery.c b/usr/discovery.c
index 4fc0205..a121ddc 100644
--- a/usr/discovery.c
+++ b/usr/discovery.c
@@ -42,6 +42,11 @@
#include "sysdeps.h"
#include "fw_context.h"
#include "iscsid_req.h"
+#include "iscsi_util.h"
+/* libisns includes */
+#include "isns.h"
+#include "paths.h"
+#include "message.h"
#ifdef SLP_ENABLE
#include "iscsi-slp-discovery.h"
@@ -54,6 +59,211 @@ static int rediscover = 0;
static char initiator_name[TARGET_NAME_MAXLEN + 1];
static char initiator_alias[TARGET_NAME_MAXLEN + 1];
+static int request_initiator_name(void)
+{
+ int rc;
+ iscsiadm_req_t req;
+ iscsiadm_rsp_t rsp;
+
+ memset(initiator_name, 0, sizeof(initiator_name));
+ initiator_name[0] = '\0';
+ memset(initiator_alias, 0, sizeof(initiator_alias));
+ initiator_alias[0] = '\0';
+
+ memset(&req, 0, sizeof(req));
+ req.command = MGMT_IPC_CONFIG_INAME;
+
+ rc = iscsid_exec_req(&req, &rsp, 1);
+ if (rc)
+ return EIO;
+
+ if (rsp.u.config.var[0] != '\0')
+ strcpy(initiator_name, rsp.u.config.var);
+
+ memset(&req, 0, sizeof(req));
+ req.command = MGMT_IPC_CONFIG_IALIAS;
+
+ rc = iscsid_exec_req(&req, &rsp, 0);
+ if (rc)
+ /* alias is optional so return ok */
+ return 0;
+
+ if (rsp.u.config.var[0] != '\0')
+ strcpy(initiator_alias, rsp.u.config.var);
+ return 0;
+}
+
+int discovery_isns(struct discovery_rec *drec, struct iface_rec *iface,
+ struct list_head *rec_list)
+{
+ isns_object_list_t objects = ISNS_OBJECT_LIST_INIT;
+ isns_simple_t *qry;
+ isns_client_t *clnt;
+ isns_attr_list_t *attrs;
+ char *server;
+ uint32_t status;
+ int rc, i;
+
+ isns_config.ic_security = 0;
+
+ if (iface && strlen(iface->iname))
+ isns_assign_string(&isns_config.ic_source_name, iface->iname);
+ else {
+ if (request_initiator_name() || initiator_name[0] == '\0') {
+ log_error("Cannot perform discovery. Initiatorname "
+ "required.");
+ return EINVAL;
+ }
+ isns_assign_string(&isns_config.ic_source_name, initiator_name);
+ }
+
+ if (drec->port > USHRT_MAX) {
+ log_error("Invalid port %d\n", drec->port);
+ rc = EINVAL;
+ goto free_mem;
+ }
+
+ /* 5 for port and 1 for colon and 1 for null */
+ i = strlen(drec->address) + 7;
+ server = calloc(1, i);
+ if (!server) {
+ rc = ENOMEM;
+ goto free_mem;
+ }
+
+ snprintf(server, i, "%s:%d", drec->address, drec->port);
+ isns_assign_string(&isns_config.ic_server_name, server);
+ free(server);
+
+ clnt = isns_create_default_client(NULL);
+ if (!clnt) {
+ rc = ENOMEM;
+ goto free_mem;
+ }
+
+ /* do not retry forever */
+ isns_socket_set_disconnect_fatal(clnt->ic_socket);
+
+ qry = isns_simple_create(ISNS_DEVICE_ATTRIBUTE_QUERY,
+ clnt->ic_source, NULL);
+ if (!qry) {
+ rc = ENOMEM;
+ goto free_clnt;
+ }
+
+ attrs = &qry->is_message_attrs;
+ isns_attr_list_append_uint32(attrs, ISNS_TAG_ISCSI_NODE_TYPE,
+ ISNS_ISCSI_TARGET_MASK);
+
+ attrs = &qry->is_operating_attrs;
+ isns_attr_list_append_nil(attrs, ISNS_TAG_ISCSI_NAME);
+ isns_attr_list_append_nil(attrs, ISNS_TAG_ISCSI_NODE_TYPE);
+ isns_attr_list_append_nil(attrs, ISNS_TAG_PORTAL_IP_ADDRESS);
+ isns_attr_list_append_nil(attrs, ISNS_TAG_PORTAL_TCP_UDP_PORT);
+ isns_attr_list_append_nil(attrs, ISNS_TAG_PG_ISCSI_NAME);
+ isns_attr_list_append_nil(attrs, ISNS_TAG_PG_PORTAL_IP_ADDR);
+ isns_attr_list_append_nil(attrs, ISNS_TAG_PG_PORTAL_TCP_UDP_PORT);
+ isns_attr_list_append_nil(attrs, ISNS_TAG_PG_TAG);
+
+ status = isns_client_call(clnt, &qry);
+ if (status != ISNS_SUCCESS) {
+ log_error("iSNS discovery failed: %s", isns_strerror(status));
+ rc = EIO;
+ goto free_query;
+ }
+
+ status = isns_query_response_get_objects(qry, &objects);
+ if (status) {
+ log_error("Unable to extract object list from query "
+ "response: %s\n", isns_strerror(status));
+ rc = EIO;
+ goto free_query;
+ }
+
+ for (i = 0; i < objects.iol_count; ++i) {
+ isns_object_t *obj = objects.iol_data[i];
+ const char *pg_tgt = NULL;
+ struct in6_addr in_addr;
+ uint32_t pg_port = ISCSI_LISTEN_PORT;
+ uint32_t pg_tag = PORTAL_GROUP_TAG_UNKNOWN;
+ char pg_addr[INET6_ADDRSTRLEN + 1];
+ struct node_rec *rec;
+
+ if (!isns_object_is_pg(obj))
+ continue;
+
+ if (!isns_object_get_string(obj, ISNS_TAG_PG_ISCSI_NAME,
+ &pg_tgt)) {
+ log_debug(1, "Missing target name");
+ continue;
+ }
+
+ if (!isns_object_get_ipaddr(obj, ISNS_TAG_PG_PORTAL_IP_ADDR,
+ &in_addr)) {
+ log_debug(1, "Missing addr");
+ continue;
+ }
+ if (IN6_IS_ADDR_V4MAPPED(&in_addr) ||
+ IN6_IS_ADDR_V4COMPAT(&in_addr)) {
+ struct in_addr ipv4;
+
+ ipv4.s_addr = in_addr.s6_addr32[3];
+ inet_ntop(AF_INET, &ipv4, pg_addr, sizeof(pg_addr));
+ } else
+ inet_ntop(AF_INET6, &in_addr, pg_addr, sizeof(pg_addr));
+
+ if (!isns_object_get_uint32(obj,
+ ISNS_TAG_PG_PORTAL_TCP_UDP_PORT,
+ &pg_port)) {
+ log_debug(1, "Missing port");
+ continue;
+ }
+
+ if (!isns_object_get_uint32(obj, ISNS_TAG_PG_TAG, &pg_tag)) {
+ log_debug(1, "Missing tag");
+ continue;
+ }
+
+ rec = calloc(1, sizeof(*rec));
+ if (!rec) {
+ rc = ENOMEM;
+ goto destroy_list;
+ }
+
+ idbm_node_setup_from_conf(rec);
+ rec->disc_type = drec->type;
+ rec->disc_port = drec->port;
+ strcpy(rec->disc_address, drec->address);
+
+ strlcpy(rec->name, pg_tgt, TARGET_NAME_MAXLEN);
+ rec->tpgt = pg_tag;
+ rec->conn[0].port = pg_port;
+ strlcpy(rec->conn[0].address, pg_addr, NI_MAXHOST);
+
+ list_add_tail(&rec->list, rec_list);
+ }
+ rc = 0;
+
+ isns_flush_events();
+destroy_list:
+ isns_object_list_destroy(&objects);
+free_query:
+ isns_simple_free(qry);
+free_clnt:
+ isns_client_destroy(clnt);
+free_mem:
+ if (isns_config.ic_source_name)
+ free(isns_config.ic_source_name);
+ isns_config.ic_source_name = NULL;
+
+ if (isns_config.ic_server_name)
+ free(isns_config.ic_server_name);
+ isns_config.ic_server_name = NULL;
+ return rc;
+}
+
+
+
int discovery_fw(struct discovery_rec *drec, struct iface_rec *iface,
struct list_head *rec_list)
{
@@ -549,40 +759,6 @@ msecs_until(struct timeval *timer)
return msecs;
}
-static int request_initiator_name(void)
-{
- int rc;
- iscsiadm_req_t req;
- iscsiadm_rsp_t rsp;
-
- memset(initiator_name, 0, sizeof(initiator_name));
- initiator_name[0] = '\0';
- memset(initiator_alias, 0, sizeof(initiator_alias));
- initiator_alias[0] = '\0';
-
- memset(&req, 0, sizeof(req));
- req.command = MGMT_IPC_CONFIG_INAME;
-
- rc = iscsid_exec_req(&req, &rsp, 1);
- if (rc)
- return EIO;
-
- if (rsp.u.config.var[0] != '\0')
- strcpy(initiator_name, rsp.u.config.var);
-
- memset(&req, 0, sizeof(req));
- req.command = MGMT_IPC_CONFIG_IALIAS;
-
- rc = iscsid_exec_req(&req, &rsp, 0);
- if (rc)
- /* alias is optional so return ok */
- return 0;
-
- if (rsp.u.config.var[0] != '\0')
- strcpy(initiator_alias, rsp.u.config.var);
- return 0;
-}
-
static iscsi_session_t *
init_new_session(struct iscsi_sendtargets_config *config,
struct iface_rec *iface)