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