Final updates for 0.9.14.
[metze/wireshark/wip.git] / packet-ipxwan.c
1 /* packet-ipxwan.c
2  * Routines for NetWare IPX WAN Protocol
3  *
4  * $Id: packet-ipxwan.c,v 1.1 2003/04/06 02:32:38 guy Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <stdio.h>
30 #include <string.h>
31 #include <glib.h>
32 #include <epan/packet.h>
33 #include "packet-ipx.h"
34
35 /*
36  * See RFC 1362 for version 1 of this protocol; see the NetWare Link
37  * Services Protocol Specification, chapter 3, for version 2.
38  */
39 static int proto_ipxwan = -1;
40
41 static int hf_ipxwan_identifier = -1;
42 static int hf_ipxwan_packet_type = -1;
43 static int hf_ipxwan_node_id = -1;
44 static int hf_ipxwan_sequence_number = -1;
45 static int hf_ipxwan_num_options = -1;
46 static int hf_ipxwan_option_num = -1;
47 static int hf_ipxwan_accept_option = -1;
48 static int hf_ipxwan_option_data_len = -1;
49 static int hf_ipxwan_routing_type = -1;
50 static int hf_ipxwan_wan_link_delay = -1;
51 static int hf_ipxwan_common_network_number = -1;
52 static int hf_ipxwan_router_name = -1;
53 static int hf_ipxwan_delay = -1;
54 static int hf_ipxwan_throughput = -1;
55 static int hf_ipxwan_request_size = -1;
56 static int hf_ipxwan_delta_time = -1;
57 static int hf_ipxwan_extended_node_id = -1;
58 static int hf_ipxwan_node_number = -1;
59 static int hf_ipxwan_compression_type = -1;
60
61 static gint ett_ipxwan = -1;
62 static gint ett_ipxwan_option = -1;
63
64 static const value_string ipxwan_packet_type_vals[] = {
65         { 0,    "Timer Request" },
66         { 1,    "Timer Response" },
67         { 2,    "Information Request" },
68         { 3,    "Information Response" },
69         { 4,    "Throughput Request" },
70         { 5,    "Throughput Response" },
71         { 6,    "Delay Request" },
72         { 7,    "Delay Response" },
73         { 0xFF, "NAK" },
74         { 0,    NULL }
75 };
76
77 #define OPT_ROUTING_TYPE                0x00
78 #define OPT_RIP_SAP_INFO_EXCHANGE       0x01
79 #define OPT_NLSP_INFORMATION            0x02
80 #define OPT_NLSP_RAW_THROUGHPUT_DATA    0x03
81 #define OPT_EXTENDED_NODE_ID            0x04
82 #define OPT_NODE_NUMBER                 0x05
83 #define OPT_COMPRESSION                 0x80
84 #define OPT_PAD                         0xFF
85
86 static const value_string ipxwan_option_num_vals[] = {
87         { OPT_ROUTING_TYPE,             "Routing Type" },
88         { OPT_RIP_SAP_INFO_EXCHANGE,    "RIP/SAP Info Exchange" },
89         { OPT_NLSP_INFORMATION,         "NLSP Information" },
90         { OPT_NLSP_RAW_THROUGHPUT_DATA, "NLSP Raw Throughput Data" },
91         { OPT_EXTENDED_NODE_ID,         "Extended Node ID" },
92         { OPT_NODE_NUMBER,              "Node Number" },
93         { OPT_COMPRESSION,              "Compression" },
94         { OPT_PAD,                      "Pad" },
95         { 0,                            NULL }
96 };
97
98 static const value_string ipxwan_accept_option_vals[] = {
99         { 0, "No" },
100         { 1, "Yes" },
101         { 3, "Not Appplicable" },
102         { 0, NULL }
103 };
104
105 static const value_string ipxwan_routing_type_vals[] = {
106         { 0, "RIP" },
107         { 1, "NLSP" },
108         { 2, "Unnumbered RIP" },
109         { 3, "On-demand, static routing" },
110         { 4, "Client-router connection" },
111         { 0, NULL }
112 };
113
114 #define COMP_TYPE_TELEBIT       0
115
116 static const value_string ipxwan_compression_type_vals[] = {
117         { COMP_TYPE_TELEBIT, "Telebit" },
118         { 0,                 NULL }
119 };
120
121 static void
122 dissect_ipxwan(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
123 {
124         proto_item *ti;
125         proto_tree *ipxwan_tree = NULL;
126         int offset = 0;
127         guint8 packet_type;
128         guint8 num_options;
129         guint8 option_number;
130         proto_tree *option_tree;
131         guint16 option_data_len;
132         guint16 wan_link_delay;
133         guint32 delay;
134         guint32 throughput;
135         guint32 delta_time;
136         guint8 compression_type;
137
138         if (check_col(pinfo->cinfo, COL_PROTOCOL))
139                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPX WAN");
140         if (check_col(pinfo->cinfo, COL_INFO))
141                 col_clear(pinfo->cinfo, COL_INFO);
142
143         if (tree) {
144                 ti = proto_tree_add_item(tree, proto_ipxwan, tvb, 0, -1,
145                     FALSE);
146                 ipxwan_tree = proto_item_add_subtree(ti, ett_ipxwan);
147         }
148
149         if (tree) {
150                 proto_tree_add_item(ipxwan_tree, hf_ipxwan_identifier, tvb,
151                     offset, 4, FALSE);
152         }
153         offset += 4;
154         packet_type = tvb_get_guint8(tvb, offset);
155         if (check_col(pinfo->cinfo, COL_INFO)) {
156                 col_add_str(pinfo->cinfo, COL_INFO,
157                     val_to_str(packet_type, ipxwan_packet_type_vals,
158                         "Unknown packet type %u"));
159         }
160         if (tree) {
161                 proto_tree_add_uint(ipxwan_tree, hf_ipxwan_packet_type, tvb,
162                         offset, 1, packet_type);
163                 offset += 1;
164                 proto_tree_add_item(ipxwan_tree, hf_ipxwan_node_id, tvb,
165                         offset, 4, FALSE);
166                 offset += 4;
167                 proto_tree_add_item(ipxwan_tree, hf_ipxwan_sequence_number, tvb,
168                         offset, 1, FALSE);
169                 offset += 1;
170                 num_options = tvb_get_guint8(tvb, offset);
171                 proto_tree_add_uint(ipxwan_tree, hf_ipxwan_num_options, tvb,
172                         offset, 1, num_options);
173                 offset += 1;
174
175                 while (num_options != 0) {
176                         option_number = tvb_get_guint8(tvb, offset);
177                         ti = proto_tree_add_text(ipxwan_tree, tvb, offset, -1,
178                             "Option: %s",
179                             val_to_str(option_number, ipxwan_option_num_vals,
180                                 "Unknown (%u)"));
181                         option_tree = proto_item_add_subtree(ti,
182                             ett_ipxwan_option);
183
184                         proto_tree_add_uint(option_tree, hf_ipxwan_option_num,
185                             tvb, offset, 1, option_number);
186                         offset += 1;
187                         proto_tree_add_item(option_tree, hf_ipxwan_accept_option,
188                             tvb, offset, 1, FALSE);
189                         offset += 1;
190                         option_data_len = tvb_get_ntohs(tvb, offset);
191                         proto_tree_add_uint(option_tree, hf_ipxwan_option_data_len,
192                             tvb, offset, 2, option_data_len);
193                         offset += 2;
194                         proto_item_set_len(ti, option_data_len+4);
195                         switch (option_number) {
196
197                         case OPT_ROUTING_TYPE:
198                                 if (option_data_len != 1) {
199                                         proto_tree_add_text(option_tree,
200                                             tvb, offset, option_data_len,
201                                             "Bogus length: %u, should be 1",
202                                             option_data_len);
203                                 } else {
204                                         proto_tree_add_item(option_tree,
205                                             hf_ipxwan_routing_type, tvb,
206                                             offset, 1, FALSE);
207                                 }
208                                 break;
209
210                         case OPT_RIP_SAP_INFO_EXCHANGE:
211                                 if (option_data_len != 54) {
212                                         proto_tree_add_text(option_tree,
213                                             tvb, offset, option_data_len,
214                                             "Bogus length: %u, should be 54",
215                                             option_data_len);
216                                 } else {
217                                         wan_link_delay = tvb_get_ntohs(tvb,
218                                             offset);
219                                         proto_tree_add_uint_format(option_tree,
220                                             hf_ipxwan_wan_link_delay, tvb,
221                                             offset, 2, wan_link_delay,
222                                             "WAN Link Delay: %ums",
223                                             wan_link_delay);
224                                         proto_tree_add_item(option_tree,
225                                             hf_ipxwan_common_network_number,
226                                             tvb, offset+2, 4, FALSE);
227                                         proto_tree_add_item(option_tree,
228                                             hf_ipxwan_router_name, tvb,
229                                             offset+6, 48, FALSE);
230                                 }
231                                 break;
232
233                         case OPT_NLSP_INFORMATION:
234                                 if (option_data_len != 8) {
235                                         proto_tree_add_text(option_tree,
236                                             tvb, offset, option_data_len,
237                                             "Bogus length: %u, should be 8",
238                                             option_data_len);
239                                 } else {
240                                         delay = tvb_get_ntohl(tvb, offset);
241                                         proto_tree_add_uint_format(option_tree,
242                                             hf_ipxwan_delay, tvb,
243                                             offset, 4, delay,
244                                             "Delay: %uus", delay);
245                                         throughput = tvb_get_ntohl(tvb, offset);
246                                         proto_tree_add_uint_format(option_tree,
247                                             hf_ipxwan_throughput, tvb,
248                                             offset, 4, throughput,
249                                             "Throughput: %uus",
250                                             throughput);
251                                 }
252                                 break;
253
254                         case OPT_NLSP_RAW_THROUGHPUT_DATA:
255                                 if (option_data_len != 8) {
256                                         proto_tree_add_text(option_tree,
257                                             tvb, offset, option_data_len,
258                                             "Bogus length: %u, should be 8",
259                                             option_data_len);
260                                 } else {
261                                         proto_tree_add_item(option_tree,
262                                             hf_ipxwan_request_size, tvb,
263                                             offset, 4, FALSE);
264                                         delta_time = tvb_get_ntohl(tvb, offset);
265                                         proto_tree_add_uint_format(option_tree,
266                                             hf_ipxwan_delta_time, tvb,
267                                             offset, 4, delta_time,
268                                             "Delta Time: %uus",
269                                             delta_time);
270                                 }
271                                 break;
272
273                         case OPT_EXTENDED_NODE_ID:
274                                 if (option_data_len != 4) {
275                                         proto_tree_add_text(option_tree,
276                                             tvb, offset, option_data_len,
277                                             "Bogus length: %u, should be 4",
278                                             option_data_len);
279                                 } else {
280                                         proto_tree_add_item(option_tree,
281                                             hf_ipxwan_extended_node_id, tvb,
282                                             offset, 4, FALSE);
283                                 }
284                                 break;
285
286                         case OPT_NODE_NUMBER:
287                                 if (option_data_len != 6) {
288                                         proto_tree_add_text(option_tree,
289                                             tvb, offset, option_data_len,
290                                             "Bogus length: %u, should be 6",
291                                             option_data_len);
292                                 } else {
293                                         proto_tree_add_item(option_tree,
294                                             hf_ipxwan_node_number, tvb,
295                                             offset, 6, FALSE);
296                                 }
297                                 break;
298
299                         case OPT_COMPRESSION:
300                                 if (option_data_len < 1) {
301                                         proto_tree_add_text(option_tree,
302                                             tvb, offset, option_data_len,
303                                             "Bogus length: %u, should be >= 1",
304                                             option_data_len);
305                                 } else {
306                                         compression_type = tvb_get_guint8(tvb,
307                                             offset);
308                                         proto_tree_add_uint(option_tree,
309                                             hf_ipxwan_compression_type, tvb,
310                                             offset, 1, compression_type);
311                                         switch (compression_type) {
312
313                                         case COMP_TYPE_TELEBIT:
314                                                 if (option_data_len < 3) {
315                                                         proto_tree_add_text(option_tree,
316                                                             tvb, offset+1,
317                                                             option_data_len-1,
318                                                             "Bogus length: %u, should be >= 3",
319                                                             option_data_len);
320                                                 } else {
321                                                         proto_tree_add_text(
322                                                             option_tree,
323                                                             tvb, offset+1, 1,
324                                                             "Compression options: 0x%02x",
325                                                             tvb_get_guint8(tvb,
326                                                                 offset+1));
327                                                         proto_tree_add_text(
328                                                             option_tree,
329                                                             tvb, offset+2, 1,
330                                                             "Number of compression slots: %u",
331                                                             tvb_get_guint8(tvb,
332                                                                 offset+2));
333                                                 }
334                                                 break;
335
336                                         default:
337                                                 proto_tree_add_text(option_tree,
338                                                     tvb, offset+1,
339                                                     option_data_len-1,
340                                                     "Option parameters");
341                                                 break;
342                                         }
343                                 }
344                                 break;
345
346                         case OPT_PAD:
347                                 proto_tree_add_text(option_tree,
348                                     tvb, offset, option_data_len,
349                                     "Padding");
350                                 break;
351
352                         default:
353                                 proto_tree_add_text(option_tree,
354                                     tvb, offset, option_data_len,
355                                     "Option value");
356                                 break;
357                         }
358
359                         offset += option_data_len;
360                         num_options--;
361                 }
362         }
363 }
364
365 void
366 proto_register_ipxwan(void)
367 {
368         static hf_register_info hf[] = {
369             { &hf_ipxwan_identifier,
370               { "Identifier",   "ipxwan.identifier",
371                 FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
372
373             { &hf_ipxwan_packet_type,
374               { "Packet Type", "ipxwan.packet_type",
375                 FT_UINT8, BASE_DEC, VALS(ipxwan_packet_type_vals), 0x0, "",
376                 HFILL }},
377
378             { &hf_ipxwan_node_id,
379               { "Node ID", "ipxwan.node_id", FT_UINT32,
380                  BASE_HEX, NULL, 0x0, "", HFILL }},
381
382             { &hf_ipxwan_sequence_number,
383               { "Sequence Number", "ipxwan.sequence_number", FT_UINT8,
384                  BASE_DEC, NULL, 0x0, "", HFILL }},
385
386             { &hf_ipxwan_num_options,
387               { "Number of Options", "ipxwan.num_options", FT_UINT8,
388                  BASE_DEC, NULL, 0x0, "", HFILL }},
389
390             { &hf_ipxwan_option_num,
391               { "Option Number", "ipxwan.option_num", FT_UINT8,
392                  BASE_HEX, VALS(ipxwan_option_num_vals), 0x0, "", HFILL }},
393
394             { &hf_ipxwan_accept_option,
395               { "Accept Option", "ipxwan.accept_option", FT_UINT8,
396                  BASE_DEC, VALS(ipxwan_accept_option_vals), 0x0, "", HFILL }},
397
398             { &hf_ipxwan_option_data_len,
399               { "Option Data Length", "ipxwan.option_data_len", FT_UINT16,
400                  BASE_DEC, NULL, 0x0, "", HFILL }},
401
402             { &hf_ipxwan_routing_type,
403               { "Routing Type", "ipxwan.routing_type", FT_UINT8,
404                  BASE_DEC, VALS(ipxwan_routing_type_vals), 0x0, "", HFILL }},
405
406             { &hf_ipxwan_wan_link_delay,
407               { "WAN Link Delay", "ipxwan.rip_sap_info_exchange.wan_link_delay",
408                  FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
409
410             { &hf_ipxwan_common_network_number,
411               { "Common Network Number", "ipxwan.rip_sap_info_exchange.common_network_number",
412                  FT_IPXNET, BASE_NONE, NULL, 0x0, "", HFILL }},
413
414             { &hf_ipxwan_router_name,
415               { "Router Name", "ipxwan.rip_sap_info_exchange.router_name",
416                  FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
417
418             { &hf_ipxwan_delay,
419               { "Delay", "ipxwan.nlsp_information.delay",
420                  FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
421
422             { &hf_ipxwan_throughput,
423               { "Throughput", "ipxwan.nlsp_information.throughput",
424                  FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
425
426             { &hf_ipxwan_request_size,
427               { "Request Size", "ipxwan.nlsp_raw_throughput_data.request_size",
428                  FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
429
430             { &hf_ipxwan_delta_time,
431               { "Delta Time", "ipxwan.nlsp_raw_throughput_data.delta_time",
432                  FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
433
434             { &hf_ipxwan_extended_node_id,
435               { "Extended Node ID", "ipxwan.extended_node_id",
436                  FT_IPXNET, BASE_NONE, NULL, 0x0, "", HFILL }},
437
438             { &hf_ipxwan_node_number,
439               { "Node Number", "ipxwan.node_number",
440                  FT_ETHER, BASE_NONE, NULL, 0x0, "", HFILL }},
441
442             { &hf_ipxwan_compression_type,
443               { "Compression Type", "ipxwan.compression.type",
444                  FT_UINT8, BASE_DEC, VALS(ipxwan_compression_type_vals), 0x0,
445                  "", HFILL }},
446         };
447         static gint *ett[] = {
448                 &ett_ipxwan,
449                 &ett_ipxwan_option,
450         };
451
452         proto_ipxwan = proto_register_protocol("IPX WAN", "IPX WAN", "ipxwan");
453         proto_register_field_array(proto_ipxwan, hf, array_length(hf));
454         proto_register_subtree_array(ett, array_length(ett));
455 }
456
457 void
458 proto_reg_handoff_ipxwan(void)
459 {
460         dissector_handle_t ipxwan_handle;
461
462         ipxwan_handle = create_dissector_handle(dissect_ipxwan,
463             proto_ipxwan);
464         dissector_add("ipx.socket", IPX_SOCKET_IPXWAN, ipxwan_handle);
465 }