netlink_packet_route/tc/actions/
nat.rs1use std::net::Ipv4Addr;
7
8use netlink_packet_utils::{
9 nla::{DefaultNla, Nla, NlaBuffer},
10 traits::{Emitable, Parseable},
11 DecodeError,
12};
13
14use super::{
15 nat_flag::TcNatFlags, TcActionGeneric, TcActionGenericBuffer, Tcf,
16 TcfBuffer, TC_TCF_BUF_LEN,
17};
18
19const TCA_NAT_PARMS: u16 = 1;
20const TCA_NAT_TM: u16 = 2;
21
22#[derive(Debug, PartialEq, Eq, Clone)]
24#[non_exhaustive]
25pub struct TcActionNat {}
26
27impl TcActionNat {
28 pub(crate) const KIND: &'static str = "nat";
29}
30
31#[derive(Debug, PartialEq, Eq, Clone)]
33#[non_exhaustive]
34pub enum TcActionNatOption {
35 Tm(Tcf),
37 Parms(TcNat),
39 Other(DefaultNla),
41}
42
43impl Nla for TcActionNatOption {
44 fn value_len(&self) -> usize {
45 match self {
46 Self::Tm(_) => TC_TCF_BUF_LEN,
47 Self::Parms(v) => v.buffer_len(),
48 Self::Other(attr) => attr.value_len(),
49 }
50 }
51
52 fn emit_value(&self, buffer: &mut [u8]) {
53 match self {
54 Self::Tm(p) => p.emit(buffer),
55 Self::Parms(p) => p.emit(buffer),
56 Self::Other(attr) => attr.emit_value(buffer),
57 }
58 }
59 fn kind(&self) -> u16 {
60 match self {
61 Self::Tm(_) => TCA_NAT_TM,
62 Self::Parms(_) => TCA_NAT_PARMS,
63 Self::Other(nla) => nla.kind(),
64 }
65 }
66}
67
68impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>>
69 for TcActionNatOption
70{
71 fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
72 let payload = buf.value();
73 Ok(match buf.kind() {
74 TCA_NAT_TM => {
75 Self::Tm(Tcf::parse(&TcfBuffer::new_checked(payload)?)?)
76 }
77 TCA_NAT_PARMS => {
78 Self::Parms(TcNat::parse(&TcNatBuffer::new_checked(payload)?)?)
79 }
80 _ => Self::Other(DefaultNla::parse(buf)?),
81 })
82 }
83}
84
85const TC_NAT_BUF_LEN: usize = TcActionGeneric::BUF_LEN + 16;
86
87#[derive(Debug, PartialEq, Eq, Clone)]
89#[non_exhaustive]
90pub struct TcNat {
91 pub generic: TcActionGeneric,
93 pub old_addr: Ipv4Addr,
95 pub new_addr: Ipv4Addr,
97 pub mask: Ipv4Addr,
99 pub flags: TcNatFlags,
101}
102
103impl Default for TcNat {
104 fn default() -> Self {
105 Self {
106 generic: TcActionGeneric::default(),
107 old_addr: Ipv4Addr::UNSPECIFIED,
108 new_addr: Ipv4Addr::UNSPECIFIED,
109 mask: Ipv4Addr::UNSPECIFIED,
110 flags: TcNatFlags::empty(),
111 }
112 }
113}
114
115buffer!(TcNatBuffer(TC_NAT_BUF_LEN) {
116 generic: (slice, 0..TcActionGeneric::BUF_LEN),
117 old_addr: (slice, TcActionGeneric::BUF_LEN..(TcActionGeneric::BUF_LEN+4)),
118 new_addr: (slice, (TcActionGeneric::BUF_LEN+4)..(TcActionGeneric::BUF_LEN+8)),
119 mask: (slice, (TcActionGeneric::BUF_LEN+8)..(TcActionGeneric::BUF_LEN+12)),
120 flags: (u32, (TcActionGeneric::BUF_LEN+12)..TC_NAT_BUF_LEN),
121});
122
123impl Emitable for TcNat {
124 fn buffer_len(&self) -> usize {
125 TC_NAT_BUF_LEN
126 }
127
128 fn emit(&self, buffer: &mut [u8]) {
129 let mut packet = TcNatBuffer::new(buffer);
130 self.generic.emit(packet.generic_mut());
131 packet
132 .old_addr_mut()
133 .copy_from_slice(&self.old_addr.octets());
134 packet
135 .new_addr_mut()
136 .copy_from_slice(&self.new_addr.octets());
137 packet.mask_mut().copy_from_slice(&self.mask.octets());
138 packet.set_flags(self.flags.bits());
139 }
140}
141
142impl<T: AsRef<[u8]> + ?Sized> Parseable<TcNatBuffer<&T>> for TcNat {
143 fn parse(buf: &TcNatBuffer<&T>) -> Result<Self, DecodeError> {
144 Ok(Self {
145 generic: TcActionGeneric::parse(&TcActionGenericBuffer::new(
146 buf.generic(),
147 ))?,
148 old_addr: parse_ipv4(buf.old_addr())?,
149 new_addr: parse_ipv4(buf.new_addr())?,
150 mask: parse_ipv4(buf.mask())?,
151 flags: TcNatFlags::from_bits_retain(buf.flags()),
152 })
153 }
154}
155
156fn parse_ipv4(data: &[u8]) -> Result<Ipv4Addr, DecodeError> {
157 if data.len() != 4 {
158 Err(DecodeError::from(format!(
159 "Invalid length of IPv4 Address, expecting 4 bytes, but got {:?}",
160 data
161 )))
162 } else {
163 Ok(Ipv4Addr::new(data[0], data[1], data[2], data[3]))
164 }
165}