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