LibIpv6_Interface_Functions.ttcn 34.9 KB
Newer Older
/*
 *	@author 	STF 276
 *  @version 	$Id$
 *	@desc		This module specifies functions definitions
 *              based on the IPv6 meta message type.  
 *  
 */
 module LibIpv6_Interface_Functions {

	//LibCommon
	import from LibCommon_BasicTypesAndValues all;
	import from LibCommon_DataStrings all;
	import from LibCommon_VerdictControl { type FncRetCode };
	//LibIpv6
	import from LibIpv6_Interface_TypesAndValues all;
	import from LibIpv6_Interface_Templates all;
	import from LibIpv6_ModuleParameters all;
	import from LibIpv6_ExternalFunctions all;
	import from LibIpv6_CommonRfcs_Functions all;
	import from LibIpv6_CommonRfcs_TypesAndValues all;
	
group rfc2460Root_Functions {
	
	group ipv6Packets {	

	/*
	 * @desc 	This sends a General IPv6 packet
	 *			from an IPv6 node to any NUT.
	 *			A General IPv6 packet is used in the case where only Extension headers
	 *			need to be sent.
	 * @remark  Time limit is defined by module parameter PX_TAC (see comp type)
	 * @param 	p_msg MIPHeader to be sent	
	 * @return 	execution status
	*/
	function f_sendGeneralIpv6(template Ipv6Packet p_msg)
	runs on LibIpv6Node
	return FncRetCode {
		//Variables
		var Ipv6Packet v_ipPkt;
		v_ipPkt := valueof(p_msg);
		//calc payloadLen
		v_ipPkt.ipv6Hdr.payloadLength := fx_payloadLength (v_ipPkt);
		
		//set extensionHeaders
		if(f_setExtensionHeaders(	v_ipPkt,
									v_ipPkt.ipv6Hdr.sourceAddress,
									v_ipPkt.ipv6Hdr.destinationAddress) != e_success) {
			log(" **** f_sendGeneralIpv6: Error when calculating length of extension headers ****");
			return e_error;
		}

		//send
		ipPort.send(v_ipPkt);

		return e_success;
	}//end f_sendGeneralIpv6

	group extHdrFns {

	/*
	 * @desc 	This goes through the extension header list and calculates length, checksum
	 *			and other specific functions of the different extension headers
	 * @param 	p_srcAddr Source Address of IPv6 packet
	 * @param 	p_dstAddr Dst Address of IPv6 packet
	 * @param 	p_extHdrList Extension Header List
	 * @return 	execution status 
	*/
	function f_setExtensionHeaders(	inout Ipv6Packet p_ipv6Packet,
									in Ipv6Address p_srcAddr,
									in Ipv6Address p_dstAddr)
	runs on LibIpv6Node
	return FncRetCode {
		var FncRetCode v_ret := e_success;
		var UInt8 i, j;
		var Ipv6Address v_homeAddress := c_16ZeroBytes;
		var UInt8 v_nrOfTunnelHdr := 0;
berge's avatar
berge committed
		var Ipv6Address v_pseudoSrcAddr := c_16ZeroBytes;
		var Ipv6Address v_pseudoDstAddr := c_16ZeroBytes;
		var boolean v_loop := true;
		var boolean v_checkPayload := true;		
		var Ipv6Packet v_originalIpv6Packet;
		var Ipv6Packet v_activeIpv6Packet := p_ipv6Packet;
		v_pseudoDstAddr := v_activeIpv6Packet.ipv6Hdr.destinationAddress;
		v_pseudoSrcAddr := v_activeIpv6Packet.ipv6Hdr.sourceAddress;
		
		//calc payloadLen
		p_ipv6Packet.ipv6Hdr.payloadLength := fx_payloadLength (p_ipv6Packet);

		if (ispresent(v_activeIpv6Packet.extHdrList)) {
			for (i:=0; i<sizeof(v_activeIpv6Packet.extHdrList) and v_loop ;i:=i+1) {
				
				// Process Home Address Destination Option
				if (ischosen(v_activeIpv6Packet.extHdrList[i].destinationOptionHeader)) {
					for (j:=0; j<sizeof(v_activeIpv6Packet.extHdrList[i].destinationOptionHeader.destOptionList);j:=j+1) {
						if (ischosen(v_activeIpv6Packet.extHdrList[i].destinationOptionHeader.destOptionList[j].homeAddressOption)) {
							v_pseudoSrcAddr := v_activeIpv6Packet.extHdrList[i].destinationOptionHeader.destOptionList[j].homeAddressOption.homeAddress;
						}
					}
				// Proccess Routing Header Type 2			
				else if (ischosen(v_activeIpv6Packet.extHdrList[i].routingHeader) and (v_activeIpv6Packet.extHdrList[i].routingHeader.routingType == c_routeHdrType2)) {
					if (ischosen(v_activeIpv6Packet.extHdrList[i].routingHeader.routingHeaderData.rtHdrDataHomeAddress)) {
						v_pseudoDstAddr := v_activeIpv6Packet.extHdrList[i].routingHeader.routingHeaderData.rtHdrDataHomeAddress;
					}
				// Process Mobile Header			
				else if (ischosen(v_activeIpv6Packet.extHdrList[i].mobileHeader)) {
					v_ret := f_setMobileHeader(	v_activeIpv6Packet.ipv6Hdr.sourceAddress,
												v_activeIpv6Packet.ipv6Hdr.destinationAddress,
												v_pseudoSrcAddr,					
												v_pseudoDstAddr,
												v_activeIpv6Packet.extHdrList[i].mobileHeader);
					
				//	update packet payloadLen
				p_ipv6Packet.ipv6Hdr.payloadLength := fx_payloadLength (p_ipv6Packet);
				// Process Tunneled Header
				else if (ischosen(v_activeIpv6Packet.extHdrList[i].tunneledIpv6)) {
					v_nrOfTunnelHdr := v_nrOfTunnelHdr + 1;
		
					//Build original packet
					v_originalIpv6Packet.ipv6Hdr := v_activeIpv6Packet.extHdrList[i].tunneledIpv6;
					for (j:=0; (i+j+1)<sizeof(v_activeIpv6Packet.extHdrList) ;j:=j+1) {
						v_originalIpv6Packet.extHdrList[j] := v_activeIpv6Packet.extHdrList[i+1];	
					}
					if (ispresent(v_activeIpv6Packet.ipv6Payload)) {
						v_originalIpv6Packet.ipv6Payload := v_activeIpv6Packet.ipv6Payload;	
					}
					v_originalIpv6Packet.ipv6Hdr.payloadLength := fx_payloadLength (v_originalIpv6Packet);
mullers's avatar
mullers committed

					f_setExtensionHeaders(	v_originalIpv6Packet,
											v_originalIpv6Packet.ipv6Hdr.sourceAddress,
											v_originalIpv6Packet.ipv6Hdr.destinationAddress);	
					v_originalIpv6Packet.ipv6Hdr.payloadLength := fx_payloadLength (v_originalIpv6Packet);											
			
					// include recursion results
					v_activeIpv6Packet.extHdrList[i].tunneledIpv6.payloadLength := v_originalIpv6Packet.ipv6Hdr.payloadLength;
					if (ispresent(v_originalIpv6Packet.extHdrList)) {
						for (j:=0; j<sizeof(v_originalIpv6Packet.extHdrList) ;j:=j+1) {
							v_activeIpv6Packet.extHdrList[i+1] := v_originalIpv6Packet.extHdrList[j];	
						}			
					}
					if (ispresent(v_originalIpv6Packet.ipv6Payload)) {
						v_activeIpv6Packet.ipv6Payload := v_originalIpv6Packet.ipv6Payload;	
					}
					
					v_checkPayload := false;
					v_loop := false;				
				}
				//Process ESP Header
				else if (ischosen(v_activeIpv6Packet.extHdrList[i].espHeader)) {
	
					v_ret := f_getOriginalIpv6Packet(
									v_activeIpv6Packet,
									v_activeIpv6Packet.extHdrList[i].espHeader,
									v_originalIpv6Packet);
					if (v_ret == e_success) {
						f_setExtensionHeaders(	v_originalIpv6Packet,
												v_originalIpv6Packet.ipv6Hdr.sourceAddress,
												v_originalIpv6Packet.ipv6Hdr.destinationAddress);
	
						v_loop := false;
					}
		if (v_checkPayload==true and ispresent(v_activeIpv6Packet.ipv6Payload)) {
			v_originalIpv6Packet := v_activeIpv6Packet;
			v_originalIpv6Packet.ipv6Hdr.sourceAddress := v_pseudoSrcAddr;
			v_originalIpv6Packet.ipv6Hdr.destinationAddress := v_pseudoDstAddr;
			
			v_ret := f_calcIpv6PayloadChecksum(v_originalIpv6Packet);
			
			v_originalIpv6Packet.ipv6Hdr.sourceAddress := v_activeIpv6Packet.ipv6Hdr.sourceAddress;
			v_originalIpv6Packet.ipv6Hdr.destinationAddress := v_activeIpv6Packet.ipv6Hdr.destinationAddress;
			v_activeIpv6Packet := v_originalIpv6Packet;
		p_ipv6Packet := v_activeIpv6Packet;

berge's avatar
berge committed
		return v_ret;
mullers's avatar
mullers committed

	}//end f_setExtensionHeaders
		
	}//end group extHdrFns

	function f_calcIpv6PayloadChecksum( inout Ipv6Packet p_ipv6Packet)
	return FncRetCode {
		
		if(ischosen(p_ipv6Packet.ipv6Payload.echoReplyMsg)) {
			if(p_ipv6Packet.ipv6Payload.echoReplyMsg.checksum == c_2ZeroBytes) {
				//calc checksum
				p_ipv6Packet.ipv6Payload.echoReplyMsg.checksum := fx_icmpv6Checksum(p_ipv6Packet);
			}
		}
		else if(ischosen(p_ipv6Packet.ipv6Payload.echoRequestMsg)) {
			if(p_ipv6Packet.ipv6Payload.echoRequestMsg.checksum == c_2ZeroBytes) {
				//calc checksum
				p_ipv6Packet.ipv6Payload.echoRequestMsg.checksum := fx_icmpv6Checksum(p_ipv6Packet);
			}
		}
		else if(ischosen(p_ipv6Packet.ipv6Payload.nbrAdvMsg)) {
			if(p_ipv6Packet.ipv6Payload.nbrAdvMsg.checksum == c_2ZeroBytes) {
				//calc checksum
				p_ipv6Packet.ipv6Payload.nbrAdvMsg.checksum := fx_icmpv6Checksum(p_ipv6Packet);
			}
		}
		else if(ischosen(p_ipv6Packet.ipv6Payload.nbrSolMsg)) {
			if(p_ipv6Packet.ipv6Payload.nbrSolMsg.checksum == c_2ZeroBytes) {
				//calc checksum
				p_ipv6Packet.ipv6Payload.nbrSolMsg.checksum := fx_icmpv6Checksum(p_ipv6Packet);
			}
		}
		else if(ischosen(p_ipv6Packet.ipv6Payload.routerAdvMsg)) {
			if(p_ipv6Packet.ipv6Payload.routerAdvMsg.checksum == c_2ZeroBytes) {
				//calc checksum
				p_ipv6Packet.ipv6Payload.routerAdvMsg.checksum := fx_icmpv6Checksum(p_ipv6Packet);
			}
		}
		else if(ischosen(p_ipv6Packet.ipv6Payload.routerSolMsg)) {
			if(p_ipv6Packet.ipv6Payload.routerSolMsg.checksum == c_2ZeroBytes) {
				//calc checksum
				p_ipv6Packet.ipv6Payload.routerSolMsg.checksum := fx_icmpv6Checksum(p_ipv6Packet);
			}
		}
		else if(ischosen(p_ipv6Packet.ipv6Payload.redirectMsg)) {
			if(p_ipv6Packet.ipv6Payload.redirectMsg.checksum == c_2ZeroBytes) {
				//calc checksum
				p_ipv6Packet.ipv6Payload.redirectMsg.checksum := fx_icmpv6Checksum(p_ipv6Packet);
			}
		}
		else if(ischosen(p_ipv6Packet.ipv6Payload.parameterProblemMsg)) {
			if(p_ipv6Packet.ipv6Payload.parameterProblemMsg.checksum == c_2ZeroBytes) {
				//calc checksum
				p_ipv6Packet.ipv6Payload.parameterProblemMsg.checksum := fx_icmpv6Checksum(p_ipv6Packet);
			}
		}
		else if(ischosen(p_ipv6Packet.ipv6Payload.timeExceededMsg)) {
			if(p_ipv6Packet.ipv6Payload.timeExceededMsg.checksum == c_2ZeroBytes) {
				//calc checksum
				p_ipv6Packet.ipv6Payload.timeExceededMsg.checksum := fx_icmpv6Checksum(p_ipv6Packet);
			}
		}
		else if(ischosen(p_ipv6Packet.ipv6Payload.packetTooBigMsg)) {
			if(p_ipv6Packet.ipv6Payload.packetTooBigMsg.checksum == c_2ZeroBytes) {
				//calc checksum
				p_ipv6Packet.ipv6Payload.packetTooBigMsg.checksum := fx_icmpv6Checksum(p_ipv6Packet);
			}
		}
		else if(ischosen(p_ipv6Packet.ipv6Payload.destinationUnreachableMsg)) {
			if(p_ipv6Packet.ipv6Payload.destinationUnreachableMsg.checksum == c_2ZeroBytes) {
				//calc checksum
				p_ipv6Packet.ipv6Payload.destinationUnreachableMsg.checksum := fx_icmpv6Checksum(p_ipv6Packet);
			}
		}
		else if(ischosen(p_ipv6Packet.ipv6Payload.mobileRouterAdvMsg)) {
			if(p_ipv6Packet.ipv6Payload.mobileRouterAdvMsg.checksum == c_2ZeroBytes) {
				//calc checksum
				p_ipv6Packet.ipv6Payload.mobileRouterAdvMsg.checksum := fx_icmpv6Checksum(p_ipv6Packet);
			}
		}
		else if(ischosen(p_ipv6Packet.ipv6Payload.homeAgentAddrDiscRequestMsg)) {
			if(p_ipv6Packet.ipv6Payload.homeAgentAddrDiscRequestMsg.checksum == c_2ZeroBytes) {
				//calc checksum
				p_ipv6Packet.ipv6Payload.homeAgentAddrDiscRequestMsg.checksum := fx_icmpv6Checksum(p_ipv6Packet);
			}
		}
		else if(ischosen(p_ipv6Packet.ipv6Payload.homeAgentAddrDiscReplyMsg)) {
			if(p_ipv6Packet.ipv6Payload.homeAgentAddrDiscReplyMsg.checksum == c_2ZeroBytes) {
				//calc checksum
				p_ipv6Packet.ipv6Payload.homeAgentAddrDiscReplyMsg.checksum := fx_icmpv6Checksum(p_ipv6Packet);
			}
		}
		else if(ischosen(p_ipv6Packet.ipv6Payload.mobilePrefixSolMsg)) {
			if(p_ipv6Packet.ipv6Payload.mobilePrefixSolMsg.checksum == c_2ZeroBytes) {
				//calc checksum
				p_ipv6Packet.ipv6Payload.mobilePrefixSolMsg.checksum := fx_icmpv6Checksum(p_ipv6Packet);
			}
		}
		else if(ischosen(p_ipv6Packet.ipv6Payload.mobilePrefixAdvMsg)) {
			if(p_ipv6Packet.ipv6Payload.mobilePrefixAdvMsg.checksum == c_2ZeroBytes) {
				//calc checksum
				p_ipv6Packet.ipv6Payload.mobilePrefixAdvMsg.checksum := fx_icmpv6Checksum(p_ipv6Packet);
			}
		}
		else if(ischosen(p_ipv6Packet.ipv6Payload.otherIcmpv6Msg)) {
			if(p_ipv6Packet.ipv6Payload.otherIcmpv6Msg.checksum == c_2ZeroBytes) {
				//calc checksum
				p_ipv6Packet.ipv6Payload.otherIcmpv6Msg.checksum := fx_icmpv6Checksum(p_ipv6Packet);
			}
		}
		
		return e_success;

	}//end f_calcIpv6PayloadChecksum


    } //end group ipv6Packets
	
}//end group rfc2460Root_Functions

group rfc3775Mipv6_ExtHdrFunctions {

	/*
	 * @desc 	This goes through the Mip header and calculates length, checksum
	 *			and other specific functions of the different messages.
	 *			This function is used when sending messages.
	 * @param 	p_msg ExtensionHeaderList to be treated	
	 * @return 	execution status 
	*/
berge's avatar
berge committed
	function f_setMobileHeader(	in Ipv6Address p_srcAddr,
								in Ipv6Address p_dstAddr,
								in Ipv6Address p_pseudoSrcAddr, 
								in Ipv6Address p_pseudoDstAddr, 	
								inout MobileHeader p_mobileHeader)
	runs on LibIpv6Node
	return FncRetCode {
		var MobileHeader v_mobileHeader := valueof(p_mobileHeader);
		var Ipv6Address v_homeAddress := c_16ZeroBytes ;

		//if (ischosen(p_mobileHeader.mobileMessage.homeTestInit)) {
			//calc homeInitCookie
			//p_mobileHeader.mobileMessage.homeTestInit.homeInitCookie := f_createInitCookie();
		//else if (ischosen(p_mobileHeader.mobileMessage.homeTest)) {//CNSimu sends this message
		//else if (ischosen(p_mobileHeader.mobileMessage.careOfTestInit) and (PX_TEST_IPSEC == true)) {
		//SMU TODO
		//}
		//else if (ischosen(p_mobileHeader.mobileMessage.careOfTest) and (PX_TEST_IPSEC == true)) {
		//SMU TODO
		//}
		if (ischosen(p_mobileHeader.mobileMessage.bindingUpdateMsg)) {//Authorization data is only needed for BU sent to CN=IUT
			var UInt8 v_position := 0;
			//Concept of including bindingAuthentication
			// specifiy on template level all options
			// 1) if authenticator == c_20ZeroBytes then value is calculated in f_setMobileHeader
			// 2) if authenticator != c_20ZeroBytes then no value is calculated in f_setMobileHeader,
			//     because it's assumed that the correct value was set on template level
			// 3) same applies to nonceIndex etc

			// Process Nonce Indices
			if (f_isPresentNonceIndices(p_mobileHeader.mobileMessage.bindingUpdateMsg, v_position) == e_success) {

				// Fill Home Nonce Index only when set to c_uInt16Zero
				if (p_mobileHeader.mobileMessage.bindingUpdateMsg.mobileOptions[v_position].mobileOptNonceIndices.homeNonceIndex == c_uInt16Zero ) {
					if(vc_mobileSec.mnSimuParams.receivedHomeNonceIndex != c_uInt16Zero) {
							p_mobileHeader.mobileMessage.bindingUpdateMsg.mobileOptions[v_position].mobileOptNonceIndices.homeNonceIndex
							:= vc_mobileSec.mnSimuParams.receivedHomeNonceIndex;
					}
					else {
						log("f_setMobileHeader: Info: NonceIndices included in Binding Update, but mnSimuParams.receivedHomeNonceIndex not initialized");
					}
				}
				
				// Fill Care-Of Nonce Index only when set to c_uInt16Zero
				if (p_mobileHeader.mobileMessage.bindingUpdateMsg.mobileOptions[v_position].mobileOptNonceIndices.careOfNonceIndex == c_uInt16Zero) {
					if(vc_mobileSec.mnSimuParams.receivedCareOfNonceIndex != c_uInt16Zero) {
							p_mobileHeader.mobileMessage.bindingUpdateMsg.mobileOptions[v_position].mobileOptNonceIndices.careOfNonceIndex
							:= vc_mobileSec.mnSimuParams.receivedCareOfNonceIndex;
					}
					else {
						log("f_setMobileHeader: Info: NonceIndices included in Binding Update, but mnSimuParams.receivedCareOfNonceIndex not initialized");
			} // end Process Nonce Indices
				
			if (f_isPresentBindingAuthorizationDataOption(p_mobileHeader.mobileMessage.bindingUpdateMsg, v_position) == e_success) {
				if(vc_mobileSec.mnSimuParams.receivedHomeKeygenToken != c_64ZeroBits
					and vc_mobileSec.mnSimuParams.receivedCareOfKeygenToken != c_64ZeroBits) {

						// kbm is different if BU is sent for de-registration				
						if (p_mobileHeader.mobileMessage.bindingUpdateMsg.lifeTime != 0) {
							vc_mobileSec.mnSimuParams.kbm := fx_mac(		e_sha1, c_1ZeroByte,
																			bit2oct(vc_mobileSec.mnSimuParams.receivedHomeKeygenToken)
																			& bit2oct(vc_mobileSec.mnSimuParams.receivedCareOfKeygenToken));
						}
						else {
							vc_mobileSec.mnSimuParams.kbm := fx_mac(		e_sha1, c_1ZeroByte,
																			bit2oct(vc_mobileSec.mnSimuParams.receivedHomeKeygenToken));	
						}
berge's avatar
berge committed
											
						//set Authenticator option with dummy Authenticator
						p_mobileHeader.mobileMessage.bindingUpdateMsg.mobileOptions[v_position].mobileBindingAuthorizationData := {
														mobileOptType := 5,
														mobileOptLen := 12,
														authenticator := c_12ZeroBytes}
																		
						//calculate the mipHeaderLength over the dummy Authenticator
berge's avatar
berge committed
						//modified by AMB to easily send packets with wrong mobileHdrLen
						//calc mobileHeaderLen
						if (p_mobileHeader.headerLen == c_uInt8Zero ) {
							p_mobileHeader.headerLen := fx_mipHeaderLength(p_mobileHeader) ;
						}
						
						//set Authenticator to omit in order to calc the authenticator
						p_mobileHeader.mobileMessage.bindingUpdateMsg.mobileOptions[v_position].mobileBindingAuthorizationData.authenticator := omit;
						// compute authenticator
berge's avatar
berge committed
						p_mobileHeader.mobileMessage.bindingUpdateMsg.mobileOptions[v_position].mobileBindingAuthorizationData.authenticator 
								 := fx_mac(	e_hmac_sha1_96, vc_mobileSec.mnSimuParams.kbm,
berge's avatar
berge committed
																		p_srcAddr //careOfaddr 
																		& p_dstAddr //cnAddr
					log("f_setMobileHeader: Error: BindingAuthorizationDataOption included in Binding Update, but receivedHomeKeygenToken/receivedCareOfKeygenToken not initialized");
					return e_error;	
				}
	//	else if (ischosen(p_mobileHeader.mobileMessage.bindingAck) and (PX_TEST_IPSEC == true)) {
		//SMU TODO
		//}
		// calc mobileHeaderLen only when set to c_uInt8Zero
berge's avatar
berge committed
		if (p_mobileHeader.headerLen == c_uInt8Zero ) {
			p_mobileHeader.headerLen := fx_mipHeaderLength(p_mobileHeader);
		}
		// calc mipChecksum only when set to c_2ZeroBytes
berge's avatar
berge committed
		if (p_mobileHeader.checksum == c_2ZeroBytes) {
berge's avatar
berge committed
			p_mobileHeader.checksum := fx_mipHeaderChecksum ( 	p_pseudoSrcAddr, 
																p_pseudoDstAddr, 
																p_mobileHeader);
berge's avatar
berge committed
		}
berge's avatar
berge committed
	function f_checkAuthenticator (	in Ipv6Address p_srcAddr,
									in Ipv6Address p_dstAddr,
									in MobileHeader p_mobileHeader,
									in octetstring p_receivedAuthenticator)
	runs on LibIpv6Node 
	return FncRetCode {
		var UInt8 v_position := 0;
		var octetstring v_computedAuthenticator;
		
		if (f_isPresentBindingAuthorizationDataOption(p_mobileHeader.mobileMessage.bindingUpdateMsg, v_position) == e_success) {
				
			p_mobileHeader.checksum := c_2ZeroBytes;			
				
berge's avatar
berge committed
			if (p_mobileHeader.mobileMessage.bindingUpdateMsg.lifeTime != 0) {
				vc_mobileSec.cnSimuParams.kbm := fx_mac(		e_sha1, c_1ZeroByte,
																bit2oct(vc_mobileSec.cnSimuParams.homeKeygenToken)
																& bit2oct(vc_mobileSec.cnSimuParams.careOfKeygenToken));
			}
			else {
				vc_mobileSec.cnSimuParams.kbm := fx_mac(		e_sha1, c_1ZeroByte,
																bit2oct(vc_mobileSec.cnSimuParams.homeKeygenToken));	
			}
									
			//set Authenticator option with dummy Authenticator
			p_mobileHeader.mobileMessage.bindingUpdateMsg.mobileOptions[v_position].mobileBindingAuthorizationData := {
											mobileOptType := 5,
											mobileOptLen := 12,
											authenticator := c_12ZeroBytes}
																
			//calculate the mipHeaderLength over the dummy Authenticator
			p_mobileHeader.headerLen := fx_mipHeaderLength(p_mobileHeader) ;
				
			//set Authenticator to omit in order to calc the authenticator
			p_mobileHeader.mobileMessage.bindingUpdateMsg.mobileOptions[v_position].mobileBindingAuthorizationData.authenticator := omit;
		
			v_computedAuthenticator := fx_mac(	e_hmac_sha1_96, vc_mobileSec.cnSimuParams.kbm,
												p_srcAddr //careOfaddr 
												& p_dstAddr //cnAddr
												& fx_mipHdrToOct(p_mobileHeader) );
												
			if (p_receivedAuthenticator != v_computedAuthenticator) {
				return e_error;
			}
			
			return e_success;	
		}
		else {
			log("f_checkAuthenticator: Error: This packet does not contain any Binding Update");
			return e_error;
		}
	} //end function f_checkAuthenticator


		/*
	 * @desc 	This goes through the BindingUpdate and
	 *			checks if a NonceIndicesOption is present.
	 * @param 	p_bindingUpdate Binding Update to be treated
	 * @param 	v_position Position of the NonceIndicesOption in the MobileOptionList
	 * @return 	execution status 
	*/
mullers's avatar
mullers committed
	function f_isPresentNonceIndices(	in BindingUpdateMsg p_bindingUpdate,
														inout UInt8 v_position)
	runs on LibIpv6Node
	return FncRetCode {
		var FncRetCode v_ret := e_error;
		var UInt8 i;

		//select ext hdrs that need special calculation
		for (i:=0; i<sizeof(p_bindingUpdate.mobileOptions) and (v_ret != e_success); i:=i+1) {
			if (ischosen(p_bindingUpdate.mobileOptions[i].mobileOptNonceIndices)) {
					v_position := i;
					v_ret := e_success;
				}
		}
		return v_ret;
	}//end function f_isPresentNonceIndices

	/*
	 * @desc 	This goes through the BindingUpdate and
	 *			checks if a AuthorizationDataOption is present.
	 * @param 	p_bindingUpdate Binding Update to be treated
	 * @param 	v_position Position of the AuthorizationDataOption in the MobileOptionList
	 * @return 	execution status 
	*/
mullers's avatar
mullers committed
	function f_isPresentBindingAuthorizationDataOption(	in BindingUpdateMsg p_bindingUpdate,
														inout UInt8 v_position)
	runs on LibIpv6Node
	return FncRetCode {
		var FncRetCode v_ret := e_error;
		var UInt8 i;

		//select ext hdrs that need special calculation
		for (i:=0; i<sizeof(p_bindingUpdate.mobileOptions) and (v_ret != e_success); i:=i+1) {
			if (ischosen(p_bindingUpdate.mobileOptions[i].mobileBindingAuthorizationData)) {
					v_position := i;
					v_ret := e_success;
				}
		}
		return v_ret;
	}//end function f_isPresentBindingAuthorizationDataOption
mullers's avatar
mullers committed

	/*
	 * @desc 	This sends a IPv6 packet with MipExtHdr - Binding Update
	 *			from an IPv6 node to any NUT.
	 *			
	 * @remark  
	 * @param 	p_msg MIPHeader to be sent	
	 * @return 	execution status
	*/
	function f_sendBU(template BindingUpdate p_msg)
	runs on LibIpv6Node
	return FncRetCode {
		//Variables
		var BindingUpdate v_ipPkt;
		v_ipPkt := valueof(p_msg);
mullers's avatar
mullers committed
		//calc payloadLen
		v_ipPkt.ipv6Hdr.payloadLength := fx_payloadLength (v_ipPkt);
		
		//set extensionHeaders
		if(f_setExtensionHeaders(	v_ipPkt,
									v_ipPkt.ipv6Hdr.sourceAddress,
									v_ipPkt.ipv6Hdr.destinationAddress) != e_success) {
			log(" **** f_sendBU: Error when calculating length of extension headers ****");
			return e_error;
		}

mullers's avatar
mullers committed
		//send
		ipPort.send(v_ipPkt);

		return e_success;
	}//end f_sendBU

	/*
	 * @desc 	This sends a IPv6 packet with MipExtHdr - Binding Acknowledgement
	 *			from an IPv6 node to any NUT.
	 *			
	 * @remark  
	 * @param 	p_msg MIPHeader to be sent	
	 * @return 	execution status
	*/
	function f_sendBA(template BindingAcknowledgement p_msg)
	runs on LibIpv6Node
	return FncRetCode {
		//Variables
		var BindingAcknowledgement v_ipPkt;
		v_ipPkt := valueof(p_msg);
mullers's avatar
mullers committed
		//calc payloadLen
		v_ipPkt.ipv6Hdr.payloadLength := fx_payloadLength (v_ipPkt);
		
		//set extensionHeaders
		if(f_setExtensionHeaders(	v_ipPkt,
									v_ipPkt.ipv6Hdr.sourceAddress,
									v_ipPkt.ipv6Hdr.destinationAddress) != e_success) {
			log(" **** f_sendBA: Error when calculating length of extension headers ****");
			return e_error;
		}
		
mullers's avatar
mullers committed
		//send
		ipPort.send(v_ipPkt);

		return e_success;
	}//end f_sendBA

	/*
	 * @desc 	This sends a IPv6 packet with MipExtHdr - Binding Error
	 *			from an IPv6 node to any NUT.
	 *			
	 * @remark  
	 * @param 	p_msg MIPHeader to be sent	
	 * @return 	execution status
	*/
	function f_sendBE(template BindingError p_msg)
	runs on LibIpv6Node
	return FncRetCode {
		//Variables
		var BindingError v_ipPkt;
		v_ipPkt := valueof(p_msg);
mullers's avatar
mullers committed
		//calc payloadLen
		v_ipPkt.ipv6Hdr.payloadLength := fx_payloadLength (v_ipPkt);

		//set extensionHeaders
		if(f_setExtensionHeaders(	v_ipPkt,
									v_ipPkt.ipv6Hdr.sourceAddress,
									v_ipPkt.ipv6Hdr.destinationAddress) != e_success) {
			log(" **** f_sendBE: Error when calculating length of extension headers ****");
			return e_error;
		}

mullers's avatar
mullers committed
		//send
		ipPort.send(v_ipPkt);

		return e_success;
	}//end f_sendBE

	/*
	 * @desc 	This sends a IPv6 packet with MipExtHdr - Binding Refresh Request
	 *			from an IPv6 node to any NUT.
	 *			
	 * @remark  
	 * @param 	p_msg MIPHeader to be sent	
	 * @return 	execution status
	*/
	function f_sendBR(template BindingRefreshRequest p_msg)
	runs on LibIpv6Node
	return FncRetCode {
		//Variables
		var BindingRefreshRequest v_ipPkt;
		v_ipPkt := valueof(p_msg);
mullers's avatar
mullers committed
		//calc payloadLen
		v_ipPkt.ipv6Hdr.payloadLength := fx_payloadLength (v_ipPkt);

		if(f_setExtensionHeaders(	v_ipPkt,
									v_ipPkt.ipv6Hdr.sourceAddress,
									v_ipPkt.ipv6Hdr.destinationAddress) != e_success) {
			log(" **** f_sendBR: Error when calculating length of extension headers ****");
			return e_error;
		}

mullers's avatar
mullers committed
		//send
		ipPort.send(v_ipPkt);

		return e_success;
	}//end f_sendBR

	/*
	 * @desc 	This sends a IPv6 packet with MipExtHdr - Home Test
	 *			from an IPv6 node to any NUT.
	 *			
	 * @remark  
	 * @param 	p_msg MIPHeader to be sent	
	 * @return 	execution status
	*/
	function f_sendHot(template HomeTest p_msg)
	runs on LibIpv6Node
	return FncRetCode {
		//Variables
		var HomeTest v_ipPkt;
		v_ipPkt := valueof(p_msg);
mullers's avatar
mullers committed
		//calc payloadLen
		v_ipPkt.ipv6Hdr.payloadLength := fx_payloadLength (v_ipPkt);

		//set extensionHeaders
		if(f_setExtensionHeaders(	v_ipPkt,
									v_ipPkt.ipv6Hdr.sourceAddress,
									v_ipPkt.ipv6Hdr.destinationAddress) != e_success) {
			log(" **** f_sendHot: Error when calculating length of extension headers ****");
			return e_error;
		}

mullers's avatar
mullers committed
		//send
		ipPort.send(v_ipPkt);

		return e_success;
	}//end f_sendHot

		/*
	 * @desc 	This sends a IPv6 packet with MipExtHdr - Home Test Init
	 *			from an IPv6 node to any NUT.
	 *			
	 * @remark  
	 * @param 	p_msg MIPHeader to be sent	
	 * @return 	execution status
	*/
	function f_sendHoti(template HomeTestInit p_msg)
	runs on LibIpv6Node
	return FncRetCode {
		//Variables
		var HomeTestInit v_ipPkt;
		v_ipPkt := valueof(p_msg);
mullers's avatar
mullers committed
		//calc payloadLen
		v_ipPkt.ipv6Hdr.payloadLength := fx_payloadLength (v_ipPkt);

		//set extensionHeaders
		if(f_setExtensionHeaders(	v_ipPkt,
									v_ipPkt.ipv6Hdr.sourceAddress,
									v_ipPkt.ipv6Hdr.destinationAddress) != e_success) {
			log(" **** f_sendHoti: Error when calculating length of extension headers ****");
			return e_error;
		}

mullers's avatar
mullers committed
		//send
		ipPort.send(v_ipPkt);

		return e_success;
	}//end f_sendHoti

	/*
	 * @desc 	This sends a IPv6 packet with MipExtHdr - CareOfTestInit
	 *			from an IPv6 node to any NUT.
	 *			
	 * @remark  
	 * @param 	p_msg MIPHeader to be sent	
	 * @return 	execution status
	*/
	function f_sendCoti(template CareOfTestInit p_msg)
	runs on LibIpv6Node
	return FncRetCode {
		//Variables
		var CareOfTestInit v_ipPkt;
		v_ipPkt := valueof(p_msg);
mullers's avatar
mullers committed
		//calc payloadLen
		v_ipPkt.ipv6Hdr.payloadLength := fx_payloadLength (v_ipPkt);

		//set extensionHeaders
		if(f_setExtensionHeaders(	v_ipPkt,
									v_ipPkt.ipv6Hdr.sourceAddress,
									v_ipPkt.ipv6Hdr.destinationAddress) != e_success) {
			log(" **** f_sendCoti: Error when calculating length of extension headers ****");
			return e_error;
		}

mullers's avatar
mullers committed
		//send
		ipPort.send(v_ipPkt);

		return e_success;
	}//end f_sendCoti

		/*
	 * @desc 	This sends a IPv6 packet with MipExtHdr - CareOfTest
	 *			from an IPv6 node to any NUT.
	 *			
	 * @remark  
	 * @param 	p_msg MIPHeader to be sent	
	 * @return 	execution status
	*/
	function f_sendCot(template CareOfTest p_msg)
	runs on LibIpv6Node
	return FncRetCode {
		//Variables
		var CareOfTest v_ipPkt;
		v_ipPkt := valueof(p_msg);
mullers's avatar
mullers committed
		//calc payloadLen
		v_ipPkt.ipv6Hdr.payloadLength := fx_payloadLength (v_ipPkt);

		//set extensionHeaders
		if(f_setExtensionHeaders(	v_ipPkt,
									v_ipPkt.ipv6Hdr.sourceAddress,
									v_ipPkt.ipv6Hdr.destinationAddress) != e_success) {
			log(" **** f_sendCoti: Error when calculating length of extension headers ****");
			return e_error;
		}

mullers's avatar
mullers committed
		//send
		ipPort.send(v_ipPkt);

		return e_success;
	}//end f_sendCot

			/*
	 * @desc 	This sends a IPv6 packet with MipExtHdr - Fast Nbr Adv
	 *			from an IPv6 node to any NUT.
	 *			
	 * @remark  
	 * @param 	p_msg MIPHeader to be sent	
	 * @return 	execution status
	*/
	function f_sendFastNbrAdv(template FastNeighborAdvertisement p_msg)
mullers's avatar
mullers committed
	runs on LibIpv6Node
	return FncRetCode {
		//Variables
mullers's avatar
mullers committed
		v_ipPkt := valueof(p_msg);
mullers's avatar
mullers committed
		//calc payloadLen
		v_ipPkt.ipv6Hdr.payloadLength := fx_payloadLength (v_ipPkt);

		//set extensionHeaders
		if(f_setExtensionHeaders(	v_ipPkt,
									v_ipPkt.ipv6Hdr.sourceAddress,
									v_ipPkt.ipv6Hdr.destinationAddress) != e_success) {
			log(" **** f_sendFastNbrAdv: Error when calculating length of extension headers ****");
			return e_error;
		}

mullers's avatar
mullers committed
		//send
		ipPort.send(v_ipPkt);

		return e_success;
	}//end f_sendFastNbrAdv

}//end group rfc3775Mipv6_ExtHdrFunctions


group rfc4303Esp_ExtHdrFunctions {
	
mullers's avatar
mullers committed
	function f_init_ipSecParams()
	runs on LibIpv6Node {
		
mullers's avatar
mullers committed
		var FncRetCode v_ret := e_error;

		vc_sad[0] := {
mullers's avatar
mullers committed
			spi := 0/*f_createSpi()*/,
mullers's avatar
mullers committed
			seqNr := c_uInt32Zero,
			// AH Integrity
			ahIntegrityAlgo := PX_INTEGRITY_ALGO,
mullers's avatar
mullers committed
			ahIntegrityKey := PX_INTEGRITY_KEY/*f_createSecretKey()*/,
			// ESP encryption
			espEncryptionAlgo := PX_ENCRYPTION_ALGO,
mullers's avatar
mullers committed
			espEncryptionKey := PX_ESP_ENCR_KEY/*f_createSecretKey()*/,
			// ESP integrity
			espIntegrityAlgo := PX_INTEGRITY_ALGO,
mullers's avatar
mullers committed
			espIntegrityKey := PX_INTEGRITY_KEY/*f_createSecretKey()*/,
			// Combined mode
			espCombinedModeAlgo := PX_COMBINED_MODE_ALGO,
mullers's avatar
mullers committed
			espCombinedModeKey := PX_COMBINED_MODE_KEY/*f_createSecretKey()*/,
			// Protocol mode
			ipSecProtocolMode := PX_IP_SEC_PROTOCOL_MODE
		}
mullers's avatar
mullers committed

		//TODO chose in function of PX_SPI the SAD to be used for testing
		v_ret := fx_setSecurityParameters(vc_sad[0]);
		if (v_ret != e_success) {log("fx_setSecurityParameters: Error when settign security parameters");}
mullers's avatar
mullers committed
	}//end f_init_ipSecParams


	/*
	 * @desc 	This generates Security Parameters Index
	 * @return 	Security Parameters Index
	*/
	function f_createSpi()
	runs on LibIpv6Node
	return UInt32 {
		var Oct4 v_spi := int2oct(float2int(int2float(20000-5000)*rnd())+5000, 4);

		return oct2int(v_spi);
	}//end f_createSpi

	/*
	 * @desc 	This generates a secret key
	 * @return 	Secret key
	*/
	function f_createSecretKey()
	runs on LibIpv6Node
	return octetstring {
		var Oct20 v_key := int2oct(float2int(int2float(20000-5000)*rnd())+5000, 20);

		return v_key;
	}//end f_createSecretKey

	/*
	 * @desc 	
	 *			This function is used when sending messages.
	 * @param 	p_msg ExtensionHeaderList to be treated	
	 * @return 	execution status 
	*/
	function f_getOriginalIpv6Packet(	in Ipv6Packet p_ipv6Packet,
										in EspHeader p_espHeader,
										out Ipv6Packet p_originalIpv6Packet)
	runs on LibIpv6Node
	return FncRetCode {
		var UInt8 i;
		var boolean v_loop := true;

		if (not(ispresent(p_espHeader.espPayload.espIpDatagram.extHdrList))
			and not(ispresent(p_espHeader.espPayload.espIpDatagram.ipv6Payload))) {
berge's avatar
berge committed
				log("**** f_setEspHeader: EspHeader.espPayload.espIpDatagram received that does neither contain extHdrList not ipv6Payload => EspHeader is not constructed correctly ****")	;			
				return e_error;
		}

		//Build original packet
		p_originalIpv6Packet.ipv6Hdr := p_ipv6Packet.ipv6Hdr;
		if (ispresent(p_espHeader.espPayload.espIpDatagram.extHdrList)) {
			p_originalIpv6Packet.extHdrList := p_espHeader.espPayload.espIpDatagram.extHdrList;
		}
		if (ispresent(p_espHeader.espPayload.espIpDatagram.ipv6Payload)) {
			p_originalIpv6Packet.ipv6Payload := p_espHeader.espPayload.espIpDatagram.ipv6Payload;
		}

		// is a tunneledIpv6Hdr in the extHdrList? If yes, then it becomes the Ipv6Hdr of the original packet
		if (ispresent(p_espHeader.espPayload.espIpDatagram.extHdrList)) {
			for (i:=0; i<sizeof(p_espHeader.espPayload.espIpDatagram.extHdrList) and v_loop ;i:=i+1) {
				if (ischosen(p_espHeader.espPayload.espIpDatagram.extHdrList[i].tunneledIpv6)) {
					p_originalIpv6Packet.ipv6Hdr := p_espHeader.espPayload.espIpDatagram.extHdrList[i].tunneledIpv6;
					v_loop := false;
				}
				else {
					p_originalIpv6Packet.extHdrList[i] := p_espHeader.espPayload.espIpDatagram.extHdrList[i];	
				}
			}
		}

		p_originalIpv6Packet.ipv6Hdr.payloadLength := fx_payloadLength (p_originalIpv6Packet);

		return e_success;

	}//end f_setEspHeader

mullers's avatar
mullers committed
	/*
mullers's avatar
mullers committed
	 *			This function is used when sending messages.
	 * @param 	p_msg ExtensionHeaderList to be treated	
	 * @return 	execution status 
	*/
/*	function f_setEspHeader(	in Ipv6Packet p_ipv6Packet,
								inout EspHeader p_espHeader)
mullers's avatar
mullers committed
	runs on LibIpv6Node
	return FncRetCode {
		var Ipv6Header v_originalIpv6Hdr;
		var EchoRequest v_originalEchoRequest;
		var EchoReply v_originalEchoReply;

		//treat MipHdr and other ext
		if (ispresent(p_espHeader.espPayload.espIpDatagram.extHdrList)) {
			
			
		}

mullers's avatar
mullers committed
		if (ispresent(p_espHeader.espPayload.espIpDatagram.ipv6Payload)) {
			if (ischosen(p_espHeader.espPayload.espIpDatagram.ipv6Payload.echoRequestMsg)) {	
				if (ischosen(p_espHeader.espPayload.espIpDatagram.extHdrList[0].tunneledIpv6)) {//tunnelMode
					v_originalIpv6Hdr := p_espHeader.espPayload.espIpDatagram.extHdrList[0].tunneledIpv6;
				}
				else { //transportMode
					v_originalIpv6Hdr := p_ipv6Packet.ipv6Hdr;
				}
				//build original packet
				v_originalEchoRequest := {
					ipv6Hdr := v_originalIpv6Hdr,
					extHdrList := omit,
					ipv6Payload := p_espHeader.espPayload.espIpDatagram.ipv6Payload
				}
				//calc checksum 
				if (v_originalEchoRequest.ipv6Payload.echoRequestMsg.checksum != c_2ZeroBytes) {
					//calc checksum
					v_originalEchoRequest.ipv6Payload.echoRequestMsg.checksum := fx_icmpv6Checksum(v_originalEchoRequest);
				}
				//assign checksum
				p_espHeader.espPayload.espIpDatagram.ipv6Payload.echoRequestMsg.checksum := v_originalEchoRequest.ipv6Payload.echoRequestMsg.checksum;
			}
			else if (ischosen(p_espHeader.espPayload.espIpDatagram.ipv6Payload.echoReplyMsg)) {
				if (ischosen(p_espHeader.espPayload.espIpDatagram.extHdrList[0].tunneledIpv6)) {//tunnelMode
					v_originalIpv6Hdr := p_espHeader.espPayload.espIpDatagram.extHdrList[0].tunneledIpv6;
				}
				else { //transportMode
					v_originalIpv6Hdr := p_ipv6Packet.ipv6Hdr;
				}
				//build original packet
				v_originalEchoReply := {
					ipv6Hdr := v_originalIpv6Hdr,
					extHdrList := omit,
					ipv6Payload := p_espHeader.espPayload.espIpDatagram.ipv6Payload
				}
				//calc checksum 
				if (v_originalEchoReply.ipv6Payload.echoReplyMsg.checksum != c_2ZeroBytes) {
					//calc checksum
					v_originalEchoReply.ipv6Payload.echoReplyMsg.checksum := fx_icmpv6Checksum(v_originalEchoReply);
				}
				//assign checksum
				p_espHeader.espPayload.espIpDatagram.ipv6Payload.echoReplyMsg.checksum := v_originalEchoReply.ipv6Payload.echoReplyMsg.checksum;
			}
mullers's avatar
mullers committed
		return e_success;
mullers's avatar
mullers committed
	}//end f_setEspHeader