aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/include/ndpi_api.h5
-rw-r--r--src/include/ndpi_private.h1
-rw-r--r--src/include/ndpi_typedefs.h12
-rw-r--r--src/lib/ndpi_main.c3
-rw-r--r--src/lib/ndpi_utils.c60
-rw-r--r--src/lib/protocols/rtp.c150
-rw-r--r--src/lib/protocols/stun.c3
7 files changed, 198 insertions, 36 deletions
diff --git a/src/include/ndpi_api.h b/src/include/ndpi_api.h
index 4a56da56f..467984f9f 100644
--- a/src/include/ndpi_api.h
+++ b/src/include/ndpi_api.h
@@ -602,10 +602,11 @@ extern "C" {
/**
* Return the name of a RTP payload type
*
- * @par payload_type = the RTP payload type
+ * @par payload_type = the RTP payload type
+ * @par evs_payload_type = EVS payload type (only in case payload_type is EVS)
* @return The symbolic payload type or "Unknown" if not found
*/
- const char* ndpi_rtp_payload_type2str(u_int8_t payload_type);
+ const char* ndpi_rtp_payload_type2str(u_int8_t payload_type, u_int32_t evs_payload_type);
/**
* Check if subprotocols of the specified master protocol are just
diff --git a/src/include/ndpi_private.h b/src/include/ndpi_private.h
index afd2f48ac..e452df10a 100644
--- a/src/include/ndpi_private.h
+++ b/src/include/ndpi_private.h
@@ -296,6 +296,7 @@ struct ndpi_detection_module_config_struct {
int stun_opportunistic_tls_enabled;
int stun_max_packets_extra_dissection;
+ int rtp_max_packets_extra_dissection;
int stun_mapped_address_enabled;
int stun_response_origin_enabled;
int stun_other_address_enabled;
diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h
index 8ca365d01..6b215aa70 100644
--- a/src/include/ndpi_typedefs.h
+++ b/src/include/ndpi_typedefs.h
@@ -1301,6 +1301,12 @@ struct ndpi_tls_obfuscated_heuristic_matching_set {
u_int32_t pkts[4];
};
+struct rtp_info {
+ u_int8_t payload_type;
+ u_int32_t evs_subtype;
+ bool payload_detected;
+};
+
struct ndpi_flow_struct {
u_int16_t detected_protocol_stack[NDPI_PROTOCOL_SIZE];
@@ -1601,10 +1607,8 @@ struct ndpi_flow_struct {
char *user_agent;
} ssdp;
- struct {
- u_int8_t payload_type;
- } rtp;
-} protos;
+ struct rtp_info rtp[2 /* directions */];
+ } protos;
/* **Packet** metadata for flows where monitoring is enabled. It is reset after each packet! */
struct ndpi_metadata_monitoring *monit;
diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c
index c29ec6ebf..904d1d971 100644
--- a/src/lib/ndpi_main.c
+++ b/src/lib/ndpi_main.c
@@ -11791,7 +11791,8 @@ static const struct cfg_param {
{ "zoom", "max_packets_extra_dissection", "4", "0", "255", CFG_PARAM_INT, __OFF(zoom_max_packets_extra_dissection), NULL },
{ "rtp", "search_for_stun", "disable", NULL, NULL, CFG_PARAM_ENABLE_DISABLE, __OFF(rtp_search_for_stun), NULL },
-
+ { "rtp", "max_packets_extra_dissection", "32", "0", "255", CFG_PARAM_INT, __OFF(rtp_max_packets_extra_dissection), NULL },
+
{ "openvpn", "dpi.heuristics", "0x00", "0", "0x01", CFG_PARAM_INT, __OFF(openvpn_heuristics), NULL },
{ "openvpn", "dpi.heuristics.num_messages", "10", "0", "255", CFG_PARAM_INT, __OFF(openvpn_heuristics_num_msgs), NULL },
{ "openvpn", "subclassification_by_ip", "enable", NULL, NULL, CFG_PARAM_ENABLE_DISABLE, __OFF(openvpn_subclassification_by_ip), NULL },
diff --git a/src/lib/ndpi_utils.c b/src/lib/ndpi_utils.c
index 63effab29..69eaeb052 100644
--- a/src/lib/ndpi_utils.c
+++ b/src/lib/ndpi_utils.c
@@ -4236,7 +4236,8 @@ ndpi_protocol_qoe_category_t ndpi_find_protocol_qoe(struct ndpi_detection_module
/* ************************************************************** */
-const char* ndpi_rtp_payload_type2str(u_int8_t payload_type) {
+/* https://gitlab.com/wireshark/wireshark/-/blob/master/epan/dissectors/packet-rtp.c */
+const char* ndpi_rtp_payload_type2str(u_int8_t payload_type, u_int32_t evs_payload_type) {
switch(payload_type) {
case 0: return("ITU-T G.711 PCMU");
case 1: return("USA Federal Standard FS-1016");
@@ -4265,7 +4266,62 @@ const char* ndpi_rtp_payload_type2str(u_int8_t payload_type) {
case 33: return("MPEG-II transport streams");
case 34: return("ITU-T H.263");
case 98: return("AMR-WB");
- case 127: return("EVS");
+ case 118: return("AMR"); /* Adptive Multirate */
+ case 126: /* Enhanced Voice Services */
+ case 127: /* Enhanced Voice Services */
+ {
+ switch(evs_payload_type) {
+ /* https://gitlab.com/wireshark/wireshark/-/blob/master/epan/dissectors/packet-evs.c */
+
+ case 0x0: return("AMR-WB IO 6.6 kbps");
+ case 0x1: return("AMR-WB IO 8.85 kbps");
+ case 0x2: return("AMR-WB IO 12.65 kbps");
+ case 0x3: return("AMR-WB IO 14.24 kbps");
+ case 0x4: return("AMR-WB IO 15.85 kbps");
+ case 0x5: return("AMR-WB IO 18.25 kbps");
+ case 0x6: return("AMR-WB IO 19.85 kbps");
+ case 0x7: return("AMR-WB IO 23.05 kbps");
+ case 0x8: return("AMR-WB IO 23.85 kbps");
+ case 0x9: return("AMR-WB IO 2.0 kbps SID");
+
+ /* ** */
+ /* Dummy SWB 30 offset */
+ case 0x3+30: return("SWB 9.6 kbps");
+ case 0x4+30: return("SWB 13.2 kbps");
+ case 0x5+30: return("SWB 16.4 kbps");
+ case 0x6+30: return("SWB 24.4 kbps");
+ case 0x7+30: return("SWB 32 kbps");
+ case 0x8+30: return("SWB 48 kbps");
+ case 0x9+30: return("SWB 64 kbps");
+ case 0xa+30: return("SWB 96 kbps");
+ case 0xb+30: return("SWB 128 kbps");
+
+
+ case 48: return("EVS Primary SID 2.4");
+ case 136: return("EVS AMR-WB IO 6.6");
+ case 144: return("EVS Primary 7.2");
+ case 160: return("EVS Primary 8.0");
+ case 184: return("EVS AMR-WB IO 8.85");
+ case 192: return("EVS Primary 9.6");
+ case 256: return("EVS AMR-WB IO 12.65");
+ case 264: return("EVS Primary 13.2");
+ case 288: return("EVS AMR-WB IO 14.25");
+ case 320: return("EVS AMR-WB IO 15.85");
+ case 328: return("EVS Primary 16.4");
+ case 368: return("EVS AMR-WB IO 18.25");
+ case 400: return("EVS AMR-WB IO 19.85");
+ case 464: return("EVS AMR-WB IO 23.05");
+ case 480: return("EVS AMR-WB IO 23.85");
+ case 488: return("EVS Primary 24.4");
+ case 640: return("EVS Primary 32.0");
+ case 960: return("EVS Primary 48.0");
+ case 1280: return("EVS Primary 64.0");
+ case 1920: return("EVS Primary 96.0");
+ case 2560: return("EVS Primary 128.0");
+ default: return("EVS 13.2");
+ }
+ }
+ break;
default: return("Unknown");
}
}
diff --git a/src/lib/protocols/rtp.c b/src/lib/protocols/rtp.c
index ffd2049d6..8e216bde6 100644
--- a/src/lib/protocols/rtp.c
+++ b/src/lib/protocols/rtp.c
@@ -32,6 +32,11 @@
#define RTP_MIN_HEADER 12
#define RTCP_MIN_HEADER 8
+static void ndpi_rtp_search(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow);
+
+/* *************************************************************** */
+
/* https://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml */
int is_valid_rtp_payload_type(uint8_t type)
{
@@ -40,6 +45,8 @@ int is_valid_rtp_payload_type(uint8_t type)
return 1;
}
+/* *************************************************************** */
+
u_int8_t rtp_get_stream_type(u_int8_t payloadType, u_int8_t *s_type, u_int16_t sub_proto)
{
/* General, from IANA */
@@ -201,10 +208,14 @@ u_int8_t rtp_get_stream_type(u_int8_t payloadType, u_int8_t *s_type, u_int16_t s
return(0);
}
+/* *************************************************************** */
+
static int is_valid_rtcp_payload_type(uint8_t type) {
return (type >= 192 && type <= 213);
}
+/* *************************************************************** */
+
int is_rtp_or_rtcp(struct ndpi_detection_module_struct *ndpi_struct,
const u_int8_t *payload, u_int16_t payload_len, u_int16_t *seq)
{
@@ -214,7 +225,7 @@ int is_rtp_or_rtcp(struct ndpi_detection_module_struct *ndpi_struct,
if(payload_len < 2)
return NO_RTP_RTCP;
-
+
if((payload[0] & 0xC0) != 0x80) { /* Version 2 */
NDPI_LOG_DBG(ndpi_struct, "Not version 2\n");
return NO_RTP_RTCP;
@@ -239,8 +250,8 @@ int is_rtp_or_rtcp(struct ndpi_detection_module_struct *ndpi_struct,
return NO_RTP_RTCP;
}
/* Check on padding doesn't work because:
- * we may have multiple RTP packets in the same TCP/UDP datagram
- * with SRTP, padding_length field is encrypted */
+ * we may have multiple RTP packets in the same TCP/UDP datagram
+ * with SRTP, padding_length field is encrypted */
if(seq)
*seq = ntohs(*(unsigned short *)&payload[2]);
return IS_RTP;
@@ -257,6 +268,17 @@ int is_rtp_or_rtcp(struct ndpi_detection_module_struct *ndpi_struct,
return NO_RTP_RTCP;
}
+/* ************************************************************ */
+
+static int rtp_search_again(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow) {
+ /* printf("***** AGAIN *****\n"); */
+ ndpi_rtp_search(ndpi_struct, flow);
+
+ return(((flow->protos.rtp[0].payload_detected && flow->protos.rtp[1].payload_detected)) ? false :true);
+}
+
+/* *************************************************************** */
static void ndpi_int_rtp_add_connection(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow,
@@ -272,6 +294,16 @@ static void ndpi_int_rtp_add_connection(struct ndpi_detection_module_struct *ndp
NDPI_LOG_DBG(ndpi_struct, "Enabling (STUN) extra dissection\n");
switch_extra_dissection_to_stun(ndpi_struct, flow, 1);
}
+ } else if(proto == NDPI_PROTOCOL_RTP) {
+ if(flow->protos.rtp[0].payload_detected && flow->protos.rtp[1].payload_detected)
+ ; /* Nothing to do */
+ else {
+ if(!flow->extra_packets_func) {
+ NDPI_LOG_DBG(ndpi_struct, "Enabling extra dissection\n");
+ flow->max_extra_packets_to_check = ndpi_struct->cfg.rtp_max_packets_extra_dissection;
+ flow->extra_packets_func = rtp_search_again;
+ }
+ }
}
}
@@ -286,15 +318,15 @@ static void ndpi_rtp_search(struct ndpi_detection_module_struct *ndpi_struct,
u_int16_t seq;
if(packet->tcp != NULL) {
- payload += 2; /* Skip the length field */
- payload_len -= 2;
+ payload += 2; /* Skip the length field */
+ payload_len -= 2;
}
NDPI_LOG_DBG(ndpi_struct, "search RTP (stage %d/%d)\n", flow->rtp_stage, flow->rtcp_stage);
/* * Let some "unknown" packets at the beginning:
- * search for 3/4 consecutive RTP/RTCP packets.
- * Wait a little longer (4 vs 3 pkts) for RTCP to try to tell if there are only
- * RTCP packets in the flow or if RTP/RTCP are multiplexed together */
+ * search for 3/4 consecutive RTP/RTCP packets.
+ * Wait a little longer (4 vs 3 pkts) for RTCP to try to tell if there are only
+ * RTCP packets in the flow or if RTP/RTCP are multiplexed together */
if(flow->packet_counter > 3 &&
flow->rtp_stage == 0 &&
@@ -307,8 +339,75 @@ static void ndpi_rtp_search(struct ndpi_detection_module_struct *ndpi_struct,
is_rtp = is_rtp_or_rtcp(ndpi_struct, payload, payload_len, &seq);
if(is_rtp == IS_RTP) {
- flow->protos.rtp.payload_type = payload[1] & 0x7F;
+ u_int8_t packet_direction = current_pkt_from_client_to_server(ndpi_struct, flow) ? 0 : 1;
+ if(flow->protos.rtp[packet_direction].payload_type == 0x0) {
+ flow->protos.rtp[packet_direction].payload_type = payload[1] & 0x7F;
+ flow->protos.rtp[packet_direction].payload_detected = true;
+
+ /* printf("********* [direction: %d] payload_type=%u\n", packet_direction, flow->protos.rtp[packet_direction].payload_type); */
+
+ if(((flow->protos.rtp[packet_direction].payload_type == 126 /* Enhanced Voice Services (EVS) */)
+ || (flow->protos.rtp[packet_direction].payload_type == 127 /* Enhanced Voice Services (EVS) */))
+ && (payload_len > 12 /* RTP header */)) {
+ const u_int8_t *evs = &payload[12];
+ u_int packet_len = payload_len - 12;
+ u_int num_bits = packet_len * 8;
+
+ flow->flow_multimedia_types = ndpi_multimedia_audio_flow;
+ /* printf("********* %02X [bits %u]\n", evs[0], num_bits); */
+
+ if(num_bits == 56) {
+ /* A.2.1.3 Special case for 56 bit payload size (EVS Primary or EVS AMR-WB IO SID) */
+
+ if((evs[0] & 0x80) == 0)
+ flow->protos.rtp[packet_direction].evs_subtype = evs[0] & 0xF;
+ else
+ flow->protos.rtp[packet_direction].evs_subtype = evs[1] & 0xF;
+ } else {
+
+ /* See ndpi_rtp_payload_type2str() */
+ switch(num_bits) {
+ case 48:
+ case 136:
+ case 144:
+ case 160:
+ case 184:
+ case 192:
+ case 256:
+ case 264:
+ case 288:
+ case 320:
+ case 328:
+ case 368:
+ case 400:
+ case 464:
+ case 480:
+ case 488:
+ case 640:
+ case 960:
+ case 1280:
+ case 1920:
+ case 2560:
+ flow->protos.rtp[packet_direction].evs_subtype = num_bits;
+ break;
+
+ default:
+ if((evs[0] >> 7) == 1) {
+ /* EVS Codec Mode Request (EVS-CMR) */
+ u_int8_t d_bits = evs[0] & 0X0F;
+
+ flow->protos.rtp[packet_direction].evs_subtype = d_bits + 30 /* dummy offset */;
+ }
+ break;
+ }
+ }
+
+ if(flow->protos.rtp[0].payload_detected && flow->protos.rtp[1].payload_detected)
+ flow->extra_packets_func = NULL; /* Nothing to do */
+ }
+ }
+
if(flow->rtp_stage == 2) {
if(flow->l4_proto == IPPROTO_UDP &&
flow->l4.udp.line_pkts[0] >= 2 && flow->l4.udp.line_pkts[1] >= 2) {
@@ -318,15 +417,16 @@ static void ndpi_rtp_search(struct ndpi_detection_module_struct *ndpi_struct,
} else if(flow->rtp_seq_set[packet->packet_direction] &&
flow->rtp_seq[packet->packet_direction] == seq) {
/* Simple heuristic to avoid false positives. tradeoff between:
- * consecutive RTP packets should have different sequence number
- * we should handle duplicated traffic */
+ * consecutive RTP packets should have different sequence number
+ * we should handle duplicated traffic */
NDPI_LOG_DBG(ndpi_struct, "Same seq on consecutive pkts\n");
flow->rtp_stage = 0;
flow->rtcp_stage = 0;
NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
NDPI_EXCLUDE_PROTO_EXT(ndpi_struct, flow, NDPI_PROTOCOL_RTCP);
} else {
- rtp_get_stream_type(flow->protos.rtp.payload_type, &flow->flow_multimedia_types, NDPI_PROTOCOL_UNKNOWN);
+ rtp_get_stream_type(flow->protos.rtp[packet->packet_direction].payload_type,
+ &flow->flow_multimedia_types, NDPI_PROTOCOL_UNKNOWN);
NDPI_LOG_INFO(ndpi_struct, "Found RTP\n");
ndpi_int_rtp_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_RTP);
@@ -360,7 +460,7 @@ static void ndpi_rtp_search(struct ndpi_detection_module_struct *ndpi_struct,
NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
NDPI_EXCLUDE_PROTO_EXT(ndpi_struct, flow, NDPI_PROTOCOL_RTCP);
}
- }
+ }
}
}
@@ -374,11 +474,11 @@ static void ndpi_rtp_search(struct ndpi_detection_module_struct *ndpi_struct,
* ---------------------------------------------------------------
*/
static void ndpi_search_rtp_tcp(struct ndpi_detection_module_struct *ndpi_struct,
- struct ndpi_flow_struct *flow)
+ struct ndpi_flow_struct *flow)
{
struct ndpi_packet_struct *packet = &ndpi_struct->packet;
const u_int8_t *payload = packet->payload;
-
+
if(packet->payload_packet_len < 4){ /* (2) len field + (2) min rtp/rtcp*/
NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
NDPI_EXCLUDE_PROTO_EXT(ndpi_struct, flow, NDPI_PROTOCOL_RTCP);
@@ -397,12 +497,12 @@ static void ndpi_search_rtp_tcp(struct ndpi_detection_module_struct *ndpi_struct
/* *************************************************************** */
static void ndpi_search_rtp_udp(struct ndpi_detection_module_struct *ndpi_struct,
- struct ndpi_flow_struct *flow)
+ struct ndpi_flow_struct *flow)
{
struct ndpi_packet_struct *packet = &ndpi_struct->packet;
u_int16_t source = ntohs(packet->udp->source);
u_int16_t dest = ntohs(packet->udp->dest);
- /*
+ /*
* XXX: not sure if rtp/rtcp over tcp will also mix with Ethereum
* for now, will not add it unitl we have a false positive.
*/
@@ -424,9 +524,9 @@ static void ndpi_search_rtp(struct ndpi_detection_module_struct *ndpi_struct, st
struct ndpi_packet_struct *packet = &ndpi_struct->packet;
if(packet->tcp != NULL) {
ndpi_search_rtp_tcp(ndpi_struct, flow);
- } else {
- ndpi_search_rtp_udp(ndpi_struct, flow);
- }
+ } else {
+ ndpi_search_rtp_udp(ndpi_struct, flow);
+ }
}
/* *************************************************************** */
@@ -434,11 +534,11 @@ static void ndpi_search_rtp(struct ndpi_detection_module_struct *ndpi_struct, st
void init_rtp_dissector(struct ndpi_detection_module_struct *ndpi_struct,
u_int32_t *id) {
ndpi_set_bitmask_protocol_detection("RTP", ndpi_struct, *id,
- NDPI_PROTOCOL_RTP,
- ndpi_search_rtp,
- NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
- SAVE_DETECTION_BITMASK_AS_UNKNOWN,
- ADD_TO_DETECTION_BITMASK);
+ NDPI_PROTOCOL_RTP,
+ ndpi_search_rtp,
+ NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD_WITHOUT_RETRANSMISSION,
+ SAVE_DETECTION_BITMASK_AS_UNKNOWN,
+ ADD_TO_DETECTION_BITMASK);
*id += 1;
}
diff --git a/src/lib/protocols/stun.c b/src/lib/protocols/stun.c
index 2fb0c89b7..683559853 100644
--- a/src/lib/protocols/stun.c
+++ b/src/lib/protocols/stun.c
@@ -961,12 +961,11 @@ static int stun_search_again(struct ndpi_detection_module_struct *ndpi_struct,
rtp_rtcp = is_rtp_or_rtcp(ndpi_struct, packet->payload, packet->payload_packet_len, NULL);
if(rtp_rtcp == IS_RTP) {
-
NDPI_LOG_DBG(ndpi_struct, "RTP (dir %d) [%d/%d]\n", packet->packet_direction,
flow->stun.rtp_counters[0], flow->stun.rtp_counters[1]);
flow->stun.rtp_counters[packet->packet_direction]++;
-
+ /* TODO: store RTP information in 'struct rtp_info' */
NDPI_LOG_INFO(ndpi_struct, "Found RTP over STUN\n");
rtp_get_stream_type(packet->payload[1] & 0x7F, &flow->flow_multimedia_types, flow->detected_protocol_stack[0]);