laforge has submitted this change. ( https://gerrit.osmocom.org/c/osmo-remsim/+/30139 )
Change subject: bankd: Add GSMTAP functionality for SIM traffic ......................................................................
bankd: Add GSMTAP functionality for SIM traffic
If a --gsmtap-host (-g) address is specified on the command line, trace SIM ATRs and APDUs to the given IP. If --gsmtap-slot (-G) is provided, limit tracing to the specified bank slot number. This feature may be useful when diagnosing issues with the remote SIM framework.
Added new log category: DGSMTAP
Also, cleaned up alignment in bankd --help output and removed unused -o option.
Change-Id: I05b599858d8758633aa56c3f12f258c27cf42d08 --- M src/bankd/Makefile.am M src/bankd/bankd.h M src/bankd/bankd_main.c A src/bankd/gsmtap.c A src/bankd/gsmtap.h M src/debug.c M src/debug.h 7 files changed, 175 insertions(+), 15 deletions(-)
Approvals: laforge: Looks good to me, approved Jenkins Builder: Verified
diff --git a/src/bankd/Makefile.am b/src/bankd/Makefile.am index 42c9bd3..4899aef 100644 --- a/src/bankd/Makefile.am +++ b/src/bankd/Makefile.am @@ -3,7 +3,7 @@ $(OSMOCORE_CFLAGS) $(OSMOGSM_CFLAGS) $(OSMOABIS_CFLAGS) \ $(PCSC_CFLAGS)
-noinst_HEADERS = bankd.h internal.h +noinst_HEADERS = bankd.h internal.h gsmtap.h
bin_PROGRAMS = osmo-remsim-bankd noinst_PROGRAMS = pcsc_test @@ -13,7 +13,7 @@ $(PCSC_LIBS) $(top_builddir)/src/libosmo-rspro.la
osmo_remsim_bankd_SOURCES = ../slotmap.c ../rspro_client_fsm.c ../debug.c \ - bankd_main.c bankd_pcsc.c + bankd_main.c bankd_pcsc.c gsmtap.c osmo_remsim_bankd_LDADD = $(OSMOCORE_LIBS) $(OSMOGSM_LIBS) $(OSMOABIS_LIBS) \ $(PCSC_LIBS) $(CSV_LIBS) $(top_builddir)/src/libosmo-rspro.la
diff --git a/src/bankd/bankd.h b/src/bankd/bankd.h index e340b5a..8a48a21 100644 --- a/src/bankd/bankd.h +++ b/src/bankd/bankd.h @@ -139,6 +139,8 @@
struct { bool permit_shared_pcsc; + char *gsmtap_host; + int gsmtap_slot; } cfg; };
diff --git a/src/bankd/bankd_main.c b/src/bankd/bankd_main.c index bf7ca82..3fd4d6b 100644 --- a/src/bankd/bankd_main.c +++ b/src/bankd/bankd_main.c @@ -47,6 +47,7 @@ #include "rspro_client_fsm.h" #include "debug.h" #include "rspro_util.h" +#include "gsmtap.h"
/* signal indicates to worker thread that its map has been deleted */ #define SIGMAPDEL SIGRTMIN+1 @@ -100,6 +101,8 @@ INIT_LLIST_HEAD(&bankd->pcsc_slot_names);
bankd->cfg.permit_shared_pcsc = false; + bankd->cfg.gsmtap_host = NULL; + bankd->cfg.gsmtap_slot = -1; }
/* create + start a new bankd_worker thread */ @@ -284,18 +287,20 @@ static void printf_help() { printf( -" -h --help Print this help message\n" -" -V --version Print the version of the program\n" -" -d --debug option Enable debug logging (e.g. DMAIN:DST2)\n" -" -i --server-host A.B.C.D remsim-server IP address (default: 127.0.0.1)\n" -" -p --server-port <1-65535> remsim-server TCP port (default: 9998)\n" -" -b --bank-id <1-1023> Bank Identifier of this SIM bank (default: 1)\n" -" -n --num-slots <1-1023> Number of Slots in this SIM bank (default: 8)\n" -" -I --bind-ip A.B.C.D Local IP address to bind for incoming client\n" -" connections (default: INADDR_ANY)\n" -" -P --bind-port <1-65535> Local TCP port to bind for incoming client\n" -" connectionss (default: 9999)\n" -" -s --permit-shared-pcsc Permit SHARED access to PC/SC readers (default: exclusive)\n" +" -h --help Print this help message\n" +" -V --version Print the version of the program\n" +" -d --debug option Enable debug logging (e.g. DMAIN:DST2)\n" +" -i --server-host A.B.C.D remsim-server IP address (default: 127.0.0.1)\n" +" -p --server-port <1-65535> remsim-server TCP port (default: 9998)\n" +" -b --bank-id <1-1023> Bank Identifier of this SIM bank (default: 1)\n" +" -n --num-slots <1-1023> Number of Slots in this SIM bank (default: 8)\n" +" -I --bind-ip A.B.C.D Local IP address to bind for incoming client\n" +" connections (default: INADDR_ANY)\n" +" -P --bind-port <1-65535> Local TCP port to bind for incoming client\n" +" connections (default: 9999)\n" +" -s --permit-shared-pcsc Permit SHARED access to PC/SC readers (default: exclusive)\n" +" -g --gsmtap-ip A.B.C.D Enable GSMTAP and send APDU traces to given IP\n" +" -G --gsmtap-slot <0-1023> Limit tracing to given bank slot, only (default: all slots)\n" ); }
@@ -318,10 +323,12 @@ { "bind-ip", 1, 0, 'I' }, { "bind-port", 1, 0, 'P' }, { "permit-shared-pcsc", 0, 0, 's' }, + { "gsmtap-ip", 1, 0, 'g' }, + { "gsmtap-slot", 1, 0, 'G' }, { 0, 0, 0, 0 } };
- c = getopt_long(argc, argv, "hVd:i:p:o:b:n:N:I:P:s", long_options, &option_index); + c = getopt_long(argc, argv, "hVd:i:p:b:n:N:I:P:sg:G:", long_options, &option_index); if (c == -1) break;
@@ -361,6 +368,12 @@ case 's': g_bankd->cfg.permit_shared_pcsc = true; break; + case 'g': + g_bankd->cfg.gsmtap_host = optarg; + break; + case 'G': + g_bankd->cfg.gsmtap_slot = atoi(optarg); + break; } } } @@ -418,6 +431,15 @@ } g_bankd->accept_fd = rc;
+ /* initialize gsmtap, if required */ + if (g_bankd->cfg.gsmtap_host) { + rc = bankd_gsmtap_init(g_bankd->cfg.gsmtap_host); + if (rc < 0) { + fprintf(stderr, "Unable to open GSMTAP"); + exit(1); + } + } + /* create worker threads: One per reader/slot! */ for (i = 0; i < g_bankd->srvc.bankd.num_slots; i++) { struct bankd_worker *w; @@ -661,6 +683,14 @@ set_atr = rspro_gen_SetAtrReq(worker->client.clslot.client_id, worker->client.clslot.slot_nr, worker->card.atr, worker->card.atr_len); + + /* trace ATR to GSMTAP, if configured */ + if (g_bankd->cfg.gsmtap_host && (g_bankd->cfg.gsmtap_slot == -1 || + g_bankd->cfg.gsmtap_slot == worker->slot.slot_nr)) { + bankd_gsmtap_send_apdu(GSMTAP_SIM_ATR, worker->card.atr, worker->card.atr_len, + NULL, 0); + } + if (!set_atr) return -1; return worker_send_rspro(worker, set_atr); @@ -761,6 +791,12 @@ rx_buf, rx_buf_len); worker_send_rspro(worker, pdu_resp);
+ /* trace APDU to GSMTAP, if configured */ + if (g_bankd->cfg.gsmtap_host && (g_bankd->cfg.gsmtap_slot == -1 || + g_bankd->cfg.gsmtap_slot == worker->slot.slot_nr)) { + bankd_gsmtap_send_apdu(GSMTAP_SIM_APDU, mdm2sim->data.buf, mdm2sim->data.size, rx_buf, + rx_buf_len); + } return 0; }
diff --git a/src/bankd/gsmtap.c b/src/bankd/gsmtap.c new file mode 100644 index 0000000..8aced6a --- /dev/null +++ b/src/bankd/gsmtap.c @@ -0,0 +1,109 @@ +/* gsmtap - How to encapsulate SIM protocol traces in GSMTAP + * + * (C) 2016-2019 by Harald Welte hwelte@hmw-consulting.de + * + * 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. + */ + +/* among other things, bring in GNU-specific strerror_r() */ +#define _GNU_SOURCE + +#include <osmocom/core/gsmtap.h> +#include <osmocom/core/gsmtap_util.h> +#include <osmocom/core/logging.h> + +#include <errno.h> +#include <string.h> +#include <unistd.h> +#include <stdio.h> +#include <sys/uio.h> + +#include "debug.h" + +/*! global GSMTAP instance */ +static struct gsmtap_inst *g_gti; + +/*! initialize the global GSMTAP instance for SIM traces + * + * \param[in] gsmtap_host Hostname to send GSMTAP packets + * + * \return 0 on success, non-zero on error + */ +int bankd_gsmtap_init(const char *gsmtap_host) +{ + if (g_gti) + return -EEXIST; + + errno = 0; + g_gti = gsmtap_source_init(gsmtap_host, GSMTAP_UDP_PORT, 0); + if (!g_gti) { + LOGP(DGSMTAP, LOGL_ERROR, "unable to initialize GSMTAP\n"); + return -EIO; + } + gsmtap_source_add_sink(g_gti); + + LOGP(DGSMTAP, LOGL_INFO, "initialized GSMTAP to %s\n", gsmtap_host); + + return 0; +} + +/*! Log one APDU via the global GSMTAP instance by concatenating mdm_tpdu and sim_tpdu. + * + * \param[in] sub_type GSMTAP sub-type (GSMTAP_SIM_* constant) + * \param[in] mdm_tpdu User-provided buffer with ModemToCard TPDU to log. May be NULL. + * \param[in] mdm_tpdu_len Length of ModemToCard TPDU, in bytes. + * \param[in] sim_tpdu User-provided buffer with CardToModem TPDU to log. May be NULL. + * \param[in] sim_tpdu_len Length of CardToModem TPDU, in bytes. + * + * \return number of bytes sent on success, -1 on failure + */ +int bankd_gsmtap_send_apdu(uint8_t sub_type, const uint8_t *mdm_tpdu, unsigned int mdm_tpdu_len, + const uint8_t *sim_tpdu, unsigned int sim_tpdu_len) +{ + const struct gsmtap_hdr gh = { + .version = GSMTAP_VERSION, + .hdr_len = sizeof(struct gsmtap_hdr)/4, + .type = GSMTAP_TYPE_SIM, + .sub_type = sub_type, + }; + + struct iovec iov[3]; + unsigned int cnt = 0; + + iov[cnt].iov_base = (void *)&gh; + iov[cnt].iov_len = sizeof(gh); + cnt++; + + if (mdm_tpdu && mdm_tpdu_len) { + iov[cnt].iov_base = (void *)mdm_tpdu; + iov[cnt].iov_len = mdm_tpdu_len; + cnt++; + } + + if (sim_tpdu && sim_tpdu_len) { + iov[cnt].iov_base = (void *)sim_tpdu; + iov[cnt].iov_len = sim_tpdu_len; + cnt++; + } + + LOGP(DGSMTAP, LOGL_DEBUG, "sending APDU sub_type=%u, mdm_tpdu len=%u, sim_tpdu len=%u, iov cnt=%u\n", + sub_type, mdm_tpdu_len, sim_tpdu_len, cnt); + + const int rc = writev(gsmtap_inst_fd(g_gti), iov, cnt); + if (rc < 0) { + char errtxt[128]; + LOGP(DGSMTAP, LOGL_ERROR, "writev() failed with errno=%d: %s\n", errno, strerror_r(errno, + errtxt, sizeof(errtxt))); + return rc; + } + + return 0; +} diff --git a/src/bankd/gsmtap.h b/src/bankd/gsmtap.h new file mode 100644 index 0000000..87fe6a0 --- /dev/null +++ b/src/bankd/gsmtap.h @@ -0,0 +1,7 @@ +#pragma once +#include <stdint.h> +#include <osmocom/core/gsmtap.h> + +int bankd_gsmtap_init(const char *gsmtap_host); +int bankd_gsmtap_send_apdu(uint8_t sub_type, const uint8_t *mdm_tpdu, unsigned int mdm_tpdu_len, + const uint8_t *sim_tpdu, unsigned int sim_tpdu_len); diff --git a/src/debug.c b/src/debug.c index fb8bb4b..2f163d3 100644 --- a/src/debug.c +++ b/src/debug.c @@ -52,6 +52,11 @@ .loglevel = LOGL_INFO, .enabled = 1, }, + [DGSMTAP] = { + .name = "DGSMTAP", + .loglevel = LOGL_INFO, + .enabled = 1, + }, };
const struct log_info log_info = { diff --git a/src/debug.h b/src/debug.h index 88288ca..6e04393 100644 --- a/src/debug.h +++ b/src/debug.h @@ -8,6 +8,7 @@ DREST, DSLOTMAP, DBANKDW, + DGSMTAP, };
extern const struct log_info log_info;