/* * (C) 2022 by Harald Welte * (C) 2021 by Andreas Eversberg * 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 . * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "v5x_internal.h" #include "v5x_protocol.h" #include "layer1.h" #include "v5x_l1_fsm.h" #include "lapv5.h" #include "v5x_le_ctrl_fsm.h" #include "v5x_le_port_fsm.h" #include "v5x_le_pstn_fsm.h" #include "v52_le_lcp_fsm.h" #include "v52_le_bcc_fsm.h" #include "v52_le_pp_fsm.h" #include "v5x_le_management.h" #include "v5le_vty.h" #include "logging.h" #define _GNU_SOURCE #include void *tall_v5le_ctx = NULL; struct v5x_instance *v5i = NULL; static int daemonize = 0; const char *v5le_copyright = "Copyright (C) 2022 by Harald Welte & Andreas Eversberg\r\n" "License AGPLv3+: GNU AGPL version 3 or later \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 char *config_file = "osmo-v5-le.cfg"; static void print_help() { printf("Some useful options:\n"); printf(" -h --help is printing this text.\n"); printf(" -c --config-file filename The config file to use.\n"); printf(" -s --disable-color\n"); printf(" -D --daemonize Fork the process into a background daemon\n"); printf(" -V --version Print the version number\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'}, {"config-file", 1, 0, 'c'}, {"daemonize", 0, 0, 'D'}, {"version", 0, 0, 'V'}, {"disable-color", 0, 0, 's'}, {"vty-ref-mode", 1, &long_option, 1}, {"vty-ref-xml", 0, &long_option, 2}, {0, 0, 0, 0}, }; c = getopt_long(argc, argv, "hc:sVD", long_options, &option_index); if (c == -1) break; switch(c) { case 'h': print_help(); exit(0); break; case 0: handle_long_options(argv[0], long_option); break; case 'c': config_file = talloc_strdup(tall_v5le_ctx, optarg); break; case 's': log_set_use_color(osmo_stderr_target, 0); break; case 'V': print_version(1); exit(0); break; case 'D': daemonize = 1; break; default: /* ignore */ break; }; } if (argc > optind) { fprintf(stderr, "Unsupported positional arguments on command line\n"); exit(2); } } static int quit = 0; static void sighandler(int sigset) { if (sigset == SIGHUP) return; if (sigset == SIGPIPE) return; fprintf(stderr, "Signal received: %d\n", sigset); quit = 1; } int main(int argc, char **argv) { int rc; tall_v5le_ctx = talloc_named_const(NULL, 1, "v5le"); vty_info.tall_ctx = tall_v5le_ctx; msgb_talloc_ctx_init(tall_v5le_ctx, 0); osmo_init_ignore_signals(); osmo_init_logging2(tall_v5le_ctx, &log_info); libosmo_abis_init(tall_v5le_ctx); vty_info.copyright = v5le_copyright; vty_init(&vty_info); logging_vty_add_cmds(); osmo_talloc_vty_add_cmds(); osmo_stats_vty_add_cmds(); v5le_vty_init(); ctrl_vty_init(tall_v5le_ctx); e1inp_vty_init(); osmo_cpu_sched_vty_init(tall_v5le_ctx); handle_options(argc, argv); rate_ctr_init(tall_v5le_ctx); osmo_stats_init(tall_v5le_ctx); /* global inits of protocols */ v5x_l1_init(); v5x_le_ctrl_init(); v5x_le_port_init(); v5x_le_pstn_init(); v52_le_lcp_init(); v52_le_bcc_init(); v52_le_pp_init(); v5x_le_mgmt_init(); /* create v5x instance */ v5i = v5x_instance_alloc(tall_v5le_ctx); if (!v5i) return -ENOMEM; rc = vty_read_config_file(config_file, NULL); if (rc < 0) { fprintf(stderr, "Failed to read config file '%s'.\n", config_file); return rc; } rc = e1_init(); OSMO_ASSERT(rc == 0); /* start telnet after reading config for vty_get_bind_addr() */ rc = telnet_init_dynif(tall_v5le_ctx, NULL, vty_get_bind_addr(), OSMO_VTY_PORT_MGW); if (rc < 0) return rc; /* start DL */ if (!llist_empty(&v5i->interfaces)) { struct v5x_interface *v5if; v5if = (struct v5x_interface *)v5i->interfaces.next; if (v5if->control.li) lapv5_dl_est_req(v5if->control.li, V5X_DLADDR_CTRL); if (v5if->pstn.li) lapv5_dl_est_req(v5if->pstn.li, V5X_DLADDR_PSTN); if (v5if->lcp.li) lapv5_dl_est_req(v5if->lcp.li, V52_DLADDR_LCP); if (v5if->bcc.li) lapv5_dl_est_req(v5if->bcc.li, V52_DLADDR_BCC); if (v5if->protection.li[0]) lapv5_dl_est_req(v5if->protection.li[0], V52_DLADDR_PROTECTION); if (v5if->protection.li[1]) lapv5_dl_est_req(v5if->protection.li[1], V52_DLADDR_PROTECTION); } /* initialisation */ srand(time(NULL)); if (daemonize) { rc = osmo_daemonize(); if (rc < 0) { perror("Error during daemonize"); exit(1); } } /* catch signals */ signal(SIGINT, sighandler); signal(SIGHUP, sighandler); signal(SIGTERM, sighandler); signal(SIGPIPE, sighandler); /* main loop */ while (!quit) { osmo_select_main(0); } /* reset signals */ signal(SIGINT, SIG_DFL); signal(SIGHUP, SIG_DFL); signal(SIGTERM, SIG_DFL); signal(SIGPIPE, SIG_DFL); /* destroy the universe */ v5x_instance_free(v5i); return 0; }