-
Notifications
You must be signed in to change notification settings - Fork 524
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2066 from zmrow/netdog-generate
Enable network config generation via `netdog`
- Loading branch information
Showing
45 changed files
with
1,281 additions
and
58 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
[Unit] | ||
Description=Generate network configuration | ||
# Block manual interactions with this service, since it could leave the system in an | ||
# unexpected state | ||
RefuseManualStart=true | ||
RefuseManualStop=true | ||
|
||
[Service] | ||
Type=oneshot | ||
ExecStart=/usr/bin/netdog generate-net-config | ||
RemainAfterExit=true | ||
StandardError=journal+console | ||
|
||
[Install] | ||
RequiredBy=network-pre.target |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -46,6 +46,7 @@ Source114: [email protected] | |
Source115: link-kernel-modules.service | ||
Source116: load-kernel-modules.service | ||
Source117: cfsignal.service | ||
Source118: generate-network-config.service | ||
|
||
# 2xx sources: tmpfilesd configs | ||
Source200: migration-tmpfiles.conf | ||
|
@@ -445,7 +446,7 @@ install -d %{buildroot}%{_cross_unitdir} | |
install -p -m 0644 \ | ||
%{S:100} %{S:101} %{S:102} %{S:103} %{S:105} \ | ||
%{S:106} %{S:107} %{S:110} %{S:111} %{S:112} \ | ||
%{S:113} %{S:114} \ | ||
%{S:113} %{S:114} %{S:118} \ | ||
%if %{_is_vendor_variant} | ||
%{S:115} %{S:116} \ | ||
%endif | ||
|
@@ -488,6 +489,7 @@ install -p -m 0644 %{S:300} %{buildroot}%{_cross_udevrulesdir}/80-ephemeral-stor | |
%files -n %{_cross_os}netdog | ||
%{_cross_bindir}/netdog | ||
%{_cross_tmpfilesdir}/netdog.conf | ||
%{_cross_unitdir}/generate-network-config.service | ||
|
||
%files -n %{_cross_os}corndog | ||
%{_cross_bindir}/corndog | ||
|
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
//! The interface_name module contains the definition of a valid network interface name and the | ||
//! code to support creation of the structure from string. | ||
//! | ||
//! A valid network interface name is defined by the criteria in the linux kernel: | ||
//! https://elixir.bootlin.com/linux/v5.10.102/source/net/core/dev.c#L1138 | ||
use serde::{Deserialize, Serialize, Serializer}; | ||
use snafu::ensure; | ||
use std::convert::TryFrom; | ||
use std::ops::Deref; | ||
|
||
/// InterfaceName can only be created from a string that contains a valid network interface name. | ||
/// Validation is handled in the `TryFrom` implementation below. | ||
#[derive(Debug, Eq, PartialEq, Hash, Deserialize)] | ||
#[serde(try_from = "&str")] | ||
pub(crate) struct InterfaceName { | ||
inner: String, | ||
} | ||
|
||
impl TryFrom<&str> for InterfaceName { | ||
type Error = error::Error; | ||
|
||
fn try_from(input: &str) -> Result<Self> { | ||
// Rust does not treat all Unicode line terminators as starting a new line, so we check for | ||
// specific characters here, rather than just counting from lines(). | ||
// https://en.wikipedia.org/wiki/Newline#Unicode | ||
let line_terminators = [ | ||
'\n', // newline (0A) | ||
'\r', // carriage return (0D) | ||
'\u{000B}', // vertical tab | ||
'\u{000C}', // form feed | ||
'\u{0085}', // next line | ||
'\u{2028}', // line separator | ||
'\u{2029}', // paragraph separator | ||
]; | ||
|
||
ensure!( | ||
!input.contains(&line_terminators[..]), | ||
error::InvalidNetworkDeviceNameSnafu { | ||
input, | ||
msg: "contains line terminators" | ||
} | ||
); | ||
|
||
// The length for an interface name is defined here: | ||
// https://elixir.bootlin.com/linux/v5.10.102/source/include/uapi/linux/if.h#L33 | ||
// The constant definition (16) is a little misleading as the check for it ensures that the | ||
// name is NOT equal to 16. A name must be 1-15 characters. | ||
ensure!( | ||
!input.is_empty() && input.len() <= 15, | ||
error::InvalidNetworkDeviceNameSnafu { | ||
input, | ||
msg: "invalid length, must be 1 to 15 characters long" | ||
} | ||
); | ||
|
||
ensure!( | ||
!input.contains('.') && !input.contains('/') && !input.contains(char::is_whitespace), | ||
error::InvalidNetworkDeviceNameSnafu { | ||
input, | ||
msg: "contains invalid characters" | ||
} | ||
); | ||
|
||
Ok(Self { | ||
inner: input.to_string(), | ||
}) | ||
} | ||
} | ||
|
||
impl TryFrom<String> for InterfaceName { | ||
type Error = error::Error; | ||
|
||
fn try_from(input: String) -> Result<Self> { | ||
Self::try_from(input.as_ref()) | ||
} | ||
} | ||
|
||
impl Deref for InterfaceName { | ||
type Target = str; | ||
fn deref(&self) -> &Self::Target { | ||
&self.inner | ||
} | ||
} | ||
|
||
impl Serialize for InterfaceName { | ||
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error> | ||
where | ||
S: Serializer, | ||
{ | ||
serializer.serialize_str(&self.inner) | ||
} | ||
} | ||
|
||
mod error { | ||
use snafu::Snafu; | ||
|
||
#[derive(Debug, Snafu)] | ||
#[snafu(visibility(pub(crate)))] | ||
pub(crate) enum Error { | ||
#[snafu(display("Invalid network device name '{}': {}", input, msg))] | ||
InvalidNetworkDeviceName { input: String, msg: String }, | ||
} | ||
} | ||
|
||
pub(crate) use error::Error; | ||
type Result<T> = std::result::Result<T, error::Error>; | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
#[test] | ||
fn invalid_interface_name() { | ||
let bad_str = [ | ||
&std::iter::repeat("a").take(16).collect::<String>(), | ||
"", | ||
".", | ||
"..", | ||
"f/eno1", | ||
"eno 1", | ||
"eno\n1", | ||
"\n", | ||
"\r", | ||
"\u{000B}", | ||
"\u{000C}", | ||
"\u{0085}", | ||
"\u{2028}", | ||
"\u{2029}", | ||
]; | ||
for bad in bad_str { | ||
assert!(InterfaceName::try_from(bad).is_err()) | ||
} | ||
} | ||
|
||
#[test] | ||
fn valid_interface_name() { | ||
let ok_str = [ | ||
&std::iter::repeat("a").take(15).collect::<String>(), | ||
"eno1", | ||
"eth0", | ||
"enp5s0", | ||
"enx0eb36944b633", | ||
]; | ||
for ok in ok_str { | ||
assert!(InterfaceName::try_from(ok).is_ok()) | ||
} | ||
} | ||
} |
Oops, something went wrong.