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.22 2001/03/09 04:35:22 guy Exp $
11 * Ethereal - Network traffic analyzer
12 * By Gerald Combs <gerald@zing.org>
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"
56 #include "packet-ipv6.h"
59 static int proto_srvloc = -1;
60 static int hf_srvloc_version = -1;
61 static int hf_srvloc_function = -1;
62 static int hf_srvloc_flags = -1;
63 static int hf_srvloc_error = -1;
65 static gint ett_srvloc = -1;
66 static gint ett_srvloc_flags = -1;
68 #define TCP_PORT_SRVLOC 427
69 #define UDP_PORT_SRVLOC 427
71 /* Define function types */
82 #define SRVTYPERPLY 10
84 /* Create protocol header structure */
97 /* List to resolve function numbers to names */
99 static const value_string srvloc_functions[] = {
100 { SRVREQ, "Service Request" },
101 { SRVRPLY, "Service Reply" },
102 { SRVREG, "Service Registration" },
103 { SRVDEREG, "Service Deregister" },
104 { SRVACK, "Service Acknowledge" },
105 { ATTRRQST, "Attribute Request" },
106 { ATTRRPLY, "Attribute Reply" },
107 { DAADVERT, "DA Advertisement" },
108 { SRVTYPERQST, "Service Type Request" },
109 { SRVTYPERPLY, "Service Type Reply" },
113 /* List to resolve flag values to names */
116 /* Define flag masks */
124 /* Define Error Codes */
127 #define LANG_NOT_SPTD 1
128 #define PROT_PARSE_ERR 2
130 #define SCOPE_NOT_SPTD 4
131 #define CHRSET_NOT_UND 5
132 #define AUTH_ABSENT 6
133 #define AUTH_FAILED 7
135 /* List to resolve error codes to names */
137 static const value_string srvloc_errs[] = {
138 { SUCCESS, "No Error" },
139 { LANG_NOT_SPTD, "Language not supported" },
140 { PROT_PARSE_ERR, "Protocol parse error" },
141 { INVLD_REG, "Invalid registration" },
142 { SCOPE_NOT_SPTD, "Scope not supported" },
143 { CHRSET_NOT_UND, "Character set not understood" },
144 { AUTH_ABSENT, "Authentication absent" },
145 { AUTH_FAILED, "Authentication failed" },
150 * Character encodings.
151 * This is a small subset of what's in
153 * http://www.isi.edu/in-notes/iana/assignments/character-sets
155 * XXX - we should do something useful with this, i.e. properly
156 * handle strings based on the character set they're in.
158 * XXX - what does "properly handle strings" mean? How do we know
159 * what character set the terminal can handle (for tty-based code)
160 * or the GUI can handle (for GUI code)?
162 * XXX - the Ethereal core really should be what does all the
163 * character set handling for strings, and it should be stuck with
164 * the task of figuring out how to properly handle them.
166 #define CHARSET_ASCII 3
167 #define CHARSET_ISO_10646_UTF_1 27
168 #define CHARSET_ISO_646_BASIC 28
169 #define CHARSET_ISO_646_IRV 30
170 #define CHARSET_ISO_8859_1 4
171 #define CHARSET_ISO_10646_UCS_2 1000 /* a/k/a Unicode */
172 #define CHARSET_UTF_7 1012
173 #define CHARSET_UTF_8 106
175 static const value_string charsets[] = {
176 { CHARSET_ASCII, "US-ASCII" },
177 { CHARSET_ISO_10646_UTF_1, "ISO 10646 UTF-1" },
178 { CHARSET_ISO_646_BASIC, "ISO 646 basic:1983" },
179 { CHARSET_ISO_646_IRV, "ISO 646 IRV:1983" },
180 { CHARSET_ISO_8859_1, "ISO 8859-1" },
181 { CHARSET_ISO_10646_UCS_2, "Unicode" },
182 { CHARSET_UTF_7, "UTF-7" },
183 { CHARSET_UTF_8, "UTF-8" },
188 dissect_authblk(tvbuff_t *tvb, int offset, proto_tree *tree)
195 seconds = tvb_get_ntohl(tvb, offset) - 2208988800ul;
196 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,
203 proto_tree_add_text(tree, tvb, offset + 8, 2, "Block Structure Desciptor: %u",
204 tvb_get_ntohs(tvb, offset + 8));
205 length = tvb_get_ntohs(tvb, offset + 10);
206 proto_tree_add_text(tree, tvb, offset + 10, 2, "Authenticator length: %u",
209 proto_tree_add_text(tree, tvb, offset, length, "Authentication block: %s",
210 tvb_format_text(tvb, offset, length));
215 /* Packet dissection routine called by tcp & udp when port 427 detected */
218 dissect_srvloc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
222 proto_tree *srvloc_tree, *srvloc_flags;
230 if (check_col(pinfo->fd, COL_PROTOCOL))
231 col_set_str(pinfo->fd, COL_PROTOCOL, "SRVLOC");
233 if (check_col(pinfo->fd, COL_INFO))
234 col_clear(pinfo->fd, COL_INFO);
236 version = tvb_get_guint8(tvb, offset);
237 function = tvb_get_guint8(tvb, offset + 1);
239 if (check_col(pinfo->fd, COL_INFO))
240 col_add_str(pinfo->fd, COL_INFO,
241 val_to_str(function, srvloc_functions, "Unknown Function (%u)"));
244 ti = proto_tree_add_item(tree, proto_srvloc, tvb, offset,
245 tvb_length(tvb), FALSE);
246 srvloc_tree = proto_item_add_subtree(ti, ett_srvloc);
248 proto_tree_add_uint(srvloc_tree, hf_srvloc_version, tvb, offset, 1,
250 proto_tree_add_uint(srvloc_tree, hf_srvloc_function, tvb, offset + 1, 1,
252 length = tvb_get_ntohs(tvb, offset + 2);
253 proto_tree_add_text(srvloc_tree, tvb, offset + 2, 2, "Length: %u",
255 flags = tvb_get_guint8(tvb, offset + 4);
256 tf = proto_tree_add_uint(srvloc_tree, hf_srvloc_flags, tvb, offset + 4, 1,
258 srvloc_flags = proto_item_add_subtree(tf, ett_srvloc_flags);
259 proto_tree_add_text(srvloc_flags, tvb, offset + 4, 0, "Overflow %d... .xxx", (flags & FLAG_O) >> 7 );
260 proto_tree_add_text(srvloc_flags, tvb, offset + 4, 0, "Monolingual .%d.. .xxx", (flags & FLAG_M) >> 6 );
261 proto_tree_add_text(srvloc_flags, tvb, offset + 4, 0, "URL Authentication Present ..%d. .xxx", (flags & FLAG_U) >> 5 );
262 proto_tree_add_text(srvloc_flags, tvb, offset + 4, 0, "Attribute Authentication Present ...%d .xxx", (flags & FLAG_A) >> 4 );
263 proto_tree_add_text(srvloc_flags, tvb, offset + 4, 0, "Fresh Service Entry .... %dxxx", (flags & FLAG_F) >> 3 );
264 proto_tree_add_text(srvloc_tree, tvb, offset + 5, 1, "Dialect: %u",
265 tvb_get_guint8(tvb, offset + 5));
266 proto_tree_add_text(srvloc_tree, tvb, offset + 6, 2, "Language: %s",
267 tvb_format_text(tvb, offset + 6, 2));
268 encoding = tvb_get_ntohs(tvb, offset + 8);
269 proto_tree_add_text(srvloc_tree, tvb, offset + 8, 2, "Encoding: %u (%s)",
271 val_to_str(encoding, charsets, "Unknown"));
272 proto_tree_add_text(srvloc_tree, tvb, offset + 10, 2, "Transaction ID: %u",
273 tvb_get_ntohs(tvb, offset + 10));
278 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Service Request");
279 length = tvb_get_ntohs(tvb, offset);
280 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Previous Response List Length: %u",
283 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Previous Response List: %s",
284 tvb_format_text(tvb, offset, length));
286 length = tvb_get_ntohs(tvb, offset);
287 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Predicate length: %u",
290 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Predicate: %s",
291 tvb_format_text(tvb, offset, length));
296 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Service Reply");
297 proto_tree_add_item(srvloc_tree, hf_srvloc_error, tvb, offset, 2, FALSE);
299 count = tvb_get_ntohs(tvb, offset);
300 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "URL Count: %u",
304 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "URL lifetime: %u",
305 tvb_get_ntohs(tvb, offset));
307 length = tvb_get_ntohs(tvb, offset);
308 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "URL length: %u",
311 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Service URL: %s",
312 tvb_format_text(tvb, offset, length));
314 if ( (flags & FLAG_U) == FLAG_U )
315 offset = dissect_authblk(tvb, offset, srvloc_tree);
321 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Service Registration");
322 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "URL lifetime: %u",
323 tvb_get_ntohs(tvb, offset));
325 length = tvb_get_ntohs(tvb, offset);
326 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "URL length: %u",
329 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Service URL: %s",
330 tvb_format_text(tvb, offset, length));
332 if ( (flags & FLAG_U) == FLAG_U )
333 offset = dissect_authblk(tvb, offset, srvloc_tree);
334 length = tvb_get_ntohs(tvb, offset);
335 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Attribute List length: %u",
338 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Attribute List: %s",
339 tvb_format_text(tvb, offset, length));
341 if ( (flags & FLAG_A) == FLAG_A )
342 offset = dissect_authblk(tvb, offset, srvloc_tree);
346 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Service Deregister");
347 length = tvb_get_ntohs(tvb, offset);
348 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "URL length: %u",
351 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Service URL: %s",
352 tvb_format_text(tvb, offset, length));
354 if ( (flags & FLAG_U) == FLAG_U )
355 offset = dissect_authblk(tvb, offset, srvloc_tree);
356 length = tvb_get_ntohs(tvb, offset);
357 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Attribute List length: %u",
360 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Attribute List: %s",
361 tvb_format_text(tvb, offset, length));
363 if ( (flags & FLAG_A) == FLAG_A )
364 offset = dissect_authblk(tvb, offset, srvloc_tree);
368 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Service Acknowledge");
369 proto_tree_add_item(srvloc_tree, hf_srvloc_error, tvb, offset, 2, FALSE);
374 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Attribute Request");
375 length = tvb_get_ntohs(tvb, offset);
376 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Previous Response List Length: %u",
379 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Previous Response List: %s",
380 tvb_format_text(tvb, offset, length));
382 length = tvb_get_ntohs(tvb, offset);
383 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "URL length: %u",
386 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Service URL: %s",
387 tvb_format_text(tvb, offset, length));
389 length = tvb_get_ntohs(tvb, offset);
390 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Scope List Length: %u",
393 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Scope Response List: %s",
394 tvb_format_text(tvb, offset, length));
396 length = tvb_get_ntohs(tvb, offset);
397 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Attribute List length: %u",
400 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Attribute List: %s",
401 tvb_format_text(tvb, offset, length));
406 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Attribute Reply");
407 proto_tree_add_item(srvloc_tree, hf_srvloc_error, tvb, offset, 2, FALSE);
409 length = tvb_get_ntohs(tvb, offset);
410 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Attribute List length: %u",
413 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Attribute List: %s",
414 tvb_format_text(tvb, offset, length));
416 if ( (flags & FLAG_A) == FLAG_A )
417 offset = dissect_authblk(tvb, offset, srvloc_tree);
421 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "DA Advertisement");
422 proto_tree_add_item(srvloc_tree, hf_srvloc_error, tvb, offset, 2, FALSE);
424 length = tvb_get_ntohs(tvb, offset);
425 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "URL length: %u",
428 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Service URL: %s",
429 tvb_format_text(tvb, offset, length));
431 length = tvb_get_ntohs(tvb, offset);
432 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Scope List Length: %u",
435 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Scope Response List: %s",
436 tvb_format_text(tvb, offset, length));
441 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Service Type Request");
442 length = tvb_get_ntohs(tvb, offset);
443 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Previous Response List Length: %u",
446 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Previous Response List: %s",
447 tvb_format_text(tvb, offset, length));
449 length = tvb_get_ntohs(tvb, offset);
450 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Naming Authority List length: %u",
453 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Naming Authority List: %s",
454 tvb_format_text(tvb, offset, length));
456 length = tvb_get_ntohs(tvb, offset);
457 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Scope List Length: %u",
460 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Scope Response List: %s",
461 tvb_format_text(tvb, offset, length));
466 proto_tree_add_text(srvloc_tree, tvb, offset, 0, "Service Type Reply");
467 proto_tree_add_item(srvloc_tree, hf_srvloc_error, tvb, offset, 2, FALSE);
469 count = tvb_get_ntohs(tvb, offset);
470 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Service Type Count: %u",
474 length = tvb_get_ntohs(tvb, offset);
475 proto_tree_add_text(srvloc_tree, tvb, offset, 2, "Service Type List length: %u",
478 proto_tree_add_text(srvloc_tree, tvb, offset, length, "Service Type List: %s",
479 tvb_format_text(tvb, offset, length));
486 proto_tree_add_text(srvloc_tree, tvb, offset, tvb_length_remaining(tvb, offset), "Unknown Function Type");
491 /* Register protocol with Ethereal. */
494 proto_register_srvloc(void)
496 static hf_register_info hf[] = {
497 { &hf_srvloc_version,
498 { "Version", "srvloc.version",
499 FT_UINT8, BASE_DEC, NULL, 0x0,
503 {&hf_srvloc_function,
504 {"Function", "srvloc.function",
505 FT_UINT8, BASE_DEC, VALS(srvloc_functions), 0x0,
510 {"Flags", "srvloc.flags",
511 FT_UINT8, BASE_HEX, NULL, 0x0,
516 {"Error Code", "srvloc.err",
517 FT_UINT16, BASE_DEC, VALS(srvloc_errs), 0x0,
522 static gint *ett[] = {
527 proto_srvloc = proto_register_protocol("Service Location Protocol",
529 proto_register_field_array(proto_srvloc, hf, array_length(hf));
530 proto_register_subtree_array(ett, array_length(ett));
534 proto_reg_handoff_srvloc(void)
536 dissector_add("tcp.port", TCP_PORT_SRVLOC, dissect_srvloc, proto_srvloc);
537 dissector_add("udp.port", UDP_PORT_SRVLOC, dissect_srvloc, proto_srvloc);