mirror of
https://github.com/kernelkit/infix.git
synced 2026-07-22 09:13:01 +02:00
Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
226ea49e7c | ||
|
|
cb633a78d6 | ||
|
|
d2e55eadf8 | ||
|
|
70d51420c9 | ||
|
|
1e80b20856 | ||
|
|
918353dcc7 | ||
|
|
d53a35b867 | ||
|
|
331f60be64 |
+15
-32
@@ -99,7 +99,20 @@
|
||||
{
|
||||
"name": "wan",
|
||||
"type": "infix-if-type:ethernet",
|
||||
"ietf-ip:ipv6": {}
|
||||
"ietf-ip:ipv6": {},
|
||||
"ietf-ip:ipv4": {
|
||||
"infix-dhcp-client:dhcp": {
|
||||
"option": [
|
||||
{"id": "ntp-server"},
|
||||
{"id": "broadcast"},
|
||||
{"id": "domain"},
|
||||
{"id": "hostname"},
|
||||
{"id": "dns-server"},
|
||||
{"id": "router"},
|
||||
{"id": "netmask"}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "wifi0",
|
||||
@@ -221,36 +234,6 @@
|
||||
},
|
||||
"infix-system:motd-banner": "Li0tLS0tLS0uCnwgIC4gLiAgfCBJbmZpeCBPUyDigJQgSW1tdXRhYmxlLkZyaWVuZGx5LlNlY3VyZQp8LS4gdiAuLXwgaHR0cHM6Ly9rZXJuZWxraXQub3JnCictJy0tLSctJwo="
|
||||
},
|
||||
"infix-dhcp-client:dhcp-client": {
|
||||
"client-if": [
|
||||
{
|
||||
"if-name": "wan",
|
||||
"option": [
|
||||
{
|
||||
"id": "ntp-server"
|
||||
},
|
||||
{
|
||||
"id": "broadcast"
|
||||
},
|
||||
{
|
||||
"id": "domain"
|
||||
},
|
||||
{
|
||||
"id": "hostname"
|
||||
},
|
||||
{
|
||||
"id": "dns-server"
|
||||
},
|
||||
{
|
||||
"id": "router"
|
||||
},
|
||||
{
|
||||
"id": "netmask"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"infix-dhcp-server:dhcp-server": {
|
||||
"option": [
|
||||
{
|
||||
@@ -311,7 +294,7 @@
|
||||
]
|
||||
},
|
||||
"infix-meta:meta": {
|
||||
"version": "1.5"
|
||||
"version": "1.6"
|
||||
},
|
||||
"infix-services:mdns": {
|
||||
"enabled": true
|
||||
|
||||
+15
-32
@@ -58,7 +58,20 @@
|
||||
{
|
||||
"name": "wan",
|
||||
"type": "infix-if-type:ethernet",
|
||||
"ietf-ip:ipv6": {}
|
||||
"ietf-ip:ipv6": {},
|
||||
"ietf-ip:ipv4": {
|
||||
"infix-dhcp-client:dhcp": {
|
||||
"option": [
|
||||
{"id": "ntp-server"},
|
||||
{"id": "broadcast"},
|
||||
{"id": "domain"},
|
||||
{"id": "hostname"},
|
||||
{"id": "dns-server"},
|
||||
{"id": "router"},
|
||||
{"id": "netmask"}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -172,36 +185,6 @@
|
||||
},
|
||||
"infix-system:motd-banner": "Li0tLS0tLS0uCnwgIC4gLiAgfCBJbmZpeCBPUyDigJQgSW1tdXRhYmxlLkZyaWVuZGx5LlNlY3VyZQp8LS4gdiAuLXwgaHR0cHM6Ly9rZXJuZWxraXQub3JnCictJy0tLSctJwo="
|
||||
},
|
||||
"infix-dhcp-client:dhcp-client": {
|
||||
"client-if": [
|
||||
{
|
||||
"if-name": "wan",
|
||||
"option": [
|
||||
{
|
||||
"id": "ntp-server"
|
||||
},
|
||||
{
|
||||
"id": "broadcast"
|
||||
},
|
||||
{
|
||||
"id": "domain"
|
||||
},
|
||||
{
|
||||
"id": "hostname"
|
||||
},
|
||||
{
|
||||
"id": "dns-server"
|
||||
},
|
||||
{
|
||||
"id": "router"
|
||||
},
|
||||
{
|
||||
"id": "netmask"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"infix-dhcp-server:dhcp-server": {
|
||||
"option": [
|
||||
{
|
||||
@@ -262,7 +245,7 @@
|
||||
]
|
||||
},
|
||||
"infix-meta:meta": {
|
||||
"version": "1.5"
|
||||
"version": "1.6"
|
||||
},
|
||||
"infix-services:mdns": {
|
||||
"enabled": true
|
||||
|
||||
+15
-32
@@ -37,7 +37,20 @@
|
||||
},
|
||||
{
|
||||
"name": "eth0",
|
||||
"type": "infix-if-type:ethernet"
|
||||
"type": "infix-if-type:ethernet",
|
||||
"ietf-ip:ipv4": {
|
||||
"infix-dhcp-client:dhcp": {
|
||||
"option": [
|
||||
{"id": "netmask"},
|
||||
{"id": "broadcast"},
|
||||
{"id": "router"},
|
||||
{"id": "domain"},
|
||||
{"id": "hostname"},
|
||||
{"id": "dns-server"},
|
||||
{"id": "ntp-server"}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "wifi0",
|
||||
@@ -157,38 +170,8 @@
|
||||
},
|
||||
"infix-system:motd-banner": "Li0tLS0tLS0uCnwgIC4gLiAgfCBJbmZpeCBPUyDigJQgSW1tdXRhYmxlLkZyaWVuZGx5LlNlY3VyZQp8LS4gdiAuLXwgaHR0cHM6Ly9rZXJuZWxraXQub3JnCictJy0tLSctJwo="
|
||||
},
|
||||
"infix-dhcp-client:dhcp-client": {
|
||||
"client-if": [
|
||||
{
|
||||
"if-name": "eth0",
|
||||
"option": [
|
||||
{
|
||||
"id": "netmask"
|
||||
},
|
||||
{
|
||||
"id": "broadcast"
|
||||
},
|
||||
{
|
||||
"id": "router"
|
||||
},
|
||||
{
|
||||
"id": "domain"
|
||||
},
|
||||
{
|
||||
"id": "hostname"
|
||||
},
|
||||
{
|
||||
"id": "dns-server"
|
||||
},
|
||||
{
|
||||
"id": "ntp-server"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"infix-meta:meta": {
|
||||
"version": "1.5"
|
||||
"version": "1.6"
|
||||
},
|
||||
"infix-services:mdns": {
|
||||
"enabled": true
|
||||
|
||||
@@ -15,9 +15,9 @@ cfgfs /config configfs nofail,noauto 0 0
|
||||
# The chosen backing storage for the overlays placed on /cfg, /etc,
|
||||
# /home, /root, and /var, are determined dynamically by /usr/libexec/infix/mnt
|
||||
# depending on the available devices.
|
||||
mnttmp /mnt/tmp tmpfs defaults 0 0
|
||||
LABEL=aux /mnt/aux auto noatime,nodiratime,noauto,commit=30,errors=remount-ro 0 0
|
||||
LABEL=var /mnt/var auto noatime,nodiratime,noauto,commit=30,errors=remount-ro 0 0
|
||||
LABEL=cfg /mnt/cfg auto noatime,nodiratime,noauto,commit=30,errors=remount-ro 0 0
|
||||
hostfs /mnt/host 9p cache=none,msize=16384,noauto 0 0
|
||||
/usr/libexec/infix/mnt# /cfg helper none 0 0
|
||||
mnttmp /mnt/tmp tmpfs defaults 0 0
|
||||
LABEL=aux /mnt/aux ext2 noatime,nodiratime,noauto,errors=remount-ro 0 0
|
||||
LABEL=var /mnt/var ext4 noatime,nodiratime,noauto,commit=30,errors=remount-ro 0 0
|
||||
LABEL=cfg /mnt/cfg ext4 noatime,nodiratime,noauto,commit=30,errors=remount-ro 0 0
|
||||
hostfs /mnt/host 9p cache=none,msize=16384,noauto 0 0
|
||||
/usr/libexec/infix/mnt# /cfg helper none 0 0
|
||||
|
||||
@@ -44,12 +44,15 @@ check_factory()
|
||||
factory_reset()
|
||||
{
|
||||
find /sys/class/leds/ -type l -exec sh -c 'echo 100 > $0/brightness' {} \;
|
||||
logger $opt -p user.crit -t "$nm" "Resetting to factory defaults."
|
||||
print_start "Resetting to factory defaults."
|
||||
logger $opt -p user.notice -t "$nm" "Resetting to factory defaults."
|
||||
|
||||
rm -rf /mnt/cfg/* /mnt/var/*
|
||||
|
||||
logger $opt -p user.crit -t "$nm" "Factory reset complete."
|
||||
sync
|
||||
|
||||
logger $opt -p user.notice -t "$nm" "Factory reset complete."
|
||||
print_end 0 "Factory reset complete."
|
||||
print_restore
|
||||
}
|
||||
|
||||
is_mmc()
|
||||
@@ -105,15 +108,18 @@ find_partition_by_label()
|
||||
esac
|
||||
|
||||
disk="/dev/$devname"
|
||||
|
||||
#
|
||||
# 1. Try GPT/MBR partition label using sgdisk
|
||||
#
|
||||
result=$(sgdisk -p "$disk" 2>/dev/null | awk -v label="$label" -v devname="$devname" '
|
||||
/^ *[0-9]/ {
|
||||
/^ *[0-9]/ {
|
||||
if ($7 == label) {
|
||||
if (devname ~ /^(mmcblk|nvme|loop)/) {
|
||||
print devname "p" $1
|
||||
} else {
|
||||
print devname $1
|
||||
}
|
||||
exit 0
|
||||
if (devname ~ /^(mmcblk|nvme|loop)/)
|
||||
print devname "p" $1;
|
||||
else
|
||||
print devname $1;
|
||||
exit 0;
|
||||
}
|
||||
}
|
||||
')
|
||||
@@ -122,7 +128,30 @@ find_partition_by_label()
|
||||
echo "$result"
|
||||
return 0
|
||||
fi
|
||||
|
||||
#
|
||||
# 2. Fallback: Check if the whole disk is an ext4/ext2/ext3 filesystem
|
||||
#
|
||||
|
||||
# Check for ext4/ext2/ext3 magic number (0xEF53) at offset 1080 (1024+56).
|
||||
magic_number=$(dd if="$disk" bs=1 skip=1080 count=2 2>/dev/null | od -t x2 -A n | tr -d ' \n')
|
||||
|
||||
# Check for both Little-Endian ('53ef') and Big-Endian ('ef53') interpretations of 0xEF53.
|
||||
# This supports bi-endian architectures like MIPS that may run in BE mode,
|
||||
# as well as the LE mode which is standard for RISC-V and ext filesystems.
|
||||
if [ "$magic_number" = "ef53" ] || [ "$magic_number" = "53ef" ]; then
|
||||
|
||||
# Read the volume label from offset 1144 (1024+120)
|
||||
fslabel=$(dd if="$disk" bs=1 skip=1144 count=16 2>/dev/null | tr -d '\000')
|
||||
logger $opt -p user.notice -t "$nm" "Found label $fslabel on disk $disk ..."
|
||||
|
||||
if [ "$fslabel" = "$label" ]; then
|
||||
echo "$devname"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
@@ -273,6 +302,9 @@ mount_rw()
|
||||
# If something is already setup, leave it be.
|
||||
mountpoint -q "/$1" && return 0
|
||||
|
||||
# If partition doesn't exist (var is optional), signal caller.
|
||||
find_partition_by_label "$1" >/dev/null || return 1
|
||||
|
||||
# Check if /var has been resized to fill the sdcard/eMMC
|
||||
if [ "$1" = "var" ] && is_mmc; then
|
||||
if [ -f /mnt/aux/resized ] || [ -f /mnt/aux/resized.failed ]; then
|
||||
@@ -289,8 +321,10 @@ mount_rw()
|
||||
|
||||
# TODO: Also look for UBI partitions
|
||||
|
||||
#
|
||||
tune2fs -c 0 -i 0 LABEL="$1" 2>/dev/null
|
||||
# Disable periodic fsck, yet keeping safety checks on ext4
|
||||
if grep "LABEL=$label" /etc/fstab |grep -q ext4; then
|
||||
tune2fs -c 0 -i 0 LABEL="$1" 2>/dev/null
|
||||
fi
|
||||
mount LABEL="$1" 2>/dev/null && return 0
|
||||
|
||||
return 1
|
||||
|
||||
@@ -8,6 +8,12 @@ All notable changes to the project are documented in this file.
|
||||
|
||||
### Changes
|
||||
|
||||
- The DHCP client configuration has moved from `/infix-dhcp-client:dhcp-client`
|
||||
to `/interfaces/interface[name]/ipv4/infix-dhcp-client:dhcp`, issue #1109.
|
||||
The configuration is automatically migrated on upgrade. The DHCP client is
|
||||
now enabled using a presence container instead of a separate `enabled` leaf
|
||||
- The `enabled` nore for IPv4 autoconf (ZeroConf) has been dropped, `autoconf`
|
||||
is now a presence container. Configuration automatically migrated on upgrade
|
||||
- Improvements to `sdcard.img` generation, useful for developers mostly:
|
||||
- The NanoPi R2S bootloader is now automatically built and uploaded to
|
||||
the [`latest-boot` release][lastest-boot] tag
|
||||
|
||||
+37
-11
@@ -996,7 +996,7 @@ default.
|
||||
admin@example:/> configure
|
||||
admin@example:/config/> edit interface eth0 ipv4
|
||||
admin@example:/config/interface/eth0/ipv4/> set address 10.0.1.1 prefix-length 24
|
||||
admin@example:/config/interface/eth0/ipv4/> set autoconf enabled true
|
||||
admin@example:/config/interface/eth0/ipv4/> set autoconf
|
||||
admin@example:/config/interface/eth0/ipv4/> diff
|
||||
+interfaces {
|
||||
+ interface eth0 {
|
||||
@@ -1004,9 +1004,7 @@ default.
|
||||
+ address 10.0.1.1 {
|
||||
+ prefix-length 24;
|
||||
+ }
|
||||
+ autoconf {
|
||||
+ enabled true;
|
||||
+ }
|
||||
+ autoconf;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
@@ -1022,15 +1020,18 @@ default.
|
||||
ipv6 ::1/128 (static)
|
||||
admin@example:/>
|
||||
|
||||
As shown, the link-local IPv4 address is configured with `set autconf
|
||||
enabled true`. The resulting address (169.254.1.3/16) is of type
|
||||
*random* ([ietf-ip.yang][2]).
|
||||
As shown, the link-local IPv4 address is configured with `set autoconf`.
|
||||
The presence of the `autoconf` container enables IPv4 link-local address
|
||||
assignment. The resulting address (169.254.1.3/16) is of type *random*
|
||||
([ietf-ip.yang][2]).
|
||||
|
||||
The IPv4LL client also supports a `request-address` setting which can be
|
||||
used to "seed" the client's starting address. If the address is free it
|
||||
will be used, otherwise it falls back to the default algorithm.
|
||||
|
||||
admin@example:/config/interface/eth0/ipv4/> set autoconf request-address 169.254.1.2
|
||||
admin@example:/config/interface/eth0/ipv4/> edit autoconf
|
||||
admin@example:/config/interface/eth0/ipv4/autoconf/> set request-address 169.254.1.2
|
||||
admin@example:/config/interface/eth0/ipv4/autoconf/> leave
|
||||
|
||||
|
||||
#### Use of DHCP for IPv4 address assignment
|
||||
@@ -1038,9 +1039,9 @@ will be used, otherwise it falls back to the default algorithm.
|
||||

|
||||
|
||||
admin@example:/> configure
|
||||
admin@example:/config/> edit dhcp-client
|
||||
admin@example:/config/dhcp-client/> set client-if eth0
|
||||
admin@example:/config/dhcp-client/> leave
|
||||
admin@example:/config/> edit interface eth0 ipv4
|
||||
admin@example:/config/interface/eth0/ipv4/> set dhcp
|
||||
admin@example:/config/interface/eth0/ipv4/> leave
|
||||
admin@example:/> show interfaces
|
||||
INTERFACE PROTOCOL STATE DATA
|
||||
eth0 ethernet UP 02:00:00:00:00:00
|
||||
@@ -1053,6 +1054,31 @@ will be used, otherwise it falls back to the default algorithm.
|
||||
|
||||
The resulting address (10.1.2.100/24) is of type *dhcp*.
|
||||
|
||||
To configure DHCP client options, such as sending a specific hostname to the
|
||||
server, you can specify options with values:
|
||||
|
||||
```
|
||||
admin@example:/> configure
|
||||
admin@example:/config/> edit interface eth0 ipv4 dhcp
|
||||
admin@example:/config/interface/eth0/ipv4/dhcp/> set option hostname value myhost
|
||||
admin@example:/config/interface/eth0/ipv4/dhcp/> show
|
||||
option hostname {
|
||||
value myhost;
|
||||
}
|
||||
admin@example:/config/interface/eth0/ipv4/dhcp/> leave
|
||||
admin@example:/>
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
> The special value `auto` can be used with the hostname option to
|
||||
> automatically use the configured system hostname.
|
||||
|
||||
Other useful DHCP options include:
|
||||
|
||||
- `client-id` - Send a specific client identifier to the server
|
||||
- `route-preference` - Set the administrative distance for DHCP-learned routes (default: 5)
|
||||
|
||||
For advanced usage with vendor-specific options, see the YANG model.
|
||||
|
||||
#### Disabling IPv6 link-local address(es)
|
||||
|
||||
|
||||
+16
-28
@@ -173,11 +173,13 @@ Enabling DHCPv4 client on interface *e0*, with current default options.
|
||||
```
|
||||
~$ cat /tmp/file.json
|
||||
{
|
||||
"infix-dhcp-client:dhcp-client": {
|
||||
"enabled": true,
|
||||
"client-if": [
|
||||
"ietf-interfaces:interfaces": {
|
||||
"interface": [
|
||||
{
|
||||
"if-name": "e0"
|
||||
"name": "e0",
|
||||
"ietf-ip:ipv4": {
|
||||
"infix-dhcp-client:dhcp": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -187,13 +189,18 @@ Enabling DHCPv4 client on interface *e0*, with current default options.
|
||||
~$
|
||||
```
|
||||
|
||||
Disabling DHCPv4 client.
|
||||
Disabling DHCPv4 client on interface *e0* (remove the dhcp container).
|
||||
|
||||
```
|
||||
~$ cat /tmp/file.json
|
||||
{
|
||||
"infix-dhcp-client:dhcp-client": {
|
||||
"enabled": false
|
||||
"ietf-interfaces:interfaces": {
|
||||
"interface": [
|
||||
{
|
||||
"name": "e0",
|
||||
"ietf-ip:ipv4": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
~$ scp file.json admin@example.local:/tmp/file.json
|
||||
@@ -201,27 +208,8 @@ Disabling DHCPv4 client.
|
||||
~$
|
||||
```
|
||||
|
||||
Configuration for client interface *e0* remains, but does not apply as
|
||||
DHCPv4 is disabled.
|
||||
|
||||
```
|
||||
admin@example:~$ sysrepocfg -X -fjson -d running -x "/infix-dhcp-client:dhcp-client"
|
||||
{
|
||||
"infix-dhcp-client:dhcp-client": {
|
||||
"enabled": false,
|
||||
"client-if": [
|
||||
{
|
||||
"if-name": "e0"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
admin@example:~$
|
||||
```
|
||||
|
||||
To fully remove the DHCPv4 client configuration or a specific
|
||||
*client-if* with sysrepocfg, one would need to read out the full
|
||||
configuration, remove relevant parts and read back.
|
||||
To fully remove the DHCPv4 client configuration, remove the `infix-dhcp-client:dhcp`
|
||||
container from the interface's ipv4 configuration.
|
||||
|
||||
## Enable/Disable IPv6
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#
|
||||
################################################################################
|
||||
|
||||
CONFD_VERSION = 1.5
|
||||
CONFD_VERSION = 1.6
|
||||
CONFD_SITE_METHOD = local
|
||||
CONFD_SITE = $(BR2_EXTERNAL_INFIX_PATH)/src/confd
|
||||
CONFD_LICENSE = BSD-3-Clause
|
||||
|
||||
@@ -169,9 +169,23 @@ if [ -n "$bridge" ]; then
|
||||
"name": "$bridge",
|
||||
"type": "infix-if-type:bridge",
|
||||
"ietf-ip:ipv4": {
|
||||
"infix-ip:autoconf": {
|
||||
"enabled": $ipv4
|
||||
}
|
||||
EOF
|
||||
if [ "$ipv4" = "true" ]; then
|
||||
cat <<EOF
|
||||
"infix-ip:autoconf": {}
|
||||
EOF
|
||||
if [ "$dhcp" = "true" ]; then
|
||||
cat <<EOF
|
||||
,
|
||||
"infix-dhcp-client:dhcp": {}
|
||||
EOF
|
||||
fi
|
||||
elif [ "$dhcp" = "true" ]; then
|
||||
cat <<EOF
|
||||
"infix-dhcp-client:dhcp": {}
|
||||
EOF
|
||||
fi
|
||||
cat <<EOF
|
||||
},
|
||||
"ietf-ip:ipv6": {
|
||||
"enabled": true,
|
||||
@@ -195,18 +209,6 @@ $(for iface in $ifaces; do gen_iface_json "$iface"; done)
|
||||
$(for iface in $ports; do gen_iface_json "$iface" "$bridge"; done)
|
||||
]
|
||||
EOF
|
||||
if [ "$dhcp" = "true" ] && [ -n "$bridge" ]; then
|
||||
cat <<EOF
|
||||
},
|
||||
"infix-dhcp-client:dhcp-client": {
|
||||
"enabled": true,
|
||||
"client-if": [
|
||||
{
|
||||
"if-name": "$bridge"
|
||||
}
|
||||
]
|
||||
EOF
|
||||
fi
|
||||
cat <<EOF
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
AC_PREREQ(2.61)
|
||||
# confd version is same as system YANG model version, step on breaking changes
|
||||
AC_INIT([confd], [1.5], [https://github.com/kernelkit/infix/issues])
|
||||
AC_INIT([confd], [1.6], [https://github.com/kernelkit/infix/issues])
|
||||
AM_INIT_AUTOMAKE(1.11 foreign subdir-objects)
|
||||
AM_SILENT_RULES(yes)
|
||||
|
||||
@@ -19,6 +19,7 @@ AC_CONFIG_FILES([
|
||||
share/migrate/1.3/Makefile
|
||||
share/migrate/1.4/Makefile
|
||||
share/migrate/1.5/Makefile
|
||||
share/migrate/1.6/Makefile
|
||||
yang/Makefile
|
||||
yang/confd/Makefile
|
||||
yang/test-mode/Makefile
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
#!/bin/sh
|
||||
# Migrate DHCP client configuration from standalone model to ietf-ip augment
|
||||
# From: /infix-dhcp-client:dhcp-client/client-if[if-name]
|
||||
# To: /ietf-interfaces:interfaces/interface[name]/ipv4/infix-dhcp-client:dhcp
|
||||
|
||||
file=$1
|
||||
temp=${file}.tmp
|
||||
|
||||
jq '
|
||||
if .["infix-dhcp-client:dhcp-client"] then
|
||||
.["infix-dhcp-client:dhcp-client"]."client-if" as $clients |
|
||||
|
||||
($clients // [] | map({
|
||||
key: ."if-name",
|
||||
value: {
|
||||
"infix-dhcp-client:dhcp": (
|
||||
. | del(."if-name") | del(.enabled)
|
||||
)
|
||||
}
|
||||
}) | from_entries) as $dhcp_configs |
|
||||
|
||||
if .["ietf-interfaces:interfaces"] then
|
||||
.["ietf-interfaces:interfaces"].interface |= map(
|
||||
if $dhcp_configs[.name] then
|
||||
.["ietf-ip:ipv4"] += $dhcp_configs[.name]
|
||||
else
|
||||
.
|
||||
end
|
||||
)
|
||||
else
|
||||
.
|
||||
end |
|
||||
|
||||
del(.["infix-dhcp-client:dhcp-client"])
|
||||
else
|
||||
.
|
||||
end
|
||||
' "$file" > "$temp" && mv "$temp" "$file"
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
#!/bin/sh
|
||||
# Migrate IPv4 autoconf from enabled leaf to presence container
|
||||
# Remove the "enabled" leaf, keeping the container only if it was enabled
|
||||
|
||||
file=$1
|
||||
temp=${file}.tmp
|
||||
|
||||
jq '
|
||||
if .["ietf-interfaces:interfaces"] then
|
||||
.["ietf-interfaces:interfaces"].interface |= map(
|
||||
if .["ietf-ip:ipv4"]?."infix-ip:autoconf" then
|
||||
if .["ietf-ip:ipv4"]."infix-ip:autoconf".enabled == false then
|
||||
# Remove autoconf container if it was disabled
|
||||
.["ietf-ip:ipv4"] |= del(."infix-ip:autoconf")
|
||||
else
|
||||
# Keep autoconf but remove the enabled leaf
|
||||
.["ietf-ip:ipv4"]."infix-ip:autoconf" |= del(.enabled)
|
||||
end
|
||||
else
|
||||
.
|
||||
end
|
||||
)
|
||||
else
|
||||
.
|
||||
end
|
||||
' "$file" > "$temp" && mv "$temp" "$file"
|
||||
@@ -0,0 +1,3 @@
|
||||
migratedir = $(pkgdatadir)/migrate/1.6
|
||||
dist_migrate_DATA = 10-dhcp-client-to-ipv4.sh \
|
||||
20-autoconf-to-presence.sh
|
||||
@@ -1,2 +1,2 @@
|
||||
SUBDIRS = 1.0 1.1 1.2 1.3 1.4 1.5
|
||||
SUBDIRS = 1.0 1.1 1.2 1.3 1.4 1.5 1.6
|
||||
migratedir = $(pkgdatadir)/migrate
|
||||
|
||||
+17
-8
@@ -8,8 +8,8 @@
|
||||
struct confd confd;
|
||||
|
||||
|
||||
int core_startup_save(sr_session_ctx_t *session, uint32_t sub_id, const char *module,
|
||||
const char *xpath, sr_event_t event, unsigned request_id, void *priv)
|
||||
static int core_startup_save(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_event_t last_event = -1;
|
||||
static unsigned int last_request = -1;
|
||||
@@ -221,8 +221,10 @@ static int change_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *mod
|
||||
goto free_diff;
|
||||
|
||||
/* infix-containers */
|
||||
#ifdef CONTAINERS
|
||||
if ((rc = infix_containers_change(session, config, diff, event, confd)))
|
||||
goto free_diff;
|
||||
#endif
|
||||
|
||||
/* ietf-hardware */
|
||||
if ((rc = ietf_hardware_change(session, config, diff, event, confd)))
|
||||
@@ -258,16 +260,21 @@ static int change_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *mod
|
||||
|
||||
AUDIT("The new configuration has been applied.");
|
||||
}
|
||||
|
||||
free_diff:
|
||||
lyd_free_tree(diff);
|
||||
return rc;
|
||||
lyd_free_tree(diff);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline int subscribe_module(char *model, struct confd *confd, int flags) {
|
||||
return sr_module_change_subscribe(confd->session, model, "//.", change_cb, confd,
|
||||
CB_PRIO_PRIMARY, SR_SUBSCR_CHANGE_ALL_MODULES | SR_SUBSCR_DEFAULT | flags, &confd->sub) &&
|
||||
static inline int subscribe_module(char *model, struct confd *confd, int flags)
|
||||
{
|
||||
ERROR("core: subscribing to models");
|
||||
return sr_module_change_subscribe(confd->session, model, "//.", change_cb, confd,
|
||||
CB_PRIO_PRIMARY, SR_SUBSCR_CHANGE_ALL_MODULES |
|
||||
SR_SUBSCR_DEFAULT | flags, &confd->sub) &&
|
||||
sr_module_change_subscribe(confd->startup, model, "//.", core_startup_save, NULL,
|
||||
CB_PRIO_PASSIVE, SR_SUBSCR_PASSIVE | SR_SUBSCR_CHANGE_ALL_MODULES, &confd->sub);
|
||||
CB_PRIO_PASSIVE, SR_SUBSCR_CHANGE_ALL_MODULES |
|
||||
SR_SUBSCR_PASSIVE, &confd->sub);
|
||||
}
|
||||
|
||||
int sr_plugin_init_cb(sr_session_ctx_t *session, void **priv)
|
||||
@@ -385,9 +392,11 @@ int sr_plugin_init_cb(sr_session_ctx_t *session, void **priv)
|
||||
rc = ietf_system_rpc_init(&confd);
|
||||
if (rc)
|
||||
goto err;
|
||||
#ifdef CONTAINERS
|
||||
rc = infix_containers_rpc_init(&confd);
|
||||
if (rc)
|
||||
goto err;
|
||||
#endif
|
||||
rc = infix_dhcp_server_rpc_init(&confd);
|
||||
if (rc)
|
||||
goto err;
|
||||
|
||||
@@ -135,7 +135,6 @@ struct confd {
|
||||
struct dagger netdag;
|
||||
};
|
||||
|
||||
int core_startup_save (sr_session_ctx_t *, uint32_t, const char *, const char *, sr_event_t, unsigned, void *);
|
||||
|
||||
static inline int register_change(sr_session_ctx_t *session, const char *module, const char *xpath,
|
||||
int flags, sr_module_change_cb cb, void *arg, sr_subscription_ctx_t **sub)
|
||||
|
||||
@@ -94,7 +94,7 @@ int netdag_gen_ipv4_autoconf(struct dagger *net, struct lyd_node *cif,
|
||||
* for various reasons: was bridge port, ipv4 was disabled...
|
||||
*/
|
||||
zcip = lydx_get_child(ipconf, "autoconf");
|
||||
if (zcip && lydx_is_enabled(zcip, "enabled")) {
|
||||
if (zcip) {
|
||||
struct lyd_node *node;
|
||||
const char *addr;
|
||||
int diff = 0;
|
||||
@@ -105,9 +105,8 @@ int netdag_gen_ipv4_autoconf(struct dagger *net, struct lyd_node *cif,
|
||||
if (node) {
|
||||
const struct lyd_node *tmp;
|
||||
|
||||
tmp = lydx_get_child(node, "enabled");
|
||||
if (tmp)
|
||||
diff++;
|
||||
/* presence container created or deleted */
|
||||
diff++;
|
||||
tmp = lydx_get_child(node, "request-address");
|
||||
if (tmp)
|
||||
diff++;
|
||||
|
||||
+119
-100
@@ -51,89 +51,122 @@ static char *filerd(const char *fn, size_t len)
|
||||
return buf;
|
||||
}
|
||||
|
||||
int ietf_keystore_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd)
|
||||
static int gen_hostkey(const char *name, struct lyd_node *change)
|
||||
{
|
||||
const char *private_key, *public_key;
|
||||
int rc = SR_ERR_OK;
|
||||
|
||||
private_key = lydx_get_cattr(change, "cleartext-private-key");
|
||||
public_key = lydx_get_cattr(change, "public-key");
|
||||
|
||||
if (mkdir(SSH_HOSTKEYS_NEXT, 0600) && (errno != EEXIST)) {
|
||||
ERRNO("Failed creating %s", SSH_HOSTKEYS_NEXT);
|
||||
rc = SR_ERR_INTERNAL;
|
||||
}
|
||||
|
||||
if (systemf("/usr/libexec/infix/mksshkey %s %s %s %s", name, SSH_HOSTKEYS_NEXT, public_key, private_key))
|
||||
rc = SR_ERR_INTERNAL;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int keystore_update(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff)
|
||||
{
|
||||
const char *xpath = "/ietf-keystore:keystore/asymmetric-keys/asymmetric-key";
|
||||
sr_val_t *list = NULL;
|
||||
size_t count = 0;
|
||||
int rc;
|
||||
|
||||
rc = sr_get_items(session, xpath, 0, 0, &list, &count);
|
||||
if (rc != SR_ERR_OK) {
|
||||
ERROR("Cannot find any asymmetric keys in configuration");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
char *name = srx_get_str(session, "%s/name", list[i].xpath);
|
||||
char *public_key_format, *private_key_format;
|
||||
char *pub_key = NULL, *priv_key = NULL;
|
||||
sr_val_t *entry = &list[i];
|
||||
|
||||
if (srx_isset(session, "%s/cleartext-private-key", entry->xpath) ||
|
||||
srx_isset(session, "%s/public-key", entry->xpath))
|
||||
continue;
|
||||
|
||||
public_key_format = srx_get_str(session, "%s/public-key-format", entry->xpath);
|
||||
if (!public_key_format)
|
||||
continue;
|
||||
|
||||
private_key_format = srx_get_str(session, "%s/private-key-format", entry->xpath);
|
||||
if (!private_key_format) {
|
||||
free(public_key_format);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(private_key_format, "infix-crypto-types:rsa-private-key-format") ||
|
||||
strcmp(public_key_format, "infix-crypto-types:ssh-public-key-format"))
|
||||
continue;
|
||||
|
||||
NOTE("SSH key (%s) does not exist, generating...", name);
|
||||
if (systemf("/usr/libexec/infix/mkkeys %s %s", SSH_PRIVATE_KEY, SSH_PUBLIC_KEY)) {
|
||||
ERROR("Failed generating SSH keys for %s", name);
|
||||
goto next;
|
||||
}
|
||||
|
||||
priv_key = filerd(SSH_PRIVATE_KEY, filesz(SSH_PRIVATE_KEY));
|
||||
if (!priv_key)
|
||||
goto next;
|
||||
|
||||
pub_key = filerd(SSH_PUBLIC_KEY, filesz(SSH_PUBLIC_KEY));
|
||||
if (!pub_key)
|
||||
goto next;
|
||||
|
||||
rc = srx_set_str(session, priv_key, 0, "%s/cleartext-private-key", entry->xpath);
|
||||
if (rc) {
|
||||
ERROR("Failed setting private key for %s... rc: %d", name, rc);
|
||||
goto next;
|
||||
}
|
||||
|
||||
rc = srx_set_str(session, pub_key, 0, "%s/public-key", entry->xpath);
|
||||
if (rc != SR_ERR_OK) {
|
||||
ERROR("Failed setting public key for %s... rc: %d", name, rc);
|
||||
goto next;
|
||||
}
|
||||
next:
|
||||
if (erase(SSH_PRIVATE_KEY))
|
||||
ERRNO("Failed removing SSH server private key");
|
||||
if (erase(SSH_PUBLIC_KEY))
|
||||
ERRNO("Failed removing SSH server public key");
|
||||
|
||||
if (priv_key)
|
||||
free(priv_key);
|
||||
|
||||
if (pub_key)
|
||||
free(pub_key);
|
||||
|
||||
free(name);
|
||||
free(public_key_format);
|
||||
free(private_key_format);
|
||||
}
|
||||
|
||||
if (list)
|
||||
sr_free_values(list, count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ietf_keystore_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff,
|
||||
sr_event_t event, struct confd *confd)
|
||||
{
|
||||
struct lyd_node *changes, *change;
|
||||
sr_val_t *list = NULL;
|
||||
int rc = SR_ERR_OK;
|
||||
size_t count = 0;
|
||||
|
||||
if (diff && !lydx_find_xpathf(diff, XPATH_KEYSTORE_))
|
||||
return SR_ERR_OK;
|
||||
|
||||
switch (event) {
|
||||
case SR_EV_UPDATE:
|
||||
rc = sr_get_items(session, "/ietf-keystore:keystore/asymmetric-keys/asymmetric-key", 0, 0, &list, &count);
|
||||
if (rc != SR_ERR_OK) {
|
||||
ERROR("Cannot find any asymmetric keys in configuration");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
sr_val_t *entry = &list[i];
|
||||
|
||||
if (!srx_isset(session, "%s/cleartext-private-key", entry->xpath) && !srx_isset(session, "%s/public-key", entry->xpath)) {
|
||||
char *private_key_format, *public_key_format;
|
||||
|
||||
public_key_format = srx_get_str(session, "%s/public-key-format", entry->xpath);
|
||||
if (!public_key_format)
|
||||
continue;
|
||||
private_key_format = srx_get_str(session, "%s/private-key-format", entry->xpath);
|
||||
if (!private_key_format) {
|
||||
free(public_key_format);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(private_key_format, "infix-crypto-types:rsa-private-key-format") &&
|
||||
!strcmp(public_key_format, "infix-crypto-types:ssh-public-key-format")) {
|
||||
char *pub_key = NULL, *priv_key = NULL, *name;
|
||||
|
||||
name = srx_get_str(session, "%s/name", entry->xpath);
|
||||
NOTE("SSH key (%s) does not exist, generating...", name);
|
||||
if (systemf("/usr/libexec/infix/mkkeys %s %s", SSH_PRIVATE_KEY, SSH_PUBLIC_KEY)) {
|
||||
ERROR("Failed to generate SSH keys for %s", name);
|
||||
goto next;
|
||||
}
|
||||
|
||||
priv_key = filerd(SSH_PRIVATE_KEY, filesz(SSH_PRIVATE_KEY));
|
||||
if (!priv_key)
|
||||
goto next;
|
||||
|
||||
pub_key = filerd(SSH_PUBLIC_KEY, filesz(SSH_PUBLIC_KEY));
|
||||
if (!pub_key)
|
||||
goto next;
|
||||
|
||||
rc = srx_set_str(session, priv_key, 0, "%s/cleartext-private-key", entry->xpath);
|
||||
if (rc) {
|
||||
ERROR("Failed setting private key for %s... rc: %d", name, rc);
|
||||
goto next;
|
||||
}
|
||||
rc = srx_set_str(session, pub_key, 0, "%s/public-key", entry->xpath);
|
||||
if (rc != SR_ERR_OK) {
|
||||
ERROR("Failed setting public key for %s... rc: %d", name, rc);
|
||||
goto next;
|
||||
}
|
||||
next:
|
||||
if (erase(SSH_PRIVATE_KEY))
|
||||
ERRNO("Failed removing SSH server private key");
|
||||
if (erase(SSH_PUBLIC_KEY))
|
||||
ERRNO("Failed removing SSH server public key");
|
||||
|
||||
if (priv_key)
|
||||
free(priv_key);
|
||||
|
||||
if (pub_key)
|
||||
free(pub_key);
|
||||
|
||||
free(name);
|
||||
}
|
||||
free(public_key_format);
|
||||
free(private_key_format);
|
||||
}
|
||||
}
|
||||
if (list)
|
||||
sr_free_values(list, count);
|
||||
|
||||
rc = keystore_update(session, config, diff);
|
||||
break;
|
||||
case SR_EV_CHANGE:
|
||||
case SR_EV_ENABLED:
|
||||
@@ -142,49 +175,35 @@ int ietf_keystore_change(sr_session_ctx_t *session, struct lyd_node *config, str
|
||||
rmrf(SSH_HOSTKEYS_NEXT);
|
||||
return SR_ERR_OK;
|
||||
case SR_EV_DONE:
|
||||
if(fexist(SSH_HOSTKEYS_NEXT)) {
|
||||
if(rmrf(SSH_HOSTKEYS)) {
|
||||
if (fexist(SSH_HOSTKEYS_NEXT)) {
|
||||
if (rmrf(SSH_HOSTKEYS))
|
||||
ERRNO("Failed to remove old SSH hostkeys: %d", errno);
|
||||
}
|
||||
|
||||
if (rename(SSH_HOSTKEYS_NEXT, SSH_HOSTKEYS))
|
||||
ERRNO("Failed switching to new %s", SSH_HOSTKEYS);
|
||||
}
|
||||
return SR_ERR_OK;
|
||||
|
||||
default:
|
||||
return SR_ERR_OK;
|
||||
}
|
||||
|
||||
changes = lydx_get_descendant(config, "keystore", "asymmetric-keys", "asymmetric-key", NULL);
|
||||
|
||||
LYX_LIST_FOR_EACH(changes, change, "asymmetric-key") {
|
||||
const char *name, *private_key_type, *public_key_type;
|
||||
const char *private_key, *public_key;
|
||||
const char *name = lydx_get_cattr(change, "name");
|
||||
const char *type;
|
||||
|
||||
name = lydx_get_cattr(change, "name");
|
||||
private_key_type = lydx_get_cattr(change, "private-key-format");
|
||||
public_key_type = lydx_get_cattr(change, "public-key-format");
|
||||
|
||||
if (strcmp(private_key_type, "infix-crypto-types:rsa-private-key-format")) {
|
||||
INFO("Private key %s is not of SSH type", name);
|
||||
type = lydx_get_cattr(change, "private-key-format");
|
||||
if (strcmp(type, "infix-crypto-types:rsa-private-key-format")) {
|
||||
INFO("Private key %s is not of SSH type (%s)", name, type);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(public_key_type, "infix-crypto-types:ssh-public-key-format")) {
|
||||
INFO("Public key %s is not of SSH type", name);
|
||||
type = lydx_get_cattr(change, "public-key-format");
|
||||
if (strcmp(type, "infix-crypto-types:ssh-public-key-format")) {
|
||||
INFO("Public key %s is not of SSH type (%s)", name, type);
|
||||
continue;
|
||||
}
|
||||
private_key = lydx_get_cattr(change, "cleartext-private-key");
|
||||
public_key = lydx_get_cattr(change, "public-key");
|
||||
|
||||
if (mkdir(SSH_HOSTKEYS_NEXT, 0600) && (errno != EEXIST)) {
|
||||
ERRNO("Failed creating %s", SSH_HOSTKEYS_NEXT);
|
||||
rc = SR_ERR_INTERNAL;
|
||||
}
|
||||
|
||||
if(systemf("/usr/libexec/infix/mksshkey %s %s %s %s", name, SSH_HOSTKEYS_NEXT, public_key, private_key))
|
||||
rc = SR_ERR_INTERNAL;
|
||||
gen_hostkey(name, change);
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
@@ -356,6 +356,7 @@ int infix_containers_change(sr_session_ctx_t *session, struct lyd_node *config,
|
||||
|
||||
if (diff && !lydx_get_xpathf(diff, CFG_XPATH))
|
||||
return SR_ERR_OK;
|
||||
|
||||
switch (event) {
|
||||
case SR_EV_DONE:
|
||||
break;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include "core.h"
|
||||
#define ARPING_MSEC 1000
|
||||
#define MODULE "infix-dhcp-client"
|
||||
#define XPATH "/infix-dhcp-client:dhcp-client"
|
||||
#define XPATH "/ietf-interfaces:interfaces/interface/ietf-ip:ipv4/infix-dhcp-client:dhcp"
|
||||
#define CACHE_TEMPLATE "/var/lib/misc/%s.cache"
|
||||
|
||||
static char *ip_cache(const char *ifname, char *str, size_t len)
|
||||
@@ -278,57 +278,61 @@ static void del(const char *ifname)
|
||||
systemf("initctl -bfq delete dhcp-client-%s", ifname);
|
||||
}
|
||||
|
||||
int infix_dhcp_client_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd)
|
||||
int infix_dhcp_client_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff,
|
||||
sr_event_t event, struct confd *confd)
|
||||
{
|
||||
struct lyd_node *global, *cifs, *difs, *cif, *dif;
|
||||
struct lyd_node *ifaces, *difaces, *iface, *diface, *ipv4, *dhcp, *ddhcp;
|
||||
sr_error_t err = 0;
|
||||
int ena = 0;
|
||||
|
||||
switch (event) {
|
||||
case SR_EV_DONE:
|
||||
break;
|
||||
case SR_EV_CHANGE:
|
||||
case SR_EV_ABORT:
|
||||
default:
|
||||
if (event != SR_EV_DONE)
|
||||
return SR_ERR_OK;
|
||||
}
|
||||
|
||||
global = lydx_get_descendant(config, "dhcp-client", NULL);
|
||||
ena = lydx_is_enabled(global, "enabled");
|
||||
ifaces = lydx_get_descendant(config, "interfaces", "interface", NULL);
|
||||
difaces = lydx_get_descendant(diff, "interfaces", "interface", NULL);
|
||||
|
||||
cifs = lydx_get_descendant(config, "dhcp-client", "client-if", NULL);
|
||||
difs = lydx_get_descendant(diff, "dhcp-client", "client-if", NULL);
|
||||
/* find the modified interfaces */
|
||||
LYX_LIST_FOR_EACH(difaces, diface, "interface") {
|
||||
const char *ifname = lydx_get_cattr(diface, "name");
|
||||
struct lyd_node *dipv4;
|
||||
char *out;
|
||||
|
||||
/* find the modified one, delete or recreate only that */
|
||||
LYX_LIST_FOR_EACH(difs, dif, "client-if") {
|
||||
const char *ifname = lydx_get_cattr(dif, "if-name");
|
||||
lyd_print_mem(&out, diface, LYD_JSON,
|
||||
LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_ALL);
|
||||
|
||||
if (lydx_get_op(dif) == LYDX_OP_DELETE) {
|
||||
dipv4 = lydx_get_descendant(lyd_child(diface), "ipv4", NULL);
|
||||
if (!dipv4)
|
||||
continue;
|
||||
|
||||
ddhcp = lydx_get_descendant(lyd_child(dipv4), "dhcp", NULL);
|
||||
if (!ddhcp)
|
||||
continue;
|
||||
|
||||
/* Check if dhcp container was deleted */
|
||||
if (lydx_get_op(ddhcp) == LYDX_OP_DELETE) {
|
||||
del(ifname);
|
||||
continue;
|
||||
}
|
||||
|
||||
LYX_LIST_FOR_EACH(cifs, cif, "client-if") {
|
||||
if (strcmp(ifname, lydx_get_cattr(cif, "if-name")))
|
||||
/* Find corresponding interface in config to check if dhcp is present */
|
||||
LYX_LIST_FOR_EACH(ifaces, iface, "interface") {
|
||||
if (strcmp(ifname, lydx_get_cattr(iface, "name")))
|
||||
continue;
|
||||
|
||||
if (!ena || !lydx_is_enabled(cif, "enabled"))
|
||||
ipv4 = lydx_get_descendant(lyd_child(iface), "ipv4", NULL);
|
||||
if (!ipv4) {
|
||||
del(ifname);
|
||||
break;
|
||||
}
|
||||
|
||||
dhcp = lydx_get_descendant(lyd_child(ipv4), "dhcp", NULL);
|
||||
if (!dhcp)
|
||||
del(ifname);
|
||||
else
|
||||
add(ifname, cif);
|
||||
add(ifname, dhcp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ena) {
|
||||
LYX_LIST_FOR_EACH(cifs, cif, "client-if") {
|
||||
const char *ifname = lydx_get_cattr(cif, "if-name");
|
||||
|
||||
INFO("DHCP client globally disabled, stopping client on %s ...", ifname);
|
||||
del(ifname);
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -368,7 +372,7 @@ static int cand(sr_session_ctx_t *session, uint32_t sub_id, const char *module,
|
||||
return SR_ERR_OK;
|
||||
}
|
||||
|
||||
err = sr_dup_changes_iter(session, XPATH "/client-if//*", &iter);
|
||||
err = sr_dup_changes_iter(session, XPATH "//*", &iter);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
||||
@@ -300,9 +300,6 @@ int infix_dhcp_server_change(sr_session_ctx_t *session, struct lyd_node *config,
|
||||
int enabled = 0, added = 0, deleted = 0;
|
||||
sr_error_t err = 0;
|
||||
|
||||
if (!lydx_get_xpathf(diff, CFG_XPATH))
|
||||
return SR_ERR_OK;
|
||||
|
||||
switch (event) {
|
||||
case SR_EV_DONE:
|
||||
break;
|
||||
@@ -312,6 +309,9 @@ int infix_dhcp_server_change(sr_session_ctx_t *session, struct lyd_node *config,
|
||||
return SR_ERR_OK;
|
||||
}
|
||||
|
||||
if (!lydx_get_xpathf(diff, CFG_XPATH))
|
||||
return SR_ERR_OK;
|
||||
|
||||
global = lydx_get_descendant(config, "dhcp-server", NULL);
|
||||
enabled = lydx_is_enabled(global, "enabled");
|
||||
|
||||
|
||||
@@ -20,13 +20,13 @@ MODULES=(
|
||||
"ietf-hardware@2018-03-13.yang -e hardware-state -e hardware-sensor"
|
||||
"infix-hardware@2025-10-30.yang"
|
||||
"ieee802-dot1q-types@2022-10-29.yang"
|
||||
"infix-ip@2024-09-16.yang"
|
||||
"infix-ip@2025-11-02.yang"
|
||||
"infix-if-type@2025-02-12.yang"
|
||||
"infix-routing@2024-11-27.yang"
|
||||
"ieee802-dot1ab-lldp@2022-03-15.yang"
|
||||
"infix-lldp@2025-05-05.yang"
|
||||
"infix-dhcp-common@2025-01-29.yang"
|
||||
"infix-dhcp-client@2025-01-29.yang"
|
||||
"infix-dhcp-client@2025-11-02.yang"
|
||||
"infix-dhcp-server@2025-10-28.yang"
|
||||
"infix-firewall@2025-04-26.yang"
|
||||
"infix-firewall-services@2025-04-26.yang"
|
||||
|
||||
@@ -6,6 +6,9 @@ module infix-dhcp-client {
|
||||
import ietf-interfaces {
|
||||
prefix if;
|
||||
}
|
||||
import ietf-ip {
|
||||
prefix ip;
|
||||
}
|
||||
import infix-dhcp-common {
|
||||
prefix dhcp;
|
||||
}
|
||||
@@ -13,6 +16,14 @@ module infix-dhcp-client {
|
||||
contact "kernelkit@googlegroups.com";
|
||||
description "This module implements a DHCPv4 client";
|
||||
|
||||
revision 2025-11-02 {
|
||||
description "Migrate DHCP client to ietf-ip augment.
|
||||
- Relocate from /dhcp-client to /interfaces/interface/ipv4/dhcp
|
||||
- Presence container instead of enabled leaf, matching autoconf
|
||||
- Drop client-if list wrapper, not needed anymore
|
||||
- Drop global enabled flag";
|
||||
reference "internal, issue #1109";
|
||||
}
|
||||
revision 2025-01-29 {
|
||||
description "Consolidate DHCP options between client and server models.
|
||||
- Rename option attribute 'name' -> 'id'
|
||||
@@ -51,30 +62,10 @@ module infix-dhcp-client {
|
||||
* Data Nodes
|
||||
*/
|
||||
|
||||
container dhcp-client {
|
||||
description "DHCPv4 client configuration";
|
||||
|
||||
leaf enabled {
|
||||
type boolean;
|
||||
default "true";
|
||||
description "Globally enables the DHCP client function.";
|
||||
}
|
||||
|
||||
list client-if {
|
||||
description "List of interfaces requesting DHCPv4 configuration.";
|
||||
key "if-name";
|
||||
|
||||
leaf if-name {
|
||||
type if:interface-ref;
|
||||
mandatory true;
|
||||
description "Name of the interface.";
|
||||
}
|
||||
|
||||
leaf enabled {
|
||||
type boolean;
|
||||
default "true";
|
||||
description "Enable DHCP client for this interface.";
|
||||
}
|
||||
augment "/if:interfaces/if:interface/ip:ipv4" {
|
||||
container dhcp {
|
||||
presence "Enable DHCP client for this interface.";
|
||||
description "DHCPv4 client configuration";
|
||||
|
||||
leaf client-id {
|
||||
type string;
|
||||
|
||||
@@ -18,6 +18,10 @@ module infix-ip {
|
||||
|
||||
description "This module augments ietf-ip with Infix extensions and deviations.";
|
||||
|
||||
revision 2025-11-02 {
|
||||
description "Change autoconf to presence container, removing enabled leaf.";
|
||||
reference "Internal, issue #1109.";
|
||||
}
|
||||
revision 2024-09-16 {
|
||||
description "Add support for IPv4LL request-address.";
|
||||
reference "Internal.";
|
||||
@@ -36,14 +40,10 @@ module infix-ip {
|
||||
*/
|
||||
augment "/if:interfaces/if:interface/ip:ipv4" {
|
||||
container autoconf {
|
||||
presence "Enable IPv4 link-local address autoconfiguration for this interface.";
|
||||
description "Parameters to control the autoconfiguration of IPv4 address.";
|
||||
reference "RFC 3927: Dynamic Configuration of IPv4 Link-Local Addresses";
|
||||
|
||||
leaf enabled {
|
||||
description "Use a ZeroConf/IPv4LL agent to retrieve an 169.254/16 address.";
|
||||
type boolean;
|
||||
}
|
||||
|
||||
leaf request-address {
|
||||
description "Try to acquire the specified IP address, if available.
|
||||
|
||||
|
||||
@@ -57,9 +57,7 @@ with infamy.Test() as test:
|
||||
"name": tport,
|
||||
"enabled": True,
|
||||
"ipv4": {
|
||||
"autoconf": {
|
||||
"enabled": True
|
||||
}
|
||||
"infix-ip:autoconf": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -79,8 +77,7 @@ with infamy.Test() as test:
|
||||
"name": tport,
|
||||
"enabled": True,
|
||||
"ipv4": {
|
||||
"autoconf": {
|
||||
"enabled": True,
|
||||
"infix-ip:autoconf": {
|
||||
"request-address": "169.254.42.42"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ import infamy.dhcp
|
||||
from infamy.util import until, parallel
|
||||
from infamy.netns import IsolatedMacVlans
|
||||
|
||||
def configure_interface(name, ip=None, prefix_length=None, forwarding=True):
|
||||
def configure_interface(name, ip=None, prefix_length=None, forwarding=True, dhcp=False):
|
||||
interface_config = {
|
||||
"name": name,
|
||||
"enabled": True,
|
||||
@@ -28,6 +28,19 @@ def configure_interface(name, ip=None, prefix_length=None, forwarding=True):
|
||||
}
|
||||
if ip and prefix_length:
|
||||
interface_config["ipv4"]["address"].append({"ip": ip, "prefix-length": prefix_length})
|
||||
if dhcp:
|
||||
interface_config["ipv4"]["infix-dhcp-client:dhcp"] = {
|
||||
"option": [
|
||||
{"id": "broadcast"},
|
||||
{"id": "dns-server"},
|
||||
{"id": "domain"},
|
||||
{"id": "hostname"},
|
||||
{"id": "ntp-server"},
|
||||
{"id": "router"},
|
||||
{"id": "netmask"}
|
||||
],
|
||||
"route-preference": 5
|
||||
}
|
||||
return interface_config
|
||||
|
||||
def config_target1(target, data1, data2, link):
|
||||
@@ -35,7 +48,7 @@ def config_target1(target, data1, data2, link):
|
||||
"ietf-interfaces": {
|
||||
"interfaces": {
|
||||
"interface": [
|
||||
configure_interface(data1),
|
||||
configure_interface(data1, dhcp=True),
|
||||
configure_interface(data2, "192.168.30.1", 24),
|
||||
configure_interface(link, "192.168.50.1", 24)
|
||||
]
|
||||
@@ -61,27 +74,6 @@ def config_target1(target, data1, data2, link):
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"infix-dhcp-client": {
|
||||
"dhcp-client": {
|
||||
"enabled": True,
|
||||
"client-if": [
|
||||
{
|
||||
"if-name": data1,
|
||||
"enabled": True,
|
||||
"option": [
|
||||
{"id": "broadcast"},
|
||||
{"id": "dns-server"},
|
||||
{"id": "domain"},
|
||||
{"id": "hostname"},
|
||||
{"id": "ntp-server"},
|
||||
{"id": "router"},
|
||||
{"id": "netmask"}
|
||||
],
|
||||
"route-preference": 5
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -24,13 +24,16 @@ with infamy.Test() as test:
|
||||
with infamy.dhcp.Server(netns, ip=ADDRESS):
|
||||
_, port = env.ltop.xlate("client", "data")
|
||||
config = {
|
||||
"dhcp-client": {
|
||||
"client-if": [{
|
||||
"if-name": f"{port}"
|
||||
"interfaces": {
|
||||
"interface": [{
|
||||
"name": f"{port}",
|
||||
"ipv4": {
|
||||
"infix-dhcp-client:dhcp": {}
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
client.put_config_dict("infix-dhcp-client", config)
|
||||
client.put_config_dict("ietf-interfaces", config)
|
||||
|
||||
with test.step("Verify client lease for 10.0.0.42"):
|
||||
until(lambda: iface.address_exist(client, port, ADDRESS))
|
||||
|
||||
@@ -26,16 +26,20 @@ with infamy.Test() as test:
|
||||
with infamy.dhcp.Server(netns, router=ROUTER):
|
||||
_, port = env.ltop.xlate("client", "data")
|
||||
config = {
|
||||
"dhcp-client": {
|
||||
"client-if": [{
|
||||
"if-name": f"{port}",
|
||||
"option": [
|
||||
{"id": "router"}
|
||||
]
|
||||
"interfaces": {
|
||||
"interface": [{
|
||||
"name": f"{port}",
|
||||
"ipv4": {
|
||||
"infix-dhcp-client:dhcp": {
|
||||
"option": [
|
||||
{"id": "router"}
|
||||
]
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
client.put_config_dict("infix-dhcp-client", config)
|
||||
client.put_config_dict("ietf-interfaces", config)
|
||||
|
||||
with test.step("Verify DHCP client has default route via 192.168.0.254"):
|
||||
until(lambda: route.ipv4_route_exist(client, "0.0.0.0/0", ROUTER))
|
||||
|
||||
@@ -59,14 +59,18 @@ with infamy.Test() as test:
|
||||
with test.step("Enabling DHCP client, allow option 3 and 121"):
|
||||
_, port = env.ltop.xlate("client", "data")
|
||||
|
||||
client.put_config_dict("infix-dhcp-client", {
|
||||
"dhcp-client": {
|
||||
"client-if": [{
|
||||
"if-name": f"{port}",
|
||||
"option": [
|
||||
{"id": "router"},
|
||||
{"id": "classless-static-route"}
|
||||
]
|
||||
client.put_config_dict("ietf-interfaces", {
|
||||
"interfaces": {
|
||||
"interface": [{
|
||||
"name": f"{port}",
|
||||
"ipv4": {
|
||||
"infix-dhcp-client:dhcp": {
|
||||
"option": [
|
||||
{"id": "router"},
|
||||
{"id": "classless-static-route"}
|
||||
]
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
})
|
||||
|
||||
@@ -68,14 +68,18 @@ with infamy.Test() as test:
|
||||
}})
|
||||
|
||||
client.put_config_dicts({
|
||||
"infix-dhcp-client": {
|
||||
"dhcp-client": {
|
||||
"client-if": [{
|
||||
"if-name": client["link"],
|
||||
"option": [
|
||||
{"id": "hostname"},
|
||||
{"id": "domain"}
|
||||
]
|
||||
"ietf-interfaces": {
|
||||
"interfaces": {
|
||||
"interface": [{
|
||||
"name": client["link"],
|
||||
"ipv4": {
|
||||
"infix-dhcp-client:dhcp": {
|
||||
"option": [
|
||||
{"id": "hostname"},
|
||||
{"id": "domain"}
|
||||
]
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
},
|
||||
|
||||
@@ -116,15 +116,19 @@ with infamy.Test() as test:
|
||||
"ietf-system": {
|
||||
"system": {"hostname": HOSTNM1}
|
||||
},
|
||||
"infix-dhcp-client": {
|
||||
"dhcp-client": {
|
||||
"client-if": [{
|
||||
"if-name": client1["link"],
|
||||
"option": [
|
||||
{"id": "router"},
|
||||
{"id": "client-id", "hex": HOSTCID1},
|
||||
{"id": 121}
|
||||
]
|
||||
"ietf-interfaces": {
|
||||
"interfaces": {
|
||||
"interface": [{
|
||||
"name": client1["link"],
|
||||
"ipv4": {
|
||||
"infix-dhcp-client:dhcp": {
|
||||
"option": [
|
||||
{"id": "router"},
|
||||
{"id": "client-id", "hex": HOSTCID1},
|
||||
{"id": 121}
|
||||
]
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
},
|
||||
@@ -134,16 +138,20 @@ with infamy.Test() as test:
|
||||
"ietf-system": {
|
||||
"system": {"hostname": HOSTNM2}
|
||||
},
|
||||
"infix-dhcp-client": {
|
||||
"dhcp-client": {
|
||||
"client-if": [{
|
||||
"if-name": client2["link"],
|
||||
"client-id": HOSTCID2,
|
||||
"option": [
|
||||
{"id": "router"},
|
||||
{"id": "hostname"},
|
||||
{"id": 121}
|
||||
]
|
||||
"ietf-interfaces": {
|
||||
"interfaces": {
|
||||
"interface": [{
|
||||
"name": client2["link"],
|
||||
"ipv4": {
|
||||
"infix-dhcp-client:dhcp": {
|
||||
"client-id": HOSTCID2,
|
||||
"option": [
|
||||
{"id": "router"},
|
||||
{"id": "hostname"},
|
||||
{"id": 121}
|
||||
]
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
},
|
||||
|
||||
@@ -200,17 +200,21 @@ with infamy.Test() as test:
|
||||
# the server is behaving correctly.
|
||||
|
||||
client1.put_config_dicts({
|
||||
"infix-dhcp-client": {
|
||||
"dhcp-client": {
|
||||
"client-if": [{
|
||||
"if-name": client1["server"],
|
||||
"option": [
|
||||
{"id": "hostname", "value": "auto"},
|
||||
{"id": "router"},
|
||||
{"id": "dns-server"},
|
||||
{"id": "ntp-server"},
|
||||
{"id": 121}
|
||||
]
|
||||
"ietf-interfaces": {
|
||||
"interfaces": {
|
||||
"interface": [{
|
||||
"name": client1["server"],
|
||||
"ipv4": {
|
||||
"infix-dhcp-client:dhcp": {
|
||||
"option": [
|
||||
{"id": "hostname", "value": "auto"},
|
||||
{"id": "router"},
|
||||
{"id": "dns-server"},
|
||||
{"id": "ntp-server"},
|
||||
{"id": 121}
|
||||
]
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
},
|
||||
@@ -222,17 +226,21 @@ with infamy.Test() as test:
|
||||
}})
|
||||
|
||||
client2.put_config_dicts({
|
||||
"infix-dhcp-client": {
|
||||
"dhcp-client": {
|
||||
"client-if": [{
|
||||
"if-name": client2["server"],
|
||||
"option": [
|
||||
{"id": "hostname", "value": "auto"},
|
||||
{"id": "router"},
|
||||
{"id": "dns-server"},
|
||||
{"id": "ntp-server"},
|
||||
{"id": 121}
|
||||
]
|
||||
"ietf-interfaces": {
|
||||
"interfaces": {
|
||||
"interface": [{
|
||||
"name": client2["server"],
|
||||
"ipv4": {
|
||||
"infix-dhcp-client:dhcp": {
|
||||
"option": [
|
||||
{"id": "hostname", "value": "auto"},
|
||||
{"id": "router"},
|
||||
{"id": "dns-server"},
|
||||
{"id": "ntp-server"},
|
||||
{"id": 121}
|
||||
]
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
},
|
||||
@@ -244,17 +252,21 @@ with infamy.Test() as test:
|
||||
}})
|
||||
|
||||
client3.put_config_dicts({
|
||||
"infix-dhcp-client": {
|
||||
"dhcp-client": {
|
||||
"client-if": [{
|
||||
"if-name": client3["server"],
|
||||
"option": [
|
||||
{"id": "hostname", "value": "auto"},
|
||||
{"id": "router"},
|
||||
{"id": "dns-server"},
|
||||
{"id": "ntp-server"},
|
||||
{"id": 121}
|
||||
]
|
||||
"ietf-interfaces": {
|
||||
"interfaces": {
|
||||
"interface": [{
|
||||
"name": client3["server"],
|
||||
"ipv4": {
|
||||
"infix-dhcp-client:dhcp": {
|
||||
"option": [
|
||||
{"id": "hostname", "value": "auto"},
|
||||
{"id": "router"},
|
||||
{"id": "dns-server"},
|
||||
{"id": "ntp-server"},
|
||||
{"id": 121}
|
||||
]
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
},
|
||||
|
||||
@@ -212,7 +212,6 @@ table ip nat {
|
||||
"enabled": True,
|
||||
"forwarding": True,
|
||||
"infix-ip:autoconf": {
|
||||
"enabled": True,
|
||||
"request-address": "169.254.1.1"
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user