<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Harish S</title>
    <description>The latest articles on DEV Community by Harish S (@harish_s).</description>
    <link>https://dev.to/harish_s</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1814542%2Fc29e8896-4e1c-4684-a877-5aef28fce2b2.jpg</url>
      <title>DEV Community: Harish S</title>
      <link>https://dev.to/harish_s</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/harish_s"/>
    <language>en</language>
    <item>
      <title>Building a 3GPP-Compliant IMS Core on Kamailio: P-CSCF, I-CSCF, and S-CSCF for 4G and 5G</title>
      <dc:creator>Harish S</dc:creator>
      <pubDate>Sun, 27 Sep 2026 10:55:54 +0000</pubDate>
      <link>https://dev.to/harish_s/building-a-3gpp-compliant-ims-core-on-kamailio-p-cscf-i-cscf-and-s-cscf-for-4g-and-5g-213n</link>
      <guid>https://dev.to/harish_s/building-a-3gpp-compliant-ims-core-on-kamailio-p-cscf-i-cscf-and-s-cscf-for-4g-and-5g-213n</guid>
      <description>&lt;h2&gt;
  
  
  The gap
&lt;/h2&gt;

&lt;p&gt;Kamailio ships a set of IMS building-block modules — ims_registrar_pcscf, ims_usrloc_pcscf, ims_charging, ims_qos, ims_icscf, ims_auth, ims_registrar_scscf, ims_usrloc_scscf, ims_isc, ims_topos, and a few more — and they're a genuinely useful starting point for anyone building IMS signaling. But out of the box they get you maybe 60% of the way to a spec-compliant P-CSCF, I-CSCF, or S-CSCF: no 5G Service-Based Interface (SBI) support at all (everything is Diameter-only), no clustering-safe storage for charging sessions or contact/IMPU state, and — as I found auditing the code while extending it — a handful of memory-safety bugs and race conditions in security-sensitive paths like IPsec SA management.&lt;/p&gt;

&lt;p&gt;This post walks through what I built to close that gap: a dual-stack (4G Diameter + 5G HTTP/2 JSON SBI) IMS core, packaged as a set of Kamailio modules that either extend the stock ims_* family or add new ones alongside it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's genuinely new
&lt;/h2&gt;

&lt;p&gt;ims_pcscf is the module that plugs the biggest hole in the stock P-CSCF stack: a place to keep P-CSCF-specific per-registration state that doesn't belong in usrloc or registrar. It owns GRUU tracking and RFC 5627 Annex-C temp-GRUU generation, P-Access-Network-Info insertion, P-Charging-Vector construction (with IOI and P-Charging-Function-Addresses) — critically, stripping any UE-supplied charging vector before regenerating it server-side, since letting a UE set its own billing correlation ID is a real security hole — emergency-session detection per TS 24.229 §5.16, barred-identity enforcement, a lawful-intercept duplication hook, TLS-on-Gm detection, SigComp negotiation detection, and the logic deciding whether a call needs IMS-AGW/rtpengine media anchoring.&lt;/p&gt;

&lt;p&gt;ims_qos_5g is the 5G sibling to ims_qos. Where ims_qos speaks Diameter Rx to a PCRF (TS 29.214), 5G moved that function to the PCF over N5 — an HTTP/2 + JSON interface (TS 29.514, following TS 29.500/29.521 SBI conventions). Because the transport and data model are unrelated to Diameter, this is a new module rather than a patch: AppSession create/update/delete, handling PCF-originated notifications (the N5 equivalent of an Rx RAR), optional BSF-based PCF discovery, IP-CAN event subscriptions, and its own retry/backoff engine running on a dedicated forked timer process so retries never block mod_init or SIP workers.&lt;/p&gt;

&lt;p&gt;ims_icscf_sbi and ims_scscf_sbi solve the same problem for the HSS-facing side: 5G has no Diameter equivalent at all here, so the I-CSCF and S-CSCF instead call Nhss_imsSDM (profile), Nhss_imsUEAU (auth vectors), and Nhss_imsUECM (server assignment) — all TS 29.562 JSON resources. Both modules are pure C bind APIs with no script functions of their own; ims_icscf, ims_auth, and ims_registrar_scscf call into them, and a network_mode parameter picks Cx/Diameter or Nhss/SBI per deployment, with no silent fallback if the wrong one is misconfigured. One nice side effect of the design: the 5G profile response is handed back as the SDM's embedded Cx CxDataType XML rather than a new JSON schema, so the existing usrloc-side XML parser needed zero changes to support 5G ingest.&lt;/p&gt;

&lt;p&gt;Redis storage backends (ims_charging_redis, ims_usrloc_pcscf_redis, ims_usrloc_scscf_redis) plug into pluggable storage-API vtables already present in the forked modules (ro_storage_api for charging, pcontact_storage_api for usrloc). Stock Kamailio keeps Ro/Rf charging sessions and usrloc contacts in process memory (or optionally SQL); neither survives a clean restart gracefully or fits a horizontally-scaled deployment well. These modules make that state live in Redis via HSET/EXPIRE/DEL, with startup recovery that reloads and fully re-attaches in-flight sessions/contacts to their live dialogs — not just a read of stale data.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I fixed in the existing modules
&lt;/h2&gt;

&lt;p&gt;Extending these modules meant reading almost every line of them, and that surfaced real bugs — not style nits:&lt;/p&gt;

&lt;p&gt;ims_ipsec_pcscf (Gm IPsec / TS 33.203, TS 24.229 sec-agree): a stack buffer over-read building the Security-Server header, an out-of-bounds read parsing WWW-Authenticate, an IK validation bug, mechanism-name comparisons that used prefix matching instead of exact-length matching (so "ipsec-3gpp" could wrongly match a longer string), and — the most serious class — SA install/expire races where a released SPI could be reused before the kernel confirmed the old XFRM state was actually gone. Fixed with an SPI quarantine window and confirmed-delete semantics. Also moved blocking netlink/XFRM calls off the SIP worker processes entirely, since one slow kernel call was previously capable of stalling SIP processing for every call in flight.&lt;br&gt;
ims_usrloc_scscf: a stack overflow in db_insert_ucontact()'s Contact-param packing — unbounded sprintf()/STR_APPEND into fixed buffers, reachable directly from a UE-supplied REGISTER Contact header whenever db_mode writes to a database. Fixed with snprintf() and an explicit bound, skipping (with a warning) any field that doesn't fit rather than writing truncated data.&lt;br&gt;
ims_qos: a double-free in the Experimental-Result-Code path, several missing NULL-checks on pkg_malloc/AAACreateAVP() results and a session pointer dereferenced before a NULL check in the ASR handler, and an off-by-one out-of-bounds read scanning SDP b=AS: bandwidth values.&lt;br&gt;
ims_charging: a Diameter session leak, a race letting a malformed Rf ACR fire twice, a double-ACR-STOP race that could double-free shared memory, and INTERIM ACRs that could fire before their matching START was confirmed — a subtle ordering bug that confuses charging servers expecting START-before-INTERIM.&lt;br&gt;
ims_topos: a Call-ID mask regression, a P-SR-XUID leak, a shared-memory leak on lock-init failure, and — layered on top as a genuine feature — RFC 3323 Privacy: id support, stripping P-Asserted-Identity toward the UE when requested.&lt;/p&gt;

&lt;h2&gt;
  
  
  Standards coverage
&lt;/h2&gt;

&lt;p&gt;Every requirement above (and many smaller ones not listed here) is tracked against its 3GPP/RFC source: TS 24.229 (core SIP signaling), TS 33.203 (Gm/IMS-AKA), TS 29.214 (Rx/PCRF), TS 29.514 with TS 29.500/29.521 (N5/PCF SBI conventions), TS 29.228/29.229 (Cx/Diameter, 4G) and TS 29.562 (Nhss SBI, its 5G equivalent), TS 23.218 (ISC/iFC evaluation), TS 23.003 Annex C (wildcarded PSI), and RFC 3310/2617 (IMS-AKA/Digest), 3323/3325 (Privacy), 3327 (Path), 3608 (Service-Route), 3680 (reg-event), 5627 (GRUU). The repo includes, for each of the three roles, a gap checklist mapping requirement → module → implementation status → file:line evidence, plus an operator-facing companion doc mapping each requirement to the actual kamailio.cfg function/modparam/event-route you'd use to enable it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this is its own project, not a Kamailio PR
&lt;/h2&gt;

&lt;p&gt;I want to be upfront about this because it's an unusual way to publish: I did submit this work as pull requests to the Kamailio project. Kamailio is maintained by a small volunteer team, and a change set of this scope (new Diameter/SBI transports, security-sensitive parsing fixes) needs dedicated IMS test infrastructure and reviewer bandwidth that the project doesn't currently have to spare. That's not a criticism — Kamailio is a large, mature project run mostly on volunteer time, and IMS is a specialized enough corner of it that it's reasonable for review to lag. But the practical result has been that the PRs sit unreviewed and go stale, and operators who need 5G SBI support, restart-safe charging state, or the security fixes above have no way to get them through the normal upstream channel yet.&lt;/p&gt;

&lt;p&gt;So, rather than let the work sit unused, I've decided to maintain it as a standalone project: drop the module directories into any Kamailio source tree's modules/ (or src/modules/ on 5.1+) and build with the normal make modules modules="..." flow — no core patches needed. It's open to contributions, bug reports, and bug fixes from anyone in the community, and it's going to keep being actively developed here rather than waiting on a merge — with the goal of turning it into a full-fledged, standalone IMS core that other applications can integrate with, and of carrying it forward past 4G/5G into whatever core-network generation comes next.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;In final development: MMTelAS (as a B2B UA), ATCF, MGCF, MRF. In planning: BGCF, BCF/IBCF, HSS/UDM. On the longer-term roadmap, moving toward a complete 5G core: AMF, UPF, AUSF, SMF, PCF, NRF.&lt;/p&gt;

&lt;p&gt;Repo, full module-by-module changelog, 3GPP gap checklists, and reference configs for P-CSCF/I-CSCF/S-CSCF (4G-only, 5G-only, and combined): &lt;a href="https://github.com/toharish/IMS" rel="noopener noreferrer"&gt;https://github.com/toharish/IMS&lt;/a&gt;&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>backend</category>
      <category>networking</category>
      <category>softwareengineering</category>
    </item>
  </channel>
</rss>
