neels has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/osmo-hnbgw/+/32620 )


Change subject: move main() to separate file
......................................................................

move main() to separate file

Conform to recent osmocom practice by having an osmo_hnbgw_main.c file
for main() and its immediate infrastructure.

Prepares for adding a non-installed libhnbgw.la -- which must not
contain a main() function -- so that linking regression tests is easy.

Separating to a new file seems appropriate because hnbgw.c has gathered
a bunch of stuff that is not strictly main() related / might be useful
to access in a C test.

Change-Id: I5f26a6b68f0d380617d73371f40f3b9055cac362
---
M include/osmocom/hnbgw/hnbgw.h
M src/osmo-hnbgw/Makefile.am
M src/osmo-hnbgw/hnbgw.c
A src/osmo-hnbgw/osmo_hnbgw_main.c
4 files changed, 417 insertions(+), 379 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-hnbgw refs/changes/20/32620/1

diff --git a/include/osmocom/hnbgw/hnbgw.h b/include/osmocom/hnbgw/hnbgw.h
index 954a356..e3ec38b 100644
--- a/include/osmocom/hnbgw/hnbgw.h
+++ b/include/osmocom/hnbgw/hnbgw.h
@@ -23,6 +23,9 @@
        DCN,
 };

+extern const struct log_info hnbgw_log_info;
+extern struct vty_app_info hnbgw_vty_info;
+
 #define LOGHNB(HNB_CTX, ss, lvl, fmt, args ...) \
        LOGP(ss, lvl, "(%s) " fmt, hnb_context_name(HNB_CTX), ## args)

@@ -171,7 +174,13 @@
 extern struct hnbgw *g_hnbgw;
 extern void *talloc_asn1_ctx;

-struct hnb_context *hnb_context_by_id(uint32_t cid);
+void g_hnbgw_alloc(void *ctx);
+
+int hnbgw_rua_accept_cb(struct osmo_stream_srv_link *srv, int fd);
+int hnb_ctrl_cmds_install(void);
+int hnb_ctrl_node_lookup(void *data, vector vline, int *node_type, void 
**node_data, int *i);
+int hnbgw_mgw_setup(void);
+
 struct hnb_context *hnb_context_by_identity_info(const char *identity_info);
 const char *hnb_context_name(struct hnb_context *ctx);

@@ -182,7 +191,6 @@
                                    uint32_t tmsi);
 void ue_context_free(struct ue_context *ue);

-struct hnb_context *hnb_context_alloc(struct osmo_stream_srv_link *link, int 
new_fd);
 void hnb_context_release(struct hnb_context *ctx);
 void hnb_context_release_ue_state(struct hnb_context *ctx);

diff --git a/src/osmo-hnbgw/Makefile.am b/src/osmo-hnbgw/Makefile.am
index d1179e4..de96128 100644
--- a/src/osmo-hnbgw/Makefile.am
+++ b/src/osmo-hnbgw/Makefile.am
@@ -43,6 +43,7 @@
        ranap_rab_ass.c \
        mgw_fsm.c \
        tdefs.c \
+       osmo_hnbgw_main.c \
        $(NULL)

 osmo_hnbgw_LDADD = \
diff --git a/src/osmo-hnbgw/hnbgw.c b/src/osmo-hnbgw/hnbgw.c
index bad7064..8876580 100644
--- a/src/osmo-hnbgw/hnbgw.c
+++ b/src/osmo-hnbgw/hnbgw.c
@@ -1,7 +1,7 @@
-/* main application for hnb-gw part of osmo-iuh */
+/* kitchen sink for OsmoHNBGW implementation */

 /* (C) 2015 by Harald Welte <lafo...@gnumonks.org>
- * (C) 2016 by sysmocom s.f.m.c. GmbH <i...@sysmocom.de>
+ * (C) 2016-2023 by sysmocom s.f.m.c. GmbH <i...@sysmocom.de>
  * All Rights Reserved
  *
  * This program is free software; you can redistribute it and/or modify
@@ -19,49 +19,14 @@
  *
  */

-#include "config.h"
-
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <getopt.h>
-#include <errno.h>
-#include <signal.h>
-#include <stdbool.h>
-
-#include <sys/types.h>
-#include <sys/socket.h>
 #include <netinet/in.h>
 #include <netinet/sctp.h>
-#include <arpa/inet.h>

-#include <osmocom/core/application.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/select.h>
-#include <osmocom/core/logging.h>
-#include <osmocom/core/socket.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/write_queue.h>
-#include <osmocom/ctrl/control_if.h>
-#include <osmocom/ctrl/control_cmd.h>
-#include <osmocom/ctrl/control_vty.h>
-#include <osmocom/ctrl/ports.h>
-#include <osmocom/vty/telnet_interface.h>
-#include <osmocom/vty/logging.h>
-#include <osmocom/vty/misc.h>
-#include <osmocom/vty/command.h>
-#include <osmocom/vty/ports.h>
-
-#include <osmocom/mgcp_client/mgcp_client.h>
+#include <osmocom/vty/vty.h>

 #include <osmocom/netif/stream.h>

-#include <osmocom/ranap/ranap_common.h>
-
-#include <osmocom/sigtran/protocol/m3ua.h>
-#include <osmocom/sigtran/sccp_sap.h>
-
+#include "config.h"
 #if ENABLE_PFCP
 #include <osmocom/pfcp/pfcp_proto.h>
 #endif
@@ -69,21 +34,11 @@
 #include <osmocom/hnbgw/hnbgw.h>
 #include <osmocom/hnbgw/hnbgw_hnbap.h>
 #include <osmocom/hnbgw/hnbgw_rua.h>
-#include <osmocom/hnbgw/hnbgw_cn.h>
-#include <osmocom/hnbgw/hnbgw_pfcp.h>
 #include <osmocom/hnbgw/context_map.h>

-static const char * const osmo_hnbgw_copyright =
-       "OsmoHNBGW - Osmocom Home Node B Gateway implementation\r\n"
-       "Copyright (C) 2016 by sysmocom s.f.m.c. GmbH <i...@sysmocom.de>\r\n"
-       "Contributions by Daniel Willmann, Harald Welte, Neels Hofmeyr\r\n"
-       "License AGPLv3+: GNU AGPL version 3 or later 
<http://gnu.org/licenses/agpl-3.0.html>\r\n"
-       "This is free software: you are free to change and redistribute it.\r\n"
-       "There is NO WARRANTY, to the extent permitted by law.\r\n";
-
 struct hnbgw *g_hnbgw = NULL;

-static void g_hnbgw_alloc(void *ctx)
+void g_hnbgw_alloc(void *ctx)
 {
        OSMO_ASSERT(!g_hnbgw);
        g_hnbgw = talloc_zero(ctx, struct hnbgw);
@@ -106,7 +61,7 @@
 #endif
 }

-struct hnb_context *hnb_context_by_id(uint32_t cid)
+static struct hnb_context *hnb_context_by_id(uint32_t cid)
 {
        struct hnb_context *hnb;

@@ -164,7 +119,7 @@
        return NULL;
 }

-void ue_context_free_by_hnb(const struct hnb_context *hnb)
+static void ue_context_free_by_hnb(const struct hnb_context *hnb)
 {
        struct ue_context *ue, *tmp;

@@ -334,7 +289,7 @@
        return 0;
 }

-struct hnb_context *hnb_context_alloc(struct osmo_stream_srv_link *link, int 
new_fd)
+static struct hnb_context *hnb_context_alloc(struct osmo_stream_srv_link 
*link, int new_fd)
 {
        struct hnb_context *ctx;

@@ -416,7 +371,7 @@
 }

 /*! call-back when the listen FD has something to read */
-static int accept_cb(struct osmo_stream_srv_link *srv, int fd)
+int hnbgw_rua_accept_cb(struct osmo_stream_srv_link *srv, int fd)
 {
        struct hnb_context *ctx;

@@ -430,185 +385,6 @@
        return 0;
 }

-static const struct log_info_cat log_cat[] = {
-       [DMAIN] = {
-               .name = "DMAIN", .loglevel = LOGL_NOTICE, .enabled = 1,
-               .color = "",
-               .description = "Main program",
-       },
-       [DHNBAP] = {
-               .name = "DHNBAP", .loglevel = LOGL_NOTICE, .enabled = 1,
-               .color = "",
-               .description = "Home Node B Application Part",
-       },
-       [DRUA] = {
-               .name = "DRUA", .loglevel = LOGL_NOTICE, .enabled = 1,
-               .color = "",
-               .description = "RANAP User Adaptation",
-       },
-       [DRANAP] = {
-               .name = "DRANAP", .loglevel = LOGL_NOTICE, .enabled = 1,
-               .color = "",
-               .description = "RAN Application Part",
-       },
-       [DMGW] = {
-               .name = "DMGW", .loglevel = LOGL_NOTICE, .enabled = 1,
-               .color = "\033[1;33m",
-               .description = "Media Gateway",
-       },
-       [DHNB] = {
-               .name = "DHNB", .loglevel = LOGL_NOTICE, .enabled = 1,
-               .color = OSMO_LOGCOLOR_CYAN,
-               .description = "HNB side (via RUA)",
-       },
-       [DCN] = {
-               .name = "DCN", .loglevel = LOGL_NOTICE, .enabled = 1,
-               .color = OSMO_LOGCOLOR_DARKYELLOW,
-               .description = "Core Network side (via SCCP)",
-       },
-};
-
-static const struct log_info hnbgw_log_info = {
-       .cat = log_cat,
-       .num_cat = ARRAY_SIZE(log_cat),
-};
-
-static struct vty_app_info vty_info = {
-       .name           = "OsmoHNBGW",
-       .version        = PACKAGE_VERSION,
-       .go_parent_cb   = hnbgw_vty_go_parent,
-};
-
-static struct {
-       int daemonize;
-       const char *config_file;
-       bool log_disable_color;
-       bool log_enable_timestamp;
-       int log_level;
-       const char *log_category_mask;
-} hnbgw_cmdline_config = {
-       0,
-       "osmo-hnbgw.cfg",
-       false,
-       false,
-       0,
-       NULL,
-};
-
-static void print_usage()
-{
-       printf("Usage: osmo-hnbgw\n");
-}
-
-static void print_help()
-{
-       printf("  -h --help                  This text.\n");
-       printf("  -d option --debug=DHNBAP:DRUA:DRANAP:DMAIN  Enable 
debugging.\n");
-       printf("  -D --daemonize             Fork the process into a background 
daemon.\n");
-       printf("  -c --config-file filename  The config file to use.\n");
-       printf("  -s --disable-color\n");
-       printf("  -T --timestamp             Prefix every log line with a 
timestamp.\n");
-       printf("  -V --version               Print the version of 
OsmoHNBGW.\n");
-       printf("  -e --log-level number      Set a global loglevel.\n");
-
-       printf("\nVTY reference generation:\n");
-       printf("     --vty-ref-mode MODE        VTY reference generation mode 
(e.g. 'expert').\n");
-       printf("     --vty-ref-xml              Generate the VTY reference XML 
output and exit.\n");
-}
-
-static void handle_long_options(const char *prog_name, const int long_option)
-{
-       static int vty_ref_mode = VTY_REF_GEN_MODE_DEFAULT;
-
-       switch (long_option) {
-       case 1:
-               vty_ref_mode = get_string_value(vty_ref_gen_mode_names, optarg);
-               if (vty_ref_mode < 0) {
-                       fprintf(stderr, "%s: Unknown VTY reference generation "
-                               "mode '%s'\n", prog_name, optarg);
-                       exit(2);
-               }
-               break;
-       case 2:
-               fprintf(stderr, "Generating the VTY reference in mode '%s' 
(%s)\n",
-                       get_value_string(vty_ref_gen_mode_names, vty_ref_mode),
-                       get_value_string(vty_ref_gen_mode_desc, vty_ref_mode));
-               vty_dump_xml_ref_mode(stdout, (enum vty_ref_gen_mode) 
vty_ref_mode);
-               exit(0);
-       default:
-               fprintf(stderr, "%s: error parsing cmdline options\n", 
prog_name);
-               exit(2);
-       }
-}
-
-static void handle_options(int argc, char **argv)
-{
-       while (1) {
-               int option_index = 0, c;
-               static int long_option = 0;
-               static struct option long_options[] = {
-                       {"help", 0, 0, 'h'},
-                       {"debug", 1, 0, 'd'},
-                       {"daemonize", 0, 0, 'D'},
-                       {"config-file", 1, 0, 'c'},
-                       {"disable-color", 0, 0, 's'},
-                       {"timestamp", 0, 0, 'T'},
-                       {"version", 0, 0, 'V' },
-                       {"log-level", 1, 0, 'e'},
-                       {"vty-ref-mode", 1, &long_option, 1},
-                       {"vty-ref-xml", 0, &long_option, 2},
-                       {0, 0, 0, 0}
-               };
-
-               c = getopt_long(argc, argv, "hd:Dc:sTVe:",
-                               long_options, &option_index);
-               if (c == -1)
-                       break;
-
-               switch (c) {
-               case 0:
-                       handle_long_options(argv[0], long_option);
-                       break;
-               case 'h':
-                       print_usage();
-                       print_help();
-                       exit(0);
-               case 's':
-                       hnbgw_cmdline_config.log_disable_color = true;
-                       break;
-               case 'd':
-                       hnbgw_cmdline_config.log_category_mask = optarg;
-                       break;
-               case 'D':
-                       hnbgw_cmdline_config.daemonize = 1;
-                       break;
-               case 'c':
-                       hnbgw_cmdline_config.config_file = optarg;
-                       break;
-               case 'T':
-                       hnbgw_cmdline_config.log_enable_timestamp = true;
-                       break;
-               case 'e':
-                       hnbgw_cmdline_config.log_level = atoi(optarg);
-                       break;
-               case 'V':
-                       print_version(1);
-                       exit(0);
-                       break;
-               default:
-                       /* catch unknown options *as well as* missing 
arguments. */
-                       fprintf(stderr, "Error in command line options. 
Exiting.\n");
-                       exit(-1);
-                       break;
-               }
-       }
-
-       if (argc > optind) {
-               fprintf(stderr, "Unsupported positional arguments on command 
line\n");
-               exit(2);
-       }
-}
-
 CTRL_CMD_DEFINE_RO(hnb_info, "info");
 static int get_hnb_info(struct ctrl_cmd *cmd, void *data)
 {
@@ -627,7 +403,7 @@
        return CTRL_CMD_REPLY;
 }

-int hnb_ctrl_cmds_install()
+int hnb_ctrl_cmds_install(void)
 {
        int rc = 0;

@@ -637,7 +413,7 @@
        return rc;
 }

-static int hnb_ctrl_node_lookup(void *data, vector vline, int *node_type, void 
**node_data, int *i)
+int hnb_ctrl_node_lookup(void *data, vector vline, int *node_type, void 
**node_data, int *i)
 {
        const char *token = vector_slot(vline, *i);
        struct hnb_context *hnb;
@@ -667,7 +443,7 @@
        return 1;
 }

-static int hnbgw_mgw_setup(void)
+int hnbgw_mgw_setup(void)
 {
        struct mgcp_client *mgcp_client_single;
        unsigned int pool_members_initalized;
@@ -706,147 +482,6 @@
        return 0;
 }

-int main(int argc, char **argv)
-{
-       struct osmo_stream_srv_link *srv;
-       int rc;
-
-       talloc_enable_null_tracking();
-
-       /* g_hnbgw serves as the root talloc ctx, so allocate with NULL parent 
*/
-       g_hnbgw_alloc(NULL);
-       g_hnbgw->config.rnc_id = 23;
-
-       talloc_asn1_ctx = talloc_named_const(g_hnbgw, 1, "asn1_context");
-       msgb_talloc_ctx_init(g_hnbgw, 0);
-
-       rc = osmo_init_logging2(g_hnbgw, &hnbgw_log_info);
-       if (rc < 0)
-               exit(1);
-
-       osmo_fsm_log_timeouts(true);
-
-       rc = osmo_ss7_init();
-       if (rc < 0) {
-               LOGP(DMAIN, LOGL_FATAL, "osmo_ss7_init() failed with rc=%d\n", 
rc);
-               exit(1);
-       }
-
-       vty_info.tall_ctx = g_hnbgw;
-       vty_info.copyright = osmo_hnbgw_copyright;
-       vty_init(&vty_info);
-
-       osmo_ss7_vty_init_asp(g_hnbgw);
-       osmo_sccp_vty_init();
-       hnbgw_vty_init();
-       ctrl_vty_init(g_hnbgw);
-       logging_vty_add_cmds();
-       osmo_talloc_vty_add_cmds();
-
-       /* Handle options after vty_init(), for --version */
-       handle_options(argc, argv);
-
-       rc = vty_read_config_file(hnbgw_cmdline_config.config_file, NULL);
-       if (rc < 0) {
-               LOGP(DMAIN, LOGL_FATAL, "Failed to parse the config file: 
'%s'\n",
-                    hnbgw_cmdline_config.config_file);
-               return 1;
-       }
-
-       /*
-        * cmdline options take precedence over config file, but if no options
-        * were passed we must not override the config file.
-        */
-       if (hnbgw_cmdline_config.log_disable_color)
-               log_set_use_color(osmo_stderr_target, 0);
-       if (hnbgw_cmdline_config.log_category_mask)
-               log_parse_category_mask(osmo_stderr_target,
-                                       hnbgw_cmdline_config.log_category_mask);
-       if (hnbgw_cmdline_config.log_enable_timestamp)
-               log_set_print_timestamp(osmo_stderr_target, 1);
-       if (hnbgw_cmdline_config.log_level)
-               log_set_log_level(osmo_stderr_target,
-                                 hnbgw_cmdline_config.log_level);
-
-       rc = telnet_init_default(g_hnbgw, g_hnbgw, OSMO_VTY_PORT_HNBGW);
-       if (rc < 0) {
-               perror("Error binding VTY port");
-               exit(1);
-       }
-
-       g_hnbgw->ctrl = ctrl_interface_setup2(g_hnbgw, OSMO_CTRL_PORT_HNBGW, 
hnb_ctrl_node_lookup,
-                                              _LAST_CTRL_NODE_HNB);
-       if (!g_hnbgw->ctrl) {
-               LOGP(DMAIN, LOGL_ERROR, "Failed to create CTRL interface on 
%s:%u\n",
-                    ctrl_vty_get_bind_addr(), OSMO_CTRL_PORT_HNBGW);
-               exit(1);
-       } else {
-               rc = hnb_ctrl_cmds_install();
-               if (rc) {
-                       LOGP(DMAIN, LOGL_ERROR, "Failed to install CTRL 
interface commands\n");
-                       return 2;
-               }
-       }
-
-       ranap_set_log_area(DRANAP);
-
-       rc = hnbgw_cnlink_init("localhost", M3UA_PORT, "localhost");
-       if (rc < 0) {
-               LOGP(DMAIN, LOGL_ERROR, "Failed to initialize SCCP link to 
CN\n");
-               exit(1);
-       }
-
-       LOGP(DHNBAP, LOGL_NOTICE, "Using RNC-Id %u\n", g_hnbgw->config.rnc_id);
-
-       OSMO_ASSERT(g_hnbgw->config.iuh_local_ip);
-       LOGP(DMAIN, LOGL_NOTICE, "Listening for Iuh at %s %d\n",
-            g_hnbgw->config.iuh_local_ip,
-            g_hnbgw->config.iuh_local_port);
-       srv = osmo_stream_srv_link_create(g_hnbgw);
-       if (!srv) {
-               perror("cannot create server");
-               exit(1);
-       }
-       osmo_stream_srv_link_set_data(srv, g_hnbgw);
-       osmo_stream_srv_link_set_proto(srv, IPPROTO_SCTP);
-       osmo_stream_srv_link_set_nodelay(srv, true);
-       osmo_stream_srv_link_set_addr(srv, g_hnbgw->config.iuh_local_ip);
-       osmo_stream_srv_link_set_port(srv, g_hnbgw->config.iuh_local_port);
-       osmo_stream_srv_link_set_accept_cb(srv, accept_cb);
-
-       if (osmo_stream_srv_link_open(srv) < 0) {
-               perror("Cannot open server");
-               exit(1);
-       }
-       g_hnbgw->iuh = srv;
-
-       /* Initialize and connect MGCP client. */
-       if (hnbgw_mgw_setup() != 0)
-               return -EINVAL;
-
-#if ENABLE_PFCP
-       /* If UPF is configured, set up PFCP socket and send Association Setup 
Request to UPF */
-       hnbgw_pfcp_init();
-#endif
-
-       if (hnbgw_cmdline_config.daemonize) {
-               rc = osmo_daemonize();
-               if (rc < 0) {
-                       perror("Error during daemonize");
-                       exit(1);
-               }
-       }
-
-       while (1) {
-               rc = osmo_select_main_ctx(0);
-               if (rc < 0)
-                       exit(3);
-       }
-
-       /* not reached */
-       exit(0);
-}
-
 struct msgb *hnbgw_ranap_msg_alloc(const char *name)
 {
        struct msgb *ranap_msg;
@@ -855,3 +490,61 @@
        ranap_msg->l2h = ranap_msg->data;
        return ranap_msg;
 }
+
+static const char * const hnbgw_copyright =
+       "OsmoHNBGW - Osmocom Home Node B Gateway implementation\r\n"
+       "Copyright (C) 2016-2023 by sysmocom s.f.m.c. GmbH 
<i...@sysmocom.de>\r\n"
+       "Contributions by Daniel Willmann, Harald Welte, Neels Hofmeyr\r\n"
+       "License AGPLv3+: GNU AGPL version 3 or later 
<http://gnu.org/licenses/agpl-3.0.html>\r\n"
+       "This is free software: you are free to change and redistribute it.\r\n"
+       "There is NO WARRANTY, to the extent permitted by law.\r\n";
+
+static const struct log_info_cat hnbgw_log_cat[] = {
+       [DMAIN] = {
+               .name = "DMAIN", .loglevel = LOGL_NOTICE, .enabled = 1,
+               .color = "",
+               .description = "Main program",
+       },
+       [DHNBAP] = {
+               .name = "DHNBAP", .loglevel = LOGL_NOTICE, .enabled = 1,
+               .color = "",
+               .description = "Home Node B Application Part",
+       },
+       [DRUA] = {
+               .name = "DRUA", .loglevel = LOGL_NOTICE, .enabled = 1,
+               .color = "",
+               .description = "RANAP User Adaptation",
+       },
+       [DRANAP] = {
+               .name = "DRANAP", .loglevel = LOGL_NOTICE, .enabled = 1,
+               .color = "",
+               .description = "RAN Application Part",
+       },
+       [DMGW] = {
+               .name = "DMGW", .loglevel = LOGL_NOTICE, .enabled = 1,
+               .color = "\033[1;33m",
+               .description = "Media Gateway",
+       },
+       [DHNB] = {
+               .name = "DHNB", .loglevel = LOGL_NOTICE, .enabled = 1,
+               .color = OSMO_LOGCOLOR_CYAN,
+               .description = "HNB side (via RUA)",
+       },
+       [DCN] = {
+               .name = "DCN", .loglevel = LOGL_NOTICE, .enabled = 1,
+               .color = OSMO_LOGCOLOR_DARKYELLOW,
+               .description = "Core Network side (via SCCP)",
+       },
+};
+
+const struct log_info hnbgw_log_info = {
+       .cat = hnbgw_log_cat,
+       .num_cat = ARRAY_SIZE(hnbgw_log_cat),
+};
+
+struct vty_app_info hnbgw_vty_info = {
+       .name = "OsmoHNBGW",
+       .version = PACKAGE_VERSION,
+       .go_parent_cb = hnbgw_vty_go_parent,
+       .copyright = hnbgw_copyright,
+};
diff --git a/src/osmo-hnbgw/osmo_hnbgw_main.c b/src/osmo-hnbgw/osmo_hnbgw_main.c
new file mode 100644
index 0000000..abb577c
--- /dev/null
+++ b/src/osmo-hnbgw/osmo_hnbgw_main.c
@@ -0,0 +1,317 @@
+/* OsmoHNBGW main routine */
+
+/* (C) 2015 by Harald Welte <lafo...@gnumonks.org>
+ * (C) 2016-2023 by sysmocom s.f.m.c. GmbH <i...@sysmocom.de>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <getopt.h>
+
+#include "config.h"
+
+#include <osmocom/core/application.h>
+#include <osmocom/core/logging.h>
+
+#include <osmocom/vty/vty.h>
+#include <osmocom/vty/command.h>
+#include <osmocom/vty/logging.h>
+#include <osmocom/vty/misc.h>
+#include <osmocom/vty/telnet_interface.h>
+#include <osmocom/vty/ports.h>
+
+#include <osmocom/ctrl/control_vty.h>
+#include <osmocom/ctrl/ports.h>
+
+#include <osmocom/netif/stream.h>
+
+#include <osmocom/sigtran/protocol/m3ua.h>
+
+#include <osmocom/ranap/ranap_common.h>
+
+#include <osmocom/hnbgw/hnbgw.h>
+#include <osmocom/hnbgw/hnbgw_cn.h>
+#include <osmocom/hnbgw/hnbgw_pfcp.h>
+
+static struct {
+       int daemonize;
+       const char *config_file;
+       bool log_disable_color;
+       bool log_enable_timestamp;
+       int log_level;
+       const char *log_category_mask;
+} hnbgw_cmdline_config = {
+       0,
+       "osmo-hnbgw.cfg",
+       false,
+       false,
+       0,
+       NULL,
+};
+
+static void print_usage()
+{
+       printf("Usage: osmo-hnbgw\n");
+}
+
+static void print_help()
+{
+       printf("  -h --help                  This text.\n");
+       printf("  -d option --debug=DHNBAP:DRUA:DRANAP:DMAIN  Enable 
debugging.\n");
+       printf("  -D --daemonize             Fork the process into a background 
daemon.\n");
+       printf("  -c --config-file filename  The config file to use.\n");
+       printf("  -s --disable-color\n");
+       printf("  -T --timestamp             Prefix every log line with a 
timestamp.\n");
+       printf("  -V --version               Print the version of 
OsmoHNBGW.\n");
+       printf("  -e --log-level number      Set a global loglevel.\n");
+
+       printf("\nVTY reference generation:\n");
+       printf("     --vty-ref-mode MODE        VTY reference generation mode 
(e.g. 'expert').\n");
+       printf("     --vty-ref-xml              Generate the VTY reference XML 
output and exit.\n");
+}
+
+static void handle_long_options(const char *prog_name, const int long_option)
+{
+       static int vty_ref_mode = VTY_REF_GEN_MODE_DEFAULT;
+
+       switch (long_option) {
+       case 1:
+               vty_ref_mode = get_string_value(vty_ref_gen_mode_names, optarg);
+               if (vty_ref_mode < 0) {
+                       fprintf(stderr, "%s: Unknown VTY reference generation "
+                               "mode '%s'\n", prog_name, optarg);
+                       exit(2);
+               }
+               break;
+       case 2:
+               fprintf(stderr, "Generating the VTY reference in mode '%s' 
(%s)\n",
+                       get_value_string(vty_ref_gen_mode_names, vty_ref_mode),
+                       get_value_string(vty_ref_gen_mode_desc, vty_ref_mode));
+               vty_dump_xml_ref_mode(stdout, (enum vty_ref_gen_mode) 
vty_ref_mode);
+               exit(0);
+       default:
+               fprintf(stderr, "%s: error parsing cmdline options\n", 
prog_name);
+               exit(2);
+       }
+}
+
+static void handle_options(int argc, char **argv)
+{
+       while (1) {
+               int option_index = 0, c;
+               static int long_option = 0;
+               static struct option long_options[] = {
+                       {"help", 0, 0, 'h'},
+                       {"debug", 1, 0, 'd'},
+                       {"daemonize", 0, 0, 'D'},
+                       {"config-file", 1, 0, 'c'},
+                       {"disable-color", 0, 0, 's'},
+                       {"timestamp", 0, 0, 'T'},
+                       {"version", 0, 0, 'V' },
+                       {"log-level", 1, 0, 'e'},
+                       {"vty-ref-mode", 1, &long_option, 1},
+                       {"vty-ref-xml", 0, &long_option, 2},
+                       {0, 0, 0, 0}
+               };
+
+               c = getopt_long(argc, argv, "hd:Dc:sTVe:",
+                               long_options, &option_index);
+               if (c == -1)
+                       break;
+
+               switch (c) {
+               case 0:
+                       handle_long_options(argv[0], long_option);
+                       break;
+               case 'h':
+                       print_usage();
+                       print_help();
+                       exit(0);
+               case 's':
+                       hnbgw_cmdline_config.log_disable_color = true;
+                       break;
+               case 'd':
+                       hnbgw_cmdline_config.log_category_mask = optarg;
+                       break;
+               case 'D':
+                       hnbgw_cmdline_config.daemonize = 1;
+                       break;
+               case 'c':
+                       hnbgw_cmdline_config.config_file = optarg;
+                       break;
+               case 'T':
+                       hnbgw_cmdline_config.log_enable_timestamp = true;
+                       break;
+               case 'e':
+                       hnbgw_cmdline_config.log_level = atoi(optarg);
+                       break;
+               case 'V':
+                       print_version(1);
+                       exit(0);
+                       break;
+               default:
+                       /* catch unknown options *as well as* missing 
arguments. */
+                       fprintf(stderr, "Error in command line options. 
Exiting.\n");
+                       exit(-1);
+                       break;
+               }
+       }
+
+       if (argc > optind) {
+               fprintf(stderr, "Unsupported positional arguments on command 
line\n");
+               exit(2);
+       }
+}
+
+int main(int argc, char **argv)
+{
+       struct osmo_stream_srv_link *srv;
+       int rc;
+
+       talloc_enable_null_tracking();
+
+       /* g_hnbgw serves as the root talloc ctx, so allocate with NULL parent 
*/
+       g_hnbgw_alloc(NULL);
+       g_hnbgw->config.rnc_id = 23;
+
+       talloc_asn1_ctx = talloc_named_const(g_hnbgw, 1, "asn1_context");
+       msgb_talloc_ctx_init(g_hnbgw, 0);
+
+       rc = osmo_init_logging2(g_hnbgw, &hnbgw_log_info);
+       if (rc < 0)
+               exit(1);
+
+       osmo_fsm_log_timeouts(true);
+
+       rc = osmo_ss7_init();
+       if (rc < 0) {
+               LOGP(DMAIN, LOGL_FATAL, "osmo_ss7_init() failed with rc=%d\n", 
rc);
+               exit(1);
+       }
+
+       hnbgw_vty_info.tall_ctx = g_hnbgw;
+       vty_init(&hnbgw_vty_info);
+
+       osmo_ss7_vty_init_asp(g_hnbgw);
+       osmo_sccp_vty_init();
+       hnbgw_vty_init();
+       ctrl_vty_init(g_hnbgw);
+       logging_vty_add_cmds();
+       osmo_talloc_vty_add_cmds();
+
+       /* Handle options after vty_init(), for --version */
+       handle_options(argc, argv);
+
+       rc = vty_read_config_file(hnbgw_cmdline_config.config_file, NULL);
+       if (rc < 0) {
+               LOGP(DMAIN, LOGL_FATAL, "Failed to parse the config file: 
'%s'\n",
+                    hnbgw_cmdline_config.config_file);
+               return 1;
+       }
+
+       /*
+        * cmdline options take precedence over config file, but if no options
+        * were passed we must not override the config file.
+        */
+       if (hnbgw_cmdline_config.log_disable_color)
+               log_set_use_color(osmo_stderr_target, 0);
+       if (hnbgw_cmdline_config.log_category_mask)
+               log_parse_category_mask(osmo_stderr_target,
+                                       hnbgw_cmdline_config.log_category_mask);
+       if (hnbgw_cmdline_config.log_enable_timestamp)
+               log_set_print_timestamp(osmo_stderr_target, 1);
+       if (hnbgw_cmdline_config.log_level)
+               log_set_log_level(osmo_stderr_target,
+                                 hnbgw_cmdline_config.log_level);
+
+       rc = telnet_init_default(g_hnbgw, g_hnbgw, OSMO_VTY_PORT_HNBGW);
+       if (rc < 0) {
+               perror("Error binding VTY port");
+               exit(1);
+       }
+
+       g_hnbgw->ctrl = ctrl_interface_setup2(g_hnbgw, OSMO_CTRL_PORT_HNBGW, 
hnb_ctrl_node_lookup,
+                                              _LAST_CTRL_NODE_HNB);
+       if (!g_hnbgw->ctrl) {
+               LOGP(DMAIN, LOGL_ERROR, "Failed to create CTRL interface on 
%s:%u\n",
+                    ctrl_vty_get_bind_addr(), OSMO_CTRL_PORT_HNBGW);
+               exit(1);
+       } else {
+               rc = hnb_ctrl_cmds_install();
+               if (rc) {
+                       LOGP(DMAIN, LOGL_ERROR, "Failed to install CTRL 
interface commands\n");
+                       return 2;
+               }
+       }
+
+       ranap_set_log_area(DRANAP);
+
+       rc = hnbgw_cnlink_init("localhost", M3UA_PORT, "localhost");
+       if (rc < 0) {
+               LOGP(DMAIN, LOGL_ERROR, "Failed to initialize SCCP link to 
CN\n");
+               exit(1);
+       }
+
+       LOGP(DHNBAP, LOGL_NOTICE, "Using RNC-Id %u\n", g_hnbgw->config.rnc_id);
+
+       OSMO_ASSERT(g_hnbgw->config.iuh_local_ip);
+       LOGP(DMAIN, LOGL_NOTICE, "Listening for Iuh at %s %d\n",
+            g_hnbgw->config.iuh_local_ip,
+            g_hnbgw->config.iuh_local_port);
+       srv = osmo_stream_srv_link_create(g_hnbgw);
+       if (!srv) {
+               perror("cannot create server");
+               exit(1);
+       }
+       osmo_stream_srv_link_set_data(srv, g_hnbgw);
+       osmo_stream_srv_link_set_proto(srv, IPPROTO_SCTP);
+       osmo_stream_srv_link_set_nodelay(srv, true);
+       osmo_stream_srv_link_set_addr(srv, g_hnbgw->config.iuh_local_ip);
+       osmo_stream_srv_link_set_port(srv, g_hnbgw->config.iuh_local_port);
+       osmo_stream_srv_link_set_accept_cb(srv, hnbgw_rua_accept_cb);
+
+       if (osmo_stream_srv_link_open(srv) < 0) {
+               perror("Cannot open server");
+               exit(1);
+       }
+       g_hnbgw->iuh = srv;
+
+       /* Initialize and connect MGCP client. */
+       if (hnbgw_mgw_setup() != 0)
+               return -EINVAL;
+
+#if ENABLE_PFCP
+       /* If UPF is configured, set up PFCP socket and send Association Setup 
Request to UPF */
+       hnbgw_pfcp_init();
+#endif
+
+       if (hnbgw_cmdline_config.daemonize) {
+               rc = osmo_daemonize();
+               if (rc < 0) {
+                       perror("Error during daemonize");
+                       exit(1);
+               }
+       }
+
+       while (1) {
+               rc = osmo_select_main_ctx(0);
+               if (rc < 0)
+                       exit(3);
+       }
+
+       /* not reached */
+       exit(0);
+}

--
To view, visit https://gerrit.osmocom.org/c/osmo-hnbgw/+/32620
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-hnbgw
Gerrit-Branch: master
Gerrit-Change-Id: I5f26a6b68f0d380617d73371f40f3b9055cac362
Gerrit-Change-Number: 32620
Gerrit-PatchSet: 1
Gerrit-Owner: neels <nhofm...@sysmocom.de>
Gerrit-MessageType: newchange

Reply via email to