@@ -94,6 +94,12 @@ int is_rtp_or_rtcp(struct ndpi_detection_module_struct *ndpi_struct, u_int16_t *
94
94
95
95
if (payload_len < 2 )
96
96
return NO_RTP_RTCP ;
97
+
98
+ if (packet -> tcp != NULL ) {
99
+ if (payload_len < 4 )
100
+ return NO_RTP_RTCP ;
101
+ payload += 2 ; /* Skip the length field */
102
+ }
97
103
98
104
if ((payload [0 ] & 0xC0 ) != 0x80 ) { /* Version 2 */
99
105
NDPI_LOG_DBG (ndpi_struct , "Not version 2\n" );
@@ -142,29 +148,23 @@ int is_rtp_or_rtcp(struct ndpi_detection_module_struct *ndpi_struct, u_int16_t *
142
148
static void ndpi_rtp_search (struct ndpi_detection_module_struct * ndpi_struct ,
143
149
struct ndpi_flow_struct * flow ) {
144
150
u_int8_t is_rtp ;
145
- u_int16_t d_port = ntohs (ndpi_struct -> packet .udp -> dest );
146
151
struct ndpi_packet_struct * packet = & ndpi_struct -> packet ;
147
152
const u_int8_t * payload = packet -> payload ;
148
153
u_int16_t seq ;
149
154
150
- NDPI_LOG_DBG (ndpi_struct , "search RTP (stage %d/%d)\n" , flow -> l4 .udp .rtp_stage , flow -> l4 .udp .rtcp_stage );
151
-
152
- if (d_port == 5355 || /* LLMNR_PORT */
153
- d_port == 5353 || /* MDNS_PORT */
154
- d_port == 9600 /* FINS_PORT */ ) {
155
- NDPI_EXCLUDE_PROTO (ndpi_struct , flow );
156
- NDPI_EXCLUDE_PROTO_EXT (ndpi_struct , flow , NDPI_PROTOCOL_RTCP );
157
- return ;
155
+ if (packet -> tcp != NULL ) {
156
+ payload += 2 ; /* Skip the length field */
158
157
}
158
+ NDPI_LOG_DBG (ndpi_struct , "search RTP (stage %d/%d)\n" , flow -> protos .rtp .rtp_stage , flow -> protos .rtcp .rtcp_stage );
159
159
160
160
/* * Let some "unknown" packets at the beginning:
161
161
* search for 3/4 consecutive RTP/RTCP packets.
162
162
* Wait a little longer (4 vs 3 pkts) for RTCP to try to tell if there are only
163
163
* RTCP packets in the flow or if RTP/RTCP are multiplexed together */
164
164
165
165
if (flow -> packet_counter > 3 &&
166
- flow -> l4 . udp .rtp_stage == 0 &&
167
- flow -> l4 . udp .rtcp_stage == 0 ) {
166
+ flow -> protos . rtp .rtp_stage == 0 &&
167
+ flow -> protos . rtcp .rtcp_stage == 0 ) {
168
168
NDPI_EXCLUDE_PROTO (ndpi_struct , flow );
169
169
NDPI_EXCLUDE_PROTO_EXT (ndpi_struct , flow , NDPI_PROTOCOL_RTCP );
170
170
return ;
@@ -173,19 +173,19 @@ static void ndpi_rtp_search(struct ndpi_detection_module_struct *ndpi_struct,
173
173
is_rtp = is_rtp_or_rtcp (ndpi_struct , & seq );
174
174
175
175
if (is_rtp == IS_RTP ) {
176
- if (flow -> l4 . udp .rtp_stage == 2 ) {
176
+ if (flow -> protos . rtp .rtp_stage == 2 ) {
177
177
if (flow -> l4 .udp .line_pkts [0 ] >= 2 && flow -> l4 .udp .line_pkts [1 ] >= 2 ) {
178
178
/* It seems that it is a LINE stuff; let its dissector to evaluate */
179
179
} else if (flow -> l4 .udp .epicgames_stage > 0 ) {
180
180
/* It seems that it is a EpicGames stuff; let its dissector to evaluate */
181
- } else if (flow -> l4 . udp .rtp_seq_set [packet -> packet_direction ] &&
182
- flow -> l4 . udp .rtp_seq [packet -> packet_direction ] == seq ) {
181
+ } else if (flow -> protos . rtp .rtp_seq_set [packet -> packet_direction ] &&
182
+ flow -> protos . rtp .rtp_seq [packet -> packet_direction ] == seq ) {
183
183
/* Simple heuristic to avoid false positives. tradeoff between:
184
184
* consecutive RTP packets should have different sequence number
185
185
* we should handle duplicated traffic */
186
186
NDPI_LOG_DBG (ndpi_struct , "Same seq on consecutive pkts\n" );
187
- flow -> l4 . udp .rtp_stage = 0 ;
188
- flow -> l4 . udp .rtcp_stage = 0 ;
187
+ flow -> protos . rtp .rtp_stage = 0 ;
188
+ flow -> protos . rtcp .rtcp_stage = 0 ;
189
189
NDPI_EXCLUDE_PROTO (ndpi_struct , flow );
190
190
NDPI_EXCLUDE_PROTO_EXT (ndpi_struct , flow , NDPI_PROTOCOL_RTCP );
191
191
} else {
@@ -198,32 +198,32 @@ static void ndpi_rtp_search(struct ndpi_detection_module_struct *ndpi_struct,
198
198
}
199
199
return ;
200
200
}
201
- if (flow -> l4 . udp .rtp_stage == 0 ) {
202
- flow -> l4 . udp .rtp_seq [packet -> packet_direction ] = seq ;
203
- flow -> l4 . udp .rtp_seq_set [packet -> packet_direction ] = 1 ;
201
+ if (flow -> protos . rtp .rtp_stage == 0 ) {
202
+ flow -> protos . rtp .rtp_seq [packet -> packet_direction ] = seq ;
203
+ flow -> protos . rtp .rtp_seq_set [packet -> packet_direction ] = 1 ;
204
204
}
205
- flow -> l4 . udp .rtp_stage += 1 ;
206
- } else if (is_rtp == IS_RTCP && flow -> l4 . udp .rtp_stage > 0 ) {
205
+ flow -> protos . rtp .rtp_stage += 1 ;
206
+ } else if (is_rtp == IS_RTCP && flow -> protos . rtp .rtp_stage > 0 ) {
207
207
/* RTCP after (some) RTP. Keep looking for RTP */
208
- } else if (is_rtp == IS_RTCP && flow -> l4 . udp .rtp_stage == 0 ) {
209
- if (flow -> l4 . udp .rtcp_stage == 3 ) {
208
+ } else if (is_rtp == IS_RTCP && flow -> protos . rtp .rtp_stage == 0 ) {
209
+ if (flow -> protos . rtcp .rtcp_stage == 3 ) {
210
210
NDPI_LOG_INFO (ndpi_struct , "Found RTCP\n" );
211
211
ndpi_set_detected_protocol (ndpi_struct , flow ,
212
212
NDPI_PROTOCOL_UNKNOWN , NDPI_PROTOCOL_RTCP ,
213
213
NDPI_CONFIDENCE_DPI );
214
214
return ;
215
215
}
216
- flow -> l4 . udp .rtcp_stage += 1 ;
216
+ flow -> protos . rtcp .rtcp_stage += 1 ;
217
217
} else {
218
- if (flow -> l4 . udp .rtp_stage || flow -> l4 . udp .rtcp_stage ) {
218
+ if (flow -> protos . rtp .rtp_stage || flow -> protos . rtcp .rtcp_stage ) {
219
219
u_int16_t app_proto ; /* unused */
220
220
u_int32_t unused ;
221
221
222
222
/* TODO: we should switch to the demultiplexing-code in stun dissector */
223
223
if (is_stun (ndpi_struct , flow , & app_proto ) != 0 &&
224
224
!is_dtls (packet -> payload , packet -> payload_packet_len , & unused )) {
225
- flow -> l4 . udp .rtp_stage = 0 ;
226
- flow -> l4 . udp .rtcp_stage = 0 ;
225
+ flow -> protos . rtp .rtp_stage = 0 ;
226
+ flow -> protos . rtcp .rtcp_stage = 0 ;
227
227
NDPI_EXCLUDE_PROTO (ndpi_struct , flow );
228
228
NDPI_EXCLUDE_PROTO_EXT (ndpi_struct , flow , NDPI_PROTOCOL_RTCP );
229
229
}
@@ -235,21 +235,61 @@ static void ndpi_rtp_search(struct ndpi_detection_module_struct *ndpi_struct,
235
235
}
236
236
237
237
/* *************************************************************** */
238
+ /* https://datatracker.ietf.org/doc/html/rfc4571
239
+ * message format for RTP/RTCP over TCP:
240
+ * 0 1 2 3
241
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
242
+ * ---------------------------------------------------------------
243
+ * | LENGTH | RTP or RTCP packet ... |
244
+ * ---------------------------------------------------------------
245
+ */
246
+ static void ndpi_search_rtp_tcp (struct ndpi_detection_module_struct * ndpi_struct ,
247
+ struct ndpi_flow_struct * flow )
248
+ {
249
+ struct ndpi_packet_struct * packet = & ndpi_struct -> packet ;
250
+ const u_int8_t * payload = packet -> payload ;
251
+ u_int16_t len = ntohs (get_u_int16_t (payload , 0 ));
252
+ if (len + sizeof (len ) != packet -> payload_packet_len ) { /*fragmented packets are not handled*/
253
+ NDPI_EXCLUDE_PROTO (ndpi_struct , flow );
254
+ NDPI_EXCLUDE_PROTO_EXT (ndpi_struct , flow , NDPI_PROTOCOL_RTCP );
255
+ } else {
256
+ ndpi_rtp_search (ndpi_struct , flow );
257
+ }
238
258
239
- static void ndpi_search_rtp (struct ndpi_detection_module_struct * ndpi_struct , struct ndpi_flow_struct * flow )
259
+ }
260
+
261
+ /* *************************************************************** */
262
+ static void ndpi_search_rtp_udp (struct ndpi_detection_module_struct * ndpi_struct ,
263
+ struct ndpi_flow_struct * flow )
240
264
{
241
265
struct ndpi_packet_struct * packet = & ndpi_struct -> packet ;
242
266
u_int16_t source = ntohs (packet -> udp -> source );
243
267
u_int16_t dest = ntohs (packet -> udp -> dest );
244
-
245
- if ((source != 30303 ) && (dest != 30303 /* Avoid to mix it with Ethereum that looks alike */ )
246
- && (dest > 1023 )
247
- )
248
- ndpi_rtp_search (ndpi_struct , flow );
249
- else {
268
+ /*
269
+ * XXX: not sure if rtp/rtcp over tcp will also mix with Ethereum
270
+ * for now, will not add it unitl we have a false positive.
271
+ */
272
+ if ((source == 30303 ) || (dest == 30303 /* Avoid to mix it with Ethereum that looks alike */ )
273
+ || (dest == 5355 /* LLMNR_PORT */ )
274
+ || (dest == 5353 /* MDNS_PORT */ )
275
+ || (dest == 9600 /* FINS_PORT */ )
276
+ || (dest <= 1023 )){
250
277
NDPI_EXCLUDE_PROTO (ndpi_struct , flow );
251
278
NDPI_EXCLUDE_PROTO_EXT (ndpi_struct , flow , NDPI_PROTOCOL_RTCP );
279
+ return ;
252
280
}
281
+ ndpi_rtp_search (ndpi_struct , flow );
282
+ }
283
+
284
+ /* *************************************************************** */
285
+ static void ndpi_search_rtp (struct ndpi_detection_module_struct * ndpi_struct , struct ndpi_flow_struct * flow )
286
+ {
287
+ struct ndpi_packet_struct * packet = & ndpi_struct -> packet ;
288
+ if (packet -> tcp != NULL ) {
289
+ ndpi_search_rtp_tcp (ndpi_struct , flow );
290
+ } else {
291
+ ndpi_search_rtp_udp (ndpi_struct , flow );
292
+ }
253
293
}
254
294
255
295
/* *************************************************************** */
@@ -259,7 +299,7 @@ void init_rtp_dissector(struct ndpi_detection_module_struct *ndpi_struct,
259
299
ndpi_set_bitmask_protocol_detection ("RTP" , ndpi_struct , * id ,
260
300
NDPI_PROTOCOL_RTP ,
261
301
ndpi_search_rtp ,
262
- NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_UDP_WITH_PAYLOAD ,
302
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION ,
263
303
SAVE_DETECTION_BITMASK_AS_UNKNOWN ,
264
304
ADD_TO_DETECTION_BITMASK );
265
305
0 commit comments