LibIpv6_Interface_Functions.ttcn 52.3 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 Ipv6Packet v_pseudoIpv6Packet;
		var Ipv6Packet v_activeIpv6Packet := p_ipv6Packet;
		v_pseudoDstAddr := v_activeIpv6Packet.ipv6Hdr.destinationAddress;
		v_pseudoSrcAddr := v_activeIpv6Packet.ipv6Hdr.sourceAddress;
		
		//calc payloadLen
		if (v_activeIpv6Packet.ipv6Hdr.payloadLength == c_uInt16Zero ) {
			v_activeIpv6Packet.ipv6Hdr.payloadLength := fx_payloadLength (v_activeIpv6Packet);
		}

		if (ispresent(v_activeIpv6Packet.extHdrList)) {
			for (i:=0; i<sizeof(v_activeIpv6Packet.extHdrList) and v_loop ;i:=i+1) {
				
				// Process Home Address Destination Option, non-recursive
				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, non-recursive		
				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, non-recursive			
				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
					v_activeIpv6Packet.ipv6Hdr.payloadLength := fx_payloadLength (v_activeIpv6Packet);
				// Process Tunneled Header, recursive
				else if (ischosen(v_activeIpv6Packet.extHdrList[i].tunneledIpv6)) {
					v_nrOfTunnelHdr := v_nrOfTunnelHdr + 1;
		
					//Build original packet
					v_pseudoIpv6Packet.ipv6Hdr := v_activeIpv6Packet.extHdrList[i].tunneledIpv6;
					for (j:=0; (i+j+1)<sizeof(v_activeIpv6Packet.extHdrList) ;j:=j+1) {
						v_pseudoIpv6Packet.extHdrList[j] := v_activeIpv6Packet.extHdrList[i+1];	
					}
					if (ispresent(v_activeIpv6Packet.ipv6Payload)) {
						v_pseudoIpv6Packet.ipv6Payload := v_activeIpv6Packet.ipv6Payload;	
					v_pseudoIpv6Packet.ipv6Hdr.payloadLength := fx_payloadLength (v_pseudoIpv6Packet);
mullers's avatar
mullers committed

					// recursive call, original packet can still contain other headers
					f_setExtensionHeaders(	v_pseudoIpv6Packet,
											v_pseudoIpv6Packet.ipv6Hdr.sourceAddress,
											v_pseudoIpv6Packet.ipv6Hdr.destinationAddress);
					//Update the original packet						
					v_pseudoIpv6Packet.ipv6Hdr.payloadLength := fx_payloadLength (v_pseudoIpv6Packet);											
			
					// include recursion results
					v_activeIpv6Packet.extHdrList[i].tunneledIpv6.payloadLength := v_pseudoIpv6Packet.ipv6Hdr.payloadLength;
					if (ispresent(v_pseudoIpv6Packet.extHdrList)) {
						for (j:=0; j<sizeof(v_pseudoIpv6Packet.extHdrList) ;j:=j+1) {
							v_activeIpv6Packet.extHdrList[i+1] := v_pseudoIpv6Packet.extHdrList[j];	
					if (ispresent(v_pseudoIpv6Packet.ipv6Payload)) {
						v_activeIpv6Packet.ipv6Payload := v_pseudoIpv6Packet.ipv6Payload;	
					}
					
					v_loop := false;				
				}
				else if (ischosen(v_activeIpv6Packet.extHdrList[i].espHeader)) {
mullers's avatar
mullers committed

					//set IV
					if (vc_sad[c_saOut].espEncryptionAlgo == e_null) {
mullers's avatar
mullers committed
						v_activeIpv6Packet.extHdrList[i].espHeader.espPayload.iv := omit; 
					}
					else {
berge's avatar
berge committed
						v_activeIpv6Packet.extHdrList[i].espHeader.espPayload.iv := int2oct(128, f_getEncryptionIvLen(PX_ENCRYPTION_ALGO)); 	
mullers's avatar
mullers committed
					}
berge's avatar
berge committed
					//Update the original packet						
					v_activeIpv6Packet.ipv6Hdr.payloadLength := fx_payloadLength (v_activeIpv6Packet);	
						
					v_ret := f_getOriginalIpv6Packet(
									v_activeIpv6Packet,
									v_activeIpv6Packet.extHdrList[i].espHeader,
					v_pseudoIpv6Packet.ipv6Hdr.destinationAddress := v_pseudoDstAddr;
					v_pseudoIpv6Packet.ipv6Hdr.sourceAddress := v_pseudoSrcAddr;
					if (v_ret == e_success) {
						f_setExtensionHeaders(	v_pseudoIpv6Packet,
												v_pseudoIpv6Packet.ipv6Hdr.sourceAddress,
												v_pseudoIpv6Packet.ipv6Hdr.destinationAddress);
						if (ispresent(v_pseudoIpv6Packet.extHdrList)) {
berge's avatar
berge committed
							v_activeIpv6Packet.extHdrList[i].espHeader.espPayload.espIpDatagram.extHdrList := v_pseudoIpv6Packet.extHdrList
						if (ispresent(v_pseudoIpv6Packet.ipv6Payload)) {
berge's avatar
berge committed
							v_activeIpv6Packet.extHdrList[i].espHeader.espPayload.espIpDatagram.ipv6Payload := v_pseudoIpv6Packet.ipv6Payload;	
						v_loop := false;
					}
vouffofeudji's avatar
vouffofeudji committed
				}
			}//end for
		}
		// all extension headers have been processed
		// Is there still a payload to be processed and which has not been already processed in a recursive call?
		if (v_loop==true and ispresent(v_activeIpv6Packet.ipv6Payload)) {
			v_ret := f_calcIpv6PayloadChecksum(v_pseudoSrcAddr, v_pseudoDstAddr, v_activeIpv6Packet.ipv6Payload);
		v_ret := f_setAuthHeader (v_activeIpv6Packet);
		p_ipv6Packet := v_activeIpv6Packet;

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

	}//end f_setExtensionHeaders

	/*
	 * @desc 	This goes through the extension header list and looks for 
	 *          Authentication Header to compute ICV.
	 *			Only 1 Authentication Header is processed
	 * @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_setAuthHeader(	inout Ipv6Packet p_ipv6Packet)
	runs on LibIpv6Node
	return FncRetCode {
		var FncRetCode v_ret := e_success;
		var UInt8 i, j;

		var boolean v_loop := true;
		var Ipv6Packet v_pseudoIpv6Packet;
		var Ipv6Packet v_activeIpv6Packet := 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, predictable field
				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)) {
							//TODO
						}
					}
				}
				// Proccess Routing Header Type 2, predictable field
				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)) {
						//TODO
					}
				}
				// Process Tunneled Header, recursive
				else if (ischosen(v_activeIpv6Packet.extHdrList[i].tunneledIpv6)) {
		
					//Build original packet
					v_pseudoIpv6Packet.ipv6Hdr := v_activeIpv6Packet.extHdrList[i].tunneledIpv6;
					for (j:=0; (i+j+1)<sizeof(v_activeIpv6Packet.extHdrList) ;j:=j+1) {
						v_pseudoIpv6Packet.extHdrList[j] := v_activeIpv6Packet.extHdrList[i+1];	
					}
					if (ispresent(v_activeIpv6Packet.ipv6Payload)) {
						v_pseudoIpv6Packet.ipv6Payload := v_activeIpv6Packet.ipv6Payload;	
					}

					// recursive call, original packet can still contain Auth header
					f_setAuthHeader( v_pseudoIpv6Packet );
					
					v_loop := false;				
				}
				// Process Authentication Header Header
				else if (ischosen(v_activeIpv6Packet.extHdrList[i].authHeader)) {
					
mullers's avatar
mullers committed
					//Set Dummy ICV of correct length
					if (vc_sad[c_saOut].icvLen == 0) {
mullers's avatar
mullers committed
						p_ipv6Packet.extHdrList[i].authHeader.icv := omit;	
					}
					else {
						p_ipv6Packet.extHdrList[i].authHeader.icv := int2oct(0, vc_sad[c_saOut].icvLen);
mullers's avatar
mullers committed
					// Check ICV padding
					if (vc_sad[c_saOut].icvPadLen == 0) {
mullers's avatar
mullers committed
						p_ipv6Packet.extHdrList[i].authHeader.icvPadding := omit;
						p_ipv6Packet.extHdrList[i].authHeader.icvPadding := int2oct(0, vc_sad[c_saOut].icvPadLen);
					p_ipv6Packet.extHdrList[i].authHeader.payloadLen := (12 + vc_sad[c_saOut].icvLen + vc_sad[c_saOut].icvPadLen) / 4 - 2;
					//Update IPv6 payload based on the calculated ICV + padding
					p_ipv6Packet.ipv6Hdr.payloadLength := fx_payloadLength (p_ipv6Packet);


					v_activeIpv6Packet := p_ipv6Packet;
					//zero mutable fields
					v_activeIpv6Packet.ipv6Hdr.flowLabel := 0;
					v_activeIpv6Packet.ipv6Hdr.hopLimit := 0;

mullers's avatar
mullers committed
					//compute icv
					if (vc_sad[c_saOut].icvLen != 0) {
						p_ipv6Packet.extHdrList[i].authHeader.icv := fx_mac( vc_sad[c_saOut].ahIntegrityAlgo , vc_sad[c_saOut].ahIntegrityKey, fx_encodeMessage(v_activeIpv6Packet));
mullers's avatar
mullers committed
					}					

					v_loop := false;				
				}				
			}//end for
		}

		return v_ret;

	}//end f_setAuthHeader

		
	}//end group extHdrFns

	function f_calcIpv6PayloadChecksum( in template Ipv6Address p_srcAddr,	
										in template Ipv6Address p_dstAddr, 
mullers's avatar
mullers committed
										inout Ipv6Payload p_ipv6Payload)
	return FncRetCode {
		
		if(ischosen(p_ipv6Payload.echoReplyMsg)) {
			if(p_ipv6Payload.echoReplyMsg.checksum == c_2ZeroBytes) {
				//calc checksum
				p_ipv6Payload.echoReplyMsg.checksum := fx_calcPayloadChecksum (p_srcAddr, p_dstAddr, p_ipv6Payload);
		else if(ischosen(p_ipv6Payload.echoRequestMsg)) {
			if(p_ipv6Payload.echoRequestMsg.checksum == c_2ZeroBytes) {
				//calc checksum
				p_ipv6Payload.echoRequestMsg.checksum := fx_calcPayloadChecksum (p_srcAddr, p_dstAddr, p_ipv6Payload);
		else if(ischosen(p_ipv6Payload.nbrAdvMsg)) {
			if(p_ipv6Payload.nbrAdvMsg.checksum == c_2ZeroBytes) {
				//calc checksum
				p_ipv6Payload.nbrAdvMsg.checksum := fx_calcPayloadChecksum (p_srcAddr, p_dstAddr, p_ipv6Payload);
		else if(ischosen(p_ipv6Payload.nbrSolMsg)) {
			if(p_ipv6Payload.nbrSolMsg.checksum == c_2ZeroBytes) {
				//calc checksum
				p_ipv6Payload.nbrSolMsg.checksum := fx_calcPayloadChecksum (p_srcAddr, p_dstAddr, p_ipv6Payload);
		else if(ischosen(p_ipv6Payload.routerAdvMsg)) {
			if(p_ipv6Payload.routerAdvMsg.checksum == c_2ZeroBytes) {
				//calc checksum
				p_ipv6Payload.routerAdvMsg.checksum := fx_calcPayloadChecksum (p_srcAddr, p_dstAddr, p_ipv6Payload);
		else if(ischosen(p_ipv6Payload.routerSolMsg)) {
			if(p_ipv6Payload.routerSolMsg.checksum == c_2ZeroBytes) {
				//calc checksum
				p_ipv6Payload.routerSolMsg.checksum := fx_calcPayloadChecksum (p_srcAddr, p_dstAddr, p_ipv6Payload);
		else if(ischosen(p_ipv6Payload.redirectMsg)) {
			if(p_ipv6Payload.redirectMsg.checksum == c_2ZeroBytes) {
				//calc checksum
				p_ipv6Payload.redirectMsg.checksum := fx_calcPayloadChecksum (p_srcAddr, p_dstAddr, p_ipv6Payload);
		else if(ischosen(p_ipv6Payload.parameterProblemMsg)) {
			if(p_ipv6Payload.parameterProblemMsg.checksum == c_2ZeroBytes) {
				//calc checksum
				p_ipv6Payload.parameterProblemMsg.checksum := fx_calcPayloadChecksum (p_srcAddr, p_dstAddr, p_ipv6Payload);
		else if(ischosen(p_ipv6Payload.timeExceededMsg)) {
			if(p_ipv6Payload.timeExceededMsg.checksum == c_2ZeroBytes) {
				//calc checksum
				p_ipv6Payload.timeExceededMsg.checksum := fx_calcPayloadChecksum (p_srcAddr, p_dstAddr, p_ipv6Payload);
		else if(ischosen(p_ipv6Payload.packetTooBigMsg)) {
			if(p_ipv6Payload.packetTooBigMsg.checksum == c_2ZeroBytes) {
				//calc checksum
				p_ipv6Payload.packetTooBigMsg.checksum := fx_calcPayloadChecksum (p_srcAddr, p_dstAddr, p_ipv6Payload);
		else if(ischosen(p_ipv6Payload.destinationUnreachableMsg)) {
			if(p_ipv6Payload.destinationUnreachableMsg.checksum == c_2ZeroBytes) {
				//calc checksum
				p_ipv6Payload.destinationUnreachableMsg.checksum := fx_calcPayloadChecksum (p_srcAddr, p_dstAddr, p_ipv6Payload);
		else if(ischosen(p_ipv6Payload.mobileRouterAdvMsg)) {
			if(p_ipv6Payload.mobileRouterAdvMsg.checksum == c_2ZeroBytes) {
				//calc checksum
				p_ipv6Payload.mobileRouterAdvMsg.checksum := fx_calcPayloadChecksum (p_srcAddr, p_dstAddr, p_ipv6Payload);
		else if(ischosen(p_ipv6Payload.homeAgentAddrDiscRequestMsg)) {
			if(p_ipv6Payload.homeAgentAddrDiscRequestMsg.checksum == c_2ZeroBytes) {
				//calc checksum
				p_ipv6Payload.homeAgentAddrDiscRequestMsg.checksum := fx_calcPayloadChecksum (p_srcAddr, p_dstAddr, p_ipv6Payload);
		else if(ischosen(p_ipv6Payload.homeAgentAddrDiscReplyMsg)) {
			if(p_ipv6Payload.homeAgentAddrDiscReplyMsg.checksum == c_2ZeroBytes) {
				//calc checksum
				p_ipv6Payload.homeAgentAddrDiscReplyMsg.checksum := fx_calcPayloadChecksum (p_srcAddr, p_dstAddr, p_ipv6Payload);
		else if(ischosen(p_ipv6Payload.mobilePrefixSolMsg)) {
			if(p_ipv6Payload.mobilePrefixSolMsg.checksum == c_2ZeroBytes) {
				//calc checksum
				p_ipv6Payload.mobilePrefixSolMsg.checksum := fx_calcPayloadChecksum (p_srcAddr, p_dstAddr, p_ipv6Payload);
		else if(ischosen(p_ipv6Payload.mobilePrefixAdvMsg)) {
			if(p_ipv6Payload.mobilePrefixAdvMsg.checksum == c_2ZeroBytes) {
				//calc checksum
				p_ipv6Payload.mobilePrefixAdvMsg.checksum := fx_calcPayloadChecksum (p_srcAddr, p_dstAddr, p_ipv6Payload);
		else if(ischosen(p_ipv6Payload.otherIcmpv6Msg)) {
			if(p_ipv6Payload.otherIcmpv6Msg.checksum == c_2ZeroBytes) {
				//calc checksum
				p_ipv6Payload.otherIcmpv6Msg.checksum := fx_calcPayloadChecksum (p_srcAddr, p_dstAddr, p_ipv6Payload);
		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_isPresentNonceIndicesInBU(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_isPresentBindingAuthorizationDataOptionInBU(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.bindingAckMsg)) {
			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_isPresentNonceIndicesInBA(p_mobileHeader.mobileMessage.bindingAckMsg, v_position) == e_success) {

				// Fill Home Nonce Index only when set to c_uInt16Zero
				if (p_mobileHeader.mobileMessage.bindingAckMsg.mobileOptions[v_position].mobileOptNonceIndices.homeNonceIndex == c_uInt16Zero ) {
					if(vc_mobileSec.cnSimuParams.nonceIndex != c_uInt16Zero) {
							p_mobileHeader.mobileMessage.bindingAckMsg.mobileOptions[v_position].mobileOptNonceIndices.homeNonceIndex
							:= vc_mobileSec.cnSimuParams.nonceIndex;
					}
					else {
						log("f_setMobileHeader: Info: NonceIndices included in Binding Ack, but cnSimuParams.nonceIndex not initialized");
					}
				}
				
				// Fill Care-Of Nonce Index only when set to c_uInt16Zero
				if (p_mobileHeader.mobileMessage.bindingAckMsg.mobileOptions[v_position].mobileOptNonceIndices.careOfNonceIndex == c_uInt16Zero) {
					if(vc_mobileSec.cnSimuParams.nonceIndex != c_uInt16Zero) {
							p_mobileHeader.mobileMessage.bindingAckMsg.mobileOptions[v_position].mobileOptNonceIndices.careOfNonceIndex
							:= vc_mobileSec.cnSimuParams.nonceIndex;
					}
					else {
						log("f_setMobileHeader: Info: NonceIndices included in Binding Ack, but cnSimuParams.nonceIndex not initialized");
					}
				}
			} // end Process Nonce Indices
				
			if (f_isPresentBindingAuthorizationDataOptionInBA(p_mobileHeader.mobileMessage.bindingAckMsg, v_position) == e_success) {
				if(vc_mobileSec.cnSimuParams.homeKeygenToken != c_64ZeroBits
					and vc_mobileSec.cnSimuParams.careOfKeygenToken != c_64ZeroBits) {

						// kbm is different if BA is sent for de-registration				
						if (p_mobileHeader.mobileMessage.bindingAckMsg.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.bindingAckMsg.mobileOptions[v_position].mobileBindingAuthorizationData := {
														mobileOptType := 5,
														mobileOptLen := 12,
														authenticator := c_12ZeroBytes}
																		
						//calculate the mipHeaderLength over the dummy Authenticator
						//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.bindingAckMsg.mobileOptions[v_position].mobileBindingAuthorizationData.authenticator := omit;
				
						// compute authenticator
						p_mobileHeader.mobileMessage.bindingAckMsg.mobileOptions[v_position].mobileBindingAuthorizationData.authenticator 
								 := fx_mac(	e_hmac_sha1_96, vc_mobileSec.cnSimuParams.kbm,
																		p_dstAddr //cnAddr			/!\ inverted /!\
																		& p_srcAddr //careOfaddr    /!\ for BA   /!\
																		& fx_mipHdrToOct(p_mobileHeader) );
				}
				else {
					log("f_setMobileHeader: Error: BindingAuthorizationDataOption included in Binding Ack, but HomeKeygenToken/CareOfKeygenToken not initialized");
					return e_error;	
				}
			}
		}
		// 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_isPresentBindingAuthorizationDataOptionInBU(p_mobileHeader.mobileMessage.bindingUpdateMsg, v_position) == e_success) {
berge's avatar
berge committed
				
			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 BindingAck 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 
	*/
	function f_isPresentNonceIndicesInBA(	in BindingAckMsg p_bindingAck,
														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_bindingAck.mobileOptions) and (v_ret != e_success); i:=i+1) {
			if (ischosen(p_bindingAck.mobileOptions[i].mobileOptNonceIndices)) {
					v_position := i;
					v_ret := e_success;
				}
		}
		return v_ret;
	}//end function f_isPresentNonceIndicesInBA
	
	/*
	 * @desc 	This goes through the BindingAck 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 
	*/
	function f_isPresentBindingAuthorizationDataOptionInBA(	in BindingAckMsg p_bindingAck,
														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_bindingAck.mobileOptions) and (v_ret != e_success); i:=i+1) {
			if (ischosen(p_bindingAck.mobileOptions[i].mobileBindingAuthorizationData)) {
					v_position := i;
					v_ret := e_success;
				}
		}
		return v_ret;
	}//end function f_isPresentBindingAuthorizationDataOptionInBA


	/*
	 * @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 
	*/
	function f_isPresentNonceIndicesInBU(	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_isPresentNonceIndicesInBU

	/*
	 * @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 
	*/
	function f_isPresentBindingAuthorizationDataOptionInBU(	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_isPresentBindingAuthorizationDataOptionInBU
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