packaging, ims-pdn-up, imsd, README: imsd runs without /etc/imsd.env and idles without a SIM
With the P-CSCF coming from the PDN's PCO, the configuration file has no required line left, so the apk's ConditionPathExists=/etc/imsd.env drop-in goes: the unit starts on every phone with the package, and VoLTE is on by default. Installing the package and inserting a SIM is the opt-in; the file holds overrides only, and its existence changes nothing. By the versioning rule (AGENTS §11, the first commit of this series) that is what moves the major number: the release is 1.0.0, and §11 now records it. What used to be the file's job — keeping a phone nobody configured out of a failing unit — is now a rule on facts, the same for every phone: a modem in the failed state with a SIM reason makes the script write IMSD_IDLE=no-sim to /run/imsd.env and exit 0; a profile-indexed connect series the network refuses ten times in a row — each a persistent 3GPP cause in ModemManager's typed error (not subscribed, unknown APN, barred, not authorised in the PLMN, authentication failed, the service option not supported, the wrong PDN type) with packet service at the time; counted only while the modem reads registered, connecting or connected with packet service not detached — stricter than the daemon's PacketServiceUp; any other read, a timeout or a transient cause starts the count again — writes IMSD_IDLE=no-ims-pdn; and a bring-up that ends with no P-CSCF — none configured, none discovered: no IPv6 P-CSCF read from the PCO (PCSCF_DISCOVERY=none in the hand-off, the reader's exit 2: the list absent, empty, unreadable or IPv4/FQDN only), discovery skipped (no rmnet mux id) or no hand-off at all (a manual run) — and no registration of imsd's own to resume is the daemon's own idle, decided before it takes the bus name (SaPeer and the holds' old_gone say what can be resumed; a pair the holds wrote off is taken out of the kernel there) and at the no-target bring-up, where a pair nothing can resume is written off and taken out of the kernel first. imsd reads the key, logs idle: … and exits 0, which Restart=on-failure leaves alone, so the unit stays inactive until the next boot, a systemctl start or a start of imsd-ofonod where that runs (its Wants starts an idle imsd again). What is not a fact keeps the retry: no coverage, a SIM still waiting for its PIN, a modem without an ims profile (the APN-string connect is tried), an APN-string series (the modem's own wall), a resumable pair whose attempt failed (the fatal), and a P-CSCF reader that did not answer (PCSCF_DISCOVERY=failed: the daemon exits 1 and the restart runs discovery again). A phone that never had the file keeps its stopped unit through the upgrade and starts at its next boot, registering where the rule above lets it — at the upgrade itself where imsd-ofonod runs, whose restart pulls imsd in through its Wants (systemd queues the marked unit's try-restart, collapses it to a restart and starts what the unit Wants in the same transaction: job_type_collapse, transaction_add_job_and_dependencies, 262~rc3); the opt-out is systemctl mask --now imsd, since a plain disable is undone by that Wants. imsd-ofonod.service loses its After=imsd.service: with imsd starting on every phone, GNOME Calls' backend would otherwise wait behind the ims PDN bring-up at every boot and at its marked restart at an upgrade, for the whole bring-up (up to its TimeoutStartSec=900); it starts at once and republishes when imsd's name appears (OnImsdAppeared). The configuration file's path is the IMSD_ENV seam the mock bench uses. AGENTS §6's lint figures are this tree's (109 findings in 16 of 20 files, 2026-10-13; the 72 of 2026-10-06 predate the Qmi files). Tested: crafter-build test, 8 passed; on the host build the daemon's idle exit for the script's keys and, with no pair, for every discovery verdict but failed (none, skipped, no hand-off) — exit 0 — and the exit 1 for failed; the script's arms on the mock bench; on the dev phone (KPN), in builds of this series: the daemon's idle at the no-target bring-up with the dead pair removed and before the bus name for a pair the holds had written off, the discovery-failed exit 1 and its restart, the start without the file, the pull-in by an imsd-ofonod restart and the mask holding against it and a reboot, and imsd-ofonod starting at once with imsd stopped and republishing when imsd's name appeared.
This commit is contained in:
parent
1d28063700
commit
7a3dcc8951
7 changed files with 476 additions and 149 deletions
16
README.md
16
README.md
|
|
@ -48,17 +48,6 @@ Both can be found in the packages tab:
|
|||
https://forgejo.catcrafts.net/Catcrafts/-/packages/alpine/imsd
|
||||
```
|
||||
|
||||
The apk's `imsd.service` is enabled by preset and starts at boot once
|
||||
`/etc/imsd.env` exists (`touch /etc/imsd.env` is enough; the condition is checked when
|
||||
the unit starts, so after creating the file run `systemctl start imsd`). It first brings the `ims` PDN up through ModemManager, then registers:
|
||||
resuming an existing registration when it can, registering fresh otherwise,
|
||||
and waiting out whatever the network tells it to wait out. Check on it with:
|
||||
|
||||
```sh
|
||||
journalctl -u imsd -f
|
||||
busctl --system call net.catcrafts.IMS1 /net/catcrafts/IMS1 net.catcrafts.IMS1 GetStatus
|
||||
```
|
||||
|
||||
## Dialers
|
||||
|
||||
imsd itself is desktop-agnostic: everything a dialer needs is on the system
|
||||
|
|
@ -91,8 +80,8 @@ Configuration is environment variables in `/etc/imsd.env`, none are required.
|
|||
|
||||
| Variable | Default | Meaning |
|
||||
|---|---|---|
|
||||
| `PCSCF` | *(the first of `PCSCF_DISCOVERED`)* | P-CSCF address (IPv6), exactly one — not a comma-separated list — in RFC 5952 §4 form (lowercase, leading zeros dropped, the longest zero run compressed, no brackets — what `ip` prints for a plain IPv6 address; an IPv4-mapped address only as hex, `::ffff:a00:1` — the dotted spelling RFC 5952 §5 and `ip` use for it is refused); upper case, leading zeros, an uncompressed run or brackets are refused at start with the spelling to use (in the packaged unit the bring-up script refuses brackets first, with the rule), a dotted-quad tail with the rule; before 1.0.0 an upper-case, zero-padded or uncompressed `PCSCF=` matched no SA in `ip xfrm`'s text and registered fresh at every restart — an upgraded phone with such a setting stops at start with the spelling to use. Set, it wins over `PCSCF_DISCOVERED`. It is where a fresh registration goes; a registration resumed from the kernel's SAs stays on the P-CSCF it was made to until its next fresh registration. With neither this nor `PCSCF_DISCOVERED`, a fresh registration fails with a clear error |
|
||||
| `PCSCF_DISCOVERED` | *(from the PDN's PCO)* | the IPv6 P-CSCF list the network put in the ims PDN's PCO, comma-separated in the order the modem reports it; the first entry `CanonicalIp6` accepts is used when `PCSCF` is unset. The packaged service gets it via `/run/imsd.env` from `ims-pdn-up.sh`, which reads it from the modem with `imsd-pcscf` (at most eight; it routes the first; imsd routes the P-CSCF it uses — the fresh target, the resumed SA peer — itself as well); entries `CanonicalIp6` does not read — an IPv4 address, a name, an IPv6 literal with a zone or a dotted-quad tail (an IPv4-mapped entry in hex only) — are logged and ignored. In `/etc/imsd.env` it is a bench seam |
|
||||
| `PCSCF` | *(the first of `PCSCF_DISCOVERED`)* | P-CSCF address (IPv6), exactly one — not a comma-separated list — in RFC 5952 §4 form (lowercase, leading zeros dropped, the longest zero run compressed, no brackets — what `ip` prints for a plain IPv6 address; an IPv4-mapped address only as hex, `::ffff:a00:1` — the dotted spelling RFC 5952 §5 and `ip` use for it is refused); upper case, leading zeros, an uncompressed run or brackets are refused at start with the spelling to use (in the packaged unit the bring-up script refuses brackets first, with the rule), a dotted-quad tail with the rule; before 1.0.0 an upper-case, zero-padded or uncompressed `PCSCF=` matched no SA in `ip xfrm`'s text and registered fresh at every restart — an upgraded phone with such a setting stops at start with the spelling to use. Set, it wins over `PCSCF_DISCOVERED`. It is where a fresh registration goes; a registration resumed from the kernel's SAs stays on the P-CSCF it was made to until its next fresh registration. With neither this nor `PCSCF_DISCOVERED` there is no fresh registration: a phone with nothing to resume idles (`idle: no P-CSCF …`), unless a resume failed with its pair still resumable, or the reader did not answer (`PCSCF_DISCOVERY=failed`): those exit non-zero for systemd's restart |
|
||||
| `PCSCF_DISCOVERED` | *(from the PDN's PCO)* | the IPv6 P-CSCF list the network put in the ims PDN's PCO, comma-separated in the order the modem reports it; the first entry `CanonicalIp6` accepts is used when `PCSCF` is unset. The packaged service gets it via `/run/imsd.env` from `ims-pdn-up.sh`, which reads it from the modem with `imsd-pcscf` (at most eight; it routes the first; imsd routes the P-CSCF it uses — the fresh target, the resumed SA peer — itself as well); entries `CanonicalIp6` does not read — an IPv4 address, a name, an IPv6 literal with a zone or a dotted-quad tail (an IPv4-mapped entry in hex only) — are ignored (logged by the engine when the daemon goes on to register); `PCSCF_DISCOVERY=found|none|failed|skipped` beside it says how the list came to be — `failed` (the reader did not answer) makes a daemon with nothing to resume exit 1 for the restart instead of idling. In `/etc/imsd.env` it is a bench seam |
|
||||
| `IMSD_PCSCF` | `/usr/libexec/imsd-pcscf` | the P-CSCF reader `ims-pdn-up.sh` runs — a bench seam (the mock bench's fake reader; a stub through a unit drop-in on the dev phone), from the environment |
|
||||
| `PCSCF_PORT` | `5060` | unprotected SIP port for the initial REGISTER |
|
||||
| `DEV` | `qmapmux0.0` | ims-PDN netdev; the packaged service passes the real one via `/run/imsd.env` |
|
||||
|
|
@ -111,6 +100,7 @@ Configuration is environment variables in `/etc/imsd.env`, none are required.
|
|||
| `DUMP_SIP` | `0` | `1` writes raw REGISTER-200/SUBSCRIBE-200 dumps, the last refused REGISTER or SUBSCRIBE final (`imsd-register-fail.raw`, `imsd-subscribe-fail.raw`), the last inbound INVITE (`imsd-invite-in.raw`) and the last outgoing INVITE (`imsd-invite-out.raw`), mode 0600, for debugging — they contain your IMSI/MSISDN and addresses. A refused REGISTER or SUBSCRIBE is logged with its status line and any Retry-After / Warning / Reason / Server headers |
|
||||
| `DUMP_DIR`, `OUT_DIR` | state dir | where dumps / per-call media stats land |
|
||||
| `IMSD_MEDIA` | *(auto)* | path to `imsd-media` (default: next to `imsd`, else `/usr/libexec/imsd-media`) |
|
||||
| `IMSD_ENV` | `/etc/imsd.env` | the configuration file's path — a bench seam for manual runs of `ims-pdn-up.sh` (the packaged unit reads `/etc/imsd.env` through `EnvironmentFile=`). The file's existence changes nothing |
|
||||
|
||||
The protected client/server ports are fixed at 45061/45062
|
||||
(`imsd::util::PortUc`/`PortUs`) — changing them in source also requires
|
||||
|
|
|
|||
Loading…
Reference in a new issue