Ethereal-dev: [Ethereal-dev] Using SDP to detect RTP and RTCP streams

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: "Lars Roland" <Lars.Roland@xxxxxxx>
Date: Mon, 17 Nov 2003 16:51:45 +0100 (MET)
Hello all,

attached is a patch for the sdp dissector. 
It will add automatic detection of RTP and RTCP for Protocols using SDP
(e.g. SIP, MGCP, ...).

However, this is a first try and it might not work in some cases. I have
tested it only with a few SIP calls. 

Best Regards,

Lars Roland
Index: ethereal/packet-sdp.c
===================================================================
RCS file: /cvsroot/ethereal/packet-sdp.c,v
retrieving revision 1.35
diff -u -r1.35 packet-sdp.c
--- ethereal/packet-sdp.c	14 Oct 2003 21:26:37 -0000	1.35
+++ ethereal/packet-sdp.c	17 Nov 2003 14:42:50 -0000
@@ -32,8 +32,12 @@
 
 #include <glib.h>
 #include <epan/packet.h>
+#include <epan/conversation.h>
 #include <epan/strutil.h>
 
+static dissector_handle_t rtp_handle=NULL;
+static dissector_handle_t rtcp_handle=NULL;
+
 static int proto_sdp = -1;
 
 /* Top level fields */
@@ -137,6 +141,11 @@
 static void dissect_sdp_media(tvbuff_t *tvb, proto_item *ti);
 static void dissect_sdp_media_attribute(tvbuff_t *tvb, proto_item *ti);
 
+static char *media_port;
+static char *media_proto;
+static char *connection_address;
+static char *connection_type;
+
 static void
 dissect_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
@@ -153,6 +162,20 @@
 	int             hf = -1;
 	char            *string;
 
+	address 	src_addr;
+	conversation_t 	*conv=NULL;
+
+	guint32 	ipv4_address=0;
+	guint32 	ipv4_port=0;
+	gboolean 	is_rtp=FALSE;
+	gboolean 	is_ipv4_addr=FALSE;
+	struct in_addr	ipaddr;
+
+	media_port=NULL;
+	media_proto=NULL;
+	connection_address=NULL;
+	connection_type=NULL;
+
 	/*
 	 * As RFC 2327 says, "SDP is purely a format for session
 	 * description - it does not incorporate a transport protocol,
@@ -289,6 +312,60 @@
 		offset = next_offset;
 	}
 
+
+	/* Now look, if we have strings collected.
+	 * Try to convert ipv4 address and port into binary format,
+	 * so we can use them to detect rtp and rtcp streams.
+	 * Don't forget to free the strings!
+	 */
+
+	if(media_port!=NULL) {
+		ipv4_port = atol(media_port);
+		g_free(media_port);
+	}
+	if(media_proto!=NULL) {
+		/* Check if media protocol is RTP */
+		is_rtp= !strcmp(media_proto,"RTP/AVP");
+		g_free(media_proto);
+	}
+	if(connection_address!=NULL) {
+		if(connection_type!=NULL && strcmp(connection_type,"IP4")==0 ) {
+			if(inet_aton(connection_address, &ipaddr) !=0 ) {
+				/* connection_address could be converted to a valid ipv4 address*/
+				is_ipv4_addr=TRUE;
+				ipv4_address = ipaddr.s_addr;
+			}
+		}
+		g_free(connection_address);
+	}
+	if(connection_type!=NULL) {
+		g_free(connection_type);
+	}
+
+	/* Add rtp and rtcp conversation, if available */
+	if((!pinfo->fd->flags.visited) && ipv4_address!=0 && ipv4_port!=0 && is_rtp && is_ipv4_addr){
+		src_addr.type=AT_IPv4;
+		src_addr.len=4;
+		src_addr.data=(char *)&ipv4_address;
+
+		if(rtp_handle){
+			conv=find_conversation(&src_addr, &src_addr, PT_UDP, ipv4_port, ipv4_port, NO_ADDR_B|NO_PORT_B);
+			if(!conv){
+				conv=conversation_new(&src_addr, &src_addr, PT_UDP, ipv4_port, ipv4_port, NO_ADDR_B|NO_PORT_B);
+				conversation_set_dissector(conv, rtp_handle);
+			}
+		}
+
+		if(rtcp_handle){
+			ipv4_port++;
+			conv=find_conversation(&src_addr, &src_addr, PT_UDP, ipv4_port, ipv4_port, NO_ADDR_B|NO_PORT_B);
+			if(!conv){
+				conv=conversation_new(&src_addr, &src_addr, PT_UDP, ipv4_port, ipv4_port, NO_ADDR_B|NO_PORT_B);
+				conversation_set_dissector(conv, rtcp_handle);
+			}
+		}
+	}
+
 	datalen = tvb_length_remaining(tvb, offset);
 	if (datalen > 0) {
 		proto_tree_add_text(sdp_tree, tvb, offset, datalen,
@@ -414,6 +491,8 @@
   if( next_offset == -1 )
     return;
   tokenlen = next_offset - offset;
+  /* Save connection address type */
+  connection_type = tvb_get_string(tvb, offset, tokenlen);
 
   proto_tree_add_item(sdp_connection_info_tree,
 		      hf_connection_info_address_type,tvb,
@@ -424,9 +503,14 @@
   next_offset = tvb_find_guint8(tvb,offset,-1,'/');
   if( next_offset == -1){
     tokenlen = -1;	/* end of tvbuff */
+    /* Save connection address */
+    connection_address = tvb_get_string(tvb, offset, tvb_length_remaining(tvb, offset));
   } else {
     tokenlen = next_offset - offset;
+    /* Save connection address */
+    connection_address = tvb_get_string(tvb, offset, tokenlen);
   }
+
   proto_tree_add_item(sdp_connection_info_tree,
 		      hf_connection_info_connection_address, tvb,
 		      offset,tokenlen,FALSE);
@@ -667,6 +751,8 @@
 
   if(next_offset != -1){
     tokenlen = next_offset - offset;
+    /* Save port info */
+    media_port = tvb_get_string(tvb, offset, tokenlen);
 
     proto_tree_add_item(sdp_media_tree, hf_media_port, tvb,
 			offset, tokenlen, FALSE);
@@ -684,6 +770,8 @@
     if(next_offset == -1)
       return;
     tokenlen = next_offset - offset;
+    /* Save port info */
+    media_port = tvb_get_string(tvb, offset, tokenlen);
 
     /* XXX Remember Port */
     proto_tree_add_item(sdp_media_tree, hf_media_port, tvb,
@@ -697,6 +785,8 @@
     return;
 
   tokenlen = next_offset - offset;
+  /* Save port protocol */
+  media_proto = tvb_get_string(tvb, offset, tokenlen);
 
   /* XXX Remember Protocol */
   proto_tree_add_item(sdp_media_tree, hf_media_proto, tvb,
@@ -722,7 +812,7 @@
    *         We need to find out the address of the other side first and it
    *         looks like that info can be found in SIP headers only.
    */
- 
+
 }
 
 static void dissect_sdp_media_attribute(tvbuff_t *tvb, proto_item * ti){
@@ -987,3 +1077,10 @@
    */
   register_dissector("sdp", dissect_sdp, proto_sdp);
 }
+
+void
+proto_reg_handoff_sdp(void)
+{
+	rtp_handle = find_dissector("rtp");
+	rtcp_handle = find_dissector("rtcp");
+}
\ No newline at end of file