diff options
author | trasz <trasz@FreeBSD.org> | 2014-11-09 13:01:09 +0000 |
---|---|---|
committer | trasz <trasz@FreeBSD.org> | 2014-11-09 13:01:09 +0000 |
commit | 4eec651ec388a7406d989f93aef0d62f748080fc (patch) | |
tree | 7fce56b0e4a689fc51e535b741025162dc8c5f61 /usr.sbin/ctld/login.c | |
parent | 037bd5af5746c3f20b892933dccfc78a245f81a4 (diff) | |
download | FreeBSD-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.c | 91 |
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); } |