huginn_net_db/
display.rs

1use crate::db::Label;
2use core::fmt;
3use std::fmt::Formatter;
4
5impl fmt::Display for Label {
6    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
7        write!(
8            f,
9            "{}:{}:{}:{}",
10            self.ty,
11            self.class.as_deref().unwrap_or_default(),
12            self.name,
13            self.flavor.as_deref().unwrap_or_default()
14        )
15    }
16}
17
18mod tcp {
19    use crate::observable_signals::TcpObservation;
20    use crate::tcp::{IpVersion, PayloadSize, Quirk, Signature, TcpOption, Ttl, WindowSize};
21    use core::fmt;
22    use std::fmt::Formatter;
23
24    trait TcpDisplayFormat {
25        fn get_version(&self) -> IpVersion;
26        fn get_ittl(&self) -> Ttl;
27        fn get_olen(&self) -> u8;
28        fn get_mss(&self) -> Option<u16>;
29        fn get_wsize(&self) -> WindowSize;
30        fn get_wscale(&self) -> Option<u8>;
31        fn get_olayout(&self) -> &[TcpOption];
32        fn get_quirks(&self) -> &[Quirk];
33        fn get_pclass(&self) -> PayloadSize;
34
35        fn format_tcp_display(&self, f: &mut Formatter<'_>) -> fmt::Result {
36            write!(
37                f,
38                "{}:{}:{}:",
39                self.get_version(),
40                self.get_ittl(),
41                self.get_olen()
42            )?;
43
44            if let Some(mss) = self.get_mss() {
45                write!(f, "{mss}")?;
46            } else {
47                f.write_str("*")?;
48            }
49
50            write!(f, ":{},", self.get_wsize())?;
51
52            if let Some(scale) = self.get_wscale() {
53                write!(f, "{scale}")?;
54            } else {
55                f.write_str("*")?;
56            }
57
58            f.write_str(":")?;
59
60            for (i, o) in self.get_olayout().iter().enumerate() {
61                if i > 0 {
62                    f.write_str(",")?;
63                }
64                write!(f, "{o}")?;
65            }
66
67            f.write_str(":")?;
68
69            for (i, q) in self.get_quirks().iter().enumerate() {
70                if i > 0 {
71                    f.write_str(",")?;
72                }
73                write!(f, "{q}")?;
74            }
75
76            write!(f, ":{}", self.get_pclass())
77        }
78    }
79
80    impl TcpDisplayFormat for TcpObservation {
81        fn get_version(&self) -> IpVersion {
82            self.version
83        }
84        fn get_ittl(&self) -> Ttl {
85            self.ittl.clone()
86        }
87        fn get_olen(&self) -> u8 {
88            self.olen
89        }
90        fn get_mss(&self) -> Option<u16> {
91            self.mss
92        }
93        fn get_wsize(&self) -> WindowSize {
94            self.wsize.clone()
95        }
96        fn get_wscale(&self) -> Option<u8> {
97            self.wscale
98        }
99        fn get_olayout(&self) -> &[TcpOption] {
100            &self.olayout
101        }
102        fn get_quirks(&self) -> &[Quirk] {
103            &self.quirks
104        }
105        fn get_pclass(&self) -> PayloadSize {
106            self.pclass
107        }
108    }
109
110    impl TcpDisplayFormat for Signature {
111        fn get_version(&self) -> IpVersion {
112            self.version
113        }
114        fn get_ittl(&self) -> Ttl {
115            self.ittl.clone()
116        }
117        fn get_olen(&self) -> u8 {
118            self.olen
119        }
120        fn get_mss(&self) -> Option<u16> {
121            self.mss
122        }
123        fn get_wsize(&self) -> WindowSize {
124            self.wsize.clone()
125        }
126        fn get_wscale(&self) -> Option<u8> {
127            self.wscale
128        }
129        fn get_olayout(&self) -> &[TcpOption] {
130            &self.olayout
131        }
132        fn get_quirks(&self) -> &[Quirk] {
133            &self.quirks
134        }
135        fn get_pclass(&self) -> PayloadSize {
136            self.pclass
137        }
138    }
139
140    impl fmt::Display for TcpObservation {
141        fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
142            self.format_tcp_display(f)
143        }
144    }
145
146    impl fmt::Display for Signature {
147        fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
148            self.format_tcp_display(f)
149        }
150    }
151
152    impl fmt::Display for IpVersion {
153        fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
154            use IpVersion::*;
155
156            f.write_str(match self {
157                V4 => "4",
158                V6 => "6",
159                Any => "*",
160            })
161        }
162    }
163
164    impl fmt::Display for Ttl {
165        fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
166            match self {
167                Ttl::Value(ttl) => write!(f, "{ttl}"),
168                Ttl::Distance(ttl, distance) => write!(f, "{ttl}+{distance}"),
169                Ttl::Guess(ttl) => write!(f, "{ttl}+?"),
170                Ttl::Bad(ttl) => write!(f, "{ttl}-"),
171            }
172        }
173    }
174
175    impl fmt::Display for WindowSize {
176        fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
177            use WindowSize::*;
178
179            match self {
180                Mss(n) => write!(f, "mss*{n}"),
181                Mtu(n) => write!(f, "mtu*{n}"),
182                Value(n) => write!(f, "{n}"),
183                Mod(n) => write!(f, "%{n}"),
184                Any => f.write_str("*"),
185            }
186        }
187    }
188
189    impl fmt::Display for TcpOption {
190        fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
191            use TcpOption::*;
192
193            match self {
194                Eol(n) => write!(f, "eol+{n}"),
195                Nop => f.write_str("nop"),
196                Mss => f.write_str("mss"),
197                Ws => f.write_str("ws"),
198                Sok => f.write_str("sok"),
199                Sack => f.write_str("sack"),
200                TS => f.write_str("ts"),
201                Unknown(n) => write!(f, "?{n}"),
202            }
203        }
204    }
205
206    impl fmt::Display for Quirk {
207        fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
208            use Quirk::*;
209
210            match self {
211                Df => f.write_str("df"),
212                NonZeroID => f.write_str("id+"),
213                ZeroID => f.write_str("id-"),
214                Ecn => f.write_str("ecn"),
215                MustBeZero => f.write_str("0+"),
216                FlowID => f.write_str("flow"),
217                SeqNumZero => f.write_str("seq-"),
218                AckNumNonZero => f.write_str("ack+"),
219                AckNumZero => f.write_str("ack-"),
220                NonZeroURG => f.write_str("uptr+"),
221                Urg => f.write_str("urgf+"),
222                Push => f.write_str("pushf+"),
223                OwnTimestampZero => f.write_str("ts1-"),
224                PeerTimestampNonZero => f.write_str("ts2+"),
225                TrailinigNonZero => f.write_str("opt+"),
226                ExcessiveWindowScaling => f.write_str("exws"),
227                OptBad => f.write_str("bad"),
228            }
229        }
230    }
231
232    impl fmt::Display for PayloadSize {
233        fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
234            use PayloadSize::*;
235
236            f.write_str(match self {
237                Zero => "0",
238                NonZero => "+",
239                Any => "*",
240            })
241        }
242    }
243}
244
245pub mod http {
246    use crate::http::{Header, HttpDiagnosis, Signature, Version};
247    use crate::observable_signals::{HttpRequestObservation, HttpResponseObservation};
248    use core::fmt;
249    use std::fmt::Formatter;
250
251    pub trait HttpDisplayFormat {
252        fn get_version(&self) -> Version;
253        fn get_horder(&self) -> &[Header];
254        fn get_habsent(&self) -> &[Header];
255        fn get_expsw(&self) -> &str;
256
257        fn format_http_display(&self, f: &mut Formatter<'_>) -> fmt::Result {
258            write!(f, "{}:", self.get_version())?;
259
260            for (i, h) in self.get_horder().iter().enumerate() {
261                if i > 0 {
262                    f.write_str(",")?;
263                }
264                write!(f, "{h}")?;
265            }
266
267            f.write_str(":")?;
268
269            for (i, h) in self.get_habsent().iter().enumerate() {
270                if i > 0 {
271                    f.write_str(",")?;
272                }
273                write!(f, "{h}")?;
274            }
275
276            write!(f, ":{}", self.get_expsw())
277        }
278    }
279
280    impl HttpDisplayFormat for HttpRequestObservation {
281        fn get_version(&self) -> Version {
282            self.version
283        }
284        fn get_horder(&self) -> &[Header] {
285            &self.horder
286        }
287        fn get_habsent(&self) -> &[Header] {
288            &self.habsent
289        }
290        fn get_expsw(&self) -> &str {
291            &self.expsw
292        }
293    }
294
295    impl HttpDisplayFormat for HttpResponseObservation {
296        fn get_version(&self) -> Version {
297            self.version
298        }
299        fn get_horder(&self) -> &[Header] {
300            &self.horder
301        }
302        fn get_habsent(&self) -> &[Header] {
303            &self.habsent
304        }
305        fn get_expsw(&self) -> &str {
306            &self.expsw
307        }
308    }
309
310    impl HttpDisplayFormat for Signature {
311        fn get_version(&self) -> Version {
312            self.version
313        }
314        fn get_horder(&self) -> &[Header] {
315            &self.horder
316        }
317        fn get_habsent(&self) -> &[Header] {
318            &self.habsent
319        }
320        fn get_expsw(&self) -> &str {
321            &self.expsw
322        }
323    }
324
325    impl fmt::Display for HttpRequestObservation {
326        fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
327            self.format_http_display(f)
328        }
329    }
330
331    impl fmt::Display for HttpResponseObservation {
332        fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
333            self.format_http_display(f)
334        }
335    }
336
337    impl fmt::Display for Signature {
338        fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
339            self.format_http_display(f)
340        }
341    }
342
343    impl fmt::Display for Version {
344        fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
345            f.write_str(match self {
346                Version::V10 => "0",
347                Version::V11 => "1",
348                Version::V20 => "2",
349                Version::V30 => "3",
350                Version::Any => "*",
351            })
352        }
353    }
354
355    impl fmt::Display for Header {
356        fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
357            if self.optional {
358                f.write_str("?")?;
359            }
360
361            f.write_str(&self.name)?;
362
363            if let Some(ref value) = self.value {
364                write!(f, "=[{value}]")?;
365            }
366
367            Ok(())
368        }
369    }
370    impl fmt::Display for HttpDiagnosis {
371        fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
372            use crate::http::HttpDiagnosis::*;
373
374            f.write_str(match self {
375                Dishonest => "dishonest",
376                Anonymous => "anonymous",
377                Generic => "generic",
378                None => "none",
379            })
380        }
381    }
382}