blob: 95a565e5ae888beccfa1392a1c36ee82f5b4168d [file] [log] [blame]
Harald Welte936f6722016-05-03 18:51:18 +02001/* (C) 2016 by Harald Welte <laforge@gnumonks.org>
2 *
3 * All Rights Reserved
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Affero General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
Harald Welteaabae9e2016-04-28 12:48:14 +020020#include <signal.h>
Harald Weltee687be52016-05-03 18:49:27 +020021#include <errno.h>
Maxea8b0d42017-02-14 16:53:04 +010022#include <stdbool.h>
Neels Hofmeyr7f9491f2017-01-30 13:30:47 +010023#include <getopt.h>
24
Harald Weltee72cf552016-04-28 07:18:49 +020025#include <osmocom/core/msgb.h>
26#include <osmocom/core/logging.h>
27#include <osmocom/core/application.h>
28#include <osmocom/gsm/gsup.h>
Max2fc63a62016-12-20 16:49:20 +010029#include <osmocom/gsm/apn.h>
Neels Hofmeyr627de842016-12-19 13:16:06 +010030#include <osmocom/gsm/gsm48_ie.h>
Neels Hofmeyr7685a782017-01-30 23:30:26 +010031#include <osmocom/vty/vty.h>
32#include <osmocom/vty/command.h>
33#include <osmocom/vty/telnet_interface.h>
34#include <osmocom/vty/ports.h>
Max372868b2017-03-02 12:12:00 +010035#include <osmocom/ctrl/control_vty.h>
Harald Weltee72cf552016-04-28 07:18:49 +020036
37#include "db.h"
Maxd4bebbd2017-03-02 12:00:19 +010038#include "hlr.h"
Max372868b2017-03-02 12:12:00 +010039#include "ctrl.h"
Harald Weltee72cf552016-04-28 07:18:49 +020040#include "logging.h"
41#include "gsup_server.h"
Harald Weltee687be52016-05-03 18:49:27 +020042#include "gsup_router.h"
Harald Weltee72cf552016-04-28 07:18:49 +020043#include "rand.h"
Maxea8b0d42017-02-14 16:53:04 +010044#include "luop.h"
Neels Hofmeyr7685a782017-01-30 23:30:26 +010045#include "hlr_vty.h"
Harald Weltee72cf552016-04-28 07:18:49 +020046
Maxd4bebbd2017-03-02 12:00:19 +010047static struct hlr *g_hlr;
Harald Weltee72cf552016-04-28 07:18:49 +020048
Harald Weltee687be52016-05-03 18:49:27 +020049/***********************************************************************
50 * Send Auth Info handling
51 ***********************************************************************/
52
Harald Weltee72cf552016-04-28 07:18:49 +020053/* process an incoming SAI request */
54static int rx_send_auth_info(struct osmo_gsup_conn *conn,
Maxd4bebbd2017-03-02 12:00:19 +010055 const struct osmo_gsup_message *gsup,
56 struct db_context *dbc)
Harald Weltee72cf552016-04-28 07:18:49 +020057{
58 struct osmo_gsup_message gsup_out;
59 struct msgb *msg_out;
60 int rc;
61
62 /* initialize return message structure */
63 memset(&gsup_out, 0, sizeof(gsup_out));
Harald Weltee72cf552016-04-28 07:18:49 +020064 memcpy(&gsup_out.imsi, &gsup->imsi, sizeof(gsup_out.imsi));
65
Maxd4bebbd2017-03-02 12:00:19 +010066 rc = db_get_auc(dbc, gsup->imsi, gsup_out.auth_vectors,
Harald Weltee72cf552016-04-28 07:18:49 +020067 ARRAY_SIZE(gsup_out.auth_vectors),
Harald Welte9be0d2f2016-06-10 17:34:02 +020068 gsup->rand, gsup->auts);
Harald Weltecfc752b2016-05-05 16:38:14 +020069 if (rc < 0) {
Harald Weltee72cf552016-04-28 07:18:49 +020070 gsup_out.message_type = OSMO_GSUP_MSGT_SEND_AUTH_INFO_ERROR;
Harald Weltecfc752b2016-05-05 16:38:14 +020071 gsup_out.cause = GMM_CAUSE_NET_FAIL;
72 } else if (rc == 0) {
73 gsup_out.message_type = OSMO_GSUP_MSGT_SEND_AUTH_INFO_ERROR;
74 gsup_out.cause = GMM_CAUSE_IMSI_UNKNOWN;
Harald Welte15db8262016-05-05 16:50:39 +020075 } else {
76 gsup_out.message_type = OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT;
77 gsup_out.num_auth_vectors = rc;
Harald Weltee72cf552016-04-28 07:18:49 +020078 }
79
Harald Weltee687be52016-05-03 18:49:27 +020080 msg_out = msgb_alloc_headroom(1024+16, 16, "GSUP AUC response");
Harald Weltee72cf552016-04-28 07:18:49 +020081 osmo_gsup_encode(msg_out, &gsup_out);
82 return osmo_gsup_conn_send(conn, msg_out);
83}
84
Harald Weltee687be52016-05-03 18:49:27 +020085/***********************************************************************
86 * LU Operation State / Structure
87 ***********************************************************************/
88
89static LLIST_HEAD(g_lu_ops);
90
Harald Weltee687be52016-05-03 18:49:27 +020091/*! Receive Cancel Location Result from old VLR/SGSN */
92void lu_op_rx_cancel_old_ack(struct lu_operation *luop,
Maxea8b0d42017-02-14 16:53:04 +010093 const struct osmo_gsup_message *gsup)
Harald Weltee687be52016-05-03 18:49:27 +020094{
95 OSMO_ASSERT(luop->state == LU_S_CANCEL_SENT);
96 /* FIXME: Check for spoofing */
97
98 osmo_timer_del(&luop->timer);
99
100 /* FIXME */
101
102 lu_op_tx_insert_subscr_data(luop);
103}
104
Harald Weltee687be52016-05-03 18:49:27 +0200105/*! Receive Insert Subscriber Data Result from new VLR/SGSN */
106static void lu_op_rx_insert_subscr_data_ack(struct lu_operation *luop,
107 const struct osmo_gsup_message *gsup)
108{
109 OSMO_ASSERT(luop->state == LU_S_ISD_SENT);
110 /* FIXME: Check for spoofing */
111
112 osmo_timer_del(&luop->timer);
113
114 /* Subscriber_Present_HLR */
115 /* CS only: Check_SS_required? -> MAP-FW-CHECK_SS_IND.req */
116
117 /* Send final ACK towards inquiring VLR/SGSN */
118 lu_op_tx_ack(luop);
119}
120
121/*! Receive GSUP message for given \ref lu_operation */
122void lu_op_rx_gsup(struct lu_operation *luop,
123 const struct osmo_gsup_message *gsup)
124{
125 switch (gsup->message_type) {
126 case OSMO_GSUP_MSGT_INSERT_DATA_ERROR:
127 /* FIXME */
128 break;
129 case OSMO_GSUP_MSGT_INSERT_DATA_RESULT:
130 lu_op_rx_insert_subscr_data_ack(luop, gsup);
131 break;
132 case OSMO_GSUP_MSGT_LOCATION_CANCEL_ERROR:
133 /* FIXME */
134 break;
135 case OSMO_GSUP_MSGT_LOCATION_CANCEL_RESULT:
136 lu_op_rx_cancel_old_ack(luop, gsup);
137 break;
138 default:
139 LOGP(DMAIN, LOGL_ERROR, "Unhandled GSUP msg_type 0x%02x\n",
140 gsup->message_type);
141 break;
142 }
143}
144
Harald Weltee687be52016-05-03 18:49:27 +0200145/*! Receive Update Location Request, creates new \ref lu_operation */
146static int rx_upd_loc_req(struct osmo_gsup_conn *conn,
147 const struct osmo_gsup_message *gsup)
148{
Maxea8b0d42017-02-14 16:53:04 +0100149 struct lu_operation *luop = lu_op_alloc_conn(conn);
150 if (!luop) {
Harald Weltee687be52016-05-03 18:49:27 +0200151 LOGP(DMAIN, LOGL_ERROR, "LU REQ from conn without addr?\n");
Maxea8b0d42017-02-14 16:53:04 +0100152 return -EINVAL;
Harald Weltee687be52016-05-03 18:49:27 +0200153 }
154
Harald Weltee687be52016-05-03 18:49:27 +0200155 lu_op_statechg(luop, LU_S_LU_RECEIVED);
Maxea8b0d42017-02-14 16:53:04 +0100156
Harald Weltee687be52016-05-03 18:49:27 +0200157 if (gsup->cn_domain == OSMO_GSUP_CN_DOMAIN_PS)
158 luop->is_ps = true;
159 llist_add(&luop->list, &g_lu_ops);
160
161 /* Roughly follwing "Process Update_Location_HLR" of TS 09.02 */
162
163 /* check if subscriber is known at all */
Maxd4bebbd2017-03-02 12:00:19 +0100164 if (!lu_op_fill_subscr(luop, g_hlr->dbc, gsup->imsi)) {
Harald Weltee687be52016-05-03 18:49:27 +0200165 /* Send Error back: Subscriber Unknown in HLR */
166 strcpy(luop->subscr.imsi, gsup->imsi);
167 lu_op_tx_error(luop, GMM_CAUSE_IMSI_UNKNOWN);
168 return 0;
169 }
170
Harald Welte99909272016-05-05 18:24:15 +0200171 /* Check if subscriber is generally permitted on CS or PS
172 * service (as requested) */
Maxea8b0d42017-02-14 16:53:04 +0100173 if (!luop->is_ps && !luop->subscr.nam_cs) {
Harald Weltee687be52016-05-03 18:49:27 +0200174 lu_op_tx_error(luop, GMM_CAUSE_PLMN_NOTALLOWED);
175 return 0;
Maxea8b0d42017-02-14 16:53:04 +0100176 } else if (luop->is_ps && !luop->subscr.nam_ps) {
Harald Weltee687be52016-05-03 18:49:27 +0200177 lu_op_tx_error(luop, GMM_CAUSE_GPRS_NOTALLOWED);
178 return 0;
179 }
180
181 /* TODO: Set subscriber tracing = deactive in VLR/SGSN */
182
183#if 0
184 /* Cancel in old VLR/SGSN, if new VLR/SGSN differs from old */
185 if (luop->is_ps == false &&
186 strcmp(subscr->vlr_number, vlr_number)) {
Harald Weltee687be52016-05-03 18:49:27 +0200187 lu_op_tx_cancel_old(luop);
188 } else if (luop->is_ps == true &&
189 strcmp(subscr->sgsn_number, sgsn_number)) {
Harald Weltee687be52016-05-03 18:49:27 +0200190 lu_op_tx_cancel_old(luop);
191 } else
192#endif
193 {
194 /* TODO: Subscriber allowed to roam in PLMN? */
195 /* TODO: Update RoutingInfo */
196 /* TODO: Reset Flag MS Purged (cs/ps) */
197 /* TODO: Control_Tracing_HLR / Control_Tracing_HLR_with_SGSN */
198 lu_op_tx_insert_subscr_data(luop);
199 }
200 return 0;
201}
202
Harald Welteb18f0e02016-05-05 21:03:03 +0200203static int rx_purge_ms_req(struct osmo_gsup_conn *conn,
204 const struct osmo_gsup_message *gsup)
205{
206 struct osmo_gsup_message gsup_reply = {0};
207 struct msgb *msg_out;
208 bool is_ps = false;
209 int rc;
210
211 LOGP(DAUC, LOGL_INFO, "%s: Purge MS (%s)\n", gsup->imsi,
212 is_ps ? "PS" : "CS");
213
214 memcpy(gsup_reply.imsi, gsup->imsi, sizeof(gsup_reply.imsi));
215
216 if (gsup->cn_domain == OSMO_GSUP_CN_DOMAIN_PS)
217 is_ps = true;
218
219 /* FIXME: check if the VLR that sends the purge is the same that
220 * we have on record. Only update if yes */
221
222 /* Perform the actual update of the DB */
Maxd4bebbd2017-03-02 12:00:19 +0100223 rc = db_subscr_purge(g_hlr->dbc, gsup->imsi, is_ps);
Harald Welteb18f0e02016-05-05 21:03:03 +0200224
225 if (rc == 1)
226 gsup_reply.message_type = OSMO_GSUP_MSGT_PURGE_MS_RESULT;
227 else if (rc == 0) {
228 gsup_reply.message_type = OSMO_GSUP_MSGT_PURGE_MS_ERROR;
229 gsup_reply.cause = GMM_CAUSE_IMSI_UNKNOWN;
230 } else {
231 gsup_reply.message_type = OSMO_GSUP_MSGT_PURGE_MS_ERROR;
232 gsup_reply.cause = GMM_CAUSE_NET_FAIL;
233 }
234
235 msg_out = msgb_alloc_headroom(1024+16, 16, "GSUP AUC response");
236 osmo_gsup_encode(msg_out, &gsup_reply);
237 return osmo_gsup_conn_send(conn, msg_out);
238}
239
Harald Weltee72cf552016-04-28 07:18:49 +0200240static int read_cb(struct osmo_gsup_conn *conn, struct msgb *msg)
241{
242 static struct osmo_gsup_message gsup;
243 int rc;
244
Harald Weltee687be52016-05-03 18:49:27 +0200245 rc = osmo_gsup_decode(msgb_l2(msg), msgb_l2len(msg), &gsup);
Harald Weltee72cf552016-04-28 07:18:49 +0200246 if (rc < 0) {
247 LOGP(DMAIN, LOGL_ERROR, "error in GSUP decode: %d\n", rc);
248 return rc;
249 }
250
251 switch (gsup.message_type) {
252 /* requests sent to us */
253 case OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST:
Maxd4bebbd2017-03-02 12:00:19 +0100254 rx_send_auth_info(conn, &gsup, g_hlr->dbc);
Harald Weltee72cf552016-04-28 07:18:49 +0200255 break;
256 case OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST:
Harald Weltee687be52016-05-03 18:49:27 +0200257 rx_upd_loc_req(conn, &gsup);
Harald Weltee72cf552016-04-28 07:18:49 +0200258 break;
Harald Welteb18f0e02016-05-05 21:03:03 +0200259 case OSMO_GSUP_MSGT_PURGE_MS_REQUEST:
260 rx_purge_ms_req(conn, &gsup);
261 break;
Harald Weltee72cf552016-04-28 07:18:49 +0200262 /* responses to requests sent by us */
263 case OSMO_GSUP_MSGT_INSERT_DATA_ERROR:
Harald Weltee72cf552016-04-28 07:18:49 +0200264 case OSMO_GSUP_MSGT_INSERT_DATA_RESULT:
Harald Weltee687be52016-05-03 18:49:27 +0200265 case OSMO_GSUP_MSGT_LOCATION_CANCEL_ERROR:
266 case OSMO_GSUP_MSGT_LOCATION_CANCEL_RESULT:
267 {
Maxea8b0d42017-02-14 16:53:04 +0100268 struct lu_operation *luop = lu_op_by_imsi(gsup.imsi,
269 &g_lu_ops);
Harald Weltee687be52016-05-03 18:49:27 +0200270 if (!luop) {
Maxaa0fefd2017-02-16 12:25:22 +0100271 LOGP(DMAIN, LOGL_ERROR, "GSUP message %s for "
272 "unknown IMSI %s\n",
273 osmo_gsup_message_type_name(gsup.message_type),
Harald Weltee687be52016-05-03 18:49:27 +0200274 gsup.imsi);
275 break;
276 }
277 lu_op_rx_gsup(luop, &gsup);
278 }
Harald Weltee72cf552016-04-28 07:18:49 +0200279 break;
280 default:
Maxaa0fefd2017-02-16 12:25:22 +0100281 LOGP(DMAIN, LOGL_DEBUG, "Unhandled GSUP message type %s\n",
282 osmo_gsup_message_type_name(gsup.message_type));
Harald Weltee72cf552016-04-28 07:18:49 +0200283 break;
284 }
Harald Welte5341b5d2016-04-28 12:48:39 +0200285 msgb_free(msg);
Harald Weltee72cf552016-04-28 07:18:49 +0200286 return 0;
287}
288
Neels Hofmeyr7f9491f2017-01-30 13:30:47 +0100289static void print_usage()
290{
291 printf("Usage: osmo-hlr\n");
292}
293
294static void print_help()
295{
296 printf(" -h --help This text.\n");
Neels Hofmeyr7685a782017-01-30 23:30:26 +0100297 printf(" -c --config-file filename The config file to use.\n");
Neels Hofmeyr7f9491f2017-01-30 13:30:47 +0100298 printf(" -l --database db-name The database to use.\n");
299 printf(" -d option --debug=DRLL:DCC:DMM:DRR:DRSL:DNM Enable debugging.\n");
300 printf(" -D --daemonize Fork the process into a background daemon.\n");
301 printf(" -s --disable-color Do not print ANSI colors in the log\n");
302 printf(" -T --timestamp Prefix every log line with a timestamp.\n");
303 printf(" -e --log-level number Set a global loglevel.\n");
Neels Hofmeyr7685a782017-01-30 23:30:26 +0100304 printf(" -V --version Print the version of OsmoHLR.\n");
Neels Hofmeyr7f9491f2017-01-30 13:30:47 +0100305}
306
307static struct {
Neels Hofmeyr7685a782017-01-30 23:30:26 +0100308 const char *config_file;
Neels Hofmeyr7f9491f2017-01-30 13:30:47 +0100309 const char *db_file;
310 bool daemonize;
311} cmdline_opts = {
Neels Hofmeyr7685a782017-01-30 23:30:26 +0100312 .config_file = "osmo-hlr.cfg",
Neels Hofmeyr7f9491f2017-01-30 13:30:47 +0100313 .db_file = "hlr.db",
314 .daemonize = false,
315};
316
317static void handle_options(int argc, char **argv)
318{
319 while (1) {
320 int option_index = 0, c;
321 static struct option long_options[] = {
322 {"help", 0, 0, 'h'},
Neels Hofmeyr7685a782017-01-30 23:30:26 +0100323 {"config-file", 1, 0, 'c'},
Neels Hofmeyr7f9491f2017-01-30 13:30:47 +0100324 {"database", 1, 0, 'l'},
325 {"debug", 1, 0, 'd'},
326 {"daemonize", 0, 0, 'D'},
327 {"disable-color", 0, 0, 's'},
328 {"log-level", 1, 0, 'e'},
329 {"timestamp", 0, 0, 'T'},
Neels Hofmeyr7685a782017-01-30 23:30:26 +0100330 {"version", 0, 0, 'V' },
Neels Hofmeyr7f9491f2017-01-30 13:30:47 +0100331 {0, 0, 0, 0}
332 };
333
Neels Hofmeyr7685a782017-01-30 23:30:26 +0100334 c = getopt_long(argc, argv, "hc:l:d:Dse:TV",
Neels Hofmeyr7f9491f2017-01-30 13:30:47 +0100335 long_options, &option_index);
336 if (c == -1)
337 break;
338
339 switch (c) {
340 case 'h':
341 print_usage();
342 print_help();
343 exit(0);
Neels Hofmeyr7685a782017-01-30 23:30:26 +0100344 case 'c':
345 cmdline_opts.config_file = optarg;
346 break;
Neels Hofmeyr7f9491f2017-01-30 13:30:47 +0100347 case 'l':
348 cmdline_opts.db_file = optarg;
349 break;
350 case 'd':
351 log_parse_category_mask(osmo_stderr_target, optarg);
352 break;
353 case 'D':
354 cmdline_opts.daemonize = 1;
355 break;
356 case 's':
357 log_set_use_color(osmo_stderr_target, 0);
358 break;
359 case 'e':
360 log_set_log_level(osmo_stderr_target, atoi(optarg));
361 break;
362 case 'T':
363 log_set_print_timestamp(osmo_stderr_target, 1);
364 break;
Neels Hofmeyr7685a782017-01-30 23:30:26 +0100365 case 'V':
366 print_version(1);
367 exit(0);
368 break;
Neels Hofmeyr7f9491f2017-01-30 13:30:47 +0100369 default:
370 /* catch unknown options *as well as* missing arguments. */
371 fprintf(stderr, "Error in command line options. Exiting.\n");
372 exit(-1);
373 break;
374 }
375 }
376}
377
Neels Hofmeyrca43e302017-01-30 13:18:23 +0100378static void *hlr_ctx = NULL;
Harald Welteaabae9e2016-04-28 12:48:14 +0200379
380static void signal_hdlr(int signal)
381{
382 switch (signal) {
383 case SIGINT:
384 LOGP(DMAIN, LOGL_NOTICE, "Terminating due to SIGINT\n");
Maxd4bebbd2017-03-02 12:00:19 +0100385 osmo_gsup_server_destroy(g_hlr->gs);
386 db_close(g_hlr->dbc);
Harald Welteaabae9e2016-04-28 12:48:14 +0200387 log_fini();
Neels Hofmeyrca43e302017-01-30 13:18:23 +0100388 talloc_report_full(hlr_ctx, stderr);
Harald Welteaabae9e2016-04-28 12:48:14 +0200389 exit(0);
390 break;
391 case SIGUSR1:
392 LOGP(DMAIN, LOGL_DEBUG, "Talloc Report due to SIGUSR1\n");
Neels Hofmeyrca43e302017-01-30 13:18:23 +0100393 talloc_report_full(hlr_ctx, stderr);
Harald Welteaabae9e2016-04-28 12:48:14 +0200394 break;
395 }
396}
Harald Weltee72cf552016-04-28 07:18:49 +0200397
Max372868b2017-03-02 12:12:00 +0100398static const char vlr_copyright[] =
399 "Copyright (C) 2016, 2017 by Harald Welte, sysmocom s.f.m.c. GmbH\r\n"
400 "License AGPLv3+: GNU AGPL version 3 or later <http://gnu.org/licenses/agpl-3.0.html>\r\n"
401 "This is free software: you are free to change and redistribute it.\r\n"
402 "There is NO WARRANTY, to the extent permitted by law.\r\n";
403
Neels Hofmeyr7685a782017-01-30 23:30:26 +0100404static struct vty_app_info vty_info = {
405 .name = "OsmoHLR",
406 .version = PACKAGE_VERSION,
Max372868b2017-03-02 12:12:00 +0100407 .copyright = vlr_copyright,
Neels Hofmeyr7685a782017-01-30 23:30:26 +0100408 .is_config_node = hlr_vty_is_config_node,
409};
410
Harald Weltee72cf552016-04-28 07:18:49 +0200411int main(int argc, char **argv)
412{
Harald Weltee72cf552016-04-28 07:18:49 +0200413 int rc;
414
Neels Hofmeyrca43e302017-01-30 13:18:23 +0100415 hlr_ctx = talloc_named_const(NULL, 1, "OsmoHLR");
416 msgb_talloc_ctx_init(hlr_ctx, 0);
Harald Welteaabae9e2016-04-28 12:48:14 +0200417
Maxd4bebbd2017-03-02 12:00:19 +0100418 g_hlr = talloc_zero(hlr_ctx, struct hlr);
419
Harald Weltee72cf552016-04-28 07:18:49 +0200420 rc = osmo_init_logging(&hlr_log_info);
421 if (rc < 0) {
422 fprintf(stderr, "Error initializing logging\n");
423 exit(1);
424 }
Neels Hofmeyr7f9491f2017-01-30 13:30:47 +0100425
Neels Hofmeyr7685a782017-01-30 23:30:26 +0100426 vty_init(&vty_info);
Max372868b2017-03-02 12:12:00 +0100427 ctrl_vty_init(hlr_ctx);
Neels Hofmeyr7f9491f2017-01-30 13:30:47 +0100428 handle_options(argc, argv);
Neels Hofmeyr7685a782017-01-30 23:30:26 +0100429 hlr_vty_init(&hlr_log_info);
430
431 rc = vty_read_config_file(cmdline_opts.config_file, NULL);
432 if (rc < 0) {
433 LOGP(DMAIN, LOGL_FATAL,
434 "Failed to parse the config file: '%s'\n",
435 cmdline_opts.config_file);
436 return rc;
437 }
438
439 /* start telnet after reading config for vty_get_bind_addr() */
440 rc = telnet_init_dynif(hlr_ctx, NULL, vty_get_bind_addr(),
441 OSMO_VTY_PORT_HLR);
442 if (rc < 0)
443 return rc;
Neels Hofmeyr7f9491f2017-01-30 13:30:47 +0100444
Harald Weltee72cf552016-04-28 07:18:49 +0200445 LOGP(DMAIN, LOGL_NOTICE, "hlr starting\n");
446
447 rc = rand_init();
448 if (rc < 0) {
449 LOGP(DMAIN, LOGL_FATAL, "Error initializing random source\n");
450 exit(1);
451 }
452
Maxd4bebbd2017-03-02 12:00:19 +0100453 g_hlr->dbc = db_open(hlr_ctx, cmdline_opts.db_file);
454 if (!g_hlr->dbc) {
Harald Weltee72cf552016-04-28 07:18:49 +0200455 LOGP(DMAIN, LOGL_FATAL, "Error opening database\n");
456 exit(1);
457 }
458
Maxd4bebbd2017-03-02 12:00:19 +0100459 g_hlr->gs = osmo_gsup_server_create(hlr_ctx, NULL, 2222, read_cb);
460 if (!g_hlr->gs) {
Harald Weltee72cf552016-04-28 07:18:49 +0200461 LOGP(DMAIN, LOGL_FATAL, "Error starting GSUP server\n");
462 exit(1);
463 }
464
Max372868b2017-03-02 12:12:00 +0100465 g_hlr->ctrl_bind_addr = ctrl_vty_get_bind_addr();
466 g_hlr->ctrl = hlr_controlif_setup(g_hlr, g_hlr->gs);
467
Harald Welteaabae9e2016-04-28 12:48:14 +0200468 osmo_init_ignore_signals();
469 signal(SIGINT, &signal_hdlr);
470 signal(SIGUSR1, &signal_hdlr);
471
Neels Hofmeyr7f9491f2017-01-30 13:30:47 +0100472 if (cmdline_opts.daemonize) {
473 rc = osmo_daemonize();
474 if (rc < 0) {
475 perror("Error during daemonize");
476 exit(1);
477 }
478 }
Harald Welteaabae9e2016-04-28 12:48:14 +0200479
Harald Weltee72cf552016-04-28 07:18:49 +0200480 while (1) {
481 osmo_select_main(0);
482 }
483
Maxd4bebbd2017-03-02 12:00:19 +0100484 db_close(g_hlr->dbc);
Harald Weltee72cf552016-04-28 07:18:49 +0200485
486 log_fini();
487
488 exit(0);
489}