1 use crate::{guid, Char8, Event, Guid, Ipv4Address, MacAddress, Status};
2 use core::ffi::c_void;
3 
4 newtype_enum! {
5     pub enum Dhcp4Event: i32 => {
6         SEND_DISCOVER   = 0x01,
7         RCVD_OFFER      = 0x02,
8         SELECT_OFFER    = 0x03,
9         SEND_REQUEST    = 0x04,
10         RCVD_ACK        = 0x05,
11         RCVD_NAK        = 0x06,
12         SEND_DECLINE    = 0x07,
13         BOUND_COMPLETED = 0x08,
14         ENTER_RENEWING  = 0x09,
15         ENTER_REBINDING = 0x0a,
16         ADDRESS_LOST    = 0x0b,
17         FAIL            = 0x0c,
18     }
19 }
20 
21 newtype_enum! {
22     pub enum Dhcp4State: i32 => {
23         STOPPED     = 0x0,
24         INIT        = 0x1,
25         SELECTING   = 0x2,
26         REQUESTING  = 0x3,
27         BOUND       = 0x4,
28         RENEWING    = 0x5,
29         REBINDING   = 0x6,
30         INIT_REBOOT = 0x7,
31         REBOOTING   = 0x8,
32     }
33 }
34 
35 #[derive(Debug)]
36 #[repr(C, packed)]
37 pub struct Dhcp4Packet {
38     pub size: u32,
39     pub length: u32,
40     pub header: Dhcp4Header,
41     pub magik: u32,
42 
43     /// Start of the DHCP packed option data.
44     ///
45     /// Note that this field is actually a variable-length array.
46     pub option: [u8; 0],
47 }
48 
49 #[derive(Clone, Copy, Debug)]
50 #[repr(C, packed)]
51 pub struct Dhcp4Header {
52     pub op_code: u8,
53     pub hw_type: u8,
54     pub hw_addr_len: u8,
55     pub hops: u8,
56     pub xid: u32,
57     pub seconds: u16,
58     pub reserved: u16,
59     pub client_addr: Ipv4Address,
60     pub your_addr: Ipv4Address,
61     pub server_addr: Ipv4Address,
62     pub gateway_addr: Ipv4Address,
63     pub client_hw_addr: [u8; 16],
64     pub server_name: [Char8; 64],
65     pub boot_file_name: [Char8; 128],
66 }
67 
68 #[derive(Debug)]
69 #[repr(C, packed)]
70 pub struct Dhcp4PacketOption {
71     pub op_code: u8,
72     pub length: u8,
73 
74     /// Start of the DHCP option data.
75     ///
76     /// Note that this field is actually a variable-length array.
77     pub data: [u8; 0],
78 }
79 
80 #[derive(Debug)]
81 #[repr(C)]
82 pub struct Dhcp4ConfigData {
83     pub discover_try_count: u32,
84     pub discover_timeout: *mut u32,
85     pub request_try_count: u32,
86     pub request_timeout: *mut u32,
87     pub client_address: Ipv4Address,
88     pub callback: Option<
89         unsafe extern "efiapi" fn(
90             this: *mut Dhcp4Protocol,
91             context: *const c_void,
92             current_state: Dhcp4State,
93             dhcp4_event: Dhcp4Event,
94             packet: *const Dhcp4Packet,
95             new_packet: *mut *const Dhcp4Packet,
96         ) -> Status,
97     >,
98     pub callback_context: *mut c_void,
99     pub option_count: u32,
100     pub option_list: *mut *const Dhcp4PacketOption,
101 }
102 
103 #[derive(Debug)]
104 #[repr(C)]
105 pub struct Dhcp4ModeData {
106     pub state: Dhcp4State,
107     pub config_data: Dhcp4ConfigData,
108     pub client_address: Ipv4Address,
109     pub client_mac_address: MacAddress,
110     pub server_address: Ipv4Address,
111     pub router_address: Ipv4Address,
112     pub subnet_mask: Ipv4Address,
113     pub lease_time: u32,
114     pub reply_packet: *const Dhcp4Packet,
115 }
116 
117 #[derive(Debug)]
118 #[repr(C)]
119 pub struct Dhcp4ListenPoint {
120     pub listen_address: Ipv4Address,
121     pub subnet_mask: Ipv4Address,
122     pub listen_port: u16,
123 }
124 
125 #[derive(Debug)]
126 #[repr(C)]
127 pub struct Dhcp4TransmitReceiveToken {
128     pub status: Status,
129     pub completion_event: Event,
130     pub remote_address: Ipv4Address,
131     pub remote_port: u16,
132     pub gateway_address: Ipv4Address,
133     pub listen_point_count: u32,
134     pub listen_points: *mut Dhcp4ListenPoint,
135     pub timeout_value: u32,
136     pub packet: *mut Dhcp4Packet,
137     pub response_count: u32,
138     pub response_list: *mut Dhcp4Packet,
139 }
140 
141 #[derive(Debug)]
142 #[repr(C)]
143 pub struct Dhcp4Protocol {
144     pub get_mode_data:
145         unsafe extern "efiapi" fn(this: *const Self, mode_data: *mut Dhcp4ModeData) -> Status,
146     pub configure:
147         unsafe extern "efiapi" fn(this: *mut Self, cfg_data: *const Dhcp4ConfigData) -> Status,
148     pub start: unsafe extern "efiapi" fn(this: *mut Self, completion_event: Event) -> Status,
149     pub renew_rebind: unsafe extern "efiapi" fn(
150         this: *mut Self,
151         rebind_request: bool,
152         completion_event: Event,
153     ) -> Status,
154     pub release: unsafe extern "efiapi" fn(this: *mut Self) -> Status,
155     pub stop: unsafe extern "efiapi" fn(this: *mut Self) -> Status,
156     pub build: unsafe extern "efiapi" fn(
157         this: *mut Self,
158         seed_packet: *mut Dhcp4Packet,
159         delete_count: u32,
160         delete_list: *mut u8,
161         append_count: u32,
162         append_list: *const *const Dhcp4PacketOption,
163         new_packet: *mut *mut Dhcp4Packet,
164     ) -> Status,
165     pub transmit_receive:
166         unsafe extern "efiapi" fn(this: *mut Self, token: *mut Dhcp4TransmitReceiveToken) -> Status,
167     pub parse: unsafe extern "efiapi" fn(
168         this: *mut Self,
169         packet: *mut Dhcp4Packet,
170         option_count: *mut u32,
171         packet_option_list: *mut *mut Dhcp4PacketOption,
172     ) -> Status,
173 }
174 
175 impl Dhcp4Protocol {
176     pub const GUID: Guid = guid!("8a219718-4ef5-4761-91c8-c0f04bda9e56");
177     pub const SERVICE_BINDING_GUID: Guid = guid!("9d9a39d8-bd42-4a73-a4d5-8ee94be11380");
178 }
179