tc.rs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. use aya_bpf_cty::{c_long, c_void};
  2. use crate::{bindings::__sk_buff, programs::sk_buff::SkBuff, BpfContext};
  3. pub struct TcContext {
  4. pub skb: SkBuff,
  5. }
  6. impl TcContext {
  7. pub fn new(skb: *mut __sk_buff) -> TcContext {
  8. let skb = SkBuff { skb };
  9. TcContext { skb }
  10. }
  11. #[allow(clippy::len_without_is_empty)]
  12. #[inline]
  13. pub fn len(&self) -> u32 {
  14. self.skb.len()
  15. }
  16. #[inline]
  17. pub fn data(&self) -> usize {
  18. self.skb.data()
  19. }
  20. #[inline]
  21. pub fn data_end(&self) -> usize {
  22. self.skb.data_end()
  23. }
  24. #[inline]
  25. pub fn set_mark(&mut self, mark: u32) {
  26. self.skb.set_mark(mark)
  27. }
  28. #[inline]
  29. pub fn cb(&self) -> &[u32] {
  30. self.skb.cb()
  31. }
  32. #[inline]
  33. pub fn cb_mut(&mut self) -> &mut [u32] {
  34. self.skb.cb_mut()
  35. }
  36. /// Returns the owner UID of the socket associated to the SKB context.
  37. #[inline]
  38. pub fn get_socket_uid(&self) -> u32 {
  39. self.skb.get_socket_uid()
  40. }
  41. #[inline]
  42. pub fn load<T>(&self, offset: usize) -> Result<T, c_long> {
  43. self.skb.load(offset)
  44. }
  45. /// Reads some bytes from the packet into the specified buffer, returning
  46. /// how many bytes were read.
  47. ///
  48. /// Starts reading at `offset` and reads at most `dst.len()` or
  49. /// `self.len() - offset` bytes, depending on which one is smaller.
  50. ///
  51. /// # Examples
  52. ///
  53. /// Read into a `PerCpuArray`.
  54. ///
  55. /// ```no_run
  56. /// use core::mem;
  57. ///
  58. /// use aya_bpf::{bindings::TC_ACT_PIPE, macros::map, maps::PerCpuArray, programs::TcContext};
  59. /// # #[allow(non_camel_case_types)]
  60. /// # struct ethhdr {};
  61. /// # #[allow(non_camel_case_types)]
  62. /// # struct iphdr {};
  63. /// # #[allow(non_camel_case_types)]
  64. /// # struct tcphdr {};
  65. ///
  66. /// const ETH_HDR_LEN: usize = mem::size_of::<ethhdr>();
  67. /// const IP_HDR_LEN: usize = mem::size_of::<iphdr>();
  68. /// const TCP_HDR_LEN: usize = mem::size_of::<tcphdr>();
  69. ///
  70. /// #[repr(C)]
  71. /// pub struct Buf {
  72. /// pub buf: [u8; 1500],
  73. /// }
  74. ///
  75. /// #[map]
  76. /// pub static mut BUF: PerCpuArray<Buf> = PerCpuArray::with_max_entries(1, 0);
  77. ///
  78. /// fn try_classifier(ctx: TcContext) -> Result<i32, i32> {
  79. /// let buf = unsafe {
  80. /// let ptr = BUF.get_ptr_mut(0).ok_or(TC_ACT_PIPE)?;
  81. /// &mut *ptr
  82. /// };
  83. /// let offset = ETH_HDR_LEN + IP_HDR_LEN + TCP_HDR_LEN;
  84. /// ctx.load_bytes(offset, &mut buf.buf).map_err(|_| TC_ACT_PIPE)?;
  85. ///
  86. /// // do something with `buf`
  87. ///
  88. /// Ok(TC_ACT_PIPE)
  89. /// }
  90. /// ```
  91. #[inline(always)]
  92. pub fn load_bytes(&self, offset: usize, dst: &mut [u8]) -> Result<usize, c_long> {
  93. self.skb.load_bytes(offset, dst)
  94. }
  95. #[inline]
  96. pub fn store<T>(&mut self, offset: usize, v: &T, flags: u64) -> Result<(), c_long> {
  97. self.skb.store(offset, v, flags)
  98. }
  99. #[inline]
  100. pub fn l3_csum_replace(
  101. &self,
  102. offset: usize,
  103. from: u64,
  104. to: u64,
  105. size: u64,
  106. ) -> Result<(), c_long> {
  107. self.skb.l3_csum_replace(offset, from, to, size)
  108. }
  109. #[inline]
  110. pub fn l4_csum_replace(
  111. &self,
  112. offset: usize,
  113. from: u64,
  114. to: u64,
  115. flags: u64,
  116. ) -> Result<(), c_long> {
  117. self.skb.l4_csum_replace(offset, from, to, flags)
  118. }
  119. #[inline]
  120. pub fn adjust_room(&self, len_diff: i32, mode: u32, flags: u64) -> Result<(), c_long> {
  121. self.skb.adjust_room(len_diff, mode, flags)
  122. }
  123. #[inline]
  124. pub fn clone_redirect(&self, if_index: u32, flags: u64) -> Result<(), c_long> {
  125. self.skb.clone_redirect(if_index, flags)
  126. }
  127. #[inline]
  128. pub fn change_type(&self, ty: u32) -> Result<(), c_long> {
  129. self.skb.change_type(ty)
  130. }
  131. /// Pulls in non-linear data in case the skb is non-linear.
  132. ///
  133. /// Make len bytes from skb readable and writable. If a zero value is passed for
  134. /// `len`, then the whole length of the skb is pulled. This helper is only needed
  135. /// for reading and writing with direct packet access.
  136. ///
  137. /// # Examples
  138. ///
  139. /// ```no_run
  140. /// mod bindings;
  141. /// use bindings::{ethhdr, iphdr, udphdr};
  142. ///
  143. /// const ETH_HLEN: usize = core::mem::size_of::<ethhdr>();
  144. /// const IP_HLEN: usize = core::mem::size_of::<iphdr>();
  145. /// const UDP_HLEN: usize = core::mem::size_of::<udphdr>();
  146. ///
  147. /// fn try_classifier(ctx: TcContext) -> Result<i32, i32> {
  148. /// let len = ETH_HLEN + IP_HLEN + UDP_HLEN;
  149. /// match ctx.pull_data(len as u32) {
  150. /// Ok(_) => return Ok(0),
  151. /// Err(ret) => return Err(ret as i32),
  152. /// }
  153. /// }
  154. /// ```
  155. #[inline(always)]
  156. pub fn pull_data(&self, len: u32) -> Result<(), c_long> {
  157. self.skb.pull_data(len)
  158. }
  159. }
  160. impl BpfContext for TcContext {
  161. fn as_ptr(&self) -> *mut c_void {
  162. self.skb.as_ptr()
  163. }
  164. }