As the gtk2 directory is no longer needed (GTK1 and 2 are using the same sources...
[obnox/wireshark/wip.git] / packet-sdp.c
index 67e0d25e3966f5ad41d5ef12755d05b2f22c8d15..3460bca5f7775b4d20f7133514eedb0dec5a2901 100644 (file)
@@ -4,7 +4,7 @@
  * Jason Lango <jal@netapp.com>
  * Liberally copied from packet-http.c, by Guy Harris <guy@alum.mit.edu>
  *
- * $Id: packet-sdp.c,v 1.39 2003/12/07 03:46:04 guy Exp $
+ * $Id$
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
 #include <epan/conversation.h>
 #include <epan/strutil.h>
 
+#include "packet-rtp.h"
+#include "rtp_pt.h"
+#include "packet-rtcp.h"
+
+
 static dissector_handle_t rtp_handle=NULL;
 static dissector_handle_t rtcp_handle=NULL;
 
@@ -139,11 +144,15 @@ static int ett_sdp_session_attribute = -1;
 static int ett_sdp_media = -1;
 static int ett_sdp_media_attribute = -1;
 
+
+#define SDP_MAX_RTP_CHANNELS 4
+
 typedef struct {
-       char *media_port;
-       char *media_proto;
        char *connection_address;
        char *connection_type;
+       char *media_port[SDP_MAX_RTP_CHANNELS];
+       char *media_proto[SDP_MAX_RTP_CHANNELS];
+       gint8 media_count;
 } transport_info_t;
 
 /* static functions */
@@ -182,19 +191,26 @@ dissect_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        char            *string;
 
        address         src_addr;
-       conversation_t  *conv=NULL;
 
        transport_info_t transport_info;
+
        guint32         ipv4_address=0;
        guint32         ipv4_port=0;
        gboolean        is_rtp=FALSE;
        gboolean        is_ipv4_addr=FALSE;
        struct in_addr  ipaddr;
+       gint            n;
 
-       transport_info.media_port=NULL;
-       transport_info.media_proto=NULL;
+       /* Initialise RTP channel info */
        transport_info.connection_address=NULL;
        transport_info.connection_type=NULL;
+       for (n=0; n < SDP_MAX_RTP_CHANNELS; n++)
+       {
+           transport_info.media_port[n]=NULL;
+           transport_info.media_proto[n]=NULL;
+       }
+       transport_info.media_count = 0;
+
 
        /*
         * As RFC 2327 says, "SDP is purely a format for session
@@ -225,7 +241,7 @@ dissect_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
         * Show the SDP message a line at a time.
         */
        in_media_description = FALSE;
-       while (tvb_offset_exists(tvb, offset)) {
+       while (tvb_reported_length_remaining(tvb, offset) > 0) {
                /*
                 * Find the end of the line.
                 */
@@ -324,66 +340,69 @@ dissect_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                                                 linelen - tokenoffset));
                g_free(string);
                call_sdp_subdissector(tvb_new_subset(tvb,offset+tokenoffset,
-                                                    linelen-tokenoffset,-1),
+                                                    linelen-tokenoffset,
+                                                    linelen-tokenoffset),
                                      hf,sub_ti,&transport_info),
                offset = next_offset;
        }
 
 
        /* Now look, if we have strings collected.
-        * Try to convert ipv4 address and port into binary format,
+        * Try to convert ipv4 addresses and ports into binary format,
         * so we can use them to detect rtp and rtcp streams.
         * Don't forget to free the strings!
         */
 
-       if(transport_info.media_port!=NULL) {
-               ipv4_port = atol(transport_info.media_port);
-               g_free(transport_info.media_port);
-       }
-       if(transport_info.media_proto!=NULL) {
-               /* Check if media protocol is RTP */
-               is_rtp = (strcmp(transport_info.media_proto,"RTP/AVP")==0);
-               g_free(transport_info.media_proto);
+       for (n = 0; n < transport_info.media_count; n++)
+       {
+           if(transport_info.media_port[n]!=NULL) {
+                   ipv4_port = atol(transport_info.media_port[n]);
+                   g_free(transport_info.media_port[n]);
+           }
+           if(transport_info.media_proto[n]!=NULL) {
+                   /* Check if media protocol is RTP */
+                   is_rtp = (strcmp(transport_info.media_proto[n],"RTP/AVP")==0);
+                   g_free(transport_info.media_proto[n]);
+           }
+           if(transport_info.connection_address!=NULL) {
+                   if(transport_info.connection_type!=NULL &&
+                       strcmp(transport_info.connection_type,"IP4")==0) {
+                           if(inet_aton(transport_info.connection_address, &ipaddr)
+                               !=0 ) {
+                                   /* connection_address could be converted to a valid ipv4 address*/
+                                   is_ipv4_addr=TRUE;
+                                   ipv4_address = ipaddr.s_addr;
+                           }
+                   }
+           }
+
+           /* 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){
+                               rtp_add_address(pinfo, (char *)&ipv4_address, ipv4_port, 0,
+                                               "SDP", pinfo->fd->num);
+                   }
+
+                   if(rtcp_handle){
+                               ipv4_port++;
+                               rtcp_add_address(pinfo, (char *)&ipv4_address, ipv4_port, 0,
+                                                "SDP", pinfo->fd->num);
+                   }
+           }
        }
-       if(transport_info.connection_address!=NULL) {
-               if(transport_info.connection_type!=NULL &&
-                   strcmp(transport_info.connection_type,"IP4")==0) {
-                       if(inet_aton(transport_info.connection_address, &ipaddr)
-                           !=0 ) {
-                               /* connection_address could be converted to a valid ipv4 address*/
-                               is_ipv4_addr=TRUE;
-                               ipv4_address = ipaddr.s_addr;
-                       }
-               }
+
+       /* Free up 'connection info' strings */
+       if(transport_info.connection_address) {
                g_free(transport_info.connection_address);
        }
        if(transport_info.connection_type!=NULL) {
                g_free(transport_info.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) {
@@ -483,6 +502,10 @@ dissect_sdp_owner(tvbuff_t *tvb, proto_item *ti){
   proto_tree_add_item(sdp_owner_tree,hf_owner_address, tvb, offset, -1, FALSE);
 }
 
+/*
+ * XXX - this can leak memory if an exception is thrown after we've fetched
+ * a string.
+ */
 static void
 dissect_sdp_connection_info(tvbuff_t *tvb, proto_item* ti,
                            transport_info_t *transport_info){
@@ -515,6 +538,7 @@ dissect_sdp_connection_info(tvbuff_t *tvb, proto_item* ti,
   /* Save connection address type */
   transport_info->connection_type = tvb_get_string(tvb, offset, tokenlen);
 
+
   proto_tree_add_item(sdp_connection_info_tree,
                      hf_connection_info_address_type,tvb,
                      offset,tokenlen,FALSE);
@@ -606,7 +630,7 @@ static void dissect_sdp_time(tvbuff_t *tvb, proto_item* ti){
 
   /* get stop time */
   offset = next_offset + 1;
-  proto_tree_add_item(sdp_time_tree,hf_time_start, tvb,
+  proto_tree_add_item(sdp_time_tree, hf_time_stop, tvb,
                      offset, -1, FALSE);
 }
 
@@ -748,6 +772,7 @@ dissect_sdp_media(tvbuff_t *tvb, proto_item *ti,
                  transport_info_t *transport_info){
   proto_tree *sdp_media_tree;
   gint offset, next_offset, tokenlen;
+  guint8 *media_format;
 
   offset = 0;
   next_offset = 0;
@@ -776,7 +801,7 @@ dissect_sdp_media(tvbuff_t *tvb, proto_item *ti,
   if(next_offset != -1){
     tokenlen = next_offset - offset;
     /* Save port info */
-    transport_info->media_port = tvb_get_string(tvb, offset, tokenlen);
+    transport_info->media_port[transport_info->media_count] = tvb_get_string(tvb, offset, tokenlen);
 
     proto_tree_add_item(sdp_media_tree, hf_media_port, tvb,
                        offset, tokenlen, FALSE);
@@ -795,7 +820,7 @@ dissect_sdp_media(tvbuff_t *tvb, proto_item *ti,
       return;
     tokenlen = next_offset - offset;
     /* Save port info */
-    transport_info->media_port = tvb_get_string(tvb, offset, tokenlen);
+    transport_info->media_port[transport_info->media_count] = tvb_get_string(tvb, offset, tokenlen);
 
     /* XXX Remember Port */
     proto_tree_add_item(sdp_media_tree, hf_media_port, tvb,
@@ -810,7 +835,7 @@ dissect_sdp_media(tvbuff_t *tvb, proto_item *ti,
 
   tokenlen = next_offset - offset;
   /* Save port protocol */
-  transport_info->media_proto = tvb_get_string(tvb, offset, tokenlen);
+  transport_info->media_proto[transport_info->media_count] = tvb_get_string(tvb, offset, tokenlen);
 
   /* XXX Remember Protocol */
   proto_tree_add_item(sdp_media_tree, hf_media_proto, tvb,
@@ -821,15 +846,29 @@ dissect_sdp_media(tvbuff_t *tvb, proto_item *ti,
     next_offset = tvb_find_guint8(tvb,offset,-1,' ');
 
     if(next_offset == -1){
-      tokenlen = -1;   /* End of tvbuff */
+      tokenlen = tvb_length_remaining(tvb, offset);    /* End of tvbuff */
+      if (tokenlen == 0)
+        break; /* Nothing more left */
     } else {
       tokenlen = next_offset - offset;
     }
 
-    proto_tree_add_item(sdp_media_tree, hf_media_format, tvb,
-                       offset, tokenlen, FALSE);
+    media_format = tvb_get_string(tvb, offset, tokenlen);
+    if (!strcmp(transport_info->media_proto[transport_info->media_count], "RTP/AVP")) {
+               proto_tree_add_string(sdp_media_tree, hf_media_format, tvb,
+                                       offset, tokenlen, val_to_str(atol(media_format), rtp_payload_type_vals, "%u"));
+       } else {
+      proto_tree_add_item(sdp_media_tree, hf_media_format, tvb,
+                         offset, tokenlen, FALSE);
+    }
   } while (next_offset != -1);
 
+  /* Increase the count of media channels, but don't walk off the end
+     of the arrays. */
+  if (transport_info->media_count < (SDP_MAX_RTP_CHANNELS-1)){
+    transport_info->media_count++;
+  }
+
   /* XXX Dissect traffic to "Port" as "Protocol"
    *     Remember this Port/Protocol pair so we can tear it down again later
    *     Actually, it's harder than that:
@@ -999,7 +1038,7 @@ proto_register_sdp(void)
     { &hf_bandwidth_value,
       { "Bandwidth Value",
        "sdp.bandwidth.value",FT_STRING, BASE_NONE, NULL, 0x0,
-       "Bandwidth Value", HFILL }},
+       "Bandwidth Value (in kbits/s)", HFILL }},
     { &hf_time_start,
       { "Session Start Time",
        "sdp.time.start",FT_STRING, BASE_NONE, NULL, 0x0,
@@ -1059,7 +1098,7 @@ proto_register_sdp(void)
     { &hf_media_proto,
       { "Media Proto",
        "sdp.media.proto",FT_STRING, BASE_NONE, NULL, 0x0,
-       "Media Proto", HFILL }},
+       "Media Protocol", HFILL }},
     { &hf_media_format,
       { "Media Format",
        "sdp.media.format",FT_STRING, BASE_NONE, NULL, 0x0,