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 * Wireshark - Network traffic analyzer
12 * By Gerald Combs <gerald@wireshark.org>
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
33 #include <epan/packet.h>
34 #include "packet-ipx.h"
35 #include "packet-sll.h"
36 #include <epan/addr_resolv.h>
37 #include <epan/etypes.h>
38 #include <epan/ppptypes.h>
39 #include <epan/llcsaps.h>
40 #include <epan/aftypes.h>
41 #include <epan/arcnet_pids.h>
42 #include <epan/conversation.h>
44 #include <epan/wmem/wmem.h>
46 static int ipx_tap
= -1;
48 /* The information in this module (IPX, SPX, NCP) comes from:
49 NetWare LAN Analysis, Second Edition
50 Laura A. Chappell and Dan E. Hakes
52 Novell Press, San Jose.
55 And from the ncpfs source code by Volker Lendecke
59 static int proto_ipx
= -1;
60 static int hf_ipx_checksum
= -1;
61 static int hf_ipx_len
= -1;
62 static int hf_ipx_src
= -1;
63 static int hf_ipx_dst
= -1;
64 static int hf_ipx_addr
= -1;
65 static int hf_ipx_hops
= -1;
66 static int hf_ipx_packet_type
= -1;
67 static int hf_ipx_dnet
= -1;
68 static int hf_ipx_dnode
= -1;
69 static int hf_ipx_dsocket
= -1;
70 static int hf_ipx_snet
= -1;
71 static int hf_ipx_snode
= -1;
72 static int hf_ipx_ssocket
= -1;
73 static int hf_ipx_net
= -1;
74 static int hf_ipx_node
= -1;
75 static int hf_ipx_socket
= -1;
77 static gint ett_ipx
= -1;
79 static dissector_table_t ipx_type_dissector_table
;
80 static dissector_table_t ipx_socket_dissector_table
;
81 static dissector_table_t spx_socket_dissector_table
;
83 static int proto_spx
= -1;
84 static int hf_spx_connection_control
= -1;
85 static int hf_spx_connection_control_sys
= -1;
86 static int hf_spx_connection_control_send_ack
= -1;
87 static int hf_spx_connection_control_attn
= -1;
88 static int hf_spx_connection_control_eom
= -1;
89 static int hf_spx_datastream_type
= -1;
90 static int hf_spx_src_id
= -1;
91 static int hf_spx_dst_id
= -1;
92 static int hf_spx_seq_nr
= -1;
93 static int hf_spx_ack_nr
= -1;
94 static int hf_spx_all_nr
= -1;
95 static int hf_spx_rexmt_frame
= -1;
97 static gint ett_spx
= -1;
98 static gint ett_spx_connctrl
= -1;
100 static int proto_ipxrip
= -1;
101 static int hf_ipxrip_request
= -1;
102 static int hf_ipxrip_response
= -1;
104 static gint ett_ipxrip
= -1;
106 static int proto_serialization
= -1;
108 static gint ett_serialization
= -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_serialization(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
);
134 dissect_ipxsap(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
);
137 dissect_ipxmsg(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
);
139 #define UDP_PORT_IPX 213 /* RFC 1234 */
141 #define IPX_HEADER_LEN 30 /* It's *always* 30 bytes */
143 /* ================================================================= */
145 /* ================================================================= */
146 static const value_string ipx_socket_vals
[] = {
147 { IPX_SOCKET_PING_CISCO
, "CISCO PING" },
148 { IPX_SOCKET_NCP
, "NCP" },
149 { IPX_SOCKET_SAP
, "SAP" },
150 { IPX_SOCKET_IPXRIP
, "RIP" },
151 { IPX_SOCKET_NETBIOS
, "NetBIOS" },
152 { IPX_SOCKET_DIAGNOSTIC
, "Diagnostic" },
153 { IPX_SOCKET_SERIALIZATION
, "Serialization" },
154 { IPX_SOCKET_NWLINK_SMB_SERVER
, "NWLink SMB Server" },
155 { IPX_SOCKET_NWLINK_SMB_NAMEQUERY
, "NWLink SMB Name Query" },
156 { IPX_SOCKET_NWLINK_SMB_REDIR
, "NWLink SMB Redirector" },
157 { IPX_SOCKET_NWLINK_SMB_MAILSLOT
, "NWLink SMB Mailslot Datagram" },
158 { IPX_SOCKET_NWLINK_SMB_MESSENGER
, "NWLink SMB Messenger" },
159 { IPX_SOCKET_NWLINK_SMB_BROWSE
, "NWLink SMB Browse" },
160 { IPX_SOCKET_ATTACHMATE_GW
, "Attachmate Gateway" },
161 { IPX_SOCKET_IPX_MESSAGE
, "IPX Message" },
162 { IPX_SOCKET_IPX_MESSAGE1
, "IPX Message" },
163 { 0x4006, "NetWare Directory Server" },
164 { 0x400C, "HP LaserJet/QuickSilver" },
165 { 0x8104, "NetWare 386" },
166 { IPX_SOCKET_ADSM
, "ADSM" },
167 { IPX_SOCKET_EIGRP
, "Cisco EIGRP for IPX" },
168 { 0x8F83, "Powerchute UPS Monitoring" },
169 { IPX_SOCKET_NLSP
, "NetWare Link Services Protocol" },
170 { IPX_SOCKET_IPXWAN
, "IPX WAN" },
171 { IPX_SOCKET_SNMP_AGENT
, "SNMP Agent" },
172 { IPX_SOCKET_SNMP_SINK
, "SNMP Sink" },
173 { 0x907B, "SMS Testing and Development" },
174 { IPX_SOCKET_PING_NOVELL
, "Novell PING" },
175 { IPX_SOCKET_TCP_TUNNEL
, "TCP Tunnel" },
176 { IPX_SOCKET_UDP_TUNNEL
, "UDP Tunnel" },
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" },
187 value_string_ext ipx_socket_vals_ext
= VALUE_STRING_EXT_INIT(ipx_socket_vals
);
190 socket_text(guint16 socket
)
192 return val_to_str_ext_const(socket
, &ipx_socket_vals_ext
, "Unknown");
195 static const value_string ipx_packet_type_vals
[] = {
196 { IPX_PACKET_TYPE_IPX
, "IPX" },
197 { IPX_PACKET_TYPE_RIP
, "RIP" },
198 { IPX_PACKET_TYPE_ECHO
, "Echo" },
199 { IPX_PACKET_TYPE_ERROR
, "Error" },
200 { IPX_PACKET_TYPE_PEP
, "PEP" }, /* Packet Exchange Packet */
201 { IPX_PACKET_TYPE_SPX
, "SPX" },
202 { 16, "Experimental Protocol" },
203 { IPX_PACKET_TYPE_NCP
, "NCP" },
204 { 18, "Experimental Protocol" },
205 { 19, "Experimental Protocol" },
206 { IPX_PACKET_TYPE_WANBCAST
, "NetBIOS Broadcast" },
207 { 21, "Experimental Protocol" },
208 { 22, "Experimental Protocol" },
209 { 23, "Experimental Protocol" },
210 { 24, "Experimental Protocol" },
211 { 25, "Experimental Protocol" },
212 { 26, "Experimental Protocol" },
213 { 27, "Experimental Protocol" },
214 { 28, "Experimental Protocol" },
215 { 29, "Experimental Protocol" },
216 { 30, "Experimental Protocol" },
217 { 31, "Experimental Protocol" },
221 static const value_string ipxmsg_sigchar_vals
[] = {
222 { '?', "Poll inactive station" },
223 { 'Y', "Station is still using the connection" },
224 { '!', "Broadcast message waiting" },
229 capture_ipx(packet_counts
*ld
)
235 dissect_ipx(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
239 proto_tree
*ipx_tree
= NULL
;
240 proto_item
*ti
= NULL
, *hidden_item
;
242 const guint8
*src_net_node
, *dst_net_node
;
246 guint16 first_socket
, second_socket
;
247 guint32 ipx_snet
, ipx_dnet
;
248 static ipxhdr_t ipxh_arr
[4];
249 static int ipx_current
=0;
256 ipxh
=&ipxh_arr
[ipx_current
];
259 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "IPX");
260 col_clear(pinfo
->cinfo
, COL_INFO
);
262 /* Calculate here for use in pinfo and in tree */
263 ipxh
->ipx_dsocket
= tvb_get_ntohs(tvb
, 16);
264 ipxh
->ipx_ssocket
= tvb_get_ntohs(tvb
, 28);
265 ipxh
->ipx_type
= tvb_get_guint8(tvb
, 5);
266 ipxh
->ipx_length
= tvb_get_ntohs(tvb
, 2);
268 pinfo
->ptype
= PT_IPX
;
269 pinfo
->srcport
= ipxh
->ipx_ssocket
;
270 pinfo
->destport
= ipxh
->ipx_dsocket
;
272 /* Adjust the tvbuff length to include only the IPX datagram. */
273 set_actual_length(tvb
, ipxh
->ipx_length
);
275 src_net_node
= tvb_get_ptr(tvb
, 18, 10);
276 dst_net_node
= tvb_get_ptr(tvb
, 6, 10);
278 SET_ADDRESS(&pinfo
->net_src
, AT_IPX
, 10, src_net_node
);
279 SET_ADDRESS(&pinfo
->src
, AT_IPX
, 10, src_net_node
);
280 SET_ADDRESS(&ipxh
->ipx_src
, AT_IPX
, 10, src_net_node
);
281 SET_ADDRESS(&pinfo
->net_dst
, AT_IPX
, 10, dst_net_node
);
282 SET_ADDRESS(&pinfo
->dst
, AT_IPX
, 10, dst_net_node
);
283 SET_ADDRESS(&ipxh
->ipx_dst
, AT_IPX
, 10, dst_net_node
);
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
, ENC_NA
);
291 ipx_tree
= proto_item_add_subtree(ti
, ett_ipx
);
294 str
=ep_address_to_str(&pinfo
->net_src
);
295 hidden_item
= proto_tree_add_string(ipx_tree
, hf_ipx_src
, tvb
, 0, 0, str
);
296 PROTO_ITEM_SET_HIDDEN(hidden_item
);
297 hidden_item
= proto_tree_add_string(ipx_tree
, hf_ipx_addr
, tvb
, 0, 0, str
);
298 PROTO_ITEM_SET_HIDDEN(hidden_item
);
299 str
=ep_address_to_str(&pinfo
->net_dst
);
300 hidden_item
= proto_tree_add_string(ipx_tree
, hf_ipx_dst
, tvb
, 0, 0, str
);
301 PROTO_ITEM_SET_HIDDEN(hidden_item
);
302 hidden_item
= proto_tree_add_string(ipx_tree
, hf_ipx_addr
, tvb
, 0, 0, str
);
303 PROTO_ITEM_SET_HIDDEN(hidden_item
);
305 proto_tree_add_item(ipx_tree
, hf_ipx_checksum
, tvb
, 0, 2, ENC_BIG_ENDIAN
);
306 proto_tree_add_uint_format_value(ipx_tree
, hf_ipx_len
, tvb
, 2, 2, ipxh
->ipx_length
,
307 "%d bytes", ipxh
->ipx_length
);
308 ipx_hops
= tvb_get_guint8(tvb
, 4);
309 proto_tree_add_uint_format(ipx_tree
, hf_ipx_hops
, tvb
, 4, 1, ipx_hops
,
310 "Transport Control: %d hops", ipx_hops
);
311 proto_tree_add_uint(ipx_tree
, hf_ipx_packet_type
, tvb
, 5, 1, ipxh
->ipx_type
);
314 ipx_dnet
= tvb_get_ntohl(tvb
, 6);
315 proto_tree_add_ipxnet(ipx_tree
, hf_ipx_dnet
, tvb
, 6, 4,
317 hidden_item
= proto_tree_add_ipxnet(ipx_tree
, hf_ipx_net
, tvb
, 6, 4,
319 PROTO_ITEM_SET_HIDDEN(hidden_item
);
320 proto_tree_add_item(ipx_tree
, hf_ipx_dnode
, tvb
, 10, 6, ENC_NA
);
321 hidden_item
= proto_tree_add_item(ipx_tree
, hf_ipx_node
, tvb
, 10, 6, ENC_NA
);
322 PROTO_ITEM_SET_HIDDEN(hidden_item
);
323 proto_tree_add_uint(ipx_tree
, hf_ipx_dsocket
, tvb
, 16, 2,
325 hidden_item
= proto_tree_add_uint(ipx_tree
, hf_ipx_socket
, tvb
, 16, 2,
327 PROTO_ITEM_SET_HIDDEN(hidden_item
);
330 ipx_snet
= tvb_get_ntohl(tvb
, 18);
331 proto_tree_add_ipxnet(ipx_tree
, hf_ipx_snet
, tvb
, 18, 4,
333 hidden_item
= proto_tree_add_ipxnet(ipx_tree
, hf_ipx_net
, tvb
, 18, 4,
335 PROTO_ITEM_SET_HIDDEN(hidden_item
);
336 proto_tree_add_item(ipx_tree
, hf_ipx_snode
, tvb
, 22, 6, ENC_NA
);
337 hidden_item
= proto_tree_add_item(ipx_tree
, hf_ipx_node
, tvb
, 22, 6, ENC_NA
);
338 PROTO_ITEM_SET_HIDDEN(hidden_item
);
339 proto_tree_add_uint(ipx_tree
, hf_ipx_ssocket
, tvb
, 28, 2,
341 hidden_item
= proto_tree_add_uint(ipx_tree
, hf_ipx_socket
, tvb
, 28, 2,
343 PROTO_ITEM_SET_HIDDEN(hidden_item
);
345 /* Make the next tvbuff */
346 next_tvb
= tvb_new_subset_remaining(tvb
, IPX_HEADER_LEN
);
349 * Check the socket numbers before we check the packet type;
350 * we've seen non-NCP packets with a type of NCP and a
351 * destination socket of IPX_SOCKET_IPX_MESSAGE, and SAP
352 * packets with a type of NCP and a destination socket of
355 * We've seen NCP packets with a type of NCP, a source socket of
356 * IPX_SOCKET_NCP, and a destination socket of IPX_SOCKET_IPX_MESSAGE,
357 * and we've seen NCP packets with a type of NCP, a source socket of
358 * IPX_SOCKET_IPX_MESSAGE, and a destination socket of
359 * IPX_SOCKET_NCP, so testing the destination socket first doesn't
360 * always give the right answer. We've also seen SAP packets with
361 * a source socket of IPX_SOCKET_SAP and a destination socket of
362 * IPX_SOCKET_IPX_MESSAGE.
364 * Unfortunately, we've also seen packets with a source socket
365 * of IPX_SOCKET_NWLINK_SMB_SERVER and a destination socket
366 * of IPX_SOCKET_NWLINK_SMB_NAMEQUERY that were NMPI packets,
367 * not SMB packets, so testing the lower-valued socket first
368 * also doesn't always give the right answer.
370 * So we start out assuming we should test the lower-numbered
371 * socket number first, but, if the higher-numbered socket is
372 * IPX_SOCKET_NWLINK_SMB_NAMEQUERY, we assume that it's a
373 * NMPI query, and test only that socket.
375 if (ipxh
->ipx_ssocket
> ipxh
->ipx_dsocket
) {
376 first_socket
= ipxh
->ipx_dsocket
;
377 second_socket
= ipxh
->ipx_ssocket
;
379 first_socket
= ipxh
->ipx_ssocket
;
380 second_socket
= ipxh
->ipx_dsocket
;
383 tap_queue_packet(ipx_tap
, pinfo
, ipxh
);
385 if (second_socket
!= IPX_SOCKET_NWLINK_SMB_NAMEQUERY
) {
386 if (dissector_try_uint_new(ipx_socket_dissector_table
, first_socket
,
387 next_tvb
, pinfo
, tree
, FALSE
, ipxh
))
390 if (dissector_try_uint_new(ipx_socket_dissector_table
, second_socket
,
391 next_tvb
, pinfo
, tree
, FALSE
, ipxh
))
395 * Neither of them are known; try the packet type, which will
396 * at least let us, for example, dissect SPX packets as SPX.
398 if (dissector_try_uint_new(ipx_type_dissector_table
, ipxh
->ipx_type
, next_tvb
,
399 pinfo
, tree
, FALSE
, ipxh
))
402 call_dissector(data_handle
,next_tvb
, pinfo
, tree
);
404 /* ================================================================= */
405 /* SPX Hash Functions */
406 /* ================================================================= */
409 conversation_t
*conversation
;
421 * Structure attached to retransmitted SPX frames; it contains the
422 * frame number of the original transmission.
428 static GHashTable
*spx_hash
= NULL
;
432 spx_equal(gconstpointer v
, gconstpointer v2
)
434 const spx_hash_key
*val1
= (const spx_hash_key
*)v
;
435 const spx_hash_key
*val2
= (const spx_hash_key
*)v2
;
437 if (val1
->conversation
== val2
->conversation
&&
438 val1
->spx_src
== val2
->spx_src
&&
439 val1
->spx_seq
== val2
->spx_seq
) {
446 spx_hash_func(gconstpointer v
)
448 const spx_hash_key
*spx_key
= (const spx_hash_key
*)v
;
449 return GPOINTER_TO_UINT(spx_key
->conversation
) + spx_key
->spx_src
;
452 /* Initializes the hash table each time a new
453 * file is loaded or re-loaded in wireshark */
455 spx_init_protocol(void)
459 g_hash_table_destroy(spx_hash
);
461 spx_hash
= g_hash_table_new(spx_hash_func
, spx_equal
);
464 /* After the sequential run, we don't need the spx hash table, or
465 * the keys and values, anymore; the lookups have already been done
466 * and the relevant info saved as SPX private data with the frame
467 * if the frame was a retransmission. */
469 spx_postseq_cleanup(void)
472 /* Destroy the hash, but don't clean up request_condition data. */
473 g_hash_table_destroy(spx_hash
);
478 static spx_hash_value
*
479 spx_hash_insert(conversation_t
*conversation
, guint32 spx_src
, guint16 spx_seq
)
482 spx_hash_value
*value
;
484 /* Now remember the packet, so we can find it if we later. */
485 key
= wmem_new(wmem_file_scope(), spx_hash_key
);
486 key
->conversation
= conversation
;
487 key
->spx_src
= spx_src
;
488 key
->spx_seq
= spx_seq
;
490 value
= wmem_new0(wmem_file_scope(), spx_hash_value
);
492 g_hash_table_insert(spx_hash
, key
, value
);
497 /* Returns the spx_hash_value*, or NULL if not found. */
498 static spx_hash_value
*
499 spx_hash_lookup(conversation_t
*conversation
, guint32 spx_src
, guint32 spx_seq
)
503 key
.conversation
= conversation
;
504 key
.spx_src
= spx_src
;
505 key
.spx_seq
= spx_seq
;
507 return (spx_hash_value
*)g_hash_table_lookup(spx_hash
, &key
);
510 /* ================================================================= */
512 /* ================================================================= */
514 #define SPX_SYS_PACKET 0x80
515 #define SPX_SEND_ACK 0x40
516 #define SPX_ATTN 0x20
520 spx_conn_ctrl(guint8 ctrl
)
524 static const value_string conn_vals
[] = {
525 { 0x00, "Data, No Ack Required" },
526 { SPX_EOM
, "End-of-Message" },
527 { SPX_ATTN
, "Attention" },
528 { SPX_SEND_ACK
, "Acknowledgment Required"},
529 { SPX_SEND_ACK
|SPX_EOM
, "Send Ack: End Message"},
530 { SPX_SYS_PACKET
, "System Packet"},
531 { SPX_SYS_PACKET
|SPX_SEND_ACK
, "System Packet: Send Ack"},
535 p
= try_val_to_str((ctrl
& 0xf0), conn_vals
);
546 spx_datastream(guint8 type
)
550 return "End-of-Connection";
552 return "End-of-Connection Acknowledgment";
558 #define SPX_HEADER_LEN 12
561 dissect_spx(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
563 proto_tree
*spx_tree
= NULL
;
568 guint8 datastream_type
;
569 const char *datastream_type_string
;
571 const char *spx_msg_string
;
572 guint16 low_socket
, high_socket
;
574 conversation_t
*conversation
;
575 spx_hash_value
*pkt_value
;
576 spx_rexmit_info
*spx_rexmit_info_p
;
579 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "SPX");
580 col_set_str(pinfo
->cinfo
, COL_INFO
, "SPX");
583 ti
= proto_tree_add_item(tree
, proto_spx
, tvb
, 0, SPX_HEADER_LEN
, ENC_NA
);
584 spx_tree
= proto_item_add_subtree(ti
, ett_spx
);
587 conn_ctrl
= tvb_get_guint8(tvb
, 0);
588 spx_msg_string
= spx_conn_ctrl(conn_ctrl
);
589 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " %s", spx_msg_string
);
591 ti
= proto_tree_add_uint_format_value(spx_tree
, hf_spx_connection_control
, tvb
,
594 spx_msg_string
, conn_ctrl
);
595 cc_tree
= proto_item_add_subtree(ti
, ett_spx_connctrl
);
596 proto_tree_add_boolean(cc_tree
, hf_spx_connection_control_sys
, tvb
,
598 proto_tree_add_boolean(cc_tree
, hf_spx_connection_control_send_ack
, tvb
,
600 proto_tree_add_boolean(cc_tree
, hf_spx_connection_control_attn
, tvb
,
602 proto_tree_add_boolean(cc_tree
, hf_spx_connection_control_eom
, tvb
,
606 datastream_type
= tvb_get_guint8(tvb
, 1);
607 datastream_type_string
= spx_datastream(datastream_type
);
608 if (datastream_type_string
!= NULL
) {
609 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (%s)",
610 datastream_type_string
);
613 if (datastream_type_string
!= NULL
) {
614 proto_tree_add_uint_format_value(spx_tree
, hf_spx_datastream_type
, tvb
,
615 1, 1, datastream_type
,
617 datastream_type_string
,
620 proto_tree_add_uint_format_value(spx_tree
, hf_spx_datastream_type
, tvb
,
621 1, 1, datastream_type
,
625 proto_tree_add_item(spx_tree
, hf_spx_src_id
, tvb
, 2, 2, ENC_BIG_ENDIAN
);
626 proto_tree_add_item(spx_tree
, hf_spx_dst_id
, tvb
, 4, 2, ENC_BIG_ENDIAN
);
628 spx_seq
= tvb_get_ntohs(tvb
, 6);
630 proto_tree_add_uint(spx_tree
, hf_spx_seq_nr
, tvb
, 6, 2, spx_seq
);
631 proto_tree_add_item(spx_tree
, hf_spx_ack_nr
, tvb
, 8, 2, ENC_BIG_ENDIAN
);
632 proto_tree_add_item(spx_tree
, hf_spx_all_nr
, tvb
, 10, 2, ENC_BIG_ENDIAN
);
636 * SPX is Connection Oriented and Delivery Guaranteed.
637 * On the first pass, we need to flag retransmissions by the SPX
638 * protocol, so that subdissectors know whether a packet was
641 * We start out by creating a conversation for this direction of the
642 * IPX session; we use "pinfo->srcport" twice, so that we have
643 * separate conversations for the two directions.
645 * XXX - that might not work correctly if there's more than one
646 * SPX session using that source port; can that happen? If so,
647 * we should probably use the direction, as well as the conversation,
648 * as part of the hash key; if we do that, we can probably just
649 * use PT_IPX as the port type, and possibly get rid of PT_NCP.
653 * http://developer.novell.com/research/appnotes/1995/december/03/apv.htm
655 * the sequence number is not incremented for system packets, so
656 * presumably that means there is no notion of a system packet
657 * being retransmitted; that document also says that system
658 * packets are used as "I'm still here" keepalives and as
659 * acknowledgements (presumably meaning ACK-only packets), which
660 * suggests that they might not be ACKed and thus might not
663 if (conn_ctrl
& SPX_SYS_PACKET
) {
665 * It's a system packet, so it isn't a retransmission.
667 spx_rexmit_info_p
= NULL
;
670 * Not a system packet - check for retransmissions.
672 if (!pinfo
->fd
->flags
.visited
) {
673 conversation
= find_conversation(pinfo
->fd
->num
, &pinfo
->src
,
674 &pinfo
->dst
, PT_NCP
, pinfo
->srcport
,
676 if (conversation
== NULL
) {
678 * It's not part of any conversation - create
681 conversation
= conversation_new(pinfo
->fd
->num
, &pinfo
->src
,
682 &pinfo
->dst
, PT_NCP
, pinfo
->srcport
,
687 * Now we'll hash the SPX header and use the result
688 * of that, plus the conversation, as a hash key to
689 * identify this packet.
691 * If we don't find it in the hash table, it's not a
692 * retransmission, otherwise it is. If we don't find
693 * it, we enter it into the hash table, with the
695 * If we do, we attach to this frame a structure giving
696 * the frame number of the original transmission, so
697 * that we, and subdissectors, know it's a
700 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);
701 pkt_value
= spx_hash_lookup(conversation
, src
, spx_seq
);
702 if (pkt_value
== NULL
) {
704 * Not found in the hash table.
705 * Enter it into the hash table.
707 pkt_value
= spx_hash_insert(conversation
, src
,
709 pkt_value
->spx_ack
= tvb_get_ntohs(tvb
, 8);
710 pkt_value
->spx_all
= tvb_get_ntohs(tvb
, 10);
711 pkt_value
->num
= pinfo
->fd
->num
;
714 * This is not a retransmission, so we shouldn't
715 * have any retransmission indicator.
717 spx_rexmit_info_p
= NULL
;
720 * Found in the hash table. Mark this frame as
723 spx_rexmit_info_p
= wmem_new(wmem_file_scope(), spx_rexmit_info
);
724 spx_rexmit_info_p
->num
= pkt_value
->num
;
725 p_add_proto_data(pinfo
->fd
, proto_spx
, 0,
730 * Do we have per-packet SPX data for this frame?
731 * If so, it's a retransmission, and the per-packet
732 * data indicates which frame had the original
735 spx_rexmit_info_p
= (spx_rexmit_info
*)p_get_proto_data(pinfo
->fd
,
741 * It's a retransmission if we have a retransmission indicator.
742 * Flag this as a retransmission, but don't pass it to the
745 if (spx_rexmit_info_p
!= NULL
) {
746 col_add_fstr(pinfo
->cinfo
, COL_INFO
,
747 "[Retransmission] Original Packet %u",
748 spx_rexmit_info_p
->num
);
751 proto_tree_add_uint_format(spx_tree
, hf_spx_rexmt_frame
,
752 tvb
, 0, 0, spx_rexmit_info_p
->num
,
753 "This is a retransmission of frame %u",
754 spx_rexmit_info_p
->num
);
755 if (tvb_length_remaining(tvb
, SPX_HEADER_LEN
) > 0) {
756 proto_tree_add_text(spx_tree
, tvb
,
758 "Retransmitted data");
764 if (tvb_reported_length_remaining(tvb
, SPX_HEADER_LEN
) > 0) {
766 * Call subdissectors based on the IPX socket numbers; a
767 * subdissector might have registered with our IPX socket
768 * dissector table rather than the IPX dissector's socket
771 * Assume the lower-numbered socket number is more likely
772 * to be the right one, along the lines of what we do for
773 * TCP and UDP. We've seen NCP packets with a type of NCP,
774 * a source socket of IPX_SOCKET_NCP, and a destination
775 * socket of IPX_SOCKET_IPX_MESSAGE, and we've seen NCP
776 * packets with a type of NCP, a source socket of
777 * IPX_SOCKET_IPX_MESSAGE, and a destination socket of
780 if (pinfo
->srcport
> pinfo
->destport
) {
781 low_socket
= pinfo
->destport
;
782 high_socket
= pinfo
->srcport
;
784 low_socket
= pinfo
->srcport
;
785 high_socket
= pinfo
->destport
;
789 * Pass information to subdissectors.
791 spx_infox
.eom
= conn_ctrl
& SPX_EOM
;
792 spx_infox
.datastream_type
= datastream_type
;
794 next_tvb
= tvb_new_subset_remaining(tvb
, SPX_HEADER_LEN
);
795 if (dissector_try_uint_new(spx_socket_dissector_table
, low_socket
,
796 next_tvb
, pinfo
, tree
, FALSE
, &spx_infox
))
800 if (dissector_try_uint_new(spx_socket_dissector_table
, high_socket
,
801 next_tvb
, pinfo
, tree
, FALSE
, &spx_infox
))
805 call_dissector(data_handle
, next_tvb
, pinfo
, tree
);
809 /* ================================================================= */
811 /* ================================================================= */
813 dissect_ipxmsg(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
815 proto_tree
*msg_tree
;
817 guint8 conn_number
, sig_char
;
819 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "IPX MSG");
820 col_clear(pinfo
->cinfo
, COL_INFO
);
822 conn_number
= tvb_get_guint8(tvb
, 0);
823 sig_char
= tvb_get_guint8(tvb
, 1);
825 col_add_fstr(pinfo
->cinfo
, COL_INFO
,
827 val_to_str_const(sig_char
, ipxmsg_sigchar_vals
, "Unknown Signature Char"), conn_number
);
830 ti
= proto_tree_add_item(tree
, proto_ipxmsg
, tvb
, 0, -1, ENC_NA
);
831 msg_tree
= proto_item_add_subtree(ti
, ett_ipxmsg
);
833 proto_tree_add_uint(msg_tree
, hf_msg_conn
, tvb
, 0, 1, conn_number
);
834 proto_tree_add_uint(msg_tree
, hf_msg_sigchar
, tvb
, 1, 1, sig_char
);
839 /* ================================================================= */
841 /* ================================================================= */
843 dissect_ipxrip(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
845 proto_tree
*rip_tree
;
846 proto_item
*ti
, *hidden_item
;
850 int available_length
;
852 static const char *rip_type
[3] = { "Request", "Response", "Unknown" };
854 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "IPX RIP");
855 col_clear(pinfo
->cinfo
, COL_INFO
);
857 operation
= tvb_get_ntohs(tvb
, 0) - 1;
859 /* rip_types 0 and 1 are valid, anything else becomes 2 or "Unknown" */
860 col_set_str(pinfo
->cinfo
, COL_INFO
, rip_type
[MIN(operation
, 2)]);
863 ti
= proto_tree_add_item(tree
, proto_ipxrip
, tvb
, 0, -1, ENC_NA
);
864 rip_tree
= proto_item_add_subtree(ti
, ett_ipxrip
);
867 proto_tree_add_text(rip_tree
, tvb
, 0, 2,
868 "RIP packet type: %s", rip_type
[operation
]);
870 if (operation
== 0) {
871 hidden_item
= proto_tree_add_boolean(rip_tree
,
875 hidden_item
= proto_tree_add_boolean(rip_tree
,
879 PROTO_ITEM_SET_HIDDEN(hidden_item
);
883 proto_tree_add_text(rip_tree
, tvb
, 0, 2, "Unknown RIP packet type");
886 available_length
= tvb_reported_length(tvb
);
887 for (cursor
= 2; cursor
< available_length
; cursor
+= 8) {
888 tvb_memcpy(tvb
, (guint8
*)&route
.network
, cursor
, 4);
889 route
.hops
= tvb_get_ntohs(tvb
, cursor
+4);
890 route
.ticks
= tvb_get_ntohs(tvb
, cursor
+6);
892 if (operation
== IPX_RIP_REQUEST
- 1) {
893 proto_tree_add_text(rip_tree
, tvb
, cursor
, 8,
894 "Route Vector: %s, %d hop%s, %d tick%s",
895 ipxnet_to_string((guint8
*)&route
.network
),
896 route
.hops
, route
.hops
== 1 ? "" : "s",
897 route
.ticks
, route
.ticks
== 1 ? "" : "s");
900 proto_tree_add_text(rip_tree
, tvb
, cursor
, 8,
901 "Route Vector: %s, %d hop%s, %d tick%s (%d ms)",
902 ipxnet_to_string((guint8
*)&route
.network
),
903 route
.hops
, route
.hops
== 1 ? "" : "s",
904 route
.ticks
, route
.ticks
== 1 ? "" : "s",
905 route
.ticks
* 1000 / 18);
911 /* ================================================================= */
912 /* IPX Serialization */
913 /* ================================================================= */
915 dissect_serialization(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
917 proto_tree
*ser_tree
= NULL
;
920 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "NW_SERIAL");
921 col_clear(pinfo
->cinfo
, COL_INFO
);
924 ti
= proto_tree_add_item(tree
, proto_serialization
, tvb
, 0, -1,
926 ser_tree
= proto_item_add_subtree(ti
, ett_serialization
);
929 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "Serial number %s",
930 tvb_bytes_to_str(tvb
, 0, 6));
932 proto_tree_add_text(ser_tree
, tvb
, 0, 6,
933 "Serial number: %s", tvb_bytes_to_str(tvb
, 0, 6));
937 * Some of these are from ncpfs, others are from the book,
938 * others are from the page at
940 * http://www.iana.org/assignments/novell-sap-numbers
942 * and some from the page at
944 * http://www.rware.demon.co.uk/ipxsap.htm
946 * (see also the page at
948 * http://developer.novell.com/research/appnotes/1998/february/03/06.htm
950 * which has a huge list - but many of the entries list only the
951 * organization owning the SAP type, not what the type is for).
953 static const value_string novell_server_vals
[] = {
954 { 0x0000, "Unknown" },
956 { 0x0002, "User Group" },
957 { 0x0003, "Print Queue or Print Group" },
958 { 0x0004, "File Server (SLIST source)" },
959 { 0x0005, "Job Server" },
960 { 0x0006, "Gateway" },
961 { 0x0007, "Print Server or Silent Print Server" },
962 { 0x0008, "Archive Queue" },
963 { 0x0009, "Archive Server" },
964 { 0x000a, "Job Queue" },
965 { 0x000b, "Administration" },
966 { 0x000F, "Novell TI-RPC" },
967 { 0x0017, "Diagnostics" },
968 { 0x0020, "NetBIOS" },
969 { 0x0021, "NAS SNA Gateway" },
970 { 0x0023, "NACS Async Gateway or Asynchronous Gateway" },
971 { 0x0024, "Remote Bridge or Routing Service" },
972 { 0x0026, "Bridge Server or Asynchronous Bridge Server" },
973 { 0x0027, "TCP/IP Gateway Server" },
974 { 0x0028, "Point to Point (Eicon) X.25 Bridge Server" },
975 { 0x0029, "Eicon 3270 Gateway" },
976 { 0x002a, "CHI Corp" },
977 { 0x002c, "PC Chalkboard" },
978 { 0x002d, "Time Synchronization Server or Asynchronous Timer" },
979 { 0x002e, "ARCserve 5.0 / Palindrome Backup Director 4.x (PDB4)" },
980 { 0x0045, "DI3270 Gateway" },
981 { 0x0047, "Advertising Print Server" },
982 { 0x004a, "NetBlazer Modems" },
983 { 0x004b, "Btrieve VAP/NLM 5.0" },
984 { 0x004c, "NetWare SQL VAP/NLM Server" },
985 { 0x004d, "Xtree Network Version/NetWare XTree" },
986 { 0x0050, "Btrieve VAP 4.11" },
987 { 0x0052, "QuickLink (Cubix)" },
988 { 0x0053, "Print Queue User" },
989 { 0x0058, "Multipoint X.25 Eicon Router" },
990 { 0x0060, "STLB/NLM" },
991 { 0x0064, "ARCserve" },
992 { 0x0066, "ARCserve 3.0" },
993 { 0x0072, "WAN Copy Utility" },
994 { 0x007a, "TES-NetWare for VMS" },
995 { 0x0092, "WATCOM Debugger or Emerald Tape Backup Server" },
996 { 0x0095, "DDA OBGYN" },
997 { 0x0098, "NetWare Access Server (Asynchronous gateway)" },
998 { 0x009a, "NetWare for VMS II or Named Pipe Server" },
999 { 0x009b, "NetWare Access Server" },
1000 { 0x009e, "Portable NetWare Server or SunLink NVT" },
1001 { 0x00a1, "Powerchute APC UPS NLM" },
1002 { 0x00aa, "LAWserve" },
1003 { 0x00ac, "Compaq IDA Status Monitor" },
1004 { 0x0100, "PIPE STAIL" },
1005 { 0x0102, "LAN Protect Bindery" },
1006 { 0x0103, "Oracle DataBase Server" },
1007 { 0x0107, "NetWare 386 or RSPX Remote Console" },
1008 { 0x010f, "Novell SNA Gateway" },
1009 { 0x0111, "Test Server" },
1010 { 0x0112, "Print Server (HP)" },
1011 { 0x0114, "CSA MUX (f/Communications Executive)" },
1012 { 0x0115, "CSA LCA (f/Communications Executive)" },
1013 { 0x0116, "CSA CM (f/Communications Executive)" },
1014 { 0x0117, "CSA SMA (f/Communications Executive)" },
1015 { 0x0118, "CSA DBA (f/Communications Executive)" },
1016 { 0x0119, "CSA NMA (f/Communications Executive)" },
1017 { 0x011a, "CSA SSA (f/Communications Executive)" },
1018 { 0x011b, "CSA STATUS (f/Communications Executive)" },
1019 { 0x011e, "CSA APPC (f/Communications Executive)" },
1020 { 0x0126, "SNA TEST SSA Profile" },
1021 { 0x012a, "CSA TRACE (f/Communications Executive)" },
1022 { 0x012b, "NetWare for SAA" },
1023 { 0x012e, "IKARUS virus scan utility" },
1024 { 0x0130, "Communications Executive" },
1025 { 0x0133, "NNS Domain Server or NetWare Naming Services Domain" },
1026 { 0x0135, "NetWare Naming Services Profile" },
1027 { 0x0137, "NetWare 386 Print Queue or NNS Print Queue" },
1028 { 0x0141, "LAN Spool Server (Vap, Intel)" },
1029 { 0x0152, "IRMALAN Gateway" },
1030 { 0x0154, "Named Pipe Server" },
1031 { 0x0166, "NetWare Management" },
1032 { 0x0168, "Intel PICKIT Comm Server or Intel CAS Talk Server" },
1033 { 0x0173, "Compaq" },
1034 { 0x0174, "Compaq SNMP Agent" },
1035 { 0x0175, "Compaq" },
1036 { 0x0180, "XTree Server or XTree Tools" },
1037 { 0x018A, "NASI services broadcast server (Novell)" },
1038 { 0x01b0, "GARP Gateway (net research)" },
1039 { 0x01b1, "Binfview (Lan Support Group)" },
1040 { 0x01bf, "Intel LanDesk Manager" },
1041 { 0x01ca, "AXTEC" },
1042 { 0x01cb, "Shiva NetModem/E" },
1043 { 0x01cc, "Shiva LanRover/E" },
1044 { 0x01cd, "Shiva LanRover/T" },
1045 { 0x01ce, "Shiva Universal" },
1046 { 0x01d8, "Castelle FAXPress Server" },
1047 { 0x01da, "Castelle LANPress Print Server" },
1048 { 0x01dc, "Castelle FAX/Xerox 7033 Fax Server/Excel Lan Fax" },
1049 { 0x01f0, "LEGATO" },
1050 { 0x01f5, "LEGATO" },
1051 { 0x0233, "NMS Agent or NetWare Management Agent" },
1052 { 0x0237, "NMS IPX Discovery or LANtern Read/Write Channel" },
1053 { 0x0238, "NMS IP Discovery or LANtern Trap/Alarm Channel" },
1054 { 0x023a, "LANtern" },
1055 { 0x023c, "MAVERICK" },
1056 { 0x023f, "SMS Testing and Development" },
1057 { 0x024e, "NetWare Connect" },
1058 { 0x024f, "NASI server broadcast (Cisco)" },
1059 { 0x026a, "Network Management (NMS) Service Console" },
1060 { 0x026b, "Time Synchronization Server (NetWare 4.x)" },
1061 { 0x0278, "Directory Server (NetWare 4.x)" },
1062 { 0x027b, "NetWare Management Agent" },
1063 { 0x0280, "Novell File and Printer Sharing Service for PC" },
1064 { 0x0304, "Novell SAA Gateway" },
1065 { 0x0308, "COM or VERMED 1" },
1066 { 0x030a, "Galacticomm's Worldgroup Server" },
1067 { 0x030c, "Intel Netport 2 or HP JetDirect or HP Quicksilver" },
1068 { 0x0320, "Attachmate Gateway" },
1069 { 0x0327, "Microsoft Diagnostics" },
1070 { 0x0328, "WATCOM SQL server" },
1071 { 0x0335, "MultiTech Systems Multisynch Comm Server" },
1072 { 0x0343, "Xylogics Remote Access Server or LAN Modem" },
1073 { 0x0355, "Arcada Backup Exec" },
1074 { 0x0358, "MSLCD1" },
1075 { 0x0361, "NETINELO" },
1076 { 0x037e, "Powerchute UPS Monitoring" },
1077 { 0x037f, "ViruSafe Notify" },
1078 { 0x0386, "HP Bridge" },
1079 { 0x0387, "HP Hub" },
1080 { 0x0394, "NetWare SAA Gateway" },
1081 { 0x039b, "Lotus Notes" },
1082 { 0x03b7, "Certus Anti Virus NLM" },
1083 { 0x03c4, "ARCserve 4.0 (Cheyenne)" },
1084 { 0x03c7, "LANspool 3.5 (Intel)" },
1085 { 0x03d7, "Lexmark printer server (type 4033-011)" },
1086 { 0x03d8, "Lexmark XLE printer server (type 4033-301)" },
1087 { 0x03dd, "Banyan ENS for NetWare Client NLM" },
1088 { 0x03de, "Gupta Sequel Base Server or NetWare SQL" },
1089 { 0x03e1, "Univel Unixware" },
1090 { 0x03e4, "Univel Unixware" },
1091 { 0x03fc, "Intel Netport" },
1092 { 0x03fd, "Intel Print Server Queue" },
1093 { 0x040A, "ipnServer" },
1094 { 0x040D, "LVERRMAN" },
1095 { 0x040E, "LVLIC" },
1096 { 0x0414, "NET Silicon (DPI)/Kyocera" },
1097 { 0x0429, "Site Lock Virus (Brightworks)" },
1098 { 0x0432, "UFHELP R" },
1099 { 0x0433, "Synoptics 281x Advanced SNMP Agent" },
1100 { 0x0444, "Microsoft NT SNA Server" },
1101 { 0x0448, "Oracle" },
1102 { 0x044c, "ARCserve 5.01" },
1103 { 0x0457, "Canon GP55 Running on a Canon GP55 network printer" },
1104 { 0x045a, "QMS Printers" },
1105 { 0x045b, "Dell SCSI Array (DSA) Monitor" },
1106 { 0x0491, "NetBlazer Modems" },
1107 { 0x04ac, "On-Time Scheduler NLM" },
1108 { 0x04b0, "CD-Net (Meridian)" },
1109 { 0x0513, "Emulex NQA" },
1110 { 0x0520, "Site Lock Checks" },
1111 { 0x0529, "Site Lock Checks (Brightworks)" },
1112 { 0x052d, "Citrix OS/2 App Server" },
1113 { 0x0535, "Tektronix" },
1114 { 0x0536, "Milan" },
1115 { 0x055d, "Attachmate SNA gateway" },
1116 { 0x056b, "IBM 8235 modem server" },
1117 { 0x056c, "Shiva LanRover/E PLUS" },
1118 { 0x056d, "Shiva LanRover/T PLUS" },
1119 { 0x0580, "McAfee's NetShield anti-virus" },
1120 { 0x05B8, "NLM to workstation communication (Revelation Software)" },
1121 { 0x05BA, "Compatible Systems Routers" },
1122 { 0x05BE, "Cheyenne Hierarchical Storage Manager" },
1123 { 0x0606, "JCWatermark Imaging" },
1124 { 0x060c, "AXIS Network Printer" },
1125 { 0x0610, "Adaptec SCSI Management" },
1126 { 0x0621, "IBM AntiVirus NLM" },
1127 { 0x0640, "Microsoft Gateway Services for NetWare" },
1128 /* { 0x0640, "NT Server-RPC/GW for NW/Win95 User Level Sec" }, */
1129 { 0x064e, "Microsoft Internet Information Server" },
1130 { 0x067b, "Microsoft Win95/98 File and Print Sharing for NetWare" },
1131 { 0x067c, "Microsoft Win95/98 File and Print Sharing for NetWare" },
1132 { 0x076C, "Xerox" },
1133 { 0x079b, "Shiva LanRover/E 115" },
1134 { 0x079c, "Shiva LanRover/T 115" },
1135 { 0x07B4, "Cubix WorldDesk" },
1136 { 0x07c1, "Quarterdeck IWare Connect V3.x NLM" },
1137 { 0x07c2, "Quarterdeck IWare Connect V2.x NLM" },
1138 { 0x0810, "ELAN License Server Demo" },
1139 { 0x0824, "Shiva LanRover Access Switch/E" },
1140 { 0x086a, "ISSC collector NLMs" },
1141 { 0x087f, "ISSC DAS agent for AIX" },
1142 { 0x0880, "Intel Netport PRO" },
1143 { 0x0881, "Intel Netport PRO" },
1144 { 0x0b29, "Site Lock" },
1145 { 0x0c29, "Site Lock Applications" },
1146 { 0x0c2c, "Licensing Server" },
1147 { 0x2101, "Performance Technology Instant Internet" },
1148 { 0x2380, "LAI Site Lock" },
1149 { 0x238c, "Meeting Maker" },
1150 { 0x4808, "Site Lock Server or Site Lock Metering VAP/NLM" },
1151 { 0x5555, "Site Lock User" },
1152 { 0x6312, "Tapeware" },
1153 { 0x6f00, "Rabbit Gateway (3270)" },
1154 { 0x7703, "MODEM" },
1155 { 0x8002, "NetPort Printers (Intel) or LANport" },
1156 { 0x8003, "SEH InterCon Printserver" },
1157 { 0x8008, "WordPerfect Network Version" },
1158 { 0x85BE, "Cisco Enhanced Interior Routing Protocol (EIGRP)" },
1159 { 0x8888, "WordPerfect Network Version or Quick Network Management" },
1160 { 0x9000, "McAfee's NetShield anti-virus" },
1161 { 0x9604, "CSA-NT_MON" },
1162 { 0xb6a8, "Ocean Isle Reachout Remote Control" },
1163 { 0xf11f, "Site Lock Metering VAP/NLM" },
1164 { 0xf1ff, "Site Lock" },
1165 { 0xf503, "Microsoft SQL Server" },
1166 { 0xf905, "IBM Time and Place/2 application" },
1167 { 0xfbfb, "TopCall III fax server" },
1168 { 0xffff, "Any Service or Wildcard" },
1172 value_string_ext novell_server_vals_ext
= VALUE_STRING_EXT_INIT(novell_server_vals
);
1175 dissect_ipxsap(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
1177 proto_tree
*sap_tree
, *s_tree
;
1178 proto_item
*ti
, *hidden_item
;
1180 struct sap_query query
;
1181 guint16 server_type
;
1183 guint16 server_port
;
1184 guint16 intermediate_network
;
1186 static const char *sap_type
[4] = { "General Query", "General Response",
1187 "Nearest Query", "Nearest Response" };
1189 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "IPX SAP");
1190 col_clear(pinfo
->cinfo
, COL_INFO
);
1192 query
.query_type
= tvb_get_ntohs(tvb
, 0);
1193 query
.server_type
= tvb_get_ntohs(tvb
, 2);
1195 if (query
.query_type
>= 1 && query
.query_type
<= 4) {
1196 col_set_str(pinfo
->cinfo
, COL_INFO
, sap_type
[query
.query_type
- 1]);
1199 col_set_str(pinfo
->cinfo
, COL_INFO
, "Unknown Packet Type");
1203 ti
= proto_tree_add_item(tree
, proto_sap
, tvb
, 0, -1, ENC_NA
);
1204 sap_tree
= proto_item_add_subtree(ti
, ett_ipxsap
);
1206 if (query
.query_type
>= 1 && query
.query_type
<= 4) {
1207 proto_tree_add_text(sap_tree
, tvb
, 0, 2, "%s", sap_type
[query
.query_type
- 1]);
1208 if ((query
.query_type
- 1) % 2) {
1209 hidden_item
= proto_tree_add_boolean(sap_tree
,
1213 hidden_item
= proto_tree_add_boolean(sap_tree
,
1217 PROTO_ITEM_SET_HIDDEN(hidden_item
);
1220 proto_tree_add_text(sap_tree
, tvb
, 0, 2,
1221 "Unknown SAP Packet Type %d", query
.query_type
);
1224 if (query
.query_type
== IPX_SAP_GENERAL_RESPONSE
||
1225 query
.query_type
== IPX_SAP_NEAREST_RESPONSE
) { /* responses */
1227 int available_length
= tvb_reported_length(tvb
);
1228 for (cursor
= 2; (cursor
+ 64) <= available_length
; cursor
+= 64) {
1229 server_type
= tvb_get_ntohs(tvb
, cursor
);
1230 server_name
= tvb_format_stringzpad(tvb
, cursor
+2, 48);
1232 ti
= proto_tree_add_text(sap_tree
, tvb
, cursor
+2, 48,
1233 "Server Name: %s", server_name
);
1234 s_tree
= proto_item_add_subtree(ti
, ett_ipxsap_server
);
1236 proto_tree_add_text(s_tree
, tvb
, cursor
, 2, "Server Type: %s (0x%04X)",
1237 val_to_str_ext_const(server_type
, &novell_server_vals_ext
, "Unknown"),
1239 proto_tree_add_text(s_tree
, tvb
, cursor
+50, 4, "Network: %s",
1240 ipxnet_to_string(tvb_get_ptr(tvb
, cursor
+50, 4)));
1241 proto_tree_add_text(s_tree
, tvb
, cursor
+54, 6, "Node: %s",
1242 tvb_ether_to_str(tvb
, cursor
+54));
1243 server_port
= tvb_get_ntohs(tvb
, cursor
+60);
1244 proto_tree_add_text(s_tree
, tvb
, cursor
+60, 2, "Socket: %s (0x%04x)",
1245 socket_text(server_port
),
1247 intermediate_network
= tvb_get_ntohs(tvb
, cursor
+62);
1248 proto_tree_add_text(s_tree
, tvb
, cursor
+62, 2,
1249 "Intermediate Networks: %d",
1250 intermediate_network
);
1253 else { /* queries */
1254 proto_tree_add_text(sap_tree
, tvb
, 2, 2, "Server Type: %s (0x%04X)",
1255 val_to_str_ext_const(query
.server_type
, &novell_server_vals_ext
, "Unknown"),
1262 proto_register_ipx(void)
1264 static hf_register_info hf_ipx
[] = {
1266 { "Checksum", "ipx.checksum", FT_UINT16
, BASE_HEX
, NULL
, 0x0,
1270 { "Source Address", "ipx.src", FT_STRING
, BASE_NONE
, NULL
, 0x0,
1271 "Source IPX Address \"network.node\"", HFILL
}},
1274 { "Destination Address", "ipx.dst", FT_STRING
, BASE_NONE
, NULL
, 0x0,
1275 "Destination IPX Address \"network.node\"", HFILL
}},
1277 { "Src/Dst Address", "ipx.addr", FT_STRING
, BASE_NONE
, NULL
, 0x0,
1278 "Source or Destination IPX Address \"network.node\"", HFILL
}},
1281 { "Length", "ipx.len", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1285 { "Transport Control (Hops)", "ipx.hops", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1288 { &hf_ipx_packet_type
,
1289 { "Packet Type", "ipx.packet_type", FT_UINT8
, BASE_HEX
, VALS(ipx_packet_type_vals
),
1294 { "Destination Network","ipx.dst.net", FT_IPXNET
, BASE_NONE
, NULL
, 0x0,
1298 { "Destination Node", "ipx.dst.node", FT_ETHER
, BASE_NONE
, NULL
, 0x0,
1302 { "Destination Socket", "ipx.dst.socket", FT_UINT16
, BASE_HEX
|BASE_EXT_STRING
,
1303 &ipx_socket_vals_ext
, 0x0,
1307 { "Source Network","ipx.src.net", FT_IPXNET
, BASE_NONE
, NULL
, 0x0,
1311 { "Source Node", "ipx.src.node", FT_ETHER
, BASE_NONE
, NULL
, 0x0,
1315 { "Source Socket", "ipx.src.socket", FT_UINT16
, BASE_HEX
|BASE_EXT_STRING
,
1316 &ipx_socket_vals_ext
, 0x0,
1320 { "Source or Destination Network","ipx.net", FT_IPXNET
, BASE_NONE
, NULL
, 0x0,
1324 { "Source or Destination Node", "ipx.node", FT_ETHER
, BASE_NONE
, NULL
, 0x0,
1328 { "Source or Destination Socket", "ipx.socket", FT_UINT16
, BASE_HEX
|BASE_EXT_STRING
,
1329 &ipx_socket_vals_ext
, 0x0,
1333 static hf_register_info hf_spx
[] = {
1334 { &hf_spx_connection_control
,
1335 { "Connection Control", "spx.ctl",
1336 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1339 { &hf_spx_connection_control_sys
,
1340 { "System Packet", "spx.ctl.sys",
1341 FT_BOOLEAN
, 8, NULL
, SPX_SYS_PACKET
,
1344 { &hf_spx_connection_control_send_ack
,
1345 { "Send Ack", "spx.ctl.send_ack",
1346 FT_BOOLEAN
, 8, NULL
, SPX_SEND_ACK
,
1349 { &hf_spx_connection_control_attn
,
1350 { "Attention", "spx.ctl.attn",
1351 FT_BOOLEAN
, 8, NULL
, SPX_ATTN
,
1354 { &hf_spx_connection_control_eom
,
1355 { "End of Message", "spx.ctl.eom",
1356 FT_BOOLEAN
, 8, NULL
, SPX_EOM
,
1359 { &hf_spx_datastream_type
,
1360 { "Datastream Type", "spx.type",
1361 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1365 { "Source Connection ID", "spx.src",
1366 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1370 { "Destination Connection ID", "spx.dst",
1371 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1375 { "Sequence Number", "spx.seq",
1376 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1380 { "Acknowledgment Number", "spx.ack",
1381 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1385 { "Allocation Number", "spx.alloc",
1386 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1389 { &hf_spx_rexmt_frame
,
1390 { "Retransmitted Frame Number", "spx.rexmt_frame",
1391 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
1395 static hf_register_info hf_ipxrip
[] = {
1396 { &hf_ipxrip_request
,
1397 { "Request", "ipxrip.request",
1398 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1399 "TRUE if IPX RIP request", HFILL
}},
1401 { &hf_ipxrip_response
,
1402 { "Response", "ipxrip.response",
1403 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1404 "TRUE if IPX RIP response", HFILL
}}
1407 static hf_register_info hf_sap
[] = {
1409 { "Request", "ipxsap.request",
1410 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1411 "TRUE if SAP request", HFILL
}},
1414 { "Response", "ipxsap.response",
1415 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1416 "TRUE if SAP response", HFILL
}}
1419 static hf_register_info hf_ipxmsg
[] = {
1421 { "Connection Number", "ipxmsg.conn",
1422 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1426 { "Signature Char", "ipxmsg.sigchar",
1427 FT_UINT8
, BASE_DEC
, VALS(ipxmsg_sigchar_vals
), 0x0,
1431 static gint
*ett
[] = {
1442 proto_ipx
= proto_register_protocol("Internetwork Packet eXchange",
1444 proto_register_field_array(proto_ipx
, hf_ipx
, array_length(hf_ipx
));
1446 register_dissector("ipx", dissect_ipx
, proto_ipx
);
1448 proto_spx
= proto_register_protocol("Sequenced Packet eXchange",
1450 proto_register_field_array(proto_spx
, hf_spx
, array_length(hf_spx
));
1452 proto_ipxrip
= proto_register_protocol("IPX Routing Information Protocol",
1453 "IPX RIP", "ipxrip");
1454 proto_register_field_array(proto_ipxrip
, hf_ipxrip
, array_length(hf_ipxrip
));
1456 proto_serialization
= proto_register_protocol("NetWare Serialization Protocol",
1457 "NW_SERIAL", "nw_serial");
1459 proto_ipxmsg
= proto_register_protocol("IPX Message", "IPX MSG",
1461 proto_register_field_array(proto_ipxmsg
, hf_ipxmsg
, array_length(hf_ipxmsg
));
1463 proto_sap
= proto_register_protocol("Service Advertisement Protocol",
1464 "IPX SAP", "ipxsap");
1465 register_dissector("ipxsap", dissect_ipxsap
, proto_sap
);
1467 proto_register_field_array(proto_sap
, hf_sap
, array_length(hf_sap
));
1469 proto_register_subtree_array(ett
, array_length(ett
));
1471 ipx_type_dissector_table
= register_dissector_table("ipx.packet_type",
1472 "IPX packet type", FT_UINT8
, BASE_HEX
);
1473 ipx_socket_dissector_table
= register_dissector_table("ipx.socket",
1474 "IPX socket", FT_UINT16
, BASE_HEX
);
1475 spx_socket_dissector_table
= register_dissector_table("spx.socket",
1476 "SPX socket", FT_UINT16
, BASE_HEX
);
1478 register_init_routine(&spx_init_protocol
);
1479 register_postseq_cleanup_routine(&spx_postseq_cleanup
);
1480 ipx_tap
=register_tap("ipx");
1484 proto_reg_handoff_ipx(void)
1486 dissector_handle_t ipx_handle
, spx_handle
;
1487 dissector_handle_t ipxsap_handle
, ipxrip_handle
;
1488 dissector_handle_t serialization_handle
, ipxmsg_handle
;
1490 ipx_handle
= find_dissector("ipx");
1491 dissector_add_uint("udp.port", UDP_PORT_IPX
, ipx_handle
);
1492 dissector_add_uint("ethertype", ETHERTYPE_IPX
, ipx_handle
);
1493 dissector_add_uint("chdlc.protocol", ETHERTYPE_IPX
, ipx_handle
);
1494 dissector_add_uint("ppp.protocol", PPP_IPX
, ipx_handle
);
1495 dissector_add_uint("llc.dsap", SAP_NETWARE1
, ipx_handle
);
1496 dissector_add_uint("llc.dsap", SAP_NETWARE2
, ipx_handle
);
1497 dissector_add_uint("sll.ltype", LINUX_SLL_P_802_3
, ipx_handle
);
1498 dissector_add_uint("null.type", BSD_AF_IPX
, ipx_handle
);
1499 dissector_add_uint("gre.proto", ETHERTYPE_IPX
, ipx_handle
);
1500 dissector_add_uint("arcnet.protocol_id", ARCNET_PROTO_IPX
, ipx_handle
);
1501 dissector_add_uint("arcnet.protocol_id", ARCNET_PROTO_NOVELL_EC
, ipx_handle
);
1503 spx_handle
= create_dissector_handle(dissect_spx
, proto_spx
);
1504 dissector_add_uint("ipx.packet_type", IPX_PACKET_TYPE_SPX
, spx_handle
);
1506 ipxsap_handle
= find_dissector("ipxsap");
1507 dissector_add_uint("ipx.socket", IPX_SOCKET_SAP
, ipxsap_handle
);
1509 ipxrip_handle
= create_dissector_handle(dissect_ipxrip
, proto_ipxrip
);
1510 dissector_add_uint("ipx.socket", IPX_SOCKET_IPXRIP
, ipxrip_handle
);
1512 serialization_handle
= create_dissector_handle(dissect_serialization
,
1513 proto_serialization
);
1514 dissector_add_uint("ipx.socket", IPX_SOCKET_SERIALIZATION
,
1515 serialization_handle
);
1517 ipxmsg_handle
= create_dissector_handle(dissect_ipxmsg
, proto_ipxmsg
);
1518 dissector_add_uint("ipx.socket", IPX_SOCKET_IPX_MESSAGE
, ipxmsg_handle
);
1519 dissector_add_uint("ipx.socket", IPX_SOCKET_IPX_MESSAGE1
, ipxmsg_handle
);
1521 data_handle
= find_dissector("data");