1use std::fs::File;
5use std::mem;
6
7use base::AsRawDescriptor;
8use base::RawDescriptor;
9use base::SafeDescriptor;
10use zerocopy::FromBytes;
11use zerocopy::Immutable;
12use zerocopy::IntoBytes;
13use zerocopy::Ref;
14
15use crate::into_single_file;
16use crate::message::*;
17use crate::Connection;
18use crate::Error;
19use crate::FrontendReq;
20use crate::Result;
21use crate::SharedMemoryRegion;
22
23#[allow(missing_docs)]
27pub trait Backend {
28 fn set_owner(&mut self) -> Result<()>;
29 fn reset_owner(&mut self) -> Result<()>;
30 fn get_features(&mut self) -> Result<u64>;
31 fn set_features(&mut self, features: u64) -> Result<()>;
32 fn set_mem_table(&mut self, ctx: &[VhostUserMemoryRegion], files: Vec<File>) -> Result<()>;
33 fn set_vring_num(&mut self, index: u32, num: u32) -> Result<()>;
34 fn set_vring_addr(
35 &mut self,
36 index: u32,
37 flags: VhostUserVringAddrFlags,
38 descriptor: u64,
39 used: u64,
40 available: u64,
41 log: u64,
42 ) -> Result<()>;
43 fn set_vring_base(&mut self, index: u32, base: u32) -> Result<()>;
45 fn get_vring_base(&mut self, index: u32) -> Result<VhostUserVringState>;
47 fn set_vring_kick(&mut self, index: u8, fd: Option<File>) -> Result<()>;
48 fn set_vring_call(&mut self, index: u8, fd: Option<File>) -> Result<()>;
49 fn set_vring_err(&mut self, index: u8, fd: Option<File>) -> Result<()>;
50
51 fn get_protocol_features(&mut self) -> Result<VhostUserProtocolFeatures>;
52 fn set_protocol_features(&mut self, features: u64) -> Result<()>;
53 fn get_queue_num(&mut self) -> Result<u64>;
54 fn set_vring_enable(&mut self, index: u32, enable: bool) -> Result<()>;
55 fn get_config(
56 &mut self,
57 offset: u32,
58 size: u32,
59 flags: VhostUserConfigFlags,
60 ) -> Result<Vec<u8>>;
61 fn set_config(&mut self, offset: u32, buf: &[u8], flags: VhostUserConfigFlags) -> Result<()>;
62 fn set_backend_req_fd(&mut self, _vu_req: Connection) {}
63 fn get_inflight_fd(
64 &mut self,
65 inflight: &VhostUserInflight,
66 ) -> Result<(VhostUserInflight, File)>;
67 fn set_inflight_fd(&mut self, inflight: &VhostUserInflight, file: File) -> Result<()>;
68 fn get_max_mem_slots(&mut self) -> Result<u64>;
69 fn add_mem_region(&mut self, region: &VhostUserSingleMemoryRegion, fd: File) -> Result<()>;
70 fn remove_mem_region(&mut self, region: &VhostUserSingleMemoryRegion) -> Result<()>;
71 fn set_device_state_fd(
72 &mut self,
73 transfer_direction: VhostUserTransferDirection,
74 migration_phase: VhostUserMigrationPhase,
75 fd: File,
76 ) -> Result<Option<File>>;
77 fn check_device_state(&mut self) -> Result<()>;
78 fn get_shmem_config(&mut self) -> Result<Vec<SharedMemoryRegion>>;
79}
80
81impl<'a> AsMut<dyn Backend + 'a> for dyn Backend + 'a {
82 fn as_mut(&mut self) -> &mut (dyn Backend + 'a) {
83 self
84 }
85}
86
87impl<'a, T> Backend for T
88where
89 T: AsMut<dyn Backend + 'a>,
90{
91 fn set_owner(&mut self) -> Result<()> {
92 self.as_mut().set_owner()
93 }
94
95 fn reset_owner(&mut self) -> Result<()> {
96 self.as_mut().reset_owner()
97 }
98
99 fn get_features(&mut self) -> Result<u64> {
100 self.as_mut().get_features()
101 }
102
103 fn set_features(&mut self, features: u64) -> Result<()> {
104 self.as_mut().set_features(features)
105 }
106
107 fn set_mem_table(&mut self, ctx: &[VhostUserMemoryRegion], files: Vec<File>) -> Result<()> {
108 self.as_mut().set_mem_table(ctx, files)
109 }
110
111 fn set_vring_num(&mut self, index: u32, num: u32) -> Result<()> {
112 self.as_mut().set_vring_num(index, num)
113 }
114
115 fn set_vring_addr(
116 &mut self,
117 index: u32,
118 flags: VhostUserVringAddrFlags,
119 descriptor: u64,
120 used: u64,
121 available: u64,
122 log: u64,
123 ) -> Result<()> {
124 self.as_mut()
125 .set_vring_addr(index, flags, descriptor, used, available, log)
126 }
127
128 fn set_vring_base(&mut self, index: u32, base: u32) -> Result<()> {
129 self.as_mut().set_vring_base(index, base)
130 }
131
132 fn get_vring_base(&mut self, index: u32) -> Result<VhostUserVringState> {
133 self.as_mut().get_vring_base(index)
134 }
135
136 fn set_vring_kick(&mut self, index: u8, fd: Option<File>) -> Result<()> {
137 self.as_mut().set_vring_kick(index, fd)
138 }
139
140 fn set_vring_call(&mut self, index: u8, fd: Option<File>) -> Result<()> {
141 self.as_mut().set_vring_call(index, fd)
142 }
143
144 fn set_vring_err(&mut self, index: u8, fd: Option<File>) -> Result<()> {
145 self.as_mut().set_vring_err(index, fd)
146 }
147
148 fn get_protocol_features(&mut self) -> Result<VhostUserProtocolFeatures> {
149 self.as_mut().get_protocol_features()
150 }
151
152 fn set_protocol_features(&mut self, features: u64) -> Result<()> {
153 self.as_mut().set_protocol_features(features)
154 }
155
156 fn get_queue_num(&mut self) -> Result<u64> {
157 self.as_mut().get_queue_num()
158 }
159
160 fn set_vring_enable(&mut self, index: u32, enable: bool) -> Result<()> {
161 self.as_mut().set_vring_enable(index, enable)
162 }
163
164 fn get_config(
165 &mut self,
166 offset: u32,
167 size: u32,
168 flags: VhostUserConfigFlags,
169 ) -> Result<Vec<u8>> {
170 self.as_mut().get_config(offset, size, flags)
171 }
172
173 fn set_config(&mut self, offset: u32, buf: &[u8], flags: VhostUserConfigFlags) -> Result<()> {
174 self.as_mut().set_config(offset, buf, flags)
175 }
176
177 fn set_backend_req_fd(&mut self, vu_req: Connection) {
178 self.as_mut().set_backend_req_fd(vu_req)
179 }
180
181 fn get_inflight_fd(
182 &mut self,
183 inflight: &VhostUserInflight,
184 ) -> Result<(VhostUserInflight, File)> {
185 self.as_mut().get_inflight_fd(inflight)
186 }
187
188 fn set_inflight_fd(&mut self, inflight: &VhostUserInflight, file: File) -> Result<()> {
189 self.as_mut().set_inflight_fd(inflight, file)
190 }
191
192 fn get_max_mem_slots(&mut self) -> Result<u64> {
193 self.as_mut().get_max_mem_slots()
194 }
195
196 fn add_mem_region(&mut self, region: &VhostUserSingleMemoryRegion, fd: File) -> Result<()> {
197 self.as_mut().add_mem_region(region, fd)
198 }
199
200 fn remove_mem_region(&mut self, region: &VhostUserSingleMemoryRegion) -> Result<()> {
201 self.as_mut().remove_mem_region(region)
202 }
203
204 fn set_device_state_fd(
205 &mut self,
206 transfer_direction: VhostUserTransferDirection,
207 migration_phase: VhostUserMigrationPhase,
208 fd: File,
209 ) -> Result<Option<File>> {
210 self.as_mut()
211 .set_device_state_fd(transfer_direction, migration_phase, fd)
212 }
213
214 fn check_device_state(&mut self) -> Result<()> {
215 self.as_mut().check_device_state()
216 }
217
218 fn get_shmem_config(&mut self) -> Result<Vec<SharedMemoryRegion>> {
219 self.as_mut().get_shmem_config()
220 }
221}
222
223pub struct BackendServer<S: Backend> {
225 connection: Connection,
227 backend: S,
229
230 virtio_features: u64,
231 acked_virtio_features: u64,
232 protocol_features: VhostUserProtocolFeatures,
233 acked_protocol_features: u64,
234
235 reply_ack_enabled: bool,
237}
238
239impl<S: Backend> AsRef<S> for BackendServer<S> {
240 fn as_ref(&self) -> &S {
241 &self.backend
242 }
243}
244
245impl<S: Backend> BackendServer<S> {
246 pub fn new(connection: Connection, backend: S) -> Self {
247 BackendServer {
248 connection,
249 backend,
250 virtio_features: 0,
251 acked_virtio_features: 0,
252 protocol_features: VhostUserProtocolFeatures::empty(),
253 acked_protocol_features: 0,
254 reply_ack_enabled: false,
255 }
256 }
257
258 pub fn recv_header(&mut self) -> Result<(VhostUserMsgHeader, Vec<File>)> {
306 let (hdr, files) = match self.connection.recv_header() {
316 Ok((hdr, files)) => (hdr, files),
317 Err(Error::Disconnect) => {
318 return Err(Error::ClientExit);
321 }
322 Err(e) => {
323 return Err(e);
324 }
325 };
326
327 if !hdr.is_valid() {
328 return Err(Error::InvalidMessage);
329 }
330
331 self.check_attached_files(&hdr, &files)?;
332
333 Ok((hdr, files))
334 }
335
336 pub fn needs_wait_for_payload(&self, hdr: &VhostUserMsgHeader) -> bool {
341 hdr.get_size() != 0
344 }
345
346 pub fn process_message(&mut self, hdr: VhostUserMsgHeader, files: Vec<File>) -> Result<()> {
359 let (buf, extra_files) = self.connection.recv_body_bytes(&hdr)?;
360 let size = buf.len();
361 if !extra_files.is_empty() {
362 return Err(Error::InvalidMessage);
363 }
364
365 match hdr.get_code() {
369 Ok(FrontendReq::SET_OWNER) => {
370 self.check_request_size(&hdr, size, 0)?;
371 let res = self.backend.set_owner();
372 self.send_ack_message(&hdr, res.is_ok())?;
373 res?;
374 }
375 Ok(FrontendReq::RESET_OWNER) => {
376 self.check_request_size(&hdr, size, 0)?;
377 let res = self.backend.reset_owner();
378 self.send_ack_message(&hdr, res.is_ok())?;
379 res?;
380 }
381 Ok(FrontendReq::GET_FEATURES) => {
382 self.check_request_size(&hdr, size, 0)?;
383 let mut features = self.backend.get_features()?;
384
385 features &= !(1 << VIRTIO_F_RING_PACKED);
389
390 let msg = VhostUserU64::new(features);
391 self.send_reply_message(&hdr, &msg)?;
392 self.virtio_features = features;
393 self.update_reply_ack_flag();
394 }
395 Ok(FrontendReq::SET_FEATURES) => {
396 let mut msg = self.extract_request_body::<VhostUserU64>(&hdr, size, &buf)?;
397
398 msg.value &= !(1 << VIRTIO_F_RING_PACKED);
402
403 let res = self.backend.set_features(msg.value);
404 self.acked_virtio_features = msg.value;
405 self.update_reply_ack_flag();
406 self.send_ack_message(&hdr, res.is_ok())?;
407 res?;
408 }
409 Ok(FrontendReq::SET_MEM_TABLE) => {
410 let res = self.set_mem_table(&hdr, size, &buf, files);
411 self.send_ack_message(&hdr, res.is_ok())?;
412 res?;
413 }
414 Ok(FrontendReq::SET_VRING_NUM) => {
415 let msg = self.extract_request_body::<VhostUserVringState>(&hdr, size, &buf)?;
416 let res = self.backend.set_vring_num(msg.index, msg.num);
417 self.send_ack_message(&hdr, res.is_ok())?;
418 res?;
419 }
420 Ok(FrontendReq::SET_VRING_ADDR) => {
421 let msg = self.extract_request_body::<VhostUserVringAddr>(&hdr, size, &buf)?;
422 let flags = match VhostUserVringAddrFlags::from_bits(msg.flags) {
423 Some(val) => val,
424 None => return Err(Error::InvalidMessage),
425 };
426 let res = self.backend.set_vring_addr(
427 msg.index,
428 flags,
429 msg.descriptor,
430 msg.used,
431 msg.available,
432 msg.log,
433 );
434 self.send_ack_message(&hdr, res.is_ok())?;
435 res?;
436 }
437 Ok(FrontendReq::SET_VRING_BASE) => {
438 let msg = self.extract_request_body::<VhostUserVringState>(&hdr, size, &buf)?;
439 let res = self.backend.set_vring_base(msg.index, msg.num);
440 self.send_ack_message(&hdr, res.is_ok())?;
441 res?;
442 }
443 Ok(FrontendReq::GET_VRING_BASE) => {
444 let msg = self.extract_request_body::<VhostUserVringState>(&hdr, size, &buf)?;
445 let reply = self.backend.get_vring_base(msg.index)?;
446 self.send_reply_message(&hdr, &reply)?;
447 }
448 Ok(FrontendReq::SET_VRING_CALL) => {
449 self.check_request_size(&hdr, size, mem::size_of::<VhostUserU64>())?;
450 let (index, file) = self.handle_vring_fd_request(&buf, files)?;
451 let res = self.backend.set_vring_call(index, file);
452 self.send_ack_message(&hdr, res.is_ok())?;
453 res?;
454 }
455 Ok(FrontendReq::SET_VRING_KICK) => {
456 self.check_request_size(&hdr, size, mem::size_of::<VhostUserU64>())?;
457 let (index, file) = self.handle_vring_fd_request(&buf, files)?;
458 let res = self.backend.set_vring_kick(index, file);
459 self.send_ack_message(&hdr, res.is_ok())?;
460 res?;
461 }
462 Ok(FrontendReq::SET_VRING_ERR) => {
463 self.check_request_size(&hdr, size, mem::size_of::<VhostUserU64>())?;
464 let (index, file) = self.handle_vring_fd_request(&buf, files)?;
465 let res = self.backend.set_vring_err(index, file);
466 self.send_ack_message(&hdr, res.is_ok())?;
467 res?;
468 }
469 Ok(FrontendReq::GET_PROTOCOL_FEATURES) => {
470 self.check_request_size(&hdr, size, 0)?;
471 let features = self.backend.get_protocol_features()?;
472 let msg = VhostUserU64::new(features.bits());
473 self.send_reply_message(&hdr, &msg)?;
474 self.protocol_features = features;
475 self.update_reply_ack_flag();
476 }
477 Ok(FrontendReq::SET_PROTOCOL_FEATURES) => {
478 let msg = self.extract_request_body::<VhostUserU64>(&hdr, size, &buf)?;
479 let res = self.backend.set_protocol_features(msg.value);
480 self.acked_protocol_features = msg.value;
481 self.update_reply_ack_flag();
482 self.send_ack_message(&hdr, res.is_ok())?;
483 res?;
484 }
485 Ok(FrontendReq::GET_QUEUE_NUM) => {
486 if self.acked_protocol_features & VhostUserProtocolFeatures::MQ.bits() == 0 {
487 return Err(Error::InvalidOperation);
488 }
489 self.check_request_size(&hdr, size, 0)?;
490 let num = self.backend.get_queue_num()?;
491 let msg = VhostUserU64::new(num);
492 self.send_reply_message(&hdr, &msg)?;
493 }
494 Ok(FrontendReq::SET_VRING_ENABLE) => {
495 let msg = self.extract_request_body::<VhostUserVringState>(&hdr, size, &buf)?;
496 if self.acked_virtio_features & 1 << VHOST_USER_F_PROTOCOL_FEATURES == 0 {
497 return Err(Error::InvalidOperation);
498 }
499 let enable = match msg.num {
500 1 => true,
501 0 => false,
502 _ => {
503 return Err(Error::InvalidParam(
504 "SET_VRING_ENABLE: num out of range (must be [0, 1])",
505 ))
506 }
507 };
508
509 let res = self.backend.set_vring_enable(msg.index, enable);
510 self.send_ack_message(&hdr, res.is_ok())?;
511 res?;
512 }
513 Ok(FrontendReq::GET_CONFIG) => {
514 if self.acked_protocol_features & VhostUserProtocolFeatures::CONFIG.bits() == 0 {
515 return Err(Error::InvalidOperation);
516 }
517 self.check_request_size(&hdr, size, hdr.get_size() as usize)?;
518 self.get_config(&hdr, &buf)?;
519 }
520 Ok(FrontendReq::SET_CONFIG) => {
521 if self.acked_protocol_features & VhostUserProtocolFeatures::CONFIG.bits() == 0 {
522 return Err(Error::InvalidOperation);
523 }
524 self.check_request_size(&hdr, size, hdr.get_size() as usize)?;
525 let res = self.set_config(&buf);
526 self.send_ack_message(&hdr, res.is_ok())?;
527 res?;
528 }
529 Ok(FrontendReq::SET_BACKEND_REQ_FD) => {
530 if self.acked_protocol_features & VhostUserProtocolFeatures::BACKEND_REQ.bits() == 0
531 {
532 return Err(Error::InvalidOperation);
533 }
534 self.check_request_size(&hdr, size, hdr.get_size() as usize)?;
535 let res = self.set_backend_req_fd(files);
536 self.send_ack_message(&hdr, res.is_ok())?;
537 res?;
538 }
539 Ok(FrontendReq::GET_INFLIGHT_FD) => {
540 if self.acked_protocol_features & VhostUserProtocolFeatures::INFLIGHT_SHMFD.bits()
541 == 0
542 {
543 return Err(Error::InvalidOperation);
544 }
545
546 let msg = self.extract_request_body::<VhostUserInflight>(&hdr, size, &buf)?;
547 let (inflight, file) = self.backend.get_inflight_fd(&msg)?;
548 let reply_hdr = self.new_reply_header::<VhostUserInflight>(&hdr, 0)?;
549 self.connection.send_message(
550 &reply_hdr,
551 &inflight,
552 Some(&[file.as_raw_descriptor()]),
553 )?;
554 }
555 Ok(FrontendReq::SET_INFLIGHT_FD) => {
556 if self.acked_protocol_features & VhostUserProtocolFeatures::INFLIGHT_SHMFD.bits()
557 == 0
558 {
559 return Err(Error::InvalidOperation);
560 }
561 let file = into_single_file(files).ok_or(Error::IncorrectFds)?;
562 let msg = self.extract_request_body::<VhostUserInflight>(&hdr, size, &buf)?;
563 let res = self.backend.set_inflight_fd(&msg, file);
564 self.send_ack_message(&hdr, res.is_ok())?;
565 res?;
566 }
567 Ok(FrontendReq::GET_MAX_MEM_SLOTS) => {
568 if self.acked_protocol_features
569 & VhostUserProtocolFeatures::CONFIGURE_MEM_SLOTS.bits()
570 == 0
571 {
572 return Err(Error::InvalidOperation);
573 }
574 self.check_request_size(&hdr, size, 0)?;
575 let num = self.backend.get_max_mem_slots()?;
576 let msg = VhostUserU64::new(num);
577 self.send_reply_message(&hdr, &msg)?;
578 }
579 Ok(FrontendReq::ADD_MEM_REG) => {
580 if self.acked_protocol_features
581 & VhostUserProtocolFeatures::CONFIGURE_MEM_SLOTS.bits()
582 == 0
583 {
584 return Err(Error::InvalidOperation);
585 }
586 let file = into_single_file(files).ok_or(Error::InvalidParam(
587 "ADD_MEM_REG: exactly one file must be provided",
588 ))?;
589 let msg =
590 self.extract_request_body::<VhostUserSingleMemoryRegion>(&hdr, size, &buf)?;
591 let res = self.backend.add_mem_region(&msg, file);
592 self.send_ack_message(&hdr, res.is_ok())?;
593 res?;
594 }
595 Ok(FrontendReq::REM_MEM_REG) => {
596 if self.acked_protocol_features
597 & VhostUserProtocolFeatures::CONFIGURE_MEM_SLOTS.bits()
598 == 0
599 {
600 return Err(Error::InvalidOperation);
601 }
602
603 let msg =
604 self.extract_request_body::<VhostUserSingleMemoryRegion>(&hdr, size, &buf)?;
605 let res = self.backend.remove_mem_region(&msg);
606 self.send_ack_message(&hdr, res.is_ok())?;
607 res?;
608 }
609 Ok(FrontendReq::SET_DEVICE_STATE_FD) => {
610 if self.acked_protocol_features & VhostUserProtocolFeatures::DEVICE_STATE.bits()
611 == 0
612 {
613 return Err(Error::InvalidOperation);
614 }
615 let msg =
617 self.extract_request_body::<DeviceStateTransferParameters>(&hdr, size, &buf)?;
618 let transfer_direction = match msg.transfer_direction {
619 0 => VhostUserTransferDirection::Save,
620 1 => VhostUserTransferDirection::Load,
621 _ => return Err(Error::InvalidMessage),
622 };
623 let migration_phase = match msg.migration_phase {
624 0 => VhostUserMigrationPhase::Stopped,
625 _ => return Err(Error::InvalidMessage),
626 };
627 let res = self.backend.set_device_state_fd(
629 transfer_direction,
630 migration_phase,
631 files.into_iter().next().ok_or(Error::IncorrectFds)?,
632 );
633 let (msg, fds) = match &res {
635 Ok(None) => (VhostUserU64::new(0x100), None),
636 Ok(Some(file)) => (VhostUserU64::new(0), Some(file.as_raw_descriptor())),
637 Err(_) => (VhostUserU64::new(0x101), None),
639 };
640 let reply_hdr: VhostUserMsgHeader =
641 self.new_reply_header::<VhostUserU64>(&hdr, 0)?;
642 self.connection.send_message(
643 &reply_hdr,
644 &msg,
645 fds.as_ref().map(std::slice::from_ref),
646 )?;
647 res?;
648 }
649 Ok(FrontendReq::CHECK_DEVICE_STATE) => {
650 if self.acked_protocol_features & VhostUserProtocolFeatures::DEVICE_STATE.bits()
651 == 0
652 {
653 return Err(Error::InvalidOperation);
654 }
655 let res = self.backend.check_device_state();
656 let msg = VhostUserU64::new(if res.is_ok() { 0 } else { 1 });
657 self.send_reply_message(&hdr, &msg)?;
658 res?;
659 }
660 Ok(FrontendReq::GET_SHMEM_CONFIG) => {
661 let msg = VhostUserShMemConfig::new(&self.backend.get_shmem_config()?);
662 self.send_reply_message(&hdr, &msg)?;
663 }
664 _ => {
665 return Err(Error::InvalidMessage);
666 }
667 }
668 Ok(())
669 }
670
671 fn new_reply_header<T: Sized>(
672 &self,
673 req: &VhostUserMsgHeader,
674 payload_size: usize,
675 ) -> Result<VhostUserMsgHeader> {
676 Ok(VhostUserMsgHeader::new_reply_header(
677 req.get_code::<FrontendReq>()
678 .map_err(|_| Error::InvalidMessage)?,
679 (mem::size_of::<T>()
680 .checked_add(payload_size)
681 .ok_or(Error::OversizedMsg)?)
682 .try_into()
683 .map_err(Error::InvalidCastToInt)?,
684 ))
685 }
686
687 fn send_ack_message(&mut self, req: &VhostUserMsgHeader, success: bool) -> Result<()> {
689 if self.reply_ack_enabled && req.is_need_reply() {
690 let hdr: VhostUserMsgHeader = self.new_reply_header::<VhostUserU64>(req, 0)?;
691 let val = if success { 0 } else { 1 };
692 let msg = VhostUserU64::new(val);
693 self.connection.send_message(&hdr, &msg, None)?;
694 }
695 Ok(())
696 }
697
698 fn send_reply_message<T: IntoBytes + Immutable>(
699 &mut self,
700 req: &VhostUserMsgHeader,
701 msg: &T,
702 ) -> Result<()> {
703 let hdr = self.new_reply_header::<T>(req, 0)?;
704 self.connection.send_message(&hdr, msg, None)?;
705 Ok(())
706 }
707
708 fn send_reply_with_payload<T: IntoBytes + Immutable>(
709 &mut self,
710 req: &VhostUserMsgHeader,
711 msg: &T,
712 payload: &[u8],
713 ) -> Result<()> {
714 let hdr = self.new_reply_header::<T>(req, payload.len())?;
715 self.connection
716 .send_message_with_payload(&hdr, msg, payload, None)?;
717 Ok(())
718 }
719
720 fn set_mem_table(
721 &mut self,
722 hdr: &VhostUserMsgHeader,
723 size: usize,
724 buf: &[u8],
725 files: Vec<File>,
726 ) -> Result<()> {
727 self.check_request_size(hdr, size, hdr.get_size() as usize)?;
728
729 let (msg, regions) =
730 Ref::<_, VhostUserMemory>::from_prefix(buf).map_err(|_| Error::InvalidMessage)?;
731 if !msg.is_valid() {
732 return Err(Error::InvalidMessage);
733 }
734
735 if files.len() != msg.num_regions as usize {
737 return Err(Error::InvalidMessage);
738 }
739
740 let (regions, excess) = Ref::<_, [VhostUserMemoryRegion]>::from_prefix_with_elems(
741 regions,
742 msg.num_regions as usize,
743 )
744 .map_err(|_| Error::InvalidMessage)?;
745 if !excess.is_empty() {
746 return Err(Error::InvalidMessage);
747 }
748
749 for region in regions.iter() {
751 if !region.is_valid() {
752 return Err(Error::InvalidMessage);
753 }
754 }
755
756 self.backend.set_mem_table(®ions, files)
757 }
758
759 fn get_config(&mut self, hdr: &VhostUserMsgHeader, buf: &[u8]) -> Result<()> {
760 let (msg, payload) =
761 Ref::<_, VhostUserConfig>::from_prefix(buf).map_err(|_| Error::InvalidMessage)?;
762 if !msg.is_valid() {
763 return Err(Error::InvalidMessage);
764 }
765 if payload.len() != msg.size as usize {
766 return Err(Error::InvalidMessage);
767 }
768 let flags = match VhostUserConfigFlags::from_bits(msg.flags) {
769 Some(val) => val,
770 None => return Err(Error::InvalidMessage),
771 };
772 let res = self.backend.get_config(msg.offset, msg.size, flags);
773
774 match res {
777 Ok(ref buf) if buf.len() == msg.size as usize => {
778 let reply = VhostUserConfig::new(msg.offset, buf.len() as u32, flags);
779 self.send_reply_with_payload(hdr, &reply, buf.as_slice())?;
780 }
781 Ok(_) => {
782 let reply = VhostUserConfig::new(msg.offset, 0, flags);
783 self.send_reply_message(hdr, &reply)?;
784 }
785 Err(_) => {
786 let reply = VhostUserConfig::new(msg.offset, 0, flags);
787 self.send_reply_message(hdr, &reply)?;
788 }
789 }
790 Ok(())
791 }
792
793 fn set_config(&mut self, buf: &[u8]) -> Result<()> {
794 let (msg, payload) =
795 Ref::<_, VhostUserConfig>::from_prefix(buf).map_err(|_| Error::InvalidMessage)?;
796 if !msg.is_valid() {
797 return Err(Error::InvalidMessage);
798 }
799 if payload.len() != msg.size as usize {
800 return Err(Error::InvalidMessage);
801 }
802 let flags: VhostUserConfigFlags = match VhostUserConfigFlags::from_bits(msg.flags) {
803 Some(val) => val,
804 None => return Err(Error::InvalidMessage),
805 };
806
807 self.backend.set_config(msg.offset, payload, flags)
808 }
809
810 fn set_backend_req_fd(&mut self, files: Vec<File>) -> Result<()> {
811 let file = into_single_file(files).ok_or(Error::InvalidMessage)?;
812 let fd: SafeDescriptor = file.into();
813 let connection = Connection::try_from(fd).map_err(|_| Error::InvalidMessage)?;
814 self.backend.set_backend_req_fd(connection);
815 Ok(())
816 }
817
818 fn handle_vring_fd_request(
821 &mut self,
822 buf: &[u8],
823 files: Vec<File>,
824 ) -> Result<(u8, Option<File>)> {
825 let (msg, _) = VhostUserU64::read_from_prefix(buf).map_err(|_| Error::InvalidMessage)?;
826 if !msg.is_valid() {
827 return Err(Error::InvalidMessage);
828 }
829
830 let has_fd = (msg.value & 0x100u64) == 0;
837
838 let file = into_single_file(files);
839
840 if has_fd && file.is_none() || !has_fd && file.is_some() {
841 return Err(Error::InvalidMessage);
842 }
843
844 Ok((msg.value as u8, file))
845 }
846
847 fn check_request_size(
848 &self,
849 hdr: &VhostUserMsgHeader,
850 size: usize,
851 expected: usize,
852 ) -> Result<()> {
853 if hdr.get_size() as usize != expected
854 || hdr.is_reply()
855 || hdr.get_version() != 0x1
856 || size != expected
857 {
858 return Err(Error::InvalidMessage);
859 }
860 Ok(())
861 }
862
863 fn check_attached_files(&self, hdr: &VhostUserMsgHeader, files: &[File]) -> Result<()> {
864 match hdr.get_code() {
865 Ok(FrontendReq::SET_MEM_TABLE)
866 | Ok(FrontendReq::SET_VRING_CALL)
867 | Ok(FrontendReq::SET_VRING_KICK)
868 | Ok(FrontendReq::SET_VRING_ERR)
869 | Ok(FrontendReq::SET_LOG_BASE)
870 | Ok(FrontendReq::SET_LOG_FD)
871 | Ok(FrontendReq::SET_BACKEND_REQ_FD)
872 | Ok(FrontendReq::SET_INFLIGHT_FD)
873 | Ok(FrontendReq::ADD_MEM_REG)
874 | Ok(FrontendReq::SET_DEVICE_STATE_FD) => Ok(()),
875 Err(_) => Err(Error::InvalidMessage),
876 _ if !files.is_empty() => Err(Error::InvalidMessage),
877 _ => Ok(()),
878 }
879 }
880
881 fn extract_request_body<T: Sized + FromBytes + VhostUserMsgValidator>(
882 &self,
883 hdr: &VhostUserMsgHeader,
884 size: usize,
885 buf: &[u8],
886 ) -> Result<T> {
887 self.check_request_size(hdr, size, mem::size_of::<T>())?;
888 let (body, _) = T::read_from_prefix(buf).map_err(|_| Error::InvalidMessage)?;
889 if body.is_valid() {
890 Ok(body)
891 } else {
892 Err(Error::InvalidMessage)
893 }
894 }
895
896 fn update_reply_ack_flag(&mut self) {
897 let pflag = VhostUserProtocolFeatures::REPLY_ACK;
898 self.reply_ack_enabled = (self.virtio_features & 1 << VHOST_USER_F_PROTOCOL_FEATURES) != 0
899 && self.protocol_features.contains(pflag)
900 && (self.acked_protocol_features & pflag.bits()) != 0;
901 }
902}
903
904impl<S: Backend> AsRawDescriptor for BackendServer<S> {
905 fn as_raw_descriptor(&self) -> RawDescriptor {
906 self.connection.as_raw_descriptor()
908 }
909}
910
911#[cfg(test)]
912mod tests {
913 use base::INVALID_DESCRIPTOR;
914
915 use super::*;
916 use crate::test_backend::TestBackend;
917 use crate::Connection;
918
919 #[test]
920 fn test_backend_server_new() {
921 let (p1, _p2) = Connection::pair().unwrap();
922 let backend = TestBackend::new();
923 let handler = BackendServer::new(p1, backend);
924
925 assert!(handler.as_raw_descriptor() != INVALID_DESCRIPTOR);
926 }
927}