The branch main has been updated by jhb:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=2bb9180bb5d0054bf79529d6a1cb56b61a94629a

commit 2bb9180bb5d0054bf79529d6a1cb56b61a94629a
Author:     John Baldwin <j...@freebsd.org>
AuthorDate: 2025-08-04 19:38:07 +0000
Commit:     John Baldwin <j...@freebsd.org>
CommitDate: 2025-08-04 19:38:07 +0000

    ctld: Convert struct target to a C++ class
    
    - Use std::string for string members.
    
    - Use std::array for the array of LUN pointers indexed by LUN id.
    
    - Move meat of the target_* functions from conf.cc into class methods.
    
    Sponsored by:   Chelsio Communications
    Pull Request:   https://github.com/freebsd/freebsd-src/pull/1794
---
 usr.sbin/ctld/conf.cc      | 165 ++----------------
 usr.sbin/ctld/ctld.cc      | 406 ++++++++++++++++++++++++++++++++-------------
 usr.sbin/ctld/ctld.hh      |  55 +++++-
 usr.sbin/ctld/discovery.cc |  16 +-
 usr.sbin/ctld/kernel.cc    |  28 ++--
 usr.sbin/ctld/login.cc     |  22 +--
 6 files changed, 384 insertions(+), 308 deletions(-)

diff --git a/usr.sbin/ctld/conf.cc b/usr.sbin/ctld/conf.cc
index 8913cccd5889..81451009067c 100644
--- a/usr.sbin/ctld/conf.cc
+++ b/usr.sbin/ctld/conf.cc
@@ -341,217 +341,78 @@ target_finish(void)
        target = NULL;
 }
 
-static bool
-target_use_private_auth(const char *keyword)
-{
-       if (target->t_auth_group != nullptr) {
-               if (!target->t_private_auth) {
-                       log_warnx("cannot use both auth-group and "
-                           "%s for target \"%s\"", keyword, target->t_name);
-                       return (false);
-               }
-       } else {
-               target->t_auth_group = auth_group_new(target);
-               if (target->t_auth_group == nullptr)
-                       return (false);
-               target->t_private_auth = true;
-       }
-       return (true);
-}
-
 bool
 target_add_chap(const char *user, const char *secret)
 {
-       if (!target_use_private_auth("chap"))
-               return (false);
-       return (target->t_auth_group->add_chap(user, secret));
+       return (target->add_chap(user, secret));
 }
 
 bool
 target_add_chap_mutual(const char *user, const char *secret,
     const char *user2, const char *secret2)
 {
-       if (!target_use_private_auth("chap-mutual"))
-               return (false);
-       return (target->t_auth_group->add_chap_mutual(user, secret, user2,
-           secret2));
+       return (target->add_chap_mutual(user, secret, user2, secret2));
 }
 
 bool
 target_add_initiator_name(const char *name)
 {
-       if (!target_use_private_auth("initiator-name"))
-               return (false);
-       return (target->t_auth_group->add_initiator_name(name));
+       return (target->add_initiator_name(name));
 }
 
 bool
 target_add_initiator_portal(const char *addr)
 {
-       if (!target_use_private_auth("initiator-portal"))
-               return (false);
-       return (target->t_auth_group->add_initiator_portal(addr));
+       return (target->add_initiator_portal(addr));
 }
 
 bool
 target_add_lun(u_int id, const char *name)
 {
-       struct lun *t_lun;
-
-       if (id >= MAX_LUNS) {
-               log_warnx("LUN %u too big for target \"%s\"", id,
-                   target->t_name);
-               return (false);
-       }
-
-       if (target->t_luns[id] != NULL) {
-               log_warnx("duplicate LUN %u for target \"%s\"", id,
-                   target->t_name);
-               return (false);
-       }
-
-       t_lun = lun_find(conf, name);
-       if (t_lun == NULL) {
-               log_warnx("unknown LUN named %s used for target \"%s\"",
-                   name, target->t_name);
-               return (false);
-       }
-
-       target->t_luns[id] = t_lun;
-       return (true);
+       return (target->add_lun(id, name));
 }
 
 bool
 target_add_portal_group(const char *pg_name, const char *ag_name)
 {
-       struct portal_group *pg;
-       auth_group_sp ag;
-
-       pg = portal_group_find(conf, pg_name);
-       if (pg == NULL) {
-               log_warnx("unknown portal-group \"%s\" for target \"%s\"",
-                   pg_name, target->t_name);
-               return (false);
-       }
-
-       if (ag_name != NULL) {
-               ag = auth_group_find(conf, ag_name);
-               if (ag == NULL) {
-                       log_warnx("unknown auth-group \"%s\" for target \"%s\"",
-                           ag_name, target->t_name);
-                       return (false);
-               }
-       }
-
-       if (!port_new(conf, target, pg, std::move(ag))) {
-               log_warnx("can't link portal-group \"%s\" to target \"%s\"",
-                   pg_name, target->t_name);
-               return (false);
-       }
-       return (true);
+       return (target->add_portal_group(pg_name, ag_name));
 }
 
 bool
 target_set_alias(const char *alias)
 {
-       if (target->t_alias != NULL) {
-               log_warnx("alias for target \"%s\" specified more than once",
-                   target->t_name);
-               return (false);
-       }
-       target->t_alias = checked_strdup(alias);
-       return (true);
+       return (target->set_alias(alias));
 }
 
 bool
 target_set_auth_group(const char *name)
 {
-       if (target->t_auth_group != nullptr) {
-               if (target->t_private_auth)
-                       log_warnx("cannot use both auth-group and explicit "
-                           "authorisations for target \"%s\"", target->t_name);
-               else
-                       log_warnx("auth-group for target \"%s\" "
-                           "specified more than once", target->t_name);
-               return (false);
-       }
-       target->t_auth_group = auth_group_find(conf, name);
-       if (target->t_auth_group == nullptr) {
-               log_warnx("unknown auth-group \"%s\" for target \"%s\"", name,
-                   target->t_name);
-               return (false);
-       }
-       return (true);
+       return (target->set_auth_group(name));
 }
 
 bool
 target_set_auth_type(const char *type)
 {
-       if (!target_use_private_auth("auth-type"))
-               return (false);
-       return (target->t_auth_group->set_type(type));
+       return (target->set_auth_type(type));
 }
 
 bool
 target_set_physical_port(const char *pport)
 {
-       if (target->t_pport != NULL) {
-               log_warnx("cannot set multiple physical ports for target "
-                   "\"%s\"", target->t_name);
-               return (false);
-       }
-       target->t_pport = checked_strdup(pport);
-       return (true);
+       return (target->set_physical_port(pport));
 }
 
 bool
 target_set_redirection(const char *addr)
 {
-
-       if (target->t_redirection != NULL) {
-               log_warnx("cannot set redirection to \"%s\" for "
-                   "target \"%s\"; already defined",
-                   addr, target->t_name);
-               return (false);
-       }
-
-       target->t_redirection = checked_strdup(addr);
-
-       return (true);
+       return (target->set_redirection(addr));
 }
 
 bool
 target_start_lun(u_int id)
 {
-       struct lun *new_lun;
-       char *name;
-
-       if (id >= MAX_LUNS) {
-               log_warnx("LUN %u too big for target \"%s\"", id,
-                   target->t_name);
-               return (false);
-       }
-
-       if (target->t_luns[id] != NULL) {
-               log_warnx("duplicate LUN %u for target \"%s\"", id,
-                   target->t_name);
-               return (false);
-       }
-
-       if (asprintf(&name, "%s,lun,%u", target->t_name, id) <= 0)
-               log_err(1, "asprintf");
-
-       new_lun = lun_new(conf, name);
-       if (new_lun == NULL)
-               return (false);
-
-       new_lun->set_scsiname(name);
-       free(name);
-
-       target->t_luns[id] = new_lun;
-
-       lun = new_lun;
-       return (true);
+       lun = target->start_lun(id);
+       return (lun != nullptr);
 }
 
 bool
diff --git a/usr.sbin/ctld/ctld.cc b/usr.sbin/ctld/ctld.cc
index 1dbc6988b9d1..2aaba32ed101 100644
--- a/usr.sbin/ctld/ctld.cc
+++ b/usr.sbin/ctld/ctld.cc
@@ -51,6 +51,7 @@
 #include <unistd.h>
 #include <cam/scsi/scsi_all.h>
 
+#include <algorithm>
 #include <libutil++.hh>
 
 #include "conf.h"
@@ -101,7 +102,6 @@ conf_new(void)
        struct conf *conf;
 
        conf = new struct conf();
-       TAILQ_INIT(&conf->conf_targets);
 
        conf->conf_isns_period = 900;
        conf->conf_isns_timeout = 5;
@@ -115,12 +115,8 @@ conf_new(void)
 void
 conf_delete(struct conf *conf)
 {
-       struct target *targ, *tmp;
-
        assert(conf->conf_pidfh == NULL);
 
-       TAILQ_FOREACH_SAFE(targ, &conf->conf_targets, t_next, tmp)
-               target_delete(targ);
        free(conf->conf_pidfile_path);
        delete conf;
 }
@@ -410,13 +406,6 @@ auth_group_new(struct conf *conf, const char *name)
        return (pair.first->second.get());
 }
 
-auth_group_sp
-auth_group_new(struct target *target)
-{
-       return (std::make_shared<auth_group>(freebsd::stringf("target \"%s\"",
-           target->t_name)));
-}
-
 auth_group_sp
 auth_group_find(const struct conf *conf, const char *name)
 {
@@ -516,13 +505,13 @@ parse_addr_port(const char *address, const char *def_port)
 void
 portal_group::add_port(struct portal_group_port *port)
 {
-       pg_ports.emplace(port->target()->t_name, port);
+       pg_ports.emplace(port->target()->name(), port);
 }
 
 void
 portal_group::remove_port(struct portal_group_port *port)
 {
-       auto it = pg_ports.find(port->target()->t_name);
+       auto it = pg_ports.find(port->target()->name());
        pg_ports.erase(it);
 }
 
@@ -821,11 +810,10 @@ isns::send_request(int s, struct isns_req req)
 static struct isns_req
 isns_register_request(struct conf *conf, const char *hostname)
 {
-       struct target *target;
        const struct portal_group *pg;
 
        isns_req req(ISNS_FUNC_DEVATTRREG, ISNS_FLAG_CLIENT, "register");
-       req.add_str(32, TAILQ_FIRST(&conf->conf_targets)->t_name);
+       req.add_str(32, conf->conf_first_target->name());
        req.add_delim();
        req.add_str(1, hostname);
        req.add_32(2, 2); /* 2 -- iSCSI */
@@ -840,12 +828,14 @@ isns_register_request(struct conf *conf, const char 
*hostname)
                        req.add_port(17, portal->ai());
                }
        }
-       TAILQ_FOREACH(target, &conf->conf_targets, t_next) {
-               req.add_str(32, target->t_name);
+       for (const auto &kv : conf->conf_targets) {
+               const struct target *target = kv.second.get();
+
+               req.add_str(32, target->name());
                req.add_32(33, 1); /* 1 -- Target*/
-               if (target->t_alias != NULL)
-                       req.add_str(34, target->t_alias);
-               for (const port *port : target->t_ports) {
+               if (target->has_alias())
+                       req.add_str(34, target->alias());
+               for (const port *port : target->ports()) {
                        pg = port->portal_group();
                        if (pg == nullptr)
                                continue;
@@ -863,7 +853,7 @@ static struct isns_req
 isns_check_request(struct conf *conf, const char *hostname)
 {
        isns_req req(ISNS_FUNC_DEVATTRQRY, ISNS_FLAG_CLIENT, "check");
-       req.add_str(32, TAILQ_FIRST(&conf->conf_targets)->t_name);
+       req.add_str(32, conf->conf_first_target->name());
        req.add_str(1, hostname);
        req.add_delim();
        req.add(2, 0, NULL);
@@ -874,7 +864,7 @@ static struct isns_req
 isns_deregister_request(struct conf *conf, const char *hostname)
 {
        isns_req req(ISNS_FUNC_DEVDEREG, ISNS_FLAG_CLIENT, "deregister");
-       req.add_str(32, TAILQ_FIRST(&conf->conf_targets)->t_name);
+       req.add_str(32, conf->conf_first_target->name());
        req.add_delim();
        req.add_str(1, hostname);
        return (req);
@@ -887,8 +877,7 @@ isns_register_targets(struct conf *conf, struct isns *isns,
        int error;
        char hostname[256];
 
-       if (TAILQ_EMPTY(&conf->conf_targets) ||
-           conf->conf_portal_groups.empty())
+       if (conf->conf_targets.empty() || conf->conf_portal_groups.empty())
                return;
        set_timeout(conf->conf_isns_timeout, false);
        freebsd::fd_up s = isns->connect();
@@ -900,7 +889,7 @@ isns_register_targets(struct conf *conf, struct isns *isns,
        if (error != 0)
                log_err(1, "gethostname");
 
-       if (oldconf == NULL || TAILQ_EMPTY(&oldconf->conf_targets))
+       if (oldconf == nullptr || oldconf->conf_first_target == nullptr)
                oldconf = conf;
        isns->send_request(s, isns_deregister_request(oldconf, hostname));
        isns->send_request(s, isns_register_request(conf, hostname));
@@ -914,8 +903,7 @@ isns_check(struct conf *conf, struct isns *isns)
        int error;
        char hostname[256];
 
-       if (TAILQ_EMPTY(&conf->conf_targets) ||
-           conf->conf_portal_groups.empty())
+       if (conf->conf_targets.empty() || conf->conf_portal_groups.empty())
                return;
        set_timeout(conf->conf_isns_timeout, false);
        freebsd::fd_up s = isns->connect();
@@ -941,8 +929,7 @@ isns_deregister_targets(struct conf *conf, struct isns 
*isns)
        int error;
        char hostname[256];
 
-       if (TAILQ_EMPTY(&conf->conf_targets) ||
-           conf->conf_portal_groups.empty())
+       if (conf->conf_targets.empty() || conf->conf_portal_groups.empty())
                return;
        set_timeout(conf->conf_isns_timeout, false);
        freebsd::fd_up s = isns->connect();
@@ -987,13 +974,13 @@ kports::find_port(std::string_view name)
 port::port(struct target *target) :
        p_target(target)
 {
-       target->t_ports.push_back(this);
+       target->add_port(this);
 }
 
 void
 port::clear_references()
 {
-       p_target->t_ports.remove(this);
+       p_target->remove_port(this);
 }
 
 portal_group_port::portal_group_port(struct target *target,
@@ -1029,7 +1016,7 @@ port_new(struct conf *conf, struct target *target, struct 
portal_group *pg,
     auth_group_sp ag)
 {
        std::string name = freebsd::stringf("%s-%s", pg->name(),
-           target->t_name);
+           target->name());
        const auto &pair = conf->conf_ports.try_emplace(name,
            std::make_unique<portal_group_port>(target, pg, ag));
        if (!pair.second) {
@@ -1045,7 +1032,7 @@ port_new(struct conf *conf, struct target *target, struct 
portal_group *pg,
     uint32_t ctl_port)
 {
        std::string name = freebsd::stringf("%s-%s", pg->name(),
-           target->t_name);
+           target->name());
        const auto &pair = conf->conf_ports.try_emplace(name,
            std::make_unique<portal_group_port>(target, pg, ctl_port));
        if (!pair.second) {
@@ -1060,7 +1047,7 @@ static bool
 port_new_pp(struct conf *conf, struct target *target, struct pport *pp)
 {
        std::string name = freebsd::stringf("%s-%s", pp->name(),
-           target->t_name);
+           target->name());
        const auto &pair = conf->conf_ports.try_emplace(name,
            std::make_unique<kernel_port>(target, pp));
        if (!pair.second) {
@@ -1084,7 +1071,7 @@ port_new_ioctl(struct conf *conf, struct kports &kports, 
struct target *target,
        if (pport != NULL)
                return (port_new_pp(conf, target, pport));
 
-       std::string name = pname + "-" + target->t_name;
+       std::string name = pname + "-" + target->name();
        const auto &pair = conf->conf_ports.try_emplace(name,
            std::make_unique<ioctl_port>(target, pp, vp));
        if (!pair.second) {
@@ -1107,55 +1094,280 @@ portal_group::find_port(std::string_view target) const
 struct target *
 target_new(struct conf *conf, const char *name)
 {
-       struct target *targ;
-       int i, len;
+       if (!valid_iscsi_name(name, log_warnx))
+               return (nullptr);
+
+       /*
+        * RFC 3722 requires us to normalize the name to lowercase.
+        */
+       std::string t_name(name);
+       for (char &c : t_name)
+               c = tolower(c);
 
-       targ = target_find(conf, name);
-       if (targ != NULL) {
+       auto const &pair = conf->conf_targets.try_emplace(t_name,
+           std::make_unique<target>(conf, t_name));
+       if (!pair.second) {
                log_warnx("duplicated target \"%s\"", name);
                return (NULL);
        }
-       if (valid_iscsi_name(name, log_warnx) == false) {
-               return (NULL);
+
+       if (conf->conf_first_target == nullptr)
+               conf->conf_first_target = pair.first->second.get();
+       return (pair.first->second.get());
+}
+
+struct target *
+target_find(struct conf *conf, const char *name)
+{
+       auto it = conf->conf_targets.find(name);
+       if (it == conf->conf_targets.end())
+               return (nullptr);
+       return (it->second.get());
+}
+
+bool
+target::use_private_auth(const char *keyword)
+{
+       if (t_private_auth)
+               return (true);
+
+       if (t_auth_group != nullptr) {
+               log_warnx("cannot use both auth-group and %s for target \"%s\"",
+                   keyword, name());
+               return (false);
        }
-       targ = new target();
-       targ->t_name = checked_strdup(name);
 
-       /*
-        * RFC 3722 requires us to normalize the name to lowercase.
-        */
-       len = strlen(name);
-       for (i = 0; i < len; i++)
-               targ->t_name[i] = tolower(targ->t_name[i]);
+       std::string label = freebsd::stringf("target \"%s\"", name());
+       t_auth_group = std::make_shared<struct auth_group>(label);
+       t_private_auth = true;
+       return (true);
+}
+
+bool
+target::add_chap(const char *user, const char *secret)
+{
+       if (!use_private_auth("chap"))
+               return (false);
+       return (t_auth_group->add_chap(user, secret));
+}
+
+bool
+target::add_chap_mutual(const char *user, const char *secret,
+    const char *user2, const char *secret2)
+{
+       if (!use_private_auth("chap-mutual"))
+               return (false);
+       return (t_auth_group->add_chap_mutual(user, secret, user2, secret2));
+}
+
+bool
+target::add_initiator_name(std::string_view name)
+{
+       if (!use_private_auth("initiator-name"))
+               return (false);
+       return (t_auth_group->add_initiator_name(name));
+}
+
+bool
+target::add_initiator_portal(const char *addr)
+{
+       if (!use_private_auth("initiator-portal"))
+               return (false);
+       return (t_auth_group->add_initiator_portal(addr));
+}
+
+bool
+target::add_lun(u_int id, const char *lun_name)
+{
+       struct lun *t_lun;
+
+       if (id >= MAX_LUNS) {
+               log_warnx("LUN %u too big for target \"%s\"", id, name());
+               return (false);
+       }
+
+       if (t_luns[id] != NULL) {
+               log_warnx("duplicate LUN %u for target \"%s\"", id, name());
+               return (false);
+       }
+
+       t_lun = lun_find(t_conf, lun_name);
+       if (t_lun == NULL) {
+               log_warnx("unknown LUN named %s used for target \"%s\"",
+                   lun_name, name());
+               return (false);
+       }
+
+       t_luns[id] = t_lun;
+       return (true);
+}
+
+bool
+target::add_portal_group(const char *pg_name, const char *ag_name)
+{
+       struct portal_group *pg;
+       auth_group_sp ag;
+
+       pg = portal_group_find(t_conf, pg_name);
+       if (pg == NULL) {
+               log_warnx("unknown portal-group \"%s\" for target \"%s\"",
+                   pg_name, name());
+               return (false);
+       }
+
+       if (ag_name != NULL) {
+               ag = auth_group_find(t_conf, ag_name);
+               if (ag == NULL) {
+                       log_warnx("unknown auth-group \"%s\" for target \"%s\"",
+                           ag_name, name());
+                       return (false);
+               }
+       }
+
+       if (!port_new(t_conf, this, pg, std::move(ag))) {
+               log_warnx("can't link portal-group \"%s\" to target \"%s\"",
+                   pg_name, name());
+               return (false);
+       }
+       return (true);
+}
+
+bool
+target::set_alias(std::string_view alias)
+{
+       if (has_alias()) {
+               log_warnx("alias for target \"%s\" specified more than once",
+                   name());
+               return (false);
+       }
+       t_alias = alias;
+       return (true);
+}
+
+bool
+target::set_auth_group(const char *ag_name)
+{
+       if (t_auth_group != nullptr) {
+               if (t_private_auth)
+                       log_warnx("cannot use both auth-group and explicit "
+                           "authorisations for target \"%s\"", name());
+               else
+                       log_warnx("auth-group for target \"%s\" "
+                           "specified more than once", name());
+               return (false);
+       }
+       t_auth_group = auth_group_find(t_conf, ag_name);
+       if (t_auth_group == nullptr) {
+               log_warnx("unknown auth-group \"%s\" for target \"%s\"",
+                   ag_name, name());
+               return (false);
+       }
+       return (true);
+}
+
+bool
+target::set_auth_type(const char *type)
+{
+       if (!use_private_auth("auth-type"))
+               return (false);
+       return (t_auth_group->set_type(type));
+}
+
+bool
+target::set_physical_port(std::string_view pport)
+{
+       if (!t_pport.empty()) {
+               log_warnx("cannot set multiple physical ports for target "
+                   "\"%s\"", name());
+               return (false);
+       }
+       t_pport = pport;
+       return (true);
+}
+
+bool
+target::set_redirection(const char *addr)
+{
+       if (!t_redirection.empty()) {
+               log_warnx("cannot set redirection to \"%s\" for "
+                   "target \"%s\"; already defined",
+                   addr, name());
+               return (false);
+       }
 
-       targ->t_conf = conf;
-       TAILQ_INSERT_TAIL(&conf->conf_targets, targ, t_next);
+       t_redirection = addr;
+       return (true);
+}
+
+struct lun *
+target::start_lun(u_int id)
+{
+       struct lun *new_lun;
 
-       return (targ);
+       if (id >= MAX_LUNS) {
+               log_warnx("LUN %u too big for target \"%s\"", id,
+                   name());
+               return (nullptr);
+       }
+
+       if (t_luns[id] != NULL) {
+               log_warnx("duplicate LUN %u for target \"%s\"", id,
+                   name());
+               return (nullptr);
+       }
+
+       std::string lun_name = freebsd::stringf("%s,lun,%u", name(), id);
+       new_lun = lun_new(t_conf, lun_name.c_str());
+       if (new_lun == nullptr)
+               return (nullptr);
+
+       new_lun->set_scsiname(lun_name.c_str());
+
+       t_luns[id] = new_lun;
+
+       return (new_lun);
 }
 
 void
-target_delete(struct target *targ)
+target::add_port(struct port *port)
 {
-       TAILQ_REMOVE(&targ->t_conf->conf_targets, targ, t_next);
+       t_ports.push_back(port);
+}
 
-       free(targ->t_pport);
-       free(targ->t_name);
-       free(targ->t_redirection);
-       delete targ;
+void
+target::remove_port(struct port *port)
+{
+       t_ports.remove(port);
 }
 
-struct target *
-target_find(struct conf *conf, const char *name)
+void
+target::remove_lun(struct lun *lun)
 {
-       struct target *targ;
+       /* XXX: clang is not able to deduce the type without the cast. */
+       std::replace(t_luns.begin(), t_luns.end(), lun,
+           static_cast<struct lun *>(nullptr));
+}
 
-       TAILQ_FOREACH(targ, &conf->conf_targets, t_next) {
-               if (strcasecmp(targ->t_name, name) == 0)
-                       return (targ);
+void
+target::verify()
+{
+       if (t_auth_group == nullptr) {
+               t_auth_group = auth_group_find(t_conf, "default");
+               assert(t_auth_group != nullptr);
+       }
+       if (t_ports.empty()) {
+               struct portal_group *pg = portal_group_find(t_conf, "default");
+               assert(pg != NULL);
+               port_new(t_conf, this, pg, nullptr);
        }
 
-       return (NULL);
+       bool found = std::any_of(t_luns.begin(), t_luns.end(),
+           [](struct lun *lun) { return (lun != nullptr); });
+       if (!found && t_redirection.empty())
+               log_warnx("no LUNs defined for target \"%s\"", name());
+       if (found && !t_redirection.empty())
+               log_debugx("target \"%s\" contains luns,  but configured "
+                   "for redirection", name());
 }
 
 lun::lun(struct conf *conf, std::string_view name)
@@ -1178,15 +1390,8 @@ lun_new(struct conf *conf, const char *name)
 static void
 conf_delete_target_luns(struct conf *conf, struct lun *lun)
 {
-       struct target *targ;
-       int i;
-
-       TAILQ_FOREACH(targ, &conf->conf_targets, t_next) {
-               for (i = 0; i < MAX_LUNS; i++) {
-                       if (targ->t_luns[i] == lun)
-                               targ->t_luns[i] = NULL;
-               }
-       }
+       for (const auto &kv : conf->conf_targets)
+               kv.second->remove_lun(lun);
 }
 
 struct lun *
@@ -1518,11 +1723,6 @@ lun::verify()
 bool
 conf_verify(struct conf *conf)
 {
-       struct portal_group *pg;
-       struct target *targ;
-       bool found;
-       int i;
-
        if (conf->conf_pidfile_path == NULL)
                conf->conf_pidfile_path = checked_strdup(DEFAULT_PIDFILE);
 
@@ -1546,31 +1746,8 @@ conf_verify(struct conf *conf)
                }
        }
 
-       TAILQ_FOREACH(targ, &conf->conf_targets, t_next) {
-               if (targ->t_auth_group == NULL) {
-                       targ->t_auth_group = auth_group_find(conf,
-                           "default");
-                       assert(targ->t_auth_group != NULL);
-               }
-               if (targ->t_ports.empty()) {
-                       pg = portal_group_find(conf, "default");
-                       assert(pg != NULL);
-                       port_new(conf, targ, pg, nullptr);
-               }
-               found = false;
-               for (i = 0; i < MAX_LUNS; i++) {
-                       if (targ->t_luns[i] != NULL)
-                               found = true;
-               }
-               if (!found && targ->t_redirection == NULL) {
-                       log_warnx("no LUNs defined for target \"%s\"",
-                           targ->t_name);
-               }
-               if (found && targ->t_redirection != NULL) {
-                       log_debugx("target \"%s\" contains luns, "
-                           " but configured for redirection",
-                           targ->t_name);
-               }
+       for (auto &kv : conf->conf_targets) {
+               kv.second->verify();
        }
        for (auto &kv : conf->conf_portal_groups) {
                kv.second->verify(conf);
@@ -2361,40 +2538,41 @@ conf_new_from_file(const char *path, bool ucl)
 static bool
 new_pports_from_conf(struct conf *conf, struct kports &kports)
 {
-       struct target *targ;
        struct pport *pp;
        int ret, i_pp, i_vp;
 
-       TAILQ_FOREACH(targ, &conf->conf_targets, t_next) {
-               if (!targ->t_pport)
+       for (auto &kv : conf->conf_targets) {
+               struct target *targ = kv.second.get();
+
+               if (!targ->has_pport())
                        continue;
 
-               ret = sscanf(targ->t_pport, "ioctl/%d/%d", &i_pp, &i_vp);
+               ret = sscanf(targ->pport(), "ioctl/%d/%d", &i_pp, &i_vp);
                if (ret > 0) {
                        if (!port_new_ioctl(conf, kports, targ, i_pp, i_vp)) {
                                log_warnx("can't create new ioctl port "
-                                   "for target \"%s\"", targ->t_name);
+                                   "for target \"%s\"", targ->name());
                                return (false);
                        }
 
                        continue;
                }
 
-               pp = kports.find_port(targ->t_pport);
+               pp = kports.find_port(targ->pport());
                if (pp == NULL) {
                        log_warnx("unknown port \"%s\" for target \"%s\"",
-                           targ->t_pport, targ->t_name);
+                           targ->pport(), targ->name());
                        return (false);
                }
                if (pp->linked()) {
                        log_warnx("can't link port \"%s\" to target \"%s\", "
                            "port already linked to some target",
-                           targ->t_pport, targ->t_name);
+                           targ->pport(), targ->name());
                        return (false);
                }
                if (!port_new_pp(conf, targ, pp)) {
                        log_warnx("can't link port \"%s\" to target \"%s\"",
-                           targ->t_pport, targ->t_name);
+                           targ->pport(), targ->name());
                        return (false);
                }
        }
diff --git a/usr.sbin/ctld/ctld.hh b/usr.sbin/ctld/ctld.hh
index 7fb0ed7a8bea..a242a3282b31 100644
--- a/usr.sbin/ctld/ctld.hh
+++ b/usr.sbin/ctld/ctld.hh
@@ -41,6 +41,7 @@
 #include <libiscsiutil.h>
 #include <libutil.h>
 
+#include <array>
 #include <list>
 #include <memory>
 #include <string>
@@ -347,16 +348,53 @@ private:
 };
 
 struct target {
-       TAILQ_ENTRY(target)             t_next;
+       target(struct conf *conf, std::string_view name) :
+               t_conf(conf), t_name(name) {}
+
+       bool has_alias() const { return !t_alias.empty(); }
+       bool has_pport() const { return !t_pport.empty(); }
+       bool has_redirection() const { return !t_redirection.empty(); }
+       const char *alias() const { return t_alias.c_str(); }
+       const char *name() const { return t_name.c_str(); }
+       const char *pport() const { return t_pport.c_str(); }
+       bool private_auth() const { return t_private_auth; }
+       const char *redirection() const { return t_redirection.c_str(); }
+
+       struct auth_group *auth_group() const { return t_auth_group.get(); }
+       const std::list<port *> &ports() const { return t_ports; }
+       const struct lun *lun(int idx) const { return t_luns[idx]; }
+
+       bool add_chap(const char *user, const char *secret);
+       bool add_chap_mutual(const char *user, const char *secret,
+           const char *user2, const char *secret2);
+       bool add_initiator_name(std::string_view name);
+       bool add_initiator_portal(const char *addr);
+       bool add_lun(u_int id, const char *lun_name);
+       bool add_portal_group(const char *pg_name, const char *ag_name);
+       bool set_alias(std::string_view alias);
+       bool set_auth_group(const char *ag_name);
+       bool set_auth_type(const char *type);
+       bool set_physical_port(std::string_view pport);
+       bool set_redirection(const char *addr);
+       struct lun *start_lun(u_int id);
+
+       void add_port(struct port *port);
+       void remove_lun(struct lun *lun);
+       void remove_port(struct port *port);
+       void verify();
+
+private:
+       bool use_private_auth(const char *keyword);
+
        struct conf                     *t_conf;
-       struct lun                      *t_luns[MAX_LUNS] = {};
+       std::array<struct lun *, MAX_LUNS> t_luns;
        auth_group_sp                   t_auth_group;
        std::list<port *>               t_ports;
-       char                            *t_name;
-       char                            *t_alias;
-       char                            *t_redirection;
+       std::string                     t_name;
+       std::string                     t_alias;
+       std::string                     t_redirection;
        /* Name of this target's physical port, if any, i.e. "isp0" */
-       char                            *t_pport;
+       std::string                     t_pport;
        bool                            t_private_auth;
 };
 
@@ -379,11 +417,12 @@ struct conf {
 
        char                            *conf_pidfile_path = nullptr;
        std::unordered_map<std::string, std::unique_ptr<lun>> conf_luns;
-       TAILQ_HEAD(, target)            conf_targets;
+       std::unordered_map<std::string, std::unique_ptr<target>> conf_targets;
        std::unordered_map<std::string, auth_group_sp> conf_auth_groups;
        std::unordered_map<std::string, std::unique_ptr<port>> conf_ports;
        std::unordered_map<std::string, portal_group_up> conf_portal_groups;
        std::unordered_map<std::string, isns> conf_isns;
+       struct target                   *conf_first_target = nullptr;
        int                             conf_isns_period;
        int                             conf_isns_timeout;
        int                             conf_debug;
@@ -466,7 +505,6 @@ void                        conf_start(struct conf 
*new_conf);
 bool                   conf_verify(struct conf *conf);
 
 struct auth_group      *auth_group_new(struct conf *conf, const char *name);
-auth_group_sp          auth_group_new(struct target *target);
*** 233 LINES SKIPPED ***

Reply via email to