2 * Routines for NetWare's IPX
3 * Gilbert Ramirez <gram@alumni.rice.edu>
4 * NDPS support added by Greg Morris (gmorris@novell.com)
6 * Portions Copyright (c) 2000-2002 by Gilbert Ramirez.
7 * Portions Copyright (c) Novell, Inc. 2002-2003
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * SPDX-License-Identifier: GPL-2.0-or-later
18 #include <epan/packet.h>
19 #include <epan/capture_dissectors.h>
20 #include "packet-ipx.h"
21 #include "packet-sll.h"
22 #include <epan/addr_resolv.h>
23 #include <epan/etypes.h>
24 #include <epan/ppptypes.h>
25 #include <epan/llcsaps.h>
26 #include <epan/aftypes.h>
27 #include <epan/arcnet_pids.h>
28 #include <epan/conversation.h>
29 #include <epan/conversation_table.h>
30 #include <epan/proto_data.h>
31 #include <epan/unit_strings.h>
33 void proto_register_ipx(void);
34 void proto_reg_handoff_ipx(void);
38 /* The information in this module (IPX, SPX, NCP) comes from:
39 NetWare LAN Analysis, Second Edition
40 Laura A. Chappell and Dan E. Hakes
42 Novell Press, San Jose.
45 And from the ncpfs source code by Volker Lendecke
50 static int hf_ipx_checksum
;
51 static int hf_ipx_len
;
52 static int hf_ipx_src
;
53 static int hf_ipx_dst
;
54 static int hf_ipx_addr
;
55 static int hf_ipx_hops
;
56 static int hf_ipx_packet_type
;
57 static int hf_ipx_dnet
;
58 static int hf_ipx_dnode
;
59 static int hf_ipx_dsocket
;
60 static int hf_ipx_snet
;
61 static int hf_ipx_snode
;
62 static int hf_ipx_ssocket
;
63 static int hf_ipx_net
;
64 static int hf_ipx_node
;
65 static int hf_ipx_socket
;
69 static dissector_table_t ipx_type_dissector_table
;
70 static dissector_table_t ipx_socket_dissector_table
;
71 static dissector_table_t spx_socket_dissector_table
;
72 static dissector_handle_t ipx_handle
;
73 static dissector_handle_t ipxsap_handle
;
74 static dissector_handle_t spx_handle
;
75 static dissector_handle_t ipxrip_handle
;
76 static dissector_handle_t serialization_handle
;
77 static dissector_handle_t ipxmsg_handle
;
80 static int hf_spx_connection_control
;
81 static int hf_spx_connection_control_sys
;
82 static int hf_spx_connection_control_send_ack
;
83 static int hf_spx_connection_control_attn
;
84 static int hf_spx_connection_control_eom
;
85 static int hf_spx_connection_control_v2
;
86 static int hf_spx_connection_control_neg_size
;
87 static int hf_spx_connection_control_reserved
;
88 static int hf_spx_connection_control_ext_header
;
89 static int hf_spx_datastream_type
;
90 static int hf_spx_src_id
;
91 static int hf_spx_dst_id
;
92 static int hf_spx_seq_nr
;
93 static int hf_spx_ack_nr
;
94 static int hf_spx_all_nr
;
95 static int hf_spx_neg_size
;
96 static int hf_spx_rexmt_frame
;
97 static int hf_spx_rexmt_data
;
100 static int ett_spx_connctrl
;
102 static int proto_ipxrip
;
103 static int hf_ipxrip_request
;
104 static int hf_ipxrip_response
;
105 static int hf_ipxrip_packet_type
;
106 static int hf_ipxrip_route_vector
;
107 static int hf_ipxrip_hops
;
108 static int hf_ipxrip_ticks
;
110 static int ett_ipxrip
;
112 static int proto_serialization
;
113 static int hf_serial_number
;
114 static int ett_serialization
;
116 static int proto_sap
;
117 static int hf_sap_request
;
118 static int hf_sap_response
;
119 static int hf_sap_packet_type
;
120 static int hf_sap_server
;
121 static int hf_sap_server_type
;
122 static int hf_sap_server_name
;
123 static int hf_sap_server_network
;
124 static int hf_sap_server_node
;
125 static int hf_sap_server_socket
;
126 static int hf_sap_server_intermediate_networks
;
128 static int ett_ipxsap
;
129 static int ett_ipxsap_server
;
131 static int ett_ipxmsg
;
132 static int proto_ipxmsg
;
133 static int hf_msg_conn
;
134 static int hf_msg_sigchar
;
136 #define UDP_PORT_IPX 213 /* RFC 1234 */
138 #define IPX_HEADER_LEN 30 /* It's *always* 30 bytes */
140 static const char* ipx_conv_get_filter_type(conv_item_t
* conv
, conv_filter_type_e filter
)
142 if ((filter
== CONV_FT_SRC_ADDRESS
) && (conv
->src_address
.type
== AT_IPX
))
145 if ((filter
== CONV_FT_DST_ADDRESS
) && (conv
->dst_address
.type
== AT_IPX
))
148 if ((filter
== CONV_FT_ANY_ADDRESS
) && (conv
->src_address
.type
== AT_IPX
))
151 return CONV_FILTER_INVALID
;
154 static ct_dissector_info_t ipx_ct_dissector_info
= {&ipx_conv_get_filter_type
};
156 static tap_packet_status
157 ipx_conversation_packet(void *pct
, packet_info
*pinfo
, epan_dissect_t
*edt _U_
, const void *vip
, tap_flags_t flags
)
159 conv_hash_t
*hash
= (conv_hash_t
*) pct
;
162 const ipxhdr_t
*ipxh
=(const ipxhdr_t
*)vip
;
164 add_conversation_table_data(hash
, &ipxh
->ipx_src
, &ipxh
->ipx_dst
, 0, 0, 1, pinfo
->fd
->pkt_len
, &pinfo
->rel_ts
, &pinfo
->abs_ts
, &ipx_ct_dissector_info
, CONVERSATION_NONE
);
166 return TAP_PACKET_REDRAW
;
169 static const char* ipx_endpoint_get_filter_type(endpoint_item_t
* endpoint
, conv_filter_type_e filter
)
171 if ((filter
== CONV_FT_ANY_ADDRESS
) && (endpoint
->myaddress
.type
== AT_IPX
))
174 return CONV_FILTER_INVALID
;
177 static et_dissector_info_t ipx_endpoint_dissector_info
= {&ipx_endpoint_get_filter_type
};
179 static tap_packet_status
180 ipx_endpoint_packet(void *pit
, packet_info
*pinfo
, epan_dissect_t
*edt _U_
, const void *vip
, tap_flags_t flags
)
182 conv_hash_t
*hash
= (conv_hash_t
*) pit
;
185 const ipxhdr_t
*ipxh
=(const ipxhdr_t
*)vip
;
187 /* Take two "add" passes per packet, adding for each direction, ensures that all
188 packets are counted properly (even if address is sending to itself)
189 XXX - this could probably be done more efficiently inside endpoint_table */
190 add_endpoint_table_data(hash
, &ipxh
->ipx_src
, 0, true, 1, pinfo
->fd
->pkt_len
, &ipx_endpoint_dissector_info
, ENDPOINT_NONE
);
191 add_endpoint_table_data(hash
, &ipxh
->ipx_dst
, 0, false, 1, pinfo
->fd
->pkt_len
, &ipx_endpoint_dissector_info
, ENDPOINT_NONE
);
193 return TAP_PACKET_REDRAW
;
196 /* ================================================================= */
198 /* ================================================================= */
199 static const value_string ipx_socket_vals
[] = {
200 { IPX_SOCKET_PING_CISCO
, "CISCO PING" },
201 { IPX_SOCKET_NCP
, "NCP" },
202 { IPX_SOCKET_SAP
, "SAP" },
203 { IPX_SOCKET_IPXRIP
, "RIP" },
204 { IPX_SOCKET_NETBIOS
, "NetBIOS" },
205 { IPX_SOCKET_DIAGNOSTIC
, "Diagnostic" },
206 { IPX_SOCKET_SERIALIZATION
, "Serialization" },
207 { IPX_SOCKET_NWLINK_SMB_SERVER
, "NWLink SMB Server" },
208 { IPX_SOCKET_NWLINK_SMB_NAMEQUERY
, "NWLink SMB Name Query" },
209 { IPX_SOCKET_NWLINK_SMB_REDIR
, "NWLink SMB Redirector" },
210 { IPX_SOCKET_NWLINK_SMB_MAILSLOT
, "NWLink SMB Mailslot Datagram" },
211 { IPX_SOCKET_NWLINK_SMB_MESSENGER
, "NWLink SMB Messenger" },
212 { IPX_SOCKET_NWLINK_SMB_BROWSE
, "NWLink SMB Browse" },
213 { IPX_SOCKET_ATTACHMATE_GW
, "Attachmate Gateway" },
214 { IPX_SOCKET_IPX_MESSAGE
, "IPX Message" },
215 { IPX_SOCKET_IPX_MESSAGE1
, "IPX Message" },
216 { 0x4006, "NetWare Directory Server" },
217 { 0x400C, "HP LaserJet/QuickSilver" },
218 { 0x8104, "NetWare 386" },
219 { IPX_SOCKET_ADSM
, "ADSM" },
220 { IPX_SOCKET_EIGRP
, "Cisco EIGRP for IPX" },
221 { 0x8F83, "Powerchute UPS Monitoring" },
222 { IPX_SOCKET_NLSP
, "NetWare Link Services Protocol" },
223 { IPX_SOCKET_IPXWAN
, "IPX WAN" },
224 { IPX_SOCKET_SNMP_AGENT
, "SNMP Agent" },
225 { IPX_SOCKET_SNMP_SINK
, "SNMP Sink" },
226 { 0x907B, "SMS Testing and Development" },
227 { IPX_SOCKET_PING_NOVELL
, "Novell PING" },
228 { IPX_SOCKET_TCP_TUNNEL
, "TCP Tunnel" },
229 { IPX_SOCKET_UDP_TUNNEL
, "UDP Tunnel" },
230 { SPX_SOCKET_PA
, "NDPS Printer Agent/PSM" },
231 { SPX_SOCKET_BROKER
, "NDPS Broker" },
232 { SPX_SOCKET_SRS
, "NDPS Service Registry Service" },
233 { SPX_SOCKET_ENS
, "NDPS Event Notification Service" },
234 { SPX_SOCKET_RMS
, "NDPS Remote Management Service" },
235 { SPX_SOCKET_NOTIFY_LISTENER
, "NDPS Notify Listener" },
236 { 0xE885, "NT Server-RPC/GW" },
240 value_string_ext ipx_socket_vals_ext
= VALUE_STRING_EXT_INIT(ipx_socket_vals
);
242 static const value_string ipx_packet_type_vals
[] = {
243 { IPX_PACKET_TYPE_IPX
, "IPX" },
244 { IPX_PACKET_TYPE_RIP
, "RIP" },
245 { IPX_PACKET_TYPE_ECHO
, "Echo" },
246 { IPX_PACKET_TYPE_ERROR
, "Error" },
247 { IPX_PACKET_TYPE_PEP
, "PEP" }, /* Packet Exchange Packet */
248 { IPX_PACKET_TYPE_SPX
, "SPX" },
249 { 16, "Experimental Protocol" },
250 { IPX_PACKET_TYPE_NCP
, "NCP" },
251 { 18, "Experimental Protocol" },
252 { 19, "Experimental Protocol" },
253 { IPX_PACKET_TYPE_WANBCAST
, "NetBIOS Broadcast" },
254 { 21, "Experimental Protocol" },
255 { 22, "Experimental Protocol" },
256 { 23, "Experimental Protocol" },
257 { 24, "Experimental Protocol" },
258 { 25, "Experimental Protocol" },
259 { 26, "Experimental Protocol" },
260 { 27, "Experimental Protocol" },
261 { 28, "Experimental Protocol" },
262 { 29, "Experimental Protocol" },
263 { 30, "Experimental Protocol" },
264 { 31, "Experimental Protocol" },
268 static const value_string ipxmsg_sigchar_vals
[] = {
269 { '?', "Poll inactive station" },
270 { 'Y', "Station is still using the connection" },
271 { '!', "Broadcast message waiting" },
276 capture_ipx(const unsigned char *pd _U_
, int offset _U_
, int len _U_
, capture_packet_info_t
*cpinfo
, const union wtap_pseudo_header
*pseudo_header _U_
)
278 capture_dissector_increment_count(cpinfo
, proto_ipx
);
283 dissect_ipx(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
287 proto_tree
*ipx_tree
= NULL
;
288 proto_item
*ti
= NULL
, *hidden_item
;
292 uint16_t first_socket
, second_socket
;
293 uint32_t ipx_snet
, ipx_dnet
;
294 static ipxhdr_t ipxh_arr
[4];
295 static int ipx_current
=0;
302 ipxh
=&ipxh_arr
[ipx_current
];
305 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "IPX");
306 col_clear(pinfo
->cinfo
, COL_INFO
);
308 /* Calculate here for use in pinfo and in tree */
309 ipxh
->ipx_dsocket
= tvb_get_ntohs(tvb
, 16);
310 ipxh
->ipx_ssocket
= tvb_get_ntohs(tvb
, 28);
311 ipxh
->ipx_type
= tvb_get_uint8(tvb
, 5);
312 ipxh
->ipx_length
= tvb_get_ntohs(tvb
, 2);
314 pinfo
->ptype
= PT_IPX
;
315 pinfo
->srcport
= ipxh
->ipx_ssocket
;
316 pinfo
->destport
= ipxh
->ipx_dsocket
;
318 /* Adjust the tvbuff length to include only the IPX datagram. */
319 set_actual_length(tvb
, ipxh
->ipx_length
);
321 set_address_tvb(&pinfo
->net_src
, AT_IPX
, 10, tvb
, 18);
322 copy_address_shallow(&pinfo
->src
, &pinfo
->net_src
);
323 copy_address_shallow(&ipxh
->ipx_src
, &pinfo
->net_src
);
324 set_address_tvb(&pinfo
->net_dst
, AT_IPX
, 10, tvb
, 6);
325 copy_address_shallow(&pinfo
->dst
, &pinfo
->net_dst
);
326 copy_address_shallow(&ipxh
->ipx_dst
, &pinfo
->net_dst
);
328 col_add_str(pinfo
->cinfo
, COL_INFO
, val_to_str_ext(ipxh
->ipx_dsocket
, &ipx_socket_vals_ext
, "Unknown (0x%04x)"));
332 ti
= proto_tree_add_item(tree
, proto_ipx
, tvb
, 0, IPX_HEADER_LEN
, ENC_NA
);
333 ipx_tree
= proto_item_add_subtree(ti
, ett_ipx
);
336 str
=address_to_str(pinfo
->pool
, &pinfo
->net_src
);
337 hidden_item
= proto_tree_add_string(ipx_tree
, hf_ipx_src
, tvb
, 0, 0, str
);
338 proto_item_set_hidden(hidden_item
);
339 hidden_item
= proto_tree_add_string(ipx_tree
, hf_ipx_addr
, tvb
, 0, 0, str
);
340 proto_item_set_hidden(hidden_item
);
341 str
=address_to_str(pinfo
->pool
, &pinfo
->net_dst
);
342 hidden_item
= proto_tree_add_string(ipx_tree
, hf_ipx_dst
, tvb
, 0, 0, str
);
343 proto_item_set_hidden(hidden_item
);
344 hidden_item
= proto_tree_add_string(ipx_tree
, hf_ipx_addr
, tvb
, 0, 0, str
);
345 proto_item_set_hidden(hidden_item
);
347 proto_tree_add_checksum(ipx_tree
, tvb
, 0, hf_ipx_checksum
, -1, NULL
, pinfo
, 0, ENC_BIG_ENDIAN
, PROTO_CHECKSUM_NO_FLAGS
);
348 proto_tree_add_uint(ipx_tree
, hf_ipx_len
, tvb
, 2, 2, ipxh
->ipx_length
);
349 ipx_hops
= tvb_get_uint8(tvb
, 4);
350 proto_tree_add_uint_format(ipx_tree
, hf_ipx_hops
, tvb
, 4, 1, ipx_hops
,
351 "Transport Control: %d hops", ipx_hops
);
352 proto_tree_add_uint(ipx_tree
, hf_ipx_packet_type
, tvb
, 5, 1, ipxh
->ipx_type
);
355 ipx_dnet
= tvb_get_ntohl(tvb
, 6);
356 proto_tree_add_ipxnet(ipx_tree
, hf_ipx_dnet
, tvb
, 6, 4,
358 hidden_item
= proto_tree_add_ipxnet(ipx_tree
, hf_ipx_net
, tvb
, 6, 4,
360 proto_item_set_hidden(hidden_item
);
361 proto_tree_add_item(ipx_tree
, hf_ipx_dnode
, tvb
, 10, 6, ENC_NA
);
362 hidden_item
= proto_tree_add_item(ipx_tree
, hf_ipx_node
, tvb
, 10, 6, ENC_NA
);
363 proto_item_set_hidden(hidden_item
);
364 proto_tree_add_uint(ipx_tree
, hf_ipx_dsocket
, tvb
, 16, 2,
366 hidden_item
= proto_tree_add_uint(ipx_tree
, hf_ipx_socket
, tvb
, 16, 2,
368 proto_item_set_hidden(hidden_item
);
371 ipx_snet
= tvb_get_ntohl(tvb
, 18);
372 proto_tree_add_ipxnet(ipx_tree
, hf_ipx_snet
, tvb
, 18, 4,
374 hidden_item
= proto_tree_add_ipxnet(ipx_tree
, hf_ipx_net
, tvb
, 18, 4,
376 proto_item_set_hidden(hidden_item
);
377 proto_tree_add_item(ipx_tree
, hf_ipx_snode
, tvb
, 22, 6, ENC_NA
);
378 hidden_item
= proto_tree_add_item(ipx_tree
, hf_ipx_node
, tvb
, 22, 6, ENC_NA
);
379 proto_item_set_hidden(hidden_item
);
380 proto_tree_add_uint(ipx_tree
, hf_ipx_ssocket
, tvb
, 28, 2,
382 hidden_item
= proto_tree_add_uint(ipx_tree
, hf_ipx_socket
, tvb
, 28, 2,
384 proto_item_set_hidden(hidden_item
);
386 /* Make the next tvbuff */
387 next_tvb
= tvb_new_subset_remaining(tvb
, IPX_HEADER_LEN
);
390 * Check the socket numbers before we check the packet type;
391 * we've seen non-NCP packets with a type of NCP and a
392 * destination socket of IPX_SOCKET_IPX_MESSAGE, and SAP
393 * packets with a type of NCP and a destination socket of
396 * We've seen NCP packets with a type of NCP, a source socket of
397 * IPX_SOCKET_NCP, and a destination socket of IPX_SOCKET_IPX_MESSAGE,
398 * and we've seen NCP packets with a type of NCP, a source socket of
399 * IPX_SOCKET_IPX_MESSAGE, and a destination socket of
400 * IPX_SOCKET_NCP, so testing the destination socket first doesn't
401 * always give the right answer. We've also seen SAP packets with
402 * a source socket of IPX_SOCKET_SAP and a destination socket of
403 * IPX_SOCKET_IPX_MESSAGE.
405 * Unfortunately, we've also seen packets with a source socket
406 * of IPX_SOCKET_NWLINK_SMB_SERVER and a destination socket
407 * of IPX_SOCKET_NWLINK_SMB_NAMEQUERY that were NMPI packets,
408 * not SMB packets, so testing the lower-valued socket first
409 * also doesn't always give the right answer.
411 * So we start out assuming we should test the lower-numbered
412 * socket number first, but, if the higher-numbered socket is
413 * IPX_SOCKET_NWLINK_SMB_NAMEQUERY, we assume that it's a
414 * NMPI query, and test only that socket.
416 if (ipxh
->ipx_ssocket
> ipxh
->ipx_dsocket
) {
417 first_socket
= ipxh
->ipx_dsocket
;
418 second_socket
= ipxh
->ipx_ssocket
;
420 first_socket
= ipxh
->ipx_ssocket
;
421 second_socket
= ipxh
->ipx_dsocket
;
424 tap_queue_packet(ipx_tap
, pinfo
, ipxh
);
426 if (second_socket
!= IPX_SOCKET_NWLINK_SMB_NAMEQUERY
) {
427 if (dissector_try_uint_with_data(ipx_socket_dissector_table
, first_socket
,
428 next_tvb
, pinfo
, tree
, false, ipxh
))
429 return tvb_captured_length(tvb
);
431 if (dissector_try_uint_with_data(ipx_socket_dissector_table
, second_socket
,
432 next_tvb
, pinfo
, tree
, false, ipxh
))
433 return tvb_captured_length(tvb
);
436 * Neither of them are known; try the packet type, which will
437 * at least let us, for example, dissect SPX packets as SPX.
439 if (dissector_try_uint_with_data(ipx_type_dissector_table
, ipxh
->ipx_type
, next_tvb
,
440 pinfo
, tree
, false, ipxh
))
441 return tvb_captured_length(tvb
);
443 call_data_dissector(next_tvb
, pinfo
, tree
);
444 return tvb_captured_length(tvb
);
446 /* ================================================================= */
447 /* SPX Hash Functions */
448 /* ================================================================= */
451 conversation_t
*conversation
;
463 * Structure attached to retransmitted SPX frames; it contains the
464 * frame number of the original transmission.
470 static wmem_map_t
*spx_hash
;
474 spx_equal(const void *v
, const void *v2
)
476 const spx_hash_key
*val1
= (const spx_hash_key
*)v
;
477 const spx_hash_key
*val2
= (const spx_hash_key
*)v2
;
479 if (val1
->conversation
== val2
->conversation
&&
480 val1
->spx_src
== val2
->spx_src
&&
481 val1
->spx_seq
== val2
->spx_seq
) {
488 spx_hash_func(const void *v
)
490 const spx_hash_key
*spx_key
= (const spx_hash_key
*)v
;
491 return GPOINTER_TO_UINT(spx_key
->conversation
) + spx_key
->spx_src
;
494 static spx_hash_value
*
495 spx_hash_insert(conversation_t
*conversation
, uint32_t spx_src
, uint16_t spx_seq
)
498 spx_hash_value
*value
;
500 /* Now remember the packet, so we can find it if we later. */
501 key
= wmem_new(wmem_file_scope(), spx_hash_key
);
502 key
->conversation
= conversation
;
503 key
->spx_src
= spx_src
;
504 key
->spx_seq
= spx_seq
;
506 value
= wmem_new0(wmem_file_scope(), spx_hash_value
);
508 wmem_map_insert(spx_hash
, key
, value
);
513 /* Returns the spx_hash_value*, or NULL if not found. */
514 static spx_hash_value
*
515 spx_hash_lookup(conversation_t
*conversation
, uint32_t spx_src
, uint32_t spx_seq
)
519 key
.conversation
= conversation
;
520 key
.spx_src
= spx_src
;
521 key
.spx_seq
= spx_seq
;
523 return (spx_hash_value
*)wmem_map_lookup(spx_hash
, &key
);
526 /* ================================================================= */
528 /* ================================================================= */
530 #define SPX_SYS_PACKET 0x80
531 #define SPX_SEND_ACK 0x40
532 #define SPX_ATTN 0x20
534 #define SPX_VII_PACKET 0x08
535 #define SPX_NEG_SIZE 0x04
536 #define SPX_RESERVED 0x02
537 #define SPX_EXT_HEADER 0x01
539 static const value_string conn_vals
[] = {
540 { 0x00, "Data, No Ack Required" },
541 { SPX_EOM
, "End-of-Message" },
542 { SPX_ATTN
, "Attention" },
543 { SPX_SEND_ACK
, "Acknowledgment Required"},
544 { SPX_SEND_ACK
|SPX_EOM
, "Send Ack: End Message"},
545 { SPX_SYS_PACKET
, "System Packet"},
546 { SPX_SYS_PACKET
|SPX_SEND_ACK
, "System Packet: Send Ack"},
551 spx_datastream(uint8_t type
)
555 return "End-of-Connection";
557 return "End-of-Connection Acknowledgment";
563 #define SPX_HEADER_LEN 12
564 #define SPX2_HEADER_LEN 14
567 dissect_spx(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
569 proto_tree
*spx_tree
;
573 uint8_t hdr_len
= SPX_HEADER_LEN
;
574 uint8_t datastream_type
;
575 const char *datastream_type_string
;
577 const char *spx_msg_string
;
578 uint16_t low_socket
, high_socket
;
580 conversation_t
*conversation
;
581 spx_hash_value
*pkt_value
;
582 spx_rexmit_info
*spx_rexmit_info_p
;
585 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "SPX");
586 col_set_str(pinfo
->cinfo
, COL_INFO
, "SPX");
588 conn_ctrl
= tvb_get_uint8(tvb
, 0);
589 if ((conn_ctrl
& SPX_VII_PACKET
) && tvb_get_ntohs(tvb
, 4) != 0xffff) {
590 /* SPX2 packets have an extra two-byte field, unless they have
591 * a dest-ID of 0xffff... */
592 hdr_len
= SPX2_HEADER_LEN
;
595 ti
= proto_tree_add_item(tree
, proto_spx
, tvb
, 0, hdr_len
, ENC_NA
);
596 spx_tree
= proto_item_add_subtree(ti
, ett_spx
);
598 spx_msg_string
= val_to_str_const((conn_ctrl
& 0xf0), conn_vals
, "Unknown" );
599 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " %s", spx_msg_string
);
601 static int * const spx_flags
[] = {
602 &hf_spx_connection_control_sys
,
603 &hf_spx_connection_control_send_ack
,
604 &hf_spx_connection_control_attn
,
605 &hf_spx_connection_control_eom
,
609 static int * const spx_vii_flags
[] = {
610 &hf_spx_connection_control_sys
,
611 &hf_spx_connection_control_send_ack
,
612 &hf_spx_connection_control_attn
,
613 &hf_spx_connection_control_eom
,
614 &hf_spx_connection_control_v2
,
615 &hf_spx_connection_control_neg_size
,
616 &hf_spx_connection_control_reserved
,
617 &hf_spx_connection_control_ext_header
,
621 if (conn_ctrl
& SPX_VII_PACKET
) {
622 proto_tree_add_bitmask_with_flags(spx_tree
, tvb
, 0, hf_spx_connection_control
,
623 ett_spx_connctrl
, spx_vii_flags
, ENC_NA
, BMT_NO_APPEND
);
625 proto_tree_add_bitmask_with_flags(spx_tree
, tvb
, 0, hf_spx_connection_control
,
626 ett_spx_connctrl
, spx_flags
, ENC_NA
, BMT_NO_APPEND
);
630 datastream_type
= tvb_get_uint8(tvb
, 1);
631 datastream_type_string
= spx_datastream(datastream_type
);
632 if (datastream_type_string
!= NULL
) {
633 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (%s)",
634 datastream_type_string
);
637 if (datastream_type_string
!= NULL
) {
638 proto_tree_add_uint_format_value(spx_tree
, hf_spx_datastream_type
, tvb
,
639 1, 1, datastream_type
,
641 datastream_type_string
,
644 proto_tree_add_uint_format_value(spx_tree
, hf_spx_datastream_type
, tvb
,
645 1, 1, datastream_type
,
649 proto_tree_add_item(spx_tree
, hf_spx_src_id
, tvb
, 2, 2, ENC_BIG_ENDIAN
);
650 proto_tree_add_item(spx_tree
, hf_spx_dst_id
, tvb
, 4, 2, ENC_BIG_ENDIAN
);
652 spx_seq
= tvb_get_ntohs(tvb
, 6);
654 proto_tree_add_uint(spx_tree
, hf_spx_seq_nr
, tvb
, 6, 2, spx_seq
);
655 proto_tree_add_item(spx_tree
, hf_spx_ack_nr
, tvb
, 8, 2, ENC_BIG_ENDIAN
);
656 proto_tree_add_item(spx_tree
, hf_spx_all_nr
, tvb
, 10, 2, ENC_BIG_ENDIAN
);
657 /* field exists on ALL SPXII packets EXCEPT the first packet of
658 * the session. The first packet can be determined by checking
659 * the destination ID field for a value of 0xffff (65535) and
660 * that the SPXII bit is set in Connection Control.
662 if ((conn_ctrl
& SPX_VII_PACKET
) && tvb_get_ntohs(tvb
, 4) != 0xffff) {
663 proto_tree_add_item(spx_tree
, hf_spx_neg_size
, tvb
, 12, 2, ENC_BIG_ENDIAN
);
668 * SPX is Connection Oriented and Delivery Guaranteed.
669 * On the first pass, we need to flag retransmissions by the SPX
670 * protocol, so that subdissectors know whether a packet was
673 * We start out by creating a conversation for this direction of the
674 * IPX session; we use "pinfo->srcport" twice, so that we have
675 * separate conversations for the two directions.
677 * XXX - that might not work correctly if there's more than one
678 * SPX session using that source port; can that happen? If so,
679 * we should probably use the direction, as well as the conversation,
680 * as part of the hash key; if we do that, we can probably just
681 * use CONVERSATION_IPX as the port type, and possibly get rid of CONVERSATION_NCP.
685 * http://developer.novell.com/research/appnotes/1995/december/03/apv.htm
687 * the sequence number is not incremented for system packets, so
688 * presumably that means there is no notion of a system packet
689 * being retransmitted; that document also says that system
690 * packets are used as "I'm still here" keepalives and as
691 * acknowledgements (presumably meaning ACK-only packets), which
692 * suggests that they might not be ACKed and thus might not
695 if (conn_ctrl
& SPX_SYS_PACKET
) {
697 * It's a system packet, so it isn't a retransmission.
699 spx_rexmit_info_p
= NULL
;
702 * Not a system packet - check for retransmissions.
704 if (!pinfo
->fd
->visited
) {
705 conversation
= find_conversation(pinfo
->num
, &pinfo
->src
,
706 &pinfo
->dst
, CONVERSATION_NCP
, pinfo
->srcport
,
708 if (conversation
== NULL
) {
710 * It's not part of any conversation - create
713 conversation
= conversation_new(pinfo
->num
, &pinfo
->src
,
714 &pinfo
->dst
, CONVERSATION_NCP
, pinfo
->srcport
,
719 * Now we'll hash the SPX header and use the result
720 * of that, plus the conversation, as a hash key to
721 * identify this packet.
723 * If we don't find it in the hash table, it's not a
724 * retransmission, otherwise it is. If we don't find
725 * it, we enter it into the hash table, with the
727 * If we do, we attach to this frame a structure giving
728 * the frame number of the original transmission, so
729 * that we, and subdissectors, know it's a
732 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);
733 pkt_value
= spx_hash_lookup(conversation
, src
, spx_seq
);
734 if (pkt_value
== NULL
) {
736 * Not found in the hash table.
737 * Enter it into the hash table.
739 pkt_value
= spx_hash_insert(conversation
, src
,
741 pkt_value
->spx_ack
= tvb_get_ntohs(tvb
, 8);
742 pkt_value
->spx_all
= tvb_get_ntohs(tvb
, 10);
743 pkt_value
->num
= pinfo
->num
;
746 * This is not a retransmission, so we shouldn't
747 * have any retransmission indicator.
749 spx_rexmit_info_p
= NULL
;
752 * Found in the hash table. Mark this frame as
755 spx_rexmit_info_p
= wmem_new(wmem_file_scope(), spx_rexmit_info
);
756 spx_rexmit_info_p
->num
= pkt_value
->num
;
757 p_add_proto_data(wmem_file_scope(), pinfo
, proto_spx
, 0,
762 * Do we have per-packet SPX data for this frame?
763 * If so, it's a retransmission, and the per-packet
764 * data indicates which frame had the original
767 spx_rexmit_info_p
= (spx_rexmit_info
*)p_get_proto_data(wmem_file_scope(), pinfo
,
773 * It's a retransmission if we have a retransmission indicator.
774 * Flag this as a retransmission, but don't pass it to the
777 if (spx_rexmit_info_p
!= NULL
) {
778 col_add_fstr(pinfo
->cinfo
, COL_INFO
,
779 "[Retransmission] Original Packet %u",
780 spx_rexmit_info_p
->num
);
783 proto_tree_add_uint_format(spx_tree
, hf_spx_rexmt_frame
,
784 tvb
, 0, 0, spx_rexmit_info_p
->num
,
785 "This is a retransmission of frame %u",
786 spx_rexmit_info_p
->num
);
787 if (tvb_reported_length_remaining(tvb
, hdr_len
) > 0) {
788 proto_tree_add_item(spx_tree
, hf_spx_rexmt_data
, tvb
, hdr_len
, -1, ENC_NA
);
791 return tvb_captured_length(tvb
);
794 if (tvb_reported_length_remaining(tvb
, hdr_len
) > 0) {
796 * Call subdissectors based on the IPX socket numbers; a
797 * subdissector might have registered with our IPX socket
798 * dissector table rather than the IPX dissector's socket
801 * Assume the lower-numbered socket number is more likely
802 * to be the right one, along the lines of what we do for
803 * TCP and UDP. We've seen NCP packets with a type of NCP,
804 * a source socket of IPX_SOCKET_NCP, and a destination
805 * socket of IPX_SOCKET_IPX_MESSAGE, and we've seen NCP
806 * packets with a type of NCP, a source socket of
807 * IPX_SOCKET_IPX_MESSAGE, and a destination socket of
810 if (pinfo
->srcport
> pinfo
->destport
) {
811 low_socket
= pinfo
->destport
;
812 high_socket
= pinfo
->srcport
;
814 low_socket
= pinfo
->srcport
;
815 high_socket
= pinfo
->destport
;
819 * Pass information to subdissectors.
821 spx_infox
.eom
= conn_ctrl
& SPX_EOM
;
822 spx_infox
.datastream_type
= datastream_type
;
824 next_tvb
= tvb_new_subset_remaining(tvb
, hdr_len
);
825 if (dissector_try_uint_with_data(spx_socket_dissector_table
, low_socket
,
826 next_tvb
, pinfo
, tree
, false, &spx_infox
))
828 return tvb_captured_length(tvb
);
830 if (dissector_try_uint_with_data(spx_socket_dissector_table
, high_socket
,
831 next_tvb
, pinfo
, tree
, false, &spx_infox
))
833 return tvb_captured_length(tvb
);
835 call_data_dissector(next_tvb
, pinfo
, tree
);
837 return tvb_captured_length(tvb
);
840 /* ================================================================= */
842 /* ================================================================= */
844 dissect_ipxmsg(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
846 proto_tree
*msg_tree
;
848 uint8_t conn_number
, sig_char
;
850 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "IPX MSG");
851 col_clear(pinfo
->cinfo
, COL_INFO
);
853 conn_number
= tvb_get_uint8(tvb
, 0);
854 sig_char
= tvb_get_uint8(tvb
, 1);
856 col_add_fstr(pinfo
->cinfo
, COL_INFO
,
858 val_to_str_const(sig_char
, ipxmsg_sigchar_vals
, "Unknown Signature Character"), conn_number
);
861 ti
= proto_tree_add_item(tree
, proto_ipxmsg
, tvb
, 0, -1, ENC_NA
);
862 msg_tree
= proto_item_add_subtree(ti
, ett_ipxmsg
);
864 proto_tree_add_uint(msg_tree
, hf_msg_conn
, tvb
, 0, 1, conn_number
);
865 proto_tree_add_uint(msg_tree
, hf_msg_sigchar
, tvb
, 1, 1, sig_char
);
867 return tvb_captured_length(tvb
);
871 /* ================================================================= */
873 /* ================================================================= */
874 static const value_string ipxrip_packet_vals
[] = {
875 { IPX_RIP_REQUEST
, "Request"},
876 { IPX_RIP_RESPONSE
, "Response"},
881 dissect_ipxrip(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
883 proto_tree
*rip_tree
;
884 proto_item
*ti
, *hidden_item
;
885 uint16_t operation
, ticks
;
887 unsigned available_length
;
889 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "IPX RIP");
890 col_clear(pinfo
->cinfo
, COL_INFO
);
892 operation
= tvb_get_ntohs(tvb
, 0);
894 /* rip_types 0 and 1 are valid, anything else becomes 2 or "Unknown" */
895 col_set_str(pinfo
->cinfo
, COL_INFO
, val_to_str_const(operation
, ipxrip_packet_vals
, "Unknown"));
898 ti
= proto_tree_add_item(tree
, proto_ipxrip
, tvb
, 0, -1, ENC_NA
);
899 rip_tree
= proto_item_add_subtree(ti
, ett_ipxrip
);
901 proto_tree_add_item(rip_tree
, hf_ipxrip_packet_type
, tvb
, 0, 2, ENC_BIG_ENDIAN
);
905 case IPX_RIP_REQUEST
:
906 hidden_item
= proto_tree_add_boolean(rip_tree
,
909 proto_item_set_hidden(hidden_item
);
911 case IPX_RIP_RESPONSE
:
912 hidden_item
= proto_tree_add_boolean(rip_tree
,
915 proto_item_set_hidden(hidden_item
);
919 available_length
= tvb_reported_length(tvb
);
920 for (cursor
= 2; cursor
< available_length
; cursor
+= 8) {
921 ticks
= tvb_get_ntohs(tvb
, cursor
+6);
923 proto_tree_add_item(rip_tree
, hf_ipxrip_route_vector
, tvb
, cursor
, 4, ENC_NA
);
924 proto_tree_add_item(rip_tree
, hf_ipxrip_hops
, tvb
, cursor
+4, 2, ENC_BIG_ENDIAN
);
925 if (operation
== IPX_RIP_REQUEST
- 1) {
926 proto_tree_add_item(rip_tree
, hf_ipxrip_ticks
, tvb
, cursor
+6, 2, ENC_BIG_ENDIAN
);
929 proto_tree_add_uint_format_value(rip_tree
, hf_ipxrip_ticks
, tvb
, cursor
+6, 2, ticks
,
930 "%d ms", ticks
* 1000 / 18);
934 return tvb_captured_length(tvb
);
937 /* ================================================================= */
938 /* IPX Serialization */
939 /* ================================================================= */
941 dissect_serialization(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
943 proto_tree
*ser_tree
= NULL
;
946 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "NW_SERIAL");
947 col_clear(pinfo
->cinfo
, COL_INFO
);
950 ti
= proto_tree_add_item(tree
, proto_serialization
, tvb
, 0, -1,
952 ser_tree
= proto_item_add_subtree(ti
, ett_serialization
);
955 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "Serial number %s",
956 tvb_bytes_to_str(pinfo
->pool
, tvb
, 0, 6));
958 proto_tree_add_item(ser_tree
, hf_serial_number
, tvb
, 0, 6, ENC_NA
);
959 return tvb_captured_length(tvb
);
963 * Some of these are from ncpfs, others are from the book,
964 * others are from the page at
966 * http://www.iana.org/assignments/novell-sap-numbers
968 * and some from the page at
970 * http://www.rware.demon.co.uk/ipxsap.htm
972 * (see also the page at
974 * http://developer.novell.com/research/appnotes/1998/february/03/06.htm
976 * which has a huge list - but many of the entries list only the
977 * organization owning the SAP type, not what the type is for).
979 static const value_string novell_server_vals
[] = {
980 { 0x0000, "Unknown" },
982 { 0x0002, "User Group" },
983 { 0x0003, "Print Queue or Print Group" },
984 { 0x0004, "File Server (SLIST source)" },
985 { 0x0005, "Job Server" },
986 { 0x0006, "Gateway" },
987 { 0x0007, "Print Server or Silent Print Server" },
988 { 0x0008, "Archive Queue" },
989 { 0x0009, "Archive Server" },
990 { 0x000a, "Job Queue" },
991 { 0x000b, "Administration" },
992 { 0x000F, "Novell TI-RPC" },
993 { 0x0017, "Diagnostics" },
994 { 0x0020, "NetBIOS" },
995 { 0x0021, "NAS SNA Gateway" },
996 { 0x0023, "NACS Async Gateway or Asynchronous Gateway" },
997 { 0x0024, "Remote Bridge or Routing Service" },
998 { 0x0026, "Bridge Server or Asynchronous Bridge Server" },
999 { 0x0027, "TCP/IP Gateway Server" },
1000 { 0x0028, "Point to Point (Eicon) X.25 Bridge Server" },
1001 { 0x0029, "Eicon 3270 Gateway" },
1002 { 0x002a, "CHI Corp" },
1003 { 0x002c, "PC Chalkboard" },
1004 { 0x002d, "Time Synchronization Server or Asynchronous Timer" },
1005 { 0x002e, "ARCserve 5.0 / Palindrome Backup Director 4.x (PDB4)" },
1006 { 0x0045, "DI3270 Gateway" },
1007 { 0x0047, "Advertising Print Server" },
1008 { 0x004a, "NetBlazer Modems" },
1009 { 0x004b, "Btrieve VAP/NLM 5.0" },
1010 { 0x004c, "NetWare SQL VAP/NLM Server" },
1011 { 0x004d, "Xtree Network Version/NetWare XTree" },
1012 { 0x0050, "Btrieve VAP 4.11" },
1013 { 0x0052, "QuickLink (Cubix)" },
1014 { 0x0053, "Print Queue User" },
1015 { 0x0058, "Multipoint X.25 Eicon Router" },
1016 { 0x0060, "STLB/NLM" },
1017 { 0x0064, "ARCserve" },
1018 { 0x0066, "ARCserve 3.0" },
1019 { 0x0072, "WAN Copy Utility" },
1020 { 0x007a, "TES-NetWare for VMS" },
1021 { 0x0092, "WATCOM Debugger or Emerald Tape Backup Server" },
1022 { 0x0095, "DDA OBGYN" },
1023 { 0x0098, "NetWare Access Server (Asynchronous gateway)" },
1024 { 0x009a, "NetWare for VMS II or Named Pipe Server" },
1025 { 0x009b, "NetWare Access Server" },
1026 { 0x009e, "Portable NetWare Server or SunLink NVT" },
1027 { 0x00a1, "Powerchute APC UPS NLM" },
1028 { 0x00aa, "LAWserve" },
1029 { 0x00ac, "Compaq IDA Status Monitor" },
1030 { 0x0100, "PIPE STAIL" },
1031 { 0x0102, "LAN Protect Bindery" },
1032 { 0x0103, "Oracle DataBase Server" },
1033 { 0x0107, "NetWare 386 or RSPX Remote Console" },
1034 { 0x010f, "Novell SNA Gateway" },
1035 { 0x0111, "Test Server" },
1036 { 0x0112, "Print Server (HP)" },
1037 { 0x0114, "CSA MUX (f/Communications Executive)" },
1038 { 0x0115, "CSA LCA (f/Communications Executive)" },
1039 { 0x0116, "CSA CM (f/Communications Executive)" },
1040 { 0x0117, "CSA SMA (f/Communications Executive)" },
1041 { 0x0118, "CSA DBA (f/Communications Executive)" },
1042 { 0x0119, "CSA NMA (f/Communications Executive)" },
1043 { 0x011a, "CSA SSA (f/Communications Executive)" },
1044 { 0x011b, "CSA STATUS (f/Communications Executive)" },
1045 { 0x011e, "CSA APPC (f/Communications Executive)" },
1046 { 0x0126, "SNA TEST SSA Profile" },
1047 { 0x012a, "CSA TRACE (f/Communications Executive)" },
1048 { 0x012b, "NetWare for SAA" },
1049 { 0x012e, "IKARUS virus scan utility" },
1050 { 0x0130, "Communications Executive" },
1051 { 0x0133, "NNS Domain Server or NetWare Naming Services Domain" },
1052 { 0x0135, "NetWare Naming Services Profile" },
1053 { 0x0137, "NetWare 386 Print Queue or NNS Print Queue" },
1054 { 0x0141, "LAN Spool Server (Vap, Intel)" },
1055 { 0x0152, "IRMALAN Gateway" },
1056 { 0x0154, "Named Pipe Server" },
1057 { 0x0166, "NetWare Management" },
1058 { 0x0168, "Intel PICKIT Comm Server or Intel CAS Talk Server" },
1059 { 0x0173, "Compaq" },
1060 { 0x0174, "Compaq SNMP Agent" },
1061 { 0x0175, "Compaq" },
1062 { 0x0180, "XTree Server or XTree Tools" },
1063 { 0x018A, "NASI services broadcast server (Novell)" },
1064 { 0x01b0, "GARP Gateway (net research)" },
1065 { 0x01b1, "Binfview (Lan Support Group)" },
1066 { 0x01bf, "Intel LanDesk Manager" },
1067 { 0x01ca, "AXTEC" },
1068 { 0x01cb, "Shiva NetModem/E" },
1069 { 0x01cc, "Shiva LanRover/E" },
1070 { 0x01cd, "Shiva LanRover/T" },
1071 { 0x01ce, "Shiva Universal" },
1072 { 0x01d8, "Castelle FAXPress Server" },
1073 { 0x01da, "Castelle LANPress Print Server" },
1074 { 0x01dc, "Castelle FAX/Xerox 7033 Fax Server/Excel Lan Fax" },
1075 { 0x01f0, "LEGATO" },
1076 { 0x01f5, "LEGATO" },
1077 { 0x0233, "NMS Agent or NetWare Management Agent" },
1078 { 0x0237, "NMS IPX Discovery or LANtern Read/Write Channel" },
1079 { 0x0238, "NMS IP Discovery or LANtern Trap/Alarm Channel" },
1080 { 0x023a, "LANtern" },
1081 { 0x023c, "MAVERICK" },
1082 { 0x023f, "SMS Testing and Development" },
1083 { 0x024e, "NetWare Connect" },
1084 { 0x024f, "NASI server broadcast (Cisco)" },
1085 { 0x026a, "Network Management (NMS) Service Console" },
1086 { 0x026b, "Time Synchronization Server (NetWare 4.x)" },
1087 { 0x0278, "Directory Server (NetWare 4.x)" },
1088 { 0x027b, "NetWare Management Agent" },
1089 { 0x0280, "Novell File and Printer Sharing Service for PC" },
1090 { 0x0304, "Novell SAA Gateway" },
1091 { 0x0308, "COM or VERMED 1" },
1092 { 0x030a, "Galacticomm's Worldgroup Server" },
1093 { 0x030c, "Intel Netport 2 or HP JetDirect or HP Quicksilver" },
1094 { 0x0320, "Attachmate Gateway" },
1095 { 0x0327, "Microsoft Diagnostics" },
1096 { 0x0328, "WATCOM SQL server" },
1097 { 0x0335, "MultiTech Systems Multisynch Comm Server" },
1098 { 0x0343, "Xylogics Remote Access Server or LAN Modem" },
1099 { 0x0355, "Arcada Backup Exec" },
1100 { 0x0358, "MSLCD1" },
1101 { 0x0361, "NETINELO" },
1102 { 0x037e, "Powerchute UPS Monitoring" },
1103 { 0x037f, "ViruSafe Notify" },
1104 { 0x0386, "HP Bridge" },
1105 { 0x0387, "HP Hub" },
1106 { 0x0394, "NetWare SAA Gateway" },
1107 { 0x039b, "Lotus Notes" },
1108 { 0x03b7, "Certus Anti Virus NLM" },
1109 { 0x03c4, "ARCserve 4.0 (Cheyenne)" },
1110 { 0x03c7, "LANspool 3.5 (Intel)" },
1111 { 0x03d7, "Lexmark printer server (type 4033-011)" },
1112 { 0x03d8, "Lexmark XLE printer server (type 4033-301)" },
1113 { 0x03dd, "Banyan ENS for NetWare Client NLM" },
1114 { 0x03de, "Gupta Sequel Base Server or NetWare SQL" },
1115 { 0x03e1, "Univel Unixware" },
1116 { 0x03e4, "Univel Unixware" },
1117 { 0x03fc, "Intel Netport" },
1118 { 0x03fd, "Intel Print Server Queue" },
1119 { 0x040A, "ipnServer" },
1120 { 0x040D, "LVERRMAN" },
1121 { 0x040E, "LVLIC" },
1122 { 0x0414, "NET Silicon (DPI)/Kyocera" },
1123 { 0x0429, "Site Lock Virus (Brightworks)" },
1124 { 0x0432, "UFHELP R" },
1125 { 0x0433, "Synoptics 281x Advanced SNMP Agent" },
1126 { 0x0444, "Microsoft NT SNA Server" },
1127 { 0x0448, "Oracle" },
1128 { 0x044c, "ARCserve 5.01" },
1129 { 0x0457, "Canon GP55 Running on a Canon GP55 network printer" },
1130 { 0x045a, "QMS Printers" },
1131 { 0x045b, "Dell SCSI Array (DSA) Monitor" },
1132 { 0x0491, "NetBlazer Modems" },
1133 { 0x04ac, "On-Time Scheduler NLM" },
1134 { 0x04b0, "CD-Net (Meridian)" },
1135 { 0x0513, "Emulex NQA" },
1136 { 0x0520, "Site Lock Checks" },
1137 { 0x0529, "Site Lock Checks (Brightworks)" },
1138 { 0x052d, "Citrix OS/2 App Server" },
1139 { 0x0535, "Tektronix" },
1140 { 0x0536, "Milan" },
1141 { 0x055d, "Attachmate SNA gateway" },
1142 { 0x056b, "IBM 8235 modem server" },
1143 { 0x056c, "Shiva LanRover/E PLUS" },
1144 { 0x056d, "Shiva LanRover/T PLUS" },
1145 { 0x0580, "McAfee's NetShield anti-virus" },
1146 { 0x05B8, "NLM to workstation communication (Revelation Software)" },
1147 { 0x05BA, "Compatible Systems Routers" },
1148 { 0x05BE, "Cheyenne Hierarchical Storage Manager" },
1149 { 0x0606, "JCWatermark Imaging" },
1150 { 0x060c, "AXIS Network Printer" },
1151 { 0x0610, "Adaptec SCSI Management" },
1152 { 0x0621, "IBM AntiVirus NLM" },
1153 { 0x0640, "Microsoft Gateway Services for NetWare" },
1154 /* { 0x0640, "NT Server-RPC/GW for NW/Win95 User Level Sec" }, */
1155 { 0x064e, "Microsoft Internet Information Server" },
1156 { 0x067b, "Microsoft Win95/98 File and Print Sharing for NetWare" },
1157 { 0x067c, "Microsoft Win95/98 File and Print Sharing for NetWare" },
1158 { 0x076C, "Xerox" },
1159 { 0x079b, "Shiva LanRover/E 115" },
1160 { 0x079c, "Shiva LanRover/T 115" },
1161 { 0x07B4, "Cubix WorldDesk" },
1162 { 0x07c1, "Quarterdeck IWare Connect V3.x NLM" },
1163 { 0x07c2, "Quarterdeck IWare Connect V2.x NLM" },
1164 { 0x0810, "ELAN License Server Demo" },
1165 { 0x0824, "Shiva LanRover Access Switch/E" },
1166 { 0x086a, "ISSC collector NLMs" },
1167 { 0x087f, "ISSC DAS agent for AIX" },
1168 { 0x0880, "Intel Netport PRO" },
1169 { 0x0881, "Intel Netport PRO" },
1170 { 0x0b29, "Site Lock" },
1171 { 0x0c29, "Site Lock Applications" },
1172 { 0x0c2c, "Licensing Server" },
1173 { 0x2101, "Performance Technology Instant Internet" },
1174 { 0x2380, "LAI Site Lock" },
1175 { 0x238c, "Meeting Maker" },
1176 { 0x4808, "Site Lock Server or Site Lock Metering VAP/NLM" },
1177 { 0x5555, "Site Lock User" },
1178 { 0x6312, "Tapeware" },
1179 { 0x6f00, "Rabbit Gateway (3270)" },
1180 { 0x7703, "MODEM" },
1181 { 0x8002, "NetPort Printers (Intel) or LANport" },
1182 { 0x8003, "SEH InterCon Printserver" },
1183 { 0x8008, "WordPerfect Network Version" },
1184 { 0x85BE, "Cisco Enhanced Interior Routing Protocol (EIGRP)" },
1185 { 0x8888, "WordPerfect Network Version or Quick Network Management" },
1186 { 0x9000, "McAfee's NetShield anti-virus" },
1187 { 0x9604, "CSA-NT_MON" },
1188 { 0xb6a8, "Ocean Isle Reachout Remote Control" },
1189 { 0xf11f, "Site Lock Metering VAP/NLM" },
1190 { 0xf1ff, "Site Lock" },
1191 { 0xf503, "Microsoft SQL Server" },
1192 { 0xf905, "IBM Time and Place/2 application" },
1193 { 0xfbfb, "TopCall III fax server" },
1194 { 0xffff, "Any Service or Wildcard" },
1198 value_string_ext novell_server_vals_ext
= VALUE_STRING_EXT_INIT(novell_server_vals
);
1200 static const value_string ipxsap_packet_vals
[] = {
1201 { IPX_SAP_GENERAL_QUERY
, "General Query"},
1202 { IPX_SAP_GENERAL_RESPONSE
, "General Response"},
1203 { IPX_SAP_NEAREST_QUERY
, "Nearest Query"},
1204 { IPX_SAP_NEAREST_RESPONSE
, "Nearest Response"},
1209 dissect_ipxsap(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
1211 proto_tree
*sap_tree
, *s_tree
;
1212 proto_item
*ti
, *hidden_item
;
1214 struct sap_query query
;
1216 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "IPX SAP");
1217 col_clear(pinfo
->cinfo
, COL_INFO
);
1219 query
.query_type
= tvb_get_ntohs(tvb
, 0);
1220 query
.server_type
= tvb_get_ntohs(tvb
, 2);
1222 col_set_str(pinfo
->cinfo
, COL_INFO
, val_to_str_const(query
.query_type
, ipxsap_packet_vals
, "Unknown Packet Type"));
1225 ti
= proto_tree_add_item(tree
, proto_sap
, tvb
, 0, -1, ENC_NA
);
1226 sap_tree
= proto_item_add_subtree(ti
, ett_ipxsap
);
1228 proto_tree_add_item(sap_tree
, hf_sap_packet_type
, tvb
, 0, 2, ENC_BIG_ENDIAN
);
1230 switch(query
.query_type
)
1232 case IPX_SAP_GENERAL_QUERY
:
1233 case IPX_SAP_NEAREST_QUERY
:
1234 hidden_item
= proto_tree_add_boolean(sap_tree
,
1237 proto_item_set_hidden(hidden_item
);
1239 case IPX_SAP_GENERAL_RESPONSE
:
1240 case IPX_SAP_NEAREST_RESPONSE
:
1241 hidden_item
= proto_tree_add_boolean(sap_tree
,
1244 proto_item_set_hidden(hidden_item
);
1248 if (query
.query_type
== IPX_SAP_GENERAL_RESPONSE
||
1249 query
.query_type
== IPX_SAP_NEAREST_RESPONSE
) { /* responses */
1251 unsigned available_length
= tvb_reported_length(tvb
);
1252 for (cursor
= 2; cursor
< available_length
; cursor
+= 64) {
1253 const uint8_t *server_name
;
1255 ti
= proto_tree_add_item(sap_tree
, hf_sap_server
, tvb
, cursor
, 64, ENC_NA
);
1256 s_tree
= proto_item_add_subtree(ti
, ett_ipxsap_server
);
1258 proto_tree_add_item(s_tree
, hf_sap_server_type
, tvb
, cursor
, 2, ENC_BIG_ENDIAN
);
1259 proto_tree_add_item_ret_string(s_tree
, hf_sap_server_name
, tvb
, cursor
+2, 48, ENC_ASCII
|ENC_NA
, pinfo
->pool
, &server_name
);
1260 proto_item_append_text(ti
, ": %s", server_name
);
1261 proto_tree_add_item(s_tree
, hf_sap_server_network
, tvb
, cursor
+50, 4, ENC_NA
);
1262 proto_tree_add_item(s_tree
, hf_sap_server_node
, tvb
, cursor
+54, 6, ENC_NA
);
1263 proto_tree_add_item(s_tree
, hf_sap_server_socket
, tvb
, cursor
+60, 2, ENC_BIG_ENDIAN
);
1264 proto_tree_add_item(s_tree
, hf_sap_server_intermediate_networks
, tvb
, cursor
+62, 2, ENC_BIG_ENDIAN
);
1267 else { /* queries */
1268 proto_tree_add_item(sap_tree
, hf_sap_server_type
, tvb
, 2, 2, ENC_BIG_ENDIAN
);
1271 return tvb_captured_length(tvb
);
1275 proto_register_ipx(void)
1277 static hf_register_info hf_ipx
[] = {
1279 { "Checksum", "ipx.checksum", FT_UINT16
, BASE_HEX
, NULL
, 0x0,
1283 { "Source Address", "ipx.src", FT_STRING
, BASE_NONE
, NULL
, 0x0,
1284 "Source IPX Address \"network.node\"", HFILL
}},
1287 { "Destination Address", "ipx.dst", FT_STRING
, BASE_NONE
, NULL
, 0x0,
1288 "Destination IPX Address \"network.node\"", HFILL
}},
1290 { "Src/Dst Address", "ipx.addr", FT_STRING
, BASE_NONE
, NULL
, 0x0,
1291 "Source or Destination IPX Address \"network.node\"", HFILL
}},
1294 { "Length", "ipx.len", FT_UINT16
, BASE_DEC
|BASE_UNIT_STRING
, UNS(&units_byte_bytes
), 0x0,
1298 { "Transport Control (Hops)", "ipx.hops", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1301 { &hf_ipx_packet_type
,
1302 { "Packet Type", "ipx.packet_type", FT_UINT8
, BASE_HEX
, VALS(ipx_packet_type_vals
),
1307 { "Destination Network","ipx.dst.net", FT_IPXNET
, BASE_NONE
, NULL
, 0x0,
1311 { "Destination Node", "ipx.dst.node", FT_ETHER
, BASE_NONE
, NULL
, 0x0,
1315 { "Destination Socket", "ipx.dst.socket", FT_UINT16
, BASE_HEX
|BASE_EXT_STRING
,
1316 &ipx_socket_vals_ext
, 0x0,
1320 { "Source Network","ipx.src.net", FT_IPXNET
, BASE_NONE
, NULL
, 0x0,
1324 { "Source Node", "ipx.src.node", FT_ETHER
, BASE_NONE
, NULL
, 0x0,
1328 { "Source Socket", "ipx.src.socket", FT_UINT16
, BASE_HEX
|BASE_EXT_STRING
,
1329 &ipx_socket_vals_ext
, 0x0,
1333 { "Source or Destination Network","ipx.net", FT_IPXNET
, BASE_NONE
, NULL
, 0x0,
1337 { "Source or Destination Node", "ipx.node", FT_ETHER
, BASE_NONE
, NULL
, 0x0,
1341 { "Source or Destination Socket", "ipx.socket", FT_UINT16
, BASE_HEX
|BASE_EXT_STRING
,
1342 &ipx_socket_vals_ext
, 0x0,
1346 static hf_register_info hf_spx
[] = {
1347 { &hf_spx_connection_control
,
1348 { "Connection Control", "spx.ctl",
1349 FT_UINT8
, BASE_HEX
, VALS(conn_vals
), 0x0,
1352 { &hf_spx_connection_control_sys
,
1353 { "System Packet", "spx.ctl.sys",
1354 FT_BOOLEAN
, 8, NULL
, SPX_SYS_PACKET
,
1357 { &hf_spx_connection_control_send_ack
,
1358 { "Send Ack", "spx.ctl.send_ack",
1359 FT_BOOLEAN
, 8, NULL
, SPX_SEND_ACK
,
1362 { &hf_spx_connection_control_attn
,
1363 { "Attention", "spx.ctl.attn",
1364 FT_BOOLEAN
, 8, NULL
, SPX_ATTN
,
1367 { &hf_spx_connection_control_eom
,
1368 { "End of Message", "spx.ctl.eom",
1369 FT_BOOLEAN
, 8, NULL
, SPX_EOM
,
1372 { &hf_spx_connection_control_v2
,
1373 { "SPXII Packet", "spx.ctl.v2",
1374 FT_BOOLEAN
, 8, NULL
, SPX_VII_PACKET
,
1377 { &hf_spx_connection_control_neg_size
,
1378 { "Negotiate Size", "spx.ctl.neg_size",
1379 FT_BOOLEAN
, 8, NULL
, SPX_NEG_SIZE
,
1382 { &hf_spx_connection_control_reserved
,
1383 { "Reserved", "spx.ctl.reserved",
1384 FT_BOOLEAN
, 8, NULL
, SPX_RESERVED
,
1387 { &hf_spx_connection_control_ext_header
,
1388 { "Extended Header", "spx.ctl.ext_header",
1389 FT_BOOLEAN
, 8, NULL
, SPX_EXT_HEADER
,
1392 { &hf_spx_datastream_type
,
1393 { "Datastream Type", "spx.type",
1394 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1398 { "Source Connection ID", "spx.src",
1399 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1403 { "Destination Connection ID", "spx.dst",
1404 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1408 { "Sequence Number", "spx.seq",
1409 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1413 { "Acknowledgment Number", "spx.ack",
1414 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1418 { "Allocation Number", "spx.alloc",
1419 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1423 { "Negotiation Size", "spx.neg_size",
1424 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1427 { &hf_spx_rexmt_frame
,
1428 { "Retransmitted Frame Number", "spx.rexmt_frame",
1429 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
1432 { &hf_spx_rexmt_data
,
1433 { "Retransmitted data", "spx.rexmt_data",
1434 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1438 static hf_register_info hf_ipxrip
[] = {
1439 { &hf_ipxrip_request
,
1440 { "Request", "ipxrip.request",
1441 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1442 "true if IPX RIP request", HFILL
}},
1444 { &hf_ipxrip_response
,
1445 { "Response", "ipxrip.response",
1446 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1447 "true if IPX RIP response", HFILL
}},
1449 { &hf_ipxrip_packet_type
,
1450 { "RIP packet type", "ipxrip.packet_type",
1451 FT_UINT16
, BASE_DEC
, VALS(ipxrip_packet_vals
), 0x0,
1454 { &hf_ipxrip_route_vector
,
1455 { "Route Vector", "ipxrip.route_vector",
1456 FT_IPXNET
, BASE_NONE
, NULL
, 0x0,
1460 { "Hops", "ipxrip.hops",
1461 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1465 { "Ticks", "ipxrip.ticks",
1466 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1470 static hf_register_info hf_sap
[] = {
1472 { "Request", "ipxsap.request",
1473 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1474 "true if SAP request", HFILL
}},
1477 { "Response", "ipxsap.response",
1478 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
1479 "true if SAP response", HFILL
}},
1481 { &hf_sap_packet_type
,
1482 { "SAP packet type", "ipxsap.packet_type",
1483 FT_UINT16
, BASE_DEC
, VALS(ipxsap_packet_vals
), 0x0,
1487 { "Server", "ipxsap.server",
1488 FT_NONE
, BASE_NONE
, NULL
, 0x0,
1491 { &hf_sap_server_type
,
1492 { "Server Type", "ipxsap.server.type",
1493 FT_UINT16
, BASE_HEX
|BASE_EXT_STRING
, &novell_server_vals_ext
, 0x0,
1496 { &hf_sap_server_name
,
1497 { "Server Name", "ipxsap.server.name",
1498 FT_STRINGZTRUNC
, BASE_NONE
, NULL
, 0x0,
1501 { &hf_sap_server_network
,
1502 { "Network", "ipxsap.server.network",
1503 FT_IPXNET
, BASE_NONE
, NULL
, 0x0,
1506 { &hf_sap_server_node
,
1507 { "Node", "ipxsap.server.node",
1508 FT_ETHER
, BASE_NONE
, NULL
, 0x0,
1511 { &hf_sap_server_socket
,
1512 { "Socket", "ipxsap.server.socket",
1513 FT_UINT16
, BASE_HEX
|BASE_EXT_STRING
, &ipx_socket_vals_ext
, 0x0,
1516 { &hf_sap_server_intermediate_networks
,
1517 { "Intermediate Networks", "ipxsap.server.intermediate_networks",
1518 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
1522 static hf_register_info hf_ipxmsg
[] = {
1524 { "Connection Number", "ipxmsg.conn",
1525 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1529 { "Signature Character", "ipxmsg.sigchar",
1530 FT_CHAR
, BASE_HEX
, VALS(ipxmsg_sigchar_vals
), 0x0,
1534 static hf_register_info hf_serial
[] = {
1535 { &hf_serial_number
,
1536 { "Serial number", "nw_serial.serial_number",
1537 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1541 static int *ett
[] = {
1552 proto_ipx
= proto_register_protocol("Internetwork Packet eXchange",
1554 proto_register_field_array(proto_ipx
, hf_ipx
, array_length(hf_ipx
));
1555 ipx_handle
= register_dissector("ipx", dissect_ipx
, proto_ipx
);
1557 proto_spx
= proto_register_protocol("Sequenced Packet eXchange",
1559 proto_register_field_array(proto_spx
, hf_spx
, array_length(hf_spx
));
1560 spx_handle
= register_dissector("spx", dissect_spx
, proto_spx
);
1562 proto_ipxrip
= proto_register_protocol("IPX Routing Information Protocol",
1563 "IPX RIP", "ipxrip");
1564 proto_register_field_array(proto_ipxrip
, hf_ipxrip
, array_length(hf_ipxrip
));
1565 ipxrip_handle
= register_dissector("ipxrip", dissect_ipxrip
, proto_ipxrip
);
1567 proto_serialization
= proto_register_protocol("NetWare Serialization Protocol",
1568 "NW_SERIAL", "nw_serial");
1569 proto_register_field_array(proto_serialization
, hf_serial
, array_length(hf_serial
));
1570 serialization_handle
= register_dissector("nw_serial", dissect_serialization
,
1571 proto_serialization
);
1573 proto_ipxmsg
= proto_register_protocol("IPX Message", "IPX MSG",
1575 proto_register_field_array(proto_ipxmsg
, hf_ipxmsg
, array_length(hf_ipxmsg
));
1576 ipxmsg_handle
= register_dissector("ipxmsg", dissect_ipxmsg
, proto_ipxmsg
);
1578 proto_sap
= proto_register_protocol("Service Advertisement Protocol",
1579 "IPX SAP", "ipxsap");
1580 ipxsap_handle
= register_dissector("ipxsap", dissect_ipxsap
, proto_sap
);
1582 proto_register_field_array(proto_sap
, hf_sap
, array_length(hf_sap
));
1584 proto_register_subtree_array(ett
, array_length(ett
));
1586 ipx_type_dissector_table
= register_dissector_table("ipx.packet_type",
1587 "IPX packet type", proto_ipx
, FT_UINT8
, BASE_HEX
);
1588 ipx_socket_dissector_table
= register_dissector_table("ipx.socket",
1589 "IPX socket", proto_ipx
, FT_UINT16
, BASE_HEX
);
1590 spx_socket_dissector_table
= register_dissector_table("spx.socket",
1591 "SPX socket", proto_spx
, FT_UINT16
, BASE_HEX
);
1593 spx_hash
= wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), spx_hash_func
, spx_equal
);
1594 ipx_tap
=register_tap("ipx");
1596 register_conversation_table(proto_ipx
, true, ipx_conversation_packet
, ipx_endpoint_packet
);
1598 register_capture_dissector("ipx", capture_ipx
, proto_ipx
);
1602 proto_reg_handoff_ipx(void)
1604 capture_dissector_handle_t ipx_cap_handle
;
1606 dissector_add_uint_with_preference("udp.port", UDP_PORT_IPX
, ipx_handle
);
1607 dissector_add_uint("ethertype", ETHERTYPE_IPX
, ipx_handle
);
1608 dissector_add_uint("chdlc.protocol", ETHERTYPE_IPX
, ipx_handle
);
1609 dissector_add_uint("ppp.protocol", PPP_IPX
, ipx_handle
);
1610 dissector_add_uint("llc.dsap", SAP_NETWARE1
, ipx_handle
);
1611 dissector_add_uint("llc.dsap", SAP_NETWARE2
, ipx_handle
);
1612 dissector_add_uint("sll.ltype", LINUX_SLL_P_802_3
, ipx_handle
);
1613 dissector_add_uint("null.type", BSD_AF_IPX
, ipx_handle
);
1614 dissector_add_uint("gre.proto", ETHERTYPE_IPX
, ipx_handle
);
1615 dissector_add_uint("arcnet.protocol_id", ARCNET_PROTO_IPX
, ipx_handle
);
1616 dissector_add_uint("arcnet.protocol_id", ARCNET_PROTO_NOVELL_EC
, ipx_handle
);
1618 dissector_add_uint("ipx.packet_type", IPX_PACKET_TYPE_SPX
, spx_handle
);
1620 dissector_add_uint("ipx.socket", IPX_SOCKET_SAP
, ipxsap_handle
);
1622 dissector_add_uint("ipx.socket", IPX_SOCKET_IPXRIP
, ipxrip_handle
);
1624 dissector_add_uint("ipx.socket", IPX_SOCKET_SERIALIZATION
,
1625 serialization_handle
);
1627 dissector_add_uint("ipx.socket", IPX_SOCKET_IPX_MESSAGE
, ipxmsg_handle
);
1628 dissector_add_uint("ipx.socket", IPX_SOCKET_IPX_MESSAGE1
, ipxmsg_handle
);
1630 ipx_cap_handle
= find_capture_dissector("ipx");
1631 capture_dissector_add_uint("ethertype", ETHERTYPE_IPX
, ipx_cap_handle
);
1632 capture_dissector_add_uint("ppp_hdlc", PPP_IPX
, ipx_cap_handle
);
1633 capture_dissector_add_uint("sll.ltype", LINUX_SLL_P_802_3
, ipx_cap_handle
);
1634 capture_dissector_add_uint("llc.dsap", SAP_NETWARE1
, ipx_cap_handle
);
1635 capture_dissector_add_uint("llc.dsap", SAP_NETWARE2
, ipx_cap_handle
);
1639 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1644 * indent-tabs-mode: t
1647 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1648 * :indentSize=8:tabSize=8:noTabs=false: