imsd: P-CSCF candidates from PCSCF_DISCOVERED when PCSCF= is not set
imsd reads PCSCF_DISCOVERED= — a comma-separated IPv6 list — from its environment; nothing in this tree writes it yet. FreshPcscfFromEnv picks the fresh target: PCSCF= when set — one address, it wins — else the first entry of the list CanonicalIp6 accepts; the journal says which, and names the entries it refused. imsd routes the P-CSCF it uses itself — the fresh target before a fresh registration (BringUp, FreshRecover), the resumed SA peer once its SAs are confirmed — with the same idempotent `ip -6 route replace` as a call's media peer: the bring-up script routes only the configured PCSCF=, so a target taken from PCSCF_DISCOVERED= (set by hand in this tree), or a route lost with the PDN, had no route. The start line prints that target; a resume still follows the kernel's SA peer and now says whether that peer is in today's list. With neither variable and nothing to resume, the fatal names both. Tested: crafter-build test, 8 passed; the configured, discovered, differing (the discovered list's order flipped: the resume stays on the SA peer, the next fresh registration's target is the other address) and empty arms in builds of this series on the dev phone (KPN).
This commit is contained in:
parent
a89ca5a60c
commit
bd52afd931
3 changed files with 105 additions and 43 deletions
79
AGENTS.md
79
AGENTS.md
|
|
@ -79,8 +79,9 @@ partition with a test. The shell (`main.cpp`; from 1.0.0 also `pcscf.cpp`'s
|
|||
QRTR control lookup and its matching of answers by type, transaction and
|
||||
message id) holds protocol decisions no
|
||||
test reaches — some older than 0.3.10, some added by 0.3.10, 0.3.11, 0.3.12 or 1.0.0: the P-CSCF in
|
||||
use (`pcscf_`: the kernel's SA peer at a resume, `PCSCF=` at a fresh
|
||||
registration, the move between them and back — §7.2); the reg-event
|
||||
use (`pcscf_`: the kernel's SA peer at a resume, `PCSCF=` or the first of
|
||||
`PCSCF_DISCOVERED=` at a fresh registration, the move between them and back —
|
||||
§7.2); the reg-event
|
||||
subscription schedule (§7.4: its retry
|
||||
ladder, Retry-After clamp, Timer F, renewal point and RFC 6665 reasons); the
|
||||
registration sequence and its transactions (`AwaitFinal`/`AwaitInitialFinal`:
|
||||
|
|
@ -496,10 +497,14 @@ a 5-minute registration gate, connect retries). `Restart=on-failure`,
|
|||
|
||||
The daemon's own bring-up (`BringUp()` in `main.cpp`):
|
||||
|
||||
1. `PCSCF=` is where a fresh registration goes; a resume needs none — the
|
||||
kernel's SAs name its P-CSCF (step 3). With none set, a bring-up that did
|
||||
not resume fails with `no P-CSCF for a fresh registration: …`, and since
|
||||
no fresh one follows: a resumable pair whose attempt failed (a silent
|
||||
1. The P-CSCF a fresh registration goes to is `PCSCF=` when set, else the
|
||||
first address of `PCSCF_DISCOVERED=` (a comma-separated IPv6 list read
|
||||
from the environment; nothing in this tree writes it yet, so a bench sets
|
||||
it by hand); the journal says which (`pcscf: configured …` / `pcscf:
|
||||
discovered … (using …)`). A resume needs neither: the kernel's SAs name
|
||||
its P-CSCF (step 3). With neither, a bring-up that did not resume fails
|
||||
with `no P-CSCF for a fresh registration: …`, and since no fresh one
|
||||
follows: a resumable pair whose attempt failed (a silent
|
||||
connect, an unanswered refresh, a first refusal without a Retry-After —
|
||||
the refusal count goes to the holds) stays for the restart to resume, unless the engine's rule
|
||||
ends it — a 401, a refusal with a Retry-After or the second refusal
|
||||
|
|
@ -507,8 +512,7 @@ The daemon's own bring-up (`BringUp()` in `main.cpp`):
|
|||
refusal is the second) give the resume up, a 403 once a fresh registration
|
||||
is due or a binding a NOTIFY terminated under the attempt write the
|
||||
registration off (`old_gone`) — so the pair counts as one nothing can
|
||||
resume; a pair nothing can resume (its UE address left
|
||||
the link, no state file, a file another attempt left behind, written off before this start or by the engine during the attempt, `RESUME=0`) is taken out of the kernel first (`the SA pair to …
|
||||
resume; a pair nothing can resume (its UE address left the link, no state file, a file another attempt left behind, written off before this start or by the engine during the attempt, `RESUME=0`) is taken out of the kernel first (`the SA pair to …
|
||||
is nothing to resume: removing it` — by exact key, what two rules select — the fingerprinted policies and the reqid-1/2 transport-mode ESP states in their direction or on the UE's ims-PDN address, §12), so the next bring-up finds nothing to resume; the holds
|
||||
keep the Retry-After of a refusal and, for a registration the engine wrote
|
||||
off, the write-off — a removed pair needs none.
|
||||
|
|
@ -550,7 +554,8 @@ The daemon's own bring-up (`BringUp()` in `main.cpp`):
|
|||
registered fresh at every restart; an upgraded phone with such a setting
|
||||
stops at bring-up with the spelling to use. A resume follows the kernel's SA peer (`SaPeer`), not
|
||||
`PCSCF=`: a registration made to another P-CSCF than today's setting is
|
||||
resumed there (`pcscf: resuming on …`) and moves at the next fresh
|
||||
resumed there (`pcscf: resuming on …`; imsd routes that peer itself once
|
||||
`ParseExistingSa` confirms the SAs) and moves at the next fresh
|
||||
registration (`the fresh registration moves from P-CSCF X to Y`; an
|
||||
attempt that fails before the SA setup goes back while the old registration
|
||||
still stands — not written off by its address leaving the link, a NOTIFY
|
||||
|
|
@ -560,12 +565,13 @@ The daemon's own bring-up (`BringUp()` in `main.cpp`):
|
|||
`spi_uc`/`spi_us` against the pair's (`FileNamesAnotherPair`), a 0.3.x
|
||||
file's too: an attempt that got through the SA setup and did not live to
|
||||
record, to this or another P-CSCF — is not used; the
|
||||
bring-up registers fresh (with no fresh target: the fatal, step 1). Every fresh registration goes to `PCSCF=`; with
|
||||
none set, a bring-up that cannot resume fails with `no P-CSCF for a fresh
|
||||
registration: …` and a recovery step that needs one restarts the daemon
|
||||
through systemd.
|
||||
4. **Fresh registration** otherwise (`FRESH registration`): an unprotected
|
||||
REGISTER on `PCSCF_PORT` (UDP, always), the 401 with the AKA challenge and
|
||||
bring-up registers fresh (with no fresh target: the fatal, step 1). Every fresh registration goes to `PCSCF=`, else the first
|
||||
entry of `PCSCF_DISCOVERED=` that `CanonicalIp6` accepts; with neither, a bring-up that cannot resume fails
|
||||
with `no P-CSCF for a fresh registration: …` and a recovery step that
|
||||
needs one restarts the daemon through systemd.
|
||||
4. **Fresh registration** otherwise (`FRESH registration`): the target's host
|
||||
route (imsd's own `ip -6 route replace`; step 3 says which target), an
|
||||
unprotected REGISTER on `PCSCF_PORT` (UDP, always), the 401 with the AKA challenge and
|
||||
the `Security-Server` list, the AKA run over a UIM logical channel
|
||||
(`--uim-open-logical-channel`, `--uim-send-apdu`), the SA pair installed
|
||||
with `ip xfrm`, the protected REGISTER over the negotiated transport
|
||||
|
|
@ -674,9 +680,9 @@ configures the muxed netdev. Idempotent; a non-zero exit fails the unit.
|
|||
uncompressed one by the daemon with the spelling to use once the route
|
||||
step took it); anything else on the IMS
|
||||
network (its DNS servers, a traceroute target) needs its own host route
|
||||
(`ip -6 route add <addr> dev qmapmux0.0`). imsd installs a host route per
|
||||
media peer itself, and one to the SA peer of a registration it resumes
|
||||
when that differs from the fresh target (§7.2).
|
||||
(`ip -6 route add <addr> dev qmapmux0.0`). imsd installs a host route
|
||||
per media peer itself, and one to the P-CSCF it registers to or resumes on
|
||||
(§7.2 step 3).
|
||||
- Opens imsd's protected ports 45061–45062 (TCP and UDP) on `qmapmux*` in
|
||||
nftables when a `inet filter` table exists (pmOS's default INPUT chain drops
|
||||
inbound on `qmapmux*`, which silently killed every network-initiated
|
||||
|
|
@ -930,16 +936,20 @@ Lines the operator (and the scripts) look for, all prefixed `imsd: `:
|
|||
until the next fresh attempt`, `X has left DEV: the registration on it is
|
||||
gone; staying on Y; next: …`, `X is no longer on DEV: the registration on
|
||||
it is gone; on the PDN's own address Y now; next: …`.
|
||||
- `pcscf: resuming on X, the registration's SA peer; the configured P-CSCF
|
||||
is Y — the next fresh registration moves there` (or `… (no P-CSCF
|
||||
configured)`), `the fresh registration moves from P-CSCF X to Y`, `back to
|
||||
P-CSCF X: the old registration stands until the next fresh attempt`,
|
||||
`no reg state file; resume falls back to fresh` and `the state file names
|
||||
- `pcscf: configured X` / `pcscf: configured X; discovery gave Y, Z (ignored:
|
||||
PCSCF= wins)` / `pcscf: discovered Y, Z (using Y)` at start, `pcscf:
|
||||
PCSCF_DISCOVERED entry '…' is not an IPv6 address; ignored`; `pcscf:
|
||||
resuming on X, the registration's SA peer; the next fresh registration
|
||||
goes to Y` (+ ` (the peer is not in today's list)`, or `… (no P-CSCF
|
||||
configured or discovered)`), `the fresh registration moves from P-CSCF X
|
||||
to Y`, `back to P-CSCF X: the old registration stands until the next fresh
|
||||
attempt`, `no reg state file; resume falls back to fresh` and `the state file names
|
||||
another SA pair (0x…/0x…[ to X]) than the kernel's (0x…/0x… to Y): another
|
||||
attempt's; resume falls back to fresh` (` to X` only when the file records a
|
||||
P-CSCF — a pre-1.0.0 file does not; with no fresh target both end in
|
||||
`nothing can resume it: the pair is removed` instead), `no P-CSCF for a fresh
|
||||
registration: none configured (PCSCF=)`.
|
||||
`nothing can resume it: the pair is removed` instead), `no P-CSCF for a
|
||||
fresh registration: none configured (PCSCF=) and none discovered
|
||||
(PCSCF_DISCOVERED empty)`.
|
||||
- `PCSCF='…' is not written as ip prints it; use PCSCF=…` (under `bring-up
|
||||
FAILED:`) — one accepted spelling of the setting (§7.2 step 3); the
|
||||
bring-up script's `ims-pdn-up: PCSCF '…': write the bare address, as ip
|
||||
|
|
@ -1184,7 +1194,19 @@ minimum `/etc/imsd.env` are in the README.
|
|||
|
||||
The README's first table. The protected client/server ports are fixed at
|
||||
45061/45062 (`imsd::util::PortUc`/`PortUs`) — changing them in source also
|
||||
requires updating the firewall rules `ims-pdn-up.sh` installs.
|
||||
requires updating the firewall rules `ims-pdn-up.sh` installs. `PCSCF` and
|
||||
`PCSCF_DISCOVERED` are read at start (`FreshPcscfFromEnv`, for the start line
|
||||
and again by the engine): the first is one address in RFC 5952 form (§7.2 step 3: another spelling is
|
||||
refused at bring-up), and wins, the second a comma-separated IPv6 list whose
|
||||
first entry `CanonicalIp6` accepts is the fresh target otherwise (an IPv4
|
||||
address, a name, a literal with a zone or a dotted-quad tail is logged and
|
||||
skipped). A resume goes to the kernel's SA
|
||||
peer whatever they say (and routes it itself); beyond the resume's `pcscf:`
|
||||
line, having a fresh target decides what a refused or failed resume
|
||||
leads to — the fresh registration (a refusal without a Retry-After is not
|
||||
counted) or, with none, the pair kept for the restart or removed (§7.2
|
||||
step 1) — and a comma-separated `PCSCF=` stops the bring-up before the
|
||||
resume.
|
||||
|
||||
### 10.2 imsd-media (per call, set through imsd's environment)
|
||||
|
||||
|
|
@ -1272,9 +1294,8 @@ only the imsd side of its bus choice.
|
|||
(`DUMP_SIP=0`), and never leave the phone in a commit.
|
||||
- The ims PDN is a walled garden: `ims-pdn-up.sh` keeps it from becoming
|
||||
the default route and gives the P-CSCF a host route; imsd adds one per
|
||||
call for the media peer (§7.3) and, at a resume, one for the registration's
|
||||
SA peer when that differs from the fresh target (§7.2: the script routed
|
||||
only the configured address). Nothing else is routed over it.
|
||||
call for the media peer (§7.3) and one for the P-CSCF it registers to or resumes on (§7.2 step 3; the
|
||||
script routes only the configured address). Nothing else is routed over it.
|
||||
A change that routes anything else over it needs a reason and a bench.
|
||||
- The fixed protected ports (45061/45062) are opened in nftables for
|
||||
`qmapmux*` only, by the bring-up script.
|
||||
|
|
|
|||
|
|
@ -98,7 +98,8 @@ session and root may place, answer and end calls; an ssh login may not.
|
|||
|
||||
| Variable | Default | Meaning |
|
||||
|---|---|---|
|
||||
| `PCSCF` | *(none)* | 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. 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. Without it a fresh registration fails with a clear error |
|
||||
| `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` | *(empty)* | a comma-separated IPv6 P-CSCF list, the first of which is used when `PCSCF` is unset; 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. imsd reads it from its environment; nothing in this tree writes it yet (a bench sets it in `/etc/imsd.env`) |
|
||||
| `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` |
|
||||
| `LOCAL` | *(auto)* | UE address (compared in RFC 5952 form). The packaged service gets the PDN address ModemManager assigned, via `/run/imsd.env` from `ims-pdn-up.sh`; a manual run prefers a global IPv6 on `DEV` that is neither temporary nor `dynamic` (RA-derived), then any non-temporary one, then the first (the kernel's temporary SLAAC address is listed first, and a registration bound to it is lost when the kernel retires it) |
|
||||
|
|
|
|||
|
|
@ -295,6 +295,20 @@ void LogAudioSession() {
|
|||
Log(AudioSessionLine(s) + (s.name.empty() ? "; looked up again at each call, set AUDIO_USER to pin one" : ""));
|
||||
}
|
||||
|
||||
// The P-CSCF a fresh registration goes to, from the environment: PCSCF=
|
||||
// when set (one address, any spelling — a list is left as it came and
|
||||
// refused at bring-up), else the first address of PCSCF_DISCOVERED=, the
|
||||
// list the bring-up read from the PDN's PCO (comma-separated IPv6, PCO
|
||||
// order). `discovered` and `rejected` get the list and what was not an
|
||||
// IPv6 literal, for the caller's log lines.
|
||||
std::string FreshPcscfFromEnv(std::vector<std::string>* discovered = nullptr, std::vector<std::string>* rejected = nullptr) {
|
||||
std::string configured = imsd::util::CanonicalAddr(EnvOr("PCSCF", ""));
|
||||
std::vector<std::string> list = imsd::util::ParseAddressList(EnvOr("PCSCF_DISCOVERED", ""), rejected);
|
||||
if (discovered) *discovered = list;
|
||||
if (!configured.empty()) return configured;
|
||||
return list.empty() ? std::string() : list.front();
|
||||
}
|
||||
|
||||
// ---- sockaddr helper ------------------------------------------------------
|
||||
socklen_t MakeAddr(std::string_view ip, int port, sockaddr_storage& ss) {
|
||||
std::memset(&ss, 0, sizeof ss);
|
||||
|
|
@ -942,11 +956,25 @@ void PostEvent(std::unique_ptr<Event> ev) {
|
|||
class Engine {
|
||||
public:
|
||||
Engine() {
|
||||
// The P-CSCF a fresh registration goes to: PCSCF= (no baked-in
|
||||
// default — carrier infrastructure). A resume follows the kernel's
|
||||
// SAs instead (TryResume), whatever this says today.
|
||||
pcscfTarget_ = imsd::util::CanonicalAddr(EnvOr("PCSCF", ""));
|
||||
// The P-CSCF a fresh registration goes to: PCSCF= when set, else the
|
||||
// first address the bring-up read from the PDN's PCO
|
||||
// (PCSCF_DISCOVERED=); no baked-in default — carrier infrastructure.
|
||||
// A resume follows the kernel's SAs instead (TryResume), whatever
|
||||
// this says today.
|
||||
{
|
||||
std::vector<std::string> rejected;
|
||||
pcscfTarget_ = FreshPcscfFromEnv(&pcscfCandidates_, &rejected);
|
||||
pcscf_ = pcscfTarget_;
|
||||
std::string configured = imsd::util::CanonicalAddr(EnvOr("PCSCF", ""));
|
||||
std::string list;
|
||||
for (const std::string& c : pcscfCandidates_) list += (list.empty() ? "" : ", ") + c;
|
||||
if (!configured.empty())
|
||||
Log(pcscfCandidates_.empty() ? std::format("pcscf: configured {}", configured)
|
||||
: std::format("pcscf: configured {}; discovery gave {} (ignored: PCSCF= wins)", configured, list));
|
||||
else if (!pcscfCandidates_.empty())
|
||||
Log(std::format("pcscf: discovered {} (using {})", list, pcscfTarget_));
|
||||
for (const std::string& r : rejected) Log(std::format("pcscf: PCSCF_DISCOVERED entry '{}' is not an IPv6 address; ignored", r));
|
||||
}
|
||||
pcscfPort_ = std::atoi(EnvOr("PCSCF_PORT", "5060").c_str());
|
||||
dev_ = EnvOr("DEV", "qmapmux0.0");
|
||||
outDir_ = EnvOr("OUT_DIR", StateDir());
|
||||
|
|
@ -1156,13 +1184,15 @@ private:
|
|||
|
||||
// config
|
||||
std::string pcscf_, dev_, outDir_, local_, ealgOffer_, mediaBin_;
|
||||
// The P-CSCF a fresh registration goes to (PCSCF=). pcscf_ is the one in
|
||||
// The P-CSCF a fresh registration goes to (PCSCF=, else the first of
|
||||
// PCSCF_DISCOVERED=) and the whole discovered list. pcscf_ is the one in
|
||||
// use: the same, or the kernel's SA peer while a resumed registration
|
||||
// made to another one lives (TryResume) — the next fresh registration
|
||||
// moves to the target, and back when it fails before the SA setup
|
||||
// (FreshRecover), as local_ does against pdnLocal_.
|
||||
std::string pcscfTarget_;
|
||||
static constexpr std::string_view NoFreshPcscf = "no P-CSCF for a fresh registration: none configured (PCSCF=)";
|
||||
std::vector<std::string> pcscfCandidates_;
|
||||
static constexpr std::string_view NoFreshPcscf = "no P-CSCF for a fresh registration: none configured (PCSCF=) and none discovered (PCSCF_DISCOVERED empty)";
|
||||
// The PDN's own address (LOCAL, else DetectLocal) — every fresh
|
||||
// registration's. local_ differs from it only while a resume runs on the
|
||||
// address an older registration was made on (TryResume).
|
||||
|
|
@ -1352,6 +1382,11 @@ private:
|
|||
local_ = pdnLocal_; ctx_.local = local_;
|
||||
KeepHolds();
|
||||
pcscf_ = pcscfTarget_;
|
||||
// the target's host route is imsd's own: the bring-up script routes only
|
||||
// the configured address (§7.2 step 3), not a target set in /etc/imsd.env
|
||||
// as PCSCF_DISCOVERED= nor a route lost with the PDN — the same idempotent
|
||||
// replace as a media peer's
|
||||
RunCmd({"ip", Is6(pcscf_) ? "-6" : "-4", "route", "replace", pcscf_, "dev", dev_});
|
||||
if (recovery_.Next(Boot()).at > Boot()) Log(std::format("the network's hold stands; {}", NextStep()));
|
||||
if (!WaitForPolicy()) throw Stopping{};
|
||||
FreshRegister();
|
||||
|
|
@ -1373,13 +1408,12 @@ private:
|
|||
// the replace covers a target that changed under a running phone.
|
||||
auto peer = imsd::ipsec::SaPeer(policy.out);
|
||||
if (!peer) return ResumeOutcome::None;
|
||||
bool routePeer = false;
|
||||
if (*peer != pcscf_) {
|
||||
bool listed = *peer == pcscfTarget_ || std::ranges::find(pcscfCandidates_, *peer) != pcscfCandidates_.end();
|
||||
Log(pcscfTarget_.empty()
|
||||
? std::format("pcscf: resuming on {}, the registration's SA peer (no P-CSCF configured)", *peer)
|
||||
: std::format("pcscf: resuming on {}, the registration's SA peer; the configured P-CSCF is {} — the next fresh registration moves there", *peer, pcscfTarget_));
|
||||
? std::format("pcscf: resuming on {}, the registration's SA peer (no P-CSCF configured or discovered)", *peer)
|
||||
: std::format("pcscf: resuming on {}, the registration's SA peer; the next fresh registration goes to {}{}", *peer, pcscfTarget_, listed ? "" : " (the peer is not in today's list)"));
|
||||
pcscf_ = *peer;
|
||||
routePeer = true; // routed below, once the SAs are confirmed: a peer named by a pair that is not ours gets no route into the PDN
|
||||
}
|
||||
auto sa = imsd::ipsec::ParseExistingSa(state.out, policy.out, pcscf_, local_);
|
||||
// The registration may sit on another address of the link: before
|
||||
|
|
@ -1403,7 +1437,10 @@ private:
|
|||
}
|
||||
}
|
||||
if (!sa) { Log(std::format("the SA pair to {} has no SA on an address of {}: nothing to resume", pcscf_, dev_)); return ResumeOutcome::Dead; }
|
||||
if (routePeer) RunCmd({"ip", Is6(pcscf_) ? "-6" : "-4", "route", "replace", pcscf_, "dev", dev_});
|
||||
// the peer's host route is imsd's own once the SAs are confirmed (a peer
|
||||
// named by a pair that is not ours gets no route into the PDN), whether
|
||||
// or not the bring-up script routed the same address — idempotent
|
||||
RunCmd({"ip", Is6(pcscf_) ? "-6" : "-4", "route", "replace", pcscf_, "dev", dev_});
|
||||
auto ps = LoadState();
|
||||
if (!ps || !ps->callid) { Log(std::format("no reg state file; {}", ResumeDeadNext())); return ResumeOutcome::Dead; }
|
||||
// A file another attempt left behind — one that got through the SA
|
||||
|
|
@ -2046,6 +2083,8 @@ private:
|
|||
Log(std::format("the fresh registration moves from {} to the PDN's own address {}", local_, pdnLocal_));
|
||||
MoveTo(pdnLocal_);
|
||||
}
|
||||
// the fresh target's host route, imsd's own (BringUp's fresh path does the same)
|
||||
RunCmd({"ip", Is6(pcscf_) ? "-6" : "-4", "route", "replace", pcscf_, "dev", dev_});
|
||||
bool ok = false;
|
||||
try {
|
||||
RefreshPani();
|
||||
|
|
@ -2680,7 +2719,8 @@ int main(int argc, char** argv) {
|
|||
return 1;
|
||||
}
|
||||
local = imsd::util::CanonicalAddr(local);
|
||||
Log(std::format("LOCAL={} P-CSCF=[{}]:{}", local, imsd::util::CanonicalAddr(EnvOr("PCSCF", "(unset)")), EnvOr("PCSCF_PORT", "5060")));
|
||||
std::string freshPcscf = FreshPcscfFromEnv();
|
||||
Log(std::format("LOCAL={} P-CSCF=[{}]:{}", local, freshPcscf.empty() ? "(none)" : freshPcscf, EnvOr("PCSCF_PORT", "5060")));
|
||||
if (!session) LogAudioSession();
|
||||
imsd::bus::AuthorizeCalls = !session;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue