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}