Removed trailing whitespaces from .h and .c files using the
[obnox/wireshark/wip.git] / packet-sap.c
index 76788a39526524d4cd95f9e6a7493ac2d41e3ab9..25ca3989bed0c240816b458d2875724452431e12 100644 (file)
@@ -1,13 +1,13 @@
-/* packet-tftp.c
+/* packet-sap.c
  * Routines for sap packet dissection
- * <draft-ietf-mmusic-sap-v2-03.txt>
+ * RFC 2974
  *
  * Heikki Vatiainen <hessu@cs.tut.fi>
  *
- * $Id: packet-sap.c,v 1.5 2000/02/15 21:03:07 gram Exp $
+ * $Id: packet-sap.c,v 1.29 2002/08/21 21:25:23 tpot Exp $
  *
  * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@zing.org>
+ * By Gerald Combs <gerald@ethereal.com>
  * Copyright 1998 Gerald Combs
  *
  * Copied from packet-tftp.c
 # include "config.h"
 #endif
 
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
-#ifdef HAVE_NETINET_IN_H
-# include <netinet/in.h>
-#endif
-
 #include <string.h>
 #include <glib.h>
-#include "packet.h"
+#include <epan/packet.h>
 #include "packet-ipv6.h"
-#include "packet-sdp.h"
+
+#define UDP_PORT_SAP   9875
 
 #define MCAST_SAP_VERSION_MASK 0xE0 /* 3 bits for  SAP version*/
 #define MCAST_SAP_VERSION_SHIFT 5   /* Right shift 5 bits to get the version */
@@ -59,11 +52,6 @@ static const true_false_string mcast_sap_address_type = {
         "IPv4"
 };
 
-static const true_false_string flags_set_truth = {
-        "Set",
-        "Not set"
-};
-
 static const true_false_string mcast_sap_message_type = {
         "Deletion",
         "Announcement"
@@ -124,56 +112,67 @@ static gint ett_sap_flags = -1;
 static gint ett_sap_auth = -1;
 static gint ett_sap_authf = -1;
 
-void dissect_sap(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
+static dissector_handle_t sdp_handle;
+
+static void
+dissect_sap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
+       int offset = 0;
         int sap_version, is_ipv6, is_del, is_enc, is_comp, addr_len;
+        guint8 vers_flags;
         guint8 auth_len;
         guint16 tmp1;
-        guint32 tmp2;
+        const guint8 *addr;
+        guint8 auth_flags;
+        tvbuff_t *next_tvb;
 
         proto_item *si, *sif;
         proto_tree *sap_tree, *sap_flags_tree;
 
-        is_ipv6 = pd[offset]&MCAST_SAP_BIT_A;
-        is_del = pd[offset]&MCAST_SAP_BIT_T;
-        is_enc = pd[offset]&MCAST_SAP_BIT_E;
-        is_comp = pd[offset]&MCAST_SAP_BIT_C;
+        if (check_col(pinfo->cinfo, COL_PROTOCOL))
+                col_set_str(pinfo->cinfo, COL_PROTOCOL, "SAP");
+        if (check_col(pinfo->cinfo, COL_INFO))
+                col_clear(pinfo->cinfo, COL_INFO);
+        
+       vers_flags = tvb_get_guint8(tvb, offset);
+        is_ipv6 = vers_flags&MCAST_SAP_BIT_A;
+        is_del = vers_flags&MCAST_SAP_BIT_T;
+        is_enc = vers_flags&MCAST_SAP_BIT_E;
+        is_comp = vers_flags&MCAST_SAP_BIT_C;
 
-        sap_version = (pd[offset]&MCAST_SAP_VERSION_MASK)>>MCAST_SAP_VERSION_SHIFT;
+        sap_version = (vers_flags&MCAST_SAP_VERSION_MASK)>>MCAST_SAP_VERSION_SHIFT;
         addr_len = (is_ipv6) ? sizeof(struct e_in6_addr) : 4;
 
-        if (check_col(fd, COL_PROTOCOL))
-                col_add_str(fd, COL_PROTOCOL, "SAP");
-        
-        if (check_col(fd, COL_INFO)) {
-                col_add_fstr(fd, COL_INFO, "%s (v%u)",
+        if (check_col(pinfo->cinfo, COL_INFO)) {
+                col_add_fstr(pinfo->cinfo, COL_INFO, "%s (v%u)",
                              (is_del) ? "Deletion" : "Announcement", sap_version);
         }
 
        if (tree) {
-         si = proto_tree_add_item(tree, proto_sap, offset, END_OF_FRAME, NULL);
+         si = proto_tree_add_item(tree, proto_sap, tvb, offset, -1, FALSE);
          sap_tree = proto_item_add_subtree(si, ett_sap);
 
-         sif = proto_tree_add_item(sap_tree, hf_sap_flags, offset, 1, pd[offset]);
+         sif = proto_tree_add_uint(sap_tree, hf_sap_flags, tvb, offset, 1, vers_flags);
           sap_flags_tree = proto_item_add_subtree(sif, ett_sap_flags);
-          proto_tree_add_item(sap_flags_tree, hf_sap_flags_v, offset, 1, pd[offset]);
-          proto_tree_add_item(sap_flags_tree, hf_sap_flags_a, offset, 1, pd[offset]);
-          proto_tree_add_item(sap_flags_tree, hf_sap_flags_r, offset, 1, pd[offset]);
-          proto_tree_add_item(sap_flags_tree, hf_sap_flags_t, offset, 1, pd[offset]);
-          proto_tree_add_item(sap_flags_tree, hf_sap_flags_e, offset, 1, pd[offset]);
-          proto_tree_add_item(sap_flags_tree, hf_sap_flags_c, offset, 1, pd[offset]);
+          proto_tree_add_uint(sap_flags_tree, hf_sap_flags_v, tvb, offset, 1, vers_flags);
+          proto_tree_add_boolean(sap_flags_tree, hf_sap_flags_a, tvb, offset, 1, vers_flags);
+          proto_tree_add_boolean(sap_flags_tree, hf_sap_flags_r, tvb, offset, 1, vers_flags);
+          proto_tree_add_boolean(sap_flags_tree, hf_sap_flags_t, tvb, offset, 1, vers_flags);
+          proto_tree_add_boolean(sap_flags_tree, hf_sap_flags_e, tvb, offset, 1, vers_flags);
+          proto_tree_add_boolean(sap_flags_tree, hf_sap_flags_c, tvb, offset, 1, vers_flags);
           offset++;
 
-          proto_tree_add_text(sap_tree, offset, 1, "Authentication Length: %u", pd[offset]);
-          auth_len = pd[offset];
+          auth_len = tvb_get_guint8(tvb, offset);
+          proto_tree_add_text(sap_tree, tvb, offset, 1, "Authentication Length: %u", auth_len);
           offset++;
 
-          tmp1 = pntohs(pd+offset);
-          proto_tree_add_text(sap_tree, offset, 2, "Message Identifier Hash: 0x%x", tmp1);
+          tmp1 = tvb_get_ntohs(tvb, offset);
+          proto_tree_add_text(sap_tree, tvb, offset, 2, "Message Identifier Hash: 0x%x", tmp1);
           offset +=2;
 
-          proto_tree_add_text(sap_tree, offset, addr_len, "Originating Source: %s",
-                              (is_ipv6) ? ip6_to_str((struct e_in6_addr*)(pd+offset)) : ip_to_str(pd+offset));
+          addr = tvb_get_ptr(tvb, offset, addr_len);
+          proto_tree_add_text(sap_tree, tvb, offset, addr_len, "Originating Source: %s",
+              (is_ipv6) ? ip6_to_str((struct e_in6_addr*)addr) : ip_to_str(addr));
           offset += addr_len;
 
           /* Authentication data lives in its own subtree */
@@ -186,58 +185,88 @@ void dissect_sap(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
 
                   auth_data_len = auth_len * sizeof(guint32);
 
-                  sdi = proto_tree_add_item(sap_tree, hf_auth_data, offset, auth_data_len, pd[offset]);
+                  sdi = proto_tree_add_item(sap_tree, hf_auth_data, tvb, offset, auth_data_len, FALSE);
                   sa_tree = proto_item_add_subtree(sdi, ett_sap_auth);
 
-                  sai = proto_tree_add_item(sa_tree, hf_auth_flags, offset, 1, pd[offset]);
+                  auth_flags = tvb_get_guint8(tvb, offset);
+                  sai = proto_tree_add_uint(sa_tree, hf_auth_flags, tvb, offset, 1, auth_flags);
                   saf_tree = proto_item_add_subtree(sai, ett_sap_authf);
-                  proto_tree_add_item(saf_tree, hf_auth_flags_v, offset, 1, pd[offset]);
-                  proto_tree_add_item(saf_tree, hf_auth_flags_p, offset, 1, pd[offset]);
-                  proto_tree_add_item(saf_tree, hf_auth_flags_t, offset, 1, pd[offset]);
+                  proto_tree_add_uint(saf_tree, hf_auth_flags_v, tvb, offset, 1, auth_flags);
+                  proto_tree_add_boolean(saf_tree, hf_auth_flags_p, tvb, offset, 1, auth_flags);
+                  proto_tree_add_uint(saf_tree, hf_auth_flags_t, tvb, offset, 1, auth_flags);
 
-                  has_pad = pd[offset]&MCAST_SAP_AUTH_BIT_P;
-                  if (has_pad) pad_len = *(pd+offset+auth_data_len-1);
+                  has_pad = auth_flags&MCAST_SAP_AUTH_BIT_P;
+                  if (has_pad)
+                         pad_len = tvb_get_guint8(tvb, offset+auth_data_len-1);
 
-                  proto_tree_add_text(sa_tree, offset+1, auth_data_len-pad_len-1,
+                  proto_tree_add_text(sa_tree, tvb, offset+1, auth_data_len-pad_len-1,
                                       "Authentication subheader: (%u byte%s)",
                                       auth_data_len-1, plurality(auth_data_len-1, "", "s"));
                   if (has_pad) {
-                          proto_tree_add_text(sa_tree, offset+auth_data_len-pad_len, pad_len,
+                          proto_tree_add_text(sa_tree, tvb, offset+auth_data_len-pad_len, pad_len,
                                               "Authentication data padding: (%u byte%s)",
                                               pad_len, plurality(pad_len, "", "s"));
-                          proto_tree_add_text(sa_tree, offset+auth_data_len-1, 1,
+                          proto_tree_add_text(sa_tree, tvb, offset+auth_data_len-1, 1,
                                               "Authentication data pad count: %u byte%s",
                                               pad_len, plurality(pad_len, "", "s"));
                   }
 
                   offset += auth_data_len;
           }
-
-          if (is_enc) { /* Encrypted payload implies valid timeout in the SAP header */
-                  tmp2 = pntohl(pd+offset);
-                  proto_tree_add_text(sap_tree, offset, 4, "Timeout: %u", tmp2);
-                  offset += sizeof(guint32);
-          }
-
           if (is_enc || is_comp) {
-                  proto_tree_add_text(sap_tree, offset, END_OF_FRAME,
-                                      "Rest of the packet is encrypted or compressed");
+                  char *mangle;
+                  if (is_enc && is_comp) mangle = "compressed and encrypted";
+                  else if (is_enc) mangle = "encrypted";
+                  else mangle = "compressed";
+                  proto_tree_add_text(sap_tree, tvb, offset, -1,
+                                      "The rest of the packet is %s", mangle);
                   return;
           }
 
           /* Do we have the optional payload type aka. MIME content specifier */
-          if (strncasecmp(pd+offset, "v=", strlen("v="))) {
-                  guint32 pt_len = strlen(pd+offset); /* BUG: should use strnlen */
-                  proto_tree_add_text(sap_tree, offset, pt_len, "Payload type: %s", pd+offset);
+          if (tvb_strneql(tvb, offset, "v=", strlen("v="))) {
+                  gint remaining_len;
+                  guint32 pt_len;
+                  int pt_string_len;
+
+                  remaining_len = tvb_length_remaining(tvb, offset);
+                  if (remaining_len == 0) {
+                      /*
+                       * "tvb_strneql()" failed because there was no
+                      * data left in the packet.
+                      *
+                      * Set the remaining length to 1, so that
+                      * we throw the appropriate exception in
+                      * "tvb_get_ptr()", rather than displaying
+                      * the payload type.
+                      */
+                     remaining_len = 1;
+                 }
+                  pt_string_len = tvb_strnlen(tvb, offset, remaining_len);
+                  if (pt_string_len == -1) {
+                      /*
+                       * We didn't find a terminating '\0'; run to the
+                       * end of the buffer.
+                       */
+                      pt_string_len = remaining_len;
+                      pt_len = pt_string_len;
+                  } else {
+                      /*
+                       * Include the '\0' in the total item length.
+                       */
+                      pt_len = pt_string_len + 1;
+                  }
+                  proto_tree_add_text(sap_tree, tvb, offset, pt_len,
+                      "Payload type: %.*s", pt_string_len,
+                      tvb_get_ptr(tvb, offset, pt_string_len));
                   offset += pt_len;
-                  if (pd[offset] == '\0')
-                          offset++; /* Skip possible '\0' */
           }
-          
-          /* Done with SAP */
-          dissect_sdp(pd, offset, fd, tree);
        }
 
+        /* Done with SAP */
+        next_tvb = tvb_new_subset(tvb, offset, -1, -1);
+        call_dissector(sdp_handle, next_tvb, pinfo, tree);
+
         return;
 }
 
@@ -248,62 +277,62 @@ void proto_register_sap(void)
     { &hf_sap_flags,
       { "Flags",         "sap.flags",
        FT_UINT8, BASE_HEX, NULL, 0x0,
-       "Bits in the beginning of the SAP header" }},
+       "Bits in the beginning of the SAP header", HFILL }},
 
     { &hf_sap_flags_v,
       { "Version Number",         "sap.flags.v",
        FT_UINT8, BASE_DEC, VALS(mcast_sap_ver), MCAST_SAP_VERSION_MASK,
-       "3 bit version field in the SAP header" }},
+       "3 bit version field in the SAP header", HFILL }},
 
     { &hf_sap_flags_a,
       { "Address Type",           "sap.flags.a",
        FT_BOOLEAN, 8, TFS(&mcast_sap_address_type), MCAST_SAP_BIT_A,
-       "Originating source address type" }},
+       "Originating source address type", HFILL }},
 
     { &hf_sap_flags_r,
       { "Reserved",               "sap.flags.r",
        FT_BOOLEAN, 8, TFS(&flags_set_truth), MCAST_SAP_BIT_R,
-       "Reserved" }},
+       "Reserved", HFILL }},
 
     { &hf_sap_flags_t,
       { "Message Type",           "sap.flags.t",
        FT_BOOLEAN, 8, TFS(&mcast_sap_message_type), MCAST_SAP_BIT_T,
-       "Announcement type" }},
+       "Announcement type", HFILL }},
 
     { &hf_sap_flags_e,
       { "Encryption Bit",         "sap.flags.e",
        FT_BOOLEAN, 8, TFS(&mcast_sap_crypt_type), MCAST_SAP_BIT_E,
-       "Encryption" }},
+       "Encryption", HFILL }},
 
     { &hf_sap_flags_c,
       { "Compression Bit",         "sap.flags.c",
        FT_BOOLEAN, 8, TFS(&mcast_sap_comp_type), MCAST_SAP_BIT_C,
-       "Compression" }},
+       "Compression", HFILL }},
 
     { &hf_auth_data,
       { "Authentication data",     "sap.auth",
        FT_NONE, BASE_NONE, NULL, 0x0,
-       "Auth data" }},
+       "Auth data", HFILL }},
 
     { &hf_auth_flags,
       { "Authentication data flags", "sap.auth.flags",
        FT_UINT8, BASE_HEX, NULL, 0x0,
-       "Auth flags" }},
+       "Auth flags", HFILL }},
 
     { &hf_auth_flags_v,
       { "Version Number",         "sap.auth.flags.v",
        FT_UINT8, BASE_DEC, VALS(&mcast_sap_auth_ver), MCAST_SAP_VERSION_MASK,
-       "Version" }},
+       "Version", HFILL }},
 
     { &hf_auth_flags_p,
       { "Padding Bit",            "sap.auth.flags.p",
        FT_BOOLEAN, 8, TFS(&mcast_sap_auth_pad), MCAST_SAP_AUTH_BIT_P,
-       "Compression" }},
+       "Compression", HFILL }},
 
     { &hf_auth_flags_t,
       { "Authentication Type",         "sap.auth.flags.t",
        FT_UINT8, BASE_DEC, VALS(&mcast_sap_auth_type), MCAST_SAP_AUTH_TYPE_MASK,
-       "Auth type" }}
+       "Auth type", HFILL }}
   };
   static gint *ett[] = {
     &ett_sap,
@@ -312,7 +341,22 @@ void proto_register_sap(void)
     &ett_sap_authf,
   };
 
-  proto_sap = proto_register_protocol("Session Announcement Protocol", "sap");
+  proto_sap = proto_register_protocol("Session Announcement Protocol", "SAP",
+                                     "sap");
   proto_register_field_array(proto_sap, hf, array_length(hf));
   proto_register_subtree_array(ett, array_length(ett));
 }
+
+void
+proto_reg_handoff_sap(void)
+{
+  dissector_handle_t sap_handle;
+
+  sap_handle = create_dissector_handle(dissect_sap, proto_sap);
+  dissector_add("udp.port", UDP_PORT_SAP, sap_handle);
+
+  /*
+   * Get a handle for the SDP dissector.
+   */
+  sdp_handle = find_dissector("sdp");
+}