diff options
| author | John Baldwin <jhb@FreeBSD.org> | 2025-08-04 19:38:07 +0000 |
|---|---|---|
| committer | John Baldwin <jhb@FreeBSD.org> | 2025-08-04 19:38:07 +0000 |
| commit | 2bb9180bb5d0054bf79529d6a1cb56b61a94629a (patch) | |
| tree | 667a863c287734a197ba95a254ea3b47d8aab803 | |
| parent | afcae14d2f241484c9c52aaa130a313eec0991c9 (diff) | |
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
| -rw-r--r-- | usr.sbin/ctld/conf.cc | 165 | ||||
| -rw-r--r-- | usr.sbin/ctld/ctld.cc | 406 | ||||
| -rw-r--r-- | usr.sbin/ctld/ctld.hh | 55 | ||||
| -rw-r--r-- | usr.sbin/ctld/discovery.cc | 16 | ||||
| -rw-r--r-- | usr.sbin/ctld/kernel.cc | 28 | ||||
| -rw-r--r-- | 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; } @@ -411,13 +407,6 @@ auth_group_new(struct conf *conf, const char *name) } 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) { auto it = conf->conf_auth_groups.find(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); auth_group_sp auth_group_find(const struct conf *conf, const char *name); @@ -486,7 +524,6 @@ bool port_new(struct conf *conf, struct target *target, struct portal_group *pg, uint32_t ctl_port); struct target *target_new(struct conf *conf, const char *name); -void target_delete(struct target *target); struct target *target_find(struct conf *conf, const char *name); diff --git a/usr.sbin/ctld/discovery.cc b/usr.sbin/ctld/discovery.cc index f3c1766ffc06..a98b5746735a 100644 --- a/usr.sbin/ctld/discovery.cc +++ b/usr.sbin/ctld/discovery.cc @@ -106,8 +106,8 @@ discovery_add_target(struct keys *response_keys, const struct target *targ) const struct addrinfo *ai; int ret; - keys_add(response_keys, "TargetName", targ->t_name); - for (const port *port : targ->t_ports) { + keys_add(response_keys, "TargetName", targ->name()); + for (const port *port : targ->ports()) { const struct portal_group *pg = port->portal_group(); if (pg == nullptr) continue; @@ -157,7 +157,7 @@ discovery_target_filtered_out(const struct ctld_connection *conn, targ = port->target(); ag = port->auth_group(); if (ag == nullptr) - ag = targ->t_auth_group.get(); + ag = targ->auth_group(); pg = conn->conn_portal->portal_group(); assert(pg->discovery_filter() != discovery_filter::UNKNOWN); @@ -165,14 +165,14 @@ discovery_target_filtered_out(const struct ctld_connection *conn, if (pg->discovery_filter() >= discovery_filter::PORTAL && !ag->initiator_permitted(conn->conn_initiator_sa)) { log_debugx("initiator does not match initiator portals " - "allowed for target \"%s\"; skipping", targ->t_name); + "allowed for target \"%s\"; skipping", targ->name()); return (true); } if (pg->discovery_filter() >= discovery_filter::PORTAL_NAME && !ag->initiator_permitted(conn->conn_initiator_name)) { log_debugx("initiator does not match initiator names " - "allowed for target \"%s\"; skipping", targ->t_name); + "allowed for target \"%s\"; skipping", targ->name()); return (true); } @@ -183,7 +183,7 @@ discovery_target_filtered_out(const struct ctld_connection *conn, auth_type::NO_AUTHENTICATION); log_debugx("initiator didn't authenticate, but target " - "\"%s\" requires CHAP; skipping", targ->t_name); + "\"%s\" requires CHAP; skipping", targ->name()); return (true); } @@ -191,7 +191,7 @@ discovery_target_filtered_out(const struct ctld_connection *conn, auth = ag->find_auth(conn->conn_user); if (auth == NULL) { log_debugx("CHAP user \"%s\" doesn't match target " - "\"%s\"; skipping", conn->conn_user, targ->t_name); + "\"%s\"; skipping", conn->conn_user, targ->name()); return (true); } @@ -199,7 +199,7 @@ discovery_target_filtered_out(const struct ctld_connection *conn, if (error != 0) { log_debugx("password for CHAP user \"%s\" doesn't " "match target \"%s\"; skipping", - conn->conn_user, targ->t_name); + conn->conn_user, targ->name()); return (true); } } diff --git a/usr.sbin/ctld/kernel.cc b/usr.sbin/ctld/kernel.cc index 7ce1bf210027..e84f75ad4f20 100644 --- a/usr.sbin/ctld/kernel.cc +++ b/usr.sbin/ctld/kernel.cc @@ -817,7 +817,7 @@ kernel_handoff(struct ctld_connection *conn) memcpy(req.data.handoff.initiator_isid, conn->conn_initiator_isid, sizeof(req.data.handoff.initiator_isid)); strlcpy(req.data.handoff.target_name, - conn->conn_target->t_name, sizeof(req.data.handoff.target_name)); + conn->conn_target->name(), sizeof(req.data.handoff.target_name)); strlcpy(req.data.handoff.offload, pg->offload(), sizeof(req.data.handoff.offload)); #ifdef ICL_KERNEL_PROXY @@ -910,14 +910,14 @@ portal_group_port::kernel_create_port() struct target *targ = p_target; freebsd::nvlist_up nvl = pg->options(); - nvlist_add_string(nvl.get(), "cfiscsi_target", targ->t_name); + nvlist_add_string(nvl.get(), "cfiscsi_target", targ->name()); nvlist_add_string(nvl.get(), "ctld_portal_group_name", pg->name()); nvlist_add_stringf(nvl.get(), "cfiscsi_portal_group_tag", "%u", pg->tag()); - if (targ->t_alias) { + if (targ->has_alias()) { nvlist_add_string(nvl.get(), "cfiscsi_target_alias", - targ->t_alias); + targ->alias()); } return (ctl_create_port("iscsi", nvl.get(), &p_ctl_port)); @@ -941,13 +941,13 @@ kernel_port::kernel_create_port() p_ctl_port = p_pport->ctl_port(); - if (strncmp(targ->t_name, "naa.", 4) == 0 && - strlen(targ->t_name) == 20) { + if (strncmp(targ->name(), "naa.", 4) == 0 && + strlen(targ->name()) == 20) { bzero(&entry, sizeof(entry)); entry.port_type = CTL_PORT_NONE; entry.targ_port = p_ctl_port; entry.flags |= CTL_PORT_WWNN_VALID; - entry.wwnn = strtoull(targ->t_name + 4, NULL, 16); + entry.wwnn = strtoull(targ->name() + 4, NULL, 16); if (ioctl(ctl_fd, CTL_SET_PORT_WWNS, &entry) == -1) log_warn("CTL_SET_PORT_WWNS ioctl failed"); } @@ -975,11 +975,11 @@ port::kernel_add() /* Map configured LUNs */ for (i = 0; i < MAX_LUNS; i++) { - if (targ->t_luns[i] == NULL) + if (targ->lun(i) == nullptr) continue; lm.port = p_ctl_port; lm.plun = i; - lm.lun = targ->t_luns[i]->ctl_lun(); + lm.lun = targ->lun(i)->ctl_lun(); error = ioctl(ctl_fd, CTL_LUN_MAP, &lm); if (error != 0) log_warn("CTL_LUN_MAP ioctl failed"); @@ -1012,14 +1012,14 @@ port::kernel_update(const struct port *oport) for (i = 0; i < MAX_LUNS; i++) { lm.port = p_ctl_port; lm.plun = i; - if (targ->t_luns[i] == NULL) + if (targ->lun(i) == nullptr) lm.lun = UINT32_MAX; else - lm.lun = targ->t_luns[i]->ctl_lun(); - if (otarg->t_luns[i] == NULL) + lm.lun = targ->lun(i)->ctl_lun(); + if (otarg->lun(i) == nullptr) olun = UINT32_MAX; else - olun = otarg->t_luns[i]->ctl_lun(); + olun = otarg->lun(i)->ctl_lun(); if (lm.lun == olun) continue; error = ioctl(ctl_fd, CTL_LUN_MAP, &lm); @@ -1066,7 +1066,7 @@ bool portal_group_port::kernel_remove_port() { freebsd::nvlist_up nvl(nvlist_create(0)); - nvlist_add_string(nvl.get(), "cfiscsi_target", p_target->t_name); + nvlist_add_string(nvl.get(), "cfiscsi_target", p_target->name()); nvlist_add_stringf(nvl.get(), "cfiscsi_portal_group_tag", "%u", p_portal_group->tag()); diff --git a/usr.sbin/ctld/login.cc b/usr.sbin/ctld/login.cc index 491cdc220aa6..61f32dcb0f51 100644 --- a/usr.sbin/ctld/login.cc +++ b/usr.sbin/ctld/login.cc @@ -722,12 +722,12 @@ login_target_redirect(struct ctld_connection *conn, struct pdu *request) if (conn->conn_target == NULL) return (false); - target_address = conn->conn_target->t_redirection; - if (target_address == NULL) + if (!conn->conn_target->has_redirection()) return (false); + target_address = conn->conn_target->redirection(); log_debugx("target \"%s\" configured to redirect to %s", - conn->conn_target->t_name, target_address); + conn->conn_target->name(), target_address); login_redirect(request, target_address); return (true); @@ -821,9 +821,9 @@ login_negotiate(struct ctld_connection *conn, struct pdu *request) if (skipped_security && conn->conn_session_type == CONN_SESSION_TYPE_NORMAL) { - if (conn->conn_target->t_alias != NULL) + if (conn->conn_target->has_alias()) keys_add(response_keys, - "TargetAlias", conn->conn_target->t_alias); + "TargetAlias", conn->conn_target->alias()); keys_add_int(response_keys, "TargetPortalGroupTag", pg->tag()); } @@ -988,15 +988,15 @@ login(struct ctld_connection *conn) if (conn->conn_session_type == CONN_SESSION_TYPE_NORMAL) { ag = conn->conn_port->auth_group(); if (ag == nullptr) - ag = conn->conn_target->t_auth_group.get(); + ag = conn->conn_target->auth_group(); if (conn->conn_port->auth_group() == nullptr && - conn->conn_target->t_private_auth) { + conn->conn_target->private_auth()) { log_debugx("initiator requests to connect " - "to target \"%s\"", conn->conn_target->t_name); + "to target \"%s\"", conn->conn_target->name()); } else { log_debugx("initiator requests to connect " "to target \"%s\"; %s", - conn->conn_target->t_name, ag->label()); + conn->conn_target->name(), ag->label()); } } else { assert(conn->conn_session_type == CONN_SESSION_TYPE_DISCOVERY); @@ -1083,9 +1083,9 @@ login(struct ctld_connection *conn) } } if (conn->conn_session_type == CONN_SESSION_TYPE_NORMAL) { - if (conn->conn_target->t_alias != NULL) + if (conn->conn_target->has_alias()) keys_add(response_keys, - "TargetAlias", conn->conn_target->t_alias); + "TargetAlias", conn->conn_target->alias()); keys_add_int(response_keys, "TargetPortalGroupTag", pg->tag()); } |
