Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
076d174579 | ||
|
|
1470c473f6 | ||
|
|
9ae7115bbf | ||
|
|
f9a0c71b1f | ||
|
|
aad5bcd4e6 | ||
|
|
e875239639 | ||
|
|
3bcc058969 | ||
|
|
3fa820b41e | ||
|
|
baec6cb35f | ||
|
|
903960f6a0 | ||
|
|
44727b9a47 | ||
|
|
eac60b1883 | ||
|
|
b5abadd52a | ||
|
|
4603649145 | ||
|
|
c1f552a8dc | ||
|
|
c1dfdd92b0 | ||
|
|
d3b28339c1 | ||
|
|
563b4a743b | ||
|
|
272a7c1e69 | ||
|
|
01e91a2fce | ||
|
|
d7abe46768 | ||
|
|
484dc940dc | ||
|
|
420f6a0556 | ||
|
|
4d4a4c68e7 | ||
|
|
eb79adce13 | ||
|
|
9fd92252ea | ||
|
|
90bda1b584 | ||
|
|
15830714f0 | ||
|
|
34cb229965 | ||
|
|
3f0b85aad9 | ||
|
|
7de94b996a | ||
|
|
09c019b236 | ||
|
|
526d3356c7 | ||
|
|
358852aa4f | ||
|
|
18640a78d5 | ||
|
|
de76b97c94 | ||
|
|
99e0a2ee1c | ||
|
|
0d0e2b168a | ||
|
|
08348c43c2 | ||
|
|
343b453c74 | ||
|
|
464e0bcb92 | ||
|
|
886d83933f | ||
|
|
ef1b1b1d1a | ||
|
|
3b4d2b38d7 | ||
|
|
0e276a97b8 | ||
|
|
afc40ac2bd | ||
|
|
5ea65aea0d | ||
|
|
614b7efd42 | ||
|
|
024acb184d | ||
|
|
e11008c7d2 | ||
|
|
e2e947629c | ||
|
|
754426f7ed | ||
|
|
31552bfc48 | ||
|
|
de27d1c7e6 | ||
|
|
24b93074c5 | ||
|
|
a14fada0ee | ||
|
|
7346f122fd | ||
|
|
227b3a92a0 | ||
|
|
6d1ac9aad2 | ||
|
|
53d90ae45a | ||
|
|
411626a8b7 | ||
|
|
a4e6e4422b | ||
|
|
3358687c39 | ||
|
|
26180859bb | ||
|
|
025c3ab7f6 | ||
|
|
026236390b | ||
|
|
284f79242a | ||
|
|
f79ad4d2d8 | ||
|
|
1852d12e7f | ||
|
|
98ff33113a | ||
|
|
cc165c5bb9 | ||
|
|
6e8f91ef3c | ||
|
|
60b8f97ad6 | ||
|
|
8b75022696 | ||
|
|
d74e7f1458 | ||
|
|
9baa3ac674 | ||
|
|
e8035f42fa | ||
|
|
9a3f7d44c4 | ||
|
|
374d24a547 | ||
|
|
dc0a68a9eb | ||
|
|
f1d730447d | ||
|
|
c0d5bfa71d | ||
|
|
02100ef1f8 | ||
|
|
00b103d3d2 | ||
|
|
c44621b8be | ||
|
|
b1bc7b42b4 | ||
|
|
6a036ec671 | ||
|
|
49c47e4732 | ||
|
|
719fe709aa | ||
|
|
03245f3631 | ||
|
|
950e868eb3 | ||
|
|
3e8e8a2e99 | ||
|
|
d8655ef70d | ||
|
|
458c1f8795 | ||
|
|
5cbe92f9ec | ||
|
|
2a5ed84898 | ||
|
|
6743223b29 | ||
|
|
a66d1d3771 | ||
|
|
65e5ab81f1 | ||
|
|
6cceecccda | ||
|
|
a5e4e016e4 | ||
|
|
883123ecdd | ||
|
|
69ba9110fc | ||
|
|
5a28a5611a | ||
|
|
571f4a6b9c | ||
|
|
4bed63d310 | ||
|
|
093a17234f | ||
|
|
a50edc7bcb | ||
|
|
b946ea937c | ||
|
|
515f1e60f9 | ||
|
|
39da7f4509 | ||
|
|
f2c60f2e16 | ||
|
|
fb3bd858e1 | ||
|
|
ba84c36878 | ||
|
|
3b17dd013b | ||
|
|
9fb2b57dd6 | ||
|
|
363516ce58 | ||
|
|
673ce2767f | ||
|
|
b88c3c3a0c | ||
|
|
ff6c63a3bd | ||
|
|
6c2e5542ca | ||
|
|
ca122ea093 | ||
|
|
2341e076a8 | ||
|
|
0d98ee5716 | ||
|
|
7871bdb9f4 | ||
|
|
64c51c7c94 | ||
|
|
19d40af20a | ||
|
|
b21945f38a | ||
|
|
712780fd5a | ||
|
|
48722e551e | ||
|
|
14234a9a77 | ||
|
|
f932f98ad2 | ||
|
|
a127925d9e | ||
|
|
63c1f36005 | ||
|
|
707e7d1a29 | ||
|
|
240a292725 | ||
|
|
e2fed7c9de | ||
|
|
19563c00f4 | ||
|
|
d37656e347 | ||
|
|
69b93507a9 | ||
|
|
e3e6477d47 | ||
|
|
808a04f125 | ||
|
|
fb8ac2aca1 | ||
|
|
6dadbd9176 | ||
|
|
3c1dc9be53 | ||
|
|
1531688ac4 |
@@ -1,25 +1,48 @@
|
||||
Contributing to Infix
|
||||
=====================
|
||||
|
||||
We welcome any and all help in the form of bug reports, fixes, patches
|
||||
to add new features -- *preferably as GitHub pull requests*.
|
||||
Thank :heart: you for taking the time to read this!
|
||||
|
||||
If you are unsure of what to do, or how to implement an idea or bug fix,
|
||||
open an issue with `"[RFC]: Unsure if this is a bug ... ?"`, or use the
|
||||
[GitHub discussions forum](https://github.com/orgs/kernelkit/discussions).
|
||||
Talking about code and problems first is often the best way to get started
|
||||
before submitting a pull request.
|
||||
We welcome any help in the form of bug reports, fixes, or patches to add
|
||||
new features. We *prefer* GitHub pull requests, but are open to other
|
||||
forms of collaboration as well. [Let's talk!][support] :handshake:
|
||||
|
||||
When submitting a bug report, patch, or pull request, please start by
|
||||
stating the version the change is made against, what it does, *and why*.
|
||||
If you are unsure how to start implementing an idea or fix:
|
||||
|
||||
- :bug: open an issue, there are human friendly templates for _bugs_
|
||||
and _feature requests_ at <https://github.com/kernelkit/infix/issues>
|
||||
- :speech_balloon: use the [Q&A Forum][discuss]
|
||||
|
||||
> _Talking about code and problems first is often the best way to get
|
||||
> started before submitting a pull request. We have found it always
|
||||
> saves time, yours and ours._
|
||||
|
||||
|
||||
:sparkles: General Guidelines
|
||||
-----------------------------
|
||||
|
||||
When submitting bug reports or patches to bugs, please state which
|
||||
version the change is made against, what it does, and, more importantly
|
||||
*why* -- from your perspective, why is it a bug, why does the code need
|
||||
changing in this way. Start with why.
|
||||
|
||||
- :bug: Bug reports need metadata like Infix version or commit hash
|
||||
- :adhesive_bandage: Bug fixes also need version, and (preferably) a
|
||||
corresponding issue number for the ChangeLog
|
||||
- :new: New features, you need to get approval of the YANG model first!
|
||||
:speech_balloon: Please use the [Forum][discuss], e.g., category:
|
||||
*Ideas*, or open a :pray: feature request issue
|
||||
- :white_check_mark: New features also need new regression tests, this
|
||||
can be basic tests or more complex use-case tests comprising multiple
|
||||
subsystems, see [Testing Changes](#test_tube-testing-changes), below
|
||||
|
||||
Please take care to ensure you follow the project coding style and the
|
||||
commit message format. If you follow these recommendations you help
|
||||
the maintainer(s) and make it easier for them to include your code.
|
||||
the maintainers and make it easier for them to include your code.
|
||||
|
||||
|
||||
Coding Style
|
||||
------------
|
||||
:woman_technologist: Coding Style
|
||||
---------------------------------
|
||||
|
||||
Before jumping into code, remember to **document new features** and bug
|
||||
fixes. Both the manual and ChangeLog are in the `doc/` sub-directory
|
||||
@@ -40,23 +63,58 @@ We expect code contributions for:
|
||||
> code! Legacy takes precedence, and remember, we read code a lot more
|
||||
> than write it, so legibility is important.
|
||||
|
||||
As a final note, lines are allowed to be longer than 72 characters these
|
||||
days. There is no enforced maximum, but the team usually keep it around
|
||||
100 characters for both C and Python.
|
||||
The ChangeLog deserves a separate mention:
|
||||
|
||||
- Releases are listed in reverse chronological order order, so the
|
||||
latest/next release is at the beginning of the file
|
||||
- Only *user-facing bugs and features* are detailed, so code refactor,
|
||||
new tests, etc. are not listed.
|
||||
- Add your changes/features to the Changes section
|
||||
- Add your Fix line in the Fixes section, in numeric order
|
||||
- Changes and fixes without an issue number are listed after all
|
||||
numbered ones
|
||||
- YANG model changes are documented in their respective model, for
|
||||
standard models, e.g., for `ietf-interfaces.yang`, the corresponding
|
||||
`infix-interfaces.yang` detail augments/deviations as revisions.
|
||||
|
||||
A final note, lines of code are allowed to be longer than 72 characters
|
||||
these days, unless you live by PEP-8 (see above). There is no enforced
|
||||
maximum, but the team usually keep it around 100 characters for both C
|
||||
and Python.
|
||||
|
||||
|
||||
Commit Messages
|
||||
---------------
|
||||
:test_tube: Testing Changes
|
||||
---------------------------
|
||||
|
||||
Please test your changes, no matter how trivial or obviously correct
|
||||
they may seem. Nobody is infallible, making mistakes is only human.
|
||||
It is also the best insurance policy for your feature, it ensures your
|
||||
use-case will remain functional as the source base evolves.
|
||||
|
||||
For new functionality we expect new regression tests to be added in
|
||||
the same pull request.
|
||||
|
||||
For help getting started with testing, see the following resources:
|
||||
|
||||
- [Developer's Guide][devguide]
|
||||
- [Regression Testing][testing]
|
||||
|
||||
|
||||
:memo: Commit Messages
|
||||
----------------------
|
||||
|
||||
Commit messages exist to track *why* a change was made. Try to be as
|
||||
clear and concise as possible in your commit messages, and always, be
|
||||
proud of your work and set up a proper GIT identity for your commits:
|
||||
|
||||
<img src="../doc/jack.png" width=70 align="right">
|
||||
|
||||
$ git config --global user.name "Jacky Linker"
|
||||
$ git config --global user.email jacky.linker@example.com
|
||||
|
||||
Example commit message from the [Pro Git][gitbook] online book, notice
|
||||
how `git commit -s` is used to automatically add a `Signed-off-by`:
|
||||
Example commit message from one of many [online guides][cbeams]. Use
|
||||
`git commit -s` to automatically add a `Signed-off-by` for proof of
|
||||
origin, see [DCO][] for more info.
|
||||
|
||||
subsystem: brief, but clear and concise summary of changes
|
||||
|
||||
@@ -73,20 +131,58 @@ how `git commit -s` is used to automatically add a `Signed-off-by`:
|
||||
- Typically a hyphen or asterisk is used for the bullet, preceded
|
||||
by a single space, with blank lines in between, but conventions
|
||||
vary here
|
||||
|
||||
|
||||
If you use an issue tracker, put references to them at the bottom,
|
||||
like this:
|
||||
|
||||
Resolves: #123
|
||||
See also: #456, #789
|
||||
|
||||
Signed-off-by: Jacky Linker <jacky.linker@example.com>
|
||||
|
||||
This is an example of how to [automatically close][closing] an issue
|
||||
when the commit is merged to mainline. Several keywords are available.
|
||||
|
||||
Code of Conduct
|
||||
---------------
|
||||
|
||||
:twisted_rightwards_arrows: Pull Requests
|
||||
-----------------------------------------
|
||||
|
||||
> _The git repository is the canonical location for information._
|
||||
|
||||
A pull request should preferably address a single issue or change. This
|
||||
may of course include multiple related changes, but what is important to
|
||||
remember is the bandwidth of the maintainers. A smaller well documented
|
||||
PR is more likely to get attention quicker in some reviewer's busy day.
|
||||
|
||||
Well documented here means that each commit message stands on its own,
|
||||
telling the complete story of the change. In fact each commit should,
|
||||
as much as possible, be independent of other changes. This is very
|
||||
important, not only when digging though logs to understand why a piece
|
||||
of code exists, but also when bisecting a problem -- each single commit
|
||||
should also compile and be possible to run.
|
||||
|
||||
If you've worked on projects that send patches, like the Linux kernel or
|
||||
Buildroot, consider the pull request message body similar to the cover
|
||||
letter for a series of patches -- it's a summary of changes, and it is
|
||||
lost when the changes are merged to the mainline branch.
|
||||
|
||||
|
||||
:balance_scale: Code of Conduct
|
||||
-------------------------------
|
||||
|
||||
It is expected of everyone to respect the [Code of Conduct][conduct].
|
||||
The *"maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, discussion forum threads, issues, and
|
||||
other contributions that are not aligned to this Code of Conduct."*
|
||||
|
||||
[Linux]: https://www.kernel.org/doc/html/v6.9/process/coding-style.html
|
||||
[PEP-8]: https://peps.python.org/pep-0008/
|
||||
[RDD]: https://tom.preston-werner.com/2010/08/23/readme-driven-development
|
||||
[gitbook]: https://git-scm.com/book/ch5-2.html
|
||||
[conduct]: CODE-OF-CONDUCT.md
|
||||
[support]: https://github.com/kernelkit/infix/blob/main/.github/SUPPORT.md
|
||||
[discuss]: https://github.com/orgs/kernelkit/discussions
|
||||
[testing]: https://github.com/kernelkit/infix/blob/main/doc/testing.md
|
||||
[devguide]: https://github.com/kernelkit/infix/blob/main/doc/developers-guide.md
|
||||
[Linux]: https://www.kernel.org/doc/html/v6.9/process/coding-style.html
|
||||
[PEP-8]: https://peps.python.org/pep-0008/
|
||||
[RDD]: https://tom.preston-werner.com/2010/08/23/readme-driven-development
|
||||
[cbeams]: https://cbea.ms/git-commit/#seven-rules
|
||||
[conduct]: CODE-OF-CONDUCT.md
|
||||
[DCO]: https://developercertificate.org/
|
||||
[closing]: https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/using-keywords-in-issues-and-pull-requests
|
||||
|
||||
@@ -1 +1,12 @@
|
||||
Paid support and development provided by Addiva Elektronik <https://addiva.se>
|
||||
Limited free support is only available using the online resources of the
|
||||
project on GitHub, and Discord, see <https://github.com/kernelkit>:
|
||||
|
||||
:speech_balloon: <https://github.com/orgs/kernelkit/discussions>
|
||||
:bug: <https://github.com/kernelkit/infix/issues>
|
||||
|
||||
Support contracts, development of new features, customer branding of
|
||||
Infix, and even customer specific features for dedicated products is
|
||||
provided by Addiva Elektronik.
|
||||
|
||||
:globe_with_meridians: <https://www.addiva.se/electronics/>
|
||||
:e-mail: <mailto:ael@addiva.se>
|
||||
|
||||
@@ -5,12 +5,6 @@
|
||||
-- Remember: assign a reviewer, or use @mentions if org. member.
|
||||
-->
|
||||
|
||||
|
||||
## Other information
|
||||
|
||||
<!-- Other relevant info, e.g., before/after screenshots -->
|
||||
|
||||
|
||||
## Checklist
|
||||
|
||||
Tick *relevant* boxes, this PR is-a or has-a:
|
||||
@@ -23,9 +17,11 @@ Tick *relevant* boxes, this PR is-a or has-a:
|
||||
- [ ] Regression tests added?
|
||||
- [ ] ChangeLog updates (for next release)
|
||||
- [ ] Documentation added?
|
||||
- [ ] Test changes
|
||||
- [ ] Checked in changed Readme.adoc (make test-spec)
|
||||
- [ ] Added new test to group Readme.adoc and yaml file
|
||||
- [ ] Code style update (formatting, renaming)
|
||||
- [ ] Refactoring (please detail in commit messages)
|
||||
- [ ] Build related changes
|
||||
- [ ] Documentation content changes
|
||||
- [ ] Other (please describe):
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
name: Adds all issues to project Infix & C:o
|
||||
|
||||
on:
|
||||
issues:
|
||||
types:
|
||||
- opened
|
||||
|
||||
jobs:
|
||||
add-to-project:
|
||||
name: Add issue to project Infix&co
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/add-to-project@v1.0.2
|
||||
with:
|
||||
project-url: https://github.com/orgs/kernelkit/projects/3
|
||||
github-token: ${{ secrets.ADD_TO_PROJECT }}
|
||||
@@ -1,28 +0,0 @@
|
||||
# To enable automatic sync of your Infix fork every day, or on dispatch,
|
||||
# set the repoistory or organisation variable (not secret):
|
||||
#
|
||||
# SYNC_FORK = true
|
||||
#
|
||||
# You also need a GH_SYNC_REPO token allowed to update workflows. For
|
||||
# more information on variables and secrets, see the GitHub docs.
|
||||
# See https://docs.github.com/en/actions/learn-github-actions/variables
|
||||
name: Synchronize your fork of Infix with upstream
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: 42 2 * * *
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
sync_fork:
|
||||
if: ${{github.repository_owner != 'kernelkit' && vars.SYNC_FORK == 'true' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: TobKed/github-forks-sync-action@master
|
||||
with:
|
||||
github_token: ${{ secrets.GH_SYNC_REPO }}
|
||||
upstream_repository: KernelKit/infix
|
||||
upstream_branch: main
|
||||
target_branch: main
|
||||
force: false
|
||||
tags: true
|
||||
@@ -128,7 +128,7 @@ what provides a default, the same default MAC addresses to Linux:
|
||||
|
||||
This is important in case you want to run multiple R2S devices on the
|
||||
same LAN. Meaning you either have to change the MAC address in the
|
||||
U-Boot environment (below), or modify your `phys-address` setting in
|
||||
U-Boot environment (below), or use the `custom-phys-address` setting in
|
||||
Infix for the interface(s).
|
||||
|
||||
Break into U-Boot using Ctrl-C at power-on, preferably when the text
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
# empty to disable port LED control on Styx, for details, see issue
|
||||
# https://github.com/kernelkit/infix/issues/670#issuecomment-2419025575
|
||||
@@ -1,102 +1,16 @@
|
||||
#!/bin/sh
|
||||
# Run .cfg migration jq scripts to backup and transform older .cfg files
|
||||
ident=$(basename "$0")
|
||||
|
||||
MIGRATIONS_DIR="/usr/share/confd/migrate"
|
||||
# Check if /cfg/startup-config.cfg needs to be migrated to new syntax.
|
||||
# Backup of the original is created in /cfg/backup/ for old versions,
|
||||
# the migrate tool inserts old version in name before .cfg extension.
|
||||
CONFIG_FILE="/cfg/startup-config.cfg"
|
||||
BACKUP_DIR="/cfg/backup"
|
||||
|
||||
note()
|
||||
{
|
||||
logger -I $$ -k -p user.notice -t "$ident" "$1"
|
||||
}
|
||||
|
||||
err()
|
||||
{
|
||||
logger -I $$ -k -p user.err -t "$ident" "$1"
|
||||
}
|
||||
|
||||
file_version()
|
||||
{
|
||||
jq -r '
|
||||
if .["infix-meta:meta"] | has("version") then
|
||||
.["infix-meta:meta"]["version"]
|
||||
else
|
||||
"0.0"
|
||||
end
|
||||
' "$1"
|
||||
}
|
||||
|
||||
atoi()
|
||||
{
|
||||
echo "$1" | awk -F. '{print $1 * 1000 + $2}'
|
||||
}
|
||||
BACKUP_FILE="/cfg/backup/startup-config.cfg"
|
||||
mkdir -p "$(dirname "$BACKUP_FILE")"
|
||||
|
||||
if [ ! -f "$CONFIG_FILE" ]; then
|
||||
# Nothing to migrate
|
||||
note "No $(basename "$CONFIG_FILE" .cfg) yet, likely factory reset."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
cfg_version=$(file_version "$CONFIG_FILE")
|
||||
current_version=$(atoi "$cfg_version")
|
||||
|
||||
# Find the latest version by examining the highest numbered directory
|
||||
sys_version=$(find "$MIGRATIONS_DIR" -mindepth 1 -maxdepth 1 -type d | sort -V | tail -n1 | xargs -n1 basename)
|
||||
latest_version=$(atoi "$sys_version")
|
||||
|
||||
# Check for downgrade
|
||||
if [ "$current_version" -gt "$latest_version" ]; then
|
||||
err "Configuration file $CONFIG_FILE version ($cfg_version) is newer than the latest supported version ($sys_version). Exiting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# If the current version is already the latest, exit the script
|
||||
if [ "$current_version" -eq "$latest_version" ]; then
|
||||
note "Configuration is already at the latest version ($sys_version). No migration needed."
|
||||
elif migrate -cq "$CONFIG_FILE"; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
note "Configuration file $CONFIG_FILE is of version $cfg_version, migrating ..."
|
||||
|
||||
# Create the backup directory if it doesn't exist
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
|
||||
# Create a backup of the current configuration file
|
||||
nm=$(basename "$CONFIG_FILE" .cfg)
|
||||
BACKUP_FILE="$BACKUP_DIR/${nm}-${cfg_version}.cfg"
|
||||
if cp "$CONFIG_FILE" "$BACKUP_FILE"; then
|
||||
note "Backup created: $BACKUP_FILE"
|
||||
else
|
||||
err "Failed creating backup: $BACKUP_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Apply the scripts for each version directory in sequence
|
||||
for version_dir in $(find "$MIGRATIONS_DIR" -mindepth 1 -maxdepth 1 -type d | sort -V); do
|
||||
dir=$(basename "$version_dir")
|
||||
version=$(atoi "$dir")
|
||||
|
||||
# Step by step upgrade file to latest version
|
||||
if [ "$current_version" -lt "$version" ]; then
|
||||
note "Applying migrations for version $dir ..."
|
||||
|
||||
# Apply all scripts in the version directory in order
|
||||
for script in $(find "$version_dir" -type f -name '*.sh' | sort -V); do
|
||||
note "Calling $script for $CONFIG_FILE ..."
|
||||
sh "$script" "$CONFIG_FILE"
|
||||
done
|
||||
|
||||
# File now at $version ...
|
||||
current_version="$version"
|
||||
fi
|
||||
done
|
||||
|
||||
# Update the JSON file to the latest version
|
||||
if jq --arg version "$sys_version" '.["infix-meta:meta"] = {"infix-meta:version": $version}' "$CONFIG_FILE" \
|
||||
> "${CONFIG_FILE}.tmp" && mv "${CONFIG_FILE}.tmp" "$CONFIG_FILE"; then
|
||||
note "Configuration updated to version $sys_version."
|
||||
else
|
||||
err "Failed updating configuration to version $sys_version!"
|
||||
exit 1
|
||||
fi
|
||||
migrate -i -b "$BACKUP_FILE" "$CONFIG_FILE"
|
||||
|
||||
@@ -17,6 +17,13 @@ device
|
||||
- Initializes auxiliary and configuration filesystems and metadata
|
||||
- Installs Infix to both primary and secondary partitions
|
||||
|
||||
To run this script again (on an already provisioned system), erase the
|
||||
partition table, reboot and netboot Infix again.
|
||||
|
||||
Example:
|
||||
|
||||
sudo sgdisk --zap-all /dev/mmcblk0
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
echo "Press Ctrl-C NOW to enter boot menu"
|
||||
echo "Press Ctrl-C NOW to override the default boot sequence"
|
||||
if sleep "${ixbootdelay}"; then
|
||||
run ixbootorder
|
||||
|
||||
@@ -7,8 +7,12 @@ if sleep "${ixbootdelay}"; then
|
||||
reset
|
||||
fi
|
||||
|
||||
bootmenu
|
||||
if test "${dev_mode}" != "yes"; then
|
||||
bootmenu
|
||||
pause "Console shell access PROHIBITED. Press any key to reset..."
|
||||
reset
|
||||
fi
|
||||
|
||||
echo
|
||||
echo 'Run "bootmenu" to interactively select a boot device'
|
||||
echo
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
setenv autoload no
|
||||
|
||||
if dhcp; then
|
||||
if test -n "${ipaddr}" || dhcp; then
|
||||
setenv proto tftp
|
||||
setenv dltool tftpboot
|
||||
setenv dlfile "${bootfile}"
|
||||
|
||||
if setexpr proto sub "^(http|tftp)://.*" "\\1" "${bootfile}" && setexpr bootfile sub "^(http|tftp)://([^/]+?)/(.*)" "\2:\3"; then
|
||||
if setexpr proto sub "^(http|tftp)://.*" "\\1" "${bootfile}"; then
|
||||
if test "${proto}" = "http"; then
|
||||
setenv dltool wget
|
||||
setexpr dlfile sub "^http://([^/]+?)/(.*)" "\\1:/\\2" "${bootfile}"
|
||||
else
|
||||
setexpr dlfile sub "^tftp://([^/]+?)/(.*)" "\\1:\\2" "${bootfile}"
|
||||
fi
|
||||
fi
|
||||
|
||||
if ${dltool} ${ramdisk_addr_r} "${bootfile}"; then
|
||||
if ${dltool} ${ramdisk_addr_r} "${dlfile}"; then
|
||||
setenv old_fdt_addr ${fdt_addr}
|
||||
if fdt addr ${ramdisk_addr_r}; then
|
||||
fdt get value sqoffs /images/rootfs data-position
|
||||
|
||||
@@ -14,6 +14,7 @@ BR2_INIT_FINIT=y
|
||||
BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y
|
||||
BR2_ROOTFS_DEVICE_TABLE="system/device_table.txt ${BR2_EXTERNAL_INFIX_PATH}/board/common/xattrs"
|
||||
# BR2_TARGET_ENABLE_ROOT_LOGIN is not set
|
||||
BR2_ROOTFS_MERGED_USR=y
|
||||
BR2_SYSTEM_BIN_SH_BASH=y
|
||||
BR2_TARGET_GENERIC_GETTY_PORT="@console"
|
||||
BR2_TARGET_GENERIC_GETTY_TERM="xterm"
|
||||
@@ -24,7 +25,6 @@ BR2_TARGET_TZ_INFO=y
|
||||
BR2_ROOTFS_OVERLAY="${BR2_EXTERNAL_INFIX_PATH}/board/common/rootfs ${BR2_EXTERNAL_INFIX_PATH}/board/aarch64/rootfs"
|
||||
BR2_ROOTFS_POST_BUILD_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-build.sh"
|
||||
BR2_ROOTFS_POST_IMAGE_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-image.sh"
|
||||
BR2_ROOTFS_MERGED_USR=y
|
||||
BR2_LINUX_KERNEL=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.6.52"
|
||||
@@ -131,7 +131,9 @@ INFIX_HOME="https://github.com/kernelkit/infix/"
|
||||
INFIX_DOC="https://github.com/kernelkit/infix/tree/main/doc"
|
||||
INFIX_SUPPORT="mailto:kernelkit@googlegroups.com"
|
||||
BR2_PACKAGE_CONFD=y
|
||||
BR2_PACKAGE_CONFD_TEST_MODE=y
|
||||
BR2_PACKAGE_CURIOS_HTTPD=y
|
||||
BR2_PACKAGE_CURIOS_NFTABLES=y
|
||||
BR2_PACKAGE_EXECD=y
|
||||
BR2_PACKAGE_GENCERT=y
|
||||
BR2_PACKAGE_STATD=y
|
||||
@@ -159,7 +161,6 @@ BR2_PACKAGE_TETRIS=y
|
||||
BR2_PACKAGE_ROUSETTE=y
|
||||
BR2_PACKAGE_LIBINPUT=y
|
||||
BR2_PACKAGE_HOST_PYTHON_YANGDOC=y
|
||||
BR2_PACKAGE_TEST_MODE=y
|
||||
DISK_IMAGE_BOOT_BIN=y
|
||||
TRUSTED_KEYS=y
|
||||
TRUSTED_KEYS_DEVELOPMENT=y
|
||||
|
||||
@@ -14,6 +14,7 @@ BR2_INIT_FINIT=y
|
||||
BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y
|
||||
BR2_ROOTFS_DEVICE_TABLE="system/device_table.txt ${BR2_EXTERNAL_INFIX_PATH}/board/common/xattrs"
|
||||
# BR2_TARGET_ENABLE_ROOT_LOGIN is not set
|
||||
BR2_ROOTFS_MERGED_USR=y
|
||||
BR2_SYSTEM_BIN_SH_BASH=y
|
||||
BR2_TARGET_GENERIC_GETTY_PORT="@console"
|
||||
BR2_TARGET_GENERIC_GETTY_TERM="xterm"
|
||||
@@ -24,7 +25,6 @@ BR2_TARGET_TZ_INFO=y
|
||||
BR2_ROOTFS_OVERLAY="${BR2_EXTERNAL_INFIX_PATH}/board/common/rootfs ${BR2_EXTERNAL_INFIX_PATH}/board/aarch64/rootfs"
|
||||
BR2_ROOTFS_POST_BUILD_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-build.sh"
|
||||
BR2_ROOTFS_POST_IMAGE_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-image.sh"
|
||||
BR2_ROOTFS_MERGED_USR=y
|
||||
BR2_LINUX_KERNEL=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.6.52"
|
||||
@@ -76,6 +76,9 @@ BR2_PACKAGE_IPROUTE2=y
|
||||
BR2_PACKAGE_IPUTILS=y
|
||||
BR2_PACKAGE_LLDPD=y
|
||||
BR2_PACKAGE_NETCALC=y
|
||||
BR2_PACKAGE_NGINX=y
|
||||
BR2_PACKAGE_NGINX_HTTP_SSL_MODULE=y
|
||||
BR2_PACKAGE_NGINX_HTTP_V2_MODULE=y
|
||||
BR2_PACKAGE_OPENRESOLV=y
|
||||
BR2_PACKAGE_OPENSSH=y
|
||||
BR2_PACKAGE_SOCAT=y
|
||||
@@ -111,6 +114,8 @@ INFIX_HOME="https://github.com/kernelkit/infix/"
|
||||
INFIX_DOC="https://github.com/kernelkit/infix/tree/main/doc"
|
||||
INFIX_SUPPORT="mailto:kernelkit@googlegroups.com"
|
||||
BR2_PACKAGE_CONFD=y
|
||||
BR2_PACKAGE_CONFD_TEST_MODE=y
|
||||
BR2_PACKAGE_GENCERT=y
|
||||
BR2_PACKAGE_STATD=y
|
||||
BR2_PACKAGE_FACTORY=y
|
||||
BR2_PACKAGE_FINIT_PLUGIN_HOTPLUG=y
|
||||
@@ -126,11 +131,6 @@ BR2_PACKAGE_LOWDOWN=y
|
||||
BR2_PACKAGE_MCD=y
|
||||
BR2_PACKAGE_MDNS_ALIAS=y
|
||||
BR2_PACKAGE_LIBINPUT=y
|
||||
BR2_PACKAGE_TEST_MODE=y
|
||||
BR2_PACKAGE_NGINX=y
|
||||
BR2_PACKAGE_NGINX_HTTP_SSL_MODULE=y
|
||||
BR2_PACKAGE_NGINX_HTTP_V2_MODULE=y
|
||||
BR2_PACKAGE_GENCERT=y
|
||||
BR2_PACKAGE_ROUSETTE=y
|
||||
DISK_IMAGE_BOOT_BIN=y
|
||||
TRUSTED_KEYS=y
|
||||
|
||||
@@ -14,8 +14,8 @@ BR2_TARGET_GENERIC_ISSUE="Infix by KernelKit"
|
||||
BR2_INIT_FINIT=y
|
||||
BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y
|
||||
BR2_ROOTFS_DEVICE_TABLE="system/device_table.txt ${BR2_EXTERNAL_INFIX_PATH}/board/common/xattrs"
|
||||
BR2_ROOTFS_MERGED_USR=y
|
||||
# BR2_TARGET_ENABLE_ROOT_LOGIN is not set
|
||||
BR2_ROOTFS_MERGED_USR=y
|
||||
BR2_SYSTEM_BIN_SH_BASH=y
|
||||
BR2_TARGET_GENERIC_GETTY_PORT="@console"
|
||||
BR2_TARGET_GENERIC_GETTY_TERM="xterm"
|
||||
@@ -71,9 +71,7 @@ BR2_PACKAGE_UBOOT_TOOLS_FIT_CHECK_SIGN=y
|
||||
BR2_PACKAGE_UBOOT_TOOLS_MKENVIMAGE=y
|
||||
BR2_PACKAGE_PYTHON3=y
|
||||
BR2_PACKAGE_PYTHON_GUNICORN=y
|
||||
BR2_PACKAGE_LIBSSH_OPENSSL=y
|
||||
BR2_PACKAGE_LIBSSH2=y
|
||||
BR2_PACKAGE_LIBSSH2_OPENSSL=y
|
||||
BR2_PACKAGE_LIBXCRYPT=y
|
||||
BR2_PACKAGE_LIBOPENSSL_BIN=y
|
||||
BR2_PACKAGE_LIBINPUT=y
|
||||
@@ -175,6 +173,7 @@ INFIX_HOME="https://github.com/kernelkit/infix/"
|
||||
INFIX_DOC="https://github.com/kernelkit/infix/tree/main/doc"
|
||||
INFIX_SUPPORT="mailto:kernelkit@googlegroups.com"
|
||||
BR2_PACKAGE_CONFD=y
|
||||
# BR2_PACKAGE_CONFD_TEST_MODE is not set
|
||||
BR2_PACKAGE_EXECD=y
|
||||
BR2_PACKAGE_GENCERT=y
|
||||
BR2_PACKAGE_STATD=y
|
||||
@@ -201,7 +200,6 @@ BR2_PACKAGE_PODMAN_DRIVER_VFS=y
|
||||
BR2_PACKAGE_TETRIS=y
|
||||
BR2_PACKAGE_ROUSETTE=y
|
||||
BR2_PACKAGE_HOST_PYTHON_YANGDOC=y
|
||||
# BR2_PACKAGE_TEST_MODE is not set
|
||||
TRUSTED_KEYS=y
|
||||
TRUSTED_KEYS_DEVELOPMENT=y
|
||||
# GNS3_APPLIANCE is not set
|
||||
|
||||
@@ -11,8 +11,8 @@ BR2_TARGET_GENERIC_ISSUE="Infix by KernelKit"
|
||||
BR2_INIT_FINIT=y
|
||||
BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y
|
||||
BR2_ROOTFS_DEVICE_TABLE="system/device_table.txt ${BR2_EXTERNAL_INFIX_PATH}/board/common/xattrs"
|
||||
BR2_ROOTFS_MERGED_USR=y
|
||||
# BR2_TARGET_ENABLE_ROOT_LOGIN is not set
|
||||
BR2_ROOTFS_MERGED_USR=y
|
||||
BR2_SYSTEM_BIN_SH_BASH=y
|
||||
BR2_TARGET_GENERIC_GETTY_PORT="@console"
|
||||
BR2_TARGET_GENERIC_GETTY_TERM="xterm"
|
||||
@@ -65,9 +65,7 @@ BR2_PACKAGE_UBOOT_TOOLS_FIT_CHECK_SIGN=y
|
||||
BR2_PACKAGE_UBOOT_TOOLS_MKENVIMAGE=y
|
||||
BR2_PACKAGE_PYTHON3=y
|
||||
BR2_PACKAGE_PYTHON_GUNICORN=y
|
||||
BR2_PACKAGE_LIBSSH_OPENSSL=y
|
||||
BR2_PACKAGE_LIBSSH2=y
|
||||
BR2_PACKAGE_LIBSSH2_OPENSSL=y
|
||||
BR2_PACKAGE_LIBXCRYPT=y
|
||||
BR2_PACKAGE_LIBOPENSSL_BIN=y
|
||||
BR2_PACKAGE_LIBINPUT=y
|
||||
@@ -166,6 +164,7 @@ INFIX_HOME="https://github.com/kernelkit/infix/"
|
||||
INFIX_DOC="https://github.com/kernelkit/infix/tree/main/doc"
|
||||
INFIX_SUPPORT="mailto:kernelkit@googlegroups.com"
|
||||
BR2_PACKAGE_CONFD=y
|
||||
# BR2_PACKAGE_CONFD_TEST_MODE is not set
|
||||
BR2_PACKAGE_EXECD=y
|
||||
BR2_PACKAGE_GENCERT=y
|
||||
BR2_PACKAGE_STATD=y
|
||||
@@ -192,7 +191,6 @@ BR2_PACKAGE_PODMAN_DRIVER_VFS=y
|
||||
BR2_PACKAGE_TETRIS=y
|
||||
BR2_PACKAGE_ROUSETTE=y
|
||||
BR2_PACKAGE_HOST_PYTHON_YANGDOC=y
|
||||
# BR2_PACKAGE_TEST_MODE is not set
|
||||
TRUSTED_KEYS=y
|
||||
TRUSTED_KEYS_DEVELOPMENT=y
|
||||
# GNS3_APPLIANCE is not set
|
||||
|
||||
@@ -13,6 +13,7 @@ BR2_INIT_FINIT=y
|
||||
BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y
|
||||
BR2_ROOTFS_DEVICE_TABLE="system/device_table.txt ${BR2_EXTERNAL_INFIX_PATH}/board/common/xattrs"
|
||||
# BR2_TARGET_ENABLE_ROOT_LOGIN is not set
|
||||
BR2_ROOTFS_MERGED_USR=y
|
||||
BR2_SYSTEM_BIN_SH_BASH=y
|
||||
BR2_TARGET_GENERIC_GETTY_PORT="@console"
|
||||
BR2_TARGET_GENERIC_GETTY_TERM="xterm"
|
||||
@@ -23,7 +24,6 @@ BR2_TARGET_TZ_INFO=y
|
||||
BR2_ROOTFS_OVERLAY="${BR2_EXTERNAL_INFIX_PATH}/board/common/rootfs ${BR2_EXTERNAL_INFIX_PATH}/board/x86_64/rootfs"
|
||||
BR2_ROOTFS_POST_BUILD_SCRIPT="board/qemu/x86_64/post-build.sh ${BR2_EXTERNAL_INFIX_PATH}/board/common/post-build.sh"
|
||||
BR2_ROOTFS_POST_IMAGE_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-image.sh"
|
||||
BR2_ROOTFS_MERGED_USR=y
|
||||
BR2_LINUX_KERNEL=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.6.52"
|
||||
@@ -57,6 +57,7 @@ BR2_PACKAGE_LIBSSH2_OPENSSL=y
|
||||
BR2_PACKAGE_LIBXCRYPT=y
|
||||
BR2_PACKAGE_LIBOPENSSL_BIN=y
|
||||
BR2_PACKAGE_LIBCURL_CURL=y
|
||||
BR2_PACKAGE_LIBMNL=y
|
||||
BR2_PACKAGE_NETOPEER2_CLI=y
|
||||
BR2_PACKAGE_NSS_MDNS=y
|
||||
BR2_PACKAGE_LINUX_PAM=y
|
||||
@@ -134,7 +135,9 @@ INFIX_HOME="https://github.com/kernelkit/infix/"
|
||||
INFIX_DOC="https://github.com/kernelkit/infix/tree/main/doc"
|
||||
INFIX_SUPPORT="mailto:kernelkit@googlegroups.com"
|
||||
BR2_PACKAGE_CONFD=y
|
||||
BR2_PACKAGE_CONFD_TEST_MODE=y
|
||||
BR2_PACKAGE_CURIOS_HTTPD=y
|
||||
BR2_PACKAGE_CURIOS_NFTABLES=y
|
||||
BR2_PACKAGE_EXECD=y
|
||||
BR2_PACKAGE_GENCERT=y
|
||||
BR2_PACKAGE_STATD=y
|
||||
@@ -161,7 +164,6 @@ BR2_PACKAGE_PODMAN_DRIVER_VFS=y
|
||||
BR2_PACKAGE_TETRIS=y
|
||||
BR2_PACKAGE_ROUSETTE=y
|
||||
BR2_PACKAGE_HOST_PYTHON_YANGDOC=y
|
||||
BR2_PACKAGE_TEST_MODE=y
|
||||
TRUSTED_KEYS=y
|
||||
TRUSTED_KEYS_DEVELOPMENT=y
|
||||
GNS3_APPLIANCE_RAM=512
|
||||
|
||||
@@ -13,6 +13,7 @@ BR2_INIT_FINIT=y
|
||||
BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y
|
||||
BR2_ROOTFS_DEVICE_TABLE="system/device_table.txt ${BR2_EXTERNAL_INFIX_PATH}/board/common/xattrs"
|
||||
# BR2_TARGET_ENABLE_ROOT_LOGIN is not set
|
||||
BR2_ROOTFS_MERGED_USR=y
|
||||
BR2_SYSTEM_BIN_SH_BASH=y
|
||||
BR2_TARGET_GENERIC_GETTY_PORT="@console"
|
||||
BR2_TARGET_GENERIC_GETTY_TERM="xterm"
|
||||
@@ -23,7 +24,6 @@ BR2_TARGET_TZ_INFO=y
|
||||
BR2_ROOTFS_OVERLAY="${BR2_EXTERNAL_INFIX_PATH}/board/common/rootfs ${BR2_EXTERNAL_INFIX_PATH}/board/x86_64/rootfs"
|
||||
BR2_ROOTFS_POST_BUILD_SCRIPT="board/qemu/x86_64/post-build.sh ${BR2_EXTERNAL_INFIX_PATH}/board/common/post-build.sh"
|
||||
BR2_ROOTFS_POST_IMAGE_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-image.sh"
|
||||
BR2_ROOTFS_MERGED_USR=y
|
||||
BR2_LINUX_KERNEL=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.6.52"
|
||||
@@ -56,6 +56,7 @@ BR2_PACKAGE_LIBSSH2_OPENSSL=y
|
||||
BR2_PACKAGE_LIBXCRYPT=y
|
||||
BR2_PACKAGE_LIBOPENSSL_BIN=y
|
||||
BR2_PACKAGE_LIBCURL_CURL=y
|
||||
BR2_PACKAGE_LIBMNL=y
|
||||
BR2_PACKAGE_NETOPEER2_CLI=y
|
||||
BR2_PACKAGE_NSS_MDNS=y
|
||||
BR2_PACKAGE_LINUX_PAM=y
|
||||
@@ -71,6 +72,9 @@ BR2_PACKAGE_IPROUTE2=y
|
||||
BR2_PACKAGE_IPUTILS=y
|
||||
BR2_PACKAGE_LLDPD=y
|
||||
BR2_PACKAGE_NETCALC=y
|
||||
BR2_PACKAGE_NGINX=y
|
||||
BR2_PACKAGE_NGINX_HTTP_SSL_MODULE=y
|
||||
BR2_PACKAGE_NGINX_HTTP_V2_MODULE=y
|
||||
BR2_PACKAGE_OPENRESOLV=y
|
||||
BR2_PACKAGE_OPENSSH=y
|
||||
BR2_PACKAGE_SOCAT=y
|
||||
@@ -114,6 +118,8 @@ INFIX_HOME="https://github.com/kernelkit/infix/"
|
||||
INFIX_DOC="https://github.com/kernelkit/infix/tree/main/doc"
|
||||
INFIX_SUPPORT="mailto:kernelkit@googlegroups.com"
|
||||
BR2_PACKAGE_CONFD=y
|
||||
BR2_PACKAGE_CONFD_TEST_MODE=y
|
||||
BR2_PACKAGE_GENCERT=y
|
||||
BR2_PACKAGE_STATD=y
|
||||
BR2_PACKAGE_FACTORY=y
|
||||
BR2_PACKAGE_FINIT_PLUGIN_HOTPLUG=y
|
||||
@@ -128,11 +134,6 @@ BR2_PACKAGE_KLISH_PLUGIN_INFIX=y
|
||||
BR2_PACKAGE_LOWDOWN=y
|
||||
BR2_PACKAGE_MCD=y
|
||||
BR2_PACKAGE_MDNS_ALIAS=y
|
||||
BR2_PACKAGE_TEST_MODE=y
|
||||
BR2_PACKAGE_NGINX=y
|
||||
BR2_PACKAGE_NGINX_HTTP_SSL_MODULE=y
|
||||
BR2_PACKAGE_NGINX_HTTP_V2_MODULE=y
|
||||
BR2_PACKAGE_GENCERT=y
|
||||
BR2_PACKAGE_ROUSETTE=y
|
||||
TRUSTED_KEYS=y
|
||||
TRUSTED_KEYS_DEVELOPMENT=y
|
||||
|
||||
@@ -4,6 +4,94 @@ Change Log
|
||||
All notable changes to the project are documented in this file.
|
||||
|
||||
|
||||
[v24.10.1][] - 2024-10-18
|
||||
-------------------------
|
||||
|
||||
### Fixes
|
||||
- Fix #735: `copy` and `erase` commands missing from CLI, regression
|
||||
in Infix v24.10.0 defconfigs, now added as dep. in klish package
|
||||
|
||||
|
||||
[v24.10.0][] - 2024-10-18
|
||||
-------------------------
|
||||
|
||||
**News:** this release contains *breaking YANG changes* in custom MAC
|
||||
addresses for interfaces! For details, see below issue #680.
|
||||
|
||||
Also, heads-up to all downstream users of Infix. YANG models have been
|
||||
renamed to ease maintenance, more info below.
|
||||
|
||||
### Changes
|
||||
- Software control of port LEDs on the Styx platform has been disabled.
|
||||
Default driver behavior, green link and green traffic blink, is kept
|
||||
as-is, which should mitigate issues reported in #670
|
||||
- Correcting documentation on QoS. For packets containing both a VLAN
|
||||
tag and an IP header, PCP priority takes precedence over DSCP
|
||||
priority (not vice versa).
|
||||
- Update CONTRIBUTING.md for scaling core team and helping external
|
||||
contributors understand the development process, issue #672
|
||||
- Updated branding documentation with more information on how dynamic
|
||||
and static factory-config work, including examples
|
||||
- Updated container documentation, improved images, detail how to set
|
||||
interface name inside the container, and some syntax fixes
|
||||
- Updated networking documentation, new General settings section, and
|
||||
more details added to initial section on network building blocks
|
||||
- As of this release, all Infix YANG models have dropped the `@DATE`
|
||||
suffix from the name, this type of versioning is not handled using
|
||||
symlinks instead.
|
||||
- Update Infix `provision` script, used to install Infix on eMMC, add
|
||||
example of how to erase partition table to be able to re-run the
|
||||
script on already provisioned devices, issue #671
|
||||
- OSPF: Add limitation to allow an interface to be in one area only
|
||||
- Add support for "dummy" interfaces, mostly useful for testing
|
||||
- Add support for container hostname format specifiers, just like it
|
||||
already works for the host's hostname setting
|
||||
- Hide all `status obsolete` YANG nodes in CLI
|
||||
- Add YANG `units`, if available, to CLI help text (default value)
|
||||
- The CLI commands `copy` and `erase` are now available also from Bash
|
||||
- Greatly reduced size of bundled curiOS httpd OCI container image,
|
||||
reduced from 1.8 MiB to 281 KiB
|
||||
- Add deviation to ietf-interfaces.yang, `link-up-down-trap-enable` is
|
||||
not supported (yet) in Infix, issue #709
|
||||
- The default builds now include the curiOS nftables container image,
|
||||
which can be used for advanced firewall setups. For an introduction
|
||||
see <https://kernelkit.org/posts/firewall-container/>
|
||||
|
||||
### Fixes
|
||||
- Fix #499: add an NACM rule to factory-config, which by default deny
|
||||
everyone to read user password hash(es)
|
||||
- Fix #663: internal Ethernet interfaces shown in CLI tab completion
|
||||
- Fix #674: CLI `show interfaces` display internal Ethernet interfaces,
|
||||
regression introduced late in v24.09 release cycle
|
||||
- Fix #676: port dropped from bridge when changing its VLAN membership
|
||||
from tagged to untagged
|
||||
- Fix #680: replace deviation for `phys-address` in ietf-interfaces.yang
|
||||
with `custom-phys-address` to allow for constructing more free-form
|
||||
MAC addresses based on the chassis MAC (a.k.a., base MAC) address.
|
||||
For more information, see the YANG model, a few examples are listed in
|
||||
the updated documentation.
|
||||
The syntax will be automatically updated in the `startup-config` and
|
||||
`factory-config` -- make sure to verify the changes and update any
|
||||
static `factory-config` used for your products
|
||||
- Fix #690: CLI `show ip route` command stops working after 24 hours,
|
||||
this includes all operational data in ietf-routing:/routing/ribs.
|
||||
- Fix #697: password is not always set for new users, bug introduced
|
||||
in v24.06.0 when replacing Augeas with native user handling
|
||||
- Fix #700: add missing `admin-status` to interface operational data
|
||||
- Fix #701: make sure CLI (and Bash) `copy` command use same sysrepo
|
||||
timeout as other operations that load sysrepo. Was 10 second timeout,
|
||||
which caused some (really big) configurations not to apply from the
|
||||
CLI, but worked at boot, for instance. New timeout is 60 seconds
|
||||
- Fix #708: allow all container networks to set interface name inside
|
||||
container, not just auto-generated veth-pair ends for `docker0` bridge
|
||||
- Fix `show interfaces` on platforms like the NanoPi R2S, which does not
|
||||
support reading RMON counters in JSON format using `ethtool`
|
||||
- Fix #730: CLI command `show ntp [sources]` stopped working in v24.08.
|
||||
Missing access rights after massive CLI lock-down
|
||||
- Fix BFD in OSPF, previously you could not enable BFD on a single
|
||||
interface without enabling it on all interfaces
|
||||
|
||||
|
||||
[v24.09.0][] - 2024-09-30
|
||||
-------------------------
|
||||
|
||||
@@ -1156,7 +1244,9 @@ Supported YANG models in addition to those used by sysrepo and netopeer:
|
||||
- N/A
|
||||
|
||||
[buildroot]: https://buildroot.org/
|
||||
[UNRELEASED]: https://github.com/kernelkit/infix/compare/v24.08.0...HEAD
|
||||
[UNRELEASED]: https://github.com/kernelkit/infix/compare/v24.10.0...HEAD
|
||||
[v24.10.1]: https://github.com/kernelkit/infix/compare/v24.10.0...v24.10.1
|
||||
[v24.10.0]: https://github.com/kernelkit/infix/compare/v24.09.0...v24.10.0
|
||||
[v24.09.0]: https://github.com/kernelkit/infix/compare/v24.08.0...v24.09.0
|
||||
[v24.08.0]: https://github.com/kernelkit/infix/compare/v24.06.0...v24.08.0
|
||||
[v24.06.0]: https://github.com/kernelkit/infix/compare/v24.04.0...v24.06.0
|
||||
|
||||
@@ -41,13 +41,92 @@ Verify the result after a build by inspecting:
|
||||
printed on a label on the device.
|
||||
|
||||
|
||||
Factory Defaults
|
||||
----------------
|
||||
Factory & Failure Config
|
||||
------------------------
|
||||
|
||||
The Infix default configuration, factory-config, is part static files
|
||||
and part per-device generated files, e.g., SSH hostkey and hostname.
|
||||
The latter is constructed from the file `/etc/hostname`, appended with
|
||||
the last three octets of the system's base MAC address. To override the
|
||||
To support booting the same image (CPU architecture) on multiple boards,
|
||||
Infix by default generates the device's initial configuration every time
|
||||
at boot. This also ensures the device can always be restored to a known
|
||||
state after a factory reset, since the `factory-config` is guaranteed to
|
||||
be compatible with the YANG models for the given software version. (For
|
||||
more information on how the system boots, please see the section [Key
|
||||
Concepts](introduction.md#key-concepts) in the Introduction document.)
|
||||
|
||||
However, for custom builds of Infix it is possible to override this with
|
||||
a single static `/etc/factory-config.cfg` (and failure-config) in your
|
||||
rootfs overlay -- with a [VPD](vpd.md) you can even support several!
|
||||
|
||||
|
||||
### Variables & Format Specifiers
|
||||
|
||||
Parts of the configuration you likely always want to generated, like the
|
||||
SSH hostkey used by NETCONF, a unique hostname, or the `admin` user's
|
||||
unique (per-device with a VPD) password hash. This section lists the
|
||||
available keywords, see the next section for examples of how to use
|
||||
them:
|
||||
|
||||
- **Default password hash:** `$factory$` (from VPD, .dtb, or built-in)
|
||||
XPath: `/ietf-system:system/authentication/user/password`
|
||||
- **Default NETCONF hostkey:** `genkey` (regenerated at factory reset)
|
||||
XPath: `/ietf-keystore:keystore/asymmetric-keys/asymmetric-key[name='genkey']`
|
||||
- **Hostname format specifiers:**
|
||||
XPath: `/ietf-system:system/hostname`
|
||||
- `%i`: OS ID, from `/etc/os-release`, from Menuconfig branding
|
||||
- `%h`: Default hostname, from `/etc/os-release`, from branding
|
||||
- `%m`: NIC specific part of base MAC, e.g., to `c0-ff-ee`
|
||||
- `%%`: Literal %
|
||||
|
||||
|
||||
### Static Files
|
||||
|
||||
> **Caveat:** maintaining static a factory-config and failure-config may
|
||||
> seem like an obvious choice, but as YANG models evolve (even the IETF
|
||||
> models get upgraded), you may need to upgrade your static files.
|
||||
|
||||
First, for one-off builds (one image per product), the simplest way is
|
||||
to override the location where the system looks for the files, `/etc`
|
||||
already at build time. This can be done using a Buildroot rootfs
|
||||
overlay providing, e.g., `/etc/factory-config.cfg`. Example: [NanoPi
|
||||
R2S][] in `${INFIX}/board/aarch64/r2s/rootfs/etc/factory-config.cfg`.
|
||||
|
||||
Second, to support multiple products in a single image, we can employ
|
||||
another method to install a `/etc/factory-config.cfg` override -- at
|
||||
runtime. This relies on the very early system `probe` that detects the
|
||||
specific product from VPD data.
|
||||
|
||||
The `probe` consists of several sequential steps that currently run from
|
||||
`${INFIX}/board/common/rootfs/usr/libexec/infix/init.d/`. One of them
|
||||
check if `/usr/share/product/<PRODUCT>` exists, and if so attempts to
|
||||
copy the entire contents to `/`. Here, `<PRODUCT>` is determined from
|
||||
the VPD, which is available in `/run/system.json` as `"product-name"`,
|
||||
after `00-probe` has run. The lower case version of the string is used.
|
||||
|
||||
I.e., create a rootfs overlay that provides any combination of:
|
||||
|
||||
- `/usr/share/product/<PRODUCT>/etc/factory-config.cfg`
|
||||
- `/usr/share/product/<PRODUCT>/etc/failure-config.cfg`
|
||||
|
||||
|
||||
### Dynamically Generated
|
||||
|
||||
The generated `factory-config` and `failure-config` files consist of
|
||||
both static JSON files and part generated files at runtime for each
|
||||
device. The resulting files are written to the RAM disk in `/run`:
|
||||
|
||||
- `/run/confd/factory-config.gen`
|
||||
- `/run/confd/failure-config.gen`
|
||||
|
||||
Provided no custom overrides (see above) have been installed already,
|
||||
these files are then copied to:
|
||||
|
||||
- `/etc/factory-config.cfg`
|
||||
- `/etc/failure-config.cfg`
|
||||
|
||||
... where the bootstrap process expects them to be in the next step.
|
||||
|
||||
Examples of generated contents are the SSH hostkey and hostname. The
|
||||
latter is constructed from the file `/etc/hostname`, appended with the
|
||||
last three octets of the system's base MAC address. To override the
|
||||
base hostname, set `BR2_TARGET_GENERIC_HOSTNAME` in your defconfig.
|
||||
|
||||
The static files are installed by Infix `confd` in `/usr/share/confd/`
|
||||
@@ -97,6 +176,112 @@ bootstrap script for more help, and up-to-date information.
|
||||
> you may want to look into `GEN_IFACE_OPTS`.
|
||||
|
||||
|
||||
### Example Snippets
|
||||
|
||||
**IETF System:**
|
||||
|
||||
```hsib
|
||||
"ietf-system:system": {
|
||||
"hostname": "example-%m",
|
||||
"ntp": {
|
||||
"enabled": true,
|
||||
"server": [
|
||||
{
|
||||
"name": "ntp.org",
|
||||
"udp": {
|
||||
"address": "pool.ntp.org"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"authentication": {
|
||||
"user": [
|
||||
{
|
||||
"name": "admin",
|
||||
"password": "$factory$",
|
||||
"infix-system:shell": "bash"
|
||||
}
|
||||
]
|
||||
},
|
||||
"infix-system:motd-banner": "Li0tLS0tLS0uCnwgIC4gLiAgfCBJbmZpeCAtLSBhIE5ldHdvcmsgT3BlcmF0aW5nIFN5c3RlbQp8LS4gdiAuLXwgaHR0cHM6Ly9rZXJuZWxraXQuZ2l0aHViLmlvCictJy0tLSctJwo="
|
||||
}, # <---- REMEMBER COMMA SEPARATORS IN SNIPPETS!
|
||||
# <---- ... and no comments.
|
||||
```
|
||||
|
||||
The `motd-banner` is a binary type, which is basically a Base64 encoded
|
||||
text file without line breaks (`-w0`):
|
||||
|
||||
```bash
|
||||
$ echo "Li0tLS0tLS0uCnwgIC4gLiAgfCBJbmZpeCAtLSBhIE5ldHdvcmsgT3BlcmF0aW5nIFN5c3RlbQp8LS4gdiAuLXwgaHR0cHM6Ly9rZXJuZWxraXQuZ2l0aHViLmlvCictJy0tLSctJwo=" |base64 -d
|
||||
.-------.
|
||||
| . . | Infix -- a Network Operating System
|
||||
|-. v .-| https://kernelkit.github.io
|
||||
'-'---'-'
|
||||
```
|
||||
|
||||
**IETF Keystore**
|
||||
|
||||
Notice how both the public and private keys are left empty here. The
|
||||
`genkey` is always automatically regenerated after each factory reset.
|
||||
Keeping the `factory-config` snippet like this means we can use the same
|
||||
file on multiple devices, without risking them sharing the same host
|
||||
keys. Sometimes you may want the same host keys, but that is the easy
|
||||
use-case and not documented here.
|
||||
|
||||
```json
|
||||
"ietf-keystore:keystore": {
|
||||
"asymmetric-keys": {
|
||||
"asymmetric-key": [
|
||||
{
|
||||
"name": "genkey",
|
||||
"public-key-format": "ietf-crypto-types:ssh-public-key-format",
|
||||
"public-key": "",
|
||||
"private-key-format": "ietf-crypto-types:rsa-private-key-format",
|
||||
"cleartext-private-key": "",
|
||||
"certificates": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
```
|
||||
|
||||
The `genkey` is currently only used by the NETCONF SSH backend.
|
||||
|
||||
**IETF NETCONF Server**
|
||||
|
||||
```json
|
||||
"ietf-netconf-server:netconf-server": {
|
||||
"listen": {
|
||||
"endpoints": {
|
||||
"endpoint": [
|
||||
{
|
||||
"name": "default-ssh",
|
||||
"ssh": {
|
||||
"tcp-server-parameters": {
|
||||
"local-address": "::"
|
||||
},
|
||||
"ssh-server-parameters": {
|
||||
"server-identity": {
|
||||
"host-key": [
|
||||
{
|
||||
"name": "default-key",
|
||||
"public-key": {
|
||||
"central-keystore-reference": "genkey"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
```
|
||||
|
||||
|
||||
|
||||
Integration
|
||||
-----------
|
||||
|
||||
@@ -203,3 +388,4 @@ variable `INFIX_OEM_PATH` to that of the br2-external. It is also
|
||||
possible to set the `GIT_VERSION` variable in your `post-build.sh`
|
||||
script to change how the VCS version is extracted.
|
||||
|
||||
[NanoPi R2S]: https://github.com/kernelkit/infix/blob/main/board/aarch64/r2s/rootfs/etc/factory-config.cfg
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
Containers in Infix
|
||||
===================
|
||||
<img align="right" src="img/docker.webp" alt="Docker whale" width=360>
|
||||
|
||||
* [Introduction](#introduction)
|
||||
* [Caution](#caution)
|
||||
@@ -75,19 +76,20 @@ Getting Started
|
||||
|
||||
In the CLI, containers can be run in one of two ways:
|
||||
|
||||
1. `container run IMAGE [COMMAND]`, and
|
||||
1. `container run IMAGE [COMMAND]`, or
|
||||
2. enter `configure` context, then `edit container NAME`
|
||||
|
||||
The first is useful mostly for testing, or running single commands in an
|
||||
image. It is a wrapper for `podman run -it --rm ...`, while the latter
|
||||
is a wrapper and adaptation of `podman create ...`.
|
||||
The former is useful mostly for testing, or running single commands in
|
||||
an image. It is a wrapper for `podman run -it --rm ...`, while the
|
||||
latter is a wrapper and adaptation of `podman create ...`.
|
||||
|
||||
The second create a container with a semi-persistent writable layer that
|
||||
survives container restarts and host system restarts. However, if you
|
||||
change the container configuration or upgrade the image (see below), the
|
||||
container will be recreated and the writable layer is lost. This is why
|
||||
it is recommended to set up a named volume for directories, or use file
|
||||
[Content Mounts][], in your container you want truly persistent content.
|
||||
[Content Mounts](#content-mounts), in your container if you want truly
|
||||
persistent content.
|
||||
|
||||
In fact, in many cases the best way is to create a `read-only` container
|
||||
and use file mounts and volumes only for the critical parts. Podman
|
||||
@@ -103,11 +105,23 @@ application to run.
|
||||
> unlike virtualization, containers reuse the host's CPU and kernel.
|
||||
|
||||
|
||||
<img align="right" src="img/docker-hello-world.svg" alt="Hello World" width=360>
|
||||
|
||||
### Examples
|
||||
|
||||
Classic Hello World:
|
||||
|
||||
admin@example:/> container run docker://hello-world
|
||||
Starting docker://hello-world :: use Ctrl-p Ctrl-q to detach
|
||||
Trying to pull docker.io/library/hello-world:latest...
|
||||
Getting image source signatures
|
||||
Copying blob c1ec31eb5944 done
|
||||
Copying config d2c94e258d done
|
||||
Writing manifest to image destination
|
||||
Storing signatures
|
||||
|
||||
Hello from Docker!
|
||||
This message shows that your installation appears to be working correctly.
|
||||
|
||||
Persistent web server using nginx, sharing the host's network:
|
||||
|
||||
@@ -132,7 +146,7 @@ container at runtime.
|
||||
Container Images
|
||||
----------------
|
||||
|
||||
The underlying `podman` project support importing and fetching images in
|
||||
The underlying `podman` project supports importing and fetching images in
|
||||
a variety of ways, the most common ones are also supported by Infix. In
|
||||
this section we present how to use them and in the next section we show
|
||||
how to upgrade to a newer base image.
|
||||
@@ -209,7 +223,7 @@ admin-exec context ...
|
||||
admin@example:/var/tmp$ cli
|
||||
admin@example:/> container load /var/tmp/curios-oci-amd64.tar.gz name curios:edge
|
||||
|
||||
> By assigning The `name curios:edge` is the tag you give the imported
|
||||
> The `name curios:edge` is the tag you give the imported
|
||||
> (raw) archive which you can then reference in your container image
|
||||
> configuration: `set image curios:edge`.
|
||||
|
||||
@@ -221,6 +235,10 @@ archive, which helps greatly with container upgrades (see below):
|
||||
|
||||
Upgrading a Container Image
|
||||
---------------------------
|
||||
<img align="right" src="img/shield-checkmark.svg" alt="Hello World" width=100>
|
||||
|
||||
The applications in your container are an active part of the system as a
|
||||
whole, so make it a routine to keep your container images up-to-date!
|
||||
|
||||
> **Note:** the default writable layer is lost when upgrading the image.
|
||||
> Use named volumes for content that you want to persist across upgrades.
|
||||
@@ -299,14 +317,19 @@ Currently two types of of container networks are supported:
|
||||
|
||||
> For more information on VETH pairs, see the [Networking Guide][0].
|
||||
|
||||
|
||||
### Container Bridge
|
||||
|
||||
A container bridge is what most container setups use and users want.
|
||||
|
||||

|
||||
|
||||
The difference from a regular bridge is that the container runtime fully
|
||||
manages them -- connecting containers automatically with VETH pairs and
|
||||
setting up firewall rules between the host and other containers, as well
|
||||
as managing port forwarding. This transparent background management is
|
||||
what makes container use seem to be so simple.
|
||||
manages them -- connecting containers with automatically created VETH
|
||||
pairs (look at the bridge port names) and setting up firewall rules
|
||||
between the host and other containers, as well as managing port
|
||||
forwarding. This transparent background management is what makes
|
||||
container use seem to be so simple.
|
||||
|
||||
All interface configuration is done in configure context.
|
||||
|
||||
@@ -325,7 +348,7 @@ have to set manually:
|
||||
admin@example:/config/interface/docker0/> set container-network type bridge
|
||||
|
||||
> **Note:** when doing the same operation over NETCONF there is no
|
||||
> inference, so all the "magic" settings needs to be defined. This
|
||||
> inference, so all the "magic" settings need to be defined. This
|
||||
> makes the CLI very useful for first setup and then extracting the
|
||||
> resulting XML from the shell using the `cfg -X` command.
|
||||
|
||||
@@ -394,20 +417,21 @@ namespace of a container[^3]. This of course works with plain Ethernet
|
||||
interfaces as well, but here we will use one end of a VETH pair as an
|
||||
example.
|
||||
|
||||
The network `option` setting is available also for this case, but only
|
||||
the `interface_name=foo0` option works. Which is still very useful. To
|
||||
change the MAC address, you need to use the `custom-phys-address` in the
|
||||
general network settings.
|
||||
|
||||
[^3]: Something which the container bridge network type does behind the
|
||||
scenes with one end of an automatically created VETH pair.
|
||||
|
||||
|
||||
#### Routed Setup
|
||||
|
||||
In this routed setup we reserve 192.168.0.0/24 for the network between
|
||||
the host and the `ntpd` container.
|
||||
|
||||
_____________
|
||||
| |
|
||||
veth0 .1 | .2 eth0 |
|
||||
\ 192.168.0.0/24 | / |
|
||||
'--------------------' [ntpd] |
|
||||
|_____________|
|
||||

|
||||
|
||||
Configuration is a straight-forward VETH pair setup where we name the
|
||||
container-end of pair `ntpd`. This is just a convenience for us when
|
||||
@@ -420,7 +444,7 @@ line where we declare the `ntpd` end as a container network interface:
|
||||
admin@example:/config/interface/veth0/> end
|
||||
admin@example:/config/> edit interface ntpd
|
||||
admin@example:/config/interface/ntpd/> set ipv4 address 192.168.0.2 prefix-length 24
|
||||
admin@example:/config/interface/ntpd/> set phys-address 00:c0:ff:ee:00:01
|
||||
admin@example:/config/interface/ntpd/> set custom-phys-address static 00:c0:ff:ee:00:01
|
||||
admin@example:/config/interface/ntpd/> set container-network
|
||||
|
||||
> Notice how you can also set a custom MAC address at the same time.
|
||||
@@ -429,9 +453,12 @@ Adding the interface to the container is the same as before, but since
|
||||
everything for host interfaces is set up in the interfaces context, we
|
||||
can take a bit of a shortcut.
|
||||
|
||||
admin@example:/config/container/ntpd/> set network ntpd
|
||||
admin@example:/config/container/ntpd/> set network interface ntpd
|
||||
admin@example:/config/container/ntpd/> leave
|
||||
|
||||
> Use the `set network interface ntpd option interface_name=foo0` to set
|
||||
> the name of the interface inside the container to `foo0`.
|
||||
|
||||
The point of the routed case is that port forwarding from the container
|
||||
in this case is limited to a single interface, not *all interfaces* as
|
||||
is the default in the masquerading container bridge setup.
|
||||
@@ -443,21 +470,15 @@ A perhaps more common case is to bridge the other end of the VETH pair
|
||||
with other physical ports. In this section we show how to add a new
|
||||
pair to give our container two interfaces:
|
||||
|
||||
_______________
|
||||
| | .1 br0
|
||||
veth0 .1 | .2 eth0 | / \
|
||||
\ 192.168.0.0/24 | / eth1 .2 | veth1b e1
|
||||
'------------------' \ | 192.168.1.0/24 /
|
||||
| [ntpd] '------------------'
|
||||
|_______________|
|
||||

|
||||
|
||||
We start by adding the second VETH pair:
|
||||
|
||||
admin@example:/config/> edit interface veth1a
|
||||
admin@example:/config/interface/veth1a/> set veth peer veth1b
|
||||
admin@example:/config/interface/veth1a/> set veth peer veth1
|
||||
admin@example:/config/interface/veth1a/> set ipv4 address 192.168.1.2 prefix-length 24
|
||||
|
||||
> The LAN bridge (br0) in this example has IP address 192.168.1.1.
|
||||
> The LAN bridge (br1) in this example has IP address 192.168.1.1.
|
||||
|
||||
When a container has multiple host interfaces it can often be useful to
|
||||
have a default route installed. This can be added from the host with a
|
||||
@@ -473,15 +494,16 @@ have a default route installed. This can be added from the host with a
|
||||
}
|
||||
}
|
||||
veth {
|
||||
peer veth1b;
|
||||
peer veth1;
|
||||
}
|
||||
admin@example:/config/interface/veth1a/> end
|
||||
admin@example:/config/> set interface veth1b bridge-port bridge br0
|
||||
admin@example:/config/> set interface veth1 bridge-port bridge br1
|
||||
|
||||
Please note, container network routes require the base interface also
|
||||
have a static IP address set. Setting only the route, but no address,
|
||||
means the route is skipped.
|
||||
|
||||
|
||||
### Host Networking
|
||||
|
||||
The third use-case is host networking, this is where a container share
|
||||
@@ -491,7 +513,7 @@ the host operating system.
|
||||
|
||||
The host networking setup cannot be combined with any other network.
|
||||
|
||||
For an example, see below.
|
||||
For an example, [see below](#application-container-nftables).
|
||||
|
||||
|
||||
Mounts and Volumes
|
||||
@@ -599,6 +621,17 @@ container ID (hash) is used, but this can be easily changed:
|
||||
admin@example:/> container shell system
|
||||
root@sys101:/#
|
||||
|
||||
In fact, the container `hostname` setting supports the same format
|
||||
specifiers as the host's `hostname` setting:
|
||||
|
||||
- `%i`: OS ID, from `/etc/os-release`, from Menuconfig branding
|
||||
- `%h`: Default hostname, from `/etc/os-release`, from branding
|
||||
- `%m`: NIC specific part of base MAC, e.g., to `c0-ff-ee`
|
||||
- `%%`: Literal %
|
||||
|
||||
The most useful combination is probably `"container-name-%m"`, which in
|
||||
this example give the container hostname `container-name-c0-ff-ee`.
|
||||
|
||||
[^1]: this does not apply to the admin-exec command `container run`.
|
||||
This command is intended to be used for testing and evaluating
|
||||
container images. Such containers are given a private network
|
||||
@@ -626,6 +659,7 @@ Notice how we `set network host`, so the container can see and act on
|
||||
all the host's interfaces, and that we also have to run the container
|
||||
in *privileged* mode.
|
||||
|
||||
|
||||
### Application Container: ntpd
|
||||
|
||||
The default NTP server/client in Infix is Chrony, a fully working and
|
||||
@@ -706,7 +740,7 @@ and then asking what the hostname is on the host:
|
||||
|
||||
One use-case for this method is when extending Infix with a management
|
||||
container that connects to other systems. For some tips on how to
|
||||
control an Infix system this way, see [Scripting Infix](scriptiong.md).
|
||||
control an Infix system this way, see [Scripting Infix](scripting.md).
|
||||
|
||||
[^2]: The `nsenter` program is available from either the util-linux
|
||||
package in Debian/Ubuntu/Mint, or in BusyBox. Note, however,
|
||||
@@ -714,7 +748,7 @@ control an Infix system this way, see [Scripting Infix](scriptiong.md).
|
||||
|
||||
|
||||
[0]: networking.md
|
||||
[1]: https://github.com/kernelkit/infix/blob/main/src/confd/yang/infix-containers%402023-12-14.yang
|
||||
[1]: https://github.com/kernelkit/infix/blob/main/src/confd/yang/infix-containers.yang
|
||||
[2]: https://github.com/troglobit/mg
|
||||
[3]: https://github.com/opencontainers/image-spec/blob/main/image-layout.md
|
||||
[4]: system.md#ssh-authorized-key
|
||||
|
||||
|
After Width: | Height: | Size: 317 KiB |
|
After Width: | Height: | Size: 340 KiB |
|
After Width: | Height: | Size: 269 KiB |
|
After Width: | Height: | Size: 261 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 339 KiB |
|
Before Width: | Height: | Size: 268 KiB After Width: | Height: | Size: 281 KiB |
|
After Width: | Height: | Size: 224 KiB |
@@ -62,9 +62,11 @@ The system has several datastores (or files):
|
||||
configure context. Any changes made here can be discarded (`abort`,
|
||||
`rollback`) or committed (`commit`, `leave`) to `running-config`.
|
||||
|
||||
> See the [Branding & Releases](branding.md) for information on how
|
||||
> `factory-config` and `failure-config` can be adapted to different
|
||||
> customer requirements.
|
||||
> Please see the [Branding & Releases](branding.md) document for more
|
||||
> in-depth information on how `factory-config` and `failure-config` can
|
||||
> be adapted to different customer requirements. Including how you can
|
||||
> override the generated versions of these files with plain per-product
|
||||
> ones -- this may even protect against some of the failure modes below.
|
||||
|
||||
|
||||
## System Boot
|
||||
@@ -90,7 +92,8 @@ password in VPD, are detailed later in this section.
|
||||
there is a working fail safe, or rather *fail secure*, mode
|
||||
4. On first power-on, and after a factory reset, the system does not
|
||||
have a `startup-config`, in which case `factory-config` is copied
|
||||
to `startup-config`
|
||||
to `startup-config` -- if a per-product specific version exists it
|
||||
is preferred over the generated one
|
||||
5. Provided the integrity of the `startup-config` is OK, a system
|
||||
service loads and activates the configuration
|
||||
|
||||
@@ -123,13 +126,17 @@ syntax, failed validation against the system's YANG model, or a bug in
|
||||
the system's `confd` service, the *Fail Secure Mode* is triggered and
|
||||
`failure-config` is loaded (unless VPD Failure, see above).
|
||||
|
||||
> Again, please see the [Branding & Releases](branding.md) document for
|
||||
> how to provide a per-product hard-coded `failure-config` to suit your
|
||||
> products preferences.
|
||||
|
||||
*Fail Secure Mode* is a fail-safe mode provided for debugging the
|
||||
system. The default[^3] is isolated interfaces with communication only to
|
||||
the management CPU, SSH and console login using the device's factory
|
||||
reset password, IP connectivity only using IPv6 link-local, and device
|
||||
discovery protocols: LLDP, mDNS-SD. The login and shell prompt are set
|
||||
to `failure-c0-ff-ee`, the last three octets of the device's base MAC
|
||||
address.
|
||||
system. The default[^3] creates a setup of isolated interfaces with
|
||||
communication only to the management CPU, SSH and console login using
|
||||
the device's factory reset password, IP connectivity only using IPv6
|
||||
link-local, and device discovery protocols: LLDP, mDNS-SD. The login
|
||||
and shell prompt are set to `failure-c0-ff-ee`, the last three octets of
|
||||
the device's base MAC address.
|
||||
|
||||
[^1]: YANG is a modeling language from IETF, replacing that used for
|
||||
SNMP (MIB), used to describe the subsystems and properties of
|
||||
|
||||
|
After Width: | Height: | Size: 17 KiB |
@@ -14,8 +14,34 @@ Infix to exploit the unique features not available in IEEE models.
|
||||
|
||||
## Interface LEGO®
|
||||
|
||||
The network building blocks available in Linux are akin to the popular
|
||||
LEGO® bricks.
|
||||
|
||||

|
||||
|
||||
There are two types of relationships that can link two blocks together:
|
||||
|
||||
1. **Lower-to-upper**: Visually represented by an extruding square
|
||||
connected upwards to a square socket. An interface _can only have
|
||||
a single_ lower-to-upper relationship, i.e., it can be attached to
|
||||
a single upper interface like a bridge or a LAG. In `iproute2`
|
||||
parlance, this corresponds to the interface's `master` setting
|
||||
2. **Upper-to-lower**: Visually represented by an extruding semicircle
|
||||
connected downwards to a semicircle socket. The lower interface in
|
||||
these relationships _accepts multiple_ upper-to-lower relationships
|
||||
from different upper blocks. E.g., multiple VLANs and IP address
|
||||
blocks can be connected to the same lower interface
|
||||
|
||||

|
||||
|
||||
An interface may simultaneously have a _lower-to-upper_ relation to some
|
||||
other interface, and be the target of one or more _upper-to-lower_
|
||||
relationships. It is valid, for example, for a physical port to be
|
||||
attached to a bridge, but also have a VLAN interface stacked on top of
|
||||
it. In this example, traffic assigned to the VLAN in question would be
|
||||
diverted to the VLAN interface before entering the bridge, while all
|
||||
other traffic would be bridged as usual.
|
||||
|
||||
| **Type** | **Yang Model** | **Description** |
|
||||
| -------- | ----------------- | ------------------------------------------------------------- |
|
||||
| bridge | infix-if-bridge | SW implementation of an IEEE 802.1Q bridge |
|
||||
@@ -27,6 +53,7 @@ Infix to exploit the unique features not available in IEEE models.
|
||||
| | ieee802-ethernet-interface | |
|
||||
| veth | infix-if-veth | Virtual Ethernet pair, typically one end is in a container |
|
||||
|
||||
|
||||
## Data Plane
|
||||
|
||||
The blocks you choose, and how you connect them, defines your data plane.
|
||||
@@ -50,6 +77,65 @@ possible to share with a container. Meaning, all the building blocks
|
||||
used on the left hand side can also be used freely on the right hand
|
||||
side as well.
|
||||
|
||||
|
||||
### General
|
||||
|
||||
General interface settings include `type`, `enable`, custom MAC address,
|
||||
and text `description`. Other settings have their own sections, below.
|
||||
|
||||
The `type` is important to set when configuring devices remotely because
|
||||
unlike the CLI, a NETCONF or RESTCONF session cannot guess the interface
|
||||
type for you. The operating system provides an override of the
|
||||
available interface types.
|
||||
|
||||
An `enabled` interface can be inspected using the operational datastore,
|
||||
nodes `admin-state` and `oper-state` show the status, . Possible values
|
||||
are listed in the YANG model.
|
||||
|
||||
The `custom-phys-address` can be used to set an interface's MAC address.
|
||||
This is an extension to the ietf-interfaces YANG model, which defines
|
||||
`phys-address` as read-only[^4]. The following shows the different
|
||||
configuration options.
|
||||
|
||||
> **Note:** there is no validation or safety checks performed by the
|
||||
> system when using `custom-phys-address`. In particular the `offset`
|
||||
> variant can be dangerous to use -- pay attention to the meaning of
|
||||
> bits in the upper-most octet: local bit, multicast/group, etc.
|
||||
|
||||
#### Fixed custom MAC
|
||||
|
||||
```
|
||||
admin@example:/config/> edit interface veth0a
|
||||
admin@example:/config/interface/veth0a/> set custom-phys-address static 00:ab:00:11:22:33
|
||||
|
||||
=> 00:ab:00:11:22:33
|
||||
```
|
||||
|
||||
#### Chassis MAC
|
||||
|
||||
Chassis MAC, sometimes also referred to as base MAC. In these two
|
||||
examples it is `00:53:00:c0:ff:ee`.
|
||||
|
||||
```
|
||||
admin@example:/config/> edit interface veth0a
|
||||
admin@example:/config/interface/veth0a/> set custom-phys-address chassis
|
||||
|
||||
=> 00:53:00:c0:ff:ee
|
||||
```
|
||||
|
||||
#### Chassis MAC, with offset
|
||||
|
||||
When constructing a derived address it is recommended to set the locally
|
||||
administered bit. Same chassis MAC as before.
|
||||
|
||||
```
|
||||
admin@example:/config/> edit interface veth0a
|
||||
admin@example:/config/interface/veth0a/> set custom-phys-address chassis offset 02:00:00:00:00:02
|
||||
|
||||
=> 02:53:00:c0:ff:f0
|
||||
```
|
||||
|
||||
|
||||
### Bridging
|
||||
|
||||
This is the most central part of the system. A bridge is a switch, and
|
||||
@@ -92,7 +178,7 @@ admin@example:/config/> edit interface br0
|
||||
admin@example:/config/interface/br0/> up
|
||||
admin@example:/config/> set interface eth0 bridge-port bridge br0
|
||||
admin@example:/config/> set interface eth0 bridge-port pvid 10
|
||||
admin@example:/config interface eth1 bridge-port bridge br0
|
||||
admin@example:/config/> set interface eth1 bridge-port bridge br0
|
||||
admin@example:/config/> set interface eth1 bridge-port pvid 20
|
||||
admin@example:/config/> edit interface br0
|
||||
admin@example:/config/interface/br0/> set bridge vlans vlan 10 untagged eth0
|
||||
@@ -1031,3 +1117,6 @@ currently supported, namely `ipv4` and `ipv6`.
|
||||
mapping the low-order 23-bits of the IP address in the low-order 23
|
||||
bits of the Ethernet address 01:00:5E:00:00:00. Meaning, more than
|
||||
one IP multicast group maps to the same MAC multicast group.
|
||||
[^4]: A YANG deviation was previously used to make it possible to set
|
||||
`phys-address`, but this has been replaced with the more flexible
|
||||
`custom-phys-address`.
|
||||
|
||||
@@ -54,8 +54,8 @@ significant bits of the DSCP is used to select the queue:
|
||||
| 6 | 48-55 | ⇒ | 6 | 25 |
|
||||
| 7 | 56-63 | ⇒ | 7 | 33 |
|
||||
|
||||
For packets containing both a VLAN tag and an IP header, DSCP priority
|
||||
takes precedence over PCP priority. In cases where neither are
|
||||
For packets containing both a VLAN tag and an IP header, PCP priority
|
||||
takes precedence over DSCP priority. In cases where neither are
|
||||
available, packets are always assigned to queue 0.
|
||||
|
||||
Each port's set of 8 egress queues operate on a Weighted Round Robin
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
menu "Packages"
|
||||
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/bin/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/confd/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/test-mode/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/confd-test-mode/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/curios-httpd/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/curios-nftables/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/execd/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/gencert/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/statd/Config.in"
|
||||
@@ -33,4 +36,5 @@ source "$BR2_EXTERNAL_INFIX_PATH/package/sysrepo-cpp/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/rousette/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/nghttp2-asio/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/date-cpp/Config.in"
|
||||
|
||||
endmenu
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
config BR2_PACKAGE_BIN
|
||||
bool "bin"
|
||||
select BR2_PACKAGE_SYSREPO
|
||||
select BR2_PACKAGE_LIBITE
|
||||
help
|
||||
Misc. tools for CLI and shell users.
|
||||
|
||||
https://github.com/kernelkit/infix
|
||||
@@ -0,0 +1 @@
|
||||
sha256 d2f96418893ac66156d0e691cda189b0d85ae1d814065d1d9aa1845383100f46 LICENSE
|
||||
@@ -0,0 +1,21 @@
|
||||
################################################################################
|
||||
#
|
||||
# bin
|
||||
#
|
||||
################################################################################
|
||||
|
||||
BIN_VERSION = 1.0
|
||||
BIN_SITE_METHOD = local
|
||||
BIN_SITE = $(BR2_EXTERNAL_INFIX_PATH)/src/bin
|
||||
BIN_LICENSE = BSD-3-Clause
|
||||
BIN_LICENSE_FILES = LICENSE
|
||||
BIN_REDISTRIBUTE = NO
|
||||
BIN_DEPENDENCIES = sysrepo libite
|
||||
BIN_CONF_OPTS = --prefix= --disable-silent-rules
|
||||
BIN_AUTORECONF = YES
|
||||
|
||||
define BIN_CONF_ENV
|
||||
CFLAGS="$(INFIX_CFLAGS)"
|
||||
endef
|
||||
|
||||
$(eval $(autotools-package))
|
||||
@@ -0,0 +1,10 @@
|
||||
config BR2_PACKAGE_CONFD_TEST_MODE
|
||||
bool "confd test mode"
|
||||
depends on BR2_PACKAGE_CONFD
|
||||
select BR2_PACKAGE_LIBITE
|
||||
select BR2_PACKAGE_LIBYANG
|
||||
select BR2_PACKAGE_SYSREPO
|
||||
select BR2_PACKAGE_LIBSRX
|
||||
help
|
||||
A companion plugin to confd providing functionality required to
|
||||
run tests with Infamy, i.e., enable Infix test mode.
|
||||
@@ -0,0 +1,32 @@
|
||||
CONFD_TEST_MODE_VERSION = 1.0
|
||||
CONFD_TEST_MODE_SITE_METHOD = local
|
||||
CONFD_TEST_MODE_SITE = $(BR2_EXTERNAL_INFIX_PATH)/src/test-mode
|
||||
CONFD_TEST_MODE_LICENSE = BSD-3-Clause
|
||||
CONFD_TEST_MODE_LICENSE_FILES = LICENSE
|
||||
CONFD_TEST_MODE_REDISTRIBUTE = NO
|
||||
CONFD_TEST_MODE_DEPENDENCIES = sysrepo libite libyang confd
|
||||
CONFD_TEST_MODE_AUTORECONF = YES
|
||||
CONFD_TEST_MODE_SYSREPO_SHM_PREFIX = sr_buildroot$(subst /,_,$(CONFIG_DIR))_test_mode
|
||||
|
||||
COMMON_SYSREPO_ENV = \
|
||||
SYSREPO_SHM_PREFIX=$(CONFD_SYSREPO_SHM_PREFIX) \
|
||||
SYSREPOCTL_EXECUTABLE="$(HOST_DIR)/bin/sysrepoctl" \
|
||||
SYSREPOCFG_EXECUTABLE="$(HOST_DIR)/bin/sysrepocfg" \
|
||||
SEARCH_PATH="$(TARGET_DIR)/usr/share/yang/modules/confd/"
|
||||
|
||||
define CONFD_TEST_MODE_INSTALL_YANG_MODULES
|
||||
$(COMMON_SYSREPO_ENV) \
|
||||
SEARCH_PATH="$(TARGET_DIR)/usr/share/yang/modules/test-mode/" $(BR2_EXTERNAL_INFIX_PATH)/utils/sysrepo-load-modules.sh $(@D)/yang/test-mode.inc
|
||||
endef
|
||||
define CONFD_TEST_MODE_PERMISSIONS
|
||||
/etc/sysrepo/data/ r 660 root wheel - - - - -
|
||||
/etc/sysrepo/data d 770 root wheel - - - - -
|
||||
endef
|
||||
define CONFD_TEST_MODE_CLEANUP
|
||||
rm -f /dev/shm/$(CONFD_TEST_MODE_SYSREPO_SHM_PREFIX)*
|
||||
endef
|
||||
|
||||
CONFD_TEST_MODE_PRE_INSTALL_TARGET_HOOKS += CONFD_TEST_MODE_CLEANUP
|
||||
CONFD_TEST_MODE_POST_INSTALL_TARGET_HOOKS += CONFD_TEST_MODE_INSTALL_YANG_MODULES
|
||||
|
||||
$(eval $(autotools-package))
|
||||
@@ -4,7 +4,7 @@
|
||||
#
|
||||
################################################################################
|
||||
|
||||
CONFD_VERSION = 1.1
|
||||
CONFD_VERSION = 1.2
|
||||
CONFD_SITE_METHOD = local
|
||||
CONFD_SITE = $(BR2_EXTERNAL_INFIX_PATH)/src/confd
|
||||
CONFD_LICENSE = BSD-3-Clause
|
||||
|
||||
@@ -2,8 +2,8 @@ config BR2_PACKAGE_CURIOS_HTTPD
|
||||
bool "curiOS-httpd"
|
||||
help
|
||||
Example of how to bundle an OCI archive of curiOS-httpd in
|
||||
/lib/oci for the given target architecture. OCI archives
|
||||
can also be bundled in post-build.sh, but with packaging
|
||||
the "source" is bundled in SDK builds.
|
||||
/lib/oci for the given target architecture. OCI archives can
|
||||
also be bundled in post-build.sh, but with packaging all the
|
||||
"source" tarballs are bundled for SDK builds (archiving).
|
||||
|
||||
https://github.com/kernelkit/curiOS
|
||||
|
||||
@@ -9,11 +9,11 @@ CURIOS_HTTPD_SOURCE = curios-httpd-oci-$(GO_GOARCH)-$(CURIOS_HTTPD_VERSION).tar.
|
||||
CURIOS_HTTPD_SITE = https://github.com/kernelkit/curiOS/releases/download/$(CURIOS_HTTPD_VERSION)
|
||||
CURIOS_HTTPD_LICENSE = GPL
|
||||
CURIOS_HTTPD_LICENSE_FILES = COPYING
|
||||
CURIOS_HTTPD_INSTALL_TARGET = YES
|
||||
|
||||
define CURIOS_HTTPD_INSTALL_TARGET_CMDS
|
||||
mkdir -p $(TARGET_DIR)/lib/oci
|
||||
(cd $(@D)/.. && $(TAR) cfz $(TARGET_DIR)/lib/oci/$(notdir $(@D)).tar.gz $(notdir $(@D)))
|
||||
cp $(CURIOS_HTTPD_DL_DIR)/$(CURIOS_HTTPD_SOURCE) \
|
||||
$(TARGET_DIR)/lib/oci/$(notdir $(@D)).tar.gz
|
||||
endef
|
||||
|
||||
$(eval $(generic-package))
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
config BR2_PACKAGE_CURIOS_NFTABLES
|
||||
bool "curiOS-nftables"
|
||||
help
|
||||
Example of how to bundle an OCI archive of curiOS-nftables in
|
||||
/lib/oci for the given target architecture. OCI archives can
|
||||
also be bundled in post-build.sh, but with packaging all the
|
||||
"source" tarballs are bundled for SDK builds (archiving).
|
||||
|
||||
https://github.com/kernelkit/curiOS
|
||||
@@ -0,0 +1,4 @@
|
||||
# Locally computed
|
||||
sha256 ab15fd526bd8dd18a9e77ebc139656bf4d33e97fc7238cd11bf60e2b9b8666c6 COPYING
|
||||
sha256 f25651505bf4fc635dc8d391f377b1116837e99dee522ce0691c15b090cee818 curios-nftables-oci-arm64-v24.05.0.tar.gz
|
||||
sha256 025c2a5d6c71c62ebbe6f96d8b9ffa3235d6812e87b51645f6e89357d9762669 curios-nftables-oci-amd64-v24.05.0.tar.gz
|
||||
@@ -0,0 +1,20 @@
|
||||
################################################################################
|
||||
#
|
||||
# curios-nftables
|
||||
#
|
||||
################################################################################
|
||||
|
||||
CURIOS_NFTABLES_VERSION = v24.05.0
|
||||
CURIOS_NFTABLES_SOURCE = curios-nftables-oci-$(GO_GOARCH)-$(CURIOS_NFTABLES_VERSION).tar.gz
|
||||
CURIOS_NFTABLES_SITE = https://github.com/kernelkit/curiOS/releases/download/$(CURIOS_NFTABLES_VERSION)
|
||||
CURIOS_NFTABLES_LICENSE = GPL
|
||||
CURIOS_NFTABLES_LICENSE_FILES = COPYING
|
||||
CURIOS_NFTABLES_INSTALL_TARGET = YES
|
||||
|
||||
define CURIOS_NFTABLES_INSTALL_TARGET_CMDS
|
||||
mkdir -p $(TARGET_DIR)/lib/oci
|
||||
cp $(CURIOS_NFTABLES_DL_DIR)/$(CURIOS_NFTABLES_SOURCE) \
|
||||
$(TARGET_DIR)/lib/oci/$(notdir $(@D)).tar.gz
|
||||
endef
|
||||
|
||||
$(eval $(generic-package))
|
||||
@@ -0,0 +1,67 @@
|
||||
From 46ffa81f5c88ce95db011369d8bfb802313e4217 Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Thu, 17 Oct 2024 14:23:24 +0200
|
||||
Subject: [PATCH] Only mark rdeps dirty if main service is nohup
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
This patch changes a behavior that's been default since Finit 4.0,
|
||||
introduced in 4d05bf9 with 4.0-rc2.
|
||||
|
||||
If service B depends on A and A needs to be reloaded, then B may be
|
||||
affected. If A is declared as NOHUP <!>, then A will be stopped and
|
||||
restarted, during which time the condition it provides is removed,
|
||||
and B will also be stopped.
|
||||
|
||||
However, and as of this patch, if A is declared supporting HUP, then the
|
||||
condition A provides will only go into flux, during which time B will be
|
||||
SIGSTOPed instead of needing to be reloaded.
|
||||
|
||||
Fix #415
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
---
|
||||
src/service.c | 8 ++++++++
|
||||
src/svc.h | 1 +
|
||||
2 files changed, 9 insertions(+)
|
||||
|
||||
diff --git a/src/service.c b/src/service.c
|
||||
index 61be85c..b995ff4 100644
|
||||
--- a/src/service.c
|
||||
+++ b/src/service.c
|
||||
@@ -2001,6 +2001,10 @@ static void svc_mark_affected(char *cond)
|
||||
* Called on conf_reload() to update service reverse dependencies.
|
||||
* E.g., if ospfd depends on zebra and the zebra Finit conf has
|
||||
* changed, we need to mark the ospfd Finit conf as changed too.
|
||||
+ *
|
||||
+ * However, a daemon that depends on syslogd (sysklogd project), need
|
||||
+ * not be reloeaded (SIGHUP'ed or stop/started) because syslogd support
|
||||
+ * reloading its configuration file on SIGHUP.
|
||||
*/
|
||||
void service_update_rdeps(void)
|
||||
{
|
||||
@@ -2012,6 +2016,10 @@ void service_update_rdeps(void)
|
||||
if (!svc_is_changed(svc))
|
||||
continue;
|
||||
|
||||
+ /* Service supports reloading conf without stop/start */
|
||||
+ if (!svc_is_nohup(svc))
|
||||
+ continue; /* Yup, no need to stop start rdeps */
|
||||
+
|
||||
svc_mark_affected(mkcond(svc, cond, sizeof(cond)));
|
||||
}
|
||||
}
|
||||
diff --git a/src/svc.h b/src/svc.h
|
||||
index d00ac14..e2f6bd8 100644
|
||||
--- a/src/svc.h
|
||||
+++ b/src/svc.h
|
||||
@@ -259,6 +259,7 @@ static inline int svc_is_tty (svc_t *svc) { return svc && SVC_TYPE_TTY
|
||||
static inline int svc_is_runtask (svc_t *svc) { return svc && (SVC_TYPE_RUNTASK & svc->type);}
|
||||
static inline int svc_is_forking (svc_t *svc) { return svc && svc->forking; }
|
||||
static inline int svc_is_manual (svc_t *svc) { return svc && svc->manual; }
|
||||
+static inline int svc_is_nohup (svc_t *svc) { return svc && (0 == svc->sighup); }
|
||||
|
||||
static inline int svc_in_runlevel (svc_t *svc, int runlevel) { return svc && ISSET(svc->runlevels, runlevel); }
|
||||
static inline int svc_nohup (svc_t *svc) { return svc && (0 == svc->sighup || 0 != svc->args_dirty); }
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
From c2218236546908ecab5eab4b32e698d7bb3d984a Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Sat, 3 Feb 2024 17:30:30 +0100
|
||||
Subject: [PATCH] shutdown: use cond_clear_noupdate() to prevent nested
|
||||
service_stop()
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
When the system shuts down, or user changes runlevels, we don't have to
|
||||
call cond_clear_update(), because this can lead to nested service_stop()
|
||||
calls, which in turn lead to out of sync progress updates:
|
||||
|
||||
[ .. ] Stopping Foo
|
||||
[ OK ] Stopping Bar
|
||||
[ OK ]
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
---
|
||||
src/cond-w.c | 6 +++++-
|
||||
src/service.c | 4 +++-
|
||||
2 files changed, 8 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/cond-w.c b/src/cond-w.c
|
||||
index 2502264..0546282 100644
|
||||
--- a/src/cond-w.c
|
||||
+++ b/src/cond-w.c
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "cond.h"
|
||||
#include "pid.h"
|
||||
#include "service.h"
|
||||
+#include "sm.h"
|
||||
|
||||
struct cond_boot {
|
||||
TAILQ_ENTRY(cond_boot) link;
|
||||
@@ -214,7 +215,10 @@ static int do_delete(const char *fpath, const struct stat *sb, int tflag, struct
|
||||
err(1, "Failed removing condition %s", fpath);
|
||||
|
||||
cond = ptr + strlen(COND_BASE) + 1;
|
||||
- cond_update(cond);
|
||||
+ if (sm_is_in_teardown(&sm))
|
||||
+ cond_clear_noupdate(cond);
|
||||
+ else
|
||||
+ cond_update(cond);
|
||||
|
||||
return 0;
|
||||
}
|
||||
diff --git a/src/service.c b/src/service.c
|
||||
index 8175757..eca9ed0 100644
|
||||
--- a/src/service.c
|
||||
+++ b/src/service.c
|
||||
@@ -2261,7 +2261,7 @@ static void svc_set_state(svc_t *svc, svc_state_t new_state)
|
||||
/* if PID isn't collected within SVC_TERM_TIMEOUT msec, kill it! */
|
||||
if (new_state == SVC_STOPPING_STATE) {
|
||||
dbg("%s is stopping, wait %d sec before sending SIGKILL ...",
|
||||
- svc_ident(svc, NULL, 0), svc->killdelay / 1000);
|
||||
+ svc_ident(svc, NULL, 0), svc->killdelay / 1000);
|
||||
service_timeout_cancel(svc);
|
||||
service_timeout_after(svc, svc->killdelay, service_kill);
|
||||
}
|
||||
@@ -2299,6 +2299,8 @@ static void svc_set_state(svc_t *svc, svc_state_t new_state)
|
||||
if ((old_state == SVC_RUNNING_STATE && new_state == SVC_PAUSED_STATE) ||
|
||||
(old_state == SVC_PAUSED_STATE && new_state == SVC_RUNNING_STATE))
|
||||
; /* only paused during reload, don't clear conds. */
|
||||
+ else if (sm_is_in_teardown(&sm))
|
||||
+ cond_clear_noupdate(cond);
|
||||
else
|
||||
cond_clear(cond);
|
||||
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
From 5998342b3e55638b0f7248383e939a64f53fa8ff Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Mon, 26 Feb 2024 08:41:14 +0100
|
||||
Subject: [PATCH] system: drop debug mode from udevd
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
---
|
||||
system/10-hotplug.conf.in | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/system/10-hotplug.conf.in b/system/10-hotplug.conf.in
|
||||
index 49ea081..a4f64b5 100644
|
||||
--- a/system/10-hotplug.conf.in
|
||||
+++ b/system/10-hotplug.conf.in
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
# Check for systemd-udevd and eudev, if we find both, we opt for the latter.
|
||||
service nowarn [S12345789] cgroup.system name:udevd notify:none pid:udevd log /lib/systemd/systemd-udevd -- Device event daemon (udev)
|
||||
-service nowarn [S12345789] cgroup.system name:udevd notify:none pid:udevd log udevd -D -- Device event daemon (udev)
|
||||
+service nowarn [S12345789] cgroup.system name:udevd notify:none pid:udevd log udevd -- Device event daemon (udev)
|
||||
|
||||
# Wait for udevd to start, then trigger coldplug events and module loading.
|
||||
# The last 'settle' call waits for it to finalize processing all uevents.
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
From c1ed3733986486f3255e77dec47ae1d4b2836e2f Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Mon, 11 Mar 2024 15:46:38 +0100
|
||||
Subject: [PATCH 3/4] Fix #397: drop ttinit() for PID 1
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
After reports from the field, see issue #397, of lockups at reboot,
|
||||
we've decided to drop this code from PID 1. It was added before the 4.x
|
||||
series, when the current progress output was introduced. For the older
|
||||
style progress it served a purpose since the placement of [OK]/[FAIL]
|
||||
was on the right hand side.
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
---
|
||||
src/log.c | 9 ---------
|
||||
1 file changed, 9 deletions(-)
|
||||
|
||||
diff --git a/src/log.c b/src/log.c
|
||||
index ea49705..b776525 100644
|
||||
--- a/src/log.c
|
||||
+++ b/src/log.c
|
||||
@@ -42,8 +42,6 @@ static int loglevel = LOG_INFO;
|
||||
|
||||
void log_init(void)
|
||||
{
|
||||
- ttinit();
|
||||
-
|
||||
if (debug)
|
||||
loglevel = LOG_DEBUG;
|
||||
else
|
||||
@@ -53,13 +51,6 @@ void log_init(void)
|
||||
/* If we enabled terse mode at boot, restore to previous setting at shutdown */
|
||||
void log_exit(void)
|
||||
{
|
||||
- /*
|
||||
- * Unless in debug mode at shutdown, Reinitialize screen,
|
||||
- * terminal may have been resized at runtime
|
||||
- */
|
||||
- if (!debug)
|
||||
- ttinit();
|
||||
-
|
||||
enable_progress(1);
|
||||
}
|
||||
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
From 146bf5512208cb906edddb3f0108cf6f7c525044 Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Mon, 11 Mar 2024 15:55:39 +0100
|
||||
Subject: [PATCH 4/4] Fix #398: display unsupported initctl command (number) in
|
||||
log
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
---
|
||||
src/api.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/api.c b/src/api.c
|
||||
index c19c0d8..8d29a23 100644
|
||||
--- a/src/api.c
|
||||
+++ b/src/api.c
|
||||
@@ -377,7 +377,9 @@ static void api_cb(uev_t *w, void *arg, int events)
|
||||
case INIT_CMD_POWEROFF:
|
||||
case INIT_CMD_SUSPEND:
|
||||
if (IS_RESERVED_RUNLEVEL(runlevel)) {
|
||||
- warnx("Unsupported command in runlevel S and 6/0.");
|
||||
+ strterm(rq.data, sizeof(rq.data));
|
||||
+ warnx("Unsupported command (cmd: %d, data: %s) in runlevel S and 6/0.",
|
||||
+ rq.cmd, rq.data);
|
||||
goto leave;
|
||||
}
|
||||
default:
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
From 90a4df8d1281fd64d048ec1bc91e8cec5f96df06 Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Mon, 11 Mar 2024 18:53:22 +0100
|
||||
Subject: [PATCH 5/6] plugins: on error-retry, don't print "Restoring RTC"
|
||||
twice
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
---
|
||||
plugins/rtc.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/plugins/rtc.c b/plugins/rtc.c
|
||||
index 31c99e0..238791f 100644
|
||||
--- a/plugins/rtc.c
|
||||
+++ b/plugins/rtc.c
|
||||
@@ -180,7 +180,8 @@ static void rtc_restore(void *arg)
|
||||
rc = 2;
|
||||
}
|
||||
|
||||
- print_desc(NULL, "Restoring system clock (UTC) from RTC");
|
||||
+ if (!rc)
|
||||
+ print_desc(NULL, "Restoring system clock (UTC) from RTC");
|
||||
tm.tm_isdst = -1; /* Use tzdata to figure it out, please. */
|
||||
tv.tv_sec = mktime(&tm);
|
||||
if (tv.tv_sec == (time_t)-1 || tv.tv_sec < rtc_date_fallback) {
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
From bf4a584e2ebfa512a2d6cfe5e43a81ee741e3296 Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Tue, 12 Mar 2024 05:18:35 +0100
|
||||
Subject: [PATCH 6/7] plugins: add support for hwrng and check if seed file is
|
||||
empty
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
---
|
||||
plugins/urandom.c | 41 ++++++++++++++++++++++++++++++-----------
|
||||
1 file changed, 30 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/plugins/urandom.c b/plugins/urandom.c
|
||||
index 64a3fa7..2da8035 100644
|
||||
--- a/plugins/urandom.c
|
||||
+++ b/plugins/urandom.c
|
||||
@@ -47,6 +47,7 @@ static void setup(void *arg)
|
||||
#ifdef RANDOMSEED
|
||||
struct rand_pool_info *rpi;
|
||||
ssize_t len = 0;
|
||||
+ struct stat st;
|
||||
int rc = -1;
|
||||
int fd, err;
|
||||
|
||||
@@ -55,7 +56,7 @@ static void setup(void *arg)
|
||||
return;
|
||||
}
|
||||
|
||||
- if (!fexist(RANDOMSEED)) {
|
||||
+ if (stat(RANDOMSEED, &st) || st.st_size < 512) {
|
||||
int ret = 1;
|
||||
mode_t prev;
|
||||
FILE *fp;
|
||||
@@ -64,16 +65,34 @@ static void setup(void *arg)
|
||||
prev = umask(077);
|
||||
fp = fopen(RANDOMSEED, "w");
|
||||
if (fp) {
|
||||
- int iter = 128;
|
||||
- struct timeval tv;
|
||||
-
|
||||
- gettimeofday(&tv, NULL);
|
||||
- srandom(tv.tv_sec % 3600);
|
||||
- while (iter--) {
|
||||
- uint32_t i, prng = random();
|
||||
-
|
||||
- for (i = 0; i < sizeof(prng); i++)
|
||||
- fputc((prng >> (i * CHAR_BIT)) & UCHAR_MAX, fp);
|
||||
+ const char *hwrng = "/dev/hwrng";
|
||||
+ FILE *hw;
|
||||
+
|
||||
+ hw = fopen(hwrng, "r");
|
||||
+ if (hw) {
|
||||
+ char buf[512];
|
||||
+ size_t len;
|
||||
+
|
||||
+ len = fread(buf, sizeof(buf[0]), sizeof(buf), hw);
|
||||
+ if (len == 0) {
|
||||
+ fclose(hw);
|
||||
+ goto no_hwrng;
|
||||
+ }
|
||||
+
|
||||
+ len = fwrite(buf, sizeof(buf[0]), len, fp);
|
||||
+ fclose(hw);
|
||||
+ } else {
|
||||
+ struct timeval tv;
|
||||
+ int iter = 128;
|
||||
+no_hwrng:
|
||||
+ gettimeofday(&tv, NULL);
|
||||
+ srandom(tv.tv_sec % 3600);
|
||||
+ while (iter--) {
|
||||
+ uint32_t i, prng = random();
|
||||
+
|
||||
+ for (i = 0; i < sizeof(prng); i++)
|
||||
+ fputc((prng >> (i * CHAR_BIT)) & UCHAR_MAX, fp);
|
||||
+ }
|
||||
}
|
||||
ret = fclose(fp);
|
||||
}
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
From b49f55ab3d1aec48bbfdf2106fd8f500406a5348 Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Wed, 13 Mar 2024 11:48:47 +0100
|
||||
Subject: [PATCH 7/7] tmpfiles.d: ignore x/X command, no cleanup at runtime
|
||||
with Finit
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Silence log warnings for command x/X (ignore clean for path), because
|
||||
Finit does not do tmpfiles cleaning at runtime.
|
||||
|
||||
x /tmp/podman-run-*
|
||||
x /tmp/containers-user-*
|
||||
x /tmp/run-*/libpod
|
||||
D! /var/lib/containers/storage/tmp 0700 root root
|
||||
D! /run/podman 0700 root root
|
||||
D! /var/lib/cni/networks
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
---
|
||||
src/tmpfiles.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/src/tmpfiles.c b/src/tmpfiles.c
|
||||
index d62b09f..15b463c 100644
|
||||
--- a/src/tmpfiles.c
|
||||
+++ b/src/tmpfiles.c
|
||||
@@ -434,6 +434,10 @@ static void tmpfiles(char *line)
|
||||
}
|
||||
}
|
||||
break;
|
||||
+ case 'X':
|
||||
+ case 'x':
|
||||
+ dbg("Unsupported x/X command, ignoring %s, no support for clean at runtime.", path);
|
||||
+ break;
|
||||
case 'Z':
|
||||
opts = "-R";
|
||||
/* fallthrough */
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
From 052136cb9927379e75bc346d46c86d728f1e33ef Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Tue, 2 Apr 2024 16:03:31 +0200
|
||||
Subject: [PATCH 08/12] initctl: touch does not respect -n switch
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Fixes #402
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
---
|
||||
src/serv.c | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/serv.c b/src/serv.c
|
||||
index e14d5ec..1cace46 100644
|
||||
--- a/src/serv.c
|
||||
+++ b/src/serv.c
|
||||
@@ -377,9 +377,9 @@ int serv_touch(char *arg)
|
||||
fn = conf(path, sizeof(path), arg, 0);
|
||||
if (!fexist(fn)) {
|
||||
if (!strstr(arg, "finit.conf"))
|
||||
- ERRX(72, "%s not available.", arg);
|
||||
+ ERRX(noerr ? 0 : 72, "%s not available.", arg);
|
||||
if (is_builtin(arg))
|
||||
- ERRX(4, "%s is a built-in service.", arg);
|
||||
+ ERRX(noerr ? 0 : 4, "%s is a built-in service.", arg);
|
||||
|
||||
strlcpy(path, finit_conf, sizeof(path));
|
||||
fn = path;
|
||||
@@ -387,7 +387,7 @@ int serv_touch(char *arg)
|
||||
|
||||
/* libite:touch() follows symlinks */
|
||||
if (utimensat(AT_FDCWD, fn, NULL, AT_SYMLINK_NOFOLLOW))
|
||||
- ERR(71, "failed marking %s for reload", fn);
|
||||
+ ERR(noerr ? 0 : 71, "failed marking %s for reload", fn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
From 7b501f255b5730ce9da5c72aa6abd87bbf20ba11 Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Wed, 3 Apr 2024 06:46:18 +0200
|
||||
Subject: [PATCH 09/12] initctl: touch does not support template services
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Fixes #403
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
---
|
||||
src/serv.c | 10 ++++++++++
|
||||
src/util.h | 20 ++++++++++++++++++++
|
||||
2 files changed, 30 insertions(+)
|
||||
|
||||
diff --git a/src/serv.c b/src/serv.c
|
||||
index 1cace46..6344ce3 100644
|
||||
--- a/src/serv.c
|
||||
+++ b/src/serv.c
|
||||
@@ -374,6 +374,15 @@ int serv_touch(char *arg)
|
||||
return serv_list("enabled");
|
||||
}
|
||||
|
||||
+ /* 1. Try /etc/finit.d/enabled/$arg.conf to handle template@.conf */
|
||||
+ paste(path, sizeof(path), finit_rcsd, "enabled/");
|
||||
+ strlcat(path, arg, sizeof(path));
|
||||
+ if (!suffix(path, sizeof(path), ".conf") && fexist(path)) {
|
||||
+ fn = path;
|
||||
+ goto touchit;
|
||||
+ }
|
||||
+
|
||||
+ /* 2. Try /etc/finit.d/available/$arg.conf and other combos (legacy) */
|
||||
fn = conf(path, sizeof(path), arg, 0);
|
||||
if (!fexist(fn)) {
|
||||
if (!strstr(arg, "finit.conf"))
|
||||
@@ -385,6 +394,7 @@ int serv_touch(char *arg)
|
||||
fn = path;
|
||||
}
|
||||
|
||||
+touchit:
|
||||
/* libite:touch() follows symlinks */
|
||||
if (utimensat(AT_FDCWD, fn, NULL, AT_SYMLINK_NOFOLLOW))
|
||||
ERR(noerr ? 0 : 71, "failed marking %s for reload", fn);
|
||||
diff --git a/src/util.h b/src/util.h
|
||||
index 9f0cbf0..80e1c51 100644
|
||||
--- a/src/util.h
|
||||
+++ b/src/util.h
|
||||
@@ -109,6 +109,26 @@ static inline int paste(char *buf, size_t len, const char *dir, const char *file
|
||||
fisslashdir(dir) ? "" : file[0] == '/' ? "" : "/", file);
|
||||
}
|
||||
|
||||
+/* ensure path has suffix */
|
||||
+static inline int suffix(char *path, size_t len, const char *sfx)
|
||||
+{
|
||||
+ size_t slen = strlen(sfx);
|
||||
+ size_t plen = strlen(path);
|
||||
+
|
||||
+ if (plen < slen)
|
||||
+ slen = strlcat(path, sfx, len);
|
||||
+ else {
|
||||
+ plen -= slen;
|
||||
+ if (strcmp(&path[plen], sfx))
|
||||
+ slen = strlcat(path, sfx, len);
|
||||
+ }
|
||||
+
|
||||
+ if (slen >= len)
|
||||
+ return -1;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
#endif /* FINIT_UTIL_H_ */
|
||||
|
||||
/**
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
From 6a89e60fc84b90e5f09f61d37892f3b17bd14631 Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Wed, 24 Apr 2024 11:33:35 +0200
|
||||
Subject: [PATCH 10/11] Fix #405: parsing >1 active consoles in tty @console
|
||||
setups
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Systems that have the following tty setup and multiple consoles listed
|
||||
in /sys/class/tty/console/active misbehave:
|
||||
|
||||
tty [12345789] @console 0 xterm noclear passenv
|
||||
|
||||
Only the first listed console is started properly, the remaining ones
|
||||
were registered using the wrong :ID and no arguments to getty.
|
||||
|
||||
This patch fixes the parsing and re-use of the base paramenters for
|
||||
all consoles listed in the active file.
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
---
|
||||
src/service.c | 45 +++++++++++++++++++++++----------------------
|
||||
1 file changed, 23 insertions(+), 22 deletions(-)
|
||||
|
||||
diff --git a/src/service.c b/src/service.c
|
||||
index eca9ed0..95a04b8 100644
|
||||
--- a/src/service.c
|
||||
+++ b/src/service.c
|
||||
@@ -1633,10 +1633,16 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
|
||||
|
||||
if (type == SVC_TYPE_TTY) {
|
||||
size_t i, len = 0;
|
||||
+ char *ptr;
|
||||
|
||||
if (tty_parse_args(&tty, cmd, &args))
|
||||
return errno;
|
||||
|
||||
+ if (tty_isatcon(tty.dev))
|
||||
+ dev = tty_atcon();
|
||||
+ else
|
||||
+ dev = tty.dev;
|
||||
+ next:
|
||||
if (tty.cmd)
|
||||
len += strlen(tty.cmd);
|
||||
else
|
||||
@@ -1659,14 +1665,22 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
|
||||
if (!cmd)
|
||||
return errno;
|
||||
|
||||
- if (tty_isatcon(tty.dev))
|
||||
- dev = tty_atcon();
|
||||
- else
|
||||
- dev = tty.dev;
|
||||
-
|
||||
/* tty's always respawn, never incr. restart_cnt */
|
||||
respawn = 1;
|
||||
- next:
|
||||
+
|
||||
+ /* Create name:id tuple for identity, e.g., tty:S0 */
|
||||
+ ptr = strrchr(dev, '/');
|
||||
+ if (ptr)
|
||||
+ ptr++;
|
||||
+ else
|
||||
+ ptr = dev;
|
||||
+ if (!strncmp(ptr, "tty", 3))
|
||||
+ ptr += 3;
|
||||
+
|
||||
+ name = "tty";
|
||||
+ if (!id || id[0] == 0)
|
||||
+ id = ptr;
|
||||
+
|
||||
svc = svc_find_by_tty(dev);
|
||||
} else
|
||||
svc = svc_find(name, id);
|
||||
@@ -1722,8 +1736,6 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
|
||||
conf_parse_cond(svc, cond);
|
||||
|
||||
if (type == SVC_TYPE_TTY) {
|
||||
- char *ptr;
|
||||
-
|
||||
if (dev)
|
||||
strlcpy(svc->dev, dev, sizeof(svc->dev));
|
||||
if (tty.baud)
|
||||
@@ -1738,19 +1750,6 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
|
||||
|
||||
/* TTYs cannot be redirected */
|
||||
log = NULL;
|
||||
-
|
||||
- /* Create name:id tuple for identity, e.g., tty:S0 */
|
||||
- ptr = strrchr(svc->dev, '/');
|
||||
- if (ptr)
|
||||
- ptr++;
|
||||
- else
|
||||
- ptr = svc->dev;
|
||||
- if (!strncmp(ptr, "tty", 3))
|
||||
- ptr += 3;
|
||||
- if (!id || id[0] == 0)
|
||||
- id = ptr;
|
||||
- strlcpy(svc->name, "tty", sizeof(svc->name));
|
||||
- strlcpy(svc->id, id, sizeof(svc->id));
|
||||
}
|
||||
|
||||
parse_cmdline_args(svc, cmd, &args);
|
||||
@@ -1870,8 +1869,10 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
|
||||
/* continue expanding any 'tty @console ...' */
|
||||
if (tty_isatcon(tty.dev)) {
|
||||
dev = tty_atcon();
|
||||
- if (dev)
|
||||
+ if (dev) {
|
||||
+ id = NULL; /* reset for next tty:ID */
|
||||
goto next;
|
||||
+ }
|
||||
}
|
||||
|
||||
return 0;
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
From 340cae4afd0d11979322a6c2f4d40a12ea59817b Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Wed, 24 Apr 2024 12:46:59 +0200
|
||||
Subject: [PATCH 11/11] Change default behavior, allow kernel logs to console
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
A Linux system booted with the kernel command line option 'quiet' only
|
||||
logs error (and above) severity messages to the console. For embedded
|
||||
systems, which is the primary target for Finit, this is what you want
|
||||
to see.
|
||||
|
||||
Hence, and after careful consideration, this patch changes the default
|
||||
behavior of Finit to allow kernel logs to the console. A build-time
|
||||
configure flags, --disable-kernel-logging, has been added to restore
|
||||
legacy behavior.
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
---
|
||||
configure.ac | 9 +++++++++
|
||||
src/finit.c | 14 +++++++++++---
|
||||
2 files changed, 20 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index a4470d0..31f4cff 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -71,6 +71,10 @@ AC_ARG_ENABLE(redirect,
|
||||
AS_HELP_STRING([--disable-redirect], [Disable redirection of service output to /dev/null]),,[
|
||||
enable_redirect=yes])
|
||||
|
||||
+AC_ARG_ENABLE(kernel_logging,
|
||||
+ AS_HELP_STRING([--disable-kernel-logging], [Disable kernel logging to console (use 'quiet' instead!]),,[
|
||||
+ enable_kernel_logging=yes])
|
||||
+
|
||||
AC_ARG_ENABLE(logrotate,
|
||||
AS_HELP_STRING([--disable-logrotate], [Disable built-in rotation of /var/log/wtmp]),,[
|
||||
enable_logrotate=yes])
|
||||
@@ -181,6 +185,9 @@ AS_IF([test "x$enable_auto_reload" = "xyes"], [
|
||||
AS_IF([test "x$enable_kernel_cmdline" = "xyes"], [
|
||||
AC_DEFINE(KERNEL_CMDLINE, 1, [Dumpster diving after init args from /proc/cmdline])])
|
||||
|
||||
+AS_IF([test "x$enable_kernel_logging" = "xyes"], [
|
||||
+ AC_DEFINE(KERNEL_LOGGING, 1, [Keep kernel warn/err logs to console])])
|
||||
+
|
||||
AS_IF([test "x$enable_fastboot" = "xyes"], [
|
||||
AC_DEFINE(FAST_BOOT, 1, [Skip fsck check on filesystems listed in /etc/fstab])])
|
||||
|
||||
@@ -382,6 +389,8 @@ Optional features:
|
||||
Built-in sulogin......: $with_sulogin $sulogin
|
||||
Built-in watchdogd....: $with_watchdog $watchdog
|
||||
Built-in logrotate....: $enable_logrotate
|
||||
+ Parse kernel cmdline..: $enable_kernel_cmdline
|
||||
+ Keep kernel logging...: $enable_kernel_logging
|
||||
Skip fsck check.......: $enable_fastboot
|
||||
Run fsck fix mode.....: $enable_fsckfix
|
||||
Redirect output.......: $enable_redirect
|
||||
diff --git a/src/finit.c b/src/finit.c
|
||||
index 27b81e9..38b1278 100644
|
||||
--- a/src/finit.c
|
||||
+++ b/src/finit.c
|
||||
@@ -87,14 +87,22 @@ svc_t *wdog = NULL; /* No watchdog by default */
|
||||
*/
|
||||
static void banner(void)
|
||||
{
|
||||
+#ifndef KERNEL_LOGGING
|
||||
/*
|
||||
* Silence kernel logs, assuming users have sysklogd or
|
||||
- * similar enabled to start emptying /dev/kmsg, but for
|
||||
- * our progress we want to own the console.
|
||||
+ * similar enabled to start emptying /dev/kmsg.
|
||||
+ *
|
||||
+ * Instead of using `configure --disable-kernel-logging`, we
|
||||
+ * recommend adjusting the kernel log level in the kernel's
|
||||
+ * menuconfig, or using sysctl kernel.printk, or setting the
|
||||
+ * desired log level, on the kernel cmdline, e.g. 'quiet'.
|
||||
+ *
|
||||
+ * By default KERNEL_LOGGING is enabled so you can see any
|
||||
+ * warnings/errors or higher on your system console.
|
||||
*/
|
||||
if (!debug && !kerndebug)
|
||||
klogctl(6, NULL, 0);
|
||||
-
|
||||
+#endif
|
||||
/*
|
||||
* First level hooks, if you want to run here, you're
|
||||
* pretty much on your own. Nothing's up yet ...
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
From 13b107b7b15e6d4823627ea4707a12108fd5a1c7 Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Fri, 21 Jun 2024 10:24:35 +0200
|
||||
Subject: [PATCH] Fix #407: extend initctl poll timeout
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
---
|
||||
src/client.c | 6 ++++--
|
||||
2 files changed, 8 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/client.c b/src/client.c
|
||||
index c3fd3aef..a8c06ac4 100644
|
||||
--- a/src/client.c
|
||||
+++ b/src/client.c
|
||||
@@ -29,6 +29,8 @@
|
||||
#include "client.h"
|
||||
#include "log.h"
|
||||
|
||||
+#define REQUEST_TIMEOUT 15000
|
||||
+
|
||||
static int sd = -1;
|
||||
|
||||
int client_connect(void)
|
||||
@@ -85,7 +87,7 @@ int client_request(struct init_request *rq, ssize_t len)
|
||||
|
||||
pfd.fd = sd;
|
||||
pfd.events = POLLOUT;
|
||||
- if (poll(&pfd, 1, 2000) <= 0) {
|
||||
+ if (poll(&pfd, 1, REQUEST_TIMEOUT) <= 0) {
|
||||
warn("Timed out waiting for Finit, errno %d", errno);
|
||||
return -1;
|
||||
}
|
||||
@@ -107,7 +109,7 @@ int client_request(struct init_request *rq, ssize_t len)
|
||||
|
||||
pfd.fd = sd;
|
||||
pfd.events = POLLIN | POLLERR | POLLHUP;
|
||||
- if ((rc = poll(&pfd, 1, 2000)) <= 0) {
|
||||
+ if ((rc = poll(&pfd, 1, REQUEST_TIMEOUT)) <= 0) {
|
||||
if (rc) {
|
||||
if (errno == EINTR) /* shutdown/reboot */
|
||||
return -1;
|
||||
@@ -1,64 +0,0 @@
|
||||
From ab62b5282b0461b14464a4a5de49f3b1fa0604fe Mon Sep 17 00:00:00 2001
|
||||
From: Joachim Wiberg <troglobit@gmail.com>
|
||||
Date: Sat, 25 May 2024 19:33:21 +0200
|
||||
Subject: [PATCH 12/12] runparts: add -b (batch) mode for syslog output
|
||||
Organization: Addiva Elektronik
|
||||
|
||||
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
|
||||
---
|
||||
src/runparts.c | 24 ++++++++++++++++++------
|
||||
1 file changed, 18 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/runparts.c b/src/runparts.c
|
||||
index 5af2c2d..c4225ce 100644
|
||||
--- a/src/runparts.c
|
||||
+++ b/src/runparts.c
|
||||
@@ -26,18 +26,27 @@
|
||||
#else
|
||||
#include <sys/prctl.h>
|
||||
|
||||
+const char *active_msg = NULL;
|
||||
+int interactive = 1;
|
||||
int debug;
|
||||
|
||||
static void print_desc(const char *prefix, const char *msg)
|
||||
{
|
||||
- fprintf(stderr, "\e[1m[\e[0m\e[1;33m ⋯ \e[0m\e[1m]\e[0m %s %s", prefix, msg);
|
||||
+ if (interactive)
|
||||
+ fprintf(stderr, "\e[1m[\e[0m\e[1;33m ⋯ \e[0m\e[1m]\e[0m %s %s", prefix, msg);
|
||||
+ else
|
||||
+ fprintf(stderr, "%s %s ...\n", prefix, msg);
|
||||
+ active_msg = msg;
|
||||
}
|
||||
static void print_result(int rc)
|
||||
{
|
||||
- if (rc)
|
||||
- fputs("\r\e[1m[\e[0m\e[1;31mFAIL\e[0m\e[1m]\e[0m\n", stderr);
|
||||
- else
|
||||
- fputs("\r\e[1m[\e[0m\e[1;32m OK \e[0m\e[1m]\e[0m\n", stderr);
|
||||
+ if (interactive) {
|
||||
+ if (rc)
|
||||
+ fputs("\r\e[1m[\e[0m\e[1;31mFAIL\e[0m\e[1m]\e[0m\n", stderr);
|
||||
+ else
|
||||
+ fputs("\r\e[1m[\e[0m\e[1;32m OK \e[0m\e[1m]\e[0m\n", stderr);
|
||||
+ } else
|
||||
+ fprintf(stderr, "[%s] %s\n", rc ? "FAIL" : " OK ", active_msg ?: "");
|
||||
}
|
||||
|
||||
void sig_unblock(void)
|
||||
@@ -193,8 +202,11 @@ int main(int argc, char *argv[])
|
||||
int rc, c, progress = 0, sysv = 0;
|
||||
char *dir;
|
||||
|
||||
- while ((c = getopt(argc, argv, "dh?ps")) != EOF) {
|
||||
+ while ((c = getopt(argc, argv, "bdh?ps")) != EOF) {
|
||||
switch(c) {
|
||||
+ case 'b': /* batch mode */
|
||||
+ interactive = 0;
|
||||
+ break;
|
||||
case 'd':
|
||||
debug = 1;
|
||||
break;
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# From https://github.com/troglobit/finit/releases/
|
||||
sha256 139adcb81ec8a5bb628249f92e2144b20f7e14c53aa56bb86a2fd42c5e7dca11 finit-4.7.tar.gz
|
||||
sha256 5026965e33f31b8fa4e2e465b9521e805fa01c31cade884c07d0fcff97cd0ddf finit-4.8.tar.gz
|
||||
|
||||
# Locally calculated
|
||||
sha256 2fd62c0fe6ea6d1861669f4c87bda83a0b5ceca64f4baa4d16dd078fbd218c14 LICENSE
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#
|
||||
################################################################################
|
||||
|
||||
FINIT_VERSION = 4.7
|
||||
FINIT_VERSION = 4.8
|
||||
FINIT_SITE = https://github.com/troglobit/finit/releases/download/$(FINIT_VERSION)
|
||||
FINIT_LICENSE = MIT
|
||||
FINIT_LICENSE_FILES = LICENSE
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
# Locally calculated
|
||||
sha256 9d9d33b873917ca5d0bdcc47a36d2fd385971ab0c045d1472fcadf95ee5bcf5b LICENCE
|
||||
sha256 7c8c1cc2234331bb8123893356562cce6731448dbaf5b80db72e34490da55b48 klish-plugin-sysrepo-261c615b903233f63c695f91c1dbe58ac063ba13-br1.tar.gz
|
||||
sha256 58b6b271912f9331ea78a815a8cec073924b423403868dd9fcc48de0942f49f8 klish-plugin-sysrepo-213cd51aa8863e7ef66944137db3dffc88d58cc1-br1.tar.gz
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#
|
||||
################################################################################
|
||||
|
||||
KLISH_PLUGIN_SYSREPO_VERSION = 261c615b903233f63c695f91c1dbe58ac063ba13
|
||||
KLISH_PLUGIN_SYSREPO_VERSION = 213cd51aa8863e7ef66944137db3dffc88d58cc1
|
||||
KLISH_PLUGIN_SYSREPO_SITE = https://github.com/kernelkit/klish-plugin-sysrepo.git
|
||||
#KLISH_PLUGIN_SYSREPO_VERSION = cdd3eb51a7f7ee0ed5bd925fa636061d3b1b85fb
|
||||
#KLISH_PLUGIN_SYSREPO_SITE = https://src.libcode.org/pkun/klish-plugin-sysrepo.git
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
config BR2_PACKAGE_KLISH
|
||||
bool "klish"
|
||||
depends on BR2_USE_MMU
|
||||
select BR2_PACKAGE_BIN
|
||||
select BR2_PACKAGE_FAUX
|
||||
select BR2_PACKAGE_LIBXML2
|
||||
help
|
||||
|
||||
@@ -10,7 +10,7 @@ STATD_SITE = $(BR2_EXTERNAL_INFIX_PATH)/src/statd
|
||||
STATD_LICENSE = BSD-3-Clause
|
||||
STATD_LICENSE_FILES = LICENSE
|
||||
STATD_REDISTRIBUTE = NO
|
||||
STATD_DEPENDENCIES = sysrepo libev libsrx jansson python-statd libyang
|
||||
STATD_DEPENDENCIES = sysrepo libev libsrx jansson python-statd libyang libite
|
||||
STATD_AUTORECONF = YES
|
||||
|
||||
define STATD_CONF_ENV
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
config BR2_PACKAGE_TEST_MODE
|
||||
bool "test-mode"
|
||||
select BR2_PACKAGE_LIBITE
|
||||
select BR2_PACKAGE_LIBYANG
|
||||
select BR2_PACKAGE_SYSREPO
|
||||
select BR2_PACKAGE_LIBSRX
|
||||
select BR2_PACKAGE_CONFD
|
||||
help
|
||||
A plugin to sysrepo that provides functionality required to
|
||||
run tests with infamy.
|
||||
@@ -1,32 +0,0 @@
|
||||
TEST_MODE_VERSION = 1.0
|
||||
TEST_MODE_SITE_METHOD = local
|
||||
TEST_MODE_SITE = $(BR2_EXTERNAL_INFIX_PATH)/src/test-mode
|
||||
TEST_MODE_LICENSE = BSD-3-Clause
|
||||
TEST_MODE_LICENSE_FILES = LICENSE
|
||||
TEST_MODE_REDISTRIBUTE = NO
|
||||
TEST_MODE_DEPENDENCIES = sysrepo libite libyang confd
|
||||
TEST_MODE_AUTORECONF = YES
|
||||
TEST_MODE_SYSREPO_SHM_PREFIX = sr_buildroot$(subst /,_,$(CONFIG_DIR))_test_mode
|
||||
|
||||
COMMON_SYSREPO_ENV = \
|
||||
SYSREPO_SHM_PREFIX=$(CONFD_SYSREPO_SHM_PREFIX) \
|
||||
SYSREPOCTL_EXECUTABLE="$(HOST_DIR)/bin/sysrepoctl" \
|
||||
SYSREPOCFG_EXECUTABLE="$(HOST_DIR)/bin/sysrepocfg" \
|
||||
SEARCH_PATH="$(TARGET_DIR)/usr/share/yang/modules/confd/"
|
||||
|
||||
define TEST_MODE_INSTALL_YANG_MODULES
|
||||
$(COMMON_SYSREPO_ENV) \
|
||||
SEARCH_PATH="$(TARGET_DIR)/usr/share/yang/modules/test-mode/" $(BR2_EXTERNAL_INFIX_PATH)/utils/sysrepo-load-modules.sh $(@D)/yang/test-mode.inc
|
||||
endef
|
||||
define TEST_MODE_PERMISSIONS
|
||||
/etc/sysrepo/data/ r 660 root wheel - - - - -
|
||||
/etc/sysrepo/data d 770 root wheel - - - - -
|
||||
endef
|
||||
define TEST_MODE_CLEANUP
|
||||
rm -f /dev/shm/$(TEST_MODE_SYSREPO_SHM_PREFIX)*
|
||||
endef
|
||||
|
||||
TEST_MODE_PRE_INSTALL_TARGET_HOOKS += TEST_MODE_CLEANUP
|
||||
TEST_MODE_POST_INSTALL_TARGET_HOOKS += TEST_MODE_INSTALL_YANG_MODULES
|
||||
|
||||
$(eval $(autotools-package))
|
||||
@@ -1,5 +1,5 @@
|
||||
# Host build of critical components, for Coverity Scan mostly
|
||||
APPS = confd execd factory keyack statd
|
||||
APPS = bin confd execd factory keyack statd
|
||||
|
||||
.PHONY: all
|
||||
all:
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
*~
|
||||
*.o
|
||||
copy
|
||||
erase
|
||||
files
|
||||
|
||||
/aclocal.m4
|
||||
/autom4te.cache/
|
||||
/aux
|
||||
/clixon.xml
|
||||
/compile
|
||||
/config.h
|
||||
/config.h.in
|
||||
/config.guess
|
||||
/config.log
|
||||
/config.status
|
||||
/config.sub
|
||||
/configure
|
||||
/depcomp
|
||||
/.deps/
|
||||
/install-sh
|
||||
/libtool
|
||||
/ltmain.sh
|
||||
/m4
|
||||
/missing
|
||||
|
||||
GPATH
|
||||
GRTAGS
|
||||
GTAGS
|
||||
Makefile
|
||||
Makefile.in
|
||||
@@ -0,0 +1,13 @@
|
||||
Copyright (c) 2024 The KernelKit Authors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
@@ -0,0 +1,22 @@
|
||||
DISTCLEANFILES = *~ *.d
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
bin_PROGRAMS = copy erase files
|
||||
|
||||
copy_SOURCES = copy.c util.c util.h
|
||||
copy_CPPFLAGS = -D_DEFAULT_SOURCE -D_GNU_SOURCE
|
||||
copy_CFLAGS = -W -Wall -Wextra
|
||||
copy_CFLAGS += $(libite_CFLAGS) $(sysrepo_CFLAGS)
|
||||
copy_LDADD = $(libite_LIBS) $(sysrepo_LIBS)
|
||||
|
||||
erase_SOURCES = erase.c util.c util.h
|
||||
erase_CPPFLAGS = -D_DEFAULT_SOURCE -D_GNU_SOURCE
|
||||
erase_CFLAGS = -W -Wall -Wextra
|
||||
erase_CFLAGS += $(libite_CFLAGS) $(sysrepo_CFLAGS)
|
||||
erase_LDADD = $(libite_LIBS) $(sysrepo_LIBS)
|
||||
|
||||
files_SOURCES = files.c util.c util.h
|
||||
files_CPPFLAGS = -D_DEFAULT_SOURCE -D_GNU_SOURCE
|
||||
files_CFLAGS = -W -Wall -Wextra
|
||||
files_CFLAGS += $(libite_CFLAGS) $(sysrepo_CFLAGS)
|
||||
files_LDADD = $(libite_LIBS) $(sysrepo_LIBS)
|
||||
@@ -0,0 +1,2 @@
|
||||
* Add bash completion to 'copy' + 'erase', use 'files'
|
||||
* https://github.com/kernelkit/infix/issues/373
|
||||
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
autoreconf -W portability -vifm
|
||||
@@ -0,0 +1,8 @@
|
||||
# Used by ../Makefile for 'make check' and Coverity Scan
|
||||
export PKG_CONFIG_PATH = $(CURDIR)/../staging/lib/pkgconfig
|
||||
|
||||
all:
|
||||
./autogen.sh
|
||||
./configure
|
||||
make V=1 all
|
||||
make distclean
|
||||
@@ -0,0 +1,70 @@
|
||||
AC_PREREQ(2.61)
|
||||
AC_INIT([bin], [1.0], [https://github.com/kernelkit/infix/issues])
|
||||
AM_INIT_AUTOMAKE(1.11 foreign subdir-objects)
|
||||
AM_SILENT_RULES(yes)
|
||||
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
])
|
||||
|
||||
AC_PROG_CC
|
||||
AC_PROG_INSTALL
|
||||
|
||||
# Check for pkg-config first, warn if it's not installed
|
||||
PKG_PROG_PKG_CONFIG
|
||||
|
||||
PKG_CHECK_MODULES([libite], [libite >= 2.5.0])
|
||||
PKG_CHECK_MODULES([sysrepo], [sysrepo >= 2.2.36])
|
||||
|
||||
# Misc variable replacements for below Summary
|
||||
test "x$prefix" = xNONE && prefix=$ac_default_prefix
|
||||
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
|
||||
|
||||
DATAROOTDIR=`eval echo $datarootdir`
|
||||
DATAROOTDIR=`eval echo $DATAROOTDIR`
|
||||
AC_SUBST(DATAROOTDIR)
|
||||
|
||||
LIBDIR=`eval echo $libdir`
|
||||
LIBDIR=`eval echo $LIBDIR`
|
||||
AC_SUBST(LIBDIR)
|
||||
|
||||
LOCALSTATEDIR=`eval echo $localstatedir`
|
||||
LOCALSTATEDIR=`eval echo $LOCALSTATEDIR`
|
||||
AC_SUBST(LOCALSTATEDIR)
|
||||
|
||||
RUNSTATEDIR=`eval echo $runstatedir`
|
||||
RUNSTATEDIR=`eval echo $RUNSTATEDIR`
|
||||
AC_SUBST(RUNSTATEDIR)
|
||||
|
||||
SYSCONFDIR=`eval echo $sysconfdir`
|
||||
SYSCONFDIR=`eval echo $SYSCONFDIR`
|
||||
AC_SUBST(SYSCONFDIR)
|
||||
|
||||
AC_OUTPUT
|
||||
|
||||
cat <<EOF
|
||||
|
||||
------------------ Summary ------------------
|
||||
$PACKAGE_NAME version $PACKAGE_VERSION
|
||||
Prefix................: $prefix
|
||||
Exec prefix...........: $eprefix
|
||||
Sysconfdir............: `eval echo $sysconfdir`
|
||||
Localstatedir.........: `eval echo $localstatedir`
|
||||
Default fstab.........: `eval echo $fstab`
|
||||
System environment....: ${sysconfig_path:-${sysconfig}}
|
||||
C Compiler............: $CC $CFLAGS $CPPFLAGS $LDFLAGS $LIBS
|
||||
Linker................: $LD $LLDP_LDFLAGS $LLDP_BIN_LDFLAGS $LDFLAGS $LIBS
|
||||
CFLAGS................: $libite_CFLAGS $sysrepo_CFLAGS
|
||||
LIBS..................: $libite_LIBS $sysrepo_LIBS
|
||||
|
||||
------------- Compiler version --------------
|
||||
$($CC --version || true)
|
||||
-------------- Linker version ---------------
|
||||
$($LD --version || true)
|
||||
---------------------------------------------
|
||||
|
||||
Check the above options and compile with:
|
||||
${MAKE-make}
|
||||
|
||||
EOF
|
||||
@@ -0,0 +1,357 @@
|
||||
/* SPDX-License-Identifier: ISC */
|
||||
#include "config.h"
|
||||
|
||||
#include <getopt.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <sysrepo.h>
|
||||
#include <sysrepo/netconf_acm.h>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
struct infix_ds {
|
||||
char *name; /* startup-config, etc. */
|
||||
char *sysrepocfg; /* ds name in sysrepocfg */
|
||||
int datastore; /* sr_datastore_t and -1 */
|
||||
int rw; /* read-write:1 or not:0 */
|
||||
char *path; /* local path or NULL */
|
||||
};
|
||||
|
||||
struct infix_ds infix_config[] = {
|
||||
{ "startup-config", "startup", SR_DS_STARTUP, 1, "/cfg/startup-config.cfg" },
|
||||
{ "running-config", "running", SR_DS_RUNNING, 1, NULL },
|
||||
{ "candidate-config", "candidate", SR_DS_CANDIDATE, 1, NULL },
|
||||
{ "operational-config", "operational", SR_DS_OPERATIONAL, 1, NULL },
|
||||
{ "factory-config", "factory-default", SR_DS_FACTORY_DEFAULT, 0, NULL }
|
||||
};
|
||||
|
||||
static const char *prognm = "copy";
|
||||
static int timeout;
|
||||
|
||||
|
||||
/*
|
||||
* Print sysrepo session errors followed by an optional string.
|
||||
*/
|
||||
static void emsg(sr_session_ctx_t *sess, const char *fmt, ...)
|
||||
{
|
||||
const sr_error_info_t *err = NULL;
|
||||
va_list ap;
|
||||
size_t i;
|
||||
int rc;
|
||||
|
||||
if (!sess)
|
||||
goto end;
|
||||
|
||||
rc = sr_session_get_error(sess, &err);
|
||||
if ((rc != SR_ERR_OK) || !err)
|
||||
goto end;
|
||||
|
||||
// Show the first error only. Because probably next errors are
|
||||
// originated from internal sysrepo code but is not from subscribers.
|
||||
// for (i = 0; i < err->err_count; i++)
|
||||
for (i = 0; i < (err->err_count < 1 ? err->err_count : 1); i++)
|
||||
fprintf(stderr, ERRMSG "%s\n", err->err[i].message);
|
||||
end:
|
||||
if (fmt) {
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
|
||||
static char *getuser(void)
|
||||
{
|
||||
const struct passwd *pw;
|
||||
uid_t uid;
|
||||
|
||||
uid = getuid();
|
||||
pw = getpwuid(uid);
|
||||
if (!pw) {
|
||||
perror("getpwuid");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return pw->pw_name;
|
||||
}
|
||||
|
||||
static void set_owner(const char *fn, const char *user)
|
||||
{
|
||||
struct passwd *pw;
|
||||
|
||||
pw = getpwnam(user);
|
||||
if (!pw) {
|
||||
fprintf(stderr, ERRMSG "setting owner %s on %s: %s\n", fn, user, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
chmod(fn, 0660);
|
||||
chown(fn, pw->pw_uid, pw->pw_gid);
|
||||
}
|
||||
|
||||
static const char *infix_ds(const char *text, struct infix_ds **ds)
|
||||
{
|
||||
size_t i, len = strlen(text);
|
||||
|
||||
for (i = 0; i < NELEMS(infix_config); i++) {
|
||||
if (!strncmp(infix_config[i].name, text, len)) {
|
||||
*ds = &infix_config[i];
|
||||
return infix_config[i].name;
|
||||
}
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
|
||||
static int copy(const char *src, const char *dst, const char *user)
|
||||
{
|
||||
struct infix_ds *srcds = NULL, *dstds = NULL;
|
||||
char temp_file[20] = "/tmp/copy.XXXXXX";
|
||||
const char *tmpfn = NULL;
|
||||
sr_session_ctx_t *sess;
|
||||
const char *fn = NULL;
|
||||
const char *username;
|
||||
sr_conn_ctx_t *conn;
|
||||
char adjust[256];
|
||||
mode_t oldmask;
|
||||
int rc = 0;
|
||||
|
||||
oldmask = umask(0660);
|
||||
|
||||
src = infix_ds(src, &srcds);
|
||||
if (!src)
|
||||
goto err;
|
||||
dst = infix_ds(dst, &dstds);
|
||||
if (!dst)
|
||||
goto err;
|
||||
|
||||
if (!strcmp(src, dst)) {
|
||||
fprintf(stderr, ERRMSG "source and destination are the same, aborting.");
|
||||
goto err;
|
||||
}
|
||||
|
||||
username = getuser();
|
||||
|
||||
/* 1. Regular ds copy */
|
||||
if (srcds && dstds) {
|
||||
/* Ensure the dst ds is writable */
|
||||
if (!dstds->rw) {
|
||||
fprintf(stderr, ERRMSG "not possible to write to \"%s\", skipping.\n", dst);
|
||||
rc = 1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (sr_connect(SR_CONN_DEFAULT, &conn)) {
|
||||
fprintf(stderr, ERRMSG "connection to datastore failed\n");
|
||||
rc = 1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
sr_log_syslog("klishd", SR_LL_WRN);
|
||||
|
||||
if (sr_session_start(conn, dstds->datastore, &sess)) {
|
||||
fprintf(stderr, ERRMSG "unable to open transaction to %s\n", dst);
|
||||
} else {
|
||||
sr_nacm_set_user(sess, username);
|
||||
rc = sr_copy_config(sess, NULL, srcds->datastore, timeout * 1000);
|
||||
if (rc)
|
||||
emsg(sess, ERRMSG "unable to copy configuration, err %d: %s\n",
|
||||
rc, sr_strerror(rc));
|
||||
else
|
||||
set_owner(dstds->path, username);
|
||||
}
|
||||
rc = sr_disconnect(conn);
|
||||
|
||||
if (!srcds->path || !dstds->path)
|
||||
goto err; /* done, not an error */
|
||||
|
||||
/* allow copy factory startup */
|
||||
}
|
||||
|
||||
if (srcds) {
|
||||
/* 2. Export from a datastore somewhere else */
|
||||
if (strstr(dst, "://")) {
|
||||
if (srcds->path)
|
||||
fn = srcds->path;
|
||||
else {
|
||||
snprintf(adjust, sizeof(adjust), "/tmp/%s.cfg", srcds->name);
|
||||
fn = tmpfn = adjust;
|
||||
rc = systemf("sysrepocfg -d %s -X%s -f json", srcds->sysrepocfg, fn);
|
||||
}
|
||||
|
||||
if (rc)
|
||||
fprintf(stderr, ERRMSG "failed exporting %s to %s\n", src, fn);
|
||||
else {
|
||||
rc = systemf("curl %s -LT %s %s", user, fn, dst);
|
||||
if (rc)
|
||||
fprintf(stderr, ERRMSG "failed uploading %s to %s\n", src, dst);
|
||||
else
|
||||
set_owner(dst, username);
|
||||
}
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (dstds && dstds->path)
|
||||
fn = dstds->path;
|
||||
else
|
||||
fn = cfg_adjust(dst, src, adjust, sizeof(adjust));
|
||||
|
||||
if (!fn) {
|
||||
fprintf(stderr, ERRMSG "invalid destination path.\n");
|
||||
rc = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!access(fn, F_OK) && !yorn("Overwrite existing file %s", fn)) {
|
||||
fprintf(stderr, "OK, aborting.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (srcds->path)
|
||||
rc = systemf("cp %s %s", srcds->path, fn);
|
||||
else
|
||||
rc = systemf("sysrepocfg -d %s -X%s -f json", srcds->sysrepocfg, fn);
|
||||
if (rc)
|
||||
fprintf(stderr, ERRMSG "failed copy %s to %s\n", src, fn);
|
||||
else
|
||||
set_owner(fn, username);
|
||||
} else if (dstds) {
|
||||
if (!dstds->sysrepocfg) {
|
||||
fprintf(stderr, ERRMSG "not possible to import to this datastore.\n");
|
||||
rc = 1;
|
||||
goto err;
|
||||
}
|
||||
if (!dstds->rw) {
|
||||
fprintf(stderr, ERRMSG "not possible to write to %s", dst);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* 3. Import from somewhere to a datastore */
|
||||
if (strstr(src, "://")) {
|
||||
tmpfn = mktemp(temp_file);
|
||||
fn = tmpfn;
|
||||
} else {
|
||||
fn = cfg_adjust(src, NULL, adjust, sizeof(adjust));
|
||||
if (!fn) {
|
||||
fprintf(stderr, ERRMSG "invalid source file location.\n");
|
||||
rc = 1;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (tmpfn)
|
||||
rc = systemf("curl %s -Lo %s %s", user, fn, src);
|
||||
if (rc) {
|
||||
fprintf(stderr, ERRMSG "failed downloading %s", src);
|
||||
} else {
|
||||
rc = systemf("sysrepocfg -d %s -I%s -f json", dstds->sysrepocfg, fn);
|
||||
if (rc)
|
||||
fprintf(stderr, ERRMSG "failed loading %s from %s", dst, src);
|
||||
}
|
||||
} else {
|
||||
if (strstr(src, "://") && strstr(dst, "://")) {
|
||||
fprintf(stderr, ERRMSG "copy from remote to remote is not supported.\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (strstr(src, "://")) {
|
||||
fn = cfg_adjust(dst, src, adjust, sizeof(adjust));
|
||||
if (!fn) {
|
||||
fprintf(stderr, ERRMSG "invalid destination file location.\n");
|
||||
rc = 1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!access(fn, F_OK)) {
|
||||
if (!yorn("Overwrite existing file %s", fn)) {
|
||||
fprintf(stderr, "OK, aborting.\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
rc = systemf("curl %s -Lo %s %s", user, fn, src);
|
||||
} else if (strstr(dst, "://")) {
|
||||
fn = cfg_adjust(src, NULL, adjust, sizeof(adjust));
|
||||
if (!fn) {
|
||||
fprintf(stderr, ERRMSG "invalid source file location.\n");
|
||||
rc = 1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (access(fn, F_OK))
|
||||
fprintf(stderr, ERRMSG "no such file %s, aborting.", fn);
|
||||
else
|
||||
rc = systemf("curl %s -LT %s %s", user, fn, dst);
|
||||
} else {
|
||||
if (!access(dst, F_OK)) {
|
||||
if (!yorn("Overwrite existing file %s", dst)) {
|
||||
fprintf(stderr, "OK, aborting.\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
rc = systemf("cp %s %s", src, dst);
|
||||
}
|
||||
}
|
||||
|
||||
err:
|
||||
if (tmpfn)
|
||||
rc = remove(tmpfn);
|
||||
|
||||
sync(); /* ensure command is flushed to disk */
|
||||
umask(oldmask);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int usage(int rc)
|
||||
{
|
||||
printf("Usage: %s [OPTIONS] SRC DST\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" -h This help text\n"
|
||||
" -u USER Username for remote commands, like scp\n"
|
||||
" -t SEEC Timeout for the operation, or default %d sec\n"
|
||||
" -v Show version\n", prognm, timeout);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
const char *user = NULL, *src = NULL, *dst = NULL;
|
||||
int c;
|
||||
|
||||
timeout = fgetint("/etc/default/confd", "=", "CONFD_TIMEOUT");
|
||||
|
||||
while ((c = getopt(argc, argv, "ht:u:v")) != EOF) {
|
||||
switch(c) {
|
||||
case 'h':
|
||||
return usage(0);
|
||||
case 't':
|
||||
timeout = atoi(optarg);
|
||||
break;
|
||||
case 'u':
|
||||
user = optarg;
|
||||
break;
|
||||
case 'v':
|
||||
puts(PACKAGE_VERSION);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (timeout < 0)
|
||||
timeout = 120;
|
||||
|
||||
if (optind >= argc)
|
||||
return usage(1);
|
||||
|
||||
src = argv[optind++];
|
||||
dst = argv[optind++];
|
||||
|
||||
return copy(src, dst, user);
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/* SPDX-License-Identifier: ISC */
|
||||
#include "config.h"
|
||||
|
||||
#include <alloca.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
static const char *prognm = "erase";
|
||||
|
||||
|
||||
static int do_erase(const char *path)
|
||||
{
|
||||
char *fn;
|
||||
|
||||
if (access(path, F_OK)) {
|
||||
size_t len = strlen(path) + 10;
|
||||
|
||||
fn = alloca(len);
|
||||
if (!fn) {
|
||||
fprintf(stderr, ERRMSG "failed allocating memory.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cfg_adjust(path, NULL, fn, len);
|
||||
if (access(fn, F_OK)) {
|
||||
fprintf(stderr, "No such file: %s\n", fn);
|
||||
return -1;
|
||||
}
|
||||
} else
|
||||
fn = (char *)path;
|
||||
|
||||
if (!yorn("Remove %s, are you sure", fn))
|
||||
return 0;
|
||||
|
||||
if (remove(fn)) {
|
||||
fprintf(stderr, ERRMSG "failed removing %s: %s\n", fn, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usage(int rc)
|
||||
{
|
||||
printf("Usage: %s [OPTIONS] PATH\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" -h This help text\n"
|
||||
" -v Show version\n", prognm);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int c;
|
||||
|
||||
while ((c = getopt(argc, argv, "hv")) != EOF) {
|
||||
switch(c) {
|
||||
case 'h':
|
||||
return usage(0);
|
||||
case 'v':
|
||||
puts(PACKAGE_VERSION);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (optind >= argc)
|
||||
return usage(1);
|
||||
|
||||
return do_erase(argv[optind++]);
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/* SPDX-License-Identifier: ISC */
|
||||
#include "config.h"
|
||||
|
||||
#include <dirent.h>
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
static const char *prognm = "files";
|
||||
|
||||
|
||||
int files(const char *path, const char *stripext)
|
||||
{
|
||||
const struct dirent *d;
|
||||
DIR *dir;
|
||||
|
||||
dir = opendir(path);
|
||||
if (!dir) {
|
||||
fprintf(stderr, ERRMSG "%s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
while ((d = readdir(dir))) {
|
||||
char name[sizeof(d->d_name) + 1];
|
||||
|
||||
/* only list regular files, skip dirs and dotfiles */
|
||||
if (d->d_type != DT_REG || d->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
strlcpy(name, d->d_name, sizeof(name));
|
||||
if (stripext) {
|
||||
size_t pos = has_ext(name, stripext);
|
||||
|
||||
if (pos)
|
||||
name[pos] = 0;
|
||||
}
|
||||
|
||||
printf("%s\n", name);
|
||||
}
|
||||
|
||||
return closedir(dir);
|
||||
}
|
||||
|
||||
|
||||
static int usage(int rc)
|
||||
{
|
||||
printf("Usage: %s [OPTIONS] PATH [EXT]\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" -h This help text\n"
|
||||
" -v Show version\n", prognm);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
const char *path = NULL, *ext = NULL;
|
||||
int c;
|
||||
|
||||
while ((c = getopt(argc, argv, "hv")) != EOF) {
|
||||
switch(c) {
|
||||
case 'h':
|
||||
return usage(0);
|
||||
case 'v':
|
||||
puts(PACKAGE_VERSION);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (optind >= argc)
|
||||
return usage(1);
|
||||
|
||||
path = argv[optind++];
|
||||
if (optind < argc)
|
||||
ext = argv[optind++];
|
||||
|
||||
return files(path, ext);
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/* SPDX-License-Identifier: ISC */
|
||||
#include "config.h"
|
||||
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
|
||||
static char rawgetch(void)
|
||||
{
|
||||
struct termios saved, c;
|
||||
char key;
|
||||
|
||||
if (tcgetattr(fileno(stdin), &saved) < 0)
|
||||
return -1;
|
||||
|
||||
c = saved;
|
||||
c.c_lflag &= ~ICANON;
|
||||
c.c_lflag &= ~ECHO;
|
||||
c.c_cc[VMIN] = 1;
|
||||
c.c_cc[VTIME] = 0;
|
||||
|
||||
if (tcsetattr(fileno(stdin), TCSANOW, &c) < 0) {
|
||||
tcsetattr(fileno(stdin), TCSANOW, &saved);
|
||||
return -1;
|
||||
}
|
||||
|
||||
key = getchar();
|
||||
tcsetattr(fileno(stdin), TCSANOW, &saved);
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
int yorn(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char ch;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
fprintf(stderr, " (y/N)? ");
|
||||
ch = rawgetch();
|
||||
fprintf(stderr, "%c\n", ch);
|
||||
if (ch != 'y' && ch != 'Y')
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int has_ext(const char *fn, const char *ext)
|
||||
{
|
||||
size_t pos = strlen(fn);
|
||||
size_t len = strlen(ext);
|
||||
|
||||
if (len < pos && !strcmp(&fn[pos - len], ext))
|
||||
return pos - len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *basenm(const char *fn)
|
||||
{
|
||||
const char *ptr;
|
||||
|
||||
if (!fn)
|
||||
return "";
|
||||
|
||||
ptr = strrchr(fn, '/');
|
||||
if (!ptr)
|
||||
ptr = fn;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
char *cfg_adjust(const char *fn, const char *tmpl, char *buf, size_t len)
|
||||
{
|
||||
if (strstr(fn, "../"))
|
||||
return NULL; /* relative paths not allowed */
|
||||
|
||||
if (fn[0] == '/') {
|
||||
strlcpy(buf, fn, len);
|
||||
return buf; /* allow absolute paths */
|
||||
}
|
||||
|
||||
/* Files in /cfg must end in .cfg */
|
||||
if (!strncmp(fn, "/cfg/", 5)) {
|
||||
strlcpy(buf, fn, len);
|
||||
if (!has_ext(fn, ".cfg"))
|
||||
strlcat(buf, ".cfg", len);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* Files ending with .cfg belong in /cfg */
|
||||
if (has_ext(fn, ".cfg")) {
|
||||
snprintf(buf, len, "/cfg/%s", fn);
|
||||
return buf;
|
||||
}
|
||||
|
||||
if (strlen(fn) > 0 && fn[0] == '.' && tmpl) {
|
||||
if (fn[1] == '/' && fn[2] != 0)
|
||||
strlcpy(buf, fn, len);
|
||||
else
|
||||
strlcpy(buf, basenm(tmpl), len);
|
||||
} else
|
||||
strlcpy(buf, fn, len);
|
||||
|
||||
return buf;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/* SPDX-License-Identifier: ISC */
|
||||
#ifndef BIN_UTIL_H_
|
||||
#define BIN_UTIL_H_
|
||||
#include <stdio.h>
|
||||
#include <libite/lite.h>
|
||||
|
||||
#define ERRMSG "Error: "
|
||||
#define INFMSG "Note: "
|
||||
|
||||
int yorn (const char *fmt, ...);
|
||||
|
||||
int files (const char *path, const char *stripext);
|
||||
|
||||
int has_ext (const char *fn, const char *ext);
|
||||
char *cfg_adjust (const char *fn, const char *tmpl, char *buf, size_t len);
|
||||
|
||||
#endif /* BIN_UTIL_H_ */
|
||||
@@ -1,3 +1,3 @@
|
||||
pkglibexec_SCRIPTS = bootstrap error load gen-service gen-hostname \
|
||||
gen-interfaces gen-motd gen-hardware gen-version
|
||||
sbin_SCRIPTS = dagger
|
||||
sbin_SCRIPTS = dagger migrate
|
||||
|
||||
@@ -22,6 +22,17 @@
|
||||
########################################################################
|
||||
STATUS=""
|
||||
|
||||
# Log functions
|
||||
critical()
|
||||
{
|
||||
logger -i -p user.crit -t bootstrap "$1" 2>/dev/null || echo "$1"
|
||||
}
|
||||
|
||||
err()
|
||||
{
|
||||
logger -i -p user.err -t bootstrap "$1" 2>/dev/null || echo "$1"
|
||||
}
|
||||
|
||||
# When logging errors, generating /etc/issue* or /etc/banner (SSH)
|
||||
. /etc/os-release
|
||||
|
||||
@@ -33,8 +44,7 @@ if [ "$1" = "-f" ] && [ -f "$2" ]; then
|
||||
fi
|
||||
|
||||
if [ ! -f "$RC" ]; then
|
||||
logger -sik -p user.error -t bootstrap "Missing rc file $RC" 2>/dev/null \
|
||||
|| echo "Missing rc file $RC"
|
||||
err "Missing rc file $RC"
|
||||
exit 99
|
||||
fi
|
||||
|
||||
@@ -72,7 +82,7 @@ collate()
|
||||
# Report error on console, syslog, and set login banners for getty + ssh
|
||||
console_error()
|
||||
{
|
||||
logger -p user.crit -t bootstrap "$1"
|
||||
critical "$1"
|
||||
|
||||
# shellcheck disable=SC3037
|
||||
/bin/echo -e "\n\n\e[31mCRITICAL BOOTSTRAP ERROR\n$1\e[0m\n" > /dev/console
|
||||
@@ -157,11 +167,20 @@ else
|
||||
fi
|
||||
rc=$?
|
||||
|
||||
# Ensure 'admin' group users always have access
|
||||
chgrp wheel "$CFG_PATH_"
|
||||
chmod g+w "$CFG_PATH_"
|
||||
|
||||
# Ensure factory-config has correct syntax
|
||||
if ! migrate -cq "$INIT_DATA"; then
|
||||
if migrate -iq -b "${INIT_DATA%.*}.bak" "$INIT_DATA"; then
|
||||
err "${INIT_DATA}: found and fixed old syntax!"
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! sysrepoctl -z "$INIT_DATA"; then
|
||||
rc=$?
|
||||
logger -sik -p user.error "Failed loading factory-default datastore"
|
||||
err "Failed loading factory-default datastore"
|
||||
else
|
||||
# Clear running-config so we can load/create startup in the next step
|
||||
temp=$(mktemp)
|
||||
|
||||
@@ -0,0 +1,235 @@
|
||||
#!/bin/sh
|
||||
# Run .cfg migration jq scripts to backup and transform older syntax.
|
||||
scripts="/usr/share/confd/migrate"
|
||||
ident=$(basename "$0")
|
||||
|
||||
usage()
|
||||
{
|
||||
echo "usage: $0 [-chiq] [-b /path/backup/file.ext] [/path/to/config.cfg]"
|
||||
echo
|
||||
echo "options:"
|
||||
echo " -b FILE Create backup FILE, appends detected version before .ext"
|
||||
echo " -c Check only, returns false when migration is not needed"
|
||||
echo " -h This help text"
|
||||
echo " -i Edit file in-place instead of sending to stdout, like sed"
|
||||
echo " -q Quiet, skip normal log messages, only errors are logged"
|
||||
echo
|
||||
echo "By default, this script reads a .cfg file on stdin, or as the first"
|
||||
echo "non-option argument, then migrates it to a new syntax on stdout."
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2317
|
||||
cleanup()
|
||||
{
|
||||
rm -f "$tmp"
|
||||
}
|
||||
|
||||
note()
|
||||
{
|
||||
if [ -n "$quiet" ]; then
|
||||
return
|
||||
fi
|
||||
logger -I $$ -k -p user.notice -t "$ident" "$1"
|
||||
}
|
||||
|
||||
err()
|
||||
{
|
||||
logger -I $$ -k -p user.err -t "$ident" "$1"
|
||||
}
|
||||
|
||||
# Convert human-readable version to integer level
|
||||
atoi()
|
||||
{
|
||||
echo "$1" | awk -F. '{print $1 * 1000 + $2}'
|
||||
}
|
||||
|
||||
file_version()
|
||||
{
|
||||
jq -r '
|
||||
if .["infix-meta:meta"] | has("infix-meta:version") then
|
||||
.["infix-meta:meta"]["infix-meta:version"]
|
||||
else
|
||||
"0.0"
|
||||
end
|
||||
' "$1"
|
||||
}
|
||||
|
||||
# Find the latest version by examining the highest numbered directory
|
||||
confd_version()
|
||||
{
|
||||
find "$scripts" -mindepth 1 -maxdepth 1 -type d \
|
||||
| sort -V | tail -n1 | xargs -n1 basename
|
||||
}
|
||||
|
||||
# Update meta data with the latest version
|
||||
meta_version()
|
||||
{
|
||||
if jq --arg version "$sys_version" '.["infix-meta:meta"] = {"infix-meta:version": $version}' "$2" \
|
||||
> "${2}.tmp" && mv "${2}.tmp" "$2"; then
|
||||
note "$1: configuration updated to version $sys_version."
|
||||
return 0
|
||||
fi
|
||||
|
||||
err "$1: failed updating configuration to version $sys_version!"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Apply the scripts for each version directory in sequence
|
||||
migrate()
|
||||
{
|
||||
note "$1: migrating from version $cfg_version"
|
||||
|
||||
for version_dir in $(find "$scripts" -mindepth 1 -maxdepth 1 -type d | sort -V); do
|
||||
dir=$(basename "$version_dir")
|
||||
version=$(atoi "$dir")
|
||||
|
||||
# Step by step upgrade file to latest version
|
||||
if [ "$cfg_level" -lt "$version" ]; then
|
||||
note "Applying migrations for version $dir ..."
|
||||
|
||||
# Apply all scripts in the version directory in order
|
||||
for script in $(find "$version_dir" -type f -name '*.sh' | sort -V); do
|
||||
note "$1: calling $script ..."
|
||||
sh "$script" "$2"
|
||||
done
|
||||
|
||||
# File now at $version ...
|
||||
cfg_level="$version"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Try migrating a copy, then diff the files, for factory-config check
|
||||
diff()
|
||||
{
|
||||
CFG=$1
|
||||
TMP=$(mktemp)
|
||||
|
||||
cp -p "$CFG" "$TMP"
|
||||
quiet=1
|
||||
migrate "(diff)" "$TMP"
|
||||
cmp -s "$CFG" "$TMP"
|
||||
rc=$?
|
||||
rm -f "$TMP"
|
||||
|
||||
return $rc
|
||||
}
|
||||
|
||||
|
||||
tmp=$(mktemp)
|
||||
chmod 600 "$tmp"
|
||||
|
||||
trap cleanup INT HUP TERM EXIT
|
||||
|
||||
OPTS=$(getopt -o b:chiq -- "$@")
|
||||
eval set -- "$OPTS"
|
||||
|
||||
while [ -n "$1" ]; do
|
||||
case $1 in
|
||||
-b)
|
||||
bak=$2
|
||||
shift
|
||||
;;
|
||||
-c)
|
||||
check=1
|
||||
;;
|
||||
-h)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
-i)
|
||||
inplace=1
|
||||
;;
|
||||
-q)
|
||||
quiet=1
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
*)
|
||||
# Likely file argument
|
||||
break
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [ -n "$1" ] && [ -f "$1" ]; then
|
||||
# Copy to tempfile to allow user to > same file
|
||||
orig="$1"
|
||||
cp -p "$1" "$tmp"
|
||||
shift
|
||||
elif [ -t 0 ]; then
|
||||
orig="(stdin)"
|
||||
cat > "$tmp"
|
||||
else
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! jq empty "$tmp" 2>/dev/null; then
|
||||
err "$tmp invalid JSON format!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cfg_version=$(file_version "$tmp")
|
||||
sys_version=$(confd_version)
|
||||
|
||||
cfg_level=$(atoi "$cfg_version")
|
||||
sys_level=$(atoi "$sys_version")
|
||||
|
||||
# Check for downgrade
|
||||
if [ "$cfg_level" -gt "$sys_level" ]; then
|
||||
err "$orig: version is newer ($cfg_version) than supported ($sys_version). Exiting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# If the current version is already the latest, exit the script
|
||||
if [ "$cfg_level" -eq "$sys_level" ]; then
|
||||
exit 0
|
||||
else
|
||||
if [ -n "$check" ]; then
|
||||
# We may be called to check a file without meta:version (factory)
|
||||
if [ "$cfg_version" = "0.0" ]; then
|
||||
if diff "$tmp"; then
|
||||
# File is OK, despite lacking meta:version
|
||||
exit 0
|
||||
fi
|
||||
msg="$orig: has syntax error, requires migrating."
|
||||
else
|
||||
msg="$orig: version $cfg_version, requires migrating."
|
||||
fi
|
||||
if [ -t 0 ]; then
|
||||
echo "$msg"
|
||||
else
|
||||
note "$msg"
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$bak" ]; then
|
||||
fil="${bak%.*}"
|
||||
ext="${bak##*.}"
|
||||
bak="${fil}-${cfg_version}.${ext}"
|
||||
if cp -p "$tmp" "$bak" 2>/dev/null; then
|
||||
note "$orig: backup created: $bak"
|
||||
else
|
||||
err "$orig: failed creating backup: $bak"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! migrate "$orig" "$tmp"; then
|
||||
exit 1
|
||||
fi
|
||||
meta_version "$orig" "$tmp"
|
||||
|
||||
if [ -n "$inplace" ] && [ "$orig" != "(stdin)" ]; then
|
||||
cp -p "$tmp" "$orig"
|
||||
else
|
||||
cat "$tmp"
|
||||
fi
|
||||
|
||||
exit 0
|
||||
@@ -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.1], [https://github.com/kernelkit/infix/issues])
|
||||
AC_INIT([confd], [1.2], [https://github.com/kernelkit/infix/issues])
|
||||
AM_INIT_AUTOMAKE(1.11 foreign subdir-objects)
|
||||
AM_SILENT_RULES(yes)
|
||||
|
||||
@@ -15,6 +15,7 @@ AC_CONFIG_FILES([
|
||||
share/migrate/Makefile
|
||||
share/migrate/1.0/Makefile
|
||||
share/migrate/1.1/Makefile
|
||||
share/migrate/1.2/Makefile
|
||||
src/Makefile
|
||||
yang/Makefile
|
||||
])
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"ietf-netconf-acm:nacm": {
|
||||
"enable-nacm": true,
|
||||
"groups": {
|
||||
"group": [
|
||||
{
|
||||
@@ -25,6 +26,19 @@
|
||||
"comment": "Allow 'admin' group complete access to all operations and data."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "default-deny-all",
|
||||
"group": ["*"],
|
||||
"rule": [
|
||||
{
|
||||
"name": "deny-password-read",
|
||||
"module-name": "ietf-system",
|
||||
"path": "/ietf-system:system/authentication/user/password",
|
||||
"access-operations": "*",
|
||||
"action": "deny"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#!/bin/sh
|
||||
# Migrate phys-address -> custom-phys-address with static option
|
||||
|
||||
file=$1
|
||||
temp=${file}.tmp
|
||||
|
||||
jq '(
|
||||
.["ietf-interfaces:interfaces"].interface[] |=
|
||||
if has("phys-address") then
|
||||
.["infix-interfaces:custom-phys-address"] = { "static": .["phys-address"] } | del(.["phys-address"])
|
||||
else
|
||||
.
|
||||
end
|
||||
)' "$file" > "$temp" &&
|
||||
mv "$temp" "$file"
|
||||
@@ -0,0 +1,2 @@
|
||||
migratedir = $(pkgdatadir)/migrate/1.2
|
||||
dist_migrate_DATA = 10-ietf-interfaces-phys-address.sh
|
||||
@@ -1,2 +1,2 @@
|
||||
SUBDIRS = 1.0 1.1
|
||||
SUBDIRS = 1.0 1.1 1.2
|
||||
migratedir = $(pkgdatadir)/migrate
|
||||
|
||||
@@ -172,7 +172,8 @@ int ietf_interfaces_init(struct confd *confd);
|
||||
int ietf_syslog_init(struct confd *confd);
|
||||
|
||||
/* ietf-system.c */
|
||||
int ietf_system_init(struct confd *confd);
|
||||
int ietf_system_init (struct confd *confd);
|
||||
int hostnamefmt (struct confd *confd, const char *fmt, char *buf, size_t len);
|
||||
|
||||
/* infix-containers.c */
|
||||
#ifdef CONTAINERS
|
||||
|
||||
@@ -227,6 +227,8 @@ static int ifchange_cand_infer_type(sr_session_ctx_t *session, const char *path)
|
||||
inferred.data.string_val = "infix-if-type:bridge";
|
||||
else if (!fnmatch("docker+([0-9])", ifname, FNM_EXTMATCH))
|
||||
inferred.data.string_val = "infix-if-type:bridge";
|
||||
else if (!fnmatch("dummy+([0-9])", ifname, FNM_EXTMATCH))
|
||||
inferred.data.string_val = "infix-if-type:dummy";
|
||||
else if (!fnmatch("podman+([0-9])", ifname, FNM_EXTMATCH))
|
||||
inferred.data.string_val = "infix-if-type:bridge";
|
||||
else if (!fnmatch("lag+([0-9])", ifname, FNM_EXTMATCH))
|
||||
@@ -431,15 +433,110 @@ static int netdag_gen_link_mtu(FILE *ip, struct lyd_node *dif)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void calc_mac(const char *base_mac, const char *mac_offset, char *buf, size_t len)
|
||||
{
|
||||
uint8_t base[6], offset[6], result[6];
|
||||
int carry = 0, i;
|
||||
|
||||
sscanf(base_mac, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
|
||||
&base[0], &base[1], &base[2], &base[3], &base[4], &base[5]);
|
||||
|
||||
sscanf(mac_offset, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
|
||||
&offset[0], &offset[1], &offset[2], &offset[3], &offset[4], &offset[5]);
|
||||
|
||||
for (i = 5; i >= 0; i--) {
|
||||
int sum = base[i] + offset[i] + carry;
|
||||
|
||||
result[i] = sum & 0xFF;
|
||||
carry = (sum > 0xFF) ? 1 : 0;
|
||||
}
|
||||
|
||||
snprintf(buf, len, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
result[0], result[1], result[2], result[3], result[4], result[5]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get child value from a diff parent, only returns value if not
|
||||
* deleted. In which case the deleted flag may be set.
|
||||
*/
|
||||
static const char *get_val(struct lyd_node *parent, char *name, int *deleted)
|
||||
{
|
||||
const char *value = NULL;
|
||||
struct lyd_node *node;
|
||||
|
||||
node = lydx_get_child(parent, name);
|
||||
if (node) {
|
||||
if (lydx_get_op(node) == LYDX_OP_DELETE) {
|
||||
if (deleted)
|
||||
*deleted = 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
value = lyd_get_value(node);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Locate custom-phys-address, adjust for any offset, and return pointer
|
||||
* to a static string. (Which will be overwritten on subsequent calls.)
|
||||
*
|
||||
* The 'deleted' flag will be set if any of the nodes in the subtree are
|
||||
* deleted. Used when restoring permaddr and similar.
|
||||
*/
|
||||
static char *get_phys_addr(struct lyd_node *parent, int *deleted)
|
||||
{
|
||||
struct lyd_node *node, *cpa;
|
||||
static char mac[18];
|
||||
struct json_t *j;
|
||||
const char *ptr;
|
||||
|
||||
cpa = lydx_get_descendant(lyd_child(parent), "custom-phys-address", NULL);
|
||||
if (!cpa || lydx_get_op(cpa) == LYDX_OP_DELETE) {
|
||||
if (cpa && deleted)
|
||||
*deleted = 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ptr = get_val(cpa, "static", deleted);
|
||||
if (ptr) {
|
||||
strlcpy(mac, ptr, sizeof(mac));
|
||||
return mac;
|
||||
}
|
||||
|
||||
node = lydx_get_child(cpa, "chassis");
|
||||
if (!node || lydx_get_op(node) == LYDX_OP_DELETE) {
|
||||
if (node && deleted)
|
||||
*deleted = 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
j = json_object_get(confd.root, "mac-address");
|
||||
if (!j) {
|
||||
WARN("cannot set chassis based MAC, not found.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ptr = json_string_value(j);
|
||||
strlcpy(mac, ptr, sizeof(mac));
|
||||
|
||||
ptr = get_val(node, "offset", deleted);
|
||||
if (ptr)
|
||||
calc_mac(mac, ptr, mac, sizeof(mac));
|
||||
|
||||
return mac;
|
||||
}
|
||||
|
||||
static int netdag_gen_link_addr(FILE *ip, struct lyd_node *cif, struct lyd_node *dif)
|
||||
{
|
||||
const char *ifname = lydx_get_cattr(dif, "name");
|
||||
const char *mac = NULL;
|
||||
struct lyd_node *node;
|
||||
const char *mac;
|
||||
int deleted = 0;
|
||||
char buf[32];
|
||||
|
||||
node = lydx_get_child(dif, "phys-address");
|
||||
if (lydx_get_op(node) == LYDX_OP_DELETE) {
|
||||
mac = get_phys_addr(dif, &deleted);
|
||||
if (!mac && deleted) {
|
||||
FILE *fp;
|
||||
|
||||
/*
|
||||
@@ -455,8 +552,6 @@ static int netdag_gen_link_addr(FILE *ip, struct lyd_node *cif, struct lyd_node
|
||||
if (mac && !strcmp(mac, "null"))
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
mac = lyd_get_value(node);
|
||||
}
|
||||
|
||||
if (!mac || !strlen(mac)) {
|
||||
@@ -890,42 +985,53 @@ done:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int bridge_diff_vlan_port(struct dagger *net, FILE *br, const char *brname, int vid,
|
||||
const char *brport, int tagged, enum lydx_op op)
|
||||
static void bridge_remove_vlan_ports(struct dagger *net, FILE *br, const char *brname,
|
||||
int vid, struct lyd_node *ports, int tagged)
|
||||
{
|
||||
int pvid = 0;
|
||||
struct lyd_node *port;
|
||||
|
||||
srx_get_int(net->session, &pvid, SR_UINT16_T, IF_XPATH "[name='%s']/bridge-port/pvid", brport);
|
||||
LYX_LIST_FOR_EACH(lyd_child(ports), port, tagged ? "tagged" : "untagged") {
|
||||
enum lydx_op op = lydx_get_op(port);
|
||||
const char *brport = lyd_get_value(port);
|
||||
|
||||
if (op != LYDX_OP_CREATE) {
|
||||
fprintf(br, "vlan del vid %d dev %s\n", vid, brport);
|
||||
}
|
||||
|
||||
if (op != LYDX_OP_CREATE) {
|
||||
fprintf(br, "vlan del vid %d dev %s\n", vid, brport);
|
||||
if (op == LYDX_OP_DELETE)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(br, "vlan add vid %d dev %s %s %s %s\n", vid, brport, vid == pvid ? "pvid" : "",
|
||||
tagged ? "" : "untagged", strcmp(brname, brport) ? "" : "self");
|
||||
static void bridge_add_vlan_ports(struct dagger *net, FILE *br, const char *brname,
|
||||
int vid, struct lyd_node *ports, int tagged)
|
||||
{
|
||||
struct lyd_node *port;
|
||||
|
||||
return 0;
|
||||
LYX_LIST_FOR_EACH(lyd_child(ports), port, tagged ? "tagged" : "untagged") {
|
||||
enum lydx_op op = lydx_get_op(port);
|
||||
const char *brport = lyd_get_value(port);
|
||||
|
||||
if (op != LYDX_OP_DELETE) {
|
||||
int pvid = 0;
|
||||
srx_get_int(net->session, &pvid, SR_UINT16_T, IF_XPATH "[name='%s']/bridge-port/pvid", brport);
|
||||
|
||||
fprintf(br, "vlan add vid %d dev %s %s %s %s\n", vid, brport, vid == pvid ? "pvid" : "",
|
||||
tagged ? "" : "untagged", strcmp(brname, brport) ? "" : "self");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int bridge_diff_vlan_ports(struct dagger *net, FILE *br, const char *brname,
|
||||
int vid, struct lyd_node *ports, int tagged)
|
||||
int vid, struct lyd_node *ports)
|
||||
{
|
||||
const char *type = tagged ? "tagged" : "untagged";
|
||||
struct lyd_node *port;
|
||||
int err = 0;
|
||||
/* First remove all VLANs that should that should be removed, see #676 */
|
||||
bridge_remove_vlan_ports(net, br, brname, vid, ports, 0);
|
||||
bridge_remove_vlan_ports(net, br, brname, vid, ports, 1);
|
||||
|
||||
LYX_LIST_FOR_EACH(lyd_child(ports), port, type) {
|
||||
const char *brport = lyd_get_value(port);
|
||||
enum lydx_op op = lydx_get_op(port);
|
||||
bridge_add_vlan_ports(net, br, brname, vid, ports, 0);
|
||||
bridge_add_vlan_ports(net, br, brname, vid, ports, 1);
|
||||
|
||||
err = bridge_diff_vlan_port(net, br, brname, vid, brport, tagged, op);
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *bridge_tagtype2str(const char *type)
|
||||
@@ -1333,9 +1439,8 @@ static int netdag_gen_bridge(sr_session_ctx_t *session, struct dagger *net, stru
|
||||
* addrgenmode eui64 with random mac, issue #357.
|
||||
*/
|
||||
if (add) {
|
||||
const char *mac;
|
||||
const char *mac = get_phys_addr(cif, NULL);
|
||||
|
||||
mac = lydx_get_cattr(cif, "phys-address");
|
||||
if (!mac) {
|
||||
struct json_t *j;
|
||||
|
||||
@@ -1390,13 +1495,7 @@ static int netdag_gen_bridge(sr_session_ctx_t *session, struct dagger *net, stru
|
||||
LYX_LIST_FOR_EACH(lyd_child(vlans), vlan, "vlan") {
|
||||
int vid = atoi(lydx_get_cattr(vlan, "vid"));
|
||||
|
||||
/* untagged ports */
|
||||
err = bridge_diff_vlan_ports(net, br, brname, vid, vlan, 0);
|
||||
if (err)
|
||||
break;
|
||||
|
||||
/* tagged ports */
|
||||
err = bridge_diff_vlan_ports(net, br, brname, vid, vlan, 1);
|
||||
err = bridge_diff_vlan_ports(net, br, brname, vid, vlan);
|
||||
if (err)
|
||||
break;
|
||||
|
||||
@@ -1425,6 +1524,16 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int netdag_gen_dummy(struct dagger *net, struct lyd_node *dif,
|
||||
struct lyd_node *cif, FILE *ip)
|
||||
{
|
||||
const char *ifname = lydx_get_cattr(cif, "name");
|
||||
|
||||
fprintf(ip, "link add dev %s type dummy\n", ifname);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int netdag_gen_veth(struct dagger *net, struct lyd_node *dif,
|
||||
struct lyd_node *cif, FILE *ip)
|
||||
{
|
||||
@@ -1444,16 +1553,17 @@ static int netdag_gen_veth(struct dagger *net, struct lyd_node *dif,
|
||||
return ERR_IFACE(cif, err, "Unable to add dep \"%s\" to %s", peer, ifname);
|
||||
} else {
|
||||
char ifname_args[64] = "", peer_args[64] = "";
|
||||
const char *mac;
|
||||
|
||||
dagger_skip_iface(net, peer);
|
||||
|
||||
node = lydx_get_child(dif, "phys-address");
|
||||
if (node)
|
||||
snprintf(ifname_args, sizeof(ifname_args), "address %s", lyd_get_value(node));
|
||||
mac = get_phys_addr(dif, NULL);
|
||||
if (mac)
|
||||
snprintf(ifname_args, sizeof(ifname_args), "address %s", mac);
|
||||
|
||||
node = lydx_find_by_name(lyd_parent(cif), "interface", peer);
|
||||
if (node && (node = lydx_get_child(node, "phys-address")))
|
||||
snprintf(peer_args, sizeof(peer_args), "address %s", lyd_get_value(node));
|
||||
if (node && (mac = get_phys_addr(node, NULL)))
|
||||
snprintf(peer_args, sizeof(peer_args), "address %s", mac);
|
||||
|
||||
fprintf(ip, "link add dev %s %s type veth peer %s %s\n",
|
||||
ifname, ifname_args, peer, peer_args);
|
||||
@@ -1567,6 +1677,8 @@ static int netdag_gen_afspec_add(sr_session_ctx_t *session, struct dagger *net,
|
||||
|
||||
if (!strcmp(iftype, "infix-if-type:bridge")) {
|
||||
err = netdag_gen_bridge(session, net, dif, cif, ip, 1);
|
||||
} else if (!strcmp(iftype, "infix-if-type:dummy")) {
|
||||
err = netdag_gen_dummy(net, NULL, cif, ip);
|
||||
} else if (!strcmp(iftype, "infix-if-type:veth")) {
|
||||
err = netdag_gen_veth(net, NULL, cif, ip);
|
||||
} else if (!strcmp(iftype, "infix-if-type:vlan")) {
|
||||
@@ -1607,10 +1719,9 @@ static int netdag_gen_afspec_set(sr_session_ctx_t *session, struct dagger *net,
|
||||
|
||||
static bool is_phys_addr_deleted(struct lyd_node *dif)
|
||||
{
|
||||
struct lyd_node *node;
|
||||
int deleted = 0;
|
||||
|
||||
node = lydx_get_child(dif, "phys-address");
|
||||
if (node && lydx_get_op(node) == LYDX_OP_DELETE)
|
||||
if (!get_phys_addr(dif, &deleted) && deleted)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
||||
@@ -29,7 +29,7 @@ log facility local2\n"
|
||||
int parse_ospf_interfaces(sr_session_ctx_t *session, struct lyd_node *areas, FILE *fp)
|
||||
{
|
||||
struct lyd_node *interface, *interfaces, *area;
|
||||
int bfd_enabled = 0;
|
||||
int num_bfd_enabled = 0;
|
||||
|
||||
LY_LIST_FOR(lyd_child(areas), area) {
|
||||
const char *area_id;
|
||||
@@ -41,11 +41,13 @@ int parse_ospf_interfaces(sr_session_ctx_t *session, struct lyd_node *areas, FIL
|
||||
const char *hello, *dead, *retransmit, *transmit, *interface_type, *cost;
|
||||
|
||||
if (lydx_get_bool(interface, "enabled")) {
|
||||
int passive = 0, bfd_enabled = 0;
|
||||
struct lyd_node *bfd;
|
||||
int passive = 0;
|
||||
|
||||
bfd = lydx_get_child(interface, "bfd");
|
||||
bfd_enabled += lydx_get_bool(bfd, "enabled");
|
||||
bfd_enabled = lydx_get_bool(bfd, "enabled");
|
||||
num_bfd_enabled += bfd_enabled;
|
||||
|
||||
passive = lydx_get_bool(interface, "passive");
|
||||
fprintf(fp, "interface %s\n", lydx_get_cattr(interface, "name"));
|
||||
|
||||
@@ -77,7 +79,7 @@ int parse_ospf_interfaces(sr_session_ctx_t *session, struct lyd_node *areas, FIL
|
||||
}
|
||||
}
|
||||
|
||||
return bfd_enabled;
|
||||
return num_bfd_enabled;
|
||||
}
|
||||
|
||||
int parse_ospf_redistribute(sr_session_ctx_t *session, struct lyd_node *redistributes, FILE *fp)
|
||||
|
||||
@@ -1407,6 +1407,7 @@ static int auth_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *modul
|
||||
lyd_new_path(*parent, NULL, xpath, spwd->sp_pwdp, 0, 0);
|
||||
}
|
||||
|
||||
endspent();
|
||||
return SR_ERR_OK;
|
||||
}
|
||||
|
||||
@@ -1594,23 +1595,6 @@ static char *get_mac(struct confd *confd, char *mac, size_t len)
|
||||
return mac;
|
||||
}
|
||||
|
||||
#define REPLACE_SPECIFIER(replacement) \
|
||||
do { \
|
||||
size_t repl_len = strlen(replacement); \
|
||||
char *ptr; \
|
||||
\
|
||||
hostlen += repl_len; \
|
||||
ptr = realloc(hostname, hostlen + 1); \
|
||||
if (!ptr) { \
|
||||
free(hostname); \
|
||||
free(*fmt); \
|
||||
return -1; \
|
||||
} \
|
||||
hostname = ptr; \
|
||||
strlcat(hostname, replacement, hostlen + 1); \
|
||||
j += repl_len; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Decode hostname format specifiers (non-standard, Infix specifc)
|
||||
*
|
||||
@@ -1621,82 +1605,62 @@ static char *get_mac(struct confd *confd, char *mac, size_t len)
|
||||
*
|
||||
* NOTE: to be forward compatible, any unknown % combination will be silently consumed.
|
||||
* E.g., "example-%z" will become "example-"
|
||||
*
|
||||
* XXX: PLEASE REFACTOR THIS INTO A PYTHON HELPER FOR FUTURE EXTENSIONS, OR BUGS!
|
||||
*/
|
||||
static int hostnamefmt(struct confd *confd, char **fmt)
|
||||
int hostnamefmt(struct confd *confd, const char *fmt, char *buf, size_t len)
|
||||
{
|
||||
size_t hostlen, fmt_len;
|
||||
char *hostname;
|
||||
char mac[10];
|
||||
size_t i, j;
|
||||
size_t i;
|
||||
|
||||
if (!fmt || !*fmt || !strchr(*fmt, '%'))
|
||||
return 0;
|
||||
|
||||
hostlen = fmt_len = strlen(*fmt);
|
||||
hostname = calloc(hostlen + 1, sizeof(char));
|
||||
if (!hostname)
|
||||
if (!fmt || !*fmt)
|
||||
return -1;
|
||||
|
||||
for (i = 0, j = 0; i < fmt_len; i++) {
|
||||
if ((*fmt)[i] == '%') {
|
||||
switch ((*fmt)[++i]) {
|
||||
memset(buf, 0, len);
|
||||
|
||||
for (i = 0; i < strlen(fmt); i++) {
|
||||
if (fmt[i] == '%') {
|
||||
switch (fmt[++i]) {
|
||||
case 'i':
|
||||
REPLACE_SPECIFIER(id);
|
||||
strlcat(buf, id, len);
|
||||
break;
|
||||
case 'h':
|
||||
REPLACE_SPECIFIER(nm);
|
||||
strlcat(buf, nm, len);
|
||||
break;
|
||||
case 'm':
|
||||
REPLACE_SPECIFIER(get_mac(confd, mac, sizeof(mac)));
|
||||
strlcat(buf, get_mac(confd, mac, sizeof(mac)), len);
|
||||
break;
|
||||
case '%':
|
||||
if (j < hostlen) {
|
||||
hostname[j++] = '%';
|
||||
hostname[j] = 0;
|
||||
}
|
||||
strlcat(buf, "%", len);
|
||||
break;
|
||||
default:
|
||||
break; /* Unknown, skip */
|
||||
}
|
||||
} else {
|
||||
if (j < hostlen) {
|
||||
hostname[j++] = (*fmt)[i];
|
||||
hostname[j] = 0;
|
||||
}
|
||||
char ch[2] = { fmt[i], 0 };
|
||||
strlcat(buf, ch, len);
|
||||
}
|
||||
}
|
||||
|
||||
free(*fmt);
|
||||
*fmt = hostname;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef REPLACE_SPECIFIER
|
||||
|
||||
static int change_hostname(sr_session_ctx_t *session, uint32_t sub_id, const char *module,
|
||||
const char *xpath, sr_event_t event, unsigned request_id, void *priv)
|
||||
{
|
||||
struct confd *confd = (struct confd *)priv;
|
||||
const char *hostip = "127.0.1.1";
|
||||
char *hostnm, buf[256];
|
||||
char hostnm[65], buf[256];
|
||||
const char *fmt;
|
||||
FILE *nfp, *fp;
|
||||
int err, fd;
|
||||
|
||||
if (event != SR_EV_DONE)
|
||||
return SR_ERR_OK;
|
||||
|
||||
hostnm = srx_get_str(session, "%s", xpath);
|
||||
if (!hostnm) {
|
||||
fmt = srx_get_str(session, "%s", xpath);
|
||||
if (!fmt) {
|
||||
fallback:
|
||||
hostnm = strdup(nm);
|
||||
if (!hostnm) {
|
||||
err = SR_ERR_NO_MEMORY;
|
||||
goto err;
|
||||
}
|
||||
} else if (hostnamefmt(confd, &hostnm))
|
||||
strlcpy(hostnm, nm, sizeof(hostnm));
|
||||
} else if (hostnamefmt(confd, fmt, hostnm, sizeof(hostnm)))
|
||||
goto fallback;
|
||||
|
||||
err = sethostname(hostnm, strlen(hostnm));
|
||||
@@ -1753,9 +1717,6 @@ static int change_hostname(sr_session_ctx_t *session, uint32_t sub_id, const cha
|
||||
systemf("avahi-set-host-name %s", hostnm);
|
||||
systemf("initctl -nbq touch netbrowse");
|
||||
err:
|
||||
if (hostnm)
|
||||
free(hostnm);
|
||||
|
||||
if (err) {
|
||||
ERROR("Failed activating changes.");
|
||||
return err;
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#define ACTIVE_QUEUE "/var/lib/containers/active"
|
||||
#define LOGGER "logger -t container -p local1.notice"
|
||||
|
||||
|
||||
static int add(const char *name, struct lyd_node *cif)
|
||||
{
|
||||
const char *image = lydx_get_cattr(cif, "image");
|
||||
@@ -46,8 +47,14 @@ static int add(const char *name, struct lyd_node *cif)
|
||||
LYX_LIST_FOR_EACH(lyd_child(cif), node, "search")
|
||||
fprintf(fp, " --dns-search %s", lyd_get_value(node));
|
||||
|
||||
if ((string = lydx_get_cattr(cif, "hostname")))
|
||||
fprintf(fp, " --hostname %s", string);
|
||||
if ((string = lydx_get_cattr(cif, "hostname"))) {
|
||||
char buf[65];
|
||||
|
||||
if (hostnamefmt(&confd, string, buf, sizeof(buf)))
|
||||
ERRNO("%s: failed setting custom hostname", name);
|
||||
else
|
||||
fprintf(fp, " --hostname %s", buf);
|
||||
}
|
||||
|
||||
if (lydx_is_enabled(cif, "read-only"))
|
||||
fprintf(fp, " --read-only");
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
yangdir = $(YANGDIR)
|
||||
yang_DATA = $(wildcard *.yang)
|
||||
yang_DATA = $(wildcard *@*.yang) ieee802-types.yang ieee802-dot1ab-types.yang
|
||||
|
||||
@@ -26,18 +26,18 @@ MODULES=(
|
||||
"infix-hardware@2024-04-25.yang"
|
||||
"ieee802-dot1q-types@2022-10-29.yang"
|
||||
"infix-ip@2024-09-16.yang"
|
||||
"infix-if-type@2024-01-29.yang"
|
||||
"infix-routing@2024-09-23.yang"
|
||||
"infix-if-type@2024-10-13.yang"
|
||||
"infix-routing@2024-10-01.yang"
|
||||
"ieee802-dot1ab-lldp@2022-03-15.yang"
|
||||
"infix-lldp@2023-08-23.yang"
|
||||
"infix-dhcp-client@2024-09-20.yang"
|
||||
"infix-meta@2024-06-19.yang"
|
||||
"infix-meta@2024-10-18.yang"
|
||||
"infix-system@2024-09-13.yang"
|
||||
"infix-services@2024-05-30.yang"
|
||||
"ieee802-ethernet-interface@2019-06-21.yang"
|
||||
"infix-ethernet-interface@2024-02-27.yang"
|
||||
"infix-factory-default@2023-06-28.yang"
|
||||
"infix-interfaces@2024-09-23.yang -e vlan-filtering"
|
||||
"infix-interfaces@2024-10-14.yang -e vlan-filtering"
|
||||
|
||||
# from rousette
|
||||
"ietf-restconf@2017-01-26.yang"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- sh -*-
|
||||
# REMEMBER TO UPDATE infix-interfaces ALSO IN confd.inc
|
||||
MODULES=(
|
||||
"infix-interfaces@2024-09-23.yang -e vlan-filtering -e containers"
|
||||
"infix-containers@2024-03-27.yang"
|
||||
"infix-interfaces@2024-10-14.yang -e vlan-filtering -e containers"
|
||||
"infix-containers@2024-10-14.yang"
|
||||
)
|
||||
|
||||
@@ -22,6 +22,17 @@ module infix-containers {
|
||||
prefix infix-if;
|
||||
}
|
||||
|
||||
import infix-system {
|
||||
prefix infix-sys;
|
||||
}
|
||||
|
||||
revision 2024-10-14 {
|
||||
description "Two major changes:
|
||||
- Allow changing name of host interfaces inside container
|
||||
- Support hostname format specifiers, like ietf-system";
|
||||
reference "internal";
|
||||
}
|
||||
|
||||
revision 2024-03-27 {
|
||||
description "Add support for capabilities.";
|
||||
reference "internal";
|
||||
@@ -160,8 +171,11 @@ module infix-containers {
|
||||
}
|
||||
|
||||
leaf hostname {
|
||||
description "Sets the container host name that is available inside the container.";
|
||||
type inet:domain-name;
|
||||
description "Sets the container host name, available inside the container.
|
||||
|
||||
Format specifiers are for, default hostname, ID, and the
|
||||
last three octets in base MAC, e.g., c0-ff-ee";
|
||||
type infix-sys:hostname;
|
||||
}
|
||||
|
||||
leaf privileged {
|
||||
@@ -201,12 +215,16 @@ module infix-containers {
|
||||
}
|
||||
|
||||
leaf-list option {
|
||||
when "deref(../name)/../infix-if:container-network/infix-if:type = 'infix-if:bridge'";
|
||||
description "Options for masquerading container bridges.
|
||||
description "Options for interface inside container, e.g., interface_name=foo0
|
||||
|
||||
Example: ip=1.2.3.4 -- request a specific IP (IPv4 or IPv6)
|
||||
mac=00:01:02:c0:ff:ee -- set fixed MAC address in container
|
||||
interface_name=foo0 -- set interface name inside container";
|
||||
Options: ip=1.2.3.4 -- Set static IPv4 address*
|
||||
ip6=2001:0:130f::9c0:876a:130b -- Set static IPv6 address*
|
||||
mac=00:01:02:c0:ff:ee -- Set fixed MAC address
|
||||
interface_name=foo0 -- Set interface name
|
||||
|
||||
NOTE: Some (*) options only work with masquerading container bridges,
|
||||
which automatically create VETH pairs with one end in the host
|
||||
bridge and the other in the container.";
|
||||
type string;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
infix-containers.yang
|
||||
@@ -0,0 +1,166 @@
|
||||
module infix-dhcp-client {
|
||||
yang-version 1.1;
|
||||
namespace "urn:ietf:params:xml:ns:yang:infix-dhcp-client";
|
||||
prefix dhc4-clnt;
|
||||
|
||||
import ietf-interfaces {
|
||||
prefix "if";
|
||||
}
|
||||
|
||||
contact "kernelkit@googlegroups.com";
|
||||
description "This module implements an IPv4 DHCP client";
|
||||
|
||||
revision 2024-09-20 {
|
||||
description "Routes are installed in Frr (staticd), clarify preference
|
||||
vs metric and adjust default preference 100 -> 5.";
|
||||
reference "internal";
|
||||
}
|
||||
revision 2024-04-12 {
|
||||
description "Adjust DHCP client hostname option, max 64 charachters.";
|
||||
reference "internal";
|
||||
}
|
||||
revision 2024-01-30 {
|
||||
description "Add DHCP client options, arping, and route preference.";
|
||||
reference "internal";
|
||||
}
|
||||
revision 2023-05-22 {
|
||||
description "Initial revision.";
|
||||
reference "rfc2131 rfc7950";
|
||||
}
|
||||
|
||||
/*
|
||||
* Typedefs
|
||||
*/
|
||||
|
||||
typedef route-preference {
|
||||
type uint32;
|
||||
description "This type is used for selecting route preference (distance).";
|
||||
}
|
||||
|
||||
typedef dhcp-options {
|
||||
type union {
|
||||
type string;
|
||||
type enumeration {
|
||||
enum subnet {
|
||||
value 1;
|
||||
description "Subnet (IP address and netmask)";
|
||||
}
|
||||
enum router {
|
||||
value 3;
|
||||
description "Default route(s)";
|
||||
}
|
||||
enum dns {
|
||||
value 6;
|
||||
description "DNS server";
|
||||
}
|
||||
enum hostname {
|
||||
value 12;
|
||||
description "Hostname";
|
||||
}
|
||||
enum domain {
|
||||
value 15;
|
||||
description "Domain name";
|
||||
}
|
||||
enum broadcast {
|
||||
value 28;
|
||||
description "Broadcast address";
|
||||
}
|
||||
enum ntpsrv {
|
||||
value 42;
|
||||
description "NTP server";
|
||||
}
|
||||
enum address {
|
||||
value 50;
|
||||
description "Requested (previously cached) address";
|
||||
}
|
||||
enum clientid {
|
||||
value 61;
|
||||
description "Client ID (default MAC, and option 12)";
|
||||
}
|
||||
enum fqdn {
|
||||
value 81;
|
||||
description "Request DNS update of client FQDN argument";
|
||||
}
|
||||
enum search {
|
||||
value 119;
|
||||
description "Domain search list";
|
||||
}
|
||||
enum staticroutes {
|
||||
value 121;
|
||||
description "Classless static routes";
|
||||
}
|
||||
enum msstaticroutes {
|
||||
value 249;
|
||||
description "Microsoft classless static routes";
|
||||
}
|
||||
}
|
||||
}
|
||||
description "Supported DHCP client request options";
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 {
|
||||
key "if-name";
|
||||
description "List of interfaces requesting DHCPv4 configuration.";
|
||||
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.";
|
||||
}
|
||||
leaf client-id {
|
||||
type string;
|
||||
description "Optional Client ID, option 61, default: MAC address.";
|
||||
}
|
||||
leaf arping {
|
||||
type boolean;
|
||||
default "true";
|
||||
description "ARP for lease to check for IP address collisions (slow).";
|
||||
}
|
||||
list option {
|
||||
key "name";
|
||||
description
|
||||
"List of DHCP options to request (and accept). The default is an
|
||||
empty list, meaning all supported options. To restrict the
|
||||
client to only get IP address and default route, set this to:
|
||||
'subnet router'";
|
||||
leaf name {
|
||||
type dhcp-options;
|
||||
description "DHCP option to request from, or inform server of.";
|
||||
}
|
||||
leaf value {
|
||||
type string;
|
||||
description "Optional value, only used for non-flag request options.
|
||||
Example: option:hostname, value:xyzzy
|
||||
option:clientid, value:01:02:03:04:05:06:07:08:09:0a
|
||||
option:0x51, value:xyzzy.example.com";
|
||||
must "../name != 'hostname' or re-match(., '[a-zA-Z0-9\\-_]{1,64}')";
|
||||
}
|
||||
}
|
||||
leaf route-preference {
|
||||
type route-preference;
|
||||
default 5;
|
||||
description
|
||||
"The preference (administrative distance) that all DHCP routes are
|
||||
installed with, option 3, 33 and 121. The default preferfence (5)
|
||||
is higher (less worth) than static routes, but lower than those
|
||||
learned via dynamic routing protocols, like OSPF.";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,166 +0,0 @@
|
||||
module infix-dhcp-client {
|
||||
yang-version 1.1;
|
||||
namespace "urn:ietf:params:xml:ns:yang:infix-dhcp-client";
|
||||
prefix dhc4-clnt;
|
||||
|
||||
import ietf-interfaces {
|
||||
prefix "if";
|
||||
}
|
||||
|
||||
contact "kernelkit@googlegroups.com";
|
||||
description "This module implements an IPv4 DHCP client";
|
||||
|
||||
revision 2024-09-20 {
|
||||
description "Routes are installed in Frr (staticd), clarify preference
|
||||
vs metric and adjust default preference 100 -> 5.";
|
||||
reference "internal";
|
||||
}
|
||||
revision 2024-04-12 {
|
||||
description "Adjust DHCP client hostname option, max 64 charachters.";
|
||||
reference "internal";
|
||||
}
|
||||
revision 2024-01-30 {
|
||||
description "Add DHCP client options, arping, and route preference.";
|
||||
reference "internal";
|
||||
}
|
||||
revision 2023-05-22 {
|
||||
description "Initial revision.";
|
||||
reference "rfc2131 rfc7950";
|
||||
}
|
||||
|
||||
/*
|
||||
* Typedefs
|
||||
*/
|
||||
|
||||
typedef route-preference {
|
||||
type uint32;
|
||||
description "This type is used for selecting route preference (distance).";
|
||||
}
|
||||
|
||||
typedef dhcp-options {
|
||||
type union {
|
||||
type string;
|
||||
type enumeration {
|
||||
enum subnet {
|
||||
value 1;
|
||||
description "Subnet (IP address and netmask)";
|
||||
}
|
||||
enum router {
|
||||
value 3;
|
||||
description "Default route(s)";
|
||||
}
|
||||
enum dns {
|
||||
value 6;
|
||||
description "DNS server";
|
||||
}
|
||||
enum hostname {
|
||||
value 12;
|
||||
description "Hostname";
|
||||
}
|
||||
enum domain {
|
||||
value 15;
|
||||
description "Domain name";
|
||||
}
|
||||
enum broadcast {
|
||||
value 28;
|
||||
description "Broadcast address";
|
||||
}
|
||||
enum ntpsrv {
|
||||
value 42;
|
||||
description "NTP server";
|
||||
}
|
||||
enum address {
|
||||
value 50;
|
||||
description "Requested (previously cached) address";
|
||||
}
|
||||
enum clientid {
|
||||
value 61;
|
||||
description "Client ID (default MAC, and option 12)";
|
||||
}
|
||||
enum fqdn {
|
||||
value 81;
|
||||
description "Request DNS update of client FQDN argument";
|
||||
}
|
||||
enum search {
|
||||
value 119;
|
||||
description "Domain search list";
|
||||
}
|
||||
enum staticroutes {
|
||||
value 121;
|
||||
description "Classless static routes";
|
||||
}
|
||||
enum msstaticroutes {
|
||||
value 249;
|
||||
description "Microsoft classless static routes";
|
||||
}
|
||||
}
|
||||
}
|
||||
description "Supported DHCP client request options";
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 {
|
||||
key "if-name";
|
||||
description "List of interfaces requesting DHCPv4 configuration.";
|
||||
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.";
|
||||
}
|
||||
leaf client-id {
|
||||
type string;
|
||||
description "Optional Client ID, option 61, default: MAC address.";
|
||||
}
|
||||
leaf arping {
|
||||
type boolean;
|
||||
default "true";
|
||||
description "ARP for lease to check for IP address collisions (slow).";
|
||||
}
|
||||
list option {
|
||||
key "name";
|
||||
description
|
||||
"List of DHCP options to request (and accept). The default is an
|
||||
empty list, meaning all supported options. To restrict the
|
||||
client to only get IP address and default route, set this to:
|
||||
'subnet router'";
|
||||
leaf name {
|
||||
type dhcp-options;
|
||||
description "DHCP option to request from, or inform server of.";
|
||||
}
|
||||
leaf value {
|
||||
type string;
|
||||
description "Optional value, only used for non-flag request options.
|
||||
Example: option:hostname, value:xyzzy
|
||||
option:clientid, value:01:02:03:04:05:06:07:08:09:0a
|
||||
option:0x51, value:xyzzy.example.com";
|
||||
must "../name != 'hostname' or re-match(., '[a-zA-Z0-9\\-_]{1,64}')";
|
||||
}
|
||||
}
|
||||
leaf route-preference {
|
||||
type route-preference;
|
||||
default 5;
|
||||
description
|
||||
"The preference (administrative distance) that all DHCP routes are
|
||||
installed with, option 3, 33 and 121. The default preferfence (5)
|
||||
is higher (less worth) than static routes, but lower than those
|
||||
learned via dynamic routing protocols, like OSPF.";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
infix-dhcp-client.yang
|
||||