@@ -50,6 +50,8 @@ pub enum DhcpOption<'a> {
5050 RequestedIp ( Ipv4Address ) ,
5151 ClientIdentifier ( EthernetAddress ) ,
5252 ServerIdentifier ( Ipv4Address ) ,
53+ Router ( Ipv4Address ) ,
54+ SubnetMask ( Ipv4Address ) ,
5355 Other { kind : u8 , data : & ' a [ u8 ] }
5456}
5557
@@ -91,6 +93,12 @@ impl<'a> DhcpOption<'a> {
9193 ( field:: OPT_SERVER_IDENTIFIER , 4 ) => {
9294 option = DhcpOption :: ServerIdentifier ( Ipv4Address :: from_bytes ( data) ) ;
9395 }
96+ ( field:: OPT_ROUTER , 4 ) => {
97+ option = DhcpOption :: Router ( Ipv4Address :: from_bytes ( data) ) ;
98+ }
99+ ( field:: OPT_SUBNET_MASK , 4 ) => {
100+ option = DhcpOption :: SubnetMask ( Ipv4Address :: from_bytes ( data) ) ;
101+ }
94102 ( _, _) => {
95103 option = DhcpOption :: Other { kind : kind, data : data } ;
96104 }
@@ -108,7 +116,10 @@ impl<'a> DhcpOption<'a> {
108116 & DhcpOption :: ClientIdentifier ( eth_addr) => {
109117 3 + eth_addr. as_bytes ( ) . len ( )
110118 }
111- & DhcpOption :: RequestedIp ( ip) | & DhcpOption :: ServerIdentifier ( ip) => {
119+ & DhcpOption :: RequestedIp ( ip) |
120+ & DhcpOption :: ServerIdentifier ( ip) |
121+ & DhcpOption :: Router ( ip) |
122+ & DhcpOption :: SubnetMask ( ip) => {
112123 2 + ip. as_bytes ( ) . len ( )
113124 } ,
114125 & DhcpOption :: Other { data, .. } => 2 + data. len ( )
@@ -148,6 +159,14 @@ impl<'a> DhcpOption<'a> {
148159 buffer[ 0 ] = field:: OPT_SERVER_IDENTIFIER ;
149160 buffer[ 2 ..6 ] . copy_from_slice ( ip. as_bytes ( ) ) ;
150161 }
162+ & DhcpOption :: Router ( ip) => {
163+ buffer[ 0 ] = field:: OPT_ROUTER ;
164+ buffer[ 2 ..6 ] . copy_from_slice ( ip. as_bytes ( ) ) ;
165+ }
166+ & DhcpOption :: SubnetMask ( mask) => {
167+ buffer[ 0 ] = field:: OPT_SUBNET_MASK ;
168+ buffer[ 2 ..6 ] . copy_from_slice ( mask. as_bytes ( ) ) ;
169+ }
151170 & DhcpOption :: Other { kind, data : provided } => {
152171 buffer[ 0 ] = kind;
153172 buffer[ 2 ..skip_length] . copy_from_slice ( provided) ;
@@ -165,7 +184,7 @@ pub struct Packet<T: AsRef<[u8]>> {
165184 buffer : T
166185}
167186
168- mod field {
187+ pub ( crate ) mod field {
169188 #![ allow( non_snake_case) ]
170189 #![ allow( unused) ]
171190
@@ -603,6 +622,10 @@ pub struct Repr<'a> {
603622 /// This field is also known as `siaddr` in the RFC. It may be set by the server in DHCPOFFER
604623 /// and DHCPACK messages, and represent the address of the next server to use in bootstrap.
605624 pub server_ip : Ipv4Address ,
625+ /// Default gateway
626+ pub router : Option < Ipv4Address > ,
627+ /// This field comes from a corresponding DhcpOption.
628+ pub subnet_mask : Option < Ipv4Address > ,
606629 /// This field is also known as `giaddr` in the RFC. In order to allow DHCP clients on subnets
607630 /// not directly served by DHCP servers to communicate with DHCP servers, DHCP relay agents can
608631 /// be installed on these subnets. The DHCP client broadcasts on the local link; the relay
@@ -635,6 +658,8 @@ pub struct Repr<'a> {
635658 /// The parameter request list informs the server about which configuration parameters
636659 /// the client is interested in.
637660 pub parameter_request_list : Option < & ' a [ u8 ] > ,
661+ /// DNS servers
662+ pub dns_servers : Option < [ Option < Ipv4Address > ; 3 ] > ,
638663}
639664
640665impl < ' a > Repr < ' a > {
@@ -680,7 +705,10 @@ impl<'a> Repr<'a> {
680705 let mut requested_ip = None ;
681706 let mut client_identifier = None ;
682707 let mut server_identifier = None ;
708+ let mut router = None ;
709+ let mut subnet_mask = None ;
683710 let mut parameter_request_list = None ;
711+ let mut dns_servers = None ;
684712
685713 let mut options = packet. options ( ) ?;
686714 while options. len ( ) > 0 {
@@ -702,9 +730,25 @@ impl<'a> Repr<'a> {
702730 DhcpOption :: ServerIdentifier ( ip) => {
703731 server_identifier = Some ( ip) ;
704732 }
733+ DhcpOption :: Router ( ip) => {
734+ router = Some ( ip) ;
735+ }
736+ DhcpOption :: SubnetMask ( mask) => {
737+ subnet_mask = Some ( mask) ;
738+ }
705739 DhcpOption :: Other { kind : field:: OPT_PARAMETER_REQUEST_LIST , data} => {
706740 parameter_request_list = Some ( data) ;
707741 }
742+ DhcpOption :: Other { kind : field:: OPT_DOMAIN_NAME_SERVER , data} => {
743+ let mut dns_servers_inner = [ None ; 3 ] ;
744+ for i in 0 .. {
745+ let offset = 4 * i;
746+ let end = offset + 4 ;
747+ if end > data. len ( ) { break }
748+ dns_servers_inner[ i] = Some ( Ipv4Address :: from_bytes ( & data[ offset..end] ) ) ;
749+ }
750+ dns_servers = Some ( dns_servers_inner) ;
751+ }
708752 DhcpOption :: Other { ..} => { }
709753 }
710754 options = next_options;
@@ -714,7 +758,8 @@ impl<'a> Repr<'a> {
714758
715759 Ok ( Repr {
716760 transaction_id, client_hardware_address, client_ip, your_ip, server_ip, relay_agent_ip,
717- broadcast, requested_ip, server_identifier, client_identifier, parameter_request_list,
761+ broadcast, requested_ip, server_identifier, router,
762+ subnet_mask, client_identifier, parameter_request_list, dns_servers,
718763 message_type : message_type?,
719764 } )
720765 }
@@ -746,6 +791,12 @@ impl<'a> Repr<'a> {
746791 if let Some ( ip) = self . server_identifier {
747792 let tmp = options; options = DhcpOption :: ServerIdentifier ( ip) . emit ( tmp) ;
748793 }
794+ if let Some ( ip) = self . router {
795+ let tmp = options; options = DhcpOption :: Router ( ip) . emit ( tmp) ;
796+ }
797+ if let Some ( ip) = self . subnet_mask {
798+ let tmp = options; options = DhcpOption :: SubnetMask ( ip) . emit ( tmp) ;
799+ }
749800 if let Some ( ip) = self . requested_ip {
750801 let tmp = options; options = DhcpOption :: RequestedIp ( ip) . emit ( tmp) ;
751802 }
@@ -878,12 +929,15 @@ mod test {
878929 client_ip : IP_NULL ,
879930 your_ip : IP_NULL ,
880931 server_ip : IP_NULL ,
932+ router : None ,
933+ subnet_mask : None ,
881934 relay_agent_ip : IP_NULL ,
882935 broadcast : false ,
883936 requested_ip : Some ( IP_NULL ) ,
884937 client_identifier : Some ( CLIENT_MAC ) ,
885938 server_identifier : None ,
886939 parameter_request_list : Some ( & [ 1 , 3 , 6 , 42 ] ) ,
940+ dns_servers : None ,
887941 }
888942 }
889943
0 commit comments