⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 text_param.c

📁 iscsi源代码 UNH的progect 有initiator端和target端的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		if (dummy) {			/* restore the comma and goto the next value */			*dummy++ = ',';		}		value = dummy;	}	while (value);      out:	TRACE(TRACE_ENTER_LEAVE, "Leave check_type_correctness\n");	return;}/* * Checks the correctness of the passed string, checks whether it * conforms to the <key>=<value> format * extracts the value from the input string and returns it as an * output parameter. * Returns pointer to parameter in p_param_tbl if ok, else NULL	 * (but on non-NULL p->neg_info can have flag set on fatal error)		*/static struct parameter_type * __attribute__ ((no_instrument_function))check_correctness(char *keytext,		  char **p_value,		  struct parameter_type p_param_tbl[MAX_CONFIG_PARAMS],		  __u32 who_called,		  __u32 when_called,		  __u32 flags,		  int *int_value, 		  struct unknown_key **unknown_key_list){	char *value;	struct parameter_type *p = NULL;	struct unknown_key *uptr;	__u32 count;	TRACE(TRACE_ENTER_LEAVE, "Enter check_correctness\n");	TRACE(TRACE_ISCSI, "Got key: %s\n", keytext);	if ((value = strchr(keytext, '=')) == NULL) {		/* could not find '=', don't accept this */		TRACE_ERROR("key \"%s\" not followed by '='\n", keytext);		goto out;	}	/* terminate the key name string and point at the value string */	*value++ = '\0';	/* Check for length of the key name. */	/*  Draft 20, Section 5.1 Text Format	 *  "A standard-lable (key-name) MUST begin with a capital letter and	 *  must not exceed 63 characters."	 */	if (strlen(keytext) > MAX_KEY_NAME_LENGTH) {		if (TRACE_TEST(TRACE_ISCSI)) {		      TRACE_WARNING("length of key name \"%s\" exceeds %d\n",					keytext, MAX_KEY_NAME_LENGTH);		}	}	/*  Draft 20, Section 10.12.10 Login Parametersr	 *  "All keys in Chapter 12, except for the X extension formats, 	 *  MUST be supported by iSCSI initiators and targets.  	 *  Keys in Chapter 11 only	 *  need to be supported when the function to which they 	 *  refer is mandatory	 *  to implement."	 */	if (!(p = find_parameter(keytext, p_param_tbl))) {		/* key not found in our table, look for 		   value = "Reject" or "Irrelevant" or "NotUnderstood" */		if (!strcmp(value, key_table->reject)		    || !strcmp(value, key_table->irrelevant)		    || !strcmp(value, key_table->notunderstood)) {			/* These values always fatal as a value for offer 			   of unknown key */			TRACE_ERROR("unknown key with illegal value: %s=%s\n",				    keytext, value);		} else {			/* value not bad, but have we seen this 				unknown key before? */			for (count = 0, uptr = *unknown_key_list;			     uptr != NULL; count++, uptr = uptr->next) {				if (!strcmp(keytext, uptr->keyname)) {					/* yes, this unknown key is 						being negotiated twice */					TRACE_ERROR					    ("unknown key \"%s\" received twice\n",					     keytext);					goto out;				}			}			/* never saw this key before, should we save 				it for later checks? */			/* chap support = CHONG */			if (!is_securitykey(keytext)) {				if (TRACE_TEST(TRACE_ISCSI)) {				      TRACE_WARNING("unknown key \"%s\"\n",							keytext);				}			}			if (count >= MAX_UNKNOWN_KEYS) {				/* no, we have seen too many unknown keys, 						bail out */				TRACE_ERROR				    ("%u unknown keys received, too many!\n",				     count);				goto out;			}			else if ((uptr =				  my_kmalloc(sizeof (struct unknown_key),					     "Unknown key"))				 == NULL) {				goto out;			}			/* chap and srp support - CHONG */			else if ((uptr->keyname =				  my_kmalloc(strlen(keytext) + 1, "Key Name"))				 == NULL) {				my_kfree((void **) &uptr, "Unknown key");				goto out;			}			else if ((uptr->keyvalue =				  my_kmalloc(strlen(value) + 1, "Key Value"))				 == NULL) {				my_kfree((void **) &uptr->keyname, "Key Name");				my_kfree((void **) &uptr, "Unknown key");				goto out;			} else {				strcpy(uptr->keyname, keytext);				strcpy(uptr->keyvalue, value);				uptr->processed = 0;				uptr->next = *unknown_key_list;				*unknown_key_list = uptr;				if ((flags & USE_REFLECT_XKEYS)					&& (strncmp(keytext, "X-", 2) == 0					    || strncmp(keytext, "X#", 2) == 0))					/* this is an X key and user wants its					 * value reflected back to sender					 */					*p_value = value;				else					/* pass back Notunderstood value for 					 * unknown key					 */					*p_value = key_table->notunderstood;			}		}		goto out;	}	if ((who_called == INITIATOR && !IS_USE_BY_TARGET(p->type))	    || (who_called == TARGET && !IS_USE_BY_INITIATOR(p->type))) {		TRACE_ERROR("key \"%s\" cannot be sent to %s\n", keytext,			    who_called == INITIATOR ? "initiator" : "target");		p->neg_info |= KEY_BAD;		goto out;	}	if (IS_KEY_GOT_FROM_OTHER_SIDE(p->neg_info)) {		/* attempting to negotiate this key twice */		/*  Draft 20, Section 5.3 Login Phase		 *  "Neither the initiator nor the target should attempt to 		 *  declare or negotiate a parameter more than once 		 *  during login except for responses to specific keys 		 *  that explicitly allow repeated key declarations 		 *  (e.e., TargetAddress).  An attempt to renegotiate/		 *  redeclare parameters not specifically allowed MUST 		 *  be detected by the initiator and target.  If such an 		 *  attempt is detected by the target, the target MUST 		 *  respond with Login reject (initiator error);		 *  if detected by the initiator, the initiator MUST drop the		 *  connection."		 */		TRACE_ERROR("key \"%s\" received twice\n", p->parameter_name);		p->neg_info |= KEY_BAD;		goto out;	}	if (!IS_KEY_SENT_TO_OTHER_SIDE(p->neg_info)) {		/* this is new offer from other side, not reply 			to one of our offers */		if (!(p->type & when_called)) {			/* wrong time to be negotiating this parameter */			TRACE_ERROR("key \"%s\" cannot be negotiated now\n",				    keytext);			p->neg_info |= KEY_BAD;			goto out;		}	}	check_type_correctness(p, value, who_called, int_value);	/* Return the value pointer on success */	*p_value = value;      out:	TRACE(TRACE_ENTER_LEAVE, "Leave check_correctness, p %p\n", p);	return p;}char * __attribute__ ((no_instrument_function))strdup(char *str){	int n = strlen(str) + 1;	char *s = kmalloc(n, GFP_KERNEL);	if (!s)		return NULL;	return strcpy(s, str);}void __attribute__ ((no_instrument_function))strreplace(char **str, char *new_str){	if (*str != NULL)		kfree(*str);	*str = strdup(new_str);}/* Copy src parameter table to dst, duplicating any strings */voidparam_tbl_cpy(struct parameter_type dst[MAX_CONFIG_PARAMS],	      struct parameter_type src[MAX_CONFIG_PARAMS]){	struct parameter_type *dptr;	int i;	TRACE(TRACE_ENTER_LEAVE,	      "Enter param_tbl_cpy, dst %p, src %p, size %d\n", dst, src,	      sizeof (struct parameter_type) * MAX_CONFIG_PARAMS);	/* copy everything in the src table to the dst table "as is" */	memcpy(dst, src, sizeof (struct parameter_type) * MAX_CONFIG_PARAMS);	/* now go back and "dup" all the strings */	for (i = 0, dptr = dst; i < MAX_CONFIG_PARAMS; i++, dptr++) {		if (dptr->parameter_name) {			dptr->parameter_name = strdup(dptr->parameter_name);		}		if (dptr->str_value) {			dptr->str_value = strdup(dptr->str_value);		}		if (dptr->value_list) {			dptr->value_list = strdup(dptr->value_list);		}	}	TRACE(TRACE_ENTER_LEAVE, "Leave param_tbl_cpy\n");}/* Copy initial parameter table to dst, duplicating any strings */voidparam_tbl_init(struct parameter_type dst[MAX_CONFIG_PARAMS]){	param_tbl_cpy(dst, config_params);}/* Free any strings referenced in dst parameter table */voidparam_tbl_uncpy(struct parameter_type dst[MAX_CONFIG_PARAMS]){	struct parameter_type *dptr;	int i;	TRACE(TRACE_ENTER_LEAVE, "Enter param_tbl_uncpy, dst %p, size %d\n",	      dst, sizeof (struct parameter_type) * MAX_CONFIG_PARAMS);	/* go thru and free all the strings that were "duped" during copy */	for (i = 0, dptr = dst; i < MAX_CONFIG_PARAMS; i++, dptr++) {		if (dptr->parameter_name) {			kfree(dptr->parameter_name);		}		if (dptr->str_value) {			kfree(dptr->str_value);		}		if (dptr->value_list) {			kfree(dptr->value_list);		}	}	TRACE(TRACE_ENTER_LEAVE, "Leave param_tbl_uncpy\n");}voidconfigure_parameter(int param_neg_info,		    char *ptr_to_keytext,		    struct parameter_type p_param_tbl[MAX_CONFIG_PARAMS]){	struct parameter_type *param = NULL;	char *value_list = NULL;	char *endptr;	int int_value;	TRACE(TRACE_ENTER_LEAVE, "Enter configure_parameter\n");	/* Get the value string */	value_list = strchr(ptr_to_keytext, '=');	if (value_list)		*value_list++ = '\0';	/* terminate the key text string */	if ((param = find_parameter(ptr_to_keytext, p_param_tbl)) != NULL) {		if (value_list) {			if (IS_NUMBER(param->type)) {				/* parameter is a number, set only the 				 * int_value field, don't set value_list 				 * or str_value fields 				 */				int_value =				    simple_strtoul(value_list, &endptr, 0);				if (strspn(endptr, WHITE_SPACE) !=				    strlen(endptr)) {					TRACE_ERROR("illegal number \"%s\"\n",						    value_list);					goto out;				} else {					param->int_value = int_value;				}			} else {				/* parameter is a string, enumerated, boolean 				 * or range,				 * set both the value_list and str_value fields,				 * do not set int_value field 				 */				if (IS_NUMBER_RANGE(param->type)) {					/* this is a range, check both 						numbers and their order */					if (check_range(value_list, -1) < 0)						goto out;				}				strreplace(&param->value_list, value_list);				endptr = strchr(value_list, ',');				if (endptr) {	/* value_list really a list,i				                 * use 1st on list as 						 * current value 						 */					*endptr = '\0';					strreplace(&param->str_value,						   value_list);					*endptr = ',';	/* repair the damage */				} else {					/* value_list only single value, make 						it current val too */					strreplace(&param->str_value,						   value_list);				}			}		}		/* set the negotiation info only if no error */		param->neg_info = param_neg_info;	}      out:	TRACE(TRACE_ENTER_LEAVE, "Leave configure_parameter\n");}/*	Draft 20, Section 5.2 Text Mode Negotiation *	"Some parameters may be subject to integrity rules (e.g., parameter-x *	must not exceed parameter-y or parameter-u not 1 implies parameter-v *	be Yes).  Whenever required, integrity rules are specified with the *	keys.  Checking for compliance with the integrity rule must only be *	performed after all the parameters are available (the existent and the *	newly negotiated).	An iSCSI target MUST perform integrity checking *	before the new parameters take effect.	An initiator MAY perform *	integrity checking." */voidcheck_integrity_rules(struct parameter_type p_param_tbl[MAX_CONFIG_PARAMS],		      __u16 secondary_connection){	struct parameter_type *p, *p2;	TRACE(TRACE_ENTER_LEAVE, "Enter check_integrity_rules\n");	/*  Draft 20, Section A.3.2 OFMarkInt, IFMarkInt	 *  "Reject is resetting the marker function in the specified	 *  direction (Output or Input) to No."	 */	if ((p = find_flag_parameter(OFMARKINT_FLAG, p_param_tbl)) != NULL) {		if (p->neg_info & KEY_REJECT) {			/* got OFMarkInt=Reject, so set OFMarker=No */			TRACE(TRACE_DEBUG, "Checking %s=%d\n",			      p->parameter_name, p->int_value);			if ((p = find_flag_parameter(OFMARKER_FLAG,						 p_param_tbl)) != NULL) {				TRACE(TRACE_DEBUG, "Have %s=%s\n",				      p->parameter_name, p->str_value);				if (!strcmp(p->str_value, key_table->yes)) {					/* have OFMarker=Yes, change value 						to No */					strreplace(&p->str_value,						   key_table->no);					TRACE(TRACE_ISCSI, "Reset %s to %s\n",					      p->parameter_name, p->str_value);				}			}		}	}	if ((p = find_flag_parameter(IFMARKINT_FLAG, p_param_tbl)) != NULL) {		if (p->neg_info & KEY_REJECT) {			/* got IFMarkInt=Reject, so set IFMarker=No */			TRACE(TRACE_DEBUG, "Checking %s=%d\n",			      p->parameter_name, p->int_value);			if ((p = find_flag_parameter(IFMARKER_FLAG,						 p_param_tbl)) != NULL) {				TRACE(TRACE_DEBUG, "Have %s=%s\n",				      p->parameter_name, p->str_value);				if (!strcmp(p->str_value, key_table->yes)) {					/* have IFMarker=Yes, change 						value to No */					strreplace(&p->str_value,						   key_table->no);					TRACE(TRACE_ISCSI, "Reset %s to %s\n",					      p->parameter_name, p->str_value);				}			}		}	}	/*  the following checks are done only on first connection in 	 * a session 	 */	if (!secondary_connection) {		/*  Draft 20, Section 12.14 FirstBurstLength		 *  "FirstBurstLength MUST NOT exceed MaxBurstLength."		 */		if ((p = find_flag_parameter(FIRSTBURSTLENGTH_FLAG,					 p_param_tbl)) != NULL) {			if ((p2 = find_flag_parameter(MAXBURSTLENGTH_FLAG,						 p_param_tbl)) != NULL) {				if (p->int_value > p2->int_value) {					if (TRACE_TEST(TRACE_ISCSI)) {					     TRACE_WARNING("FirstBurstLength %u"					     " exceeds MaxBurstLength %u\n",					     p->int_value, p2->int_value);					}					/* fix FirstBurstLength */					p->int_value = p2->int_value;					}			}		}		/*  Draft 20, Section 12.21 SessionType		 *  "The discovery session implies MaxConnections = 1 		 *  and overrides both		 *  the default and an explicit setting."		 */		if ((p = find_flag_parameter(SESSIONTYPE_FLAG,					 p_param_tbl)) != NULL) {			if (!strcmp(p->str_value, key_table->discovery)			    && (p2 = find_flag_parameter(MAXCONNECTIONS_FLAG,						    p_param_tbl)) != NULL) {				if (p2->int_value != 1) {					/* do not have MaxConnections=1, 						change value to 1 */					p2->int_value = 1;					TRACE(TRACE_ISCSI, "Reset %s to %u\n",					      p2->parameter_name,					      p2->int_value);				}			}		}		/*  Draft 20, Section 12.19 DataSequenceInOrder		 *  "If DataSequenceInOrder is set to Yes, a target may 		 *  retry at most the last R2T, and an initiator may 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -