ipsec, imsd, ims-pdn-up: the SA reader and the holds key compare in canonical form; LOCAL is canonicalised, PCSCF= accepted in RFC 5952 §4 form only
ParseExistingSa and SaLocals compared PCSCF= and LOCAL= as text against `ip xfrm` output, which prints RFC 5952 form, so an upper-case or uncompressed PCSCF= found no SAs and the restart registered fresh — on KPN into the live-SA refusal; the holds file's pdn key compared the same way. Both sides of each of those compares now go through imsd::util::CanonicalAddr, LOCAL is canonicalised once on the way in, and PCSCF= is accepted in that one spelling only — upper case, leading zeros or an uncompressed run are refused at bring-up with the spelling to use, a dotted-quad tail (the form ip prints for an IPv4-mapped address, which CanonicalIp6 does not read) with the rule alone, a bracketed one by the bring-up script, which routes the value as typed, with the rule (no brackets) — and a comma-separated PCSCF= (a list) with its own message instead of reaching the socket layer: one spelling, instead of a leniency both consumers of the setting would have to share. Tested: crafter-build test, 7 passed; the upper-case PCSCF= refused with the spelling to use, a bracketed one refused by the script, and the spelling they name resuming, in builds of this series on the dev phone (KPN).
This commit is contained in:
parent
146d4368d0
commit
b60a3633c1
7 changed files with 84 additions and 22 deletions
|
|
@ -835,7 +835,7 @@ std::optional<imsd::engine::RegRecovery::Held> LoadHolds(const std::string& pdn)
|
|||
char buf[512]; std::size_t n;
|
||||
while ((n = std::fread(buf, 1, sizeof buf, f)) > 0) s.append(buf, n);
|
||||
std::fclose(f);
|
||||
if (QuotedAfter(s, "\"pdn\": \"").value_or("") != pdn) return std::nullopt;
|
||||
if (imsd::util::CanonicalAddr(QuotedAfter(s, "\"pdn\": \"").value_or("")) != imsd::util::CanonicalAddr(pdn)) return std::nullopt;
|
||||
if (QuotedAfter(s, "\"boot\": \"").value_or("") != BootId()) return std::nullopt;
|
||||
long elapsed = BootSeconds() - IntAfter(s, "\"written_at\": ").value_or(0);
|
||||
imsd::engine::RegRecovery::Held h;
|
||||
|
|
@ -915,7 +915,7 @@ public:
|
|||
// No baked-in default: the P-CSCF is carrier infrastructure, learned
|
||||
// from the IMS PDN's PCO on a stock stack. Until PCO discovery is
|
||||
// implemented, PCSCF= must be configured (see README).
|
||||
pcscf_ = EnvOr("PCSCF", "");
|
||||
pcscf_ = imsd::util::CanonicalAddr(EnvOr("PCSCF", ""));
|
||||
pcscfPort_ = std::atoi(EnvOr("PCSCF_PORT", "5060").c_str());
|
||||
dev_ = EnvOr("DEV", "qmapmux0.0");
|
||||
outDir_ = EnvOr("OUT_DIR", StateDir());
|
||||
|
|
@ -956,7 +956,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void SetLocal(std::string l) { local_ = l; pdnLocal_ = std::move(l); }
|
||||
void SetLocal(std::string l) { local_ = imsd::util::CanonicalAddr(l); pdnLocal_ = local_; }
|
||||
void SetDevMode(bool d) { devMode_ = d; }
|
||||
const std::string& Local() const { return local_; }
|
||||
|
||||
|
|
@ -1199,6 +1199,15 @@ private:
|
|||
// ---- bring-up: warm resume if an SA + state file exist, else fresh ----
|
||||
void BringUp() {
|
||||
if (pcscf_.empty()) throw std::runtime_error("PCSCF not set — configure the carrier's P-CSCF address " "(P-CSCF discovery from the PDN's PCO is not implemented yet)");
|
||||
if (pcscf_.contains(',')) throw std::runtime_error(std::format("PCSCF='{}' must be one address", pcscf_));
|
||||
// PCSCF= is accepted in one spelling only: the one `ip` prints (RFC
|
||||
// 5952 — what the journal and `ip xfrm` show). Another spelling is
|
||||
// refused with the one to use rather than normalised, so the bring-up
|
||||
// script, which routes the value as typed, and the daemon agree on it.
|
||||
if (std::string raw = EnvOr("PCSCF", ""); !raw.empty()) {
|
||||
auto canon = imsd::util::CanonicalIp6(raw);
|
||||
if (!canon || *canon != raw) throw std::runtime_error(std::format("PCSCF='{}' is not written as ip prints it; use PCSCF={}", raw, canon.value_or("<one bare IPv6 address, RFC 5952 form>")));
|
||||
}
|
||||
auto card = RunCapture({"qmicli", "-d", "qrtr://0", "--uim-get-card-status"});
|
||||
auto sel = imsd::aka::ParseCardStatus(card.out);
|
||||
if (!sel) throw std::runtime_error("no ready USIM found");
|
||||
|
|
@ -2518,7 +2527,8 @@ int main(int argc, char** argv) {
|
|||
std::println(std::cerr, "imsd: no global IPv6 on {} — is the ims PDN up?", dev);
|
||||
return 1;
|
||||
}
|
||||
Log(std::format("LOCAL={} P-CSCF=[{}]:{}", local, EnvOr("PCSCF", "(unset)"), EnvOr("PCSCF_PORT", "5060")));
|
||||
local = imsd::util::CanonicalAddr(local);
|
||||
Log(std::format("LOCAL={} P-CSCF=[{}]:{}", local, imsd::util::CanonicalAddr(EnvOr("PCSCF", "(unset)")), EnvOr("PCSCF_PORT", "5060")));
|
||||
if (!session) LogAudioSession();
|
||||
imsd::bus::AuthorizeCalls = !session;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue