netlink_packet_route/tc/actions/
nat.rs

1// SPDX-License-Identifier: MIT
2
3/// Nat action
4///
5/// The nat action maps one IP prefix to another
6use std::net::Ipv4Addr;
7
8use netlink_packet_utils::nla::{DefaultNla, Nla, NlaBuffer};
9use netlink_packet_utils::traits::{Emitable, Parseable};
10use netlink_packet_utils::DecodeError;
11
12use super::nat_flag::TcNatFlags;
13use super::{TcActionGeneric, TcActionGenericBuffer};
14
15const TCA_NAT_PARMS: u16 = 1;
16const TCA_NAT_TM: u16 = 2;
17
18/// Network address translation action.
19#[derive(Debug, PartialEq, Eq, Clone)]
20#[non_exhaustive]
21pub struct TcActionNat {}
22
23impl TcActionNat {
24    pub(crate) const KIND: &'static str = "nat";
25}
26
27/// Options for the [`TcActionNat`] action.
28#[derive(Debug, PartialEq, Eq, Clone)]
29#[non_exhaustive]
30pub enum TcActionNatOption {
31    /// TODO: document this after we make it something better than `Vec<u8>`
32    Tm(Vec<u8>),
33    /// Parameters for the nat action.
34    Parms(TcNat),
35    /// Other attributes unknown at the time of writing.
36    Other(DefaultNla),
37}
38
39impl Nla for TcActionNatOption {
40    fn value_len(&self) -> usize {
41        match self {
42            Self::Tm(bytes) => bytes.len(),
43            Self::Parms(v) => v.buffer_len(),
44            Self::Other(attr) => attr.value_len(),
45        }
46    }
47
48    fn emit_value(&self, buffer: &mut [u8]) {
49        match self {
50            Self::Tm(bytes) => buffer.copy_from_slice(bytes.as_slice()),
51            Self::Parms(p) => p.emit(buffer),
52            Self::Other(attr) => attr.emit_value(buffer),
53        }
54    }
55    fn kind(&self) -> u16 {
56        match self {
57            Self::Tm(_) => TCA_NAT_TM,
58            Self::Parms(_) => TCA_NAT_PARMS,
59            Self::Other(nla) => nla.kind(),
60        }
61    }
62}
63
64impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<NlaBuffer<&'a T>> for TcActionNatOption {
65    type Error = DecodeError;
66    fn parse(buf: &NlaBuffer<&'a T>) -> Result<Self, DecodeError> {
67        let payload = buf.value();
68        Ok(match buf.kind() {
69            TCA_NAT_TM => Self::Tm(payload.to_vec()),
70            TCA_NAT_PARMS => Self::Parms(TcNat::parse(&TcNatBuffer::new_checked(payload)?)?),
71            _ => Self::Other(DefaultNla::parse(buf)?),
72        })
73    }
74}
75
76const TC_NAT_BUF_LEN: usize = TcActionGeneric::BUF_LEN + 16;
77
78/// Network address translation action.
79#[derive(Debug, PartialEq, Eq, Clone)]
80#[non_exhaustive]
81pub struct TcNat {
82    /// Common attributes for all actions.
83    pub generic: TcActionGeneric,
84    /// Original address.
85    pub old_addr: Ipv4Addr,
86    /// New address.
87    pub new_addr: Ipv4Addr,
88    /// Mask of the old address
89    pub mask: Ipv4Addr,
90    /// Flags for the NAT action.
91    pub flags: TcNatFlags,
92}
93
94impl Default for TcNat {
95    fn default() -> Self {
96        Self {
97            generic: TcActionGeneric::default(),
98            old_addr: Ipv4Addr::UNSPECIFIED,
99            new_addr: Ipv4Addr::UNSPECIFIED,
100            mask: Ipv4Addr::UNSPECIFIED,
101            flags: TcNatFlags::empty(),
102        }
103    }
104}
105
106buffer!(TcNatBuffer(TC_NAT_BUF_LEN) {
107    generic: (slice, 0..TcActionGeneric::BUF_LEN),
108    old_addr: (slice, TcActionGeneric::BUF_LEN..(TcActionGeneric::BUF_LEN+4)),
109    new_addr: (slice, (TcActionGeneric::BUF_LEN+4)..(TcActionGeneric::BUF_LEN+8)),
110    mask: (slice, (TcActionGeneric::BUF_LEN+8)..(TcActionGeneric::BUF_LEN+12)),
111    flags: (u32, (TcActionGeneric::BUF_LEN+12)..TC_NAT_BUF_LEN),
112});
113
114impl Emitable for TcNat {
115    fn buffer_len(&self) -> usize {
116        TC_NAT_BUF_LEN
117    }
118
119    fn emit(&self, buffer: &mut [u8]) {
120        let mut packet = TcNatBuffer::new(buffer);
121        self.generic.emit(packet.generic_mut());
122        packet.old_addr_mut().copy_from_slice(&self.old_addr.octets());
123        packet.new_addr_mut().copy_from_slice(&self.new_addr.octets());
124        packet.mask_mut().copy_from_slice(&self.mask.octets());
125        packet.set_flags(self.flags.bits());
126    }
127}
128
129impl<'a, T: AsRef<[u8]> + ?Sized> Parseable<TcNatBuffer<&'a T>> for TcNat {
130    type Error = DecodeError;
131    fn parse(buf: &TcNatBuffer<&T>) -> Result<Self, DecodeError> {
132        Ok(Self {
133            generic: TcActionGeneric::parse(&TcActionGenericBuffer::new(buf.generic()))?,
134            old_addr: parse_ipv4(buf.old_addr())?,
135            new_addr: parse_ipv4(buf.new_addr())?,
136            mask: parse_ipv4(buf.mask())?,
137            flags: TcNatFlags::from_bits_retain(buf.flags()),
138        })
139    }
140}
141
142fn parse_ipv4(data: &[u8]) -> Result<Ipv4Addr, DecodeError> {
143    if data.len() != 4 {
144        Err(DecodeError::InvalidIPAddress)
145    } else {
146        Ok(Ipv4Addr::new(data[0], data[1], data[2], data[3]))
147    }
148}