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.25 2001/07/15 19:14:00 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"
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->fd, COL_PROTOCOL))
234 col_set_str(pinfo->fd, COL_PROTOCOL, "SRVLOC");
236 if (check_col(pinfo->fd, COL_INFO))
237 col_clear(pinfo->fd, COL_INFO);
239 version = tvb_get_guint8(tvb, offset);
240 function = tvb_get_guint8(tvb, offset + 1);
242 if (check_col(pinfo->fd, COL_INFO))
243 col_add_str(pinfo->fd, COL_INFO,
244 val_to_str(function, srvloc_functions, "Unknown Function (%u)"));
247 ti = proto_tree_add_item(tree, proto_srvloc, tvb, offset,
248 tvb_length(tvb), FALSE);
249 srvloc_tree = proto_item_add_subtree(ti, ett_srvloc);
251 proto_tree_add_uint(srvloc_tree, hf_srvloc_version, tvb, offset, 1,
253 proto_tree_add_uint(srvloc_tree, hf_srvloc_function, tvb, offset + 1, 1,
255 length = tvb_get_ntohs(tvb, offset + 2);
256 proto_tree_add_text(srvloc_tree, tvb, offset + 2, 2, "Length: %u",
258 flags = tvb_get_guint8(tvb, offset + 4);
259 tf = proto_tree_add_uint(srvloc_tree, hf_srvloc_flags, tvb, offset + 4, 1,
261 srvloc_flags = proto_item_add_subtree(tf, ett_srvloc_flags);
262 proto_tree_add_text(srvloc_flags, tvb, offset + 4, 0, "Overflow %d... .xxx", (flags & FLAG_O) >> 7 );
263 proto_tree_add_text(srvloc_flags, tvb, offset + 4, 0, "Monolingual .%d.. .xxx", (flags & FLAG_M) >> 6 );
264 proto_tree_add_text(srvloc_flags, tvb, offset + 4, 0, "URL Authentication Present ..%d. .xxx", (flags & FLAG_U) >> 5 );
265 proto_tree_add_text(srvloc_flags, tvb, offset + 4, 0, "Attribute Authentication Present ...%d .xxx", (flags & FLAG_A) >> 4 );
266 proto_tree_add_text(srvloc_flags, tvb, offset + 4, 0, "Fresh Service Entry .... %dxxx", (flags & FLAG_F) >> 3 );
267 proto_tree_add_text(srvloc_tree, tvb, offset + 5, 1, "Dialect: %u",
268 tvb_get_guint8(tvb, offset + 5));
269 proto_tree_add_text(srvloc_tree, tvb, offset + 6, 2, "Language: %s",
270 tvb_format_text(tvb, offset + 6, 2));
271 encoding = tvb_get_ntohs(tvb, offset + 8);
272 proto_tree_add_text(srvloc_tree, tvb, offset + 8, 2, "Encoding: %u (%s)",
274 val_to_str(encoding, charsets, "Unknown"));
275 proto_tree_add_text(srvloc_tree, tvb, offset + 10, 2, "Transaction ID: %u",
276 tvb_get_ntohs(tvb, offset + 10));
281 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Service Request");
282 length = tvb_get_ntohs(tvb, offset);
283 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Previous Response List Length: %u",
286 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Previous Response List: %s",
287 tvb_format_text(tvb, offset, length));
289 length = tvb_get_ntohs(tvb, offset);
290 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Predicate length: %u",
293 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Predicate: %s",
294 tvb_format_text(tvb, offset, length));
299 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Service Reply");
300 proto_tree_add_item(srvloc_tree, hf_srvloc_error, tvb, offset, 2, FALSE);
302 count = tvb_get_ntohs(tvb, offset);
303 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "URL Count: %u",
307 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "URL lifetime: %u",
308 tvb_get_ntohs(tvb, offset));
310 length = tvb_get_ntohs(tvb, offset);
311 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "URL length: %u",
314 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Service URL: %s",
315 tvb_format_text(tvb, offset, length));
317 if ( (flags & FLAG_U) == FLAG_U )
318 offset = dissect_authblk(tvb, offset, srvloc_tree);
324 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Service Registration");
325 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "URL lifetime: %u",
326 tvb_get_ntohs(tvb, offset));
328 length = tvb_get_ntohs(tvb, offset);
329 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "URL length: %u",
332 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Service URL: %s",
333 tvb_format_text(tvb, offset, length));
335 if ( (flags & FLAG_U) == FLAG_U )
336 offset = dissect_authblk(tvb, offset, srvloc_tree);
337 length = tvb_get_ntohs(tvb, offset);
338 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Attribute List length: %u",
341 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Attribute List: %s",
342 tvb_format_text(tvb, offset, length));
344 if ( (flags & FLAG_A) == FLAG_A )
345 offset = dissect_authblk(tvb, offset, srvloc_tree);
349 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Service Deregister");
350 length = tvb_get_ntohs(tvb, offset);
351 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "URL length: %u",
354 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Service URL: %s",
355 tvb_format_text(tvb, offset, length));
357 if ( (flags & FLAG_U) == FLAG_U )
358 offset = dissect_authblk(tvb, offset, srvloc_tree);
359 length = tvb_get_ntohs(tvb, offset);
360 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Attribute List length: %u",
363 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Attribute List: %s",
364 tvb_format_text(tvb, offset, length));
366 if ( (flags & FLAG_A) == FLAG_A )
367 offset = dissect_authblk(tvb, offset, srvloc_tree);
371 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Service Acknowledge");
372 proto_tree_add_item(srvloc_tree, hf_srvloc_error, tvb, offset, 2, FALSE);
377 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Attribute Request");
378 length = tvb_get_ntohs(tvb, offset);
379 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Previous Response List Length: %u",
382 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Previous Response List: %s",
383 tvb_format_text(tvb, offset, length));
385 length = tvb_get_ntohs(tvb, offset);
386 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "URL length: %u",
389 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Service URL: %s",
390 tvb_format_text(tvb, offset, length));
392 length = tvb_get_ntohs(tvb, offset);
393 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Scope List Length: %u",
396 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Scope Response List: %s",
397 tvb_format_text(tvb, offset, length));
399 length = tvb_get_ntohs(tvb, offset);
400 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Attribute List length: %u",
403 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Attribute List: %s",
404 tvb_format_text(tvb, offset, length));
409 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Attribute Reply");
410 proto_tree_add_item(srvloc_tree, hf_srvloc_error, tvb, offset, 2, FALSE);
412 length = tvb_get_ntohs(tvb, offset);
413 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Attribute List length: %u",
416 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Attribute List: %s",
417 tvb_format_text(tvb, offset, length));
419 if ( (flags & FLAG_A) == FLAG_A )
420 offset = dissect_authblk(tvb, offset, srvloc_tree);
424 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "DA Advertisement");
425 proto_tree_add_item(srvloc_tree, hf_srvloc_error, tvb, offset, 2, FALSE);
427 length = tvb_get_ntohs(tvb, offset);
428 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "URL length: %u",
431 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Service URL: %s",
432 tvb_format_text(tvb, offset, length));
434 length = tvb_get_ntohs(tvb, offset);
435 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Scope List Length: %u",
438 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Scope Response List: %s",
439 tvb_format_text(tvb, offset, length));
444 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Service Type Request");
445 length = tvb_get_ntohs(tvb, offset);
446 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Previous Response List Length: %u",
449 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Previous Response List: %s",
450 tvb_format_text(tvb, offset, length));
452 length = tvb_get_ntohs(tvb, offset);
453 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Naming Authority List length: %u",
456 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Naming Authority List: %s",
457 tvb_format_text(tvb, offset, length));
459 length = tvb_get_ntohs(tvb, offset);
460 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Scope List Length: %u",
463 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Scope Response List: %s",
464 tvb_format_text(tvb, offset, length));
469 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Service Type Reply");
470 proto_tree_add_item(srvloc_tree, hf_srvloc_error, tvb, offset, 2, FALSE);
472 count = tvb_get_ntohs(tvb, offset);
473 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Service Type Count: %u",
477 length = tvb_get_ntohs(tvb, offset);
478 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Service Type List length: %u",
481 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Service Type List: %s",
482 tvb_format_text(tvb, offset, length));
489 proto_tree_add_text(srvloc_tree, tvb, offset, tvb_length_remaining(tvb, offset), "Unknown Function Type");
494 /* Register protocol with Ethereal. */
497 proto_register_srvloc(void)
499 static hf_register_info hf[] = {
500 { &hf_srvloc_version,
501 { "Version", "srvloc.version",
502 FT_UINT8, BASE_DEC, NULL, 0x0,
506 {&hf_srvloc_function,
507 {"Function", "srvloc.function",
508 FT_UINT8, BASE_DEC, VALS(srvloc_functions), 0x0,
513 {"Flags", "srvloc.flags",
514 FT_UINT8, BASE_HEX, NULL, 0x0,
519 {"Error Code", "srvloc.err",
520 FT_UINT16, BASE_DEC, VALS(srvloc_errs), 0x0,
525 static gint *ett[] = {
530 proto_srvloc = proto_register_protocol("Service Location Protocol",
532 proto_register_field_array(proto_srvloc, hf, array_length(hf));
533 proto_register_subtree_array(ett, array_length(ett));
537 proto_reg_handoff_srvloc(void)
539 dissector_add("tcp.port", TCP_PORT_SRVLOC, dissect_srvloc, proto_srvloc);
540 dissector_add("udp.port", UDP_PORT_SRVLOC, dissect_srvloc, proto_srvloc);