103 Commits
Author SHA1 Message Date
Dmitry Baryshkov 128cd6e0a3 Merge pull request #48 from lumag/xz
tqftpserv: add support for xz decompression
2026-10-07 00:10:01 +02:00
Dmitry Baryshkov 49f6a862b4 ci: exercise xz autodetection
Mirror the zstd handling for xz: add an "xz" matrix dimension that
installs the liblzma development package for the "enabled" variant and
omits it for the "disabled" one, and verify with check-xz.sh that
xz-decompress.c is compiled iff liblzma was available. liblzma ships in
the Arch base image, so the xz-disabled variant is excluded there.

Assisted-by: Claude Code:claude-opus-4-8
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
2026-10-06 09:07:03 +02:00
Dmitry Baryshkov 80a65872be tqftpserv: add support for xz decompression
Some distributions (e.g. Fedora) use xz compression for the firmware
files stored in /lib/firmware. Add an xz decompression path using
liblzma, mirroring the existing zstd support, and try the .xz variant
when opening a possibly-compressed file.

Closes: #46
Assisted-by: Claude Code:claude-opus-4-8
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
2026-10-06 09:07:03 +02:00
Dmitry Baryshkov c0da4aa516 Merge pull request #49 from lumag/ci
Add GitHub Actions build CI with zstd autodetection
2026-10-06 09:06:30 +02:00
Dmitry Baryshkov 998ea7dabc ci: cross-compile for Android with the NDK
Add an Android job to the CI that cross-compiles tqftpserv with the
Android NDK for the arm64-v8a, armeabi-v7a and x86_64 ABIs. libqrtr is
cross-built from source and linked in, matching the Android.bp build.
The NDK download and the per-ABI libqrtr build are cached.

Define the ANDROID macro when building for an Android host so the vendor
firmware paths in translate.c are selected.

Assisted-by: Claude Code:claude-opus-4-8
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
2026-09-15 23:02:45 +03:00
Dmitry Baryshkov c4aee5ebc4 tqftpserv: fix seek option format on 32-bit
The seek option value is an off_t, but it was formatted with %zd, which
consumes an ssize_t. On 32-bit platforms with _FILE_OFFSET_BITS=64 off_t
is 64-bit while ssize_t is 32-bit, so the wrong value is emitted (and the
NDK build flags it as a -Wformat error). Cast to size_t to match the
conversion specifier, as is done for the other numeric options.

Fixes: 7557ca4754 ("tftp: Ensure that the oack message stays within bounds")
Assisted-by: Claude Code:claude-opus-4-8
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
2026-09-15 23:02:45 +03:00
Dmitry Baryshkov 1d25793a68 ci: add GitHub Actions build matrix
Add a GitHub Actions workflow modeled on the cdba project's CI. It builds
tqftpserv across a matrix of distributions (Alpine, Arch, Debian, Fedora,
Ubuntu) and compilers (gcc, clang).

The matrix additionally toggles zstd support: the "enabled" variant
installs the libzstd development package, the "disabled" variant does
not, so that both autodetected configurations are exercised. A small
check verifies that the autodetection matched the requested variant.

qrtr is installed from the distribution packages where available; on Arch
(where it only exists in the AUR) it is built from source. zstd is part
of the Arch base image and cannot be removed, so the zstd-disabled
variant is excluded there.

Assisted-by: Claude Code:claude-opus-4-8
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
2026-09-15 23:02:45 +03:00
Dmitry Baryshkov c2559a2609 Merge pull request #53 from f-izzo/populate-readwrite
tqftpserv-populate-readwrite: add unit to copy files from persist part
2026-09-02 03:26:54 +03:00
Federico Amedeo Izzo 33e310c141 tqftpserv-populate-readwrite: add unit to copy files from persist part
Some devices (motorola-dubai) need to access readwrite files found in the
persist partition in `rfs/msm/mpss` to have working modem.

Create a new systemd unit that calls a shell script to copy the files
into the readwrite folder (currently /var/lib/tqftpserv).
The units runs only if and after /dev/disk/by-partlabel/persist is available.

Signed-off-by: Federico Amedeo Izzo <federico@izzo.pro>
2026-08-30 10:07:10 +02:00
Dmitry Baryshkov 3d2774d60e meson: fall back to finding libqrtr without pkg-config
Support old libqrtr that does not ship a qrtr.pc pkg-config file by
locating the library and its header directly when the pkg-config lookup
fails.

Assisted-by: Claude Code:claude-opus-4-8
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
2026-07-06 02:25:36 +03:00
Dmitry Baryshkov dec7b7e543 meson: autodetect zstd support
Make libzstd an optional, autodetected dependency instead of a hard
requirement: build in the zstd decompression path when libzstd is
available and fall back to the stub in zstd-decompress.h otherwise. This
lets tqftpserv be built on systems without libzstd and makes it possible
to exercise both configurations in CI.

Assisted-by: Claude Code:claude-opus-4-8
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
2026-07-06 02:13:33 +03:00
Dmitry Baryshkov 836161d68d zstd-decompress: include stdio.h in the stub
The fallback zstd_decompress_file() stub, used when built without zstd
support, calls fprintf() but relied on the includer having pulled in
stdio.h already. Include it directly so the header is self-contained.

Assisted-by: Claude Code:claude-opus-4-8
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
2026-07-06 02:13:33 +03:00
Dmitry Baryshkov 1085b1f948 meson: define systemd_system_unit_dir in the else branch
systemd_system_unit_dir was only assigned inside the if/elif handling the
systemd-unit-prefix option and a found systemd pkg-config file. When
neither applies (e.g. on musl-based distros without a systemd .pc file),
the variable was left undefined and referenced later, aborting configure.
Add an else branch that sets it to an empty string.

Fixes: d4c7f06435 ("build: allow building systemd unit files without systemd dependency")
Assisted-by: Claude Code:claude-opus-4-8
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
2026-07-06 02:13:33 +03:00
Dmitry Baryshkov b6bb92d40c Merge pull request #44 from orbisai0security/fix-v001-path-traversal-wrq
fix: add path validation in tqftpserv.c
v1.2
2026-05-19 01:51:27 +03:00
Dmitry Baryshkov eda00d2917 Merge pull request #43 from zjc-enigma/topic/readonly-vendor-firmware
translate: support /readonly/vendor/firmware/ paths
2026-05-19 01:51:12 +03:00
OrbisAI Security 566445f44f tqftpserv: use memcpy instead of strcpy in tftp_send_error
Replace strcpy() with memcpy() when copying the error message into
the TFTP error packet buffer. The buffer length is already computed
as (4 + strlen(msg) + 1), so memcpy with (len - 4) copies exactly
the right amount. This avoids reliance on strcpy's null-terminator
scanning behavior for a fixed-length copy.

Signed-off-by: OrbisAI Security <mediratta01.pally@gmail.com>
2026-05-18 21:01:24 +05:30
OrbisAI Security fc66ee26a4 translate: reject path traversal in readwrite handler
The translate_readwrite() function opens files relative to the
persistent readwrite directory based on client-supplied paths.
A malicious TFTP client could use '..' sequences to escape the
intended directory and read/write arbitrary files on the host.

Add a strstr() check to reject any path containing '..' before
opening the file.

Signed-off-by: OrbisAI Security <mediratta01.pally@gmail.com>
2026-05-18 21:01:10 +05:30
Dmitry Baryshkov 7259073ad9 translate: verify asprintf return value
asprintf() can fail, keeping the path_with_zstd_extension unchanged,
which can lead to further errors / crashes. Return early if asprintf
fails.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
2026-05-18 09:25:12 +02:00
Astro Enigma e3533ef115 translate: support /readonly/vendor/firmware/ paths
Some Qualcomm modem firmware (Xiaomi raphael on sm8150, db845c, ...)
requests its protection-domain firmware blobs via TFTP-over-QRTR at
Android-style vendor partition paths, which tqftpserv currently
rejects with "invalid path ... rejecting", leaving the wifi (or other)
protection domain unloaded.

Add two more readonly prefixes that delegate to translate_readonly()
(the existing remoteproc-firmware-dir search):

  /readonly/vendor/firmware/             - Xiaomi raphael (sm8150), ...
  /readonly/vendor/firmware_mnt/image/   - db845c (per issue #7)

For this to actually serve a blob, the file needs to exist in one of
the firmware directories that translate_readonly() iterates (i.e.
alongside a remoteproc's firmware= attribute). On postmarketOS
xiaomi-raphael, the firmware-xiaomi-raphael-wlan package currently
ships wlanmdsp.mbn at /lib/firmware/wlanmdsp.mbn; once that is moved
(or symlinked) into /lib/firmware/qcom/sm8150/xiaomi/raphael/
(alongside modem.mbn), ath10k_snoc completes its probe, phy0 appears,
and NetworkManager auto-creates wlan0.

Refs: https://github.com/linux-msm/tqftpserv/issues/7

Signed-off-by: Astro Enigma <astronazer@gmail.com>
2026-05-18 12:10:36 +08:00
Dmitry Baryshkov 238de1c6a2 Merge pull request #39 from bhaskarv79/topic/rw_persist
translate: add persistent path for read-write and fix read-only search path
2026-05-13 12:47:19 +03:00
Bhaskar Valaboju 3828238cff translate: map /readonly/firmware/modem_pr to FIRMWARE_BASE/modem_pr
On qcm6490, the inbuilt modem requests firmware images via TFTP
RRQ using the path prefix /readonly/firmware/modem_pr/so/ instead of the
previously expected /readonly/firmware/image/. The server fails to match
this path and does not invoke translate_readonly, causing the modem boot
to fail.

Add READONLY_FW_BASE and READONLY_MODEM_PATH macros to explicitly match
/readonly/firmware/modem_pr and reuse translate_readonly() by passing
the modem_pr relative path (e.g., modem_pr/so/file.mbn).
translate_readonly() then searches the remoteproc firmware directory
and constructs the full path as:

  READONLY_FW_BASE/<fw_dir>/modem_pr/so/file.mbn

With this fix, the modem boots successfully and the link comes up.

Signed-off-by: Bhaskar Valaboju <bhaskar.valaboju@oss.qualcomm.com>
2026-05-12 18:27:16 +05:30
Bhaskar Valaboju ac0e4ac2df translate: rename TQFTPSERV_TMP to TQFTPSERV_RW_DIR
The macro name TQFTPSERV_TMP is misleading since /var/lib/tqftpserv
is persistent storage, not a temporary directory. Rename it to
TQFTPSERV_RW_DIR to reflect its role as the base directory for
/readwrite/ path requests (WRQ operations).

Also update the warn() messages and kdoc comment in
translate_readwrite() to drop the stale "temporary" wording.

Signed-off-by: Bhaskar Valaboju <bhaskar.valaboju@oss.qualcomm.com>
2026-05-12 18:27:16 +05:30
Bhaskar Valaboju 614a2de2ed translate: use /var/lib/tqftpserv for persistent readwrite storage
Modem subsystems write calibration data and other persistent files via
TFTP to the readwrite path. These files must survive system reboots to
avoid re-calibration on every boot cycle.

Change TQFTPSERV_TMP from /tmp/tqftpserv to /var/lib/tqftpserv on
non-Android builds. The /tmp directory is typically a tmpfs that is
cleared on reboot, which would cause loss of modem calibration data.
/var/lib/tqftpserv provides persistent storage that survives reboots
and is the appropriate location for application state data.

Update tqftpserv.service.in and include StateDirectory to let systemd
create /var/lib/tqftpserv if it is not present.

Signed-off-by: Bhaskar Valaboju <bhaskar.valaboju@oss.qualcomm.com>
2026-05-11 14:10:11 +05:30
Dmitry Baryshkov a8a29e947d Merge pull request #36 from me-cafebabe/master
Fix build for Android
2026-04-22 17:34:20 +03:00
Dmitry Baryshkov cbc47b5855 Merge pull request #37 from bhaskarv79/topic/fix_wsize_resp
tftp: ACK short DATA packets in WRQ window mode
2026-04-22 17:33:44 +03:00