]> www.infradead.org Git - users/sagi/libnvme.git/commitdiff
tree: argument checking for nvme_create_ctrl()
authorHannes Reinecke <hare@suse.de>
Wed, 16 Jun 2021 07:25:50 +0000 (09:25 +0200)
committerHannes Reinecke <hare@suse.de>
Wed, 16 Jun 2021 07:25:50 +0000 (09:25 +0200)
Add argument checking for nvme_create_ctrl() to ensure the controller
values are correct and avoid failures later on in nvme_add_ctrl().

Signed-off-by: Hannes Reinecke <hare@suse.de>
src/nvme/tree.c
src/nvme/types.h

index 896257dc27cf2a7b06e6ce7d24f1a64543a26a4f..e3ce92b6f660e37bdbed015cdfa5157d2f66d25e 100644 (file)
 #include <libgen.h>
 #include <unistd.h>
 
+#include <sys/types.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
 #include <ccan/list/list.h>
 #include "ioctl.h"
 #include "filters.h"
@@ -835,14 +839,98 @@ void nvme_free_ctrl(nvme_ctrl_t c)
        free(c);
 }
 
+#define ____stringify(x...) #x
+#define __stringify(x...) ____stringify(x)
+
+static void discovery_trsvcid(nvme_ctrl_t c)
+{
+       if (!strcmp(c->transport, "tcp")) {
+               /* Default port for NVMe/TCP discovery controllers */
+               c->trsvcid = strdup(__stringify(NVME_DISC_IP_PORT));
+       } else if (!strcmp(c->transport, "rdma")) {
+               /* Default port for NVMe/RDMA controllers */
+               c->trsvcid = strdup(__stringify(NVME_RDMA_IP_PORT));
+       }
+}
+
+static bool traddr_is_hostname(const char *transport, const char *traddr)
+{
+       char addrstr[NVMF_TRADDR_SIZE];
+
+       if (!traddr || !transport)
+               return false;
+       if (strcmp(transport, "tcp") &&
+           strcmp(transport, "rdma"))
+               return false;
+       if (inet_pton(AF_INET, traddr, addrstr) > 0 ||
+           inet_pton(AF_INET6, traddr, addrstr) > 0)
+               return false;
+       return true;
+}
+
+void hostname2traddr(nvme_ctrl_t c, const char *host_traddr)
+{
+       struct addrinfo *host_info, hints = {.ai_family = AF_UNSPEC};
+       char addrstr[NVMF_TRADDR_SIZE];
+       const char *p;
+       int ret;
+
+       ret = getaddrinfo(host_traddr, NULL, &hints, &host_info);
+       if (ret) {
+               nvme_msg(LOG_DEBUG, "failed to resolve host %s info\n",
+                        host_traddr);
+               c->host_traddr = strdup(host_traddr);
+               return;
+       }
+
+       switch (host_info->ai_family) {
+       case AF_INET:
+               p = inet_ntop(host_info->ai_family,
+                       &(((struct sockaddr_in *)host_info->ai_addr)->sin_addr),
+                       addrstr, NVMF_TRADDR_SIZE);
+               break;
+       case AF_INET6:
+               p = inet_ntop(host_info->ai_family,
+                       &(((struct sockaddr_in6 *)host_info->ai_addr)->sin6_addr),
+                       addrstr, NVMF_TRADDR_SIZE);
+               break;
+       default:
+               nvme_msg(LOG_DEBUG, "unrecognized address family (%d) %s\n",
+                        host_info->ai_family, c->traddr);
+               c->host_traddr = strdup(host_traddr);
+               goto free_addrinfo;
+       }
+       if (!p) {
+               nvme_msg(LOG_DEBUG, "failed to get traddr for %s\n",
+                        c->traddr);
+               c->host_traddr = strdup(host_traddr);
+       } else
+               c->host_traddr = strdup(addrstr);
+
+free_addrinfo:
+       freeaddrinfo(host_info);
+}
+
 struct nvme_ctrl *nvme_create_ctrl(const char *subsysnqn,
                                   const char *transport, const char *traddr,
                                   const char *host_traddr, const char *trsvcid)
 {
        struct nvme_ctrl *c;
+       bool discovery = false;
 
-       if (!transport)
+       if (!transport) {
+               nvme_msg(LOG_ERR, "No transport specified\n");
+               return NULL;
+       }
+       if (strncmp(transport, "loop", 4) && !traddr) {
+               nvme_msg(LOG_ERR, "No transport address for '%s'\n", transport);
+              return NULL;
+       }
+       if (!subsysnqn) {
+               nvme_msg(LOG_ERR, "No subsystem NQN specified\n");
                return NULL;
+       } else if (!strcmp(subsysnqn, NVME_DISC_SUBSYS_NAME))
+               discovery = true;
        c = calloc(1, sizeof(*c));
        c->fd = -1;
        c->cfg.tos = -1;
@@ -850,20 +938,26 @@ struct nvme_ctrl *nvme_create_ctrl(const char *subsysnqn,
        list_head_init(&c->paths);
        list_node_init(&c->entry);
        c->transport = strdup(transport);
-       if (subsysnqn)
-               c->subsysnqn = strdup(subsysnqn);
+       c->subsysnqn = strdup(subsysnqn);
        if (traddr)
                c->traddr = strdup(traddr);
-       else
-               c->traddr = strdup("none");
-       if (host_traddr)
-               c->host_traddr = strdup(host_traddr);
-       else
-               c->host_traddr = strdup("none");
+       if (host_traddr) {
+               if (traddr_is_hostname(transport, host_traddr))
+                       hostname2traddr(c, host_traddr);
+               else
+                       c->host_traddr = strdup(host_traddr);
+       }
        if (trsvcid)
                c->trsvcid = strdup(trsvcid);
-       else
-               c->trsvcid = strdup("none");
+       else if (discovery)
+               discovery_trsvcid(c);
+       else if (!strncmp(transport, "rdma", 4) ||
+                !strncmp(transport, "tcp", 3)) {
+               nvme_msg(LOG_ERR, "No trsvcid specified for '%s'\n",
+                        transport);
+               nvme_free_ctrl(c);
+               c = NULL;
+       }
 
        return c;
 }
@@ -879,13 +973,13 @@ struct nvme_ctrl *nvme_lookup_ctrl(struct nvme_subsystem *s,
        nvme_subsystem_for_each_ctrl(s, c) {
                if (strcmp(c->transport, transport))
                        continue;
-               if (traddr &&
+               if (traddr && c->traddr &&
                    strcmp(c->traddr, traddr))
                        continue;
-               if (host_traddr &&
+               if (host_traddr && c->host_traddr &&
                    strcmp(c->host_traddr, host_traddr))
                        continue;
-               if (trsvcid &&
+               if (trsvcid && c->trsvcid &&
                    strcmp(c->trsvcid, trsvcid))
                        continue;
                return c;
index 9b3427b7db17b61eb2582eb1510ecca86db1ee06..773c721c7c8611a997d0c31a2ce0b92925ca4e60 100644 (file)
@@ -3564,6 +3564,7 @@ enum nvme_subsys_type {
 
 #define NVME_DISC_SUBSYS_NAME  "nqn.2014-08.org.nvmexpress.discovery"
 #define NVME_RDMA_IP_PORT      4420
+#define NVME_DISC_IP_PORT      8009
 
 /* However the max length of a qualified name is another size */
 #define NVMF_NQN_SIZE          223