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.17 2001/01/03 06:55:33 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" },
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" },
148 dissect_authblk(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
155 seconds = pntohl(&pd[offset]) - 2208988800ul;
156 stamp = gmtime(&seconds);
157 floatsec = stamp->tm_sec + pntohl(&pd[offset + 4]) / 4294967296.0;
158 proto_tree_add_text(tree, NullTVB, offset, 8,
159 "Timestamp: %04d-%02d-%02d %02d:%02d:%07.4f UTC",
160 stamp->tm_year + 1900, stamp->tm_mon + 1,
161 stamp->tm_mday, stamp->tm_hour, stamp->tm_min,
163 proto_tree_add_text(tree, NullTVB, offset + 8, 2, "Block Structure Desciptor: %u",
164 pntohs(&pd[offset + 8]));
165 length = pntohs(&pd[offset + 10]);
166 proto_tree_add_text(tree, NullTVB, offset + 10, 2, "Authenticator length: %u",
169 proto_tree_add_text(tree, NullTVB, offset, length, "Authentication block: %s",
170 format_text(&pd[offset], length));
175 /* Packet dissection routine called by tcp & udp when port 427 detected */
178 dissect_srvloc(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
181 proto_tree *srvloc_tree, *srvloc_flags;
182 struct srvloc_hdr srvloc_hdr;
186 OLD_CHECK_DISPLAY_AS_DATA(proto_srvloc, pd, offset, fd, tree);
188 if (check_col(fd, COL_PROTOCOL))
189 col_set_str(fd, COL_PROTOCOL, "SRVLOC");
191 if (check_col(fd, COL_INFO))
192 col_add_str(fd, COL_INFO, val_to_str(pd[offset + 1], srvloc_functions, "Unknown Function (%d)"));
195 ti = proto_tree_add_item(tree, proto_srvloc, NullTVB, offset, END_OF_FRAME, FALSE);
196 srvloc_tree = proto_item_add_subtree(ti, ett_srvloc);
198 if ( END_OF_FRAME > sizeof(srvloc_hdr) ) {
199 memcpy( &srvloc_hdr, &pd[offset], sizeof(srvloc_hdr) );
200 srvloc_hdr.length = pntohs(&srvloc_hdr.length);
201 srvloc_hdr.encoding = pntohs(&srvloc_hdr.encoding);
202 srvloc_hdr.xid = pntohs(&srvloc_hdr.xid);
203 proto_tree_add_uint(srvloc_tree, hf_srvloc_version, NullTVB, offset, 1, srvloc_hdr.version);
204 proto_tree_add_uint(srvloc_tree, hf_srvloc_function, NullTVB, offset + 1, 1, srvloc_hdr.function);
205 proto_tree_add_text(srvloc_tree, NullTVB, offset + 2, 2, "Length: %d",srvloc_hdr.length);
206 tf = proto_tree_add_uint(srvloc_tree, hf_srvloc_flags, NullTVB, offset + 4, 1, srvloc_hdr.flags);
207 srvloc_flags = proto_item_add_subtree(tf, ett_srvloc_flags);
208 proto_tree_add_text(srvloc_flags, NullTVB, offset + 4, 0, "Overflow %d... .xxx", (srvloc_hdr.flags & FLAG_O) >> 7 );
209 proto_tree_add_text(srvloc_flags, NullTVB, offset + 4, 0, "Monolingual .%d.. .xxx", (srvloc_hdr.flags & FLAG_M) >> 6 );
210 proto_tree_add_text(srvloc_flags, NullTVB, offset + 4, 0, "URL Authentication Present ..%d. .xxx", (srvloc_hdr.flags & FLAG_U) >> 5 );
211 proto_tree_add_text(srvloc_flags, NullTVB, offset + 4, 0, "Attribute Authentication Present ...%d .xxx", (srvloc_hdr.flags & FLAG_A) >> 4 );
212 proto_tree_add_text(srvloc_flags, NullTVB, offset + 4, 0, "Fresh Service Entry .... %dxxx", (srvloc_hdr.flags & FLAG_F) >> 3 );
213 proto_tree_add_text(srvloc_tree, NullTVB, offset + 5, 1, "Dialect: %d",srvloc_hdr.dialect);
214 proto_tree_add_text(srvloc_tree, NullTVB, offset + 6, 2, "Language: %s", format_text(srvloc_hdr.language,2));
215 proto_tree_add_text(srvloc_tree, NullTVB, offset + 8, 2, "Encoding: %d", srvloc_hdr.encoding);
216 proto_tree_add_text(srvloc_tree, NullTVB, offset + 10, 2, "Transaction ID: %d", srvloc_hdr.xid);
219 proto_tree_add_text(srvloc_tree, NullTVB, offset, END_OF_FRAME, "Invalid Packet: Length less than header.");
222 if (( srvloc_hdr.length - 12 ) == END_OF_FRAME ) {
223 switch (srvloc_hdr.function) {
225 proto_tree_add_text(srvloc_tree, NullTVB, offset, 0, "Service Request");
226 if (!BYTES_ARE_IN_FRAME(offset, 2))
228 length = pntohs(&pd[offset]);
229 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Previous Response List Length: %u", length);
231 if (!BYTES_ARE_IN_FRAME(offset, length))
233 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Previous Response List: %s", format_text(&pd[offset], length));
235 if (!BYTES_ARE_IN_FRAME(offset, 2))
237 length = pntohs(&pd[offset]);
238 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Predicate length: %u", length);
240 if (!BYTES_ARE_IN_FRAME(offset, length))
242 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Predicate: %s", format_text(&pd[offset], length));
247 proto_tree_add_text(srvloc_tree, NullTVB, offset, 0, "Service Reply");
248 if (!BYTES_ARE_IN_FRAME(offset, 2))
250 proto_tree_add_uint(srvloc_tree, hf_srvloc_error, NullTVB, offset, 2, pntohs(&pd[offset]));
252 if (!BYTES_ARE_IN_FRAME(offset, 2))
254 count = pntohs(&pd[offset]);
255 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "URL Count: %u", count);
258 if (!BYTES_ARE_IN_FRAME(offset, 2))
260 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "URL lifetime: %d", pntohs(&pd[offset]));
262 if (!BYTES_ARE_IN_FRAME(offset, 2))
264 length = pntohs(&pd[offset]);
265 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "URL length: %u", length);
267 if (!BYTES_ARE_IN_FRAME(offset, length))
269 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Service URL: %s", format_text(&pd[offset], length));
271 if ( (srvloc_hdr.flags & FLAG_U) == FLAG_U )
272 offset = dissect_authblk(pd, offset, fd, srvloc_tree);
278 proto_tree_add_text(srvloc_tree, NullTVB, offset, 0, "Service Registration");
279 if (!BYTES_ARE_IN_FRAME(offset, 2))
281 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "URL lifetime: %d", pntohs(&pd[offset]));
283 if (!BYTES_ARE_IN_FRAME(offset, 2))
285 length = pntohs(&pd[offset]);
286 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "URL length: %u", length);
288 if (!BYTES_ARE_IN_FRAME(offset, length))
290 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Service URL: %s", format_text(&pd[offset], length));
292 if ( (srvloc_hdr.flags & FLAG_U) == FLAG_U )
293 offset = dissect_authblk(pd, offset, fd, srvloc_tree);
294 if (!BYTES_ARE_IN_FRAME(offset, 2))
296 length = pntohs(&pd[offset]);
297 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Attribute List length: %u", length);
299 if (!BYTES_ARE_IN_FRAME(offset, length))
301 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Attribute List: %s", format_text(&pd[offset], length));
303 if ( (srvloc_hdr.flags & FLAG_A) == FLAG_A )
304 offset = dissect_authblk(pd, offset, fd, srvloc_tree);
308 proto_tree_add_text(srvloc_tree, NullTVB, offset, 0, "Service Deregister");
309 if (!BYTES_ARE_IN_FRAME(offset, 2))
311 length = pntohs(&pd[offset]);
312 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "URL length: %u", length);
314 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Service URL: %s", format_text(&pd[offset], length));
315 if (!BYTES_ARE_IN_FRAME(offset, length))
318 if ( (srvloc_hdr.flags & FLAG_U) == FLAG_U )
319 offset = dissect_authblk(pd, offset, fd, srvloc_tree);
320 if (!BYTES_ARE_IN_FRAME(offset, 2))
322 length = pntohs(&pd[offset]);
323 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Attribute List length: %u", length);
325 if (!BYTES_ARE_IN_FRAME(offset, length))
327 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Attribute List: %s", format_text(&pd[offset], length));
329 if ( (srvloc_hdr.flags & FLAG_A) == FLAG_A )
330 offset = dissect_authblk(pd, offset, fd, srvloc_tree);
334 proto_tree_add_text(srvloc_tree, NullTVB, offset, 0, "Service Acknowledge");
335 if (!BYTES_ARE_IN_FRAME(offset, 2))
337 proto_tree_add_uint(srvloc_tree, hf_srvloc_error, NullTVB, offset, 2, pntohs(&pd[offset]));
342 proto_tree_add_text(srvloc_tree, NullTVB, offset, 0, "Attribute Request");
343 if (!BYTES_ARE_IN_FRAME(offset, 2))
345 length = pntohs(&pd[offset]);
346 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Previous Response List Length: %u", length);
348 if (!BYTES_ARE_IN_FRAME(offset, length))
350 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Previous Response List: %s", format_text(&pd[offset], length));
352 if (!BYTES_ARE_IN_FRAME(offset, 2))
354 length = pntohs(&pd[offset]);
355 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "URL length: %u", length);
357 if (!BYTES_ARE_IN_FRAME(offset, length))
359 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Service URL: %s", format_text(&pd[offset], length));
361 if (!BYTES_ARE_IN_FRAME(offset, 2))
363 length = pntohs(&pd[offset]);
364 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Scope List Length: %u", length);
366 if (!BYTES_ARE_IN_FRAME(offset, length))
368 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Scope Response List: %s", format_text(&pd[offset], length));
370 if (!BYTES_ARE_IN_FRAME(offset, 2))
372 length = pntohs(&pd[offset]);
373 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Attribute List length: %u", length);
375 if (!BYTES_ARE_IN_FRAME(offset, length))
377 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Attribute List: %s", format_text(&pd[offset], length));
382 proto_tree_add_text(srvloc_tree, NullTVB, offset, 0, "Attribute Reply");
383 if (!BYTES_ARE_IN_FRAME(offset, 2))
385 proto_tree_add_uint(srvloc_tree, hf_srvloc_error, NullTVB, offset, 2, pntohs(&pd[offset]));
387 if (!BYTES_ARE_IN_FRAME(offset, 2))
389 length = pntohs(&pd[offset]);
390 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Attribute List length: %u", length);
392 if (!BYTES_ARE_IN_FRAME(offset, length))
394 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Attribute List: %s", format_text(&pd[offset], length));
396 if ( (srvloc_hdr.flags & FLAG_A) == FLAG_A )
397 offset = dissect_authblk(pd, offset, fd, srvloc_tree);
401 proto_tree_add_text(srvloc_tree, NullTVB, offset, 0, "DA Advertisement");
402 if (!BYTES_ARE_IN_FRAME(offset, 2))
404 proto_tree_add_uint(srvloc_tree, hf_srvloc_error, NullTVB, offset, 2, pntohs(&pd[offset]));
406 if (!BYTES_ARE_IN_FRAME(offset, 2))
408 length = pntohs(&pd[offset]);
409 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "URL length: %u", length);
411 if (!BYTES_ARE_IN_FRAME(offset, length))
413 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Service URL: %s", format_text(&pd[offset], length));
415 if (!BYTES_ARE_IN_FRAME(offset, 2))
417 length = pntohs(&pd[offset]);
418 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Scope List Length: %u", length);
420 if (!BYTES_ARE_IN_FRAME(offset, length))
422 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Scope Response List: %s", format_text(&pd[offset], length));
427 proto_tree_add_text(srvloc_tree, NullTVB, offset, 0, "Service Type Request");
428 if (!BYTES_ARE_IN_FRAME(offset, 2))
430 length = pntohs(&pd[offset]);
431 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Previous Response List Length: %u", length);
433 if (!BYTES_ARE_IN_FRAME(offset, length))
435 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Previous Response List: %s", format_text(&pd[offset], length));
437 if (!BYTES_ARE_IN_FRAME(offset, 2))
439 length = pntohs(&pd[offset]);
440 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Naming Authority List length: %u", length);
442 if (!BYTES_ARE_IN_FRAME(offset, length))
444 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Naming Authority List: %s", format_text(&pd[offset], length));
446 if (!BYTES_ARE_IN_FRAME(offset, 2))
448 length = pntohs(&pd[offset]);
449 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Scope List Length: %u", length);
451 if (!BYTES_ARE_IN_FRAME(offset, length))
453 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Scope Response List: %s", format_text(&pd[offset], length));
458 proto_tree_add_text(srvloc_tree, NullTVB, offset, 0, "Service Type Reply");
459 if (!BYTES_ARE_IN_FRAME(offset, 2))
461 proto_tree_add_uint(srvloc_tree, hf_srvloc_error, NullTVB, offset, 2, pntohs(&pd[offset]));
463 if (!BYTES_ARE_IN_FRAME(offset, 2))
465 count = pntohs(&pd[offset]);
466 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Service Type Count: %u", count);
469 if (!BYTES_ARE_IN_FRAME(offset, 2))
471 length = pntohs(&pd[offset]);
472 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Service Type List length: %u", length);
474 if (!BYTES_ARE_IN_FRAME(offset, length))
476 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Service Type List: %s", format_text(&pd[offset], length));
483 proto_tree_add_text(srvloc_tree, NullTVB, offset, END_OF_FRAME, "Unknown Function Type");
485 } else { proto_tree_add_text(srvloc_tree, NullTVB, offset, END_OF_FRAME,"Invalid packet: Bad length value");
490 /* Register protocol with Ethereal. */
493 proto_register_srvloc(void)
495 static hf_register_info hf[] = {
496 { &hf_srvloc_version,
497 { "Version", "srvloc.version",
498 FT_UINT8, BASE_DEC, NULL, 0x0,
502 {&hf_srvloc_function,
503 {"Function", "srvloc.function",
504 FT_UINT8, BASE_DEC, VALS(srvloc_functions), 0x0,
509 {"Flags", "srvloc.flags",
510 FT_UINT8, BASE_HEX, NULL, 0x0,
515 {"Error Code", "srvloc.err",
516 FT_UINT16, BASE_DEC, VALS(srvloc_errs), 0x0,
521 static gint *ett[] = {
526 proto_srvloc = proto_register_protocol("Service Location Protocol",
528 proto_register_field_array(proto_srvloc, hf, array_length(hf));
529 proto_register_subtree_array(ett, array_length(ett));
533 proto_reg_handoff_srvloc(void)
535 old_dissector_add("tcp.port", TCP_PORT_SRVLOC, dissect_srvloc);
536 old_dissector_add("udp.port", UDP_PORT_SRVLOC, dissect_srvloc);