From 061fa5fc7259029a9ea88c4951855c5681488b53 Mon Sep 17 00:00:00 2001 From: Tobias Waldekranz Date: Wed, 8 Jan 2025 15:28:49 +0100 Subject: [PATCH 01/12] confd: Add missing module dependencies These are also provided by other packages (sysrepo, netopeer, etc.) but having them in here allows us to lint all of our own models without the need for a build tree. --- ...iana-tls-cipher-suite-algs@2022-06-16.yang | 3775 +++++++++++++++++ .../yang/ietf-crypto-types@2023-12-28.yang | 1028 +++++ src/confd/yang/ietf-keystore@2023-12-28.yang | 374 ++ .../yang/ietf-netconf-acm@2018-02-14.yang | 423 ++ .../yang/ietf-truststore@2023-12-28.yang | 359 ++ 5 files changed, 5959 insertions(+) create mode 100644 src/confd/yang/iana-tls-cipher-suite-algs@2022-06-16.yang create mode 100644 src/confd/yang/ietf-crypto-types@2023-12-28.yang create mode 100644 src/confd/yang/ietf-keystore@2023-12-28.yang create mode 100644 src/confd/yang/ietf-netconf-acm@2018-02-14.yang create mode 100644 src/confd/yang/ietf-truststore@2023-12-28.yang diff --git a/src/confd/yang/iana-tls-cipher-suite-algs@2022-06-16.yang b/src/confd/yang/iana-tls-cipher-suite-algs@2022-06-16.yang new file mode 100644 index 00000000..ed24bd67 --- /dev/null +++ b/src/confd/yang/iana-tls-cipher-suite-algs@2022-06-16.yang @@ -0,0 +1,3775 @@ +module iana-tls-cipher-suite-algs { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:iana-tls-cipher-suite-algs"; + prefix tlscsa; + + organization + "Internet Assigned Numbers Authority (IANA)"; + contact + "Postal: ICANN + 12025 Waterfront Drive, Suite 300 + Los Angeles, CA 90094-2536 + United States of America + Tel: +1 310 301 5800 + Email: iana@iana.org"; + description + "This module defines identities for the Cipher Suite + algorithms defined in the 'TLS Cipher Suites' sub-registry + of the 'Transport Layer Security (TLS) Parameters' registry + maintained by IANA. + + Copyright (c) 2022 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). + + The initial 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."; + + revision 2022-06-16 { + description + "Reflect contents of the public key algorithms registry + on June 16, 2022."; + reference + "RFC FFFF: YANG Groupings for TLS Clients and TLS Servers"; + } + + identity cipher-suite-alg-base { + description + "Base identity used to identify TLS cipher suites."; + } + + identity tls-null-with-null-null { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-NULL-WITH-NULL-NULL"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2"; + } + + identity tls-rsa-with-null-md5 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-WITH-NULL-MD5"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2"; + } + + identity tls-rsa-with-null-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-WITH-NULL-SHA"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2"; + } + + identity tls-rsa-export-with-rc4-40-md5 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-EXPORT-WITH-RC4-40-MD5"; + reference + "RFC 4346: + The TLS Protocol Version 1.1 + RFC 6347: + Datagram Transport Layer Security version 1.2"; + } + + identity tls-rsa-with-rc4-128-md5 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-WITH-RC4-128-MD5"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2 + RFC 6347: + Datagram Transport Layer Security version 1.2"; + } + + identity tls-rsa-with-rc4-128-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-WITH-RC4-128-SHA"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2 + RFC 6347: + Datagram Transport Layer Security version 1.2"; + } + + identity tls-rsa-export-with-rc2-cbc-40-md5 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-EXPORT-WITH-RC2-CBC-40-MD5"; + reference + "RFC 4346: + The TLS Protocol Version 1.1"; + } + + identity tls-rsa-with-idea-cbc-sha { + base cipher-suite-alg-base; + status obsolete; + description + "TLS-RSA-WITH-IDEA-CBC-SHA"; + reference + "RFC 5469: + DES and IDEA Cipher Suites for + Transport Layer Security (TLS) + RFC 5469: + DES and IDEA Cipher Suites for + Transport Layer Security (TLS)"; + } + + identity tls-rsa-export-with-des40-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-EXPORT-WITH-DES40-CBC-SHA"; + reference + "RFC 4346: + The TLS Protocol Version 1.1"; + } + + identity tls-rsa-with-des-cbc-sha { + base cipher-suite-alg-base; + status obsolete; + description + "TLS-RSA-WITH-DES-CBC-SHA"; + reference + "RFC 5469: + DES and IDEA Cipher Suites for + Transport Layer Security (TLS) + RFC 5469: + DES and IDEA Cipher Suites for + Transport Layer Security (TLS)"; + } + + identity tls-rsa-with-3des-ede-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-WITH-3DES-EDE-CBC-SHA"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2"; + } + + identity tls-dh-dss-export-with-des40-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-DSS-EXPORT-WITH-DES40-CBC-SHA"; + reference + "RFC 4346: + The TLS Protocol Version 1.1"; + } + + identity tls-dh-dss-with-des-cbc-sha { + base cipher-suite-alg-base; + status obsolete; + description + "TLS-DH-DSS-WITH-DES-CBC-SHA"; + reference + "RFC 5469: + DES and IDEA Cipher Suites for + Transport Layer Security (TLS) + RFC 5469: + DES and IDEA Cipher Suites for + Transport Layer Security (TLS)"; + } + + identity tls-dh-dss-with-3des-ede-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-DSS-WITH-3DES-EDE-CBC-SHA"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2"; + } + + identity tls-dh-rsa-export-with-des40-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-RSA-EXPORT-WITH-DES40-CBC-SHA"; + reference + "RFC 4346: + The TLS Protocol Version 1.1"; + } + + identity tls-dh-rsa-with-des-cbc-sha { + base cipher-suite-alg-base; + status obsolete; + description + "TLS-DH-RSA-WITH-DES-CBC-SHA"; + reference + "RFC 5469: + DES and IDEA Cipher Suites for + Transport Layer Security (TLS) + RFC 5469: + DES and IDEA Cipher Suites for + Transport Layer Security (TLS)"; + } + + identity tls-dh-rsa-with-3des-ede-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-RSA-WITH-3DES-EDE-CBC-SHA"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2"; + } + + identity tls-dhe-dss-export-with-des40-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-DSS-EXPORT-WITH-DES40-CBC-SHA"; + reference + "RFC 4346: + The TLS Protocol Version 1.1"; + } + + identity tls-dhe-dss-with-des-cbc-sha { + base cipher-suite-alg-base; + status obsolete; + description + "TLS-DHE-DSS-WITH-DES-CBC-SHA"; + reference + "RFC 5469: + DES and IDEA Cipher Suites for + Transport Layer Security (TLS) + RFC 5469: + DES and IDEA Cipher Suites for + Transport Layer Security (TLS)"; + } + + identity tls-dhe-dss-with-3des-ede-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-DSS-WITH-3DES-EDE-CBC-SHA"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2"; + } + + identity tls-dhe-rsa-export-with-des40-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-RSA-EXPORT-WITH-DES40-CBC-SHA"; + reference + "RFC 4346: + The TLS Protocol Version 1.1"; + } + + identity tls-dhe-rsa-with-des-cbc-sha { + base cipher-suite-alg-base; + status obsolete; + description + "TLS-DHE-RSA-WITH-DES-CBC-SHA"; + reference + "RFC 5469: + DES and IDEA Cipher Suites for + Transport Layer Security (TLS) + RFC 5469: + DES and IDEA Cipher Suites for + Transport Layer Security (TLS)"; + } + + identity tls-dhe-rsa-with-3des-ede-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2"; + } + + identity tls-dh-anon-export-with-rc4-40-md5 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-ANON-EXPORT-WITH-RC4-40-MD5"; + reference + "RFC 4346: + The TLS Protocol Version 1.1 + RFC 6347: + Datagram Transport Layer Security version 1.2"; + } + + identity tls-dh-anon-with-rc4-128-md5 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-ANON-WITH-RC4-128-MD5"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2 + RFC 6347: + Datagram Transport Layer Security version 1.2"; + } + + identity tls-dh-anon-export-with-des40-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-ANON-EXPORT-WITH-DES40-CBC-SHA"; + reference + "RFC 4346: + The TLS Protocol Version 1.1"; + } + + identity tls-dh-anon-with-des-cbc-sha { + base cipher-suite-alg-base; + status obsolete; + description + "TLS-DH-ANON-WITH-DES-CBC-SHA"; + reference + "RFC 5469: + DES and IDEA Cipher Suites for + Transport Layer Security (TLS) + RFC 5469: + DES and IDEA Cipher Suites for + Transport Layer Security (TLS)"; + } + + identity tls-dh-anon-with-3des-ede-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-ANON-WITH-3DES-EDE-CBC-SHA"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2"; + } + + identity tls-krb5-with-des-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-KRB5-WITH-DES-CBC-SHA"; + reference + "RFC 2712: + Addition of Kerberos Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-krb5-with-3des-ede-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-KRB5-WITH-3DES-EDE-CBC-SHA"; + reference + "RFC 2712: + Addition of Kerberos Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-krb5-with-rc4-128-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-KRB5-WITH-RC4-128-SHA"; + reference + "RFC 2712: + Addition of Kerberos Cipher Suites to + Transport Layer Security (TLS) + RFC 6347: + Datagram Transport Layer Security version 1.2"; + } + + identity tls-krb5-with-idea-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-KRB5-WITH-IDEA-CBC-SHA"; + reference + "RFC 2712: + Addition of Kerberos Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-krb5-with-des-cbc-md5 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-KRB5-WITH-DES-CBC-MD5"; + reference + "RFC 2712: + Addition of Kerberos Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-krb5-with-3des-ede-cbc-md5 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-KRB5-WITH-3DES-EDE-CBC-MD5"; + reference + "RFC 2712: + Addition of Kerberos Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-krb5-with-rc4-128-md5 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-KRB5-WITH-RC4-128-MD5"; + reference + "RFC 2712: + Addition of Kerberos Cipher Suites to + Transport Layer Security (TLS) + RFC 6347: + Datagram Transport Layer Security version 1.2"; + } + + identity tls-krb5-with-idea-cbc-md5 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-KRB5-WITH-IDEA-CBC-MD5"; + reference + "RFC 2712: + Addition of Kerberos Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-krb5-export-with-des-cbc-40-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-KRB5-EXPORT-WITH-DES-CBC-40-SHA"; + reference + "RFC 2712: + Addition of Kerberos Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-krb5-export-with-rc2-cbc-40-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-KRB5-EXPORT-WITH-RC2-CBC-40-SHA"; + reference + "RFC 2712: + Addition of Kerberos Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-krb5-export-with-rc4-40-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-KRB5-EXPORT-WITH-RC4-40-SHA"; + reference + "RFC 2712: + Addition of Kerberos Cipher Suites to + Transport Layer Security (TLS) + RFC 6347: + Datagram Transport Layer Security version 1.2"; + } + + identity tls-krb5-export-with-des-cbc-40-md5 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-KRB5-EXPORT-WITH-DES-CBC-40-MD5"; + reference + "RFC 2712: + Addition of Kerberos Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-krb5-export-with-rc2-cbc-40-md5 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-KRB5-EXPORT-WITH-RC2-CBC-40-MD5"; + reference + "RFC 2712: + Addition of Kerberos Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-krb5-export-with-rc4-40-md5 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-KRB5-EXPORT-WITH-RC4-40-MD5"; + reference + "RFC 2712: + Addition of Kerberos Cipher Suites to + Transport Layer Security (TLS) + RFC 6347: + Datagram Transport Layer Security version 1.2"; + } + + identity tls-psk-with-null-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-PSK-WITH-NULL-SHA"; + reference + "RFC 4785: + Pre-Shared Key Cipher Suites with NULL Encryption for + Transport Layer Security (TLS)"; + } + + identity tls-dhe-psk-with-null-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-PSK-WITH-NULL-SHA"; + reference + "RFC 4785: + Pre-Shared Key Cipher Suites with NULL Encryption for + Transport Layer Security (TLS)"; + } + + identity tls-rsa-psk-with-null-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-PSK-WITH-NULL-SHA"; + reference + "RFC 4785: + Pre-Shared Key Cipher Suites with NULL Encryption for + Transport Layer Security (TLS)"; + } + + identity tls-rsa-with-aes-128-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-WITH-AES-128-CBC-SHA"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2"; + } + + identity tls-dh-dss-with-aes-128-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-DSS-WITH-AES-128-CBC-SHA"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2"; + } + + identity tls-dh-rsa-with-aes-128-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-RSA-WITH-AES-128-CBC-SHA"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2"; + } + + identity tls-dhe-dss-with-aes-128-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-DSS-WITH-AES-128-CBC-SHA"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2"; + } + + identity tls-dhe-rsa-with-aes-128-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-RSA-WITH-AES-128-CBC-SHA"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2"; + } + + identity tls-dh-anon-with-aes-128-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-ANON-WITH-AES-128-CBC-SHA"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2"; + } + + identity tls-rsa-with-aes-256-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-WITH-AES-256-CBC-SHA"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2"; + } + + identity tls-dh-dss-with-aes-256-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-DSS-WITH-AES-256-CBC-SHA"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2"; + } + + identity tls-dh-rsa-with-aes-256-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-RSA-WITH-AES-256-CBC-SHA"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2"; + } + + identity tls-dhe-dss-with-aes-256-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-DSS-WITH-AES-256-CBC-SHA"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2"; + } + + identity tls-dhe-rsa-with-aes-256-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-RSA-WITH-AES-256-CBC-SHA"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2"; + } + + identity tls-dh-anon-with-aes-256-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-ANON-WITH-AES-256-CBC-SHA"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2"; + } + + identity tls-rsa-with-null-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-WITH-NULL-SHA256"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2"; + } + + identity tls-rsa-with-aes-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-WITH-AES-128-CBC-SHA256"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2"; + } + + identity tls-rsa-with-aes-256-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-WITH-AES-256-CBC-SHA256"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2"; + } + + identity tls-dh-dss-with-aes-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-DSS-WITH-AES-128-CBC-SHA256"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2"; + } + + identity tls-dh-rsa-with-aes-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-RSA-WITH-AES-128-CBC-SHA256"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2"; + } + + identity tls-dhe-dss-with-aes-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-DSS-WITH-AES-128-CBC-SHA256"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2"; + } + + identity tls-rsa-with-camellia-128-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA"; + reference + "RFC 5932: + Camellia Cipher Suites for TLS"; + } + + identity tls-dh-dss-with-camellia-128-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-DSS-WITH-CAMELLIA-128-CBC-SHA"; + reference + "RFC 5932: + Camellia Cipher Suites for TLS"; + } + + identity tls-dh-rsa-with-camellia-128-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-RSA-WITH-CAMELLIA-128-CBC-SHA"; + reference + "RFC 5932: + Camellia Cipher Suites for TLS"; + } + + identity tls-dhe-dss-with-camellia-128-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA"; + reference + "RFC 5932: + Camellia Cipher Suites for TLS"; + } + + identity tls-dhe-rsa-with-camellia-128-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA"; + reference + "RFC 5932: + Camellia Cipher Suites for TLS"; + } + + identity tls-dh-anon-with-camellia-128-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-ANON-WITH-CAMELLIA-128-CBC-SHA"; + reference + "RFC 5932: + Camellia Cipher Suites for TLS"; + } + + identity tls-dhe-rsa-with-aes-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2"; + } + + identity tls-dh-dss-with-aes-256-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-DSS-WITH-AES-256-CBC-SHA256"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2"; + } + + identity tls-dh-rsa-with-aes-256-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-RSA-WITH-AES-256-CBC-SHA256"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2"; + } + + identity tls-dhe-dss-with-aes-256-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-DSS-WITH-AES-256-CBC-SHA256"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2"; + } + + identity tls-dhe-rsa-with-aes-256-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2"; + } + + identity tls-dh-anon-with-aes-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-ANON-WITH-AES-128-CBC-SHA256"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2"; + } + + identity tls-dh-anon-with-aes-256-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-ANON-WITH-AES-256-CBC-SHA256"; + reference + "RFC 5246: + The Transport Layer Security (TLS) Protocol Version 1.2"; + } + + identity tls-rsa-with-camellia-256-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA"; + reference + "RFC 5932: + Camellia Cipher Suites for TLS"; + } + + identity tls-dh-dss-with-camellia-256-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-DSS-WITH-CAMELLIA-256-CBC-SHA"; + reference + "RFC 5932: + Camellia Cipher Suites for TLS"; + } + + identity tls-dh-rsa-with-camellia-256-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-RSA-WITH-CAMELLIA-256-CBC-SHA"; + reference + "RFC 5932: + Camellia Cipher Suites for TLS"; + } + + identity tls-dhe-dss-with-camellia-256-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA"; + reference + "RFC 5932: + Camellia Cipher Suites for TLS"; + } + + identity tls-dhe-rsa-with-camellia-256-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA"; + reference + "RFC 5932: + Camellia Cipher Suites for TLS"; + } + + identity tls-dh-anon-with-camellia-256-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-ANON-WITH-CAMELLIA-256-CBC-SHA"; + reference + "RFC 5932: + Camellia Cipher Suites for TLS"; + } + + identity tls-psk-with-rc4-128-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-PSK-WITH-RC4-128-SHA"; + reference + "RFC 4279: + Pre-Shared Key Ciphersuites for + Transport Layer Security (TLS) + RFC 6347: + Datagram Transport Layer Security version 1.2"; + } + + identity tls-psk-with-3des-ede-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-PSK-WITH-3DES-EDE-CBC-SHA"; + reference + "RFC 4279: + Pre-Shared Key Ciphersuites for + Transport Layer Security (TLS)"; + } + + identity tls-psk-with-aes-128-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-PSK-WITH-AES-128-CBC-SHA"; + reference + "RFC 4279: + Pre-Shared Key Ciphersuites for + Transport Layer Security (TLS)"; + } + + identity tls-psk-with-aes-256-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-PSK-WITH-AES-256-CBC-SHA"; + reference + "RFC 4279: + Pre-Shared Key Ciphersuites for + Transport Layer Security (TLS)"; + } + + identity tls-dhe-psk-with-rc4-128-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-PSK-WITH-RC4-128-SHA"; + reference + "RFC 4279: + Pre-Shared Key Ciphersuites for + Transport Layer Security (TLS) + RFC 6347: + Datagram Transport Layer Security version 1.2"; + } + + identity tls-dhe-psk-with-3des-ede-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-PSK-WITH-3DES-EDE-CBC-SHA"; + reference + "RFC 4279: + Pre-Shared Key Ciphersuites for + Transport Layer Security (TLS)"; + } + + identity tls-dhe-psk-with-aes-128-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-PSK-WITH-AES-128-CBC-SHA"; + reference + "RFC 4279: + Pre-Shared Key Ciphersuites for + Transport Layer Security (TLS)"; + } + + identity tls-dhe-psk-with-aes-256-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-PSK-WITH-AES-256-CBC-SHA"; + reference + "RFC 4279: + Pre-Shared Key Ciphersuites for + Transport Layer Security (TLS)"; + } + + identity tls-rsa-psk-with-rc4-128-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-PSK-WITH-RC4-128-SHA"; + reference + "RFC 4279: + Pre-Shared Key Ciphersuites for + Transport Layer Security (TLS) + RFC 6347: + Datagram Transport Layer Security version 1.2"; + } + + identity tls-rsa-psk-with-3des-ede-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-PSK-WITH-3DES-EDE-CBC-SHA"; + reference + "RFC 4279: + Pre-Shared Key Ciphersuites for + Transport Layer Security (TLS)"; + } + + identity tls-rsa-psk-with-aes-128-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-PSK-WITH-AES-128-CBC-SHA"; + reference + "RFC 4279: + Pre-Shared Key Ciphersuites for + Transport Layer Security (TLS)"; + } + + identity tls-rsa-psk-with-aes-256-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-PSK-WITH-AES-256-CBC-SHA"; + reference + "RFC 4279: + Pre-Shared Key Ciphersuites for + Transport Layer Security (TLS)"; + } + + identity tls-rsa-with-seed-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-WITH-SEED-CBC-SHA"; + reference + "RFC 4162: + Addition of SEED Ciphersuites to + Transport Layer Security (TLS)"; + } + + identity tls-dh-dss-with-seed-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-DSS-WITH-SEED-CBC-SHA"; + reference + "RFC 4162: + Addition of SEED Ciphersuites to + Transport Layer Security (TLS)"; + } + + identity tls-dh-rsa-with-seed-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-RSA-WITH-SEED-CBC-SHA"; + reference + "RFC 4162: + Addition of SEED Ciphersuites to + Transport Layer Security (TLS)"; + } + + identity tls-dhe-dss-with-seed-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-DSS-WITH-SEED-CBC-SHA"; + reference + "RFC 4162: + Addition of SEED Ciphersuites to + Transport Layer Security (TLS)"; + } + + identity tls-dhe-rsa-with-seed-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-RSA-WITH-SEED-CBC-SHA"; + reference + "RFC 4162: + Addition of SEED Ciphersuites to + Transport Layer Security (TLS)"; + } + + identity tls-dh-anon-with-seed-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-ANON-WITH-SEED-CBC-SHA"; + reference + "RFC 4162: + Addition of SEED Ciphersuites to + Transport Layer Security (TLS)"; + } + + identity tls-rsa-with-aes-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-WITH-AES-128-GCM-SHA256"; + reference + "RFC 5288: + AES-GCM Cipher Suites for TLS"; + } + + identity tls-rsa-with-aes-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-WITH-AES-256-GCM-SHA384"; + reference + "RFC 5288: + AES-GCM Cipher Suites for TLS"; + } + + identity tls-dhe-rsa-with-aes-128-gcm-sha256 { + base cipher-suite-alg-base; + description + "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256"; + reference + "RFC 5288: + AES-GCM Cipher Suites for TLS"; + } + + identity tls-dhe-rsa-with-aes-256-gcm-sha384 { + base cipher-suite-alg-base; + description + "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384"; + reference + "RFC 5288: + AES-GCM Cipher Suites for TLS"; + } + + identity tls-dh-rsa-with-aes-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-RSA-WITH-AES-128-GCM-SHA256"; + reference + "RFC 5288: + AES-GCM Cipher Suites for TLS"; + } + + identity tls-dh-rsa-with-aes-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-RSA-WITH-AES-256-GCM-SHA384"; + reference + "RFC 5288: + AES-GCM Cipher Suites for TLS"; + } + + identity tls-dhe-dss-with-aes-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-DSS-WITH-AES-128-GCM-SHA256"; + reference + "RFC 5288: + AES-GCM Cipher Suites for TLS"; + } + + identity tls-dhe-dss-with-aes-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-DSS-WITH-AES-256-GCM-SHA384"; + reference + "RFC 5288: + AES-GCM Cipher Suites for TLS"; + } + + identity tls-dh-dss-with-aes-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-DSS-WITH-AES-128-GCM-SHA256"; + reference + "RFC 5288: + AES-GCM Cipher Suites for TLS"; + } + + identity tls-dh-dss-with-aes-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-DSS-WITH-AES-256-GCM-SHA384"; + reference + "RFC 5288: + AES-GCM Cipher Suites for TLS"; + } + + identity tls-dh-anon-with-aes-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-ANON-WITH-AES-128-GCM-SHA256"; + reference + "RFC 5288: + AES-GCM Cipher Suites for TLS"; + } + + identity tls-dh-anon-with-aes-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-ANON-WITH-AES-256-GCM-SHA384"; + reference + "RFC 5288: + AES-GCM Cipher Suites for TLS"; + } + + identity tls-psk-with-aes-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-PSK-WITH-AES-128-GCM-SHA256"; + reference + "RFC 5487: + Pre-Shared Key Cipher Suites for Transport Layer Security + (TLS) with SHA-256/384 and AES Galois Counter Mode"; + } + + identity tls-psk-with-aes-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-PSK-WITH-AES-256-GCM-SHA384"; + reference + "RFC 5487: + Pre-Shared Key Cipher Suites for Transport Layer Security + (TLS) with SHA-256/384 and AES Galois Counter Mode"; + } + + identity tls-dhe-psk-with-aes-128-gcm-sha256 { + base cipher-suite-alg-base; + description + "TLS-DHE-PSK-WITH-AES-128-GCM-SHA256"; + reference + "RFC 5487: + Pre-Shared Key Cipher Suites for Transport Layer Security + (TLS) with SHA-256/384 and AES Galois Counter Mode"; + } + + identity tls-dhe-psk-with-aes-256-gcm-sha384 { + base cipher-suite-alg-base; + description + "TLS-DHE-PSK-WITH-AES-256-GCM-SHA384"; + reference + "RFC 5487: + Pre-Shared Key Cipher Suites for Transport Layer Security + (TLS) with SHA-256/384 and AES Galois Counter Mode"; + } + + identity tls-rsa-psk-with-aes-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-PSK-WITH-AES-128-GCM-SHA256"; + reference + "RFC 5487: + Pre-Shared Key Cipher Suites for Transport Layer Security + (TLS) with SHA-256/384 and AES Galois Counter Mode"; + } + + identity tls-rsa-psk-with-aes-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-PSK-WITH-AES-256-GCM-SHA384"; + reference + "RFC 5487: + Pre-Shared Key Cipher Suites for Transport Layer Security + (TLS) with SHA-256/384 and AES Galois Counter Mode"; + } + + identity tls-psk-with-aes-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-PSK-WITH-AES-128-CBC-SHA256"; + reference + "RFC 5487: + Pre-Shared Key Cipher Suites for Transport Layer Security + (TLS) with SHA-256/384 and AES Galois Counter Mode"; + } + + identity tls-psk-with-aes-256-cbc-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-PSK-WITH-AES-256-CBC-SHA384"; + reference + "RFC 5487: + Pre-Shared Key Cipher Suites for Transport Layer Security + (TLS) with SHA-256/384 and AES Galois Counter Mode"; + } + + identity tls-psk-with-null-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-PSK-WITH-NULL-SHA256"; + reference + "RFC 5487: + Pre-Shared Key Cipher Suites for Transport Layer Security + (TLS) with SHA-256/384 and AES Galois Counter Mode"; + } + + identity tls-psk-with-null-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-PSK-WITH-NULL-SHA384"; + reference + "RFC 5487: + Pre-Shared Key Cipher Suites for Transport Layer Security + (TLS) with SHA-256/384 and AES Galois Counter Mode"; + } + + identity tls-dhe-psk-with-aes-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-PSK-WITH-AES-128-CBC-SHA256"; + reference + "RFC 5487: + Pre-Shared Key Cipher Suites for Transport Layer Security + (TLS) with SHA-256/384 and AES Galois Counter Mode"; + } + + identity tls-dhe-psk-with-aes-256-cbc-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-PSK-WITH-AES-256-CBC-SHA384"; + reference + "RFC 5487: + Pre-Shared Key Cipher Suites for Transport Layer Security + (TLS) with SHA-256/384 and AES Galois Counter Mode"; + } + + identity tls-dhe-psk-with-null-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-PSK-WITH-NULL-SHA256"; + reference + "RFC 5487: + Pre-Shared Key Cipher Suites for Transport Layer Security + (TLS) with SHA-256/384 and AES Galois Counter Mode"; + } + + identity tls-dhe-psk-with-null-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-PSK-WITH-NULL-SHA384"; + reference + "RFC 5487: + Pre-Shared Key Cipher Suites for Transport Layer Security + (TLS) with SHA-256/384 and AES Galois Counter Mode"; + } + + identity tls-rsa-psk-with-aes-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-PSK-WITH-AES-128-CBC-SHA256"; + reference + "RFC 5487: + Pre-Shared Key Cipher Suites for Transport Layer Security + (TLS) with SHA-256/384 and AES Galois Counter Mode"; + } + + identity tls-rsa-psk-with-aes-256-cbc-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-PSK-WITH-AES-256-CBC-SHA384"; + reference + "RFC 5487: + Pre-Shared Key Cipher Suites for Transport Layer Security + (TLS) with SHA-256/384 and AES Galois Counter Mode"; + } + + identity tls-rsa-psk-with-null-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-PSK-WITH-NULL-SHA256"; + reference + "RFC 5487: + Pre-Shared Key Cipher Suites for Transport Layer Security + (TLS) with SHA-256/384 and AES Galois Counter Mode"; + } + + identity tls-rsa-psk-with-null-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-PSK-WITH-NULL-SHA384"; + reference + "RFC 5487: + Pre-Shared Key Cipher Suites for Transport Layer Security + (TLS) with SHA-256/384 and AES Galois Counter Mode"; + } + + identity tls-rsa-with-camellia-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256"; + reference + "RFC 5932: + Camellia Cipher Suites for TLS"; + } + + identity tls-dh-dss-with-camellia-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-DSS-WITH-CAMELLIA-128-CBC-SHA256"; + reference + "RFC 5932: + Camellia Cipher Suites for TLS"; + } + + identity tls-dh-rsa-with-camellia-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-RSA-WITH-CAMELLIA-128-CBC-SHA256"; + reference + "RFC 5932: + Camellia Cipher Suites for TLS"; + } + + identity tls-dhe-dss-with-camellia-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA256"; + reference + "RFC 5932: + Camellia Cipher Suites for TLS"; + } + + identity tls-dhe-rsa-with-camellia-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256"; + reference + "RFC 5932: + Camellia Cipher Suites for TLS"; + } + + identity tls-dh-anon-with-camellia-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-ANON-WITH-CAMELLIA-128-CBC-SHA256"; + reference + "RFC 5932: + Camellia Cipher Suites for TLS"; + } + + identity tls-rsa-with-camellia-256-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256"; + reference + "RFC 5932: + Camellia Cipher Suites for TLS"; + } + + identity tls-dh-dss-with-camellia-256-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-DSS-WITH-CAMELLIA-256-CBC-SHA256"; + reference + "RFC 5932: + Camellia Cipher Suites for TLS"; + } + + identity tls-dh-rsa-with-camellia-256-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-RSA-WITH-CAMELLIA-256-CBC-SHA256"; + reference + "RFC 5932: + Camellia Cipher Suites for TLS"; + } + + identity tls-dhe-dss-with-camellia-256-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA256"; + reference + "RFC 5932: + Camellia Cipher Suites for TLS"; + } + + identity tls-dhe-rsa-with-camellia-256-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256"; + reference + "RFC 5932: + Camellia Cipher Suites for TLS"; + } + + identity tls-dh-anon-with-camellia-256-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-ANON-WITH-CAMELLIA-256-CBC-SHA256"; + reference + "RFC 5932: + Camellia Cipher Suites for TLS"; + } + + identity tls-sm4-gcm-sm3 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-SM4-GCM-SM3"; + reference + "RFC 8998: + ShangMi (SM) Cipher Suites for Transport Layer Security + (TLS) Protocol Version 1.3"; + } + + identity tls-sm4-ccm-sm3 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-SM4-CCM-SM3"; + reference + "RFC 8998: + ShangMi (SM) Cipher Suites for Transport Layer Security + (TLS) Protocol Version 1.3"; + } + + identity tls-empty-renegotiation-info-scsv { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-EMPTY-RENEGOTIATION-INFO-SCSV"; + reference + "RFC 5746: + Transport Layer Security (TLS) + Renegotiation Indication Extension"; + } + + identity tls-aes-128-gcm-sha256 { + base cipher-suite-alg-base; + description + "TLS-AES-128-GCM-SHA256"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity tls-aes-256-gcm-sha384 { + base cipher-suite-alg-base; + description + "TLS-AES-256-GCM-SHA384"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity tls-chacha20-poly1305-sha256 { + base cipher-suite-alg-base; + description + "TLS-CHACHA20-POLY1305-SHA256"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity tls-aes-128-ccm-sha256 { + base cipher-suite-alg-base; + description + "TLS-AES-128-CCM-SHA256"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity tls-aes-128-ccm-8-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-AES-128-CCM-8-SHA256"; + reference + "RFC 8446: + The Transport Layer Security (TLS) Protocol Version 1.3"; + } + + identity tls-fallback-scsv { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-FALLBACK-SCSV"; + reference + "RFC 7507: + TLS Fallback Signaling Cipher Suite Value (SCSV) + for Preventing Protocol Downgrade Attacks"; + } + + identity tls-ecdh-ecdsa-with-null-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-ECDSA-WITH-NULL-SHA"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier"; + } + + identity tls-ecdh-ecdsa-with-rc4-128-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-ECDSA-WITH-RC4-128-SHA"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier + RFC 6347: + Datagram Transport Layer Security version 1.2"; + } + + identity tls-ecdh-ecdsa-with-3des-ede-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-ECDSA-WITH-3DES-EDE-CBC-SHA"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier"; + } + + identity tls-ecdh-ecdsa-with-aes-128-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier"; + } + + identity tls-ecdh-ecdsa-with-aes-256-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier"; + } + + identity tls-ecdhe-ecdsa-with-null-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-ECDSA-WITH-NULL-SHA"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier"; + } + + identity tls-ecdhe-ecdsa-with-rc4-128-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-ECDSA-WITH-RC4-128-SHA"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier + RFC 6347: + Datagram Transport Layer Security version 1.2"; + } + + identity tls-ecdhe-ecdsa-with-3des-ede-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-ECDSA-WITH-3DES-EDE-CBC-SHA"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier"; + } + + identity tls-ecdhe-ecdsa-with-aes-128-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier"; + } + + identity tls-ecdhe-ecdsa-with-aes-256-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier"; + } + + identity tls-ecdh-rsa-with-null-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-RSA-WITH-NULL-SHA"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier"; + } + + identity tls-ecdh-rsa-with-rc4-128-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-RSA-WITH-RC4-128-SHA"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier + RFC 6347: + Datagram Transport Layer Security version 1.2"; + } + + identity tls-ecdh-rsa-with-3des-ede-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-RSA-WITH-3DES-EDE-CBC-SHA"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier"; + } + + identity tls-ecdh-rsa-with-aes-128-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier"; + } + + identity tls-ecdh-rsa-with-aes-256-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier"; + } + + identity tls-ecdhe-rsa-with-null-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-RSA-WITH-NULL-SHA"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier"; + } + + identity tls-ecdhe-rsa-with-rc4-128-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-RSA-WITH-RC4-128-SHA"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier + RFC 6347: + Datagram Transport Layer Security version 1.2"; + } + + identity tls-ecdhe-rsa-with-3des-ede-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier"; + } + + identity tls-ecdhe-rsa-with-aes-128-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier"; + } + + identity tls-ecdhe-rsa-with-aes-256-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier"; + } + + identity tls-ecdh-anon-with-null-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-ANON-WITH-NULL-SHA"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier"; + } + + identity tls-ecdh-anon-with-rc4-128-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-ANON-WITH-RC4-128-SHA"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier + RFC 6347: + Datagram Transport Layer Security version 1.2"; + } + + identity tls-ecdh-anon-with-3des-ede-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-ANON-WITH-3DES-EDE-CBC-SHA"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier"; + } + + identity tls-ecdh-anon-with-aes-128-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-ANON-WITH-AES-128-CBC-SHA"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier"; + } + + identity tls-ecdh-anon-with-aes-256-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-ANON-WITH-AES-256-CBC-SHA"; + reference + "RFC 8422: + Elliptic Curve Cryptography (ECC) Cipher Suites for + Transport Layer Security (TLS) Versions 1.2 and Earlier"; + } + + identity tls-srp-sha-with-3des-ede-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-SRP-SHA-WITH-3DES-EDE-CBC-SHA"; + reference + "RFC 5054: + Using SRP for TLS Authentication"; + } + + identity tls-srp-sha-rsa-with-3des-ede-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-SRP-SHA-RSA-WITH-3DES-EDE-CBC-SHA"; + reference + "RFC 5054: + Using SRP for TLS Authentication"; + } + + identity tls-srp-sha-dss-with-3des-ede-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-SRP-SHA-DSS-WITH-3DES-EDE-CBC-SHA"; + reference + "RFC 5054: + Using SRP for TLS Authentication"; + } + + identity tls-srp-sha-with-aes-128-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-SRP-SHA-WITH-AES-128-CBC-SHA"; + reference + "RFC 5054: + Using SRP for TLS Authentication"; + } + + identity tls-srp-sha-rsa-with-aes-128-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-SRP-SHA-RSA-WITH-AES-128-CBC-SHA"; + reference + "RFC 5054: + Using SRP for TLS Authentication"; + } + + identity tls-srp-sha-dss-with-aes-128-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-SRP-SHA-DSS-WITH-AES-128-CBC-SHA"; + reference + "RFC 5054: + Using SRP for TLS Authentication"; + } + + identity tls-srp-sha-with-aes-256-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-SRP-SHA-WITH-AES-256-CBC-SHA"; + reference + "RFC 5054: + Using SRP for TLS Authentication"; + } + + identity tls-srp-sha-rsa-with-aes-256-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-SRP-SHA-RSA-WITH-AES-256-CBC-SHA"; + reference + "RFC 5054: + Using SRP for TLS Authentication"; + } + + identity tls-srp-sha-dss-with-aes-256-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-SRP-SHA-DSS-WITH-AES-256-CBC-SHA"; + reference + "RFC 5054: + Using SRP for TLS Authentication"; + } + + identity tls-ecdhe-ecdsa-with-aes-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256"; + reference + "RFC 5289: + TLS Elliptic Curve Cipher Suites with SHA-256/384 + and AES Galois Counter Mode"; + } + + identity tls-ecdhe-ecdsa-with-aes-256-cbc-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384"; + reference + "RFC 5289: + TLS Elliptic Curve Cipher Suites with SHA-256/384 + and AES Galois Counter Mode"; + } + + identity tls-ecdh-ecdsa-with-aes-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA256"; + reference + "RFC 5289: + TLS Elliptic Curve Cipher Suites with SHA-256/384 + and AES Galois Counter Mode"; + } + + identity tls-ecdh-ecdsa-with-aes-256-cbc-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA384"; + reference + "RFC 5289: + TLS Elliptic Curve Cipher Suites with SHA-256/384 + and AES Galois Counter Mode"; + } + + identity tls-ecdhe-rsa-with-aes-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256"; + reference + "RFC 5289: + TLS Elliptic Curve Cipher Suites with SHA-256/384 + and AES Galois Counter Mode"; + } + + identity tls-ecdhe-rsa-with-aes-256-cbc-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384"; + reference + "RFC 5289: + TLS Elliptic Curve Cipher Suites with SHA-256/384 + and AES Galois Counter Mode"; + } + + identity tls-ecdh-rsa-with-aes-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA256"; + reference + "RFC 5289: + TLS Elliptic Curve Cipher Suites with SHA-256/384 + and AES Galois Counter Mode"; + } + + identity tls-ecdh-rsa-with-aes-256-cbc-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA384"; + reference + "RFC 5289: + TLS Elliptic Curve Cipher Suites with SHA-256/384 + and AES Galois Counter Mode"; + } + + identity tls-ecdhe-ecdsa-with-aes-128-gcm-sha256 { + base cipher-suite-alg-base; + description + "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256"; + reference + "RFC 5289: + TLS Elliptic Curve Cipher Suites with SHA-256/384 + and AES Galois Counter Mode"; + } + + identity tls-ecdhe-ecdsa-with-aes-256-gcm-sha384 { + base cipher-suite-alg-base; + description + "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384"; + reference + "RFC 5289: + TLS Elliptic Curve Cipher Suites with SHA-256/384 + and AES Galois Counter Mode"; + } + + identity tls-ecdh-ecdsa-with-aes-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256"; + reference + "RFC 5289: + TLS Elliptic Curve Cipher Suites with SHA-256/384 + and AES Galois Counter Mode"; + } + + identity tls-ecdh-ecdsa-with-aes-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-ECDSA-WITH-AES-256-GCM-SHA384"; + reference + "RFC 5289: + TLS Elliptic Curve Cipher Suites with SHA-256/384 + and AES Galois Counter Mode"; + } + + identity tls-ecdhe-rsa-with-aes-128-gcm-sha256 { + base cipher-suite-alg-base; + description + "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256"; + reference + "RFC 5289: + TLS Elliptic Curve Cipher Suites with SHA-256/384 + and AES Galois Counter Mode"; + } + + identity tls-ecdhe-rsa-with-aes-256-gcm-sha384 { + base cipher-suite-alg-base; + description + "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384"; + reference + "RFC 5289: + TLS Elliptic Curve Cipher Suites with SHA-256/384 + and AES Galois Counter Mode"; + } + + identity tls-ecdh-rsa-with-aes-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-RSA-WITH-AES-128-GCM-SHA256"; + reference + "RFC 5289: + TLS Elliptic Curve Cipher Suites with SHA-256/384 + and AES Galois Counter Mode"; + } + + identity tls-ecdh-rsa-with-aes-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-RSA-WITH-AES-256-GCM-SHA384"; + reference + "RFC 5289: + TLS Elliptic Curve Cipher Suites with SHA-256/384 + and AES Galois Counter Mode"; + } + + identity tls-ecdhe-psk-with-rc4-128-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-PSK-WITH-RC4-128-SHA"; + reference + "RFC 5489: + ECDHE_PSK Ciphersuites for Transport Layer Security (TLS) + RFC 6347: + Datagram Transport Layer Security version 1.2"; + } + + identity tls-ecdhe-psk-with-3des-ede-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-PSK-WITH-3DES-EDE-CBC-SHA"; + reference + "RFC 5489: + ECDHE_PSK Ciphersuites for Transport Layer Security (TLS)"; + } + + identity tls-ecdhe-psk-with-aes-128-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA"; + reference + "RFC 5489: + ECDHE_PSK Ciphersuites for Transport Layer Security (TLS)"; + } + + identity tls-ecdhe-psk-with-aes-256-cbc-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA"; + reference + "RFC 5489: + ECDHE_PSK Ciphersuites for Transport Layer Security (TLS)"; + } + + identity tls-ecdhe-psk-with-aes-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256"; + reference + "RFC 5489: + ECDHE_PSK Ciphersuites for Transport Layer Security (TLS)"; + } + + identity tls-ecdhe-psk-with-aes-256-cbc-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA384"; + reference + "RFC 5489: + ECDHE_PSK Ciphersuites for Transport Layer Security (TLS)"; + } + + identity tls-ecdhe-psk-with-null-sha { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-PSK-WITH-NULL-SHA"; + reference + "RFC 5489: + ECDHE_PSK Ciphersuites for Transport Layer Security (TLS)"; + } + + identity tls-ecdhe-psk-with-null-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-PSK-WITH-NULL-SHA256"; + reference + "RFC 5489: + ECDHE_PSK Ciphersuites for Transport Layer Security (TLS)"; + } + + identity tls-ecdhe-psk-with-null-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-PSK-WITH-NULL-SHA384"; + reference + "RFC 5489: + ECDHE_PSK Ciphersuites for Transport Layer Security (TLS)"; + } + + identity tls-rsa-with-aria-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-WITH-ARIA-128-CBC-SHA256"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-rsa-with-aria-256-cbc-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-WITH-ARIA-256-CBC-SHA384"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dh-dss-with-aria-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-DSS-WITH-ARIA-128-CBC-SHA256"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dh-dss-with-aria-256-cbc-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-DSS-WITH-ARIA-256-CBC-SHA384"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dh-rsa-with-aria-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-RSA-WITH-ARIA-128-CBC-SHA256"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dh-rsa-with-aria-256-cbc-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-RSA-WITH-ARIA-256-CBC-SHA384"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dhe-dss-with-aria-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-DSS-WITH-ARIA-128-CBC-SHA256"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dhe-dss-with-aria-256-cbc-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-DSS-WITH-ARIA-256-CBC-SHA384"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dhe-rsa-with-aria-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dhe-rsa-with-aria-256-cbc-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dh-anon-with-aria-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-ANON-WITH-ARIA-128-CBC-SHA256"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dh-anon-with-aria-256-cbc-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-ANON-WITH-ARIA-256-CBC-SHA384"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdhe-ecdsa-with-aria-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdhe-ecdsa-with-aria-256-cbc-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdh-ecdsa-with-aria-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-ECDSA-WITH-ARIA-128-CBC-SHA256"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdh-ecdsa-with-aria-256-cbc-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-ECDSA-WITH-ARIA-256-CBC-SHA384"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdhe-rsa-with-aria-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdhe-rsa-with-aria-256-cbc-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdh-rsa-with-aria-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-RSA-WITH-ARIA-128-CBC-SHA256"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdh-rsa-with-aria-256-cbc-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-RSA-WITH-ARIA-256-CBC-SHA384"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-rsa-with-aria-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-WITH-ARIA-128-GCM-SHA256"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-rsa-with-aria-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-WITH-ARIA-256-GCM-SHA384"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dhe-rsa-with-aria-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-RSA-WITH-ARIA-128-GCM-SHA256"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dhe-rsa-with-aria-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-RSA-WITH-ARIA-256-GCM-SHA384"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dh-rsa-with-aria-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-RSA-WITH-ARIA-128-GCM-SHA256"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dh-rsa-with-aria-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-RSA-WITH-ARIA-256-GCM-SHA384"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dhe-dss-with-aria-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-DSS-WITH-ARIA-128-GCM-SHA256"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dhe-dss-with-aria-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-DSS-WITH-ARIA-256-GCM-SHA384"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dh-dss-with-aria-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-DSS-WITH-ARIA-128-GCM-SHA256"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dh-dss-with-aria-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-DSS-WITH-ARIA-256-GCM-SHA384"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dh-anon-with-aria-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-ANON-WITH-ARIA-128-GCM-SHA256"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dh-anon-with-aria-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-ANON-WITH-ARIA-256-GCM-SHA384"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdhe-ecdsa-with-aria-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-ECDSA-WITH-ARIA-128-GCM-SHA256"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdhe-ecdsa-with-aria-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-ECDSA-WITH-ARIA-256-GCM-SHA384"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdh-ecdsa-with-aria-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-ECDSA-WITH-ARIA-128-GCM-SHA256"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdh-ecdsa-with-aria-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-ECDSA-WITH-ARIA-256-GCM-SHA384"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdhe-rsa-with-aria-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-RSA-WITH-ARIA-128-GCM-SHA256"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdhe-rsa-with-aria-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-RSA-WITH-ARIA-256-GCM-SHA384"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdh-rsa-with-aria-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-RSA-WITH-ARIA-128-GCM-SHA256"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdh-rsa-with-aria-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-RSA-WITH-ARIA-256-GCM-SHA384"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-psk-with-aria-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-PSK-WITH-ARIA-128-CBC-SHA256"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-psk-with-aria-256-cbc-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-PSK-WITH-ARIA-256-CBC-SHA384"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dhe-psk-with-aria-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-PSK-WITH-ARIA-128-CBC-SHA256"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dhe-psk-with-aria-256-cbc-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-PSK-WITH-ARIA-256-CBC-SHA384"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-rsa-psk-with-aria-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-PSK-WITH-ARIA-128-CBC-SHA256"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-rsa-psk-with-aria-256-cbc-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-PSK-WITH-ARIA-256-CBC-SHA384"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-psk-with-aria-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-PSK-WITH-ARIA-128-GCM-SHA256"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-psk-with-aria-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-PSK-WITH-ARIA-256-GCM-SHA384"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dhe-psk-with-aria-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-PSK-WITH-ARIA-128-GCM-SHA256"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dhe-psk-with-aria-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-PSK-WITH-ARIA-256-GCM-SHA384"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-rsa-psk-with-aria-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-PSK-WITH-ARIA-128-GCM-SHA256"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-rsa-psk-with-aria-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-PSK-WITH-ARIA-256-GCM-SHA384"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdhe-psk-with-aria-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-PSK-WITH-ARIA-128-CBC-SHA256"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdhe-psk-with-aria-256-cbc-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-PSK-WITH-ARIA-256-CBC-SHA384"; + reference + "RFC 6209: + Addition of the ARIA Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdhe-ecdsa-with-camellia-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA256"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdhe-ecdsa-with-camellia-256-cbc-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA384"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdh-ecdsa-with-camellia-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-CBC-SHA256"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdh-ecdsa-with-camellia-256-cbc-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdhe-rsa-with-camellia-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA256"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdhe-rsa-with-camellia-256-cbc-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA384"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdh-rsa-with-camellia-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-RSA-WITH-CAMELLIA-128-CBC-SHA256"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdh-rsa-with-camellia-256-cbc-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-RSA-WITH-CAMELLIA-256-CBC-SHA384"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-rsa-with-camellia-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-WITH-CAMELLIA-128-GCM-SHA256"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-rsa-with-camellia-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-WITH-CAMELLIA-256-GCM-SHA384"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dhe-rsa-with-camellia-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-RSA-WITH-CAMELLIA-128-GCM-SHA256"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dhe-rsa-with-camellia-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-RSA-WITH-CAMELLIA-256-GCM-SHA384"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dh-rsa-with-camellia-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-RSA-WITH-CAMELLIA-128-GCM-SHA256"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dh-rsa-with-camellia-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-RSA-WITH-CAMELLIA-256-GCM-SHA384"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dhe-dss-with-camellia-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-DSS-WITH-CAMELLIA-128-GCM-SHA256"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dhe-dss-with-camellia-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-DSS-WITH-CAMELLIA-256-GCM-SHA384"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dh-dss-with-camellia-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-DSS-WITH-CAMELLIA-128-GCM-SHA256"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dh-dss-with-camellia-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-DSS-WITH-CAMELLIA-256-GCM-SHA384"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dh-anon-with-camellia-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-ANON-WITH-CAMELLIA-128-GCM-SHA256"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dh-anon-with-camellia-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DH-ANON-WITH-CAMELLIA-256-GCM-SHA384"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdhe-ecdsa-with-camellia-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-GCM-SHA256"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdhe-ecdsa-with-camellia-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-GCM-SHA384"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdh-ecdsa-with-camellia-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-GCM-SHA256"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdh-ecdsa-with-camellia-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-GCM-SHA384"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdhe-rsa-with-camellia-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-RSA-WITH-CAMELLIA-128-GCM-SHA256"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdhe-rsa-with-camellia-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-RSA-WITH-CAMELLIA-256-GCM-SHA384"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdh-rsa-with-camellia-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-RSA-WITH-CAMELLIA-128-GCM-SHA256"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdh-rsa-with-camellia-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDH-RSA-WITH-CAMELLIA-256-GCM-SHA384"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-psk-with-camellia-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-PSK-WITH-CAMELLIA-128-GCM-SHA256"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-psk-with-camellia-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-PSK-WITH-CAMELLIA-256-GCM-SHA384"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dhe-psk-with-camellia-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-PSK-WITH-CAMELLIA-128-GCM-SHA256"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dhe-psk-with-camellia-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-PSK-WITH-CAMELLIA-256-GCM-SHA384"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-rsa-psk-with-camellia-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-PSK-WITH-CAMELLIA-128-GCM-SHA256"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-rsa-psk-with-camellia-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-PSK-WITH-CAMELLIA-256-GCM-SHA384"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-psk-with-camellia-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-PSK-WITH-CAMELLIA-128-CBC-SHA256"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-psk-with-camellia-256-cbc-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-PSK-WITH-CAMELLIA-256-CBC-SHA384"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dhe-psk-with-camellia-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-PSK-WITH-CAMELLIA-128-CBC-SHA256"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-dhe-psk-with-camellia-256-cbc-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-PSK-WITH-CAMELLIA-256-CBC-SHA384"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-rsa-psk-with-camellia-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-PSK-WITH-CAMELLIA-128-CBC-SHA256"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-rsa-psk-with-camellia-256-cbc-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-PSK-WITH-CAMELLIA-256-CBC-SHA384"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdhe-psk-with-camellia-128-cbc-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-PSK-WITH-CAMELLIA-128-CBC-SHA256"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-ecdhe-psk-with-camellia-256-cbc-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-PSK-WITH-CAMELLIA-256-CBC-SHA384"; + reference + "RFC 6367: + Addition of the Camellia Cipher Suites to + Transport Layer Security (TLS)"; + } + + identity tls-rsa-with-aes-128-ccm { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-WITH-AES-128-CCM"; + reference + "RFC 6655: + AES-CCM Cipher Suites for TLS"; + } + + identity tls-rsa-with-aes-256-ccm { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-WITH-AES-256-CCM"; + reference + "RFC 6655: + AES-CCM Cipher Suites for TLS"; + } + + identity tls-dhe-rsa-with-aes-128-ccm { + base cipher-suite-alg-base; + description + "TLS-DHE-RSA-WITH-AES-128-CCM"; + reference + "RFC 6655: + AES-CCM Cipher Suites for TLS"; + } + + identity tls-dhe-rsa-with-aes-256-ccm { + base cipher-suite-alg-base; + description + "TLS-DHE-RSA-WITH-AES-256-CCM"; + reference + "RFC 6655: + AES-CCM Cipher Suites for TLS"; + } + + identity tls-rsa-with-aes-128-ccm-8 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-WITH-AES-128-CCM-8"; + reference + "RFC 6655: + AES-CCM Cipher Suites for TLS"; + } + + identity tls-rsa-with-aes-256-ccm-8 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-WITH-AES-256-CCM-8"; + reference + "RFC 6655: + AES-CCM Cipher Suites for TLS"; + } + + identity tls-dhe-rsa-with-aes-128-ccm-8 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-RSA-WITH-AES-128-CCM-8"; + reference + "RFC 6655: + AES-CCM Cipher Suites for TLS"; + } + + identity tls-dhe-rsa-with-aes-256-ccm-8 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-DHE-RSA-WITH-AES-256-CCM-8"; + reference + "RFC 6655: + AES-CCM Cipher Suites for TLS"; + } + + identity tls-psk-with-aes-128-ccm { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-PSK-WITH-AES-128-CCM"; + reference + "RFC 6655: + AES-CCM Cipher Suites for TLS"; + } + + identity tls-psk-with-aes-256-ccm { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-PSK-WITH-AES-256-CCM"; + reference + "RFC 6655: + AES-CCM Cipher Suites for TLS"; + } + + identity tls-dhe-psk-with-aes-128-ccm { + base cipher-suite-alg-base; + description + "TLS-DHE-PSK-WITH-AES-128-CCM"; + reference + "RFC 6655: + AES-CCM Cipher Suites for TLS"; + } + + identity tls-dhe-psk-with-aes-256-ccm { + base cipher-suite-alg-base; + description + "TLS-DHE-PSK-WITH-AES-256-CCM"; + reference + "RFC 6655: + AES-CCM Cipher Suites for TLS"; + } + + identity tls-psk-with-aes-128-ccm-8 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-PSK-WITH-AES-128-CCM-8"; + reference + "RFC 6655: + AES-CCM Cipher Suites for TLS"; + } + + identity tls-psk-with-aes-256-ccm-8 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-PSK-WITH-AES-256-CCM-8"; + reference + "RFC 6655: + AES-CCM Cipher Suites for TLS"; + } + + identity tls-psk-dhe-with-aes-128-ccm-8 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-PSK-DHE-WITH-AES-128-CCM-8"; + reference + "RFC 6655: + AES-CCM Cipher Suites for TLS"; + } + + identity tls-psk-dhe-with-aes-256-ccm-8 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-PSK-DHE-WITH-AES-256-CCM-8"; + reference + "RFC 6655: + AES-CCM Cipher Suites for TLS"; + } + + identity tls-ecdhe-ecdsa-with-aes-128-ccm { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-ECDSA-WITH-AES-128-CCM"; + reference + "RFC 7251: + AES-CCM ECC Cipher Suites for TLS"; + } + + identity tls-ecdhe-ecdsa-with-aes-256-ccm { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-ECDSA-WITH-AES-256-CCM"; + reference + "RFC 7251: + AES-CCM ECC Cipher Suites for TLS"; + } + + identity tls-ecdhe-ecdsa-with-aes-128-ccm-8 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-ECDSA-WITH-AES-128-CCM-8"; + reference + "RFC 7251: + AES-CCM ECC Cipher Suites for TLS"; + } + + identity tls-ecdhe-ecdsa-with-aes-256-ccm-8 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-ECDSA-WITH-AES-256-CCM-8"; + reference + "RFC 7251: + AES-CCM ECC Cipher Suites for TLS"; + } + + identity tls-eccpwd-with-aes-128-gcm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECCPWD-WITH-AES-128-GCM-SHA256"; + reference + "RFC 8492: + Secure Password Ciphersuites for + Transport Layer Security (TLS)"; + } + + identity tls-eccpwd-with-aes-256-gcm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECCPWD-WITH-AES-256-GCM-SHA384"; + reference + "RFC 8492: + Secure Password Ciphersuites for + Transport Layer Security (TLS)"; + } + + identity tls-eccpwd-with-aes-128-ccm-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECCPWD-WITH-AES-128-CCM-SHA256"; + reference + "RFC 8492: + Secure Password Ciphersuites for + Transport Layer Security (TLS)"; + } + + identity tls-eccpwd-with-aes-256-ccm-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECCPWD-WITH-AES-256-CCM-SHA384"; + reference + "RFC 8492: + Secure Password Ciphersuites for + Transport Layer Security (TLS)"; + } + + identity tls-sha256-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-SHA256-SHA256"; + reference + "RFC 9150: + TLS 1.3 Authentication and Integrity-Only Cipher Suites"; + } + + identity tls-sha384-sha384 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-SHA384-SHA384"; + reference + "RFC 9150: + TLS 1.3 Authentication and Integrity-Only Cipher Suites"; + } + + identity tls-gostr341112-256-with-kuznyechik-ctr-omac { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-GOSTR341112-256-WITH-KUZNYECHIK-CTR-OMAC"; + reference + "RFC 9189: + GOST Cipher Suites for Transport Layer Security (TLS) + Protocol Version 1.2"; + } + + identity tls-gostr341112-256-with-magma-ctr-omac { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-GOSTR341112-256-WITH-MAGMA-CTR-OMAC"; + reference + "RFC 9189: + GOST Cipher Suites for Transport Layer Security (TLS) + Protocol Version 1.2"; + } + + identity tls-gostr341112-256-with-28147-cnt-imit { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-GOSTR341112-256-WITH-28147-CNT-IMIT"; + reference + "RFC 9189: + GOST Cipher Suites for Transport Layer Security (TLS) + Protocol Version 1.2"; + } + + identity tls-ecdhe-rsa-with-chacha20-poly1305-sha256 { + base cipher-suite-alg-base; + description + "TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256"; + reference + "RFC 7905: + ChaCha20-Poly1305 Cipher Suites for + Transport Layer Security (TLS)"; + } + + identity tls-ecdhe-ecdsa-with-chacha20-poly1305-sha256 { + base cipher-suite-alg-base; + description + "TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256"; + reference + "RFC 7905: + ChaCha20-Poly1305 Cipher Suites for + Transport Layer Security (TLS)"; + } + + identity tls-dhe-rsa-with-chacha20-poly1305-sha256 { + base cipher-suite-alg-base; + description + "TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256"; + reference + "RFC 7905: + ChaCha20-Poly1305 Cipher Suites for + Transport Layer Security (TLS)"; + } + + identity tls-psk-with-chacha20-poly1305-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-PSK-WITH-CHACHA20-POLY1305-SHA256"; + reference + "RFC 7905: + ChaCha20-Poly1305 Cipher Suites for + Transport Layer Security (TLS)"; + } + + identity tls-ecdhe-psk-with-chacha20-poly1305-sha256 { + base cipher-suite-alg-base; + description + "TLS-ECDHE-PSK-WITH-CHACHA20-POLY1305-SHA256"; + reference + "RFC 7905: + ChaCha20-Poly1305 Cipher Suites for + Transport Layer Security (TLS)"; + } + + identity tls-dhe-psk-with-chacha20-poly1305-sha256 { + base cipher-suite-alg-base; + description + "TLS-DHE-PSK-WITH-CHACHA20-POLY1305-SHA256"; + reference + "RFC 7905: + ChaCha20-Poly1305 Cipher Suites for + Transport Layer Security (TLS)"; + } + + identity tls-rsa-psk-with-chacha20-poly1305-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-RSA-PSK-WITH-CHACHA20-POLY1305-SHA256"; + reference + "RFC 7905: + ChaCha20-Poly1305 Cipher Suites for + Transport Layer Security (TLS)"; + } + + identity tls-ecdhe-psk-with-aes-128-gcm-sha256 { + base cipher-suite-alg-base; + description + "TLS-ECDHE-PSK-WITH-AES-128-GCM-SHA256"; + reference + "RFC 8442: + ECDHE_PSK with AES-GCM and AES-CCM Cipher Suites"; + } + + identity tls-ecdhe-psk-with-aes-256-gcm-sha384 { + base cipher-suite-alg-base; + description + "TLS-ECDHE-PSK-WITH-AES-256-GCM-SHA384"; + reference + "RFC 8442: + ECDHE_PSK with AES-GCM and AES-CCM Cipher Suites"; + } + + identity tls-ecdhe-psk-with-aes-128-ccm-8-sha256 { + base cipher-suite-alg-base; + status deprecated; + description + "TLS-ECDHE-PSK-WITH-AES-128-CCM-8-SHA256"; + reference + "RFC 8442: + ECDHE_PSK with AES-GCM and AES-CCM Cipher Suites"; + } + + identity tls-ecdhe-psk-with-aes-128-ccm-sha256 { + base cipher-suite-alg-base; + description + "TLS-ECDHE-PSK-WITH-AES-128-CCM-SHA256"; + reference + "RFC 8442: + ECDHE_PSK with AES-GCM and AES-CCM Cipher Suites"; + } + + typedef cipher-suite-algorithm-ref { + type identityref { + base cipher-suite-alg-base; + } + description + "A reference to a TLS cipher suite algorithm identifier."; + } + + container supported-algorithms { + config false; + description + "A container for a list of cipher suite algorithms supported + by the server."; + leaf-list supported-algorithm { + type cipher-suite-algorithm-ref; + description + "A cipher suite algorithm supported by the server."; + } + } +} diff --git a/src/confd/yang/ietf-crypto-types@2023-12-28.yang b/src/confd/yang/ietf-crypto-types@2023-12-28.yang new file mode 100644 index 00000000..2013727c --- /dev/null +++ b/src/confd/yang/ietf-crypto-types@2023-12-28.yang @@ -0,0 +1,1028 @@ +module ietf-crypto-types { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-crypto-types"; + prefix ct; + + import ietf-yang-types { + prefix yang; + reference + "RFC 6991: Common YANG Data Types"; + } + import ietf-netconf-acm { + prefix nacm; + reference + "RFC 8341: Network Configuration Access Control Model"; + } + + organization + "IETF NETCONF (Network Configuration) Working Group"; + contact + "WG Web: https://datatracker.ietf.org/wg/netconf + WG List: NETCONF WG list + Author: Kent Watsen "; + description + "This module defines common YANG types for cryptographic + applications. + + Copyright (c) 2023 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 AAAA + (https://www.rfc-editor.org/info/rfcAAAA); 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 2023-12-28 { + description + "Initial version"; + reference + "RFC AAAA: YANG Data Types and Groupings for Cryptography"; + } + + feature one-symmetric-key-format { + description + "Indicates that the server supports the + 'one-symmetric-key-format' identity."; + } + + feature one-asymmetric-key-format { + description + "Indicates that the server supports the + 'one-asymmetric-key-format' identity."; + } + + feature symmetrically-encrypted-value-format { + description + "Indicates that the server supports the + 'symmetrically-encrypted-value-format' identity."; + } + + feature asymmetrically-encrypted-value-format { + description + "Indicates that the server supports the + 'asymmetrically-encrypted-value-format' identity."; + } + + feature cms-enveloped-data-format { + description + "Indicates that the server supports the + 'cms-enveloped-data-format' identity."; + } + + feature cms-encrypted-data-format { + description + "Indicates that the server supports the + 'cms-encrypted-data-format' identity."; + } + + feature p10-csr-format { + description + "Indicates that the server implements support + for generating P10-based CSRs, as defined + in RFC 2986."; + reference + "RFC 2986: PKCS #10: Certification Request Syntax + Specification Version 1.7"; + } + + feature csr-generation { + description + "Indicates that the server implements the + 'generate-csr' action."; + } + + feature certificate-expiration-notification { + description + "Indicates that the server implements the + 'certificate-expiration' notification."; + } + + feature cleartext-passwords { + description + "Indicates that the server supports cleartext + passwords."; + } + + feature encrypted-passwords { + description + "Indicates that the server supports password + encryption."; + } + + feature cleartext-symmetric-keys { + description + "Indicates that the server supports cleartext + symmetric keys."; + } + + feature hidden-symmetric-keys { + description + "Indicates that the server supports hidden keys."; + } + + feature encrypted-symmetric-keys { + description + "Indicates that the server supports encryption + of symmetric keys."; + } + + feature cleartext-private-keys { + description + "Indicates that the server supports cleartext + private keys."; + } + + feature hidden-private-keys { + description + "Indicates that the server supports hidden keys."; + } + + feature encrypted-private-keys { + description + "Indicates that the server supports encryption + of private keys."; + } + + identity symmetric-key-format { + description + "Base key-format identity for symmetric keys."; + } + + identity public-key-format { + description + "Base key-format identity for public keys."; + } + + identity private-key-format { + description + "Base key-format identity for private keys."; + } + + identity rsa-private-key-format { + base private-key-format; + description + "Indicates that the private key value is encoded as + an RSAPrivateKey (from RFC 3447), encoded using ASN.1 + distinguished encoding rules (DER), as specified in + ITU-T X.690."; + reference + "RFC 3447: + PKCS #1: RSA Cryptography Specifications Version 2.2 + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER) 02/2021."; + } + + identity ec-private-key-format { + base private-key-format; + description + "Indicates that the private key value is encoded as + an ECPrivateKey (from RFC 5915), encoded using ASN.1 + distinguished encoding rules (DER), as specified in + ITU-T X.690."; + reference + "RFC 5915: + Elliptic Curve Private Key Structure + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER) 02/2021."; + } + + identity one-asymmetric-key-format { + if-feature "one-asymmetric-key-format"; + base private-key-format; + description + "Indicates that the private key value is a CMS + OneAsymmetricKey structure, as defined in RFC 5958, + encoded using ASN.1 distinguished encoding rules + (DER), as specified in ITU-T X.690."; + reference + "RFC 5958: Asymmetric Key Packages + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER) 02/2021."; + } + + identity ssh-public-key-format { + base public-key-format; + description + "Indicates that the public key value is an SSH public key, + as specified by RFC 4253, Section 6.6, i.e.: + + string certificate or public key format + identifier + byte[n] key/certificate data."; + reference + "RFC 4253: The Secure Shell (SSH) Transport Layer Protocol"; + } + + identity subject-public-key-info-format { + base public-key-format; + description + "Indicates that the public key value is a SubjectPublicKeyInfo + structure, as described in RFC 5280 encoded using ASN.1 + distinguished encoding rules (DER), as specified in + ITU-T X.690."; + reference + "RFC 5280: + Internet X.509 Public Key Infrastructure Certificate + and Certificate Revocation List (CRL) Profile + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER) 02/2021."; + } + + identity octet-string-key-format { + base symmetric-key-format; + description + "Indicates that the key is encoded as a raw octet string. + The length of the octet string MUST be appropriate for + the associated algorithm's block size. + + The identity of the associated algorithm is outside the + scope of this specification. This is also true when + the octet string has been encrypted."; + } + + identity one-symmetric-key-format { + if-feature "one-symmetric-key-format"; + base symmetric-key-format; + description + "Indicates that the private key value is a CMS + OneSymmetricKey structure, as defined in RFC 6031, + encoded using ASN.1 distinguished encoding rules + (DER), as specified in ITU-T X.690."; + reference + "RFC 6031: Cryptographic Message Syntax (CMS) + Symmetric Key Package Content Type + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER) 02/2021."; + } + + identity encrypted-value-format { + description + "Base format identity for encrypted values."; + } + + identity symmetrically-encrypted-value-format { + if-feature "symmetrically-encrypted-value-format"; + base encrypted-value-format; + description + "Base format identity for symmetrically encrypted + values."; + } + + identity asymmetrically-encrypted-value-format { + if-feature "asymmetrically-encrypted-value-format"; + base encrypted-value-format; + description + "Base format identity for asymmetrically encrypted + values."; + } + + identity cms-encrypted-data-format { + if-feature "cms-encrypted-data-format"; + base symmetrically-encrypted-value-format; + description + "Indicates that the encrypted value conforms to + the 'encrypted-data-cms' type with the constraint + that the 'unprotectedAttrs' value is not set."; + reference + "RFC 5652: Cryptographic Message Syntax (CMS) + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER) 02/2021."; + } + + identity cms-enveloped-data-format { + if-feature "cms-enveloped-data-format"; + base asymmetrically-encrypted-value-format; + description + "Indicates that the encrypted value conforms to the + 'enveloped-data-cms' type with the following constraints: + + The EnvelopedData structure MUST have exactly one + 'RecipientInfo'. + + If the asymmetric key supports public key cryptography + (e.g., RSA), then the 'RecipientInfo' must be a + 'KeyTransRecipientInfo' with the 'RecipientIdentifier' + using a 'subjectKeyIdentifier' with the value set using + 'method 1' in RFC 7093 over the recipient's public key. + + Otherwise, if the asymmetric key supports key agreement + (e.g., ECC), then the 'RecipientInfo' must be a + 'KeyAgreeRecipientInfo'. The 'OriginatorIdentifierOrKey' + value must use the 'OriginatorPublicKey' alternative. + The 'UserKeyingMaterial' value must not be present. + There must be exactly one 'RecipientEncryptedKeys' value + having the 'KeyAgreeRecipientIdentifier' set to 'rKeyId' + with the value set using 'method 1' in RFC 7093 over the + recipient's public key."; + reference + "RFC 5652: Cryptographic Message Syntax (CMS) + RFC 7093: + Additional Methods for Generating Key + Identifiers Values + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER) 02/2021."; + } + + identity csr-format { + description + "A base identity for the certificate signing request + formats. Additional derived identities MAY be defined + by future efforts."; + } + + identity p10-csr-format { + if-feature "p10-csr-format"; + base csr-format; + description + "Indicates the 'CertificationRequest' structure + defined in RFC 2986."; + reference + "RFC 2986: PKCS #10: Certification Request Syntax + Specification Version 1.7"; + } + + typedef csr-info { + type binary; + description + "A CertificationRequestInfo structure, as defined in + RFC 2986, encoded using ASN.1 distinguished encoding + rules (DER), as specified in ITU-T X.690."; + reference + "RFC 2986: PKCS #10: Certification Request Syntax + Specification Version 1.7 + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER) 02/2021."; + } + + typedef p10-csr { + type binary; + description + "A CertificationRequest structure, as specified in + RFC 2986, encoded using ASN.1 distinguished encoding + rules (DER), as specified in ITU-T X.690."; + reference + "RFC 2986: + PKCS #10: Certification Request Syntax Specification + Version 1.7 + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER) 02/2021."; + } + + typedef x509 { + type binary; + description + "A Certificate structure, as specified in RFC 5280, + encoded using ASN.1 distinguished encoding rules (DER), + as specified in ITU-T X.690."; + reference + "RFC 5280: + Internet X.509 Public Key Infrastructure Certificate + and Certificate Revocation List (CRL) Profile + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER) 02/2021."; + } + + typedef crl { + type binary; + description + "A CertificateList structure, as specified in RFC 5280, + encoded using ASN.1 distinguished encoding rules (DER), + as specified in ITU-T X.690."; + reference + "RFC 5280: + Internet X.509 Public Key Infrastructure Certificate + and Certificate Revocation List (CRL) Profile + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER) 02/2021."; + } + + typedef oscp-request { + type binary; + description + "A OCSPRequest structure, as specified in RFC 6960, + encoded using ASN.1 distinguished encoding rules + (DER), as specified in ITU-T X.690."; + reference + "RFC 6960: + X.509 Internet Public Key Infrastructure Online + Certificate Status Protocol - OCSP + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER) 02/2021."; + } + + typedef oscp-response { + type binary; + description + "A OCSPResponse structure, as specified in RFC 6960, + encoded using ASN.1 distinguished encoding rules + (DER), as specified in ITU-T X.690."; + reference + "RFC 6960: + X.509 Internet Public Key Infrastructure Online + Certificate Status Protocol - OCSP + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER) 02/2021."; + } + + typedef cms { + type binary; + description + "A ContentInfo structure, as specified in RFC 5652, + encoded using ASN.1 distinguished encoding rules (DER), + as specified in ITU-T X.690."; + reference + "RFC 5652: + Cryptographic Message Syntax (CMS) + ITU-T X.690: + Information technology - ASN.1 encoding rules: + Specification of Basic Encoding Rules (BER), + Canonical Encoding Rules (CER) and Distinguished + Encoding Rules (DER) 02/2021."; + } + + typedef data-content-cms { + type cms; + description + "A CMS structure whose top-most content type MUST be the + data content type, as described by Section 4 in RFC 5652."; + reference + "RFC 5652: Cryptographic Message Syntax (CMS)"; + } + + typedef signed-data-cms { + type cms; + description + "A CMS structure whose top-most content type MUST be the + signed-data content type, as described by Section 5 in + RFC 5652."; + reference + "RFC 5652: Cryptographic Message Syntax (CMS)"; + } + + typedef enveloped-data-cms { + type cms; + description + "A CMS structure whose top-most content type MUST be the + enveloped-data content type, as described by Section 6 + in RFC 5652."; + reference + "RFC 5652: Cryptographic Message Syntax (CMS)"; + } + + typedef digested-data-cms { + type cms; + description + "A CMS structure whose top-most content type MUST be the + digested-data content type, as described by Section 7 + in RFC 5652."; + reference + "RFC 5652: Cryptographic Message Syntax (CMS)"; + } + + typedef encrypted-data-cms { + type cms; + description + "A CMS structure whose top-most content type MUST be the + encrypted-data content type, as described by Section 8 + in RFC 5652."; + reference + "RFC 5652: Cryptographic Message Syntax (CMS)"; + } + + typedef authenticated-data-cms { + type cms; + description + "A CMS structure whose top-most content type MUST be the + authenticated-data content type, as described by Section 9 + in RFC 5652."; + reference + "RFC 5652: Cryptographic Message Syntax (CMS)"; + } + + typedef trust-anchor-cert-x509 { + type x509; + description + "A Certificate structure that MUST encode a self-signed + root certificate."; + } + + typedef end-entity-cert-x509 { + type x509; + description + "A Certificate structure that MUST encode a certificate + that is neither self-signed nor having Basic constraint + CA true."; + } + + typedef trust-anchor-cert-cms { + type signed-data-cms; + description + "A CMS SignedData structure that MUST contain the chain of + X.509 certificates needed to authenticate the certificate + presented by a client or end-entity. + + The CMS MUST contain only a single chain of certificates. + The client or end-entity certificate MUST only authenticate + to the last intermediate CA certificate listed in the chain. + + In all cases, the chain MUST include a self-signed root + certificate. In the case where the root certificate is + itself the issuer of the client or end-entity certificate, + only one certificate is present. + + This CMS structure MAY (as applicable where this type is + used) also contain suitably fresh (as defined by local + policy) revocation objects with which the device can + verify the revocation status of the certificates. + + This CMS encodes the degenerate form of the SignedData + structure (RFC 5652, Section 5.2) that is commonly used + to disseminate X.509 certificates and revocation objects + (RFC 5280)."; + reference + "RFC 5280: + Internet X.509 Public Key Infrastructure Certificate + and Certificate Revocation List (CRL) Profile. + RFC 5652: + Cryptographic Message Syntax (CMS)"; + } + + typedef end-entity-cert-cms { + type signed-data-cms; + description + "A CMS SignedData structure that MUST contain the end + entity certificate itself, and MAY contain any number + of intermediate certificates leading up to a trust + anchor certificate. The trust anchor certificate + MAY be included as well. + + The CMS MUST contain a single end entity certificate. + The CMS MUST NOT contain any spurious certificates. + + This CMS structure MAY (as applicable where this type is + used) also contain suitably fresh (as defined by local + policy) revocation objects with which the device can + verify the revocation status of the certificates. + + This CMS encodes the degenerate form of the SignedData + structure (RFC 5652, Section 5.2) that is commonly + used to disseminate X.509 certificates and revocation + objects (RFC 5280)."; + reference + "RFC 5280: + Internet X.509 Public Key Infrastructure Certificate + and Certificate Revocation List (CRL) Profile. + RFC 5652: + Cryptographic Message Syntax (CMS)"; + } + + grouping encrypted-value-grouping { + description + "A reusable grouping for a value that has been encrypted by + a referenced symmetric or asymmetric key."; + container encrypted-by { + nacm:default-deny-write; + description + "An empty container enabling a reference to the key that + encrypted the value to be augmented in. The referenced + key MUST be a symmetric key or an asymmetric key. + + A symmetric key MUST be referenced via a leaf node called + 'symmetric-key-ref'. An asymmetric key MUST be referenced + via a leaf node called 'asymmetric-key-ref'. + + The leaf nodes MUST be direct descendants in the data tree, + and MAY be direct descendants in the schema tree (e.g., + choice/case statements are allowed, but not a container)."; + } + leaf encrypted-value-format { + type identityref { + base encrypted-value-format; + } + mandatory true; + description + "Identifies the format of the 'encrypted-value' leaf. + + If 'encrypted-by' points to a symmetric key, then a + 'symmetrically-encrypted-value-format' based identity + MUST by set (e.g., cms-encrypted-data-format). + + If 'encrypted-by' points to an asymmetric key, then an + 'asymmetrically-encrypted-value-format' based identity + MUST by set (e.g., cms-enveloped-data-format)."; + } + leaf encrypted-value { + nacm:default-deny-write; + type binary; + must '../encrypted-by'; + mandatory true; + description + "The value, encrypted using the referenced symmetric + or asymmetric key. The value MUST be encoded using + the format associated with the 'encrypted-value-format' + leaf."; + } + } + + grouping password-grouping { + description + "A password that may be encrypted."; + choice password-type { + nacm:default-deny-write; + mandatory true; + description + "Choice between password types."; + case cleartext-password { + if-feature "cleartext-passwords"; + leaf cleartext-password { + nacm:default-deny-all; + type string; + description + "The cleartext value of the password."; + } + } + case encrypted-password { + if-feature "encrypted-passwords"; + container encrypted-password { + description + "A container for the encrypted password value."; + uses encrypted-value-grouping; + } + } + } + } + + grouping symmetric-key-grouping { + description + "A symmetric key."; + leaf key-format { + nacm:default-deny-write; + type identityref { + base symmetric-key-format; + } + description + "Identifies the symmetric key's format. Implementations + SHOULD ensure that the incoming symmetric key value is + encoded in the specified format. + + For encrypted keys, the value is the decrypted key's + format (i.e., the 'encrypted-value-format' conveys the + encrypted key's format."; + } + choice key-type { + nacm:default-deny-write; + mandatory true; + description + "Choice between key types."; + case cleartext-key { + leaf cleartext-key { + nacm:default-deny-all; + if-feature "cleartext-symmetric-keys"; + type binary; + must '../key-format'; + description + "The binary value of the key. The interpretation of + the value is defined by the 'key-format' field."; + } + } + case hidden-key { + if-feature "hidden-symmetric-keys"; + leaf hidden-key { + type empty; + must 'not(../key-format)'; + description + "A hidden key. How such keys are created is outside + the scope of this module."; + } + } + case encrypted-key { + if-feature "encrypted-symmetric-keys"; + container encrypted-key { + must '../key-format'; + description + "A container for the encrypted symmetric key value. + The interpretation of the 'encrypted-value' node + is via the 'key-format' node"; + uses encrypted-value-grouping; + } + } + } + } + + grouping public-key-grouping { + description + "A public key."; + leaf public-key-format { + nacm:default-deny-write; + type identityref { + base public-key-format; + } + mandatory true; + description + "Identifies the public key's format. Implementations SHOULD + ensure that the incoming public key value is encoded in the + specified format."; + } + leaf public-key { + nacm:default-deny-write; + type binary; + mandatory true; + description + "The binary value of the public key. The interpretation + of the value is defined by 'public-key-format' field."; + } + } + + grouping private-key-grouping { + description + "A private key."; + leaf private-key-format { + nacm:default-deny-write; + type identityref { + base private-key-format; + } + description + "Identifies the private key's format. Implementations SHOULD + ensure that the incoming private key value is encoded in the + specified format. + + For encrypted keys, the value is the decrypted key's + format (i.e., the 'encrypted-value-format' conveys the + encrypted key's format."; + } + choice private-key-type { + nacm:default-deny-write; + mandatory true; + description + "Choice between key types."; + case cleartext-private-key { + if-feature "cleartext-private-keys"; + leaf cleartext-private-key { + nacm:default-deny-all; + type binary; + must '../private-key-format'; + description + "The value of the binary key The key's value is + interpreted by the 'private-key-format' field."; + } + } + case hidden-private-key { + if-feature "hidden-private-keys"; + leaf hidden-private-key { + type empty; + must 'not(../private-key-format)'; + description + "A hidden key. How such keys are created is + outside the scope of this module."; + } + } + case encrypted-private-key { + if-feature "encrypted-private-keys"; + container encrypted-private-key { + must '../private-key-format'; + description + "A container for the encrypted asymmetric private key + value. The interpretation of the 'encrypted-value' + node is via the 'private-key-format' node"; + uses encrypted-value-grouping; + } + } + } + } + + grouping asymmetric-key-pair-grouping { + description + "A private key and, optionally, its associated public key. + Implementations SHOULD ensure that the two keys, when both + are specified, are a matching pair."; + uses public-key-grouping { + refine "public-key-format" { + mandatory false; + } + refine "public-key" { + mandatory false; + } + } + uses private-key-grouping; + } + + grouping certificate-expiration-grouping { + description + "A notification for when a certificate is about to, or + already has, expired."; + notification certificate-expiration { + if-feature "certificate-expiration-notification"; + description + "A notification indicating that the configured certificate + is either about to expire or has already expired. When to + send notifications is an implementation specific decision, + but it is RECOMMENDED that a notification be sent once a + month for 3 months, then once a week for four weeks, and + then once a day thereafter until the issue is resolved."; + leaf expiration-date { + type yang:date-and-time; + mandatory true; + description + "Identifies the expiration date on the certificate."; + } + } + } + + grouping trust-anchor-cert-grouping { + description + "A trust anchor certificate, and a notification for when + it is about to (or already has) expire."; + leaf cert-data { + nacm:default-deny-write; + type trust-anchor-cert-cms; + description + "The binary certificate data for this certificate."; + } + uses certificate-expiration-grouping; + } + + grouping end-entity-cert-grouping { + description + "An end entity certificate, and a notification for when + it is about to (or already has) expire. Implementations + SHOULD assert that, where used, the end entity certificate + contains the expected public key."; + leaf cert-data { + nacm:default-deny-write; + type end-entity-cert-cms; + description + "The binary certificate data for this certificate."; + } + uses certificate-expiration-grouping; + } + + grouping generate-csr-grouping { + description + "Defines the 'generate-csr' action."; + action generate-csr { + nacm:default-deny-all; + if-feature "csr-generation"; + description + "Generates a certificate signing request structure for + the associated asymmetric key using the passed subject + and attribute values. + + This action statement is only available when the + associated 'public-key-format' node's value is + 'subject-public-key-info-format'."; + reference + "RFC 6125: + Representation and Verification of Domain-Based + Application Service Identity within Internet Public Key + Infrastructure Using X.509 (PKIX) Certificates in the + Context of Transport Layer Security (TLS)"; + + input { + leaf csr-format { + type identityref { + base csr-format; + } + mandatory true; + description + "Specifies the format for the returned certificate."; + } + leaf csr-info { + type csr-info; + mandatory true; + description + "A CertificationRequestInfo structure, as defined in + RFC 2986. + + Enables the client to provide a fully-populated + CertificationRequestInfo structure that the server + only needs to sign in order to generate the complete + 'CertificationRequest' structure to return in the + 'output'. + + The 'AlgorithmIdentifier' field contained inside + the 'SubjectPublicKeyInfo' field MUST be one known + to be supported by the device."; + reference + "RFC 2986: + PKCS #10: Certification Request Syntax Specification + RFC AAAA: + YANG Data Types and Groupings for Cryptography"; + } + } + output { + choice csr-type { + mandatory true; + description + "A choice amongst certificate signing request formats. + Additional formats MAY be augmented into this 'choice' + statement by future efforts."; + case p10-csr { + description + "A CertificationRequest, as defined in RFC 2986."; + reference + "RFC 2986: + PKCS #10: Certification Request Syntax Specification + RFC AAAA: + YANG Data Types and Groupings for Cryptography"; + leaf p10-csr { + type p10-csr; + description + "A CertificationRequest, as defined in RFC 2986."; + } + } + } + } + } + } + + grouping asymmetric-key-pair-with-cert-grouping { + description + "A private/public key pair and an associated certificate. + Implementations SHOULD assert that the certificate contains + the matching public key."; + uses asymmetric-key-pair-grouping; + uses end-entity-cert-grouping; + uses generate-csr-grouping; + } + + grouping asymmetric-key-pair-with-certs-grouping { + description + "A private/public key pair and a list of associated + certificates. Implementations SHOULD assert that + certificates contain the matching public key."; + uses asymmetric-key-pair-grouping; + container certificates { + nacm:default-deny-write; + description + "Certificates associated with this asymmetric key."; + list certificate { + key "name"; + description + "A certificate for this asymmetric key."; + leaf name { + type string; + description + "An arbitrary name for the certificate."; + } + uses end-entity-cert-grouping { + refine "cert-data" { + mandatory true; + } + } + } + } + uses generate-csr-grouping; + } +} diff --git a/src/confd/yang/ietf-keystore@2023-12-28.yang b/src/confd/yang/ietf-keystore@2023-12-28.yang new file mode 100644 index 00000000..8b3d1656 --- /dev/null +++ b/src/confd/yang/ietf-keystore@2023-12-28.yang @@ -0,0 +1,374 @@ +module ietf-keystore { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-keystore"; + prefix ks; + + 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"; + } + + organization + "IETF NETCONF (Network Configuration) Working Group"; + contact + "WG Web: https://datatracker.ietf.org/wg/netconf + WG List: NETCONF WG list + Author: Kent Watsen "; + description + "This module defines a 'keystore' to centralize management + of security credentials. + + Copyright (c) 2023 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 CCCC + (https://www.rfc-editor.org/info/rfcCCCC); 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 2023-12-28 { + description + "Initial version"; + reference + "RFC CCCC: A YANG Data Model for a Keystore"; + } + + feature central-keystore-supported { + description + "The 'central-keystore-supported' feature indicates that + the server supports the central keystore (i.e., fully + implements the 'ietf-keystore' module)."; + } + + feature inline-definitions-supported { + description + "The 'inline-definitions-supported' feature indicates that + the server supports locally-defined keys."; + } + + feature asymmetric-keys { + description + "The 'asymmetric-keys' feature indicates that the server + implements the /keystore/asymmetric-keys subtree."; + } + + feature symmetric-keys { + description + "The 'symmetric-keys' feature indicates that the server + implements the /keystore/symmetric-keys subtree."; + } + + typedef symmetric-key-ref { + type leafref { + path "/ks:keystore/ks:symmetric-keys/ks:symmetric-key/ks:name"; + } + description + "This typedef enables modules to easily define a reference + to a symmetric key stored in the central keystore."; + } + + typedef asymmetric-key-ref { + type leafref { + path "/ks:keystore/ks:asymmetric-keys/ks:asymmetric-key/ks:name"; + } + description + "This typedef enables modules to easily define a reference + to an asymmetric key stored in the central keystore."; + } + + grouping encrypted-by-grouping { + description + "A grouping that defines a 'choice' statement that can be + augmented into the 'encrypted-by' node, present in the + 'symmetric-key-grouping' and 'asymmetric-key-pair-grouping' + groupings defined in RFC AAAA, enabling references to keys + in the central keystore."; + choice encrypted-by { + nacm:default-deny-write; + mandatory true; + description + "A choice amongst other symmetric or asymmetric keys."; + case symmetric-key-ref { + if-feature "central-keystore-supported"; + if-feature "symmetric-keys"; + leaf symmetric-key-ref { + type ks:symmetric-key-ref; + description + "Identifies the symmetric key used to encrypt the + associated key."; + } + } + case asymmetric-key-ref { + if-feature "central-keystore-supported"; + if-feature "asymmetric-keys"; + leaf asymmetric-key-ref { + type ks:asymmetric-key-ref; + description + "Identifies the asymmetric key whose public key + encrypted the associated key."; + } + } + } + } + + grouping asymmetric-key-certificate-ref-grouping { + description + "Grouping for the reference to a certificate associated + with an asymmetric key stored in the central keystore."; + leaf asymmetric-key { + nacm:default-deny-write; + if-feature "central-keystore-supported"; + if-feature "asymmetric-keys"; + type ks:asymmetric-key-ref; + must '../certificate'; + description + "A reference to an asymmetric key in the keystore."; + } + leaf certificate { + nacm:default-deny-write; + type leafref { + path "/ks:keystore/ks:asymmetric-keys/ks:asymmetric-key[ks:name = current()/../asymmetric-key]/ks:certificates/ks:certificate/ks:name"; + } + must '../asymmetric-key'; + description + "A reference to a specific certificate of the + asymmetric key in the keystore."; + } + } + + grouping inline-or-keystore-symmetric-key-grouping { + description + "A grouping for the configuration of a symmetric key. The + symmetric key may be defined inline or as a reference to + a symmetric key stored in the central keystore. + + Servers that do not define the 'central-keystore-supported' + feature SHOULD augment in custom 'case' statements enabling + references to alternate keystore locations."; + choice inline-or-keystore { + nacm:default-deny-write; + mandatory true; + description + "A choice between an inlined definition and a definition + that exists in the keystore."; + case inline { + if-feature "inline-definitions-supported"; + container inline-definition { + description + "Container to hold the local key definition."; + uses ct:symmetric-key-grouping; + } + } + case central-keystore { + if-feature "central-keystore-supported"; + if-feature "symmetric-keys"; + leaf central-keystore-reference { + type ks:symmetric-key-ref; + description + "A reference to an symmetric key that exists in + the central keystore."; + } + } + } + } + + grouping inline-or-keystore-asymmetric-key-grouping { + description + "A grouping for the configuration of an asymmetric key. The + asymmetric key may be defined inline or as a reference to + an asymmetric key stored in the central keystore. + + Servers that do not define the 'central-keystore-supported' + feature SHOULD augment in custom 'case' statements enabling + references to alternate keystore locations."; + choice inline-or-keystore { + nacm:default-deny-write; + mandatory true; + description + "A choice between an inlined definition and a definition + that exists in the keystore."; + case inline { + if-feature "inline-definitions-supported"; + container inline-definition { + description + "Container to hold the local key definition."; + uses ct:asymmetric-key-pair-grouping; + } + } + case central-keystore { + if-feature "central-keystore-supported"; + if-feature "asymmetric-keys"; + leaf central-keystore-reference { + type ks:asymmetric-key-ref; + description + "A reference to an asymmetric key that exists in + the central keystore. The intent is to reference + just the asymmetric key without any regard for + any certificates that may be associated with it."; + } + } + } + } + + grouping inline-or-keystore-asymmetric-key-with-certs-grouping { + description + "A grouping for the configuration of an asymmetric key and + its associated certificates. The asymmetric key and its + associated certificates may be defined inline or as a + reference to an asymmetric key (and its associated + certificates) in the central keystore. + + Servers that do not define the 'central-keystore-supported' + feature SHOULD augment in custom 'case' statements enabling + references to alternate keystore locations."; + choice inline-or-keystore { + nacm:default-deny-write; + mandatory true; + description + "A choice between an inlined definition and a definition + that exists in the keystore."; + case inline { + if-feature "inline-definitions-supported"; + container inline-definition { + description + "Container to hold the local key definition."; + uses ct:asymmetric-key-pair-with-certs-grouping; + } + } + case central-keystore { + if-feature "central-keystore-supported"; + if-feature "asymmetric-keys"; + leaf central-keystore-reference { + type ks:asymmetric-key-ref; + description + "A reference to an asymmetric-key (and all of its + associated certificates) in the keystore, when + this module is implemented."; + } + } + } + } + + grouping inline-or-keystore-end-entity-cert-with-key-grouping { + description + "A grouping for the configuration of an asymmetric key and + its associated end-entity certificate. The asymmetric key + and its associated end-entity certificate may be defined + inline or as a reference to an asymmetric key (and its + associated end-entity certificate) in the central keystore. + + Servers that do not define the 'central-keystore-supported' + feature SHOULD augment in custom 'case' statements enabling + references to alternate keystore locations."; + choice inline-or-keystore { + nacm:default-deny-write; + mandatory true; + description + "A choice between an inlined definition and a definition + that exists in the keystore."; + case inline { + if-feature "inline-definitions-supported"; + container inline-definition { + description + "Container to hold the local key definition."; + uses ct:asymmetric-key-pair-with-cert-grouping; + } + } + case central-keystore { + if-feature "central-keystore-supported"; + if-feature "asymmetric-keys"; + container central-keystore-reference { + description + "A reference to a specific certificate associated with + an asymmetric key stored in the central keystore."; + uses asymmetric-key-certificate-ref-grouping; + } + } + } + } + + grouping keystore-grouping { + description + "Grouping definition enables use in other contexts. If ever + done, implementations MUST augment new 'case' statements + into the various inline-or-keystore 'choice' statements to + supply leafrefs to the model-specific location(s)."; + container asymmetric-keys { + nacm:default-deny-write; + if-feature "asymmetric-keys"; + description + "A list of asymmetric keys."; + list asymmetric-key { + key "name"; + description + "An asymmetric key."; + leaf name { + type string; + description + "An arbitrary name for the asymmetric key."; + } + uses ct:asymmetric-key-pair-with-certs-grouping; + } + } + container symmetric-keys { + nacm:default-deny-write; + if-feature "symmetric-keys"; + description + "A list of symmetric keys."; + list symmetric-key { + key "name"; + description + "A symmetric key."; + leaf name { + type string; + description + "An arbitrary name for the symmetric key."; + } + uses ct:symmetric-key-grouping; + } + } + } + + container keystore { + nacm:default-deny-write; + if-feature "central-keystore-supported"; + description + "A central keystore containing a list of symmetric keys and + a list of asymmetric keys."; + uses keystore-grouping { + augment "symmetric-keys/symmetric-key/key-type/encrypted-key/encrypted-key/encrypted-by" { + description + "Augments in a choice statement enabling the encrypting + key to be any other symmetric or asymmetric key in the + central keystore."; + uses encrypted-by-grouping; + } + augment "asymmetric-keys/asymmetric-key/private-key-type/encrypted-private-key/encrypted-private-key/encrypted-by" { + description + "Augments in a choice statement enabling the encrypting + key to be any other symmetric or asymmetric key in the + central keystore."; + uses encrypted-by-grouping; + } + } + } +} diff --git a/src/confd/yang/ietf-netconf-acm@2018-02-14.yang b/src/confd/yang/ietf-netconf-acm@2018-02-14.yang new file mode 100644 index 00000000..2a8fedaa --- /dev/null +++ b/src/confd/yang/ietf-netconf-acm@2018-02-14.yang @@ -0,0 +1,423 @@ +module ietf-netconf-acm { + namespace "urn:ietf:params:xml:ns:yang:ietf-netconf-acm"; + prefix nacm; + + import ietf-yang-types { + prefix yang; + } + + organization + "IETF NETCONF (Network Configuration) Working Group"; + contact + "WG Web: + WG List: + + Author: Andy Bierman + + + Author: Martin Bjorklund + "; + description + "Network Configuration Access Control Model. + + Copyright (c) 2012 - 2018 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 Simplified 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 8341; see + the RFC itself for full legal notices."; + + revision 2018-02-14 { + description + "Added support for YANG 1.1 actions and notifications tied to + data nodes. Clarified how NACM extensions can be used by + other data models."; + reference + "RFC 8341: Network Configuration Access Control Model"; + } + revision 2012-02-22 { + description + "Initial version."; + reference + "RFC 6536: Network Configuration Protocol (NETCONF) + Access Control Model"; + } + + extension default-deny-write { + description + "Used to indicate that the data model node + represents a sensitive security system parameter. + + If present, the NETCONF server will only allow the designated + 'recovery session' to have write access to the node. An + explicit access control rule is required for all other users. + + If the NACM module is used, then it must be enabled (i.e., + /nacm/enable-nacm object equals 'true'), or this extension + is ignored. + + The 'default-deny-write' extension MAY appear within a data + definition statement. It is ignored otherwise."; + } + extension default-deny-all { + description + "Used to indicate that the data model node + controls a very sensitive security system parameter. + + If present, the NETCONF server will only allow the designated + 'recovery session' to have read, write, or execute access to + the node. An explicit access control rule is required for all + other users. + + If the NACM module is used, then it must be enabled (i.e., + /nacm/enable-nacm object equals 'true'), or this extension + is ignored. + + The 'default-deny-all' extension MAY appear within a data + definition statement, 'rpc' statement, or 'notification' + statement. It is ignored otherwise."; + } + + typedef user-name-type { + type string { + length "1..max"; + } + description + "General-purpose username string."; + } + + typedef matchall-string-type { + type string { + pattern '\*'; + } + description + "The string containing a single asterisk '*' is used + to conceptually represent all possible values + for the particular leaf using this data type."; + } + + typedef access-operations-type { + type bits { + bit create { + description + "Any protocol operation that creates a + new data node."; + } + bit read { + description + "Any protocol operation or notification that + returns the value of a data node."; + } + bit update { + description + "Any protocol operation that alters an existing + data node."; + } + bit delete { + description + "Any protocol operation that removes a data node."; + } + bit exec { + description + "Execution access to the specified protocol operation."; + } + } + description + "Access operation."; + } + + typedef group-name-type { + type string { + length "1..max"; + pattern '[^\*].*'; + } + description + "Name of administrative group to which + users can be assigned."; + } + + typedef action-type { + type enumeration { + enum "permit" { + description + "Requested action is permitted."; + } + enum "deny" { + description + "Requested action is denied."; + } + } + description + "Action taken by the server when a particular + rule matches."; + } + + typedef node-instance-identifier { + type yang:xpath1.0; + description + "Path expression used to represent a special + data node, action, or notification instance-identifier + string. + + A node-instance-identifier value is an + unrestricted YANG instance-identifier expression. + All the same rules as an instance-identifier apply, + except that predicates for keys are optional. If a key + predicate is missing, then the node-instance-identifier + represents all possible server instances for that key. + + This XML Path Language (XPath) expression is evaluated in the + following context: + + o The set of namespace declarations are those in scope on + the leaf element where this type is used. + + o The set of variable bindings contains one variable, + 'USER', which contains the name of the user of the + current session. + + o The function library is the core function library, but + note that due to the syntax restrictions of an + instance-identifier, no functions are allowed. + + o The context node is the root node in the data tree. + + The accessible tree includes actions and notifications tied + to data nodes."; + } + + container nacm { + nacm:default-deny-all; + description + "Parameters for NETCONF access control model."; + leaf enable-nacm { + type boolean; + default "true"; + description + "Enables or disables all NETCONF access control + enforcement. If 'true', then enforcement + is enabled. If 'false', then enforcement + is disabled."; + } + leaf read-default { + type action-type; + default "permit"; + description + "Controls whether read access is granted if + no appropriate rule is found for a + particular read request."; + } + leaf write-default { + type action-type; + default "deny"; + description + "Controls whether create, update, or delete access + is granted if no appropriate rule is found for a + particular write request."; + } + leaf exec-default { + type action-type; + default "permit"; + description + "Controls whether exec access is granted if no appropriate + rule is found for a particular protocol operation request."; + } + leaf enable-external-groups { + type boolean; + default "true"; + description + "Controls whether the server uses the groups reported by the + NETCONF transport layer when it assigns the user to a set of + NACM groups. If this leaf has the value 'false', any group + names reported by the transport layer are ignored by the + server."; + } + leaf denied-operations { + type yang:zero-based-counter32; + config false; + mandatory true; + description + "Number of times since the server last restarted that a + protocol operation request was denied."; + } + leaf denied-data-writes { + type yang:zero-based-counter32; + config false; + mandatory true; + description + "Number of times since the server last restarted that a + protocol operation request to alter + a configuration datastore was denied."; + } + leaf denied-notifications { + type yang:zero-based-counter32; + config false; + mandatory true; + description + "Number of times since the server last restarted that + a notification was dropped for a subscription because + access to the event type was denied."; + } + container groups { + description + "NETCONF access control groups."; + list group { + key "name"; + description + "One NACM group entry. This list will only contain + configured entries, not any entries learned from + any transport protocols."; + leaf name { + type group-name-type; + description + "Group name associated with this entry."; + } + leaf-list user-name { + type user-name-type; + description + "Each entry identifies the username of + a member of the group associated with + this entry."; + } + } + } + list rule-list { + key "name"; + ordered-by user; + description + "An ordered collection of access control rules."; + leaf name { + type string { + length "1..max"; + } + description + "Arbitrary name assigned to the rule-list."; + } + leaf-list group { + type union { + type matchall-string-type; + type group-name-type; + } + description + "List of administrative groups that will be + assigned the associated access rights + defined by the 'rule' list. + + The string '*' indicates that all groups apply to the + entry."; + } + list rule { + key "name"; + ordered-by user; + description + "One access control rule. + + Rules are processed in user-defined order until a match is + found. A rule matches if 'module-name', 'rule-type', and + 'access-operations' match the request. If a rule + matches, the 'action' leaf determines whether or not + access is granted."; + leaf name { + type string { + length "1..max"; + } + description + "Arbitrary name assigned to the rule."; + } + leaf module-name { + type union { + type matchall-string-type; + type string; + } + default "*"; + description + "Name of the module associated with this rule. + + This leaf matches if it has the value '*' or if the + object being accessed is defined in the module with the + specified module name."; + } + choice rule-type { + description + "This choice matches if all leafs present in the rule + match the request. If no leafs are present, the + choice matches all requests."; + case protocol-operation { + leaf rpc-name { + type union { + type matchall-string-type; + type string; + } + description + "This leaf matches if it has the value '*' or if + its value equals the requested protocol operation + name."; + } + } + case notification { + leaf notification-name { + type union { + type matchall-string-type; + type string; + } + description + "This leaf matches if it has the value '*' or if its + value equals the requested notification name."; + } + } + case data-node { + leaf path { + type node-instance-identifier; + mandatory true; + description + "Data node instance-identifier associated with the + data node, action, or notification controlled by + this rule. + + Configuration data or state data + instance-identifiers start with a top-level + data node. A complete instance-identifier is + required for this type of path value. + + The special value '/' refers to all possible + datastore contents."; + } + } + } + leaf access-operations { + type union { + type matchall-string-type; + type access-operations-type; + } + default "*"; + description + "Access operations associated with this rule. + + This leaf matches if it has the value '*' or if the + bit corresponding to the requested operation is set."; + } + leaf action { + type action-type; + mandatory true; + description + "The access control action associated with the + rule. If a rule has been determined to match a + particular request, then this object is used + to determine whether to permit or deny the + request."; + } + leaf comment { + type string; + description + "A textual description of the access rule."; + } + } + } + } +} diff --git a/src/confd/yang/ietf-truststore@2023-12-28.yang b/src/confd/yang/ietf-truststore@2023-12-28.yang new file mode 100644 index 00000000..f1dfb796 --- /dev/null +++ b/src/confd/yang/ietf-truststore@2023-12-28.yang @@ -0,0 +1,359 @@ +module ietf-truststore { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-truststore"; + prefix ts; + + 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"; + } + + organization + "IETF NETCONF (Network Configuration) Working Group"; + contact + "WG Web : https://datatracker.ietf.org/wg/netconf + WG List : NETCONF WG list + Author : Kent Watsen "; + description + "This module defines a 'truststore' to centralize management + of trust anchors including certificates and public keys. + + Copyright (c) 2023 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 BBBB + (https://www.rfc-editor.org/info/rfcBBBB); 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 2023-12-28 { + description + "Initial version"; + reference + "RFC BBBB: A YANG Data Model for a Truststore"; + } + + feature central-truststore-supported { + description + "The 'central-truststore-supported' feature indicates that + the server supports the truststore (i.e., implements the + 'ietf-truststore' module)."; + } + + feature inline-definitions-supported { + description + "The 'inline-definitions-supported' feature indicates that + the server supports locally-defined trust anchors."; + } + + feature certificates { + description + "The 'certificates' feature indicates that the server + implements the /truststore/certificate-bags subtree."; + } + + feature public-keys { + description + "The 'public-keys' feature indicates that the server + implements the /truststore/public-key-bags subtree."; + } + + typedef certificate-bag-ref { + type leafref { + path "/ts:truststore/ts:certificate-bags/ts:certificate-bag/ts:name"; + } + description + "This typedef defines a reference to a certificate bag + in the central truststore."; + } + + typedef certificate-ref { + type leafref { + path "/ts:truststore/ts:certificate-bags/ts:certificate-bag[ts:name = current()/../certificate-bag]/ts:certificate/ts:name"; + } + description + "This typedef defines a reference to a specific certificate + in a certificate bag in the central truststore. This typedef + requires that there exist a sibling 'leaf' node called + 'certificate-bag' that SHOULD have the typedef + 'certificate-bag-ref'."; + } + + typedef public-key-bag-ref { + type leafref { + path "/ts:truststore/ts:public-key-bags/ts:public-key-bag/ts:name"; + } + description + "This typedef defines a reference to a public key bag + in the central truststore."; + } + + typedef public-key-ref { + type leafref { + path "/ts:truststore/ts:public-key-bags/ts:public-key-bag[ts:name = current()/../public-key-bag]/ts:public-key/ts:name"; + } + description + "This typedef defines a reference to a specific public key + in a public key bag in the truststore. This typedef + requires that there exist a sibling 'leaf' node called + 'public-key-bag' that SHOULD have the typedef + 'public-key-bag-ref'."; + } + + grouping certificate-ref-grouping { + description + "Grouping for the reference to a certificate in a + certificate-bag in the central truststore."; + leaf certificate-bag { + nacm:default-deny-write; + if-feature "central-truststore-supported"; + if-feature "certificates"; + type ts:certificate-bag-ref; + must "../certificate"; + description + "Reference to a certificate-bag in the truststore."; + } + leaf certificate { + nacm:default-deny-write; + type ts:certificate-ref; + must "../certificate-bag"; + description + "Reference to a specific certificate in the + referenced certificate-bag."; + } + } + + grouping public-key-ref-grouping { + description + "Grouping for the reference to a public key in a + public-key-bag in the central truststore."; + leaf public-key-bag { + nacm:default-deny-write; + if-feature "central-truststore-supported"; + if-feature "public-keys"; + type ts:public-key-bag-ref; + description + "Reference of a public key bag in the truststore inlucding + the certificate to authenticate the TLS client."; + } + leaf public-key { + nacm:default-deny-write; + type ts:public-key-ref; + description + "Reference to a specific public key in the + referenced public-key-bag."; + } + } + + grouping inline-or-truststore-certs-grouping { + description + "A grouping for the configuration of a list of certificates. + The list of certificate may be defined inline or as a + reference to a certificate bag in the central truststore. + + Servers that do not define the 'central-truststore-supported' + feature SHOULD augment in custom 'case' statements enabling + references to alternate truststore locations."; + choice inline-or-truststore { + nacm:default-deny-write; + mandatory true; + description + "A choice between an inlined definition and a definition + that exists in the truststore."; + case inline { + if-feature "inline-definitions-supported"; + container inline-definition { + description + "A container for locally configured trust anchor + certificates."; + list certificate { + key "name"; + min-elements 1; + description + "A trust anchor certificate."; + leaf name { + type string; + description + "An arbitrary name for this certificate."; + } + uses ct:trust-anchor-cert-grouping { + refine "cert-data" { + mandatory true; + } + } + } + } + } + case central-truststore { + if-feature "central-truststore-supported"; + if-feature "certificates"; + leaf central-truststore-reference { + type ts:certificate-bag-ref; + description + "A reference to a certificate bag that exists in the + central truststore."; + } + } + } + } + + grouping inline-or-truststore-public-keys-grouping { + description + "A grouping that allows the public keys to be either + configured locally, within the using data model, or be a + reference to a public key bag stored in the truststore. + + Servers that do not define the 'central-truststore-supported' + feature SHOULD augment in custom 'case' statements enabling + references to alternate truststore locations."; + choice inline-or-truststore { + nacm:default-deny-write; + mandatory true; + description + "A choice between an inlined definition and a definition + that exists in the truststore."; + case inline { + if-feature "inline-definitions-supported"; + container inline-definition { + description + "A container to hold local public key definitions."; + list public-key { + key "name"; + description + "A public key definition."; + leaf name { + type string; + description + "An arbitrary name for this public key."; + } + uses ct:public-key-grouping; + } + } + } + case central-truststore { + if-feature "central-truststore-supported"; + if-feature "public-keys"; + leaf central-truststore-reference { + type ts:public-key-bag-ref; + description + "A reference to a bag of public keys that exists + in the central truststore."; + } + } + } + } + + grouping truststore-grouping { + description + "A grouping definition that enables use in other contexts. + Where used, implementations MUST augment new 'case' + statements into the various inline-or-truststore 'choice' + statements to supply leafrefs to the model-specific + location(s)."; + container certificate-bags { + nacm:default-deny-write; + if-feature "certificates"; + description + "A collection of certificate bags."; + list certificate-bag { + key "name"; + description + "A bag of certificates. Each bag of certificates SHOULD + be for a specific purpose. For instance, one bag could + be used to authenticate a specific set of servers, while + another could be used to authenticate a specific set of + clients."; + leaf name { + type string; + description + "An arbitrary name for this bag of certificates."; + } + leaf description { + type string; + description + "A description for this bag of certificates. The + intended purpose for the bag SHOULD be described."; + } + list certificate { + key "name"; + description + "A trust anchor certificate."; + leaf name { + type string; + description + "An arbitrary name for this certificate."; + } + uses ct:trust-anchor-cert-grouping { + refine "cert-data" { + mandatory true; + } + } + } + } + } + container public-key-bags { + nacm:default-deny-write; + if-feature "public-keys"; + description + "A collection of public key bags."; + list public-key-bag { + key "name"; + description + "A bag of public keys. Each bag of keys SHOULD be for + a specific purpose. For instance, one bag could be used + authenticate a specific set of servers, while another + could be used to authenticate a specific set of clients."; + leaf name { + type string; + description + "An arbitrary name for this bag of public keys."; + } + leaf description { + type string; + description + "A description for this bag public keys. The + intended purpose for the bag SHOULD be described."; + } + list public-key { + key "name"; + description + "A public key."; + leaf name { + type string; + description + "An arbitrary name for this public key."; + } + uses ct:public-key-grouping; + } + } + } + } + + container truststore { + nacm:default-deny-write; + if-feature "central-truststore-supported"; + description + "The truststore contains bags of certificates and + public keys."; + uses truststore-grouping; + } +} From bc33d8bc8aff70019a05f82dcb8f0064311d2ea3 Mon Sep 17 00:00:00 2001 From: Tobias Waldekranz Date: Wed, 8 Jan 2025 16:37:40 +0100 Subject: [PATCH 02/12] confd: Reactivate supported interface counter in-total-frames This was always supported, but was accendentally marked as not-supported. --- src/confd/yang/infix-ethernet-interface.yang | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/confd/yang/infix-ethernet-interface.yang b/src/confd/yang/infix-ethernet-interface.yang index ab4f2547..f663a91f 100644 --- a/src/confd/yang/infix-ethernet-interface.yang +++ b/src/confd/yang/infix-ethernet-interface.yang @@ -71,9 +71,6 @@ module infix-ethernet-interface { } /* Deviations for statistics */ - deviation "/if:interfaces/if:interface/eth:ethernet/eth:statistics/eth:frame/eth:in-total-frames" { - deviate not-supported; - } deviation "/if:interfaces/if:interface/eth:ethernet/eth:statistics/eth:frame/eth:out-error-mac-internal-frames" { deviate not-supported; } @@ -82,5 +79,5 @@ module infix-ethernet-interface { } deviation "/if:interfaces/if:interface/eth:ethernet/eth:statistics/eth:mac-control" { deviate not-supported; - } + } } From 385eab20163e2b21fd092e1072266ebfe963ee50 Mon Sep 17 00:00:00 2001 From: Tobias Waldekranz Date: Thu, 9 Jan 2025 15:58:29 +0100 Subject: [PATCH 03/12] statd: Ignore generated Python byte code files When interactively running, for exampe, yanger interactively from the source tree, we end up with compiled files in our working tree. Make sure to ignore these. --- src/statd/python/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/statd/python/.gitignore diff --git a/src/statd/python/.gitignore b/src/statd/python/.gitignore new file mode 100644 index 00000000..0d20b648 --- /dev/null +++ b/src/statd/python/.gitignore @@ -0,0 +1 @@ +*.pyc From c4a79766b7b5109fe2869490d6f8faa84a50da71 Mon Sep 17 00:00:00 2001 From: Tobias Waldekranz Date: Thu, 9 Jan 2025 16:21:13 +0100 Subject: [PATCH 04/12] statd: Make sure subpackages in python packages are distributed Rather than explicitly defining the sources, specify the package names and let poetry figure out the details. Otherwise, subpackages are not included, which we want to start using in yanger. --- src/statd/python/pyproject.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/statd/python/pyproject.toml b/src/statd/python/pyproject.toml index 5dc18f68..d5162e70 100644 --- a/src/statd/python/pyproject.toml +++ b/src/statd/python/pyproject.toml @@ -4,9 +4,9 @@ version = "1.0" description = "Linux to infix-YANG" license = "MIT" packages = [ - { include = "yanger/*.py" }, - { include = "cli_pretty/*.py" }, - { include = "ospf_status/*.py" } + { include = "yanger" }, + { include = "cli_pretty" }, + { include = "ospf_status" } ] authors = [ "KernelKit developers" From dadf0e2d1631e705ae248796bd657c62c4c698ec Mon Sep 17 00:00:00 2001 From: Tobias Waldekranz Date: Thu, 9 Jan 2025 13:09:46 +0100 Subject: [PATCH 05/12] yanger: Start the modularization process with ietf-system The yanger source grown significantly, code is disorganized, the namespace is all over the place, etc. Take a stab at remedying the situation by splitting out the individual YANG models in separate Python modules, starting with ietf-system. --- src/statd/python/pyproject.toml | 4 +- src/statd/python/yanger/__init__.py | 4 - src/statd/python/yanger/__main__.py | 3 + src/statd/python/yanger/common.py | 27 ++ src/statd/python/yanger/host.py | 133 +++++++++ src/statd/python/yanger/ietf_system.py | 139 +++++++++ src/statd/python/yanger/yanger | 5 + src/statd/python/yanger/yanger.py | 270 +++++------------- test/case/cli/sysrepo-emulator.sh | 2 +- .../chronyc_-c_sources} | 0 .../fw_printenv_BOOT_ORDER} | 0 .../rauc-installation-status} | 0 ...uc_status_--detailed_--output-format=json} | 0 13 files changed, 383 insertions(+), 204 deletions(-) create mode 100644 src/statd/python/yanger/__main__.py create mode 100644 src/statd/python/yanger/common.py create mode 100644 src/statd/python/yanger/host.py create mode 100644 src/statd/python/yanger/ietf_system.py create mode 100755 src/statd/python/yanger/yanger mode change 100755 => 100644 src/statd/python/yanger/yanger.py rename test/case/cli/system-output/{chronyc-sources.txt => run/chronyc_-c_sources} (100%) rename test/case/cli/system-output/{boot-order.txt => run/fw_printenv_BOOT_ORDER} (100%) rename test/case/cli/system-output/{rauc-installer-status.json => run/rauc-installation-status} (100%) rename test/case/cli/system-output/{rauc-status.json => run/rauc_status_--detailed_--output-format=json} (100%) diff --git a/src/statd/python/pyproject.toml b/src/statd/python/pyproject.toml index d5162e70..8f33838a 100644 --- a/src/statd/python/pyproject.toml +++ b/src/statd/python/pyproject.toml @@ -18,6 +18,6 @@ build-backend = "poetry.core.masonry.api" [tool.poetry.scripts] -yanger = "yanger:main" +yanger = "yanger.__main__:main" cli-pretty = "cli_pretty:main" -ospf-status = "ospf_status:main" \ No newline at end of file +ospf-status = "ospf_status:main" diff --git a/src/statd/python/yanger/__init__.py b/src/statd/python/yanger/__init__.py index 3ab9057f..e69de29b 100644 --- a/src/statd/python/yanger/__init__.py +++ b/src/statd/python/yanger/__init__.py @@ -1,4 +0,0 @@ -from .yanger import main - -if __name__ == "__main__": - main() diff --git a/src/statd/python/yanger/__main__.py b/src/statd/python/yanger/__main__.py new file mode 100644 index 00000000..bc9fc135 --- /dev/null +++ b/src/statd/python/yanger/__main__.py @@ -0,0 +1,3 @@ +from .yanger import main + +main() diff --git a/src/statd/python/yanger/common.py b/src/statd/python/yanger/common.py new file mode 100644 index 00000000..34f59742 --- /dev/null +++ b/src/statd/python/yanger/common.py @@ -0,0 +1,27 @@ +LOG = None + +def lookup(obj, *keys): + """This function returns a value from a nested json object""" + curr = obj + for key in keys: + if isinstance(curr, dict) and key in curr: + curr = curr[key] + else: + return None + return curr + + +def insert(obj, *path_and_value): + """"This function inserts a value into a nested json object""" + if len(path_and_value) < 2: + raise ValueError("Error: insert() takes at least two args") + + *path, value = path_and_value + + curr = obj + for key in path[:-1]: + if key not in curr or not isinstance(curr[key], dict): + curr[key] = {} + curr = curr[key] + + curr[path[-1]] = value diff --git a/src/statd/python/yanger/host.py b/src/statd/python/yanger/host.py new file mode 100644 index 00000000..040851fc --- /dev/null +++ b/src/statd/python/yanger/host.py @@ -0,0 +1,133 @@ +import abc +import datetime +import json +import os +import subprocess + +from . import common + +HOST = None + +class Host(abc.ABC): + """Host system API""" + + @abc.abstractmethod + def now(self): + """Get the current time as a `datetime`""" + pass + + @abc.abstractmethod + def run(self, cmd, default=None, log=True): + """Get stdout of cmd + + Run cmd, provided as an argv, and return the output it + produces. On error, return the default value if provided, + otherwise raise an exception. + + """ + pass + + def run_multiline(self, cmd, default=None): + """Get lines of stdout of cmd""" + try: + txt = self.run(cmd, log=(default is None)) + return txt.splitlines() + except: + if default is not None: + return default + raise + + def run_json(self, cmd, default=None): + """Get JSON object from stdout of cmd""" + try: + txt = self.run(cmd, log=(default is None)) + return json.loads(txt) + except: + if default is not None: + return default + raise + + @abc.abstractmethod + def read(self, path): + """Get the contents of path + + Returns `None` if the file is not readable for any reason. + + """ + pass + + def read_json(self, path, default=None): + """Get JSON object from path """ + try: + txt = self.read(path) + return json.loads(txt) + except: + if default is not None: + return default + raise + +class Localhost(Host): + def now(self): + return datetime.datetime.now(tz=datetime.timezone.utc) + + def run(self, cmd, default=None, log=True): + try: + result = subprocess.run(cmd, check=True, text=True, + stdin=subprocess.DEVNULL, + stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL) + return result.stdout + except subprocess.CalledProcessError as err: + if default is not None: + return default + + if log: + common.LOG.error(f"Failed to run {err}") + raise + + def read(self, path): + try: + with open(path, 'r') as f: + data = f.read().strip() + return data + except FileNotFoundError: + # This is considered OK + pass + except IOError: + common.LOG.error(f"Failed to read \"{path}\"") + + return None + +class Testhost(Host): + def __init__(self, basedir): + self.basedir = basedir + + def now(self): + return datetime.datetime(2023, 1, 1, 12, 0, 0, tzinfo=datetime.timezone.utc) + + def run(self, cmd, default=None, log=True): + slug = "_".join(cmd).replace("/", "+").replace(" ", "-") + path = os.path.join(self.basedir, "run", slug) + + try: + with open(path, 'r') as f: + return f.read() + except: + if default is not None: + return default + + if log: + common.LOG.error(f"No recording found for run \"{path}\"") + raise + + def read(self, path): + path = os.path.join(self.basedir, "rootfs", path[1:]) + try: + with open(path, 'r') as f: + return f.read() + except FileNotFoundError: + # This is considered OK + pass + except: + common.LOG.error(f"No recording found for file \"{path}\"") + raise diff --git a/src/statd/python/yanger/ietf_system.py b/src/statd/python/yanger/ietf_system.py new file mode 100644 index 00000000..2f424fc5 --- /dev/null +++ b/src/statd/python/yanger/ietf_system.py @@ -0,0 +1,139 @@ +import subprocess + +from .common import insert +from .host import HOST + +def uboot_get_boot_order(): + data = HOST.run_multiline("fw_printenv BOOT_ORDER".split(), []) + for line in data: + if "BOOT_ORDER" in line: + return line.strip().split("=")[1].split() + + raise Exception + +def grub_get_boot_order(): + data = HOST.run_multiline("grub-editenv /mnt/aux/grub/grubenv list".split(), []) + for line in data: + if "ORDER" in line: + return line.split("=")[1].strip().split() + + raise Exception + +def get_boot_order(): + order = None + try: + order = uboot_get_boot_order() + except: + pass + try: + if order is None: + order = grub_get_boot_order() + except: + pass + + return order + +def add_ntp(out): + data = HOST.run_multiline(["chronyc", "-c", "sources"], []) + source = [] + state_mode_map = { + "^": "server", + "=": "peer", + "#": "local-clock" + } + source_state_map = { + "*": "selected", + "+": "candidate", + "-": "outlier", + "?": "unusable", + "x": "falseticker", + "~": "unstable" + } + for line in data: + src = {} + line = line.split(',') + src["address"] = line[2] + src["mode"] = state_mode_map[line[0]] + src["state"] = source_state_map[line[1]] + src["stratum"] = int(line[3]) + src["poll"] = int(line[4]) + source.append(src) + + insert(out, "infix-system:ntp", "sources", "source", source) + +def add_software_slots(out, data): + slots = [] + for slot in data["slots"]: + for key, value in slot.items(): + new = {} + new["name"] = key + new["bootname"] = slot[key].get("bootname") + new["class"] = slot[key].get("class") + new["state"] = slot[key].get("state") + new["bundle"] = {} + slot_status=value.get("slot_status", {}) + if slot_status.get("bundle", {}).get("compatible"): + new["bundle"]["compatible"] = slot_status.get("bundle", {}).get("compatible") + if slot_status.get("bundle", {}).get("version"): + new["bundle"]["version"] = slot_status.get("bundle", {}).get("version") + if slot_status.get("checksum", {}).get("size"): + new["size"] = str(slot_status.get("checksum", {}).get("size")) + if slot_status.get("checksum", {}).get("sha256"): + new["sha256"] = slot_status.get("checksum", {}).get("sha256") + + new["installed"] = {} + if slot_status.get("installed", {}).get("timestamp"): + new["installed"]["datetime"] = slot_status.get("installed", {}).get("timestamp") + + if slot_status.get("installed", {}).get("count"): + new["installed"]["count"] = slot_status.get("installed", {}).get("count") + + new["activated"] = {} + if slot_status.get("activated", {}).get("timestamp"): + new["activated"]["datetime"] = slot_status.get("activated", {}).get("timestamp") + + if slot_status.get("activated", {}).get("count"): + new["activated"]["count"] = slot_status.get("activated", {}).get("count") + slots.append(new) + out["slot"] = slots + +def add_software(out): + software = {} + try: + data = HOST.run_json(["rauc", "status", "--detailed", "--output-format=json"]) + software["compatible"] = data["compatible"] + software["variant"] = data["variant"] + software["booted"] = data["booted"] + boot_order = get_boot_order() + if not boot_order is None: + software["boot-order"] = boot_order + add_software_slots(software, data) + except subprocess.CalledProcessError: + pass # Maybe an upgrade i progress, then rauc does not respond + + installer_status = HOST.run_json(["rauc-installation-status"]) + installer = {} + if installer_status.get("operation"): + installer["operation"] = installer_status["operation"] + if "progress" in installer_status: + progress = {} + + if installer_status["progress"].get("percentage"): + progress["percentage"] = int(installer_status["progress"]["percentage"]) + if installer_status["progress"].get("message"): + progress["message"] = installer_status["progress"]["message"] + installer["progress"] = progress + software["installer"] = installer + + insert(out, "infix-system:software", software) + +def operational(): + out = { + "ietf-system:system-state": { + } + } + out_state = out["ietf-system:system-state"] + + add_software(out_state) + add_ntp(out_state) + return out diff --git a/src/statd/python/yanger/yanger b/src/statd/python/yanger/yanger new file mode 100755 index 00000000..e4f3da36 --- /dev/null +++ b/src/statd/python/yanger/yanger @@ -0,0 +1,5 @@ +#!/bin/sh + +exec env PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=$(readlink -f $(dirname "$0")/../) \ + python3 -m yanger "$@" + diff --git a/src/statd/python/yanger/yanger.py b/src/statd/python/yanger/yanger.py old mode 100755 new mode 100644 index 62fdc125..9d1aea05 --- a/src/statd/python/yanger/yanger.py +++ b/src/statd/python/yanger/yanger.py @@ -9,6 +9,9 @@ import argparse from re import match from datetime import datetime, timedelta, timezone +from . import common +from . import host + TESTPATH = "" logger = None @@ -17,82 +20,6 @@ def datetime_now(): return datetime(2023, 1, 1, 12, 0, 0, tzinfo=timezone.utc) return datetime.now(timezone.utc) -def uboot_get_boot_order(): - data = run_cmd("fw_printenv BOOT_ORDER".split(), "boot-order.txt") - for line in data: - if "BOOT_ORDER" in line: - return line.strip().split("=")[1].split() - - raise Exception - -def grub_get_boot_order(): - data = run_cmd("grub-editenv /mnt/aux/grub/grubenv list".split(), None) # No need for testfile, will be returned from uboot - - for line in data: - if "ORDER" in line: - return line.split("=")[1].strip().split() - - raise Exception - -def json_get_yang_type(iface_in): - if iface_in['link_type'] == "loopback": - return "infix-if-type:loopback" - - if iface_in['link_type'] in ("gre", "gre6"): - return "infix-if-type:gre" - - if iface_in['link_type'] != "ether": - return "infix-if-type:other" - - if 'parentbus' in iface_in and iface_in['parentbus'] == "virtio": - return "infix-if-type:etherlike" - - if 'linkinfo' not in iface_in: - return "infix-if-type:ethernet" - - if 'info_kind' not in iface_in['linkinfo']: - return "infix-if-type:ethernet" - - if iface_in['linkinfo']['info_kind'] == "veth": - return "infix-if-type:veth" - - if iface_in['linkinfo']['info_kind'] in ("gretap", "ip6gretap"): - return "infix-if-type:gretap" - - if iface_in['linkinfo']['info_kind'] == "vlan": - return "infix-if-type:vlan" - - if iface_in['linkinfo']['info_kind'] == "bridge": - return "infix-if-type:bridge" - - if iface_in['linkinfo']['info_kind'] == "dsa": - return "infix-if-type:ethernet" - - if iface_in['linkinfo']['info_kind'] == "dummy": - return "infix-if-type:dummy" - - # Fallback - return "infix-if-type:ethernet" - - -def json_get_yang_origin(addr): - """Translate kernel IP address origin to YANG""" - xlate = { - "kernel_ll": "link-layer", - "kernel_ra": "link-layer", - "static": "static", - "dhcp": "dhcp", - "random": "random", - } - proto = addr['protocol'] - - if proto in ("kernel_ll", "kernel_ra"): - if "stable-privacy" in addr: - return "random" - - return xlate.get(proto, "other") - - def get_proc_value(procfile): """Return contents of /proc file, or None""" try: @@ -176,6 +103,66 @@ def run_json_cmd(cmd, testfile, default=None, check=True): raise return data +def json_get_yang_type(iface_in): + if iface_in['link_type'] == "loopback": + return "infix-if-type:loopback" + + if iface_in['link_type'] in ("gre", "gre6"): + return "infix-if-type:gre" + + if iface_in['link_type'] != "ether": + return "infix-if-type:other" + + if 'parentbus' in iface_in and iface_in['parentbus'] == "virtio": + return "infix-if-type:etherlike" + + if 'linkinfo' not in iface_in: + return "infix-if-type:ethernet" + + if 'info_kind' not in iface_in['linkinfo']: + return "infix-if-type:ethernet" + + if iface_in['linkinfo']['info_kind'] == "veth": + return "infix-if-type:veth" + + if iface_in['linkinfo']['info_kind'] in ("gretap", "ip6gretap"): + return "infix-if-type:gretap" + + if iface_in['linkinfo']['info_kind'] == "vlan": + return "infix-if-type:vlan" + + if iface_in['linkinfo']['info_kind'] == "bridge": + return "infix-if-type:bridge" + + if iface_in['linkinfo']['info_kind'] == "dsa": + return "infix-if-type:ethernet" + + if iface_in['linkinfo']['info_kind'] == "dummy": + return "infix-if-type:dummy" + + # Fallback + return "infix-if-type:ethernet" + + +def json_get_yang_origin(addr): + """Translate kernel IP address origin to YANG""" + xlate = { + "kernel_ll": "link-layer", + "kernel_ra": "link-layer", + "static": "static", + "dhcp": "dhcp", + "random": "random", + } + proto = addr['protocol'] + + if proto in ("kernel_ll", "kernel_ra"): + if "stable-privacy" in addr: + return "random" + + return xlate.get(proto, "other") + + + def iface_is_dsa(iface_in): """Check if interface is a DSA/intra-switch port""" @@ -1090,118 +1077,6 @@ def add_interface(ifname, yang_ifaces): add_container_ifaces(yang_ifaces) -def add_system_ntp(out): - data = run_cmd(["chronyc", "-c", "sources"], "chronyc-sources.txt", "") - source = [] - state_mode_map = { - "^": "server", - "=": "peer", - "#": "local-clock" - } - source_state_map = { - "*": "selected", - "+": "candidate", - "-": "outlier", - "?": "unusable", - "x": "falseticker", - "~": "unstable" - } - for line in data: - src = {} - line = line.split(',') - src["address"] = line[2] - src["mode"] = state_mode_map[line[0]] - src["state"] = source_state_map[line[1]] - src["stratum"] = int(line[3]) - src["poll"] = int(line[4]) - source.append(src) - - insert(out, "infix-system:ntp", "sources", "source", source) - -def add_system_software_slots(out, data): - slots = [] - for slot in data["slots"]: - for key, value in slot.items(): - new = {} - new["name"] = key - new["bootname"] = slot[key].get("bootname") - new["class"] = slot[key].get("class") - new["state"] = slot[key].get("state") - new["bundle"] = {} - slot_status=value.get("slot_status", {}) - if slot_status.get("bundle", {}).get("compatible"): - new["bundle"]["compatible"] = slot_status.get("bundle", {}).get("compatible") - if slot_status.get("bundle", {}).get("version"): - new["bundle"]["version"] = slot_status.get("bundle", {}).get("version") - if slot_status.get("checksum", {}).get("size"): - new["size"] = str(slot_status.get("checksum", {}).get("size")) - if slot_status.get("checksum", {}).get("sha256"): - new["sha256"] = slot_status.get("checksum", {}).get("sha256") - - new["installed"] = {} - if slot_status.get("installed", {}).get("timestamp"): - new["installed"]["datetime"] = slot_status.get("installed", {}).get("timestamp") - - if slot_status.get("installed", {}).get("count"): - new["installed"]["count"] = slot_status.get("installed", {}).get("count") - - new["activated"] = {} - if slot_status.get("activated", {}).get("timestamp"): - new["activated"]["datetime"] = slot_status.get("activated", {}).get("timestamp") - - if slot_status.get("activated", {}).get("count"): - new["activated"]["count"] = slot_status.get("activated", {}).get("count") - slots.append(new) - out["slot"] = slots - -def get_system_software_boot_order(): - order = None - try: - order = uboot_get_boot_order() - except: - pass - try: - if order is None: - order = grub_get_boot_order() - except: - pass - - return order - -def add_system_software(out): - software = {} - try: - data = run_json_cmd(["rauc", "status", "--detailed", "--output-format=json"], "rauc-status.json") - software["compatible"] = data["compatible"] - software["variant"] = data["variant"] - software["booted"] = data["booted"] - boot_order = get_system_software_boot_order() - if not boot_order is None: - software["boot-order"] = boot_order - add_system_software_slots(software, data) - except subprocess.CalledProcessError: - pass # Maybe an upgrade i progress, then rauc does not respond - - installer_status = run_json_cmd(["rauc-installation-status"], "rauc-installer-status.json") - installer = {} - if installer_status.get("operation"): - installer["operation"] = installer_status["operation"] - if "progress" in installer_status: - progress = {} - - if installer_status["progress"].get("percentage"): - progress["percentage"] = int(installer_status["progress"]["percentage"]) - if installer_status["progress"].get("message"): - progress["message"] = installer_status["progress"]["message"] - installer["progress"] = progress - software["installer"] = installer - - insert(out, "infix-system:software", software) - -def add_system(yang_data): - add_system_software(yang_data) - add_system_ntp(yang_data) - def main(): global TESTPATH global logger @@ -1212,10 +1087,6 @@ def main(): parser.add_argument("-t", "--test", default=None, help="Test data base path") args = parser.parse_args() - if args.test: - TESTPATH = args.test - else: - TESTPATH = "" # Set up syslog output for critical errors to aid debugging logger = logging.getLogger('yanger') @@ -1229,6 +1100,14 @@ def main(): log.setFormatter(fmt) logger.setLevel(logging.INFO) logger.addHandler(log) + common.LOG = logger + + if args.test: + TESTPATH = args.test + host.HOST = host.Testhost(args.test) + else: + TESTPATH = "" + host.HOST = host.Localhost() if args.model == 'ietf-interfaces': yang_data = { @@ -1283,11 +1162,8 @@ def main(): add_container(yang_data['infix-containers:containers']['container']) elif args.model == 'ietf-system': - yang_data = { - "ietf-system:system-state": { - } - } - add_system(yang_data['ietf-system:system-state']) + from . import ietf_system + yang_data = ietf_system.operational() else: logger.warning(f"Unsupported model {args.model}", file=sys.stderr) sys.exit(1) diff --git a/test/case/cli/sysrepo-emulator.sh b/test/case/cli/sysrepo-emulator.sh index 49933c4b..f846301d 100755 --- a/test/case/cli/sysrepo-emulator.sh +++ b/test/case/cli/sysrepo-emulator.sh @@ -3,7 +3,7 @@ SCRIPT_PATH="$(dirname "$(readlink -f "$0")")" ROOT_PATH="$SCRIPT_PATH/../../../" -YANGER_TOOL="$ROOT_PATH/src/statd/python/yanger/yanger.py" +YANGER_TOOL="$ROOT_PATH/src/statd/python/yanger/yanger" INTERFACES_OUTPUT_FILE="$(mktemp)" ROUTES_OUTPUT_FILE="$(mktemp)" diff --git a/test/case/cli/system-output/chronyc-sources.txt b/test/case/cli/system-output/run/chronyc_-c_sources similarity index 100% rename from test/case/cli/system-output/chronyc-sources.txt rename to test/case/cli/system-output/run/chronyc_-c_sources diff --git a/test/case/cli/system-output/boot-order.txt b/test/case/cli/system-output/run/fw_printenv_BOOT_ORDER similarity index 100% rename from test/case/cli/system-output/boot-order.txt rename to test/case/cli/system-output/run/fw_printenv_BOOT_ORDER diff --git a/test/case/cli/system-output/rauc-installer-status.json b/test/case/cli/system-output/run/rauc-installation-status similarity index 100% rename from test/case/cli/system-output/rauc-installer-status.json rename to test/case/cli/system-output/run/rauc-installation-status diff --git a/test/case/cli/system-output/rauc-status.json b/test/case/cli/system-output/run/rauc_status_--detailed_--output-format=json similarity index 100% rename from test/case/cli/system-output/rauc-status.json rename to test/case/cli/system-output/run/rauc_status_--detailed_--output-format=json From 28bf2d6c3cc6d9e42d2659b7a36085b74e5bba0b Mon Sep 17 00:00:00 2001 From: Tobias Waldekranz Date: Thu, 9 Jan 2025 13:48:15 +0100 Subject: [PATCH 06/12] yanger: Move infix-containers implementation to separate module --- src/statd/python/yanger/infix_containers.py | 76 +++++++++++++++++++ src/statd/python/yanger/yanger.py | 73 +----------------- .../podman_ps_-a_--format=json} | 0 3 files changed, 78 insertions(+), 71 deletions(-) create mode 100644 src/statd/python/yanger/infix_containers.py rename test/case/cli/system-output/{podman-ps.json => run/podman_ps_-a_--format=json} (100%) diff --git a/src/statd/python/yanger/infix_containers.py b/src/statd/python/yanger/infix_containers.py new file mode 100644 index 00000000..4289fb85 --- /dev/null +++ b/src/statd/python/yanger/infix_containers.py @@ -0,0 +1,76 @@ +from .common import LOG +from .host import HOST + +def podman_inspect(name): + """Call podman inspect {name}, return object at {path} or None.""" + cmd = ['podman', 'inspect', name] + try: + return HOST.run_json(cmd, default=[]) + except Exception as e: + LOG(f"Error running podman inspect: {e}") + return [] + +def podman_ps(): + """We list *all* containers, not just those in the configuraion.""" + return HOST.run_json("podman ps -a --format=json".split(), default=[]) + + +def network(ps, inspect): + net = {} + + # The 'podman ps' command lists ports even in host mode, but + # that's not applicable, so skip networks and port forwardings + networks = inspect.get("NetworkSettings", {}).get("Networks") + if networks and "host" in networks: + net = {"host": True} + else: + net = { + "interface": [{"name": net} for net in ps["Networks"]], + "publish": [] + } + + if (ps["State"] == "running") and ps["Ports"]: + for port in ps["Ports"]: + addr = "" + if port["host_ip"]: + addr = f"{port['host_ip']}:" + + pub = f"{addr}{port['host_port']}->{port['container_port']}/{port['protocol']}" + net["publish"].append(pub) + + return net + + +def container(ps): + out = { + "name": ps["Names"][0], + "id": ps["Id"], + "image": ps["Image"], + "image-id": ps["ImageID"], + "running": ps["State"] == "running", + "status": ps["Status"] + } + + # Bonus information, may not be available + if ps["Command"]: + out["command"] = " ".join(ps["Command"]) + + inspect = podman_inspect(out["name"]) + if inspect and isinstance(inspect, list) and len(inspect) > 0: + inspect = inspect[0] + else: + inspect = {} + + net = network(ps, inspect) + if net: + out["network"] = net + + return out + + +def operational(): + return { + "infix-containers:containers": { + "container": [container(ps) for ps in podman_ps()] + } + } diff --git a/src/statd/python/yanger/yanger.py b/src/statd/python/yanger/yanger.py index 9d1aea05..7d233739 100644 --- a/src/statd/python/yanger/yanger.py +++ b/src/statd/python/yanger/yanger.py @@ -552,70 +552,6 @@ def get_bridge_port_stp_state(ifname): return None -def container_inspect(name): - """Call podman inspect {name}, return object at {path} or None.""" - cmd = ['podman', 'inspect', name] - try: - return run_json_cmd(cmd, "", default=[]) - except Exception as e: - logging.error(f"Error running podman inspect: {e}") - return [] - - -def add_container(containers): - """We list *all* containers, not just those in the configuraion.""" - cmd = ['podman', 'ps', '-a', '--format=json'] - - raw = run_json_cmd(cmd, "", default=[]) - for entry in raw: - running = entry["State"] == "running" - - container = { - "name": entry["Names"][0], - "id": entry["Id"], - "image": entry["Image"], - "image-id": entry["ImageID"], - "running": running, - "status": entry["Status"] - } - - # Bonus information, may not be available - if entry["Command"]: - container["command"] = " ".join(entry["Command"]) - - # The 'podman ps' command lists ports even in host mode, but - # that's not applicable, so skip networks and port forwardings - cont = container_inspect(container["name"]) - if cont and isinstance(cont, list) and len(cont) > 0: - cont = cont[0] - else: - cont = {} - - networks = cont.get("NetworkSettings", {}).get("Networks") - if networks and "host" in networks: - container["network"] = {"host": True} - else: - container["network"] = { - "interface": [], - "publish": [] - } - - if entry["Networks"]: - for net in entry["Networks"]: - container["network"]["interface"].append({"name": net}) - - if running and entry["Ports"]: - for port in entry["Ports"]: - addr = "" - if port["host_ip"]: - addr = f"{port['host_ip']}:" - - pub = f"{addr}{port['host_port']}->{port['container_port']}/{port['protocol']}" - container["network"]["publish"].append(pub) - - containers.append(container) - - def get_brport_multicast(ifname): """Check if multicast snooping is enabled on bridge, default: nope""" data = run_json_cmd(['mctl', 'show', 'igmp', 'json'], "igmp-status.json", @@ -1154,13 +1090,8 @@ def main(): add_hardware(yang_data["ietf-hardware:hardware"]) elif args.model == 'infix-containers': - yang_data = { - "infix-containers:containers": { - "container": [] - } - } - add_container(yang_data['infix-containers:containers']['container']) - + from . import infix_containers + yang_data = infix_containers.operational() elif args.model == 'ietf-system': from . import ietf_system yang_data = ietf_system.operational() diff --git a/test/case/cli/system-output/podman-ps.json b/test/case/cli/system-output/run/podman_ps_-a_--format=json similarity index 100% rename from test/case/cli/system-output/podman-ps.json rename to test/case/cli/system-output/run/podman_ps_-a_--format=json From 8812ae70523f7b196f998892e2c7360a02f8e0ca Mon Sep 17 00:00:00 2001 From: Tobias Waldekranz Date: Thu, 9 Jan 2025 14:31:09 +0100 Subject: [PATCH 07/12] yanger: Move ietf-hardware implementation to separate module --- src/statd/python/yanger/ietf_hardware.py | 90 +++++++++++++++++++ src/statd/python/yanger/yanger.py | 81 +---------------- .../cli/system-output/rootfs/run/system.json | 1 + 3 files changed, 93 insertions(+), 79 deletions(-) create mode 100644 src/statd/python/yanger/ietf_hardware.py create mode 100644 test/case/cli/system-output/rootfs/run/system.json diff --git a/src/statd/python/yanger/ietf_hardware.py b/src/statd/python/yanger/ietf_hardware.py new file mode 100644 index 00000000..70a4aa29 --- /dev/null +++ b/src/statd/python/yanger/ietf_hardware.py @@ -0,0 +1,90 @@ +import datetime +import os + +from .common import insert +from .host import HOST + + +def vpd_vendor_extensions(data): + vendor_extensions = [] + for ext in data: + vendor_extension = {} + vendor_extension["iana-enterprise-number"] = ext[0] + vendor_extension["extension-data"] = ext[1] + vendor_extensions.append(vendor_extension) + return vendor_extensions + + +def vpd_component(vpd): + component = {} + component["name"] = vpd.get("board") + component["infix-hardware:vpd-data"] = {} + + if vpd.get("data"): + component["class"] = "infix-hardware:vpd" + if vpd["data"].get("manufacture-date"): + mfgdate = datetime.datetime.strptime(vpd["data"]["manufacture-date"], + "%m/%d/%Y %H:%M:%S") + component["mfg-date"] = mfgdate.strftime("%Y-%m-%dT%H:%M:%SZ") + if vpd["data"].get("manufacter"): + component["mfg-name"] = vpd["data"]["manufacturer"] + if vpd["data"].get("product-name"): + component["model-name"] = vpd["data"]["product-name"] + if vpd["data"].get("serial-number"): + component["serial-num"] = vpd["data"]["serial-number"] + + # Set VPD-data entrys + for k, v in vpd["data"].items(): + if vpd["data"].get(k): + if k != "vendor-extension": + component["infix-hardware:vpd-data"][k] = v + else: + vendor_extensions=vpd_vendor_extensions(v) + component["infix-hardware:vpd-data"]["infix-hardware:vendor-extension"] = vendor_extensions + return component + + +def vpd_components(systemjson): + return [vpd_component(vpd) for vpd in systemjson.get("vpd", {}).values()] + + +def usb_port_components(systemjson): + usb_ports = systemjson.get("usb-ports", []) + + ports=[] + names=[] + for usb_port in usb_ports: + port={} + if usb_port.get("path"): + if usb_port["name"] in names: + continue + + path = usb_port["path"] + if os.path.basename(path) == "authorized_default": + # TODO: Untestable. Should be done via the host API + if os.path.exists(path): + with open(path, "r") as f: + names.append(usb_port["name"]) + data = int(f.readline().strip()) + enabled = "unlocked" if data == 1 else "locked" + port["state"] = {} + port["state"]["admin-state"] = enabled + port["name"] = usb_port["name"] + port["class"] = "infix-hardware:usb" + port["state"]["oper-state"] = "enabled" + ports.append(port) + + return ports + + +def operational(): + systemjson = HOST.read_json("/run/system.json") + + return { + "ietf-hardware:hardware": { + "component": + vpd_components(systemjson) + + usb_port_components(systemjson) + + [], + }, + } diff --git a/src/statd/python/yanger/yanger.py b/src/statd/python/yanger/yanger.py index 7d233739..ab3c2aa0 100644 --- a/src/statd/python/yanger/yanger.py +++ b/src/statd/python/yanger/yanger.py @@ -175,79 +175,6 @@ def iface_is_dsa(iface_in): return True -def get_vpd_vendor_extensions(data): - vendor_extensions = [] - for ext in data: - vendor_extension = {} - vendor_extension["iana-enterprise-number"] = ext[0] - vendor_extension["extension-data"] = ext[1] - vendor_extensions.append(vendor_extension) - return vendor_extensions - - -def get_vpd_data(vpd): - component = {} - component["name"] = vpd.get("board") - component["infix-hardware:vpd-data"] = {} - - if vpd.get("data"): - component["class"] = "infix-hardware:vpd" - if vpd["data"].get("manufacture-date"): - component["mfg-date"] = datetime.strptime(vpd["data"]["manufacture-date"],"%m/%d/%Y %H:%M:%S").strftime("%Y-%m-%dT%H:%M:%SZ") - if vpd["data"].get("manufacter"): - component["mfg-name"] = vpd["data"]["manufacturer"] - if vpd["data"].get("product-name"): - component["model-name"] = vpd["data"]["product-name"] - if vpd["data"].get("serial-number"): - component["serial-num"] = vpd["data"]["serial-number"] - - # Set VPD-data entrys - for k, v in vpd["data"].items(): - if vpd["data"].get(k): - if k != "vendor-extension": - component["infix-hardware:vpd-data"][k] = v - else: - vendor_extensions=get_vpd_vendor_extensions(v) - component["infix-hardware:vpd-data"]["infix-hardware:vendor-extension"] = vendor_extensions - return component - -def get_usb_ports(usb_ports): - ports=[] - names=[] - for usb_port in usb_ports: - port={} - if usb_port.get("path"): - if usb_port["name"] in names: - continue - - path = usb_port["path"] - if os.path.basename(path) == "authorized_default": - if os.path.exists(path): - with open(path, "r") as f: - names.append(usb_port["name"]) - data = int(f.readline().strip()) - enabled = "unlocked" if data == 1 else "locked" - port["state"] = {} - port["state"]["admin-state"] = enabled - port["name"] = usb_port["name"] - port["class"] = "infix-hardware:usb" - port["state"]["oper-state"] = "enabled" - ports.append(port) - - return ports - - -def add_hardware(hw_out): - data = run_json_cmd(['cat', "/run/system.json"], "system.json") - components = [] - for _, vpd in data.get("vpd").items(): - component = get_vpd_data(vpd) - components.append(component) - if data.get("usb-ports", None): - components.extend(get_usb_ports(data["usb-ports"])) - insert(hw_out, "component", components) - - def uptime2datetime(uptime): """ Convert uptime to YANG format (YYYY-MM-DDTHH:MM:SS+00:00) @@ -1083,12 +1010,8 @@ def main(): add_ospf(yang_data['ietf-routing:routing']['control-plane-protocols']) elif args.model == 'ietf-hardware': - yang_data = { - "ietf-hardware:hardware": { - } - } - add_hardware(yang_data["ietf-hardware:hardware"]) - + from . import ietf_hardware + yang_data = ietf_hardware.operational() elif args.model == 'infix-containers': from . import infix_containers yang_data = infix_containers.operational() diff --git a/test/case/cli/system-output/rootfs/run/system.json b/test/case/cli/system-output/rootfs/run/system.json new file mode 100644 index 00000000..b95bd5af --- /dev/null +++ b/test/case/cli/system-output/rootfs/run/system.json @@ -0,0 +1 @@ +{"vendor": "QEMU", "product-name": "VM", "part-number": null, "serial-number": null, "mac-address": "02:00:00:00:00:00", "factory-password-hash": "$5$mI/zpOAqZYKLC2WU$i7iPzZiIjOjrBF3NyftS9CCq8dfYwHwrmUK097Jca9A", "vpd": {"product": {"board": "product", "available": false, "trusted": true, "data": {}}}, "usb-ports": [{"name": "USB", "path": "/sys/bus/usb/devices/usb1/authorized"}, {"name": "USB", "path": "/sys/bus/usb/devices/usb1/authorized_default"}, {"name": "USB2", "path": "/sys/bus/usb/devices/usb2/authorized"}, {"name": "USB2", "path": "/sys/bus/usb/devices/usb2/authorized_default"}]} \ No newline at end of file From a0e4e813dd3ca2c26a9dd1d6feb88c9db2c2461e Mon Sep 17 00:00:00 2001 From: Tobias Waldekranz Date: Thu, 9 Jan 2025 14:54:36 +0100 Subject: [PATCH 08/12] yanger: Move ietf-ospf implementation to separate module --- src/statd/python/yanger/ietf_ospf.py | 156 ++++++++++++++++++ src/statd/python/yanger/yanger.py | 152 +---------------- .../run/+usr+libexec+statd+ospf-status | 1 + .../run/vtysh_-c_show-ip-ospf-route-json | 1 + 4 files changed, 160 insertions(+), 150 deletions(-) create mode 100644 src/statd/python/yanger/ietf_ospf.py create mode 100644 test/case/cli/system-output/run/+usr+libexec+statd+ospf-status create mode 100644 test/case/cli/system-output/run/vtysh_-c_show-ip-ospf-route-json diff --git a/src/statd/python/yanger/ietf_ospf.py b/src/statd/python/yanger/ietf_ospf.py new file mode 100644 index 00000000..73aae734 --- /dev/null +++ b/src/statd/python/yanger/ietf_ospf.py @@ -0,0 +1,156 @@ +from .common import insert +from .host import HOST + + +def frr_to_ietf_neighbor_state(state): + """Fetch OSPF neighbor state from Frr""" + state = state.split("/")[0] + if state == "TwoWay": + return "2-way" + return state.lower() + + +def add_routes(ospf): + """Fetch OSPF routes from Frr""" + cmd = ['vtysh', '-c', "show ip ospf route json"] + data = HOST.run_json(cmd, default=[]) + if data == []: + return # No OSPF routes available + + routes = [] + for prefix, info in data.items(): + if prefix.find("/") == -1: # Ignore router IDs + continue + + route = {} + route["prefix"] = prefix + + nexthops = [] + routetype = info["routeType"].split(" ") + + if len(routetype) > 1: + if routetype[1] == "E1": + route["route-type"] = "external-1" + elif routetype[1] == "E2": + route["route-type"] = "external-2" + elif routetype[1] == "IA": + route["route-type"] = "inter-area" + elif routetype[0] == "N": + route["route-type"] = "intra-area" + + for hop in info["nexthops"]: + nexthop = {} + if hop["ip"] != " ": + nexthop["next-hop"] = hop["ip"] + else: + nexthop["outgoing-interface"] = hop["directlyAttachedTo"] + nexthops.append(nexthop) + + route["next-hops"] = {} + route["next-hops"]["next-hop"] = nexthops + routes.append(route) + + insert(ospf, "ietf-ospf:local-rib", "ietf-ospf:route", routes) + + +def add_areas(control_protocols): + """Populate OSPF status""" + cmd = ['/usr/libexec/statd/ospf-status'] + data = HOST.run_json(cmd, default={}) + if data == {}: + return # No OSPF data available + + control_protocol = {} + control_protocol["type"] = "infix-routing:ospfv2" + control_protocol["name"] = "default" + control_protocol["ietf-ospf:ospf"] = {} + control_protocol["ietf-ospf:ospf"]["ietf-ospf:areas"] = {} + + + control_protocol["ietf-ospf:ospf"]["ietf-ospf:router-id"] = data.get("routerId") + control_protocol["ietf-ospf:ospf"]["ietf-ospf:address-family"] = "ipv4" + areas = [] + + for area_id, values in data.get("areas", {}).items(): + area = {} + area["ietf-ospf:area-id"] = area_id + area["ietf-ospf:interfaces"] = {} + if values.get("area-type"): + area["ietf-ospf:area-type"] = values["area-type"] + interfaces = [] + for iface in values.get("interfaces", {}): + interface = {} + interface["ietf-ospf:neighbors"] = {} + interface["name"] = iface["name"] + + if iface.get("drId"): + interface["dr-router-id"] = iface["drId"] + if iface.get("drAddress"): + interface["dr-ip-addr"] = iface["drAddress"] + if iface.get("bdrId"): + interface["bdr-router-id"] = iface["bdrId"] + if iface.get("bdrAddress"): + interface["bdr-ip-addr"] = iface["bdrAddress"] + + if iface.get("timerPassiveIface"): + interface["passive"] = True + else: + interface["passive"] = False + + interface["enabled"] = iface["ospfEnabled"] + if iface["networkType"] == "POINTOPOINT": + interface["interface-type"] = "point-to-point" + if iface["networkType"] == "BROADCAST": + interface["interface-type"] = "broadcast" + + if iface.get("state"): + # Wev've never seen "DependUpon", and has no entry in + # the YANG model, but is listed before down in Frr + xlate = { + "DependUpon": "down", + "Down": "down", + "Waiting": "waiting", + "Loopback": "loopback", + "Point-To-Point": "point-to-point", + "DROther": "dr-other", + "Backup": "bdr", + "DR": "dr" + } + val = xlate.get(iface["state"], "unknown") + interface["state"] = val + + neighbors = [] + for neigh in iface["neighbors"]: + neighbor = {} + neighbor["neighbor-router-id"] = neigh["neighborIp"] + neighbor["address"] = neigh["ifaceAddress"] + neighbor["dead-timer"] = neigh["routerDeadIntervalTimerDueMsec"] + neighbor["state"] = frr_to_ietf_neighbor_state(neigh["nbrState"]) + if neigh.get("routerDesignatedId"): + neighbor["dr-router-id"] = neigh["routerDesignatedId"] + if neigh.get("routerDesignatedBackupId"): + neighbor["bdr-router-id"] = neigh["routerDesignatedBackupId"] + neighbors.append(neighbor) + + interface["ietf-ospf:neighbors"] = {} + interface["ietf-ospf:neighbors"]["ietf-ospf:neighbor"] = neighbors + interfaces.append(interface) + + area["ietf-ospf:interfaces"]["ietf-ospf:interface"] = interfaces + areas.append(area) + + add_routes(control_protocol["ietf-ospf:ospf"]) + control_protocol["ietf-ospf:ospf"]["ietf-ospf:areas"]["ietf-ospf:area"] = areas + insert(control_protocols, "control-plane-protocol", [control_protocol]) + + +def operational(): + out = { + "ietf-routing:routing": { + "control-plane-protocols": { + } + } + } + + add_areas(out['ietf-routing:routing']['control-plane-protocols']) + return out diff --git a/src/statd/python/yanger/yanger.py b/src/statd/python/yanger/yanger.py index ab3c2aa0..e8319632 100644 --- a/src/statd/python/yanger/yanger.py +++ b/src/statd/python/yanger/yanger.py @@ -307,148 +307,6 @@ def add_ipv6_route(routes): get_routes(routes, "ipv6", data) -def frr_to_ietf_neighbor_state(state): - """Fetch OSPF neighbor state from Frr""" - state = state.split("/")[0] - if state == "TwoWay": - return "2-way" - return state.lower() - - -def add_ospf_routes(ospf): - """Fetch OSPF routes from Frr""" - cmd = ['vtysh', '-c', "show ip ospf rout json"] - data = run_json_cmd(cmd, "", check=False, default=[]) - if data == []: - return # No OSPF routes available - - routes = [] - for prefix, info in data.items(): - if prefix.find("/") == -1: # Ignore router IDs - continue - - route = {} - route["prefix"] = prefix - - nexthops = [] - routetype = info["routeType"].split(" ") - - if len(routetype) > 1: - if routetype[1] == "E1": - route["route-type"] = "external-1" - elif routetype[1] == "E2": - route["route-type"] = "external-2" - elif routetype[1] == "IA": - route["route-type"] = "inter-area" - elif routetype[0] == "N": - route["route-type"] = "intra-area" - - for hop in info["nexthops"]: - nexthop = {} - if hop["ip"] != " ": - nexthop["next-hop"] = hop["ip"] - else: - nexthop["outgoing-interface"] = hop["directlyAttachedTo"] - nexthops.append(nexthop) - - route["next-hops"] = {} - route["next-hops"]["next-hop"] = nexthops - routes.append(route) - - insert(ospf, "ietf-ospf:local-rib", "ietf-ospf:route", routes) - - -def add_ospf(control_protocols): - """Populate OSPF status""" - cmd = ['/usr/libexec/statd/ospf-status'] - data = run_json_cmd(cmd, "", check=False, default={}) - if data == {}: - return # No OSPF data available - - control_protocol = {} - control_protocol["type"] = "infix-routing:ospfv2" - control_protocol["name"] = "default" - control_protocol["ietf-ospf:ospf"] = {} - control_protocol["ietf-ospf:ospf"]["ietf-ospf:areas"] = {} - - - control_protocol["ietf-ospf:ospf"]["ietf-ospf:router-id"] = data.get("routerId") - control_protocol["ietf-ospf:ospf"]["ietf-ospf:address-family"] = "ipv4" - areas = [] - - for area_id, values in data.get("areas", {}).items(): - area = {} - area["ietf-ospf:area-id"] = area_id - area["ietf-ospf:interfaces"] = {} - if values.get("area-type"): - area["ietf-ospf:area-type"] = values["area-type"] - interfaces = [] - for iface in values.get("interfaces", {}): - interface = {} - interface["ietf-ospf:neighbors"] = {} - interface["name"] = iface["name"] - - if iface.get("drId"): - interface["dr-router-id"] = iface["drId"] - if iface.get("drAddress"): - interface["dr-ip-addr"] = iface["drAddress"] - if iface.get("bdrId"): - interface["bdr-router-id"] = iface["bdrId"] - if iface.get("bdrAddress"): - interface["bdr-ip-addr"] = iface["bdrAddress"] - - if iface.get("timerPassiveIface"): - interface["passive"] = True - else: - interface["passive"] = False - - interface["enabled"] = iface["ospfEnabled"] - if iface["networkType"] == "POINTOPOINT": - interface["interface-type"] = "point-to-point" - if iface["networkType"] == "BROADCAST": - interface["interface-type"] = "broadcast" - - if iface.get("state"): - # Wev've never seen "DependUpon", and has no entry in - # the YANG model, but is listed before down in Frr - xlate = { - "DependUpon": "down", - "Down": "down", - "Waiting": "waiting", - "Loopback": "loopback", - "Point-To-Point": "point-to-point", - "DROther": "dr-other", - "Backup": "bdr", - "DR": "dr" - } - val = xlate.get(iface["state"], "unknown") - interface["state"] = val - - neighbors = [] - for neigh in iface["neighbors"]: - neighbor = {} - neighbor["neighbor-router-id"] = neigh["neighborIp"] - neighbor["address"] = neigh["ifaceAddress"] - neighbor["dead-timer"] = neigh["routerDeadIntervalTimerDueMsec"] - neighbor["state"] = frr_to_ietf_neighbor_state(neigh["nbrState"]) - if neigh.get("routerDesignatedId"): - neighbor["dr-router-id"] = neigh["routerDesignatedId"] - if neigh.get("routerDesignatedBackupId"): - neighbor["bdr-router-id"] = neigh["routerDesignatedBackupId"] - neighbors.append(neighbor) - - interface["ietf-ospf:neighbors"] = {} - interface["ietf-ospf:neighbors"]["ietf-ospf:neighbor"] = neighbors - interfaces.append(interface) - - area["ietf-ospf:interfaces"]["ietf-ospf:interface"] = interfaces - areas.append(area) - - add_ospf_routes(control_protocol["ietf-ospf:ospf"]) - control_protocol["ietf-ospf:ospf"]["ietf-ospf:areas"]["ietf-ospf:area"] = areas - insert(control_protocols, "control-plane-protocol", [control_protocol]) - - def get_bridge_port_pvid(ifname): data = run_json_cmd(['bridge', '-j', 'vlan', 'show', 'dev', ifname], f"bridge-vlan-show-dev-{ifname}.json") @@ -1001,14 +859,8 @@ def main(): add_ipv6_route(ipv6routes) elif args.model == 'ietf-ospf': - yang_data = { - "ietf-routing:routing": { - "control-plane-protocols": { - } - } - } - add_ospf(yang_data['ietf-routing:routing']['control-plane-protocols']) - + from . import ietf_ospf + yang_data = ietf_ospf.operational() elif args.model == 'ietf-hardware': from . import ietf_hardware yang_data = ietf_hardware.operational() diff --git a/test/case/cli/system-output/run/+usr+libexec+statd+ospf-status b/test/case/cli/system-output/run/+usr+libexec+statd+ospf-status new file mode 100644 index 00000000..7f22ea8b --- /dev/null +++ b/test/case/cli/system-output/run/+usr+libexec+statd+ospf-status @@ -0,0 +1 @@ +{"routerId": "10.0.0.1", "tosRoutesOnly": true, "rfc2328Conform": true, "spfScheduleDelayMsecs": 0, "holdtimeMinMsecs": 50, "holdtimeMaxMsecs": 5000, "holdtimeMultplier": 1, "spfLastExecutedMsecs": 17503, "spfLastDurationMsecs": 0, "lsaMinIntervalMsecs": 5000, "lsaMinArrivalMsecs": 1000, "writeMultiplier": 20, "refreshTimerMsecs": 10000, "maximumPaths": 256, "preference": 110, "abrType": "Alternative Cisco", "asbrRouter": "injectingExternalRoutingInformation", "lsaExternalCounter": 1, "lsaExternalChecksum": 23527, "lsaAsopaqueCounter": 0, "lsaAsOpaqueChecksum": 0, "attachedAreaCounter": 3, "areas": {"0.0.0.0": {"backbone": true, "areaIfTotalCounter": 1, "areaIfActiveCounter": 1, "nbrFullAdjacentCounter": 1, "authentication": "authenticationNone", "spfExecutedCounter": 19, "lsaNumber": 24, "lsaRouterNumber": 2, "lsaRouterChecksum": 103244, "lsaNetworkNumber": 1, "lsaNetworkChecksum": 32939, "lsaSummaryNumber": 18, "lsaSummaryChecksum": 593799, "lsaAsbrNumber": 3, "lsaAsbrChecksum": 97451, "lsaNssaNumber": 0, "lsaNssaChecksum": 0, "lsaOpaqueLinkNumber": 0, "lsaOpaqueLinkChecksum": 0, "lsaOpaqueAreaNumber": 0, "lsaOpaqueAreaChecksum": 0, "area-type": "normal-area", "interfaces": [{"ifUp": true, "ifIndex": 6, "mtuBytes": 1500, "bandwidthMbit": 4294967295, "ifFlags": "", "ospfEnabled": true, "interfaceIp": {"10.0.12.1": {"ipAddress": "10.0.12.1", "ipAddressPrefixlen": 30, "ospfIfType": "Broadcast", "localIfUsed": "10.0.12.3", "area": "0.0.0.0", "routerId": "10.0.0.1", "networkType": "BROADCAST", "cost": 1, "transmitDelaySecs": 1, "state": "DR", "priority": 1, "drId": "10.0.0.1", "drAddress": "10.0.12.1", "bdrId": "1.1.1.1", "bdrAddress": "10.0.12.2", "mcastMemberOspfAllRouters": true, "mcastMemberOspfDesignatedRouters": true, "timerMsecs": 1000, "timerDeadSecs": 4, "timerWaitSecs": 4, "timerRetransmitSecs": 5, "timerHelloInMsecs": 565, "nbrCount": 1, "nbrAdjacentCount": 1, "grHelloDelaySecs": 10, "prefixSuppression": false}}, "ipAddress": "10.0.12.1", "ipAddressPrefixlen": 30, "ospfIfType": "Broadcast", "localIfUsed": "10.0.12.3", "area": "0.0.0.0", "routerId": "10.0.0.1", "networkType": "BROADCAST", "cost": 1, "transmitDelaySecs": 1, "state": "DR", "priority": 1, "opaqueCapable": true, "drId": "10.0.0.1", "drAddress": "10.0.12.1", "bdrId": "1.1.1.1", "bdrAddress": "10.0.12.2", "mcastMemberOspfAllRouters": true, "mcastMemberOspfDesignatedRouters": true, "timerMsecs": 1000, "timerDeadSecs": 4, "timerWaitSecs": 4, "timerRetransmitSecs": 5, "timerHelloInMsecs": 565, "nbrCount": 1, "nbrAdjacentCount": 1, "grHelloDelaySecs": 10, "peerBfdInfo": {"detectionMultiplier": 3, "rxMinInterval": 300, "txMinInterval": 300}, "prefixSuppression": false, "name": "e5", "neighbors": [{"ifaceAddress": "10.0.12.2", "areaId": "0.0.0.0", "ifaceName": "e5", "localIfaceAddress": "10.0.12.1", "nbrPriority": 1, "nbrState": "Full/Backup", "role": "Backup", "stateChangeCounter": 5, "lastPrgrsvChangeMsec": 38523, "routerDesignatedId": "10.0.0.1", "routerDesignatedBackupId": "1.1.1.1", "optionsCounter": 2, "optionsList": "*|-|-|-|-|-|E|-", "routerDeadIntervalTimerDueMsec": 3794, "databaseSummaryListCounter": 0, "linkStateRequestListCounter": 0, "linkStateRetransmissionListCounter": 0, "threadInactivityTimer": "on", "threadLinkStateRequestRetransmission": "on", "threadLinkStateUpdateRetransmission": "on", "grHelperStatus": "None", "peerBfdInfo": {"type": "single hop", "detectMultiplier": 3, "rxMinInterval": 300, "txMinInterval": 300, "status": "Up", "lastUpdate": "0:00:00:44"}, "neighborIp": "1.1.1.1"}]}]}, "0.0.0.1": {"nssaNoSummary": true, "shortcuttingMode": "Default", "areaIfTotalCounter": 3, "areaIfActiveCounter": 3, "nssa": true, "abr": true, "nssaTranslatorElected": true, "nbrFullAdjacentCounter": 1, "authentication": "authenticationNone", "virtualAdjacenciesPassingCounter": 0, "spfExecutedCounter": 20, "lsaNumber": 7, "lsaRouterNumber": 3, "lsaRouterChecksum": 184123, "lsaNetworkNumber": 2, "lsaNetworkChecksum": 80372, "lsaSummaryNumber": 2, "lsaSummaryChecksum": 43268, "lsaAsbrNumber": 0, "lsaAsbrChecksum": 0, "lsaNssaNumber": 0, "lsaNssaChecksum": 0, "lsaOpaqueLinkNumber": 0, "lsaOpaqueLinkChecksum": 0, "lsaOpaqueAreaNumber": 0, "lsaOpaqueAreaChecksum": 0, "area-type": "nssa-area", "interfaces": [{"ifUp": true, "ifIndex": 7, "mtuBytes": 1500, "bandwidthMbit": 4294967295, "ifFlags": "", "ospfEnabled": true, "interfaceIp": {"10.0.13.1": {"ipAddress": "10.0.13.1", "ipAddressPrefixlen": 30, "ospfIfType": "Broadcast", "localIfUsed": "10.0.13.3", "area": "0.0.0.1 [NSSA]", "routerId": "10.0.0.1", "networkType": "BROADCAST", "cost": 2000, "transmitDelaySecs": 1, "state": "Backup", "priority": 1, "drId": "10.0.0.3", "drAddress": "10.0.13.2", "bdrId": "10.0.0.1", "bdrAddress": "10.0.13.1", "mcastMemberOspfAllRouters": true, "mcastMemberOspfDesignatedRouters": true, "timerMsecs": 1000, "timerDeadSecs": 4, "timerWaitSecs": 4, "timerRetransmitSecs": 5, "timerHelloInMsecs": 444, "nbrCount": 1, "nbrAdjacentCount": 1, "grHelloDelaySecs": 10, "prefixSuppression": false}}, "ipAddress": "10.0.13.1", "ipAddressPrefixlen": 30, "ospfIfType": "Broadcast", "localIfUsed": "10.0.13.3", "area": "0.0.0.1", "routerId": "10.0.0.1", "networkType": "BROADCAST", "cost": 2000, "transmitDelaySecs": 1, "state": "Backup", "priority": 1, "opaqueCapable": true, "drId": "10.0.0.3", "drAddress": "10.0.13.2", "bdrId": "10.0.0.1", "bdrAddress": "10.0.13.1", "mcastMemberOspfAllRouters": true, "mcastMemberOspfDesignatedRouters": true, "timerMsecs": 1000, "timerDeadSecs": 4, "timerWaitSecs": 4, "timerRetransmitSecs": 5, "timerHelloInMsecs": 444, "nbrCount": 1, "nbrAdjacentCount": 1, "grHelloDelaySecs": 10, "peerBfdInfo": {"detectionMultiplier": 3, "rxMinInterval": 300, "txMinInterval": 300}, "prefixSuppression": false, "name": "e6", "neighbors": [{"ifaceAddress": "10.0.13.2", "areaId": "0.0.0.1", "ifaceName": "e6", "localIfaceAddress": "10.0.13.1", "nbrPriority": 1, "nbrState": "Full/DR", "role": "DR", "stateChangeCounter": 6, "lastPrgrsvChangeMsec": 41758, "routerDesignatedId": "10.0.0.3", "routerDesignatedBackupId": "10.0.0.1", "optionsCounter": 8, "optionsList": "*|-|-|-|N/P|-|-|-", "routerDeadIntervalTimerDueMsec": 3244, "databaseSummaryListCounter": 0, "linkStateRequestListCounter": 0, "linkStateRetransmissionListCounter": 0, "threadInactivityTimer": "on", "threadLinkStateRequestRetransmission": "on", "threadLinkStateUpdateRetransmission": "on", "grHelperStatus": "None", "peerBfdInfo": {"type": "single hop", "detectMultiplier": 3, "rxMinInterval": 300, "txMinInterval": 300, "status": "Up", "lastUpdate": "0:00:00:43"}, "neighborIp": "10.0.0.3"}]}, {"ifUp": true, "ifIndex": 1, "mtuBytes": 65536, "bandwidthMbit": 0, "ifFlags": "", "ospfEnabled": true, "interfaceIp": {"10.0.0.1": {"ipAddress": "10.0.0.1", "ipAddressPrefixlen": 32, "ospfIfType": "Broadcast", "localIfUsed": "10.0.0.1", "area": "0.0.0.1 [NSSA]", "routerId": "10.0.0.1", "networkType": "LOOPBACK", "cost": 0, "transmitDelaySecs": 1, "state": "Loopback", "priority": 1, "timerMsecs": 10000, "timerDeadSecs": 40, "timerWaitSecs": 40, "timerRetransmitSecs": 5, "timerHelloInMsecs": 0, "nbrCount": 0, "nbrAdjacentCount": 0, "grHelloDelaySecs": 10, "prefixSuppression": false}, "11.0.8.1": {"ipAddress": "11.0.8.1", "ipAddressPrefixlen": 24, "ospfIfType": "Broadcast", "localIfUsed": "11.0.8.255", "area": "0.0.0.1 [NSSA]", "routerId": "10.0.0.1", "networkType": "LOOPBACK", "cost": 0, "transmitDelaySecs": 1, "state": "Loopback", "priority": 1, "timerMsecs": 10000, "timerDeadSecs": 40, "timerWaitSecs": 40, "timerRetransmitSecs": 5, "timerHelloInMsecs": 0, "nbrCount": 0, "nbrAdjacentCount": 0, "grHelloDelaySecs": 10, "prefixSuppression": false}}, "ipAddress": "11.0.8.1", "ipAddressPrefixlen": 24, "ospfIfType": "Broadcast", "localIfUsed": "11.0.8.255", "area": "0.0.0.1", "routerId": "10.0.0.1", "networkType": "LOOPBACK", "cost": 0, "transmitDelaySecs": 1, "state": "Loopback", "priority": 1, "opaqueCapable": true, "timerMsecs": 10000, "timerDeadSecs": 40, "timerWaitSecs": 40, "timerRetransmitSecs": 5, "timerHelloInMsecs": 0, "nbrCount": 0, "nbrAdjacentCount": 0, "grHelloDelaySecs": 10, "prefixSuppression": false, "name": "lo", "neighbors": []}]}, "0.0.0.2": {"shortcuttingMode": "Default", "sBitConcensus": true, "areaIfTotalCounter": 0, "areaIfActiveCounter": 0, "nbrFullAdjacentCounter": 0, "authentication": "authenticationNone", "virtualAdjacenciesPassingCounter": 0, "spfExecutedCounter": 19, "lsaNumber": 39, "lsaRouterNumber": 3, "lsaRouterChecksum": 104816, "lsaNetworkNumber": 1, "lsaNetworkChecksum": 9970, "lsaSummaryNumber": 33, "lsaSummaryChecksum": 1065387, "lsaAsbrNumber": 2, "lsaAsbrChecksum": 110374, "lsaNssaNumber": 0, "lsaNssaChecksum": 0, "lsaOpaqueLinkNumber": 0, "lsaOpaqueLinkChecksum": 0, "lsaOpaqueAreaNumber": 0, "lsaOpaqueAreaChecksum": 0}}} diff --git a/test/case/cli/system-output/run/vtysh_-c_show-ip-ospf-route-json b/test/case/cli/system-output/run/vtysh_-c_show-ip-ospf-route-json new file mode 100644 index 00000000..e03c6425 --- /dev/null +++ b/test/case/cli/system-output/run/vtysh_-c_show-ip-ospf-route-json @@ -0,0 +1 @@ +{"10.0.0.1/32":{"routeType":"N","transit":false,"cost":0,"area":"0.0.0.1","nexthops":[{"ip":" ","directlyAttachedTo":"lo"}]},"10.0.0.2/32":{"routeType":"N","transit":false,"cost":1,"area":"0.0.0.0","nexthops":[{"ip":"10.0.12.2","via":"e5","advertisedRouter":"1.1.1.1"}]},"10.0.0.3/32":{"routeType":"N","transit":false,"cost":2000,"area":"0.0.0.1","nexthops":[{"ip":"10.0.13.2","via":"e6","advertisedRouter":"10.0.0.3"}]},"10.0.0.4/32":{"routeType":"N IA","cost":2001,"area":"0.0.0.0","nexthops":[{"ip":"10.0.12.2","via":"e5","advertisedRouter":"1.1.1.1"}]},"10.0.12.0/30":{"routeType":"N","transit":true,"cost":1,"area":"0.0.0.0","nexthops":[{"ip":" ","directlyAttachedTo":"e5"}]},"10.0.13.0/30":{"routeType":"N","transit":true,"cost":2000,"area":"0.0.0.1","nexthops":[{"ip":" ","directlyAttachedTo":"e6"}]},"10.0.23.0/30":{"routeType":"N","transit":true,"cost":2001,"area":"0.0.0.1","nexthops":[{"ip":"10.0.13.2","via":"e6","advertisedRouter":"10.0.0.3"}]},"10.0.24.0/30":{"routeType":"N IA","cost":2001,"area":"0.0.0.0","nexthops":[{"ip":"10.0.12.2","via":"e5","advertisedRouter":"1.1.1.1"}]},"10.0.41.0/30":{"routeType":"N IA","cost":2002,"area":"0.0.0.0","nexthops":[{"ip":"10.0.12.2","via":"e5","advertisedRouter":"1.1.1.1"}]},"11.0.8.1/32":{"routeType":"N","transit":false,"cost":0,"area":"0.0.0.1","nexthops":[{"ip":" ","directlyAttachedTo":"lo"}]},"11.0.9.1/32":{"routeType":"N","transit":false,"cost":1,"area":"0.0.0.0","nexthops":[{"ip":"10.0.12.2","via":"e5","advertisedRouter":"1.1.1.1"}]},"11.0.10.1/32":{"routeType":"N","transit":false,"cost":1,"area":"0.0.0.0","nexthops":[{"ip":"10.0.12.2","via":"e5","advertisedRouter":"1.1.1.1"}]},"11.0.11.1/32":{"routeType":"N","transit":false,"cost":1,"area":"0.0.0.0","nexthops":[{"ip":"10.0.12.2","via":"e5","advertisedRouter":"1.1.1.1"}]},"11.0.12.1/32":{"routeType":"N","transit":false,"cost":1,"area":"0.0.0.0","nexthops":[{"ip":"10.0.12.2","via":"e5","advertisedRouter":"1.1.1.1"}]},"11.0.13.1/32":{"routeType":"N","transit":false,"cost":1,"area":"0.0.0.0","nexthops":[{"ip":"10.0.12.2","via":"e5","advertisedRouter":"1.1.1.1"}]},"11.0.14.1/32":{"routeType":"N","transit":false,"cost":1,"area":"0.0.0.0","nexthops":[{"ip":"10.0.12.2","via":"e5","advertisedRouter":"1.1.1.1"}]},"11.0.15.1/32":{"routeType":"N","transit":false,"cost":1,"area":"0.0.0.0","nexthops":[{"ip":"10.0.12.2","via":"e5","advertisedRouter":"1.1.1.1"}]},"192.168.3.0/24":{"routeType":"N","transit":false,"cost":2001,"area":"0.0.0.1","nexthops":[{"ip":"10.0.13.2","via":"e6","advertisedRouter":"10.0.0.3"}]},"1.1.1.1":{"routeType":"R ","cost":1,"area":"0.0.0.0","routerType":"abr","nexthops":[{"ip":"10.0.12.2","via":"e5"}]},"10.0.0.4":{"routeType":"R ","cost":2001,"area":"0.0.0.0","IA":true,"ia":true,"routerType":"asbr","nexthops":[{"ip":"10.0.12.2","via":"e5"}]},"192.168.4.0/24":{"routeType":"N E2","cost":2001,"type2cost":20,"tag":0,"nexthops":[{"ip":"10.0.12.2","via":"e5","advertisedRouter":"1.1.1.1"}]}} From 2ec226640e8386f186a362f149e65b031dcc7d35 Mon Sep 17 00:00:00 2001 From: Tobias Waldekranz Date: Thu, 9 Jan 2025 15:47:49 +0100 Subject: [PATCH 09/12] yanger: Move ietf-{interfaces,routing} implementations to separate modules Should this have been two commits: yes. Should we spend time on splitting them after the fact because yours truly dropped the ball: no. --- .../python/yanger/ietf_interfaces/__init__.py | 564 +++++++++++++ src/statd/python/yanger/ietf_routing.py | 149 ++++ src/statd/python/yanger/yanger.py | 761 +----------------- .../{bridge-link.json => run/bridge_-j_link} | 0 .../bridge_-j_link_show_dev_e0} | 0 .../bridge_-j_link_show_dev_e1} | 0 .../bridge_-j_link_show_dev_e2} | 0 .../{bridge-vlan.json => run/bridge_-j_vlan} | 0 .../bridge_-j_vlan_show_dev_br0} | 0 .../bridge_-j_vlan_show_dev_br1} | 0 .../bridge_-j_vlan_show_dev_e0} | 0 .../bridge_-j_vlan_show_dev_e1} | 0 .../bridge_-j_vlan_show_dev_e2} | 0 .../ethtool_--json_-S_br0_--all-groups} | 0 .../ethtool_--json_-S_dsa0_--all-groups} | 0 .../ethtool_--json_-S_e0_--all-groups} | 0 .../ethtool_--json_-S_e1_--all-groups} | 0 .../ethtool_--json_-S_e2_--all-groups} | 0 .../ethtool_--json_-S_e3_--all-groups} | 0 .../ethtool_--json_-S_e4_--all-groups} | 0 .../{ethtool-br0.txt => run/ethtool_br0} | 0 .../{ethtool-dsa0.txt => run/ethtool_dsa0} | 0 .../{ethtool-e0.txt => run/ethtool_e0} | 0 .../{ethtool-e1.txt => run/ethtool_e1} | 0 .../{ethtool-e2.txt => run/ethtool_e2} | 0 .../{ethtool-e3.txt => run/ethtool_e3} | 0 .../{ethtool-e4.txt => run/ethtool_e4} | 0 .../ip_-j_addr_show} | 0 .../{netns-list.json => run/ip_-j_netns_list} | 0 .../ip_-s_-d_-j_link_show} | 0 .../ip_netns_exec_57ff63cb_ip_-j_addr_show} | 0 ...netns_exec_57ff63cb_ip_-s_-d_-j_link_show} | 0 .../ip_netns_exec_db5ad90e_ip_-j_addr_show} | 0 ...netns_exec_db5ad90e_ip_-s_-d_-j_link_show} | 0 .../mctl_-p_show_igmp_json} | 0 .../vtysh_-c_show-ip-route-json} | 0 .../vtysh_-c_show-ipv6-route-json} | 0 37 files changed, 723 insertions(+), 751 deletions(-) create mode 100644 src/statd/python/yanger/ietf_interfaces/__init__.py create mode 100644 src/statd/python/yanger/ietf_routing.py rename test/case/cli/system-output/{bridge-link.json => run/bridge_-j_link} (100%) rename test/case/cli/system-output/{bridge-link-show-dev-e0.json => run/bridge_-j_link_show_dev_e0} (100%) rename test/case/cli/system-output/{bridge-link-show-dev-e1.json => run/bridge_-j_link_show_dev_e1} (100%) rename test/case/cli/system-output/{bridge-link-show-dev-e2.json => run/bridge_-j_link_show_dev_e2} (100%) rename test/case/cli/system-output/{bridge-vlan.json => run/bridge_-j_vlan} (100%) rename test/case/cli/system-output/{bridge-vlan-show-dev-br0.json => run/bridge_-j_vlan_show_dev_br0} (100%) rename test/case/cli/system-output/{bridge-vlan-show-dev-br1.json => run/bridge_-j_vlan_show_dev_br1} (100%) rename test/case/cli/system-output/{bridge-vlan-show-dev-e0.json => run/bridge_-j_vlan_show_dev_e0} (100%) rename test/case/cli/system-output/{bridge-vlan-show-dev-e1.json => run/bridge_-j_vlan_show_dev_e1} (100%) rename test/case/cli/system-output/{bridge-vlan-show-dev-e2.json => run/bridge_-j_vlan_show_dev_e2} (100%) rename test/case/cli/system-output/{ethtool-groups-br0.json => run/ethtool_--json_-S_br0_--all-groups} (100%) rename test/case/cli/system-output/{ethtool-groups-dsa0.json => run/ethtool_--json_-S_dsa0_--all-groups} (100%) rename test/case/cli/system-output/{ethtool-groups-e0.json => run/ethtool_--json_-S_e0_--all-groups} (100%) rename test/case/cli/system-output/{ethtool-groups-e1.json => run/ethtool_--json_-S_e1_--all-groups} (100%) rename test/case/cli/system-output/{ethtool-groups-e2.json => run/ethtool_--json_-S_e2_--all-groups} (100%) rename test/case/cli/system-output/{ethtool-groups-e3.json => run/ethtool_--json_-S_e3_--all-groups} (100%) rename test/case/cli/system-output/{ethtool-groups-e4.json => run/ethtool_--json_-S_e4_--all-groups} (100%) rename test/case/cli/system-output/{ethtool-br0.txt => run/ethtool_br0} (100%) rename test/case/cli/system-output/{ethtool-dsa0.txt => run/ethtool_dsa0} (100%) rename test/case/cli/system-output/{ethtool-e0.txt => run/ethtool_e0} (100%) rename test/case/cli/system-output/{ethtool-e1.txt => run/ethtool_e1} (100%) rename test/case/cli/system-output/{ethtool-e2.txt => run/ethtool_e2} (100%) rename test/case/cli/system-output/{ethtool-e3.txt => run/ethtool_e3} (100%) rename test/case/cli/system-output/{ethtool-e4.txt => run/ethtool_e4} (100%) rename test/case/cli/system-output/{ip-addr-show.json => run/ip_-j_addr_show} (100%) rename test/case/cli/system-output/{netns-list.json => run/ip_-j_netns_list} (100%) rename test/case/cli/system-output/{ip-link-show.json => run/ip_-s_-d_-j_link_show} (100%) rename test/case/cli/system-output/{netns-57ff63cb-ip-addr-show.json => run/ip_netns_exec_57ff63cb_ip_-j_addr_show} (100%) rename test/case/cli/system-output/{netns-57ff63cb-ip-link-show.json => run/ip_netns_exec_57ff63cb_ip_-s_-d_-j_link_show} (100%) rename test/case/cli/system-output/{netns-db5ad90e-ip-addr-show.json => run/ip_netns_exec_db5ad90e_ip_-j_addr_show} (100%) rename test/case/cli/system-output/{netns-db5ad90e-ip-link-show.json => run/ip_netns_exec_db5ad90e_ip_-s_-d_-j_link_show} (100%) rename test/case/cli/system-output/{igmp-status.json => run/mctl_-p_show_igmp_json} (100%) rename test/case/cli/system-output/{vtysh-ip4-route.json => run/vtysh_-c_show-ip-route-json} (100%) rename test/case/cli/system-output/{vtysh-ip6-route.json => run/vtysh_-c_show-ipv6-route-json} (100%) diff --git a/src/statd/python/yanger/ietf_interfaces/__init__.py b/src/statd/python/yanger/ietf_interfaces/__init__.py new file mode 100644 index 00000000..87b21b7e --- /dev/null +++ b/src/statd/python/yanger/ietf_interfaces/__init__.py @@ -0,0 +1,564 @@ +from ..common import insert, lookup, LOG +from ..host import HOST + + +def json_get_yang_type(iface_in): + if iface_in['link_type'] == "loopback": + return "infix-if-type:loopback" + + if iface_in['link_type'] in ("gre", "gre6"): + return "infix-if-type:gre" + + if iface_in['link_type'] != "ether": + return "infix-if-type:other" + + if 'parentbus' in iface_in and iface_in['parentbus'] == "virtio": + return "infix-if-type:etherlike" + + if 'linkinfo' not in iface_in: + return "infix-if-type:ethernet" + + if 'info_kind' not in iface_in['linkinfo']: + return "infix-if-type:ethernet" + + if iface_in['linkinfo']['info_kind'] == "veth": + return "infix-if-type:veth" + + if iface_in['linkinfo']['info_kind'] in ("gretap", "ip6gretap"): + return "infix-if-type:gretap" + + if iface_in['linkinfo']['info_kind'] == "vlan": + return "infix-if-type:vlan" + + if iface_in['linkinfo']['info_kind'] == "bridge": + return "infix-if-type:bridge" + + if iface_in['linkinfo']['info_kind'] == "dsa": + return "infix-if-type:ethernet" + + if iface_in['linkinfo']['info_kind'] == "dummy": + return "infix-if-type:dummy" + + # Fallback + return "infix-if-type:ethernet" + + +def json_get_yang_origin(addr): + """Translate kernel IP address origin to YANG""" + xlate = { + "kernel_ll": "link-layer", + "kernel_ra": "link-layer", + "static": "static", + "dhcp": "dhcp", + "random": "random", + } + proto = addr['protocol'] + + if proto in ("kernel_ll", "kernel_ra"): + if "stable-privacy" in addr: + return "random" + + return xlate.get(proto, "other") + + + + +def iface_is_dsa(iface_in): + """Check if interface is a DSA/intra-switch port""" + if "linkinfo" not in iface_in: + return False + if "info_kind" not in iface_in['linkinfo']: + return False + if iface_in['linkinfo']['info_kind'] != "dsa": + return False + return True + + +def get_bridge_port_pvid(ifname): + data = HOST.run_json(['bridge', '-j', 'vlan', 'show', 'dev', ifname]) + if len(data) != 1: + return None + + iface = data[0] + + for vlan in iface['vlans']: + if 'flags' in vlan and 'PVID' in vlan['flags']: + return vlan['vlan'] + + return None + + +def get_bridge_port_stp_state(ifname): + data = HOST.run_json(['bridge', '-j', 'link', 'show', 'dev', ifname]) + if len(data) != 1: + return None + + iface = data[0] + + states = ['disabled', 'listening', 'learning', 'forwarding', 'blocking'] + if 'state' in iface and iface['state'] in states: + return iface['state'] + + return None + + +def get_brport_multicast(ifname): + """Check if multicast snooping is enabled on bridge, default: nope""" + data = HOST.run_json(['mctl', '-p', 'show', 'igmp', 'json'], default={}) + multicast = {} + + if ifname in data.get('fast-leave-ports', []): + multicast["fast-leave"] = True + else: + multicast["fast-leave"] = False + + if ifname in data.get('multicast-router-ports', []): + multicast["router"] = "permanent" + else: + multicast["router"] = "auto" + + return multicast + + +# We always get all interfaces for two reasons. +# 1) To increase speed on large iron with many ports. +# 2) To simplify testing (single dummy file ip-link-show.json). +def get_ip_link(): + """Fetch interface link information from kernel""" + return HOST.run_json(['ip', '-s', '-d', '-j', 'link', 'show']) + +def netns_get_ip_link(netns): + """Fetch interface link information from within a network namespace""" + return HOST.run_json(['ip', 'netns', 'exec', netns, 'ip', '-s', '-d', '-j', 'link', 'show']) + +def get_ip_addr(): + """Fetch interface address information from kernel""" + return HOST.run_json(['ip', '-j', 'addr', 'show']) + +def netns_get_ip_addr(netns): + """Fetch interface address information from within a network namespace""" + return HOST.run_json(['ip', 'netns', 'exec', netns, 'ip', '-j', 'addr', 'show']) + +def get_netns_list(): + """Fetch a list of network namespaces""" + return HOST.run_json(['ip', '-j', 'netns', 'list'], []) + +def netns_find_ifname(ifname): + """Find which network namespace owns ifname (if any)""" + for netns in get_netns_list(): + for iface in netns_get_ip_link(netns['name']): + if 'ifalias' in iface and iface['ifalias'] == ifname: + return netns['name'] + return None + +def netns_ifindex_to_ifname(ifindex): + """Look through all network namespaces for an interface index and return its name""" + for netns in get_netns_list(): + for iface in netns_get_ip_link(netns['name']): + if iface['ifindex'] == ifindex: + if 'ifalias' in iface: + return iface['ifalias'] + if 'ifname' in iface: + return iface['ifname'] + return None + + return None + +def add_bridge_port_common(ifname, iface_in, iface_out): + li = iface_in.get("linkinfo", {}) + if not (li.get("info_slave_kind") == "bridge" or \ + li.get("info_kind") == "bridge"): + return + + pvid = get_bridge_port_pvid(ifname) + if pvid is not None: + insert(iface_out, "infix-interfaces:bridge-port", "pvid", pvid) + +def add_bridge_port_lower(ifname, iface_in, iface_out): + li = iface_in.get("linkinfo", {}) + if not li.get("info_slave_kind") == "bridge": + return + + insert(iface_out, "infix-interfaces:bridge-port", "bridge", iface_in['master']) + + stp_state = get_bridge_port_stp_state(ifname) + if stp_state is not None: + insert(iface_out, "infix-interfaces:bridge-port", "stp-state", stp_state) + + multicast = get_brport_multicast(ifname) + insert(iface_out, "infix-interfaces:bridge-port", "multicast", multicast) + + +def add_gre(iface_in, iface_out): + if 'link_type' in iface_in: + val = json_get_yang_type(iface_in) + if val != "infix-if-type:gre" and val != "infix-if-type:gretap": + return; + gre={} + info_data=iface_in.get("linkinfo", {}).get("info_data", {}) + gre["local"] = info_data.get("local") + gre["remote"] = info_data.get("remote") + insert(iface_out, "infix-interfaces:gre", gre) + + +def add_ip_link(ifname, iface_in, iface_out): + if 'ifname' in iface_in: + iface_out['name'] = ifname + + if 'ifindex' in iface_in: + iface_out['if-index'] = iface_in['ifindex'] + + if 'ifalias' in iface_in: + iface_out['description'] = iface_in['ifalias'] + + if 'address' in iface_in and not "POINTOPOINT" in iface_in["flags"]: + iface_out['phys-address'] = iface_in['address'] + + add_bridge_port_common(ifname, iface_in, iface_out) + add_bridge_port_lower(ifname, iface_in, iface_out) + + if not iface_is_dsa(iface_in): + if iface_in.get('link'): + insert(iface_out, "infix-interfaces:vlan", "lower-layer-if", iface_in['link']) + elif 'link_index' in iface_in: + # 'link_index' is the only reference we have if the link iface is in a namespace + lower = netns_ifindex_to_ifname(iface_in['link_index']) + if lower: + insert(iface_out, "infix-interfaces:vlan", "lower-layer-if", lower) + + if 'flags' in iface_in: + iface_out['admin-status'] = "up" if "UP" in iface_in['flags'] else "down" + + if 'operstate' in iface_in: + xlate = { + "DOWN": "down", + "UP": "up", + "DORMANT": "dormant", + "TESTING": "testing", + "LOWERLAYERDOWN": "lower-layer-down", + "NOTPRESENT": "not-present" + } + val = xlate.get(iface_in['operstate'], "unknown") + iface_out['oper-status'] = val + + if 'link_type' in iface_in: + val = json_get_yang_type(iface_in) + iface_out['type'] = val + add_gre(iface_in, iface_out) + + val = lookup(iface_in, "stats64", "rx", "bytes") + if val is not None: + insert(iface_out, "statistics", "out-octets", str(val)) + + val = lookup(iface_in, "stats64", "tx", "bytes") + if val is not None: + insert(iface_out, "statistics", "in-octets", str(val)) + + +def add_ip_addr(ifname, iface_in, iface_out): + if 'mtu' in iface_in and ifname != "lo": + insert(iface_out, "ietf-ip:ipv4", "mtu", iface_in['mtu']) + + val = HOST.read(f"/proc/sys/net/ipv6/conf/{ifname}/mtu") + if val is not None: + insert(iface_out, "ietf-ip:ipv6", "mtu", int(val.strip())) + + if 'addr_info' in iface_in: + inet = [] + inet6 = [] + + for addr in iface_in['addr_info']: + new = {} + + if 'family' not in addr: + LOG.error("'family' missing from 'addr_info'") + continue + + if 'local' in addr: + new['ip'] = addr['local'] + if 'prefixlen' in addr: + new['prefix-length'] = addr['prefixlen'] + if 'protocol' in addr: + new['origin'] = json_get_yang_origin(addr) + + if addr['family'] == "inet": + inet.append(new) + elif addr['family'] == "inet6": + inet6.append(new) + else: + LOG.error("invalid 'family' in 'addr_info'") + sys.exit(1) + + insert(iface_out, "ietf-ip:ipv4", "address", inet) + insert(iface_out, "ietf-ip:ipv6", "address", inet6) + + +def add_ethtool_groups(ifname, iface_out): + """Fetch interface counters from kernel (need new JSON format!)""" + cmd = ['ethtool', '--json', '-S', ifname, '--all-groups'] + try: + data = HOST.run_json(cmd) + if len(data) != 1: + LOG.warning("%s: no counters available, skipping.", ifname) + return + except subprocess.CalledProcessError: + # Allow comand to fail, not all NICs support --json yet + return + + iface_in = data[0] + + # TODO: room for improvement, the "frame" creation could be more dynamic. + if "eth-mac" in iface_in or "rmon" in iface_in: + insert(iface_out, "ieee802-ethernet-interface:ethernet", "statistics", "frame", {}) + frame = iface_out['ieee802-ethernet-interface:ethernet']['statistics']['frame'] + + if "eth-mac" in iface_in: + mac_in = iface_in['eth-mac'] + + if "FramesTransmittedOK" in mac_in: + frame['out-frames'] = str(mac_in['FramesTransmittedOK']) + if "MulticastFramesXmittedOK" in mac_in: + frame['out-multicast-frames'] = str(mac_in['MulticastFramesXmittedOK']) + if "BroadcastFramesXmittedOK" in mac_in: + frame['out-broadcast-frames'] = str(mac_in['BroadcastFramesXmittedOK']) + if "FramesReceivedOK" in mac_in: + frame['in-frames'] = str(mac_in['FramesReceivedOK']) + if "MulticastFramesReceivedOK" in mac_in: + frame['in-multicast-frames'] = str(mac_in['MulticastFramesReceivedOK']) + if "BroadcastFramesReceivedOK" in mac_in: + frame['in-broadcast-frames'] = str(mac_in['BroadcastFramesReceivedOK']) + if "FrameCheckSequenceErrors" in mac_in: + frame['in-error-fcs-frames'] = str(mac_in['FrameCheckSequenceErrors']) + if "FramesLostDueToIntMACRcvError" in mac_in: + frame['in-error-mac-internal-frames'] = str(mac_in['FramesLostDueToIntMACRcvError']) + + if "OctetsTransmittedOK" in mac_in: + frame['infix-ethernet-interface:out-good-octets'] = str(mac_in['OctetsTransmittedOK']) + if "OctetsReceivedOK" in mac_in: + frame['infix-ethernet-interface:in-good-octets'] = str(mac_in['OctetsReceivedOK']) + + tot = 0 + found = False + if "FramesReceivedOK" in mac_in: + tot += mac_in['FramesReceivedOK'] + found = True + if "FrameCheckSequenceErrors" in mac_in: + tot += mac_in['FrameCheckSequenceErrors'] + found = True + if "FramesLostDueToIntMACRcvError" in mac_in: + tot += mac_in['FramesLostDueToIntMACRcvError'] + found = True + if "AlignmentErrors" in mac_in: + tot += mac_in['AlignmentErrors'] + found = True + if "etherStatsOversizePkts" in mac_in: + tot += mac_in['etherStatsOversizePkts'] + found = True + if "etherStatsJabbers" in mac_in: + tot += mac_in['etherStatsJabbers'] + found = True + if found: + frame['in-total-frames'] = str(tot) + + if "rmon" in iface_in: + rmon_in = iface_in['rmon'] + + if "undersize_pkts" in rmon_in: + frame['in-error-undersize-frames'] = str(rmon_in['undersize_pkts']) + + tot = 0 + found = False + if "etherStatsJabbers" in rmon_in: + tot += rmon_in['etherStatsJabbers'] + found = True + if "etherStatsOversizePkts" in rmon_in: + tot += rmon_in['etherStatsOversizePkts'] + found = True + if found: + frame['in-error-oversize-frames'] = str(tot) + +def add_ethtool_std(ifname, iface_out): + """Fetch interface speed/duplex/autoneg from kernel""" + keys = ['Speed', 'Duplex', 'Auto-negotiation'] + result = {} + + lines = HOST.run_multiline(['ethtool', ifname]) + for line in lines: + line = line.strip() + key = line.split(':', 1)[0].strip() + if key in keys: + key, value = line.split(':', 1) + result[key.strip()] = value.strip() + + if "Auto-negotiation" in result: + if result['Auto-negotiation'] == "on": + insert(iface_out, "ieee802-ethernet-interface:ethernet", "auto-negotiation", "enable", True) + else: + insert(iface_out, "ieee802-ethernet-interface:ethernet", "auto-negotiation", "enable", False) + + if "Duplex" in result: + if result['Duplex'] == "Half": + insert(iface_out, "ieee802-ethernet-interface:ethernet", "duplex", "half") + elif result['Duplex'] == "Full": + insert(iface_out, "ieee802-ethernet-interface:ethernet", "duplex", "full") + else: + insert(iface_out, "ieee802-ethernet-interface:ethernet", "duplex", "unknown") + + if "Speed" in result and result['Speed'] != "Unknown!": + # Avoid importing re (performance) + num = ''.join(filter(str.isdigit, result['Speed'])) + if num: + num = round((int(num) / 1000), 3) + insert(iface_out, "ieee802-ethernet-interface:ethernet", "speed", str(num)) + +def get_querier_data(querier_data): + multicast={} + + if not querier_data: + multicast["snooping"] = False + return multicast + multicast["snooping"] = True + if(querier_data.get("query-interval")): + multicast["query-interval"] = querier_data["query-interval"] + + return multicast + +def get_multicast_filters(filters): + multicast_filters=[] + for f in filters: + multicast_filter={} + multicast_filter["group"] = f["group"] + multicast_filter["ports"] = [] + for p in f["ports"]: + port={} + port["port"] = p + multicast_filter["ports"].append(port) + multicast_filters.append(multicast_filter) + return multicast_filters + +def add_mdb_to_bridge(brname, iface_out, mc_status): + filters = [entry for entry in mc_status.get("multicast-groups", []) if entry.get('vid') == None and entry.get('bridge') == brname] + querier = next((querier for querier in mc_status.get('multicast-queriers', []) if (querier.get("interface", "") == brname) and (querier.get("vid") is None)), None) + multicast = get_querier_data(querier) + multicast_filters = get_multicast_filters(filters) + insert(iface_out, "infix-interfaces:bridge", "multicast", multicast) + insert(iface_out, "infix-interfaces:bridge", "multicast-filters", "multicast-filter", multicast_filters) + +def add_container_ifaces(yang_ifaces): + """Add all podman interfaces with limited data""" + interfaces={} + try: + containers = HOST.run_json(['podman', 'ps', '-a', '--format=json'], default=[]) + except Exception as e: + logging.error(f"Error, unable to run podman: {e}") + return + + for container in containers: + name = container.get('Names', ['Unknown'])[0] + networks = container.get('Networks', []) + + for network in networks: + if not network in interfaces: + interfaces[network] = [] + if name not in interfaces[network]: + interfaces[network].append(name) + + for ifname, containers in interfaces.items(): + iface_out = {} + iface_out['name'] = ifname + iface_out['type'] = "infix-if-type:other" # Fallback + insert(iface_out, "infix-interfaces:container-network", "containers", containers) + + netns = netns_find_ifname(ifname) + if netns is not None: + ip_link_data = netns_get_ip_link(netns) + ip_link_data = next((d for d in ip_link_data if d.get('ifalias') == ifname), None) + add_ip_link(ifname, ip_link_data, iface_out) + + yang_ifaces.append(iface_out) + +# Helper function to add tagged/untagged interfaces to a vlan dict in a list +def _add_vlan_iface(vlans, multicast_filter, multicast, vid, key, val): + for d in vlans: + if d['vid'] == vid: + if key in d: + d[key].append(val) + else: + d[key] = [val] + return + + vlans.append({'vid': vid, "multicast-filters": {"multicast-filter": multicast_filter}, "multicast": multicast, key: [val]}) + +def add_vlans_to_bridge(brname, iface_out, mc_status): + slaves = [] # Contains all interfaces that has this bridge as 'master' + for iface in HOST.run_json(['bridge', '-j', 'link']): + if "master" in iface and iface['master'] == brname: + slaves.append(iface['ifname']) + + vlans = [] # Contains all vlans and slaves belonging to this bridge + for iface in HOST.run_json(['bridge', '-j', 'vlan']): + if iface['ifname'] not in slaves and iface['ifname'] != brname: + continue + for vlan in iface['vlans']: + querier = next((querier for querier in mc_status.get('multicast-queriers', []) if (querier.get("vid") == vlan['vlan'])), None) + filters = [entry for entry in mc_status.get("multicast-groups", []) if (entry.get("vid") == vlan["vlan"])] + if 'flags' in vlan and 'Egress Untagged' in vlan['flags']: + _add_vlan_iface(vlans, get_multicast_filters(filters), get_querier_data(querier), vlan['vlan'], 'untagged', iface['ifname']) + else: + _add_vlan_iface(vlans, get_multicast_filters(filters), get_querier_data(querier), vlan['vlan'], 'tagged', iface['ifname']) + + insert(iface_out, "infix-interfaces:bridge", "vlans", "vlan", vlans) + +def get_iface_data(ifname, ip_link_data, ip_addr_data): + iface_out = {} + + add_ip_link(ifname, ip_link_data, iface_out) + add_ip_addr(ifname, ip_addr_data, iface_out) + + if 'type' in iface_out and iface_out['type'] == "infix-if-type:ethernet": + add_ethtool_groups(ifname, iface_out) + add_ethtool_std(ifname, iface_out) + + if 'type' in iface_out and iface_out['type'] == "infix-if-type:bridge": + # Fail silent, multicast snooping may not be enabled on bridge + mc_status = HOST.run_json(['mctl', '-p', 'show', 'igmp', 'json'], default={}) + + add_vlans_to_bridge(ifname, iface_out, mc_status) + add_mdb_to_bridge(ifname, iface_out, mc_status) + + return iface_out + +def _add_interface(ifname, ip_link_data, ip_addr_data, yang_ifaces): + # We expect both ip addr and link data to exist. + if not ip_link_data or not ip_addr_data: + return + + # Skip internal interfaces. + if 'group' in ip_link_data and ip_link_data['group'] == "internal": + return + + yang_ifaces.append(get_iface_data(ifname, ip_link_data, ip_addr_data)) + +def operational(ifname=None): + out = { + "ietf-interfaces:interfaces": { + "interface": [] + } + } + out_ifaces = out["ietf-interfaces:interfaces"]["interface"] + + ip_link_data = get_ip_link() + ip_addr_data = get_ip_addr() + + if ifname: + ip_link_data = next((d for d in ip_link_data if d.get('ifname') == ifname), None) + ip_addr_data = next((d for d in ip_addr_data if d.get('ifname') == ifname), None) + _add_interface(ifname, ip_link_data, ip_addr_data, out_ifaces) + else: + for link in ip_link_data: + addr = next((d for d in ip_addr_data if d.get('ifname') == link["ifname"]), None) + _add_interface(link["ifname"], link, addr, out_ifaces) + + add_container_ifaces(out_ifaces) + + return out diff --git a/src/statd/python/yanger/ietf_routing.py b/src/statd/python/yanger/ietf_routing.py new file mode 100644 index 00000000..d9737d9c --- /dev/null +++ b/src/statd/python/yanger/ietf_routing.py @@ -0,0 +1,149 @@ +from datetime import timedelta +from re import match + +from .common import insert +from .host import HOST + + +def uptime2datetime(uptime): + """ + Convert uptime to YANG format (YYYY-MM-DDTHH:MM:SS+00:00) + + Handles the following input formats (frrtime): + HH:MM:SS + XdXXhXXm + XXwXdXXh + """ + h = m = s = 0 + + # Format HH:MM:SS + if match(r'^\d{2}:\d{2}:\d{2}$', uptime): + h, m, s = map(int, uptime.split(':')) + + # Format XdXXhXXm (days, hours, minutes) + elif match(r'^\d+d\d{2}h\d{2}m$', uptime): + days = int(uptime.split('d')[0]) + h = int(uptime.split('d')[1].split('h')[0]) + m = int(uptime.split('h')[1].split('m')[0]) + h += days * 24 + + # Format XwXdXXh (weeks, days, hours) + elif match(r'^\d{2}w\d{1}d\d{2}h$', uptime): + weeks = int(uptime.split('w')[0]) + days = int(uptime.split('w')[1].split('d')[0]) + h = int(uptime.split('d')[1].split('h')[0]) + h += weeks * 7 * 24 + h += days * 24 + + uptime_delta = timedelta(hours=h, minutes=m, seconds=s) + current_time = HOST.now() + last_updated = current_time - uptime_delta + date_timestd = last_updated.strftime('%Y-%m-%dT%H:%M:%S%z') + + return date_timestd[:-2] + ':' + date_timestd[-2:] + + +def add_protocol(routes, proto): + """Populate routes from vtysh JSON output""" + + frrproto = "ip" if proto == "ipv4" else proto + data = HOST.run_json(['vtysh', '-c', f"show {frrproto} route json"], {}) + + # Mapping of FRR protocol names to IETF routing-protocol + pmap = { + 'kernel': 'infix-routing:kernel', + 'connected': 'direct', + 'static': 'static', + 'ospf': 'ietf-ospf:ospfv2', + 'ospf6': 'ietf-ospf:ospfv3', + } + + out = {} + out["route"] = [] + + if proto == "ipv4": + default = "0.0.0.0/0" + host_prefix_length = "32" + else: + default = "::/0" + host_prefix_length = "128" + + for prefix, entries in data.items(): + for route in entries: + new = {} + dst = route.get('prefix', default) + if '/' not in dst: + dst = f"{dst}/{route.get('prefixLen', host_prefix_length)}" + + new[f'ietf-{proto}-unicast-routing:destination-prefix'] = dst + frr = route.get('protocol', 'infix-routing:kernel') + new['source-protocol'] = pmap.get(frr, 'infix-routing:kernel') + new['route-preference'] = route.get('distance', 0) + + # Metric only available in the model for OSPF routes + if 'ospf' in frr: + new['ietf-ospf:metric'] = route.get('metric', 0) + + # See https://datatracker.ietf.org/doc/html/rfc7951#section-6.9 + # for details on how presence leaves are encoded in JSON: [null] + if route.get('selected', False): + new['active'] = [None] + + new['last-updated'] = uptime2datetime(route.get('uptime', 0)) + installed = route.get('installed', False) + + next_hops = [] + for hop in route.get('nexthops', []): + next_hop = {} + if hop.get('ip'): + next_hop[f'ietf-{proto}-unicast-routing:address'] = hop['ip'] + elif hop.get('interfaceName'): + next_hop['outgoing-interface'] = hop['interfaceName'] + # See zebra/zebra_vty.c:re_status_outpupt_char() + if installed and hop.get('fib', False): + next_hop['infix-routing:installed'] = [None] + next_hops.append(next_hop) + + if next_hops: + new['next-hop'] = {'next-hop-list': {'next-hop': next_hops}} + else: + next_hop = {} + protocol = route.get('protocol', 'unicast') + if protocol == "blackhole": + next_hop['special-next-hop'] = "blackhole" + elif protocol == "unreachable": + next_hop['special-next-hop'] = "unreachable" + else: + if route.get('interfaceName'): + next_hop['outgoing-interface'] = route['interfaceName'] + if route.get('nexthop'): + next_hop[f'ietf-{proto}-unicast-routing:next-hop-address'] = route['nexthop'] + + new['next-hop'] = next_hop + + out['route'].append(new) + + insert(routes, 'routes', out) + + +def operational(): + out = { + "ietf-routing:routing": { + "ribs": { + "rib": [{ + "name": "ipv4", + "address-family": "ipv4" + }, { + "name": "ipv6", + "address-family": "ipv6" + }] + } + } + } + + ipv4routes = out['ietf-routing:routing']['ribs']['rib'][0] + ipv6routes = out['ietf-routing:routing']['ribs']['rib'][1] + add_protocol(ipv4routes, "ipv4") + add_protocol(ipv6routes, "ipv6") + + return out diff --git a/src/statd/python/yanger/yanger.py b/src/statd/python/yanger/yanger.py index e8319632..549b7a5d 100644 --- a/src/statd/python/yanger/yanger.py +++ b/src/statd/python/yanger/yanger.py @@ -6,7 +6,6 @@ import json import sys # (built-in module) import os import argparse -from re import match from datetime import datetime, timedelta, timezone from . import common @@ -20,29 +19,6 @@ def datetime_now(): return datetime(2023, 1, 1, 12, 0, 0, tzinfo=timezone.utc) return datetime.now(timezone.utc) -def get_proc_value(procfile): - """Return contents of /proc file, or None""" - try: - with open(procfile, 'r') as file: - data = file.read().strip() - return data - except FileNotFoundError: - # This is considered OK - return None - except IOError: - logger.error(f"failed reading from {procfile}") - - -def lookup(obj, *keys): - """This function returns a value from a nested json object""" - curr = obj - for key in keys: - if isinstance(curr, dict) and key in curr: - curr = curr[key] - else: - return None - return curr - def insert(obj, *path_and_value): """"This function inserts a value into a nested json object""" @@ -72,7 +48,7 @@ def run_cmd(cmd, testfile, default=None, check=True): output = result.stdout return output.splitlines() except subprocess.CalledProcessError as err: - logger.error(f"{err}") + common.LOG.error(f"{err}") if default is not None: return default raise @@ -90,713 +66,19 @@ def run_json_cmd(cmd, testfile, default=None, check=True): output = result.stdout data = json.loads(output) except subprocess.CalledProcessError as err: - logger.error(f"{err}") + common.LOG.error(f"{err}") if default is not None: return default raise except json.JSONDecodeError as err: if check is True: - logger.error("failed parsing JSON output of command: " + common.LOG.error("failed parsing JSON output of command: " f"{' '.join(cmd)}, error: {err}") if default is not None: return default raise return data -def json_get_yang_type(iface_in): - if iface_in['link_type'] == "loopback": - return "infix-if-type:loopback" - - if iface_in['link_type'] in ("gre", "gre6"): - return "infix-if-type:gre" - - if iface_in['link_type'] != "ether": - return "infix-if-type:other" - - if 'parentbus' in iface_in and iface_in['parentbus'] == "virtio": - return "infix-if-type:etherlike" - - if 'linkinfo' not in iface_in: - return "infix-if-type:ethernet" - - if 'info_kind' not in iface_in['linkinfo']: - return "infix-if-type:ethernet" - - if iface_in['linkinfo']['info_kind'] == "veth": - return "infix-if-type:veth" - - if iface_in['linkinfo']['info_kind'] in ("gretap", "ip6gretap"): - return "infix-if-type:gretap" - - if iface_in['linkinfo']['info_kind'] == "vlan": - return "infix-if-type:vlan" - - if iface_in['linkinfo']['info_kind'] == "bridge": - return "infix-if-type:bridge" - - if iface_in['linkinfo']['info_kind'] == "dsa": - return "infix-if-type:ethernet" - - if iface_in['linkinfo']['info_kind'] == "dummy": - return "infix-if-type:dummy" - - # Fallback - return "infix-if-type:ethernet" - - -def json_get_yang_origin(addr): - """Translate kernel IP address origin to YANG""" - xlate = { - "kernel_ll": "link-layer", - "kernel_ra": "link-layer", - "static": "static", - "dhcp": "dhcp", - "random": "random", - } - proto = addr['protocol'] - - if proto in ("kernel_ll", "kernel_ra"): - if "stable-privacy" in addr: - return "random" - - return xlate.get(proto, "other") - - - - -def iface_is_dsa(iface_in): - """Check if interface is a DSA/intra-switch port""" - if "linkinfo" not in iface_in: - return False - if "info_kind" not in iface_in['linkinfo']: - return False - if iface_in['linkinfo']['info_kind'] != "dsa": - return False - return True - - -def uptime2datetime(uptime): - """ - Convert uptime to YANG format (YYYY-MM-DDTHH:MM:SS+00:00) - - Handles the following input formats (frrtime): - HH:MM:SS - XdXXhXXm - XXwXdXXh - """ - h = m = s = 0 - - # Format HH:MM:SS - if match(r'^\d{2}:\d{2}:\d{2}$', uptime): - h, m, s = map(int, uptime.split(':')) - - # Format XdXXhXXm (days, hours, minutes) - elif match(r'^\d+d\d{2}h\d{2}m$', uptime): - days = int(uptime.split('d')[0]) - h = int(uptime.split('d')[1].split('h')[0]) - m = int(uptime.split('h')[1].split('m')[0]) - h += days * 24 - - # Format XwXdXXh (weeks, days, hours) - elif match(r'^\d{2}w\d{1}d\d{2}h$', uptime): - weeks = int(uptime.split('w')[0]) - days = int(uptime.split('w')[1].split('d')[0]) - h = int(uptime.split('d')[1].split('h')[0]) - h += weeks * 7 * 24 - h += days * 24 - - uptime_delta = timedelta(hours=h, minutes=m, seconds=s) - current_time = datetime_now() - last_updated = current_time - uptime_delta - date_timestd = last_updated.strftime('%Y-%m-%dT%H:%M:%S%z') - - return date_timestd[:-2] + ':' + date_timestd[-2:] - - -def get_routes(routes, proto, data): - """Populate routes from vtysh JSON output""" - - # Mapping of FRR protocol names to IETF routing-protocol - pmap = { - 'kernel': 'infix-routing:kernel', - 'connected': 'direct', - 'static': 'static', - 'ospf': 'ietf-ospf:ospfv2', - 'ospf6': 'ietf-ospf:ospfv3', - } - - out = {} - out["route"] = [] - - if proto == "ipv4": - default = "0.0.0.0/0" - host_prefix_length = "32" - else: - default = "::/0" - host_prefix_length = "128" - - for prefix, entries in data.items(): - for route in entries: - new = {} - dst = route.get('prefix', default) - if '/' not in dst: - dst = f"{dst}/{route.get('prefixLen', host_prefix_length)}" - - new[f'ietf-{proto}-unicast-routing:destination-prefix'] = dst - frr = route.get('protocol', 'infix-routing:kernel') - new['source-protocol'] = pmap.get(frr, 'infix-routing:kernel') - new['route-preference'] = route.get('distance', 0) - - # Metric only available in the model for OSPF routes - if 'ospf' in frr: - new['ietf-ospf:metric'] = route.get('metric', 0) - - # See https://datatracker.ietf.org/doc/html/rfc7951#section-6.9 - # for details on how presence leaves are encoded in JSON: [null] - if route.get('selected', False): - new['active'] = [None] - - new['last-updated'] = uptime2datetime(route.get('uptime', 0)) - installed = route.get('installed', False) - - next_hops = [] - for hop in route.get('nexthops', []): - next_hop = {} - if hop.get('ip'): - next_hop[f'ietf-{proto}-unicast-routing:address'] = hop['ip'] - elif hop.get('interfaceName'): - next_hop['outgoing-interface'] = hop['interfaceName'] - # See zebra/zebra_vty.c:re_status_outpupt_char() - if installed and hop.get('fib', False): - next_hop['infix-routing:installed'] = [None] - next_hops.append(next_hop) - - if next_hops: - new['next-hop'] = {'next-hop-list': {'next-hop': next_hops}} - else: - next_hop = {} - protocol = route.get('protocol', 'unicast') - if protocol == "blackhole": - next_hop['special-next-hop'] = "blackhole" - elif protocol == "unreachable": - next_hop['special-next-hop'] = "unreachable" - else: - if route.get('interfaceName'): - next_hop['outgoing-interface'] = route['interfaceName'] - if route.get('nexthop'): - next_hop[f'ietf-{proto}-unicast-routing:next-hop-address'] = route['nexthop'] - - new['next-hop'] = next_hop - - out['route'].append(new) - - insert(routes, 'routes', out) - - -def add_ipv4_route(routes): - """Fetch IPv4 routes from kernel and populate tree""" - data = run_json_cmd(['sudo', 'vtysh', '-c', "show ip route json"], - "vtysh-ip4-route.json", check=False, default={}) - get_routes(routes, "ipv4", data) - - -def add_ipv6_route(routes): - """Fetch IPv6 routes from kernel and populate tree""" - data = run_json_cmd(['sudo', 'vtysh', '-c', "show ipv6 route json"], - "vtysh-ip6-route.json", check=False, default={}) - get_routes(routes, "ipv6", data) - - -def get_bridge_port_pvid(ifname): - data = run_json_cmd(['bridge', '-j', 'vlan', 'show', 'dev', ifname], - f"bridge-vlan-show-dev-{ifname}.json") - if len(data) != 1: - return None - - iface = data[0] - - for vlan in iface['vlans']: - if 'flags' in vlan and 'PVID' in vlan['flags']: - return vlan['vlan'] - - return None - - -def get_bridge_port_stp_state(ifname): - data = run_json_cmd(['bridge', '-j', 'link', 'show', 'dev', ifname], - f"bridge-link-show-dev-{ifname}.json") - if len(data) != 1: - return None - - iface = data[0] - - states = ['disabled', 'listening', 'learning', 'forwarding', 'blocking'] - if 'state' in iface and iface['state'] in states: - return iface['state'] - - return None - - -def get_brport_multicast(ifname): - """Check if multicast snooping is enabled on bridge, default: nope""" - data = run_json_cmd(['mctl', 'show', 'igmp', 'json'], "igmp-status.json", - default={}, check=False) - multicast = {} - - if ifname in data.get('fast-leave-ports', []): - multicast["fast-leave"] = True - else: - multicast["fast-leave"] = False - - if ifname in data.get('multicast-router-ports', []): - multicast["router"] = "permanent" - else: - multicast["router"] = "auto" - - return multicast - - -# We always get all interfaces for two reasons. -# 1) To increase speed on large iron with many ports. -# 2) To simplify testing (single dummy file ip-link-show.json). -def get_ip_link(): - """Fetch interface link information from kernel""" - return run_json_cmd(['ip', '-s', '-d', '-j', 'link', 'show'], - "ip-link-show.json") - -def netns_get_ip_link(netns): - """Fetch interface link information from within a network namespace""" - return run_json_cmd(['ip', 'netns', 'exec', netns, 'ip', '-s', '-d', '-j', 'link', 'show'], - f"netns-{netns}-ip-link-show.json") - -def get_ip_addr(): - """Fetch interface address information from kernel""" - return run_json_cmd(['ip', '-j', 'addr', 'show'], - "ip-addr-show.json") - -def netns_get_ip_addr(netns): - """Fetch interface address information from within a network namespace""" - return run_json_cmd(['ip', 'netns', 'exec', netns, 'ip', '-j', 'addr', 'show'], - f"netns-{netns}-ip-addr-show.json") - -def get_netns_list(): - """Fetch a list of network namespaces""" - return run_json_cmd(['ip', '-j', 'netns', 'list'], - "netns-list.json") - -def netns_find_ifname(ifname): - """Find which network namespace owns ifname (if any)""" - for netns in get_netns_list(): - for iface in netns_get_ip_link(netns['name']): - if 'ifalias' in iface and iface['ifalias'] == ifname: - return netns['name'] - return None - -def netns_ifindex_to_ifname(ifindex): - """Look through all network namespaces for an interface index and return its name""" - for netns in get_netns_list(): - for iface in netns_get_ip_link(netns['name']): - if iface['ifindex'] == ifindex: - if 'ifalias' in iface: - return iface['ifalias'] - if 'ifname' in iface: - return iface['ifname'] - return None - - return None - -def add_bridge_port_common(ifname, iface_in, iface_out): - li = iface_in.get("linkinfo", {}) - if not (li.get("info_slave_kind") == "bridge" or \ - li.get("info_kind") == "bridge"): - return - - pvid = get_bridge_port_pvid(ifname) - if pvid is not None: - insert(iface_out, "infix-interfaces:bridge-port", "pvid", pvid) - -def add_bridge_port_lower(ifname, iface_in, iface_out): - li = iface_in.get("linkinfo", {}) - if not li.get("info_slave_kind") == "bridge": - return - - insert(iface_out, "infix-interfaces:bridge-port", "bridge", iface_in['master']) - - stp_state = get_bridge_port_stp_state(ifname) - if stp_state is not None: - insert(iface_out, "infix-interfaces:bridge-port", "stp-state", stp_state) - - multicast = get_brport_multicast(ifname) - insert(iface_out, "infix-interfaces:bridge-port", "multicast", multicast) - - -def add_gre(iface_in, iface_out): - if 'link_type' in iface_in: - val = json_get_yang_type(iface_in) - if val != "infix-if-type:gre" and val != "infix-if-type:gretap": - return; - gre={} - info_data=iface_in.get("linkinfo", {}).get("info_data", {}) - gre["local"] = info_data.get("local") - gre["remote"] = info_data.get("remote") - insert(iface_out, "infix-interfaces:gre", gre) - - -def add_ip_link(ifname, iface_in, iface_out): - if 'ifname' in iface_in: - iface_out['name'] = ifname - - if 'ifindex' in iface_in: - iface_out['if-index'] = iface_in['ifindex'] - - if 'ifalias' in iface_in: - iface_out['description'] = iface_in['ifalias'] - - if 'address' in iface_in and not "POINTOPOINT" in iface_in["flags"]: - iface_out['phys-address'] = iface_in['address'] - - add_bridge_port_common(ifname, iface_in, iface_out) - add_bridge_port_lower(ifname, iface_in, iface_out) - - if not iface_is_dsa(iface_in): - if iface_in.get('link'): - insert(iface_out, "infix-interfaces:vlan", "lower-layer-if", iface_in['link']) - elif 'link_index' in iface_in: - # 'link_index' is the only reference we have if the link iface is in a namespace - lower = netns_ifindex_to_ifname(iface_in['link_index']) - if lower: - insert(iface_out, "infix-interfaces:vlan", "lower-layer-if", lower) - - if 'flags' in iface_in: - iface_out['admin-status'] = "up" if "UP" in iface_in['flags'] else "down" - - if 'operstate' in iface_in: - xlate = { - "DOWN": "down", - "UP": "up", - "DORMANT": "dormant", - "TESTING": "testing", - "LOWERLAYERDOWN": "lower-layer-down", - "NOTPRESENT": "not-present" - } - val = xlate.get(iface_in['operstate'], "unknown") - iface_out['oper-status'] = val - - if 'link_type' in iface_in: - val = json_get_yang_type(iface_in) - iface_out['type'] = val - add_gre(iface_in, iface_out) - - val = lookup(iface_in, "stats64", "rx", "bytes") - if val is not None: - insert(iface_out, "statistics", "out-octets", str(val)) - - val = lookup(iface_in, "stats64", "tx", "bytes") - if val is not None: - insert(iface_out, "statistics", "in-octets", str(val)) - - -def add_ip_addr(ifname, iface_in, iface_out): - if 'mtu' in iface_in and ifname != "lo": - insert(iface_out, "ietf-ip:ipv4", "mtu", iface_in['mtu']) - - # We avoid importing os to check if the file exists (for performance) - val = get_proc_value(f"/proc/sys/net/ipv6/conf/{ifname}/mtu") - if val is not None: - insert(iface_out, "ietf-ip:ipv6", "mtu", int(val)) - - if 'addr_info' in iface_in: - inet = [] - inet6 = [] - - for addr in iface_in['addr_info']: - new = {} - - if 'family' not in addr: - logger.error("'family' missing from 'addr_info'") - continue - - if 'local' in addr: - new['ip'] = addr['local'] - if 'prefixlen' in addr: - new['prefix-length'] = addr['prefixlen'] - if 'protocol' in addr: - new['origin'] = json_get_yang_origin(addr) - - if addr['family'] == "inet": - inet.append(new) - elif addr['family'] == "inet6": - inet6.append(new) - else: - logger.error("invalid 'family' in 'addr_info'") - sys.exit(1) - - insert(iface_out, "ietf-ip:ipv4", "address", inet) - insert(iface_out, "ietf-ip:ipv6", "address", inet6) - - -def add_ethtool_groups(ifname, iface_out): - """Fetch interface counters from kernel (need new JSON format!)""" - cmd = ['ethtool', '--json', '-S', ifname, '--all-groups'] - try: - data = run_json_cmd(cmd, f"ethtool-groups-{ifname}.json") - if len(data) != 1: - logger.warning("%s: no counters available, skipping.", ifname) - return - except subprocess.CalledProcessError: - # Allow comand to fail, not all NICs support --json yet - return - - iface_in = data[0] - - # TODO: room for improvement, the "frame" creation could be more dynamic. - if "eth-mac" in iface_in or "rmon" in iface_in: - insert(iface_out, "ieee802-ethernet-interface:ethernet", "statistics", "frame", {}) - frame = iface_out['ieee802-ethernet-interface:ethernet']['statistics']['frame'] - - if "eth-mac" in iface_in: - mac_in = iface_in['eth-mac'] - - if "FramesTransmittedOK" in mac_in: - frame['out-frames'] = str(mac_in['FramesTransmittedOK']) - if "MulticastFramesXmittedOK" in mac_in: - frame['out-multicast-frames'] = str(mac_in['MulticastFramesXmittedOK']) - if "BroadcastFramesXmittedOK" in mac_in: - frame['out-broadcast-frames'] = str(mac_in['BroadcastFramesXmittedOK']) - if "FramesReceivedOK" in mac_in: - frame['in-frames'] = str(mac_in['FramesReceivedOK']) - if "MulticastFramesReceivedOK" in mac_in: - frame['in-multicast-frames'] = str(mac_in['MulticastFramesReceivedOK']) - if "BroadcastFramesReceivedOK" in mac_in: - frame['in-broadcast-frames'] = str(mac_in['BroadcastFramesReceivedOK']) - if "FrameCheckSequenceErrors" in mac_in: - frame['in-error-fcs-frames'] = str(mac_in['FrameCheckSequenceErrors']) - if "FramesLostDueToIntMACRcvError" in mac_in: - frame['in-error-mac-internal-frames'] = str(mac_in['FramesLostDueToIntMACRcvError']) - - if "OctetsTransmittedOK" in mac_in: - frame['infix-ethernet-interface:out-good-octets'] = str(mac_in['OctetsTransmittedOK']) - if "OctetsReceivedOK" in mac_in: - frame['infix-ethernet-interface:in-good-octets'] = str(mac_in['OctetsReceivedOK']) - - tot = 0 - found = False - if "FramesReceivedOK" in mac_in: - tot += mac_in['FramesReceivedOK'] - found = True - if "FrameCheckSequenceErrors" in mac_in: - tot += mac_in['FrameCheckSequenceErrors'] - found = True - if "FramesLostDueToIntMACRcvError" in mac_in: - tot += mac_in['FramesLostDueToIntMACRcvError'] - found = True - if "AlignmentErrors" in mac_in: - tot += mac_in['AlignmentErrors'] - found = True - if "etherStatsOversizePkts" in mac_in: - tot += mac_in['etherStatsOversizePkts'] - found = True - if "etherStatsJabbers" in mac_in: - tot += mac_in['etherStatsJabbers'] - found = True - if found: - frame['in-total-frames'] = str(tot) - - if "rmon" in iface_in: - rmon_in = iface_in['rmon'] - - if "undersize_pkts" in rmon_in: - frame['in-error-undersize-frames'] = str(rmon_in['undersize_pkts']) - - tot = 0 - found = False - if "etherStatsJabbers" in rmon_in: - tot += rmon_in['etherStatsJabbers'] - found = True - if "etherStatsOversizePkts" in rmon_in: - tot += rmon_in['etherStatsOversizePkts'] - found = True - if found: - frame['in-error-oversize-frames'] = str(tot) - -def add_ethtool_std(ifname, iface_out): - """Fetch interface speed/duplex/autoneg from kernel""" - keys = ['Speed', 'Duplex', 'Auto-negotiation'] - result = {} - - lines = run_cmd(['ethtool', ifname], f"ethtool-{ifname}.txt") - for line in lines: - line = line.strip() - key = line.split(':', 1)[0].strip() - if key in keys: - key, value = line.split(':', 1) - result[key.strip()] = value.strip() - - if "Auto-negotiation" in result: - if result['Auto-negotiation'] == "on": - insert(iface_out, "ieee802-ethernet-interface:ethernet", "auto-negotiation", "enable", True) - else: - insert(iface_out, "ieee802-ethernet-interface:ethernet", "auto-negotiation", "enable", False) - - if "Duplex" in result: - if result['Duplex'] == "Half": - insert(iface_out, "ieee802-ethernet-interface:ethernet", "duplex", "half") - elif result['Duplex'] == "Full": - insert(iface_out, "ieee802-ethernet-interface:ethernet", "duplex", "full") - else: - insert(iface_out, "ieee802-ethernet-interface:ethernet", "duplex", "unknown") - - if "Speed" in result and result['Speed'] != "Unknown!": - # Avoid importing re (performance) - num = ''.join(filter(str.isdigit, result['Speed'])) - if num: - num = round((int(num) / 1000), 3) - insert(iface_out, "ieee802-ethernet-interface:ethernet", "speed", str(num)) - -def get_querier_data(querier_data): - multicast={} - - if not querier_data: - multicast["snooping"] = False - return multicast - multicast["snooping"] = True - if(querier_data.get("query-interval")): - multicast["query-interval"] = querier_data["query-interval"] - - return multicast - -def get_multicast_filters(filters): - multicast_filters=[] - for f in filters: - multicast_filter={} - multicast_filter["group"] = f["group"] - multicast_filter["ports"] = [] - for p in f["ports"]: - port={} - port["port"] = p - multicast_filter["ports"].append(port) - multicast_filters.append(multicast_filter) - return multicast_filters - -def add_mdb_to_bridge(brname, iface_out, mc_status): - filters = [entry for entry in mc_status.get("multicast-groups", []) if entry.get('vid') == None and entry.get('bridge') == brname] - querier = next((querier for querier in mc_status.get('multicast-queriers', []) if (querier.get("interface", "") == brname) and (querier.get("vid") is None)), None) - multicast = get_querier_data(querier) - multicast_filters = get_multicast_filters(filters) - insert(iface_out, "infix-interfaces:bridge", "multicast", multicast) - insert(iface_out, "infix-interfaces:bridge", "multicast-filters", "multicast-filter", multicast_filters) - -def add_container_ifaces(yang_ifaces): - """Add all podman interfaces with limited data""" - interfaces={} - try: - containers = run_json_cmd(['podman', 'ps', '--format', 'json'], "podman-ps.json", default=[]) - except Exception as e: - logging.error(f"Error, unable to run podman: {e}") - return - - for container in containers: - name = container.get('Names', ['Unknown'])[0] - networks = container.get('Networks', []) - - for network in networks: - if not network in interfaces: - interfaces[network] = [] - if name not in interfaces[network]: - interfaces[network].append(name) - - for ifname, containers in interfaces.items(): - iface_out = {} - iface_out['name'] = ifname - iface_out['type'] = "infix-if-type:other" # Fallback - insert(iface_out, "infix-interfaces:container-network", "containers", containers) - - netns = netns_find_ifname(ifname) - if netns is not None: - ip_link_data = netns_get_ip_link(netns) - ip_link_data = next((d for d in ip_link_data if d.get('ifalias') == ifname), None) - add_ip_link(ifname, ip_link_data, iface_out) - - yang_ifaces.append(iface_out) - -# Helper function to add tagged/untagged interfaces to a vlan dict in a list -def _add_vlan_iface(vlans, multicast_filter, multicast, vid, key, val): - for d in vlans: - if d['vid'] == vid: - if key in d: - d[key].append(val) - else: - d[key] = [val] - return - - vlans.append({'vid': vid, "multicast-filters": {"multicast-filter": multicast_filter}, "multicast": multicast, key: [val]}) - -def add_vlans_to_bridge(brname, iface_out, mc_status): - slaves = [] # Contains all interfaces that has this bridge as 'master' - for iface in run_json_cmd(['bridge', '-j', 'link'], "bridge-link.json"): - if "master" in iface and iface['master'] == brname: - slaves.append(iface['ifname']) - - vlans = [] # Contains all vlans and slaves belonging to this bridge - for iface in run_json_cmd(['bridge', '-j', 'vlan'], "bridge-vlan.json"): - if iface['ifname'] not in slaves and iface['ifname'] != brname: - continue - for vlan in iface['vlans']: - querier = next((querier for querier in mc_status.get('multicast-queriers', []) if (querier.get("vid") == vlan['vlan'])), None) - filters = [entry for entry in mc_status.get("multicast-groups", []) if (entry.get("vid") == vlan["vlan"])] - if 'flags' in vlan and 'Egress Untagged' in vlan['flags']: - _add_vlan_iface(vlans, get_multicast_filters(filters), get_querier_data(querier), vlan['vlan'], 'untagged', iface['ifname']) - else: - _add_vlan_iface(vlans, get_multicast_filters(filters), get_querier_data(querier), vlan['vlan'], 'tagged', iface['ifname']) - - insert(iface_out, "infix-interfaces:bridge", "vlans", "vlan", vlans) - -def get_iface_data(ifname, ip_link_data, ip_addr_data): - iface_out = {} - - add_ip_link(ifname, ip_link_data, iface_out) - add_ip_addr(ifname, ip_addr_data, iface_out) - - if 'type' in iface_out and iface_out['type'] == "infix-if-type:ethernet": - add_ethtool_groups(ifname, iface_out) - add_ethtool_std(ifname, iface_out) - - if 'type' in iface_out and iface_out['type'] == "infix-if-type:bridge": - # Fail silent, multicast snooping may not be enabled on bridge - mc_status = run_json_cmd(['mctl', '-p', 'show', 'igmp', 'json'], - "igmp-status.json", default={}, - check=False) - - add_vlans_to_bridge(ifname, iface_out, mc_status) - add_mdb_to_bridge(ifname, iface_out, mc_status) - - return iface_out - -def _add_interface(ifname, ip_link_data, ip_addr_data, yang_ifaces): - # We expect both ip addr and link data to exist. - if not ip_link_data or not ip_addr_data: - return - - # Skip internal interfaces. - if 'group' in ip_link_data and ip_link_data['group'] == "internal": - return - - yang_ifaces.append(get_iface_data(ifname, ip_link_data, ip_addr_data)) - -def add_interface(ifname, yang_ifaces): - ip_link_data = get_ip_link() - ip_addr_data = get_ip_addr() - - if ifname: - ip_link_data = next((d for d in ip_link_data if d.get('ifname') == ifname), None) - ip_addr_data = next((d for d in ip_addr_data if d.get('ifname') == ifname), None) - _add_interface(ifname, ip_link_data, ip_addr_data, yang_ifaces) - else: - for link in ip_link_data: - addr = next((d for d in ip_addr_data if d.get('ifname') == link["ifname"]), None) - _add_interface(link["ifname"], link, addr, yang_ifaces) - - add_container_ifaces(yang_ifaces) def main(): global TESTPATH @@ -810,7 +92,7 @@ def main(): # Set up syslog output for critical errors to aid debugging - logger = logging.getLogger('yanger') + common.LOG = logging.getLogger('yanger') if os.path.exists('/dev/log'): log = logging.handlers.SysLogHandler(address='/dev/log') else: @@ -819,9 +101,8 @@ def main(): fmt = logging.Formatter('%(name)s[%(process)d]: %(message)s') log.setFormatter(fmt) - logger.setLevel(logging.INFO) - logger.addHandler(log) - common.LOG = logger + common.LOG.setLevel(logging.INFO) + common.LOG.addHandler(log) if args.test: TESTPATH = args.test @@ -831,33 +112,11 @@ def main(): host.HOST = host.Localhost() if args.model == 'ietf-interfaces': - yang_data = { - "ietf-interfaces:interfaces": { - "interface": [] - } - } - add_interface(args.param, yang_data['ietf-interfaces:interfaces']['interface']) - + from . import ietf_interfaces + yang_data = ietf_interfaces.operational(args.param) elif args.model == 'ietf-routing': - yang_data = { - "ietf-routing:routing": { - "ribs": { - "rib": [{ - "name": "ipv4", - "address-family": "ipv4" - }, { - "name": "ipv6", - "address-family": "ipv6" - }] - } - } - } - - ipv4routes = yang_data['ietf-routing:routing']['ribs']['rib'][0] - ipv6routes = yang_data['ietf-routing:routing']['ribs']['rib'][1] - add_ipv4_route(ipv4routes) - add_ipv6_route(ipv6routes) - + from . import ietf_routing + yang_data = ietf_routing.operational() elif args.model == 'ietf-ospf': from . import ietf_ospf yang_data = ietf_ospf.operational() diff --git a/test/case/cli/system-output/bridge-link.json b/test/case/cli/system-output/run/bridge_-j_link similarity index 100% rename from test/case/cli/system-output/bridge-link.json rename to test/case/cli/system-output/run/bridge_-j_link diff --git a/test/case/cli/system-output/bridge-link-show-dev-e0.json b/test/case/cli/system-output/run/bridge_-j_link_show_dev_e0 similarity index 100% rename from test/case/cli/system-output/bridge-link-show-dev-e0.json rename to test/case/cli/system-output/run/bridge_-j_link_show_dev_e0 diff --git a/test/case/cli/system-output/bridge-link-show-dev-e1.json b/test/case/cli/system-output/run/bridge_-j_link_show_dev_e1 similarity index 100% rename from test/case/cli/system-output/bridge-link-show-dev-e1.json rename to test/case/cli/system-output/run/bridge_-j_link_show_dev_e1 diff --git a/test/case/cli/system-output/bridge-link-show-dev-e2.json b/test/case/cli/system-output/run/bridge_-j_link_show_dev_e2 similarity index 100% rename from test/case/cli/system-output/bridge-link-show-dev-e2.json rename to test/case/cli/system-output/run/bridge_-j_link_show_dev_e2 diff --git a/test/case/cli/system-output/bridge-vlan.json b/test/case/cli/system-output/run/bridge_-j_vlan similarity index 100% rename from test/case/cli/system-output/bridge-vlan.json rename to test/case/cli/system-output/run/bridge_-j_vlan diff --git a/test/case/cli/system-output/bridge-vlan-show-dev-br0.json b/test/case/cli/system-output/run/bridge_-j_vlan_show_dev_br0 similarity index 100% rename from test/case/cli/system-output/bridge-vlan-show-dev-br0.json rename to test/case/cli/system-output/run/bridge_-j_vlan_show_dev_br0 diff --git a/test/case/cli/system-output/bridge-vlan-show-dev-br1.json b/test/case/cli/system-output/run/bridge_-j_vlan_show_dev_br1 similarity index 100% rename from test/case/cli/system-output/bridge-vlan-show-dev-br1.json rename to test/case/cli/system-output/run/bridge_-j_vlan_show_dev_br1 diff --git a/test/case/cli/system-output/bridge-vlan-show-dev-e0.json b/test/case/cli/system-output/run/bridge_-j_vlan_show_dev_e0 similarity index 100% rename from test/case/cli/system-output/bridge-vlan-show-dev-e0.json rename to test/case/cli/system-output/run/bridge_-j_vlan_show_dev_e0 diff --git a/test/case/cli/system-output/bridge-vlan-show-dev-e1.json b/test/case/cli/system-output/run/bridge_-j_vlan_show_dev_e1 similarity index 100% rename from test/case/cli/system-output/bridge-vlan-show-dev-e1.json rename to test/case/cli/system-output/run/bridge_-j_vlan_show_dev_e1 diff --git a/test/case/cli/system-output/bridge-vlan-show-dev-e2.json b/test/case/cli/system-output/run/bridge_-j_vlan_show_dev_e2 similarity index 100% rename from test/case/cli/system-output/bridge-vlan-show-dev-e2.json rename to test/case/cli/system-output/run/bridge_-j_vlan_show_dev_e2 diff --git a/test/case/cli/system-output/ethtool-groups-br0.json b/test/case/cli/system-output/run/ethtool_--json_-S_br0_--all-groups similarity index 100% rename from test/case/cli/system-output/ethtool-groups-br0.json rename to test/case/cli/system-output/run/ethtool_--json_-S_br0_--all-groups diff --git a/test/case/cli/system-output/ethtool-groups-dsa0.json b/test/case/cli/system-output/run/ethtool_--json_-S_dsa0_--all-groups similarity index 100% rename from test/case/cli/system-output/ethtool-groups-dsa0.json rename to test/case/cli/system-output/run/ethtool_--json_-S_dsa0_--all-groups diff --git a/test/case/cli/system-output/ethtool-groups-e0.json b/test/case/cli/system-output/run/ethtool_--json_-S_e0_--all-groups similarity index 100% rename from test/case/cli/system-output/ethtool-groups-e0.json rename to test/case/cli/system-output/run/ethtool_--json_-S_e0_--all-groups diff --git a/test/case/cli/system-output/ethtool-groups-e1.json b/test/case/cli/system-output/run/ethtool_--json_-S_e1_--all-groups similarity index 100% rename from test/case/cli/system-output/ethtool-groups-e1.json rename to test/case/cli/system-output/run/ethtool_--json_-S_e1_--all-groups diff --git a/test/case/cli/system-output/ethtool-groups-e2.json b/test/case/cli/system-output/run/ethtool_--json_-S_e2_--all-groups similarity index 100% rename from test/case/cli/system-output/ethtool-groups-e2.json rename to test/case/cli/system-output/run/ethtool_--json_-S_e2_--all-groups diff --git a/test/case/cli/system-output/ethtool-groups-e3.json b/test/case/cli/system-output/run/ethtool_--json_-S_e3_--all-groups similarity index 100% rename from test/case/cli/system-output/ethtool-groups-e3.json rename to test/case/cli/system-output/run/ethtool_--json_-S_e3_--all-groups diff --git a/test/case/cli/system-output/ethtool-groups-e4.json b/test/case/cli/system-output/run/ethtool_--json_-S_e4_--all-groups similarity index 100% rename from test/case/cli/system-output/ethtool-groups-e4.json rename to test/case/cli/system-output/run/ethtool_--json_-S_e4_--all-groups diff --git a/test/case/cli/system-output/ethtool-br0.txt b/test/case/cli/system-output/run/ethtool_br0 similarity index 100% rename from test/case/cli/system-output/ethtool-br0.txt rename to test/case/cli/system-output/run/ethtool_br0 diff --git a/test/case/cli/system-output/ethtool-dsa0.txt b/test/case/cli/system-output/run/ethtool_dsa0 similarity index 100% rename from test/case/cli/system-output/ethtool-dsa0.txt rename to test/case/cli/system-output/run/ethtool_dsa0 diff --git a/test/case/cli/system-output/ethtool-e0.txt b/test/case/cli/system-output/run/ethtool_e0 similarity index 100% rename from test/case/cli/system-output/ethtool-e0.txt rename to test/case/cli/system-output/run/ethtool_e0 diff --git a/test/case/cli/system-output/ethtool-e1.txt b/test/case/cli/system-output/run/ethtool_e1 similarity index 100% rename from test/case/cli/system-output/ethtool-e1.txt rename to test/case/cli/system-output/run/ethtool_e1 diff --git a/test/case/cli/system-output/ethtool-e2.txt b/test/case/cli/system-output/run/ethtool_e2 similarity index 100% rename from test/case/cli/system-output/ethtool-e2.txt rename to test/case/cli/system-output/run/ethtool_e2 diff --git a/test/case/cli/system-output/ethtool-e3.txt b/test/case/cli/system-output/run/ethtool_e3 similarity index 100% rename from test/case/cli/system-output/ethtool-e3.txt rename to test/case/cli/system-output/run/ethtool_e3 diff --git a/test/case/cli/system-output/ethtool-e4.txt b/test/case/cli/system-output/run/ethtool_e4 similarity index 100% rename from test/case/cli/system-output/ethtool-e4.txt rename to test/case/cli/system-output/run/ethtool_e4 diff --git a/test/case/cli/system-output/ip-addr-show.json b/test/case/cli/system-output/run/ip_-j_addr_show similarity index 100% rename from test/case/cli/system-output/ip-addr-show.json rename to test/case/cli/system-output/run/ip_-j_addr_show diff --git a/test/case/cli/system-output/netns-list.json b/test/case/cli/system-output/run/ip_-j_netns_list similarity index 100% rename from test/case/cli/system-output/netns-list.json rename to test/case/cli/system-output/run/ip_-j_netns_list diff --git a/test/case/cli/system-output/ip-link-show.json b/test/case/cli/system-output/run/ip_-s_-d_-j_link_show similarity index 100% rename from test/case/cli/system-output/ip-link-show.json rename to test/case/cli/system-output/run/ip_-s_-d_-j_link_show diff --git a/test/case/cli/system-output/netns-57ff63cb-ip-addr-show.json b/test/case/cli/system-output/run/ip_netns_exec_57ff63cb_ip_-j_addr_show similarity index 100% rename from test/case/cli/system-output/netns-57ff63cb-ip-addr-show.json rename to test/case/cli/system-output/run/ip_netns_exec_57ff63cb_ip_-j_addr_show diff --git a/test/case/cli/system-output/netns-57ff63cb-ip-link-show.json b/test/case/cli/system-output/run/ip_netns_exec_57ff63cb_ip_-s_-d_-j_link_show similarity index 100% rename from test/case/cli/system-output/netns-57ff63cb-ip-link-show.json rename to test/case/cli/system-output/run/ip_netns_exec_57ff63cb_ip_-s_-d_-j_link_show diff --git a/test/case/cli/system-output/netns-db5ad90e-ip-addr-show.json b/test/case/cli/system-output/run/ip_netns_exec_db5ad90e_ip_-j_addr_show similarity index 100% rename from test/case/cli/system-output/netns-db5ad90e-ip-addr-show.json rename to test/case/cli/system-output/run/ip_netns_exec_db5ad90e_ip_-j_addr_show diff --git a/test/case/cli/system-output/netns-db5ad90e-ip-link-show.json b/test/case/cli/system-output/run/ip_netns_exec_db5ad90e_ip_-s_-d_-j_link_show similarity index 100% rename from test/case/cli/system-output/netns-db5ad90e-ip-link-show.json rename to test/case/cli/system-output/run/ip_netns_exec_db5ad90e_ip_-s_-d_-j_link_show diff --git a/test/case/cli/system-output/igmp-status.json b/test/case/cli/system-output/run/mctl_-p_show_igmp_json similarity index 100% rename from test/case/cli/system-output/igmp-status.json rename to test/case/cli/system-output/run/mctl_-p_show_igmp_json diff --git a/test/case/cli/system-output/vtysh-ip4-route.json b/test/case/cli/system-output/run/vtysh_-c_show-ip-route-json similarity index 100% rename from test/case/cli/system-output/vtysh-ip4-route.json rename to test/case/cli/system-output/run/vtysh_-c_show-ip-route-json diff --git a/test/case/cli/system-output/vtysh-ip6-route.json b/test/case/cli/system-output/run/vtysh_-c_show-ipv6-route-json similarity index 100% rename from test/case/cli/system-output/vtysh-ip6-route.json rename to test/case/cli/system-output/run/vtysh_-c_show-ipv6-route-json From 547a9cd632d18d1ab9a43e7d22adf626319e1352 Mon Sep 17 00:00:00 2001 From: Tobias Waldekranz Date: Thu, 9 Jan 2025 15:59:59 +0100 Subject: [PATCH 10/12] yanger: Remove dead code remaining after modularization --- src/statd/python/yanger/__main__.py | 64 ++++++++++++- src/statd/python/yanger/yanger.py | 140 ---------------------------- 2 files changed, 62 insertions(+), 142 deletions(-) delete mode 100644 src/statd/python/yanger/yanger.py diff --git a/src/statd/python/yanger/__main__.py b/src/statd/python/yanger/__main__.py index bc9fc135..9ab8d0e7 100644 --- a/src/statd/python/yanger/__main__.py +++ b/src/statd/python/yanger/__main__.py @@ -1,3 +1,63 @@ -from .yanger import main +import logging +import logging.handlers +import subprocess +import json +import sys # (built-in module) +import os +import argparse -main() +from . import common +from . import host + +def main(): + parser = argparse.ArgumentParser(description="YANG data creator") + parser.add_argument("model", help="YANG Model") + parser.add_argument("-p", "--param", default=None, help="Model dependent parameter") + parser.add_argument("-t", "--test", default=None, help="Test data base path") + args = parser.parse_args() + + + # Set up syslog output for critical errors to aid debugging + common.LOG = logging.getLogger('yanger') + if os.path.exists('/dev/log'): + log = logging.handlers.SysLogHandler(address='/dev/log') + else: + # Use /dev/null as a fallback for unit tests + log = logging.FileHandler('/dev/null') + + fmt = logging.Formatter('%(name)s[%(process)d]: %(message)s') + log.setFormatter(fmt) + common.LOG.setLevel(logging.INFO) + common.LOG.addHandler(log) + + if args.test: + host.HOST = host.Testhost(args.test) + else: + host.HOST = host.Localhost() + + if args.model == 'ietf-interfaces': + from . import ietf_interfaces + yang_data = ietf_interfaces.operational(args.param) + elif args.model == 'ietf-routing': + from . import ietf_routing + yang_data = ietf_routing.operational() + elif args.model == 'ietf-ospf': + from . import ietf_ospf + yang_data = ietf_ospf.operational() + elif args.model == 'ietf-hardware': + from . import ietf_hardware + yang_data = ietf_hardware.operational() + elif args.model == 'infix-containers': + from . import infix_containers + yang_data = infix_containers.operational() + elif args.model == 'ietf-system': + from . import ietf_system + yang_data = ietf_system.operational() + else: + common.LOG.warning(f"Unsupported model {args.model}", file=sys.stderr) + sys.exit(1) + + print(json.dumps(yang_data, indent=2)) + +if __name__ == "__main__": + main() diff --git a/src/statd/python/yanger/yanger.py b/src/statd/python/yanger/yanger.py deleted file mode 100644 index 549b7a5d..00000000 --- a/src/statd/python/yanger/yanger.py +++ /dev/null @@ -1,140 +0,0 @@ -#!/usr/bin/env python3 -import logging -import logging.handlers -import subprocess -import json -import sys # (built-in module) -import os -import argparse -from datetime import datetime, timedelta, timezone - -from . import common -from . import host - -TESTPATH = "" -logger = None - -def datetime_now(): - if TESTPATH: - return datetime(2023, 1, 1, 12, 0, 0, tzinfo=timezone.utc) - return datetime.now(timezone.utc) - - -def insert(obj, *path_and_value): - """"This function inserts a value into a nested json object""" - if len(path_and_value) < 2: - raise ValueError("Error: insert() takes at least two args") - - *path, value = path_and_value - - curr = obj - for key in path[:-1]: - if key not in curr or not isinstance(curr[key], dict): - curr[key] = {} - curr = curr[key] - - curr[path[-1]] = value - - -def run_cmd(cmd, testfile, default=None, check=True): - """Run a command (array of args) and return an array of lines""" - - if TESTPATH and testfile: - cmd = ['cat', os.path.join(TESTPATH, testfile)] - - try: - result = subprocess.run(cmd, check=check, stderr=subprocess.DEVNULL, - stdout=subprocess.PIPE, text=True) - output = result.stdout - return output.splitlines() - except subprocess.CalledProcessError as err: - common.LOG.error(f"{err}") - if default is not None: - return default - raise - - -def run_json_cmd(cmd, testfile, default=None, check=True): - """Run a command (array of args) with JSON output and return the JSON""" - - if TESTPATH and testfile: - cmd = ['cat', os.path.join(TESTPATH, testfile)] - - try: - result = subprocess.run(cmd, check=check, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, text=True) - output = result.stdout - data = json.loads(output) - except subprocess.CalledProcessError as err: - common.LOG.error(f"{err}") - if default is not None: - return default - raise - except json.JSONDecodeError as err: - if check is True: - common.LOG.error("failed parsing JSON output of command: " - f"{' '.join(cmd)}, error: {err}") - if default is not None: - return default - raise - return data - - -def main(): - global TESTPATH - global logger - - parser = argparse.ArgumentParser(description="YANG data creator") - parser.add_argument("model", help="YANG Model") - parser.add_argument("-p", "--param", default=None, help="Model dependent parameter") - parser.add_argument("-t", "--test", default=None, help="Test data base path") - args = parser.parse_args() - - - # Set up syslog output for critical errors to aid debugging - common.LOG = logging.getLogger('yanger') - if os.path.exists('/dev/log'): - log = logging.handlers.SysLogHandler(address='/dev/log') - else: - # Use /dev/null as a fallback for unit tests - log = logging.FileHandler('/dev/null') - - fmt = logging.Formatter('%(name)s[%(process)d]: %(message)s') - log.setFormatter(fmt) - common.LOG.setLevel(logging.INFO) - common.LOG.addHandler(log) - - if args.test: - TESTPATH = args.test - host.HOST = host.Testhost(args.test) - else: - TESTPATH = "" - host.HOST = host.Localhost() - - if args.model == 'ietf-interfaces': - from . import ietf_interfaces - yang_data = ietf_interfaces.operational(args.param) - elif args.model == 'ietf-routing': - from . import ietf_routing - yang_data = ietf_routing.operational() - elif args.model == 'ietf-ospf': - from . import ietf_ospf - yang_data = ietf_ospf.operational() - elif args.model == 'ietf-hardware': - from . import ietf_hardware - yang_data = ietf_hardware.operational() - elif args.model == 'infix-containers': - from . import infix_containers - yang_data = infix_containers.operational() - elif args.model == 'ietf-system': - from . import ietf_system - yang_data = ietf_system.operational() - else: - logger.warning(f"Unsupported model {args.model}", file=sys.stderr) - sys.exit(1) - - print(json.dumps(yang_data, indent=2)) - - -if __name__ == "__main__": - main() From 805ddf6c9273d9f5b55e2c430a639c57beef37c9 Mon Sep 17 00:00:00 2001 From: Tobias Waldekranz Date: Wed, 8 Jan 2025 14:16:13 +0100 Subject: [PATCH 11/12] utils: Make srop's output directory resolution reusable --- utils/libix.sh | 33 +++++++++++++++++++++++++++++++++ utils/srop | 26 +++----------------------- 2 files changed, 36 insertions(+), 23 deletions(-) create mode 100644 utils/libix.sh diff --git a/utils/libix.sh b/utils/libix.sh new file mode 100644 index 00000000..0725262c --- /dev/null +++ b/utils/libix.sh @@ -0,0 +1,33 @@ + +resolve_o() +{ + [ -n "$O" ] && return + + if [ -f ".config" ] && [ -d "output" ]; then + # Buildroot + O=./output + elif [ -f "output/.config" ]; then + # BR2_EXTERNAL + O=./output + elif [ -f ".config" ] && [ -d "host" ]; then + # Called from inside output/ directory + O=. + else + echo "*** Error: cannot find Buildroot output dir!" >&2 + exit 1 + fi +} + +resolve_host_dir() +{ + [ -n "$HOST_DIR" ] && return + + resolve_o || exit 1 + + if ! [ -d "$O/host" ]; then + echo "*** Error: cannot find Buildroot host binaries dir!" >&2 + exit 1 + fi + + HOST_DIR="$O/host" +} diff --git a/utils/srop b/utils/srop index e2e58a54..a0a7dfad 100755 --- a/utils/srop +++ b/utils/srop @@ -1,6 +1,8 @@ #!/bin/sh # Interact with sysrepo in a Buildroot setup +. $(dirname $(readlink -f "$0"))/libix.sh + usage() { cat <&2 - exit 1 - fi -fi - -if [ -d "$O/host" ]; then - HOST_DIR="$O/host" -else - echo "*** Error: cannot find Buildroot host binaries dir!" >&2 - exit 1 -fi +resolve_host_dir MOD="$O/target/usr/share/yang/modules/confd/" CTL="$HOST_DIR/bin/sysrepoctl" From 41b96e8a01e5832da099b626cf1fa5d584f7e4de Mon Sep 17 00:00:00 2001 From: Tobias Waldekranz Date: Wed, 8 Jan 2025 15:31:30 +0100 Subject: [PATCH 12/12] utils/ixyang: Simplify linting of infix YANG models Usage examples: Run yanglint on all infix models: ixyang check Lint a single model: ixyang lint infix-interfaces Dump a tree of ietf-interfaces with all infix augments: ixyang lint infix-interfaces ietf-interfaces -- -f tree --- utils/ixyang | 114 +++++++++++++++++++++++++++++++++++++++++++++++++ utils/libix.sh | 8 ++-- 2 files changed, 118 insertions(+), 4 deletions(-) create mode 100755 utils/ixyang diff --git a/utils/ixyang b/utils/ixyang new file mode 100755 index 00000000..f448165d --- /dev/null +++ b/utils/ixyang @@ -0,0 +1,114 @@ +#!/bin/sh + +ixdir=$(readlink -f $(dirname "$0")/../) +. "$ixdir/utils/libix.sh" + +resolve_host_dir + +YANGLINT="$HOST_DIR/bin/yanglint" +[ -x "$YANGLINT" ] || { + echo "*** Error: yanglint is not installed" >&2 + exit 1 +} + +yangdir="$ixdir/src/confd/yang" + +check() +{ + find "$yangdir" -type f -name '*infix*.yang' | while read file; do + head -n1 "$file" | grep -q "submodule" && continue + + printf "%-40s " $(basename "$file") + + "$YANGLINT" -p "$yangdir" -i "$file" || { + printf "%-40s FAIL\n" $(basename "$file") + continue + } + + echo ok + done +} + +resolve_model() +{ + local model="$1" + + if [ -e "$model" ]; then + file="$model" + elif [ -e "$yangdir/$model" ]; then + file="$yangdir/$model" + elif [ -e "$yangdir/$model.yang" ]; then + file="$yangdir/$model.yang" + else + file=$(find "$yangdir" -name "$model*" -print -quit) + fi + + if [ -z "$file" ]; then + echo "*** Error: Found no model matching \"$model\"" >&2 + exit 1 + fi + + echo "$file" +} + +lint() +{ + local files= + while [ $# -gt 0 ]; do + if [ "$1" = "--" ]; then + shift + break + fi + + files="$files $(resolve_model $1)" + shift + done + + "$YANGLINT" -p "$yangdir" -i "$@" $files +} + +yanger() +{ + local model="$1" + + "$ixdir/src/statd/python/yanger/yanger" \ + -t "$ixdir/test/case/cli/system-output" \ + "$model" +} + +yangerlint() +{ + local model="$1" + + yanger "$model" >/tmp/ixyang-yangerlint.json || { + echo "*** Error: Failed to dump \"$model\"" >&2 + exit 1 + } + + case "$model" in + ietf-interfaces) + lint \ + ietf-interfaces \ + ieee802-ethernet-interface \ + infix-interfaces \ + infix-ethernet-interface \ + \ + /tmp/ixyang-yangerlint.json \ + -- -i -t data + ;; + *) + echo "*** Error: yangerlint not implemented for \"$model\"" >&2 + ;; + esac + + rm /tmp/ixyang-yangerlint.json +} + +case "$1" in + check|lint|yanger|yangerlint) + "$@" + ;; + *) + echo "*** Error: Unknown command \"$1\"" >&2 + return 1 +esac diff --git a/utils/libix.sh b/utils/libix.sh index 0725262c..ddc620c5 100644 --- a/utils/libix.sh +++ b/utils/libix.sh @@ -5,13 +5,13 @@ resolve_o() if [ -f ".config" ] && [ -d "output" ]; then # Buildroot - O=./output + O=$(readlink -f ./output) elif [ -f "output/.config" ]; then # BR2_EXTERNAL - O=./output + O=$(readlink -f ./output) elif [ -f ".config" ] && [ -d "host" ]; then # Called from inside output/ directory - O=. + O=$(readlink -f .) else echo "*** Error: cannot find Buildroot output dir!" >&2 exit 1 @@ -22,7 +22,7 @@ resolve_host_dir() { [ -n "$HOST_DIR" ] && return - resolve_o || exit 1 + resolve_o if ! [ -d "$O/host" ]; then echo "*** Error: cannot find Buildroot host binaries dir!" >&2