Removed trailing whitespaces from .h and .c files using the
[obnox/wireshark/wip.git] / packet-sctp.c
index 1587dd937eabb4dbd550ca782ad0ed0d22692c5b..e26dbf34f3b7c5b0f3e6f60d9e27cb57054b4344 100644 (file)
@@ -2,15 +2,15 @@
  * Routines for Stream Control Transmission Protocol dissection
  * It should be compilant to
  * - RFC 2960, for basic SCTP support
- * - http://www.ietf.org/internet-drafts/draft-ietf-tsvwg-addip-sctp-05.txt for the add-IP extension
- * - http://www.ietf.org/internet-drafts/draft-stewart-prsctp-00.txt for the 'Partial Reliability' extension
+ * - http://www.ietf.org/internet-drafts/draft-ietf-tsvwg-addip-sctp-06.txt for the add-IP extension
+ * - http://www.ietf.org/internet-drafts/draft-stewart-tsvwg-prsctp-01.txt for the 'Partial Reliability' extension
  * - http://www.ietf.org/internet-drafts/draft-ietf-tsvwg-sctpcsum-07.txt
  * Copyright 2000, 2001, 2002, Michael Tuexen <Michael.Tuexen@icn.siemens.de>
  * Still to do (so stay tuned)
  * - support for reassembly
  * - code cleanup
  *
- * $Id: packet-sctp.c,v 1.38 2002/06/08 21:54:52 guy Exp $
+ * $Id: packet-sctp.c,v 1.40 2002/07/10 21:01:57 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
 # include "config.h"
 #endif
 
-#include <stdio.h>
-#include <stdlib.h>
-
-
-#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>
-
-#ifdef NEED_SNPRINTF_H
-# include "snprintf.h"
-#endif
-
 #include "prefs.h"
 #include <epan/packet.h>
 #include "ipproto.h"
@@ -126,6 +107,8 @@ static int hf_sctp_cause_measure_of_staleness = -1;
 static int hf_sctp_cause_tsn = -1;
 
 static int hf_sctp_forward_tsn_chunk_tsn = -1;
+static int hf_sctp_forward_tsn_chunk_sid = -1;
+static int hf_sctp_forward_tsn_chunk_ssn = -1;
 
 static int hf_sctp_asconf_ack_serial = -1;
 static int hf_sctp_asconf_serial = -1;
@@ -150,6 +133,8 @@ static gint ett_sctp_sack_chunk_gap_block = -1;
 static gint ett_sctp_supported_address_types_parameter = -1;
 static gint ett_sctp_unrecognized_parameter_parameter = -1;
 
+static dissector_handle_t data_handle;
+
 #define SCTP_DATA_CHUNK_ID               0
 #define SCTP_INIT_CHUNK_ID               1
 #define SCTP_INIT_ACK_CHUNK_ID           2
@@ -289,10 +274,10 @@ static const value_string sctp_parameter_identifier_values[] = {
 #define NO_USER_DATA                               0x09
 #define COOKIE_RECEIVED_WHILE_SHUTTING_DOWN        0x0a
 #define RESTART_WITH_NEW_ADDRESSES                 0x0b
-#define REQUEST_TO_DELETE_LAST_ADDRESS             0x0c
-#define OPERATION_REFUSED_DUE_TO_RESOURCE_SHORTAGE 0X0d
-#define REQUEST_TO_DELETE_SOURCE_ADDRESS           0x0e
-#define ABORT_DUE_TO_ILLEGAL_ASCONF                0x0f
+#define REQUEST_TO_DELETE_LAST_ADDRESS             0x0100
+#define OPERATION_REFUSED_DUE_TO_RESOURCE_SHORTAGE 0X0101
+#define REQUEST_TO_DELETE_SOURCE_ADDRESS           0x0102
+#define ABORT_DUE_TO_ILLEGAL_ASCONF                0x0103
 
 static const value_string sctp_cause_code_values[] = {
   { INVALID_STREAM_IDENTIFIER,                  "Invalid stream identifier" },
@@ -1314,8 +1299,7 @@ dissect_error_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *chunk_t
 */
 
 static gboolean
-dissect_payload(tvbuff_t *payload_tvb, packet_info *pinfo, proto_tree *tree,
-               proto_tree *chunk_tree, guint32 ppi, guint16 payload_length, guint16 padding_length)
+dissect_payload(tvbuff_t *payload_tvb, packet_info *pinfo, proto_tree *tree, guint32 ppi)
 {
   guint32 low_port, high_port;
 
@@ -1354,14 +1338,8 @@ dissect_payload(tvbuff_t *payload_tvb, packet_info *pinfo, proto_tree *tree,
 
   if (check_col(pinfo->cinfo, COL_INFO))
     col_append_str(pinfo->cinfo, COL_INFO, "DATA ");
-  proto_tree_add_text(chunk_tree, payload_tvb, 0, payload_length,
-                     "Payload (%u byte%s)",
-                     payload_length, plurality(payload_length, "", "s")); 
-  if (padding_length > 0)
-    proto_tree_add_text(chunk_tree, payload_tvb, payload_length, padding_length,
-                       "Padding: %u byte%s",
-                       padding_length, plurality(padding_length, "", "s"));
-  return FALSE;
+  call_dissector(data_handle, payload_tvb, pinfo, tree);
+  return TRUE;
 }
 
 static gboolean
@@ -1379,7 +1357,7 @@ dissect_data_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
   padding_length       = nr_of_padding_bytes(length);
   total_payload_length = payload_length + padding_length;
   payload_tvb          = tvb_new_subset(chunk_tvb, DATA_CHUNK_PAYLOAD_OFFSET,
-                                         total_payload_length, total_payload_length);
+                                                           payload_length, payload_length);
   payload_proto_id     = tvb_get_ntohl(chunk_tvb, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET);
 
   if (chunk_tree) {
@@ -1412,11 +1390,18 @@ dissect_data_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree,
     proto_tree_add_uint(chunk_tree, hf_sctp_data_chunk_payload_proto_id, 
                        chunk_tvb, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH,
                        payload_proto_id);
+    if (padding_length > 0)
+      proto_tree_add_text(chunk_tree, chunk_tvb, DATA_CHUNK_PAYLOAD_OFFSET + payload_length, padding_length,
+                                 "Padding: %u byte%s",
+                                      padding_length, plurality(padding_length, "", "s"));
+
     proto_item_set_text(chunk_item, "DATA chunk with TSN %u (%u:%u) containing %u byte%s of payload",
                        tsn, stream_id, stream_seq_number, 
                        payload_length, plurality(payload_length, "", "s"));
+    proto_item_set_len(chunk_item, DATA_CHUNK_HEADER_LENGTH);
+
   };   
-  return dissect_payload(payload_tvb, pinfo, tree, chunk_tree, payload_proto_id, payload_length, padding_length); 
+  return dissect_payload(payload_tvb, pinfo, tree, payload_proto_id); 
 }
 
 static void
@@ -1812,13 +1797,19 @@ dissect_shutdown_complete_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo,
   } 
 }
 
-#define FORWARD_TSN_CHUNK_TSN_OFFSET CHUNK_VALUE_OFFSET
 #define FORWARD_TSN_CHUNK_TSN_LENGTH 4
+#define FORWARD_TSN_CHUNK_SID_LENGTH 2
+#define FORWARD_TSN_CHUNK_SSN_LENGTH 2
+#define FORWARD_TSN_CHUNK_TSN_OFFSET CHUNK_VALUE_OFFSET
+#define FORWARD_TSN_CHUNK_SID_OFFSET 0
+#define FORWARD_TSN_CHUNK_SSN_OFFSET (FORWARD_TSN_CHUNK_SID_OFFSET + FORWARD_TSN_CHUNK_SID_LENGTH)
 
 static void
 dissect_forward_tsn_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
 { 
   guint32 tsn;
+  guint   offset;
+  guint16 number_of_affected_streams, affected_stream, length, sid, ssn;
   
   if (check_col(pinfo->cinfo, COL_INFO))
     col_append_str(pinfo->cinfo, COL_INFO, "FORWARD TSN ");
@@ -1826,6 +1817,20 @@ dissect_forward_tsn_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *c
   if (chunk_tree) {
     tsn = tvb_get_ntohl(chunk_tvb, FORWARD_TSN_CHUNK_TSN_OFFSET);
     proto_tree_add_uint(chunk_tree, hf_sctp_forward_tsn_chunk_tsn, chunk_tvb, FORWARD_TSN_CHUNK_TSN_OFFSET, FORWARD_TSN_CHUNK_TSN_LENGTH, tsn);
+    length = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
+    number_of_affected_streams = (length - CHUNK_HEADER_LENGTH - FORWARD_TSN_CHUNK_TSN_LENGTH) /
+                                 (FORWARD_TSN_CHUNK_SID_LENGTH + FORWARD_TSN_CHUNK_SSN_LENGTH);
+    offset = CHUNK_VALUE_OFFSET + FORWARD_TSN_CHUNK_TSN_LENGTH;
+    
+    for(affected_stream = 0;  affected_stream < number_of_affected_streams; affected_stream++) {
+        sid    = tvb_get_ntohs(chunk_tvb, offset + FORWARD_TSN_CHUNK_SID_OFFSET);
+        ssn    = tvb_get_ntohs(chunk_tvb, offset + FORWARD_TSN_CHUNK_SSN_OFFSET);
+        proto_tree_add_uint(chunk_tree, hf_sctp_forward_tsn_chunk_sid, 
+                                       chunk_tvb, offset + FORWARD_TSN_CHUNK_SID_OFFSET, FORWARD_TSN_CHUNK_SID_LENGTH, sid);
+        proto_tree_add_uint(chunk_tree, hf_sctp_forward_tsn_chunk_ssn, 
+                                       chunk_tvb, offset + FORWARD_TSN_CHUNK_SSN_OFFSET, FORWARD_TSN_CHUNK_SSN_LENGTH, ssn);
+        offset = offset + (FORWARD_TSN_CHUNK_SID_LENGTH + FORWARD_TSN_CHUNK_SSN_LENGTH);
+    }
     proto_item_set_text(chunk_item, "FORWARD TSN chunk (new cumulative TSN %u)", tsn);
   } 
 }
@@ -2346,6 +2351,16 @@ proto_register_sctp(void)
        FT_UINT32, BASE_DEC, NULL, 0x0,          
        "", HFILL }
     }, 
+    {&hf_sctp_forward_tsn_chunk_sid,
+     { "Stream identifier", "sctp.forward_tsn.sid",
+       FT_UINT16, BASE_DEC, NULL, 0x0,          
+       "", HFILL }
+    }, 
+    {&hf_sctp_forward_tsn_chunk_ssn,
+     { "Stream sequence number", "sctp.forward_tsn.ssn",
+       FT_UINT16, BASE_DEC, NULL, 0x0,          
+       "", HFILL }
+    }, 
     {&hf_sctp_chunk_parameter_type,
      { "Parameter type", "sctp.parameter.type",
        FT_UINT16, BASE_HEX, VALS(sctp_parameter_identifier_values), 0x0,
@@ -2483,6 +2498,7 @@ proto_reg_handoff_sctp(void)
 {
   dissector_handle_t sctp_handle;
 
+  data_handle = find_dissector("data");
   sctp_handle = create_dissector_handle(dissect_sctp, proto_sctp);
   dissector_add("ip.proto", IP_PROTO_SCTP, sctp_handle);
 }