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}