module DIAMETER_ts29_272_Templates {

/* (C) 2023 by sysmocom s.f.m.c. GmbH <info@sysmocom.de
 * All rights reserved.
 *
 * Released under the terms of GNU General Public License, Version 2 or
 * (at your option) any later version.
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 *
 * Templates for AVPs and messages for TS 29.272
 */

import from General_Types all;
import from DIAMETER_Types all;
import from DIAMETER_Templates all;
import from Osmocom_Types all;
import from Misc_Helpers all;

/*******************************
 * S6a 3GPP TS 29.272 section 7
 *******************************/

/* 3GPP TS 29.272 Section 7.1.8 */
const uint32_t c_DIAMETER_3GPP_S6_AID := 16777251; /* S6a/S6d */
const uint32_t c_DIAMETER_3GPP_S13_AID := 16777252;

/* 3GPP TS 29.272 section 7.4. Errors in Experimental-Result-Code */
type enumerated DIAMETER_ExperimentalResultcode {
	/* transient */
	DIAMETER_AUTHENTICATION_DATA_UNAVAILABLE 	(4181),
	DIAMETER_ERROR_CAMEL_SUBSCRIPTION_PRESENT 	(4182),
	/* permanent */
	DIAMETER_ERROR_USER_UNKNOWN			(5001),
	DIAMETER_AUTHORIZATION_REJECTED			(5003),
	DIAMETER_ERROR_ROAMING_NOT_ALLOWED		(5004),
	DIAMETER_MISSING_AVP				(5005),
	DIAMETER_ERROR_UNKNOWN_EPS_SUBSCRIPTION		(5420),
	DIAMETER_ERROR_RAT_NOT_ALLOWED			(5421),
	DIAMETER_ERROR_EQUIPMENT_UNKNOWN		(5422),
	DIAMETER_ERROR_UNKOWN_SERVING_NODE		(5423)
}

/* TS 29.272 7.3.53 RAND */
template (value) GenericAVP ts_AVP_RAND(template (value) octetstring rand) := {
	avp := {
		avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_RAND),
		avp_data := {
			avp_AAA_3GPP_RAND := rand
		}
	}
}

/* TS 29.272 7.3.54 XRES */
template (value) GenericAVP ts_AVP_XRES(template (value) octetstring xres) := {
	avp := {
		avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_XRES),
		avp_data := {
			avp_AAA_3GPP_XRES := xres
		}
	}
}

/* TS 29.272 7.3.55 XRES */
template (value) GenericAVP ts_AVP_AUTN(template (value) octetstring autn) := {
	avp := {
		avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_AUTN),
		avp_data := {
			avp_AAA_3GPP_AUTN := autn
		}
	}
}

/* TS 29.272 7.3.56 KASME */
template (value) GenericAVP ts_AVP_KASME(template (value) octetstring kasme) := {
	avp := {
		avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_KASME),
		avp_data := {
			avp_AAA_3GPP_KASME := kasme
		}
	}
}

/* TS 29.272 7.3.23 Item-Number */
template (value) GenericAVP ts_AVP_ItemNumber(uint32_t num) := {
	avp := {
		avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_KASME),
		avp_data := {
			avp_AAA_3GPP_Item_Number := int2oct(num, 4)
		}
	}
}

/* TS 29.272 7.3.18 E-UTRAN Vector */
template (value) GenericAVP ts_AVP_EutranVec(uint32_t item_num, octetstring rand, octetstring xres,
					     octetstring autn, octetstring kasme) := {
	avp := {
		avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_E_UTRAN_Vector),
		avp_data := {
			avp_AAA_3GPP_E_UTRAN_Vector := {
				ts_AVP_ItemNumber(item_num),
				ts_AVP_RAND(rand),
				ts_AVP_XRES(xres),
				ts_AVP_AUTN(autn),
				ts_AVP_KASME(kasme)
			}
		}
	}
}

/* TS 29.272 7.3.2 Subscription-Data */
template (value) GenericAVP ts_AVP_3GPP_SubscriptionData(template (value) AVP_list content) := {
	avp := {
		avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Subscription_Data),
		avp_data := {
			avp_AAA_3GPP_Subscription_Data := content
		}
	}
}
template (present) GenericAVP
tr_AVP_3GPP_SubscriptionData(template (present) AVP_list content := ?) := {
	avp := {
		avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Subscription_Data),
		avp_data := {
			avp_AAA_3GPP_Subscription_Data := content
		}
	}
}


/* TS 29.272 7.3.17 Authentication-Info */
template (value) GenericAVP ts_AVP_3GPP_AuthInfo(template (value) AVP_list content) := {
	avp := {
		avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Authentication_Info),
		avp_data := {
			avp_AAA_3GPP_Authentication_Info := content
		}
	}
}
template (present) GenericAVP
tr_AVP_3GPP_AuthInfo(template (present) AVP_list content := ?) := {
	avp := {
		avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Authentication_Info),
		avp_data := {
			avp_AAA_3GPP_Authentication_Info := content
		}
	}
}

/* TS 29.272 7.3.9 Visited-PLMN-Id */
template (value) GenericAVP ts_AVP_3GPP_VisitedPlmnId(template (value) octetstring id) := {
	avp := {
		avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Visited_PLMN_Id),
		avp_data := {
			avp_AAA_3GPP_Visited_PLMN_Id := id
		}
	}
}
template (present) GenericAVP tr_AVP_3GPP_VisitedPlmnId(template (present) octetstring id := ?) := {
	avp := {
		avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Visited_PLMN_Id),
		avp_data := {
			avp_AAA_3GPP_Visited_PLMN_Id := id
		}
	}
}

/* TS 29.272 7.3.13 RAT-Type */
template (value) GenericAVP ts_AVP_PCC_3GPP_RatType(template (value) PCC_3GPP_RAT_Type rat_type) := {
	avp := {
		avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_PCC_3GPP_RAT_Type),
		avp_data := {
			avp_PCC_3GPP_RAT_Type := rat_type
		}
	}
}
template (present) GenericAVP tr_AVP_PCC_3GPP_RatType(template (present) PCC_3GPP_RAT_Type rat_type := ?) := {
	avp := {
		avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_PCC_3GPP_RAT_Type),
		avp_data := {
			avp_PCC_3GPP_RAT_Type := rat_type
		}
	}
}

template (present) GenericAVP tr_AVP_GI_3GPP_RatType(template (present) GI_3GPP_3GPP_RAT_Type rat_type := ?) := {
	avp := {
		avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_GI_3GPP_3GPP_RAT_Type),
		avp_data := {
			avp_GI_3GPP_3GPP_RAT_Type := rat_type
		}
	}
}

/* TS 29.272 7.3.7 ULR-Flags */
template (value) GenericAVP ts_AVP_3GPP_UlrFlags(template (value) UINT32 flags) := {
	avp := {
		avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_ULR_Flags),
		avp_data := {
			avp_AAA_3GPP_ULR_Flags := flags
		}
	}
}
template (present) GenericAVP tr_AVP_3GPP_UlrFlags(template (present) UINT32 flags := ?) := {
	avp := {
		avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_ULR_Flags),
		avp_data := {
			avp_AAA_3GPP_ULR_Flags := flags
		}
	}
}

/* TS 29.272 7.3.8 ULA-Flags */
template (value) GenericAVP ts_AVP_3GPP_UlaFlags(template (value) UINT32 flags) := {
	avp := {
		avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_ULA_Flags),
		avp_data := {
			avp_AAA_3GPP_ULA_Flags := flags
		}
	}
}
template (present) GenericAVP tr_AVP_3GPP_UlaFlags(template (present) UINT32 flags := ?) := {
	avp := {
		avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_ULA_Flags),
		avp_data := {
			avp_AAA_3GPP_ULA_Flags := flags
		}
	}
}


/* TS 29.272 7.3.27 Context-Identifier */
template (present) GenericAVP tr_AVP_3GPP_ContextId(template (present) uint32_t ctx := ?) := {
	avp := {
		avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Context_Identifier),
		avp_data := {
			avp_AAA_3GPP_Context_Identifier := int2oct_tmpl(ctx, 4)
		}
	}
}
template (value) GenericAVP ts_AVP_3GPP_ContextId(template (value) uint32_t ctx) := {
	avp := {
		avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Context_Identifier),
		avp_data := {
			avp_AAA_3GPP_Context_Identifier := int2oct(valueof(ctx), 4)
		}
	}
}

/* Ts 29.272 7.3.29 Subscriber-Status */
template (present) GenericAVP tr_AVP_3GPP_SubscriberStatus(template (present) AAA_3GPP_Subscriber_Status sts) := {
	avp := {
		avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Subscriber_Status),
		avp_data := {
			avp_AAA_3GPP_Subscriber_Status := sts
		}
	}
}
template (value) GenericAVP ts_AVP_3GPP_SubscriberStatus(template (value) AAA_3GPP_Subscriber_Status sts) := {
	avp := {
		avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Subscriber_Status),
		avp_data := {
			avp_AAA_3GPP_Subscriber_Status := sts
		}
	}
}

/* Ts 29.272 7.3.30 Operator-Determined-Barring */
template (present) GenericAVP tr_AVP_3GPP_OperatorDeterminedBarring(template (present) uint32_t val := ?) := {
	avp := {
		avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Operator_Determined_Barring),
		avp_data := {
			avp_AAA_3GPP_Operator_Determined_Barring := int2oct_tmpl(val, 4)
		}
	}
}
template (value) GenericAVP ts_AVP_3GPP_OperatorDeterminedBarring(uint32_t val) := {
	avp := {
		avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Operator_Determined_Barring),
		avp_data := {
			avp_AAA_3GPP_Operator_Determined_Barring := int2oct(val, 4)
		}
	}
}

/* TS 29.272 7.3.33 All-APN-Configurations-Included-Indicator */
template (present) GenericAVP tr_AVP_3GPP_AllApnConfigsIncl(template (present) AAA_3GPP_All_APN_Configurations_Included_Indicator ind := ?) := {
	avp := {
		avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_All_APN_Configurations_Included_Indicator),
		avp_data := {
			avp_AAA_3GPP_All_APN_Configurations_Included_Indicator := ind
		}
	}
}
template (value) GenericAVP ts_AVP_3GPP_AllApnConfigsIncl(template (value) AAA_3GPP_All_APN_Configurations_Included_Indicator ind := All_APN_CONFIGURATIONS_INCLUDED) := {
	avp := {
		avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_All_APN_Configurations_Included_Indicator),
		avp_data := {
			avp_AAA_3GPP_All_APN_Configurations_Included_Indicator := ind
		}
	}
}

/* TS 29.272 7.3.24 Cancellation-Type */
template (value) GenericAVP ts_AVP_3GPP_CancellationType(template (value) AAA_3GPP_Cancellation_Type t) := {
	avp := {
		avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Cancellation_Type),
		avp_data := {
			avp_AAA_3GPP_Cancellation_Type := t
		}
	}
}

/* TS 29.272 7.3.34 APN-Configuration-Profile */
template (present) GenericAVP tr_AVP_3GPP_ApnConfigProfile(template (present) AVP_list content := ?) := {
	avp := {
		avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_APN_Configuration_Profile),
		avp_data := {
			avp_AAA_3GPP_APN_Configuration_Profile := content
		}
	}
}
template (value) GenericAVP ts_AVP_3GPP_ApnConfigProfile(template (value) AVP_list content) := {
	avp := {
		avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_APN_Configuration_Profile),
		avp_data := {
			avp_AAA_3GPP_APN_Configuration_Profile := content
		}
	}
}

/* TS 29.272 7.3.35 APN-Configuration */
template (present) GenericAVP tr_AVP_3GPP_ApnConfig(template (present) uint32_t ctx := ?,
						    template (present) AAA_3GPP_PDN_Type pdn_type := ?,
						    template (present) charstring apn := ?) := {
	avp := {
		avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_APN_Configuration),
		avp_data := {
			avp_AAA_3GPP_APN_Configuration := superset(
				tr_AVP_3GPP_ContextId(ctx),
				tr_AVP_3GPP_PdnType(pdn_type),
				tr_AVP_ServiceSelection(apn),
				tr_AVP_3GPP_EpsSubscrQosProfile(?, ?)
			)
		}
	}
}
template (value) GenericAVP ts_AVP_3GPP_ApnConfig(template (value) uint32_t ctx,
						  template (value) AAA_3GPP_PDN_Type pdn_type,
						  template (value) charstring apn) := {
	avp := {
		avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_APN_Configuration),
		avp_data := {
			avp_AAA_3GPP_APN_Configuration := {
				ts_AVP_3GPP_ContextId(ctx),
				ts_AVP_3GPP_PdnType(pdn_type),
				ts_AVP_ServiceSelection(apn),
				ts_AVP_3GPP_EpsSubscrQosProfile(1, 1)
			}
		}
	}
}

/* Service-Selection, TS 29.272 7.3.36, TS 29.273 5.2.3.5, (RFC 5778) */
template (present) GenericAVP tr_AVP_ServiceSelection(template (present) charstring apn := ?) := {
	avp := {
		avp_header := tr_DIA_Hdr(c_AVP_Code_MIPv6_NONE_Service_Selection),
		avp_data := {
			avp_MIPv6_NONE_Service_Selection := char2oct_tmpl(apn)
		}
	}
}
template (value) GenericAVP ts_AVP_ServiceSelection(template (value) charstring apn) := {
	avp := {
		avp_header := ts_DIA_Hdr(c_AVP_Code_MIPv6_NONE_Service_Selection),
		avp_data := {
			avp_MIPv6_NONE_Service_Selection := char2oct(valueof(apn))
		}
	}
}

/* TS 29.272 7.3.41 AMBR */
template (present) GenericAVP tr_AVP_3GPP_AMBR(template (present) uint32_t ul := ?, template (present) uint32_t dl := ?) := {
	avp := {
		avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_AMBR),
		avp_data := {
			avp_AAA_3GPP_AMBR := {
				tr_AVP_3GPP_MaxReqBwUL(ul),
				tr_AVP_3GPP_MaxReqBwDL(dl)
			}
		}
	}
}
template (value) GenericAVP ts_AVP_3GPP_AMBR(template (value) uint32_t ul,
					     template (value) uint32_t dl) := {
	avp := {
		avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_AMBR),
		avp_data := {
			avp_AAA_3GPP_AMBR := {
				ts_AVP_3GPP_MaxReqBwUL(ul),
				ts_AVP_3GPP_MaxReqBwDL(dl)
			}
		}
	}
}

template (present) GenericAVP tr_AVP_3GPP_MaxReqBwUL(template (present) uint32_t bw := ?) := {
	avp := {
		avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_RX_3GPP_Max_Requested_Bandwidth_UL),
		avp_data := {
			avp_RX_3GPP_Max_Requested_Bandwidth_UL := int2oct_tmpl(bw, 4)
		}
	}
}

template (value) GenericAVP ts_AVP_3GPP_MaxReqBwUL(template (value) uint32_t bw) := {
	avp := {
		avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_RX_3GPP_Max_Requested_Bandwidth_UL),
		avp_data := {
			avp_RX_3GPP_Max_Requested_Bandwidth_UL := int2oct(valueof(bw), 4)
		}
	}
}

template (present) GenericAVP tr_AVP_3GPP_MaxReqBwDL(template (present) uint32_t bw := ?) := {
	avp := {
		avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_RX_3GPP_Max_Requested_Bandwidth_DL),
		avp_data := {
			avp_RX_3GPP_Max_Requested_Bandwidth_DL := int2oct_tmpl(bw, 4)
		}
	}
}

template (value) GenericAVP ts_AVP_3GPP_MaxReqBwDL(template (value) uint32_t bw) := {
	avp := {
		avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_RX_3GPP_Max_Requested_Bandwidth_DL),
		avp_data := {
			avp_RX_3GPP_Max_Requested_Bandwidth_DL := int2oct(valueof(bw), 4)
		}
	}
}

/* TS 29.272 7.3.62 PDN-Type */
template (present) GenericAVP tr_AVP_3GPP_PdnType(template (present) AAA_3GPP_PDN_Type pdn_type := ?) := {
	avp := {
		avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_PDN_Type),
		avp_data := {
			avp_AAA_3GPP_PDN_Type := pdn_type
		}
	}
}
template (value) GenericAVP ts_AVP_3GPP_PdnType(template (value) AAA_3GPP_PDN_Type pdn_type) := {
	avp := {
		avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_PDN_Type),
		avp_data := {
			avp_AAA_3GPP_PDN_Type := pdn_type
		}
	}
}


/* TS 29.272 5.2.3.1 + 7.2.6 Authentication Information Answer */
template (value) PDU_DIAMETER
ts_DIA_AIA(template (value) AVP_list auth_info_contents,
	   template (value) octetstring sess_id := c_def_sess_id,
	   template (value) charstring orig_host := "hss.localdomain",
	   template (value) charstring orig_realm := "localdomain",
	   template (value) UINT32 hbh_id := '00000000'O,
	   template (value) UINT32 ete_id := '00000000'O) :=
	ts_DIAMETER(flags := '01000000'B,
		    cmd_code := Authentication_Information,
		    app_id := int2oct(c_DIAMETER_3GPP_S6_AID, 4),
		    hbh_id := hbh_id,
		    ete_id := ete_id,
		    avps := {
			ts_AVP_SessionId(sess_id),
			ts_AVP_ResultCode(DIAMETER_SUCCESS),
			ts_AVP_AuthSessionState(NO_STATE_MAINTAINED),
			ts_AVP_OriginHost(orig_host),
			ts_AVP_OriginRealm(orig_realm),
			ts_AVP_3GPP_AuthInfo(auth_info_contents)
	});
template (present) PDU_DIAMETER
tr_DIA_AIA(template (present) AVP_list auth_info_contents := ?,
	   template (present) octetstring sess_id := ?,
	   template (present) charstring orig_host := ?,
	   template (present) charstring orig_realm := ?,
	   template (present) UINT32 hbh_id := ?,
	   template (present) UINT32 ete_id := ?) :=
	tr_DIAMETER(flags := '0???????'B,
		    cmd_code := Authentication_Information,
		    app_id := int2oct(c_DIAMETER_3GPP_S6_AID, 4),
		    hbh_id := hbh_id,
		    ete_id := ete_id,
		    avps := superset(
			tr_AVP_SessionId(sess_id),
			tr_AVP_AuthSessionState(NO_STATE_MAINTAINED),
			tr_AVP_OriginHost(orig_host),
			tr_AVP_OriginRealm(orig_realm),
			tr_AVP_ResultCode(DIAMETER_SUCCESS),
			tr_AVP_3GPP_AuthInfo(auth_info_contents)
	));
template (present) PDU_DIAMETER
tr_DIA_AIA_ERR(template (present) GenericAVP err_avp := ?,
	   template (present) octetstring sess_id := ?,
	   template (present) charstring orig_host := ?,
	   template (present) charstring orig_realm := ?,
	   template (present) UINT32 hbh_id := ?,
	   template (present) UINT32 ete_id := ?) :=
	tr_DIAMETER(flags := '0???????'B,
		    cmd_code := Authentication_Information,
		    app_id := int2oct(c_DIAMETER_3GPP_S6_AID, 4),
		    hbh_id := hbh_id,
		    ete_id := ete_id,
		    avps := superset(
			tr_AVP_SessionId(sess_id),
			tr_AVP_AuthSessionState(NO_STATE_MAINTAINED),
			tr_AVP_OriginHost(orig_host),
			tr_AVP_OriginRealm(orig_realm),
			err_avp
	));


/* TS 29.272 7.2.3 Update Location Request */
template (value) PDU_DIAMETER
ts_DIA_ULR(/* template (value) */ hexstring imsi,
	   template (value) octetstring mcc_mnc := '111F11'O,
	   template (value) octetstring sess_id := c_def_sess_id,
	   template (value) charstring orig_host := "ttcn3.localdomain",
	   template (value) charstring orig_realm := "localdomain",
	   template (value) charstring dest_realm := "localdomain",
	   template (value) UINT32 hbh_id := '00000000'O,
	   template (value) UINT32 ete_id := '00000000'O) :=
	ts_DIAMETER(flags := '11000000'B,
		    cmd_code := Update_Location,
		    app_id := int2oct(c_DIAMETER_3GPP_S6_AID, 4),
		    hbh_id := hbh_id,
		    ete_id := ete_id,
		    avps := {
			ts_AVP_SessionId(sess_id),
			ts_AVP_AuthSessionState(NO_STATE_MAINTAINED),
			ts_AVP_UserNameImsi(imsi),
			ts_AVP_3GPP_UlrFlags('00000000'O),
			ts_AVP_3GPP_VisitedPlmnId(mcc_mnc),
			ts_AVP_PCC_3GPP_RatType(EUTRAN),
			ts_AVP_OriginHost(orig_host),
			ts_AVP_OriginRealm(orig_realm),
			ts_AVP_DestinationRealm(dest_realm)
	});
template (present) PDU_DIAMETER
tr_DIA_ULR(/* template (present) */ hexstring imsi,
	   template (present) octetstring sess_id := ?,
	   template (present) charstring orig_host := ?,
	   template (present) charstring orig_realm := ?,
	   template (present) charstring dest_realm := ?,
	   template (present) UINT32 hbh_id := ?,
	   template (present) UINT32 ete_id := ?) :=
	tr_DIAMETER(flags := '11000000'B,
		    cmd_code := Update_Location,
		    app_id := int2oct(c_DIAMETER_3GPP_S6_AID, 4),
		    hbh_id := hbh_id,
		    ete_id := ete_id,
		    avps := superset(
			tr_AVP_SessionId(sess_id),
			tr_AVP_AuthSessionState,
			tr_AVP_OriginHost(orig_host),
			tr_AVP_OriginRealm(orig_realm),
			tr_AVP_DestinationRealm(dest_realm),
			tr_AVP_UserNameImsi(imsi),
			tr_AVP_PCC_3GPP_RatType,
			tr_AVP_3GPP_UlrFlags,
			tr_AVP_3GPP_VisitedPlmnId
	));

template (value) PDU_DIAMETER
ts_DIA_ULA(template (value) AVP_list sub_data,
	   template (value) octetstring sess_id := c_def_sess_id,
	   template (value) charstring orig_host := "hss.localdomain",
	   template (value) charstring orig_realm := "localdomain",
	   template (value) UINT32 hbh_id := '00000000'O,
	   template (value) UINT32 ete_id := '00000000'O) :=
	ts_DIAMETER(flags:='01000000'B,
		    cmd_code := Update_Location,
		    app_id := int2oct(c_DIAMETER_3GPP_S6_AID, 4),
		    hbh_id := hbh_id,
		    ete_id := ete_id,
		    avps := {
			ts_AVP_SessionId(sess_id),
			ts_AVP_ResultCode(DIAMETER_SUCCESS), /* optional */
			ts_AVP_AuthSessionState(NO_STATE_MAINTAINED),
			ts_AVP_OriginHost(orig_host),
			ts_AVP_OriginRealm(orig_realm),
			ts_AVP_3GPP_UlaFlags('00000002'O),
			ts_AVP_3GPP_SubscriptionData(sub_data)
	});
template (present) PDU_DIAMETER
tr_DIA_ULA(template (present) AVP_list sub_data := ?,
	   template (present) octetstring sess_id := ?,
	   template (present) charstring orig_host := ?,
	   template (present) charstring orig_realm := ?,
	   template (present) UINT32 hbh_id := ?,
	   template (present) UINT32 ete_id := ?) :=
	tr_DIAMETER(flags := '0???????'B,
		    cmd_code := Update_Location,
		    app_id := int2oct(c_DIAMETER_3GPP_S6_AID, 4),
		    hbh_id := hbh_id,
		    ete_id := ete_id,
		    avps := superset(
			tr_AVP_SessionId(sess_id),
			tr_AVP_ResultCode(DIAMETER_SUCCESS),
			tr_AVP_AuthSessionState,
			tr_AVP_OriginHost(orig_host),
			tr_AVP_OriginRealm(orig_realm),
			tr_AVP_3GPP_UlaFlags,
			tr_AVP_3GPP_SubscriptionData(sub_data)
	));

/* TS 29.272 7.2.5 Authentication-Information-Request */
template (value) PDU_DIAMETER
ts_DIA_AIR(/* template (value) */ hexstring imsi,
	   template (value) octetstring mcc_mnc := '111F11'O,
	   template (value) octetstring sess_id := c_def_sess_id,
	   template (value) charstring orig_host := "ttcn3.localdomain",
	   template (value) charstring orig_realm := "localdomain",
	   template (value) charstring dest_realm := "localdomain",
	   template (value) UINT32 hbh_id := '00000000'O,
	   template (value) UINT32 ete_id := '00000000'O) :=
	ts_DIAMETER(flags := '11000000'B,
		    cmd_code := Authentication_Information,
		    app_id := int2oct(c_DIAMETER_3GPP_S6_AID, 4),
		    hbh_id := hbh_id,
		    ete_id := ete_id,
		    avps := {
			ts_AVP_SessionId(sess_id),
			ts_AVP_DestinationRealm(dest_realm),
			ts_AVP_OriginHost(orig_host),
			ts_AVP_OriginRealm(orig_realm),
			ts_AVP_UserNameImsi(imsi),
			/* Requested EUTRAN Auth Info */
			ts_AVP_RequestedEutranAuthInfo,
			ts_AVP_AuthSessionState(NO_STATE_MAINTAINED),
			ts_AVP_3GPP_VisitedPlmnId(mcc_mnc)
	});
template (present) PDU_DIAMETER
tr_DIA_AIR(/* template (present) */ hexstring imsi,
	   template (present) octetstring sess_id := ?,
	   template (present) charstring dest_realm := ?,
	   template (present) UINT32 hbh_id := ?,
	   template (present) UINT32 ete_id := ?) :=
	tr_DIAMETER(flags := '1???????'B,
		    cmd_code := Authentication_Information,
		    app_id := int2oct(c_DIAMETER_3GPP_S6_AID, 4),
		    hbh_id := hbh_id, ete_id := ete_id,
		    avps := superset(
			tr_AVP_SessionId(sess_id),
			tr_AVP_DestinationRealm(dest_realm),
			tr_AVP_UserNameImsi(imsi),
			tr_AVP_3GPP_VisitedPlmnId
	));

/* TS 29.272 7.2.7 Cancel-Location-Request */
template (value) PDU_DIAMETER
ts_DIA_CLR(/* template (value) */ hexstring imsi,
	   template (value) AAA_3GPP_Cancellation_Type cancel_type,
	   template (value) octetstring sess_id := c_def_sess_id,
	   template (value) charstring orig_host := "ttcn3.localdomain",
	   template (value) charstring orig_realm := "localdomain",
	   template (value) charstring dest_host := "iut.localdomain",
	   template (value) charstring dest_realm := "localdomain",
	   template (value) UINT32 hbh_id := '00000000'O,
	   template (value) UINT32 ete_id := '00000000'O) :=
	ts_DIAMETER(flags := '11000000'B,
		    cmd_code := Cancel_Location,
		    app_id := int2oct(c_DIAMETER_3GPP_S6_AID, 4),
		    hbh_id := hbh_id,
		    ete_id := ete_id,
		    avps := {
			ts_AVP_SessionId(sess_id),
			ts_AVP_AuthSessionState(NO_STATE_MAINTAINED),
			ts_AVP_OriginHost(orig_host),
			ts_AVP_OriginRealm(orig_realm),
			ts_AVP_DestinationHost(dest_host),
			ts_AVP_DestinationRealm(dest_realm),
			ts_AVP_UserNameImsi(imsi),
			/* [Supported-Features ] */
			ts_AVP_3GPP_CancellationType(cancel_type)
	});

/* TS 29.272 7.2.8 Cancel-Location-Answer */
template (present) PDU_DIAMETER
tr_DIA_CLA(template (present) AVP_list sub_data := ?,
	   template (present) octetstring sess_id := ?,
	   template (present) charstring orig_host := ?,
	   template (present) charstring orig_realm := ?,
	   template (present) UINT32 hbh_id := ?,
	   template (present) UINT32 ete_id := ?) :=
	tr_DIAMETER(flags := '0???????'B,
		    cmd_code := Cancel_Location,
		    app_id := int2oct(c_DIAMETER_3GPP_S6_AID, 4),
		    hbh_id := hbh_id,
		    ete_id := ete_id,
		    avps := superset(
			tr_AVP_SessionId(sess_id),
			tr_AVP_ResultCode(DIAMETER_SUCCESS),
			tr_AVP_AuthSessionState,
			tr_AVP_OriginHost(orig_host),
			tr_AVP_OriginRealm(orig_realm)
	));

} /* module */
