viceroy_lib/wiggle_abi/
acl.rs

1use crate::error::{Error, HandleError};
2use crate::session::Session;
3use crate::wiggle_abi::{fastly_acl, types};
4use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
5
6#[wiggle::async_trait]
7impl fastly_acl::FastlyAcl for Session {
8    /// Open a handle to an ACL by its linked name.
9    fn open(
10        &mut self,
11        memory: &mut wiggle::GuestMemory<'_>,
12        acl_name: wiggle::GuestPtr<str>,
13    ) -> Result<types::AclHandle, Error> {
14        let acl_name = memory.as_str(acl_name)?.ok_or(Error::SharedMemory)?;
15        self.acl_handle_by_name(acl_name).ok_or(Error::ValueAbsent)
16    }
17
18    /// Perform an ACL lookup operation using the given ACL handle.
19    ///
20    /// There are two levels of errors returned by this function:
21    ///   - Error: These are general hostcall errors, e.g. handle not found.
22    ///   - AclError: There are ACL-specific errors, e.g. 'no content'.
23    /// It's the callers responsibility to check both errors.
24    async fn lookup(
25        &mut self,
26        memory: &mut wiggle::GuestMemory<'_>,
27        acl_handle: types::AclHandle,
28        ip_octets: wiggle::GuestPtr<u8>, // This should be either a 4 or 16-byte array.
29        ip_len: u32,                     // Either 4 or 16.
30        body_handle_out: wiggle::GuestPtr<types::BodyHandle>,
31        acl_error_out: wiggle::GuestPtr<types::AclError>,
32    ) -> Result<(), Error> {
33        let acl = self.acl_by_handle(acl_handle).ok_or(Error::HandleError(
34            HandleError::InvalidAclHandle(acl_handle),
35        ))?;
36
37        let ip: IpAddr = {
38            let ip_octets = memory.to_vec(ip_octets.as_array(ip_len))?;
39            match ip_len {
40                4 => IpAddr::V4(Ipv4Addr::from(
41                    TryInto::<[u8; 4]>::try_into(ip_octets).unwrap(),
42                )),
43                16 => IpAddr::V6(Ipv6Addr::from(
44                    TryInto::<[u8; 16]>::try_into(ip_octets).unwrap(),
45                )),
46                _ => return Err(Error::InvalidArgument),
47            }
48        };
49
50        match acl.lookup(ip) {
51            Some(entry) => {
52                let body =
53                    serde_json::to_vec_pretty(&entry).map_err(|err| Error::Other(err.into()))?;
54                let body_handle = self.insert_body(body.into());
55                memory.write(body_handle_out, body_handle)?;
56                memory.write(acl_error_out, types::AclError::Ok)?;
57                Ok(())
58            }
59            None => {
60                memory.write(acl_error_out, types::AclError::NoContent)?;
61                Ok(())
62            }
63        }
64    }
65}