Skip to content

Commit

Permalink
add sname/fname to config, update dhcproto
Browse files Browse the repository at this point in the history
  • Loading branch information
leshow committed Feb 3, 2023
1 parent 7ae301b commit 3e46281
Show file tree
Hide file tree
Showing 11 changed files with 55 additions and 140 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,10 @@ We _could_ go much faster by keeping leases in memory and appending to the db li
[perfdhcp](https://kea.readthedocs.io/en/kea-2.0.1/man/perfdhcp.8.html) can be used to test dora, include `giaddr`, the subnet select option or the relay agent link selection opt, you can use this as a starting point:

```
sudo perfdhcp -4 -N 9901 -L 9903 -r 1 -xi -t 1 -o 118,C0A80001 -R 100 127.0.0.1
sudo perfdhcp -4 -N 9900 -L 9903 -r 1 -xi -t 1 -o 118,C0A80001 -R 100 127.0.0.1
```

This will start perfdhcp using dhcpv4, send messages to `127.0.0.1:9901`, listen on port `9903` at a rate of 1/sec, and using 100 different devices. It includes the subnet select opt (118) with `C0A80001` as a hex encoded value of the integer of `192.168.0.1`. `dora` must be listening on `9901` and have a config with ranges to allocate on the `192.168.0.1` network.
This will start perfdhcp using dhcpv4, send messages to `127.0.0.1:9900`, listen on port `9903` at a rate of 1/sec, and using 100 different devices. It includes the subnet select opt (118) with `C0A80001` as a hex encoded value of the integer of `192.168.0.1`. `dora` must be listening on `9900` and have a config with ranges to allocate on the `192.168.0.1` network.

### Setting up dora on the PI

Expand All @@ -156,4 +156,4 @@ See [PI setup](./docs/pi_setup.md)

If you find a bug, or see something that doesn't look right, please open an issue and let us know. We welcome any and all constructive feedback.

We're still actively working on this. Some of the things we'd like to add in the future include: DDNS updates, stateful DHCPv6, HA & Client classification.
We're still actively working on this. Some of the things we'd like to add in the future include: DDNS updates, stateful DHCPv6, HA & Client classification.
118 changes: 0 additions & 118 deletions basic.yaml

This file was deleted.

4 changes: 2 additions & 2 deletions bin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,13 @@ OPTIONS:
Run on non-standard ports:

```
dora -c /path/to/config.yaml --v4-addr 0.0.0.0:9901
dora -c /path/to/config.yaml --v4-addr 0.0.0.0:9900
```

is equivalent to:

```
V4_ADDR="0.0.0.0:9901" CONFIG_PATH="/path/to/config.yaml" dora
V4_ADDR="0.0.0.0:9900" CONFIG_PATH="/path/to/config.yaml" dora
```

Use `DORA_LOG` to control dora's log level. Takes same arguments as `RUST_LOG`
18 changes: 9 additions & 9 deletions bin/tests/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ fn test_basic_dhcpv4_unicast() -> Result<()> {
let settings = ClientSettingsBuilder::default()
.iface_name("dhcpcli")
.target("192.168.2.1".parse::<std::net::IpAddr>().unwrap())
.port(9901_u16)
.port(9900_u16)
.build()?;
// create a client that sends dhcpv4 messages
let mut client = Client::<v4::Message>::new(settings);
Expand Down Expand Up @@ -79,7 +79,7 @@ fn static_chaddr_dora() -> Result<()> {
let settings = ClientSettingsBuilder::default()
.iface_name("dhcpcli")
.target("192.168.2.1".parse::<std::net::IpAddr>().unwrap())
.port(9901_u16)
.port(9900_u16)
.build()?;
let chaddr = "aa:bb:cc:dd:ee:ff".parse::<MacAddr>()?.octets();

Expand Down Expand Up @@ -126,7 +126,7 @@ fn static_opt_dora() -> Result<()> {
let settings = ClientSettingsBuilder::default()
.iface_name("dhcpcli")
.target("192.168.2.1".parse::<std::net::IpAddr>().unwrap())
.port(9901_u16)
.port(9900_u16)
.build()?;

let mut client = Client::<v4::Message>::new(settings);
Expand Down Expand Up @@ -178,7 +178,7 @@ fn discover_req_addr() -> Result<()> {
let settings = ClientSettingsBuilder::default()
.iface_name("dhcpcli")
.target("192.168.2.1".parse::<std::net::IpAddr>().unwrap())
.port(9901_u16)
.port(9900_u16)
.build()?;

// create a client that sends dhcpv4 messages
Expand Down Expand Up @@ -226,7 +226,7 @@ fn request_nak() -> Result<()> {
let settings = ClientSettingsBuilder::default()
.iface_name("dhcpcli")
.target("192.168.2.1".parse::<std::net::IpAddr>().unwrap())
.port(9901_u16)
.port(9900_u16)
.build()?;

// create a client that sends dhcpv4 messages
Expand Down Expand Up @@ -270,7 +270,7 @@ fn requested_lease_time() -> Result<()> {
let settings = ClientSettingsBuilder::default()
.iface_name("dhcpcli")
.target("192.168.2.1".parse::<std::net::IpAddr>().unwrap())
.port(9901_u16)
.port(9900_u16)
.build()?;
// create a client that sends dhcpv4 messages
let mut client = Client::<v4::Message>::new(settings);
Expand Down Expand Up @@ -327,7 +327,7 @@ fn test_requested_opts() -> Result<()> {
let settings = ClientSettingsBuilder::default()
.iface_name("dhcpcli")
.target("192.168.2.1".parse::<std::net::IpAddr>().unwrap())
.port(9901_u16)
.port(9900_u16)
.build()?;
// create a client that sends dhcpv4 messages
let mut client = Client::<v4::Message>::new(settings);
Expand Down Expand Up @@ -363,7 +363,7 @@ fn test_exclusions() -> Result<()> {
let settings = ClientSettingsBuilder::default()
.iface_name("dhcpcli")
.target("192.168.2.1".parse::<std::net::IpAddr>().unwrap())
.port(9901_u16)
.port(9900_u16)
.build()?;
// create a client that sends dhcpv4 messages
let mut client = Client::<v4::Message>::new(settings);
Expand Down Expand Up @@ -403,7 +403,7 @@ fn test_decline() -> Result<()> {
let settings = ClientSettingsBuilder::default()
.iface_name("dhcpcli")
.target("192.168.2.1".parse::<std::net::IpAddr>().unwrap())
.port(9901_u16)
.port(9900_u16)
.build()?;
// create a client that sends dhcpv4 messages
let mut client = Client::<v4::Message>::new(settings);
Expand Down
2 changes: 1 addition & 1 deletion bin/tests/common/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ fn start_dhcp_server(config: &str, netns: &str, db: &str) -> Child {
let workspace_root = env::var("WORKSPACE_ROOT").unwrap_or_else(|_| "..".to_owned());
let config_path = format!("{workspace_root}/bin/tests/test_configs/{config}");
let dora_debug = format!(
"./{workspace_root}/target/debug/dora -d={db} --config-path={config_path} --threads=2 --dora-log=debug --v4-addr=0.0.0.0:9901",
"./{workspace_root}/target/debug/dora -d={db} --config-path={config_path} --threads=2 --dora-log=debug --v4-addr=0.0.0.0:9900",
);
let cmd = format!("ip netns exec {netns} {dora_debug}");

Expand Down
2 changes: 2 additions & 0 deletions dora-core/src/server/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,8 @@ impl MsgContext<v4::Message> {
v4::MessageType::Nak => {
let giaddr = resp.giaddr();
resp.clear_addrs();
resp.clear_fname();
resp.clear_sname();
resp.set_giaddr(giaddr);
// remove all opts. in the future, we may need to remove exclusively
// what was added in the param req list, for now we will just remove all
Expand Down
5 changes: 5 additions & 0 deletions example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ networks:
# OR IF IT IS NOT specified, dora will use the IP of the interface we recv'd the message on.
# OR If bound to loopback, we will just use the first non-loopback interface IP
server_id: 192.168.5.1
# this will replace the `sname` field in the DHCP header
# server_name: "example.org"
#
# this will replace the `fname` field in the DHCP header
# file_name: "bootfile.efi"
ranges:
-
# start of your range
Expand Down
12 changes: 12 additions & 0 deletions libs/config/src/v4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ impl Config {
authoritative,
server_id,
ping_timeout_ms,
server_name,
file_name,
} = net;

let ranges = ranges.into_iter().map(|range| range.into()).collect();
Expand Down Expand Up @@ -160,6 +162,8 @@ impl Config {
reserved_opts,
authoritative,
ping_timeout_ms: Duration::from_millis(ping_timeout_ms),
server_name,
file_name,
};
// set total addr space for metrics
dora_core::metrics::TOTAL_AVAILABLE_ADDRS.set(network.total_addrs() as i64);
Expand Down Expand Up @@ -225,9 +229,17 @@ pub struct Network {
/// with authoritative == true then dora will always try to respond
/// to REQUEST/INFORM
authoritative: bool,
server_name: Option<String>,
file_name: Option<String>,
}

impl Network {
pub fn server_name(&self) -> Option<&str> {
self.server_name.as_deref()
}
pub fn file_name(&self) -> Option<&str> {
self.file_name.as_deref()
}
pub fn subnet(&self) -> Ipv4Addr {
self.subnet.network()
}
Expand Down
2 changes: 2 additions & 0 deletions libs/config/src/wire/v4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ pub struct Net {
/// Whether we are authoritative for this network (default: true)
#[serde(default = "super::default_authoritative")]
pub authoritative: bool,
pub server_name: Option<String>,
pub file_name: Option<String>,
}

#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
Expand Down
24 changes: 18 additions & 6 deletions plugins/message-type/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,12 @@ impl Plugin<Message> for MsgType {
.v4()
.server_id(meta.ifindex, subnet)
.context("cannot find server_id")?;

// look up which network the message belongs to
let network = self.cfg.v4().get_network(subnet);
let sname = network.and_then(|net| net.server_name());
let fname = network.and_then(|net| net.file_name());
// message that will be returned
let mut resp = util::new_msg(req, server_id);
let mut resp = util::new_msg(req, server_id, sname, fname);

// if there is a server identifier it must match ours
if matches!(req.opts().get(OptionCode::ServerIdentifier), Some(DhcpOption::ServerIdentifier(id)) if *id != server_id && !id.is_unspecified())
Expand All @@ -84,9 +87,6 @@ impl Plugin<Message> for MsgType {
resp.opts_mut()
.insert(DhcpOption::ServerIdentifier(server_id));

// look up which network the message belongs to
let network = self.cfg.v4().get_network(subnet);

match msg_type.context("no option 53 (message type) found")? {
MessageType::Discover => {
resp.opts_mut()
Expand Down Expand Up @@ -148,7 +148,12 @@ impl Plugin<Message> for MsgType {
pub mod util {
use super::*;

pub fn new_msg(req: &Message, siaddr: Ipv4Addr) -> Message {
pub fn new_msg(
req: &Message,
siaddr: Ipv4Addr,
sname: Option<&str>,
fname: Option<&str>,
) -> Message {
let mut msg = Message::new_with_id(
req.xid(),
Ipv4Addr::UNSPECIFIED,
Expand All @@ -160,6 +165,13 @@ pub mod util {
msg.set_opcode(Opcode::BootReply)
.set_htype(req.htype())
.set_flags(req.flags());
// set the sname & fname header fields
if let Some(sname) = sname {
msg.set_sname_str(sname);
}
if let Some(fname) = fname {
msg.set_fname_str(fname);
}
msg
}
}
Expand Down

0 comments on commit 3e46281

Please sign in to comment.