rtnetlink/addr/
builder.rs

1// SPDX-License-Identifier: MIT
2
3use std::{
4    marker::PhantomData,
5    net::{Ipv4Addr, Ipv6Addr},
6};
7
8use netlink_packet_route::{
9    address::{AddressAttribute, AddressMessage},
10    AddressFamily,
11};
12
13#[derive(Debug)]
14/// Helper struct for building [AddressMessage].
15pub struct AddressMessageBuilder<T> {
16    message: AddressMessage,
17    _phantom: PhantomData<T>,
18}
19
20impl<T> AddressMessageBuilder<T> {
21    /// Create a new [AddressMessageBuilder] without specifying the address
22    /// family.
23    fn new_no_address_family() -> Self {
24        AddressMessageBuilder {
25            message: AddressMessage::default(),
26            _phantom: PhantomData,
27        }
28    }
29
30    /// Sets the interface index.
31    pub fn index(mut self, index: u32) -> Self {
32        self.message.header.index = index;
33        self
34    }
35
36    /// Builds [AddressMessage].
37    pub fn build(self) -> AddressMessage {
38        self.message
39    }
40}
41
42impl Default for AddressMessageBuilder<Ipv4Addr> {
43    fn default() -> Self {
44        Self::new()
45    }
46}
47
48impl AddressMessageBuilder<Ipv4Addr> {
49    /// Create a new [AddressMessageBuilder] for IPv4 addresses.
50    pub fn new() -> Self {
51        let mut builder = Self::new_no_address_family();
52        builder.message.header.family = AddressFamily::Inet;
53        builder
54    }
55
56    /// Sets the address and prefix length.
57    pub fn address(mut self, address: Ipv4Addr, prefix_len: u8) -> Self {
58        self.message.header.prefix_len = prefix_len;
59
60        if !address.is_multicast() {
61            self.message
62                .attributes
63                .push(AddressAttribute::Address(address.into()));
64
65            // The IFA_LOCAL address can be set to the same value as
66            // IFA_ADDRESS.
67            self.message
68                .attributes
69                .push(AddressAttribute::Local(address.into()));
70
71            // Set the IFA_BROADCAST address as well.
72            if prefix_len == 32 {
73                self.message
74                    .attributes
75                    .push(AddressAttribute::Broadcast(address));
76            } else {
77                let ip_addr = u32::from(address);
78                let brd = Ipv4Addr::from(
79                    (0xffff_ffff_u32) >> u32::from(prefix_len) | ip_addr,
80                );
81                self.message
82                    .attributes
83                    .push(AddressAttribute::Broadcast(brd));
84            };
85        }
86
87        self
88    }
89}
90
91impl Default for AddressMessageBuilder<Ipv6Addr> {
92    fn default() -> Self {
93        Self::new()
94    }
95}
96
97impl AddressMessageBuilder<Ipv6Addr> {
98    /// Create a new [AddressMessageBuilder] for IPv6 addresses.
99    pub fn new() -> Self {
100        let mut builder = Self::new_no_address_family();
101        builder.message.header.family = AddressFamily::Inet6;
102        builder
103    }
104
105    /// Sets the address and prefix length.
106    pub fn address(mut self, address: Ipv6Addr, prefix_len: u8) -> Self {
107        self.message.header.prefix_len = prefix_len;
108
109        if address.is_multicast() {
110            self.message
111                .attributes
112                .push(AddressAttribute::Multicast(address));
113        } else {
114            self.message
115                .attributes
116                .push(AddressAttribute::Address(address.into()));
117
118            // The IFA_LOCAL address can be set to the same value as
119            // IFA_ADDRESS.
120            self.message
121                .attributes
122                .push(AddressAttribute::Local(address.into()));
123        }
124
125        self
126    }
127}