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