Mark requests as such in the Info column.
[obnox/wireshark/wip.git] / packet-ipx.c
1 /* packet-ipx.c
2  * Routines for NetWare's IPX
3  * Gilbert Ramirez <gram@alumni.rice.edu>
4  *
5  * $Id: packet-ipx.c,v 1.103 2002/04/24 06:03:34 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  * 
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  * 
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  * 
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #ifdef HAVE_SYS_TYPES_H
31 # include <sys/types.h>
32 #endif
33
34 #include <stdio.h>
35 #include <string.h>
36 #include <glib.h>
37 #include <epan/packet.h>
38 #include "packet-ipx.h"
39 #include <epan/resolv.h>
40 #include "etypes.h"
41 #include "ppptypes.h"
42 #include "llcsaps.h"
43 #include "aftypes.h"
44
45 /* The information in this module (IPX, SPX, NCP) comes from:
46         NetWare LAN Analysis, Second Edition
47         Laura A. Chappell and Dan E. Hakes
48         (c) 1994 Novell, Inc.
49         Novell Press, San Jose.
50         ISBN: 0-7821-1362-1
51
52   And from the ncpfs source code by Volker Lendecke
53
54 */
55         
56 static int proto_ipx = -1;
57 static int hf_ipx_checksum = -1;
58 static int hf_ipx_len = -1;
59 static int hf_ipx_hops = -1;
60 static int hf_ipx_packet_type = -1;
61 static int hf_ipx_dnet = -1;
62 static int hf_ipx_dnode = -1;
63 static int hf_ipx_dsocket = -1;
64 static int hf_ipx_snet = -1;
65 static int hf_ipx_snode = -1;
66 static int hf_ipx_ssocket = -1;
67
68 static gint ett_ipx = -1;
69
70 static dissector_table_t ipx_type_dissector_table;
71 static dissector_table_t ipx_socket_dissector_table;
72
73 static int proto_spx = -1;
74 static int hf_spx_connection_control = -1;
75 static int hf_spx_datastream_type = -1;
76 static int hf_spx_src_id = -1;
77 static int hf_spx_dst_id = -1;
78 static int hf_spx_seq_nr = -1;
79 static int hf_spx_ack_nr = -1;
80 static int hf_spx_all_nr = -1;
81
82 static gint ett_spx = -1;
83
84 static int proto_ipxrip = -1;
85 static int hf_ipxrip_request = -1;
86 static int hf_ipxrip_response = -1;
87
88 static gint ett_ipxrip = -1;
89
90 static int proto_sap = -1;
91 static int hf_sap_request = -1;
92 static int hf_sap_response = -1;
93
94 static gint ett_ipxsap = -1;
95 static gint ett_ipxsap_server = -1;
96
97 static gint ett_ipxmsg = -1;
98 static int proto_ipxmsg = -1;
99 static int hf_msg_conn = -1;
100 static int hf_msg_sigchar = -1;
101
102 static dissector_handle_t data_handle;
103
104 static void
105 dissect_spx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
106
107 static void
108 dissect_ipxrip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
109
110 static void
111 dissect_ipxsap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
112
113 static void
114 dissect_ipxmsg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
115
116 #define UDP_PORT_IPX    213             /* RFC 1234 */
117
118 #define IPX_HEADER_LEN  30              /* It's *always* 30 bytes */
119
120 /* ================================================================= */
121 /* IPX                                                               */
122 /* ================================================================= */
123 static const value_string ipx_socket_vals[] = {
124         { IPX_SOCKET_PING_CISCO,                "CISCO PING" },
125         { IPX_SOCKET_NCP,                       "NCP" },
126         { IPX_SOCKET_SAP,                       "SAP" },
127         { IPX_SOCKET_IPXRIP,                    "RIP" },
128         { IPX_SOCKET_NETBIOS,                   "NetBIOS" },
129         { IPX_SOCKET_DIAGNOSTIC,                "Diagnostic" },
130         { IPX_SOCKET_SERIALIZATION,             "Serialization" },
131         { IPX_SOCKET_NWLINK_SMB_SERVER,         "NWLink SMB Server" },
132         { IPX_SOCKET_NWLINK_SMB_NAMEQUERY,      "NWLink SMB Name Query" },
133         { IPX_SOCKET_NWLINK_SMB_REDIR,          "NWLink SMB Redirector" },
134         { IPX_SOCKET_NWLINK_SMB_MAILSLOT,       "NWLink SMB Mailslot Datagram" },
135         { IPX_SOCKET_NWLINK_SMB_MESSENGER,      "NWLink SMB Messenger" },
136         { IPX_SOCKET_NWLINK_SMB_BROWSE,         "NWLink SMB Browse" },
137         { IPX_SOCKET_ATTACHMATE_GW,             "Attachmate Gateway" },
138         { IPX_SOCKET_IPX_MESSAGE,               "IPX Message" },
139         { IPX_SOCKET_SNMP_AGENT,                "SNMP Agent" },
140         { IPX_SOCKET_SNMP_SINK,                 "SNMP Sink" },
141         { IPX_SOCKET_PING_NOVELL,               "Novell PING" },
142         { IPX_SOCKET_UDP_TUNNEL,                "UDP Tunnel" },
143         { IPX_SOCKET_TCP_TUNNEL,                "TCP Tunnel" },
144         { IPX_SOCKET_TCP_TUNNEL,                "TCP Tunnel" },
145         { IPX_SOCKET_ADSM,                      "ADSM" },
146         { IPX_SOCKET_EIGRP,                     "Cisco EIGRP for IPX" },
147         { IPX_SOCKET_WIDE_AREA_ROUTER,          "Wide Area Router" },
148         { 0xE885,                               "NT Server-RPC/GW" },
149         { 0x400C,                               "HP LaserJet/QuickSilver" },
150         { 0x907B,                               "SMS Testing and Development" },
151         { 0x8F83,                               "Powerchute UPS Monitoring" },
152         { 0x4006,                               "Netware Directory Server" },
153         { 0x8104,                               "Netware 386" },
154         { 0x0000,                               NULL }
155 };
156
157 static const char*
158 socket_text(guint16 socket)
159 {
160         return val_to_str(socket, ipx_socket_vals, "Unknown");
161 }
162
163 static const value_string ipx_packet_type_vals[] = {
164         { IPX_PACKET_TYPE_IPX,          "IPX" },
165         { IPX_PACKET_TYPE_RIP,          "RIP" },
166         { IPX_PACKET_TYPE_ECHO,         "Echo" },
167         { IPX_PACKET_TYPE_ERROR,        "Error" },
168         { IPX_PACKET_TYPE_PEP,          "PEP" }, /* Packet Exchange Packet */
169         { IPX_PACKET_TYPE_SPX,          "SPX" },
170         { 16,                           "Experimental Protocol" },
171         { IPX_PACKET_TYPE_NCP,          "NCP" },
172         { 18,                           "Experimental Protocol" },
173         { 19,                           "Experimental Protocol" },
174         { IPX_PACKET_TYPE_WANBCAST,     "NetBIOS Broadcast" },
175         { 21,                           "Experimental Protocol" },
176         { 22,                           "Experimental Protocol" },
177         { 23,                           "Experimental Protocol" },
178         { 24,                           "Experimental Protocol" },
179         { 25,                           "Experimental Protocol" },
180         { 26,                           "Experimental Protocol" },
181         { 27,                           "Experimental Protocol" },
182         { 28,                           "Experimental Protocol" },
183         { 29,                           "Experimental Protocol" },
184         { 30,                           "Experimental Protocol" },
185         { 31,                           "Experimental Protocol" },
186         { 0,                            NULL }
187 };
188
189 static const value_string ipxmsg_sigchar_vals[] = {
190         { '?', "Poll inactive station" },
191         { 0, NULL }
192 };
193
194 void
195 capture_ipx(packet_counts *ld)
196 {
197         ld->ipx++;
198 }
199
200 static void
201 dissect_ipx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
202 {
203         tvbuff_t        *next_tvb;
204
205         proto_tree      *ipx_tree;
206         proto_item      *ti;
207
208         const guint8    *src_net_node, *dst_net_node;
209
210         guint8          ipx_type, ipx_hops;
211         guint16         ipx_length;
212
213         guint16         ipx_dsocket, ipx_ssocket;
214
215         if (check_col(pinfo->cinfo, COL_PROTOCOL))
216                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPX");
217         if (check_col(pinfo->cinfo, COL_INFO))
218                 col_clear(pinfo->cinfo, COL_INFO);
219
220         /* Calculate here for use in pinfo and in tree */
221         ipx_dsocket     = tvb_get_ntohs(tvb, 16);
222         ipx_ssocket     = tvb_get_ntohs(tvb, 28);
223         ipx_type        = tvb_get_guint8(tvb, 5);
224         ipx_length      = tvb_get_ntohs(tvb, 2);
225
226         /* Adjust the tvbuff length to include only the IPX datagram. */
227         set_actual_length(tvb, ipx_length);
228
229         src_net_node = tvb_get_ptr(tvb, 18, 10);
230         dst_net_node = tvb_get_ptr(tvb, 6,  10);
231
232         SET_ADDRESS(&pinfo->net_src,    AT_IPX, 10, src_net_node);
233         SET_ADDRESS(&pinfo->src,        AT_IPX, 10, src_net_node);
234         SET_ADDRESS(&pinfo->net_dst,    AT_IPX, 10, dst_net_node);
235         SET_ADDRESS(&pinfo->dst,        AT_IPX, 10, dst_net_node);
236
237         if (check_col(pinfo->cinfo, COL_INFO))
238                 col_add_fstr(pinfo->cinfo, COL_INFO, "%s (0x%04x)",
239                                 socket_text(ipx_dsocket), ipx_dsocket);
240
241         if (tree) {
242
243                 ti = proto_tree_add_item(tree, proto_ipx, tvb, 0, IPX_HEADER_LEN, FALSE);
244                 ipx_tree = proto_item_add_subtree(ti, ett_ipx);
245
246                 proto_tree_add_item(ipx_tree, hf_ipx_checksum, tvb, 0, 2, FALSE);
247                 proto_tree_add_uint_format(ipx_tree, hf_ipx_len, tvb, 2, 2, ipx_length,
248                         "Length: %d bytes", ipx_length);
249                 ipx_hops = tvb_get_guint8(tvb, 4);
250                 proto_tree_add_uint_format(ipx_tree, hf_ipx_hops, tvb, 4, 1, ipx_hops,
251                         "Transport Control: %d hops", ipx_hops);
252                 proto_tree_add_uint(ipx_tree, hf_ipx_packet_type, tvb, 5, 1, ipx_type);
253
254                 /* Destination */
255                 proto_tree_add_item(ipx_tree, hf_ipx_dnet, tvb, 6, 4, FALSE);
256                 proto_tree_add_item(ipx_tree, hf_ipx_dnode, tvb, 10, 6, FALSE);
257                 proto_tree_add_uint(ipx_tree, hf_ipx_dsocket, tvb, 16, 2,
258                         ipx_dsocket);
259
260                 /* Source */
261                 proto_tree_add_item(ipx_tree, hf_ipx_snet, tvb, 18, 4, FALSE);
262                 proto_tree_add_item(ipx_tree, hf_ipx_snode, tvb, 22, 6, FALSE);
263                 proto_tree_add_uint(ipx_tree, hf_ipx_ssocket, tvb, 28, 2,
264                         ipx_ssocket);
265         }
266
267         /* Make the next tvbuff */
268         next_tvb = tvb_new_subset(tvb, IPX_HEADER_LEN, -1, -1);
269
270         if (dissector_try_port(ipx_type_dissector_table, ipx_type, next_tvb,
271             pinfo, tree))
272                 return;
273
274         /*
275          * Let the subdissector know what type of IPX packet this is.
276          */
277         pinfo->ipxptype = ipx_type;
278
279         if (dissector_try_port(ipx_socket_dissector_table, ipx_dsocket,
280             next_tvb, pinfo, tree))
281                 return;
282         if (dissector_try_port(ipx_socket_dissector_table, ipx_ssocket,
283             next_tvb, pinfo, tree))
284                 return;
285         call_dissector(data_handle,next_tvb, pinfo, tree);
286 }
287
288
289 /* ================================================================= */
290 /* SPX                                                               */
291 /* ================================================================= */
292 static const char*
293 spx_conn_ctrl(guint8 ctrl)
294 {
295         const char *p;
296
297         static const value_string conn_vals[] = {
298                 { 0x10, "End-of-Message" },
299                 { 0x20, "Attention" },
300                 { 0x40, "Acknowledgment Required"},
301                 { 0x80, "System Packet"},
302                 { 0x00, NULL }
303         };
304
305         p = match_strval(ctrl, conn_vals);
306
307         if (p) {
308                 return p;
309         }
310         else {
311                 return "Unknown";
312         }
313 }
314
315 static const char*
316 spx_datastream(guint8 type)
317 {
318         switch (type) {
319                 case 0xfe:
320                         return "End-of-Connection";
321                 case 0xff:
322                         return "End-of-Connection Acknowledgment";
323                 default:
324                         return "Client-Defined";
325         }
326 }
327
328 #define SPX_HEADER_LEN  12
329
330 static void
331 dissect_spx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
332 {
333         proto_tree      *spx_tree;
334         proto_item      *ti;
335         tvbuff_t        *next_tvb;
336
337         guint8          conn_ctrl;
338         guint8          datastream_type;
339
340         if (check_col(pinfo->cinfo, COL_PROTOCOL))
341                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SPX");
342         if (check_col(pinfo->cinfo, COL_INFO))
343                 col_set_str(pinfo->cinfo, COL_INFO, "SPX");
344
345         if (tree) {
346                 ti = proto_tree_add_item(tree, proto_spx, tvb, 0, SPX_HEADER_LEN, FALSE);
347                 spx_tree = proto_item_add_subtree(ti, ett_spx);
348
349                 conn_ctrl = tvb_get_guint8(tvb, 0);
350                 proto_tree_add_uint_format(spx_tree, hf_spx_connection_control, tvb,
351                                            0, 1, conn_ctrl,
352                                            "Connection Control: %s (0x%02X)",
353                                            spx_conn_ctrl(conn_ctrl), conn_ctrl);
354
355                 datastream_type = tvb_get_guint8(tvb, 1);
356                 proto_tree_add_uint_format(spx_tree, hf_spx_datastream_type, tvb,
357                                            1, 1, datastream_type,
358                                            "Datastream Type: %s (0x%02X)",
359                                            spx_datastream(datastream_type), datastream_type);
360
361                 proto_tree_add_item(spx_tree, hf_spx_src_id, tvb,  2, 2, FALSE);
362                 proto_tree_add_item(spx_tree, hf_spx_dst_id, tvb,  4, 2, FALSE);
363                 proto_tree_add_item(spx_tree, hf_spx_seq_nr, tvb,  6, 2, FALSE);
364                 proto_tree_add_item(spx_tree, hf_spx_ack_nr, tvb,  8, 2, FALSE);
365                 proto_tree_add_item(spx_tree, hf_spx_all_nr, tvb, 10, 2, FALSE);
366
367                 next_tvb = tvb_new_subset(tvb, SPX_HEADER_LEN, -1, -1);
368                 call_dissector(data_handle,next_tvb, pinfo, tree);
369         }
370 }
371
372 /* ================================================================= */
373 /* IPX Message                                                       */
374 /* ================================================================= */
375 static void
376 dissect_ipxmsg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
377 {
378         proto_tree      *msg_tree;
379         proto_item      *ti;
380         guint8          conn_number, sig_char;
381
382         if (check_col(pinfo->cinfo, COL_PROTOCOL))
383                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPX MSG");
384         if (check_col(pinfo->cinfo, COL_INFO))
385                 col_clear(pinfo->cinfo, COL_INFO);
386
387         conn_number = tvb_get_guint8(tvb, 0);
388         sig_char = tvb_get_guint8(tvb, 1);
389
390         if (check_col(pinfo->cinfo, COL_INFO)) {
391                 col_add_fstr(pinfo->cinfo, COL_INFO, 
392                         "%s, Connection %d", 
393                         val_to_str(sig_char, ipxmsg_sigchar_vals, "Unknown Signature Char"), conn_number);
394         }
395
396         if (tree) {
397                 ti = proto_tree_add_item(tree, proto_ipxmsg, tvb, 0, -1, FALSE);
398                 msg_tree = proto_item_add_subtree(ti, ett_ipxmsg);
399
400                 proto_tree_add_uint(msg_tree, hf_msg_conn, tvb, 0, 1, conn_number);
401                 proto_tree_add_uint(msg_tree, hf_msg_sigchar, tvb, 1, 1, sig_char);
402         }
403 }
404
405
406 /* ================================================================= */
407 /* IPX RIP                                                           */
408 /* ================================================================= */
409 static void
410 dissect_ipxrip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
411 {
412         proto_tree      *rip_tree;
413         proto_item      *ti;
414         guint16         operation;
415         struct ipx_rt_def route;
416         int             cursor;
417         int             available_length;
418
419         static char     *rip_type[3] = { "Request", "Response", "Unknown" };
420
421         if (check_col(pinfo->cinfo, COL_PROTOCOL))
422                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPX RIP");
423         if (check_col(pinfo->cinfo, COL_INFO))
424                 col_clear(pinfo->cinfo, COL_INFO);
425
426         operation = tvb_get_ntohs(tvb, 0) - 1;
427
428         if (check_col(pinfo->cinfo, COL_INFO)) {
429                 /* rip_types 0 and 1 are valid, anything else becomes 2 or "Unknown" */
430                 col_set_str(pinfo->cinfo, COL_INFO, rip_type[MIN(operation, 2)]);
431         }
432
433         if (tree) {
434                 ti = proto_tree_add_item(tree, proto_ipxrip, tvb, 0, -1, FALSE);
435                 rip_tree = proto_item_add_subtree(ti, ett_ipxrip);
436
437                 if (operation < 2) {
438                         proto_tree_add_text(rip_tree, tvb, 0, 2,
439                         "RIP packet type: %s", rip_type[operation]);
440
441                         if (operation == 0) {
442                           proto_tree_add_boolean_hidden(rip_tree, 
443                                                      hf_ipxrip_request, 
444                                                      tvb, 0, 2, 1);
445                         } else {
446                           proto_tree_add_boolean_hidden(rip_tree, 
447                                                      hf_ipxrip_response, 
448                                                      tvb, 0, 2, 1);
449                         }
450
451                 }
452                 else {
453                         proto_tree_add_text(rip_tree, tvb, 0, 2, "Unknown RIP packet type");
454                 }
455
456                 available_length = tvb_reported_length(tvb);
457                 for (cursor =  2; cursor < available_length; cursor += 8) {
458                         tvb_memcpy(tvb, (guint8 *)&route.network, cursor, 4);
459                         route.hops = tvb_get_ntohs(tvb, cursor+4);
460                         route.ticks = tvb_get_ntohs(tvb, cursor+6);
461
462                         if (operation == IPX_RIP_REQUEST - 1) {
463                                 proto_tree_add_text(rip_tree, tvb, cursor,      8,
464                                         "Route Vector: %s, %d hop%s, %d tick%s",
465                                         ipxnet_to_string((guint8*)&route.network),
466                                         route.hops,  route.hops  == 1 ? "" : "s",
467                                         route.ticks, route.ticks == 1 ? "" : "s");
468                         }
469                         else {
470                                 proto_tree_add_text(rip_tree, tvb, cursor,      8,
471                                         "Route Vector: %s, %d hop%s, %d tick%s (%d ms)",
472                                         ipxnet_to_string((guint8*)&route.network),
473                                         route.hops,  route.hops  == 1 ? "" : "s",
474                                         route.ticks, route.ticks == 1 ? "" : "s",
475                                         route.ticks * 1000 / 18);
476                         }
477                 }
478         }
479 }
480
481
482
483 /* ================================================================= */
484 /* SAP                                                                   */
485 /* ================================================================= */
486 static const char*
487 server_type(guint16 type)
488 {
489         const char *p;
490
491         /*
492          * Some of these are from ncpfs, others are from the book,
493          * others are from the page at
494          *
495          *      http://www.iana.org/assignments/novell-sap-numbers
496          *
497          * and some from the page at
498          *
499          *      http://www.rware.demon.co.uk/ipxsap.htm
500          *
501          * (see also the page at
502          *
503          *      http://developer.novell.com/research/appnotes/1998/february/03/06.htm
504          *
505          * which has a huge list - but many of the entries list only the
506          * organization owning the SAP type, not what the type is for).
507          */
508         static const value_string server_vals[] = {
509                 { 0x0000,       "Unknown" },
510                 { 0x0001,       "User" },
511                 { 0x0002,       "User Group" },
512                 { 0x0003,       "Print Queue or Print Group" },
513                 { 0x0004,       "File Server (SLIST source)" },
514                 { 0x0005,       "Job Server" },
515                 { 0x0006,       "Gateway" },
516                 { 0x0007,       "Print Server or Silent Print Server" },
517                 { 0x0008,       "Archive Queue" },
518                 { 0x0009,       "Archive Server" },
519                 { 0x000a,       "Job Queue" },
520                 { 0x000b,       "Administration" },
521                 { 0x000F,       "Novell TI-RPC" },
522                 { 0x0017,       "Diagnostics" },
523                 { 0x0020,       "NetBIOS" },
524                 { 0x0021,       "NAS SNA Gateway" },
525                 { 0x0023,       "NACS Async Gateway or Asynchronous Gateway" },
526                 { 0x0024,       "Remote Bridge or Routing Service" },
527                 { 0x0026,       "Bridge Server or Asynchronous Bridge Server" },
528                 { 0x0027,       "TCP/IP Gateway Server" },
529                 { 0x0028,       "Point to Point (Eicon) X.25 Bridge Server" },
530                 { 0x0029,       "Eicon 3270 Gateway" },
531                 { 0x002a,       "CHI Corp" },
532                 { 0x002c,       "PC Chalkboard" },
533                 { 0x002d,       "Time Synchronization Server or Asynchronous Timer" },
534                 { 0x002e,       "ARCserve 5.0 / Palindrome Backup Director 4.x (PDB4)" },
535                 { 0x0045,       "DI3270 Gateway" },
536                 { 0x0047,       "Advertising Print Server" },
537                 { 0x004a,       "NetBlazer Modems" },
538                 { 0x004b,       "Btrieve VAP/NLM 5.0" },
539                 { 0x004c,       "Netware SQL VAP/NLM Server" },
540                 { 0x004d,       "Xtree Network Version/Netware XTree" },
541                 { 0x0050,       "Btrieve VAP 4.11" },
542                 { 0x0052,       "QuickLink (Cubix)" },
543                 { 0x0053,       "Print Queue User" },
544                 { 0x0058,       "Multipoint X.25 Eicon Router" },
545                 { 0x0060,       "STLB/NLM" },
546                 { 0x0064,       "ARCserve" },
547                 { 0x0066,       "ARCserve 3.0" },
548                 { 0x0072,       "WAN Copy Utility" },
549                 { 0x007a,       "TES-Netware for VMS" },
550                 { 0x0092,       "WATCOM Debugger or Emerald Tape Backup Server" },
551                 { 0x0095,       "DDA OBGYN" },
552                 { 0x0098,       "Netware Access Server (Asynchronous gateway)" },
553                 { 0x009a,       "Netware for VMS II or Named Pipe Server" },
554                 { 0x009b,       "Netware Access Server" },
555                 { 0x009e,       "Portable Netware Server or SunLink NVT" },
556                 { 0x00a1,       "Powerchute APC UPS NLM" },
557                 { 0x00aa,       "LAWserve" },
558                 { 0x00ac,       "Compaq IDA Status Monitor" },
559                 { 0x0100,       "PIPE STAIL" },
560                 { 0x0102,       "LAN Protect Bindery" },
561                 { 0x0103,       "Oracle DataBase Server" },
562                 { 0x0107,       "Netware 386 or RSPX Remote Console" },
563                 { 0x010f,       "Novell SNA Gateway" },
564                 { 0x0111,       "Test Server" },
565                 { 0x0112,       "Print Server (HP)" },
566                 { 0x0114,       "CSA MUX (f/Communications Executive)" },
567                 { 0x0115,       "CSA LCA (f/Communications Executive)" },
568                 { 0x0116,       "CSA CM (f/Communications Executive)" },
569                 { 0x0117,       "CSA SMA (f/Communications Executive)" },
570                 { 0x0118,       "CSA DBA (f/Communications Executive)" },
571                 { 0x0119,       "CSA NMA (f/Communications Executive)" },
572                 { 0x011a,       "CSA SSA (f/Communications Executive)" },
573                 { 0x011b,       "CSA STATUS (f/Communications Executive)" },
574                 { 0x011e,       "CSA APPC (f/Communications Executive)" },
575                 { 0x0126,       "SNA TEST SSA Profile" },
576                 { 0x012a,       "CSA TRACE (f/Communications Executive)" },
577                 { 0x012b,       "Netware for SAA" },
578                 { 0x012e,       "IKARUS virus scan utility" },
579                 { 0x0130,       "Communications Executive" },
580                 { 0x0133,       "NNS Domain Server or Netware Naming Services Domain" },
581                 { 0x0135,       "Netware Naming Services Profile" },
582                 { 0x0137,       "Netware 386 Print Queue or NNS Print Queue" },
583                 { 0x0141,       "LAN Spool Server (Vap, Intel)" },
584                 { 0x0152,       "IRMALAN Gateway" },
585                 { 0x0154,       "Named Pipe Server" },
586                 { 0x0166,       "NetWare Management" },
587                 { 0x0168,       "Intel PICKIT Comm Server or Intel CAS Talk Server" },
588                 { 0x0173,       "Compaq" },
589                 { 0x0174,       "Compaq SNMP Agent" },
590                 { 0x0175,       "Compaq" },
591                 { 0x0180,       "XTree Server or XTree Tools" },
592                 { 0x018A,       "NASI services broadcast server (Novell)" },
593                 { 0x01b0,       "GARP Gateway (net research)" },
594                 { 0x01b1,       "Binfview (Lan Support Group)" },
595                 { 0x01bf,       "Intel LanDesk Manager" },
596                 { 0x01ca,       "AXTEC" },
597                 { 0x01cb,       "Shiva NetModem/E" },
598                 { 0x01cc,       "Shiva LanRover/E" },
599                 { 0x01cd,       "Shiva LanRover/T" },
600                 { 0x01ce,       "Shiva Universal" },
601                 { 0x01d8,       "Castelle FAXPress Server" },
602                 { 0x01da,       "Castelle LANPress Print Server" },
603                 { 0x01dc,       "Castelle FAX/Xerox 7033 Fax Server/Excel Lan Fax" },
604                 { 0x01f0,       "LEGATO" },
605                 { 0x01f5,       "LEGATO" },
606                 { 0x0233,       "NMS Agent or Netware Management Agent" },
607                 { 0x0237,       "NMS IPX Discovery or LANtern Read/Write Channel" },
608                 { 0x0238,       "NMS IP Discovery or LANtern Trap/Alarm Channel" },
609                 { 0x023a,       "LANtern" },
610                 { 0x023c,       "MAVERICK" },
611                 { 0x023f,       "SMS Testing and Development" },
612                 { 0x024e,       "Netware Connect" },
613                 { 0x024f,       "NASI server broadcast (Cisco)" },
614                 { 0x026a,       "Network Management (NMS) Service Console" },
615                 { 0x026b,       "Time Synchronization Server (Netware 4.x)" },
616                 { 0x0278,       "Directory Server (Netware 4.x)" },
617                 { 0x027b,       "Netware Management Agent" },
618                 { 0x0280,       "Novell File and Printer Sharing Service for PC" },
619                 { 0x0304,       "Novell SAA Gateway" },
620                 { 0x0308,       "COM or VERMED 1" },
621                 { 0x030a,       "Galacticomm's Worldgroup Server" },
622                 { 0x030c,       "Intel Netport 2 or HP JetDirect or HP Quicksilver" },
623                 { 0x0320,       "Attachmate Gateway" },
624                 { 0x0327,       "Microsoft Diagnostics" },
625                 { 0x0328,       "WATCOM SQL server" },
626                 { 0x0335,       "MultiTech Systems Multisynch Comm Server" },
627                 { 0x0343,       "Xylogics Remote Access Server or LAN Modem" },
628                 { 0x0355,       "Arcada Backup Exec" },
629                 { 0x0358,       "MSLCD1" },
630                 { 0x0361,       "NETINELO" },
631                 { 0x037e,       "Powerchute UPS Monitoring" },
632                 { 0x037f,       "ViruSafe Notify" },
633                 { 0x0386,       "HP Bridge" },
634                 { 0x0387,       "HP Hub" },
635                 { 0x0394,       "NetWare SAA Gateway" },
636                 { 0x039b,       "Lotus Notes" },
637                 { 0x03b7,       "Certus Anti Virus NLM" },
638                 { 0x03c4,       "ARCserve 4.0 (Cheyenne)" },
639                 { 0x03c7,       "LANspool 3.5 (Intel)" },
640                 { 0x03d7,       "Lexmark printer server (type 4033-011)" },
641                 { 0x03d8,       "Lexmark XLE printer server (type 4033-301)" },
642                 { 0x03dd,       "Banyan ENS for Netware Client NLM" },
643                 { 0x03de,       "Gupta Sequel Base Server or NetWare SQL" },
644                 { 0x03e1,       "Univel Unixware" },
645                 { 0x03e4,       "Univel Unixware" },
646                 { 0x03fc,       "Intel Netport" },
647                 { 0x03fd,       "Intel Print Server Queue" },
648                 { 0x040A,       "ipnServer" },
649                 { 0x040D,       "LVERRMAN" },
650                 { 0x040E,       "LVLIC" },
651                 { 0x0414,       "NET Silicon (DPI)/Kyocera" },
652                 { 0x0429,       "Site Lock Virus (Brightworks)" },
653                 { 0x0432,       "UFHELP R" },
654                 { 0x0433,       "Synoptics 281x Advanced SNMP Agent" },
655                 { 0x0444,       "Microsoft NT SNA Server" },
656                 { 0x0448,       "Oracle" },
657                 { 0x044c,       "ARCserve 5.01" },
658                 { 0x0457,       "Canon GP55 Running on a Canon GP55 network printer" },
659                 { 0x045a,       "QMS Printers" },
660                 { 0x045b,       "Dell SCSI Array (DSA) Monitor" },
661                 { 0x0491,       "NetBlazer Modems" },
662                 { 0x04ac,       "On-Time Scheduler NLM" },
663                 { 0x04b0,       "CD-Net (Meridian)" },
664                 { 0x0513,       "Emulex NQA" },
665                 { 0x0520,       "Site Lock Checks" },
666                 { 0x0529,       "Site Lock Checks (Brightworks)" },
667                 { 0x052d,       "Citrix OS/2 App Server" },
668                 { 0x0535,       "Tektronix" },
669                 { 0x0536,       "Milan" },
670                 { 0x055d,       "Attachmate SNA gateway" },
671                 { 0x056b,       "IBM 8235 modem server" },
672                 { 0x056c,       "Shiva LanRover/E PLUS" },
673                 { 0x056d,       "Shiva LanRover/T PLUS" },
674                 { 0x0580,       "McAfee's NetShield anti-virus" },
675                 { 0x05B8,       "NLM to workstation communication (Revelation Software)" },
676                 { 0x05BA,       "Compatible Systems Routers" },
677                 { 0x05BE,       "Cheyenne Hierarchical Storage Manager" },
678                 { 0x0606,       "JCWatermark Imaging" },
679                 { 0x060c,       "AXIS Network Printer" },
680                 { 0x0610,       "Adaptec SCSI Management" },
681                 { 0x0621,       "IBM AntiVirus NLM" },
682                 { 0x0640,       "Microsoft Gateway Services for NetWare" },
683 /*              { 0x0640,       "NT Server-RPC/GW for NW/Win95 User Level Sec" }, */
684                 { 0x064e,       "Microsoft Internet Information Server" },
685                 { 0x067b,       "Microsoft Win95/98 File and Print Sharing for NetWare" },
686                 { 0x067c,       "Microsoft Win95/98 File and Print Sharing for NetWare" },
687                 { 0x076C,       "Xerox" },
688                 { 0x079b,       "Shiva LanRover/E 115" },
689                 { 0x079c,       "Shiva LanRover/T 115" },
690                 { 0x07B4,       "Cubix WorldDesk" },
691                 { 0x07c2,       "Quarterdeck IWare Connect V2.x NLM" },
692                 { 0x07c1,       "Quarterdeck IWare Connect V3.x NLM" },
693                 { 0x0810,       "ELAN License Server Demo" },
694                 { 0x0824,       "Shiva LanRover Access Switch/E" },
695                 { 0x086a,       "ISSC collector NLMs" },
696                 { 0x087f,       "ISSC DAS agent for AIX" },
697                 { 0x0880,       "Intel Netport PRO" },
698                 { 0x0881,       "Intel Netport PRO" },
699                 { 0x0b29,       "Site Lock" },
700                 { 0x0c29,       "Site Lock Applications" },
701                 { 0x0c2c,       "Licensing Server" },
702                 { 0x2101,       "Performance Technology Instant Internet" },
703                 { 0x2380,       "LAI Site Lock" },
704                 { 0x238c,       "Meeting Maker" },
705                 { 0x4808,       "Site Lock Server or Site Lock Metering VAP/NLM" },
706                 { 0x5555,       "Site Lock User" },
707                 { 0x6312,       "Tapeware" },
708                 { 0x6f00,       "Rabbit Gateway (3270)" },
709                 { 0x7703,       "MODEM" },
710                 { 0x8002,       "NetPort Printers (Intel) or LANport" },
711                 { 0x8008,       "WordPerfect Network Version" },
712                 { 0x85BE,       "Cisco Enhanced Interior Routing Protocol (EIGRP)" },
713                 { 0x8888,       "WordPerfect Network Version or Quick Network Management" },
714                 { 0x9000,       "McAfee's NetShield anti-virus" },
715                 { 0x9604,       "CSA-NT_MON" },
716                 { 0xb6a8,       "Ocean Isle Reachout Remote Control" },
717                 { 0xf11f,       "Site Lock Metering VAP/NLM" },
718                 { 0xf1ff,       "Site Lock" },
719                 { 0xf503,       "Microsoft SQL Server" },
720                 { 0xf905,       "IBM Time and Place/2 application" },
721                 { 0xfbfb,       "TopCall III fax server" },
722                 { 0xffff,       "Any Service or Wildcard" },
723                 { 0x0000,       NULL }
724         };
725
726         p = match_strval(type, server_vals);
727         if (p) {
728                 return p;
729         }
730         else {
731                 return "Unknown";
732         }
733 }
734
735 static void
736 dissect_ipxsap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
737 {
738         proto_tree      *sap_tree, *s_tree;
739         proto_item      *ti;
740         int             cursor;
741         struct sap_query query;
742         struct sap_server_ident server;
743
744         static char     *sap_type[4] = { "General Query", "General Response",
745                 "Nearest Query", "Nearest Response" };
746
747         if (check_col(pinfo->cinfo, COL_PROTOCOL))
748                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPX SAP");
749         if (check_col(pinfo->cinfo, COL_INFO))
750                 col_clear(pinfo->cinfo, COL_INFO);
751
752         query.query_type = tvb_get_ntohs(tvb, 0);
753         query.server_type = tvb_get_ntohs(tvb, 2);
754
755         if (check_col(pinfo->cinfo, COL_INFO)) {
756                 if (query.query_type >= 1 && query.query_type <= 4) {
757                         col_set_str(pinfo->cinfo, COL_INFO, sap_type[query.query_type - 1]);
758                 }
759                 else {
760                         col_set_str(pinfo->cinfo, COL_INFO, "Unknown Packet Type");
761                 }
762         }
763
764         if (tree) {
765                 ti = proto_tree_add_item(tree, proto_sap, tvb, 0, -1, FALSE);
766                 sap_tree = proto_item_add_subtree(ti, ett_ipxsap);
767
768                 if (query.query_type >= 1 && query.query_type <= 4) {
769                         proto_tree_add_text(sap_tree, tvb, 0, 2, sap_type[query.query_type - 1]);
770                         if ((query.query_type - 1) % 2) {
771                           proto_tree_add_boolean_hidden(sap_tree, 
772                                                      hf_sap_response, 
773                                                      tvb, 0, 2, 1);
774                         } else {
775                           proto_tree_add_boolean_hidden(sap_tree, 
776                                                      hf_sap_request, 
777                                                      tvb, 0, 2, 1);
778                         }
779                 }
780                 else {
781                         proto_tree_add_text(sap_tree, tvb, 0, 2,
782                                         "Unknown SAP Packet Type %d", query.query_type);
783                 }
784
785                 if (query.query_type == IPX_SAP_GENERAL_RESPONSE ||
786                                 query.query_type == IPX_SAP_NEAREST_RESPONSE) { /* responses */
787
788                         int available_length = tvb_reported_length(tvb);
789                         for (cursor =  2; (cursor + 64) <= available_length; cursor += 64) {
790                                 server.server_type = tvb_get_ntohs(tvb, cursor);
791                                 tvb_memcpy(tvb, (guint8 *)server.server_name,
792                                     cursor+2, 48);
793                                 tvb_memcpy(tvb, (guint8 *)&server.server_network,
794                                     cursor+50, 4);
795                                 tvb_memcpy(tvb, (guint8 *)&server.server_node,
796                                     cursor+54, 6);
797                                 server.server_port = tvb_get_ntohs(tvb, cursor+60);
798                                 server.intermediate_network = tvb_get_ntohs(tvb, cursor+62);
799
800                                 ti = proto_tree_add_text(sap_tree, tvb, cursor+2, 48,
801                                         "Server Name: %s", server.server_name);
802                                 s_tree = proto_item_add_subtree(ti, ett_ipxsap_server);
803
804                                 proto_tree_add_text(s_tree, tvb, cursor, 2, "Server Type: %s (0x%04X)",
805                                                 server_type(server.server_type), server.server_type);
806                                 proto_tree_add_text(s_tree, tvb, cursor+50, 4, "Network: %s",
807                                                 ipxnet_to_string((guint8*)tvb_get_ptr(tvb, cursor+50, 4)));
808                                 proto_tree_add_text(s_tree, tvb, cursor+54, 6, "Node: %s",
809                                                 ether_to_str((guint8*)tvb_get_ptr(tvb, cursor+54, 6)));
810                                 proto_tree_add_text(s_tree, tvb, cursor+60, 2, "Socket: %s (0x%04x)",
811                                                 socket_text(server.server_port), server.server_port);
812                                 proto_tree_add_text(s_tree, tvb, cursor+62, 2,
813                                                 "Intermediate Networks: %d",
814                                                 server.intermediate_network);
815                         }
816                 }
817                 else {  /* queries */
818                         proto_tree_add_text(sap_tree, tvb, 2, 2, "Server Type: %s (0x%04X)",
819                                         server_type(query.server_type), query.server_type);
820                 }
821         }
822 }
823
824 void
825 proto_register_ipx(void)
826 {
827         static hf_register_info hf_ipx[] = {
828                 { &hf_ipx_checksum,
829                 { "Checksum",           "ipx.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
830                         "", HFILL }},
831
832                 { &hf_ipx_len,
833                 { "Length",             "ipx.len", FT_UINT16, BASE_DEC, NULL, 0x0,
834                         "", HFILL }},
835
836                 { &hf_ipx_hops,
837                 { "Transport Control (Hops)", "ipx.hops", FT_UINT8, BASE_DEC, NULL, 0x0,
838                         "", HFILL }},
839
840                 { &hf_ipx_packet_type,
841                 { "Packet Type",        "ipx.packet_type", FT_UINT8, BASE_HEX, VALS(ipx_packet_type_vals),
842                         0x0,
843                         "", HFILL }},
844
845                 { &hf_ipx_dnet,
846                 { "Destination Network","ipx.dst.net", FT_IPXNET, BASE_NONE, NULL, 0x0,
847                         "", HFILL }},
848
849                 { &hf_ipx_dnode,
850                 { "Destination Node",   "ipx.dst.node", FT_ETHER, BASE_NONE, NULL, 0x0,
851                         "", HFILL }},
852
853                 { &hf_ipx_dsocket,
854                 { "Destination Socket", "ipx.dst.socket", FT_UINT16, BASE_HEX,
855                         VALS(ipx_socket_vals), 0x0,
856                         "", HFILL }},
857
858                 { &hf_ipx_snet,
859                 { "Source Network","ipx.src.net", FT_IPXNET, BASE_NONE, NULL, 0x0,
860                         "", HFILL }},
861
862                 { &hf_ipx_snode,
863                 { "Source Node",        "ipx.src.node", FT_ETHER, BASE_NONE, NULL, 0x0,
864                         "", HFILL }},
865
866                 { &hf_ipx_ssocket,
867                 { "Source Socket",      "ipx.src.socket", FT_UINT16, BASE_HEX,
868                         VALS(ipx_socket_vals), 0x0,
869                         "", HFILL }},
870         };
871
872         static hf_register_info hf_spx[] = {
873                 { &hf_spx_connection_control,
874                 { "Connection Control",         "spx.ctl", 
875                   FT_UINT8,     BASE_HEX,       NULL,   0x0,
876                   "", HFILL }},
877
878                 { &hf_spx_datastream_type,
879                 { "Datastream type",            "spx.type", 
880                   FT_UINT8,     BASE_HEX,       NULL,   0x0,
881                   "", HFILL }},
882
883                 { &hf_spx_src_id,
884                 { "Source Connection ID",       "spx.src", 
885                   FT_UINT16,    BASE_DEC,       NULL,   0x0,
886                   "", HFILL }},
887
888                 { &hf_spx_dst_id,
889                 { "Destination Connection ID",  "spx.dst", 
890                   FT_UINT16,    BASE_DEC,       NULL,   0x0,
891                   "", HFILL }},
892
893                 { &hf_spx_seq_nr,
894                 { "Sequence Number",            "spx.seq", 
895                   FT_UINT16,    BASE_DEC,       NULL,   0x0,
896                   "", HFILL }},
897
898                 { &hf_spx_ack_nr,
899                 { "Acknowledgment Number",      "spx.ack", 
900                   FT_UINT16,    BASE_DEC,       NULL,   0x0,
901                   "", HFILL }},
902
903                 { &hf_spx_all_nr,
904                 { "Allocation Number",          "spx.alloc", 
905                   FT_UINT16,    BASE_DEC,       NULL,   0x0,
906                   "", HFILL }}
907         };
908
909         static hf_register_info hf_ipxrip[] = {
910                 { &hf_ipxrip_request,
911                 { "Request",                    "ipxrip.request", 
912                   FT_BOOLEAN,   BASE_NONE,      NULL,   0x0,
913                   "TRUE if IPX RIP request", HFILL }},
914
915                 { &hf_ipxrip_response,
916                 { "Response",                   "ipxrip.response", 
917                   FT_BOOLEAN,   BASE_NONE,      NULL,   0x0,
918                   "TRUE if IPX RIP response", HFILL }}
919         };
920
921         static hf_register_info hf_sap[] = {
922                 { &hf_sap_request,
923                 { "Request",                    "ipxsap.request", 
924                   FT_BOOLEAN,   BASE_NONE,      NULL,   0x0,
925                   "TRUE if SAP request", HFILL }},
926
927                 { &hf_sap_response,
928                 { "Response",                   "ipxsap.response", 
929                   FT_BOOLEAN,   BASE_NONE,      NULL,   0x0,
930                   "TRUE if SAP response", HFILL }}
931         };
932
933         static hf_register_info hf_ipxmsg[] = {
934                 { &hf_msg_conn,
935                 { "Connection Number",                  "ipxmsg.conn", 
936                   FT_UINT8,     BASE_DEC,       NULL,   0x0,
937                   "Connection Number", HFILL }},
938
939                 { &hf_msg_sigchar,
940                 { "Signature Char",                     "ipxmsg.sigchar", 
941                   FT_UINT8,     BASE_DEC,       VALS(ipxmsg_sigchar_vals),      0x0,
942                   "Signature Char", HFILL }}
943         };
944
945         static gint *ett[] = {
946                 &ett_ipx,
947                 &ett_spx,
948                 &ett_ipxmsg,
949                 &ett_ipxrip,
950                 &ett_ipxsap,
951                 &ett_ipxsap_server,
952         };
953
954         proto_ipx = proto_register_protocol("Internetwork Packet eXchange",
955             "IPX", "ipx");
956         proto_register_field_array(proto_ipx, hf_ipx, array_length(hf_ipx));
957
958         register_dissector("ipx", dissect_ipx, proto_ipx);
959
960         proto_spx = proto_register_protocol("Sequenced Packet eXchange",
961             "SPX", "spx");
962         proto_register_field_array(proto_spx, hf_spx, array_length(hf_spx));
963
964         proto_ipxrip = proto_register_protocol("IPX Routing Information Protocol",
965             "IPX RIP", "ipxrip");
966         proto_register_field_array(proto_ipxrip, hf_ipxrip, array_length(hf_ipxrip));
967
968         proto_ipxmsg = proto_register_protocol("IPX Message", "IPX MSG",
969             "ipxmsg");
970         proto_register_field_array(proto_ipxmsg, hf_ipxmsg, array_length(hf_ipxmsg));
971
972         proto_sap = proto_register_protocol("Service Advertisement Protocol",
973             "IPX SAP", "ipxsap");
974         register_dissector("ipxsap", dissect_ipxsap, proto_sap);
975
976         proto_register_field_array(proto_sap, hf_sap, array_length(hf_sap));
977
978         proto_register_subtree_array(ett, array_length(ett));
979
980         ipx_type_dissector_table = register_dissector_table("ipx.packet_type",
981             "IPX packet type", FT_UINT8, BASE_HEX);
982         ipx_socket_dissector_table = register_dissector_table("ipx.socket",
983             "IPX socket", FT_UINT16, BASE_HEX);
984 }
985
986 void
987 proto_reg_handoff_ipx(void)
988 {
989         dissector_handle_t ipx_handle, spx_handle;
990         dissector_handle_t ipxsap_handle, ipxrip_handle;
991         dissector_handle_t ipxmsg_handle;
992
993         ipx_handle = find_dissector("ipx");
994         dissector_add("udp.port", UDP_PORT_IPX, ipx_handle);
995         dissector_add("ethertype", ETHERTYPE_IPX, ipx_handle);
996         dissector_add("chdlctype", ETHERTYPE_IPX, ipx_handle);
997         dissector_add("ppp.protocol", PPP_IPX, ipx_handle);
998         dissector_add("llc.dsap", SAP_NETWARE, ipx_handle);
999         dissector_add("null.type", BSD_AF_IPX, ipx_handle);
1000         dissector_add("gre.proto", ETHERTYPE_IPX, ipx_handle);
1001         spx_handle = create_dissector_handle(dissect_spx, proto_spx);
1002         dissector_add("ipx.packet_type", IPX_PACKET_TYPE_SPX, spx_handle);
1003         ipxsap_handle = find_dissector("ipxsap");
1004         dissector_add("ipx.socket", IPX_SOCKET_SAP, ipxsap_handle);
1005         ipxrip_handle = create_dissector_handle(dissect_ipxrip, proto_ipxrip);
1006         dissector_add("ipx.socket", IPX_SOCKET_IPXRIP, ipxrip_handle);
1007         ipxmsg_handle = create_dissector_handle(dissect_ipxmsg, proto_ipxmsg);
1008         dissector_add("ipx.socket", IPX_SOCKET_IPX_MESSAGE, ipxmsg_handle);
1009         data_handle = find_dissector("data");
1010 }