diff options
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 |