Add {0, NULL} to the isup_Pass_on_not_possible_indicator_vals and
[obnox/wireshark/wip.git] / packet-srvloc.c
index 410d83cd5c04ad0f3a02bb2647b74b9a387bf27e..e0807c6fb0d829db3feb795719cad61fa9077f95 100644 (file)
@@ -2,12 +2,14 @@
  * Routines for SRVLOC (Service Location Protocol) packet dissection
  * Copyright 1999, James Coe <jammer@cin.net>
  * Copyright 2002, Brad Hards
+ * Updated for TCP segments by Greg Morris <gmorris@novell.com>
+ * Copyright 2003, Greg Morris
  *
  * NOTE: This is Alpha software not all features have been verified yet.
  *       In particular I have not had an opportunity to see how it
  *       responds to SRVLOC over TCP.
  *
- * $Id: packet-srvloc.c,v 1.37 2003/02/24 01:22:20 guy Exp $
+ * $Id: packet-srvloc.c,v 1.43 2003/10/01 21:15:45 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
 
 #include <epan/packet.h>
 #include <epan/strutil.h>
+#include "prefs.h"
+#include "packet-tcp.h"
+#include "reassemble.h"
 
+static gboolean srvloc_desegment = TRUE;
 static int proto_srvloc = -1;
 static int hf_srvloc_version = -1;
 static int hf_srvloc_function = -1;
@@ -54,7 +60,12 @@ static int hf_srvloc_xid = -1;
 static int hf_srvloc_langtaglen = -1;
 static int hf_srvloc_langtag = -1;
 static int hf_srvloc_nextextoff = -1;
-static int hf_srvloc_flags = -1;
+static int hf_srvloc_flags_v1 = -1;
+static int hf_srvloc_flags_v1_overflow = -1;
+static int hf_srvloc_flags_v1_monolingual = -1;
+static int hf_srvloc_flags_v1_url_auth = -1;
+static int hf_srvloc_flags_v1_attribute_auth = -1;
+static int hf_srvloc_flags_v1_fresh = -1;
 static int hf_srvloc_error = -1;
 static int hf_srvloc_flags_v2 = -1;
 static int hf_srvloc_flags_v2_overflow = -1;
@@ -89,8 +100,6 @@ static int hf_srvloc_srvreg_srvtypelen = -1;
 static int hf_srvloc_srvreg_srvtype = -1;
 static int hf_srvloc_srvreg_scopelistlen = -1;
 static int hf_srvloc_srvreg_scopelist = -1;
-static int hf_srvloc_srvdereg_attrlistlen = -1;
-static int hf_srvloc_srvdereg_attrlist = -1;
 static int hf_srvloc_srvdereg_scopelistlen = -1;
 static int hf_srvloc_srvdereg_scopelist = -1;
 static int hf_srvloc_srvdereg_taglistlen = -1;
@@ -144,11 +153,23 @@ static gint ett_srvloc = -1;
 static gint ett_srvloc_flags = -1;
 
 
-static const true_false_string tfs_srvloc_flags_v2_overflow = {
+static const true_false_string tfs_srvloc_flags_overflow = {
     "Message will not fit in datagram",
     "Message will fit in a datagram"
 };
-static const true_false_string tfs_srvloc_flags_v2_fresh = {
+static const true_false_string tfs_srvloc_flags_v1_monolingual = {
+    "Only responses in specified language will be accepted",
+    "Responses in any language will be accepted"
+};
+static const true_false_string tfs_srvloc_flags_v1_url_auth = {
+    "URL Authentication Block is present",
+    "URL Authentication Block is absent"
+};
+static const true_false_string tfs_srvloc_flags_v1_attribute_auth = {
+    "Attribute Authentication Block is present",
+    "Attribute Authentication Block is absent"
+};
+static const true_false_string tfs_srvloc_flags_fresh = {
     "New Service Registration",
     "Not a new Service Registration"
 };
@@ -403,8 +424,8 @@ add_v1_string(proto_tree *tree, int hf, tvbuff_t *tvb, int offset, int length,
 }
 
 static int
-dissect_url_entry(tvbuff_t *tvb, int offset, proto_tree *tree, guint16 encoding,
-                  guint16 flags)
+dissect_url_entry_v1(tvbuff_t *tvb, int offset, proto_tree *tree,
+                     guint16 encoding, guint16 flags)
 {
     guint16    url_len;
 
@@ -497,14 +518,19 @@ dissect_srvloc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
            proto_tree_add_uint(srvloc_tree, hf_srvloc_pktlen, tvb, offset + 2, 2,
                                length);
            flags = tvb_get_guint8(tvb, offset + 4);
-           tf = proto_tree_add_uint(srvloc_tree, hf_srvloc_flags, tvb, offset + 4, 1,
+           tf = proto_tree_add_uint(srvloc_tree, hf_srvloc_flags_v1, tvb, offset + 4, 1,
                                     flags);
            srvloc_flags = proto_item_add_subtree(tf, ett_srvloc_flags);
-           proto_tree_add_text(srvloc_flags, tvb, offset + 4, 0, "Overflow                          %d... .xxx", (flags & FLAG_O) >> 7 );
-           proto_tree_add_text(srvloc_flags, tvb, offset + 4, 0, "Monolingual                       .%d.. .xxx", (flags & FLAG_M) >> 6 );
-           proto_tree_add_text(srvloc_flags, tvb, offset + 4, 0, "URL Authentication Present        ..%d. .xxx", (flags & FLAG_U) >> 5 );
-           proto_tree_add_text(srvloc_flags, tvb, offset + 4, 0, "Attribute Authentication Present  ...%d .xxx", (flags & FLAG_A) >> 4 );
-           proto_tree_add_text(srvloc_flags, tvb, offset + 4, 0, "Fresh Service Entry               .... %dxxx", (flags & FLAG_F) >> 3 );
+           proto_tree_add_boolean(srvloc_flags, hf_srvloc_flags_v1_overflow,
+                                  tvb, offset+4, 1, flags);
+           proto_tree_add_boolean(srvloc_flags, hf_srvloc_flags_v1_monolingual,
+                                  tvb, offset+4, 1, flags);
+           proto_tree_add_boolean(srvloc_flags, hf_srvloc_flags_v1_url_auth,
+                                  tvb, offset+4, 1, flags);
+           proto_tree_add_boolean(srvloc_flags, hf_srvloc_flags_v1_attribute_auth,
+                                  tvb, offset+4, 1, flags);
+           proto_tree_add_boolean(srvloc_flags, hf_srvloc_flags_v1_fresh,
+                                  tvb, offset+4, 1, flags);
            proto_tree_add_text(srvloc_tree, tvb, offset + 5, 1, "Dialect: %u",
                                tvb_get_guint8(tvb, offset + 5));
            proto_tree_add_text(srvloc_tree, tvb, offset + 6, 2, "Language: %s",
@@ -519,7 +545,6 @@ dissect_srvloc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 
            switch (function) {
             case SRVREQ:
-                proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Service Request");
                 length = tvb_get_ntohs(tvb, offset);
                 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreq_prlistlen, tvb, offset, 2, length);
                 offset += 2;
@@ -533,22 +558,20 @@ dissect_srvloc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                break;
                
             case SRVRPLY:
-                proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Service Reply");
                 proto_tree_add_item(srvloc_tree, hf_srvloc_error, tvb, offset, 2, FALSE);
                 offset += 2;
                 count = tvb_get_ntohs(tvb, offset);
                 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvrply_urlcount, tvb, offset, 2, count);
                 offset += 2;
                 while (count > 0) {
-                    offset = dissect_url_entry(tvb, offset, srvloc_tree,
-                                               encoding, flags);
+                    offset = dissect_url_entry_v1(tvb, offset, srvloc_tree,
+                                                  encoding, flags);
                     count--;
                 };
             break;
 
             case SRVREG:
-                proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Service Registration");
-                offset = dissect_url_entry(tvb, offset, srvloc_tree, encoding,
+                offset = dissect_url_entry_v1(tvb, offset, srvloc_tree, encoding,
                                            flags);
                 length = tvb_get_ntohs(tvb, offset);
                 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreg_attrlistlen, tvb, offset, 2, length);
@@ -560,25 +583,34 @@ dissect_srvloc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
             break;
 
             case SRVDEREG:
-                proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Service Deregister");
-                offset = dissect_url_entry(tvb, offset, srvloc_tree, encoding,
-                                           flags);
                 length = tvb_get_ntohs(tvb, offset);
-                proto_tree_add_uint(srvloc_tree, hf_srvloc_srvdereg_attrlistlen, tvb, offset, 2, length);
-                add_v1_string(srvloc_tree, hf_srvloc_srvdereg_attrlist, tvb, offset, length, encoding);
+                proto_tree_add_uint(tree, hf_srvloc_url_urllen, tvb, offset, 2, length);
+                offset += 2;
+                add_v1_string(tree, hf_srvloc_url_url, tvb, offset, length, encoding);
+                offset += length;
+                if ( (flags & FLAG_U) == FLAG_U )
+                    offset = dissect_authblk(tvb, offset, srvloc_tree);
+                length = tvb_get_ntohs(tvb, offset);
+                proto_tree_add_uint(srvloc_tree, hf_srvloc_srvdereg_taglistlen, tvb, offset, 2, length);
+                offset += 2;
+                add_v1_string(srvloc_tree, hf_srvloc_srvdereg_taglist, tvb, offset, length, encoding);
                 offset += length;
+                /*
+                 * XXX - this was there before, but RFC 2165 doesn't speak
+                 * of there being an attribute authentication block in
+                 * a Service Deregister message.  Is that a post-RFC-2165
+                 * addition?
+                 */
                 if ( (flags & FLAG_A) == FLAG_A )
                     offset = dissect_authblk(tvb, offset, srvloc_tree);
             break;
 
             case SRVACK:
-                proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Service Acknowledge");
                 proto_tree_add_item(srvloc_tree, hf_srvloc_error, tvb, offset, 2, FALSE);
                 offset += 2;
             break;
 
             case ATTRRQST:
-                proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Attribute Request");
                 length = tvb_get_ntohs(tvb, offset);
                 proto_tree_add_uint(srvloc_tree, hf_srvloc_attrreq_prlistlen, tvb, offset, 2, length);
                 offset += 2;
@@ -602,7 +634,6 @@ dissect_srvloc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
             break;
 
             case ATTRRPLY:
-                proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Attribute Reply");
                 proto_tree_add_item(srvloc_tree, hf_srvloc_error_v2, tvb, offset, 2, FALSE);
                 offset += 2;
                 length = tvb_get_ntohs(tvb, offset);
@@ -615,7 +646,6 @@ dissect_srvloc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
             break;
 
             case DAADVERT:
-                proto_tree_add_text(srvloc_tree, tvb, offset, 0, "DA Advertisement");
                 proto_tree_add_item(srvloc_tree, hf_srvloc_error, tvb, offset, 2, FALSE);
                 offset += 2;
                 length = tvb_get_ntohs(tvb, offset);
@@ -631,7 +661,6 @@ dissect_srvloc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
             break;
 
             case SRVTYPERQST:
-                proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Service Type Request");
                 length = tvb_get_ntohs(tvb, offset);
                 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtypereq_prlistlen, tvb, offset, 2, length);
                 offset += 2;
@@ -650,7 +679,6 @@ dissect_srvloc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
             break;
 
             case SRVTYPERPLY:
-                proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Service Type Reply");
                 proto_tree_add_item(srvloc_tree, hf_srvloc_error, tvb, offset, 2, FALSE);
                 offset += 2;
                 count = tvb_get_ntohs(tvb, offset);
@@ -903,6 +931,7 @@ dissect_srvloc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                offset += 2;
                proto_tree_add_item(srvloc_tree, hf_srvloc_saadvert_url, tvb, offset, length, TRUE);
                offset += length;
+               length = tvb_get_ntohs(tvb, offset);
                proto_tree_add_uint(srvloc_tree, hf_srvloc_saadvert_scopelistlen, tvb, offset, 2, length);
                offset += 2;
                proto_tree_add_item(srvloc_tree, hf_srvloc_saadvert_scopelist, tvb, offset, length, TRUE);
@@ -928,6 +957,54 @@ dissect_srvloc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     }
 }
 
+static guint
+get_srvloc_pdu_len(tvbuff_t *tvb, int offset)
+{
+    /*
+     * Get the length of the SRVLOC packet.
+     * It starts at offset+2, but it's 2 bytes in SLPv1 and 3 bytes
+     * in SLPv2.
+     */
+    if (tvb_get_guint8(tvb, offset) == 2)
+        return tvb_get_ntoh24(tvb, offset + 2);
+    else
+        return tvb_get_ntohs(tvb, offset + 2);
+}
+
+static void
+dissect_srvloc_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+    proto_tree     *srvloc_tree = NULL;
+    proto_item     *ti;
+
+    if (check_col(pinfo->cinfo, COL_PROTOCOL))
+        col_set_str(pinfo->cinfo, COL_PROTOCOL, "SRVLOC");
+
+    if (check_col(pinfo->cinfo, COL_INFO))
+        col_clear(pinfo->cinfo, COL_INFO);
+       
+    if (tree) {
+        ti = proto_tree_add_item(tree, proto_srvloc, tvb, 0, -1, FALSE);
+        srvloc_tree = proto_item_add_subtree(ti, ett_srvloc);
+    }
+    dissect_srvloc(tvb, pinfo, srvloc_tree);
+}
+
+static void
+dissect_srvloc_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+    /*
+     * XXX - in SLPv1, the fixed length need only be 4, as the length
+     * is 2 bytes long; however, it must be 5 for SLPv2, as the length
+     * is 3 bytes long, and there's probably no harm in asking for 5
+     * bytes, as even SLPv1 packets start with a 12-byte header,
+     * and if the packet has a length that's 4 or less, it's bogus,
+     * and we can't handle a length < 4 anyway.
+     */
+    tcp_dissect_pdus(tvb, pinfo, tree, srvloc_desegment, 5, get_srvloc_pdu_len,
+       dissect_srvloc_pdu);
+}
+
 /* Register protocol with Ethereal. */
 
 void
@@ -954,7 +1031,7 @@ proto_register_srvloc(void)
         },
         {&hf_srvloc_langtag,
             {"Lang Tag", "srvloc.langtag", 
-            FT_STRING, BASE_DEC, NULL, 0x0, 
+            FT_STRING, BASE_NONE, NULL, 0x0, 
             "", HFILL }
         },
         {&hf_srvloc_langtaglen,
@@ -983,7 +1060,7 @@ proto_register_srvloc(void)
        },
        {&hf_srvloc_url_url,
         {"URL", "srvloc.url.url",
-         FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
+         FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }
        },
        {&hf_srvloc_url_numauths,
         {"Num Auths", "srvloc.url.numauths",
@@ -1009,12 +1086,32 @@ proto_register_srvloc(void)
             "", HFILL }
         },
 
-        {&hf_srvloc_flags,
-            {"Flags", "srvloc.flags",
+        {&hf_srvloc_flags_v1,
+            {"Flags", "srvloc.flags_v1",
             FT_UINT8, BASE_HEX, NULL, 0x0,
             "", HFILL }
         },
 
+       { &hf_srvloc_flags_v1_overflow,
+         { "Overflow", "srvloc.flags_v1.overflow.", FT_BOOLEAN, 8,
+           TFS(&tfs_srvloc_flags_overflow), FLAG_O, "Can whole packet fit into a datagram?", HFILL }},
+
+       { &hf_srvloc_flags_v1_monolingual,
+         { "Monolingual", "srvloc.flags_v1.monolingual", FT_BOOLEAN, 8,
+           TFS(&tfs_srvloc_flags_v1_monolingual), FLAG_M, "Can whole packet fit into a datagram?", HFILL }},
+
+       { &hf_srvloc_flags_v1_url_auth,
+         { "URL Authentication", "srvloc.flags_v1.url_auth", FT_BOOLEAN, 8,
+           TFS(&tfs_srvloc_flags_v1_url_auth), FLAG_U, "Can whole packet fit into a datagram?", HFILL }},
+
+       { &hf_srvloc_flags_v1_attribute_auth,
+         { "Attribute Authentication", "srvloc.flags_v1.attribute_auth", FT_BOOLEAN, 8,
+           TFS(&tfs_srvloc_flags_v1_attribute_auth), FLAG_A, "Can whole packet fit into a datagram?", HFILL }},
+
+       { &hf_srvloc_flags_v1_fresh,
+         { "Fresh Registration", "srvloc.flags_v1.fresh", FT_BOOLEAN, 8,
+           TFS(&tfs_srvloc_flags_fresh), FLAG_F, "Is this a new registration?", HFILL }},
+
         {&hf_srvloc_flags_v2,
             {"Flags", "srvloc.flags_v2", 
             FT_UINT16, BASE_HEX, NULL, 0x0, 
@@ -1022,16 +1119,16 @@ proto_register_srvloc(void)
          },
 
        { &hf_srvloc_flags_v2_overflow,
-         { "Overflow", "srvloc.flags_v2.overflow.", FT_BOOLEAN, 16,
-           TFS(&tfs_srvloc_flags_v2_overflow), 0x8000, "Can whole packet fit into a datagram?", HFILL }},
+         { "Overflow", "srvloc.flags_v2.overflow", FT_BOOLEAN, 16,
+           TFS(&tfs_srvloc_flags_overflow), FLAG_O_V2, "Can whole packet fit into a datagram?", HFILL }},
 
        { &hf_srvloc_flags_v2_fresh,
-         { "Fresh Registration", "srvloc.flags_v2.fresh.", FT_BOOLEAN, 16,
-           TFS(&tfs_srvloc_flags_v2_fresh), 0x4000, "Is this a new registration?", HFILL }},
+         { "Fresh Registration", "srvloc.flags_v2.fresh", FT_BOOLEAN, 16,
+           TFS(&tfs_srvloc_flags_fresh), FLAG_F_V2, "Is this a new registration?", HFILL }},
 
        { &hf_srvloc_flags_v2_reqmulti,
-         { "Multicast requested", "srvloc.flags_v2.reqmulti.", FT_BOOLEAN, 16,
-           TFS(&tfs_srvloc_flags_v2_reqmulti), 0x2000, "Do we want multicast?", HFILL }},
+         { "Multicast requested", "srvloc.flags_v2.reqmulti", FT_BOOLEAN, 16,
+           TFS(&tfs_srvloc_flags_v2_reqmulti), FLAG_R_V2, "Do we want multicast?", HFILL }},
 
        /* collection of helper functions for dissect_authblk_v2 */
        { &hf_srvloc_authblkv2_bsd,
@@ -1051,7 +1148,7 @@ proto_register_srvloc(void)
            "Length of the SLP SPI", HFILL}
        },
        { &hf_srvloc_authblkv2_slpspi,
-         { "SLP SPI", "srvloc.authblkv2.slpspi", FT_STRING, BASE_DEC, NULL, 0x0,
+         { "SLP SPI", "srvloc.authblkv2.slpspi", FT_STRING, BASE_NONE, NULL, 0x0,
            "", HFILL}
        },
 
@@ -1061,7 +1158,7 @@ proto_register_srvloc(void)
            "Length of Previous Response List", HFILL}
        },
        { &hf_srvloc_srvreq_prlist,
-         { "Previous Response List", "srvloc.srvreq.prlist", FT_STRING, BASE_DEC, NULL, 0x0,
+         { "Previous Response List", "srvloc.srvreq.prlist", FT_STRING, BASE_NONE, NULL, 0x0,
            "Previous Response List", HFILL}
        },
        { &hf_srvloc_srvreq_srvtypelen,
@@ -1069,7 +1166,7 @@ proto_register_srvloc(void)
            "Length of Service Type List", HFILL}
        },
        { &hf_srvloc_srvreq_srvtypelist,
-         { "Service Type List", "srvloc.srvreq.srvtypelist", FT_STRING, BASE_DEC, NULL, 0x0,
+         { "Service Type List", "srvloc.srvreq.srvtypelist", FT_STRING, BASE_NONE, NULL, 0x0,
            "", HFILL}
        },
        { &hf_srvloc_srvreq_scopelistlen,
@@ -1077,7 +1174,7 @@ proto_register_srvloc(void)
            "Length of the Scope List", HFILL}
        },
        { &hf_srvloc_srvreq_scopelist,
-         { "Scope List", "srvloc.srvreq.scopelist", FT_STRING, BASE_DEC, NULL, 0x0,
+         { "Scope List", "srvloc.srvreq.scopelist", FT_STRING, BASE_NONE, NULL, 0x0,
            "", HFILL}
        },
        { &hf_srvloc_srvreq_predicatelen,
@@ -1085,7 +1182,7 @@ proto_register_srvloc(void)
            "Length of the Predicate", HFILL}
        },
        { &hf_srvloc_srvreq_predicate,
-         { "Predicate", "srvloc.srvreq.predicate", FT_STRING, BASE_DEC, NULL, 0x0,
+         { "Predicate", "srvloc.srvreq.predicate", FT_STRING, BASE_NONE, NULL, 0x0,
            "", HFILL}
        },
        { &hf_srvloc_srvreq_slpspilen,
@@ -1093,7 +1190,7 @@ proto_register_srvloc(void)
            "Length of the SLP SPI", HFILL}
        },
        { &hf_srvloc_srvreq_slpspi,
-         { "SLP SPI", "srvloc.srvreq.slpspi", FT_STRING, BASE_DEC, NULL, 0x0,
+         { "SLP SPI", "srvloc.srvreq.slpspi", FT_STRING, BASE_NONE, NULL, 0x0,
            "", HFILL}
        },
 
@@ -1109,7 +1206,7 @@ proto_register_srvloc(void)
            "", HFILL}
        },
        { &hf_srvloc_srvreg_srvtype,
-         { "Service Type", "srvloc.srvreq.srvtype", FT_STRING, BASE_DEC, NULL, 0x0,
+         { "Service Type", "srvloc.srvreq.srvtype", FT_STRING, BASE_NONE, NULL, 0x0,
            "", HFILL}
        },
        { &hf_srvloc_srvreg_scopelistlen,
@@ -1117,7 +1214,7 @@ proto_register_srvloc(void)
            "", HFILL}
        },
        { &hf_srvloc_srvreg_scopelist,
-         { "Scope List", "srvloc.srvreq.scopelist", FT_STRING, BASE_DEC, NULL, 0x0,
+         { "Scope List", "srvloc.srvreq.scopelist", FT_STRING, BASE_NONE, NULL, 0x0,
            "", HFILL}
        },
        { &hf_srvloc_srvreg_attrlistlen,
@@ -1125,7 +1222,7 @@ proto_register_srvloc(void)
            "", HFILL}
        },
        { &hf_srvloc_srvreg_attrlist,
-         { "Attribute List", "srvloc.srvreq.attrlist", FT_STRING, BASE_DEC, NULL, 0x0,
+         { "Attribute List", "srvloc.srvreq.attrlist", FT_STRING, BASE_NONE, NULL, 0x0,
            "", HFILL}
        },
        { &hf_srvloc_srvreg_attrauthcount,
@@ -1134,20 +1231,12 @@ proto_register_srvloc(void)
        },
 
        /* Helper functions for Service Deregistration */
-       { &hf_srvloc_srvdereg_attrlistlen,
-         { "Attribute List Length", "srvloc.srvdereg.attrlistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
-           "", HFILL}
-       },
-       { &hf_srvloc_srvdereg_attrlist,
-         { "Attribute List", "srvloc.srvdereg.attrlist", FT_STRING, BASE_DEC, NULL, 0x0,
-           "", HFILL}
-       },
        { &hf_srvloc_srvdereg_scopelistlen,
          { "Scope List Length", "srvloc.srvdereq.scopelistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
            "", HFILL}
        },
        { &hf_srvloc_srvdereg_scopelist,
-         { "Scope List", "srvloc.srvdereq.scopelist", FT_STRING, BASE_DEC, NULL, 0x0,
+         { "Scope List", "srvloc.srvdereq.scopelist", FT_STRING, BASE_NONE, NULL, 0x0,
            "", HFILL}
        },
        { &hf_srvloc_srvdereg_taglistlen,
@@ -1155,7 +1244,7 @@ proto_register_srvloc(void)
            "", HFILL}
        },
        { &hf_srvloc_srvdereg_taglist,
-         { "Tag List", "srvloc.srvdereq.taglist", FT_STRING, BASE_DEC, NULL, 0x0,
+         { "Tag List", "srvloc.srvdereq.taglist", FT_STRING, BASE_NONE, NULL, 0x0,
            "", HFILL}
        },
 
@@ -1166,7 +1255,7 @@ proto_register_srvloc(void)
            "Length of Previous Response List", HFILL}
        },
        { &hf_srvloc_attrreq_prlist,
-         { "Previous Response List", "srvloc.attrreq.prlist", FT_STRING, BASE_DEC, NULL, 0x0,
+         { "Previous Response List", "srvloc.attrreq.prlist", FT_STRING, BASE_NONE, NULL, 0x0,
            "Previous Response List", HFILL}
        },
        { &hf_srvloc_attrreq_urllen,
@@ -1174,7 +1263,7 @@ proto_register_srvloc(void)
            "", HFILL}
        },
        { &hf_srvloc_attrreq_url,
-         { "Service URL", "srvloc.attrreq.url", FT_STRING, BASE_DEC, NULL, 0x0,
+         { "Service URL", "srvloc.attrreq.url", FT_STRING, BASE_NONE, NULL, 0x0,
            "URL of service", HFILL}
        },
        { &hf_srvloc_attrreq_scopelistlen,
@@ -1182,7 +1271,7 @@ proto_register_srvloc(void)
            "Length of the Scope List", HFILL}
        },
        { &hf_srvloc_attrreq_scopelist,
-         { "Scope List", "srvloc.attrreq.scopelist", FT_STRING, BASE_DEC, NULL, 0x0,
+         { "Scope List", "srvloc.attrreq.scopelist", FT_STRING, BASE_NONE, NULL, 0x0,
            "", HFILL}
        },
        { &hf_srvloc_attrreq_attrlistlen,
@@ -1190,7 +1279,7 @@ proto_register_srvloc(void)
            "", HFILL}
        },
        { &hf_srvloc_attrreq_attrlist,
-         { "Attribute List", "srvloc.attrreq.attrlist", FT_STRING, BASE_DEC, NULL, 0x0,
+         { "Attribute List", "srvloc.attrreq.attrlist", FT_STRING, BASE_NONE, NULL, 0x0,
            "", HFILL}
        },
        { &hf_srvloc_attrreq_taglistlen,
@@ -1198,7 +1287,7 @@ proto_register_srvloc(void)
            "", HFILL}
        },
        { &hf_srvloc_attrreq_taglist,
-         { "Tag List", "srvloc.attrreq.taglist", FT_STRING, BASE_DEC, NULL, 0x0,
+         { "Tag List", "srvloc.attrreq.taglist", FT_STRING, BASE_NONE, NULL, 0x0,
            "", HFILL}
        },
        { &hf_srvloc_attrreq_slpspilen,
@@ -1206,7 +1295,7 @@ proto_register_srvloc(void)
            "Length of the SLP SPI", HFILL}
        },
        { &hf_srvloc_attrreq_slpspi,
-         { "SLP SPI", "srvloc.attrreq.slpspi", FT_STRING, BASE_DEC, NULL, 0x0,
+         { "SLP SPI", "srvloc.attrreq.slpspi", FT_STRING, BASE_NONE, NULL, 0x0,
            "", HFILL}
        },
 
@@ -1216,7 +1305,7 @@ proto_register_srvloc(void)
            "Length of Attribute List", HFILL}
        },
        { &hf_srvloc_attrrply_attrlist,
-         { "Attribute List", "srvloc.attrrply.attrlist", FT_STRING, BASE_DEC, NULL, 0x0,
+         { "Attribute List", "srvloc.attrrply.attrlist", FT_STRING, BASE_NONE, NULL, 0x0,
            "", HFILL}
        },
        { &hf_srvloc_attrrply_attrauthcount,
@@ -1234,7 +1323,7 @@ proto_register_srvloc(void)
            "", HFILL}
        },
        { &hf_srvloc_daadvert_url,
-         { "URL", "srvloc.daadvert.url", FT_STRING, BASE_DEC, NULL, 0x0,
+         { "URL", "srvloc.daadvert.url", FT_STRING, BASE_NONE, NULL, 0x0,
            "", HFILL}
        },
        { &hf_srvloc_daadvert_scopelistlen,
@@ -1242,7 +1331,7 @@ proto_register_srvloc(void)
            "Length of the Scope List", HFILL}
        },
        { &hf_srvloc_daadvert_scopelist,
-         { "Scope List", "srvloc.daadvert.scopelist", FT_STRING, BASE_DEC, NULL, 0x0,
+         { "Scope List", "srvloc.daadvert.scopelist", FT_STRING, BASE_NONE, NULL, 0x0,
            "", HFILL}
        },
        { &hf_srvloc_daadvert_attrlistlen,
@@ -1250,7 +1339,7 @@ proto_register_srvloc(void)
            "", HFILL}
        },
        { &hf_srvloc_daadvert_attrlist,
-         { "Attribute List", "srvloc.daadvert.attrlist", FT_STRING, BASE_DEC, NULL, 0x0,
+         { "Attribute List", "srvloc.daadvert.attrlist", FT_STRING, BASE_NONE, NULL, 0x0,
            "", HFILL}
        },
        { &hf_srvloc_daadvert_slpspilen,
@@ -1258,7 +1347,7 @@ proto_register_srvloc(void)
            "Length of the SLP SPI", HFILL}
        },
        { &hf_srvloc_daadvert_slpspi,
-         { "SLP SPI", "srvloc.daadvert.slpspi", FT_STRING, BASE_DEC, NULL, 0x0,
+         { "SLP SPI", "srvloc.daadvert.slpspi", FT_STRING, BASE_NONE, NULL, 0x0,
            "", HFILL}
        },
        { &hf_srvloc_daadvert_authcount,
@@ -1268,11 +1357,11 @@ proto_register_srvloc(void)
 
        /* collection of helper functions for Service Type Request */
        { &hf_srvloc_srvtypereq_prlistlen,
-         { "PR List Length", "srvloc.srvtypereq.prlistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
+         { "Previous Response List Length", "srvloc.srvtypereq.prlistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
            "Length of Previous Response List", HFILL}
        },
        { &hf_srvloc_srvtypereq_prlist,
-         { "PR List", "srvloc.srvtypereq.prlist", FT_STRING, BASE_DEC, NULL, 0x0,
+         { "Previous Response List", "srvloc.srvtypereq.prlist", FT_STRING, BASE_NONE, NULL, 0x0,
            "Previous Response List", HFILL}
        },
        { &hf_srvloc_srvtypereq_nameauthlistlen,
@@ -1284,7 +1373,7 @@ proto_register_srvloc(void)
            "Length of the Naming Authority List", HFILL}
        },
        { &hf_srvloc_srvtypereq_nameauthlist,
-         { "Naming Authority List", "srvloc.srvtypereq.nameauthlist", FT_STRING, BASE_DEC, NULL, 0x0,
+         { "Naming Authority List", "srvloc.srvtypereq.nameauthlist", FT_STRING, BASE_NONE, NULL, 0x0,
            "", HFILL}
        },
        { &hf_srvloc_srvtypereq_scopelistlen,
@@ -1292,7 +1381,7 @@ proto_register_srvloc(void)
            "Length of the Scope List", HFILL}
        },
        { &hf_srvloc_srvtypereq_scopelist,
-         { "Scope List", "srvloc.srvtypereq.scopelist", FT_STRING, BASE_DEC, NULL, 0x0,
+         { "Scope List", "srvloc.srvtypereq.scopelist", FT_STRING, BASE_NONE, NULL, 0x0,
            "", HFILL}
        },
 
@@ -1302,7 +1391,7 @@ proto_register_srvloc(void)
            "Length of the Service Type", HFILL}
        },
        { &hf_srvloc_srvtyperply_srvtype,
-         { "Service Type", "srvloc.srvtyperply.srvtype", FT_STRING, BASE_DEC, NULL, 0x0,
+         { "Service Type", "srvloc.srvtyperply.srvtype", FT_STRING, BASE_NONE, NULL, 0x0,
            "", HFILL}
        },
        { &hf_srvloc_srvtyperply_srvtypelistlen,
@@ -1310,7 +1399,7 @@ proto_register_srvloc(void)
            "Length of the Service Type List", HFILL}
        },
        { &hf_srvloc_srvtyperply_srvtypelist,
-         { "Service Type List", "srvloc.srvtyperply.srvtypelist", FT_STRING, BASE_DEC, NULL, 0x0,
+         { "Service Type List", "srvloc.srvtyperply.srvtypelist", FT_STRING, BASE_NONE, NULL, 0x0,
            "", HFILL}
        },
 
@@ -1320,7 +1409,7 @@ proto_register_srvloc(void)
            "", HFILL}
        },
        { &hf_srvloc_saadvert_url,
-         { "URL", "srvloc.saadvert.url", FT_STRING, BASE_DEC, NULL, 0x0,
+         { "URL", "srvloc.saadvert.url", FT_STRING, BASE_NONE, NULL, 0x0,
            "", HFILL}
        },
        { &hf_srvloc_saadvert_scopelistlen,
@@ -1328,7 +1417,7 @@ proto_register_srvloc(void)
            "Length of the Scope List", HFILL}
        },
        { &hf_srvloc_saadvert_scopelist,
-         { "Scope List", "srvloc.saadvert.scopelist", FT_STRING, BASE_DEC, NULL, 0x0,
+         { "Scope List", "srvloc.saadvert.scopelist", FT_STRING, BASE_NONE, NULL, 0x0,
            "", HFILL}
        },
        { &hf_srvloc_saadvert_attrlistlen,
@@ -1336,7 +1425,7 @@ proto_register_srvloc(void)
            "", HFILL}
        },
        { &hf_srvloc_saadvert_attrlist,
-         { "Attribute List", "srvloc.saadvert.attrlist", FT_STRING, BASE_DEC, NULL, 0x0,
+         { "Attribute List", "srvloc.saadvert.attrlist", FT_STRING, BASE_NONE, NULL, 0x0,
            "", HFILL}
        },
        { &hf_srvloc_saadvert_authcount,
@@ -1350,19 +1439,27 @@ proto_register_srvloc(void)
        &ett_srvloc,
        &ett_srvloc_flags,
     };
+       module_t *srvloc_module;
 
     proto_srvloc = proto_register_protocol("Service Location Protocol",
                                           "SRVLOC", "srvloc");
     proto_register_field_array(proto_srvloc, hf, array_length(hf));
     proto_register_subtree_array(ett, array_length(ett));
+       srvloc_module = prefs_register_protocol(proto_srvloc, NULL);
+       prefs_register_bool_preference(srvloc_module, "desegment_tcp",
+           "Desegment all SRVLOC messages spanning multiple TCP segments",
+           "Whether the SRVLOC dissector should desegment all messages spanning multiple TCP segments",
+           &srvloc_desegment);
 }
 
 void
 proto_reg_handoff_srvloc(void)
 {
-    dissector_handle_t srvloc_handle;
+    dissector_handle_t srvloc_handle, srvloc_tcp_handle;
 
     srvloc_handle = create_dissector_handle(dissect_srvloc, proto_srvloc);
-    dissector_add("tcp.port", TCP_PORT_SRVLOC, srvloc_handle);
     dissector_add("udp.port", UDP_PORT_SRVLOC, srvloc_handle);
+    srvloc_tcp_handle = create_dissector_handle(dissect_srvloc_tcp,
+                                               proto_srvloc);
+    dissector_add("tcp.port", TCP_PORT_SRVLOC, srvloc_tcp_handle);
 }