blob: 75b4ff910be9197ca37ce7d5448e1d4a3004e5c8 [file] [log] [blame]
Harald Weltef8db61b2015-12-18 17:29:59 +01001/* high-level RANAP messsage generation code */
2
3/* (C) 2015 by Harald Welte <laforge@gnumonks.org>
4 * All Rights Reserved
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Affero General Public License for more details.
15 *
16 * You should have received a copy of the GNU Affero General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21#include <osmocom/core/utils.h>
22#include <osmocom/core/msgb.h>
23
24#include "asn1helpers.h"
Neels Hofmeyr96979af2016-01-05 15:19:44 +010025#include <osmocom/ranap/iu_helpers.h>
Harald Weltef8db61b2015-12-18 17:29:59 +010026
Neels Hofmeyr96979af2016-01-05 15:19:44 +010027#include <osmocom/ranap/ranap_common.h>
28#include <osmocom/ranap/ranap_ies_defs.h>
29#include <osmocom/ranap/ranap_msg_factory.h>
Harald Weltef8db61b2015-12-18 17:29:59 +010030
Harald Weltebdf3fd12016-01-03 17:04:09 +010031#define DRANAP _ranap_DRANAP
Harald Weltef8db61b2015-12-18 17:29:59 +010032
33/*! \brief allocate a new long and assing a value to it */
34static long *new_long(long in)
35{
36 long *out = CALLOC(1, sizeof(long));
37 *out = in;
38 return out;
39}
40
Harald Weltec4338de2015-12-24 00:40:52 +010041/*! \brief generate RANAP RESET message */
42struct msgb *ranap_new_msg_reset(RANAP_CN_DomainIndicator_t domain,
Harald Welte1cdb81d2016-01-01 16:21:05 +010043 const RANAP_Cause_t *cause)
Harald Weltec4338de2015-12-24 00:40:52 +010044{
45 RANAP_ResetIEs_t ies;
46 RANAP_Reset_t out;
47 struct msgb *msg;
48 int rc;
49
50 memset(&ies, 0, sizeof(ies));
51 ies.cN_DomainIndicator = domain;
52 if (cause)
53 memcpy(&ies.cause, cause, sizeof(ies.cause));
54
55 memset(&out, 0, sizeof(out));
56 rc = ranap_encode_reseties(&out, &ies);
57 if (rc < 0) {
58 LOGP(DRANAP, LOGL_ERROR, "error encoding reset IEs: %d\n", rc);
59 return NULL;
60 }
61
62 msg = ranap_generate_initiating_message(RANAP_ProcedureCode_id_Reset,
63 RANAP_Criticality_reject,
64 &asn_DEF_RANAP_Reset,
65 &out);
66
67 /* release dynamic allocations attached to dt */
68 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_Reset, &out);
69
70 return msg;
71}
72
73/*! \brief generate RANAP RESET ACK message */
74struct msgb *ranap_new_msg_reset_ack(RANAP_CN_DomainIndicator_t domain,
75 RANAP_GlobalRNC_ID_t *rnc_id)
76{
77 RANAP_ResetAcknowledgeIEs_t ies;
78 RANAP_ResetAcknowledge_t out;
79 struct msgb *msg;
80 int rc;
81
82 memset(&ies, 0, sizeof(ies));
83 ies.cN_DomainIndicator = domain;
84
85 /* The RNC shall include the globalRNC_ID in the RESET
86 * ACKNOWLEDGE message to the CN */
87 if (rnc_id) {
88 ies.presenceMask = RESETACKNOWLEDGEIES_RANAP_GLOBALRNC_ID_PRESENT;
Harald Welte74157f62016-01-01 16:43:59 +010089 OCTET_STRING_noalloc(&ies.globalRNC_ID.pLMNidentity,
Harald Welteea98b6f2015-12-24 15:09:06 +010090 rnc_id->pLMNidentity.buf,
91 rnc_id->pLMNidentity.size);
Harald Weltec4338de2015-12-24 00:40:52 +010092 ies.globalRNC_ID.rNC_ID = rnc_id->rNC_ID;
93 }
94
95 /* FIXME: Do we need criticalityDiagnostics */
96
97 memset(&out, 0, sizeof(out));
98 rc = ranap_encode_resetacknowledgeies(&out, &ies);
99 if (rc < 0) {
100 LOGP(DRANAP, LOGL_ERROR, "error encoding reset ack IEs: %d\n", rc);
101 return NULL;
102 }
103
104 msg = ranap_generate_successful_outcome(RANAP_ProcedureCode_id_Reset,
105 RANAP_Criticality_reject,
106 &asn_DEF_RANAP_ResetAcknowledge,
107 &out);
108
109 /* release dynamic allocations attached to dt */
110 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_ResetAcknowledge, &out);
111
112 return msg;
113}
114
Harald Welteea98b6f2015-12-24 15:09:06 +0100115/*! \brief generate RANAP INITIAL UE message */
116struct msgb *ranap_new_msg_initial_ue(uint32_t conn_id, int is_ps,
117 RANAP_GlobalRNC_ID_t *rnc_id,
118 uint8_t *nas_pdu, unsigned int nas_len)
119{
120 RANAP_InitialUE_MessageIEs_t ies;
121 RANAP_InitialUE_Message_t out;
122 struct msgb *msg;
123 uint32_t ctxidbuf;
124 int rc;
125 uint16_t buf0 = 0x2342;
126
127 memset(&ies, 0, sizeof(ies));
128 if (is_ps)
129 ies.cN_DomainIndicator = RANAP_CN_DomainIndicator_ps_domain;
130 else
131 ies.cN_DomainIndicator = RANAP_CN_DomainIndicator_cs_domain;
132
Harald Welte74157f62016-01-01 16:43:59 +0100133 OCTET_STRING_noalloc(&ies.lai.pLMNidentity, rnc_id->pLMNidentity.buf, rnc_id->pLMNidentity.size);
134 OCTET_STRING_noalloc(&ies.lai.lAC, (uint8_t *)&buf0, sizeof(buf0));
Harald Welteea98b6f2015-12-24 15:09:06 +0100135
Harald Welte74157f62016-01-01 16:43:59 +0100136 OCTET_STRING_noalloc(&ies.sai.pLMNidentity, rnc_id->pLMNidentity.buf, rnc_id->pLMNidentity.size);
137 OCTET_STRING_noalloc(&ies.sai.lAC, (uint8_t *)&buf0, sizeof(buf0));
138 OCTET_STRING_noalloc(&ies.sai.sAC, (uint8_t *)&buf0, sizeof(buf0));
Harald Welteea98b6f2015-12-24 15:09:06 +0100139
Harald Welte74157f62016-01-01 16:43:59 +0100140 OCTET_STRING_noalloc(&ies.nas_pdu, nas_pdu, nas_len);
Harald Welteea98b6f2015-12-24 15:09:06 +0100141 asn1_u24_to_bitstring(&ies.iuSigConId, &ctxidbuf, conn_id);
Harald Welte74157f62016-01-01 16:43:59 +0100142 OCTET_STRING_noalloc(&ies.globalRNC_ID.pLMNidentity, rnc_id->pLMNidentity.buf, rnc_id->pLMNidentity.size);
Harald Welteea98b6f2015-12-24 15:09:06 +0100143 ies.globalRNC_ID.rNC_ID = rnc_id->rNC_ID;
144
145 memset(&out, 0, sizeof(out));
146 rc = ranap_encode_initialue_messageies(&out, &ies);
147 if (rc < 0) {
148 LOGP(DRANAP, LOGL_ERROR, "error encoding initial UE IEs: %d\n", rc);
149 return NULL;
150 }
151
152 msg = ranap_generate_initiating_message(RANAP_ProcedureCode_id_InitialUE_Message,
153 RANAP_Criticality_reject,
154 &asn_DEF_RANAP_InitialUE_Message,
155 &out);
156
157 /* release dynamic allocations attached to dt */
158 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_InitialUE_Message, &out);
159
160 return msg;
161}
162
163
Harald Weltef8db61b2015-12-18 17:29:59 +0100164/*! \brief generate RANAP DIRECT TRANSFER message */
165struct msgb *ranap_new_msg_dt(uint8_t sapi, const uint8_t *nas, unsigned int nas_len)
166{
167 RANAP_DirectTransferIEs_t ies;
168 RANAP_DirectTransfer_t dt;
169 struct msgb *msg;
170 int rc;
171
172 memset(&ies, 0, sizeof(ies));
173 memset(&dt, 0, sizeof(dt));
174
175 /* only SAPI optional field shall be present for CN->RNC */
176 ies.presenceMask = DIRECTTRANSFERIES_RANAP_SAPI_PRESENT;
177
178 if (sapi == 3)
179 ies.sapi = RANAP_SAPI_sapi_3;
180 else
181 ies.sapi = RANAP_SAPI_sapi_0;
182
Harald Welte74157f62016-01-01 16:43:59 +0100183 /* Avoid copying + later freeing of OCTET STRING */
184 OCTET_STRING_noalloc(&ies.nas_pdu, nas, nas_len);
Harald Weltef8db61b2015-12-18 17:29:59 +0100185
186 /* ies -> dt */
187 rc = ranap_encode_directtransferies(&dt, &ies);
188
189 /* dt -> msg */
190 msg = ranap_generate_initiating_message(RANAP_ProcedureCode_id_DirectTransfer,
191 RANAP_Criticality_reject,
192 &asn_DEF_RANAP_DirectTransfer,
193 &dt);
194
195 /* release dynamic allocations attached to dt */
196 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_DirectTransfer, &dt);
197
198 return msg;
199}
200
201static const enum RANAP_IntegrityProtectionAlgorithm ip_alg[2] = {
202 RANAP_IntegrityProtectionAlgorithm_standard_UMTS_integrity_algorithm_UIA1,
203 RANAP_IntegrityProtectionAlgorithm_standard_UMTS_integrity_algorithm_UIA2,
204};
205
206static const RANAP_EncryptionAlgorithm_t enc_alg[2] = {
207 RANAP_EncryptionAlgorithm_standard_UMTS_encryption_algorith_UEA1,
208 RANAP_EncryptionAlgorithm_standard_UMTS_encryption_algorithm_UEA2,
209};
210
211/*! \brief generate RANAP SECURITY MODE COMMAND message */
212struct msgb *ranap_new_msg_sec_mod_cmd(const uint8_t *ik, const uint8_t *ck)
213{
214 RANAP_SecurityModeCommandIEs_t ies;
215 RANAP_SecurityModeCommand_t out;
216 struct msgb *msg;
217 int i, rc;
218
219 memset(&ies, 0, sizeof(ies));
220 memset(&out, 0, sizeof(out));
221
Harald Weltef8db61b2015-12-18 17:29:59 +0100222 for (i = 0; i < ARRAY_SIZE(ip_alg); i++) {
223 /* needs to be dynamically allocated, as
224 * SET_OF_free() will call FREEMEM() on it */
225 RANAP_IntegrityProtectionAlgorithm_t *alg = CALLOC(1, sizeof(*alg));
226 *alg = ip_alg[i];
227 ASN_SEQUENCE_ADD(&ies.integrityProtectionInformation.permittedAlgorithms, alg);
228 }
229
230 BIT_STRING_fromBuf(&ies.integrityProtectionInformation.key, ik, 16*8);
231
232 if (ck) {
Harald Welte2cf0d8f2015-12-28 13:13:47 +0100233 ies.presenceMask = SECURITYMODECOMMANDIES_RANAP_ENCRYPTIONINFORMATION_PRESENT;
Harald Weltef8db61b2015-12-18 17:29:59 +0100234 for (i = 0; i < ARRAY_SIZE(ip_alg); i++) {
235 /* needs to be dynamically allocated, as
236 * SET_OF_free() will call FREEMEM() on it */
237 RANAP_EncryptionAlgorithm_t *alg = CALLOC(1, sizeof(*alg));
238 *alg = enc_alg[i];
239 ASN_SEQUENCE_ADD(&ies.encryptionInformation.permittedAlgorithms, alg);
240 }
241 BIT_STRING_fromBuf(&ies.encryptionInformation.key, ck, 16*8);
242 }
243
244 ies.keyStatus = RANAP_KeyStatus_new; /* FIXME */
245
246 /* ies -> out */
247 rc = ranap_encode_securitymodecommandies(&out, &ies);
248
249 /* release dynamic allocations attached to ies */
250 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_IntegrityProtectionInformation, &ies.integrityProtectionInformation);
Harald Welte2cf0d8f2015-12-28 13:13:47 +0100251 if (ck)
252 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_EncryptionInformation, &ies.encryptionInformation);
Harald Weltef8db61b2015-12-18 17:29:59 +0100253
254 /* out -> msg */
255 msg = ranap_generate_initiating_message(RANAP_ProcedureCode_id_SecurityModeControl,
256 RANAP_Criticality_reject,
257 &asn_DEF_RANAP_SecurityModeCommand,
258 &out);
259
260 /* release dynamic allocations attached to out */
261 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_SecurityModeCommand, &out);
262
263 return msg;
264}
265
Neels Hofmeyr7e760acc2016-04-19 01:41:17 +0200266/*! \brief generate RANAP SECURITY MODE COMPLETE message */
Neels Hofmeyra9f55662016-04-19 01:21:41 +0200267struct msgb *ranap_new_msg_sec_mod_compl(
268 RANAP_ChosenIntegrityProtectionAlgorithm_t chosen_ip_alg,
269 RANAP_ChosenEncryptionAlgorithm_t chosen_enc_alg)
270{
271 RANAP_SecurityModeCompleteIEs_t ies;
272 RANAP_SecurityModeComplete_t out;
273 struct msgb *msg;
274 int i, rc;
275
276 memset(&ies, 0, sizeof(ies));
277 memset(&out, 0, sizeof(out));
278
279 ies.presenceMask = SECURITYMODECOMPLETEIES_RANAP_CHOSENENCRYPTIONALGORITHM_PRESENT;
280 ies.chosenIntegrityProtectionAlgorithm = chosen_ip_alg;
281 ies.chosenEncryptionAlgorithm = chosen_enc_alg;
282
283 /* ies -> out */
284 rc = ranap_encode_securitymodecompleteies(&out, &ies);
285
286 /* out -> msg */
287 msg = ranap_generate_successful_outcome(RANAP_ProcedureCode_id_SecurityModeControl,
288 RANAP_Criticality_reject,
289 &asn_DEF_RANAP_SecurityModeComplete,
290 &out);
291
292 /* release dynamic allocations attached to out */
293 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_SecurityModeComplete, &out);
294
295 return msg;
296}
297
Harald Weltef8db61b2015-12-18 17:29:59 +0100298/*! \brief generate RANAP COMMON ID message */
299struct msgb *ranap_new_msg_common_id(const char *imsi)
300{
301 RANAP_CommonID_IEs_t ies;
302 RANAP_CommonID_t out;
303 struct msgb *msg;
304 int rc;
305
306 memset(&ies, 0, sizeof(ies));
307 memset(&out, 0, sizeof(out));
308
309 if (imsi) {
310 uint8_t *imsi_buf = CALLOC(1, 16);
Harald Welte056984f2016-01-03 16:31:31 +0100311 rc = ranap_imsi_encode(imsi_buf, 16, imsi);
Harald Weltef8db61b2015-12-18 17:29:59 +0100312 ies.permanentNAS_UE_ID.present = RANAP_PermanentNAS_UE_ID_PR_iMSI;
313 ies.permanentNAS_UE_ID.choice.iMSI.buf = imsi_buf;
314 ies.permanentNAS_UE_ID.choice.iMSI.size = rc;
315 } else
316 ies.permanentNAS_UE_ID.present = RANAP_PermanentNAS_UE_ID_PR_NOTHING;
317
318 /* ies -> out */
319 rc = ranap_encode_commonid_ies(&out, &ies);
320 /* release dynamic allocations attached to ies */
321 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_PermanentNAS_UE_ID, &ies.permanentNAS_UE_ID);
322 if (rc < 0)
323 return NULL;
324
325 /* out -> msg */
326 msg = ranap_generate_initiating_message(RANAP_ProcedureCode_id_CommonID,
327 RANAP_Criticality_ignore,
328 &asn_DEF_RANAP_CommonID,
329 &out);
330
331 /* release dynamic allocations attached to out */
332 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_CommonID, &out);
333
334 return msg;
335}
336
337/*! \brief generate RANAP IU RELEASE COMMAND message */
338struct msgb *ranap_new_msg_iu_rel_cmd(const RANAP_Cause_t *cause_in)
339{
340 RANAP_Iu_ReleaseCommandIEs_t ies;
341 RANAP_Iu_ReleaseCommand_t out;
342 struct msgb *msg;
343 int rc;
344
345 memset(&ies, 0, sizeof(ies));
346 memset(&out, 0, sizeof(out));
347
348 memcpy(&ies.cause, cause_in, sizeof(ies.cause));
349
350 /* ies -> out */
351 rc = ranap_encode_iu_releasecommandies(&out, &ies);
352 if (rc < 0)
353 return NULL;
354
355 /* out -> msg */
356 msg = ranap_generate_initiating_message(RANAP_ProcedureCode_id_Iu_Release,
357 RANAP_Criticality_reject,
358 &asn_DEF_RANAP_Iu_ReleaseCommand,
359 &out);
360
361 /* release dynamic allocations attached to out */
362 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_Iu_ReleaseCommand, &out);
363
364 return msg;
365}
366
367/*! \brief generate RANAP PAGING COMMAND message */
368struct msgb *ranap_new_msg_paging_cmd(const char *imsi, const uint32_t *tmsi, int is_ps, uint32_t cause)
369{
370 RANAP_PagingIEs_t ies;
371 RANAP_Paging_t out;
372 struct msgb *msg;
373 uint8_t *imsi_buf = CALLOC(1, 16);
374 int rc;
375
376 memset(&ies, 0, sizeof(ies));
377 memset(&out, 0, sizeof(out));
378
379 /* put together the 'ies' */
380 if (is_ps)
381 ies.cN_DomainIndicator = RANAP_CN_DomainIndicator_ps_domain;
382 else
383 ies.cN_DomainIndicator = RANAP_CN_DomainIndicator_cs_domain;
384
Harald Welte056984f2016-01-03 16:31:31 +0100385 rc = ranap_imsi_encode(imsi_buf, 16, imsi);
Harald Weltef8db61b2015-12-18 17:29:59 +0100386 ies.permanentNAS_UE_ID.present = RANAP_PermanentNAS_UE_ID_PR_iMSI;
387 ies.permanentNAS_UE_ID.choice.iMSI.buf = imsi_buf;
388 ies.permanentNAS_UE_ID.choice.iMSI.size = rc;
389
390 if (tmsi) {
391 uint32_t *tmsi_buf = CALLOC(1, sizeof(*tmsi_buf));
392 *tmsi_buf = *tmsi;
393 ies.presenceMask |= PAGINGIES_RANAP_TEMPORARYUE_ID_PRESENT;
394 if (is_ps) {
395 ies.temporaryUE_ID.present = RANAP_TemporaryUE_ID_PR_p_TMSI;
Harald Weltef9c9aa52015-12-24 15:39:00 +0100396 ies.temporaryUE_ID.choice.tMSI.buf = (uint8_t *) tmsi_buf;
Harald Weltef8db61b2015-12-18 17:29:59 +0100397 ies.temporaryUE_ID.choice.tMSI.size = sizeof(*tmsi_buf);
398 } else {
399 ies.temporaryUE_ID.present = RANAP_TemporaryUE_ID_PR_tMSI;
Harald Weltef9c9aa52015-12-24 15:39:00 +0100400 ies.temporaryUE_ID.choice.p_TMSI.buf = (uint8_t *) tmsi_buf;
Harald Weltef8db61b2015-12-18 17:29:59 +0100401 ies.temporaryUE_ID.choice.p_TMSI.size = sizeof(*tmsi_buf);
402 }
403 }
404
405 if (cause) {
406 ies.presenceMask |= PAGINGIES_RANAP_PAGINGCAUSE_PRESENT;
407 ies.pagingCause = cause;
408 }
409
410 /* ies -> out */
411 rc = ranap_encode_pagingies(&out, &ies);
412 /* release dynamic allocation attached to ies */
413 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_PermanentNAS_UE_ID, &ies.permanentNAS_UE_ID);
414 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_TemporaryUE_ID, &ies.temporaryUE_ID);
415 if (rc < 0)
416 return NULL;
417
418 /* out -> msg */
419 msg = ranap_generate_initiating_message(RANAP_ProcedureCode_id_Paging,
420 RANAP_Criticality_reject,
421 &asn_DEF_RANAP_Paging,
422 &out);
423
424 /* release dynamic allocations attached to out */
425 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_Paging, &out);
426
427 return msg;
428}
429
430static RANAP_SDU_ErrorRatio_t *new_sdu_error_ratio(long mantissa, long exponent)
431{
432 RANAP_SDU_ErrorRatio_t *err = CALLOC(1, sizeof(*err));
433
434 err->mantissa = mantissa;
435 err->exponent = exponent;
436
437 return err;
438}
439
440
441static RANAP_SDU_FormatInformationParameterItem_t *
442new_format_info_pars(long sdu_size)
443{
444 RANAP_SDU_FormatInformationParameterItem_t *fmti = CALLOC(1, sizeof(*fmti));
445 fmti->subflowSDU_Size = new_long(sdu_size);
446 return fmti;
447}
448
449enum sdu_par_profile {
450 SDUPAR_P_VOICE0,
451 SDUPAR_P_VOICE1,
452 SDUPAR_P_VOICE2,
453 SDUPAR_P_DATA,
454};
455
456/* See Chapter 5 of TS 26.102 */
457static RANAP_SDU_ParameterItem_t *new_sdu_par_item(enum sdu_par_profile profile)
458{
459 RANAP_SDU_ParameterItem_t *sdui = CALLOC(1, sizeof(*sdui));
460 RANAP_SDU_FormatInformationParameters_t *fmtip = CALLOC(1, sizeof(*fmtip));
461 RANAP_SDU_FormatInformationParameterItem_t *fmti;
462
463 switch (profile) {
464 case SDUPAR_P_VOICE0:
465 sdui->sDU_ErrorRatio = new_sdu_error_ratio(1, 5);
466 sdui->residualBitErrorRatio.mantissa = 1;
467 sdui->residualBitErrorRatio.exponent = 6;
468 sdui->deliveryOfErroneousSDU = RANAP_DeliveryOfErroneousSDU_yes;
469 sdui->sDU_FormatInformationParameters = fmtip;
470 fmti = new_format_info_pars(81);
471 ASN_SEQUENCE_ADD(fmtip, fmti);
472 fmti = new_format_info_pars(39);
473 ASN_SEQUENCE_ADD(fmtip, fmti);
474 /* FIXME: could be 10 SDU descriptors for AMR! */
475 break;
476 case SDUPAR_P_VOICE1:
477 sdui->residualBitErrorRatio.mantissa = 1;
478 sdui->residualBitErrorRatio.exponent = 3;
479 sdui->deliveryOfErroneousSDU = RANAP_DeliveryOfErroneousSDU_no_error_detection_consideration;
480 sdui->sDU_FormatInformationParameters = fmtip;
481 fmti = new_format_info_pars(103);
482 ASN_SEQUENCE_ADD(fmtip, fmti);
483 fmti = new_format_info_pars(0);
484 ASN_SEQUENCE_ADD(fmtip, fmti);
485 /* FIXME: could be 10 SDU descriptors for AMR! */
486 break;
487 case SDUPAR_P_VOICE2:
488 sdui->residualBitErrorRatio.mantissa = 5;
489 sdui->residualBitErrorRatio.exponent = 3;
490 sdui->deliveryOfErroneousSDU = RANAP_DeliveryOfErroneousSDU_no_error_detection_consideration;
491 sdui->sDU_FormatInformationParameters = fmtip;
492 fmti = new_format_info_pars(60);
493 ASN_SEQUENCE_ADD(fmtip, fmti);
494 fmti = new_format_info_pars(0);
495 ASN_SEQUENCE_ADD(fmtip, fmti);
496 /* FIXME: could be 10 SDU descriptors for AMR! */
497 break;
498 case SDUPAR_P_DATA:
499 sdui->sDU_ErrorRatio = new_sdu_error_ratio(1, 4);
500 sdui->residualBitErrorRatio.mantissa = 1;
501 sdui->residualBitErrorRatio.exponent = 5;
502 sdui->deliveryOfErroneousSDU = RANAP_DeliveryOfErroneousSDU_no;
503 FREEMEM(fmtip);
504 break;
505 }
506
507 return sdui;
508}
509
510static RANAP_AllocationOrRetentionPriority_t *
511new_alloc_ret_prio(RANAP_PriorityLevel_t level, int capability, int vulnerability,
512 int queueing_allowed)
513{
514 RANAP_AllocationOrRetentionPriority_t *arp = CALLOC(1, sizeof(*arp));
515
516 arp->priorityLevel = level;
517
518 if (capability)
519 arp->pre_emptionCapability = RANAP_Pre_emptionCapability_may_trigger_pre_emption;
520 else
521 arp->pre_emptionCapability = RANAP_Pre_emptionCapability_shall_not_trigger_pre_emption;
522
523 if (vulnerability)
524 arp->pre_emptionVulnerability = RANAP_Pre_emptionVulnerability_pre_emptable;
525 else
526 arp->pre_emptionVulnerability = RANAP_Pre_emptionVulnerability_not_pre_emptable;
527
528 if (queueing_allowed)
529 arp->queuingAllowed = RANAP_QueuingAllowed_queueing_allowed;
530 else
531 arp->queuingAllowed = RANAP_QueuingAllowed_queueing_not_allowed;
532
533 return arp;
534}
535
536/* See Chapter 5 of TS 26.102 */
537static RANAP_RAB_Parameters_t *new_rab_par_voice(void)
538{
539 RANAP_RAB_Parameters_t *rab = CALLOC(1, sizeof(*rab));
540 RANAP_SDU_ParameterItem_t *sdui;
541
542 rab->trafficClass = RANAP_TrafficClass_conversational;
543 rab->rAB_AsymmetryIndicator = RANAP_RAB_AsymmetryIndicator_symmetric_bidirectional;
544
545 ASN_SEQUENCE_ADD(&rab->maxBitrate.list, new_long(12200));
546 rab->guaranteedBitRate = CALLOC(1, sizeof(*rab->guaranteedBitRate));
547 ASN_SEQUENCE_ADD(rab->guaranteedBitRate, new_long(12200));
548 rab->deliveryOrder = RANAP_DeliveryOrder_delivery_order_requested;
549 rab->maxSDU_Size = 244;
550
551 sdui = new_sdu_par_item(SDUPAR_P_VOICE0);
552 ASN_SEQUENCE_ADD(&rab->sDU_Parameters, sdui);
553 sdui = new_sdu_par_item(SDUPAR_P_VOICE1);
554 ASN_SEQUENCE_ADD(&rab->sDU_Parameters, sdui);
555 sdui = new_sdu_par_item(SDUPAR_P_VOICE2);
556 ASN_SEQUENCE_ADD(&rab->sDU_Parameters, sdui);
557
558 rab->transferDelay = new_long(80);
559 rab->allocationOrRetentionPriority = new_alloc_ret_prio(RANAP_PriorityLevel_no_priority, 0, 1, 0);
560
561 rab->sourceStatisticsDescriptor = new_long(RANAP_SourceStatisticsDescriptor_speech);
562
563 return rab;
564}
565
Harald Welte05ac6772015-12-29 19:09:52 +0100566static RANAP_RAB_Parameters_t *new_rab_par_data(uint32_t dl_max_bitrate, uint32_t ul_max_bitrate)
Harald Weltef8db61b2015-12-18 17:29:59 +0100567{
568 RANAP_RAB_Parameters_t *rab = CALLOC(1, sizeof(*rab));
569 RANAP_SDU_ParameterItem_t *sdui;
570
571 rab->trafficClass = RANAP_TrafficClass_background;
572 rab->rAB_AsymmetryIndicator = RANAP_RAB_AsymmetryIndicator_asymmetric_bidirectional;
573
Harald Welte05ac6772015-12-29 19:09:52 +0100574 ASN_SEQUENCE_ADD(&rab->maxBitrate.list, new_long(dl_max_bitrate));
575 ASN_SEQUENCE_ADD(&rab->maxBitrate.list, new_long(ul_max_bitrate));
Harald Weltef8db61b2015-12-18 17:29:59 +0100576 rab->deliveryOrder = RANAP_DeliveryOrder_delivery_order_requested;
577 rab->maxSDU_Size = 8000;
578
579 sdui = new_sdu_par_item(SDUPAR_P_DATA);
580 ASN_SEQUENCE_ADD(&rab->sDU_Parameters, sdui);
581
582 rab->allocationOrRetentionPriority = new_alloc_ret_prio(RANAP_PriorityLevel_no_priority, 0, 0, 0);
583
584 /* FIXME: RAB-Parameter-ExtendedMaxBitrateList for 42Mbps? */
585
586 return rab;
587}
588
Harald Weltebfe49a22015-12-28 13:14:52 +0100589static void new_transp_layer_addr(BIT_STRING_t *out, uint32_t ip, int use_x213_nsap)
590{
591 uint8_t *buf;
592 unsigned int len;
593
594 if (use_x213_nsap) {
595 len = 7;
596 buf = CALLOC(len, sizeof(uint8_t));
597 buf[0] = 0x35; /* AFI For IANA ICP */
598 buf[1] = 0x00; /* See A.5.2.1.2.7 of X.213 */
599 buf[2] = 0x01;
600 *(uint32_t *)&buf[3] = ntohl(ip);
601 } else {
602 len = 4;
603 buf = CALLOC(len, sizeof(uint8_t));
604 *(uint32_t *)buf = ip;
605 }
606 out->buf = buf;
607 out->size = len;
608 out->bits_unused = 0;
609}
610
Harald Weltef8db61b2015-12-18 17:29:59 +0100611static RANAP_TransportLayerInformation_t *new_transp_info_rtp(uint32_t ip, uint16_t port)
612{
613 RANAP_TransportLayerInformation_t *tli = CALLOC(1, sizeof(*tli));
Harald Weltef8db61b2015-12-18 17:29:59 +0100614 uint8_t binding_id[4];
615
Harald Welte37223d82016-01-01 16:18:55 +0100616#if 0
Harald Weltef8db61b2015-12-18 17:29:59 +0100617 binding_id[0] = port >> 8;
618 binding_id[1] = port & 0xff;
619 binding_id[2] = binding_id[3] = 0;
Harald Welte37223d82016-01-01 16:18:55 +0100620#else
621 binding_id[0] = binding_id[1] = binding_id[2] = 0;
622 binding_id[3] = 1;
623#endif
Harald Weltef8db61b2015-12-18 17:29:59 +0100624
Harald Weltebfe49a22015-12-28 13:14:52 +0100625 new_transp_layer_addr(&tli->transportLayerAddress, ip, 1);
Harald Weltef8db61b2015-12-18 17:29:59 +0100626 tli->iuTransportAssociation.present = RANAP_IuTransportAssociation_PR_bindingID;
627 OCTET_STRING_fromBuf(&tli->iuTransportAssociation.choice.bindingID,
628 (const char *) binding_id, sizeof(binding_id));
629
630 return tli;
631}
632
633static RANAP_TransportLayerInformation_t *new_transp_info_gtp(uint32_t ip, uint32_t tei)
634{
635 RANAP_TransportLayerInformation_t *tli = CALLOC(1, sizeof(*tli));
Harald Welte01de8d72015-12-29 19:10:48 +0100636 uint32_t binding_buf = htonl(tei);
Harald Weltef8db61b2015-12-18 17:29:59 +0100637
Harald Weltebfe49a22015-12-28 13:14:52 +0100638 new_transp_layer_addr(&tli->transportLayerAddress, ip, 1);
Harald Weltef8db61b2015-12-18 17:29:59 +0100639 tli->iuTransportAssociation.present = RANAP_IuTransportAssociation_PR_gTP_TEI;
Harald Welte01de8d72015-12-29 19:10:48 +0100640 OCTET_STRING_fromBuf(&tli->iuTransportAssociation.choice.gTP_TEI,
Harald Weltef8db61b2015-12-18 17:29:59 +0100641 (const char *) &binding_buf, sizeof(binding_buf));
642
643 return tli;
644}
645
646static RANAP_UserPlaneInformation_t *new_upi(long mode, uint8_t mode_versions)
647{
648 RANAP_UserPlaneInformation_t *upi = CALLOC(1, sizeof(*upi));
649 uint16_t *buf = CALLOC(1, sizeof(*buf));
650
Daniel Willmann49f99cd2016-01-26 09:37:22 +0100651 *buf = ntohs(mode_versions);
Harald Weltef8db61b2015-12-18 17:29:59 +0100652
653 upi->userPlaneMode = mode;
Harald Weltef9c9aa52015-12-24 15:39:00 +0100654 upi->uP_ModeVersions.buf = (uint8_t *) buf;
Harald Weltef8db61b2015-12-18 17:29:59 +0100655 upi->uP_ModeVersions.size = sizeof(*buf);
656 upi->uP_ModeVersions.bits_unused = 0;
657
658 return upi;
659}
660
661
662static void assign_new_ra_id(RANAP_RAB_ID_t *id, uint8_t rab_id)
663{
664 uint8_t *buf = CALLOC(1, sizeof(*buf));
Harald Welte0a3eafe2015-12-19 02:38:09 +0100665 *buf = rab_id;
Harald Weltef8db61b2015-12-18 17:29:59 +0100666
667 id->buf = buf;
668 id->size = 1;
669 id->bits_unused = 0;
670}
671
672/*! \brief generate RANAP RAB ASSIGNMENT REQUEST message for CS (voice) */
673struct msgb *ranap_new_msg_rab_assign_voice(uint8_t rab_id, uint32_t rtp_ip, uint16_t rtp_port)
674{
675 RANAP_ProtocolIE_FieldPair_t *pair;
676 RANAP_RAB_AssignmentRequestIEs_t ies;
677 RANAP_RAB_AssignmentRequest_t out;
678 struct msgb *msg;
679 int rc;
680
681 memset(&ies, 0, sizeof(ies));
682 memset(&out, 0, sizeof(out));
683
684 /* only assingnment is present, no release */
685 ies.presenceMask = RAB_ASSIGNMENTREQUESTIES_RANAP_RAB_SETUPORMODIFYLIST_PRESENT;
686
687 /* put together the 'First' part */
688 RANAP_RAB_SetupOrModifyItemFirst_t first;
689 memset(&first, 0, sizeof(first));
690 assign_new_ra_id(&first.rAB_ID, rab_id);
691 //first.nAS_SynchronisationIndicator = FIXME;
692 first.rAB_Parameters = new_rab_par_voice();
693 first.userPlaneInformation = new_upi(RANAP_UserPlaneMode_support_mode_for_predefined_SDU_sizes, 1); /* 2? */
694 first.transportLayerInformation = new_transp_info_rtp(rtp_ip, rtp_port);
695
696 /* put together the 'Second' part */
697 RANAP_RAB_SetupOrModifyItemSecond_t second;
698 memset(&second, 0, sizeof(second));
699
700 /* Build an IE Pair out of first and second part:
701 * (first, second) -> pair */
702 pair = ranap_new_ie_pair(RANAP_ProtocolIE_ID_id_RAB_SetupOrModifyItem,
703 RANAP_Criticality_reject,
704 &asn_DEF_RANAP_RAB_SetupOrModifyItemFirst, &first,
705 RANAP_Criticality_ignore,
706 &asn_DEF_RANAP_RAB_SetupOrModifyItemSecond, &second);
707
708 /* the pair has been made, we can release any of its elements */
709 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_SetupOrModifyItemFirst, &first);
710 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_SetupOrModifyItemSecond, &second);
711
Harald Welteb7f67c42015-12-19 02:36:52 +0100712 RANAP_ProtocolIE_ContainerPair_t *container_pair = CALLOC(1, sizeof(*container_pair));
Harald Weltef8db61b2015-12-18 17:29:59 +0100713 /* Add the pair to the list of IEs of the RAB ass.req */
Harald Welteb7f67c42015-12-19 02:36:52 +0100714 ASN_SEQUENCE_ADD(container_pair, pair);
715 ASN_SEQUENCE_ADD(&ies.raB_SetupOrModifyList.list, container_pair);
Harald Weltef8db61b2015-12-18 17:29:59 +0100716
717 /* encode the IEs into the actual assignment request:
718 * ies -> out */
719 rc = ranap_encode_rab_assignmentrequesties(&out, &ies);
720 /* 'out' has been generated, we can now release the input */
721 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_SetupOrModifyList,
722 &ies.raB_SetupOrModifyList);
723 if (rc < 0)
724 return NULL;
725
726 /* generate an Initiating Mesasage: out -> msg */
727 msg = ranap_generate_initiating_message(RANAP_ProcedureCode_id_RAB_Assignment,
728 RANAP_Criticality_reject,
729 &asn_DEF_RANAP_RAB_AssignmentRequest, &out);
730
731 /* 'msg' has been generated, we cann now release the input 'out' */
732 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_AssignmentRequest, &out);
733
734 return msg;
735}
736
737/*! \brief generate RANAP RAB ASSIGNMENT REQUEST message for PS (data) */
738struct msgb *ranap_new_msg_rab_assign_data(uint8_t rab_id, uint32_t gtp_ip, uint32_t gtp_tei)
739{
740 RANAP_ProtocolIE_FieldPair_t *pair;
741 RANAP_RAB_AssignmentRequestIEs_t ies;
742 RANAP_RAB_AssignmentRequest_t out;
743 RANAP_DataVolumeReportingIndication_t *dat_vol_ind;
744 struct msgb *msg;
745 int rc;
746
747 memset(&ies, 0, sizeof(ies));
748 memset(&out, 0, sizeof(out));
749
750 /* only assingnment is present, no release */
751 ies.presenceMask = RAB_ASSIGNMENTREQUESTIES_RANAP_RAB_SETUPORMODIFYLIST_PRESENT;
752
753 /* put together the 'First' part */
754 RANAP_RAB_SetupOrModifyItemFirst_t first;
755 memset(&first, 0, sizeof(first));
756 assign_new_ra_id(&first.rAB_ID, rab_id);
757 //first.nAS_SynchronisationIndicator = FIXME;
Harald Welte05ac6772015-12-29 19:09:52 +0100758
759 first.rAB_Parameters = new_rab_par_data(1600000, 800000);
Harald Weltef8db61b2015-12-18 17:29:59 +0100760 first.userPlaneInformation = new_upi(RANAP_UserPlaneMode_transparent_mode, 1);
Harald Welte01de8d72015-12-29 19:10:48 +0100761 first.transportLayerInformation = new_transp_info_gtp(gtp_ip, gtp_tei);
Harald Weltef8db61b2015-12-18 17:29:59 +0100762
763 /* put together the 'Second' part */
764 RANAP_RAB_SetupOrModifyItemSecond_t second;
765 memset(&second, 0, sizeof(second));
766 second.pDP_TypeInformation = CALLOC(1, sizeof(*second.pDP_TypeInformation));
767 ASN_SEQUENCE_ADD(second.pDP_TypeInformation, new_long(RANAP_PDP_Type_ipv4));
768 dat_vol_ind = CALLOC(1, sizeof(*dat_vol_ind));
769 *dat_vol_ind = RANAP_DataVolumeReportingIndication_do_not_report;
770 second.dataVolumeReportingIndication = dat_vol_ind;
771 second.dl_GTP_PDU_SequenceNumber = new_long(0);
772 second.ul_GTP_PDU_SequenceNumber = new_long(0);
773
774 /* Build an IE Pair out of first and second part:
775 * (first, second) -> pair */
776 pair = ranap_new_ie_pair(RANAP_ProtocolIE_ID_id_RAB_SetupOrModifyItem,
777 RANAP_Criticality_reject,
778 &asn_DEF_RANAP_RAB_SetupOrModifyItemFirst,
779 &first, RANAP_Criticality_ignore,
780 &asn_DEF_RANAP_RAB_SetupOrModifyItemSecond,
781 &second);
782
783 /* the pair has been made, we can release any of its elements */
784 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_SetupOrModifyItemFirst, &first);
785 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_SetupOrModifyItemSecond, &second);
786
Harald Welteb7f67c42015-12-19 02:36:52 +0100787 RANAP_ProtocolIE_ContainerPair_t *container_pair = CALLOC(1, sizeof(*container_pair));
Harald Weltef8db61b2015-12-18 17:29:59 +0100788 /* Add the pair to the list of IEs of the RAB ass.req */
Harald Welteb7f67c42015-12-19 02:36:52 +0100789 ASN_SEQUENCE_ADD(container_pair, pair);
790 /* Add the pair to the list of IEs of the RAB ass.req */
791 ASN_SEQUENCE_ADD(&ies.raB_SetupOrModifyList.list, container_pair);
Harald Weltef8db61b2015-12-18 17:29:59 +0100792
793 /* encode the IEs into the actual assignment request:
794 * ies -> out */
795 rc = ranap_encode_rab_assignmentrequesties(&out, &ies);
796 /* 'out' has been generated, we can now release the input */
797 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_SetupOrModifyList,
798 &ies.raB_SetupOrModifyList);
799 if (rc < 0)
800 return NULL;
801
802 /* generate an Initiating Mesasage: out -> msg */
803 msg = ranap_generate_initiating_message(RANAP_ProcedureCode_id_RAB_Assignment,
804 RANAP_Criticality_reject,
805 &asn_DEF_RANAP_RAB_AssignmentRequest, &out);
806
807 /* 'msg' has been generated, we cann now release the input 'out' */
808 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_AssignmentRequest, &out);
809
810 return msg;
811}
Harald Welte37223d82016-01-01 16:18:55 +0100812
813struct msgb *ranap_new_msg_iu_rel_req(const RANAP_Cause_t *cause)
814{
815 RANAP_Iu_ReleaseRequestIEs_t ies;
816 RANAP_Iu_ReleaseRequest_t out;
817 struct msgb *msg;
818 int rc;
819
820 memset(&ies, 0, sizeof(ies));
821 memset(&out, 0, sizeof(out));
822
823 memcpy(&ies.cause, cause, sizeof(ies.cause));
824
825 rc = ranap_encode_iu_releaserequesties(&out, &ies);
826 if (rc < 0)
827 return NULL;
828
829 /* encode the output into the msgb */
830 msg = ranap_generate_initiating_message(RANAP_ProcedureCode_id_Iu_ReleaseRequest,
831 RANAP_Criticality_reject,
832 &asn_DEF_RANAP_Iu_ReleaseRequest, &out);
833 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_Iu_ReleaseRequest, &out);
834
835 return msg;
836}
837
838struct msgb *ranap_new_msg_rab_rel_req(uint8_t rab_id, const RANAP_Cause_t *cause)
839{
840 RANAP_RAB_ReleaseItemIEs_t item_ies;
841 RANAP_RAB_ReleaseRequestIEs_t ies;
842 RANAP_RAB_ReleaseRequest_t out;
843 struct msgb *msg;
844 int rc;
845
846 memset(&item_ies, 0, sizeof(item_ies));
847 memset(&ies, 0, sizeof(ies));
848 memset(&out, 0, sizeof(out));
849
850 /* put together the ReleaseItem */
851 assign_new_ra_id(&item_ies.raB_ReleaseItem.rAB_ID, rab_id);
852 memcpy(&item_ies.raB_ReleaseItem.cause, cause, sizeof(item_ies.raB_ReleaseItem.cause));
853
854 /* add to the list */
855 rc = ranap_encode_rab_releaseitemies(&ies.raB_ReleaseList, &item_ies);
856 if (rc < 0)
857 return NULL;
858 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_ReleaseItem, &item_ies.raB_ReleaseItem);
859
860 /* encoe the list IEs into the output */
861 rc = ranap_encode_rab_releaserequesties(&out, &ies);
862 if (rc < 0)
863 return NULL;
864 /* 'out' has been generated, we can release the input */
865 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_ReleaseList, &ies.raB_ReleaseList);
866
867 /* encode the output into the msgb */
868 msg = ranap_generate_initiating_message(RANAP_ProcedureCode_id_RAB_ReleaseRequest,
869 RANAP_Criticality_reject,
870 &asn_DEF_RANAP_RAB_ReleaseRequest, &out);
871
872 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_ReleaseRequest, &out);
873
874 return msg;
875}