lynxis lazus has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/erlang/osmo_dia2gsup/+/35006?usp=email )


Change subject: WIP: diameter: add support for Cx (VoLTE)
......................................................................

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 <[email protected]>
+;;
+;; 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 <[email protected]>
+;; Author: Alexander Couzens <[email protected]>
+;;
+;; 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 <[email protected]>
+;;
+;; 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 <[email protected]>
+;; Author: Alexander Couzens <[email protected]>
+;;
+;; 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 
https://gerrit.osmocom.org/c/erlang/osmo_dia2gsup/+/35006?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: erlang/osmo_dia2gsup
Gerrit-Branch: master
Gerrit-Change-Id: Icd623563c495fb6da4216bb6f74bc31873dc7d6e
Gerrit-Change-Number: 35006
Gerrit-PatchSet: 1
Gerrit-Owner: lynxis lazus <[email protected]>
Gerrit-MessageType: newchange

Reply via email to