migration of code from ffasn1c to asn1c + asn1tostruct.py
diff --git a/src/Makefile b/src/Makefile
index 298a33c..9bff932 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,11 +1,20 @@
-LIBFFASN1_DIR=../../../kommerz/sysmocom/git/admin/ffasn1c/libffasn1
+ASN1_ROOT=../asn1/
+ASN1_DIR=$(ASN1_ROOT)/hnbap
+ASN1_FILES=HNBAP-CommonDataTypes.asn
 
-CFLAGS=-g -Wall `pkg-config --cflags libosmocore libosmovty libosmogsm` -I$(LIBFFASN1_DIR)
+ASN1TOSTRUCT:=$(ASN1_ROOT)/utils/asn1tostruct.py
+#ASN1_SRCS:=$(patsubst 
+
+CFLAGS=-g -Wall `pkg-config --cflags libosmocore libosmovty libosmogsm` -I$(ASN1_DIR)/asn1c/
 LDFLAGS=`pkg-config --libs libosmocore libosmovty libosmogsm` -lsctp
 
 all: hnbgw
 
-hnbgw: hnbgw.o hnbgw_hnbap.o hnbap.o asn1helpers.o $(LIBFFASN1_DIR)/libffasn1.a $(LIBFFASN1_DIR)/libffasn1_runtime_stdc.a
+.PHONY: hnbap_encoder.c
+hnbap_encoder.c: $(ASN1_DIR)/HNBAP-PDU-Contents.asn
+	$(ASN1TOSTRUCT) -f $<
+
+hnbgw: asn1helpers.o hnbap_common.o hnbap_encoder.o hnbap_decoder.o hnbgw.o hnbgw_hnbap.o
 	$(CC) $(LDFLAGS) -o $@ $^
 
 %.o: %.c
diff --git a/src/asn1helpers.c b/src/asn1helpers.c
index fe886e3..436afa5 100644
--- a/src/asn1helpers.c
+++ b/src/asn1helpers.c
@@ -1,19 +1,45 @@
 
 #include <string.h>
 
-#include <asn1defs.h>
+#include <osmocom/core/utils.h>
 
 #include "asn1helpers.h"
 
-int asn1_strncpy(char *out, const ASN1String *in, size_t n)
+void asn1_u32_to_bitstring(BIT_STRING_t *bitstr, uint32_t *in)
+{
+	bitstr->buf = (uint8_t *) in;
+	bitstr->size = sizeof(uint32_t);
+	bitstr->bits_unused = 0;
+}
+
+
+int asn1_strncpy(char *out, const OCTET_STRING_t *in, size_t n)
 {
 	size_t cpylen = n;
 
-	if (in->len < cpylen)
-		cpylen = in->len;
+	if (in->size < cpylen)
+		cpylen = in->size;
 
 	strncpy(out, (char *)in->buf, cpylen);
 	out[n-1] = '\0';
 
 	return cpylen;
 }
+
+uint16_t asn1str_to_u16(const OCTET_STRING_t *in)
+{
+	OSMO_ASSERT(in && in->size >= sizeof(uint16_t));
+	return *(uint16_t *)in->buf;
+}
+
+uint8_t asn1str_to_u8(const OCTET_STRING_t *in)
+{
+	OSMO_ASSERT(in && in->size >= sizeof(uint8_t));
+	return *(uint8_t *)in->buf;
+}
+
+uint32_t asn1bitstr_to_u32(const BIT_STRING_t *in)
+{
+	OSMO_ASSERT(in && in->size >= sizeof(uint32_t));
+	return *(uint32_t *)in->buf;
+}
diff --git a/src/asn1helpers.h b/src/asn1helpers.h
index 3861d13..75b00e2 100644
--- a/src/asn1helpers.h
+++ b/src/asn1helpers.h
@@ -1,29 +1,12 @@
 #pragma once
 
-#include <asn1defs.h>
+#include <unistd.h>
 
-static inline uint16_t asn1str_to_u16(ASN1String *as)
-{
-	if (as->len < 2)
-		return 0;
-	else
-		return *(uint16_t *)as->buf;
-}
+#include "BIT_STRING.h"
+#include "OCTET_STRING.h"
 
-static inline uint8_t asn1str_to_u8(ASN1String *as)
-{
-	if (as->len < 1)
-		return 0;
-	else
-		return *(uint8_t *)as->buf;
-}
-
-static inline uint8_t asn1bitstr_to_u32(ASN1BitString *as)
-{
-	if (as->len < 25)
-		return 0;
-	else
-		return *(uint32_t *)as->buf;
-}
-
-int asn1_strncpy(char *out, const ASN1String *in, size_t n);
+void asn1_u32_to_bitstring(BIT_STRING_t *bitstr, uint32_t *in);
+int asn1_strncpy(char *out, const OCTET_STRING_t *in, size_t n);
+uint16_t asn1str_to_u16(const OCTET_STRING_t *in);
+uint8_t asn1str_to_u8(const OCTET_STRING_t *in);
+uint32_t asn1bitstr_to_u32(const BIT_STRING_t *in);
diff --git a/src/hnbap_common.c b/src/hnbap_common.c
new file mode 100644
index 0000000..bd7a0eb
--- /dev/null
+++ b/src/hnbap_common.c
@@ -0,0 +1,133 @@
+#include <stdint.h>
+
+#include <osmocom/core/msgb.h>
+
+#include "HNBAP-PDU.h"
+#include "hnbap_common.h"
+
+int asn_debug = 0;
+int asn1_xer_print = 0;
+
+static struct msgb *hnbap_msgb_alloc(void)
+{
+	return msgb_alloc(1024, "HNBAP Tx");
+}
+
+#if 0
+ssize_t s1ap_generate_initiating_message(uint8_t ** buffer,
+					 uint32_t * length,
+					 e_ProcedureCode procedureCode,
+					 Criticality_t criticality,
+					 asn_TYPE_descriptor_t * td, void *sptr)
+{
+
+	HNBAP_PDU_t pdu;
+	ssize_t encoded;
+
+	memset(&pdu, 0, sizeof(HNBAP_PDU_t));
+
+	pdu.present = HNBAP_PDU_PR_initiatingMessage;
+	pdu.choice.initiatingMessage.procedureCode = procedureCode;
+	pdu.choice.initiatingMessage.criticality = criticality;
+	ANY_fromType_aper(&pdu.choice.initiatingMessage.value, td, sptr);
+
+	if (asn1_xer_print)
+		xer_fprint(stdout, &asn_DEF_HNBAP_PDU, (void *)&pdu);
+
+	if ((encoded =
+	     aper_encode_to_new_buffer(&asn_DEF_HNBAP_PDU, 0, &pdu,
+				       (void **)buffer)) < 0) {
+		return -1;
+	}
+
+	*length = encoded;
+	return encoded;
+}
+#endif
+
+struct msgb *hnbap_generate_successfull_outcome(
+					   e_ProcedureCode procedureCode,
+					   Criticality_t criticality,
+					   asn_TYPE_descriptor_t * td,
+					   void *sptr)
+{
+
+	HNBAP_PDU_t pdu;
+	struct msgb *msg = hnbap_msgb_alloc();
+	asn_enc_rval_t rval;
+
+	memset(&pdu, 0, sizeof(HNBAP_PDU_t));
+	pdu.present = HNBAP_PDU_PR_successfulOutcome;
+	pdu.choice.successfulOutcome.procedureCode = procedureCode;
+	pdu.choice.successfulOutcome.criticality = criticality;
+	ANY_fromType_aper(&pdu.choice.successfulOutcome.value, td, sptr);
+
+	rval = aper_encode_to_buffer(&asn_DEF_HNBAP_PDU, &pdu,
+				     msg->data, msgb_length(msg));
+	if (rval.encoded < 0) {
+		msgb_free(msg);
+		return NULL;
+	}
+
+	msgb_put(msg, rval.encoded);
+
+	return msg;
+}
+
+#if 0
+ssize_t s1ap_generate_unsuccessfull_outcome(uint8_t ** buffer,
+					    uint32_t * length,
+					    e_ProcedureCode procedureCode,
+					    Criticality_t criticality,
+					    asn_TYPE_descriptor_t * td,
+					    void *sptr)
+{
+
+	HNBAP_PDU_t pdu;
+	ssize_t encoded;
+
+	memset(&pdu, 0, sizeof(HNBAP_PDU_t));
+
+	pdu.present = HNBAP_PDU_PR_unsuccessfulOutcome;
+	pdu.choice.successfulOutcome.procedureCode = procedureCode;
+	pdu.choice.successfulOutcome.criticality = criticality;
+	ANY_fromType_aper(&pdu.choice.successfulOutcome.value, td, sptr);
+
+	if ((encoded =
+	     aper_encode_to_new_buffer(&asn_DEF_HNBAP_PDU, 0, &pdu,
+				       (void **)buffer)) < 0) {
+		return -1;
+	}
+
+	*length = encoded;
+
+	return encoded;
+}
+#endif
+
+IE_t *hnbap_new_ie(ProtocolIE_ID_t id,
+		   Criticality_t criticality,
+		   asn_TYPE_descriptor_t * type, void *sptr)
+{
+
+	IE_t *buff;
+
+	if ((buff = malloc(sizeof(IE_t))) == NULL) {
+		// Possible error on malloc
+		return NULL;
+	}
+	memset((void *)buff, 0, sizeof(IE_t));
+
+	buff->id = id;
+	buff->criticality = criticality;
+
+	ANY_fromType_aper(&buff->value, type, sptr);
+
+	if (asn1_xer_print)
+		if (xer_fprint(stdout, &asn_DEF_IE, buff) < 0) {
+			free(buff);
+			return NULL;
+		}
+
+	return buff;
+}
diff --git a/src/hnbap_common.h b/src/hnbap_common.h
new file mode 100644
index 0000000..9b77423
--- /dev/null
+++ b/src/hnbap_common.h
@@ -0,0 +1,142 @@
+#pragma once
+
+#include "asn_application.h"
+
+#include "ANY.h"
+#include "Access-stratum-release-indicator.h"
+#include "AccessResult.h"
+#include "AdditionalNeighbourInfoList.h"
+#include "AltitudeAndDirection.h"
+#include "BIT_STRING.h"
+#include "BackoffTimer.h"
+#include "BindingID.h"
+#include "CELL-FACHMobilitySupport.h"
+#include "CGI.h"
+#include "CI.h"
+#include "CN-DomainIndicator.h"
+#include "CSG-Capability.h"
+#include "CSG-ID.h"
+#include "CSGMembershipStatus.h"
+#include "CSGMembershipUpdate.h"
+#include "Cause.h"
+#include "CauseMisc.h"
+#include "CauseProtocol.h"
+#include "CauseRadioNetwork.h"
+#include "CauseTransport.h"
+#include "CellIdentity.h"
+#include "ConfigurationInformation.h"
+#include "Context-ID.h"
+#include "Criticality.h"
+#include "CriticalityDiagnostics-IE-List.h"
+#include "CriticalityDiagnostics.h"
+#include "ESN.h"
+#include "ErrorIndication.h"
+#include "GTP-TEI.h"
+#include "GeographicalCoordinates.h"
+#include "GeographicalLocation.h"
+#include "HNB-Cell-Access-Mode.h"
+#include "HNB-Cell-Identifier.h"
+#include "HNB-GWResponse.h"
+#include "HNB-Identity-Info.h"
+#include "HNB-Identity.h"
+#include "HNB-Location-Information.h"
+#include "HNB-RNL-Identity.h"
+#include "HNBAP-PDU.h"
+#include "HNBCapacity.h"
+#include "HNBConfigInfo.h"
+#include "HNBConfigTransferRequest.h"
+#include "HNBConfigTransferResponse.h"
+#include "HNBConfigurationInformationMissing.h"
+#include "HNBConfigurationInformationProvided.h"
+#include "HNBDe-Register.h"
+#include "HNBRegisterAccept.h"
+#include "HNBRegisterReject.h"
+#include "HNBRegisterRequest.h"
+#include "IE-Extensions.h"
+#include "IE.h"
+#include "IMEI.h"
+#include "IMSI.h"
+#include "IMSIDS41.h"
+#include "IMSIESN.h"
+#include "INTEGER.h"
+#include "IP-Address.h"
+#include "InitiatingMessage.h"
+#include "Ipv4Address.h"
+#include "Ipv6Address.h"
+#include "Iurh-Signalling-TNL-AddressList.h"
+#include "LAC.h"
+#include "LAI.h"
+#include "MacroCellID.h"
+#include "MacroCoverageInformation.h"
+#include "MuxPortNumber.h"
+#include "NativeEnumerated.h"
+#include "NativeInteger.h"
+#include "NeighbourCellIdentityList.h"
+#include "NeighbourIdentity.h"
+#include "NeighbourInfoList.h"
+#include "NeighbourInfoRequestItem.h"
+#include "NeighbourInfoRequestList.h"
+#include "OBJECT_IDENTIFIER.h"
+#include "OCTET_STRING.h"
+#include "PLMNidentity.h"
+#include "PSC.h"
+#include "PTMSI.h"
+#include "PTMSIRAI.h"
+#include "Presence.h"
+#include "PrivateIE-ID.h"
+#include "PrivateMessage.h"
+#include "ProcedureCode.h"
+#include "ProtocolIE-ID.h"
+#include "RAB-ID.h"
+#include "RABList.h"
+#include "RABListItem.h"
+#include "RAC.h"
+#include "RAI.h"
+#include "RNC-ID.h"
+#include "Registration-Cause.h"
+#include "RelocationComplete.h"
+#include "S-RNTIPrefix.h"
+#include "SAC.h"
+#include "SuccessfulOutcome.h"
+#include "TMSIDS41.h"
+#include "TMSILAI.h"
+#include "TNLUpdateFailure.h"
+#include "TNLUpdateRequest.h"
+#include "TNLUpdateResponse.h"
+#include "TransportInfo.h"
+#include "TransportLayerAddress.h"
+#include "TriggeringMessage.h"
+#include "Tunnel-Information.h"
+#include "TypeOfError.h"
+#include "U-RNTI.h"
+#include "U-RNTIQueryRequest.h"
+#include "U-RNTIQueryResponse.h"
+#include "UDP-Port-Number.h"
+#include "UE-Capabilities.h"
+#include "UE-Identity.h"
+#include "UEDe-Register.h"
+#include "UERegisterAccept.h"
+#include "UERegisterReject.h"
+#include "UERegisterRequest.h"
+#include "URAIdentity.h"
+#include "URAIdentityList.h"
+#include "UTRANCellID.h"
+#include "UnknownU-RNTIIndication.h"
+#include "UnsuccessfulOutcome.h"
+#include "Update-cause.h"
+
+#if (ASN1C_ENVIRONMENT_VERSION < 924)
+# error "You are compiling with the wrong version of ASN1C"
+#endif
+
+extern int asn1_xer_print;
+
+struct msgb *hnbap_generate_successfull_outcome(
+					   e_ProcedureCode procedureCode,
+					   Criticality_t criticality,
+					   asn_TYPE_descriptor_t * td,
+					   void *sptr);
+
+IE_t *hnbap_new_ie(ProtocolIE_ID_t id, Criticality_t criticality,
+		  asn_TYPE_descriptor_t *type, void *sptr);
+
diff --git a/src/hnbap_const.h b/src/hnbap_const.h
deleted file mode 100644
index 36c5422..0000000
--- a/src/hnbap_const.h
+++ /dev/null
@@ -1,54 +0,0 @@
-#pragma once
-
-/* should be auto-generated by ffasn1c, but isn't :( */
-enum hnbap_procedure_code {
-	HNBAP_PC_HNBRegister		= 1,
-	HNBAP_PC_HNBDe_Register 	= 2,
-	HNBAP_PC_UERegister		= 3,
-	HNBAP_PC_UEDe_Register		= 4,
-	HNBAP_PC_ErrorIndication	= 5,
-	HNBAP_PC_privateMessage		= 6,
-	HNBAP_PC_CSGMembershipUpdate	= 7,
-	HNBAP_PC_TNLUpdate		= 9,
-	HNBAP_PC_HNBConfigTransfer	= 10,
-	HNBAP_PC_RelocationComplete	= 11,
-	HNBAP_PC_U_RNTIQuery		= 14,
-};
-
-/* should be auto-generated by ffasn1c, but isn't :( */
-enum hnbap_iei {
-	HNBAP_IEI_Cause				= 1,
-	HNBAP_IEI_CriticalityDiagnostics	= 2,
-	HNBAP_IEI_HNB_Identity			= 3,
-	HNBAP_IEI_Context_ID			= 4,
-	HNBAP_IEI_UE_Identity			= 5,
-	HNBAP_IEI_LAC				= 6,
-	HNBAP_IEI_RAC				= 7,
-	HNBAP_IEI_HNB_Location_Information	= 8,
-	HNBAP_IEI_PLMNidentity			= 9,
-	HNBAP_IEI_SAC				= 10,
-	HNBAP_IEI_CellIdentity			= 11,
-	HNBAP_IEI_RegistrationCause		= 12,
-	HNBAP_IEI_UE_Capabilities		= 13,
-	HNBAP_IEI_RNC_ID			= 14,
-	HNBAP_IEI_CSG_ID			= 15,
-	HNBAP_IEI_BackoffTimer			= 16,
-	HNBAP_IEI_HNB_Internet_Information	= 17,
-	HNBAP_IEI_HNB_Cell_Acces_Mode		= 18,
-	HNBAP_IEI_MuxPortNumber			= 19,
-	HNBAP_IEI_Service_Area_For_Broadcast	= 20,
-	HNBAP_IEI_CSGMembershipStatus		= 21,
-	HNBAP_IEI_RABList			= 22,
-	HNBAP_IEI_HNBConfigInfo			= 23,
-	HNBAP_IEI_AccessResult			= 25,
-	HNBAP_IEI_Update_cause			= 26,
-	HNBAP_IEI_NeighborInfoList		= 27,
-	HNBAP_IEI_NeighborInfoRequestList	= 28,
-	HNBAP_IEI_Iurh_Signalling_TNL_Address	= 29,
-	HNBAP_IEI_PSC				= 30,
-	HNBAP_IEI_HNB_Cell_Identifier		= 31,
-	HNBAP_IEI_HNB_Tunnel_Information	= 41,
-	HNBAP_IEI_CELL_FACHMobilitySupport	= 42,
-	HNBAP_IEI_S_RNTIPrefix			= 43,
-	/* FIXME */
-};
diff --git a/src/hnbgw_hnbap.c b/src/hnbgw_hnbap.c
index 9db670e..5100bf5 100644
--- a/src/hnbgw_hnbap.c
+++ b/src/hnbgw_hnbap.c
@@ -7,211 +7,164 @@
 
 #include "asn1helpers.h"
 
-#include "hnbap.h"
 #include "hnbgw.h"
-#include "hnbap_const.h"
+#include "hnbap_common.h"
+#include "hnbap_ies_defs.h"
 
 #define IU_MSG_NUM_IES		32
 #define IU_MSG_NUM_EXT_IES	32
 
-/* common structure of a HNBAP / RUA / RANAP message, must have identical
- * memory footprint as the other messages, such as HNBRegisterRequest */
-struct iu_common_msg {
-	ProtocolIE_Container_1 protocolIEs;
-	BOOL protocolExtensions_option;
-	ProtocolIE_Container_1 protocolExtensions;
-};
-
-/* Add an IE to a Iu message
- * \param _msg Message to which we want to add
- * \param[in] ie Information Element to be added (ffasn1c generated struct)
- * \param[in] iei Information Element Identifier
- * \param[in] type asn1_type of the IE
- * \param[in] ext should this be an extension field?
- */
-int iu_msg_add_ie(void *_msg, void *ie, int iei, ASN1CType *type, int ext)
+static int hnbgw_hnbap_tx(struct hnb_context *ctx, struct msgb *msg)
 {
-	struct iu_common_msg *msg = _msg;
-	ProtocolIE_Field_1 *field;
+	/* FIXME */
+}
 
-	if (ext) {
-		msg->protocolExtensions_option = TRUE;
-		if (msg->protocolExtensions.count >= IU_MSG_NUM_EXT_IES)
-			return -ERANGE;
-		field = &msg->protocolExtensions.tab[msg->protocolExtensions.count++];
-	} else {
-		if (msg->protocolIEs.count >= IU_MSG_NUM_IES)
-			return -ERANGE;
-		field = &msg->protocolIEs.tab[msg->protocolIEs.count++];
+static int hnbgw_tx_hnb_register_acc(struct hnb_context *ctx)
+{
+	HNBRegisterAccept_t accept_out;
+	struct msgb *msg;
+	int rc;
+
+	/* Single required response IE: RNC-ID */
+	HNBRegisterAcceptIEs_t accept = {
+		.rnc_id = ctx->gw->config.rnc_id
+	};
+
+	/* encode the Information Elements */
+	rc = hnbap_encode_hnbregisteraccepties(&accept_out,  &accept);
+	if (rc < 0) {
+		return rc;
 	}
 
-	field->id = iei;
-	//field->criticality = FIXME;
-	field->value.type = type;
-	field->value.u.data = ie;
+	/* generate a successfull outcome PDU */
+	msg = hnbap_generate_successful_outcome(ProcedureCode_id_HNBRegister,
+					       Criticality_reject,
+					       &asn_DEF_HNBRegisterAccept,
+					       &accept_out);
 
-	return 0;
+	return hnbgw_hnbap_tx(ctx, msg);
 }
 
 
-
-static int hnbgw_hnbap_tx(struct HNBAP_PDU *pdu)
+static int hnbgw_tx_ue_register_acc(struct ue_context *ue)
 {
-	/* FIXME */
-}
+	UERegisterAccept_t accept_out;
+	UERegisterAcceptIEs_t accept;
+	struct msgb *msg;
+	int rc;
 
-static int hnbgw_tx_hnb_register_acc()
-{
-	/* FIXME */
-	/* Single required response IE: RNC-ID */
-}
+	/* FIXME accept.uE_Identity; */
+	asn1_u32_to_bitstring(&accept.context_ID, &ue->context_id);
 
-static int hnbgw_tx_ue_register_acc()
-{
-#if 0
-	HNBAP_PDU pdu;
-	HNBRegisterAccept hnb_reg_acc;
-
-	hnb_reg_acc.protocol_IEs
-
-	pdu.choice = HNBAP_PDU_successfulOutcome;
-	pdu.u.successfulOutcome.procedureCode = HNBAP_PC_HNBRegister;
-	pdu.u.successfulOutcome.criticality = ;
-	pdu.u.successfulOutcome.value.type = asn1_type_HNBRegisterAccept;
-	pdu.u.successfulOutcome.value.u.data = &hnb_reg_acc;
-#endif
-	/* FIXME */
-	/* Single required response IE: RNC-ID */
-}
-
-/* we type-cast to ProtocolIE_Container_1, as all the containers structs have
- * the same definiition.  This is of course ugly, but I see no cleaner way.
- * Similarly, from the IEI it is clear what the type should be, but in a
- * statically typed language we can only return 'void *' and hope the caller
- * doesn the right typecast. */
-#define FIND_IE(cont, id) find_ie((const struct ProtocolIE_Container_1 *)cont, id)
-static void *find_ie(const struct ProtocolIE_Container_1 *cont, ProtocolIE_ID id)
-{
-	int i;
-
-	/* iterate over the array of IEs in the IE container and look for the first
-	 * occurrence of the right IEI */
-	for (i = 0; i < cont->count; i++) {
-		ProtocolIE_Field_1 *field = &cont->tab[i];
-		if (field->id == id) {
-			OSMO_ASSERT(field->value.type);
-			/* FIXME: we shoudl check if it is the correct type, not just any type */
-			return field->value.u.data;
-		}
+	rc = hnbap_encode_ueregisteraccepties(&accept_out, &accept);
+	if (rc < 0) {
+		return rc;
 	}
-	return NULL;
+
+	msg = hnbap_generate_successful_outcome(ProcedureCode_id_UERegister,
+						Criticality_reject,
+						&asn_DEF_UERegisterAccept,
+						&accept_out);
+	return hnbgw_hnbap_tx(ue->hnb, msg);
 }
 
-static int hnbgw_rx_hnb_register_req(struct hnb_context *ctx, struct HNBRegisterRequest *req)
+static int hnbgw_rx_hnb_register_req(struct hnb_context *ctx, ANY_t *in)
 {
-	HNB_Identity *identity =
-		FIND_IE(&req->protocolIEs, HNBAP_IEI_HNB_Identity);
-	HNB_Location_Information *loc =
-		FIND_IE(&req->protocolIEs, HNBAP_IEI_HNB_Location_Information);
-	PLMNidentity *plmn_id =
-		FIND_IE(&req->protocolIEs, HNBAP_IEI_PLMNidentity);
-	CellIdentity *cell_id =
-		FIND_IE(&req->protocolIEs, HNBAP_IEI_CellIdentity);
-	LAC *lac = FIND_IE(&req->protocolIEs, HNBAP_IEI_LAC);
-	RAC *rac = FIND_IE(&req->protocolIEs, HNBAP_IEI_RAC);
-	SAC *sac = FIND_IE(&req->protocolIEs, HNBAP_IEI_SAC);
-	/* Optional: CSG-ID */
+	HNBRegisterRequestIEs_t ies;
+	int rc;
 
-	if(!identity || !loc || !plmn_id || !cell_id || !lac || !rac || !sac)
-		return -1;
+	rc = hnbap_decode_hnbregisterrequesties(&ies, in);
+	if (rc < 0)
+		return rc;
 
 	/* copy all identity parameters from the message to ctx */
-	asn1_strncpy(ctx->identity_info, &identity->hNB_Identity_Info,
-		sizeof(ctx->identity_info));
-	ctx->id.lac = asn1str_to_u16(lac);
-	ctx->id.sac = asn1str_to_u16(sac);
-	ctx->id.rac = asn1str_to_u8(rac);
-	ctx->id.cid = asn1bitstr_to_u32(cell_id);
+	asn1_strncpy(ctx->identity_info, &ies.hnB_Identity.hNB_Identity_Info,
+			sizeof(ctx->identity_info));
+	ctx->id.lac = asn1str_to_u16(&ies.lac);
+	ctx->id.sac = asn1str_to_u16(&ies.sac);
+	ctx->id.rac = asn1str_to_u8(&ies.rac);
+	ctx->id.cid = asn1bitstr_to_u32(&ies.cellIdentity);
 	//ctx->id.mcc FIXME
 	//ctx->id.mnc FIXME
 
 	DEBUGP(DMAIN, "HNB-REGISTER-REQ from %s\n", ctx->identity_info);
 
-	/* FIXME: Send HNBRegisterAccept */
+	/* Send HNBRegisterAccept */
+	return hnbgw_tx_hnb_register_acc(ctx);
 }
 
-static int hnbgw_rx_ue_register_req(struct hnb_context *ctx, struct UERegisterRequest *req)
+static int hnbgw_rx_ue_register_req(struct hnb_context *ctx, ANY_t *in)
 {
-	UE_Identity *id =
-		FIND_IE(&req->protocolIEs, HNBAP_IEI_UE_Identity);
-	Registration_Cause *reg_cause =
-		FIND_IE(&req->protocolIEs, HNBAP_IEI_RegistrationCause);
-	UE_Capabilities *ue_cap =
-		FIND_IE(&req->protocolIEs, HNBAP_IEI_UE_Capabilities);
+	UERegisterRequestIEs_t ies;
+	struct ue_context *ue;
+	int rc;
 
-	if (!id || !reg_cause || !ue_cap)
-		return -1;
+	rc = hnbap_decode_ueregisterrequesties(&ies, in);
+	if (rc < 0)
+		return rc;
 
-	/* FIXME: Send UERegisterAccept */
+	DEBUGP(DMAIN, "UE-REGSITER-REQ ID_type=%d cause=%ld\n",
+		ies.uE_Identity.present, ies.registration_Cause);
+
+	/* FIXME: convert UE identity into a more palatable format */
+
+	/* Send UERegisterAccept */
+	return hnbgw_tx_ue_register_acc(ue);
 }
 
-static int hnbgw_rx_initiating_msg(struct hnb_context *hnb, struct InitiatingMessage *imsg)
+static int hnbgw_rx_initiating_msg(struct hnb_context *hnb, InitiatingMessage_t *imsg)
 {
 	int rc;
 
 	switch (imsg->procedureCode) {
-	case HNBAP_PC_HNBRegister:	/* 8.2 */
-		if (imsg->value.type != asn1_type_HNBRegisterRequest)
-			return -1;
-		rc = hnbgw_rx_hnb_register_req(hnb, imsg->value.u.data);
+	case ProcedureCode_id_HNBRegister:	/* 8.2 */
+		rc = hnbgw_rx_hnb_register_req(hnb, &imsg->value);
 		break;
-	case HNBAP_PC_HNBDe_Register:	/* 8.3 */
+	case ProcedureCode_id_HNBDe_Register:	/* 8.3 */
 		break;
-	case HNBAP_PC_UERegister: 	/* 8.4 */
-		if (imsg->value.type != asn1_type_UERegisterRequest)
-			return -1;
-		rc = hnbgw_rx_ue_register_req(hnb, imsg->value.u.data);
+	case ProcedureCode_id_UERegister: 	/* 8.4 */
+		rc = hnbgw_rx_ue_register_req(hnb, &imsg->value);
 		break;
-	case HNBAP_PC_UEDe_Register:	/* 8.5 */
+	case ProcedureCode_id_UEDe_Register:	/* 8.5 */
 		break;
-	case HNBAP_PC_ErrorIndication:	/* 8.6 */
-	case HNBAP_PC_TNLUpdate:	/* 8.9 */
-	case HNBAP_PC_HNBConfigTransfer:	/* 8.10 */
-	case HNBAP_PC_RelocationComplete:	/* 8.11 */
-	case HNBAP_PC_U_RNTIQuery:	/* 8.12 */
-	case HNBAP_PC_privateMessage:
+	case ProcedureCode_id_ErrorIndication:	/* 8.6 */
+	case ProcedureCode_id_TNLUpdate:	/* 8.9 */
+	case ProcedureCode_id_HNBConfigTransfer:	/* 8.10 */
+	case ProcedureCode_id_RelocationComplete:	/* 8.11 */
+	case ProcedureCode_id_U_RNTIQuery:	/* 8.12 */
+	case ProcedureCode_id_privateMessage:
 		break;
 	default:
 		break;
 	}
 }
 
-static int hnbgw_rx_successful_outcome_msg(struct hnb_context *hnb, struct SuccessfulOutcome *msg)
+static int hnbgw_rx_successful_outcome_msg(struct hnb_context *hnb, SuccessfulOutcome_t *msg)
 {
 
 }
 
-static int hnbgw_rx_unsuccessful_outcome_msg(struct hnb_context *hnb, struct UnsuccessfulOutcome *msg)
+static int hnbgw_rx_unsuccessful_outcome_msg(struct hnb_context *hnb, UnsuccessfulOutcome_t *msg)
 {
 
 }
 
 
-static int _hnbgw_hnbap_rx(struct hnb_context *hnb, struct HNBAP_PDU *pdu)
+static int _hnbgw_hnbap_rx(struct hnb_context *hnb, HNBAP_PDU_t *pdu)
 {
 	int rc;
 
 	/* it's a bit odd that we can't dispatch on procedure code, but
 	 * that's not possible */
-	switch (pdu->choice) {
-	case HNBAP_PDU_initiatingMessage:
-		rc = hnbgw_rx_initiating_msg(hnb, &pdu->u.initiatingMessage);
+	switch (pdu->present) {
+	case HNBAP_PDU_PR_initiatingMessage:
+		rc = hnbgw_rx_initiating_msg(hnb, &pdu->choice.initiatingMessage);
 		break;
-	case HNBAP_PDU_successfulOutcome:
-		rc = hnbgw_rx_successful_outcome_msg(hnb, &pdu->u.successfulOutcome);
+	case HNBAP_PDU_PR_successfulOutcome:
+		rc = hnbgw_rx_successful_outcome_msg(hnb, &pdu->choice.successfulOutcome);
 		break;
-	case HNBAP_PDU_unsuccessfulOutcome:
-		rc = hnbgw_rx_unsuccessful_outcome_msg(hnb, &pdu->u.unsuccessfulOutcome);
+	case HNBAP_PDU_PR_unsuccessfulOutcome:
+		rc = hnbgw_rx_unsuccessful_outcome_msg(hnb, &pdu->choice.unsuccessfulOutcome);
 		break;
 	default:
 		return -1;
@@ -220,20 +173,20 @@
 
 int hnbgw_hnbap_rx(struct hnb_context *hnb, struct msgb *msg)
 {
-	HNBAP_PDU *pdu;
-	ASN1Error err;
+	HNBAP_PDU_t _pdu, *pdu = &_pdu;
+	asn_dec_rval_t dec_ret;
 	int rc;
 
 	/* decode and handle to _hnbgw_hnbap_rx() */
 
-	rc = asn1_aper_decode(&pdu, asn1_type_HNBAP_PDU, msg->data, msgb_length(msg), &err);
-	if (rc < 0) {
-		LOGP(DMAIN, LOGL_ERROR, "Error in ASN.1 decode (bit=%d): %s\n", err.bit_pos, err.msg);
+	dec_ret = aper_decode(NULL, &asn_DEF_HNBAP_PDU, (void **) &pdu,
+			      msg->data, msgb_length(msg), 0, 0);
+	if (dec_ret.code != RC_OK) {
+		LOGP(DMAIN, LOGL_ERROR, "Error in ASN.1 decode\n");
 		return rc;
 	}
 
 	rc = _hnbgw_hnbap_rx(hnb, pdu);
-	asn1_free_value(asn1_type_HNBAP_PDU, pdu);
 
 	return rc;
 }
diff --git a/src/regen-common-includes.sh b/src/regen-common-includes.sh
new file mode 100755
index 0000000..bc029e6
--- /dev/null
+++ b/src/regen-common-includes.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+for f in `(cd ../asn1/hnbap/asn1c && ls --color=none -1 *.h)`; do echo "#include \"$f\""; done