MSWSP: add two more Property Sets
[wireshark-wip.git] / epan / dissectors / packet-srvloc.c
blobf8addd577ba52ddbd2ca3d9018e6a07b5f5a047b
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 * Updated for TCP segments by Greg Morris <gmorris@novell.com>
6 * Copyright 2003, Greg Morris
8 * NOTE: This is Alpha software not all features have been verified yet.
9 * In particular I have not had an opportunity to see how it
10 * responds to SRVLOC over TCP.
12 * $Id$
14 * Wireshark - Network traffic analyzer
15 * By Gerald Combs <gerald@wireshark.org>
16 * Copyright 1998 Gerald Combs
18 * Service Location Protocol is RFC 2165
19 * Service Location Protocol Version 2 is RFC 2608
20 * - partial support by Brad Hards <bradh@frogmouth.net>
22 * This program is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU General Public License
24 * as published by the Free Software Foundation; either version 2
25 * of the License, or (at your option) any later version.
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU General Public License for more details.
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
37 #include "config.h"
39 #include <stdio.h>
40 #include <stdlib.h>
42 #include <string.h>
43 #include <time.h>
44 #include <glib.h>
46 #include <epan/packet.h>
47 #include <epan/strutil.h>
48 #include <epan/prefs.h>
49 #include <epan/wmem/wmem.h>
50 #include "packet-tcp.h"
51 #include <epan/expert.h>
53 static gboolean srvloc_desegment = TRUE;
54 static int proto_srvloc = -1;
55 static int hf_srvloc_version = -1;
56 static int hf_srvloc_function = -1;
57 static int hf_srvloc_pktlen = -1;
58 static int hf_srvloc_xid = -1;
59 static int hf_srvloc_langtaglen = -1;
60 static int hf_srvloc_langtag = -1;
61 static int hf_srvloc_nextextoff = -1;
62 static int hf_srvloc_flags_v1 = -1;
63 static int hf_srvloc_flags_v1_overflow = -1;
64 static int hf_srvloc_flags_v1_monolingual = -1;
65 static int hf_srvloc_flags_v1_url_auth = -1;
66 static int hf_srvloc_flags_v1_attribute_auth = -1;
67 static int hf_srvloc_flags_v1_fresh = -1;
68 static int hf_srvloc_error = -1;
69 static int hf_srvloc_flags_v2 = -1;
70 static int hf_srvloc_flags_v2_overflow = -1;
71 static int hf_srvloc_flags_v2_fresh = -1;
72 static int hf_srvloc_flags_v2_reqmulti = -1;
73 static int hf_srvloc_error_v2 = -1;
74 static int hf_srvloc_daadvert_timestamp = -1;
75 static int hf_srvloc_daadvert_urllen = -1;
76 static int hf_srvloc_daadvert_url = -1;
77 static int hf_srvloc_daadvert_scopelistlen = -1;
78 static int hf_srvloc_daadvert_scopelist = -1;
79 static int hf_srvloc_daadvert_attrlistlen = -1;
80 static int hf_srvloc_daadvert_attrlist = -1;
81 static int hf_srvloc_daadvert_slpspilen = -1;
82 static int hf_srvloc_daadvert_slpspi = -1;
83 static int hf_srvloc_daadvert_authcount = -1;
84 static int hf_srvloc_srvreq_prlistlen = -1;
85 static int hf_srvloc_srvreq_prlist = -1;
86 static int hf_srvloc_srvreq_srvtypelen = -1;
87 static int hf_srvloc_srvreq_srvtypelist = -1;
88 static int hf_srvloc_srvreq_scopelistlen = -1;
89 static int hf_srvloc_srvreq_scopelist = -1;
90 static int hf_srvloc_srvreq_predicatelen = -1;
91 static int hf_srvloc_srvreq_predicate = -1;
92 static int hf_srvloc_srvreq_slpspilen = -1;
93 static int hf_srvloc_srvreq_slpspi = -1;
94 static int hf_srvloc_srvrply_urlcount = -1;
95 static int hf_srvloc_srvreg_attrlistlen = -1;
96 static int hf_srvloc_srvreg_attrlist = -1;
97 static int hf_srvloc_srvreg_attrauthcount = -1;
98 static int hf_srvloc_srvreg_srvtypelen = -1;
99 static int hf_srvloc_srvreg_srvtype = -1;
100 static int hf_srvloc_srvreg_scopelistlen = -1;
101 static int hf_srvloc_srvreg_scopelist = -1;
102 static int hf_srvloc_srvdereg_scopelistlen = -1;
103 static int hf_srvloc_srvdereg_scopelist = -1;
104 static int hf_srvloc_srvdereg_taglistlen = -1;
105 static int hf_srvloc_srvdereg_taglist = -1;
106 static int hf_srvloc_attrreq_prlistlen = -1;
107 static int hf_srvloc_attrreq_prlist = -1;
108 static int hf_srvloc_attrreq_urllen = -1;
109 static int hf_srvloc_attrreq_url = -1;
110 static int hf_srvloc_attrreq_scopelistlen = -1;
111 static int hf_srvloc_attrreq_scopelist = -1;
112 static int hf_srvloc_attrreq_attrlistlen = -1;
113 static int hf_srvloc_attrreq_attrlist = -1;
114 static int hf_srvloc_attrreq_taglistlen = -1;
115 static int hf_srvloc_attrreq_taglist = -1;
116 static int hf_srvloc_attrreq_slpspilen = -1;
117 static int hf_srvloc_attrreq_slpspi = -1;
118 static int hf_srvloc_attrrply_attrlistlen = -1;
119 static int hf_srvloc_attrrply_attrlist = -1;
120 static int hf_srvloc_attrrply_attrauthcount = -1;
121 static int hf_srvloc_srvtypereq_prlistlen = -1;
122 static int hf_srvloc_srvtypereq_prlist = -1;
123 static int hf_srvloc_srvtypereq_nameauthlistlen = -1;
124 static int hf_srvloc_srvtypereq_nameauthlistlenall = -1;
125 static int hf_srvloc_srvtypereq_nameauthlist = -1;
126 static int hf_srvloc_srvtypereq_scopelistlen = -1;
127 static int hf_srvloc_srvtypereq_scopelist = -1;
128 static int hf_srvloc_srvtyperply_srvtypelen = -1;
129 static int hf_srvloc_srvtyperply_srvtype = -1;
130 static int hf_srvloc_srvtyperply_srvtypelistlen = -1;
131 static int hf_srvloc_srvtyperply_srvtypelist = -1;
132 static int hf_srvloc_saadvert_urllen = -1;
133 static int hf_srvloc_saadvert_url = -1;
134 static int hf_srvloc_saadvert_scopelistlen = -1;
135 static int hf_srvloc_saadvert_scopelist = -1;
136 static int hf_srvloc_saadvert_attrlistlen = -1;
137 static int hf_srvloc_saadvert_attrlist = -1;
138 static int hf_srvloc_saadvert_authcount = -1;
139 static int hf_srvloc_authblkv2_bsd = -1;
140 static int hf_srvloc_authblkv2_len = -1;
141 static int hf_srvloc_authblkv2_timestamp = -1;
142 static int hf_srvloc_authblkv2_slpspilen = -1;
143 static int hf_srvloc_authblkv2_slpspi = -1;
144 static int hf_srvloc_url_reserved = -1;
145 static int hf_srvloc_url_lifetime = -1;
146 static int hf_srvloc_url_urllen = -1;
147 static int hf_srvloc_url_url = -1;
148 static int hf_srvloc_url_numauths = -1;
149 static int hf_srvloc_add_ref_ip = -1;
150 static int hf_srvloc_srvrply_svcname = -1;
153 static gint ett_srvloc = -1;
154 static gint ett_srvloc_attr = -1;
155 static gint ett_srvloc_flags = -1;
157 static expert_field ei_srvloc_error = EI_INIT;
158 static expert_field ei_srvloc_error_v2 = EI_INIT;
159 static expert_field ei_srvloc_function_unknown = EI_INIT;
161 static const true_false_string tfs_srvloc_flags_overflow = {
162 "Message will not fit in datagram",
163 "Message will fit in a datagram"
165 static const true_false_string tfs_srvloc_flags_v1_monolingual = {
166 "Only responses in specified language will be accepted",
167 "Responses in any language will be accepted"
169 static const true_false_string tfs_srvloc_flags_v1_url_auth = {
170 "URL Authentication Block is present",
171 "URL Authentication Block is absent"
173 static const true_false_string tfs_srvloc_flags_v1_attribute_auth = {
174 "Attribute Authentication Block is present",
175 "Attribute Authentication Block is absent"
177 static const true_false_string tfs_srvloc_flags_fresh = {
178 "New Service Registration",
179 "Not a new Service Registration"
181 static const true_false_string tfs_srvloc_flags_v2_reqmulti = {
182 "Multicast (or broadcast) request",
183 "Not multicast or broadcast"
186 #define TCP_PORT_SRVLOC 427
187 #define UDP_PORT_SRVLOC 427
189 /* Define function types */
191 #define SRVREQ 1
192 #define SRVRPLY 2
193 #define SRVREG 3
194 #define SRVDEREG 4
195 #define SRVACK 5
196 #define ATTRRQST 6
197 #define ATTRRPLY 7
198 #define DAADVERT 8
199 #define SRVTYPERQST 9
200 #define SRVTYPERPLY 10
201 #define SAADVERT 11 /* SLPv2, section 8 */
203 /* Create protocol header structure */
205 /* bradh: looks like never used. */
206 /* bradh: comment it out for now since it doesn't work for v2
207 struct srvloc_hdr {
208 guint8 version;
209 guint8 function;
210 guint16 length;
211 guint8 flags;
212 guint8 dialect;
213 guchar language[2];
214 guint16 encoding;
215 guint16 xid;
219 /* List to resolve function numbers to names */
221 static const value_string srvloc_functions[] = {
222 { SRVREQ, "Service Request" },
223 { SRVRPLY, "Service Reply" },
224 { SRVREG, "Service Registration" },
225 { SRVDEREG, "Service Deregister" },
226 { SRVACK, "Service Acknowledge" },
227 { ATTRRQST, "Attribute Request" },
228 { ATTRRPLY, "Attribute Reply" },
229 { DAADVERT, "DA Advertisement" },
230 { SRVTYPERQST, "Service Type Request" },
231 { SRVTYPERPLY, "Service Type Reply" },
232 { SAADVERT, "SA Advertisement" }, /* v2 only */
233 { 0, NULL }
236 /* List to resolve flag values to names */
239 /* Define flag masks */
241 #define FLAG_O 0x80
242 #define FLAG_M 0x40
243 #define FLAG_U 0x20
244 #define FLAG_A 0x10
245 #define FLAG_F 0x08
247 /* it all changes for Version 2 */
248 #define FLAG_O_V2 0x8000
249 #define FLAG_F_V2 0x4000
250 #define FLAG_R_V2 0x2000
252 /* Define Error Codes - Version 1*/
254 #define SUCCESS 0
255 #define LANG_NOT_SPTD 1
256 #define PROT_PARSE_ERR 2
257 #define INVLD_REG 3
258 #define SCOPE_NOT_SPTD 4
259 #define CHRSET_NOT_UND 5
260 #define AUTH_ABSENT 6
261 #define AUTH_FAILED 7
263 /* List to resolve error codes to names */
265 static const value_string srvloc_errs[] = {
266 { SUCCESS, "No Error" },
267 { LANG_NOT_SPTD, "Language not supported" },
268 { PROT_PARSE_ERR, "Protocol parse error" },
269 { INVLD_REG, "Invalid registration" },
270 { SCOPE_NOT_SPTD, "Scope not supported" },
271 { CHRSET_NOT_UND, "Character set not understood" },
272 { AUTH_ABSENT, "Authentication absent" },
273 { AUTH_FAILED, "Authentication failed" },
274 { 0, NULL }
277 /* Define Error Codes for Version 2 */
279 #define LANGUAGE_NOT_SUPPORTED 1
280 #define PARSE_ERROR 2
281 #define INVALID_REGISTRATION 3
282 #define SCOPE_NOT_SUPPORTED 4
283 #define AUTHENTICATION_UNKNOWN 5
284 #define AUTHENTICATION_ABSENT 6
285 #define AUTHENTICATION_FAILED 7
286 #define VER_NOT_SUPPORTED 9
287 #define INTERNAL_ERROR 10
288 #define DA_BUSY_NOW 11
289 #define OPTION_NOT_UNDERSTOOD 12
290 #define INVALID_UPDATE 13
291 #define MSG_NOT_SUPPORTED 14
292 #define REFRESH_REJECTED 15
294 static const value_string srvloc_errs_v2[] = {
295 { SUCCESS, "No Error" },
296 { LANGUAGE_NOT_SUPPORTED, "No data in the requested language" },
297 { PARSE_ERROR, "The message fails to obey SLP syntax." },
298 { INVALID_REGISTRATION, "The SrvReg has problems" },
299 { SCOPE_NOT_SUPPORTED, "Scope list not supported" },
300 { AUTHENTICATION_UNKNOWN, "Unsupported SLP SPI." },
301 { AUTHENTICATION_ABSENT, "URL and ATTR authentication not provided"},
302 { AUTHENTICATION_FAILED, "Authentication error"},
303 { VER_NOT_SUPPORTED, "Unsupported version number in message header" },
304 { INTERNAL_ERROR, "The DA (or SA) is too sick to respond" },
305 { DA_BUSY_NOW, "UA or SA SHOULD retry" },
306 { OPTION_NOT_UNDERSTOOD, "Unknown option from the mandatory range"},
307 { INVALID_UPDATE, "Invalid SrvReg" },
308 { MSG_NOT_SUPPORTED, "No support for AttrRqst or SrvTypeRqst" },
309 { REFRESH_REJECTED, "SrvReg sent too soon"},
310 { 0, NULL }
314 * Character encodings.
315 * This is a small subset of what's in
317 * http://www.iana.org/assignments/character-sets
319 * XXX - we should do something useful with this, i.e. properly
320 * handle strings based on the character set they're in.
322 * XXX - what does "properly handle strings" mean? How do we know
323 * what character set the terminal can handle (for tty-based code)
324 * or the GUI can handle (for GUI code)?
326 * XXX - the Wireshark core really should be what does all the
327 * character set handling for strings, and it should be stuck with
328 * the task of figuring out how to properly handle them.
330 #define CHARSET_ASCII 3
331 #define CHARSET_ISO_10646_UTF_1 27
332 #define CHARSET_ISO_646_BASIC 28
333 #define CHARSET_ISO_646_IRV 30
334 #define CHARSET_ISO_8859_1 4
335 #define CHARSET_ISO_10646_UCS_2 1000 /* a/k/a Unicode */
336 #define CHARSET_UTF_7 1012
337 #define CHARSET_UTF_8 106
339 static const value_string charsets[] = {
340 { CHARSET_ASCII, "US-ASCII" },
341 { CHARSET_ISO_10646_UTF_1, "ISO 10646 UTF-1" },
342 { CHARSET_ISO_646_BASIC, "ISO 646 basic:1983" },
343 { CHARSET_ISO_646_IRV, "ISO 646 IRV:1983" },
344 { CHARSET_ISO_8859_1, "ISO 8859-1" },
345 { CHARSET_ISO_10646_UCS_2, "Unicode" },
346 { CHARSET_UTF_7, "UTF-7" },
347 { CHARSET_UTF_8, "UTF-8" },
348 { 0, NULL }
351 static int
352 dissect_authblk(tvbuff_t *tvb, int offset, proto_tree *tree)
354 struct tm *stamp;
355 time_t seconds;
356 double floatsec;
357 guint16 length;
359 seconds = tvb_get_ntohl(tvb, offset) - 2208988800ul;
360 stamp = gmtime(&seconds);
361 if (stamp != NULL) {
362 floatsec = stamp->tm_sec + tvb_get_ntohl(tvb, offset + 4) / 4294967296.0;
363 proto_tree_add_text(tree, tvb, offset, 8,
364 "Timestamp: %04d-%02d-%02d %02d:%02d:%07.4f UTC",
365 stamp->tm_year + 1900, stamp->tm_mon + 1,
366 stamp->tm_mday, stamp->tm_hour, stamp->tm_min,
367 floatsec);
368 } else {
369 proto_tree_add_text(tree, tvb, offset, 8, "Timestamp not representable");
371 proto_tree_add_text(tree, tvb, offset + 8, 2, "Block Structure Descriptor: %u",
372 tvb_get_ntohs(tvb, offset + 8));
373 length = tvb_get_ntohs(tvb, offset + 10);
374 proto_tree_add_text(tree, tvb, offset + 10, 2, "Authenticator length: %u",
375 length);
376 offset += 12;
377 proto_tree_add_text(tree, tvb, offset, length, "Authentication block: %s",
378 tvb_format_text(tvb, offset, length));
379 offset += length;
380 return offset;
383 /* SLPv2 version - Needs to be fixed to match RFC2608 sect 9.2*/
384 static int
385 dissect_authblk_v2(tvbuff_t *tvb, int offset, proto_tree *tree)
387 guint16 length;
388 nstime_t ts;
390 proto_tree_add_item(tree, hf_srvloc_authblkv2_bsd, tvb, offset, 2, ENC_BIG_ENDIAN);
391 proto_tree_add_item(tree, hf_srvloc_authblkv2_len, tvb, offset+2, 2, ENC_BIG_ENDIAN);
392 ts.nsecs = 0;
393 ts.secs = tvb_get_ntohl(tvb, offset + 4);
394 proto_tree_add_time(tree, hf_srvloc_authblkv2_timestamp, tvb, offset+4, 4, &ts);
395 length = tvb_get_ntohs(tvb, offset + 8);
396 proto_tree_add_uint(tree, hf_srvloc_authblkv2_slpspilen, tvb, offset + 8, 2, length);
397 offset += 10;
398 proto_tree_add_item(tree, hf_srvloc_authblkv2_slpspi, tvb, offset, length, ENC_ASCII|ENC_NA);
399 offset += length;
400 /* add code in here to handle Structured Authentication Block */
401 return offset;
404 static int
405 dissect_attrauthblk_v2(tvbuff_t *tvb _U_, int offset, proto_tree *tree _U_)
407 /* add code in here to handle attribute authentication */
408 return offset;
411 static void
412 add_v1_string(proto_tree *tree, int hf, tvbuff_t *tvb, int offset, int length,
413 guint16 encoding)
415 char *unicode_str;
417 switch (encoding) {
419 case CHARSET_ISO_10646_UCS_2:
420 unicode_str = tvb_get_unicode_string(wmem_packet_scope(), tvb, offset, length, ENC_BIG_ENDIAN);
421 proto_tree_add_string(tree, hf, tvb, offset, length,
422 unicode_str);
423 break;
425 default:
426 /* XXX - need to support all the CHARSET_ values */
427 proto_tree_add_item(tree, hf, tvb, offset, length, ENC_ASCII|ENC_NA);
428 break;
433 * XXX - is this trying to guess the byte order?
435 * http://www.iana.org/assignments/character-sets
437 * says of ISO-10646-UCS-2, which has the code 1000 (this routine is used
438 * with CHARSET_ISO_10646_UCS_2, which is #defined to be 1000):
440 * this needs to specify network byte order: the standard
441 * does not specify (it is a 16-bit integer space)
443 * Does that mean that in SRVLOC, ISO-10646-UCS-2 is always big-endian?
444 * If so, can we just use "tvb_get_unicode_string()" and be
445 * done with it?
447 * XXX - this is also used with CHARSET_UTF_8. Is that a cut-and-pasteo?
449 static const guint8*
450 unicode_to_bytes(tvbuff_t *tvb, int offset, int length, gboolean endianness)
452 const guint8 *ascii_text = tvb_get_string(wmem_packet_scope(), tvb, offset, length);
453 int i, j=0;
454 guint8 c_char, c_char1;
455 guint8 *byte_array;
457 /* XXX - Is this the correct behavior? */
458 if (length < 1)
459 return "";
461 if (endianness) {
462 byte_array = (guint8 *)wmem_alloc(wmem_packet_scope(), length*2 + 1);
463 for (i = length; i > 0; i--) {
464 c_char = ascii_text[i];
465 if (c_char != 0) {
466 i--;
467 c_char1 = ascii_text[i];
468 if (c_char1 == 0) {
469 i--;
470 c_char1 = ascii_text[i];
472 byte_array[j] = c_char1;
473 j++;
474 byte_array[j] = c_char;
475 j++;
479 else
481 byte_array = (guint8 *)wmem_alloc(wmem_packet_scope(), length + 1);
482 for (i = 0; i < length; i++) {
483 c_char = ascii_text[i];
484 if (c_char != 0) {
485 byte_array[j] = c_char;
486 j++;
491 byte_array[j]=0;
492 return byte_array;
496 * Format of x-x-x-xxxxxxxx. Each of these entries represents the service binding to UDP, TCP, or IPX.
497 * The first digit is the protocol family: 2 for TCP/UPD, 6 for IPX.
498 * The second digit is the socket type: 1 for socket stream (TCP), 2 for datagram (UDP and IPX).
499 * The third is the protocol: 6 for TCP, 17 for UDP, and 1000 for IPX.
500 * Last is the IP address, in hex, of the interface that is registered (or, in the case of IPX, an IPX network number).
502 * OpenSLP supports multiple attribute replies so we need to parse the attribute name and then decode accourdingly.
503 * We currently only parse the (non-utf8) attributes:
504 * svcname
505 * svcaddr
507 static void
508 attr_list(proto_tree *tree, int hf, tvbuff_t *tvb, int offset, int length,
509 guint16 encoding)
511 const char *attr_type;
512 int i, svc, ss, type_len, foffset=offset;
513 guint32 prot;
514 const guint8 *byte_value;
515 proto_item *ti;
516 proto_tree *srvloc_tree;
517 char *tmp;
519 static const value_string srvloc_svc[] = {
520 { 50, "TCP/UDP" },
521 { 54, "IPX" },
522 { 0, NULL }
525 static const value_string srvloc_ss[] = {
526 { 49, "Socket" },
527 { 50, "Datagram" },
528 { 0, NULL }
531 static const value_string srvloc_prot[] = {
532 { 54, "TCP" },
533 { 17, "UDP" },
534 { 1000, "IPX" },
535 { 0, NULL }
538 switch (encoding) {
540 case CHARSET_ISO_10646_UCS_2:
541 while (offset+2<length) {
542 offset += 2;
543 /* If the length passed is longer then the actual payload then this must be an incomplete packet. */
544 if (tvb_length_remaining(tvb, 4)<length) {
545 proto_tree_add_text(tree, tvb, offset, -1, "Status: Too much data to pass inside this protocol. Resubmit request using a streaming protocol like TCP.");
546 proto_tree_add_text(tree, tvb, offset, -1, "Note: Protocol dissection is aborted due to packet overflow. See overflow flag.");
547 break;
549 /* Parse the attribute name */
550 tmp = tvb_get_unicode_string(wmem_packet_scope(), tvb, offset, length-offset, ENC_BIG_ENDIAN);
551 type_len = (int)strcspn(tmp, "=");
552 attr_type = tvb_get_unicode_string(wmem_packet_scope(), tvb, offset, type_len*2, ENC_BIG_ENDIAN);
553 proto_tree_add_string(tree, hf, tvb, offset, type_len*2, attr_type);
554 offset += (type_len*2)+2;
555 if (strcmp(attr_type, "svcname-ws")==0) {
556 /* This is the attribute svcname */
557 tmp = tvb_get_unicode_string(wmem_packet_scope(), tvb, offset, length-offset, ENC_BIG_ENDIAN);
558 type_len = (int)strcspn(tmp, ")");
559 add_v1_string(tree, hf_srvloc_srvrply_svcname, tvb, offset, type_len*2, encoding);
560 offset += (type_len*2)+4;
561 attr_type = "";
562 } else if (strcmp(attr_type, "svcaddr-ws")==0) {
563 /* This is the attribute svcaddr */
564 i=1;
565 for (foffset = offset; foffset<length; foffset += 2) {
567 ti = proto_tree_add_text(tree, tvb, foffset, -1, "Item %d", i);
568 srvloc_tree = proto_item_add_subtree(ti, ett_srvloc_attr);
570 svc = tvb_get_guint8(tvb, foffset+1);
571 proto_tree_add_text(srvloc_tree, tvb, foffset+1, 1,
572 "Service Type: %s", val_to_str_const(svc, srvloc_svc, "Unknown"));
573 ss = tvb_get_guint8(tvb, foffset+5);
574 proto_tree_add_text(srvloc_tree, tvb, foffset+5, 1,
575 "Communication Type: %s", val_to_str_const(ss, srvloc_ss, "Unknown"));
576 foffset += 9;
577 if (svc == 50) {
578 if (tvb_get_guint8(tvb, foffset)==54) { /* TCP */
579 prot = tvb_get_guint8(tvb, foffset);
580 proto_tree_add_text(srvloc_tree, tvb, foffset, 1,
581 "Protocol: %s", val_to_str_const(prot, srvloc_prot, "Unknown"));
582 foffset += 2;
584 else
586 byte_value = unicode_to_bytes(tvb, foffset, 4, FALSE); /* UDP */
587 prot = (guint32)strtoul(byte_value, NULL, 10);
588 proto_tree_add_text(srvloc_tree, tvb, foffset, 4,
589 "Protocol: %s", val_to_str_const(prot, srvloc_prot, "Unknown"));
590 foffset += 4;
593 else
595 byte_value = unicode_to_bytes(tvb, foffset, 8, FALSE); /* IPX */
596 prot = (guint32)strtoul(byte_value, NULL, 10);
597 proto_tree_add_text(srvloc_tree, tvb, foffset, 8,
598 "Protocol: %s", val_to_str_const(prot, srvloc_prot, "Unknown"));
599 foffset += 8;
601 if (svc == 50) {
602 byte_value = unicode_to_bytes(tvb, foffset, 16, TRUE); /* IP Address */
603 sscanf(byte_value,"%x",&prot);
604 proto_tree_add_ipv4(srvloc_tree, hf_srvloc_add_ref_ip, tvb, foffset+2, 16, prot);
605 byte_value = unicode_to_bytes(tvb, foffset+18, 8, FALSE); /* Port */
606 sscanf(byte_value,"%x",&prot);
607 proto_tree_add_text(srvloc_tree, tvb, foffset+18, 8, "Port: %d", prot);
609 else
611 byte_value = unicode_to_bytes(tvb, foffset+2, 16, FALSE); /* IPX Network Address */
612 sscanf(byte_value,"%x",&prot);
613 proto_tree_add_text(srvloc_tree, tvb, foffset+2, 16, "Network: %s", byte_value);
614 byte_value = unicode_to_bytes(tvb, foffset+18, 24, FALSE); /* IPX Node Address */
615 sscanf(byte_value,"%x",&prot);
616 proto_tree_add_text(srvloc_tree, tvb, foffset+18, 24, "Node: %s", byte_value);
617 byte_value = unicode_to_bytes(tvb, foffset+42, 8, FALSE); /* Socket */
618 sscanf(byte_value,"%x",&prot);
619 proto_tree_add_text(srvloc_tree, tvb, foffset+42, 8, "Socket: %s", byte_value);
621 i++;
622 foffset += 57;
624 offset = foffset;
625 attr_type = "";
627 /* If there are no more supported attributes available then abort dissection */
628 if (strcmp(attr_type, "svcaddr-ws")!=0 && strcmp(attr_type, "svcname-ws")!=0 && strcmp(attr_type, "")!=0) {
629 break;
632 break;
634 case CHARSET_UTF_8:
635 type_len = (int)strcspn(tvb_get_string(wmem_packet_scope(), tvb, offset, length), "=");
636 attr_type = unicode_to_bytes(tvb, offset+1, type_len-1, FALSE);
637 proto_tree_add_string(tree, hf, tvb, offset+1, type_len-1, attr_type);
638 i=1;
639 for (foffset = offset + (type_len); foffset<length; foffset++) {
641 ti = proto_tree_add_text(tree, tvb, foffset, -1, "Item %d", i);
642 srvloc_tree = proto_item_add_subtree(ti, ett_srvloc_attr);
644 svc = tvb_get_guint8(tvb, foffset+1);
645 proto_tree_add_text(srvloc_tree, tvb, foffset+1, 1,
646 "Service Type: %s", val_to_str_const(svc, srvloc_svc, "Unknown"));
647 ss = tvb_get_guint8(tvb, foffset+3);
648 proto_tree_add_text(srvloc_tree, tvb, foffset+3, 1,
649 "Communication Type: %s", val_to_str_const(ss, srvloc_ss, "Unknown"));
650 foffset += 5;
651 if (svc == 50) {
652 if (tvb_get_guint8(tvb, foffset)==54) { /* TCP */
653 prot = tvb_get_guint8(tvb, foffset);
654 proto_tree_add_text(srvloc_tree, tvb, foffset, 1,
655 "Protocol: %s", val_to_str_const(prot, srvloc_prot, "Unknown"));
656 foffset += 1;
658 else
660 /* UDP */
661 byte_value = unicode_to_bytes(tvb, foffset, 2, FALSE); /* UDP */
662 prot = (guint32)strtoul(byte_value, NULL, 10);
663 proto_tree_add_text(srvloc_tree, tvb, foffset, 2,
664 "Protocol: %s", val_to_str_const(prot, srvloc_prot, "Unknown"));
665 foffset += 2;
668 else
670 byte_value = unicode_to_bytes(tvb, foffset, 4, FALSE); /* IPX */
671 prot = (guint32)strtoul(byte_value, NULL, 10);
672 proto_tree_add_text(srvloc_tree, tvb, foffset, 4,
673 "Protocol: %s", val_to_str_const(prot, srvloc_prot, "Unknown"));
674 foffset += 4;
676 if (svc == 50) {
677 byte_value = unicode_to_bytes(tvb, foffset, 8, TRUE); /* IP Address */
678 sscanf(byte_value,"%x",&prot);
679 proto_tree_add_ipv4(srvloc_tree, hf_srvloc_add_ref_ip, tvb, foffset+1, 8, prot);
680 byte_value = unicode_to_bytes(tvb, foffset+9, 4, FALSE); /* Port */
681 sscanf(byte_value,"%x",&prot);
682 proto_tree_add_text(srvloc_tree, tvb, foffset+9, 4, "Port: %d", prot);
684 else
686 byte_value = unicode_to_bytes(tvb, foffset+1, 8, FALSE); /* IPX Network Address */
687 sscanf(byte_value,"%x",&prot);
688 proto_tree_add_text(srvloc_tree, tvb, foffset+1, 8, "Network: %s", byte_value);
689 byte_value = unicode_to_bytes(tvb, foffset+9, 12, FALSE); /* IPX Node Address */
690 sscanf(byte_value,"%x",&prot);
691 proto_tree_add_text(srvloc_tree, tvb, foffset+9, 12, "Node: %s", byte_value);
692 byte_value = unicode_to_bytes(tvb, foffset+21, 4, FALSE); /* Socket */
693 sscanf(byte_value,"%x",&prot);
694 proto_tree_add_text(srvloc_tree, tvb, foffset+21, 4, "Socket: %s", byte_value);
696 i++;
697 foffset += 28;
699 break;
702 default:
703 /* XXX - need to handle specific encodings */
704 proto_tree_add_item(tree, hf, tvb, offset, length, ENC_ASCII|ENC_NA);
705 break;
709 static void
710 attr_list2(proto_tree *tree, int hf, tvbuff_t *tvb, int offset, int length, guint16 encoding _U_)
712 guint8 *start;
713 guint8 c;
714 guint32 x;
715 guint32 cnt;
716 proto_item *ti;
717 proto_tree *attr_tree;
719 /* if we were to decode:
720 * For slp, these 9 characters: (),\!<=>~ and 0x00-1F, 0x7f are reserved and must be escaped in the form \HH
723 /* create a sub tree for attributes */
724 /* XXX - is this always ASCII, or what? */
725 ti = proto_tree_add_item(tree, hf, tvb, offset, length, ENC_ASCII|ENC_NA);
726 attr_tree = proto_item_add_subtree(ti, ett_srvloc_attr);
728 /* this will ensure there is a terminating null */
729 start = tvb_get_string(wmem_packet_scope(), tvb, offset, length);
731 cnt = 0;
732 x = 0;
733 c = start[x];
734 while (c) {
735 if (c == ',') {
736 cnt++; /* Attribute count */
737 start[x] = 0;
738 proto_tree_add_text(attr_tree, tvb, offset, x, "Item %d: %s", cnt, start);
739 offset += x+1;
740 start += x+1;
741 /* reset string length */
742 x = 0;
743 c = start[x];
744 } else {
745 /* increment and get next */
746 x++;
747 c = start[x];
750 /* display anything remaining */
751 if (x) {
752 cnt++;
753 proto_tree_add_text(attr_tree, tvb, offset, x, "Item %d: %s", cnt, start);
757 static int
758 dissect_url_entry_v1(tvbuff_t *tvb, int offset, proto_tree *tree,
759 guint16 encoding, guint16 flags)
761 guint16 url_len;
763 proto_tree_add_item(tree, hf_srvloc_url_lifetime, tvb, offset, 2,
764 ENC_BIG_ENDIAN);
765 offset += 2;
766 url_len = tvb_get_ntohs(tvb, offset);
767 proto_tree_add_uint(tree, hf_srvloc_url_urllen, tvb, offset, 2,
768 url_len);
769 offset += 2;
770 add_v1_string(tree, hf_srvloc_url_url, tvb, offset, url_len, encoding);
771 offset += url_len;
772 if ( (flags & FLAG_U) == FLAG_U )
773 offset = dissect_authblk(tvb, offset, tree);
774 return offset;
777 static int
778 dissect_url_entry_v2(tvbuff_t *tvb, int offset, proto_tree *tree)
780 guint8 reserved;
781 guint16 url_len;
782 guint8 num_auths;
784 reserved = tvb_get_guint8(tvb, offset);
785 proto_tree_add_uint(tree, hf_srvloc_url_reserved, tvb, offset, 1,
786 reserved);
787 offset += 1;
788 proto_tree_add_item(tree, hf_srvloc_url_lifetime, tvb, offset, 2,
789 ENC_BIG_ENDIAN);
790 offset += 2;
791 url_len = tvb_get_ntohs(tvb, offset);
792 proto_tree_add_uint(tree, hf_srvloc_url_urllen, tvb, offset, 2,
793 url_len);
794 offset += 2;
795 proto_tree_add_item(tree, hf_srvloc_url_url, tvb, offset, url_len, ENC_ASCII|ENC_NA);
796 offset += url_len;
797 num_auths = tvb_get_guint8(tvb, offset);
798 proto_tree_add_uint(tree, hf_srvloc_url_numauths, tvb, offset, 1,
799 num_auths);
800 offset += 1;
801 while (num_auths > 0) {
802 offset = dissect_authblk_v2(tvb, offset, tree);
803 num_auths--;
805 return offset;
808 /* Packet dissection routine called by tcp & udp when port 427 detected */
810 static int
811 dissect_srvloc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
813 int offset = 0;
814 proto_item *ti, *tf;
815 proto_tree *srvloc_tree, *srvloc_flags;
816 guint8 version;
817 guint8 function;
818 guint16 encoding;
819 guint32 length; /* three bytes needed for v2 */
820 guint16 flags; /* two byes needed for v2 */
821 guint32 count;
822 guint32 next_ext_off; /* three bytes, v2 only */
823 guint16 lang_tag_len;
824 nstime_t ts;
825 proto_item *expert_item;
826 guint16 expert_status;
828 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SRVLOC");
830 col_clear(pinfo->cinfo, COL_INFO);
832 version = tvb_get_guint8(tvb, offset);
833 function = tvb_get_guint8(tvb, offset + 1);
835 col_add_str(pinfo->cinfo, COL_INFO,
836 val_to_str(function, srvloc_functions, "Unknown Function (%u)"));
838 ti = proto_tree_add_item(tree, proto_srvloc, tvb, offset, -1, ENC_NA);
839 srvloc_tree = proto_item_add_subtree(ti, ett_srvloc);
841 proto_tree_add_uint(srvloc_tree, hf_srvloc_version, tvb, offset, 1,
842 version);
843 proto_tree_add_uint(srvloc_tree, hf_srvloc_function, tvb, offset + 1, 1,
844 function);
845 if (version < 2) {
846 length = tvb_get_ntohs(tvb, offset + 2);
847 proto_tree_add_uint(srvloc_tree, hf_srvloc_pktlen, tvb, offset + 2, 2,
848 length);
849 flags = tvb_get_guint8(tvb, offset + 4);
850 tf = proto_tree_add_uint(srvloc_tree, hf_srvloc_flags_v1, tvb, offset + 4, 1,
851 flags);
852 srvloc_flags = proto_item_add_subtree(tf, ett_srvloc_flags);
853 proto_tree_add_boolean(srvloc_flags, hf_srvloc_flags_v1_overflow,
854 tvb, offset+4, 1, flags);
855 proto_tree_add_boolean(srvloc_flags, hf_srvloc_flags_v1_monolingual,
856 tvb, offset+4, 1, flags);
857 proto_tree_add_boolean(srvloc_flags, hf_srvloc_flags_v1_url_auth,
858 tvb, offset+4, 1, flags);
859 proto_tree_add_boolean(srvloc_flags, hf_srvloc_flags_v1_attribute_auth,
860 tvb, offset+4, 1, flags);
861 proto_tree_add_boolean(srvloc_flags, hf_srvloc_flags_v1_fresh,
862 tvb, offset+4, 1, flags);
863 proto_tree_add_text(srvloc_tree, tvb, offset + 5, 1, "Dialect: %u",
864 tvb_get_guint8(tvb, offset + 5));
865 proto_tree_add_text(srvloc_tree, tvb, offset + 6, 2, "Language: %s",
866 tvb_format_text(tvb, offset + 6, 2));
867 encoding = tvb_get_ntohs(tvb, offset + 8);
868 proto_tree_add_text(srvloc_tree, tvb, offset + 8, 2, "Encoding: %u (%s)",
869 encoding,
870 val_to_str_const(encoding, charsets, "Unknown"));
871 proto_tree_add_text(srvloc_tree, tvb, offset + 10, 2, "Transaction ID: %u",
872 tvb_get_ntohs(tvb, offset + 10));
873 /* added echo of XID to info colomn by Greg Morris 0ct 14, 2005 */
874 col_append_fstr(pinfo->cinfo, COL_INFO, ", V1 Transaction ID - %u", tvb_get_ntohs(tvb, offset + 10));
876 offset += 12;
878 switch (function) {
880 case SRVREQ:
881 length = tvb_get_ntohs(tvb, offset);
882 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreq_prlistlen, tvb, offset, 2, length);
883 offset += 2;
884 add_v1_string(srvloc_tree, hf_srvloc_srvreq_prlist, tvb, offset, length, encoding);
885 offset += length;
886 length = tvb_get_ntohs(tvb, offset);
887 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreq_predicatelen, tvb, offset, 2, length);
888 offset += 2;
889 add_v1_string(srvloc_tree, hf_srvloc_srvreq_predicate, tvb, offset, length, encoding);
890 offset += length;
891 break;
893 case SRVRPLY:
894 expert_item = proto_tree_add_item(srvloc_tree, hf_srvloc_error, tvb, offset, 2, ENC_BIG_ENDIAN);
895 expert_status = tvb_get_ntohs(tvb, offset);
896 if (expert_status!=0) {
897 expert_add_info_format(pinfo, expert_item, &ei_srvloc_error, "Error: %s", val_to_str(expert_status, srvloc_errs, "Unknown SRVLOC Error (0x%02x)"));
899 offset += 2;
900 count = tvb_get_ntohs(tvb, offset);
901 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvrply_urlcount, tvb, offset, 2, count);
902 offset += 2;
903 while (count > 0) {
904 offset = dissect_url_entry_v1(tvb, offset, srvloc_tree,
905 encoding, flags);
906 count--;
908 break;
910 case SRVREG:
911 offset = dissect_url_entry_v1(tvb, offset, srvloc_tree, encoding,
912 flags);
913 length = tvb_get_ntohs(tvb, offset);
914 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreg_attrlistlen, tvb, offset, 2, length);
915 offset += 2;
916 add_v1_string(srvloc_tree, hf_srvloc_srvreg_attrlist, tvb, offset, length, encoding);
917 offset += length;
918 if ( (flags & FLAG_A) == FLAG_A )
919 offset = dissect_authblk(tvb, offset, srvloc_tree);
920 break;
922 case SRVDEREG:
923 length = tvb_get_ntohs(tvb, offset);
924 proto_tree_add_uint(tree, hf_srvloc_url_urllen, tvb, offset, 2, length);
925 offset += 2;
926 add_v1_string(tree, hf_srvloc_url_url, tvb, offset, length, encoding);
927 offset += length;
928 if ( (flags & FLAG_U) == FLAG_U )
929 offset = dissect_authblk(tvb, offset, srvloc_tree);
930 length = tvb_get_ntohs(tvb, offset);
931 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvdereg_taglistlen, tvb, offset, 2, length);
932 offset += 2;
933 add_v1_string(srvloc_tree, hf_srvloc_srvdereg_taglist, tvb, offset, length, encoding);
934 offset += length;
936 * XXX - this was there before, but RFC 2165 doesn't speak
937 * of there being an attribute authentication block in
938 * a Service Deregister message. Is that a post-RFC-2165
939 * addition?
941 if ( (flags & FLAG_A) == FLAG_A )
942 offset = dissect_authblk(tvb, offset, srvloc_tree);
943 break;
945 case SRVACK:
946 expert_item = proto_tree_add_item(srvloc_tree, hf_srvloc_error, tvb, offset, 2, ENC_BIG_ENDIAN);
947 expert_status = tvb_get_ntohs(tvb, offset);
948 if (expert_status!=0) {
949 expert_add_info_format(pinfo, expert_item, &ei_srvloc_error, "Error: %s", val_to_str(expert_status, srvloc_errs, "Unknown SRVLOC Error (0x%02x)"));
951 offset += 2;
952 break;
954 case ATTRRQST:
955 length = tvb_get_ntohs(tvb, offset);
956 proto_tree_add_uint(srvloc_tree, hf_srvloc_attrreq_prlistlen, tvb, offset, 2, length);
957 offset += 2;
958 add_v1_string(srvloc_tree, hf_srvloc_attrreq_prlist, tvb, offset, length, encoding);
959 offset += length;
960 length = tvb_get_ntohs(tvb, offset);
961 proto_tree_add_uint(srvloc_tree, hf_srvloc_attrreq_urllen, tvb, offset, 2, length);
962 offset += 2;
963 add_v1_string(srvloc_tree, hf_srvloc_attrreq_url, tvb, offset, length, encoding);
964 offset += length;
965 length = tvb_get_ntohs(tvb, offset);
966 proto_tree_add_uint(srvloc_tree, hf_srvloc_attrreq_scopelistlen, tvb, offset, 2, length);
967 offset += 2;
968 add_v1_string(srvloc_tree, hf_srvloc_attrreq_scopelist, tvb, offset, length, encoding);
969 offset += length;
970 length = tvb_get_ntohs(tvb, offset);
971 proto_tree_add_uint(srvloc_tree, hf_srvloc_attrreq_attrlistlen, tvb, offset, 2, length);
972 offset += 2;
973 add_v1_string(srvloc_tree, hf_srvloc_attrreq_attrlist, tvb, offset, length, encoding);
974 offset += length;
975 break;
977 case ATTRRPLY:
978 expert_item = proto_tree_add_item(srvloc_tree, hf_srvloc_error_v2, tvb, offset, 2, ENC_BIG_ENDIAN);
979 expert_status = tvb_get_ntohs(tvb, offset);
980 if (expert_status!=0) {
981 expert_add_info_format(pinfo, expert_item, &ei_srvloc_error, "Error: %s", val_to_str(expert_status, srvloc_errs_v2, "Unknown SRVLOC Error (0x%02x)"));
983 offset += 2;
984 length = tvb_get_ntohs(tvb, offset);
985 proto_tree_add_uint(srvloc_tree, hf_srvloc_attrrply_attrlistlen, tvb, offset, 2, length);
986 if (length > 0) {
987 offset += 2;
988 attr_list(srvloc_tree, hf_srvloc_attrrply_attrlist, tvb, offset, length, encoding);
989 offset += length;
990 if ( (flags & FLAG_A) == FLAG_A )
991 offset = dissect_authblk(tvb, offset, srvloc_tree);
993 break;
995 case DAADVERT:
996 expert_item = proto_tree_add_item(srvloc_tree, hf_srvloc_error, tvb, offset, 2, ENC_BIG_ENDIAN);
997 expert_status = tvb_get_ntohs(tvb, offset);
998 if (expert_status!=0) {
999 expert_add_info_format(pinfo, expert_item, &ei_srvloc_error, "Error: %s", val_to_str(expert_status, srvloc_errs, "Unknown SRVLOC Error (0x%02x)"));
1001 offset += 2;
1002 length = tvb_get_ntohs(tvb, offset);
1003 proto_tree_add_uint(srvloc_tree, hf_srvloc_daadvert_urllen, tvb, offset, 2, length);
1004 offset += 2;
1005 add_v1_string(srvloc_tree, hf_srvloc_daadvert_url, tvb, offset, length, encoding);
1006 offset += length;
1007 length = tvb_get_ntohs(tvb, offset);
1008 proto_tree_add_uint(srvloc_tree, hf_srvloc_daadvert_scopelistlen, tvb, offset, 2, length);
1009 offset += 2;
1010 add_v1_string(srvloc_tree, hf_srvloc_daadvert_scopelist, tvb, offset, length, encoding);
1011 offset += length;
1012 break;
1014 case SRVTYPERQST:
1015 length = tvb_get_ntohs(tvb, offset);
1016 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtypereq_prlistlen, tvb, offset, 2, length);
1017 offset += 2;
1018 add_v1_string(srvloc_tree, hf_srvloc_srvtypereq_prlist, tvb, offset, length, encoding);
1019 offset += length;
1020 length = tvb_get_ntohs(tvb, offset);
1021 /* Updated by Greg Morris on 1-30-04 */
1022 if (0xFFFF == length) {
1023 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtypereq_nameauthlistlenall, tvb, offset, 2, length);
1024 offset += 2;
1026 else
1028 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtypereq_nameauthlistlen, tvb, offset, 2, length);
1029 offset += 2;
1030 add_v1_string(srvloc_tree, hf_srvloc_srvtypereq_nameauthlist, tvb, offset, length, encoding);
1031 offset += length;
1033 length = tvb_get_ntohs(tvb, offset);
1034 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtypereq_scopelistlen, tvb, offset, 2, length);
1035 offset += 2;
1036 add_v1_string(srvloc_tree, hf_srvloc_srvtypereq_scopelist, tvb, offset, length, encoding);
1037 offset += length;
1038 break;
1040 case SRVTYPERPLY:
1041 expert_item = proto_tree_add_item(srvloc_tree, hf_srvloc_error, tvb, offset, 2, ENC_BIG_ENDIAN);
1042 expert_status = tvb_get_ntohs(tvb, offset);
1043 if (expert_status!=0) {
1044 expert_add_info_format(pinfo, expert_item, &ei_srvloc_error, "Error: %s", val_to_str(expert_status, srvloc_errs, "Unknown SRVLOC Error (0x%02x)"));
1046 offset += 2;
1047 count = tvb_get_ntohs(tvb, offset);
1048 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Service Type Count: %u",
1049 count);
1050 offset += 2;
1051 while (count > 0) {
1052 length = tvb_get_ntohs(tvb, offset);
1053 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtyperply_srvtypelen, tvb, offset, 2, length);
1054 offset += 2;
1055 add_v1_string(srvloc_tree, hf_srvloc_srvtyperply_srvtype, tvb, offset, length, encoding);
1056 offset += length;
1057 count--;
1059 break;
1061 default:
1062 proto_tree_add_expert_format(srvloc_tree, pinfo, &ei_srvloc_function_unknown,
1063 tvb, offset, -1, "Unknown Function Type: %d", function);
1066 else { /* Version 2 */
1067 length = tvb_get_ntoh24(tvb, offset + 2);
1068 proto_tree_add_uint(srvloc_tree, hf_srvloc_pktlen, tvb, offset + 2, 3,
1069 length);
1070 flags = tvb_get_ntohs(tvb, offset + 5);
1071 tf = proto_tree_add_uint(srvloc_tree, hf_srvloc_flags_v2, tvb, offset + 5, 2,
1072 flags);
1073 srvloc_flags = proto_item_add_subtree(tf, ett_srvloc_flags);
1074 proto_tree_add_boolean(srvloc_flags, hf_srvloc_flags_v2_overflow,
1075 tvb, offset+5, 1, flags);
1076 proto_tree_add_boolean(srvloc_flags, hf_srvloc_flags_v2_fresh,
1077 tvb, offset+5, 1, flags);
1078 proto_tree_add_boolean(srvloc_flags, hf_srvloc_flags_v2_reqmulti,
1079 tvb, offset+5, 1, flags);
1081 next_ext_off = tvb_get_ntoh24(tvb, offset + 7);
1082 proto_tree_add_uint(srvloc_tree, hf_srvloc_nextextoff, tvb, offset + 7, 3,
1083 next_ext_off);
1084 proto_tree_add_uint(srvloc_tree, hf_srvloc_xid, tvb, offset + 10, 2,
1085 tvb_get_ntohs(tvb, offset + 10));
1086 col_append_fstr(pinfo->cinfo, COL_INFO, ", V2 XID - %u", tvb_get_ntohs(tvb, offset + 10));
1087 lang_tag_len = tvb_get_ntohs(tvb, offset + 12);
1088 proto_tree_add_uint(srvloc_tree, hf_srvloc_langtaglen, tvb, offset + 12, 2, lang_tag_len);
1089 proto_tree_add_item(srvloc_tree, hf_srvloc_langtag, tvb, offset + 14, lang_tag_len, ENC_ASCII|ENC_NA);
1090 offset += 14+lang_tag_len;
1092 switch (function) {
1094 case SRVREQ: /* RFC2608 8.1 */
1095 length = tvb_get_ntohs(tvb, offset);
1096 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreq_prlistlen, tvb, offset, 2, length);
1097 offset += 2;
1098 if (length) {
1099 proto_tree_add_item(srvloc_tree, hf_srvloc_srvreq_prlist, tvb, offset, length, ENC_ASCII|ENC_NA);
1100 offset += length;
1102 length = tvb_get_ntohs(tvb, offset);
1103 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreq_srvtypelen, tvb, offset, 2, length);
1104 offset += 2;
1105 if (length) {
1106 proto_tree_add_item(srvloc_tree, hf_srvloc_srvreq_srvtypelist, tvb, offset, length, ENC_ASCII|ENC_NA);
1107 offset += length;
1109 length = tvb_get_ntohs(tvb, offset);
1110 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreq_scopelistlen, tvb, offset, 2, length);
1111 offset += 2;
1112 if (length) {
1113 proto_tree_add_item(srvloc_tree, hf_srvloc_srvreq_scopelist, tvb, offset, length, ENC_ASCII|ENC_NA);
1114 offset += length;
1116 length = tvb_get_ntohs(tvb, offset);
1117 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreq_predicatelen, tvb, offset, 2, length);
1118 offset += 2;
1119 if (length) {
1120 proto_tree_add_item(srvloc_tree, hf_srvloc_srvreq_predicate, tvb, offset, length, ENC_ASCII|ENC_NA);
1121 offset += length;
1123 length = tvb_get_ntohs(tvb, offset);
1124 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreq_slpspilen, tvb, offset, 2, length);
1125 offset += 2;
1126 if (length) {
1127 proto_tree_add_item(srvloc_tree, hf_srvloc_srvreq_slpspi, tvb, offset, length, ENC_ASCII|ENC_NA);
1128 offset += length;
1130 break;
1132 case SRVRPLY: /* RFC2608 8.2 */
1133 expert_item = proto_tree_add_item(srvloc_tree, hf_srvloc_error_v2, tvb, offset, 2, ENC_BIG_ENDIAN);
1134 expert_status = tvb_get_ntohs(tvb, offset);
1135 if (expert_status!=0) {
1136 expert_add_info_format(pinfo, expert_item, &ei_srvloc_error_v2, "Error: %s", val_to_str(expert_status, srvloc_errs_v2, "Unknown SRVLOC Error (0x%02x)"));
1138 offset += 2;
1139 count = tvb_get_ntohs(tvb, offset);
1140 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvrply_urlcount, tvb, offset, 2, count);
1141 offset += 2;
1142 while (count > 0) {
1143 offset = dissect_url_entry_v2(tvb, offset, srvloc_tree);
1144 count--;
1146 break;
1148 case SRVREG: /* RFC2608 8.3 */
1149 offset = dissect_url_entry_v2(tvb, offset, srvloc_tree);
1150 length = tvb_get_ntohs(tvb, offset);
1151 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreg_srvtypelen, tvb, offset, 2, length);
1152 offset += 2;
1153 if (length) {
1154 proto_tree_add_item(srvloc_tree, hf_srvloc_srvreg_srvtype, tvb, offset, length, ENC_ASCII|ENC_NA);
1155 offset += length;
1157 length = tvb_get_ntohs(tvb, offset);
1158 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreg_scopelistlen, tvb, offset, 2, length);
1159 offset += 2;
1160 if (length) {
1161 proto_tree_add_item(srvloc_tree, hf_srvloc_srvreg_scopelist, tvb, offset, length, ENC_ASCII|ENC_NA);
1162 offset += length;
1164 length = tvb_get_ntohs(tvb, offset);
1165 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreg_attrlistlen, tvb, offset, 2, length);
1166 offset += 2;
1167 if (length) {
1168 attr_list2(srvloc_tree, hf_srvloc_srvreg_attrlist, tvb, offset, length, CHARSET_UTF_8);
1169 offset += length;
1171 count = tvb_get_guint8(tvb, offset);
1172 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreg_attrauthcount, tvb, offset, 1, count);
1173 offset += 1;
1174 while (count > 0) {
1175 offset = dissect_attrauthblk_v2(tvb, offset, srvloc_tree);
1176 count--;
1178 break;
1180 case SRVDEREG: /* RFC2608 10.6 */
1181 length = tvb_get_ntohs(tvb, offset);
1182 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvdereg_scopelistlen, tvb, offset, 2, length);
1183 offset += 2;
1184 if (length) {
1185 proto_tree_add_item(srvloc_tree, hf_srvloc_srvdereg_scopelist, tvb, offset, length, ENC_ASCII|ENC_NA);
1186 offset += length;
1188 offset = dissect_url_entry_v2(tvb, offset, srvloc_tree);
1189 length = tvb_get_ntohs(tvb, offset);
1190 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvdereg_taglistlen, tvb, offset, 2, length);
1191 offset += 2;
1192 if (length) {
1193 proto_tree_add_item(srvloc_tree, hf_srvloc_srvdereg_taglist, tvb, offset, length, ENC_ASCII|ENC_NA);
1194 offset += length;
1196 break;
1198 case SRVACK: /* RFC2608 8.4 */
1199 expert_item = proto_tree_add_item(srvloc_tree, hf_srvloc_error_v2, tvb, offset, 2, ENC_BIG_ENDIAN);
1200 expert_status = tvb_get_ntohs(tvb, offset);
1201 if (expert_status!=0) {
1202 expert_add_info_format(pinfo, expert_item, &ei_srvloc_error_v2, "Error: %s", val_to_str(expert_status, srvloc_errs_v2, "Unknown SRVLOC Error (0x%02x)"));
1204 offset += 2;
1205 break;
1207 case ATTRRQST: /* RFC2608 10.3*/
1208 length = tvb_get_ntohs(tvb, offset);
1209 proto_tree_add_uint(srvloc_tree, hf_srvloc_attrreq_prlistlen, tvb, offset, 2, length);
1210 offset += 2;
1211 if (length) {
1212 proto_tree_add_item(srvloc_tree, hf_srvloc_attrreq_prlist, tvb, offset, length, ENC_ASCII|ENC_NA);
1213 offset += length;
1215 length = tvb_get_ntohs(tvb, offset);
1216 proto_tree_add_uint(srvloc_tree, hf_srvloc_attrreq_urllen, tvb, offset, 2, length);
1217 offset += 2;
1218 if (length) {
1219 proto_tree_add_item(srvloc_tree, hf_srvloc_attrreq_url, tvb, offset, length, ENC_ASCII|ENC_NA);
1220 offset += length;
1222 length = tvb_get_ntohs(tvb, offset);
1223 proto_tree_add_uint(srvloc_tree, hf_srvloc_attrreq_scopelistlen, tvb, offset, 2, length);
1224 offset += 2;
1225 if (length) {
1226 proto_tree_add_item(srvloc_tree, hf_srvloc_attrreq_scopelist, tvb, offset, length, ENC_ASCII|ENC_NA);
1227 offset += length;
1229 length = tvb_get_ntohs(tvb, offset);
1230 proto_tree_add_uint(srvloc_tree, hf_srvloc_attrreq_taglistlen, tvb, offset, 2, length);
1231 offset += 2;
1232 if (length) {
1233 proto_tree_add_item(srvloc_tree, hf_srvloc_attrreq_taglist, tvb, offset, length, ENC_ASCII|ENC_NA);
1234 offset += length;
1236 length = tvb_get_ntohs(tvb, offset);
1237 proto_tree_add_uint(srvloc_tree, hf_srvloc_attrreq_slpspilen, tvb, offset, 2, length);
1238 offset += 2;
1239 if (length) {
1240 proto_tree_add_item(srvloc_tree, hf_srvloc_attrreq_slpspi, tvb, offset, length, ENC_ASCII|ENC_NA);
1241 offset += length;
1243 break;
1245 case ATTRRPLY: /* RFC2608 10.4 */
1246 expert_item = proto_tree_add_item(srvloc_tree, hf_srvloc_error_v2, tvb, offset, 2, ENC_BIG_ENDIAN);
1247 expert_status = tvb_get_ntohs(tvb, offset);
1248 if (expert_status!=0) {
1249 expert_add_info_format(pinfo, expert_item, &ei_srvloc_error_v2, "Error: %s", val_to_str(expert_status, srvloc_errs_v2, "Unknown SRVLOC Error (0x%02x)"));
1251 offset += 2;
1252 length = tvb_get_ntohs(tvb, offset);
1253 proto_tree_add_uint(srvloc_tree, hf_srvloc_attrrply_attrlistlen, tvb, offset, 2, length);
1254 offset += 2;
1255 if (length) {
1256 attr_list2(srvloc_tree, hf_srvloc_attrrply_attrlist, tvb, offset, length, CHARSET_UTF_8);
1257 offset += length;
1259 count = tvb_get_guint8(tvb, offset);
1260 proto_tree_add_uint(srvloc_tree, hf_srvloc_attrrply_attrauthcount, tvb, offset, 1, count);
1261 offset += 1;
1262 while (count > 0) {
1263 offset = dissect_attrauthblk_v2(tvb, offset, srvloc_tree);
1264 count--;
1266 break;
1268 case DAADVERT: /* RCC 2608 8.5 */
1269 expert_item = proto_tree_add_item(srvloc_tree, hf_srvloc_error_v2, tvb, offset, 2, ENC_BIG_ENDIAN);
1270 expert_status = tvb_get_ntohs(tvb, offset);
1271 if (expert_status!=0) {
1272 expert_add_info_format(pinfo, expert_item, &ei_srvloc_error_v2, "Error: %s", val_to_str(expert_status, srvloc_errs_v2, "Unknown SRVLOC Error (0x%02x)"));
1274 offset += 2;
1275 ts.nsecs = 0;
1276 ts.secs = tvb_get_ntohl(tvb, offset);
1277 proto_tree_add_time(srvloc_tree, hf_srvloc_daadvert_timestamp, tvb, offset, 4,
1278 &ts);
1279 offset += 4;
1280 length = tvb_get_ntohs(tvb, offset);
1281 proto_tree_add_uint(srvloc_tree, hf_srvloc_daadvert_urllen, tvb, offset, 2, length);
1282 offset += 2;
1283 if (length) {
1284 proto_tree_add_item(srvloc_tree, hf_srvloc_daadvert_url, tvb, offset, length, ENC_ASCII|ENC_NA);
1285 offset += length;
1287 length = tvb_get_ntohs(tvb, offset);
1288 proto_tree_add_uint(srvloc_tree, hf_srvloc_daadvert_scopelistlen, tvb, offset, 2, length);
1289 offset += 2;
1290 if (length) {
1291 proto_tree_add_item(srvloc_tree, hf_srvloc_daadvert_scopelist, tvb, offset, length, ENC_ASCII|ENC_NA);
1292 offset += length;
1294 length = tvb_get_ntohs(tvb, offset);
1295 proto_tree_add_uint(srvloc_tree, hf_srvloc_daadvert_attrlistlen, tvb, offset, 2, length);
1296 offset += 2;
1297 if (length) {
1298 proto_tree_add_item(srvloc_tree, hf_srvloc_daadvert_attrlist, tvb, offset, length, ENC_ASCII|ENC_NA);
1299 offset += length;
1301 length = tvb_get_ntohs(tvb, offset);
1302 proto_tree_add_uint(srvloc_tree, hf_srvloc_daadvert_slpspilen, tvb, offset, 2, length);
1303 offset += 2;
1304 if (length) {
1305 proto_tree_add_item(srvloc_tree, hf_srvloc_daadvert_slpspi, tvb, offset, length, ENC_ASCII|ENC_NA);
1306 offset += length;
1308 count = tvb_get_guint8(tvb, offset);
1309 proto_tree_add_uint(srvloc_tree, hf_srvloc_daadvert_authcount, tvb, offset, 1, count);
1310 offset += 1;
1311 while (count > 0) {
1312 offset = dissect_authblk_v2(tvb, offset, srvloc_tree);
1313 count--;
1315 break;
1317 case SRVTYPERQST: /* RFC2608 10.1 */
1318 length = tvb_get_ntohs(tvb, offset);
1319 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtypereq_prlistlen, tvb, offset, 2, length);
1320 offset += 2;
1321 if (length) {
1322 proto_tree_add_item(srvloc_tree, hf_srvloc_srvtypereq_prlist, tvb, offset, length, ENC_ASCII|ENC_NA);
1323 offset += length;
1325 length = tvb_get_ntohs(tvb, offset);
1326 if (0xFFFF == length) {
1327 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtypereq_nameauthlistlenall, tvb, offset, 2, length);
1328 offset += 2;
1329 } else {
1330 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtypereq_nameauthlistlen, tvb, offset, 2, length);
1331 offset += 2;
1332 if (length) {
1333 proto_tree_add_item(srvloc_tree, hf_srvloc_srvtypereq_nameauthlist, tvb, offset, length, ENC_ASCII|ENC_NA);
1334 offset += length;
1337 length = tvb_get_ntohs(tvb, offset);
1338 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtypereq_scopelistlen, tvb, offset, 2, length);
1339 offset += 2;
1340 if (length) {
1341 proto_tree_add_item(srvloc_tree, hf_srvloc_srvtypereq_scopelist, tvb, offset, length, ENC_ASCII|ENC_NA);
1342 offset += length;
1344 break;
1346 case SRVTYPERPLY: /* rfc2608 10.2 */
1347 expert_item = proto_tree_add_item(srvloc_tree, hf_srvloc_error_v2, tvb, offset, 2, ENC_BIG_ENDIAN);
1348 expert_status = tvb_get_ntohs(tvb, offset);
1349 if (expert_status!=0) {
1350 expert_add_info_format(pinfo, expert_item, &ei_srvloc_error_v2, "Error: %s", val_to_str(expert_status, srvloc_errs_v2, "Unknown SRVLOC Error (0x%02x)"));
1352 offset += 2;
1353 length = tvb_get_ntohs(tvb, offset);
1354 proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtyperply_srvtypelistlen, tvb, offset, 2, length);
1355 offset += 2;
1356 if (length) {
1357 proto_tree_add_item(srvloc_tree, hf_srvloc_srvtyperply_srvtypelist, tvb, offset, length, ENC_ASCII|ENC_NA);
1358 offset += length;
1360 break;
1362 case SAADVERT: /* rfc2608 10.2 */
1363 length = tvb_get_ntohs(tvb, offset);
1364 proto_tree_add_uint(srvloc_tree, hf_srvloc_saadvert_urllen, tvb, offset, 2, length);
1365 offset += 2;
1366 if (length) {
1367 proto_tree_add_item(srvloc_tree, hf_srvloc_saadvert_url, tvb, offset, length, ENC_ASCII|ENC_NA);
1368 offset += length;
1370 length = tvb_get_ntohs(tvb, offset);
1371 proto_tree_add_uint(srvloc_tree, hf_srvloc_saadvert_scopelistlen, tvb, offset, 2, length);
1372 offset += 2;
1373 if (length) {
1374 proto_tree_add_item(srvloc_tree, hf_srvloc_saadvert_scopelist, tvb, offset, length, ENC_ASCII|ENC_NA);
1375 offset += length;
1377 length = tvb_get_ntohs(tvb, offset);
1378 proto_tree_add_uint(srvloc_tree, hf_srvloc_saadvert_attrlistlen, tvb, offset, 2, length);
1379 offset += 2;
1380 if (length) {
1381 proto_tree_add_item(srvloc_tree, hf_srvloc_saadvert_attrlist, tvb, offset, length, ENC_ASCII|ENC_NA);
1382 offset += length;
1384 count = tvb_get_guint8(tvb, offset);
1385 proto_tree_add_uint(srvloc_tree, hf_srvloc_saadvert_authcount, tvb, offset, 1, length);
1386 offset += 1;
1387 while (count > 0) {
1388 offset = dissect_authblk_v2(tvb, offset, srvloc_tree);
1389 count--;
1391 break;
1393 default:
1394 proto_tree_add_expert_format(srvloc_tree, pinfo, &ei_srvloc_function_unknown,
1395 tvb, offset, -1, "Unknown Function Type: %d", function);
1398 return offset;
1401 static guint
1402 get_srvloc_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
1405 * Get the length of the SRVLOC packet.
1406 * It starts at offset+2, but it's 2 bytes in SLPv1 and 3 bytes
1407 * in SLPv2.
1409 if (tvb_get_guint8(tvb, offset) == 2)
1410 return tvb_get_ntoh24(tvb, offset + 2);
1411 else
1412 return tvb_get_ntohs(tvb, offset + 2);
1415 static int
1416 dissect_srvloc_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1418 proto_tree *srvloc_tree = NULL;
1419 proto_item *ti;
1421 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SRVLOC");
1423 col_clear(pinfo->cinfo, COL_INFO);
1425 if (tree) {
1426 ti = proto_tree_add_item(tree, proto_srvloc, tvb, 0, -1, ENC_NA);
1427 srvloc_tree = proto_item_add_subtree(ti, ett_srvloc);
1429 dissect_srvloc(tvb, pinfo, srvloc_tree, NULL);
1430 return tvb_length(tvb);
1433 static int
1434 dissect_srvloc_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
1437 * XXX - in SLPv1, the fixed length need only be 4, as the length
1438 * is 2 bytes long; however, it must be 5 for SLPv2, as the length
1439 * is 3 bytes long, and there's probably no harm in asking for 5
1440 * bytes, as even SLPv1 packets start with a 12-byte header,
1441 * and if the packet has a length that's 4 or less, it's bogus,
1442 * and we can't handle a length < 4 anyway.
1444 tcp_dissect_pdus(tvb, pinfo, tree, srvloc_desegment, 5, get_srvloc_pdu_len,
1445 dissect_srvloc_pdu, data);
1446 return tvb_length(tvb);
1449 /* Register protocol with Wireshark. */
1451 void
1452 proto_register_srvloc(void)
1454 static hf_register_info hf[] = {
1455 /* Helper functions for the Version 1 Header*/
1456 {&hf_srvloc_error,
1457 {"Error Code", "srvloc.err",
1458 FT_UINT16, BASE_DEC, VALS(srvloc_errs), 0x0,
1459 NULL, HFILL }
1462 /* Helper function for the Version 2 Header */
1463 {&hf_srvloc_error_v2,
1464 {"Error Code", "srvloc.errv2",
1465 FT_UINT16, BASE_DEC, VALS(srvloc_errs_v2), 0x0,
1466 NULL, HFILL }
1468 {&hf_srvloc_xid,
1469 {"XID", "srvloc.xid",
1470 FT_UINT24, BASE_DEC, NULL, 0x0,
1471 "Transaction ID", HFILL }
1473 {&hf_srvloc_langtag,
1474 {"Lang Tag", "srvloc.langtag",
1475 FT_STRING, BASE_NONE, NULL, 0x0,
1476 NULL, HFILL }
1478 {&hf_srvloc_langtaglen,
1479 {"Lang Tag Len", "srvloc.langtaglen",
1480 FT_UINT16, BASE_DEC, NULL, 0x0,
1481 NULL, HFILL }
1483 {&hf_srvloc_nextextoff,
1484 {"Next Extension Offset", "srvloc.nextextoff",
1485 FT_UINT24, BASE_DEC, NULL, 0x0,
1486 NULL, HFILL }
1489 /* Helper functions for URL and URL Entry parsing - both versions */
1490 {&hf_srvloc_url_reserved,
1491 {"Reserved", "srvloc.url.reserved",
1492 FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }
1494 {&hf_srvloc_url_lifetime,
1495 {"URL lifetime", "srvloc.url.lifetime",
1496 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
1498 {&hf_srvloc_url_urllen,
1499 {"URL Length", "srvloc.url.urllen",
1500 FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
1502 {&hf_srvloc_url_url,
1503 {"URL", "srvloc.url.url",
1504 FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }
1506 {&hf_srvloc_url_numauths,
1507 {"Num Auths", "srvloc.url.numauths",
1508 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }
1511 /* Helper functions for the common header fields */
1512 {&hf_srvloc_function,
1513 {"Function", "srvloc.function",
1514 FT_UINT8, BASE_DEC, VALS(srvloc_functions), 0x0,
1515 NULL, HFILL }
1518 {&hf_srvloc_pktlen,
1519 {"Packet Length", "srvloc.pktlen",
1520 FT_UINT24, BASE_DEC, NULL, 0x0,
1521 NULL, HFILL }
1524 { &hf_srvloc_version,
1525 { "Version", "srvloc.version",
1526 FT_UINT8, BASE_DEC, NULL, 0x0,
1527 NULL, HFILL }
1530 {&hf_srvloc_flags_v1,
1531 {"Flags", "srvloc.flags_v1",
1532 FT_UINT8, BASE_HEX, NULL, 0x0,
1533 NULL, HFILL }
1536 { &hf_srvloc_flags_v1_overflow,
1537 { "Overflow", "srvloc.flags_v1.overflow.", FT_BOOLEAN, 8,
1538 TFS(&tfs_srvloc_flags_overflow), FLAG_O, "Can whole packet fit into a datagram?", HFILL }},
1540 { &hf_srvloc_flags_v1_monolingual,
1541 { "Monolingual", "srvloc.flags_v1.monolingual", FT_BOOLEAN, 8,
1542 TFS(&tfs_srvloc_flags_v1_monolingual), FLAG_M, "Can whole packet fit into a datagram?", HFILL }},
1544 { &hf_srvloc_flags_v1_url_auth,
1545 { "URL Authentication", "srvloc.flags_v1.url_auth", FT_BOOLEAN, 8,
1546 TFS(&tfs_srvloc_flags_v1_url_auth), FLAG_U, "Can whole packet fit into a datagram?", HFILL }},
1548 { &hf_srvloc_flags_v1_attribute_auth,
1549 { "Attribute Authentication", "srvloc.flags_v1.attribute_auth", FT_BOOLEAN, 8,
1550 TFS(&tfs_srvloc_flags_v1_attribute_auth), FLAG_A, "Can whole packet fit into a datagram?", HFILL }},
1552 { &hf_srvloc_flags_v1_fresh,
1553 { "Fresh Registration", "srvloc.flags_v1.fresh", FT_BOOLEAN, 8,
1554 TFS(&tfs_srvloc_flags_fresh), FLAG_F, "Is this a new registration?", HFILL }},
1556 {&hf_srvloc_flags_v2,
1557 {"Flags", "srvloc.flags_v2",
1558 FT_UINT16, BASE_HEX, NULL, 0x0,
1559 NULL, HFILL }
1562 { &hf_srvloc_flags_v2_overflow,
1563 { "Overflow", "srvloc.flags_v2.overflow", FT_BOOLEAN, 16,
1564 TFS(&tfs_srvloc_flags_overflow), FLAG_O_V2, "Can whole packet fit into a datagram?", HFILL }},
1566 { &hf_srvloc_flags_v2_fresh,
1567 { "Fresh Registration", "srvloc.flags_v2.fresh", FT_BOOLEAN, 16,
1568 TFS(&tfs_srvloc_flags_fresh), FLAG_F_V2, "Is this a new registration?", HFILL }},
1570 { &hf_srvloc_flags_v2_reqmulti,
1571 { "Multicast requested", "srvloc.flags_v2.reqmulti", FT_BOOLEAN, 16,
1572 TFS(&tfs_srvloc_flags_v2_reqmulti), FLAG_R_V2, "Do we want multicast?", HFILL }},
1574 /* collection of helper functions for dissect_authblk_v2 */
1575 { &hf_srvloc_authblkv2_bsd,
1576 { "BSD", "srvloc.authblkv2_bsd", FT_UINT16, BASE_HEX, NULL, 0x0,
1577 "Block Structure Descriptor", HFILL}
1579 { &hf_srvloc_authblkv2_len,
1580 { "Length", "srvloc.authblkv2_len", FT_UINT16, BASE_DEC, NULL, 0x0,
1581 "Length of Authentication Block", HFILL}
1583 { &hf_srvloc_authblkv2_timestamp,
1584 { "Timestamp", "srvloc.authblkv2.timestamp", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL,
1585 NULL, 0, "Timestamp on Authentication Block", HFILL }
1587 { &hf_srvloc_authblkv2_slpspilen,
1588 { "SLP SPI Length", "srvloc.authblkv2.slpspilen", FT_UINT16, BASE_DEC, NULL, 0x0,
1589 "Length of the SLP SPI", HFILL}
1591 { &hf_srvloc_authblkv2_slpspi,
1592 { "SLP SPI", "srvloc.authblkv2.slpspi", FT_STRING, BASE_NONE, NULL, 0x0,
1593 NULL, HFILL}
1596 /* collection of helper functions for Service Request */
1597 { &hf_srvloc_srvreq_prlistlen,
1598 { "Previous Response List Length", "srvloc.srvreq.prlistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1599 "Length of Previous Response List", HFILL}
1601 { &hf_srvloc_srvreq_prlist,
1602 { "Previous Response List", "srvloc.srvreq.prlist", FT_STRING, BASE_NONE, NULL, 0x0,
1603 NULL, HFILL}
1605 { &hf_srvloc_srvreq_srvtypelen,
1606 { "Service Type Length", "srvloc.srvreq.srvtypelen", FT_UINT16, BASE_DEC, NULL, 0x0,
1607 "Length of Service Type List", HFILL}
1609 { &hf_srvloc_srvreq_srvtypelist,
1610 { "Service Type List", "srvloc.srvreq.srvtypelist", FT_STRING, BASE_NONE, NULL, 0x0,
1611 NULL, HFILL}
1613 { &hf_srvloc_srvreq_scopelistlen,
1614 { "Scope List Length", "srvloc.srvreq.scopelistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1615 "Length of the Scope List", HFILL}
1617 { &hf_srvloc_srvreq_scopelist,
1618 { "Scope List", "srvloc.srvreq.scopelist", FT_STRING, BASE_NONE, NULL, 0x0,
1619 NULL, HFILL}
1621 { &hf_srvloc_srvreq_predicatelen,
1622 { "Predicate Length", "srvloc.srvreq.predicatelen", FT_UINT16, BASE_DEC, NULL, 0x0,
1623 "Length of the Predicate", HFILL}
1625 { &hf_srvloc_srvreq_predicate,
1626 { "Predicate", "srvloc.srvreq.predicate", FT_STRING, BASE_NONE, NULL, 0x0,
1627 NULL, HFILL}
1629 { &hf_srvloc_srvreq_slpspilen,
1630 { "SLP SPI Length", "srvloc.srvreq.slpspilen", FT_UINT16, BASE_DEC, NULL, 0x0,
1631 "Length of the SLP SPI", HFILL}
1633 { &hf_srvloc_srvreq_slpspi,
1634 { "SLP SPI", "srvloc.srvreq.slpspi", FT_STRING, BASE_NONE, NULL, 0x0,
1635 NULL, HFILL}
1638 /* Helper function for Service Request */
1639 { &hf_srvloc_srvrply_urlcount,
1640 { "Number of URLs", "srvloc.srvreq.urlcount", FT_UINT16, BASE_DEC, NULL, 0x0,
1641 NULL, HFILL}
1644 /* Helper functions for Service Registration */
1645 { &hf_srvloc_srvreg_srvtypelen,
1646 { "Service Type Length", "srvloc.srvreq.srvtypelen", FT_UINT16, BASE_DEC, NULL, 0x0,
1647 NULL, HFILL}
1649 { &hf_srvloc_srvreg_srvtype,
1650 { "Service Type", "srvloc.srvreq.srvtype", FT_STRING, BASE_NONE, NULL, 0x0,
1651 NULL, HFILL}
1653 { &hf_srvloc_srvreg_scopelistlen,
1654 { "Scope List Length", "srvloc.srvreq.scopelistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1655 NULL, HFILL}
1657 { &hf_srvloc_srvreg_scopelist,
1658 { "Scope List", "srvloc.srvreq.scopelist", FT_STRING, BASE_NONE, NULL, 0x0,
1659 NULL, HFILL}
1661 { &hf_srvloc_srvreg_attrlistlen,
1662 { "Attribute List Length", "srvloc.srvreq.attrlistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1663 NULL, HFILL}
1665 { &hf_srvloc_srvreg_attrlist,
1666 { "Attribute List", "srvloc.srvreq.attrlist", FT_STRING, BASE_NONE, NULL, 0x0,
1667 NULL, HFILL}
1669 { &hf_srvloc_srvreg_attrauthcount,
1670 { "Attr Auths", "srvloc.srvreq.attrauthcount", FT_UINT8, BASE_DEC, NULL, 0x0,
1671 "Number of Attribute Authentication Blocks", HFILL}
1674 /* Helper functions for Service Deregistration */
1675 { &hf_srvloc_srvdereg_scopelistlen,
1676 { "Scope List Length", "srvloc.srvdereq.scopelistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1677 NULL, HFILL}
1679 { &hf_srvloc_srvdereg_scopelist,
1680 { "Scope List", "srvloc.srvdereq.scopelist", FT_STRING, BASE_NONE, NULL, 0x0,
1681 NULL, HFILL}
1683 { &hf_srvloc_srvdereg_taglistlen,
1684 { "Tag List Length", "srvloc.srvdereq.taglistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1685 NULL, HFILL}
1687 { &hf_srvloc_srvdereg_taglist,
1688 { "Tag List", "srvloc.srvdereq.taglist", FT_STRING, BASE_NONE, NULL, 0x0,
1689 NULL, HFILL}
1693 /* collection of helper functions for Attribute Request */
1694 { &hf_srvloc_attrreq_prlistlen,
1695 { "Previous Response List Length", "srvloc.attrreq.prlistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1696 "Length of Previous Response List", HFILL}
1698 { &hf_srvloc_attrreq_prlist,
1699 { "Previous Response List", "srvloc.attrreq.prlist", FT_STRING, BASE_NONE, NULL, 0x0,
1700 NULL, HFILL}
1702 { &hf_srvloc_attrreq_urllen,
1703 { "URL Length", "srvloc.attrreq.urllen", FT_UINT16, BASE_DEC, NULL, 0x0,
1704 NULL, HFILL}
1706 { &hf_srvloc_attrreq_url,
1707 { "Service URL", "srvloc.attrreq.url", FT_STRING, BASE_NONE, NULL, 0x0,
1708 "URL of service", HFILL}
1710 { &hf_srvloc_attrreq_scopelistlen,
1711 { "Scope List Length", "srvloc.attrreq.scopelistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1712 "Length of the Scope List", HFILL}
1714 { &hf_srvloc_attrreq_scopelist,
1715 { "Scope List", "srvloc.attrreq.scopelist", FT_STRING, BASE_NONE, NULL, 0x0,
1716 NULL, HFILL}
1718 { &hf_srvloc_attrreq_attrlistlen,
1719 { "Attribute List Length", "srvloc.attrreq.attrlistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1720 NULL, HFILL}
1722 { &hf_srvloc_attrreq_attrlist,
1723 { "Attribute List", "srvloc.attrreq.attrlist", FT_STRING, BASE_NONE, NULL, 0x0,
1724 NULL, HFILL}
1726 { &hf_srvloc_attrreq_taglistlen,
1727 { "Tag List Length", "srvloc.attrreq.taglistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1728 NULL, HFILL}
1730 { &hf_srvloc_attrreq_taglist,
1731 { "Tag List", "srvloc.attrreq.taglist", FT_STRING, BASE_NONE, NULL, 0x0,
1732 NULL, HFILL}
1734 { &hf_srvloc_attrreq_slpspilen,
1735 { "SLP SPI Length", "srvloc.attrreq.slpspilen", FT_UINT16, BASE_DEC, NULL, 0x0,
1736 "Length of the SLP SPI", HFILL}
1738 { &hf_srvloc_attrreq_slpspi,
1739 { "SLP SPI", "srvloc.attrreq.slpspi", FT_STRING, BASE_NONE, NULL, 0x0,
1740 NULL, HFILL}
1743 /* collection of helper functions for Attribute Reply */
1744 { &hf_srvloc_attrrply_attrlistlen,
1745 { "Attribute List Length", "srvloc.attrrply.attrlistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1746 "Length of Attribute List", HFILL}
1748 { &hf_srvloc_attrrply_attrlist,
1749 { "Attribute List", "srvloc.attrrply.attrlist", FT_STRING, BASE_NONE, NULL, 0x0,
1750 NULL, HFILL}
1752 { &hf_srvloc_attrrply_attrauthcount,
1753 { "Attr Auths", "srvloc.srvreq.attrauthcount", FT_UINT8, BASE_DEC, NULL, 0x0,
1754 "Number of Attribute Authentication Blocks", HFILL}
1757 /* collection of helper functions for DA Advertisement */
1758 { &hf_srvloc_daadvert_timestamp,
1759 { "DAADVERT Timestamp", "srvloc.daadvert.timestamp", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL,
1760 NULL, 0, "Timestamp on DA Advert", HFILL }
1762 { &hf_srvloc_daadvert_urllen,
1763 { "URL Length", "srvloc.daadvert.urllen", FT_UINT16, BASE_DEC, NULL, 0x0,
1764 NULL, HFILL}
1766 { &hf_srvloc_daadvert_url,
1767 { "URL", "srvloc.daadvert.url", FT_STRING, BASE_NONE, NULL, 0x0,
1768 NULL, HFILL}
1770 { &hf_srvloc_daadvert_scopelistlen,
1771 { "Scope List Length", "srvloc.daadvert.scopelistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1772 "Length of the Scope List", HFILL}
1774 { &hf_srvloc_daadvert_scopelist,
1775 { "Scope List", "srvloc.daadvert.scopelist", FT_STRING, BASE_NONE, NULL, 0x0,
1776 NULL, HFILL}
1778 { &hf_srvloc_daadvert_attrlistlen,
1779 { "Attribute List Length", "srvloc.daadvert.attrlistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1780 NULL, HFILL}
1782 { &hf_srvloc_daadvert_attrlist,
1783 { "Attribute List", "srvloc.daadvert.attrlist", FT_STRING, BASE_NONE, NULL, 0x0,
1784 NULL, HFILL}
1786 { &hf_srvloc_daadvert_slpspilen,
1787 { "SLP SPI Length", "srvloc.daadvert.slpspilen", FT_UINT16, BASE_DEC, NULL, 0x0,
1788 "Length of the SLP SPI", HFILL}
1790 { &hf_srvloc_daadvert_slpspi,
1791 { "SLP SPI", "srvloc.daadvert.slpspi", FT_STRING, BASE_NONE, NULL, 0x0,
1792 NULL, HFILL}
1794 { &hf_srvloc_daadvert_authcount,
1795 { "Auths", "srvloc.daadvert.authcount", FT_UINT8, BASE_DEC, NULL, 0x0,
1796 "Number of Authentication Blocks", HFILL}
1799 /* collection of helper functions for Service Type Request */
1800 { &hf_srvloc_srvtypereq_prlistlen,
1801 { "Previous Response List Length", "srvloc.srvtypereq.prlistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1802 "Length of Previous Response List", HFILL}
1804 { &hf_srvloc_srvtypereq_prlist,
1805 { "Previous Response List", "srvloc.srvtypereq.prlist", FT_STRING, BASE_NONE, NULL, 0x0,
1806 NULL, HFILL}
1808 { &hf_srvloc_srvtypereq_nameauthlistlen,
1809 { "Naming Authority List Length", "srvloc.srvtypereq.nameauthlistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1810 "Length of the Naming Authority List", HFILL}
1812 { &hf_srvloc_srvtypereq_nameauthlistlenall,
1813 { "Naming Authority List Length (All Naming Authorities)", "srvloc.srvtypereq.nameauthlistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1814 "Length of the Naming Authority List", HFILL}
1816 { &hf_srvloc_srvtypereq_nameauthlist,
1817 { "Naming Authority List", "srvloc.srvtypereq.nameauthlist", FT_STRING, BASE_NONE, NULL, 0x0,
1818 NULL, HFILL}
1820 { &hf_srvloc_srvtypereq_scopelistlen,
1821 { "Scope List Length", "srvloc.srvtypereq.scopelistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1822 "Length of the Scope List", HFILL}
1824 { &hf_srvloc_srvtypereq_scopelist,
1825 { "Scope List", "srvloc.srvtypereq.scopelist", FT_STRING, BASE_NONE, NULL, 0x0,
1826 NULL, HFILL}
1829 /* collection of helper functions for Service Type Replies */
1830 { &hf_srvloc_srvtyperply_srvtypelen,
1831 { "Service Type Length", "srvloc.srvtypereq.srvtypelen", FT_UINT16, BASE_DEC, NULL, 0x0,
1832 "Length of the Service Type", HFILL}
1834 { &hf_srvloc_srvtyperply_srvtype,
1835 { "Service Type", "srvloc.srvtyperply.srvtype", FT_STRING, BASE_NONE, NULL, 0x0,
1836 NULL, HFILL}
1838 { &hf_srvloc_srvtyperply_srvtypelistlen,
1839 { "Service Type List Length", "srvloc.srvtypereq.srvtypelistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1840 "Length of the Service Type List", HFILL}
1842 { &hf_srvloc_srvtyperply_srvtypelist,
1843 { "Service Type List", "srvloc.srvtyperply.srvtypelist", FT_STRING, BASE_NONE, NULL, 0x0,
1844 NULL, HFILL}
1847 /* collection of helper functions for SA Advertisement */
1848 { &hf_srvloc_saadvert_urllen,
1849 { "URL Length", "srvloc.saadvert.urllen", FT_UINT16, BASE_DEC, NULL, 0x0,
1850 NULL, HFILL}
1852 { &hf_srvloc_saadvert_url,
1853 { "URL", "srvloc.saadvert.url", FT_STRING, BASE_NONE, NULL, 0x0,
1854 NULL, HFILL}
1856 { &hf_srvloc_saadvert_scopelistlen,
1857 { "Scope List Length", "srvloc.saadvert.scopelistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1858 "Length of the Scope List", HFILL}
1860 { &hf_srvloc_saadvert_scopelist,
1861 { "Scope List", "srvloc.saadvert.scopelist", FT_STRING, BASE_NONE, NULL, 0x0,
1862 NULL, HFILL}
1864 { &hf_srvloc_saadvert_attrlistlen,
1865 { "Attribute List Length", "srvloc.saadvert.attrlistlen", FT_UINT16, BASE_DEC, NULL, 0x0,
1866 NULL, HFILL}
1868 { &hf_srvloc_saadvert_attrlist,
1869 { "Attribute List", "srvloc.saadvert.attrlist", FT_STRING, BASE_NONE, NULL, 0x0,
1870 NULL, HFILL}
1872 { &hf_srvloc_saadvert_authcount,
1873 { "Auths", "srvloc.saadvert.authcount", FT_UINT8, BASE_DEC, NULL, 0x0,
1874 "Number of Authentication Blocks", HFILL}
1876 { &hf_srvloc_add_ref_ip,
1877 { "IP Address", "srvloc.list.ipaddr", FT_IPv4, BASE_NONE, NULL, 0x0,
1878 "IP Address of SLP server", HFILL}
1880 { &hf_srvloc_srvrply_svcname,
1881 { "Service Name Value", "srvloc.srvrply.svcname", FT_STRING, BASE_NONE, NULL, 0x0,
1882 NULL, HFILL}
1886 static gint *ett[] = {
1887 &ett_srvloc,
1888 &ett_srvloc_attr,
1889 &ett_srvloc_flags,
1891 static ei_register_info ei[] = {
1892 { &ei_srvloc_error, { "srvloc.err.expert", PI_RESPONSE_CODE, PI_ERROR, "Error", EXPFILL }},
1893 { &ei_srvloc_error_v2, { "srvloc.errv2.expert", PI_RESPONSE_CODE, PI_ERROR, "Error", EXPFILL }},
1894 { &ei_srvloc_function_unknown, { "srvloc.function.unknown", PI_RESPONSE_CODE, PI_ERROR, "Unknown Function Type", EXPFILL }},
1897 module_t *srvloc_module;
1898 expert_module_t* expert_srvloc;
1900 proto_srvloc = proto_register_protocol("Service Location Protocol",
1901 "SRVLOC", "srvloc");
1902 proto_register_field_array(proto_srvloc, hf, array_length(hf));
1903 proto_register_subtree_array(ett, array_length(ett));
1904 expert_srvloc = expert_register_protocol(proto_srvloc);
1905 expert_register_field_array(expert_srvloc, ei, array_length(ei));
1906 srvloc_module = prefs_register_protocol(proto_srvloc, NULL);
1907 prefs_register_bool_preference(srvloc_module, "desegment_tcp",
1908 "Reassemble SRVLOC messages spanning multiple TCP segments",
1909 "Whether the SRVLOC dissector should reassemble messages spanning multiple TCP segments. "
1910 "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
1911 &srvloc_desegment);
1914 void
1915 proto_reg_handoff_srvloc(void)
1917 dissector_handle_t srvloc_handle, srvloc_tcp_handle;
1918 srvloc_handle = new_create_dissector_handle(dissect_srvloc, proto_srvloc);
1919 dissector_add_uint("udp.port", UDP_PORT_SRVLOC, srvloc_handle);
1920 srvloc_tcp_handle = new_create_dissector_handle(dissect_srvloc_tcp,
1921 proto_srvloc);
1922 dissector_add_uint("tcp.port", TCP_PORT_SRVLOC, srvloc_tcp_handle);