/* * (C) 2017-2018 by sysmocom - s.f.m.c. GmbH, Author: Max * (C) 2018 by Vadim Yanitskiy * (C) 2011-2012 by Luca Melette * * All Rights Reserved * * SPDX-License-Identifier: GPL-2.0+ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "l1ctl_proto.h" #include "gsmtap.h" #include "gprs.h" static struct { char *capture_file; char *gsmtap_ip; bool verbose; bool quit; } app_data; static void burst_handle(struct l1ctl_burst_ind *bi) { uint8_t type, subch, ts; uint32_t fn; fn = ntohl(bi->frame_nr); rsl_dec_chan_nr(bi->chan_nr, &type, &subch, &ts); switch (type) { case RSL_CHAN_Bm_ACCHs: /* FIXME: what is (fn % 13) != 12? */ /* TODO: use the multiframe layout here */ if ((ts > 0) && ((fn % 13) != 12)) process_pdch(bi, app_data.verbose); break; default: /* We are only interested in GPRS messages */ break; } } static void print_help(const char *app) { printf(" Some help...\n\n"); printf(" Usage: %s [OPTIONS]\n\n", app); printf(" -h --help this text\n"); printf(" -c --capture The capture file to decode\n"); printf(" -i --gsmtap-ip The destination IP used for GSMTAP\n"); printf(" -v --verbose Increase the verbosity level\n"); } static int handle_options(int argc, char **argv) { /* Init defaults */ app_data.capture_file = NULL; app_data.gsmtap_ip = NULL; app_data.verbose = false; app_data.quit = false; /* Parse options */ while (1) { int option_index = 0, c; static struct option long_options[] = { {"help", 0, 0, 'h'}, {"verbose", 0, 0, 'v'}, {"capture", 1, 0, 'c'}, {"gsmtap-ip", 1, 0, 'i'}, {0, 0, 0, 0} }; c = getopt_long(argc, argv, "c:i:vh", long_options, &option_index); if (c == -1) break; switch (c) { case 'h': print_help(argv[0]); return 1; case 'c': app_data.capture_file = optarg; break; case 'i': app_data.gsmtap_ip = optarg; break; case 'v': app_data.verbose = true; break; default: break; } } /* Make sure we have the capture file path */ if (!app_data.capture_file) { print_help(argv[0]); printf("\nPlease specify the capture file\n"); return -1; } return 0; } static void signal_handler(int signal) { fprintf(stderr, "signal %d received\n", signal); switch (signal) { case SIGINT: app_data.quit = true; break; default: break; } } int main(int argc, char **argv) { struct l1ctl_burst_ind bi; FILE *burst_fd; int rc; /* Setup signal handlers */ signal(SIGINT, &signal_handler); osmo_init_ignore_signals(); /* Parse options */ rc = handle_options(argc, argv); if (rc) return EXIT_FAILURE; /* Attempt to open the capture for reading */ burst_fd = fopen(app_data.capture_file, "rb"); if (!burst_fd) { printf("Cannot open capture file '%s': %s\n", app_data.capture_file, strerror(errno)); return EXIT_FAILURE; } /* Init GSMTAP sink if required */ if (app_data.gsmtap_ip != NULL) gsmtap_init(app_data.gsmtap_ip); /* Application main loop */ while (!app_data.quit) { /* The end of capture file */ if (feof(burst_fd)) break; /* Read a single burst */ rc = fread(&bi, sizeof(bi), 1, burst_fd); if (!rc) break; /* Filter or handle burst */ burst_handle(&bi); osmo_select_main(1); } /* Close the capture file */ fclose(burst_fd); return 0; }