Module Name: src Committed By: mlelstv Date: Sun Jun 24 17:01:35 UTC 2012
Modified Files: src/sys/dev/iscsi: iscsi_ioctl.c iscsi_rcv.c iscsi_send.c iscsi_text.c iscsi_utils.c Log Message: Add more debugging, fix filehandle usage, login negotiation and session shutdown. Add #ifdef'd code to send negotiation parameters in hex instead of base64, so it works against older Linux targets. To generate a diff of this commit: cvs rdiff -u -r1.3 -r1.4 src/sys/dev/iscsi/iscsi_ioctl.c cvs rdiff -u -r1.2 -r1.3 src/sys/dev/iscsi/iscsi_rcv.c \ src/sys/dev/iscsi/iscsi_utils.c cvs rdiff -u -r1.4 -r1.5 src/sys/dev/iscsi/iscsi_send.c \ src/sys/dev/iscsi/iscsi_text.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/iscsi/iscsi_ioctl.c diff -u src/sys/dev/iscsi/iscsi_ioctl.c:1.3 src/sys/dev/iscsi/iscsi_ioctl.c:1.4 --- src/sys/dev/iscsi/iscsi_ioctl.c:1.3 Sat Jun 9 06:19:58 2012 +++ src/sys/dev/iscsi/iscsi_ioctl.c Sun Jun 24 17:01:35 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: iscsi_ioctl.c,v 1.3 2012/06/09 06:19:58 mlelstv Exp $ */ +/* $NetBSD: iscsi_ioctl.c,v 1.4 2012/06/24 17:01:35 mlelstv Exp $ */ /*- * Copyright (c) 2004,2005,2006,2011 The NetBSD Foundation, Inc. @@ -488,7 +488,6 @@ kill_connection(connection_t *conn, uint conn->terminating = status; conn->state = ST_SETTLING; - callout_stop(&conn->timeout); /* let send thread take over next step of cleanup */ wakeup(&conn->pdus_to_send); @@ -634,6 +633,7 @@ create_connection(iscsi_login_parameters callout_setfunc(&connection->timeout, connection_timeout, connection); connection->idle_timeout_val = CONNECTION_IDLE_TIMEOUT; + init_sernum(&connection->StatSN_buf); create_pdus(connection); if ((rc = get_socket(par->socket, &connection->sock)) != 0) { @@ -646,6 +646,9 @@ create_connection(iscsi_login_parameters DEBC(connection, 1, ("get_socket: par_sock=%d, fdesc=%p\n", par->socket, connection->sock)); + /* close the file descriptor */ + fd_close(par->socket); + connection->threadobj = p; connection->login_par = par; @@ -666,7 +669,7 @@ create_connection(iscsi_login_parameters "ConnSend")) != 0) { DEBOUT(("Can't create send thread (rc %d)\n", rc)); - connection->terminating = TRUE; + connection->terminating = ISCSI_STATUS_NO_RESOURCES; /* * We must close the socket here to force the receive @@ -716,9 +719,6 @@ create_connection(iscsi_login_parameters session->mru_connection = connection; CS_END; - /* close the file descriptor */ - fd_close(par->socket); - DEBC(connection, 5, ("Connection created successfully!\n")); return 0; } @@ -764,9 +764,12 @@ recreate_connection(iscsi_login_paramete return rc; } + /* close the file descriptor */ + fd_close(par->socket); + connection->threadobj = p; connection->login_par = par; - connection->terminating = 0; + connection->terminating = ISCSI_STATUS_SUCCESS; connection->recover++; connection->num_timeouts = 0; connection->state = ST_SEC_NEG; @@ -831,9 +834,6 @@ recreate_connection(iscsi_login_paramete DEBC(connection, 5, ("Connection ReCreated successfully - status %d\n", par->status)); - /* close the file descriptor */ - fd_close(par->socket); - return 0; } @@ -906,7 +906,7 @@ check_login_pars(iscsi_login_parameters_ return ISCSI_STATUS_PARAMETER_INVALID; } } - return ISCSI_STATUS_SUCCESS; + return 0; } @@ -1491,6 +1491,8 @@ iscsi_cleanup_thread(void *par) while (conn->usecount > 0) tsleep(conn, PWAIT, "finalwait", 20); + callout_stop(&conn->timeout); + closef(conn->sock); free(conn, M_DEVBUF); if (!(--sess->total_connections)) { Index: src/sys/dev/iscsi/iscsi_rcv.c diff -u src/sys/dev/iscsi/iscsi_rcv.c:1.2 src/sys/dev/iscsi/iscsi_rcv.c:1.3 --- src/sys/dev/iscsi/iscsi_rcv.c:1.2 Tue Jun 5 16:36:06 2012 +++ src/sys/dev/iscsi/iscsi_rcv.c Sun Jun 24 17:01:35 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: iscsi_rcv.c,v 1.2 2012/06/05 16:36:06 mhitch Exp $ */ +/* $NetBSD: iscsi_rcv.c,v 1.3 2012/06/24 17:01:35 mlelstv Exp $ */ /*- * Copyright (c) 2004,2005,2006,2011 The NetBSD Foundation, Inc. @@ -163,6 +163,8 @@ read_pdu_data(pdu_t *pdu, uint8_t *data, int i, pad; connection_t *conn = pdu->connection; + DEBOUT(("read_pdu_data: data segment length = %d\n", + ntoh3(pdu->pdu.DataSegmentLength))); if (!(len = ntoh3(pdu->pdu.DataSegmentLength))) { return 0; } @@ -324,8 +326,11 @@ check_StatSN(connection_t *conn, uint32_ ack_sernum(&conn->StatSN_buf, sn); if (rc != 1) { - if (!rc) + if (rc == 0) { + DEBOUT(("Duplicate PDU, ExpSN %d, Recvd: %d\n", + conn->StatSN_buf.ExpSN, sn)); return -1; + } if (rc < 0) { DEBOUT(("Excessive outstanding Status PDUs, ExpSN %d, Recvd: %d\n", @@ -410,8 +415,9 @@ receive_login_pdu(connection_t *conn, pd { int rc; - DEBC(conn, 9, ("Received Login Response PDU, op=%x, flags=%x\n", - pdu->pdu.Opcode, pdu->pdu.Flags)); + DEBC(conn, 9, ("Received Login Response PDU, op=%x, flags=%x, sn=%u\n", + pdu->pdu.Opcode, pdu->pdu.Flags, + ntohl(pdu->pdu.p.login_rsp.StatSN))); if (req_ccb == NULL) { /* Duplicate?? */ @@ -419,31 +425,31 @@ receive_login_pdu(connection_t *conn, pd return -1; } - if (!conn->StatSN_buf.next_sn) - conn->StatSN_buf.next_sn = conn->StatSN_buf.ExpSN = - ntohl(pdu->pdu.p.login_rsp.StatSN) + 1; - else if (check_StatSN(conn, pdu->pdu.p.login_rsp.StatSN, TRUE)) - return -1; - - if (pdu->temp_data_len) { - if ((rc = collect_text_data(pdu, req_ccb)) != 0) { - return max(rc, 0); - } - } - if (pdu->pdu.p.login_rsp.StatusClass) { DEBC(conn, 1, ("Login problem - Class = %x, Detail = %x\n", pdu->pdu.p.login_rsp.StatusClass, pdu->pdu.p.login_rsp.StatusDetail)); req_ccb->status = ISCSI_STATUS_LOGIN_FAILED; - } else { - negotiate_login(conn, pdu, req_ccb); - /* negotiate_login will decide whether login is complete or not */ + /* XXX */ + wake_ccb(req_ccb); return 0; } - wake_ccb(req_ccb); + if (!conn->StatSN_buf.next_sn) { + conn->StatSN_buf.next_sn = conn->StatSN_buf.ExpSN = + ntohl(pdu->pdu.p.login_rsp.StatSN) + 1; + } else if (check_StatSN(conn, pdu->pdu.p.login_rsp.StatSN, TRUE)) + return -1; + + if (pdu->temp_data_len) { + if ((rc = collect_text_data(pdu, req_ccb)) != 0) + return max(rc, 0); + } + + negotiate_login(conn, pdu, req_ccb); + + /* negotiate_login will decide whether login is complete or not */ return 0; } Index: src/sys/dev/iscsi/iscsi_utils.c diff -u src/sys/dev/iscsi/iscsi_utils.c:1.2 src/sys/dev/iscsi/iscsi_utils.c:1.3 --- src/sys/dev/iscsi/iscsi_utils.c:1.2 Sat Jun 9 06:19:58 2012 +++ src/sys/dev/iscsi/iscsi_utils.c Sun Jun 24 17:01:35 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: iscsi_utils.c,v 1.2 2012/06/09 06:19:58 mlelstv Exp $ */ +/* $NetBSD: iscsi_utils.c,v 1.3 2012/06/24 17:01:35 mlelstv Exp $ */ /*- * Copyright (c) 2004,2005,2006,2008 The NetBSD Foundation, Inc. @@ -624,7 +624,9 @@ init_sernum(sernum_buffer_t *buff) int add_sernum(sernum_buffer_t *buff, uint32_t num) { - int i, t, b, n, diff; + int i, t, b; + uint32_t n; + int32_t diff; /* * next_sn is the next expected SN, so normally diff should be 1. @@ -633,7 +635,7 @@ add_sernum(sernum_buffer_t *buff, uint32 diff = (num - n) + 1; if (diff <= 0) { - PDEB(1, ("Rx Duplicate Block: SN %d < Next SN %d\n", num, n)); + PDEB(1, ("Rx Duplicate Block: SN %u < Next SN %u\n", num, n)); return 0; /* ignore if SN is smaller than expected (dup or retransmit) */ } @@ -652,7 +654,7 @@ add_sernum(sernum_buffer_t *buff, uint32 } buff->top = t; - DEB(10, ("AddSernum bottom %d [%d], top %d, num %d, diff %d\n", + DEB(10, ("AddSernum bottom %d [%d], top %d, num %u, diff %d\n", b, buff->sernum[b], buff->top, num, diff)); return diff; Index: src/sys/dev/iscsi/iscsi_send.c diff -u src/sys/dev/iscsi/iscsi_send.c:1.4 src/sys/dev/iscsi/iscsi_send.c:1.5 --- src/sys/dev/iscsi/iscsi_send.c:1.4 Tue Jun 19 14:19:46 2012 +++ src/sys/dev/iscsi/iscsi_send.c Sun Jun 24 17:01:35 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: iscsi_send.c,v 1.4 2012/06/19 14:19:46 martin Exp $ */ +/* $NetBSD: iscsi_send.c,v 1.5 2012/06/24 17:01:35 mlelstv Exp $ */ /*- * Copyright (c) 2004,2005,2006,2011 The NetBSD Foundation, Inc. @@ -344,19 +344,20 @@ iscsi_send_thread(void *par) fp = conn->sock; /* - * We must close the socket here to force the receive + * We shutdown the socket here to force the receive * thread to wake up */ DEBC(conn, 9, ("Closing Socket %p\n", conn->sock)); solock((struct socket *) fp->f_data); soshutdown((struct socket *) fp->f_data, SHUT_RDWR); sounlock((struct socket *) fp->f_data); - closef(fp); /* wake up any non-reassignable waiting CCBs */ for (ccb = TAILQ_FIRST(&conn->ccbs_waiting); ccb != NULL; ccb = nccb) { nccb = TAILQ_NEXT(ccb, chain); if (!(ccb->flags & CCBF_REASSIGN) || ccb->pdu_waiting == NULL) { + DEBC(conn, 9, ("Terminating CCB %p (t=%p)\n", + ccb,&ccb->timeout)); ccb->status = conn->terminating; wake_ccb(ccb); } else { Index: src/sys/dev/iscsi/iscsi_text.c diff -u src/sys/dev/iscsi/iscsi_text.c:1.4 src/sys/dev/iscsi/iscsi_text.c:1.5 --- src/sys/dev/iscsi/iscsi_text.c:1.4 Sat Jun 9 06:19:58 2012 +++ src/sys/dev/iscsi/iscsi_text.c Sun Jun 24 17:01:35 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: iscsi_text.c,v 1.4 2012/06/09 06:19:58 mlelstv Exp $ */ +/* $NetBSD: iscsi_text.c,v 1.5 2012/06/24 17:01:35 mlelstv Exp $ */ /*- * Copyright (c) 2005,2006,2011 The NetBSD Foundation, Inc. @@ -34,6 +34,9 @@ #include <sys/md5.h> #include <sys/cprng.h> +/* define to send T_BIGNUM in hex format instead of base64 */ +/* #define ISCSI_HEXBIGNUMS */ + #define isdigit(x) ((x) >= '0' && (x) <= '9') #define toupper(x) ((x) & ~0x20) @@ -555,6 +558,10 @@ get_parameter(uint8_t *buf, negotiation_ return skiptozero(bp); } + DEB(10, ("get_par: key <%s>=%d, val=%d, ret %p\n", + buf, i, entries[i].val, bp)); + DEB(10, ("get_par: value '%s'\n",bp)); + switch (entries[i].val) { case T_NUM: bp = get_numval(bp, &par->val.nval[0]); @@ -589,8 +596,6 @@ get_parameter(uint8_t *buf, negotiation_ bp = NULL; break; } - DEB(10, ("get_par: key <%s>=%d, val=%d, ret %p\n", - buf, i, entries[i].val, bp)); return bp; } @@ -619,6 +624,38 @@ my_strcpy(uint8_t *dest, const uint8_t * return cc; } +/* + * put_bignumval: + * Write a large numeric value. + * NOTE: Overwrites source string. + * + * Parameter: + * buf The buffer pointer + * par The parameter + * + * Returns: The pointer to the next parameter, NULL on error. + */ + +STATIC unsigned +put_bignumval(negotiation_parameter_t *par, uint8_t *buf) +{ +#ifdef ISCSI_HEXBIGNUMS + int k, c; + + my_strcpy(buf, "0x"); + for (k=0; k<par->list_num; ++k) { + c = par->val.sval[k] >> 4; + buf[2+2*k] = c < 10 ? '0' + c : 'a' + (c-10); + c = par->val.sval[k] & 0xf; + buf[2+2*k+1] = c < 10 ? '0' + c : 'a' + (c-10); + } + buf[2+2*k] = '\0'; + + return 2+2*par->list_num; +#else + return base64_encode(par->val.sval, par->list_num, buf); +#endif +} /* * put_parameter: @@ -635,9 +672,12 @@ STATIC unsigned put_parameter(uint8_t *buf, unsigned len, negotiation_parameter_t *par) { int i; - unsigned cc; + unsigned cc, cl; const uint8_t *sp; + DEB(10, ("put_par: key <%s>=%d, val=%d\n", + entries[par->key].name, par->key, entries[par->key].val)); + if (par->key > MAX_KEY) { return snprintf(buf, len, "%s=NotUnderstood", par->val.sval); } @@ -647,21 +687,21 @@ put_parameter(uint8_t *buf, unsigned len for (i = 0; i < par->list_num; i++) { switch (entries[par->key].val) { case T_NUM: - cc += snprintf(&buf[cc], len - cc, "%d", par->val.nval[i]); + cl = snprintf(&buf[cc], len - cc, "%d", + par->val.nval[i]); break; case T_BIGNUM: - /* list_num holds value size */ - cc += base64_encode(par->val.sval, par->list_num, &buf[cc]); + cl = put_bignumval(par, &buf[cc]); i = par->list_num; break; case T_STRING: - cc += my_strcpy(&buf[cc], par->val.sval); + cl = my_strcpy(&buf[cc], par->val.sval); break; case T_YESNO: - cc += my_strcpy(&buf[cc], + cl = my_strcpy(&buf[cc], (par->val.nval[i]) ? "Yes" : "No"); break; @@ -680,18 +720,19 @@ put_parameter(uint8_t *buf, unsigned len sp = "None"; break; } - cc += my_strcpy(&buf[cc], sp); + cl = my_strcpy(&buf[cc], sp); break; case T_DIGEST: - cc += my_strcpy(&buf[cc], (par->val.nval[i]) ? "CRC32C" : "None"); + cl = my_strcpy(&buf[cc], + (par->val.nval[i]) ? "CRC32C" : "None"); break; case T_RANGE: if ((i + 1) >= par->list_num) { - cc += my_strcpy(&buf[cc], "Reject"); + cl = my_strcpy(&buf[cc], "Reject"); } else { - cc += snprintf(&buf[cc], len - cc, + cl = snprintf(&buf[cc], len - cc, "%d~%d", par->val.nval[i], par->val.nval[i + 1]); i++; @@ -699,26 +740,31 @@ put_parameter(uint8_t *buf, unsigned len break; case T_SENDT: - cc += my_strcpy(&buf[cc], par->val.sval); + cl = my_strcpy(&buf[cc], par->val.sval); break; case T_SESS: - cc += my_strcpy(&buf[cc], + cl = my_strcpy(&buf[cc], (par->val.nval[i]) ? "Normal" : "Discovery"); break; default: + cl = 0; /* We should't be here... */ DEBOUT(("Invalid type %d in put_parameter!\n", entries[par->key].val)); break; } + + DEB(10, ("put_par: value '%s'\n",&buf[cc])); + + cc += cl; if ((i + 1) < par->list_num) { buf[cc++] = ','; } } - buf[cc] = 0x0; /* make sure it's terminated */ + buf[cc] = 0x0; /* make sure it's terminated */ return cc + 1; /* return next place in list */ } @@ -781,7 +827,11 @@ parameter_size(negotiation_parameter_t * case T_BIGNUM: /* list_num holds value size */ +#ifdef ISCSI_HEXBIGNUMS + size += 2 + 2*par->list_num; +#else size += base64_enclen(par->list_num); +#endif i = par->list_num; break;