diff options
-rw-r--r-- | etc/iscsid.conf | 15 | ||||
-rw-r--r-- | usr/config.h | 3 | ||||
-rw-r--r-- | usr/discovery.c | 569 | ||||
-rw-r--r-- | usr/idbm.c | 154 | ||||
-rw-r--r-- | usr/idbm.h | 4 | ||||
-rw-r--r-- | usr/iscsi_settings.h | 1 | ||||
-rw-r--r-- | usr/iscsiadm.c | 14 | ||||
-rw-r--r-- | usr/iscsiadm.h | 11 | ||||
-rw-r--r-- | usr/strings.c | 1 |
9 files changed, 162 insertions, 610 deletions
diff --git a/etc/iscsid.conf b/etc/iscsid.conf index 64127b7..81f464b 100644 --- a/etc/iscsid.conf +++ b/etc/iscsid.conf @@ -153,6 +153,16 @@ node.session.iscsi.MaxBurstLength = 16776192 # the default is 131072 node.conn[0].iscsi.MaxRecvDataSegmentLength = 131072 + +# To specify the maximum number of data bytes the initiator can receive +# in an iSCSI PDU from a target during a discovery session, edit the +# following line. +# +# The value is the number of bytes in the range of 512 to (2^24-1) and +# the default is 32768 +# +discovery.sendtargets.iscsi.MaxRecvDataSegmentLength = 32768 + # To allow the targets to control the setting of the digest checking, # with the initiator requesting a preference of enabling the checking, uncomment# one or both of the following lines: #node.conn[0].iscsi.HeaderDigest = CRC32C,None @@ -177,8 +187,3 @@ node.conn[0].iscsi.MaxRecvDataSegmentLength = 131072 # The default is to never use DataDigests and to allow the target to control # the setting of the HeaderDigest checking with the initiator requesting # a preference of disabling the checking. - -# -# To enable the iSNS server -#isns.address = 192.168.0.1 -#isns.port = 3205 diff --git a/usr/config.h b/usr/config.h index a071de9..2cbb465 100644 --- a/usr/config.h +++ b/usr/config.h @@ -148,11 +148,10 @@ struct iscsi_session_operational_config { struct iscsi_sendtargets_config { char address[NI_MAXHOST]; int port; - int continuous; - int send_async_text; int reopen_max; struct iscsi_auth_config auth; struct iscsi_connection_timeout_config conn_timeo; + struct iscsi_conn_operational_config iscsi; }; struct iscsi_slp_config { diff --git a/usr/discovery.c b/usr/discovery.c index ab3b2ca..0eefe33 100644 --- a/usr/discovery.c +++ b/usr/discovery.c @@ -38,6 +38,9 @@ #include "initiator.h" #include "iscsiadm.h" #include "log.h" +#include "idbm.h" +#include "iscsi_settings.h" +#include "iscsi_proto.h" #ifdef SLP_ENABLE #include "iscsi-slp-discovery.h" @@ -46,32 +49,6 @@ #define DISCOVERY_NEED_RECONNECT 0xdead0001 static int rediscover = 0; -static int record_begin; - -static int -send_nop_reply(iscsi_session_t *session, struct iscsi_nopin *nop, - char *data, int timeout) -{ - struct iscsi_nopout out; - - memset(&out, 0, sizeof (out)); - out.opcode = ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE; - out.flags = ISCSI_FLAG_CMD_FINAL; - memcpy(out.lun, nop->lun, sizeof (out.lun)); - out.itt = nop->itt; - out.ttt = nop->ttt; - memcpy(out.dlength, nop->dlength, sizeof (out.dlength)); - out.cmdsn = htonl(session->cmdsn); /* don't increment after - * immediate cmds - */ - out.exp_statsn = htonl(session->conn[0].exp_statsn); - - log_debug(4, "sending nop reply for ttt %u, cmdsn %u, dlength %d", - ntohl(out.ttt), ntohl(out.cmdsn), ntoh24(out.dlength)); - - return iscsi_io_send_pdu(&session->conn[0], (struct iscsi_hdr *)&out, - ISCSI_DIGEST_NONE, data, ISCSI_DIGEST_NONE, timeout); -} static int iscsi_make_text_pdu(iscsi_session_t *session, struct iscsi_hdr *hdr, @@ -158,8 +135,8 @@ iterate_targets(iscsi_session_t *session, uint32_t ttt) return 1; } -int -add_portal(struct string_buffer *info, char *address, char *port, char *tag) +static int +add_portal(idbm_t *db, node_rec_t *rec, char *address, char *port, char *tag) { struct sockaddr_storage ss; char host[NI_MAXHOST]; @@ -174,41 +151,30 @@ add_portal(struct string_buffer *info, char *address, char *port, char *tag) getnameinfo((struct sockaddr *) &ss, sizeof(ss), host, sizeof(host), NULL, 0, NI_NUMERICHOST); - if (tag && *tag) { - if (!append_sprintf(info, "TT=%s\n", tag)) { - log_error("couldn't add portal tag %s", - tag); - return 0; - } - } - - if (port && *port) { - if (!append_sprintf(info, "TP=%s\n", port)) { - log_error("couldn't add port %s", port); - return 0; - } - } - - if (strcmp(host, address)) - /* if the resolved name doesn't match the original, - * send an RA line as well as a TA line - */ - return append_sprintf(info, "RA=%s\nTA=%s\n", - host, address); + if (tag && *tag) + rec->tpgt = atoi(tag); else - /* don't need the RA line */ - return append_sprintf(info, "TA=%s\n", address); + rec->tpgt = PORTAL_GROUP_TAG_UNKNOWN; + if (port && *port) + rec->conn[0].port = atoi(port); + else + rec->conn[0].port = DEF_ISCSI_PORT; + strncpy(rec->conn[0].address, address, NI_MAXHOST); + + if (idbm_add_nodes(db, rec)) + log_error("Could not add record for %s %s,%d,%d\n", + rec->name, address, rec->conn[0].port, rec->tpgt); + return 1; } int -add_target_record(struct string_buffer *info, char *name, char *end, - int lun_inventory_changed, char *default_address, - char *default_port) +add_target_record(idbm_t *db, char *name, char *end, + char *default_address, char *default_port) { char *text = NULL; char *nul = name; size_t length; - size_t original = data_length(info); + node_rec_t rec; /* address = IPv4 * address = [IPv6] @@ -236,24 +202,8 @@ add_target_record(struct string_buffer *info, char *name, char *end, return 0; } - if (!record_begin) { - if (!append_sprintf - (info, lun_inventory_changed ? "DLC=%s\n" : "DTN=%s\n", - name)) { - log_error("couldn't report target %s", name); - truncate_buffer(info, original); - return 0; - } - record_begin = 1; - } else { - if (!append_sprintf - (info, lun_inventory_changed ? "LC=%s\n" : "TN=%s\n", - name)) { - log_error("couldn't report target %s", name); - truncate_buffer(info, original); - return 0; - } - } + idbm_node_setup_from_conf(db, &rec); + strncpy(rec.name, name, TARGET_NAME_MAXLEN); text = name + length; @@ -264,26 +214,15 @@ add_target_record(struct string_buffer *info, char *name, char *end, /* if no address is provided, use the default */ if (text >= end) { if (default_address == NULL) { - log_error( - "no default address known for target %s", name); - truncate_buffer(info, original); - return 0; - } else - if (!add_portal(info, default_address, default_port, NULL)) - { - log_error( - "failed to add default portal, ignoring " - "target %s", name); - truncate_buffer(info, original); + log_error("no default address known for target %s", + name); return 0; - } else if (!append_string(info, ";\n")) { - log_error( - "failed to terminate target record, " - "ignoring target %s", name); - truncate_buffer(info, original); + } else if (!add_portal(db, &rec, default_address, default_port, + NULL)) { + log_error("failed to add default portal, ignoring " + "target %s", name); return 0; } - /* finished adding the default */ return 1; } @@ -316,37 +255,23 @@ add_target_record(struct string_buffer *info, char *name, char *end, *temp = '\0'; } - if (!add_portal(info, address, port, tag)) { - log_error( - "failed to add default portal, " - "ignoring target %s", name); - truncate_buffer(info, original); + if (!add_portal(db, &rec, address, port, tag)) { + log_error("failed to add default portal, " + "ignoring target %s", name); return 0; } - } else { + } else log_error("unexpected SendTargets data: %s", text); - } - text = next; } - /* indicate the end of the target record */ - if (!append_string(info, ";\n")) { - log_error( - "failed to terminate target record, ignoring target %s", - name); - truncate_buffer(info, original); - return 0; - } - return 1; } static int -process_sendtargets_response(struct string_buffer *sendtargets, - struct string_buffer *info, int final, - int lun_inventory_changed, char *default_address, +process_sendtargets_response(idbm_t *db, struct string_buffer *sendtargets, + int final, char *default_address, char *default_port) { char *start = buffer_data(sendtargets); @@ -355,7 +280,6 @@ process_sendtargets_response(struct string_buffer *sendtargets, char *nul = end - 1; char *record = NULL; int num_targets = 0; - size_t valid_info = 0; if (start == end) { /* no SendTargets data */ @@ -398,17 +322,15 @@ process_sendtargets_response(struct string_buffer *sendtargets, * the end of. don't bother passing the * "TargetName=" prefix. */ - if (!add_target_record(info, record + 11, text, - lun_inventory_changed, default_address, - default_port)) { + if (!add_target_record(db, record + 11, text, + default_address, + default_port)) { log_error( "failed to add target record"); truncate_buffer(sendtargets, 0); - truncate_buffer(info, valid_info); goto done; } num_targets++; - valid_info = data_length(info); } record = text; } @@ -429,16 +351,14 @@ process_sendtargets_response(struct string_buffer *sendtargets, "processing final sendtargets record %p, " "line %s", record, record); - if (add_target_record (info, record + 11, text, - lun_inventory_changed, default_address, - default_port)) { + if (add_target_record (db, record + 11, text, + default_address, default_port)) { num_targets++; record = NULL; truncate_buffer(sendtargets, 0); } else { log_error("failed to add target record"); truncate_buffer(sendtargets, 0); - truncate_buffer(info, valid_info); goto done; } } else { @@ -458,95 +378,16 @@ process_sendtargets_response(struct string_buffer *sendtargets, } done: - /* send all of the discovered targets to the fd ("stdout" currently) */ - if (append_string(info, final ? "!\n" : ".\n")) { - if (final) { - record_begin = 0; - } - log_debug(4, "sent %d targets to the parent", num_targets); - return 1; - } else { - log_error("couldn't send %d targets to the parent", - num_targets); - return 0; - } return 1; } -static int -add_async_record(struct string_buffer *info, char *record, int targetoffline) -{ - int length = strlen(record); - size_t original = data_length(info); - - log_debug(7, " adding async record for %s", record); - - if (targetoffline) { - /* We have received targetoffline event */ - if (length > TARGET_NAME_MAXLEN) { - log_error("Targetname %s too long, ignoring", - record); - return 0; - } - } - if (!append_sprintf - (info, targetoffline ? "ATF=%s\n" : "APF=%s\n", record)) { - log_error("couldn't report the record\n"); - truncate_buffer(info, original); - return 0; - } else if (!append_string(info, ";\n")) { - log_error( - "failed to terminate target record, ignoring target %s", - record); - truncate_buffer(info, original); - } - return 1; -} - static void clear_timer(struct timeval *timer) { memset(timer, 0, sizeof (*timer)); } -static int -process_async_event_text(struct string_buffer *sendtargets, - struct string_buffer *info, struct timeval *timer) -{ - char *text = buffer_data(sendtargets); - int targetoffline = 0; - int slen = (ntohs(*(short *) (text))); - text = text + 2 + slen; - - if (strncmp(text, "X-com.cisco.targetOffline=", 26) == 0) { - targetoffline = 1; - if (!add_async_record(info, text + 26, targetoffline)) { - log_error("failed to add async record"); - return 0; - } - clear_timer(timer); - } else if (strncmp(text, "X-com.cisco.portalOffline=", 26) == 0) { - targetoffline = 0; - if (!add_async_record(info, text + 26, targetoffline)) { - log_error("failed to add async record"); - return 0; - } - clear_timer(timer); - } else { - log_debug(1, "sendtargets for the other events"); - return 1; - } - - if (append_string(info, "!\n")) { - log_debug(4, "sent async event record to the caller"); - return 1; - } else { - log_error("couldn't send async event record to the caller"); - return 0; - } -} - /* set timer to now + seconds */ static void set_timer(struct timeval *timer, int seconds) @@ -662,12 +503,21 @@ init_new_session(struct iscsi_sendtargets_config *config) session->conn[0].auth_timeout = config->conn_timeo.auth_timeout; session->conn[0].active_timeout = config->conn_timeo.active_timeout; session->conn[0].idle_timeout = config->conn_timeo.idle_timeout; - session->conn[0].ping_timeout = config->conn_timeo.ping_timeout; - session->send_async_text = config->continuous ? - config->send_async_text : -1; session->conn[0].hdrdgst_en = ISCSI_DIGEST_NONE; session->conn[0].datadgst_en = ISCSI_DIGEST_NONE; - session->conn[0].max_recv_dlength = ISCSI_DEF_MAX_RECV_SEG_LEN; + + session->conn[0].max_recv_dlength = + config->iscsi.MaxRecvDataSegmentLength; + if (session->conn[0].max_recv_dlength < ISCSI_MIN_MAX_RECV_SEG_LEN || + session->conn[0].max_recv_dlength > ISCSI_MAX_MAX_RECV_SEG_LEN) { + log_error("Invalid iscsi.MaxRecvDataSegmentLength. Must be " + "within %u and %u. Setting to %u.", + ISCSI_MIN_MAX_RECV_SEG_LEN, + ISCSI_MAX_MAX_RECV_SEG_LEN, + DEF_INI_DISC_MAX_RECV_SEG_LEN); + session->conn[0].max_recv_dlength = + DEF_INI_DISC_MAX_RECV_SEG_LEN; + } session->conn[0].max_xmit_dlength = ISCSI_DEF_MAX_RECV_SEG_LEN; session->reopen_cnt = config->reopen_max; @@ -781,15 +631,12 @@ setup_authentication(iscsi_session_t *session, } static int -process_recvd_pdu(struct iscsi_hdr *pdu, +process_recvd_pdu(idbm_t *db, struct iscsi_hdr *pdu, struct iscsi_sendtargets_config *config, iscsi_session_t *session, struct string_buffer *sendtargets, - struct string_buffer *info, - int *lun_inventory_changed, char *default_port, int *active, - int *long_lived, struct timeval *async_timer, char *data) { @@ -819,17 +666,15 @@ process_recvd_pdu(struct iscsi_hdr *pdu, enlarge_data (sendtargets, dlength); /* process as much as we can right now */ - process_sendtargets_response (sendtargets, - info, final, - *lun_inventory_changed, - config->address, - default_port); + process_sendtargets_response(db, sendtargets, + final, + config->address, + default_port); if (final) { /* SendTargets exchange is now complete */ *active = 0; - *lun_inventory_changed = 1; /* from now on, after any reconnect, * assume LUNs may have changed */ @@ -843,150 +688,13 @@ process_recvd_pdu(struct iscsi_hdr *pdu, } break; } - case ISCSI_OP_ASYNC_EVENT:{ - struct iscsi_async *async_hdr = - (struct iscsi_async *) pdu; - int dlength = ntoh24(pdu->dlength); - short senselen; - char logbuf[128]; - int i; - - /* - * If we receive an async message stating - * the target wants to close the connection, - * then don't try to reconnect anymore. - * This is reasonable, so we don't log - * anything here. - */ - if ((async_hdr->async_event == - ISCSI_ASYNC_MSG_REQUEST_LOGOUT)|| - (async_hdr->async_event == - ISCSI_ASYNC_MSG_DROPPING_CONNECTION)|| - (async_hdr->async_event == - ISCSI_ASYNC_MSG_DROPPING_ALL_CONNECTIONS)) { - *long_lived=0; - break; - } - - /* - * Log info about the async message. - */ - log_warning( - "Received Async Msg from target, Event = %d, " - "Code = %d, Data Len = %d", - async_hdr->async_event, - async_hdr->async_vcode, dlength); - - /* - * If there was data, print out the first 8 bytes - */ - if (dlength > 0) { - memset(logbuf, 0, sizeof(logbuf)); - for (i=0; i<8 && i<dlength; ++i) { - sprintf(logbuf+i*5, "0x%02x ", - data[i]); - } - log_warning(" Data[0]-[%d]: %s", - i<dlength ? dlength-1 : i-1, - logbuf); - } - - - if (dlength > (sizeof (short))) { - senselen = (ntohs(*(short *) (data))); - - log_debug(1, " senselen = %d", senselen); - if (dlength > senselen + 2) { - log_debug(1, "recvd async event : %s", - data + 2 + senselen); - } - } - *long_lived = 1; - - /* - * Arrange for a rediscovery to occur in the near - * future. We use a timer so that we merge - * multiple events that occur in rapid succession, - * and only rediscover once for each burst of - * Async events. - */ - set_timer(async_timer, 1); - if (*active) { - log_debug(4, "discovery process received Async " - "event while active"); - } else { - log_debug(4, "discovery process received Async " - "event while idle"); - } - process_async_event_text(sendtargets, info, - async_timer); - break; - } - case ISCSI_OP_NOOP_IN:{ - struct iscsi_nopin *nop = - (struct iscsi_nopin *) pdu; - - /* - * The iSCSI spec doesn't allow Nops on - * discovery sessions, but some targets - * use them anyway. If we receive one, we - * can safely assume that the target - * supports long-lived discovery sessions - * (otherwise it wouldn't be sending nops - * to verify the connection is still - * working). - */ - *long_lived = 1; - log_debug(4,"discovery session to %s:%d received" - " Nop-in with itt %u, ttt %u, dlength %u", - config->address, config->port, - ntohl(nop->itt), ntohl(nop->ttt), - ntoh24(nop->dlength)); - - if (nop->ttt != ISCSI_RESERVED_TAG) { - /* reply to the Nop-in */ - if (!send_nop_reply(session, nop, data, - session->conn[0].active_timeout)) { - log_error( - "discovery session to %s:%d " - "failed to send Nop reply, " - "ttt %u, reconnecting", - config->address, - config->port, - ntohl(nop->ttt)); - rc = DISCOVERY_NEED_RECONNECT; - goto done; - } - } - break; - } - case ISCSI_OP_REJECT:{ - struct iscsi_reject *reject = - (struct iscsi_reject *) pdu; - int dlength = ntoh24(pdu->dlength); - - log_error("reject, dlength=%d, " - "data[0]=0x%x", - dlength, data[0]); - log_error( - "Received a reject from the target " - "with reason code = 0x%x", - reject->reason); - /* - * Just attempt to reconnect if we receive a reject - */ - rc = DISCOVERY_NEED_RECONNECT; - goto done; - break; - } - default:{ + default: log_warning( "discovery session to %s:%d received " "unexpected opcode 0x%x", config->address, config->port, pdu->opcode); rc = DISCOVERY_NEED_RECONNECT; goto done; - } } done: return(rc); @@ -1052,8 +760,7 @@ done: } int -sendtargets_discovery(struct iscsi_sendtargets_config *config, - struct string_buffer *info) +sendtargets_discovery(idbm_t *db, struct iscsi_sendtargets_config *config) { iscsi_session_t *session; struct pollfd pfd; @@ -1061,8 +768,6 @@ sendtargets_discovery(struct iscsi_sendtargets_config *config, struct iscsi_hdr *pdu = &pdu_buffer; char *data = NULL; char *end_of_data; - int long_lived = (config->continuous > 0) ? 1 : 0; - int lun_inventory_changed = 0; int active = 0; struct timeval connection_timer, async_timer; int timeout; @@ -1075,27 +780,31 @@ sendtargets_discovery(struct iscsi_sendtargets_config *config, char host[NI_MAXHOST], serv[NI_MAXSERV], default_port[NI_MAXSERV]; /* initial setup */ - log_debug(1, "starting sendtargets discovery, address %s:%d, " - "continuous %d", config->address, config->port, - config->continuous); + log_debug(1, "starting sendtargets discovery, address %s:%d, ", + config->address, config->port); memset(&pdu_buffer, 0, sizeof (pdu_buffer)); clear_timer(&connection_timer); clear_timer(&async_timer); - /* allocate data buffers for SendTargets data and discovery pipe info */ - init_string_buffer(&sendtargets, 32 * 1024); - /* allocate a new session, and initialize default values */ session = init_new_session(config); - if (session == NULL) { + if (session == NULL) return 1; + + /* allocate data buffers for SendTargets data and discovery pipe info */ + init_string_buffer(&sendtargets, + session->conn[0].max_recv_dlength); + if (!sendtargets.buffer) { + rc = 1; + goto free_session; } sprintf(default_port, "%d", config->port); /* resolve the DiscoveryAddress to an IP address */ if (resolve_address(config->address, default_port, &ss)) { log_error("cannot resolve host name %s", config->address); - return 1; + rc = 1; + goto free_sendtargets; } log_debug(4, "discovery timeouts: login %d, reopen_cnt %d, auth %d, " @@ -1106,8 +815,10 @@ sendtargets_discovery(struct iscsi_sendtargets_config *config, /* setup authentication variables for the session*/ rc = setup_authentication(session, config); - if (rc == 0) - return 1; + if (rc == 0) { + rc = 1; + goto free_sendtargets; + } set_address: /* @@ -1121,7 +832,8 @@ reconnect: if (--session->reopen_cnt < 0) { log_error("connection login retries (reopen_max) %d exceeded", config->reopen_max); - return 1; + rc = 1; + goto free_sendtargets; } redirect_reconnect: @@ -1207,7 +919,8 @@ redirect_reconnect: case LOGIN_INVALID_PDU: log_error("discovery login to %s failed, giving up", host); iscsi_io_disconnect(&session->conn[0]); - return 1; + rc = 1; + goto free_sendtargets; } /* check the login status */ @@ -1248,7 +961,8 @@ redirect_reconnect: "initiator error (%02x/%02x), non-retryable, giving up", host, status_class, status_detail); iscsi_io_disconnect(&session->conn[0]); - return 1; + rc = 1; + goto free_sendtargets; case ISCSI_STATUS_CLS_TARGET_ERR: log_error( "discovery login to %s rejected: " @@ -1271,7 +985,6 @@ redirect_reconnect: rediscover: /* reinitialize */ truncate_buffer(&sendtargets, 0); - truncate_buffer(info, 0); /* we're going to do a discovery regardless */ clear_timer(&async_timer); @@ -1283,12 +996,7 @@ redirect_reconnect: active = 1; /* set timeouts */ - if (long_lived) { - clear_timer(&connection_timer); - } else { - set_timer(&connection_timer, - session->conn[0].active_timeout + session->conn[0].ping_timeout); - } + set_timer(&connection_timer, session->conn[0].active_timeout); /* prepare to poll */ memset(&pfd, 0, sizeof (pfd)); @@ -1297,24 +1005,12 @@ redirect_reconnect: /* check timers before blocking */ if (timer_expired(&connection_timer)) { - if (long_lived || !lun_inventory_changed) { - /* long-lived, or never finished the first - * exchange (might be long-lived) - */ - clear_timer(&connection_timer); - log_debug(1, - "discovery session to %s:%d " - "reconnecting after connection timeout", - config->address, config->port); - goto reconnect; - } else { - log_warning( - "discovery session to %s:%d session " - "logout, connection timer expired", - config->address, config->port); - iscsi_logout_and_disconnect(session); - return 1; - } + log_warning("discovery session to %s:%d session " + "logout, connection timer expired", + config->address, config->port); + iscsi_logout_and_disconnect(session); + rc = 1; + goto free_sendtargets; } if (active) { @@ -1376,75 +1072,46 @@ redirect_reconnect: * process iSCSI PDU received */ rc = process_recvd_pdu( + db, pdu, config, session, &sendtargets, - info, - &lun_inventory_changed, default_port, &active, - &long_lived, &async_timer, data); if (rc == DISCOVERY_NEED_RECONNECT) goto reconnect; /* reset timers after receiving a PDU */ - if (long_lived) { - clear_timer(&connection_timer); - } else { - if (active) - set_timer - (&connection_timer, - session->conn[0]. - active_timeout); - else - /* - * 3 minutes to try - * to go long-lived - */ - set_timer(&connection_timer, - 3 * 60); - } + if (active) + set_timer(&connection_timer, + session->conn[0].active_timeout); + else + /* + * 3 minutes to try + * to go long-lived + */ + set_timer(&connection_timer, 3 * 60); } else { - if (long_lived) { - log_debug(1, - "discovery session to " - "%s:%d failed to recv a " - "PDU response, " - "reconnecting", - config->address, - config->port); - goto reconnect; - } else { - log_debug(1, - "discovery session to " - "%s:%d failed to recv a " - "PDU response, " - "terminating", - config->address, - config->port); - iscsi_io_disconnect(&session->conn[0]); - return 1; - } + log_debug(1, "discovery session to " + "%s:%d failed to recv a PDU " + "response, terminating", + config->address, + config->port); + iscsi_io_disconnect(&session->conn[0]); + rc = 1; + goto free_sendtargets; } } if (pfd.revents & POLLHUP) { - if (long_lived) { - log_warning( - "discovery session to %s:%d " - "reconnecting after hangup", - config->address, config->port); - goto reconnect; - } else { - log_warning( - "discovery session to %s:%d " - "terminating after hangup", - config->address, config->port); - iscsi_io_disconnect(&session->conn[0]); - return 1; - } + log_warning("discovery session to %s:%d " + "terminating after hangup", + config->address, config->port); + iscsi_io_disconnect(&session->conn[0]); + rc = 1; + goto free_sendtargets; } if (pfd.revents & POLLNVAL) { @@ -1468,14 +1135,20 @@ redirect_reconnect: } } else { log_error("poll error"); - return 1; + rc = 1; + goto free_sendtargets; } } log_debug(1, "discovery process to %s:%d exiting", config->address, config->port); + rc = 0; - return 0; +free_sendtargets: + free_string_buffer(&sendtargets); +free_session: + free(session); + return rc; } #ifdef SLP_ENABLE @@ -35,6 +35,7 @@ #include "idbm.h" #include "log.h" #include "util.h" +#include "iscsi_settings.h" #define IDBM_HIDE 0 /* Hide parameter when print. */ #define IDBM_SHOW 1 /* Show parameter when print. */ @@ -163,10 +164,6 @@ idbm_recinfo_discovery(discovery_rec_t *r, recinfo_t *ri) u.sendtargets.address, IDBM_SHOW, num); __recinfo_int("discovery.sendtargets.port", ri, r, u.sendtargets.port, IDBM_SHOW, num); - __recinfo_int("discovery.sendtargets.continuous", ri, r, - u.sendtargets.continuous, IDBM_SHOW, num); - __recinfo_int("discovery.sendtargets.send_async_text", ri, r, - u.sendtargets.send_async_text, IDBM_SHOW, num); __recinfo_int_o2("discovery.sendtargets.auth.authmethod", ri, r, u.sendtargets.auth.authmethod, IDBM_SHOW, "None", "CHAP", num); @@ -199,8 +196,8 @@ idbm_recinfo_discovery(discovery_rec_t *r, recinfo_t *ri) __recinfo_int("discovery.sendtargets.timeo.idle_timeout", ri, r, u.sendtargets.conn_timeo.idle_timeout, IDBM_SHOW, num); - __recinfo_int("discovery.sendtargets.timeo.ping_timeout", ri, r, - u.sendtargets.conn_timeo.ping_timeout, + __recinfo_int("discovery.sendtargets.iscsi.MaxRecvDataSegmentLength", + ri, r, u.sendtargets.iscsi.MaxRecvDataSegmentLength, IDBM_SHOW, num); } } @@ -402,17 +399,16 @@ idbm_discovery_setup_defaults(discovery_rec_t *rec, discovery_type_e type) rec->startup = ISCSI_STARTUP_MANUAL; rec->type = type; if (type == DISCOVERY_TYPE_SENDTARGETS) { - rec->u.sendtargets.continuous = 0; - rec->u.sendtargets.send_async_text = 0; rec->u.sendtargets.reopen_max = 5; rec->u.sendtargets.auth.authmethod = 0; rec->u.sendtargets.auth.password_length = 0; rec->u.sendtargets.auth.password_in_length = 0; rec->u.sendtargets.conn_timeo.login_timeout=15; rec->u.sendtargets.conn_timeo.auth_timeout = 45; - rec->u.sendtargets.conn_timeo.active_timeout=5; - rec->u.sendtargets.conn_timeo.idle_timeout = 60; - rec->u.sendtargets.conn_timeo.ping_timeout = 5; + rec->u.sendtargets.conn_timeo.active_timeout=30; + rec->u.sendtargets.conn_timeo.idle_timeout = 60; + rec->u.sendtargets.iscsi.MaxRecvDataSegmentLength = + DEF_INI_DISC_MAX_RECV_SEG_LEN; } else if (type == DISCOVERY_TYPE_SLP) { rec->u.slp.interfaces = NULL; rec->u.slp.scopes = NULL; @@ -1143,139 +1139,29 @@ idbm_new_node(idbm_t *db, node_rec_t *newrec) return idbm_node_write(db, newrec); } -discovery_rec_t* -idbm_new_discovery(idbm_t *db, char *ip, int port, - discovery_type_e type, char *info) +/* Do we even need to store this? */ +void idbm_new_discovery(idbm_t *db, char *ip, int port, discovery_type_e type) { - char *ptr, *newinfo; discovery_rec_t *drec; - node_rec_t *nrec; + + if (type != DISCOVERY_TYPE_SENDTARGETS) + return; /* allocate new discovery record and initialize with defaults */ drec = malloc(sizeof(discovery_rec_t)); if (!drec) { log_error("out of memory on discovery record allocation"); - return NULL; - } - drec->type = type; - - if (drec->type == DISCOVERY_TYPE_SENDTARGETS) { - memcpy(drec, &db->drec_st, sizeof(discovery_rec_t)); - } else if (drec->type == DISCOVERY_TYPE_SLP) { - memcpy(drec, &db->drec_slp, sizeof(discovery_rec_t)); - } else if (drec->type == DISCOVERY_TYPE_ISNS) { - memcpy(drec, &db->drec_isns, sizeof(discovery_rec_t)); - } - - /* allocate new node record and initialize with defaults */ - nrec = malloc(sizeof(node_rec_t)); - if (!nrec) { - log_error("out of memory on node record allocation"); - free(drec); - return NULL; - } - memcpy(nrec, &db->nrec, sizeof(node_rec_t)); - - /* update discovery record */ - if (drec->type == DISCOVERY_TYPE_SENDTARGETS) { - strncpy(drec->u.sendtargets.address, ip, NI_MAXHOST); - drec->u.sendtargets.port = port; - } else if (drec->type == DISCOVERY_TYPE_SLP) { - log_error("not implemented discovery type"); - } else if (drec->type == DISCOVERY_TYPE_ISNS) { - log_error("not implemented discovery type"); - } - - /* - * Discovery info example: - * - * DTN=iqn.2001-04.com.example:storage.disk2.sys1.xyz - * TT=1 - * TP=3260 - * TA=10.16.16.227 - * ; - * DTN=iqn.2001-04.com.example:storage.disk2.sys2.xyz - * TT=1 - * TP=3260 - * TA=10.16.16.228 - * ; - * ! - */ - ptr = newinfo = strdup(info); - log_debug(6, "parsing discovery info:\n---\n%s\n---", ptr); - - /* Maybe there are no targets */ - if (!strcmp(ptr, "!\n")) { - log_debug(3, "No targets were found\n"); - free(drec); - drec = NULL; - goto out; + return; } - while (*ptr) { - char *dp; - - /* convert line to zero-string */ - if ((dp = strchr(ptr, '\n'))) { - *dp = '\0'; - } - - /* separate name and value */ - if ((dp = strchr(ptr, '='))) { - *dp = '\0'; dp++; - if (!strcmp(ptr, "DTN") || !strcmp(ptr, "TN")) { - strncpy(nrec->name, dp, TARGET_NAME_MAXLEN); - } else if (!strcmp(ptr, "TT")) { - nrec->tpgt = strtoul(dp, NULL, 10); - } else if (!strcmp(ptr, "TP")) { - nrec->conn[0].port = strtoul(dp, NULL, 10); - } else if (!strcmp(ptr, "TA")) { - strncpy(nrec->conn[0].address, dp, NI_MAXHOST); - if (idbm_add_discovery(db, drec)) { - log_error("can not update discovery " - "record."); - free(drec); - drec = NULL; - goto out; - } - - if (idbm_add_nodes(db, nrec)) { - log_error("can not update node " - "record."); - free(drec); - drec = NULL; - goto out; - } - } else { - log_error("can not parse discovery info value. " - "Bug?"); - free(drec); - drec = NULL; - goto out; - } - log_debug(7, "discovery info key %s value %s", ptr, dp); - ptr = dp + strlen(dp) + 1; - } else if (*ptr == ';' && *(ptr+1) == '\0' && *(ptr+2) == '!') { - /* end of discovery info */ - ptr += 3; - } else if (*ptr == ';' && *(ptr+1) == '\0') { - /* end of entry */ - ptr += 2; - } else if (*ptr == '\0') { - ptr++; - } else { - log_error("can not parse discovery info key '..%s' " - "Bug?", ptr); - free(drec); - drec = NULL; - goto out; - } - } + memcpy(drec, &db->drec_st, sizeof(discovery_rec_t)); + strncpy(drec->u.sendtargets.address, ip, NI_MAXHOST); + drec->u.sendtargets.port = port; + drec->type = DISCOVERY_TYPE_SENDTARGETS; -out: - free(nrec); - free(newinfo); - return drec; + if (idbm_add_discovery(db, drec)) + log_error("can not update discovery record."); + free(drec); } int @@ -91,8 +91,8 @@ extern int idbm_delete_node(void *data, node_rec_t *rec); extern int idbm_new_node(idbm_t *db, node_rec_t *newrec); extern int idbm_add_nodes(idbm_t *db, node_rec_t *newrec); extern int idbm_add_discovery(idbm_t *db, discovery_rec_t *newrec); -extern discovery_rec_t* idbm_new_discovery(idbm_t *db, char *ip, int port, - discovery_type_e type, char *info); +extern void idbm_new_discovery(idbm_t *db, char *ip, int port, + discovery_type_e type); extern void idbm_sendtargets_defaults(idbm_t *db, struct iscsi_sendtargets_config *cfg); extern void idbm_slp_defaults(idbm_t *db, struct iscsi_slp_config *cfg); diff --git a/usr/iscsi_settings.h b/usr/iscsi_settings.h index d47e438..c3260a5 100644 --- a/usr/iscsi_settings.h +++ b/usr/iscsi_settings.h @@ -13,3 +13,4 @@ #define DEF_INI_FIRST_BURST_LEN 262144 #define DEF_INI_MAX_BURST_LEN 16776192 #define DEF_INI_MAX_RECV_SEG_LEN 131072 +#define DEF_INI_DISC_MAX_RECV_SEG_LEN 32768 diff --git a/usr/iscsiadm.c b/usr/iscsiadm.c index 897934f..58da7d4 100644 --- a/usr/iscsiadm.c +++ b/usr/iscsiadm.c @@ -1034,19 +1034,13 @@ static int do_sendtargets(idbm_t *db, struct iscsi_sendtargets_config *cfg) { int rc; - struct string_buffer info; - init_string_buffer(&info, 8 * 1024); - rc = sendtargets_discovery(cfg, &info); + rc = sendtargets_discovery(db, cfg); if (!rc) { - discovery_rec_t *drec; - if ((drec = idbm_new_discovery(db, cfg->address, cfg->port, - DISCOVERY_TYPE_SENDTARGETS, info.buffer))) { - idbm_for_each_node(db, NULL, print_node); - free(drec); - } + idbm_new_discovery(db, cfg->address, cfg->port, + DISCOVERY_TYPE_SENDTARGETS); + idbm_for_each_node(db, NULL, print_node); } - truncate_buffer(&info, 0); return rc; } diff --git a/usr/iscsiadm.h b/usr/iscsiadm.h index cf61f01..c545092 100644 --- a/usr/iscsiadm.h +++ b/usr/iscsiadm.h @@ -27,13 +27,8 @@ extern char initiator_name[]; extern char initiator_alias[]; /* discovery.c */ -extern int sendtargets_discovery(struct iscsi_sendtargets_config *config, - struct string_buffer *info); -extern int slp_discovery(struct iscsi_slp_config *config); -extern int add_target_record(struct string_buffer *info, char *name, char *end, - int lun_inventory_changed, char *default_address, - char *default_port); -extern int add_portal(struct string_buffer *info, char *address, char *port, - char *tag); +struct idbm; +extern int sendtargets_discovery(struct idbm *db, + struct iscsi_sendtargets_config *config); #endif /* ISCSIADM_H */ diff --git a/usr/strings.c b/usr/strings.c index 4edc4c1..e885685 100644 --- a/usr/strings.c +++ b/usr/strings.c @@ -68,7 +68,6 @@ free_string_buffer(struct string_buffer *s) } s->allocated_length = 0; s->data_length = 0; - free(s); } } |