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