diff --git a/src/hnbap_const.h b/src/hnbap_const.h new file mode 100644 index 00000000..7d3dfa3f --- /dev/null +++ b/src/hnbap_const.h @@ -0,0 +1,55 @@ +#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, + HNBAP_IEI_S_RNTIPrefix = 43, + /* FIXME */ +}; diff --git a/src/hnbgw.h b/src/hnbgw.h new file mode 100644 index 00000000..87a5a2fd --- /dev/null +++ b/src/hnbgw.h @@ -0,0 +1,29 @@ +#pragma once + +#include +#include + +struct hnb_context { + /*! Entry in HNB-global list of HNB */ + struct llist_head list; + /*! SCTP socket for Iuh to this specific HNB */ + struct osmo_fd socket; + + /*! copied from HNB-Identity-Info */ + char identity[256]; +}; + +struct ue_context { + struct llist_head list; + uint32_t context_id; +}; + +struct hnb_gw { + struct { + /*! SCTP port for Iuh listening */ + uint16_t iuh_listen_port; + } config; + /*! SCTP listen socket for incoming connections */ + struct osmo_fd listen_fd; + struct llist_head hnb_list; +}; diff --git a/src/hnbgw_hnbap.c b/src/hnbgw_hnbap.c new file mode 100644 index 00000000..9b674adf --- /dev/null +++ b/src/hnbgw_hnbap.c @@ -0,0 +1,138 @@ +#include + +#include "hnbgw.h" +#include "hnbap_const.h" + +static int hnbgw_hnbap_tx(struct HNBAP_PDU *pdu) +{ + /* FIXME */ +} + +static int hnbgw_tx_hnb_register_acc() +{ + /* FIXME */ + /* Single required response IE: RNC-ID */ +} + +static int hnbgw_tx_ue_register_acc() +{ + /* FIXME */ + /* Single required response IE: RNC-ID */ +} + +struct ProtocolIE_Field_1 *find_ie(const struct ProtocolIE_Container_1 *cont, ProtocolIE_ID id) +{ + for (i = 0; i < cont->count; i++) { + if (cont->tab[i].id == id) + return &cont->tab[i]; + } + return NULL; +} + +static int hnbgw_rx_hnb_register_req(struct HNBRegisterRequest *req) +{ + 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 */ + + if(!identity || !loc || !plmn_id || !cell_id || !lac || !rac || !sac) + return -1; + + /* FIXME: Send HNBRegisterAccept */ +} + +static int hnbgw_rx_ue_register_req(struct UERegisterRequest *req) +{ + 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); + + if (!id || !reg_cause || !ue_cap) + return -1; + + /* FIXME: Send UERegisterAccept */ +} + +static int hnbgw_rx_initiating_msg(struct InitiatingMessage *msg) +{ + int rc; + + switch (msg->procedureCode) { + case HNBAP_PC_HNBRegister: /* 8.2 */ + if (msg->value.type != asn1_type_HNBRegisterRequest) + return -1; + rc = hnbgw_rx_hnb_register_req(); + break; + case HNBAP_PC_HNBDe_Register: /* 8.3 */ + break; + case HNBAP_PC_UERegister: /* 8.4 */ + if (msg->value.type != asn1_type_UERegisterRequest) + return -1; + rc = hnbgw_rx_ue_register_req(); + break; + case HNBAP_PC_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: + break; + default: + break; + } +} + +static int hnbgw_rx_successful_outcome_msg(struct SuccessfulOutcome *msg) +{ + +} + +static int hnbgw_rx_unsuccessful_outcome_msg(struct UnsuccessfulOutcome *msg) +{ + +} + + +static int _hnbgw_hnbap_rx(struct HNBAP_PDU *pdu) +{ + /* 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(&pdu->u.initiatingMessage); + break; + case HNBAP_PDU_successfulOutcome: + rc = hnbgw_rx_successful_outcome_msg(&pdu->u.successfulOutcome); + break; + case HNBAP_PDU_unsuccessfulOutcome: + rc = hnbgw_rx_unsuccessful_outcome_msg(&pdu->u.unsuccessfulOutcome); + break; + default: + return -1; + } +} + +int hnbgw_hnbap_rx(struct msgb *msg) +{ + /* FIXME: decode and handle to _hnbgw_hnbap_rx() */ +} + + +int hnbgw_hnbap_init(void) +{ + +}