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}