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.137 2003/10/03 09:09:34 sahlberg 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>
48 static int ipx_tap = -1;
50 #define SPX_PACKET_INIT_COUNT 200
52 /* The information in this module (IPX, SPX, NCP) comes from:
53 NetWare LAN Analysis, Second Edition
54 Laura A. Chappell and Dan E. Hakes
56 Novell Press, San Jose.
59 And from the ncpfs source code by Volker Lendecke
63 static int proto_ipx = -1;
64 static int hf_ipx_checksum = -1;
65 static int hf_ipx_len = -1;
66 static int hf_ipx_src = -1;
67 static int hf_ipx_dst = -1;
68 static int hf_ipx_addr = -1;
69 static int hf_ipx_hops = -1;
70 static int hf_ipx_packet_type = -1;
71 static int hf_ipx_dnet = -1;
72 static int hf_ipx_dnode = -1;
73 static int hf_ipx_dsocket = -1;
74 static int hf_ipx_snet = -1;
75 static int hf_ipx_snode = -1;
76 static int hf_ipx_ssocket = -1;
77 static int hf_ipx_net = -1;
78 static int hf_ipx_node = -1;
79 static int hf_ipx_socket = -1;
81 static gint ett_ipx = -1;
83 static dissector_table_t ipx_type_dissector_table;
84 static dissector_table_t ipx_socket_dissector_table;
85 static dissector_table_t spx_socket_dissector_table;
87 static int proto_spx = -1;
88 static int hf_spx_connection_control = -1;
89 static int hf_spx_connection_control_sys = -1;
90 static int hf_spx_connection_control_send_ack = -1;
91 static int hf_spx_connection_control_attn = -1;
92 static int hf_spx_connection_control_eom = -1;
93 static int hf_spx_datastream_type = -1;
94 static int hf_spx_src_id = -1;
95 static int hf_spx_dst_id = -1;
96 static int hf_spx_seq_nr = -1;
97 static int hf_spx_ack_nr = -1;
98 static int hf_spx_all_nr = -1;
99 static int hf_spx_rexmt_frame = -1;
101 static gint ett_spx = -1;
102 static gint ett_spx_connctrl = -1;
104 static int proto_ipxrip = -1;
105 static int hf_ipxrip_request = -1;
106 static int hf_ipxrip_response = -1;
108 static gint ett_ipxrip = -1;
110 static int proto_sap = -1;
111 static int hf_sap_request = -1;
112 static int hf_sap_response = -1;
114 static gint ett_ipxsap = -1;
115 static gint ett_ipxsap_server = -1;
117 static gint ett_ipxmsg = -1;
118 static int proto_ipxmsg = -1;
119 static int hf_msg_conn = -1;
120 static int hf_msg_sigchar = -1;
122 static dissector_handle_t data_handle;
125 dissect_spx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
128 dissect_ipxrip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
131 dissect_ipxsap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
134 dissect_ipxmsg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
136 #define UDP_PORT_IPX 213 /* RFC 1234 */
138 #define IPX_HEADER_LEN 30 /* It's *always* 30 bytes */
140 /* ================================================================= */
142 /* ================================================================= */
143 const value_string ipx_socket_vals[] = {
144 { IPX_SOCKET_PING_CISCO, "CISCO PING" },
145 { IPX_SOCKET_NCP, "NCP" },
146 { IPX_SOCKET_SAP, "SAP" },
147 { IPX_SOCKET_IPXRIP, "RIP" },
148 { IPX_SOCKET_NETBIOS, "NetBIOS" },
149 { IPX_SOCKET_DIAGNOSTIC, "Diagnostic" },
150 { IPX_SOCKET_SERIALIZATION, "Serialization" },
151 { IPX_SOCKET_NWLINK_SMB_SERVER, "NWLink SMB Server" },
152 { IPX_SOCKET_NWLINK_SMB_NAMEQUERY, "NWLink SMB Name Query" },
153 { IPX_SOCKET_NWLINK_SMB_REDIR, "NWLink SMB Redirector" },
154 { IPX_SOCKET_NWLINK_SMB_MAILSLOT, "NWLink SMB Mailslot Datagram" },
155 { IPX_SOCKET_NWLINK_SMB_MESSENGER, "NWLink SMB Messenger" },
156 { IPX_SOCKET_NWLINK_SMB_BROWSE, "NWLink SMB Browse" },
157 { IPX_SOCKET_ATTACHMATE_GW, "Attachmate Gateway" },
158 { IPX_SOCKET_IPX_MESSAGE, "IPX Message" },
159 { IPX_SOCKET_IPX_MESSAGE1, "IPX Message" },
160 { IPX_SOCKET_SNMP_AGENT, "SNMP Agent" },
161 { IPX_SOCKET_SNMP_SINK, "SNMP Sink" },
162 { IPX_SOCKET_PING_NOVELL, "Novell PING" },
163 { IPX_SOCKET_UDP_TUNNEL, "UDP Tunnel" },
164 { IPX_SOCKET_TCP_TUNNEL, "TCP Tunnel" },
165 { IPX_SOCKET_TCP_TUNNEL, "TCP Tunnel" },
166 { IPX_SOCKET_ADSM, "ADSM" },
167 { IPX_SOCKET_EIGRP, "Cisco EIGRP for IPX" },
168 { IPX_SOCKET_NLSP, "NetWare Link Services Protocol" },
169 { IPX_SOCKET_IPXWAN, "IPX WAN" },
170 { SPX_SOCKET_PA, "NDPS Printer Agent/PSM" },
171 { SPX_SOCKET_BROKER, "NDPS Broker" },
172 { SPX_SOCKET_SRS, "NDPS Service Registry Service" },
173 { SPX_SOCKET_ENS, "NDPS Event Notification Service" },
174 { SPX_SOCKET_RMS, "NDPS Remote Management Service" },
175 { SPX_SOCKET_NOTIFY_LISTENER, "NDPS Notify Listener" },
176 { 0xE885, "NT Server-RPC/GW" },
177 { 0x400C, "HP LaserJet/QuickSilver" },
178 { 0x907B, "SMS Testing and Development" },
179 { 0x8F83, "Powerchute UPS Monitoring" },
180 { 0x4006, "NetWare Directory Server" },
181 { 0x8104, "NetWare 386" },
186 socket_text(guint16 socket)
188 return val_to_str(socket, ipx_socket_vals, "Unknown");
191 static const value_string ipx_packet_type_vals[] = {
192 { IPX_PACKET_TYPE_IPX, "IPX" },
193 { IPX_PACKET_TYPE_RIP, "RIP" },
194 { IPX_PACKET_TYPE_ECHO, "Echo" },
195 { IPX_PACKET_TYPE_ERROR, "Error" },
196 { IPX_PACKET_TYPE_PEP, "PEP" }, /* Packet Exchange Packet */
197 { IPX_PACKET_TYPE_SPX, "SPX" },
198 { 16, "Experimental Protocol" },
199 { IPX_PACKET_TYPE_NCP, "NCP" },
200 { 18, "Experimental Protocol" },
201 { 19, "Experimental Protocol" },
202 { IPX_PACKET_TYPE_WANBCAST, "NetBIOS Broadcast" },
203 { 21, "Experimental Protocol" },
204 { 22, "Experimental Protocol" },
205 { 23, "Experimental Protocol" },
206 { 24, "Experimental Protocol" },
207 { 25, "Experimental Protocol" },
208 { 26, "Experimental Protocol" },
209 { 27, "Experimental Protocol" },
210 { 28, "Experimental Protocol" },
211 { 29, "Experimental Protocol" },
212 { 30, "Experimental Protocol" },
213 { 31, "Experimental Protocol" },
217 static const value_string ipxmsg_sigchar_vals[] = {
218 { '?', "Poll inactive station" },
219 { 'Y', "Station is still using the connection" },
220 { '!', "Broadcast message waiting" },
225 capture_ipx(packet_counts *ld)
231 dissect_ipx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
235 proto_tree *ipx_tree = NULL;
236 proto_item *ti = NULL;
238 const guint8 *src_net_node, *dst_net_node;
242 guint16 first_socket, second_socket;
243 guint32 ipx_snet, ipx_dnet;
244 const guint8 *ipx_snode, *ipx_dnode;
245 static ipxhdr_t ipxh_arr[4];
246 static int ipx_current=0;
253 ipxh=&ipxh_arr[ipx_current];
256 if (check_col(pinfo->cinfo, COL_PROTOCOL))
257 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPX");
258 if (check_col(pinfo->cinfo, COL_INFO))
259 col_clear(pinfo->cinfo, COL_INFO);
261 /* Calculate here for use in pinfo and in tree */
262 ipxh->ipx_dsocket = tvb_get_ntohs(tvb, 16);
263 ipxh->ipx_ssocket = tvb_get_ntohs(tvb, 28);
264 ipxh->ipx_type = tvb_get_guint8(tvb, 5);
265 ipxh->ipx_length = tvb_get_ntohs(tvb, 2);
267 pinfo->ptype = PT_IPX;
268 pinfo->srcport = ipxh->ipx_ssocket;
269 pinfo->destport = ipxh->ipx_dsocket;
271 /* Adjust the tvbuff length to include only the IPX datagram. */
272 set_actual_length(tvb, ipxh->ipx_length);
274 src_net_node = tvb_get_ptr(tvb, 18, 10);
275 dst_net_node = tvb_get_ptr(tvb, 6, 10);
277 SET_ADDRESS(&pinfo->net_src, AT_IPX, 10, src_net_node);
278 SET_ADDRESS(&pinfo->src, AT_IPX, 10, src_net_node);
279 SET_ADDRESS(&ipxh->ipx_src, AT_IPX, 10, src_net_node);
280 SET_ADDRESS(&pinfo->net_dst, AT_IPX, 10, dst_net_node);
281 SET_ADDRESS(&pinfo->dst, AT_IPX, 10, dst_net_node);
282 SET_ADDRESS(&ipxh->ipx_dst, AT_IPX, 10, dst_net_node);
284 if (check_col(pinfo->cinfo, COL_INFO))
285 col_add_fstr(pinfo->cinfo, COL_INFO, "%s (0x%04x)",
286 socket_text(ipxh->ipx_dsocket), ipxh->ipx_dsocket);
290 ti = proto_tree_add_item(tree, proto_ipx, tvb, 0, IPX_HEADER_LEN, FALSE);
291 ipx_tree = proto_item_add_subtree(ti, ett_ipx);
294 str=address_to_str(&pinfo->net_src);
295 proto_tree_add_string_hidden(ipx_tree, hf_ipx_src, tvb, 0, 0, str);
296 proto_tree_add_string_hidden(ipx_tree, hf_ipx_addr, tvb, 0, 0, str);
297 str=address_to_str(&pinfo->net_dst);
298 proto_tree_add_string_hidden(ipx_tree, hf_ipx_dst, tvb, 0, 0, str);
299 proto_tree_add_string_hidden(ipx_tree, hf_ipx_addr, tvb, 0, 0, str);
301 proto_tree_add_item(ipx_tree, hf_ipx_checksum, tvb, 0, 2, FALSE);
302 proto_tree_add_uint_format(ipx_tree, hf_ipx_len, tvb, 2, 2, ipxh->ipx_length,
303 "Length: %d bytes", ipxh->ipx_length);
304 ipx_hops = tvb_get_guint8(tvb, 4);
305 proto_tree_add_uint_format(ipx_tree, hf_ipx_hops, tvb, 4, 1, ipx_hops,
306 "Transport Control: %d hops", ipx_hops);
307 proto_tree_add_uint(ipx_tree, hf_ipx_packet_type, tvb, 5, 1, ipxh->ipx_type);
310 ipx_dnet = tvb_get_ntohl(tvb, 6);
311 proto_tree_add_ipxnet(ipx_tree, hf_ipx_dnet, tvb, 6, 4,
313 proto_tree_add_ipxnet_hidden(ipx_tree, hf_ipx_net, tvb, 6, 4,
315 ipx_dnode = tvb_get_ptr(tvb, 10, 6);
316 proto_tree_add_ether(ipx_tree, hf_ipx_dnode, tvb, 10, 6,
318 proto_tree_add_ether_hidden(ipx_tree, hf_ipx_node, tvb, 10, 6,
320 proto_tree_add_uint(ipx_tree, hf_ipx_dsocket, tvb, 16, 2,
322 proto_tree_add_uint_hidden(ipx_tree, hf_ipx_socket, tvb, 16, 2,
326 ipx_snet = tvb_get_ntohl(tvb, 18);
327 proto_tree_add_ipxnet(ipx_tree, hf_ipx_snet, tvb, 18, 4,
329 proto_tree_add_ipxnet_hidden(ipx_tree, hf_ipx_net, tvb, 18, 4,
331 ipx_snode = tvb_get_ptr(tvb, 22, 6);
332 proto_tree_add_ether(ipx_tree, hf_ipx_snode, tvb, 22, 6,
334 proto_tree_add_ether_hidden(ipx_tree, hf_ipx_node, tvb, 22, 6,
336 proto_tree_add_uint(ipx_tree, hf_ipx_ssocket, tvb, 28, 2,
338 proto_tree_add_uint_hidden(ipx_tree, hf_ipx_socket, tvb, 28, 2,
341 /* Make the next tvbuff */
342 next_tvb = tvb_new_subset(tvb, IPX_HEADER_LEN, -1, -1);
345 * Let the subdissector know what type of IPX packet this is.
347 pinfo->ipxptype = ipxh->ipx_type;
350 * Check the socket numbers before we check the packet type;
351 * we've seen non-NCP packets with a type of NCP and a
352 * destination socket of IPX_SOCKET_IPX_MESSAGE, and SAP
353 * packets with a type of NCP and a destination socket of
356 * We've seen NCP packets with a type of NCP, a source socket of
357 * IPX_SOCKET_NCP, and a destination socket of IPX_SOCKET_IPX_MESSAGE,
358 * and we've seen NCP packets with a type of NCP, a source socket of
359 * IPX_SOCKET_IPX_MESSAGE, and a destination socket of
360 * IPX_SOCKET_NCP, so testing the destination socket first doesn't
361 * always give the right answer. We've also seen SAP packets with
362 * a source socket of IPX_SOCKET_SAP and a destination socket of
363 * IPX_SOCKET_IPX_MESSAGE.
365 * Unfortunately, we've also seen packets with a source socket
366 * of IPX_SOCKET_NWLINK_SMB_SERVER and a destination socket
367 * of IPX_SOCKET_NWLINK_SMB_NAMEQUERY that were NMPI packets,
368 * not SMB packets, so testing the lower-valued socket first
369 * also doesn't always give the right answer.
371 * So we start out assuming we should test the lower-numbered
372 * socket number first, but, if the higher-numbered socket is
373 * IPX_SOCKET_NWLINK_SMB_NAMEQUERY, we assume that it's a
374 * NMPI query, and test only that socket.
376 if (ipxh->ipx_ssocket > ipxh->ipx_dsocket) {
377 first_socket = ipxh->ipx_dsocket;
378 second_socket = ipxh->ipx_ssocket;
380 first_socket = ipxh->ipx_ssocket;
381 second_socket = ipxh->ipx_dsocket;
384 tap_queue_packet(ipx_tap, pinfo, ipxh);
386 if (second_socket != IPX_SOCKET_NWLINK_SMB_NAMEQUERY) {
387 if (dissector_try_port(ipx_socket_dissector_table, first_socket,
388 next_tvb, pinfo, tree))
391 if (dissector_try_port(ipx_socket_dissector_table, second_socket,
392 next_tvb, pinfo, tree))
396 * Neither of them are known; try the packet type, which will
397 * at least let us, for example, dissect SPX packets as SPX.
399 if (dissector_try_port(ipx_type_dissector_table, ipxh->ipx_type, next_tvb,
403 call_dissector(data_handle,next_tvb, pinfo, tree);
405 /* ================================================================= */
406 /* SPX Hash Functions */
407 /* ================================================================= */
410 conversation_t *conversation;
422 * Structure attached to retransmitted SPX frames; it contains the
423 * frame number of the original transmission.
429 static GHashTable *spx_hash = NULL;
430 static GMemChunk *spx_hash_keys = NULL;
431 static GMemChunk *spx_hash_values = NULL;
432 static GMemChunk *spx_rexmit_infos = NULL;
436 spx_equal(gconstpointer v, gconstpointer v2)
438 const spx_hash_key *val1 = (const spx_hash_key*)v;
439 const spx_hash_key *val2 = (const spx_hash_key*)v2;
441 if (val1->conversation == val2->conversation &&
442 val1->spx_src == val2->spx_src &&
443 val1->spx_seq == val2->spx_seq) {
450 spx_hash_func(gconstpointer v)
452 const spx_hash_key *spx_key = (const spx_hash_key*)v;
453 return GPOINTER_TO_UINT(spx_key->conversation) + spx_key->spx_src;
456 /* Initializes the hash table and the mem_chunk area each time a new
457 * file is loaded or re-loaded in ethereal */
459 spx_init_protocol(void)
463 g_hash_table_destroy(spx_hash);
465 g_mem_chunk_destroy(spx_hash_keys);
467 g_mem_chunk_destroy(spx_hash_values);
468 if (spx_rexmit_infos)
469 g_mem_chunk_destroy(spx_rexmit_infos);
471 spx_hash = g_hash_table_new(spx_hash_func, spx_equal);
472 spx_hash_keys = g_mem_chunk_new("spx_hash_keys",
473 sizeof(spx_hash_key),
474 SPX_PACKET_INIT_COUNT * sizeof(spx_hash_key),
476 spx_hash_values = g_mem_chunk_new("spx_hash_values",
477 sizeof(spx_hash_value),
478 SPX_PACKET_INIT_COUNT * sizeof(spx_hash_value),
480 spx_rexmit_infos = g_mem_chunk_new("spx_rexmit_infos",
481 sizeof(spx_rexmit_infos),
482 SPX_PACKET_INIT_COUNT * sizeof(spx_rexmit_infos),
486 /* After the sequential run, we don't need the spx hash table, or
487 * the keys and values, anymore; the lookups have already been done
488 * and the relevant info saved as SPX private data with the frame
489 * if the frame was a retransmission. */
491 spx_postseq_cleanup(void)
494 /* Destroy the hash, but don't clean up request_condition data. */
495 g_hash_table_destroy(spx_hash);
499 g_mem_chunk_destroy(spx_hash_keys);
500 spx_hash_keys = NULL;
502 if (spx_hash_values) {
503 g_mem_chunk_destroy(spx_hash_values);
504 spx_hash_values = NULL;
506 /* Don't free the spx_rexmit_infos, as they're
507 * needed during random-access processing of the proto_tree.*/
511 spx_hash_insert(conversation_t *conversation, guint32 spx_src, guint16 spx_seq)
514 spx_hash_value *value;
516 /* Now remember the packet, so we can find it if we later. */
517 key = g_mem_chunk_alloc(spx_hash_keys);
518 key->conversation = conversation;
519 key->spx_src = spx_src;
520 key->spx_seq = spx_seq;
522 value = g_mem_chunk_alloc(spx_hash_values);
527 g_hash_table_insert(spx_hash, key, value);
532 /* Returns the spx_hash_value*, or NULL if not found. */
534 spx_hash_lookup(conversation_t *conversation, guint32 spx_src, guint32 spx_seq)
538 key.conversation = conversation;
539 key.spx_src = spx_src;
540 key.spx_seq = spx_seq;
542 return g_hash_table_lookup(spx_hash, &key);
545 /* ================================================================= */
547 /* ================================================================= */
549 #define SPX_SYS_PACKET 0x80
550 #define SPX_SEND_ACK 0x40
551 #define SPX_ATTN 0x20
555 spx_conn_ctrl(guint8 ctrl)
559 static const value_string conn_vals[] = {
560 { 0x00, "Data, No Ack Required" },
561 { SPX_EOM, "End-of-Message" },
562 { SPX_ATTN, "Attention" },
563 { SPX_SEND_ACK, "Acknowledgment Required"},
564 { SPX_SEND_ACK|SPX_EOM, "Send Ack: End Message"},
565 { SPX_SYS_PACKET, "System Packet"},
566 { SPX_SYS_PACKET|SPX_SEND_ACK, "System Packet: Send Ack"},
570 p = match_strval((ctrl & 0xf0), conn_vals );
581 spx_datastream(guint8 type)
585 return "End-of-Connection";
587 return "End-of-Connection Acknowledgment";
593 #define SPX_HEADER_LEN 12
596 dissect_spx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
598 proto_tree *spx_tree = NULL;
603 guint8 datastream_type;
604 const char *datastream_type_string;
606 const char *spx_msg_string;
607 guint16 low_socket, high_socket;
609 conversation_t *conversation;
610 spx_hash_value *pkt_value;
611 spx_rexmit_info *spx_rexmit_info;
614 if (check_col(pinfo->cinfo, COL_PROTOCOL))
615 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SPX");
616 if (check_col(pinfo->cinfo, COL_INFO))
617 col_set_str(pinfo->cinfo, COL_INFO, "SPX");
620 ti = proto_tree_add_item(tree, proto_spx, tvb, 0, SPX_HEADER_LEN, FALSE);
621 spx_tree = proto_item_add_subtree(ti, ett_spx);
624 conn_ctrl = tvb_get_guint8(tvb, 0);
625 spx_msg_string = spx_conn_ctrl(conn_ctrl);
626 if (check_col(pinfo->cinfo, COL_INFO))
627 col_append_fstr(pinfo->cinfo, COL_INFO, " %s", spx_msg_string);
629 ti = proto_tree_add_uint_format(spx_tree, hf_spx_connection_control, tvb,
631 "Connection Control: %s (0x%02X)",
632 spx_msg_string, conn_ctrl);
633 cc_tree = proto_item_add_subtree(ti, ett_spx_connctrl);
634 proto_tree_add_boolean(cc_tree, hf_spx_connection_control_sys, tvb,
636 proto_tree_add_boolean(cc_tree, hf_spx_connection_control_send_ack, tvb,
638 proto_tree_add_boolean(cc_tree, hf_spx_connection_control_attn, tvb,
640 proto_tree_add_boolean(cc_tree, hf_spx_connection_control_eom, tvb,
644 datastream_type = tvb_get_guint8(tvb, 1);
645 datastream_type_string = spx_datastream(datastream_type);
646 if (datastream_type_string != NULL) {
647 if (check_col(pinfo->cinfo, COL_INFO))
648 col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
649 datastream_type_string);
652 if (datastream_type_string != NULL) {
653 proto_tree_add_uint_format(spx_tree, hf_spx_datastream_type, tvb,
654 1, 1, datastream_type,
655 "Datastream Type: %s (0x%02X)",
656 datastream_type_string,
659 proto_tree_add_uint_format(spx_tree, hf_spx_datastream_type, tvb,
660 1, 1, datastream_type,
661 "Datastream Type: 0x%02X",
664 proto_tree_add_item(spx_tree, hf_spx_src_id, tvb, 2, 2, FALSE);
665 proto_tree_add_item(spx_tree, hf_spx_dst_id, tvb, 4, 2, FALSE);
667 spx_seq = tvb_get_ntohs(tvb, 6);
669 proto_tree_add_uint(spx_tree, hf_spx_seq_nr, tvb, 6, 2, spx_seq);
670 proto_tree_add_item(spx_tree, hf_spx_ack_nr, tvb, 8, 2, FALSE);
671 proto_tree_add_item(spx_tree, hf_spx_all_nr, tvb, 10, 2, FALSE);
675 * SPX is Connection Oriented and Delivery Guaranteed.
676 * On the first pass, we need to flag retransmissions by the SPX
677 * protocol, so that subdissectors know whether a packet was
680 * We start out by creating a conversation for this direction of the
681 * IPX session; we use "pinfo->srcport" twice, so that we have
682 * separate conversations for the two directions.
684 * XXX - that might not work correctly if there's more than one
685 * SPX session using that source port; can that happen? If so,
686 * we should probably use the direction, as well as the conversation,
687 * as part of the hash key; if we do that, we can probably just
688 * use PT_IPX as the port type, and possibly get rid of PT_NCP.
692 * http://developer.novell.com/research/appnotes/1995/december/03/apv.htm
694 * the sequence number is not incremented for system packets, so
695 * presumably that means there is no notion of a system packet
696 * being retransmitted; that document also says that system
697 * packets are used as "I'm still here" keepalives and as
698 * acknowledgements (presumably meaning ACK-only packets), which
699 * suggests that they might not be ACKed and thus might not
702 if (conn_ctrl & SPX_SYS_PACKET) {
704 * It's a system packet, so it isn't a retransmission.
706 spx_rexmit_info = NULL;
709 * Not a system packet - check for retransmissions.
711 if (!pinfo->fd->flags.visited) {
712 conversation = find_conversation(&pinfo->src,
713 &pinfo->dst, PT_NCP, pinfo->srcport,
715 if (conversation == NULL) {
717 * It's not part of any conversation - create
720 conversation = conversation_new(&pinfo->src,
721 &pinfo->dst, PT_NCP, pinfo->srcport,
726 * Now we'll hash the SPX header and use the result
727 * of that, plus the conversation, as a hash key to
728 * identify this packet.
730 * If we don't find it in the hash table, it's not a
731 * retransmission, otherwise it is. If we don't find
732 * it, we enter it into the hash table, with the
734 * If we do, we attach to this frame a structure giving
735 * the frame number of the original transmission, so
736 * that we, and subdissectors, know it's a
739 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);
740 pkt_value = spx_hash_lookup(conversation, src, spx_seq);
741 if (pkt_value == NULL) {
743 * Not found in the hash table.
744 * Enter it into the hash table.
746 pkt_value = spx_hash_insert(conversation, src,
748 pkt_value->spx_ack = tvb_get_ntohs(tvb, 8);
749 pkt_value->spx_all = tvb_get_ntohs(tvb, 10);
750 pkt_value->num = pinfo->fd->num;
753 * This is not a retransmission, so we shouldn't
754 * have any retransmission indicator.
756 spx_rexmit_info = NULL;
759 * Found in the hash table. Mark this frame as
762 spx_rexmit_info = g_mem_chunk_alloc(spx_rexmit_infos);
763 spx_rexmit_info->num = pkt_value->num;
764 p_add_proto_data(pinfo->fd, proto_spx,
769 * Do we have per-packet SPX data for this frame?
770 * If so, it's a retransmission, and the per-packet
771 * data indicates which frame had the original
774 spx_rexmit_info = p_get_proto_data(pinfo->fd,
780 * It's a retransmission if we have a retransmission indicator.
781 * Flag this as a retransmission, but don't pass it to the
784 if (spx_rexmit_info != NULL) {
785 if (check_col(pinfo->cinfo, COL_INFO)) {
786 col_add_fstr(pinfo->cinfo, COL_INFO,
787 "[Retransmission] Original Packet %u",
788 spx_rexmit_info->num);
791 proto_tree_add_uint_format(spx_tree, hf_spx_rexmt_frame,
792 tvb, 0, 0, spx_rexmit_info->num,
793 "This is a retransmission of frame %u",
794 spx_rexmit_info->num);
795 if (tvb_length_remaining(tvb, SPX_HEADER_LEN) > 0) {
796 proto_tree_add_text(spx_tree, tvb,
798 "Retransmitted data");
804 if (tvb_reported_length_remaining(tvb, SPX_HEADER_LEN) > 0) {
806 * Call subdissectors based on the IPX socket numbers; a
807 * subdissector might have registered with our IPX socket
808 * dissector table rather than the IPX dissector's socket
811 * Assume the lower-numbered socket number is more likely
812 * to be the right one, along the lines of what we do for
813 * TCP and UDP. We've seen NCP packets with a type of NCP,
814 * a source socket of IPX_SOCKET_NCP, and a destination
815 * socket of IPX_SOCKET_IPX_MESSAGE, and we've seen NCP
816 * packets with a type of NCP, a source socket of
817 * IPX_SOCKET_IPX_MESSAGE, and a destination socket of
820 if (pinfo->srcport > pinfo->destport) {
821 low_socket = pinfo->destport;
822 high_socket = pinfo->srcport;
824 low_socket = pinfo->srcport;
825 high_socket = pinfo->destport;
829 * Pass information to subdissectors.
831 spx_info.eom = conn_ctrl & SPX_EOM;
832 spx_info.datastream_type = datastream_type;
833 pinfo->private_data = &spx_info;
835 next_tvb = tvb_new_subset(tvb, SPX_HEADER_LEN, -1, -1);
836 if (dissector_try_port(spx_socket_dissector_table, low_socket,
837 next_tvb, pinfo, tree))
839 if (dissector_try_port(spx_socket_dissector_table, high_socket,
840 next_tvb, pinfo, tree))
842 call_dissector(data_handle, next_tvb, pinfo, tree);
846 /* ================================================================= */
848 /* ================================================================= */
850 dissect_ipxmsg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
852 proto_tree *msg_tree;
854 guint8 conn_number, sig_char;
856 if (check_col(pinfo->cinfo, COL_PROTOCOL))
857 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPX MSG");
858 if (check_col(pinfo->cinfo, COL_INFO))
859 col_clear(pinfo->cinfo, COL_INFO);
861 conn_number = tvb_get_guint8(tvb, 0);
862 sig_char = tvb_get_guint8(tvb, 1);
864 if (check_col(pinfo->cinfo, COL_INFO)) {
865 col_add_fstr(pinfo->cinfo, COL_INFO,
867 val_to_str(sig_char, ipxmsg_sigchar_vals, "Unknown Signature Char"), conn_number);
871 ti = proto_tree_add_item(tree, proto_ipxmsg, tvb, 0, -1, FALSE);
872 msg_tree = proto_item_add_subtree(ti, ett_ipxmsg);
874 proto_tree_add_uint(msg_tree, hf_msg_conn, tvb, 0, 1, conn_number);
875 proto_tree_add_uint(msg_tree, hf_msg_sigchar, tvb, 1, 1, sig_char);
880 /* ================================================================= */
882 /* ================================================================= */
884 dissect_ipxrip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
886 proto_tree *rip_tree;
889 struct ipx_rt_def route;
891 int available_length;
893 static char *rip_type[3] = { "Request", "Response", "Unknown" };
895 if (check_col(pinfo->cinfo, COL_PROTOCOL))
896 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPX RIP");
897 if (check_col(pinfo->cinfo, COL_INFO))
898 col_clear(pinfo->cinfo, COL_INFO);
900 operation = tvb_get_ntohs(tvb, 0) - 1;
902 if (check_col(pinfo->cinfo, COL_INFO)) {
903 /* rip_types 0 and 1 are valid, anything else becomes 2 or "Unknown" */
904 col_set_str(pinfo->cinfo, COL_INFO, rip_type[MIN(operation, 2)]);
908 ti = proto_tree_add_item(tree, proto_ipxrip, tvb, 0, -1, FALSE);
909 rip_tree = proto_item_add_subtree(ti, ett_ipxrip);
912 proto_tree_add_text(rip_tree, tvb, 0, 2,
913 "RIP packet type: %s", rip_type[operation]);
915 if (operation == 0) {
916 proto_tree_add_boolean_hidden(rip_tree,
920 proto_tree_add_boolean_hidden(rip_tree,
927 proto_tree_add_text(rip_tree, tvb, 0, 2, "Unknown RIP packet type");
930 available_length = tvb_reported_length(tvb);
931 for (cursor = 2; cursor < available_length; cursor += 8) {
932 tvb_memcpy(tvb, (guint8 *)&route.network, cursor, 4);
933 route.hops = tvb_get_ntohs(tvb, cursor+4);
934 route.ticks = tvb_get_ntohs(tvb, cursor+6);
936 if (operation == IPX_RIP_REQUEST - 1) {
937 proto_tree_add_text(rip_tree, tvb, cursor, 8,
938 "Route Vector: %s, %d hop%s, %d tick%s",
939 ipxnet_to_string((guint8*)&route.network),
940 route.hops, route.hops == 1 ? "" : "s",
941 route.ticks, route.ticks == 1 ? "" : "s");
944 proto_tree_add_text(rip_tree, tvb, cursor, 8,
945 "Route Vector: %s, %d hop%s, %d tick%s (%d ms)",
946 ipxnet_to_string((guint8*)&route.network),
947 route.hops, route.hops == 1 ? "" : "s",
948 route.ticks, route.ticks == 1 ? "" : "s",
949 route.ticks * 1000 / 18);
956 * Some of these are from ncpfs, others are from the book,
957 * others are from the page at
959 * http://www.iana.org/assignments/novell-sap-numbers
961 * and some from the page at
963 * http://www.rware.demon.co.uk/ipxsap.htm
965 * (see also the page at
967 * http://developer.novell.com/research/appnotes/1998/february/03/06.htm
969 * which has a huge list - but many of the entries list only the
970 * organization owning the SAP type, not what the type is for).
972 const value_string server_vals[] = {
973 { 0x0000, "Unknown" },
975 { 0x0002, "User Group" },
976 { 0x0003, "Print Queue or Print Group" },
977 { 0x0004, "File Server (SLIST source)" },
978 { 0x0005, "Job Server" },
979 { 0x0006, "Gateway" },
980 { 0x0007, "Print Server or Silent Print Server" },
981 { 0x0008, "Archive Queue" },
982 { 0x0009, "Archive Server" },
983 { 0x000a, "Job Queue" },
984 { 0x000b, "Administration" },
985 { 0x000F, "Novell TI-RPC" },
986 { 0x0017, "Diagnostics" },
987 { 0x0020, "NetBIOS" },
988 { 0x0021, "NAS SNA Gateway" },
989 { 0x0023, "NACS Async Gateway or Asynchronous Gateway" },
990 { 0x0024, "Remote Bridge or Routing Service" },
991 { 0x0026, "Bridge Server or Asynchronous Bridge Server" },
992 { 0x0027, "TCP/IP Gateway Server" },
993 { 0x0028, "Point to Point (Eicon) X.25 Bridge Server" },
994 { 0x0029, "Eicon 3270 Gateway" },
995 { 0x002a, "CHI Corp" },
996 { 0x002c, "PC Chalkboard" },
997 { 0x002d, "Time Synchronization Server or Asynchronous Timer" },
998 { 0x002e, "ARCserve 5.0 / Palindrome Backup Director 4.x (PDB4)" },
999 { 0x0045, "DI3270 Gateway" },
1000 { 0x0047, "Advertising Print Server" },
1001 { 0x004a, "NetBlazer Modems" },
1002 { 0x004b, "Btrieve VAP/NLM 5.0" },
1003 { 0x004c, "NetWare SQL VAP/NLM Server" },
1004 { 0x004d, "Xtree Network Version/NetWare XTree" },
1005 { 0x0050, "Btrieve VAP 4.11" },
1006 { 0x0052, "QuickLink (Cubix)" },
1007 { 0x0053, "Print Queue User" },
1008 { 0x0058, "Multipoint X.25 Eicon Router" },
1009 { 0x0060, "STLB/NLM" },
1010 { 0x0064, "ARCserve" },
1011 { 0x0066, "ARCserve 3.0" },
1012 { 0x0072, "WAN Copy Utility" },
1013 { 0x007a, "TES-NetWare for VMS" },
1014 { 0x0092, "WATCOM Debugger or Emerald Tape Backup Server" },
1015 { 0x0095, "DDA OBGYN" },
1016 { 0x0098, "NetWare Access Server (Asynchronous gateway)" },
1017 { 0x009a, "NetWare for VMS II or Named Pipe Server" },
1018 { 0x009b, "NetWare Access Server" },
1019 { 0x009e, "Portable NetWare Server or SunLink NVT" },
1020 { 0x00a1, "Powerchute APC UPS NLM" },
1021 { 0x00aa, "LAWserve" },
1022 { 0x00ac, "Compaq IDA Status Monitor" },
1023 { 0x0100, "PIPE STAIL" },
1024 { 0x0102, "LAN Protect Bindery" },
1025 { 0x0103, "Oracle DataBase Server" },
1026 { 0x0107, "NetWare 386 or RSPX Remote Console" },
1027 { 0x010f, "Novell SNA Gateway" },
1028 { 0x0111, "Test Server" },
1029 { 0x0112, "Print Server (HP)" },
1030 { 0x0114, "CSA MUX (f/Communications Executive)" },
1031 { 0x0115, "CSA LCA (f/Communications Executive)" },
1032 { 0x0116, "CSA CM (f/Communications Executive)" },
1033 { 0x0117, "CSA SMA (f/Communications Executive)" },
1034 { 0x0118, "CSA DBA (f/Communications Executive)" },
1035 { 0x0119, "CSA NMA (f/Communications Executive)" },
1036 { 0x011a, "CSA SSA (f/Communications Executive)" },
1037 { 0x011b, "CSA STATUS (f/Communications Executive)" },
1038 { 0x011e, "CSA APPC (f/Communications Executive)" },
1039 { 0x0126, "SNA TEST SSA Profile" },
1040 { 0x012a, "CSA TRACE (f/Communications Executive)" },
1041 { 0x012b, "NetWare for SAA" },
1042 { 0x012e, "IKARUS virus scan utility" },
1043 { 0x0130, "Communications Executive" },
1044 { 0x0133, "NNS Domain Server or NetWare Naming Services Domain" },
1045 { 0x0135, "NetWare Naming Services Profile" },
1046 { 0x0137, "NetWare 386 Print Queue or NNS Print Queue" },
1047 { 0x0141, "LAN Spool Server (Vap, Intel)" },
1048 { 0x0152, "IRMALAN Gateway" },
1049 { 0x0154, "Named Pipe Server" },
1050 { 0x0166, "NetWare Management" },
1051 { 0x0168, "Intel PICKIT Comm Server or Intel CAS Talk Server" },
1052 { 0x0173, "Compaq" },
1053 { 0x0174, "Compaq SNMP Agent" },
1054 { 0x0175, "Compaq" },
1055 { 0x0180, "XTree Server or XTree Tools" },
1056 { 0x018A, "NASI services broadcast server (Novell)" },
1057 { 0x01b0, "GARP Gateway (net research)" },
1058 { 0x01b1, "Binfview (Lan Support Group)" },
1059 { 0x01bf, "Intel LanDesk Manager" },
1060 { 0x01ca, "AXTEC" },
1061 { 0x01cb, "Shiva NetModem/E" },
1062 { 0x01cc, "Shiva LanRover/E" },
1063 { 0x01cd, "Shiva LanRover/T" },
1064 { 0x01ce, "Shiva Universal" },
1065 { 0x01d8, "Castelle FAXPress Server" },
1066 { 0x01da, "Castelle LANPress Print Server" },
1067 { 0x01dc, "Castelle FAX/Xerox 7033 Fax Server/Excel Lan Fax" },
1068 { 0x01f0, "LEGATO" },
1069 { 0x01f5, "LEGATO" },
1070 { 0x0233, "NMS Agent or NetWare Management Agent" },
1071 { 0x0237, "NMS IPX Discovery or LANtern Read/Write Channel" },
1072 { 0x0238, "NMS IP Discovery or LANtern Trap/Alarm Channel" },
1073 { 0x023a, "LANtern" },
1074 { 0x023c, "MAVERICK" },
1075 { 0x023f, "SMS Testing and Development" },
1076 { 0x024e, "NetWare Connect" },
1077 { 0x024f, "NASI server broadcast (Cisco)" },
1078 { 0x026a, "Network Management (NMS) Service Console" },
1079 { 0x026b, "Time Synchronization Server (NetWare 4.x)" },
1080 { 0x0278, "Directory Server (NetWare 4.x)" },
1081 { 0x027b, "NetWare Management Agent" },
1082 { 0x0280, "Novell File and Printer Sharing Service for PC" },
1083 { 0x0304, "Novell SAA Gateway" },
1084 { 0x0308, "COM or VERMED 1" },
1085 { 0x030a, "Galacticomm's Worldgroup Server" },
1086 { 0x030c, "Intel Netport 2 or HP JetDirect or HP Quicksilver" },
1087 { 0x0320, "Attachmate Gateway" },
1088 { 0x0327, "Microsoft Diagnostics" },
1089 { 0x0328, "WATCOM SQL server" },
1090 { 0x0335, "MultiTech Systems Multisynch Comm Server" },
1091 { 0x0343, "Xylogics Remote Access Server or LAN Modem" },
1092 { 0x0355, "Arcada Backup Exec" },
1093 { 0x0358, "MSLCD1" },
1094 { 0x0361, "NETINELO" },
1095 { 0x037e, "Powerchute UPS Monitoring" },
1096 { 0x037f, "ViruSafe Notify" },
1097 { 0x0386, "HP Bridge" },
1098 { 0x0387, "HP Hub" },
1099 { 0x0394, "NetWare SAA Gateway" },
1100 { 0x039b, "Lotus Notes" },
1101 { 0x03b7, "Certus Anti Virus NLM" },
1102 { 0x03c4, "ARCserve 4.0 (Cheyenne)" },
1103 { 0x03c7, "LANspool 3.5 (Intel)" },
1104 { 0x03d7, "Lexmark printer server (type 4033-011)" },
1105 { 0x03d8, "Lexmark XLE printer server (type 4033-301)" },
1106 { 0x03dd, "Banyan ENS for NetWare Client NLM" },
1107 { 0x03de, "Gupta Sequel Base Server or NetWare SQL" },
1108 { 0x03e1, "Univel Unixware" },
1109 { 0x03e4, "Univel Unixware" },
1110 { 0x03fc, "Intel Netport" },
1111 { 0x03fd, "Intel Print Server Queue" },
1112 { 0x040A, "ipnServer" },
1113 { 0x040D, "LVERRMAN" },
1114 { 0x040E, "LVLIC" },
1115 { 0x0414, "NET Silicon (DPI)/Kyocera" },
1116 { 0x0429, "Site Lock Virus (Brightworks)" },
1117 { 0x0432, "UFHELP R" },
1118 { 0x0433, "Synoptics 281x Advanced SNMP Agent" },
1119 { 0x0444, "Microsoft NT SNA Server" },
1120 { 0x0448, "Oracle" },
1121 { 0x044c, "ARCserve 5.01" },
1122 { 0x0457, "Canon GP55 Running on a Canon GP55 network printer" },
1123 { 0x045a, "QMS Printers" },
1124 { 0x045b, "Dell SCSI Array (DSA) Monitor" },
1125 { 0x0491, "NetBlazer Modems" },
1126 { 0x04ac, "On-Time Scheduler NLM" },
1127 { 0x04b0, "CD-Net (Meridian)" },
1128 { 0x0513, "Emulex NQA" },
1129 { 0x0520, "Site Lock Checks" },
1130 { 0x0529, "Site Lock Checks (Brightworks)" },
1131 { 0x052d, "Citrix OS/2 App Server" },
1132 { 0x0535, "Tektronix" },
1133 { 0x0536, "Milan" },
1134 { 0x055d, "Attachmate SNA gateway" },
1135 { 0x056b, "IBM 8235 modem server" },
1136 { 0x056c, "Shiva LanRover/E PLUS" },
1137 { 0x056d, "Shiva LanRover/T PLUS" },
1138 { 0x0580, "McAfee's NetShield anti-virus" },
1139 { 0x05B8, "NLM to workstation communication (Revelation Software)" },
1140 { 0x05BA, "Compatible Systems Routers" },
1141 { 0x05BE, "Cheyenne Hierarchical Storage Manager" },
1142 { 0x0606, "JCWatermark Imaging" },
1143 { 0x060c, "AXIS Network Printer" },
1144 { 0x0610, "Adaptec SCSI Management" },
1145 { 0x0621, "IBM AntiVirus NLM" },
1146 { 0x0640, "Microsoft Gateway Services for NetWare" },
1147 /* { 0x0640, "NT Server-RPC/GW for NW/Win95 User Level Sec" }, */
1148 { 0x064e, "Microsoft Internet Information Server" },
1149 { 0x067b, "Microsoft Win95/98 File and Print Sharing for NetWare" },
1150 { 0x067c, "Microsoft Win95/98 File and Print Sharing for NetWare" },
1151 { 0x076C, "Xerox" },
1152 { 0x079b, "Shiva LanRover/E 115" },
1153 { 0x079c, "Shiva LanRover/T 115" },
1154 { 0x07B4, "Cubix WorldDesk" },
1155 { 0x07c2, "Quarterdeck IWare Connect V2.x NLM" },
1156 { 0x07c1, "Quarterdeck IWare Connect V3.x NLM" },
1157 { 0x0810, "ELAN License Server Demo" },
1158 { 0x0824, "Shiva LanRover Access Switch/E" },
1159 { 0x086a, "ISSC collector NLMs" },
1160 { 0x087f, "ISSC DAS agent for AIX" },
1161 { 0x0880, "Intel Netport PRO" },
1162 { 0x0881, "Intel Netport PRO" },
1163 { 0x0b29, "Site Lock" },
1164 { 0x0c29, "Site Lock Applications" },
1165 { 0x0c2c, "Licensing Server" },
1166 { 0x2101, "Performance Technology Instant Internet" },
1167 { 0x2380, "LAI Site Lock" },
1168 { 0x238c, "Meeting Maker" },
1169 { 0x4808, "Site Lock Server or Site Lock Metering VAP/NLM" },
1170 { 0x5555, "Site Lock User" },
1171 { 0x6312, "Tapeware" },
1172 { 0x6f00, "Rabbit Gateway (3270)" },
1173 { 0x7703, "MODEM" },
1174 { 0x8002, "NetPort Printers (Intel) or LANport" },
1175 { 0x8003, "SEH InterCon Printserver" },
1176 { 0x8008, "WordPerfect Network Version" },
1177 { 0x85BE, "Cisco Enhanced Interior Routing Protocol (EIGRP)" },
1178 { 0x8888, "WordPerfect Network Version or Quick Network Management" },
1179 { 0x9000, "McAfee's NetShield anti-virus" },
1180 { 0x9604, "CSA-NT_MON" },
1181 { 0xb6a8, "Ocean Isle Reachout Remote Control" },
1182 { 0xf11f, "Site Lock Metering VAP/NLM" },
1183 { 0xf1ff, "Site Lock" },
1184 { 0xf503, "Microsoft SQL Server" },
1185 { 0xf905, "IBM Time and Place/2 application" },
1186 { 0xfbfb, "TopCall III fax server" },
1187 { 0xffff, "Any Service or Wildcard" },
1192 dissect_ipxsap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1194 proto_tree *sap_tree, *s_tree;
1197 struct sap_query query;
1198 guint16 server_type;
1199 char server_name[48];
1200 guint16 server_port;
1201 guint16 intermediate_network;
1203 static char *sap_type[4] = { "General Query", "General Response",
1204 "Nearest Query", "Nearest Response" };
1206 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1207 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPX SAP");
1208 if (check_col(pinfo->cinfo, COL_INFO))
1209 col_clear(pinfo->cinfo, COL_INFO);
1211 query.query_type = tvb_get_ntohs(tvb, 0);
1212 query.server_type = tvb_get_ntohs(tvb, 2);
1214 if (check_col(pinfo->cinfo, COL_INFO)) {
1215 if (query.query_type >= 1 && query.query_type <= 4) {
1216 col_set_str(pinfo->cinfo, COL_INFO, sap_type[query.query_type - 1]);
1219 col_set_str(pinfo->cinfo, COL_INFO, "Unknown Packet Type");
1224 ti = proto_tree_add_item(tree, proto_sap, tvb, 0, -1, FALSE);
1225 sap_tree = proto_item_add_subtree(ti, ett_ipxsap);
1227 if (query.query_type >= 1 && query.query_type <= 4) {
1228 proto_tree_add_text(sap_tree, tvb, 0, 2, sap_type[query.query_type - 1]);
1229 if ((query.query_type - 1) % 2) {
1230 proto_tree_add_boolean_hidden(sap_tree,
1234 proto_tree_add_boolean_hidden(sap_tree,
1240 proto_tree_add_text(sap_tree, tvb, 0, 2,
1241 "Unknown SAP Packet Type %d", query.query_type);
1244 if (query.query_type == IPX_SAP_GENERAL_RESPONSE ||
1245 query.query_type == IPX_SAP_NEAREST_RESPONSE) { /* responses */
1247 int available_length = tvb_reported_length(tvb);
1248 for (cursor = 2; (cursor + 64) <= available_length; cursor += 64) {
1249 server_type = tvb_get_ntohs(tvb, cursor);
1250 tvb_memcpy(tvb, (guint8 *)server_name,
1253 ti = proto_tree_add_text(sap_tree, tvb, cursor+2, 48,
1254 "Server Name: %.48s", server_name);
1255 s_tree = proto_item_add_subtree(ti, ett_ipxsap_server);
1257 proto_tree_add_text(s_tree, tvb, cursor, 2, "Server Type: %s (0x%04X)",
1258 val_to_str(server_type, server_vals, "Unknown"),
1260 proto_tree_add_text(s_tree, tvb, cursor+50, 4, "Network: %s",
1261 ipxnet_to_string(tvb_get_ptr(tvb, cursor+50, 4)));
1262 proto_tree_add_text(s_tree, tvb, cursor+54, 6, "Node: %s",
1263 ether_to_str(tvb_get_ptr(tvb, cursor+54, 6)));
1264 server_port = tvb_get_ntohs(tvb, cursor+60);
1265 proto_tree_add_text(s_tree, tvb, cursor+60, 2, "Socket: %s (0x%04x)",
1266 socket_text(server_port),
1268 intermediate_network = tvb_get_ntohs(tvb, cursor+62);
1269 proto_tree_add_text(s_tree, tvb, cursor+62, 2,
1270 "Intermediate Networks: %d",
1271 intermediate_network);
1274 else { /* queries */
1275 proto_tree_add_text(sap_tree, tvb, 2, 2, "Server Type: %s (0x%04X)",
1276 val_to_str(query.server_type, server_vals, "Unknown"),
1283 proto_register_ipx(void)
1285 static hf_register_info hf_ipx[] = {
1287 { "Checksum", "ipx.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1291 { "Source Address", "ipx.src", FT_STRING, BASE_DEC, NULL, 0x0,
1292 "Source IPX Address \"network.node\"", HFILL }},
1295 { "Destination Address", "ipx.dst", FT_STRING, BASE_DEC, NULL, 0x0,
1296 "Destination IPX Address \"network.node\"", HFILL }},
1298 { "Src/Dst Address", "ipx.addr", FT_STRING, BASE_DEC, NULL, 0x0,
1299 "Source or Destination IPX Address \"network.node\"", HFILL }},
1302 { "Length", "ipx.len", FT_UINT16, BASE_DEC, NULL, 0x0,
1306 { "Transport Control (Hops)", "ipx.hops", FT_UINT8, BASE_DEC, NULL, 0x0,
1309 { &hf_ipx_packet_type,
1310 { "Packet Type", "ipx.packet_type", FT_UINT8, BASE_HEX, VALS(ipx_packet_type_vals),
1315 { "Destination Network","ipx.dst.net", FT_IPXNET, BASE_NONE, NULL, 0x0,
1319 { "Destination Node", "ipx.dst.node", FT_ETHER, BASE_NONE, NULL, 0x0,
1323 { "Destination Socket", "ipx.dst.socket", FT_UINT16, BASE_HEX,
1324 VALS(ipx_socket_vals), 0x0,
1328 { "Source Network","ipx.src.net", FT_IPXNET, BASE_NONE, NULL, 0x0,
1332 { "Source Node", "ipx.src.node", FT_ETHER, BASE_NONE, NULL, 0x0,
1336 { "Source Socket", "ipx.src.socket", FT_UINT16, BASE_HEX,
1337 VALS(ipx_socket_vals), 0x0,
1341 { "Source or Destination Network","ipx.net", FT_IPXNET, BASE_NONE, NULL, 0x0,
1345 { "Source or Destination Node", "ipx.node", FT_ETHER, BASE_NONE, NULL, 0x0,
1349 { "Source or Destination Socket", "ipx.socket", FT_UINT16, BASE_HEX,
1350 VALS(ipx_socket_vals), 0x0,
1354 static hf_register_info hf_spx[] = {
1355 { &hf_spx_connection_control,
1356 { "Connection Control", "spx.ctl",
1357 FT_UINT8, BASE_HEX, NULL, 0x0,
1360 { &hf_spx_connection_control_sys,
1361 { "System Packet", "spx.ctl.sys",
1362 FT_BOOLEAN, 8, NULL, SPX_SYS_PACKET,
1365 { &hf_spx_connection_control_send_ack,
1366 { "Send Ack", "spx.ctl.send_ack",
1367 FT_BOOLEAN, 8, NULL, SPX_SEND_ACK,
1370 { &hf_spx_connection_control_attn,
1371 { "Attention", "spx.ctl.attn",
1372 FT_BOOLEAN, 8, NULL, SPX_ATTN,
1375 { &hf_spx_connection_control_eom,
1376 { "End of Message", "spx.ctl.eom",
1377 FT_BOOLEAN, 8, NULL, SPX_EOM,
1380 { &hf_spx_datastream_type,
1381 { "Datastream type", "spx.type",
1382 FT_UINT8, BASE_HEX, NULL, 0x0,
1386 { "Source Connection ID", "spx.src",
1387 FT_UINT16, BASE_DEC, NULL, 0x0,
1391 { "Destination Connection ID", "spx.dst",
1392 FT_UINT16, BASE_DEC, NULL, 0x0,
1396 { "Sequence Number", "spx.seq",
1397 FT_UINT16, BASE_DEC, NULL, 0x0,
1401 { "Acknowledgment Number", "spx.ack",
1402 FT_UINT16, BASE_DEC, NULL, 0x0,
1406 { "Allocation Number", "spx.alloc",
1407 FT_UINT16, BASE_DEC, NULL, 0x0,
1410 { &hf_spx_rexmt_frame,
1411 { "Retransmitted Frame Number", "spx.rexmt_frame",
1412 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1416 static hf_register_info hf_ipxrip[] = {
1417 { &hf_ipxrip_request,
1418 { "Request", "ipxrip.request",
1419 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1420 "TRUE if IPX RIP request", HFILL }},
1422 { &hf_ipxrip_response,
1423 { "Response", "ipxrip.response",
1424 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1425 "TRUE if IPX RIP response", HFILL }}
1428 static hf_register_info hf_sap[] = {
1430 { "Request", "ipxsap.request",
1431 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1432 "TRUE if SAP request", HFILL }},
1435 { "Response", "ipxsap.response",
1436 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1437 "TRUE if SAP response", HFILL }}
1440 static hf_register_info hf_ipxmsg[] = {
1442 { "Connection Number", "ipxmsg.conn",
1443 FT_UINT8, BASE_DEC, NULL, 0x0,
1444 "Connection Number", HFILL }},
1447 { "Signature Char", "ipxmsg.sigchar",
1448 FT_UINT8, BASE_DEC, VALS(ipxmsg_sigchar_vals), 0x0,
1449 "Signature Char", HFILL }}
1452 static gint *ett[] = {
1462 proto_ipx = proto_register_protocol("Internetwork Packet eXchange",
1464 proto_register_field_array(proto_ipx, hf_ipx, array_length(hf_ipx));
1466 register_dissector("ipx", dissect_ipx, proto_ipx);
1468 proto_spx = proto_register_protocol("Sequenced Packet eXchange",
1470 proto_register_field_array(proto_spx, hf_spx, array_length(hf_spx));
1472 proto_ipxrip = proto_register_protocol("IPX Routing Information Protocol",
1473 "IPX RIP", "ipxrip");
1474 proto_register_field_array(proto_ipxrip, hf_ipxrip, array_length(hf_ipxrip));
1476 proto_ipxmsg = proto_register_protocol("IPX Message", "IPX MSG",
1478 proto_register_field_array(proto_ipxmsg, hf_ipxmsg, array_length(hf_ipxmsg));
1480 proto_sap = proto_register_protocol("Service Advertisement Protocol",
1481 "IPX SAP", "ipxsap");
1482 register_dissector("ipxsap", dissect_ipxsap, proto_sap);
1484 proto_register_field_array(proto_sap, hf_sap, array_length(hf_sap));
1486 proto_register_subtree_array(ett, array_length(ett));
1488 ipx_type_dissector_table = register_dissector_table("ipx.packet_type",
1489 "IPX packet type", FT_UINT8, BASE_HEX);
1490 ipx_socket_dissector_table = register_dissector_table("ipx.socket",
1491 "IPX socket", FT_UINT16, BASE_HEX);
1492 spx_socket_dissector_table = register_dissector_table("spx.socket",
1493 "SPX socket", FT_UINT16, BASE_HEX);
1495 register_init_routine(&spx_init_protocol);
1496 register_postseq_cleanup_routine(&spx_postseq_cleanup);
1497 ipx_tap=register_tap("ipx");
1501 proto_reg_handoff_ipx(void)
1503 dissector_handle_t ipx_handle, spx_handle;
1504 dissector_handle_t ipxsap_handle, ipxrip_handle;
1505 dissector_handle_t ipxmsg_handle;
1507 ipx_handle = find_dissector("ipx");
1508 dissector_add("udp.port", UDP_PORT_IPX, ipx_handle);
1509 dissector_add("ethertype", ETHERTYPE_IPX, ipx_handle);
1510 dissector_add("chdlctype", ETHERTYPE_IPX, ipx_handle);
1511 dissector_add("ppp.protocol", PPP_IPX, ipx_handle);
1512 dissector_add("llc.dsap", SAP_NETWARE1, ipx_handle);
1513 dissector_add("llc.dsap", SAP_NETWARE2, ipx_handle);
1514 dissector_add("null.type", BSD_AF_IPX, ipx_handle);
1515 dissector_add("gre.proto", ETHERTYPE_IPX, ipx_handle);
1516 dissector_add("arcnet.protocol_id", ARCNET_PROTO_IPX, ipx_handle);
1517 dissector_add("arcnet.protocol_id", ARCNET_PROTO_NOVELL_EC, ipx_handle);
1519 spx_handle = create_dissector_handle(dissect_spx, proto_spx);
1520 dissector_add("ipx.packet_type", IPX_PACKET_TYPE_SPX, spx_handle);
1522 ipxsap_handle = find_dissector("ipxsap");
1523 dissector_add("ipx.socket", IPX_SOCKET_SAP, ipxsap_handle);
1525 ipxrip_handle = create_dissector_handle(dissect_ipxrip, proto_ipxrip);
1526 dissector_add("ipx.socket", IPX_SOCKET_IPXRIP, ipxrip_handle);
1528 ipxmsg_handle = create_dissector_handle(dissect_ipxmsg, proto_ipxmsg);
1529 dissector_add("ipx.socket", IPX_SOCKET_IPX_MESSAGE, ipxmsg_handle);
1530 dissector_add("ipx.socket", IPX_SOCKET_IPX_MESSAGE1, ipxmsg_handle);
1532 data_handle = find_dissector("data");