1use std::fmt;
24use std::path::{PathBuf, Path};
25
26#[cfg(feature = "build_with_net")]
27use std::net::{SocketAddr, IpAddr, Ipv4Addr};
28
29#[cfg(feature = "build_with_tls")]
30use std::sync::Arc;
31
32#[cfg(feature = "build_with_tls")]
33use rustls::pki_types::CertificateDer;
34#[cfg(feature = "build_with_tls")]
35use rustls::pki_types::ServerName;
36#[cfg(feature = "build_with_tls")]
37use rustls::ClientConfig;
38#[cfg(feature = "build_with_tls")]
39use rustls::RootCertStore;
40
41use crate::formatters::SyslogFormatter;
42use crate::throw_error;
43use crate::error::SyRes;
44
45#[cfg(feature = "build_with_net")]
46use crate::map_error;
47
48#[cfg(feature = "build_with_net")]
49#[derive(Copy, Clone, Debug, PartialEq, Eq)]
50pub enum TapTypeDataRemProto
51{
52 Tcp, Udp
53}
54
55#[derive(Clone, Debug)]
56pub enum TapTypeData
57{
58 #[cfg(feature = "build_with_file")]
59 LocalFile
60 {
61 file_path: PathBuf,
62 },
63
64 Local
65 {
66 custom_remote_path: Option<PathBuf>,
67 use_alternative: bool
68 },
69
70 #[cfg(feature = "build_with_net")]
71 Remote
72 {
73 proto: TapTypeDataRemProto,
74 remote_addr: SocketAddr,
75 bind_addr: SocketAddr
76 },
77
78 #[cfg(feature = "build_with_tls")]
79 RemoteTls
80 {
81 remote_addr: SocketAddr,
82 serv_name: ServerName<'static>,
83 client_config: Arc<ClientConfig>
84 }
85}
86
87impl fmt::Display for TapTypeData
88{
89 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
90 {
91 match self
92 {
93 Self::Local{ .. } =>
94 write!(f, "Local Syslog Socket"),
95
96 #[cfg(feature = "build_with_file")]
97 Self::LocalFile{ .. } =>
98 write!(f, "Local File"),
99
100 #[cfg(feature = "build_with_net")]
101 Self::Remote{ .. } =>
102 write!(f, "Remote"),
103
104 #[cfg(feature = "build_with_tls")]
105 Self::RemoteTls{ .. } =>
106 write!(f, "RemoteTLS"),
107 }
108 }
109}
110
111
112impl TapTypeData
113{
114 #[inline]
115 pub(crate)
116 fn is_same_variant(&self, other: &Self) -> bool
117 {
118 return std::mem::discriminant(self) == std::mem::discriminant(other);
119 }
120}
121
122
123
124impl TapTypeData
125{
126 #[cfg(feature = "build_with_file")]
127 pub(crate)
128 fn new_file(path: impl Into<PathBuf>) -> SyRes<Self>
129 {
130 return Ok(
131 Self::LocalFile{ file_path: path.into() }
132 );
133 }
134
135 pub(crate)
145 fn new_unix(custom_path: Option<&Path>, use_alt: bool) -> SyRes<Self>
146 {
147 let remote_path: Option<PathBuf> =
148 if let Some(path) = custom_path
149 {
150 if use_alt == false
151 {
152 if path.exists() == false || path.is_file() == false
153 {
154 throw_error!("path either does not exists or not a file: '{}'", path.display());
155 }
156 }
157
158 Some(path.to_path_buf())
159 }
160 else
161 {
162 None
163 };
164
165 return Ok(
166 Self::Local{ custom_remote_path: remote_path, use_alternative: use_alt }
167 );
168 }
169
170 #[cfg(feature = "build_with_net")]
171 pub(crate)
172 fn new_net<P>(proto: TapTypeDataRemProto, remote: P, local: Option<P>) -> SyRes<Self>
173 where P: AsRef<str>
174 {
175 let remote_addr: SocketAddr =
176 remote
177 .as_ref()
178 .parse()
179 .map_err(|e|
180 map_error!("failed parsing remote addr '{}', error: '{}'", remote.as_ref(), e)
181 )?;
182
183 let bind_addr: SocketAddr =
184 if let Some(bind) = local
185 {
186 bind
187 .as_ref()
188 .parse()
189 .map_err(|e|
190 map_error!("failed parsing bind addr '{}', error: '{}'", remote.as_ref(), e)
191 )?
192 }
193 else
194 {
195 SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0)
196 };
197
198 return Ok(
199 Self::Remote{ proto: proto, remote_addr: remote_addr, bind_addr: bind_addr }
200 );
201 }
202
203 #[cfg(feature = "build_with_tls")]
204 pub(crate)
205 fn new_tls<P>(remote: P, server_name: &str, cert: &[u8]) -> SyRes<Self>
206 where P: AsRef<str>
207 {
208 use rustls::pki_types::pem::PemObject;
209
210 let remote_addr: SocketAddr =
211 remote
212 .as_ref()
213 .parse()
214 .map_err(|e|
215 map_error!("failed parsing remote addr '{}', error: '{}'", remote.as_ref(), e)
216 )?;
217
218 let cert =
219 CertificateDer::from_pem_slice(cert)
220 .map_err(|e|
221 map_error!("certificate parse error: '{}'", e)
222 )?;
223
224 let mut root_store = RootCertStore::empty();
225 root_store
226 .add(cert)
227 .map_err(|e|
228 map_error!("can not add root ceritficate, error: '{}'", e)
229 )?;
230
231 let serv_name =
232 server_name
233 .to_string()
234 .try_into()
235 .map_err(|e|
236 map_error!("server name error: '{}'", e)
237 )?;
238
239 let client_config =
240 rustls::ClientConfig::builder()
241 .with_root_certificates(root_store)
242 .with_no_client_auth();
243
244 return Ok(
245 Self::RemoteTls{ remote_addr: remote_addr, serv_name: serv_name, client_config: Arc::new(client_config) }
246 );
247 }
248
249
250 #[cfg(feature = "build_with_net")]
251 #[allow(unused)]
252 #[inline]
253 pub(crate)
254 fn get_net_proto(&self) -> TapTypeDataRemProto
255 {
256 let Self::Remote { proto, .. } = self
257 else { panic!("Assertion trap: TapTypeData is not remote, misused!") };
258
259 return *proto;
260 }
261
262 #[allow(unused)]
263 #[inline]
264 pub(crate)
265 fn get_max_msg_length<F: SyslogFormatter>(&self) -> usize
266 {
267 use crate::common;
268
269 match self
270 {
271 TapTypeData::Local{ .. } =>
272 {
273 if *common::RFC5424_MAX_DGRAM >= common::MAXLINE
274 {
275 return common::MAXLINE;
276 }
277 else
278 {
279 return *common::RFC5424_MAX_DGRAM;
280 };
281 },
282 TapTypeData::Remote{ proto, .. } =>
283 {
284 match proto
285 {
286 TapTypeDataRemProto::Tcp =>
287 return common::RFC5424_TCP_MAX_PKT_LEN,
288 TapTypeDataRemProto::Udp =>
289 return common::RFC5424_UDP_MAX_PKT_LEN,
290 }
291 },
292 TapTypeData::LocalFile{ .. } =>
293 return common::MAXLINE,
294 TapTypeData::RemoteTls{ .. } =>
295 return common::RFC5424_TCP_MAX_PKT_LEN
296 }
297 }
298}
299
300
301
302
303
304#[derive(Copy, Clone, Debug, PartialEq, Eq)]
306pub enum TapType
307{
308 None,
310
311 UnPriv,
313
314 Priv,
316
317 OldLog,
319
320 CustomLog,
322
323 LocalFile,
325
326 NetUdp,
328
329 NetTcp,
331
332 NetTls,
334}
335
336impl fmt::Display for TapType
337{
338 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
339 {
340 match self
341 {
342 Self::None =>
343 write!(f, "NO TYPE"),
344 Self::UnPriv =>
345 write!(f, "UNPRIV"),
346 Self::Priv =>
347 write!(f, "PRIV"),
348 Self::OldLog =>
349 write!(f, "OLD LOG"),
350 Self::CustomLog =>
351 write!(f, "CUSTOM LOG"),
352 Self::LocalFile =>
353 write!(f, "LOCAL FILE"),
354 Self::NetUdp =>
355 write!(f, "NET UDP"),
356 Self::NetTcp =>
357 write!(f, "NET TCP"),
358 Self::NetTls =>
359 write!(f, "NET TLS TCP")
360 }
361 }
362}
363
364impl TapType
365{
366 pub(crate)
367 fn is_priv(&self) -> bool
368 {
369 return *self == Self::Priv;
370 }
371
372 pub(crate)
373 fn is_network(&self) -> bool
374 {
375 return *self == Self::NetTcp || *self == Self::NetUdp;
376 }
377
378 pub(crate)
379 fn is_file(&self) -> bool
380 {
381 return *self == Self::LocalFile;
382 }
383
384}