aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2026-06-25 16:21:25 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2026-06-27 16:01:55 +0000
commit4907d1c5c7f97ca985611441df5871705b90030c (patch)
tree8c0dea8730ee09dbc6a6310bbeb32c6dde22b12d
parent27e292627589172e70ea01a736f639d7aedbab9d (diff)
ctld: Normalize physical port names
Don't require ioctl port names to be fully expanded as this contradicts the syntax documented in the ctl.conf(5). However, don't require users to exactly guess when pp or vp can be omitted. Instead, normalize all physical port names by parsing any port name with a pp or vp value and reformatting them to a standardized format. This format is also used when generating names for kernel-enumerated ports. Reported by: Seth Hoffert <seth.hoffert@gmail.com> Fixes: caef3c50ac06 ("ctld: Refactor ioctl port handling") Sponsored by: Chelsio Communications
-rw-r--r--usr.sbin/ctld/ctld.cc59
-rw-r--r--usr.sbin/ctld/kernel.cc5
2 files changed, 51 insertions, 13 deletions
diff --git a/usr.sbin/ctld/ctld.cc b/usr.sbin/ctld/ctld.cc
index 834bef4ef363..19baa0486e44 100644
--- a/usr.sbin/ctld/ctld.cc
+++ b/usr.sbin/ctld/ctld.cc
@@ -53,6 +53,7 @@
#include <cam/scsi/scsi_all.h>
#include <algorithm>
+#include <charconv>
#include <libutil++.hh>
#include "conf.h"
@@ -1378,17 +1379,55 @@ target::set_auth_type(const char *type)
bool
target::add_physical_port(std::string_view pport)
{
- /* Normalize ioctl port names. */
+ /* Normalize port names. */
std::string pname;
- if (pport.compare(0, strlen("ioctl/"), "ioctl/") == 0) {
- int ret, pp, vp;
+ size_t pos = pport.find('/');
+ if (pos == 0) {
+ log_warnx("invalid physical port \"%s\" for target "
+ "\"%s\"", std::string(pport).c_str(), name());
+ return (false);
+ }
+
+ if (pos != pport.npos) {
+ const char *pport_end = pport.data() + pport.size();
+ int pp, vp;
+
+ auto parse_int = [](const char *start, const char *end) -> int {
+ int value;
+
+ if (start == end)
+ return -1;
+
+ auto [ptr, ec] = std::from_chars(start, end, value);
+ if (ec != std::errc() || ptr != end)
+ return -1;
+ return value;
+ };
+
+ const char *ppstart = pport.data() + pos + 1;
+ size_t ppend = pport.find('/', pos + 1);
+ if (ppend == pport.npos) {
+ pp = parse_int(ppstart, pport_end);
+ vp = 0;
+ } else {
+ const char *vpstart = pport.data() + ppend + 1;
+ pp = parse_int(ppstart, pport.data() + ppend);
+ vp = parse_int(vpstart, pport_end);
+ }
+
+ if (pp == -1 || vp == -1) {
+ log_warnx("invalid physical port \"%s\" for target "
+ "\"%s\"", std::string(pport).c_str(), name());
+ return (false);
+ }
- pname = std::string(pport);
- ret = sscanf(pname.c_str(), "ioctl/%d/%d", &pp, &vp);
- if (ret == 2) {
- pname = freebsd::stringf("ioctl/%d/%d", pp, vp);
- pport = pname;
+ pname = pport.substr(0, pos);
+ if (pp != 0 || vp != 0) {
+ pname += "/" + std::to_string(pp);
+ if (vp != 0)
+ pname += "/" + std::to_string(vp);
}
+ pport = pname;
}
for (const auto &s : t_pports) {
@@ -2679,7 +2718,9 @@ conf::add_pports(struct kports &kports)
*/
ret = sscanf(pport.c_str(), "ioctl/%d/%d", &i_pp,
&i_vp);
- if (ret == 2) {
+ if (ret > 0) {
+ if (ret == 1)
+ i_vp = 0;
if (!add_port(targ, pport, i_pp, i_vp)) {
log_warnx("can't create new port %s "
"for %s", pport.c_str(),
diff --git a/usr.sbin/ctld/kernel.cc b/usr.sbin/ctld/kernel.cc
index f84440d64c23..188d01052a1c 100644
--- a/usr.sbin/ctld/kernel.cc
+++ b/usr.sbin/ctld/kernel.cc
@@ -559,10 +559,7 @@ conf_new_from_kernel(struct kports &kports)
continue;
std::string name = port.port_name;
- if (port.port_frontend == "ioctl")
- name += "/" + std::to_string(port.pp) + "/" +
- std::to_string(port.vp);
- else if (port.pp != 0 || port.vp != 0) {
+ if (port.pp != 0 || port.vp != 0) {
name += "/" + std::to_string(port.pp);
if (port.vp != 0)
name += "/" + std::to_string(port.vp);