2 * Routines for NetWare's IPX
3 * Gilbert Ramirez <gram@xiexie.org>
5 * $Id: packet-ipx.c,v 1.46 2000/01/22 06:22:13 guy Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@zing.org>
9 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 #ifdef HAVE_SYS_TYPES_H
32 # include <sys/types.h>
38 #include "packet-ipx.h"
39 #include "packet-ncp.h"
42 #include "packet-snmp.h"
44 /* The information in this module (IPX, SPX, NCP) comes from:
45 NetWare LAN Analysis, Second Edition
46 Laura A. Chappell and Dan E. Hakes
48 Novell Press, San Jose.
51 And from the ncpfs source code by Volker Lendecke
55 static int proto_ipx = -1;
56 static int hf_ipx_checksum = -1;
57 static int hf_ipx_len = -1;
58 static int hf_ipx_hops = -1;
59 static int hf_ipx_packet_type = -1;
60 static int hf_ipx_dnet = -1;
61 static int hf_ipx_dnode = -1;
62 static int hf_ipx_dsocket = -1;
63 static int hf_ipx_snet = -1;
64 static int hf_ipx_snode = -1;
65 static int hf_ipx_ssocket = -1;
67 static gint ett_ipx = -1;
69 static int proto_spx = -1;
70 static int hf_spx_connection_control = -1;
71 static int hf_spx_datastream_type = -1;
72 static int hf_spx_src_id = -1;
73 static int hf_spx_dst_id = -1;
74 static int hf_spx_seq_nr = -1;
75 static int hf_spx_ack_nr = -1;
76 static int hf_spx_all_nr = -1;
78 static gint ett_spx = -1;
80 static int proto_ipxrip = -1;
81 static int hf_ipxrip_request = -1;
82 static int hf_ipxrip_response = -1;
84 static gint ett_ipxrip = -1;
86 static int proto_sap = -1;
87 static int hf_sap_request = -1;
88 static int hf_sap_response = -1;
90 static gint ett_ipxsap = -1;
91 static gint ett_ipxsap_server = -1;
93 static gint ett_ipxmsg = -1;
94 static int proto_ipxmsg = -1;
95 static int hf_msg_conn = -1;
96 static int hf_msg_sigchar = -1;
99 dissect_spx(const u_char *pd, int offset, frame_data *fd, proto_tree *tree);
102 dissect_ipxrip(const u_char *pd, int offset, frame_data *fd, proto_tree *tree);
105 dissect_ipxsap(const u_char *pd, int offset, frame_data *fd, proto_tree *tree);
108 dissect_ipxmsg(const u_char *pd, int offset, frame_data *fd, proto_tree *tree);
110 typedef void (dissect_func_t)(const u_char *, int, frame_data *, proto_tree *);
114 dissect_func_t *func;
128 /* ================================================================= */
130 /* ================================================================= */
132 /* info on these sockets can be found in this listing from Novell:
134 http://developer.novell.com/engsup/sample/tids/dsoc1b/dsoc1b.htm
137 #define IPX_SOCKET_NCP 0x0451
138 #define IPX_SOCKET_SAP 0x0452
139 #define IPX_SOCKET_IPXRIP 0x0453
140 #define IPX_SOCKET_NETBIOS 0x0455
141 #define IPX_SOCKET_DIAGNOSTIC 0x0456
142 #define IPX_SOCKET_SERIALIZATION 0x0457
143 #define IPX_SOCKET_NWLINK_SMB_NAMEQUERY 0x0551
144 #define IPX_SOCKET_NWLINK_SMB_DGRAM 0x0553
145 #define IPX_SOCKET_NWLINK_SMB_BROWSE 0x0555 /* ? not sure on this
146 but I guessed based on the content of the packet I saw */
147 #define IPX_SOCKET_ATTACHMATE_GW 0x055d
148 #define IPX_SOCKET_IPX_MESSAGE 0x4001
149 #define IPX_SOCKET_ADSM 0x8522 /* www.tivoli.com */
150 #define IPX_SOCKET_WIDE_AREA_ROUTER 0x9001
151 #define IPX_SOCKET_SNMP_AGENT 0x900F /* RFC 1906 */
152 #define IPX_SOCKET_SNMP_SINK 0x9010 /* RFC 1906 */
153 #define IPX_SOCKET_TCP_TUNNEL 0x9091 /* RFC 1791 */
154 #define IPX_SOCKET_UDP_TUNNEL 0x9092 /* RFC 1791 */
156 static struct port_info ports[] = {
157 { IPX_SOCKET_NCP, dissect_ncp,
159 { IPX_SOCKET_SAP, dissect_ipxsap,
161 { IPX_SOCKET_IPXRIP, dissect_ipxrip,
163 { IPX_SOCKET_NETBIOS, NULL,
165 { IPX_SOCKET_DIAGNOSTIC, NULL,
167 { IPX_SOCKET_SERIALIZATION, NULL,
169 { IPX_SOCKET_NWLINK_SMB_NAMEQUERY, NULL,
170 "NWLink SMB Name Query" },
171 { IPX_SOCKET_NWLINK_SMB_DGRAM, dissect_nwlink_dg,
172 "NWLink SMB Datagram" },
173 { IPX_SOCKET_NWLINK_SMB_BROWSE, NULL, "NWLink SMB Browse" },
174 { IPX_SOCKET_ATTACHMATE_GW, NULL, "Attachmate Gateway" },
175 { IPX_SOCKET_IPX_MESSAGE, dissect_ipxmsg, "IPX Message" },
176 { IPX_SOCKET_SNMP_AGENT, dissect_snmp, "SNMP Agent" },
177 { IPX_SOCKET_SNMP_SINK, dissect_snmp, "SNMP Sink" },
179 { IPX_SOCKET_UDP_TUNNEL, NULL, "UDP Tunnel" },
180 { IPX_SOCKET_TCP_TUNNEL, NULL, "TCP Tunnel" },
181 { IPX_SOCKET_TCP_TUNNEL, NULL, "TCP Tunnel" },
182 { IPX_SOCKET_ADSM, NULL, "ADSM" },
183 { IPX_SOCKET_WIDE_AREA_ROUTER, NULL, "Wide Area Router" },
189 port_text(guint16 port) {
192 while (ports[i].text != NULL) {
193 if (ports[i].port == port) {
194 return ports[i].text;
201 static dissect_func_t*
202 port_func(guint16 port) {
205 while (ports[i].text != NULL) {
206 if (ports[i].port == port) {
207 return ports[i].func;
217 * http://alr.base2co.com:457/netguide/dipxD.ipx_packet_struct.html
219 * which is part of SCO's "Network Programmer's Guide and Reference".
221 * It calls type 20 "NetBIOS name packet". Microsoft Network Monitor
222 * calls it "WAN Broadcast"; it's also used for SMB browser announcements,
223 * i.e. NetBIOS (broadcast) datagrams.
225 #define IPX_PACKET_TYPE_IPX 0
226 #define IPX_PACKET_TYPE_RIP 1
227 #define IPX_PACKET_TYPE_ECHO 2
228 #define IPX_PACKET_TYPE_ERROR 3
229 #define IPX_PACKET_TYPE_PEP 4
230 #define IPX_PACKET_TYPE_SPX 5
231 #define IPX_PACKET_TYPE_NCP 17
232 #define IPX_PACKET_TYPE_WANBCAST 20 /* propagated NetBIOS packet? */
234 static const value_string ipx_packet_type_vals[] = {
235 { IPX_PACKET_TYPE_IPX, "IPX" },
236 { IPX_PACKET_TYPE_RIP, "RIP" },
237 { IPX_PACKET_TYPE_ECHO, "Echo" },
238 { IPX_PACKET_TYPE_ERROR, "Error" },
239 { IPX_PACKET_TYPE_PEP, "PEP" }, /* Packet Exchange Packet */
240 { IPX_PACKET_TYPE_SPX, "SPX" },
241 { 16, "Experimental Protocol" },
242 { IPX_PACKET_TYPE_NCP, "NCP" },
243 { 18, "Experimental Protocol" },
244 { 19, "Experimental Protocol" },
245 { IPX_PACKET_TYPE_WANBCAST, "NetBIOS Broadcast" },
246 { 21, "Experimental Protocol" },
247 { 22, "Experimental Protocol" },
248 { 23, "Experimental Protocol" },
249 { 24, "Experimental Protocol" },
250 { 25, "Experimental Protocol" },
251 { 26, "Experimental Protocol" },
252 { 27, "Experimental Protocol" },
253 { 28, "Experimental Protocol" },
254 { 29, "Experimental Protocol" },
255 { 30, "Experimental Protocol" },
256 { 31, "Experimental Protocol" },
260 static const value_string ipxmsg_sigchar_vals[] = {
261 { '?', "Poll inactive station" },
266 ipxnet_to_string(const guint8 *ad)
268 guint32 addr = pntohl(ad);
269 return ipxnet_to_str_punct(addr, ' ');
272 /* We use a different representation of hardware addresses
273 * than ether_to_str(); we don't put punctuation between the hex
278 ipx_addr_to_str(guint32 net, const guint8 *ad)
280 static gchar str[3][8+1+MAXNAMELEN+1]; /* 8 digits, 1 period, NAME, 1 null */
284 if (cur == &str[0][0]) {
286 } else if (cur == &str[1][0]) {
292 name = get_ether_name_if_known(ad);
295 sprintf(cur, "%s.%s", get_ipxnet_name(net), name);
298 sprintf(cur, "%s.%s", get_ipxnet_name(net), ether_to_str_punct(ad, '\0'));
304 ipxnet_to_str_punct(const guint32 ad, char punct) {
305 static gchar str[3][12];
310 static const gchar hex_digits[16] = "0123456789ABCDEF";
311 static const guint32 octet_mask[4] =
312 { 0xff000000 , 0x00ff0000, 0x0000ff00, 0x000000ff };
314 if (cur == &str[0][0]) {
316 } else if (cur == &str[1][0]) {
325 octet = (ad & octet_mask[i]) >> ((3 - i) * 8);
326 *--p = hex_digits[octet&0xF];
328 *--p = hex_digits[octet&0xF];
339 capture_ipx(const u_char *pd, int offset, guint32 cap_len, packet_counts *ld)
345 dissect_ipx(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
347 proto_tree *ipx_tree;
349 guint8 ipx_type, ipx_hops;
350 guint16 ipx_checksum, ipx_length;
352 guint8 *ipx_snode, *ipx_dnode, *ipx_snet, *ipx_dnet;
354 guint16 ipx_dsocket, ipx_ssocket;
355 dissect_func_t *dissect;
356 guint32 ipx_dnet_val, ipx_snet_val;
358 /* Calculate here for use in pinfo and in tree */
359 ipx_dnet = (guint8*)&pd[offset+6];
360 ipx_snet = (guint8*)&pd[offset+18];
361 ipx_dnet_val = pntohl(ipx_dnet);
362 ipx_snet_val = pntohl(ipx_snet);
363 ipx_dsocket = pntohs(&pd[offset+16]);
364 ipx_ssocket = pntohs(&pd[offset+28]);
365 ipx_dnode = (guint8*)&pd[offset+10];
366 ipx_snode = (guint8*)&pd[offset+22];
367 ipx_type = pd[offset+5];
368 ipx_length = pntohs(&pd[offset+2]);
370 /* Length of IPX datagram plus headers above it. */
371 len = ipx_length + offset;
373 /* Set the payload and captured-payload lengths to the minima of
374 (the IPX length plus the length of the headers above it) and
375 the frame lengths. */
378 if (pi.captured_len > len)
379 pi.captured_len = len;
381 SET_ADDRESS(&pi.net_src, AT_IPX, 10, &pd[offset+18]);
382 SET_ADDRESS(&pi.src, AT_IPX, 10, &pd[offset+18]);
383 SET_ADDRESS(&pi.net_dst, AT_IPX, 10, &pd[offset+6]);
384 SET_ADDRESS(&pi.dst, AT_IPX, 10, &pd[offset+6]);
386 if (check_col(fd, COL_PROTOCOL))
387 col_add_str(fd, COL_PROTOCOL, "IPX");
388 if (check_col(fd, COL_INFO))
389 col_add_fstr(fd, COL_INFO, "%s (0x%04X)", port_text(ipx_dsocket),
393 ipx_checksum = pntohs(&pd[offset]);
394 ipx_hops = pd[offset+4];
396 ti = proto_tree_add_item(tree, proto_ipx, offset, 30, NULL);
397 ipx_tree = proto_item_add_subtree(ti, ett_ipx);
398 proto_tree_add_item(ipx_tree, hf_ipx_checksum, offset, 2, ipx_checksum);
399 proto_tree_add_item_format(ipx_tree, hf_ipx_len, offset+2, 2, ipx_length,
400 "Length: %d bytes", ipx_length);
401 proto_tree_add_item_format(ipx_tree, hf_ipx_hops, offset+4, 1, ipx_hops,
402 "Transport Control: %d hops", ipx_hops);
403 proto_tree_add_item(ipx_tree, hf_ipx_packet_type, offset+5, 1, ipx_type);
404 proto_tree_add_item(ipx_tree, hf_ipx_dnet, offset+6, 4, ipx_dnet_val);
405 proto_tree_add_item(ipx_tree, hf_ipx_dnode, offset+10, 6, ipx_dnode);
406 proto_tree_add_item_format(ipx_tree, hf_ipx_dsocket, offset+16, 2,
407 ipx_dsocket, "Destination Socket: %s (0x%04X)",
408 port_text(ipx_dsocket), ipx_dsocket);
409 proto_tree_add_item(ipx_tree, hf_ipx_snet, offset+18, 4, ipx_snet_val);
410 proto_tree_add_item(ipx_tree, hf_ipx_snode, offset+22, 6, ipx_snode);
411 proto_tree_add_item_format(ipx_tree, hf_ipx_ssocket, offset+28, 2,
412 ipx_ssocket, "Source Socket: %s (0x%04X)", port_text(ipx_ssocket),
418 case IPX_PACKET_TYPE_SPX:
419 dissect_spx(pd, offset, fd, tree);
422 case IPX_PACKET_TYPE_NCP:
423 /* Is the destination node 00:00:00:00:00:01 ? */
424 if (pntohl(ipx_dnode) == 0 && pntohs(ipx_dnode + 4) == 1)
425 nw_server_address = pntohl(ipx_dnet);
427 /* Is the source node 00:00:00:00:00:01 ? */
428 else if (pntohl(ipx_snode) == 0 && pntohs(ipx_snode + 4) == 1)
429 nw_server_address = pntohl(ipx_snet);
431 nw_server_address = 0;
433 dissect_ncp(pd, offset, fd, tree);
436 case IPX_PACKET_TYPE_WANBCAST:
437 case IPX_PACKET_TYPE_PEP:
438 if (ipx_dsocket == IPX_SOCKET_NETBIOS) {
439 dissect_nbipx(pd, offset, fd, tree);
442 /* else fall through */
444 case 0: /* IPX, fall through to default */
445 /* XXX - should type 0's be dissected as NBIPX
446 if they're aimed at the NetBIOS socket? */
448 dissect = port_func(ipx_dsocket);
450 dissect(pd, offset, fd, tree);
453 dissect = port_func(ipx_ssocket);
455 dissect(pd, offset, fd, tree);
458 dissect_data(pd, offset, fd, tree);
466 /* ================================================================= */
468 /* ================================================================= */
470 spx_conn_ctrl(u_char ctrl)
474 static struct conn_info conns[] = {
475 { 0x10, "End-of-Message" },
476 { 0x20, "Attention" },
477 { 0x40, "Acknowledgment Required"},
478 { 0x80, "System Packet"},
482 while (conns[i].text != NULL) {
483 if (conns[i].ctrl == ctrl) {
484 return conns[i].text;
492 spx_datastream(u_char type)
496 return "End-of-Connection";
498 return "End-of-Connection Acknowledgment";
500 return "Client-Defined";
505 dissect_spx(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
506 proto_tree *spx_tree;
509 if (check_col(fd, COL_PROTOCOL))
510 col_add_str(fd, COL_PROTOCOL, "SPX");
511 if (check_col(fd, COL_INFO))
512 col_add_str(fd, COL_INFO, "SPX");
515 ti = proto_tree_add_item(tree, proto_spx, offset, 12, NULL);
516 spx_tree = proto_item_add_subtree(ti, ett_spx);
518 proto_tree_add_item_format(spx_tree, hf_spx_connection_control,
521 "Connection Control: %s (0x%02X)",
522 spx_conn_ctrl(pd[offset]),
525 proto_tree_add_item_format(spx_tree, hf_spx_datastream_type,
528 "Datastream Type: %s (0x%02X)",
529 spx_datastream(pd[offset+1]),
532 proto_tree_add_item(spx_tree, hf_spx_src_id,
534 pntohs( &pd[offset+2] ));
536 proto_tree_add_item(spx_tree, hf_spx_dst_id,
538 pntohs( &pd[offset+4] ));
540 proto_tree_add_item(spx_tree, hf_spx_seq_nr,
542 pntohs( &pd[offset+6] ) );
544 proto_tree_add_item(spx_tree, hf_spx_ack_nr,
546 pntohs( &pd[offset+8] ) );
548 proto_tree_add_item(spx_tree, hf_spx_all_nr,
550 pntohs( &pd[offset+10] ) );
553 dissect_data(pd, offset, fd, tree);
557 /* ================================================================= */
559 /* ================================================================= */
561 dissect_ipxmsg(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
562 proto_tree *msg_tree;
564 u_char conn_number, sig_char;
566 if ( ! BYTES_ARE_IN_FRAME(offset,2) )
571 conn_number = pd[offset];
572 sig_char = pd[offset+1];
574 if (check_col(fd, COL_PROTOCOL))
575 col_add_str(fd, COL_PROTOCOL, "IPX MSG");
576 if (check_col(fd, COL_PROTOCOL)) {
577 col_add_fstr(fd, COL_INFO,
579 val_to_str(sig_char, ipxmsg_sigchar_vals, "Unknown Signature Char"), conn_number);
583 ti = proto_tree_add_item(tree, proto_ipxmsg, offset, END_OF_FRAME, NULL);
584 msg_tree = proto_item_add_subtree(ti, ett_ipxmsg);
586 proto_tree_add_item(msg_tree, hf_msg_conn, offset, 1, conn_number);
587 proto_tree_add_item(msg_tree, hf_msg_sigchar, offset+1, 1, sig_char);
592 /* ================================================================= */
594 /* ================================================================= */
596 dissect_ipxrip(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
597 proto_tree *rip_tree;
600 struct ipx_rt_def route;
603 char *rip_type[2] = { "Request", "Response" };
605 operation = pntohs(&pd[offset]) - 1;
607 if (check_col(fd, COL_PROTOCOL))
608 col_add_str(fd, COL_PROTOCOL, "IPX RIP");
609 if (check_col(fd, COL_PROTOCOL)) {
611 col_add_str(fd, COL_INFO, rip_type[operation]);
614 col_add_str(fd, COL_INFO, "Unknown Packet Type");
619 ti = proto_tree_add_item(tree, proto_ipxrip, offset, END_OF_FRAME, NULL);
620 rip_tree = proto_item_add_subtree(ti, ett_ipxrip);
623 proto_tree_add_text(rip_tree, offset, 2,
624 "RIP packet type: %s", rip_type[operation]);
626 if (operation == 0) {
627 proto_tree_add_item_hidden(rip_tree,
631 proto_tree_add_item_hidden(rip_tree,
638 proto_tree_add_text(rip_tree, offset, 2, "Unknown RIP packet type");
641 for (cursor = offset + 2; cursor < fd->cap_len; cursor += 8) {
642 memcpy(&route.network, &pd[cursor], 4);
643 route.hops = pntohs(&pd[cursor+4]);
644 route.ticks = pntohs(&pd[cursor+6]);
646 if (operation == IPX_RIP_REQUEST - 1) {
647 proto_tree_add_text(rip_tree, cursor, 8,
648 "Route Vector: %s, %d hop%s, %d tick%s",
649 ipxnet_to_string((guint8*)&route.network),
650 route.hops, route.hops == 1 ? "" : "s",
651 route.ticks, route.ticks == 1 ? "" : "s");
654 proto_tree_add_text(rip_tree, cursor, 8,
655 "Route Vector: %s, %d hop%s, %d tick%s (%d ms)",
656 ipxnet_to_string((guint8*)&route.network),
657 route.hops, route.hops == 1 ? "" : "s",
658 route.ticks, route.ticks == 1 ? "" : "s",
659 route.ticks * 1000 / 18);
667 /* ================================================================= */
669 /* ================================================================= */
671 server_type(guint16 type)
675 /* some of these are from ncpfs, others are from the book */
676 static struct server_info servers[] = {
678 { 0x0002, "User Group" },
679 { 0x0003, "Print Queue" },
680 { 0x0004, "File server" },
681 { 0x0005, "Job server" },
682 { 0x0007, "Print server" },
683 { 0x0008, "Archive server" },
684 { 0x0009, "Archive server" },
685 { 0x000a, "Job queue" },
686 { 0x000b, "Administration" },
687 { 0x0021, "NAS SNA gateway" },
688 { 0x0024, "Remote bridge" },
689 { 0x0026, "Bridge server" },
690 { 0x0027, "TCP/IP gateway" },
691 { 0x002d, "Time Synchronization VAP" },
692 { 0x002e, "Archive Server Dynamic SAP" },
693 { 0x0047, "Advertising print server" },
694 { 0x004b, "Btrieve VAP 5.0" },
695 { 0x004c, "SQL VAP" },
696 { 0x0050, "Btrieve VAP" },
697 { 0x0053, "Print Queue VAP" },
698 { 0x007a, "TES NetWare for VMS" },
699 { 0x0098, "NetWare access server" },
700 { 0x009a, "Named Pipes server" },
701 { 0x009e, "Portable NetWare Unix" },
702 { 0x0107, "NetWare 386" },
703 { 0x0111, "Test server" },
704 { 0x0133, "NetWare Name Service" },
705 { 0x0166, "NetWare management" },
706 { 0x023f, "SMS Testing and Development" },
707 { 0x026a, "NetWare management" },
708 { 0x026b, "Time synchronization" },
709 { 0x027b, "NetWare Management Agent" },
710 { 0x0278, "NetWare Directory server" },
711 { 0x030c, "HP LaserJet / Quick Silver" },
712 { 0x0355, "Arcada Software" },
713 { 0x0361, "NETINELO" },
714 { 0x037e, "Powerchute UPS Monitoring" },
715 { 0x03e1, "UnixWare Application Server" },
716 { 0x044c, "Archive" },
717 { 0x055d, "Attachmate SNA gateway" },
718 { 0x0610, "Adaptec SCSI Management" },
719 { 0x0640, "NT Server-RPC/GW for NW/Win95 User Level Sec" },
720 { 0x064e, "NT Server-IIS" },
721 { 0x0810, "ELAN License Server Demo" },
722 { 0x8002, "Intel NetPort Print Server" },
724 /* For any unidentified ones, I found a really big list of them at: */
725 /* http://www.inpnet.org/cnpweb/saplist.txt */
726 /* http://www.isi.edu/in-notes/iana/assignments/novell-sap-numbers */
731 while (servers[i].text != NULL) {
732 if (servers[i].type == type) {
733 return servers[i].text;
741 dissect_ipxsap(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
743 proto_tree *sap_tree, *s_tree;
746 struct sap_query query;
747 struct sap_server_ident server;
749 char *sap_type[4] = { "General Query", "General Response",
750 "Nearest Query", "Nearest Response" };
752 query.query_type = pntohs(&pd[offset]);
753 query.server_type = pntohs(&pd[offset+2]);
755 if (check_col(fd, COL_PROTOCOL))
756 col_add_str(fd, COL_PROTOCOL, "SAP");
757 if (check_col(fd, COL_INFO)) {
758 if (query.query_type >= 1 && query.query_type <= 4) {
759 col_add_str(fd, COL_INFO, sap_type[query.query_type - 1]);
762 col_add_str(fd, COL_INFO, "Unknown Packet Type");
767 ti = proto_tree_add_item(tree, proto_sap, offset, END_OF_FRAME, NULL);
768 sap_tree = proto_item_add_subtree(ti, ett_ipxsap);
770 if (query.query_type >= 1 && query.query_type <= 4) {
771 proto_tree_add_text(sap_tree, offset, 2, sap_type[query.query_type - 1]);
772 if ((query.query_type - 1) % 2) {
773 proto_tree_add_item_hidden(sap_tree,
777 proto_tree_add_item_hidden(sap_tree,
783 proto_tree_add_text(sap_tree, offset, 2,
784 "Unknown SAP Packet Type %d", query.query_type);
787 if (query.query_type == IPX_SAP_GENERAL_RESPONSE ||
788 query.query_type == IPX_SAP_NEAREST_RESPONSE) { /* responses */
790 for (cursor = offset + 2; (cursor + 64) <= fd->cap_len; cursor += 64) {
791 server.server_type = pntohs(&pd[cursor]);
792 memcpy(server.server_name, &pd[cursor+2], 48);
793 memcpy(&server.server_network, &pd[cursor+50], 4);
794 memcpy(&server.server_node, &pd[cursor+54], 6);
795 server.server_port = pntohs(&pd[cursor+60]);
796 server.intermediate_network = pntohs(&pd[cursor+62]);
798 ti = proto_tree_add_text(sap_tree, cursor+2, 48,
799 "Server Name: %s", server.server_name);
800 s_tree = proto_item_add_subtree(ti, ett_ipxsap_server);
802 proto_tree_add_text(s_tree, cursor, 2, "Server Type: %s (0x%04X)",
803 server_type(server.server_type), server.server_type);
804 proto_tree_add_text(s_tree, cursor+50, 4, "Network: %s",
805 ipxnet_to_string((guint8*)&pd[cursor+50]));
806 proto_tree_add_text(s_tree, cursor+54, 6, "Node: %s",
807 ether_to_str((guint8*)&pd[cursor+54]));
808 proto_tree_add_text(s_tree, cursor+60, 2, "Socket: %s (0x%04X)",
809 port_text(server.server_port), server.server_port);
810 proto_tree_add_text(s_tree, cursor+62, 2,
811 "Intermediate Networks: %d",
812 server.intermediate_network);
816 proto_tree_add_text(sap_tree, offset+2, 2, "Server Type: %s (0x%04X)",
817 server_type(query.server_type), query.server_type);
824 proto_register_ipx(void)
826 static hf_register_info hf_ipx[] = {
828 { "Checksum", "ipx.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
832 { "Length", "ipx.len", FT_UINT16, BASE_DEC, NULL, 0x0,
836 { "Transport Control (Hops)", "ipx.hops", FT_UINT8, BASE_DEC, NULL, 0x0,
839 { &hf_ipx_packet_type,
840 { "Packet Type", "ipx.packet_type", FT_UINT8, BASE_HEX, VALS(ipx_packet_type_vals),
845 { "Destination Network","ipx.dst.net", FT_IPXNET, BASE_NONE, NULL, 0x0,
849 { "Destination Node", "ipx.dst.node", FT_ETHER, BASE_NONE, NULL, 0x0,
853 { "Destination Socket", "ipx.dst.socket", FT_UINT16, BASE_HEX, NULL, 0x0,
857 { "Source Network","ipx.src.net", FT_IPXNET, BASE_NONE, NULL, 0x0,
861 { "Source Node", "ipx.src.node", FT_ETHER, BASE_NONE, NULL, 0x0,
865 { "Source Socket", "ipx.src.socket", FT_UINT16, BASE_HEX, NULL, 0x0,
869 static hf_register_info hf_spx[] = {
870 { &hf_spx_connection_control,
871 { "Connection Control", "spx.ctl",
872 FT_UINT8, BASE_HEX, NULL, 0x0,
875 { &hf_spx_datastream_type,
876 { "Datastream type", "spx.type",
877 FT_UINT8, BASE_HEX, NULL, 0x0,
881 { "Source Connection ID", "spx.src",
882 FT_UINT16, BASE_DEC, NULL, 0x0,
886 { "Destination Connection ID", "spx.dst",
887 FT_UINT16, BASE_DEC, NULL, 0x0,
891 { "Sequence Number", "spx.seq",
892 FT_UINT16, BASE_DEC, NULL, 0x0,
896 { "Acknowledgment Number", "spx.ack",
897 FT_UINT16, BASE_DEC, NULL, 0x0,
901 { "Allocation Number", "spx.alloc",
902 FT_UINT16, BASE_DEC, NULL, 0x0,
906 static hf_register_info hf_ipxrip[] = {
907 { &hf_ipxrip_request,
908 { "Request", "ipxrip.request",
909 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
910 "TRUE if IPX RIP request" }},
912 { &hf_ipxrip_response,
913 { "Response", "ipxrip.response",
914 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
915 "TRUE if IPX RIP response" }}
918 static hf_register_info hf_sap[] = {
920 { "Request", "sap.request",
921 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
922 "TRUE if SAP request" }},
925 { "Response", "sap.response",
926 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
927 "TRUE if SAP response" }}
930 static hf_register_info hf_ipxmsg[] = {
932 { "Connection Number", "ipxmsg.conn",
933 FT_UINT8, BASE_NONE, NULL, 0x0,
934 "Connection Number" }},
937 { "Signature Char", "ipxmsg.sigchar",
938 FT_UINT8, BASE_NONE, VALS(ipxmsg_sigchar_vals), 0x0,
942 static gint *ett[] = {
951 proto_ipx = proto_register_protocol ("Internetwork Packet eXchange", "ipx");
952 proto_register_field_array(proto_ipx, hf_ipx, array_length(hf_ipx));
954 proto_spx = proto_register_protocol ("Sequenced Packet eXchange", "spx");
955 proto_register_field_array(proto_spx, hf_spx, array_length(hf_spx));
957 proto_ipxrip = proto_register_protocol ("IPX Routing Information Protocol", "ipxrip");
958 proto_register_field_array(proto_ipxrip, hf_ipxrip, array_length(hf_ipxrip));
960 proto_ipxmsg = proto_register_protocol ("IPX Message", "ipxmsg");
961 proto_register_field_array(proto_ipxmsg, hf_ipxmsg, array_length(hf_ipxmsg));
963 proto_sap = proto_register_protocol ("Service Advertisement Protocol", "sap");
964 proto_register_field_array(proto_sap, hf_sap, array_length(hf_sap));
966 proto_register_subtree_array(ett, array_length(ett));