📄 text_param.c
字号:
/* Called to get pointer to table entry for key identified by its special flag*/struct parameter_type * __attribute__ ((no_instrument_function))find_flag_parameter(__u64 key_flag, struct parameter_type p_param_tbl[MAX_CONFIG_PARAMS]){ struct parameter_type *p, *result = NULL; int i; for (i = 0, p = p_param_tbl; i < MAX_CONFIG_PARAMS; i++, p++) { if (p->special_key_flag & key_flag) { result = p; break; } } return result;}/* Called to set max_recv_length to value we sent to target in a * MaxRecvDataSegmentLength key */voidset_connection_recv_length(struct parameter_type p_param_tbl[MAX_CONFIG_PARAMS], int *max_recv_length){ struct parameter_type *p; TRACE(TRACE_ENTER_LEAVE, "Enter set_connection_recv_length\n"); if ((p = find_flag_parameter(MAXRECVDATASEGMENTLENGTH_FLAG, p_param_tbl)) && IS_KEY_SENT_TO_OTHER_SIDE(p->neg_info)) { /* we did send this key to the other side */ *max_recv_length = p->int_value; } TRACE(TRACE_ENTER_LEAVE, "Leave set_connection_recv_length\n");}voidset_digestflags(struct parameter_type p_param_tbl[MAX_CONFIG_PARAMS], __u32 * connection_flags){ struct parameter_type *p; if ((p = find_flag_parameter(HEADERDIGEST_FLAG, p_param_tbl))) { if (strcmp(p->str_value, CRC32C) == 0) { *connection_flags |= USE_HEADERDIGEST; TRACE(TRACE_ISCSI, "Enabling Header Digests\n"); } } if ((p = find_flag_parameter(DATADIGEST_FLAG, p_param_tbl))) { if (strcmp(p->str_value, CRC32C) == 0) { *connection_flags |= USE_DATADIGEST; TRACE(TRACE_ISCSI, "Enabling Data Digests\n"); } }}/* Check that a number is within legal bounds depending on its type. * Returns 1 if ok, 0 if error */int __attribute__ ((no_instrument_function))check_bounds(struct parameter_type *p, int int_value, int who_called){ int retval = 1; if (IS_ONE_TO_65535(p->type)) { if ((int_value < 1) || (int_value > 65535)) { TRACE_ERROR("illegal number %d - " "should be between 1 and 65535\n", int_value); retval = 0; } } else if (IS_ZERO_TO_65535(p->type)) { if ((int_value < 0) || (int_value > 65535)) { TRACE_ERROR("illegal number %d - " "should be between 0 and 65535\n", int_value); retval = 0; } } else if (IS_N512_TO_16777215(p->type)) { if ((int_value < 512) || (int_value > 16777215)) { if (who_called == MANAGEMENT && (p->special_key_flag & (MAXBURSTLENGTH_FLAG | FIRSTBURSTLENGTH_FLAG))) { /* Burst limits depend on draft, do it at run time */ } else { TRACE_ERROR("illegal number %d - " "should be between 512 and 16777215\n", int_value); retval = 0; } } } else if (IS_ZERO_TO_3600(p->type)) { if ((int_value < 0) || (int_value > 3600)) { TRACE_ERROR("illegal number %d - " "should be between 0 and 3600\n", int_value); retval = 0; } } else if (IS_ZERO_TO_2(p->type)) { if ((int_value < 0) || (int_value > 2)) { TRACE_ERROR("illegal number %d - " "should be between 0 and 2\n", int_value); retval = 0; } } return retval;}/* This is a range, check both numbers and their order. * Returns first number in range if ok, -1 if error */int __attribute__ ((no_instrument_function))check_range(char *value_list, int value){ char *endptr; int lower, upper; lower = simple_strtoul(value_list, &endptr, 0); if (*endptr == '~') { /* first number followed by ~ must be followed by another number */ upper = simple_strtoul(endptr + 1, &endptr, 0); } else { /* only 1 value was specified, which is ok */ upper = lower; } if (strspn(endptr, WHITE_SPACE) != strlen(endptr) || lower > upper) { TRACE_ERROR("illegal range \"%s\"\n", value_list); return -1; } if (value >= 0 && (value < lower || value > upper)) { TRACE_ERROR("value %d out of range \"%s\"\n", value, value_list); return -1; } return lower;}/* * Checks correctness of the type of parameter with the value passed * The main types are defined in "text_param.h" * If the value is NULL, no checks made. * On return, a flag is set in p->neg_info if a fatal error occured * Called only from check_correctness */static void __attribute__ ((no_instrument_function))check_type_correctness(struct parameter_type *p, char *value, int who_called, int *int_value){ char *dummy; char *endptr = NULL; TRACE(TRACE_ENTER_LEAVE, "Enter check_type_correctness\n"); TRACE(TRACE_ENTER_LEAVE, "Parameter: %s, value: %s\n", p->parameter_name, value); /* If the value is inquiry, ignore it */ if (!strcmp(value, "?")) goto out; /* look for value = "Reject" or "Irrelevant" or "NotUnderstood" */ if (!strcmp(value, key_table->reject)) { if (!IS_KEY_SENT_TO_OTHER_SIDE(p->neg_info)) { /* Reject always fatal as an offer */ TRACE_ERROR("illegal offer: %s=%s\n", p->parameter_name, value); p->neg_info |= KEY_BAD; } else if (p-> special_key_flag & (OFMARKINT_FLAG | IFMARKINT_FLAG)) { /* Reject is not fatal as a reply to * OFMarkInt/IFMarkInt keys * Draft 20, Section A.3.2 OFMarkInt, IFMarkInt * "When the interval is unacceptable the responder * answers with "Reject". Reject is resetting * the marker function in the * specified direction (Output or Input) to No." */ /* so we can do a reset later */ p->neg_info |= KEY_REJECT; } else { /* Reject always fatal as a reply to all other keys */ TRACE_ERROR("got key: %s=%s\n", p->parameter_name, value); p->neg_info |= KEY_BAD; } goto out; } if (!strcmp(value, key_table->irrelevant)) { if (!IS_KEY_SENT_TO_OTHER_SIDE(p->neg_info)) { /* Irrelevant always fatal as an offer */ TRACE_ERROR("illegal offer: %s=%s\n", p->parameter_name, value); p->neg_info |= KEY_BAD; } else { /* Irrelevant is a legal reply in all negotiations */ if (TRACE_TEST(TRACE_ISCSI)) { TRACE_WARNING("got key: %s=%s\n", p->parameter_name, value); } p->neg_info |= KEY_IRRELEVANT; } goto out; } /* Draft 20, Section 5.2 Text Mode Negotiation * "All keys in this document, except for the X extension formats, * MUST be supported by iSCSI initiators and targets when used * as specified here. * If used as specified, these keys MUST NOT be answered with * NotUnderstood." */ if (!strcmp(value, key_table->notunderstood)) { if (!IS_KEY_SENT_TO_OTHER_SIDE(p->neg_info)) { /* NotUnderstood always fatal as an offer */ TRACE_ERROR("illegal offer: %s=%s\n", p->parameter_name, value); p->neg_info |= KEY_BAD; } else if ((p->special_key_flag & X_EXTENSIONKEY_FLAG)) { /* target not expected to understand this anyway, consider its response irrelevant */ p->neg_info |= KEY_IRRELEVANT; } else { /* NotUnderstood always fatal as a reply to a standard key */ TRACE_ERROR ("standard key \"%s\" MUST NOT be answered with " "\"%s\"\n", p->parameter_name, key_table->notunderstood); p->neg_info |= KEY_BAD; } goto out; } if (IS_STRING(p->type)) { /* key value is a string, just check its total length */ /* Draft 20, Section 5.1 Text Format * "If not otherwise specified, the maximum length of a * simple-value (not its encoded representation) is 255 * bytes not including the delimiter (comma or zero byte)." * * Draft 20, Section 3.2.6.1 iSCSI Name Properties * "Each iSCSI node, whether an initiator or target, * MUST have an iSCSI name. * * Initiators and targets MUST support the receipt of iSCSI * names of up to the maximum length of 223 bytes. " */ char *tptr; int len = strlen(value); int t_num; if (len > MAX_KEY_VALUE_LENGTH) { TRACE_ERROR ("value of key \"%s\" longer than %d characters\n", p->parameter_name, (IS_ISCSI_NAME(p->type) ? MAX_ISCSI_NAME_LENGTH : MAX_KEY_VALUE_LENGTH)); p->neg_info |= KEY_BAD; } /* check ISCSI_NAME type */ if (IS_ISCSI_NAME(p->type)) { if (who_called == TARGET && p->special_key_flag & TARGETNAME_FLAG) { /* check TargetName sent by the initiator */ p->int_value = 0; /* assume an error */ if ((strncmp(TARGETNAME_HEADER, value, strlen(TARGETNAME_HEADER)) != 0) || (tptr = strchr(value, ':')) == NULL) { TRACE_WARNING ("invalid %s \"%s\". " "Use Discovery session" " to get proper %s.\n", p->parameter_name, value, p->parameter_name); goto out; } tptr++; /* point at char after ':' */ if (strspn(tptr, WHITE_SPACE) == strlen(tptr)) { TRACE_ERROR ("no target number in %s \"%s\"\n", p->parameter_name, value); p->neg_info |= KEY_BAD; goto out; } t_num = simple_strtoul(tptr, &endptr, 10); if (t_num < 0 || *endptr != '\0') { TRACE_ERROR ("bad target number \"%s\" " "in %s \"%s\"\n", tptr, p->parameter_name, value); p->neg_info |= KEY_BAD; goto out; } /* check target number from the target name */ if (!target_in_use(t_num)) { TRACE_ERROR ("target number %d not in use " "in %s \"%s\"\n", t_num, p->parameter_name, value); p->neg_info |= KEY_BAD; goto out; } /* target number ok, save it for pickup later */ p->int_value = t_num; } /* check the format of the iSCSI name */ /* Draft 20, 3.2.6.3 iSCSI Name Structure * "The type designator strings currently defined are: * iqn. - iSCSI Qualified name * eui. - Remainder of the string is an * IEEE EUI-64 identifier, in * ASCII-encoded hexadecimal." */ if (len == 20 && strncmp(value, "eui.", 4) == 0) { /* IEEE format world wide unique name -- 16 hex digits must follow */ if (strspn(value + 4, "0123456789abcdefABCDEF") == 16) /* ok, have exactly 16 hex digits following the "eui." */ goto out; } else if (len > 12 && len <= MAX_ISCSI_NAME_LENGTH && strncmp(value, "iqn.", 4) == 0) { /* iSCSI qualified name -- must get "yyyy-mm." then alphanums, ., - */ if (strspn(value + 4, "0123456789") == 4 && *(value + 8) == '-' && strspn(value + 9, "0123456789") == 2 && *(value + 11) == '.' && strspn(value + 12, "0123456789abcdefghijklmnopqrstuvwxyz-.:") == len - 12) { /* ok, have iqn.yyyy-mm.xxx with xxx * all digits, lower-case letters, * * '-', '.', ':' */ goto out; } } /* If reach here have invalid iSCSI name */ if (TRACE_TEST(TRACE_ISCSI)) { TRACE_WARNING("invalid iSCSI name \"%s\"\n", value); } goto out; } } /* the following are to be tested for each value in the list */ do { endptr = NULL; /* extract just a single value */ dummy = strchr(value, ','); if (dummy) { /* found a comma so value contains list of values -- is this ok? */ if (!IS_KEY_MULTI_VALUE(p->type) && !(p->special_key_flag & TARGETADDRESS_FLAG)) { /* this key cannot accept a list of values */ TRACE_ERROR ("key \"%s\" does not accept a list of values " "\"%s\"\n", p->parameter_name, value); p->neg_info |= KEY_BAD; break; } /* terminate first item in the list so it is a string by itself */ *dummy = '\0'; } TRACE(TRACE_DEBUG, "value: %s\n", value); /* Check for length of the key value. */ /* Draft 20, Section 5.1 Text Format * "If not otherwise specified, the maximum length of * a simple-value (not its encoded representation) is * 255 bytes not including the * delimiter (comma or zero byte)." */ if (strlen(value) > MAX_KEY_VALUE_LENGTH) { if (TRACE_TEST(TRACE_ISCSI)) { TRACE_WARNING("value of key \"%s\" " "exceeds %d characters\n", p->parameter_name,MAX_KEY_VALUE_LENGTH); } } if (*value == '\0' && !IS_KEY_NO_VALUE(p->type)) { TRACE_ERROR("no value after '=' for key \"%s\"\n", p->parameter_name); p->neg_info |= KEY_BAD; break; } else if (IS_NUMBER(p->type) || (IS_NUMBER_RANGE(p->type) && IS_KEY_SENT_TO_OTHER_SIDE(p->neg_info))) { /* a number or a reply to a range */ *int_value = simple_strtoul(value, &endptr, 0); if (strspn(endptr, WHITE_SPACE) != strlen(endptr)) { TRACE_ERROR("illegal number \"%s\"\n", value); p->neg_info |= KEY_BAD; break; } if (!check_bounds(p, *int_value, who_called)) { p->neg_info |= KEY_BAD; break; } } else if (IS_BOOLEAN(p->type)) { if (strcmp(value, key_table->yes) && strcmp(value, key_table->no)) { TRACE_ERROR("illegal value \"%s\" - expected " "\"%s\" or \"%s\"\n", value, key_table->yes, key_table->no); p->neg_info |= KEY_BAD; break; } } else if (IS_ENUMERATED(p->type)) { if (IS_AUTH_PARAM(p->type)) { if (strcmp(value, KRB5) && strcmp(value, SPKM1) && strcmp(value, SPKM2) && strcmp(value, SRP) && strcmp(value, CHAP) && strcmp(value, key_table->none)) { TRACE_ERROR ("illegal value \"%s\" - expected " "\"KRB5\" or " "\"SPKM1\" or \"SPKM2\" or \"SRP\" or " "\"CHAP\" or \"%s\"\n", value, key_table->none); p->neg_info |= KEY_BAD; break; } } else if (IS_DISCOVERY_NORMAL(p->type)) { if (strcmp(value, key_table->discovery) && strcmp(value, key_table->normal)) { TRACE_ERROR ("illegal value \"%s\" - expected " "\"%s\" or \"%s\"\n", value, key_table->discovery, key_table->normal); p->neg_info |= KEY_BAD; break; } } } else if (IS_NUMBER_RANGE(p->type) && !IS_KEY_SENT_TO_OTHER_SIDE(p->neg_info)) { /* is an offer of a numeric range */ if ((*int_value = check_range(value, -1)) < 0 || !check_bounds(p, *int_value, who_called)) { p->neg_info |= KEY_BAD; break; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -