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

📄 initiator_negotiate.c

📁 iscsi源代码 UNH的progect 有initiator端和target端的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
 */intss_done_func( enum security_steps *security_step,        struct unknown_key **   unknown_key_list,        struct parameter_type *p_param_tbl,        struct auth_parameter_type p_auth_param,        int noperational,        struct generic_pdu *inputpdu,        struct generic_pdu *outputpdu,        __u32 * got_keys,	int *count){			int got_bitmask;	struct unknown_key *key;	TRACE(TRACE_ENTER_LEAVE, "Enter ss_done %d\n",				*security_step);	/* deal with unknown keys: CHAP, SRP keys illegal 	   in this state */	for (key = *unknown_key_list; key != NULL; key = key->next) {		if (!key->processed) {			key->processed = 1;			if ((got_bitmask = print_bad_security_key(key))) {				print_not_allowed_security_key(key);			}			goto out;		}	}	if (inputpdu->flags & T_BIT) {		/* target agreed to transition out of security stage */		*count = LOOP_TIMES;		goto break_out; 	}	TRACE(TRACE_ISCSI, "end up the security phase\n");	if (noperational == 0)		outputpdu->flags |= (NSG3 | T_BIT);	else		outputpdu->flags |= (NSG1 | T_BIT);break_out:	TRACE(TRACE_ENTER_LEAVE, "Leaving ss_find_srp_h %d\n",				*security_step);	return 0;out:	TRACE(TRACE_ENTER_LEAVE, "Leaving ss_find_srp_h Failure Next %d\n",				*security_step);	return -1;}/*	Returns 1 for redirection,  *	0 for all other successes, -1 for any error */static intinitiator_operational_phase(struct socket *sock, 	struct parameter_type	p_param_tbl[MAX_CONFIG_PARAMS], 	__u32 * cur_cmd_sn,	int *exp_stat_sn, 	int *max_send_length,	__u32 when_called, 	struct generic_pdu *inputpdu,	struct generic_pdu *outputpdu,	int *target_version_max, 	int *target_version_active,	__u32 connection_flags, 	__u64 * login_flags,	struct unknown_key **unknown_key_list){	int add_length = 0;	int count, retval = 0;	TRACE(TRACE_ENTER_LEAVE, "Entering initiator_operational_phase\n");	count = 0;	do {		TRACE(TRACE_DEBUG, "count %d, inputpdu->T_BIT 0x%02x\n",		      count, inputpdu->flags & T_BIT);		/* assume there is only one message is to be 		 * sent in this phase 		 */		outputpdu->flags &= (~CSG | NSG);		outputpdu->flags |= CSG1 | T_BIT | NSG3;			if ((*login_flags & MORE_TO_SEND_FLAG) && count < 3) {			/* set output.T = 0 */			outputpdu->flags &= ~(T_BIT);		}		*login_flags &= ~MORE_TO_SEND_FLAG;		/* scan through our table and process any 		 * unsent O or I keys 		 *      -- if any unsent S keys then protocol error   		 */		add_length = scan_table_and_process(sock,						    p_param_tbl,						    OPERATIONAL_PARAM |						    INFORMATIONAL_PARAM,						    TARGETNAME_FLAG,						    INITIATOR, inputpdu,						    outputpdu, connection_flags,						    login_flags);		if (add_length < 0) {			retval = add_length;			goto out;		}		outputpdu->text_length += add_length;		/*  Draft 20, Section 10.12.8 CmdSN (for Login Request):		   "CmdSN is either the initial command sequence number 		    of a session (for the first Login request of a 		    session - the "leading" login), or the command 		    sequence number in the command stream if the login		   is for a new connection in an existing session."		 */		/*  This means we always have to pick up the session's 		    CmdSN and put it into the pdu just as we are about 		    to send it on the wire.  However, we do not 		    advance it during login phase.		 */		outputpdu->cmd_sn = cpu_to_be32(*cur_cmd_sn);		TRACE(TRACE_ISCSI, "Send Login, ITT %u\n",		      ntohl(outputpdu->init_task_tag));		if ((retval = write_and_read(sock, inputpdu, outputpdu,					     target_version_max,					     target_version_active,					     connection_flags)) < 0) {			goto out;		}		/* pass back the exp_stat_sn from the last login 		 * response we get 		 */		/* exp_stat_sn is always 1 greater than last statsn received */		*exp_stat_sn = 1 +		    be32_to_cpu(((struct iscsi_targ_login_rsp *) inputpdu)->				stat_sn);		/* set up the reply (if any) to have the correct ExpStatSN */		outputpdu->exp_stat_sn = cpu_to_be32(*exp_stat_sn);		/* process each key attached to the input packet */		add_length = scan_input_and_process(sock,						    p_param_tbl,						    OPERATIONAL_PARAM |						    INFORMATIONAL_PARAM,						    TARGETPORTALGROUPTAG_FLAG,						    INITIATOR, max_send_length,						    when_called, inputpdu,						    outputpdu, connection_flags,						    login_flags,						    unknown_key_list);		if (add_length < 0) {			retval = add_length;			goto out;		}		outputpdu->text_length = add_length;		/* see if Login Request was a redirect */		if (retval == STAT_CLASS_REDIRECTION) {			goto out;		}		if (*login_flags & FIRST_FLAG) {			/* this was first Login Request/Login Response pair */			if (!(*login_flags & TARGETPORTALGROUPTAG_FLAG)				&& *login_flags & TARGETNAME_FLAG) {				/* RFC 3720 Section 5.3.1 Login Phase Start				 * During the Login Phase the iSCSI target 				 * MUST return the TargetPortalGroupTag 				 * key with the first Login Response				 * PDU with which it is allowed to do 				 * so (i.e., the first Login Response 				 * issued after the first Login Request with				 * the C bit set to 0) for all session types				 * when TargetName is given and the response				 * is not a redirection."				 */				TRACE(TRACE_ISCSI, "\"TargetPortalGroupTag\" "				      "not in first Login Response from target\n");				retval = -1;				goto out;			}			*login_flags &= ~FIRST_FLAG;		}		count++;	/* to prevent infinite loops */		if (count >= LOOP_TIMES) {			TRACE_ERROR			    ("infinite loop in operational phase negotiations\n");			retval = -1;			goto out;		}		if ((inputpdu->flags & T_BIT) && add_length > 0) {			/* protocol error  */			TRACE_ERROR			    ("target has T bit set, but initiator still needs to send more\n");			retval = -1;			goto out;		}	} while (add_length > 0 || !(inputpdu->flags & T_BIT));	/* When loop ends, operational parameter negotiation stage 	 * is finished 	 *	 * Check whether all parameters that were sent in this stage 	 * have received their responses  	 */	if (check_neg_responses(p_param_tbl, 1) < 0) {		/* for now, ignore this (message already given) */	}	if (*login_flags & MORE_TO_SEND_FLAG) {	/* protocol error */		TRACE_ERROR("not all parameters negotiated\n");	}      out:	TRACE(TRACE_ENTER_LEAVE,	      "Leaving initiator_operational_phase, retval %d\n", retval);	return retval;}/*	This local function performs parameter negotiation on initiator side. *	Called only from initiator_parameter_negotiate() after all local *	working storage has been allocated. *	Returns 1 if Redirection, 0 if otherwise successful, -1 on error. *	If successful: *		login phase is complete, *		digests have been enabled as necessary, *		all parameters passed by pointer have been updated, *		we are now in FFP. */static intinit_parameter_negotiate(struct socket *sock,	struct parameter_type p_param_tbl[MAX_CONFIG_PARAMS],	struct auth_parameter_type auth_param,	__u32 * cur_cmd_sn,	__u32 * connection_flags,	__u32 when_called,	int *exp_stat_sn,	int *max_send_length,	int *max_recv_length,	struct generic_pdu *inputpdu,	struct generic_pdu *outputpdu,	struct unknown_key **unknown_key_list){	int retval = 0;	int nsecurity, ninformational, noperational;	int target_version_max = -1, target_version_active = -1;	__u64 login_flags;	TRACE(TRACE_ENTER_LEAVE, "Enter init_parameter_negotiate\n");	/* about to process the first Login Request/Response */	login_flags = FIRST_FLAG;	/* count the number of each kind of parameter still to be negotiated */	scan_table_and_count(p_param_tbl, &nsecurity, &ninformational,			     &noperational);	/* to force a login phase, make it look like there is a 	 * param of that type 	 */	if (*connection_flags & USE_SECURITY_PHASE)		nsecurity++;	if (*connection_flags & USE_OPERATIONAL_PHASE)		noperational++;	if (nsecurity + noperational + ninformational == 0) {		/* no parameters at all to negotiate, and no phases forced! */		nsecurity++;	/* might as well start in security phase */	}	if (nsecurity > 0) {		/* have some security parameters to negotiate		 * or want to force security phase in any case		 * chap support - CHONG		 */		if ((retval =		     initiator_security_phase(sock, p_param_tbl, 						auth_param,						cur_cmd_sn, 						exp_stat_sn,						max_send_length, 						noperational,						when_called, 						inputpdu, 						outputpdu,						&target_version_max,						&target_version_active,						*connection_flags, 						&login_flags,						unknown_key_list)) < 0) {			goto out;		}		ninformational = 0;	/* these have been sent in security phase */	}	if ((noperational + ninformational > 0 ||	     (inputpdu->flags & NSG) == NSG1) && retval == 0) {		/* enter the operational negotiation phase */		if ((retval = initiator_operational_phase(sock, p_param_tbl,							cur_cmd_sn,							exp_stat_sn,							max_send_length,							when_called, 							inputpdu,							outputpdu,							&target_version_max,							&target_version_active,							*connection_flags,							&login_flags,							unknown_key_list)) < 0)							 { goto out;		}	}      out:	TRACE(TRACE_ENTER_LEAVE, "Leave init_parameter_negotiate, retval %d\n",	      retval);	return retval;}/*	This function is the entry point to this file to perform parameter *	negotiation on initiator side. *	Called only from iscsi_initiator_login() in iscsi_initiator.c. *	Returns 1 on Redirection, 0 on all other successes, -1 on any error. */intinitiator_parameter_negotiate(struct socket *sock,	struct parameter_type	p_param_tbl[MAX_CONFIG_PARAMS],	struct auth_parameter_type auth_param,	__u32 *cur_cmd_sn, 	__u32 login_task_tag,	void *isid, 	__u16 *tsih, 	__u16 cid,	__u32 *connection_flags, 	__u32 version_number,	__u32 when_called, 	int *exp_stat_sn,	int *max_send_length, 	int *max_recv_length){	int retval = 0;	struct generic_pdu *inputpdu, *outputpdu;	struct iscsi_init_login_cmnd *loginpdu;	struct unknown_key *uptr, *unknown_key_list = NULL;	TRACE(TRACE_ENTER_LEAVE, "Enter initiator_parameter_negotiate\n");	if ((inputpdu =	     my_kmalloc(sizeof (struct generic_pdu), "Input pdu")) == NULL) {		retval = -1;		goto out;	}	if ((outputpdu =	     my_kmalloc(sizeof (struct generic_pdu), "Output pdu")) == NULL) {		my_kfree((void **) &inputpdu, "Input pdu");		retval = -1;		goto out;	}	/* Get memory for text portion of inputpdu and outputpdu */	if ((inputpdu->text = my_kmalloc(MAX_TEXT_LEN, "Input text")) == NULL) {		my_kfree((void **) &outputpdu, "Output pdu");		my_kfree((void **) &inputpdu, "Input pdu");		retval = -1;		goto out;	}	inputpdu->text_length = 0;	if ((outputpdu->text = my_kmalloc(MAX_TEXT_LEN, 		"Output text")) == NULL) {		my_kfree((void **) &inputpdu->text, "Input text");		my_kfree((void **) &outputpdu, "Output pdu");		my_kfree((void **) &inputpdu, "Input pdu");		retval = -1;		goto out;	}	outputpdu->text_length = 0;	/* Set up the output pdu */	loginpdu = (struct iscsi_init_login_cmnd *) outputpdu;	/* initialize everything to 0 so reserved fields will be 0 */	memset(loginpdu, 0, ISCSI_HDR_LEN);	/* then set up those fields in the Login Request 	 * PDU that will not change 	 */	loginpdu->opcode = ISCSI_INIT_LOGIN_CMND;		/* Login command always marked immediate */	loginpdu->opcode |= I_BIT;	loginpdu->version_max = version_number;	loginpdu->version_min = version_number;	memcpy(loginpdu->isid, isid, 6);	loginpdu->tsih = cpu_to_be16(*tsih);	loginpdu->init_task_tag = cpu_to_be32(login_task_tag);	loginpdu->cid = cpu_to_be16(cid);	TRACE(TRACE_DEBUG, "initiator_parameter_negotiate version_number %u\n",	      version_number);	/* chap support - CHONG */	retval = init_parameter_negotiate(sock, 					p_param_tbl, 					auth_param, 					cur_cmd_sn,					connection_flags, 					when_called, 					exp_stat_sn,					max_send_length, 					max_recv_length, 					inputpdu,					outputpdu, 					&unknown_key_list);	/*  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	 *  newly negotiated).  An iSCSI target MUST perform integrity checking	 *  before the new parameters take effect.  An initiator MAY perform	 *  integrity checking."	 */	if (retval == 0) {	/* not a redirection */		check_integrity_rules(p_param_tbl, *tsih);		/*  Draft 20 Section 12.1 HeaderDigest and DataDigest		 *  "When Initiator and Target agree on a digest, 		 *  this digest MUST be used for every PDU in 		 *  Full Feature Phase."		 */		set_digestflags(p_param_tbl, connection_flags);		/*  if we (the initiator) sent a 		 * MaxRecvDataSegmentLength (draft 18)		 *  value to the target, we have to now start using it in FFP		 */		set_connection_recv_length(p_param_tbl, max_recv_length);		if (*tsih == 0) {			/* first login phase of a new session 			 * completed successfully,			 * pass back the tsih assigned to this session 			 * by the target 			 */			*tsih = be16_to_cpu(((struct iscsi_targ_login_rsp *)					    inputpdu)->tsih);		}	}	/* free up memory allocated for any unknown keys we received */	while (unknown_key_list != NULL) {		if (!unknown_key_list->processed) {			TRACE_ERROR("unknown key \"%s=%s\"\n",				    unknown_key_list->keyname,				    unknown_key_list->keyvalue);		}		uptr = unknown_key_list->next;		my_kfree((void **) &unknown_key_list->keyvalue, "Key Value");		my_kfree((void **) &unknown_key_list->keyname, "Key Name");		my_kfree((void **) &unknown_key_list, "Unknown key");		unknown_key_list = uptr;	}	/* Free all allocated memory */	my_kfree((void **) &outputpdu->text, "Output text");	my_kfree((void **) &inputpdu->text, "Input text");	my_kfree((void **) &outputpdu, "Output pdu");	my_kfree((void **) &inputpdu, "Input pdu");      out:	TRACE(TRACE_ENTER_LEAVE,	      "Leave initiator_parameter_negotiate, retval %d\n", retval);	return retval;}

⌨️ 快捷键说明

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