rsln/types/
addr.rs

1use std::net::IpAddr;
2
3use anyhow::Result;
4use derive_builder::Builder;
5use ipnet::IpNet;
6
7use super::{
8    message::{AddressMessage, Attribute, RouteAttrs},
9    vec_to_addr,
10};
11
12pub enum AddrCmd {
13    Add,
14    Change,
15    Replace,
16    Delete,
17}
18
19pub enum AddrFamily {
20    All = 0,
21    V4 = 2,
22    V6 = 10,
23}
24
25impl From<AddrFamily> for i32 {
26    fn from(val: AddrFamily) -> Self {
27        val as i32
28    }
29}
30
31impl From<u16> for AddrFamily {
32    fn from(val: u16) -> Self {
33        match val {
34            2 => Self::V4,
35            10 => Self::V6,
36            _ => Self::All,
37        }
38    }
39}
40
41#[derive(Default, Builder, Debug)]
42#[builder(default)]
43pub struct Address {
44    pub index: i32,
45    pub ip: IpNet,
46    pub label: String,
47    pub flags: u8,
48    pub scope: u8,
49    pub broadcast: Option<IpAddr>,
50    pub peer: Option<IpNet>,
51    pub preferred_lifetime: i32,
52    pub valid_lifetime: i32,
53}
54
55impl From<&[u8]> for Address {
56    fn from(buf: &[u8]) -> Self {
57        let addr_msg: AddressMessage = bincode::deserialize(buf).unwrap();
58        let attrs = RouteAttrs::from(&buf[addr_msg.len()..]);
59
60        let mut addr = Self {
61            index: addr_msg.index,
62            scope: addr_msg.scope,
63            ..Default::default()
64        };
65
66        for attr in attrs {
67            match attr.header.rta_type {
68                libc::IFA_ADDRESS => {
69                    addr.update_address(&attr.payload, addr_msg.prefix_len)
70                        .unwrap();
71                }
72                libc::IFA_LOCAL => {}
73                _ => {}
74            }
75        }
76
77        addr
78    }
79}
80
81impl Address {
82    pub fn update_address(&mut self, payload: &[u8], prefix_len: u8) -> Result<()> {
83        let ip = vec_to_addr(payload)?;
84        self.ip = IpNet::new(ip, prefix_len)?;
85        Ok(())
86    }
87}
88
89#[cfg(test)]
90mod tests {
91    use crate::types::message::{Payload, RouteAttr, RouteAttrHeader};
92
93    use super::*;
94
95    #[test]
96    fn test_address_builder() {
97        let address = AddressBuilder::default().build().unwrap();
98        assert_eq!(address.index, 0);
99    }
100
101    #[test]
102    fn test_update_address_ipv4() {
103        let mut address = Address::default();
104        let payload = Payload::from(&[192, 168, 1, 1][..]);
105        let prefix_len = 24;
106
107        address.update_address(&payload, prefix_len).unwrap();
108
109        assert_eq!(address.ip, IpNet::V4("192.168.1.1/24".parse().unwrap()));
110    }
111
112    #[test]
113    fn test_update_address_ipv6() {
114        let mut address = Address::default();
115        let payload = vec![
116            0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0x02, 0x60, 0x97, 0xff, 0xfe, 0x07, 0x69, 0xea,
117        ];
118        let prefix_len = 64;
119
120        address.update_address(&payload, prefix_len).unwrap();
121
122        assert_eq!(
123            address.ip,
124            IpNet::V6("fe80::260:97ff:fe07:69ea/64".parse().unwrap())
125        );
126    }
127
128    #[test]
129    fn test_from_bytes() {
130        let addr_msg = AddressMessage {
131            index: 1,
132            scope: 2,
133            prefix_len: 24,
134            ..Default::default()
135        };
136        let mut rt_attrs = RouteAttrs::default();
137        rt_attrs.push(RouteAttr {
138            header: RouteAttrHeader {
139                rta_type: libc::IFA_ADDRESS,
140                rta_len: 8,
141            },
142            payload: Payload::from(&[192, 168, 1, 1][..]),
143            attributes: None,
144        });
145
146        let mut buf = AddressMessage::serialize(&addr_msg).unwrap();
147        buf.extend_from_slice(RouteAttrs::serialize(&rt_attrs).unwrap().as_slice());
148
149        let address = Address::from(&buf[..]);
150
151        assert_eq!(address.index, addr_msg.index);
152        assert_eq!(address.scope, addr_msg.scope);
153    }
154}