The branch main has been updated by jhb:

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

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

    ctld: Convert struct ctld_connection to a C++ class
    
    Note that some of the functions for handling iSCSI login, discovery,
    and kernel handoff are now functions of this class as they are logical
    operations on an iSCSI connection and need access to various members
    of this class.
    
    This also fixes some memory leaks as ctld_connection wasn't properly
    torn down once a connection finishes.  These leaks were harmless in
    practice since the ctld process exits after handling each connection.
    
    Sponsored by:   Chelsio Communications
    Pull Request:   https://github.com/freebsd/freebsd-src/pull/1794
---
 usr.sbin/ctld/ctld.cc      |  37 +++----
 usr.sbin/ctld/ctld.hh      |  54 ++++++----
 usr.sbin/ctld/discovery.cc |  36 +++----
 usr.sbin/ctld/kernel.cc    |  48 ++++-----
 usr.sbin/ctld/login.cc     | 246 ++++++++++++++++++++++-----------------------
 5 files changed, 213 insertions(+), 208 deletions(-)

diff --git a/usr.sbin/ctld/ctld.cc b/usr.sbin/ctld/ctld.cc
index 63b5f9164205..23d01364a6a4 100644
--- a/usr.sbin/ctld/ctld.cc
+++ b/usr.sbin/ctld/ctld.cc
@@ -1753,22 +1753,18 @@ pdu_fail(const struct connection *conn __unused, const 
char *reason __unused)
 {
 }
 
-static struct ctld_connection *
-connection_new(struct portal *portal, int fd, const char *host,
-    const struct sockaddr *client_sa)
+ctld_connection::ctld_connection(struct portal *portal, int fd,
+    const char *host, const struct sockaddr *client_sa) :
+       conn_portal(portal), conn_initiator_addr(host),
+       conn_initiator_sa(client_sa)
 {
-       struct ctld_connection *conn;
-
-       conn = reinterpret_cast<struct ctld_connection *>(calloc(1, 
sizeof(*conn)));
-       if (conn == NULL)
-               log_err(1, "calloc");
-       connection_init(&conn->conn, &conn_ops, proxy_mode);
-       conn->conn.conn_socket = fd;
-       conn->conn_portal = portal;
-       conn->conn_initiator_addr = checked_strdup(host);
-       conn->conn_initiator_sa = client_sa;
+       connection_init(&conn, &conn_ops, proxy_mode);
+       conn.conn_socket = fd;
+}
 
-       return (conn);
+ctld_connection::~ctld_connection()
+{
+       chap_delete(conn_chap);
 }
 
 bool
@@ -2349,7 +2345,6 @@ static void
 handle_connection(struct portal *portal, int fd,
     const struct sockaddr *client_sa, bool dont_fork)
 {
-       struct ctld_connection *conn;
        struct portal_group *pg;
        int error;
        pid_t pid;
@@ -2395,16 +2390,16 @@ handle_connection(struct portal *portal, int fd,
        log_set_peer_addr(host);
        setproctitle("%s", host);
 
-       conn = connection_new(portal, fd, host, client_sa);
+       ctld_connection conn(portal, fd, host, client_sa);
        start_timer(conf->timeout(), true);
        kernel_capsicate();
-       login(conn);
-       if (conn->conn_session_type == CONN_SESSION_TYPE_NORMAL) {
-               kernel_handoff(conn);
+       conn.login();
+       if (conn.session_type() == CONN_SESSION_TYPE_NORMAL) {
+               conn.kernel_handoff();
                log_debugx("connection handed off to the kernel");
        } else {
-               assert(conn->conn_session_type == CONN_SESSION_TYPE_DISCOVERY);
-               discovery(conn);
+               assert(conn.session_type() == CONN_SESSION_TYPE_DISCOVERY);
+               conn.discovery();
        }
        log_debugx("nothing more to do; exiting");
        exit(0);
diff --git a/usr.sbin/ctld/ctld.hh b/usr.sbin/ctld/ctld.hh
index 1a71971c6a1d..059f719668f9 100644
--- a/usr.sbin/ctld/ctld.hh
+++ b/usr.sbin/ctld/ctld.hh
@@ -533,22 +533,43 @@ private:
 #define        CONN_SESSION_TYPE_NORMAL        2
 
 struct ctld_connection {
+       ctld_connection(struct portal *portal, int fd, const char *host,
+           const struct sockaddr *client_sa);
+       ~ctld_connection();
+
+       int session_type() const { return conn_session_type; }
+
+       void login();
+       void discovery();
+       void kernel_handoff();
+private:
+       void login_chap(struct auth_group *ag);
+       void login_negotiate_key(struct pdu *request, const char *name,
+           const char *value, bool skipped_security,
+           struct keys *response_keys);
+       bool login_portal_redirect(struct pdu *request);
+       bool login_target_redirect(struct pdu *request);
+       void login_negotiate(struct pdu *request);
+       void login_wait_transition();
+
+       bool discovery_target_filtered_out(const struct port *port) const;
+
        struct connection       conn;
-       struct portal           *conn_portal;
-       const struct port       *conn_port;
-       struct target           *conn_target;
-       int                     conn_session_type;
-       char                    *conn_initiator_name;
-       char                    *conn_initiator_addr;
-       char                    *conn_initiator_alias;
+       struct portal           *conn_portal = nullptr;
+       const struct port       *conn_port = nullptr;
+       struct target           *conn_target = nullptr;
+       int                     conn_session_type = CONN_SESSION_TYPE_NONE;
+       std::string             conn_initiator_name;
+       std::string             conn_initiator_addr;
+       std::string             conn_initiator_alias;
        uint8_t                 conn_initiator_isid[6];
-       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;
-       int                     conn_first_burst_limit;
-       const char              *conn_user;
-       struct chap             *conn_chap;
+       const struct sockaddr   *conn_initiator_sa = nullptr;
+       int                     conn_max_recv_data_segment_limit = 0;
+       int                     conn_max_send_data_segment_limit = 0;
+       int                     conn_max_burst_limit = 0;
+       int                     conn_first_burst_limit = 0;
+       std::string             conn_user;
+       struct chap             *conn_chap = nullptr;
 };
 
 extern int ctl_fd;
@@ -564,7 +585,6 @@ bool                        option_new(nvlist_t *nvl,
                            const char *name, const char *value);
 
 void                   kernel_init(void);
-void                   kernel_handoff(struct ctld_connection *conn);
 void                   kernel_capsicate(void);
 
 #ifdef ICL_KERNEL_PROXY
@@ -577,10 +597,6 @@ void                       kernel_send(struct pdu *pdu);
 void                   kernel_receive(struct pdu *pdu);
 #endif
 
-void                   login(struct ctld_connection *conn);
-
-void                   discovery(struct ctld_connection *conn);
-
 void                   start_timer(int timeout, bool fatal = false);
 void                   stop_timer();
 
diff --git a/usr.sbin/ctld/discovery.cc b/usr.sbin/ctld/discovery.cc
index a98b5746735a..3c9f1cfa1dac 100644
--- a/usr.sbin/ctld/discovery.cc
+++ b/usr.sbin/ctld/discovery.cc
@@ -144,9 +144,8 @@ discovery_add_target(struct keys *response_keys, const 
struct target *targ)
        }
 }
 
-static bool
-discovery_target_filtered_out(const struct ctld_connection *conn,
-    const struct port *port)
+bool
+ctld_connection::discovery_target_filtered_out(const struct port *port) const
 {
        const struct auth_group *ag;
        const struct portal_group *pg;
@@ -158,19 +157,19 @@ discovery_target_filtered_out(const struct 
ctld_connection *conn,
        ag = port->auth_group();
        if (ag == nullptr)
                ag = targ->auth_group();
-       pg = conn->conn_portal->portal_group();
+       pg = conn_portal->portal_group();
 
        assert(pg->discovery_filter() != discovery_filter::UNKNOWN);
 
        if (pg->discovery_filter() >= discovery_filter::PORTAL &&
-           !ag->initiator_permitted(conn->conn_initiator_sa)) {
+           !ag->initiator_permitted(conn_initiator_sa)) {
                log_debugx("initiator does not match initiator portals "
                    "allowed for target \"%s\"; skipping", targ->name());
                return (true);
        }
 
        if (pg->discovery_filter() >= discovery_filter::PORTAL_NAME &&
-           !ag->initiator_permitted(conn->conn_initiator_name)) {
+           !ag->initiator_permitted(conn_initiator_name)) {
                log_debugx("initiator does not match initiator names "
                    "allowed for target \"%s\"; skipping", targ->name());
                return (true);
@@ -178,7 +177,7 @@ discovery_target_filtered_out(const struct ctld_connection 
*conn,
 
        if (pg->discovery_filter() >= discovery_filter::PORTAL_NAME_AUTH &&
            ag->type() != auth_type::NO_AUTHENTICATION) {
-               if (conn->conn_chap == NULL) {
+               if (conn_chap == nullptr) {
                        assert(pg->discovery_auth_group()->type() ==
                            auth_type::NO_AUTHENTICATION);
 
@@ -187,19 +186,20 @@ discovery_target_filtered_out(const struct 
ctld_connection *conn,
                        return (true);
                }
 
-               assert(conn->conn_user != NULL);
-               auth = ag->find_auth(conn->conn_user);
+               assert(!conn_user.empty());
+               auth = ag->find_auth(conn_user);
                if (auth == NULL) {
                        log_debugx("CHAP user \"%s\" doesn't match target "
-                           "\"%s\"; skipping", conn->conn_user, targ->name());
+                           "\"%s\"; skipping", conn_user.c_str(),
+                           targ->name());
                        return (true);
                }
 
-               error = chap_authenticate(conn->conn_chap, auth->secret());
+               error = chap_authenticate(conn_chap, auth->secret());
                if (error != 0) {
                        log_debugx("password for CHAP user \"%s\" doesn't "
                            "match target \"%s\"; skipping",
-                           conn->conn_user, targ->name());
+                           conn_user.c_str(), targ->name());
                        return (true);
                }
        }
@@ -208,7 +208,7 @@ discovery_target_filtered_out(const struct ctld_connection 
*conn,
 }
 
 void
-discovery(struct ctld_connection *conn)
+ctld_connection::discovery()
 {
        struct pdu *request, *response;
        struct keys *request_keys, *response_keys;
@@ -216,10 +216,10 @@ discovery(struct ctld_connection *conn)
        const struct portal_group *pg;
        const char *send_targets;
 
-       pg = conn->conn_portal->portal_group();
+       pg = conn_portal->portal_group();
 
        log_debugx("beginning discovery session; waiting for TextRequest PDU");
-       request_keys = text_read_request(&conn->conn, &request);
+       request_keys = text_read_request(&conn, &request);
 
        send_targets = keys_find(request_keys, "SendTargets");
        if (send_targets == NULL)
@@ -230,7 +230,7 @@ discovery(struct ctld_connection *conn)
        if (strcmp(send_targets, "All") == 0) {
                for (const auto &kv : pg->ports()) {
                        port = kv.second;
-                       if (discovery_target_filtered_out(conn, port)) {
+                       if (discovery_target_filtered_out(port)) {
                                /* Ignore this target. */
                                continue;
                        }
@@ -242,7 +242,7 @@ discovery(struct ctld_connection *conn)
                        log_debugx("initiator requested information on unknown "
                            "target \"%s\"; returning nothing", send_targets);
                } else {
-                       if (discovery_target_filtered_out(conn, port)) {
+                       if (discovery_target_filtered_out(port)) {
                                /* Ignore this target. */
                        } else {
                                discovery_add_target(response_keys,
@@ -257,7 +257,7 @@ discovery(struct ctld_connection *conn)
        keys_delete(request_keys);
 
        log_debugx("done sending targets; waiting for Logout PDU");
-       request = logout_receive(&conn->conn);
+       request = logout_receive(&conn);
        response = logout_new_response(request);
 
        pdu_send(response);
diff --git a/usr.sbin/ctld/kernel.cc b/usr.sbin/ctld/kernel.cc
index 10b5f16768fd..39bbb4290e84 100644
--- a/usr.sbin/ctld/kernel.cc
+++ b/usr.sbin/ctld/kernel.cc
@@ -706,51 +706,51 @@ lun::kernel_remove() const
 }
 
 void
-kernel_handoff(struct ctld_connection *conn)
+ctld_connection::kernel_handoff()
 {
-       struct portal_group *pg = conn->conn_portal->portal_group();
+       struct portal_group *pg = conn_portal->portal_group();
        struct ctl_iscsi req;
 
        bzero(&req, sizeof(req));
 
        req.type = CTL_ISCSI_HANDOFF;
-       strlcpy(req.data.handoff.initiator_name,
-           conn->conn_initiator_name, sizeof(req.data.handoff.initiator_name));
-       strlcpy(req.data.handoff.initiator_addr,
-           conn->conn_initiator_addr, sizeof(req.data.handoff.initiator_addr));
-       if (conn->conn_initiator_alias != NULL) {
+       strlcpy(req.data.handoff.initiator_name, conn_initiator_name.c_str(),
+           sizeof(req.data.handoff.initiator_name));
+       strlcpy(req.data.handoff.initiator_addr, conn_initiator_addr.c_str(),
+           sizeof(req.data.handoff.initiator_addr));
+       if (!conn_initiator_alias.empty()) {
                strlcpy(req.data.handoff.initiator_alias,
-                   conn->conn_initiator_alias, 
sizeof(req.data.handoff.initiator_alias));
+                   conn_initiator_alias.c_str(),
+                   sizeof(req.data.handoff.initiator_alias));
        }
-       memcpy(req.data.handoff.initiator_isid, conn->conn_initiator_isid,
+       memcpy(req.data.handoff.initiator_isid, conn_initiator_isid,
            sizeof(req.data.handoff.initiator_isid));
-       strlcpy(req.data.handoff.target_name,
-           conn->conn_target->name(), sizeof(req.data.handoff.target_name));
+       strlcpy(req.data.handoff.target_name, 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
        if (proxy_mode)
-               req.data.handoff.connection_id = conn->conn.conn_socket;
+               req.data.handoff.connection_id = conn.conn_socket;
        else
-               req.data.handoff.socket = conn->conn.conn_socket;
+               req.data.handoff.socket = conn.conn_socket;
 #else
-       req.data.handoff.socket = conn->conn.conn_socket;
+       req.data.handoff.socket = conn.conn_socket;
 #endif
        req.data.handoff.portal_group_tag = pg->tag();
-       if (conn->conn.conn_header_digest == CONN_DIGEST_CRC32C)
+       if (conn.conn_header_digest == CONN_DIGEST_CRC32C)
                req.data.handoff.header_digest = CTL_ISCSI_DIGEST_CRC32C;
-       if (conn->conn.conn_data_digest == CONN_DIGEST_CRC32C)
+       if (conn.conn_data_digest == CONN_DIGEST_CRC32C)
                req.data.handoff.data_digest = CTL_ISCSI_DIGEST_CRC32C;
-       req.data.handoff.cmdsn = conn->conn.conn_cmdsn;
-       req.data.handoff.statsn = conn->conn.conn_statsn;
+       req.data.handoff.cmdsn = conn.conn_cmdsn;
+       req.data.handoff.statsn = conn.conn_statsn;
        req.data.handoff.max_recv_data_segment_length =
-           conn->conn.conn_max_recv_data_segment_length;
+           conn.conn_max_recv_data_segment_length;
        req.data.handoff.max_send_data_segment_length =
-           conn->conn.conn_max_send_data_segment_length;
-       req.data.handoff.max_burst_length = conn->conn.conn_max_burst_length;
-       req.data.handoff.first_burst_length =
-           conn->conn.conn_first_burst_length;
-       req.data.handoff.immediate_data = conn->conn.conn_immediate_data;
+           conn.conn_max_send_data_segment_length;
+       req.data.handoff.max_burst_length = conn.conn_max_burst_length;
+       req.data.handoff.first_burst_length = conn.conn_first_burst_length;
+       req.data.handoff.immediate_data = conn.conn_immediate_data;
 
        if (ioctl(ctl_fd, CTL_ISCSI, &req) == -1) {
                log_err(1, "error issuing CTL_ISCSI ioctl; "
diff --git a/usr.sbin/ctld/login.cc b/usr.sbin/ctld/login.cc
index 61f32dcb0f51..aa62cd4c8b5b 100644
--- a/usr.sbin/ctld/login.cc
+++ b/usr.sbin/ctld/login.cc
@@ -454,8 +454,8 @@ login_send_chap_success(struct pdu *request,
        pdu_delete(response);
 }
 
-static void
-login_chap(struct ctld_connection *conn, struct auth_group *ag)
+void
+ctld_connection::login_chap(struct auth_group *ag)
 {
        std::string user;
        const struct auth *auth;
@@ -466,7 +466,7 @@ login_chap(struct ctld_connection *conn, struct auth_group 
*ag)
         * Receive CHAP_A PDU.
         */
        log_debugx("beginning CHAP authentication; waiting for CHAP_A");
-       request = login_receive_chap_a(&conn->conn);
+       request = login_receive_chap_a(&conn);
 
        /*
         * Generate the challenge.
@@ -485,7 +485,7 @@ login_chap(struct ctld_connection *conn, struct auth_group 
*ag)
         * Receive CHAP_N/CHAP_R PDU and authenticate.
         */
        log_debugx("waiting for CHAP_N/CHAP_R");
-       request = login_receive_chap_r(&conn->conn, ag, chap, &auth, user);
+       request = login_receive_chap_r(&conn, ag, chap, &auth, user);
 
        /*
         * Yay, authentication succeeded!
@@ -498,19 +498,18 @@ login_chap(struct ctld_connection *conn, struct 
auth_group *ag)
        /*
         * Leave username and CHAP information for discovery().
         */
-       conn->conn_user = checked_strdup(user.c_str());
-       conn->conn_chap = chap;
+       conn_user = user;
+       conn_chap = chap;
 }
 
-static void
-login_negotiate_key(struct pdu *request, const char *name,
+void
+ctld_connection::login_negotiate_key(struct pdu *request, const char *name,
     const char *value, bool skipped_security, struct keys *response_keys)
 {
        int which;
        size_t tmp;
-       struct ctld_connection *conn;
 
-       conn = (struct ctld_connection *)request->pdu_connection;
+       assert(request->pdu_connection == &conn);
 
        if (strcmp(name, "InitiatorName") == 0) {
                if (!skipped_security)
@@ -522,16 +521,14 @@ login_negotiate_key(struct pdu *request, const char *name,
                if (!skipped_security)
                        log_errx(1, "initiator resent TargetName");
        } else if (strcmp(name, "InitiatorAlias") == 0) {
-               if (conn->conn_initiator_alias != NULL)
-                       free(conn->conn_initiator_alias);
-               conn->conn_initiator_alias = checked_strdup(value);
+               conn_initiator_alias = value;
        } else if (strcmp(value, "Irrelevant") == 0) {
                /* Ignore. */
        } else if (strcmp(name, "HeaderDigest") == 0) {
                /*
                 * We don't handle digests for discovery sessions.
                 */
-               if (conn->conn_session_type == CONN_SESSION_TYPE_DISCOVERY) {
+               if (conn_session_type == CONN_SESSION_TYPE_DISCOVERY) {
                        log_debugx("discovery session; digests disabled");
                        keys_add(response_keys, name, "None");
                        return;
@@ -542,7 +539,7 @@ login_negotiate_key(struct pdu *request, const char *name,
                case 1:
                        log_debugx("initiator prefers CRC32C "
                            "for header digest; we'll use it");
-                       conn->conn.conn_header_digest = CONN_DIGEST_CRC32C;
+                       conn.conn_header_digest = CONN_DIGEST_CRC32C;
                        keys_add(response_keys, name, "CRC32C");
                        break;
                case 2:
@@ -557,7 +554,7 @@ login_negotiate_key(struct pdu *request, const char *name,
                        break;
                }
        } else if (strcmp(name, "DataDigest") == 0) {
-               if (conn->conn_session_type == CONN_SESSION_TYPE_DISCOVERY) {
+               if (conn_session_type == CONN_SESSION_TYPE_DISCOVERY) {
                        log_debugx("discovery session; digests disabled");
                        keys_add(response_keys, name, "None");
                        return;
@@ -568,7 +565,7 @@ login_negotiate_key(struct pdu *request, const char *name,
                case 1:
                        log_debugx("initiator prefers CRC32C "
                            "for data digest; we'll use it");
-                       conn->conn.conn_data_digest = CONN_DIGEST_CRC32C;
+                       conn.conn_data_digest = CONN_DIGEST_CRC32C;
                        keys_add(response_keys, name, "CRC32C");
                        break;
                case 2:
@@ -587,15 +584,15 @@ login_negotiate_key(struct pdu *request, const char *name,
        } else if (strcmp(name, "InitialR2T") == 0) {
                keys_add(response_keys, name, "Yes");
        } else if (strcmp(name, "ImmediateData") == 0) {
-               if (conn->conn_session_type == CONN_SESSION_TYPE_DISCOVERY) {
+               if (conn_session_type == CONN_SESSION_TYPE_DISCOVERY) {
                        log_debugx("discovery session; ImmediateData 
irrelevant");
                        keys_add(response_keys, name, "Irrelevant");
                } else {
                        if (strcmp(value, "Yes") == 0) {
-                               conn->conn.conn_immediate_data = true;
+                               conn.conn_immediate_data = true;
                                keys_add(response_keys, name, "Yes");
                        } else {
-                               conn->conn.conn_immediate_data = false;
+                               conn.conn_immediate_data = false;
                                keys_add(response_keys, name, "No");
                        }
                }
@@ -613,25 +610,25 @@ login_negotiate_key(struct pdu *request, const char *name,
                 * our MaxRecvDataSegmentLength is not influenced by the
                 * initiator in any way.
                 */
-               if ((int)tmp > conn->conn_max_send_data_segment_limit) {
+               if ((int)tmp > conn_max_send_data_segment_limit) {
                        log_debugx("capping MaxRecvDataSegmentLength "
                            "from %zd to %d", tmp,
-                           conn->conn_max_send_data_segment_limit);
-                       tmp = conn->conn_max_send_data_segment_limit;
+                           conn_max_send_data_segment_limit);
+                       tmp = conn_max_send_data_segment_limit;
                }
-               conn->conn.conn_max_send_data_segment_length = tmp;
+               conn.conn_max_send_data_segment_length = tmp;
        } else if (strcmp(name, "MaxBurstLength") == 0) {
                tmp = strtoul(value, NULL, 10);
                if (tmp <= 0) {
                        login_send_error(request, 0x02, 0x00);
                        log_errx(1, "received invalid MaxBurstLength");
                }
-               if ((int)tmp > conn->conn_max_burst_limit) {
+               if ((int)tmp > conn_max_burst_limit) {
                        log_debugx("capping MaxBurstLength from %zd to %d",
-                           tmp, conn->conn_max_burst_limit);
-                       tmp = conn->conn_max_burst_limit;
+                           tmp, conn_max_burst_limit);
+                       tmp = conn_max_burst_limit;
                }
-               conn->conn.conn_max_burst_length = tmp;
+               conn.conn_max_burst_length = tmp;
                keys_add_int(response_keys, name, tmp);
        } else if (strcmp(name, "FirstBurstLength") == 0) {
                tmp = strtoul(value, NULL, 10);
@@ -639,12 +636,12 @@ login_negotiate_key(struct pdu *request, const char *name,
                        login_send_error(request, 0x02, 0x00);
                        log_errx(1, "received invalid FirstBurstLength");
                }
-               if ((int)tmp > conn->conn_first_burst_limit) {
+               if ((int)tmp > conn_first_burst_limit) {
                        log_debugx("capping FirstBurstLength from %zd to %d",
-                           tmp, conn->conn_first_burst_limit);
-                       tmp = conn->conn_first_burst_limit;
+                           tmp, conn_first_burst_limit);
+                       tmp = conn_first_burst_limit;
                }
-               conn->conn.conn_first_burst_length = tmp;
+               conn.conn_first_burst_length = tmp;
                keys_add_int(response_keys, name, tmp);
        } else if (strcmp(name, "DefaultTime2Wait") == 0) {
                keys_add(response_keys, name, value);
@@ -696,12 +693,12 @@ login_redirect(struct pdu *request, const char 
*target_address)
        keys_delete(response_keys);
 }
 
-static bool
-login_portal_redirect(struct ctld_connection *conn, struct pdu *request)
+bool
+ctld_connection::login_portal_redirect(struct pdu *request)
 {
        const struct portal_group *pg;
 
-       pg = conn->conn_portal->portal_group();
+       pg = conn_portal->portal_group();
        if (!pg->is_redirecting())
                return (false);
 
@@ -712,87 +709,84 @@ login_portal_redirect(struct ctld_connection *conn, 
struct pdu *request)
        return (true);
 }
 
-static bool
-login_target_redirect(struct ctld_connection *conn, struct pdu *request)
+bool
+ctld_connection::login_target_redirect(struct pdu *request)
 {
        const char *target_address;
 
-       assert(!conn->conn_portal->portal_group()->is_redirecting());
+       assert(!conn_portal->portal_group()->is_redirecting());
 
-       if (conn->conn_target == NULL)
+       if (conn_target == NULL)
                return (false);
 
-       if (!conn->conn_target->has_redirection())
+       if (!conn_target->has_redirection())
                return (false);
 
-       target_address = conn->conn_target->redirection();
+       target_address = conn_target->redirection();
        log_debugx("target \"%s\" configured to redirect to %s",
-         conn->conn_target->name(), target_address);
+         conn_target->name(), target_address);
        login_redirect(request, target_address);
 
        return (true);
 }
 
-static void
-login_negotiate(struct ctld_connection *conn, struct pdu *request)
+void
+ctld_connection::login_negotiate(struct pdu *request)
 {
-       struct portal_group *pg = conn->conn_portal->portal_group();
+       struct portal_group *pg = conn_portal->portal_group();
        struct pdu *response;
        struct iscsi_bhs_login_response *bhslr2;
        struct keys *request_keys, *response_keys;
        int i;
        bool redirected, skipped_security;
 
-       if (conn->conn_session_type == CONN_SESSION_TYPE_NORMAL) {
+       if (conn_session_type == CONN_SESSION_TYPE_NORMAL) {
                /*
                 * Query the kernel for various size limits.  In case of
                 * offload, it depends on hardware capabilities.
                 */
-               assert(conn->conn_target != NULL);
-               conn->conn_max_recv_data_segment_limit = (1 << 24) - 1;
-               conn->conn_max_send_data_segment_limit = (1 << 24) - 1;
-               conn->conn_max_burst_limit = (1 << 24) - 1;
-               conn->conn_first_burst_limit = (1 << 24) - 1;
+               assert(conn_target != NULL);
+               conn_max_recv_data_segment_limit = (1 << 24) - 1;
+               conn_max_send_data_segment_limit = (1 << 24) - 1;
+               conn_max_burst_limit = (1 << 24) - 1;
+               conn_first_burst_limit = (1 << 24) - 1;
                kernel_limits(pg->offload(),
-                   conn->conn.conn_socket,
-                   &conn->conn_max_recv_data_segment_limit,
-                   &conn->conn_max_send_data_segment_limit,
-                   &conn->conn_max_burst_limit,
-                   &conn->conn_first_burst_limit);
+                   conn.conn_socket,
+                   &conn_max_recv_data_segment_limit,
+                   &conn_max_send_data_segment_limit,
+                   &conn_max_burst_limit,
+                   &conn_first_burst_limit);
 
                /* We expect legal, usable values at this point. */
-               assert(conn->conn_max_recv_data_segment_limit >= 512);
-               assert(conn->conn_max_recv_data_segment_limit < (1 << 24));
-               assert(conn->conn_max_send_data_segment_limit >= 512);
-               assert(conn->conn_max_send_data_segment_limit < (1 << 24));
-               assert(conn->conn_max_burst_limit >= 512);
-               assert(conn->conn_max_burst_limit < (1 << 24));
-               assert(conn->conn_first_burst_limit >= 512);
-               assert(conn->conn_first_burst_limit < (1 << 24));
-               assert(conn->conn_first_burst_limit <=
-                   conn->conn_max_burst_limit);
+               assert(conn_max_recv_data_segment_limit >= 512);
+               assert(conn_max_recv_data_segment_limit < (1 << 24));
+               assert(conn_max_send_data_segment_limit >= 512);
+               assert(conn_max_send_data_segment_limit < (1 << 24));
+               assert(conn_max_burst_limit >= 512);
+               assert(conn_max_burst_limit < (1 << 24));
+               assert(conn_first_burst_limit >= 512);
+               assert(conn_first_burst_limit < (1 << 24));
+               assert(conn_first_burst_limit <= conn_max_burst_limit);
 
                /*
                 * Limit default send length in case it won't be negotiated.
                 * We can't do it for other limits, since they may affect both
                 * sender and receiver operation, and we must obey defaults.
                 */
-               if (conn->conn_max_send_data_segment_limit <
-                   conn->conn.conn_max_send_data_segment_length) {
-                       conn->conn.conn_max_send_data_segment_length =
-                           conn->conn_max_send_data_segment_limit;
+               if (conn_max_send_data_segment_limit <
+                   conn.conn_max_send_data_segment_length) {
+                       conn.conn_max_send_data_segment_length =
+                           conn_max_send_data_segment_limit;
                }
        } else {
-               conn->conn_max_recv_data_segment_limit =
-                   MAX_DATA_SEGMENT_LENGTH;
-               conn->conn_max_send_data_segment_limit =
-                   MAX_DATA_SEGMENT_LENGTH;
+               conn_max_recv_data_segment_limit = MAX_DATA_SEGMENT_LENGTH;
+               conn_max_send_data_segment_limit = MAX_DATA_SEGMENT_LENGTH;
        }
 
        if (request == NULL) {
                log_debugx("beginning operational parameter negotiation; "
                    "waiting for Login PDU");
-               request = login_receive(&conn->conn, false);
+               request = login_receive(&conn, false);
                skipped_security = false;
        } else
                skipped_security = true;
@@ -803,7 +797,7 @@ login_negotiate(struct ctld_connection *conn, struct pdu 
*request)
         * authentication, but MUST be accepted afterwards; that's
         * why we're doing it here and not earlier.
         */
-       redirected = login_target_redirect(conn, request);
+       redirected = login_target_redirect(request);
        if (redirected) {
                log_debugx("initiator redirected; exiting");
                exit(0);
@@ -820,10 +814,10 @@ login_negotiate(struct ctld_connection *conn, struct pdu 
*request)
        response_keys = keys_new();
 
        if (skipped_security &&
-           conn->conn_session_type == CONN_SESSION_TYPE_NORMAL) {
-               if (conn->conn_target->has_alias())
+           conn_session_type == CONN_SESSION_TYPE_NORMAL) {
+               if (conn_target->has_alias())
                        keys_add(response_keys,
-                           "TargetAlias", conn->conn_target->alias());
+                           "TargetAlias", conn_target->alias());
                keys_add_int(response_keys, "TargetPortalGroupTag",
                    pg->tag());
        }
@@ -844,16 +838,15 @@ login_negotiate(struct ctld_connection *conn, struct pdu 
*request)
         * pairs in the order they are in the request we might have ended up
         * with illegal values here.
         */
-       if (conn->conn_session_type == CONN_SESSION_TYPE_NORMAL &&
-           conn->conn.conn_first_burst_length >
-           conn->conn.conn_max_burst_length) {
+       if (conn_session_type == CONN_SESSION_TYPE_NORMAL &&
+           conn.conn_first_burst_length > conn.conn_max_burst_length) {
                log_errx(1, "initiator sent FirstBurstLength > MaxBurstLength");
        }
 
-       conn->conn.conn_max_recv_data_segment_length =
-           conn->conn_max_recv_data_segment_limit;
+       conn.conn_max_recv_data_segment_length =
+           conn_max_recv_data_segment_limit;
        keys_add_int(response_keys, "MaxRecvDataSegmentLength",
-                   conn->conn.conn_max_recv_data_segment_length);
+                   conn.conn_max_recv_data_segment_length);
 
        log_debugx("operational parameter negotiation done; "
            "transitioning to Full Feature Phase");
@@ -866,14 +859,14 @@ login_negotiate(struct ctld_connection *conn, struct pdu 
*request)
        keys_delete(request_keys);
 }
 
-static void
-login_wait_transition(struct ctld_connection *conn)
+void
+ctld_connection::login_wait_transition()
 {
        struct pdu *request, *response;
        struct iscsi_bhs_login_request *bhslr;
 
        log_debugx("waiting for state transition request");
-       request = login_receive(&conn->conn, false);
+       request = login_receive(&conn, false);
        bhslr = (struct iscsi_bhs_login_request *)request->pdu_bhs;
        if ((bhslr->bhslr_flags & BHSLR_FLAGS_TRANSIT) == 0) {
                login_send_error(request, 0x02, 0x00);
@@ -887,11 +880,11 @@ login_wait_transition(struct ctld_connection *conn)
        pdu_send(response);
        pdu_delete(response);
 
-       login_negotiate(conn, NULL);
+       login_negotiate(nullptr);
 }
 
 void
-login(struct ctld_connection *conn)
+ctld_connection::login()
 {
        struct pdu *request, *response;
        struct iscsi_bhs_login_request *bhslr;
@@ -908,17 +901,17 @@ login(struct ctld_connection *conn)
         * is required, or call appropriate authentication code.
         */
        log_debugx("beginning Login Phase; waiting for Login PDU");
-       request = login_receive(&conn->conn, true);
+       request = login_receive(&conn, true);
        bhslr = (struct iscsi_bhs_login_request *)request->pdu_bhs;
        if (bhslr->bhslr_tsih != 0) {
                login_send_error(request, 0x02, 0x0a);
                log_errx(1, "received Login PDU with non-zero TSIH");
        }
 
-       pg = conn->conn_portal->portal_group();
+       pg = conn_portal->portal_group();
 
-       memcpy(conn->conn_initiator_isid, bhslr->bhslr_isid,
-           sizeof(conn->conn_initiator_isid));
+       memcpy(conn_initiator_isid, bhslr->bhslr_isid,
+           sizeof(conn_initiator_isid));
 
        /*
         * XXX: Implement the C flag some day.
@@ -926,7 +919,7 @@ login(struct ctld_connection *conn)
        request_keys = keys_new();
        keys_load_pdu(request_keys, request);
 
-       assert(conn->conn_initiator_name == NULL);
+       assert(conn_initiator_name.empty());
        initiator_name = keys_find(request_keys, "InitiatorName");
        if (initiator_name == NULL) {
                login_send_error(request, 0x02, 0x07);
@@ -936,11 +929,12 @@ login(struct ctld_connection *conn)
                login_send_error(request, 0x02, 0x00);
                log_errx(1, "received Login PDU with invalid InitiatorName");
        }
-       conn->conn_initiator_name = checked_strdup(initiator_name);
-       log_set_peer_name(conn->conn_initiator_name);
-       setproctitle("%s (%s)", conn->conn_initiator_addr, 
conn->conn_initiator_name);
+       conn_initiator_name = initiator_name;
+       log_set_peer_name(conn_initiator_name.c_str());
+       setproctitle("%s (%s)", conn_initiator_addr.c_str(),
+           conn_initiator_name.c_str());
 
-       redirected = login_portal_redirect(conn, request);
+       redirected = login_portal_redirect(request);
        if (redirected) {
                log_debugx("initiator redirected; exiting");
                exit(0);
@@ -948,58 +942,58 @@ login(struct ctld_connection *conn)
 
        initiator_alias = keys_find(request_keys, "InitiatorAlias");
        if (initiator_alias != NULL)
-               conn->conn_initiator_alias = checked_strdup(initiator_alias);
+               conn_initiator_alias = initiator_alias;
 
-       assert(conn->conn_session_type == CONN_SESSION_TYPE_NONE);
+       assert(conn_session_type == CONN_SESSION_TYPE_NONE);
        session_type = keys_find(request_keys, "SessionType");
        if (session_type != NULL) {
                if (strcmp(session_type, "Normal") == 0) {
-                       conn->conn_session_type = CONN_SESSION_TYPE_NORMAL;
+                       conn_session_type = CONN_SESSION_TYPE_NORMAL;
                } else if (strcmp(session_type, "Discovery") == 0) {
-                       conn->conn_session_type = CONN_SESSION_TYPE_DISCOVERY;
+                       conn_session_type = CONN_SESSION_TYPE_DISCOVERY;
                } else {
                        login_send_error(request, 0x02, 0x00);
                        log_errx(1, "received Login PDU with invalid "
                            "SessionType \"%s\"", session_type);
                }
        } else
-               conn->conn_session_type = CONN_SESSION_TYPE_NORMAL;
+               conn_session_type = CONN_SESSION_TYPE_NORMAL;
 
-       assert(conn->conn_target == NULL);
-       if (conn->conn_session_type == CONN_SESSION_TYPE_NORMAL) {
+       assert(conn_target == NULL);
+       if (conn_session_type == CONN_SESSION_TYPE_NORMAL) {
                target_name = keys_find(request_keys, "TargetName");
                if (target_name == NULL) {
                        login_send_error(request, 0x02, 0x07);
                        log_errx(1, "received Login PDU without TargetName");
                }
 
-               conn->conn_port = pg->find_port(target_name);
-               if (conn->conn_port == NULL) {
+               conn_port = pg->find_port(target_name);
+               if (conn_port == NULL) {
                        login_send_error(request, 0x02, 0x03);
                        log_errx(1, "requested target \"%s\" not found",
                            target_name);
                }
-               conn->conn_target = conn->conn_port->target();
+               conn_target = conn_port->target();
        }
 
        /*
         * At this point we know what kind of authentication we need.
         */
-       if (conn->conn_session_type == CONN_SESSION_TYPE_NORMAL) {
-               ag = conn->conn_port->auth_group();
+       if (conn_session_type == CONN_SESSION_TYPE_NORMAL) {
+               ag = conn_port->auth_group();
                if (ag == nullptr)
-                       ag = conn->conn_target->auth_group();
-               if (conn->conn_port->auth_group() == nullptr &&
-                   conn->conn_target->private_auth()) {
+                       ag = conn_target->auth_group();
+               if (conn_port->auth_group() == nullptr &&
+                   conn_target->private_auth()) {
                        log_debugx("initiator requests to connect "
-                           "to target \"%s\"", conn->conn_target->name());
+                           "to target \"%s\"", conn_target->name());
                } else {
                        log_debugx("initiator requests to connect "
                            "to target \"%s\"; %s",
-                           conn->conn_target->name(), ag->label());
+                           conn_target->name(), ag->label());
                }
        } else {
-               assert(conn->conn_session_type == CONN_SESSION_TYPE_DISCOVERY);
+               assert(conn_session_type == CONN_SESSION_TYPE_DISCOVERY);
                ag = pg->discovery_auth_group();
                log_debugx("initiator requests discovery session; %s",
                    ag->label());
@@ -1026,7 +1020,7 @@ login(struct ctld_connection *conn)
                log_errx(1, "initiator does not match allowed initiator names");
        }
 
-       if (!ag->initiator_permitted(conn->conn_initiator_sa)) {
+       if (!ag->initiator_permitted(conn_initiator_sa)) {
                login_send_error(request, 0x02, 0x02);
                log_errx(1, "initiator does not match allowed "
                    "initiator portals");
@@ -1047,7 +1041,7 @@ login(struct ctld_connection *conn)
 
                log_debugx("initiator skipped the authentication, "
                    "and we don't need it; proceeding with negotiation");
-               login_negotiate(conn, request);
+               login_negotiate(request);
                return;
        }
 
@@ -1082,10 +1076,10 @@ login(struct ctld_connection *conn)
                        fail = true;
                }
        }
-       if (conn->conn_session_type == CONN_SESSION_TYPE_NORMAL) {
-               if (conn->conn_target->has_alias())
+       if (conn_session_type == CONN_SESSION_TYPE_NORMAL) {
+               if (conn_target->has_alias())
                        keys_add(response_keys,
-                           "TargetAlias", conn->conn_target->alias());
+                           "TargetAlias", conn_target->alias());
                keys_add_int(response_keys,
                    "TargetPortalGroupTag", pg->tag());
        }
@@ -1103,11 +1097,11 @@ login(struct ctld_connection *conn)
        }
 
        if (ag->type() != auth_type::NO_AUTHENTICATION) {
-               login_chap(conn, ag);
-               login_negotiate(conn, NULL);
+               login_chap(ag);
+               login_negotiate(nullptr);
        } else if (trans) {
-               login_negotiate(conn, NULL);
+               login_negotiate(nullptr);
        } else {
-               login_wait_transition(conn);
+               login_wait_transition();
        }
 }

Reply via email to