mirror of
https://github.com/kernelkit/infix.git
synced 2026-08-02 22:03:01 +02:00
Merge pull request #1198 from kernelkit/misc
Mixed bag of fixes mostly for RPi4 Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
@@ -56,6 +56,7 @@ CONFIG_JUMP_LABEL=y
|
|||||||
# CONFIG_GCC_PLUGINS is not set
|
# CONFIG_GCC_PLUGINS is not set
|
||||||
CONFIG_MODULES=y
|
CONFIG_MODULES=y
|
||||||
CONFIG_MODULE_UNLOAD=y
|
CONFIG_MODULE_UNLOAD=y
|
||||||
|
CONFIG_PARTITION_ADVANCED=y
|
||||||
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
|
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
|
||||||
# CONFIG_COMPAT_BRK is not set
|
# CONFIG_COMPAT_BRK is not set
|
||||||
CONFIG_KSM=y
|
CONFIG_KSM=y
|
||||||
|
|||||||
@@ -51,11 +51,140 @@ factory_reset()
|
|||||||
sync
|
sync
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is_rpi()
|
||||||
|
{
|
||||||
|
[ -r /sys/firmware/devicetree/base/model ] || return 1
|
||||||
|
|
||||||
|
model=$(cat /sys/firmware/devicetree/base/model 2>/dev/null | tr -d '\0')
|
||||||
|
echo "$model" | grep -q "^Raspberry Pi"
|
||||||
|
}
|
||||||
|
|
||||||
|
wait_mmc()
|
||||||
|
{
|
||||||
|
# Try up to 50 times with 0.2s sleep = 10 second timeout
|
||||||
|
for _ in $(seq 50); do
|
||||||
|
if ls /dev/mmcblk* >/dev/null 2>&1; then
|
||||||
|
logger $opt -p user.notice -t "$nm" "MMC device available after delay"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
sleep .2
|
||||||
|
done
|
||||||
|
|
||||||
|
logger $opt -p user.warn -t "$nm" "Timeout waiting for MMC device"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# This early on we don't have the luxury of /dev/disk/by-label/$1
|
||||||
|
find_partition_by_label()
|
||||||
|
{
|
||||||
|
label="$1"
|
||||||
|
|
||||||
|
for diskpath in /sys/class/block/*; do
|
||||||
|
devname=$(basename "$diskpath")
|
||||||
|
[ -f "$diskpath/partition" ] && continue
|
||||||
|
|
||||||
|
disk="/dev/$devname"
|
||||||
|
result=$(sgdisk -p "$disk" 2>/dev/null | awk -v label="$label" -v devname="$devname" '
|
||||||
|
/^ *[0-9]/ {
|
||||||
|
if ($7 == label) {
|
||||||
|
if (devname ~ /^(mmcblk|nvme|loop)/) {
|
||||||
|
print devname "p" $1
|
||||||
|
} else {
|
||||||
|
print devname $1
|
||||||
|
}
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
')
|
||||||
|
|
||||||
|
if [ -n "$result" ]; then
|
||||||
|
echo "$result"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Expand the given partition to fill up the rest of storage (sdcard)
|
||||||
|
resize_by_label()
|
||||||
|
{
|
||||||
|
label="$1"
|
||||||
|
|
||||||
|
devname=$(find_partition_by_label "$label")
|
||||||
|
if [ -z "$devname" ]; then
|
||||||
|
logger $opt -p user.err -t "$nm" "Label \"$label\" not found"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
part="/dev/$devname"
|
||||||
|
diskname=$(basename "$(readlink -f "/sys/class/block/$devname/..")")
|
||||||
|
disk="/dev/$diskname"
|
||||||
|
partnum="${devname##*[^0-9]}"
|
||||||
|
|
||||||
|
logger $opt -p user.notice -t "$nm" "Found partition $part (partition $partnum on $disk)"
|
||||||
|
|
||||||
|
start=$(sgdisk -i "$partnum" "$disk" 2>/dev/null | grep "First sector:" | awk '{print $3}')
|
||||||
|
if [ -z "$start" ]; then
|
||||||
|
logger $opt -p user.err -t "$nm" "Could not determine start sector for partition $partnum"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf "\r\033[K[ ⋯ ] Resizing /var partition on sdcard, please wait ..." > /dev/console
|
||||||
|
logger $opt -p user.notice -t "$nm" "Expanding partition $partnum from sector $start to end of disk"
|
||||||
|
|
||||||
|
if ! sgdisk -e "$disk" 2>&1 | logger $opt -p user.notice -t "$nm"; then
|
||||||
|
logger $opt -p user.warn -t "$nm" "Failed expanding GPT on $disk"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! sgdisk -d "$partnum" "$disk" >/dev/null 2>&1; then
|
||||||
|
logger $opt -p user.warn -t "$nm" "Failed deleting partition $partnum on $disk"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! sgdisk -n "$partnum:$start:0" "$disk" >/dev/null 2>&1; then
|
||||||
|
logger $opt -p user.warn -t "$nm" "Failed recreating partition $partnum on $disk"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! sgdisk -t "$partnum:8300" "$disk" >/dev/null 2>&1; then
|
||||||
|
logger $opt -p user.warn -t "$nm" "Failed setting partition type on $disk"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! sgdisk -c "$partnum:$label" "$disk" >/dev/null 2>&1; then
|
||||||
|
logger $opt -p user.warn -t "$nm" "Failed setting partition label on $disk"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
logger $opt -p user.notice -t "$nm" "Partition table updated on $disk"
|
||||||
|
partprobe "$disk" 2>/dev/null
|
||||||
|
|
||||||
|
logger $opt -p user.notice -t "$nm" "Resizing filesystem on $part"
|
||||||
|
if ! resize2fs "$part" 2>&1 | logger $opt -p user.notice -t "$nm"; then
|
||||||
|
logger $opt -p user.warn -t "$nm" "Failed resizing filesystem on $part"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
tune2fs -O resize_inode "$part" 2>/dev/null
|
||||||
|
printf "\r\033[K[ \033[32mOK\033[0m ] Resizing /var partition on sdcard, done. Rebooting ...\n" > /dev/console
|
||||||
|
logger $opt -p user.notice -t "$nm" "Partition expanded, rebooting to complete filesystem resize"
|
||||||
|
|
||||||
|
reboot -f
|
||||||
|
}
|
||||||
|
|
||||||
mount_rw()
|
mount_rw()
|
||||||
{
|
{
|
||||||
# If something is already setup, leave it be.
|
# If something is already setup, leave it be.
|
||||||
mountpoint -q "/$1" && return 0
|
mountpoint -q "/$1" && return 0
|
||||||
|
|
||||||
|
if [ "$1" = "var" ]; then
|
||||||
|
if is_rpi && [ ! -e /mnt/aux/resized ] ; then
|
||||||
|
touch /mnt/aux/resized
|
||||||
|
resize_by_label "$1"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# TODO: Also look for UBI partitions
|
# TODO: Also look for UBI partitions
|
||||||
mount LABEL="$1" 2>/dev/null && return 0
|
mount LABEL="$1" 2>/dev/null && return 0
|
||||||
|
|
||||||
@@ -103,6 +232,15 @@ if ! logger -? |grep -q "Log to kernel"; then
|
|||||||
opt="-c"
|
opt="-c"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# On Raspberry Pi, MMC controller may probe slowly, in particular if we
|
||||||
|
# netboot (ram load) the devcice wait for it
|
||||||
|
if is_rpi && ! ls /dev/mmcblk* >/dev/null 2>&1; then
|
||||||
|
wait_mmc
|
||||||
|
fi
|
||||||
|
|
||||||
|
# The aux partition must be mounted before everything else since it's used
|
||||||
|
# for internal bookkeeping.
|
||||||
if ! mount_rw aux >/dev/null 2>&1; then
|
if ! mount_rw aux >/dev/null 2>&1; then
|
||||||
logger $opt -p user.warn -t "$nm" \
|
logger $opt -p user.warn -t "$nm" \
|
||||||
"No auxiliary partition found, software updates not supported."
|
"No auxiliary partition found, software updates not supported."
|
||||||
|
|||||||
@@ -11,9 +11,13 @@ All notable changes to the project are documented in this file.
|
|||||||
- Upgrade Linux kernel to 6.12.50 (LTS)
|
- Upgrade Linux kernel to 6.12.50 (LTS)
|
||||||
- Extend NETCONF and RESTCONF scripting documentation with operational
|
- Extend NETCONF and RESTCONF scripting documentation with operational
|
||||||
data examples, discovery patterns, and common workflow examples, issue #1156
|
data examples, discovery patterns, and common workflow examples, issue #1156
|
||||||
|
- Initial support for a zone-based firewall, based on `firewalld`, issue #448
|
||||||
|
- Automatically expand `/var` partition on SD card at first boot on RPi
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
|
|
||||||
|
- Fix #1194: CLI `text-editor` command does not do proper input sanitation
|
||||||
|
- Fix #1197: RPi4 no longer boots after BPi-R3 merge, introduced in v25.09
|
||||||
|
|
||||||
[v25.09.0][] - 2025-09-30
|
[v25.09.0][] - 2025-09-30
|
||||||
-------------------------
|
-------------------------
|
||||||
@@ -1656,6 +1660,7 @@ Supported YANG models in addition to those used by sysrepo and netopeer:
|
|||||||
|
|
||||||
[buildroot]: https://buildroot.org/
|
[buildroot]: https://buildroot.org/
|
||||||
[UNRELEASED]: https://github.com/kernelkit/infix/compare/v25.09.0...HEAD
|
[UNRELEASED]: https://github.com/kernelkit/infix/compare/v25.09.0...HEAD
|
||||||
|
[v25.10.0]: https://github.com/kernelkit/infix/compare/v25.09.0...v26.10.0
|
||||||
[v25.09.0]: https://github.com/kernelkit/infix/compare/v25.08.0...v26.09.0
|
[v25.09.0]: https://github.com/kernelkit/infix/compare/v25.08.0...v26.09.0
|
||||||
[v25.08.0]: https://github.com/kernelkit/infix/compare/v25.06.1...v26.08.0
|
[v25.08.0]: https://github.com/kernelkit/infix/compare/v25.06.1...v26.08.0
|
||||||
[v25.06.0]: https://github.com/kernelkit/infix/compare/v25.05.1...v26.06.0
|
[v25.06.0]: https://github.com/kernelkit/infix/compare/v25.05.1...v26.06.0
|
||||||
|
|||||||
@@ -1,72 +0,0 @@
|
|||||||
* TODO Add support for firewall
|
|
||||||
- [X] All "implicit" policies in zones are now policies: intra- and inter-zone policies
|
|
||||||
- [X] Add locked rules for implicit drop/reject policy as last rule in policy (ANY, ANY)
|
|
||||||
- [X] Firewall logs should show IN=iface (IIF) before SOURCE
|
|
||||||
- [X] Interfaces are not defaulting to the default zone, must handle bridge
|
|
||||||
ports and changes to enslavement, so regenerate every time is a must!
|
|
||||||
- [ ] firewalld helpers -- possibly for conntrack, e.g., ftp
|
|
||||||
- [ ] With =modprobe br_netfilter= firewalld would see *all* traffic, but there are
|
|
||||||
issues, <https://github.com/firewalld/firewalld/issues/1236>, and limits to what
|
|
||||||
seem to be possible atm. You may also need to enable these callbacks:
|
|
||||||
=echo 1 | sudo tee /proc/sys/net/bridge/bridge-nf-call-iptables=
|
|
||||||
=echo 1 | sudo tee /proc/sys/net/bridge/bridge-nf-call-ip6tables=
|
|
||||||
=echo 1 | sudo tee /proc/sys/net/bridge/bridge-nf-call-arptables=
|
|
||||||
- [X] Add missing upper to port forward since port ranges are supported, see services!
|
|
||||||
- [X] =[do] show firewall= not available yet
|
|
||||||
- [X] Add RPC to pause firewall using =firewall-cmd --panic-on= and restart
|
|
||||||
firewall again with =firewall-cmd --panic-off=. The current state can
|
|
||||||
be queried using =firewall-cmd --query-panic=, which returns =yes=
|
|
||||||
- [X] Remove debug log messages!
|
|
||||||
- [X] Add "Log Messages" section to =show firewall= when =LogDenied ≠ off=
|
|
||||||
- [ ] Investigate filtering out firewall log messages from other log files
|
|
||||||
- [1/2] Rename policy->policy to policy->action, and replace allow->forward
|
|
||||||
- [X] Rename zone->sources to networks
|
|
||||||
- [X] A zone's action is for ingress, clarify this if missing!
|
|
||||||
- [X] Any services/ports listed in a zone with policy:accept are a NO-OP
|
|
||||||
- [X] =firwall-cmd --reload= takes fooooorever! :-(
|
|
||||||
- [X] If forwarding is disabled in a zone then the zone matrix should
|
|
||||||
show deny for the same zone-to-zone communication
|
|
||||||
- [X] We should show the implicit rules for communicating with the HOST
|
|
||||||
- [X] Investigate "padlock" on built-in policys (and zones?) and expose more?
|
|
||||||
- [X] Document established,related somewhere, fixed/padlocked policy? Also,
|
|
||||||
document why this is a good idea to always have enabled. See RH docs.
|
|
||||||
- [ ] Podman published ports, <https://firewalld.org/2024/11/strict-forward-ports>
|
|
||||||
- [ ] Software fastpath <https://firewalld.org/2023/05/nftables-flowtable>
|
|
||||||
- +[ ] Allow overriding/editing immutable policies and zones+
|
|
||||||
- [X] Add tests: basic (end device), wan-lan, wan-lan-dmz, +hammer (stress)+
|
|
||||||
- [X] Add documentation
|
|
||||||
- See <https://docs.rockylinux.org/guides/security/firewalld-beginners/>
|
|
||||||
- Add some tool tips: nc, nmap, ping, and socat to stress the firewall
|
|
||||||
- [X] Fix inference so we can remove defaults from factory-config!
|
|
||||||
- [X] Add iperf service
|
|
||||||
- [X] Add nftables ownership=yes setting, introduced in later firewalld versions
|
|
||||||
- [ ] Investigate fail2ban integration with firewalld, for more info, see:
|
|
||||||
https://github.com/firewalld/firewalld/issues/1466#issuecomment-2773130569
|
|
||||||
- [ ] Update screenshots for documentation
|
|
||||||
- [ ] Review both cli-pretty and yanger code
|
|
||||||
- [ ] Review default-zone handling (needed?)
|
|
||||||
- [ ] Clean up =INFER_POLICY= ifdefs
|
|
||||||
- [ ] Revisit built-in fallback zones (public, block, drop)
|
|
||||||
|
|
||||||
* TODO doc: User Guide
|
|
||||||
|
|
||||||
- Feature set and scope, e.g.
|
|
||||||
- Device discovery: LLDP, mDNS-SD how do they work, interfacing with Windows/macOS/Linux
|
|
||||||
- Network redundancy protocols: STP/RSTP, MRP
|
|
||||||
- Configuring the system; using ifupdown2, enabling/disabling services
|
|
||||||
- Diagnosing the system; using rmon, port mirroring, debugging services, searching logs
|
|
||||||
- Limitations, e.g., PRP/HSR or IEEE 802.1CB will not be possible to support
|
|
||||||
- Tips & Trix
|
|
||||||
|
|
||||||
* TODO document how to set up passwordless SSH
|
|
||||||
* TODO add setup wizard, based on pdmenu
|
|
||||||
|
|
||||||
- setup-port script to tweak ethtool settings
|
|
||||||
- setup-iface script to configure a layer-3 interface
|
|
||||||
- setup-bridge script that creates a new bridge with config from cmdline
|
|
||||||
- setup-firewall script that can do basic firewall rules and masquerading
|
|
||||||
|
|
||||||
* TODO split out qemu Config.in to a "make run-menuconfing"
|
|
||||||
* TODO rename qemu/ to run/, perhaps?
|
|
||||||
* TODO ship qemu/* with output/images/ for stand-alone runs of older builds
|
|
||||||
|
|
||||||
+104
-44
@@ -16,23 +16,79 @@ To simplify RESTCONF operations, create a `curl.sh` wrapper script:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
# RESTCONF CLI wrapper for curl
|
||||||
|
|
||||||
AUTH=${AUTH:-admin:admin}
|
# Show usage and exit
|
||||||
|
usage()
|
||||||
|
{
|
||||||
|
cat <<-EOF >&2
|
||||||
|
Usage: $0 [-h HOST] [-d DATASTORE] [-u USER:PASS] METHOD PATH [CURL_ARGS...]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-h HOST Target host (default: infix.local)
|
||||||
|
-d DS Datastore: running, operational, startup (default: running)
|
||||||
|
-u CREDS Credentials as user:pass (default: admin:admin)
|
||||||
|
|
||||||
|
Methods: GET, POST, PUT, PATCH, DELETE
|
||||||
|
EOF
|
||||||
|
exit "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Default values
|
||||||
HOST=${HOST:-infix.local}
|
HOST=${HOST:-infix.local}
|
||||||
|
DATASTORE=running
|
||||||
|
AUTH=admin:admin
|
||||||
|
|
||||||
method=$1
|
# Parse options
|
||||||
path=$2
|
while getopts "h:d:u:" opt; do
|
||||||
|
case $opt in
|
||||||
|
h) HOST="$OPTARG" ;;
|
||||||
|
d) DATASTORE="$OPTARG" ;;
|
||||||
|
u) AUTH="$OPTARG" ;;
|
||||||
|
*) usage 1 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
shift $((OPTIND - 1))
|
||||||
|
|
||||||
|
# Validate required arguments
|
||||||
|
if [ $# -lt 2 ]; then
|
||||||
|
echo "Error: METHOD and PATH are required" >&2
|
||||||
|
usage 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
METHOD=$1
|
||||||
|
PATH=$2
|
||||||
shift 2
|
shift 2
|
||||||
|
|
||||||
set -x
|
# Ensure PATH starts with /
|
||||||
exec curl \
|
case "$PATH" in
|
||||||
--insecure \
|
/*) ;;
|
||||||
--user ${AUTH} \
|
*) PATH="/$PATH" ;;
|
||||||
--request ${method} \
|
esac
|
||||||
--header "Content-Type: application/yang-data+json" \
|
|
||||||
--header "Accept: application/yang-data+json" \
|
# Build URL based on datastore
|
||||||
"$@" \
|
case "$DATASTORE" in
|
||||||
https://${HOST}/restconf/ds/ietf-datastores:${path}
|
running|startup)
|
||||||
|
URL="https://${HOST}/restconf/data${PATH}"
|
||||||
|
;;
|
||||||
|
operational)
|
||||||
|
URL="https://${HOST}/restconf/data${PATH}"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Error: Invalid datastore '$DATASTORE'. Use: running, operational, or startup" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Execute curl with all remaining arguments passed through
|
||||||
|
exec /usr/bin/curl \
|
||||||
|
--insecure \
|
||||||
|
--user "${AUTH}" \
|
||||||
|
--request "${METHOD}" \
|
||||||
|
--header "Content-Type: application/yang-data+json" \
|
||||||
|
--header "Accept: application/yang-data+json" \
|
||||||
|
"$@" \
|
||||||
|
"${URL}"
|
||||||
```
|
```
|
||||||
|
|
||||||
Make it executable:
|
Make it executable:
|
||||||
@@ -41,12 +97,16 @@ Make it executable:
|
|||||||
~$ chmod +x curl.sh
|
~$ chmod +x curl.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
This wrapper handles authentication, headers, and the base URL construction,
|
This wrapper handles authentication, headers, SSL certificates, and URL
|
||||||
making commands much cleaner. You can override defaults with environment
|
construction, making commands much cleaner. You can override defaults with
|
||||||
variables:
|
command-line options or environment variables:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
~$ HOST=192.168.1.10 AUTH=admin:secret ./curl.sh GET running/...
|
# Using command-line options
|
||||||
|
~$ ./curl.sh -h 192.168.1.10 -d operational -u admin:secret GET /ietf-interfaces:interfaces
|
||||||
|
|
||||||
|
# Using environment variables
|
||||||
|
~$ HOST=192.168.1.10 ./curl.sh GET /ietf-system:system
|
||||||
```
|
```
|
||||||
|
|
||||||
The examples below show both raw `curl` commands and the equivalent using
|
The examples below show both raw `curl` commands and the equivalent using
|
||||||
@@ -63,7 +123,7 @@ practical workflows.
|
|||||||
**List all interface names:**
|
**List all interface names:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
~$ ./curl.sh example.local GET operational/ietf-interfaces:interfaces 2>/dev/null | jq -r '.["ietf-interfaces:interfaces"]["interface"][].name'
|
~$ ./curl.sh -h example.local -d operational GET /ietf-interfaces:interfaces 2>/dev/null | jq -r '.["ietf-interfaces:interfaces"]["interface"][].name'
|
||||||
lo
|
lo
|
||||||
e0
|
e0
|
||||||
e1
|
e1
|
||||||
@@ -89,7 +149,7 @@ This returns all supported YANG modules, revisions, and features.
|
|||||||
Useful for exploration or backup:
|
Useful for exploration or backup:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
~$ ./curl.sh example.local GET running -o backup.json
|
~$ ./curl.sh -h example.local GET / -o backup.json
|
||||||
```
|
```
|
||||||
|
|
||||||
### Common Workflow Patterns
|
### Common Workflow Patterns
|
||||||
@@ -99,21 +159,21 @@ Useful for exploration or backup:
|
|||||||
Get all interfaces with IPs and search:
|
Get all interfaces with IPs and search:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
~$ ./curl.sh example.local GET operational/ietf-interfaces:interfaces 2>/dev/null \
|
~$ ./curl.sh -h example.local -d operational GET /ietf-interfaces:interfaces 2>/dev/null \
|
||||||
| jq -r '.["ietf-interfaces:interfaces"]["interface"][] | select(.["ietf-ip:ipv4"]["address"][]?.ip == "192.168.1.100") | .name'
|
| jq -r '.["ietf-interfaces:interfaces"]["interface"][] | select(.["ietf-ip:ipv4"]["address"][]?.ip == "192.168.1.100") | .name'
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Pattern 2: List all interfaces that are down
|
#### Pattern 2: List all interfaces that are down
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
~$ ./curl.sh example.local GET operational/ietf-interfaces:interfaces 2>/dev/null \
|
~$ ./curl.sh -h example.local -d operational GET /ietf-interfaces:interfaces 2>/dev/null \
|
||||||
| jq -r '.["ietf-interfaces:interfaces"]["interface"][] | select(.["oper-status"] == "down") | .name'
|
| jq -r '.["ietf-interfaces:interfaces"]["interface"][] | select(.["oper-status"] == "down") | .name'
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Pattern 3: Get statistics for all interfaces
|
#### Pattern 3: Get statistics for all interfaces
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
~$ ./curl.sh example.local GET operational/ietf-interfaces:interfaces 2>/dev/null \
|
~$ ./curl.sh -h example.local -d operational GET /ietf-interfaces:interfaces 2>/dev/null \
|
||||||
| jq -r '.["ietf-interfaces:interfaces"]["interface"][] | "\(.name): RX \(.statistics["in-octets"]) TX \(.statistics["out-octets"])"'
|
| jq -r '.["ietf-interfaces:interfaces"]["interface"][] | "\(.name): RX \(.statistics["in-octets"]) TX \(.statistics["out-octets"])"'
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -128,7 +188,7 @@ e1: RX 0 TX 0
|
|||||||
#### Pattern 4: Check if interface exists before configuring
|
#### Pattern 4: Check if interface exists before configuring
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
~$ if ./curl.sh example.local GET running/ietf-interfaces:interfaces/interface=eth0 2>/dev/null | grep -q "ietf-interfaces:interface"; then
|
~$ if ./curl.sh -h example.local GET /ietf-interfaces:interfaces/interface=eth0 2>/dev/null | grep -q "ietf-interfaces:interface"; then
|
||||||
echo "Interface eth0 exists"
|
echo "Interface eth0 exists"
|
||||||
else
|
else
|
||||||
echo "Interface eth0 not found"
|
echo "Interface eth0 not found"
|
||||||
@@ -157,7 +217,7 @@ Example of fetching JSON configuration data:
|
|||||||
**Using curl.sh:**
|
**Using curl.sh:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
~$ ./curl.sh example.local GET running/ietf-system:system/hostname
|
~$ ./curl.sh -h example.local GET /ietf-system:system/hostname
|
||||||
{
|
{
|
||||||
"ietf-system:system": {
|
"ietf-system:system": {
|
||||||
"hostname": "foo"
|
"hostname": "foo"
|
||||||
@@ -181,7 +241,7 @@ Example of updating configuration with inline JSON data:
|
|||||||
**Using curl.sh:**
|
**Using curl.sh:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
~$ ./curl.sh example.local PATCH running/ietf-system:system \
|
~$ ./curl.sh -h example.local PATCH /ietf-system:system \
|
||||||
-d '{"ietf-system:system":{"hostname":"bar"}}'
|
-d '{"ietf-system:system":{"hostname":"bar"}}'
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -190,8 +250,8 @@ Example of updating configuration with inline JSON data:
|
|||||||
Add an IP address to the loopback interface:
|
Add an IP address to the loopback interface:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
~$ ./curl.sh example.local POST \
|
~$ ./curl.sh -h example.local POST \
|
||||||
running/ietf-interfaces:interfaces/interface=lo/ietf-ip:ipv4/address=192.168.254.254 \
|
/ietf-interfaces:interfaces/interface=lo/ietf-ip:ipv4/address=192.168.254.254 \
|
||||||
-d '{ "prefix-length": 32 }'
|
-d '{ "prefix-length": 32 }'
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -200,8 +260,8 @@ Add an IP address to the loopback interface:
|
|||||||
Remove an IP address from the loopback interface:
|
Remove an IP address from the loopback interface:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
~$ ./curl.sh example.local DELETE \
|
~$ ./curl.sh -h example.local DELETE \
|
||||||
running/ietf-interfaces:interfaces/interface=lo/ietf-ip:ipv4/address=192.168.254.254
|
/ietf-interfaces:interfaces/interface=lo/ietf-ip:ipv4/address=192.168.254.254
|
||||||
```
|
```
|
||||||
|
|
||||||
### Copy Running to Startup
|
### Copy Running to Startup
|
||||||
@@ -228,8 +288,8 @@ and then update startup with it:
|
|||||||
**Using curl.sh:**
|
**Using curl.sh:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
~$ ./curl.sh example.local GET running -o running-config.json
|
~$ ./curl.sh -h example.local GET / -o running-config.json
|
||||||
~$ ./curl.sh example.local PUT startup -d @running-config.json
|
~$ ./curl.sh -h example.local -d startup PUT / -d @running-config.json
|
||||||
```
|
```
|
||||||
|
|
||||||
## Operational Data
|
## Operational Data
|
||||||
@@ -239,7 +299,7 @@ and then update startup with it:
|
|||||||
Get the running configuration for the loopback interface:
|
Get the running configuration for the loopback interface:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
~$ ./curl.sh example.local GET running/ietf-interfaces:interfaces/interface=lo
|
~$ ./curl.sh -h example.local GET /ietf-interfaces:interfaces/interface=lo
|
||||||
```
|
```
|
||||||
|
|
||||||
### Read Interface Operational State
|
### Read Interface Operational State
|
||||||
@@ -247,7 +307,7 @@ Get the running configuration for the loopback interface:
|
|||||||
Get operational data (state, statistics, etc.) for an interface:
|
Get operational data (state, statistics, etc.) for an interface:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
~$ ./curl.sh example.local GET operational/ietf-interfaces:interfaces/interface=lo
|
~$ ./curl.sh -h example.local -d operational GET /ietf-interfaces:interfaces/interface=lo
|
||||||
```
|
```
|
||||||
|
|
||||||
This includes administrative and operational state, MAC address, MTU, and
|
This includes administrative and operational state, MAC address, MTU, and
|
||||||
@@ -258,7 +318,7 @@ statistics counters.
|
|||||||
Extract specific statistics using `jq`:
|
Extract specific statistics using `jq`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
~$ ./curl.sh example.local GET operational/ietf-interfaces:interfaces/interface=eth0 2>/dev/null \
|
~$ ./curl.sh -h example.local -d operational GET /ietf-interfaces:interfaces/interface=eth0 2>/dev/null \
|
||||||
| jq -r '.["ietf-interfaces:interfaces"]["interface"][0]["statistics"]["in-octets"]'
|
| jq -r '.["ietf-interfaces:interfaces"]["interface"][0]["statistics"]["in-octets"]'
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -267,7 +327,7 @@ Extract specific statistics using `jq`:
|
|||||||
Get operational data for all interfaces:
|
Get operational data for all interfaces:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
~$ ./curl.sh example.local GET operational/ietf-interfaces:interfaces
|
~$ ./curl.sh -h example.local -d operational GET /ietf-interfaces:interfaces
|
||||||
```
|
```
|
||||||
|
|
||||||
### Read Routing Table
|
### Read Routing Table
|
||||||
@@ -275,7 +335,7 @@ Get operational data for all interfaces:
|
|||||||
Get the IPv4 routing table:
|
Get the IPv4 routing table:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
~$ ./curl.sh example.local GET operational/ietf-routing:routing/ribs/rib=ipv4-default
|
~$ ./curl.sh -h example.local -d operational GET /ietf-routing:routing/ribs/rib=ipv4-default
|
||||||
```
|
```
|
||||||
|
|
||||||
### Read OSPF State
|
### Read OSPF State
|
||||||
@@ -283,13 +343,13 @@ Get the IPv4 routing table:
|
|||||||
Get OSPF operational data (neighbors, routes, etc.):
|
Get OSPF operational data (neighbors, routes, etc.):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
~$ ./curl.sh example.local GET operational/ietf-routing:routing/control-plane-protocols/control-plane-protocol=ietf-ospf:ospfv2,default
|
~$ ./curl.sh -h example.local -d operational GET /ietf-routing:routing/control-plane-protocols/control-plane-protocol=ietf-ospf:ospfv2,default
|
||||||
```
|
```
|
||||||
|
|
||||||
Or get just the neighbor information:
|
Or get just the neighbor information:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
~$ ./curl.sh example.local GET operational/ietf-routing:routing/control-plane-protocols/control-plane-protocol=ietf-ospf:ospfv2,default/ietf-ospf:ospf/areas/area=0.0.0.0/interfaces
|
~$ ./curl.sh -h example.local -d operational GET /ietf-routing:routing/control-plane-protocols/control-plane-protocol=ietf-ospf:ospfv2,default/ietf-ospf:ospf/areas/area=0.0.0.0/interfaces
|
||||||
```
|
```
|
||||||
|
|
||||||
## System Operations (RPCs)
|
## System Operations (RPCs)
|
||||||
@@ -345,22 +405,22 @@ Create a `Makefile` to simplify common operations:
|
|||||||
HOST ?= infix.local
|
HOST ?= infix.local
|
||||||
|
|
||||||
lo-running:
|
lo-running:
|
||||||
./curl.sh $(HOST) GET running/ietf-interfaces:interfaces/interface=lo
|
./curl.sh -h $(HOST) GET /ietf-interfaces:interfaces/interface=lo
|
||||||
|
|
||||||
lo-operational:
|
lo-operational:
|
||||||
./curl.sh $(HOST) GET operational/ietf-interfaces:interfaces/interface=lo
|
./curl.sh -h $(HOST) -d operational GET /ietf-interfaces:interfaces/interface=lo
|
||||||
|
|
||||||
lo-add-ip:
|
lo-add-ip:
|
||||||
./curl.sh $(HOST) POST \
|
./curl.sh -h $(HOST) POST \
|
||||||
running/ietf-interfaces:interfaces/interface=lo/ietf-ip:ipv4/address=192.168.254.254 \
|
/ietf-interfaces:interfaces/interface=lo/ietf-ip:ipv4/address=192.168.254.254 \
|
||||||
-d '{ "prefix-length": 32 }'
|
-d '{ "prefix-length": 32 }'
|
||||||
|
|
||||||
lo-del-ip:
|
lo-del-ip:
|
||||||
./curl.sh $(HOST) DELETE \
|
./curl.sh -h $(HOST) DELETE \
|
||||||
running/ietf-interfaces:interfaces/interface=lo/ietf-ip:ipv4/address=192.168.254.254
|
/ietf-interfaces:interfaces/interface=lo/ietf-ip:ipv4/address=192.168.254.254
|
||||||
|
|
||||||
%-stats:
|
%-stats:
|
||||||
@./curl.sh $(HOST) GET operational/ietf-interfaces:interfaces/interface=$* 2>/dev/null \
|
@./curl.sh -h $(HOST) -d operational GET /ietf-interfaces:interfaces/interface=$* 2>/dev/null \
|
||||||
| jq -r '.["ietf-interfaces:interfaces"]["interface"][0]["statistics"]["in-octets"]'
|
| jq -r '.["ietf-interfaces:interfaces"]["interface"][0]["statistics"]["in-octets"]'
|
||||||
|
|
||||||
%-monitor:
|
%-monitor:
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ define BANANA_PI_R3_LINUX_CONFIG_FIXUPS
|
|||||||
$(call KCONFIG_SET_OPT,CONFIG_USB_XHCI_MTK,m)
|
$(call KCONFIG_SET_OPT,CONFIG_USB_XHCI_MTK,m)
|
||||||
$(call KCONFIG_SET_OPT,CONFIG_PHY_MTK_TPHY,m)
|
$(call KCONFIG_SET_OPT,CONFIG_PHY_MTK_TPHY,m)
|
||||||
$(call KCONFIG_SET_OPT,CONFIG_PHY_MTK_XSPHY,m)
|
$(call KCONFIG_SET_OPT,CONFIG_PHY_MTK_XSPHY,m)
|
||||||
$(call KCONFIG_SET_OPT,CONFIG_REGULATOR_GPIO,m)
|
$(call KCONFIG_SET_OPT,CONFIG_REGULATOR_GPIO,y)
|
||||||
$(call KCONFIG_SET_OPT,CONFIG_REGULATOR_MT6380,m)
|
$(call KCONFIG_SET_OPT,CONFIG_REGULATOR_MT6380,m)
|
||||||
$(call KCONFIG_SET_OPT,CONFIG_PWM_MEDIATEK,m)
|
$(call KCONFIG_SET_OPT,CONFIG_PWM_MEDIATEK,m)
|
||||||
$(call KCONFIG_SET_OPT,CONFIG_SENSORS_PWM_FAN,m)
|
$(call KCONFIG_SET_OPT,CONFIG_SENSORS_PWM_FAN,m)
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# The CONFIG_REGULATOR_GPIO=y is load bearing for booting the RPi4 from
|
||||||
|
# SD card, see regulator-sd-io-1v8 in bcm2711-rpi-4-b.dts for details.
|
||||||
define RASPBERRY_PI_4_LINUX_CONFIG_FIXUPS
|
define RASPBERRY_PI_4_LINUX_CONFIG_FIXUPS
|
||||||
$(call KCONFIG_ENABLE_OPT,CONFIG_SOUND)
|
$(call KCONFIG_ENABLE_OPT,CONFIG_SOUND)
|
||||||
$(call KCONFIG_ENABLE_OPT,CONFIG_SND)
|
$(call KCONFIG_ENABLE_OPT,CONFIG_SND)
|
||||||
@@ -32,6 +34,7 @@ define RASPBERRY_PI_4_LINUX_CONFIG_FIXUPS
|
|||||||
$(call KCONFIG_ENABLE_OPT,CONFIG_NET_VENDOR_BROADCOM)
|
$(call KCONFIG_ENABLE_OPT,CONFIG_NET_VENDOR_BROADCOM)
|
||||||
$(call KCONFIG_SET_OPT,CONFIG_BCMGENET,m)
|
$(call KCONFIG_SET_OPT,CONFIG_BCMGENET,m)
|
||||||
$(call KCONFIG_SET_OPT,CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY,m)
|
$(call KCONFIG_SET_OPT,CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY,m)
|
||||||
|
$(call KCONFIG_SET_OPT,CONFIG_REGULATOR_GPIO,y)
|
||||||
$(call KCONFIG_ENABLE_OPT,CONFIG_COMMON_CLK_BCM2835)
|
$(call KCONFIG_ENABLE_OPT,CONFIG_COMMON_CLK_BCM2835)
|
||||||
$(call KCONFIG_ENABLE_OPT,CONFIG_CLK_RASPBERRYPI)
|
$(call KCONFIG_ENABLE_OPT,CONFIG_CLK_RASPBERRYPI)
|
||||||
$(call KCONFIG_ENABLE_OPT,CONFIG_DRM)
|
$(call KCONFIG_ENABLE_OPT,CONFIG_DRM)
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
# Locally calculated
|
# Locally calculated
|
||||||
sha256 9d9d33b873917ca5d0bdcc47a36d2fd385971ab0c045d1472fcadf95ee5bcf5b LICENCE
|
sha256 9d9d33b873917ca5d0bdcc47a36d2fd385971ab0c045d1472fcadf95ee5bcf5b LICENCE
|
||||||
sha256 a6fe769a8f24a065b274f4e0f5f1fec634b2aae5bdd586aa6f71fe60ca6b8a64 klish-plugin-sysrepo-30bc6294489807ea026abed20f94d1ad1583cc6b-git4.tar.gz
|
sha256 cfe1064849a158f3eb9e82f12a709723115fc9bc4d30056e0e96ea0ba03672a2 klish-plugin-sysrepo-4e86a836c9b09a14c9625ea3d3b56b6578be4833-git4.tar.gz
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#
|
#
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
KLISH_PLUGIN_SYSREPO_VERSION = 30bc6294489807ea026abed20f94d1ad1583cc6b
|
KLISH_PLUGIN_SYSREPO_VERSION = 4e86a836c9b09a14c9625ea3d3b56b6578be4833
|
||||||
KLISH_PLUGIN_SYSREPO_SITE = https://github.com/kernelkit/klish-plugin-sysrepo.git
|
KLISH_PLUGIN_SYSREPO_SITE = https://github.com/kernelkit/klish-plugin-sysrepo.git
|
||||||
#KLISH_PLUGIN_SYSREPO_VERSION = cdd3eb51a7f7ee0ed5bd925fa636061d3b1b85fb
|
#KLISH_PLUGIN_SYSREPO_VERSION = cdd3eb51a7f7ee0ed5bd925fa636061d3b1b85fb
|
||||||
#KLISH_PLUGIN_SYSREPO_SITE = https://src.libcode.org/pkun/klish-plugin-sysrepo.git
|
#KLISH_PLUGIN_SYSREPO_SITE = https://src.libcode.org/pkun/klish-plugin-sysrepo.git
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
image cfg.ext4 {
|
image cfg.ext4 {
|
||||||
empty = true
|
empty = true
|
||||||
temporary = true
|
temporary = true
|
||||||
@@ -27,19 +26,19 @@ image #INFIX_ID##VERSION#-bpi-r3-sdcard.img {
|
|||||||
partition bl2 {
|
partition bl2 {
|
||||||
image = "bl2.img"
|
image = "bl2.img"
|
||||||
offset = 1024s # 0x80000 = sector 1024
|
offset = 1024s # 0x80000 = sector 1024
|
||||||
size = 4M # 0x400000
|
size = 4M # 0x400000
|
||||||
bootable = true
|
bootable = true
|
||||||
}
|
}
|
||||||
|
|
||||||
# Factory/calibration data (sectors 9216-13311)
|
# Factory/calibration data (sectors 9216-13311)
|
||||||
partition factory {
|
partition factory {
|
||||||
offset = 4608K # 0x480000
|
offset = 4608K # 0x480000
|
||||||
size = 2M # 0x200000
|
size = 2M # 0x200000
|
||||||
}
|
}
|
||||||
|
|
||||||
# FIP partition - BL31 + U-Boot (sectors 13312-17407)
|
# FIP partition - BL31 + U-Boot (sectors 13312-17407)
|
||||||
partition fip {
|
partition fip {
|
||||||
# partition-type = 0x83 # Linux filesystem
|
# partition-type = 0x83 # Linux filesystem
|
||||||
image = "fip.bin"
|
image = "fip.bin"
|
||||||
offset = 13312s
|
offset = 13312s
|
||||||
size = 4096s
|
size = 4096s
|
||||||
|
|||||||
@@ -48,14 +48,14 @@ image #INFIX_ID##VERSION#-rpi4-sdcard.img {
|
|||||||
partition primary {
|
partition primary {
|
||||||
partition-type-uuid = 0FC63DAF-8483-4772-8E79-3D69D8477DE4
|
partition-type-uuid = 0FC63DAF-8483-4772-8E79-3D69D8477DE4
|
||||||
bootable = true
|
bootable = true
|
||||||
size = 200M
|
size = 250M
|
||||||
image = "rootfs.squashfs"
|
image = "rootfs.squashfs"
|
||||||
}
|
}
|
||||||
|
|
||||||
partition secondary {
|
partition secondary {
|
||||||
partition-type-uuid = 0FC63DAF-8483-4772-8E79-3D69D8477DE4
|
partition-type-uuid = 0FC63DAF-8483-4772-8E79-3D69D8477DE4
|
||||||
bootable = true
|
bootable = true
|
||||||
size = 200M
|
size = 250M
|
||||||
image = "rootfs.squashfs"
|
image = "rootfs.squashfs"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,152 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
usage()
|
||||||
|
{
|
||||||
|
cat <<EOF
|
||||||
|
Create Raspberry Pi 4 SD card image from build artifacts.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
$0 [OPTIONS]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-h This help text
|
||||||
|
-b boot-dir Path to bootloader build directory, default: O= or output/
|
||||||
|
-r root-dir Path to Linux rootfs.squashfs, default O= or output/
|
||||||
|
|
||||||
|
Description:
|
||||||
|
When called without arguments (from Buildroot), uses environment variables:
|
||||||
|
BINARIES_DIR, BUILD_DIR, BR2_EXTERNAL_INFIX_PATH, RELEASE, INFIX_ID
|
||||||
|
|
||||||
|
When called with arguments, sets up standalone mode and combines artifacts
|
||||||
|
from separate boot and rootfs sources.
|
||||||
|
|
||||||
|
Output:
|
||||||
|
The resulting SD card image is saved to boot-dir/images/*-sdcard.img
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
# Using separate build directories:
|
||||||
|
$0 -b x-boot -r output
|
||||||
|
|
||||||
|
# Using a rootfs file directly:
|
||||||
|
$0 -b x-boot -r ~/Downloads/rootfs.squashfs
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
getconfig()
|
||||||
|
{
|
||||||
|
[ -f .config ] || return 1
|
||||||
|
grep "^$1=" .config | sed -e "s/$1=\"\?\([^\"]*\)\"\?/\1/"
|
||||||
|
}
|
||||||
|
|
||||||
|
find_build_dir()
|
||||||
|
{
|
||||||
|
# Check O= environment variable first
|
||||||
|
if [ -n "$O" ] && [ -f "$O/.config" ]; then
|
||||||
|
echo "$O"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check output/ directory
|
||||||
|
if [ -f "output/.config" ]; then
|
||||||
|
echo "output"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parse command line options
|
||||||
|
STANDALONE=0
|
||||||
|
while getopts "hb:r:" flag; do
|
||||||
|
case "${flag}" in
|
||||||
|
h) usage; exit 0;;
|
||||||
|
b) BOOT_DIR=${OPTARG}; STANDALONE=1;;
|
||||||
|
r) ROOT_DIR=${OPTARG}; STANDALONE=1;;
|
||||||
|
*) usage; exit 1;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Standalone mode: set up environment from build directories
|
||||||
|
if [ "$STANDALONE" -eq 1 ] || [ $# -gt 0 ]; then
|
||||||
|
STANDALONE=1
|
||||||
|
|
||||||
|
# Find BR2_EXTERNAL_INFIX_PATH (current script is in src/board/raspberry-pi-4/)
|
||||||
|
SCRIPT_DIR=$(dirname "$0")
|
||||||
|
BR2_EXTERNAL_INFIX_PATH=$(cd "$SCRIPT_DIR/../../.." && pwd)
|
||||||
|
|
||||||
|
# Find boot directory if not specified (try common patterns)
|
||||||
|
if [ -z "$BOOT_DIR" ]; then
|
||||||
|
for dir in x-boot build-boot output-boot; do
|
||||||
|
if [ -f "$dir/.config" ]; then
|
||||||
|
BOOT_DIR="$dir"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ -z "$BOOT_DIR" ]; then
|
||||||
|
BOOT_DIR=$(find_build_dir) || {
|
||||||
|
echo "Error: Could not find boot directory. Use -b option" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Find rootfs if not specified
|
||||||
|
if [ -z "$ROOT_DIR" ]; then
|
||||||
|
ROOT_DIR=$(find_build_dir) || {
|
||||||
|
echo "Error: Could not find rootfs directory. Set O= or use -r option" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set up environment variables (use BOOT_DIR as base)
|
||||||
|
export BINARIES_DIR="$BOOT_DIR/images"
|
||||||
|
export BUILD_DIR="$BOOT_DIR/build"
|
||||||
|
export BR2_EXTERNAL_INFIX_PATH
|
||||||
|
export RELEASE=${RELEASE:-""}
|
||||||
|
export INFIX_ID=${INFIX_ID:-"infix"}
|
||||||
|
|
||||||
|
# Add host tools to PATH (for genimage, etc.)
|
||||||
|
for dir in "$BOOT_DIR" "$ROOT_DIR"; do
|
||||||
|
if [ -d "$dir/host/bin" ]; then
|
||||||
|
export PATH="$dir/host/bin:$PATH"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Copy rootfs and partition images to boot directory
|
||||||
|
mkdir -p "$BINARIES_DIR"
|
||||||
|
if [ -f "$ROOT_DIR" ]; then
|
||||||
|
# Direct path to rootfs.squashfs file
|
||||||
|
echo "Copying rootfs from $ROOT_DIR to $BINARIES_DIR/rootfs.squashfs"
|
||||||
|
cp "$ROOT_DIR" "$BINARIES_DIR/rootfs.squashfs"
|
||||||
|
elif [ -f "$ROOT_DIR/images/rootfs.squashfs" ]; then
|
||||||
|
# Build directory with images/ - copy rootfs and partition images
|
||||||
|
echo "Copying rootfs and partitions from $ROOT_DIR/images/ to $BINARIES_DIR/"
|
||||||
|
cp "$ROOT_DIR/images/rootfs.squashfs" "$BINARIES_DIR/"
|
||||||
|
# Copy partition images (aux.ext4, cfg.ext4, var.ext4) if they exist
|
||||||
|
for img in aux.ext4 cfg.ext4 var.ext4; do
|
||||||
|
if [ -f "$ROOT_DIR/images/$img" ]; then
|
||||||
|
cp "$ROOT_DIR/images/$img" "$BINARIES_DIR/"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
elif [ -f "$ROOT_DIR/rootfs.squashfs" ]; then
|
||||||
|
# Directory directly containing rootfs.squashfs
|
||||||
|
echo "Copying rootfs from $ROOT_DIR/rootfs.squashfs to $BINARIES_DIR/"
|
||||||
|
cp "$ROOT_DIR/rootfs.squashfs" "$BINARIES_DIR/"
|
||||||
|
# Copy partition images if they exist in same directory
|
||||||
|
for img in aux.ext4 cfg.ext4 var.ext4; do
|
||||||
|
if [ -f "$ROOT_DIR/$img" ]; then
|
||||||
|
cp "$ROOT_DIR/$img" "$BINARIES_DIR/"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
else
|
||||||
|
echo "Error: Could not find rootfs.squashfs in $ROOT_DIR" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
BOARD_DIR=$(dirname "$0")
|
BOARD_DIR=$(dirname "$0")
|
||||||
GENIMAGE_CFG="${BUILD_DIR}/genimage.cfg"
|
GENIMAGE_CFG="${BUILD_DIR}/genimage.cfg"
|
||||||
GENIMAGE_TMP="${BUILD_DIR}/genimage.tmp"
|
GENIMAGE_TMP="${BUILD_DIR}/genimage.tmp"
|
||||||
@@ -9,36 +155,57 @@ GENIMAGE_TMP="${BUILD_DIR}/genimage.tmp"
|
|||||||
# key and our ixboot scripts. Make sure here they are installed in the
|
# key and our ixboot scripts. Make sure here they are installed in the
|
||||||
# proper directory so genimage can create the DOS partition the SPL
|
# proper directory so genimage can create the DOS partition the SPL
|
||||||
# reads config.txt from.
|
# reads config.txt from.
|
||||||
find "${BINARIES_DIR}" -type f -name '*.dtbo' -exec mv '{}' "${BINARIES_DIR}/rpi-firmware/overlays/" \;
|
find "${BINARIES_DIR}" -type f -name '*.dtbo' ! -path "${BINARIES_DIR}/rpi-firmware/overlays/*" -exec \
|
||||||
|
mv '{}' "${BINARIES_DIR}/rpi-firmware/overlays/" \;
|
||||||
|
|
||||||
# Create FILES array for the genimage.cfg generation
|
# Create FILES array for the genimage.cfg generation
|
||||||
FILES=""
|
FILES=""
|
||||||
for f in "${BINARIES_DIR}"/rpi-firmware/*; do
|
for f in "${BINARIES_DIR}"/rpi-firmware/*; do
|
||||||
case "$f" in
|
case "$f" in
|
||||||
*~|*.bak) continue ;;
|
*~ | *.bak)
|
||||||
|
continue
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
echo "${FILES}" | grep -q `basename $f` && continue # If already exist it has been added by us.
|
# If already exist it has been added by us.
|
||||||
|
echo "${FILES}" | grep -q "$(basename "$f")" && continue
|
||||||
FILES="${FILES}\t\t\t\"${f#"${BINARIES_DIR}/"}\",\n"
|
FILES="${FILES}\t\t\t\"${f#"${BINARIES_DIR}/"}\",\n"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|
||||||
FILES="${FILES}\t\t\t\"splash.bmp\",\n"
|
FILES="${FILES}\t\t\t\"splash.bmp\",\n"
|
||||||
echo $FILES
|
|
||||||
KERNEL=$(sed -n 's/^kernel=//p' "${BINARIES_DIR}/rpi-firmware/config.txt")
|
KERNEL=$(sed -n 's/^kernel=//p' "${BINARIES_DIR}/rpi-firmware/config.txt")
|
||||||
FILES="${FILES}\t\t\t\"${KERNEL}\""
|
FILES="${FILES}\t\t\t\"${KERNEL}\""
|
||||||
|
|
||||||
|
# Create genimage.cfg from template .in
|
||||||
sed "s|#BOOT_FILES#|${FILES}|" "${BOARD_DIR}/genimage.cfg.in" | \
|
sed "s|#BOOT_FILES#|${FILES}|" "${BOARD_DIR}/genimage.cfg.in" | \
|
||||||
sed "s|#INFIX_ID#|${INFIX_ID}|" | \
|
sed "s|#INFIX_ID#|${INFIX_ID}|" | \
|
||||||
sed "s|#VERSION#|${RELEASE}|" > "${GENIMAGE_CFG}"
|
sed "s|#VERSION#|${RELEASE}|" > "${GENIMAGE_CFG}"
|
||||||
|
|
||||||
|
# Create temporary root path
|
||||||
ROOTPATH_TMP=$(mktemp -d)
|
ROOTPATH_TMP=$(mktemp -d)
|
||||||
trap 'rm -rf \"$ROOTPATH_TMP\"' EXIT
|
trap 'rm -rf \"$ROOTPATH_TMP\"' EXIT
|
||||||
|
|
||||||
|
# Clean previous genimage temp directory
|
||||||
rm -rf "${GENIMAGE_TMP}"
|
rm -rf "${GENIMAGE_TMP}"
|
||||||
|
|
||||||
|
# Generate the SD card image
|
||||||
genimage \
|
genimage \
|
||||||
--rootpath "${ROOTPATH_TMP}" \
|
--rootpath "${ROOTPATH_TMP}" \
|
||||||
--tmppath "${GENIMAGE_TMP}" \
|
--tmppath "${GENIMAGE_TMP}" \
|
||||||
--inputpath "${BINARIES_DIR}" \
|
--inputpath "${BINARIES_DIR}" \
|
||||||
--outputpath "${BINARIES_DIR}" \
|
--outputpath "${BINARIES_DIR}" \
|
||||||
--config "${GENIMAGE_CFG}"
|
--config "${GENIMAGE_CFG}"
|
||||||
|
|
||||||
|
# Print the resulting image path
|
||||||
|
if [ "$STANDALONE" -eq 1 ]; then
|
||||||
|
echo ""
|
||||||
|
echo "SD card image created successfully:"
|
||||||
|
for img in "${BINARIES_DIR}"/*-sdcard.img; do
|
||||||
|
if [ -f "$img" ]; then
|
||||||
|
# Get relative path from current directory
|
||||||
|
rel_path=$(realpath --relative-to="$PWD" "$img" 2>/dev/null || echo "$img")
|
||||||
|
echo " $rel_path"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|||||||
@@ -542,10 +542,10 @@ static int change(sr_session_ctx_t *session, uint32_t sub_id, const char *module
|
|||||||
|
|
||||||
err = srx_get_diff(session, &diff);
|
err = srx_get_diff(session, &diff);
|
||||||
if (err)
|
if (err)
|
||||||
goto err_release_data;
|
goto done;
|
||||||
|
|
||||||
if (!diff)
|
if (!diff)
|
||||||
goto err_release_data;
|
goto done;
|
||||||
|
|
||||||
/* Create /etc/firewalld+ directory structure */
|
/* Create /etc/firewalld+ directory structure */
|
||||||
if (fmkpath(0755, FIREWALLD_DIR_NEXT) ||
|
if (fmkpath(0755, FIREWALLD_DIR_NEXT) ||
|
||||||
@@ -554,7 +554,7 @@ static int change(sr_session_ctx_t *session, uint32_t sub_id, const char *module
|
|||||||
fmkpath(0755, FIREWALLD_POLICIES_DIR)) {
|
fmkpath(0755, FIREWALLD_POLICIES_DIR)) {
|
||||||
ERROR("Failed creating " FIREWALLD_DIR_NEXT " directory structure");
|
ERROR("Failed creating " FIREWALLD_DIR_NEXT " directory structure");
|
||||||
err = SR_ERR_SYS;
|
err = SR_ERR_SYS;
|
||||||
goto err_release_data;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lydx_get_descendant(diff, "firewall", "default", NULL) ||
|
if (lydx_get_descendant(diff, "firewall", "default", NULL) ||
|
||||||
@@ -630,7 +630,7 @@ static int change(sr_session_ctx_t *session, uint32_t sub_id, const char *module
|
|||||||
|
|
||||||
if (generate_policy(cnode, name, &priority)) {
|
if (generate_policy(cnode, name, &priority)) {
|
||||||
ERROR("Failed to generate policy %s", name);
|
ERROR("Failed to generate policy %s", name);
|
||||||
goto err_release_data;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -644,7 +644,7 @@ done:
|
|||||||
|
|
||||||
if (diff)
|
if (diff)
|
||||||
lyd_free_tree(diff);
|
lyd_free_tree(diff);
|
||||||
err_release_data:
|
|
||||||
if (cfg)
|
if (cfg)
|
||||||
sr_release_data(cfg);
|
sr_release_data(cfg);
|
||||||
|
|
||||||
|
|||||||
Executable
+74
@@ -0,0 +1,74 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# RESTCONF CLI wrapper for curl
|
||||||
|
|
||||||
|
# Show usage and exit
|
||||||
|
usage()
|
||||||
|
{
|
||||||
|
cat <<-EOF >&2
|
||||||
|
Usage: $0 [-h HOST] [-d DATASTORE] [-u USER:PASS] METHOD PATH [CURL_ARGS...]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-h HOST Target host (default: infix.local)
|
||||||
|
-d DS Datastore: running, operational, startup (default: running)
|
||||||
|
-u CREDS Credentials as user:pass (default: admin:admin)
|
||||||
|
|
||||||
|
Methods: GET, POST, PUT, PATCH, DELETE
|
||||||
|
EOF
|
||||||
|
exit "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Default values
|
||||||
|
HOST=${HOST:-infix.local}
|
||||||
|
DATASTORE=running
|
||||||
|
AUTH=admin:admin
|
||||||
|
|
||||||
|
# Parse options
|
||||||
|
while getopts "h:d:u:" opt; do
|
||||||
|
case $opt in
|
||||||
|
h) HOST="$OPTARG" ;;
|
||||||
|
d) DATASTORE="$OPTARG" ;;
|
||||||
|
u) AUTH="$OPTARG" ;;
|
||||||
|
*) usage 1 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
shift $((OPTIND - 1))
|
||||||
|
|
||||||
|
# Validate required arguments
|
||||||
|
if [ $# -lt 2 ]; then
|
||||||
|
echo "Error: METHOD and PATH are required" >&2
|
||||||
|
usage 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
METHOD=$1
|
||||||
|
PATH=$2
|
||||||
|
shift 2
|
||||||
|
|
||||||
|
# Ensure PATH starts with /
|
||||||
|
case "$PATH" in
|
||||||
|
/*) ;;
|
||||||
|
*) PATH="/$PATH" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Build URL based on datastore
|
||||||
|
case "$DATASTORE" in
|
||||||
|
running|startup)
|
||||||
|
URL="https://${HOST}/restconf/data${PATH}"
|
||||||
|
;;
|
||||||
|
operational)
|
||||||
|
URL="https://${HOST}/restconf/data${PATH}"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Error: Invalid datastore '$DATASTORE'. Use: running, operational, or startup" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Execute curl with all remaining arguments passed through
|
||||||
|
exec /usr/bin/curl \
|
||||||
|
--insecure \
|
||||||
|
--user "${AUTH}" \
|
||||||
|
--request "${METHOD}" \
|
||||||
|
--header "Content-Type: application/yang-data+json" \
|
||||||
|
--header "Accept: application/yang-data+json" \
|
||||||
|
"$@" \
|
||||||
|
"${URL}"
|
||||||
Reference in New Issue
Block a user