2 * Routines for SRVLOC (Service Location Protocol) packet dissection
3 * Copyright 1999, James Coe <jammer@cin.net>
5 * NOTE: This is Alpha software not all features have been verified yet.
6 * In particular I have not had an opportunity to see how it
7 * responds to SRVLOC over TCP.
9 * $Id: packet-srvloc.c,v 1.29 2002/01/24 09:20:51 guy Exp $
11 * Ethereal - Network traffic analyzer
12 * By Gerald Combs <gerald@ethereal.com>
13 * Copyright 1998 Gerald Combs
15 * Service Location Protocol is RFC 2165
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License
19 * as published by the Free Software Foundation; either version 2
20 * of the License, or (at your option) any later version.
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
39 #ifdef HAVE_SYS_TYPES_H
40 # include <sys/types.h>
43 #ifdef HAVE_NETINET_IN_H
44 # include <netinet/in.h>
51 #ifdef NEED_SNPRINTF_H
52 # include "snprintf.h"
55 #include <epan/packet.h>
56 #include <epan/strutil.h>
58 static int proto_srvloc = -1;
59 static int hf_srvloc_version = -1;
60 static int hf_srvloc_function = -1;
61 static int hf_srvloc_flags = -1;
62 static int hf_srvloc_error = -1;
64 static gint ett_srvloc = -1;
65 static gint ett_srvloc_flags = -1;
67 #define TCP_PORT_SRVLOC 427
68 #define UDP_PORT_SRVLOC 427
70 /* Define function types */
81 #define SRVTYPERPLY 10
83 /* Create protocol header structure */
96 /* List to resolve function numbers to names */
98 static const value_string srvloc_functions[] = {
99 { SRVREQ, "Service Request" },
100 { SRVRPLY, "Service Reply" },
101 { SRVREG, "Service Registration" },
102 { SRVDEREG, "Service Deregister" },
103 { SRVACK, "Service Acknowledge" },
104 { ATTRRQST, "Attribute Request" },
105 { ATTRRPLY, "Attribute Reply" },
106 { DAADVERT, "DA Advertisement" },
107 { SRVTYPERQST, "Service Type Request" },
108 { SRVTYPERPLY, "Service Type Reply" },
112 /* List to resolve flag values to names */
115 /* Define flag masks */
123 /* Define Error Codes */
126 #define LANG_NOT_SPTD 1
127 #define PROT_PARSE_ERR 2
129 #define SCOPE_NOT_SPTD 4
130 #define CHRSET_NOT_UND 5
131 #define AUTH_ABSENT 6
132 #define AUTH_FAILED 7
134 /* List to resolve error codes to names */
136 static const value_string srvloc_errs[] = {
137 { SUCCESS, "No Error" },
138 { LANG_NOT_SPTD, "Language not supported" },
139 { PROT_PARSE_ERR, "Protocol parse error" },
140 { INVLD_REG, "Invalid registration" },
141 { SCOPE_NOT_SPTD, "Scope not supported" },
142 { CHRSET_NOT_UND, "Character set not understood" },
143 { AUTH_ABSENT, "Authentication absent" },
144 { AUTH_FAILED, "Authentication failed" },
149 * Character encodings.
150 * This is a small subset of what's in
152 * http://www.isi.edu/in-notes/iana/assignments/character-sets
154 * XXX - we should do something useful with this, i.e. properly
155 * handle strings based on the character set they're in.
157 * XXX - what does "properly handle strings" mean? How do we know
158 * what character set the terminal can handle (for tty-based code)
159 * or the GUI can handle (for GUI code)?
161 * XXX - the Ethereal core really should be what does all the
162 * character set handling for strings, and it should be stuck with
163 * the task of figuring out how to properly handle them.
165 #define CHARSET_ASCII 3
166 #define CHARSET_ISO_10646_UTF_1 27
167 #define CHARSET_ISO_646_BASIC 28
168 #define CHARSET_ISO_646_IRV 30
169 #define CHARSET_ISO_8859_1 4
170 #define CHARSET_ISO_10646_UCS_2 1000 /* a/k/a Unicode */
171 #define CHARSET_UTF_7 1012
172 #define CHARSET_UTF_8 106
174 static const value_string charsets[] = {
175 { CHARSET_ASCII, "US-ASCII" },
176 { CHARSET_ISO_10646_UTF_1, "ISO 10646 UTF-1" },
177 { CHARSET_ISO_646_BASIC, "ISO 646 basic:1983" },
178 { CHARSET_ISO_646_IRV, "ISO 646 IRV:1983" },
179 { CHARSET_ISO_8859_1, "ISO 8859-1" },
180 { CHARSET_ISO_10646_UCS_2, "Unicode" },
181 { CHARSET_UTF_7, "UTF-7" },
182 { CHARSET_UTF_8, "UTF-8" },
187 dissect_authblk(tvbuff_t *tvb, int offset, proto_tree *tree)
194 seconds = tvb_get_ntohl(tvb, offset) - 2208988800ul;
195 stamp = gmtime(&seconds);
197 floatsec = stamp->tm_sec + tvb_get_ntohl(tvb, offset + 4) / 4294967296.0;
198 proto_tree_add_text(tree, tvb, offset, 8,
199 "Timestamp: %04d-%02d-%02d %02d:%02d:%07.4f UTC",
200 stamp->tm_year + 1900, stamp->tm_mon + 1,
201 stamp->tm_mday, stamp->tm_hour, stamp->tm_min,
204 proto_tree_add_text(tree, tvb, offset, 8, "Timestamp not representable");
206 proto_tree_add_text(tree, tvb, offset + 8, 2, "Block Structure Desciptor: %u",
207 tvb_get_ntohs(tvb, offset + 8));
208 length = tvb_get_ntohs(tvb, offset + 10);
209 proto_tree_add_text(tree, tvb, offset + 10, 2, "Authenticator length: %u",
212 proto_tree_add_text(tree, tvb, offset, length, "Authentication block: %s",
213 tvb_format_text(tvb, offset, length));
218 /* Packet dissection routine called by tcp & udp when port 427 detected */
221 dissect_srvloc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
225 proto_tree *srvloc_tree, *srvloc_flags;
233 if (check_col(pinfo->cinfo, COL_PROTOCOL))
234 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SRVLOC");
236 if (check_col(pinfo->cinfo, COL_INFO))
237 col_clear(pinfo->cinfo, COL_INFO);
239 version = tvb_get_guint8(tvb, offset);
240 function = tvb_get_guint8(tvb, offset + 1);
242 if (check_col(pinfo->cinfo, COL_INFO))
243 col_add_str(pinfo->cinfo, COL_INFO,
244 val_to_str(function, srvloc_functions, "Unknown Function (%u)"));
247 ti = proto_tree_add_item(tree, proto_srvloc, tvb, offset, -1, FALSE);
248 srvloc_tree = proto_item_add_subtree(ti, ett_srvloc);
250 proto_tree_add_uint(srvloc_tree, hf_srvloc_version, tvb, offset, 1,
252 proto_tree_add_uint(srvloc_tree, hf_srvloc_function, tvb, offset + 1, 1,
254 length = tvb_get_ntohs(tvb, offset + 2);
255 proto_tree_add_text(srvloc_tree, tvb, offset + 2, 2, "Length: %u",
257 flags = tvb_get_guint8(tvb, offset + 4);
258 tf = proto_tree_add_uint(srvloc_tree, hf_srvloc_flags, tvb, offset + 4, 1,
260 srvloc_flags = proto_item_add_subtree(tf, ett_srvloc_flags);
261 proto_tree_add_text(srvloc_flags, tvb, offset + 4, 0, "Overflow %d... .xxx", (flags & FLAG_O) >> 7 );
262 proto_tree_add_text(srvloc_flags, tvb, offset + 4, 0, "Monolingual .%d.. .xxx", (flags & FLAG_M) >> 6 );
263 proto_tree_add_text(srvloc_flags, tvb, offset + 4, 0, "URL Authentication Present ..%d. .xxx", (flags & FLAG_U) >> 5 );
264 proto_tree_add_text(srvloc_flags, tvb, offset + 4, 0, "Attribute Authentication Present ...%d .xxx", (flags & FLAG_A) >> 4 );
265 proto_tree_add_text(srvloc_flags, tvb, offset + 4, 0, "Fresh Service Entry .... %dxxx", (flags & FLAG_F) >> 3 );
266 proto_tree_add_text(srvloc_tree, tvb, offset + 5, 1, "Dialect: %u",
267 tvb_get_guint8(tvb, offset + 5));
268 proto_tree_add_text(srvloc_tree, tvb, offset + 6, 2, "Language: %s",
269 tvb_format_text(tvb, offset + 6, 2));
270 encoding = tvb_get_ntohs(tvb, offset + 8);
271 proto_tree_add_text(srvloc_tree, tvb, offset + 8, 2, "Encoding: %u (%s)",
273 val_to_str(encoding, charsets, "Unknown"));
274 proto_tree_add_text(srvloc_tree, tvb, offset + 10, 2, "Transaction ID: %u",
275 tvb_get_ntohs(tvb, offset + 10));
280 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Service Request");
281 length = tvb_get_ntohs(tvb, offset);
282 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Previous Response List Length: %u",
285 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Previous Response List: %s",
286 tvb_format_text(tvb, offset, length));
288 length = tvb_get_ntohs(tvb, offset);
289 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Predicate length: %u",
292 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Predicate: %s",
293 tvb_format_text(tvb, offset, length));
298 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Service Reply");
299 proto_tree_add_item(srvloc_tree, hf_srvloc_error, tvb, offset, 2, FALSE);
301 count = tvb_get_ntohs(tvb, offset);
302 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "URL Count: %u",
306 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "URL lifetime: %u",
307 tvb_get_ntohs(tvb, offset));
309 length = tvb_get_ntohs(tvb, offset);
310 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "URL length: %u",
313 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Service URL: %s",
314 tvb_format_text(tvb, offset, length));
316 if ( (flags & FLAG_U) == FLAG_U )
317 offset = dissect_authblk(tvb, offset, srvloc_tree);
323 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Service Registration");
324 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "URL lifetime: %u",
325 tvb_get_ntohs(tvb, offset));
327 length = tvb_get_ntohs(tvb, offset);
328 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "URL length: %u",
331 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Service URL: %s",
332 tvb_format_text(tvb, offset, length));
334 if ( (flags & FLAG_U) == FLAG_U )
335 offset = dissect_authblk(tvb, offset, srvloc_tree);
336 length = tvb_get_ntohs(tvb, offset);
337 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Attribute List length: %u",
340 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Attribute List: %s",
341 tvb_format_text(tvb, offset, length));
343 if ( (flags & FLAG_A) == FLAG_A )
344 offset = dissect_authblk(tvb, offset, srvloc_tree);
348 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Service Deregister");
349 length = tvb_get_ntohs(tvb, offset);
350 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "URL length: %u",
353 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Service URL: %s",
354 tvb_format_text(tvb, offset, length));
356 if ( (flags & FLAG_U) == FLAG_U )
357 offset = dissect_authblk(tvb, offset, srvloc_tree);
358 length = tvb_get_ntohs(tvb, offset);
359 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Attribute List length: %u",
362 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Attribute List: %s",
363 tvb_format_text(tvb, offset, length));
365 if ( (flags & FLAG_A) == FLAG_A )
366 offset = dissect_authblk(tvb, offset, srvloc_tree);
370 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Service Acknowledge");
371 proto_tree_add_item(srvloc_tree, hf_srvloc_error, tvb, offset, 2, FALSE);
376 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Attribute Request");
377 length = tvb_get_ntohs(tvb, offset);
378 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Previous Response List Length: %u",
381 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Previous Response List: %s",
382 tvb_format_text(tvb, offset, length));
384 length = tvb_get_ntohs(tvb, offset);
385 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "URL length: %u",
388 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Service URL: %s",
389 tvb_format_text(tvb, offset, length));
391 length = tvb_get_ntohs(tvb, offset);
392 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Scope List Length: %u",
395 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Scope Response List: %s",
396 tvb_format_text(tvb, offset, length));
398 length = tvb_get_ntohs(tvb, offset);
399 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Attribute List length: %u",
402 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Attribute List: %s",
403 tvb_format_text(tvb, offset, length));
408 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Attribute Reply");
409 proto_tree_add_item(srvloc_tree, hf_srvloc_error, tvb, offset, 2, FALSE);
411 length = tvb_get_ntohs(tvb, offset);
412 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Attribute List length: %u",
415 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Attribute List: %s",
416 tvb_format_text(tvb, offset, length));
418 if ( (flags & FLAG_A) == FLAG_A )
419 offset = dissect_authblk(tvb, offset, srvloc_tree);
423 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "DA Advertisement");
424 proto_tree_add_item(srvloc_tree, hf_srvloc_error, tvb, offset, 2, FALSE);
426 length = tvb_get_ntohs(tvb, offset);
427 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "URL length: %u",
430 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Service URL: %s",
431 tvb_format_text(tvb, offset, length));
433 length = tvb_get_ntohs(tvb, offset);
434 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Scope List Length: %u",
437 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Scope Response List: %s",
438 tvb_format_text(tvb, offset, length));
443 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Service Type Request");
444 length = tvb_get_ntohs(tvb, offset);
445 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Previous Response List Length: %u",
448 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Previous Response List: %s",
449 tvb_format_text(tvb, offset, length));
451 length = tvb_get_ntohs(tvb, offset);
452 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Naming Authority List length: %u",
455 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Naming Authority List: %s",
456 tvb_format_text(tvb, offset, length));
458 length = tvb_get_ntohs(tvb, offset);
459 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Scope List Length: %u",
462 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Scope Response List: %s",
463 tvb_format_text(tvb, offset, length));
468 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Service Type Reply");
469 proto_tree_add_item(srvloc_tree, hf_srvloc_error, tvb, offset, 2, FALSE);
471 count = tvb_get_ntohs(tvb, offset);
472 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Service Type Count: %u",
476 length = tvb_get_ntohs(tvb, offset);
477 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Service Type List length: %u",
480 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Service Type List: %s",
481 tvb_format_text(tvb, offset, length));
488 proto_tree_add_text(srvloc_tree, tvb, offset, -1, "Unknown Function Type");
493 /* Register protocol with Ethereal. */
496 proto_register_srvloc(void)
498 static hf_register_info hf[] = {
499 { &hf_srvloc_version,
500 { "Version", "srvloc.version",
501 FT_UINT8, BASE_DEC, NULL, 0x0,
505 {&hf_srvloc_function,
506 {"Function", "srvloc.function",
507 FT_UINT8, BASE_DEC, VALS(srvloc_functions), 0x0,
512 {"Flags", "srvloc.flags",
513 FT_UINT8, BASE_HEX, NULL, 0x0,
518 {"Error Code", "srvloc.err",
519 FT_UINT16, BASE_DEC, VALS(srvloc_errs), 0x0,
524 static gint *ett[] = {
529 proto_srvloc = proto_register_protocol("Service Location Protocol",
531 proto_register_field_array(proto_srvloc, hf, array_length(hf));
532 proto_register_subtree_array(ett, array_length(ett));
536 proto_reg_handoff_srvloc(void)
538 dissector_handle_t srvloc_handle;
540 srvloc_handle = create_dissector_handle(dissect_srvloc, proto_srvloc);
541 dissector_add("tcp.port", TCP_PORT_SRVLOC, srvloc_handle);
542 dissector_add("udp.port", UDP_PORT_SRVLOC, srvloc_handle);