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.13 2000/08/11 13:34:57 deniel 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"
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" },
111 /* List to resolve flag values to names */
114 /* Define flag masks */
122 /* Define Error Codes */
125 #define LANG_NOT_SPTD 1
126 #define PROT_PARSE_ERR 2
128 #define SCOPE_NOT_SPTD 4
129 #define CHRSET_NOT_UND 5
130 #define AUTH_ABSENT 6
131 #define AUTH_FAILED 7
133 /* List to resolve error codes to names */
135 static const value_string srvloc_errs[] = {
136 { SUCCESS, "No Error" },
137 { LANG_NOT_SPTD, "Language not supported" },
138 { PROT_PARSE_ERR, "Protocol parse error" },
139 { INVLD_REG, "Invalid registration" },
140 { SCOPE_NOT_SPTD, "Scope not supported" },
141 { CHRSET_NOT_UND, "Character set not understood" },
142 { AUTH_ABSENT, "Authentication absent" },
143 { AUTH_FAILED, "Authentication failed" },
147 dissect_authblk(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
154 seconds = pntohl(&pd[offset]) - 2208988800ul;
155 stamp = gmtime(&seconds);
156 floatsec = stamp->tm_sec + pntohl(&pd[offset + 4]) / 4294967296.0;
157 proto_tree_add_text(tree, NullTVB, offset, 8,
158 "Timestamp: %04d-%02d-%02d %02d:%02d:%07.4f UTC",
159 stamp->tm_year + 1900, stamp->tm_mon + 1,
160 stamp->tm_mday, stamp->tm_hour, stamp->tm_min,
162 proto_tree_add_text(tree, NullTVB, offset + 8, 2, "Block Structure Desciptor: %u",
163 pntohs(&pd[offset + 8]));
164 length = pntohs(&pd[offset + 10]);
165 proto_tree_add_text(tree, NullTVB, offset + 10, 2, "Authenticator length: %u",
168 proto_tree_add_text(tree, NullTVB, offset, length, "Authentication block: %s",
169 format_text(&pd[offset], length));
174 /* Packet dissection routine called by tcp & udp when port 427 detected */
177 dissect_srvloc(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
180 proto_tree *srvloc_tree, *srvloc_flags;
181 struct srvloc_hdr srvloc_hdr;
185 if (check_col(fd, COL_PROTOCOL))
186 col_add_str(fd, COL_PROTOCOL, "SRVLOC");
188 if (check_col(fd, COL_INFO))
189 col_add_str(fd, COL_INFO, val_to_str(pd[offset + 1], srvloc_functions, "Unknown Function (%d)"));
192 ti = proto_tree_add_item(tree, proto_srvloc, NullTVB, offset, END_OF_FRAME, FALSE);
193 srvloc_tree = proto_item_add_subtree(ti, ett_srvloc);
195 if ( END_OF_FRAME > sizeof(srvloc_hdr) ) {
196 memcpy( &srvloc_hdr, &pd[offset], sizeof(srvloc_hdr) );
197 srvloc_hdr.length = pntohs(&srvloc_hdr.length);
198 srvloc_hdr.encoding = pntohs(&srvloc_hdr.encoding);
199 srvloc_hdr.xid = pntohs(&srvloc_hdr.xid);
200 proto_tree_add_uint(srvloc_tree, hf_srvloc_version, NullTVB, offset, 1, srvloc_hdr.version);
201 proto_tree_add_uint(srvloc_tree, hf_srvloc_function, NullTVB, offset + 1, 1, srvloc_hdr.function);
202 proto_tree_add_text(srvloc_tree, NullTVB, offset + 2, 2, "Length: %d",srvloc_hdr.length);
203 tf = proto_tree_add_uint(srvloc_tree, hf_srvloc_flags, NullTVB, offset + 4, 1, srvloc_hdr.flags);
204 srvloc_flags = proto_item_add_subtree(tf, ett_srvloc_flags);
205 proto_tree_add_text(srvloc_flags, NullTVB, offset + 4, 0, "Overflow %d... .xxx", (srvloc_hdr.flags & FLAG_O) >> 7 );
206 proto_tree_add_text(srvloc_flags, NullTVB, offset + 4, 0, "Monolingual .%d.. .xxx", (srvloc_hdr.flags & FLAG_M) >> 6 );
207 proto_tree_add_text(srvloc_flags, NullTVB, offset + 4, 0, "URL Authentication Present ..%d. .xxx", (srvloc_hdr.flags & FLAG_U) >> 5 );
208 proto_tree_add_text(srvloc_flags, NullTVB, offset + 4, 0, "Attribute Authentication Present ...%d .xxx", (srvloc_hdr.flags & FLAG_A) >> 4 );
209 proto_tree_add_text(srvloc_flags, NullTVB, offset + 4, 0, "Fresh Service Entry .... %dxxx", (srvloc_hdr.flags & FLAG_F) >> 3 );
210 proto_tree_add_text(srvloc_tree, NullTVB, offset + 5, 1, "Dialect: %d",srvloc_hdr.dialect);
211 proto_tree_add_text(srvloc_tree, NullTVB, offset + 6, 2, "Language: %s", format_text(srvloc_hdr.language,2));
212 proto_tree_add_text(srvloc_tree, NullTVB, offset + 8, 2, "Encoding: %d", srvloc_hdr.encoding);
213 proto_tree_add_text(srvloc_tree, NullTVB, offset + 10, 2, "Transaction ID: %d", srvloc_hdr.xid);
216 proto_tree_add_text(srvloc_tree, NullTVB, offset, END_OF_FRAME, "Invalid Packet: Length less than header.");
219 if (( srvloc_hdr.length - 12 ) == END_OF_FRAME ) {
220 switch (srvloc_hdr.function) {
222 proto_tree_add_text(srvloc_tree, NullTVB, offset, 0, "Service Request");
223 if (!BYTES_ARE_IN_FRAME(offset, 2))
225 length = pntohs(&pd[offset]);
226 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Previous Response List Length: %u", length);
228 if (!BYTES_ARE_IN_FRAME(offset, length))
230 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Previous Response List: %s", format_text(&pd[offset], length));
232 if (!BYTES_ARE_IN_FRAME(offset, 2))
234 length = pntohs(&pd[offset]);
235 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Predicate length: %u", length);
237 if (!BYTES_ARE_IN_FRAME(offset, length))
239 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Predicate: %s", format_text(&pd[offset], length));
244 proto_tree_add_text(srvloc_tree, NullTVB, offset, 0, "Service Reply");
245 if (!BYTES_ARE_IN_FRAME(offset, 2))
247 proto_tree_add_uint(srvloc_tree, hf_srvloc_error, NullTVB, offset, 2, pntohs(&pd[offset]));
249 if (!BYTES_ARE_IN_FRAME(offset, 2))
251 count = pntohs(&pd[offset]);
252 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "URL Count: %u", count);
255 if (!BYTES_ARE_IN_FRAME(offset, 2))
257 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "URL lifetime: %d", pntohs(&pd[offset]));
259 if (!BYTES_ARE_IN_FRAME(offset, 2))
261 length = pntohs(&pd[offset]);
262 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "URL length: %u", length);
264 if (!BYTES_ARE_IN_FRAME(offset, length))
266 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Service URL: %s", format_text(&pd[offset], length));
268 if ( (srvloc_hdr.flags & FLAG_U) == FLAG_U )
269 offset = dissect_authblk(pd, offset, fd, srvloc_tree);
275 proto_tree_add_text(srvloc_tree, NullTVB, offset, 0, "Service Registration");
276 if (!BYTES_ARE_IN_FRAME(offset, 2))
278 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "URL lifetime: %d", pntohs(&pd[offset]));
280 if (!BYTES_ARE_IN_FRAME(offset, 2))
282 length = pntohs(&pd[offset]);
283 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "URL length: %u", length);
285 if (!BYTES_ARE_IN_FRAME(offset, length))
287 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Service URL: %s", format_text(&pd[offset], length));
289 if ( (srvloc_hdr.flags & FLAG_U) == FLAG_U )
290 offset = dissect_authblk(pd, offset, fd, srvloc_tree);
291 if (!BYTES_ARE_IN_FRAME(offset, 2))
293 length = pntohs(&pd[offset]);
294 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Attribute List length: %u", length);
296 if (!BYTES_ARE_IN_FRAME(offset, length))
298 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Attribute List: %s", format_text(&pd[offset], length));
300 if ( (srvloc_hdr.flags & FLAG_A) == FLAG_A )
301 offset = dissect_authblk(pd, offset, fd, srvloc_tree);
305 proto_tree_add_text(srvloc_tree, NullTVB, offset, 0, "Service Deregister");
306 if (!BYTES_ARE_IN_FRAME(offset, 2))
308 length = pntohs(&pd[offset]);
309 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "URL length: %u", length);
311 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Service URL: %s", format_text(&pd[offset], length));
312 if (!BYTES_ARE_IN_FRAME(offset, length))
315 if ( (srvloc_hdr.flags & FLAG_U) == FLAG_U )
316 offset = dissect_authblk(pd, offset, fd, srvloc_tree);
317 if (!BYTES_ARE_IN_FRAME(offset, 2))
319 length = pntohs(&pd[offset]);
320 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Attribute List length: %u", length);
322 if (!BYTES_ARE_IN_FRAME(offset, length))
324 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Attribute List: %s", format_text(&pd[offset], length));
326 if ( (srvloc_hdr.flags & FLAG_A) == FLAG_A )
327 offset = dissect_authblk(pd, offset, fd, srvloc_tree);
331 proto_tree_add_text(srvloc_tree, NullTVB, offset, 0, "Service Acknowledge");
332 if (!BYTES_ARE_IN_FRAME(offset, 2))
334 proto_tree_add_uint(srvloc_tree, hf_srvloc_error, NullTVB, offset, 2, pntohs(&pd[offset]));
339 proto_tree_add_text(srvloc_tree, NullTVB, offset, 0, "Attribute Request");
340 if (!BYTES_ARE_IN_FRAME(offset, 2))
342 length = pntohs(&pd[offset]);
343 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Previous Response List Length: %u", length);
345 if (!BYTES_ARE_IN_FRAME(offset, length))
347 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Previous Response List: %s", format_text(&pd[offset], length));
349 if (!BYTES_ARE_IN_FRAME(offset, 2))
351 length = pntohs(&pd[offset]);
352 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "URL length: %u", length);
354 if (!BYTES_ARE_IN_FRAME(offset, length))
356 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Service URL: %s", format_text(&pd[offset], length));
358 if (!BYTES_ARE_IN_FRAME(offset, 2))
360 length = pntohs(&pd[offset]);
361 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Scope List Length: %u", length);
363 if (!BYTES_ARE_IN_FRAME(offset, length))
365 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Scope Response List: %s", format_text(&pd[offset], length));
367 if (!BYTES_ARE_IN_FRAME(offset, 2))
369 length = pntohs(&pd[offset]);
370 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Attribute List length: %u", length);
372 if (!BYTES_ARE_IN_FRAME(offset, length))
374 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Attribute List: %s", format_text(&pd[offset], length));
379 proto_tree_add_text(srvloc_tree, NullTVB, offset, 0, "Attribute Reply");
380 if (!BYTES_ARE_IN_FRAME(offset, 2))
382 proto_tree_add_uint(srvloc_tree, hf_srvloc_error, NullTVB, offset, 2, pntohs(&pd[offset]));
384 if (!BYTES_ARE_IN_FRAME(offset, 2))
386 length = pntohs(&pd[offset]);
387 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Attribute List length: %u", length);
389 if (!BYTES_ARE_IN_FRAME(offset, length))
391 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Attribute List: %s", format_text(&pd[offset], length));
393 if ( (srvloc_hdr.flags & FLAG_A) == FLAG_A )
394 offset = dissect_authblk(pd, offset, fd, srvloc_tree);
398 proto_tree_add_text(srvloc_tree, NullTVB, offset, 0, "DA Advertisement");
399 if (!BYTES_ARE_IN_FRAME(offset, 2))
401 proto_tree_add_uint(srvloc_tree, hf_srvloc_error, NullTVB, offset, 2, pntohs(&pd[offset]));
403 if (!BYTES_ARE_IN_FRAME(offset, 2))
405 length = pntohs(&pd[offset]);
406 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "URL length: %u", length);
408 if (!BYTES_ARE_IN_FRAME(offset, length))
410 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Service URL: %s", format_text(&pd[offset], length));
412 if (!BYTES_ARE_IN_FRAME(offset, 2))
414 length = pntohs(&pd[offset]);
415 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Scope List Length: %u", length);
417 if (!BYTES_ARE_IN_FRAME(offset, length))
419 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Scope Response List: %s", format_text(&pd[offset], length));
424 proto_tree_add_text(srvloc_tree, NullTVB, offset, 0, "Service Type Request");
425 if (!BYTES_ARE_IN_FRAME(offset, 2))
427 length = pntohs(&pd[offset]);
428 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Previous Response List Length: %u", length);
430 if (!BYTES_ARE_IN_FRAME(offset, length))
432 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Previous Response List: %s", format_text(&pd[offset], length));
434 if (!BYTES_ARE_IN_FRAME(offset, 2))
436 length = pntohs(&pd[offset]);
437 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Naming Authority List length: %u", length);
439 if (!BYTES_ARE_IN_FRAME(offset, length))
441 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Naming Authority List: %s", format_text(&pd[offset], length));
443 if (!BYTES_ARE_IN_FRAME(offset, 2))
445 length = pntohs(&pd[offset]);
446 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Scope List Length: %u", length);
448 if (!BYTES_ARE_IN_FRAME(offset, length))
450 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Scope Response List: %s", format_text(&pd[offset], length));
455 proto_tree_add_text(srvloc_tree, NullTVB, offset, 0, "Service Type Reply");
456 if (!BYTES_ARE_IN_FRAME(offset, 2))
458 proto_tree_add_uint(srvloc_tree, hf_srvloc_error, NullTVB, offset, 2, pntohs(&pd[offset]));
460 if (!BYTES_ARE_IN_FRAME(offset, 2))
462 count = pntohs(&pd[offset]);
463 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Service Type Count: %u", count);
466 if (!BYTES_ARE_IN_FRAME(offset, 2))
468 length = pntohs(&pd[offset]);
469 proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Service Type List length: %u", length);
471 if (!BYTES_ARE_IN_FRAME(offset, length))
473 proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Service Type List: %s", format_text(&pd[offset], length));
480 proto_tree_add_text(srvloc_tree, NullTVB, offset, END_OF_FRAME, "Unknown Function Type");
482 } else { proto_tree_add_text(srvloc_tree, NullTVB, offset, END_OF_FRAME,"Invalid packet: Bad length value");
487 /* Register protocol with Ethereal. */
490 proto_register_srvloc(void)
492 static hf_register_info hf[] = {
493 { &hf_srvloc_version,
494 { "Version", "srvloc.version",
495 FT_UINT8, BASE_DEC, NULL, 0x0,
499 {&hf_srvloc_function,
500 {"Function", "srvloc.function",
501 FT_UINT8, BASE_DEC, VALS(srvloc_functions), 0x0,
506 {"Flags", "srvloc.flags",
507 FT_UINT8, BASE_HEX, NULL, 0x0,
512 {"Error Code", "srvloc.err",
513 FT_UINT16, BASE_DEC, VALS(srvloc_errs), 0x0,
518 static gint *ett[] = {
523 proto_srvloc = proto_register_protocol("Service Location Protocol", "srvloc");
524 proto_register_field_array(proto_srvloc, hf, array_length(hf));
525 proto_register_subtree_array(ett, array_length(ett));
529 proto_reg_handoff_srvloc(void)
531 old_dissector_add("tcp.port", TCP_PORT_SRVLOC, dissect_srvloc);
532 old_dissector_add("udp.port", UDP_PORT_SRVLOC, dissect_srvloc);