host: use autotools and split shared code to libosmo-simtrace2

Change-Id: I57e77f927ee9e169cc794c5dc6b128a2d590201b
This commit is contained in:
Harald Welte 2019-11-24 22:27:10 +01:00
parent 331fa5a237
commit 964cda309d
31 changed files with 791 additions and 382 deletions

View File

@ -50,9 +50,15 @@ make clean
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
@ -68,6 +74,10 @@ EOF
rsync --archive --verbose --compress --rsh "$SSH_COMMAND" --exclude $TOPDIR/firmware/bin/*-latest.{bin,elf} $TOPDIR/firmware/bin/*-*-*-*.{bin,elf} binaries@rita.osmocom.org:web-files/simtrace2/firmware/all/
fi
echo
echo "=============== HOST CLEAN =============="
$MAKE maintainer-clean
echo
echo "=============== FIRMWARE CLEAN =============="
cd $TOPDIR/firmware/

32
host/.gitignore vendored Normal file
View File

@ -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

14
host/Makefile.am Normal file
View File

@ -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
@RELMAKE@
BUILT_SOURCES = $(top_srcdir)/.version
$(top_srcdir)/.version:
echo $(VERSION) > $@-t && mv $@-t $@
dist-hook:
echo $(VERSION) > $(distdir)/.tarball-version

View File

@ -5,7 +5,7 @@ APPS=simtrace2-remsim simtrace2-remsim-usb2udp simtrace2-list simtrace2-sniff
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

102
host/configure.ac Normal file
View File

@ -0,0 +1,102 @@
AC_INIT([simtrace2],
m4_esyscmd([./git-version-gen .tarball-version]),
[simtrace@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)

1
host/contrib/Makefile.am Normal file
View File

@ -0,0 +1 @@
EXTRA_DIST = 99-simtrace2.rules

151
host/git-version-gen Executable file
View File

@ -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@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:

7
host/include/Makefile.am Normal file
View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -0,0 +1 @@
../../../../firmware/libcommon/include/simtrace_prot.h

View File

@ -0,0 +1 @@
../../../../firmware/libcommon/include/simtrace_usb.h

19
host/lib/Makefile.am Normal file
View File

@ -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

View File

@ -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)

57
host/lib/gsmtap.c Normal file
View File

@ -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;
}

View File

@ -1,6 +1,6 @@
/* libusb utilities
*
* (C) 2010-2016 by Harald Welte <hwelte@hmw-consulting.de>
* (C) 2010-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
@ -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];

281
host/lib/simtrace2_api.c Normal file
View File

@ -0,0 +1,281 @@
/* simtrace2-protocol - USB protocol library code for SIMtrace2
*
* (C) 2016-2019 by Harald Welte <hwelte@hmw-consulting.de>
* (C) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@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);
}

View File

@ -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}/

View File

@ -1,7 +0,0 @@
#ifndef _SIMTRACE_H
#define _SIMTRACE_H
#define SIMTRACE_USB_VENDOR 0x1d50
#define SIMTRACE_USB_PRODUCT 0x60e3
#endif

View File

@ -1 +0,0 @@
../firmware/libcommon/include/simtrace_prot.h

View File

@ -1 +0,0 @@
../firmware/libcommon/include/simtrace_usb.h

18
host/src/Makefile.am Normal file
View File

@ -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

View File

@ -18,6 +18,7 @@
* 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>
@ -37,231 +38,20 @@
#include <libusb.h>
#include "libusb_util.h"
#include "simtrace.h"
#include "simtrace_prot.h"
#include "apdu_dispatch.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/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;
@ -273,90 +63,6 @@ static void atr_update_csum(uint8_t *atr, unsigned int atr_len)
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
***********************************************************************/
@ -663,12 +369,11 @@ int main(int argc, char **argv)
}
}
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);
reader = osim_reader_open(OSIM_READER_DRV_PCSC, 0, "", NULL);
if (!reader) {

View File

@ -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 @@ struct st_transport {
} 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 @@ static int process_data(enum simtrace_msg_type_sniff type, const uint8_t *buf, i
/* 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 @@ int main(int argc, char **argv)
}
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);

View File

@ -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 },

View File

@ -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>