The branch main has been updated by jhb:

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

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

    ctld: Convert struct auth_group to a C++ class
    
    Make data members private and convert functions for adding and
    checking user and initiator authentication into class methods.
    
    Use std::string to store the label for an auth_group and add a label()
    method to retrieve a const C string version for logging.
    
    Replace AG_TYPE_* macros with a scoped enum.
    
    Replace the TAILQ of auth_group objects in struct conf with an
    unordered_map<> of named auth_group objects.  Anonymous auth_group
    objects for targets are no longer stored in a global data structure.
    
    Since a target can have a pointer to either named or anonymous
    objects, use a shared_ptr<> to store references to auth_group objects.
    Use the shared_ptr<>'s reference count to determine if a named
    auth_group is unused in conf_verify() instead of walking all the
    linked lists to check for references.
    
    While here, avoid making a second copy of socket address for a client
    and instead just store a pointer in ctld_connection.
    
    Sponsored by:   Chelsio Communications
    Pull Request:   https://github.com/freebsd/freebsd-src/pull/1794
---
 usr.sbin/ctld/conf.cc      |  74 ++++---------
 usr.sbin/ctld/ctld.cc      | 260 ++++++++++++++++++++-------------------------
 usr.sbin/ctld/ctld.hh      | 115 ++++++++++----------
 usr.sbin/ctld/discovery.cc |  18 ++--
 usr.sbin/ctld/login.cc     |  35 +++---
 5 files changed, 221 insertions(+), 281 deletions(-)

diff --git a/usr.sbin/ctld/conf.cc b/usr.sbin/ctld/conf.cc
index 4354d25147a4..a30bf72c0469 100644
--- a/usr.sbin/ctld/conf.cc
+++ b/usr.sbin/ctld/conf.cc
@@ -114,64 +114,35 @@ conf_set_timeout(int timeout)
        conf->conf_timeout = timeout;
 }
 
-static bool
-_auth_group_set_type(struct auth_group *ag, const char *str)
-{
-       int type;
-
-       if (strcmp(str, "none") == 0) {
-               type = AG_TYPE_NO_AUTHENTICATION;
-       } else if (strcmp(str, "deny") == 0) {
-               type = AG_TYPE_DENY;
-       } else if (strcmp(str, "chap") == 0) {
-               type = AG_TYPE_CHAP;
-       } else if (strcmp(str, "chap-mutual") == 0) {
-               type = AG_TYPE_CHAP_MUTUAL;
-       } else {
-               log_warnx("invalid auth-type \"%s\" for %s", str, ag->ag_label);
-               return (false);
-       }
-
-       if (ag->ag_type != AG_TYPE_UNKNOWN && ag->ag_type != type) {
-               log_warnx("cannot set auth-type to \"%s\" for %s; "
-                   "already has a different type", str, ag->ag_label);
-               return (false);
-       }
-
-       ag->ag_type = type;
-
-       return (true);
-}
-
 bool
 auth_group_add_chap(const char *user, const char *secret)
 {
-       return (auth_new_chap(auth_group, user, secret));
+       return (auth_group->add_chap(user, secret));
 }
 
 bool
 auth_group_add_chap_mutual(const char *user, const char *secret,
     const char *user2, const char *secret2)
 {
-       return (auth_new_chap_mutual(auth_group, user, secret, user2, secret2));
+       return (auth_group->add_chap_mutual(user, secret, user2, secret2));
 }
 
 bool
 auth_group_add_initiator_name(const char *name)
 {
-       return (auth_name_new(auth_group, name));
+       return (auth_group->add_initiator_name(name));
 }
 
 bool
 auth_group_add_initiator_portal(const char *portal)
 {
-       return (auth_portal_new(auth_group, portal));
+       return (auth_group->add_initiator_portal(portal));
 }
 
 bool
 auth_group_set_type(const char *type)
 {
-       return (_auth_group_set_type(auth_group, type));
+       return (auth_group->set_type(type));
 }
 
 bool
@@ -188,12 +159,12 @@ auth_group_start(const char *name)
                }
 
                conf->conf_default_ag_defined = true;
-               auth_group = auth_group_find(conf, "default");
+               auth_group = auth_group_find(conf, "default").get();
                return (true);
        }
 
        auth_group = auth_group_new(conf, name);
-       return (auth_group != NULL);
+       return (auth_group != nullptr);
 }
 
 void
@@ -245,14 +216,14 @@ portal_group_add_option(const char *name, const char 
*value)
 bool
 portal_group_set_discovery_auth_group(const char *name)
 {
-       if (portal_group->pg_discovery_auth_group != NULL) {
+       if (portal_group->pg_discovery_auth_group != nullptr) {
                log_warnx("discovery-auth-group for portal-group "
                    "\"%s\" specified more than once",
                    portal_group->pg_name);
                return (false);
        }
        portal_group->pg_discovery_auth_group = auth_group_find(conf, name);
-       if (portal_group->pg_discovery_auth_group == NULL) {
+       if (portal_group->pg_discovery_auth_group == nullptr) {
                log_warnx("unknown discovery-auth-group \"%s\" "
                    "for portal-group \"%s\"", name, portal_group->pg_name);
                return (false);
@@ -518,15 +489,15 @@ target_finish(void)
 static bool
 target_use_private_auth(const char *keyword)
 {
-       if (target->t_auth_group != NULL) {
+       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(conf, target);
-               if (target->t_auth_group == NULL)
+               target->t_auth_group = auth_group_new(target);
+               if (target->t_auth_group == nullptr)
                        return (false);
                target->t_private_auth = true;
        }
@@ -538,7 +509,7 @@ target_add_chap(const char *user, const char *secret)
 {
        if (!target_use_private_auth("chap"))
                return (false);
-       return (auth_new_chap(target->t_auth_group, user, secret));
+       return (target->t_auth_group->add_chap(user, secret));
 }
 
 bool
@@ -547,7 +518,7 @@ target_add_chap_mutual(const char *user, const char *secret,
 {
        if (!target_use_private_auth("chap-mutual"))
                return (false);
-       return (auth_new_chap_mutual(target->t_auth_group, user, secret, user2,
+       return (target->t_auth_group->add_chap_mutual(user, secret, user2,
            secret2));
 }
 
@@ -556,7 +527,7 @@ target_add_initiator_name(const char *name)
 {
        if (!target_use_private_auth("initiator-name"))
                return (false);
-       return (auth_name_new(target->t_auth_group, name));
+       return (target->t_auth_group->add_initiator_name(name));
 }
 
 bool
@@ -564,7 +535,7 @@ target_add_initiator_portal(const char *addr)
 {
        if (!target_use_private_auth("initiator-portal"))
                return (false);
-       return (auth_portal_new(target->t_auth_group, addr));
+       return (target->t_auth_group->add_initiator_portal(addr));
 }
 
 bool
@@ -599,7 +570,7 @@ bool
 target_add_portal_group(const char *pg_name, const char *ag_name)
 {
        struct portal_group *pg;
-       struct auth_group *ag;
+       auth_group_sp ag;
        struct port *p;
 
        pg = portal_group_find(conf, pg_name);
@@ -616,8 +587,7 @@ target_add_portal_group(const char *pg_name, const char 
*ag_name)
                            ag_name, target->t_name);
                        return (false);
                }
-       } else
-               ag = NULL;
+       }
 
        p = port_new(conf, target, pg);
        if (p == NULL) {
@@ -625,7 +595,7 @@ target_add_portal_group(const char *pg_name, const char 
*ag_name)
                    pg_name, target->t_name);
                return (false);
        }
-       p->p_auth_group = ag;
+       p->p_auth_group = std::move(ag);
        return (true);
 }
 
@@ -644,7 +614,7 @@ target_set_alias(const char *alias)
 bool
 target_set_auth_group(const char *name)
 {
-       if (target->t_auth_group != NULL) {
+       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);
@@ -654,7 +624,7 @@ target_set_auth_group(const char *name)
                return (false);
        }
        target->t_auth_group = auth_group_find(conf, name);
-       if (target->t_auth_group == NULL) {
+       if (target->t_auth_group == nullptr) {
                log_warnx("unknown auth-group \"%s\" for target \"%s\"", name,
                    target->t_name);
                return (false);
@@ -667,7 +637,7 @@ target_set_auth_type(const char *type)
 {
        if (!target_use_private_auth("auth-type"))
                return (false);
-       return (_auth_group_set_type(target->t_auth_group, type));
+       return (target->t_auth_group->set_type(type));
 }
 
 bool
diff --git a/usr.sbin/ctld/ctld.cc b/usr.sbin/ctld/ctld.cc
index 396b8db13323..b2cf31fff18f 100644
--- a/usr.sbin/ctld/ctld.cc
+++ b/usr.sbin/ctld/ctld.cc
@@ -100,12 +100,9 @@ conf_new(void)
 {
        struct conf *conf;
 
-       conf = reinterpret_cast<struct conf *>(calloc(1, sizeof(*conf)));
-       if (conf == NULL)
-               log_err(1, "calloc");
+       conf = new struct conf();
        TAILQ_INIT(&conf->conf_luns);
        TAILQ_INIT(&conf->conf_targets);
-       TAILQ_INIT(&conf->conf_auth_groups);
        TAILQ_INIT(&conf->conf_ports);
        TAILQ_INIT(&conf->conf_portal_groups);
        TAILQ_INIT(&conf->conf_isns);
@@ -124,7 +121,6 @@ conf_delete(struct conf *conf)
 {
        struct lun *lun, *ltmp;
        struct target *targ, *tmp;
-       struct auth_group *ag, *cagtmp;
        struct portal_group *pg, *cpgtmp;
        struct isns *is, *istmp;
 
@@ -134,30 +130,65 @@ conf_delete(struct conf *conf)
                lun_delete(lun);
        TAILQ_FOREACH_SAFE(targ, &conf->conf_targets, t_next, tmp)
                target_delete(targ);
-       TAILQ_FOREACH_SAFE(ag, &conf->conf_auth_groups, ag_next, cagtmp)
-               auth_group_delete(ag);
        TAILQ_FOREACH_SAFE(pg, &conf->conf_portal_groups, pg_next, cpgtmp)
                portal_group_delete(pg);
        TAILQ_FOREACH_SAFE(is, &conf->conf_isns, i_next, istmp)
                isns_delete(is);
        assert(TAILQ_EMPTY(&conf->conf_ports));
        free(conf->conf_pidfile_path);
-       free(conf);
+       delete conf;
+}
+
+bool
+auth_group::set_type(const char *str)
+{
+       auth_type type;
+
+       if (strcmp(str, "none") == 0) {
+               type = auth_type::NO_AUTHENTICATION;
+       } else if (strcmp(str, "deny") == 0) {
+               type = auth_type::DENY;
+       } else if (strcmp(str, "chap") == 0) {
+               type = auth_type::CHAP;
+       } else if (strcmp(str, "chap-mutual") == 0) {
+               type = auth_type::CHAP_MUTUAL;
+       } else {
+               log_warnx("invalid auth-type \"%s\" for %s", str, label());
+               return (false);
+       }
+
+       if (ag_type != auth_type::UNKNOWN && ag_type != type) {
+               log_warnx("cannot set auth-type to \"%s\" for %s; "
+                   "already has a different type", str, label());
+               return (false);
+       }
+
+       ag_type = type;
+
+       return (true);
+}
+
+void
+auth_group::set_type(auth_type type)
+{
+       assert(ag_type == auth_type::UNKNOWN);
+
+       ag_type = type;
 }
 
 const struct auth *
-auth_find(const struct auth_group *ag, const char *user)
+auth_group::find_auth(std::string_view user) const
 {
-       auto it = ag->ag_auths.find(user);
-       if (it == ag->ag_auths.end())
+       auto it = ag_auths.find(std::string(user));
+       if (it == ag_auths.end())
                return (nullptr);
 
        return (&it->second);
 }
 
-static void
-auth_check_secret_length(const struct auth_group *ag, const char *user,
-    const char *secret, const char *secret_type)
+void
+auth_group::check_secret_length(const char *user, const char *secret,
+    const char *secret_type)
 {
        size_t len;
 
@@ -165,34 +196,31 @@ auth_check_secret_length(const struct auth_group *ag, 
const char *user,
        assert(len != 0);
        if (len > 16) {
                log_warnx("%s for user \"%s\", %s, is too long; it should be "
-                   "at most 16 characters long", secret_type, user,
-                   ag->ag_label);
+                   "at most 16 characters long", secret_type, user, label());
        }
        if (len < 12) {
                log_warnx("%s for user \"%s\", %s, is too short; it should be "
-                   "at least 12 characters long", secret_type, user,
-                   ag->ag_label);
+                   "at least 12 characters long", secret_type, user, label());
        }
 }
 
 bool
-auth_new_chap(struct auth_group *ag, const char *user,
-    const char *secret)
+auth_group::add_chap(const char *user, const char *secret)
 {
-       if (ag->ag_type == AG_TYPE_UNKNOWN)
-               ag->ag_type = AG_TYPE_CHAP;
-       if (ag->ag_type != AG_TYPE_CHAP) {
+       if (ag_type == auth_type::UNKNOWN)
+               ag_type = auth_type::CHAP;
+       if (ag_type != auth_type::CHAP) {
                log_warnx("cannot mix \"chap\" authentication with "
-                   "other types for %s", ag->ag_label);
+                   "other types for %s", label());
                return (false);
        }
 
-       auth_check_secret_length(ag, user, secret, "secret");
+       check_secret_length(user, secret, "secret");
 
-       const auto &pair = ag->ag_auths.try_emplace(user, secret);
+       const auto &pair = ag_auths.try_emplace(user, secret);
        if (!pair.second) {
                log_warnx("duplicate credentials for user \"%s\" for %s",
-                   user, ag->ag_label);
+                   user, label());
                return (false);
        }
 
@@ -200,25 +228,24 @@ auth_new_chap(struct auth_group *ag, const char *user,
 }
 
 bool
-auth_new_chap_mutual(struct auth_group *ag, const char *user,
-    const char *secret, const char *user2, const char *secret2)
+auth_group::add_chap_mutual(const char *user, const char *secret,
+    const char *user2, const char *secret2)
 {
-       if (ag->ag_type == AG_TYPE_UNKNOWN)
-               ag->ag_type = AG_TYPE_CHAP_MUTUAL;
-       if (ag->ag_type != AG_TYPE_CHAP_MUTUAL) {
+       if (ag_type == auth_type::UNKNOWN)
+               ag_type = auth_type::CHAP_MUTUAL;
+       if (ag_type != auth_type::CHAP_MUTUAL) {
                log_warnx("cannot mix \"chap-mutual\" authentication "
-                   "with other types for %s", ag->ag_label);
+                   "with other types for %s", label());
                return (false);
        }
 
-       auth_check_secret_length(ag, user, secret, "secret");
-       auth_check_secret_length(ag, user, secret2, "mutual secret");
+       check_secret_length(user, secret, "secret");
+       check_secret_length(user, secret2, "mutual secret");
 
-       const auto &pair = ag->ag_auths.try_emplace(user, secret, user2,
-           secret2);
+       const auto &pair = ag_auths.try_emplace(user, secret, user2, secret2);
        if (!pair.second) {
                log_warnx("duplicate credentials for user \"%s\" for %s",
-                   user, ag->ag_label);
+                   user, label());
                return (false);
        }
 
@@ -226,20 +253,20 @@ auth_new_chap_mutual(struct auth_group *ag, const char 
*user,
 }
 
 bool
-auth_name_new(struct auth_group *ag, const char *name)
+auth_group::add_initiator_name(std::string_view name)
 {
        /* Silently ignore duplicates. */
-       ag->ag_names.emplace(name);
+       ag_names.emplace(name);
        return (true);
 }
 
 bool
-auth_name_check(const struct auth_group *ag, const char *initiator_name)
+auth_group::initiator_permitted(std::string_view initiator_name) const
 {
-       if (ag->ag_names.empty())
+       if (ag_names.empty())
                return (true);
 
-       return (ag->ag_names.count(initiator_name) != 0);
+       return (ag_names.count(std::string(initiator_name)) != 0);
 }
 
 bool
@@ -309,15 +336,16 @@ auth_portal::parse(const char *portal)
 }
 
 bool
-auth_portal_new(struct auth_group *ag, const char *portal)
+auth_group::add_initiator_portal(const char *portal)
 {
        auth_portal ap;
        if (!ap.parse(portal)) {
-               log_warnx("invalid initiator portal \"%s\"", portal);
+               log_warnx("invalid initiator portal \"%s\" for %s", portal,
+                   label());
                return (false);
        }
 
-       ag->ag_portals.emplace_back(ap);
+       ag_portals.emplace_back(ap);
        return (true);
 }
 
@@ -354,80 +382,46 @@ auth_portal::matches(const struct sockaddr *sa) const
 }
 
 bool
-auth_portal_check(const struct auth_group *ag,
-    const struct sockaddr_storage *sa)
+auth_group::initiator_permitted(const struct sockaddr *sa) const
 {
-       if (ag->ag_portals.empty())
+       if (ag_portals.empty())
                return (true);
 
-       for (const auth_portal &ap : ag->ag_portals)
-               if (ap.matches((const struct sockaddr *)sa))
+       for (const auth_portal &ap : ag_portals)
+               if (ap.matches(sa))
                        return (true);
        return (false);
 }
 
-static struct auth_group *
-auth_group_create(struct conf *conf, const char *name, char *label)
-{
-       struct auth_group *ag;
-
-       ag = new auth_group();
-       if (name != NULL)
-               ag->ag_name = checked_strdup(name);
-       ag->ag_label = label;
-       ag->ag_conf = conf;
-       TAILQ_INSERT_TAIL(&conf->conf_auth_groups, ag, ag_next);
-
-       return (ag);
-}
-
 struct auth_group *
 auth_group_new(struct conf *conf, const char *name)
 {
-       struct auth_group *ag;
-       char *label;
-
-       ag = auth_group_find(conf, name);
-       if (ag != NULL) {
+       const auto &pair = conf->conf_auth_groups.try_emplace(name,
+           std::make_shared<auth_group>(freebsd::stringf("auth-group \"%s\"",
+           name)));
+       if (!pair.second) {
                log_warnx("duplicated auth-group \"%s\"", name);
                return (NULL);
        }
 
-       asprintf(&label, "auth-group \"%s\"", name);
-       return (auth_group_create(conf, name, label));
+       return (pair.first->second.get());
 }
 
-struct auth_group *
-auth_group_new(struct conf *conf, struct target *target)
+auth_group_sp
+auth_group_new(struct target *target)
 {
-       char *label;
-
-       asprintf(&label, "target \"%s\"", target->t_name);
-       return (auth_group_create(conf, NULL, label));
+       return (std::make_shared<auth_group>(freebsd::stringf("target \"%s\"",
+           target->t_name)));
 }
 
-void
-auth_group_delete(struct auth_group *ag)
-{
-       TAILQ_REMOVE(&ag->ag_conf->conf_auth_groups, ag, ag_next);
-
-       free(ag->ag_label);
-       free(ag->ag_name);
-       delete ag;
-}
-
-struct auth_group *
+auth_group_sp
 auth_group_find(const struct conf *conf, const char *name)
 {
-       struct auth_group *ag;
-
-       assert(name != NULL);
-       TAILQ_FOREACH(ag, &conf->conf_auth_groups, ag_next) {
-               if (ag->ag_name != NULL && strcmp(ag->ag_name, name) == 0)
-                       return (ag);
-       }
+       auto it = conf->conf_auth_groups.find(name);
+       if (it == conf->conf_auth_groups.end())
+               return {};
 
-       return (NULL);
+       return (it->second);
 }
 
 static struct portal *
@@ -466,9 +460,7 @@ portal_group_new(struct conf *conf, const char *name)
                return (NULL);
        }
 
-       pg = reinterpret_cast<struct portal_group *>(calloc(1, sizeof(*pg)));
-       if (pg == NULL)
-               log_err(1, "calloc");
+       pg = new portal_group();
        pg->pg_name = checked_strdup(name);
        pg->pg_options = nvlist_create(0);
        TAILQ_INIT(&pg->pg_portals);
@@ -498,7 +490,7 @@ portal_group_delete(struct portal_group *pg)
        free(pg->pg_name);
        free(pg->pg_offload);
        free(pg->pg_redirection);
-       free(pg);
+       delete pg;
 }
 
 struct portal_group *
@@ -920,9 +912,7 @@ port_new(struct conf *conf, struct target *target, struct 
portal_group *pg)
                free(name);
                return (NULL);
        }
-       port = reinterpret_cast<struct port *>(calloc(1, sizeof(*port)));
-       if (port == NULL)
-               log_err(1, "calloc");
+       port = new struct port();
        port->p_conf = conf;
        port->p_name = name;
        TAILQ_INSERT_TAIL(&conf->conf_ports, port, p_next);
@@ -965,9 +955,7 @@ port_new_ioctl(struct conf *conf, struct kports *kports, 
struct target *target,
                free(name);
                return (NULL);
        }
-       port = reinterpret_cast<struct port *>(calloc(1, sizeof(*port)));
-       if (port == NULL)
-               log_err(1, "calloc");
+       port = new struct port();
        port->p_conf = conf;
        port->p_name = name;
        port->p_ioctl_port = true;
@@ -994,9 +982,7 @@ port_new_pp(struct conf *conf, struct target *target, 
struct pport *pp)
                free(name);
                return (NULL);
        }
-       port = reinterpret_cast<struct port *>(calloc(1, sizeof(*port)));
-       if (port == NULL)
-               log_err(1, "calloc");
+       port = new struct port();
        port->p_conf = conf;
        port->p_name = name;
        TAILQ_INSERT_TAIL(&conf->conf_ports, port, p_next);
@@ -1075,9 +1061,7 @@ target_new(struct conf *conf, const char *name)
        if (valid_iscsi_name(name, log_warnx) == false) {
                return (NULL);
        }
-       targ = reinterpret_cast<struct target *>(calloc(1, sizeof(*targ)));
-       if (targ == NULL)
-               log_err(1, "calloc");
+       targ = new target();
        targ->t_name = checked_strdup(name);
 
        /*
@@ -1106,7 +1090,7 @@ target_delete(struct target *targ)
        free(targ->t_pport);
        free(targ->t_name);
        free(targ->t_redirection);
-       free(targ);
+       delete targ;
 }
 
 struct target *
@@ -1260,7 +1244,7 @@ connection_new(struct portal *portal, int fd, const char 
*host,
        conn->conn.conn_socket = fd;
        conn->conn_portal = portal;
        conn->conn_initiator_addr = checked_strdup(host);
-       memcpy(&conn->conn_initiator_sa, client_sa, client_sa->sa_len);
+       conn->conn_initiator_sa = client_sa;
 
        return (conn);
 }
@@ -1324,9 +1308,7 @@ conf_verify_lun(struct lun *lun)
 bool
 conf_verify(struct conf *conf)
 {
-       struct auth_group *ag;
        struct portal_group *pg;
-       struct port *port;
        struct target *targ;
        struct lun *lun;
        bool found;
@@ -1393,32 +1375,16 @@ conf_verify(struct conf *conf)
                        pg->pg_unassigned = true;
                }
        }
-       TAILQ_FOREACH(ag, &conf->conf_auth_groups, ag_next) {
-               found = false;
-               TAILQ_FOREACH(targ, &conf->conf_targets, t_next) {
-                       if (targ->t_auth_group == ag) {
-                               found = true;
-                               break;
-                       }
-               }
-               TAILQ_FOREACH(port, &conf->conf_ports, p_next) {
-                       if (port->p_auth_group == ag) {
-                               found = true;
-                               break;
-                       }
-               }
-               TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) {
-                       if (pg->pg_discovery_auth_group == ag) {
-                               found = true;
-                               break;
-                       }
-               }
-               if (!found && ag->ag_name != NULL &&
-                   strcmp(ag->ag_name, "default") != 0 &&
-                   strcmp(ag->ag_name, "no-authentication") != 0 &&
-                   strcmp(ag->ag_name, "no-access") != 0) {
+       for (const auto &kv : conf->conf_auth_groups) {
+               const std::string &ag_name = kv.first;
+               if (ag_name == "default" ||
+                   ag_name == "no-authentication" ||
+                   ag_name == "no-access")
+                       continue;
+
+               if (kv.second.use_count() == 1) {
                        log_warnx("auth-group \"%s\" not assigned "
-                           "to any target", ag->ag_name);
+                           "to any target", ag_name.c_str());
                }
        }
 
@@ -2200,11 +2166,11 @@ conf_new_from_file(const char *path, bool ucl)
 
        ag = auth_group_new(conf, "no-authentication");
        assert(ag != NULL);
-       ag->ag_type = AG_TYPE_NO_AUTHENTICATION;
+       ag->set_type(auth_type::NO_AUTHENTICATION);
 
        ag = auth_group_new(conf, "no-access");
        assert(ag != NULL);
-       ag->ag_type = AG_TYPE_DENY;
+       ag->set_type(auth_type::DENY);
 
        pg = portal_group_new(conf, "default");
        assert(pg != NULL);
@@ -2226,9 +2192,9 @@ conf_new_from_file(const char *path, bool ucl)
        if (conf->conf_default_ag_defined == false) {
                log_debugx("auth-group \"default\" not defined; "
                    "going with defaults");
-               ag = auth_group_find(conf, "default");
+               ag = auth_group_find(conf, "default").get();
                assert(ag != NULL);
-               ag->ag_type = AG_TYPE_DENY;
+               ag->set_type(auth_type::DENY);
        }
 
        if (conf->conf_default_pg_defined == false) {
diff --git a/usr.sbin/ctld/ctld.hh b/usr.sbin/ctld/ctld.hh
index fa0b2256f8be..585e5d24663d 100644
--- a/usr.sbin/ctld/ctld.hh
+++ b/usr.sbin/ctld/ctld.hh
@@ -42,6 +42,7 @@
 #include <libutil.h>
 
 #include <list>
+#include <memory>
 #include <string>
 #include <string_view>
 #include <unordered_map>
@@ -83,23 +84,47 @@ private:
        int                             ap_mask = 0;
 };
 
-#define        AG_TYPE_UNKNOWN                 0
-#define        AG_TYPE_DENY                    1
-#define        AG_TYPE_NO_AUTHENTICATION       2
-#define        AG_TYPE_CHAP                    3
-#define        AG_TYPE_CHAP_MUTUAL             4
+enum class auth_type {
+       UNKNOWN,
+       DENY,
+       NO_AUTHENTICATION,
+       CHAP,
+       CHAP_MUTUAL
+};
 
 struct auth_group {
-       TAILQ_ENTRY(auth_group)         ag_next;
-       struct conf                     *ag_conf;
-       char                            *ag_name;
-       char                            *ag_label;
-       int                             ag_type;
+       auth_group(std::string label) : ag_label(label) {}
+
+       auth_type type() const { return ag_type; }
+       bool set_type(const char *str);
+       void set_type(auth_type type);
+
+       const char *label() const { return ag_label.c_str(); }
+
+       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);
+       const struct auth *find_auth(std::string_view user) const;
+
+       bool add_initiator_name(std::string_view initiator_name);
+       bool initiator_permitted(std::string_view initiator_name) const;
+
+       bool add_initiator_portal(const char *initiator_portal);
+       bool initiator_permitted(const struct sockaddr *sa) const;
+
+private:
+       void check_secret_length(const char *user, const char *secret,
+           const char *secret_type);
+
+       std::string                     ag_label;
+       auth_type                       ag_type = auth_type::UNKNOWN;
        std::unordered_map<std::string, auth> ag_auths;
        std::unordered_set<std::string> ag_names;
        std::list<auth_portal>          ag_portals;
 };
 
+using auth_group_sp = std::shared_ptr<auth_group>;
+
 struct portal {
        TAILQ_ENTRY(portal)             p_next;
        struct portal_group             *p_portal_group;
@@ -125,14 +150,14 @@ struct portal_group {
        struct conf                     *pg_conf;
        nvlist_t                        *pg_options;
        char                            *pg_name;
-       struct auth_group               *pg_discovery_auth_group;
-       int                             pg_discovery_filter;
-       bool                            pg_foreign;
-       bool                            pg_unassigned;
+       auth_group_sp                   pg_discovery_auth_group;
+       int                             pg_discovery_filter = PG_FILTER_UNKNOWN;
+       bool                            pg_foreign = false;
+       bool                            pg_unassigned = false;
        TAILQ_HEAD(, portal)            pg_portals;
        TAILQ_HEAD(, port)              pg_ports;
-       char                            *pg_offload;
-       char                            *pg_redirection;
+       char                            *pg_offload = nullptr;
+       char                            *pg_redirection = nullptr;
        int                             pg_dscp;
        int                             pg_pcp;
 
@@ -156,15 +181,15 @@ struct port {
        TAILQ_ENTRY(port)               p_ts;
        struct conf                     *p_conf;
        char                            *p_name;
-       struct auth_group               *p_auth_group;
-       struct portal_group             *p_portal_group;
-       struct pport                    *p_pport;
+       auth_group_sp                   p_auth_group;
+       struct portal_group             *p_portal_group = nullptr;
+       struct pport                    *p_pport = nullptr;
        struct target                   *p_target;
 
-       bool                            p_ioctl_port;
-       int                             p_ioctl_pp;
-       int                             p_ioctl_vp;
-       uint32_t                        p_ctl_port;
+       bool                            p_ioctl_port = false;
+       int                             p_ioctl_pp = 0;
+       int                             p_ioctl_vp = 0;
+       uint32_t                        p_ctl_port = 0;
 };
 
 struct lun {
@@ -187,8 +212,8 @@ struct lun {
 struct target {
        TAILQ_ENTRY(target)             t_next;
        struct conf                     *t_conf;
-       struct lun                      *t_luns[MAX_LUNS];
-       struct auth_group               *t_auth_group;
+       struct lun                      *t_luns[MAX_LUNS] = {};
+       auth_group_sp                   t_auth_group;
        TAILQ_HEAD(, port)              t_ports;
        char                            *t_name;
        char                            *t_alias;
@@ -206,10 +231,10 @@ struct isns {
 };
 
 struct conf {
-       char                            *conf_pidfile_path;
+       char                            *conf_pidfile_path = nullptr;
        TAILQ_HEAD(, lun)               conf_luns;
        TAILQ_HEAD(, target)            conf_targets;
-       TAILQ_HEAD(, auth_group)        conf_auth_groups;
+       std::unordered_map<std::string, auth_group_sp> conf_auth_groups;
        TAILQ_HEAD(, port)              conf_ports;
        TAILQ_HEAD(, portal_group)      conf_portal_groups;
        TAILQ_HEAD(, isns)              conf_isns;
@@ -220,13 +245,13 @@ struct conf {
        int                             conf_maxproc;
 
 #ifdef ICL_KERNEL_PROXY
-       int                             conf_portal_id;
+       int                             conf_portal_id = 0;
 #endif
-       struct pidfh                    *conf_pidfh;
+       struct pidfh                    *conf_pidfh = nullptr;
 
-       bool                            conf_default_pg_defined;
-       bool                            conf_default_ag_defined;
-       bool                            conf_kernel_port_on;
+       bool                            conf_default_pg_defined = false;
+       bool                            conf_default_ag_defined = false;
+       bool                            conf_kernel_port_on = false;
 };
 
 /* Physical ports exposed by the kernel */
@@ -248,7 +273,7 @@ struct ctld_connection {
        char                    *conn_initiator_addr;
        char                    *conn_initiator_alias;
        uint8_t                 conn_initiator_isid[6];
-       struct sockaddr_storage conn_initiator_sa;
+       const struct sockaddr   *conn_initiator_sa;
        int                     conn_max_recv_data_segment_limit;
        int                     conn_max_send_data_segment_limit;
        int                     conn_max_burst_limit;
@@ -270,30 +295,10 @@ 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);
-struct auth_group      *auth_group_new(struct conf *conf,
-                           struct target *target);
-void                   auth_group_delete(struct auth_group *ag);
-struct auth_group      *auth_group_find(const struct conf *conf,
+auth_group_sp          auth_group_new(struct target *target);
+auth_group_sp          auth_group_find(const struct conf *conf,
                            const char *name);
 
-bool                   auth_new_chap(struct auth_group *ag, const char *user,
-                           const char *secret);
-bool                   auth_new_chap_mutual(struct auth_group *ag,
-                           const char *user, const char *secret,
-                           const char *user2, const char *secret2);
-const struct auth      *auth_find(const struct auth_group *ag,
-                           const char *user);
-
-bool                   auth_name_new(struct auth_group *ag,
-                           const char *initiator_name);
-bool                   auth_name_check(const struct auth_group *ag,
-                           const char *initiator_name);
-
-bool                   auth_portal_new(struct auth_group *ag,
-                           const char *initiator_portal);
-bool                   auth_portal_check(const struct auth_group *ag,
-                           const struct sockaddr_storage *sa);
-
 struct portal_group    *portal_group_new(struct conf *conf, const char *name);
 void                   portal_group_delete(struct portal_group *pg);
 struct portal_group    *portal_group_find(const struct conf *conf,
diff --git a/usr.sbin/ctld/discovery.cc b/usr.sbin/ctld/discovery.cc
index c4bfb94669f9..5ef8a7e7027b 100644
--- a/usr.sbin/ctld/discovery.cc
+++ b/usr.sbin/ctld/discovery.cc
@@ -156,32 +156,32 @@ discovery_target_filtered_out(const struct 
ctld_connection *conn,
        int error;
 
        targ = port->p_target;
-       ag = port->p_auth_group;
-       if (ag == NULL)
-               ag = targ->t_auth_group;
+       ag = port->p_auth_group.get();
+       if (ag == nullptr)
+               ag = targ->t_auth_group.get();
        pg = conn->conn_portal->p_portal_group;
 
        assert(pg->pg_discovery_filter != PG_FILTER_UNKNOWN);
 
        if (pg->pg_discovery_filter >= PG_FILTER_PORTAL &&
-           !auth_portal_check(ag, &conn->conn_initiator_sa)) {
+           !ag->initiator_permitted(conn->conn_initiator_sa)) {
                log_debugx("initiator does not match initiator portals "
                    "allowed for target \"%s\"; skipping", targ->t_name);
                return (true);
        }
 
        if (pg->pg_discovery_filter >= PG_FILTER_PORTAL_NAME &&
-           !auth_name_check(ag, conn->conn_initiator_name)) {
+           !ag->initiator_permitted(conn->conn_initiator_name)) {
                log_debugx("initiator does not match initiator names "
                    "allowed for target \"%s\"; skipping", targ->t_name);
                return (true);
        }
 
        if (pg->pg_discovery_filter >= PG_FILTER_PORTAL_NAME_AUTH &&
-           ag->ag_type != AG_TYPE_NO_AUTHENTICATION) {
+           ag->type() != auth_type::NO_AUTHENTICATION) {
                if (conn->conn_chap == NULL) {
-                       assert(pg->pg_discovery_auth_group->ag_type ==
-                           AG_TYPE_NO_AUTHENTICATION);
+                       assert(pg->pg_discovery_auth_group->type() ==
*** 114 LINES SKIPPED ***

Reply via email to