@@ -111,6 +111,85 @@ static __inline __u32 infer_http_message(const char* buf, size_t count) {
111
111
return kUnknown ;
112
112
}
113
113
114
+ // frame format: https://www.rfc-editor.org/rfc/rfc7540.html#section-4.1
115
+ static __inline __u32 infer_http2_message (const char * buf_src , size_t count ) {
116
+ static const uint8_t kFrameBasicSize = 0x9 ; // including Length, Type, Flags, Reserved, Stream Identity
117
+ static const uint8_t kFrameTypeHeader = 0x1 ; // the type of the frame: https://www.rfc-editor.org/rfc/rfc7540.html#section-6.2
118
+ static const uint8_t kFrameLoopCount = 5 ;
119
+
120
+ static const uint8_t kStaticTableMaxSize = 61 ;// https://www.rfc-editor.org/rfc/rfc7541#appendix-A
121
+ static const uint8_t kStaticTableAuth = 1 ;
122
+ static const uint8_t kStaticTableGet = 2 ;
123
+ static const uint8_t kStaticTablePost = 3 ;
124
+ static const uint8_t kStaticTablePath1 = 4 ;
125
+ static const uint8_t kStaticTablePath2 = 5 ;
126
+
127
+ // the buffer size must bigger than basic frame size
128
+ if (count < kFrameBasicSize ) {
129
+ return kUnknown ;
130
+ }
131
+
132
+ // frame info
133
+ __u8 frame [21 ] = { 0 };
134
+ __u32 frameOffset = 0 ;
135
+ // header info
136
+ __u8 staticInx , headerBlockFragmentOffset ;
137
+
138
+ // each all frame
139
+ #pragma unroll
140
+ for (__u8 i = 0 ; i < kFrameLoopCount ; i ++ ) {
141
+ if (frameOffset >= count ) {
142
+ break ;
143
+ }
144
+
145
+ // read frame
146
+ bpf_probe_read (frame , sizeof (frame ), buf_src + frameOffset );
147
+ frameOffset += (bpf_ntohl (* (__u32 * ) frame ) >> 8 ) + kFrameBasicSize ;
148
+
149
+ // is header frame
150
+ if (frame [3 ] != kFrameTypeHeader ) {
151
+ continue ;
152
+ }
153
+
154
+ // validate the header(unset): not HTTP2 protocol
155
+ // this frame must is a send request
156
+ if ((frame [4 ] & 0xd2 ) || frame [5 ] & 0x01 ) {
157
+ return kUnknown ;
158
+ }
159
+
160
+ // locate the header block fragment offset
161
+ headerBlockFragmentOffset = kFrameBasicSize ;
162
+ if (frame [4 ] & 0x20 ) { // PADDED flag is set
163
+ headerBlockFragmentOffset += 1 ;
164
+ }
165
+ if (frame [4 ] & 0x20 ) { // PRIORITY flag is set
166
+ headerBlockFragmentOffset += 5 ;
167
+ }
168
+
169
+ #pragma unroll
170
+ for (__u8 j = 0 ; j <= kStaticTablePath2 ; j ++ ) {
171
+ if (headerBlockFragmentOffset > count ) {
172
+ return kUnknown ;
173
+ }
174
+ staticInx = frame [headerBlockFragmentOffset ] & 0x7f ;
175
+ if (staticInx <= kStaticTableMaxSize && staticInx > 0 ) {
176
+ if (staticInx == kStaticTableAuth ||
177
+ staticInx == kStaticTableGet ||
178
+ staticInx == kStaticTablePost ||
179
+ staticInx == kStaticTablePath1 ||
180
+ staticInx == kStaticTablePath2 ) {
181
+ return kRequest ;
182
+ } else {
183
+ return kResponse ;
184
+ }
185
+ }
186
+ headerBlockFragmentOffset ++ ;
187
+ }
188
+ }
189
+
190
+ return kUnknown ;
191
+ }
192
+
114
193
// Cassandra frame:
115
194
// 0 8 16 24 32 40
116
195
// +---------+---------+---------+---------+---------+
@@ -678,6 +757,8 @@ static __inline enum message_type_t analyze_protocol(char *buf, __u32 count, str
678
757
// PROTOCOL_LIST: Requires update on new protocols.
679
758
if ((inferred_message .type = infer_http_message (buf , count )) != kUnknown ) {
680
759
inferred_message .protocol = kProtocolHTTP ;
760
+ } else if ((inferred_message .type = infer_http2_message (buf , count )) != kUnknown ) {
761
+ inferred_message .protocol = kProtocolHTTP2 ;
681
762
} else if ((inferred_message .type = infer_cql_message (buf , count )) != kUnknown ) {
682
763
inferred_message .protocol = kProtocolCQL ;
683
764
} else if ((inferred_message .type = infer_mongo_message (buf , count )) != kUnknown ) {
0 commit comments