ui: FPLMN manual-selection clear and duplicate guard (v2.7.19)

Attaching to a PLMN listed in EF.FPLMN used to write successful locations
anyway, i.e. it attached to a forbidden network.  Per TS 23.122 a
successful manual selection removes the entry, so the attach scenarios
clear it first:

- netsim.remove_fplmn() clears every occurrence of the PLMN (entries are
  not compacted; FFFFFF gaps stay); insert_fplmn() returns None when the
  PLMN is already listed, so roaming_denied no longer stores duplicates
  (the live card had '250-99, 250-99').
- clear_fplmn() step, called from write_real_locations() -> covers
  attach_eps, attach_2g and the sms_received location rewrite; the write
  is logged as a normal fplmn update_binary.
- tests: remove_fplmn duplicates/absent/gaps; roaming_denied duplicate
  skip; attach clears both occurrences before the location writes;
  make_runner now copies FakeFileInfo so seeded data does not leak
  between tests.
- help EN/RU and AGENTS updated.
This commit is contained in:
2026-09-21 01:14:45 +03:00
parent dfb7b694f9
commit 0446d2a93c
8 changed files with 101 additions and 14 deletions
+3 -3
View File
@@ -482,14 +482,14 @@
<p class="text-sm mb-2">Воспроизводит шаблоны записи реального телефона при смене сетевых условий (исследование трасс в <code class="font-mono text-sm">projects/UICC_NAA.md</code>): подключение EPS, потеря сервиса / ограниченный сервис, запрет роуминга, откат на 2G, приём SMS, перенастройка cell broadcast и AUTHENTICATE. По кнопке на сценарий; карта должна быть подключена.</p>
<ul class="list-disc list-inside text-sm space-y-1 mb-3">
<li><strong>Холодная загрузка</strong> — инвалидация EPSNSC (KSI 07, ключ стирается) и фиктивные location-файлы.</li>
<li><strong>Подключение EPS / 2G</strong> — запись реального контекста EPS NAS (KSI, KASME, счётчики NAS, алгоритм) и реальных LOCI/PSLOCI/EPSLOCI (в 2G дополнительно реальные Kc/KcGPRS).</li>
<li><strong>Потеря сервиса / ограниченный сервис / запрет роуминга</strong> — событие Location status (только если карта на него подписана), инвалидация EPSNSC (по желанию с сохранением старого KASME), фиктивные location-файлы (LOCI/PSLOCI сохраняют PLMN, LAC <code class="font-mono text-sm">FFFE</code>, статус <code class="font-mono text-sm">01</code>; EPSLOCI стирается до <code class="font-mono text-sm">0B F6</code> + FF&times;13 + <code class="font-mono text-sm">FF FE 01</code>) и инвалидация Kc. <strong>Запрет роуминга</strong> эмулирует постоянный отказ &laquo;PLMN not allowed&raquo; (NAS cause #11): location-файлы получают статус <code class="font-mono text-sm">010</code> (EPSLOCI <code class="font-mono text-sm">0B F6</code> + FF&times;13 + <code class="font-mono text-sm">FF FE 02</code>), запрещённый VPLMN дописывается в <strong>EF.FPLMN</strong> по семантике сдвига из TS 31.102 §4.2.16 (домашняя сеть не записывается), ключевой контекст стирается.</li>
<li><strong>Подключение EPS / 2G</strong> — запись реального контекста EPS NAS (KSI, KASME, счётчики NAS, алгоритм) и реальных LOCI/PSLOCI/EPSLOCI (в 2G дополнительно реальные Kc/KcGPRS). Подключение считается успешным ручным выбором выбранного PLMN: если он есть в EF.FPLMN, его записи сначала очищаются (TS 23.122), поэтому подключение к запрещённой сети не проходит незаметно.</li>
<li><strong>Потеря сервиса / ограниченный сервис / запрет роуминга</strong> — событие Location status (только если карта на него подписана), инвалидация EPSNSC (по желанию с сохранением старого KASME), фиктивные location-файлы (LOCI/PSLOCI сохраняют PLMN, LAC <code class="font-mono text-sm">FFFE</code>, статус <code class="font-mono text-sm">01</code>; EPSLOCI стирается до <code class="font-mono text-sm">0B F6</code> + FF&times;13 + <code class="font-mono text-sm">FF FE 01</code>) и инвалидация Kc. <strong>Запрет роуминга</strong> эмулирует постоянный отказ &laquo;PLMN not allowed&raquo; (NAS cause #11): location-файлы получают статус <code class="font-mono text-sm">010</code> (EPSLOCI <code class="font-mono text-sm">0B F6</code> + FF&times;13 + <code class="font-mono text-sm">FF FE 02</code>), запрещённый VPLMN дописывается в <strong>EF.FPLMN</strong> по семантике сдвига из TS 31.102 §4.2.16 (домашняя сеть не записывается, дубликаты не создаются — уже имеющаяся запись пропускается), ключевой контекст стирается.</li>
<li><strong>Серия переподключений</strong> — реальная → невалидная запись EPSNSC подряд (число циклов и задержка настраиваются).</li>
<li><strong>Принято SMS</strong> — инкремент счётчика EF.SMSstatus (чтение-изменение-запись) и, по желанию, перезапись location-файлов.</li>
<li><strong>Перенастройка CB</strong> — запись списков CBMI/CBMIR или их очистка (все FF).</li>
<li><strong>AUTHENTICATE</strong> — команда AUTHENTICATE (3G/EPS/5G, <code class="font-mono text-sm">00 88 00 81 22</code>) с заданными или случайными RAND/AUTN и показ ответа (успех <code class="font-mono text-sm">DB</code> или ошибка синхронизации <code class="font-mono text-sm">DC</code> с AUTS).</li>
</ul>
<p class="text-sm mb-3"><strong>Параметры</strong> (свёрнуты) задают оператора (поиск по мировому списку MCC/MNC с сервера плюс выбор случайного роуминг-оператора и кнопка <strong>&laquo;Домашняя сеть&raquo;</strong>, заполняющая HPLMN карты из первой записи EF.HPLMNwAcT с откатом на IMSI), LAC/Cell ID/TAC/RAC, необязательные идентификаторы (пусто = случайно: TMSI, GUTI, KSI, KASME, Kc, счётчики NAS, алгоритм, RAND/AUTN), переключатели сценария (включая <strong>&laquo;Отказ: записать FPLMN&raquo;</strong>) и число циклов/задержку. Журнал шагов показывает каждую запись, ENVELOPE и AUTHENTICATE с их SW. Отправляются только UPDATE BINARY/RECORD, ENVELOPE и AUTHENTICATE — FPLMN записывается только сценарием постоянного отказа (TS 31.102 §4.2.16), а 5GS location-файлы не записываются; записи меняют карту и видны в последующих сравнениях снимков.</p>
<p class="text-sm mb-3"><strong>Параметры</strong> (свёрнуты) задают оператора (поиск по мировому списку MCC/MNC с сервера плюс выбор случайного роуминг-оператора и кнопка <strong>&laquo;Домашняя сеть&raquo;</strong>, заполняющая HPLMN карты из первой записи EF.HPLMNwAcT с откатом на IMSI), LAC/Cell ID/TAC/RAC, необязательные идентификаторы (пусто = случайно: TMSI, GUTI, KSI, KASME, Kc, счётчики NAS, алгоритм, RAND/AUTN), переключатели сценария (включая <strong>&laquo;Отказ: записать FPLMN&raquo;</strong>) и число циклов/задержку. Журнал шагов показывает каждую запись, ENVELOPE и AUTHENTICATE с их SW. Отправляются только UPDATE BINARY/RECORD, ENVELOPE и AUTHENTICATE — FPLMN дописывается только сценарием постоянного отказа (TS 31.102 §4.2.16, без дубликатов), а подключение к сети из списка сначала очищает её запись (успешный ручной выбор, TS 23.122); 5GS location-файлы не записываются; записи меняют карту и видны в последующих сравнениях снимков.</p>
<h4 id="network-state" class="font-medium mb-1">Монитор сетевого состояния</h4>
<p class="text-sm mb-3">Рядом с кнопками симуляции компактная панель <strong>&laquo;Сетевое состояние&raquo;</strong> показывает, что сейчас хранит карта и что было сэмулировано последним. В заголовке — <strong>сэмулированное состояние сервиса</strong>: <em>Не определено</em>, пока его не задаст сценарий или событие Location status, затем <em>Обычный сервис</em> (зелёный), <em>Ограниченный сервис</em> (жёлтый) или <em>Нет сервиса</em> (красный), с красной пометкой <em>PLMN не разрешён</em>, если location-файлы или EF.FPLMN указывают на отказ регистрации — плюс текущее <strong>местоположение</strong>: PLMN, страна и оператор (из необязательного мирового списка MCC/MNC, если он загружен), LAI/RAI/TAI и <strong>класс роуминга</strong> (<em>Домашняя сеть</em>, если PLMN совпадает с HPLMN; <em>Эквивалентная домашней</em>, если он есть в EF.EHPLMN; иначе <em>Гостевая (роуминг)</em>). Ниже — по одной компактной строке на контролируемый файл (IMSI, EHPLMN, SPDI, HPLMNwAcT, LOCI, PSLOCI, EPSLOCI, EPSNSC, CBMI, CBMIR, SMSstatus, FPLMN) с декодированной сводкой и признаком последнего обновления (<code class="font-mono text-sm">init</code>, <code class="font-mono text-sm">write</code>, <code class="font-mono text-sm">read</code>, <code class="font-mono text-sm">refresh</code>); при наведении — все декодированные поля; длинные списки PLMN сокращаются (EF.HPLMNwAcT показывает только первую сеть и пометку <code class="font-mono text-sm">… +N</code>, а технологии доступа — в подсказке). Панель читает файлы один раз при подключении карты (только если ICCID читается), обновляет их на месте по записанным симулятором байтам, перечитывает EF.IMSI после каждого сценария и события Location status (мульти-IMSI апплеты) и никогда не опрашивает карту — кнопка <strong>&laquo;Обновить&raquo;</strong> перечитывает все файлы по требованию.</p>