diff options
author | trasz <trasz@FreeBSD.org> | 2014-09-17 08:47:58 +0000 |
---|---|---|
committer | trasz <trasz@FreeBSD.org> | 2014-09-17 08:47:58 +0000 |
commit | 312a175bdaf969fe82f1472761a6ac1b811db765 (patch) | |
tree | 25a5e5f61248a12a8255d3005a294f962dc3fe1c /usr.sbin/iscsid | |
parent | e073d019f54a312574e298a30d832799ff259bf0 (diff) | |
download | FreeBSD-src-312a175bdaf969fe82f1472761a6ac1b811db765.zip FreeBSD-src-312a175bdaf969fe82f1472761a6ac1b811db765.tar.gz |
MFC r271437:
Don't blindly assume the target agreed to transition to Full Feature Phase;
if we got a Login Response PDU without the "T" bit set, try again with
an empty request. This fixes interoperability with COMSTAR.
Reviewed by: mav
Tested by: mav
Approved by: re (kib)
Sponsored by: The FreeBSD Foundation
Diffstat (limited to 'usr.sbin/iscsid')
-rw-r--r-- | usr.sbin/iscsid/login.c | 40 |
1 files changed, 31 insertions, 9 deletions
diff --git a/usr.sbin/iscsid/login.c b/usr.sbin/iscsid/login.c index 3391f90..1b8703c 100644 --- a/usr.sbin/iscsid/login.c +++ b/usr.sbin/iscsid/login.c @@ -574,7 +574,7 @@ login_negotiate(struct connection *conn) struct pdu *request, *response; struct keys *request_keys, *response_keys; struct iscsi_bhs_login_response *bhslr; - int i; + int i, nrequests = 0; log_debugx("beginning operational parameter negotiation"); request = login_new_request(conn, BHSLR_STAGE_OPERATIONAL_NEGOTIATION); @@ -628,19 +628,41 @@ login_negotiate(struct connection *conn) response_keys->keys_names[i], response_keys->keys_values[i]); } - bhslr = (struct iscsi_bhs_login_response *)response->pdu_bhs; - if ((bhslr->bhslr_flags & BHSLR_FLAGS_TRANSIT) == 0) - log_warnx("received final login response " - "without the \"T\" flag"); - else if (login_nsg(response) != BHSLR_STAGE_FULL_FEATURE_PHASE) + keys_delete(response_keys); + response_keys = NULL; + + for (;;) { + bhslr = (struct iscsi_bhs_login_response *)response->pdu_bhs; + if ((bhslr->bhslr_flags & BHSLR_FLAGS_TRANSIT) != 0) + break; + + nrequests++; + if (nrequests > 5) { + log_warnx("received login response " + "without the \"T\" flag too many times; giving up"); + break; + } + + log_debugx("received login response " + "without the \"T\" flag; sending another request"); + + pdu_delete(response); + + request = login_new_request(conn, + BHSLR_STAGE_OPERATIONAL_NEGOTIATION); + pdu_send(request); + pdu_delete(request); + + response = login_receive(conn); + } + + if (login_nsg(response) != BHSLR_STAGE_FULL_FEATURE_PHASE) log_warnx("received final login response with wrong NSG 0x%x", login_nsg(response)); + pdu_delete(response); log_debugx("operational parameter negotiation done; " "transitioning to Full Feature phase"); - - keys_delete(response_keys); - pdu_delete(response); } static void |