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.131 2003/06/10 05:38:52 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;
72 static gint ett_ipx = -1;
74 static dissector_table_t ipx_type_dissector_table;
75 static dissector_table_t ipx_socket_dissector_table;
76 static dissector_table_t spx_socket_dissector_table;
78 static int proto_spx = -1;
79 static int hf_spx_connection_control = -1;
80 static int hf_spx_connection_control_sys = -1;
81 static int hf_spx_connection_control_send_ack = -1;
82 static int hf_spx_connection_control_attn = -1;
83 static int hf_spx_connection_control_eom = -1;
84 static int hf_spx_datastream_type = -1;
85 static int hf_spx_src_id = -1;
86 static int hf_spx_dst_id = -1;
87 static int hf_spx_seq_nr = -1;
88 static int hf_spx_ack_nr = -1;
89 static int hf_spx_all_nr = -1;
90 static int hf_spx_rexmt_frame = -1;
92 static gint ett_spx = -1;
93 static gint ett_spx_connctrl = -1;
95 static int proto_ipxrip = -1;
96 static int hf_ipxrip_request = -1;
97 static int hf_ipxrip_response = -1;
99 static gint ett_ipxrip = -1;
101 static int proto_sap = -1;
102 static int hf_sap_request = -1;
103 static int hf_sap_response = -1;
105 static gint ett_ipxsap = -1;
106 static gint ett_ipxsap_server = -1;
108 static gint ett_ipxmsg = -1;
109 static int proto_ipxmsg = -1;
110 static int hf_msg_conn = -1;
111 static int hf_msg_sigchar = -1;
113 static dissector_handle_t data_handle;
116 dissect_spx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
119 dissect_ipxrip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
122 dissect_ipxsap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
125 dissect_ipxmsg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
127 #define UDP_PORT_IPX 213 /* RFC 1234 */
129 #define IPX_HEADER_LEN 30 /* It's *always* 30 bytes */
131 /* ================================================================= */
133 /* ================================================================= */
134 const value_string ipx_socket_vals[] = {
135 { IPX_SOCKET_PING_CISCO, "CISCO PING" },
136 { IPX_SOCKET_NCP, "NCP" },
137 { IPX_SOCKET_SAP, "SAP" },
138 { IPX_SOCKET_IPXRIP, "RIP" },
139 { IPX_SOCKET_NETBIOS, "NetBIOS" },
140 { IPX_SOCKET_DIAGNOSTIC, "Diagnostic" },
141 { IPX_SOCKET_SERIALIZATION, "Serialization" },
142 { IPX_SOCKET_NWLINK_SMB_SERVER, "NWLink SMB Server" },
143 { IPX_SOCKET_NWLINK_SMB_NAMEQUERY, "NWLink SMB Name Query" },
144 { IPX_SOCKET_NWLINK_SMB_REDIR, "NWLink SMB Redirector" },
145 { IPX_SOCKET_NWLINK_SMB_MAILSLOT, "NWLink SMB Mailslot Datagram" },
146 { IPX_SOCKET_NWLINK_SMB_MESSENGER, "NWLink SMB Messenger" },
147 { IPX_SOCKET_NWLINK_SMB_BROWSE, "NWLink SMB Browse" },
148 { IPX_SOCKET_ATTACHMATE_GW, "Attachmate Gateway" },
149 { IPX_SOCKET_IPX_MESSAGE, "IPX Message" },
150 { IPX_SOCKET_IPX_MESSAGE1, "IPX Message" },
151 { IPX_SOCKET_SNMP_AGENT, "SNMP Agent" },
152 { IPX_SOCKET_SNMP_SINK, "SNMP Sink" },
153 { IPX_SOCKET_PING_NOVELL, "Novell PING" },
154 { IPX_SOCKET_UDP_TUNNEL, "UDP Tunnel" },
155 { IPX_SOCKET_TCP_TUNNEL, "TCP Tunnel" },
156 { IPX_SOCKET_TCP_TUNNEL, "TCP Tunnel" },
157 { IPX_SOCKET_ADSM, "ADSM" },
158 { IPX_SOCKET_EIGRP, "Cisco EIGRP for IPX" },
159 { IPX_SOCKET_NLSP, "NetWare Link Services Protocol" },
160 { IPX_SOCKET_IPXWAN, "IPX WAN" },
161 { SPX_SOCKET_PA, "NDPS Printer Agent/PSM" },
162 { SPX_SOCKET_BROKER, "NDPS Broker" },
163 { SPX_SOCKET_SRS, "NDPS Service Registry Service" },
164 { SPX_SOCKET_ENS, "NDPS Event Notification Service" },
165 { SPX_SOCKET_RMS, "NDPS Remote Management Service" },
166 { SPX_SOCKET_NOTIFY_LISTENER, "NDPS Notify Listener" },
167 { 0xE885, "NT Server-RPC/GW" },
168 { 0x400C, "HP LaserJet/QuickSilver" },
169 { 0x907B, "SMS Testing and Development" },
170 { 0x8F83, "Powerchute UPS Monitoring" },
171 { 0x4006, "NetWare Directory Server" },
172 { 0x8104, "NetWare 386" },
177 socket_text(guint16 socket)
179 return val_to_str(socket, ipx_socket_vals, "Unknown");
182 static const value_string ipx_packet_type_vals[] = {
183 { IPX_PACKET_TYPE_IPX, "IPX" },
184 { IPX_PACKET_TYPE_RIP, "RIP" },
185 { IPX_PACKET_TYPE_ECHO, "Echo" },
186 { IPX_PACKET_TYPE_ERROR, "Error" },
187 { IPX_PACKET_TYPE_PEP, "PEP" }, /* Packet Exchange Packet */
188 { IPX_PACKET_TYPE_SPX, "SPX" },
189 { 16, "Experimental Protocol" },
190 { IPX_PACKET_TYPE_NCP, "NCP" },
191 { 18, "Experimental Protocol" },
192 { 19, "Experimental Protocol" },
193 { IPX_PACKET_TYPE_WANBCAST, "NetBIOS Broadcast" },
194 { 21, "Experimental Protocol" },
195 { 22, "Experimental Protocol" },
196 { 23, "Experimental Protocol" },
197 { 24, "Experimental Protocol" },
198 { 25, "Experimental Protocol" },
199 { 26, "Experimental Protocol" },
200 { 27, "Experimental Protocol" },
201 { 28, "Experimental Protocol" },
202 { 29, "Experimental Protocol" },
203 { 30, "Experimental Protocol" },
204 { 31, "Experimental Protocol" },
208 static const value_string ipxmsg_sigchar_vals[] = {
209 { '?', "Poll inactive station" },
210 { 'Y', "Station is still using the connection" },
211 { '!', "Broadcast message waiting" },
216 capture_ipx(packet_counts *ld)
222 dissect_ipx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
226 proto_tree *ipx_tree;
229 const guint8 *src_net_node, *dst_net_node;
231 guint8 ipx_type, ipx_hops;
234 guint16 ipx_dsocket, ipx_ssocket;
235 guint16 first_socket, second_socket;
237 if (check_col(pinfo->cinfo, COL_PROTOCOL))
238 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPX");
239 if (check_col(pinfo->cinfo, COL_INFO))
240 col_clear(pinfo->cinfo, COL_INFO);
242 /* Calculate here for use in pinfo and in tree */
243 ipx_dsocket = tvb_get_ntohs(tvb, 16);
244 ipx_ssocket = tvb_get_ntohs(tvb, 28);
245 ipx_type = tvb_get_guint8(tvb, 5);
246 ipx_length = tvb_get_ntohs(tvb, 2);
248 pinfo->ptype = PT_IPX;
249 pinfo->srcport = ipx_ssocket;
250 pinfo->destport = ipx_dsocket;
252 /* Adjust the tvbuff length to include only the IPX datagram. */
253 set_actual_length(tvb, ipx_length);
255 src_net_node = tvb_get_ptr(tvb, 18, 10);
256 dst_net_node = tvb_get_ptr(tvb, 6, 10);
258 SET_ADDRESS(&pinfo->net_src, AT_IPX, 10, src_net_node);
259 SET_ADDRESS(&pinfo->src, AT_IPX, 10, src_net_node);
260 SET_ADDRESS(&pinfo->net_dst, AT_IPX, 10, dst_net_node);
261 SET_ADDRESS(&pinfo->dst, AT_IPX, 10, dst_net_node);
263 if (check_col(pinfo->cinfo, COL_INFO))
264 col_add_fstr(pinfo->cinfo, COL_INFO, "%s (0x%04x)",
265 socket_text(ipx_dsocket), ipx_dsocket);
269 ti = proto_tree_add_item(tree, proto_ipx, tvb, 0, IPX_HEADER_LEN, FALSE);
270 ipx_tree = proto_item_add_subtree(ti, ett_ipx);
272 proto_tree_add_item(ipx_tree, hf_ipx_checksum, tvb, 0, 2, FALSE);
273 proto_tree_add_uint_format(ipx_tree, hf_ipx_len, tvb, 2, 2, ipx_length,
274 "Length: %d bytes", ipx_length);
275 ipx_hops = tvb_get_guint8(tvb, 4);
276 proto_tree_add_uint_format(ipx_tree, hf_ipx_hops, tvb, 4, 1, ipx_hops,
277 "Transport Control: %d hops", ipx_hops);
278 proto_tree_add_uint(ipx_tree, hf_ipx_packet_type, tvb, 5, 1, ipx_type);
281 proto_tree_add_item(ipx_tree, hf_ipx_dnet, tvb, 6, 4, FALSE);
282 proto_tree_add_item(ipx_tree, hf_ipx_dnode, tvb, 10, 6, FALSE);
283 proto_tree_add_uint(ipx_tree, hf_ipx_dsocket, tvb, 16, 2,
287 proto_tree_add_item(ipx_tree, hf_ipx_snet, tvb, 18, 4, FALSE);
288 proto_tree_add_item(ipx_tree, hf_ipx_snode, tvb, 22, 6, FALSE);
289 proto_tree_add_uint(ipx_tree, hf_ipx_ssocket, tvb, 28, 2,
293 /* Make the next tvbuff */
294 next_tvb = tvb_new_subset(tvb, IPX_HEADER_LEN, -1, -1);
297 * Let the subdissector know what type of IPX packet this is.
299 pinfo->ipxptype = ipx_type;
302 * Check the socket numbers before we check the packet type;
303 * we've seen non-NCP packets with a type of NCP and a
304 * destination socket of IPX_SOCKET_IPX_MESSAGE, and SAP
305 * packets with a type of NCP and a destination socket of
308 * We've seen NCP packets with a type of NCP, a source socket of
309 * IPX_SOCKET_NCP, and a destination socket of IPX_SOCKET_IPX_MESSAGE,
310 * and we've seen NCP packets with a type of NCP, a source socket of
311 * IPX_SOCKET_IPX_MESSAGE, and a destination socket of
312 * IPX_SOCKET_NCP, so testing the destination socket first doesn't
313 * always give the right answer. We've also seen SAP packets with
314 * a source socket of IPX_SOCKET_SAP and a destination socket of
315 * IPX_SOCKET_IPX_MESSAGE.
317 * Unfortunately, we've also seen packets with a source socket
318 * of IPX_SOCKET_NWLINK_SMB_SERVER and a destination socket
319 * of IPX_SOCKET_NWLINK_SMB_NAMEQUERY that were NMPI packets,
320 * not SMB packets, so testing the lower-valued socket first
321 * also doesn't always give the right answer.
323 * So we start out assuming we should test the lower-numbered
324 * socket number first, but, if the higher-numbered socket is
325 * IPX_SOCKET_NWLINK_SMB_NAMEQUERY, we assume that it's a
326 * NMPI query, and test only that socket.
328 if (ipx_ssocket > ipx_dsocket) {
329 first_socket = ipx_dsocket;
330 second_socket = ipx_ssocket;
332 first_socket = ipx_ssocket;
333 second_socket = ipx_dsocket;
335 if (second_socket != IPX_SOCKET_NWLINK_SMB_NAMEQUERY) {
336 if (dissector_try_port(ipx_socket_dissector_table, first_socket,
337 next_tvb, pinfo, tree))
340 if (dissector_try_port(ipx_socket_dissector_table, second_socket,
341 next_tvb, pinfo, tree))
345 * Neither of them are known; try the packet type, which will
346 * at least let us, for example, dissect SPX packets as SPX.
348 if (dissector_try_port(ipx_type_dissector_table, ipx_type, next_tvb,
352 call_dissector(data_handle,next_tvb, pinfo, tree);
354 /* ================================================================= */
355 /* SPX Hash Functions */
356 /* ================================================================= */
359 conversation_t *conversation;
371 * Structure attached to retransmitted SPX frames; it contains the
372 * frame number of the original transmission.
378 static GHashTable *spx_hash = NULL;
379 static GMemChunk *spx_hash_keys = NULL;
380 static GMemChunk *spx_hash_values = NULL;
381 static GMemChunk *spx_rexmit_infos = NULL;
385 spx_equal(gconstpointer v, gconstpointer v2)
387 const spx_hash_key *val1 = (const spx_hash_key*)v;
388 const spx_hash_key *val2 = (const spx_hash_key*)v2;
390 if (val1->conversation == val2->conversation &&
391 val1->spx_src == val2->spx_src &&
392 val1->spx_seq == val2->spx_seq) {
399 spx_hash_func(gconstpointer v)
401 const spx_hash_key *spx_key = (const spx_hash_key*)v;
402 return GPOINTER_TO_UINT(spx_key->conversation) + spx_key->spx_src;
405 /* Initializes the hash table and the mem_chunk area each time a new
406 * file is loaded or re-loaded in ethereal */
408 spx_init_protocol(void)
412 g_hash_table_destroy(spx_hash);
414 g_mem_chunk_destroy(spx_hash_keys);
416 g_mem_chunk_destroy(spx_hash_values);
417 if (spx_rexmit_infos)
418 g_mem_chunk_destroy(spx_rexmit_infos);
420 spx_hash = g_hash_table_new(spx_hash_func, spx_equal);
421 spx_hash_keys = g_mem_chunk_new("spx_hash_keys",
422 sizeof(spx_hash_key),
423 SPX_PACKET_INIT_COUNT * sizeof(spx_hash_key),
425 spx_hash_values = g_mem_chunk_new("spx_hash_values",
426 sizeof(spx_hash_value),
427 SPX_PACKET_INIT_COUNT * sizeof(spx_hash_value),
429 spx_rexmit_infos = g_mem_chunk_new("spx_rexmit_infos",
430 sizeof(spx_rexmit_infos),
431 SPX_PACKET_INIT_COUNT * sizeof(spx_rexmit_infos),
435 /* After the sequential run, we don't need the spx hash table, or
436 * the keys and values, anymore; the lookups have already been done
437 * and the relevant info saved as SPX private data with the frame
438 * if the frame was a retransmission. */
440 spx_postseq_cleanup(void)
443 /* Destroy the hash, but don't clean up request_condition data. */
444 g_hash_table_destroy(spx_hash);
448 g_mem_chunk_destroy(spx_hash_keys);
449 spx_hash_keys = NULL;
451 if (spx_hash_values) {
452 g_mem_chunk_destroy(spx_hash_values);
453 spx_hash_values = NULL;
455 /* Don't free the spx_rexmit_infos, as they're
456 * needed during random-access processing of the proto_tree.*/
460 spx_hash_insert(conversation_t *conversation, guint32 spx_src, guint16 spx_seq)
463 spx_hash_value *value;
465 /* Now remember the packet, so we can find it if we later. */
466 key = g_mem_chunk_alloc(spx_hash_keys);
467 key->conversation = conversation;
468 key->spx_src = spx_src;
469 key->spx_seq = spx_seq;
471 value = g_mem_chunk_alloc(spx_hash_values);
476 g_hash_table_insert(spx_hash, key, value);
481 /* Returns the spx_hash_value*, or NULL if not found. */
483 spx_hash_lookup(conversation_t *conversation, guint32 spx_src, guint32 spx_seq)
487 key.conversation = conversation;
488 key.spx_src = spx_src;
489 key.spx_seq = spx_seq;
491 return g_hash_table_lookup(spx_hash, &key);
494 /* ================================================================= */
496 /* ================================================================= */
498 #define SPX_SYS_PACKET 0x80
499 #define SPX_SEND_ACK 0x40
500 #define SPX_ATTN 0x20
504 spx_conn_ctrl(guint8 ctrl)
508 static const value_string conn_vals[] = {
509 { 0x00, "Data, No Ack Required" },
510 { SPX_EOM, "End-of-Message" },
511 { SPX_ATTN, "Attention" },
512 { SPX_SEND_ACK, "Acknowledgment Required"},
513 { SPX_SEND_ACK|SPX_EOM, "Send Ack: End Message"},
514 { SPX_SYS_PACKET, "System Packet"},
515 { SPX_SYS_PACKET|SPX_SEND_ACK, "System Packet: Send Ack"},
519 p = match_strval((ctrl & 0xf0), conn_vals );
530 spx_datastream(guint8 type)
534 return "End-of-Connection";
536 return "End-of-Connection Acknowledgment";
542 #define SPX_HEADER_LEN 12
545 dissect_spx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
547 proto_tree *spx_tree = NULL;
552 guint8 datastream_type;
553 const char *datastream_type_string;
555 const char *spx_msg_string;
556 guint16 low_socket, high_socket;
558 conversation_t *conversation;
559 spx_hash_value *pkt_value;
560 spx_rexmit_info *spx_rexmit_info;
563 if (check_col(pinfo->cinfo, COL_PROTOCOL))
564 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SPX");
565 if (check_col(pinfo->cinfo, COL_INFO))
566 col_set_str(pinfo->cinfo, COL_INFO, "SPX");
569 ti = proto_tree_add_item(tree, proto_spx, tvb, 0, SPX_HEADER_LEN, FALSE);
570 spx_tree = proto_item_add_subtree(ti, ett_spx);
573 conn_ctrl = tvb_get_guint8(tvb, 0);
574 spx_msg_string = spx_conn_ctrl(conn_ctrl);
575 if (check_col(pinfo->cinfo, COL_INFO))
576 col_append_fstr(pinfo->cinfo, COL_INFO, " %s", spx_msg_string);
578 ti = proto_tree_add_uint_format(spx_tree, hf_spx_connection_control, tvb,
580 "Connection Control: %s (0x%02X)",
581 spx_msg_string, conn_ctrl);
582 cc_tree = proto_item_add_subtree(ti, ett_spx_connctrl);
583 proto_tree_add_boolean(cc_tree, hf_spx_connection_control_sys, tvb,
585 proto_tree_add_boolean(cc_tree, hf_spx_connection_control_send_ack, tvb,
587 proto_tree_add_boolean(cc_tree, hf_spx_connection_control_attn, tvb,
589 proto_tree_add_boolean(cc_tree, hf_spx_connection_control_eom, tvb,
593 datastream_type = tvb_get_guint8(tvb, 1);
594 datastream_type_string = spx_datastream(datastream_type);
595 if (datastream_type_string != NULL) {
596 if (check_col(pinfo->cinfo, COL_INFO))
597 col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
598 datastream_type_string);
601 if (datastream_type_string != NULL) {
602 proto_tree_add_uint_format(spx_tree, hf_spx_datastream_type, tvb,
603 1, 1, datastream_type,
604 "Datastream Type: %s (0x%02X)",
605 datastream_type_string,
608 proto_tree_add_uint_format(spx_tree, hf_spx_datastream_type, tvb,
609 1, 1, datastream_type,
610 "Datastream Type: 0x%02X",
613 proto_tree_add_item(spx_tree, hf_spx_src_id, tvb, 2, 2, FALSE);
614 proto_tree_add_item(spx_tree, hf_spx_dst_id, tvb, 4, 2, FALSE);
616 spx_seq = tvb_get_ntohs(tvb, 6);
618 proto_tree_add_uint(spx_tree, hf_spx_seq_nr, tvb, 6, 2, spx_seq);
619 proto_tree_add_item(spx_tree, hf_spx_ack_nr, tvb, 8, 2, FALSE);
620 proto_tree_add_item(spx_tree, hf_spx_all_nr, tvb, 10, 2, FALSE);
624 * SPX is Connection Oriented and Delivery Guaranteed.
625 * On the first pass, we need to flag retransmissions by the SPX
626 * protocol, so that subdissectors know whether a packet was
629 * We start out by creating a conversation for this direction of the
630 * IPX session; we use "pinfo->srcport" twice, so that we have
631 * separate conversations for the two directions.
633 * XXX - that might not work correctly if there's more than one
634 * SPX session using that source port; can that happen? If so,
635 * we should probably use the direction, as well as the conversation,
636 * as part of the hash key; if we do that, we can probably just
637 * use PT_IPX as the port type, and possibly get rid of PT_NCP.
641 * http://developer.novell.com/research/appnotes/1995/december/03/apv.htm
643 * the sequence number is not incremented for system packets, so
644 * presumably that means there is no notion of a system packet
645 * being retransmitted; that document also says that system
646 * packets are used as "I'm still here" keepalives and as
647 * acknowledgements (presumably meaning ACK-only packets), which
648 * suggests that they might not be ACKed and thus might not
651 if (conn_ctrl & SPX_SYS_PACKET) {
653 * It's a system packet, so it isn't a retransmission.
655 spx_rexmit_info = NULL;
658 * Not a system packet - check for retransmissions.
660 if (!pinfo->fd->flags.visited) {
661 conversation = find_conversation(&pinfo->src,
662 &pinfo->dst, PT_NCP, pinfo->srcport,
664 if (conversation == NULL) {
666 * It's not part of any conversation - create
669 conversation = conversation_new(&pinfo->src,
670 &pinfo->dst, PT_NCP, pinfo->srcport,
675 * Now we'll hash the SPX header and use the result
676 * of that, plus the conversation, as a hash key to
677 * identify this packet.
679 * If we don't find it in the hash table, it's not a
680 * retransmission, otherwise it is. If we don't find
681 * it, we enter it into the hash table, with the
683 * If we do, we attach to this frame a structure giving
684 * the frame number of the original transmission, so
685 * that we, and subdissectors, know it's a
688 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);
689 pkt_value = spx_hash_lookup(conversation, src, spx_seq);
690 if (pkt_value == NULL) {
692 * Not found in the hash table.
693 * Enter it into the hash table.
695 pkt_value = spx_hash_insert(conversation, src,
697 pkt_value->spx_ack = tvb_get_ntohs(tvb, 8);
698 pkt_value->spx_all = tvb_get_ntohs(tvb, 10);
699 pkt_value->num = pinfo->fd->num;
702 * This is not a retransmission, so we shouldn't
703 * have any retransmission indicator.
705 spx_rexmit_info = NULL;
708 * Found in the hash table. Mark this frame as
711 spx_rexmit_info = g_mem_chunk_alloc(spx_rexmit_infos);
712 spx_rexmit_info->num = pkt_value->num;
713 p_add_proto_data(pinfo->fd, proto_spx,
718 * Do we have per-packet SPX data for this frame?
719 * If so, it's a retransmission, and the per-packet
720 * data indicates which frame had the original
723 spx_rexmit_info = p_get_proto_data(pinfo->fd,
729 * It's a retransmission if we have a retransmission indicator.
730 * Flag this as a retransmission, but don't pass it to the
733 if (spx_rexmit_info != NULL) {
734 if (check_col(pinfo->cinfo, COL_INFO)) {
735 col_add_fstr(pinfo->cinfo, COL_INFO,
736 "[Retransmission] Original Packet %u",
737 spx_rexmit_info->num);
740 proto_tree_add_uint_format(spx_tree, hf_spx_rexmt_frame,
741 tvb, 0, 0, spx_rexmit_info->num,
742 "This is a retransmission of frame %u",
743 spx_rexmit_info->num);
744 if (tvb_length_remaining(tvb, SPX_HEADER_LEN) > 0) {
745 proto_tree_add_text(spx_tree, tvb,
747 "Retransmitted data");
753 if (tvb_reported_length_remaining(tvb, SPX_HEADER_LEN) > 0) {
755 * Call subdissectors based on the IPX socket numbers; a
756 * subdissector might have registered with our IPX socket
757 * dissector table rather than the IPX dissector's socket
760 * Assume the lower-numbered socket number is more likely
761 * to be the right one, along the lines of what we do for
762 * TCP and UDP. We've seen NCP packets with a type of NCP,
763 * a source socket of IPX_SOCKET_NCP, and a destination
764 * socket of IPX_SOCKET_IPX_MESSAGE, and we've seen NCP
765 * packets with a type of NCP, a source socket of
766 * IPX_SOCKET_IPX_MESSAGE, and a destination socket of
769 if (pinfo->srcport > pinfo->destport) {
770 low_socket = pinfo->destport;
771 high_socket = pinfo->srcport;
773 low_socket = pinfo->srcport;
774 high_socket = pinfo->destport;
778 * Pass information to subdissectors.
780 spx_info.eom = conn_ctrl & SPX_EOM;
781 spx_info.datastream_type = datastream_type;
782 pinfo->private_data = &spx_info;
784 next_tvb = tvb_new_subset(tvb, SPX_HEADER_LEN, -1, -1);
785 if (dissector_try_port(spx_socket_dissector_table, low_socket,
786 next_tvb, pinfo, tree))
788 if (dissector_try_port(spx_socket_dissector_table, high_socket,
789 next_tvb, pinfo, tree))
791 call_dissector(data_handle, next_tvb, pinfo, tree);
795 /* ================================================================= */
797 /* ================================================================= */
799 dissect_ipxmsg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
801 proto_tree *msg_tree;
803 guint8 conn_number, sig_char;
805 if (check_col(pinfo->cinfo, COL_PROTOCOL))
806 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPX MSG");
807 if (check_col(pinfo->cinfo, COL_INFO))
808 col_clear(pinfo->cinfo, COL_INFO);
810 conn_number = tvb_get_guint8(tvb, 0);
811 sig_char = tvb_get_guint8(tvb, 1);
813 if (check_col(pinfo->cinfo, COL_INFO)) {
814 col_add_fstr(pinfo->cinfo, COL_INFO,
816 val_to_str(sig_char, ipxmsg_sigchar_vals, "Unknown Signature Char"), conn_number);
820 ti = proto_tree_add_item(tree, proto_ipxmsg, tvb, 0, -1, FALSE);
821 msg_tree = proto_item_add_subtree(ti, ett_ipxmsg);
823 proto_tree_add_uint(msg_tree, hf_msg_conn, tvb, 0, 1, conn_number);
824 proto_tree_add_uint(msg_tree, hf_msg_sigchar, tvb, 1, 1, sig_char);
829 /* ================================================================= */
831 /* ================================================================= */
833 dissect_ipxrip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
835 proto_tree *rip_tree;
838 struct ipx_rt_def route;
840 int available_length;
842 static char *rip_type[3] = { "Request", "Response", "Unknown" };
844 if (check_col(pinfo->cinfo, COL_PROTOCOL))
845 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPX RIP");
846 if (check_col(pinfo->cinfo, COL_INFO))
847 col_clear(pinfo->cinfo, COL_INFO);
849 operation = tvb_get_ntohs(tvb, 0) - 1;
851 if (check_col(pinfo->cinfo, COL_INFO)) {
852 /* rip_types 0 and 1 are valid, anything else becomes 2 or "Unknown" */
853 col_set_str(pinfo->cinfo, COL_INFO, rip_type[MIN(operation, 2)]);
857 ti = proto_tree_add_item(tree, proto_ipxrip, tvb, 0, -1, FALSE);
858 rip_tree = proto_item_add_subtree(ti, ett_ipxrip);
861 proto_tree_add_text(rip_tree, tvb, 0, 2,
862 "RIP packet type: %s", rip_type[operation]);
864 if (operation == 0) {
865 proto_tree_add_boolean_hidden(rip_tree,
869 proto_tree_add_boolean_hidden(rip_tree,
876 proto_tree_add_text(rip_tree, tvb, 0, 2, "Unknown RIP packet type");
879 available_length = tvb_reported_length(tvb);
880 for (cursor = 2; cursor < available_length; cursor += 8) {
881 tvb_memcpy(tvb, (guint8 *)&route.network, cursor, 4);
882 route.hops = tvb_get_ntohs(tvb, cursor+4);
883 route.ticks = tvb_get_ntohs(tvb, cursor+6);
885 if (operation == IPX_RIP_REQUEST - 1) {
886 proto_tree_add_text(rip_tree, tvb, cursor, 8,
887 "Route Vector: %s, %d hop%s, %d tick%s",
888 ipxnet_to_string((guint8*)&route.network),
889 route.hops, route.hops == 1 ? "" : "s",
890 route.ticks, route.ticks == 1 ? "" : "s");
893 proto_tree_add_text(rip_tree, tvb, cursor, 8,
894 "Route Vector: %s, %d hop%s, %d tick%s (%d ms)",
895 ipxnet_to_string((guint8*)&route.network),
896 route.hops, route.hops == 1 ? "" : "s",
897 route.ticks, route.ticks == 1 ? "" : "s",
898 route.ticks * 1000 / 18);
905 * Some of these are from ncpfs, others are from the book,
906 * others are from the page at
908 * http://www.iana.org/assignments/novell-sap-numbers
910 * and some from the page at
912 * http://www.rware.demon.co.uk/ipxsap.htm
914 * (see also the page at
916 * http://developer.novell.com/research/appnotes/1998/february/03/06.htm
918 * which has a huge list - but many of the entries list only the
919 * organization owning the SAP type, not what the type is for).
921 const value_string server_vals[] = {
922 { 0x0000, "Unknown" },
924 { 0x0002, "User Group" },
925 { 0x0003, "Print Queue or Print Group" },
926 { 0x0004, "File Server (SLIST source)" },
927 { 0x0005, "Job Server" },
928 { 0x0006, "Gateway" },
929 { 0x0007, "Print Server or Silent Print Server" },
930 { 0x0008, "Archive Queue" },
931 { 0x0009, "Archive Server" },
932 { 0x000a, "Job Queue" },
933 { 0x000b, "Administration" },
934 { 0x000F, "Novell TI-RPC" },
935 { 0x0017, "Diagnostics" },
936 { 0x0020, "NetBIOS" },
937 { 0x0021, "NAS SNA Gateway" },
938 { 0x0023, "NACS Async Gateway or Asynchronous Gateway" },
939 { 0x0024, "Remote Bridge or Routing Service" },
940 { 0x0026, "Bridge Server or Asynchronous Bridge Server" },
941 { 0x0027, "TCP/IP Gateway Server" },
942 { 0x0028, "Point to Point (Eicon) X.25 Bridge Server" },
943 { 0x0029, "Eicon 3270 Gateway" },
944 { 0x002a, "CHI Corp" },
945 { 0x002c, "PC Chalkboard" },
946 { 0x002d, "Time Synchronization Server or Asynchronous Timer" },
947 { 0x002e, "ARCserve 5.0 / Palindrome Backup Director 4.x (PDB4)" },
948 { 0x0045, "DI3270 Gateway" },
949 { 0x0047, "Advertising Print Server" },
950 { 0x004a, "NetBlazer Modems" },
951 { 0x004b, "Btrieve VAP/NLM 5.0" },
952 { 0x004c, "NetWare SQL VAP/NLM Server" },
953 { 0x004d, "Xtree Network Version/NetWare XTree" },
954 { 0x0050, "Btrieve VAP 4.11" },
955 { 0x0052, "QuickLink (Cubix)" },
956 { 0x0053, "Print Queue User" },
957 { 0x0058, "Multipoint X.25 Eicon Router" },
958 { 0x0060, "STLB/NLM" },
959 { 0x0064, "ARCserve" },
960 { 0x0066, "ARCserve 3.0" },
961 { 0x0072, "WAN Copy Utility" },
962 { 0x007a, "TES-NetWare for VMS" },
963 { 0x0092, "WATCOM Debugger or Emerald Tape Backup Server" },
964 { 0x0095, "DDA OBGYN" },
965 { 0x0098, "NetWare Access Server (Asynchronous gateway)" },
966 { 0x009a, "NetWare for VMS II or Named Pipe Server" },
967 { 0x009b, "NetWare Access Server" },
968 { 0x009e, "Portable NetWare Server or SunLink NVT" },
969 { 0x00a1, "Powerchute APC UPS NLM" },
970 { 0x00aa, "LAWserve" },
971 { 0x00ac, "Compaq IDA Status Monitor" },
972 { 0x0100, "PIPE STAIL" },
973 { 0x0102, "LAN Protect Bindery" },
974 { 0x0103, "Oracle DataBase Server" },
975 { 0x0107, "NetWare 386 or RSPX Remote Console" },
976 { 0x010f, "Novell SNA Gateway" },
977 { 0x0111, "Test Server" },
978 { 0x0112, "Print Server (HP)" },
979 { 0x0114, "CSA MUX (f/Communications Executive)" },
980 { 0x0115, "CSA LCA (f/Communications Executive)" },
981 { 0x0116, "CSA CM (f/Communications Executive)" },
982 { 0x0117, "CSA SMA (f/Communications Executive)" },
983 { 0x0118, "CSA DBA (f/Communications Executive)" },
984 { 0x0119, "CSA NMA (f/Communications Executive)" },
985 { 0x011a, "CSA SSA (f/Communications Executive)" },
986 { 0x011b, "CSA STATUS (f/Communications Executive)" },
987 { 0x011e, "CSA APPC (f/Communications Executive)" },
988 { 0x0126, "SNA TEST SSA Profile" },
989 { 0x012a, "CSA TRACE (f/Communications Executive)" },
990 { 0x012b, "NetWare for SAA" },
991 { 0x012e, "IKARUS virus scan utility" },
992 { 0x0130, "Communications Executive" },
993 { 0x0133, "NNS Domain Server or NetWare Naming Services Domain" },
994 { 0x0135, "NetWare Naming Services Profile" },
995 { 0x0137, "NetWare 386 Print Queue or NNS Print Queue" },
996 { 0x0141, "LAN Spool Server (Vap, Intel)" },
997 { 0x0152, "IRMALAN Gateway" },
998 { 0x0154, "Named Pipe Server" },
999 { 0x0166, "NetWare Management" },
1000 { 0x0168, "Intel PICKIT Comm Server or Intel CAS Talk Server" },
1001 { 0x0173, "Compaq" },
1002 { 0x0174, "Compaq SNMP Agent" },
1003 { 0x0175, "Compaq" },
1004 { 0x0180, "XTree Server or XTree Tools" },
1005 { 0x018A, "NASI services broadcast server (Novell)" },
1006 { 0x01b0, "GARP Gateway (net research)" },
1007 { 0x01b1, "Binfview (Lan Support Group)" },
1008 { 0x01bf, "Intel LanDesk Manager" },
1009 { 0x01ca, "AXTEC" },
1010 { 0x01cb, "Shiva NetModem/E" },
1011 { 0x01cc, "Shiva LanRover/E" },
1012 { 0x01cd, "Shiva LanRover/T" },
1013 { 0x01ce, "Shiva Universal" },
1014 { 0x01d8, "Castelle FAXPress Server" },
1015 { 0x01da, "Castelle LANPress Print Server" },
1016 { 0x01dc, "Castelle FAX/Xerox 7033 Fax Server/Excel Lan Fax" },
1017 { 0x01f0, "LEGATO" },
1018 { 0x01f5, "LEGATO" },
1019 { 0x0233, "NMS Agent or NetWare Management Agent" },
1020 { 0x0237, "NMS IPX Discovery or LANtern Read/Write Channel" },
1021 { 0x0238, "NMS IP Discovery or LANtern Trap/Alarm Channel" },
1022 { 0x023a, "LANtern" },
1023 { 0x023c, "MAVERICK" },
1024 { 0x023f, "SMS Testing and Development" },
1025 { 0x024e, "NetWare Connect" },
1026 { 0x024f, "NASI server broadcast (Cisco)" },
1027 { 0x026a, "Network Management (NMS) Service Console" },
1028 { 0x026b, "Time Synchronization Server (NetWare 4.x)" },
1029 { 0x0278, "Directory Server (NetWare 4.x)" },
1030 { 0x027b, "NetWare Management Agent" },
1031 { 0x0280, "Novell File and Printer Sharing Service for PC" },
1032 { 0x0304, "Novell SAA Gateway" },
1033 { 0x0308, "COM or VERMED 1" },
1034 { 0x030a, "Galacticomm's Worldgroup Server" },
1035 { 0x030c, "Intel Netport 2 or HP JetDirect or HP Quicksilver" },
1036 { 0x0320, "Attachmate Gateway" },
1037 { 0x0327, "Microsoft Diagnostics" },
1038 { 0x0328, "WATCOM SQL server" },
1039 { 0x0335, "MultiTech Systems Multisynch Comm Server" },
1040 { 0x0343, "Xylogics Remote Access Server or LAN Modem" },
1041 { 0x0355, "Arcada Backup Exec" },
1042 { 0x0358, "MSLCD1" },
1043 { 0x0361, "NETINELO" },
1044 { 0x037e, "Powerchute UPS Monitoring" },
1045 { 0x037f, "ViruSafe Notify" },
1046 { 0x0386, "HP Bridge" },
1047 { 0x0387, "HP Hub" },
1048 { 0x0394, "NetWare SAA Gateway" },
1049 { 0x039b, "Lotus Notes" },
1050 { 0x03b7, "Certus Anti Virus NLM" },
1051 { 0x03c4, "ARCserve 4.0 (Cheyenne)" },
1052 { 0x03c7, "LANspool 3.5 (Intel)" },
1053 { 0x03d7, "Lexmark printer server (type 4033-011)" },
1054 { 0x03d8, "Lexmark XLE printer server (type 4033-301)" },
1055 { 0x03dd, "Banyan ENS for NetWare Client NLM" },
1056 { 0x03de, "Gupta Sequel Base Server or NetWare SQL" },
1057 { 0x03e1, "Univel Unixware" },
1058 { 0x03e4, "Univel Unixware" },
1059 { 0x03fc, "Intel Netport" },
1060 { 0x03fd, "Intel Print Server Queue" },
1061 { 0x040A, "ipnServer" },
1062 { 0x040D, "LVERRMAN" },
1063 { 0x040E, "LVLIC" },
1064 { 0x0414, "NET Silicon (DPI)/Kyocera" },
1065 { 0x0429, "Site Lock Virus (Brightworks)" },
1066 { 0x0432, "UFHELP R" },
1067 { 0x0433, "Synoptics 281x Advanced SNMP Agent" },
1068 { 0x0444, "Microsoft NT SNA Server" },
1069 { 0x0448, "Oracle" },
1070 { 0x044c, "ARCserve 5.01" },
1071 { 0x0457, "Canon GP55 Running on a Canon GP55 network printer" },
1072 { 0x045a, "QMS Printers" },
1073 { 0x045b, "Dell SCSI Array (DSA) Monitor" },
1074 { 0x0491, "NetBlazer Modems" },
1075 { 0x04ac, "On-Time Scheduler NLM" },
1076 { 0x04b0, "CD-Net (Meridian)" },
1077 { 0x0513, "Emulex NQA" },
1078 { 0x0520, "Site Lock Checks" },
1079 { 0x0529, "Site Lock Checks (Brightworks)" },
1080 { 0x052d, "Citrix OS/2 App Server" },
1081 { 0x0535, "Tektronix" },
1082 { 0x0536, "Milan" },
1083 { 0x055d, "Attachmate SNA gateway" },
1084 { 0x056b, "IBM 8235 modem server" },
1085 { 0x056c, "Shiva LanRover/E PLUS" },
1086 { 0x056d, "Shiva LanRover/T PLUS" },
1087 { 0x0580, "McAfee's NetShield anti-virus" },
1088 { 0x05B8, "NLM to workstation communication (Revelation Software)" },
1089 { 0x05BA, "Compatible Systems Routers" },
1090 { 0x05BE, "Cheyenne Hierarchical Storage Manager" },
1091 { 0x0606, "JCWatermark Imaging" },
1092 { 0x060c, "AXIS Network Printer" },
1093 { 0x0610, "Adaptec SCSI Management" },
1094 { 0x0621, "IBM AntiVirus NLM" },
1095 { 0x0640, "Microsoft Gateway Services for NetWare" },
1096 /* { 0x0640, "NT Server-RPC/GW for NW/Win95 User Level Sec" }, */
1097 { 0x064e, "Microsoft Internet Information Server" },
1098 { 0x067b, "Microsoft Win95/98 File and Print Sharing for NetWare" },
1099 { 0x067c, "Microsoft Win95/98 File and Print Sharing for NetWare" },
1100 { 0x076C, "Xerox" },
1101 { 0x079b, "Shiva LanRover/E 115" },
1102 { 0x079c, "Shiva LanRover/T 115" },
1103 { 0x07B4, "Cubix WorldDesk" },
1104 { 0x07c2, "Quarterdeck IWare Connect V2.x NLM" },
1105 { 0x07c1, "Quarterdeck IWare Connect V3.x NLM" },
1106 { 0x0810, "ELAN License Server Demo" },
1107 { 0x0824, "Shiva LanRover Access Switch/E" },
1108 { 0x086a, "ISSC collector NLMs" },
1109 { 0x087f, "ISSC DAS agent for AIX" },
1110 { 0x0880, "Intel Netport PRO" },
1111 { 0x0881, "Intel Netport PRO" },
1112 { 0x0b29, "Site Lock" },
1113 { 0x0c29, "Site Lock Applications" },
1114 { 0x0c2c, "Licensing Server" },
1115 { 0x2101, "Performance Technology Instant Internet" },
1116 { 0x2380, "LAI Site Lock" },
1117 { 0x238c, "Meeting Maker" },
1118 { 0x4808, "Site Lock Server or Site Lock Metering VAP/NLM" },
1119 { 0x5555, "Site Lock User" },
1120 { 0x6312, "Tapeware" },
1121 { 0x6f00, "Rabbit Gateway (3270)" },
1122 { 0x7703, "MODEM" },
1123 { 0x8002, "NetPort Printers (Intel) or LANport" },
1124 { 0x8003, "SEH InterCon Printserver" },
1125 { 0x8008, "WordPerfect Network Version" },
1126 { 0x85BE, "Cisco Enhanced Interior Routing Protocol (EIGRP)" },
1127 { 0x8888, "WordPerfect Network Version or Quick Network Management" },
1128 { 0x9000, "McAfee's NetShield anti-virus" },
1129 { 0x9604, "CSA-NT_MON" },
1130 { 0xb6a8, "Ocean Isle Reachout Remote Control" },
1131 { 0xf11f, "Site Lock Metering VAP/NLM" },
1132 { 0xf1ff, "Site Lock" },
1133 { 0xf503, "Microsoft SQL Server" },
1134 { 0xf905, "IBM Time and Place/2 application" },
1135 { 0xfbfb, "TopCall III fax server" },
1136 { 0xffff, "Any Service or Wildcard" },
1141 dissect_ipxsap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1143 proto_tree *sap_tree, *s_tree;
1146 struct sap_query query;
1147 guint16 server_type;
1148 char server_name[48];
1149 guint16 server_port;
1150 guint16 intermediate_network;
1152 static char *sap_type[4] = { "General Query", "General Response",
1153 "Nearest Query", "Nearest Response" };
1155 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1156 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPX SAP");
1157 if (check_col(pinfo->cinfo, COL_INFO))
1158 col_clear(pinfo->cinfo, COL_INFO);
1160 query.query_type = tvb_get_ntohs(tvb, 0);
1161 query.server_type = tvb_get_ntohs(tvb, 2);
1163 if (check_col(pinfo->cinfo, COL_INFO)) {
1164 if (query.query_type >= 1 && query.query_type <= 4) {
1165 col_set_str(pinfo->cinfo, COL_INFO, sap_type[query.query_type - 1]);
1168 col_set_str(pinfo->cinfo, COL_INFO, "Unknown Packet Type");
1173 ti = proto_tree_add_item(tree, proto_sap, tvb, 0, -1, FALSE);
1174 sap_tree = proto_item_add_subtree(ti, ett_ipxsap);
1176 if (query.query_type >= 1 && query.query_type <= 4) {
1177 proto_tree_add_text(sap_tree, tvb, 0, 2, sap_type[query.query_type - 1]);
1178 if ((query.query_type - 1) % 2) {
1179 proto_tree_add_boolean_hidden(sap_tree,
1183 proto_tree_add_boolean_hidden(sap_tree,
1189 proto_tree_add_text(sap_tree, tvb, 0, 2,
1190 "Unknown SAP Packet Type %d", query.query_type);
1193 if (query.query_type == IPX_SAP_GENERAL_RESPONSE ||
1194 query.query_type == IPX_SAP_NEAREST_RESPONSE) { /* responses */
1196 int available_length = tvb_reported_length(tvb);
1197 for (cursor = 2; (cursor + 64) <= available_length; cursor += 64) {
1198 server_type = tvb_get_ntohs(tvb, cursor);
1199 tvb_memcpy(tvb, (guint8 *)server_name,
1202 ti = proto_tree_add_text(sap_tree, tvb, cursor+2, 48,
1203 "Server Name: %.48s", server_name);
1204 s_tree = proto_item_add_subtree(ti, ett_ipxsap_server);
1206 proto_tree_add_text(s_tree, tvb, cursor, 2, "Server Type: %s (0x%04X)",
1207 val_to_str(server_type, server_vals, "Unknown"),
1209 proto_tree_add_text(s_tree, tvb, cursor+50, 4, "Network: %s",
1210 ipxnet_to_string(tvb_get_ptr(tvb, cursor+50, 4)));
1211 proto_tree_add_text(s_tree, tvb, cursor+54, 6, "Node: %s",
1212 ether_to_str(tvb_get_ptr(tvb, cursor+54, 6)));
1213 server_port = tvb_get_ntohs(tvb, cursor+60);
1214 proto_tree_add_text(s_tree, tvb, cursor+60, 2, "Socket: %s (0x%04x)",
1215 socket_text(server_port),
1217 intermediate_network = tvb_get_ntohs(tvb, cursor+62);
1218 proto_tree_add_text(s_tree, tvb, cursor+62, 2,
1219 "Intermediate Networks: %d",
1220 intermediate_network);
1223 else { /* queries */
1224 proto_tree_add_text(sap_tree, tvb, 2, 2, "Server Type: %s (0x%04X)",
1225 val_to_str(query.server_type, server_vals, "Unknown"),
1232 proto_register_ipx(void)
1234 static hf_register_info hf_ipx[] = {
1236 { "Checksum", "ipx.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1240 { "Length", "ipx.len", FT_UINT16, BASE_DEC, NULL, 0x0,
1244 { "Transport Control (Hops)", "ipx.hops", FT_UINT8, BASE_DEC, NULL, 0x0,
1247 { &hf_ipx_packet_type,
1248 { "Packet Type", "ipx.packet_type", FT_UINT8, BASE_HEX, VALS(ipx_packet_type_vals),
1253 { "Destination Network","ipx.dst.net", FT_IPXNET, BASE_NONE, NULL, 0x0,
1257 { "Destination Node", "ipx.dst.node", FT_ETHER, BASE_NONE, NULL, 0x0,
1261 { "Destination Socket", "ipx.dst.socket", FT_UINT16, BASE_HEX,
1262 VALS(ipx_socket_vals), 0x0,
1266 { "Source Network","ipx.src.net", FT_IPXNET, BASE_NONE, NULL, 0x0,
1270 { "Source Node", "ipx.src.node", FT_ETHER, BASE_NONE, NULL, 0x0,
1274 { "Source Socket", "ipx.src.socket", FT_UINT16, BASE_HEX,
1275 VALS(ipx_socket_vals), 0x0,
1279 static hf_register_info hf_spx[] = {
1280 { &hf_spx_connection_control,
1281 { "Connection Control", "spx.ctl",
1282 FT_UINT8, BASE_HEX, NULL, 0x0,
1285 { &hf_spx_connection_control_sys,
1286 { "System Packet", "spx.ctl.sys",
1287 FT_BOOLEAN, 8, NULL, SPX_SYS_PACKET,
1290 { &hf_spx_connection_control_send_ack,
1291 { "Send Ack", "spx.ctl.send_ack",
1292 FT_BOOLEAN, 8, NULL, SPX_SEND_ACK,
1295 { &hf_spx_connection_control_attn,
1296 { "Attention", "spx.ctl.attn",
1297 FT_BOOLEAN, 8, NULL, SPX_ATTN,
1300 { &hf_spx_connection_control_eom,
1301 { "End of Message", "spx.ctl.eom",
1302 FT_BOOLEAN, 8, NULL, SPX_EOM,
1305 { &hf_spx_datastream_type,
1306 { "Datastream type", "spx.type",
1307 FT_UINT8, BASE_HEX, NULL, 0x0,
1311 { "Source Connection ID", "spx.src",
1312 FT_UINT16, BASE_DEC, NULL, 0x0,
1316 { "Destination Connection ID", "spx.dst",
1317 FT_UINT16, BASE_DEC, NULL, 0x0,
1321 { "Sequence Number", "spx.seq",
1322 FT_UINT16, BASE_DEC, NULL, 0x0,
1326 { "Acknowledgment Number", "spx.ack",
1327 FT_UINT16, BASE_DEC, NULL, 0x0,
1331 { "Allocation Number", "spx.alloc",
1332 FT_UINT16, BASE_DEC, NULL, 0x0,
1335 { &hf_spx_rexmt_frame,
1336 { "Retransmitted Frame Number", "spx.rexmt_frame",
1337 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1341 static hf_register_info hf_ipxrip[] = {
1342 { &hf_ipxrip_request,
1343 { "Request", "ipxrip.request",
1344 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1345 "TRUE if IPX RIP request", HFILL }},
1347 { &hf_ipxrip_response,
1348 { "Response", "ipxrip.response",
1349 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1350 "TRUE if IPX RIP response", HFILL }}
1353 static hf_register_info hf_sap[] = {
1355 { "Request", "ipxsap.request",
1356 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1357 "TRUE if SAP request", HFILL }},
1360 { "Response", "ipxsap.response",
1361 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1362 "TRUE if SAP response", HFILL }}
1365 static hf_register_info hf_ipxmsg[] = {
1367 { "Connection Number", "ipxmsg.conn",
1368 FT_UINT8, BASE_DEC, NULL, 0x0,
1369 "Connection Number", HFILL }},
1372 { "Signature Char", "ipxmsg.sigchar",
1373 FT_UINT8, BASE_DEC, VALS(ipxmsg_sigchar_vals), 0x0,
1374 "Signature Char", HFILL }}
1377 static gint *ett[] = {
1387 proto_ipx = proto_register_protocol("Internetwork Packet eXchange",
1389 proto_register_field_array(proto_ipx, hf_ipx, array_length(hf_ipx));
1391 register_dissector("ipx", dissect_ipx, proto_ipx);
1393 proto_spx = proto_register_protocol("Sequenced Packet eXchange",
1395 proto_register_field_array(proto_spx, hf_spx, array_length(hf_spx));
1397 proto_ipxrip = proto_register_protocol("IPX Routing Information Protocol",
1398 "IPX RIP", "ipxrip");
1399 proto_register_field_array(proto_ipxrip, hf_ipxrip, array_length(hf_ipxrip));
1401 proto_ipxmsg = proto_register_protocol("IPX Message", "IPX MSG",
1403 proto_register_field_array(proto_ipxmsg, hf_ipxmsg, array_length(hf_ipxmsg));
1405 proto_sap = proto_register_protocol("Service Advertisement Protocol",
1406 "IPX SAP", "ipxsap");
1407 register_dissector("ipxsap", dissect_ipxsap, proto_sap);
1409 proto_register_field_array(proto_sap, hf_sap, array_length(hf_sap));
1411 proto_register_subtree_array(ett, array_length(ett));
1413 ipx_type_dissector_table = register_dissector_table("ipx.packet_type",
1414 "IPX packet type", FT_UINT8, BASE_HEX);
1415 ipx_socket_dissector_table = register_dissector_table("ipx.socket",
1416 "IPX socket", FT_UINT16, BASE_HEX);
1417 spx_socket_dissector_table = register_dissector_table("spx.socket",
1418 "SPX socket", FT_UINT16, BASE_HEX);
1420 register_init_routine(&spx_init_protocol);
1421 register_postseq_cleanup_routine(&spx_postseq_cleanup);
1425 proto_reg_handoff_ipx(void)
1427 dissector_handle_t ipx_handle, spx_handle;
1428 dissector_handle_t ipxsap_handle, ipxrip_handle;
1429 dissector_handle_t ipxmsg_handle;
1431 ipx_handle = find_dissector("ipx");
1432 dissector_add("udp.port", UDP_PORT_IPX, ipx_handle);
1433 dissector_add("ethertype", ETHERTYPE_IPX, ipx_handle);
1434 dissector_add("chdlctype", ETHERTYPE_IPX, ipx_handle);
1435 dissector_add("ppp.protocol", PPP_IPX, ipx_handle);
1436 dissector_add("llc.dsap", SAP_NETWARE1, ipx_handle);
1437 dissector_add("llc.dsap", SAP_NETWARE2, ipx_handle);
1438 dissector_add("null.type", BSD_AF_IPX, ipx_handle);
1439 dissector_add("gre.proto", ETHERTYPE_IPX, ipx_handle);
1440 dissector_add("arcnet.protocol_id", ARCNET_PROTO_IPX, ipx_handle);
1441 dissector_add("arcnet.protocol_id", ARCNET_PROTO_NOVELL_EC, ipx_handle);
1443 spx_handle = create_dissector_handle(dissect_spx, proto_spx);
1444 dissector_add("ipx.packet_type", IPX_PACKET_TYPE_SPX, spx_handle);
1446 ipxsap_handle = find_dissector("ipxsap");
1447 dissector_add("ipx.socket", IPX_SOCKET_SAP, ipxsap_handle);
1449 ipxrip_handle = create_dissector_handle(dissect_ipxrip, proto_ipxrip);
1450 dissector_add("ipx.socket", IPX_SOCKET_IPXRIP, ipxrip_handle);
1452 ipxmsg_handle = create_dissector_handle(dissect_ipxmsg, proto_ipxmsg);
1453 dissector_add("ipx.socket", IPX_SOCKET_IPX_MESSAGE, ipxmsg_handle);
1454 dissector_add("ipx.socket", IPX_SOCKET_IPX_MESSAGE1, ipxmsg_handle);
1456 data_handle = find_dissector("data");