1#[cfg(feature = "nat")]
4use crate::nat::NatConfig;
5use serde::{Deserialize, Serialize};
6use std::net::{IpAddr, Ipv4Addr, SocketAddr};
7use std::path::PathBuf;
8use std::time::Duration;
9
10#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
12pub struct OverlayConfig {
13 pub local_endpoint: SocketAddr,
15
16 pub private_key: String,
18
19 #[serde(default = "OverlayConfig::default_public_key")]
21 pub public_key: String,
22
23 #[serde(default = "OverlayConfig::default_cidr")]
29 pub overlay_cidr: String,
30
31 #[serde(default)]
40 pub cluster_cidr: Option<String>,
41
42 #[serde(default = "OverlayConfig::default_discovery")]
44 pub peer_discovery_interval: Duration,
45
46 #[cfg(feature = "nat")]
48 #[serde(default)]
49 pub nat: NatConfig,
50
51 #[serde(default = "OverlayConfig::default_uapi_sock_dir")]
57 pub uapi_sock_dir: PathBuf,
58
59 #[serde(default = "default_mtu")]
73 pub mtu: u32,
74}
75
76fn default_mtu() -> u32 {
79 1420
80}
81
82impl OverlayConfig {
83 fn default_public_key() -> String {
84 String::new()
85 }
86
87 fn default_cidr() -> String {
88 "10.0.0.0/8".to_string()
89 }
90
91 fn default_discovery() -> Duration {
92 Duration::from_secs(30)
93 }
94
95 fn default_uapi_sock_dir() -> PathBuf {
103 PathBuf::from("/var/run/wireguard")
104 }
105}
106
107impl Default for OverlayConfig {
108 fn default() -> Self {
109 Self {
110 local_endpoint: SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 51820),
111 private_key: String::new(),
112 public_key: String::new(),
113 overlay_cidr: "10.0.0.0/8".to_string(),
114 cluster_cidr: None,
115 peer_discovery_interval: Duration::from_secs(30),
116 #[cfg(feature = "nat")]
117 nat: NatConfig::default(),
118 uapi_sock_dir: Self::default_uapi_sock_dir(),
119 mtu: default_mtu(),
120 }
121 }
122}
123
124#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
126pub struct PeerInfo {
127 pub public_key: String,
129
130 pub endpoint: SocketAddr,
132
133 pub allowed_ips: String,
135
136 pub persistent_keepalive_interval: Duration,
138}
139
140impl PeerInfo {
141 #[must_use]
143 pub fn new(
144 public_key: String,
145 endpoint: SocketAddr,
146 allowed_ips: &str,
147 persistent_keepalive_interval: Duration,
148 ) -> Self {
149 Self {
150 public_key,
151 endpoint,
152 allowed_ips: allowed_ips.to_string(),
153 persistent_keepalive_interval,
154 }
155 }
156
157 #[must_use]
159 pub fn to_peer_config(&self) -> String {
160 format!(
161 "[Peer]\n\
162 PublicKey = {}\n\
163 Endpoint = {}\n\
164 AllowedIPs = {}\n\
165 PersistentKeepalive = {}\n",
166 self.public_key,
167 self.endpoint,
168 self.allowed_ips,
169 self.persistent_keepalive_interval.as_secs()
170 )
171 }
172}
173
174#[cfg(test)]
175mod tests {
176 use super::*;
177
178 #[test]
179 fn test_peer_info_to_peer_config() {
180 let peer = PeerInfo::new(
181 "public_key_here".to_string(),
182 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1)), 51820),
183 "10.0.0.2/32",
184 Duration::from_secs(25),
185 );
186
187 let config = peer.to_peer_config();
188 assert!(config.contains("PublicKey = public_key_here"));
189 assert!(config.contains("Endpoint = 192.168.1.1:51820"));
190 }
191
192 #[test]
193 fn test_overlay_config_default() {
194 let config = OverlayConfig::default();
195 assert_eq!(config.local_endpoint.port(), 51820);
196 assert_eq!(config.overlay_cidr, "10.0.0.0/8");
197 }
198
199 #[test]
200 fn test_peer_info_to_peer_config_v6() {
201 use std::net::Ipv6Addr;
202
203 let peer = PeerInfo::new(
204 "public_key_here".to_string(),
205 SocketAddr::new(IpAddr::V6(Ipv6Addr::LOCALHOST), 51820),
206 "fd00::2/128",
207 Duration::from_secs(25),
208 );
209
210 let config = peer.to_peer_config();
211 assert!(config.contains("PublicKey = public_key_here"));
212 assert!(config.contains("Endpoint = [::1]:51820"));
213 assert!(config.contains("AllowedIPs = fd00::2/128"));
214 }
215
216 #[test]
217 fn test_overlay_config_accepts_ipv6_cidr() {
218 let config = OverlayConfig {
219 overlay_cidr: "fd00:200::/48".to_string(),
220 ..OverlayConfig::default()
221 };
222 assert_eq!(config.overlay_cidr, "fd00:200::/48");
223 }
224
225 #[test]
226 fn test_overlay_config_default_mtu() {
227 let config = OverlayConfig::default();
228 assert_eq!(config.mtu, 1420);
229 }
230
231 #[test]
232 fn test_overlay_config_mtu_serde_round_trip() {
233 let config = OverlayConfig {
234 mtu: 1280,
235 ..OverlayConfig::default()
236 };
237 let json = serde_json::to_string(&config).expect("serialize");
238 assert!(json.contains("\"mtu\":1280"));
239 let decoded: OverlayConfig = serde_json::from_str(&json).expect("deserialize");
240 assert_eq!(decoded, config);
241 assert_eq!(decoded.mtu, 1280);
242 }
243
244 #[test]
245 fn test_overlay_config_missing_mtu_defaults() {
246 let json = r#"{
249 "local_endpoint": "0.0.0.0:51820",
250 "private_key": ""
251 }"#;
252 let config: OverlayConfig = serde_json::from_str(json).expect("deserialize without mtu");
253 assert_eq!(config.mtu, 1420);
254 }
255}