📄 text_param.c
字号:
* at most request retransmission for the last read * data sequence. For this reason, if * ErrorRecoveryLevel is not 0 and DataSequenceInOrder is * set to Yes then MaxOutstandingR2T MUST be set to 1." */ if ((p = find_flag_parameter(DATASEQUENCEINORDER_FLAG, p_param_tbl)) != NULL) { if (!strcmp(p->str_value, key_table->yes) && (p2 = find_flag_parameter(ERRORRECOVERYLEVEL_FLAG, p_param_tbl)) != NULL) { /* have DataSequenceInOrder=Yes */ if (p2->int_value > 0 && (p = find_flag_parameter (MAXOUTSTANDINGR2T_FLAG, p_param_tbl)) != NULL) { /* have ErrorRecoveryLevel>0 */ if (p->int_value != 1) { /* do not have * MaxOutstandingR2T = 1, * change it to 1 */ if (TRACE_TEST(TRACE_ISCSI)) { TRACE_WARNING ("%s=%u reset to 1\n", p->parameter_name, p->int_value); } p->int_value = 1; } } } } } TRACE(TRACE_ENTER_LEAVE, "Leave check_integrity_rules\n");}/* * This function receives 'length' bytes into buffer from the socket */intiscsi_recv_msg(struct socket *sock, int length, char *buffer, int flags){ struct msghdr msg; size_t size; int received, retval; struct iovec iov; mm_segment_t oldfs; TRACE(TRACE_ENTER_LEAVE, "Enter iscsi_recv_msg, length %d bytes\n", length); /* the following code will receive PDU's from the other side */ size = length; for (received = 0; received < length;) { /* most fields remain 0/NULL */ memset(&msg, 0, sizeof (struct msghdr)); msg.msg_iovlen = 1; msg.msg_iov = &iov; iov.iov_len = size; iov.iov_base = buffer + received; oldfs = get_fs(); set_fs(get_ds()); retval = sock_recvmsg(sock, &msg, size, MSG_WAITALL); set_fs(oldfs); if (retval <= 0) { if (retval == 0) { TRACE_ERROR("remote peer disconnected\n"); } else { TRACE_ERROR("sock_recvmsg error %d\n", retval); } retval = -1; goto out; } received += retval; size = length - received; TRACE(TRACE_DEBUG, "Received: %d, total_rx: %d, data: %d\n", retval, received, length); } TRACE_BUFFER(TRACE_BUF, buffer, length, "Got buffer, length: %d\n", length); retval = 0; out: TRACE(TRACE_ENTER_LEAVE, "Leave iscsi_recv_msg, retval %d\n", retval); return retval;}/* * returns 1 if needs a break from the loop * else returns a 0 */int __attribute__ ((no_instrument_function))check_out_length(int out_length, int resp_len){ TRACE(TRACE_ENTER_LEAVE, "Enter check_out_length cur_len: %d, add_len: %d\n", out_length, resp_len); /* Increment the out_length */ out_length += resp_len + 2; TRACE(TRACE_ENTER_LEAVE, "Leave check_out_length\n"); if (out_length > MAX_TEXT_LEN) return 1; else return 0;}/* * sends the PDUs to the other end. */intiscsi_send_msg(struct socket *sock, struct generic_pdu *outputpdu, int flags){ struct msghdr msg; struct iovec *iov, actual_iov[3]; mm_segment_t oldfs; struct iscsi_targ_login_rsp *targ_login_rsp; int total_tx, tx_loop; int data_length, count, hdr_length, send_length; TRACE(TRACE_ENTER_LEAVE, "Enter iscsi_send_msg\n"); switch (outputpdu->opcode & (ISCSI_OPCODE)) { case ISCSI_INIT_LOGIN_CMND: /* Send the login Command */ if (TRACE_TEST(TRACE_ISCSI_FULL)) print_init_login_cmnd((struct iscsi_init_login_cmnd *) outputpdu); break; case ISCSI_TARG_LOGIN_RSP: /* Send the Login Response */ targ_login_rsp = (struct iscsi_targ_login_rsp *) outputpdu; TRACE(TRACE_ISCSI, "Send Login Response, CSG %d, NSG %d, T %d\n", (outputpdu->flags & CSG) >> CSG_SHIFT, outputpdu->flags & NSG, (outputpdu->flags & T_BIT) >> 7); if (TRACE_TEST(TRACE_ISCSI_FULL)) print_targ_login_rsp(targ_login_rsp); break; default: TRACE_ERROR("sending bad opcode 0x%02X during Login phase\n", outputpdu->opcode & ISCSI_OPCODE); return -1; } /* switch */ /* all pdus store the DSL in the same place */ outputpdu->length = cpu_to_be32(outputpdu->text_length); /* set up the i/o message and vectors */ memset(&msg, 0, sizeof (struct msghdr)); msg.msg_iov = iov = actual_iov; msg.msg_flags = MSG_NOSIGNAL; count = 1; hdr_length = ISCSI_HDR_LEN; /* NO packets sent or received during login will have digests of any kind */ iov->iov_base = (char *) outputpdu; iov->iov_len = send_length = hdr_length; if ((data_length = outputpdu->text_length) > 0) { /* there is data attached to this pdu */ /* Add padding to end of any attached data */ data_length += (-data_length) & 3; if (data_length > outputpdu->text_length) { TRACE(TRACE_DEBUG, "Length with padding = %d, without = %d\n", data_length, outputpdu->text_length); memset(outputpdu->text + outputpdu->text_length, 0, data_length - outputpdu->text_length); } count++; iov++; iov->iov_base = outputpdu->text; iov->iov_len = data_length; send_length += data_length; } /* i/o message and vector now set up */ msg.msg_iovlen = count; TRACE(TRACE_DEBUG, "Sending %d bytes total, %d actual_iovs\n", send_length, count); total_tx = 0; do { TRACE(TRACE_NET, "Sending %d bytes, %d actual_iovs on sock %p\n", send_length, count, sock); oldfs = get_fs(); set_fs(get_ds()); tx_loop = sock_sendmsg(sock, &msg, send_length); set_fs(oldfs); if (tx_loop <= 0) { TRACE_ERROR("sock_sendmsg error %d, total_tx %d\n", tx_loop, total_tx); return tx_loop; } total_tx += tx_loop; TRACE(TRACE_NET, "tx_loop=%d, total_tx=%d, send_length=%d\n", tx_loop, total_tx, send_length); if (total_tx != send_length) { TRACE_ERROR("sock_sendmsg total_tx %d, expected %d\n", total_tx, send_length); } } while (total_tx < send_length); TRACE_BUFFER(TRACE_BUF, (char *) outputpdu, hdr_length, "Sent header, length: %d\n", hdr_length); if (count > 1) { TRACE_BUFFER(TRACE_BUF, (char *) outputpdu->text, data_length, "Sent data, length: %d\n", data_length); } TRACE(TRACE_ENTER_LEAVE, "Leave iscsi_send_msg\n"); return 0;}/* * checks whether the receiving side has received all the responses * for the negotiations it started in the last packet. * Return: * -1 if error, didn't receive the response * 0 if success */intcheck_neg_responses(struct parameter_type p_param_tbl[MAX_CONFIG_PARAMS], __u32 print_error){ int i = 0; int retval = 0; struct parameter_type *p = NULL; TRACE(TRACE_ENTER_LEAVE, "Enter check_neg_responses\n"); for (i = 0; i < MAX_CONFIG_PARAMS; i++) { p = &p_param_tbl[i]; if (IS_KEY_TO_BE_NEGOTIATED(p->neg_info) && IS_KEY_SENT_TO_OTHER_SIDE(p->neg_info) && !IS_KEY_GOT_FROM_OTHER_SIDE(p->neg_info) && !IS_KEY_REPLY_OPTIONAL(p->neg_info)) { /* parameter was sent, no reply was received * and reply not optional */ if (!IS_INFORMATIONAL_PARAM(p->type) && !(p-> special_key_flag & MAXRECVDATASEGMENTLENGTH_FLAG)) { /* informational parameters expect no * response and neither do * MaxRecvPDULength/MaxRecvDataSegmentLength */ TRACE(TRACE_DEBUG, "response not yet received for parameter %s\n", p->parameter_name); if (print_error) { TRACE_ERROR ("response expected for parameter %s\n", p->parameter_name); /* set got bit so we won't get this message again */ p->neg_info |= KEY_GOT_FROM_OTHER_SIDE; } retval = -1; } } } TRACE(TRACE_ENTER_LEAVE, "Leave check_neg_responses, retval = %d\n", retval); return retval;}/* * checks whether the receiving side supports the parameter values * offered by the sender. * (because in this case this function is not called) * Return: * If supported returns the pointer to the (terminated) value in * the supplied_values_from_sender list, else returns NULL */static char * __attribute__ ((no_instrument_function))check_for_support(struct parameter_type *p, char *supplied_values_from_sender){ char *dummy1 = NULL; char *dummy2 = NULL; char *sender_value = NULL; char *receiver_value = p->value_list; TRACE(TRACE_ENTER_LEAVE, "Enter check_for_support, sender_value %s\n", supplied_values_from_sender); /* No support */ if (receiver_value == NULL) goto out; TRACE(TRACE_DEBUG, "%s's value_list: %s\n", p->parameter_name, receiver_value); /* Check whether the parameter's str_value agrees with * * one of the supplied values */ do { /* Get the receiver_value from the parameter's value_list */ dummy1 = strchr(receiver_value, ','); if (dummy1) { *dummy1 = '\0'; } TRACE(TRACE_DEBUG, "receiver_value: %s\n", receiver_value); /* Initialise */ sender_value = supplied_values_from_sender; do { /* extract just a single value */ dummy2 = strchr(sender_value, ','); if (dummy2) { *dummy2 = '\0'; } TRACE(TRACE_DEBUG, "sender_value: %s\n", sender_value); if (!strcmp(receiver_value, sender_value)) { /* Found a match, return pointer to it in sender_value */ if (dummy1) *dummy1 = ','; /* restore the * comma before * leaving */ goto out; } /* goto the next value supplied by sender */ if (dummy2) { *dummy2++ = ','; /* restore comma */ TRACE(TRACE_DEBUG, "dummy2++sender_value: %s\n", sender_value); } else { TRACE(TRACE_DEBUG, "dummy2 null sender_value: %s\n", sender_value); } sender_value = dummy2; } while (sender_value); /* restore the comma and goto the next value in receiver's table list */ if (dummy1) { *dummy1++ = ','; } receiver_value = dummy1; } while (receiver_value); out: if (sender_value) { TRACE(TRACE_ENTER_LEAVE, "Leave check_for_support, return value %s\n", sender_value); } else { TRACE(TRACE_ENTER_LEAVE, "Leave check_for_support, return value NULL\n"); } return sender_value;}static void __attribute__ ((no_instrument_function))update_key_value(struct parameter_type *p, int int_value, char *value){ if (IS_NUMBER(p->type) || IS_NUMBER_RANGE(p->type)) { if (p->int_value != int_value) { /* have a new numeric value for this key */ p->int_value = int_value; TRACE(TRACE_ISCSI, "Update key %s, new value %d\n", p->parameter_name, p->int_value); } } else if (p->str_value && !strcmp(value, p->str_value)) { /* already have this string value in place */ } else { /* have a new string value for this key */ strreplace(&p->str_value, value); TRACE(TRACE_ISCSI, "Update key %s, new value %s\n", p->parameter_name, p->str_value); }}static void __attribute__ ((no_instrument_function))handle_boolean_param(struct parameter_type *p, char **value);static int __attribute__ ((no_instrument_function))handle_params_noexch(struct parameter_type *p, struct parameter_type p_param_tbl [MAX_CONFIG_PARAMS], __u32 flags, int int_value, char *value, char *string, int *resp_len, int *FBLength , struct parameter_type **FBp, int *MBLength, struct parameter_type **MBp);static int __attribute__ ((no_instrument_function))handle_params_resp(struct parameter_type *p, char *value, int int_value, int *out_length);/* * scan through the input and process keys * p_param_tbl - pointer to the table of parameters * sock - pointer to the socket structure * process_these_types - types of parameters to be processed. * flags_to_be_set - Which flags to set * role - who is calling (INITIATOR/TARGET) * Return: returns the length of the string added to the output string */intscan_input_and_process(struct socket *sock, struct parameter_type p_param_tbl[MAX_CONFIG_PARAMS], int process_these_types, int flags_to_be_set, int role, int *max_send_length, __u32 when_called, struct generic_pdu *inputpdu, struct generic_pdu *outputpdu, __u32 flags, __u64 * login_flags, struct unknown_key **unknown_key_list){ struct parameter_type *p = NULL; int resp_len, n; char *dummy_string; char *input_str, *this_key; char *input_string; int out_length = 0; char *output_string; int key_value_len; char *value; int int_value; char *last_input; int FBLength = -1, MBLength = -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -