Compare commits

...
45 Commits
Author SHA1 Message Date
Tobias Waldekranz 964a4c755e [TEMP] save 2023-04-12 09:36:50 +02:00
Tobias Waldekranz 7eec8c2964 sysrest: Initial add
A RESTCONF front-end for sysrepo.
2023-04-05 17:00:01 +02:00
Tobias Waldekranz e729c82c32 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.
2023-03-31 17:31:34 +02:00
Joachim Wiberg abd001f57d package/confd: start netopeer2-server along with sysrepo
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-03-31 11:03:44 +02:00
Joachim Wiberg cfef79bbf9 configs: enable netopeer2-cli and add klish to defconfigs
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-03-31 11:02:45 +02:00
Joachim Wiberg 3cce1e6427 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 <troglobit@gmail.com>
2023-03-29 13:00:10 +02:00
Tobias Waldekranz d66dc16600 package/klish-plugin-sysrepo: Bump to latest master
This adds completion support for nodes nested under choice and case
nodes.
2023-03-29 11:32:09 +02:00
Joachim Wiberg 24a1eb542d src/confd: add support for enabling yang features
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-03-29 08:03:37 +02:00
Joachim Wiberg 708b756eba src/confd: minor, coding style
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-03-29 07:43:48 +02:00
Joachim Wiberg 3bbc5c49cd src/confd: derive YANG module search path from configure
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-03-29 07:12:13 +02:00
Joachim Wiberg 41db19ffaa src/confd: import updated yang models from mech
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-03-29 06:22:27 +02:00
Joachim Wiberg 1907bd6a75 src/confd: adjust Denis' copyright year, last changed 2020
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-03-29 06:22:27 +02:00
Joachim Wiberg d1444b900a package/confd: allow klishd to run in NETCONF mode
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-03-28 20:53:55 +02:00
Joachim Wiberg 737f99e35e package/klish: make sure to enable libxml2 in configure
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-03-28 20:53:41 +02:00
Tobias WaldekranzandJoachim Wiberg b549ddd88a package/klish-plugin-sysrepo: Add version 1.0.0
Adds a klish interface to local datastores managed by sysrepo.
2023-03-28 20:29:31 +02:00
Tobias WaldekranzandJoachim Wiberg 5d8e0ec123 package/klish: Add version 3.0.0
Extensible CLI application
2023-03-28 20:29:31 +02:00
Tobias WaldekranzandJoachim Wiberg fdfcac70eb package/faux: Add version 2.1.0
Used by the upcoming klish package
2023-03-28 20:29:31 +02:00
Joachim Wiberg 7a69c21e9d 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 <troglobit@gmail.com>
2023-03-28 20:27:18 +02:00
Joachim Wiberg b1be357a41 package/confd: new package
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-03-28 20:27:18 +02:00
Joachim Wiberg 767296e830 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 <troglobit@gmail.com>
2023-03-28 20:27:18 +02:00
Joachim Wiberg 91d67e6b00 src/confd: import sysrepo ietf-system plugin by Denis Kalashnikov
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-03-28 20:27:18 +02:00
Joachim Wiberg 8e03114518 patches: add support for running sysrepo-plugind in the foreground
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-03-28 20:27:18 +02:00
Joachim Wiberg 546a2f3afb package/mech: relocate clixon system setup
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-03-28 20:27:18 +02:00
Joachim Wiberg aa3d8945b9 buildroot: switch to (updated) sysrepo branch from kkit
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-03-28 13:37:45 +02:00
Joachim Wiberg d7b032cee7 .github: dispatch workflows manually from now on
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-03-27 15:53:35 +02:00
Joachim Wiberg f5a863df04 package/finit: bump for initctl -n additions (enable/disable)
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-03-27 15:48:38 +02:00
Joachim Wiberg 0cfd0fcd89 package/skeleton-init-finit: add Frr pathd and vrrpd start scripts
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-03-27 14:38:17 +02:00
Joachim Wiberg 81c9398a19 doc: project goals and founding ideas
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-03-27 14:13:25 +02:00
Joachim Wiberg eed61988d1 doc: RESTCONF adventures, lab notes
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-03-27 14:11:10 +02:00
Joachim Wiberg fe20f4a470 mech: new autocli commands, cut-and-paste from various examples
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-03-27 14:10:26 +02:00
Joachim Wiberg ac7b9073a5 mech: disable debug dumps of transactions by default
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-03-27 14:08:27 +02:00
Joachim Wiberg aec2514eae mech: add support for ietf-syste:system/dns-resolver
This commit adds multi-nameserver support using openresolv (resolvconf)
and dnsmasq.  This means that a DHCP client (dhcpcd) or VPN client can
be providers of nameservers to the system.  Dnsmasq takes over as the
system resolver, except when the user has set up static configuration.

Static nameserver(s), as well as search and options, are always added
first by openresolv to /etc/resolv.conf.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-03-27 14:05:03 +02:00
Joachim Wiberg a5258d7102 mech: wrap system() as run(), returning WEXITSTATUS() or -1 on error
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-03-27 14:03:03 +02:00
Joachim Wiberg 4acaa170e4 mech: add support for ietf-system:set-current-datetime rpc
Also adds:
 - namespace validation
 - proper rpc operation lookup

Fixes:
 - ietf-system:system-shutdown (broken due do invalid op)

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-03-24 01:50:36 +01:00
Joachim Wiberg 688c0ce2f7 mech: add support for ietf-system state data
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-03-24 01:50:36 +01:00
Joachim Wiberg 2ff4f869fa board/common: add ID_LIKE, BUILD_ID and ARCHITECTURE to /etc/os-release
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-03-24 01:50:36 +01:00
Joachim Wiberg cdb68cb611 package/skeleton-init-finit: add remaining Frr daemons
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-03-24 01:50:36 +01:00
Joachim Wiberg 8cff15e215 package/skeleton-init-finit: drop stdout log redirection
lldpd already use syslog

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-03-24 01:50:31 +01:00
Joachim Wiberg b25a374409 mech: drop unused code
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-03-23 18:40:18 +01:00
Joachim Wiberg 35b0880e7b package/clixon: add clish alias and append to /etc/shells
Allow clixon_cli to be a login shell.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-03-23 15:00:15 +01:00
Joachim Wiberg 80f57d0809 Add Building section and ToC
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-03-23 14:51:49 +01:00
Joachim Wiberg 89d08338ce mech: initial support for ietf-interfaces state data
First example of how to implement supoort for ro/state-data.
Only oper-status and phys-address per interface currently.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-03-23 13:25:23 +01:00
Joachim Wiberg 2abb0a5eb9 mech: add support for setting interface description as ifalias
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-03-23 13:24:26 +01:00
Joachim Wiberg 4730f3fe09 mech: clean up developer logs in ietf-interfaces
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-03-23 13:23:54 +01:00
Joachim Wiberg ec7d72c4c5 package/finit: bump to latest snapshot
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2023-03-22 09:43:41 +01:00
103 changed files with 9053 additions and 90 deletions
+8 -6
View File
@@ -1,13 +1,15 @@
name: Bob the Builder
# Consider switching to 'on: workflow_dispatch' when activity increases.
#on:
# push:
# branches:
# - '*'
# pull_request:
# branches:
# - '*'
on:
push:
branches:
- '*'
pull_request:
branches:
- '*'
workflow_dispatch:
jobs:
build:
+1 -1
View File
@@ -1,3 +1,3 @@
[submodule "buildroot"]
path = buildroot
url = https://github.com/buildroot/buildroot.git
url = ../buildroot.git
+33
View File
@@ -1,5 +1,16 @@
<img align="right" src="doc/text3134.png" alt="Infix Linux Networking Made Easy">
* [Introduction](#introduction)
* [Hardware](#hardware)
* [Qemu](#qemu)
* [GNS3](#gns3)
* [Building](#building)
* [Origin & Licensing](origin--licensing)
Introduction
------------
Infix is an embedded Linux Network Operating System (NOS) based on
[Buildroot][1], [Finit][2], [ifupdown-ng][3], and [Clixon][6].
Providing an easy-to-maintain and easy-to-port Open Source base for
@@ -54,6 +65,27 @@ Infix will show up in the "Router" category, it has 10 interfaces
available by default for use as switch ports or routing.
Building
--------
Buildroot is almost stand-alone, but need a few locally installed tools
to bootstrap itself. For details, see the [excellent manual][manual].
Briefly, to build an Infix image; select the target and then make:
make amd64_defconfig
make
Online help is available:
make help
To see available defconfigs for supported targets, use:
make list-defconfigs
> **Note:** build dependencies (Debian/Ubuntu): <kbd>sudo apt install make libssl-dev</kbd>
Origin & Licensing
------------------
@@ -94,3 +126,4 @@ any GPL[^1] licensed library.
[QEMU]: https://www.qemu.org/
[GNS3]: https://gns3.com/
[training]: https://addiva-elektronik.github.io/
[manual]: https://buildroot.org/downloads/manual/manual.html
+9
View File
@@ -18,6 +18,15 @@ config SIGN_KEY
comment "Additional Artifacts"
# For /etc/os-release, uses CondtionArchitechture= from systemd.unit(5)
config INFIX_ARCH
string
default "arm" if BR2_arm
default "arm64" if BR2_aarch64
default "mips64" if BR2_mips64
default "riscv64" if BR2_riscv
default "x86_64" if BR2_x86_64
menuconfig DISK_IMAGE
bool "Disk image"
help
+8
View File
@@ -1,4 +1,9 @@
#!/bin/sh
. "$BR2_CONFIG"
. "$TARGET_DIR/usr/lib/os-release"
if [ -n "${ID_LIKE}" ]; then
ID="${ID} ${ID_LIKE}"
fi
GIT_VERSION=$(git -C $BR2_EXTERNAL_INFIX_PATH describe --always --dirty --tags)
@@ -9,8 +14,11 @@ rm "$TARGET_DIR/etc/os-release"
echo "NAME=\"Infix\""
echo "VERSION=${GIT_VERSION}"
echo "ID=infix"
echo "ID_LIKE=\"${ID}\""
echo "VERSION_ID=${GIT_VERSION}"
echo "BUILD_ID=\"${NAME} ${VERSION}\""
echo "PRETTY_NAME=\"Infix by KernelKit\""
echo "ARCHITECTURE=\"${INFIX_ARCH}\""
echo "HOME_URL=https://github.com/KernelKit"
} > "$TARGET_DIR/etc/os-release"
+14
View File
@@ -0,0 +1,14 @@
# dnsmasq is the system resolver, the file /etc/resolv.conf is
# managed by openresolv. DHCP lease, VPN tunnel establishment,
# and similar events feed servers and configuration to dnsmasq.
domain-needed
#interface=lo
listen-address=127.0.0.1
enable-dbus
# Generated by openresolv
resolv-file=/var/lib/misc/resolv.conf
# Include all files in a directory which end in .conf
conf-dir=/etc/dnsmasq.d/,*.conf
+6 -1
View File
@@ -45,8 +45,13 @@ http {
index index.html index.htm;
}
location /.well-known/host-meta {
fastcgi_pass unix:/run/sysrest.sock;
include fastcgi_params;
}
location /restconf/ {
fastcgi_pass unix:/var/run/clixon/restconf.sock;
fastcgi_pass unix:/run/sysrest.sock;
include fastcgi_params;
}
+10
View File
@@ -0,0 +1,10 @@
# dnsmasq is the system resolver
name_servers="127.0.0.1"
resolv_conf=/etc/resolv.conf
resolv_conf_options="edns0 trust-ad"
# dnsmasq specific settings and list of
# nameservers in non-standard locations
dnsmasq_conf=/etc/dnsmasq.d/resolvconf.conf
dnsmasq_resolv=/var/lib/misc/resolv.conf
@@ -0,0 +1 @@
lo
+5 -2
View File
@@ -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
@@ -119,7 +120,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 +131,9 @@ 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_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
+5 -2
View File
@@ -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
@@ -122,7 +123,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 +134,9 @@ 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_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
+221
View File
@@ -0,0 +1,221 @@
Infix System Configuration and RESTCONF API
===========================================
This document shows how to configure settings in the Infix CLI and how
to remotely inspect and change the configuration, as well as send RPC
commands, using the RESTCONF API.
Configuration
-------------
### NTP Client
How to configure two NTP servers with different options:
```
set system ntp
set system ntp server default
set system ntp server default udp address 1.2.3.4
set system ntp server default udp port 1231
set system ntp server default iburst true
set system ntp server default prefer true
set system ntp server foo
set system ntp server foo udp address 4.3.2.1
set system ntp server foo iburst false
commit
```
How to set up an actually working configuration when the system has a
valid IP address:
```
set system ntp server bar
set system ntp server bar udp address 192.168.122.1
commit
```
### Static IP Address
DHCP support not yet ready, but would be the default in a product
with NETCONF as the primary interface. This eliminates the need
to set up the device and give a works-out-of-the-box experience.
(Pending separate discussion on security aspects, of course).
```
set interface eth0
set interface eth0 type ianaift:ethernetCsmacd
set interface eth0 enabled true
set interface eth0 ipv4
set interface eth0 ipv4 enabled true
set interface eth0 ipv4 address 192.168.122.22
set interface eth0 ipv4 address 192.168.122.22 prefix-length 24
commit
```
Multiple IP addresses per interface will be in the final product.
```
> show configuration
ietf-system:system {
hostname flood;
}
ietf-interfaces:interfaces {
interface eth0 {
type ianaift:ethernetCsmacd;
enabled true;
ietf-ip:ipv4 {
enabled true;
address 192.168.122.22 {
prefix-length 24;
}
}
}
interface eth1 {
}
}
clixon-restconf:restconf {
enable true;
auth-type none;
fcgi-socket /run/clixon/restconf.sock;
}
```
**Note:** authentication disabled for demo purposes.
To save the configuration so that it persists across reboots:
```
copy running startup
```
RESTCONF API
------------
Get a subset of the configuration:
```
$ curl -X GET http://192.168.122.22/restconf/data/ietf-system:system
{
"ietf-system:system": {
"hostname": "foo"
}
}
```
```
$ curl -k -X GET http://192.168.122.22/restconf/data/ietf-system:system-state/
{
"ietf-system:system-state": {
"platform": {
"os-name": "Infix",
"os-release": "Buildroot 2023.02",
"os-version": "latest-227-g51c35e9-dirty",
"machine": "x86_64"
},
"clock": {
"current-datetime": "2023-03-23T22:15:53+01:00",
"boot-datetime": "2023-03-23T22:08:42+01:00"
}
}
}
```
List available RPC operations:
```
$ curl -X GET http://192.168.122.22/restconf/operations
{"operations": {
"ietf-system:set-current-datetime": [null],
"ietf-system:system-restart": [null],
"ietf-system:system-shutdown": [null],
"clixon-lib:debug": [null],
"clixon-lib:ping": [null],
"clixon-lib:stats": [null],
"clixon-lib:restart-plugin": [null],
"clixon-lib:process-control": [null],
"ietf-netconf-monitoring:get-schema": [null],
"ietf-netconf:get-config": [null],
"ietf-netconf:edit-config": [null],
"ietf-netconf:copy-config": [null],
"ietf-netconf:delete-config": [null],
"ietf-netconf:lock": [null],
"ietf-netconf:unlock": [null],
"ietf-netconf:get": [null],
"ietf-netconf:close-session": [null],
"ietf-netconf:kill-session": [null],
"ietf-netconf:commit": [null],
"ietf-netconf:discard-changes": [null],
"ietf-netconf:cancel-commit": [null],
"ietf-netconf:validate": [null],
"clixon-rfc5277:create-subscription": [null],
"ietf-netconf-nmda:get-data": [null],
"ietf-netconf-nmda:edit-data": [null]}
}
```
### Set hostname remotely
```
$ curl -is -H 'Content-Type: application/yang-data+json' -H 'Accept: application/yang-data+json' -X PATCH -d @hostname.cfg http://192.168.122.22/restconf/data/ietf-system:system
HTTP/1.1 204 No Content
Server: nginx/1.22.1
Date: Thu, 16 Mar 2023 13:53:53 GMT
Connection: keep-alive
```
The file `hostname.cfg` is in JSON format and looks like this:
```
{
"ietf-system:system": {
"hostname": "foo"
}
}
```
One-liner command without external `.cfg` file:
```
$ curl -is -H 'Content-Type: application/yang-data+json' -H 'Accept: application/yang-data+json' -X PATCH -d '{"ietf-system:system":{"hostname":"flood"}}' http://192.168.122.22/restconf/data/ietf-system:system
HTTP/1.1 204 No Content
Server: nginx/1.22.1
Date: Thu, 16 Mar 2023 14:1
```
Run this on a PC connected to the "switch" to see how the settings take effect immediately:
```
$ watch 'lldpcli show neighbors |grep -A20 tap0'
```
### RPCs
Perform system reboot remotely:
```
$ curl -k -X POST http://192.168.122.22/restconf/operations/ietf-system:system-restart
```
Enable debug remotely:
```
$ curl -Ssik -X POST -H "Content-Type: application/yang-data+json" http://192.168.122.22/restconf/operations/clixon-lib:debug -d '{"clixon-lib:input":{"level":1}}'
```
Set current date/time:
```
$ curl -Ssik -X POST -H "Content-Type: application/yang-data+json" http://192.168.122.22/restconf/operations/ietf-system:set-current-datetime -d '{"ietf-system:input":{"current-datetime":"2023-03-23T22:15:53+01:00"}}'
HTTP/1.1 204 No Content
Server: nginx/1.22.1
Date: Thu, 23 Mar 2023 22:46:52 GMT
Connection: keep-alive
```
$ curl -Ssik -X POST -H "Content-Type: application/yang-data+json" http://192.168.122.22/restconf/operations/ietf-system:set-current-datetime -d '{"ietf-system:input":{"current-datetime":"2023-03-23T20:15:53+05:00"}}'
+55
View File
@@ -0,0 +1,55 @@
Infix Goals
===========
The founding ideas that drive Infix are:
- Use Buildroot, it is:
- High quality, track their LTS releases whenever possible
- Well maintained and responsive community
- Easy to use (c.f. Yocto or roll-your-own)
- Well curated Open Source components
- Take active part in Buildroot to secure investment in key components
- Extend with other Open Source components for system monitoring,
networking, etc. With the intent of upstreaming them to become parts
of Buildroot proper
- Rely on standards, i.e., use NETCONF and YANG
- When standards are not enough create models that fit well with Linux
and chosen Open Source components
- Keep as much as possible Open Source, no need to maintain stuff that
is not core business
- Secure boot by default
- Use RAUC for upgrades, it works
- Serve as a stand-alone(!) base for other projects that use Infix as
their Buildroot external -- this makes Infix a great layer for where
to publish used Open Source components and patches used in customer
projects
**Note:** projects derived from Infix (as a Buildroot external) will be
able to seamlessly extend the CLI with other models.
Short Term
----------
- Integrate Clixon and some well-chosen IETF/IEEE YANG models
(ietf-system, ietf-interfaces/ip)
- Get the (from YANG) automatically generated CLI working similar to
Cisco, HP ProCurve, and other well-known command line interfaces,
with a focus on usability
- First baseline release, from Buildroot 2023.02 (LTS) -> v23.6.0
Medium Term
-----------
- First Web interface built on top of RESTCONF API
- Static routing, firewalling, and other advanced YANG models
- OSPF YANG model integrated with Frr as backend
- Second release -> v23.10.0
Long Term
---------
- Not determined.
- Third release -> v24.6.0
+6
View File
@@ -1,9 +1,14 @@
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"
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"
source "$BR2_EXTERNAL_INFIX_PATH/package/mech/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/osal/Config.in"
@@ -13,6 +18,7 @@ source "$BR2_EXTERNAL_INFIX_PATH/package/python-templating/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/skeleton-init-finit/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/sysrepo-plugins-common/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/sysrepo-plugin-system/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/sysrest/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/tetris/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/umgmt/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/querierd/Config.in"
+5 -2
View File
@@ -68,9 +68,12 @@ endef
CLIXON_POST_INSTALL_TARGET_HOOKS += CLIXON_INSTALL_EXAMPLE
endif
define CLIXON_INSTALL_CLEANUP
define CLIXON_INSTALL_EXTRA
rm -rf $(TARGET_DIR)/var/clixon
ln -sf clixon_cli $(TARGET_DIR)/usr/bin/clish
grep -qsE '^/usr/bin/clish$$' "$(TARGET_DIR)/etc/shells" \
|| echo "/usr/bin/clish" >> "$(TARGET_DIR)/etc/shells"
endef
CLIXON_POST_INSTALL_TARGET_HOOKS += CLIXON_INSTALL_CLEANUP
CLIXON_POST_INSTALL_TARGET_HOOKS += CLIXON_INSTALL_EXTRA
$(eval $(autotools-package))
+10
View File
@@ -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.
+20
View File
@@ -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 dnsmasq getty klish lldpd nginx sysklogd sysrepo sysrest; 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
+24
View File
@@ -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))
+4
View File
@@ -0,0 +1,4 @@
#!/bin/sh
set -e
exit 0
+6
View File
@@ -0,0 +1,6 @@
run if:<boot/netconf> [S] /lib/infix/clean-etc --
run if:<boot/netconf> [S] /lib/infix/prep-db --
service if:<boot/netconf> name:sysrepo [12345789] sysrepo-plugind -n -- Configuration daemon
service if:<boot/netconf> name:netopeer [12345789] netopeer2-server -n -- NETCONF daemon
task if:<boot/netconf> [12345789] resolvconf -u -- Update DNS configuration
+1
View File
@@ -0,0 +1 @@
d /run/resolvconf/interfaces - - -
+7
View File
@@ -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/
+3
View File
@@ -0,0 +1,3 @@
# Locally calculated
sha256 9d9d33b873917ca5d0bdcc47a36d2fd385971ab0c045d1472fcadf95ee5bcf5b LICENCE
sha256 8e369f54c2da317030ff4cad905e501303d0489b98e4b208d0ff611b4484c94e faux-tags_2.1.0-br1.tar.gz
+15
View File
@@ -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))
+1 -1
View File
@@ -5,5 +5,5 @@ sha256 262d8cfea80d94e048e3f1b149f5d940b4579a38f2b7dba563cf4b0b497e7422 finit-
sha256 abdb9adbbc1faacc35c80bc2974c7d6b842e3e50b066d688385b5d21be86206f LICENSE
# Snapshot before 4.-rc1
sha256 ff6a16640b6dcee17be0bb810d92cf0ef081f5907d4555d74e58f52d2f0df954 finit-571250a9b98d6a924ca2ce704083e8dda881a4f2.tar.gz
sha256 2278adb4884495b784d8220f3dc0a1df88c3caf1e8bb222428f6eab3ed93b739 finit-c3ba15045b4336d3520dbeb068b68eafdf54e6c3.tar.gz
+1 -1
View File
@@ -14,7 +14,7 @@ FINIT_INSTALL_STAGING = YES
FINIT_D = $(TARGET_DIR)/etc/finit.d
# Create configure script using autoreconf when building from git
FINIT_VERSION = 571250a9b98d6a924ca2ce704083e8dda881a4f2
FINIT_VERSION = c3ba15045b4336d3520dbeb068b68eafdf54e6c3
FINIT_SITE = $(call github,troglobit,finit,$(FINIT_VERSION))
FINIT_AUTORECONF = YES
FINIT_DEPENDENCIES += host-automake host-autoconf host-libtool
+8
View File
@@ -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.
+14
View File
@@ -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))
+22
View File
@@ -0,0 +1,22 @@
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
depends on !BR2_PACKAGE_KLINFIX
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.
@@ -0,0 +1,4 @@
# Locally calculated
sha256 9d9d33b873917ca5d0bdcc47a36d2fd385971ab0c045d1472fcadf95ee5bcf5b LICENCE
sha256 515fa2a3c66b41d6ab5ec93d61cdd32097115b2f46e39c522659b84d555eebf5 klish-plugin-sysrepo-cdd3eb51a7f7ee0ed5bd925fa636061d3b1b85fb-br1.tar.gz
@@ -0,0 +1,25 @@
################################################################################
#
# klish-plugin-sysrepo
#
################################################################################
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
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))
+22
View File
@@ -0,0 +1,22 @@
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
depends on !BR2_PACKAGE_KLINFIX
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.
+35
View File
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<KLISH
xmlns="https://klish.libcode.org/klish3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://src.libcode.org/pkun/klish/src/master/klish.xsd">
<PLUGIN name="klish"/>
<ENTRY name="COMMAND" purpose="ptype">
<ENTRY name="completion" purpose="completion">
<ACTION sym="completion_COMMAND"/>
</ENTRY>
<ENTRY name="help" purpose="help">
<ACTION sym="completion_COMMAND"/>
</ENTRY>
<ACTION sym="COMMAND"/>
</ENTRY>
<ENTRY name="main" mode="switch" container="true">
<ENTRY name="prompt" purpose="prompt">
<ACTION sym="prompt">%u@%h&gt; </ACTION>
</ENTRY>
<ENTRY name="exit" help="Exit view">
<ENTRY name="COMMAND" purpose="ptype" ref="/COMMAND"/>
<ACTION sym="nav">pop</ACTION>
<ACTION sym="printl">Exiting klish session</ACTION>
</ENTRY>
<HOTKEY key="^Z" cmd="exit"/>
</ENTRY>
</KLISH>
+3
View File
@@ -0,0 +1,3 @@
# Locally calculated
sha256 9d9d33b873917ca5d0bdcc47a36d2fd385971ab0c045d1472fcadf95ee5bcf5b LICENCE
sha256 e7c09457ed0b030eddd8eaf7d9f7c9344c2fcd7ac2083f1d8ebeaafc4ed6dba6 klish-tags_3.0.0-br1.tar.gz
+46
View File
@@ -0,0 +1,46 @@
################################################################################
#
# 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
KLISH_CONF_OPTS += --with-libxml2
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))
+1
View File
@@ -0,0 +1 @@
service <!> [2345789] /usr/bin/klishd -d -- CLI backend
+1
View File
@@ -2,6 +2,7 @@ config BR2_PACKAGE_MECH
bool "mech"
select BR2_PACKAGE_CLIXON
select BR2_PACKAGE_AUGEAS
select BR2_PACKAGE_JANSSON
help
Orchestrate an Infix node using any of the front-ends
offered by Clixon, e.g. NETCONF, RESTCONF or SNMP.
@@ -7,7 +7,7 @@
# ... except for some core services
reserved()
{
for svc in clixon getty lldpd nginx sysklogd; do
for svc in clixon dnsmasq getty lldpd nginx sysklogd; do
[ "$1" = "${svc}.conf" ] && return 0
done
+1
View File
@@ -5,3 +5,4 @@ run if:<boot/netconf> name:clixon :boot log:prio:daemon.warning \
service if:<boot/netconf> name:clixon log:prio:daemon.warning \
[12345789] clixon_backend -F -l s -D 7 -s none -- Configuration daemon
task if:<boot/netconf> [12345789] resolvconf -u -- Update DNS configuration
+3
View File
@@ -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
+2 -1
View File
@@ -1 +1,2 @@
d /run/clixon - - -
d /run/clixon - - -
d /run/resolvconf/interfaces - - -
@@ -77,7 +77,7 @@ endif
ifeq ($(BR2_PACKAGE_FRR),y)
define SKELETON_INIT_FINIT_SET_FRR
for svc in babeld bfdd bgpd eigrpd isisd ldpd pathd ripd ripng static ospfd ospf6d vrrpd zebra; do \
for svc in babeld bfdd bgpd eigrpd isisd ldpd ospfd ospf6d pathd ripd ripng staticd vrrpd zebra; do \
cp $(SKELETON_INIT_FINIT_AVAILABLE)/frr/$$svc.conf $(FINIT_D)/available/$$svc.conf; \
done
ln -sf ../available/zebra.conf $(FINIT_D)/enabled/zebra.conf
@@ -1 +1 @@
service [2345] dnsmasq -k -- DHCP/DNS proxy
service [S12345789] dnsmasq -k -u root -- DHCP/DNS proxy
@@ -0,0 +1 @@
service [2345789] log:null <!pid/zebra> bfdd -A 127.0.0.1 -u frr -g frr -- BFD daemon
@@ -0,0 +1 @@
service [2345789] log:null <!pid/zebra> bgpd -A 127.0.0.1 -u frr -g frr -- BGP daemon
@@ -0,0 +1 @@
service [2345789] log:null <!pid/zebra> eigrpd -A 127.0.0.1 -u frr -g frr -- EIGRP daemon
@@ -0,0 +1 @@
service [2345789] log:null <!pid/zebra> ldpd -A 127.0.0.1 -u frr -g frr -- LDP daemon
@@ -0,0 +1 @@
service [2345789] log:null <!pid/zebra> pathd -A 127.0.0.1 -u frr -g frr -- PCEP daemon
@@ -0,0 +1 @@
service [2345789] log:null <!pid/zebra> pim6d -A 127.0.0.1 -u frr -g frr -- PIM6 daemon
@@ -0,0 +1 @@
service [2345789] log:null <!pid/zebra> pimd -A 127.0.0.1 -u frr -g frr -- PIM daemon
@@ -0,0 +1 @@
service [2345789] log:null <!pid/zebra> staticd -A 127.0.0.1 -u frr -g frr -- Static routing daemon
@@ -0,0 +1 @@
service [2345789] log:null <!pid/zebra> vrrpd -A 127.0.0.1 -u frr -g frr -- VRRP daemon
@@ -1,3 +1,2 @@
service if:<!boot/profinet> [2345789] log:prio:daemon.info,tag:lldpd \
<!> env:-/etc/default/lldpd \
service if:<!boot/profinet> [2345789] <!> env:-/etc/default/lldpd \
lldpd -d $LLDPD_ARGS -- LLDP daemon (IEEE 802.1ab)
+6
View File
@@ -0,0 +1,6 @@
config BR2_PACKAGE_SYSREST
bool "sysrest"
depends on BR2_PACKAGE_SYSREPO
select BR2_PACKAGE_LIBCFGI
help
RESTCONF front-end for Sysrepo
+1
View File
@@ -0,0 +1 @@
service if:<boot/netconf> [2345789] sysrest -- RESTCONF daemon
+20
View File
@@ -0,0 +1,20 @@
################################################################################
#
# sysrest
#
################################################################################
SYSREST_VERSION = 1.0
SYSREST_LICENSE = BSD-3-Clause
SYSREST_SITE_METHOD = local
SYSREST_SITE = $(BR2_EXTERNAL_INFIX_PATH)/src/sysrest
SYSREST_DEPENDENCIES = sysrepo libfcgi
SYSREST_AUTORECONF = YES
define SYSREST_INSTALL_EXTRA
cp $(SYSREST_PKGDIR)/sysrest.conf $(FINIT_D)/available/
ln -sf ../available/sysrest.conf $(FINIT_D)/enabled/sysrest.conf
endef
SYSREST_TARGET_FINALIZE_HOOKS += SYSREST_INSTALL_EXTRA
$(eval $(autotools-package))
@@ -0,0 +1,12 @@
diff -ru openresolv-3.12.0.orig/resolvconf.in openresolv-3.12.0/resolvconf.in
--- openresolv-3.12.0.orig/resolvconf.in 2020-12-27 19:05:10.000000000 +0100
+++ openresolv-3.12.0/resolvconf.in 2023-03-27 00:19:03.365164029 +0200
@@ -315,6 +315,8 @@
then
/usr/bin/systemctl restart $1.service
fi'
+ elif [ -x /sbin/initctl ]; then
+ RESTARTCMD="/sbin/initctl -bnq restart \$1"
elif [ -x /sbin/rc-service ] &&
{ [ -s /libexec/rc/init.d/softlevel ] ||
[ -s /run/openrc/softlevel ]; }
@@ -0,0 +1,16 @@
diff -ru openresolv-3.12.0.orig/resolvconf.in openresolv-3.12.0/resolvconf.in
--- openresolv-3.12.0.orig/resolvconf.in 2020-12-27 19:05:10.000000000 +0100
+++ openresolv-3.12.0/resolvconf.in 2023-03-27 00:19:03.365164029 +0200
@@ -315,6 +315,12 @@
then
/usr/bin/systemctl restart $1.service
fi'
+ elif [ -x /sbin/initctl ]; then
+ # Finit
+ RESTARTCMD='
+ if /sbin/initctl -bq status $1; then
+ /sbin/initctl -bnq restart $1
+ fi'
elif [ -x /sbin/rc-service ] &&
{ [ -s /libexec/rc/init.d/softlevel ] ||
[ -s /run/openrc/softlevel ]; }
@@ -0,0 +1,64 @@
commit 6fc440089353d76a9b8cb7c480402ee911a1387d
Author: Joachim Wiberg <troglobit@gmail.com>
Date: Tue Mar 28 10:37:53 2023 +0200
sysrepo-plugind: add support for running in foreground with syslog
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
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 <path>\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)) {
+33
View File
@@ -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
+28
View File
@@ -0,0 +1,28 @@
Copyright (c) 2020 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.
+3
View File
@@ -0,0 +1,3 @@
SUBDIRS = src yang
DISTCLEANFILES = *~ *.d
ACLOCAL_AMFLAGS = -I m4
+15
View File
@@ -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
+3
View File
@@ -0,0 +1,3 @@
#!/bin/sh
autoreconf -W portability -vifm
+55
View File
@@ -0,0 +1,55 @@
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([srpdplugindir], [sysrepo], [SRPD_PLUGINS_PATH])
AC_SUBST(srpdplugindir)
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)
YANGDIR=`eval echo $datarootdir/yang/modules/confd`
AC_SUBST(YANGDIR)
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
+9
View File
@@ -0,0 +1,9 @@
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_LDFLAGS = -module -avoid-version -shared
confd_plugin_la_SOURCES = ietf-system.c
+316
View File
@@ -0,0 +1,316 @@
/* Sysrepo plugin of ietf-system@2014-08-06.yang module */
#include <stdio.h>
#include <syslog.h>
#include <stdlib.h>
#include <string.h>
#include <sys/utsname.h>
#include <time.h>
#include <sys/time.h>
#include <errno.h>
#include <unistd.h>
/* Linux specific */
#include <sys/sysinfo.h>
#include <libyang/libyang.h>
#include <sysrepo.h>
#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 ": %s", __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, 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] = { 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));
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);
if (!*boottime) {
t = time(NULL) - get_uptime();
get_time_as_str(&t, 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));
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);
return SR_ERR_OK;
}
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;
int rc;
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:
ERROR("Failed building data tree, libyang error %d", rc);
return SR_ERR_INTERNAL;
}
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);
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);
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)
{
int rc;
DEBUG("path: %s", path);
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, 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;
time_t t;
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, uint32_t sub_id, const char *module,
const char *xpath, sr_event_t event,
unsigned request_id, void *priv)
{
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;
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) {
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)
{
sr_subscription_ctx_t *sub = NULL;
sr_conn_ctx_t *conn;
const 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@2014-08-06.yang", NULL, features);
rc = sr_oper_get_subscribe(sess, "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_,
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;
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;
}
*(sr_subscription_ctx_t **)priv = sub;
DEBUG("init ok");
return SR_ERR_OK;
err:
ERROR("init failed: %s", sr_strerror(rc));
sr_unsubscribe(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");
}
+2
View File
@@ -0,0 +1,2 @@
yangdir = $(YANGDIR)
yang_DATA = $(wildcard *.yang)
@@ -0,0 +1,120 @@
module iana-crypt-hash {
namespace "urn:ietf:params:xml:ns:yang:iana-crypt-hash";
prefix ianach;
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
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).
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 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";
}
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$<clear text password>
$<id>$<salt>$<password hash>
$<id>$<parameter>$<salt>$<password hash>
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 '$<id>$<salt>$' or
$<id>$<parameter>$<salt>$ is prepended to the result. This
value is stored in the configuration data store.
If a value starting with '$<id>$', where <id> 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-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-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)";
}
}
File diff suppressed because it is too large Load Diff
@@ -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: <https://datatracker.ietf.org/wg/netmod/>
WG List: <mailto:netmod@ietf.org>
Author: Martin Bjorklund
<mailto:mbj@tail-f.com>
Author: Juergen Schoenwaelder
<mailto:j.schoenwaelder@jacobs-university.de>
Author: Phil Shafer
<mailto:phil@juniper.net>
Author: Kent Watsen
<mailto:kwatsen@juniper.net>
Author: Rob Wilton
<rwilton@cisco.com>";
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.";
}
}
@@ -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: <http://tools.ietf.org/wg/netmod/>
WG List: <mailto:netmod@ietf.org>
WG Chair: David Kessens
<mailto:david.kessens@nsn.com>
WG Chair: Juergen Schoenwaelder
<mailto:j.schoenwaelder@jacobs-university.de>
Editor: Juergen Schoenwaelder
<mailto:j.schoenwaelder@jacobs-university.de>";
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 <http://www.iana.org/>.
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)";
}
}
File diff suppressed because it is too large Load Diff
+876
View File
@@ -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: <https://datatracker.ietf.org/wg/netmod/>
WG List: <mailto:netmod@ietf.org>
Editor: Martin Bjorklund
<mailto:mbj@tail-f.com>";
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";
}
}
}
}
}
@@ -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: <https://datatracker.ietf.org/wg/netconf/>
WG List: <mailto:netconf@ietf.org>
Author: Andy Bierman
<mailto:andy@yumaworks.com>
Author: Martin Bjorklund
<mailto:mbj@tail-f.com>";
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.";
}
}
}
}
}
+800
View File
@@ -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: <http://tools.ietf.org/wg/netmod/>
WG List: <mailto:netmod@ietf.org>
WG Chair: Thomas Nadeau
<mailto:tnadeau@lucidvision.com>
WG Chair: Juergen Schoenwaelder
<mailto:j.schoenwaelder@jacobs-university.de>
Editor: Andy Bierman
<mailto:andy@yumaworks.com>
Editor: Martin Bjorklund
<mailto:mbj@tail-f.com>";
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.";
}
}
@@ -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: <http://tools.ietf.org/wg/netmod/>
WG List: <mailto:netmod@ietf.org>
WG Chair: David Kessens
<mailto:david.kessens@nsn.com>
WG Chair: Juergen Schoenwaelder
<mailto:j.schoenwaelder@jacobs-university.de>
Editor: Juergen Schoenwaelder
<mailto:j.schoenwaelder@jacobs-university.de>";
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.";
}
}
+33
View File
@@ -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
+3
View File
@@ -0,0 +1,3 @@
SUBDIRS = src xml
DISTCLEANFILES = *~ *.d
ACLOCAL_AMFLAGS = -I m4
+74
View File
@@ -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 <src> <dst>` | Copy `<src>` to `<dst>` | |
| `exit` | Exit | `C-d` |
| `logout` | Alias for `exit` | |
| `shell` | Start system shell | |
| `show <item>` | Show various configuration and status | |
#### Copy Command
`copy <src> <dst>`
Where `<src>` is one of:
- `factory-config`
- `startup-config`
- `running-config`
And `<dst>` is one of:
- `startup-config`
- `running-config`
#### Show Command
`show <item>`
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` |
+3
View File
@@ -0,0 +1,3 @@
#!/bin/sh
autoreconf -W portability -vifm
+33
View File
@@ -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
+9
View File
@@ -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
+155
View File
@@ -0,0 +1,155 @@
#include <assert.h>
#include <stdio.h>
#include <sysrepo.h>
#include <sysrepo_types.h>
#include <klish/kplugin.h>
#include <klish/kcontext.h>
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;
}
+2
View File
@@ -0,0 +1,2 @@
klishconfdir = $(KLISHCONFDIR)
klishconf_DATA = $(wildcard *.xml)
+215
View File
@@ -0,0 +1,215 @@
<?xml version="1.0" encoding="UTF-8"?>
<KLISH
xmlns="https://klish.libcode.org/klish3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://src.libcode.org/pkun/klish/src/master/klish.xsd">
<PLUGIN name="klish"/>
<PLUGIN name="klinfix"/>
<PLUGIN name="script"/>
<PLUGIN name="sysrepo">
ShowBrackets = y
ShowSemicolons = y
FirstKeyWithStatement = n
MultiKeysWithStatement = y
Colorize = y
Indent = 2
</PLUGIN>
<PTYPE name="DATASTORE">
<COMPL>
<ACTION sym="printl">factory-config</ACTION>
<ACTION sym="printl">startup-config</ACTION>
<ACTION sym="printl">running-config</ACTION>
</COMPL>
<ACTION sym="STRING"/>
</PTYPE>
<PTYPE name="RW_DATASTORE">
<COMPL>
<ACTION sym="printl">startup-config</ACTION>
<ACTION sym="printl">running-config</ACTION>
</COMPL>
<ACTION sym="STRING"/>
</PTYPE>
<PTYPE name="PLINE_SET">
<COMPL>
<ACTION sym="srp_compl@sysrepo"/>
</COMPL>
<HELP>
<ACTION sym="srp_help@sysrepo"/>
</HELP>
<ACTION sym="PLINE_SET@sysrepo"/>
</PTYPE>
<PTYPE name="PLINE_DEL">
<COMPL>
<ACTION sym="srp_compl@sysrepo"/>
</COMPL>
<HELP>
<ACTION sym="srp_help@sysrepo"/>
</HELP>
<ACTION sym="PLINE_DEL@sysrepo"/>
</PTYPE>
<PTYPE name="PLINE_EDIT">
<COMPL>
<ACTION sym="srp_compl@sysrepo"/>
</COMPL>
<HELP>
<ACTION sym="srp_help@sysrepo"/>
</HELP>
<ACTION sym="PLINE_EDIT@sysrepo"/>
</PTYPE>
<PTYPE name="PLINE_INSERT_FROM">
<COMPL>
<ACTION sym="srp_compl@sysrepo"/>
</COMPL>
<HELP>
<ACTION sym="srp_help@sysrepo"/>
</HELP>
<ACTION sym="PLINE_INSERT_FROM@sysrepo"/>
</PTYPE>
<PTYPE name="PLINE_INSERT_TO">
<COMPL>
<ACTION sym="srp_compl_insert_to@sysrepo"/>
</COMPL>
<HELP>
<ACTION sym="srp_help_insert_to@sysrepo"/>
</HELP>
<ACTION sym="PLINE_INSERT_TO@sysrepo"/>
</PTYPE>
<VIEW name="main">
<HOTKEY key="^D" cmd="exit"/>
<PROMPT>
<ACTION sym="prompt" exec_on="always">%u@%h:exec> </ACTION>
</PROMPT>
<COMMAND name="shell" help="Enter system shell">
<ACTION sym="script" interactive="true">/bin/sh -l</ACTION>
</COMMAND>
<COMMAND name="exit" help="Exit">
<ACTION sym="nav">pop</ACTION>
</COMMAND>
<COMMAND name="logout" help="Alias for exit">
<ACTION sym="nav">pop</ACTION>
</COMMAND>
<COMMAND name="configure" help="Create new candidate-config based on running-config">
<ACTION sym="nav">replace configure</ACTION>
</COMMAND>
<COMMAND name="copy" help="Copy">
<PARAM name="src" ptype="/DATASTORE" help="Source datastore"/>
<PARAM name="dst" ptype="/RW_DATASTORE" help="Destination datastore"/>
<ACTION sym="klix_copy@klinfix"/>
</COMMAND>
<COMMAND name="show" help="Show" mode="switch">
<COMMAND name="running-config" help="Show running-config">
<ACTION sym="srp_show_running@sysrepo"/>
</COMMAND>
</COMMAND>
</VIEW>
<VIEW name="configure">
<PROMPT>
<ACTION sym="srp_prompt_edit_path@sysrepo"/>
<ACTION sym="prompt" exec_on="always">%u@%h:configure> </ACTION>
</PROMPT>
<HOTKEY key="^C" cmd="up"/>
<HOTKEY key="^D" cmd="abort"/>
<HOTKEY key="^Z" cmd="leave"/>
<!-- Move -->
<COMMAND name="abort" help="Abandon candidate">
<ACTION sym="srp_rollback@sysrepo"/>
<ACTION sym="nav">replace main</ACTION>
</COMMAND>
<COMMAND name="leave" help="Finalize candidate and apply to running-config">
<ACTION sym="klix_commit@klinfix"/>
<ACTION sym="nav" exec_on="success">replace main</ACTION>
</COMMAND>
<COMMAND name="exit" help="Ascend to the parent configuration node, or abort (from top)">
<ACTION sym="srp_up@sysrepo"/>
<ACTION sym="klix_commit@klinfix" exec_on="fail"/>
<ACTION sym="nav" exec_on="success">replace main</ACTION>
</COMMAND>
<COMMAND name="up" help="Ascend to the parent configuration node">
<ACTION sym="srp_up@sysrepo"/>
</COMMAND>
<COMMAND name="top" help="Ascend to the configuration root">
<ACTION sym="srp_top@sysrepo"/>
</COMMAND>
<COMMAND name="edit" help="Descend to the specified configuration node">
<PARAM name="path" ptype="/PLINE_EDIT" max="100"/>
<ACTION sym="srp_edit@sysrepo"/>
</COMMAND>
<!-- Edit -->
<COMMAND name="set" help="Set configuration setting">
<PARAM name="path" ptype="/PLINE_SET" max="100"/>
<ACTION sym="srp_set@sysrepo"/>
</COMMAND>
<COMMAND name="delete" help="Delete configuration setting(s)">
<PARAM name="path" ptype="/PLINE_DEL" max="100"/>
<ACTION sym="srp_del@sysrepo"/>
</COMMAND>
<COMMAND name="no" help="Alias for delete">
<PARAM name="path" ptype="/PLINE_DEL" max="100"/>
<ACTION sym="srp_del@sysrepo"/>
</COMMAND>
<COMMAND name="commit" help="Commit current candidate to running-config">
<ACTION sym="klix_commit@klinfix"/>
</COMMAND>
<COMMAND name="rollback" help="Restore candidate to running-config">
<ACTION sym="srp_rollback@sysrepo"/>
</COMMAND>
<!-- Display -->
<COMMAND name="check" help="Validate candidate">
<ACTION sym="srp_verify@sysrepo"/>
</COMMAND>
<COMMAND name="show" help="Show configuration">
<PARAM name="path" ptype="/PLINE_EDIT" min="0" max="100"/>
<ACTION sym="srp_show@sysrepo"/>
</COMMAND>
<COMMAND name="diff" help="Summarize uncommitted changes">
<PARAM name="path" ptype="/PLINE_EDIT" min="0" max="100"/>
<ACTION sym="srp_diff@sysrepo"/>
</COMMAND>
<!-- Misc -->
<COMMAND name="do" help="Execute operational mode command">
<VIEW name="operational" ref="/main"/>
</COMMAND>
</VIEW>
</KLISH>
+3 -2
View File
@@ -1,5 +1,6 @@
CFLAGS = -Wall -Wextra -Werror -Wno-unused-parameter
CPPFLAGS = -I$(top_srcdir)/include/
CPPFLAGS += -D_DEFAULT_SOURCE -D_XOPEN_SOURCE
clixonlibdir = $(libdir)/clixon
backenddir = $(clixonlibdir)/backend
@@ -16,7 +17,7 @@ yang_DATA =
cli_libadd = -lclixon -lclixon_cli
cli_ldflags = -module -avoid-version -shared
backend_cflags = $(CFLAGS) $(augeas_CFLAGS)
backend_libadd = $(augeas_LIBS) -lclixon -lclixon_backend ../common/common.la
backend_cflags = $(augeas_CFLAGS) $(jansson_CFLAGS) $(CFLAGS)
backend_libadd = $(augeas_LIBS) $(jansson_LIBS) -lclixon -lclixon_backend ../common/common.la
backend_ldflags = -module -avoid-version -shared
+1 -1
View File
@@ -22,7 +22,7 @@ AC_PROG_INSTALL
AC_CHECK_LIB([clixon], [yang_len_get],, AC_MSG_ERROR([Clixon not found]))
PKG_CHECK_MODULES([augeas], [augeas >= 1.12.0])
PKG_CHECK_MODULES([jansson], [jansson >= 2.0.0])
test "x$prefix" = xNONE && prefix=$ac_default_prefix
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+51 -7
View File
@@ -3,16 +3,17 @@ CLICON_MODE="exec";
CLICON_PROMPT="%U@%H:%w> ";
CLICON_PLUGIN="core-cli";
exit("Exit"), cli_quit();
# Autocli syntax tree operations, from clixon's "main" example
edit @datamodelmode, cli_auto_edit("basemodel");
up, cli_auto_up("basemodel");
top, cli_auto_top("basemodel");
edit @datamodelmode, cli_auto_edit("basemodel"); # XXX: remove in favor of configure
configure @datamodelmode, cli_auto_edit("basemodel"); # XXX: should edit 'native' candiate
up, cli_auto_up("basemodel"); # XXX: remove
end, cli_auto_up("basemodel");
top, cli_auto_top("basemodel"); # XXX: remove
leave, cli_auto_top("basemodel"); # XXX: should leave configure mode and validate candiate
set @datamodel, cli_auto_set();
merge @datamodel, cli_auto_merge();
create @datamodel, cli_auto_create();
delete("Delete a configuration item") {
no("Delete a configuration item") {
@datamodel, cli_auto_del();
all("Delete whole candidate configuration"), delete_all("candidate");
}
@@ -33,12 +34,45 @@ copy("Copy and create a new object") {
}
}
debug("Debugging parts of the system"){
cli("Set cli debug") <level:int32>("Set debug level (0..n)"), cli_debug_cli();
backend("Set backend debug") <level:int32>("Set debug level (0..n)"), cli_debug_backend();
restconf("Set restconf debug") <level:int32>("Set debug level (0..n)"), cli_debug_restconf();
}
discard("Discard edits (rollback 0)"), discard_changes();
exit("Exit"), cli_quit();
quit("Exit"), hide, cli_quit();
follow("Continuously monitor a log file, default syslog"), cli_exec_log(); {
<fn:string logfiles()>(""), cli_exec_log();
}
help("Show help"), cli_help();
load("Load configuration from XML file") <filename:string>("Filename (local filename)"),load_config_file("filename", "replace");{
replace("Replace candidate with file contents"), load_config_file("filename", "replace");{
cli("Replace candidate with file containing CLI commands"), load_config_file("filename", "replace", "cli");
xml("Replace candidate with file containing XML"), load_config_file("filename", "replace", "xml");
json("Replace candidate with file containing JSON"), load_config_file("filename", "replace", "json");
text("Replace candidate with file containing TEXT"), load_config_file("filename", "replace", "text");
}
merge("Merge file with existent candidate"), load_config_file("filename", "merge");{
cli("Merge candidate with file containing CLI commands"), load_config_file("filename", "merge", "cli");
xml("Merge candidate with file containing XML"), load_config_file("filename", "merge", "xml");
json("Merge candidate with file containing JSON"), load_config_file("filename", "merge", "json");
text("Merge candidate with file containing TEXT"), load_config_file("filename", "merge", "text");
}
}
save("Save candidate configuration to XML file") <filename:string>("Filename (local filename)"), save_config_file("candidate","filename", "xml");{
cli("Save configuration as CLI commands"), save_config_file("candidate","filename", "cli");
xml("Save configuration as XML"), save_config_file("candidate","filename", "xml");
json("Save configuration as JSON"), save_config_file("candidate","filename", "json");
text("Save configuration as TEXT"), save_config_file("candidate","filename", "text");
netconf("Save configuration as NETCONF"), save_config_file("candidate","filename", "netconf");
}
show("Show various system state and configuration") {
system-information("System information"), cli_exec_show();
fdb("Show forwarding database (unicast)"), cli_exec_show();
@@ -59,6 +93,11 @@ show("Show various system state and configuration") {
cli @datamodelshow, cli_show_auto("candidate", "cli", true, false, "report-all", "set ");
}
compare("Compare candidate and running databases"), compare_dbs((int32)0);{
xml("Show comparison in xml"), compare_dbs((int32)0);
text("Show comparison in text"), compare_dbs((int32)1);
}
configuration("Show configuration"), cli_show_auto_mode("candidate", "text", true, false); {
xml("Show configuration as XML"), cli_show_auto_mode("candidate", "xml", true, false); {
default("With-default mode") {
@@ -87,7 +126,12 @@ show("Show various system state and configuration") {
}
}
}
yang("Show yang specs"), show_yang(); {
clixon-example("Show clixon-example yang spec"), show_yang("clixon-example");
}
}
# Hidden shell command, after 'show' command to avoid any possible completion problems
shell("Start domain shell"), hide, cli_exec_shell();
shell("Start domain shell"), hide, cli_exec_shell();{
<source:rest>("Single shell command"), cli_exec_shell();
}
+144 -27
View File
@@ -1,6 +1,8 @@
/* SPDX-License-Identifier: Apache-2.0 */
#include <ctype.h>
#include <errno.h>
#include <jansson.h>
#include <stdio.h>
#include <syslog.h>
#include <unistd.h>
@@ -26,77 +28,79 @@ int ietf_if_tr_begin(clicon_handle h, transaction_data td)
return 0;
}
void sysfs_net_write(char *ifname, char *fn, char *data)
{
char filename[128];
FILE *fp;
snprintf(filename, sizeof(filename), "/sys/class/net/%s/%s", ifname, fn);
fp = fopen(filename, "w");
if (!fp) {
clicon_log(LOG_WARNING, "ietf-interfaces: failed writing '%s' to %s: %s",
data, filename, strerror(errno));
return;
}
fprintf(fp, "%s\n", data);
fclose(fp);
}
int ietf_if_tr_commit_interface(cxobj *src, cxobj *tgt)
{
const char *fmt = "/etc/network/interfaces.d/%s.conf";
cxobj *obj, *iface = NULL;
if (!tgt) {
clicon_log(LOG_NOTICE, "No tgt, removing all network settings!");
clicon_log(LOG_DEBUG, "ietf-interfaces: no tgt, removing all network settings!");
return system("rm -f /etc/network/interfaces.d/*");
}
clicon_log(LOG_NOTICE, "Let's find some interfaces!");
while ((iface = xml_child_each(tgt, iface, CX_ELMNT))) {
char *ifname, *addr, *len;
char *ifname, *addr, *len, *desc = NULL;
char cmd[128], fn[60];
cxobj *ip, *address;
FILE *fp;
clicon_log(LOG_NOTICE, "Found something ...");
if (strcmp(xml_name(iface), "interface")) {
clicon_log(LOG_NOTICE, "Not an interface ...");
continue;
}
clicon_log(LOG_NOTICE, "An interface!");
obj = xml_find(iface, "name");
if (!obj) {
clicon_log(LOG_NOTICE, "No name!");
if (!obj)
continue;
}
ifname = xml_body(obj);
clicon_log(LOG_NOTICE, "iface %s", ifname);
snprintf(fn, sizeof(fn), fmt, ifname);
clicon_log(LOG_NOTICE, "fn %s", fn);
if (!is_true(iface, "enabled")) {
clicon_log(LOG_NOTICE, "%s not enabled", ifname);
delete:
clicon_log(LOG_NOTICE, "deletinf %s", fn);
snprintf(cmd, sizeof(cmd), "rm -f %s", fn);
system(cmd);
continue;
}
obj = xml_find(iface, "description");
if (obj)
desc = xml_body(obj);
ip = xml_find(iface, "ipv4");
if (!ip || !is_true(ip, "enabled")) {
clicon_log(LOG_NOTICE, "no ipv4 or not enabled");
if (!ip || !is_true(ip, "enabled"))
goto delete;
}
/* XXX: iterate over address, may be more than one */
address = xml_find(ip, "address");
if (!address) {
clicon_log(LOG_NOTICE, "no address");
if (!address)
goto delete;
}
obj = xml_find(address, "ip");
if (!obj) {
clicon_log(LOG_NOTICE, "no address/ip");
if (!obj)
goto delete;
}
addr = xml_body(obj);
clicon_log(LOG_NOTICE, "address %s", addr);
obj = xml_find(address, "prefix-length");
if (!obj) {
clicon_log(LOG_NOTICE, "no address/plen");
if (!obj)
goto delete;
}
len = xml_body(obj);
clicon_log(LOG_NOTICE, "address %s/%s", addr, len);
fp = fopen(fn, "w");
if (!fp) {
@@ -107,6 +111,8 @@ int ietf_if_tr_commit_interface(cxobj *src, cxobj *tgt)
fprintf(fp, "iface %s inet static\n"
" address %s/%s\n", ifname, addr, len);
fclose(fp);
sysfs_net_write(ifname, "ifalias", desc ?: "");
}
return 0;
@@ -119,7 +125,7 @@ int ietf_if_tr_commit(clicon_handle h, transaction_data td)
int slen = 0, tlen = 0, err = -EINVAL;
cxobj **ssys, **tsys;
show_transaction("ietf-interfaces", td, true);
// show_transaction("ietf-interfaces", td, true);
if (src && clixon_xml_find_instance_id(src, yspec, &ssys, &slen,
"/if:interfaces") < 0)
@@ -138,12 +144,123 @@ err:
return err;
}
/* Verify obj is a string and then lowercase print it in fmt */
void cprint_xml_string(cbuf *cb, const char *fmt, json_t *obj, const char *key)
{
json_t *val;
char *str;
val = json_object_get(obj, key);
if (!val || !json_is_string(val))
return;
str = strdup(json_string_value(val));
if (!str)
return;
for (size_t i = 0; i < strlen(str); i++)
str[i] = tolower(str[i]);
cprintf(cb, fmt, str);
free(str);
}
void cprint_ifdata(cbuf *cb, char *ifname)
{
json_t *root = NULL, *obj;
json_error_t error;
FILE *fp = NULL;
char cmd[128];
size_t len;
char *buf;
buf = malloc(BUFSIZ);
if (!buf)
goto err;
snprintf(cmd, sizeof(cmd), "ip -j -p link show %s", ifname);
fp = popen(cmd, "r");
if (!fp)
goto err;
len = fread(buf, 1, 4096, fp);
if (len == 0 || ferror(fp))
goto err;
root = json_loadb(buf, len, 0, &error);
if (!root)
goto err;
if (!json_is_array(root)) {
if (!json_is_object(root))
goto err;
obj = root;
} else
obj = json_array_get(root, 0);
cprintf(cb,
"<interface xmlns:ex=\"urn:example:clixon\">\n"
" <name>%s</name>\n"
" <type>ex:eth</type>\n", ifname);
cprint_xml_string(cb, " <phys-address>%s</phys-address>\n", obj, "address");
cprint_xml_string(cb, " <oper-status>%s</oper-status>\n", obj, "operstate");
cprintf(cb, "</interface>");
err:
if (root)
json_decref(root);
if (fp)
pclose(fp);
if (buf)
free(buf);
}
int ietf_if_statedata(clicon_handle h, cvec *nsc, char *xpath, cxobj *xstate)
{
cxobj **xvec = NULL;
size_t xlen = 0;
cbuf *cb = NULL;
cxobj *xt = NULL;
cvec *nsc1 = NULL;
int rc = -1;
if ((cb = cbuf_new()) == NULL) {
clicon_err(OE_UNIX, errno, "cbuf_new");
goto done;
}
if ((nsc1 = xml_nsctx_init(NULL, "urn:ietf:params:xml:ns:yang:ietf-interfaces")) == NULL)
goto done;
if (xmldb_get0(h, "running", YB_MODULE, nsc1, "/interfaces/interface/name", 1, 0, &xt, NULL, NULL) < 0)
goto done;
if (xpath_vec(xt, nsc1, "/interfaces/interface/name", &xvec, &xlen) < 0)
goto done;
if (xlen) {
cprintf(cb, "<interfaces xmlns=\"urn:ietf:params:xml:ns:yang:ietf-interfaces\">");
for (size_t i = 0; i < xlen; i++)
cprint_ifdata(cb, xml_body(xvec[i]));
cprintf(cb, "</interfaces>");
if (clixon_xml_parse_string(cbuf_get(cb), YB_NONE, NULL, &xstate, NULL) < 0)
goto done;
}
rc = 0;
done:
if (nsc1)
xml_nsctx_free(nsc1);
if (xt)
xml_free(xt);
if (cb)
cbuf_free(cb);
if (xvec)
free(xvec);
return rc;
}
static clixon_plugin_api ietf_interfaces_api = {
.ca_name = "ietf-interfaces",
.ca_init = clixon_plugin_init,
.ca_trans_begin = ietf_if_tr_begin,
.ca_trans_commit = ietf_if_tr_commit,
.ca_statedata = ietf_if_statedata,
};
clixon_plugin_api *clixon_plugin_init(clicon_handle h)
+368 -30
View File
@@ -1,14 +1,79 @@
/* SPDX-License-Identifier: Apache-2.0 */
#include <augeas.h>
#include <ctype.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <sys/utsname.h>
#include <sys/sysinfo.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#include "common.h"
#define XMLNS "urn:ietf:params:xml:ns:yang:ietf-system"
static augeas *aug;
static char *ver = NULL;
static char *rel = NULL;
static char *sys = NULL;
static char *os = NULL;
/**
* 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;
}
// clicon_debug(LOG_ERR, "ietf-system:run(%s) => %d", cmd, rc);
return rc;
}
static bool is_true(cxobj *xp, char *name)
{
@@ -24,9 +89,23 @@ static bool is_true(cxobj *xp, char *name)
return false;
}
static char *get_str(cxobj *xp, char *name)
{
cxobj *obj;
if (!xp || !name)
return NULL;
obj = xml_find(xp, name);
if (obj)
return xml_body(obj);
return NULL;
}
static int sys_reload_services(void)
{
return system("initctl -nbq touch sysklogd lldpd");
return run("initctl -nbq touch sysklogd lldpd");
}
int ietf_sys_tr_begin(clicon_handle h, transaction_data td)
@@ -92,7 +171,7 @@ int ietf_sys_tr_commit_clock(cxobj *src, cxobj *tgt)
timezone = xml_body(obj);
snprintf(cmd, sizeof(cmd), "cp /usr/share/zoneinfo/%s /etc/localtime", timezone);
if (system(cmd)) {
if (run(cmd)) {
clicon_log(LOG_WARNING, "ietf-system: failed setting timezone %s", timezone);
return -1;
}
@@ -172,11 +251,88 @@ int ietf_sys_tr_commit_ntp(cxobj *src, cxobj *tgt)
* If chrony is alrady enabled we tell Finit it's been
* modified , so Finit restarts it, otherwise enable it.
*/
system("initctl -nbq touch chronyd");
return system("initctl -nbq enable chronyd");
run("initctl -nbq touch chronyd");
return run("initctl -nbq enable chronyd");
}
disable:
return system("initctl -nbq disable chronyd");
return run("initctl -nbq disable chronyd");
}
/*
* dnsmasq is the resolver, it gets its nameservers from various
* sources: static, dhcp, vpn, via the resolvconf wrapper.
*/
int ietf_sys_tr_commit_dns(cxobj *src, cxobj *tgt)
{
const char *fn = "/etc/resolv.conf.head";
cxobj *obj, *opt = NULL, *srv = NULL;
int first = 1, valid = 0;
FILE *fp;
clicon_log(LOG_ERR, "ietf-system: dns src %p tgt %p", src, tgt);
if (!tgt)
goto disable;
fp = fopen(fn, "w");
if (!fp) {
clicon_log(LOG_WARNING, "ietf-system: failed updating %s: %s", fn, strerror(errno));
return -1;
}
obj = xml_find(tgt, "options");
if (obj) {
char *str;
fprintf(fp, "options");
str = get_str(obj, "timeout");
if (str)
fprintf(fp, " timeout:%s", str);
str = get_str(obj, "attempts");
if (str)
fprintf(fp, " attempts:%s ", str);
fprintf(fp, "\n");
}
while ((opt = xml_child_each(tgt, opt, CX_ELMNT))) {
if (strcmp(xml_name(opt), "search"))
continue;
if (first) {
fprintf(fp, "search ");
first = 0;
}
fprintf(fp, "%s ", xml_body(opt));
}
if (!first)
fprintf(fp, "\n");
while ((srv = xml_child_each(tgt, srv, CX_ELMNT))) {
cxobj *tmp;
if (strcmp(xml_name(srv), "server"))
continue;
tmp = xml_find(srv, "udp-and-tcp");
if (tmp) {
obj = xml_find(tmp, "address");
if (obj) {
fprintf(fp, "nameserver %s\n", xml_body(obj));
valid++;
}
}
}
fclose(fp);
disable:
if (!valid)
remove(fn);
if (run("initctl cond get hook/sys/up")) {
clicon_log(LOG_ERR, "ietf-system: failed cond get hook/sys/up");
return 0;
}
clicon_log(LOG_ERR, "ietf-status: calling resolvconf -u");
return run("resolvconf -u");
}
int ietf_sys_tr_commit(clicon_handle h, transaction_data td)
@@ -186,8 +342,7 @@ int ietf_sys_tr_commit(clicon_handle h, transaction_data td)
int slen = 0, tlen = 0, err = -EINVAL;
cxobj **ssys, **tsys;
show_transaction("ietf-system", td, true);
// show_transaction("ietf-system", td, true);
if (src && clixon_xml_find_instance_id(src, yspec, &ssys, &slen,
"/sys:system") < 0)
goto err;
@@ -205,33 +360,214 @@ int ietf_sys_tr_commit(clicon_handle h, transaction_data td)
tlen ? xml_find(tsys[0], "clock") : NULL);
if (err)
goto err;
err = ietf_sys_tr_commit_ntp(slen ? xml_find(ssys[0], "ntp") : NULL,
tlen ? xml_find(tsys[0], "ntp") : NULL);
if (err)
goto err;
err = ietf_sys_tr_commit_dns(slen ? xml_find(ssys[0], "dns-resolver") : NULL,
tlen ? xml_find(tsys[0], "dns-resolver") : NULL);
if (err)
goto err;
err:
err = err ? : aug_save(aug);
return err;
}
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)
{
const char *isofmt = "%FT%T%z";
struct tm tm;
size_t i, n;
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] = ':';
}
return buf;
}
int ietf_sys_statedata(clicon_handle h, cvec *nsc, char *xpath, cxobj *xstate)
{
struct sysinfo si;
time_t now, boot;
char buf[42];
cbuf *cb;
int rc;
cb = cbuf_new();
if (!cb) {
clicon_err(OE_UNIX, errno, "ietf-system:cbuf_new");
return -1;
}
tzset();
sysinfo(&si);
now = time(NULL);
boot = now - si.uptime;
cprintf(cb, "<system-state xmlns=\"%s\">", XMLNS);
cprintf(cb, " <platform>\n");
cprintf(cb, " <os-name>%s</os-name>\n", os);
cprintf(cb, " <os-version>%s</os-version>\n", ver);
if (rel)
cprintf(cb, " <os-release>%s</os-release>\n", rel);
cprintf(cb, " <machine>%s</machine>\n", sys);
cprintf(cb, " </platform>\n");
cprintf(cb, " <clock>\n");
cprintf(cb, " <current-datetime>%s</current-datetime>\n", fmtime(now, buf, sizeof(buf)));
cprintf(cb, " <boot-datetime>%s</boot-datetime>\n", fmtime(boot, buf, sizeof(buf)));
cprintf(cb, " </clock>\n");
cprintf(cb, "</system-state>");
rc = clixon_xml_parse_string(cbuf_get(cb), YB_NONE, NULL, &xstate, NULL) < 0 ? -1 : 0;
cbuf_free(cb);
return rc;
}
static int set_datetime(cxobj *xe)
{
const char *isofmt = "%FT%T%z";
struct timeval tv;
struct tm tm;
char tz[24];
int rc = -1;
cxobj *obj;
char *buf;
size_t n;
obj = xml_find(xe, "current-datetime");
if (!obj)
return 0;
buf = strdup(xml_body(obj));
if (!buf)
return -1;
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";
memset(&tm, 0, sizeof(tm));
if (!strptime(buf, isofmt, &tm)) {
clicon_log(LOG_WARNING, "ietf-system:failed strptime: %s", strerror(errno));
goto done;
}
snprintf(tz, sizeof(tz), "UTC%s%ld", tm.tm_gmtoff > 0 ? "+" : "", tm.tm_gmtoff / 3600);
setenv("TZ", tz, 1);
// clicon_log(LOG_ERR, "time %s gmtoff %ld TZ=%s", buf, tm.tm_gmtoff, tz);
tv.tv_sec = mktime(&tm);
tv.tv_usec = 0;
if (settimeofday(&tv, NULL)) {
clicon_log(LOG_WARNING, "ietf-system:failed settimeofday: %s", strerror(errno));
goto done;
}
rc = 0;
done:
unsetenv("TZ");
free(buf);
return rc;
}
static int do_rpc(clicon_handle h, /* Clicon handle */
cxobj *xe, /* Request: <rpc><xn></rpc> */
cbuf *cbret, /* Reply eg <rpc-reply>... */
void *arg, /* client_entry */
void *regarg) /* Argument given at register */
{
char *namespace = NETCONF_BASE_NAMESPACE;
char *namespace;
char *op;
// if ((namespace = xml_find_type_value(xe, NULL, "xmlns", CX_ATTR)) == NULL){
// clicon_err(OE_XML, ENOENT, "No namespace given in RPC %s", xml_name(xe));
// return -1;
// }
if ((namespace = xml_find_type_value(xe, NULL, "xmlns", CX_ATTR)) == NULL) {
clicon_err(OE_XML, ENOENT, "No namespace given in RPC %s", xml_name(xe));
return -1;
}
if (strcmp(namespace, XMLNS))
return 0; /* not for us */
cprintf(cbret, "<rpc-reply xmlns=\"%s\"><ok/></rpc-reply>", namespace);
if (regarg && !strcmp(regarg, "system-shutdown"))
return system("poweroff");
cprintf(cbret, "<rpc-reply xmlns=\"%s\"><ok/></rpc-reply>", NETCONF_BASE_NAMESPACE);
return system("reboot");
op = xml_name(xe);
if (!strcmp(op, "set-current-datetime"))
return set_datetime(xe);
if (!strcmp(op, "system-shutdown"))
return run("poweroff");
if (!strcmp(op, "system-restart"))
return run("reboot");
return 0;
}
static clixon_plugin_api ietf_system_api = {
@@ -240,10 +576,23 @@ static clixon_plugin_api ietf_system_api = {
.ca_trans_begin = ietf_sys_tr_begin,
.ca_trans_commit = ietf_sys_tr_commit,
.ca_statedata = ietf_sys_statedata,
};
static void register_rpc(clicon_handle h, const char *rpc)
{
int rc;
rc = rpc_callback_register(h, do_rpc, NULL, XMLNS, rpc);
if (rc < 0)
clicon_err(OE_PLUGIN, EINVAL, "ietf-system: failed registering RPC %s", rpc);
}
clixon_plugin_api *clixon_plugin_init(clicon_handle h)
{
os_init();
aug = aug_init(NULL, "", 0);
if (!aug ||
aug_load_file(aug, "/etc/hostname") ||
@@ -253,20 +602,9 @@ clixon_plugin_api *clixon_plugin_init(clicon_handle h)
return NULL;
}
if (rpc_callback_register(h, do_rpc, NULL,
"urn:ietf:params:xml:ns:yang:ietf-system",
"system-restart") < 0) {
clicon_err(OE_PLUGIN, EINVAL,
"ietf-system: failed registering RPC callback");
return NULL;
}
if (rpc_callback_register(h, do_rpc, NULL,
"urn:ietf:params:xml:ns:yang:ietf-system",
"system-shutdown") < 0) {
clicon_err(OE_PLUGIN, EINVAL,
"ietf-system: failed registering RPC callback");
return NULL;
}
register_rpc(h, "set-current-datetime");
register_rpc(h, "system-restart");
register_rpc(h, "system-shutdown");
return &ietf_system_api;
}
+33
View File
@@ -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
+25
View File
@@ -0,0 +1,25 @@
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.
+3
View File
@@ -0,0 +1,3 @@
SUBDIRS = src
DISTCLEANFILES = *~ *.d
ACLOCAL_AMFLAGS = -I m4
+15
View File
@@ -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
+3
View File
@@ -0,0 +1,3 @@
#!/bin/sh
autoreconf -W portability -vifm
+51
View File
@@ -0,0 +1,51 @@
AC_PREREQ(2.61)
AC_INIT([sysrest], [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
])
AC_PROG_CC
AC_PROG_INSTALL
# Check for pkg-config first, warn if it's not installed
PKG_PROG_PKG_CONFIG
PKG_CHECK_MODULES([fcgi], [fcgi >= 2.4.2])
PKG_CHECK_MODULES([sysrepo], [sysrepo >= 2.2.36])
PKG_CHECK_MODULES([libyang], [libyang >= 2.1.55])
# Plugin installation path for sysrepo-plugind
dnl PKG_CHECK_VAR([srpdplugindir], [sysrepo], [SRPD_PLUGINS_PATH])
dnl AC_SUBST(srpdplugindir)
dnl test "x$prefix" = xNONE && prefix=$ac_default_prefix
dnl test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
dnl DATAROOTDIR=`eval echo $datarootdir`
dnl DATAROOTDIR=`eval echo $DATAROOTDIR`
dnl AC_SUBST(DATAROOTDIR)
dnl LIBDIR=`eval echo $libdir`
dnl LIBDIR=`eval echo $LIBDIR`
dnl AC_SUBST(LIBDIR)
dnl LOCALSTATEDIR=`eval echo $localstatedir`
dnl LOCALSTATEDIR=`eval echo $LOCALSTATEDIR`
dnl AC_SUBST(LOCALSTATEDIR)
dnl RUNSTATEDIR=`eval echo $runstatedir`
dnl RUNSTATEDIR=`eval echo $RUNSTATEDIR`
dnl AC_SUBST(RUNSTATEDIR)
dnl SYSCONFDIR=`eval echo $sysconfdir`
dnl SYSCONFDIR=`eval echo $SYSCONFDIR`
dnl AC_SUBST(SYSCONFDIR)
AC_OUTPUT

Some files were not shown because too many files have changed in this diff Show More