Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 4 Aug 2025 19:46:48 GMT
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: eb0dc901a541 - main - ctld: Convert struct auth_group to a C++ class
Message-ID:  <202508041946.574JkmB1099061@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by jhb:

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

commit eb0dc901a54183dd8e2bd6ee37b64c7a3222301c
Author:     John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2025-08-04 19:38:06 +0000
Commit:     John Baldwin <jhb@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 ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202508041946.574JkmB1099061>