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

📄 initiator_negotiate.c

📁 iscsi源代码 UNH的progect 有initiator端和target端的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/*	common/initiator_negotiate.c * *	This defines the functions used in the Login phase *	by the iSCSI initiator for parameter negotiation * *	vi: set autoindent tabstop=8 shiftwidth=4 : * *	This file contains auxilliary functions for iscsi initiator  *	code that are responsible for dealing with error recovery. * *	Copyright (C) 2001-2003 InterOperability Lab (IOL) *	University of New Hampshier (UNH) *	Durham, NH 03824 * *	This program is free software; you can redistribute it and/or modify *	it under the terms of the GNU General Public License as published by *	the Free Software Foundation; either version 2, or (at your option) *	any later version. * *	This program is distributed in the hope that it will be useful, *	but WITHOUT ANY WARRANTY; without even the implied warranty of *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *	GNU General Public License for more details. * *	You should have received a copy of the GNU General Public License *	along with this program; if not, write to the Free Software *	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, *	USA. * *	The name of IOL and/or UNH may not be used to endorse or promote  *	products derived from this software without specific prior  * 	written permission.*//*	 * The code for redirection during login is based on code first written * by Scott Cranston of Equal Logic (scranston@equallogic.com).*//* * Converted to:  indent -kr -i8 -ts8 -sob -l80 -ss -bs -psl on 10/8/2003 . *  */#include <linux/kernel.h>#include <linux/types.h>#include <linux/slab.h>#include <linux/ctype.h>#include <linux/string.h>#include <linux/socket.h>#include <linux/ip.h>#include "iscsi_common.h"#include "debug.h"#include "my_memory.h"/* chap support - CHONG */#include "../security/chap/chap.h"#include "../security/srp/srp.h"#include "../security/misc/misc_func.h"#include "text_param.h"#include "initiator_negotiate.h"/*	check the correctness of target ip address which should be in format of *	TargetAddress=domainname[:port][,portal-group-tag] */intcheck_target_address(char *value, int when){	int retval = 0;	return retval;}/*	when get here, we already know that opcode is login response. *	returns 1 if valid redirection, 0 if other success, -1 if any error */static intcheck_login_response(struct generic_pdu *inputpdu,		     struct generic_pdu *outputpdu){	int retval = 0;	char *tsix;	struct iscsi_targ_login_rsp *login_rsp;	struct iscsi_init_login_cmnd *login_req;	TRACE(TRACE_ENTER_LEAVE, "Enter check_login_response\n");	tsix = "TSIH";	login_rsp = (struct iscsi_targ_login_rsp *) inputpdu;	login_req = (struct iscsi_init_login_cmnd *) outputpdu;	/* check that reserved fields in the login response are all zero */	if ((login_rsp->opcode & OLD_X_BIT)	    || (login_rsp->flags & (W_BIT | BRO_BIT))	    || login_rsp->rsvd1 || login_rsp->rsvd2 || login_rsp->rsvd3) {		TRACE_WARNING		    ("reserved fields in Login Response header not all 0\n");	}	if ((inputpdu->status_class != STAT_CLASS_SUCCESS)) {		/* the target sent a login reject */		TRACE_ERROR		      ("Login Response with non-zero StatusClass 0x%02x, "		      "StatusDetail 0x%02x\n", inputpdu->status_class,		      inputpdu->status_detail);		/*  Draft 20, Section 5.3.1 Login Phase Start		 */		if ((inputpdu->flags & T_BIT)		    || (inputpdu->flags & CSG) != 0		    || (inputpdu->flags & NSG) != 0) {			/* protocol error */			TRACE_ERROR			    ("non-zero Status-Class MUST have T=0, CSG=0 & NSG=0\n");			retval = -1;		}		if (inputpdu->status_class == STAT_CLASS_REDIRECTION) {			/* target redirecting login to different IP 				address/Port number */			if (inputpdu->status_detail <			    STAT_DETAIL_TARG_MOVED_TEMP			    && inputpdu->status_detail >			    STAT_DETAIL_TARG_MOVED_PERM) {				TRACE_ERROR				    ("invalid Status Detail 0x%02x for Redirection\n",				     inputpdu->status_detail);				retval = -1;			} else {				/* valid redirection detail, there 				 * should be a TargetAddress				 * key attached to this PDU containing 			 	 * the redirection info 				 */				retval = 1;			}		} else if (inputpdu->status_class == STAT_CLASS_INITIATOR) {			/* Initiator Error (not a format error) */			if (inputpdu->status_detail >			    STAT_DETAIL_INVALID_DURING_LOGIN) {				TRACE_ERROR				    ("invalid Status Detail 0x%02x for Initiator Error\n",				     inputpdu->status_detail);			}			retval = -1;		} else if (inputpdu->status_class == STAT_CLASS_TARGET) {			/* Target Error */			if (inputpdu->status_detail >			    STAT_DETAIL_OUT_OF_RESOURCE) {				TRACE_ERROR				    ("invalid Status Detail 0x%02x for Target Error\n",				     inputpdu->status_detail);			}			retval = -1;		} else {			/* Bad status class */			TRACE_ERROR("invalid Status Class 0x%02x\n",				    inputpdu->status_class);			retval = -1;		}	}	/* status_class is 0, status_detail should also be 0 */	else if ((inputpdu->status_detail != 0x0)) {		TRACE_ERROR("Login Response with zero StatusClass but non-zero "			    "StatusDetail 0x%02x\n", inputpdu->status_detail);		retval = -1;	}	else if ((inputpdu->flags & CSG) != (outputpdu->flags & CSG)) {		/* target's state not the same as initiator's state */		/*  protocol error */		TRACE_ERROR		    ("inconsistant state! Target in state %d, initiator in %d\n",		     (inputpdu->flags & CSG) >> CSG_SHIFT,		     (outputpdu->flags & CSG) >> CSG_SHIFT);		retval = -1;	}	else if (memcmp(login_rsp->isid, login_req->isid, 6) != 0) {		/* target changed the isid */		/*  protocol error */		TRACE_ERROR("target changed the isid\n");		retval = -1;	}	else if (!(inputpdu->flags & T_BIT)) {		/* target does not want to change stage */		if (inputpdu->flags & NSG) {			/* check reserved field, but only give 			 * warning if we find errors 			 */			if (TRACE_TEST(TRACE_ISCSI)) {			      TRACE_WARNING("NSG %d should be 0 when T bit is 0\n",			      inputpdu->flags & NSG);			}		}	}	/* input T bit is set to 1, target wants to change stage */	else if (!(outputpdu->flags & T_BIT)) {		/* but initiator did not want to change stage yet */		/*  protocol error */		TRACE_ERROR		    ("Login Response with T bit set but Initiator's T bit "		     "not set \n");		retval = -1;	}	else if ((inputpdu->flags & NSG) <=		 ((inputpdu->flags & CSG) >> CSG_SHIFT)		 || (inputpdu->flags & NSG) == NSG2) {		/* target wants to go to an illegal stage */		/*  protocol error */		TRACE_ERROR("target trying to change to illegal stage %d\n",			    inputpdu->flags & NSG);		retval = -1;	}	else if ((inputpdu->flags & NSG) == NSG3) {		/* target going to FFP, can only do this if initiator 		 * asked for it 		 *  Draft 20, Section 5.3 Login Phase		 */		if ((outputpdu->flags & NSG) != NSG3) {			TRACE_ERROR			    ("target trying to change to FFP, initiator wanted "			     "to change to Operational stage only\n");			retval = -1;		} else if (login_rsp->tsih == 0) {	/* protocol error */			TRACE_ERROR			    ("target's final login response has %s = 0\n",			     tsix);			retval = -1;		}	} else if (login_req->tsih != login_rsp->tsih) {		TRACE_ERROR("target changed initiator's %s from %u to %u\n",			    tsix, be16_to_cpu(login_req->tsih),			    be16_to_cpu(login_rsp->tsih));	}	TRACE(TRACE_ENTER_LEAVE, "Leave check_login_response retval = %d\n",	      retval);	return retval;}/*	Called to send a Login PDU already set up in outputpdu *	and then to read back a login response into inputpdu *	Returns 1 on redirection, 0 on other success, -1 on any error */static intwrite_and_read(struct socket *sock,	struct generic_pdu *inputpdu,	struct generic_pdu *outputpdu,	int *target_version_max, 	int *target_version_active, 	__u32 flags){	int padding = 0;	int retval = 0;	__u32 size;	TRACE(TRACE_ENTER_LEAVE, "Enter write_and_read\n");	/* send output */	if (iscsi_send_msg(sock, outputpdu, flags) < 0) {		TRACE(TRACE_DEBUG, "iscsi_send_msg failed\n");		return -1;	}	/* After sending the outputpdu, reset it's text len to 0 */	outputpdu->text_length = 0;	/* wait for input from target */	size = ISCSI_HDR_LEN;	/* NO packets sent or received during login will have 	 * digests of any kind 	 */	if (iscsi_recv_msg(sock, size, (char *) inputpdu, flags) < 0) {		TRACE(TRACE_DEBUG, "iscsi_recv_msg failed\n");		return -1;	}	/* Also get the text associated with it */	inputpdu->text_length = be32_to_cpu(inputpdu->length);	/* Include the padding bytes too */	padding = inputpdu->text_length + ((-inputpdu->text_length) & 3);	if (inputpdu->text_length > MAX_TEXT_LEN) {		TRACE_ERROR		    ("DSL %u greater than default MaxRecvDataSegmentLength %d\n",		     inputpdu->text_length, MAX_TEXT_LEN);		return -1;	}	if (padding > 0	    && iscsi_recv_msg(sock, padding, inputpdu->text, flags) < 0) {		TRACE(TRACE_DEBUG, "iscsi_recv_msg failed\n");		return -1;	}	if ((inputpdu->opcode & ISCSI_OPCODE) == ISCSI_TARG_LOGIN_RSP) {		/* as expected, this is a login response, check it */		TRACE(TRACE_ISCSI, "Got Login Rsp, ITT %u\n",		      ntohl(inputpdu->init_task_tag));		if (TRACE_TEST(TRACE_ISCSI_FULL))			print_targ_login_rsp((struct iscsi_targ_login_rsp *)					     inputpdu);		/* Check the initiator task tag */		if (inputpdu->init_task_tag != outputpdu->init_task_tag) {			if (TRACE_TEST(TRACE_ISCSI)) {			      TRACE_WARNING("received init_task_tag = %d, "					"expected %d\n",					be32_to_cpu(inputpdu->init_task_tag),					be32_to_cpu(outputpdu->init_task_tag));			}		}		/* Check recved version_max and version_active fields 		 * for consistency 		 */		if (inputpdu->version_max < inputpdu->version_active) {			if (TRACE_TEST(TRACE_ISCSI)) {			      TRACE_WARNING("received version_max = 0x%02x "			      "less than received version_active 0x%02x\n",			      inputpdu->version_max, inputpdu->version_active);			}		}		/* The received version_max and version_active fields 		 * must not change 		 */		/*  Draft 20, Section 10.13.1 Version-max (for Login Response)		 *  "All Login responses within the Login Phase MUST 		 *  carry the same Version-max.		 *		 *  Draft 20, Section 10.13.2 Version-active (for 		 *  Login Response)		 *  "All Login responses within the Login Phase 		 *  MUST carry the same Version-active.		 *  The initiator MUST use the value presented as 		 *  response to the first login request."		 */		if (*target_version_max < 0) {			/* first login response, just remember its values */			*target_version_max = inputpdu->version_max;			*target_version_active = inputpdu->version_active;		} else if (*target_version_max != inputpdu->version_max) {			if (TRACE_TEST(TRACE_ISCSI)) {			      TRACE_WARNING("received version_max = 0x%02x "			      "differs from received version_max 0x%02x\n",			      inputpdu->version_max, *target_version_max);			}		} else if (*target_version_active != inputpdu->version_active) {			if (TRACE_TEST(TRACE_ISCSI)) {			      TRACE_WARNING("received version_active = 0x%02x"			      " differs from received version_active 0x%02x\n",			      inputpdu->version_active, *target_version_active);			}		}		/*  Check the version_active field to see if we can use it		 *  For now, we send version_min == version_max, so 		 *  target has no choice		 */		if (inputpdu->version_active != outputpdu->version_active) {			TRACE_ERROR			    ("received version_active = 0x%02x, expected 0x%02x\n",			     inputpdu->version_active,			     outputpdu->version_active);			retval = -1;		}		/* Check the C bit, which we do not use yet */		else if (inputpdu->flags & C_BIT) {				/* C bit is set in Login Response */			/*  Draft 20, Section 10.13.7 C (Continue) Bit			 *  "A Login Response with the C bit set must have the			 *  T bit set to 0."			 */			if (inputpdu->flags & T_BIT) {				TRACE_ERROR				    ("C=1 in Login Response requires T=0, not T=1\n");			} else {	/* for now */				TRACE_ERROR				    ("C=1 in Login Response not implemented yet\n");			}			retval = -1;		} else			retval = check_login_response(inputpdu, outputpdu);	}	else if ((inputpdu->opcode & ISCSI_OPCODE) == ISCSI_TARG_RJT) {		/* protocol error */		TRACE_ERROR("got Reject PDU\n");		print_targ_rjt((struct iscsi_targ_rjt *) inputpdu);		retval = -1;	}	else {		TRACE_ERROR("received opcode = 0x%02x, expected 0x%02x\n",			    inputpdu->opcode & ISCSI_OPCODE,			    ISCSI_TARG_LOGIN_RSP);		retval = -1;	/* this is fatal */	}	TRACE(TRACE_ENTER_LEAVE, "Leave write_and_read, retval %d\n", retval);	return retval;}/*	states to drive authentication steps during security phase */enum security_steps {	ss_initial,             // 0	ss_find_chap_a_i_c,	// 1	ss_find_chap_n_r,	// 2	ss_find_srp_g_s,	// 3	ss_find_srp_b,		// 4	ss_find_srp_h,		// 5	ss_done,		// 6	ss_error		// 7};/* forward defs */intss_initial_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 parameter_type *auth_p,	struct generic_pdu *inputpdu,	struct generic_pdu *outputpdu);intss_find_chap_a_i_c_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 parameter_type *auth_p,	struct generic_pdu *inputpdu,	struct generic_pdu *outputpdu,	__u32 * got_keys,	__u32 * got_value);intss_find_chap_n_r_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,        __u32 * got_value,	int *count);intss_find_srp_g_s_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 );intss_find_srp_b_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 );intss_find_srp_h_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);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,

⌨️ 快捷键说明

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