lynxis lazus has uploaded this change for review.

View Change

WIP: diameter: add support for Cx (VoLTE)

Change-Id: Icd623563c495fb6da4216bb6f74bc31873dc7d6e
---
M dia/diameter_3gpp_ts29_229.dia
A dia/diameter_3gpp_ts29_229_cx.dia
A dia/diameter_etsi_es283_035.dia
A dia/diameter_rfc4740.dia
A dia/diameter_rfc8583.dia
A src/osmo_cx2gsup.erl
A src/osmo_cx2gsup_cb.erl
M src/osmo_dia2gsup_sup.erl
8 files changed, 991 insertions(+), 12 deletions(-)

git pull ssh://gerrit.osmocom.org:29418/erlang/osmo_dia2gsup refs/changes/06/35006/1
diff --git a/dia/diameter_3gpp_ts29_229.dia b/dia/diameter_3gpp_ts29_229.dia
index efaa147..557fed7 100644
--- a/dia/diameter_3gpp_ts29_229.dia
+++ b/dia/diameter_3gpp_ts29_229.dia
@@ -24,6 +24,8 @@
@vendor 10415 3GPP

@inherits diameter_gen_base_rfc6733
+@inherits diameter_etsi_es283_035
+@inherits diameter_rfc4005_nasreq

;; only attributes required by other applications are defined

@@ -32,7 +34,7 @@
Visited-Network-Identifier 600 OctetString MV
Public-Identity 601 UTF8String MV
Server-Name 602 UTF8String MV
-;; Server-Capabilities 603 Grouped MV
+ Server-Capabilities 603 Grouped MV
Mandatory-Capability 604 Unsigned32 MV
Optional-Capability 605 Unsigned32 MV
User-Data 606 OctetString MV
@@ -41,10 +43,10 @@
SIP-Authenticate 609 OctetString MV
SIP-Authorization 610 OctetString MV
SIP-Authentication-Context 611 OctetString MV
-;; SIP-Auth-Data-Item 612 Grouped MV
+ SIP-Auth-Data-Item 612 Grouped MV
SIP-Item-Number 613 Unsigned32 MV
Server-Assignment-Type 614 Enumerated MV
-;; Deregistration-Reason 615 Grouped MV
+ Deregistration-Reason 615 Grouped MV
Reason-Code 616 Enumerated MV
Reason-Info 617 UTF8String MV
Charging-Information 618 Grouped MV
@@ -60,38 +62,50 @@
Feature-List-ID 629 Unsigned32 V
Feature-List 630 Unsigned32 V
Supported-Applications 631 Grouped V
-;; Associated-Identities 632 Grouped V
+ Associated-Identities 632 Grouped V
Originating-Request 633 Enumerated MV
Wildcarded-Public-Identity 634 UTF8String V
-;; SIP-Digest-Authenticate 635 Grouped V
+ SIP-Digest-Authenticate 635 Grouped V
Digest-Realm 104 UTF8String M ;; RFC-4590
Digest-Algorithm 111 UTF8String M ;; RFC-4590
Digest-QoP 110 UTF8String M ;; RFC-4590
Digest-HA1 121 UTF8String M ;; RFC-4590
UAR-Flags 637 Unsigned32 V
Loose-Route-Indication 638 Enumerated V
-;; SCSCF-Restoration-Info 639 Grouped V
+ SCSCF-Restoration-Info 639 Grouped V
Path 640 OctetString V
Contact 641 OctetString V
-;; Subscription-Info 642 Grouped V
+ Subscription-Info 642 Grouped V
Call-ID-SIP-Header 643 OctetString V
From-SIP-Header 644 OctetString V
To-SIP-Header 645 OctetString V
Record-Route 646 OctetString V
-;; Associated-Registered-Identities 647 Grouped V
+ Associated-Registered-Identities 647 Grouped V
Multiple-Registration-Indication 648 Enumerated V
-;; Restoration-Info 649 Grouped V
+ Restoration-Info 649 Grouped V
Session-Priority 650 Enumerated V
-;; Identity-with-Emergency-Registration 651 Grouped V
+ Identity-with-Emergency-Registration 651 Grouped V
Priviledged-Sender-Indication 652 Enumerated V
LIA-Flags 653 Unsigned32 V
;; OC-Supported-Features TBD Grouped - ;; IETF draft-ietf-dime-02
;; OC-OLR TBD Grouped - ;; IETF draft-ietf-dime-02
Initial-CSeq-Sequence-Number 654 Unsigned32 V
SAR-Flags 655 Unsigned32 V
+ Allowed-WAF-WWSF-Identities 656 Grouped V
+ RTR-Flags 659 Unsigned32 V
+ P-CSCF-Subscription-Info 660 Grouped V
+ Registration-Time-Out 661 Time V
+ PCSCF-FQDN 665 DiameterIdentity V

@grouped

+;; 6.3.4 Server-Capabilities AVP
+ Server-Capabilities ::= <AVP Header: 603 10415>
+ *[Mandatory-Capability]
+ *[Optional-Capability]
+ *[Server-Name]
+ *[AVP]
+
Charging-Information ::= < AVP Header : 618 >
[ Primary-Event-Charging-Function-Name ]
[ Secondary-Event-Charging-Function-Name ]
@@ -110,3 +124,109 @@
*[ Acct-Application-Id ]
*[ Vendor-Specific-Application-Id ]
*[ AVP ]
+
+;; 6.3.13
+ SIP-Auth-Data-Item ::= < AVP Header: 612 10415 >
+ [ SIP-Item-Number ]
+ [ SIP-Authentication-Scheme ]
+ [ SIP-Authenticate ]
+ [ SIP-Authorization ]
+ [ SIP-Authentication-Context ]
+ [ Confidentiality-Key ]
+ [ Integrity-Key ]
+ [ SIP-Digest-Authenticate ]
+ [ Framed-IP-Address ]
+ [ Framed-IPv6-Prefix ]
+ [ Framed-Interface-Id ]
+ *[ Line-Identifier ]
+ *[AVP]
+
+;; 6.3.16
+ Deregistration-Reason ::= < AVP Header: 615 10415 >
+ { Reason-Code }
+ [ Reason-Info ]
+ * [AVP]
+
+;; 6.3.33 Associated-Identities
+ Associated-Identities ::= < AVP Header: 632 10415 >
+ *[ User-Name ]
+ *[ AVP ]
+
+;; 6.3.36
+ SIP-Digest-Authenticate ::= < AVP Header: 635 10415>
+ { Digest-Realm }
+ { Digest-QoP }
+ { Digest-HA1}
+ [ Digest-Algorithm ]
+ *[ AVP ]
+
+;; 6.3.46 SCSCF-Restoration-Info AVP
+ SCSCF-Restoration-Info ::= < AVP Header: 639 10415>
+ { User-Name }
+ 1* { Restoration-Info }
+ [ Registration-Time-Out ]
+ [ SIP-Authentication-Scheme ]
+ *[ AVP ]
+
+;; 6.3.49 Subscription-Info AVP
+ Subscription-Info ::= < AVP Header: 642 10415>
+ { Call-ID-SIP-Header }
+ { From-SIP-Header }
+ { To-SIP-Header }
+ { Record-Route }
+ {Contact}
+ *[ AVP ]
+
+;; 6.3.50 Associated-Registered-Identities
+Associated-Registered-Identities ::= < AVP Header: 647 10415 >
+ *[ User-Name ]
+ *[ AVP ]
+
+;; 6.3.52 Restoration-Info AVP
+ Restoration-Info ::= < AVP Header: 649 10415>
+ { Path }
+ { Contact }
+ [ Initial-CSeq-Sequence-Number ]
+ [ Call-ID-SIP-Header ]
+ [ Subscription-Info ]
+ [ P-CSCF-Subscription-Info ]
+ *[ AVP ]
+
+;; 6.3.57 Identity-with-Emergency-Registration
+ Identity-with-Emergency-Registration ::= < AVP Header: 651 10415 >
+ { User-Name }
+ { Public-Identity }
+ *[ AVP ]
+
+;; 6.3.64 Allowed-WAF-WWSF-Identities AVP
+ Allowed-WAF-WWSF-Identities ::= < AVP Header: 656 10415 >
+ ;; *[ WebRTC-Authentication-Function-Name ]
+ ;; *[ WebRTC-Web-Server-Function-Name ]
+ *[ AVP]
+
+;; 6.3.70 P-CSCF-Subscription-Info AVP
+ P-CSCF-Subscription-Info ::= < AVP Header: 660 10415>
+ { Call-ID-SIP-Header }
+ { From-SIP-Header }
+ { To-SIP-Header }
+ { Contact }
+ *[ AVP ]
+
+;; 6.3.15
+@enum Server-Assignment-Type
+ NO_ASSIGNMENT 0
+ REGISTRATION 1
+ RE_REGISTRATION 2
+ UNREGISTERED_USER 3
+ TIMEOUT_DEREGISTRATION 4
+ USER_DEREGISTRATION 5
+ TIMEOUT_DEREGISTRATION_STORE_SERVER_NAME 6
+ USER_DEREGISTRATION_STORE_SERVER_NAME 7
+ ADMINISTRATIVE_DEREGISTRATION 8
+ AUTHENTICATION_FAILURE 9
+ AUTHENTICATION_TIMEOUT 10
+ DEREGISTRATION_TOO_MUCH_DATA 11
+ AAA_USER_DATA_REQUEST 12
+ PGW_UPDATE 13
+ RESTORATION 14
+
diff --git a/dia/diameter_3gpp_ts29_229_cx.dia b/dia/diameter_3gpp_ts29_229_cx.dia
new file mode 100644
index 0000000..2f0fc7b
--- /dev/null
+++ b/dia/diameter_3gpp_ts29_229_cx.dia
@@ -0,0 +1,326 @@
+;;
+;; %CopyrightBegin%
+;;
+;; Copyright (C) 2023 by Alexander Couzens <lynxis@fe80.eu>
+;;
+;; This resembles 3GPP TS 29.272 version 17.2.0 Release 17
+;;
+;; Licensed under the Apache License, Version 2.0 (the "License");
+;; you may not use this file except in compliance with the License.
+;; You may obtain a copy of the License at
+;;
+;; http://www.apache.org/licenses/LICENSE-2.0
+;;
+;; Unless required by applicable law or agreed to in writing, software
+;; distributed under the License is distributed on an "AS IS" BASIS,
+;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+;; See the License for the specific language governing permissions and
+;; limitations under the License.
+;;
+;; %CopyrightEnd%
+;;
+
+;;
+;; Edits:
+;;
+;;
+
+
+@id 16777216
+@name diameter_3gpp_ts29_229_cx
+@vendor 10415 3GPP
+
+@inherits diameter_gen_base_rfc6733
+@inherits diameter_3gpp_base
+@inherits diameter_3gpp_break_circles
+@inherits diameter_3gpp_ts29_212
+@inherits diameter_3gpp_ts29_214
+@inherits diameter_3gpp_ts29_229
+@inherits diameter_3gpp_ts29_272
+@inherits diameter_3gpp_ts32_299
+@inherits diameter_etsi_es283_034
+@inherits diameter_rfc4006_cc
+@inherits diameter_rfc5447
+@inherits diameter_rfc5778
+@inherits diameter_rfc7683
+@inherits diameter_rfc7944
+@inherits diameter_rfc8583
+
+@avp_types
+
+ ;; 6.3.74
+ Failed-PCSCF 664 Grouped MV
+ ;; 6.3.76
+ PCSCF-IP-Address 666 Address V
+ ;; 6.3.16
+
+@grouped
+Failed-PCSCF ::= < AVP Header: 664>
+ [ PCSCF-FQDN ]
+ *[ PCSCF-IP-Address ]
+ *[ AVP ]
+
+
+
+@messages
+
+;; 6.1.1 User-Authorization-Request (UAR) Command
+ UAR ::= < Diameter Header: 300, REQ, PXY >
+ < Session-Id >
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { User-Name }
+ { Vendor-Specific-Application-Id }
+ { Public-Identity }
+ { Visited-Network-Identifier }
+ [ Destination-Host ]
+ [ DRMP ]
+ [ OC-Supported-Features ]
+ * [ Supported-Features ]
+ [ User-Authorization-Type ]
+ [ UAR-Flags ]
+ * [ AVP ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+
+;; 6.1.2 User-Authorization-Answer (UAA) Command
+ UAA ::= < Diameter Header: 300, PXY >
+ < Session-Id >
+ { Vendor-Specific-Application-Id }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ [ DRMP ]
+ [ Result-Code ]
+ [ Experimental-Result ]
+ [ OC-Supported-Features ]
+ [ OC-OLR ]
+ * [ Load ]
+ * [ Supported-Features ]
+ [ Server-Name ]
+ [ Server-Capabilities ]
+ * [ AVP ]
+ [ Failed-AVP ]
+ * [ Proxy-Info ]
+ * [ Route-Record ]
+
+;; 6.1.3 Server-Assignment-Request (SAR) Command
+ SAR ::= < Diameter Header: 301, REQ, PXY>
+ < Session-Id >
+ { Vendor-Specific-Application-Id }
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Realm }
+ { Server-Name }
+ { Server-Assignment-Type }
+ { User-Data-Already-Available }
+ [ DRMP ]
+ [ Destination-Host ]
+ [ User-Name ]
+ [ OC-Supported-Features ]
+ *[ Supported-Features ]
+ *[ Public-Identity ]
+ [ Wildcarded-Public-Identity ]
+ [ SCSCF-Restoration-Info ]
+ [ Multiple-Registration-Indication ]
+ [ Session-Priority ]
+ [ SAR-Flags ]
+ [ Failed-PCSCF ]
+ *[ AVP ]
+ *[ Proxy-Info ]
+ *[ Route-Record ]
+
+
+;; 6.1.4 Server-Assignment-Answer (SAA) Command
+ SAA ::= < Diameter Header: 301, PXY>
+ < Session-Id >
+ { Vendor-Specific-Application-Id }
+ { Origin-Realm }
+ { Origin-Host }
+ { Auth-Session-State }
+ [ Wildcarded-Public-Identity ]
+ [ User-Name ]
+ [ User-Data ]
+ [ Server-Name ]
+ [ Result-Code ]
+ [ Priviledged-Sender-Indication ]
+ [ OC-Supported-Features ]
+ [ OC-OLR ]
+ [ Loose-Route-Indication ]
+ [ Failed-AVP ]
+ [ Experimental-Result ]
+ [ DRMP ]
+ [ Charging-Information ]
+ [ Associated-Registered-Identities ]
+ [ Associated-Identities ]
+ [ Allowed-WAF-WWSF-Identities ]
+ *[ Supported-Features ]
+ *[ SCSCF-Restoration-Info ]
+ *[ Route-Record ]
+ *[ Proxy-Info ]
+ *[ Load ]
+ *[ AVP ]
+
+;; 6.1.5 Location-Info-Request (LIR) Command
+ LIR ::= < Diameter Header: 302, REQ, PXY>
+ < Session-Id >
+ { Vendor-Specific-Application-Id }
+ { Public-Identity }
+ { Origin-Realm }
+ { Origin-Host }
+ { Destination-Realm }
+ { Auth-Session-State }
+ [ User-Authorization-Type ]
+ [ Session-Priority ]
+ [ Originating-Request ]
+ [ OC-Supported-Features ]
+ [ Destination-Host ]
+ [ DRMP ]
+ *[ Supported-Features ]
+ *[ Route-Record ]
+ *[ Proxy-Info ]
+ *[ AVP ]
+
+
+;; 6.1.6 Location-Info-Answer (LIA) Command
+ LAI ::= < Diameter Header: 302, PXY>
+ < Session-Id >
+ { Vendor-Specific-Application-Id }
+ { Origin-Realm }
+ { Origin-Host }
+ { Auth-Session-State }
+ [ Wildcarded-Public-Identity ]
+ [ Server-Name ]
+ [ Server-Capabilities ]
+ [ Result-Code ]
+ [ OC-Supported-Features ]
+ [ OC-OLR ]
+ [ LIA-Flags ]
+ [ Failed-AVP ]
+ [ Experimental-Result ]
+ [ DRMP ]
+ *[ Supported-Features ]
+ *[ Route-Record ]
+ *[ Proxy-Info ]
+ *[ Load ]
+ *[ AVP ]
+
+;; 6.1.7 Multimedia-Auth-Request (MAR) Command
+ MAR ::= < Diameter Header: 303, REQ, PXY >
+ < Session-Id >
+ { Vendor-Specific-Application-Id }
+ { User-Name }
+ { Server-Name }
+ { SIP-Number-Auth-Items }
+ { SIP-Auth-Data-Item }
+ { Public-Identity }
+ { Origin-Realm }
+ { Origin-Host }
+ { Destination-Realm }
+ { Auth-Session-State }
+ [ OC-Supported-Features ]
+ [ Destination-Host ]
+ [ DRMP ]
+ *[ Supported-Features ]
+ *[ Route-Record ]
+ *[ Proxy-Info ]
+ *[ AVP ]
+
+;; 6.1.8 Multimedia-Auth-Answer (MAA) Command
+ MAA ::= < Diameter Header: 303, PXY>
+ < Session-Id >
+ { Vendor-Specific-Application-Id }
+ { Origin-Realm }
+ { Origin-Host }
+ { Auth-Session-State }
+ [ User-Name ]
+ [ SIP-Number-Auth-Items ]
+ [ Result-Code ]
+ [ Public-Identity ]
+ [ OC-Supported-Features ]
+ [ OC-OLR ]
+ [ Failed-AVP ]
+ [ Experimental-Result ]
+ [ DRMP ]
+ *[SIP-Auth-Data-Item ]
+ *[ Supported-Features ]
+ *[ Route-Record ]
+ *[ Proxy-Info ]
+ *[ Load ]
+ *[ AVP ]
+
+;; 6.1.9 Registration-Termination-Request (RTR) Command
+ RTR ::= < Diameter Header: 304, REQ, PXY>
+ < Session-Id >
+ { Vendor-Specific-Application-Id }
+ { User-Name }
+ { Origin-Realm }
+ { Origin-Host }
+ { Destination-Realm }
+ { Deregistration-Reason }
+ { Auth-Session-State }
+ [ RTR-Flags ]
+ [ DRMP ]
+ [ Associated-Identities ]
+ *[ Supported-Features ]
+ *[ Route-Record ]
+ *[ Public-Identity ]
+ *[ Proxy-Info ]
+ *[ AVP ]
+
+;; 6.1.10 Registration-Termination-Answer (RTA) Command
+ RTA ::= < Diameter Header: 304, PXY >
+ < Session-Id >
+ { Vendor-Specific-Application-Id }
+ { Origin-Realm }
+ { Origin-Host }
+ { Auth-Session-State }
+ [ Result-Code ]
+ [ Failed-AVP ]
+ [ Experimental-Result ]
+ [ DRMP ]
+ [ Associated-Identities ]
+ *[ Supported-Features ]
+ *[ Route-Record ]
+ *[ Proxy-Info ]
+ *[ Identity-with-Emergency-Registration ]
+ *[ AVP ]
+
+;; 6.1.11 Push-Profile-Request (PPR) Command
+ PPR ::= < Diameter Header: 305, REQ, PXY>
+ < Session-Id >
+ { Vendor-Specific-Application-Id }
+ { User-Name }
+ { Origin-Realm }
+ { Origin-Host }
+ { Destination-Realm }
+ { Destination-Host }
+ { Auth-Session-State }
+ [ User-Data ]
+ [ SIP-Auth-Data-Item ]
+ [ DRMP ]
+ [ Charging-Information ]
+ [ Allowed-WAF-WWSF-Identities ]
+ *[ Supported-Features ]
+ *[ Route-Record ]
+ *[ Proxy-Info ]
+ *[ AVP ]
+
+;; 6.1.12 Push-Profile-Answer (PPA) Command
+ PAA::= < Diameter Header: 305, PXY>
+ < Session-Id >
+ { Vendor-Specific-Application-Id }
+ { Origin-Realm }
+ { Origin-Host }
+ { Auth-Session-State }
+ [Result-Code ]
+ [ Failed-AVP ]
+ [ Experimental-Result ]
+ [ DRMP ]
+ *[ Supported-Features ]
+ *[ Route-Record ]
+ *[ Proxy-Info ]
+ *[ AVP ]
diff --git a/dia/diameter_etsi_es283_035.dia b/dia/diameter_etsi_es283_035.dia
new file mode 100644
index 0000000..c0baff2
--- /dev/null
+++ b/dia/diameter_etsi_es283_035.dia
@@ -0,0 +1,75 @@
+;;
+;; %CopyrightBegin%
+;;
+;; Copyright (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+;; Author: Alexander Couzens <lynxis@fe80.eu>
+;;
+;; This resembles 3GPP TS 29.273 version 15.4.0 Release 15
+;;
+;; Licensed under the Apache License, Version 2.0 (the "License");
+;; you may not use this file except in compliance with the License.
+;; You may obtain a copy of the License at
+;;
+;; http://www.apache.org/licenses/LICENSE-2.0
+;;
+;; Unless required by applicable law or agreed to in writing, software
+;; distributed under the License is distributed on an "AS IS" BASIS,
+;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+;; See the License for the specific language governing permissions and
+;; limitations under the License.
+;;
+;; %CopyrightEnd%
+;;
+
+@id 16777231
+@name diameter_etsi_es283_035
+@prefix diameter_e4
+@vendor 13019 ETSI
+
+@inherits diameter_gen_base_rfc6733
+
+;; only attributes required by other applications are defined
+
+@avp_types
+
+ Location-Information 350 Grouped V ;; 7.3.1
+ Policy-Control-Contact-Point 351 DiameterIdentity V ;; 7.3.2
+ Terminal-Type 352 OctetString V ;; 7.3.3
+ Requested-Information 353 Enumerated V ;; 7.3.4
+ Event-Type 354 Enumerated V ;; 7.3.6
+ Line-Identifier 500 OctetString V ;; 7.3.5
+ Civic-Location 355 OctetString V ;; 7.3.1.A
+ Geospatial-Location 356 OctetString V ;; 7.3.1.B
+
+@grouped
+;; 7.3.1
+ Location-Information ::= < AVP Header: 350 13019 >
+ [Line-Identifier]
+ [Civic-Location]
+ [Geospatial-Location]
+ *[AVP]
+
+;; 7.3.4
+@enum Requested-Information
+ IP-CONNECTIVITY-USER-ID 0
+ LOCATION-INFORMATION 1
+ POLICY-CONTROL-CONTACT-POINT 2
+ ACCESS-NETWORK-TYPE 3
+ TERMINAL-TYPE 4
+ LOGICAL-ACCESS-ID 5
+ PHYSICAL-ACCESS-ID 6
+
+;; 7.3.6
+@enum Event-Type
+ USER-LOGON 0
+ LOCATION-INFORMATION-CHANGED 1
+ POLICY-CONTROL-CONTACT-POINT-CHANGED 2
+ ACCESS-NETWORK-TYPE-CHANGED 3
+ TERMINAL-TYPE-CHANGED 4
+ LOGICAL-ACCESS-ID-CHANGED 5
+ PHYSICAL-ACCESS-ID-CHANGED 6
+ IP-ADDRESS-CHANGED 7
+ INITIAL-GATE-SETTING-CHANGED 8
+ QOS-PROFILE-CHANGED 9
+ USER-LOGOFF 10
+
diff --git a/dia/diameter_rfc4740.dia b/dia/diameter_rfc4740.dia
new file mode 100644
index 0000000..5515cb7
--- /dev/null
+++ b/dia/diameter_rfc4740.dia
@@ -0,0 +1,42 @@
+;;
+;; %CopyrightBegin%
+;;
+;; Transcribed from RFC 4740 by Alexander Couzens <lynxis@fe80.eu>
+;;
+;; Licensed under the Apache License, Version 2.0 (the "License");
+;; you may not use this file except in compliance with the License.
+;; You may obtain a copy of the License at
+;;
+;; http://www.apache.org/licenses/LICENSE-2.0
+;;
+;; Unless required by applicable law or agreed to in writing, software
+;; distributed under the License is distributed on an "AS IS" BASIS,
+;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+;; See the License for the specific language governing permissions and
+;; limitations under the License.
+;;
+;; %CopyrightEnd%
+;;
+
+;;
+;; RFC 4740, Diameter Session Initiation Protocol (SIP) Application
+;;
+
+@id 1
+
+@inherits diameter_gen_base_rfc6733
+
+;; ===========================================================================
+
+@avp_types
+
+ ERP-RK-Request 618 Grouped -
+ ERP-Realm 619 DiameterIdentity -
+
+;; ===========================================================================
+
+@grouped
+
+ERP-RK-Request ::= < AVP Header: 618 >
+ { ERP-Realm }
+ * [ AVP ]
diff --git a/dia/diameter_rfc8583.dia b/dia/diameter_rfc8583.dia
new file mode 100644
index 0000000..59df542
--- /dev/null
+++ b/dia/diameter_rfc8583.dia
@@ -0,0 +1,54 @@
+;;
+;; %CopyrightBegin%
+;;
+;; Copyright (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+;; Author: Alexander Couzens <lynxis@fe80.eu>
+;;
+;; This resembles 3GPP TS 29.273 version 15.4.0 Release 15
+;;
+;; Licensed under the Apache License, Version 2.0 (the "License");
+;; you may not use this file except in compliance with the License.
+;; You may obtain a copy of the License at
+;;
+;; http://www.apache.org/licenses/LICENSE-2.0
+;;
+;; Unless required by applicable law or agreed to in writing, software
+;; distributed under the License is distributed on an "AS IS" BASIS,
+;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+;; See the License for the specific language governing permissions and
+;; limitations under the License.
+;;
+;; %CopyrightEnd%
+;;
+
+;;
+;; Edits:
+;;
+;;
+
+@id 1
+@inherits diameter_gen_base_rfc6733
+
+;; only used AVP are defined here.
+
+;; ===========================================================================
+
+@avp_types
+
+ SourceID 649 DiameterIdentity - ;; 7.4
+ Load 650 Grouped - ;; 7.1
+ Load-Type 651 Enumerated - ;; 7.2
+ Load-Value 652 Unsigned64 - ;; 7.3
+
+@grouped
+;; 7.1
+ Load ::= < AVP Header: 650 >
+ [ Load-Type ]
+ [ Load-Value ]
+ [ SourceID ]
+ * [ AVP ]
+
+@enum Load-Type
+ HOST 0 ;; The load report is for a host.
+ PEER 1 ;; The load report is for a peer.
+
diff --git a/src/osmo_cx2gsup.erl b/src/osmo_cx2gsup.erl
new file mode 100644
index 0000000..cce7560
--- /dev/null
+++ b/src/osmo_cx2gsup.erl
@@ -0,0 +1,131 @@
+-module(osmo_cx2gsup).
+-behavior(gen_server).
+
+-include_lib("diameter/include/diameter.hrl").
+-include_lib("diameter/include/diameter_gen_base_rfc6733.hrl").
+
+-export([main/1]).
+
+% API
+-export([start_link/0]).
+-export([start/0, stop/0]).
+
+% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2]).
+-export([code_change/3, terminate/2]).
+
+-define(SERVER, ?MODULE).
+
+% Diameter application definitions
+
+-define(VENDOR_ID_3GPP, 10415).
+-define(VENDOR_ID_3GPP2, 5535).
+-define(VENDOR_ID_ETSI, 13019).
+
+-define(DIA_STATS_TAB, iwf_stats).
+-define(DIA_STATS_COUNTERS, [event_OK, event_ERR]).
+
+-define(SVC_NAME, ?MODULE).
+-define(APP_ALIAS, ?MODULE).
+-define(CALLBACK_MOD, osmo_cx2gsup_cb).
+-define(DIAMETER_DICT_CX, diameter_3gpp_ts29_292_cx).
+
+-define(APPID_CX, #'diameter_base_Vendor-Specific-Application-Id'{'Vendor-Id'=10415, 'Auth-Application-Id'=[16777216]}).
+-define(SERVICE(Name), [{'Origin-Host', application:get_env(osmo_cx2gsup, origin_host, "hss.localdomain")},
+ {'Origin-Realm', application:get_env(osmo_cx2gsup, origin_realm, "localdomain")},
+ {'Vendor-Id', application:get_env(osmo_cx2gsup, vendor_id, 0)},
+ {'Origin-State-Id', diameter:origin_state_id()},
+ {'Product-Name', "osmo_dia2gsup"},
+ {'Auth-Application-Id', []},
+ {'Vendor-Specific-Application-Id', [?APPID_CX]},
+ {'Supported-Vendor-Id', [?VENDOR_ID_3GPP, ?VENDOR_ID_ETSI, ?VENDOR_ID_3GPP2]},
+ {application,
+ [{alias, ?APP_ALIAS},
+ {dictionary, ?DIAMETER_DICT_CX},
+ {module, ?CALLBACK_MOD}]
+ }]).
+
+
+
+%% ------------------------------------------------------------------
+%% API
+%% ------------------------------------------------------------------
+
+start_link() ->
+ gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
+
+start() ->
+ application:ensure_all_started(?MODULE),
+ start_link().
+
+stop() ->
+ gen_server:cast(?SERVER, stop).
+
+main(_Args) ->
+ application:ensure_all_started(?MODULE),
+ timer:sleep(infinity).
+
+%% ------------------------------------------------------------------
+%% gen_server Function Definitions
+%% ------------------------------------------------------------------
+
+%% @callback gen_server
+init(State) ->
+ % DIAMETER side
+ SvcName = ?MODULE,
+ diameter:start_service(SvcName, ?SERVICE(SvcName)),
+
+ Ip = application:get_env(osmo_cx2gsup, diameter_ip, "127.0.0.9"),
+ Port = application:get_env(osmo_cx2gsup, diameter_port, 3868),
+ Proto = application:get_env(osmo_cx2gsup, diameter_proto, sctp),
+ ConnectTimer = application:get_env(osmo_cx2gsup, diameter_connect_timer, 30000),
+ listen(?SVC_NAME, {address, Proto, element(2,inet:parse_address(Ip)), Port}, {timer, ConnectTimer}),
+ lager:info("Diameter HSS Application started on IP ~s, ~p port ~p~n", [Ip, Proto, Port]),
+ {ok, State}.
+
+%% @callback gen_server
+handle_call(_Req, _From, State) ->
+ {noreply, State}.
+
+%% @callback gen_server
+handle_cast(stop, State) ->
+ {stop, normal, State};
+handle_cast(_req, State) ->
+ {noreply, State}.
+
+
+%% @callback gen_server
+handle_info(_Info, State) ->
+ {noreply, State}.
+
+%% @callback gen_server
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+%% @callback gen_server
+terminate(normal, _State) ->
+ diameter:stop_service(?SVC_NAME),
+ lager:info("Diameter HSS Application stopped.~n"),
+ ok;
+terminate(shutdown, _State) ->
+ ok;
+terminate({shutdown, _Reason}, _State) ->
+ ok;
+terminate(_Reason, _State) ->
+ ok.
+
+
+
+%% ------------------------------------------------------------------
+%% Internal Function Definitions
+%% ------------------------------------------------------------------
+
+listen(Name, {address, Protocol, IPAddr, Port}, {timer, ConnectTimer}) ->
+ TransOpts = [{transport_module, tmod(Protocol)},
+ {transport_config, [{reuseaddr, true},
+ {ip, IPAddr}, {port, Port}]},
+ {connect_timer, ConnectTimer}],
+ {ok, _} = diameter:add_transport(Name, {listen, TransOpts}).
+
+tmod(tcp) -> diameter_tcp;
+tmod(sctp) -> diameter_sctp.
diff --git a/src/osmo_cx2gsup_cb.erl b/src/osmo_cx2gsup_cb.erl
new file mode 100644
index 0000000..85cb9b3
--- /dev/null
+++ b/src/osmo_cx2gsup_cb.erl
@@ -0,0 +1,217 @@
+-module(osmo_cx2gsup_cb).
+
+
+-include_lib("diameter/include/diameter.hrl").
+-include_lib("diameter/include/diameter_gen_base_rfc6733.hrl").
+-include_lib("diameter_3gpp_ts29_229_cx.hrl").
+-include_lib("osmo_gsup/include/gsup_protocol.hrl").
+
+-define(DIA_VENDOR_3GPP, 10415).
+
+%% diameter callbacks
+-export([peer_up/3, peer_down/3, pick_peer/4, prepare_request/3, prepare_retransmit/3,
+ handle_answer/4, handle_error/4, handle_request/3]).
+
+-define(UNEXPECTED, erlang:error({unexpected, ?MODULE, ?LINE})).
+
+peer_up(_SvcName, {PeerRef, Caps}, State) ->
+ lager:info("Peer up ~p - ~p~n", [PeerRef, lager:pr(Caps, ?MODULE)]),
+ State.
+
+peer_down(_SvcName, {PeerRef, Caps}, State) ->
+ lager:info("Peer down ~p - ~p~n", [PeerRef, lager:pr(Caps, ?MODULE)]),
+ State.
+
+pick_peer(_, _, _SvcName, _State) ->
+ ?UNEXPECTED.
+
+prepare_request(_, _SvcName, _Peer) ->
+ ?UNEXPECTED.
+
+prepare_retransmit(_Packet, _SvcName, _Peer) ->
+ ?UNEXPECTED.
+
+handle_answer(_Packet, _Request, _SvcName, _Peer) ->
+ ?UNEXPECTED.
+
+handle_error(_Reason, _Request, _SvcName, _Peer) ->
+ lager:error("Request error: ~p~n", [_Reason]),
+ ?UNEXPECTED.
+
+
+% transient (only in Experimental-Result-Code)
+-define(DIAMETER_AUTHENTICATION_DATA_UNAVAILABLE, 4181).
+-define(DIAMETER_ERROR_CAMEL_SUBSCRIPTION_PRESENT, 4182).
+% permanent (only in Experimental-Result-Code)
+-define(DIAMETER_ERROR_USER_UNKNOWN, 5001).
+-define(DIAMETER_AUTHORIZATION_REJECTED, 5003).
+-define(DIAMETER_ERROR_ROAMING_NOT_ALLOWED, 5004).
+-define(DIAMETER_MISSING_AVP, 5005).
+-define(DIAMETER_UNABLE_TO_COMPLY, 5012).
+-define(DIAMETER_ERROR_UNKNOWN_EPS_SUBSCRIPTION, 5420).
+-define(DIAMETER_ERROR_RAT_NOT_ALLOWED, 5421).
+-define(DIAMETER_ERROR_EQUIPMENT_UNKNOWN, 5422).
+-define(DIAMETER_ERROR_UNKOWN_SERVING_NODE, 5423).
+
+% 10.5.5.14
+-define(GMM_CAUSE_IMSI_UNKNOWN, 16#02).
+-define(GMM_CAUSE_ILLEGAL_MS, 16#03).
+-define(GMM_CAUSE_GPRS_NOTALLOWED, 16#07).
+-define(GMM_CAUSE_PLMN_NOTALLOWED, 16#0b).
+-define(GMM_CAUSE_LA_NOTALLOWED, 16#0c).
+-define(GMM_CAUSE_ROAMING_NOTALLOWED, 16#0d).
+-define(GMM_CAUSE_NO_SUIT_CELL_IN_LA, 16#0f).
+-define(GMM_CAUSE_NET_FAIL, 16#11).
+-define(GMM_CAUSE_CONGESTION, 16#16).
+-define(GMM_CAUSE_GSM_AUTH_UNACCEPT, 16#17).
+-define(GMM_CAUSE_INV_MAND_INFO, 16#60).
+-define(GMM_CAUSE_PROTO_ERR_UNSPEC, 16#6f).
+
+-define(EXP_RES(Exp), #'Experimental-Result'{'Vendor-Id'=?DIA_VENDOR_3GPP, 'Experimental-Result-Code'=Exp}).
+
+%% see 29.272 Annex A/B
+-type empty_or_intl() :: [] | [integer()].
+-spec gsup_cause2dia(integer()) -> {empty_or_intl(), empty_or_intl()}.
+gsup_cause2dia(?GMM_CAUSE_IMSI_UNKNOWN) -> {[], [?EXP_RES(?DIAMETER_ERROR_USER_UNKNOWN)]};
+gsup_cause2dia(?GMM_CAUSE_ILLEGAL_MS) -> {[], [?EXP_RES(?DIAMETER_ERROR_USER_UNKNOWN)]};
+gsup_cause2dia(?GMM_CAUSE_PLMN_NOTALLOWED) -> {[], [?EXP_RES(?DIAMETER_ERROR_ROAMING_NOT_ALLOWED)]};
+gsup_cause2dia(?GMM_CAUSE_GPRS_NOTALLOWED) -> {[], [?EXP_RES(?DIAMETER_ERROR_UNKNOWN_EPS_SUBSCRIPTION)]};
+
+gsup_cause2dia(?GMM_CAUSE_LA_NOTALLOWED) -> {[?DIAMETER_AUTHORIZATION_REJECTED], []};
+gsup_cause2dia(?GMM_CAUSE_ROAMING_NOTALLOWED) -> {[], [?EXP_RES(?DIAMETER_ERROR_ROAMING_NOT_ALLOWED)]};
+gsup_cause2dia(?GMM_CAUSE_NO_SUIT_CELL_IN_LA) -> {[], [?EXP_RES(?DIAMETER_ERROR_UNKNOWN_EPS_SUBSCRIPTION)]};
+gsup_cause2dia(?GMM_CAUSE_NET_FAIL) -> {[?DIAMETER_UNABLE_TO_COMPLY], []};
+gsup_cause2dia(?GMM_CAUSE_CONGESTION) -> {[?DIAMETER_UNABLE_TO_COMPLY], []};
+gsup_cause2dia(?GMM_CAUSE_INV_MAND_INFO) -> {[?DIAMETER_MISSING_AVP], []};
+gsup_cause2dia(?GMM_CAUSE_PROTO_ERR_UNSPEC) -> {[?DIAMETER_UNABLE_TO_COMPLY], []};
+gsup_cause2dia(_) -> {[?DIAMETER_UNABLE_TO_COMPLY], []}.
+
+% get the value for a tiven key in Map1. If not found, try same key in Map2. If not found, return Default
+-spec twomap_get(atom(), map(), map(), any()) -> any().
+twomap_get(Key, Map1, Map2, Default) ->
+ maps:get(Key, Map1, maps:get(Key, Map2, Default)).
+
+dia_sip2gsup(#'SIP-Auth-Data-Item'{'SIP-Authenticate' = [Authenticate], 'SIP-Authorization' = [Authorization],
+ 'Confidentiality-Key' = [CKey], 'Integrity-Key' = [IKey]}) ->
+ #{rand => list_to_binary(lists:sublist(Authenticate, 1, 16)),
+ autn=> list_to_binary(lists:sublist(Authenticate, 17, 16)),
+ res=> list_to_binary(Authorization),
+ ik=> list_to_binary(IKey),
+ ck=> list_to_binary(CKey)}.
+
+-spec gsup_tuple2dia_sip('GSUPAuthTuple'(), integer()) -> #'E-UTRAN-Vector'{}.
+gsup_tuple2dia_sip(#{autn:=Autn, ck:=Ck, ik:=Ik, rand:=Rand, res:=Res}, Idx) ->
+ #'SIP-Auth-Data-Item'{
+ 'SIP-Item-Number' = Idx,
+ 'Confidentiality-Key' = Ck,
+ 'Integrity-Key' = Ik,
+ 'SIP-Authenticate' = lists:merge(Rand, Autn),
+ 'SIP-Authorization' = Res
+ }.
+
+-spec gsup_tuples2dia_sip(['GSUPAuthTuple'()]) -> [#'E-UTRAN-Vector'{}].
+gsup_tuples2dia_sip(List) -> gsup_tuples2dia_sip(List, [], 1).
+gsup_tuples2dia_sip([], Out, _Idx) -> Out;
+gsup_tuples2dia_sip([Head|Tail], Out, Ctr) ->
+ Dia = gsup_tuple2dia_sip(Head, Ctr),
+ gsup_tuples2dia_sip(Tail, [Dia|Out], Ctr+1).
+
+-type int_or_false() :: false | integer().
+-spec gsup_tuples2dia(['GSUPAuthTuple'()], int_or_false()) -> #'Authentication-Info'{}.
+gsup_tuples2dia(Tuples, NumEutran) ->
+ case NumEutran of
+ false -> EutranVecs = [];
+ 0 -> EutranVecs = [];
+ _ -> EutranVecs = gsup_tuples2dia_sip(lists:sublist(Tuples, NumEutran))
+ end,
+ [EutranVecs].
+
+-type binary_or_false() :: false | binary().
+-spec req_resynchronization_info([tuple()]) -> binary_or_false().
+req_resynchronization_info(#'SIP-Auth-Data-Item'{'SIP-Authorization'=[]}) ->
+ false;
+req_resynchronization_info(#'SIP-Auth-Data-Item'{'SIP-Authorization'=[Auth]}) ->
+ list_to_binary(Auth);
+req_resynchronization_info(_) ->
+ false.
+
+% Cx
+handle_request(#diameter_packet{msg = Req, errors = []}, _SvcName, {_, Caps}) when is_record(Req, 'UAR') ->
+ % extract relevant fields from DIAMETER ULR
+ #diameter_caps{origin_host = {OH,_}, origin_realm = {OR,_}} = Caps,
+ #'UAR'{'Session-Id' = SessionId,
+ 'UAR-Flags' = UarFlags,
+ 'User-Name' = UserName} = Req,
+ ServerName = "sip:scscf.core.osmocom.org:6060",
+
+ Resp = #'UAA'{'Session-Id'= SessionId, 'Auth-Session-State'=1,
+ 'Origin-Host'=OH, 'Origin-Realm'=OR,
+ 'Experimental-Result'=2001,
+ 'Server-Name'=ServerName},
+ lager:info("UAA Resp: ~p~n", [Resp]),
+ {reply, Resp};
+
+
+% Server Assignement Request
+handle_request(#diameter_packet{msg = Req, errors = []}, _SvcName, {_, Caps}) when is_record(Req, 'SAR') ->
+ % extract relevant fields from DIAMETER ULR
+ #diameter_caps{origin_host = {OH,_}, origin_realm = {OR,_}} = Caps,
+ #'SAR'{'Session-Id' = SessionId,
+ 'User-Name' = UserName,
+ 'Server-Name' = ServerName,
+ 'Server-Assignment-Type' = Type} = Req,
+ % TODO: Type == 0
+ ServerName = "sip:scscf.core.osmocom.org:6060",
+ Resp = #'SAA'{'Session-Id'= SessionId, 'Auth-Session-State'=1,
+ 'Origin-Host'=OH, 'Origin-Realm'=OR,
+ 'Experimental-Result'=2001,
+ 'User-Name' = UserName,
+ 'Server-Name'=ServerName},
+ lager:info("SAA Resp: ~p~n", [Resp]),
+ {reply, Resp};
+
+
+% Multimedia Authentication Request
+handle_request(#diameter_packet{msg = Req, errors = []}, _SvcName, {_, Caps}) when is_record(Req, 'MAR') ->
+ #diameter_caps{origin_host = {OH,_}, origin_realm = {OR,_}} = Caps,
+ #'MAR'{'Session-Id' = SessionId,
+ 'User-Name' = UserName,
+ 'Server-Name' = ServerName,
+ 'Public-Identity' = PublicIdentity,
+ 'SIP-Auth-Data-Item' = AuthData,
+ 'SIP-Number-Auth-Items' = NumAuthData} = Req,
+ % TODO: parse User-Name and Public-Identity, get the MNC/MCC from it
+ GsupTx1 = #{message_type => send_auth_info_req, imsi => list_to_binary(UserName),
+ supported_rat_types => [rat_eutran_sgs], current_rat_type => rat_eutran_sgs},
+ ResyncInfo = req_resynchronization_info(Req),
+ case ResyncInfo of
+ false ->
+ GsupTx2 = #{};
+ ValidResyncInfo ->
+ GsupTx2 = #{rand => binary:part(ValidResyncInfo, 0, 16),
+ auts => binary:part(ValidResyncInfo, 16, 14)}
+ end,
+ GsupTx = maps:merge(GsupTx1, GsupTx2),
+ GsupRx = gen_server:call(gsup_client, {transceive_gsup, GsupTx, send_auth_info_res, send_auth_info_err}),
+ lager:info("GsupRx: ~p~n", [GsupRx]),
+ case GsupRx of
+ #{message_type:=send_auth_info_res, auth_tuples:=GsupAuthTuples} ->
+ AuthInfo = gsup_tuples2dia(GsupAuthTuples, NumAuthData),
+ Resp = #'MAA'{'Session-Id'=SessionId, 'Origin-Host'=OH, 'Origin-Realm'=OR,
+ 'Experimental-Result'=2001, 'Auth-Session-State'=1,
+ 'SIP-Auth-Data-Item'=AuthInfo};
+ #{message_type := send_auth_info_err, cause:=Cause} ->
+ {Res, ExpRes} = gsup_cause2dia(Cause),
+ Resp = #'MAA'{'Session-Id'=SessionId, 'Origin-Host'=OH, 'Origin-Realm'=OR,
+ 'Result-Code'=Res, 'Experimental-Result'=ExpRes,
+ 'Auth-Session-State'=1};
+ timeout ->
+ Resp = #'MAA'{'Session-Id'=SessionId, 'Origin-Host'=OH, 'Origin-Realm'=OR,
+ 'Result-Code'=4181, 'Auth-Session-State'=1}
+ end,
+ lager:info("Resp: ~p~n", [Resp]),
+ {reply, Resp};
+
+handle_request(Packet, _SvcName, {_,_}) ->
+ lager:error("Unsuppoerted message: ~p~n", [Packet]),
+ discard.
diff --git a/src/osmo_dia2gsup_sup.erl b/src/osmo_dia2gsup_sup.erl
index 03c780d..6047fac 100644
--- a/src/osmo_dia2gsup_sup.erl
+++ b/src/osmo_dia2gsup_sup.erl
@@ -15,9 +15,14 @@
Args = [{local, gsup_client}, gsup_client, [HlrIp, HlrPort, "HSS-00-00-00-00-00-00"], [{debug, [trace]}]],
GsupChild = {gsup_client, {gen_server, start_link, Args}, permanent, 2000, worker, [gsup_client]},
% DIAMETER side
- DiaServer = {osmo_dia2gsup,{osmo_dia2gsup,start_link,[]},
+ S6a = {osmo_dia2gsup,{osmo_dia2gsup,start_link,[]},
permanent,
5000,
worker,
[server_cb]},
- {ok, { {one_for_one, 5, 10}, [DiaServer, GsupChild]} }.
+ Cx = {osmo_cx2gsup, {osmo_cx2gsup,start_link,[]},
+ permanent,
+ 5000,
+ worker,
+ [osmo_cx2gsup_cb]},
+ {ok, { {one_for_one, 5, 10}, [S6a, Cx, GsupChild]} }.

To view, visit change 35006. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: erlang/osmo_dia2gsup
Gerrit-Branch: master
Gerrit-Change-Id: Icd623563c495fb6da4216bb6f74bc31873dc7d6e
Gerrit-Change-Number: 35006
Gerrit-PatchSet: 1
Gerrit-Owner: lynxis lazus <lynxis@fe80.eu>
Gerrit-MessageType: newchange