added decode support for 'poll inactive station' ipx message
[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.1 1999/12/07 06:09:58 guy Exp $
10  *
11  * Ethereal - Network traffic analyzer
12  * By Gerald Combs <gerald@unicom.net>
13  * Copyright 1998 Gerald Combs
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  * 
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  * 
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
28  */
29
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33
34 #include <stdio.h>
35 #include <stdlib.h>
36
37 #ifdef HAVE_SYS_TYPES_H
38 # include <sys/types.h>
39 #endif
40
41 #ifdef HAVE_NETINET_IN_H
42 # include <netinet/in.h>
43 #endif
44
45 #ifdef NEED_SNPRINTF_H
46 # ifdef HAVE_STDARG_H
47 #  include <stdarg.h>
48 # else
49 #  include <varargs.h>
50 # endif
51 # include "snprintf.h"
52 #endif
53
54 #include <string.h>
55 #include <glib.h>
56 #include "packet.h"
57 #include "packet-ipv6.h"
58
59 int proto_srvloc = -1;
60 int hf_srvloc_version = -1;
61 int hf_srvloc_function = -1;
62 int hf_srvloc_flags = -1;
63 int hf_srvloc_error = -1;
64
65 static gint ett_srvloc = -1;
66
67 /* Define function types */
68
69 #define SRVREQ          1
70 #define SRVRPLY         2
71 #define SRVREG          3
72 #define SRVDEREG        4
73 #define SRVACK          5
74 #define ATTRRQST        6
75 #define ATTRRPLY        7
76 #define DAADVERT        8
77 #define SRVTYPERQST     9
78 #define SRVTYPERPLY     10
79
80 /* Create protocol header structure */
81
82 struct srvloc_hdr {
83     guint8      version;
84     guint8      function;
85     guint16     length;
86     guint8      flags;
87     guint8      dialect;
88     u_char      language[2];
89     guint16     encoding;
90     guint16     xid;
91 };
92
93 /* List to resolve function numbers to names */
94
95 static const value_string srvlocfunctionvals[] = {
96     { SRVREQ, "Service Request" }, 
97     { SRVRPLY, "Service Reply" }, 
98     { SRVREG, "Service Registration" }, 
99     { SRVDEREG, "Service Deregister" }, 
100     { SRVACK, "Service Acknowledge" }, 
101     { ATTRRQST, "Attribute Request" }, 
102     { ATTRRPLY, "Attribute Reply" }, 
103     { DAADVERT, "DA Advertisement" }, 
104     { SRVTYPERQST, "Service Type Request" }, 
105     { SRVTYPERPLY, "Service Type Reply" }, 
106 };
107
108 /* List to resolve flag values to names */
109
110
111 /* Define Error Codes */
112
113 #define SUCCESS         0
114 #define LANG_NOT_SPTD   1
115 #define PROT_PARSE_ERR  2
116 #define INVLD_REG       3
117 #define SCOPE_NOT_SPTD  4
118 #define CHRSET_NOT_UND  5
119 #define AUTH_ABSENT     6
120 #define AUTH_FAILED     7
121
122 /* List to resolve error codes to names */
123
124 static const value_string srvloc_errs[] = {
125     { SUCCESS, "No Error" },
126     { LANG_NOT_SPTD, "Language not supported" },
127     { PROT_PARSE_ERR, "Protocol parse error" },
128     { INVLD_REG, "Invalid registration" },
129     { SCOPE_NOT_SPTD, "Scope not supported" },
130     { CHRSET_NOT_UND, "Character set not understood" },
131     { AUTH_ABSENT, "Authentication absent" },
132     { AUTH_FAILED, "Authentication failed" },
133 };
134
135 /* Packet dissection routine called by tcp & udp when port 427 detected */
136
137 void
138 dissect_srvloc(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
139 {
140     proto_item *ti;
141     proto_tree *srvloc_tree;
142     struct srvloc_hdr srvloc_hdr;
143     int count;
144     int length;
145     
146     if (check_col(fd, COL_PROTOCOL))
147         col_add_str(fd, COL_PROTOCOL, "SRVLOC");
148     
149     if (check_col(fd, COL_INFO))
150         col_add_str(fd, COL_INFO, "Service Location Protocol");
151         
152     if (tree) {
153         ti = proto_tree_add_item(tree, proto_srvloc, offset, END_OF_FRAME, NULL);
154         srvloc_tree = proto_item_add_subtree(ti, ett_srvloc);
155     
156         if ( END_OF_FRAME > sizeof(srvloc_hdr) ) {
157             memcpy( &srvloc_hdr, &pd[offset], sizeof(srvloc_hdr) );
158             srvloc_hdr.length = ntohs(srvloc_hdr.length);
159             srvloc_hdr.encoding = ntohs(srvloc_hdr.encoding);
160             srvloc_hdr.xid = ntohs(srvloc_hdr.xid);
161             proto_tree_add_item(srvloc_tree, hf_srvloc_version, offset, 1, srvloc_hdr.version);
162             proto_tree_add_item(srvloc_tree, hf_srvloc_function, offset + 1, 1, srvloc_hdr.function);
163             proto_tree_add_text(srvloc_tree, offset + 2, 2, "Length: %d",srvloc_hdr.length);
164             proto_tree_add_item(srvloc_tree, hf_srvloc_flags, offset + 4, 1, srvloc_hdr.flags);
165             proto_tree_add_text(srvloc_tree, offset + 4, 0, "Overflow                          %d... .xxx", (srvloc_hdr.flags & 0x80) >> 7 );
166             proto_tree_add_text(srvloc_tree, offset + 4, 0, "Monolingual                       .%d.. .xxx", (srvloc_hdr.flags & 0x40) >> 6 ); 
167             proto_tree_add_text(srvloc_tree, offset + 4, 0, "URL Authentication Present        ..%d. .xxx", (srvloc_hdr.flags & 0x20) >> 5 );
168             proto_tree_add_text(srvloc_tree, offset + 4, 0, "Attribute Authentication Present  ...%d .xxx", (srvloc_hdr.flags & 0x10) >> 4 );
169             proto_tree_add_text(srvloc_tree, offset + 4, 0, "Fresh Service Entry               .... %dxxx", (srvloc_hdr.flags & 0x08) >> 3 );
170             proto_tree_add_text(srvloc_tree, offset + 5, 1, "Dialect: %d",srvloc_hdr.dialect); 
171             proto_tree_add_text(srvloc_tree, offset + 6, 2, "Language: %s", format_text(srvloc_hdr.language,2));
172             proto_tree_add_text(srvloc_tree, offset + 8, 2, "Encoding: %d", srvloc_hdr.encoding);
173             proto_tree_add_text(srvloc_tree, offset + 10, 2, "Transaction ID: %d", srvloc_hdr.xid);
174             offset += 12;
175         } else {
176         proto_tree_add_text(srvloc_tree, offset, END_OF_FRAME, "Invalid Packet: Length less than header.");
177         };
178         
179         if (( srvloc_hdr.length - 12 ) == END_OF_FRAME ) {
180             switch (srvloc_hdr.function) {
181                 case SRVREQ:
182                     proto_tree_add_text(srvloc_tree, offset, 0, "Service Request");
183                     length = pntohs(&pd[offset]);
184                     proto_tree_add_text(srvloc_tree, offset, 2, "Previous Response List Length: %d", length);
185                     offset += 2;
186                     proto_tree_add_text(srvloc_tree, offset, length, "Previous Response List: %s", format_text(&pd[offset], length)); 
187                     offset += length;
188                     length = pntohs(&pd[offset]);
189                     proto_tree_add_text(srvloc_tree, offset, 2, "Predicate length: %d", length);
190                     offset += 2;
191                     proto_tree_add_text(srvloc_tree, offset, length, "Predicate: %s", format_text(&pd[offset], length));
192                     offset += length;
193                 break;
194             
195                 case SRVRPLY:
196                     proto_tree_add_text(srvloc_tree, offset, 0, "Service Reply");
197                     proto_tree_add_item(srvloc_tree, hf_srvloc_error, offset, 2, pd[offset]);;
198                     offset += 2;
199                     proto_tree_add_text(srvloc_tree, offset, 2, "URL Count: %d", pntohs(&pd[offset]));
200                     offset += 2;
201                     for (count = pntohs(&pd[offset]) + 1; count > 0; count--, offset++) {
202                         proto_tree_add_text(srvloc_tree, offset, 2, "URL lifetime: %d", pntohs(&pd[offset]));
203                         offset += 2;
204                         length = pntohs(&pd[offset]);
205                         proto_tree_add_text(srvloc_tree, offset, 2, "URL length: %d", length);
206                         offset += 2;
207                         proto_tree_add_text(srvloc_tree, offset, length, "Service URL: %s", format_text(&pd[offset], length));
208                         offset += length;
209                     };
210                 break;
211
212                 case SRVREG:
213                     proto_tree_add_text(srvloc_tree, offset, 0, "Service Registration");
214                     proto_tree_add_text(srvloc_tree, offset, 2, "URL lifetime: %d", pntohs(&pd[offset]));
215                     offset += 2;
216                     length = pntohs(&pd[offset]);
217                     proto_tree_add_text(srvloc_tree, offset, 2, "URL length: %d", length);
218                     offset += 2;
219                     proto_tree_add_text(srvloc_tree, offset, length, "Service URL: %s", format_text(&pd[offset], length));
220                     offset += length;
221                     length = pntohs(&pd[offset]);
222                     proto_tree_add_text(srvloc_tree, offset, 2, "Attribute List length: %d", length);
223                     offset += 2;
224                     proto_tree_add_text(srvloc_tree, offset, length, "Attribute List: %s", format_text(&pd[offset], length));
225                     offset += length;
226                 break;
227
228                 case SRVDEREG:
229                     proto_tree_add_text(srvloc_tree, offset, 0, "Service Deregister");
230                     length = pntohs(&pd[offset]);
231                     proto_tree_add_text(srvloc_tree, offset, 2, "URL length: %d", length);
232                     offset += 2;
233                     proto_tree_add_text(srvloc_tree, offset, length, "Service URL: %s", format_text(&pd[offset], length));
234                     offset += length;
235                     length = pntohs(&pd[offset]);
236                     proto_tree_add_text(srvloc_tree, offset, 2, "Attribute List length: %d", length);
237                     offset += 2;
238                     proto_tree_add_text(srvloc_tree, offset, length, "Attribute List: %s", format_text(&pd[offset], length));
239                     offset += length;
240                 break;
241             
242                 case SRVACK:
243                     proto_tree_add_text(srvloc_tree, offset, 0, "Service Acknowledge");
244                     proto_tree_add_item(srvloc_tree, hf_srvloc_error, offset, 2, pd[offset]);;
245                     offset += 2;
246                 break;
247
248                 case ATTRRQST:
249                     proto_tree_add_text(srvloc_tree, offset, 0, "Attribute Request");
250                     length = pntohs(&pd[offset]);
251                     proto_tree_add_text(srvloc_tree, offset, 2, "Previous Response List Length: %d", length);
252                     offset += 2;
253                     proto_tree_add_text(srvloc_tree, offset, length, "Previous Response List: %s", format_text(&pd[offset], length)); 
254                     offset += length;
255                     length = pntohs(&pd[offset]);
256                     proto_tree_add_text(srvloc_tree, offset, 2, "URL length: %d", length);
257                     offset += 2;
258                     proto_tree_add_text(srvloc_tree, offset, length, "Service URL: %s", format_text(&pd[offset], length));
259                     offset += length;
260                     length = pntohs(&pd[offset]);
261                     proto_tree_add_text(srvloc_tree, offset, 2, "Scope List Length: %d", length);
262                     offset += 2;
263                     proto_tree_add_text(srvloc_tree, offset, length, "Scope Response List: %s", format_text(&pd[offset], length)); 
264                     offset += length;
265                     length = pntohs(&pd[offset]);
266                     proto_tree_add_text(srvloc_tree, offset, 2, "Attribute List length: %d", length);
267                     offset += 2;
268                     proto_tree_add_text(srvloc_tree, offset, length, "Attribute List: %s", format_text(&pd[offset], length));
269                     offset += length;
270                 break;
271             
272                 case ATTRRPLY:
273                     proto_tree_add_text(srvloc_tree, offset, 0, "Attribute Reply");
274                     proto_tree_add_item(srvloc_tree, hf_srvloc_error, offset, 2, pd[offset]);;
275                     offset += 2;
276                     length = pntohs(&pd[offset]);
277                     proto_tree_add_text(srvloc_tree, offset, 2, "Attribute List length: %d", length);
278                     offset += 2;
279                     proto_tree_add_text(srvloc_tree, offset, length, "Attribute List: %s", format_text(&pd[offset], length));
280                     offset += length;
281                 break;
282             
283                 case DAADVERT:
284                     proto_tree_add_text(srvloc_tree, offset, 0, "DA Advertisement");
285                     proto_tree_add_item(srvloc_tree, hf_srvloc_error, offset, 2, pd[offset]);;
286                     offset += 2;
287                     length = pntohs(&pd[offset]);
288                     proto_tree_add_text(srvloc_tree, offset, 2, "URL length: %d", length);
289                     offset += 2;
290                     proto_tree_add_text(srvloc_tree, offset, length, "Service URL: %s", format_text(&pd[offset], length));
291                     offset += length;
292                     length = pntohs(&pd[offset]);
293                     proto_tree_add_text(srvloc_tree, offset, 2, "Scope List Length: %d", length);
294                     offset += 2;
295                     proto_tree_add_text(srvloc_tree, offset, length, "Scope Response List: %s", format_text(&pd[offset], length)); 
296                     offset += length;
297                 break;
298
299                 case SRVTYPERQST:
300                     proto_tree_add_text(srvloc_tree, offset, 0, "Service Type Request");
301                     length = pntohs(&pd[offset]);
302                     proto_tree_add_text(srvloc_tree, offset, 2, "Previous Response List Length: %d", length);
303                     offset += 2;
304                     proto_tree_add_text(srvloc_tree, offset, length, "Previous Response List: %s", format_text(&pd[offset], length)); 
305                     offset += length;
306                     length = pntohs(&pd[offset]);
307                     proto_tree_add_text(srvloc_tree, offset, 2, "Naming Authority List length: %d", length);
308                     offset += 2;
309                     proto_tree_add_text(srvloc_tree, offset, length, "Naming Authority List: %s", format_text(&pd[offset], length)); 
310                     offset += length;
311                     length = pntohs(&pd[offset]);
312                     proto_tree_add_text(srvloc_tree, offset, 2, "Scope List Length: %d", length);
313                     offset += 2;
314                     proto_tree_add_text(srvloc_tree, offset, length, "Scope Response List: %s", format_text(&pd[offset], length)); 
315                     offset += length;
316                 break;
317
318                 case SRVTYPERPLY:
319                     proto_tree_add_text(srvloc_tree, offset, 0, "Service Type Reply");
320                     proto_tree_add_item(srvloc_tree, hf_srvloc_error, offset, 2, pd[offset]);;
321                     offset += 2;
322                     proto_tree_add_text(srvloc_tree, offset, 2, "Service Type Count: %d", pntohs(&pd[offset]));
323                     offset += 2;
324                     for (count = pntohs(&pd[offset]) + 1; count > 0; count--, offset++) {
325                         length = pntohs(&pd[offset]);
326                         proto_tree_add_text(srvloc_tree, offset, 2, "Service Type List length: %d", length);
327                         offset += 2;
328                         proto_tree_add_text(srvloc_tree, offset, length, "Service Type List: %s", format_text(&pd[offset], length));
329                         offset += length;
330                     };
331                 break;
332
333                 default:
334                     proto_tree_add_text(srvloc_tree, offset, END_OF_FRAME, "Unknown Function Type");
335             };
336         } else { proto_tree_add_text(srvloc_tree, offset, END_OF_FRAME,"Invalid packet: Bad length value");
337         };        
338     };
339 };
340
341 /* Register protocol with Ethereal. */
342
343 void
344 proto_register_srvloc(void)
345 {
346     static hf_register_info hf[] = {
347         { &hf_srvloc_version,
348             { "Version",           "srvloc.version",
349             FT_UINT8, BASE_DEC, NULL, 0x0,
350             "" }
351         },
352       
353         {&hf_srvloc_function,
354             {"Function", "srvloc.function", 
355             FT_UINT8, BASE_DEC, VALS(srvlocfunctionvals), 0x0, 
356             ""}
357         },
358
359         {&hf_srvloc_flags,
360             {"Flags", "srvloc.flags", 
361             FT_UINT8, BASE_HEX, NULL, 0x0, 
362             ""}
363         },
364         
365         {&hf_srvloc_error,
366             {"Error Code", "srvloc.err",
367             FT_UINT8, BASE_DEC, VALS(srvloc_errs), 0x0,
368             ""}
369         },
370    };
371                   
372    static gint *ett[] = {
373       &ett_srvloc,
374    };
375
376     proto_srvloc = proto_register_protocol("Service Location Protocol", "srvloc");
377     proto_register_field_array(proto_srvloc, hf, array_length(hf));
378     proto_register_subtree_array(ett, array_length(ett));
379 };