blob: 2b099afe5812f32de3d64f77cc0a156ce027340f [file] [log] [blame]
Harald Welte350814a2015-09-10 22:32:15 +02001#include <osmocom/core/msgb.h>
2#include <osmocom/core/utils.h>
Harald Welte80401ad2015-09-11 19:48:06 +02003#include <osmocom/gsm/gsm48.h>
Harald Welte350814a2015-09-10 22:32:15 +02004
5#include <unistd.h>
6#include <errno.h>
7#include <string.h>
8
9#include "asn1helpers.h"
10
11#include "hnbgw.h"
Harald Weltee2e5d4d2015-09-10 23:49:45 +020012#include "hnbgw_rua.h"
Harald Welte350814a2015-09-10 22:32:15 +020013//#include "ranap_common.h"
14
15#include "ranap/RANAP_RANAP-PDU.h"
16#include "ranap/RANAP_ResetAcknowledge.h"
17#include "ranap/RANAP_Reset.h"
18#include "ranap/RANAP_ProtocolIE-ID.h"
19#include "ranap/RANAP_Cause.h"
20#include "ranap/RANAP_CN-DomainIndicator.h"
21#include "ranap/RANAP_GlobalRNC-ID.h"
22#include "ranap/RANAP_CriticalityDiagnostics.h"
23
Harald Welte350814a2015-09-10 22:32:15 +020024/***********************************************************************
25 * BEGIN auto-generated copy+pasted
26 ***********************************************************************/
27
28/* this is copy+pasted from the asn1tostruct generated code that doesn't
29 * compile as a whole */
30
31#define RANAP_DEBUG(x, args ...) DEBUGP(0, x, ## args)
32
33extern int asn1_xer_print;
34
35struct msgb *ranap_generate_successful_outcome(
36 e_RANAP_ProcedureCode procedureCode,
37 RANAP_Criticality_t criticality,
38 asn_TYPE_descriptor_t * td,
39 void *sptr);
40
41RANAP_IE_t *ranap_new_ie(RANAP_ProtocolIE_ID_t id, RANAP_Criticality_t criticality,
42 asn_TYPE_descriptor_t *type, void *sptr);
43
44#define RESETIES_RANAP_GLOBALRNC_ID_PRESENT (1 << 0)
45
46typedef struct RANAP_ResetIEs_s {
47 uint16_t presenceMask;
48 RANAP_Cause_t cause;
49 RANAP_CN_DomainIndicator_t cN_DomainIndicator;
50 RANAP_GlobalRNC_ID_t globalRNC_ID; ///< Optional field
51} RANAP_ResetIEs_t;
52
53#define RESETACKNOWLEDGEIES_RANAP_CRITICALITYDIAGNOSTICS_PRESENT (1 << 0)
54#define RESETACKNOWLEDGEIES_RANAP_GLOBALRNC_ID_PRESENT (1 << 1)
55
56typedef struct RANAP_ResetAcknowledgeIEs_s {
57 uint16_t presenceMask;
58 RANAP_CN_DomainIndicator_t cN_DomainIndicator;
59 RANAP_CriticalityDiagnostics_t criticalityDiagnostics; ///< Optional field
60 RANAP_GlobalRNC_ID_t globalRNC_ID; ///< Optional field
61} RANAP_ResetAcknowledgeIEs_t;
62
63int ranap_decode_reseties(
64 RANAP_ResetIEs_t *resetIEs,
65 ANY_t *any_p) {
66
67 RANAP_Reset_t reset;
68 RANAP_Reset_t *reset_p = &reset;
69 int i, decoded = 0;
70 int tempDecoded = 0;
71 assert(any_p != NULL);
72 assert(resetIEs != NULL);
73
74 RANAP_DEBUG("Decoding message RANAP_ResetIEs (%s:%d)\n", __FILE__, __LINE__);
75
76 ANY_to_type_aper(any_p, &asn_DEF_RANAP_Reset, (void**)&reset_p);
77
78 for (i = 0; i < reset_p->reset_ies.list.count; i++) {
79 RANAP_IE_t *ie_p;
80 ie_p = reset_p->reset_ies.list.array[i];
81 switch(ie_p->id) {
82 case RANAP_ProtocolIE_ID_id_Cause:
83 {
84 RANAP_Cause_t ranaP_Cause;
85 RANAP_Cause_t *ranaP_Cause_p = &ranaP_Cause;
86 tempDecoded = ANY_to_type_aper(&ie_p->value, &asn_DEF_RANAP_Cause, (void**)&ranaP_Cause_p);
87 if (tempDecoded < 0) {
88 RANAP_DEBUG("Decoding of IE cause failed\n");
89 return -1;
90 }
91 decoded += tempDecoded;
92 if (asn1_xer_print)
93 xer_fprint(stdout, &asn_DEF_RANAP_Cause, ranaP_Cause_p);
94 memcpy(&resetIEs->cause, ranaP_Cause_p, sizeof(RANAP_Cause_t));
95 } break;
96 case RANAP_ProtocolIE_ID_id_CN_DomainIndicator:
97 {
98 RANAP_CN_DomainIndicator_t ranaP_CNDomainIndicator;
99 RANAP_CN_DomainIndicator_t *ranaP_CNDomainIndicator_p = &ranaP_CNDomainIndicator;
100 tempDecoded = ANY_to_type_aper(&ie_p->value, &asn_DEF_RANAP_CN_DomainIndicator, (void**)&ranaP_CNDomainIndicator_p);
101 if (tempDecoded < 0) {
102 RANAP_DEBUG("Decoding of IE cN_DomainIndicator failed\n");
103 return -1;
104 }
105 decoded += tempDecoded;
106 if (asn1_xer_print)
107 xer_fprint(stdout, &asn_DEF_RANAP_CN_DomainIndicator, ranaP_CNDomainIndicator_p);
108 memcpy(&resetIEs->cN_DomainIndicator, ranaP_CNDomainIndicator_p, sizeof(RANAP_CN_DomainIndicator_t));
109 } break;
110 /* Optional field */
111 case RANAP_ProtocolIE_ID_id_GlobalRNC_ID:
112 {
113#if 0
114 RANAP_GlobalRNC_ID_t ranaP_GlobalRNCID;
115 RANAP_GlobalRNC_ID_t *ranaP_GlobalRNCID_p = &ranaP_GlobalRNCID;
116 resetIEs->presenceMask |= RESETIES_RANAP_GLOBALRNC_ID_PRESENT;
117 tempDecoded = ANY_to_type_aper(&ie_p->value, &asn_DEF_RANAP_GlobalRNC_ID, (void**)&ranaP_GlobalRNCID_p);
118 if (tempDecoded < 0) {
119 RANAP_DEBUG("Decoding of IE globalRNC_ID failed\n");
120 return -1;
121 }
122 decoded += tempDecoded;
123 if (asn1_xer_print)
124 xer_fprint(stdout, &asn_DEF_RANAP_GlobalRNC_ID, ranaP_GlobalRNCID_p);
125 memcpy(&resetIEs->globalRNC_ID, ranaP_GlobalRNCID_p, sizeof(RANAP_GlobalRNC_ID_t));
126#endif
127 } break;
128 default:
129 RANAP_DEBUG("Unknown protocol IE id (%d) for message reseties\n", (int)ie_p->id);
130 return -1;
131 }
132 }
133 return decoded;
134}
135
136int ranap_encode_resetacknowledgeies(
137 RANAP_ResetAcknowledge_t *resetAcknowledge,
138 RANAP_ResetAcknowledgeIEs_t *resetAcknowledgeIEs) {
139
140 RANAP_IE_t *ie;
141
142 if ((ie = ranap_new_ie(RANAP_ProtocolIE_ID_id_CN_DomainIndicator,
143 RANAP_Criticality_reject,
144 &asn_DEF_RANAP_CN_DomainIndicator,
145 &resetAcknowledgeIEs->cN_DomainIndicator)) == NULL) {
146 return -1;
147 }
148 ASN_SEQUENCE_ADD(&resetAcknowledge->resetAcknowledge_ies.list, ie);
149
150 /* Optional field */
151 if ((resetAcknowledgeIEs->presenceMask & RESETACKNOWLEDGEIES_RANAP_CRITICALITYDIAGNOSTICS_PRESENT)
152 == RESETACKNOWLEDGEIES_RANAP_CRITICALITYDIAGNOSTICS_PRESENT) {
153 if ((ie = ranap_new_ie(RANAP_ProtocolIE_ID_id_CriticalityDiagnostics,
154 RANAP_Criticality_ignore,
155 &asn_DEF_RANAP_CriticalityDiagnostics,
156 &resetAcknowledgeIEs->criticalityDiagnostics)) == NULL) {
157 return -1;
158 }
159 ASN_SEQUENCE_ADD(&resetAcknowledge->resetAcknowledge_ies.list, ie);
160 }
161
162 /* Optional field */
163 if ((resetAcknowledgeIEs->presenceMask & RESETACKNOWLEDGEIES_RANAP_GLOBALRNC_ID_PRESENT)
164 == RESETACKNOWLEDGEIES_RANAP_GLOBALRNC_ID_PRESENT) {
165 if ((ie = ranap_new_ie(RANAP_ProtocolIE_ID_id_GlobalRNC_ID,
166 RANAP_Criticality_ignore,
167 &asn_DEF_RANAP_GlobalRNC_ID,
168 &resetAcknowledgeIEs->globalRNC_ID)) == NULL) {
169 return -1;
170 }
171 ASN_SEQUENCE_ADD(&resetAcknowledge->resetAcknowledge_ies.list, ie);
172 }
173
174 return 0;
175}
176
Harald Weltecc27beb2015-09-11 18:45:39 +0200177#include "ranap/RANAP_InitialUE-Message.h"
178#include "ranap/RANAP_CN-DomainIndicator.h"
179#include "ranap/RANAP_LAI.h"
180#include "ranap/RANAP_SAI.h"
181#include "ranap/RANAP_NAS-PDU.h"
182#include "ranap/RANAP_IuSignallingConnectionIdentifier.h"
183#include "ranap/RANAP_GlobalCN-ID.h"
184
185typedef struct RANAP_InitialUE_MessageIEs_s {
186 RANAP_CN_DomainIndicator_t cN_DomainIndicator;
187 RANAP_LAI_t lai;
188 RANAP_SAI_t sai;
189 RANAP_NAS_PDU_t nas_pdu;
190 RANAP_IuSignallingConnectionIdentifier_t iuSigConId;
191 RANAP_GlobalRNC_ID_t globalRNC_ID;
192} RANAP_InitialUE_MessageIEs_t;
193
194int ranap_decode_initialue_messageies(
195 RANAP_InitialUE_MessageIEs_t *initialUE_MessageIEs,
196 ANY_t *any_p) {
197
198 RANAP_InitialUE_Message_t initialUE_Message;
199 RANAP_InitialUE_Message_t *initialUE_Message_p = &initialUE_Message;
200 int i, decoded = 0;
201 int tempDecoded = 0;
202 assert(any_p != NULL);
203 assert(initialUE_MessageIEs != NULL);
204
205 RANAP_DEBUG("Decoding message RANAP_InitialUE_MessageIEs (%s:%d)\n", __FILE__, __LINE__);
206
207 ANY_to_type_aper(any_p, &asn_DEF_RANAP_InitialUE_Message, (void**)&initialUE_Message_p);
208
209 for (i = 0; i < initialUE_Message_p->initialUE_Message_ies.list.count; i++) {
210 RANAP_IE_t *ie_p;
211 ie_p = initialUE_Message_p->initialUE_Message_ies.list.array[i];
212 switch(ie_p->id) {
213 case RANAP_ProtocolIE_ID_id_CN_DomainIndicator:
214 {
215 RANAP_CN_DomainIndicator_t ranaP_CNDomainIndicator;
216 RANAP_CN_DomainIndicator_t *ranaP_CNDomainIndicator_p = &ranaP_CNDomainIndicator;
217 tempDecoded = ANY_to_type_aper(&ie_p->value, &asn_DEF_RANAP_CN_DomainIndicator, (void**)&ranaP_CNDomainIndicator_p);
218 if (tempDecoded < 0) {
219 RANAP_DEBUG("Decoding of IE cN_DomainIndicator failed\n");
220 return -1;
221 }
222 decoded += tempDecoded;
223 if (asn1_xer_print)
224 xer_fprint(stdout, &asn_DEF_RANAP_CN_DomainIndicator, ranaP_CNDomainIndicator_p);
225 memcpy(&initialUE_MessageIEs->cN_DomainIndicator, ranaP_CNDomainIndicator_p, sizeof(RANAP_CN_DomainIndicator_t));
226 } break;
227 case RANAP_ProtocolIE_ID_id_LAI:
228 {
229 RANAP_LAI_t ranap_lai;
230 RANAP_LAI_t *ranap_lai_p = &ranap_lai;
231 tempDecoded = ANY_to_type_aper(&ie_p->value, &asn_DEF_RANAP_LAI, (void**)&ranap_lai_p);
232 if (tempDecoded < 0) {
233 RANAP_DEBUG("Decoding of IE lai failed\n");
234 return -1;
235 }
236 decoded += tempDecoded;
237 if (asn1_xer_print)
238 xer_fprint(stdout, &asn_DEF_RANAP_LAI, ranap_lai_p);
239 memcpy(&initialUE_MessageIEs->lai, ranap_lai_p, sizeof(RANAP_LAI_t));
240 } break;
241 case RANAP_ProtocolIE_ID_id_SAI:
242 {
243 RANAP_SAI_t ranap_sai;
244 RANAP_SAI_t *ranap_sai_p = &ranap_sai;
245 tempDecoded = ANY_to_type_aper(&ie_p->value, &asn_DEF_RANAP_SAI, (void**)&ranap_sai_p);
246 if (tempDecoded < 0) {
247 RANAP_DEBUG("Decoding of IE sai failed\n");
248 return -1;
249 }
250 decoded += tempDecoded;
251 if (asn1_xer_print)
252 xer_fprint(stdout, &asn_DEF_RANAP_SAI, ranap_sai_p);
253 memcpy(&initialUE_MessageIEs->sai, ranap_sai_p, sizeof(RANAP_SAI_t));
254 } break;
255 case RANAP_ProtocolIE_ID_id_NAS_PDU:
256 {
257 RANAP_NAS_PDU_t ranap_naspdu;
258 RANAP_NAS_PDU_t *ranap_naspdu_p = &ranap_naspdu;
259 tempDecoded = ANY_to_type_aper(&ie_p->value, &asn_DEF_RANAP_NAS_PDU, (void**)&ranap_naspdu_p);
260 if (tempDecoded < 0) {
261 RANAP_DEBUG("Decoding of IE nas_pdu failed\n");
262 return -1;
263 }
264 decoded += tempDecoded;
265 if (asn1_xer_print)
266 xer_fprint(stdout, &asn_DEF_RANAP_NAS_PDU, ranap_naspdu_p);
267 memcpy(&initialUE_MessageIEs->nas_pdu, ranap_naspdu_p, sizeof(RANAP_NAS_PDU_t));
268 } break;
269 case RANAP_ProtocolIE_ID_id_IuSigConId:
270 {
271 RANAP_IuSignallingConnectionIdentifier_t ranaP_IuSignallingConnectionIdentifier;
272 RANAP_IuSignallingConnectionIdentifier_t *ranaP_IuSignallingConnectionIdentifier_p = &ranaP_IuSignallingConnectionIdentifier;
273 tempDecoded = ANY_to_type_aper(&ie_p->value, &asn_DEF_RANAP_IuSignallingConnectionIdentifier, (void**)&ranaP_IuSignallingConnectionIdentifier_p);
274 if (tempDecoded < 0) {
275 RANAP_DEBUG("Decoding of IE iuSigConId failed\n");
276 return -1;
277 }
278 decoded += tempDecoded;
279 if (asn1_xer_print)
280 xer_fprint(stdout, &asn_DEF_RANAP_IuSignallingConnectionIdentifier, ranaP_IuSignallingConnectionIdentifier_p);
281 memcpy(&initialUE_MessageIEs->iuSigConId, ranaP_IuSignallingConnectionIdentifier_p, sizeof(RANAP_IuSignallingConnectionIdentifier_t));
282 } break;
283 case RANAP_ProtocolIE_ID_id_GlobalRNC_ID:
284 {
285 RANAP_GlobalRNC_ID_t ranaP_GlobalRNCID;
286 RANAP_GlobalRNC_ID_t *ranaP_GlobalRNCID_p = &ranaP_GlobalRNCID;
287 tempDecoded = ANY_to_type_aper(&ie_p->value, &asn_DEF_RANAP_GlobalRNC_ID, (void**)&ranaP_GlobalRNCID_p);
288 if (tempDecoded < 0) {
289 RANAP_DEBUG("Decoding of IE globalRNC_ID failed\n");
290 return -1;
291 }
292 decoded += tempDecoded;
293 if (asn1_xer_print)
294 xer_fprint(stdout, &asn_DEF_RANAP_GlobalRNC_ID, ranaP_GlobalRNCID_p);
295 memcpy(&initialUE_MessageIEs->globalRNC_ID, ranaP_GlobalRNCID_p, sizeof(RANAP_GlobalRNC_ID_t));
296 } break;
297 default:
298 RANAP_DEBUG("Unknown protocol IE id (%d) for message initialue_messageies\n", (int)ie_p->id);
299 return -1;
300 }
301 }
302 return decoded;
303}
304
305
Harald Welte350814a2015-09-10 22:32:15 +0200306/***********************************************************************
307 * END auto-generated copy+pasted
308 ***********************************************************************/
309
Harald Weltee2e5d4d2015-09-10 23:49:45 +0200310static int ranap_tx_reset_ack(struct hnb_context *hnb,
311 RANAP_CN_DomainIndicator_t domain)
Harald Welte350814a2015-09-10 22:32:15 +0200312{
Harald Weltee2e5d4d2015-09-10 23:49:45 +0200313 RANAP_ResetAcknowledge_t out;
314 RANAP_ResetAcknowledgeIEs_t ies;
315 struct msgb *msg;
316 int rc;
Harald Welte350814a2015-09-10 22:32:15 +0200317
318 memset(&ies, 0, sizeof(ies));
Harald Weltee2e5d4d2015-09-10 23:49:45 +0200319 ies.cN_DomainIndicator = domain;
Harald Welte350814a2015-09-10 22:32:15 +0200320
Harald Weltee2e5d4d2015-09-10 23:49:45 +0200321 memset(&out, 0, sizeof(out));
322 rc = ranap_encode_resetacknowledgeies(&out, &ies);
323 if (rc < 0) {
324 LOGP(DMAIN, LOGL_ERROR, "error encoding reset ack IEs: %d\n", rc);
325 return rc;
326 }
327
328 msg = ranap_generate_successful_outcome(RANAP_ProcedureCode_id_Reset,
329 RANAP_Criticality_reject,
330 &asn_DEF_RANAP_ResetAcknowledge,
331 &out);
332 if (!msg)
333 return -1;
334
335 msg->dst = hnb;
336
337 rc = rua_tx_udt(msg);
338
339 return rc;
Harald Welte350814a2015-09-10 22:32:15 +0200340}
Harald Welte350814a2015-09-10 22:32:15 +0200341
342static int ranap_rx_init_reset(struct hnb_context *hnb, ANY_t *in)
343{
344 RANAP_ResetIEs_t ies;
345 int rc;
346
347 rc = ranap_decode_reseties(&ies, in);
348 if (rc < 0)
349 return rc;
350
351 DEBUGP(DMAIN, "RESET.req\n");
352
Harald Welte80401ad2015-09-11 19:48:06 +0200353 /* FIXME: Actually we have to wait for some guard time? */
354 /* FIXME: Reset all resources related to this HNB/RNC */
Harald Weltee2e5d4d2015-09-10 23:49:45 +0200355 ranap_tx_reset_ack(hnb, ies.cN_DomainIndicator);
356
Harald Welte350814a2015-09-10 22:32:15 +0200357 return 0;
358}
359
Harald Welte80401ad2015-09-11 19:48:06 +0200360int ranap_parse_lai(struct gprs_ra_id *ra_id, const RANAP_LAI_t *lai)
361{
362 uint8_t *ptr = lai->pLMNidentity.buf;
363
364 /* TS 25.413 9.2.3.55 */
365 if (lai->pLMNidentity.size != 3)
366 return -1;
367
368 ra_id->mcc = (ptr[0] & 0xF) * 100 +
369 (ptr[0] >> 4) * 10 +
370 (ptr[1] & 0xF);
371 ra_id->mnc = (ptr[2] & 0xF) +
372 (ptr[2] >> 4) * 10;
373 if ((ptr[1] >> 4) != 0xF)
374 ra_id->mnc += (ptr[1] >> 4) * 100;
375
376 ra_id->lac = asn1str_to_u16(&lai->lAC);
377
378 /* TS 25.413 9.2.3.6 */
379 if (ra_id->lac == 0 || ra_id->lac == 0xfffe)
380 return -1;
381
382 return 0;
383}
384
385static int ranap_rx_init_ue_msg(struct hnb_context *hnb, ANY_t *in)
386{
387 RANAP_InitialUE_MessageIEs_t ies;
388 struct gprs_ra_id ra_id;
389 int rc;
390
391 rc = ranap_decode_initialue_messageies(&ies, in);
392 if (rc < 0)
393 return rc;
394
395 /* location area ID of the serving cell */
396 ranap_parse_lai(&ra_id, &ies.lai);
397
398 DEBUGP(DMAIN, "%u-%u-%u: InitialUE: %s\n", ra_id.mcc, ra_id.mnc,
399 ra_id.lac, osmo_hexdump(ies.nas_pdu.buf, ies.nas_pdu.size));
400 /* FIXME: hand NAS PDU into MSC */
401
402 return 0;
403}
404
Harald Welte350814a2015-09-10 22:32:15 +0200405static int ranap_rx_initiating_msg(struct hnb_context *hnb, RANAP_InitiatingMessage_t *imsg)
406{
407 int rc;
408
409 switch (imsg->procedureCode) {
410 case RANAP_ProcedureCode_id_Reset:
411 rc = ranap_rx_init_reset(hnb, &imsg->value);
412 break;
Harald Welte80401ad2015-09-11 19:48:06 +0200413 case RANAP_ProcedureCode_id_InitialUE_Message:
414 rc = ranap_rx_init_ue_msg(hnb, &imsg->value);
415 break;
Harald Welte350814a2015-09-10 22:32:15 +0200416 }
417}
418
419static int _hnbgw_ranap_rx(struct hnb_context *hnb, RANAP_RANAP_PDU_t *pdu)
420{
421 int rc;
422
423 switch (pdu->present) {
424 case RANAP_RANAP_PDU_PR_initiatingMessage:
425 rc = ranap_rx_initiating_msg(hnb, &pdu->choice.initiatingMessage);
426 break;
427 case RANAP_RANAP_PDU_PR_successfulOutcome:
428 break;
429 case RANAP_RANAP_PDU_PR_unsuccessfulOutcome:
430 break;
431 default:
432 break;
433 }
434}
435
436
437int hnbgw_ranap_rx(struct msgb *msg, uint8_t *data, size_t len)
438{
439 RANAP_RANAP_PDU_t _pdu, *pdu = &_pdu;
440 asn_dec_rval_t dec_ret;
441 int rc;
442
443 memset(pdu, 0, sizeof(*pdu));
444 dec_ret = aper_decode(NULL,&asn_DEF_RANAP_RANAP_PDU, (void **) &pdu,
445 data, len, 0, 0);
446 if (dec_ret.code != RC_OK) {
447 LOGP(DMAIN, LOGL_ERROR, "Error in RANAP ASN.1 decode\n");
448 return rc;
449 }
450
451 rc = _hnbgw_ranap_rx(msg->dst, pdu);
452
453 return rc;
454}
455
456int hnbgw_ranap_init(void)
457{
458
459}