54cd8fc21e1df0b5f089af3fe83f449ebe73458a
[obnox/wireshark/wip.git] / packet-srvloc.c
1 /* packet-srvloc.c
2  * Routines for SRVLOC (Service Location Protocol) packet dissection
3  * Copyright 1999, James Coe <jammer@cin.net>
4  * Copyright 2002, Brad Hards
5  *
6  * NOTE: This is Alpha software not all features have been verified yet.
7  *       In particular I have not had an opportunity to see how it
8  *       responds to SRVLOC over TCP.
9  *
10  * $Id: packet-srvloc.c,v 1.36 2003/02/14 07:20:40 guy Exp $
11  *
12  * Ethereal - Network traffic analyzer
13  * By Gerald Combs <gerald@ethereal.com>
14  * Copyright 1998 Gerald Combs
15  *
16  * Service Location Protocol is RFC 2165
17  * Service Location Protocol Version 2 is RFC 2608
18  *   - partial support by Brad Hards <bradh@frogmouth.net>
19  *
20  * This program is free software; you can redistribute it and/or
21  * modify it under the terms of the GNU General Public License
22  * as published by the Free Software Foundation; either version 2
23  * of the License, or (at your option) any later version.
24  *
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28  * GNU General Public License for more details.
29  *
30  * You should have received a copy of the GNU General Public License
31  * along with this program; if not, write to the Free Software
32  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
33  */
34
35 #ifdef HAVE_CONFIG_H
36 # include "config.h"
37 #endif
38
39 #include <stdio.h>
40 #include <stdlib.h>
41
42 #include <string.h>
43 #include <time.h>
44 #include <glib.h>
45
46 #include <epan/packet.h>
47 #include <epan/strutil.h>
48
49 static int proto_srvloc = -1;
50 static int hf_srvloc_version = -1;
51 static int hf_srvloc_function = -1;
52 static int hf_srvloc_pktlen = -1;
53 static int hf_srvloc_xid = -1;
54 static int hf_srvloc_langtaglen = -1;
55 static int hf_srvloc_langtag = -1;
56 static int hf_srvloc_nextextoff = -1;
57 static int hf_srvloc_flags = -1;
58 static int hf_srvloc_error = -1;
59 static int hf_srvloc_flags_v2 = -1;
60 static int hf_srvloc_flags_v2_overflow = -1;
61 static int hf_srvloc_flags_v2_fresh = -1;
62 static int hf_srvloc_flags_v2_reqmulti = -1;
63 static int hf_srvloc_error_v2 = -1;
64 static int hf_srvloc_daadvert_timestamp = -1;
65 static int hf_srvloc_daadvert_urllen = -1;
66 static int hf_srvloc_daadvert_url = -1;
67 static int hf_srvloc_daadvert_scopelistlen = -1;
68 static int hf_srvloc_daadvert_scopelist = -1;
69 static int hf_srvloc_daadvert_attrlistlen = -1;
70 static int hf_srvloc_daadvert_attrlist = -1;
71 static int hf_srvloc_daadvert_slpspilen = -1;
72 static int hf_srvloc_daadvert_slpspi = -1;
73 static int hf_srvloc_daadvert_authcount = -1;
74 static int hf_srvloc_srvreq_prlistlen = -1;
75 static int hf_srvloc_srvreq_prlist = -1;
76 static int hf_srvloc_srvreq_srvtypelen = -1;
77 static int hf_srvloc_srvreq_srvtypelist = -1;
78 static int hf_srvloc_srvreq_scopelistlen = -1;
79 static int hf_srvloc_srvreq_scopelist = -1;
80 static int hf_srvloc_srvreq_predicatelen = -1;
81 static int hf_srvloc_srvreq_predicate = -1;
82 static int hf_srvloc_srvreq_slpspilen = -1;
83 static int hf_srvloc_srvreq_slpspi = -1;
84 static int hf_srvloc_srvrply_urlcount = -1;
85 static int hf_srvloc_srvreg_attrlistlen = -1;
86 static int hf_srvloc_srvreg_attrlist = -1;
87 static int hf_srvloc_srvreg_attrauthcount = -1;
88 static int hf_srvloc_srvreg_srvtypelen = -1;
89 static int hf_srvloc_srvreg_srvtype = -1;
90 static int hf_srvloc_srvreg_scopelistlen = -1;
91 static int hf_srvloc_srvreg_scopelist = -1;
92 static int hf_srvloc_srvdereg_scopelistlen = -1;
93 static int hf_srvloc_srvdereg_scopelist = -1;
94 static int hf_srvloc_srvdereg_taglistlen = -1;
95 static int hf_srvloc_srvdereg_taglist = -1;
96 static int hf_srvloc_attrreq_prlistlen  = -1;
97 static int hf_srvloc_attrreq_prlist  = -1;
98 static int hf_srvloc_attrreq_urllen  = -1;
99 static int hf_srvloc_attrreq_url  = -1;
100 static int hf_srvloc_attrreq_scopelistlen  = -1;
101 static int hf_srvloc_attrreq_scopelist  = -1;
102 static int hf_srvloc_attrreq_taglistlen  = -1;
103 static int hf_srvloc_attrreq_taglist  = -1;
104 static int hf_srvloc_attrreq_slpspilen = -1;
105 static int hf_srvloc_attrreq_slpspi = -1;
106 static int hf_srvloc_attrrply_attrlistlen = -1;
107 static int hf_srvloc_attrrply_attrlist = -1;
108 static int hf_srvloc_attrrply_attrauthcount = -1;
109 static int hf_srvloc_srvtypereq_prlistlen = -1;
110 static int hf_srvloc_srvtypereq_prlist = -1;
111 static int hf_srvloc_srvtypereq_authlistlen = -1;
112 static int hf_srvloc_srvtypereq_authlistlenall = -1;
113 static int hf_srvloc_srvtypereq_authlist = -1;
114 static int hf_srvloc_srvtypereq_scopelistlen = -1;
115 static int hf_srvloc_srvtypereq_scopelist = -1;
116 static int hf_srvloc_srvtyperply_len = -1;
117 static int hf_srvloc_srvtyperply_type = -1;
118 static int hf_srvloc_saadvert_urllen = -1;
119 static int hf_srvloc_saadvert_url = -1;
120 static int hf_srvloc_saadvert_scopelistlen = -1;
121 static int hf_srvloc_saadvert_scopelist = -1;
122 static int hf_srvloc_saadvert_attrlistlen = -1;
123 static int hf_srvloc_saadvert_attrlist = -1;
124 static int hf_srvloc_saadvert_authcount = -1;
125 static int hf_srvloc_authblkv2_bsd = -1;
126 static int hf_srvloc_authblkv2_len = -1;
127 static int hf_srvloc_authblkv2_timestamp = -1;
128 static int hf_srvloc_authblkv2_slpspilen = -1;
129 static int hf_srvloc_authblkv2_slpspi = -1;
130 static int hf_srvloc_url_reserved = -1;
131 static int hf_srvloc_url_lifetime = -1;
132 static int hf_srvloc_url_urllen = -1;
133 static int hf_srvloc_url_url = -1;
134 static int hf_srvloc_url_numauths = -1;
135
136
137 static gint ett_srvloc = -1;
138 static gint ett_srvloc_flags = -1;
139
140
141 static const true_false_string tfs_srvloc_flags_v2_overflow = {
142     "Message will not fit in datagram",
143     "Message will fit in a datagram"
144 };
145 static const true_false_string tfs_srvloc_flags_v2_fresh = {
146     "New Service Registration",
147     "Not a new Service Registration"
148 };
149 static const true_false_string tfs_srvloc_flags_v2_reqmulti = {
150     "Multicast (or broadcast) request",
151     "Not multicast or broadcast"
152 };
153
154
155 #define TCP_PORT_SRVLOC 427
156 #define UDP_PORT_SRVLOC 427
157
158 /* Define function types */
159
160 #define SRVREQ          1
161 #define SRVRPLY         2
162 #define SRVREG          3
163 #define SRVDEREG        4
164 #define SRVACK          5
165 #define ATTRRQST        6
166 #define ATTRRPLY        7
167 #define DAADVERT        8
168 #define SRVTYPERQST     9
169 #define SRVTYPERPLY     10
170 #define SAADVERT        11 /* SLPv2, section 8 */
171
172 /* Create protocol header structure */
173
174 /* bradh: looks like never used. */
175 /* bradh: comment it out for now since it doesn't work for v2
176 struct srvloc_hdr {
177     guint8      version;
178     guint8      function;
179     guint16     length;
180     guint8      flags;
181     guint8      dialect;
182     guchar      language[2];
183     guint16     encoding;
184     guint16     xid;
185 };
186 */
187
188 /* List to resolve function numbers to names */
189
190 static const value_string srvloc_functions[] = {
191     { SRVREQ, "Service Request" },
192     { SRVRPLY, "Service Reply" },
193     { SRVREG, "Service Registration" },
194     { SRVDEREG, "Service Deregister" },
195     { SRVACK, "Service Acknowledge" },
196     { ATTRRQST, "Attribute Request" },
197     { ATTRRPLY, "Attribute Reply" },
198     { DAADVERT, "DA Advertisement" },
199     { SRVTYPERQST, "Service Type Request" },
200     { SRVTYPERPLY, "Service Type Reply" },
201     { SAADVERT, "SA Advertisement" }, /* v2 only */
202     { 0, NULL }
203 };
204
205 /* List to resolve flag values to names */
206
207
208 /* Define flag masks */
209
210 #define FLAG_O          0x80
211 #define FLAG_M          0x40
212 #define FLAG_U          0x20
213 #define FLAG_A          0x10
214 #define FLAG_F          0x08
215
216 /* it all changes for Version 2 */
217 #define FLAG_O_V2       0x8000
218 #define FLAG_F_V2       0x4000
219 #define FLAG_R_V2       0x2000
220
221 /* Define Error Codes  - Version 1*/
222
223 #define SUCCESS         0
224 #define LANG_NOT_SPTD   1
225 #define PROT_PARSE_ERR  2
226 #define INVLD_REG       3
227 #define SCOPE_NOT_SPTD  4
228 #define CHRSET_NOT_UND  5
229 #define AUTH_ABSENT     6
230 #define AUTH_FAILED     7
231
232 /* List to resolve error codes to names */
233
234 static const value_string srvloc_errs[] = {
235     { SUCCESS, "No Error" },
236     { LANG_NOT_SPTD, "Language not supported" },
237     { PROT_PARSE_ERR, "Protocol parse error" },
238     { INVLD_REG, "Invalid registration" },
239     { SCOPE_NOT_SPTD, "Scope not supported" },
240     { CHRSET_NOT_UND, "Character set not understood" },
241     { AUTH_ABSENT, "Authentication absent" },
242     { AUTH_FAILED, "Authentication failed" },
243     { 0, NULL }
244 };
245
246 /* Define Error Codes for Version 2 */
247
248 #define LANGUAGE_NOT_SUPPORTED  1 
249 #define PARSE_ERROR             2
250 #define INVALID_REGISTRATION    3
251 #define SCOPE_NOT_SUPPORTED     4
252 #define AUTHENTICATION_UNKNOWN  5
253 #define AUTHENTICATION_ABSENT   6
254 #define AUTHENTICATION_FAILED   7
255 #define VER_NOT_SUPPORTED       9
256 #define INTERNAL_ERROR          10
257 #define DA_BUSY_NOW             11
258 #define OPTION_NOT_UNDERSTOOD   12
259 #define INVALID_UPDATE          13
260 #define MSG_NOT_SUPPORTED       14
261 #define REFRESH_REJECTED        15
262
263 static const value_string srvloc_errs_v2[] = {
264     { SUCCESS, "No Error" },
265     { LANGUAGE_NOT_SUPPORTED, "No data in the requested language" },
266     { PARSE_ERROR, "The message fails to obey SLP syntax." },
267     { INVALID_REGISTRATION, "The SrvReg has problems" },
268     { SCOPE_NOT_SUPPORTED, "Scope list not supported" },
269     { AUTHENTICATION_UNKNOWN, "Unsupported SLP SPI." },
270     { AUTHENTICATION_ABSENT, "URL and ATTR authentication not provided"},
271     { AUTHENTICATION_FAILED, "Authentication error"},
272     { VER_NOT_SUPPORTED, "Unsupported version number in message header" },
273     { INTERNAL_ERROR, "The DA (or SA) is too sick to respond" },
274     { DA_BUSY_NOW, "UA or SA SHOULD retry" },
275     { OPTION_NOT_UNDERSTOOD, "Unknown option from the mandatory range"},
276     { INVALID_UPDATE, "Invalid SrvReg" },
277     { MSG_NOT_SUPPORTED, "No support for AttrRqst or SrvTypeRqst" },
278     { REFRESH_REJECTED, "SrvReg sent too soon"},
279     { 0, NULL }
280 };
281
282 /*
283  * Character encodings.
284  * This is a small subset of what's in
285  *
286  *      http://www.isi.edu/in-notes/iana/assignments/character-sets
287  *
288  * XXX - we should do something useful with this, i.e. properly
289  * handle strings based on the character set they're in.
290  *
291  * XXX - what does "properly handle strings" mean?  How do we know
292  * what character set the terminal can handle (for tty-based code)
293  * or the GUI can handle (for GUI code)?
294  *
295  * XXX - the Ethereal core really should be what does all the
296  * character set handling for strings, and it should be stuck with
297  * the task of figuring out how to properly handle them.
298  */
299 #define CHARSET_ASCII           3
300 #define CHARSET_ISO_10646_UTF_1 27
301 #define CHARSET_ISO_646_BASIC   28
302 #define CHARSET_ISO_646_IRV     30
303 #define CHARSET_ISO_8859_1      4
304 #define CHARSET_ISO_10646_UCS_2 1000    /* a/k/a Unicode */
305 #define CHARSET_UTF_7           1012
306 #define CHARSET_UTF_8           106
307
308 static const value_string charsets[] = {
309         { CHARSET_ASCII, "US-ASCII" },
310         { CHARSET_ISO_10646_UTF_1, "ISO 10646 UTF-1" },
311         { CHARSET_ISO_646_BASIC, "ISO 646 basic:1983" },
312         { CHARSET_ISO_646_IRV, "ISO 646 IRV:1983" },
313         { CHARSET_ISO_8859_1, "ISO 8859-1" },
314         { CHARSET_ISO_10646_UCS_2, "Unicode" },
315         { CHARSET_UTF_7, "UTF-7" },
316         { CHARSET_UTF_8, "UTF-8" },
317         { 0, NULL }
318 };
319
320 static int
321 dissect_authblk(tvbuff_t *tvb, int offset, proto_tree *tree)
322 {
323     struct tm   *stamp;
324     time_t      seconds;
325     double      floatsec;
326     guint16     length;
327
328     seconds = tvb_get_ntohl(tvb, offset) - 2208988800ul;
329     stamp = gmtime(&seconds);
330     if (stamp != NULL) {
331       floatsec = stamp->tm_sec + tvb_get_ntohl(tvb, offset + 4) / 4294967296.0;
332       proto_tree_add_text(tree, tvb, offset, 8,
333                           "Timestamp: %04d-%02d-%02d %02d:%02d:%07.4f UTC",
334                           stamp->tm_year + 1900, stamp->tm_mon + 1,
335                           stamp->tm_mday, stamp->tm_hour, stamp->tm_min,
336                           floatsec);
337     } else {
338       proto_tree_add_text(tree, tvb, offset, 8, "Timestamp not representable");
339     }
340     proto_tree_add_text(tree, tvb, offset + 8, 2, "Block Structure Desciptor: %u",
341                         tvb_get_ntohs(tvb, offset + 8));
342     length = tvb_get_ntohs(tvb, offset + 10);
343     proto_tree_add_text(tree, tvb, offset + 10, 2, "Authenticator length: %u",
344                         length);
345     offset += 12;
346     proto_tree_add_text(tree, tvb, offset, length, "Authentication block: %s",
347                         tvb_format_text(tvb, offset, length));
348     offset += length;
349     return offset;
350 }
351
352 /* SLPv2 version - Needs to be fixed to match RFC2608 sect 9.2*/
353 static int
354 dissect_authblk_v2(tvbuff_t *tvb, int offset, proto_tree *tree)
355 {
356     guint16 length;
357     
358     proto_tree_add_item(tree, hf_srvloc_authblkv2_bsd, tvb, offset, 2, FALSE);
359     proto_tree_add_item(tree, hf_srvloc_authblkv2_len, tvb, offset+2, 2, FALSE);
360     proto_tree_add_item(tree, hf_srvloc_authblkv2_timestamp, tvb, offset+4, 4, FALSE);
361     length = tvb_get_ntohs(tvb, offset + 8);
362     proto_tree_add_uint(tree, hf_srvloc_authblkv2_slpspilen, tvb, offset + 8, 2, length);
363     offset += 10;
364     proto_tree_add_item(tree, hf_srvloc_authblkv2_slpspi, tvb, offset, length, TRUE);
365     offset += length;
366     /* add code in here to handle Structured Authentication Block */
367     return offset;
368 }
369
370 static int
371 dissect_attrauthblk_v2(tvbuff_t *tvb, int offset, proto_tree *tree)
372 {
373     tvb=tvb; tree=tree; /* silence gcc for now */
374     /* add code in here to handle attribute authentication */
375     return offset;
376 }
377
378 static int
379 dissect_url_entry(tvbuff_t *tvb, int offset, proto_tree *tree)
380 {
381     guint8      reserved;
382     guint16     lifetime;
383     guint16     url_len;
384     guint8      num_auths;
385
386     reserved = tvb_get_guint8(tvb, offset);
387     proto_tree_add_uint(tree, hf_srvloc_url_reserved, tvb, offset, 1,
388                         reserved);
389     offset += 1;
390     lifetime = tvb_get_ntohs(tvb, offset);
391     proto_tree_add_uint(tree, hf_srvloc_url_lifetime, tvb, offset, 2,
392                         lifetime);
393     offset += 2;
394     url_len = tvb_get_ntohs(tvb, offset);
395     proto_tree_add_uint(tree, hf_srvloc_url_urllen, tvb, offset, 2,
396                         url_len);
397     offset += 2;
398     proto_tree_add_item(tree, hf_srvloc_url_url, tvb, offset, url_len, TRUE);
399     offset += url_len;
400     num_auths = tvb_get_guint8(tvb, offset);
401     proto_tree_add_uint(tree, hf_srvloc_url_numauths, tvb, offset, 1,
402                         num_auths);
403     offset += 1;
404     while (num_auths > 0) {
405         offset = dissect_authblk_v2(tvb, offset, tree);
406         num_auths--;
407     }
408     return offset;
409 }
410
411 /* Packet dissection routine called by tcp & udp when port 427 detected */
412
413 static void
414 dissect_srvloc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
415 {
416     int         offset = 0;
417     proto_item  *ti, *tf;
418     proto_tree  *srvloc_tree, *srvloc_flags;
419     guint8      version;
420     guint8      function;
421     guint16     encoding;
422     guint32     length; /* three bytes needed for v2 */
423     guint16     flags; /* two byes needed for v2 */
424     guint32     count;
425     guint32     next_ext_off; /* three bytes, v2 only */
426     guint16     lang_tag_len;
427     nstime_t    ts;
428
429     if (check_col(pinfo->cinfo, COL_PROTOCOL))
430         col_set_str(pinfo->cinfo, COL_PROTOCOL, "SRVLOC");
431
432     if (check_col(pinfo->cinfo, COL_INFO))
433         col_clear(pinfo->cinfo, COL_INFO);
434
435     version = tvb_get_guint8(tvb, offset);
436     function = tvb_get_guint8(tvb, offset + 1);
437
438     if (check_col(pinfo->cinfo, COL_INFO))
439         col_add_str(pinfo->cinfo, COL_INFO,
440             val_to_str(function, srvloc_functions, "Unknown Function (%u)"));
441
442     if (tree) {
443         ti = proto_tree_add_item(tree, proto_srvloc, tvb, offset, -1, FALSE);
444         srvloc_tree = proto_item_add_subtree(ti, ett_srvloc);
445
446         proto_tree_add_uint(srvloc_tree, hf_srvloc_version, tvb, offset, 1,
447                             version);
448         proto_tree_add_uint(srvloc_tree, hf_srvloc_function, tvb, offset + 1, 1,
449                             function);
450         if (version < 2) {
451             length = tvb_get_ntohs(tvb, offset + 2);
452             proto_tree_add_text(srvloc_tree, tvb, offset + 2, 2, "Length: %u",
453                                 length);
454             flags = tvb_get_guint8(tvb, offset + 4);
455             tf = proto_tree_add_uint(srvloc_tree, hf_srvloc_flags, tvb, offset + 4, 1,
456                                      flags);
457             srvloc_flags = proto_item_add_subtree(tf, ett_srvloc_flags);
458             proto_tree_add_text(srvloc_flags, tvb, offset + 4, 0, "Overflow                          %d... .xxx", (flags & FLAG_O) >> 7 );
459             proto_tree_add_text(srvloc_flags, tvb, offset + 4, 0, "Monolingual                       .%d.. .xxx", (flags & FLAG_M) >> 6 );
460             proto_tree_add_text(srvloc_flags, tvb, offset + 4, 0, "URL Authentication Present        ..%d. .xxx", (flags & FLAG_U) >> 5 );
461             proto_tree_add_text(srvloc_flags, tvb, offset + 4, 0, "Attribute Authentication Present  ...%d .xxx", (flags & FLAG_A) >> 4 );
462             proto_tree_add_text(srvloc_flags, tvb, offset + 4, 0, "Fresh Service Entry               .... %dxxx", (flags & FLAG_F) >> 3 );
463             proto_tree_add_text(srvloc_tree, tvb, offset + 5, 1, "Dialect: %u",
464                                 tvb_get_guint8(tvb, offset + 5));
465             proto_tree_add_text(srvloc_tree, tvb, offset + 6, 2, "Language: %s",
466                                 tvb_format_text(tvb, offset + 6, 2));
467             encoding = tvb_get_ntohs(tvb, offset + 8);
468             proto_tree_add_text(srvloc_tree, tvb, offset + 8, 2, "Encoding: %u (%s)",
469                                 encoding,
470                                 val_to_str(encoding, charsets, "Unknown"));
471             proto_tree_add_text(srvloc_tree, tvb, offset + 10, 2, "Transaction ID: %u",
472                                 tvb_get_ntohs(tvb, offset + 10));
473             offset += 12;
474
475             switch (function) {
476             case SRVREQ:
477                 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Service Request");
478                 length = tvb_get_ntohs(tvb, offset);
479                 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Previous Response List Length: %u",
480                                     length);
481                 offset += 2;
482                 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Previous Response List: %s",
483                                     tvb_format_text(tvb, offset, length));
484                 offset += length;
485                 length = tvb_get_ntohs(tvb, offset);
486                 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Predicate length: %u",
487                                     length);
488                 offset += 2;
489                 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Predicate: %s",
490                                     tvb_format_text(tvb, offset, length));
491                 offset += length;
492                 break;
493                 
494             case SRVRPLY:
495                 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Service Reply");
496                 proto_tree_add_item(srvloc_tree, hf_srvloc_error, tvb, offset, 2, FALSE);
497                 offset += 2;
498                 count = tvb_get_ntohs(tvb, offset);
499                 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "URL Count: %u",
500                                     count);
501                 offset += 2;
502                 while (count > 0) {
503                     proto_tree_add_text(srvloc_tree, tvb, offset, 2, "URL lifetime: %u",
504                                         tvb_get_ntohs(tvb, offset));
505                     offset += 2;
506                     length = tvb_get_ntohs(tvb, offset);
507                     proto_tree_add_text(srvloc_tree, tvb, offset, 2, "URL length: %u",
508                                         length);
509                     offset += 2;
510                     proto_tree_add_text(srvloc_tree, tvb, offset, length, "Service URL: %s",
511                                         tvb_format_text(tvb, offset, length));
512                     offset += length;
513                     if ( (flags & FLAG_U) == FLAG_U )
514                         offset = dissect_authblk(tvb, offset, srvloc_tree);
515                     count--;
516                 };
517             break;
518
519             case SRVREG:
520                 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Service Registration");
521                 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "URL lifetime: %u",
522                                     tvb_get_ntohs(tvb, offset));
523                 offset += 2;
524                 length = tvb_get_ntohs(tvb, offset);
525                 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "URL length: %u",
526                                     length);
527                 offset += 2;
528                 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Service URL: %s",
529                                     tvb_format_text(tvb, offset, length));
530                 offset += length;
531                 if ( (flags & FLAG_U) == FLAG_U )
532                     offset = dissect_authblk(tvb, offset, srvloc_tree);
533                 length = tvb_get_ntohs(tvb, offset);
534                 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Attribute List length: %u",
535                                     length);
536                 offset += 2;
537                 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Attribute List: %s",
538                                     tvb_format_text(tvb, offset, length));
539                 offset += length;
540                 if ( (flags & FLAG_A) == FLAG_A )
541                     offset = dissect_authblk(tvb, offset, srvloc_tree);
542             break;
543
544             case SRVDEREG:
545                 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Service Deregister");
546                 length = tvb_get_ntohs(tvb, offset);
547                 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "URL length: %u",
548                                     length);
549                 offset += 2;
550                 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Service URL: %s",
551                                     tvb_format_text(tvb, offset, length));
552                 offset += length;
553                 if ( (flags & FLAG_U) == FLAG_U )
554                     offset = dissect_authblk(tvb, offset, srvloc_tree);
555                 length = tvb_get_ntohs(tvb, offset);
556                 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Attribute List length: %u",
557                                     length);
558                 offset += 2;
559                 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Attribute List: %s",
560                                     tvb_format_text(tvb, offset, length));
561                 offset += length;
562                 if ( (flags & FLAG_A) == FLAG_A )
563                     offset = dissect_authblk(tvb, offset, srvloc_tree);
564             break;
565
566             case SRVACK:
567                 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Service Acknowledge");
568                 proto_tree_add_item(srvloc_tree, hf_srvloc_error, tvb, offset, 2, FALSE);
569                 offset += 2;
570             break;
571
572             case ATTRRQST:
573                 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Attribute Request");
574                 length = tvb_get_ntohs(tvb, offset);
575                 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Previous Response List Length: %u",
576                                     length);
577                 offset += 2;
578                 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Previous Response List: %s",
579                                     tvb_format_text(tvb, offset, length));
580                 offset += length;
581                 length = tvb_get_ntohs(tvb, offset);
582                 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "URL length: %u",
583                                     length);
584                 offset += 2;
585                 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Service URL: %s",
586                                     tvb_format_text(tvb, offset, length));
587                 offset += length;
588                 length = tvb_get_ntohs(tvb, offset);
589                 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Scope List Length: %u",
590                                     length);
591                 offset += 2;
592                 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Scope Response List: %s",
593                                     tvb_format_text(tvb, offset, length));
594                 offset += length;
595                 length = tvb_get_ntohs(tvb, offset);
596                 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Attribute List length: %u",
597                                     length);
598                 offset += 2;
599                 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Attribute List: %s",
600                                     tvb_format_text(tvb, offset, length));
601                 offset += length;
602             break;
603
604             case ATTRRPLY:
605                 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Attribute Reply");
606                 proto_tree_add_item(srvloc_tree, hf_srvloc_error_v2, tvb, offset, 2, FALSE);
607                 offset += 2;
608                 length = tvb_get_ntohs(tvb, offset);
609                 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Attribute List length: %u",
610                                     length);
611                 offset += 2;
612                 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Attribute List: %s",
613                                     tvb_format_text(tvb, offset, length));
614                 offset += length;
615                 if ( (flags & FLAG_A) == FLAG_A )
616                     offset = dissect_authblk(tvb, offset, srvloc_tree);
617             break;
618
619             case DAADVERT:
620                 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "DA Advertisement");
621                 proto_tree_add_item(srvloc_tree, hf_srvloc_error, tvb, offset, 2, FALSE);
622                 offset += 2;
623                 length = tvb_get_ntohs(tvb, offset);
624                 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "URL length: %u",
625                                     length);
626                 offset += 2;
627                 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Service URL: %s",
628                                     tvb_format_text(tvb, offset, length));
629                 offset += length;
630                 length = tvb_get_ntohs(tvb, offset);
631                 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Scope List Length: %u",
632                                     length);
633                 offset += 2;
634                 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Scope Response List: %s",
635                                     tvb_format_text(tvb, offset, length));
636                 offset += length;
637             break;
638
639             case SRVTYPERQST:
640                 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Service Type Request");
641                 length = tvb_get_ntohs(tvb, offset);
642                 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Previous Response List Length: %u",
643                                     length);
644                 offset += 2;
645                 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Previous Response List: %s",
646                                     tvb_format_text(tvb, offset, length));
647                 offset += length;
648                 length = tvb_get_ntohs(tvb, offset);
649                 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Naming Authority List length: %u",
650                                     length);
651                 offset += 2;
652                 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Naming Authority List: %s",
653                                     tvb_format_text(tvb, offset, length));
654                 offset += length;
655                 length = tvb_get_ntohs(tvb, offset);
656                 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Scope List Length: %u",
657                                     length);
658                 offset += 2;
659                 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Scope Response List: %s",
660                                     tvb_format_text(tvb, offset, length));
661                 offset += length;
662             break;
663
664             case SRVTYPERPLY:
665                 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Service Type Reply");
666                 proto_tree_add_item(srvloc_tree, hf_srvloc_error, tvb, offset, 2, FALSE);
667                 offset += 2;
668                 count = tvb_get_ntohs(tvb, offset);
669                 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Service Type Count: %u",
670                                     count);
671                 offset += 2;
672                 while (count > 0) {
673                     length = tvb_get_ntohs(tvb, offset);
674                     proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Service Type List length: %u",
675                                         length);
676                     offset += 2;
677                     proto_tree_add_text(srvloc_tree, tvb, offset, length, "Service Type List: %s",
678                                         tvb_format_text(tvb, offset, length));
679                     offset += length;
680                     count--;
681                 };
682             break;
683
684             default:
685                 proto_tree_add_text(srvloc_tree, tvb, offset, -1, "Unknown Function Type");
686             };
687         }
688         else { /* Version 2 */
689             length = tvb_get_ntoh24(tvb, offset + 2);
690             proto_tree_add_uint(srvloc_tree, hf_srvloc_pktlen, tvb, offset + 2, 3,
691                                 length);
692             flags = tvb_get_ntohs(tvb, offset + 5);
693             tf = proto_tree_add_uint(srvloc_tree, hf_srvloc_flags_v2, tvb, offset + 5, 2,
694                                      flags);
695             srvloc_flags = proto_item_add_subtree(tf, ett_srvloc_flags);
696             proto_tree_add_boolean(srvloc_flags, hf_srvloc_flags_v2_overflow,
697                                    tvb, offset+5, 1, flags);
698             proto_tree_add_boolean(srvloc_flags, hf_srvloc_flags_v2_fresh,
699                                    tvb, offset+5, 1, flags);
700             proto_tree_add_boolean(srvloc_flags, hf_srvloc_flags_v2_reqmulti,
701                                    tvb, offset+5, 1, flags);
702
703             next_ext_off = tvb_get_ntoh24(tvb, offset + 7);
704             proto_tree_add_uint(srvloc_tree, hf_srvloc_nextextoff, tvb, offset + 7, 3,
705                                 next_ext_off);
706             proto_tree_add_uint(srvloc_tree, hf_srvloc_xid, tvb, offset + 10, 2,
707                                 tvb_get_ntohs(tvb, offset + 10));
708             lang_tag_len = tvb_get_ntohs(tvb, offset + 12);
709             proto_tree_add_uint(srvloc_tree, hf_srvloc_langtaglen, tvb, offset + 12, 2, lang_tag_len);
710             proto_tree_add_item(srvloc_tree, hf_srvloc_langtag, tvb, offset + 14, lang_tag_len, TRUE);
711             offset += 14+lang_tag_len;
712
713             switch (function) {
714             case SRVREQ: /* RFC2608 8.1 */
715                 length = tvb_get_ntohs(tvb, offset);
716                 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreq_prlistlen, tvb, offset, 2, length);
717                 offset += 2;
718                 proto_tree_add_item(srvloc_tree, hf_srvloc_srvreq_prlist, tvb, offset, length, TRUE);
719                 offset += length;
720                 length = tvb_get_ntohs(tvb, offset);
721                 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreq_srvtypelen, tvb, offset, 2, length);
722                 offset += 2;
723                 proto_tree_add_item(srvloc_tree, hf_srvloc_srvreq_srvtypelist, tvb, offset, length, TRUE);
724                 offset += length;
725                 length = tvb_get_ntohs(tvb, offset);
726                 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreq_scopelistlen, tvb, offset, 2, length);
727                 offset += 2;
728                 proto_tree_add_item(srvloc_tree, hf_srvloc_srvreq_scopelist, tvb, offset, length, TRUE);
729                 offset += length;
730                 length = tvb_get_ntohs(tvb, offset);
731                 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreq_predicatelen, tvb, offset, 2, length);
732                 offset += 2;
733                 proto_tree_add_item(srvloc_tree, hf_srvloc_srvreq_predicate, tvb, offset, length, TRUE);
734                 offset += length;
735                 length = tvb_get_ntohs(tvb, offset);
736                 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreq_slpspilen, tvb, offset, 2, length);
737                 offset += 2;
738                 proto_tree_add_item(srvloc_tree, hf_srvloc_srvreq_slpspi, tvb, offset, length, TRUE);
739                 offset += length;
740                 break;
741                 
742             case SRVRPLY: /* RFC2608 8.2 */
743                 proto_tree_add_item(srvloc_tree, hf_srvloc_error_v2, tvb, offset, 2, FALSE);
744                 offset += 2;
745                 count = tvb_get_ntohs(tvb, offset);
746                 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvrply_urlcount, tvb, offset, 2, count);
747                 offset += 2;
748                 while (count > 0) {
749                     offset = dissect_url_entry(tvb, offset, srvloc_tree);
750                     count--;
751                 };
752             break;
753
754             case SRVREG: /* RFC2608 8.3 */
755                 offset = dissect_url_entry(tvb, offset, srvloc_tree);
756                 length = tvb_get_ntohs(tvb, offset);
757                 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreg_srvtypelen, tvb, offset, 2, length);
758                 offset += 2;
759                 proto_tree_add_item(srvloc_tree, hf_srvloc_srvreg_srvtype, tvb, offset, length, TRUE);
760                 offset += length;
761                 length = tvb_get_ntohs(tvb, offset);
762                 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreg_scopelistlen, tvb, offset, 2, length);
763                 offset += 2;
764                 proto_tree_add_item(srvloc_tree, hf_srvloc_srvreg_scopelist, tvb, offset, length, TRUE);
765                 offset += length;
766                 length = tvb_get_ntohs(tvb, offset);
767                 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreg_attrlistlen, tvb, offset, 2, length);
768                 offset += 2;
769                 proto_tree_add_item(srvloc_tree, hf_srvloc_srvreg_attrlist, tvb, offset, length, TRUE);
770                 offset += length;
771                 count = tvb_get_guint8(tvb, offset);
772                 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreg_attrauthcount, tvb, offset, 1, count);
773                 offset += 1;
774                 while (count > 0) {
775                     offset = dissect_attrauthblk_v2(tvb, offset, srvloc_tree);
776                     count--;
777                 }
778                 break;
779
780             case SRVDEREG: /* RFC2608 10.6 */
781                 length = tvb_get_ntohs(tvb, offset);
782                 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvdereg_scopelistlen, tvb, offset, 2, length);
783                 offset += 2;
784                 proto_tree_add_item(srvloc_tree, hf_srvloc_srvdereg_scopelist, tvb, offset, length, TRUE);
785                 offset += length;
786                 offset = dissect_url_entry(tvb, offset, srvloc_tree);
787                 length = tvb_get_ntohs(tvb, offset);
788                 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvdereg_taglistlen, tvb, offset, 2, length);
789                 offset += 2;
790                 proto_tree_add_item(srvloc_tree, hf_srvloc_srvdereg_taglist, tvb, offset, length, TRUE);
791                 offset += length;
792                 break;
793             
794             case SRVACK: /* RFC2608 8.4 */
795                 proto_tree_add_item(srvloc_tree, hf_srvloc_error_v2, tvb, offset, 2, FALSE);
796                 offset += 2;
797             break;
798
799             case ATTRRQST: /* RFC2608 10.3*/
800                 length = tvb_get_ntohs(tvb, offset);
801                 proto_tree_add_uint(srvloc_tree, hf_srvloc_attrreq_prlistlen, tvb, offset, 2, length);
802                 offset += 2;
803                 proto_tree_add_item(srvloc_tree, hf_srvloc_attrreq_prlist, tvb, offset, length, TRUE);
804                 offset += length;
805                 length = tvb_get_ntohs(tvb, offset);
806                 proto_tree_add_uint(srvloc_tree, hf_srvloc_attrreq_urllen, tvb, offset, 2, length);
807                 offset += 2;
808                 proto_tree_add_item(srvloc_tree, hf_srvloc_attrreq_url, tvb, offset, length, TRUE);
809                 offset += length;
810                 length = tvb_get_ntohs(tvb, offset);
811                 proto_tree_add_uint(srvloc_tree, hf_srvloc_attrreq_scopelistlen, tvb, offset, 2, length);
812                 offset += 2;
813                 proto_tree_add_item(srvloc_tree, hf_srvloc_attrreq_scopelist, tvb, offset, length, TRUE);
814                 offset += length;
815                 length = tvb_get_ntohs(tvb, offset);
816                 proto_tree_add_uint(srvloc_tree, hf_srvloc_attrreq_taglistlen, tvb, offset, 2, length);
817                 offset += 2;
818                 proto_tree_add_item(srvloc_tree, hf_srvloc_attrreq_taglist, tvb, offset, length, TRUE);
819                 offset += length;
820                 length = tvb_get_ntohs(tvb, offset);
821                 proto_tree_add_uint(srvloc_tree, hf_srvloc_attrreq_slpspilen, tvb, offset, 2, length);
822                 offset += 2;
823                 proto_tree_add_item(srvloc_tree, hf_srvloc_attrreq_slpspi, tvb, offset, length, TRUE);
824                 offset += length;
825             break;
826
827             case ATTRRPLY: /* RFC2608 10.4 */
828                 proto_tree_add_item(srvloc_tree, hf_srvloc_error_v2, tvb, offset, 2, FALSE);
829                 offset += 2;
830                 length = tvb_get_ntohs(tvb, offset);
831                 proto_tree_add_uint(srvloc_tree, hf_srvloc_attrrply_attrlistlen, tvb, offset, 2, length);
832                 offset += 2;
833                 proto_tree_add_item(srvloc_tree, hf_srvloc_attrrply_attrlist, tvb, offset, length, TRUE);
834                 offset += length;
835                 count = tvb_get_guint8(tvb, offset); 
836                 proto_tree_add_uint(srvloc_tree, hf_srvloc_attrrply_attrauthcount, tvb, offset, 1, count);
837                 offset += 1;
838                 while (count > 0) {
839                     offset = dissect_attrauthblk_v2(tvb, offset, srvloc_tree);
840                     count--;
841                 }
842             break;
843             
844             case DAADVERT: /* RCC 2608 8.5 */
845                 proto_tree_add_item(srvloc_tree, hf_srvloc_error_v2, tvb, offset, 2, FALSE);
846                 offset += 2;
847                 ts.nsecs = 0;
848                 ts.secs = tvb_get_ntohl(tvb, offset);
849                 proto_tree_add_time(srvloc_tree, hf_srvloc_daadvert_timestamp, tvb, offset, 4,
850                                     &ts);
851                 offset += 4;
852                 length = tvb_get_ntohs(tvb, offset);
853                 proto_tree_add_uint(srvloc_tree, hf_srvloc_daadvert_urllen, tvb, offset, 2, length);
854                 offset += 2;
855                 proto_tree_add_item(srvloc_tree, hf_srvloc_daadvert_url, tvb, offset, length, TRUE);
856                 offset += length;
857                 length = tvb_get_ntohs(tvb, offset);
858                 proto_tree_add_uint(srvloc_tree, hf_srvloc_daadvert_scopelistlen, tvb, offset, 2, length);
859                 offset += 2;
860                 proto_tree_add_item(srvloc_tree, hf_srvloc_daadvert_scopelist, tvb, offset, length, TRUE);
861                 offset += length;
862                 length = tvb_get_ntohs(tvb, offset);
863                 proto_tree_add_uint(srvloc_tree, hf_srvloc_daadvert_attrlistlen, tvb, offset, 2, length);
864                 offset += 2;
865                 proto_tree_add_item(srvloc_tree, hf_srvloc_daadvert_attrlist, tvb, offset, length, TRUE);
866                 offset += length;
867                 length = tvb_get_ntohs(tvb, offset);
868                 proto_tree_add_uint(srvloc_tree, hf_srvloc_daadvert_slpspilen, tvb, offset, 2, length);
869                 offset += 2;
870                 proto_tree_add_item(srvloc_tree, hf_srvloc_daadvert_slpspi, tvb, offset, length, TRUE);
871                 offset += length;
872                 count = tvb_get_guint8(tvb, offset); 
873                 proto_tree_add_uint(srvloc_tree, hf_srvloc_daadvert_authcount, tvb, offset, 1, count);
874                 offset += 1;
875                 while (count > 0) {
876                     offset = dissect_authblk_v2(tvb, offset, srvloc_tree);
877                     count--;
878                 }
879             break;
880
881             case SRVTYPERQST: /* RFC2608 10.1 */
882                 length = tvb_get_ntohs(tvb, offset);
883                 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtypereq_prlistlen, tvb, offset, 2, length);
884                 offset += 2;
885                 proto_tree_add_item(srvloc_tree, hf_srvloc_srvtypereq_prlist, tvb, offset, length, TRUE);
886                 offset += length;
887                 length = tvb_get_ntohs(tvb, offset);
888                 if (0xFFFF == length) {
889                     proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtypereq_authlistlenall, tvb, offset, 2, length);
890                     offset += 2;
891                 } else {
892                     proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtypereq_authlistlen, tvb, offset, 2, length);
893                     offset += 2;
894                     proto_tree_add_item(srvloc_tree, hf_srvloc_srvtypereq_authlist, tvb, offset, length, TRUE);
895                     offset += length;
896                 }
897                 length = tvb_get_ntohs(tvb, offset);
898                 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtypereq_scopelistlen, tvb, offset, 2, length);
899                 offset += 2;
900                 proto_tree_add_item(srvloc_tree, hf_srvloc_srvtypereq_scopelist, tvb, offset, length, TRUE);
901                 offset += length;
902             break;
903
904             case SRVTYPERPLY: /* rfc2608 10.2 */
905                 proto_tree_add_item(srvloc_tree, hf_srvloc_error_v2, tvb, offset, 2, FALSE);
906                 offset += 2;
907                 length = tvb_get_ntohs(tvb, offset);
908                 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtyperply_len, tvb, offset, 2, length);
909                 offset += 2;
910                 proto_tree_add_item(srvloc_tree, hf_srvloc_srvtyperply_type, tvb, offset, length, TRUE);
911             break;
912
913             case SAADVERT: /* rfc2608 10.2 */
914                 length = tvb_get_ntohs(tvb, offset);
915                 proto_tree_add_uint(srvloc_tree, hf_srvloc_saadvert_urllen, tvb, offset, 2,
916                                     length);
917                 offset += 2;
918                 proto_tree_add_item(srvloc_tree, hf_srvloc_saadvert_url, tvb, offset, length, TRUE);
919                 offset += length;
920                 proto_tree_add_uint(srvloc_tree, hf_srvloc_saadvert_scopelistlen, tvb, offset, 2, length);
921                 offset += 2;
922                 proto_tree_add_item(srvloc_tree, hf_srvloc_saadvert_scopelist, tvb, offset, length, TRUE);
923                 offset += length;
924                 length = tvb_get_ntohs(tvb, offset);
925                 proto_tree_add_uint(srvloc_tree, hf_srvloc_saadvert_attrlistlen, tvb, offset, 2, length);
926                 offset += 2;
927                 proto_tree_add_item(srvloc_tree, hf_srvloc_saadvert_attrlist, tvb, offset, length, TRUE);
928                 offset += length;
929                 count = tvb_get_guint8(tvb, offset);
930                 proto_tree_add_uint(srvloc_tree, hf_srvloc_saadvert_authcount, tvb, offset, 1, length);
931                 offset += 1;
932                 while (count > 0) {
933                     offset = dissect_authblk_v2(tvb, offset, srvloc_tree);
934                     count--;
935                 }
936                 break;
937
938             default:
939                 proto_tree_add_text(srvloc_tree, tvb, offset, -1, "Unknown Function Type");
940             };
941         };
942     }
943 }
944
945 /* Register protocol with Ethereal. */
946
947 void
948 proto_register_srvloc(void)
949 {
950     static hf_register_info hf[] = {
951         /* Helper functions for the Version 1 Header*/
952         {&hf_srvloc_error,
953             {"Error Code", "srvloc.err",
954             FT_UINT16, BASE_DEC, VALS(srvloc_errs), 0x0,
955             "", HFILL }
956         },
957
958         /* Helper function for the Version 2 Header */
959         {&hf_srvloc_error_v2,
960             {"Error Code", "srvloc.errv2",
961             FT_UINT16, BASE_DEC, VALS(srvloc_errs_v2), 0x0,
962             "", HFILL }
963         },
964         {&hf_srvloc_xid,
965             {"XID", "srvloc.xid", 
966             FT_UINT24, BASE_DEC, NULL, 0x0, 
967             "Transaction ID", HFILL }
968         },
969         {&hf_srvloc_langtag,
970             {"Lang Tag", "srvloc.langtag", 
971             FT_STRING, BASE_DEC, NULL, 0x0, 
972             "", HFILL }
973         },
974         {&hf_srvloc_langtaglen,
975             {"Lang Tag Len", "srvloc.langtaglen", 
976             FT_UINT16, BASE_DEC, NULL, 0x0, 
977             "", HFILL }
978         },
979         {&hf_srvloc_nextextoff,
980             {"Next Extension Offset", "srvloc.nextextoff", 
981             FT_UINT24, BASE_DEC, NULL, 0x0, 
982             "", HFILL }
983         },
984         /* Helper functions for URL parsing - Version 2 */
985         {&hf_srvloc_url_reserved,
986          {"Reserved", "srvloc.url.reserved",
987           FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }
988         },
989         {&hf_srvloc_url_lifetime,
990          {"Lifetime", "srvloc.url.lifetime",
991           FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
992         },
993         {&hf_srvloc_url_urllen,
994          {"URL Length", "srvloc.url.urllen",
995           FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
996         },
997         {&hf_srvloc_url_url,
998          {"URL", "srvloc.url.url",
999           FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }
1000         },
1001         {&hf_srvloc_url_numauths,
1002          {"Num Auths", "srvloc.url.numauths",
1003           FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
1004         },
1005
1006         /* Helper functions for the common header fields */
1007         {&hf_srvloc_function,
1008             {"Function", "srvloc.function",
1009             FT_UINT8, BASE_DEC, VALS(srvloc_functions), 0x0,
1010             "", HFILL }
1011         },
1012
1013         {&hf_srvloc_pktlen,
1014             {"Packet Length", "srvloc.pktlen", 
1015             FT_UINT24, BASE_DEC, NULL, 0x0, 
1016             "", HFILL }
1017         },
1018
1019         { &hf_srvloc_version,
1020             { "Version",           "srvloc.version",
1021             FT_UINT8, BASE_DEC, NULL, 0x0,
1022             "", HFILL }
1023         },
1024
1025         {&hf_srvloc_flags,
1026             {"Flags", "srvloc.flags",
1027             FT_UINT8, BASE_HEX, NULL, 0x0,
1028             "", HFILL }
1029         },
1030
1031         {&hf_srvloc_flags_v2,
1032             {"Flags", "srvloc.flags_v2", 
1033             FT_UINT16, BASE_HEX, NULL, 0x0, 
1034              "", HFILL }
1035          },
1036
1037         { &hf_srvloc_flags_v2_overflow,
1038           { "Overflow", "srvloc.flags_v2.overflow.", FT_BOOLEAN, 16,
1039             TFS(&tfs_srvloc_flags_v2_overflow), 0x8000, "Can whole packet fit into a datagram?", HFILL }},
1040
1041         { &hf_srvloc_flags_v2_fresh,
1042           { "Fresh Registration", "srvloc.flags_v2.fresh.", FT_BOOLEAN, 16,
1043             TFS(&tfs_srvloc_flags_v2_fresh), 0x4000, "Is this a new registration?", HFILL }},
1044
1045         { &hf_srvloc_flags_v2_reqmulti,
1046           { "Multicast requested", "srvloc.flags_v2.reqmulti.", FT_BOOLEAN, 16,
1047             TFS(&tfs_srvloc_flags_v2_reqmulti), 0x2000, "Do we want multicast?", HFILL }},
1048
1049         /* collection of helper functions for dissect_authblk_v2 */
1050         { &hf_srvloc_authblkv2_bsd,
1051           { "BSD", "srvloc.authblkv2_bsd", FT_UINT16, BASE_HEX, NULL, 0x0,
1052             "Block Structure Descriptor", HFILL}
1053         },
1054         { &hf_srvloc_authblkv2_len,
1055           { "Length", "srvloc.authblkv2_len", FT_UINT16, BASE_DEC, NULL, 0x0,
1056             "Length of Authentication Block", HFILL}
1057         },
1058         { &hf_srvloc_authblkv2_timestamp,
1059           { "Timestamp", "srvloc.authblkv2.timestamp", FT_ABSOLUTE_TIME, BASE_NONE,
1060             NULL, 0, "Timestamp on Authentication Block", HFILL }
1061         },
1062         { &hf_srvloc_authblkv2_slpspilen,
1063           { "SLP SPI Length", "srvloc.authblkv2.slpspilen", FT_UINT16, BASE_DEC, NULL, 0x0,
1064             "Length of the SLP SPI", HFILL}
1065         },
1066         { &hf_srvloc_authblkv2_slpspi,
1067           { "SLP SPI", "srvloc.authblkv2.slpspi", FT_STRING, BASE_DEC, NULL, 0x0,
1068             "", HFILL}
1069         },
1070
1071         /* collection of helper functions for Service Request */
1072         { &hf_srvloc_srvreq_prlistlen,
1073           { "PR List Length", "srvloc.srvreq.prlistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1074             "Length of Previous Response List", HFILL}
1075         },
1076         { &hf_srvloc_srvreq_prlist,
1077           { "PR List", "srvloc.srvreq.prlist", FT_STRING, BASE_DEC, NULL, 0x0,
1078             "Previous Response List", HFILL}
1079         },
1080         { &hf_srvloc_srvreq_srvtypelen,
1081           { "Service Type Length", "srvloc.srvreq.srvtypelen", FT_UINT16, BASE_DEC, NULL, 0x0,
1082             "Length of Service Type List", HFILL}
1083         },
1084         { &hf_srvloc_srvreq_srvtypelist,
1085           { "Service Type List", "srvloc.srvreq.srvtypelist", FT_STRING, BASE_DEC, NULL, 0x0,
1086             "", HFILL}
1087         },
1088         { &hf_srvloc_srvreq_scopelistlen,
1089           { "Scope List Length", "srvloc.srvreq.scopelistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1090             "Length of the Scope List", HFILL}
1091         },
1092         { &hf_srvloc_srvreq_scopelist,
1093           { "Scope List", "srvloc.srvreq.scopelist", FT_STRING, BASE_DEC, NULL, 0x0,
1094             "", HFILL}
1095         },
1096         { &hf_srvloc_srvreq_predicatelen,
1097           { "Predicate Length", "srvloc.srvreq.predicatelen", FT_UINT16, BASE_DEC, NULL, 0x0,
1098             "Length of the Predicate", HFILL}
1099         },
1100         { &hf_srvloc_srvreq_predicate,
1101           { "Predicate", "srvloc.srvreq.predicate", FT_STRING, BASE_DEC, NULL, 0x0,
1102             "", HFILL}
1103         },
1104         { &hf_srvloc_srvreq_slpspilen,
1105           { "SLP SPI Length", "srvloc.srvreq.slpspilen", FT_UINT16, BASE_DEC, NULL, 0x0,
1106             "Length of the SLP SPI", HFILL}
1107         },
1108         { &hf_srvloc_srvreq_slpspi,
1109           { "SLP SPI", "srvloc.srvreq.slpspi", FT_STRING, BASE_DEC, NULL, 0x0,
1110             "", HFILL}
1111         },
1112
1113         /* Helper function for Service Request */
1114         { &hf_srvloc_srvrply_urlcount,
1115           { "Number of URLs", "srvloc.srvreq.urlcount", FT_UINT16, BASE_DEC, NULL, 0x0,
1116             "", HFILL}
1117         },
1118
1119         /* Helper functions for Service Registration */
1120         { &hf_srvloc_srvreg_srvtypelen,
1121           { "Service Type Length", "srvloc.srvreq.srvtypelen", FT_UINT16, BASE_DEC, NULL, 0x0,
1122             "", HFILL}
1123         },
1124         { &hf_srvloc_srvreg_srvtype,
1125           { "Service Type", "srvloc.srvreq.srvtype", FT_STRING, BASE_DEC, NULL, 0x0,
1126             "", HFILL}
1127         },
1128         { &hf_srvloc_srvreg_scopelistlen,
1129           { "Scope List Length", "srvloc.srvreq.scopelistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1130             "", HFILL}
1131         },
1132         { &hf_srvloc_srvreg_scopelist,
1133           { "Scope List", "srvloc.srvreq.scopelist", FT_STRING, BASE_DEC, NULL, 0x0,
1134             "", HFILL}
1135         },
1136         { &hf_srvloc_srvreg_attrlistlen,
1137           { "Attribute List Length", "srvloc.srvreq.attrlistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1138             "", HFILL}
1139         },
1140         { &hf_srvloc_srvreg_attrlist,
1141           { "Attribute List", "srvloc.srvreq.attrlist", FT_STRING, BASE_DEC, NULL, 0x0,
1142             "", HFILL}
1143         },
1144         { &hf_srvloc_srvreg_attrauthcount,
1145           { "Attr Auths", "srvloc.srvreq.attrauthcount", FT_UINT8, BASE_DEC, NULL, 0x0,
1146             "Number of Attribute Authentication Blocks", HFILL}
1147         },
1148
1149         /* Helper functions for Service Deregistration */
1150         { &hf_srvloc_srvdereg_scopelistlen,
1151           { "Scope List Length", "srvloc.srvdereq.scopelistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1152             "", HFILL}
1153         },
1154         { &hf_srvloc_srvdereg_scopelist,
1155           { "Scope List", "srvloc.srvdereq.scopelist", FT_STRING, BASE_DEC, NULL, 0x0,
1156             "", HFILL}
1157         },
1158         { &hf_srvloc_srvdereg_taglistlen,
1159           { "Tag List Length", "srvloc.srvdereq.taglistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1160             "", HFILL}
1161         },
1162         { &hf_srvloc_srvdereg_taglist,
1163           { "Tag List", "srvloc.srvdereq.taglist", FT_STRING, BASE_DEC, NULL, 0x0,
1164             "", HFILL}
1165         },
1166
1167
1168         /* collection of helper functions for Attribute Request */
1169         { &hf_srvloc_attrreq_prlistlen,
1170           { "PR List Length", "srvloc.attrreq.prlistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1171             "Length of Previous Response List", HFILL}
1172         },
1173         { &hf_srvloc_attrreq_prlist,
1174           { "PR List", "srvloc.attrreq.prlist", FT_STRING, BASE_DEC, NULL, 0x0,
1175             "Previous Response List", HFILL}
1176         },
1177         { &hf_srvloc_attrreq_urllen,
1178           { "URL Length", "srvloc.attrreq.urllen", FT_UINT16, BASE_DEC, NULL, 0x0,
1179             "", HFILL}
1180         },
1181         { &hf_srvloc_attrreq_url,
1182           { "URL", "srvloc.attrreq.url", FT_STRING, BASE_DEC, NULL, 0x0,
1183             "URL of service", HFILL}
1184         },
1185         { &hf_srvloc_attrreq_scopelistlen,
1186           { "Scope List Length", "srvloc.attrreq.scopelistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1187             "Length of the Scope List", HFILL}
1188         },
1189         { &hf_srvloc_attrreq_scopelist,
1190           { "Scope List", "srvloc.attrreq.scopelist", FT_STRING, BASE_DEC, NULL, 0x0,
1191             "", HFILL}
1192         },
1193         { &hf_srvloc_attrreq_taglistlen,
1194           { "Tag List Length", "srvloc.attrreq.taglistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1195             "", HFILL}
1196         },
1197         { &hf_srvloc_attrreq_taglist,
1198           { "Tag List", "srvloc.attrreq.taglist", FT_STRING, BASE_DEC, NULL, 0x0,
1199             "", HFILL}
1200         },
1201         { &hf_srvloc_attrreq_slpspilen,
1202           { "SLP SPI Length", "srvloc.attrreq.slpspilen", FT_UINT16, BASE_DEC, NULL, 0x0,
1203             "Length of the SLP SPI", HFILL}
1204         },
1205         { &hf_srvloc_attrreq_slpspi,
1206           { "SLP SPI", "srvloc.attrreq.slpspi", FT_STRING, BASE_DEC, NULL, 0x0,
1207             "", HFILL}
1208         },
1209
1210         /* collection of helper functions for Attribute Reply */
1211         { &hf_srvloc_attrrply_attrlistlen,
1212           { "Attribute List Length", "srvloc.attrrply.attrlistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1213             "Length of Attribute List", HFILL}
1214         },
1215         { &hf_srvloc_attrrply_attrlist,
1216           { "Attribute Reply", "srvloc.attrrply.attrlist", FT_STRING, BASE_DEC, NULL, 0x0,
1217             "", HFILL}
1218         },
1219         { &hf_srvloc_attrrply_attrauthcount,
1220           { "Attr Auths", "srvloc.srvreq.attrauthcount", FT_UINT8, BASE_DEC, NULL, 0x0,
1221             "Number of Attribute Authentication Blocks", HFILL}
1222         },
1223
1224         /* collection of helper functions for DA Advertisement */
1225         { &hf_srvloc_daadvert_timestamp,
1226           { "DAADVERT Timestamp", "srvloc.daadvert.timestamp", FT_ABSOLUTE_TIME, BASE_NONE,
1227             NULL, 0, "Timestamp on DA Advert", HFILL }
1228         },
1229         { &hf_srvloc_daadvert_urllen,
1230           { "URL Length", "srvloc.daadvert.urllen", FT_UINT16, BASE_DEC, NULL, 0x0,
1231             "", HFILL}
1232         },
1233         { &hf_srvloc_daadvert_url,
1234           { "URL", "srvloc.daadvert.url", FT_STRING, BASE_DEC, NULL, 0x0,
1235             "", HFILL}
1236         },
1237         { &hf_srvloc_daadvert_scopelistlen,
1238           { "Scope List Length", "srvloc.daadvert.scopelistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1239             "Length of the Scope List", HFILL}
1240         },
1241         { &hf_srvloc_daadvert_scopelist,
1242           { "Scope List", "srvloc.daadvert.scopelist", FT_STRING, BASE_DEC, NULL, 0x0,
1243             "", HFILL}
1244         },
1245         { &hf_srvloc_daadvert_attrlistlen,
1246           { "Attribute List Length", "srvloc.daadvert.attrlistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1247             "", HFILL}
1248         },
1249         { &hf_srvloc_daadvert_attrlist,
1250           { "Attribute List", "srvloc.daadvert.attrlist", FT_STRING, BASE_DEC, NULL, 0x0,
1251             "", HFILL}
1252         },
1253         { &hf_srvloc_daadvert_slpspilen,
1254           { "SLP SPI Length", "srvloc.daadvert.slpspilen", FT_UINT16, BASE_DEC, NULL, 0x0,
1255             "Length of the SLP SPI", HFILL}
1256         },
1257         { &hf_srvloc_daadvert_slpspi,
1258           { "SLP SPI", "srvloc.daadvert.slpspi", FT_STRING, BASE_DEC, NULL, 0x0,
1259             "", HFILL}
1260         },
1261         { &hf_srvloc_daadvert_authcount,
1262           { "Auths", "srvloc.daadvert.authcount", FT_UINT8, BASE_DEC, NULL, 0x0,
1263             "Number of Authentication Blocks", HFILL}
1264         },
1265
1266         /* collection of helper functions for Service Type Request */
1267         { &hf_srvloc_srvtypereq_prlistlen,
1268           { "PR List Length", "srvloc.srvtypereq.prlistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1269             "Length of Previous Response List", HFILL}
1270         },
1271         { &hf_srvloc_srvtypereq_prlist,
1272           { "PR List", "srvloc.srvtypereq.prlist", FT_STRING, BASE_DEC, NULL, 0x0,
1273             "Previous Response List", HFILL}
1274         },
1275         { &hf_srvloc_srvtypereq_authlistlen,
1276           { "Naming Authority List Length", "srvloc.srvtypereq.nameauthlistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1277             "Length of the Naming Authority List", HFILL}
1278         },
1279         { &hf_srvloc_srvtypereq_authlistlenall,
1280           { "Naming Authority List Length (All Naming Authorities)", "srvloc.srvtypereq.nameauthlistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1281             "Length of the Naming Authority List", HFILL}
1282         },
1283         { &hf_srvloc_srvtypereq_authlist,
1284           { "Naming Authority List", "srvloc.srvtypereq.nameauthlist", FT_STRING, BASE_DEC, NULL, 0x0,
1285             "", HFILL}
1286         },
1287         { &hf_srvloc_srvtypereq_scopelistlen,
1288           { "Scope List Length", "srvloc.srvtypereq.scopelistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1289             "Length of the Scope List", HFILL}
1290         },
1291         { &hf_srvloc_srvtypereq_scopelist,
1292           { "Scope List", "srvloc.srvtypereq.scopelist", FT_STRING, BASE_DEC, NULL, 0x0,
1293             "", HFILL}
1294         },
1295
1296         /* collection of helper functions for Service Type Replies */
1297         { &hf_srvloc_srvtyperply_len,
1298           { "Service Length", "srvloc.srvtypereq.len", FT_UINT16, BASE_DEC, NULL, 0x0,
1299             "Length of the Scope List", HFILL}
1300         },
1301         { &hf_srvloc_srvtyperply_type,
1302           { "Service", "srvloc.srvtyperply.type", FT_STRING, BASE_DEC, NULL, 0x0,
1303             "", HFILL}
1304         },
1305
1306         /* collection of helper functions for SA Advertisement */
1307         { &hf_srvloc_saadvert_urllen,
1308           { "URL Length", "srvloc.saadvert.urllen", FT_UINT16, BASE_DEC, NULL, 0x0,
1309             "", HFILL}
1310         },
1311         { &hf_srvloc_saadvert_url,
1312           { "URL", "srvloc.saadvert.url", FT_STRING, BASE_DEC, NULL, 0x0,
1313             "", HFILL}
1314         },
1315         { &hf_srvloc_saadvert_scopelistlen,
1316           { "Scope List Length", "srvloc.saadvert.scopelistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1317             "Length of the Scope List", HFILL}
1318         },
1319         { &hf_srvloc_saadvert_scopelist,
1320           { "Scope List", "srvloc.saadvert.scopelist", FT_STRING, BASE_DEC, NULL, 0x0,
1321             "", HFILL}
1322         },
1323         { &hf_srvloc_saadvert_attrlistlen,
1324           { "Attribute List Length", "srvloc.saadvert.attrlistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1325             "", HFILL}
1326         },
1327         { &hf_srvloc_saadvert_attrlist,
1328           { "Attribute List", "srvloc.saadvert.attrlist", FT_STRING, BASE_DEC, NULL, 0x0,
1329             "", HFILL}
1330         },
1331         { &hf_srvloc_saadvert_authcount,
1332           { "Auths", "srvloc.saadvert.authcount", FT_UINT8, BASE_DEC, NULL, 0x0,
1333             "Number of Authentication Blocks", HFILL}
1334         }
1335
1336     };
1337
1338     static gint *ett[] = {
1339         &ett_srvloc,
1340         &ett_srvloc_flags,
1341     };
1342
1343     proto_srvloc = proto_register_protocol("Service Location Protocol",
1344                                            "SRVLOC", "srvloc");
1345     proto_register_field_array(proto_srvloc, hf, array_length(hf));
1346     proto_register_subtree_array(ett, array_length(ett));
1347 }
1348
1349 void
1350 proto_reg_handoff_srvloc(void)
1351 {
1352     dissector_handle_t srvloc_handle;
1353
1354     srvloc_handle = create_dissector_handle(dissect_srvloc, proto_srvloc);
1355     dissector_add("tcp.port", TCP_PORT_SRVLOC, srvloc_handle);
1356     dissector_add("udp.port", UDP_PORT_SRVLOC, srvloc_handle);
1357 }