summaryrefslogtreecommitdiffstats
path: root/usr.sbin/ctld/login.c
diff options
context:
space:
mode:
authortrasz <trasz@FreeBSD.org>2014-11-09 13:01:09 +0000
committertrasz <trasz@FreeBSD.org>2014-11-09 13:01:09 +0000
commit4eec651ec388a7406d989f93aef0d62f748080fc (patch)
tree7fce56b0e4a689fc51e535b741025162dc8c5f61 /usr.sbin/ctld/login.c
parent037bd5af5746c3f20b892933dccfc78a245f81a4 (diff)
downloadFreeBSD-src-4eec651ec388a7406d989f93aef0d62f748080fc.zip
FreeBSD-src-4eec651ec388a7406d989f93aef0d62f748080fc.tar.gz
Add support for sending redirections to iSCSI target.
MFC after: 1 month Sponsored by: The FreeBSD Foundation
Diffstat (limited to 'usr.sbin/ctld/login.c')
-rw-r--r--usr.sbin/ctld/login.c91
1 files changed, 91 insertions, 0 deletions
diff --git a/usr.sbin/ctld/login.c b/usr.sbin/ctld/login.c
index c59cea0..edba16b 100644
--- a/usr.sbin/ctld/login.c
+++ b/usr.sbin/ctld/login.c
@@ -613,6 +613,66 @@ login_negotiate_key(struct pdu *request, const char *name,
}
static void
+login_redirect(struct pdu *request, const char *target_address)
+{
+ struct pdu *response;
+ struct iscsi_bhs_login_response *bhslr2;
+ struct keys *response_keys;
+
+ response = login_new_response(request);
+ bhslr2 = (struct iscsi_bhs_login_response *)response->pdu_bhs;
+ bhslr2->bhslr_status_class = 0x01;
+ bhslr2->bhslr_status_detail = 0x01;
+ login_set_csg(response, BHSLR_STAGE_OPERATIONAL_NEGOTIATION);
+ login_set_nsg(response, BHSLR_STAGE_OPERATIONAL_NEGOTIATION);
+
+ response_keys = keys_new();
+ keys_add(response_keys, "TargetAddress", target_address);
+
+ keys_save(response_keys, response);
+ pdu_send(response);
+ pdu_delete(response);
+ keys_delete(response_keys);
+}
+
+static bool
+login_portal_redirect(struct connection *conn, struct pdu *request)
+{
+ const struct portal_group *pg;
+
+ pg = conn->conn_portal->p_portal_group;
+ if (pg->pg_redirection == NULL)
+ return (false);
+
+ log_debugx("portal-group \"%s\" configured to redirect to %s",
+ pg->pg_name, pg->pg_redirection);
+ login_redirect(request, pg->pg_redirection);
+
+ return (true);
+}
+
+static bool
+login_target_redirect(struct connection *conn, struct pdu *request)
+{
+ const char *target_address;
+
+ assert(conn->conn_portal->p_portal_group->pg_redirection == NULL);
+
+ if (conn->conn_target == NULL)
+ return (false);
+
+ target_address = conn->conn_target->t_redirection;
+ if (target_address == NULL)
+ return (false);
+
+ log_debugx("target \"%s\" configured to redirect to %s",
+ conn->conn_target->t_name, target_address);
+ login_redirect(request, target_address);
+
+ return (true);
+}
+
+static void
login_negotiate(struct connection *conn, struct pdu *request)
{
struct pdu *response;
@@ -680,6 +740,7 @@ login(struct connection *conn)
struct portal_group *pg;
const char *initiator_name, *initiator_alias, *session_type,
*target_name, *auth_method;
+ bool redirected;
/*
* Handle the initial Login Request - figure out required authentication
@@ -722,6 +783,12 @@ login(struct connection *conn)
*/
setproctitle("%s (%s)", conn->conn_initiator_addr, conn->conn_initiator_name);
+ redirected = login_portal_redirect(conn, request);
+ if (redirected) {
+ log_debugx("initiator redirected; exiting");
+ exit(0);
+ }
+
initiator_alias = keys_find(request_keys, "InitiatorAlias");
if (initiator_alias != NULL)
conn->conn_initiator_alias = checked_strdup(initiator_alias);
@@ -809,6 +876,12 @@ login(struct connection *conn)
keys_delete(request_keys);
+ redirected = login_target_redirect(conn, request);
+ if (redirected) {
+ log_debugx("initiator redirected; exiting");
+ exit(0);
+ }
+
log_debugx("initiator skipped the authentication, "
"and we don't need it; proceeding with negotiation");
login_negotiate(conn, request);
@@ -820,6 +893,12 @@ login(struct connection *conn)
* Initiator might want to to authenticate,
* but we don't need it.
*/
+ redirected = login_target_redirect(conn, request);
+ if (redirected) {
+ log_debugx("initiator redirected; exiting");
+ exit(0);
+ }
+
log_debugx("authentication not required; "
"transitioning to operational parameter negotiation");
@@ -908,5 +987,17 @@ login(struct connection *conn)
login_chap(conn, ag);
+ /*
+ * RFC 3720, 10.13.5. Status-Class and Status-Detail, says
+ * the redirection SHOULD be accepted by the initiator before
+ * authentication, but MUST be be accepted afterwards; that's
+ * why we're doing it here and not earlier.
+ */
+ redirected = login_target_redirect(conn, request);
+ if (redirected) {
+ log_debugx("initiator redirected; exiting");
+ exit(0);
+ }
+
login_negotiate(conn, NULL);
}
OpenPOWER on IntegriCloud