Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoInstallSign in
Socket

dhcplayer

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

dhcplayer - npm Package Compare versions

Comparing version
0.1.3
to
0.1.4
+242
src/dhcp/packet.rs
use super::{ClientFqdn, err::IResult};
use super::helpers::{parse_ipv4, parse_mac};
use super::options::{DhcpOption, DhcpOptions};
use nom::bytes::complete::{tag, take};
use nom::multi::many_till;
use nom::number::complete::{be_u16, be_u32, be_u8};
use pnet::util::MacAddr;
use std::net::Ipv4Addr;
pub const BROADCAST_FLAG: u16 = 0x8000;
const DHCP_COOKIE: [u8; 4] = [99, 130, 83, 99];
#[derive(Debug)]
pub struct DhcpPacket {
/// Message op code.
pub op: u8,
/// Client sets to zero, optionally used by relay agents
/// when booting via a relay agent.
pub hops: u8,
/// Transaction ID, a random number chosen by the
/// client, used by the client and server to associate
/// messages and responses between a client and a
/// server.
pub xid: u32,
/// Filled in by client, seconds elapsed since client
/// began address acquisition or renewal process.
pub secs: u16,
/// Used to indicate if message is unicast or broadcast
pub flags: u16,
/// Client IP address; only filled in if client is in
/// BOUND, RENEW or REBINDING state and can respond
/// to ARP requests.
pub ciaddr: Ipv4Addr,
/// 'your' (client) IP address.
pub yiaddr: Ipv4Addr,
/// IP address of next server to use in bootstrap;
/// returned in DHCPOFFER, DHCPACK by server.
pub siaddr: Ipv4Addr,
/// Relay agent IP address, used in booting via a
/// relay agent.
pub giaddr: Ipv4Addr,
/// Client hardware address.
pub chaddr: MacAddr,
pub options: Vec<DhcpOption>,
}
pub const BOOT_REQUEST: u8 = 1; // From Client;
pub const BOOT_REPLY: u8 = 2; // From Server;
pub const ETHERNET_TYPE: u8 = 1;
pub const ETHERNET_ADDRESS_LEN: u8 = 6;
pub const DHCP_PACKET_MIN_SIZE: usize = 272;
macro_rules! get_option {
($fn:ident, $option:tt, $type:tt) => {
pub fn $fn(&self) -> Option<$type> {
for opt in &self.options {
match opt {
DhcpOption::$option(t) => return Some(*t),
_ => {}
}
}
return None;
}
};
}
macro_rules! get_option_ref {
($fn:ident, $option:tt, $type:path) => {
pub fn $fn(&self) -> Option<&$type> {
for opt in &self.options {
match opt {
DhcpOption::$option(t) => return Some(t),
_ => {}
}
}
return None;
}
};
}
macro_rules! add_option {
($fn:ident, $option:tt, $type:path) => {
pub fn $fn(&mut self, val: $type) {
self.options.push(DhcpOption::$option(val));
}
};
}
impl DhcpPacket {
pub fn new_reply() -> Self {
let mut p = Self::default();
p.op = BOOT_REPLY;
return p;
}
pub fn new_request() -> Self {
let mut p = Self::default();
p.op = BOOT_REQUEST;
return p;
}
pub fn set_broadcast(&mut self) {
self.flags = self.flags & BROADCAST_FLAG;
}
get_option!(dhcp_msg_type, DhcpMsgType, u8);
get_option!(dhcp_server_id, DhcpServerId, Ipv4Addr);
get_option_ref!(hostname, HostName, String);
get_option_ref!(message, Message, String);
get_option_ref!(parameter_request_list, ParameterRequestList, Vec<u8>);
get_option!(requested_ip_address, RequestedIpAddress, Ipv4Addr);
add_option!(add_broadcast_address, BroadcastAddress, Ipv4Addr);
add_option!(add_client_fqdn, ClientFqdn, ClientFqdn);
add_option!(add_dhcp_msg_type, DhcpMsgType, u8);
add_option!(add_dhcp_server_id, DhcpServerId, Ipv4Addr);
add_option!(add_domain_name, DomainName, String);
add_option!(add_domain_server, DomainServer, Vec<Ipv4Addr>);
add_option!(add_hostname, HostName, String);
add_option!(add_ip_address_lease_time, IpAddressLeaseTime, u32);
add_option!(add_message, Message, String);
add_option!(add_netbios_name_server, NetbiosNameServer, Vec<Ipv4Addr>);
add_option!(add_parameter_request_list, ParameterRequestList, Vec<u8>);
add_option!(add_requested_ip_address, RequestedIpAddress, Ipv4Addr);
add_option!(add_renewal_time, RenewalTime, u32);
add_option!(add_rebinding_time, RebindingTime, u32);
add_option!(add_router, Router, Vec<Ipv4Addr>);
add_option!(add_subnet_mask, SubnetMask, Ipv4Addr);
add_option!(add_wpad, WPAD, String);
pub fn build(&self) -> Vec<u8> {
let mut raw = Vec::new();
raw.push(self.op);
raw.push(ETHERNET_TYPE);
raw.push(ETHERNET_ADDRESS_LEN);
raw.push(self.hops);
raw.extend(&self.xid.to_be_bytes());
raw.extend(&self.secs.to_be_bytes());
raw.extend(&self.flags.to_be_bytes());
raw.extend(&self.ciaddr.octets());
raw.extend(&self.yiaddr.octets());
raw.extend(&self.siaddr.octets());
raw.extend(&self.giaddr.octets());
raw.extend(&self.chaddr.octets());
raw.extend(&[0; 10]);
raw.extend(&[0; 64]);
raw.extend(&[0; 128]);
raw.extend(&DHCP_COOKIE);
for opt in &self.options {
raw.extend(&opt.build());
}
raw.push(DhcpOptions::END);
while raw.len() < DHCP_PACKET_MIN_SIZE {
raw.push(0);
}
return raw;
}
pub fn parse(raw: &[u8]) -> IResult<&[u8], Self> {
let (raw, op) = be_u8(raw)?;
let (raw, _htype) = be_u8(raw)?;
let (raw, _hlen) = be_u8(raw)?;
let (raw, hops) = be_u8(raw)?;
let (raw, xid) = be_u32(raw)?;
let (raw, secs) = be_u16(raw)?;
let (raw, flags) = be_u16(raw)?;
let (raw, ciaddr) = parse_ipv4(raw)?;
let (raw, yiaddr) = parse_ipv4(raw)?;
let (raw, siaddr) = parse_ipv4(raw)?;
let (raw, giaddr) = parse_ipv4(raw)?;
let (raw, chaddr) = parse_mac(raw)?;
let (raw, _chaddr_padding) = take(10u8)(raw)?;
// Optional server host name, null terminated string.
let (raw, _sname) = take(64u8)(raw)?;
// Boot file name, null terminated string; "generic"
// name or null in DHCPDISCOVER, fully qualified
// directory-path name in DHCPOFFER.
let (raw, _file) = take(128u8)(raw)?;
let (raw, _) = tag(DHCP_COOKIE)(raw)?;
let (raw, (options, _)) =
many_till(DhcpOption::parse, tag(&[DhcpOptions::END]))(raw)?;
return Ok((
raw,
Self {
op,
hops,
xid,
secs,
flags,
ciaddr,
yiaddr,
siaddr,
giaddr,
chaddr,
options,
},
));
}
}
impl Default for DhcpPacket {
fn default() -> Self {
return DhcpPacket {
op: BOOT_REPLY,
hops: 0,
xid: 0,
secs: 0,
flags: 0,
ciaddr: Ipv4Addr::from(0),
yiaddr: Ipv4Addr::from(0),
siaddr: Ipv4Addr::from(0),
giaddr: Ipv4Addr::from(0),
chaddr: MacAddr::new(0, 0, 0, 0, 0, 0),
options: Vec::new(),
};
}
}
+1
-1
{
"git": {
"sha1": "88da1d11d180d77ae4ac0aec55c88dea495fb98f"
"sha1": "bd29ec7353d9abddeb8d18269d8fbcc5bd5259e6"
}
}

@@ -114,3 +114,3 @@ # This file is automatically @generated by Cargo.

name = "dhcplayer"
version = "0.1.3"
version = "0.1.4"
dependencies = [

@@ -117,0 +117,0 @@ "clap",

@@ -16,3 +16,3 @@ # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO

name = "dhcplayer"
version = "0.1.3"
version = "0.1.4"
authors = ["Eloy Pérez <zer1t0ps@protonmail.com>"]

@@ -19,0 +19,0 @@ description = "A tool to play and attack DHCP"

@@ -80,2 +80,20 @@ use std::{net::Ipv4Addr, time::Duration};

.arg(
Arg::with_name("fqdn")
.long("fqdn")
.takes_value(true)
.help("Fully Qualified Domain Name of the client (the hostname with the domain)")
)
.arg(
Arg::with_name("dns-update")
.long("dns-update")
.help("Requests creation of DNS record using the given FQDN or hostname. If none of them are given, can be used to delete the DNS record.")
)
.arg(
Arg::with_name("hostname")
.long("hostname")
.short("H")
.takes_value(true)
.help("Hostname to send in the petition")
)
.arg(
Arg::with_name("verbosity")

@@ -97,2 +115,5 @@ .short("v")

pub servers: Option<Vec<Ipv4Addr>>,
pub hostname: Option<String>,
pub fqdn: Option<String>,
pub dns_update: bool,
pub verbosity: usize,

@@ -118,2 +139,5 @@ }

servers: helpers::parse_ips(matches, "server"),
hostname: helpers::parse_string(matches, "hostname"),
fqdn: helpers::parse_string(matches, "fqdn"),
dns_update: matches.is_present("dns-update"),
verbosity: matches.occurrences_of("verbosity") as usize,

@@ -120,0 +144,0 @@ }

@@ -8,2 +8,8 @@

impl<I> From<nom::Err<(I, nom::error::ErrorKind)>> for Error<I> {
fn from(error: nom::Err<(I, nom::error::ErrorKind)>) -> Self {
return Self::NomError(error);
}
}
impl<I> nom::error::ParseError<I> for Error<I> {

@@ -10,0 +16,0 @@ fn from_error_kind(input: I, kind: nom::error::ErrorKind) -> Self {

@@ -6,245 +6,8 @@ // Adapted from https://github.com/krolaw/dhcp4r

mod options;
mod packet;
use err::IResult;
use helpers::{parse_ipv4, parse_mac};
use nom::bytes::complete::{tag, take};
use nom::multi::many_till;
use nom::number::complete::{be_u16, be_u32, be_u8};
pub use options::{DhcpMessageTypes, DhcpOption, DhcpOptions};
use pnet::util::MacAddr;
use std::net::Ipv4Addr;
pub use packet::DhcpPacket;
pub use options::{ClientFqdn, DhcpMessageTypes, DhcpOption, DhcpOptions};
pub const DHCP_SERVER_PORT: u16 = 67;
pub const DHCP_CLIENT_PORT: u16 = 68;
pub const BROADCAST_FLAG: u16 = 0x8000;
const DHCP_COOKIE: [u8; 4] = [99, 130, 83, 99];
#[derive(Debug)]
pub struct DhcpPacket {
/// Message op code.
pub op: u8,
/// Client sets to zero, optionally used by relay agents
/// when booting via a relay agent.
pub hops: u8,
/// Transaction ID, a random number chosen by the
/// client, used by the client and server to associate
/// messages and responses between a client and a
/// server.
pub xid: u32,
/// Filled in by client, seconds elapsed since client
/// began address acquisition or renewal process.
pub secs: u16,
/// Used to indicate if message is unicast or broadcast
pub flags: u16,
/// Client IP address; only filled in if client is in
/// BOUND, RENEW or REBINDING state and can respond
/// to ARP requests.
pub ciaddr: Ipv4Addr,
/// 'your' (client) IP address.
pub yiaddr: Ipv4Addr,
/// IP address of next server to use in bootstrap;
/// returned in DHCPOFFER, DHCPACK by server.
pub siaddr: Ipv4Addr,
/// Relay agent IP address, used in booting via a
/// relay agent.
pub giaddr: Ipv4Addr,
/// Client hardware address.
pub chaddr: MacAddr,
pub options: Vec<DhcpOption>,
}
pub const BOOT_REQUEST: u8 = 1; // From Client;
pub const BOOT_REPLY: u8 = 2; // From Server;
pub const ETHERNET_TYPE: u8 = 1;
pub const ETHERNET_ADDRESS_LEN: u8 = 6;
pub const DHCP_PACKET_MIN_SIZE: usize = 272;
macro_rules! get_option {
($fn:ident, $option:tt, $type:tt) => {
pub fn $fn(&self) -> Option<$type> {
for opt in &self.options {
match opt {
DhcpOption::$option(t) => return Some(*t),
_ => {}
}
}
return None;
}
};
}
macro_rules! get_option_ref {
($fn:ident, $option:tt, $type:path) => {
pub fn $fn(&self) -> Option<&$type> {
for opt in &self.options {
match opt {
DhcpOption::$option(t) => return Some(t),
_ => {}
}
}
return None;
}
};
}
macro_rules! add_option {
($fn:ident, $option:tt, $type:path) => {
pub fn $fn(&mut self, val: $type) {
self.options.push(DhcpOption::$option(val));
}
};
}
impl DhcpPacket {
pub fn new_reply() -> Self {
let mut p = Self::default();
p.op = BOOT_REPLY;
return p;
}
pub fn new_request() -> Self {
let mut p = Self::default();
p.op = BOOT_REQUEST;
return p;
}
pub fn set_broadcast(&mut self) {
self.flags = self.flags & BROADCAST_FLAG;
}
get_option!(dhcp_msg_type, DhcpMsgType, u8);
get_option!(dhcp_server_id, DhcpServerId, Ipv4Addr);
get_option_ref!(hostname, HostName, String);
get_option_ref!(message, Message, String);
get_option_ref!(parameter_request_list, ParameterRequestList, Vec<u8>);
get_option!(requested_ip_address, RequestedIpAddress, Ipv4Addr);
add_option!(add_broadcast_address, BroadcastAddress, Ipv4Addr);
add_option!(add_dhcp_msg_type, DhcpMsgType, u8);
add_option!(add_dhcp_server_id, DhcpServerId, Ipv4Addr);
add_option!(add_domain_name, DomainName, String);
add_option!(add_domain_server, DomainServer, Vec<Ipv4Addr>);
add_option!(add_ip_address_lease_time, IpAddressLeaseTime, u32);
add_option!(add_message, Message, String);
add_option!(add_netbios_name_server, NetbiosNameServer, Vec<Ipv4Addr>);
add_option!(add_parameter_request_list, ParameterRequestList, Vec<u8>);
add_option!(add_requested_ip_address, RequestedIpAddress, Ipv4Addr);
add_option!(add_renewal_time, RenewalTime, u32);
add_option!(add_rebinding_time, RebindingTime, u32);
add_option!(add_router, Router, Vec<Ipv4Addr>);
add_option!(add_subnet_mask, SubnetMask, Ipv4Addr);
add_option!(add_wpad, WPAD, String);
pub fn build(&self) -> Vec<u8> {
let mut raw = Vec::new();
raw.push(self.op);
raw.push(ETHERNET_TYPE);
raw.push(ETHERNET_ADDRESS_LEN);
raw.push(self.hops);
raw.extend(&self.xid.to_be_bytes());
raw.extend(&self.secs.to_be_bytes());
raw.extend(&self.flags.to_be_bytes());
raw.extend(&self.ciaddr.octets());
raw.extend(&self.yiaddr.octets());
raw.extend(&self.siaddr.octets());
raw.extend(&self.giaddr.octets());
raw.extend(&self.chaddr.octets());
raw.extend(&[0; 10]);
raw.extend(&[0; 64]);
raw.extend(&[0; 128]);
raw.extend(&DHCP_COOKIE);
for opt in &self.options {
raw.extend(&opt.build());
}
raw.push(DhcpOptions::END);
while raw.len() < DHCP_PACKET_MIN_SIZE {
raw.push(0);
}
return raw;
}
pub fn parse(raw: &[u8]) -> IResult<&[u8], Self> {
let (raw, op) = be_u8(raw)?;
let (raw, _htype) = be_u8(raw)?;
let (raw, _hlen) = be_u8(raw)?;
let (raw, hops) = be_u8(raw)?;
let (raw, xid) = be_u32(raw)?;
let (raw, secs) = be_u16(raw)?;
let (raw, flags) = be_u16(raw)?;
let (raw, ciaddr) = parse_ipv4(raw)?;
let (raw, yiaddr) = parse_ipv4(raw)?;
let (raw, siaddr) = parse_ipv4(raw)?;
let (raw, giaddr) = parse_ipv4(raw)?;
let (raw, chaddr) = parse_mac(raw)?;
let (raw, _chaddr_padding) = take(10u8)(raw)?;
// Optional server host name, null terminated string.
let (raw, _sname) = take(64u8)(raw)?;
// Boot file name, null terminated string; "generic"
// name or null in DHCPDISCOVER, fully qualified
// directory-path name in DHCPOFFER.
let (raw, _file) = take(128u8)(raw)?;
let (raw, _) = tag(DHCP_COOKIE)(raw)?;
let (raw, (options, _)) =
many_till(DhcpOption::parse, tag(&[DhcpOptions::END]))(raw)?;
return Ok((
raw,
Self {
op,
hops,
xid,
secs,
flags,
ciaddr,
yiaddr,
siaddr,
giaddr,
chaddr,
options,
},
));
}
}
impl Default for DhcpPacket {
fn default() -> Self {
return DhcpPacket {
op: BOOT_REPLY,
hops: 0,
xid: 0,
secs: 0,
flags: 0,
ciaddr: Ipv4Addr::from(0),
yiaddr: Ipv4Addr::from(0),
siaddr: Ipv4Addr::from(0),
giaddr: Ipv4Addr::from(0),
chaddr: MacAddr::new(0, 0, 0, 0, 0, 0),
options: Vec::new(),
};
}
}

@@ -1,2 +0,2 @@

use super::err::IResult;
use super::err::{Error, IResult};
use super::helpers::{parse_ipv4, parse_utf8};

@@ -11,2 +11,3 @@ use nom::bytes::complete::take;

BroadcastAddress(Ipv4Addr),
ClientFqdn(ClientFqdn),
DhcpMsgType(u8),

@@ -42,2 +43,5 @@ DhcpServerId(Ipv4Addr),

}
DhcpOptions::CLIENT_FQDN => DhcpOption::ClientFqdn(
ClientFqdn::parse(data).map_err(|e| nom::Err::Error(e))?,
),
DhcpOptions::DHCP_MSG_TYPE => {

@@ -105,2 +109,6 @@ DhcpOption::DhcpMsgType(be_u8(data)?.1)

},
Self::ClientFqdn(cf) => RawDhcpOption {
code: DhcpOptions::CLIENT_FQDN,
data: cf.build(),
},
Self::DhcpMsgType(mtype) => RawDhcpOption {

@@ -133,6 +141,5 @@ code: DhcpOptions::DHCP_MSG_TYPE,

},
Self::NameServer(addrs) => RawDhcpOption::from_addrs(
DhcpOptions::NAME_SERVER,
addrs,
),
Self::NameServer(addrs) => {
RawDhcpOption::from_addrs(DhcpOptions::NAME_SERVER, addrs)
}
Self::NetbiosNameServer(addrs) => RawDhcpOption::from_addrs(

@@ -176,2 +183,3 @@ DhcpOptions::NETBIOS_NAME_SERVER,

Self::BroadcastAddress(addr) => format!("{}", addr),
Self::ClientFqdn(cf) => format!("{}", cf.value_str()),
Self::DhcpMsgType(mtype) => {

@@ -249,2 +257,53 @@ format!(

pub const FQDN_SERVER_UDPATE: u8 = 0x1;
/// Defined in https://datatracker.ietf.org/doc/html/rfc4702
#[derive(PartialEq, Debug, Clone)]
pub struct ClientFqdn {
pub flags: u8,
pub aresult: u8,
pub ptrresult: u8,
pub name: String,
}
impl ClientFqdn {
pub fn parse(input: &[u8]) -> Result<Self, Error<&[u8]>> {
let (input, flags) = be_u8(input)?;
let (input, aresult) = be_u8(input)?;
let (input, ptrresult) = be_u8(input)?;
let name = parse_utf8(input)?;
return Ok(Self {
flags,
aresult,
ptrresult,
name,
});
}
pub fn build(&self) -> Vec<u8> {
let mut raw = Vec::new();
raw.push(self.flags);
raw.push(self.aresult);
raw.push(self.ptrresult);
raw.extend(self.name.as_bytes());
return raw;
}
pub fn value_str(&self) -> String {
let flags_names = if (self.flags & FQDN_SERVER_UDPATE) != 0 {
" (server-update)"
} else {
""
};
format!(
"flags: 0x{:x}{} A-result: {} PTR-result: {} {}",
self.flags, flags_names, self.aresult, self.ptrresult, self.name
)
}
}
#[allow(non_snake_case)]

@@ -279,2 +338,4 @@ pub mod DhcpOptions {

pub const CLIENT_FQDN: u8 = 81;
pub const WPAD: u8 = 252;

@@ -302,2 +363,3 @@

REBINDING_TIME => Some("Rebinding Time"),
CLIENT_FQDN => Some("Client FQDN"),
WPAD => Some("WPAD"),

@@ -304,0 +366,0 @@ _ => None,

use std::net::Ipv4Addr;
use crate::dhcp::{DhcpMessageTypes, DhcpOption, DhcpPacket};
use crate::dhcp::{ClientFqdn, DhcpMessageTypes, DhcpOption, DhcpPacket};
use crate::{

@@ -36,5 +36,2 @@ args,

let mut channel = TransportChannel::new(iface, Some(args.timeout))
.map_err(|e| format!("Unable to create a raw socket: {}", e))?;
let request_list = match args.options {

@@ -51,2 +48,25 @@ Some(options) => options,

let dns_update = args.dns_update;
let fqdn = args.fqdn.unwrap_or("".to_string());
let client_fqdn = if dns_update || fqdn.len() != 0 {
Some(ClientFqdn {
flags: dns_update as u8,
aresult: 0,
ptrresult: 0,
name: fqdn,
})
} else {
None
};
let client_options = ClientOptions {
request_list,
hostname: args.hostname,
client_fqdn,
};
let mut channel = TransportChannel::new(iface, Some(args.timeout))
.map_err(|e| format!("Unable to create a raw socket: {}", e))?;
match get_action(args.inform, args.send_request) {

@@ -57,3 +77,3 @@ Action::Discover => discover_all(

ether_mac,
request_list,
&client_options,
args.servers.as_ref(),

@@ -66,3 +86,3 @@ )?,

ether_mac,
request_list,
&client_options,
args.servers.as_ref(),

@@ -84,3 +104,3 @@ )?;

ether_mac,
request_list,
&client_options,
args.servers.as_ref(),

@@ -110,3 +130,3 @@ )?;

ether_mac: MacAddr,
request_list: Vec<u8>,
client_options: &ClientOptions,
servers: Option<&Vec<Ipv4Addr>>,

@@ -118,3 +138,9 @@ ) -> Result<(), String> {

info!("DISCOVER sent - Client MAC {}", dhcp_mac);
send_discover(channel, transaction_id, dhcp_mac, ether_mac, request_list)?;
send_discover(
channel,
transaction_id,
dhcp_mac,
ether_mac,
client_options,
)?;

@@ -147,3 +173,3 @@ loop {

ether_mac: MacAddr,
request_list: Vec<u8>,
client_options: &ClientOptions,
servers: Option<&Vec<Ipv4Addr>>,

@@ -161,3 +187,3 @@ ) -> Result<(), String> {

ether_mac,
request_list,
client_options,
client_ip,

@@ -241,3 +267,3 @@ )?;

ether_mac: MacAddr,
request_list: Vec<u8>,
client_options: &ClientOptions,
servers: Option<&Vec<Ipv4Addr>>,

@@ -254,3 +280,3 @@ ) -> Result<DhcpPacket, String> {

ether_mac,
request_list.clone(),
client_options,
servers,

@@ -272,3 +298,3 @@ )?;

ether_mac,
request_list,
client_options,
client_ip,

@@ -284,6 +310,12 @@ dhcp_server,

ether_mac: MacAddr,
request_list: Vec<u8>,
client_options: &ClientOptions,
servers: Option<&Vec<Ipv4Addr>>,
) -> Result<DhcpPacket, String> {
send_discover(channel, transaction_id, dhcp_mac, ether_mac, request_list)?;
send_discover(
channel,
transaction_id,
dhcp_mac,
ether_mac,
client_options,
)?;

@@ -305,3 +337,3 @@ let (_, dhcp_resp) = channel.recv_dhcp(

ether_mac: MacAddr,
request_list: Vec<u8>,
client_options: &ClientOptions,
) -> Result<(), String> {

@@ -312,3 +344,3 @@ let mut dp = DhcpPacket::new_request();

dp.chaddr = dhcp_mac;
dp.add_parameter_request_list(request_list);
set_client_options(&mut dp, client_options);

@@ -336,3 +368,3 @@ channel

ether_mac: MacAddr,
request_list: Vec<u8>,
client_options: &ClientOptions,
client_ip: Ipv4Addr,

@@ -347,4 +379,5 @@ dhcp_server: Ipv4Addr,

dp.add_dhcp_server_id(dhcp_server);
dp.add_parameter_request_list(request_list);
set_client_options(&mut dp, client_options);
channel

@@ -378,3 +411,3 @@ .build_and_send(

ether_mac: MacAddr,
request_list: Vec<u8>,
client_options: &ClientOptions,
client_ip: Ipv4Addr,

@@ -387,3 +420,3 @@ ) -> Result<(), String> {

dp.chaddr = dhcp_mac;
dp.add_parameter_request_list(request_list.clone());
set_client_options(&mut dp, client_options);

@@ -405,1 +438,19 @@ channel

}
pub fn set_client_options(dp: &mut DhcpPacket, co: &ClientOptions) {
dp.add_parameter_request_list(co.request_list.clone());
if let Some(hostname) = &co.hostname {
dp.add_hostname(hostname.clone());
}
if let Some(client_fqdn) = &co.client_fqdn {
dp.add_client_fqdn(client_fqdn.clone());
}
}
pub struct ClientOptions {
pub request_list: Vec<u8>,
pub hostname: Option<String>,
pub client_fqdn: Option<ClientFqdn>,
}

Sorry, the diff of this file is not supported yet