@@ -16,18 +16,21 @@ use crate::{Options, Packet};
16
16
17
17
/// Represents the additional network-related information that might be returned by the DHCP server.
18
18
#[ derive( Debug , Clone ) ]
19
- pub struct NetworkInfo {
19
+ #[ non_exhaustive]
20
+ pub struct NetworkInfo < ' a > {
20
21
pub gateway : Option < Ipv4Addr > ,
21
22
pub subnet : Option < Ipv4Addr > ,
22
23
pub dns1 : Option < Ipv4Addr > ,
23
24
pub dns2 : Option < Ipv4Addr > ,
25
+ pub captive_url : Option < & ' a str > ,
24
26
}
25
27
26
28
/// Represents a DHCP IP lease.
27
29
///
28
30
/// This structure has a set of asynchronous methods that can utilize a supplied DHCP client instance and UDP socket to
29
31
/// transparently implement all aspects of negotiating an IP with the DHCP server and then keeping the lease of that IP up to date.
30
32
#[ derive( Debug , Clone ) ]
33
+ #[ non_exhaustive]
31
34
pub struct Lease {
32
35
pub ip : Ipv4Addr ,
33
36
pub server_ip : Ipv4Addr ,
@@ -40,46 +43,57 @@ impl Lease {
40
43
/// This is done by utilizing the supplied DHCP client instance and UDP socket.
41
44
///
42
45
/// Note that the supplied UDP socket should be capable of sending and receiving broadcast UDP packets.
43
- pub async fn new < T , S > (
46
+ pub async fn new < ' a , T , S > (
44
47
client : & mut dhcp:: client:: Client < T > ,
45
48
socket : & mut S ,
46
- buf : & mut [ u8 ] ,
47
- ) -> Result < ( Self , NetworkInfo ) , Error < S :: Error > >
49
+ buf : & ' a mut [ u8 ] ,
50
+ ) -> Result < ( Self , NetworkInfo < ' a > ) , Error < S :: Error > >
48
51
where
49
52
T : RngCore ,
50
53
S : UdpReceive + UdpSend ,
51
54
{
52
55
loop {
53
56
let offer = Self :: discover ( client, socket, buf, Duration :: from_secs ( 3 ) ) . await ?;
57
+ let server_ip = offer. server_ip . unwrap ( ) ;
58
+ let ip = offer. ip ;
54
59
55
60
let now = Instant :: now ( ) ;
56
61
57
- if let Some ( settings) = Self :: request (
58
- client,
59
- socket,
60
- buf,
61
- offer. server_ip . unwrap ( ) ,
62
- offer. ip ,
63
- true ,
64
- Duration :: from_secs ( 3 ) ,
65
- 3 ,
66
- )
67
- . await ?
68
62
{
69
- break Ok ( (
70
- Self {
71
- ip : settings. ip ,
72
- server_ip : settings. server_ip . unwrap ( ) ,
73
- duration : Duration :: from_secs ( settings. lease_time_secs . unwrap_or ( 7200 ) as _ ) ,
74
- acquired : now,
75
- } ,
76
- NetworkInfo {
77
- gateway : settings. gateway ,
78
- subnet : settings. subnet ,
79
- dns1 : settings. dns1 ,
80
- dns2 : settings. dns2 ,
81
- } ,
82
- ) ) ;
63
+ // Nasty but necessary to avoid Rust's borrow checker not dealing
64
+ // with the non-lexical lifetimes involved here
65
+ let buf = unsafe { Self :: unsafe_reborrow ( buf) } ;
66
+
67
+ if let Some ( settings) = Self :: request (
68
+ client,
69
+ socket,
70
+ buf,
71
+ server_ip,
72
+ ip,
73
+ true ,
74
+ Duration :: from_secs ( 3 ) ,
75
+ 3 ,
76
+ )
77
+ . await ?
78
+ {
79
+ break Ok ( (
80
+ Self {
81
+ ip : settings. ip ,
82
+ server_ip : settings. server_ip . unwrap ( ) ,
83
+ duration : Duration :: from_secs (
84
+ settings. lease_time_secs . unwrap_or ( 7200 ) as _
85
+ ) ,
86
+ acquired : now,
87
+ } ,
88
+ NetworkInfo {
89
+ gateway : settings. gateway ,
90
+ subnet : settings. subnet ,
91
+ dns1 : settings. dns1 ,
92
+ dns2 : settings. dns2 ,
93
+ captive_url : settings. captive_url ,
94
+ } ,
95
+ ) ) ;
96
+ }
83
97
}
84
98
}
85
99
}
@@ -173,12 +187,12 @@ impl Lease {
173
187
Ok ( ( ) )
174
188
}
175
189
176
- async fn discover < T , S > (
190
+ async fn discover < ' a , T , S > (
177
191
client : & mut dhcp:: client:: Client < T > ,
178
192
socket : & mut S ,
179
- buf : & mut [ u8 ] ,
193
+ buf : & ' a mut [ u8 ] ,
180
194
timeout : Duration ,
181
- ) -> Result < Settings , Error < S :: Error > >
195
+ ) -> Result < Settings < ' a > , Error < S :: Error > >
182
196
where
183
197
T : RngCore ,
184
198
S : UdpReceive + UdpSend ,
@@ -203,11 +217,15 @@ impl Lease {
203
217
204
218
if let Either :: First ( result) = select ( socket. receive ( buf) , Timer :: after ( timeout) ) . await
205
219
{
220
+ // Nasty but necessary to avoid Rust's borrow checker not dealing
221
+ // with the non-lexical lifetimes involved here
222
+ let buf = unsafe { Self :: unsafe_reborrow ( buf) } ;
223
+
206
224
let ( len, _remote) = result. map_err ( Error :: Io ) ?;
207
225
let reply = Packet :: decode ( & buf[ ..len] ) ?;
208
226
209
227
if client. is_offer ( & reply, xid) {
210
- let settings: Settings = ( & reply) . into ( ) ;
228
+ let settings = Settings :: new ( & reply) ;
211
229
212
230
info ! (
213
231
"IP {} offered by DHCP server {}" ,
@@ -224,16 +242,16 @@ impl Lease {
224
242
}
225
243
226
244
#[ allow( clippy:: too_many_arguments) ]
227
- async fn request < T , S > (
245
+ async fn request < ' a , T , S > (
228
246
client : & mut dhcp:: client:: Client < T > ,
229
247
socket : & mut S ,
230
- buf : & mut [ u8 ] ,
248
+ buf : & ' a mut [ u8 ] ,
231
249
server_ip : Ipv4Addr ,
232
250
ip : Ipv4Addr ,
233
251
broadcast : bool ,
234
252
timeout : Duration ,
235
253
retries : usize ,
236
- ) -> Result < Option < Settings > , Error < S :: Error > >
254
+ ) -> Result < Option < Settings < ' a > > , Error < S :: Error > >
237
255
where
238
256
T : RngCore ,
239
257
S : UdpReceive + UdpSend ,
@@ -270,12 +288,17 @@ impl Lease {
270
288
if let Either :: First ( result) = select ( socket. receive ( buf) , Timer :: after ( timeout) ) . await
271
289
{
272
290
let ( len, _remote) = result. map_err ( Error :: Io ) ?;
291
+
292
+ // Nasty but necessary to avoid Rust's borrow checker not dealing
293
+ // with the non-lexical lifetimes involved here
294
+ let buf = unsafe { Self :: unsafe_reborrow ( buf) } ;
295
+
273
296
let packet = & buf[ ..len] ;
274
297
275
298
let reply = Packet :: decode ( packet) ?;
276
299
277
300
if client. is_ack ( & reply, xid) {
278
- let settings = ( & reply) . into ( ) ;
301
+ let settings = Settings :: new ( & reply) ;
279
302
280
303
info ! ( "IP {} leased successfully" , ip) ;
281
304
@@ -292,4 +315,11 @@ impl Lease {
292
315
293
316
Ok ( None )
294
317
}
318
+
319
+ // Useful when Rust's borrow-checker still cannot handle some NLLs
320
+ // https://rust-lang.github.io/rfcs/2094-nll.html
321
+ unsafe fn unsafe_reborrow < ' a > ( buf : & mut [ u8 ] ) -> & ' a mut [ u8 ] {
322
+ let len = buf. len ( ) ;
323
+ unsafe { core:: slice:: from_raw_parts_mut ( buf. as_mut_ptr ( ) , len) }
324
+ }
295
325
}
0 commit comments