Add a new "prefs_register_protocol()" routine, which is like
[obnox/wireshark/wip.git] / packet-srvloc.c
1 /* packet-srvloc.c
2  * Routines for SRVLOC (Service Location Protocol) packet dissection
3  * Copyright 1999, James Coe <jammer@cin.net>
4  *
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.
8  *
9  * $Id: packet-srvloc.c,v 1.17 2001/01/03 06:55:33 guy Exp $
10  *
11  * Ethereal - Network traffic analyzer
12  * By Gerald Combs <gerald@zing.org>
13  * Copyright 1998 Gerald Combs
14  *
15  * Service Location Protocol is RFC 2165
16  *
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.
21  * 
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.
26  * 
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.
30  */
31
32 #ifdef HAVE_CONFIG_H
33 # include "config.h"
34 #endif
35
36 #include <stdio.h>
37 #include <stdlib.h>
38
39 #ifdef HAVE_SYS_TYPES_H
40 # include <sys/types.h>
41 #endif
42
43 #ifdef HAVE_NETINET_IN_H
44 # include <netinet/in.h>
45 #endif
46
47 #include <string.h>
48 #include <time.h>
49 #include <glib.h>
50
51 #ifdef NEED_SNPRINTF_H
52 # include "snprintf.h"
53 #endif
54
55 #include "packet.h"
56 #include "packet-ipv6.h"
57 #include "strutil.h"
58
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;
64
65 static gint ett_srvloc = -1;
66 static gint ett_srvloc_flags = -1;
67
68 #define TCP_PORT_SRVLOC 427
69 #define UDP_PORT_SRVLOC 427
70
71 /* Define function types */
72
73 #define SRVREQ          1
74 #define SRVRPLY         2
75 #define SRVREG          3
76 #define SRVDEREG        4
77 #define SRVACK          5
78 #define ATTRRQST        6
79 #define ATTRRPLY        7
80 #define DAADVERT        8
81 #define SRVTYPERQST     9
82 #define SRVTYPERPLY     10
83
84 /* Create protocol header structure */
85
86 struct srvloc_hdr {
87     guint8      version;
88     guint8      function;
89     guint16     length;
90     guint8      flags;
91     guint8      dialect;
92     u_char      language[2];
93     guint16     encoding;
94     guint16     xid;
95 };
96
97 /* List to resolve function numbers to names */
98
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" }, 
110 };
111
112 /* List to resolve flag values to names */
113
114
115 /* Define flag masks */
116
117 #define FLAG_O          0x80
118 #define FLAG_M          0x40
119 #define FLAG_U          0x20
120 #define FLAG_A          0x10
121 #define FLAG_F          0x08
122
123 /* Define Error Codes */
124
125 #define SUCCESS         0
126 #define LANG_NOT_SPTD   1
127 #define PROT_PARSE_ERR  2
128 #define INVLD_REG       3
129 #define SCOPE_NOT_SPTD  4
130 #define CHRSET_NOT_UND  5
131 #define AUTH_ABSENT     6
132 #define AUTH_FAILED     7
133
134 /* List to resolve error codes to names */
135
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" },
145 };
146
147 static int
148 dissect_authblk(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
149 {
150     struct tm *stamp;
151     time_t seconds;
152     double floatsec;
153     guint16 length;
154     
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,
162                         floatsec);
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",
167                         length);
168     offset += 12;
169     proto_tree_add_text(tree, NullTVB, offset, length, "Authentication block: %s",
170                         format_text(&pd[offset], length));
171     offset += length;
172     return offset;
173 };
174
175 /* Packet dissection routine called by tcp & udp when port 427 detected */
176
177 static void
178 dissect_srvloc(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
179 {
180     proto_item *ti, *tf;
181     proto_tree *srvloc_tree, *srvloc_flags;
182     struct srvloc_hdr srvloc_hdr;
183     guint32 count;
184     guint32 length;
185
186     OLD_CHECK_DISPLAY_AS_DATA(proto_srvloc, pd, offset, fd, tree);
187     
188     if (check_col(fd, COL_PROTOCOL))
189         col_set_str(fd, COL_PROTOCOL, "SRVLOC");
190     
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)"));
193         
194     if (tree) {
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);
197     
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);
217             offset += 12;
218         } else {
219         proto_tree_add_text(srvloc_tree, NullTVB, offset, END_OF_FRAME, "Invalid Packet: Length less than header.");
220         };
221         
222         if (( srvloc_hdr.length - 12 ) == END_OF_FRAME ) {
223             switch (srvloc_hdr.function) {
224                 case SRVREQ:
225                     proto_tree_add_text(srvloc_tree, NullTVB, offset, 0, "Service Request");
226                     if (!BYTES_ARE_IN_FRAME(offset, 2))
227                         break;
228                     length = pntohs(&pd[offset]);
229                     proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Previous Response List Length: %u", length);
230                     offset += 2;
231                     if (!BYTES_ARE_IN_FRAME(offset, length))
232                         break;
233                     proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Previous Response List: %s", format_text(&pd[offset], length)); 
234                     offset += length;
235                     if (!BYTES_ARE_IN_FRAME(offset, 2))
236                         break;
237                     length = pntohs(&pd[offset]);
238                     proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Predicate length: %u", length);
239                     offset += 2;
240                     if (!BYTES_ARE_IN_FRAME(offset, length))
241                         break;
242                     proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Predicate: %s", format_text(&pd[offset], length));
243                     offset += length;
244                 break;
245             
246                 case SRVRPLY:
247                     proto_tree_add_text(srvloc_tree, NullTVB, offset, 0, "Service Reply");
248                     if (!BYTES_ARE_IN_FRAME(offset, 2))
249                         break;
250                     proto_tree_add_uint(srvloc_tree, hf_srvloc_error, NullTVB, offset, 2, pntohs(&pd[offset]));
251                     offset += 2;
252                     if (!BYTES_ARE_IN_FRAME(offset, 2))
253                         break;
254                     count = pntohs(&pd[offset]);
255                     proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "URL Count: %u", count);
256                     offset += 2;
257                     while (count > 0) {
258                         if (!BYTES_ARE_IN_FRAME(offset, 2))
259                             break;
260                         proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "URL lifetime: %d", pntohs(&pd[offset]));
261                         offset += 2;
262                         if (!BYTES_ARE_IN_FRAME(offset, 2))
263                             break;
264                         length = pntohs(&pd[offset]);
265                         proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "URL length: %u", length);
266                         offset += 2;
267                         if (!BYTES_ARE_IN_FRAME(offset, length))
268                             break;
269                         proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Service URL: %s", format_text(&pd[offset], length));
270                         offset += length;
271                         if ( (srvloc_hdr.flags & FLAG_U) == FLAG_U ) 
272                             offset = dissect_authblk(pd, offset, fd, srvloc_tree);
273                         count--;
274                     };
275                 break;
276
277                 case SRVREG:
278                     proto_tree_add_text(srvloc_tree, NullTVB, offset, 0, "Service Registration");
279                     if (!BYTES_ARE_IN_FRAME(offset, 2))
280                         break;
281                     proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "URL lifetime: %d", pntohs(&pd[offset]));
282                     offset += 2;
283                     if (!BYTES_ARE_IN_FRAME(offset, 2))
284                         break;
285                     length = pntohs(&pd[offset]);
286                     proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "URL length: %u", length);
287                     offset += 2;
288                     if (!BYTES_ARE_IN_FRAME(offset, length))
289                         break;
290                     proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Service URL: %s", format_text(&pd[offset], length));
291                     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))
295                         break;
296                     length = pntohs(&pd[offset]);
297                     proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Attribute List length: %u", length);
298                     offset += 2;
299                     if (!BYTES_ARE_IN_FRAME(offset, length))
300                         break;
301                     proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Attribute List: %s", format_text(&pd[offset], length));
302                     offset += length;
303                     if ( (srvloc_hdr.flags & FLAG_A) == FLAG_A ) 
304                         offset = dissect_authblk(pd, offset, fd, srvloc_tree);
305                 break;
306
307                 case SRVDEREG:
308                     proto_tree_add_text(srvloc_tree, NullTVB, offset, 0, "Service Deregister");
309                     if (!BYTES_ARE_IN_FRAME(offset, 2))
310                         break;
311                     length = pntohs(&pd[offset]);
312                     proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "URL length: %u", length);
313                     offset += 2;
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))
316                         break;
317                     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))
321                         break;
322                     length = pntohs(&pd[offset]);
323                     proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Attribute List length: %u", length);
324                     offset += 2;
325                     if (!BYTES_ARE_IN_FRAME(offset, length))
326                         break;
327                     proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Attribute List: %s", format_text(&pd[offset], length));
328                     offset += length;
329                     if ( (srvloc_hdr.flags & FLAG_A) == FLAG_A ) 
330                         offset = dissect_authblk(pd, offset, fd, srvloc_tree);
331                 break;
332             
333                 case SRVACK:
334                     proto_tree_add_text(srvloc_tree, NullTVB, offset, 0, "Service Acknowledge");
335                     if (!BYTES_ARE_IN_FRAME(offset, 2))
336                         break;
337                     proto_tree_add_uint(srvloc_tree, hf_srvloc_error, NullTVB, offset, 2, pntohs(&pd[offset]));
338                     offset += 2;
339                 break;
340
341                 case ATTRRQST:
342                     proto_tree_add_text(srvloc_tree, NullTVB, offset, 0, "Attribute Request");
343                     if (!BYTES_ARE_IN_FRAME(offset, 2))
344                         break;
345                     length = pntohs(&pd[offset]);
346                     proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Previous Response List Length: %u", length);
347                     offset += 2;
348                     if (!BYTES_ARE_IN_FRAME(offset, length))
349                         break;
350                     proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Previous Response List: %s", format_text(&pd[offset], length)); 
351                     offset += length;
352                     if (!BYTES_ARE_IN_FRAME(offset, 2))
353                         break;
354                     length = pntohs(&pd[offset]);
355                     proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "URL length: %u", length);
356                     offset += 2;
357                     if (!BYTES_ARE_IN_FRAME(offset, length))
358                         break;
359                     proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Service URL: %s", format_text(&pd[offset], length));
360                     offset += length;
361                     if (!BYTES_ARE_IN_FRAME(offset, 2))
362                         break;
363                     length = pntohs(&pd[offset]);
364                     proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Scope List Length: %u", length);
365                     offset += 2;
366                     if (!BYTES_ARE_IN_FRAME(offset, length))
367                         break;
368                     proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Scope Response List: %s", format_text(&pd[offset], length)); 
369                     offset += length;
370                     if (!BYTES_ARE_IN_FRAME(offset, 2))
371                         break;
372                     length = pntohs(&pd[offset]);
373                     proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Attribute List length: %u", length);
374                     offset += 2;
375                     if (!BYTES_ARE_IN_FRAME(offset, length))
376                         break;
377                     proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Attribute List: %s", format_text(&pd[offset], length));
378                     offset += length;
379                 break;
380             
381                 case ATTRRPLY:
382                     proto_tree_add_text(srvloc_tree, NullTVB, offset, 0, "Attribute Reply");
383                     if (!BYTES_ARE_IN_FRAME(offset, 2))
384                         break;
385                     proto_tree_add_uint(srvloc_tree, hf_srvloc_error, NullTVB, offset, 2, pntohs(&pd[offset]));
386                     offset += 2;
387                     if (!BYTES_ARE_IN_FRAME(offset, 2))
388                         break;
389                     length = pntohs(&pd[offset]);
390                     proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Attribute List length: %u", length);
391                     offset += 2;
392                     if (!BYTES_ARE_IN_FRAME(offset, length))
393                         break;
394                     proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Attribute List: %s", format_text(&pd[offset], length));
395                     offset += length;
396                     if ( (srvloc_hdr.flags & FLAG_A) == FLAG_A ) 
397                         offset = dissect_authblk(pd, offset, fd, srvloc_tree);
398                 break;
399             
400                 case DAADVERT:
401                     proto_tree_add_text(srvloc_tree, NullTVB, offset, 0, "DA Advertisement");
402                     if (!BYTES_ARE_IN_FRAME(offset, 2))
403                         break;
404                     proto_tree_add_uint(srvloc_tree, hf_srvloc_error, NullTVB, offset, 2, pntohs(&pd[offset]));
405                     offset += 2;
406                     if (!BYTES_ARE_IN_FRAME(offset, 2))
407                         break;
408                     length = pntohs(&pd[offset]);
409                     proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "URL length: %u", length);
410                     offset += 2;
411                     if (!BYTES_ARE_IN_FRAME(offset, length))
412                         break;
413                     proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Service URL: %s", format_text(&pd[offset], length));
414                     offset += length;
415                     if (!BYTES_ARE_IN_FRAME(offset, 2))
416                         break;
417                     length = pntohs(&pd[offset]);
418                     proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Scope List Length: %u", length);
419                     offset += 2;
420                     if (!BYTES_ARE_IN_FRAME(offset, length))
421                         break;
422                     proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Scope Response List: %s", format_text(&pd[offset], length)); 
423                     offset += length;
424                 break;
425
426                 case SRVTYPERQST:
427                     proto_tree_add_text(srvloc_tree, NullTVB, offset, 0, "Service Type Request");
428                     if (!BYTES_ARE_IN_FRAME(offset, 2))
429                         break;
430                     length = pntohs(&pd[offset]);
431                     proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Previous Response List Length: %u", length);
432                     offset += 2;
433                     if (!BYTES_ARE_IN_FRAME(offset, length))
434                         break;
435                     proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Previous Response List: %s", format_text(&pd[offset], length)); 
436                     offset += length;
437                     if (!BYTES_ARE_IN_FRAME(offset, 2))
438                         break;
439                     length = pntohs(&pd[offset]);
440                     proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Naming Authority List length: %u", length);
441                     offset += 2;
442                     if (!BYTES_ARE_IN_FRAME(offset, length))
443                         break;
444                     proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Naming Authority List: %s", format_text(&pd[offset], length)); 
445                     offset += length;
446                     if (!BYTES_ARE_IN_FRAME(offset, 2))
447                         break;
448                     length = pntohs(&pd[offset]);
449                     proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Scope List Length: %u", length);
450                     offset += 2;
451                     if (!BYTES_ARE_IN_FRAME(offset, length))
452                         break;
453                     proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Scope Response List: %s", format_text(&pd[offset], length)); 
454                     offset += length;
455                 break;
456
457                 case SRVTYPERPLY:
458                     proto_tree_add_text(srvloc_tree, NullTVB, offset, 0, "Service Type Reply");
459                     if (!BYTES_ARE_IN_FRAME(offset, 2))
460                         break;
461                     proto_tree_add_uint(srvloc_tree, hf_srvloc_error, NullTVB, offset, 2, pntohs(&pd[offset]));
462                     offset += 2;
463                     if (!BYTES_ARE_IN_FRAME(offset, 2))
464                         break;
465                     count = pntohs(&pd[offset]);
466                     proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Service Type Count: %u", count);
467                     offset += 2;
468                     while (count > 0) {
469                         if (!BYTES_ARE_IN_FRAME(offset, 2))
470                             break;
471                         length = pntohs(&pd[offset]);
472                         proto_tree_add_text(srvloc_tree, NullTVB, offset, 2, "Service Type List length: %u", length);
473                         offset += 2;
474                         if (!BYTES_ARE_IN_FRAME(offset, length))
475                             break;
476                         proto_tree_add_text(srvloc_tree, NullTVB, offset, length, "Service Type List: %s", format_text(&pd[offset], length));
477                         offset += length;
478                         count--;
479                     };
480                 break;
481
482                 default:
483                     proto_tree_add_text(srvloc_tree, NullTVB, offset, END_OF_FRAME, "Unknown Function Type");
484             };
485         } else { proto_tree_add_text(srvloc_tree, NullTVB, offset, END_OF_FRAME,"Invalid packet: Bad length value");
486         };        
487     };
488 };
489
490 /* Register protocol with Ethereal. */
491
492 void
493 proto_register_srvloc(void)
494 {
495     static hf_register_info hf[] = {
496         { &hf_srvloc_version,
497             { "Version",           "srvloc.version",
498             FT_UINT8, BASE_DEC, NULL, 0x0,
499             "" }
500         },
501       
502         {&hf_srvloc_function,
503             {"Function", "srvloc.function", 
504             FT_UINT8, BASE_DEC, VALS(srvloc_functions), 0x0, 
505             ""}
506         },
507
508         {&hf_srvloc_flags,
509             {"Flags", "srvloc.flags", 
510             FT_UINT8, BASE_HEX, NULL, 0x0, 
511             ""}
512         },
513         
514         {&hf_srvloc_error,
515             {"Error Code", "srvloc.err",
516             FT_UINT16, BASE_DEC, VALS(srvloc_errs), 0x0,
517             ""}
518         },
519    };
520                   
521    static gint *ett[] = {
522       &ett_srvloc,
523       &ett_srvloc_flags,
524    };
525
526     proto_srvloc = proto_register_protocol("Service Location Protocol",
527                                            "SRVLOC", "srvloc");
528     proto_register_field_array(proto_srvloc, hf, array_length(hf));
529     proto_register_subtree_array(ett, array_length(ett));
530 };
531
532 void
533 proto_reg_handoff_srvloc(void)
534 {
535     old_dissector_add("tcp.port", TCP_PORT_SRVLOC, dissect_srvloc);
536     old_dissector_add("udp.port", UDP_PORT_SRVLOC, dissect_srvloc);
537 }
538