blob: 9db670e029792882427e223667e4e11ec46ff398 [file] [log] [blame]
Harald Welteba43de42015-08-29 20:33:16 +02001#include <osmocom/core/msgb.h>
Harald Welteb3dae302015-08-30 12:20:09 +02002#include <osmocom/core/utils.h>
Harald Welteba43de42015-08-29 20:33:16 +02003
Harald Welteb3dae302015-08-30 12:20:09 +02004#include <unistd.h>
Harald Welteee77cff2015-08-30 16:57:53 +02005#include <errno.h>
Harald Welteb3dae302015-08-30 12:20:09 +02006#include <string.h>
7
Harald Welte30afef32015-08-30 12:28:29 +02008#include "asn1helpers.h"
9
Harald Welteb3dae302015-08-30 12:20:09 +020010#include "hnbap.h"
Harald Welteba43de42015-08-29 20:33:16 +020011#include "hnbgw.h"
12#include "hnbap_const.h"
13
Harald Welteee77cff2015-08-30 16:57:53 +020014#define IU_MSG_NUM_IES 32
15#define IU_MSG_NUM_EXT_IES 32
16
17/* common structure of a HNBAP / RUA / RANAP message, must have identical
18 * memory footprint as the other messages, such as HNBRegisterRequest */
19struct iu_common_msg {
20 ProtocolIE_Container_1 protocolIEs;
21 BOOL protocolExtensions_option;
22 ProtocolIE_Container_1 protocolExtensions;
23};
24
25/* Add an IE to a Iu message
26 * \param _msg Message to which we want to add
27 * \param[in] ie Information Element to be added (ffasn1c generated struct)
28 * \param[in] iei Information Element Identifier
29 * \param[in] type asn1_type of the IE
30 * \param[in] ext should this be an extension field?
31 */
32int iu_msg_add_ie(void *_msg, void *ie, int iei, ASN1CType *type, int ext)
33{
34 struct iu_common_msg *msg = _msg;
35 ProtocolIE_Field_1 *field;
36
37 if (ext) {
38 msg->protocolExtensions_option = TRUE;
39 if (msg->protocolExtensions.count >= IU_MSG_NUM_EXT_IES)
40 return -ERANGE;
41 field = &msg->protocolExtensions.tab[msg->protocolExtensions.count++];
42 } else {
43 if (msg->protocolIEs.count >= IU_MSG_NUM_IES)
44 return -ERANGE;
45 field = &msg->protocolIEs.tab[msg->protocolIEs.count++];
46 }
47
48 field->id = iei;
49 //field->criticality = FIXME;
50 field->value.type = type;
51 field->value.u.data = ie;
52
53 return 0;
54}
55
56
Harald Welteb3dae302015-08-30 12:20:09 +020057
Harald Welteba43de42015-08-29 20:33:16 +020058static int hnbgw_hnbap_tx(struct HNBAP_PDU *pdu)
59{
60 /* FIXME */
61}
62
63static int hnbgw_tx_hnb_register_acc()
64{
65 /* FIXME */
66 /* Single required response IE: RNC-ID */
67}
68
69static int hnbgw_tx_ue_register_acc()
70{
Harald Welteee77cff2015-08-30 16:57:53 +020071#if 0
72 HNBAP_PDU pdu;
73 HNBRegisterAccept hnb_reg_acc;
74
75 hnb_reg_acc.protocol_IEs
76
77 pdu.choice = HNBAP_PDU_successfulOutcome;
78 pdu.u.successfulOutcome.procedureCode = HNBAP_PC_HNBRegister;
79 pdu.u.successfulOutcome.criticality = ;
80 pdu.u.successfulOutcome.value.type = asn1_type_HNBRegisterAccept;
81 pdu.u.successfulOutcome.value.u.data = &hnb_reg_acc;
82#endif
Harald Welteba43de42015-08-29 20:33:16 +020083 /* FIXME */
84 /* Single required response IE: RNC-ID */
85}
86
Harald Welteee77cff2015-08-30 16:57:53 +020087/* we type-cast to ProtocolIE_Container_1, as all the containers structs have
88 * the same definiition. This is of course ugly, but I see no cleaner way.
89 * Similarly, from the IEI it is clear what the type should be, but in a
90 * statically typed language we can only return 'void *' and hope the caller
91 * doesn the right typecast. */
Harald Welteb3dae302015-08-30 12:20:09 +020092#define FIND_IE(cont, id) find_ie((const struct ProtocolIE_Container_1 *)cont, id)
Harald Welteb3dae302015-08-30 12:20:09 +020093static void *find_ie(const struct ProtocolIE_Container_1 *cont, ProtocolIE_ID id)
Harald Welteba43de42015-08-29 20:33:16 +020094{
Harald Welteb3dae302015-08-30 12:20:09 +020095 int i;
96
Harald Welteee77cff2015-08-30 16:57:53 +020097 /* iterate over the array of IEs in the IE container and look for the first
98 * occurrence of the right IEI */
Harald Welteba43de42015-08-29 20:33:16 +020099 for (i = 0; i < cont->count; i++) {
Harald Welteb3dae302015-08-30 12:20:09 +0200100 ProtocolIE_Field_1 *field = &cont->tab[i];
101 if (field->id == id) {
102 OSMO_ASSERT(field->value.type);
103 /* FIXME: we shoudl check if it is the correct type, not just any type */
104 return field->value.u.data;
105 }
Harald Welteba43de42015-08-29 20:33:16 +0200106 }
107 return NULL;
108}
109
Harald Weltea2e6a7a2015-08-29 21:47:39 +0200110static int hnbgw_rx_hnb_register_req(struct hnb_context *ctx, struct HNBRegisterRequest *req)
Harald Welteba43de42015-08-29 20:33:16 +0200111{
112 HNB_Identity *identity =
Harald Welteb3dae302015-08-30 12:20:09 +0200113 FIND_IE(&req->protocolIEs, HNBAP_IEI_HNB_Identity);
Harald Welteba43de42015-08-29 20:33:16 +0200114 HNB_Location_Information *loc =
Harald Welteb3dae302015-08-30 12:20:09 +0200115 FIND_IE(&req->protocolIEs, HNBAP_IEI_HNB_Location_Information);
Harald Welteba43de42015-08-29 20:33:16 +0200116 PLMNidentity *plmn_id =
Harald Welteb3dae302015-08-30 12:20:09 +0200117 FIND_IE(&req->protocolIEs, HNBAP_IEI_PLMNidentity);
Harald Welteba43de42015-08-29 20:33:16 +0200118 CellIdentity *cell_id =
Harald Welteb3dae302015-08-30 12:20:09 +0200119 FIND_IE(&req->protocolIEs, HNBAP_IEI_CellIdentity);
120 LAC *lac = FIND_IE(&req->protocolIEs, HNBAP_IEI_LAC);
121 RAC *rac = FIND_IE(&req->protocolIEs, HNBAP_IEI_RAC);
122 SAC *sac = FIND_IE(&req->protocolIEs, HNBAP_IEI_SAC);
Harald Welteba43de42015-08-29 20:33:16 +0200123 /* Optional: CSG-ID */
124
125 if(!identity || !loc || !plmn_id || !cell_id || !lac || !rac || !sac)
126 return -1;
127
Harald Weltea2e6a7a2015-08-29 21:47:39 +0200128 /* copy all identity parameters from the message to ctx */
Harald Welte30afef32015-08-30 12:28:29 +0200129 asn1_strncpy(ctx->identity_info, &identity->hNB_Identity_Info,
Harald Welteb3dae302015-08-30 12:20:09 +0200130 sizeof(ctx->identity_info));
Harald Weltea2e6a7a2015-08-29 21:47:39 +0200131 ctx->id.lac = asn1str_to_u16(lac);
132 ctx->id.sac = asn1str_to_u16(sac);
133 ctx->id.rac = asn1str_to_u8(rac);
134 ctx->id.cid = asn1bitstr_to_u32(cell_id);
Harald Welteb3dae302015-08-30 12:20:09 +0200135 //ctx->id.mcc FIXME
136 //ctx->id.mnc FIXME
Harald Weltea2e6a7a2015-08-29 21:47:39 +0200137
Harald Welteee77cff2015-08-30 16:57:53 +0200138 DEBUGP(DMAIN, "HNB-REGISTER-REQ from %s\n", ctx->identity_info);
139
Harald Welteba43de42015-08-29 20:33:16 +0200140 /* FIXME: Send HNBRegisterAccept */
141}
142
Harald Weltea2e6a7a2015-08-29 21:47:39 +0200143static int hnbgw_rx_ue_register_req(struct hnb_context *ctx, struct UERegisterRequest *req)
Harald Welteba43de42015-08-29 20:33:16 +0200144{
145 UE_Identity *id =
Harald Welteb3dae302015-08-30 12:20:09 +0200146 FIND_IE(&req->protocolIEs, HNBAP_IEI_UE_Identity);
Harald Welteba43de42015-08-29 20:33:16 +0200147 Registration_Cause *reg_cause =
Harald Welteb3dae302015-08-30 12:20:09 +0200148 FIND_IE(&req->protocolIEs, HNBAP_IEI_RegistrationCause);
Harald Welteba43de42015-08-29 20:33:16 +0200149 UE_Capabilities *ue_cap =
Harald Welteb3dae302015-08-30 12:20:09 +0200150 FIND_IE(&req->protocolIEs, HNBAP_IEI_UE_Capabilities);
Harald Welteba43de42015-08-29 20:33:16 +0200151
152 if (!id || !reg_cause || !ue_cap)
153 return -1;
154
155 /* FIXME: Send UERegisterAccept */
156}
157
Harald Welteb3dae302015-08-30 12:20:09 +0200158static int hnbgw_rx_initiating_msg(struct hnb_context *hnb, struct InitiatingMessage *imsg)
Harald Welteba43de42015-08-29 20:33:16 +0200159{
160 int rc;
161
Harald Welteb3dae302015-08-30 12:20:09 +0200162 switch (imsg->procedureCode) {
Harald Welteba43de42015-08-29 20:33:16 +0200163 case HNBAP_PC_HNBRegister: /* 8.2 */
Harald Welteb3dae302015-08-30 12:20:09 +0200164 if (imsg->value.type != asn1_type_HNBRegisterRequest)
Harald Welteba43de42015-08-29 20:33:16 +0200165 return -1;
Harald Welteb3dae302015-08-30 12:20:09 +0200166 rc = hnbgw_rx_hnb_register_req(hnb, imsg->value.u.data);
Harald Welteba43de42015-08-29 20:33:16 +0200167 break;
168 case HNBAP_PC_HNBDe_Register: /* 8.3 */
169 break;
170 case HNBAP_PC_UERegister: /* 8.4 */
Harald Welteb3dae302015-08-30 12:20:09 +0200171 if (imsg->value.type != asn1_type_UERegisterRequest)
Harald Welteba43de42015-08-29 20:33:16 +0200172 return -1;
Harald Welteb3dae302015-08-30 12:20:09 +0200173 rc = hnbgw_rx_ue_register_req(hnb, imsg->value.u.data);
Harald Welteba43de42015-08-29 20:33:16 +0200174 break;
175 case HNBAP_PC_UEDe_Register: /* 8.5 */
176 break;
177 case HNBAP_PC_ErrorIndication: /* 8.6 */
178 case HNBAP_PC_TNLUpdate: /* 8.9 */
179 case HNBAP_PC_HNBConfigTransfer: /* 8.10 */
180 case HNBAP_PC_RelocationComplete: /* 8.11 */
181 case HNBAP_PC_U_RNTIQuery: /* 8.12 */
182 case HNBAP_PC_privateMessage:
183 break;
184 default:
185 break;
186 }
187}
188
Harald Welteb3dae302015-08-30 12:20:09 +0200189static int hnbgw_rx_successful_outcome_msg(struct hnb_context *hnb, struct SuccessfulOutcome *msg)
Harald Welteba43de42015-08-29 20:33:16 +0200190{
191
192}
193
Harald Welteb3dae302015-08-30 12:20:09 +0200194static int hnbgw_rx_unsuccessful_outcome_msg(struct hnb_context *hnb, struct UnsuccessfulOutcome *msg)
Harald Welteba43de42015-08-29 20:33:16 +0200195{
196
197}
198
199
Harald Weltea2e6a7a2015-08-29 21:47:39 +0200200static int _hnbgw_hnbap_rx(struct hnb_context *hnb, struct HNBAP_PDU *pdu)
Harald Welteba43de42015-08-29 20:33:16 +0200201{
Harald Welteb3dae302015-08-30 12:20:09 +0200202 int rc;
203
Harald Welteba43de42015-08-29 20:33:16 +0200204 /* it's a bit odd that we can't dispatch on procedure code, but
205 * that's not possible */
206 switch (pdu->choice) {
207 case HNBAP_PDU_initiatingMessage:
Harald Welteb3dae302015-08-30 12:20:09 +0200208 rc = hnbgw_rx_initiating_msg(hnb, &pdu->u.initiatingMessage);
Harald Welteba43de42015-08-29 20:33:16 +0200209 break;
210 case HNBAP_PDU_successfulOutcome:
Harald Welteb3dae302015-08-30 12:20:09 +0200211 rc = hnbgw_rx_successful_outcome_msg(hnb, &pdu->u.successfulOutcome);
Harald Welteba43de42015-08-29 20:33:16 +0200212 break;
213 case HNBAP_PDU_unsuccessfulOutcome:
Harald Welteb3dae302015-08-30 12:20:09 +0200214 rc = hnbgw_rx_unsuccessful_outcome_msg(hnb, &pdu->u.unsuccessfulOutcome);
Harald Welteba43de42015-08-29 20:33:16 +0200215 break;
216 default:
217 return -1;
218 }
219}
220
Harald Weltea2e6a7a2015-08-29 21:47:39 +0200221int hnbgw_hnbap_rx(struct hnb_context *hnb, struct msgb *msg)
Harald Welteba43de42015-08-29 20:33:16 +0200222{
Harald Welteee77cff2015-08-30 16:57:53 +0200223 HNBAP_PDU *pdu;
224 ASN1Error err;
225 int rc;
226
227 /* decode and handle to _hnbgw_hnbap_rx() */
228
229 rc = asn1_aper_decode(&pdu, asn1_type_HNBAP_PDU, msg->data, msgb_length(msg), &err);
230 if (rc < 0) {
231 LOGP(DMAIN, LOGL_ERROR, "Error in ASN.1 decode (bit=%d): %s\n", err.bit_pos, err.msg);
232 return rc;
233 }
234
235 rc = _hnbgw_hnbap_rx(hnb, pdu);
236 asn1_free_value(asn1_type_HNBAP_PDU, pdu);
237
238 return rc;
Harald Welteba43de42015-08-29 20:33:16 +0200239}
240
241
242int hnbgw_hnbap_init(void)
243{
244
245}