Skip to content

Commit

Permalink
Adapt illumos route utils to support ipv4 and ipv6
Browse files Browse the repository at this point in the history
  • Loading branch information
karencfv committed Feb 15, 2024
1 parent 01f3f9f commit 26fb1d8
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 11 deletions.
68 changes: 60 additions & 8 deletions illumos-utils/src/route.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,80 @@

//! Utilities for manipulating the routing tables.
use crate::ipadm::Ipadm;
use crate::zone::ROUTE;
use crate::{execute, inner, output_to_exec_error, ExecutionError, PFEXEC};
use libc::ESRCH;
use std::net::Ipv6Addr;
use std::net::{Ipv4Addr, Ipv6Addr};

/// Wraps commands for interacting with routing tables.
pub struct Route {}

pub enum Gateway {
Ipv4(Ipv4Addr),
Ipv6(Ipv6Addr),
}

#[cfg_attr(any(test, feature = "testing"), mockall::automock)]
impl Route {
pub fn ensure_default_route_with_gateway(
gateway: &Ipv6Addr,
gateway: Gateway,
) -> Result<(), ExecutionError> {
let inet;
let gw;
match gateway {
Gateway::Ipv4(addr) => {
inet = "-inet";
gw = addr.to_string();
}
Gateway::Ipv6(addr) => {
inet = "-inet6";
gw = addr.to_string();
}
}
// Add the desired route if it doesn't already exist
let destination = "default";
let mut cmd = std::process::Command::new(PFEXEC);
let cmd = cmd.args(&[ROUTE, "-n", "get", inet, destination, inet, &gw]);

let out =
cmd.output().map_err(|err| ExecutionError::ExecutionStart {
command: inner::to_string(cmd),
err,
})?;
match out.status.code() {
Some(0) => (),
// If the entry is not found in the table,
// the exit status of the command will be 3 (ESRCH).
// When that is the case, we'll add the route.
Some(ESRCH) => {
let mut cmd = std::process::Command::new(PFEXEC);
let cmd =
cmd.args(&[ROUTE, "add", inet, destination, inet, &gw]);
execute(cmd)?;
}
Some(_) | None => return Err(output_to_exec_error(cmd, &out)),
};
Ok(())
}

pub fn ensure_opte_interface(
gateway: &Ipv4Addr,
iface: &Ipv4Addr,
) -> Result<(), ExecutionError> {
let opte_ip = Ipadm::retrieve_opte_ip(iface)?;
// Add the desired route if it doesn't already exist
let mut cmd = std::process::Command::new(PFEXEC);
let cmd = cmd.args(&[
ROUTE,
"-n",
"get",
"-inet6",
destination,
"-inet6",
"-host",
&gateway.to_string(),
&opte_ip.to_string(),
"-interface",
"-ifp",
&iface.to_string(),
]);

let out =
Expand All @@ -45,10 +95,12 @@ impl Route {
let cmd = cmd.args(&[
ROUTE,
"add",
"-inet6",
destination,
"-inet6",
"-host",
&gateway.to_string(),
&opte_ip.to_string(),
"-interface",
"-ifp",
&iface.to_string(),
]);
execute(cmd)?;
}
Expand Down
6 changes: 3 additions & 3 deletions zone-network-setup/src/bin/zone-networking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use anyhow::anyhow;
use clap::{arg, command};
use illumos_utils::ipadm::Ipadm;
use illumos_utils::route::Route;
use illumos_utils::route::{Gateway, Route};
use omicron_common::cmd::fatal;
use omicron_common::cmd::CmdError;
use slog::info;
Expand Down Expand Up @@ -74,7 +74,7 @@ async fn do_run() -> Result<(), CmdError> {
zone::current().await.expect("Could not determine local zone name");
let datalink: &String = matches.get_one("datalink").unwrap();
let static_addr: &Ipv6Addr = matches.get_one("static_addr").unwrap();
let gateway: &Ipv6Addr = matches.get_one("gateway").unwrap();
let gateway: Ipv6Addr = *matches.get_one("gateway").unwrap();

// TODO: remove when https://github.com/oxidecomputer/stlouis/issues/435 is
// addressed
Expand All @@ -91,7 +91,7 @@ async fn do_run() -> Result<(), CmdError> {
.map_err(|err| CmdError::Failure(anyhow!(err)))?;

info!(&log, "Ensuring there is a default route"; "gateway" => ?gateway);
Route::ensure_default_route_with_gateway(gateway)
Route::ensure_default_route_with_gateway(Gateway::Ipv6(gateway))
.map_err(|err| CmdError::Failure(anyhow!(err)))?;

info!(&log, "Populating hosts file for zone"; "zonename" => ?zonename);
Expand Down

0 comments on commit 26fb1d8

Please sign in to comment.