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.
11 // a. CB calls C.
12 // 4. The call from #2 completes.
13 // Closures are represented as trait objects, and trait object references are wide/fat pointers
14 // (2x machine pointer size) that contain pointers to the closure's struct & its vtable. Since wide
15 // pointers are obviously too large to fit into a *mut c_void (this is the opaque data), we cannot
16 // pass them directly. Luckily, wide pointers themselves are simple sized data structures, so we can
17 // pass a reference to the wide pointer as a *mut c_void; in other words, the way to pass a closure
18 // is to cast &mut &mut some_closure into a *mut c_void. We can then unpack this easily and call
19 // the closure.
20 //
21 // Why is CallbackHandler involved in the outbound (guest -> host) packet path?
22 // ----------------------------------------------------------------------------
23 // In short, ownership. Since the CallbackHandler is responsible for writing to the guest, it must
24 // own the connection/stream that is attached to the guest. Because CallbackHandler owns the
25 // connection, it would be significantly complicated to have any other entity read from the
26 // connection.
27 //
28 // Safety assumptions
29 // ------------------
30 // Most statements explaining the safety of unsafe code depend on libslirp behaving in a safe
31 // & expected manner. Given that libslirp is has experienced CVEs related to safety problems,
32 // these statements should be taken with a grain of salt. Consumers of this library are STRONGLY
33 // RECOMMENDED to run this code in a separate process with strong sandboxing.
34
35 // Some bindings of the libslirp API are used, but we want to keep them for completeness
36 #![allow(dead_code)]
37
38 use std::ffi::CStr;
39 use std::ffi::CString;
40 use std::fmt;
41 use std::io;
42 use std::net::Ipv4Addr;
43 use std::net::Ipv6Addr;
44 use std::ops;
45 use std::os::raw::c_char;
46 use std::os::raw::c_int;
47 use std::os::raw::c_void;
48 use std::slice;
49 use std::str;
50
51 use base::error;
52 use base::RawDescriptor;
53 use libslirp_sys::*;
54
55 use crate::slirp::SlirpError;
56 use crate::Error;
57 use crate::Result;
58
59 /// An instance of libslirp is represented by a Context, which provides methods that consumers use
60 /// to interact with Slirp. The Context is also where consumers register their CallbackHandler,
61 /// which provides required functions to libslirp, and allows libslirp to communicate back to the
62 /// consumer. The Context is intended to be used from an event loop which handles polling for IO
63 /// from the guest and host (see `Context.pollfds_fill`, `Context.pollfds_poll`, and
64 /// `Context.handle_guest_input`).
65 ///
66 /// Example data flow for an outbound packet:
67 /// 1. Context `ctx` created with CallbackHandler `h`. An event loop (henceforth the slirp loop) is
68 /// started, which polls for packets from the guest, and from the outside world (sockets).
69 /// 2. Guest emits an ethernet frame. The consumer makes this frame available through their
70 /// implementation of `h.read_from_guest`.
71 /// 3. The slirp loop is notified there is a packet from the guest, and invokes
72 /// `ctx.handle_guest_input`. `ctx.handle_guest_input` reads all currently available packets
73 /// using `h.read_from_guest` & returns back to the slirp loop.
74 ///
75 /// Example data flow for an inbound packet:
76 /// 1. Same as above.
77 /// 2. An ethernet frame arrives to the host, and gets demuxed by the host kernel into one of the
78 /// host sockets opened by libslirp.
79 /// 3. The slirp loop receives a notification that data has arrived on one of the libslirp sockets,
80 /// and invokes `ctx.pollfds_poll` to notify libslirp.
81 /// a. libslirp calls into `h.send_packet` to deliver the packet to the consumer.
82 pub struct Context<H> {
83 slirp: *mut Slirp,
84 callbacks: SlirpCb,
85 callback_handler: H,
86 }
87
88 impl<H> Drop for Context<H> {
drop(&mut self)89 fn drop(&mut self) {
90 // Safe because self.context is guaranteed to be valid or null upon construction.
91 if !self.slirp.is_null() {
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,
109 /// and 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 // Safe because we pass in opaque as exactly this type.
160 let closure = unsafe { &mut *(opaque as *mut &mut dyn FnMut(&[u8]) -> isize) };
161
162 // Safe because libslirp provides us with a valid buffer & that buffer's length.
163 let slice = unsafe { slice::from_raw_parts(buf as *const u8, len) };
164
165 closure(slice)
166 }
167
read_handler_callback(buf: *mut c_void, len: usize, opaque: *mut c_void) -> isize168 extern "C" fn read_handler_callback(buf: *mut c_void, len: usize, opaque: *mut c_void) -> isize {
169 // Safe because we pass in opaque as exactly this type.
170 let closure = unsafe { &mut *(opaque as *mut &mut dyn FnMut(&mut [u8]) -> isize) };
171
172 // Safe because libslirp provides us with a valid buffer & that buffer's length.
173 let slice = unsafe { slice::from_raw_parts_mut(buf as *mut u8, len) };
174
175 closure(slice)
176 }
177
178 /// Represents poll events in libslirp's format (e.g. `struct pollfd.[r]events`).
179 #[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord)]
180 pub struct PollEvents(usize);
181
182 impl PollEvents {
empty() -> Self183 pub fn empty() -> Self {
184 PollEvents(0)
185 }
poll_in() -> Self186 pub fn poll_in() -> Self {
187 PollEvents(SLIRP_POLL_IN as usize)
188 }
poll_out() -> Self189 pub fn poll_out() -> Self {
190 PollEvents(SLIRP_POLL_OUT as usize)
191 }
poll_pri() -> Self192 pub fn poll_pri() -> Self {
193 PollEvents(SLIRP_POLL_PRI as usize)
194 }
poll_err() -> Self195 pub fn poll_err() -> Self {
196 PollEvents(SLIRP_POLL_ERR as usize)
197 }
poll_hup() -> Self198 pub fn poll_hup() -> Self {
199 PollEvents(SLIRP_POLL_HUP as usize)
200 }
contains<T: Into<Self>>(&self, other: T) -> bool201 pub fn contains<T: Into<Self>>(&self, other: T) -> bool {
202 let other = other.into();
203 (*self & other) == other
204 }
is_empty(&self) -> bool205 pub fn is_empty(&self) -> bool {
206 self.0 == 0
207 }
has_in(&self) -> bool208 pub fn has_in(&self) -> bool {
209 self.contains(PollEvents::poll_in())
210 }
has_out(&self) -> bool211 pub fn has_out(&self) -> bool {
212 self.contains(PollEvents::poll_out())
213 }
has_pri(&self) -> bool214 pub fn has_pri(&self) -> bool {
215 self.contains(PollEvents::poll_pri())
216 }
has_err(&self) -> bool217 pub fn has_err(&self) -> bool {
218 self.contains(PollEvents::poll_err())
219 }
has_hup(&self) -> bool220 pub fn has_hup(&self) -> bool {
221 self.contains(PollEvents::poll_hup())
222 }
223 }
224
225 impl<T: Into<PollEvents>> ops::BitAnd<T> for PollEvents {
226 type Output = PollEvents;
227
bitand(self, other: T) -> PollEvents228 fn bitand(self, other: T) -> PollEvents {
229 PollEvents(self.0 & other.into().0)
230 }
231 }
232
233 impl<T: Into<PollEvents>> ops::BitOr<T> for PollEvents {
234 type Output = PollEvents;
235
bitor(self, other: T) -> PollEvents236 fn bitor(self, other: T) -> PollEvents {
237 PollEvents(self.0 | other.into().0)
238 }
239 }
240
241 impl<T: Into<PollEvents>> ops::BitOrAssign<T> for PollEvents {
bitor_assign(&mut self, other: T)242 fn bitor_assign(&mut self, other: T) {
243 self.0 |= other.into().0;
244 }
245 }
246
247 impl fmt::Debug for PollEvents {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result248 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
249 let mut one = false;
250 let flags = [
251 (PollEvents(SLIRP_POLL_IN as usize), "IN"),
252 (PollEvents(SLIRP_POLL_OUT as usize), "OUT"),
253 (PollEvents(SLIRP_POLL_PRI as usize), "PRI"),
254 (PollEvents(SLIRP_POLL_ERR as usize), "ERR"),
255 (PollEvents(SLIRP_POLL_HUP as usize), "HUP"),
256 ];
257
258 for &(flag, msg) in &flags {
259 if self.contains(flag) {
260 if one {
261 write!(fmt, " | ")?
262 }
263 write!(fmt, "{}", msg)?;
264
265 one = true
266 }
267 }
268
269 if !one {
270 fmt.write_str("(empty)")?;
271 }
272
273 Ok(())
274 }
275 }
276
add_poll_handler_callback(fd: c_int, events: c_int, opaque: *mut c_void) -> c_int277 extern "C" fn add_poll_handler_callback(fd: c_int, events: c_int, opaque: *mut c_void) -> c_int {
278 // Safe because we pass in opaque as exactly this type.
279 let closure = unsafe { &mut *(opaque as *mut &mut dyn FnMut(i32, PollEvents) -> i32) };
280
281 closure(fd, PollEvents(events as usize))
282 }
283
get_revents_handler_callback(idx: c_int, opaque: *mut c_void) -> c_int284 extern "C" fn get_revents_handler_callback(idx: c_int, opaque: *mut c_void) -> c_int {
285 // Safe because we pass in opaque as exactly this type.
286 let closure = unsafe { &mut *(opaque as *mut &mut dyn FnMut(i32) -> PollEvents) };
287
288 closure(idx).0 as c_int
289 }
290
291 /// Inbound packets from libslirp are delivered to this handler, which passes them on to the
292 /// Context's CallbackHandler for forwarding to the guest.
send_packet_handler<H: CallbackHandler>( buf: *const c_void, len: usize, opaque: *mut c_void, ) -> isize293 extern "C" fn send_packet_handler<H: CallbackHandler>(
294 buf: *const c_void,
295 len: usize,
296 opaque: *mut c_void,
297 ) -> isize {
298 // Safe because libslirp gives us a valid buffer & that buffer's length.
299 let slice = unsafe { slice::from_raw_parts(buf as *const u8, len) };
300
301 // Safe because we pass in opaque as exactly this type when constructing the Slirp object.
302 let res = unsafe {
303 (*(opaque as *mut Context<H>))
304 .callback_handler
305 .send_packet(slice)
306 };
307
308 match res {
309 Ok(res) => res as isize,
310 Err(e) => {
311 error!("send_packet error: {}", e);
312 -1
313 }
314 }
315 }
316
guest_error_handler<H: CallbackHandler>(msg: *const c_char, opaque: *mut c_void)317 extern "C" fn guest_error_handler<H: CallbackHandler>(msg: *const c_char, opaque: *mut c_void) {
318 // Safe because libslirp gives us a valid C string representing the error message.
319 let msg = str::from_utf8(unsafe { CStr::from_ptr(msg) }.to_bytes()).unwrap_or("");
320
321 // Safe because we pass in opaque as exactly this type when constructing the Slirp object.
322 unsafe {
323 (*(opaque as *mut Context<H>))
324 .callback_handler
325 .guest_error(msg)
326 }
327 }
328
clock_get_ns_handler<H: CallbackHandler>(opaque: *mut c_void) -> i64329 extern "C" fn clock_get_ns_handler<H: CallbackHandler>(opaque: *mut c_void) -> i64 {
330 // Safe because we pass in opaque as exactly this type when constructing the Slirp object.
331 unsafe {
332 (*(opaque as *mut Context<H>))
333 .callback_handler
334 .clock_get_ns()
335 }
336 }
337
timer_new_handler<H: CallbackHandler>( cb: SlirpTimerCb, cb_opaque: *mut c_void, opaque: *mut c_void, ) -> *mut c_void338 extern "C" fn timer_new_handler<H: CallbackHandler>(
339 cb: SlirpTimerCb,
340 cb_opaque: *mut c_void,
341 opaque: *mut c_void,
342 ) -> *mut c_void {
343 let callback = Box::new(move || {
344 if let Some(cb) = cb {
345 // Safe because libslirp gives us a valid callback function to call.
346 unsafe {
347 cb(cb_opaque);
348 }
349 }
350 });
351
352 // Safe because we pass in opaque as exactly this type when constructing the Slirp object.
353 let timer = unsafe {
354 (*(opaque as *mut Context<H>))
355 .callback_handler
356 .timer_new(callback)
357 };
358
359 Box::into_raw(timer) as *mut c_void
360 }
361
timer_free_handler<H: CallbackHandler>(timer: *mut c_void, opaque: *mut c_void)362 extern "C" fn timer_free_handler<H: CallbackHandler>(timer: *mut c_void, opaque: *mut c_void) {
363 // Safe because we pass in opaque as exactly this type when constructing the Slirp object.
364 // Also, timer was created by us as exactly the type we unpack into.
365 unsafe {
366 let timer = Box::from_raw(timer as *mut H::Timer);
367 (*(opaque as *mut Context<H>))
368 .callback_handler
369 .timer_free(timer);
370 }
371 }
372
timer_mod_handler<H: CallbackHandler>( timer: *mut c_void, expire_time: i64, opaque: *mut c_void, )373 extern "C" fn timer_mod_handler<H: CallbackHandler>(
374 timer: *mut c_void,
375 expire_time: i64,
376 opaque: *mut c_void,
377 ) {
378 // Safe because:
379 // 1. We pass in opaque as exactly this type when constructing the Slirp object.
380 // 2. timer was created by us as exactly the type we unpack into
381 // 3. libslirp is responsible for freeing timer, so forgetting about it is safe.
382 unsafe {
383 let mut timer = Box::from_raw(timer as *mut H::Timer);
384 (*(opaque as *mut Context<H>))
385 .callback_handler
386 .timer_mod(&mut timer, expire_time);
387 Box::into_raw(timer);
388 }
389 }
390
register_poll_fd_handler<H: CallbackHandler>(fd: c_int, opaque: *mut c_void)391 extern "C" fn register_poll_fd_handler<H: CallbackHandler>(fd: c_int, opaque: *mut c_void) {
392 // Safe because we pass in opaque as exactly this type when constructing the Slirp object.
393 unsafe {
394 (*(opaque as *mut Context<H>))
395 .callback_handler
396 .register_poll_fd(fd)
397 }
398 }
399
unregister_poll_fd_handler<H: CallbackHandler>(fd: c_int, opaque: *mut c_void)400 extern "C" fn unregister_poll_fd_handler<H: CallbackHandler>(fd: c_int, opaque: *mut c_void) {
401 // Safe because we pass in opaque as exactly this type when constructing the Slirp object.
402 unsafe {
403 (*(opaque as *mut Context<H>))
404 .callback_handler
405 .unregister_poll_fd(fd)
406 }
407 }
408
notify_handler<H: CallbackHandler>(opaque: *mut c_void)409 extern "C" fn notify_handler<H: CallbackHandler>(opaque: *mut c_void) {
410 // Safe because we pass in opaque as exactly this type when constructing the Slirp object.
411 unsafe { (*(opaque as *mut Context<H>)).callback_handler.notify() }
412 }
413
414 impl<H: CallbackHandler> Context<H> {
415 /// Create a new instance of the libslirp context.
416 ///
417 /// The parameters which are prefixed by "host" refer to the system on which libslirp runs;
418 /// for example, host_v4_address is the IP address of the host system that the guest will be
419 /// able to connect to.
420 ///
421 /// `host_v[4|6]_address` maps to the host's local loopback interface.
422 /// `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>>>423 pub fn new(
424 disable_access_to_host: bool,
425 ipv4_enabled: bool,
426 virtual_network_v4_address: Ipv4Addr,
427 virtual_network_v4_mask: Ipv4Addr,
428 host_v4_address: Ipv4Addr,
429 ipv6_enabled: bool,
430 virtual_network_v6_address: Ipv6Addr,
431 virtual_network_v6_prefix_len: u8,
432 host_v6_address: Ipv6Addr,
433 host_hostname: Option<String>,
434 dhcp_start_addr: Ipv4Addr,
435 dns_server_v4_addr: Ipv4Addr,
436 dns_server_v6_addr: Ipv6Addr,
437 virtual_network_dns_search_domains: Vec<String>,
438 dns_server_domain_name: Option<String>,
439 callback_handler: H,
440 ) -> Result<Box<Context<H>>> {
441 let mut ret = Box::new(Context {
442 slirp: std::ptr::null_mut(),
443 callbacks: SlirpCb {
444 send_packet: Some(send_packet_handler::<H>),
445 guest_error: Some(guest_error_handler::<H>),
446 clock_get_ns: Some(clock_get_ns_handler::<H>),
447 timer_new: Some(timer_new_handler::<H>),
448 timer_free: Some(timer_free_handler::<H>),
449 timer_mod: Some(timer_mod_handler::<H>),
450 register_poll_fd: Some(register_poll_fd_handler::<H>),
451 unregister_poll_fd: Some(unregister_poll_fd_handler::<H>),
452 notify: Some(notify_handler::<H>),
453 },
454 callback_handler,
455 });
456
457 let cstr_dns_search: Vec<_> = virtual_network_dns_search_domains
458 .iter()
459 .map(|arg| CString::new(arg.clone().into_bytes()).unwrap())
460 .collect();
461 let mut p_dns_search: Vec<_> = cstr_dns_search.iter().map(|arg| arg.as_ptr()).collect();
462 p_dns_search.push(std::ptr::null());
463
464 let host_hostname = host_hostname.and_then(|s| CString::new(s).ok());
465 let dns_server_domain_name = dns_server_domain_name.and_then(|s| CString::new(s).ok());
466 let rust_context_ptr = &*ret as *const _ as *mut _;
467
468 let as_ptr = |p: &Option<CString>| p.as_ref().map_or(std::ptr::null(), |s| s.as_ptr());
469
470 let slirp_config = SlirpConfig {
471 version: 1,
472 restricted: 0,
473 disable_dhcp: false,
474 in_enabled: ipv4_enabled,
475 vnetwork: virtual_network_v4_address.into(),
476 vnetmask: virtual_network_v4_mask.into(),
477 vhost: host_v4_address.into(),
478 in6_enabled: ipv6_enabled,
479 vprefix_addr6: virtual_network_v6_address.into(),
480 vprefix_len: virtual_network_v6_prefix_len,
481 vhost6: host_v6_address.into(),
482 vhostname: as_ptr(&host_hostname),
483 tftp_server_name: std::ptr::null(),
484 tftp_path: std::ptr::null(),
485 bootfile: std::ptr::null(),
486 vdhcp_start: dhcp_start_addr.into(),
487 vnameserver: dns_server_v4_addr.into(),
488 vnameserver6: dns_server_v6_addr.into(),
489 vdnssearch: p_dns_search.as_ptr() as *mut *const _,
490 vdomainname: as_ptr(&dns_server_domain_name),
491 if_mtu: 0,
492 if_mru: 0,
493 disable_host_loopback: disable_access_to_host,
494 enable_emu: false,
495 outbound_addr: std::ptr::null(),
496 outbound_addr6: std::ptr::null(),
497 disable_dns: false,
498 };
499
500 // Safe because we pass valid pointers (or null as appropriate) as parameters and we check
501 // that the return value is valid.
502 let slirp = unsafe {
503 slirp_new(
504 &slirp_config,
505 &ret.callbacks,
506 // This value is passed to callbacks as opaque data, which allows those callbacks
507 // to get access to the Context struct. It allows them to invoke the appropriate
508 // methods on the CallbackHandler to notify it about new packets, get data about
509 // sockets that are ready for reading, etc.
510 rust_context_ptr,
511 )
512 };
513 assert!(!slirp.is_null());
514 match ret.callback_handler.begin_read_from_guest() {
515 Err(e) if e.kind() == std::io::ErrorKind::BrokenPipe => {
516 return Err(Error::Slirp(SlirpError::BrokenPipe(e)));
517 }
518 Err(e) => {
519 return Err(Error::Slirp(SlirpError::OverlappedError(e)));
520 }
521 _ => {}
522 }
523 ret.slirp = slirp;
524 Ok(ret)
525 }
526
527 /// Reads from the guest & injects into Slirp. This method reads until an error is encountered
528 /// or io::ErrorKind::WouldBlock is returned by the callback_handler's read_from_guest.
handle_guest_input(&mut self) -> Result<()>529 pub fn handle_guest_input(&mut self) -> Result<()> {
530 loop {
531 match self.callback_handler.end_read_from_guest() {
532 Ok(ethernet_frame) => unsafe {
533 // Safe because the buffer (ethernet_frame) is valid & libslirp is provided
534 // with the data's underlying length.
535 slirp_input(
536 self.slirp,
537 ethernet_frame.as_ptr(),
538 ethernet_frame.len() as i32,
539 );
540 },
541 Err(e) if e.kind() == std::io::ErrorKind::InvalidData => {
542 error!("error reading packet from guest: {}", e);
543 }
544 Err(e) if e.kind() == std::io::ErrorKind::WouldBlock => {
545 // No packets are available. Yield back to the Slirp loop.
546 break;
547 }
548 Err(e) if e.kind() == std::io::ErrorKind::BrokenPipe => {
549 return Err(Error::Slirp(SlirpError::BrokenPipe(e)));
550 }
551 Err(_) => {
552 match self.callback_handler.begin_read_from_guest() {
553 Err(e) if e.kind() == std::io::ErrorKind::BrokenPipe => {
554 return Err(Error::Slirp(SlirpError::BrokenPipe(e)));
555 }
556 Err(e) => {
557 return Err(Error::Slirp(SlirpError::OverlappedError(e)));
558 }
559 _ => {}
560 }
561 break;
562 }
563 }
564 match self.callback_handler.begin_read_from_guest() {
565 Err(e) if e.kind() == std::io::ErrorKind::BrokenPipe => {
566 return Err(Error::Slirp(SlirpError::BrokenPipe(e)));
567 }
568 Err(e) => {
569 return Err(Error::Slirp(SlirpError::OverlappedError(e)));
570 }
571 _ => {}
572 }
573 }
574 Ok(())
575 }
576
connection_info(&mut self) -> &str577 pub fn connection_info(&mut self) -> &str {
578 str::from_utf8(unsafe { CStr::from_ptr(slirp_connection_info(self.slirp)) }.to_bytes())
579 .unwrap_or("")
580 }
581
582 /// Requests libslirp provide the set of sockets & events that should be polled for. These
583 /// sockets are provided to you by 0..n calls to `add_poll_cb`. `add_poll_cb` must return an
584 /// integer (henceforth the socket reference) which libslirp can use to later request the
585 /// revents that came from polling on that socket.
586 ///
587 /// The `timeout` value expresses how long (in ms) the consumer intends to wait (at most) when
588 /// it invokes the polling function. libslirp will overwrite this with the time that the
589 /// consumer should wait.
pollfds_fill<F>(&mut self, timeout: &mut u32, mut add_poll_cb: F) where F: FnMut(i32, PollEvents) -> i32,590 pub fn pollfds_fill<F>(&mut self, timeout: &mut u32, mut add_poll_cb: F)
591 where
592 F: FnMut(i32, PollEvents) -> i32,
593 {
594 let cb = &mut (&mut add_poll_cb as &mut dyn FnMut(i32, PollEvents) -> i32);
595 // Safe because cb is only used while slirp_pollfds_fill is running, and self.slirp is
596 // guaranteed to be valid.
597 unsafe {
598 slirp_pollfds_fill(
599 self.slirp,
600 timeout,
601 Some(add_poll_handler_callback),
602 cb as *mut _ as *mut c_void,
603 );
604 }
605 }
606
607 /// Informs libslirp that polling has returned with some events on sockets that libslirp said
608 /// should be polled for when you called `pollfds_fill`. You provide the results of polling by
609 /// supplying `get_revents_cb`, which returns the `PollEvents` for each provided socket
610 /// reference. libslirp will call that function 0..n times to gather results from the polling
611 /// operation.
pollfds_poll<F>(&mut self, error: bool, mut get_revents_cb: F) where F: FnMut(i32) -> PollEvents,612 pub fn pollfds_poll<F>(&mut self, error: bool, mut get_revents_cb: F)
613 where
614 F: FnMut(i32) -> PollEvents,
615 {
616 let cb = &mut (&mut get_revents_cb as &mut dyn FnMut(i32) -> PollEvents);
617
618 // Safe because cb is only used while slirp_pollfds_poll is running, and self.slirp is
619 // guaranteed to be valid.
620 unsafe {
621 slirp_pollfds_poll(
622 self.slirp,
623 error as i32,
624 Some(get_revents_handler_callback),
625 cb as *mut _ as *mut c_void,
626 );
627 }
628 }
629
state_save<F>(&mut self, mut write_cb: F) where F: FnMut(&[u8]) -> isize,630 pub fn state_save<F>(&mut self, mut write_cb: F)
631 where
632 F: FnMut(&[u8]) -> isize,
633 {
634 // Safe because cb is only used while state_save is running, and self.slirp is
635 // guaranteed to be valid.
636 let cb = &mut (&mut write_cb as &mut dyn FnMut(&[u8]) -> isize);
637 unsafe {
638 slirp_state_save(
639 self.slirp,
640 Some(write_handler_callback),
641 cb as *mut _ as *mut c_void,
642 );
643 }
644 }
645
state_load<F>(&mut self, version_id: i32, mut read_cb: F) -> i32 where F: FnMut(&mut [u8]) -> isize,646 pub fn state_load<F>(&mut self, version_id: i32, mut read_cb: F) -> i32
647 where
648 F: FnMut(&mut [u8]) -> isize,
649 {
650 // Safe because cb is only used while state_load is running, and self.slirp is
651 // guaranteed to be valid. While this function may fail, interpretation of the error code
652 // is the responsibility of the caller.
653 //
654 // TODO(nkgold): if state_load becomes used by crosvm, interpretation of the error code
655 // should occur here.
656 let cb = &mut (&mut read_cb as &mut dyn FnMut(&mut [u8]) -> isize);
657 unsafe {
658 slirp_state_load(
659 self.slirp,
660 version_id,
661 Some(read_handler_callback),
662 cb as *mut _ as *mut c_void,
663 )
664 }
665 }
666
get_timers<'a>(&'a self) -> Box<dyn Iterator<Item = &RawDescriptor> + 'a>667 pub fn get_timers<'a>(&'a self) -> Box<dyn Iterator<Item = &RawDescriptor> + 'a> {
668 self.callback_handler.get_timers()
669 }
670
execute_timer(&mut self, timer: RawDescriptor)671 pub fn execute_timer(&mut self, timer: RawDescriptor) {
672 self.callback_handler.execute_timer(timer)
673 }
674 }
675