uqmid: add preliminary support for gsmtapv3
authorAlexander Couzens <[email protected]>
Sun, 19 May 2024 15:29:38 +0000 (16:29 +0100)
committerDavid Bauer <[email protected]>
Sat, 31 May 2025 20:41:00 +0000 (22:41 +0200)
gsmtap is a protocol to encapsulate debug messages. It originates
from osmocom to encapsulate GSM protocols of multiple layers.
It has been extended to encapsulate many different types of protocols
including non-3GPP messages.
gsmptap version 3 is currently under review and an initial draft exists.

uqmid will use gsmtap to copy and transmit QMI messages to a remote debug destination.
Either use wireshark or a custom utilty to receive and print those messages.

Signed-off-by: Alexander Couzens <[email protected]>
uqmid/CMakeLists.txt
uqmid/ddev.c
uqmid/gsmtap_util.c [new file with mode: 0644]
uqmid/gsmtap_util.h [new file with mode: 0644]
uqmid/gsmtapv3.h [new file with mode: 0644]
uqmid/services.c
uqmid/ubus.c
uqmid/utils/README.md [new file with mode: 0644]
uqmid/utils/compile.sh [new file with mode: 0644]
uqmid/utils/gsmtap_read.c [new file with mode: 0644]
uqmid/utils/test_gsmtap.c [new file with mode: 0644]

index ebda892717ce99812949ab680ca868d4113bf15a..3dd063a1480bc057bf57dad5c6ae1e593922ca86 100644 (file)
@@ -1,7 +1,7 @@
 
 SET(UQMID_LIBS ${talloc_library} ${ubus_library})
 
-SET(UQMID uqmid.c ddev.c ubus.c modem.c modem_fsm.c modem_tx.c services.c sim.c ctrl.c wwan.c)
+SET(UQMID uqmid.c ddev.c ubus.c modem.c modem_fsm.c modem_tx.c services.c sim.c ctrl.c wwan.c gsmtap_util.c)
 
 ADD_SUBDIRECTORY(osmocom)
 ADD_EXECUTABLE(uqmid ${UQMID})
@@ -12,3 +12,8 @@ TARGET_INCLUDE_DIRECTORIES(uqmid PRIVATE ${ubus_include_dir} ${ubox_include_dir}
 INSTALL(TARGETS uqmid
        RUNTIME DESTINATION sbin
 )
+
+
+ADD_EXECUTABLE(testgsmtap gsmtap_util.c utils/test_gsmtap.c)
+TARGET_LINK_LIBRARIES(testgsmtap ${LIBS} ${UQMID_LIBS})
+TARGET_INCLUDE_DIRECTORIES(testgsmtap PRIVATE ${ubus_include_dir} ${ubox_include_dir} ${blobmsg_json_include_dir} ${json_include_dir} ${talloc_include_dir} ${CMAKE_SOURCE_DIR})
index c9a69a94e1b9a10227752bd3f17f4401b8f83016..61a0805ff136e76cf2184d27cc458f384688e6e6 100644 (file)
@@ -16,6 +16,7 @@
 #include "logging.h"
 #include "services.h"
 #include "modem.h"
+#include "gsmtap_util.h"
 
 /* FIXME: decide dump_packet */
 #define dump_packet(str, buf, len)
@@ -126,6 +127,7 @@ static void qmi_notify_read(struct ustream *us, int bytes)
                if (len < msg_len)
                        return;
 
+               gsmtap_send(qmi->modem, msg, msg_len);
                qmi_process_msg(qmi, msg);
                ustream_consume(us, msg_len);
        }
diff --git a/uqmid/gsmtap_util.c b/uqmid/gsmtap_util.c
new file mode 100644 (file)
index 0000000..d78bbaf
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * uqmi -- tiny QMI support implementation
+ *
+ * Copyright (C) 2023 Alexander Couzens <[email protected]>
+ *
+ * This library 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 library 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.
+ */
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/socket.h>
+
+#include <talloc.h>
+#include <unistd.h>
+#include "gsmtapv3.h"
+
+#include "gsmtap_util.h"
+
+struct t16l16v {
+       uint16_t type;
+       uint16_t length;
+       uint8_t value[0];
+} __attribute__((packed));
+
+#define GSMTAPV3_BB_DIAG_QC_QMI 1
+
+struct gsmtap_instance {
+       int fd;
+       bool valid;
+};
+
+static struct gsmtap_instance gsmtap_inst;
+
+void gsmtap_disable(void)
+{
+       if (!gsmtap_inst.valid)
+               return;
+
+       if (gsmtap_inst.fd >= 0) {
+               close(gsmtap_inst.fd);
+               gsmtap_inst.fd = -1;
+       }
+
+       gsmtap_inst.valid = false;
+}
+
+/* add support for IPv6 */
+int gsmtap_enable(const char *gsmtap_addr)
+{
+       int ret, sfd;
+       struct sockaddr_in in = {};
+
+       gsmtap_disable();
+       sfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+       if (sfd < 0)
+               return -1;
+
+       in.sin_addr.s_addr = inet_addr(gsmtap_addr);
+       in.sin_port = htons(GSMTAPV3_UDP_PORT);
+       in.sin_family = AF_INET;
+       ret = connect(sfd, (struct sockaddr *) &in, sizeof(struct sockaddr_in));
+       if (ret < 0)
+               return -1;
+
+       gsmtap_inst.fd = sfd;
+       gsmtap_inst.valid = true;
+
+       return 0;
+}
+
+static void tx_gsmtap(void *msg, size_t length)
+{
+       if (!gsmtap_inst.valid)
+               return ;
+
+       write(gsmtap_inst.fd, msg, length);
+}
+
+void gsmtap_send(struct modem *modem, void *data, size_t length)
+{
+       if (!gsmtap_inst.valid)
+               return;
+
+       /* WARNING. GSMTAPv3 is still under development and defines will change! */
+       void *user_data;
+       void *msg = talloc_size(modem, length + sizeof(struct gsmtap_hdr_v3) + 32);
+       struct gsmtap_hdr_v3 *gsmtap = msg;
+       struct t16l16v *metadata = msg + sizeof(struct gsmtap_hdr_v3);
+       int meta_len = 0, rest;
+       size_t packet_len = 0;
+
+       gsmtap->version = GSMTAPV3_VERSION;
+       gsmtap->res = 0;
+       gsmtap->hdr_len = sizeof(struct gsmtap_hdr_v3) >> 2;
+       gsmtap->type = htons(GSMTAPV3_TYPE_BASEBAND_DIAG);
+       gsmtap->sub_type = htons(GSMTAPV3_BASEBAND_DIAG_QUALCOMM);
+
+       metadata->type = 0x1;
+       metadata->length = 0x1;
+       metadata->value[0] = 0x1;
+
+       meta_len = sizeof(*metadata) + metadata->length;
+       rest = meta_len % 4;
+       if (rest)
+               meta_len += 4 - rest;
+
+       gsmtap->hdr_len += (meta_len >> 2);
+       gsmtap->hdr_len = htons(gsmtap->hdr_len);
+
+       user_data = msg + sizeof(struct gsmtap_hdr_v3) + meta_len;
+       memcpy(user_data, data, length);
+
+       packet_len = length + sizeof(struct gsmtap_hdr_v3) + meta_len;
+       tx_gsmtap(msg, packet_len);
+}
diff --git a/uqmid/gsmtap_util.h b/uqmid/gsmtap_util.h
new file mode 100644 (file)
index 0000000..ef2ed16
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * uqmi -- tiny QMI support implementation
+ *
+ * Copyright (C) 2023 Alexander Couzens <[email protected]>
+ *
+ * This library 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 library 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.
+ */
+
+#ifndef __UQMID_GSMTAP_UTIL_H
+#define __UQMID_GSMTAP_UTIL_H
+
+#include <stddef.h>
+
+struct modem;
+
+int gsmtap_enable(const char *gsmtap_addr);
+void gsmtap_disable(void);
+void gsmtap_send(struct modem *modem, void *data, size_t length);
+
+#endif /* __UQMID_GSMTAP_UTIL_H */
diff --git a/uqmid/gsmtapv3.h b/uqmid/gsmtapv3.h
new file mode 100644 (file)
index 0000000..c07a291
--- /dev/null
@@ -0,0 +1,338 @@
+/*! \file gsmtapv3.h
+ * GSMTAP header, pseudo-header in front of the non-IP cellular payload.
+ * GSMTAP is a generic header format for cellular protocol captures.
+ * It could be carried over various transport layer protocols, including
+ * UDP with the IANA-assigned UDP port number 4729. It carries
+ * payload in various formats of cellular interfaces.
+ *
+ * Example programs generating GSMTAP data are airprobe
+ * (http://airprobe.org/) or OsmocomBB (http://bb.osmocom.org/)
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
+
+/* The GSMTAPv3 format definition is maintained in libosmocore,
+ * specifically the latest version can always be obtained from
+ * - TBD -
+ *
+ * If you want to introduce new protocol/burst/channel types or extend
+ * GSMTAP in any way, please contact the GSMTAP maintainer at either the
+ * public [email protected] mailing list, or privately at
+ * Harald Welte <[email protected]>.
+ *
+ * Your cooperation ensures that all projects will use the same GSMTAP
+ * definitions and remain compatible with each other.
+ */
+
+#define GSMTAPV3_VERSION               0x03
+
+/* 0x00, 0x01: Common and non-3GPP protocols */
+#define GSMTAPV3_TYPE_OSMOCORE_LOG     0x0000  /* libosmocore logging */
+#define GSMTAPV3_TYPE_SIM                      0x0001  /* ISO 7816 smartcard interface */
+#define GSMTAPV3_TYPE_BASEBAND_DIAG    0x0002  /* Baseband diagnostic data */
+#define GSMTAPV3_TYPE_SIGNAL_STATUS_REPORT     0x0003  /* Radio signal status report, exact data TBD */
+#define GSMTAPV3_TYPE_TETRA_I1         0x0004  /* TETRA air interface */
+#define GSMTAPV3_TYPE_TETRA_I1_BURST   0x0005  /* TETRA air interface */
+#define GSMTAPV3_TYPE_GMR1_UM          0x0006  /* GMR-1 L2 packets */
+#define GSMTAPV3_TYPE_E1T1                     0x0007  /* E1/T1 Lines */
+#define GSMTAPV3_TYPE_WMX_BURST                0x0008  /* WiMAX burst, shall we deprecate? */
+#define GSMTAPV3_TYPE_DECT             0x0009  /* DECT frames */
+#define GSMTAPV3_TYPE_QCOM_MSM         0x0010  /* Qualcomm Modem related protocol: QMI */
+
+/* 0x02: GSM */
+#define GSMTAPV3_TYPE_UM                       0x0200
+#define GSMTAPV3_TYPE_UM_BURST         0x0201  /* raw burst bits */
+#define GSMTAPV3_TYPE_GB_RLCMAC                0x0202  /* GPRS Gb interface: RLC/MAC */
+#define GSMTAPV3_TYPE_GB_LLC           0x0203  /* GPRS Gb interface: LLC */
+#define GSMTAPV3_TYPE_GB_SNDCP         0x0204  /* GPRS Gb interface: SNDCP */
+#define GSMTAPV3_TYPE_ABIS                     0x0205
+#define GSMTAPV3_TYPE_RLP                      0x0206  /* GSM RLP frames, as per 3GPP TS 24.022 */
+
+/* 0x03: UMTS/WCDMA */
+#define GSMTAPV3_TYPE_UMTS_MAC         0x0300  /* UMTS MAC PDU with context, as per 3GPP TS 25.321 */
+#define GSMTAPV3_TYPE_UMTS_RLC         0x0301  /* UMTS RLC PDU with context, as per 3GPP TS 25.322 */
+#define GSMTAPV3_TYPE_UMTS_PDCP                0x0302  /* UMTS PDCP PDU with context, as per 3GPP TS 25.323 */
+#define GSMTAPV3_TYPE_UMTS_RRC         0x0303  /* UMTS RRC PDU, as per 3GPP TS 25.331 */
+
+/* 0x04: LTE */
+#define GSMTAPV3_TYPE_LTE_MAC          0x0400  /* LTE MAC PDU with context, as per 3GPP TS 36.321 */ 
+#define GSMTAPV3_TYPE_LTE_RLC          0x0401  /* LTE RLC PDU with context, as per 3GPP TS 36.322 */ 
+#define GSMTAPV3_TYPE_LTE_PDCP         0x0402  /* LTE PDCP PDU with context, as per 3GPP TS 36.323 */ 
+#define GSMTAPV3_TYPE_LTE_RRC          0x0403  /* LTE RRC PDU, as per 3GPP TS 36.331 */
+#define GSMTAPV3_TYPE_NAS_EPS          0x0404  /* EPS Non-Access Stratum, as per 3GPP TS 24.301 */
+
+/* 0x05: NR */
+#define GSMTAPV3_TYPE_NR_MAC           0x0500  /* NR MAC PDU with context, as per 3GPP TS 38.321 */ 
+#define GSMTAPV3_TYPE_NR_RLC           0x0501  /* NR RLC PDU with context, as per 3GPP TS 38.322 */ 
+#define GSMTAPV3_TYPE_NR_PDCP          0x0502  /* NR PDCP PDU with context, as per 3GPP TS 38.323 */ 
+#define GSMTAPV3_TYPE_NR_RRC           0x0503  /* NR RRC PDU, as per 3GPP TS 38.331 */
+#define GSMTAPV3_TYPE_NAS_5GS          0x0504  /* 5GS Non-Access Stratum, as per 3GPP TS 24.501 */
+
+/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
+
+/* sub-types for TYPE_SIM (0x0001) */
+#define GSMTAPV3_SIM_APDU                      0x0001 /* APDU data (complete APDU) */
+#define GSMTAPV3_SIM_ATR                       0x0002 /* card ATR data */
+#define GSMTAPV3_SIM_PPS_REQ           0x0003 /* PPS request data */
+#define GSMTAPV3_SIM_PPS_RSP           0x0004 /* PPS response data */
+#define GSMTAPV3_SIM_TPDU_HDR          0x0005 /* TPDU command header */
+#define GSMTAPV3_SIM_TPDU_CMD          0x0006 /* TPDU command body */
+#define GSMTAPV3_SIM_TPDU_RSP          0x0007 /* TPDU response body */
+#define GSMTAPV3_SIM_TPDU_SW           0x0008 /* TPDU response trailer */
+
+/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
+
+/* sub-types for TYPE_BASEBAND_DIAG (0x0002) */
+#define GSMTAPV3_BASEBAND_DIAG_QUALCOMM                0x0001 /* Qualcomm DIAG */
+#define GSMTAPV3_BASEBAND_DIAG_SAMSUNG         0x0002 /* Samsung SDM */
+#define GSMTAPV3_BASEBAND_DIAG_MEDIATEK                0x0003
+#define GSMTAPV3_BASEBAND_DIAG_UNISOC          0x0004
+#define GSMTAPV3_BASEBAND_DIAG_HISILICON       0x0005
+#define GSMTAPV3_BASEBAND_DIAG_INTEL           0x0006
+#define GSMTAPV3_BASEBAND_DIAG_QMI             0x0012 /* Qualcomm MSM Interface */
+
+/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
+
+/* sub-types for TYPE_TETRA_AIR (0x0004, 0x0005) */
+#define GSMTAPV3_TETRA_BSCH                    0x0001
+#define GSMTAPV3_TETRA_AACH                    0x0002
+#define GSMTAPV3_TETRA_SCH_HU          0x0003
+#define GSMTAPV3_TETRA_SCH_HD          0x0004
+#define GSMTAPV3_TETRA_SCH_F           0x0005
+#define GSMTAPV3_TETRA_BNCH                    0x0006
+#define GSMTAPV3_TETRA_STCH                    0x0007
+#define GSMTAPV3_TETRA_TCH_F           0x0008
+#define GSMTAPV3_TETRA_DMO_SCH_S       0x0009
+#define GSMTAPV3_TETRA_DMO_SCH_H       0x000a
+#define GSMTAPV3_TETRA_DMO_SCH_F       0x000b
+#define GSMTAPV3_TETRA_DMO_STCH                0x000c
+#define GSMTAPV3_TETRA_DMO_TCH         0x000d
+
+/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
+
+/* sub-types for TYPE_GMR1_UM (0x0006) */
+#define GSMTAPV3_GMR1_BCCH             0x0001
+#define GSMTAPV3_GMR1_CCCH             0x0002  /* either AGCH or PCH */
+#define GSMTAPV3_GMR1_PCH              0x0003
+#define GSMTAPV3_GMR1_AGCH             0x0004
+#define GSMTAPV3_GMR1_BACH             0x0005
+#define GSMTAPV3_GMR1_RACH             0x0006
+#define GSMTAPV3_GMR1_CBCH             0x0007
+#define GSMTAPV3_GMR1_SDCCH            0x0008
+#define GSMTAPV3_GMR1_TACCH            0x0009
+#define GSMTAPV3_GMR1_GBCH             0x000a
+
+#define GSMTAPV3_GMR1_SACCH            0x0001  /* to be combined with _TCH{6,9}   */
+#define GSMTAPV3_GMR1_FACCH            0x0002  /* to be combines with _TCH{3,6,9} */
+#define GSMTAPV3_GMR1_DKAB             0x0003  /* to be combined with _TCH3 */
+#define GSMTAPV3_GMR1_TCH3             0x0100
+#define GSMTAPV3_GMR1_TCH6             0x0200
+#define GSMTAPV3_GMR1_TCH9             0x0300
+
+/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
+
+/* sub-types for TYPE_E1T1 (0x0007) */
+#define GSMTAPV3_E1T1_LAPD             0x0001  /* Q.921 LAPD */
+#define GSMTAPV3_E1T1_FR               0x0002  /* Frame Relay */
+#define GSMTAPV3_E1T1_RAW              0x0003  /* raw/transparent B-channel */
+#define GSMTAPV3_E1T1_TRAU16   0x0004  /* 16k TRAU frames; sub-slot 0-3 */
+#define GSMTAPV3_E1T1_TRAU8            0x0005  /* 8k TRAU frames; sub-slot 0-7 */
+
+/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
+
+/* sub-types for TYPE_WMX_BURST (0x0008) */
+#define GSMTAPV3_WMX_BURST_CDMA_CODE   0x0001  /* WiMAX CDMA Code Attribute burst */
+#define GSMTAPV3_WMX_BURST_FCH                 0x0002  /* WiMAX FCH burst */
+#define GSMTAPV3_WMX_BURST_FFB                 0x0003  /* WiMAX Fast Feedback burst */
+#define GSMTAPV3_WMX_BURST_PDU                 0x0004  /* WiMAX PDU burst */
+#define GSMTAPV3_WMX_BURST_HACK                        0x0005  /* WiMAX HARQ ACK burst */
+#define GSMTAPV3_WMX_BURST_PHY_ATTRIBUTES      0x0006  /* WiMAX PHY Attributes burst */
+
+/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
+
+/* sub-types for TYPE_UM (0x0200) */
+#define GSMTAPV3_UM_CHANNEL_UNKNOWN    0x0000
+#define GSMTAPV3_UM_CHANNEL_BCCH               0x0001
+#define GSMTAPV3_UM_CHANNEL_CCCH               0x0002
+#define GSMTAPV3_UM_CHANNEL_RACH               0x0003
+#define GSMTAPV3_UM_CHANNEL_AGCH               0x0004
+#define GSMTAPV3_UM_CHANNEL_PCH                        0x0005
+#define GSMTAPV3_UM_CHANNEL_SDCCH              0x0006
+#define GSMTAPV3_UM_CHANNEL_SDCCH4             0x0007
+#define GSMTAPV3_UM_CHANNEL_SDCCH8             0x0008
+#define GSMTAPV3_UM_CHANNEL_FACCH_F            0x0009
+#define GSMTAPV3_UM_CHANNEL_FACCH_H            0x000a
+#define GSMTAPV3_UM_CHANNEL_PACCH              0x000b
+#define GSMTAPV3_UM_CHANNEL_CBCH52             0x000c
+#define GSMTAPV3_UM_CHANNEL_PDCH               0x000d
+#define GSMTAPV3_UM_CHANNEL_PTCCH              0x000e
+#define GSMTAPV3_UM_CHANNEL_CBCH51             0x000f
+#define GSMTAPV3_UM_CHANNEL_VOICE_F            0x0010  /* voice codec payload (FR/EFR/AMR) */
+#define GSMTAPV3_UM_CHANNEL_VOICE_H            0x0011  /* voice codec payload (HR/AMR) */
+
+#define GSMTAPV3_UM_CHANNEL_ACCH               0x0100
+
+/* GPRS Coding Scheme CS1..4 */
+#define GSMTAPV3_UM_GPRS_CS_BASE               0x0200
+#define GSMTAPV3_UM_GPRS_CS(N) (GSMTAP_GPRS_CS_BASE + N)
+/* (E) GPRS Coding Scheme MCS0..9 */
+#define GSMTAPV3_UM_GPRS_MCS_BASE              0x0300
+#define GSMTAPV3_UM_GPRS_MCS(N)        (GSMTAP_GPRS_MCS_BASE + N)
+
+/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
+
+/* sub-types for TYPE_UM_BURST (0x0201) */
+#define GSMTAPV3_UM_BURST_FCCH                 0x0001
+#define GSMTAPV3_UM_BURST_PARTIAL_SCH  0x0002
+#define GSMTAPV3_UM_BURST_SCH                  0x0003
+#define GSMTAPV3_UM_BURST_CTS_SCH              0x0004
+#define GSMTAPV3_UM_BURST_COMPACT_SCH  0x0005
+#define GSMTAPV3_UM_BURST_NORMAL               0x0006
+#define GSMTAPV3_UM_BURST_DUMMY                        0x0007
+#define GSMTAPV3_UM_BURST_ACCESS               0x0008
+#define GSMTAPV3_UM_BURST_NONE                 0x0009
+
+/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
+
+/* sub-types for TYPE_UMTS_RRC (0x0303) */
+#define GSMTAPV3_UMTS_RRC_DL_DCCH                      0x0001
+#define GSMTAPV3_UMTS_RRC_UL_DCCH                      0x0002
+#define GSMTAPV3_UMTS_RRC_DL_CCCH                      0x0003
+#define GSMTAPV3_UMTS_RRC_UL_CCCH                      0x0004
+#define GSMTAPV3_UMTS_RRC_PCCH                         0x0005
+#define GSMTAPV3_UMTS_RRC_DL_SHCCH                     0x0006
+#define GSMTAPV3_UMTS_RRC_UL_SHCCH                     0x0007
+#define GSMTAPV3_UMTS_RRC_BCCH_FACH                    0x0008
+#define GSMTAPV3_UMTS_RRC_BCCH_BCH                     0x0009
+#define GSMTAPV3_UMTS_RRC_BCCH_BCH2                    0x000a
+#define GSMTAPV3_UMTS_RRC_MCCH                         0x000b
+#define GSMTAPV3_UMTS_RRC_MSCH                         0x000c
+
+/* sub-types for individual UMTS RRC message */
+#define GSMTAPV3_UMTS_RRC_HandoverToUTRANCommand               0x0101
+#define GSMTAPV3_UMTS_RRC_InterRATHandoverInfo                 0x0102
+#define GSMTAPV3_UMTS_RRC_SystemInformation_BCH                        0x0103
+#define GSMTAPV3_UMTS_RRC_System_Information_Container 0x0104
+#define GSMTAPV3_UMTS_RRC_UE_RadioAccessCapabilityInfo 0x0105
+#define GSMTAPV3_UMTS_RRC_MasterInformationBlock               0x0106
+#define GSMTAPV3_UMTS_RRC_SysInfoType1                                 0x0107
+#define GSMTAPV3_UMTS_RRC_SysInfoType2                                 0x0108
+#define GSMTAPV3_UMTS_RRC_SysInfoType3                                 0x0109
+#define GSMTAPV3_UMTS_RRC_SysInfoType4                                 0x010a
+#define GSMTAPV3_UMTS_RRC_SysInfoType5                                 0x010b
+#define GSMTAPV3_UMTS_RRC_SysInfoType5bis                              0x010c
+#define GSMTAPV3_UMTS_RRC_SysInfoType6                                 0x010d
+#define GSMTAPV3_UMTS_RRC_SysInfoType7                                 0x010e
+#define GSMTAPV3_UMTS_RRC_SysInfoType8                                 0x010f
+#define GSMTAPV3_UMTS_RRC_SysInfoType9                                 0x0110
+#define GSMTAPV3_UMTS_RRC_SysInfoType10                                        0x0111
+#define GSMTAPV3_UMTS_RRC_SysInfoType11                                        0x0112
+#define GSMTAPV3_UMTS_RRC_SysInfoType11bis                             0x0113
+#define GSMTAPV3_UMTS_RRC_SysInfoType12                                        0x0114
+#define GSMTAPV3_UMTS_RRC_SysInfoType13                                        0x0115
+#define GSMTAPV3_UMTS_RRC_SysInfoType13_1                              0x0116
+#define GSMTAPV3_UMTS_RRC_SysInfoType13_2                              0x0117
+#define GSMTAPV3_UMTS_RRC_SysInfoType13_3                              0x0118
+#define GSMTAPV3_UMTS_RRC_SysInfoType13_4                              0x0119
+#define GSMTAPV3_UMTS_RRC_SysInfoType14                                        0x011a
+#define GSMTAPV3_UMTS_RRC_SysInfoType15                                        0x011b
+#define GSMTAPV3_UMTS_RRC_SysInfoType15bis                             0x011c
+#define GSMTAPV3_UMTS_RRC_SysInfoType15_1                              0x011d
+#define GSMTAPV3_UMTS_RRC_SysInfoType15_1bis                   0x011e
+#define GSMTAPV3_UMTS_RRC_SysInfoType15_2                              0x011f
+#define GSMTAPV3_UMTS_RRC_SysInfoType15_2bis                   0x0120
+#define GSMTAPV3_UMTS_RRC_SysInfoType15_2ter                   0x0121
+#define GSMTAPV3_UMTS_RRC_SysInfoType15_3                              0x0122
+#define GSMTAPV3_UMTS_RRC_SysInfoType15_3bis                   0x0123
+#define GSMTAPV3_UMTS_RRC_SysInfoType15_4                              0x0124
+#define GSMTAPV3_UMTS_RRC_SysInfoType15_5                              0x0125
+#define GSMTAPV3_UMTS_RRC_SysInfoType15_6                              0x0126
+#define GSMTAPV3_UMTS_RRC_SysInfoType15_7                              0x0127
+#define GSMTAPV3_UMTS_RRC_SysInfoType15_8                              0x0128
+#define GSMTAPV3_UMTS_RRC_SysInfoType16                                        0x0129
+#define GSMTAPV3_UMTS_RRC_SysInfoType17                                        0x012a
+#define GSMTAPV3_UMTS_RRC_SysInfoType18                                        0x012b
+#define GSMTAPV3_UMTS_RRC_SysInfoType19                                        0x012c
+#define GSMTAPV3_UMTS_RRC_SysInfoType20                                        0x012d
+#define GSMTAPV3_UMTS_RRC_SysInfoType21                                        0x012e
+#define GSMTAPV3_UMTS_RRC_SysInfoType22                                        0x012f
+#define GSMTAPV3_UMTS_RRC_SysInfoTypeSB1                               0x0130
+#define GSMTAPV3_UMTS_RRC_SysInfoTypeSB2                               0x0131
+#define GSMTAPV3_UMTS_RRC_ToTargetRNC_Container                        0x0132
+#define GSMTAPV3_UMTS_RRC_TargetRNC_ToSourceRNC_Container      0x0133
+
+/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
+
+/* sub-types for TYPE_LTE_RRC (0x0403) */
+#define GSMTAPV3_LTE_RRC_BCCH_BCH                      0x0001
+#define GSMTAPV3_LTE_RRC_BCCH_BCH_MBMS         0x0002
+#define GSMTAPV3_LTE_RRC_BCCH_DL_SCH           0x0003
+#define GSMTAPV3_LTE_RRC_BCCH_DL_SCH_BR                0x0004
+#define GSMTAPV3_LTE_RRC_BCCH_DL_SCH_MBMS      0x0005
+#define GSMTAPV3_LTE_RRC_MCCH                          0x0006
+#define GSMTAPV3_LTE_RRC_PCCH                          0x0007
+#define GSMTAPV3_LTE_RRC_DL_CCCH                       0x0008
+#define GSMTAPV3_LTE_RRC_DL_DCCH                       0x0009
+#define GSMTAPV3_LTE_RRC_UL_CCCH                       0x000a
+#define GSMTAPV3_LTE_RRC_UL_DCCH                       0x000b
+#define GSMTAPV3_LTE_RRC_SC_MCCH                       0x000c
+
+#define GSMTAPV3_LTE_RRC_SBCCH_SL_BCH          0x0101
+#define GSMTAPV3_LTE_RRC_SBCCH_SL_BCH_V2X      0x0102
+
+#define GSMTAPV3_LTE_RRC_BCCH_BCH_NB           0x0200
+#define GSMTAPV3_LTE_RRC_BCCH_BCH_TDD_NB       0x0201
+#define GSMTAPV3_LTE_RRC_BCCH_DL_SCH_NB                0x0202
+#define GSMTAPV3_LTE_RRC_PCCH_NB                       0x0203
+#define GSMTAPV3_LTE_RRC_DL_CCCH_NB                    0x0204
+#define GSMTAPV3_LTE_RRC_DL_DCCH_NB                    0x0205
+#define GSMTAPV3_LTE_RRC_UL_CCCH_NB                    0x0205
+#define GSMTAPV3_LTE_RRC_SC_MCCH_NB                    0x0206
+#define GSMTAPV3_LTE_RRC_UL_DCCH_NB                    0x0207
+
+/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
+
+/* sub-types for TYPE_NR_RRC (0x0503) */
+#define GSMTAPV3_NR_RRC_BCCH_BCH               0x0001
+#define GSMTAPV3_NR_RRC_BCCH_DL_SCH            0x0002
+#define GSMTAPV3_NR_RRC_DL_CCCH                        0x0003
+#define GSMTAPV3_NR_RRC_DL_DCCH                        0x0004
+#define GSMTAPV3_NR_RRC_MCCH                   0x0005
+#define GSMTAPV3_NR_RRC_PCCH                   0x0006
+#define GSMTAPV3_NR_RRC_UL_CCCH                        0x0007
+#define GSMTAPV3_NR_RRC_UL_CCCH1               0x0008
+#define GSMTAPV3_NR_RRC_UL_DCCH                        0x0009
+
+#define GSMTAPV3_NR_RRC_SBCCH_SL_BCH   0x0101
+#define GSMTAPV3_NR_RRC_SCCH                   0x0102
+
+/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
+
+/* sub-types for TYPE_LTE_NAS and TYPE_NR_NAS (0x0404, 0x0504) */
+#define GSMTAPV3_NAS_EPS_PLAIN         0x0000
+#define GSMTAPV3_NAS_EPS_SEC_HEADER    0x0001
+#define GSMTAPV3_NAS_5GS_PLAIN         GSMTAPV3_NAS_EPS_PLAIN
+#define GSMTAPV3_NAS_5GS_SEC_HEADER    GSMTAPV3_NAS_EPS_SEC_HEADER
+
+/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
+
+/* IANA-assigned well-known UDP port for GSMTAP messages */
+#define GSMTAPV3_UDP_PORT                      4729
+
+/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
+
+/*! Structure of the GSMTAP pseudo-header */
+struct gsmtap_hdr_v3 {
+       uint8_t version;        /*!< version, set to 0x03 */
+       uint8_t res;            /*!< reserved for future use (RFU). Padding. */
+       uint16_t hdr_len;       /*!< length (including metadata) in number of 32bit words */
+
+       uint16_t type;          /*!< see GSMTAPV3_TYPE */
+       uint16_t sub_type;      /*!< type of burst/channel, see above */
+
+       uint8_t metadata[0];    /*!< type-specific metadata structure */
+} __attribute__((packed));
index edd425212b4fa4a963c8fd919d112d25b50aacc2..3e84797f0347024934c21997b689c4bff1b0371d 100644 (file)
@@ -14,6 +14,7 @@
 #include "services.h"
 #include "uqmid.h"
 
+#include "gsmtap_util.h"
 
 #ifdef DEBUG_PACKET
 static void dump_packet(const char *prefix, void *ptr, int len)
@@ -113,6 +114,7 @@ _service_send_request(struct qmi_service *service, struct qmi_request *req)
                          msg->qmux.service, le16_to_cpu(msg->svc.message), msg->flags, le16_to_cpu(msg->svc.transaction));
 
        dump_packet("Send packet", msg, len);
+       gsmtap_send(service->qmi->modem, msg, len);
        ustream_write(&service->qmi->sf.stream, (void *) msg, len, false);
 
        return 0;
index a1775869707ef2531b68140c225625a2b52e741f..546b177dbf9023f67d6951affb9a29d00bfc463d 100644 (file)
@@ -14,6 +14,7 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
+#include "gsmtap_util.h"
 #include "osmocom/fsm.h"
 #include "qmi-enums-wds.h"
 
@@ -64,6 +65,42 @@ static int uqmid_handle_reload(struct ubus_context *ctx, struct ubus_object *obj
        return UBUS_STATUS_OK;
 }
 
+enum {
+       GSMTAP_TARGET,
+       __GSMTAP_MAX
+};
+
+static const struct blobmsg_policy enable_gsmtap_policy[__GSMTAP_MAX] = {
+       [GSMTAP_TARGET] = { .name = "target", .type = BLOBMSG_TYPE_STRING },
+};
+
+static int enable_gsmtap(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req,
+                        const char *method, struct blob_attr *msg)
+{
+       struct blob_attr *tb[__GSMTAP_MAX];
+       char *target = NULL;
+       int ret;
+
+       blobmsg_parse(enable_gsmtap_policy, __GSMTAP_MAX, tb, blob_data(msg), blob_len(msg));
+       if (tb[GSMTAP_TARGET]) {
+               target = blobmsg_get_string(tb[GSMTAP_TARGET]);
+       } else {
+               target = "127.0.0.1";
+       }
+       ret = gsmtap_enable(target);
+       if (ret)
+               return UBUS_STATUS_UNKNOWN_ERROR;
+
+       return UBUS_STATUS_OK;
+}
+
+static int disable_gsmtap_policy(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req,
+                                const char *method, struct blob_attr *msg)
+{
+       gsmtap_disable();
+       return UBUS_STATUS_OK;
+}
+
 static int uqmid_add_object(struct ubus_object *obj)
 {
        int ret = ubus_add_object(ubus_ctx, obj);
@@ -204,6 +241,8 @@ static void uqmid_ubus_connection_lost(struct ubus_context *ctx)
 static struct ubus_method main_object_methods[] = {
        { .name = "restart", .handler = uqmid_handle_restart },
        { .name = "reload", .handler = uqmid_handle_reload },
+       UBUS_METHOD("enable_gsmtap", enable_gsmtap, enable_gsmtap_policy),
+       { .name = "disable_gsmtap", .handler = disable_gsmtap_policy },
        UBUS_METHOD("add_modem", add_modem, add_modem_policy),
        UBUS_METHOD("remove_modem", remove_modem, remove_modem_policy),
 };
diff --git a/uqmid/utils/README.md b/uqmid/utils/README.md
new file mode 100644 (file)
index 0000000..ff5435d
--- /dev/null
@@ -0,0 +1,3 @@
+# uqmid utils
+
+* `gsmtap_read`: a utility which reads gsmtap v3 via the network and parse the QMI packages via libqmi
diff --git a/uqmid/utils/compile.sh b/uqmid/utils/compile.sh
new file mode 100644 (file)
index 0000000..f1ead66
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+gcc -o gsmtap_read gsmtap_read.c -I/usr/include/libqmi-glib/ -I/usr/include/glib-2.0/ -I/usr/lib/glib-2.0/include/ -I/usr/include/libqrtr-glib/ -I../ -lqmi-glib -lglib-2.0
diff --git a/uqmid/utils/gsmtap_read.c b/uqmid/utils/gsmtap_read.c
new file mode 100644 (file)
index 0000000..c4b7528
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * uqmid -- tiny QMI support implementation
+ *
+ * Copyright (C) 2024 Alexander Couzens <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include <libqmi-glib.h>
+#include "gsmtapv3.h"
+
+/* from osmo-qcdiag under GPLv2 */
+/* A small wrapper around libqmi-glib to give us a human-readable string
+ * representation of QMI messages that we receive from DIAG */
+static int dump_qmi_msg(const uint8_t *data, unsigned int len)
+{
+       GByteArray *buffer;
+       GError *error = NULL;
+       QmiMessage *message;
+       gchar *printable;
+
+       buffer = g_byte_array_sized_new(len);
+       g_byte_array_append(buffer, data, len);
+
+       message = qmi_message_new_from_raw(buffer, &error);
+       if (!message) {
+               fprintf(stderr, "qmi_message_new_from_raw() returned NULL\n");
+               return -1;
+       }
+
+       printable = qmi_message_get_printable(message, "QMI ");
+       printf("<<<< QMI\n");
+       fputs(printable, stdout);
+       printf(">>>> QMI\n");
+       printf("\n");
+       g_free(printable);
+
+       return 0;
+}
+
+int main() {
+       int sfd, ret;
+       struct sockaddr_in in = {};
+               sfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+       if (sfd < 0) {
+               fprintf(stderr, "Failed to create socket! %d", ret);
+               return -1;
+       }
+
+       in.sin_addr.s_addr = 0;
+       in.sin_port = htons(GSMTAPV3_UDP_PORT);
+       in.sin_family = AF_INET;
+       ret = bind(sfd, (struct sockaddr *) &in, sizeof(struct sockaddr_in));
+       if (ret < 0) {
+               fprintf(stderr, "Failed to bind! %d", ret);
+               return -1;
+       }
+
+       struct gsmtap_hdr_v3 ghdr;
+       uint8_t buffer[4096];
+       ssize_t rs;
+       void *data;
+       while ((rs = recvfrom(sfd, buffer, sizeof(buffer), 0, NULL, 0)) >= 0) {
+               uint16_t hdrlen;
+
+               if (rs < sizeof(ghdr))
+                       continue;
+
+               memcpy(&ghdr, buffer, sizeof(ghdr));
+               hdrlen = htons(ghdr.hdr_len) * 4;
+               if (hdrlen > rs)
+                       continue;
+
+               if (ghdr.type != htons(GSMTAPV3_TYPE_BASEBAND_DIAG))
+                       continue;
+
+               if (ghdr.sub_type != htons(GSMTAPV3_BASEBAND_DIAG_QUALCOMM))
+                       continue;
+
+               if (hdrlen == rs)
+                       continue;
+
+               data = buffer + hdrlen;
+               dump_qmi_msg(data, rs - hdrlen);
+       }
+}
diff --git a/uqmid/utils/test_gsmtap.c b/uqmid/utils/test_gsmtap.c
new file mode 100644 (file)
index 0000000..ed38292
--- /dev/null
@@ -0,0 +1,19 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "../gsmtap_util.h"
+#include <talloc.h>
+
+struct modem {
+       int foo;
+};
+
+int main() {
+       uint8_t data[1024] = { 0, 1, 2, 3, 4 };
+       int ret = gsmtap_enable("127.0.0.1");
+       printf("gsmtap enable: %d\n", ret);
+       gsmtap_send(NULL, data, sizeof(data));
+
+       return 0;
+}