blob: 879cbe08b182127329b26ed7669f99f90344dd88 [file] [log] [blame]
Daniel Willmann97374c02015-12-03 09:37:58 +01001/* Test HNB */
2
3/* (C) 2015 by Daniel Willmann <dwillmann@sysmocom.de>
4 * (C) 2015 by Sysmocom s.f.m.c. GmbH
5 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
16 *
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22#include <unistd.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <getopt.h>
27#include <errno.h>
28#include <signal.h>
29
30#include <sys/types.h>
31#include <sys/socket.h>
32#include <netinet/in.h>
33#include <netinet/sctp.h>
34#include <arpa/inet.h>
35
36#include <osmocom/core/application.h>
37#include <osmocom/core/talloc.h>
38#include <osmocom/core/select.h>
39#include <osmocom/core/logging.h>
40#include <osmocom/core/socket.h>
41#include <osmocom/core/msgb.h>
42#include <osmocom/core/write_queue.h>
Harald Weltec3851222015-12-24 15:41:21 +010043#include <osmocom/netif/stream.h>
Neels Hofmeyrae937122016-02-29 09:32:00 +010044#include <osmocom/gsm/tlv.h>
45#include <osmocom/gsm/gsm48.h>
Daniel Willmann97374c02015-12-03 09:37:58 +010046
47#include <osmocom/vty/telnet_interface.h>
48#include <osmocom/vty/logging.h>
Harald Weltec3851222015-12-24 15:41:21 +010049#include <osmocom/vty/command.h>
Daniel Willmann97374c02015-12-03 09:37:58 +010050
51#include "hnb-test.h"
Daniel Willmanna1e202e2015-12-07 17:21:07 +010052#include "hnbap_common.h"
53#include "hnbap_ies_defs.h"
Harald Welteb66c5d02016-01-03 18:04:28 +010054#include "rua_msg_factory.h"
Harald Weltec3851222015-12-24 15:41:21 +010055#include "asn1helpers.h"
Neels Hofmeyr96979af2016-01-05 15:19:44 +010056#include <osmocom/ranap/iu_helpers.h>
Harald Welte87ffeb92015-12-25 15:34:22 +010057#include "test_common.h"
Harald Weltec3851222015-12-24 15:41:21 +010058
Neels Hofmeyr96979af2016-01-05 15:19:44 +010059#include <osmocom/ranap/ranap_msg_factory.h>
Daniel Willmann97374c02015-12-03 09:37:58 +010060
Neels Hofmeyr0968a582016-01-11 15:19:38 +010061#include <osmocom/rua/RUA_RUA-PDU.h>
62
Neels Hofmeyr860a1292016-02-18 23:03:15 +010063#include <osmocom/gsm/protocol/gsm_04_08.h>
64
65#include <osmocom/ranap/RANAP_ProcedureCode.h>
66#include <osmocom/ranap/RANAP_Criticality.h>
67#include <osmocom/ranap/RANAP_DirectTransfer.h>
68
Daniel Willmann97374c02015-12-03 09:37:58 +010069static void *tall_hnb_ctx;
Daniel Willmann97374c02015-12-03 09:37:58 +010070
71struct hnb_test g_hnb_test = {
Neels Hofmeyr5f9be1e2016-02-29 13:33:44 +010072 .gw_addr = "127.0.0.1",
Daniel Willmann97374c02015-12-03 09:37:58 +010073 .gw_port = IUH_DEFAULT_SCTP_PORT,
74};
75
Harald Weltec3851222015-12-24 15:41:21 +010076struct msgb *rua_new_udt(struct msgb *inmsg);
77
Harald Weltec3851222015-12-24 15:41:21 +010078static int hnb_test_ue_de_register_tx(struct hnb_test *hnb_test)
Daniel Willmann19dedbb2015-12-17 11:57:41 +010079{
80 struct msgb *msg;
81 int rc, imsi_len;
82 uint32_t ctx_id;
83
84 UEDe_Register_t dereg;
85 UEDe_RegisterIEs_t dereg_ies;
86 memset(&dereg_ies, 0, sizeof(dereg_ies));
87
88 asn1_u24_to_bitstring(&dereg_ies.context_ID, &ctx_id, hnb_test->ctx_id);
89 dereg_ies.cause.present = Cause_PR_radioNetwork;
90 dereg_ies.cause.choice.radioNetwork = CauseRadioNetwork_connection_with_UE_lost;
91
92 memset(&dereg, 0, sizeof(dereg));
93 rc = hnbap_encode_uede_registeries(&dereg, &dereg_ies);
94
95 msg = hnbap_generate_initiating_message(ProcedureCode_id_UEDe_Register,
96 Criticality_ignore,
97 &asn_DEF_UEDe_Register,
98 &dereg);
99
Harald Weltec3851222015-12-24 15:41:21 +0100100 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_UEDe_Register, &dereg);
Daniel Willmann19dedbb2015-12-17 11:57:41 +0100101
Harald Weltec3851222015-12-24 15:41:21 +0100102 msgb_sctp_ppid(msg) = IUH_PPI_HNBAP;
Daniel Willmann19dedbb2015-12-17 11:57:41 +0100103
104 return osmo_wqueue_enqueue(&hnb_test->wqueue, msg);
105}
106
Harald Weltec3851222015-12-24 15:41:21 +0100107static int hnb_test_ue_register_tx(struct hnb_test *hnb_test, const char *imsi_str)
Daniel Willmann479cb302015-12-09 17:54:59 +0100108{
Daniel Willmann4e312502015-12-09 17:59:24 +0100109 struct msgb *msg;
110 int rc, imsi_len;
111
112 char imsi_buf[16];
Daniel Willmann141a0ba2015-12-17 18:03:52 +0100113
Daniel Willmann4e312502015-12-09 17:59:24 +0100114 UERegisterRequest_t request_out;
115 UERegisterRequestIEs_t request;
116 memset(&request, 0, sizeof(request));
117
118 request.uE_Identity.present = UE_Identity_PR_iMSI;
119
Harald Welte056984f2016-01-03 16:31:31 +0100120 imsi_len = ranap_imsi_encode(imsi_buf, sizeof(imsi_buf), imsi_str);
Harald Weltec3851222015-12-24 15:41:21 +0100121 OCTET_STRING_fromBuf(&request.uE_Identity.choice.iMSI, imsi_buf, imsi_len);
Daniel Willmann4e312502015-12-09 17:59:24 +0100122
123 request.registration_Cause = Registration_Cause_normal;
124 request.uE_Capabilities.access_stratum_release_indicator = Access_stratum_release_indicator_rel_6;
125 request.uE_Capabilities.csg_capability = CSG_Capability_not_csg_capable;
126
127 memset(&request_out, 0, sizeof(request_out));
128 rc = hnbap_encode_ueregisterrequesties(&request_out, &request);
129
130 msg = hnbap_generate_initiating_message(ProcedureCode_id_UERegister,
131 Criticality_reject,
132 &asn_DEF_UERegisterRequest,
133 &request_out);
134
Harald Weltec3851222015-12-24 15:41:21 +0100135 ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_UERegisterRequest, &request_out);
Daniel Willmann4e312502015-12-09 17:59:24 +0100136
Harald Weltec3851222015-12-24 15:41:21 +0100137 msgb_sctp_ppid(msg) = IUH_PPI_HNBAP;
Daniel Willmann4e312502015-12-09 17:59:24 +0100138
139 return osmo_wqueue_enqueue(&hnb_test->wqueue, msg);
Daniel Willmann479cb302015-12-09 17:54:59 +0100140}
141
Harald Weltec3851222015-12-24 15:41:21 +0100142static int hnb_test_rx_hnb_register_acc(struct hnb_test *hnb, ANY_t *in)
Daniel Willmann479cb302015-12-09 17:54:59 +0100143{
144 int rc;
145 HNBRegisterAcceptIEs_t accept;
146
147 rc = hnbap_decode_hnbregisteraccepties(&accept, in);
148 if (rc < 0) {
149 }
150
151 hnb->rnc_id = accept.rnc_id;
152 printf("HNB Register accept with RNC ID %u\n", hnb->rnc_id);
153
Daniel Willmann11e912a2016-01-07 13:19:30 +0100154 hnbap_free_hnbregisteraccepties(&accept);
Harald Weltec3851222015-12-24 15:41:21 +0100155 return 0;
Daniel Willmann479cb302015-12-09 17:54:59 +0100156}
157
Harald Weltec3851222015-12-24 15:41:21 +0100158static int hnb_test_rx_ue_register_acc(struct hnb_test *hnb, ANY_t *in)
Daniel Willmanna7b02402015-12-09 19:05:09 +0100159{
160 int rc;
161 uint32_t ctx_id;
162 UERegisterAcceptIEs_t accept;
163 char imsi[16];
164
165 rc = hnbap_decode_ueregisteraccepties(&accept, in);
166 if (rc < 0) {
167 return rc;
168 }
169
170 if (accept.uE_Identity.present != UE_Identity_PR_iMSI) {
171 printf("Wrong type in UE register accept\n");
172 return -1;
173 }
174
175 ctx_id = asn1bitstr_to_u24(&accept.context_ID);
176
Harald Welte056984f2016-01-03 16:31:31 +0100177 ranap_bcd_decode(imsi, sizeof(imsi), accept.uE_Identity.choice.iMSI.buf,
Daniel Willmanna7b02402015-12-09 19:05:09 +0100178 accept.uE_Identity.choice.iMSI.size);
179 printf("UE Register accept for IMSI %s, context %u\n", imsi, ctx_id);
180
Daniel Willmann19dedbb2015-12-17 11:57:41 +0100181 hnb->ctx_id = ctx_id;
Daniel Willmann11e912a2016-01-07 13:19:30 +0100182 hnbap_free_ueregisteraccepties(&accept);
Daniel Willmann19dedbb2015-12-17 11:57:41 +0100183
Daniel Willmanna7b02402015-12-09 19:05:09 +0100184 return 0;
185}
186
Neels Hofmeyr860a1292016-02-18 23:03:15 +0100187static struct msgb *gen_nas_id_resp()
188{
189 uint8_t id_resp[] = {
Neels Hofmeyr5c1cc8c2016-02-29 09:28:48 +0100190 GSM48_PDISC_MM,
191 GSM48_MT_MM_ID_RESP,
Neels Hofmeyr860a1292016-02-18 23:03:15 +0100192 /* IMEISV */
193 0x09, /* len */
194 0x03, /* first digit (0000) + even (0) + id IMEISV (011) */
195 0x31, 0x91, 0x06, 0x00, 0x28, 0x47, 0x11, /* digits */
196 0xf2, /* filler (1111) + last digit (0010) */
197 };
198
Neels Hofmeyre1f709f2016-02-28 00:50:45 +0100199 return ranap_new_msg_dt(0, id_resp, sizeof(id_resp));
Neels Hofmeyr860a1292016-02-18 23:03:15 +0100200}
201
Neels Hofmeyrae937122016-02-29 09:32:00 +0100202static struct msgb *gen_nas_tmsi_realloc_compl()
203{
204 uint8_t id_resp[] = {
205 GSM48_PDISC_MM,
206 GSM48_MT_MM_TMSI_REALL_COMPL,
207 };
208
209 return ranap_new_msg_dt(0, id_resp, sizeof(id_resp));
210}
211
Neels Hofmeyr35888102016-03-09 01:39:56 +0100212static struct msgb *gen_nas_auth_resp()
213{
214 uint8_t id_resp[] = {
215 GSM48_PDISC_MM,
216 GSM48_MT_MM_AUTH_RESP,
217 0x61, 0xb5, 0x69, 0xf5 /* hardcoded SRES */
218 };
219
220 return ranap_new_msg_dt(0, id_resp, sizeof(id_resp));
221}
222
Neels Hofmeyrae937122016-02-29 09:32:00 +0100223static int hnb_test_nas_tx_dt(struct hnb_test *hnb, struct msgb *txm)
Neels Hofmeyr860a1292016-02-18 23:03:15 +0100224{
225 struct hnbtest_chan *chan;
Neels Hofmeyrae937122016-02-29 09:32:00 +0100226 struct msgb *rua;
Neels Hofmeyr860a1292016-02-18 23:03:15 +0100227
228 chan = hnb->cs.chan;
229 if (!chan) {
Neels Hofmeyrae937122016-02-29 09:32:00 +0100230 printf("hnb_test_nas_tx_tmsi_realloc_compl(): No CS channel established yet.\n");
Neels Hofmeyr860a1292016-02-18 23:03:15 +0100231 return -1;
232 }
233
Neels Hofmeyr860a1292016-02-18 23:03:15 +0100234 rua = rua_new_dt(chan->is_ps, chan->conn_id, txm);
Neels Hofmeyr860a1292016-02-18 23:03:15 +0100235 osmo_wqueue_enqueue(&g_hnb_test.wqueue, rua);
Neels Hofmeyr860a1292016-02-18 23:03:15 +0100236 return 0;
237}
238
Neels Hofmeyrd4598fa2016-03-09 01:37:40 +0100239static struct tlv_parsed *parse_mm(struct msgb *rxm)
240{
241 static struct tlv_parsed tp;
242 struct gsm48_hdr *gh;
243 int parse_res;
244 int length = msgb_l3len(rxm);
245
246 if (length < sizeof(*gh)) {
247 printf("GSM48 header does not fit.\n");
248 return NULL;
249 }
250
251 gh = (struct gsm48_hdr *) msgb_l3(rxm);
Neels Hofmeyr8c2b4ec2016-04-04 19:27:53 +0200252 if (!gh) {
253 printf("received msg buffer with invalid layer 3. Ignoring.\n");
254 return -1;
255 }
Neels Hofmeyrd4598fa2016-03-09 01:37:40 +0100256 length -= (const char *)&gh->data[0] - (const char *)gh;
257
258 parse_res = tlv_parse(&tp, &gsm48_mm_att_tlvdef, &gh->data[0], length, 0, 0);
259 if (parse_res <= 0) {
Neels Hofmeyr7c28f6f2016-04-05 11:49:53 +0200260 uint8_t msg_type = gsm48_hdr_msg_type(gh);
Neels Hofmeyrd4598fa2016-03-09 01:37:40 +0100261 printf("Error parsing MM message 0x%hhx: %d\n", msg_type, parse_res);
262 return NULL;
263 }
264
265 return &tp;
266}
267
Neels Hofmeyrc04eb532016-03-04 12:38:43 +0100268int hnb_test_nas_rx_lu_accept(struct msgb *rxm, int *sent_tmsi)
Neels Hofmeyrae937122016-02-29 09:32:00 +0100269{
270 printf(" :D Location Update Accept :D\n");
271 struct gsm48_hdr *gh;
272 struct gsm48_loc_area_id *lai;
Neels Hofmeyrc04eb532016-03-04 12:38:43 +0100273 int length = msgb_l3len(rxm);
274
275 if (length < sizeof(*gh)) {
276 printf("GSM48 header does not fit.\n");
277 return -1;
278 }
279
Neels Hofmeyrae937122016-02-29 09:32:00 +0100280 gh = (struct gsm48_hdr *)msgb_l3(rxm);
Neels Hofmeyr8c2b4ec2016-04-04 19:27:53 +0200281 if (!gh) {
282 printf("received msg buffer with invalid layer 3. Ignoring.\n");
283 return -1;
284 }
Neels Hofmeyrae937122016-02-29 09:32:00 +0100285 lai = (struct gsm48_loc_area_id *)&gh->data[0];
286
287 uint16_t mcc, mnc, lac;
288 gsm48_decode_lai(lai, &mcc, &mnc, &lac);
289 printf("LU: mcc %hd mnc %hd lac %hd\n",
290 mcc, mnc, lac);
291
Neels Hofmeyrc04eb532016-03-04 12:38:43 +0100292 struct tlv_parsed tp;
293 int parse_res;
294
295 length -= (const char *)&gh->data[0] - (const char *)gh;
296 parse_res = tlv_parse(&tp, &gsm48_mm_att_tlvdef, &gh->data[0], length, 0, 0);
297 if (parse_res <= 0) {
298 printf("Error parsing Location Update Accept message: %d\n", parse_res);
299 return -1;
300 }
301
302 if (TLVP_PRESENT(&tp, GSM48_IE_MOBILE_ID)) {
303 uint8_t type = TLVP_VAL(&tp, GSM48_IE_NAME_SHORT)[0] & 0x0f;
304 if (type == GSM_MI_TYPE_TMSI)
305 *sent_tmsi = 1;
306 else *sent_tmsi = 0;
307 }
308 return 0;
Neels Hofmeyrae937122016-02-29 09:32:00 +0100309}
310
311void hnb_test_nas_rx_mm_info(struct msgb *rxm)
312{
313 printf(" :) MM Info :)\n");
Neels Hofmeyrd4598fa2016-03-09 01:37:40 +0100314 struct tlv_parsed *tp = parse_mm(rxm);
315 if (!tp)
Neels Hofmeyrae937122016-02-29 09:32:00 +0100316 return;
Neels Hofmeyrae937122016-02-29 09:32:00 +0100317
Neels Hofmeyrd4598fa2016-03-09 01:37:40 +0100318 if (TLVP_PRESENT(tp, GSM48_IE_NAME_SHORT)) {
Neels Hofmeyrae937122016-02-29 09:32:00 +0100319 char name[128] = {0};
320 gsm_7bit_decode_n(name, 127,
Neels Hofmeyrd4598fa2016-03-09 01:37:40 +0100321 TLVP_VAL(tp, GSM48_IE_NAME_SHORT)+1,
322 (TLVP_LEN(tp, GSM48_IE_NAME_SHORT)-1)*8/7);
Neels Hofmeyrae937122016-02-29 09:32:00 +0100323 printf("Info: Short Network Name: %s\n", name);
324 }
325
Neels Hofmeyrd4598fa2016-03-09 01:37:40 +0100326 if (TLVP_PRESENT(tp, GSM48_IE_NAME_LONG)) {
Neels Hofmeyrae937122016-02-29 09:32:00 +0100327 char name[128] = {0};
328 gsm_7bit_decode_n(name, 127,
Neels Hofmeyrd4598fa2016-03-09 01:37:40 +0100329 TLVP_VAL(tp, GSM48_IE_NAME_LONG)+1,
330 (TLVP_LEN(tp, GSM48_IE_NAME_LONG)-1)*8/7);
Neels Hofmeyrae937122016-02-29 09:32:00 +0100331 printf("Info: Long Network Name: %s\n", name);
332 }
Neels Hofmeyrae937122016-02-29 09:32:00 +0100333}
334
Neels Hofmeyr35888102016-03-09 01:39:56 +0100335static void hnb_test_nas_rx_auth_req(struct msgb *rxm)
336{
337 struct gsm48_hdr *gh;
338 struct gsm48_auth_req *ar;
339 int parse_res;
340 int length = msgb_l3len(rxm);
341
342 if (length < sizeof(*gh)) {
343 printf("GSM48 header does not fit.\n");
344 return;
345 }
346
347 gh = (struct gsm48_hdr *) msgb_l3(rxm);
Neels Hofmeyr8c2b4ec2016-04-04 19:27:53 +0200348 if (!gh) {
349 printf("received msg buffer with invalid layer 3. Ignoring.\n");
350 return -1;
351 }
Neels Hofmeyr35888102016-03-09 01:39:56 +0100352 length -= (const char *)&gh->data[0] - (const char *)gh;
353
354 if (length < sizeof(*ar)) {
355 printf("GSM48 Auth Req does not fit.\n");
356 return;
357 }
358
359 printf(" :) Authentication Request :)\n");
360
361 ar = (struct gsm48_auth_req*) &gh->data[0];
362 int seq = ar->key_seq;
363 printf("seq %d rand %s\n", seq, osmo_hexdump(ar->rand, sizeof(ar->rand)));
364}
365
Neels Hofmeyr860a1292016-02-18 23:03:15 +0100366static int hnb_test_nas_rx_mm(struct hnb_test *hnb, struct msgb *rxm)
367{
368 struct hnbtest_chan *chan;
369
370 chan = hnb->cs.chan;
371 if (!chan) {
372 printf("hnb_test_nas_rx_mm(): No CS channel established yet.\n");
373 return -1;
374 }
375
376 OSMO_ASSERT(!chan->is_ps);
377
378 struct gsm48_hdr *gh = msgb_l3(rxm);
Neels Hofmeyr8c2b4ec2016-04-04 19:27:53 +0200379 if (!gh) {
380 printf("received msg buffer with invalid layer 3. Ignoring.\n");
381 return -1;
382 }
Neels Hofmeyr7c28f6f2016-04-05 11:49:53 +0200383 uint8_t msg_type = gsm48_hdr_msg_type(gh);
Neels Hofmeyrc04eb532016-03-04 12:38:43 +0100384 int sent_tmsi;
Neels Hofmeyr860a1292016-02-18 23:03:15 +0100385
386 switch (msg_type) {
387 case GSM48_MT_MM_ID_REQ:
Neels Hofmeyrae937122016-02-29 09:32:00 +0100388 return hnb_test_nas_tx_dt(hnb, gen_nas_id_resp());
Neels Hofmeyr860a1292016-02-18 23:03:15 +0100389
Neels Hofmeyrae937122016-02-29 09:32:00 +0100390 case GSM48_MT_MM_LOC_UPD_ACCEPT:
Neels Hofmeyrc04eb532016-03-04 12:38:43 +0100391 if (hnb_test_nas_rx_lu_accept(rxm, &sent_tmsi))
392 return -1;
393 if (sent_tmsi)
394 return hnb_test_nas_tx_dt(hnb, gen_nas_tmsi_realloc_compl());
395 else
396 return 0;
Neels Hofmeyrae937122016-02-29 09:32:00 +0100397
Neels Hofmeyr5dbb7b22016-03-09 01:38:13 +0100398 case GSM48_MT_MM_LOC_UPD_REJECT:
399 printf("Received Location Update Reject\n");
400 return 0;
401
Neels Hofmeyrae937122016-02-29 09:32:00 +0100402 case GSM48_MT_MM_INFO:
403 hnb_test_nas_rx_mm_info(rxm);
404 return 0;
405
Neels Hofmeyr35888102016-03-09 01:39:56 +0100406 case GSM48_MT_MM_AUTH_REQ:
407 hnb_test_nas_rx_auth_req(rxm);
408 return hnb_test_nas_tx_dt(hnb, gen_nas_auth_resp());
409
Neels Hofmeyr860a1292016-02-18 23:03:15 +0100410 default:
Neels Hofmeyrae937122016-02-29 09:32:00 +0100411 printf("04.08 message type not handled by hnb-test: 0x%x\n",
Neels Hofmeyr860a1292016-02-18 23:03:15 +0100412 msg_type);
413 return 0;
414 }
415
416}
417
418static int hnb_test_nas_rx_dtap(struct hnb_test *hnb, struct msgb *msg)
419{
420 printf("got %s\n", osmo_hexdump(msg->data, msg->len));
421
422 // nas_pdu == '05 08 12' ==> IMEI Identity request
423 // '05 04 0d' ==> LU reject
424
425 struct gsm48_hdr *gh = msgb_l3(msg);
Neels Hofmeyr8c2b4ec2016-04-04 19:27:53 +0200426 if (!gh) {
427 printf("received msg buffer with invalid layer 3. Ignoring.\n");
428 return -1;
429 }
Neels Hofmeyr7c28f6f2016-04-05 11:49:53 +0200430 uint8_t pdisc = gsm48_hdr_pdisc(gh);
Neels Hofmeyr860a1292016-02-18 23:03:15 +0100431
432 switch (pdisc) {
433 case GSM48_PDISC_MM:
434 return hnb_test_nas_rx_mm(hnb, msg);
435 default:
436 printf("04.08 discriminator not handled by hnb-test: %d\n",
437 pdisc);
438 return 0;
439 }
440
441
442}
443
Daniel Willmann479cb302015-12-09 17:54:59 +0100444int hnb_test_hnbap_rx(struct hnb_test *hnb, struct msgb *msg)
445{
446 HNBAP_PDU_t _pdu, *pdu = &_pdu;
447 asn_dec_rval_t dec_ret;
448 int rc;
449
450 memset(pdu, 0, sizeof(*pdu));
451 dec_ret = aper_decode(NULL, &asn_DEF_HNBAP_PDU, (void **) &pdu,
452 msg->data, msgb_length(msg), 0, 0);
453 if (dec_ret.code != RC_OK) {
454 LOGP(DMAIN, LOGL_ERROR, "Error in ASN.1 decode\n");
455 return rc;
456 }
457
458 if (pdu->present != HNBAP_PDU_PR_successfulOutcome) {
459 printf("Unexpected HNBAP message received\n");
460 }
461
462 switch (pdu->choice.successfulOutcome.procedureCode) {
463 case ProcedureCode_id_HNBRegister:
464 /* Get HNB id and send UE Register request */
465 rc = hnb_test_rx_hnb_register_acc(hnb, &pdu->choice.successfulOutcome.value);
466 break;
467 case ProcedureCode_id_UERegister:
Daniel Willmanna7b02402015-12-09 19:05:09 +0100468 rc = hnb_test_rx_ue_register_acc(hnb, &pdu->choice.successfulOutcome.value);
Daniel Willmann479cb302015-12-09 17:54:59 +0100469 break;
470 default:
471 break;
472 }
473
474 return rc;
475}
476
Neels Hofmeyrb984f362016-02-18 01:18:20 +0100477extern void direct_transfer_nas_pdu_print(ANY_t *in);
478
Neels Hofmeyr0968a582016-01-11 15:19:38 +0100479int hnb_test_rua_rx(struct hnb_test *hnb, struct msgb *msg)
480{
481 RUA_RUA_PDU_t _pdu, *pdu = &_pdu;
482 asn_dec_rval_t dec_ret;
483 int rc;
484
485 memset(pdu, 0, sizeof(*pdu));
486 dec_ret = aper_decode(NULL, &asn_DEF_RUA_RUA_PDU, (void **) &pdu,
487 msg->data, msgb_length(msg), 0, 0);
488 if (dec_ret.code != RC_OK) {
489 LOGP(DMAIN, LOGL_ERROR, "Error in ASN.1 decode\n");
490 return rc;
491 }
492
493 switch (pdu->present) {
494 case RUA_RUA_PDU_PR_successfulOutcome:
495 printf("RUA_RUA_PDU_PR_successfulOutcome\n");
496 break;
497 case RUA_RUA_PDU_PR_initiatingMessage:
498 printf("RUA_RUA_PDU_PR_initiatingMessage\n");
499 break;
500 case RUA_RUA_PDU_PR_NOTHING:
501 printf("RUA_RUA_PDU_PR_NOTHING\n");
502 break;
503 case RUA_RUA_PDU_PR_unsuccessfulOutcome:
504 printf("RUA_RUA_PDU_PR_unsuccessfulOutcome\n");
505 break;
506 default:
507 printf("Unexpected RUA message received\n");
508 break;
509 }
510
511 switch (pdu->choice.successfulOutcome.procedureCode) {
512 case RUA_ProcedureCode_id_ConnectionlessTransfer:
513 printf("RUA rx Connectionless Transfer\n");
514 break;
515 case RUA_ProcedureCode_id_Connect:
516 printf("RUA rx Connect\n");
517 break;
518 case RUA_ProcedureCode_id_DirectTransfer:
519 printf("RUA rx DirectTransfer\n");
Neels Hofmeyrb984f362016-02-18 01:18:20 +0100520 {
521 struct msgb *m = msgb_alloc(1500, "direct_transfer_nas_pdu");
522 direct_transfer_nas_pdu_get(&pdu->choice.successfulOutcome.value, m);
523
Neels Hofmeyr860a1292016-02-18 23:03:15 +0100524 hnb_test_nas_rx_dtap(hnb, m);
Neels Hofmeyrb984f362016-02-18 01:18:20 +0100525
Neels Hofmeyrb984f362016-02-18 01:18:20 +0100526 msgb_free(m);
527 }
Neels Hofmeyr0968a582016-01-11 15:19:38 +0100528 break;
529 case RUA_ProcedureCode_id_Disconnect:
530 printf("RUA rx Disconnect\n");
531 break;
532 case RUA_ProcedureCode_id_ErrorIndication:
533 printf("RUA rx ErrorIndication\n");
534 break;
535 case RUA_ProcedureCode_id_privateMessage:
536 printf("RUA rx privateMessage\n");
537 break;
538 default:
539 printf("RUA rx unknown message\n");
540 break;
541 }
542
543 return rc;
544}
545
Daniel Willmann97374c02015-12-03 09:37:58 +0100546static int hnb_read_cb(struct osmo_fd *fd)
547{
548 struct hnb_test *hnb_test = fd->data;
549 struct sctp_sndrcvinfo sinfo;
550 struct msgb *msg = msgb_alloc(IUH_MSGB_SIZE, "Iuh rx");
551 int flags = 0;
552 int rc;
553
554 if (!msg)
555 return -ENOMEM;
556
557 rc = sctp_recvmsg(fd->fd, msgb_data(msg), msgb_tailroom(msg),
558 NULL, NULL, &sinfo, &flags);
559 if (rc < 0) {
560 LOGP(DMAIN, LOGL_ERROR, "Error during sctp_recvmsg()\n");
561 /* FIXME: clean up after disappeared HNB */
Daniel Willmann6637a282015-12-17 14:47:51 +0100562 close(fd->fd);
563 osmo_fd_unregister(fd);
Daniel Willmann97374c02015-12-03 09:37:58 +0100564 return rc;
Daniel Willmann6637a282015-12-17 14:47:51 +0100565 } else if (rc == 0) {
566 LOGP(DMAIN, LOGL_INFO, "Connection to HNB closed\n");
567 close(fd->fd);
568 osmo_fd_unregister(fd);
569 fd->fd = -1;
570
571 return -1;
572 } else {
Daniel Willmann97374c02015-12-03 09:37:58 +0100573 msgb_put(msg, rc);
Daniel Willmann6637a282015-12-17 14:47:51 +0100574 }
Daniel Willmann97374c02015-12-03 09:37:58 +0100575
576 if (flags & MSG_NOTIFICATION) {
Daniel Willmann32797802015-12-17 12:53:05 +0100577 LOGP(DMAIN, LOGL_DEBUG, "Ignoring SCTP notification\n");
Daniel Willmann97374c02015-12-03 09:37:58 +0100578 msgb_free(msg);
579 return 0;
580 }
581
582 sinfo.sinfo_ppid = ntohl(sinfo.sinfo_ppid);
583
584 switch (sinfo.sinfo_ppid) {
585 case IUH_PPI_HNBAP:
Neels Hofmeyr0968a582016-01-11 15:19:38 +0100586 printf("HNBAP message received\n");
Daniel Willmann479cb302015-12-09 17:54:59 +0100587 rc = hnb_test_hnbap_rx(hnb_test, msg);
Daniel Willmann97374c02015-12-03 09:37:58 +0100588 break;
589 case IUH_PPI_RUA:
Neels Hofmeyr0968a582016-01-11 15:19:38 +0100590 printf("RUA message received\n");
591 rc = hnb_test_rua_rx(hnb_test, msg);
Daniel Willmann97374c02015-12-03 09:37:58 +0100592 break;
593 case IUH_PPI_SABP:
594 case IUH_PPI_RNA:
595 case IUH_PPI_PUA:
596 LOGP(DMAIN, LOGL_ERROR, "Unimplemented SCTP PPID=%u received\n",
597 sinfo.sinfo_ppid);
598 rc = 0;
599 break;
600 default:
601 LOGP(DMAIN, LOGL_ERROR, "Unknown SCTP PPID=%u received\n",
602 sinfo.sinfo_ppid);
603 rc = 0;
604 break;
605 }
606
607 msgb_free(msg);
608 return rc;
609}
610
611static int hnb_write_cb(struct osmo_fd *fd, struct msgb *msg)
612{
613 struct hnb_test *ctx = fd->data;
614 struct sctp_sndrcvinfo sinfo = {
Harald Weltec3851222015-12-24 15:41:21 +0100615 .sinfo_ppid = htonl(msgb_sctp_ppid(msg)),
Daniel Willmann97374c02015-12-03 09:37:58 +0100616 .sinfo_stream = 0,
617 };
618 int rc;
619
Neels Hofmeyre25faa82016-03-04 02:49:52 +0100620 printf("Sending: %s\n", osmo_hexdump(msgb_data(msg), msgb_length(msg)));
Daniel Willmann97374c02015-12-03 09:37:58 +0100621 rc = sctp_send(fd->fd, msgb_data(msg), msgb_length(msg),
622 &sinfo, 0);
623 /* we don't need to msgb_free(), write_queue does this for us */
624 return rc;
625}
626
Daniel Willmann4aeef6c2015-12-03 17:02:13 +0100627static void hnb_send_register_req(struct hnb_test *hnb_test)
628{
Daniel Willmanna1e202e2015-12-07 17:21:07 +0100629 HNBRegisterRequest_t request_out;
Daniel Willmann4aeef6c2015-12-03 17:02:13 +0100630 struct msgb *msg;
631 int rc;
Daniel Willmanna1e202e2015-12-07 17:21:07 +0100632 uint16_t lac, sac;
633 uint8_t rac;
634 uint32_t cid;
635 uint8_t plmn[] = {0x09, 0xf1, 0x99};
636 char identity[50] = "ATestHNB@";
Daniel Willmann4aeef6c2015-12-03 17:02:13 +0100637
Daniel Willmanna1e202e2015-12-07 17:21:07 +0100638 HNBRegisterRequestIEs_t request;
639 memset(&request, 0, sizeof(request));
Daniel Willmann4aeef6c2015-12-03 17:02:13 +0100640
Daniel Willmanna1e202e2015-12-07 17:21:07 +0100641 lac = 0xc0fe;
642 sac = 0xabab;
643 rac = 0x42;
Daniel Willmannd6a45b42015-12-08 13:55:17 +0100644 cid = 0xadceaab;
Daniel Willmann4aeef6c2015-12-03 17:02:13 +0100645
Daniel Willmanna1e202e2015-12-07 17:21:07 +0100646 asn1_u16_to_str(&request.lac, &lac, lac);
647 asn1_u16_to_str(&request.sac, &sac, sac);
648 asn1_u8_to_str(&request.rac, &rac, rac);
Daniel Willmannd6a45b42015-12-08 13:55:17 +0100649 asn1_u28_to_bitstring(&request.cellIdentity, &cid, cid);
Daniel Willmanna1e202e2015-12-07 17:21:07 +0100650
651 request.hnB_Identity.hNB_Identity_Info.buf = identity;
652 request.hnB_Identity.hNB_Identity_Info.size = strlen(identity);
653
654 request.plmNidentity.buf = plmn;
655 request.plmNidentity.size = 3;
656
657
658
659 memset(&request_out, 0, sizeof(request_out));
660 rc = hnbap_encode_hnbregisterrequesties(&request_out, &request);
661 if (rc < 0) {
662 printf("Could not encode HNB register request IEs\n");
663 }
664
665 msg = hnbap_generate_initiating_message(ProcedureCode_id_HNBRegister,
666 Criticality_reject,
667 &asn_DEF_HNBRegisterRequest,
668 &request_out);
669
Daniel Willmann4aeef6c2015-12-03 17:02:13 +0100670
Harald Weltec3851222015-12-24 15:41:21 +0100671 msgb_sctp_ppid(msg) = IUH_PPI_HNBAP;
672
673 osmo_wqueue_enqueue(&hnb_test->wqueue, msg);
674}
675
676static void hnb_send_deregister_req(struct hnb_test *hnb_test)
677{
678 struct msgb *msg;
679 int rc;
680
681 HNBDe_RegisterIEs_t request;
682 memset(&request, 0, sizeof(request));
683
684 request.cause.present = Cause_PR_misc;
685 request.cause.choice.misc = CauseMisc_o_and_m_intervention;
686
687 HNBDe_Register_t request_out;
688 memset(&request_out, 0, sizeof(request_out));
689 rc = hnbap_encode_hnbde_registeries(&request_out, &request);
690 if (rc < 0) {
691 printf("Could not encode HNB deregister request IEs\n");
692 }
693
694 msg = hnbap_generate_initiating_message(ProcedureCode_id_HNBDe_Register,
695 Criticality_reject,
696 &asn_DEF_HNBDe_Register,
697 &request_out);
698
699 msgb_sctp_ppid(msg) = IUH_PPI_HNBAP;
Daniel Willmann4aeef6c2015-12-03 17:02:13 +0100700
701 osmo_wqueue_enqueue(&hnb_test->wqueue, msg);
702}
703
704
Daniel Willmann97374c02015-12-03 09:37:58 +0100705static const struct log_info_cat log_cat[] = {
706 [DMAIN] = {
Daniel Willmann32797802015-12-17 12:53:05 +0100707 .name = "DMAIN", .loglevel = LOGL_INFO, .enabled = 1,
Daniel Willmann97374c02015-12-03 09:37:58 +0100708 .color = "",
709 .description = "Main program",
710 },
Daniel Willmann32797802015-12-17 12:53:05 +0100711 [DHNBAP] = {
712 .name = "DHNBAP", .loglevel = LOGL_DEBUG, .enabled = 1,
713 .color = "",
714 .description = "Home Node B Application Part",
715 },
Daniel Willmann97374c02015-12-03 09:37:58 +0100716};
717
718static const struct log_info hnb_test_log_info = {
719 .cat = log_cat,
720 .num_cat = ARRAY_SIZE(log_cat),
721};
722
723static struct vty_app_info vty_info = {
724 .name = "OsmoHNB-Test",
725 .version = "0",
726};
727
Daniel Willmann4abdee02015-12-09 17:57:32 +0100728static int sctp_sock_init(int fd)
729{
730 struct sctp_event_subscribe event;
731 int rc;
732
733 /* subscribe for all events */
734 memset((uint8_t *)&event, 1, sizeof(event));
735 rc = setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS,
736 &event, sizeof(event));
737
738 return rc;
739}
740
Harald Weltec3851222015-12-24 15:41:21 +0100741#define HNBAP_STR "HNBAP related commands\n"
742#define HNB_STR "HomeNodeB commands\n"
743#define UE_STR "User Equipment commands\n"
744#define RANAP_STR "RANAP related commands\n"
745#define CSPS_STR "Circuit Switched\n" "Packet Switched\n"
746
747DEFUN(hnb_register, hnb_register_cmd,
748 "hnbap hnb register", HNBAP_STR HNB_STR "Send HNB-REGISTER REQUEST")
749{
750 hnb_send_register_req(&g_hnb_test);
751
752 return CMD_SUCCESS;
753}
754
755DEFUN(hnb_deregister, hnb_deregister_cmd,
756 "hnbap hnb deregister", HNBAP_STR HNB_STR "Send HNB-DEREGISTER REQUEST")
757{
758 hnb_send_deregister_req(&g_hnb_test);
759
760 return CMD_SUCCESS;
761}
762
763DEFUN(ue_register, ue_register_cmd,
764 "hnbap ue register IMSI", HNBAP_STR UE_STR "Send UE-REGISTER REQUEST")
765{
766 hnb_test_ue_register_tx(&g_hnb_test, argv[0]);
767
768 return CMD_SUCCESS;
769}
770
771DEFUN(asn_dbg, asn_dbg_cmd,
772 "asn-debug (1|0)", "Enable or disabel libasn1c debugging")
773{
774 asn_debug = atoi(argv[0]);
775
776 return CMD_SUCCESS;
777}
778
779DEFUN(ranap_reset, ranap_reset_cmd,
780 "ranap reset (cs|ps)", RANAP_STR "Send RANAP RESET\n" CSPS_STR)
781{
782 int is_ps = 0;
783 struct msgb *msg, *rua;
784
785 RANAP_Cause_t cause = {
786 .present = RANAP_Cause_PR_transmissionNetwork,
787 .choice.transmissionNetwork = RANAP_CauseTransmissionNetwork_signalling_transport_resource_failure,
788 };
789
790 if (!strcmp(argv[0], "ps"))
791 is_ps = 1;
792
793 msg = ranap_new_msg_reset(is_ps, &cause);
794 rua = rua_new_udt(msg);
795 //msgb_free(msg);
796 osmo_wqueue_enqueue(&g_hnb_test.wqueue, rua);
797
798 return CMD_SUCCESS;
799}
800
801
802enum my_vty_nodes {
803 CHAN_NODE = _LAST_OSMOVTY_NODE,
804};
805
806static struct cmd_node chan_node = {
807 CHAN_NODE,
808 "%s(chan)> ",
809 1,
810};
811
812
Harald Weltec3851222015-12-24 15:41:21 +0100813static struct msgb *gen_initue_lu(int is_ps, uint32_t conn_id, const char *imsi)
814{
Neels Hofmeyr5c1cc8c2016-02-29 09:28:48 +0100815 uint8_t lu[] = { GSM48_PDISC_MM, GSM48_MT_MM_LOC_UPD_REQUEST,
816 0x70, 0x62, 0xf2, 0x30, 0xff, 0xf3, 0x57,
Neels Hofmeyr32828702016-01-14 13:06:47 +0100817 /* len, IMSI/type, IMSI-------------------------------- */
Harald Weltec3851222015-12-24 15:41:21 +0100818 0x08, 0x29, 0x26, 0x24, 0x10, 0x32, 0x54, 0x76, 0x98,
819 0x33, 0x03, 0x57, 0x18 , 0xb2 };
820 uint8_t plmn_id[] = { 0x09, 0x01, 0x99 };
821 RANAP_GlobalRNC_ID_t rnc_id = {
822 .rNC_ID = 23,
823 .pLMNidentity.buf = plmn_id,
824 .pLMNidentity.size = sizeof(plmn_id),
825 };
Harald Weltec3851222015-12-24 15:41:21 +0100826
827 /* FIXME: patch imsi */
Neels Hofmeyr7b811282016-01-14 13:05:24 +0100828 /* Note: the Mobile Identitiy IE's IMSI data has the identity type and
829 * an even/odd indicator bit encoded in the first octet. So the first
830 * octet looks like this:
831 *
832 * 8 7 6 5 | 4 | 3 2 1
833 * IMSI-digit | even/odd | type
834 *
835 * followed by the remaining IMSI digits.
836 * If digit count is even (bit 4 == 0), that first high-nibble is 0xf.
837 * (derived from Iu pcap Location Update Request msg and TS 25.413)
838 *
839 * TODO I'm only 90% sure about this
840 */
Harald Weltec3851222015-12-24 15:41:21 +0100841
Neels Hofmeyr6a62e542016-01-15 03:07:45 +0100842 return ranap_new_msg_initial_ue(conn_id, is_ps, &rnc_id, lu, sizeof(lu));
Harald Weltec3851222015-12-24 15:41:21 +0100843}
844
845DEFUN(chan, chan_cmd,
846 "channel (cs|ps) lu imsi IMSI",
847 "Open a new Signalling Connection\n"
848 "To Circuit-Switched CN\n"
849 "To Packet-Switched CN\n"
850 "Performing a Location Update\n"
851 )
852{
853 struct hnbtest_chan *chan;
854 struct msgb *msg, *rua;
Daniel Willmann85927162016-01-14 15:36:49 +0100855 static uint16_t conn_id = 42;
Harald Weltec3851222015-12-24 15:41:21 +0100856
857 chan = talloc_zero(tall_hnb_ctx, struct hnbtest_chan);
858 if (!strcmp(argv[0], "ps"))
859 chan->is_ps = 1;
860 chan->imsi = talloc_strdup(chan, argv[1]);
Daniel Willmann85927162016-01-14 15:36:49 +0100861 chan->conn_id = conn_id;
862 conn_id++;
Harald Weltec3851222015-12-24 15:41:21 +0100863
864 msg = gen_initue_lu(chan->is_ps, chan->conn_id, chan->imsi);
865 rua = rua_new_conn(chan->is_ps, chan->conn_id, msg);
866
867 osmo_wqueue_enqueue(&g_hnb_test.wqueue, rua);
868
869 vty->index = chan;
870 vty->node = CHAN_NODE;
871
Neels Hofmeyr860a1292016-02-18 23:03:15 +0100872 if (!chan->is_ps)
873 g_hnb_test.cs.chan = chan;
874
875
Harald Weltec3851222015-12-24 15:41:21 +0100876 return CMD_SUCCESS;
877}
878
879static void hnbtest_vty_init(void)
880{
881 install_element_ve(&asn_dbg_cmd);
882 install_element_ve(&hnb_register_cmd);
883 install_element_ve(&hnb_deregister_cmd);
884 install_element_ve(&ue_register_cmd);
885 install_element_ve(&ranap_reset_cmd);
886 install_element_ve(&chan_cmd);
887
888 install_node(&chan_node, NULL);
889 vty_install_default(CHAN_NODE);
890}
891
Daniel Willmann141a0ba2015-12-17 18:03:52 +0100892static void handle_options(int argc, char **argv)
893{
894 while (1) {
895 int idx = 0, c;
896 static const struct option long_options[] = {
897 { "ues", 1, 0, 'u' },
Neels Hofmeyr5f9be1e2016-02-29 13:33:44 +0100898 { "gw-addr", 1, 0, 'g' },
Daniel Willmann141a0ba2015-12-17 18:03:52 +0100899 { 0, 0, 0, 0 },
900 };
901
Neels Hofmeyr5f9be1e2016-02-29 13:33:44 +0100902 c = getopt_long(argc, argv, "u:g:", long_options, &idx);
Daniel Willmann141a0ba2015-12-17 18:03:52 +0100903
904 if (c == -1)
905 break;
906
907 switch (c) {
908 case 'u':
909 g_hnb_test.ues = atoi(optarg);
910 break;
Neels Hofmeyr5f9be1e2016-02-29 13:33:44 +0100911 case 'g':
912 g_hnb_test.gw_addr = optarg;
913 break;
Daniel Willmann141a0ba2015-12-17 18:03:52 +0100914 }
915 }
916}
917
Harald Weltec3851222015-12-24 15:41:21 +0100918int main(int argc, char **argv)
Daniel Willmann97374c02015-12-03 09:37:58 +0100919{
920 int rc;
921
Harald Welte87ffeb92015-12-25 15:34:22 +0100922 test_common_init();
Daniel Willmann97374c02015-12-03 09:37:58 +0100923
Harald Welte87ffeb92015-12-25 15:34:22 +0100924 tall_hnb_ctx = talloc_named_const(NULL, 0, "hnb_context");
Daniel Willmann97374c02015-12-03 09:37:58 +0100925
926 vty_init(&vty_info);
Harald Weltec3851222015-12-24 15:41:21 +0100927 hnbtest_vty_init();
928
Neels Hofmeyra0d21472016-02-24 20:50:31 +0100929 printf("VTY at %s %d\n", vty_get_bind_addr(), 2324);
930 rc = telnet_init_dynif(NULL, NULL, vty_get_bind_addr(), 2324);
Harald Weltec3851222015-12-24 15:41:21 +0100931 if (rc < 0) {
932 perror("Error binding VTY port");
933 exit(1);
934 }
Daniel Willmann97374c02015-12-03 09:37:58 +0100935
Daniel Willmann141a0ba2015-12-17 18:03:52 +0100936 handle_options(argc, argv);
937
Daniel Willmann97374c02015-12-03 09:37:58 +0100938 osmo_wqueue_init(&g_hnb_test.wqueue, 16);
939 g_hnb_test.wqueue.bfd.data = &g_hnb_test;
940 g_hnb_test.wqueue.read_cb = hnb_read_cb;
941 g_hnb_test.wqueue.write_cb = hnb_write_cb;
942
943 rc = osmo_sock_init_ofd(&g_hnb_test.wqueue.bfd, AF_INET, SOCK_STREAM,
Neels Hofmeyr5f9be1e2016-02-29 13:33:44 +0100944 IPPROTO_SCTP, g_hnb_test.gw_addr,
Daniel Willmann97374c02015-12-03 09:37:58 +0100945 g_hnb_test.gw_port, OSMO_SOCK_F_CONNECT);
946 if (rc < 0) {
947 perror("Error connecting to Iuh port");
948 exit(1);
949 }
Daniel Willmann4abdee02015-12-09 17:57:32 +0100950 sctp_sock_init(g_hnb_test.wqueue.bfd.fd);
Daniel Willmann97374c02015-12-03 09:37:58 +0100951
Harald Weltec3851222015-12-24 15:41:21 +0100952#if 0
953 /* some hard-coded message generation. Doesn't make sense from
954 * a protocol point of view but enables to look at the encoded
955 * results in wireshark for manual verification */
956 {
957 struct msgb *msg, *rua;
958 const uint8_t nas[] = { 0, 1, 2, 3 };
959 const uint8_t ik[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
960
961 msg = ranap_new_msg_dt(0, nas, sizeof(nas));
962 rua = rua_new_udt(msg);
963 osmo_wqueue_enqueue(&g_hnb_test.wqueue, rua);
964
965 msg = ranap_new_msg_sec_mod_cmd(ik, ik);
966 rua = rua_new_udt(msg);
967 osmo_wqueue_enqueue(&g_hnb_test.wqueue, rua);
968
969 msg = ranap_new_msg_iu_rel_cmd()
970 rua = rua_new_udt(msg);
971 osmo_wqueue_enqueue(&g_hnb_test.wqueue, rua);
972
973 msg = ranap_new_msg_paging_cmd("901990123456789", NULL, 0, 0);
974 rua = rua_new_udt(msg);
975 osmo_wqueue_enqueue(&g_hnb_test.wqueue, rua);
976
977 msg = ranap_new_msg_rab_assign_voice(1, 0x01020304, 0x1020);
978 rua = rua_new_udt(msg);
979 osmo_wqueue_enqueue(&g_hnb_test.wqueue, rua);
980
981 msg = ranap_new_msg_rab_assign_data(2, 0x01020304, 0x11223344);
982 rua = rua_new_udt(msg);
983 osmo_wqueue_enqueue(&g_hnb_test.wqueue, rua);
984 }
985#endif
Daniel Willmann4aeef6c2015-12-03 17:02:13 +0100986
Daniel Willmann97374c02015-12-03 09:37:58 +0100987 while (1) {
988 rc = osmo_select_main(0);
989 if (rc < 0)
990 exit(3);
991 }
992
993 /* not reached */
994 exit(0);
995}