2 * Routines for NetWare's IPX
3 * Gilbert Ramirez <gram@alumni.rice.edu>
4 * NDPS support added by Greg Morris (gmorris@novell.com)
6 * Portions Copyright (c) 2000-2002 by Gilbert Ramirez.
7 * Portions Copyright (c) Novell, Inc. 2002-2003
9 * $Id: packet-ipx.c,v 1.133 2003/08/05 05:45:04 guy Exp $
11 * Ethereal - Network traffic analyzer
12 * By Gerald Combs <gerald@ethereal.com>
13 * Copyright 1998 Gerald Combs
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.
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.
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.
37 #include <epan/packet.h>
38 #include "packet-ipx.h"
39 #include <epan/resolv.h>
44 #include "arcnet_pids.h"
45 #include <epan/conversation.h>
47 #define SPX_PACKET_INIT_COUNT 200
49 /* The information in this module (IPX, SPX, NCP) comes from:
50 NetWare LAN Analysis, Second Edition
51 Laura A. Chappell and Dan E. Hakes
53 Novell Press, San Jose.
56 And from the ncpfs source code by Volker Lendecke
60 static int proto_ipx = -1;
61 static int hf_ipx_checksum = -1;
62 static int hf_ipx_len = -1;
63 static int hf_ipx_hops = -1;
64 static int hf_ipx_packet_type = -1;
65 static int hf_ipx_dnet = -1;
66 static int hf_ipx_dnode = -1;
67 static int hf_ipx_dsocket = -1;
68 static int hf_ipx_snet = -1;
69 static int hf_ipx_snode = -1;
70 static int hf_ipx_ssocket = -1;
71 static int hf_ipx_net = -1;
72 static int hf_ipx_node = -1;
73 static int hf_ipx_socket = -1;
75 static gint ett_ipx = -1;
77 static dissector_table_t ipx_type_dissector_table;
78 static dissector_table_t ipx_socket_dissector_table;
79 static dissector_table_t spx_socket_dissector_table;
81 static int proto_spx = -1;
82 static int hf_spx_connection_control = -1;
83 static int hf_spx_connection_control_sys = -1;
84 static int hf_spx_connection_control_send_ack = -1;
85 static int hf_spx_connection_control_attn = -1;
86 static int hf_spx_connection_control_eom = -1;
87 static int hf_spx_datastream_type = -1;
88 static int hf_spx_src_id = -1;
89 static int hf_spx_dst_id = -1;
90 static int hf_spx_seq_nr = -1;
91 static int hf_spx_ack_nr = -1;
92 static int hf_spx_all_nr = -1;
93 static int hf_spx_rexmt_frame = -1;
95 static gint ett_spx = -1;
96 static gint ett_spx_connctrl = -1;
98 static int proto_ipxrip = -1;
99 static int hf_ipxrip_request = -1;
100 static int hf_ipxrip_response = -1;
102 static gint ett_ipxrip = -1;
104 static int proto_sap = -1;
105 static int hf_sap_request = -1;
106 static int hf_sap_response = -1;
108 static gint ett_ipxsap = -1;
109 static gint ett_ipxsap_server = -1;
111 static gint ett_ipxmsg = -1;
112 static int proto_ipxmsg = -1;
113 static int hf_msg_conn = -1;
114 static int hf_msg_sigchar = -1;
116 static dissector_handle_t data_handle;
119 dissect_spx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
122 dissect_ipxrip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
125 dissect_ipxsap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
128 dissect_ipxmsg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
130 #define UDP_PORT_IPX 213 /* RFC 1234 */
132 #define IPX_HEADER_LEN 30 /* It's *always* 30 bytes */
134 /* ================================================================= */
136 /* ================================================================= */
137 const value_string ipx_socket_vals[] = {
138 { IPX_SOCKET_PING_CISCO, "CISCO PING" },
139 { IPX_SOCKET_NCP, "NCP" },
140 { IPX_SOCKET_SAP, "SAP" },
141 { IPX_SOCKET_IPXRIP, "RIP" },
142 { IPX_SOCKET_NETBIOS, "NetBIOS" },
143 { IPX_SOCKET_DIAGNOSTIC, "Diagnostic" },
144 { IPX_SOCKET_SERIALIZATION, "Serialization" },
145 { IPX_SOCKET_NWLINK_SMB_SERVER, "NWLink SMB Server" },
146 { IPX_SOCKET_NWLINK_SMB_NAMEQUERY, "NWLink SMB Name Query" },
147 { IPX_SOCKET_NWLINK_SMB_REDIR, "NWLink SMB Redirector" },
148 { IPX_SOCKET_NWLINK_SMB_MAILSLOT, "NWLink SMB Mailslot Datagram" },
149 { IPX_SOCKET_NWLINK_SMB_MESSENGER, "NWLink SMB Messenger" },
150 { IPX_SOCKET_NWLINK_SMB_BROWSE, "NWLink SMB Browse" },
151 { IPX_SOCKET_ATTACHMATE_GW, "Attachmate Gateway" },
152 { IPX_SOCKET_IPX_MESSAGE, "IPX Message" },
153 { IPX_SOCKET_IPX_MESSAGE1, "IPX Message" },
154 { IPX_SOCKET_SNMP_AGENT, "SNMP Agent" },
155 { IPX_SOCKET_SNMP_SINK, "SNMP Sink" },
156 { IPX_SOCKET_PING_NOVELL, "Novell PING" },
157 { IPX_SOCKET_UDP_TUNNEL, "UDP Tunnel" },
158 { IPX_SOCKET_TCP_TUNNEL, "TCP Tunnel" },
159 { IPX_SOCKET_TCP_TUNNEL, "TCP Tunnel" },
160 { IPX_SOCKET_ADSM, "ADSM" },
161 { IPX_SOCKET_EIGRP, "Cisco EIGRP for IPX" },
162 { IPX_SOCKET_NLSP, "NetWare Link Services Protocol" },
163 { IPX_SOCKET_IPXWAN, "IPX WAN" },
164 { SPX_SOCKET_PA, "NDPS Printer Agent/PSM" },
165 { SPX_SOCKET_BROKER, "NDPS Broker" },
166 { SPX_SOCKET_SRS, "NDPS Service Registry Service" },
167 { SPX_SOCKET_ENS, "NDPS Event Notification Service" },
168 { SPX_SOCKET_RMS, "NDPS Remote Management Service" },
169 { SPX_SOCKET_NOTIFY_LISTENER, "NDPS Notify Listener" },
170 { 0xE885, "NT Server-RPC/GW" },
171 { 0x400C, "HP LaserJet/QuickSilver" },
172 { 0x907B, "SMS Testing and Development" },
173 { 0x8F83, "Powerchute UPS Monitoring" },
174 { 0x4006, "NetWare Directory Server" },
175 { 0x8104, "NetWare 386" },
180 socket_text(guint16 socket)
182 return val_to_str(socket, ipx_socket_vals, "Unknown");
185 static const value_string ipx_packet_type_vals[] = {
186 { IPX_PACKET_TYPE_IPX, "IPX" },
187 { IPX_PACKET_TYPE_RIP, "RIP" },
188 { IPX_PACKET_TYPE_ECHO, "Echo" },
189 { IPX_PACKET_TYPE_ERROR, "Error" },
190 { IPX_PACKET_TYPE_PEP, "PEP" }, /* Packet Exchange Packet */
191 { IPX_PACKET_TYPE_SPX, "SPX" },
192 { 16, "Experimental Protocol" },
193 { IPX_PACKET_TYPE_NCP, "NCP" },
194 { 18, "Experimental Protocol" },
195 { 19, "Experimental Protocol" },
196 { IPX_PACKET_TYPE_WANBCAST, "NetBIOS Broadcast" },
197 { 21, "Experimental Protocol" },
198 { 22, "Experimental Protocol" },
199 { 23, "Experimental Protocol" },
200 { 24, "Experimental Protocol" },
201 { 25, "Experimental Protocol" },
202 { 26, "Experimental Protocol" },
203 { 27, "Experimental Protocol" },
204 { 28, "Experimental Protocol" },
205 { 29, "Experimental Protocol" },
206 { 30, "Experimental Protocol" },
207 { 31, "Experimental Protocol" },
211 static const value_string ipxmsg_sigchar_vals[] = {
212 { '?', "Poll inactive station" },
213 { 'Y', "Station is still using the connection" },
214 { '!', "Broadcast message waiting" },
219 capture_ipx(packet_counts *ld)
225 dissect_ipx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
229 proto_tree *ipx_tree;
232 const guint8 *src_net_node, *dst_net_node;
234 guint8 ipx_type, ipx_hops;
237 guint16 ipx_dsocket, ipx_ssocket;
238 guint16 first_socket, second_socket;
239 guint32 ipx_snet, ipx_dnet;
240 const guint8 *ipx_snode, *ipx_dnode;
242 if (check_col(pinfo->cinfo, COL_PROTOCOL))
243 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPX");
244 if (check_col(pinfo->cinfo, COL_INFO))
245 col_clear(pinfo->cinfo, COL_INFO);
247 /* Calculate here for use in pinfo and in tree */
248 ipx_dsocket = tvb_get_ntohs(tvb, 16);
249 ipx_ssocket = tvb_get_ntohs(tvb, 28);
250 ipx_type = tvb_get_guint8(tvb, 5);
251 ipx_length = tvb_get_ntohs(tvb, 2);
253 pinfo->ptype = PT_IPX;
254 pinfo->srcport = ipx_ssocket;
255 pinfo->destport = ipx_dsocket;
257 /* Adjust the tvbuff length to include only the IPX datagram. */
258 set_actual_length(tvb, ipx_length);
260 src_net_node = tvb_get_ptr(tvb, 18, 10);
261 dst_net_node = tvb_get_ptr(tvb, 6, 10);
263 SET_ADDRESS(&pinfo->net_src, AT_IPX, 10, src_net_node);
264 SET_ADDRESS(&pinfo->src, AT_IPX, 10, src_net_node);
265 SET_ADDRESS(&pinfo->net_dst, AT_IPX, 10, dst_net_node);
266 SET_ADDRESS(&pinfo->dst, AT_IPX, 10, dst_net_node);
268 if (check_col(pinfo->cinfo, COL_INFO))
269 col_add_fstr(pinfo->cinfo, COL_INFO, "%s (0x%04x)",
270 socket_text(ipx_dsocket), ipx_dsocket);
274 ti = proto_tree_add_item(tree, proto_ipx, tvb, 0, IPX_HEADER_LEN, FALSE);
275 ipx_tree = proto_item_add_subtree(ti, ett_ipx);
277 proto_tree_add_item(ipx_tree, hf_ipx_checksum, tvb, 0, 2, FALSE);
278 proto_tree_add_uint_format(ipx_tree, hf_ipx_len, tvb, 2, 2, ipx_length,
279 "Length: %d bytes", ipx_length);
280 ipx_hops = tvb_get_guint8(tvb, 4);
281 proto_tree_add_uint_format(ipx_tree, hf_ipx_hops, tvb, 4, 1, ipx_hops,
282 "Transport Control: %d hops", ipx_hops);
283 proto_tree_add_uint(ipx_tree, hf_ipx_packet_type, tvb, 5, 1, ipx_type);
286 ipx_dnet = tvb_get_ntohl(tvb, 6);
287 proto_tree_add_ipxnet(ipx_tree, hf_ipx_dnet, tvb, 6, 4,
289 proto_tree_add_ipxnet_hidden(ipx_tree, hf_ipx_net, tvb, 6, 4,
291 ipx_dnode = tvb_get_ptr(tvb, 10, 6);
292 proto_tree_add_ether(ipx_tree, hf_ipx_dnode, tvb, 10, 6,
294 proto_tree_add_ether_hidden(ipx_tree, hf_ipx_node, tvb, 10, 6,
296 proto_tree_add_uint(ipx_tree, hf_ipx_dsocket, tvb, 16, 2,
298 proto_tree_add_uint_hidden(ipx_tree, hf_ipx_socket, tvb, 16, 2,
302 ipx_snet = tvb_get_ntohl(tvb, 18);
303 proto_tree_add_ipxnet(ipx_tree, hf_ipx_snet, tvb, 18, 4,
305 proto_tree_add_ipxnet_hidden(ipx_tree, hf_ipx_net, tvb, 18, 4,
307 ipx_snode = tvb_get_ptr(tvb, 22, 6);
308 proto_tree_add_ether(ipx_tree, hf_ipx_snode, tvb, 22, 6,
310 proto_tree_add_ether_hidden(ipx_tree, hf_ipx_node, tvb, 22, 6,
312 proto_tree_add_uint(ipx_tree, hf_ipx_ssocket, tvb, 28, 2,
314 proto_tree_add_uint_hidden(ipx_tree, hf_ipx_socket, tvb, 28, 2,
318 /* Make the next tvbuff */
319 next_tvb = tvb_new_subset(tvb, IPX_HEADER_LEN, -1, -1);
322 * Let the subdissector know what type of IPX packet this is.
324 pinfo->ipxptype = ipx_type;
327 * Check the socket numbers before we check the packet type;
328 * we've seen non-NCP packets with a type of NCP and a
329 * destination socket of IPX_SOCKET_IPX_MESSAGE, and SAP
330 * packets with a type of NCP and a destination socket of
333 * We've seen NCP packets with a type of NCP, a source socket of
334 * IPX_SOCKET_NCP, and a destination socket of IPX_SOCKET_IPX_MESSAGE,
335 * and we've seen NCP packets with a type of NCP, a source socket of
336 * IPX_SOCKET_IPX_MESSAGE, and a destination socket of
337 * IPX_SOCKET_NCP, so testing the destination socket first doesn't
338 * always give the right answer. We've also seen SAP packets with
339 * a source socket of IPX_SOCKET_SAP and a destination socket of
340 * IPX_SOCKET_IPX_MESSAGE.
342 * Unfortunately, we've also seen packets with a source socket
343 * of IPX_SOCKET_NWLINK_SMB_SERVER and a destination socket
344 * of IPX_SOCKET_NWLINK_SMB_NAMEQUERY that were NMPI packets,
345 * not SMB packets, so testing the lower-valued socket first
346 * also doesn't always give the right answer.
348 * So we start out assuming we should test the lower-numbered
349 * socket number first, but, if the higher-numbered socket is
350 * IPX_SOCKET_NWLINK_SMB_NAMEQUERY, we assume that it's a
351 * NMPI query, and test only that socket.
353 if (ipx_ssocket > ipx_dsocket) {
354 first_socket = ipx_dsocket;
355 second_socket = ipx_ssocket;
357 first_socket = ipx_ssocket;
358 second_socket = ipx_dsocket;
360 if (second_socket != IPX_SOCKET_NWLINK_SMB_NAMEQUERY) {
361 if (dissector_try_port(ipx_socket_dissector_table, first_socket,
362 next_tvb, pinfo, tree))
365 if (dissector_try_port(ipx_socket_dissector_table, second_socket,
366 next_tvb, pinfo, tree))
370 * Neither of them are known; try the packet type, which will
371 * at least let us, for example, dissect SPX packets as SPX.
373 if (dissector_try_port(ipx_type_dissector_table, ipx_type, next_tvb,
377 call_dissector(data_handle,next_tvb, pinfo, tree);
379 /* ================================================================= */
380 /* SPX Hash Functions */
381 /* ================================================================= */
384 conversation_t *conversation;
396 * Structure attached to retransmitted SPX frames; it contains the
397 * frame number of the original transmission.
403 static GHashTable *spx_hash = NULL;
404 static GMemChunk *spx_hash_keys = NULL;
405 static GMemChunk *spx_hash_values = NULL;
406 static GMemChunk *spx_rexmit_infos = NULL;
410 spx_equal(gconstpointer v, gconstpointer v2)
412 const spx_hash_key *val1 = (const spx_hash_key*)v;
413 const spx_hash_key *val2 = (const spx_hash_key*)v2;
415 if (val1->conversation == val2->conversation &&
416 val1->spx_src == val2->spx_src &&
417 val1->spx_seq == val2->spx_seq) {
424 spx_hash_func(gconstpointer v)
426 const spx_hash_key *spx_key = (const spx_hash_key*)v;
427 return GPOINTER_TO_UINT(spx_key->conversation) + spx_key->spx_src;
430 /* Initializes the hash table and the mem_chunk area each time a new
431 * file is loaded or re-loaded in ethereal */
433 spx_init_protocol(void)
437 g_hash_table_destroy(spx_hash);
439 g_mem_chunk_destroy(spx_hash_keys);
441 g_mem_chunk_destroy(spx_hash_values);
442 if (spx_rexmit_infos)
443 g_mem_chunk_destroy(spx_rexmit_infos);
445 spx_hash = g_hash_table_new(spx_hash_func, spx_equal);
446 spx_hash_keys = g_mem_chunk_new("spx_hash_keys",
447 sizeof(spx_hash_key),
448 SPX_PACKET_INIT_COUNT * sizeof(spx_hash_key),
450 spx_hash_values = g_mem_chunk_new("spx_hash_values",
451 sizeof(spx_hash_value),
452 SPX_PACKET_INIT_COUNT * sizeof(spx_hash_value),
454 spx_rexmit_infos = g_mem_chunk_new("spx_rexmit_infos",
455 sizeof(spx_rexmit_infos),
456 SPX_PACKET_INIT_COUNT * sizeof(spx_rexmit_infos),
460 /* After the sequential run, we don't need the spx hash table, or
461 * the keys and values, anymore; the lookups have already been done
462 * and the relevant info saved as SPX private data with the frame
463 * if the frame was a retransmission. */
465 spx_postseq_cleanup(void)
468 /* Destroy the hash, but don't clean up request_condition data. */
469 g_hash_table_destroy(spx_hash);
473 g_mem_chunk_destroy(spx_hash_keys);
474 spx_hash_keys = NULL;
476 if (spx_hash_values) {
477 g_mem_chunk_destroy(spx_hash_values);
478 spx_hash_values = NULL;
480 /* Don't free the spx_rexmit_infos, as they're
481 * needed during random-access processing of the proto_tree.*/
485 spx_hash_insert(conversation_t *conversation, guint32 spx_src, guint16 spx_seq)
488 spx_hash_value *value;
490 /* Now remember the packet, so we can find it if we later. */
491 key = g_mem_chunk_alloc(spx_hash_keys);
492 key->conversation = conversation;
493 key->spx_src = spx_src;
494 key->spx_seq = spx_seq;
496 value = g_mem_chunk_alloc(spx_hash_values);
501 g_hash_table_insert(spx_hash, key, value);
506 /* Returns the spx_hash_value*, or NULL if not found. */
508 spx_hash_lookup(conversation_t *conversation, guint32 spx_src, guint32 spx_seq)
512 key.conversation = conversation;
513 key.spx_src = spx_src;
514 key.spx_seq = spx_seq;
516 return g_hash_table_lookup(spx_hash, &key);
519 /* ================================================================= */
521 /* ================================================================= */
523 #define SPX_SYS_PACKET 0x80
524 #define SPX_SEND_ACK 0x40
525 #define SPX_ATTN 0x20
529 spx_conn_ctrl(guint8 ctrl)
533 static const value_string conn_vals[] = {
534 { 0x00, "Data, No Ack Required" },
535 { SPX_EOM, "End-of-Message" },
536 { SPX_ATTN, "Attention" },
537 { SPX_SEND_ACK, "Acknowledgment Required"},
538 { SPX_SEND_ACK|SPX_EOM, "Send Ack: End Message"},
539 { SPX_SYS_PACKET, "System Packet"},
540 { SPX_SYS_PACKET|SPX_SEND_ACK, "System Packet: Send Ack"},
544 p = match_strval((ctrl & 0xf0), conn_vals );
555 spx_datastream(guint8 type)
559 return "End-of-Connection";
561 return "End-of-Connection Acknowledgment";
567 #define SPX_HEADER_LEN 12
570 dissect_spx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
572 proto_tree *spx_tree = NULL;
577 guint8 datastream_type;
578 const char *datastream_type_string;
580 const char *spx_msg_string;
581 guint16 low_socket, high_socket;
583 conversation_t *conversation;
584 spx_hash_value *pkt_value;
585 spx_rexmit_info *spx_rexmit_info;
588 if (check_col(pinfo->cinfo, COL_PROTOCOL))
589 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SPX");
590 if (check_col(pinfo->cinfo, COL_INFO))
591 col_set_str(pinfo->cinfo, COL_INFO, "SPX");
594 ti = proto_tree_add_item(tree, proto_spx, tvb, 0, SPX_HEADER_LEN, FALSE);
595 spx_tree = proto_item_add_subtree(ti, ett_spx);
598 conn_ctrl = tvb_get_guint8(tvb, 0);
599 spx_msg_string = spx_conn_ctrl(conn_ctrl);
600 if (check_col(pinfo->cinfo, COL_INFO))
601 col_append_fstr(pinfo->cinfo, COL_INFO, " %s", spx_msg_string);
603 ti = proto_tree_add_uint_format(spx_tree, hf_spx_connection_control, tvb,
605 "Connection Control: %s (0x%02X)",
606 spx_msg_string, conn_ctrl);
607 cc_tree = proto_item_add_subtree(ti, ett_spx_connctrl);
608 proto_tree_add_boolean(cc_tree, hf_spx_connection_control_sys, tvb,
610 proto_tree_add_boolean(cc_tree, hf_spx_connection_control_send_ack, tvb,
612 proto_tree_add_boolean(cc_tree, hf_spx_connection_control_attn, tvb,
614 proto_tree_add_boolean(cc_tree, hf_spx_connection_control_eom, tvb,
618 datastream_type = tvb_get_guint8(tvb, 1);
619 datastream_type_string = spx_datastream(datastream_type);
620 if (datastream_type_string != NULL) {
621 if (check_col(pinfo->cinfo, COL_INFO))
622 col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
623 datastream_type_string);
626 if (datastream_type_string != NULL) {
627 proto_tree_add_uint_format(spx_tree, hf_spx_datastream_type, tvb,
628 1, 1, datastream_type,
629 "Datastream Type: %s (0x%02X)",
630 datastream_type_string,
633 proto_tree_add_uint_format(spx_tree, hf_spx_datastream_type, tvb,
634 1, 1, datastream_type,
635 "Datastream Type: 0x%02X",
638 proto_tree_add_item(spx_tree, hf_spx_src_id, tvb, 2, 2, FALSE);
639 proto_tree_add_item(spx_tree, hf_spx_dst_id, tvb, 4, 2, FALSE);
641 spx_seq = tvb_get_ntohs(tvb, 6);
643 proto_tree_add_uint(spx_tree, hf_spx_seq_nr, tvb, 6, 2, spx_seq);
644 proto_tree_add_item(spx_tree, hf_spx_ack_nr, tvb, 8, 2, FALSE);
645 proto_tree_add_item(spx_tree, hf_spx_all_nr, tvb, 10, 2, FALSE);
649 * SPX is Connection Oriented and Delivery Guaranteed.
650 * On the first pass, we need to flag retransmissions by the SPX
651 * protocol, so that subdissectors know whether a packet was
654 * We start out by creating a conversation for this direction of the
655 * IPX session; we use "pinfo->srcport" twice, so that we have
656 * separate conversations for the two directions.
658 * XXX - that might not work correctly if there's more than one
659 * SPX session using that source port; can that happen? If so,
660 * we should probably use the direction, as well as the conversation,
661 * as part of the hash key; if we do that, we can probably just
662 * use PT_IPX as the port type, and possibly get rid of PT_NCP.
666 * http://developer.novell.com/research/appnotes/1995/december/03/apv.htm
668 * the sequence number is not incremented for system packets, so
669 * presumably that means there is no notion of a system packet
670 * being retransmitted; that document also says that system
671 * packets are used as "I'm still here" keepalives and as
672 * acknowledgements (presumably meaning ACK-only packets), which
673 * suggests that they might not be ACKed and thus might not
676 if (conn_ctrl & SPX_SYS_PACKET) {
678 * It's a system packet, so it isn't a retransmission.
680 spx_rexmit_info = NULL;
683 * Not a system packet - check for retransmissions.
685 if (!pinfo->fd->flags.visited) {
686 conversation = find_conversation(&pinfo->src,
687 &pinfo->dst, PT_NCP, pinfo->srcport,
689 if (conversation == NULL) {
691 * It's not part of any conversation - create
694 conversation = conversation_new(&pinfo->src,
695 &pinfo->dst, PT_NCP, pinfo->srcport,
700 * Now we'll hash the SPX header and use the result
701 * of that, plus the conversation, as a hash key to
702 * identify this packet.
704 * If we don't find it in the hash table, it's not a
705 * retransmission, otherwise it is. If we don't find
706 * it, we enter it into the hash table, with the
708 * If we do, we attach to this frame a structure giving
709 * the frame number of the original transmission, so
710 * that we, and subdissectors, know it's a
713 src = tvb_get_ntohs(tvb, 0)+tvb_get_ntohs(tvb, 2)+tvb_get_ntohs(tvb, 4)+tvb_get_ntohs(tvb, 6)+tvb_get_ntohs(tvb, 8);
714 pkt_value = spx_hash_lookup(conversation, src, spx_seq);
715 if (pkt_value == NULL) {
717 * Not found in the hash table.
718 * Enter it into the hash table.
720 pkt_value = spx_hash_insert(conversation, src,
722 pkt_value->spx_ack = tvb_get_ntohs(tvb, 8);
723 pkt_value->spx_all = tvb_get_ntohs(tvb, 10);
724 pkt_value->num = pinfo->fd->num;
727 * This is not a retransmission, so we shouldn't
728 * have any retransmission indicator.
730 spx_rexmit_info = NULL;
733 * Found in the hash table. Mark this frame as
736 spx_rexmit_info = g_mem_chunk_alloc(spx_rexmit_infos);
737 spx_rexmit_info->num = pkt_value->num;
738 p_add_proto_data(pinfo->fd, proto_spx,
743 * Do we have per-packet SPX data for this frame?
744 * If so, it's a retransmission, and the per-packet
745 * data indicates which frame had the original
748 spx_rexmit_info = p_get_proto_data(pinfo->fd,
754 * It's a retransmission if we have a retransmission indicator.
755 * Flag this as a retransmission, but don't pass it to the
758 if (spx_rexmit_info != NULL) {
759 if (check_col(pinfo->cinfo, COL_INFO)) {
760 col_add_fstr(pinfo->cinfo, COL_INFO,
761 "[Retransmission] Original Packet %u",
762 spx_rexmit_info->num);
765 proto_tree_add_uint_format(spx_tree, hf_spx_rexmt_frame,
766 tvb, 0, 0, spx_rexmit_info->num,
767 "This is a retransmission of frame %u",
768 spx_rexmit_info->num);
769 if (tvb_length_remaining(tvb, SPX_HEADER_LEN) > 0) {
770 proto_tree_add_text(spx_tree, tvb,
772 "Retransmitted data");
778 if (tvb_reported_length_remaining(tvb, SPX_HEADER_LEN) > 0) {
780 * Call subdissectors based on the IPX socket numbers; a
781 * subdissector might have registered with our IPX socket
782 * dissector table rather than the IPX dissector's socket
785 * Assume the lower-numbered socket number is more likely
786 * to be the right one, along the lines of what we do for
787 * TCP and UDP. We've seen NCP packets with a type of NCP,
788 * a source socket of IPX_SOCKET_NCP, and a destination
789 * socket of IPX_SOCKET_IPX_MESSAGE, and we've seen NCP
790 * packets with a type of NCP, a source socket of
791 * IPX_SOCKET_IPX_MESSAGE, and a destination socket of
794 if (pinfo->srcport > pinfo->destport) {
795 low_socket = pinfo->destport;
796 high_socket = pinfo->srcport;
798 low_socket = pinfo->srcport;
799 high_socket = pinfo->destport;
803 * Pass information to subdissectors.
805 spx_info.eom = conn_ctrl & SPX_EOM;
806 spx_info.datastream_type = datastream_type;
807 pinfo->private_data = &spx_info;
809 next_tvb = tvb_new_subset(tvb, SPX_HEADER_LEN, -1, -1);
810 if (dissector_try_port(spx_socket_dissector_table, low_socket,
811 next_tvb, pinfo, tree))
813 if (dissector_try_port(spx_socket_dissector_table, high_socket,
814 next_tvb, pinfo, tree))
816 call_dissector(data_handle, next_tvb, pinfo, tree);
820 /* ================================================================= */
822 /* ================================================================= */
824 dissect_ipxmsg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
826 proto_tree *msg_tree;
828 guint8 conn_number, sig_char;
830 if (check_col(pinfo->cinfo, COL_PROTOCOL))
831 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPX MSG");
832 if (check_col(pinfo->cinfo, COL_INFO))
833 col_clear(pinfo->cinfo, COL_INFO);
835 conn_number = tvb_get_guint8(tvb, 0);
836 sig_char = tvb_get_guint8(tvb, 1);
838 if (check_col(pinfo->cinfo, COL_INFO)) {
839 col_add_fstr(pinfo->cinfo, COL_INFO,
841 val_to_str(sig_char, ipxmsg_sigchar_vals, "Unknown Signature Char"), conn_number);
845 ti = proto_tree_add_item(tree, proto_ipxmsg, tvb, 0, -1, FALSE);
846 msg_tree = proto_item_add_subtree(ti, ett_ipxmsg);
848 proto_tree_add_uint(msg_tree, hf_msg_conn, tvb, 0, 1, conn_number);
849 proto_tree_add_uint(msg_tree, hf_msg_sigchar, tvb, 1, 1, sig_char);
854 /* ================================================================= */
856 /* ================================================================= */
858 dissect_ipxrip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
860 proto_tree *rip_tree;
863 struct ipx_rt_def route;
865 int available_length;
867 static char *rip_type[3] = { "Request", "Response", "Unknown" };
869 if (check_col(pinfo->cinfo, COL_PROTOCOL))
870 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPX RIP");
871 if (check_col(pinfo->cinfo, COL_INFO))
872 col_clear(pinfo->cinfo, COL_INFO);
874 operation = tvb_get_ntohs(tvb, 0) - 1;
876 if (check_col(pinfo->cinfo, COL_INFO)) {
877 /* rip_types 0 and 1 are valid, anything else becomes 2 or "Unknown" */
878 col_set_str(pinfo->cinfo, COL_INFO, rip_type[MIN(operation, 2)]);
882 ti = proto_tree_add_item(tree, proto_ipxrip, tvb, 0, -1, FALSE);
883 rip_tree = proto_item_add_subtree(ti, ett_ipxrip);
886 proto_tree_add_text(rip_tree, tvb, 0, 2,
887 "RIP packet type: %s", rip_type[operation]);
889 if (operation == 0) {
890 proto_tree_add_boolean_hidden(rip_tree,
894 proto_tree_add_boolean_hidden(rip_tree,
901 proto_tree_add_text(rip_tree, tvb, 0, 2, "Unknown RIP packet type");
904 available_length = tvb_reported_length(tvb);
905 for (cursor = 2; cursor < available_length; cursor += 8) {
906 tvb_memcpy(tvb, (guint8 *)&route.network, cursor, 4);
907 route.hops = tvb_get_ntohs(tvb, cursor+4);
908 route.ticks = tvb_get_ntohs(tvb, cursor+6);
910 if (operation == IPX_RIP_REQUEST - 1) {
911 proto_tree_add_text(rip_tree, tvb, cursor, 8,
912 "Route Vector: %s, %d hop%s, %d tick%s",
913 ipxnet_to_string((guint8*)&route.network),
914 route.hops, route.hops == 1 ? "" : "s",
915 route.ticks, route.ticks == 1 ? "" : "s");
918 proto_tree_add_text(rip_tree, tvb, cursor, 8,
919 "Route Vector: %s, %d hop%s, %d tick%s (%d ms)",
920 ipxnet_to_string((guint8*)&route.network),
921 route.hops, route.hops == 1 ? "" : "s",
922 route.ticks, route.ticks == 1 ? "" : "s",
923 route.ticks * 1000 / 18);
930 * Some of these are from ncpfs, others are from the book,
931 * others are from the page at
933 * http://www.iana.org/assignments/novell-sap-numbers
935 * and some from the page at
937 * http://www.rware.demon.co.uk/ipxsap.htm
939 * (see also the page at
941 * http://developer.novell.com/research/appnotes/1998/february/03/06.htm
943 * which has a huge list - but many of the entries list only the
944 * organization owning the SAP type, not what the type is for).
946 const value_string server_vals[] = {
947 { 0x0000, "Unknown" },
949 { 0x0002, "User Group" },
950 { 0x0003, "Print Queue or Print Group" },
951 { 0x0004, "File Server (SLIST source)" },
952 { 0x0005, "Job Server" },
953 { 0x0006, "Gateway" },
954 { 0x0007, "Print Server or Silent Print Server" },
955 { 0x0008, "Archive Queue" },
956 { 0x0009, "Archive Server" },
957 { 0x000a, "Job Queue" },
958 { 0x000b, "Administration" },
959 { 0x000F, "Novell TI-RPC" },
960 { 0x0017, "Diagnostics" },
961 { 0x0020, "NetBIOS" },
962 { 0x0021, "NAS SNA Gateway" },
963 { 0x0023, "NACS Async Gateway or Asynchronous Gateway" },
964 { 0x0024, "Remote Bridge or Routing Service" },
965 { 0x0026, "Bridge Server or Asynchronous Bridge Server" },
966 { 0x0027, "TCP/IP Gateway Server" },
967 { 0x0028, "Point to Point (Eicon) X.25 Bridge Server" },
968 { 0x0029, "Eicon 3270 Gateway" },
969 { 0x002a, "CHI Corp" },
970 { 0x002c, "PC Chalkboard" },
971 { 0x002d, "Time Synchronization Server or Asynchronous Timer" },
972 { 0x002e, "ARCserve 5.0 / Palindrome Backup Director 4.x (PDB4)" },
973 { 0x0045, "DI3270 Gateway" },
974 { 0x0047, "Advertising Print Server" },
975 { 0x004a, "NetBlazer Modems" },
976 { 0x004b, "Btrieve VAP/NLM 5.0" },
977 { 0x004c, "NetWare SQL VAP/NLM Server" },
978 { 0x004d, "Xtree Network Version/NetWare XTree" },
979 { 0x0050, "Btrieve VAP 4.11" },
980 { 0x0052, "QuickLink (Cubix)" },
981 { 0x0053, "Print Queue User" },
982 { 0x0058, "Multipoint X.25 Eicon Router" },
983 { 0x0060, "STLB/NLM" },
984 { 0x0064, "ARCserve" },
985 { 0x0066, "ARCserve 3.0" },
986 { 0x0072, "WAN Copy Utility" },
987 { 0x007a, "TES-NetWare for VMS" },
988 { 0x0092, "WATCOM Debugger or Emerald Tape Backup Server" },
989 { 0x0095, "DDA OBGYN" },
990 { 0x0098, "NetWare Access Server (Asynchronous gateway)" },
991 { 0x009a, "NetWare for VMS II or Named Pipe Server" },
992 { 0x009b, "NetWare Access Server" },
993 { 0x009e, "Portable NetWare Server or SunLink NVT" },
994 { 0x00a1, "Powerchute APC UPS NLM" },
995 { 0x00aa, "LAWserve" },
996 { 0x00ac, "Compaq IDA Status Monitor" },
997 { 0x0100, "PIPE STAIL" },
998 { 0x0102, "LAN Protect Bindery" },
999 { 0x0103, "Oracle DataBase Server" },
1000 { 0x0107, "NetWare 386 or RSPX Remote Console" },
1001 { 0x010f, "Novell SNA Gateway" },
1002 { 0x0111, "Test Server" },
1003 { 0x0112, "Print Server (HP)" },
1004 { 0x0114, "CSA MUX (f/Communications Executive)" },
1005 { 0x0115, "CSA LCA (f/Communications Executive)" },
1006 { 0x0116, "CSA CM (f/Communications Executive)" },
1007 { 0x0117, "CSA SMA (f/Communications Executive)" },
1008 { 0x0118, "CSA DBA (f/Communications Executive)" },
1009 { 0x0119, "CSA NMA (f/Communications Executive)" },
1010 { 0x011a, "CSA SSA (f/Communications Executive)" },
1011 { 0x011b, "CSA STATUS (f/Communications Executive)" },
1012 { 0x011e, "CSA APPC (f/Communications Executive)" },
1013 { 0x0126, "SNA TEST SSA Profile" },
1014 { 0x012a, "CSA TRACE (f/Communications Executive)" },
1015 { 0x012b, "NetWare for SAA" },
1016 { 0x012e, "IKARUS virus scan utility" },
1017 { 0x0130, "Communications Executive" },
1018 { 0x0133, "NNS Domain Server or NetWare Naming Services Domain" },
1019 { 0x0135, "NetWare Naming Services Profile" },
1020 { 0x0137, "NetWare 386 Print Queue or NNS Print Queue" },
1021 { 0x0141, "LAN Spool Server (Vap, Intel)" },
1022 { 0x0152, "IRMALAN Gateway" },
1023 { 0x0154, "Named Pipe Server" },
1024 { 0x0166, "NetWare Management" },
1025 { 0x0168, "Intel PICKIT Comm Server or Intel CAS Talk Server" },
1026 { 0x0173, "Compaq" },
1027 { 0x0174, "Compaq SNMP Agent" },
1028 { 0x0175, "Compaq" },
1029 { 0x0180, "XTree Server or XTree Tools" },
1030 { 0x018A, "NASI services broadcast server (Novell)" },
1031 { 0x01b0, "GARP Gateway (net research)" },
1032 { 0x01b1, "Binfview (Lan Support Group)" },
1033 { 0x01bf, "Intel LanDesk Manager" },
1034 { 0x01ca, "AXTEC" },
1035 { 0x01cb, "Shiva NetModem/E" },
1036 { 0x01cc, "Shiva LanRover/E" },
1037 { 0x01cd, "Shiva LanRover/T" },
1038 { 0x01ce, "Shiva Universal" },
1039 { 0x01d8, "Castelle FAXPress Server" },
1040 { 0x01da, "Castelle LANPress Print Server" },
1041 { 0x01dc, "Castelle FAX/Xerox 7033 Fax Server/Excel Lan Fax" },
1042 { 0x01f0, "LEGATO" },
1043 { 0x01f5, "LEGATO" },
1044 { 0x0233, "NMS Agent or NetWare Management Agent" },
1045 { 0x0237, "NMS IPX Discovery or LANtern Read/Write Channel" },
1046 { 0x0238, "NMS IP Discovery or LANtern Trap/Alarm Channel" },
1047 { 0x023a, "LANtern" },
1048 { 0x023c, "MAVERICK" },
1049 { 0x023f, "SMS Testing and Development" },
1050 { 0x024e, "NetWare Connect" },
1051 { 0x024f, "NASI server broadcast (Cisco)" },
1052 { 0x026a, "Network Management (NMS) Service Console" },
1053 { 0x026b, "Time Synchronization Server (NetWare 4.x)" },
1054 { 0x0278, "Directory Server (NetWare 4.x)" },
1055 { 0x027b, "NetWare Management Agent" },
1056 { 0x0280, "Novell File and Printer Sharing Service for PC" },
1057 { 0x0304, "Novell SAA Gateway" },
1058 { 0x0308, "COM or VERMED 1" },
1059 { 0x030a, "Galacticomm's Worldgroup Server" },
1060 { 0x030c, "Intel Netport 2 or HP JetDirect or HP Quicksilver" },
1061 { 0x0320, "Attachmate Gateway" },
1062 { 0x0327, "Microsoft Diagnostics" },
1063 { 0x0328, "WATCOM SQL server" },
1064 { 0x0335, "MultiTech Systems Multisynch Comm Server" },
1065 { 0x0343, "Xylogics Remote Access Server or LAN Modem" },
1066 { 0x0355, "Arcada Backup Exec" },
1067 { 0x0358, "MSLCD1" },
1068 { 0x0361, "NETINELO" },
1069 { 0x037e, "Powerchute UPS Monitoring" },
1070 { 0x037f, "ViruSafe Notify" },
1071 { 0x0386, "HP Bridge" },
1072 { 0x0387, "HP Hub" },
1073 { 0x0394, "NetWare SAA Gateway" },
1074 { 0x039b, "Lotus Notes" },
1075 { 0x03b7, "Certus Anti Virus NLM" },
1076 { 0x03c4, "ARCserve 4.0 (Cheyenne)" },
1077 { 0x03c7, "LANspool 3.5 (Intel)" },
1078 { 0x03d7, "Lexmark printer server (type 4033-011)" },
1079 { 0x03d8, "Lexmark XLE printer server (type 4033-301)" },
1080 { 0x03dd, "Banyan ENS for NetWare Client NLM" },
1081 { 0x03de, "Gupta Sequel Base Server or NetWare SQL" },
1082 { 0x03e1, "Univel Unixware" },
1083 { 0x03e4, "Univel Unixware" },
1084 { 0x03fc, "Intel Netport" },
1085 { 0x03fd, "Intel Print Server Queue" },
1086 { 0x040A, "ipnServer" },
1087 { 0x040D, "LVERRMAN" },
1088 { 0x040E, "LVLIC" },
1089 { 0x0414, "NET Silicon (DPI)/Kyocera" },
1090 { 0x0429, "Site Lock Virus (Brightworks)" },
1091 { 0x0432, "UFHELP R" },
1092 { 0x0433, "Synoptics 281x Advanced SNMP Agent" },
1093 { 0x0444, "Microsoft NT SNA Server" },
1094 { 0x0448, "Oracle" },
1095 { 0x044c, "ARCserve 5.01" },
1096 { 0x0457, "Canon GP55 Running on a Canon GP55 network printer" },
1097 { 0x045a, "QMS Printers" },
1098 { 0x045b, "Dell SCSI Array (DSA) Monitor" },
1099 { 0x0491, "NetBlazer Modems" },
1100 { 0x04ac, "On-Time Scheduler NLM" },
1101 { 0x04b0, "CD-Net (Meridian)" },
1102 { 0x0513, "Emulex NQA" },
1103 { 0x0520, "Site Lock Checks" },
1104 { 0x0529, "Site Lock Checks (Brightworks)" },
1105 { 0x052d, "Citrix OS/2 App Server" },
1106 { 0x0535, "Tektronix" },
1107 { 0x0536, "Milan" },
1108 { 0x055d, "Attachmate SNA gateway" },
1109 { 0x056b, "IBM 8235 modem server" },
1110 { 0x056c, "Shiva LanRover/E PLUS" },
1111 { 0x056d, "Shiva LanRover/T PLUS" },
1112 { 0x0580, "McAfee's NetShield anti-virus" },
1113 { 0x05B8, "NLM to workstation communication (Revelation Software)" },
1114 { 0x05BA, "Compatible Systems Routers" },
1115 { 0x05BE, "Cheyenne Hierarchical Storage Manager" },
1116 { 0x0606, "JCWatermark Imaging" },
1117 { 0x060c, "AXIS Network Printer" },
1118 { 0x0610, "Adaptec SCSI Management" },
1119 { 0x0621, "IBM AntiVirus NLM" },
1120 { 0x0640, "Microsoft Gateway Services for NetWare" },
1121 /* { 0x0640, "NT Server-RPC/GW for NW/Win95 User Level Sec" }, */
1122 { 0x064e, "Microsoft Internet Information Server" },
1123 { 0x067b, "Microsoft Win95/98 File and Print Sharing for NetWare" },
1124 { 0x067c, "Microsoft Win95/98 File and Print Sharing for NetWare" },
1125 { 0x076C, "Xerox" },
1126 { 0x079b, "Shiva LanRover/E 115" },
1127 { 0x079c, "Shiva LanRover/T 115" },
1128 { 0x07B4, "Cubix WorldDesk" },
1129 { 0x07c2, "Quarterdeck IWare Connect V2.x NLM" },
1130 { 0x07c1, "Quarterdeck IWare Connect V3.x NLM" },
1131 { 0x0810, "ELAN License Server Demo" },
1132 { 0x0824, "Shiva LanRover Access Switch/E" },
1133 { 0x086a, "ISSC collector NLMs" },
1134 { 0x087f, "ISSC DAS agent for AIX" },
1135 { 0x0880, "Intel Netport PRO" },
1136 { 0x0881, "Intel Netport PRO" },
1137 { 0x0b29, "Site Lock" },
1138 { 0x0c29, "Site Lock Applications" },
1139 { 0x0c2c, "Licensing Server" },
1140 { 0x2101, "Performance Technology Instant Internet" },
1141 { 0x2380, "LAI Site Lock" },
1142 { 0x238c, "Meeting Maker" },
1143 { 0x4808, "Site Lock Server or Site Lock Metering VAP/NLM" },
1144 { 0x5555, "Site Lock User" },
1145 { 0x6312, "Tapeware" },
1146 { 0x6f00, "Rabbit Gateway (3270)" },
1147 { 0x7703, "MODEM" },
1148 { 0x8002, "NetPort Printers (Intel) or LANport" },
1149 { 0x8003, "SEH InterCon Printserver" },
1150 { 0x8008, "WordPerfect Network Version" },
1151 { 0x85BE, "Cisco Enhanced Interior Routing Protocol (EIGRP)" },
1152 { 0x8888, "WordPerfect Network Version or Quick Network Management" },
1153 { 0x9000, "McAfee's NetShield anti-virus" },
1154 { 0x9604, "CSA-NT_MON" },
1155 { 0xb6a8, "Ocean Isle Reachout Remote Control" },
1156 { 0xf11f, "Site Lock Metering VAP/NLM" },
1157 { 0xf1ff, "Site Lock" },
1158 { 0xf503, "Microsoft SQL Server" },
1159 { 0xf905, "IBM Time and Place/2 application" },
1160 { 0xfbfb, "TopCall III fax server" },
1161 { 0xffff, "Any Service or Wildcard" },
1166 dissect_ipxsap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1168 proto_tree *sap_tree, *s_tree;
1171 struct sap_query query;
1172 guint16 server_type;
1173 char server_name[48];
1174 guint16 server_port;
1175 guint16 intermediate_network;
1177 static char *sap_type[4] = { "General Query", "General Response",
1178 "Nearest Query", "Nearest Response" };
1180 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1181 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPX SAP");
1182 if (check_col(pinfo->cinfo, COL_INFO))
1183 col_clear(pinfo->cinfo, COL_INFO);
1185 query.query_type = tvb_get_ntohs(tvb, 0);
1186 query.server_type = tvb_get_ntohs(tvb, 2);
1188 if (check_col(pinfo->cinfo, COL_INFO)) {
1189 if (query.query_type >= 1 && query.query_type <= 4) {
1190 col_set_str(pinfo->cinfo, COL_INFO, sap_type[query.query_type - 1]);
1193 col_set_str(pinfo->cinfo, COL_INFO, "Unknown Packet Type");
1198 ti = proto_tree_add_item(tree, proto_sap, tvb, 0, -1, FALSE);
1199 sap_tree = proto_item_add_subtree(ti, ett_ipxsap);
1201 if (query.query_type >= 1 && query.query_type <= 4) {
1202 proto_tree_add_text(sap_tree, tvb, 0, 2, sap_type[query.query_type - 1]);
1203 if ((query.query_type - 1) % 2) {
1204 proto_tree_add_boolean_hidden(sap_tree,
1208 proto_tree_add_boolean_hidden(sap_tree,
1214 proto_tree_add_text(sap_tree, tvb, 0, 2,
1215 "Unknown SAP Packet Type %d", query.query_type);
1218 if (query.query_type == IPX_SAP_GENERAL_RESPONSE ||
1219 query.query_type == IPX_SAP_NEAREST_RESPONSE) { /* responses */
1221 int available_length = tvb_reported_length(tvb);
1222 for (cursor = 2; (cursor + 64) <= available_length; cursor += 64) {
1223 server_type = tvb_get_ntohs(tvb, cursor);
1224 tvb_memcpy(tvb, (guint8 *)server_name,
1227 ti = proto_tree_add_text(sap_tree, tvb, cursor+2, 48,
1228 "Server Name: %.48s", server_name);
1229 s_tree = proto_item_add_subtree(ti, ett_ipxsap_server);
1231 proto_tree_add_text(s_tree, tvb, cursor, 2, "Server Type: %s (0x%04X)",
1232 val_to_str(server_type, server_vals, "Unknown"),
1234 proto_tree_add_text(s_tree, tvb, cursor+50, 4, "Network: %s",
1235 ipxnet_to_string(tvb_get_ptr(tvb, cursor+50, 4)));
1236 proto_tree_add_text(s_tree, tvb, cursor+54, 6, "Node: %s",
1237 ether_to_str(tvb_get_ptr(tvb, cursor+54, 6)));
1238 server_port = tvb_get_ntohs(tvb, cursor+60);
1239 proto_tree_add_text(s_tree, tvb, cursor+60, 2, "Socket: %s (0x%04x)",
1240 socket_text(server_port),
1242 intermediate_network = tvb_get_ntohs(tvb, cursor+62);
1243 proto_tree_add_text(s_tree, tvb, cursor+62, 2,
1244 "Intermediate Networks: %d",
1245 intermediate_network);
1248 else { /* queries */
1249 proto_tree_add_text(sap_tree, tvb, 2, 2, "Server Type: %s (0x%04X)",
1250 val_to_str(query.server_type, server_vals, "Unknown"),
1257 proto_register_ipx(void)
1259 static hf_register_info hf_ipx[] = {
1261 { "Checksum", "ipx.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1265 { "Length", "ipx.len", FT_UINT16, BASE_DEC, NULL, 0x0,
1269 { "Transport Control (Hops)", "ipx.hops", FT_UINT8, BASE_DEC, NULL, 0x0,
1272 { &hf_ipx_packet_type,
1273 { "Packet Type", "ipx.packet_type", FT_UINT8, BASE_HEX, VALS(ipx_packet_type_vals),
1278 { "Destination Network","ipx.dst.net", FT_IPXNET, BASE_NONE, NULL, 0x0,
1282 { "Destination Node", "ipx.dst.node", FT_ETHER, BASE_NONE, NULL, 0x0,
1286 { "Destination Socket", "ipx.dst.socket", FT_UINT16, BASE_HEX,
1287 VALS(ipx_socket_vals), 0x0,
1291 { "Source Network","ipx.src.net", FT_IPXNET, BASE_NONE, NULL, 0x0,
1295 { "Source Node", "ipx.src.node", FT_ETHER, BASE_NONE, NULL, 0x0,
1299 { "Source Socket", "ipx.src.socket", FT_UINT16, BASE_HEX,
1300 VALS(ipx_socket_vals), 0x0,
1304 { "Source or Destination Network","ipx.net", FT_IPXNET, BASE_NONE, NULL, 0x0,
1308 { "Source or Destination Node", "ipx.node", FT_ETHER, BASE_NONE, NULL, 0x0,
1312 { "Source or Destination Socket", "ipx.socket", FT_UINT16, BASE_HEX,
1313 VALS(ipx_socket_vals), 0x0,
1317 static hf_register_info hf_spx[] = {
1318 { &hf_spx_connection_control,
1319 { "Connection Control", "spx.ctl",
1320 FT_UINT8, BASE_HEX, NULL, 0x0,
1323 { &hf_spx_connection_control_sys,
1324 { "System Packet", "spx.ctl.sys",
1325 FT_BOOLEAN, 8, NULL, SPX_SYS_PACKET,
1328 { &hf_spx_connection_control_send_ack,
1329 { "Send Ack", "spx.ctl.send_ack",
1330 FT_BOOLEAN, 8, NULL, SPX_SEND_ACK,
1333 { &hf_spx_connection_control_attn,
1334 { "Attention", "spx.ctl.attn",
1335 FT_BOOLEAN, 8, NULL, SPX_ATTN,
1338 { &hf_spx_connection_control_eom,
1339 { "End of Message", "spx.ctl.eom",
1340 FT_BOOLEAN, 8, NULL, SPX_EOM,
1343 { &hf_spx_datastream_type,
1344 { "Datastream type", "spx.type",
1345 FT_UINT8, BASE_HEX, NULL, 0x0,
1349 { "Source Connection ID", "spx.src",
1350 FT_UINT16, BASE_DEC, NULL, 0x0,
1354 { "Destination Connection ID", "spx.dst",
1355 FT_UINT16, BASE_DEC, NULL, 0x0,
1359 { "Sequence Number", "spx.seq",
1360 FT_UINT16, BASE_DEC, NULL, 0x0,
1364 { "Acknowledgment Number", "spx.ack",
1365 FT_UINT16, BASE_DEC, NULL, 0x0,
1369 { "Allocation Number", "spx.alloc",
1370 FT_UINT16, BASE_DEC, NULL, 0x0,
1373 { &hf_spx_rexmt_frame,
1374 { "Retransmitted Frame Number", "spx.rexmt_frame",
1375 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1379 static hf_register_info hf_ipxrip[] = {
1380 { &hf_ipxrip_request,
1381 { "Request", "ipxrip.request",
1382 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1383 "TRUE if IPX RIP request", HFILL }},
1385 { &hf_ipxrip_response,
1386 { "Response", "ipxrip.response",
1387 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1388 "TRUE if IPX RIP response", HFILL }}
1391 static hf_register_info hf_sap[] = {
1393 { "Request", "ipxsap.request",
1394 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1395 "TRUE if SAP request", HFILL }},
1398 { "Response", "ipxsap.response",
1399 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1400 "TRUE if SAP response", HFILL }}
1403 static hf_register_info hf_ipxmsg[] = {
1405 { "Connection Number", "ipxmsg.conn",
1406 FT_UINT8, BASE_DEC, NULL, 0x0,
1407 "Connection Number", HFILL }},
1410 { "Signature Char", "ipxmsg.sigchar",
1411 FT_UINT8, BASE_DEC, VALS(ipxmsg_sigchar_vals), 0x0,
1412 "Signature Char", HFILL }}
1415 static gint *ett[] = {
1425 proto_ipx = proto_register_protocol("Internetwork Packet eXchange",
1427 proto_register_field_array(proto_ipx, hf_ipx, array_length(hf_ipx));
1429 register_dissector("ipx", dissect_ipx, proto_ipx);
1431 proto_spx = proto_register_protocol("Sequenced Packet eXchange",
1433 proto_register_field_array(proto_spx, hf_spx, array_length(hf_spx));
1435 proto_ipxrip = proto_register_protocol("IPX Routing Information Protocol",
1436 "IPX RIP", "ipxrip");
1437 proto_register_field_array(proto_ipxrip, hf_ipxrip, array_length(hf_ipxrip));
1439 proto_ipxmsg = proto_register_protocol("IPX Message", "IPX MSG",
1441 proto_register_field_array(proto_ipxmsg, hf_ipxmsg, array_length(hf_ipxmsg));
1443 proto_sap = proto_register_protocol("Service Advertisement Protocol",
1444 "IPX SAP", "ipxsap");
1445 register_dissector("ipxsap", dissect_ipxsap, proto_sap);
1447 proto_register_field_array(proto_sap, hf_sap, array_length(hf_sap));
1449 proto_register_subtree_array(ett, array_length(ett));
1451 ipx_type_dissector_table = register_dissector_table("ipx.packet_type",
1452 "IPX packet type", FT_UINT8, BASE_HEX);
1453 ipx_socket_dissector_table = register_dissector_table("ipx.socket",
1454 "IPX socket", FT_UINT16, BASE_HEX);
1455 spx_socket_dissector_table = register_dissector_table("spx.socket",
1456 "SPX socket", FT_UINT16, BASE_HEX);
1458 register_init_routine(&spx_init_protocol);
1459 register_postseq_cleanup_routine(&spx_postseq_cleanup);
1463 proto_reg_handoff_ipx(void)
1465 dissector_handle_t ipx_handle, spx_handle;
1466 dissector_handle_t ipxsap_handle, ipxrip_handle;
1467 dissector_handle_t ipxmsg_handle;
1469 ipx_handle = find_dissector("ipx");
1470 dissector_add("udp.port", UDP_PORT_IPX, ipx_handle);
1471 dissector_add("ethertype", ETHERTYPE_IPX, ipx_handle);
1472 dissector_add("chdlctype", ETHERTYPE_IPX, ipx_handle);
1473 dissector_add("ppp.protocol", PPP_IPX, ipx_handle);
1474 dissector_add("llc.dsap", SAP_NETWARE1, ipx_handle);
1475 dissector_add("llc.dsap", SAP_NETWARE2, ipx_handle);
1476 dissector_add("null.type", BSD_AF_IPX, ipx_handle);
1477 dissector_add("gre.proto", ETHERTYPE_IPX, ipx_handle);
1478 dissector_add("arcnet.protocol_id", ARCNET_PROTO_IPX, ipx_handle);
1479 dissector_add("arcnet.protocol_id", ARCNET_PROTO_NOVELL_EC, ipx_handle);
1481 spx_handle = create_dissector_handle(dissect_spx, proto_spx);
1482 dissector_add("ipx.packet_type", IPX_PACKET_TYPE_SPX, spx_handle);
1484 ipxsap_handle = find_dissector("ipxsap");
1485 dissector_add("ipx.socket", IPX_SOCKET_SAP, ipxsap_handle);
1487 ipxrip_handle = create_dissector_handle(dissect_ipxrip, proto_ipxrip);
1488 dissector_add("ipx.socket", IPX_SOCKET_IPXRIP, ipxrip_handle);
1490 ipxmsg_handle = create_dissector_handle(dissect_ipxmsg, proto_ipxmsg);
1491 dissector_add("ipx.socket", IPX_SOCKET_IPX_MESSAGE, ipxmsg_handle);
1492 dissector_add("ipx.socket", IPX_SOCKET_IPX_MESSAGE1, ipxmsg_handle);
1494 data_handle = find_dissector("data");