📄 text_param.c
字号:
struct parameter_type *FBp = NULL, *MBp = NULL; TRACE(TRACE_ENTER_LEAVE, "Enter scan_input_and_process\n"); ALLOCATE_MAX_TEXT_LEN(dummy_string); ALLOCATE_MAX_TEXT_LEN(input_str); output_string = outputpdu->text + outputpdu->text_length; /* Copy the input text to a local buffer */ memcpy(input_str, inputpdu->text, inputpdu->text_length); input_string = input_str; /* point at first char */ last_input = input_str + inputpdu->text_length; /* point beyond last char */ *last_input = '\0'; /* ensure '\0' at end of last */ while (input_string < last_input) { key_value_len = strlen(input_string); TRACE(TRACE_DEBUG, "key_value_len = %d\n", key_value_len); TRACE(TRACE_DEBUG, "FBLength %x MBLength %x\n", FBLength,MBLength); /* assume no reply will be sent */ resp_len = 0; value = NULL; int_value = -1; if ((p = check_correctness(input_string, &value, p_param_tbl, role, when_called, flags, &int_value, unknown_key_list)) == NULL) { /* We don't understand the request. */ if (value == NULL) { /* Error is fatal */ out_length = -1; goto out; } if (!((process_these_types & SECURITY_PARAM)) || (!is_securitykey(input_string))) { resp_len = sprintf(dummy_string, "%s=%s", input_string, value); } } else if (IS_KEY_BAD(p->neg_info)) { out_length = -1; goto out; } else if (!IS_KEY_IRRELEVANT(p->neg_info)) { /* p is the pointer to the table entry for the * received parameter and value points to the * string following the "=" in the input */ TRACE(TRACE_DEBUG, "Process input param: %s, value: %s\n", p->parameter_name, value); /* check if this is a Full Feature Only key */ if (IS_FULL_FEATURE_ONLY(p->type)) { /* protocol error */ TRACE_ERROR ("%p only valid in full feature phase\n", p->parameter_name); out_length = -1; goto out; } if (p->special_key_flag & flags_to_be_set) { /* caller wants to know that this key * was processed */ *login_flags |= p->special_key_flag; if (p->special_key_flag & SESSIONTYPE_FLAG) { /* set the DISCOVERY_FLAG when * get SessionType=Discovery */ if (!strcmp (value, key_table->discovery)) { *login_flags |= DISCOVERY_FLAG; } } } if ((p->type & process_these_types)) { /* handle key enquiry by replying with our current value */ if (!strcmp(value, "?")) { /* inquiry no longer accepted in draft 11 and after */ TRACE_ERROR ("inquiry no longer accepted " "param: %s, value: %s\n", p->parameter_name, value); resp_len = sprintf(dummy_string, "%s=%s", p->parameter_name, key_table->reject); /* do not consider this param as "gotten from other side" */ p = NULL; } else if (p->str_value && !strcmp(p->str_value, "?")) { /* we sent an inquiry and this is * the response * Note this should never happen * for draft 11 and after */ printk ("iscsi response to inquiry: %s=%s\n", p->parameter_name, value); } else { /* neither an inquiry or a reply to * an inquiry . * First convert boolean to yes or * no result */ if (IS_BOOLEAN(p->type)) { handle_boolean_param(p, &value); } if (p->special_key_flag & MAXRECVDATASEGMENTLENGTH_FLAG) { /* this is * MaxRecvDataSegmentLength * that other side wants to * receive, i.e., the max * size PDU we should send. * No reply is necessary for * this key. */ if (int_value < 512 || int_value > 16777215) { if (TRACE_TEST (TRACE_ISCSI)) { TRACE_WARNING ("%s %d out of " "bounds " "[512..16777215]\n", p->parameter_name, int_value); } } else { /* value is within * bounds, pass it back * to caller after * forcing it to be a * multiple of 512 */ int_value /= 512; *max_send_length = 512 * int_value; } } else if (!IS_KEY_SENT_TO_OTHER_SIDE (p->neg_info)) { handle_params_noexch(p, p_param_tbl, flags, int_value, value, dummy_string, &resp_len, &FBLength , &FBp, &MBLength, &MBp); } else { if (handle_params_resp(p, value, int_value, &out_length) < 0 ){ TRACE_ERROR ("handle_params_resp !\n"); goto out; } } } } else { if (IS_SECURITY_PARAM(p->type)) { TRACE_ERROR ("not in security phase when " " received input " "param: %s, value: %s\n", p->parameter_name, value); out_length = -1; goto out; } else if (IS_OPERATIONAL_PARAM(p->type)) { TRACE_ERROR ("not in operational phase when " " received input " "param: %s, value: %s\n", p->parameter_name, value); out_length = -1; goto out; } else if (IS_INFORMATIONAL_PARAM(p->type)) { TRACE_ERROR ("not processing informational " " parameters when " "recv input param: %s,value: %s\n", p->parameter_name, value); out_length = -1; goto out; } else { TRACE_ERROR ("recv unclassied input param: %s, " "value: %s\n", p->parameter_name, value); out_length = -1; goto out; } } } /* Always check if the response length exceeds MAX_TEXT_LEN */ /* Then the remaining parameters have to be sent in a */ /* separate text command/response */ TRACE(TRACE_DEBUG, "resp_len = %d\n", resp_len); if (resp_len) { if (check_out_length(out_length, resp_len)) { *login_flags |= MORE_TO_SEND_FLAG; break; } else { /* Update resp_len and the pointer to output_string */ sprintf(output_string, "%s", dummy_string); output_string += resp_len + 1; TRACE(TRACE_ISCSI, "Attach key: %s\n", dummy_string); /* update out_length */ out_length += resp_len + 1; if (p) { /* set sent-to-other-side bit */ p->neg_info |= KEY_SENT_TO_OTHER_SIDE; } resp_len = 0; } } if (p) { /* set got-from-other-side bit */ p->neg_info |= KEY_GOT_FROM_OTHER_SIDE; } /* Goto the next key=value pair */ this_key = input_string; /* remember where this key started */ /* this should be start of next key */ input_string += key_value_len + 1; /* In Drafts 9 and before, Section 3.10.4 Text * "Every key=value pair (including the last or only pair) MUST * be followed by at least one null (0x00) delimiter." * * This implied there could be more than one null (0x00) at the * end of a string, so skip over these extra nulls now */ while (*input_string == '\0' && input_string < last_input) { input_string++; } /* In final Draft 20, Section 5.1 Text Format * "Every key=value pair, including the last or only * pair in a LTDS, MUST be followed by one null (0x00) * delimiter." * * This implies that there can NOT be more than one * null (0x00) at the * end of a string, so if there were extra nulls, * give a warning now. */ n = (input_string - this_key) - (key_value_len + 1); if (n > 0) { if (TRACE_TEST(TRACE_ISCSI)) { TRACE_WARNING("%d extra nulls (0x00) found after" " key \"%s\"\n", n, this_key); } } } /* process FirstBurstLength and MaxBurstLength if their reply was delayed */ TRACE(TRACE_DEBUG, "FBLength %x MBLength %x\n",FBLength,MBLength); if (FBLength > 0 && MBLength > 0) { /* both keys were offered by other side in this pdu */ if (FBLength <= MBLength) { /* ok */ /* MaxBurstLength is bigger than FirstBurstLength, all ok */ } else { /* FirstBurstLength bigger than MaxBurstLength, fix it */ FBp->int_value = FBLength = MBLength; TRACE (TRACE_DEBUG, "Updated FBp %p\n",FBp); } } else if (FBLength > 0) { /* only FirstBurstLength was received in this pdu */ if ((MBp = find_flag_parameter(MAXBURSTLENGTH_FLAG, p_param_tbl)) != NULL) { if (FBLength > MBp->int_value) { /* The received FirstBurstLength is bigger than our current MaxBurstLength */ if (IS_KEY_SENT_TO_OTHER_SIDE(MBp->neg_info)) { /* MaxBurstLength already sent, can't be fixed */ TRACE_ERROR ("FirstBurstLength %d bigger " " than negotiated " "MaxBurstLength %d", FBLength, MBp->int_value); out_length = -1; goto out; } /* The unsent MaxBurstLength is smaller * than the received FirstBurstLength, * reduce the FirstBurstLength to the * MaxBurstLength and send both */ FBLength = FBp->int_value = MBLength = MBp->int_value; TRACE (TRACE_DEBUG, "Updated FBLength %u\n", FBLength); } else { /* The received FirstBurstLength not * bigger than our current * MaxBurstLength, send MaxBurstLength only if * negotiation needed. */ if ((IS_KEY_TO_BE_NEGOTIATED(MBp->neg_info) || IS_KEY_GOT_FROM_OTHER_SIDE(MBp-> neg_info)) && !IS_KEY_SENT_TO_OTHER_SIDE(MBp-> neg_info)) { MBLength = MBp->int_value; } } } } else if (MBLength > 0) { /* only MaxBurstLength was received in this pdu */ if ((FBp = find_flag_parameter(FIRSTBURSTLENGTH_FLAG, p_param_tbl)) != NULL) { /* must have MaxBurstLength > FirstBurstLength */ if (MBLength < FBp->int_value) { /* MaxBurstLength is smaller than FirstBurstLength */ if (IS_KEY_SENT_TO_OTHER_SIDE(FBp->neg_info)) { /* FirstBurstLength already sent, can't be fixed */ TRACE_ERROR ("MaxBurstLength %d smaller than " " negotiated " "FirstBurstLength %d", MBLength, FBp->int_value); out_length = -1; goto out; } /* FirstBurstLength has not been sent yet, * so force it to be equal to * MaxBurstLength and offer it now */ FBLength = FBp->int_value = MBLength; TRACE (TRACE_DEBUG, "Updated FBLength %u\n", FBLength); } else { /* MaxBurstLength not smaller than * FirstBurstLength, send * FirstBurstLength only if it still needs * to be negotiated */ if ((IS_KEY_TO_BE_NEGOTIATED(FBp->neg_info) || IS_KEY_GOT_FROM_OTHER_SIDE(FBp-> neg_info)) && !IS_KEY_SENT_TO_OTHER_SIDE(FBp-> neg_info)) { FBLength = FBp->int_value; } } } } if (FBLength > 0) { /* reply to or offer the FirstBurstLength */ TRACE(TRACE_DEBUG, "FBLength %x FBp %p\n",FBLength,FBp); FBp->neg_info |= KEY_SENT_TO_OTHER_SIDE; if (!IS_KEY_GOT_FROM_OTHER_SIDE(FBp->neg_info)) outputpdu->flags &= (~T_BIT); resp_len = sprintf(dummy_string, "%s=%d", FIRSTBURSTLENGTH, FBLength); sprintf(output_string, "%s", dummy_string); output_string += resp_len + 1; TRACE(TRACE_ISCSI, "Attach key, %s\n", dummy_string); /* update out_length */ out_length += resp_len + 1; resp_len = 0; FBLength = -1; } if (MBLength > 0) { /* reply to or offer the MaxBurstLength */ TRACE(TRACE_DEBUG, "MBLength %x MBp %p\n",MBLength,MBp); MBp->neg_info |= KEY_SENT_TO_OTHER_SIDE; if (!IS_KEY_GOT_FROM_OTHER_SIDE(MBp->neg_info)) outputpdu->flags &= (~T_BIT); resp_len = sprintf(dummy_string, "%s=%d", MAXBURSTLENGTH, MBLength); sprintf(output_string, "%s", dummy_string); output_string += resp_len + 1; TRACE(TRACE_ISCSI, "Attach key, %s\n", dummy_string); /* update out_length */ out_length += resp_len + 1; MBLength = -1; } out: FREE_STRING(dummy_string); FREE_STRING(input_str); TRACE(TRACE_ENTER_LEAVE, "Leave scan_input_and_process, out_length %d\n", out_length); /* return the length added to the output_string */ return out_length;}/* * Populates "value" with the approprite return value * that we expect back from the other end. */static void __attribute__ ((no_instrument_function))handle_boolean_param(struct parameter_type *p, char **value){ int receiver_value; int sender_value; TRACE(TRACE_ENTER_LEAVE, "Enter handle_boolean_param %s=%s\n", p->parameter_name, *value); if (!strcmp(*value, key_table->yes)) sender_value = 1; else sender_value = 0; if (!strcmp(p->str_value, key_table->yes)) receiver_value = 1; else receiver_value = 0; if (IS_BOOL_AND(p->type)) { /* Boolean AND function */ if (sender_value & receiver_value) { /* both sides said YES so result is YES */ *value = key_table->yes; } else { /* either (or both) of the sides said NO */ *value = key_table->no; if (sender_value == 0) { /* sender sent NO, so reply is optional * * Draft 20, Section 5.2.2 Simple-value * Negotiations * "Specifically, the two cases in * which answers are OPTIONAL are: * * - The boolean functi
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -