1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
//! HTTP/2 parsing.
//!
//! [`Parser`] compiles the configured patterns into a DFA whose edges
//! are injected into the BPF parser program. The kernel walks the message
//! byte by byte, follows the edges and runs each action it encounters.
//!
//! Note that [`Parser`] operates directly on the Huffman-encoded bytes,
//! and manages a copy of the dynamic table for each connection.
//!
//! # Examples
//!
//! Captures the `User-Agent` header and passes its match ID to the target
//! program through the read-only data of its skeleton, before the program
//! is loaded:
//!
//! ```no_run
//! # fn main() -> Result<(), beeper::Error> {
//! # struct Rodata { user_agent_mid: u8 }
//! # let mut rodata = Rodata { user_agent_mid: 0 };
//! # let prog_fd = 0;
//! use beeper::{MessageBuffer, http2};
//! use http::header::USER_AGENT;
//!
//! let mut parser = http2::Parser::new();
//! let user_agent_mid = parser.capture_hdr(&USER_AGENT)?;
//!
//! // e.g. open_skel.maps.rodata_data.as_mut().unwrap()
//! rodata.user_agent_mid = user_agent_mid.into();
//!
//! let parser = parser
//! .parse_fn("parse_http2", MessageBuffer::Msg)
//! .extract_fn("extract_http2_match", MessageBuffer::Msg)
//! .get_dynamic_table_entry("get_dt_entry")
//! .attach(prog_fd)?;
//! # Ok(())
//! # }
//! ```
//!
//! The target program declares the stub and calls it with that match ID
//! to get the captured value:
//!
//! ```c
//! #include "beeper/http2.h"
//!
//! volatile const u8 user_agent_mid;
//!
//! BEEPER_HTTP2_PARSE_MSG(parse_http2)
//! BEEPER_EXTRACT_MATCH_MSG(extract_http2_match)
//!
//! SEC("sk_msg")
//! int msg_verdict(struct sk_msg_md *msg) {
//! struct http_parse_res pres = { 0 };
//! struct http2_frame frame = { 0 };
//! if (parse_http2(msg, &pres, &frame) < 0) return SK_PASS;
//!
//! struct bytes user_agent = { 0 };
//! if (extract_http2_match(msg, &pres, user_agent_mid, &user_agent) == 0) {
//! // user_agent.ptr points to the user_agent.len bytes of the value
//! }
//!
//! return SK_PASS;
//! }
//! ```
use SocketAddr;
pub use ;
use ip4_addr;