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 <[email protected]>
+ *
+ * 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;

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

Gerrit-Project: osmo-remsim
Gerrit-Branch: master
Gerrit-Change-Id: I05b599858d8758633aa56c3f12f258c27cf42d08
Gerrit-Change-Number: 30139
Gerrit-PatchSet: 5
Gerrit-Owner: jtavares <[email protected]>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <[email protected]>
Gerrit-MessageType: merged

Reply via email to