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(); } }