From 7d9359fdfc68608dec993703ac6a3edc6048b71c Mon Sep 17 00:00:00 2001 From: Roman Janota Date: Wed, 15 Jul 2026 04:01:08 +0200 Subject: [PATCH 1/2] server UPDATE add ietf-yp-transport-capabilities support --- ...-yp-transport-capabilities@2026-05-15.yang | 146 +++++ scripts/common.sh | 1 + src/main.c | 120 +++- ...subscribed-notif-receivers@2024-02-01.yang | 110 ++++ tests/modules/ietf-tls-client@2024-03-16.yang | 525 ++++++++++++++++++ tests/modules/ietf-udp-client@2025-05-14.yang | 104 ++++ .../ietf-udp-notif-transport@2025-06-04.yang | 189 +++++++ tests/np2_test.c | 12 + tests/test_sub_ntf_advanced.c | 52 +- 9 files changed, 1256 insertions(+), 3 deletions(-) create mode 100644 modules/ietf-yp-transport-capabilities@2026-05-15.yang create mode 100644 tests/modules/ietf-subscribed-notif-receivers@2024-02-01.yang create mode 100644 tests/modules/ietf-tls-client@2024-03-16.yang create mode 100644 tests/modules/ietf-udp-client@2025-05-14.yang create mode 100644 tests/modules/ietf-udp-notif-transport@2025-06-04.yang diff --git a/modules/ietf-yp-transport-capabilities@2026-05-15.yang b/modules/ietf-yp-transport-capabilities@2026-05-15.yang new file mode 100644 index 00000000..513c3ac1 --- /dev/null +++ b/modules/ietf-yp-transport-capabilities@2026-05-15.yang @@ -0,0 +1,146 @@ +module ietf-yp-transport-capabilities { + yang-version 1.1; + namespace + "urn:ietf:params:xml:ns:yang:ietf-yp-transport-capabilities"; + prefix ntc; + + import ietf-subscribed-notifications { + prefix sn; + reference + "RFC 8639: Subscription to YANG Notifications"; + } + import ietf-system-capabilities { + prefix sysc; + reference + "RFC 9196: YANG Modules Describing Capabilities for + Systems and Datastore Update Notifications"; + } + import ietf-notification-capabilities { + prefix notc; + reference + "RFC 9196: YANG Modules Describing Capabilities for + Systems and Datastore Update Notifications"; + } + import ietf-tls-common { + prefix tlscmn; + reference + "RFC 9645: YANG Groupings for TLS Clients and TLS Servers"; + } + + organization + "IETF NETCONF (Network Configuration) Working Group"; + contact + "WG Web: + WG List: + + Authors: Qin Wu + + Qiufang Ma + + Alex Huang Feng + + Thomas Graf + "; + description + "This module defines an extension to YANG-Push + Notification Capabilities model that provides additional + transport specific capabilities for YANG notifications. + + The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', 'SHALL + NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', 'NOT RECOMMENDED', + 'MAY', and 'OPTIONAL' in this document are to be interpreted as + described in BCP 14 (RFC 2119) (RFC 8174) when, and only when, + they appear in all capitals, as shown here. + + Copyright (c) 2026 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Revised BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (http://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC XXXX + (https://www.rfc-editor.org/info/rfcXXXX); see the RFC itself + for full legal notices."; + + revision 2026-05-15 { + description + "Initial revision."; + reference + "RFC XXXX: YANG Notifications Transport Capabilities"; + } + + identity security-protocol { + description + "Identity for YANG notifications security protocols."; + } + + identity dtls12 { + base security-protocol; + description + "Indicates DTLS Protocol Version 1.2. DTLS 1.2 is obsolete, + and thus it is NOT RECOMMENDED to enable this feature."; + reference + "RFC 6347: The Datagram Transport Layer Security (DTLS) + Protocol Version 1.2."; + } + + identity dtls13 { + base security-protocol; + description + "Indicates DTLS Protocol Version 1.3."; + reference + "RFC 9147: The Datagram Transport Layer Security (DTLS) + Protocol Version 1.3."; + } + + augment "/sysc:system-capabilities" + + "/notc:subscription-capabilities" { + description + "Adds subscription-related system level capabilities."; + container transport-capabilities { + description + "Specifies capabilities related to YANG-Push transports."; + list transport-capability { + key "transport-protocol"; + description + "Indicates supported YANG notifications transport protocol + for Subscribed Notifications [RFC8639] and YANG-Push + [RFC8641]. Defines the supported transports, security + protocols and supported notification encodings."; + leaf transport-protocol { + type identityref { + base sn:transport; + } + description + "Indicates the supported YANG notifications transport + protocol for Subscribed Notifications [RFC8639] and + YANG-Push [RFC8641]."; + } + leaf-list security-protocol { + type union { + type identityref { + base security-protocol; + } + type identityref { + base tlscmn:tls-version-base; + } + } + description + "Indicates the supported YANG notifications transport + encryption protocols."; + } + leaf-list encoding-format { + type identityref { + base sn:encoding; + } + description + "Indicates supported encoding formats for YANG notifications."; + } + } + } + } +} diff --git a/scripts/common.sh b/scripts/common.sh index e2e49758..2d4ffabb 100644 --- a/scripts/common.sh +++ b/scripts/common.sh @@ -15,6 +15,7 @@ NP2_MODULES=( "netopeer-notifications@2026-01-05.yang" "ietf-system-capabilities@2022-02-17.yang" "ietf-notification-capabilities@2022-02-17.yang" +"ietf-yp-transport-capabilities@2026-05-15.yang" "ietf-netconf-private-candidate@2026-02-03.yang -e private-candidate" ) diff --git a/src/main.c b/src/main.c index 083dfb12..3e98889f 100644 --- a/src/main.c +++ b/src/main.c @@ -531,6 +531,114 @@ np2srv_content_id_cb(void *UNUSED(user_data)) return strdup(buf); } +/** + * @brief Add UDP-Notif transport capability to the transport-capabilities node. + * + * @param[in] transport_capas transport-capabilities container node. + * @param[in] yptc_mod ietf-yp-transport-capabilities module. + * @param[in] unt_mod ietf-udp-notif-transport module. + * @param[in] sn_mod ietf-subscribed-notifications module, may be NULL. + * @return 0 on success, -1 on error. + */ +static int +np2srv_add_udp_notif_transport_capability(struct lyd_node *transport_capas, + const struct lys_module *yptc_mod, const struct lys_module *unt_mod, + const struct lys_module *sn_mod) +{ + struct lyd_node *cap = NULL; + int rc = 0; + + if (lyd_new_list(transport_capas, yptc_mod, "transport-capability", 0, &cap, + "ietf-udp-notif-transport:udp-notif")) { + ERR("Failed to create transport-capability."); + rc = -1; + goto cleanup; + } + + /* security-protocol */ + if (lys_feature_value(unt_mod, "dtls") == LY_SUCCESS) { + if (lyd_new_term(cap, yptc_mod, "security-protocol", "ietf-yp-transport-capabilities:dtls12", 0, NULL)) { + ERR("Failed to create security-protocol dtls12."); + rc = -1; + goto cleanup; + } + if (lyd_new_term(cap, yptc_mod, "security-protocol", "ietf-yp-transport-capabilities:dtls13", 0, NULL)) { + ERR("Failed to create security-protocol dtls13."); + rc = -1; + goto cleanup; + } + } + + /* encoding-format */ + if (sn_mod && (lys_feature_value(sn_mod, "encode-xml") == LY_SUCCESS)) { + if (lyd_new_term(cap, yptc_mod, "encoding-format", "ietf-subscribed-notifications:encode-xml", 0, NULL)) { + ERR("Failed to create encoding-format encode-xml."); + rc = -1; + goto cleanup; + } + } + if (sn_mod && (lys_feature_value(sn_mod, "encode-json") == LY_SUCCESS)) { + if (lyd_new_term(cap, yptc_mod, "encoding-format", "ietf-subscribed-notifications:encode-json", 0, NULL)) { + ERR("Failed to create encoding-format encode-json."); + rc = -1; + goto cleanup; + } + } + if (lys_feature_value(unt_mod, "encode-cbor") == LY_SUCCESS) { + if (lyd_new_term(cap, yptc_mod, "encoding-format", "ietf-udp-notif-transport:encode-cbor", 0, NULL)) { + ERR("Failed to create encoding-format encode-cbor."); + rc = -1; + goto cleanup; + } + } + +cleanup: + return rc; +} + +/** + * @brief Add transport capabilities to a subscription-capabilities node. + * + * @param[in] subs_capas subscription-capabilities node. + * @param[in] ly_ctx libyang context. + * @return SR_ERR_OK on success, -1 on error. + */ +static int +np2srv_add_transport_capabilities(struct lyd_node *subs_capas, const struct ly_ctx *ly_ctx) +{ + const struct lys_module *yptc_mod, *unt_mod, *sn_mod; + struct lyd_node *transport_capas = NULL; + int rc = SR_ERR_OK; + + yptc_mod = ly_ctx_get_module_implemented(ly_ctx, "ietf-yp-transport-capabilities"); + if (!yptc_mod) { + goto cleanup; + } + + unt_mod = ly_ctx_get_module_implemented(ly_ctx, "ietf-udp-notif-transport"); + if (!unt_mod) { + /* no transport module implemented, do not create an empty container */ + goto cleanup; + } + + /* transport-capabilities */ + if (lyd_new_path(subs_capas, ly_ctx, "ietf-yp-transport-capabilities:transport-capabilities", + NULL, 0, &transport_capas)) { + ERR("Failed to create transport-capabilities."); + rc = -1; + goto cleanup; + } + + sn_mod = ly_ctx_get_module_implemented(ly_ctx, "ietf-subscribed-notifications"); + + if ((rc = np2srv_add_udp_notif_transport_capability(transport_capas, yptc_mod, unt_mod, sn_mod))) { + goto cleanup; + } + +cleanup: + return rc; +} + /** * @brief Add subscription capabilities to a node * @param[in,out] node is a part of ietf-system-capabilities. @@ -568,6 +676,7 @@ np2srv_add_subscription_capabilities(struct lyd_node *node, const struct ly_ctx goto cleanup; } } + cleanup: return rc; } @@ -580,7 +689,7 @@ np2srv_capabilities_oper_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *module_name, const char *path, const char *request_xpath, uint32_t request_id, struct lyd_node **parent, void *private_data) { - struct lyd_node *sys_capas = NULL, *datastore_capas, *per_node_capas; + struct lyd_node *sys_capas = NULL, *datastore_capas, *per_node_capas, *global_subs_capas; const struct ly_ctx *ly_ctx; int rc = SR_ERR_OK; uint32_t ds; @@ -645,6 +754,15 @@ np2srv_capabilities_oper_cb(sr_session_ctx_t *session, uint32_t sub_id, goto cleanup; } + /* transport capabilities (subscription-capabilities was just created above, so it must be found) */ + lyd_find_path(sys_capas, "ietf-notification-capabilities:subscription-capabilities", 0, &global_subs_capas); + assert(global_subs_capas); + if (np2srv_add_transport_capabilities(global_subs_capas, ly_ctx)) { + ERR("Failed to add transport-capabilities."); + rc = -1; + goto cleanup; + } + cleanup: if (rc) { lyd_free_tree(sys_capas); diff --git a/tests/modules/ietf-subscribed-notif-receivers@2024-02-01.yang b/tests/modules/ietf-subscribed-notif-receivers@2024-02-01.yang new file mode 100644 index 00000000..b3ebb8f9 --- /dev/null +++ b/tests/modules/ietf-subscribed-notif-receivers@2024-02-01.yang @@ -0,0 +1,110 @@ +module ietf-subscribed-notif-receivers { + yang-version 1.1; + namespace + "urn:ietf:params:xml:ns:yang:ietf-subscribed-notif-receivers"; + prefix "snr"; + + import ietf-subscribed-notifications { + prefix sn; + reference + "RFC 8639: Subscription to YANG Notifications"; + } + + organization + "IETF NETCONF Working Group"; + + contact + "WG Web: + WG List: + + Authors: Mahesh Jethanandani (mjethanandani at gmail dot com) + Kent Watsen (kent plus ietf at watsen dot net)"; + + description + "This YANG module is implemented by Publishers implementing + the 'ietf-subscribed-notifications' module defined in RFC 8639. + + While this module is defined in RFC XXXX, which primarily + defines an HTTPS-based transport for notifications, this module + is not HTTP-specific. It is a generic extension that can be + used by any 'notif' transport. + + This module defines two 'augment' statements. One statement + augments a 'container' statement called 'receiver-instances' + into the top-level 'subscriptions' container. The other + statement, called 'receiver-instance-ref', augments a 'leaf' + statement into each 'receiver' that references one of the + afore mentioned receiver instances. This indirection enables + multiple configured subscriptions to send notifications to + the same receiver instance. + + Copyright (c) 2024 IETF Trust and the persons identified as + authors of the code. All rights reserved. + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Revised BSD + License set forth in Section 4.c of the IETF Trust's Legal + Provisions Relating to IETF Documents + (http://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC XXXX; see + the RFC itself for full legal notices. + + The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', 'SHALL + NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', 'NOT RECOMMENDED', + 'MAY', and 'OPTIONAL' in this document are to be interpreted as + described in BCP 14 (RFC 2119) (RFC 8174) when, and only when, + they appear in all capitals, as shown here."; + + revision "2024-02-01" { + description + "Initial Version."; + reference + "RFC XXXX: An HTTPS-based Transport for YANG Notifications."; + } + + augment "/sn:subscriptions" { + container receiver-instances { + description + "A container for all instances of receivers."; + + list receiver-instance { + key "name"; + + leaf name { + type string; + description + "An arbitrary but unique name for this receiver + instance."; + } + + choice transport-type { + mandatory true; + description + "Choice of different types of transports used to + send notifications. The 'case' statements must + be augmented in by other modules."; + } + description + "A list of all receiver instances."; + } + } + description + "Augment the subscriptions container to define the + transport type."; + } + augment + "/sn:subscriptions/sn:subscription/sn:receivers/sn:receiver" { + leaf receiver-instance-ref { + type leafref { + path "/sn:subscriptions/snr:receiver-instances/" + + "snr:receiver-instance/snr:name"; + } + description + "Reference to a receiver instance."; + } + description + "Augment the subscriptions container to define an optional + reference to a receiver instance."; + } +} diff --git a/tests/modules/ietf-tls-client@2024-03-16.yang b/tests/modules/ietf-tls-client@2024-03-16.yang new file mode 100644 index 00000000..447185b2 --- /dev/null +++ b/tests/modules/ietf-tls-client@2024-03-16.yang @@ -0,0 +1,525 @@ +module ietf-tls-client { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-tls-client"; + prefix tlsc; + + import ietf-netconf-acm { + prefix nacm; + reference + "RFC 8341: Network Configuration Access Control Model"; + } + + import ietf-crypto-types { + prefix ct; + reference + "RFC AAAA: YANG Data Types and Groupings for Cryptography"; + } + + import ietf-truststore { + prefix ts; + reference + "RFC BBBB: A YANG Data Model for a Truststore"; + } + + import ietf-keystore { + prefix ks; + reference + "RFC CCCC: A YANG Data Model for a Keystore"; + } + + import ietf-tls-common { + prefix tlscmn; + reference + "RFC FFFF: YANG Groupings for TLS Clients and TLS Servers"; + } + + organization + "IETF NETCONF (Network Configuration) Working Group"; + + contact + "WG List: NETCONF WG list + WG Web: https://datatracker.ietf.org/wg/netconf + Author: Kent Watsen + Author: Jeff Hartley "; + + description + "This module defines reusable groupings for TLS clients that + can be used as a basis for specific TLS client instances. + + Copyright (c) 2024 IETF Trust and the persons identified + as authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with + or without modification, is permitted pursuant to, and + subject to the license terms contained in, the Revised + BSD License set forth in Section 4.c of the IETF Trust's + Legal Provisions Relating to IETF Documents + (https://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC FFFF + (https://www.rfc-editor.org/info/rfcFFFF); see the RFC + itself for full legal notices. + + The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', + 'SHALL NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', + 'NOT RECOMMENDED', 'MAY', and 'OPTIONAL' in this document + are to be interpreted as described in BCP 14 (RFC 2119) + (RFC 8174) when, and only when, they appear in all + capitals, as shown here."; + + revision 2024-03-16 { + description + "Initial version"; + reference + "RFC FFFF: YANG Groupings for TLS Clients and TLS Servers"; + } + + // Features + + feature tls-client-keepalives { + description + "Per socket TLS keepalive parameters are configurable for + TLS clients on the server implementing this feature."; + } + + feature client-ident-x509-cert { + description + "Indicates that the client supports identifying itself + using X.509 certificates."; + reference + "RFC 5280: + Internet X.509 Public Key Infrastructure Certificate + and Certificate Revocation List (CRL) Profile"; + } + + feature client-ident-raw-public-key { + description + "Indicates that the client supports identifying itself + using raw public keys."; + reference + "RFC 7250: + Using Raw Public Keys in Transport Layer Security (TLS) + and Datagram Transport Layer Security (DTLS)"; + } + + feature client-ident-tls12-psk { + if-feature "tlscmn:tls12"; + description + "Indicates that the client supports identifying itself + using TLS-1.2 PSKs (pre-shared or pairwise-symmetric keys)."; + reference + "RFC 4279: + Pre-Shared Key Ciphersuites for Transport Layer Security + (TLS)"; + } + + feature client-ident-tls13-epsk { + if-feature "tlscmn:tls13"; + description + "Indicates that the client supports identifying itself + using TLS-1.3 External PSKs (pre-shared keys)."; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + feature server-auth-x509-cert { + description + "Indicates that the client supports authenticating servers + using X.509 certificates."; + reference + "RFC 5280: + Internet X.509 Public Key Infrastructure Certificate + and Certificate Revocation List (CRL) Profile"; + } + + feature server-auth-raw-public-key { + description + "Indicates that the client supports authenticating servers + using raw public keys."; + reference + "RFC 7250: + Using Raw Public Keys in Transport Layer Security (TLS) + and Datagram Transport Layer Security (DTLS)"; + } + + feature server-auth-tls12-psk { + description + "Indicates that the client supports authenticating servers + using PSKs (pre-shared or pairwise-symmetric keys)."; + reference + "RFC 4279: + Pre-Shared Key Ciphersuites for Transport Layer Security + (TLS)"; + } + + feature server-auth-tls13-epsk { + description + "Indicates that the client supports authenticating servers + using TLS-1.3 External PSKs (pre-shared keys)."; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + // Groupings + + grouping tls-client-grouping { + description + "A reusable grouping for configuring a TLS client without + any consideration for how an underlying TCP session is + established. + + Note that this grouping uses fairly typical descendant + node names such that a stack of 'uses' statements will + have name conflicts. It is intended that the consuming + data model will resolve the issue (e.g., by wrapping + the 'uses' statement in a container called + 'tls-client-parameters'). This model purposely does + not do this itself so as to provide maximum flexibility + to consuming models."; + + container client-identity { + nacm:default-deny-write; + presence + "Indicates that a TLS-level client identity has been + configured. This statement is present so the mandatory + descendant do not imply that this node must be configured."; + description + "Identity credentials the TLS client MAY present when + establishing a connection to a TLS server. If not + configured, then client authentication is presumed to + occur in a protocol layer above TLS. When configured, + and requested by the TLS server when establishing a + TLS session, these credentials are passed in the + Certificate message defined in Section 7.4.2 of + RFC 5246 and Section 4.4.2 in RFC 8446."; + reference + "RFC 5246: The Transport Layer Security (TLS) + Protocol Version 1.2 + RFC 8446: The Transport Layer Security (TLS) + Protocol Version 1.3 + RFC CCCC: A YANG Data Model for a Keystore"; + choice auth-type { + mandatory true; + description + "A choice amongst authentication types, of which one must + be enabled (via its associated 'feature') and selected."; + case certificate { + if-feature "client-ident-x509-cert"; + container certificate { + description + "Specifies the client identity using a certificate."; + uses + "ks:inline-or-keystore-end-entity-cert-with-key-" + + "grouping" { + refine "inline-or-keystore/inline/inline-definition" { + must 'not(public-key-format) or derived-from-or-self' + + '(public-key-format, "ct:subject-public-key-' + + 'info-format")'; + } + refine "inline-or-keystore/central-keystore/" + + "central-keystore-reference/asymmetric-key" { + must 'not(deref(.)/../ks:public-key-format) or ' + + 'derived-from-or-self(deref(.)/../ks:public-' + + 'key-format, "ct:subject-public-key-info-' + + 'format")'; + } + } + } + } + case raw-public-key { + if-feature "client-ident-raw-public-key"; + container raw-private-key { + description + "Specifies the client identity using a raw + private key."; + uses ks:inline-or-keystore-asymmetric-key-grouping { + refine "inline-or-keystore/inline/inline-definition" { + must 'not(public-key-format) or derived-from-or-self' + + '(public-key-format, "ct:subject-public-key-' + + 'info-format")'; + } + refine "inline-or-keystore/central-keystore/" + + "central-keystore-reference" { + must 'not(deref(.)/../ks:public-key-format) or ' + + 'derived-from-or-self(deref(.)/../ks:public-' + + 'key-format, "ct:subject-public-key-info-' + + 'format")'; + } + } + } + } + case tls12-psk { + if-feature "client-ident-tls12-psk"; + container tls12-psk { + description + "Specifies the client identity using a PSK (pre-shared + or pairwise-symmetric key)."; + uses ks:inline-or-keystore-symmetric-key-grouping; + leaf id { + type string; + description + "The key 'psk_identity' value used in the TLS + 'ClientKeyExchange' message."; + reference + "RFC 4279: Pre-Shared Key Ciphersuites for + Transport Layer Security (TLS)"; + } + } + } + case tls13-epsk { + if-feature "client-ident-tls13-epsk"; + container tls13-epsk { + description + "An External Pre-Shared Key (EPSK) is established + or provisioned out-of-band, i.e., not from a TLS + connection. An EPSK is a tuple of (Base Key, + External Identity, Hash). External PSKs MUST NOT + be imported for (D)TLS 1.2 or prior versions. When + PSKs are provisioned out of band, the PSK identity + and the KDF hash algorithm to be used with the PSK + MUST also be provisioned. + + The structure of this container is designed to + satisfy the requirements of RFC 8446 Section + 4.2.11, the recommendations from Section 6 in + RFC 9257, and the EPSK input fields detailed in + Section 5.1 in RFC 9258. The base-key is based + upon ks:inline-or-keystore-symmetric-key-grouping + in order to provide users with flexible and + secure storage options."; + reference + "RFC 8446: The Transport Layer Security (TLS) + Protocol Version 1.3 + RFC 9257: Guidance for External Pre-Shared Key + (PSK) Usage in TLS + RFC 9258: Importing External Pre-Shared Keys + (PSKs) for TLS 1.3"; + uses ks:inline-or-keystore-symmetric-key-grouping; + leaf external-identity { + type string; + mandatory true; + description + "As per Section 4.2.11 of RFC 8446, and Section 4.1 + of RFC 9257, a sequence of bytes used to identify + an EPSK. A label for a pre-shared key established + externally."; + reference + "RFC 8446: The Transport Layer Security (TLS) + Protocol Version 1.3 + RFC 9257: Guidance for External Pre-Shared Key + (PSK) Usage in TLS"; + } + leaf hash { + type tlscmn:epsk-supported-hash; + default sha-256; + description + "As per Section 4.2.11 of RFC 8446, for externally + established PSKs, the Hash algorithm MUST be set + when the PSK is established or default to SHA-256 + if no such algorithm is defined. The server MUST + ensure that it selects a compatible PSK (if any) + and cipher suite. Each PSK MUST only be used with + a single hash function."; + reference + "RFC 8446: The Transport Layer Security (TLS) + Protocol Version 1.3"; + } + leaf context { + type string; + description + "Per Section 5.1 of RFC 9258, context MUST include + the context used to determine the EPSK, if + any exists. For example, context may include + information about peer roles or identities + to mitigate Selfie-style reflection attacks. + Since the EPSK is a key derived from an external + protocol or sequence of protocols, context MUST + include a channel binding for the deriving + protocols [RFC5056]. The details of this + binding are protocol specfic and out of scope + for this document."; + reference + "RFC 9258: Importing External Pre-Shared Keys + (PSKs) for TLS 1.3"; + } + leaf target-protocol { + type uint16; + description + "As per Section 3 of RFC 9258, the protocol + for which a PSK is imported for use."; + reference + "RFC 9258: Importing External Pre-Shared Keys + (PSKs) for TLS 1.3"; + } + leaf target-kdf { + type uint16; + description + "As per Section 3 of RFC 9258, the KDF for + which a PSK is imported for use."; + reference + "RFC 9258: Importing External Pre-Shared Keys + (PSKs) for TLS 1.3"; + } + } + } + } + } // container client-identity + + container server-authentication { + nacm:default-deny-write; + must 'ca-certs or ee-certs or raw-public-keys or tls12-psks + or tls13-epsks'; + description + "Specifies how the TLS client can authenticate TLS servers. + Any combination of credentials is additive and unordered. + + Note that no configuration is required for PSK (pre-shared + or pairwise-symmetric key) based authentication as the key + is necessarily the same as configured in the '../client- + identity' node."; + container ca-certs { + if-feature "server-auth-x509-cert"; + presence + "Indicates that CA certificates have been configured. + This statement is present so the mandatory descendant + nodes do not imply that this node must be configured."; + description + "A set of certificate authority (CA) certificates used by + the TLS client to authenticate TLS server certificates. + A server certificate is authenticated if it has a valid + chain of trust to a configured CA certificate."; + reference + "RFC BBBB: A YANG Data Model for a Truststore"; + uses ts:inline-or-truststore-certs-grouping; + } + container ee-certs { + if-feature "server-auth-x509-cert"; + presence + "Indicates that EE certificates have been configured. + This statement is present so the mandatory descendant + nodes do not imply that this node must be configured."; + description + "A set of server certificates (i.e., end entity + certificates) used by the TLS client to authenticate + certificates presented by TLS servers. A server + certificate is authenticated if it is an exact + match to a configured server certificate."; + reference + "RFC BBBB: A YANG Data Model for a Truststore"; + uses ts:inline-or-truststore-certs-grouping; + } + container raw-public-keys { + if-feature "server-auth-raw-public-key"; + presence + "Indicates that raw public keys have been configured. + This statement is present so the mandatory descendant + nodes do not imply that this node must be configured."; + description + "A set of raw public keys used by the TLS client to + authenticate raw public keys presented by the TLS + server. A raw public key is authenticated if it + is an exact match to a configured raw public key."; + reference + "RFC BBBB: A YANG Data Model for a Truststore"; + uses ts:inline-or-truststore-public-keys-grouping { + refine "inline-or-truststore/inline/inline-definition/" + + "public-key" { + must 'derived-from-or-self(public-key-format,' + + ' "ct:subject-public-key-info-format")'; + } + refine "inline-or-truststore/central-truststore/" + + "central-truststore-reference" { + must 'not(deref(.)/../ts:public-key/ts:public-key-' + + 'format[not(derived-from-or-self(., "ct:subject-' + + 'public-key-info-format"))])'; + } + } + } + leaf tls12-psks { + if-feature "server-auth-tls12-psk"; + type empty; + description + "Indicates that the TLS client can authenticate TLS servers + using configured PSKs (pre-shared or pairwise-symmetric + keys). + + No configuration is required since the PSK value is the + same as PSK value configured in the 'client-identity' + node."; + } + leaf tls13-epsks { + if-feature "server-auth-tls13-epsk"; + type empty; + description + "Indicates that the TLS client can authenticate TLS servers + using configured external PSKs (pre-shared keys). + + No configuration is required since the PSK value is the + same as PSK value configured in the 'client-identity' + node."; + } + } // container server-authentication + + container hello-params { + nacm:default-deny-write; + if-feature "tlscmn:hello-params"; + uses tlscmn:hello-params-grouping; + description + "Configurable parameters for the TLS hello message."; + } // container hello-params + container keepalives { + nacm:default-deny-write; + if-feature "tls-client-keepalives"; + description + "Configures the keepalive policy for the TLS client."; + leaf peer-allowed-to-send { + type empty; + description + "Indicates that the remote TLS server is allowed to send + HeartbeatRequest messages, as defined by RFC 6520 + to this TLS client."; + reference + "RFC 6520: Transport Layer Security (TLS) and Datagram + Transport Layer Security (DTLS) Heartbeat Extension"; + } + container test-peer-aliveness { + presence + "Indicates that the TLS client proactively tests the + aliveness of the remote TLS server."; + description + "Configures the keep-alive policy to proactively test + the aliveness of the TLS server. An unresponsive + TLS server is dropped after approximately max-wait + * max-attempts seconds. The TLS client MUST send + HeartbeatRequest messages, as defined by RFC 6520."; + reference + "RFC 6520: Transport Layer Security (TLS) and Datagram + Transport Layer Security (DTLS) Heartbeat Extension"; + leaf max-wait { + type uint16 { + range "1..max"; + } + units "seconds"; + default "30"; + description + "Sets the amount of time in seconds after which if + no data has been received from the TLS server, a + TLS-level message will be sent to test the + aliveness of the TLS server."; + } + leaf max-attempts { + type uint8; + default "3"; + description + "Sets the maximum number of sequential keep-alive + messages that can fail to obtain a response from + the TLS server before assuming the TLS server is + no longer alive."; + } + } + } + } // grouping tls-client-grouping + +} diff --git a/tests/modules/ietf-udp-client@2025-05-14.yang b/tests/modules/ietf-udp-client@2025-05-14.yang new file mode 100644 index 00000000..d2302290 --- /dev/null +++ b/tests/modules/ietf-udp-client@2025-05-14.yang @@ -0,0 +1,104 @@ +module ietf-udp-client { + yang-version 1.1; + namespace + "urn:ietf:params:xml:ns:yang:ietf-udp-client"; + prefix udpc; + import ietf-inet-types { + prefix inet; + reference + "RFC 6991: Common YANG Data Types"; + } + + organization "IETF NETCONF (Network Configuration) Working Group"; + contact + "WG Web: + WG List: + + Authors: Alex Huang Feng + + Pierre Francois + "; + + description + "Defines a generic grouping for UDP-based client applications. + + Copyright (c) 2025 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, is permitted pursuant to, and subject to the license + terms contained in, the Revised BSD License set forth in Section + 4.c of the IETF Trust's Legal Provisions Relating to IETF Documents + (https://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC-to-be; see the RFC + itself for full legal notices."; + + revision 2025-05-14 { + description + "Initial revision"; + reference + "RFC-to-be: YANG Groupings for UDP Clients and UDP Servers"; + } + + feature local-binding { + description + "Indicates that the UDP client supports configuring local + bindings (i.e., the local address and local port number) + for UDP clients."; + } + + grouping udp-client { + description + "A reusable grouping for UDP clients. + + Note that this grouping uses fairly typical descendant + node names such that a stack of 'uses' statements will + have name conflicts. It is intended that the consuming + data model will resolve the issue (e.g., by wrapping + the 'uses' statement in a container called + 'udp-client-parameters'). This model purposely does + not do this itself so as to provide maximum flexibility + to consuming models."; + + leaf remote-address { + type inet:host; + mandatory true; + description + "The IP address or hostname of the remote UDP server. + If a domain name is configured, then the name resolution + should happen before each datagram is sent, unless a + previously resolved address is cached and still valid. + If the name resolution results in multiple IP addresses, + the IP addresses are tried until a connection has been + established or until all IP addresses have failed. "; + } + + leaf remote-port { + type inet:port-number; + description + "The port number of the remote UDP server."; + } + + leaf local-address { + if-feature "local-binding"; + type inet:ip-address; + description + "The local IP address to bind to when sending UDP + datagrams to the remote server. INADDR_ANY ('0.0.0.0') or + INADDR6_ANY ('0:0:0:0:0:0:0:0' a.k.a. '::') may be used + so that the client can bind to any IPv4 or IPv6 address."; + } + + leaf local-port { + if-feature "local-binding"; + type inet:port-number; + default "0"; + description + "The local port number to bind to when sending UDP + datagrams to the remote server. The port number '0', + which is the default value, indicates that any available + local port number may be used."; + } + } +} diff --git a/tests/modules/ietf-udp-notif-transport@2025-06-04.yang b/tests/modules/ietf-udp-notif-transport@2025-06-04.yang new file mode 100644 index 00000000..4078d877 --- /dev/null +++ b/tests/modules/ietf-udp-notif-transport@2025-06-04.yang @@ -0,0 +1,189 @@ +module ietf-udp-notif-transport { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-udp-notif-transport"; + prefix unt; + + import ietf-subscribed-notifications { + prefix sn; + reference + "RFC 8639: Subscription to YANG Notifications"; + } + import ietf-subscribed-notif-receivers { + prefix snr; + reference + "draft-ietf-netconf-https-notif: An HTTPS-based Transport + for Configured Subscriptions"; + } + import ietf-udp-client { + prefix udpc; + reference + "draft-ietf-netconf-udp-client-server: YANG Grouping for + UDP Clients and UDP Servers"; + } + import ietf-tls-client { + prefix tlsc; + reference + "RFC 9645: YANG Groupings for TLS Clients and TLS Servers"; + } + + organization + "IETF NETCONF (Network Configuration) Working Group"; + contact + "WG Web: + WG List: + + Authors: Guangying Zheng + + Tianran Zhou + + Thomas Graf + + Pierre Francois + + Alex Huang Feng + + Paolo Lucente + "; + description + "Defines a model for configuring UDP-Notif as a transport + for configured subscriptions [RFC8639]. + + Copyright (c) 2025 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject to + the license terms contained in, the Revised BSD License set + forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (https://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC XXXX + (https://www.rfc-editor.org/info/rfcXXXX); see the RFC itself + for full legal notices. + + The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', 'SHALL + NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', 'NOT RECOMMENDED', + 'MAY', and 'OPTIONAL' in this document are to be interpreted as + described in BCP 14 (RFC 2119) (RFC 8174) when, and only when, + they appear in all capitals, as shown here."; + + revision 2025-06-04 { + description + "Initial revision"; + reference + "RFC XXXX: UDP-based Transport for Configured Subscriptions"; + } + + /* + * FEATURES + */ + + feature encode-cbor { + description + "Indicates that CBOR encoding of notification + messages is supported."; + reference + "RFC 9254: CBOR Encoding of Data Modeled with YANG"; + } + + feature dtls { + description + "Indicates that DTLS encryption of UDP + packets is supported. UDP-Notif mandates that, in + unsecured networks, DTLS 1.2 or later MUST be supported, + and DTLS 1.3 SHOULD be supported."; + reference + "RFC6347: Datagram Transport Layer Security Version 1.2, + RFC 9147: The Datagram Transport Layer Security (DTLS) + Protocol Version 1.3"; + } + + /* + * IDENTITIES + */ + + identity udp-notif { + base sn:transport; + base sn:configurable-encoding; + description + "UDP-Notif is used as transport for notification messages + and state change notifications."; + } + + identity encode-cbor { + base sn:encoding; + description + "Encode data using CBOR."; + reference + "RFC 9254: CBOR Encoding of Data Modeled with YANG"; + } + + identity unsupported-max-segment-size { + base sn:establish-subscription-error; + base sn:modify-subscription-error; + description + "Error triggered when the specified value 'max-segment-size' + is not supported by the publisher. An implementation may + only support a subset of the uint16."; + reference + "RFC XXXX: UDP-based Transport for Configured Subscriptions"; + } + + grouping udp-notif-receiver { + description + "Provides a reusable identification of a UDP-Notif target + receiver."; + uses udpc:udp-client { + refine "remote-port" { + mandatory true; + } + } + container dtls { + if-feature "dtls"; + presence "dtls"; + uses tlsc:tls-client-grouping { + // Remove keep-alives for DTLS + refine "keepalives" { + if-feature "not tlsc:tls-client-keepalives"; + } + } + description + "Container for configuring DTLS parameters."; + } + leaf enable-segmentation { + type boolean; + default "true"; + description + "When disabled, the publisher will not segment UDP-Notif + messages. This may cause IP-layer fragmentation when + messages are larger than the MTU. IP fragmentation is + discouraged (RFC 8085, RFC 8900) and generally unsafe. + Disabling is not recommended."; + } + leaf max-segment-size { + type uint16; + description + "UDP-Notif provides a configurable max-segment-size to + control the size of each segment (UDP-Notif header, with + options, included). + The publisher may trigger an 'unsupported-max-segment-size' + error if the publisher does not support the configured + value."; + } + } + + augment "/sn:subscriptions/snr:receiver-instances/" + + "snr:receiver-instance/snr:transport-type" { + case udp-notif { + container udp-notif-receiver { + description + "The UDP-Notif receiver to send notifications to."; + uses udp-notif-receiver; + } + } + description + "Augments the transport-type choice to include the 'udp-notif' + transport."; + } +} diff --git a/tests/np2_test.c b/tests/np2_test.c index 17703696..863148b5 100644 --- a/tests/np2_test.c +++ b/tests/np2_test.c @@ -240,6 +240,18 @@ np2_glob_test_setup_sess_ctx(struct nc_session *sess, const char **modules) SETUP_FAIL_LOG; return 1; } + if (!ly_ctx_load_module(ctx, "ietf-system-capabilities", "2022-02-17", NULL)) { + SETUP_FAIL_LOG; + return 1; + } + if (!ly_ctx_load_module(ctx, "ietf-notification-capabilities", "2022-02-17", NULL)) { + SETUP_FAIL_LOG; + return 1; + } + if (!ly_ctx_load_module(ctx, "ietf-yp-transport-capabilities", "2026-05-15", NULL)) { + SETUP_FAIL_LOG; + return 1; + } /* test module searchdir */ ly_ctx_set_searchdir(ctx, NP_TEST_MODULE_DIR); diff --git a/tests/test_sub_ntf_advanced.c b/tests/test_sub_ntf_advanced.c index 20ac3b07..59020d95 100644 --- a/tests/test_sub_ntf_advanced.c +++ b/tests/test_sub_ntf_advanced.c @@ -38,8 +38,19 @@ static int local_setup(void **state) { struct np2_test *st; - const char *modules[] = {NP_TEST_MODULE_DIR "/notif1.yang", NP_TEST_MODULE_DIR "/notif2.yang", NULL}; + const char *modules[] = { + NP_TEST_MODULE_DIR "/ietf-subscribed-notif-receivers@2024-02-01.yang", + NP_TEST_MODULE_DIR "/ietf-udp-client@2025-05-14.yang", + NP_TEST_MODULE_DIR "/ietf-tls-client@2024-03-16.yang", + NP_TEST_MODULE_DIR "/ietf-udp-notif-transport@2025-06-04.yang", + NP_TEST_MODULE_DIR "/notif1.yang", NP_TEST_MODULE_DIR "/notif2.yang", NULL + }; + /* features per module; only ietf-udp-notif-transport needs dtls and encode-cbor */ + const char *unt_features[] = {"dtls", "encode-cbor", NULL}; + const char **features[] = {NULL, NULL, NULL, unt_features, NULL, NULL}; + const char *search_dirs = NP_ROOT_DIR "/modules:" NP_TEST_MODULE_DIR ":" LN2_YANG_MODULE_DIR; char test_name[256]; + sr_conn_ctx_t *conn; int rc; /* get test name */ @@ -49,6 +60,11 @@ local_setup(void **state) rc = np2_glob_test_setup_env(test_name); assert_int_equal(rc, 0); + /* install UDP-Notif modules with features before the server starts */ + assert_int_equal(SR_ERR_OK, sr_connect(0, &conn)); + assert_int_equal(SR_ERR_OK, sr_install_modules(conn, modules, search_dirs, features)); + sr_disconnect(conn); + /* setup netopeer2 server */ rc = np2_glob_test_setup_server(state, test_name, modules, NULL, 0); assert_int_equal(rc, 0); @@ -89,7 +105,10 @@ static int local_teardown(void **state) { struct np2_test *st = *state; - const char *modules[] = {"notif1", "notif2", NULL}; + const char *modules[] = { + "ietf-udp-notif-transport", "ietf-tls-client", "ietf-udp-client", + "ietf-subscribed-notif-receivers", "notif1", "notif2", NULL + }; if (!st) { return 0; @@ -947,6 +966,34 @@ test_killsub_diff_sess(void **state) nc_session_free(tmp, NULL); } +static void +test_transport_capabilities(void **state) +{ + struct np2_test *st = *state; + const char *template = + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " unt:udp-notif\n" + " dtls12\n" + " dtls13\n" + " sn:encode-xml\n" + " unt:encode-cbor\n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; + + GET_FILTER(st, "/ietf-system-capabilities:system-capabilities/ietf-notification-capabilities:subscription-capabilities/ietf-yp-transport-capabilities:transport-capabilities"); + assert_string_equal(st->str, template); + FREE_TEST_VARS(st); +} + int main(int argc, char **argv) { @@ -962,6 +1009,7 @@ main(int argc, char **argv) cmocka_unit_test_teardown(test_ds_subscriptions, teardown_common), cmocka_unit_test_teardown(test_ds_subscriptions_sent_event, teardown_common), cmocka_unit_test_teardown(test_ds_subscriptions_excluded_event, teardown_common), + cmocka_unit_test_teardown(test_transport_capabilities, teardown_common), cmocka_unit_test_teardown(test_multiple_subscriptions, teardown_common), cmocka_unit_test_teardown(test_multiple_subscriptions_notif, teardown_common), cmocka_unit_test_setup_teardown(test_multiple_subscriptions_notif_interlaced, setup_notif2_data, teardown_common), From 116573c93a2421e12f3349f07675278b6523b88f Mon Sep 17 00:00:00 2001 From: Roman Janota Date: Thu, 30 Jul 2026 09:41:13 +0200 Subject: [PATCH 2/2] VERSION bump to version 2.8.11 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c8e2e918..f62f96bb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,7 +41,7 @@ endif() # Generic version of not only the library. Major version is reserved for really big changes of the project, # minor version changes with added functionality (new tool, functionality of the tool or library, ...) and # micro version is changed with a set of small changes or bugfixes anywhere in the project. -set(NP2SRV_VERSION 2.8.10) +set(NP2SRV_VERSION 2.8.11) # libyang required version set(LIBYANG_DEP_VERSION 5.1.3)