This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.
laforge gerrit-no-reply at lists.osmocom.orglaforge has uploaded this change for review. ( https://gerrit.osmocom.org/c/simtrace2/+/16194 ) Change subject: host: use autotools and split shared code to libosmo-simtrace2 ...................................................................... host: use autotools and split shared code to libosmo-simtrace2 Change-Id: I57e77f927ee9e169cc794c5dc6b128a2d590201b --- M contrib/jenkins.sh A host/.gitignore A host/Makefile.am R host/Makefile.old A host/configure.ac R host/contrib/99-simtrace2.rules A host/contrib/Makefile.am A host/git-version-gen A host/include/Makefile.am R host/include/osmocom/simtrace2/apdu_dispatch.h A host/include/osmocom/simtrace2/gsmtap.h R host/include/osmocom/simtrace2/libusb_util.h A host/include/osmocom/simtrace2/simtrace2_api.h A host/include/osmocom/simtrace2/simtrace_prot.h A host/include/osmocom/simtrace2/simtrace_usb.h A host/lib/Makefile.am R host/lib/apdu_dispatch.c A host/lib/gsmtap.c R host/lib/libusb_util.c A host/lib/simtrace2_api.c A host/libosmo-simtrace2.pc.in D host/simtrace.h D host/simtrace2-remsim.c D host/simtrace_prot.h D host/simtrace_usb.h A host/src/Makefile.am R host/src/simtrace2-discovery.c R host/src/simtrace2-discovery.h A host/src/simtrace2-remsim.c R host/src/simtrace2-sniff.c R host/src/simtrace2_usb.c R host/src/usb2udp.c 32 files changed, 1,245 insertions(+), 836 deletions(-) git pull ssh://gerrit.osmocom.org:29418/simtrace2 refs/changes/94/16194/1 diff --git a/contrib/jenkins.sh b/contrib/jenkins.sh index b85e4b3..a8426bd 100755 --- a/contrib/jenkins.sh +++ b/contrib/jenkins.sh @@ -50,9 +50,15 @@ echo echo "=============== HOST START ==============" cd $TOPDIR/host -make clean -make -make clean +autoreconf --install --force +./configure --enable-sanitize --enable-werror +$MAKE $PARALLEL_MAKE +#$MAKE distcheck || cat-testlogs.sh +make dist + +#if [ "$WITH_MANUALS" = "1" ] && [ "$PUBLISH" = "1" ]; then +# make -C "$base/doc/manuals" publish +#fi if [ "x$publish" = "x--publish" ]; then echo @@ -69,6 +75,10 @@ fi echo +echo "=============== HOST CLEAN ==============" +$MAKE maintainer-clean + +echo echo "=============== FIRMWARE CLEAN ==============" cd $TOPDIR/firmware/ for build in $BUILDS; do diff --git a/host/.gitignore b/host/.gitignore new file mode 100644 index 0000000..44ca2a0 --- /dev/null +++ b/host/.gitignore @@ -0,0 +1,32 @@ +.o +*.a +*.lo +*.la +.deps +Makefile +Makefile.in + +#configure +aclocal.m4 +autom4te.cache/ +compile +config.guess +config.log +config.status +config.sub +configure +configure.lineno +depcomp +install-sh +missing +stamp-h1 + +#libtool +ltmain.sh +libtool +.libs + +.tarball-version +.version + +*.pc diff --git a/host/Makefile.am b/host/Makefile.am new file mode 100644 index 0000000..d1b3b31 --- /dev/null +++ b/host/Makefile.am @@ -0,0 +1,14 @@ +AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6 + +AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include +SUBDIRS = include lib src contrib #tests examples doc + +EXTRA_DIST = .version git-version-gen + + at RELMAKE@ + +BUILT_SOURCES = $(top_srcdir)/.version +$(top_srcdir)/.version: + echo $(VERSION) > $@-t && mv $@-t $@ +dist-hook: + echo $(VERSION) > $(distdir)/.tarball-version diff --git a/host/Makefile b/host/Makefile.old similarity index 94% rename from host/Makefile rename to host/Makefile.old index aee399c..ab767cd 100644 --- a/host/Makefile +++ b/host/Makefile.old @@ -5,7 +5,7 @@ all: $(APPS) -simtrace2-remsim: simtrace2-remsim.o apdu_dispatch.o simtrace2-discovery.o libusb_util.o +simtrace2-remsim: simtrace2-remsim.o apdu_dispatch.o simtrace2-discovery.o simtrace2_api.o libusb_util.o $(CC) -o $@ $^ $(LDFLAGS) `pkg-config --libs libosmosim libpcsclite` simtrace2-remsim-usb2udp: usb2udp.o simtrace2-discovery.o diff --git a/host/configure.ac b/host/configure.ac new file mode 100644 index 0000000..7929884 --- /dev/null +++ b/host/configure.ac @@ -0,0 +1,102 @@ +AC_INIT([simtrace2], + m4_esyscmd([./git-version-gen .tarball-version]), + [simtrace at lists.osmocom.org]) + +dnl *This* is the root dir, even if an install-sh exists in ../ or ../../ +AC_CONFIG_AUX_DIR([.]) + +AM_INIT_AUTOMAKE([foreign dist-bzip2 no-dist-gzip 1.6 subdir-objects]) +AC_CONFIG_TESTDIR(tests) + +dnl kernel style compile messages +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +dnl include release helper +RELMAKE='-include osmo-release.mk' +AC_SUBST([RELMAKE]) + +dnl checks for programs +AC_PROG_MAKE_SET +AC_PROG_CC +AC_PROG_INSTALL +LT_INIT([pic-only]) + +dnl check for pkg-config (explained in detail in libosmocore/configure.ac) +AC_PATH_PROG(PKG_CONFIG_INSTALLED, pkg-config, no) +if test "x$PKG_CONFIG_INSTALLED" = "xno"; then + AC_MSG_WARN([You need to install pkg-config]) +fi +PKG_PROG_PKG_CONFIG([0.20]) + +AC_CONFIG_MACRO_DIR([m4]) + +CFLAGS="$CFLAGS -Wall" +CPPFLAGS="$CPPFLAGS -Wall" + +AC_ARG_ENABLE(sanitize, + [AS_HELP_STRING( + [--enable-sanitize], + [Compile with address sanitizer enabled], + )], + [sanitize=$enableval], [sanitize="no"]) +if test x"$sanitize" = x"yes" +then + CFLAGS="$CFLAGS -fsanitize=address -fsanitize=undefined" + CPPFLAGS="$CPPFLAGS -fsanitize=address -fsanitize=undefined" +fi + +# The following test is taken from WebKit's webkit.m4 +saved_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS -fvisibility=hidden " +AC_MSG_CHECKING([if ${CC} supports -fvisibility=hidden]) +AC_COMPILE_IFELSE([AC_LANG_SOURCE([char foo;])], + [ AC_MSG_RESULT([yes]) + SYMBOL_VISIBILITY="-fvisibility=hidden"], + AC_MSG_RESULT([no])) +CFLAGS="$saved_CFLAGS" +AC_SUBST(SYMBOL_VISIBILITY) + +PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.0.0) +PKG_CHECK_MODULES(LIBOSMOSIM, libosmosim >= 1.0.0) +PKG_CHECK_MODULES(LIBUSB, libusb-1.0) + +AC_ARG_ENABLE(sanitize, + [AS_HELP_STRING( + [--enable-sanitize], + [Compile with address sanitizer enabled], + )], + [sanitize=$enableval], [sanitize="no"]) +if test x"$sanitize" = x"yes" +then + CFLAGS="$CFLAGS -fsanitize=address -fsanitize=undefined" + CPPFLAGS="$CPPFLAGS -fsanitize=address -fsanitize=undefined" +fi + +AC_ARG_ENABLE(werror, + [AS_HELP_STRING( + [--enable-werror], + [Turn all compiler warnings into errors, with exceptions: + a) deprecation (allow upstream to mark deprecation without breaking builds); + b) "#warning" pragmas (allow to remind ourselves of errors without breaking builds) + ] + )], + [werror=$enableval], [werror="no"]) +if test x"$werror" = x"yes" +then + WERROR_FLAGS="-Werror" + WERROR_FLAGS+=" -Wno-error=deprecated -Wno-error=deprecated-declarations" + WERROR_FLAGS+=" -Wno-error=cpp" # "#warning" + CFLAGS="$CFLAGS $WERROR_FLAGS" + CPPFLAGS="$CPPFLAGS $WERROR_FLAGS" +fi + +AC_MSG_RESULT([CFLAGS="$CFLAGS"]) +AC_MSG_RESULT([CPPFLAGS="$CPPFLAGS"]) + +AC_OUTPUT( + libosmo-simtrace2.pc + include/Makefile + src/Makefile + lib/Makefile + contrib/Makefile + Makefile) diff --git a/host/99-simtrace2.rules b/host/contrib/99-simtrace2.rules similarity index 100% rename from host/99-simtrace2.rules rename to host/contrib/99-simtrace2.rules diff --git a/host/contrib/Makefile.am b/host/contrib/Makefile.am new file mode 100644 index 0000000..4f11962 --- /dev/null +++ b/host/contrib/Makefile.am @@ -0,0 +1 @@ +EXTRA_DIST = 99-simtrace2.rules diff --git a/host/git-version-gen b/host/git-version-gen new file mode 100755 index 0000000..42cf3d2 --- /dev/null +++ b/host/git-version-gen @@ -0,0 +1,151 @@ +#!/bin/sh +# Print a version string. +scriptversion=2010-01-28.01 + +# Copyright (C) 2007-2010 Free Software Foundation, Inc. +# +# 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 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# This script is derived from GIT-VERSION-GEN from GIT: http://git.or.cz/. +# It may be run two ways: +# - from a git repository in which the "git describe" command below +# produces useful output (thus requiring at least one signed tag) +# - from a non-git-repo directory containing a .tarball-version file, which +# presumes this script is invoked like "./git-version-gen .tarball-version". + +# In order to use intra-version strings in your project, you will need two +# separate generated version string files: +# +# .tarball-version - present only in a distribution tarball, and not in +# a checked-out repository. Created with contents that were learned at +# the last time autoconf was run, and used by git-version-gen. Must not +# be present in either $(srcdir) or $(builddir) for git-version-gen to +# give accurate answers during normal development with a checked out tree, +# but must be present in a tarball when there is no version control system. +# Therefore, it cannot be used in any dependencies. GNUmakefile has +# hooks to force a reconfigure at distribution time to get the value +# correct, without penalizing normal development with extra reconfigures. +# +# .version - present in a checked-out repository and in a distribution +# tarball. Usable in dependencies, particularly for files that don't +# want to depend on config.h but do want to track version changes. +# Delete this file prior to any autoconf run where you want to rebuild +# files to pick up a version string change; and leave it stale to +# minimize rebuild time after unrelated changes to configure sources. +# +# It is probably wise to add these two files to .gitignore, so that you +# don't accidentally commit either generated file. +# +# Use the following line in your configure.ac, so that $(VERSION) will +# automatically be up-to-date each time configure is run (and note that +# since configure.ac no longer includes a version string, Makefile rules +# should not depend on configure.ac for version updates). +# +# AC_INIT([GNU project], +# m4_esyscmd([build-aux/git-version-gen .tarball-version]), +# [bug-project at example]) +# +# Then use the following lines in your Makefile.am, so that .version +# will be present for dependencies, and so that .tarball-version will +# exist in distribution tarballs. +# +# BUILT_SOURCES = $(top_srcdir)/.version +# $(top_srcdir)/.version: +# echo $(VERSION) > $@-t && mv $@-t $@ +# dist-hook: +# echo $(VERSION) > $(distdir)/.tarball-version + +case $# in + 1) ;; + *) echo 1>&2 "Usage: $0 \$srcdir/.tarball-version"; exit 1;; +esac + +tarball_version_file=$1 +nl=' +' + +# First see if there is a tarball-only version file. +# then try "git describe", then default. +if test -f $tarball_version_file +then + v=`cat $tarball_version_file` || exit 1 + case $v in + *$nl*) v= ;; # reject multi-line output + [0-9]*) ;; + *) v= ;; + esac + test -z "$v" \ + && echo "$0: WARNING: $tarball_version_file seems to be damaged" 1>&2 +fi + +if test -n "$v" +then + : # use $v +elif + v=`git describe --abbrev=4 --match='v*' HEAD 2>/dev/null \ + || git describe --abbrev=4 HEAD 2>/dev/null` \ + && case $v in + [0-9]*) ;; + v[0-9]*) ;; + *) (exit 1) ;; + esac +then + # Is this a new git that lists number of commits since the last + # tag or the previous older version that did not? + # Newer: v6.10-77-g0f8faeb + # Older: v6.10-g0f8faeb + case $v in + *-*-*) : git describe is okay three part flavor ;; + *-*) + : git describe is older two part flavor + # Recreate the number of commits and rewrite such that the + # result is the same as if we were using the newer version + # of git describe. + vtag=`echo "$v" | sed 's/-.*//'` + numcommits=`git rev-list "$vtag"..HEAD | wc -l` + v=`echo "$v" | sed "s/\(.*\)-\(.*\)/\1-$numcommits-\2/"`; + ;; + esac + + # Change the first '-' to a '.', so version-comparing tools work properly. + # Remove the "g" in git describe's output string, to save a byte. + v=`echo "$v" | sed 's/-/./;s/\(.*\)-g/\1-/'`; +else + v=UNKNOWN +fi + +v=`echo "$v" |sed 's/^v//'` + +# Don't declare a version "dirty" merely because a time stamp has changed. +git status > /dev/null 2>&1 + +dirty=`sh -c 'git diff-index --name-only HEAD' 2>/dev/null` || dirty= +case "$dirty" in + '') ;; + *) # Append the suffix only if there isn't one already. + case $v in + *-dirty) ;; + *) v="$v-dirty" ;; + esac ;; +esac + +# Omit the trailing newline, so that m4_esyscmd can use the result directly. +echo "$v" | tr -d '\012' + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/host/include/Makefile.am b/host/include/Makefile.am new file mode 100644 index 0000000..4222484 --- /dev/null +++ b/host/include/Makefile.am @@ -0,0 +1,7 @@ +nobase_include_HEADERS = \ + osmocom/simtrace2/apdu_dispatch.h \ + osmocom/simtrace2/libusb_util.h \ + osmocom/simtrace2/simtrace2_api.h \ + osmocom/simtrace2/simtrace_usb.h \ + osmocom/simtrace2/simtrace_prot.h \ + osmocom/simtrace2/gsmtap.h diff --git a/host/apdu_dispatch.h b/host/include/osmocom/simtrace2/apdu_dispatch.h similarity index 100% rename from host/apdu_dispatch.h rename to host/include/osmocom/simtrace2/apdu_dispatch.h diff --git a/host/include/osmocom/simtrace2/gsmtap.h b/host/include/osmocom/simtrace2/gsmtap.h new file mode 100644 index 0000000..d7184dc --- /dev/null +++ b/host/include/osmocom/simtrace2/gsmtap.h @@ -0,0 +1,6 @@ +#pragma once +#include <stdint.h> +#include <osmocom/core/gsmtap.h> + +int osmo_st2_gsmtap_init(const char *gsmtap_host); +int osmo_st2_gsmtap_send_apdu(uint8_t sub_type, const uint8_t *apdu, unsigned int len); diff --git a/host/libusb_util.h b/host/include/osmocom/simtrace2/libusb_util.h similarity index 100% rename from host/libusb_util.h rename to host/include/osmocom/simtrace2/libusb_util.h diff --git a/host/include/osmocom/simtrace2/simtrace2_api.h b/host/include/osmocom/simtrace2/simtrace2_api.h new file mode 100644 index 0000000..5a9f4a3 --- /dev/null +++ b/host/include/osmocom/simtrace2/simtrace2_api.h @@ -0,0 +1,52 @@ +#pragma once + +#include <stdint.h> +#include <osmocom/sim/sim.h> + +/* transport to a SIMtrace device */ +struct st_transport { + /* USB */ + struct libusb_device_handle *usb_devh; + struct { + uint8_t in; + uint8_t out; + uint8_t irq_in; + } usb_ep; + + /* UDP */ + int udp_fd; +}; + +/* a SIMtrace slot; communicates over a transport */ +struct st_slot { + /* transport through which the slot can be reached */ + struct st_transport *transp; + /* number of the slot within the transport */ + uint8_t slot_nr; +}; + +/* One istance of card emulation */ +struct cardem_inst { + /* slot on which this card emulation instance runs */ + struct st_slot *slot; + /* libosmosim SIM card profile */ + const struct osim_cla_ins_card_profile *card_prof; + /* libosmosim SIM card channel */ + struct osim_chan_hdl *chan; +}; + + +int cardem_request_card_insert(struct cardem_inst *ci, bool inserted); +int cardem_request_pb_and_rx(struct cardem_inst *ci, uint8_t pb, uint8_t le); +int cardem_request_pb_and_tx(struct cardem_inst *ci, uint8_t pb, + const uint8_t *data, uint16_t data_len_in); +int cardem_request_sw_tx(struct cardem_inst *ci, const uint8_t *sw); +int cardem_request_set_atr(struct cardem_inst *ci, const uint8_t *atr, unsigned int atr_len); + + +int st_modem_reset_pulse(struct st_slot *slot, uint16_t duration_ms); +int st_modem_reset_active(struct st_slot *slot); +int st_modem_reset_inactive(struct st_slot *slot); +int st_modem_sim_select_local(struct st_slot *slot); +int st_modem_sim_select_remote(struct st_slot *slot); +int st_modem_get_status(struct st_slot *slot); diff --git a/host/include/osmocom/simtrace2/simtrace_prot.h b/host/include/osmocom/simtrace2/simtrace_prot.h new file mode 120000 index 0000000..cf485f3 --- /dev/null +++ b/host/include/osmocom/simtrace2/simtrace_prot.h @@ -0,0 +1 @@ +../../../../firmware/libcommon/include/simtrace_prot.h \ No newline at end of file diff --git a/host/include/osmocom/simtrace2/simtrace_usb.h b/host/include/osmocom/simtrace2/simtrace_usb.h new file mode 120000 index 0000000..ec0c021 --- /dev/null +++ b/host/include/osmocom/simtrace2/simtrace_usb.h @@ -0,0 +1 @@ +../../../../firmware/libcommon/include/simtrace_usb.h \ No newline at end of file diff --git a/host/lib/Makefile.am b/host/lib/Makefile.am new file mode 100644 index 0000000..8416923 --- /dev/null +++ b/host/lib/Makefile.am @@ -0,0 +1,19 @@ +# This is _NOT_ the library release version, it's an API version. +# Please read chapter "Library interface versions" of the libtool documentation +# before making any modifications: https://www.gnu.org/software/libtool/manual/html_node/Versioning.html +ST2_LIBVERSION=0:0:0 + +AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir) +AM_CFLAGS= -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOSIM_CFLAGS) $(LIBUSB_CFLAGS) $(COVERAGE_CFLAGS) +AM_LDFLAGS = $(COVERAGE_LDFLAGS) +COMMONLIBS = $(LIBOSMOCORE_LIBS) $(LIBOSMOSIM_LIBS) $(LIBUSB_LIBS) + +lib_LTLIBRARIES = libosmo-simtrace2.la + +libosmo_simtrace2_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(ST2_LIBVERSION) +libosmo_simtrace2_la_LIBADD = $(COMMONLIBS) +libosmo_simtrace2_la_SOURCES = \ + apdu_dispatch.c \ + gsmtap.c \ + libusb_util.c \ + simtrace2_api.c diff --git a/host/apdu_dispatch.c b/host/lib/apdu_dispatch.c similarity index 98% rename from host/apdu_dispatch.c rename to host/lib/apdu_dispatch.c index 7c7ed01..ae892eb 100644 --- a/host/apdu_dispatch.c +++ b/host/lib/apdu_dispatch.c @@ -27,7 +27,7 @@ #include <osmocom/sim/sim.h> #include <osmocom/sim/class_tables.h> -#include "apdu_dispatch.h" +#include <osmocom/simtrace2/apdu_dispatch.h> /*! \brief Has the command-data phase been completed yet? */ static inline bool is_dc_complete(struct apdu_context *ac) diff --git a/host/lib/gsmtap.c b/host/lib/gsmtap.c new file mode 100644 index 0000000..d5575e0 --- /dev/null +++ b/host/lib/gsmtap.c @@ -0,0 +1,57 @@ +#include <osmocom/simtrace2/gsmtap.h> + +#include <osmocom/core/gsmtap.h> +#include <osmocom/core/gsmtap_util.h> + +#include <errno.h> +#include <string.h> +#include <unistd.h> +#include <stdio.h> + +/* global GSMTAP instance */ +static struct gsmtap_inst *g_gti; + +int osmo_st2_gsmtap_init(const char *gsmtap_host) +{ + if (g_gti) + return -EEXIST; + + g_gti = gsmtap_source_init(gsmtap_host, GSMTAP_UDP_PORT, 0); + if (!g_gti) { + perror("unable to open GSMTAP"); + return -EIO; + } + gsmtap_source_add_sink(g_gti); + + return 0; +} + +int osmo_st2_gsmtap_send_apdu(uint8_t sub_type, const uint8_t *apdu, unsigned int len) +{ + struct gsmtap_hdr *gh; + unsigned int gross_len = len + sizeof(*gh); + uint8_t *buf = malloc(gross_len); + int rc; + + if (!buf) + return -ENOMEM; + + memset(buf, 0, sizeof(*gh)); + gh = (struct gsmtap_hdr *) buf; + gh->version = GSMTAP_VERSION; + gh->hdr_len = sizeof(*gh)/4; + gh->type = GSMTAP_TYPE_SIM; + gh->sub_type = sub_type; + + memcpy(buf + sizeof(*gh), apdu, len); + + rc = write(gsmtap_inst_fd(g_gti), buf, gross_len); + if (rc < 0) { + perror("write gsmtap"); + free(buf); + return rc; + } + + free(buf); + return 0; +} diff --git a/host/libusb_util.c b/host/lib/libusb_util.c similarity index 98% rename from host/libusb_util.c rename to host/lib/libusb_util.c index 71fb488..d88b043 100644 --- a/host/libusb_util.c +++ b/host/lib/libusb_util.c @@ -1,6 +1,6 @@ /* libusb utilities * - * (C) 2010-2016 by Harald Welte <hwelte at hmw-consulting.de> + * (C) 2010-2019 by Harald Welte <hwelte at 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 @@ -25,7 +25,7 @@ #include <libusb.h> -#include "libusb_util.h" +#include <osmocom/simtrace2/libusb_util.h> static char path_buf[USB_MAX_PATH_LEN]; diff --git a/host/lib/simtrace2_api.c b/host/lib/simtrace2_api.c new file mode 100644 index 0000000..0d48b8e --- /dev/null +++ b/host/lib/simtrace2_api.c @@ -0,0 +1,281 @@ + +/* simtrace2-protocol - USB protocol library code for SIMtrace2 + * + * (C) 2016-2019 by Harald Welte <hwelte at hmw-consulting.de> + * (C) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon at sysmocom.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. + * + * 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 <errno.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <signal.h> +#include <time.h> +#define _GNU_SOURCE +#include <getopt.h> + +#include <sys/time.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <libusb.h> + +//#include <osmocom/simtrace2/libusb_util.h> +#include <osmocom/simtrace2/simtrace_prot.h> +#include <osmocom/simtrace2/simtrace2_api.h> +//#include "apdu_dispatch.h" +//#include "simtrace2-discovery.h" + +#include <osmocom/core/utils.h> +#include <osmocom/core/socket.h> +#include <osmocom/core/msgb.h> +#include <osmocom/sim/class_tables.h> +#include <osmocom/sim/sim.h> + +/*********************************************************************** + * SIMTRACE core protocol + ***********************************************************************/ + +/*! \brief allocate a message buffer for simtrace use */ +static struct msgb *st_msgb_alloc(void) +{ + return msgb_alloc_headroom(1024+32, 32, "SIMtrace"); +} + +#if 0 +static void apdu_out_cb(uint8_t *buf, unsigned int len, void *user_data) +{ + printf("APDU: %s\n", osmo_hexdump(buf, len)); + gsmtap_send_sim(buf, len); +} +#endif + +/*! \brief Transmit a given command to the SIMtrace2 device */ +int st_transp_tx_msg(struct st_transport *transp, struct msgb *msg) +{ + int rc; + + printf("<- %s\n", msgb_hexdump(msg)); + + if (transp->udp_fd < 0) { + int xfer_len; + + rc = libusb_bulk_transfer(transp->usb_devh, transp->usb_ep.out, + msgb_data(msg), msgb_length(msg), + &xfer_len, 100000); + } else { + rc = write(transp->udp_fd, msgb_data(msg), msgb_length(msg)); + } + + msgb_free(msg); + return rc; +} + +static struct simtrace_msg_hdr *st_push_hdr(struct msgb *msg, uint8_t msg_class, uint8_t msg_type, + uint8_t slot_nr) +{ + struct simtrace_msg_hdr *sh; + + sh = (struct simtrace_msg_hdr *) msgb_push(msg, sizeof(*sh)); + memset(sh, 0, sizeof(*sh)); + sh->msg_class = msg_class; + sh->msg_type = msg_type; + sh->slot_nr = slot_nr; + sh->msg_len = msgb_length(msg); + + return sh; +} + +/* transmit a given message to a specified slot. Expects all headers + * present before calling the function */ +int st_slot_tx_msg(struct st_slot *slot, struct msgb *msg, + uint8_t msg_class, uint8_t msg_type) +{ + st_push_hdr(msg, msg_class, msg_type, slot->slot_nr); + + return st_transp_tx_msg(slot->transp, msg); +} + +/*********************************************************************** + * Card Emulation protocol + ***********************************************************************/ + + +/*! \brief Request the SIMtrace2 to generate a card-insert signal */ +int cardem_request_card_insert(struct cardem_inst *ci, bool inserted) +{ + struct msgb *msg = st_msgb_alloc(); + struct cardemu_usb_msg_cardinsert *cins; + + cins = (struct cardemu_usb_msg_cardinsert *) msgb_put(msg, sizeof(*cins)); + memset(cins, 0, sizeof(*cins)); + if (inserted) + cins->card_insert = 1; + + return st_slot_tx_msg(ci->slot, msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DT_CEMU_CARDINSERT); +} + +/*! \brief Request the SIMtrace2 to transmit a Procedure Byte, then Rx */ +int cardem_request_pb_and_rx(struct cardem_inst *ci, uint8_t pb, uint8_t le) +{ + struct msgb *msg = st_msgb_alloc(); + struct cardemu_usb_msg_tx_data *txd; + txd = (struct cardemu_usb_msg_tx_data *) msgb_put(msg, sizeof(*txd)); + + printf("<= %s(%02x, %d)\n", __func__, pb, le); + + memset(txd, 0, sizeof(*txd)); + txd->data_len = 1; + txd->flags = CEMU_DATA_F_PB_AND_RX; + /* one data byte */ + msgb_put_u8(msg, pb); + + return st_slot_tx_msg(ci->slot, msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DT_CEMU_TX_DATA); +} + +/*! \brief Request the SIMtrace2 to transmit a Procedure Byte, then Tx */ +int cardem_request_pb_and_tx(struct cardem_inst *ci, uint8_t pb, + const uint8_t *data, uint16_t data_len_in) +{ + struct msgb *msg = st_msgb_alloc(); + struct cardemu_usb_msg_tx_data *txd; + uint8_t *cur; + + txd = (struct cardemu_usb_msg_tx_data *) msgb_put(msg, sizeof(*txd)); + + printf("<= %s(%02x, %s, %d)\n", __func__, pb, + osmo_hexdump(data, data_len_in), data_len_in); + + memset(txd, 0, sizeof(*txd)); + txd->data_len = 1 + data_len_in; + txd->flags = CEMU_DATA_F_PB_AND_TX; + /* procedure byte */ + msgb_put_u8(msg, pb); + /* data */ + cur = msgb_put(msg, data_len_in); + memcpy(cur, data, data_len_in); + + return st_slot_tx_msg(ci->slot, msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DT_CEMU_TX_DATA); +} + +/*! \brief Request the SIMtrace2 to send a Status Word */ +int cardem_request_sw_tx(struct cardem_inst *ci, const uint8_t *sw) +{ + struct msgb *msg = st_msgb_alloc(); + struct cardemu_usb_msg_tx_data *txd; + uint8_t *cur; + + txd = (struct cardemu_usb_msg_tx_data *) msgb_put(msg, sizeof(*txd)); + + printf("<= %s(%02x %02x)\n", __func__, sw[0], sw[1]); + + memset(txd, 0, sizeof(*txd)); + txd->data_len = 2; + txd->flags = CEMU_DATA_F_PB_AND_TX | CEMU_DATA_F_FINAL; + cur = msgb_put(msg, 2); + cur[0] = sw[0]; + cur[1] = sw[1]; + + return st_slot_tx_msg(ci->slot, msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DT_CEMU_TX_DATA); +} + +int cardem_request_set_atr(struct cardem_inst *ci, const uint8_t *atr, unsigned int atr_len) +{ + struct msgb *msg = st_msgb_alloc(); + struct cardemu_usb_msg_set_atr *satr; + uint8_t *cur; + + satr = (struct cardemu_usb_msg_set_atr *) msgb_put(msg, sizeof(*satr)); + + printf("<= %s(%s)\n", __func__, osmo_hexdump(atr, atr_len)); + + memset(satr, 0, sizeof(*satr)); + satr->atr_len = atr_len; + cur = msgb_put(msg, atr_len); + memcpy(cur, atr, atr_len); + + return st_slot_tx_msg(ci->slot, msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DT_CEMU_SET_ATR); +} + +/*********************************************************************** + * Modem Control protocol + ***********************************************************************/ + +static int _modem_reset(struct st_slot *slot, uint8_t asserted, uint16_t pulse_ms) +{ + struct msgb *msg = st_msgb_alloc(); + struct st_modem_reset *sr ; + + sr = (struct st_modem_reset *) msgb_put(msg, sizeof(*sr)); + sr->asserted = asserted; + sr->pulse_duration_msec = pulse_ms; + + return st_slot_tx_msg(slot, msg, SIMTRACE_MSGC_MODEM, SIMTRACE_MSGT_DT_MODEM_RESET); +} + +/*! \brief pulse the RESET line of the modem for \a duration_ms milli-seconds*/ +int st_modem_reset_pulse(struct st_slot *slot, uint16_t duration_ms) +{ + return _modem_reset(slot, 2, duration_ms); +} + +/*! \brief assert the RESET line of the modem */ +int st_modem_reset_active(struct st_slot *slot) +{ + return _modem_reset(slot, 1, 0); +} + +/*! \brief de-assert the RESET line of the modem */ +int st_modem_reset_inactive(struct st_slot *slot) +{ + return _modem_reset(slot, 0, 0); +} + +static int _modem_sim_select(struct st_slot *slot, uint8_t remote_sim) +{ + struct msgb *msg = st_msgb_alloc(); + struct st_modem_sim_select *ss; + + ss = (struct st_modem_sim_select *) msgb_put(msg, sizeof(*ss)); + ss->remote_sim = remote_sim; + + return st_slot_tx_msg(slot, msg, SIMTRACE_MSGC_MODEM, SIMTRACE_MSGT_DT_MODEM_SIM_SELECT); +} + +/*! \brief select local (physical) SIM for given slot */ +int st_modem_sim_select_local(struct st_slot *slot) +{ + return _modem_sim_select(slot, 0); +} + +/*! \brief select remote (emulated/forwarded) SIM for given slot */ +int st_modem_sim_select_remote(struct st_slot *slot) +{ + return _modem_sim_select(slot, 1); +} + +/*! \brief Request slot to send us status information about the modem */ +int st_modem_get_status(struct st_slot *slot) +{ + struct msgb *msg = st_msgb_alloc(); + + return st_slot_tx_msg(slot, msg, SIMTRACE_MSGC_MODEM, SIMTRACE_MSGT_BD_MODEM_STATUS); +} diff --git a/host/libosmo-simtrace2.pc.in b/host/libosmo-simtrace2.pc.in new file mode 100644 index 0000000..6e9f6f2 --- /dev/null +++ b/host/libosmo-simtrace2.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: Osmocom SIMtrace2 library +Description: Library for SIM Card / Smart Card tracing + emulation +Version: @VERSION@ +Libs: -L${libdir} -losmo-simtrace2 +Cflags: -I${includedir}/ diff --git a/host/simtrace.h b/host/simtrace.h deleted file mode 100644 index c4a20da..0000000 --- a/host/simtrace.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _SIMTRACE_H -#define _SIMTRACE_H - -#define SIMTRACE_USB_VENDOR 0x1d50 -#define SIMTRACE_USB_PRODUCT 0x60e3 - -#endif diff --git a/host/simtrace2-remsim.c b/host/simtrace2-remsim.c deleted file mode 100644 index 918c9fd..0000000 --- a/host/simtrace2-remsim.c +++ /dev/null @@ -1,758 +0,0 @@ -/* simtrace2-remsim - main program for the host PC to provide a remote SIM - * using the SIMtrace 2 firmware in card emulation mode - * - * (C) 2016-2017 by Harald Welte <hwelte at hmw-consulting.de> - * (C) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon at sysmocom.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. - * - * 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 <errno.h> -#include <unistd.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <stdint.h> -#include <signal.h> -#include <time.h> -#define _GNU_SOURCE -#include <getopt.h> - -#include <sys/time.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> - -#include <libusb.h> - -#include "libusb_util.h" -#include "simtrace.h" -#include "simtrace_prot.h" -#include "apdu_dispatch.h" -#include "simtrace2-discovery.h" - -#include <osmocom/core/gsmtap.h> -#include <osmocom/core/gsmtap_util.h> -#include <osmocom/core/utils.h> -#include <osmocom/core/socket.h> -#include <osmocom/core/msgb.h> -#include <osmocom/sim/class_tables.h> -#include <osmocom/sim/sim.h> - -/* transport to a SIMtrace device */ -struct st_transport { - /* USB */ - struct libusb_device_handle *usb_devh; - struct { - uint8_t in; - uint8_t out; - uint8_t irq_in; - } usb_ep; - - /* UDP */ - int udp_fd; -}; - -/* a SIMtrace slot; communicates over a transport */ -struct st_slot { - /* transport through which the slot can be reached */ - struct st_transport *transp; - /* number of the slot within the transport */ - uint8_t slot_nr; -}; - -/* One istance of card emulation */ -struct cardem_inst { - /* slot on which this card emulation instance runs */ - struct st_slot *slot; - /* libosmosim SIM card profile */ - const struct osim_cla_ins_card_profile *card_prof; - /* libosmosim SIM card channel */ - struct osim_chan_hdl *chan; -}; - -/* global GSMTAP instance */ -static struct gsmtap_inst *g_gti; - -static int gsmtap_send_sim(const uint8_t *apdu, unsigned int len) -{ - struct gsmtap_hdr *gh; - unsigned int gross_len = len + sizeof(*gh); - uint8_t *buf = malloc(gross_len); - int rc; - - if (!buf) - return -ENOMEM; - - memset(buf, 0, sizeof(*gh)); - gh = (struct gsmtap_hdr *) buf; - gh->version = GSMTAP_VERSION; - gh->hdr_len = sizeof(*gh)/4; - gh->type = GSMTAP_TYPE_SIM; - - memcpy(buf + sizeof(*gh), apdu, len); - - rc = write(gsmtap_inst_fd(g_gti), buf, gross_len); - if (rc < 0) { - perror("write gsmtap"); - free(buf); - return rc; - } - - free(buf); - return 0; -} - -/*********************************************************************** - * SIMTRACE pcore protocol - ***********************************************************************/ - -/*! \brief allocate a message buffer for simtrace use */ -static struct msgb *st_msgb_alloc(void) -{ - return msgb_alloc_headroom(1024+32, 32, "SIMtrace"); -} - -#if 0 -static void apdu_out_cb(uint8_t *buf, unsigned int len, void *user_data) -{ - printf("APDU: %s\n", osmo_hexdump(buf, len)); - gsmtap_send_sim(buf, len); -} -#endif - -/*! \brief Transmit a given command to the SIMtrace2 device */ -int st_transp_tx_msg(struct st_transport *transp, struct msgb *msg) -{ - int rc; - - printf("<- %s\n", msgb_hexdump(msg)); - - if (transp->udp_fd < 0) { - int xfer_len; - - rc = libusb_bulk_transfer(transp->usb_devh, transp->usb_ep.out, - msgb_data(msg), msgb_length(msg), - &xfer_len, 100000); - } else { - rc = write(transp->udp_fd, msgb_data(msg), msgb_length(msg)); - } - - msgb_free(msg); - return rc; -} - -static struct simtrace_msg_hdr *st_push_hdr(struct msgb *msg, uint8_t msg_class, uint8_t msg_type, - uint8_t slot_nr) -{ - struct simtrace_msg_hdr *sh; - - sh = (struct simtrace_msg_hdr *) msgb_push(msg, sizeof(*sh)); - memset(sh, 0, sizeof(*sh)); - sh->msg_class = msg_class; - sh->msg_type = msg_type; - sh->slot_nr = slot_nr; - sh->msg_len = msgb_length(msg); - - return sh; -} - -/* transmit a given message to a specified slot. Expects all headers - * present before calling the function */ -int st_slot_tx_msg(struct st_slot *slot, struct msgb *msg, - uint8_t msg_class, uint8_t msg_type) -{ - st_push_hdr(msg, msg_class, msg_type, slot->slot_nr); - - return st_transp_tx_msg(slot->transp, msg); -} - -/*********************************************************************** - * Card Emulation protocol - ***********************************************************************/ - - -/*! \brief Request the SIMtrace2 to generate a card-insert signal */ -static int cardem_request_card_insert(struct cardem_inst *ci, bool inserted) -{ - struct msgb *msg = st_msgb_alloc(); - struct cardemu_usb_msg_cardinsert *cins; - - cins = (struct cardemu_usb_msg_cardinsert *) msgb_put(msg, sizeof(*cins)); - memset(cins, 0, sizeof(*cins)); - if (inserted) - cins->card_insert = 1; - - return st_slot_tx_msg(ci->slot, msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DT_CEMU_CARDINSERT); -} - -/*! \brief Request the SIMtrace2 to transmit a Procedure Byte, then Rx */ -static int cardem_request_pb_and_rx(struct cardem_inst *ci, uint8_t pb, uint8_t le) -{ - struct msgb *msg = st_msgb_alloc(); - struct cardemu_usb_msg_tx_data *txd; - txd = (struct cardemu_usb_msg_tx_data *) msgb_put(msg, sizeof(*txd)); - - printf("<= %s(%02x, %d)\n", __func__, pb, le); - - memset(txd, 0, sizeof(*txd)); - txd->data_len = 1; - txd->flags = CEMU_DATA_F_PB_AND_RX; - /* one data byte */ - msgb_put_u8(msg, pb); - - return st_slot_tx_msg(ci->slot, msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DT_CEMU_TX_DATA); -} - -/*! \brief Request the SIMtrace2 to transmit a Procedure Byte, then Tx */ -static int cardem_request_pb_and_tx(struct cardem_inst *ci, uint8_t pb, - const uint8_t *data, uint16_t data_len_in) -{ - struct msgb *msg = st_msgb_alloc(); - struct cardemu_usb_msg_tx_data *txd; - uint8_t *cur; - - txd = (struct cardemu_usb_msg_tx_data *) msgb_put(msg, sizeof(*txd)); - - printf("<= %s(%02x, %s, %d)\n", __func__, pb, - osmo_hexdump(data, data_len_in), data_len_in); - - memset(txd, 0, sizeof(*txd)); - txd->data_len = 1 + data_len_in; - txd->flags = CEMU_DATA_F_PB_AND_TX; - /* procedure byte */ - msgb_put_u8(msg, pb); - /* data */ - cur = msgb_put(msg, data_len_in); - memcpy(cur, data, data_len_in); - - return st_slot_tx_msg(ci->slot, msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DT_CEMU_TX_DATA); -} - -/*! \brief Request the SIMtrace2 to send a Status Word */ -static int cardem_request_sw_tx(struct cardem_inst *ci, const uint8_t *sw) -{ - struct msgb *msg = st_msgb_alloc(); - struct cardemu_usb_msg_tx_data *txd; - uint8_t *cur; - - txd = (struct cardemu_usb_msg_tx_data *) msgb_put(msg, sizeof(*txd)); - - printf("<= %s(%02x %02x)\n", __func__, sw[0], sw[1]); - - memset(txd, 0, sizeof(*txd)); - txd->data_len = 2; - txd->flags = CEMU_DATA_F_PB_AND_TX | CEMU_DATA_F_FINAL; - cur = msgb_put(msg, 2); - cur[0] = sw[0]; - cur[1] = sw[1]; - - return st_slot_tx_msg(ci->slot, msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DT_CEMU_TX_DATA); -} - -static void atr_update_csum(uint8_t *atr, unsigned int atr_len) -{ - uint8_t csum = 0; - int i; - - for (i = 1; i < atr_len - 1; i++) - csum = csum ^ atr[i]; - - atr[atr_len-1] = csum; -} - -static int cardem_request_set_atr(struct cardem_inst *ci, const uint8_t *atr, unsigned int atr_len) -{ - struct msgb *msg = st_msgb_alloc(); - struct cardemu_usb_msg_set_atr *satr; - uint8_t *cur; - - satr = (struct cardemu_usb_msg_set_atr *) msgb_put(msg, sizeof(*satr)); - - printf("<= %s(%s)\n", __func__, osmo_hexdump(atr, atr_len)); - - memset(satr, 0, sizeof(*satr)); - satr->atr_len = atr_len; - cur = msgb_put(msg, atr_len); - memcpy(cur, atr, atr_len); - - return st_slot_tx_msg(ci->slot, msg, SIMTRACE_MSGC_CARDEM, SIMTRACE_MSGT_DT_CEMU_SET_ATR); -} - -/*********************************************************************** - * Modem Control protocol - ***********************************************************************/ - -static int _modem_reset(struct st_slot *slot, uint8_t asserted, uint16_t pulse_ms) -{ - struct msgb *msg = st_msgb_alloc(); - struct st_modem_reset *sr ; - - sr = (struct st_modem_reset *) msgb_put(msg, sizeof(*sr)); - sr->asserted = asserted; - sr->pulse_duration_msec = pulse_ms; - - return st_slot_tx_msg(slot, msg, SIMTRACE_MSGC_MODEM, SIMTRACE_MSGT_DT_MODEM_RESET); -} - -/*! \brief pulse the RESET line of the modem for \a duration_ms milli-seconds*/ -int st_modem_reset_pulse(struct st_slot *slot, uint16_t duration_ms) -{ - return _modem_reset(slot, 2, duration_ms); -} - -/*! \brief assert the RESET line of the modem */ -int st_modem_reset_active(struct st_slot *slot) -{ - return _modem_reset(slot, 1, 0); -} - -/*! \brief de-assert the RESET line of the modem */ -int st_modem_reset_inactive(struct st_slot *slot) -{ - return _modem_reset(slot, 0, 0); -} - -static int _modem_sim_select(struct st_slot *slot, uint8_t remote_sim) -{ - struct msgb *msg = st_msgb_alloc(); - struct st_modem_sim_select *ss; - - ss = (struct st_modem_sim_select *) msgb_put(msg, sizeof(*ss)); - ss->remote_sim = remote_sim; - - return st_slot_tx_msg(slot, msg, SIMTRACE_MSGC_MODEM, SIMTRACE_MSGT_DT_MODEM_SIM_SELECT); -} - -/*! \brief select local (physical) SIM for given slot */ -int st_modem_sim_select_local(struct st_slot *slot) -{ - return _modem_sim_select(slot, 0); -} - -/*! \brief select remote (emulated/forwarded) SIM for given slot */ -int st_modem_sim_select_remote(struct st_slot *slot) -{ - return _modem_sim_select(slot, 1); -} - -/*! \brief Request slot to send us status information about the modem */ -int st_modem_get_status(struct st_slot *slot) -{ - struct msgb *msg = st_msgb_alloc(); - - return st_slot_tx_msg(slot, msg, SIMTRACE_MSGC_MODEM, SIMTRACE_MSGT_BD_MODEM_STATUS); -} - - -/*********************************************************************** - * Incoming Messages - ***********************************************************************/ - -/*! \brief Process a STATUS message from the SIMtrace2 */ -static int process_do_status(struct cardem_inst *ci, uint8_t *buf, int len) -{ - struct cardemu_usb_msg_status *status; - status = (struct cardemu_usb_msg_status *) buf; - - printf("=> STATUS: flags=0x%x, fi=%u, di=%u, wi=%u wtime=%u\n", - status->flags, status->fi, status->di, status->wi, - status->waiting_time); - - return 0; -} - -/*! \brief Process a PTS indication message from the SIMtrace2 */ -static int process_do_pts(struct cardem_inst *ci, uint8_t *buf, int len) -{ - struct cardemu_usb_msg_pts_info *pts; - pts = (struct cardemu_usb_msg_pts_info *) buf; - - printf("=> PTS req: %s\n", osmo_hexdump(pts->req, sizeof(pts->req))); - - return 0; -} - -/*! \brief Process a RX-DATA indication message from the SIMtrace2 */ -static int process_do_rx_da(struct cardem_inst *ci, uint8_t *buf, int len) -{ - static struct apdu_context ac; - struct cardemu_usb_msg_rx_data *data; - int rc; - - data = (struct cardemu_usb_msg_rx_data *) buf; - - printf("=> DATA: flags=%x, %s: ", data->flags, - osmo_hexdump(data->data, data->data_len)); - - rc = apdu_segment_in(&ac, data->data, data->data_len, - data->flags & CEMU_DATA_F_TPDU_HDR); - - if (rc & APDU_ACT_TX_CAPDU_TO_CARD) { - struct msgb *tmsg = msgb_alloc(1024, "TPDU"); - struct osim_reader_hdl *rh = ci->chan->card->reader; - uint8_t *cur; - - /* Copy TPDU header */ - cur = msgb_put(tmsg, sizeof(ac.hdr)); - memcpy(cur, &ac.hdr, sizeof(ac.hdr)); - /* Copy D(c), if any */ - if (ac.lc.tot) { - cur = msgb_put(tmsg, ac.lc.tot); - memcpy(cur, ac.dc, ac.lc.tot); - } - /* send to actual card */ - tmsg->l3h = tmsg->tail; - rc = rh->ops->transceive(rh, tmsg); - if (rc < 0) { - fprintf(stderr, "error during transceive: %d\n", rc); - msgb_free(tmsg); - return rc; - } - msgb_apdu_sw(tmsg) = msgb_get_u16(tmsg); - ac.sw[0] = msgb_apdu_sw(tmsg) >> 8; - ac.sw[1] = msgb_apdu_sw(tmsg) & 0xff; - printf("SW=0x%04x, len_rx=%d\n", msgb_apdu_sw(tmsg), msgb_l3len(tmsg)); - if (msgb_l3len(tmsg)) - cardem_request_pb_and_tx(ci, ac.hdr.ins, tmsg->l3h, msgb_l3len(tmsg)); - cardem_request_sw_tx(ci, ac.sw); - } else if (ac.lc.tot > ac.lc.cur) { - cardem_request_pb_and_rx(ci, ac.hdr.ins, ac.lc.tot - ac.lc.cur); - } - return 0; -} - -/*! \brief Process an incoming message from the SIMtrace2 */ -static int process_usb_msg(struct cardem_inst *ci, uint8_t *buf, int len) -{ - struct simtrace_msg_hdr *sh = (struct simtrace_msg_hdr *)buf; - int rc; - - printf("-> %s\n", osmo_hexdump(buf, len)); - - buf += sizeof(*sh); - - switch (sh->msg_type) { - case SIMTRACE_MSGT_BD_CEMU_STATUS: - rc = process_do_status(ci, buf, len); - break; - case SIMTRACE_MSGT_DO_CEMU_PTS: - rc = process_do_pts(ci, buf, len); - break; - case SIMTRACE_MSGT_DO_CEMU_RX_DATA: - rc = process_do_rx_da(ci, buf, len); - break; - default: - printf("unknown simtrace msg type 0x%02x\n", sh->msg_type); - rc = -1; - break; - } - - return rc; -} - -static void print_welcome(void) -{ - printf("simtrace2-remsim - Remote SIM card forwarding\n" - "(C) 2010-2017, Harald Welte <laforge at gnumonks.org>\n" - "(C) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon at sysmocom.de>\n\n"); -} - -static void print_help(void) -{ - printf( "\t-r\t--remote-udp-host HOST\n" - "\t-p\t--remote-udp-port PORT\n" - "\t-h\t--help\n" - "\t-i\t--gsmtap-ip\tA.B.C.D\n" - "\t-a\t--skip-atr\n" - "\t-k\t--keep-running\n" - "\t-V\t--usb-vendor\tVENDOR_ID\n" - "\t-P\t--usb-product\tPRODUCT_ID\n" - "\t-C\t--usb-config\tCONFIG_ID\n" - "\t-I\t--usb-interface\tINTERFACE_ID\n" - "\t-S\t--usb-altsetting ALTSETTING_ID\n" - "\t-A\t--usb-address\tADDRESS\n" - "\t-H\t--usb-path\tPATH\n" - "\n" - ); -} - -static const struct option opts[] = { - { "remote-udp-host", 1, 0, 'r' }, - { "remote-udp-port", 1, 0, 'p' }, - { "gsmtap-ip", 1, 0, 'i' }, - { "skip-atr", 0, 0, 'a' }, - { "help", 0, 0, 'h' }, - { "keep-running", 0, 0, 'k' }, - { "usb-vendor", 1, 0, 'V' }, - { "usb-product", 1, 0, 'P' }, - { "usb-config", 1, 0, 'C' }, - { "usb-interface", 1, 0, 'I' }, - { "usb-altsetting", 1, 0, 'S' }, - { "usb-address", 1, 0, 'A' }, - { "usb-path", 1, 0, 'H' }, - { NULL, 0, 0, 0 } -}; - -static void run_mainloop(struct cardem_inst *ci) -{ - struct st_transport *transp = ci->slot->transp; - unsigned int msg_count, byte_count = 0; - uint8_t buf[16*265]; - int xfer_len; - int rc; - - printf("Entering main loop\n"); - - while (1) { - /* read data from SIMtrace2 device (local or via USB) */ - if (transp->udp_fd < 0) { - rc = libusb_bulk_transfer(transp->usb_devh, transp->usb_ep.in, - buf, sizeof(buf), &xfer_len, 100); - if (rc < 0 && rc != LIBUSB_ERROR_TIMEOUT && - rc != LIBUSB_ERROR_INTERRUPTED && - rc != LIBUSB_ERROR_IO) { - fprintf(stderr, "BULK IN transfer error; rc=%d\n", rc); - return; - } - } else { - rc = read(transp->udp_fd, buf, sizeof(buf)); - if (rc <= 0) { - fprintf(stderr, "shor read from UDP\n"); - return; - } - xfer_len = rc; - } - /* dispatch any incoming data */ - if (xfer_len > 0) { - printf("URB: %s\n", osmo_hexdump(buf, xfer_len)); - process_usb_msg(ci, buf, xfer_len); - msg_count++; - byte_count += xfer_len; - } - } -} - -static struct st_transport _transp; - -static struct st_slot _slot = { - .transp = &_transp, - .slot_nr = 0, -}; - -struct cardem_inst _ci = { - .slot = &_slot, -}; - -struct cardem_inst *ci = &_ci; - -static void signal_handler(int signal) -{ - switch (signal) { - case SIGINT: - cardem_request_card_insert(ci, false); - exit(0); - break; - default: - break; - } -} - -int main(int argc, char **argv) -{ - struct st_transport *transp = ci->slot->transp; - char *gsmtap_host = "127.0.0.1"; - int rc; - int c, ret = 1; - int skip_atr = 0; - int keep_running = 0; - int remote_udp_port = 52342; - int if_num = 0, vendor_id = -1, product_id = -1; - int config_id = -1, altsetting = 0, addr = -1; - char *remote_udp_host = NULL; - char *path = NULL; - struct osim_reader_hdl *reader; - struct osim_card_hdl *card; - - print_welcome(); - - while (1) { - int option_index = 0; - - c = getopt_long(argc, argv, "r:p:hi:V:P:C:I:S:A:H:ak", opts, &option_index); - if (c == -1) - break; - switch (c) { - case 'r': - remote_udp_host = optarg; - break; - case 'p': - remote_udp_port = atoi(optarg); - break; - case 'h': - print_help(); - exit(0); - break; - case 'i': - gsmtap_host = optarg; - break; - case 'a': - skip_atr = 1; - break; - case 'k': - keep_running = 1; - break; - case 'V': - vendor_id = strtol(optarg, NULL, 16); - break; - case 'P': - product_id = strtol(optarg, NULL, 16); - break; - case 'C': - config_id = atoi(optarg); - break; - case 'I': - if_num = atoi(optarg); - break; - case 'S': - altsetting = atoi(optarg); - break; - case 'A': - addr = atoi(optarg); - break; - case 'H': - path = optarg; - break; - } - } - - if (!remote_udp_host && (vendor_id < 0 || product_id < 0)) { - fprintf(stderr, "You have to specify the vendor and product ID\n"); - goto do_exit; - } - - transp->udp_fd = -1; - - ci->card_prof = &osim_uicc_sim_cic_profile; - - if (!remote_udp_host) { - rc = libusb_init(NULL); - if (rc < 0) { - fprintf(stderr, "libusb initialization failed\n"); - goto do_exit; - } - } else { - transp->udp_fd = osmo_sock_init(AF_INET, SOCK_DGRAM, IPPROTO_UDP, - remote_udp_host, remote_udp_port+if_num, - OSMO_SOCK_F_CONNECT); - if (transp->udp_fd < 0) { - fprintf(stderr, "error binding UDP port\n"); - goto do_exit; - } - } - - g_gti = gsmtap_source_init(gsmtap_host, GSMTAP_UDP_PORT, 0); - if (!g_gti) { - perror("unable to open GSMTAP"); - goto close_exit; - } - gsmtap_source_add_sink(g_gti); - - reader = osim_reader_open(OSIM_READER_DRV_PCSC, 0, "", NULL); - if (!reader) { - perror("unable to open PC/SC reader"); - goto close_exit; - } - - card = osim_card_open(reader, OSIM_PROTO_T0); - if (!card) { - perror("unable to open SIM card"); - goto close_exit; - } - - ci->chan = llist_entry(card->channels.next, struct osim_chan_hdl, list); - if (!ci->chan) { - perror("SIM card has no channel?!?"); - goto close_exit; - } - - signal(SIGINT, &signal_handler); - - do { - if (transp->udp_fd < 0) { - struct usb_interface_match _ifm, *ifm = &_ifm; - ifm->vendor = vendor_id; - ifm->product = product_id; - ifm->configuration = config_id; - ifm->interface = if_num; - ifm->altsetting = altsetting; - ifm->addr = addr; - if (path) - osmo_strlcpy(ifm->path, path, sizeof(ifm->path)); - transp->usb_devh = usb_open_claim_interface(NULL, ifm); - if (!transp->usb_devh) { - fprintf(stderr, "can't open USB device\n"); - goto close_exit; - } - - rc = libusb_claim_interface(transp->usb_devh, if_num); - if (rc < 0) { - fprintf(stderr, "can't claim interface %d; rc=%d\n", if_num, rc); - goto close_exit; - } - - rc = get_usb_ep_addrs(transp->usb_devh, if_num, &transp->usb_ep.out, - &transp->usb_ep.in, &transp->usb_ep.irq_in); - if (rc < 0) { - fprintf(stderr, "can't obtain EP addrs; rc=%d\n", rc); - goto close_exit; - } - } - - /* simulate card-insert to modem (owhw, not qmod) */ - cardem_request_card_insert(ci, true); - - /* select remote (forwarded) SIM */ - st_modem_sim_select_remote(ci->slot); - - if (!skip_atr) { - /* set the ATR */ - uint8_t real_atr[] = { 0x3B, 0x9F, 0x96, 0x80, 0x1F, 0xC7, 0x80, 0x31, - 0xA0, 0x73, 0xBE, 0x21, 0x13, 0x67, 0x43, 0x20, - 0x07, 0x18, 0x00, 0x00, 0x01, 0xA5 }; - atr_update_csum(real_atr, sizeof(real_atr)); - cardem_request_set_atr(ci, real_atr, sizeof(real_atr)); - } - - /* select remote (forwarded) SIM */ - st_modem_reset_pulse(ci->slot, 300); - - run_mainloop(ci); - ret = 0; - - if (transp->udp_fd < 0) - libusb_release_interface(transp->usb_devh, 0); -close_exit: - if (transp->usb_devh) - libusb_close(transp->usb_devh); - if (keep_running) - sleep(1); - } while (keep_running); - - if (transp->udp_fd < 0) - libusb_exit(NULL); -do_exit: - return ret; -} diff --git a/host/simtrace_prot.h b/host/simtrace_prot.h deleted file mode 120000 index a9fffe1..0000000 --- a/host/simtrace_prot.h +++ /dev/null @@ -1 +0,0 @@ -../firmware/libcommon/include/simtrace_prot.h \ No newline at end of file diff --git a/host/simtrace_usb.h b/host/simtrace_usb.h deleted file mode 120000 index f1e0982..0000000 --- a/host/simtrace_usb.h +++ /dev/null @@ -1 +0,0 @@ -../firmware/libcommon/include/simtrace_usb.h \ No newline at end of file diff --git a/host/src/Makefile.am b/host/src/Makefile.am new file mode 100644 index 0000000..b0f1f91 --- /dev/null +++ b/host/src/Makefile.am @@ -0,0 +1,18 @@ +AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include +AM_CFLAGS=-Wall -g $(LIBOSMOCORE_CFLAGS) $(LIBOSMOSIM_CFLAGS) $(LIBUSB_CFLAGS) $(COVERAGE_FLAGS) +AM_LDFLAGS=$(COVERAGE_LDFLAGS) + +LDADD= $(top_builddir)/lib/libosmo-simtrace2.la \ + $(LIBOSMOCORE_LIBS) $(LIBOSMOSIM_LIBS) $(LIBUSB_LIBS) + +noinst_HEADERS = simtrace2-discovery.h + +bin_PROGRAMS = simtrace2-remsim simtrace2-remsim-usb2udp simtrace2-list simtrace2-sniff + +simtrace2_remsim_SOURCES = simtrace2-remsim.c simtrace2-discovery.c + +simtrace2_remsim_usb2udp_SOURCES = usb2udp.c simtrace2-discovery.c + +simtrace2_list_SOURCES = simtrace2_usb.c + +simtrace2_sniff_SOURCES = simtrace2-sniff.c simtrace2-discovery.c diff --git a/host/simtrace2-discovery.c b/host/src/simtrace2-discovery.c similarity index 100% rename from host/simtrace2-discovery.c rename to host/src/simtrace2-discovery.c diff --git a/host/simtrace2-discovery.h b/host/src/simtrace2-discovery.h similarity index 100% rename from host/simtrace2-discovery.h rename to host/src/simtrace2-discovery.h diff --git a/host/src/simtrace2-remsim.c b/host/src/simtrace2-remsim.c new file mode 100644 index 0000000..c76e587 --- /dev/null +++ b/host/src/simtrace2-remsim.c @@ -0,0 +1,463 @@ +/* simtrace2-remsim - main program for the host PC to provide a remote SIM + * using the SIMtrace 2 firmware in card emulation mode + * + * (C) 2016-2017 by Harald Welte <hwelte at hmw-consulting.de> + * (C) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon at sysmocom.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. + * + * 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 <errno.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <signal.h> +#include <time.h> +#define _GNU_SOURCE +#include <getopt.h> + +#include <sys/time.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <libusb.h> + +#include <osmocom/simtrace2/libusb_util.h> +#include <osmocom/simtrace2/simtrace2_api.h> +#include <osmocom/simtrace2/simtrace_prot.h> +#include <osmocom/simtrace2/apdu_dispatch.h> +#include <osmocom/simtrace2/gsmtap.h> + +#include "simtrace2-discovery.h" + +#include <osmocom/core/utils.h> +#include <osmocom/core/socket.h> +#include <osmocom/core/msgb.h> +#include <osmocom/sim/class_tables.h> +#include <osmocom/sim/sim.h> + +static void atr_update_csum(uint8_t *atr, unsigned int atr_len) +{ + uint8_t csum = 0; + int i; + + for (i = 1; i < atr_len - 1; i++) + csum = csum ^ atr[i]; + + atr[atr_len-1] = csum; +} + +/*********************************************************************** + * Incoming Messages + ***********************************************************************/ + +/*! \brief Process a STATUS message from the SIMtrace2 */ +static int process_do_status(struct cardem_inst *ci, uint8_t *buf, int len) +{ + struct cardemu_usb_msg_status *status; + status = (struct cardemu_usb_msg_status *) buf; + + printf("=> STATUS: flags=0x%x, fi=%u, di=%u, wi=%u wtime=%u\n", + status->flags, status->fi, status->di, status->wi, + status->waiting_time); + + return 0; +} + +/*! \brief Process a PTS indication message from the SIMtrace2 */ +static int process_do_pts(struct cardem_inst *ci, uint8_t *buf, int len) +{ + struct cardemu_usb_msg_pts_info *pts; + pts = (struct cardemu_usb_msg_pts_info *) buf; + + printf("=> PTS req: %s\n", osmo_hexdump(pts->req, sizeof(pts->req))); + + return 0; +} + +/*! \brief Process a RX-DATA indication message from the SIMtrace2 */ +static int process_do_rx_da(struct cardem_inst *ci, uint8_t *buf, int len) +{ + static struct apdu_context ac; + struct cardemu_usb_msg_rx_data *data; + int rc; + + data = (struct cardemu_usb_msg_rx_data *) buf; + + printf("=> DATA: flags=%x, %s: ", data->flags, + osmo_hexdump(data->data, data->data_len)); + + rc = apdu_segment_in(&ac, data->data, data->data_len, + data->flags & CEMU_DATA_F_TPDU_HDR); + + if (rc & APDU_ACT_TX_CAPDU_TO_CARD) { + struct msgb *tmsg = msgb_alloc(1024, "TPDU"); + struct osim_reader_hdl *rh = ci->chan->card->reader; + uint8_t *cur; + + /* Copy TPDU header */ + cur = msgb_put(tmsg, sizeof(ac.hdr)); + memcpy(cur, &ac.hdr, sizeof(ac.hdr)); + /* Copy D(c), if any */ + if (ac.lc.tot) { + cur = msgb_put(tmsg, ac.lc.tot); + memcpy(cur, ac.dc, ac.lc.tot); + } + /* send to actual card */ + tmsg->l3h = tmsg->tail; + rc = rh->ops->transceive(rh, tmsg); + if (rc < 0) { + fprintf(stderr, "error during transceive: %d\n", rc); + msgb_free(tmsg); + return rc; + } + msgb_apdu_sw(tmsg) = msgb_get_u16(tmsg); + ac.sw[0] = msgb_apdu_sw(tmsg) >> 8; + ac.sw[1] = msgb_apdu_sw(tmsg) & 0xff; + printf("SW=0x%04x, len_rx=%d\n", msgb_apdu_sw(tmsg), msgb_l3len(tmsg)); + if (msgb_l3len(tmsg)) + cardem_request_pb_and_tx(ci, ac.hdr.ins, tmsg->l3h, msgb_l3len(tmsg)); + cardem_request_sw_tx(ci, ac.sw); + } else if (ac.lc.tot > ac.lc.cur) { + cardem_request_pb_and_rx(ci, ac.hdr.ins, ac.lc.tot - ac.lc.cur); + } + return 0; +} + +/*! \brief Process an incoming message from the SIMtrace2 */ +static int process_usb_msg(struct cardem_inst *ci, uint8_t *buf, int len) +{ + struct simtrace_msg_hdr *sh = (struct simtrace_msg_hdr *)buf; + int rc; + + printf("-> %s\n", osmo_hexdump(buf, len)); + + buf += sizeof(*sh); + + switch (sh->msg_type) { + case SIMTRACE_MSGT_BD_CEMU_STATUS: + rc = process_do_status(ci, buf, len); + break; + case SIMTRACE_MSGT_DO_CEMU_PTS: + rc = process_do_pts(ci, buf, len); + break; + case SIMTRACE_MSGT_DO_CEMU_RX_DATA: + rc = process_do_rx_da(ci, buf, len); + break; + default: + printf("unknown simtrace msg type 0x%02x\n", sh->msg_type); + rc = -1; + break; + } + + return rc; +} + +static void print_welcome(void) +{ + printf("simtrace2-remsim - Remote SIM card forwarding\n" + "(C) 2010-2017, Harald Welte <laforge at gnumonks.org>\n" + "(C) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon at sysmocom.de>\n\n"); +} + +static void print_help(void) +{ + printf( "\t-r\t--remote-udp-host HOST\n" + "\t-p\t--remote-udp-port PORT\n" + "\t-h\t--help\n" + "\t-i\t--gsmtap-ip\tA.B.C.D\n" + "\t-a\t--skip-atr\n" + "\t-k\t--keep-running\n" + "\t-V\t--usb-vendor\tVENDOR_ID\n" + "\t-P\t--usb-product\tPRODUCT_ID\n" + "\t-C\t--usb-config\tCONFIG_ID\n" + "\t-I\t--usb-interface\tINTERFACE_ID\n" + "\t-S\t--usb-altsetting ALTSETTING_ID\n" + "\t-A\t--usb-address\tADDRESS\n" + "\t-H\t--usb-path\tPATH\n" + "\n" + ); +} + +static const struct option opts[] = { + { "remote-udp-host", 1, 0, 'r' }, + { "remote-udp-port", 1, 0, 'p' }, + { "gsmtap-ip", 1, 0, 'i' }, + { "skip-atr", 0, 0, 'a' }, + { "help", 0, 0, 'h' }, + { "keep-running", 0, 0, 'k' }, + { "usb-vendor", 1, 0, 'V' }, + { "usb-product", 1, 0, 'P' }, + { "usb-config", 1, 0, 'C' }, + { "usb-interface", 1, 0, 'I' }, + { "usb-altsetting", 1, 0, 'S' }, + { "usb-address", 1, 0, 'A' }, + { "usb-path", 1, 0, 'H' }, + { NULL, 0, 0, 0 } +}; + +static void run_mainloop(struct cardem_inst *ci) +{ + struct st_transport *transp = ci->slot->transp; + unsigned int msg_count, byte_count = 0; + uint8_t buf[16*265]; + int xfer_len; + int rc; + + printf("Entering main loop\n"); + + while (1) { + /* read data from SIMtrace2 device (local or via USB) */ + if (transp->udp_fd < 0) { + rc = libusb_bulk_transfer(transp->usb_devh, transp->usb_ep.in, + buf, sizeof(buf), &xfer_len, 100); + if (rc < 0 && rc != LIBUSB_ERROR_TIMEOUT && + rc != LIBUSB_ERROR_INTERRUPTED && + rc != LIBUSB_ERROR_IO) { + fprintf(stderr, "BULK IN transfer error; rc=%d\n", rc); + return; + } + } else { + rc = read(transp->udp_fd, buf, sizeof(buf)); + if (rc <= 0) { + fprintf(stderr, "shor read from UDP\n"); + return; + } + xfer_len = rc; + } + /* dispatch any incoming data */ + if (xfer_len > 0) { + printf("URB: %s\n", osmo_hexdump(buf, xfer_len)); + process_usb_msg(ci, buf, xfer_len); + msg_count++; + byte_count += xfer_len; + } + } +} + +static struct st_transport _transp; + +static struct st_slot _slot = { + .transp = &_transp, + .slot_nr = 0, +}; + +struct cardem_inst _ci = { + .slot = &_slot, +}; + +struct cardem_inst *ci = &_ci; + +static void signal_handler(int signal) +{ + switch (signal) { + case SIGINT: + cardem_request_card_insert(ci, false); + exit(0); + break; + default: + break; + } +} + +int main(int argc, char **argv) +{ + struct st_transport *transp = ci->slot->transp; + char *gsmtap_host = "127.0.0.1"; + int rc; + int c, ret = 1; + int skip_atr = 0; + int keep_running = 0; + int remote_udp_port = 52342; + int if_num = 0, vendor_id = -1, product_id = -1; + int config_id = -1, altsetting = 0, addr = -1; + char *remote_udp_host = NULL; + char *path = NULL; + struct osim_reader_hdl *reader; + struct osim_card_hdl *card; + + print_welcome(); + + while (1) { + int option_index = 0; + + c = getopt_long(argc, argv, "r:p:hi:V:P:C:I:S:A:H:ak", opts, &option_index); + if (c == -1) + break; + switch (c) { + case 'r': + remote_udp_host = optarg; + break; + case 'p': + remote_udp_port = atoi(optarg); + break; + case 'h': + print_help(); + exit(0); + break; + case 'i': + gsmtap_host = optarg; + break; + case 'a': + skip_atr = 1; + break; + case 'k': + keep_running = 1; + break; + case 'V': + vendor_id = strtol(optarg, NULL, 16); + break; + case 'P': + product_id = strtol(optarg, NULL, 16); + break; + case 'C': + config_id = atoi(optarg); + break; + case 'I': + if_num = atoi(optarg); + break; + case 'S': + altsetting = atoi(optarg); + break; + case 'A': + addr = atoi(optarg); + break; + case 'H': + path = optarg; + break; + } + } + + if (!remote_udp_host && (vendor_id < 0 || product_id < 0)) { + fprintf(stderr, "You have to specify the vendor and product ID\n"); + goto do_exit; + } + + transp->udp_fd = -1; + + ci->card_prof = &osim_uicc_sim_cic_profile; + + if (!remote_udp_host) { + rc = libusb_init(NULL); + if (rc < 0) { + fprintf(stderr, "libusb initialization failed\n"); + goto do_exit; + } + } else { + transp->udp_fd = osmo_sock_init(AF_INET, SOCK_DGRAM, IPPROTO_UDP, + remote_udp_host, remote_udp_port+if_num, + OSMO_SOCK_F_CONNECT); + if (transp->udp_fd < 0) { + fprintf(stderr, "error binding UDP port\n"); + goto do_exit; + } + } + + rc = osmo_st2_gsmtap_init(gsmtap_host); + if (rc < 0) { + perror("unable to open GSMTAP"); + goto close_exit; + } + + reader = osim_reader_open(OSIM_READER_DRV_PCSC, 0, "", NULL); + if (!reader) { + perror("unable to open PC/SC reader"); + goto close_exit; + } + + card = osim_card_open(reader, OSIM_PROTO_T0); + if (!card) { + perror("unable to open SIM card"); + goto close_exit; + } + + ci->chan = llist_entry(card->channels.next, struct osim_chan_hdl, list); + if (!ci->chan) { + perror("SIM card has no channel?!?"); + goto close_exit; + } + + signal(SIGINT, &signal_handler); + + do { + if (transp->udp_fd < 0) { + struct usb_interface_match _ifm, *ifm = &_ifm; + ifm->vendor = vendor_id; + ifm->product = product_id; + ifm->configuration = config_id; + ifm->interface = if_num; + ifm->altsetting = altsetting; + ifm->addr = addr; + if (path) + osmo_strlcpy(ifm->path, path, sizeof(ifm->path)); + transp->usb_devh = usb_open_claim_interface(NULL, ifm); + if (!transp->usb_devh) { + fprintf(stderr, "can't open USB device\n"); + goto close_exit; + } + + rc = libusb_claim_interface(transp->usb_devh, if_num); + if (rc < 0) { + fprintf(stderr, "can't claim interface %d; rc=%d\n", if_num, rc); + goto close_exit; + } + + rc = get_usb_ep_addrs(transp->usb_devh, if_num, &transp->usb_ep.out, + &transp->usb_ep.in, &transp->usb_ep.irq_in); + if (rc < 0) { + fprintf(stderr, "can't obtain EP addrs; rc=%d\n", rc); + goto close_exit; + } + } + + /* simulate card-insert to modem (owhw, not qmod) */ + cardem_request_card_insert(ci, true); + + /* select remote (forwarded) SIM */ + st_modem_sim_select_remote(ci->slot); + + if (!skip_atr) { + /* set the ATR */ + uint8_t real_atr[] = { 0x3B, 0x9F, 0x96, 0x80, 0x1F, 0xC7, 0x80, 0x31, + 0xA0, 0x73, 0xBE, 0x21, 0x13, 0x67, 0x43, 0x20, + 0x07, 0x18, 0x00, 0x00, 0x01, 0xA5 }; + atr_update_csum(real_atr, sizeof(real_atr)); + cardem_request_set_atr(ci, real_atr, sizeof(real_atr)); + } + + /* select remote (forwarded) SIM */ + st_modem_reset_pulse(ci->slot, 300); + + run_mainloop(ci); + ret = 0; + + if (transp->udp_fd < 0) + libusb_release_interface(transp->usb_devh, 0); +close_exit: + if (transp->usb_devh) + libusb_close(transp->usb_devh); + if (keep_running) + sleep(1); + } while (keep_running); + + if (transp->udp_fd < 0) + libusb_exit(NULL); +do_exit: + return ret; +} diff --git a/host/simtrace2-sniff.c b/host/src/simtrace2-sniff.c similarity index 88% rename from host/simtrace2-sniff.c rename to host/src/simtrace2-sniff.c index dddf5cf..f3c37dc 100644 --- a/host/simtrace2-sniff.c +++ b/host/src/simtrace2-sniff.c @@ -37,33 +37,19 @@ #include <libusb.h> -#include "libusb_util.h" -#include "simtrace.h" -#include "simtrace_usb.h" -#include "simtrace_prot.h" +#include <osmocom/simtrace2/libusb_util.h> +#include <osmocom/simtrace2/simtrace_usb.h> +#include <osmocom/simtrace2/simtrace_prot.h> #include "simtrace2-discovery.h" -#include <osmocom/core/gsmtap.h> -#include <osmocom/core/gsmtap_util.h> +#include <osmocom/simtrace2/gsmtap.h> + #include <osmocom/core/utils.h> #include <osmocom/core/socket.h> #include <osmocom/core/msgb.h> #include <osmocom/sim/class_tables.h> #include <osmocom/sim/sim.h> -/* as of August 26, 2018 we don't have any released libosmocore version which includes those - * definitions yet. Let's ensure some backwards compatibility: */ -#ifndef GSMTAP_SIM_APDU -#define GSMTAP_SIM_APDU 0x00 /* APDU data (complete APDU) */ -#define GSMTAP_SIM_ATR 0x01 /* card ATR data */ -#define GSMTAP_SIM_PPS_REQ 0x02 /* PPS request data */ -#define GSMTAP_SIM_PPS_RSP 0x03 /* PPS response data */ -#define GSMTAP_SIM_TPDU_HDR 0x04 /* TPDU command header */ -#define GSMTAP_SIM_TPDU_CMD 0x05 /* TPDU command body */ -#define GSMTAP_SIM_TPDU_RSP 0x06 /* TPDU response body */ -#define GSMTAP_SIM_TPDU_SW 0x07 /* TPDU response trailer */ -#endif - /* transport to a SIMtrace device */ struct st_transport { /* USB */ @@ -75,39 +61,6 @@ } usb_ep; }; -/* global GSMTAP instance */ -static struct gsmtap_inst *g_gti; - -static int gsmtap_send_sim(uint8_t sub_type, const uint8_t *data, unsigned int len) -{ - struct gsmtap_hdr *gh; - unsigned int gross_len = len + sizeof(*gh); - uint8_t *buf = malloc(gross_len); - int rc; - - if (!buf) - return -ENOMEM; - - memset(buf, 0, sizeof(*gh)); - gh = (struct gsmtap_hdr *) buf; - gh->version = GSMTAP_VERSION; - gh->hdr_len = sizeof(*gh)/4; - gh->type = GSMTAP_TYPE_SIM; - gh->sub_type = sub_type; - - memcpy(buf + sizeof(*gh), data, len); - - rc = write(gsmtap_inst_fd(g_gti), buf, gross_len); - if (rc < 0) { - perror("write gsmtap"); - free(buf); - return rc; - } - - free(buf); - return 0; -} - const struct value_string change_flags[] = { { .value = SNIFF_CHANGE_FLAG_CARD_INSERT, @@ -252,11 +205,11 @@ /* Send message as GSNTAP */ switch (type) { case SIMTRACE_MSGT_SNIFF_ATR: - gsmtap_send_sim(GSMTAP_SIM_ATR, data->data, data->length); + osmo_st2_gsmtap_send_apdu(GSMTAP_SIM_ATR, data->data, data->length); break; case SIMTRACE_MSGT_SNIFF_TPDU: /* TPDU is now considered as APDU since SIMtrace sends complete TPDU */ - gsmtap_send_sim(GSMTAP_SIM_APDU, data->data, data->length); + osmo_st2_gsmtap_send_apdu(GSMTAP_SIM_APDU, data->data, data->length); break; default: break; @@ -542,12 +495,11 @@ } printf("(%s)\n", strbuf); - g_gti = gsmtap_source_init(gsmtap_host, GSMTAP_UDP_PORT, 0); - if (!g_gti) { + rc = osmo_st2_gsmtap_init(gsmtap_host); + if (rc < 0) { perror("unable to open GSMTAP"); goto close_exit; } - gsmtap_source_add_sink(g_gti); signal(SIGINT, &signal_handler); diff --git a/host/simtrace2_usb.c b/host/src/simtrace2_usb.c similarity index 96% rename from host/simtrace2_usb.c rename to host/src/simtrace2_usb.c index 1e3104a..d31ff29 100644 --- a/host/simtrace2_usb.c +++ b/host/src/simtrace2_usb.c @@ -23,8 +23,8 @@ #include <osmocom/core/utils.h> -#include "libusb_util.h" -#include "simtrace_usb.h" +#include <osmocom/simtrace2/libusb_util.h> +#include <osmocom/simtrace2/simtrace_usb.h> static const struct dev_id compatible_dev_ids[] = { { USB_VENDOR_OPENMOKO, USB_PRODUCT_OWHW_SAM3 }, diff --git a/host/usb2udp.c b/host/src/usb2udp.c similarity index 98% rename from host/usb2udp.c rename to host/src/usb2udp.c index 97ffad0..9927594 100644 --- a/host/usb2udp.c +++ b/host/src/usb2udp.c @@ -35,9 +35,8 @@ #include <libusb.h> -#include "simtrace_usb.h" -#include "simtrace_prot.h" -#include "apdu_dispatch.h" +#include <osmocom/simtrace2/simtrace_usb.h> +#include <osmocom/simtrace2/simtrace_prot.h> #include "simtrace2-discovery.h" #include <osmocom/core/utils.h> -- To view, visit https://gerrit.osmocom.org/c/simtrace2/+/16194 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: simtrace2 Gerrit-Branch: master Gerrit-Change-Id: I57e77f927ee9e169cc794c5dc6b128a2d590201b Gerrit-Change-Number: 16194 Gerrit-PatchSet: 1 Gerrit-Owner: laforge <laforge at osmocom.org> Gerrit-MessageType: newchange -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20191124/5a7dbaa2/attachment.htm>