add_ipv4_addr() is needed on this branch
This change was originally made in another branch for another feature,
that feature got into master and I rebased this branch onto it. Resulting
in a dependency.
The ipv4 dialer address feature got yanked from master so now this needs to be
pulled over here.
use super::KernelInterface;
+use failure::Error;
+use std::net::Ipv4Addr;
+
impl dyn KernelInterface {
/// Returns a bool based on device state, "UP" or "DOWN", "UNKNOWN" is
/// interpreted as DOWN
@@ -17,6 +20,82 @@ impl dyn KernelInterface {
_ => None,
}
}
+
+ /// Adds an ipv4 address to a given interface, true is returned when
+ /// the ip is added, false if it is already there and Error if the interface
+ /// does not exist or some other error has occured
+ pub fn add_ipv4(&self, ip: Ipv4Addr, dev: &str) -> Result<bool, Error> {
+ // upwrap here because it's ok if we panic when the system does not have 'ip' installed
+ let output = self
+ .run_command("ip", &["addr", "add", &format!("{}/32", ip), "dev", dev])
+ .unwrap();
+ // Get the first line, check if it has "file exists"
+ match String::from_utf8(output.stderr) {
+ Ok(stdout) => match stdout.lines().next() {
+ Some(line) => {
+ if line.contains("File exists") {
+ Ok(false)
+ } else {
+ Err(format_err!("Error setting ip {}", line))
+ }
+ }
+ None => Ok(true),
+ },
+ Err(e) => Err(format_err!("Could not decode stderr from ip with {:?}", e)),
+ }
+ }
+}
+
+#[test]
+fn test_add_ipv4() {
+ use crate::KI;
+
+ use std::os::unix::process::ExitStatusExt;
+ use std::process::ExitStatus;
+ use std::process::Output;
+
+ KI.set_mock(Box::new(move |program, args| {
+ assert_eq!(program, "ip");
+ assert_eq!(args, &["addr", "add", "192.168.31.2/32", "dev", "eth0"]);
+
+ Ok(Output {
+ stdout: b"".to_vec(),
+ stderr: b"RTNETLINK answers: File exists".to_vec(),
+ status: ExitStatus::from_raw(0),
+ })
+ }));
+ let val = KI
+ .add_ipv4("192.168.31.2".parse().unwrap(), "eth0")
+ .expect("Failure to run ip test");
+ assert_eq!(false, val);
+
+ KI.set_mock(Box::new(move |program, args| {
+ assert_eq!(program, "ip");
+ assert_eq!(args, &["addr", "add", "192.168.31.2/32", "dev", "eth0"]);
+
+ Ok(Output {
+ stdout: b"".to_vec(),
+ stderr: b"Cannot find device \"eth0\"".to_vec(),
+ status: ExitStatus::from_raw(0),
+ })
+ }));
+ let val = KI.add_ipv4("192.168.31.2".parse().unwrap(), "eth0");
+ assert!(val.is_err());
+
+ KI.set_mock(Box::new(move |program, args| {
+ assert_eq!(program, "ip");
+ assert_eq!(args, &["addr", "add", "192.168.31.2/32", "dev", "eth0"]);
+
+ Ok(Output {
+ stdout: b"".to_vec(),
+ stderr: b"".to_vec(),
+ status: ExitStatus::from_raw(0),
+ })
+ }));
+ let val = KI
+ .add_ipv4("192.168.31.2".parse().unwrap(), "eth0")
+ .expect("Failure to run ip test");
+ assert_eq!(true, val);
}
#[test]
