xref: /aosp_15_r20/external/crosvm/third_party/libslirp-rs/src/context.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1 // Documentation for code maintainers:
2 //
3 // Closure pointers as *c_void
4 // -----------------
5 // This file interfaces with Slirp's callbacks extensively. As part of that, it passes Rust closures
6 // to callbacks as opaque data, and those closures are executed during a call into Slirp; in other
7 // words, the sequence of events looks like this:
8 //    1. Rust creates a closure C.
9 //    2. Rust calls Slirp and gives it callback CB (a Rust func.), and opaque data that contains C.
10 //    3. (0...n times) CB runs and unpacks C from the opaque data. a. CB calls C.
11 //    4. The call from #2 completes.
12 // Closures are represented as trait objects, and trait object references are wide/fat pointers
13 // (2x machine pointer size) that contain pointers to the closure's struct & its vtable. Since wide
14 // pointers are obviously too large to fit into a *mut c_void (this is the opaque data), we cannot
15 // pass them directly. Luckily, wide pointers themselves are simple sized data structures, so we can
16 // pass a reference to the wide pointer as a *mut c_void; in other words, the way to pass a closure
17 // is to cast &mut &mut some_closure into a *mut c_void. We can then unpack this easily and call
18 // the closure.
19 //
20 // Why is CallbackHandler involved in the outbound (guest -> host) packet path?
21 // ----------------------------------------------------------------------------
22 // In short, ownership. Since the CallbackHandler is responsible for writing to the guest, it must
23 // own the connection/stream that is attached to the guest. Because CallbackHandler owns the
24 // connection, it would be significantly complicated to have any other entity read from the
25 // connection.
26 //
27 // Safety assumptions
28 // ------------------
29 // Most statements explaining the safety of unsafe code depend on libslirp behaving in a safe
30 // & expected manner. Given that libslirp is has experienced CVEs related to safety problems,
31 // these statements should be taken with a grain of salt. Consumers of this library are STRONGLY
32 // RECOMMENDED to run this code in a separate process with strong sandboxing.
33 
34 // Some bindings of the libslirp API are used, but we want to keep them for completeness
35 #![allow(dead_code)]
36 
37 use std::ffi::CStr;
38 use std::ffi::CString;
39 use std::fmt;
40 use std::io;
41 use std::net::Ipv4Addr;
42 use std::net::Ipv6Addr;
43 use std::ops;
44 use std::os::raw::c_char;
45 use std::os::raw::c_int;
46 use std::os::raw::c_void;
47 use std::slice;
48 use std::str;
49 
50 use base::error;
51 use base::RawDescriptor;
52 use libslirp_sys::*;
53 
54 use crate::slirp::SlirpError;
55 use crate::Error;
56 use crate::Result;
57 
58 /// An instance of libslirp is represented by a Context, which provides methods that consumers use
59 /// to interact with Slirp. The Context is also where consumers register their CallbackHandler,
60 /// which provides required functions to libslirp, and allows libslirp to communicate back to the
61 /// consumer. The Context is intended to be used from an event loop which handles polling for IO
62 /// from the guest and host (see `Context.pollfds_fill`, `Context.pollfds_poll`, and
63 /// `Context.handle_guest_input`).
64 ///
65 /// Example data flow for an outbound packet:
66 /// 1. Context `ctx` created with CallbackHandler `h`. An event loop (henceforth the slirp loop) is
67 ///    started, which polls for packets from the guest, and from the outside world (sockets).
68 /// 2. Guest emits an ethernet frame. The consumer makes this frame available through their
69 ///    implementation of `h.read_from_guest`.
70 /// 3. The slirp loop is notified there is a packet from the guest, and invokes
71 ///    `ctx.handle_guest_input`. `ctx.handle_guest_input` reads all currently available packets
72 ///    using `h.read_from_guest` & returns back to the slirp loop.
73 ///
74 /// Example data flow for an inbound packet:
75 /// 1. Same as above.
76 /// 2. An ethernet frame arrives to the host, and gets demuxed by the host kernel into one of the
77 ///    host sockets opened by libslirp.
78 /// 3. The slirp loop receives a notification that data has arrived on one of the libslirp sockets,
79 ///    and invokes `ctx.pollfds_poll` to notify libslirp. a. libslirp calls into `h.send_packet` to
80 ///    deliver the packet to the consumer.
81 pub struct Context<H> {
82     slirp: *mut Slirp,
83     callbacks: SlirpCb,
84     callback_handler: H,
85 }
86 
87 impl<H> Drop for Context<H> {
drop(&mut self)88     fn drop(&mut self) {
89         if !self.slirp.is_null() {
90             // SAFETY:
91             // Safe because self.context is guaranteed to be valid or null upon construction.
92             unsafe {
93                 slirp_cleanup(self.slirp);
94             }
95         }
96     }
97 }
98 
99 /// `CallbackHandler` is the safe Rust interface for the Slirp callbacks. Consumers of Slirp MUST
100 /// implement this interface to handle the required callbacks from Slirp.
101 ///
102 /// ## Notes about timers
103 /// To send NDP router advertisements on IPv6, libslirp uses a timer. If IPv6 support is not
104 /// needed, the timer callbacks can be left unimplemented.
105 ///
106 /// Example data flow for timer creation/modification (`timer_new`/`timer_mod`/`timer_free`):
107 /// 1. libslirp calls into `timer_new` to request a new timer. `timer_new` creates some entity to
108 ///    represent the timer and boxes it. A pointer to that boxed entity is returned to libslirp, and
109 ///    is how libslirp will refer to the timer in the future.
110 /// 2. The timer's expire time can be changed when timer_mod is called by libslirp. A pointer to the
111 ///    boxed timer is passed in by libslirp.
112 /// 3. The implementor of `CallbackHandler` is responsible for ensuring that the timer's callback as
113 ///    provided in `timer_new` is invoked at/after the `expire_time`.
114 /// 4. libslirp will free timers using `timer_free` when `slirp_cleanup` runs.
115 ///
116 /// libslirp never does anything with the timer pointer beyond passing it to/from the the functions
117 /// in `CallbackHandler`.
118 pub trait CallbackHandler {
119     type Timer;
120 
121     /// Returns a timestamp in nanoseconds relative to the moment that this instance of libslirp
122     /// started running.
clock_get_ns(&mut self) -> i64123     fn clock_get_ns(&mut self) -> i64;
124 
send_packet(&mut self, buf: &[u8]) -> io::Result<usize>125     fn send_packet(&mut self, buf: &[u8]) -> io::Result<usize>;
126 
127     /// Gets an iterator of timers (as raw descriptors) so they can be awaited with a suitable
128     /// polling function as part of libslirp's main consumer loop.
get_timers<'a>(&'a self) -> Box<dyn Iterator<Item = &RawDescriptor> + 'a>129     fn get_timers<'a>(&'a self) -> Box<dyn Iterator<Item = &RawDescriptor> + 'a>;
130 
131     /// Runs the handler function for a specific timer.
execute_timer(&mut self, timer: RawDescriptor)132     fn execute_timer(&mut self, timer: RawDescriptor);
133 
134     // Normally in crosvm we refer to FDs as descriptors, because FDs are platform specific;
135     // however, this interface is very close to the libslirp FFI, and libslirp follows the Linux
136     // philosophy of everything is an FD. Since even Windows refers to FDs in WSAPoll, keeping FD
137     // as a concept here helps keep terminology consistent between crosvm code interfacing with
138     // libslirp, and libslirp itself.
register_poll_fd(&mut self, fd: i32)139     fn register_poll_fd(&mut self, fd: i32);
unregister_poll_fd(&mut self, fd: i32)140     fn unregister_poll_fd(&mut self, fd: i32);
141 
guest_error(&mut self, msg: &str)142     fn guest_error(&mut self, msg: &str);
143 
notify(&mut self)144     fn notify(&mut self);
145 
timer_new(&mut self, callback: Box<dyn FnMut()>) -> Box<Self::Timer>146     fn timer_new(&mut self, callback: Box<dyn FnMut()>) -> Box<Self::Timer>;
147 
148     /// Sets a timer to expire in expire_time_ms - (clock_get_ns() (as ms).
timer_mod(&mut self, timer: &mut Self::Timer, expire_time: i64)149     fn timer_mod(&mut self, timer: &mut Self::Timer, expire_time: i64);
150 
timer_free(&mut self, timer: Box<Self::Timer>)151     fn timer_free(&mut self, timer: Box<Self::Timer>);
152 
begin_read_from_guest(&mut self) -> io::Result<()>153     fn begin_read_from_guest(&mut self) -> io::Result<()>;
154 
end_read_from_guest(&mut self) -> io::Result<&[u8]>155     fn end_read_from_guest(&mut self) -> io::Result<&[u8]>;
156 }
157 
write_handler_callback(buf: *const c_void, len: usize, opaque: *mut c_void) -> isize158 extern "C" fn write_handler_callback(buf: *const c_void, len: usize, opaque: *mut c_void) -> isize {
159     // SAFETY:
160     // Safe because we pass in opaque as exactly this type.
161     let closure = unsafe { &mut *(opaque as *mut &mut dyn FnMut(&[u8]) -> isize) };
162 
163     // SAFETY:
164     // Safe because libslirp provides us with a valid buffer & that buffer's length.
165     let slice = unsafe { slice::from_raw_parts(buf as *const u8, len) };
166 
167     closure(slice)
168 }
169 
read_handler_callback(buf: *mut c_void, len: usize, opaque: *mut c_void) -> isize170 extern "C" fn read_handler_callback(buf: *mut c_void, len: usize, opaque: *mut c_void) -> isize {
171     // SAFETY:
172     // Safe because we pass in opaque as exactly this type.
173     let closure = unsafe { &mut *(opaque as *mut &mut dyn FnMut(&mut [u8]) -> isize) };
174 
175     // SAFETY:
176     // Safe because libslirp provides us with a valid buffer & that buffer's length.
177     let slice = unsafe { slice::from_raw_parts_mut(buf as *mut u8, len) };
178 
179     closure(slice)
180 }
181 
182 /// Represents poll events in libslirp's format (e.g. `struct pollfd.[r]events`).
183 #[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord)]
184 pub struct PollEvents(usize);
185 
186 impl PollEvents {
empty() -> Self187     pub fn empty() -> Self {
188         PollEvents(0)
189     }
poll_in() -> Self190     pub fn poll_in() -> Self {
191         PollEvents(SLIRP_POLL_IN as usize)
192     }
poll_out() -> Self193     pub fn poll_out() -> Self {
194         PollEvents(SLIRP_POLL_OUT as usize)
195     }
poll_pri() -> Self196     pub fn poll_pri() -> Self {
197         PollEvents(SLIRP_POLL_PRI as usize)
198     }
poll_err() -> Self199     pub fn poll_err() -> Self {
200         PollEvents(SLIRP_POLL_ERR as usize)
201     }
poll_hup() -> Self202     pub fn poll_hup() -> Self {
203         PollEvents(SLIRP_POLL_HUP as usize)
204     }
contains<T: Into<Self>>(&self, other: T) -> bool205     pub fn contains<T: Into<Self>>(&self, other: T) -> bool {
206         let other = other.into();
207         (*self & other) == other
208     }
is_empty(&self) -> bool209     pub fn is_empty(&self) -> bool {
210         self.0 == 0
211     }
has_in(&self) -> bool212     pub fn has_in(&self) -> bool {
213         self.contains(PollEvents::poll_in())
214     }
has_out(&self) -> bool215     pub fn has_out(&self) -> bool {
216         self.contains(PollEvents::poll_out())
217     }
has_pri(&self) -> bool218     pub fn has_pri(&self) -> bool {
219         self.contains(PollEvents::poll_pri())
220     }
has_err(&self) -> bool221     pub fn has_err(&self) -> bool {
222         self.contains(PollEvents::poll_err())
223     }
has_hup(&self) -> bool224     pub fn has_hup(&self) -> bool {
225         self.contains(PollEvents::poll_hup())
226     }
227 }
228 
229 impl<T: Into<PollEvents>> ops::BitAnd<T> for PollEvents {
230     type Output = PollEvents;
231 
bitand(self, other: T) -> PollEvents232     fn bitand(self, other: T) -> PollEvents {
233         PollEvents(self.0 & other.into().0)
234     }
235 }
236 
237 impl<T: Into<PollEvents>> ops::BitOr<T> for PollEvents {
238     type Output = PollEvents;
239 
bitor(self, other: T) -> PollEvents240     fn bitor(self, other: T) -> PollEvents {
241         PollEvents(self.0 | other.into().0)
242     }
243 }
244 
245 impl<T: Into<PollEvents>> ops::BitOrAssign<T> for PollEvents {
bitor_assign(&mut self, other: T)246     fn bitor_assign(&mut self, other: T) {
247         self.0 |= other.into().0;
248     }
249 }
250 
251 impl fmt::Debug for PollEvents {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result252     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
253         let mut one = false;
254         let flags = [
255             (PollEvents(SLIRP_POLL_IN as usize), "IN"),
256             (PollEvents(SLIRP_POLL_OUT as usize), "OUT"),
257             (PollEvents(SLIRP_POLL_PRI as usize), "PRI"),
258             (PollEvents(SLIRP_POLL_ERR as usize), "ERR"),
259             (PollEvents(SLIRP_POLL_HUP as usize), "HUP"),
260         ];
261 
262         for &(flag, msg) in &flags {
263             if self.contains(flag) {
264                 if one {
265                     write!(fmt, " | ")?
266                 }
267                 write!(fmt, "{}", msg)?;
268 
269                 one = true
270             }
271         }
272 
273         if !one {
274             fmt.write_str("(empty)")?;
275         }
276 
277         Ok(())
278     }
279 }
280 
add_poll_handler_callback(fd: c_int, events: c_int, opaque: *mut c_void) -> c_int281 extern "C" fn add_poll_handler_callback(fd: c_int, events: c_int, opaque: *mut c_void) -> c_int {
282     // SAFETY:
283     // Safe because we pass in opaque as exactly this type.
284     let closure = unsafe { &mut *(opaque as *mut &mut dyn FnMut(i32, PollEvents) -> i32) };
285 
286     closure(fd, PollEvents(events as usize))
287 }
288 
get_revents_handler_callback(idx: c_int, opaque: *mut c_void) -> c_int289 extern "C" fn get_revents_handler_callback(idx: c_int, opaque: *mut c_void) -> c_int {
290     // SAFETY:
291     // Safe because we pass in opaque as exactly this type.
292     let closure = unsafe { &mut *(opaque as *mut &mut dyn FnMut(i32) -> PollEvents) };
293 
294     closure(idx).0 as c_int
295 }
296 
297 /// Inbound packets from libslirp are delivered to this handler, which passes them on to the
298 /// Context's CallbackHandler for forwarding to the guest.
send_packet_handler<H: CallbackHandler>( buf: *const c_void, len: usize, opaque: *mut c_void, ) -> isize299 extern "C" fn send_packet_handler<H: CallbackHandler>(
300     buf: *const c_void,
301     len: usize,
302     opaque: *mut c_void,
303 ) -> isize {
304     // SAFETY:
305     // Safe because libslirp gives us a valid buffer & that buffer's length.
306     let slice = unsafe { slice::from_raw_parts(buf as *const u8, len) };
307 
308     // SAFETY:
309     // Safe because we pass in opaque as exactly this type when constructing the Slirp object.
310     let res = unsafe {
311         (*(opaque as *mut Context<H>))
312             .callback_handler
313             .send_packet(slice)
314     };
315 
316     match res {
317         Ok(res) => res as isize,
318         Err(e) => {
319             error!("send_packet error: {}", e);
320             -1
321         }
322     }
323 }
324 
guest_error_handler<H: CallbackHandler>(msg: *const c_char, opaque: *mut c_void)325 extern "C" fn guest_error_handler<H: CallbackHandler>(msg: *const c_char, opaque: *mut c_void) {
326     // SAFETY:
327     // Safe because libslirp gives us a valid C string representing the error message.
328     let msg = str::from_utf8(unsafe { CStr::from_ptr(msg) }.to_bytes()).unwrap_or("");
329 
330     // SAFETY:
331     // Safe because we pass in opaque as exactly this type when constructing the Slirp object.
332     unsafe {
333         (*(opaque as *mut Context<H>))
334             .callback_handler
335             .guest_error(msg)
336     }
337 }
338 
clock_get_ns_handler<H: CallbackHandler>(opaque: *mut c_void) -> i64339 extern "C" fn clock_get_ns_handler<H: CallbackHandler>(opaque: *mut c_void) -> i64 {
340     // SAFETY:
341     // Safe because we pass in opaque as exactly this type when constructing the Slirp object.
342     unsafe {
343         (*(opaque as *mut Context<H>))
344             .callback_handler
345             .clock_get_ns()
346     }
347 }
348 
timer_new_handler<H: CallbackHandler>( cb: SlirpTimerCb, cb_opaque: *mut c_void, opaque: *mut c_void, ) -> *mut c_void349 extern "C" fn timer_new_handler<H: CallbackHandler>(
350     cb: SlirpTimerCb,
351     cb_opaque: *mut c_void,
352     opaque: *mut c_void,
353 ) -> *mut c_void {
354     let callback = Box::new(move || {
355         if let Some(cb) = cb {
356             // SAFETY:
357             // Safe because libslirp gives us a valid callback function to call.
358             unsafe {
359                 cb(cb_opaque);
360             }
361         }
362     });
363 
364     // SAFETY:
365     // Safe because we pass in opaque as exactly this type when constructing the Slirp object.
366     let timer = unsafe {
367         (*(opaque as *mut Context<H>))
368             .callback_handler
369             .timer_new(callback)
370     };
371 
372     Box::into_raw(timer) as *mut c_void
373 }
374 
timer_free_handler<H: CallbackHandler>(timer: *mut c_void, opaque: *mut c_void)375 extern "C" fn timer_free_handler<H: CallbackHandler>(timer: *mut c_void, opaque: *mut c_void) {
376     // SAFETY:
377     // Safe because we pass in opaque as exactly this type when constructing the Slirp object.
378     // Also, timer was created by us as exactly the type we unpack into.
379     unsafe {
380         let timer = Box::from_raw(timer as *mut H::Timer);
381         (*(opaque as *mut Context<H>))
382             .callback_handler
383             .timer_free(timer);
384     }
385 }
386 
timer_mod_handler<H: CallbackHandler>( timer: *mut c_void, expire_time: i64, opaque: *mut c_void, )387 extern "C" fn timer_mod_handler<H: CallbackHandler>(
388     timer: *mut c_void,
389     expire_time: i64,
390     opaque: *mut c_void,
391 ) {
392     // SAFETY:
393     // Safe because:
394     // 1. We pass in opaque as exactly this type when constructing the Slirp object.
395     // 2. timer was created by us as exactly the type we unpack into
396     // 3. libslirp is responsible for freeing timer, so forgetting about it is safe.
397     unsafe {
398         let mut timer = Box::from_raw(timer as *mut H::Timer);
399         (*(opaque as *mut Context<H>))
400             .callback_handler
401             .timer_mod(&mut timer, expire_time);
402         Box::into_raw(timer);
403     }
404 }
405 
register_poll_fd_handler<H: CallbackHandler>(fd: c_int, opaque: *mut c_void)406 extern "C" fn register_poll_fd_handler<H: CallbackHandler>(fd: c_int, opaque: *mut c_void) {
407     // SAFETY:
408     // Safe because we pass in opaque as exactly this type when constructing the Slirp object.
409     unsafe {
410         (*(opaque as *mut Context<H>))
411             .callback_handler
412             .register_poll_fd(fd)
413     }
414 }
415 
unregister_poll_fd_handler<H: CallbackHandler>(fd: c_int, opaque: *mut c_void)416 extern "C" fn unregister_poll_fd_handler<H: CallbackHandler>(fd: c_int, opaque: *mut c_void) {
417     // SAFETY:
418     // Safe because we pass in opaque as exactly this type when constructing the Slirp object.
419     unsafe {
420         (*(opaque as *mut Context<H>))
421             .callback_handler
422             .unregister_poll_fd(fd)
423     }
424 }
425 
notify_handler<H: CallbackHandler>(opaque: *mut c_void)426 extern "C" fn notify_handler<H: CallbackHandler>(opaque: *mut c_void) {
427     // SAFETY:
428     // Safe because we pass in opaque as exactly this type when constructing the Slirp object.
429     unsafe { (*(opaque as *mut Context<H>)).callback_handler.notify() }
430 }
431 
432 impl<H: CallbackHandler> Context<H> {
433     /// Create a new instance of the libslirp context.
434     ///
435     /// The parameters which are prefixed by "host" refer to the system on which libslirp runs;
436     /// for example, host_v4_address is the IP address of the host system that the guest will be
437     /// able to connect to.
438     ///
439     /// `host_v[4|6]_address` maps to the host's local loopback interface.
440     /// `dns_server_` options configure the DNS server provided on the virtual network by libslirp.
new( disable_access_to_host: bool, ipv4_enabled: bool, virtual_network_v4_address: Ipv4Addr, virtual_network_v4_mask: Ipv4Addr, host_v4_address: Ipv4Addr, ipv6_enabled: bool, virtual_network_v6_address: Ipv6Addr, virtual_network_v6_prefix_len: u8, host_v6_address: Ipv6Addr, host_hostname: Option<String>, dhcp_start_addr: Ipv4Addr, dns_server_v4_addr: Ipv4Addr, dns_server_v6_addr: Ipv6Addr, virtual_network_dns_search_domains: Vec<String>, dns_server_domain_name: Option<String>, callback_handler: H, ) -> Result<Box<Context<H>>>441     pub fn new(
442         disable_access_to_host: bool,
443         ipv4_enabled: bool,
444         virtual_network_v4_address: Ipv4Addr,
445         virtual_network_v4_mask: Ipv4Addr,
446         host_v4_address: Ipv4Addr,
447         ipv6_enabled: bool,
448         virtual_network_v6_address: Ipv6Addr,
449         virtual_network_v6_prefix_len: u8,
450         host_v6_address: Ipv6Addr,
451         host_hostname: Option<String>,
452         dhcp_start_addr: Ipv4Addr,
453         dns_server_v4_addr: Ipv4Addr,
454         dns_server_v6_addr: Ipv6Addr,
455         virtual_network_dns_search_domains: Vec<String>,
456         dns_server_domain_name: Option<String>,
457         callback_handler: H,
458     ) -> Result<Box<Context<H>>> {
459         let mut ret = Box::new(Context {
460             slirp: std::ptr::null_mut(),
461             callbacks: SlirpCb {
462                 send_packet: Some(send_packet_handler::<H>),
463                 guest_error: Some(guest_error_handler::<H>),
464                 clock_get_ns: Some(clock_get_ns_handler::<H>),
465                 timer_new: Some(timer_new_handler::<H>),
466                 timer_free: Some(timer_free_handler::<H>),
467                 timer_mod: Some(timer_mod_handler::<H>),
468                 register_poll_fd: Some(register_poll_fd_handler::<H>),
469                 unregister_poll_fd: Some(unregister_poll_fd_handler::<H>),
470                 notify: Some(notify_handler::<H>),
471             },
472             callback_handler,
473         });
474 
475         let cstr_dns_search: Vec<_> = virtual_network_dns_search_domains
476             .iter()
477             .map(|arg| CString::new(arg.clone().into_bytes()).unwrap())
478             .collect();
479         let mut p_dns_search: Vec<_> = cstr_dns_search.iter().map(|arg| arg.as_ptr()).collect();
480         p_dns_search.push(std::ptr::null());
481 
482         let host_hostname = host_hostname.and_then(|s| CString::new(s).ok());
483         let dns_server_domain_name = dns_server_domain_name.and_then(|s| CString::new(s).ok());
484         let rust_context_ptr = &*ret as *const _ as *mut _;
485 
486         let as_ptr = |p: &Option<CString>| p.as_ref().map_or(std::ptr::null(), |s| s.as_ptr());
487 
488         let slirp_config = SlirpConfig {
489             version: 1,
490             restricted: 0,
491             disable_dhcp: false,
492             in_enabled: ipv4_enabled,
493             vnetwork: virtual_network_v4_address.into(),
494             vnetmask: virtual_network_v4_mask.into(),
495             vhost: host_v4_address.into(),
496             in6_enabled: ipv6_enabled,
497             vprefix_addr6: virtual_network_v6_address.into(),
498             vprefix_len: virtual_network_v6_prefix_len,
499             vhost6: host_v6_address.into(),
500             vhostname: as_ptr(&host_hostname),
501             tftp_server_name: std::ptr::null(),
502             tftp_path: std::ptr::null(),
503             bootfile: std::ptr::null(),
504             vdhcp_start: dhcp_start_addr.into(),
505             vnameserver: dns_server_v4_addr.into(),
506             vnameserver6: dns_server_v6_addr.into(),
507             vdnssearch: p_dns_search.as_ptr() as *mut *const _,
508             vdomainname: as_ptr(&dns_server_domain_name),
509             if_mtu: 0,
510             if_mru: 0,
511             disable_host_loopback: disable_access_to_host,
512             enable_emu: false,
513             outbound_addr: std::ptr::null(),
514             outbound_addr6: std::ptr::null(),
515             disable_dns: false,
516         };
517 
518         // SAFETY:
519         // Safe because we pass valid pointers (or null as appropriate) as parameters and we check
520         // that the return value is valid.
521         let slirp = unsafe {
522             slirp_new(
523                 &slirp_config,
524                 &ret.callbacks,
525                 // This value is passed to callbacks as opaque data, which allows those callbacks
526                 // to get access to the Context struct. It allows them to invoke the appropriate
527                 // methods on the CallbackHandler to notify it about new packets, get data about
528                 // sockets that are ready for reading, etc.
529                 rust_context_ptr,
530             )
531         };
532         assert!(!slirp.is_null());
533         match ret.callback_handler.begin_read_from_guest() {
534             Err(e) if e.kind() == std::io::ErrorKind::BrokenPipe => {
535                 return Err(Error::Slirp(SlirpError::BrokenPipe(e)));
536             }
537             Err(e) => {
538                 return Err(Error::Slirp(SlirpError::OverlappedError(e)));
539             }
540             _ => {}
541         }
542         ret.slirp = slirp;
543         Ok(ret)
544     }
545 
546     /// Reads from the guest & injects into Slirp. This method reads until an error is encountered
547     /// or io::ErrorKind::WouldBlock is returned by the callback_handler's read_from_guest.
handle_guest_input(&mut self) -> Result<()>548     pub fn handle_guest_input(&mut self) -> Result<()> {
549         loop {
550             match self.callback_handler.end_read_from_guest() {
551                 Ok(ethernet_frame) => {
552                     // SAFETY:
553                     // Safe because the buffer (ethernet_frame) is valid & libslirp is provided
554                     // with the data's underlying length.
555                     unsafe {
556                         slirp_input(
557                             self.slirp,
558                             ethernet_frame.as_ptr(),
559                             ethernet_frame.len() as i32,
560                         );
561                     }
562                 }
563                 Err(e) if e.kind() == std::io::ErrorKind::InvalidData => {
564                     error!("error reading packet from guest: {}", e);
565                 }
566                 Err(e) if e.kind() == std::io::ErrorKind::WouldBlock => {
567                     // No packets are available. Yield back to the Slirp loop.
568                     break;
569                 }
570                 Err(e) if e.kind() == std::io::ErrorKind::BrokenPipe => {
571                     return Err(Error::Slirp(SlirpError::BrokenPipe(e)));
572                 }
573                 Err(_) => {
574                     match self.callback_handler.begin_read_from_guest() {
575                         Err(e) if e.kind() == std::io::ErrorKind::BrokenPipe => {
576                             return Err(Error::Slirp(SlirpError::BrokenPipe(e)));
577                         }
578                         Err(e) => {
579                             return Err(Error::Slirp(SlirpError::OverlappedError(e)));
580                         }
581                         _ => {}
582                     }
583                     break;
584                 }
585             }
586             match self.callback_handler.begin_read_from_guest() {
587                 Err(e) if e.kind() == std::io::ErrorKind::BrokenPipe => {
588                     return Err(Error::Slirp(SlirpError::BrokenPipe(e)));
589                 }
590                 Err(e) => {
591                     return Err(Error::Slirp(SlirpError::OverlappedError(e)));
592                 }
593                 _ => {}
594             }
595         }
596         Ok(())
597     }
598 
connection_info(&mut self) -> &str599     pub fn connection_info(&mut self) -> &str {
600         str::from_utf8(
601             // TODO(b/315998194): Add safety comment
602             #[allow(clippy::undocumented_unsafe_blocks)]
603             unsafe { CStr::from_ptr(slirp_connection_info(self.slirp)) }.to_bytes(),
604         )
605         .unwrap_or("")
606     }
607 
608     /// Requests libslirp provide the set of sockets & events that should be polled for. These
609     /// sockets are provided to you by 0..n calls to `add_poll_cb`. `add_poll_cb` must return an
610     /// integer (henceforth the socket reference) which libslirp can use to later request the
611     /// revents that came from polling on that socket.
612     ///
613     /// The `timeout` value expresses how long (in ms) the consumer intends to wait (at most) when
614     /// it invokes the polling function. libslirp will overwrite this with the time that the
615     /// consumer should wait.
pollfds_fill<F>(&mut self, timeout: &mut u32, mut add_poll_cb: F) where F: FnMut(i32, PollEvents) -> i32,616     pub fn pollfds_fill<F>(&mut self, timeout: &mut u32, mut add_poll_cb: F)
617     where
618         F: FnMut(i32, PollEvents) -> i32,
619     {
620         let cb = &mut (&mut add_poll_cb as &mut dyn FnMut(i32, PollEvents) -> i32);
621         // SAFETY:
622         // Safe because cb is only used while slirp_pollfds_fill is running, and self.slirp is
623         // guaranteed to be valid.
624         unsafe {
625             slirp_pollfds_fill(
626                 self.slirp,
627                 timeout,
628                 Some(add_poll_handler_callback),
629                 cb as *mut _ as *mut c_void,
630             );
631         }
632     }
633 
634     /// Informs libslirp that polling has returned with some events on sockets that libslirp said
635     /// should be polled for when you called `pollfds_fill`. You provide the results of polling by
636     /// supplying `get_revents_cb`, which returns the `PollEvents` for each provided socket
637     /// reference. libslirp will call that function 0..n times to gather results from the polling
638     /// operation.
pollfds_poll<F>(&mut self, error: bool, mut get_revents_cb: F) where F: FnMut(i32) -> PollEvents,639     pub fn pollfds_poll<F>(&mut self, error: bool, mut get_revents_cb: F)
640     where
641         F: FnMut(i32) -> PollEvents,
642     {
643         let cb = &mut (&mut get_revents_cb as &mut dyn FnMut(i32) -> PollEvents);
644 
645         // SAFETY:
646         // Safe because cb is only used while slirp_pollfds_poll is running, and self.slirp is
647         // guaranteed to be valid.
648         unsafe {
649             slirp_pollfds_poll(
650                 self.slirp,
651                 error as i32,
652                 Some(get_revents_handler_callback),
653                 cb as *mut _ as *mut c_void,
654             );
655         }
656     }
657 
state_save<F>(&mut self, mut write_cb: F) where F: FnMut(&[u8]) -> isize,658     pub fn state_save<F>(&mut self, mut write_cb: F)
659     where
660         F: FnMut(&[u8]) -> isize,
661     {
662         let cb = &mut (&mut write_cb as &mut dyn FnMut(&[u8]) -> isize);
663         // SAFETY:
664         // Safe because cb is only used while state_save is running, and self.slirp is
665         // guaranteed to be valid.
666         unsafe {
667             slirp_state_save(
668                 self.slirp,
669                 Some(write_handler_callback),
670                 cb as *mut _ as *mut c_void,
671             );
672         }
673     }
674 
state_load<F>(&mut self, version_id: i32, mut read_cb: F) -> i32 where F: FnMut(&mut [u8]) -> isize,675     pub fn state_load<F>(&mut self, version_id: i32, mut read_cb: F) -> i32
676     where
677         F: FnMut(&mut [u8]) -> isize,
678     {
679         let cb = &mut (&mut read_cb as &mut dyn FnMut(&mut [u8]) -> isize);
680         // SAFETY:
681         // Safe because cb is only used while state_load is running, and self.slirp is
682         // guaranteed to be valid. While this function may fail, interpretation of the error code
683         // is the responsibility of the caller.
684         //
685         // TODO(nkgold): if state_load becomes used by crosvm, interpretation of the error code
686         // should occur here.
687         unsafe {
688             slirp_state_load(
689                 self.slirp,
690                 version_id,
691                 Some(read_handler_callback),
692                 cb as *mut _ as *mut c_void,
693             )
694         }
695     }
696 
get_timers<'a>(&'a self) -> Box<dyn Iterator<Item = &RawDescriptor> + 'a>697     pub fn get_timers<'a>(&'a self) -> Box<dyn Iterator<Item = &RawDescriptor> + 'a> {
698         self.callback_handler.get_timers()
699     }
700 
execute_timer(&mut self, timer: RawDescriptor)701     pub fn execute_timer(&mut self, timer: RawDescriptor) {
702         self.callback_handler.execute_timer(timer)
703     }
704 }
705