From aa3d8945b9c0e20ff489f2f2ed784f5a9835bdce Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Tue, 28 Mar 2023 13:37:45 +0200 Subject: [PATCH 01/52] buildroot: switch to (updated) sysrepo branch from kkit Signed-off-by: Joachim Wiberg --- .gitmodules | 2 +- buildroot | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index e1d58ff5..d3faed24 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "buildroot"] path = buildroot - url = https://github.com/buildroot/buildroot.git + url = ../buildroot.git diff --git a/buildroot b/buildroot index 8cca1e6d..3790a1f4 160000 --- a/buildroot +++ b/buildroot @@ -1 +1 @@ -Subproject commit 8cca1e6de1c69a0a5e876116906bb3f6da4a5bd5 +Subproject commit 3790a1f4b6163f106cc87512efe01e22404296b4 From 546a2f3afb185348aabb7aeb0d1b6de36d0cf55f Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Tue, 28 Mar 2023 13:40:23 +0200 Subject: [PATCH 02/52] package/mech: relocate clixon system setup Signed-off-by: Joachim Wiberg --- {board/common/rootfs/lib/infix => package/mech}/clean-etc | 0 package/mech/mech.mk | 3 +++ {board/common/rootfs/lib/infix => package/mech}/prep-db | 0 3 files changed, 3 insertions(+) rename {board/common/rootfs/lib/infix => package/mech}/clean-etc (100%) rename {board/common/rootfs/lib/infix => package/mech}/prep-db (100%) diff --git a/board/common/rootfs/lib/infix/clean-etc b/package/mech/clean-etc similarity index 100% rename from board/common/rootfs/lib/infix/clean-etc rename to package/mech/clean-etc diff --git a/package/mech/mech.mk b/package/mech/mech.mk index 649bbb56..7c33ac9b 100644 --- a/package/mech/mech.mk +++ b/package/mech/mech.mk @@ -15,6 +15,9 @@ define MECH_INSTALL_EXTRA cp $(MECH_PKGDIR)/clixon.conf $(FINIT_D)/available/ ln -sf ../available/clixon.conf $(FINIT_D)/enabled/clixon.conf cp $(MECH_PKGDIR)/tmpfiles.conf $(TARGET_DIR)/etc/tmpfiles.d/mech.conf + mkdir -p $(TARGET_DIR)/lib/infix + cp $(MECH_PKGDIR)/prep-db $(TARGET_DIR)/lib/infix/ + cp $(MECH_PKGDIR)/clean-etc $(TARGET_DIR)/lib/infix/ endef MECH_TARGET_FINALIZE_HOOKS += MECH_INSTALL_EXTRA diff --git a/board/common/rootfs/lib/infix/prep-db b/package/mech/prep-db similarity index 100% rename from board/common/rootfs/lib/infix/prep-db rename to package/mech/prep-db From 8e03114518950ce9982e841cebada749dcf2c991 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Tue, 28 Mar 2023 15:01:18 +0200 Subject: [PATCH 03/52] patches: add support for running sysrepo-plugind in the foreground Signed-off-by: Joachim Wiberg --- .../sysrepo/sysrepo-plugind-foreground.patch | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 patches/sysrepo/sysrepo-plugind-foreground.patch diff --git a/patches/sysrepo/sysrepo-plugind-foreground.patch b/patches/sysrepo/sysrepo-plugind-foreground.patch new file mode 100644 index 00000000..827cfded --- /dev/null +++ b/patches/sysrepo/sysrepo-plugind-foreground.patch @@ -0,0 +1,64 @@ +commit 6fc440089353d76a9b8cb7c480402ee911a1387d +Author: Joachim Wiberg +Date: Tue Mar 28 10:37:53 2023 +0200 + + sysrepo-plugind: add support for running in foreground with syslog + + Signed-off-by: Joachim Wiberg + +diff --git a/src/executables/sysrepo-plugind.c b/src/executables/sysrepo-plugind.c +index bd584ed5..3079a855 100644 +--- a/src/executables/sysrepo-plugind.c ++++ b/src/executables/sysrepo-plugind.c +@@ -97,6 +97,7 @@ help_print(void) + " Change verbosity to a level (none, error, warning, info, debug) or\n" + " number (0, 1, 2, 3, 4).\n" + " -d, --debug Debug mode - is not daemonized and logs to stderr instead of syslog.\n" ++ " -n, --foreground Run in foreground and log to syslog.\n" + " -P, --plugin-install \n" + " Install a sysrepo-plugind plugin. The plugin is simply copied\n" + " to the designated plugin directory.\n" +@@ -200,6 +201,8 @@ daemon_init(int debug, sr_log_level_t log_level) + + if (debug) { + handle_signals(); ++ if (debug < 0) ++ goto done; + sr_log_stderr(log_level); + return; + } +@@ -240,6 +243,7 @@ daemon_init(int debug, sr_log_level_t log_level) + close(fd); + } + ++done: + /* set verbosity */ + sr_log_syslog("sysrepo-plugind", log_level); + } +@@ -459,6 +463,7 @@ main(int argc, char **argv) + {"version", no_argument, NULL, 'V'}, + {"verbosity", required_argument, NULL, 'v'}, + {"debug", no_argument, NULL, 'd'}, ++ {"foreground", no_argument, NULL, 'n'}, + {"plugin-install", required_argument, NULL, 'P'}, + {"pid-file", required_argument, NULL, 'p'}, + {"fatal-plugin-fail", no_argument, NULL, 'f'}, +@@ -467,7 +472,7 @@ main(int argc, char **argv) + + /* process options */ + opterr = 0; +- while ((opt = getopt_long(argc, argv, "hVv:dP:p:f", options, NULL)) != -1) { ++ while ((opt = getopt_long(argc, argv, "hVv:dnP:p:f", options, NULL)) != -1) { + switch (opt) { + case 'h': + version_print(); +@@ -499,6 +504,9 @@ main(int argc, char **argv) + case 'd': + debug = 1; + break; ++ case 'n': ++ debug = -1; ++ break; + case 'P': + /* plugin-install */ + if (get_plugins_dir(&plugins_dir)) { From 91d67e6b008382885e36bfbb6c6a7c6c52ad7c6c Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Tue, 28 Mar 2023 16:27:51 +0200 Subject: [PATCH 04/52] src/confd: import sysrepo ietf-system plugin by Denis Kalashnikov Signed-off-by: Joachim Wiberg --- src/confd/.gitignore | 33 ++ src/confd/LICENSE | 28 ++ src/confd/Makefile.am | 3 + src/confd/README.md | 15 + src/confd/autogen.sh | 3 + src/confd/configure.ac | 51 ++ src/confd/src/Makefile.am | 7 + src/confd/src/ietf-system.c | 307 ++++++++++++ src/confd/yang/Makefile.am | 2 + src/confd/yang/iana-crypt-hash.yang | 132 +++++ src/confd/yang/ietf-inet-types.yang | 457 +++++++++++++++++ src/confd/yang/ietf-netconf-acm.yang | 439 +++++++++++++++++ src/confd/yang/ietf-system.yang | 711 +++++++++++++++++++++++++++ 13 files changed, 2188 insertions(+) create mode 100644 src/confd/.gitignore create mode 100644 src/confd/LICENSE create mode 100644 src/confd/Makefile.am create mode 100644 src/confd/README.md create mode 100755 src/confd/autogen.sh create mode 100644 src/confd/configure.ac create mode 100644 src/confd/src/Makefile.am create mode 100644 src/confd/src/ietf-system.c create mode 100644 src/confd/yang/Makefile.am create mode 100644 src/confd/yang/iana-crypt-hash.yang create mode 100644 src/confd/yang/ietf-inet-types.yang create mode 100644 src/confd/yang/ietf-netconf-acm.yang create mode 100644 src/confd/yang/ietf-system.yang diff --git a/src/confd/.gitignore b/src/confd/.gitignore new file mode 100644 index 00000000..e9e8e747 --- /dev/null +++ b/src/confd/.gitignore @@ -0,0 +1,33 @@ +*~ +*.o +*.la +*.lo +*.so +.deps +.libs + +/aclocal.m4 +/autom4te.cache/ +/aux +/clixon.xml +/compile +/config.h +/config.h.in +/config.guess +/config.log +/config.status +/config.sub +/configure +/depcomp +/install-sh +/libtool +/ltmain.sh +/m4 +/missing + +GPATH +GRTAGS +GTAGS +Makefile +Makefile.in + diff --git a/src/confd/LICENSE b/src/confd/LICENSE new file mode 100644 index 00000000..7e5b6c82 --- /dev/null +++ b/src/confd/LICENSE @@ -0,0 +1,28 @@ +Copyright (c) 2023 Denis Kalashnikov +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of copyright holders nor the names of + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/src/confd/Makefile.am b/src/confd/Makefile.am new file mode 100644 index 00000000..a949b1fc --- /dev/null +++ b/src/confd/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = src yang +DISTCLEANFILES = *~ *.d +ACLOCAL_AMFLAGS = -I m4 diff --git a/src/confd/README.md b/src/confd/README.md new file mode 100644 index 00000000..02951ac8 --- /dev/null +++ b/src/confd/README.md @@ -0,0 +1,15 @@ +Configuration Daemon +==================== + +`confd` is the Infix configuration daemon that serves as the glue +between sysrepo and netopeer2 (NETCONF) and the UNIX system under +it all. + + +Origin & References +------------------- + +Based on the Open Source [dklibc/sysrepo_plugin_ietf_system][0] +project by Denis Kalashnikov. + +[0]: https://github.com/dklibc/sysrepo_plugin_ietf_system diff --git a/src/confd/autogen.sh b/src/confd/autogen.sh new file mode 100755 index 00000000..69ad0e18 --- /dev/null +++ b/src/confd/autogen.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +autoreconf -W portability -vifm diff --git a/src/confd/configure.ac b/src/confd/configure.ac new file mode 100644 index 00000000..f67a2723 --- /dev/null +++ b/src/confd/configure.ac @@ -0,0 +1,51 @@ +AC_PREREQ(2.61) +AC_INIT([confd], [1.0.0], + [https://github.com/kernelkit/infix/issues]) +AM_INIT_AUTOMAKE(1.11 foreign subdir-objects) +AM_SILENT_RULES(yes) + +LT_INIT + +AC_CONFIG_FILES([ + Makefile + src/Makefile + yang/Makefile +]) + +AC_PROG_CC +AC_PROG_INSTALL + +# Check for pkg-config first, warn if it's not installed +PKG_PROG_PKG_CONFIG + +PKG_CHECK_MODULES([sysrepo], [sysrepo >= 2.2.36]) +PKG_CHECK_MODULES([augeas], [augeas >= 1.12.0]) +PKG_CHECK_MODULES([jansson], [jansson >= 2.0.0]) + +# Plugin installation path for sysrepo-plugind +PKG_CHECK_VAR([SRPD_PLUGINS_PATH], [sysrepo], [plugindir]) + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DATAROOTDIR=`eval echo $datarootdir` +DATAROOTDIR=`eval echo $DATAROOTDIR` +AC_SUBST(DATAROOTDIR) + +LIBDIR=`eval echo $libdir` +LIBDIR=`eval echo $LIBDIR` +AC_SUBST(LIBDIR) + +LOCALSTATEDIR=`eval echo $localstatedir` +LOCALSTATEDIR=`eval echo $LOCALSTATEDIR` +AC_SUBST(LOCALSTATEDIR) + +RUNSTATEDIR=`eval echo $runstatedir` +RUNSTATEDIR=`eval echo $RUNSTATEDIR` +AC_SUBST(RUNSTATEDIR) + +SYSCONFDIR=`eval echo $sysconfdir` +SYSCONFDIR=`eval echo $SYSCONFDIR` +AC_SUBST(SYSCONFDIR) + +AC_OUTPUT diff --git a/src/confd/src/Makefile.am b/src/confd/src/Makefile.am new file mode 100644 index 00000000..7e22675d --- /dev/null +++ b/src/confd/src/Makefile.am @@ -0,0 +1,7 @@ +plugindir = $(sysrepo_plugind_PLUGINDIR) +plugin_LTLIBRARIES = confd-plugin.la + +confd_plugin_la_CFLAGS = $(sysrepo_CFLAGS) $(CFLAGS) +confd_plugin_la_LIBADD = $(sysrepo_LIBS) $(CFLAGS) +confd_plugin_la_LDFLAGS = -module -avoid-version -shared +confd_plugin_la_SOURCES = ietf-system.c diff --git a/src/confd/src/ietf-system.c b/src/confd/src/ietf-system.c new file mode 100644 index 00000000..1a61f8f3 --- /dev/null +++ b/src/confd/src/ietf-system.c @@ -0,0 +1,307 @@ +/* Sysrepo plugin of ietf-system@2014-08-06.yang module */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Linux specific */ +#include + +#include +#include + +#define CLOCK_PATH "/ietf-system:system-state/clock" +#define PLATFORM_PATH "/ietf-system:system-state/platform" + +#define DEBUG(frmt, ...) +//#define DEBUG(frmt, ...) syslog(LOG_DEBUG, "%s: "frmt, __func__, ##__VA_ARGS__) +#define ERROR(frmt, ...) syslog(LOG_ERR, "%s: "frmt, __func__, ##__VA_ARGS__) +#define ERRNO(frmt, ...) syslog(LOG_ERR, "%s: "frmt": ", __func__, ##__VA_ARGS__, strerror(errno)) + +/* Return seconds since boot */ +static long get_uptime(void) +{ + struct sysinfo info; + + /* + * !!!Linux specific!!! Use '/var/run/utmp' BOOT record + * to be portable. But utmp file can be missing in some + * Unixes. + */ + sysinfo(&info); + return info.uptime; +} + +static int get_time_as_str(time_t *time, char *buf, int bufsz) +{ + int n; + + n = strftime(buf, bufsz, "%Y-%m-%dT%H:%M:%S%z", + localtime(time)); + if (!n) + return -1; + + /* Buf ends with +hhmm but should be +hh:mm, fix this */ + memmove(buf + n - 1, buf + n - 2, 3); + buf[n - 2] = ':'; + + return 0; +} + +static int clock_cb(sr_session_ctx_t *session, const char *module, + const char *path, const char *request_path, + unsigned request_id, struct lyd_node **parent, + void *priv) +{ + static char boottime[64]; + char curtime[64]; + time_t t; + char *buf; + const struct ly_ctx *ctx; + + DEBUG("path=%s, request_path=%s", path, request_path); + + ctx = sr_get_context(sr_session_get_connection(session)); + + *parent = lyd_new_path(NULL, ctx, CLOCK_PATH, NULL, 0, 0); + + lyd_print_mem(&buf, *parent, LYD_XML, 0); + DEBUG("%s", buf); + + if (!*boottime) { + t = time(NULL) - get_uptime(); + get_time_as_str(&t, boottime, sizeof(boottime)); + } + + if (!lyd_new_path(*parent, NULL, CLOCK_PATH"/boot-datetime", + boottime, 0, 0)) { + ERROR("lyd_new_path() boot-datetime failed"); + } + + t = time(NULL); + get_time_as_str(&t, curtime, sizeof(curtime)); + if (!lyd_new_path(*parent, NULL, CLOCK_PATH"/current-datetime", + curtime, 0, 0)) { + ERROR("lyd_new_path() current-datetime failed"); + } + + lyd_print_mem(&buf, *parent, LYD_XML, 0); + DEBUG("%s", buf); + + return SR_ERR_OK; +} + +static int platform_cb(sr_session_ctx_t *session, const char *module, + const char *path, const char *request_path, + unsigned request_id, struct lyd_node **parent, + void *priv) +{ + struct utsname data; + char *buf; + const struct ly_ctx *ctx; + + DEBUG("path=%s request_path=%s", path, request_path); + + /* POSIX func */ + uname(&data); + + ctx = sr_get_context(sr_session_get_connection(session)); + + *parent = lyd_new_path(NULL, ctx, PLATFORM_PATH, NULL, 0, 0); + + lyd_print_mem(&buf, *parent, LYD_XML, 0); + DEBUG("%s", buf); + + lyd_new_path(*parent, NULL, PLATFORM_PATH"/os-name", + data.sysname, 0, 0); + lyd_new_path(*parent, NULL, PLATFORM_PATH"/os-release", + data.release, 0, 0); + lyd_new_path(*parent, NULL, PLATFORM_PATH"/os-version", + data.version, 0, 0); + lyd_new_path(*parent, NULL, PLATFORM_PATH"/machine", + data.machine, 0, 0); + + lyd_print_mem(&buf, *parent, LYD_XML, 0); + DEBUG("%s", buf); + + return SR_ERR_OK; +} + +static int exec_rpc_cb(sr_session_ctx_t *session, const char *path, + const sr_val_t *input, const size_t input_cnt, + sr_event_t event, unsigned request_id, + sr_val_t **output, size_t *output_cnt, + void *priv) +{ + DEBUG("path: %s", path); + system(priv); + + return SR_ERR_OK; +} + +/* '/ietf-system:set-current-date-time' */ +static int set_datetime_rpc_cb(sr_session_ctx_t *session, + const char *path, const sr_val_t *input, + const size_t input_cnt, sr_event_t event, + unsigned request_id, sr_val_t **output, + size_t *output_cnt, void *priv) +{ + struct tm tm; + time_t t; + struct timeval tv; + + memset(&tm, 0, sizeof(tm)); + + /* Parse 'current-datetime'. */ + sscanf(input->data.string_val, "%d-%d-%dT%d:%d:%d", &tm.tm_year, + &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, + &tm.tm_sec); + + DEBUG("Setting datetime to '%d-%02d-%02d %02d:%02d:%02d'", + tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, + tm.tm_sec); + + tm.tm_year -= 1900; + tm.tm_mon--; + + /* + * We suppose that this is a local time and ignore timezone. + */ + + t = mktime(&tm); + + tv.tv_sec = t; + tv.tv_usec = 0; + if (settimeofday(&tv, NULL)) { + ERRNO("settimeofday() failed"); + return SR_ERR_SYS; + } + + return SR_ERR_OK; +} + +int hostname_change_cb(sr_session_ctx_t *session, const char *module, + const char *xpath, sr_event_t event, + unsigned request_id, void *priv) +{ + int r; + sr_val_t *old_val, *new_val, *val; + sr_change_iter_t *iter; + sr_change_oper_t op; + + if (event != SR_EV_ENABLED && event != SR_EV_DONE) + return SR_ERR_OK; + + r = sr_get_changes_iter(session, "//.", &iter); + if (r != SR_ERR_OK) { + ERROR("failed to get changes iter: %s", sr_strerror(r)); + return r; + } + + while (sr_get_change_next(session, iter, &op, &old_val, + &new_val) == SR_ERR_OK) { + val = new_val ? new_val : old_val; + if (strcmp(val->xpath, "/ietf-system:system/hostname")) + goto free_vals; + + switch (op) { + case SR_OP_CREATED: + case SR_OP_MODIFIED: + if (sethostname(new_val->data.string_val, + strlen(new_val->data.string_val))) { + ERRNO("Failed to set hostname"); + return SR_ERR_SYS; + } + + DEBUG("Set hostname to '%s'", + new_val->data.string_val); + break; + } + +free_vals: + sr_free_val(old_val); + sr_free_val(new_val); + } + + return SR_ERR_OK; +} + +int sr_plugin_init_cb(sr_session_ctx_t *sess, void **priv) +{ + int r; + sr_subscription_ctx_t *sub = NULL; + + openlog("sysrepo ietf-system plugin", LOG_USER, 0); + + r = sr_oper_get_items_subscribe(sess, "ietf-system", + CLOCK_PATH, + clock_cb, NULL, + SR_SUBSCR_CTX_REUSE, &sub); + if (r != SR_ERR_OK) + goto err; + + r = sr_oper_get_items_subscribe(sess, "ietf-system", + PLATFORM_PATH, + platform_cb, NULL, + SR_SUBSCR_CTX_REUSE, &sub); + if (r != SR_ERR_OK) + goto err; + + r = sr_rpc_subscribe(sess, "/ietf-system:system-restart", + exec_rpc_cb, "shutdown -r now", + 0, SR_SUBSCR_CTX_REUSE, &sub); + if (r != SR_ERR_OK) + goto err; + + r = sr_rpc_subscribe(sess, "/ietf-system:system-shutdown", + exec_rpc_cb, "shutdown -h now", + 0, SR_SUBSCR_CTX_REUSE, &sub); + if (r != SR_ERR_OK) + goto err; + + r = sr_rpc_subscribe(sess, "/ietf-system:set-current-datetime", + set_datetime_rpc_cb, NULL, + 0, SR_SUBSCR_CTX_REUSE, &sub); + if (r != SR_ERR_OK) + goto err; + + + r = sr_module_change_subscribe(sess, "ietf-system", + "/ietf-system:system/hostname", + hostname_change_cb, NULL, 0, + SR_SUBSCR_CTX_REUSE | + SR_SUBSCR_ENABLED, &sub); + + if (r != SR_ERR_OK) { + ERROR("failed to subscribe to changes of hostname: %s", + sr_strerror(r)); + goto err; + } + + + *(sr_subscription_ctx_t **)priv = sub; + + DEBUG("init ok"); + + return SR_ERR_OK; + +err: + ERROR("init failed: %s", sr_strerror(r)); + + sr_unsubscribe(sub); + + return r; +} + +void sr_plugin_cleanup_cb(sr_session_ctx_t *session, void *priv) +{ + sr_unsubscribe((sr_subscription_ctx_t *)priv); + + DEBUG("cleanup ok"); +} diff --git a/src/confd/yang/Makefile.am b/src/confd/yang/Makefile.am new file mode 100644 index 00000000..a741c5fa --- /dev/null +++ b/src/confd/yang/Makefile.am @@ -0,0 +1,2 @@ +yangdir = $(datarootdir)/yang/modules/confd +yang_DATA = $(wildcard *.yang) diff --git a/src/confd/yang/iana-crypt-hash.yang b/src/confd/yang/iana-crypt-hash.yang new file mode 100644 index 00000000..f7134ccf --- /dev/null +++ b/src/confd/yang/iana-crypt-hash.yang @@ -0,0 +1,132 @@ + + module iana-crypt-hash { + + yang-version 1; + + namespace + "urn:ietf:params:xml:ns:yang:iana-crypt-hash"; + + prefix ianach; + + organization "IANA"; + + contact + " Internet Assigned Numbers Authority + + Postal: ICANN + 4676 Admiralty Way, Suite 330 + Marina del Rey, CA 90292 + + Tel: +1 310 823 9358 + E-Mail: iana&iana.org"; + + description + "This YANG module defines a typedef for storing passwords + using a hash function, and features to indicate which hash + functions are supported by an implementation. + + The latest revision of this YANG module can be obtained from + the IANA web site. + + Requests for new values should be made to IANA via + email (iana&iana.org). + + Copyright (c) 2014 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 + (http://trustee.ietf.org/license-info). + + The initial version of this YANG module is part of RFC XXXX; + see the RFC itself for full legal notices."; + + revision "2014-04-04" { + description "Initial revision."; + reference + "RFC XXXX: A YANG Data Model for System Management"; + + } + + + typedef crypt-hash { + type string { + pattern + '$0$.*|$1$[a-zA-Z0-9./]{1,8}$[a-zA-Z0-9./]{22}|$5$(rounds=\d+$)?[a-zA-Z0-9./]{1,16}$[a-zA-Z0-9./]{43}|$6$(rounds=\d+$)?[a-zA-Z0-9./]{1,16}$[a-zA-Z0-9./]{86}'; + } + description + "The crypt-hash type is used to store passwords using + a hash function. The algorithms for applying the hash + function and encoding the result are implemented in + various UNIX systems as the function crypt(3). + + A value of this type matches one of the forms: + + $0$ + $$$ + $$$$ + + The '$0$' prefix signals that the value is clear text. When + such a value is received by the server, a hash value is + calculated, and the string '$$$' or + $$$$ is prepended to the result. This + value is stored in the configuration data store. + + If a value starting with '$$', where is not '0', is + received, the server knows that the value already represents a + hashed value, and stores it as is in the data store. + + When a server needs to verify a password given by a user, it + finds the stored password hash string for that user, extracts + the salt, and calculates the hash with the salt and given + password as input. If the calculated hash value is the same + as the stored value, the password given by the client is + accepted. + + This type defines the following hash functions: + + id | hash function | feature + ---+---------------+------------------- + 1 | MD5 | crypt-hash-md5 + 5 | SHA-256 | crypt-hash-sha-256 + 6 | SHA-512 | crypt-hash-sha-512 + + The server indicates support for the different hash functions + by advertising the corresponding feature."; + reference + "IEEE Std 1003.1-2008 - crypt() function + RFC 1321: The MD5 Message-Digest Algorithm + FIPS.180-3.2008: Secure Hash Standard"; + + } + + feature crypt-hash-md5 { + description + "Indicates that the device supports the MD5 + hash function in 'crypt-hash' values"; + reference + "RFC 1321: The MD5 Message-Digest Algorithm"; + + } + + feature crypt-hash-sha-256 { + description + "Indicates that the device supports the SHA-256 + hash function in 'crypt-hash' values"; + reference + "FIPS.180-3.2008: Secure Hash Standard"; + + } + + feature crypt-hash-sha-512 { + description + "Indicates that the device supports the SHA-512 + hash function in 'crypt-hash' values"; + reference + "FIPS.180-3.2008: Secure Hash Standard"; + + } + } // module iana-crypt-hash diff --git a/src/confd/yang/ietf-inet-types.yang b/src/confd/yang/ietf-inet-types.yang new file mode 100644 index 00000000..2f14270d --- /dev/null +++ b/src/confd/yang/ietf-inet-types.yang @@ -0,0 +1,457 @@ +module ietf-inet-types { + + namespace "urn:ietf:params:xml:ns:yang:ietf-inet-types"; + prefix "inet"; + + organization + "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; + + contact + "WG Web: + WG List: + + WG Chair: David Kessens + + + WG Chair: Juergen Schoenwaelder + + + Editor: Juergen Schoenwaelder + "; + + description + "This module contains a collection of generally useful derived + YANG data types for Internet addresses and related things. + + Copyright (c) 2013 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 + (http://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 6991; see + the RFC itself for full legal notices."; + + revision 2013-07-15 { + description + "This revision adds the following new data types: + - ip-address-no-zone + - ipv4-address-no-zone + - ipv6-address-no-zone"; + reference + "RFC 6991: Common YANG Data Types"; + } + + revision 2010-09-24 { + description + "Initial revision."; + reference + "RFC 6021: Common YANG Data Types"; + } + + /*** collection of types related to protocol fields ***/ + + typedef ip-version { + type enumeration { + enum unknown { + value "0"; + description + "An unknown or unspecified version of the Internet + protocol."; + } + enum ipv4 { + value "1"; + description + "The IPv4 protocol as defined in RFC 791."; + } + enum ipv6 { + value "2"; + description + "The IPv6 protocol as defined in RFC 2460."; + } + } + description + "This value represents the version of the IP protocol. + + In the value set and its semantics, this type is equivalent + to the InetVersion textual convention of the SMIv2."; + reference + "RFC 791: Internet Protocol + RFC 2460: Internet Protocol, Version 6 (IPv6) Specification + RFC 4001: Textual Conventions for Internet Network Addresses"; + } + + typedef dscp { + type uint8 { + range "0..63"; + } + description + "The dscp type represents a Differentiated Services Code Point + that may be used for marking packets in a traffic stream. + In the value set and its semantics, this type is equivalent + to the Dscp textual convention of the SMIv2."; + reference + "RFC 3289: Management Information Base for the Differentiated + Services Architecture + RFC 2474: Definition of the Differentiated Services Field + (DS Field) in the IPv4 and IPv6 Headers + RFC 2780: IANA Allocation Guidelines For Values In + the Internet Protocol and Related Headers"; + } + + typedef ipv6-flow-label { + type uint32 { + range "0..1048575"; + } + description + "The ipv6-flow-label type represents the flow identifier or Flow + Label in an IPv6 packet header that may be used to + discriminate traffic flows. + + In the value set and its semantics, this type is equivalent + to the IPv6FlowLabel textual convention of the SMIv2."; + reference + "RFC 3595: Textual Conventions for IPv6 Flow Label + RFC 2460: Internet Protocol, Version 6 (IPv6) Specification"; + } + + typedef port-number { + type uint16 { + range "0..65535"; + } + description + "The port-number type represents a 16-bit port number of an + Internet transport-layer protocol such as UDP, TCP, DCCP, or + SCTP. Port numbers are assigned by IANA. A current list of + all assignments is available from . + + Note that the port number value zero is reserved by IANA. In + situations where the value zero does not make sense, it can + be excluded by subtyping the port-number type. + In the value set and its semantics, this type is equivalent + to the InetPortNumber textual convention of the SMIv2."; + reference + "RFC 768: User Datagram Protocol + RFC 793: Transmission Control Protocol + RFC 4960: Stream Control Transmission Protocol + RFC 4340: Datagram Congestion Control Protocol (DCCP) + RFC 4001: Textual Conventions for Internet Network Addresses"; + } + + /*** collection of types related to autonomous systems ***/ + + typedef as-number { + type uint32; + description + "The as-number type represents autonomous system numbers + which identify an Autonomous System (AS). An AS is a set + of routers under a single technical administration, using + an interior gateway protocol and common metrics to route + packets within the AS, and using an exterior gateway + protocol to route packets to other ASes. IANA maintains + the AS number space and has delegated large parts to the + regional registries. + + Autonomous system numbers were originally limited to 16 + bits. BGP extensions have enlarged the autonomous system + number space to 32 bits. This type therefore uses an uint32 + base type without a range restriction in order to support + a larger autonomous system number space. + + In the value set and its semantics, this type is equivalent + to the InetAutonomousSystemNumber textual convention of + the SMIv2."; + reference + "RFC 1930: Guidelines for creation, selection, and registration + of an Autonomous System (AS) + RFC 4271: A Border Gateway Protocol 4 (BGP-4) + RFC 4001: Textual Conventions for Internet Network Addresses + RFC 6793: BGP Support for Four-Octet Autonomous System (AS) + Number Space"; + } + + /*** collection of types related to IP addresses and hostnames ***/ + + typedef ip-address { + type union { + type inet:ipv4-address; + type inet:ipv6-address; + } + description + "The ip-address type represents an IP address and is IP + version neutral. The format of the textual representation + implies the IP version. This type supports scoped addresses + by allowing zone identifiers in the address format."; + reference + "RFC 4007: IPv6 Scoped Address Architecture"; + } + + typedef ipv4-address { + type string { + pattern + '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])' + + '(%[\p{N}\p{L}]+)?'; + } + description + "The ipv4-address type represents an IPv4 address in + dotted-quad notation. The IPv4 address may include a zone + index, separated by a % sign. + + The zone index is used to disambiguate identical address + values. For link-local addresses, the zone index will + typically be the interface index number or the name of an + interface. If the zone index is not present, the default + zone of the device will be used. + + The canonical format for the zone index is the numerical + format"; + } + + typedef ipv6-address { + type string { + pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}' + + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|' + + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}' + + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))' + + '(%[\p{N}\p{L}]+)?'; + pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|' + + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)' + + '(%.+)?'; + } + description + "The ipv6-address type represents an IPv6 address in full, + mixed, shortened, and shortened-mixed notation. The IPv6 + address may include a zone index, separated by a % sign. + + The zone index is used to disambiguate identical address + values. For link-local addresses, the zone index will + typically be the interface index number or the name of an + interface. If the zone index is not present, the default + zone of the device will be used. + + The canonical format of IPv6 addresses uses the textual + representation defined in Section 4 of RFC 5952. The + canonical format for the zone index is the numerical + format as described in Section 11.2 of RFC 4007."; + reference + "RFC 4291: IP Version 6 Addressing Architecture + RFC 4007: IPv6 Scoped Address Architecture + RFC 5952: A Recommendation for IPv6 Address Text + Representation"; + } + + typedef ip-address-no-zone { + type union { + type inet:ipv4-address-no-zone; + type inet:ipv6-address-no-zone; + } + description + "The ip-address-no-zone type represents an IP address and is + IP version neutral. The format of the textual representation + implies the IP version. This type does not support scoped + addresses since it does not allow zone identifiers in the + address format."; + reference + "RFC 4007: IPv6 Scoped Address Architecture"; + } + + typedef ipv4-address-no-zone { + type inet:ipv4-address { + pattern '[0-9\.]*'; + } + description + "An IPv4 address without a zone index. This type, derived from + ipv4-address, may be used in situations where the zone is + known from the context and hence no zone index is needed."; + } + + typedef ipv6-address-no-zone { + type inet:ipv6-address { + pattern '[0-9a-fA-F:\.]*'; + } + description + "An IPv6 address without a zone index. This type, derived from + ipv6-address, may be used in situations where the zone is + known from the context and hence no zone index is needed."; + reference + "RFC 4291: IP Version 6 Addressing Architecture + RFC 4007: IPv6 Scoped Address Architecture + RFC 5952: A Recommendation for IPv6 Address Text + Representation"; + } + + typedef ip-prefix { + type union { + type inet:ipv4-prefix; + type inet:ipv6-prefix; + } + description + "The ip-prefix type represents an IP prefix and is IP + version neutral. The format of the textual representations + implies the IP version."; + } + + typedef ipv4-prefix { + type string { + pattern + '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])' + + '/(([0-9])|([1-2][0-9])|(3[0-2]))'; + } + description + "The ipv4-prefix type represents an IPv4 address prefix. + The prefix length is given by the number following the + slash character and must be less than or equal to 32. + + A prefix length value of n corresponds to an IP address + mask that has n contiguous 1-bits from the most + significant bit (MSB) and all other bits set to 0. + + The canonical format of an IPv4 prefix has all bits of + the IPv4 address set to zero that are not part of the + IPv4 prefix."; + } + + typedef ipv6-prefix { + type string { + pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}' + + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|' + + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}' + + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))' + + '(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'; + pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|' + + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)' + + '(/.+)'; + } + description + "The ipv6-prefix type represents an IPv6 address prefix. + The prefix length is given by the number following the + slash character and must be less than or equal to 128. + + A prefix length value of n corresponds to an IP address + mask that has n contiguous 1-bits from the most + significant bit (MSB) and all other bits set to 0. + + The IPv6 address should have all bits that do not belong + to the prefix set to zero. + + The canonical format of an IPv6 prefix has all bits of + the IPv6 address set to zero that are not part of the + IPv6 prefix. Furthermore, the IPv6 address is represented + as defined in Section 4 of RFC 5952."; + reference + "RFC 5952: A Recommendation for IPv6 Address Text + Representation"; + } + + /*** collection of domain name and URI types ***/ + + typedef domain-name { + type string { + length "1..253"; + pattern + '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*' + + '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)' + + '|\.'; + } + description + "The domain-name type represents a DNS domain name. The + name SHOULD be fully qualified whenever possible. + + Internet domain names are only loosely specified. Section + 3.5 of RFC 1034 recommends a syntax (modified in Section + 2.1 of RFC 1123). The pattern above is intended to allow + for current practice in domain name use, and some possible + future expansion. It is designed to hold various types of + domain names, including names used for A or AAAA records + (host names) and other records, such as SRV records. Note + that Internet host names have a stricter syntax (described + in RFC 952) than the DNS recommendations in RFCs 1034 and + 1123, and that systems that want to store host names in + schema nodes using the domain-name type are recommended to + adhere to this stricter standard to ensure interoperability. + + The encoding of DNS names in the DNS protocol is limited + to 255 characters. Since the encoding consists of labels + prefixed by a length bytes and there is a trailing NULL + byte, only 253 characters can appear in the textual dotted + notation. + + The description clause of schema nodes using the domain-name + type MUST describe when and how these names are resolved to + IP addresses. Note that the resolution of a domain-name value + may require to query multiple DNS records (e.g., A for IPv4 + and AAAA for IPv6). The order of the resolution process and + which DNS record takes precedence can either be defined + explicitly or may depend on the configuration of the + resolver. + + Domain-name values use the US-ASCII encoding. Their canonical + format uses lowercase US-ASCII characters. Internationalized + domain names MUST be A-labels as per RFC 5890."; + reference + "RFC 952: DoD Internet Host Table Specification + RFC 1034: Domain Names - Concepts and Facilities + RFC 1123: Requirements for Internet Hosts -- Application + and Support + RFC 2782: A DNS RR for specifying the location of services + (DNS SRV) + RFC 5890: Internationalized Domain Names in Applications + (IDNA): Definitions and Document Framework"; + } + + typedef host { + type union { + type inet:ip-address; + type inet:domain-name; + } + description + "The host type represents either an IP address or a DNS + domain name."; + } + + typedef uri { + type string; + description + "The uri type represents a Uniform Resource Identifier + (URI) as defined by STD 66. + + Objects using the uri type MUST be in US-ASCII encoding, + and MUST be normalized as described by RFC 3986 Sections + 6.2.1, 6.2.2.1, and 6.2.2.2. All unnecessary + percent-encoding is removed, and all case-insensitive + characters are set to lowercase except for hexadecimal + digits, which are normalized to uppercase as described in + Section 6.2.2.1. + + The purpose of this normalization is to help provide + unique URIs. Note that this normalization is not + sufficient to provide uniqueness. Two URIs that are + textually distinct after this normalization may still be + equivalent. + + Objects using the uri type may restrict the schemes that + they permit. For example, 'data:' and 'urn:' schemes + might not be appropriate. + + A zero-length URI is not a valid URI. This can be used to + express 'URI absent' where required. + + In the value set and its semantics, this type is equivalent + to the Uri SMIv2 textual convention defined in RFC 5017."; + reference + "RFC 3986: Uniform Resource Identifier (URI): Generic Syntax + RFC 3305: Report from the Joint W3C/IETF URI Planning Interest + Group: Uniform Resource Identifiers (URIs), URLs, + and Uniform Resource Names (URNs): Clarifications + and Recommendations + RFC 5017: MIB Textual Conventions for Uniform Resource + Identifiers (URIs)"; + } + +} diff --git a/src/confd/yang/ietf-netconf-acm.yang b/src/confd/yang/ietf-netconf-acm.yang new file mode 100644 index 00000000..8347cc05 --- /dev/null +++ b/src/confd/yang/ietf-netconf-acm.yang @@ -0,0 +1,439 @@ + module ietf-netconf-acm { + + yang-version 1; + + 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: + + WG Chair: Mehmet Ersue + + + WG Chair: Bert Wijnen + + + Editor: Andy Bierman + + + Editor: Martin Bjorklund + "; + + description + "NETCONF Access Control Model. + + Copyright (c) 2012 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 + (http://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 6536; see + the RFC itself for full legal notices."; + + revision "2012-02-22" { + description + "Initial version; + Errata ID: 3862 and 3863"; + 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, and the NACM module is enabled (i.e., + /nacm/enable-nacm object equals 'true'), 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. + + 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, and the NACM module is enabled (i.e., + /nacm/enable-nacm object equals 'true'), 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. + + 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 { + position 0; + description + "Any protocol operation that creates a + new data node."; + } + bit read { + position 1; + description + "Any protocol operation or notification that + returns the value of a data node."; + } + bit update { + position 2; + description + "Any protocol operation that alters an existing + data node."; + } + bit delete { + position 3; + description + "Any protocol operation that removes a data node."; + } + bit exec { + position 4; + description + "Execution access to the specified protocol operation."; + } + } + description + "NETCONF 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" { + value 0; + description + "Requested action is permitted."; + } + enum "deny" { + value 1; + 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 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 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 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."; + } + + 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 group + } // container groups + + 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 if access is granted + or not."; + 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."; + 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."; + } + 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."; + } + leaf path { + type node-instance-identifier; + mandatory true; + description + "Data Node Instance Identifier associated with the + data node 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."; + } + } // choice rule-type + + 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 is 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."; + } + } // list rule + } // list rule-list + } // container nacm + } // module ietf-netconf-acm diff --git a/src/confd/yang/ietf-system.yang b/src/confd/yang/ietf-system.yang new file mode 100644 index 00000000..a8d9e089 --- /dev/null +++ b/src/confd/yang/ietf-system.yang @@ -0,0 +1,711 @@ +module ietf-system { + namespace "urn:ietf:params:xml:ns:yang:ietf-system"; + prefix "sys"; + import ietf-yang-types { + prefix yang; + } + import ietf-inet-types { + prefix inet; + } + import ietf-netconf-acm { + prefix nacm; + } + import iana-crypt-hash { + prefix ianach; + } + organization + "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; + contact + "WG Web: + WG List: + WG Chair: Thomas Nadeau + + WG Chair: Juergen Schoenwaelder + + Editor: Andy Bierman + + Editor: Martin Bjorklund + "; + description + "This module contains a collection of YANG definitions for the + configuration and identification of some common system + properties within a device containing a NETCONF server. This + includes data node definitions for system identification, + time-of-day management, user management, DNS resolver + configuration, and some protocol operations for system + management. + Copyright (c) 2014 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 + (http://trustee.ietf.org/license-info). + This version of this YANG module is part of RFC 7317; see + the RFC itself for full legal notices."; + revision 2014-08-06 { + description + "Initial revision."; + reference + "RFC 7317: A YANG Data Model for System Management"; + } + /* + * Typedefs + */ + typedef timezone-name { + type string; + description + "A time zone name as used by the Time Zone Database, + sometimes referred to as the 'Olson Database'. + The exact set of valid values is an implementation-specific + matter. Client discovery of the exact set of time zone names + for a particular server is out of scope."; + reference + "RFC 6557: Procedures for Maintaining the Time Zone Database"; + } + /* + * Features + */ + feature radius { + description + "Indicates that the device can be configured as a RADIUS + client."; + reference + "RFC 2865: Remote Authentication Dial In User Service (RADIUS)"; + } + feature authentication { + description + "Indicates that the device supports configuration of + user authentication."; + } + feature local-users { + if-feature authentication; + description + "Indicates that the device supports configuration of + local user authentication."; + } + feature radius-authentication { + if-feature radius; + if-feature authentication; + description + "Indicates that the device supports configuration of user + authentication over RADIUS."; + reference + "RFC 2865: Remote Authentication Dial In User Service (RADIUS) + RFC 5607: Remote Authentication Dial-In User Service (RADIUS) + Authorization for Network Access Server (NAS) + Management"; + } + feature ntp { + description + "Indicates that the device can be configured to use one or + more NTP servers to set the system date and time."; + } + feature ntp-udp-port { + if-feature ntp; + description + "Indicates that the device supports the configuration of + the UDP port for NTP servers. + This is a 'feature', since many implementations do not support + any port other than the default port."; + } + feature timezone-name { + description + "Indicates that the local time zone on the device + can be configured to use the TZ database + to set the time zone and manage daylight saving time."; + reference + "RFC 6557: Procedures for Maintaining the Time Zone Database"; + } + feature dns-udp-tcp-port { + description + "Indicates that the device supports the configuration of + the UDP and TCP port for DNS servers. + This is a 'feature', since many implementations do not support + any port other than the default port."; + } + /* + * Identities + */ + identity authentication-method { + description + "Base identity for user authentication methods."; + } + identity radius { + base authentication-method; + description + "Indicates user authentication using RADIUS."; + reference + "RFC 2865: Remote Authentication Dial In User Service (RADIUS) + RFC 5607: Remote Authentication Dial-In User Service (RADIUS) + Authorization for Network Access Server (NAS) + Management"; + } + identity local-users { + base authentication-method; + description + "Indicates password-based authentication of locally + configured users."; + } + identity radius-authentication-type { + description + "Base identity for RADIUS authentication types."; + } + identity radius-pap { + base radius-authentication-type; + description + "The device requests Password Authentication Protocol (PAP) + authentication from the RADIUS server."; + reference + "RFC 2865: Remote Authentication Dial In User Service (RADIUS)"; + } + identity radius-chap { + base radius-authentication-type; + description + "The device requests Challenge Handshake Authentication + Protocol (CHAP) authentication from the RADIUS server."; + reference + "RFC 2865: Remote Authentication Dial In User Service (RADIUS)"; + } + /* + * Configuration data nodes + */ + container system { + description + "System group configuration."; + leaf contact { + type string; + description + "The administrator contact information for the system. + A server implementation MAY map this leaf to the sysContact + MIB object. Such an implementation needs to use some + mechanism to handle the differences in size and characters + allowed between this leaf and sysContact. The definition of + such a mechanism is outside the scope of this document."; + reference + "RFC 3418: Management Information Base (MIB) for the + Simple Network Management Protocol (SNMP) + SNMPv2-MIB.sysContact"; + } + leaf hostname { + type inet:domain-name; + description + "The name of the host. This name can be a single domain + label or the fully qualified domain name of the host."; + } + leaf location { + type string; + description + "The system location. + A server implementation MAY map this leaf to the sysLocation + MIB object. Such an implementation needs to use some + mechanism to handle the differences in size and characters + allowed between this leaf and sysLocation. The definition + of such a mechanism is outside the scope of this document."; + reference + "RFC 3418: Management Information Base (MIB) for the + Simple Network Management Protocol (SNMP) + SNMPv2-MIB.sysLocation"; + } + container clock { + description + "Configuration of the system date and time properties."; + choice timezone { + description + "The system time zone information."; + case timezone-name { + if-feature timezone-name; + leaf timezone-name { + type timezone-name; + description + "The TZ database name to use for the system, such + as 'Europe/Stockholm'."; + } + } + case timezone-utc-offset { + leaf timezone-utc-offset { + type int16 { + range "-1500 .. 1500"; + } + units "minutes"; + description + "The number of minutes to add to UTC time to + identify the time zone for this system. For example, + 'UTC - 8:00 hours' would be represented as '-480'. + Note that automatic daylight saving time adjustment + is not provided if this object is used."; + } + } + } + } + container ntp { + if-feature ntp; + presence + "Enables the NTP client unless the 'enabled' leaf + (which defaults to 'true') is set to 'false'"; + description + "Configuration of the NTP client."; + leaf enabled { + type boolean; + default true; + description + "Indicates that the system should attempt to + synchronize the system clock with an NTP server + from the 'ntp/server' list."; + } + list server { + key name; + description + "List of NTP servers to use for system clock + synchronization. If '/system/ntp/enabled' + is 'true', then the system will attempt to + contact and utilize the specified NTP servers."; + leaf name { + type string; + description + "An arbitrary name for the NTP server."; + } + choice transport { + mandatory true; + description + "The transport-protocol-specific parameters for this + server."; + case udp { + container udp { + description + "Contains UDP-specific configuration parameters + for NTP."; + leaf address { + type inet:host; + mandatory true; + description + "The address of the NTP server."; + } + leaf port { + if-feature ntp-udp-port; + type inet:port-number; + default 123; + description + "The port number of the NTP server."; + } + } + } + } + leaf association-type { + type enumeration { + enum server { + description + "Use client association mode. This device + will not provide synchronization to the + configured NTP server."; + } + enum peer { + description + "Use symmetric active association mode. + This device may provide synchronization + to the configured NTP server."; + } + enum pool { + description + "Use client association mode with one or + more of the NTP servers found by DNS + resolution of the domain name given by + the 'address' leaf. This device will not + provide synchronization to the servers."; + } + } + default server; + description + "The desired association type for this NTP server."; + } + leaf iburst { + type boolean; + default false; + description + "Indicates whether this server should enable burst + synchronization or not."; + } + leaf prefer { + type boolean; + default false; + description + "Indicates whether this server should be preferred + or not."; + } + } + } + container dns-resolver { + description + "Configuration of the DNS resolver."; + leaf-list search { + type inet:domain-name; + ordered-by user; + description + "An ordered list of domains to search when resolving + a host name."; + } + list server { + key name; + ordered-by user; + description + "List of the DNS servers that the resolver should query. + When the resolver is invoked by a calling application, it + sends the query to the first name server in this list. If + no response has been received within 'timeout' seconds, + the resolver continues with the next server in the list. + If no response is received from any server, the resolver + continues with the first server again. When the resolver + has traversed the list 'attempts' times without receiving + any response, it gives up and returns an error to the + calling application. + Implementations MAY limit the number of entries in this + list."; + leaf name { + type string; + description + "An arbitrary name for the DNS server."; + } + choice transport { + mandatory true; + description + "The transport-protocol-specific parameters for this + server."; + case udp-and-tcp { + container udp-and-tcp { + description + "Contains UDP- and TCP-specific configuration + parameters for DNS."; + reference + "RFC 1035: Domain Names - Implementation and + Specification + RFC 5966: DNS Transport over TCP - Implementation + Requirements"; + leaf address { + type inet:ip-address; + mandatory true; + description + "The address of the DNS server."; + } + leaf port { + if-feature dns-udp-tcp-port; + type inet:port-number; + default 53; + description + "The UDP and TCP port number of the DNS server."; + } + } + } + } + } + container options { + description + "Resolver options. The set of available options has been + limited to those that are generally available across + different resolver implementations and generally useful."; + leaf timeout { + type uint8 { + range "1..max"; + } + units "seconds"; + default "5"; + description + "The amount of time the resolver will wait for a + response from each remote name server before + retrying the query via a different name server."; + } + leaf attempts { + type uint8 { + range "1..max"; + } + default "2"; + description + "The number of times the resolver will send a query to + all of its name servers before giving up and returning + an error to the calling application."; + } + } + } + container radius { + if-feature radius; + description + "Configuration of the RADIUS client."; + list server { + key name; + ordered-by user; + description + "List of RADIUS servers used by the device. + When the RADIUS client is invoked by a calling + application, it sends the query to the first server in + this list. If no response has been received within + 'timeout' seconds, the client continues with the next + server in the list. If no response is received from any + server, the client continues with the first server again. + When the client has traversed the list 'attempts' times + without receiving any response, it gives up and returns an + error to the calling application."; + leaf name { + type string; + description + "An arbitrary name for the RADIUS server."; + } + choice transport { + mandatory true; + description + "The transport-protocol-specific parameters for this + server."; + case udp { + container udp { + description + "Contains UDP-specific configuration parameters + for RADIUS."; + leaf address { + type inet:host; + mandatory true; + description + "The address of the RADIUS server."; + } + leaf authentication-port { + type inet:port-number; + default "1812"; + description + "The port number of the RADIUS server."; + } + leaf shared-secret { + type string; + mandatory true; + nacm:default-deny-all; + description + "The shared secret, which is known to both the + RADIUS client and server."; + reference + "RFC 2865: Remote Authentication Dial In User + Service (RADIUS)"; + } + } + } + } + leaf authentication-type { + type identityref { + base radius-authentication-type; + } + default radius-pap; + description + "The authentication type requested from the RADIUS + server."; + } + } + container options { + description + "RADIUS client options."; + leaf timeout { + type uint8 { + range "1..max"; + } + units "seconds"; + default "5"; + description + "The number of seconds the device will wait for a + response from each RADIUS server before trying with a + different server."; + } + leaf attempts { + type uint8 { + range "1..max"; + } + default "2"; + description + "The number of times the device will send a query to + all of its RADIUS servers before giving up."; + } + } + } + container authentication { + nacm:default-deny-write; + if-feature authentication; + description + "The authentication configuration subtree."; + leaf-list user-authentication-order { + type identityref { + base authentication-method; + } + must '(. != "sys:radius" or ../../radius/server)' { + error-message + "When 'radius' is used, a RADIUS server" + + " must be configured."; + description + "When 'radius' is used as an authentication method, + a RADIUS server must be configured."; + } + ordered-by user; + description + "When the device authenticates a user with a password, + it tries the authentication methods in this leaf-list in + order. If authentication with one method fails, the next + method is used. If no method succeeds, the user is + denied access. + An empty user-authentication-order leaf-list still allows + authentication of users using mechanisms that do not + involve a password. + If the 'radius-authentication' feature is advertised by + the NETCONF server, the 'radius' identity can be added to + this list. + If the 'local-users' feature is advertised by the + NETCONF server, the 'local-users' identity can be + added to this list."; + } + list user { + if-feature local-users; + key name; + description + "The list of local users configured on this device."; + leaf name { + type string; + description + "The user name string identifying this entry."; + } + leaf password { + type ianach:crypt-hash; + description + "The password for this entry."; + } + list authorized-key { + key name; + description + "A list of public SSH keys for this user. These keys + are allowed for SSH authentication, as described in + RFC 4253."; + reference + "RFC 4253: The Secure Shell (SSH) Transport Layer + Protocol"; + leaf name { + type string; + description + "An arbitrary name for the SSH key."; + } + leaf algorithm { + type string; + mandatory true; + description + "The public key algorithm name for this SSH key. + Valid values are the values in the IANA 'Secure Shell + (SSH) Protocol Parameters' registry, Public Key + Algorithm Names."; + reference + "IANA 'Secure Shell (SSH) Protocol Parameters' + registry, Public Key Algorithm Names"; + } + leaf key-data { + type binary; + mandatory true; + description + "The binary public key data for this SSH 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"; + } + } + } + } + } + /* + * Operational state data nodes + */ + container system-state { + config false; + description + "System group operational state."; + container platform { + description + "Contains vendor-specific information for + identifying the system platform and operating system."; + reference + "IEEE Std 1003.1-2008 - sys/utsname.h"; + leaf os-name { + type string; + description + "The name of the operating system in use - + for example, 'Linux'."; + reference + "IEEE Std 1003.1-2008 - utsname.sysname"; + } + leaf os-release { + type string; + description + "The current release level of the operating + system in use. This string MAY indicate + the OS source code revision."; + reference + "IEEE Std 1003.1-2008 - utsname.release"; + } + leaf os-version { + type string; + description + "The current version level of the operating + system in use. This string MAY indicate + the specific OS build date and target variant + information."; + reference + "IEEE Std 1003.1-2008 - utsname.version"; + } + leaf machine { + type string; + description + "A vendor-specific identifier string representing + the hardware in use."; + reference + "IEEE Std 1003.1-2008 - utsname.machine"; + } + } + container clock { + description + "Monitoring of the system date and time properties."; + leaf current-datetime { + type yang:date-and-time; + description + "The current system date and time."; + } + leaf boot-datetime { + type yang:date-and-time; + description + "The system date and time when the system last restarted."; + } + } + } + rpc set-current-datetime { + nacm:default-deny-all; + description + "Set the /system-state/clock/current-datetime leaf + to the specified value. + If the system is using NTP (i.e., /system/ntp/enabled + is set to 'true'), then this operation will fail with + error-tag 'operation-failed' and error-app-tag value of + 'ntp-active'."; + input { + leaf current-datetime { + type yang:date-and-time; + mandatory true; + description + "The current system date and time."; + } + } + } + rpc system-restart { + nacm:default-deny-all; + description + "Request that the entire system be restarted immediately. + A server SHOULD send an rpc reply to the client before + restarting the system."; + } + rpc system-shutdown { + nacm:default-deny-all; + description + "Request that the entire system be shut down immediately. + A server SHOULD send an rpc reply to the client before + shutting down the system."; + } +} From 767296e8301f8870d09a231af6997be65c9ea2b3 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Tue, 28 Mar 2023 19:55:20 +0200 Subject: [PATCH 05/52] src/confd: port to sysrepo 2.x Changes compared to original project: - installs into the sysrepo-plugind plugin directory, so no need for calling sysrepoctl to load the plugin - the plugin loads its yang module, so no need for calling sysrepoctl to load the module before starting sysrepo-plugind - bug fix ERROR() macro Signed-off-by: Joachim Wiberg --- src/confd/configure.ac | 3 +- src/confd/src/Makefile.am | 2 +- src/confd/src/ietf-system.c | 118 +++++++++++++++++++++--------------- src/confd/yang/Makefile.am | 2 +- 4 files changed, 73 insertions(+), 52 deletions(-) diff --git a/src/confd/configure.ac b/src/confd/configure.ac index f67a2723..3ed9eeca 100644 --- a/src/confd/configure.ac +++ b/src/confd/configure.ac @@ -23,7 +23,8 @@ PKG_CHECK_MODULES([augeas], [augeas >= 1.12.0]) PKG_CHECK_MODULES([jansson], [jansson >= 2.0.0]) # Plugin installation path for sysrepo-plugind -PKG_CHECK_VAR([SRPD_PLUGINS_PATH], [sysrepo], [plugindir]) +PKG_CHECK_VAR([srpdplugindir], [sysrepo], [SRPD_PLUGINS_PATH]) +AC_SUBST(srpdplugindir) test "x$prefix" = xNONE && prefix=$ac_default_prefix test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' diff --git a/src/confd/src/Makefile.am b/src/confd/src/Makefile.am index 7e22675d..aba4347a 100644 --- a/src/confd/src/Makefile.am +++ b/src/confd/src/Makefile.am @@ -1,4 +1,4 @@ -plugindir = $(sysrepo_plugind_PLUGINDIR) +plugindir = $(srpdplugindir) plugin_LTLIBRARIES = confd-plugin.la confd_plugin_la_CFLAGS = $(sysrepo_CFLAGS) $(CFLAGS) diff --git a/src/confd/src/ietf-system.c b/src/confd/src/ietf-system.c index 1a61f8f3..04aa23c4 100644 --- a/src/confd/src/ietf-system.c +++ b/src/confd/src/ietf-system.c @@ -21,8 +21,8 @@ #define DEBUG(frmt, ...) //#define DEBUG(frmt, ...) syslog(LOG_DEBUG, "%s: "frmt, __func__, ##__VA_ARGS__) -#define ERROR(frmt, ...) syslog(LOG_ERR, "%s: "frmt, __func__, ##__VA_ARGS__) -#define ERRNO(frmt, ...) syslog(LOG_ERR, "%s: "frmt": ", __func__, ##__VA_ARGS__, strerror(errno)) +#define ERROR(frmt, ...) syslog(LOG_ERR, "%s: " frmt, __func__, ##__VA_ARGS__) +#define ERRNO(frmt, ...) syslog(LOG_ERR, "%s: " frmt ": %s", __func__, ##__VA_ARGS__, strerror(errno)) /* Return seconds since boot */ static long get_uptime(void) @@ -54,22 +54,26 @@ static int get_time_as_str(time_t *time, char *buf, int bufsz) return 0; } -static int clock_cb(sr_session_ctx_t *session, const char *module, - const char *path, const char *request_path, - unsigned request_id, struct lyd_node **parent, - void *priv) +static int clock_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *module, + const char *path, const char *request_path, uint32_t request_id, + struct lyd_node **parent, void *priv) { - static char boottime[64]; - char curtime[64]; - time_t t; - char *buf; + static char boottime[64] = { 0 }; const struct ly_ctx *ctx; + char curtime[64]; + char *buf; + time_t t; + int rc; DEBUG("path=%s, request_path=%s", path, request_path); + ctx = sr_acquire_context(sr_session_get_connection(session)); - ctx = sr_get_context(sr_session_get_connection(session)); - - *parent = lyd_new_path(NULL, ctx, CLOCK_PATH, NULL, 0, 0); + rc = lyd_new_path(NULL, ctx, CLOCK_PATH, NULL, 0, parent); + if (rc) { + fail: + ERROR("Failed building data tree, libyang error %d", rc); + return SR_ERR_INTERNAL; + } lyd_print_mem(&buf, *parent, LYD_XML, 0); DEBUG("%s", buf); @@ -79,17 +83,15 @@ static int clock_cb(sr_session_ctx_t *session, const char *module, get_time_as_str(&t, boottime, sizeof(boottime)); } - if (!lyd_new_path(*parent, NULL, CLOCK_PATH"/boot-datetime", - boottime, 0, 0)) { - ERROR("lyd_new_path() boot-datetime failed"); - } + rc = lyd_new_path(*parent, NULL, CLOCK_PATH "/boot-datetime", boottime, 0, NULL); + if (rc) + goto fail; t = time(NULL); get_time_as_str(&t, curtime, sizeof(curtime)); - if (!lyd_new_path(*parent, NULL, CLOCK_PATH"/current-datetime", - curtime, 0, 0)) { - ERROR("lyd_new_path() current-datetime failed"); - } + rc = lyd_new_path(*parent, NULL, CLOCK_PATH "/current-datetime", curtime, 0, NULL); + if (rc) + goto fail; lyd_print_mem(&buf, *parent, LYD_XML, 0); DEBUG("%s", buf); @@ -97,35 +99,43 @@ static int clock_cb(sr_session_ctx_t *session, const char *module, return SR_ERR_OK; } -static int platform_cb(sr_session_ctx_t *session, const char *module, - const char *path, const char *request_path, - unsigned request_id, struct lyd_node **parent, - void *priv) +static int platform_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *module, + const char *path, const char *request_path, uint32_t request_id, + struct lyd_node **parent, void *priv) { + const struct ly_ctx *ctx; struct utsname data; char *buf; - const struct ly_ctx *ctx; + int rc; DEBUG("path=%s request_path=%s", path, request_path); + ctx = sr_acquire_context(sr_session_get_connection(session)); /* POSIX func */ uname(&data); - ctx = sr_get_context(sr_session_get_connection(session)); - - *parent = lyd_new_path(NULL, ctx, PLATFORM_PATH, NULL, 0, 0); + rc = lyd_new_path(NULL, ctx, PLATFORM_PATH, NULL, 0, parent); + if (rc) { + fail: + ERROR("Failed building data tree, libyang error %d", rc); + return SR_ERR_INTERNAL; + } lyd_print_mem(&buf, *parent, LYD_XML, 0); DEBUG("%s", buf); - lyd_new_path(*parent, NULL, PLATFORM_PATH"/os-name", - data.sysname, 0, 0); - lyd_new_path(*parent, NULL, PLATFORM_PATH"/os-release", - data.release, 0, 0); - lyd_new_path(*parent, NULL, PLATFORM_PATH"/os-version", - data.version, 0, 0); - lyd_new_path(*parent, NULL, PLATFORM_PATH"/machine", - data.machine, 0, 0); + rc = lyd_new_path(*parent, NULL, PLATFORM_PATH"/os-name", data.sysname, 0, NULL); + if (rc) + goto fail; + rc = lyd_new_path(*parent, NULL, PLATFORM_PATH"/os-release", data.release, 0, NULL); + if (rc) + goto fail; + rc = lyd_new_path(*parent, NULL, PLATFORM_PATH"/os-version", data.version, 0, NULL); + if (rc) + goto fail; + rc = lyd_new_path(*parent, NULL, PLATFORM_PATH"/machine", data.machine, 0, NULL); + if (rc) + goto fail; lyd_print_mem(&buf, *parent, LYD_XML, 0); DEBUG("%s", buf); @@ -133,20 +143,25 @@ static int platform_cb(sr_session_ctx_t *session, const char *module, return SR_ERR_OK; } -static int exec_rpc_cb(sr_session_ctx_t *session, const char *path, +static int exec_rpc_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *path, const sr_val_t *input, const size_t input_cnt, sr_event_t event, unsigned request_id, sr_val_t **output, size_t *output_cnt, void *priv) { + int rc; + DEBUG("path: %s", path); - system(priv); + + rc = system(priv); + if (WIFSIGNALED(rc) || (WIFEXITED(rc) && WEXITSTATUS(rc))) + return SR_ERR_INTERNAL; return SR_ERR_OK; } /* '/ietf-system:set-current-date-time' */ -static int set_datetime_rpc_cb(sr_session_ctx_t *session, +static int set_datetime_rpc_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *path, const sr_val_t *input, const size_t input_cnt, sr_event_t event, unsigned request_id, sr_val_t **output, @@ -186,7 +201,7 @@ static int set_datetime_rpc_cb(sr_session_ctx_t *session, return SR_ERR_OK; } -int hostname_change_cb(sr_session_ctx_t *session, const char *module, +int hostname_change_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *module, const char *xpath, sr_event_t event, unsigned request_id, void *priv) { @@ -232,42 +247,47 @@ free_vals: return SR_ERR_OK; } +#define YANG_PATH_ "/usr/share/yang/modules/sysrepo/" + int sr_plugin_init_cb(sr_session_ctx_t *sess, void **priv) { int r; sr_subscription_ctx_t *sub = NULL; + sr_conn_ctx_t *conn; openlog("sysrepo ietf-system plugin", LOG_USER, 0); + conn = sr_session_get_connection(sess); + sr_install_module(conn, YANG_PATH_"ietf-system.yang", NULL, NULL); - r = sr_oper_get_items_subscribe(sess, "ietf-system", + r = sr_oper_get_subscribe(sess, "ietf-system", CLOCK_PATH, clock_cb, NULL, - SR_SUBSCR_CTX_REUSE, &sub); + SR_SUBSCR_DEFAULT, &sub); if (r != SR_ERR_OK) goto err; - r = sr_oper_get_items_subscribe(sess, "ietf-system", + r = sr_oper_get_subscribe(sess, "ietf-system", PLATFORM_PATH, platform_cb, NULL, - SR_SUBSCR_CTX_REUSE, &sub); + SR_SUBSCR_DEFAULT, &sub); if (r != SR_ERR_OK) goto err; r = sr_rpc_subscribe(sess, "/ietf-system:system-restart", exec_rpc_cb, "shutdown -r now", - 0, SR_SUBSCR_CTX_REUSE, &sub); + 0, SR_SUBSCR_DEFAULT, &sub); if (r != SR_ERR_OK) goto err; r = sr_rpc_subscribe(sess, "/ietf-system:system-shutdown", exec_rpc_cb, "shutdown -h now", - 0, SR_SUBSCR_CTX_REUSE, &sub); + 0, SR_SUBSCR_DEFAULT, &sub); if (r != SR_ERR_OK) goto err; r = sr_rpc_subscribe(sess, "/ietf-system:set-current-datetime", set_datetime_rpc_cb, NULL, - 0, SR_SUBSCR_CTX_REUSE, &sub); + 0, SR_SUBSCR_DEFAULT, &sub); if (r != SR_ERR_OK) goto err; @@ -275,7 +295,7 @@ int sr_plugin_init_cb(sr_session_ctx_t *sess, void **priv) r = sr_module_change_subscribe(sess, "ietf-system", "/ietf-system:system/hostname", hostname_change_cb, NULL, 0, - SR_SUBSCR_CTX_REUSE | + SR_SUBSCR_DEFAULT | SR_SUBSCR_ENABLED, &sub); if (r != SR_ERR_OK) { diff --git a/src/confd/yang/Makefile.am b/src/confd/yang/Makefile.am index a741c5fa..c36471ee 100644 --- a/src/confd/yang/Makefile.am +++ b/src/confd/yang/Makefile.am @@ -1,2 +1,2 @@ -yangdir = $(datarootdir)/yang/modules/confd +yangdir = $(datarootdir)/yang/modules/sysrepo yang_DATA = $(wildcard *.yang) From b1be357a41426df435b49f6cd43a7c95f3b929bc Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Tue, 28 Mar 2023 19:58:34 +0200 Subject: [PATCH 06/52] package/confd: new package Signed-off-by: Joachim Wiberg --- package/Config.in | 1 + package/confd/Config.in | 10 ++++++++++ package/confd/clean-etc | 20 ++++++++++++++++++++ package/confd/confd.mk | 24 ++++++++++++++++++++++++ package/confd/prep-db | 4 ++++ package/confd/sysrepo.conf | 5 +++++ package/confd/tmpfiles.conf | 1 + 7 files changed, 65 insertions(+) create mode 100644 package/confd/Config.in create mode 100755 package/confd/clean-etc create mode 100644 package/confd/confd.mk create mode 100755 package/confd/prep-db create mode 100644 package/confd/sysrepo.conf create mode 100644 package/confd/tmpfiles.conf diff --git a/package/Config.in b/package/Config.in index cd6e312e..ba3eea4c 100644 --- a/package/Config.in +++ b/package/Config.in @@ -1,5 +1,6 @@ source "$BR2_EXTERNAL_INFIX_PATH/package/cligen/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/clixon/Config.in" +source "$BR2_EXTERNAL_INFIX_PATH/package/confd/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/factory/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/finit/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/ifupdown2/Config.in" diff --git a/package/confd/Config.in b/package/confd/Config.in new file mode 100644 index 00000000..cb551a7a --- /dev/null +++ b/package/confd/Config.in @@ -0,0 +1,10 @@ +config BR2_PACKAGE_CONFD + bool "confd" + select BR2_PACKAGE_SYSREPO + select BR2_PACKAGE_NETOPEER2 + select BR2_PACKAGE_AUGEAS + select BR2_PACKAGE_JANSSON + help + A plugin to sysrepo that provides the core YANG models used to + manage an Infix based system. Configuration can be done using + either the on-system CLI or using NETCONF. diff --git a/package/confd/clean-etc b/package/confd/clean-etc new file mode 100755 index 00000000..ffae2f9c --- /dev/null +++ b/package/confd/clean-etc @@ -0,0 +1,20 @@ +#!/bin/sh + +# This is an unmanaged node, leave /etc as-is +/lib/infix/use-etc && exit 0 + +# This is a managed node, ignore all default configuration ... +# ... except for some core services +reserved() +{ + for svc in sysrepo dnsmasq getty lldpd nginx sysklogd; do + [ "$1" = "${svc}.conf" ] && return 0 + done + + return 1 +} + +for file in /etc/finit.d/enabled/*.conf; do + reserved "$(basename "$file")" && continue + rm "$file" +done diff --git a/package/confd/confd.mk b/package/confd/confd.mk new file mode 100644 index 00000000..d47a7ee6 --- /dev/null +++ b/package/confd/confd.mk @@ -0,0 +1,24 @@ +################################################################################ +# +# confd +# +################################################################################ + +CONFD_VERSION = 1.0 +CONFD_LICENSE = BSD-3-Clause +CONFD_SITE_METHOD = local +CONFD_SITE = $(BR2_EXTERNAL_INFIX_PATH)/src/confd +CONFD_DEPENDENCIES = augeas sysrepo +CONFD_AUTORECONF = YES + +define CONFD_INSTALL_EXTRA + cp $(CONFD_PKGDIR)/sysrepo.conf $(FINIT_D)/available/ + ln -sf ../available/sysrepo.conf $(FINIT_D)/enabled/sysrepo.conf + cp $(CONFD_PKGDIR)/tmpfiles.conf $(TARGET_DIR)/etc/tmpfiles.d/confd.conf + mkdir -p $(TARGET_DIR)/lib/infix + cp $(CONFD_PKGDIR)/prep-db $(TARGET_DIR)/lib/infix/ + cp $(CONFD_PKGDIR)/clean-etc $(TARGET_DIR)/lib/infix/ +endef +CONFD_TARGET_FINALIZE_HOOKS += CONFD_INSTALL_EXTRA + +$(eval $(autotools-package)) diff --git a/package/confd/prep-db b/package/confd/prep-db new file mode 100755 index 00000000..541a41f5 --- /dev/null +++ b/package/confd/prep-db @@ -0,0 +1,4 @@ +#!/bin/sh +set -e + +exit 0 diff --git a/package/confd/sysrepo.conf b/package/confd/sysrepo.conf new file mode 100644 index 00000000..08c717c2 --- /dev/null +++ b/package/confd/sysrepo.conf @@ -0,0 +1,5 @@ +run if: [S] /lib/infix/clean-etc -- +run if: [S] /lib/infix/prep-db -- +service if: name:sysrepo [12345789] sysrepo-plugind -n -- Configuration daemon + +task if: [12345789] resolvconf -u -- Update DNS configuration diff --git a/package/confd/tmpfiles.conf b/package/confd/tmpfiles.conf new file mode 100644 index 00000000..504121c4 --- /dev/null +++ b/package/confd/tmpfiles.conf @@ -0,0 +1 @@ +d /run/resolvconf/interfaces - - - From 7a69c21e9df889672b28bf7a25dd45d6aefe7fd4 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Tue, 28 Mar 2023 20:00:12 +0200 Subject: [PATCH 07/52] configs: change default NETCONF to use sysrepo instead of clixon Extended evaluation of sysrepo due to problems parsing yang v1.1 models with the built-in yang parser in Clixon. Problems not seen with libyang Signed-off-by: Joachim Wiberg --- configs/aarch64_defconfig | 3 +-- configs/amd64_defconfig | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/configs/aarch64_defconfig b/configs/aarch64_defconfig index cfdaf484..5303cd03 100644 --- a/configs/aarch64_defconfig +++ b/configs/aarch64_defconfig @@ -119,7 +119,7 @@ BR2_PACKAGE_HOST_RAUC=y BR2_PACKAGE_HOST_UBOOT_TOOLS=y BR2_PACKAGE_HOST_UBOOT_TOOLS_FIT_SUPPORT=y BR2_PACKAGE_HOST_UBOOT_TOOLS_FIT_SIGNATURE_SUPPORT=y -BR2_PACKAGE_CLIXON_RESTCONF_FCGI=y +BR2_PACKAGE_CONFD=y BR2_PACKAGE_FACTORY=y BR2_PACKAGE_FINIT_SULOGIN=y BR2_PACKAGE_FINIT_PLUGIN_HOTPLUG=y @@ -130,7 +130,6 @@ BR2_PACKAGE_FINIT_PLUGIN_RTC=y BR2_PACKAGE_FINIT_PLUGIN_TTY=y BR2_PACKAGE_FINIT_PLUGIN_URANDOM=y BR2_PACKAGE_IFUPDOWN_NG=y -BR2_PACKAGE_MECH=y BR2_PACKAGE_P_NET=y BR2_PACKAGE_P_NET_MAX_SUBSLOTS=12 BR2_PACKAGE_P_NET_MAX_PHYSICAL_PORTS=10 diff --git a/configs/amd64_defconfig b/configs/amd64_defconfig index d27a0540..d81e85d4 100644 --- a/configs/amd64_defconfig +++ b/configs/amd64_defconfig @@ -122,7 +122,7 @@ BR2_PACKAGE_HOST_RAUC=y BR2_PACKAGE_HOST_UBOOT_TOOLS=y BR2_PACKAGE_HOST_UBOOT_TOOLS_FIT_SUPPORT=y BR2_PACKAGE_HOST_UBOOT_TOOLS_FIT_SIGNATURE_SUPPORT=y -BR2_PACKAGE_CLIXON_RESTCONF_FCGI=y +BR2_PACKAGE_CONFD=y BR2_PACKAGE_FACTORY=y BR2_PACKAGE_FINIT_SULOGIN=y BR2_PACKAGE_FINIT_PLUGIN_HOTPLUG=y @@ -133,7 +133,6 @@ BR2_PACKAGE_FINIT_PLUGIN_RTC=y BR2_PACKAGE_FINIT_PLUGIN_TTY=y BR2_PACKAGE_FINIT_PLUGIN_URANDOM=y BR2_PACKAGE_IFUPDOWN_NG=y -BR2_PACKAGE_MECH=y BR2_PACKAGE_P_NET=y BR2_PACKAGE_P_NET_MAX_SUBSLOTS=12 BR2_PACKAGE_P_NET_MAX_PHYSICAL_PORTS=10 From fdfcac70eb6ad33a21d99d8fe5068d2e0bda742e Mon Sep 17 00:00:00 2001 From: Tobias Waldekranz Date: Tue, 28 Mar 2023 16:11:56 +0200 Subject: [PATCH 08/52] package/faux: Add version 2.1.0 Used by the upcoming klish package --- package/Config.in | 1 + package/faux/Config.in | 7 +++++++ package/faux/faux.hash | 3 +++ package/faux/faux.mk | 15 +++++++++++++++ 4 files changed, 26 insertions(+) create mode 100644 package/faux/Config.in create mode 100644 package/faux/faux.hash create mode 100644 package/faux/faux.mk diff --git a/package/Config.in b/package/Config.in index ba3eea4c..cf24f8b7 100644 --- a/package/Config.in +++ b/package/Config.in @@ -2,6 +2,7 @@ source "$BR2_EXTERNAL_INFIX_PATH/package/cligen/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/clixon/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/confd/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/factory/Config.in" +source "$BR2_EXTERNAL_INFIX_PATH/package/faux/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/finit/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/ifupdown2/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/ifupdown-ng/Config.in" diff --git a/package/faux/Config.in b/package/faux/Config.in new file mode 100644 index 00000000..cdee852e --- /dev/null +++ b/package/faux/Config.in @@ -0,0 +1,7 @@ +config BR2_PACKAGE_FAUX + bool "faux" + depends on BR2_USE_MMU + help + The library contains a set of auxiliary functions. + + https://src.libcode.org/pkun/faux/ diff --git a/package/faux/faux.hash b/package/faux/faux.hash new file mode 100644 index 00000000..3059a197 --- /dev/null +++ b/package/faux/faux.hash @@ -0,0 +1,3 @@ +# Locally calculated +sha256 9d9d33b873917ca5d0bdcc47a36d2fd385971ab0c045d1472fcadf95ee5bcf5b LICENCE +sha256 8e369f54c2da317030ff4cad905e501303d0489b98e4b208d0ff611b4484c94e faux-tags_2.1.0-br1.tar.gz diff --git a/package/faux/faux.mk b/package/faux/faux.mk new file mode 100644 index 00000000..ff1e3cd6 --- /dev/null +++ b/package/faux/faux.mk @@ -0,0 +1,15 @@ +################################################################################ +# +# faux +# +################################################################################ + +FAUX_VERSION = tags/2.1.0 +FAUX_SITE = https://src.libcode.org/pkun/faux.git +FAUX_SITE_METHOD = git +FAUX_LICENSE = BSD-3 +FAUX_LICENSE_FILES = LICENSE +FAUX_INSTALL_STAGING = YES +FAUX_AUTORECONF = YES + +$(eval $(autotools-package)) From 5d8e0ec123f6576c93731a3c5a2bc980fd1b10a3 Mon Sep 17 00:00:00 2001 From: Tobias Waldekranz Date: Tue, 28 Mar 2023 16:12:47 +0200 Subject: [PATCH 09/52] package/klish: Add version 3.0.0 Extensible CLI application --- package/Config.in | 1 + package/klish/Config.in | 21 +++++++++++++++++++ package/klish/default.xml | 35 +++++++++++++++++++++++++++++++ package/klish/klish.hash | 3 +++ package/klish/klish.mk | 44 +++++++++++++++++++++++++++++++++++++++ package/klish/klish.svc | 1 + 6 files changed, 105 insertions(+) create mode 100644 package/klish/Config.in create mode 100644 package/klish/default.xml create mode 100644 package/klish/klish.hash create mode 100644 package/klish/klish.mk create mode 100644 package/klish/klish.svc diff --git a/package/Config.in b/package/Config.in index cf24f8b7..483279d9 100644 --- a/package/Config.in +++ b/package/Config.in @@ -6,6 +6,7 @@ source "$BR2_EXTERNAL_INFIX_PATH/package/faux/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/finit/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/ifupdown2/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/ifupdown-ng/Config.in" +source "$BR2_EXTERNAL_INFIX_PATH/package/klish/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/mdnsd/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/mech/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/osal/Config.in" diff --git a/package/klish/Config.in b/package/klish/Config.in new file mode 100644 index 00000000..9f55b085 --- /dev/null +++ b/package/klish/Config.in @@ -0,0 +1,21 @@ +config BR2_PACKAGE_KLISH + bool "klish" + depends on BR2_USE_MMU + select BR2_PACKAGE_FAUX + select BR2_PACKAGE_LIBXML2 + help + Klish is a framework for implementing a CISCO-like or + Juniper-like CLI on a UNIX systems. + + https://src.libcode.org/pkun/klish/ + +config BR2_PACKAGE_KLISH_DEFAULT_XML + bool "install xml" + depends on BR2_PACKAGE_KLISH + default y + help + Install a small XML spec containing a definition of an + 'exit' command. This lets klish work out-of-the-box, even if + no other specs are available. + + If unsure, say Y. diff --git a/package/klish/default.xml b/package/klish/default.xml new file mode 100644 index 00000000..62e90d4c --- /dev/null +++ b/package/klish/default.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + %u@%h> + + + + + pop + Exiting klish session + + + + + + + diff --git a/package/klish/klish.hash b/package/klish/klish.hash new file mode 100644 index 00000000..ff5eb0a7 --- /dev/null +++ b/package/klish/klish.hash @@ -0,0 +1,3 @@ +# Locally calculated +sha256 9d9d33b873917ca5d0bdcc47a36d2fd385971ab0c045d1472fcadf95ee5bcf5b LICENCE +sha256 e7c09457ed0b030eddd8eaf7d9f7c9344c2fcd7ac2083f1d8ebeaafc4ed6dba6 klish-tags_3.0.0-br1.tar.gz diff --git a/package/klish/klish.mk b/package/klish/klish.mk new file mode 100644 index 00000000..a85b089f --- /dev/null +++ b/package/klish/klish.mk @@ -0,0 +1,44 @@ +################################################################################ +# +# klish +# +################################################################################ + +KLISH_VERSION = tags/3.0.0 +KLISH_SITE = https://src.libcode.org/pkun/klish.git +KLISH_SITE_METHOD = git +KLISH_LICENSE = BSD-3 +KLISH_LICENSE_FILES = LICENSE +KLISH_DEPENDENCIES = libxml2 +KLISH_INSTALL_STAGING = YES +KLISH_AUTORECONF = YES + +define KLISH_INSTALL_CONFIG + $(INSTALL) -t $(TARGET_DIR)/etc/klish -D -m 0644 \ + $(@D)/klish.conf $(@D)/klishd.conf + +# klish's default pager settings assumes that less understands +# all GNU options, so we disable it. + sed -i -e 's/#UsePager=y/UsePager=n/' \ + $(TARGET_DIR)/etc/klish/klish.conf +endef +KLISH_POST_INSTALL_TARGET_HOOKS += KLISH_INSTALL_CONFIG + +ifeq ($(BR2_PACKAGE_KLISH_DEFAULT_XML),y) +define KLISH_INSTALL_XML + $(INSTALL) -t $(TARGET_DIR)/etc/klish -D -m 0644 \ + $(BR2_EXTERNAL_INFIX_PATH)/package/klish/default.xml +endef +KLISH_POST_INSTALL_TARGET_HOOKS += KLISH_INSTALL_XML +endif + +define KLISH_INSTALL_FINIT_SVC + $(INSTALL) -D -m 0644 $(BR2_EXTERNAL_INFIX_PATH)/package/klish/klish.svc \ + $(FINIT_D)/available/klish.conf + $(INSTALL) -d -m 0755 $(FINIT_D)/enabled + ln -sf ../available/klish.conf $(FINIT_D)/enabled/klish.conf +endef + +KLISH_POST_INSTALL_TARGET_HOOKS += KLISH_INSTALL_FINIT_SVC + +$(eval $(autotools-package)) diff --git a/package/klish/klish.svc b/package/klish/klish.svc new file mode 100644 index 00000000..a5bb2e6f --- /dev/null +++ b/package/klish/klish.svc @@ -0,0 +1 @@ +service [2345789] /usr/bin/klishd -d -- CLI backend From b549ddd88a261533c14b306f19288bd859296f3b Mon Sep 17 00:00:00 2001 From: Tobias Waldekranz Date: Tue, 28 Mar 2023 16:13:25 +0200 Subject: [PATCH 10/52] package/klish-plugin-sysrepo: Add version 1.0.0 Adds a klish interface to local datastores managed by sysrepo. --- package/Config.in | 1 + package/klish-plugin-sysrepo/Config.in | 21 ++++++++++++++++ .../klish-plugin-sysrepo.hash | 3 +++ .../klish-plugin-sysrepo.mk | 25 +++++++++++++++++++ 4 files changed, 50 insertions(+) create mode 100644 package/klish-plugin-sysrepo/Config.in create mode 100644 package/klish-plugin-sysrepo/klish-plugin-sysrepo.hash create mode 100644 package/klish-plugin-sysrepo/klish-plugin-sysrepo.mk diff --git a/package/Config.in b/package/Config.in index 483279d9..a0a0a24f 100644 --- a/package/Config.in +++ b/package/Config.in @@ -7,6 +7,7 @@ source "$BR2_EXTERNAL_INFIX_PATH/package/finit/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/ifupdown2/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/ifupdown-ng/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/klish/Config.in" +source "$BR2_EXTERNAL_INFIX_PATH/package/klish-plugin-sysrepo/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/mdnsd/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/mech/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/osal/Config.in" diff --git a/package/klish-plugin-sysrepo/Config.in b/package/klish-plugin-sysrepo/Config.in new file mode 100644 index 00000000..b61e20b9 --- /dev/null +++ b/package/klish-plugin-sysrepo/Config.in @@ -0,0 +1,21 @@ +config BR2_PACKAGE_KLISH_PLUGIN_SYSREPO + bool "klish-plugin-sysrepo" + depends on BR2_PACKAGE_KLISH + depends on BR2_PACKAGE_SYSREPO + help + This plugin allows klish framework to implement Juniper-like + interface for configuration. It uses sysrepo project as + background for datastores and libyang for yang files parsing + and configuration schemes. + + https://src.libcode.org/pkun/klish-plugin-sysrepo/ + +config BR2_PACKAGE_KLISH_PLUGIN_SYSREPO_XML + bool "install xml" + depends on BR2_PACKAGE_KLISH_PLUGIN_SYSREPO + default y + help + Install the default XML spec bundled with the project, which + exports the 'show' command, and the 'configure' view, etc. + + If unsure, say Y. diff --git a/package/klish-plugin-sysrepo/klish-plugin-sysrepo.hash b/package/klish-plugin-sysrepo/klish-plugin-sysrepo.hash new file mode 100644 index 00000000..432c9c19 --- /dev/null +++ b/package/klish-plugin-sysrepo/klish-plugin-sysrepo.hash @@ -0,0 +1,3 @@ +# Locally calculated +sha256 9d9d33b873917ca5d0bdcc47a36d2fd385971ab0c045d1472fcadf95ee5bcf5b LICENCE +sha256 cf972522d296b82e96fe0d366bb01a9fe47e71c785ed69205b7f20af251c5a48 klish-plugin-sysrepo-tags_1.0.0-br1.tar.gz diff --git a/package/klish-plugin-sysrepo/klish-plugin-sysrepo.mk b/package/klish-plugin-sysrepo/klish-plugin-sysrepo.mk new file mode 100644 index 00000000..4bd9e445 --- /dev/null +++ b/package/klish-plugin-sysrepo/klish-plugin-sysrepo.mk @@ -0,0 +1,25 @@ +################################################################################ +# +# klish-plugin-sysrepo +# +################################################################################ + +KLISH_PLUGIN_SYSREPO_VERSION = tags/1.0.0 +KLISH_PLUGIN_SYSREPO_SITE = https://src.libcode.org/pkun/klish-plugin-sysrepo.git +KLISH_PLUGIN_SYSREPO_SITE_METHOD = git +KLISH_PLUGIN_SYSREPO_LICENSE = BSD-3 +KLISH_PLUGIN_SYSREPO_LICENSE_FILES = LICENSE +KLISH_PLUGIN_SYSREPO_DEPENDENCIES = klish sysrepo +KLISH_PLUGIN_SYSREPO_INSTALL_STAGING = YES +KLISH_PLUGIN_SYSREPO_AUTORECONF = YES + +ifeq ($(BR2_PACKAGE_KLISH_PLUGIN_SYSREPO_XML),y) +define KLISH_PLUGIN_SYSREPO_INSTALL_XML + $(INSTALL) -t $(TARGET_DIR)/etc/klish -D -m 0644 \ + $(@D)/xml/sysrepo.xml +endef +KLISH_PLUGIN_SYSREPO_POST_INSTALL_TARGET_HOOKS += \ + KLISH_PLUGIN_SYSREPO_INSTALL_XML +endif + +$(eval $(autotools-package)) From 737f99e35e1091330c35032df43f4e8adea79310 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Tue, 28 Mar 2023 20:53:41 +0200 Subject: [PATCH 11/52] package/klish: make sure to enable libxml2 in configure Signed-off-by: Joachim Wiberg --- package/klish/klish.mk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package/klish/klish.mk b/package/klish/klish.mk index a85b089f..99e2d6a2 100644 --- a/package/klish/klish.mk +++ b/package/klish/klish.mk @@ -13,6 +13,8 @@ KLISH_DEPENDENCIES = libxml2 KLISH_INSTALL_STAGING = YES KLISH_AUTORECONF = YES +KLISH_CONF_OPTS += --with-libxml2 + define KLISH_INSTALL_CONFIG $(INSTALL) -t $(TARGET_DIR)/etc/klish -D -m 0644 \ $(@D)/klish.conf $(@D)/klishd.conf From d1444b900abbfdb95efd674c9015f9bcf43ceef9 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Tue, 28 Mar 2023 20:53:55 +0200 Subject: [PATCH 12/52] package/confd: allow klishd to run in NETCONF mode Signed-off-by: Joachim Wiberg --- package/confd/clean-etc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/confd/clean-etc b/package/confd/clean-etc index ffae2f9c..342f47e4 100755 --- a/package/confd/clean-etc +++ b/package/confd/clean-etc @@ -7,7 +7,7 @@ # ... except for some core services reserved() { - for svc in sysrepo dnsmasq getty lldpd nginx sysklogd; do + for svc in dnsmasq getty klish lldpd nginx sysklogd sysrepo; do [ "$1" = "${svc}.conf" ] && return 0 done From 1907bd6a7502a2c5d9074967e2e2e34adec48682 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Wed, 29 Mar 2023 06:09:41 +0200 Subject: [PATCH 13/52] src/confd: adjust Denis' copyright year, last changed 2020 Signed-off-by: Joachim Wiberg --- src/confd/LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/confd/LICENSE b/src/confd/LICENSE index 7e5b6c82..1ae040d8 100644 --- a/src/confd/LICENSE +++ b/src/confd/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2023 Denis Kalashnikov +Copyright (c) 2020 Denis Kalashnikov All rights reserved. Redistribution and use in source and binary forms, with or without From 41db19ffaa4b9508f805a000ddd8b4e8a339a373 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Wed, 29 Mar 2023 06:20:24 +0200 Subject: [PATCH 14/52] src/confd: import updated yang models from mech Signed-off-by: Joachim Wiberg --- ...h.yang => iana-crypt-hash@2014-08-06.yang} | 124 +- src/confd/yang/iana-if-type.yang | 1 + src/confd/yang/iana-if-type@2017-01-19.yang | 1619 +++++++++++++++++ src/confd/yang/ietf-datastores.yang | 1 + .../yang/ietf-datastores@2018-02-14.yang | 117 ++ src/confd/yang/ietf-inet-types.yang | 458 +---- .../yang/ietf-inet-types@2013-07-15.yang | 458 +++++ src/confd/yang/ietf-interfaces.yang | 1 + .../yang/ietf-interfaces@2018-02-20.yang | 1123 ++++++++++++ src/confd/yang/ietf-ip.yang | 1 + src/confd/yang/ietf-ip@2018-02-22.yang | 876 +++++++++ src/confd/yang/ietf-netconf-acm.yang | 440 +---- .../yang/ietf-netconf-acm@2018-02-14.yang | 464 +++++ src/confd/yang/ietf-system.yang | 712 +------- src/confd/yang/ietf-system@2014-08-06.yang | 800 ++++++++ src/confd/yang/ietf-yang-types.yang | 1 + .../yang/ietf-yang-types@2013-07-15.yang | 474 +++++ 17 files changed, 5995 insertions(+), 1675 deletions(-) rename src/confd/yang/{iana-crypt-hash.yang => iana-crypt-hash@2014-08-06.yang} (53%) create mode 120000 src/confd/yang/iana-if-type.yang create mode 100644 src/confd/yang/iana-if-type@2017-01-19.yang create mode 120000 src/confd/yang/ietf-datastores.yang create mode 100644 src/confd/yang/ietf-datastores@2018-02-14.yang mode change 100644 => 120000 src/confd/yang/ietf-inet-types.yang create mode 100644 src/confd/yang/ietf-inet-types@2013-07-15.yang create mode 120000 src/confd/yang/ietf-interfaces.yang create mode 100644 src/confd/yang/ietf-interfaces@2018-02-20.yang create mode 120000 src/confd/yang/ietf-ip.yang create mode 100644 src/confd/yang/ietf-ip@2018-02-22.yang mode change 100644 => 120000 src/confd/yang/ietf-netconf-acm.yang create mode 100644 src/confd/yang/ietf-netconf-acm@2018-02-14.yang mode change 100644 => 120000 src/confd/yang/ietf-system.yang create mode 100644 src/confd/yang/ietf-system@2014-08-06.yang create mode 120000 src/confd/yang/ietf-yang-types.yang create mode 100644 src/confd/yang/ietf-yang-types@2013-07-15.yang diff --git a/src/confd/yang/iana-crypt-hash.yang b/src/confd/yang/iana-crypt-hash@2014-08-06.yang similarity index 53% rename from src/confd/yang/iana-crypt-hash.yang rename to src/confd/yang/iana-crypt-hash@2014-08-06.yang index f7134ccf..48dc50e3 100644 --- a/src/confd/yang/iana-crypt-hash.yang +++ b/src/confd/yang/iana-crypt-hash@2014-08-06.yang @@ -1,35 +1,28 @@ +module iana-crypt-hash { + namespace "urn:ietf:params:xml:ns:yang:iana-crypt-hash"; + prefix ianach; - module iana-crypt-hash { - - yang-version 1; - - namespace - "urn:ietf:params:xml:ns:yang:iana-crypt-hash"; - - prefix ianach; - - organization "IANA"; - - contact - " Internet Assigned Numbers Authority + organization "IANA"; + contact + " Internet Assigned Numbers Authority Postal: ICANN - 4676 Admiralty Way, Suite 330 - Marina del Rey, CA 90292 + 12025 Waterfront Drive, Suite 300 + Los Angeles, CA 90094-2536 + United States - Tel: +1 310 823 9358 - E-Mail: iana&iana.org"; - - description - "This YANG module defines a typedef for storing passwords - using a hash function, and features to indicate which hash + Tel: +1 310 301 5800 + E-Mail: iana@iana.org>"; + description + "This YANG module defines a type for storing passwords + using a hash function and features to indicate which hash functions are supported by an implementation. The latest revision of this YANG module can be obtained from the IANA web site. Requests for new values should be made to IANA via - email (iana&iana.org). + email (iana@iana.org). Copyright (c) 2014 IETF Trust and the persons identified as authors of the code. All rights reserved. @@ -41,24 +34,26 @@ Relating to IETF Documents (http://trustee.ietf.org/license-info). - The initial version of this YANG module is part of RFC XXXX; + The initial version of this YANG module is part of RFC 7317; see the RFC itself for full legal notices."; - revision "2014-04-04" { - description "Initial revision."; - reference - "RFC XXXX: A YANG Data Model for System Management"; + revision 2014-08-06 { + description + "Initial revision."; + reference + "RFC 7317: A YANG Data Model for System Management"; + } + typedef crypt-hash { + type string { + pattern + '$0$.*' + + '|$1$[a-zA-Z0-9./]{1,8}$[a-zA-Z0-9./]{22}' + + '|$5$(rounds=\d+$)?[a-zA-Z0-9./]{1,16}$[a-zA-Z0-9./]{43}' + + '|$6$(rounds=\d+$)?[a-zA-Z0-9./]{1,16}$[a-zA-Z0-9./]{86}'; } - - - typedef crypt-hash { - type string { - pattern - '$0$.*|$1$[a-zA-Z0-9./]{1,8}$[a-zA-Z0-9./]{22}|$5$(rounds=\d+$)?[a-zA-Z0-9./]{1,16}$[a-zA-Z0-9./]{43}|$6$(rounds=\d+$)?[a-zA-Z0-9./]{1,16}$[a-zA-Z0-9./]{86}'; - } - description - "The crypt-hash type is used to store passwords using + description + "The crypt-hash type is used to store passwords using a hash function. The algorithms for applying the hash function and encoding the result are implemented in various UNIX systems as the function crypt(3). @@ -74,10 +69,9 @@ calculated, and the string '$$$' or $$$$ is prepended to the result. This value is stored in the configuration data store. - If a value starting with '$$', where is not '0', is received, the server knows that the value already represents a - hashed value, and stores it as is in the data store. + hashed value and stores it 'as is' in the data store. When a server needs to verify a password given by a user, it finds the stored password hash string for that user, extracts @@ -96,37 +90,31 @@ The server indicates support for the different hash functions by advertising the corresponding feature."; - reference - "IEEE Std 1003.1-2008 - crypt() function - RFC 1321: The MD5 Message-Digest Algorithm - FIPS.180-3.2008: Secure Hash Standard"; + reference + "IEEE Std 1003.1-2008 - crypt() function + RFC 1321: The MD5 Message-Digest Algorithm + FIPS.180-4.2012: Secure Hash Standard (SHS)"; + } - } + feature crypt-hash-md5 { + description + "Indicates that the device supports the MD5 + hash function in 'crypt-hash' values."; + reference "RFC 1321: The MD5 Message-Digest Algorithm"; + } - feature crypt-hash-md5 { - description - "Indicates that the device supports the MD5 - hash function in 'crypt-hash' values"; - reference - "RFC 1321: The MD5 Message-Digest Algorithm"; + feature crypt-hash-sha-256 { + description + "Indicates that the device supports the SHA-256 + hash function in 'crypt-hash' values."; + reference "FIPS.180-4.2012: Secure Hash Standard (SHS)"; + } - } + feature crypt-hash-sha-512 { + description + "Indicates that the device supports the SHA-512 + hash function in 'crypt-hash' values."; + reference "FIPS.180-4.2012: Secure Hash Standard (SHS)"; + } - feature crypt-hash-sha-256 { - description - "Indicates that the device supports the SHA-256 - hash function in 'crypt-hash' values"; - reference - "FIPS.180-3.2008: Secure Hash Standard"; - - } - - feature crypt-hash-sha-512 { - description - "Indicates that the device supports the SHA-512 - hash function in 'crypt-hash' values"; - reference - "FIPS.180-3.2008: Secure Hash Standard"; - - } - } // module iana-crypt-hash +} \ No newline at end of file diff --git a/src/confd/yang/iana-if-type.yang b/src/confd/yang/iana-if-type.yang new file mode 120000 index 00000000..e069e989 --- /dev/null +++ b/src/confd/yang/iana-if-type.yang @@ -0,0 +1 @@ +iana-if-type@2017-01-19.yang \ No newline at end of file diff --git a/src/confd/yang/iana-if-type@2017-01-19.yang b/src/confd/yang/iana-if-type@2017-01-19.yang new file mode 100644 index 00000000..7bfee364 --- /dev/null +++ b/src/confd/yang/iana-if-type@2017-01-19.yang @@ -0,0 +1,1619 @@ +module iana-if-type { + namespace "urn:ietf:params:xml:ns:yang:iana-if-type"; + prefix ianaift; + + import ietf-interfaces { + prefix if; + } + + organization "IANA"; + contact + " Internet Assigned Numbers Authority + + Postal: ICANN + 12025 Waterfront Drive, Suite 300 + Los Angeles, CA 90094-2536 + United States + + Tel: +1 310 301 5800 + "; + description + "This YANG module defines YANG identities for IANA-registered + interface types. + + This YANG module is maintained by IANA and reflects the + 'ifType definitions' registry. + + The latest revision of this YANG module can be obtained from + the IANA web site. + + Requests for new values should be made to IANA via + email (iana&iana.org). + + Copyright (c) 2014 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 + (http://trustee.ietf.org/license-info). + + The initial version of this YANG module is part of RFC 7224; + see the RFC itself for full legal notices."; + reference + "IANA 'ifType definitions' registry. + "; + + revision 2017-01-19 { + description + "Registered ifType 289."; + } + + revision 2016-11-23 { + description + "Registered ifTypes 283-288."; + } + + revision 2016-06-09 { + description + "Registered ifType 282."; + } + revision 2016-05-03 { + description + "Registered ifType 281."; + } + revision 2015-06-12 { + description + "Corrected formatting issue."; + } + revision 2014-09-24 { + description + "Registered ifType 280."; + } + revision 2014-09-19 { + description + "Registered ifType 279."; + } + revision 2014-07-03 { + description + "Registered ifTypes 277-278."; + } + revision 2014-05-19 { + description + "Updated the contact address."; + } + revision 2014-05-08 { + description + "Initial revision."; + reference + "RFC 7224: IANA Interface Type YANG Module"; + } + + identity iana-interface-type { + base if:interface-type; + description + "This identity is used as a base for all interface types + defined in the 'ifType definitions' registry."; + } + + identity other { + base iana-interface-type; + } + identity regular1822 { + base iana-interface-type; + } + identity hdh1822 { + base iana-interface-type; + } + identity ddnX25 { + base iana-interface-type; + } + identity rfc877x25 { + base iana-interface-type; + reference + "RFC 1382 - SNMP MIB Extension for the X.25 Packet Layer"; + } + identity ethernetCsmacd { + base iana-interface-type; + description + "For all Ethernet-like interfaces, regardless of speed, + as per RFC 3635."; + reference + "RFC 3635 - Definitions of Managed Objects for the + Ethernet-like Interface Types"; + } + identity iso88023Csmacd { + base iana-interface-type; + status deprecated; + description + "Deprecated via RFC 3635. + Use ethernetCsmacd(6) instead."; + reference + "RFC 3635 - Definitions of Managed Objects for the + Ethernet-like Interface Types"; + } + identity iso88024TokenBus { + base iana-interface-type; + } + identity iso88025TokenRing { + base iana-interface-type; + } + identity iso88026Man { + base iana-interface-type; + } + identity starLan { + base iana-interface-type; + status deprecated; + description + "Deprecated via RFC 3635. + Use ethernetCsmacd(6) instead."; + reference + "RFC 3635 - Definitions of Managed Objects for the + Ethernet-like Interface Types"; + } + identity proteon10Mbit { + base iana-interface-type; + } + identity proteon80Mbit { + base iana-interface-type; + } + identity hyperchannel { + base iana-interface-type; + } + identity fddi { + base iana-interface-type; + reference + "RFC 1512 - FDDI Management Information Base"; + } + identity lapb { + base iana-interface-type; + reference + "RFC 1381 - SNMP MIB Extension for X.25 LAPB"; + } + identity sdlc { + base iana-interface-type; + } + identity ds1 { + base iana-interface-type; + description + "DS1-MIB."; + reference + "RFC 4805 - Definitions of Managed Objects for the + DS1, J1, E1, DS2, and E2 Interface Types"; + } + identity e1 { + base iana-interface-type; + status obsolete; + description + "Obsolete; see DS1-MIB."; + reference + "RFC 4805 - Definitions of Managed Objects for the + DS1, J1, E1, DS2, and E2 Interface Types"; + } + identity basicISDN { + base iana-interface-type; + description + "No longer used. See also RFC 2127."; + } + identity primaryISDN { + base iana-interface-type; + description + "No longer used. See also RFC 2127."; + } + identity propPointToPointSerial { + base iana-interface-type; + description + "Proprietary serial."; + } + identity ppp { + base iana-interface-type; + } + identity softwareLoopback { + base iana-interface-type; + } + identity eon { + base iana-interface-type; + description + "CLNP over IP."; + } + identity ethernet3Mbit { + base iana-interface-type; + } + identity nsip { + base iana-interface-type; + description + "XNS over IP."; + } + identity slip { + base iana-interface-type; + description + "Generic SLIP."; + } + identity ultra { + base iana-interface-type; + description + "Ultra Technologies."; + } + identity ds3 { + base iana-interface-type; + description + "DS3-MIB."; + reference + "RFC 3896 - Definitions of Managed Objects for the + DS3/E3 Interface Type"; + } + identity sip { + base iana-interface-type; + description + "SMDS, coffee."; + reference + "RFC 1694 - Definitions of Managed Objects for SMDS + Interfaces using SMIv2"; + } + identity frameRelay { + base iana-interface-type; + description + "DTE only."; + reference + "RFC 2115 - Management Information Base for Frame Relay + DTEs Using SMIv2"; + } + identity rs232 { + base iana-interface-type; + reference + "RFC 1659 - Definitions of Managed Objects for RS-232-like + Hardware Devices using SMIv2"; + } + identity para { + base iana-interface-type; + description + "Parallel-port."; + reference + "RFC 1660 - Definitions of Managed Objects for + Parallel-printer-like Hardware Devices using + SMIv2"; + } + identity arcnet { + base iana-interface-type; + description + "ARCnet."; + } + identity arcnetPlus { + base iana-interface-type; + description + "ARCnet Plus."; + } + identity atm { + base iana-interface-type; + description + "ATM cells."; + } + identity miox25 { + base iana-interface-type; + reference + "RFC 1461 - SNMP MIB extension for Multiprotocol + Interconnect over X.25"; + } + identity sonet { + base iana-interface-type; + description + "SONET or SDH."; + } + identity x25ple { + base iana-interface-type; + reference + "RFC 2127 - ISDN Management Information Base using SMIv2"; + } + identity iso88022llc { + base iana-interface-type; + } + identity localTalk { + base iana-interface-type; + } + identity smdsDxi { + base iana-interface-type; + } + identity frameRelayService { + base iana-interface-type; + description + "FRNETSERV-MIB."; + reference + "RFC 2954 - Definitions of Managed Objects for Frame + Relay Service"; + } + identity v35 { + base iana-interface-type; + } + identity hssi { + base iana-interface-type; + } + identity hippi { + base iana-interface-type; + } + identity modem { + base iana-interface-type; + description + "Generic modem."; + } + identity aal5 { + base iana-interface-type; + description + "AAL5 over ATM."; + } + identity sonetPath { + base iana-interface-type; + } + identity sonetVT { + base iana-interface-type; + } + identity smdsIcip { + base iana-interface-type; + description + "SMDS InterCarrier Interface."; + } + identity propVirtual { + base iana-interface-type; + description + "Proprietary virtual/internal."; + reference + "RFC 2863 - The Interfaces Group MIB"; + } + identity propMultiplexor { + base iana-interface-type; + description + "Proprietary multiplexing."; + reference + "RFC 2863 - The Interfaces Group MIB"; + } + identity ieee80212 { + base iana-interface-type; + description + "100BaseVG."; + } + identity fibreChannel { + base iana-interface-type; + description + "Fibre Channel."; + } + identity hippiInterface { + base iana-interface-type; + description + "HIPPI interfaces."; + } + identity frameRelayInterconnect { + base iana-interface-type; + status obsolete; + description + "Obsolete; use either + frameRelay(32) or frameRelayService(44)."; + } + identity aflane8023 { + base iana-interface-type; + description + "ATM Emulated LAN for 802.3."; + } + identity aflane8025 { + base iana-interface-type; + description + "ATM Emulated LAN for 802.5."; + } + identity cctEmul { + base iana-interface-type; + description + "ATM Emulated circuit."; + } + identity fastEther { + base iana-interface-type; + status deprecated; + description + "Obsoleted via RFC 3635. + ethernetCsmacd(6) should be used instead."; + reference + "RFC 3635 - Definitions of Managed Objects for the + Ethernet-like Interface Types"; + } + identity isdn { + base iana-interface-type; + description + "ISDN and X.25."; + reference + "RFC 1356 - Multiprotocol Interconnect on X.25 and ISDN + in the Packet Mode"; + } + identity v11 { + base iana-interface-type; + description + "CCITT V.11/X.21."; + } + identity v36 { + base iana-interface-type; + description + "CCITT V.36."; + } + identity g703at64k { + base iana-interface-type; + description + "CCITT G703 at 64Kbps."; + } + identity g703at2mb { + base iana-interface-type; + status obsolete; + description + "Obsolete; see DS1-MIB."; + } + identity qllc { + base iana-interface-type; + description + "SNA QLLC."; + } + identity fastEtherFX { + base iana-interface-type; + status deprecated; + description + "Obsoleted via RFC 3635. + ethernetCsmacd(6) should be used instead."; + reference + "RFC 3635 - Definitions of Managed Objects for the + Ethernet-like Interface Types"; + } + identity channel { + base iana-interface-type; + description + "Channel."; + } + identity ieee80211 { + base iana-interface-type; + description + "Radio spread spectrum."; + } + identity ibm370parChan { + base iana-interface-type; + description + "IBM System 360/370 OEMI Channel."; + } + identity escon { + base iana-interface-type; + description + "IBM Enterprise Systems Connection."; + } + identity dlsw { + base iana-interface-type; + description + "Data Link Switching."; + } + identity isdns { + base iana-interface-type; + description + "ISDN S/T interface."; + } + identity isdnu { + base iana-interface-type; + description + "ISDN U interface."; + } + identity lapd { + base iana-interface-type; + description + "Link Access Protocol D."; + } + identity ipSwitch { + base iana-interface-type; + description + "IP Switching Objects."; + } + identity rsrb { + base iana-interface-type; + description + "Remote Source Route Bridging."; + } + identity atmLogical { + base iana-interface-type; + description + "ATM Logical Port."; + reference + "RFC 3606 - Definitions of Supplemental Managed Objects + for ATM Interface"; + } + identity ds0 { + base iana-interface-type; + description + "Digital Signal Level 0."; + reference + "RFC 2494 - Definitions of Managed Objects for the DS0 + and DS0 Bundle Interface Type"; + } + identity ds0Bundle { + base iana-interface-type; + description + "Group of ds0s on the same ds1."; + reference + "RFC 2494 - Definitions of Managed Objects for the DS0 + and DS0 Bundle Interface Type"; + } + identity bsc { + base iana-interface-type; + description + "Bisynchronous Protocol."; + } + identity async { + base iana-interface-type; + description + "Asynchronous Protocol."; + } + identity cnr { + base iana-interface-type; + description + "Combat Net Radio."; + } + identity iso88025Dtr { + base iana-interface-type; + description + "ISO 802.5r DTR."; + } + identity eplrs { + base iana-interface-type; + description + "Ext Pos Loc Report Sys."; + } + identity arap { + base iana-interface-type; + description + "Appletalk Remote Access Protocol."; + } + identity propCnls { + base iana-interface-type; + description + "Proprietary Connectionless Protocol."; + } + identity hostPad { + base iana-interface-type; + description + "CCITT-ITU X.29 PAD Protocol."; + } + identity termPad { + base iana-interface-type; + description + "CCITT-ITU X.3 PAD Facility."; + } + identity frameRelayMPI { + base iana-interface-type; + description + "Multiproto Interconnect over FR."; + } + identity x213 { + base iana-interface-type; + description + "CCITT-ITU X213."; + } + identity adsl { + base iana-interface-type; + description + "Asymmetric Digital Subscriber Loop."; + } + identity radsl { + base iana-interface-type; + description + "Rate-Adapt. Digital Subscriber Loop."; + } + identity sdsl { + base iana-interface-type; + description + "Symmetric Digital Subscriber Loop."; + } + identity vdsl { + base iana-interface-type; + description + "Very H-Speed Digital Subscrib. Loop."; + } + identity iso88025CRFPInt { + base iana-interface-type; + description + "ISO 802.5 CRFP."; + } + identity myrinet { + base iana-interface-type; + description + "Myricom Myrinet."; + } + identity voiceEM { + base iana-interface-type; + description + "Voice recEive and transMit."; + } + identity voiceFXO { + base iana-interface-type; + description + "Voice Foreign Exchange Office."; + } + identity voiceFXS { + base iana-interface-type; + description + "Voice Foreign Exchange Station."; + } + identity voiceEncap { + base iana-interface-type; + description + "Voice encapsulation."; + } + identity voiceOverIp { + base iana-interface-type; + description + "Voice over IP encapsulation."; + } + identity atmDxi { + base iana-interface-type; + description + "ATM DXI."; + } + identity atmFuni { + base iana-interface-type; + description + "ATM FUNI."; + } + identity atmIma { + base iana-interface-type; + description + "ATM IMA."; + } + identity pppMultilinkBundle { + base iana-interface-type; + description + "PPP Multilink Bundle."; + } + identity ipOverCdlc { + base iana-interface-type; + description + "IBM ipOverCdlc."; + } + identity ipOverClaw { + base iana-interface-type; + description + "IBM Common Link Access to Workstn."; + } + identity stackToStack { + base iana-interface-type; + description + "IBM stackToStack."; + } + identity virtualIpAddress { + base iana-interface-type; + description + "IBM VIPA."; + } + identity mpc { + base iana-interface-type; + description + "IBM multi-protocol channel support."; + } + identity ipOverAtm { + base iana-interface-type; + description + "IBM ipOverAtm."; + reference + "RFC 2320 - Definitions of Managed Objects for Classical IP + and ARP Over ATM Using SMIv2 (IPOA-MIB)"; + } + identity iso88025Fiber { + base iana-interface-type; + description + "ISO 802.5j Fiber Token Ring."; + } + identity tdlc { + base iana-interface-type; + description + "IBM twinaxial data link control."; + } + identity gigabitEthernet { + base iana-interface-type; + status deprecated; + description + "Obsoleted via RFC 3635. + ethernetCsmacd(6) should be used instead."; + reference + "RFC 3635 - Definitions of Managed Objects for the + Ethernet-like Interface Types"; + } + identity hdlc { + base iana-interface-type; + description + "HDLC."; + } + identity lapf { + base iana-interface-type; + description + "LAP F."; + } + identity v37 { + base iana-interface-type; + description + "V.37."; + } + identity x25mlp { + base iana-interface-type; + description + "Multi-Link Protocol."; + } + identity x25huntGroup { + base iana-interface-type; + description + "X25 Hunt Group."; + } + identity transpHdlc { + base iana-interface-type; + description + "Transp HDLC."; + } + identity interleave { + base iana-interface-type; + description + "Interleave channel."; + } + identity fast { + base iana-interface-type; + description + "Fast channel."; + } + identity ip { + base iana-interface-type; + description + "IP (for APPN HPR in IP networks)."; + } + identity docsCableMaclayer { + base iana-interface-type; + description + "CATV Mac Layer."; + } + identity docsCableDownstream { + base iana-interface-type; + description + "CATV Downstream interface."; + } + identity docsCableUpstream { + base iana-interface-type; + description + "CATV Upstream interface."; + } + identity a12MppSwitch { + base iana-interface-type; + description + "Avalon Parallel Processor."; + } + identity tunnel { + base iana-interface-type; + description + "Encapsulation interface."; + } + identity coffee { + base iana-interface-type; + description + "Coffee pot."; + reference + "RFC 2325 - Coffee MIB"; + } + identity ces { + base iana-interface-type; + description + "Circuit Emulation Service."; + } + identity atmSubInterface { + base iana-interface-type; + description + "ATM Sub Interface."; + } + identity l2vlan { + base iana-interface-type; + description + "Layer 2 Virtual LAN using 802.1Q."; + } + identity l3ipvlan { + base iana-interface-type; + description + "Layer 3 Virtual LAN using IP."; + } + identity l3ipxvlan { + base iana-interface-type; + description + "Layer 3 Virtual LAN using IPX."; + } + identity digitalPowerline { + base iana-interface-type; + description + "IP over Power Lines."; + } + identity mediaMailOverIp { + base iana-interface-type; + description + "Multimedia Mail over IP."; + } + identity dtm { + base iana-interface-type; + description + "Dynamic synchronous Transfer Mode."; + } + identity dcn { + base iana-interface-type; + description + "Data Communications Network."; + } + identity ipForward { + base iana-interface-type; + description + "IP Forwarding Interface."; + } + identity msdsl { + base iana-interface-type; + description + "Multi-rate Symmetric DSL."; + } + identity ieee1394 { + base iana-interface-type; + + description + "IEEE1394 High Performance Serial Bus."; + } + identity if-gsn { + base iana-interface-type; + description + "HIPPI-6400."; + } + identity dvbRccMacLayer { + base iana-interface-type; + description + "DVB-RCC MAC Layer."; + } + identity dvbRccDownstream { + base iana-interface-type; + description + "DVB-RCC Downstream Channel."; + } + identity dvbRccUpstream { + base iana-interface-type; + description + "DVB-RCC Upstream Channel."; + } + identity atmVirtual { + base iana-interface-type; + description + "ATM Virtual Interface."; + } + identity mplsTunnel { + base iana-interface-type; + description + "MPLS Tunnel Virtual Interface."; + } + identity srp { + base iana-interface-type; + description + "Spatial Reuse Protocol."; + } + identity voiceOverAtm { + base iana-interface-type; + description + "Voice over ATM."; + } + identity voiceOverFrameRelay { + base iana-interface-type; + description + "Voice Over Frame Relay."; + } + identity idsl { + base iana-interface-type; + description + "Digital Subscriber Loop over ISDN."; + } + identity compositeLink { + base iana-interface-type; + description + "Avici Composite Link Interface."; + } + identity ss7SigLink { + base iana-interface-type; + description + "SS7 Signaling Link."; + } + identity propWirelessP2P { + base iana-interface-type; + description + "Prop. P2P wireless interface."; + } + identity frForward { + base iana-interface-type; + description + "Frame Forward Interface."; + } + identity rfc1483 { + base iana-interface-type; + description + "Multiprotocol over ATM AAL5."; + reference + "RFC 1483 - Multiprotocol Encapsulation over ATM + Adaptation Layer 5"; + } + identity usb { + base iana-interface-type; + description + "USB Interface."; + } + identity ieee8023adLag { + base iana-interface-type; + description + "IEEE 802.3ad Link Aggregate."; + } + identity bgppolicyaccounting { + base iana-interface-type; + description + "BGP Policy Accounting."; + } + identity frf16MfrBundle { + base iana-interface-type; + description + "FRF.16 Multilink Frame Relay."; + } + identity h323Gatekeeper { + base iana-interface-type; + description + "H323 Gatekeeper."; + } + identity h323Proxy { + base iana-interface-type; + description + "H323 Voice and Video Proxy."; + } + identity mpls { + base iana-interface-type; + description + "MPLS."; + } + identity mfSigLink { + base iana-interface-type; + description + "Multi-frequency signaling link."; + } + identity hdsl2 { + base iana-interface-type; + description + "High Bit-Rate DSL - 2nd generation."; + } + identity shdsl { + base iana-interface-type; + description + "Multirate HDSL2."; + } + identity ds1FDL { + base iana-interface-type; + description + "Facility Data Link (4Kbps) on a DS1."; + } + identity pos { + base iana-interface-type; + description + "Packet over SONET/SDH Interface."; + } + identity dvbAsiIn { + base iana-interface-type; + description + "DVB-ASI Input."; + } + identity dvbAsiOut { + base iana-interface-type; + description + "DVB-ASI Output."; + } + identity plc { + base iana-interface-type; + description + "Power Line Communications."; + } + identity nfas { + base iana-interface-type; + description + "Non-Facility Associated Signaling."; + } + identity tr008 { + base iana-interface-type; + description + "TR008."; + } + identity gr303RDT { + base iana-interface-type; + description + "Remote Digital Terminal."; + } + identity gr303IDT { + base iana-interface-type; + description + "Integrated Digital Terminal."; + } + identity isup { + base iana-interface-type; + description + "ISUP."; + } + identity propDocsWirelessMaclayer { + base iana-interface-type; + description + "Cisco proprietary Maclayer."; + } + identity propDocsWirelessDownstream { + base iana-interface-type; + description + "Cisco proprietary Downstream."; + } + identity propDocsWirelessUpstream { + base iana-interface-type; + description + "Cisco proprietary Upstream."; + } + identity hiperlan2 { + base iana-interface-type; + description + "HIPERLAN Type 2 Radio Interface."; + } + identity propBWAp2Mp { + base iana-interface-type; + description + "PropBroadbandWirelessAccesspt2Multipt (use of this value + for IEEE 802.16 WMAN interfaces as per IEEE Std 802.16f + is deprecated, and ieee80216WMAN(237) should be used + instead)."; + } + identity sonetOverheadChannel { + base iana-interface-type; + description + "SONET Overhead Channel."; + } + identity digitalWrapperOverheadChannel { + base iana-interface-type; + description + "Digital Wrapper."; + } + identity aal2 { + base iana-interface-type; + description + "ATM adaptation layer 2."; + } + identity radioMAC { + base iana-interface-type; + description + "MAC layer over radio links."; + } + identity atmRadio { + base iana-interface-type; + description + "ATM over radio links."; + } + identity imt { + base iana-interface-type; + description + "Inter-Machine Trunks."; + } + identity mvl { + base iana-interface-type; + description + "Multiple Virtual Lines DSL."; + } + identity reachDSL { + base iana-interface-type; + description + "Long Reach DSL."; + } + identity frDlciEndPt { + base iana-interface-type; + description + "Frame Relay DLCI End Point."; + } + identity atmVciEndPt { + base iana-interface-type; + description + "ATM VCI End Point."; + } + identity opticalChannel { + base iana-interface-type; + description + "Optical Channel."; + } + identity opticalTransport { + base iana-interface-type; + description + "Optical Transport."; + } + identity propAtm { + base iana-interface-type; + description + "Proprietary ATM."; + } + identity voiceOverCable { + base iana-interface-type; + description + "Voice Over Cable Interface."; + } + identity infiniband { + base iana-interface-type; + description + "Infiniband."; + } + identity teLink { + base iana-interface-type; + description + "TE Link."; + } + identity q2931 { + base iana-interface-type; + description + "Q.2931."; + } + identity virtualTg { + base iana-interface-type; + description + "Virtual Trunk Group."; + } + identity sipTg { + base iana-interface-type; + description + "SIP Trunk Group."; + } + identity sipSig { + base iana-interface-type; + description + "SIP Signaling."; + } + identity docsCableUpstreamChannel { + base iana-interface-type; + description + "CATV Upstream Channel."; + } + identity econet { + base iana-interface-type; + description + "Acorn Econet."; + } + identity pon155 { + base iana-interface-type; + description + "FSAN 155Mb Symetrical PON interface."; + } + identity pon622 { + base iana-interface-type; + description + "FSAN 622Mb Symetrical PON interface."; + } + identity bridge { + base iana-interface-type; + description + "Transparent bridge interface."; + } + identity linegroup { + base iana-interface-type; + description + "Interface common to multiple lines."; + } + identity voiceEMFGD { + base iana-interface-type; + description + "Voice E&M Feature Group D."; + } + identity voiceFGDEANA { + base iana-interface-type; + description + "Voice FGD Exchange Access North American."; + } + identity voiceDID { + base iana-interface-type; + description + "Voice Direct Inward Dialing."; + } + identity mpegTransport { + base iana-interface-type; + description + "MPEG transport interface."; + } + identity sixToFour { + base iana-interface-type; + status deprecated; + description + "6to4 interface (DEPRECATED)."; + reference + "RFC 4087 - IP Tunnel MIB"; + } + identity gtp { + base iana-interface-type; + description + "GTP (GPRS Tunneling Protocol)."; + } + identity pdnEtherLoop1 { + base iana-interface-type; + description + "Paradyne EtherLoop 1."; + } + identity pdnEtherLoop2 { + base iana-interface-type; + description + "Paradyne EtherLoop 2."; + } + identity opticalChannelGroup { + base iana-interface-type; + description + "Optical Channel Group."; + } + identity homepna { + base iana-interface-type; + description + "HomePNA ITU-T G.989."; + } + identity gfp { + base iana-interface-type; + description + "Generic Framing Procedure (GFP)."; + } + identity ciscoISLvlan { + base iana-interface-type; + description + "Layer 2 Virtual LAN using Cisco ISL."; + } + identity actelisMetaLOOP { + base iana-interface-type; + description + "Acteleis proprietary MetaLOOP High Speed Link."; + } + identity fcipLink { + base iana-interface-type; + description + "FCIP Link."; + } + identity rpr { + base iana-interface-type; + description + "Resilient Packet Ring Interface Type."; + } + identity qam { + base iana-interface-type; + description + "RF Qam Interface."; + } + identity lmp { + base iana-interface-type; + description + "Link Management Protocol."; + reference + "RFC 4327 - Link Management Protocol (LMP) Management + Information Base (MIB)"; + } + identity cblVectaStar { + base iana-interface-type; + description + "Cambridge Broadband Networks Limited VectaStar."; + } + identity docsCableMCmtsDownstream { + base iana-interface-type; + description + "CATV Modular CMTS Downstream Interface."; + } + identity adsl2 { + base iana-interface-type; + status deprecated; + description + "Asymmetric Digital Subscriber Loop Version 2 + (DEPRECATED/OBSOLETED - please use adsl2plus(238) + instead)."; + reference + "RFC 4706 - Definitions of Managed Objects for Asymmetric + Digital Subscriber Line 2 (ADSL2)"; + } + identity macSecControlledIF { + base iana-interface-type; + description + "MACSecControlled."; + } + identity macSecUncontrolledIF { + base iana-interface-type; + description + "MACSecUncontrolled."; + } + identity aviciOpticalEther { + base iana-interface-type; + description + "Avici Optical Ethernet Aggregate."; + } + identity atmbond { + base iana-interface-type; + description + "atmbond."; + } + identity voiceFGDOS { + base iana-interface-type; + description + "Voice FGD Operator Services."; + } + identity mocaVersion1 { + base iana-interface-type; + description + "MultiMedia over Coax Alliance (MoCA) Interface + as documented in information provided privately to IANA."; + } + identity ieee80216WMAN { + base iana-interface-type; + description + "IEEE 802.16 WMAN interface."; + } + identity adsl2plus { + base iana-interface-type; + description + "Asymmetric Digital Subscriber Loop Version 2 - + Version 2 Plus and all variants."; + } + identity dvbRcsMacLayer { + base iana-interface-type; + description + "DVB-RCS MAC Layer."; + reference + "RFC 5728 - The SatLabs Group DVB-RCS MIB"; + } + identity dvbTdm { + base iana-interface-type; + description + "DVB Satellite TDM."; + reference + "RFC 5728 - The SatLabs Group DVB-RCS MIB"; + } + identity dvbRcsTdma { + base iana-interface-type; + description + "DVB-RCS TDMA."; + reference + "RFC 5728 - The SatLabs Group DVB-RCS MIB"; + } + identity x86Laps { + base iana-interface-type; + description + "LAPS based on ITU-T X.86/Y.1323."; + } + identity wwanPP { + base iana-interface-type; + description + "3GPP WWAN."; + } + identity wwanPP2 { + base iana-interface-type; + description + "3GPP2 WWAN."; + } + identity voiceEBS { + base iana-interface-type; + description + "Voice P-phone EBS physical interface."; + } + identity ifPwType { + base iana-interface-type; + description + "Pseudowire interface type."; + reference + "RFC 5601 - Pseudowire (PW) Management Information Base (MIB)"; + } + identity ilan { + base iana-interface-type; + description + "Internal LAN on a bridge per IEEE 802.1ap."; + } + identity pip { + base iana-interface-type; + description + "Provider Instance Port on a bridge per IEEE 802.1ah PBB."; + } + identity aluELP { + base iana-interface-type; + description + "Alcatel-Lucent Ethernet Link Protection."; + } + identity gpon { + base iana-interface-type; + description + "Gigabit-capable passive optical networks (G-PON) as per + ITU-T G.948."; + } + identity vdsl2 { + base iana-interface-type; + description + "Very high speed digital subscriber line Version 2 + (as per ITU-T Recommendation G.993.2)."; + reference + "RFC 5650 - Definitions of Managed Objects for Very High + Speed Digital Subscriber Line 2 (VDSL2)"; + } + identity capwapDot11Profile { + base iana-interface-type; + description + "WLAN Profile Interface."; + reference + "RFC 5834 - Control and Provisioning of Wireless Access + Points (CAPWAP) Protocol Binding MIB for + IEEE 802.11"; + } + identity capwapDot11Bss { + base iana-interface-type; + description + "WLAN BSS Interface."; + reference + "RFC 5834 - Control and Provisioning of Wireless Access + Points (CAPWAP) Protocol Binding MIB for + IEEE 802.11"; + } + identity capwapWtpVirtualRadio { + base iana-interface-type; + description + "WTP Virtual Radio Interface."; + reference + "RFC 5833 - Control and Provisioning of Wireless Access + Points (CAPWAP) Protocol Base MIB"; + } + identity bits { + base iana-interface-type; + description + "bitsport."; + } + identity docsCableUpstreamRfPort { + base iana-interface-type; + description + "DOCSIS CATV Upstream RF Port."; + } + identity cableDownstreamRfPort { + base iana-interface-type; + description + "CATV downstream RF Port."; + } + identity vmwareVirtualNic { + base iana-interface-type; + description + "VMware Virtual Network Interface."; + } + identity ieee802154 { + base iana-interface-type; + description + "IEEE 802.15.4 WPAN interface."; + reference + "IEEE 802.15.4-2006"; + } + identity otnOdu { + base iana-interface-type; + description + "OTN Optical Data Unit."; + } + identity otnOtu { + base iana-interface-type; + description + "OTN Optical channel Transport Unit."; + } + identity ifVfiType { + base iana-interface-type; + description + "VPLS Forwarding Instance Interface Type."; + } + identity g9981 { + base iana-interface-type; + description + "G.998.1 bonded interface."; + } + identity g9982 { + base iana-interface-type; + description + "G.998.2 bonded interface."; + } + identity g9983 { + base iana-interface-type; + description + "G.998.3 bonded interface."; + } + + identity aluEpon { + base iana-interface-type; + description + "Ethernet Passive Optical Networks (E-PON)."; + } + identity aluEponOnu { + base iana-interface-type; + description + "EPON Optical Network Unit."; + } + identity aluEponPhysicalUni { + base iana-interface-type; + description + "EPON physical User to Network interface."; + } + identity aluEponLogicalLink { + base iana-interface-type; + description + "The emulation of a point-to-point link over the EPON + layer."; + } + identity aluGponOnu { + base iana-interface-type; + description + "GPON Optical Network Unit."; + reference + "ITU-T G.984.2"; + } + identity aluGponPhysicalUni { + base iana-interface-type; + description + "GPON physical User to Network interface."; + reference + "ITU-T G.984.2"; + } + identity vmwareNicTeam { + base iana-interface-type; + description + "VMware NIC Team."; + } + identity docsOfdmDownstream { + base iana-interface-type; + description + "CATV Downstream OFDM interface."; + } + identity docsOfdmaUpstream { + base iana-interface-type; + description + "CATV Upstream OFDMA interface."; + } + identity gfast { + base iana-interface-type; + description + "G.fast port."; + reference + "ITU-T G.9701"; + } + identity sdci { + base iana-interface-type; + description + "SDCI (IO-Link)."; + reference + "IEC 61131-9 Edition 1.0 2013-09"; + } + identity xboxWireless { + base iana-interface-type; + description + "Xbox wireless."; + } + identity fastdsl { + base iana-interface-type; + description + "FastDSL."; + reference + "BBF TR-355"; + } + identity docsCableScte55d1FwdOob { + base iana-interface-type; + description + "Cable SCTE 55-1 OOB Forward Channel."; + } + identity docsCableScte55d1RetOob { + base iana-interface-type; + description + "Cable SCTE 55-1 OOB Return Channel."; + } + identity docsCableScte55d2DsOob { + base iana-interface-type; + description + "Cable SCTE 55-2 OOB Downstream Channel."; + } + identity docsCableScte55d2UsOob { + base iana-interface-type; + description + "Cable SCTE 55-2 OOB Upstream Channel."; + } + identity docsCableNdf { + base iana-interface-type; + description + "Cable Narrowband Digital Forward."; + } + identity docsCableNdr { + base iana-interface-type; + description + "Cable Narrowband Digital Return."; + } + identity ptm { + base iana-interface-type; + description + "Packet Transfer Mode."; + } +} diff --git a/src/confd/yang/ietf-datastores.yang b/src/confd/yang/ietf-datastores.yang new file mode 120000 index 00000000..31d0773b --- /dev/null +++ b/src/confd/yang/ietf-datastores.yang @@ -0,0 +1 @@ +ietf-datastores@2018-02-14.yang \ No newline at end of file diff --git a/src/confd/yang/ietf-datastores@2018-02-14.yang b/src/confd/yang/ietf-datastores@2018-02-14.yang new file mode 100644 index 00000000..9e875ab6 --- /dev/null +++ b/src/confd/yang/ietf-datastores@2018-02-14.yang @@ -0,0 +1,117 @@ +module ietf-datastores { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-datastores"; + prefix ds; + + organization + "IETF Network Modeling (NETMOD) Working Group"; + + contact + "WG Web: + + WG List: + + Author: Martin Bjorklund + + + Author: Juergen Schoenwaelder + + + Author: Phil Shafer + + + Author: Kent Watsen + + + Author: Rob Wilton + "; + + description + "This YANG module defines a set of identities for identifying + datastores. + + Copyright (c) 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 8342 + (https://www.rfc-editor.org/info/rfc8342); see the RFC itself + for full legal notices."; + + revision 2018-02-14 { + description + "Initial revision."; + reference + "RFC 8342: Network Management Datastore Architecture (NMDA)"; + } + + /* + * Identities + */ + + identity datastore { + description + "Abstract base identity for datastore identities."; + } + + identity conventional { + base datastore; + description + "Abstract base identity for conventional configuration + datastores."; + } + + identity running { + base conventional; + description + "The running configuration datastore."; + } + + identity candidate { + base conventional; + description + "The candidate configuration datastore."; + } + + identity startup { + base conventional; + description + "The startup configuration datastore."; + } + + identity intended { + base conventional; + description + "The intended configuration datastore."; + } + + identity dynamic { + base datastore; + description + "Abstract base identity for dynamic configuration datastores."; + } + + identity operational { + base datastore; + description + "The operational state datastore."; + } + + /* + * Type definitions + */ + + typedef datastore-ref { + type identityref { + base datastore; + } + description + "A datastore identity reference."; + } +} diff --git a/src/confd/yang/ietf-inet-types.yang b/src/confd/yang/ietf-inet-types.yang deleted file mode 100644 index 2f14270d..00000000 --- a/src/confd/yang/ietf-inet-types.yang +++ /dev/null @@ -1,457 +0,0 @@ -module ietf-inet-types { - - namespace "urn:ietf:params:xml:ns:yang:ietf-inet-types"; - prefix "inet"; - - organization - "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; - - contact - "WG Web: - WG List: - - WG Chair: David Kessens - - - WG Chair: Juergen Schoenwaelder - - - Editor: Juergen Schoenwaelder - "; - - description - "This module contains a collection of generally useful derived - YANG data types for Internet addresses and related things. - - Copyright (c) 2013 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 - (http://trustee.ietf.org/license-info). - - This version of this YANG module is part of RFC 6991; see - the RFC itself for full legal notices."; - - revision 2013-07-15 { - description - "This revision adds the following new data types: - - ip-address-no-zone - - ipv4-address-no-zone - - ipv6-address-no-zone"; - reference - "RFC 6991: Common YANG Data Types"; - } - - revision 2010-09-24 { - description - "Initial revision."; - reference - "RFC 6021: Common YANG Data Types"; - } - - /*** collection of types related to protocol fields ***/ - - typedef ip-version { - type enumeration { - enum unknown { - value "0"; - description - "An unknown or unspecified version of the Internet - protocol."; - } - enum ipv4 { - value "1"; - description - "The IPv4 protocol as defined in RFC 791."; - } - enum ipv6 { - value "2"; - description - "The IPv6 protocol as defined in RFC 2460."; - } - } - description - "This value represents the version of the IP protocol. - - In the value set and its semantics, this type is equivalent - to the InetVersion textual convention of the SMIv2."; - reference - "RFC 791: Internet Protocol - RFC 2460: Internet Protocol, Version 6 (IPv6) Specification - RFC 4001: Textual Conventions for Internet Network Addresses"; - } - - typedef dscp { - type uint8 { - range "0..63"; - } - description - "The dscp type represents a Differentiated Services Code Point - that may be used for marking packets in a traffic stream. - In the value set and its semantics, this type is equivalent - to the Dscp textual convention of the SMIv2."; - reference - "RFC 3289: Management Information Base for the Differentiated - Services Architecture - RFC 2474: Definition of the Differentiated Services Field - (DS Field) in the IPv4 and IPv6 Headers - RFC 2780: IANA Allocation Guidelines For Values In - the Internet Protocol and Related Headers"; - } - - typedef ipv6-flow-label { - type uint32 { - range "0..1048575"; - } - description - "The ipv6-flow-label type represents the flow identifier or Flow - Label in an IPv6 packet header that may be used to - discriminate traffic flows. - - In the value set and its semantics, this type is equivalent - to the IPv6FlowLabel textual convention of the SMIv2."; - reference - "RFC 3595: Textual Conventions for IPv6 Flow Label - RFC 2460: Internet Protocol, Version 6 (IPv6) Specification"; - } - - typedef port-number { - type uint16 { - range "0..65535"; - } - description - "The port-number type represents a 16-bit port number of an - Internet transport-layer protocol such as UDP, TCP, DCCP, or - SCTP. Port numbers are assigned by IANA. A current list of - all assignments is available from . - - Note that the port number value zero is reserved by IANA. In - situations where the value zero does not make sense, it can - be excluded by subtyping the port-number type. - In the value set and its semantics, this type is equivalent - to the InetPortNumber textual convention of the SMIv2."; - reference - "RFC 768: User Datagram Protocol - RFC 793: Transmission Control Protocol - RFC 4960: Stream Control Transmission Protocol - RFC 4340: Datagram Congestion Control Protocol (DCCP) - RFC 4001: Textual Conventions for Internet Network Addresses"; - } - - /*** collection of types related to autonomous systems ***/ - - typedef as-number { - type uint32; - description - "The as-number type represents autonomous system numbers - which identify an Autonomous System (AS). An AS is a set - of routers under a single technical administration, using - an interior gateway protocol and common metrics to route - packets within the AS, and using an exterior gateway - protocol to route packets to other ASes. IANA maintains - the AS number space and has delegated large parts to the - regional registries. - - Autonomous system numbers were originally limited to 16 - bits. BGP extensions have enlarged the autonomous system - number space to 32 bits. This type therefore uses an uint32 - base type without a range restriction in order to support - a larger autonomous system number space. - - In the value set and its semantics, this type is equivalent - to the InetAutonomousSystemNumber textual convention of - the SMIv2."; - reference - "RFC 1930: Guidelines for creation, selection, and registration - of an Autonomous System (AS) - RFC 4271: A Border Gateway Protocol 4 (BGP-4) - RFC 4001: Textual Conventions for Internet Network Addresses - RFC 6793: BGP Support for Four-Octet Autonomous System (AS) - Number Space"; - } - - /*** collection of types related to IP addresses and hostnames ***/ - - typedef ip-address { - type union { - type inet:ipv4-address; - type inet:ipv6-address; - } - description - "The ip-address type represents an IP address and is IP - version neutral. The format of the textual representation - implies the IP version. This type supports scoped addresses - by allowing zone identifiers in the address format."; - reference - "RFC 4007: IPv6 Scoped Address Architecture"; - } - - typedef ipv4-address { - type string { - pattern - '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' - + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])' - + '(%[\p{N}\p{L}]+)?'; - } - description - "The ipv4-address type represents an IPv4 address in - dotted-quad notation. The IPv4 address may include a zone - index, separated by a % sign. - - The zone index is used to disambiguate identical address - values. For link-local addresses, the zone index will - typically be the interface index number or the name of an - interface. If the zone index is not present, the default - zone of the device will be used. - - The canonical format for the zone index is the numerical - format"; - } - - typedef ipv6-address { - type string { - pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}' - + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|' - + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}' - + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))' - + '(%[\p{N}\p{L}]+)?'; - pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|' - + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)' - + '(%.+)?'; - } - description - "The ipv6-address type represents an IPv6 address in full, - mixed, shortened, and shortened-mixed notation. The IPv6 - address may include a zone index, separated by a % sign. - - The zone index is used to disambiguate identical address - values. For link-local addresses, the zone index will - typically be the interface index number or the name of an - interface. If the zone index is not present, the default - zone of the device will be used. - - The canonical format of IPv6 addresses uses the textual - representation defined in Section 4 of RFC 5952. The - canonical format for the zone index is the numerical - format as described in Section 11.2 of RFC 4007."; - reference - "RFC 4291: IP Version 6 Addressing Architecture - RFC 4007: IPv6 Scoped Address Architecture - RFC 5952: A Recommendation for IPv6 Address Text - Representation"; - } - - typedef ip-address-no-zone { - type union { - type inet:ipv4-address-no-zone; - type inet:ipv6-address-no-zone; - } - description - "The ip-address-no-zone type represents an IP address and is - IP version neutral. The format of the textual representation - implies the IP version. This type does not support scoped - addresses since it does not allow zone identifiers in the - address format."; - reference - "RFC 4007: IPv6 Scoped Address Architecture"; - } - - typedef ipv4-address-no-zone { - type inet:ipv4-address { - pattern '[0-9\.]*'; - } - description - "An IPv4 address without a zone index. This type, derived from - ipv4-address, may be used in situations where the zone is - known from the context and hence no zone index is needed."; - } - - typedef ipv6-address-no-zone { - type inet:ipv6-address { - pattern '[0-9a-fA-F:\.]*'; - } - description - "An IPv6 address without a zone index. This type, derived from - ipv6-address, may be used in situations where the zone is - known from the context and hence no zone index is needed."; - reference - "RFC 4291: IP Version 6 Addressing Architecture - RFC 4007: IPv6 Scoped Address Architecture - RFC 5952: A Recommendation for IPv6 Address Text - Representation"; - } - - typedef ip-prefix { - type union { - type inet:ipv4-prefix; - type inet:ipv6-prefix; - } - description - "The ip-prefix type represents an IP prefix and is IP - version neutral. The format of the textual representations - implies the IP version."; - } - - typedef ipv4-prefix { - type string { - pattern - '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' - + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])' - + '/(([0-9])|([1-2][0-9])|(3[0-2]))'; - } - description - "The ipv4-prefix type represents an IPv4 address prefix. - The prefix length is given by the number following the - slash character and must be less than or equal to 32. - - A prefix length value of n corresponds to an IP address - mask that has n contiguous 1-bits from the most - significant bit (MSB) and all other bits set to 0. - - The canonical format of an IPv4 prefix has all bits of - the IPv4 address set to zero that are not part of the - IPv4 prefix."; - } - - typedef ipv6-prefix { - type string { - pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}' - + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|' - + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}' - + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))' - + '(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'; - pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|' - + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)' - + '(/.+)'; - } - description - "The ipv6-prefix type represents an IPv6 address prefix. - The prefix length is given by the number following the - slash character and must be less than or equal to 128. - - A prefix length value of n corresponds to an IP address - mask that has n contiguous 1-bits from the most - significant bit (MSB) and all other bits set to 0. - - The IPv6 address should have all bits that do not belong - to the prefix set to zero. - - The canonical format of an IPv6 prefix has all bits of - the IPv6 address set to zero that are not part of the - IPv6 prefix. Furthermore, the IPv6 address is represented - as defined in Section 4 of RFC 5952."; - reference - "RFC 5952: A Recommendation for IPv6 Address Text - Representation"; - } - - /*** collection of domain name and URI types ***/ - - typedef domain-name { - type string { - length "1..253"; - pattern - '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*' - + '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)' - + '|\.'; - } - description - "The domain-name type represents a DNS domain name. The - name SHOULD be fully qualified whenever possible. - - Internet domain names are only loosely specified. Section - 3.5 of RFC 1034 recommends a syntax (modified in Section - 2.1 of RFC 1123). The pattern above is intended to allow - for current practice in domain name use, and some possible - future expansion. It is designed to hold various types of - domain names, including names used for A or AAAA records - (host names) and other records, such as SRV records. Note - that Internet host names have a stricter syntax (described - in RFC 952) than the DNS recommendations in RFCs 1034 and - 1123, and that systems that want to store host names in - schema nodes using the domain-name type are recommended to - adhere to this stricter standard to ensure interoperability. - - The encoding of DNS names in the DNS protocol is limited - to 255 characters. Since the encoding consists of labels - prefixed by a length bytes and there is a trailing NULL - byte, only 253 characters can appear in the textual dotted - notation. - - The description clause of schema nodes using the domain-name - type MUST describe when and how these names are resolved to - IP addresses. Note that the resolution of a domain-name value - may require to query multiple DNS records (e.g., A for IPv4 - and AAAA for IPv6). The order of the resolution process and - which DNS record takes precedence can either be defined - explicitly or may depend on the configuration of the - resolver. - - Domain-name values use the US-ASCII encoding. Their canonical - format uses lowercase US-ASCII characters. Internationalized - domain names MUST be A-labels as per RFC 5890."; - reference - "RFC 952: DoD Internet Host Table Specification - RFC 1034: Domain Names - Concepts and Facilities - RFC 1123: Requirements for Internet Hosts -- Application - and Support - RFC 2782: A DNS RR for specifying the location of services - (DNS SRV) - RFC 5890: Internationalized Domain Names in Applications - (IDNA): Definitions and Document Framework"; - } - - typedef host { - type union { - type inet:ip-address; - type inet:domain-name; - } - description - "The host type represents either an IP address or a DNS - domain name."; - } - - typedef uri { - type string; - description - "The uri type represents a Uniform Resource Identifier - (URI) as defined by STD 66. - - Objects using the uri type MUST be in US-ASCII encoding, - and MUST be normalized as described by RFC 3986 Sections - 6.2.1, 6.2.2.1, and 6.2.2.2. All unnecessary - percent-encoding is removed, and all case-insensitive - characters are set to lowercase except for hexadecimal - digits, which are normalized to uppercase as described in - Section 6.2.2.1. - - The purpose of this normalization is to help provide - unique URIs. Note that this normalization is not - sufficient to provide uniqueness. Two URIs that are - textually distinct after this normalization may still be - equivalent. - - Objects using the uri type may restrict the schemes that - they permit. For example, 'data:' and 'urn:' schemes - might not be appropriate. - - A zero-length URI is not a valid URI. This can be used to - express 'URI absent' where required. - - In the value set and its semantics, this type is equivalent - to the Uri SMIv2 textual convention defined in RFC 5017."; - reference - "RFC 3986: Uniform Resource Identifier (URI): Generic Syntax - RFC 3305: Report from the Joint W3C/IETF URI Planning Interest - Group: Uniform Resource Identifiers (URIs), URLs, - and Uniform Resource Names (URNs): Clarifications - and Recommendations - RFC 5017: MIB Textual Conventions for Uniform Resource - Identifiers (URIs)"; - } - -} diff --git a/src/confd/yang/ietf-inet-types.yang b/src/confd/yang/ietf-inet-types.yang new file mode 120000 index 00000000..f2c4cfee --- /dev/null +++ b/src/confd/yang/ietf-inet-types.yang @@ -0,0 +1 @@ +ietf-inet-types@2013-07-15.yang \ No newline at end of file diff --git a/src/confd/yang/ietf-inet-types@2013-07-15.yang b/src/confd/yang/ietf-inet-types@2013-07-15.yang new file mode 100644 index 00000000..eacefb63 --- /dev/null +++ b/src/confd/yang/ietf-inet-types@2013-07-15.yang @@ -0,0 +1,458 @@ +module ietf-inet-types { + + namespace "urn:ietf:params:xml:ns:yang:ietf-inet-types"; + prefix "inet"; + + organization + "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; + + contact + "WG Web: + WG List: + + WG Chair: David Kessens + + + WG Chair: Juergen Schoenwaelder + + + Editor: Juergen Schoenwaelder + "; + + description + "This module contains a collection of generally useful derived + YANG data types for Internet addresses and related things. + + Copyright (c) 2013 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 + (http://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 6991; see + the RFC itself for full legal notices."; + + revision 2013-07-15 { + description + "This revision adds the following new data types: + - ip-address-no-zone + - ipv4-address-no-zone + - ipv6-address-no-zone"; + reference + "RFC 6991: Common YANG Data Types"; + } + + revision 2010-09-24 { + description + "Initial revision."; + reference + "RFC 6021: Common YANG Data Types"; + } + + /*** collection of types related to protocol fields ***/ + + typedef ip-version { + type enumeration { + enum unknown { + value "0"; + description + "An unknown or unspecified version of the Internet + protocol."; + } + enum ipv4 { + value "1"; + description + "The IPv4 protocol as defined in RFC 791."; + } + enum ipv6 { + value "2"; + description + "The IPv6 protocol as defined in RFC 2460."; + } + } + description + "This value represents the version of the IP protocol. + + In the value set and its semantics, this type is equivalent + to the InetVersion textual convention of the SMIv2."; + reference + "RFC 791: Internet Protocol + RFC 2460: Internet Protocol, Version 6 (IPv6) Specification + RFC 4001: Textual Conventions for Internet Network Addresses"; + } + + typedef dscp { + type uint8 { + range "0..63"; + } + description + "The dscp type represents a Differentiated Services Code Point + that may be used for marking packets in a traffic stream. + In the value set and its semantics, this type is equivalent + to the Dscp textual convention of the SMIv2."; + reference + "RFC 3289: Management Information Base for the Differentiated + Services Architecture + RFC 2474: Definition of the Differentiated Services Field + (DS Field) in the IPv4 and IPv6 Headers + RFC 2780: IANA Allocation Guidelines For Values In + the Internet Protocol and Related Headers"; + } + + typedef ipv6-flow-label { + type uint32 { + range "0..1048575"; + } + description + "The ipv6-flow-label type represents the flow identifier or Flow + Label in an IPv6 packet header that may be used to + discriminate traffic flows. + + In the value set and its semantics, this type is equivalent + to the IPv6FlowLabel textual convention of the SMIv2."; + reference + "RFC 3595: Textual Conventions for IPv6 Flow Label + RFC 2460: Internet Protocol, Version 6 (IPv6) Specification"; + } + + typedef port-number { + type uint16 { + range "0..65535"; + } + description + "The port-number type represents a 16-bit port number of an + Internet transport-layer protocol such as UDP, TCP, DCCP, or + SCTP. Port numbers are assigned by IANA. A current list of + all assignments is available from . + + Note that the port number value zero is reserved by IANA. In + situations where the value zero does not make sense, it can + be excluded by subtyping the port-number type. + In the value set and its semantics, this type is equivalent + to the InetPortNumber textual convention of the SMIv2."; + reference + "RFC 768: User Datagram Protocol + RFC 793: Transmission Control Protocol + RFC 4960: Stream Control Transmission Protocol + RFC 4340: Datagram Congestion Control Protocol (DCCP) + RFC 4001: Textual Conventions for Internet Network Addresses"; + } + + /*** collection of types related to autonomous systems ***/ + + typedef as-number { + type uint32; + description + "The as-number type represents autonomous system numbers + which identify an Autonomous System (AS). An AS is a set + of routers under a single technical administration, using + an interior gateway protocol and common metrics to route + packets within the AS, and using an exterior gateway + protocol to route packets to other ASes. IANA maintains + the AS number space and has delegated large parts to the + regional registries. + + Autonomous system numbers were originally limited to 16 + bits. BGP extensions have enlarged the autonomous system + number space to 32 bits. This type therefore uses an uint32 + base type without a range restriction in order to support + a larger autonomous system number space. + + In the value set and its semantics, this type is equivalent + to the InetAutonomousSystemNumber textual convention of + the SMIv2."; + reference + "RFC 1930: Guidelines for creation, selection, and registration + of an Autonomous System (AS) + RFC 4271: A Border Gateway Protocol 4 (BGP-4) + RFC 4001: Textual Conventions for Internet Network Addresses + RFC 6793: BGP Support for Four-Octet Autonomous System (AS) + Number Space"; + } + + /*** collection of types related to IP addresses and hostnames ***/ + + typedef ip-address { + type union { + type inet:ipv4-address; + type inet:ipv6-address; + } + description + "The ip-address type represents an IP address and is IP + version neutral. The format of the textual representation + implies the IP version. This type supports scoped addresses + by allowing zone identifiers in the address format."; + reference + "RFC 4007: IPv6 Scoped Address Architecture"; + } + + typedef ipv4-address { + type string { + pattern + '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])' + + '(%[\p{N}\p{L}]+)?'; + } + description + "The ipv4-address type represents an IPv4 address in + dotted-quad notation. The IPv4 address may include a zone + index, separated by a % sign. + + The zone index is used to disambiguate identical address + values. For link-local addresses, the zone index will + typically be the interface index number or the name of an + interface. If the zone index is not present, the default + zone of the device will be used. + + The canonical format for the zone index is the numerical + format"; + } + + typedef ipv6-address { + type string { + pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}' + + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|' + + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}' + + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))' + + '(%[\p{N}\p{L}]+)?'; + pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|' + + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)' + + '(%.+)?'; + } + description + "The ipv6-address type represents an IPv6 address in full, + mixed, shortened, and shortened-mixed notation. The IPv6 + address may include a zone index, separated by a % sign. + + The zone index is used to disambiguate identical address + values. For link-local addresses, the zone index will + typically be the interface index number or the name of an + interface. If the zone index is not present, the default + zone of the device will be used. + + The canonical format of IPv6 addresses uses the textual + representation defined in Section 4 of RFC 5952. The + canonical format for the zone index is the numerical + format as described in Section 11.2 of RFC 4007."; + reference + "RFC 4291: IP Version 6 Addressing Architecture + RFC 4007: IPv6 Scoped Address Architecture + RFC 5952: A Recommendation for IPv6 Address Text + Representation"; + } + + typedef ip-address-no-zone { + type union { + type inet:ipv4-address-no-zone; + type inet:ipv6-address-no-zone; + } + description + "The ip-address-no-zone type represents an IP address and is + IP version neutral. The format of the textual representation + implies the IP version. This type does not support scoped + addresses since it does not allow zone identifiers in the + address format."; + reference + "RFC 4007: IPv6 Scoped Address Architecture"; + } + + typedef ipv4-address-no-zone { + type inet:ipv4-address { + pattern '[0-9\.]*'; + } + description + "An IPv4 address without a zone index. This type, derived from + ipv4-address, may be used in situations where the zone is + known from the context and hence no zone index is needed."; + } + + typedef ipv6-address-no-zone { + type inet:ipv6-address { + pattern '[0-9a-fA-F:\.]*'; + } + description + "An IPv6 address without a zone index. This type, derived from + ipv6-address, may be used in situations where the zone is + known from the context and hence no zone index is needed."; + reference + "RFC 4291: IP Version 6 Addressing Architecture + RFC 4007: IPv6 Scoped Address Architecture + RFC 5952: A Recommendation for IPv6 Address Text + Representation"; + } + + typedef ip-prefix { + type union { + type inet:ipv4-prefix; + type inet:ipv6-prefix; + } + description + "The ip-prefix type represents an IP prefix and is IP + version neutral. The format of the textual representations + implies the IP version."; + } + + typedef ipv4-prefix { + type string { + pattern + '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])' + + '/(([0-9])|([1-2][0-9])|(3[0-2]))'; + } + description + "The ipv4-prefix type represents an IPv4 address prefix. + The prefix length is given by the number following the + slash character and must be less than or equal to 32. + + A prefix length value of n corresponds to an IP address + mask that has n contiguous 1-bits from the most + significant bit (MSB) and all other bits set to 0. + + The canonical format of an IPv4 prefix has all bits of + the IPv4 address set to zero that are not part of the + IPv4 prefix."; + } + + typedef ipv6-prefix { + type string { + pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}' + + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|' + + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}' + + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))' + + '(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'; + pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|' + + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)' + + '(/.+)'; + } + + description + "The ipv6-prefix type represents an IPv6 address prefix. + The prefix length is given by the number following the + slash character and must be less than or equal to 128. + + A prefix length value of n corresponds to an IP address + mask that has n contiguous 1-bits from the most + significant bit (MSB) and all other bits set to 0. + + The IPv6 address should have all bits that do not belong + to the prefix set to zero. + + The canonical format of an IPv6 prefix has all bits of + the IPv6 address set to zero that are not part of the + IPv6 prefix. Furthermore, the IPv6 address is represented + as defined in Section 4 of RFC 5952."; + reference + "RFC 5952: A Recommendation for IPv6 Address Text + Representation"; + } + + /*** collection of domain name and URI types ***/ + + typedef domain-name { + type string { + pattern + '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*' + + '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)' + + '|\.'; + length "1..253"; + } + description + "The domain-name type represents a DNS domain name. The + name SHOULD be fully qualified whenever possible. + + Internet domain names are only loosely specified. Section + 3.5 of RFC 1034 recommends a syntax (modified in Section + 2.1 of RFC 1123). The pattern above is intended to allow + for current practice in domain name use, and some possible + future expansion. It is designed to hold various types of + domain names, including names used for A or AAAA records + (host names) and other records, such as SRV records. Note + that Internet host names have a stricter syntax (described + in RFC 952) than the DNS recommendations in RFCs 1034 and + 1123, and that systems that want to store host names in + schema nodes using the domain-name type are recommended to + adhere to this stricter standard to ensure interoperability. + + The encoding of DNS names in the DNS protocol is limited + to 255 characters. Since the encoding consists of labels + prefixed by a length bytes and there is a trailing NULL + byte, only 253 characters can appear in the textual dotted + notation. + + The description clause of schema nodes using the domain-name + type MUST describe when and how these names are resolved to + IP addresses. Note that the resolution of a domain-name value + may require to query multiple DNS records (e.g., A for IPv4 + and AAAA for IPv6). The order of the resolution process and + which DNS record takes precedence can either be defined + explicitly or may depend on the configuration of the + resolver. + + Domain-name values use the US-ASCII encoding. Their canonical + format uses lowercase US-ASCII characters. Internationalized + domain names MUST be A-labels as per RFC 5890."; + reference + "RFC 952: DoD Internet Host Table Specification + RFC 1034: Domain Names - Concepts and Facilities + RFC 1123: Requirements for Internet Hosts -- Application + and Support + RFC 2782: A DNS RR for specifying the location of services + (DNS SRV) + RFC 5890: Internationalized Domain Names in Applications + (IDNA): Definitions and Document Framework"; + } + + typedef host { + type union { + type inet:ip-address; + type inet:domain-name; + } + description + "The host type represents either an IP address or a DNS + domain name."; + } + + typedef uri { + type string; + description + "The uri type represents a Uniform Resource Identifier + (URI) as defined by STD 66. + + Objects using the uri type MUST be in US-ASCII encoding, + and MUST be normalized as described by RFC 3986 Sections + 6.2.1, 6.2.2.1, and 6.2.2.2. All unnecessary + percent-encoding is removed, and all case-insensitive + characters are set to lowercase except for hexadecimal + digits, which are normalized to uppercase as described in + Section 6.2.2.1. + + The purpose of this normalization is to help provide + unique URIs. Note that this normalization is not + sufficient to provide uniqueness. Two URIs that are + textually distinct after this normalization may still be + equivalent. + + Objects using the uri type may restrict the schemes that + they permit. For example, 'data:' and 'urn:' schemes + might not be appropriate. + + A zero-length URI is not a valid URI. This can be used to + express 'URI absent' where required. + + In the value set and its semantics, this type is equivalent + to the Uri SMIv2 textual convention defined in RFC 5017."; + reference + "RFC 3986: Uniform Resource Identifier (URI): Generic Syntax + RFC 3305: Report from the Joint W3C/IETF URI Planning Interest + Group: Uniform Resource Identifiers (URIs), URLs, + and Uniform Resource Names (URNs): Clarifications + and Recommendations + RFC 5017: MIB Textual Conventions for Uniform Resource + Identifiers (URIs)"; + } + +} diff --git a/src/confd/yang/ietf-interfaces.yang b/src/confd/yang/ietf-interfaces.yang new file mode 120000 index 00000000..00c2e9ad --- /dev/null +++ b/src/confd/yang/ietf-interfaces.yang @@ -0,0 +1 @@ +ietf-interfaces@2018-02-20.yang \ No newline at end of file diff --git a/src/confd/yang/ietf-interfaces@2018-02-20.yang b/src/confd/yang/ietf-interfaces@2018-02-20.yang new file mode 100644 index 00000000..f66c205c --- /dev/null +++ b/src/confd/yang/ietf-interfaces@2018-02-20.yang @@ -0,0 +1,1123 @@ +module ietf-interfaces { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-interfaces"; + prefix if; + + import ietf-yang-types { + prefix yang; + } + + organization + "IETF NETMOD (Network Modeling) Working Group"; + + contact + "WG Web: + WG List: + + Editor: Martin Bjorklund + "; + + description + "This module contains a collection of YANG definitions for + managing network interfaces. + + Copyright (c) 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 8343; see + the RFC itself for full legal notices."; + + revision 2018-02-20 { + description + "Updated to support NMDA."; + reference + "RFC 8343: A YANG Data Model for Interface Management"; + } + + revision 2014-05-08 { + description + "Initial revision."; + reference + "RFC 7223: A YANG Data Model for Interface Management"; + } + + /* + * Typedefs + */ + + typedef interface-ref { + type leafref { + path "/if:interfaces/if:interface/if:name"; + } + description + "This type is used by data models that need to reference + interfaces."; + } + + /* + * Identities + */ + + identity interface-type { + description + "Base identity from which specific interface types are + derived."; + } + + /* + * Features + */ + + feature arbitrary-names { + description + "This feature indicates that the device allows user-controlled + interfaces to be named arbitrarily."; + } + feature pre-provisioning { + description + "This feature indicates that the device supports + pre-provisioning of interface configuration, i.e., it is + possible to configure an interface whose physical interface + hardware is not present on the device."; + } + feature if-mib { + description + "This feature indicates that the device implements + the IF-MIB."; + reference + "RFC 2863: The Interfaces Group MIB"; + } + + /* + * Data nodes + */ + + container interfaces { + description + "Interface parameters."; + + list interface { + key "name"; + + description + "The list of interfaces on the device. + + The status of an interface is available in this list in the + operational state. If the configuration of a + system-controlled interface cannot be used by the system + (e.g., the interface hardware present does not match the + interface type), then the configuration is not applied to + the system-controlled interface shown in the operational + state. If the configuration of a user-controlled interface + cannot be used by the system, the configured interface is + not instantiated in the operational state. + + System-controlled interfaces created by the system are + always present in this list in the operational state, + whether or not they are configured."; + + leaf name { + type string; + description + "The name of the interface. + + A device MAY restrict the allowed values for this leaf, + possibly depending on the type of the interface. + For system-controlled interfaces, this leaf is the + device-specific name of the interface. + + If a client tries to create configuration for a + system-controlled interface that is not present in the + operational state, the server MAY reject the request if + the implementation does not support pre-provisioning of + interfaces or if the name refers to an interface that can + never exist in the system. A Network Configuration + Protocol (NETCONF) server MUST reply with an rpc-error + with the error-tag 'invalid-value' in this case. + + If the device supports pre-provisioning of interface + configuration, the 'pre-provisioning' feature is + advertised. + + If the device allows arbitrarily named user-controlled + interfaces, the 'arbitrary-names' feature is advertised. + + When a configured user-controlled interface is created by + the system, it is instantiated with the same name in the + operational state. + + A server implementation MAY map this leaf to the ifName + MIB object. Such an implementation needs to use some + mechanism to handle the differences in size and characters + allowed between this leaf and ifName. The definition of + such a mechanism is outside the scope of this document."; + reference + "RFC 2863: The Interfaces Group MIB - ifName"; + } + + leaf description { + type string; + description + "A textual description of the interface. + + A server implementation MAY map this leaf to the ifAlias + MIB object. Such an implementation needs to use some + mechanism to handle the differences in size and characters + allowed between this leaf and ifAlias. The definition of + such a mechanism is outside the scope of this document. + + Since ifAlias is defined to be stored in non-volatile + storage, the MIB implementation MUST map ifAlias to the + value of 'description' in the persistently stored + configuration."; + reference + "RFC 2863: The Interfaces Group MIB - ifAlias"; + } + + leaf type { + type identityref { + base interface-type; + } + mandatory true; + description + "The type of the interface. + + When an interface entry is created, a server MAY + initialize the type leaf with a valid value, e.g., if it + is possible to derive the type from the name of the + interface. + + If a client tries to set the type of an interface to a + value that can never be used by the system, e.g., if the + type is not supported or if the type does not match the + name of the interface, the server MUST reject the request. + A NETCONF server MUST reply with an rpc-error with the + error-tag 'invalid-value' in this case."; + reference + "RFC 2863: The Interfaces Group MIB - ifType"; + } + + leaf enabled { + type boolean; + default "true"; + description + "This leaf contains the configured, desired state of the + interface. + + Systems that implement the IF-MIB use the value of this + leaf in the intended configuration to set + IF-MIB.ifAdminStatus to 'up' or 'down' after an ifEntry + has been initialized, as described in RFC 2863. + + Changes in this leaf in the intended configuration are + reflected in ifAdminStatus."; + reference + "RFC 2863: The Interfaces Group MIB - ifAdminStatus"; + } + + leaf link-up-down-trap-enable { + if-feature if-mib; + type enumeration { + enum enabled { + value 1; + description + "The device will generate linkUp/linkDown SNMP + notifications for this interface."; + } + enum disabled { + value 2; + description + "The device will not generate linkUp/linkDown SNMP + notifications for this interface."; + } + } + description + "Controls whether linkUp/linkDown SNMP notifications + should be generated for this interface. + + If this node is not configured, the value 'enabled' is + operationally used by the server for interfaces that do + not operate on top of any other interface (i.e., there are + no 'lower-layer-if' entries), and 'disabled' otherwise."; + reference + "RFC 2863: The Interfaces Group MIB - + ifLinkUpDownTrapEnable"; + } + + leaf admin-status { + if-feature if-mib; + type enumeration { + enum up { + value 1; + description + "Ready to pass packets."; + } + enum down { + value 2; + description + "Not ready to pass packets and not in some test mode."; + } + enum testing { + value 3; + description + "In some test mode."; + } + } + config false; + mandatory true; + description + "The desired state of the interface. + + This leaf has the same read semantics as ifAdminStatus."; + reference + "RFC 2863: The Interfaces Group MIB - ifAdminStatus"; + } + + leaf oper-status { + type enumeration { + enum up { + value 1; + description + "Ready to pass packets."; + } + enum down { + value 2; + + description + "The interface does not pass any packets."; + } + enum testing { + value 3; + description + "In some test mode. No operational packets can + be passed."; + } + enum unknown { + value 4; + description + "Status cannot be determined for some reason."; + } + enum dormant { + value 5; + description + "Waiting for some external event."; + } + enum not-present { + value 6; + description + "Some component (typically hardware) is missing."; + } + enum lower-layer-down { + value 7; + description + "Down due to state of lower-layer interface(s)."; + } + } + config false; + mandatory true; + description + "The current operational state of the interface. + + This leaf has the same semantics as ifOperStatus."; + reference + "RFC 2863: The Interfaces Group MIB - ifOperStatus"; + } + + leaf last-change { + type yang:date-and-time; + config false; + description + "The time the interface entered its current operational + state. If the current state was entered prior to the + last re-initialization of the local network management + subsystem, then this node is not present."; + reference + "RFC 2863: The Interfaces Group MIB - ifLastChange"; + } + + leaf if-index { + if-feature if-mib; + type int32 { + range "1..2147483647"; + } + config false; + mandatory true; + description + "The ifIndex value for the ifEntry represented by this + interface."; + reference + "RFC 2863: The Interfaces Group MIB - ifIndex"; + } + + leaf phys-address { + type yang:phys-address; + config false; + description + "The interface's address at its protocol sub-layer. For + example, for an 802.x interface, this object normally + contains a Media Access Control (MAC) address. The + interface's media-specific modules must define the bit + and byte ordering and the format of the value of this + object. For interfaces that do not have such an address + (e.g., a serial line), this node is not present."; + reference + "RFC 2863: The Interfaces Group MIB - ifPhysAddress"; + } + + leaf-list higher-layer-if { + type interface-ref; + config false; + description + "A list of references to interfaces layered on top of this + interface."; + reference + "RFC 2863: The Interfaces Group MIB - ifStackTable"; + } + + leaf-list lower-layer-if { + type interface-ref; + config false; + + description + "A list of references to interfaces layered underneath this + interface."; + reference + "RFC 2863: The Interfaces Group MIB - ifStackTable"; + } + + leaf speed { + type yang:gauge64; + units "bits/second"; + config false; + description + "An estimate of the interface's current bandwidth in bits + per second. For interfaces that do not vary in + bandwidth or for those where no accurate estimation can + be made, this node should contain the nominal bandwidth. + For interfaces that have no concept of bandwidth, this + node is not present."; + reference + "RFC 2863: The Interfaces Group MIB - + ifSpeed, ifHighSpeed"; + } + + container statistics { + config false; + description + "A collection of interface-related statistics objects."; + + leaf discontinuity-time { + type yang:date-and-time; + mandatory true; + description + "The time on the most recent occasion at which any one or + more of this interface's counters suffered a + discontinuity. If no such discontinuities have occurred + since the last re-initialization of the local management + subsystem, then this node contains the time the local + management subsystem re-initialized itself."; + } + + leaf in-octets { + type yang:counter64; + description + "The total number of octets received on the interface, + including framing characters. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifHCInOctets"; + } + + leaf in-unicast-pkts { + type yang:counter64; + description + "The number of packets, delivered by this sub-layer to a + higher (sub-)layer, that were not addressed to a + multicast or broadcast address at this sub-layer. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifHCInUcastPkts"; + } + + leaf in-broadcast-pkts { + type yang:counter64; + description + "The number of packets, delivered by this sub-layer to a + higher (sub-)layer, that were addressed to a broadcast + address at this sub-layer. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - + ifHCInBroadcastPkts"; + } + + leaf in-multicast-pkts { + type yang:counter64; + description + "The number of packets, delivered by this sub-layer to a + higher (sub-)layer, that were addressed to a multicast + address at this sub-layer. For a MAC-layer protocol, + this includes both Group and Functional addresses. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - + ifHCInMulticastPkts"; + } + + leaf in-discards { + type yang:counter32; + description + "The number of inbound packets that were chosen to be + discarded even though no errors had been detected to + prevent their being deliverable to a higher-layer + protocol. One possible reason for discarding such a + packet could be to free up buffer space. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifInDiscards"; + } + + leaf in-errors { + type yang:counter32; + description + "For packet-oriented interfaces, the number of inbound + packets that contained errors preventing them from being + deliverable to a higher-layer protocol. For character- + oriented or fixed-length interfaces, the number of + inbound transmission units that contained errors + preventing them from being deliverable to a higher-layer + protocol. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifInErrors"; + } + + leaf in-unknown-protos { + type yang:counter32; + + description + "For packet-oriented interfaces, the number of packets + received via the interface that were discarded because + of an unknown or unsupported protocol. For + character-oriented or fixed-length interfaces that + support protocol multiplexing, the number of + transmission units received via the interface that were + discarded because of an unknown or unsupported protocol. + For any interface that does not support protocol + multiplexing, this counter is not present. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifInUnknownProtos"; + } + + leaf out-octets { + type yang:counter64; + description + "The total number of octets transmitted out of the + interface, including framing characters. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifHCOutOctets"; + } + + leaf out-unicast-pkts { + type yang:counter64; + description + "The total number of packets that higher-level protocols + requested be transmitted and that were not addressed + to a multicast or broadcast address at this sub-layer, + including those that were discarded or not sent. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifHCOutUcastPkts"; + } + + leaf out-broadcast-pkts { + type yang:counter64; + description + "The total number of packets that higher-level protocols + requested be transmitted and that were addressed to a + broadcast address at this sub-layer, including those + that were discarded or not sent. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - + ifHCOutBroadcastPkts"; + } + + leaf out-multicast-pkts { + type yang:counter64; + description + "The total number of packets that higher-level protocols + requested be transmitted and that were addressed to a + multicast address at this sub-layer, including those + that were discarded or not sent. For a MAC-layer + protocol, this includes both Group and Functional + addresses. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - + ifHCOutMulticastPkts"; + } + + leaf out-discards { + type yang:counter32; + description + "The number of outbound packets that were chosen to be + discarded even though no errors had been detected to + prevent their being transmitted. One possible reason + for discarding such a packet could be to free up buffer + space. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifOutDiscards"; + } + + leaf out-errors { + type yang:counter32; + description + "For packet-oriented interfaces, the number of outbound + packets that could not be transmitted because of errors. + For character-oriented or fixed-length interfaces, the + number of outbound transmission units that could not be + transmitted because of errors. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifOutErrors"; + } + } + + } + } + + /* + * Legacy typedefs + */ + + typedef interface-state-ref { + type leafref { + path "/if:interfaces-state/if:interface/if:name"; + } + status deprecated; + description + "This type is used by data models that need to reference + the operationally present interfaces."; + } + + /* + * Legacy operational state data nodes + */ + + container interfaces-state { + config false; + status deprecated; + description + "Data nodes for the operational state of interfaces."; + + list interface { + key "name"; + status deprecated; + + description + "The list of interfaces on the device. + + System-controlled interfaces created by the system are + always present in this list, whether or not they are + configured."; + + leaf name { + type string; + status deprecated; + description + "The name of the interface. + + A server implementation MAY map this leaf to the ifName + MIB object. Such an implementation needs to use some + mechanism to handle the differences in size and characters + allowed between this leaf and ifName. The definition of + such a mechanism is outside the scope of this document."; + reference + "RFC 2863: The Interfaces Group MIB - ifName"; + } + + leaf type { + type identityref { + base interface-type; + } + mandatory true; + status deprecated; + description + "The type of the interface."; + reference + "RFC 2863: The Interfaces Group MIB - ifType"; + } + + leaf admin-status { + if-feature if-mib; + type enumeration { + enum up { + value 1; + description + "Ready to pass packets."; + } + enum down { + value 2; + description + "Not ready to pass packets and not in some test mode."; + } + enum testing { + value 3; + description + "In some test mode."; + } + } + mandatory true; + status deprecated; + description + "The desired state of the interface. + + This leaf has the same read semantics as ifAdminStatus."; + reference + "RFC 2863: The Interfaces Group MIB - ifAdminStatus"; + } + + leaf oper-status { + type enumeration { + enum up { + value 1; + description + "Ready to pass packets."; + } + enum down { + value 2; + description + "The interface does not pass any packets."; + } + enum testing { + value 3; + description + "In some test mode. No operational packets can + be passed."; + } + enum unknown { + value 4; + description + "Status cannot be determined for some reason."; + } + enum dormant { + value 5; + description + "Waiting for some external event."; + } + enum not-present { + value 6; + description + "Some component (typically hardware) is missing."; + } + enum lower-layer-down { + value 7; + description + "Down due to state of lower-layer interface(s)."; + } + } + mandatory true; + status deprecated; + description + "The current operational state of the interface. + + This leaf has the same semantics as ifOperStatus."; + reference + "RFC 2863: The Interfaces Group MIB - ifOperStatus"; + } + + leaf last-change { + type yang:date-and-time; + status deprecated; + description + "The time the interface entered its current operational + state. If the current state was entered prior to the + last re-initialization of the local network management + subsystem, then this node is not present."; + reference + "RFC 2863: The Interfaces Group MIB - ifLastChange"; + } + + leaf if-index { + if-feature if-mib; + type int32 { + range "1..2147483647"; + } + mandatory true; + status deprecated; + description + "The ifIndex value for the ifEntry represented by this + interface."; + + reference + "RFC 2863: The Interfaces Group MIB - ifIndex"; + } + + leaf phys-address { + type yang:phys-address; + status deprecated; + description + "The interface's address at its protocol sub-layer. For + example, for an 802.x interface, this object normally + contains a Media Access Control (MAC) address. The + interface's media-specific modules must define the bit + and byte ordering and the format of the value of this + object. For interfaces that do not have such an address + (e.g., a serial line), this node is not present."; + reference + "RFC 2863: The Interfaces Group MIB - ifPhysAddress"; + } + + leaf-list higher-layer-if { + type interface-state-ref; + status deprecated; + description + "A list of references to interfaces layered on top of this + interface."; + reference + "RFC 2863: The Interfaces Group MIB - ifStackTable"; + } + + leaf-list lower-layer-if { + type interface-state-ref; + status deprecated; + description + "A list of references to interfaces layered underneath this + interface."; + reference + "RFC 2863: The Interfaces Group MIB - ifStackTable"; + } + + leaf speed { + type yang:gauge64; + units "bits/second"; + status deprecated; + description + "An estimate of the interface's current bandwidth in bits + per second. For interfaces that do not vary in + bandwidth or for those where no accurate estimation can + + be made, this node should contain the nominal bandwidth. + For interfaces that have no concept of bandwidth, this + node is not present."; + reference + "RFC 2863: The Interfaces Group MIB - + ifSpeed, ifHighSpeed"; + } + + container statistics { + status deprecated; + description + "A collection of interface-related statistics objects."; + + leaf discontinuity-time { + type yang:date-and-time; + mandatory true; + status deprecated; + description + "The time on the most recent occasion at which any one or + more of this interface's counters suffered a + discontinuity. If no such discontinuities have occurred + since the last re-initialization of the local management + subsystem, then this node contains the time the local + management subsystem re-initialized itself."; + } + + leaf in-octets { + type yang:counter64; + status deprecated; + description + "The total number of octets received on the interface, + including framing characters. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifHCInOctets"; + } + + leaf in-unicast-pkts { + type yang:counter64; + status deprecated; + description + "The number of packets, delivered by this sub-layer to a + higher (sub-)layer, that were not addressed to a + multicast or broadcast address at this sub-layer. + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifHCInUcastPkts"; + } + + leaf in-broadcast-pkts { + type yang:counter64; + status deprecated; + description + "The number of packets, delivered by this sub-layer to a + higher (sub-)layer, that were addressed to a broadcast + address at this sub-layer. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - + ifHCInBroadcastPkts"; + } + + leaf in-multicast-pkts { + type yang:counter64; + status deprecated; + description + "The number of packets, delivered by this sub-layer to a + higher (sub-)layer, that were addressed to a multicast + address at this sub-layer. For a MAC-layer protocol, + this includes both Group and Functional addresses. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - + ifHCInMulticastPkts"; + } + + leaf in-discards { + type yang:counter32; + status deprecated; + + description + "The number of inbound packets that were chosen to be + discarded even though no errors had been detected to + prevent their being deliverable to a higher-layer + protocol. One possible reason for discarding such a + packet could be to free up buffer space. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifInDiscards"; + } + + leaf in-errors { + type yang:counter32; + status deprecated; + description + "For packet-oriented interfaces, the number of inbound + packets that contained errors preventing them from being + deliverable to a higher-layer protocol. For character- + oriented or fixed-length interfaces, the number of + inbound transmission units that contained errors + preventing them from being deliverable to a higher-layer + protocol. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifInErrors"; + } + + leaf in-unknown-protos { + type yang:counter32; + status deprecated; + description + "For packet-oriented interfaces, the number of packets + received via the interface that were discarded because + of an unknown or unsupported protocol. For + character-oriented or fixed-length interfaces that + support protocol multiplexing, the number of + transmission units received via the interface that were + discarded because of an unknown or unsupported protocol. + For any interface that does not support protocol + multiplexing, this counter is not present. + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifInUnknownProtos"; + } + + leaf out-octets { + type yang:counter64; + status deprecated; + description + "The total number of octets transmitted out of the + interface, including framing characters. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifHCOutOctets"; + } + + leaf out-unicast-pkts { + type yang:counter64; + status deprecated; + description + "The total number of packets that higher-level protocols + requested be transmitted and that were not addressed + to a multicast or broadcast address at this sub-layer, + including those that were discarded or not sent. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifHCOutUcastPkts"; + } + + leaf out-broadcast-pkts { + type yang:counter64; + status deprecated; + + description + "The total number of packets that higher-level protocols + requested be transmitted and that were addressed to a + broadcast address at this sub-layer, including those + that were discarded or not sent. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - + ifHCOutBroadcastPkts"; + } + + leaf out-multicast-pkts { + type yang:counter64; + status deprecated; + description + "The total number of packets that higher-level protocols + requested be transmitted and that were addressed to a + multicast address at this sub-layer, including those + that were discarded or not sent. For a MAC-layer + protocol, this includes both Group and Functional + addresses. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - + ifHCOutMulticastPkts"; + } + + leaf out-discards { + type yang:counter32; + status deprecated; + description + "The number of outbound packets that were chosen to be + discarded even though no errors had been detected to + prevent their being transmitted. One possible reason + for discarding such a packet could be to free up buffer + space. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifOutDiscards"; + } + + leaf out-errors { + type yang:counter32; + status deprecated; + description + "For packet-oriented interfaces, the number of outbound + packets that could not be transmitted because of errors. + For character-oriented or fixed-length interfaces, the + number of outbound transmission units that could not be + transmitted because of errors. + + Discontinuities in the value of this counter can occur + at re-initialization of the management system and at + other times as indicated by the value of + 'discontinuity-time'."; + reference + "RFC 2863: The Interfaces Group MIB - ifOutErrors"; + } + } + } + } +} diff --git a/src/confd/yang/ietf-ip.yang b/src/confd/yang/ietf-ip.yang new file mode 120000 index 00000000..d16e72fc --- /dev/null +++ b/src/confd/yang/ietf-ip.yang @@ -0,0 +1 @@ +ietf-ip@2018-02-22.yang \ No newline at end of file diff --git a/src/confd/yang/ietf-ip@2018-02-22.yang b/src/confd/yang/ietf-ip@2018-02-22.yang new file mode 100644 index 00000000..a270f67b --- /dev/null +++ b/src/confd/yang/ietf-ip@2018-02-22.yang @@ -0,0 +1,876 @@ +module ietf-ip { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-ip"; + prefix ip; + + import ietf-interfaces { + prefix if; + } + import ietf-inet-types { + prefix inet; + } + import ietf-yang-types { + prefix yang; + } + + organization + "IETF NETMOD (Network Modeling) Working Group"; + + contact + "WG Web: + WG List: + + Editor: Martin Bjorklund + "; + description + "This module contains a collection of YANG definitions for + managing IP implementations. + + Copyright (c) 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 8344; see + the RFC itself for full legal notices."; + + revision 2018-02-22 { + description + "Updated to support NMDA."; + reference + "RFC 8344: A YANG Data Model for IP Management"; + } + + revision 2014-06-16 { + description + "Initial revision."; + reference + "RFC 7277: A YANG Data Model for IP Management"; + } + + /* + * Features + */ + + feature ipv4-non-contiguous-netmasks { + description + "Indicates support for configuring non-contiguous + subnet masks."; + } + + feature ipv6-privacy-autoconf { + description + "Indicates support for privacy extensions for stateless address + autoconfiguration in IPv6."; + reference + "RFC 4941: Privacy Extensions for Stateless Address + Autoconfiguration in IPv6"; + } + + /* + * Typedefs + */ + + typedef ip-address-origin { + type enumeration { + enum other { + description + "None of the following."; + } + + enum static { + description + "Indicates that the address has been statically + configured -- for example, using the Network Configuration + Protocol (NETCONF) or a command line interface."; + } + enum dhcp { + description + "Indicates an address that has been assigned to this + system by a DHCP server."; + } + enum link-layer { + description + "Indicates an address created by IPv6 stateless + autoconfiguration that embeds a link-layer address in its + interface identifier."; + } + enum random { + description + "Indicates an address chosen by the system at + random, e.g., an IPv4 address within 169.254/16, a + temporary address as described in RFC 4941, or a + semantically opaque address as described in RFC 7217."; + reference + "RFC 4941: Privacy Extensions for Stateless Address + Autoconfiguration in IPv6 + RFC 7217: A Method for Generating Semantically Opaque + Interface Identifiers with IPv6 Stateless + Address Autoconfiguration (SLAAC)"; + } + } + description + "The origin of an address."; + } + + typedef neighbor-origin { + type enumeration { + enum other { + description + "None of the following."; + } + enum static { + description + "Indicates that the mapping has been statically + configured -- for example, using NETCONF or a command line + interface."; + } + + enum dynamic { + description + "Indicates that the mapping has been dynamically resolved + using, for example, IPv4 ARP or the IPv6 Neighbor + Discovery protocol."; + } + } + description + "The origin of a neighbor entry."; + } + + /* + * Data nodes + */ + + augment "/if:interfaces/if:interface" { + description + "IP parameters on interfaces. + + If an interface is not capable of running IP, the server + must not allow the client to configure these parameters."; + + container ipv4 { + presence + "Enables IPv4 unless the 'enabled' leaf + (which defaults to 'true') is set to 'false'"; + description + "Parameters for the IPv4 address family."; + + leaf enabled { + type boolean; + default true; + description + "Controls whether IPv4 is enabled or disabled on this + interface. When IPv4 is enabled, this interface is + connected to an IPv4 stack, and the interface can send + and receive IPv4 packets."; + } + leaf forwarding { + type boolean; + default false; + description + "Controls IPv4 packet forwarding of datagrams received by, + but not addressed to, this interface. IPv4 routers + forward datagrams. IPv4 hosts do not (except those + source-routed via the host)."; + } + + leaf mtu { + type uint16 { + range "68..max"; + } + units "octets"; + description + "The size, in octets, of the largest IPv4 packet that the + interface will send and receive. + + The server may restrict the allowed values for this leaf, + depending on the interface's type. + + If this leaf is not configured, the operationally used MTU + depends on the interface's type."; + reference + "RFC 791: Internet Protocol"; + } + list address { + key "ip"; + description + "The list of IPv4 addresses on the interface."; + + leaf ip { + type inet:ipv4-address-no-zone; + description + "The IPv4 address on the interface."; + } + choice subnet { + mandatory true; + description + "The subnet can be specified as a prefix length or, + if the server supports non-contiguous netmasks, as + a netmask."; + leaf prefix-length { + type uint8 { + range "0..32"; + } + description + "The length of the subnet prefix."; + } + leaf netmask { + if-feature ipv4-non-contiguous-netmasks; + type yang:dotted-quad; + description + "The subnet specified as a netmask."; + } + } + + leaf origin { + type ip-address-origin; + config false; + description + "The origin of this address."; + } + } + list neighbor { + key "ip"; + description + "A list of mappings from IPv4 addresses to + link-layer addresses. + + Entries in this list in the intended configuration are + used as static entries in the ARP Cache. + + In the operational state, this list represents the ARP + Cache."; + reference + "RFC 826: An Ethernet Address Resolution Protocol"; + + leaf ip { + type inet:ipv4-address-no-zone; + description + "The IPv4 address of the neighbor node."; + } + leaf link-layer-address { + type yang:phys-address; + mandatory true; + description + "The link-layer address of the neighbor node."; + } + leaf origin { + type neighbor-origin; + config false; + description + "The origin of this neighbor entry."; + } + } + } + + container ipv6 { + presence + "Enables IPv6 unless the 'enabled' leaf + (which defaults to 'true') is set to 'false'"; + description + "Parameters for the IPv6 address family."; + + leaf enabled { + type boolean; + default true; + description + "Controls whether IPv6 is enabled or disabled on this + interface. When IPv6 is enabled, this interface is + connected to an IPv6 stack, and the interface can send + and receive IPv6 packets."; + } + leaf forwarding { + type boolean; + default false; + description + "Controls IPv6 packet forwarding of datagrams received by, + but not addressed to, this interface. IPv6 routers + forward datagrams. IPv6 hosts do not (except those + source-routed via the host)."; + reference + "RFC 4861: Neighbor Discovery for IP version 6 (IPv6) + Section 6.2.1, IsRouter"; + } + leaf mtu { + type uint32 { + range "1280..max"; + } + units "octets"; + description + "The size, in octets, of the largest IPv6 packet that the + interface will send and receive. + + The server may restrict the allowed values for this leaf, + depending on the interface's type. + + If this leaf is not configured, the operationally used MTU + depends on the interface's type."; + reference + "RFC 8200: Internet Protocol, Version 6 (IPv6) + Specification + Section 5"; + } + + list address { + key "ip"; + description + "The list of IPv6 addresses on the interface."; + + leaf ip { + type inet:ipv6-address-no-zone; + description + "The IPv6 address on the interface."; + } + leaf prefix-length { + type uint8 { + range "0..128"; + } + mandatory true; + description + "The length of the subnet prefix."; + } + leaf origin { + type ip-address-origin; + config false; + description + "The origin of this address."; + } + leaf status { + type enumeration { + enum preferred { + description + "This is a valid address that can appear as the + destination or source address of a packet."; + } + enum deprecated { + description + "This is a valid but deprecated address that should + no longer be used as a source address in new + communications, but packets addressed to such an + address are processed as expected."; + } + enum invalid { + description + "This isn't a valid address, and it shouldn't appear + as the destination or source address of a packet."; + } + + enum inaccessible { + description + "The address is not accessible because the interface + to which this address is assigned is not + operational."; + } + enum unknown { + description + "The status cannot be determined for some reason."; + } + enum tentative { + description + "The uniqueness of the address on the link is being + verified. Addresses in this state should not be + used for general communication and should only be + used to determine the uniqueness of the address."; + } + enum duplicate { + description + "The address has been determined to be non-unique on + the link and so must not be used."; + } + enum optimistic { + description + "The address is available for use, subject to + restrictions, while its uniqueness on a link is + being verified."; + } + } + config false; + description + "The status of an address. Most of the states correspond + to states from the IPv6 Stateless Address + Autoconfiguration protocol."; + reference + "RFC 4293: Management Information Base for the + Internet Protocol (IP) + - IpAddressStatusTC + RFC 4862: IPv6 Stateless Address Autoconfiguration"; + } + } + + list neighbor { + key "ip"; + description + "A list of mappings from IPv6 addresses to + link-layer addresses. + + Entries in this list in the intended configuration are + used as static entries in the Neighbor Cache. + + In the operational state, this list represents the + Neighbor Cache."; + reference + "RFC 4861: Neighbor Discovery for IP version 6 (IPv6)"; + + leaf ip { + type inet:ipv6-address-no-zone; + description + "The IPv6 address of the neighbor node."; + } + leaf link-layer-address { + type yang:phys-address; + mandatory true; + description + "The link-layer address of the neighbor node. + + In the operational state, if the neighbor's 'state' leaf + is 'incomplete', this leaf is not instantiated."; + } + leaf origin { + type neighbor-origin; + config false; + description + "The origin of this neighbor entry."; + } + leaf is-router { + type empty; + config false; + description + "Indicates that the neighbor node acts as a router."; + } + + leaf state { + type enumeration { + enum incomplete { + description + "Address resolution is in progress, and the + link-layer address of the neighbor has not yet been + determined."; + } + enum reachable { + description + "Roughly speaking, the neighbor is known to have been + reachable recently (within tens of seconds ago)."; + } + enum stale { + description + "The neighbor is no longer known to be reachable, but + until traffic is sent to the neighbor no attempt + should be made to verify its reachability."; + } + enum delay { + description + "The neighbor is no longer known to be reachable, and + traffic has recently been sent to the neighbor. + Rather than probe the neighbor immediately, however, + delay sending probes for a short while in order to + give upper-layer protocols a chance to provide + reachability confirmation."; + } + enum probe { + description + "The neighbor is no longer known to be reachable, and + unicast Neighbor Solicitation probes are being sent + to verify reachability."; + } + } + config false; + description + "The Neighbor Unreachability Detection state of this + entry."; + reference + "RFC 4861: Neighbor Discovery for IP version 6 (IPv6) + Section 7.3.2"; + } + } + + leaf dup-addr-detect-transmits { + type uint32; + default 1; + description + "The number of consecutive Neighbor Solicitation messages + sent while performing Duplicate Address Detection on a + tentative address. A value of zero indicates that + Duplicate Address Detection is not performed on + tentative addresses. A value of one indicates a single + transmission with no follow-up retransmissions."; + reference + "RFC 4862: IPv6 Stateless Address Autoconfiguration"; + } + container autoconf { + description + "Parameters to control the autoconfiguration of IPv6 + addresses, as described in RFC 4862."; + reference + "RFC 4862: IPv6 Stateless Address Autoconfiguration"; + + leaf create-global-addresses { + type boolean; + default true; + description + "If enabled, the host creates global addresses as + described in RFC 4862."; + reference + "RFC 4862: IPv6 Stateless Address Autoconfiguration + Section 5.5"; + } + leaf create-temporary-addresses { + if-feature ipv6-privacy-autoconf; + type boolean; + default false; + description + "If enabled, the host creates temporary addresses as + described in RFC 4941."; + reference + "RFC 4941: Privacy Extensions for Stateless Address + Autoconfiguration in IPv6"; + } + + leaf temporary-valid-lifetime { + if-feature ipv6-privacy-autoconf; + type uint32; + units "seconds"; + default 604800; + description + "The time period during which the temporary address + is valid."; + reference + "RFC 4941: Privacy Extensions for Stateless Address + Autoconfiguration in IPv6 + - TEMP_VALID_LIFETIME"; + } + leaf temporary-preferred-lifetime { + if-feature ipv6-privacy-autoconf; + type uint32; + units "seconds"; + default 86400; + description + "The time period during which the temporary address is + preferred."; + reference + "RFC 4941: Privacy Extensions for Stateless Address + Autoconfiguration in IPv6 + - TEMP_PREFERRED_LIFETIME"; + } + } + } + } + + /* + * Legacy operational state data nodes + */ + + augment "/if:interfaces-state/if:interface" { + status deprecated; + description + "Data nodes for the operational state of IP on interfaces."; + + container ipv4 { + presence + "Present if IPv4 is enabled on this interface"; + config false; + status deprecated; + description + "Interface-specific parameters for the IPv4 address family."; + + leaf forwarding { + type boolean; + status deprecated; + description + "Indicates whether IPv4 packet forwarding is enabled or + disabled on this interface."; + } + leaf mtu { + type uint16 { + range "68..max"; + } + units "octets"; + status deprecated; + description + "The size, in octets, of the largest IPv4 packet that the + interface will send and receive."; + reference + "RFC 791: Internet Protocol"; + } + list address { + key "ip"; + status deprecated; + description + "The list of IPv4 addresses on the interface."; + + leaf ip { + type inet:ipv4-address-no-zone; + status deprecated; + description + "The IPv4 address on the interface."; + } + choice subnet { + status deprecated; + description + "The subnet can be specified as a prefix length or, + if the server supports non-contiguous netmasks, as + a netmask."; + leaf prefix-length { + type uint8 { + range "0..32"; + } + status deprecated; + description + "The length of the subnet prefix."; + } + leaf netmask { + if-feature ipv4-non-contiguous-netmasks; + type yang:dotted-quad; + status deprecated; + description + "The subnet specified as a netmask."; + } + } + leaf origin { + type ip-address-origin; + status deprecated; + description + "The origin of this address."; + } + } + list neighbor { + key "ip"; + status deprecated; + description + "A list of mappings from IPv4 addresses to + link-layer addresses. + + This list represents the ARP Cache."; + reference + "RFC 826: An Ethernet Address Resolution Protocol"; + + leaf ip { + type inet:ipv4-address-no-zone; + status deprecated; + description + "The IPv4 address of the neighbor node."; + } + + leaf link-layer-address { + type yang:phys-address; + status deprecated; + description + "The link-layer address of the neighbor node."; + } + leaf origin { + type neighbor-origin; + status deprecated; + description + "The origin of this neighbor entry."; + } + } + } + + container ipv6 { + presence + "Present if IPv6 is enabled on this interface"; + config false; + status deprecated; + description + "Parameters for the IPv6 address family."; + + leaf forwarding { + type boolean; + default false; + status deprecated; + description + "Indicates whether IPv6 packet forwarding is enabled or + disabled on this interface."; + reference + "RFC 4861: Neighbor Discovery for IP version 6 (IPv6) + Section 6.2.1, IsRouter"; + } + leaf mtu { + type uint32 { + range "1280..max"; + } + units "octets"; + status deprecated; + description + "The size, in octets, of the largest IPv6 packet that the + interface will send and receive."; + reference + "RFC 8200: Internet Protocol, Version 6 (IPv6) + Specification + Section 5"; + } + list address { + key "ip"; + status deprecated; + description + "The list of IPv6 addresses on the interface."; + + leaf ip { + type inet:ipv6-address-no-zone; + status deprecated; + description + "The IPv6 address on the interface."; + } + leaf prefix-length { + type uint8 { + range "0..128"; + } + mandatory true; + status deprecated; + description + "The length of the subnet prefix."; + } + leaf origin { + type ip-address-origin; + status deprecated; + description + "The origin of this address."; + } + leaf status { + type enumeration { + enum preferred { + description + "This is a valid address that can appear as the + destination or source address of a packet."; + } + enum deprecated { + description + "This is a valid but deprecated address that should + no longer be used as a source address in new + communications, but packets addressed to such an + address are processed as expected."; + } + enum invalid { + description + "This isn't a valid address, and it shouldn't appear + as the destination or source address of a packet."; + } + + enum inaccessible { + description + "The address is not accessible because the interface + to which this address is assigned is not + operational."; + } + enum unknown { + description + "The status cannot be determined for some reason."; + } + enum tentative { + description + "The uniqueness of the address on the link is being + verified. Addresses in this state should not be + used for general communication and should only be + used to determine the uniqueness of the address."; + } + enum duplicate { + description + "The address has been determined to be non-unique on + the link and so must not be used."; + } + enum optimistic { + description + "The address is available for use, subject to + restrictions, while its uniqueness on a link is + being verified."; + } + } + status deprecated; + description + "The status of an address. Most of the states correspond + to states from the IPv6 Stateless Address + Autoconfiguration protocol."; + reference + "RFC 4293: Management Information Base for the + Internet Protocol (IP) + - IpAddressStatusTC + RFC 4862: IPv6 Stateless Address Autoconfiguration"; + } + } + + list neighbor { + key "ip"; + status deprecated; + description + "A list of mappings from IPv6 addresses to + link-layer addresses. + + This list represents the Neighbor Cache."; + reference + "RFC 4861: Neighbor Discovery for IP version 6 (IPv6)"; + + leaf ip { + type inet:ipv6-address-no-zone; + status deprecated; + description + "The IPv6 address of the neighbor node."; + } + leaf link-layer-address { + type yang:phys-address; + status deprecated; + description + "The link-layer address of the neighbor node."; + } + leaf origin { + type neighbor-origin; + status deprecated; + description + "The origin of this neighbor entry."; + } + leaf is-router { + type empty; + status deprecated; + description + "Indicates that the neighbor node acts as a router."; + } + leaf state { + type enumeration { + enum incomplete { + description + "Address resolution is in progress, and the + link-layer address of the neighbor has not yet been + determined."; + } + enum reachable { + description + "Roughly speaking, the neighbor is known to have been + reachable recently (within tens of seconds ago)."; + } + enum stale { + description + "The neighbor is no longer known to be reachable, but + until traffic is sent to the neighbor no attempt + should be made to verify its reachability."; + } + enum delay { + description + "The neighbor is no longer known to be reachable, and + traffic has recently been sent to the neighbor. + Rather than probe the neighbor immediately, however, + delay sending probes for a short while in order to + give upper-layer protocols a chance to provide + reachability confirmation."; + } + enum probe { + description + "The neighbor is no longer known to be reachable, and + unicast Neighbor Solicitation probes are being sent + to verify reachability."; + } + } + status deprecated; + description + "The Neighbor Unreachability Detection state of this + entry."; + reference + "RFC 4861: Neighbor Discovery for IP version 6 (IPv6) + Section 7.3.2"; + } + } + } + } +} diff --git a/src/confd/yang/ietf-netconf-acm.yang b/src/confd/yang/ietf-netconf-acm.yang deleted file mode 100644 index 8347cc05..00000000 --- a/src/confd/yang/ietf-netconf-acm.yang +++ /dev/null @@ -1,439 +0,0 @@ - module ietf-netconf-acm { - - yang-version 1; - - 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: - - WG Chair: Mehmet Ersue - - - WG Chair: Bert Wijnen - - - Editor: Andy Bierman - - - Editor: Martin Bjorklund - "; - - description - "NETCONF Access Control Model. - - Copyright (c) 2012 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 - (http://trustee.ietf.org/license-info). - - This version of this YANG module is part of RFC 6536; see - the RFC itself for full legal notices."; - - revision "2012-02-22" { - description - "Initial version; - Errata ID: 3862 and 3863"; - 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, and the NACM module is enabled (i.e., - /nacm/enable-nacm object equals 'true'), 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. - - 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, and the NACM module is enabled (i.e., - /nacm/enable-nacm object equals 'true'), 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. - - 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 { - position 0; - description - "Any protocol operation that creates a - new data node."; - } - bit read { - position 1; - description - "Any protocol operation or notification that - returns the value of a data node."; - } - bit update { - position 2; - description - "Any protocol operation that alters an existing - data node."; - } - bit delete { - position 3; - description - "Any protocol operation that removes a data node."; - } - bit exec { - position 4; - description - "Execution access to the specified protocol operation."; - } - } - description - "NETCONF 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" { - value 0; - description - "Requested action is permitted."; - } - enum "deny" { - value 1; - 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 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 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 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."; - } - - 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 group - } // container groups - - 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 if access is granted - or not."; - 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."; - 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."; - } - 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."; - } - leaf path { - type node-instance-identifier; - mandatory true; - description - "Data Node Instance Identifier associated with the - data node 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."; - } - } // choice rule-type - - 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 is 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."; - } - } // list rule - } // list rule-list - } // container nacm - } // module ietf-netconf-acm diff --git a/src/confd/yang/ietf-netconf-acm.yang b/src/confd/yang/ietf-netconf-acm.yang new file mode 120000 index 00000000..5c83622b --- /dev/null +++ b/src/confd/yang/ietf-netconf-acm.yang @@ -0,0 +1 @@ +ietf-netconf-acm@2018-02-14.yang \ No newline at end of file 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..bf4855fa --- /dev/null +++ b/src/confd/yang/ietf-netconf-acm@2018-02-14.yang @@ -0,0 +1,464 @@ +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 statements + */ + + 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."; + } + + /* + * Derived types + */ + + 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."; + } + + /* + * Data definition statements + */ + + 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-system.yang b/src/confd/yang/ietf-system.yang deleted file mode 100644 index a8d9e089..00000000 --- a/src/confd/yang/ietf-system.yang +++ /dev/null @@ -1,711 +0,0 @@ -module ietf-system { - namespace "urn:ietf:params:xml:ns:yang:ietf-system"; - prefix "sys"; - import ietf-yang-types { - prefix yang; - } - import ietf-inet-types { - prefix inet; - } - import ietf-netconf-acm { - prefix nacm; - } - import iana-crypt-hash { - prefix ianach; - } - organization - "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; - contact - "WG Web: - WG List: - WG Chair: Thomas Nadeau - - WG Chair: Juergen Schoenwaelder - - Editor: Andy Bierman - - Editor: Martin Bjorklund - "; - description - "This module contains a collection of YANG definitions for the - configuration and identification of some common system - properties within a device containing a NETCONF server. This - includes data node definitions for system identification, - time-of-day management, user management, DNS resolver - configuration, and some protocol operations for system - management. - Copyright (c) 2014 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 - (http://trustee.ietf.org/license-info). - This version of this YANG module is part of RFC 7317; see - the RFC itself for full legal notices."; - revision 2014-08-06 { - description - "Initial revision."; - reference - "RFC 7317: A YANG Data Model for System Management"; - } - /* - * Typedefs - */ - typedef timezone-name { - type string; - description - "A time zone name as used by the Time Zone Database, - sometimes referred to as the 'Olson Database'. - The exact set of valid values is an implementation-specific - matter. Client discovery of the exact set of time zone names - for a particular server is out of scope."; - reference - "RFC 6557: Procedures for Maintaining the Time Zone Database"; - } - /* - * Features - */ - feature radius { - description - "Indicates that the device can be configured as a RADIUS - client."; - reference - "RFC 2865: Remote Authentication Dial In User Service (RADIUS)"; - } - feature authentication { - description - "Indicates that the device supports configuration of - user authentication."; - } - feature local-users { - if-feature authentication; - description - "Indicates that the device supports configuration of - local user authentication."; - } - feature radius-authentication { - if-feature radius; - if-feature authentication; - description - "Indicates that the device supports configuration of user - authentication over RADIUS."; - reference - "RFC 2865: Remote Authentication Dial In User Service (RADIUS) - RFC 5607: Remote Authentication Dial-In User Service (RADIUS) - Authorization for Network Access Server (NAS) - Management"; - } - feature ntp { - description - "Indicates that the device can be configured to use one or - more NTP servers to set the system date and time."; - } - feature ntp-udp-port { - if-feature ntp; - description - "Indicates that the device supports the configuration of - the UDP port for NTP servers. - This is a 'feature', since many implementations do not support - any port other than the default port."; - } - feature timezone-name { - description - "Indicates that the local time zone on the device - can be configured to use the TZ database - to set the time zone and manage daylight saving time."; - reference - "RFC 6557: Procedures for Maintaining the Time Zone Database"; - } - feature dns-udp-tcp-port { - description - "Indicates that the device supports the configuration of - the UDP and TCP port for DNS servers. - This is a 'feature', since many implementations do not support - any port other than the default port."; - } - /* - * Identities - */ - identity authentication-method { - description - "Base identity for user authentication methods."; - } - identity radius { - base authentication-method; - description - "Indicates user authentication using RADIUS."; - reference - "RFC 2865: Remote Authentication Dial In User Service (RADIUS) - RFC 5607: Remote Authentication Dial-In User Service (RADIUS) - Authorization for Network Access Server (NAS) - Management"; - } - identity local-users { - base authentication-method; - description - "Indicates password-based authentication of locally - configured users."; - } - identity radius-authentication-type { - description - "Base identity for RADIUS authentication types."; - } - identity radius-pap { - base radius-authentication-type; - description - "The device requests Password Authentication Protocol (PAP) - authentication from the RADIUS server."; - reference - "RFC 2865: Remote Authentication Dial In User Service (RADIUS)"; - } - identity radius-chap { - base radius-authentication-type; - description - "The device requests Challenge Handshake Authentication - Protocol (CHAP) authentication from the RADIUS server."; - reference - "RFC 2865: Remote Authentication Dial In User Service (RADIUS)"; - } - /* - * Configuration data nodes - */ - container system { - description - "System group configuration."; - leaf contact { - type string; - description - "The administrator contact information for the system. - A server implementation MAY map this leaf to the sysContact - MIB object. Such an implementation needs to use some - mechanism to handle the differences in size and characters - allowed between this leaf and sysContact. The definition of - such a mechanism is outside the scope of this document."; - reference - "RFC 3418: Management Information Base (MIB) for the - Simple Network Management Protocol (SNMP) - SNMPv2-MIB.sysContact"; - } - leaf hostname { - type inet:domain-name; - description - "The name of the host. This name can be a single domain - label or the fully qualified domain name of the host."; - } - leaf location { - type string; - description - "The system location. - A server implementation MAY map this leaf to the sysLocation - MIB object. Such an implementation needs to use some - mechanism to handle the differences in size and characters - allowed between this leaf and sysLocation. The definition - of such a mechanism is outside the scope of this document."; - reference - "RFC 3418: Management Information Base (MIB) for the - Simple Network Management Protocol (SNMP) - SNMPv2-MIB.sysLocation"; - } - container clock { - description - "Configuration of the system date and time properties."; - choice timezone { - description - "The system time zone information."; - case timezone-name { - if-feature timezone-name; - leaf timezone-name { - type timezone-name; - description - "The TZ database name to use for the system, such - as 'Europe/Stockholm'."; - } - } - case timezone-utc-offset { - leaf timezone-utc-offset { - type int16 { - range "-1500 .. 1500"; - } - units "minutes"; - description - "The number of minutes to add to UTC time to - identify the time zone for this system. For example, - 'UTC - 8:00 hours' would be represented as '-480'. - Note that automatic daylight saving time adjustment - is not provided if this object is used."; - } - } - } - } - container ntp { - if-feature ntp; - presence - "Enables the NTP client unless the 'enabled' leaf - (which defaults to 'true') is set to 'false'"; - description - "Configuration of the NTP client."; - leaf enabled { - type boolean; - default true; - description - "Indicates that the system should attempt to - synchronize the system clock with an NTP server - from the 'ntp/server' list."; - } - list server { - key name; - description - "List of NTP servers to use for system clock - synchronization. If '/system/ntp/enabled' - is 'true', then the system will attempt to - contact and utilize the specified NTP servers."; - leaf name { - type string; - description - "An arbitrary name for the NTP server."; - } - choice transport { - mandatory true; - description - "The transport-protocol-specific parameters for this - server."; - case udp { - container udp { - description - "Contains UDP-specific configuration parameters - for NTP."; - leaf address { - type inet:host; - mandatory true; - description - "The address of the NTP server."; - } - leaf port { - if-feature ntp-udp-port; - type inet:port-number; - default 123; - description - "The port number of the NTP server."; - } - } - } - } - leaf association-type { - type enumeration { - enum server { - description - "Use client association mode. This device - will not provide synchronization to the - configured NTP server."; - } - enum peer { - description - "Use symmetric active association mode. - This device may provide synchronization - to the configured NTP server."; - } - enum pool { - description - "Use client association mode with one or - more of the NTP servers found by DNS - resolution of the domain name given by - the 'address' leaf. This device will not - provide synchronization to the servers."; - } - } - default server; - description - "The desired association type for this NTP server."; - } - leaf iburst { - type boolean; - default false; - description - "Indicates whether this server should enable burst - synchronization or not."; - } - leaf prefer { - type boolean; - default false; - description - "Indicates whether this server should be preferred - or not."; - } - } - } - container dns-resolver { - description - "Configuration of the DNS resolver."; - leaf-list search { - type inet:domain-name; - ordered-by user; - description - "An ordered list of domains to search when resolving - a host name."; - } - list server { - key name; - ordered-by user; - description - "List of the DNS servers that the resolver should query. - When the resolver is invoked by a calling application, it - sends the query to the first name server in this list. If - no response has been received within 'timeout' seconds, - the resolver continues with the next server in the list. - If no response is received from any server, the resolver - continues with the first server again. When the resolver - has traversed the list 'attempts' times without receiving - any response, it gives up and returns an error to the - calling application. - Implementations MAY limit the number of entries in this - list."; - leaf name { - type string; - description - "An arbitrary name for the DNS server."; - } - choice transport { - mandatory true; - description - "The transport-protocol-specific parameters for this - server."; - case udp-and-tcp { - container udp-and-tcp { - description - "Contains UDP- and TCP-specific configuration - parameters for DNS."; - reference - "RFC 1035: Domain Names - Implementation and - Specification - RFC 5966: DNS Transport over TCP - Implementation - Requirements"; - leaf address { - type inet:ip-address; - mandatory true; - description - "The address of the DNS server."; - } - leaf port { - if-feature dns-udp-tcp-port; - type inet:port-number; - default 53; - description - "The UDP and TCP port number of the DNS server."; - } - } - } - } - } - container options { - description - "Resolver options. The set of available options has been - limited to those that are generally available across - different resolver implementations and generally useful."; - leaf timeout { - type uint8 { - range "1..max"; - } - units "seconds"; - default "5"; - description - "The amount of time the resolver will wait for a - response from each remote name server before - retrying the query via a different name server."; - } - leaf attempts { - type uint8 { - range "1..max"; - } - default "2"; - description - "The number of times the resolver will send a query to - all of its name servers before giving up and returning - an error to the calling application."; - } - } - } - container radius { - if-feature radius; - description - "Configuration of the RADIUS client."; - list server { - key name; - ordered-by user; - description - "List of RADIUS servers used by the device. - When the RADIUS client is invoked by a calling - application, it sends the query to the first server in - this list. If no response has been received within - 'timeout' seconds, the client continues with the next - server in the list. If no response is received from any - server, the client continues with the first server again. - When the client has traversed the list 'attempts' times - without receiving any response, it gives up and returns an - error to the calling application."; - leaf name { - type string; - description - "An arbitrary name for the RADIUS server."; - } - choice transport { - mandatory true; - description - "The transport-protocol-specific parameters for this - server."; - case udp { - container udp { - description - "Contains UDP-specific configuration parameters - for RADIUS."; - leaf address { - type inet:host; - mandatory true; - description - "The address of the RADIUS server."; - } - leaf authentication-port { - type inet:port-number; - default "1812"; - description - "The port number of the RADIUS server."; - } - leaf shared-secret { - type string; - mandatory true; - nacm:default-deny-all; - description - "The shared secret, which is known to both the - RADIUS client and server."; - reference - "RFC 2865: Remote Authentication Dial In User - Service (RADIUS)"; - } - } - } - } - leaf authentication-type { - type identityref { - base radius-authentication-type; - } - default radius-pap; - description - "The authentication type requested from the RADIUS - server."; - } - } - container options { - description - "RADIUS client options."; - leaf timeout { - type uint8 { - range "1..max"; - } - units "seconds"; - default "5"; - description - "The number of seconds the device will wait for a - response from each RADIUS server before trying with a - different server."; - } - leaf attempts { - type uint8 { - range "1..max"; - } - default "2"; - description - "The number of times the device will send a query to - all of its RADIUS servers before giving up."; - } - } - } - container authentication { - nacm:default-deny-write; - if-feature authentication; - description - "The authentication configuration subtree."; - leaf-list user-authentication-order { - type identityref { - base authentication-method; - } - must '(. != "sys:radius" or ../../radius/server)' { - error-message - "When 'radius' is used, a RADIUS server" - + " must be configured."; - description - "When 'radius' is used as an authentication method, - a RADIUS server must be configured."; - } - ordered-by user; - description - "When the device authenticates a user with a password, - it tries the authentication methods in this leaf-list in - order. If authentication with one method fails, the next - method is used. If no method succeeds, the user is - denied access. - An empty user-authentication-order leaf-list still allows - authentication of users using mechanisms that do not - involve a password. - If the 'radius-authentication' feature is advertised by - the NETCONF server, the 'radius' identity can be added to - this list. - If the 'local-users' feature is advertised by the - NETCONF server, the 'local-users' identity can be - added to this list."; - } - list user { - if-feature local-users; - key name; - description - "The list of local users configured on this device."; - leaf name { - type string; - description - "The user name string identifying this entry."; - } - leaf password { - type ianach:crypt-hash; - description - "The password for this entry."; - } - list authorized-key { - key name; - description - "A list of public SSH keys for this user. These keys - are allowed for SSH authentication, as described in - RFC 4253."; - reference - "RFC 4253: The Secure Shell (SSH) Transport Layer - Protocol"; - leaf name { - type string; - description - "An arbitrary name for the SSH key."; - } - leaf algorithm { - type string; - mandatory true; - description - "The public key algorithm name for this SSH key. - Valid values are the values in the IANA 'Secure Shell - (SSH) Protocol Parameters' registry, Public Key - Algorithm Names."; - reference - "IANA 'Secure Shell (SSH) Protocol Parameters' - registry, Public Key Algorithm Names"; - } - leaf key-data { - type binary; - mandatory true; - description - "The binary public key data for this SSH 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"; - } - } - } - } - } - /* - * Operational state data nodes - */ - container system-state { - config false; - description - "System group operational state."; - container platform { - description - "Contains vendor-specific information for - identifying the system platform and operating system."; - reference - "IEEE Std 1003.1-2008 - sys/utsname.h"; - leaf os-name { - type string; - description - "The name of the operating system in use - - for example, 'Linux'."; - reference - "IEEE Std 1003.1-2008 - utsname.sysname"; - } - leaf os-release { - type string; - description - "The current release level of the operating - system in use. This string MAY indicate - the OS source code revision."; - reference - "IEEE Std 1003.1-2008 - utsname.release"; - } - leaf os-version { - type string; - description - "The current version level of the operating - system in use. This string MAY indicate - the specific OS build date and target variant - information."; - reference - "IEEE Std 1003.1-2008 - utsname.version"; - } - leaf machine { - type string; - description - "A vendor-specific identifier string representing - the hardware in use."; - reference - "IEEE Std 1003.1-2008 - utsname.machine"; - } - } - container clock { - description - "Monitoring of the system date and time properties."; - leaf current-datetime { - type yang:date-and-time; - description - "The current system date and time."; - } - leaf boot-datetime { - type yang:date-and-time; - description - "The system date and time when the system last restarted."; - } - } - } - rpc set-current-datetime { - nacm:default-deny-all; - description - "Set the /system-state/clock/current-datetime leaf - to the specified value. - If the system is using NTP (i.e., /system/ntp/enabled - is set to 'true'), then this operation will fail with - error-tag 'operation-failed' and error-app-tag value of - 'ntp-active'."; - input { - leaf current-datetime { - type yang:date-and-time; - mandatory true; - description - "The current system date and time."; - } - } - } - rpc system-restart { - nacm:default-deny-all; - description - "Request that the entire system be restarted immediately. - A server SHOULD send an rpc reply to the client before - restarting the system."; - } - rpc system-shutdown { - nacm:default-deny-all; - description - "Request that the entire system be shut down immediately. - A server SHOULD send an rpc reply to the client before - shutting down the system."; - } -} diff --git a/src/confd/yang/ietf-system.yang b/src/confd/yang/ietf-system.yang new file mode 120000 index 00000000..c3b6168c --- /dev/null +++ b/src/confd/yang/ietf-system.yang @@ -0,0 +1 @@ +ietf-system@2014-08-06.yang \ No newline at end of file diff --git a/src/confd/yang/ietf-system@2014-08-06.yang b/src/confd/yang/ietf-system@2014-08-06.yang new file mode 100644 index 00000000..1618242b --- /dev/null +++ b/src/confd/yang/ietf-system@2014-08-06.yang @@ -0,0 +1,800 @@ +module ietf-system { + namespace "urn:ietf:params:xml:ns:yang:ietf-system"; + prefix "sys"; + + import ietf-yang-types { + prefix yang; + } + + import ietf-inet-types { + prefix inet; + } + + import ietf-netconf-acm { + prefix nacm; + } + + import iana-crypt-hash { + prefix ianach; + } + + organization + "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; + + contact + "WG Web: + WG List: + + WG Chair: Thomas Nadeau + + + WG Chair: Juergen Schoenwaelder + + + Editor: Andy Bierman + + + Editor: Martin Bjorklund + "; + + description + "This module contains a collection of YANG definitions for the + configuration and identification of some common system + properties within a device containing a NETCONF server. This + includes data node definitions for system identification, + time-of-day management, user management, DNS resolver + configuration, and some protocol operations for system + management. + + Copyright (c) 2014 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 + (http://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 7317; see + the RFC itself for full legal notices."; + + revision 2014-08-06 { + description + "Initial revision."; + reference + "RFC 7317: A YANG Data Model for System Management"; + } + + /* + * Typedefs + */ + + typedef timezone-name { + type string; + description + "A time zone name as used by the Time Zone Database, + sometimes referred to as the 'Olson Database'. + + The exact set of valid values is an implementation-specific + matter. Client discovery of the exact set of time zone names + for a particular server is out of scope."; + reference + "RFC 6557: Procedures for Maintaining the Time Zone Database"; + } + + /* + * Features + */ + + feature radius { + description + "Indicates that the device can be configured as a RADIUS + client."; + reference + "RFC 2865: Remote Authentication Dial In User Service (RADIUS)"; + } + + feature authentication { + description + "Indicates that the device supports configuration of + user authentication."; + } + + feature local-users { + if-feature authentication; + description + "Indicates that the device supports configuration of + local user authentication."; + } + + feature radius-authentication { + if-feature radius; + if-feature authentication; + description + "Indicates that the device supports configuration of user + authentication over RADIUS."; + reference + "RFC 2865: Remote Authentication Dial In User Service (RADIUS) + RFC 5607: Remote Authentication Dial-In User Service (RADIUS) + Authorization for Network Access Server (NAS) + Management"; + } + + feature ntp { + description + "Indicates that the device can be configured to use one or + more NTP servers to set the system date and time."; + } + + feature ntp-udp-port { + if-feature ntp; + description + "Indicates that the device supports the configuration of + the UDP port for NTP servers. + + This is a 'feature', since many implementations do not support + any port other than the default port."; + } + + feature timezone-name { + description + "Indicates that the local time zone on the device + can be configured to use the TZ database + to set the time zone and manage daylight saving time."; + reference + "RFC 6557: Procedures for Maintaining the Time Zone Database"; + } + + feature dns-udp-tcp-port { + description + "Indicates that the device supports the configuration of + the UDP and TCP port for DNS servers. + + This is a 'feature', since many implementations do not support + any port other than the default port."; + } + + /* + * Identities + */ + + identity authentication-method { + description + "Base identity for user authentication methods."; + } + + identity radius { + base authentication-method; + description + "Indicates user authentication using RADIUS."; + reference + "RFC 2865: Remote Authentication Dial In User Service (RADIUS) + RFC 5607: Remote Authentication Dial-In User Service (RADIUS) + Authorization for Network Access Server (NAS) + Management"; + } + + identity local-users { + base authentication-method; + description + "Indicates password-based authentication of locally + configured users."; + } + + identity radius-authentication-type { + description + "Base identity for RADIUS authentication types."; + } + + identity radius-pap { + base radius-authentication-type; + description + "The device requests Password Authentication Protocol (PAP) + authentication from the RADIUS server."; + reference + "RFC 2865: Remote Authentication Dial In User Service (RADIUS)"; + } + + identity radius-chap { + base radius-authentication-type; + description + "The device requests Challenge Handshake Authentication + Protocol (CHAP) authentication from the RADIUS server."; + reference + "RFC 2865: Remote Authentication Dial In User Service (RADIUS)"; + } + + /* + * Configuration data nodes + */ + + container system { + description + "System group configuration."; + + leaf contact { + type string; + description + "The administrator contact information for the system. + + A server implementation MAY map this leaf to the sysContact + MIB object. Such an implementation needs to use some + mechanism to handle the differences in size and characters + allowed between this leaf and sysContact. The definition of + such a mechanism is outside the scope of this document."; + reference + "RFC 3418: Management Information Base (MIB) for the + Simple Network Management Protocol (SNMP) + SNMPv2-MIB.sysContact"; + } + leaf hostname { + type inet:domain-name; + description + "The name of the host. This name can be a single domain + label or the fully qualified domain name of the host."; + } + leaf location { + type string; + description + "The system location. + + A server implementation MAY map this leaf to the sysLocation + MIB object. Such an implementation needs to use some + mechanism to handle the differences in size and characters + allowed between this leaf and sysLocation. The definition + of such a mechanism is outside the scope of this document."; + reference + "RFC 3418: Management Information Base (MIB) for the + Simple Network Management Protocol (SNMP) + SNMPv2-MIB.sysLocation"; + } + + container clock { + description + "Configuration of the system date and time properties."; + + choice timezone { + description + "The system time zone information."; + + case timezone-name { + if-feature timezone-name; + leaf timezone-name { + type timezone-name; + description + "The TZ database name to use for the system, such + as 'Europe/Stockholm'."; + } + } + case timezone-utc-offset { + leaf timezone-utc-offset { + type int16 { + range "-1500 .. 1500"; + } + units "minutes"; + description + "The number of minutes to add to UTC time to + identify the time zone for this system. For example, + 'UTC - 8:00 hours' would be represented as '-480'. + Note that automatic daylight saving time adjustment + is not provided if this object is used."; + } + } + } + } + + container ntp { + if-feature ntp; + presence + "Enables the NTP client unless the 'enabled' leaf + (which defaults to 'true') is set to 'false'"; + description + "Configuration of the NTP client."; + + leaf enabled { + type boolean; + default true; + description + "Indicates that the system should attempt to + synchronize the system clock with an NTP server + from the 'ntp/server' list."; + } + list server { + key name; + description + "List of NTP servers to use for system clock + synchronization. If '/system/ntp/enabled' + is 'true', then the system will attempt to + contact and utilize the specified NTP servers."; + + leaf name { + type string; + description + "An arbitrary name for the NTP server."; + } + choice transport { + mandatory true; + description + "The transport-protocol-specific parameters for this + server."; + + case udp { + container udp { + description + "Contains UDP-specific configuration parameters + for NTP."; + leaf address { + type inet:host; + mandatory true; + description + "The address of the NTP server."; + } + leaf port { + if-feature ntp-udp-port; + type inet:port-number; + default 123; + description + "The port number of the NTP server."; + } + } + } + } + leaf association-type { + type enumeration { + enum server { + description + "Use client association mode. This device + will not provide synchronization to the + configured NTP server."; + } + enum peer { + description + "Use symmetric active association mode. + This device may provide synchronization + to the configured NTP server."; + } + enum pool { + description + "Use client association mode with one or + more of the NTP servers found by DNS + resolution of the domain name given by + the 'address' leaf. This device will not + provide synchronization to the servers."; + } + } + default server; + description + "The desired association type for this NTP server."; + } + leaf iburst { + type boolean; + default false; + description + "Indicates whether this server should enable burst + synchronization or not."; + } + leaf prefer { + type boolean; + default false; + description + "Indicates whether this server should be preferred + or not."; + } + } + } + + container dns-resolver { + description + "Configuration of the DNS resolver."; + + leaf-list search { + type inet:domain-name; + ordered-by user; + description + "An ordered list of domains to search when resolving + a host name."; + } + list server { + key name; + ordered-by user; + description + "List of the DNS servers that the resolver should query. + + When the resolver is invoked by a calling application, it + sends the query to the first name server in this list. If + no response has been received within 'timeout' seconds, + the resolver continues with the next server in the list. + If no response is received from any server, the resolver + continues with the first server again. When the resolver + has traversed the list 'attempts' times without receiving + any response, it gives up and returns an error to the + calling application. + + Implementations MAY limit the number of entries in this + list."; + + leaf name { + type string; + description + "An arbitrary name for the DNS server."; + } + choice transport { + mandatory true; + description + "The transport-protocol-specific parameters for this + server."; + + case udp-and-tcp { + container udp-and-tcp { + description + "Contains UDP- and TCP-specific configuration + parameters for DNS."; + reference + "RFC 1035: Domain Names - Implementation and + Specification + RFC 5966: DNS Transport over TCP - Implementation + Requirements"; + + leaf address { + type inet:ip-address; + mandatory true; + description + "The address of the DNS server."; + } + leaf port { + if-feature dns-udp-tcp-port; + type inet:port-number; + default 53; + description + "The UDP and TCP port number of the DNS server."; + } + } + } + } + } + container options { + description + "Resolver options. The set of available options has been + limited to those that are generally available across + different resolver implementations and generally useful."; + leaf timeout { + type uint8 { + range "1..max"; + } + units "seconds"; + default "5"; + description + "The amount of time the resolver will wait for a + response from each remote name server before + retrying the query via a different name server."; + } + leaf attempts { + type uint8 { + range "1..max"; + } + default "2"; + description + "The number of times the resolver will send a query to + all of its name servers before giving up and returning + an error to the calling application."; + } + } + } + + container radius { + if-feature radius; + + description + "Configuration of the RADIUS client."; + + list server { + key name; + ordered-by user; + description + "List of RADIUS servers used by the device. + + When the RADIUS client is invoked by a calling + application, it sends the query to the first server in + this list. If no response has been received within + 'timeout' seconds, the client continues with the next + server in the list. If no response is received from any + server, the client continues with the first server again. + When the client has traversed the list 'attempts' times + without receiving any response, it gives up and returns an + error to the calling application."; + + leaf name { + type string; + description + "An arbitrary name for the RADIUS server."; + } + choice transport { + mandatory true; + description + "The transport-protocol-specific parameters for this + server."; + + case udp { + container udp { + description + "Contains UDP-specific configuration parameters + for RADIUS."; + leaf address { + type inet:host; + mandatory true; + description + "The address of the RADIUS server."; + } + + leaf authentication-port { + type inet:port-number; + default "1812"; + description + "The port number of the RADIUS server."; + } + leaf shared-secret { + type string; + mandatory true; + nacm:default-deny-all; + description + "The shared secret, which is known to both the + RADIUS client and server."; + reference + "RFC 2865: Remote Authentication Dial In User + Service (RADIUS)"; + } + } + } + } + leaf authentication-type { + type identityref { + base radius-authentication-type; + } + default radius-pap; + description + "The authentication type requested from the RADIUS + server."; + } + } + container options { + description + "RADIUS client options."; + + leaf timeout { + type uint8 { + range "1..max"; + } + units "seconds"; + default "5"; + description + "The number of seconds the device will wait for a + response from each RADIUS server before trying with a + different server."; + } + + leaf attempts { + type uint8 { + range "1..max"; + } + default "2"; + description + "The number of times the device will send a query to + all of its RADIUS servers before giving up."; + } + } + } + + container authentication { + nacm:default-deny-write; + if-feature authentication; + + description + "The authentication configuration subtree."; + + leaf-list user-authentication-order { + type identityref { + base authentication-method; + } + must '(. != "sys:radius" or ../../radius/server)' { + error-message + "When 'radius' is used, a RADIUS server" + + " must be configured."; + description + "When 'radius' is used as an authentication method, + a RADIUS server must be configured."; + } + ordered-by user; + + description + "When the device authenticates a user with a password, + it tries the authentication methods in this leaf-list in + order. If authentication with one method fails, the next + method is used. If no method succeeds, the user is + denied access. + + An empty user-authentication-order leaf-list still allows + authentication of users using mechanisms that do not + involve a password. + + If the 'radius-authentication' feature is advertised by + the NETCONF server, the 'radius' identity can be added to + this list. + + If the 'local-users' feature is advertised by the + NETCONF server, the 'local-users' identity can be + added to this list."; + } + + list user { + if-feature local-users; + key name; + description + "The list of local users configured on this device."; + + leaf name { + type string; + description + "The user name string identifying this entry."; + } + leaf password { + type ianach:crypt-hash; + description + "The password for this entry."; + } + list authorized-key { + key name; + description + "A list of public SSH keys for this user. These keys + are allowed for SSH authentication, as described in + RFC 4253."; + reference + "RFC 4253: The Secure Shell (SSH) Transport Layer + Protocol"; + + leaf name { + type string; + description + "An arbitrary name for the SSH key."; + } + + leaf algorithm { + type string; + mandatory true; + description + "The public key algorithm name for this SSH key. + + Valid values are the values in the IANA 'Secure Shell + (SSH) Protocol Parameters' registry, Public Key + Algorithm Names."; + reference + "IANA 'Secure Shell (SSH) Protocol Parameters' + registry, Public Key Algorithm Names"; + } + leaf key-data { + type binary; + mandatory true; + description + "The binary public key data for this SSH 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"; + } + } + } + } + } + + /* + * Operational state data nodes + */ + + container system-state { + config false; + description + "System group operational state."; + + container platform { + description + "Contains vendor-specific information for + identifying the system platform and operating system."; + reference + "IEEE Std 1003.1-2008 - sys/utsname.h"; + + leaf os-name { + type string; + description + "The name of the operating system in use - + for example, 'Linux'."; + reference + "IEEE Std 1003.1-2008 - utsname.sysname"; + } + leaf os-release { + type string; + description + "The current release level of the operating + system in use. This string MAY indicate + the OS source code revision."; + reference + "IEEE Std 1003.1-2008 - utsname.release"; + } + leaf os-version { + type string; + description + "The current version level of the operating + system in use. This string MAY indicate + the specific OS build date and target variant + information."; + reference + "IEEE Std 1003.1-2008 - utsname.version"; + } + leaf machine { + type string; + description + "A vendor-specific identifier string representing + the hardware in use."; + reference + "IEEE Std 1003.1-2008 - utsname.machine"; + } + } + + container clock { + description + "Monitoring of the system date and time properties."; + + leaf current-datetime { + type yang:date-and-time; + description + "The current system date and time."; + } + + leaf boot-datetime { + type yang:date-and-time; + description + "The system date and time when the system last restarted."; + } + } + } + + rpc set-current-datetime { + nacm:default-deny-all; + description + "Set the /system-state/clock/current-datetime leaf + to the specified value. + + If the system is using NTP (i.e., /system/ntp/enabled + is set to 'true'), then this operation will fail with + error-tag 'operation-failed' and error-app-tag value of + 'ntp-active'."; + input { + leaf current-datetime { + type yang:date-and-time; + mandatory true; + description + "The current system date and time."; + } + } + } + + rpc system-restart { + nacm:default-deny-all; + description + "Request that the entire system be restarted immediately. + A server SHOULD send an rpc reply to the client before + restarting the system."; + } + + rpc system-shutdown { + nacm:default-deny-all; + description + "Request that the entire system be shut down immediately. + A server SHOULD send an rpc reply to the client before + shutting down the system."; + } + +} diff --git a/src/confd/yang/ietf-yang-types.yang b/src/confd/yang/ietf-yang-types.yang new file mode 120000 index 00000000..a9d02a25 --- /dev/null +++ b/src/confd/yang/ietf-yang-types.yang @@ -0,0 +1 @@ +ietf-yang-types@2013-07-15.yang \ No newline at end of file diff --git a/src/confd/yang/ietf-yang-types@2013-07-15.yang b/src/confd/yang/ietf-yang-types@2013-07-15.yang new file mode 100644 index 00000000..ee58fa3a --- /dev/null +++ b/src/confd/yang/ietf-yang-types@2013-07-15.yang @@ -0,0 +1,474 @@ +module ietf-yang-types { + + namespace "urn:ietf:params:xml:ns:yang:ietf-yang-types"; + prefix "yang"; + + organization + "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; + + contact + "WG Web: + WG List: + + WG Chair: David Kessens + + + WG Chair: Juergen Schoenwaelder + + + Editor: Juergen Schoenwaelder + "; + + description + "This module contains a collection of generally useful derived + YANG data types. + + Copyright (c) 2013 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 + (http://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 6991; see + the RFC itself for full legal notices."; + + revision 2013-07-15 { + description + "This revision adds the following new data types: + - yang-identifier + - hex-string + - uuid + - dotted-quad"; + reference + "RFC 6991: Common YANG Data Types"; + } + + revision 2010-09-24 { + description + "Initial revision."; + reference + "RFC 6021: Common YANG Data Types"; + } + + /*** collection of counter and gauge types ***/ + + typedef counter32 { + type uint32; + description + "The counter32 type represents a non-negative integer + that monotonically increases until it reaches a + maximum value of 2^32-1 (4294967295 decimal), when it + wraps around and starts increasing again from zero. + + Counters have no defined 'initial' value, and thus, a + single value of a counter has (in general) no information + content. Discontinuities in the monotonically increasing + value normally occur at re-initialization of the + management system, and at other times as specified in the + description of a schema node using this type. If such + other times can occur, for example, the creation of + a schema node of type counter32 at times other than + re-initialization, then a corresponding schema node + should be defined, with an appropriate type, to indicate + the last discontinuity. + + The counter32 type should not be used for configuration + schema nodes. A default statement SHOULD NOT be used in + combination with the type counter32. + + In the value set and its semantics, this type is equivalent + to the Counter32 type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; + } + + typedef zero-based-counter32 { + type yang:counter32; + default "0"; + description + "The zero-based-counter32 type represents a counter32 + that has the defined 'initial' value zero. + + A schema node of this type will be set to zero (0) on creation + and will thereafter increase monotonically until it reaches + a maximum value of 2^32-1 (4294967295 decimal), when it + wraps around and starts increasing again from zero. + + Provided that an application discovers a new schema node + of this type within the minimum time to wrap, it can use the + 'initial' value as a delta. It is important for a management + station to be aware of this minimum time and the actual time + between polls, and to discard data if the actual time is too + long or there is no defined minimum time. + + In the value set and its semantics, this type is equivalent + to the ZeroBasedCounter32 textual convention of the SMIv2."; + reference + "RFC 4502: Remote Network Monitoring Management Information + Base Version 2"; + } + + typedef counter64 { + type uint64; + description + "The counter64 type represents a non-negative integer + that monotonically increases until it reaches a + maximum value of 2^64-1 (18446744073709551615 decimal), + when it wraps around and starts increasing again from zero. + + Counters have no defined 'initial' value, and thus, a + single value of a counter has (in general) no information + content. Discontinuities in the monotonically increasing + value normally occur at re-initialization of the + management system, and at other times as specified in the + description of a schema node using this type. If such + other times can occur, for example, the creation of + a schema node of type counter64 at times other than + re-initialization, then a corresponding schema node + should be defined, with an appropriate type, to indicate + the last discontinuity. + + The counter64 type should not be used for configuration + schema nodes. A default statement SHOULD NOT be used in + combination with the type counter64. + + In the value set and its semantics, this type is equivalent + to the Counter64 type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; + } + + typedef zero-based-counter64 { + type yang:counter64; + default "0"; + description + "The zero-based-counter64 type represents a counter64 that + has the defined 'initial' value zero. + + A schema node of this type will be set to zero (0) on creation + and will thereafter increase monotonically until it reaches + a maximum value of 2^64-1 (18446744073709551615 decimal), + when it wraps around and starts increasing again from zero. + + Provided that an application discovers a new schema node + of this type within the minimum time to wrap, it can use the + 'initial' value as a delta. It is important for a management + station to be aware of this minimum time and the actual time + between polls, and to discard data if the actual time is too + long or there is no defined minimum time. + + In the value set and its semantics, this type is equivalent + to the ZeroBasedCounter64 textual convention of the SMIv2."; + reference + "RFC 2856: Textual Conventions for Additional High Capacity + Data Types"; + } + + typedef gauge32 { + type uint32; + description + "The gauge32 type represents a non-negative integer, which + may increase or decrease, but shall never exceed a maximum + value, nor fall below a minimum value. The maximum value + cannot be greater than 2^32-1 (4294967295 decimal), and + the minimum value cannot be smaller than 0. The value of + a gauge32 has its maximum value whenever the information + being modeled is greater than or equal to its maximum + value, and has its minimum value whenever the information + being modeled is smaller than or equal to its minimum value. + If the information being modeled subsequently decreases + below (increases above) the maximum (minimum) value, the + gauge32 also decreases (increases). + + In the value set and its semantics, this type is equivalent + to the Gauge32 type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; + } + + typedef gauge64 { + type uint64; + description + "The gauge64 type represents a non-negative integer, which + may increase or decrease, but shall never exceed a maximum + value, nor fall below a minimum value. The maximum value + cannot be greater than 2^64-1 (18446744073709551615), and + the minimum value cannot be smaller than 0. The value of + a gauge64 has its maximum value whenever the information + being modeled is greater than or equal to its maximum + value, and has its minimum value whenever the information + being modeled is smaller than or equal to its minimum value. + If the information being modeled subsequently decreases + below (increases above) the maximum (minimum) value, the + gauge64 also decreases (increases). + + In the value set and its semantics, this type is equivalent + to the CounterBasedGauge64 SMIv2 textual convention defined + in RFC 2856"; + reference + "RFC 2856: Textual Conventions for Additional High Capacity + Data Types"; + } + + /*** collection of identifier-related types ***/ + + typedef object-identifier { + type string { + pattern '(([0-1](\.[1-3]?[0-9]))|(2\.(0|([1-9]\d*))))' + + '(\.(0|([1-9]\d*)))*'; + } + description + "The object-identifier type represents administratively + assigned names in a registration-hierarchical-name tree. + + Values of this type are denoted as a sequence of numerical + non-negative sub-identifier values. Each sub-identifier + value MUST NOT exceed 2^32-1 (4294967295). Sub-identifiers + are separated by single dots and without any intermediate + whitespace. + + The ASN.1 standard restricts the value space of the first + sub-identifier to 0, 1, or 2. Furthermore, the value space + of the second sub-identifier is restricted to the range + 0 to 39 if the first sub-identifier is 0 or 1. Finally, + the ASN.1 standard requires that an object identifier + has always at least two sub-identifiers. The pattern + captures these restrictions. + + Although the number of sub-identifiers is not limited, + module designers should realize that there may be + implementations that stick with the SMIv2 limit of 128 + sub-identifiers. + + This type is a superset of the SMIv2 OBJECT IDENTIFIER type + since it is not restricted to 128 sub-identifiers. Hence, + this type SHOULD NOT be used to represent the SMIv2 OBJECT + IDENTIFIER type; the object-identifier-128 type SHOULD be + used instead."; + reference + "ISO9834-1: Information technology -- Open Systems + Interconnection -- Procedures for the operation of OSI + Registration Authorities: General procedures and top + arcs of the ASN.1 Object Identifier tree"; + } + + typedef object-identifier-128 { + type object-identifier { + pattern '\d*(\.\d*){1,127}'; + } + description + "This type represents object-identifiers restricted to 128 + sub-identifiers. + + In the value set and its semantics, this type is equivalent + to the OBJECT IDENTIFIER type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; + } + + typedef yang-identifier { + type string { + length "1..max"; + pattern '[a-zA-Z_][a-zA-Z0-9\-_.]*'; + pattern '.|..|[^xX].*|.[^mM].*|..[^lL].*'; + } + description + "A YANG identifier string as defined by the 'identifier' + rule in Section 12 of RFC 6020. An identifier must + start with an alphabetic character or an underscore + followed by an arbitrary sequence of alphabetic or + numeric characters, underscores, hyphens, or dots. + + A YANG identifier MUST NOT start with any possible + combination of the lowercase or uppercase character + sequence 'xml'."; + reference + "RFC 6020: YANG - A Data Modeling Language for the Network + Configuration Protocol (NETCONF)"; + } + + /*** collection of types related to date and time***/ + + typedef date-and-time { + type string { + pattern '\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?' + + '(Z|[\+\-]\d{2}:\d{2})'; + } + description + "The date-and-time type is a profile of the ISO 8601 + standard for representation of dates and times using the + Gregorian calendar. The profile is defined by the + date-time production in Section 5.6 of RFC 3339. + + The date-and-time type is compatible with the dateTime XML + schema type with the following notable exceptions: + + (a) The date-and-time type does not allow negative years. + + (b) The date-and-time time-offset -00:00 indicates an unknown + time zone (see RFC 3339) while -00:00 and +00:00 and Z + all represent the same time zone in dateTime. + + (c) The canonical format (see below) of data-and-time values + differs from the canonical format used by the dateTime XML + schema type, which requires all times to be in UTC using + the time-offset 'Z'. + + This type is not equivalent to the DateAndTime textual + convention of the SMIv2 since RFC 3339 uses a different + separator between full-date and full-time and provides + higher resolution of time-secfrac. + + The canonical format for date-and-time values with a known time + zone uses a numeric time zone offset that is calculated using + the device's configured known offset to UTC time. A change of + the device's offset to UTC time will cause date-and-time values + to change accordingly. Such changes might happen periodically + in case a server follows automatically daylight saving time + (DST) time zone offset changes. The canonical format for + date-and-time values with an unknown time zone (usually + referring to the notion of local time) uses the time-offset + -00:00."; + reference + "RFC 3339: Date and Time on the Internet: Timestamps + RFC 2579: Textual Conventions for SMIv2 + XSD-TYPES: XML Schema Part 2: Datatypes Second Edition"; + } + + typedef timeticks { + type uint32; + description + "The timeticks type represents a non-negative integer that + represents the time, modulo 2^32 (4294967296 decimal), in + hundredths of a second between two epochs. When a schema + node is defined that uses this type, the description of + the schema node identifies both of the reference epochs. + + In the value set and its semantics, this type is equivalent + to the TimeTicks type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; + } + + typedef timestamp { + type yang:timeticks; + description + "The timestamp type represents the value of an associated + timeticks schema node at which a specific occurrence + happened. The specific occurrence must be defined in the + description of any schema node defined using this type. When + the specific occurrence occurred prior to the last time the + associated timeticks attribute was zero, then the timestamp + value is zero. Note that this requires all timestamp values + to be reset to zero when the value of the associated timeticks + attribute reaches 497+ days and wraps around to zero. + + The associated timeticks schema node must be specified + in the description of any schema node using this type. + + In the value set and its semantics, this type is equivalent + to the TimeStamp textual convention of the SMIv2."; + reference + "RFC 2579: Textual Conventions for SMIv2"; + } + + /*** collection of generic address types ***/ + + typedef phys-address { + type string { + pattern '([0-9a-fA-F]{2}(:[0-9a-fA-F]{2})*)?'; + } + + description + "Represents media- or physical-level addresses represented + as a sequence octets, each octet represented by two hexadecimal + numbers. Octets are separated by colons. The canonical + representation uses lowercase characters. + + In the value set and its semantics, this type is equivalent + to the PhysAddress textual convention of the SMIv2."; + reference + "RFC 2579: Textual Conventions for SMIv2"; + } + + typedef mac-address { + type string { + pattern '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'; + } + description + "The mac-address type represents an IEEE 802 MAC address. + The canonical representation uses lowercase characters. + + In the value set and its semantics, this type is equivalent + to the MacAddress textual convention of the SMIv2."; + reference + "IEEE 802: IEEE Standard for Local and Metropolitan Area + Networks: Overview and Architecture + RFC 2579: Textual Conventions for SMIv2"; + } + + /*** collection of XML-specific types ***/ + + typedef xpath1.0 { + type string; + description + "This type represents an XPATH 1.0 expression. + + When a schema node is defined that uses this type, the + description of the schema node MUST specify the XPath + context in which the XPath expression is evaluated."; + reference + "XPATH: XML Path Language (XPath) Version 1.0"; + } + + /*** collection of string types ***/ + + typedef hex-string { + type string { + pattern '([0-9a-fA-F]{2}(:[0-9a-fA-F]{2})*)?'; + } + description + "A hexadecimal string with octets represented as hex digits + separated by colons. The canonical representation uses + lowercase characters."; + } + + typedef uuid { + type string { + pattern '[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-' + + '[0-9a-fA-F]{4}-[0-9a-fA-F]{12}'; + } + description + "A Universally Unique IDentifier in the string representation + defined in RFC 4122. The canonical representation uses + lowercase characters. + + The following is an example of a UUID in string representation: + f81d4fae-7dec-11d0-a765-00a0c91e6bf6 + "; + reference + "RFC 4122: A Universally Unique IDentifier (UUID) URN + Namespace"; + } + + typedef dotted-quad { + type string { + pattern + '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'; + } + description + "An unsigned 32-bit number expressed in the dotted-quad + notation, i.e., four octets written as decimal numbers + and separated with the '.' (full stop) character."; + } +} From 3bbc5c49cd2a6d373bd46029d8d76342e650bf4c Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Wed, 29 Mar 2023 07:12:13 +0200 Subject: [PATCH 15/52] src/confd: derive YANG module search path from configure Signed-off-by: Joachim Wiberg --- src/confd/configure.ac | 3 +++ src/confd/src/Makefile.am | 2 ++ src/confd/src/ietf-system.c | 2 -- src/confd/yang/Makefile.am | 2 +- src/confd/yang/iana-crypt-hash.yang | 1 + 5 files changed, 7 insertions(+), 3 deletions(-) create mode 120000 src/confd/yang/iana-crypt-hash.yang diff --git a/src/confd/configure.ac b/src/confd/configure.ac index 3ed9eeca..fe2923ee 100644 --- a/src/confd/configure.ac +++ b/src/confd/configure.ac @@ -33,6 +33,9 @@ DATAROOTDIR=`eval echo $datarootdir` DATAROOTDIR=`eval echo $DATAROOTDIR` AC_SUBST(DATAROOTDIR) +YANGDIR=`eval echo $datarootdir/yang/modules/confd` +AC_SUBST(YANGDIR) + LIBDIR=`eval echo $libdir` LIBDIR=`eval echo $LIBDIR` AC_SUBST(LIBDIR) diff --git a/src/confd/src/Makefile.am b/src/confd/src/Makefile.am index aba4347a..7c9edbd4 100644 --- a/src/confd/src/Makefile.am +++ b/src/confd/src/Makefile.am @@ -1,3 +1,5 @@ +AM_CPPFLAGS = -DYANG_PATH_=\"$(YANGDIR)/\" + plugindir = $(srpdplugindir) plugin_LTLIBRARIES = confd-plugin.la diff --git a/src/confd/src/ietf-system.c b/src/confd/src/ietf-system.c index 04aa23c4..a516a060 100644 --- a/src/confd/src/ietf-system.c +++ b/src/confd/src/ietf-system.c @@ -247,8 +247,6 @@ free_vals: return SR_ERR_OK; } -#define YANG_PATH_ "/usr/share/yang/modules/sysrepo/" - int sr_plugin_init_cb(sr_session_ctx_t *sess, void **priv) { int r; diff --git a/src/confd/yang/Makefile.am b/src/confd/yang/Makefile.am index c36471ee..3e287aca 100644 --- a/src/confd/yang/Makefile.am +++ b/src/confd/yang/Makefile.am @@ -1,2 +1,2 @@ -yangdir = $(datarootdir)/yang/modules/sysrepo +yangdir = $(YANGDIR) yang_DATA = $(wildcard *.yang) diff --git a/src/confd/yang/iana-crypt-hash.yang b/src/confd/yang/iana-crypt-hash.yang new file mode 120000 index 00000000..6c6431e3 --- /dev/null +++ b/src/confd/yang/iana-crypt-hash.yang @@ -0,0 +1 @@ +iana-crypt-hash@2014-08-06.yang \ No newline at end of file From 708b756eba6eb256a3715ba15aef4b08fa9be41d Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Wed, 29 Mar 2023 07:38:01 +0200 Subject: [PATCH 16/52] src/confd: minor, coding style Signed-off-by: Joachim Wiberg --- src/confd/src/ietf-system.c | 115 ++++++++++++++++-------------------- 1 file changed, 50 insertions(+), 65 deletions(-) diff --git a/src/confd/src/ietf-system.c b/src/confd/src/ietf-system.c index a516a060..1bc084ed 100644 --- a/src/confd/src/ietf-system.c +++ b/src/confd/src/ietf-system.c @@ -16,8 +16,8 @@ #include #include -#define CLOCK_PATH "/ietf-system:system-state/clock" -#define PLATFORM_PATH "/ietf-system:system-state/platform" +#define CLOCK_PATH_ "/ietf-system:system-state/clock" +#define PLATFORM_PATH_ "/ietf-system:system-state/platform" #define DEBUG(frmt, ...) //#define DEBUG(frmt, ...) syslog(LOG_DEBUG, "%s: "frmt, __func__, ##__VA_ARGS__) @@ -68,7 +68,7 @@ static int clock_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *modu DEBUG("path=%s, request_path=%s", path, request_path); ctx = sr_acquire_context(sr_session_get_connection(session)); - rc = lyd_new_path(NULL, ctx, CLOCK_PATH, NULL, 0, parent); + rc = lyd_new_path(NULL, ctx, CLOCK_PATH_, NULL, 0, parent); if (rc) { fail: ERROR("Failed building data tree, libyang error %d", rc); @@ -83,13 +83,13 @@ static int clock_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *modu get_time_as_str(&t, boottime, sizeof(boottime)); } - rc = lyd_new_path(*parent, NULL, CLOCK_PATH "/boot-datetime", boottime, 0, NULL); + rc = lyd_new_path(*parent, NULL, CLOCK_PATH_ "/boot-datetime", boottime, 0, NULL); if (rc) goto fail; t = time(NULL); get_time_as_str(&t, curtime, sizeof(curtime)); - rc = lyd_new_path(*parent, NULL, CLOCK_PATH "/current-datetime", curtime, 0, NULL); + rc = lyd_new_path(*parent, NULL, CLOCK_PATH_ "/current-datetime", curtime, 0, NULL); if (rc) goto fail; @@ -114,7 +114,7 @@ static int platform_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *m /* POSIX func */ uname(&data); - rc = lyd_new_path(NULL, ctx, PLATFORM_PATH, NULL, 0, parent); + rc = lyd_new_path(NULL, ctx, PLATFORM_PATH_, NULL, 0, parent); if (rc) { fail: ERROR("Failed building data tree, libyang error %d", rc); @@ -124,16 +124,16 @@ static int platform_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *m lyd_print_mem(&buf, *parent, LYD_XML, 0); DEBUG("%s", buf); - rc = lyd_new_path(*parent, NULL, PLATFORM_PATH"/os-name", data.sysname, 0, NULL); + rc = lyd_new_path(*parent, NULL, PLATFORM_PATH_"/os-name", data.sysname, 0, NULL); if (rc) goto fail; - rc = lyd_new_path(*parent, NULL, PLATFORM_PATH"/os-release", data.release, 0, NULL); + rc = lyd_new_path(*parent, NULL, PLATFORM_PATH_"/os-release", data.release, 0, NULL); if (rc) goto fail; - rc = lyd_new_path(*parent, NULL, PLATFORM_PATH"/os-version", data.version, 0, NULL); + rc = lyd_new_path(*parent, NULL, PLATFORM_PATH_"/os-version", data.version, 0, NULL); if (rc) goto fail; - rc = lyd_new_path(*parent, NULL, PLATFORM_PATH"/machine", data.machine, 0, NULL); + rc = lyd_new_path(*parent, NULL, PLATFORM_PATH_"/machine", data.machine, 0, NULL); if (rc) goto fail; @@ -167,9 +167,9 @@ static int set_datetime_rpc_cb(sr_session_ctx_t *session, uint32_t sub_id, unsigned request_id, sr_val_t **output, size_t *output_cnt, void *priv) { + struct timeval tv; struct tm tm; time_t t; - struct timeval tv; memset(&tm, 0, sizeof(tm)); @@ -205,41 +205,39 @@ int hostname_change_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *m const char *xpath, sr_event_t event, unsigned request_id, void *priv) { - int r; sr_val_t *old_val, *new_val, *val; sr_change_iter_t *iter; sr_change_oper_t op; + int rc; if (event != SR_EV_ENABLED && event != SR_EV_DONE) return SR_ERR_OK; - r = sr_get_changes_iter(session, "//.", &iter); - if (r != SR_ERR_OK) { - ERROR("failed to get changes iter: %s", sr_strerror(r)); - return r; + rc = sr_get_changes_iter(session, "//.", &iter); + if (rc) { + ERROR("failed to get changes iter: %s", sr_strerror(rc)); + return rc; } - while (sr_get_change_next(session, iter, &op, &old_val, - &new_val) == SR_ERR_OK) { + while (sr_get_change_next(session, iter, &op, &old_val, &new_val) == SR_ERR_OK) { val = new_val ? new_val : old_val; if (strcmp(val->xpath, "/ietf-system:system/hostname")) goto free_vals; switch (op) { - case SR_OP_CREATED: - case SR_OP_MODIFIED: - if (sethostname(new_val->data.string_val, - strlen(new_val->data.string_val))) { - ERRNO("Failed to set hostname"); - return SR_ERR_SYS; - } + case SR_OP_CREATED: + case SR_OP_MODIFIED: + if (sethostname(new_val->data.string_val, + strlen(new_val->data.string_val))) { + ERRNO("Failed to set hostname"); + return SR_ERR_SYS; + } - DEBUG("Set hostname to '%s'", - new_val->data.string_val); - break; + DEBUG("Set hostname to '%s'", new_val->data.string_val); + break; } -free_vals: + free_vals: sr_free_val(old_val); sr_free_val(new_val); } @@ -249,72 +247,59 @@ free_vals: int sr_plugin_init_cb(sr_session_ctx_t *sess, void **priv) { - int r; sr_subscription_ctx_t *sub = NULL; sr_conn_ctx_t *conn; + int rc; openlog("sysrepo ietf-system plugin", LOG_USER, 0); conn = sr_session_get_connection(sess); sr_install_module(conn, YANG_PATH_"ietf-system.yang", NULL, NULL); - r = sr_oper_get_subscribe(sess, "ietf-system", - CLOCK_PATH, - clock_cb, NULL, - SR_SUBSCR_DEFAULT, &sub); - if (r != SR_ERR_OK) + rc = sr_oper_get_subscribe(sess, "ietf-system", CLOCK_PATH_, + clock_cb, NULL, SR_SUBSCR_DEFAULT, &sub); + if (rc != SR_ERR_OK) goto err; - r = sr_oper_get_subscribe(sess, "ietf-system", - PLATFORM_PATH, - platform_cb, NULL, - SR_SUBSCR_DEFAULT, &sub); - if (r != SR_ERR_OK) + rc = sr_oper_get_subscribe(sess, "ietf-system", PLATFORM_PATH_, + platform_cb, NULL, SR_SUBSCR_DEFAULT, &sub); + if (rc != SR_ERR_OK) goto err; - r = sr_rpc_subscribe(sess, "/ietf-system:system-restart", - exec_rpc_cb, "shutdown -r now", - 0, SR_SUBSCR_DEFAULT, &sub); - if (r != SR_ERR_OK) + rc = sr_rpc_subscribe(sess, "/ietf-system:system-restart", + exec_rpc_cb, "reboot", + 0, SR_SUBSCR_DEFAULT, &sub); + if (rc != SR_ERR_OK) goto err; - r = sr_rpc_subscribe(sess, "/ietf-system:system-shutdown", - exec_rpc_cb, "shutdown -h now", - 0, SR_SUBSCR_DEFAULT, &sub); - if (r != SR_ERR_OK) + rc = sr_rpc_subscribe(sess, "/ietf-system:system-shutdown", + exec_rpc_cb, "poweroff", 0, SR_SUBSCR_DEFAULT, &sub); + if (rc != SR_ERR_OK) goto err; - r = sr_rpc_subscribe(sess, "/ietf-system:set-current-datetime", - set_datetime_rpc_cb, NULL, - 0, SR_SUBSCR_DEFAULT, &sub); - if (r != SR_ERR_OK) + rc = sr_rpc_subscribe(sess, "/ietf-system:set-current-datetime", + set_datetime_rpc_cb, NULL, 0, SR_SUBSCR_DEFAULT, &sub); + if (rc != SR_ERR_OK) goto err; - - r = sr_module_change_subscribe(sess, "ietf-system", - "/ietf-system:system/hostname", + rc = sr_module_change_subscribe(sess, "ietf-system", "/ietf-system:system/hostname", hostname_change_cb, NULL, 0, - SR_SUBSCR_DEFAULT | - SR_SUBSCR_ENABLED, &sub); - - if (r != SR_ERR_OK) { + SR_SUBSCR_DEFAULT | SR_SUBSCR_ENABLED, &sub); + if (rc != SR_ERR_OK) { ERROR("failed to subscribe to changes of hostname: %s", - sr_strerror(r)); + sr_strerror(rc)); goto err; } - *(sr_subscription_ctx_t **)priv = sub; - DEBUG("init ok"); return SR_ERR_OK; err: - ERROR("init failed: %s", sr_strerror(r)); - + ERROR("init failed: %s", sr_strerror(rc)); sr_unsubscribe(sub); - return r; + return rc; } void sr_plugin_cleanup_cb(sr_session_ctx_t *session, void *priv) From 24a1eb542d6ee17c02c1fa8a26a50cac08f8ed5f Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Wed, 29 Mar 2023 08:03:37 +0200 Subject: [PATCH 17/52] src/confd: add support for enabling yang features Signed-off-by: Joachim Wiberg --- src/confd/src/ietf-system.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/confd/src/ietf-system.c b/src/confd/src/ietf-system.c index 1bc084ed..471da7b2 100644 --- a/src/confd/src/ietf-system.c +++ b/src/confd/src/ietf-system.c @@ -249,11 +249,17 @@ int sr_plugin_init_cb(sr_session_ctx_t *sess, void **priv) { sr_subscription_ctx_t *sub = NULL; sr_conn_ctx_t *conn; + char *features[] = { + "ntp", + "ntp-udp-port", + "timezone-name", + NULL + }; int rc; openlog("sysrepo ietf-system plugin", LOG_USER, 0); conn = sr_session_get_connection(sess); - sr_install_module(conn, YANG_PATH_"ietf-system.yang", NULL, NULL); + sr_install_module(conn, YANG_PATH_"ietf-system.yang", NULL, features); rc = sr_oper_get_subscribe(sess, "ietf-system", CLOCK_PATH_, clock_cb, NULL, SR_SUBSCR_DEFAULT, &sub); From d66dc166003234b2b0139eead755a60cecc069f9 Mon Sep 17 00:00:00 2001 From: Tobias Waldekranz Date: Wed, 29 Mar 2023 11:25:10 +0200 Subject: [PATCH 18/52] package/klish-plugin-sysrepo: Bump to latest master This adds completion support for nodes nested under choice and case nodes. --- package/klish-plugin-sysrepo/klish-plugin-sysrepo.hash | 3 ++- package/klish-plugin-sysrepo/klish-plugin-sysrepo.mk | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/package/klish-plugin-sysrepo/klish-plugin-sysrepo.hash b/package/klish-plugin-sysrepo/klish-plugin-sysrepo.hash index 432c9c19..ceb5ac66 100644 --- a/package/klish-plugin-sysrepo/klish-plugin-sysrepo.hash +++ b/package/klish-plugin-sysrepo/klish-plugin-sysrepo.hash @@ -1,3 +1,4 @@ # Locally calculated sha256 9d9d33b873917ca5d0bdcc47a36d2fd385971ab0c045d1472fcadf95ee5bcf5b LICENCE -sha256 cf972522d296b82e96fe0d366bb01a9fe47e71c785ed69205b7f20af251c5a48 klish-plugin-sysrepo-tags_1.0.0-br1.tar.gz +sha256 515fa2a3c66b41d6ab5ec93d61cdd32097115b2f46e39c522659b84d555eebf5 klish-plugin-sysrepo-cdd3eb51a7f7ee0ed5bd925fa636061d3b1b85fb-br1.tar.gz + diff --git a/package/klish-plugin-sysrepo/klish-plugin-sysrepo.mk b/package/klish-plugin-sysrepo/klish-plugin-sysrepo.mk index 4bd9e445..3f695c23 100644 --- a/package/klish-plugin-sysrepo/klish-plugin-sysrepo.mk +++ b/package/klish-plugin-sysrepo/klish-plugin-sysrepo.mk @@ -4,7 +4,7 @@ # ################################################################################ -KLISH_PLUGIN_SYSREPO_VERSION = tags/1.0.0 +KLISH_PLUGIN_SYSREPO_VERSION = cdd3eb51a7f7ee0ed5bd925fa636061d3b1b85fb KLISH_PLUGIN_SYSREPO_SITE = https://src.libcode.org/pkun/klish-plugin-sysrepo.git KLISH_PLUGIN_SYSREPO_SITE_METHOD = git KLISH_PLUGIN_SYSREPO_LICENSE = BSD-3 From 3cce1e642733e37d7053d0b2ad9ac40832bbed1b Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Wed, 29 Mar 2023 10:26:53 +0200 Subject: [PATCH 19/52] src/confd: drop shortname yang module aliases and load with version Drop the shortname yang aliases, installed they become copies of their versioned counterpart, which is not the intention, but also, no other yang consumer does this. We'd like to use ly_ctx_load_module() directly, or a slim sysrepo wrapper of the same, but no such API (load by yang module *name* with optional revision) exists currently. Signed-off-by: Joachim Wiberg --- src/confd/src/ietf-system.c | 4 ++-- src/confd/yang/iana-crypt-hash.yang | 1 - src/confd/yang/iana-if-type.yang | 1 - src/confd/yang/ietf-datastores.yang | 1 - src/confd/yang/ietf-inet-types.yang | 1 - src/confd/yang/ietf-interfaces.yang | 1 - src/confd/yang/ietf-ip.yang | 1 - src/confd/yang/ietf-netconf-acm.yang | 1 - src/confd/yang/ietf-system.yang | 1 - src/confd/yang/ietf-yang-types.yang | 1 - 10 files changed, 2 insertions(+), 11 deletions(-) delete mode 120000 src/confd/yang/iana-crypt-hash.yang delete mode 120000 src/confd/yang/iana-if-type.yang delete mode 120000 src/confd/yang/ietf-datastores.yang delete mode 120000 src/confd/yang/ietf-inet-types.yang delete mode 120000 src/confd/yang/ietf-interfaces.yang delete mode 120000 src/confd/yang/ietf-ip.yang delete mode 120000 src/confd/yang/ietf-netconf-acm.yang delete mode 120000 src/confd/yang/ietf-system.yang delete mode 120000 src/confd/yang/ietf-yang-types.yang diff --git a/src/confd/src/ietf-system.c b/src/confd/src/ietf-system.c index 471da7b2..5a4b743b 100644 --- a/src/confd/src/ietf-system.c +++ b/src/confd/src/ietf-system.c @@ -249,7 +249,7 @@ int sr_plugin_init_cb(sr_session_ctx_t *sess, void **priv) { sr_subscription_ctx_t *sub = NULL; sr_conn_ctx_t *conn; - char *features[] = { + const char *features[] = { "ntp", "ntp-udp-port", "timezone-name", @@ -259,7 +259,7 @@ int sr_plugin_init_cb(sr_session_ctx_t *sess, void **priv) openlog("sysrepo ietf-system plugin", LOG_USER, 0); conn = sr_session_get_connection(sess); - sr_install_module(conn, YANG_PATH_"ietf-system.yang", NULL, features); + sr_install_module(conn, YANG_PATH_"ietf-system@2014-08-06.yang", NULL, features); rc = sr_oper_get_subscribe(sess, "ietf-system", CLOCK_PATH_, clock_cb, NULL, SR_SUBSCR_DEFAULT, &sub); diff --git a/src/confd/yang/iana-crypt-hash.yang b/src/confd/yang/iana-crypt-hash.yang deleted file mode 120000 index 6c6431e3..00000000 --- a/src/confd/yang/iana-crypt-hash.yang +++ /dev/null @@ -1 +0,0 @@ -iana-crypt-hash@2014-08-06.yang \ No newline at end of file diff --git a/src/confd/yang/iana-if-type.yang b/src/confd/yang/iana-if-type.yang deleted file mode 120000 index e069e989..00000000 --- a/src/confd/yang/iana-if-type.yang +++ /dev/null @@ -1 +0,0 @@ -iana-if-type@2017-01-19.yang \ No newline at end of file diff --git a/src/confd/yang/ietf-datastores.yang b/src/confd/yang/ietf-datastores.yang deleted file mode 120000 index 31d0773b..00000000 --- a/src/confd/yang/ietf-datastores.yang +++ /dev/null @@ -1 +0,0 @@ -ietf-datastores@2018-02-14.yang \ No newline at end of file diff --git a/src/confd/yang/ietf-inet-types.yang b/src/confd/yang/ietf-inet-types.yang deleted file mode 120000 index f2c4cfee..00000000 --- a/src/confd/yang/ietf-inet-types.yang +++ /dev/null @@ -1 +0,0 @@ -ietf-inet-types@2013-07-15.yang \ No newline at end of file diff --git a/src/confd/yang/ietf-interfaces.yang b/src/confd/yang/ietf-interfaces.yang deleted file mode 120000 index 00c2e9ad..00000000 --- a/src/confd/yang/ietf-interfaces.yang +++ /dev/null @@ -1 +0,0 @@ -ietf-interfaces@2018-02-20.yang \ No newline at end of file diff --git a/src/confd/yang/ietf-ip.yang b/src/confd/yang/ietf-ip.yang deleted file mode 120000 index d16e72fc..00000000 --- a/src/confd/yang/ietf-ip.yang +++ /dev/null @@ -1 +0,0 @@ -ietf-ip@2018-02-22.yang \ No newline at end of file diff --git a/src/confd/yang/ietf-netconf-acm.yang b/src/confd/yang/ietf-netconf-acm.yang deleted file mode 120000 index 5c83622b..00000000 --- a/src/confd/yang/ietf-netconf-acm.yang +++ /dev/null @@ -1 +0,0 @@ -ietf-netconf-acm@2018-02-14.yang \ No newline at end of file diff --git a/src/confd/yang/ietf-system.yang b/src/confd/yang/ietf-system.yang deleted file mode 120000 index c3b6168c..00000000 --- a/src/confd/yang/ietf-system.yang +++ /dev/null @@ -1 +0,0 @@ -ietf-system@2014-08-06.yang \ No newline at end of file diff --git a/src/confd/yang/ietf-yang-types.yang b/src/confd/yang/ietf-yang-types.yang deleted file mode 120000 index a9d02a25..00000000 --- a/src/confd/yang/ietf-yang-types.yang +++ /dev/null @@ -1 +0,0 @@ -ietf-yang-types@2013-07-15.yang \ No newline at end of file From cfef79bbf95ea30ad91af4554a53d9cc4774a1cc Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Fri, 31 Mar 2023 11:02:45 +0200 Subject: [PATCH 20/52] configs: enable netopeer2-cli and add klish to defconfigs Signed-off-by: Joachim Wiberg --- configs/aarch64_defconfig | 3 +++ configs/amd64_defconfig | 3 +++ 2 files changed, 6 insertions(+) diff --git a/configs/aarch64_defconfig b/configs/aarch64_defconfig index 5303cd03..887fa2b4 100644 --- a/configs/aarch64_defconfig +++ b/configs/aarch64_defconfig @@ -48,6 +48,7 @@ BR2_PACKAGE_UBOOT_TOOLS_FIT_SUPPORT=y BR2_PACKAGE_UBOOT_TOOLS_FIT_SIGNATURE_SUPPORT=y BR2_PACKAGE_UBOOT_TOOLS_FIT_CHECK_SIGN=y BR2_PACKAGE_LIBCURL_CURL=y +BR2_PACKAGE_NETOPEER2_CLI=y BR2_PACKAGE_NSS_MDNS=y BR2_PACKAGE_ONIGURUMA=y BR2_PACKAGE_AVAHI=y @@ -130,6 +131,8 @@ BR2_PACKAGE_FINIT_PLUGIN_RTC=y BR2_PACKAGE_FINIT_PLUGIN_TTY=y BR2_PACKAGE_FINIT_PLUGIN_URANDOM=y BR2_PACKAGE_IFUPDOWN_NG=y +BR2_PACKAGE_KLISH=y +BR2_PACKAGE_KLISH_PLUGIN_SYSREPO=y BR2_PACKAGE_P_NET=y BR2_PACKAGE_P_NET_MAX_SUBSLOTS=12 BR2_PACKAGE_P_NET_MAX_PHYSICAL_PORTS=10 diff --git a/configs/amd64_defconfig b/configs/amd64_defconfig index d81e85d4..5356cafe 100644 --- a/configs/amd64_defconfig +++ b/configs/amd64_defconfig @@ -45,6 +45,7 @@ BR2_PACKAGE_UBOOT_TOOLS_FIT_SUPPORT=y BR2_PACKAGE_UBOOT_TOOLS_FIT_SIGNATURE_SUPPORT=y BR2_PACKAGE_UBOOT_TOOLS_FIT_CHECK_SIGN=y BR2_PACKAGE_LIBCURL_CURL=y +BR2_PACKAGE_NETOPEER2_CLI=y BR2_PACKAGE_NSS_MDNS=y BR2_PACKAGE_ONIGURUMA=y BR2_PACKAGE_AVAHI=y @@ -133,6 +134,8 @@ BR2_PACKAGE_FINIT_PLUGIN_RTC=y BR2_PACKAGE_FINIT_PLUGIN_TTY=y BR2_PACKAGE_FINIT_PLUGIN_URANDOM=y BR2_PACKAGE_IFUPDOWN_NG=y +BR2_PACKAGE_KLISH=y +BR2_PACKAGE_KLISH_PLUGIN_SYSREPO=y BR2_PACKAGE_P_NET=y BR2_PACKAGE_P_NET_MAX_SUBSLOTS=12 BR2_PACKAGE_P_NET_MAX_PHYSICAL_PORTS=10 From abd001f57dc2fd2420fc8a871237d71447d9a3d0 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Fri, 31 Mar 2023 11:03:14 +0200 Subject: [PATCH 21/52] package/confd: start netopeer2-server along with sysrepo Signed-off-by: Joachim Wiberg --- package/confd/sysrepo.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/package/confd/sysrepo.conf b/package/confd/sysrepo.conf index 08c717c2..d5e00ded 100644 --- a/package/confd/sysrepo.conf +++ b/package/confd/sysrepo.conf @@ -1,5 +1,6 @@ run if: [S] /lib/infix/clean-etc -- run if: [S] /lib/infix/prep-db -- service if: name:sysrepo [12345789] sysrepo-plugind -n -- Configuration daemon +service if: name:netopeer [12345789] netopeer2-server -n -- NETCONF daemon task if: [12345789] resolvconf -u -- Update DNS configuration From e729c82c32be801ad791143e909db2b645b3fb5f Mon Sep 17 00:00:00 2001 From: Tobias Waldekranz Date: Wed, 29 Mar 2023 13:35:23 +0200 Subject: [PATCH 22/52] klinfix: Initial add Infix integration of klish and klish-plugin-sysrepo. Initially we add: More flexible management of running vs. startup: Instead of always committing changes both to running and startup, commit only modifies running. To persist changes to startup, the copy command is introduced. This lets the user copy from factory/startup/running to startup/running at any time. Well-known verbs like abort, leave, end, etc. --- configs/aarch64_defconfig | 1 + configs/amd64_defconfig | 1 + package/Config.in | 1 + package/klinfix/Config.in | 8 + package/klinfix/klinfix.mk | 14 ++ package/klish-plugin-sysrepo/Config.in | 1 + package/klish/Config.in | 1 + src/klinfix/.gitignore | 33 ++++ src/klinfix/Makefile.am | 3 + src/klinfix/README.md | 74 +++++++++ src/klinfix/autogen.sh | 3 + src/klinfix/configure.ac | 33 ++++ src/klinfix/src/Makefile.am | 9 ++ src/klinfix/src/klinfix.c | 155 ++++++++++++++++++ src/klinfix/xml/Makefile.am | 2 + src/klinfix/xml/infix.xml | 215 +++++++++++++++++++++++++ 16 files changed, 554 insertions(+) create mode 100644 package/klinfix/Config.in create mode 100644 package/klinfix/klinfix.mk create mode 100644 src/klinfix/.gitignore create mode 100644 src/klinfix/Makefile.am create mode 100644 src/klinfix/README.md create mode 100755 src/klinfix/autogen.sh create mode 100644 src/klinfix/configure.ac create mode 100644 src/klinfix/src/Makefile.am create mode 100644 src/klinfix/src/klinfix.c create mode 100644 src/klinfix/xml/Makefile.am create mode 100644 src/klinfix/xml/infix.xml diff --git a/configs/aarch64_defconfig b/configs/aarch64_defconfig index 887fa2b4..620cf446 100644 --- a/configs/aarch64_defconfig +++ b/configs/aarch64_defconfig @@ -131,6 +131,7 @@ BR2_PACKAGE_FINIT_PLUGIN_RTC=y BR2_PACKAGE_FINIT_PLUGIN_TTY=y BR2_PACKAGE_FINIT_PLUGIN_URANDOM=y BR2_PACKAGE_IFUPDOWN_NG=y +BR2_PACKAGE_KLINFIX=y BR2_PACKAGE_KLISH=y BR2_PACKAGE_KLISH_PLUGIN_SYSREPO=y BR2_PACKAGE_P_NET=y diff --git a/configs/amd64_defconfig b/configs/amd64_defconfig index 5356cafe..60170bdc 100644 --- a/configs/amd64_defconfig +++ b/configs/amd64_defconfig @@ -134,6 +134,7 @@ BR2_PACKAGE_FINIT_PLUGIN_RTC=y BR2_PACKAGE_FINIT_PLUGIN_TTY=y BR2_PACKAGE_FINIT_PLUGIN_URANDOM=y BR2_PACKAGE_IFUPDOWN_NG=y +BR2_PACKAGE_KLINFIX=y BR2_PACKAGE_KLISH=y BR2_PACKAGE_KLISH_PLUGIN_SYSREPO=y BR2_PACKAGE_P_NET=y diff --git a/package/Config.in b/package/Config.in index a0a0a24f..f9e24aff 100644 --- a/package/Config.in +++ b/package/Config.in @@ -6,6 +6,7 @@ source "$BR2_EXTERNAL_INFIX_PATH/package/faux/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/finit/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/ifupdown2/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/ifupdown-ng/Config.in" +source "$BR2_EXTERNAL_INFIX_PATH/package/klinfix/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/klish/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/klish-plugin-sysrepo/Config.in" source "$BR2_EXTERNAL_INFIX_PATH/package/mdnsd/Config.in" diff --git a/package/klinfix/Config.in b/package/klinfix/Config.in new file mode 100644 index 00000000..933d1289 --- /dev/null +++ b/package/klinfix/Config.in @@ -0,0 +1,8 @@ +config BR2_PACKAGE_KLINFIX + bool "klinfix" + select BR2_PACKAGE_KLISH + select BR2_PACKAGE_KLISH_PLUGIN_SYSREPO + select BR2_PACKAGE_SYSREPO + help + A plugin to klish with an opinionated config and some + command extensions, suitable for systems running Infix. diff --git a/package/klinfix/klinfix.mk b/package/klinfix/klinfix.mk new file mode 100644 index 00000000..d2f88539 --- /dev/null +++ b/package/klinfix/klinfix.mk @@ -0,0 +1,14 @@ +################################################################################ +# +# klinfix +# +################################################################################ + +KLINFIX_VERSION = 1.0 +KLINFIX_LICENSE = BSD-3-Clause +KLINFIX_SITE_METHOD = local +KLINFIX_SITE = $(BR2_EXTERNAL_INFIX_PATH)/src/klinfix +KLINFIX_DEPENDENCIES = klish-plugin-sysrepo +KLINFIX_AUTORECONF = YES + +$(eval $(autotools-package)) diff --git a/package/klish-plugin-sysrepo/Config.in b/package/klish-plugin-sysrepo/Config.in index b61e20b9..b9c735e8 100644 --- a/package/klish-plugin-sysrepo/Config.in +++ b/package/klish-plugin-sysrepo/Config.in @@ -13,6 +13,7 @@ config BR2_PACKAGE_KLISH_PLUGIN_SYSREPO config BR2_PACKAGE_KLISH_PLUGIN_SYSREPO_XML bool "install xml" depends on BR2_PACKAGE_KLISH_PLUGIN_SYSREPO + depends on !BR2_PACKAGE_KLINFIX default y help Install the default XML spec bundled with the project, which diff --git a/package/klish/Config.in b/package/klish/Config.in index 9f55b085..e3f03e0e 100644 --- a/package/klish/Config.in +++ b/package/klish/Config.in @@ -12,6 +12,7 @@ config BR2_PACKAGE_KLISH config BR2_PACKAGE_KLISH_DEFAULT_XML bool "install xml" depends on BR2_PACKAGE_KLISH + depends on !BR2_PACKAGE_KLINFIX default y help Install a small XML spec containing a definition of an diff --git a/src/klinfix/.gitignore b/src/klinfix/.gitignore new file mode 100644 index 00000000..e9e8e747 --- /dev/null +++ b/src/klinfix/.gitignore @@ -0,0 +1,33 @@ +*~ +*.o +*.la +*.lo +*.so +.deps +.libs + +/aclocal.m4 +/autom4te.cache/ +/aux +/clixon.xml +/compile +/config.h +/config.h.in +/config.guess +/config.log +/config.status +/config.sub +/configure +/depcomp +/install-sh +/libtool +/ltmain.sh +/m4 +/missing + +GPATH +GRTAGS +GTAGS +Makefile +Makefile.in + diff --git a/src/klinfix/Makefile.am b/src/klinfix/Makefile.am new file mode 100644 index 00000000..cb106dee --- /dev/null +++ b/src/klinfix/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = src xml +DISTCLEANFILES = *~ *.d +ACLOCAL_AMFLAGS = -I m4 diff --git a/src/klinfix/README.md b/src/klinfix/README.md new file mode 100644 index 00000000..7dfcc518 --- /dev/null +++ b/src/klinfix/README.md @@ -0,0 +1,74 @@ +Infix Extensions to klish-plugin-sysrepo +---------------------------------------- + +Tailor `klish` and `klish-plugin-sysrepo` to suit Infix. The resulting +CLI is, in many respects, still very similar to Juniper's JunOS, since +that is also the primary inspiration for klish, with some additions +and modifications. + +Broadly speaking, the CLI is split up in two major modes: + +- Admin/Exec: This is the default mode, where operational commands can + be issued. +- Configure: Where a new candidate configuration is prepared. + + +### Admin/Exec Mode + +The following table lists the available commands: + +| Command | Description | Hotkey | +|--------------------|---------------------------------------|--------| +| `configure` | Enter configuration mode | | +| `copy ` | Copy `` to `` | | +| `exit` | Exit | `C-d` | +| `logout` | Alias for `exit` | | +| `shell` | Start system shell | | +| `show ` | Show various configuration and status | | + +#### Copy Command + +`copy ` + +Where `` is one of: +- `factory-config` +- `startup-config` +- `running-config` + +And `` is one of: +- `startup-config` +- `running-config` + +#### Show Command + +`show ` + +The following table lists the available items: + +| Item | Description | +|------------------|--------------------------------------| +| `running-config` | Show the active system configuration | +| | | + + +### Configure + +The following table lists the available commands: + +| Command | Description | Hotkey | +|------------|--------------------------------------------------------------|--------| +| `abort` | Abandon candidate | `C-d` | +| `check` | Validate candidate | | +| `commit` | Commit current candidate to running-config | | +| `delete` | Delete configuration setting(s) | | +| `diff` | Summarize uncommitted changes | | +| `do` | Execute operational mode command | | +| `edit` | Descend to the specified configuration node | | +| `exit` | Ascend to the parent configuration node, or abort (from top) | | +| `leave` | Finalize candidate and apply to running-config | `C-z` | +| `no` | Alias for delete | | +| `rollback` | Restore candidate to running-config | | +| `set` | Set configuration setting | | +| `show` | Show configuration | | +| `top` | Ascend to the configuration root | | +| `up` | Ascend to the parent configuration node | `C-c` | diff --git a/src/klinfix/autogen.sh b/src/klinfix/autogen.sh new file mode 100755 index 00000000..69ad0e18 --- /dev/null +++ b/src/klinfix/autogen.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +autoreconf -W portability -vifm diff --git a/src/klinfix/configure.ac b/src/klinfix/configure.ac new file mode 100644 index 00000000..06f0af1d --- /dev/null +++ b/src/klinfix/configure.ac @@ -0,0 +1,33 @@ +AC_PREREQ(2.61) +AC_INIT([klinfix], [1.0.0], + [https://github.com/kernelkit/infix/issues]) +AM_INIT_AUTOMAKE(1.11 foreign subdir-objects) +AM_SILENT_RULES(yes) + +LT_INIT + +AC_CONFIG_FILES([ + Makefile + src/Makefile + xml/Makefile +]) + +AC_PROG_CC +AC_PROG_INSTALL + +# Check for pkg-config first, warn if it's not installed +PKG_PROG_PKG_CONFIG + +PKG_CHECK_MODULES([sysrepo], [sysrepo >= 2.2.60]) +AC_CHECK_LIB([klish], [kplugin_new],, AC_MSG_ERROR([Klish not found])) + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +KLISHLIBDIR=`eval echo $libdir/klish` +AC_SUBST(KLISHLIBDIR) + +KLISHCONFDIR=`eval echo $sysconfdir/klish` +AC_SUBST(KLISHCONFDIR) + +AC_OUTPUT diff --git a/src/klinfix/src/Makefile.am b/src/klinfix/src/Makefile.am new file mode 100644 index 00000000..5e236e85 --- /dev/null +++ b/src/klinfix/src/Makefile.am @@ -0,0 +1,9 @@ +CFLAGS = -Wall -Wextra -Werror -Wno-unused-parameter + +pluginsdir = $(KLISHLIBDIR)/plugins +plugins_LTLIBRARIES = kplugin-klinfix.la + +kplugin_klinfix_la_CFLAGS = $(sysrepo_CFLAGS) $(klish_CFLAGS) $(CFLAGS) +kplugin_klinfix_la_LIBADD = $(sysrepo_LIBS) $(klish_LIBS) +kplugin_klinfix_la_LDFLAGS = -module -avoid-version -shared +kplugin_klinfix_la_SOURCES = klinfix.c diff --git a/src/klinfix/src/klinfix.c b/src/klinfix/src/klinfix.c new file mode 100644 index 00000000..8abd910f --- /dev/null +++ b/src/klinfix/src/klinfix.c @@ -0,0 +1,155 @@ +#include +#include + +#include +#include + +#include +#include + +const uint8_t kplugin_klinfix_major = 1; +const uint8_t kplugin_klinfix_minor = 0; + +int klix_ds_from_str(const char *text, sr_datastore_t *ds) +{ + size_t len = strlen(text); + + if (!strncmp("startup-config", text, len)) + *ds = SR_DS_STARTUP; + else if (!strncmp("running-config", text, len)) + *ds = SR_DS_RUNNING; + else if (!strncmp("candidate-config", text, len)) + *ds = SR_DS_CANDIDATE; + else if (!strncmp("operational-config", text, len)) + *ds = SR_DS_OPERATIONAL; + else if (!strncmp("factory-config", text, len)) + *ds = SR_DS_FACTORY_DEFAULT; + else + return -1; + + return 0; +} + +int klix_copy(kcontext_t *ctx) +{ + kpargv_t *pargv = kcontext_pargv(ctx); + sr_datastore_t srcds, dstds; + kparg_t *srcarg, *dstarg; + sr_session_ctx_t *sess; + sr_conn_ctx_t *conn; + int err; + + srcarg = kpargv_find(pargv, "src"); + dstarg = kpargv_find(pargv, "dst"); + if (!srcarg || !dstarg) + goto err; + + if (klix_ds_from_str(kparg_value(srcarg), &srcds)) { + fprintf(stderr, + "Error: \"%s\" is not the name of any known datastore\n", + kparg_value(srcarg)); + goto err; + } + if (klix_ds_from_str(kparg_value(dstarg), &dstds)) { + fprintf(stderr, + "Error: \"%s\" is not the name of any known datastore\n", + kparg_value(dstarg)); + goto err; + } + + switch (srcds) { + case SR_DS_STARTUP: + case SR_DS_RUNNING: + case SR_DS_FACTORY_DEFAULT: + break; + default: + fprintf(stderr, + "Error: \"%s\" is not a valid source datastore\n", + kparg_value(srcarg)); + goto err; + } + + switch (dstds) { + case SR_DS_STARTUP: + case SR_DS_RUNNING: + break; + default: + fprintf(stderr, + "Error: \"%s\" is not a valid destination datastore\n", + kparg_value(dstarg)); + goto err; + } + + if (sr_connect(SR_CONN_DEFAULT, &conn)) { + fprintf(stderr, "Error: Connection to datastore failed\n"); + goto err; + } + if (sr_session_start(conn, dstds, &sess)) { + fprintf(stderr, "Error: Unable to open transaction to %s\n", + kparg_value(dstarg)); + goto err_disconnect; + } + + err = sr_copy_config(sess, NULL, srcds, 0); + if (err) { + fprintf(stderr, "Error: Unable to copy configuration (%d)\n", + err); + goto err_disconnect; + } + + sr_disconnect(conn); + return 0; + +err_disconnect: + sr_disconnect(conn); +err: + return -1; +} + +int klix_commit(kcontext_t *ctx) +{ + sr_session_ctx_t *sess; + sr_conn_ctx_t *conn; + int err; + + if (sr_connect(SR_CONN_DEFAULT, &conn)) { + fprintf(stderr, "Error: Connection to datastore failed\n"); + goto err; + } + + if (sr_session_start(conn, SR_DS_RUNNING, &sess)) { + fprintf(stderr, + "Error: Unable to open transaction to running-config\n"); + goto err_disconnect; + } + + err = sr_copy_config(sess, NULL, SR_DS_CANDIDATE, 0); + if (err) { + fprintf(stderr, + "Error: Unable to commit candidate to running (%d)\n", + err); + goto err; + } + + sr_disconnect(conn); + return 0; + +err_disconnect: + sr_disconnect(conn); +err: + return -1; +} + +int kplugin_klinfix_fini(kcontext_t *ctx) +{ + return 0; +} + +int kplugin_klinfix_init(kcontext_t *ctx) +{ + kplugin_t *plugin = kcontext_plugin(ctx); + + kplugin_add_syms(plugin, ksym_new("klix_copy", klix_copy)); + kplugin_add_syms(plugin, ksym_new("klix_commit", klix_commit)); + return 0; +} diff --git a/src/klinfix/xml/Makefile.am b/src/klinfix/xml/Makefile.am new file mode 100644 index 00000000..1bd6bfa9 --- /dev/null +++ b/src/klinfix/xml/Makefile.am @@ -0,0 +1,2 @@ +klishconfdir = $(KLISHCONFDIR) +klishconf_DATA = $(wildcard *.xml) diff --git a/src/klinfix/xml/infix.xml b/src/klinfix/xml/infix.xml new file mode 100644 index 00000000..927ff1dc --- /dev/null +++ b/src/klinfix/xml/infix.xml @@ -0,0 +1,215 @@ + + + + + + + + + ShowBrackets = y + ShowSemicolons = y + FirstKeyWithStatement = n + MultiKeysWithStatement = y + Colorize = y + Indent = 2 + + + + + factory-config + startup-config + running-config + + + + + + + startup-config + running-config + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %u@%h:exec> + + + + /bin/sh -l + + + + pop + + + pop + + + + replace configure + + + + + + + + + + + + + + + + + + + + + %u@%h:configure> + + + + + + + + + + + replace main + + + + + replace main + + + + + + replace main + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From b639812ba4795def54d644822dd6b640c4fce20a Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sun, 2 Apr 2023 16:22:56 +0200 Subject: [PATCH 23/52] patches/netopeer2: add support for running in foreground with syslog The default is to use -d (debug), which changes logging to stdout, which we do not want with Finit. Signed-off-by: Joachim Wiberg --- .../netopeer2-server-foreground.patch | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 patches/netopeer2/netopeer2-server-foreground.patch diff --git a/patches/netopeer2/netopeer2-server-foreground.patch b/patches/netopeer2/netopeer2-server-foreground.patch new file mode 100644 index 00000000..45a05388 --- /dev/null +++ b/patches/netopeer2/netopeer2-server-foreground.patch @@ -0,0 +1,60 @@ +commit 9e18bd10df1ac2aabd46a790ac6148c638a513b8 +Author: Joachim Wiberg +Date: Fri Mar 31 10:44:32 2023 +0200 + + netopeer2-server: add support for running in foreground with syslog + + Signed-off-by: Joachim Wiberg + +diff --git a/src/main.c b/src/main.c +index 6d054f5..c403000 100644 +--- a/src/main.c ++++ b/src/main.c +@@ -1082,6 +1082,7 @@ print_usage(char *progname) + fprintf(stdout, " -f PATH Path to netopeer2 server files directory (default path is \"%s\")\n", SERVER_DIR); + fprintf(stdout, " -U[PATH] Listen on a local UNIX socket (default path is \"%s\").\n", NP2SRV_UNIX_SOCK_PATH); + fprintf(stdout, " -m MODE Set mode for the listening UNIX socket.\n"); ++ fprintf(stdout, " -n Run in foreground and log to syslog.\n"); + fprintf(stdout, " -u UID Set UID/user for the listening UNIX socket.\n"); + fprintf(stdout, " -g GID Set GID/group for the listening UNIX socket.\n"); + fprintf(stdout, " -t TIMEOUT Timeout in seconds of all sysrepo functions (applying edit-config, reading data, ...),\n"); +@@ -1112,7 +1113,7 @@ main(int argc, char *argv[]) + { + int ret = EXIT_SUCCESS; + int c, *idx, i; +- int daemonize = 1, verb = 0; ++ int daemonize = 1, verb = 0, use_syslog = 0; + int pidfd; + const char *pidfile = NP2SRV_PID_FILE_PATH; + char pid[8]; +@@ -1145,7 +1146,7 @@ main(int argc, char *argv[]) + np2srv.server_dir = SERVER_DIR; + + /* process command line options */ +- while ((c = getopt(argc, argv, "dhVp:f:U::m:u:g:t:x:v:c:")) != -1) { ++ while ((c = getopt(argc, argv, "dhVp:f:U::m:nu:g:t:x:v:c:")) != -1) { + switch (c) { + case 'd': + daemonize = 0; +@@ -1202,6 +1203,10 @@ main(int argc, char *argv[]) + return EXIT_FAILURE; + } + break; ++ case 'n': ++ daemonize = 0; ++ use_syslog = 1; ++ break; + case 'u': + np2srv.unix_uid = strtoul(optarg, &ptr, 10); + if (*ptr) { +@@ -1306,6 +1311,10 @@ main(int argc, char *argv[]) + np2_stderr_log = 0; + } + ++ /* use syslog even if running in foreground */ ++ if (use_syslog == 1) ++ np2_stderr_log = 0; ++ + /* make sure we are the only instance - lock the PID file and write the PID */ + pidfd = open(pidfile, O_RDWR | O_CREAT, 0640); + if (pidfd < 0) { From 3bef1eec167ff066c6510d4c8ef972a3e999aeb4 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Fri, 31 Mar 2023 14:15:18 +0200 Subject: [PATCH 24/52] Disable rauc streaming and kernel nbd, not used atm. Signed-off-by: Joachim Wiberg --- board/aarch64/linux_defconfig | 1 - board/amd64/linux_defconfig | 1 - configs/aarch64_defconfig | 1 - configs/amd64_defconfig | 1 - 4 files changed, 4 deletions(-) diff --git a/board/aarch64/linux_defconfig b/board/aarch64/linux_defconfig index b57529a0..ca1ab4c2 100644 --- a/board/aarch64/linux_defconfig +++ b/board/aarch64/linux_defconfig @@ -141,7 +141,6 @@ CONFIG_MTD_SPI_NOR=y CONFIG_OF_OVERLAY=y CONFIG_BLK_DEV_NULL_BLK=y CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_NBD=y CONFIG_BLK_DEV_RAM=y CONFIG_VIRTIO_BLK=y CONFIG_BLK_DEV_NVME=y diff --git a/board/amd64/linux_defconfig b/board/amd64/linux_defconfig index 7c3eca33..423675b5 100644 --- a/board/amd64/linux_defconfig +++ b/board/amd64/linux_defconfig @@ -95,7 +95,6 @@ CONFIG_FW_CFG_SYSFS=y CONFIG_FW_CFG_SYSFS_CMDLINE=y CONFIG_BLK_DEV_NULL_BLK=y CONFIG_BLK_DEV_LOOP=y -CONFIG_BLK_DEV_NBD=y CONFIG_BLK_DEV_RAM=y CONFIG_VIRTIO_BLK=y CONFIG_BLK_DEV_SD=y diff --git a/configs/aarch64_defconfig b/configs/aarch64_defconfig index 620cf446..05df7a3a 100644 --- a/configs/aarch64_defconfig +++ b/configs/aarch64_defconfig @@ -103,7 +103,6 @@ BR2_PACKAGE_PWGEN=y BR2_PACKAGE_RAUC=y BR2_PACKAGE_RAUC_GPT=y BR2_PACKAGE_RAUC_NETWORK=y -BR2_PACKAGE_RAUC_STREAMING=y BR2_PACKAGE_SYSKLOGD=y BR2_PACKAGE_SYSKLOGD_LOGGER=y BR2_PACKAGE_WATCHDOGD=y diff --git a/configs/amd64_defconfig b/configs/amd64_defconfig index 60170bdc..0a8e58f4 100644 --- a/configs/amd64_defconfig +++ b/configs/amd64_defconfig @@ -100,7 +100,6 @@ BR2_PACKAGE_PWGEN=y BR2_PACKAGE_RAUC=y BR2_PACKAGE_RAUC_GPT=y BR2_PACKAGE_RAUC_NETWORK=y -BR2_PACKAGE_RAUC_STREAMING=y BR2_PACKAGE_SYSKLOGD=y BR2_PACKAGE_SYSKLOGD_LOGGER=y BR2_PACKAGE_WATCHDOGD=y From 7079a35088309fc650d717bbbf4ed41eaac4ee9b Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Fri, 31 Mar 2023 15:54:14 +0200 Subject: [PATCH 25/52] configs: disable nginx temporarily while evaluating sysrepo Signed-off-by: Joachim Wiberg --- configs/aarch64_defconfig | 4 ---- configs/amd64_defconfig | 4 ---- 2 files changed, 8 deletions(-) diff --git a/configs/aarch64_defconfig b/configs/aarch64_defconfig index 05df7a3a..77c20eae 100644 --- a/configs/aarch64_defconfig +++ b/configs/aarch64_defconfig @@ -75,10 +75,6 @@ BR2_PACKAGE_NETCALC=y BR2_PACKAGE_NETCAT_OPENBSD=y BR2_PACKAGE_NETSNMP=y BR2_PACKAGE_NFTABLES=y -BR2_PACKAGE_NGINX_HTTP_SSL_MODULE=y -BR2_PACKAGE_NGINX_HTTP_V2_MODULE=y -BR2_PACKAGE_NGINX_HTTP_GUNZIP_MODULE=y -BR2_PACKAGE_NGINX_HTTP_AUTH_REQUEST_MODULE=y BR2_PACKAGE_NMAP=y BR2_PACKAGE_NMAP_NCAT=y BR2_PACKAGE_NMAP_NMAP=y diff --git a/configs/amd64_defconfig b/configs/amd64_defconfig index 0a8e58f4..ed4161f8 100644 --- a/configs/amd64_defconfig +++ b/configs/amd64_defconfig @@ -72,10 +72,6 @@ BR2_PACKAGE_NETCALC=y BR2_PACKAGE_NETCAT_OPENBSD=y BR2_PACKAGE_NETSNMP=y BR2_PACKAGE_NFTABLES=y -BR2_PACKAGE_NGINX_HTTP_SSL_MODULE=y -BR2_PACKAGE_NGINX_HTTP_V2_MODULE=y -BR2_PACKAGE_NGINX_HTTP_GUNZIP_MODULE=y -BR2_PACKAGE_NGINX_HTTP_AUTH_REQUEST_MODULE=y BR2_PACKAGE_NMAP=y BR2_PACKAGE_NMAP_NCAT=y BR2_PACKAGE_NMAP_NMAP=y From b3b25ed4d626d8649d86c48c44d5a56574153b15 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sat, 1 Apr 2023 10:15:14 +0200 Subject: [PATCH 26/52] src/confd: improved coverage of ietf-system - Call external programs safely with run() - Use augeas to update /etc/hostname and /etc/hosts - Add support for generating /etc/chrony.conf - Update license copyright due to significant contrib. Signed-off-by: Joachim Wiberg --- src/confd/LICENSE | 1 + src/confd/src/Makefile.am | 4 +- src/confd/src/ietf-system.c | 423 ++++++++++++++++++++++++++++++------ 3 files changed, 355 insertions(+), 73 deletions(-) diff --git a/src/confd/LICENSE b/src/confd/LICENSE index 1ae040d8..0423839d 100644 --- a/src/confd/LICENSE +++ b/src/confd/LICENSE @@ -1,4 +1,5 @@ Copyright (c) 2020 Denis Kalashnikov +Copyright (c) 2023 The KernelKit Authors All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/src/confd/src/Makefile.am b/src/confd/src/Makefile.am index 7c9edbd4..6606c972 100644 --- a/src/confd/src/Makefile.am +++ b/src/confd/src/Makefile.am @@ -3,7 +3,7 @@ AM_CPPFLAGS = -DYANG_PATH_=\"$(YANGDIR)/\" plugindir = $(srpdplugindir) plugin_LTLIBRARIES = confd-plugin.la -confd_plugin_la_CFLAGS = $(sysrepo_CFLAGS) $(CFLAGS) -confd_plugin_la_LIBADD = $(sysrepo_LIBS) $(CFLAGS) +confd_plugin_la_CFLAGS = $(augeas_CFLAGS) $(sysrepo_CFLAGS) $(CFLAGS) +confd_plugin_la_LIBADD = $(augeas_LIBS) $(sysrepo_LIBS) $(CFLAGS) confd_plugin_la_LDFLAGS = -module -avoid-version -shared confd_plugin_la_SOURCES = ietf-system.c diff --git a/src/confd/src/ietf-system.c b/src/confd/src/ietf-system.c index 5a4b743b..183b34dc 100644 --- a/src/confd/src/ietf-system.c +++ b/src/confd/src/ietf-system.c @@ -1,5 +1,6 @@ -/* Sysrepo plugin of ietf-system@2014-08-06.yang module */ +/* SPDX-License-Identifier: BSD-3-Clause */ +#include #include #include #include @@ -15,15 +16,72 @@ #include #include +#include +#include #define CLOCK_PATH_ "/ietf-system:system-state/clock" #define PLATFORM_PATH_ "/ietf-system:system-state/platform" + +#define NELEMS(arr) (sizeof(arr) / sizeof(arr[0])) + #define DEBUG(frmt, ...) //#define DEBUG(frmt, ...) syslog(LOG_DEBUG, "%s: "frmt, __func__, ##__VA_ARGS__) #define ERROR(frmt, ...) syslog(LOG_ERR, "%s: " frmt, __func__, ##__VA_ARGS__) #define ERRNO(frmt, ...) syslog(LOG_ERR, "%s: " frmt ": %s", __func__, ##__VA_ARGS__, strerror(errno)) +static augeas *aug; + + +/** + * Like system(), but takes a formatted string as argument. + * @param fmt printf style format list to command to run + * + * This system() wrapper greatly simplifies operations that usually + * consist of composing a command from parts into a dynamic buffer + * before calling it. The return value from system() is also parsed, + * checking for proper exit and signals. + * + * @returns If the command exits normally, the return code of the command + * is returned. Otherwise, if the command is signalled, the return code + * is -1 and @a errno is set to @c EINTR. + */ +static int run(const char *fmt, ...) +{ + va_list ap; + char *cmd; + int len; + int rc; + + va_start(ap, fmt); + len = vsnprintf(NULL, 0, fmt, ap); + va_end(ap); + + cmd = alloca(++len); + if (!cmd) { + errno = ENOMEM; + return -1; + } + + va_start(ap, fmt); + vsnprintf(cmd, len, fmt, ap); + va_end(ap); + + rc = system(cmd); + if (rc == -1) + return -1; + + if (WIFEXITED(rc)) { + errno = 0; + rc = WEXITSTATUS(rc); + } else if (WIFSIGNALED(rc)) { + errno = EINTR; + rc = -1; + } + + return rc; +} + /* Return seconds since boot */ static long get_uptime(void) { @@ -143,29 +201,26 @@ static int platform_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *m return SR_ERR_OK; } -static int exec_rpc_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *path, - const sr_val_t *input, const size_t input_cnt, - sr_event_t event, unsigned request_id, - sr_val_t **output, size_t *output_cnt, - void *priv) +static int rpc_exec(sr_session_ctx_t *session, uint32_t sub_id, const char *path, + const sr_val_t *input, const size_t input_cnt, + sr_event_t event, unsigned request_id, + sr_val_t **output, size_t *output_cnt, + void *priv) { - int rc; - DEBUG("path: %s", path); - rc = system(priv); - if (WIFSIGNALED(rc) || (WIFEXITED(rc) && WEXITSTATUS(rc))) + if (run(priv)) return SR_ERR_INTERNAL; return SR_ERR_OK; } /* '/ietf-system:set-current-date-time' */ -static int set_datetime_rpc_cb(sr_session_ctx_t *session, uint32_t sub_id, - const char *path, const sr_val_t *input, - const size_t input_cnt, sr_event_t event, - unsigned request_id, sr_val_t **output, - size_t *output_cnt, void *priv) +static int rpc_set_datetime(sr_session_ctx_t *session, uint32_t sub_id, + const char *path, const sr_val_t *input, + const size_t input_cnt, sr_event_t event, + unsigned request_id, sr_val_t **output, + size_t *output_cnt, void *priv) { struct timeval tv; struct tm tm; @@ -201,51 +256,287 @@ static int set_datetime_rpc_cb(sr_session_ctx_t *session, uint32_t sub_id, return SR_ERR_OK; } -int hostname_change_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *module, - const char *xpath, sr_event_t event, - unsigned request_id, void *priv) +static int sys_reload_services(void) { - sr_val_t *old_val, *new_val, *val; - sr_change_iter_t *iter; - sr_change_oper_t op; + return run("initctl -nbq touch sysklogd lldpd"); +} + +static void print_val(sr_val_t *val) +{ + char *str; + + if (sr_print_val_mem(&str, val)) + return; + ERROR("%s", str); + free(str); +} + +int sr_get_bool(sr_session_ctx_t *session, const char *fmt, ...) +{ + sr_val_t *val = NULL; + char *xpath; + va_list ap; + int rc = 0; + int len; + + va_start(ap, fmt); + len = vsnprintf(NULL, 0, fmt, ap) + 1; + va_end(ap); + + xpath = alloca(len); + if (!xpath) + goto fail; + + va_start(ap, fmt); + vsnprintf(xpath, len, fmt, ap); + va_end(ap); + + if (sr_get_item(session, xpath, 0, &val)) + goto fail; + if (!val || val->type != SR_BOOL_T) + goto fail; + + rc = val->data.bool_val; +fail: + if (val) + sr_free_val(val); + return rc; +} + +char *sr_get_str(sr_session_ctx_t *session, const char *fmt, ...) +{ + char *str = NULL; + sr_val_t *val; + char *xpath; + va_list ap; + int len; + + va_start(ap, fmt); + len = vsnprintf(NULL, 0, fmt, ap) + 1; + va_end(ap); + + xpath = alloca(len); + if (!xpath) + return NULL; + + va_start(ap, fmt); + vsnprintf(xpath, len, fmt, ap); + va_end(ap); + + if (sr_get_item(session, xpath, 0, &val)) { + ERROR("Failed reading string value from xpath %s", xpath); + goto fail; + } + if (!val || val->type != SR_STRING_T) + goto fail; + + str = strdup(val->data.string_val); +fail: + if (val) + sr_free_val(val); + return str; +} + +#define CHRONY_CONF "/etc/chrony.conf" +#define CHRONY_PREV CHRONY_CONF "-" +#define CHRONY_NEXT CHRONY_CONF "+" + +static int change_ntp(sr_session_ctx_t *session, uint32_t sub_id, const char *module, + const char *xpath, sr_event_t event, unsigned request_id, void *priv) +{ + const char *fn = CHRONY_NEXT; + int valid = -1; + sr_data_t *sdt; + sr_val_t *val; + size_t cnt; + FILE *fp; int rc; - if (event != SR_EV_ENABLED && event != SR_EV_DONE) + switch (event) { + case SR_EV_ENABLED: /* first time, on register. */ + case SR_EV_CHANGE: /* regular change (copy cand running) */ + /* Generate next config */ + break; + + case SR_EV_ABORT: /* User abort, or other plugin failed */ + remove(CHRONY_NEXT); return SR_ERR_OK; - rc = sr_get_changes_iter(session, "//.", &iter); - if (rc) { - ERROR("failed to get changes iter: %s", sr_strerror(rc)); - return rc; + case SR_EV_DONE: + /* Check if passed validation in previous event */ + if (access(CHRONY_NEXT, F_OK)) + return SR_ERR_OK; + + remove(CHRONY_PREV); + rename(CHRONY_CONF, CHRONY_PREV); + rename(CHRONY_NEXT, CHRONY_CONF); + if (!sr_get_bool(session, "/ietf-system:system/ntp/enabled")) { + run("initctl -nbq disable chronyd"); + return SR_ERR_OK; + } + /* + * If chrony is alrady enabled we tell Finit it's been + * modified , so Finit restarts it, otherwise enable it. + */ + run("initctl -nbq touch chronyd"); + run("initctl -nbq enable chronyd"); + return SR_ERR_OK; } - while (sr_get_change_next(session, iter, &op, &old_val, &new_val) == SR_ERR_OK) { - val = new_val ? new_val : old_val; - if (strcmp(val->xpath, "/ietf-system:system/hostname")) - goto free_vals; + if (rc = sr_get_items(session, "/ietf-system:system/ntp/server", 0, 0, &val, &cnt)) { + remove(CHRONY_NEXT); + return rc; + } + + fp = fopen(fn, "w"); + if (!fp) { + ERROR("failed updating %s: %s", fn, strerror(errno)); + sr_free_values(val, cnt); + return SR_ERR_SYS; + } - switch (op) { - case SR_OP_CREATED: - case SR_OP_MODIFIED: - if (sethostname(new_val->data.string_val, - strlen(new_val->data.string_val))) { - ERRNO("Failed to set hostname"); - return SR_ERR_SYS; + for (size_t i = 0; i < cnt; i++) { + const char *xpath = val[i].xpath; + char *type, *ptr; + int server = 0; + + /* + * Handle empty startup-config on SR_EV_ENABLED, + * prevents subscribe failure due to false invalid. + */ + if (i == 0) + valid = 0; + + /* Get /ietf-system:system/ntp/server[name='foo'] */ + ptr = sr_get_str(session, "%s/udp/address", xpath); + if (ptr) { + type = sr_get_str(session, "%s/association-type", xpath); + fprintf(fp, "%s %s", type ?: "server", ptr); + server++; + if (type) + free(type); + free(ptr); + + if (ptr = sr_get_str(session, "%s/udp/port", xpath)) { + fprintf(fp, " port %s", ptr); + free(ptr); } - - DEBUG("Set hostname to '%s'", new_val->data.string_val); - break; } - free_vals: - sr_free_val(old_val); - sr_free_val(new_val); + if (server) { + if (sr_get_bool(session, "%s/iburst", xpath)) + fprintf(fp, " iburst"); + if (sr_get_bool(session, "%s/prefer", xpath)) + fprintf(fp, " prefer"); + + fprintf(fp, "\n"); + valid++; + } + } + sr_free_values(val, cnt); + + fprintf(fp, "driftfile /var/lib/chrony/drift\n"); + fprintf(fp, "makestep 1.0 3\n"); + fprintf(fp, "maxupdateskew 100.0\n"); + fprintf(fp, "dumpdir /var/lib/chrony\n"); + fprintf(fp, "rtcfile /var/lib/chrony/rtc\n"); + fclose(fp); + + if (!valid) { + remove(fn); + return SR_ERR_VALIDATION_FAILED; } return SR_ERR_OK; } -int sr_plugin_init_cb(sr_session_ctx_t *sess, void **priv) +static int change_hostname(sr_session_ctx_t *session, uint32_t sub_id, const char *module, + const char *xpath, sr_event_t event, unsigned request_id, void *priv) +{ + const char *host, *nm, *tmp; + char **hosts, *current; + int err, i, nhosts; + int rc; + + switch (event) { + case SR_EV_ENABLED: /* first time, on register. */ + case SR_EV_CHANGE: /* regular change (copy cand running) */ + /* Wait for DONE to activate changes */ + return SR_ERR_OK; + + case SR_EV_ABORT: /* User abort, or other plugin failed */ + return SR_ERR_OK; + + case SR_EV_DONE: + /* Activate changes */ + break; + } + + nm = sr_get_str(session, xpath); + if (!nm) { + ERROR("No valid hostname in current session"); + nm = "infix"; /* XXX: derive from global "options.h" */ + } + ERROR("Got hostname %s", nm); + + aug_get(aug, "etc/hostname/hostname", &tmp); + current = strdup(tmp); + ERROR("Current hostname %s", current); + + err = sethostname(nm, strlen(nm)); + err = err ? : aug_set(aug, "etc/hostname/hostname", nm); + + nhosts = aug_match(aug, "etc/hosts/*/canonical", &hosts); + for (i = 0; i < nhosts; i++) { + aug_get(aug, hosts[i], &host); + if (!strcmp(host, current)) + err = err ? : aug_set(aug, hosts[i], nm); + free(hosts[i]); + } + free(hosts); + free(current); + + if (err) { + ERROR("Failed activating changes."); + return err; + } + + ERROR("Reload hostname-dependent services ..."); + err = err ? : aug_save(aug); + if (sys_reload_services()) + return SR_ERR_SYS; + + return SR_ERR_OK; +} + +static int register_change(sr_session_ctx_t *session, const char *xpath, + sr_module_change_cb cb, void *arg, sr_subscription_ctx_t **sub) +{ + int rc = sr_module_change_subscribe(session, "ietf-system", xpath, cb, arg, 0, + SR_SUBSCR_DEFAULT | SR_SUBSCR_ENABLED, sub); + if (rc) + ERROR("failed subscribing to changes of %s: %s", xpath, sr_strerror(rc)); + return rc; +} + +static int register_rpc(sr_session_ctx_t *session, const char *xpath, + sr_rpc_cb cb, void *arg, sr_subscription_ctx_t **sub) +{ + int rc = sr_rpc_subscribe(session, xpath, cb, arg, 0, SR_SUBSCR_DEFAULT, sub); + if (rc) + ERROR("failed subscribing to %s rpc: %s", xpath, sr_strerror(rc)); + return rc; +} + +#define REGISTER_CHANGE(s,x,c,a,u) \ + if (rc = register_change(s, x, c, a, u))\ + goto err + +#define REGISTER_RPC(s,x,c,a,u) \ + if (rc = register_rpc(s, x, c, a, u)) \ + goto err + +int sr_plugin_init_cb(sr_session_ctx_t *session, void **priv) { sr_subscription_ctx_t *sub = NULL; sr_conn_ctx_t *conn; @@ -257,44 +548,34 @@ int sr_plugin_init_cb(sr_session_ctx_t *sess, void **priv) }; int rc; - openlog("sysrepo ietf-system plugin", LOG_USER, 0); - conn = sr_session_get_connection(sess); + aug = aug_init(NULL, "", 0); + if (!aug || + aug_load_file(aug, "/etc/hostname") || + aug_load_file(aug, "/etc/hosts")) { + ERROR("ietf-system: Augeas initialization failed"); + goto err; + } + + openlog("ietf-system", LOG_USER, 0); + conn = sr_session_get_connection(session); sr_install_module(conn, YANG_PATH_"ietf-system@2014-08-06.yang", NULL, features); - rc = sr_oper_get_subscribe(sess, "ietf-system", CLOCK_PATH_, + rc = sr_oper_get_subscribe(session, "ietf-system", CLOCK_PATH_, clock_cb, NULL, SR_SUBSCR_DEFAULT, &sub); if (rc != SR_ERR_OK) goto err; - rc = sr_oper_get_subscribe(sess, "ietf-system", PLATFORM_PATH_, + rc = sr_oper_get_subscribe(session, "ietf-system", PLATFORM_PATH_, platform_cb, NULL, SR_SUBSCR_DEFAULT, &sub); if (rc != SR_ERR_OK) goto err; - rc = sr_rpc_subscribe(sess, "/ietf-system:system-restart", - exec_rpc_cb, "reboot", - 0, SR_SUBSCR_DEFAULT, &sub); - if (rc != SR_ERR_OK) - goto err; + REGISTER_RPC(session, "/ietf-system:system-restart", rpc_exec, "reboot", &sub); + REGISTER_RPC(session, "/ietf-system:system-shutdown", rpc_exec, "poweroff", &sub); + REGISTER_RPC(session, "/ietf-system:set-current-datetime", rpc_set_datetime, NULL, &sub); - rc = sr_rpc_subscribe(sess, "/ietf-system:system-shutdown", - exec_rpc_cb, "poweroff", 0, SR_SUBSCR_DEFAULT, &sub); - if (rc != SR_ERR_OK) - goto err; - - rc = sr_rpc_subscribe(sess, "/ietf-system:set-current-datetime", - set_datetime_rpc_cb, NULL, 0, SR_SUBSCR_DEFAULT, &sub); - if (rc != SR_ERR_OK) - goto err; - - rc = sr_module_change_subscribe(sess, "ietf-system", "/ietf-system:system/hostname", - hostname_change_cb, NULL, 0, - SR_SUBSCR_DEFAULT | SR_SUBSCR_ENABLED, &sub); - if (rc != SR_ERR_OK) { - ERROR("failed to subscribe to changes of hostname: %s", - sr_strerror(rc)); - goto err; - } + REGISTER_CHANGE(session, "/ietf-system:system/hostname", change_hostname, NULL, &sub); + REGISTER_CHANGE(session, "/ietf-system:system/ntp", change_ntp, NULL, &sub); *(sr_subscription_ctx_t **)priv = sub; DEBUG("init ok"); From 405e1f1b70c7b46f5eadc5c2d8bb135bd218bb7f Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sat, 1 Apr 2023 15:56:08 +0200 Subject: [PATCH 27/52] src/confd: minor refactor, split in multiple files Signed-off-by: Joachim Wiberg --- src/confd/src/Makefile.am | 2 +- src/confd/src/core.c | 41 +++++++++ src/confd/src/core.h | 70 ++++++++++++++++ src/confd/src/ietf-system.c | 161 ++++++------------------------------ src/confd/src/run.c | 52 ++++++++++++ 5 files changed, 188 insertions(+), 138 deletions(-) create mode 100644 src/confd/src/core.c create mode 100644 src/confd/src/core.h create mode 100644 src/confd/src/run.c diff --git a/src/confd/src/Makefile.am b/src/confd/src/Makefile.am index 6606c972..af19cdcf 100644 --- a/src/confd/src/Makefile.am +++ b/src/confd/src/Makefile.am @@ -6,4 +6,4 @@ plugin_LTLIBRARIES = confd-plugin.la confd_plugin_la_CFLAGS = $(augeas_CFLAGS) $(sysrepo_CFLAGS) $(CFLAGS) confd_plugin_la_LIBADD = $(augeas_LIBS) $(sysrepo_LIBS) $(CFLAGS) confd_plugin_la_LDFLAGS = -module -avoid-version -shared -confd_plugin_la_SOURCES = ietf-system.c +confd_plugin_la_SOURCES = core.c core.h run.c ietf-system.c diff --git a/src/confd/src/core.c b/src/confd/src/core.c new file mode 100644 index 00000000..1727cace --- /dev/null +++ b/src/confd/src/core.c @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#include "core.h" + +static struct confd confd; + +int sr_plugin_init_cb(sr_session_ctx_t *session, void **priv) +{ + int rc = SR_ERR_SYS; + + openlog("confd", LOG_USER, 0); + + confd.session = session; + confd.conn = sr_session_get_connection(session); + confd.sub = NULL; + + if (!confd.conn) + goto err; + + confd.aug = aug_init(NULL, "", 0); + if (!confd.aug) + goto err; + + *priv = (void *)&confd; + + if (ietf_system_init(&confd)) + goto err; + + return SR_ERR_OK; +err: + ERROR("init failed: %s", sr_strerror(rc)); + sr_unsubscribe(confd.sub); + + return rc; +} + +void sr_plugin_cleanup_cb(sr_session_ctx_t *session, void *priv) +{ + sr_unsubscribe((sr_subscription_ctx_t *)priv); + closelog(); +} diff --git a/src/confd/src/core.h b/src/confd/src/core.h new file mode 100644 index 00000000..9b708a0f --- /dev/null +++ b/src/confd/src/core.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +#ifndef CONFD_CORE_H_ +#define CONFD_CORE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +#define NELEMS(arr) (sizeof(arr) / sizeof(arr[0])) + +#define DEBUG(frmt, ...) +//#define DEBUG(frmt, ...) syslog(LOG_DEBUG, "%s: "frmt, __func__, ##__VA_ARGS__) +#define ERROR(frmt, ...) syslog(LOG_ERR, "%s: " frmt, __func__, ##__VA_ARGS__) +#define ERRNO(frmt, ...) syslog(LOG_ERR, "%s: " frmt ": %s", __func__, ##__VA_ARGS__, strerror(errno)) + +#define REGISTER_CHANGE(s,x,c,a,u) \ + if (rc = register_change(s, x, c, a, u))\ + goto err + +#define REGISTER_RPC(s,x,c,a,u) \ + if (rc = register_rpc(s, x, c, a, u)) \ + goto err + +struct confd { + sr_session_ctx_t *session; + sr_conn_ctx_t *conn; + sr_subscription_ctx_t *sub; + + augeas *aug; +}; + +static inline int register_change(sr_session_ctx_t *session, const char *xpath, + sr_module_change_cb cb, void *arg, sr_subscription_ctx_t **sub) +{ + int rc = sr_module_change_subscribe(session, "ietf-system", xpath, cb, arg, 0, + SR_SUBSCR_DEFAULT | SR_SUBSCR_ENABLED, sub); + if (rc) + ERROR("failed subscribing to changes of %s: %s", xpath, sr_strerror(rc)); + return rc; +} + +static inline int register_rpc(sr_session_ctx_t *session, const char *xpath, + sr_rpc_cb cb, void *arg, sr_subscription_ctx_t **sub) +{ + int rc = sr_rpc_subscribe(session, xpath, cb, arg, 0, SR_SUBSCR_DEFAULT, sub); + if (rc) + ERROR("failed subscribing to %s rpc: %s", xpath, sr_strerror(rc)); + return rc; +} + + +/* core.c */ +int run(const char *fmt, ...); + +/* ietf-syste.c */ +int ietf_system_init(struct confd *confd); + +#endif /* CONFD_CORE_H_ */ diff --git a/src/confd/src/ietf-system.c b/src/confd/src/ietf-system.c index 183b34dc..ed0ffa55 100644 --- a/src/confd/src/ietf-system.c +++ b/src/confd/src/ietf-system.c @@ -1,87 +1,13 @@ /* SPDX-License-Identifier: BSD-3-Clause */ -#include -#include -#include -#include -#include +#include "core.h" #include -#include -#include -#include -#include - -/* Linux specific */ #include -#include -#include -#include -#include - #define CLOCK_PATH_ "/ietf-system:system-state/clock" #define PLATFORM_PATH_ "/ietf-system:system-state/platform" -#define NELEMS(arr) (sizeof(arr) / sizeof(arr[0])) - -#define DEBUG(frmt, ...) -//#define DEBUG(frmt, ...) syslog(LOG_DEBUG, "%s: "frmt, __func__, ##__VA_ARGS__) -#define ERROR(frmt, ...) syslog(LOG_ERR, "%s: " frmt, __func__, ##__VA_ARGS__) -#define ERRNO(frmt, ...) syslog(LOG_ERR, "%s: " frmt ": %s", __func__, ##__VA_ARGS__, strerror(errno)) - -static augeas *aug; - - -/** - * Like system(), but takes a formatted string as argument. - * @param fmt printf style format list to command to run - * - * This system() wrapper greatly simplifies operations that usually - * consist of composing a command from parts into a dynamic buffer - * before calling it. The return value from system() is also parsed, - * checking for proper exit and signals. - * - * @returns If the command exits normally, the return code of the command - * is returned. Otherwise, if the command is signalled, the return code - * is -1 and @a errno is set to @c EINTR. - */ -static int run(const char *fmt, ...) -{ - va_list ap; - char *cmd; - int len; - int rc; - - va_start(ap, fmt); - len = vsnprintf(NULL, 0, fmt, ap); - va_end(ap); - - cmd = alloca(++len); - if (!cmd) { - errno = ENOMEM; - return -1; - } - - va_start(ap, fmt); - vsnprintf(cmd, len, fmt, ap); - va_end(ap); - - rc = system(cmd); - if (rc == -1) - return -1; - - if (WIFEXITED(rc)) { - errno = 0; - rc = WEXITSTATUS(rc); - } else if (WIFSIGNALED(rc)) { - errno = EINTR; - rc = -1; - } - - return rc; -} - /* Return seconds since boot */ static long get_uptime(void) { @@ -344,6 +270,7 @@ fail: static int change_ntp(sr_session_ctx_t *session, uint32_t sub_id, const char *module, const char *xpath, sr_event_t event, unsigned request_id, void *priv) { + struct confd *confd = (struct confd *)priv; const char *fn = CHRONY_NEXT; int valid = -1; sr_data_t *sdt; @@ -453,6 +380,7 @@ static int change_ntp(sr_session_ctx_t *session, uint32_t sub_id, const char *mo static int change_hostname(sr_session_ctx_t *session, uint32_t sub_id, const char *module, const char *xpath, sr_event_t event, unsigned request_id, void *priv) { + struct confd *confd = (struct confd *)priv; const char *host, *nm, *tmp; char **hosts, *current; int err, i, nhosts; @@ -479,18 +407,18 @@ static int change_hostname(sr_session_ctx_t *session, uint32_t sub_id, const cha } ERROR("Got hostname %s", nm); - aug_get(aug, "etc/hostname/hostname", &tmp); + aug_get(confd->aug, "etc/hostname/hostname", &tmp); current = strdup(tmp); ERROR("Current hostname %s", current); err = sethostname(nm, strlen(nm)); - err = err ? : aug_set(aug, "etc/hostname/hostname", nm); + err = err ? : aug_set(confd->aug, "etc/hostname/hostname", nm); - nhosts = aug_match(aug, "etc/hosts/*/canonical", &hosts); + nhosts = aug_match(confd->aug, "etc/hosts/*/canonical", &hosts); for (i = 0; i < nhosts; i++) { - aug_get(aug, hosts[i], &host); + aug_get(confd->aug, hosts[i], &host); if (!strcmp(host, current)) - err = err ? : aug_set(aug, hosts[i], nm); + err = err ? : aug_set(confd->aug, hosts[i], nm); free(hosts[i]); } free(hosts); @@ -502,44 +430,15 @@ static int change_hostname(sr_session_ctx_t *session, uint32_t sub_id, const cha } ERROR("Reload hostname-dependent services ..."); - err = err ? : aug_save(aug); + err = err ? : aug_save(confd->aug); if (sys_reload_services()) return SR_ERR_SYS; return SR_ERR_OK; } -static int register_change(sr_session_ctx_t *session, const char *xpath, - sr_module_change_cb cb, void *arg, sr_subscription_ctx_t **sub) +int ietf_system_init(struct confd *confd) { - int rc = sr_module_change_subscribe(session, "ietf-system", xpath, cb, arg, 0, - SR_SUBSCR_DEFAULT | SR_SUBSCR_ENABLED, sub); - if (rc) - ERROR("failed subscribing to changes of %s: %s", xpath, sr_strerror(rc)); - return rc; -} - -static int register_rpc(sr_session_ctx_t *session, const char *xpath, - sr_rpc_cb cb, void *arg, sr_subscription_ctx_t **sub) -{ - int rc = sr_rpc_subscribe(session, xpath, cb, arg, 0, SR_SUBSCR_DEFAULT, sub); - if (rc) - ERROR("failed subscribing to %s rpc: %s", xpath, sr_strerror(rc)); - return rc; -} - -#define REGISTER_CHANGE(s,x,c,a,u) \ - if (rc = register_change(s, x, c, a, u))\ - goto err - -#define REGISTER_RPC(s,x,c,a,u) \ - if (rc = register_rpc(s, x, c, a, u)) \ - goto err - -int sr_plugin_init_cb(sr_session_ctx_t *session, void **priv) -{ - sr_subscription_ctx_t *sub = NULL; - sr_conn_ctx_t *conn; const char *features[] = { "ntp", "ntp-udp-port", @@ -548,50 +447,38 @@ int sr_plugin_init_cb(sr_session_ctx_t *session, void **priv) }; int rc; - aug = aug_init(NULL, "", 0); - if (!aug || - aug_load_file(aug, "/etc/hostname") || - aug_load_file(aug, "/etc/hosts")) { + if (aug_load_file(confd->aug, "/etc/hostname") || + aug_load_file(confd->aug, "/etc/hosts")) { ERROR("ietf-system: Augeas initialization failed"); goto err; } - openlog("ietf-system", LOG_USER, 0); - conn = sr_session_get_connection(session); - sr_install_module(conn, YANG_PATH_"ietf-system@2014-08-06.yang", NULL, features); + if (rc = sr_install_module(confd->conn, YANG_PATH_"ietf-system@2014-08-06.yang", NULL, features)) + goto err; - rc = sr_oper_get_subscribe(session, "ietf-system", CLOCK_PATH_, - clock_cb, NULL, SR_SUBSCR_DEFAULT, &sub); + rc = sr_oper_get_subscribe(confd->session, "ietf-system", CLOCK_PATH_, + clock_cb, NULL, SR_SUBSCR_DEFAULT, &confd->sub); if (rc != SR_ERR_OK) goto err; - rc = sr_oper_get_subscribe(session, "ietf-system", PLATFORM_PATH_, - platform_cb, NULL, SR_SUBSCR_DEFAULT, &sub); + rc = sr_oper_get_subscribe(confd->session, "ietf-system", PLATFORM_PATH_, + platform_cb, NULL, SR_SUBSCR_DEFAULT, &confd->sub); if (rc != SR_ERR_OK) goto err; - REGISTER_RPC(session, "/ietf-system:system-restart", rpc_exec, "reboot", &sub); - REGISTER_RPC(session, "/ietf-system:system-shutdown", rpc_exec, "poweroff", &sub); - REGISTER_RPC(session, "/ietf-system:set-current-datetime", rpc_set_datetime, NULL, &sub); + REGISTER_RPC(confd->session, "/ietf-system:system-restart", rpc_exec, "reboot", &confd->sub); + REGISTER_RPC(confd->session, "/ietf-system:system-shutdown", rpc_exec, "poweroff", &confd->sub); + REGISTER_RPC(confd->session, "/ietf-system:set-current-datetime", rpc_set_datetime, NULL, &confd->sub); - REGISTER_CHANGE(session, "/ietf-system:system/hostname", change_hostname, NULL, &sub); - REGISTER_CHANGE(session, "/ietf-system:system/ntp", change_ntp, NULL, &sub); + REGISTER_CHANGE(confd->session, "/ietf-system:system/hostname", change_hostname, NULL, &confd->sub); + REGISTER_CHANGE(confd->session, "/ietf-system:system/ntp", change_ntp, NULL, &confd->sub); - *(sr_subscription_ctx_t **)priv = sub; DEBUG("init ok"); return SR_ERR_OK; - err: ERROR("init failed: %s", sr_strerror(rc)); - sr_unsubscribe(sub); + sr_unsubscribe(confd->sub); return rc; } - -void sr_plugin_cleanup_cb(sr_session_ctx_t *session, void *priv) -{ - sr_unsubscribe((sr_subscription_ctx_t *)priv); - - DEBUG("cleanup ok"); -} diff --git a/src/confd/src/run.c b/src/confd/src/run.c new file mode 100644 index 00000000..1a809c68 --- /dev/null +++ b/src/confd/src/run.c @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#include "core.h" + +/** + * Like system(), but takes a formatted string as argument. + * @param fmt printf style format list to command to run + * + * This system() wrapper greatly simplifies operations that usually + * consist of composing a command from parts into a dynamic buffer + * before calling it. The return value from system() is also parsed, + * checking for proper exit and signals. + * + * @returns If the command exits normally, the return code of the command + * is returned. Otherwise, if the command is signalled, the return code + * is -1 and @a errno is set to @c EINTR. + */ +int run(const char *fmt, ...) +{ + va_list ap; + char *cmd; + int len; + int rc; + + va_start(ap, fmt); + len = vsnprintf(NULL, 0, fmt, ap); + va_end(ap); + + cmd = alloca(++len); + if (!cmd) { + errno = ENOMEM; + return -1; + } + + va_start(ap, fmt); + vsnprintf(cmd, len, fmt, ap); + va_end(ap); + + rc = system(cmd); + if (rc == -1) + return -1; + + if (WIFEXITED(rc)) { + errno = 0; + rc = WEXITSTATUS(rc); + } else if (WIFSIGNALED(rc)) { + errno = EINTR; + rc = -1; + } + + return rc; +} From af5c5bc3d238e1d02adfcb053ebb019ccbd96071 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sun, 2 Apr 2023 16:14:21 +0200 Subject: [PATCH 28/52] src/confd: refactor, expose flags arg to change subscrie Signed-off-by: Joachim Wiberg --- src/confd/src/core.h | 15 +++++++-------- src/confd/src/ietf-system.c | 8 +++----- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/confd/src/core.h b/src/confd/src/core.h index 9b708a0f..3b1c036f 100644 --- a/src/confd/src/core.h +++ b/src/confd/src/core.h @@ -25,12 +25,12 @@ #define ERROR(frmt, ...) syslog(LOG_ERR, "%s: " frmt, __func__, ##__VA_ARGS__) #define ERRNO(frmt, ...) syslog(LOG_ERR, "%s: " frmt ": %s", __func__, ##__VA_ARGS__, strerror(errno)) -#define REGISTER_CHANGE(s,x,c,a,u) \ - if (rc = register_change(s, x, c, a, u))\ +#define REGISTER_CHANGE(s,m,x,f,c,a,u) \ + if (rc = register_change(s, m, x, f, c, a, u)) \ goto err -#define REGISTER_RPC(s,x,c,a,u) \ - if (rc = register_rpc(s, x, c, a, u)) \ +#define REGISTER_RPC(s,x,c,a,u) \ + if (rc = register_rpc(s, x, c, a, u)) \ goto err struct confd { @@ -41,11 +41,10 @@ struct confd { augeas *aug; }; -static inline int register_change(sr_session_ctx_t *session, const char *xpath, - sr_module_change_cb cb, void *arg, sr_subscription_ctx_t **sub) +static inline int register_change(sr_session_ctx_t *session, const char *module, const char *xpath, + int flags, sr_module_change_cb cb, void *arg, sr_subscription_ctx_t **sub) { - int rc = sr_module_change_subscribe(session, "ietf-system", xpath, cb, arg, 0, - SR_SUBSCR_DEFAULT | SR_SUBSCR_ENABLED, sub); + int rc = sr_module_change_subscribe(session, module, xpath, cb, arg, 0, flags | SR_SUBSCR_DEFAULT, sub); if (rc) ERROR("failed subscribing to changes of %s: %s", xpath, sr_strerror(rc)); return rc; diff --git a/src/confd/src/ietf-system.c b/src/confd/src/ietf-system.c index ed0ffa55..1ced3a30 100644 --- a/src/confd/src/ietf-system.c +++ b/src/confd/src/ietf-system.c @@ -466,15 +466,13 @@ int ietf_system_init(struct confd *confd) if (rc != SR_ERR_OK) goto err; + REGISTER_CHANGE(confd->session, "ietf-system", "/ietf-system:system/hostname", 0, change_hostname, confd, &confd->sub); + REGISTER_CHANGE(confd->session, "ietf-system", "/ietf-system:system/ntp", 0, change_ntp, confd, &confd->sub); + REGISTER_RPC(confd->session, "/ietf-system:system-restart", rpc_exec, "reboot", &confd->sub); REGISTER_RPC(confd->session, "/ietf-system:system-shutdown", rpc_exec, "poweroff", &confd->sub); REGISTER_RPC(confd->session, "/ietf-system:set-current-datetime", rpc_set_datetime, NULL, &confd->sub); - REGISTER_CHANGE(confd->session, "/ietf-system:system/hostname", change_hostname, NULL, &confd->sub); - REGISTER_CHANGE(confd->session, "/ietf-system:system/ntp", change_ntp, NULL, &confd->sub); - - DEBUG("init ok"); - return SR_ERR_OK; err: ERROR("init failed: %s", sr_strerror(rc)); From d8eb88e6da1ba9e990493f6f57c3a50e4cc465b2 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sun, 2 Apr 2023 16:15:00 +0200 Subject: [PATCH 29/52] src/confd: improve error handling in ietf-system Signed-off-by: Joachim Wiberg --- src/confd/src/ietf-system.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/src/confd/src/ietf-system.c b/src/confd/src/ietf-system.c index 1ced3a30..f208a6b9 100644 --- a/src/confd/src/ietf-system.c +++ b/src/confd/src/ietf-system.c @@ -381,10 +381,11 @@ static int change_hostname(sr_session_ctx_t *session, uint32_t sub_id, const cha const char *xpath, sr_event_t event, unsigned request_id, void *priv) { struct confd *confd = (struct confd *)priv; - const char *host, *nm, *tmp; + const char *host, *tmp = NULL; char **hosts, *current; int err, i, nhosts; - int rc; + int rc = SR_ERR_SYS; + char *nm; switch (event) { case SR_EV_ENABLED: /* first time, on register. */ @@ -402,27 +403,39 @@ static int change_hostname(sr_session_ctx_t *session, uint32_t sub_id, const cha nm = sr_get_str(session, xpath); if (!nm) { - ERROR("No valid hostname in current session"); - nm = "infix"; /* XXX: derive from global "options.h" */ + /* XXX: derive from global "options.h" or /usr/share/factory/ */ + nm = strdup("infix"); + if (!nm) + goto err; } - ERROR("Got hostname %s", nm); - aug_get(confd->aug, "etc/hostname/hostname", &tmp); + if (aug_get(confd->aug, "etc/hostname/hostname", &tmp) <= 0) + goto err; + current = strdup(tmp); - ERROR("Current hostname %s", current); + if (!current) + goto err; err = sethostname(nm, strlen(nm)); err = err ? : aug_set(confd->aug, "etc/hostname/hostname", nm); nhosts = aug_match(confd->aug, "etc/hosts/*/canonical", &hosts); for (i = 0; i < nhosts; i++) { - aug_get(confd->aug, hosts[i], &host); + if (aug_get(confd->aug, hosts[i], &host) <= 0) + continue; + if (!strcmp(host, current)) err = err ? : aug_set(confd->aug, hosts[i], nm); + free(hosts[i]); } - free(hosts); + + if (nhosts) + free(hosts); free(current); +err: + if (nm) + free(nm); if (err) { ERROR("Failed activating changes."); From 79eb5fd5f40a75987b22065b64d0aff697046e87 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sun, 2 Apr 2023 16:16:58 +0200 Subject: [PATCH 30/52] confd: startup-config hook with support for merging in at bootstrap This change adds a hook to the startup datastore, we use the ietf-system module because the module argument is mandatory. The hook runs when all changes have been saved to the internal store. Since sysrepo has many startup files in /etc/sysrepo, we saving a JSON copy of all these files in /cfg/startup-config.cfg, which is persistent. On system bootstrap this file is merged into the (empty) running datastore, which is what the sysrepo maintainers recommend to be independent of any yang model updates that might occur on image upgrades. Signed-off-by: Joachim Wiberg --- package/confd/sysrepo.conf | 4 +++- src/confd/src/core.c | 28 +++++++++++++++++++++++++--- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/package/confd/sysrepo.conf b/package/confd/sysrepo.conf index d5e00ded..a78d4e56 100644 --- a/package/confd/sysrepo.conf +++ b/package/confd/sysrepo.conf @@ -1,6 +1,8 @@ run if: [S] /lib/infix/clean-etc -- run if: [S] /lib/infix/prep-db -- -service if: name:sysrepo [12345789] sysrepo-plugind -n -- Configuration daemon + +service if: name:sysrepo [S12345789] sysrepo-plugind -p /run/sysrepo.pid -n -- Configuration daemon +run if: [S] log sysrepocfg -v4 -E/cfg/startup-config.cfg -f json -- service if: name:netopeer [12345789] netopeer2-server -n -- NETCONF daemon task if: [12345789] resolvconf -u -- Update DNS configuration diff --git a/src/confd/src/core.c b/src/confd/src/core.c index 1727cace..1d5faa58 100644 --- a/src/confd/src/core.c +++ b/src/confd/src/core.c @@ -4,12 +4,24 @@ static struct confd confd; +static int startup_save_hook(sr_session_ctx_t *session, uint32_t sub_id, const char *module, + const char *xpath, sr_event_t event, unsigned request_id, void *priv) +{ + if (run("sysrepocfg -X/cfg/startup-config.cfg -d startup -f json")) + return SR_ERR_SYS; + + return SR_ERR_OK; +} + int sr_plugin_init_cb(sr_session_ctx_t *session, void **priv) { + sr_session_ctx_t *startup; int rc = SR_ERR_SYS; openlog("confd", LOG_USER, 0); + /* Save context with default running config datastore for all our models */ + *priv = (void *)&confd; confd.session = session; confd.conn = sr_session_get_connection(session); confd.sub = NULL; @@ -21,11 +33,21 @@ int sr_plugin_init_cb(sr_session_ctx_t *session, void **priv) if (!confd.aug) goto err; - *priv = (void *)&confd; - - if (ietf_system_init(&confd)) + if (rc = ietf_system_init(&confd)) goto err; + /* YOUR_INIT GOES HERE */ + + /* Set up hook to save startup-config to persisten backend store */ + if (rc = sr_session_start(confd.conn, SR_DS_STARTUP, &startup)) + goto err; + + if (rc = sr_module_change_subscribe(startup, "ietf-system", "/ietf-system:system//.", + startup_save_hook, NULL, 0, SR_SUBSCR_PASSIVE | SR_SUBSCR_DONE_ONLY, &confd.sub)) { + ERROR("failed setting up startup-config hook: %s", sr_strerror(rc)); + goto err; + } + return SR_ERR_OK; err: ERROR("init failed: %s", sr_strerror(rc)); From f9a7c256ca6a959fb77190f821df17c7f2d2c1d5 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Mon, 3 Apr 2023 06:00:16 +0200 Subject: [PATCH 31/52] package/libite: backport rsync + copyfile fixes from upcoming v2.5.3 Signed-off-by: Joachim Wiberg --- ...urn-value-when-copying-a-single-file.patch | 30 ++++++++ ...for-missing-dst-when-dst-is-a-direct.patch | 29 ++++++++ ...opying-empty-files-to-non-existing-d.patch | 68 +++++++++++++++++++ 3 files changed, 127 insertions(+) create mode 100644 patches/libite/2.5.2/0001-rsync-fix-return-value-when-copying-a-single-file.patch create mode 100644 patches/libite/2.5.2/0002-rsync-fix-check-for-missing-dst-when-dst-is-a-direct.patch create mode 100644 patches/libite/2.5.2/0003-copyfile-allow-copying-empty-files-to-non-existing-d.patch diff --git a/patches/libite/2.5.2/0001-rsync-fix-return-value-when-copying-a-single-file.patch b/patches/libite/2.5.2/0001-rsync-fix-return-value-when-copying-a-single-file.patch new file mode 100644 index 00000000..7e06dcd6 --- /dev/null +++ b/patches/libite/2.5.2/0001-rsync-fix-return-value-when-copying-a-single-file.patch @@ -0,0 +1,30 @@ +From 90fdcdeb39e35193fe4e8f5d5277cf9ca28d5055 Mon Sep 17 00:00:00 2001 +From: Joachim Wiberg +Date: Sun, 2 Apr 2023 22:16:50 +0200 +Subject: [PATCH 1/4] rsync: fix return value when copying a single file +Organization: Addiva Elektronik + +Signed-off-by: Joachim Wiberg +--- + src/rsync.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/rsync.c b/src/rsync.c +index 392e1d2..92b8d63 100644 +--- a/src/rsync.c ++++ b/src/rsync.c +@@ -85,9 +85,9 @@ int rsync(char *src, char *dst, int opt, int (*filter)(const char *file)) + return 1; + + if (copy(src, dst, keep_mtim)) +- result++; ++ return 1; + +- return errno; ++ return 0; + } + + /* Copy dir as well? */ +-- +2.34.1 + diff --git a/patches/libite/2.5.2/0002-rsync-fix-check-for-missing-dst-when-dst-is-a-direct.patch b/patches/libite/2.5.2/0002-rsync-fix-check-for-missing-dst-when-dst-is-a-direct.patch new file mode 100644 index 00000000..e9916cf7 --- /dev/null +++ b/patches/libite/2.5.2/0002-rsync-fix-check-for-missing-dst-when-dst-is-a-direct.patch @@ -0,0 +1,29 @@ +From d61b847e557e5162163dffd1abd4b5d9bedc6d7a Mon Sep 17 00:00:00 2001 +From: Joachim Wiberg +Date: Sun, 2 Apr 2023 22:17:09 +0200 +Subject: [PATCH 2/4] rsync: fix check for missing dst when dst is a directory +Organization: Addiva Elektronik + +Signed-off-by: Joachim Wiberg +--- + src/rsync.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/rsync.c b/src/rsync.c +index 92b8d63..695fac3 100644 +--- a/src/rsync.c ++++ b/src/rsync.c +@@ -77,7 +77,9 @@ int rsync(char *src, char *dst, int opt, int (*filter)(const char *file)) + char **files; /* Array of file names. */ + struct stat st; + +- if (!fisdir(dst)) ++ errno = 0; ++ ++ if (stat(dst, &st) && fisslashdir(dst)) + makedir(dst, 0755); + + if (!fisdir(src)) { +-- +2.34.1 + diff --git a/patches/libite/2.5.2/0003-copyfile-allow-copying-empty-files-to-non-existing-d.patch b/patches/libite/2.5.2/0003-copyfile-allow-copying-empty-files-to-non-existing-d.patch new file mode 100644 index 00000000..b7491c0a --- /dev/null +++ b/patches/libite/2.5.2/0003-copyfile-allow-copying-empty-files-to-non-existing-d.patch @@ -0,0 +1,68 @@ +From 4e9b5c13c16f7e7261a15143d9418385274a008e Mon Sep 17 00:00:00 2001 +From: Joachim Wiberg +Date: Sun, 2 Apr 2023 22:17:47 +0200 +Subject: [PATCH 3/4] copyfile: allow copying empty files to non-existing + destination dirs +Organization: Addiva Elektronik + +Signed-off-by: Joachim Wiberg +--- + src/copyfile.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/src/copyfile.c b/src/copyfile.c +index afbbda9..af34012 100644 +--- a/src/copyfile.c ++++ b/src/copyfile.c +@@ -38,6 +38,7 @@ static int adjust_target(const char *src, char **dst) + { + int isdir = 0; + ++ retry: + if (fisdir(*dst)) { + int slash = 0; + char *tmp, *ptr = strrchr(src, '/'); +@@ -58,6 +59,13 @@ static int adjust_target(const char *src, char **dst) + + sprintf(tmp, "%s%s%s", *dst, slash ? "" : "/", ptr); + *dst = tmp; ++ } else { ++ struct stat st; ++ ++ if (stat(*dst, &st) && fisslashdir(*dst)) { ++ makedir(*dst, 0755); ++ goto retry; ++ } + } + + return isdir; +@@ -67,7 +75,7 @@ static int adjust_target(const char *src, char **dst) + * breaks loop on error and EOF */ + static ssize_t do_copy(int in, int out, size_t num, char *buffer, size_t len) + { +- ssize_t ret = 0, size = 0; ++ ssize_t ret = 0, size = -1; + + do { + size_t count = num > len ? len : num; +@@ -76,6 +84,8 @@ static ssize_t do_copy(int in, int out, size_t num, char *buffer, size_t len) + if (ret <= 0) { + if (ret == -1 && EINTR == errno) + continue; ++ if (ret == 0 && size == -1) ++ size = 0; + break; + } + +@@ -194,7 +204,7 @@ ssize_t copyfile(const char *src, const char *dst, int len, int opt) + } + + size = do_copy(in, out, num, buffer, BUFSIZ); +- if (!size && errno) ++ if (size < 0) + saved_errno = errno; + else if (keep_mtim) + set_mtime(in, out); +-- +2.34.1 + From 36ff60f99c9d23912687ad292673c1f7e66c85f2 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Mon, 3 Apr 2023 06:00:54 +0200 Subject: [PATCH 32/52] package/confd: support for customer factory startup-config.cfg When researching the systemd tmpfiles.d implementation I discovered the effort to standarize on /usr/share/factory as a generic factory defaults for Linux systems. This patch adds a small example factory.cfg file that is installed as /usr/share/factory/cfg/startup-config.cfg. The tmpfiles.d backend will then install it as /cfg/startup-config.cfg if that file is missing at boot. Confd does the rest to bootstrap our (by default) empty sysrepo db with this startup-config. Signed-off-by: Joachim Wiberg --- package/confd/confd.mk | 2 ++ package/confd/factory.cfg | 5 +++++ package/confd/tmpfiles.conf | 1 + 3 files changed, 8 insertions(+) create mode 100644 package/confd/factory.cfg diff --git a/package/confd/confd.mk b/package/confd/confd.mk index d47a7ee6..f707dfae 100644 --- a/package/confd/confd.mk +++ b/package/confd/confd.mk @@ -15,6 +15,8 @@ define CONFD_INSTALL_EXTRA cp $(CONFD_PKGDIR)/sysrepo.conf $(FINIT_D)/available/ ln -sf ../available/sysrepo.conf $(FINIT_D)/enabled/sysrepo.conf cp $(CONFD_PKGDIR)/tmpfiles.conf $(TARGET_DIR)/etc/tmpfiles.d/confd.conf + mkdir -p $(TARGET_DIR)/usr/share/factory/cfg + cp $(CONFD_PKGDIR)/factory.cfg $(TARGET_DIR)/usr/share/factory/cfg/startup-config.cfg mkdir -p $(TARGET_DIR)/lib/infix cp $(CONFD_PKGDIR)/prep-db $(TARGET_DIR)/lib/infix/ cp $(CONFD_PKGDIR)/clean-etc $(TARGET_DIR)/lib/infix/ diff --git a/package/confd/factory.cfg b/package/confd/factory.cfg new file mode 100644 index 00000000..8711e168 --- /dev/null +++ b/package/confd/factory.cfg @@ -0,0 +1,5 @@ +{ + "ietf-system:system": { + "hostname": "default" + } +} diff --git a/package/confd/tmpfiles.conf b/package/confd/tmpfiles.conf index 504121c4..58cf1038 100644 --- a/package/confd/tmpfiles.conf +++ b/package/confd/tmpfiles.conf @@ -1 +1,2 @@ d /run/resolvconf/interfaces - - - +C /cfg/startup-config.cfg - - - From 4e3f3a01b3133cb61e012f4b58f1afaf2acb9db1 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Mon, 3 Apr 2023 06:31:47 +0200 Subject: [PATCH 33/52] board/common: change cli alias to start klish Signed-off-by: Joachim Wiberg --- board/common/rootfs/etc/profile.d/convenience.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/board/common/rootfs/etc/profile.d/convenience.sh b/board/common/rootfs/etc/profile.d/convenience.sh index 5393b2e5..e27fc5c5 100644 --- a/board/common/rootfs/etc/profile.d/convenience.sh +++ b/board/common/rootfs/etc/profile.d/convenience.sh @@ -16,4 +16,4 @@ alias ipaddr='ip addr' alias iplink='ip link' alias bridge='bridge --color=auto' alias setup='pdmenu; clear' -alias cli='clixon_cli' +alias cli='klish' From 32e55d3562f75e6cac1868c550d29e9980c8112b Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Mon, 3 Apr 2023 06:32:17 +0200 Subject: [PATCH 34/52] configs: update defconfigs post e729c82 Signed-off-by: Joachim Wiberg --- configs/aarch64_defconfig | 2 -- configs/amd64_defconfig | 2 -- 2 files changed, 4 deletions(-) diff --git a/configs/aarch64_defconfig b/configs/aarch64_defconfig index 77c20eae..0ded6949 100644 --- a/configs/aarch64_defconfig +++ b/configs/aarch64_defconfig @@ -127,8 +127,6 @@ BR2_PACKAGE_FINIT_PLUGIN_TTY=y BR2_PACKAGE_FINIT_PLUGIN_URANDOM=y BR2_PACKAGE_IFUPDOWN_NG=y BR2_PACKAGE_KLINFIX=y -BR2_PACKAGE_KLISH=y -BR2_PACKAGE_KLISH_PLUGIN_SYSREPO=y BR2_PACKAGE_P_NET=y BR2_PACKAGE_P_NET_MAX_SUBSLOTS=12 BR2_PACKAGE_P_NET_MAX_PHYSICAL_PORTS=10 diff --git a/configs/amd64_defconfig b/configs/amd64_defconfig index ed4161f8..80cf0a7d 100644 --- a/configs/amd64_defconfig +++ b/configs/amd64_defconfig @@ -130,8 +130,6 @@ BR2_PACKAGE_FINIT_PLUGIN_TTY=y BR2_PACKAGE_FINIT_PLUGIN_URANDOM=y BR2_PACKAGE_IFUPDOWN_NG=y BR2_PACKAGE_KLINFIX=y -BR2_PACKAGE_KLISH=y -BR2_PACKAGE_KLISH_PLUGIN_SYSREPO=y BR2_PACKAGE_P_NET=y BR2_PACKAGE_P_NET_MAX_SUBSLOTS=12 BR2_PACKAGE_P_NET_MAX_PHYSICAL_PORTS=10 From a2d2d0948ffeb6b7920ee69d4a66f57469b93831 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Mon, 3 Apr 2023 14:08:30 +0200 Subject: [PATCH 35/52] src/confd: minor refactor Reuse code from mech, verified and working. Signed-off-by: Joachim Wiberg --- src/confd/src/ietf-system.c | 55 ++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 31 deletions(-) diff --git a/src/confd/src/ietf-system.c b/src/confd/src/ietf-system.c index f208a6b9..f9c7e8d1 100644 --- a/src/confd/src/ietf-system.c +++ b/src/confd/src/ietf-system.c @@ -8,34 +8,24 @@ #define PLATFORM_PATH_ "/ietf-system:system-state/platform" -/* Return seconds since boot */ -static long get_uptime(void) + +static char *fmtime(time_t t, char *buf, size_t len) { - struct sysinfo info; + const char *isofmt = "%FT%T%z"; + struct tm tm; + size_t i, n; - /* - * !!!Linux specific!!! Use '/var/run/utmp' BOOT record - * to be portable. But utmp file can be missing in some - * Unixes. - */ - sysinfo(&info); - return info.uptime; -} + localtime_r(&t, &tm); + n = strftime(buf, len, isofmt, &tm); + i = n - 5; + if (buf[i] == '+' || buf[i] == '-') { + buf[i + 6] = buf[i + 5]; + buf[i + 5] = buf[i + 4]; + buf[i + 4] = buf[i + 3]; + buf[i + 3] = ':'; + } -static int get_time_as_str(time_t *time, char *buf, int bufsz) -{ - int n; - - n = strftime(buf, bufsz, "%Y-%m-%dT%H:%M:%S%z", - localtime(time)); - if (!n) - return -1; - - /* Buf ends with +hhmm but should be +hh:mm, fix this */ - memmove(buf + n - 1, buf + n - 2, 3); - buf[n - 2] = ':'; - - return 0; + return buf; } static int clock_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *module, @@ -45,8 +35,8 @@ static int clock_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *modu static char boottime[64] = { 0 }; const struct ly_ctx *ctx; char curtime[64]; + time_t now, boot; char *buf; - time_t t; int rc; DEBUG("path=%s, request_path=%s", path, request_path); @@ -62,17 +52,20 @@ static int clock_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *modu lyd_print_mem(&buf, *parent, LYD_XML, 0); DEBUG("%s", buf); - if (!*boottime) { - t = time(NULL) - get_uptime(); - get_time_as_str(&t, boottime, sizeof(boottime)); + now = time(NULL); + if (!boottime[0]) { + struct sysinfo si; + + sysinfo(&si); + boot = now - si.uptime; + fmtime(boot, boottime, sizeof(boottime)); } rc = lyd_new_path(*parent, NULL, CLOCK_PATH_ "/boot-datetime", boottime, 0, NULL); if (rc) goto fail; - t = time(NULL); - get_time_as_str(&t, curtime, sizeof(curtime)); + fmtime(now, curtime, sizeof(curtime)); rc = lyd_new_path(*parent, NULL, CLOCK_PATH_ "/current-datetime", curtime, 0, NULL); if (rc) goto fail; From 4e0d7ad4942cd18577b6874cc85e83bcb1b0704a Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Mon, 3 Apr 2023 14:14:05 +0200 Subject: [PATCH 36/52] src/confd: use /etc/os-release for platform operational data Signed-off-by: Joachim Wiberg --- src/confd/src/ietf-system.c | 75 +++++++++++++++++++++++++++++++++---- 1 file changed, 68 insertions(+), 7 deletions(-) diff --git a/src/confd/src/ietf-system.c b/src/confd/src/ietf-system.c index f9c7e8d1..95bec9d7 100644 --- a/src/confd/src/ietf-system.c +++ b/src/confd/src/ietf-system.c @@ -7,7 +7,69 @@ #define CLOCK_PATH_ "/ietf-system:system-state/clock" #define PLATFORM_PATH_ "/ietf-system:system-state/platform" +static char *ver = NULL; +static char *rel = NULL; +static char *sys = NULL; +static char *os = NULL; +static char *strip_quotes(char *str) +{ + char *ptr; + + while (*str && (isspace(*str) || *str == '"')) + str++; + + for (ptr = str + strlen(str); ptr > str; ptr--) { + if (*ptr != '"') + continue; + + *ptr = 0; + break; + } + + return str; +} + +static void setvar(char *line, const char *nm, char **var) +{ + char *ptr; + + if (!strncmp(line, nm, strlen(nm)) && (ptr = strchr(line, '='))) { + if (*var) + free(*var); + *var = strdup(strip_quotes(++ptr)); + } +} + +static void os_init(void) +{ + struct utsname uts; + char line[80]; + FILE *fp; + + if (!uname(&uts)) { + os = strdup(uts.sysname); + ver = strdup(uts.release); + rel = strdup(uts.release); + sys = strdup(uts.machine); + } + + fp = fopen("/etc/os-release", "r"); + if (!fp) { + fp = fopen("/usr/lib/os-release", "r"); + if (!fp) + return; + } + + while (fgets(line, sizeof(line), fp)) { + line[strlen(line) - 1] = 0; /* drop \n */ + setvar(line, "NAME", &os); + setvar(line, "VERSION_ID", &ver); + setvar(line, "BUILD_ID", &rel); + setvar(line, "ARCHITECTURE", &sys); + } + fclose(fp); +} static char *fmtime(time_t t, char *buf, size_t len) { @@ -88,9 +150,6 @@ static int platform_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *m DEBUG("path=%s request_path=%s", path, request_path); ctx = sr_acquire_context(sr_session_get_connection(session)); - /* POSIX func */ - uname(&data); - rc = lyd_new_path(NULL, ctx, PLATFORM_PATH_, NULL, 0, parent); if (rc) { fail: @@ -101,16 +160,16 @@ static int platform_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *m lyd_print_mem(&buf, *parent, LYD_XML, 0); DEBUG("%s", buf); - rc = lyd_new_path(*parent, NULL, PLATFORM_PATH_"/os-name", data.sysname, 0, NULL); + rc = lyd_new_path(*parent, NULL, PLATFORM_PATH_"/os-name", os, 0, NULL); if (rc) goto fail; - rc = lyd_new_path(*parent, NULL, PLATFORM_PATH_"/os-release", data.release, 0, NULL); + rc = lyd_new_path(*parent, NULL, PLATFORM_PATH_"/os-release", rel, 0, NULL); if (rc) goto fail; - rc = lyd_new_path(*parent, NULL, PLATFORM_PATH_"/os-version", data.version, 0, NULL); + rc = lyd_new_path(*parent, NULL, PLATFORM_PATH_"/os-version", ver, 0, NULL); if (rc) goto fail; - rc = lyd_new_path(*parent, NULL, PLATFORM_PATH_"/machine", data.machine, 0, NULL); + rc = lyd_new_path(*parent, NULL, PLATFORM_PATH_"/machine", sys, 0, NULL); if (rc) goto fail; @@ -453,6 +512,8 @@ int ietf_system_init(struct confd *confd) }; int rc; + os_init(); + if (aug_load_file(confd->aug, "/etc/hostname") || aug_load_file(confd->aug, "/etc/hosts")) { ERROR("ietf-system: Augeas initialization failed"); From 68a5a500400c0cefac928c5884f056ce27f193d1 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Mon, 3 Apr 2023 16:32:21 +0200 Subject: [PATCH 37/52] src/confd: add timezone support to set-current-datetime rpc How to verify, use the following command and paste the XML below: $ sysrepocfg -R 2022-01-12T14:29:00-02:00 Reuse code from mech, verified and working. Signed-off-by: Joachim Wiberg --- src/confd/src/Makefile.am | 2 +- src/confd/src/ietf-system.c | 65 ++++++++++++++++++++++--------------- 2 files changed, 39 insertions(+), 28 deletions(-) diff --git a/src/confd/src/Makefile.am b/src/confd/src/Makefile.am index af19cdcf..975bf7d5 100644 --- a/src/confd/src/Makefile.am +++ b/src/confd/src/Makefile.am @@ -1,4 +1,4 @@ -AM_CPPFLAGS = -DYANG_PATH_=\"$(YANGDIR)/\" +AM_CPPFLAGS = -D_DEFAULT_SOURCE -D_XOPEN_SOURCE -DYANG_PATH_=\"$(YANGDIR)/\" plugindir = $(srpdplugindir) plugin_LTLIBRARIES = confd-plugin.la diff --git a/src/confd/src/ietf-system.c b/src/confd/src/ietf-system.c index 95bec9d7..495665b5 100644 --- a/src/confd/src/ietf-system.c +++ b/src/confd/src/ietf-system.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause */ #include "core.h" +#include #include #include @@ -200,38 +201,48 @@ static int rpc_set_datetime(sr_session_ctx_t *session, uint32_t sub_id, unsigned request_id, sr_val_t **output, size_t *output_cnt, void *priv) { - struct timeval tv; - struct tm tm; - time_t t; + const char *isofmt = "%FT%T%z"; + static int rc = SR_ERR_SYS; + struct timeval tv; + struct tm tm; + char tz[24]; + char *buf; + size_t n; - memset(&tm, 0, sizeof(tm)); + buf = strdup(input->data.string_val); + if (!buf) + return SR_ERR_NO_MEMORY; - /* Parse 'current-datetime'. */ - sscanf(input->data.string_val, "%d-%d-%dT%d:%d:%d", &tm.tm_year, - &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, - &tm.tm_sec); + n = strlen(buf); + if (buf[n - 3] == ':' && (buf[n - 6] == '+' || buf[n - 6] == '-')) { + buf[n - 3] = buf[n - 2]; + buf[n - 2] = buf[n - 1]; + buf[n - 1] = 0; + } else + isofmt = "%FT%TZ"; - DEBUG("Setting datetime to '%d-%02d-%02d %02d:%02d:%02d'", - tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, - tm.tm_sec); - - tm.tm_year -= 1900; - tm.tm_mon--; - - /* - * We suppose that this is a local time and ignore timezone. - */ - - t = mktime(&tm); - - tv.tv_sec = t; - tv.tv_usec = 0; - if (settimeofday(&tv, NULL)) { - ERRNO("settimeofday() failed"); - return SR_ERR_SYS; + memset(&tm, 0, sizeof(tm)); + if (!strptime(buf, isofmt, &tm)) { + ERRNO("ietf-system:failed strptime: %s", strerror(errno)); + goto done; } - return SR_ERR_OK; + snprintf(tz, sizeof(tz), "UTC%s%ld", tm.tm_gmtoff > 0 ? "+" : "", tm.tm_gmtoff / 3600); + setenv("TZ", tz, 1); + + tv.tv_sec = mktime(&tm); + tv.tv_usec = 0; + if (settimeofday(&tv, NULL)) { + ERRNO("ietf-system:settimeofday() failed"); + goto done; + } + + rc = SR_ERR_OK; +done: + unsetenv("TZ"); + free(buf); + + return rc; } static int sys_reload_services(void) From 443cb2ddf1490941ab5f5b65f0767c4c19a7259d Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Mon, 3 Apr 2023 18:17:59 +0200 Subject: [PATCH 38/52] src/confd: add support for /ietf-system:system/clock, with deviation Declare deviation for /ietf-system:system/clock/timezone-utc-offset, which we currently do not support. Please note, when setting out to add support for timezone-utc-offset, you need to ensure the user does not input both, that should be a validation error. It's an either-or thing. Signed-off-by: Joachim Wiberg --- src/confd/src/core.c | 3 + src/confd/src/ietf-system.c | 63 +++++++++++++++++++ .../yang/kernelkit-infix-deviations.yang | 19 ++++++ 3 files changed, 85 insertions(+) create mode 100644 src/confd/yang/kernelkit-infix-deviations.yang diff --git a/src/confd/src/core.c b/src/confd/src/core.c index 1d5faa58..48a7e30e 100644 --- a/src/confd/src/core.c +++ b/src/confd/src/core.c @@ -48,6 +48,9 @@ int sr_plugin_init_cb(sr_session_ctx_t *session, void **priv) goto err; } + if (rc = sr_install_module(confd.conn, YANG_PATH_"kernelkit-infix-deviations.yang", NULL, NULL)) + goto err; + return SR_ERR_OK; err: ERROR("init failed: %s", sr_strerror(rc)); diff --git a/src/confd/src/ietf-system.c b/src/confd/src/ietf-system.c index 495665b5..8fb05199 100644 --- a/src/confd/src/ietf-system.c +++ b/src/confd/src/ietf-system.c @@ -326,6 +326,68 @@ fail: return str; } +#define TIMEZONE_CONF "/etc/timezone" +#define TIMEZONE_PREV TIMEZONE_CONF "-" +#define TIMEZONE_NEXT TIMEZONE_CONF "+" + +static int change_clock(sr_session_ctx_t *session, uint32_t sub_id, const char *module, + const char *xpath, sr_event_t event, unsigned request_id, void *priv) +{ + struct confd *confd = (struct confd *)priv; + const char *fn = TIMEZONE_CONF; + char *timezone; + FILE *fp; + int rc; + + switch (event) { + case SR_EV_ENABLED: /* first time, on register. */ + case SR_EV_CHANGE: /* regular change (copy cand running) */ + /* Set up next timezone */ + break; + + case SR_EV_ABORT: /* User abort, or other plugin failed */ + remove(TIMEZONE_NEXT); + return SR_ERR_OK; + + case SR_EV_DONE: + /* Check if passed validation in previous event */ + if (access(TIMEZONE_NEXT, F_OK)) + return SR_ERR_OK; + + remove(TIMEZONE_PREV); + rename(TIMEZONE_CONF, TIMEZONE_PREV); + rename(TIMEZONE_NEXT, TIMEZONE_CONF); + + remove("/etc/localtime-"); + rename("/etc/localtime", "/etc/localtime-"); + rename("/etc/localtime+", "/etc/localtime"); + + return SR_ERR_OK; + } + + timezone = sr_get_str(session, "/ietf-system:system/clock/timezone-name"); + if (!timezone) { + ERROR("Failed reading timezone-name"); + return SR_ERR_VALIDATION_FAILED; + } + + remove("/etc/localtime+"); + if (run("ln -s /usr/share/zoneinfo/%s /etc/localtime+", timezone)) { + ERROR("No such timezone %s", timezone); + return SR_ERR_VALIDATION_FAILED; + } + + fp = fopen(TIMEZONE_NEXT, "w"); + if (!fp) { + ERRNO("Failed preparing %s", TIMEZONE_NEXT); + return SR_ERR_SYS; + } + fprintf(fp, "%s\n", timezone); + fclose(fp); + + return SR_ERR_OK; +} + #define CHRONY_CONF "/etc/chrony.conf" #define CHRONY_PREV CHRONY_CONF "-" #define CHRONY_NEXT CHRONY_CONF "+" @@ -545,6 +607,7 @@ int ietf_system_init(struct confd *confd) goto err; REGISTER_CHANGE(confd->session, "ietf-system", "/ietf-system:system/hostname", 0, change_hostname, confd, &confd->sub); + REGISTER_CHANGE(confd->session, "ietf-system", "/ietf-system:system/clock", 0, change_clock, confd, &confd->sub); REGISTER_CHANGE(confd->session, "ietf-system", "/ietf-system:system/ntp", 0, change_ntp, confd, &confd->sub); REGISTER_RPC(confd->session, "/ietf-system:system-restart", rpc_exec, "reboot", &confd->sub); diff --git a/src/confd/yang/kernelkit-infix-deviations.yang b/src/confd/yang/kernelkit-infix-deviations.yang new file mode 100644 index 00000000..0513d1d7 --- /dev/null +++ b/src/confd/yang/kernelkit-infix-deviations.yang @@ -0,0 +1,19 @@ +module kernelkit-infix-deviations { + yang-version 1.1; + namespace "urn:kernelkit:params:xml:ns:yang:infix"; + prefix "kkit"; + import ietf-system { + prefix sys; + } + organization "KernelKit"; + contact "kernelkit@googlegroups.com"; + description "Infix deviations in standard yang models."; + + revision "2023-04-03" { + description "Initial revision."; + } + + deviation /sys:system/sys:clock/sys:timezone/sys:timezone-utc-offset/sys:timezone-utc-offset { + deviate not-supported; + } +} From 42281378f8b86fd26492e9473be9dc08d13f2fda Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Mon, 3 Apr 2023 19:29:55 +0200 Subject: [PATCH 39/52] src/confd: new function, sr_get_int() Really ugly handling here, needs to be reworked into sr_uint8() etc., adding as-is for big upcoming demo. Signed-off-by: Joachim Wiberg --- src/confd/src/ietf-system.c | 58 +++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/src/confd/src/ietf-system.c b/src/confd/src/ietf-system.c index 8fb05199..7b94621e 100644 --- a/src/confd/src/ietf-system.c +++ b/src/confd/src/ietf-system.c @@ -260,6 +260,64 @@ static void print_val(sr_val_t *val) free(str); } +int sr_get_int(sr_session_ctx_t *session, const char *fmt, ...) +{ + sr_val_t *val = NULL; + char *xpath; + va_list ap; + int rc = 0; + int len; + + va_start(ap, fmt); + len = vsnprintf(NULL, 0, fmt, ap) + 1; + va_end(ap); + + xpath = alloca(len); + if (!xpath) + goto fail; + + va_start(ap, fmt); + vsnprintf(xpath, len, fmt, ap); + va_end(ap); + + if (sr_get_item(session, xpath, 0, &val) || !val) + goto fail; + + switch (val->type) { + case SR_INT8_T: + rc = val->data.int8_val; + break; + case SR_UINT8_T: + rc = val->data.uint8_val; + break; + case SR_INT16_T: + rc = val->data.int16_val; + break; + case SR_UINT16_T: + rc = val->data.uint16_val; + break; + case SR_INT32_T: + rc = val->data.int32_val; + break; + case SR_UINT32_T: + rc = val->data.uint32_val; + break; + case SR_INT64_T: + rc = val->data.int64_val; + break; + case SR_UINT64_T: + rc = val->data.uint64_val; + break; + default: + goto fail; + } + +fail: + if (val) + sr_free_val(val); + return rc; +} + int sr_get_bool(sr_session_ctx_t *session, const char *fmt, ...) { sr_val_t *val = NULL; From 69920cb2308e8dcce025402dbef4b5ffa6de39ee Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Mon, 3 Apr 2023 19:31:34 +0200 Subject: [PATCH 40/52] src/confd: add support for /ietf-system:system/dns-resolver Signed-off-by: Joachim Wiberg --- src/confd/src/ietf-system.c | 98 +++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/src/confd/src/ietf-system.c b/src/confd/src/ietf-system.c index 7b94621e..6645c7b2 100644 --- a/src/confd/src/ietf-system.c +++ b/src/confd/src/ietf-system.c @@ -560,6 +560,103 @@ static int change_ntp(sr_session_ctx_t *session, uint32_t sub_id, const char *mo return SR_ERR_OK; } +#define RESOLV_CONF "/etc/resolv.conf.head" +#define RESOLV_PREV RESOLV_CONF "-" +#define RESOLV_NEXT RESOLV_CONF "+" + +static int change_dns(sr_session_ctx_t *session, uint32_t sub_id, const char *module, + const char *xpath, sr_event_t event, unsigned request_id, void *priv) +{ + struct confd *confd = (struct confd *)priv; + const char *fn = RESOLV_NEXT; + int timeout, attempts; + int rc = SR_ERR_SYS; + int valid = -1; + sr_data_t *sdt; + sr_val_t *val; + size_t cnt; + FILE *fp; + + switch (event) { + case SR_EV_ENABLED: /* first time, on register. */ + case SR_EV_CHANGE: /* regular change (copy cand running) */ + /* Generate next config */ + break; + + case SR_EV_ABORT: /* User abort, or other plugin failed */ + remove(RESOLV_NEXT); + return SR_ERR_OK; + + case SR_EV_DONE: + /* Check if passed validation in previous event */ + if (access(RESOLV_NEXT, F_OK)) + return SR_ERR_OK; + + remove(RESOLV_PREV); + rename(RESOLV_CONF, RESOLV_PREV); + rename(RESOLV_NEXT, RESOLV_CONF); + + /* in bootstrap, another resolvconf will soon take your call */ + if (run("initctl cond get hook/sys/up")) + return 0; + + run("resolvconf -u"); + return SR_ERR_OK; + } + + fp = fopen(fn, "w"); + if (!fp) { + ERROR("failed updating %s: %s", fn, strerror(errno)); + sr_free_values(val, cnt); + return SR_ERR_SYS; + } + + timeout = sr_get_int(session, "/ietf-system:system/dns-resolver/options/timeout"); + attempts = sr_get_int(session, "/ietf-system:system/dns-resolver/options/attempts"); + if (timeout || attempts) { + fprintf(fp, "options"); + if (timeout) + fprintf(fp, " timeout:%d", timeout); + if (attempts) + fprintf(fp, " attempts:%d ", attempts); + fprintf(fp, "\n"); + } + + if (rc = sr_get_items(session, "/ietf-system:system/dns-resolver/search", 0, 0, &val, &cnt)) + goto fail; + + if (cnt) { + fprintf(fp, "search "); + for (size_t i = 0; i < cnt; i++) + fprintf(fp, "%s ", val[i].data.string_val); + fprintf(fp, "\n"); + } + sr_free_values(val, cnt); + + if (rc = sr_get_items(session, "/ietf-system:system/dns-resolver/server", 0, 0, &val, &cnt)) + goto fail; + + for (size_t i = 0; i < cnt; i++) { + const char *xpath = val[i].xpath; + char *type, *ptr; + int server = 0; + + /* Get /ietf-system:system/dns-resolver/server[name='foo'] */ + ptr = sr_get_str(session, "%s/udp-and-tcp/address", xpath); + if (ptr) + fprintf(fp, "nameserver %s\n", ptr); + } + sr_free_values(val, cnt); + + rc = SR_ERR_OK; +fail: + fclose(fp); + if (rc) + remove(fn); + + return rc; +} + static int change_hostname(sr_session_ctx_t *session, uint32_t sub_id, const char *module, const char *xpath, sr_event_t event, unsigned request_id, void *priv) { @@ -667,6 +764,7 @@ int ietf_system_init(struct confd *confd) REGISTER_CHANGE(confd->session, "ietf-system", "/ietf-system:system/hostname", 0, change_hostname, confd, &confd->sub); REGISTER_CHANGE(confd->session, "ietf-system", "/ietf-system:system/clock", 0, change_clock, confd, &confd->sub); REGISTER_CHANGE(confd->session, "ietf-system", "/ietf-system:system/ntp", 0, change_ntp, confd, &confd->sub); + REGISTER_CHANGE(confd->session, "ietf-system", "/ietf-system:system/dns-resolver", 0, change_dns, confd, &confd->sub); REGISTER_RPC(confd->session, "/ietf-system:system-restart", rpc_exec, "reboot", &confd->sub); REGISTER_RPC(confd->session, "/ietf-system:system-shutdown", rpc_exec, "poweroff", &confd->sub); From 59d5340eaea4cb7d52688aaf76e766fc9eb9eb6a Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Mon, 3 Apr 2023 19:33:37 +0200 Subject: [PATCH 41/52] src/confd: mark missing yang support with XXX Signed-off-by: Joachim Wiberg --- src/confd/src/ietf-system.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/confd/src/ietf-system.c b/src/confd/src/ietf-system.c index 6645c7b2..52060141 100644 --- a/src/confd/src/ietf-system.c +++ b/src/confd/src/ietf-system.c @@ -423,6 +423,7 @@ static int change_clock(sr_session_ctx_t *session, uint32_t sub_id, const char * return SR_ERR_OK; } + /* XXX: add support also for /ietf-system:system/clock/timezone-utc-offset (deviation) */ timezone = sr_get_str(session, "/ietf-system:system/clock/timezone-name"); if (!timezone) { ERROR("Failed reading timezone-name"); @@ -644,6 +645,7 @@ static int change_dns(sr_session_ctx_t *session, uint32_t sub_id, const char *mo /* Get /ietf-system:system/dns-resolver/server[name='foo'] */ ptr = sr_get_str(session, "%s/udp-and-tcp/address", xpath); if (ptr) + /* XXX: add support also for udp-and-tcp/port */ fprintf(fp, "nameserver %s\n", ptr); } sr_free_values(val, cnt); From 2ba8612f7fc91d2744703ecd4b515e5ca22e0d53 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Mon, 3 Apr 2023 20:35:55 +0200 Subject: [PATCH 42/52] src/confd: add commit_done_hook() to call initctl reload This is needed to confirm the new system configuration generation and reload all affected services. E.g., when configuring an NTP server and committing the candidate to running, the ietf-system plugin has only enabled the service, as a last step we need to tell Finit to actually start it. This hook needs to run last since the enabled service(s) may depend on other service(s), or networking, to be enabled in the proper order. Signed-off-by: Joachim Wiberg --- src/confd/src/core.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/confd/src/core.c b/src/confd/src/core.c index 48a7e30e..4337db88 100644 --- a/src/confd/src/core.c +++ b/src/confd/src/core.c @@ -13,6 +13,15 @@ static int startup_save_hook(sr_session_ctx_t *session, uint32_t sub_id, const c return SR_ERR_OK; } +static int commit_done_hook(sr_session_ctx_t *session, uint32_t sub_id, const char *module, + const char *xpath, sr_event_t event, unsigned request_id, void *priv) +{ + if (system("initctl -nbq reload")) + return SR_ERR_SYS; + + return SR_ERR_OK; +} + int sr_plugin_init_cb(sr_session_ctx_t *session, void **priv) { sr_session_ctx_t *startup; @@ -48,6 +57,12 @@ int sr_plugin_init_cb(sr_session_ctx_t *session, void **priv) goto err; } + if (rc = sr_module_change_subscribe(session, "ietf-system", "/ietf-system:system//.", + commit_done_hook, NULL, 0, SR_SUBSCR_PASSIVE | SR_SUBSCR_DONE_ONLY, &confd.sub)) { + ERROR("failed setting up startup-config hook: %s", sr_strerror(rc)); + goto err; + } + if (rc = sr_install_module(confd.conn, YANG_PATH_"kernelkit-infix-deviations.yang", NULL, NULL)) goto err; From 2943922b4c6e63c64a03a700df974fcf7bd71364 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Tue, 4 Apr 2023 15:11:55 +0200 Subject: [PATCH 43/52] configs: add dosfstools and mtools for disk image generation + gns3 Signed-off-by: Joachim Wiberg --- configs/amd64_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/amd64_defconfig b/configs/amd64_defconfig index 80cf0a7d..87f9dd51 100644 --- a/configs/amd64_defconfig +++ b/configs/amd64_defconfig @@ -110,10 +110,12 @@ BR2_TARGET_GRUB2_X86_64_EFI=y BR2_TARGET_GRUB2_BUILTIN_MODULES_EFI="boot linux ext2 fat squash4 part_gpt normal efi_gop configfile loadenv test terminfo terminal echo" BR2_TARGET_GRUB2_BUILTIN_CONFIG_EFI="${BR2_EXTERNAL_INFIX_PATH}/board/amd64/grub-embed.cfg" BR2_TARGET_GRUB2_INSTALL_TOOLS=y +BR2_PACKAGE_HOST_DOSFSTOOLS=y BR2_PACKAGE_HOST_E2FSPROGS=y BR2_PACKAGE_HOST_ENVIRONMENT_SETUP=y BR2_PACKAGE_HOST_GENEXT2FS=y BR2_PACKAGE_HOST_GENIMAGE=y +BR2_PACKAGE_HOST_MTOOLS=y BR2_PACKAGE_HOST_RAUC=y BR2_PACKAGE_HOST_UBOOT_TOOLS=y BR2_PACKAGE_HOST_UBOOT_TOOLS_FIT_SUPPORT=y From 8f1f74263d8526c363b8b91ca6134d0406a28de8 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Wed, 5 Apr 2023 16:08:07 +0200 Subject: [PATCH 44/52] src/net: first prototype Signed-off-by: Joachim Wiberg --- src/net/.gitignore | 2 + src/net/Makefile | 10 +++ src/net/README.md | 115 +++++++++++++++++++++++++++++++ src/net/gen.sh | 33 +++++++++ src/net/main.c | 167 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 327 insertions(+) create mode 100644 src/net/.gitignore create mode 100644 src/net/Makefile create mode 100644 src/net/README.md create mode 100755 src/net/gen.sh create mode 100644 src/net/main.c diff --git a/src/net/.gitignore b/src/net/.gitignore new file mode 100644 index 00000000..5166df2d --- /dev/null +++ b/src/net/.gitignore @@ -0,0 +1,2 @@ +*.o +net diff --git a/src/net/Makefile b/src/net/Makefile new file mode 100644 index 00000000..348f67ae --- /dev/null +++ b/src/net/Makefile @@ -0,0 +1,10 @@ +LDLIBS = -lite + +net: main.o + $(CC) -o $@ $^ $(LDLIBS) + +clean: + $(RM) net + +distclean: clean + $(RM) *.o *~ diff --git a/src/net/README.md b/src/net/README.md new file mode 100644 index 00000000..c86d6f12 --- /dev/null +++ b/src/net/README.md @@ -0,0 +1,115 @@ +net - an iproute2 wrapper +========================= + +The net tool is a wrapper around the iproute2 and ethtool programs to +set up networking on a Linux system. It also handles transitions from +a previously configured state to the next while attempting to keep the +amount of changes needed to a minimum. + + +Overview +-------- + +net applies a configuration from `/run/net/next`, where `next` is a file +that holds the number of the current generation. It is up to the user +to create the below structure with commands to run. Consider the case +when `next` contains `0`, net reads all interfaces, in dependency order, +from `/run/net/0/` and runs all the `ip-link` and `ip-addr` commands. +When it is done, it writes `0` to the file `/run/net/gen` and removes +the `next` file to confirm the next generation has been activated. + +Note: it is currently up to the user to remove any old generation. + + /run/net/0/ + |-- lo/ + | |-- deps/ + | |-- ip-link + | `-- ip-addr + |-- br0/ + | |-- deps/ + | | |-- eth1 -> ../../eth1 + | | |-- eth2 -> ../../eth2 + | | |-- eth3 -> ../../eth3 + | | `-- lag0 -> ../../lag0 + | |-- ip-link.up + | `-- ip-addr.up + |-- eth0/ + | |-- deps/ + | |-- ip-link.up + | `-- ip-addr.up + |-- lag0/ + | |-- deps/ + | | |-- eth4 -> ../../eth4 + | | `-- eth5 -> ../../eth5 + | |-- ip-link.up + | `-- ip-addr.up + `-- vlan1/ + |-- deps/ + | `-- br0 -> ../../br0 + |-- ip-link.up + `-- ip-addr.up + +The `deps/` sub-directory for each of the interfaces contains symlinks +to all interfaces that this interface depends on. I.e., when bringing +networking up or down these dependent interfaces are evaluated in order +creating a dependency tree: + + vlan1 + _____/____ + [___br0____] + / / \ \ + eth1 eth2 eth3 lag0 + / \ + eth4 eth5 + +Essentially, all leaves must be set up before their parents. + + +Concepts +-------- + +Conceptually, net is built to complement sysrepo. The idea is to listen +to added, deleted, modified states in sysrepo changes to a candidate +configuration and generate the `next` generation. + + + /run/net// + |-- lo/ + | |-- deps/ + | |-- ip-link.up + | `-- ip-addr.up + |-- br0/ + | |-- deps/ + | | |-- eth1 -> ../../eth1 + | | |-- eth2 -> ../../eth2 + | | |-- eth3 -> ../../eth3 + | | |-- eth4 -> ../../eth4 + | | `-- lag0 -> ../../lag0 + | `-- ip-link.up + |-- eth0/ + | |-- deps/ + | |-- ip-link.up + | `-- ip-addr.up + |-- eth4/ + | |-- deps/ + | |-- ip-link.dn + | `-- ip-link.up + |-- lag0/ + | |-- deps/ + | | `-- eth5 -> ../../eth5 + | `-- ip-link.up + `-- vlan1/ + |-- deps/ + | `-- br0 -> ../../br0 + |-- ip-link.up + `-- ip-addr.up + + +Interfaces can be evaluated in any order. The `deps/` directory of each +is interface is always evaluated first. For each dependency, `foo.dn` +is evaluated first and `foo.up` is evaluated last. Any `ip-link` script +is also evaluated before any `ip-addr` script. + +In the case above, interface `eth4` has been moved from `lag0` to `br0`, +so we need to run `eth4/ip-link.dn` to remove `eth4` from `lag0` before +its `ip-link.up` script sets `eth4` as a bridge member instead. diff --git a/src/net/gen.sh b/src/net/gen.sh new file mode 100755 index 00000000..eaacf6fe --- /dev/null +++ b/src/net/gen.sh @@ -0,0 +1,33 @@ +#!/bin/sh +# Generate test directory structure for verifying the net tool + +gensh() +{ + cat <<-EOF >"$1" + #!/bin/sh + echo "Running \$0 ..." + EOF + chmod +x "$1" +} + +mkdir -p /tmp/net/1 +echo 1 > /tmp/net/next + +mkdir -p /tmp/net/1/lo/deps +mkdir -p /tmp/net/1/eth0/deps +mkdir -p /tmp/net/1/eth1/deps +mkdir -p /tmp/net/1/eth2/deps + +mkdir -p /tmp/net/1/br0/deps +ln -sf ../../eth1 /tmp/net/1/br0/deps/ +ln -sf ../../eth2 /tmp/net/1/br0/deps/ + +mkdir -p /tmp/net/1/vlan1/deps +ln -sf ../../br0 /tmp/net/1/vlan1/deps/ + +gensh /tmp/net/1/lo/ip-link.up +gensh /tmp/net/1/eth0/ip-link.up +gensh /tmp/net/1/eth1/ip-link.up +gensh /tmp/net/1/eth2/ip-link.up +gensh /tmp/net/1/br0/ip-link.up +gensh /tmp/net/1/vlan1/ip-link.up diff --git a/src/net/main.c b/src/net/main.c new file mode 100644 index 00000000..0eae4307 --- /dev/null +++ b/src/net/main.c @@ -0,0 +1,167 @@ +#include +#include +#include +#include +#include + +#define _PATH_NET "/run/net" +#define DEBUG 1 +#define dbg(fmt, args...) if (DEBUG) warnx(fmt, ##args) + +static char **handled; +static int if_num; + + +static void if_alloc(int num) +{ + handled = calloc(num, sizeof(char *)); + if (!handled) + err(1, "calloc"); + if_num = num; +} + +static void if_free() +{ + for (int i = 0; i < if_num; i++) { + if (handled[i]) + free(handled[i]); + } + free(handled); +} + +static void if_done(char *ifname) +{ + for (int i = 0; i < if_num; i++) { + if (handled[i]) { + if (strcmp(handled[i], ifname)) + continue; + return; + } + handled[i] = strdup(ifname); + break; + } +} + +static int if_find(char *ifname) +{ + for (int i = 0; i < if_num; i++) { + if (handled[i] && !strcmp(handled[i], ifname)) + return 1; + } + return 0; +} + +static int deps(char *ipath, char *ifname, char *action) +{ + char path[strlen(ipath) + 42]; + int num, rc = -1; + char **files; + char *cmd; + + snprintf(path, sizeof(path), "%s/deps", ipath); + num = dir(path, NULL, NULL, &files, 0); + for (int i = 0; i < num; i++) { + char dpath[sizeof(path) + strlen(files[i])]; + char *ifnm = files[i]; + char *rp; + + snprintf(dpath, sizeof(dpath), "%s/%s", path, ifnm); + rp = realpath(dpath, NULL); + if (!rp) + continue; + + deps(rp, ifnm, action); + free(ifnm); + free(rp); + } + + if (if_find(ifname)) + return 0; + + snprintf(path, sizeof(path), "%s/%s", ipath, action); + cmd = realpath(path, NULL); + if (!cmd || access(cmd, X_OK)) { + if (errno == ENOENT) + rc = 0; /* no action for this interface */ + goto done; + } + + rc = systemf("%s", cmd); +done: + free(cmd); + if_done(ifname); + + return rc; +} + +static int activate(const char *net, char *gen) +{ + char path[strlen(net) + strlen(gen) + 5 + IFNAMSIZ]; + char *action[] = { + "ip-addr.dn", + "ip-link.dn", + "ip-link.up", + "ip-addr.up", + }; + char **files; + int rc = 0; + + snprintf(path, sizeof(path), "%s/%s", net, gen); + + for (size_t i = 0; i < NELEMS(action); i++) { + char *act = action[i]; + int num; + + num = dir(path, NULL, NULL, &files, 0); + if_alloc(num); + + for (int j = 0; j < num; j++) { + char ipath[sizeof(path)]; + char *ifname = files[j]; + + snprintf(ipath, sizeof(ipath), "%s/%s", path, ifname); + rc += deps(ipath, ifname, act); + free(ifname); + } + + if_free(); + } + + return rc; +} + +int main(void) +{ + const char *net = _PATH_NET; + char next[512]; + FILE *fp; + int rc; + + if (getenv("NET_DIR")) + net = getenv("NET_DIR"); + if (access(net, X_OK)) { + if (makedir(net, 0755)) + err(1, "makedir"); + } + + fp = fopenf("r", "%s/next", net); + if (!fp) + exit(0); /* nothing to do */ + + if (!fgets(next, sizeof(next), fp)) + err(1, "missing next generation"); + fclose(fp); + + rc = activate(net, chomp(next)); + if (rc) + err(1, "failed activating next generation"); + + fp = fopenf("w", "%s/gen", net); + if (!fp) + err(1, "next generation applied, failed current"); + + fprintf(fp, "%s\n", next); + fclose(fp); + + return fremove("%s/next", net); +} From caa07e8b2054836036ff16de4144daadc8d849b6 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sat, 8 Apr 2023 07:18:46 +0200 Subject: [PATCH 45/52] Drop local libite patches in favor of libite v2.5.3 Signed-off-by: Joachim Wiberg --- buildroot | 2 +- ...urn-value-when-copying-a-single-file.patch | 30 -------- ...for-missing-dst-when-dst-is-a-direct.patch | 29 -------- ...opying-empty-files-to-non-existing-d.patch | 68 ------------------- 4 files changed, 1 insertion(+), 128 deletions(-) delete mode 100644 patches/libite/2.5.2/0001-rsync-fix-return-value-when-copying-a-single-file.patch delete mode 100644 patches/libite/2.5.2/0002-rsync-fix-check-for-missing-dst-when-dst-is-a-direct.patch delete mode 100644 patches/libite/2.5.2/0003-copyfile-allow-copying-empty-files-to-non-existing-d.patch diff --git a/buildroot b/buildroot index 3790a1f4..58814174 160000 --- a/buildroot +++ b/buildroot @@ -1 +1 @@ -Subproject commit 3790a1f4b6163f106cc87512efe01e22404296b4 +Subproject commit 588141749e57c0edb4df2daaef8697f98800a8b2 diff --git a/patches/libite/2.5.2/0001-rsync-fix-return-value-when-copying-a-single-file.patch b/patches/libite/2.5.2/0001-rsync-fix-return-value-when-copying-a-single-file.patch deleted file mode 100644 index 7e06dcd6..00000000 --- a/patches/libite/2.5.2/0001-rsync-fix-return-value-when-copying-a-single-file.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 90fdcdeb39e35193fe4e8f5d5277cf9ca28d5055 Mon Sep 17 00:00:00 2001 -From: Joachim Wiberg -Date: Sun, 2 Apr 2023 22:16:50 +0200 -Subject: [PATCH 1/4] rsync: fix return value when copying a single file -Organization: Addiva Elektronik - -Signed-off-by: Joachim Wiberg ---- - src/rsync.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/rsync.c b/src/rsync.c -index 392e1d2..92b8d63 100644 ---- a/src/rsync.c -+++ b/src/rsync.c -@@ -85,9 +85,9 @@ int rsync(char *src, char *dst, int opt, int (*filter)(const char *file)) - return 1; - - if (copy(src, dst, keep_mtim)) -- result++; -+ return 1; - -- return errno; -+ return 0; - } - - /* Copy dir as well? */ --- -2.34.1 - diff --git a/patches/libite/2.5.2/0002-rsync-fix-check-for-missing-dst-when-dst-is-a-direct.patch b/patches/libite/2.5.2/0002-rsync-fix-check-for-missing-dst-when-dst-is-a-direct.patch deleted file mode 100644 index e9916cf7..00000000 --- a/patches/libite/2.5.2/0002-rsync-fix-check-for-missing-dst-when-dst-is-a-direct.patch +++ /dev/null @@ -1,29 +0,0 @@ -From d61b847e557e5162163dffd1abd4b5d9bedc6d7a Mon Sep 17 00:00:00 2001 -From: Joachim Wiberg -Date: Sun, 2 Apr 2023 22:17:09 +0200 -Subject: [PATCH 2/4] rsync: fix check for missing dst when dst is a directory -Organization: Addiva Elektronik - -Signed-off-by: Joachim Wiberg ---- - src/rsync.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/src/rsync.c b/src/rsync.c -index 92b8d63..695fac3 100644 ---- a/src/rsync.c -+++ b/src/rsync.c -@@ -77,7 +77,9 @@ int rsync(char *src, char *dst, int opt, int (*filter)(const char *file)) - char **files; /* Array of file names. */ - struct stat st; - -- if (!fisdir(dst)) -+ errno = 0; -+ -+ if (stat(dst, &st) && fisslashdir(dst)) - makedir(dst, 0755); - - if (!fisdir(src)) { --- -2.34.1 - diff --git a/patches/libite/2.5.2/0003-copyfile-allow-copying-empty-files-to-non-existing-d.patch b/patches/libite/2.5.2/0003-copyfile-allow-copying-empty-files-to-non-existing-d.patch deleted file mode 100644 index b7491c0a..00000000 --- a/patches/libite/2.5.2/0003-copyfile-allow-copying-empty-files-to-non-existing-d.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 4e9b5c13c16f7e7261a15143d9418385274a008e Mon Sep 17 00:00:00 2001 -From: Joachim Wiberg -Date: Sun, 2 Apr 2023 22:17:47 +0200 -Subject: [PATCH 3/4] copyfile: allow copying empty files to non-existing - destination dirs -Organization: Addiva Elektronik - -Signed-off-by: Joachim Wiberg ---- - src/copyfile.c | 14 ++++++++++++-- - 1 file changed, 12 insertions(+), 2 deletions(-) - -diff --git a/src/copyfile.c b/src/copyfile.c -index afbbda9..af34012 100644 ---- a/src/copyfile.c -+++ b/src/copyfile.c -@@ -38,6 +38,7 @@ static int adjust_target(const char *src, char **dst) - { - int isdir = 0; - -+ retry: - if (fisdir(*dst)) { - int slash = 0; - char *tmp, *ptr = strrchr(src, '/'); -@@ -58,6 +59,13 @@ static int adjust_target(const char *src, char **dst) - - sprintf(tmp, "%s%s%s", *dst, slash ? "" : "/", ptr); - *dst = tmp; -+ } else { -+ struct stat st; -+ -+ if (stat(*dst, &st) && fisslashdir(*dst)) { -+ makedir(*dst, 0755); -+ goto retry; -+ } - } - - return isdir; -@@ -67,7 +75,7 @@ static int adjust_target(const char *src, char **dst) - * breaks loop on error and EOF */ - static ssize_t do_copy(int in, int out, size_t num, char *buffer, size_t len) - { -- ssize_t ret = 0, size = 0; -+ ssize_t ret = 0, size = -1; - - do { - size_t count = num > len ? len : num; -@@ -76,6 +84,8 @@ static ssize_t do_copy(int in, int out, size_t num, char *buffer, size_t len) - if (ret <= 0) { - if (ret == -1 && EINTR == errno) - continue; -+ if (ret == 0 && size == -1) -+ size = 0; - break; - } - -@@ -194,7 +204,7 @@ ssize_t copyfile(const char *src, const char *dst, int len, int opt) - } - - size = do_copy(in, out, num, buffer, BUFSIZ); -- if (!size && errno) -+ if (size < 0) - saved_errno = errno; - else if (keep_mtim) - set_mtime(in, out); --- -2.34.1 - From 82c8423ceaf8fd87c024ad7f01ae51de7a69e857 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sat, 8 Apr 2023 10:18:32 +0200 Subject: [PATCH 46/52] src/net: fixes after spec. audit by wkz Signed-off-by: Joachim Wiberg --- src/net/Makefile | 4 ++ src/net/README.md | 117 ++++++++++++++++++++++++++++------------- src/net/gen.sh | 33 ------------ src/net/main.c | 131 ++++++++++++++++++++++++++++++++-------------- src/net/test.sh | 101 +++++++++++++++++++++++++++++++++++ 5 files changed, 278 insertions(+), 108 deletions(-) delete mode 100755 src/net/gen.sh create mode 100755 src/net/test.sh diff --git a/src/net/Makefile b/src/net/Makefile index 348f67ae..5c14a66e 100644 --- a/src/net/Makefile +++ b/src/net/Makefile @@ -1,8 +1,12 @@ LDLIBS = -lite +EXEC = net net: main.o $(CC) -o $@ $^ $(LDLIBS) +check: $(EXEC) + ./test.sh + clean: $(RM) net diff --git a/src/net/README.md b/src/net/README.md index c86d6f12..55625148 100644 --- a/src/net/README.md +++ b/src/net/README.md @@ -7,24 +7,35 @@ a previously configured state to the next while attempting to keep the amount of changes needed to a minimum. -Overview --------- +Concept Overview +---------------- net applies a configuration from `/run/net/next`, where `next` is a file -that holds the number of the current generation. It is up to the user -to create the below structure with commands to run. Consider the case -when `next` contains `0`, net reads all interfaces, in dependency order, -from `/run/net/0/` and runs all the `ip-link` and `ip-addr` commands. -When it is done, it writes `0` to the file `/run/net/gen` and removes -the `next` file to confirm the next generation has been activated. +that holds the number of the current generation. It is up to the user, +i.e., sysrepo, to create the below tree structure with commands to run. -Note: it is currently up to the user to remove any old generation. +The setup we start with and later move `eth4` from `lag0` to `br0`. + + vlan1 + ______/____ + [____br0____] + / / \ \ + eth1 eth2 eth3 lag0 + / \ + eth4 eth5 + +Consider the case when `next` contains `0`, net reads all interfaces, in +dependency order, from `/run/net/0/` running all `ip-link` and `ip-addr` +commands. When done, it writes `0` to the file `/run/net/gen` and then +removes the `next` file to confirm the generation has been activated. + +**Note:** it is currently up to the user to remove any old generation. /run/net/0/ |-- lo/ | |-- deps/ - | |-- ip-link - | `-- ip-addr + | |-- ip-link.up + | `-- ip-addr.up |-- br0/ | |-- deps/ | | |-- eth1 -> ../../eth1 @@ -37,6 +48,9 @@ Note: it is currently up to the user to remove any old generation. | |-- deps/ | |-- ip-link.up | `-- ip-addr.up + |-- ethX/ + | |-- ... + : : |-- lag0/ | |-- deps/ | | |-- eth4 -> ../../eth4 @@ -50,30 +64,67 @@ Note: it is currently up to the user to remove any old generation. `-- ip-addr.up The `deps/` sub-directory for each of the interfaces contains symlinks -to all interfaces that this interface depends on. I.e., when bringing -networking up or down these dependent interfaces are evaluated in order -creating a dependency tree: +to any interfaces this interface may depend on. I.e., those interfaces +are evaluated first. - vlan1 - _____/____ - [___br0____] - / / \ \ - eth1 eth2 eth3 lag0 - / \ - eth4 eth5 - -Essentially, all leaves must be set up before their parents. +Essentially, all leaves must be set up before their parents. Moving a +leaf from one parent to another, e.g., from lag0 to br0, is tricky, it +involves traversing the previous dependency order when removing leaves, +and traversing the next dependency order when addning, see next section +for an example. -Concepts --------- +Example +------- -Conceptually, net is built to complement sysrepo. The idea is to listen -to added, deleted, modified states in sysrepo changes to a candidate -configuration and generate the `next` generation. +net is built to complement sysrepo. The idea is to listen to any added, +deleted, modified states in sysrepo changes to a candidate configuration +and generate the `next` generation. However, as mentioned previously, +when moving leaves between parents we must do so in the dependency order +of the current generation. +So, the user (sysrepo) needs to add `.dn` scripts in the current tree, +and `.up` scripts in the next. - /run/net// +In our example, interface `eth4` is moved from `lag0` to `br0`, so we +need to run `eth4/ip-link.dn` in the current generation first to remove +`eth4` from `lag0` before its `ip-link.up` script in the next generation +sets `eth4` as a bridge member instead. + +We traverse the current generation and execute all `.dn` scripts: + + /run/net// + |-- lo/ + | `-- deps/ + |-- br0/ + | |-- deps/ + | | |-- eth1 -> ../../eth1 + | | |-- eth2 -> ../../eth2 + | | |-- eth3 -> ../../eth3 + | | `-- lag0 -> ../../lag0 + | `-- ip-link.up + |-- eth0/ + | |-- deps/ + | |-- ip-link.up + | `-- ip-addr.up + |-- eth4/ + | |-- deps/ + | |-- ip-link.dn + | `-- ip-link.up + |-- lag0/ + | |-- deps/ + | | |-- eth4 -> ../../eth4 + | | `-- eth5 -> ../../eth5 + | `-- ip-link.up + `-- vlan1/ + |-- deps/ + | `-- br0 -> ../../br0 + |-- ip-link.up + `-- ip-addr.up + +Now we can run all the `.up` scripts in the next generation: + + /run/net// |-- lo/ | |-- deps/ | |-- ip-link.up @@ -105,11 +156,3 @@ configuration and generate the `next` generation. `-- ip-addr.up -Interfaces can be evaluated in any order. The `deps/` directory of each -is interface is always evaluated first. For each dependency, `foo.dn` -is evaluated first and `foo.up` is evaluated last. Any `ip-link` script -is also evaluated before any `ip-addr` script. - -In the case above, interface `eth4` has been moved from `lag0` to `br0`, -so we need to run `eth4/ip-link.dn` to remove `eth4` from `lag0` before -its `ip-link.up` script sets `eth4` as a bridge member instead. diff --git a/src/net/gen.sh b/src/net/gen.sh deleted file mode 100755 index eaacf6fe..00000000 --- a/src/net/gen.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/sh -# Generate test directory structure for verifying the net tool - -gensh() -{ - cat <<-EOF >"$1" - #!/bin/sh - echo "Running \$0 ..." - EOF - chmod +x "$1" -} - -mkdir -p /tmp/net/1 -echo 1 > /tmp/net/next - -mkdir -p /tmp/net/1/lo/deps -mkdir -p /tmp/net/1/eth0/deps -mkdir -p /tmp/net/1/eth1/deps -mkdir -p /tmp/net/1/eth2/deps - -mkdir -p /tmp/net/1/br0/deps -ln -sf ../../eth1 /tmp/net/1/br0/deps/ -ln -sf ../../eth2 /tmp/net/1/br0/deps/ - -mkdir -p /tmp/net/1/vlan1/deps -ln -sf ../../br0 /tmp/net/1/vlan1/deps/ - -gensh /tmp/net/1/lo/ip-link.up -gensh /tmp/net/1/eth0/ip-link.up -gensh /tmp/net/1/eth1/ip-link.up -gensh /tmp/net/1/eth2/ip-link.up -gensh /tmp/net/1/br0/ip-link.up -gensh /tmp/net/1/vlan1/ip-link.up diff --git a/src/net/main.c b/src/net/main.c index 0eae4307..8b0943c8 100644 --- a/src/net/main.c +++ b/src/net/main.c @@ -1,11 +1,12 @@ #include #include #include +#include #include #include #define _PATH_NET "/run/net" -#define DEBUG 1 +#define DEBUG 0 #define dbg(fmt, args...) if (DEBUG) warnx(fmt, ##args) static char **handled; @@ -51,7 +52,7 @@ static int if_find(char *ifname) return 0; } -static int deps(char *ipath, char *ifname, char *action) +static int deps(char *ipath, char *ifname, const char *action) { char path[strlen(ipath) + 42]; int num, rc = -1; @@ -94,47 +95,94 @@ done: return rc; } -static int activate(const char *net, char *gen) +static int iter(char *path, size_t len, const char *action) +{ + char **files; + int rc = 0; + int num; + + num = dir(path, NULL, NULL, &files, 0); + if_alloc(num); + + for (int j = 0; j < num; j++) { + char *ifname = files[j]; + char ipath[len]; + + snprintf(ipath, sizeof(ipath), "%s/%s", path, ifname); + dbg("Calling deps(%s, %s, %s)", ipath, ifname, action); + rc += deps(ipath, ifname, action); + free(ifname); + } + + if_free(); + + return rc; +} + +static int deactivate(const char *net, char *gen) { char path[strlen(net) + strlen(gen) + 5 + IFNAMSIZ]; char *action[] = { "ip-addr.dn", "ip-link.dn", - "ip-link.up", - "ip-addr.up", }; - char **files; int rc = 0; snprintf(path, sizeof(path), "%s/%s", net, gen); - - for (size_t i = 0; i < NELEMS(action); i++) { - char *act = action[i]; - int num; - - num = dir(path, NULL, NULL, &files, 0); - if_alloc(num); - - for (int j = 0; j < num; j++) { - char ipath[sizeof(path)]; - char *ifname = files[j]; - - snprintf(ipath, sizeof(ipath), "%s/%s", path, ifname); - rc += deps(ipath, ifname, act); - free(ifname); - } - - if_free(); - } + for (size_t i = 0; i < NELEMS(action); i++) + rc += iter(path, sizeof(path), action[i]); return rc; } +static int activate(const char *net, char *gen) +{ + char path[strlen(net) + strlen(gen) + 5 + IFNAMSIZ]; + char *action[] = { + "ip-link.up", + "ip-addr.up", + }; + int rc = 0; + + snprintf(path, sizeof(path), "%s/%s", net, gen); + for (size_t i = 0; i < NELEMS(action); i++) + rc += iter(path, sizeof(path), action[i]); + + return rc; +} + +static int load_gen(const char *net, char *gen, char *buf, size_t len) +{ + FILE *fp; + + fp = fopenf("r", "%s/%s", net, gen); + if (!fp) + return EX_OSFILE; + if (!fgets(buf, len, fp)) + return EX_IOERR; + fclose(fp); + chomp(buf); + + return 0; +} + +static int save_gen(const char *net, char *gen, char *buf) +{ + FILE *fp; + + fp = fopenf("w", "%s/%s", net, gen); + if (!fp) + return -1; + fprintf(fp, "%s\n", buf); + fclose(fp); + + return 0; +} + int main(void) { const char *net = _PATH_NET; - char next[512]; - FILE *fp; + char curr[512], next[512]; int rc; if (getenv("NET_DIR")) @@ -144,24 +192,31 @@ int main(void) err(1, "makedir"); } - fp = fopenf("r", "%s/next", net); - if (!fp) + if ((rc = load_gen(net, "next", next, sizeof(next)))) { + if (rc == EX_IOERR) + warnx("missing next generation"); exit(0); /* nothing to do */ + } - if (!fgets(next, sizeof(next), fp)) - err(1, "missing next generation"); - fclose(fp); + if ((rc = load_gen(net, "gen", curr, sizeof(curr)))) { + if (rc == EX_IOERR) + errx(rc, "missing current generation"); + /* no current generation */ + } else { + rc = deactivate(net, curr); + if (rc) + err(1, "failed deactivating current generation"); + } - rc = activate(net, chomp(next)); + rc = activate(net, next); if (rc) err(1, "failed activating next generation"); - fp = fopenf("w", "%s/gen", net); - if (!fp) + if (save_gen(net, "gen", next)) err(1, "next generation applied, failed current"); - fprintf(fp, "%s\n", next); - fclose(fp); + if (fremove("%s/next", net)) + err(1, "failed removing %s/next", net); - return fremove("%s/next", net); + return 0; } diff --git a/src/net/test.sh b/src/net/test.sh new file mode 100755 index 00000000..c008f527 --- /dev/null +++ b/src/net/test.sh @@ -0,0 +1,101 @@ +#!/bin/sh +# Generate test directory structure for verifying the net tool +set -e + +NET_DIR=/tmp/net +export NET_DIR + +gensh() +{ + cat <<-EOF >"$1" + #!/bin/sh + echo "Running \$0 ..." + EOF + chmod +x "$1" +} + +check() +{ + if ./net; then + printf "\n[\033[1;32m OK \033[0m] Checking %s\n" "$1" + return 0 + fi + + printf "\n[\033[1;31FAIL\033[0m] Checking %s\n" "$1" + return 1 +} + +echo "Verify that all leaves and dependencies are" +echo "evaluated first:" +echo " vlan1" +echo " ______/____" +echo " [____br0____]" +echo " / / \\ \\" +echo "lo eth0 eth1 eth2 eth3 lag0" +echo " / \\" +echo " eth4 eth5" +printf "_______________________________________________\n\n" + +mkdir -p $NET_DIR/0 +echo 0 > $NET_DIR/next + +mkdir -p $NET_DIR/0/lo/deps +gensh $NET_DIR/0/lo/ip-link.up + +mkdir -p $NET_DIR/0/eth0/deps +mkdir -p $NET_DIR/0/eth1/deps +mkdir -p $NET_DIR/0/eth2/deps +mkdir -p $NET_DIR/0/eth3/deps +mkdir -p $NET_DIR/0/eth4/deps + +gensh $NET_DIR/0/eth0/ip-link.up +gensh $NET_DIR/0/eth1/ip-link.up +gensh $NET_DIR/0/eth2/ip-link.up +gensh $NET_DIR/0/eth3/ip-link.up +gensh $NET_DIR/0/eth4/ip-link.up + +mkdir -p $NET_DIR/0/lag0/deps +ln -sf ../../eth3 $NET_DIR/0/lag0/deps/ +ln -sf ../../eth4 $NET_DIR/0/lag0/deps/ +gensh $NET_DIR/0/lag0/ip-link.up + +mkdir -p $NET_DIR/0/br0/deps +ln -sf ../../eth1 $NET_DIR/0/br0/deps/ +ln -sf ../../eth2 $NET_DIR/0/br0/deps/ +ln -sf ../../lag0 $NET_DIR/0/br0/deps/ +gensh $NET_DIR/0/br0/ip-link.up + +mkdir -p $NET_DIR/0/vlan1/deps +ln -sf ../../br0 $NET_DIR/0/vlan1/deps/ +gensh $NET_DIR/0/vlan1/ip-link.up + +check "initial startup, gen 0" + +printf "_______________________________________________\n\n" +mkdir -p $NET_DIR/1 + +mkdir -p $NET_DIR/1/lo/deps +mkdir -p $NET_DIR/1/eth0/deps +mkdir -p $NET_DIR/1/eth1/deps +mkdir -p $NET_DIR/1/eth2/deps +mkdir -p $NET_DIR/1/eth3/deps +mkdir -p $NET_DIR/1/eth4/deps + +mkdir -p $NET_DIR/1/lag0/deps +ln -sf ../../eth4 $NET_DIR/1/lag0/deps/ + +mkdir -p $NET_DIR/1/br0/deps +ln -sf ../../eth1 $NET_DIR/1/br0/deps/ +ln -sf ../../eth2 $NET_DIR/1/br0/deps/ +ln -sf ../../eth3 $NET_DIR/1/br0/deps/ + +mkdir -p $NET_DIR/1/vlan1/deps +ln -sf ../../br0 $NET_DIR/1/vlan1/deps/ + +gensh $NET_DIR/0/eth3/ip-link.dn +gensh $NET_DIR/1/eth3/ip-link.up +echo 1 > $NET_DIR/next + +check "move eth3 from lag0 to br0" + +exit 0 From 015f1b7a877485081245e706c2be25fb7ad29368 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Mon, 10 Apr 2023 16:36:32 +0200 Subject: [PATCH 47/52] package/finit: add support for setting RTC plugin fallback datetime Signed-off-by: Joachim Wiberg --- package/finit/Config.in | 22 ++++++++++++++++++++++ package/finit/finit.mk | 6 ++++++ 2 files changed, 28 insertions(+) diff --git a/package/finit/Config.in b/package/finit/Config.in index e0290304..94098312 100644 --- a/package/finit/Config.in +++ b/package/finit/Config.in @@ -150,6 +150,28 @@ config BR2_PACKAGE_FINIT_PLUGIN_RTC For lxc/docker application builds you do not need this. +if BR2_PACKAGE_FINIT_PLUGIN_RTC + +config BR2_PACKAGE_FINIT_RTC_DATE + string "Fallback RTC date" + help + On many embedded systems there is no RTC battery, maybe there + is a "supercap" but on first boot it is usually out of juice. + When this happens the RTC will return its default value, or + the driver will fail and report error. In these cases Linux + will detect a too old/invalid date set from userspace. Any + date prior to 2000-01-01 00:00 is denied. (Previously this + was the start of the UNIX epoch, Jan 1 1970.) + + This setting changes the default fallback date/time the RTC + plugin uses in case of such failures. Useful, e.g., for an + HTTPS certificate generated at first boot before any network + connection (DHCP/NTP) has been made to get the current time. + Ensuring the default system time to be closer to actual time + for a period after releasing a firmware image. + +endif + config BR2_PACKAGE_FINIT_PLUGIN_TTY bool "TTY plugin" help diff --git a/package/finit/finit.mk b/package/finit/finit.mk index 674acd7b..d67baf2e 100644 --- a/package/finit/finit.mk +++ b/package/finit/finit.mk @@ -89,6 +89,12 @@ else FINIT_CONF_OPTS += --disable-rtc-plugin endif +ifeq ($(BR2_PACKAGE_FINIT_RTC_DATE),y) +FINIT_CONF_OPTS += --with-rtc-date="$(BR2_PACKAGE_FINIT_RTC_DATE)" +else +FINIT_CONF_OPTS += --without-rtc-date +endif + ifeq ($(BR2_PACKAGE_FINIT_PLUGIN_TTY),y) FINIT_CONF_OPTS += --enable-tty-plugin else From 22a18f3e612524336fddd8d9be0dc22fd1cf25ee Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Wed, 12 Apr 2023 09:22:50 +0200 Subject: [PATCH 48/52] src/confd: skeleton for ietf-interfaces Signed-off-by: Joachim Wiberg --- src/confd/src/Makefile.am | 2 +- src/confd/src/core.c | 3 +++ src/confd/src/ietf-interfaces.c | 24 ++++++++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 src/confd/src/ietf-interfaces.c diff --git a/src/confd/src/Makefile.am b/src/confd/src/Makefile.am index 975bf7d5..06393ff6 100644 --- a/src/confd/src/Makefile.am +++ b/src/confd/src/Makefile.am @@ -6,4 +6,4 @@ plugin_LTLIBRARIES = confd-plugin.la confd_plugin_la_CFLAGS = $(augeas_CFLAGS) $(sysrepo_CFLAGS) $(CFLAGS) confd_plugin_la_LIBADD = $(augeas_LIBS) $(sysrepo_LIBS) $(CFLAGS) confd_plugin_la_LDFLAGS = -module -avoid-version -shared -confd_plugin_la_SOURCES = core.c core.h run.c ietf-system.c +confd_plugin_la_SOURCES = core.c core.h run.c ietf-system.c ietf-interfaces.c diff --git a/src/confd/src/core.c b/src/confd/src/core.c index 4337db88..d790236d 100644 --- a/src/confd/src/core.c +++ b/src/confd/src/core.c @@ -45,6 +45,9 @@ int sr_plugin_init_cb(sr_session_ctx_t *session, void **priv) if (rc = ietf_system_init(&confd)) goto err; + /* if (rc = ietf_interfaces_init(&confd)) */ + /* goto err; */ + /* YOUR_INIT GOES HERE */ /* Set up hook to save startup-config to persisten backend store */ diff --git a/src/confd/src/ietf-interfaces.c b/src/confd/src/ietf-interfaces.c new file mode 100644 index 00000000..eb5870df --- /dev/null +++ b/src/confd/src/ietf-interfaces.c @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#include "core.h" + +int ietf_system_init(struct confd *confd) +{ + char *model[] = { + YANG_PATH_"ietf-interfaces@2018-02-20.yang", + YANG_PATH_"ietf-ip@2018-02-22.yang", + }; + int rc, i; + + for (i = 0; i < NELEMS(model); i++) { + if (rc = sr_install_module(confd->conn, model[i], NULL, NULL)) + goto err; + } + + return SR_ERR_OK; +err: + ERROR("init failed: %s", sr_strerror(rc)); + sr_unsubscribe(confd->sub); + + return rc; +} From 02ac6a7ea7860b18c3c70cf1d5d411563835ba27 Mon Sep 17 00:00:00 2001 From: Richard Alpe Date: Tue, 11 Apr 2023 16:38:50 +0200 Subject: [PATCH 49/52] src/confd: add the ability to change MotD in cli Add the ability to set and delete system MotD (Message Of The Day) using the cli. This patch augments the standard ietf-system yang schema with a new infix-system schema which contains a new motd leaf. The default value is hard coded in two places, confd and the rootfs file /etc/motd. The intention is to fix this in upcoming patches. Introduces: exec> configure> set system motd STRING exec> configure> delete system motd --- .../sysrepo-plugin-system.mk | 2 ++ src/confd/src/ietf-system.c | 31 +++++++++++++++++++ src/confd/yang/infix-system@2014-08-06.yang | 20 ++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 src/confd/yang/infix-system@2014-08-06.yang diff --git a/package/sysrepo-plugin-system/sysrepo-plugin-system.mk b/package/sysrepo-plugin-system/sysrepo-plugin-system.mk index 5bd29954..044413b1 100644 --- a/package/sysrepo-plugin-system/sysrepo-plugin-system.mk +++ b/package/sysrepo-plugin-system/sysrepo-plugin-system.mk @@ -22,6 +22,8 @@ define SYSREPO_PLUGIN_SYSTEM_INSTALL_YANG_MODELS $(TARGET_DIR)/usr/share/yang/modules/sysrepo-plugin-system/iana-crypt-hash@2014-08-06.yang $(INSTALL) -D -m 0644 $(@D)/yang/ietf-system@2014-08-06.yang \ $(TARGET_DIR)/usr/share/yang/modules/sysrepo-plugin-system/ietf-system@2014-08-06.yang + $(INSTALL) -D -m 0644 $(@D)/yang/infix-system@2014-08-06.yang \ + $(TARGET_DIR)/usr/share/yang/modules/sysrepo-plugin-system/infix-system@2014-08-06.yang endef SYSREPO_PLUGIN_SYSTEM_POST_INSTALL_TARGET_HOOKS += SYSREPO_PLUGIN_SYSTEM_INSTALL_YANG_MODELS diff --git a/src/confd/src/ietf-system.c b/src/confd/src/ietf-system.c index 52060141..995bdb3f 100644 --- a/src/confd/src/ietf-system.c +++ b/src/confd/src/ietf-system.c @@ -659,6 +659,33 @@ fail: return rc; } +static int change_motd(sr_session_ctx_t *session, uint32_t sub_id, const char *module, + const char *xpath, sr_event_t event, unsigned request_id, void *priv) +{ + char *nm; + FILE *fp; + + /* Ignore all events except SR_EV_DONE */ + if (event != SR_EV_DONE) + return SR_ERR_OK; + + fp = fopen("/etc/motd", "w"); + if (!fp) + return SR_ERR_SYS; + + nm = sr_get_str(session, xpath); + if (nm) { + fprintf(fp, "%s\n", nm); + } else { + /* XXX: derive from global "options.h" or /usr/share/factory/ */ + fprintf(fp, "\033[1;90mNote:\033[0m "); + fprintf(fp, "\033[0;90m use help, show, and setup commands to set up and diagnose the system\033[0m\n"); + } + fclose(fp); + + return SR_ERR_OK; +} + static int change_hostname(sr_session_ctx_t *session, uint32_t sub_id, const char *module, const char *xpath, sr_event_t event, unsigned request_id, void *priv) { @@ -752,6 +779,9 @@ int ietf_system_init(struct confd *confd) if (rc = sr_install_module(confd->conn, YANG_PATH_"ietf-system@2014-08-06.yang", NULL, features)) goto err; + /* Augment to ietf-systems */ + if (rc = sr_install_module(confd->conn, YANG_PATH_"infix-system@2014-08-06.yang", NULL, NULL)) + goto err; rc = sr_oper_get_subscribe(confd->session, "ietf-system", CLOCK_PATH_, clock_cb, NULL, SR_SUBSCR_DEFAULT, &confd->sub); @@ -764,6 +794,7 @@ int ietf_system_init(struct confd *confd) goto err; REGISTER_CHANGE(confd->session, "ietf-system", "/ietf-system:system/hostname", 0, change_hostname, confd, &confd->sub); + REGISTER_CHANGE(confd->session, "ietf-system", "/ietf-system:system/infix-system:motd", 0, change_motd, confd, &confd->sub); REGISTER_CHANGE(confd->session, "ietf-system", "/ietf-system:system/clock", 0, change_clock, confd, &confd->sub); REGISTER_CHANGE(confd->session, "ietf-system", "/ietf-system:system/ntp", 0, change_ntp, confd, &confd->sub); REGISTER_CHANGE(confd->session, "ietf-system", "/ietf-system:system/dns-resolver", 0, change_dns, confd, &confd->sub); diff --git a/src/confd/yang/infix-system@2014-08-06.yang b/src/confd/yang/infix-system@2014-08-06.yang new file mode 100644 index 00000000..3034613b --- /dev/null +++ b/src/confd/yang/infix-system@2014-08-06.yang @@ -0,0 +1,20 @@ +module infix-system { + prefix "infix-sys"; + yang-version 1.1; + namespace "urn:infix:params:xml:ns:yang:infix-system"; + + import ietf-system { + prefix "sys"; + } + + revision 2014-08-06 { + description "Initial revision."; + } + + augment "/sys:system" { + leaf motd { + type string; + description "Set the MotD (Message of the Day), which is shown after login"; + } + } +} From 3320175abdbdd99a6dcd879860afd7515c936223 Mon Sep 17 00:00:00 2001 From: Tobias Waldekranz Date: Thu, 13 Apr 2023 09:22:43 +0200 Subject: [PATCH 50/52] confd: Fix symbol redefinition error --- src/confd/src/ietf-interfaces.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/src/confd/src/ietf-interfaces.c b/src/confd/src/ietf-interfaces.c index eb5870df..d2052a4b 100644 --- a/src/confd/src/ietf-interfaces.c +++ b/src/confd/src/ietf-interfaces.c @@ -2,23 +2,7 @@ #include "core.h" -int ietf_system_init(struct confd *confd) +int ietf_interfaces_init(struct confd *confd) { - char *model[] = { - YANG_PATH_"ietf-interfaces@2018-02-20.yang", - YANG_PATH_"ietf-ip@2018-02-22.yang", - }; - int rc, i; - - for (i = 0; i < NELEMS(model); i++) { - if (rc = sr_install_module(confd->conn, model[i], NULL, NULL)) - goto err; - } - return SR_ERR_OK; -err: - ERROR("init failed: %s", sr_strerror(rc)); - sr_unsubscribe(confd->sub); - - return rc; } From f5259b32d806c652d08038ad099a4ad33b7509bc Mon Sep 17 00:00:00 2001 From: Tobias Waldekranz Date: Thu, 13 Apr 2023 09:24:01 +0200 Subject: [PATCH 51/52] confd: Kill all -Wall -Wextra warnings --- src/confd/src/core.c | 25 ++++++++------ src/confd/src/core.h | 21 +++++++++--- src/confd/src/ietf-system.c | 67 ++++++++++++++----------------------- 3 files changed, 57 insertions(+), 56 deletions(-) diff --git a/src/confd/src/core.c b/src/confd/src/core.c index d790236d..8c2708aa 100644 --- a/src/confd/src/core.c +++ b/src/confd/src/core.c @@ -42,31 +42,36 @@ int sr_plugin_init_cb(sr_session_ctx_t *session, void **priv) if (!confd.aug) goto err; - if (rc = ietf_system_init(&confd)) + rc = ietf_interfaces_init(&confd); + if (rc) + goto err; + rc = ietf_system_init(&confd); + if (rc) goto err; - - /* if (rc = ietf_interfaces_init(&confd)) */ - /* goto err; */ /* YOUR_INIT GOES HERE */ /* Set up hook to save startup-config to persisten backend store */ - if (rc = sr_session_start(confd.conn, SR_DS_STARTUP, &startup)) + rc = sr_session_start(confd.conn, SR_DS_STARTUP, &startup); + if (rc) goto err; - if (rc = sr_module_change_subscribe(startup, "ietf-system", "/ietf-system:system//.", - startup_save_hook, NULL, 0, SR_SUBSCR_PASSIVE | SR_SUBSCR_DONE_ONLY, &confd.sub)) { + rc = sr_module_change_subscribe(startup, "ietf-system", "/ietf-system:system//.", + startup_save_hook, NULL, 0, SR_SUBSCR_PASSIVE | SR_SUBSCR_DONE_ONLY, &confd.sub); + if (rc) { ERROR("failed setting up startup-config hook: %s", sr_strerror(rc)); goto err; } - if (rc = sr_module_change_subscribe(session, "ietf-system", "/ietf-system:system//.", - commit_done_hook, NULL, 0, SR_SUBSCR_PASSIVE | SR_SUBSCR_DONE_ONLY, &confd.sub)) { + rc = sr_module_change_subscribe(session, "ietf-system", "/ietf-system:system//.", + commit_done_hook, NULL, 0, SR_SUBSCR_PASSIVE | SR_SUBSCR_DONE_ONLY, &confd.sub); + if (rc) { ERROR("failed setting up startup-config hook: %s", sr_strerror(rc)); goto err; } - if (rc = sr_install_module(confd.conn, YANG_PATH_"kernelkit-infix-deviations.yang", NULL, NULL)) + rc = sr_install_module(confd.conn, YANG_PATH_"kernelkit-infix-deviations.yang", NULL, NULL); + if (rc) goto err; return SR_ERR_OK; diff --git a/src/confd/src/core.h b/src/confd/src/core.h index 3b1c036f..4dd130fc 100644 --- a/src/confd/src/core.h +++ b/src/confd/src/core.h @@ -25,12 +25,22 @@ #define ERROR(frmt, ...) syslog(LOG_ERR, "%s: " frmt, __func__, ##__VA_ARGS__) #define ERRNO(frmt, ...) syslog(LOG_ERR, "%s: " frmt ": %s", __func__, ##__VA_ARGS__, strerror(errno)) -#define REGISTER_CHANGE(s,m,x,f,c,a,u) \ - if (rc = register_change(s, m, x, f, c, a, u)) \ +static inline void print_val(sr_val_t *val) +{ + char *str; + + if (sr_print_val_mem(&str, val)) + return; + ERROR("%s", str); + free(str); +} + +#define REGISTER_CHANGE(s,m,x,f,c,a,u) \ + if ((rc = register_change(s, m, x, f, c, a, u))) \ goto err #define REGISTER_RPC(s,x,c,a,u) \ - if (rc = register_rpc(s, x, c, a, u)) \ + if ((rc = register_rpc(s, x, c, a, u))) \ goto err struct confd { @@ -63,7 +73,10 @@ static inline int register_rpc(sr_session_ctx_t *session, const char *xpath, /* core.c */ int run(const char *fmt, ...); -/* ietf-syste.c */ +/* ietf-interfaces.c */ +int ietf_interfaces_init(struct confd *confd); + +/* ietf-system.c */ int ietf_system_init(struct confd *confd); #endif /* CONFD_CORE_H_ */ diff --git a/src/confd/src/ietf-system.c b/src/confd/src/ietf-system.c index 995bdb3f..7c7841c4 100644 --- a/src/confd/src/ietf-system.c +++ b/src/confd/src/ietf-system.c @@ -144,7 +144,6 @@ static int platform_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *m struct lyd_node **parent, void *priv) { const struct ly_ctx *ctx; - struct utsname data; char *buf; int rc; @@ -250,16 +249,6 @@ static int sys_reload_services(void) return run("initctl -nbq touch sysklogd lldpd"); } -static void print_val(sr_val_t *val) -{ - char *str; - - if (sr_print_val_mem(&str, val)) - return; - ERROR("%s", str); - free(str); -} - int sr_get_int(sr_session_ctx_t *session, const char *fmt, ...) { sr_val_t *val = NULL; @@ -391,11 +380,8 @@ fail: static int change_clock(sr_session_ctx_t *session, uint32_t sub_id, const char *module, const char *xpath, sr_event_t event, unsigned request_id, void *priv) { - struct confd *confd = (struct confd *)priv; - const char *fn = TIMEZONE_CONF; char *timezone; FILE *fp; - int rc; switch (event) { case SR_EV_ENABLED: /* first time, on register. */ @@ -421,6 +407,9 @@ static int change_clock(sr_session_ctx_t *session, uint32_t sub_id, const char * rename("/etc/localtime+", "/etc/localtime"); return SR_ERR_OK; + + default: + return SR_ERR_OK; } /* XXX: add support also for /ietf-system:system/clock/timezone-utc-offset (deviation) */ @@ -454,10 +443,8 @@ static int change_clock(sr_session_ctx_t *session, uint32_t sub_id, const char * static int change_ntp(sr_session_ctx_t *session, uint32_t sub_id, const char *module, const char *xpath, sr_event_t event, unsigned request_id, void *priv) { - struct confd *confd = (struct confd *)priv; const char *fn = CHRONY_NEXT; int valid = -1; - sr_data_t *sdt; sr_val_t *val; size_t cnt; FILE *fp; @@ -492,13 +479,17 @@ static int change_ntp(sr_session_ctx_t *session, uint32_t sub_id, const char *mo run("initctl -nbq touch chronyd"); run("initctl -nbq enable chronyd"); return SR_ERR_OK; + + default: + return SR_ERR_OK; } - if (rc = sr_get_items(session, "/ietf-system:system/ntp/server", 0, 0, &val, &cnt)) { + rc = sr_get_items(session, "/ietf-system:system/ntp/server", 0, 0, &val, &cnt); + if (rc) { remove(CHRONY_NEXT); return rc; } - + fp = fopen(fn, "w"); if (!fp) { ERROR("failed updating %s: %s", fn, strerror(errno)); @@ -511,7 +502,7 @@ static int change_ntp(sr_session_ctx_t *session, uint32_t sub_id, const char *mo char *type, *ptr; int server = 0; - /* + /* * Handle empty startup-config on SR_EV_ENABLED, * prevents subscribe failure due to false invalid. */ @@ -528,7 +519,8 @@ static int change_ntp(sr_session_ctx_t *session, uint32_t sub_id, const char *mo free(type); free(ptr); - if (ptr = sr_get_str(session, "%s/udp/port", xpath)) { + ptr = sr_get_str(session, "%s/udp/port", xpath); + if (ptr) { fprintf(fp, " port %s", ptr); free(ptr); } @@ -568,12 +560,9 @@ static int change_ntp(sr_session_ctx_t *session, uint32_t sub_id, const char *mo static int change_dns(sr_session_ctx_t *session, uint32_t sub_id, const char *module, const char *xpath, sr_event_t event, unsigned request_id, void *priv) { - struct confd *confd = (struct confd *)priv; const char *fn = RESOLV_NEXT; int timeout, attempts; int rc = SR_ERR_SYS; - int valid = -1; - sr_data_t *sdt; sr_val_t *val; size_t cnt; FILE *fp; @@ -603,6 +592,9 @@ static int change_dns(sr_session_ctx_t *session, uint32_t sub_id, const char *mo run("resolvconf -u"); return SR_ERR_OK; + + default: + return SR_ERR_OK; } fp = fopen(fn, "w"); @@ -623,7 +615,8 @@ static int change_dns(sr_session_ctx_t *session, uint32_t sub_id, const char *mo fprintf(fp, "\n"); } - if (rc = sr_get_items(session, "/ietf-system:system/dns-resolver/search", 0, 0, &val, &cnt)) + rc = sr_get_items(session, "/ietf-system:system/dns-resolver/search", 0, 0, &val, &cnt); + if (rc) goto fail; if (cnt) { @@ -634,13 +627,13 @@ static int change_dns(sr_session_ctx_t *session, uint32_t sub_id, const char *mo } sr_free_values(val, cnt); - if (rc = sr_get_items(session, "/ietf-system:system/dns-resolver/server", 0, 0, &val, &cnt)) + rc = sr_get_items(session, "/ietf-system:system/dns-resolver/server", 0, 0, &val, &cnt); + if (rc) goto fail; for (size_t i = 0; i < cnt; i++) { const char *xpath = val[i].xpath; - char *type, *ptr; - int server = 0; + char *ptr; /* Get /ietf-system:system/dns-resolver/server[name='foo'] */ ptr = sr_get_str(session, "%s/udp-and-tcp/address", xpath); @@ -693,23 +686,11 @@ static int change_hostname(sr_session_ctx_t *session, uint32_t sub_id, const cha const char *host, *tmp = NULL; char **hosts, *current; int err, i, nhosts; - int rc = SR_ERR_SYS; char *nm; - switch (event) { - case SR_EV_ENABLED: /* first time, on register. */ - case SR_EV_CHANGE: /* regular change (copy cand running) */ - /* Wait for DONE to activate changes */ + if (event != SR_EV_DONE) return SR_ERR_OK; - case SR_EV_ABORT: /* User abort, or other plugin failed */ - return SR_ERR_OK; - - case SR_EV_DONE: - /* Activate changes */ - break; - } - nm = sr_get_str(session, xpath); if (!nm) { /* XXX: derive from global "options.h" or /usr/share/factory/ */ @@ -777,10 +758,12 @@ int ietf_system_init(struct confd *confd) goto err; } - if (rc = sr_install_module(confd->conn, YANG_PATH_"ietf-system@2014-08-06.yang", NULL, features)) + rc = sr_install_module(confd->conn, YANG_PATH_"ietf-system@2014-08-06.yang", NULL, features); + if (rc) goto err; /* Augment to ietf-systems */ - if (rc = sr_install_module(confd->conn, YANG_PATH_"infix-system@2014-08-06.yang", NULL, NULL)) + rc = sr_install_module(confd->conn, YANG_PATH_"infix-system@2014-08-06.yang", NULL, NULL); + if (rc) goto err; rc = sr_oper_get_subscribe(confd->session, "ietf-system", CLOCK_PATH_, From e9c4bafb4cf95e06cce005e19e39cd34b63b16dc Mon Sep 17 00:00:00 2001 From: Tobias Waldekranz Date: Thu, 13 Apr 2023 09:25:43 +0200 Subject: [PATCH 52/52] confd: Treat all build warnings as errors We exclude unused parameters, since many callbacks have parameters that we're not interested in. --- src/confd/src/Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/confd/src/Makefile.am b/src/confd/src/Makefile.am index 06393ff6..49083c9a 100644 --- a/src/confd/src/Makefile.am +++ b/src/confd/src/Makefile.am @@ -1,9 +1,10 @@ +CFLAGS = -Wall -Wextra -Werror -Wno-unused-parameter AM_CPPFLAGS = -D_DEFAULT_SOURCE -D_XOPEN_SOURCE -DYANG_PATH_=\"$(YANGDIR)/\" plugindir = $(srpdplugindir) plugin_LTLIBRARIES = confd-plugin.la confd_plugin_la_CFLAGS = $(augeas_CFLAGS) $(sysrepo_CFLAGS) $(CFLAGS) -confd_plugin_la_LIBADD = $(augeas_LIBS) $(sysrepo_LIBS) $(CFLAGS) +confd_plugin_la_LIBADD = $(augeas_LIBS) $(sysrepo_LIBS) confd_plugin_la_LDFLAGS = -module -avoid-version -shared confd_plugin_la_SOURCES = core.c core.h run.c ietf-system.c ietf-interfaces.c