📄 iscsi-discovery.c
字号:
* current target record */ while ((text < nul) && (*text != '\0')) text++; } if (record) { if (final) { /* if this is the last PDU of the text sequence, * it also ends a target record */ debugmsg(7, "processing final sendtargets record %p, " "line %s", record, record); if (add_target_record (info, record + 11, text, lun_inventory_changed, default_address, default_port, fd)) { num_targets++; record = NULL; truncate_buffer(sendtargets, 0); } else { logmsg(AS_ERROR, "failed to add target record"); truncate_buffer(sendtargets, 0); truncate_buffer(info, valid_info); goto done; } } else { /* remove the parts of the sendtargets buffer we've * processed, and move the parts we haven't to the * beginning of the buffer. */ debugmsg(7, "processed %d bytes of sendtargets data, " "%d remaining", record - buffer_data(sendtargets), buffer_data(sendtargets) + data_length(sendtargets) - record); remove_initial(sendtargets, record - buffer_data(sendtargets)); } } done: /* send all of the discovered targets to the parent daemon */ if (append_string(info, final ? "!\n" : ".\n")) { write_buffer(info, fd); truncate_buffer(info, 0); if (final) { record_begin = 0; } debugmsg(4, "sent %d targets to parent daemon", num_targets); return 1; } else { logmsg(AS_ERROR, "couldn't send %d targets to parent", num_targets); truncate_buffer(info, 0); return 0; } return 1;}static intadd_async_record(struct string_buffer *info, char *record, int targetoffline, int fd){ int length = strlen(record); size_t original = data_length(info); debugmsg(7, " adding async record for %s", record); if (targetoffline) { /* We have received targetoffline event */ if (length > TARGET_NAME_MAXLEN) { logmsg(AS_ERROR, "Targetname %s too long, ignoring", record); return 0; } } if (!append_sprintf (info, targetoffline ? "ATF=%s\n" : "APF=%s\n", record)) { logmsg(AS_ERROR, "couldn't report the record\n"); truncate_buffer(info, original); return 0; } else if (!append_string(info, ";\n")) { logmsg(AS_ERROR, "failed to terminate target record, ignoring target %s", record); truncate_buffer(info, original); } return 1;}static voidclear_timer(struct timeval *timer){ memset(timer, 0, sizeof (*timer));}static intprocess_async_event_text(struct string_buffer *sendtargets, struct string_buffer *info, struct timeval *timer, int fd){ 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, fd)) { logmsg(AS_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, fd)) { logmsg(AS_ERROR, "failed to add async record"); return 0; } clear_timer(timer); } else { debugmsg(1, "sendtargets for the other events\n"); return 1; } if (append_string(info, "!\n")) { write_buffer(info, fd); truncate_buffer(info, 0); debugmsg(4, "sent async event record to parent daemon\n"); return 1; } else { logmsg(AS_ERROR, "couldn't send async event record \n"); return 0; }}/* set timer to now + seconds */static voidset_timer(struct timeval *timer, int seconds){ if (timer) { memset(timer, 0, sizeof (*timer)); gettimeofday(timer, NULL); timer->tv_sec += seconds; }}static inttimer_expired(struct timeval *timer){ struct timeval now; /* no timer, can't have expired */ if ((timer == NULL) || ((timer->tv_sec == 0) && (timer->tv_usec == 0))) return 0; memset(&now, 0, sizeof (now)); gettimeofday(&now, NULL); if (now.tv_sec > timer->tv_sec) return 1; if ((now.tv_sec == timer->tv_sec) && (now.tv_usec >= timer->tv_usec)) return 1; return 0;}static intmsecs_until(struct timeval *timer){ struct timeval now; int msecs; long partial; /* no timer, can't have expired, infinite time til it expires */ if ((timer == NULL) || ((timer->tv_sec == 0) && (timer->tv_usec == 0))) return -1; memset(&now, 0, sizeof (now)); gettimeofday(&now, NULL); /* already expired? */ if (now.tv_sec > timer->tv_sec) return 0; if ((now.tv_sec == timer->tv_sec) && (now.tv_usec >= timer->tv_usec)) return 0; /* not expired yet, do the math */ partial = timer->tv_usec - now.tv_usec; if (partial < 0) { partial += 1000 * 1000; msecs = (partial + 500) / 1000; msecs += (timer->tv_sec - now.tv_sec - 1) * 1000; } else { msecs = (partial + 500) / 1000; msecs += (timer->tv_sec - now.tv_sec) * 1000; } return msecs;}static intsoonest_msecs(struct timeval *t1, struct timeval *t2, struct timeval *t3){ int m1 = msecs_until(t1); int m2 = msecs_until(t2); int m3 = msecs_until(t3); /* infinity is -1, handle it specically */ if ((m1 == -1) && (m2 == -1)) return m3; if ((m1 == -1) && (m3 == -1)) return m2; if ((m2 == -1) && (m3 == -1)) return m1; if (m1 == -1) return (m2 < m3) ? m2 : m3; if (m2 == -1) return (m1 < m3) ? m1 : m3; if (m3 == -1) return (m1 < m2) ? m1 : m2; if (m1 < m2) return (m1 < m3) ? m1 : m3; else return (m2 < m3) ? m2 : m3;}static intalloc_auth_buffers(struct iscsi_session *session){ session->auth_client_block = (struct iscsi_acl *)malloc(sizeof(*session->auth_client_block)); if (!session->auth_client_block) goto error; session->auth_recv_string_block = (struct auth_str_block *) malloc(sizeof(*session->auth_recv_string_block)); if (!session->auth_recv_string_block) goto error; session->auth_send_string_block = (struct auth_str_block *) malloc(sizeof(*session->auth_send_string_block)); if (!session->auth_send_string_block) goto error; session->auth_recv_binary_block = (struct auth_large_binary *) malloc(sizeof(*session->auth_recv_binary_block)); if (!session->auth_recv_binary_block) goto error; session->auth_send_binary_block = (struct auth_large_binary *) malloc(sizeof(*session->auth_send_binary_block)); if (!session->auth_send_binary_block) goto error; return 0; error: free(session->auth_client_block); free(session->auth_recv_string_block); free(session->auth_send_string_block); free(session->auth_recv_binary_block); iscsi_err("Session couldn't allocate authentication stuctures\n"); return -ENOMEM;}static void free_session(struct iscsi_session **session){ free((*session)->auth_client_block); free((*session)->auth_recv_string_block); free((*session)->auth_send_string_block); free((*session)->auth_recv_binary_block); free((*session)->auth_send_binary_block); free(*session); *session = NULL;}static struct iscsi_session *init_new_session(struct iscsi_sendtargets_config *config, struct iscsi_discovery_process *process){ struct iscsi_session *session; session = calloc(1, sizeof (*session)); if (session == NULL) { logmsg(AS_ERROR, "discovery process to %s:%d failed to " "allocate a session\n", config->address, config->port); goto done; } if (alloc_auth_buffers(session)) { free(session); session = NULL; goto done; } /* initialize the session */ session->socket_fd = -1; session->type = ISCSI_SESSION_TYPE_DISCOVERY; session->login_timeout = config->connection_timeout_options.login_timeout; session->auth_timeout = config->connection_timeout_options.auth_timeout; session->active_timeout = config->connection_timeout_options.active_timeout; session->idle_timeout = config->connection_timeout_options.idle_timeout; session->ping_timeout = config->connection_timeout_options.ping_timeout; session->send_async_text = config->continuous ? config->send_async_text : -1; /* OUI and uniqifying number */ session->isid[0] = DRIVER_ISID_0; session->isid[1] = DRIVER_ISID_1; session->isid[2] = DRIVER_ISID_2; session->isid[3] = (process->order >> 16) & 0xFF; session->isid[4] = (process->order >> 8) & 0xFF; session->isid[5] = (process->order >> 0) & 0xFF; session->initiator_name = daemon_config.initiator_name; session->initiator_alias = daemon_config.initiator_alias; session->header_digest = ISCSI_DIGEST_NONE; session->data_digest = ISCSI_DIGEST_NONE; session->max_recv_data_segment_len = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH; session->max_xmit_data_segment_len = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH; session->portal_group_tag = PORTAL_GROUP_TAG_UNKNOWN; debugmsg(4, "sendtargets discovery process %p to %s:%d using " "isid 0x%02x%02x%02x%02x%02x%02x", process, config->address, config->port, session->isid[0], session->isid[1], session->isid[2], session->isid[3], session->isid[4], session->isid[5]); done: return(session);}static intsetup_authentication(struct iscsi_session *session, struct iscsi_sendtargets_config *config){ int rc; rc = 1; /* if we have any incoming credentials, we insist on authenticating * the target or not logging in at all */ if (config->auth_options.username_in[0] || config->auth_options.password_length_in) { session->bidirectional_auth = 1; /* sanity check the config */ if ((config->auth_options.username[0] == '\0') || (config->auth_options.password_length == 0)) { logmsg(AS_ERROR, "discovery process to %s:%d has incoming " "authentication credentials but has no outgoing " "credentials configured\n", config->address, config->port); logmsg(AS_ERROR, "discovery process to %s:%d exiting, bad " "configuration\n", config->address, config->port); rc = 0; goto done; } } else { /* no or 1-way authentication */ session->bidirectional_auth = 0; } /* copy in whatever credentials we have */ strncpy(session->username, config->auth_options.username, sizeof (session->username)); session->username[sizeof (session->username) - 1] = '\0'; if ((session->password_length = config->auth_options.password_length)) memcpy(session->password, config->auth_options.password, session->password_length); strncpy(session->username_in, config->auth_options.username_in, sizeof (session->username_in)); session->username_in[sizeof (session->username_in) - 1] = '\0'; if ((session->password_length_in = config->auth_options.password_length_in)) memcpy(session->password_in, config->auth_options.password_in, session->password_length_in); done: return(rc);} static intprocess_recvd_pdu(struct iscsi_hdr *pdu, struct iscsi_sendtargets_config *config, struct iscsi_session *session, struct string_buffer *sendtargets, struct string_buffer *info, int *lun_inventory_changed, char *default_port, struct iscsi_discovery_process *process, int *active, int *long_lived, struct timeval *async_timer, char *data){ int rc=0; switch (pdu->opcode) { case ISCSI_OP_TEXT_RSP:{ struct iscsi_txt_rsp_hdr *text_response = (struct iscsi_txt_rsp_hdr *) pdu; int dlength = ntoh24(pdu->dlength); int final = (text_response->flags & ISCSI_FLAG_FINAL)|| (text_response-> ttt == ISCSI_RSVD_TASK_TAG); debugmsg(4, "discovery session to %s:%d received text" " response, %d data bytes, ttt 0x%x, " "final 0x%x", config->address, config->port, dlength, ntohl(text_response->ttt), text_response->flags & ISCSI_FLAG_FINAL); /* mark how much more data in the sendtargets * buffer is now valid */ 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->pipe_fd); if (final) { /* SendTargets exchange is now complete */ *active = 0; *lun_inventory_changed = 1; /* from now on, after any reconnect, * assume LUNs may have changed */ } else { /* ask for more targets */ if (!iterate_targets(session, text_response->ttt)) { rc = DISCOVERY_NEED_RECONNECT; goto done; } } break; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -