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
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_serialization = -1;
112 static gint ett_serialization = -1;
114 static int proto_sap = -1;
115 static int hf_sap_request = -1;
116 static int hf_sap_response = -1;
118 static gint ett_ipxsap = -1;
119 static gint ett_ipxsap_server = -1;
121 static gint ett_ipxmsg = -1;
122 static int proto_ipxmsg = -1;
123 static int hf_msg_conn = -1;
124 static int hf_msg_sigchar = -1;
126 static dissector_handle_t data_handle;
129 dissect_spx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
132 dissect_ipxrip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
135 dissect_serialization(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
138 dissect_ipxsap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
141 dissect_ipxmsg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
143 #define UDP_PORT_IPX 213 /* RFC 1234 */
145 #define IPX_HEADER_LEN 30 /* It's *always* 30 bytes */
147 /* ================================================================= */
149 /* ================================================================= */
150 const value_string ipx_socket_vals[] = {
151 { IPX_SOCKET_PING_CISCO, "CISCO PING" },
152 { IPX_SOCKET_NCP, "NCP" },
153 { IPX_SOCKET_SAP, "SAP" },
154 { IPX_SOCKET_IPXRIP, "RIP" },
155 { IPX_SOCKET_NETBIOS, "NetBIOS" },
156 { IPX_SOCKET_DIAGNOSTIC, "Diagnostic" },
157 { IPX_SOCKET_SERIALIZATION, "Serialization" },
158 { IPX_SOCKET_NWLINK_SMB_SERVER, "NWLink SMB Server" },
159 { IPX_SOCKET_NWLINK_SMB_NAMEQUERY, "NWLink SMB Name Query" },
160 { IPX_SOCKET_NWLINK_SMB_REDIR, "NWLink SMB Redirector" },
161 { IPX_SOCKET_NWLINK_SMB_MAILSLOT, "NWLink SMB Mailslot Datagram" },
162 { IPX_SOCKET_NWLINK_SMB_MESSENGER, "NWLink SMB Messenger" },
163 { IPX_SOCKET_NWLINK_SMB_BROWSE, "NWLink SMB Browse" },
164 { IPX_SOCKET_ATTACHMATE_GW, "Attachmate Gateway" },
165 { IPX_SOCKET_IPX_MESSAGE, "IPX Message" },
166 { IPX_SOCKET_IPX_MESSAGE1, "IPX Message" },
167 { IPX_SOCKET_SNMP_AGENT, "SNMP Agent" },
168 { IPX_SOCKET_SNMP_SINK, "SNMP Sink" },
169 { IPX_SOCKET_PING_NOVELL, "Novell PING" },
170 { IPX_SOCKET_UDP_TUNNEL, "UDP Tunnel" },
171 { IPX_SOCKET_TCP_TUNNEL, "TCP Tunnel" },
172 { IPX_SOCKET_TCP_TUNNEL, "TCP Tunnel" },
173 { IPX_SOCKET_ADSM, "ADSM" },
174 { IPX_SOCKET_EIGRP, "Cisco EIGRP for IPX" },
175 { IPX_SOCKET_NLSP, "NetWare Link Services Protocol" },
176 { IPX_SOCKET_IPXWAN, "IPX WAN" },
177 { SPX_SOCKET_PA, "NDPS Printer Agent/PSM" },
178 { SPX_SOCKET_BROKER, "NDPS Broker" },
179 { SPX_SOCKET_SRS, "NDPS Service Registry Service" },
180 { SPX_SOCKET_ENS, "NDPS Event Notification Service" },
181 { SPX_SOCKET_RMS, "NDPS Remote Management Service" },
182 { SPX_SOCKET_NOTIFY_LISTENER, "NDPS Notify Listener" },
183 { 0xE885, "NT Server-RPC/GW" },
184 { 0x400C, "HP LaserJet/QuickSilver" },
185 { 0x907B, "SMS Testing and Development" },
186 { 0x8F83, "Powerchute UPS Monitoring" },
187 { 0x4006, "NetWare Directory Server" },
188 { 0x8104, "NetWare 386" },
193 socket_text(guint16 socket)
195 return val_to_str(socket, ipx_socket_vals, "Unknown");
198 static const value_string ipx_packet_type_vals[] = {
199 { IPX_PACKET_TYPE_IPX, "IPX" },
200 { IPX_PACKET_TYPE_RIP, "RIP" },
201 { IPX_PACKET_TYPE_ECHO, "Echo" },
202 { IPX_PACKET_TYPE_ERROR, "Error" },
203 { IPX_PACKET_TYPE_PEP, "PEP" }, /* Packet Exchange Packet */
204 { IPX_PACKET_TYPE_SPX, "SPX" },
205 { 16, "Experimental Protocol" },
206 { IPX_PACKET_TYPE_NCP, "NCP" },
207 { 18, "Experimental Protocol" },
208 { 19, "Experimental Protocol" },
209 { IPX_PACKET_TYPE_WANBCAST, "NetBIOS Broadcast" },
210 { 21, "Experimental Protocol" },
211 { 22, "Experimental Protocol" },
212 { 23, "Experimental Protocol" },
213 { 24, "Experimental Protocol" },
214 { 25, "Experimental Protocol" },
215 { 26, "Experimental Protocol" },
216 { 27, "Experimental Protocol" },
217 { 28, "Experimental Protocol" },
218 { 29, "Experimental Protocol" },
219 { 30, "Experimental Protocol" },
220 { 31, "Experimental Protocol" },
224 static const value_string ipxmsg_sigchar_vals[] = {
225 { '?', "Poll inactive station" },
226 { 'Y', "Station is still using the connection" },
227 { '!', "Broadcast message waiting" },
232 capture_ipx(packet_counts *ld)
238 dissect_ipx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
242 proto_tree *ipx_tree = NULL;
243 proto_item *ti = NULL;
245 const guint8 *src_net_node, *dst_net_node;
249 guint16 first_socket, second_socket;
250 guint32 ipx_snet, ipx_dnet;
251 const guint8 *ipx_snode, *ipx_dnode;
252 static ipxhdr_t ipxh_arr[4];
253 static int ipx_current=0;
260 ipxh=&ipxh_arr[ipx_current];
263 if (check_col(pinfo->cinfo, COL_PROTOCOL))
264 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPX");
265 if (check_col(pinfo->cinfo, COL_INFO))
266 col_clear(pinfo->cinfo, COL_INFO);
268 /* Calculate here for use in pinfo and in tree */
269 ipxh->ipx_dsocket = tvb_get_ntohs(tvb, 16);
270 ipxh->ipx_ssocket = tvb_get_ntohs(tvb, 28);
271 ipxh->ipx_type = tvb_get_guint8(tvb, 5);
272 ipxh->ipx_length = tvb_get_ntohs(tvb, 2);
274 pinfo->ptype = PT_IPX;
275 pinfo->srcport = ipxh->ipx_ssocket;
276 pinfo->destport = ipxh->ipx_dsocket;
278 /* Adjust the tvbuff length to include only the IPX datagram. */
279 set_actual_length(tvb, ipxh->ipx_length);
281 src_net_node = tvb_get_ptr(tvb, 18, 10);
282 dst_net_node = tvb_get_ptr(tvb, 6, 10);
284 SET_ADDRESS(&pinfo->net_src, AT_IPX, 10, src_net_node);
285 SET_ADDRESS(&pinfo->src, AT_IPX, 10, src_net_node);
286 SET_ADDRESS(&ipxh->ipx_src, AT_IPX, 10, src_net_node);
287 SET_ADDRESS(&pinfo->net_dst, AT_IPX, 10, dst_net_node);
288 SET_ADDRESS(&pinfo->dst, AT_IPX, 10, dst_net_node);
289 SET_ADDRESS(&ipxh->ipx_dst, AT_IPX, 10, dst_net_node);
291 if (check_col(pinfo->cinfo, COL_INFO))
292 col_add_fstr(pinfo->cinfo, COL_INFO, "%s (0x%04x)",
293 socket_text(ipxh->ipx_dsocket), ipxh->ipx_dsocket);
297 ti = proto_tree_add_item(tree, proto_ipx, tvb, 0, IPX_HEADER_LEN, FALSE);
298 ipx_tree = proto_item_add_subtree(ti, ett_ipx);
301 str=address_to_str(&pinfo->net_src);
302 proto_tree_add_string_hidden(ipx_tree, hf_ipx_src, tvb, 0, 0, str);
303 proto_tree_add_string_hidden(ipx_tree, hf_ipx_addr, tvb, 0, 0, str);
304 str=address_to_str(&pinfo->net_dst);
305 proto_tree_add_string_hidden(ipx_tree, hf_ipx_dst, tvb, 0, 0, str);
306 proto_tree_add_string_hidden(ipx_tree, hf_ipx_addr, tvb, 0, 0, str);
308 proto_tree_add_item(ipx_tree, hf_ipx_checksum, tvb, 0, 2, FALSE);
309 proto_tree_add_uint_format(ipx_tree, hf_ipx_len, tvb, 2, 2, ipxh->ipx_length,
310 "Length: %d bytes", ipxh->ipx_length);
311 ipx_hops = tvb_get_guint8(tvb, 4);
312 proto_tree_add_uint_format(ipx_tree, hf_ipx_hops, tvb, 4, 1, ipx_hops,
313 "Transport Control: %d hops", ipx_hops);
314 proto_tree_add_uint(ipx_tree, hf_ipx_packet_type, tvb, 5, 1, ipxh->ipx_type);
317 ipx_dnet = tvb_get_ntohl(tvb, 6);
318 proto_tree_add_ipxnet(ipx_tree, hf_ipx_dnet, tvb, 6, 4,
320 proto_tree_add_ipxnet_hidden(ipx_tree, hf_ipx_net, tvb, 6, 4,
322 ipx_dnode = tvb_get_ptr(tvb, 10, 6);
323 proto_tree_add_ether(ipx_tree, hf_ipx_dnode, tvb, 10, 6,
325 proto_tree_add_ether_hidden(ipx_tree, hf_ipx_node, tvb, 10, 6,
327 proto_tree_add_uint(ipx_tree, hf_ipx_dsocket, tvb, 16, 2,
329 proto_tree_add_uint_hidden(ipx_tree, hf_ipx_socket, tvb, 16, 2,
333 ipx_snet = tvb_get_ntohl(tvb, 18);
334 proto_tree_add_ipxnet(ipx_tree, hf_ipx_snet, tvb, 18, 4,
336 proto_tree_add_ipxnet_hidden(ipx_tree, hf_ipx_net, tvb, 18, 4,
338 ipx_snode = tvb_get_ptr(tvb, 22, 6);
339 proto_tree_add_ether(ipx_tree, hf_ipx_snode, tvb, 22, 6,
341 proto_tree_add_ether_hidden(ipx_tree, hf_ipx_node, tvb, 22, 6,
343 proto_tree_add_uint(ipx_tree, hf_ipx_ssocket, tvb, 28, 2,
345 proto_tree_add_uint_hidden(ipx_tree, hf_ipx_socket, tvb, 28, 2,
348 /* Make the next tvbuff */
349 next_tvb = tvb_new_subset(tvb, IPX_HEADER_LEN, -1, -1);
352 * Let the subdissector know what type of IPX packet this is.
354 pinfo->ipxptype = ipxh->ipx_type;
357 * Check the socket numbers before we check the packet type;
358 * we've seen non-NCP packets with a type of NCP and a
359 * destination socket of IPX_SOCKET_IPX_MESSAGE, and SAP
360 * packets with a type of NCP and a destination socket of
363 * We've seen NCP packets with a type of NCP, a source socket of
364 * IPX_SOCKET_NCP, and a destination socket of IPX_SOCKET_IPX_MESSAGE,
365 * and we've seen NCP packets with a type of NCP, a source socket of
366 * IPX_SOCKET_IPX_MESSAGE, and a destination socket of
367 * IPX_SOCKET_NCP, so testing the destination socket first doesn't
368 * always give the right answer. We've also seen SAP packets with
369 * a source socket of IPX_SOCKET_SAP and a destination socket of
370 * IPX_SOCKET_IPX_MESSAGE.
372 * Unfortunately, we've also seen packets with a source socket
373 * of IPX_SOCKET_NWLINK_SMB_SERVER and a destination socket
374 * of IPX_SOCKET_NWLINK_SMB_NAMEQUERY that were NMPI packets,
375 * not SMB packets, so testing the lower-valued socket first
376 * also doesn't always give the right answer.
378 * So we start out assuming we should test the lower-numbered
379 * socket number first, but, if the higher-numbered socket is
380 * IPX_SOCKET_NWLINK_SMB_NAMEQUERY, we assume that it's a
381 * NMPI query, and test only that socket.
383 if (ipxh->ipx_ssocket > ipxh->ipx_dsocket) {
384 first_socket = ipxh->ipx_dsocket;
385 second_socket = ipxh->ipx_ssocket;
387 first_socket = ipxh->ipx_ssocket;
388 second_socket = ipxh->ipx_dsocket;
391 tap_queue_packet(ipx_tap, pinfo, ipxh);
393 if (second_socket != IPX_SOCKET_NWLINK_SMB_NAMEQUERY) {
394 if (dissector_try_port(ipx_socket_dissector_table, first_socket,
395 next_tvb, pinfo, tree))
398 if (dissector_try_port(ipx_socket_dissector_table, second_socket,
399 next_tvb, pinfo, tree))
403 * Neither of them are known; try the packet type, which will
404 * at least let us, for example, dissect SPX packets as SPX.
406 if (dissector_try_port(ipx_type_dissector_table, ipxh->ipx_type, next_tvb,
410 call_dissector(data_handle,next_tvb, pinfo, tree);
412 /* ================================================================= */
413 /* SPX Hash Functions */
414 /* ================================================================= */
417 conversation_t *conversation;
429 * Structure attached to retransmitted SPX frames; it contains the
430 * frame number of the original transmission.
436 static GHashTable *spx_hash = NULL;
437 static GMemChunk *spx_hash_keys = NULL;
438 static GMemChunk *spx_hash_values = NULL;
439 static GMemChunk *spx_rexmit_infos = NULL;
443 spx_equal(gconstpointer v, gconstpointer v2)
445 const spx_hash_key *val1 = (const spx_hash_key*)v;
446 const spx_hash_key *val2 = (const spx_hash_key*)v2;
448 if (val1->conversation == val2->conversation &&
449 val1->spx_src == val2->spx_src &&
450 val1->spx_seq == val2->spx_seq) {
457 spx_hash_func(gconstpointer v)
459 const spx_hash_key *spx_key = (const spx_hash_key*)v;
460 return GPOINTER_TO_UINT(spx_key->conversation) + spx_key->spx_src;
463 /* Initializes the hash table and the mem_chunk area each time a new
464 * file is loaded or re-loaded in ethereal */
466 spx_init_protocol(void)
470 g_hash_table_destroy(spx_hash);
472 g_mem_chunk_destroy(spx_hash_keys);
474 g_mem_chunk_destroy(spx_hash_values);
475 if (spx_rexmit_infos)
476 g_mem_chunk_destroy(spx_rexmit_infos);
478 spx_hash = g_hash_table_new(spx_hash_func, spx_equal);
479 spx_hash_keys = g_mem_chunk_new("spx_hash_keys",
480 sizeof(spx_hash_key),
481 SPX_PACKET_INIT_COUNT * sizeof(spx_hash_key),
483 spx_hash_values = g_mem_chunk_new("spx_hash_values",
484 sizeof(spx_hash_value),
485 SPX_PACKET_INIT_COUNT * sizeof(spx_hash_value),
487 spx_rexmit_infos = g_mem_chunk_new("spx_rexmit_infos",
488 sizeof(spx_rexmit_infos),
489 SPX_PACKET_INIT_COUNT * sizeof(spx_rexmit_infos),
493 /* After the sequential run, we don't need the spx hash table, or
494 * the keys and values, anymore; the lookups have already been done
495 * and the relevant info saved as SPX private data with the frame
496 * if the frame was a retransmission. */
498 spx_postseq_cleanup(void)
501 /* Destroy the hash, but don't clean up request_condition data. */
502 g_hash_table_destroy(spx_hash);
506 g_mem_chunk_destroy(spx_hash_keys);
507 spx_hash_keys = NULL;
509 if (spx_hash_values) {
510 g_mem_chunk_destroy(spx_hash_values);
511 spx_hash_values = NULL;
513 /* Don't free the spx_rexmit_infos, as they're
514 * needed during random-access processing of the proto_tree.*/
518 spx_hash_insert(conversation_t *conversation, guint32 spx_src, guint16 spx_seq)
521 spx_hash_value *value;
523 /* Now remember the packet, so we can find it if we later. */
524 key = g_mem_chunk_alloc(spx_hash_keys);
525 key->conversation = conversation;
526 key->spx_src = spx_src;
527 key->spx_seq = spx_seq;
529 value = g_mem_chunk_alloc(spx_hash_values);
534 g_hash_table_insert(spx_hash, key, value);
539 /* Returns the spx_hash_value*, or NULL if not found. */
541 spx_hash_lookup(conversation_t *conversation, guint32 spx_src, guint32 spx_seq)
545 key.conversation = conversation;
546 key.spx_src = spx_src;
547 key.spx_seq = spx_seq;
549 return g_hash_table_lookup(spx_hash, &key);
552 /* ================================================================= */
554 /* ================================================================= */
556 #define SPX_SYS_PACKET 0x80
557 #define SPX_SEND_ACK 0x40
558 #define SPX_ATTN 0x20
562 spx_conn_ctrl(guint8 ctrl)
566 static const value_string conn_vals[] = {
567 { 0x00, "Data, No Ack Required" },
568 { SPX_EOM, "End-of-Message" },
569 { SPX_ATTN, "Attention" },
570 { SPX_SEND_ACK, "Acknowledgment Required"},
571 { SPX_SEND_ACK|SPX_EOM, "Send Ack: End Message"},
572 { SPX_SYS_PACKET, "System Packet"},
573 { SPX_SYS_PACKET|SPX_SEND_ACK, "System Packet: Send Ack"},
577 p = match_strval((ctrl & 0xf0), conn_vals );
588 spx_datastream(guint8 type)
592 return "End-of-Connection";
594 return "End-of-Connection Acknowledgment";
600 #define SPX_HEADER_LEN 12
603 dissect_spx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
605 proto_tree *spx_tree = NULL;
610 guint8 datastream_type;
611 const char *datastream_type_string;
613 const char *spx_msg_string;
614 guint16 low_socket, high_socket;
616 conversation_t *conversation;
617 spx_hash_value *pkt_value;
618 spx_rexmit_info *spx_rexmit_info;
621 if (check_col(pinfo->cinfo, COL_PROTOCOL))
622 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SPX");
623 if (check_col(pinfo->cinfo, COL_INFO))
624 col_set_str(pinfo->cinfo, COL_INFO, "SPX");
627 ti = proto_tree_add_item(tree, proto_spx, tvb, 0, SPX_HEADER_LEN, FALSE);
628 spx_tree = proto_item_add_subtree(ti, ett_spx);
631 conn_ctrl = tvb_get_guint8(tvb, 0);
632 spx_msg_string = spx_conn_ctrl(conn_ctrl);
633 if (check_col(pinfo->cinfo, COL_INFO))
634 col_append_fstr(pinfo->cinfo, COL_INFO, " %s", spx_msg_string);
636 ti = proto_tree_add_uint_format(spx_tree, hf_spx_connection_control, tvb,
638 "Connection Control: %s (0x%02X)",
639 spx_msg_string, conn_ctrl);
640 cc_tree = proto_item_add_subtree(ti, ett_spx_connctrl);
641 proto_tree_add_boolean(cc_tree, hf_spx_connection_control_sys, tvb,
643 proto_tree_add_boolean(cc_tree, hf_spx_connection_control_send_ack, tvb,
645 proto_tree_add_boolean(cc_tree, hf_spx_connection_control_attn, tvb,
647 proto_tree_add_boolean(cc_tree, hf_spx_connection_control_eom, tvb,
651 datastream_type = tvb_get_guint8(tvb, 1);
652 datastream_type_string = spx_datastream(datastream_type);
653 if (datastream_type_string != NULL) {
654 if (check_col(pinfo->cinfo, COL_INFO))
655 col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
656 datastream_type_string);
659 if (datastream_type_string != NULL) {
660 proto_tree_add_uint_format(spx_tree, hf_spx_datastream_type, tvb,
661 1, 1, datastream_type,
662 "Datastream Type: %s (0x%02X)",
663 datastream_type_string,
666 proto_tree_add_uint_format(spx_tree, hf_spx_datastream_type, tvb,
667 1, 1, datastream_type,
668 "Datastream Type: 0x%02X",
671 proto_tree_add_item(spx_tree, hf_spx_src_id, tvb, 2, 2, FALSE);
672 proto_tree_add_item(spx_tree, hf_spx_dst_id, tvb, 4, 2, FALSE);
674 spx_seq = tvb_get_ntohs(tvb, 6);
676 proto_tree_add_uint(spx_tree, hf_spx_seq_nr, tvb, 6, 2, spx_seq);
677 proto_tree_add_item(spx_tree, hf_spx_ack_nr, tvb, 8, 2, FALSE);
678 proto_tree_add_item(spx_tree, hf_spx_all_nr, tvb, 10, 2, FALSE);
682 * SPX is Connection Oriented and Delivery Guaranteed.
683 * On the first pass, we need to flag retransmissions by the SPX
684 * protocol, so that subdissectors know whether a packet was
687 * We start out by creating a conversation for this direction of the
688 * IPX session; we use "pinfo->srcport" twice, so that we have
689 * separate conversations for the two directions.
691 * XXX - that might not work correctly if there's more than one
692 * SPX session using that source port; can that happen? If so,
693 * we should probably use the direction, as well as the conversation,
694 * as part of the hash key; if we do that, we can probably just
695 * use PT_IPX as the port type, and possibly get rid of PT_NCP.
699 * http://developer.novell.com/research/appnotes/1995/december/03/apv.htm
701 * the sequence number is not incremented for system packets, so
702 * presumably that means there is no notion of a system packet
703 * being retransmitted; that document also says that system
704 * packets are used as "I'm still here" keepalives and as
705 * acknowledgements (presumably meaning ACK-only packets), which
706 * suggests that they might not be ACKed and thus might not
709 if (conn_ctrl & SPX_SYS_PACKET) {
711 * It's a system packet, so it isn't a retransmission.
713 spx_rexmit_info = NULL;
716 * Not a system packet - check for retransmissions.
718 if (!pinfo->fd->flags.visited) {
719 conversation = find_conversation(&pinfo->src,
720 &pinfo->dst, PT_NCP, pinfo->srcport,
722 if (conversation == NULL) {
724 * It's not part of any conversation - create
727 conversation = conversation_new(&pinfo->src,
728 &pinfo->dst, PT_NCP, pinfo->srcport,
733 * Now we'll hash the SPX header and use the result
734 * of that, plus the conversation, as a hash key to
735 * identify this packet.
737 * If we don't find it in the hash table, it's not a
738 * retransmission, otherwise it is. If we don't find
739 * it, we enter it into the hash table, with the
741 * If we do, we attach to this frame a structure giving
742 * the frame number of the original transmission, so
743 * that we, and subdissectors, know it's a
746 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);
747 pkt_value = spx_hash_lookup(conversation, src, spx_seq);
748 if (pkt_value == NULL) {
750 * Not found in the hash table.
751 * Enter it into the hash table.
753 pkt_value = spx_hash_insert(conversation, src,
755 pkt_value->spx_ack = tvb_get_ntohs(tvb, 8);
756 pkt_value->spx_all = tvb_get_ntohs(tvb, 10);
757 pkt_value->num = pinfo->fd->num;
760 * This is not a retransmission, so we shouldn't
761 * have any retransmission indicator.
763 spx_rexmit_info = NULL;
766 * Found in the hash table. Mark this frame as
769 spx_rexmit_info = g_mem_chunk_alloc(spx_rexmit_infos);
770 spx_rexmit_info->num = pkt_value->num;
771 p_add_proto_data(pinfo->fd, proto_spx,
776 * Do we have per-packet SPX data for this frame?
777 * If so, it's a retransmission, and the per-packet
778 * data indicates which frame had the original
781 spx_rexmit_info = p_get_proto_data(pinfo->fd,
787 * It's a retransmission if we have a retransmission indicator.
788 * Flag this as a retransmission, but don't pass it to the
791 if (spx_rexmit_info != NULL) {
792 if (check_col(pinfo->cinfo, COL_INFO)) {
793 col_add_fstr(pinfo->cinfo, COL_INFO,
794 "[Retransmission] Original Packet %u",
795 spx_rexmit_info->num);
798 proto_tree_add_uint_format(spx_tree, hf_spx_rexmt_frame,
799 tvb, 0, 0, spx_rexmit_info->num,
800 "This is a retransmission of frame %u",
801 spx_rexmit_info->num);
802 if (tvb_length_remaining(tvb, SPX_HEADER_LEN) > 0) {
803 proto_tree_add_text(spx_tree, tvb,
805 "Retransmitted data");
811 if (tvb_reported_length_remaining(tvb, SPX_HEADER_LEN) > 0) {
813 * Call subdissectors based on the IPX socket numbers; a
814 * subdissector might have registered with our IPX socket
815 * dissector table rather than the IPX dissector's socket
818 * Assume the lower-numbered socket number is more likely
819 * to be the right one, along the lines of what we do for
820 * TCP and UDP. We've seen NCP packets with a type of NCP,
821 * a source socket of IPX_SOCKET_NCP, and a destination
822 * socket of IPX_SOCKET_IPX_MESSAGE, and we've seen NCP
823 * packets with a type of NCP, a source socket of
824 * IPX_SOCKET_IPX_MESSAGE, and a destination socket of
827 if (pinfo->srcport > pinfo->destport) {
828 low_socket = pinfo->destport;
829 high_socket = pinfo->srcport;
831 low_socket = pinfo->srcport;
832 high_socket = pinfo->destport;
836 * Pass information to subdissectors.
838 spx_info.eom = conn_ctrl & SPX_EOM;
839 spx_info.datastream_type = datastream_type;
840 pinfo->private_data = &spx_info;
842 next_tvb = tvb_new_subset(tvb, SPX_HEADER_LEN, -1, -1);
843 if (dissector_try_port(spx_socket_dissector_table, low_socket,
844 next_tvb, pinfo, tree))
846 if (dissector_try_port(spx_socket_dissector_table, high_socket,
847 next_tvb, pinfo, tree))
849 call_dissector(data_handle, next_tvb, pinfo, tree);
853 /* ================================================================= */
855 /* ================================================================= */
857 dissect_ipxmsg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
859 proto_tree *msg_tree;
861 guint8 conn_number, sig_char;
863 if (check_col(pinfo->cinfo, COL_PROTOCOL))
864 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPX MSG");
865 if (check_col(pinfo->cinfo, COL_INFO))
866 col_clear(pinfo->cinfo, COL_INFO);
868 conn_number = tvb_get_guint8(tvb, 0);
869 sig_char = tvb_get_guint8(tvb, 1);
871 if (check_col(pinfo->cinfo, COL_INFO)) {
872 col_add_fstr(pinfo->cinfo, COL_INFO,
874 val_to_str(sig_char, ipxmsg_sigchar_vals, "Unknown Signature Char"), conn_number);
878 ti = proto_tree_add_item(tree, proto_ipxmsg, tvb, 0, -1, FALSE);
879 msg_tree = proto_item_add_subtree(ti, ett_ipxmsg);
881 proto_tree_add_uint(msg_tree, hf_msg_conn, tvb, 0, 1, conn_number);
882 proto_tree_add_uint(msg_tree, hf_msg_sigchar, tvb, 1, 1, sig_char);
887 /* ================================================================= */
889 /* ================================================================= */
891 dissect_ipxrip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
893 proto_tree *rip_tree;
896 struct ipx_rt_def route;
898 int available_length;
900 static char *rip_type[3] = { "Request", "Response", "Unknown" };
902 if (check_col(pinfo->cinfo, COL_PROTOCOL))
903 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPX RIP");
904 if (check_col(pinfo->cinfo, COL_INFO))
905 col_clear(pinfo->cinfo, COL_INFO);
907 operation = tvb_get_ntohs(tvb, 0) - 1;
909 if (check_col(pinfo->cinfo, COL_INFO)) {
910 /* rip_types 0 and 1 are valid, anything else becomes 2 or "Unknown" */
911 col_set_str(pinfo->cinfo, COL_INFO, rip_type[MIN(operation, 2)]);
915 ti = proto_tree_add_item(tree, proto_ipxrip, tvb, 0, -1, FALSE);
916 rip_tree = proto_item_add_subtree(ti, ett_ipxrip);
919 proto_tree_add_text(rip_tree, tvb, 0, 2,
920 "RIP packet type: %s", rip_type[operation]);
922 if (operation == 0) {
923 proto_tree_add_boolean_hidden(rip_tree,
927 proto_tree_add_boolean_hidden(rip_tree,
934 proto_tree_add_text(rip_tree, tvb, 0, 2, "Unknown RIP packet type");
937 available_length = tvb_reported_length(tvb);
938 for (cursor = 2; cursor < available_length; cursor += 8) {
939 tvb_memcpy(tvb, (guint8 *)&route.network, cursor, 4);
940 route.hops = tvb_get_ntohs(tvb, cursor+4);
941 route.ticks = tvb_get_ntohs(tvb, cursor+6);
943 if (operation == IPX_RIP_REQUEST - 1) {
944 proto_tree_add_text(rip_tree, tvb, cursor, 8,
945 "Route Vector: %s, %d hop%s, %d tick%s",
946 ipxnet_to_string((guint8*)&route.network),
947 route.hops, route.hops == 1 ? "" : "s",
948 route.ticks, route.ticks == 1 ? "" : "s");
951 proto_tree_add_text(rip_tree, tvb, cursor, 8,
952 "Route Vector: %s, %d hop%s, %d tick%s (%d ms)",
953 ipxnet_to_string((guint8*)&route.network),
954 route.hops, route.hops == 1 ? "" : "s",
955 route.ticks, route.ticks == 1 ? "" : "s",
956 route.ticks * 1000 / 18);
962 /* ================================================================= */
963 /* IPX Serialization */
964 /* ================================================================= */
966 dissect_serialization(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
968 proto_tree *ser_tree = NULL;
971 if (check_col(pinfo->cinfo, COL_PROTOCOL))
972 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NW_SERIAL");
973 if (check_col(pinfo->cinfo, COL_INFO))
974 col_clear(pinfo->cinfo, COL_INFO);
977 ti = proto_tree_add_item(tree, proto_serialization, tvb, 0, -1,
979 ser_tree = proto_item_add_subtree(ti, ett_serialization);
982 if (check_col(pinfo->cinfo, COL_INFO)) {
983 col_add_fstr(pinfo->cinfo, COL_INFO, "Serial number %s",
984 tvb_bytes_to_str(tvb, 0, 6));
988 proto_tree_add_text(ser_tree, tvb, 0, 6,
989 "Serial number: %s", tvb_bytes_to_str(tvb, 0, 6));
994 * Some of these are from ncpfs, others are from the book,
995 * others are from the page at
997 * http://www.iana.org/assignments/novell-sap-numbers
999 * and some from the page at
1001 * http://www.rware.demon.co.uk/ipxsap.htm
1003 * (see also the page at
1005 * http://developer.novell.com/research/appnotes/1998/february/03/06.htm
1007 * which has a huge list - but many of the entries list only the
1008 * organization owning the SAP type, not what the type is for).
1010 const value_string server_vals[] = {
1011 { 0x0000, "Unknown" },
1013 { 0x0002, "User Group" },
1014 { 0x0003, "Print Queue or Print Group" },
1015 { 0x0004, "File Server (SLIST source)" },
1016 { 0x0005, "Job Server" },
1017 { 0x0006, "Gateway" },
1018 { 0x0007, "Print Server or Silent Print Server" },
1019 { 0x0008, "Archive Queue" },
1020 { 0x0009, "Archive Server" },
1021 { 0x000a, "Job Queue" },
1022 { 0x000b, "Administration" },
1023 { 0x000F, "Novell TI-RPC" },
1024 { 0x0017, "Diagnostics" },
1025 { 0x0020, "NetBIOS" },
1026 { 0x0021, "NAS SNA Gateway" },
1027 { 0x0023, "NACS Async Gateway or Asynchronous Gateway" },
1028 { 0x0024, "Remote Bridge or Routing Service" },
1029 { 0x0026, "Bridge Server or Asynchronous Bridge Server" },
1030 { 0x0027, "TCP/IP Gateway Server" },
1031 { 0x0028, "Point to Point (Eicon) X.25 Bridge Server" },
1032 { 0x0029, "Eicon 3270 Gateway" },
1033 { 0x002a, "CHI Corp" },
1034 { 0x002c, "PC Chalkboard" },
1035 { 0x002d, "Time Synchronization Server or Asynchronous Timer" },
1036 { 0x002e, "ARCserve 5.0 / Palindrome Backup Director 4.x (PDB4)" },
1037 { 0x0045, "DI3270 Gateway" },
1038 { 0x0047, "Advertising Print Server" },
1039 { 0x004a, "NetBlazer Modems" },
1040 { 0x004b, "Btrieve VAP/NLM 5.0" },
1041 { 0x004c, "NetWare SQL VAP/NLM Server" },
1042 { 0x004d, "Xtree Network Version/NetWare XTree" },
1043 { 0x0050, "Btrieve VAP 4.11" },
1044 { 0x0052, "QuickLink (Cubix)" },
1045 { 0x0053, "Print Queue User" },
1046 { 0x0058, "Multipoint X.25 Eicon Router" },
1047 { 0x0060, "STLB/NLM" },
1048 { 0x0064, "ARCserve" },
1049 { 0x0066, "ARCserve 3.0" },
1050 { 0x0072, "WAN Copy Utility" },
1051 { 0x007a, "TES-NetWare for VMS" },
1052 { 0x0092, "WATCOM Debugger or Emerald Tape Backup Server" },
1053 { 0x0095, "DDA OBGYN" },
1054 { 0x0098, "NetWare Access Server (Asynchronous gateway)" },
1055 { 0x009a, "NetWare for VMS II or Named Pipe Server" },
1056 { 0x009b, "NetWare Access Server" },
1057 { 0x009e, "Portable NetWare Server or SunLink NVT" },
1058 { 0x00a1, "Powerchute APC UPS NLM" },
1059 { 0x00aa, "LAWserve" },
1060 { 0x00ac, "Compaq IDA Status Monitor" },
1061 { 0x0100, "PIPE STAIL" },
1062 { 0x0102, "LAN Protect Bindery" },
1063 { 0x0103, "Oracle DataBase Server" },
1064 { 0x0107, "NetWare 386 or RSPX Remote Console" },
1065 { 0x010f, "Novell SNA Gateway" },
1066 { 0x0111, "Test Server" },
1067 { 0x0112, "Print Server (HP)" },
1068 { 0x0114, "CSA MUX (f/Communications Executive)" },
1069 { 0x0115, "CSA LCA (f/Communications Executive)" },
1070 { 0x0116, "CSA CM (f/Communications Executive)" },
1071 { 0x0117, "CSA SMA (f/Communications Executive)" },
1072 { 0x0118, "CSA DBA (f/Communications Executive)" },
1073 { 0x0119, "CSA NMA (f/Communications Executive)" },
1074 { 0x011a, "CSA SSA (f/Communications Executive)" },
1075 { 0x011b, "CSA STATUS (f/Communications Executive)" },
1076 { 0x011e, "CSA APPC (f/Communications Executive)" },
1077 { 0x0126, "SNA TEST SSA Profile" },
1078 { 0x012a, "CSA TRACE (f/Communications Executive)" },
1079 { 0x012b, "NetWare for SAA" },
1080 { 0x012e, "IKARUS virus scan utility" },
1081 { 0x0130, "Communications Executive" },
1082 { 0x0133, "NNS Domain Server or NetWare Naming Services Domain" },
1083 { 0x0135, "NetWare Naming Services Profile" },
1084 { 0x0137, "NetWare 386 Print Queue or NNS Print Queue" },
1085 { 0x0141, "LAN Spool Server (Vap, Intel)" },
1086 { 0x0152, "IRMALAN Gateway" },
1087 { 0x0154, "Named Pipe Server" },
1088 { 0x0166, "NetWare Management" },
1089 { 0x0168, "Intel PICKIT Comm Server or Intel CAS Talk Server" },
1090 { 0x0173, "Compaq" },
1091 { 0x0174, "Compaq SNMP Agent" },
1092 { 0x0175, "Compaq" },
1093 { 0x0180, "XTree Server or XTree Tools" },
1094 { 0x018A, "NASI services broadcast server (Novell)" },
1095 { 0x01b0, "GARP Gateway (net research)" },
1096 { 0x01b1, "Binfview (Lan Support Group)" },
1097 { 0x01bf, "Intel LanDesk Manager" },
1098 { 0x01ca, "AXTEC" },
1099 { 0x01cb, "Shiva NetModem/E" },
1100 { 0x01cc, "Shiva LanRover/E" },
1101 { 0x01cd, "Shiva LanRover/T" },
1102 { 0x01ce, "Shiva Universal" },
1103 { 0x01d8, "Castelle FAXPress Server" },
1104 { 0x01da, "Castelle LANPress Print Server" },
1105 { 0x01dc, "Castelle FAX/Xerox 7033 Fax Server/Excel Lan Fax" },
1106 { 0x01f0, "LEGATO" },
1107 { 0x01f5, "LEGATO" },
1108 { 0x0233, "NMS Agent or NetWare Management Agent" },
1109 { 0x0237, "NMS IPX Discovery or LANtern Read/Write Channel" },
1110 { 0x0238, "NMS IP Discovery or LANtern Trap/Alarm Channel" },
1111 { 0x023a, "LANtern" },
1112 { 0x023c, "MAVERICK" },
1113 { 0x023f, "SMS Testing and Development" },
1114 { 0x024e, "NetWare Connect" },
1115 { 0x024f, "NASI server broadcast (Cisco)" },
1116 { 0x026a, "Network Management (NMS) Service Console" },
1117 { 0x026b, "Time Synchronization Server (NetWare 4.x)" },
1118 { 0x0278, "Directory Server (NetWare 4.x)" },
1119 { 0x027b, "NetWare Management Agent" },
1120 { 0x0280, "Novell File and Printer Sharing Service for PC" },
1121 { 0x0304, "Novell SAA Gateway" },
1122 { 0x0308, "COM or VERMED 1" },
1123 { 0x030a, "Galacticomm's Worldgroup Server" },
1124 { 0x030c, "Intel Netport 2 or HP JetDirect or HP Quicksilver" },
1125 { 0x0320, "Attachmate Gateway" },
1126 { 0x0327, "Microsoft Diagnostics" },
1127 { 0x0328, "WATCOM SQL server" },
1128 { 0x0335, "MultiTech Systems Multisynch Comm Server" },
1129 { 0x0343, "Xylogics Remote Access Server or LAN Modem" },
1130 { 0x0355, "Arcada Backup Exec" },
1131 { 0x0358, "MSLCD1" },
1132 { 0x0361, "NETINELO" },
1133 { 0x037e, "Powerchute UPS Monitoring" },
1134 { 0x037f, "ViruSafe Notify" },
1135 { 0x0386, "HP Bridge" },
1136 { 0x0387, "HP Hub" },
1137 { 0x0394, "NetWare SAA Gateway" },
1138 { 0x039b, "Lotus Notes" },
1139 { 0x03b7, "Certus Anti Virus NLM" },
1140 { 0x03c4, "ARCserve 4.0 (Cheyenne)" },
1141 { 0x03c7, "LANspool 3.5 (Intel)" },
1142 { 0x03d7, "Lexmark printer server (type 4033-011)" },
1143 { 0x03d8, "Lexmark XLE printer server (type 4033-301)" },
1144 { 0x03dd, "Banyan ENS for NetWare Client NLM" },
1145 { 0x03de, "Gupta Sequel Base Server or NetWare SQL" },
1146 { 0x03e1, "Univel Unixware" },
1147 { 0x03e4, "Univel Unixware" },
1148 { 0x03fc, "Intel Netport" },
1149 { 0x03fd, "Intel Print Server Queue" },
1150 { 0x040A, "ipnServer" },
1151 { 0x040D, "LVERRMAN" },
1152 { 0x040E, "LVLIC" },
1153 { 0x0414, "NET Silicon (DPI)/Kyocera" },
1154 { 0x0429, "Site Lock Virus (Brightworks)" },
1155 { 0x0432, "UFHELP R" },
1156 { 0x0433, "Synoptics 281x Advanced SNMP Agent" },
1157 { 0x0444, "Microsoft NT SNA Server" },
1158 { 0x0448, "Oracle" },
1159 { 0x044c, "ARCserve 5.01" },
1160 { 0x0457, "Canon GP55 Running on a Canon GP55 network printer" },
1161 { 0x045a, "QMS Printers" },
1162 { 0x045b, "Dell SCSI Array (DSA) Monitor" },
1163 { 0x0491, "NetBlazer Modems" },
1164 { 0x04ac, "On-Time Scheduler NLM" },
1165 { 0x04b0, "CD-Net (Meridian)" },
1166 { 0x0513, "Emulex NQA" },
1167 { 0x0520, "Site Lock Checks" },
1168 { 0x0529, "Site Lock Checks (Brightworks)" },
1169 { 0x052d, "Citrix OS/2 App Server" },
1170 { 0x0535, "Tektronix" },
1171 { 0x0536, "Milan" },
1172 { 0x055d, "Attachmate SNA gateway" },
1173 { 0x056b, "IBM 8235 modem server" },
1174 { 0x056c, "Shiva LanRover/E PLUS" },
1175 { 0x056d, "Shiva LanRover/T PLUS" },
1176 { 0x0580, "McAfee's NetShield anti-virus" },
1177 { 0x05B8, "NLM to workstation communication (Revelation Software)" },
1178 { 0x05BA, "Compatible Systems Routers" },
1179 { 0x05BE, "Cheyenne Hierarchical Storage Manager" },
1180 { 0x0606, "JCWatermark Imaging" },
1181 { 0x060c, "AXIS Network Printer" },
1182 { 0x0610, "Adaptec SCSI Management" },
1183 { 0x0621, "IBM AntiVirus NLM" },
1184 { 0x0640, "Microsoft Gateway Services for NetWare" },
1185 /* { 0x0640, "NT Server-RPC/GW for NW/Win95 User Level Sec" }, */
1186 { 0x064e, "Microsoft Internet Information Server" },
1187 { 0x067b, "Microsoft Win95/98 File and Print Sharing for NetWare" },
1188 { 0x067c, "Microsoft Win95/98 File and Print Sharing for NetWare" },
1189 { 0x076C, "Xerox" },
1190 { 0x079b, "Shiva LanRover/E 115" },
1191 { 0x079c, "Shiva LanRover/T 115" },
1192 { 0x07B4, "Cubix WorldDesk" },
1193 { 0x07c2, "Quarterdeck IWare Connect V2.x NLM" },
1194 { 0x07c1, "Quarterdeck IWare Connect V3.x NLM" },
1195 { 0x0810, "ELAN License Server Demo" },
1196 { 0x0824, "Shiva LanRover Access Switch/E" },
1197 { 0x086a, "ISSC collector NLMs" },
1198 { 0x087f, "ISSC DAS agent for AIX" },
1199 { 0x0880, "Intel Netport PRO" },
1200 { 0x0881, "Intel Netport PRO" },
1201 { 0x0b29, "Site Lock" },
1202 { 0x0c29, "Site Lock Applications" },
1203 { 0x0c2c, "Licensing Server" },
1204 { 0x2101, "Performance Technology Instant Internet" },
1205 { 0x2380, "LAI Site Lock" },
1206 { 0x238c, "Meeting Maker" },
1207 { 0x4808, "Site Lock Server or Site Lock Metering VAP/NLM" },
1208 { 0x5555, "Site Lock User" },
1209 { 0x6312, "Tapeware" },
1210 { 0x6f00, "Rabbit Gateway (3270)" },
1211 { 0x7703, "MODEM" },
1212 { 0x8002, "NetPort Printers (Intel) or LANport" },
1213 { 0x8003, "SEH InterCon Printserver" },
1214 { 0x8008, "WordPerfect Network Version" },
1215 { 0x85BE, "Cisco Enhanced Interior Routing Protocol (EIGRP)" },
1216 { 0x8888, "WordPerfect Network Version or Quick Network Management" },
1217 { 0x9000, "McAfee's NetShield anti-virus" },
1218 { 0x9604, "CSA-NT_MON" },
1219 { 0xb6a8, "Ocean Isle Reachout Remote Control" },
1220 { 0xf11f, "Site Lock Metering VAP/NLM" },
1221 { 0xf1ff, "Site Lock" },
1222 { 0xf503, "Microsoft SQL Server" },
1223 { 0xf905, "IBM Time and Place/2 application" },
1224 { 0xfbfb, "TopCall III fax server" },
1225 { 0xffff, "Any Service or Wildcard" },
1230 dissect_ipxsap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1232 proto_tree *sap_tree, *s_tree;
1235 struct sap_query query;
1236 guint16 server_type;
1237 char server_name[48];
1238 guint16 server_port;
1239 guint16 intermediate_network;
1241 static char *sap_type[4] = { "General Query", "General Response",
1242 "Nearest Query", "Nearest Response" };
1244 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1245 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPX SAP");
1246 if (check_col(pinfo->cinfo, COL_INFO))
1247 col_clear(pinfo->cinfo, COL_INFO);
1249 query.query_type = tvb_get_ntohs(tvb, 0);
1250 query.server_type = tvb_get_ntohs(tvb, 2);
1252 if (check_col(pinfo->cinfo, COL_INFO)) {
1253 if (query.query_type >= 1 && query.query_type <= 4) {
1254 col_set_str(pinfo->cinfo, COL_INFO, sap_type[query.query_type - 1]);
1257 col_set_str(pinfo->cinfo, COL_INFO, "Unknown Packet Type");
1262 ti = proto_tree_add_item(tree, proto_sap, tvb, 0, -1, FALSE);
1263 sap_tree = proto_item_add_subtree(ti, ett_ipxsap);
1265 if (query.query_type >= 1 && query.query_type <= 4) {
1266 proto_tree_add_text(sap_tree, tvb, 0, 2, sap_type[query.query_type - 1]);
1267 if ((query.query_type - 1) % 2) {
1268 proto_tree_add_boolean_hidden(sap_tree,
1272 proto_tree_add_boolean_hidden(sap_tree,
1278 proto_tree_add_text(sap_tree, tvb, 0, 2,
1279 "Unknown SAP Packet Type %d", query.query_type);
1282 if (query.query_type == IPX_SAP_GENERAL_RESPONSE ||
1283 query.query_type == IPX_SAP_NEAREST_RESPONSE) { /* responses */
1285 int available_length = tvb_reported_length(tvb);
1286 for (cursor = 2; (cursor + 64) <= available_length; cursor += 64) {
1287 server_type = tvb_get_ntohs(tvb, cursor);
1288 tvb_memcpy(tvb, (guint8 *)server_name,
1291 ti = proto_tree_add_text(sap_tree, tvb, cursor+2, 48,
1292 "Server Name: %.48s", server_name);
1293 s_tree = proto_item_add_subtree(ti, ett_ipxsap_server);
1295 proto_tree_add_text(s_tree, tvb, cursor, 2, "Server Type: %s (0x%04X)",
1296 val_to_str(server_type, server_vals, "Unknown"),
1298 proto_tree_add_text(s_tree, tvb, cursor+50, 4, "Network: %s",
1299 ipxnet_to_string(tvb_get_ptr(tvb, cursor+50, 4)));
1300 proto_tree_add_text(s_tree, tvb, cursor+54, 6, "Node: %s",
1301 ether_to_str(tvb_get_ptr(tvb, cursor+54, 6)));
1302 server_port = tvb_get_ntohs(tvb, cursor+60);
1303 proto_tree_add_text(s_tree, tvb, cursor+60, 2, "Socket: %s (0x%04x)",
1304 socket_text(server_port),
1306 intermediate_network = tvb_get_ntohs(tvb, cursor+62);
1307 proto_tree_add_text(s_tree, tvb, cursor+62, 2,
1308 "Intermediate Networks: %d",
1309 intermediate_network);
1312 else { /* queries */
1313 proto_tree_add_text(sap_tree, tvb, 2, 2, "Server Type: %s (0x%04X)",
1314 val_to_str(query.server_type, server_vals, "Unknown"),
1321 proto_register_ipx(void)
1323 static hf_register_info hf_ipx[] = {
1325 { "Checksum", "ipx.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1329 { "Source Address", "ipx.src", FT_STRING, BASE_DEC, NULL, 0x0,
1330 "Source IPX Address \"network.node\"", HFILL }},
1333 { "Destination Address", "ipx.dst", FT_STRING, BASE_DEC, NULL, 0x0,
1334 "Destination IPX Address \"network.node\"", HFILL }},
1336 { "Src/Dst Address", "ipx.addr", FT_STRING, BASE_DEC, NULL, 0x0,
1337 "Source or Destination IPX Address \"network.node\"", HFILL }},
1340 { "Length", "ipx.len", FT_UINT16, BASE_DEC, NULL, 0x0,
1344 { "Transport Control (Hops)", "ipx.hops", FT_UINT8, BASE_DEC, NULL, 0x0,
1347 { &hf_ipx_packet_type,
1348 { "Packet Type", "ipx.packet_type", FT_UINT8, BASE_HEX, VALS(ipx_packet_type_vals),
1353 { "Destination Network","ipx.dst.net", FT_IPXNET, BASE_NONE, NULL, 0x0,
1357 { "Destination Node", "ipx.dst.node", FT_ETHER, BASE_NONE, NULL, 0x0,
1361 { "Destination Socket", "ipx.dst.socket", FT_UINT16, BASE_HEX,
1362 VALS(ipx_socket_vals), 0x0,
1366 { "Source Network","ipx.src.net", FT_IPXNET, BASE_NONE, NULL, 0x0,
1370 { "Source Node", "ipx.src.node", FT_ETHER, BASE_NONE, NULL, 0x0,
1374 { "Source Socket", "ipx.src.socket", FT_UINT16, BASE_HEX,
1375 VALS(ipx_socket_vals), 0x0,
1379 { "Source or Destination Network","ipx.net", FT_IPXNET, BASE_NONE, NULL, 0x0,
1383 { "Source or Destination Node", "ipx.node", FT_ETHER, BASE_NONE, NULL, 0x0,
1387 { "Source or Destination Socket", "ipx.socket", FT_UINT16, BASE_HEX,
1388 VALS(ipx_socket_vals), 0x0,
1392 static hf_register_info hf_spx[] = {
1393 { &hf_spx_connection_control,
1394 { "Connection Control", "spx.ctl",
1395 FT_UINT8, BASE_HEX, NULL, 0x0,
1398 { &hf_spx_connection_control_sys,
1399 { "System Packet", "spx.ctl.sys",
1400 FT_BOOLEAN, 8, NULL, SPX_SYS_PACKET,
1403 { &hf_spx_connection_control_send_ack,
1404 { "Send Ack", "spx.ctl.send_ack",
1405 FT_BOOLEAN, 8, NULL, SPX_SEND_ACK,
1408 { &hf_spx_connection_control_attn,
1409 { "Attention", "spx.ctl.attn",
1410 FT_BOOLEAN, 8, NULL, SPX_ATTN,
1413 { &hf_spx_connection_control_eom,
1414 { "End of Message", "spx.ctl.eom",
1415 FT_BOOLEAN, 8, NULL, SPX_EOM,
1418 { &hf_spx_datastream_type,
1419 { "Datastream type", "spx.type",
1420 FT_UINT8, BASE_HEX, NULL, 0x0,
1424 { "Source Connection ID", "spx.src",
1425 FT_UINT16, BASE_DEC, NULL, 0x0,
1429 { "Destination Connection ID", "spx.dst",
1430 FT_UINT16, BASE_DEC, NULL, 0x0,
1434 { "Sequence Number", "spx.seq",
1435 FT_UINT16, BASE_DEC, NULL, 0x0,
1439 { "Acknowledgment Number", "spx.ack",
1440 FT_UINT16, BASE_DEC, NULL, 0x0,
1444 { "Allocation Number", "spx.alloc",
1445 FT_UINT16, BASE_DEC, NULL, 0x0,
1448 { &hf_spx_rexmt_frame,
1449 { "Retransmitted Frame Number", "spx.rexmt_frame",
1450 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1454 static hf_register_info hf_ipxrip[] = {
1455 { &hf_ipxrip_request,
1456 { "Request", "ipxrip.request",
1457 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1458 "TRUE if IPX RIP request", HFILL }},
1460 { &hf_ipxrip_response,
1461 { "Response", "ipxrip.response",
1462 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1463 "TRUE if IPX RIP response", HFILL }}
1466 static hf_register_info hf_sap[] = {
1468 { "Request", "ipxsap.request",
1469 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1470 "TRUE if SAP request", HFILL }},
1473 { "Response", "ipxsap.response",
1474 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1475 "TRUE if SAP response", HFILL }}
1478 static hf_register_info hf_ipxmsg[] = {
1480 { "Connection Number", "ipxmsg.conn",
1481 FT_UINT8, BASE_DEC, NULL, 0x0,
1482 "Connection Number", HFILL }},
1485 { "Signature Char", "ipxmsg.sigchar",
1486 FT_UINT8, BASE_DEC, VALS(ipxmsg_sigchar_vals), 0x0,
1487 "Signature Char", HFILL }}
1490 static gint *ett[] = {
1501 proto_ipx = proto_register_protocol("Internetwork Packet eXchange",
1503 proto_register_field_array(proto_ipx, hf_ipx, array_length(hf_ipx));
1505 register_dissector("ipx", dissect_ipx, proto_ipx);
1507 proto_spx = proto_register_protocol("Sequenced Packet eXchange",
1509 proto_register_field_array(proto_spx, hf_spx, array_length(hf_spx));
1511 proto_ipxrip = proto_register_protocol("IPX Routing Information Protocol",
1512 "IPX RIP", "ipxrip");
1513 proto_register_field_array(proto_ipxrip, hf_ipxrip, array_length(hf_ipxrip));
1515 proto_serialization = proto_register_protocol("NetWare Serialization Protocol",
1516 "NW_SERIAL", "nw_serial");
1518 proto_ipxmsg = proto_register_protocol("IPX Message", "IPX MSG",
1520 proto_register_field_array(proto_ipxmsg, hf_ipxmsg, array_length(hf_ipxmsg));
1522 proto_sap = proto_register_protocol("Service Advertisement Protocol",
1523 "IPX SAP", "ipxsap");
1524 register_dissector("ipxsap", dissect_ipxsap, proto_sap);
1526 proto_register_field_array(proto_sap, hf_sap, array_length(hf_sap));
1528 proto_register_subtree_array(ett, array_length(ett));
1530 ipx_type_dissector_table = register_dissector_table("ipx.packet_type",
1531 "IPX packet type", FT_UINT8, BASE_HEX);
1532 ipx_socket_dissector_table = register_dissector_table("ipx.socket",
1533 "IPX socket", FT_UINT16, BASE_HEX);
1534 spx_socket_dissector_table = register_dissector_table("spx.socket",
1535 "SPX socket", FT_UINT16, BASE_HEX);
1537 register_init_routine(&spx_init_protocol);
1538 register_postseq_cleanup_routine(&spx_postseq_cleanup);
1539 ipx_tap=register_tap("ipx");
1543 proto_reg_handoff_ipx(void)
1545 dissector_handle_t ipx_handle, spx_handle;
1546 dissector_handle_t ipxsap_handle, ipxrip_handle;
1547 dissector_handle_t serialization_handle, ipxmsg_handle;
1549 ipx_handle = find_dissector("ipx");
1550 dissector_add("udp.port", UDP_PORT_IPX, ipx_handle);
1551 dissector_add("ethertype", ETHERTYPE_IPX, ipx_handle);
1552 dissector_add("chdlctype", ETHERTYPE_IPX, ipx_handle);
1553 dissector_add("ppp.protocol", PPP_IPX, ipx_handle);
1554 dissector_add("llc.dsap", SAP_NETWARE1, ipx_handle);
1555 dissector_add("llc.dsap", SAP_NETWARE2, ipx_handle);
1556 dissector_add("null.type", BSD_AF_IPX, ipx_handle);
1557 dissector_add("gre.proto", ETHERTYPE_IPX, ipx_handle);
1558 dissector_add("arcnet.protocol_id", ARCNET_PROTO_IPX, ipx_handle);
1559 dissector_add("arcnet.protocol_id", ARCNET_PROTO_NOVELL_EC, ipx_handle);
1561 spx_handle = create_dissector_handle(dissect_spx, proto_spx);
1562 dissector_add("ipx.packet_type", IPX_PACKET_TYPE_SPX, spx_handle);
1564 ipxsap_handle = find_dissector("ipxsap");
1565 dissector_add("ipx.socket", IPX_SOCKET_SAP, ipxsap_handle);
1567 ipxrip_handle = create_dissector_handle(dissect_ipxrip, proto_ipxrip);
1568 dissector_add("ipx.socket", IPX_SOCKET_IPXRIP, ipxrip_handle);
1570 serialization_handle = create_dissector_handle(dissect_serialization,
1571 proto_serialization);
1572 dissector_add("ipx.socket", IPX_SOCKET_SERIALIZATION,
1573 serialization_handle);
1575 ipxmsg_handle = create_dissector_handle(dissect_ipxmsg, proto_ipxmsg);
1576 dissector_add("ipx.socket", IPX_SOCKET_IPX_MESSAGE, ipxmsg_handle);
1577 dissector_add("ipx.socket", IPX_SOCKET_IPX_MESSAGE1, ipxmsg_handle);
1579 data_handle = find_dissector("data");