mirror of
https://github.com/kernelkit/infix.git
synced 2026-07-22 09:13:01 +02:00
Compare commits
45
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
964a4c755e | ||
|
|
7eec8c2964 | ||
|
|
e729c82c32 | ||
|
|
abd001f57d | ||
|
|
cfef79bbf9 | ||
|
|
3cce1e6427 | ||
|
|
d66dc16600 | ||
|
|
24a1eb542d | ||
|
|
708b756eba | ||
|
|
3bbc5c49cd | ||
|
|
41db19ffaa | ||
|
|
1907bd6a75 | ||
|
|
d1444b900a | ||
|
|
737f99e35e | ||
|
|
b549ddd88a | ||
|
|
5d8e0ec123 | ||
|
|
fdfcac70eb | ||
|
|
7a69c21e9d | ||
|
|
b1be357a41 | ||
|
|
767296e830 | ||
|
|
91d67e6b00 | ||
|
|
8e03114518 | ||
|
|
546a2f3afb | ||
|
|
aa3d8945b9 | ||
|
|
d7b032cee7 | ||
|
|
f5a863df04 | ||
|
|
0cfd0fcd89 | ||
|
|
81c9398a19 | ||
|
|
eed61988d1 | ||
|
|
fe20f4a470 | ||
|
|
ac7b9073a5 | ||
|
|
aec2514eae | ||
|
|
a5258d7102 | ||
|
|
4acaa170e4 | ||
|
|
688c0ce2f7 | ||
|
|
2ff4f869fa | ||
|
|
cdb68cb611 | ||
|
|
8cff15e215 | ||
|
|
b25a374409 | ||
|
|
35b0880e7b | ||
|
|
80f57d0809 | ||
|
|
89d08338ce | ||
|
|
2abb0a5eb9 | ||
|
|
4730f3fe09 | ||
|
|
ec7d72c4c5 |
@@ -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
@@ -1,3 +1,3 @@
|
||||
[submodule "buildroot"]
|
||||
path = buildroot
|
||||
url = https://github.com/buildroot/buildroot.git
|
||||
url = ../buildroot.git
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
+1
-1
Submodule buildroot updated: 8cca1e6de1...3790a1f4b6
@@ -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
|
||||
|
||||
@@ -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
@@ -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"}}'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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.
|
||||
Executable
+20
@@ -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
|
||||
@@ -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))
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
exit 0
|
||||
@@ -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
|
||||
@@ -0,0 +1 @@
|
||||
d /run/resolvconf/interfaces - - -
|
||||
@@ -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/
|
||||
@@ -0,0 +1,3 @@
|
||||
# Locally calculated
|
||||
sha256 9d9d33b873917ca5d0bdcc47a36d2fd385971ab0c045d1472fcadf95ee5bcf5b LICENCE
|
||||
sha256 8e369f54c2da317030ff4cad905e501303d0489b98e4b208d0ff611b4484c94e faux-tags_2.1.0-br1.tar.gz
|
||||
@@ -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))
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
@@ -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))
|
||||
@@ -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))
|
||||
@@ -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.
|
||||
@@ -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> </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>
|
||||
@@ -0,0 +1,3 @@
|
||||
# Locally calculated
|
||||
sha256 9d9d33b873917ca5d0bdcc47a36d2fd385971ab0c045d1472fcadf95ee5bcf5b LICENCE
|
||||
sha256 e7c09457ed0b030eddd8eaf7d9f7c9344c2fcd7ac2083f1d8ebeaafc4ed6dba6 klish-tags_3.0.0-br1.tar.gz
|
||||
@@ -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))
|
||||
@@ -0,0 +1 @@
|
||||
service <!> [2345789] /usr/bin/klishd -d -- CLI backend
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1 @@
|
||||
service if:<boot/netconf> [2345789] sysrest -- RESTCONF daemon
|
||||
@@ -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)) {
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
SUBDIRS = src yang
|
||||
DISTCLEANFILES = *~ *.d
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
@@ -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
|
||||
Executable
+3
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
autoreconf -W portability -vifm
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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");
|
||||
}
|
||||
@@ -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
@@ -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.";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.";
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
SUBDIRS = src xml
|
||||
DISTCLEANFILES = *~ *.d
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
@@ -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` |
|
||||
Executable
+3
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
autoreconf -W portability -vifm
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
klishconfdir = $(KLISHCONFDIR)
|
||||
klishconf_DATA = $(wildcard *.xml)
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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}'
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
SUBDIRS = src
|
||||
DISTCLEANFILES = *~ *.d
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
@@ -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
|
||||
Executable
+3
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
autoreconf -W portability -vifm
|
||||
@@ -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
Reference in New Issue
Block a user