blob: 3202e1a12ea49cbe3c3c42756fd2b6748156a61c [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"
25#include "iu_helpers.h"
26
27#include "ranap_common.h"
28#include "ranap_ies_defs.h"
29#include "ranap_msg_factory.h"
30
31#include "hnbgw.h"
32
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,
43 RANAP_Cause_t *cause)
44{
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;
89 /* FIXME: Copy PLMN Identity TBCD-String */
90 ies.globalRNC_ID.rNC_ID = rnc_id->rNC_ID;
91 }
92
93 /* FIXME: Do we need criticalityDiagnostics */
94
95 memset(&out, 0, sizeof(out));
96 rc = ranap_encode_resetacknowledgeies(&out, &ies);
97 if (rc < 0) {
98 LOGP(DRANAP, LOGL_ERROR, "error encoding reset ack IEs: %d\n", rc);
99 return NULL;
100 }
101
102 msg = ranap_generate_successful_outcome(RANAP_ProcedureCode_id_Reset,
103 RANAP_Criticality_reject,
104 &asn_DEF_RANAP_ResetAcknowledge,
105 &out);
106
107 /* release dynamic allocations attached to dt */
108 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_ResetAcknowledge, &out);
109
110 return msg;
111}
112
Harald Weltef8db61b2015-12-18 17:29:59 +0100113/*! \brief generate RANAP DIRECT TRANSFER message */
114struct msgb *ranap_new_msg_dt(uint8_t sapi, const uint8_t *nas, unsigned int nas_len)
115{
116 RANAP_DirectTransferIEs_t ies;
117 RANAP_DirectTransfer_t dt;
118 struct msgb *msg;
119 int rc;
120
121 memset(&ies, 0, sizeof(ies));
122 memset(&dt, 0, sizeof(dt));
123
124 /* only SAPI optional field shall be present for CN->RNC */
125 ies.presenceMask = DIRECTTRANSFERIES_RANAP_SAPI_PRESENT;
126
127 if (sapi == 3)
128 ies.sapi = RANAP_SAPI_sapi_3;
129 else
130 ies.sapi = RANAP_SAPI_sapi_0;
131
132 ies.nas_pdu.buf = (uint8_t *) nas;
133 ies.nas_pdu.size = nas_len;
134
135 /* ies -> dt */
136 rc = ranap_encode_directtransferies(&dt, &ies);
137
138 /* dt -> msg */
139 msg = ranap_generate_initiating_message(RANAP_ProcedureCode_id_DirectTransfer,
140 RANAP_Criticality_reject,
141 &asn_DEF_RANAP_DirectTransfer,
142 &dt);
143
144 /* release dynamic allocations attached to dt */
145 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_DirectTransfer, &dt);
146
147 return msg;
148}
149
150static const enum RANAP_IntegrityProtectionAlgorithm ip_alg[2] = {
151 RANAP_IntegrityProtectionAlgorithm_standard_UMTS_integrity_algorithm_UIA1,
152 RANAP_IntegrityProtectionAlgorithm_standard_UMTS_integrity_algorithm_UIA2,
153};
154
155static const RANAP_EncryptionAlgorithm_t enc_alg[2] = {
156 RANAP_EncryptionAlgorithm_standard_UMTS_encryption_algorith_UEA1,
157 RANAP_EncryptionAlgorithm_standard_UMTS_encryption_algorithm_UEA2,
158};
159
160/*! \brief generate RANAP SECURITY MODE COMMAND message */
161struct msgb *ranap_new_msg_sec_mod_cmd(const uint8_t *ik, const uint8_t *ck)
162{
163 RANAP_SecurityModeCommandIEs_t ies;
164 RANAP_SecurityModeCommand_t out;
165 struct msgb *msg;
166 int i, rc;
167
168 memset(&ies, 0, sizeof(ies));
169 memset(&out, 0, sizeof(out));
170
171 ies.presenceMask = SECURITYMODECOMMANDIES_RANAP_ENCRYPTIONINFORMATION_PRESENT;
172
173 for (i = 0; i < ARRAY_SIZE(ip_alg); i++) {
174 /* needs to be dynamically allocated, as
175 * SET_OF_free() will call FREEMEM() on it */
176 RANAP_IntegrityProtectionAlgorithm_t *alg = CALLOC(1, sizeof(*alg));
177 *alg = ip_alg[i];
178 ASN_SEQUENCE_ADD(&ies.integrityProtectionInformation.permittedAlgorithms, alg);
179 }
180
181 BIT_STRING_fromBuf(&ies.integrityProtectionInformation.key, ik, 16*8);
182
183 if (ck) {
184 for (i = 0; i < ARRAY_SIZE(ip_alg); i++) {
185 /* needs to be dynamically allocated, as
186 * SET_OF_free() will call FREEMEM() on it */
187 RANAP_EncryptionAlgorithm_t *alg = CALLOC(1, sizeof(*alg));
188 *alg = enc_alg[i];
189 ASN_SEQUENCE_ADD(&ies.encryptionInformation.permittedAlgorithms, alg);
190 }
191 BIT_STRING_fromBuf(&ies.encryptionInformation.key, ck, 16*8);
192 }
193
194 ies.keyStatus = RANAP_KeyStatus_new; /* FIXME */
195
196 /* ies -> out */
197 rc = ranap_encode_securitymodecommandies(&out, &ies);
198
199 /* release dynamic allocations attached to ies */
200 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_IntegrityProtectionInformation, &ies.integrityProtectionInformation);
201 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_EncryptionInformation, &ies.encryptionInformation);
202
203 /* out -> msg */
204 msg = ranap_generate_initiating_message(RANAP_ProcedureCode_id_SecurityModeControl,
205 RANAP_Criticality_reject,
206 &asn_DEF_RANAP_SecurityModeCommand,
207 &out);
208
209 /* release dynamic allocations attached to out */
210 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_SecurityModeCommand, &out);
211
212 return msg;
213}
214
215/*! \brief generate RANAP COMMON ID message */
216struct msgb *ranap_new_msg_common_id(const char *imsi)
217{
218 RANAP_CommonID_IEs_t ies;
219 RANAP_CommonID_t out;
220 struct msgb *msg;
221 int rc;
222
223 memset(&ies, 0, sizeof(ies));
224 memset(&out, 0, sizeof(out));
225
226 if (imsi) {
227 uint8_t *imsi_buf = CALLOC(1, 16);
228 rc = encode_iu_imsi(imsi_buf, 16, imsi);
229 ies.permanentNAS_UE_ID.present = RANAP_PermanentNAS_UE_ID_PR_iMSI;
230 ies.permanentNAS_UE_ID.choice.iMSI.buf = imsi_buf;
231 ies.permanentNAS_UE_ID.choice.iMSI.size = rc;
232 } else
233 ies.permanentNAS_UE_ID.present = RANAP_PermanentNAS_UE_ID_PR_NOTHING;
234
235 /* ies -> out */
236 rc = ranap_encode_commonid_ies(&out, &ies);
237 /* release dynamic allocations attached to ies */
238 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_PermanentNAS_UE_ID, &ies.permanentNAS_UE_ID);
239 if (rc < 0)
240 return NULL;
241
242 /* out -> msg */
243 msg = ranap_generate_initiating_message(RANAP_ProcedureCode_id_CommonID,
244 RANAP_Criticality_ignore,
245 &asn_DEF_RANAP_CommonID,
246 &out);
247
248 /* release dynamic allocations attached to out */
249 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_CommonID, &out);
250
251 return msg;
252}
253
254/*! \brief generate RANAP IU RELEASE COMMAND message */
255struct msgb *ranap_new_msg_iu_rel_cmd(const RANAP_Cause_t *cause_in)
256{
257 RANAP_Iu_ReleaseCommandIEs_t ies;
258 RANAP_Iu_ReleaseCommand_t out;
259 struct msgb *msg;
260 int rc;
261
262 memset(&ies, 0, sizeof(ies));
263 memset(&out, 0, sizeof(out));
264
265 memcpy(&ies.cause, cause_in, sizeof(ies.cause));
266
267 /* ies -> out */
268 rc = ranap_encode_iu_releasecommandies(&out, &ies);
269 if (rc < 0)
270 return NULL;
271
272 /* out -> msg */
273 msg = ranap_generate_initiating_message(RANAP_ProcedureCode_id_Iu_Release,
274 RANAP_Criticality_reject,
275 &asn_DEF_RANAP_Iu_ReleaseCommand,
276 &out);
277
278 /* release dynamic allocations attached to out */
279 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_Iu_ReleaseCommand, &out);
280
281 return msg;
282}
283
284/*! \brief generate RANAP PAGING COMMAND message */
285struct msgb *ranap_new_msg_paging_cmd(const char *imsi, const uint32_t *tmsi, int is_ps, uint32_t cause)
286{
287 RANAP_PagingIEs_t ies;
288 RANAP_Paging_t out;
289 struct msgb *msg;
290 uint8_t *imsi_buf = CALLOC(1, 16);
291 int rc;
292
293 memset(&ies, 0, sizeof(ies));
294 memset(&out, 0, sizeof(out));
295
296 /* put together the 'ies' */
297 if (is_ps)
298 ies.cN_DomainIndicator = RANAP_CN_DomainIndicator_ps_domain;
299 else
300 ies.cN_DomainIndicator = RANAP_CN_DomainIndicator_cs_domain;
301
302 rc = encode_iu_imsi(imsi_buf, 16, imsi);
303 ies.permanentNAS_UE_ID.present = RANAP_PermanentNAS_UE_ID_PR_iMSI;
304 ies.permanentNAS_UE_ID.choice.iMSI.buf = imsi_buf;
305 ies.permanentNAS_UE_ID.choice.iMSI.size = rc;
306
307 if (tmsi) {
308 uint32_t *tmsi_buf = CALLOC(1, sizeof(*tmsi_buf));
309 *tmsi_buf = *tmsi;
310 ies.presenceMask |= PAGINGIES_RANAP_TEMPORARYUE_ID_PRESENT;
311 if (is_ps) {
312 ies.temporaryUE_ID.present = RANAP_TemporaryUE_ID_PR_p_TMSI;
313 ies.temporaryUE_ID.choice.tMSI.buf = tmsi_buf;
314 ies.temporaryUE_ID.choice.tMSI.size = sizeof(*tmsi_buf);
315 } else {
316 ies.temporaryUE_ID.present = RANAP_TemporaryUE_ID_PR_tMSI;
317 ies.temporaryUE_ID.choice.p_TMSI.buf = tmsi_buf;
318 ies.temporaryUE_ID.choice.p_TMSI.size = sizeof(*tmsi_buf);
319 }
320 }
321
322 if (cause) {
323 ies.presenceMask |= PAGINGIES_RANAP_PAGINGCAUSE_PRESENT;
324 ies.pagingCause = cause;
325 }
326
327 /* ies -> out */
328 rc = ranap_encode_pagingies(&out, &ies);
329 /* release dynamic allocation attached to ies */
330 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_PermanentNAS_UE_ID, &ies.permanentNAS_UE_ID);
331 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_TemporaryUE_ID, &ies.temporaryUE_ID);
332 if (rc < 0)
333 return NULL;
334
335 /* out -> msg */
336 msg = ranap_generate_initiating_message(RANAP_ProcedureCode_id_Paging,
337 RANAP_Criticality_reject,
338 &asn_DEF_RANAP_Paging,
339 &out);
340
341 /* release dynamic allocations attached to out */
342 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_Paging, &out);
343
344 return msg;
345}
346
347static RANAP_SDU_ErrorRatio_t *new_sdu_error_ratio(long mantissa, long exponent)
348{
349 RANAP_SDU_ErrorRatio_t *err = CALLOC(1, sizeof(*err));
350
351 err->mantissa = mantissa;
352 err->exponent = exponent;
353
354 return err;
355}
356
357
358static RANAP_SDU_FormatInformationParameterItem_t *
359new_format_info_pars(long sdu_size)
360{
361 RANAP_SDU_FormatInformationParameterItem_t *fmti = CALLOC(1, sizeof(*fmti));
362 fmti->subflowSDU_Size = new_long(sdu_size);
363 return fmti;
364}
365
366enum sdu_par_profile {
367 SDUPAR_P_VOICE0,
368 SDUPAR_P_VOICE1,
369 SDUPAR_P_VOICE2,
370 SDUPAR_P_DATA,
371};
372
373/* See Chapter 5 of TS 26.102 */
374static RANAP_SDU_ParameterItem_t *new_sdu_par_item(enum sdu_par_profile profile)
375{
376 RANAP_SDU_ParameterItem_t *sdui = CALLOC(1, sizeof(*sdui));
377 RANAP_SDU_FormatInformationParameters_t *fmtip = CALLOC(1, sizeof(*fmtip));
378 RANAP_SDU_FormatInformationParameterItem_t *fmti;
379
380 switch (profile) {
381 case SDUPAR_P_VOICE0:
382 sdui->sDU_ErrorRatio = new_sdu_error_ratio(1, 5);
383 sdui->residualBitErrorRatio.mantissa = 1;
384 sdui->residualBitErrorRatio.exponent = 6;
385 sdui->deliveryOfErroneousSDU = RANAP_DeliveryOfErroneousSDU_yes;
386 sdui->sDU_FormatInformationParameters = fmtip;
387 fmti = new_format_info_pars(81);
388 ASN_SEQUENCE_ADD(fmtip, fmti);
389 fmti = new_format_info_pars(39);
390 ASN_SEQUENCE_ADD(fmtip, fmti);
391 /* FIXME: could be 10 SDU descriptors for AMR! */
392 break;
393 case SDUPAR_P_VOICE1:
394 sdui->residualBitErrorRatio.mantissa = 1;
395 sdui->residualBitErrorRatio.exponent = 3;
396 sdui->deliveryOfErroneousSDU = RANAP_DeliveryOfErroneousSDU_no_error_detection_consideration;
397 sdui->sDU_FormatInformationParameters = fmtip;
398 fmti = new_format_info_pars(103);
399 ASN_SEQUENCE_ADD(fmtip, fmti);
400 fmti = new_format_info_pars(0);
401 ASN_SEQUENCE_ADD(fmtip, fmti);
402 /* FIXME: could be 10 SDU descriptors for AMR! */
403 break;
404 case SDUPAR_P_VOICE2:
405 sdui->residualBitErrorRatio.mantissa = 5;
406 sdui->residualBitErrorRatio.exponent = 3;
407 sdui->deliveryOfErroneousSDU = RANAP_DeliveryOfErroneousSDU_no_error_detection_consideration;
408 sdui->sDU_FormatInformationParameters = fmtip;
409 fmti = new_format_info_pars(60);
410 ASN_SEQUENCE_ADD(fmtip, fmti);
411 fmti = new_format_info_pars(0);
412 ASN_SEQUENCE_ADD(fmtip, fmti);
413 /* FIXME: could be 10 SDU descriptors for AMR! */
414 break;
415 case SDUPAR_P_DATA:
416 sdui->sDU_ErrorRatio = new_sdu_error_ratio(1, 4);
417 sdui->residualBitErrorRatio.mantissa = 1;
418 sdui->residualBitErrorRatio.exponent = 5;
419 sdui->deliveryOfErroneousSDU = RANAP_DeliveryOfErroneousSDU_no;
420 FREEMEM(fmtip);
421 break;
422 }
423
424 return sdui;
425}
426
427static RANAP_AllocationOrRetentionPriority_t *
428new_alloc_ret_prio(RANAP_PriorityLevel_t level, int capability, int vulnerability,
429 int queueing_allowed)
430{
431 RANAP_AllocationOrRetentionPriority_t *arp = CALLOC(1, sizeof(*arp));
432
433 arp->priorityLevel = level;
434
435 if (capability)
436 arp->pre_emptionCapability = RANAP_Pre_emptionCapability_may_trigger_pre_emption;
437 else
438 arp->pre_emptionCapability = RANAP_Pre_emptionCapability_shall_not_trigger_pre_emption;
439
440 if (vulnerability)
441 arp->pre_emptionVulnerability = RANAP_Pre_emptionVulnerability_pre_emptable;
442 else
443 arp->pre_emptionVulnerability = RANAP_Pre_emptionVulnerability_not_pre_emptable;
444
445 if (queueing_allowed)
446 arp->queuingAllowed = RANAP_QueuingAllowed_queueing_allowed;
447 else
448 arp->queuingAllowed = RANAP_QueuingAllowed_queueing_not_allowed;
449
450 return arp;
451}
452
453/* See Chapter 5 of TS 26.102 */
454static RANAP_RAB_Parameters_t *new_rab_par_voice(void)
455{
456 RANAP_RAB_Parameters_t *rab = CALLOC(1, sizeof(*rab));
457 RANAP_SDU_ParameterItem_t *sdui;
458
459 rab->trafficClass = RANAP_TrafficClass_conversational;
460 rab->rAB_AsymmetryIndicator = RANAP_RAB_AsymmetryIndicator_symmetric_bidirectional;
461
462 ASN_SEQUENCE_ADD(&rab->maxBitrate.list, new_long(12200));
463 rab->guaranteedBitRate = CALLOC(1, sizeof(*rab->guaranteedBitRate));
464 ASN_SEQUENCE_ADD(rab->guaranteedBitRate, new_long(12200));
465 rab->deliveryOrder = RANAP_DeliveryOrder_delivery_order_requested;
466 rab->maxSDU_Size = 244;
467
468 sdui = new_sdu_par_item(SDUPAR_P_VOICE0);
469 ASN_SEQUENCE_ADD(&rab->sDU_Parameters, sdui);
470 sdui = new_sdu_par_item(SDUPAR_P_VOICE1);
471 ASN_SEQUENCE_ADD(&rab->sDU_Parameters, sdui);
472 sdui = new_sdu_par_item(SDUPAR_P_VOICE2);
473 ASN_SEQUENCE_ADD(&rab->sDU_Parameters, sdui);
474
475 rab->transferDelay = new_long(80);
476 rab->allocationOrRetentionPriority = new_alloc_ret_prio(RANAP_PriorityLevel_no_priority, 0, 1, 0);
477
478 rab->sourceStatisticsDescriptor = new_long(RANAP_SourceStatisticsDescriptor_speech);
479
480 return rab;
481}
482
483static RANAP_RAB_Parameters_t *new_rab_par_data(void)
484{
485 RANAP_RAB_Parameters_t *rab = CALLOC(1, sizeof(*rab));
486 RANAP_SDU_ParameterItem_t *sdui;
487
488 rab->trafficClass = RANAP_TrafficClass_background;
489 rab->rAB_AsymmetryIndicator = RANAP_RAB_AsymmetryIndicator_asymmetric_bidirectional;
490
491 ASN_SEQUENCE_ADD(&rab->maxBitrate.list, new_long(16000000));
492 ASN_SEQUENCE_ADD(&rab->maxBitrate.list, new_long(8000000));
493 rab->deliveryOrder = RANAP_DeliveryOrder_delivery_order_requested;
494 rab->maxSDU_Size = 8000;
495
496 sdui = new_sdu_par_item(SDUPAR_P_DATA);
497 ASN_SEQUENCE_ADD(&rab->sDU_Parameters, sdui);
498
499 rab->allocationOrRetentionPriority = new_alloc_ret_prio(RANAP_PriorityLevel_no_priority, 0, 0, 0);
500
501 /* FIXME: RAB-Parameter-ExtendedMaxBitrateList for 42Mbps? */
502
503 return rab;
504}
505
506static RANAP_TransportLayerInformation_t *new_transp_info_rtp(uint32_t ip, uint16_t port)
507{
508 RANAP_TransportLayerInformation_t *tli = CALLOC(1, sizeof(*tli));
509 uint32_t *ipbuf = CALLOC(1, sizeof(*ipbuf));
510 uint8_t binding_id[4];
511
512 binding_id[0] = port >> 8;
513 binding_id[1] = port & 0xff;
514 binding_id[2] = binding_id[3] = 0;
515
Harald Welte94a62d52015-12-19 02:37:48 +0100516 asn1_u32_to_bitstring(&tli->transportLayerAddress, ipbuf, ip);
Harald Weltef8db61b2015-12-18 17:29:59 +0100517 tli->iuTransportAssociation.present = RANAP_IuTransportAssociation_PR_bindingID;
518 OCTET_STRING_fromBuf(&tli->iuTransportAssociation.choice.bindingID,
519 (const char *) binding_id, sizeof(binding_id));
520
521 return tli;
522}
523
524static RANAP_TransportLayerInformation_t *new_transp_info_gtp(uint32_t ip, uint32_t tei)
525{
526 RANAP_TransportLayerInformation_t *tli = CALLOC(1, sizeof(*tli));
527 uint32_t *ipbuf = CALLOC(1, sizeof(*ipbuf));
Harald Welte94a62d52015-12-19 02:37:48 +0100528 uint32_t binding_buf = tei;
Harald Weltef8db61b2015-12-18 17:29:59 +0100529
Harald Welte94a62d52015-12-19 02:37:48 +0100530 asn1_u32_to_bitstring(&tli->transportLayerAddress, ipbuf, ip);
Harald Weltef8db61b2015-12-18 17:29:59 +0100531 tli->iuTransportAssociation.present = RANAP_IuTransportAssociation_PR_gTP_TEI;
532 OCTET_STRING_fromBuf(&tli->iuTransportAssociation.choice.bindingID,
533 (const char *) &binding_buf, sizeof(binding_buf));
534
535 return tli;
536}
537
538static RANAP_UserPlaneInformation_t *new_upi(long mode, uint8_t mode_versions)
539{
540 RANAP_UserPlaneInformation_t *upi = CALLOC(1, sizeof(*upi));
541 uint16_t *buf = CALLOC(1, sizeof(*buf));
542
543 *buf = mode_versions;
544
545 upi->userPlaneMode = mode;
546 upi->uP_ModeVersions.buf = buf;
547 upi->uP_ModeVersions.size = sizeof(*buf);
548 upi->uP_ModeVersions.bits_unused = 0;
549
550 return upi;
551}
552
553
554static void assign_new_ra_id(RANAP_RAB_ID_t *id, uint8_t rab_id)
555{
556 uint8_t *buf = CALLOC(1, sizeof(*buf));
Harald Welte0a3eafe2015-12-19 02:38:09 +0100557 *buf = rab_id;
Harald Weltef8db61b2015-12-18 17:29:59 +0100558
559 id->buf = buf;
560 id->size = 1;
561 id->bits_unused = 0;
562}
563
564/*! \brief generate RANAP RAB ASSIGNMENT REQUEST message for CS (voice) */
565struct msgb *ranap_new_msg_rab_assign_voice(uint8_t rab_id, uint32_t rtp_ip, uint16_t rtp_port)
566{
567 RANAP_ProtocolIE_FieldPair_t *pair;
568 RANAP_RAB_AssignmentRequestIEs_t ies;
569 RANAP_RAB_AssignmentRequest_t out;
570 struct msgb *msg;
571 int rc;
572
573 memset(&ies, 0, sizeof(ies));
574 memset(&out, 0, sizeof(out));
575
576 /* only assingnment is present, no release */
577 ies.presenceMask = RAB_ASSIGNMENTREQUESTIES_RANAP_RAB_SETUPORMODIFYLIST_PRESENT;
578
579 /* put together the 'First' part */
580 RANAP_RAB_SetupOrModifyItemFirst_t first;
581 memset(&first, 0, sizeof(first));
582 assign_new_ra_id(&first.rAB_ID, rab_id);
583 //first.nAS_SynchronisationIndicator = FIXME;
584 first.rAB_Parameters = new_rab_par_voice();
585 first.userPlaneInformation = new_upi(RANAP_UserPlaneMode_support_mode_for_predefined_SDU_sizes, 1); /* 2? */
586 first.transportLayerInformation = new_transp_info_rtp(rtp_ip, rtp_port);
587
588 /* put together the 'Second' part */
589 RANAP_RAB_SetupOrModifyItemSecond_t second;
590 memset(&second, 0, sizeof(second));
591
592 /* Build an IE Pair out of first and second part:
593 * (first, second) -> pair */
594 pair = ranap_new_ie_pair(RANAP_ProtocolIE_ID_id_RAB_SetupOrModifyItem,
595 RANAP_Criticality_reject,
596 &asn_DEF_RANAP_RAB_SetupOrModifyItemFirst, &first,
597 RANAP_Criticality_ignore,
598 &asn_DEF_RANAP_RAB_SetupOrModifyItemSecond, &second);
599
600 /* the pair has been made, we can release any of its elements */
601 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_SetupOrModifyItemFirst, &first);
602 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_SetupOrModifyItemSecond, &second);
603
Harald Welteb7f67c42015-12-19 02:36:52 +0100604 RANAP_ProtocolIE_ContainerPair_t *container_pair = CALLOC(1, sizeof(*container_pair));
Harald Weltef8db61b2015-12-18 17:29:59 +0100605 /* Add the pair to the list of IEs of the RAB ass.req */
Harald Welteb7f67c42015-12-19 02:36:52 +0100606 ASN_SEQUENCE_ADD(container_pair, pair);
607 ASN_SEQUENCE_ADD(&ies.raB_SetupOrModifyList.list, container_pair);
Harald Weltef8db61b2015-12-18 17:29:59 +0100608
609 /* encode the IEs into the actual assignment request:
610 * ies -> out */
611 rc = ranap_encode_rab_assignmentrequesties(&out, &ies);
612 /* 'out' has been generated, we can now release the input */
613 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_SetupOrModifyList,
614 &ies.raB_SetupOrModifyList);
615 if (rc < 0)
616 return NULL;
617
618 /* generate an Initiating Mesasage: out -> msg */
619 msg = ranap_generate_initiating_message(RANAP_ProcedureCode_id_RAB_Assignment,
620 RANAP_Criticality_reject,
621 &asn_DEF_RANAP_RAB_AssignmentRequest, &out);
622
623 /* 'msg' has been generated, we cann now release the input 'out' */
624 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_AssignmentRequest, &out);
625
626 return msg;
627}
628
629/*! \brief generate RANAP RAB ASSIGNMENT REQUEST message for PS (data) */
630struct msgb *ranap_new_msg_rab_assign_data(uint8_t rab_id, uint32_t gtp_ip, uint32_t gtp_tei)
631{
632 RANAP_ProtocolIE_FieldPair_t *pair;
633 RANAP_RAB_AssignmentRequestIEs_t ies;
634 RANAP_RAB_AssignmentRequest_t out;
635 RANAP_DataVolumeReportingIndication_t *dat_vol_ind;
636 struct msgb *msg;
637 int rc;
638
639 memset(&ies, 0, sizeof(ies));
640 memset(&out, 0, sizeof(out));
641
642 /* only assingnment is present, no release */
643 ies.presenceMask = RAB_ASSIGNMENTREQUESTIES_RANAP_RAB_SETUPORMODIFYLIST_PRESENT;
644
645 /* put together the 'First' part */
646 RANAP_RAB_SetupOrModifyItemFirst_t first;
647 memset(&first, 0, sizeof(first));
648 assign_new_ra_id(&first.rAB_ID, rab_id);
649 //first.nAS_SynchronisationIndicator = FIXME;
650 first.rAB_Parameters = new_rab_par_data();
651 first.userPlaneInformation = new_upi(RANAP_UserPlaneMode_transparent_mode, 1);
652 first.transportLayerInformation = new_transp_info_rtp(gtp_ip, gtp_tei);
653
654 /* put together the 'Second' part */
655 RANAP_RAB_SetupOrModifyItemSecond_t second;
656 memset(&second, 0, sizeof(second));
657 second.pDP_TypeInformation = CALLOC(1, sizeof(*second.pDP_TypeInformation));
658 ASN_SEQUENCE_ADD(second.pDP_TypeInformation, new_long(RANAP_PDP_Type_ipv4));
659 dat_vol_ind = CALLOC(1, sizeof(*dat_vol_ind));
660 *dat_vol_ind = RANAP_DataVolumeReportingIndication_do_not_report;
661 second.dataVolumeReportingIndication = dat_vol_ind;
662 second.dl_GTP_PDU_SequenceNumber = new_long(0);
663 second.ul_GTP_PDU_SequenceNumber = new_long(0);
664
665 /* Build an IE Pair out of first and second part:
666 * (first, second) -> pair */
667 pair = ranap_new_ie_pair(RANAP_ProtocolIE_ID_id_RAB_SetupOrModifyItem,
668 RANAP_Criticality_reject,
669 &asn_DEF_RANAP_RAB_SetupOrModifyItemFirst,
670 &first, RANAP_Criticality_ignore,
671 &asn_DEF_RANAP_RAB_SetupOrModifyItemSecond,
672 &second);
673
674 /* the pair has been made, we can release any of its elements */
675 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_SetupOrModifyItemFirst, &first);
676 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_SetupOrModifyItemSecond, &second);
677
Harald Welteb7f67c42015-12-19 02:36:52 +0100678 RANAP_ProtocolIE_ContainerPair_t *container_pair = CALLOC(1, sizeof(*container_pair));
Harald Weltef8db61b2015-12-18 17:29:59 +0100679 /* Add the pair to the list of IEs of the RAB ass.req */
Harald Welteb7f67c42015-12-19 02:36:52 +0100680 ASN_SEQUENCE_ADD(container_pair, pair);
681 /* Add the pair to the list of IEs of the RAB ass.req */
682 ASN_SEQUENCE_ADD(&ies.raB_SetupOrModifyList.list, container_pair);
Harald Weltef8db61b2015-12-18 17:29:59 +0100683
684 /* encode the IEs into the actual assignment request:
685 * ies -> out */
686 rc = ranap_encode_rab_assignmentrequesties(&out, &ies);
687 /* 'out' has been generated, we can now release the input */
688 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_SetupOrModifyList,
689 &ies.raB_SetupOrModifyList);
690 if (rc < 0)
691 return NULL;
692
693 /* generate an Initiating Mesasage: out -> msg */
694 msg = ranap_generate_initiating_message(RANAP_ProcedureCode_id_RAB_Assignment,
695 RANAP_Criticality_reject,
696 &asn_DEF_RANAP_RAB_AssignmentRequest, &out);
697
698 /* 'msg' has been generated, we cann now release the input 'out' */
699 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_AssignmentRequest, &out);
700
701 return msg;
702}