From 70ad886cf76f26feb7c5a681adaca3e64e9ef48f Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sun, 19 May 2024 16:29:38 +0100 Subject: [PATCH] uqmid: add preliminary support for gsmtapv3 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 --- uqmid/CMakeLists.txt | 7 +- uqmid/ddev.c | 2 + uqmid/gsmtap_util.c | 125 ++++++++++++++ uqmid/gsmtap_util.h | 28 ++++ uqmid/gsmtapv3.h | 338 ++++++++++++++++++++++++++++++++++++++ uqmid/services.c | 2 + uqmid/ubus.c | 39 +++++ uqmid/utils/README.md | 3 + uqmid/utils/compile.sh | 3 + uqmid/utils/gsmtap_read.c | 105 ++++++++++++ uqmid/utils/test_gsmtap.c | 19 +++ 11 files changed, 670 insertions(+), 1 deletion(-) create mode 100644 uqmid/gsmtap_util.c create mode 100644 uqmid/gsmtap_util.h create mode 100644 uqmid/gsmtapv3.h create mode 100644 uqmid/utils/README.md create mode 100644 uqmid/utils/compile.sh create mode 100644 uqmid/utils/gsmtap_read.c create mode 100644 uqmid/utils/test_gsmtap.c diff --git a/uqmid/CMakeLists.txt b/uqmid/CMakeLists.txt index ebda892..3dd063a 100644 --- a/uqmid/CMakeLists.txt +++ b/uqmid/CMakeLists.txt @@ -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}) diff --git a/uqmid/ddev.c b/uqmid/ddev.c index c9a69a9..61a0805 100644 --- a/uqmid/ddev.c +++ b/uqmid/ddev.c @@ -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 index 0000000..d78bbaf --- /dev/null +++ b/uqmid/gsmtap_util.c @@ -0,0 +1,125 @@ +/* + * uqmi -- tiny QMI support implementation + * + * Copyright (C) 2023 Alexander Couzens + * + * 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 +#include +#include +#include +#include + +#include +#include +#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 index 0000000..ef2ed16 --- /dev/null +++ b/uqmid/gsmtap_util.h @@ -0,0 +1,28 @@ +/* + * uqmi -- tiny QMI support implementation + * + * Copyright (C) 2023 Alexander Couzens + * + * 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 + +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 index 0000000..c07a291 --- /dev/null +++ b/uqmid/gsmtapv3.h @@ -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 + +/* ====== 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 openbsc@lists.osmocom.org mailing list, or privately at + * Harald Welte . + * + * 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)); diff --git a/uqmid/services.c b/uqmid/services.c index edd4252..3e84797 100644 --- a/uqmid/services.c +++ b/uqmid/services.c @@ -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; diff --git a/uqmid/ubus.c b/uqmid/ubus.c index a177586..546b177 100644 --- a/uqmid/ubus.c +++ b/uqmid/ubus.c @@ -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 index 0000000..ff5435d --- /dev/null +++ b/uqmid/utils/README.md @@ -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 index 0000000..f1ead66 --- /dev/null +++ b/uqmid/utils/compile.sh @@ -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 index 0000000..c4b7528 --- /dev/null +++ b/uqmid/utils/gsmtap_read.c @@ -0,0 +1,105 @@ +/* + * uqmid -- tiny QMI support implementation + * + * Copyright (C) 2024 Alexander Couzens + * + * 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 +#include + +#include +#include +#include +#include +#include +#include + +#include +#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 index 0000000..ed38292 --- /dev/null +++ b/uqmid/utils/test_gsmtap.c @@ -0,0 +1,19 @@ +#include +#include +#include + +#include "../gsmtap_util.h" +#include + +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; +} -- 2.30.2