mirror of
https://github.com/pj1234678/RustyDHCP.git
synced 2026-08-18 18:15:20 +08:00
368 lines
14 KiB
Rust
368 lines
14 KiB
Rust
///use num_traits::FromPrimitive;
|
|
use std::net::Ipv4Addr;
|
|
|
|
#[derive(PartialEq, Clone, Debug)]
|
|
pub struct RawDhcpOption {
|
|
pub code: u8,
|
|
pub data: Vec<u8>,
|
|
}
|
|
|
|
#[derive(PartialEq, Debug)]
|
|
pub enum DhcpOption {
|
|
DhcpMessageType(MessageType),
|
|
ServerIdentifier(Ipv4Addr),
|
|
ParameterRequestList(Vec<u8>),
|
|
RequestedIpAddress(Ipv4Addr),
|
|
HostName(String),
|
|
Router(Vec<Ipv4Addr>),
|
|
DomainNameServer(Vec<Ipv4Addr>),
|
|
IpAddressLeaseTime(u32),
|
|
SubnetMask(Ipv4Addr),
|
|
Message(String),
|
|
Unrecognized(RawDhcpOption),
|
|
}
|
|
|
|
impl DhcpOption {
|
|
pub fn to_raw(&self) -> RawDhcpOption {
|
|
match self {
|
|
Self::DhcpMessageType(mtype) => RawDhcpOption {
|
|
code: DHCP_MESSAGE_TYPE,
|
|
data: vec![*mtype as u8],
|
|
},
|
|
Self::ServerIdentifier(addr) => RawDhcpOption {
|
|
code: SERVER_IDENTIFIER,
|
|
data: addr.octets().to_vec(),
|
|
},
|
|
Self::ParameterRequestList(prl) => RawDhcpOption {
|
|
code: PARAMETER_REQUEST_LIST,
|
|
data: prl.clone(),
|
|
},
|
|
Self::RequestedIpAddress(addr) => RawDhcpOption {
|
|
code: REQUESTED_IP_ADDRESS,
|
|
data: addr.octets().to_vec(),
|
|
},
|
|
Self::HostName(name) => RawDhcpOption {
|
|
code: HOST_NAME,
|
|
data: name.as_bytes().to_vec(),
|
|
},
|
|
Self::Router(addrs) => RawDhcpOption {
|
|
code: ROUTER,
|
|
data: {
|
|
let mut v = vec![];
|
|
for a in addrs {
|
|
v.extend(a.octets().iter());
|
|
}
|
|
v
|
|
},
|
|
},
|
|
Self::DomainNameServer(addrs) => RawDhcpOption {
|
|
code: DOMAIN_NAME_SERVER,
|
|
data: {
|
|
let mut v = vec![];
|
|
for a in addrs {
|
|
v.extend(a.octets().iter());
|
|
}
|
|
v
|
|
},
|
|
},
|
|
Self::IpAddressLeaseTime(secs) => RawDhcpOption {
|
|
code: IP_ADDRESS_LEASE_TIME,
|
|
data: secs.to_be_bytes().to_vec(),
|
|
},
|
|
Self::SubnetMask(mask) => RawDhcpOption {
|
|
code: SUBNET_MASK,
|
|
data: mask.octets().to_vec(),
|
|
},
|
|
Self::Message(msg) => RawDhcpOption {
|
|
code: MESSAGE,
|
|
data: msg.as_bytes().to_vec(),
|
|
},
|
|
Self::Unrecognized(raw) => raw.clone(),
|
|
}
|
|
}
|
|
|
|
pub fn code(&self) -> u8 {
|
|
match self {
|
|
Self::DhcpMessageType(_) => DHCP_MESSAGE_TYPE,
|
|
Self::ServerIdentifier(_) => SERVER_IDENTIFIER,
|
|
Self::ParameterRequestList(_) => PARAMETER_REQUEST_LIST,
|
|
Self::RequestedIpAddress(_) => REQUESTED_IP_ADDRESS,
|
|
Self::HostName(_) => HOST_NAME,
|
|
Self::Router(_) => ROUTER,
|
|
Self::DomainNameServer(_) => DOMAIN_NAME_SERVER,
|
|
Self::IpAddressLeaseTime(_) => IP_ADDRESS_LEASE_TIME,
|
|
Self::SubnetMask(_) => SUBNET_MASK,
|
|
Self::Message(_) => MESSAGE,
|
|
Self::Unrecognized(x) => x.code,
|
|
}
|
|
}
|
|
}
|
|
|
|
// DHCP Options;
|
|
pub const SUBNET_MASK: u8 = 1;
|
|
pub const TIME_OFFSET: u8 = 2;
|
|
pub const ROUTER: u8 = 3;
|
|
pub const TIME_SERVER: u8 = 4;
|
|
pub const NAME_SERVER: u8 = 5;
|
|
pub const DOMAIN_NAME_SERVER: u8 = 6;
|
|
pub const LOG_SERVER: u8 = 7;
|
|
pub const COOKIE_SERVER: u8 = 8;
|
|
pub const LPR_SERVER: u8 = 9;
|
|
pub const IMPRESS_SERVER: u8 = 10;
|
|
pub const RESOURCE_LOCATION_SERVER: u8 = 11;
|
|
pub const HOST_NAME: u8 = 12;
|
|
pub const BOOT_FILE_SIZE: u8 = 13;
|
|
pub const MERIT_DUMP_FILE: u8 = 14;
|
|
pub const DOMAIN_NAME: u8 = 15;
|
|
pub const SWAP_SERVER: u8 = 16;
|
|
pub const ROOT_PATH: u8 = 17;
|
|
pub const EXTENSIONS_PATH: u8 = 18;
|
|
|
|
// IP LAYER PARAMETERS PER HOST;
|
|
pub const IP_FORWARDING_ENABLE_DISABLE: u8 = 19;
|
|
pub const NON_LOCAL_SOURCE_ROUTING_ENABLE_DISABLE: u8 = 20;
|
|
pub const POLICY_FILTER: u8 = 21;
|
|
pub const MAXIMUM_DATAGRAM_REASSEMBLY_SIZE: u8 = 22;
|
|
pub const DEFAULT_IP_TIME_TO_LIVE: u8 = 23;
|
|
pub const PATH_MTU_AGING_TIMEOUT: u8 = 24;
|
|
pub const PATH_MTU_PLATEAU_TABLE: u8 = 25;
|
|
|
|
// IP LAYER PARAMETERS PER INTERFACE;
|
|
pub const INTERFACE_MTU: u8 = 26;
|
|
pub const ALL_SUBNETS_ARE_LOCAL: u8 = 27;
|
|
pub const BROADCAST_ADDRESS: u8 = 28;
|
|
pub const PERFORM_MASK_DISCOVERY: u8 = 29;
|
|
pub const MASK_SUPPLIER: u8 = 30;
|
|
pub const PERFORM_ROUTER_DISCOVERY: u8 = 31;
|
|
pub const ROUTER_SOLICITATION_ADDRESS: u8 = 32;
|
|
pub const STATIC_ROUTE: u8 = 33;
|
|
|
|
// LINK LAYER PARAMETERS PER INTERFACE;
|
|
pub const TRAILER_ENCAPSULATION: u8 = 34;
|
|
pub const ARP_CACHE_TIMEOUT: u8 = 35;
|
|
pub const ETHERNET_ENCAPSULATION: u8 = 36;
|
|
|
|
// TCP PARAMETERS;
|
|
pub const TCP_DEFAULT_TTL: u8 = 37;
|
|
pub const TCP_KEEPALIVE_INTERVAL: u8 = 38;
|
|
pub const TCP_KEEPALIVE_GARBAGE: u8 = 39;
|
|
|
|
// APPLICATION AND SERVICE PARAMETERS;
|
|
pub const NETWORK_INFORMATION_SERVICE_DOMAIN: u8 = 40;
|
|
pub const NETWORK_INFORMATION_SERVERS: u8 = 41;
|
|
pub const NETWORK_TIME_PROTOCOL_SERVERS: u8 = 42;
|
|
pub const VENDOR_SPECIFIC_INFORMATION: u8 = 43;
|
|
pub const NETBIOS_OVER_TCPIP_NAME_SERVER: u8 = 44;
|
|
pub const NETBIOS_OVER_TCPIP_DATAGRAM_DISTRIBUTION_SERVER: u8 = 45;
|
|
pub const NETBIOS_OVER_TCPIP_NODE_TYPE: u8 = 46;
|
|
pub const NETBIOS_OVER_TCPIP_SCOPE: u8 = 47;
|
|
pub const XWINDOW_SYSTEM_FONT_SERVER: u8 = 48;
|
|
pub const XWINDOW_SYSTEM_DISPLAY_MANAGER: u8 = 49;
|
|
pub const NETWORK_INFORMATION_SERVICEPLUS_DOMAIN: u8 = 64;
|
|
pub const NETWORK_INFORMATION_SERVICEPLUS_SERVERS: u8 = 65;
|
|
pub const MOBILE_IP_HOME_AGENT: u8 = 68;
|
|
pub const SIMPLE_MAIL_TRANSPORT_PROTOCOL: u8 = 69;
|
|
pub const POST_OFFICE_PROTOCOL_SERVER: u8 = 70;
|
|
pub const NETWORK_NEWS_TRANSPORT_PROTOCOL: u8 = 71;
|
|
pub const DEFAULT_WORLD_WIDE_WEB_SERVER: u8 = 72;
|
|
pub const DEFAULT_FINGER_SERVER: u8 = 73;
|
|
pub const DEFAULT_INTERNET_RELAY_CHAT_SERVER: u8 = 74;
|
|
pub const STREETTALK_SERVER: u8 = 75;
|
|
pub const STREETTALK_DIRECTORY_ASSISTANCE: u8 = 76;
|
|
|
|
pub const RELAY_AGENT_INFORMATION: u8 = 82;
|
|
|
|
// DHCP EXTENSIONS
|
|
pub const REQUESTED_IP_ADDRESS: u8 = 50;
|
|
pub const IP_ADDRESS_LEASE_TIME: u8 = 51;
|
|
pub const OVERLOAD: u8 = 52;
|
|
pub const DHCP_MESSAGE_TYPE: u8 = 53;
|
|
pub const SERVER_IDENTIFIER: u8 = 54;
|
|
pub const PARAMETER_REQUEST_LIST: u8 = 55;
|
|
pub const MESSAGE: u8 = 56;
|
|
pub const MAXIMUM_DHCP_MESSAGE_SIZE: u8 = 57;
|
|
pub const RENEWAL_TIME_VALUE: u8 = 58;
|
|
pub const REBINDING_TIME_VALUE: u8 = 59;
|
|
pub const VENDOR_CLASS_IDENTIFIER: u8 = 60;
|
|
pub const CLIENT_IDENTIFIER: u8 = 61;
|
|
|
|
pub const TFTP_SERVER_NAME: u8 = 66;
|
|
pub const BOOTFILE_NAME: u8 = 67;
|
|
|
|
pub const USER_CLASS: u8 = 77;
|
|
|
|
pub const CLIENT_ARCHITECTURE: u8 = 93;
|
|
|
|
pub const TZ_POSIX_STRING: u8 = 100;
|
|
pub const TZ_DATABASE_STRING: u8 = 101;
|
|
|
|
pub const CLASSLESS_ROUTE_FORMAT: u8 = 121;
|
|
|
|
/// Returns title of DHCP Option code, if known.
|
|
pub fn title(code: u8) -> Option<&'static str> {
|
|
Some(match code {
|
|
SUBNET_MASK => "Subnet Mask",
|
|
|
|
TIME_OFFSET => "Time Offset",
|
|
ROUTER => "Router",
|
|
TIME_SERVER => "Time Server",
|
|
NAME_SERVER => "Name Server",
|
|
DOMAIN_NAME_SERVER => "Domain Name Server",
|
|
LOG_SERVER => "Log Server",
|
|
COOKIE_SERVER => "Cookie Server",
|
|
LPR_SERVER => "LPR Server",
|
|
IMPRESS_SERVER => "Impress Server",
|
|
RESOURCE_LOCATION_SERVER => "Resource Location Server",
|
|
HOST_NAME => "Host Name",
|
|
BOOT_FILE_SIZE => "Boot File Size",
|
|
MERIT_DUMP_FILE => "Merit Dump File",
|
|
DOMAIN_NAME => "Domain Name",
|
|
SWAP_SERVER => "Swap Server",
|
|
ROOT_PATH => "Root Path",
|
|
EXTENSIONS_PATH => "Extensions Path",
|
|
|
|
// IP LAYER PARAMETERS PER HOST",
|
|
IP_FORWARDING_ENABLE_DISABLE => "IP Forwarding Enable/Disable",
|
|
NON_LOCAL_SOURCE_ROUTING_ENABLE_DISABLE => "Non-Local Source Routing Enable/Disable",
|
|
POLICY_FILTER => "Policy Filter",
|
|
MAXIMUM_DATAGRAM_REASSEMBLY_SIZE => "Maximum Datagram Reassembly Size",
|
|
DEFAULT_IP_TIME_TO_LIVE => "Default IP Time-to-live",
|
|
PATH_MTU_AGING_TIMEOUT => "Path MTU Aging Timeout",
|
|
PATH_MTU_PLATEAU_TABLE => "Path MTU Plateau Table",
|
|
|
|
// IP LAYER PARAMETERS PER INTERFACE",
|
|
INTERFACE_MTU => "Interface MTU",
|
|
ALL_SUBNETS_ARE_LOCAL => "All Subnets are Local",
|
|
BROADCAST_ADDRESS => "Broadcast Address",
|
|
PERFORM_MASK_DISCOVERY => "Perform Mask Discovery",
|
|
MASK_SUPPLIER => "Mask Supplier",
|
|
PERFORM_ROUTER_DISCOVERY => "Perform Router Discovery",
|
|
ROUTER_SOLICITATION_ADDRESS => "Router Solicitation Address",
|
|
STATIC_ROUTE => "Static Route",
|
|
|
|
// LINK LAYER PARAMETERS PER INTERFACE",
|
|
TRAILER_ENCAPSULATION => "Trailer Encapsulation",
|
|
ARP_CACHE_TIMEOUT => "ARP Cache Timeout",
|
|
ETHERNET_ENCAPSULATION => "Ethernet Encapsulation",
|
|
|
|
// TCP PARAMETERS",
|
|
TCP_DEFAULT_TTL => "TCP Default TTL",
|
|
TCP_KEEPALIVE_INTERVAL => "TCP Keepalive Interval",
|
|
TCP_KEEPALIVE_GARBAGE => "TCP Keepalive Garbage",
|
|
|
|
// APPLICATION AND SERVICE PARAMETERS",
|
|
NETWORK_INFORMATION_SERVICE_DOMAIN => "Network Information Service Domain",
|
|
NETWORK_INFORMATION_SERVERS => "Network Information Servers",
|
|
NETWORK_TIME_PROTOCOL_SERVERS => "Network Time Protocol Servers",
|
|
VENDOR_SPECIFIC_INFORMATION => "Vendor Specific Information",
|
|
NETBIOS_OVER_TCPIP_NAME_SERVER => "NetBIOS over TCP/IP Name Server",
|
|
NETBIOS_OVER_TCPIP_DATAGRAM_DISTRIBUTION_SERVER => {
|
|
"NetBIOS over TCP/IP Datagram Distribution Server"
|
|
}
|
|
NETBIOS_OVER_TCPIP_NODE_TYPE => "NetBIOS over TCP/IP Node Type",
|
|
NETBIOS_OVER_TCPIP_SCOPE => "NetBIOS over TCP/IP Scope",
|
|
XWINDOW_SYSTEM_FONT_SERVER => "X Window System Font Server",
|
|
XWINDOW_SYSTEM_DISPLAY_MANAGER => "X Window System Display Manager",
|
|
NETWORK_INFORMATION_SERVICEPLUS_DOMAIN => "Network Information Service+ Domain",
|
|
NETWORK_INFORMATION_SERVICEPLUS_SERVERS => "Network Information Service+ Servers",
|
|
MOBILE_IP_HOME_AGENT => "Mobile IP Home Agent",
|
|
SIMPLE_MAIL_TRANSPORT_PROTOCOL => "Simple Mail Transport Protocol (SMTP) Server",
|
|
POST_OFFICE_PROTOCOL_SERVER => "Post Office Protocol (POP3) Server",
|
|
NETWORK_NEWS_TRANSPORT_PROTOCOL => "Network News Transport Protocol (NNTP) Server",
|
|
DEFAULT_WORLD_WIDE_WEB_SERVER => "Default World Wide Web (WWW) Server",
|
|
DEFAULT_FINGER_SERVER => "Default Finger Server",
|
|
DEFAULT_INTERNET_RELAY_CHAT_SERVER => "Default Internet Relay Chat (IRC) Server",
|
|
STREETTALK_SERVER => "StreetTalk Server",
|
|
STREETTALK_DIRECTORY_ASSISTANCE => "StreetTalk Directory Assistance (STDA) Server",
|
|
|
|
RELAY_AGENT_INFORMATION => "Relay Agent Information",
|
|
|
|
// DHCP EXTENSIONS
|
|
REQUESTED_IP_ADDRESS => "Requested IP Address",
|
|
IP_ADDRESS_LEASE_TIME => "IP Address Lease Time",
|
|
OVERLOAD => "Overload",
|
|
DHCP_MESSAGE_TYPE => "DHCP Message Type",
|
|
SERVER_IDENTIFIER => "Server Identifier",
|
|
PARAMETER_REQUEST_LIST => "Parameter Request List",
|
|
MESSAGE => "Message",
|
|
MAXIMUM_DHCP_MESSAGE_SIZE => "Maximum DHCP Message Size",
|
|
RENEWAL_TIME_VALUE => "Renewal (T1) Time Value",
|
|
REBINDING_TIME_VALUE => "Rebinding (T2) Time Value",
|
|
VENDOR_CLASS_IDENTIFIER => "Vendor class identifier",
|
|
CLIENT_IDENTIFIER => "Client-identifier",
|
|
|
|
// Find below
|
|
TFTP_SERVER_NAME => "TFTP server name",
|
|
BOOTFILE_NAME => "Bootfile name",
|
|
|
|
USER_CLASS => "User Class",
|
|
|
|
CLIENT_ARCHITECTURE => "Client Architecture",
|
|
|
|
TZ_POSIX_STRING => "TZ-POSIX String",
|
|
TZ_DATABASE_STRING => "TZ-Database String",
|
|
CLASSLESS_ROUTE_FORMAT => "Classless Route Format",
|
|
|
|
_ => return None,
|
|
})
|
|
}
|
|
|
|
///
|
|
/// DHCP Message Type.
|
|
///
|
|
/// # Standards
|
|
///
|
|
/// The semantics of the various DHCP message types are described in RFC 2131 (see Table 2).
|
|
/// Their numeric values are described in Section 9.6 of RFC 2132, which begins:
|
|
///
|
|
/// > This option is used to convey the type of the DHCP message. The code for this option is 53,
|
|
/// > and its length is 1.
|
|
///
|
|
#[derive(Copy, Clone, PartialEq, Debug)]
|
|
pub enum MessageType {
|
|
/// Client broadcast to locate available servers.
|
|
Discover = 1,
|
|
|
|
/// Server to client in response to DHCPDISCOVER with offer of configuration parameters.
|
|
Offer = 2,
|
|
|
|
/// Client message to servers either (a) requesting offered parameters from one server and
|
|
/// implicitly declining offers from all others, (b) confirming correctness of previously
|
|
/// allocated address after, e.g., system reboot, or (c) extending the lease on a particular
|
|
/// network address.
|
|
Request = 3,
|
|
|
|
/// Client to server indicating network address is already in use.
|
|
Decline = 4,
|
|
|
|
/// Server to client with configuration parameters, including committed network address.
|
|
Ack = 5,
|
|
|
|
/// Server to client indicating client's notion of network address is incorrect (e.g., client
|
|
/// has moved to new subnet) or client's lease as expired.
|
|
Nak = 6,
|
|
|
|
/// Client to server relinquishing network address and cancelling remaining lease.
|
|
Release = 7,
|
|
|
|
/// Client to server, asking only for local configuration parameters; client already has
|
|
/// externally configured network address.
|
|
Inform = 8,
|
|
}
|
|
|
|
impl MessageType {
|
|
pub fn from(val: u8) -> Result<MessageType, String> {
|
|
match val {
|
|
1 => Ok(MessageType::Discover),
|
|
2 => Ok(MessageType::Offer),
|
|
3 => Ok(MessageType::Request),
|
|
4 => Ok(MessageType::Decline),
|
|
5 => Ok(MessageType::Ack),
|
|
6 => Ok(MessageType::Nak),
|
|
7 => Ok(MessageType::Release),
|
|
8 => Ok(MessageType::Inform),
|
|
_ => Err(format!("Invalid DHCP Message Type: {:?}", val)),
|
|
}
|
|
}
|
|
}
|