|  |  | @ -14,22 +14,48 @@ use crate::{ | 
			
		
	
		
		
			
				
					
					|  |  |  |     Pod, |  |  |  |     Pod, | 
			
		
	
		
		
			
				
					
					|  |  |  | }; |  |  |  | }; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | /// A hash map that can be shared between eBPF programs and user space.
 |  |  |  | /// A hash map of TCP or UDP sockets.
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | ///
 |  |  |  | ///
 | 
			
		
	
		
		
			
				
					
					|  |  |  | /// It is required that both keys and values implement the [`Pod`] trait.
 |  |  |  | /// A `SockHash` is used to store TCP or UDP sockets. eBPF programs can then be
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | /// attached to the map to inspect, filter or redirect network buffers on those
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | /// sockets.
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | ///
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | /// A `SockHash` can also be used to redirect packets to sockets contained by the
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | /// map using `bpf_redirect_map()`, `bpf_sk_redirect_hash()` etc.
 | 
			
		
	
		
		
			
				
					
					|  |  |  | ///
 |  |  |  | ///
 | 
			
		
	
		
		
			
				
					
					|  |  |  | /// # Example
 |  |  |  | /// # Example
 | 
			
		
	
		
		
			
				
					
					|  |  |  | ///
 |  |  |  | ///
 | 
			
		
	
		
		
			
				
					
					|  |  |  | /// ```no_run
 |  |  |  | /// ```no_run
 | 
			
		
	
		
		
			
				
					
					|  |  |  | /// # let bpf = aya::Bpf::load(&[], None)?;
 |  |  |  | /// ##[derive(Debug, thiserror::Error)]
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | /// # enum Error {
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | /// #     #[error(transparent)]
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | /// #     IO(#[from] std::io::Error),
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | /// #     #[error(transparent)]
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | /// #     Map(#[from] aya::maps::MapError),
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | /// #     #[error(transparent)]
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | /// #     Program(#[from] aya::programs::ProgramError),
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | /// #     #[error(transparent)]
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | /// #     Bpf(#[from] aya::BpfError)
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | /// # }
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | /// # let mut bpf = aya::Bpf::load(&[], None)?;
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | /// use std::convert::{TryFrom, TryInto};
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | /// use std::io::Write;
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | /// use std::net::TcpStream;
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | /// use std::os::unix::io::AsRawFd;
 | 
			
		
	
		
		
			
				
					
					|  |  |  | /// use aya::maps::SockHash;
 |  |  |  | /// use aya::maps::SockHash;
 | 
			
		
	
		
		
			
				
					
					|  |  |  | /// use std::convert::TryFrom;
 |  |  |  | /// use aya::programs::SkMsg;
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | ///
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | /// let mut intercept_egress = SockHash::try_from(bpf.map_mut("INTERCEPT_EGRESS")?)?;
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | /// let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet")?.try_into()?;
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | /// prog.load()?;
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | /// prog.attach(&intercept_egress)?;
 | 
			
		
	
		
		
			
				
					
					|  |  |  | ///
 |  |  |  | ///
 | 
			
		
	
		
		
			
				
					
					|  |  |  | /// const CONFIG_KEY_NUM_RETRIES: u8 = 1;
 |  |  |  | /// let mut client = TcpStream::connect("127.0.0.1:1234")?;
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | /// intercept_egress.insert(1234, client.as_raw_fd(), 0)?;
 | 
			
		
	
		
		
			
				
					
					|  |  |  | ///
 |  |  |  | ///
 | 
			
		
	
		
		
			
				
					
					|  |  |  | /// let mut hm = SockHash::try_from(bpf.map_mut("CONFIG")?)?;
 |  |  |  | /// // the write will be intercepted
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | /// hm.insert(CONFIG_KEY_NUM_RETRIES, 3, 0 /* flags */);
 |  |  |  | /// client.write_all(b"foo")?;
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | /// # Ok::<(), aya::BpfError>(())
 |  |  |  | /// # Ok::<(), Error>(())
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | /// ```
 |  |  |  | /// ```
 | 
			
		
	
		
		
			
				
					
					|  |  |  | #[doc(alias = "BPF_MAP_TYPE_SOCKHASH")] |  |  |  | #[doc(alias = "BPF_MAP_TYPE_SOCKHASH")] | 
			
		
	
		
		
			
				
					
					|  |  |  | pub struct SockHash<T: Deref<Target = Map>, K> { |  |  |  | pub struct SockHash<T: Deref<Target = Map>, K> { | 
			
		
	
	
		
		
			
				
					|  |  | @ -56,8 +82,8 @@ impl<T: Deref<Target = Map>, K: Pod> SockHash<T, K> { | 
			
		
	
		
		
			
				
					
					|  |  |  |         }) |  |  |  |         }) | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /// Returns a copy of the value associated with the key.
 |  |  |  |     /// Returns the fd of the socket stored at the given key.
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     pub unsafe fn get(&self, key: &K, flags: u64) -> Result<u32, MapError> { |  |  |  |     pub unsafe fn get(&self, key: &K, flags: u64) -> Result<RawFd, MapError> { | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         let fd = self.inner.deref().fd_or_err()?; |  |  |  |         let fd = self.inner.deref().fd_or_err()?; | 
			
		
	
		
		
			
				
					
					|  |  |  |         let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(code, io_error)| { |  |  |  |         let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(code, io_error)| { | 
			
		
	
		
		
			
				
					
					|  |  |  |             MapError::SyscallError { |  |  |  |             MapError::SyscallError { | 
			
		
	
	
		
		
			
				
					|  |  | @ -71,7 +97,7 @@ impl<T: Deref<Target = Map>, K: Pod> SockHash<T, K> { | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /// An iterator visiting all key-value pairs in arbitrary order. The
 |  |  |  |     /// An iterator visiting all key-value pairs in arbitrary order. The
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /// iterator item type is `Result<(K, V), MapError>`.
 |  |  |  |     /// iterator item type is `Result<(K, V), MapError>`.
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     pub unsafe fn iter(&self) -> MapIter<'_, K, u32> { |  |  |  |     pub unsafe fn iter(&self) -> MapIter<'_, K, RawFd> { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         MapIter::new(self) |  |  |  |         MapIter::new(self) | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -83,23 +109,23 @@ impl<T: Deref<Target = Map>, K: Pod> SockHash<T, K> { | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | impl<T: DerefMut<Target = Map>, K: Pod> SockHash<T, K> { |  |  |  | impl<T: DerefMut<Target = Map>, K: Pod> SockHash<T, K> { | 
			
		
	
		
		
			
				
					
					|  |  |  |     /// Inserts a key-value pair into the map.
 |  |  |  |     /// Inserts a socket under the given key.
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     pub fn insert<I: AsRawFd>(&mut self, key: K, value: I, flags: u64) -> Result<(), MapError> { |  |  |  |     pub fn insert<I: AsRawFd>(&mut self, key: K, value: I, flags: u64) -> Result<(), MapError> { | 
			
		
	
		
		
			
				
					
					|  |  |  |         hash_map::insert(&mut self.inner, key, value.as_raw_fd(), flags) |  |  |  |         hash_map::insert(&mut self.inner, key, value.as_raw_fd(), flags) | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /// Removes a key from the map.
 |  |  |  |     /// Removes a socket from the map.
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     pub fn remove(&mut self, key: &K) -> Result<(), MapError> { |  |  |  |     pub fn remove(&mut self, key: &K) -> Result<(), MapError> { | 
			
		
	
		
		
			
				
					
					|  |  |  |         hash_map::remove(&mut self.inner, key) |  |  |  |         hash_map::remove(&mut self.inner, key) | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | impl<T: Deref<Target = Map>, K: Pod> IterableMap<K, u32> for SockHash<T, K> { |  |  |  | impl<T: Deref<Target = Map>, K: Pod> IterableMap<K, RawFd> for SockHash<T, K> { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     fn map(&self) -> &Map { |  |  |  |     fn map(&self) -> &Map { | 
			
		
	
		
		
			
				
					
					|  |  |  |         &self.inner |  |  |  |         &self.inner | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     unsafe fn get(&self, key: &K) -> Result<u32, MapError> { |  |  |  |     unsafe fn get(&self, key: &K) -> Result<RawFd, MapError> { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         SockHash::get(self, key, 0) |  |  |  |         SockHash::get(self, key, 0) | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
	
		
		
			
				
					|  |  | 
 |