From: Hannes Reinecke Date: Wed, 16 Jun 2021 07:25:50 +0000 (+0200) Subject: tree: argument checking for nvme_create_ctrl() X-Git-Tag: v1.0-rc0~127^2~3 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=f5fa40c89d3d4d8840322c4e5373c00ea2e5eaca;p=users%2Fsagi%2Flibnvme.git tree: argument checking for nvme_create_ctrl() 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 --- diff --git a/src/nvme/tree.c b/src/nvme/tree.c index 896257dc..e3ce92b6 100644 --- a/src/nvme/tree.c +++ b/src/nvme/tree.c @@ -16,6 +16,10 @@ #include #include +#include +#include +#include + #include #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; diff --git a/src/nvme/types.h b/src/nvme/types.h index 9b3427b7..773c721c 100644 --- a/src/nvme/types.h +++ b/src/nvme/types.h @@ -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