2 * Routines for NetWare's IPX
3 * Gilbert Ramirez <gram@verdict.uthscsa.edu>
5 * $Id: packet-ipx.c,v 1.38 1999/11/30 09:01:55 guy Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@unicom.net>
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 /* The information in this module (IPX, SPX, NCP) comes from:
43 NetWare LAN Analysis, Second Edition
44 Laura A. Chappell and Dan E. Hakes
46 Novell Press, San Jose.
49 And from the ncpfs source code by Volker Lendecke
53 static int proto_ipx = -1;
54 static int hf_ipx_checksum = -1;
55 static int hf_ipx_len = -1;
56 static int hf_ipx_hops = -1;
57 static int hf_ipx_packet_type = -1;
58 static int hf_ipx_dnet = -1;
59 static int hf_ipx_dnode = -1;
60 static int hf_ipx_dsocket = -1;
61 static int hf_ipx_snet = -1;
62 static int hf_ipx_snode = -1;
63 static int hf_ipx_ssocket = -1;
65 static gint ett_ipx = -1;
67 static int proto_spx = -1;
68 static int hf_spx_connection_control = -1;
69 static int hf_spx_datastream_type = -1;
70 static int hf_spx_src_id = -1;
71 static int hf_spx_dst_id = -1;
72 static int hf_spx_seq_nr = -1;
73 static int hf_spx_ack_nr = -1;
74 static int hf_spx_all_nr = -1;
76 static gint ett_spx = -1;
78 static int proto_ipxrip = -1;
79 static int hf_ipxrip_request = -1;
80 static int hf_ipxrip_response = -1;
82 static gint ett_ipxrip = -1;
84 static int proto_sap = -1;
85 static int hf_sap_request = -1;
86 static int hf_sap_response = -1;
88 static gint ett_ipxsap = -1;
89 static gint ett_ipxsap_server = -1;
92 dissect_spx(const u_char *pd, int offset, frame_data *fd, proto_tree *tree);
95 dissect_ipxrip(const u_char *pd, int offset, frame_data *fd, proto_tree *tree);
98 dissect_ipxsap(const u_char *pd, int offset, frame_data *fd, proto_tree *tree);
100 typedef void (dissect_func_t)(const u_char *, int, frame_data *, proto_tree *);
104 dissect_func_t *func;
118 /* ================================================================= */
120 /* ================================================================= */
122 #define IPX_SOCKET_NCP 0x0451
123 #define IPX_SOCKET_SAP 0x0452
124 #define IPX_SOCKET_IPXRIP 0x0453
125 #define IPX_SOCKET_NETBIOS 0x0455
126 #define IPX_SOCKET_DIAGNOSTIC 0x0456
127 #define IPX_SOCKET_SERIALIZATION 0x0457
128 #define IPX_SOCKET_NWLINK_SMB_NAMEQUERY 0x0551
129 #define IPX_SOCKET_NWLINK_SMB_DGRAM 0x0553
130 #define IPX_SOCKET_NWLINK_SMB_BROWSE 0x0555 /* ? not sure on this
131 but I guessed based on the content of the packet I saw */
132 #define IPX_SOCKET_ATTACHMATE_GW 0x055d
133 #define IPX_SOCKET_IPX_MESSAGE 0x4001
134 #define IPX_SOCKET_ADSM 0x8522 /* www.tivoli.com */
135 #define IPX_SOCKET_SNMP_AGENT 0x900F /* RFC 1906 */
136 #define IPX_SOCKET_SNMP_SINK 0x9010 /* RFC 1906 */
137 #define IPX_SOCKET_TCP_TUNNEL 0x9091 /* RFC 1791 */
138 #define IPX_SOCKET_UDP_TUNNEL 0x9092 /* RFC 1791 */
140 static struct port_info ports[] = {
141 { IPX_SOCKET_NCP, dissect_ncp,
143 { IPX_SOCKET_SAP, dissect_ipxsap,
145 { IPX_SOCKET_IPXRIP, dissect_ipxrip,
147 { IPX_SOCKET_NETBIOS, NULL,
149 { IPX_SOCKET_DIAGNOSTIC, NULL,
151 { IPX_SOCKET_SERIALIZATION, NULL,
153 { IPX_SOCKET_NWLINK_SMB_NAMEQUERY, NULL,
154 "NWLink SMB Name Query" },
155 { IPX_SOCKET_NWLINK_SMB_DGRAM, dissect_nwlink_dg,
156 "NWLink SMB Datagram" },
157 { IPX_SOCKET_NWLINK_SMB_BROWSE, NULL,
158 "NWLink SMB Browse" },
159 { IPX_SOCKET_ATTACHMATE_GW, NULL,
160 "Attachmate Gateway" },
161 { IPX_SOCKET_IPX_MESSAGE, NULL,
163 { IPX_SOCKET_SNMP_AGENT, NULL, "SNMP Agent" },
164 { IPX_SOCKET_SNMP_SINK, NULL, "SNMP Sink" },
165 { IPX_SOCKET_UDP_TUNNEL, NULL, "UDP Tunnel" },
166 { IPX_SOCKET_TCP_TUNNEL, NULL, "TCP Tunnel" },
167 { IPX_SOCKET_TCP_TUNNEL, NULL, "TCP Tunnel" },
168 { IPX_SOCKET_ADSM, NULL, "ADSM" },
174 port_text(guint16 port) {
177 while (ports[i].text != NULL) {
178 if (ports[i].port == port) {
179 return ports[i].text;
186 static dissect_func_t*
187 port_func(guint16 port) {
190 while (ports[i].text != NULL) {
191 if (ports[i].port == port) {
192 return ports[i].func;
202 * http://alr.base2co.com:457/netguide/dipxD.ipx_packet_struct.html
204 * which is part of SCO's "Network Programmer's Guide and Reference".
206 * It calls type 20 "NetBIOS name packet". Microsoft Network Monitor
207 * calls it "WAN Broadcast"; it's also used for SMB browser announcements,
208 * i.e. NetBIOS (broadcast) datagrams.
210 #define IPX_PACKET_TYPE_IPX 0
211 #define IPX_PACKET_TYPE_RIP 1
212 #define IPX_PACKET_TYPE_ECHO 2
213 #define IPX_PACKET_TYPE_ERROR 3
214 #define IPX_PACKET_TYPE_PEP 4
215 #define IPX_PACKET_TYPE_SPX 5
216 #define IPX_PACKET_TYPE_NCP 17
217 #define IPX_PACKET_TYPE_WANBCAST 20 /* propagated NetBIOS packet? */
219 static const value_string ipx_packet_type_vals[] = {
220 { IPX_PACKET_TYPE_IPX, "IPX" },
221 { IPX_PACKET_TYPE_RIP, "RIP" },
222 { IPX_PACKET_TYPE_ECHO, "Echo" },
223 { IPX_PACKET_TYPE_ERROR, "Error" },
224 { IPX_PACKET_TYPE_PEP, "PEP" }, /* Packet Exchange Packet */
225 { IPX_PACKET_TYPE_SPX, "SPX" },
226 { 16, "Experimental Protocol" },
227 { IPX_PACKET_TYPE_NCP, "NCP" },
228 { 18, "Experimental Protocol" },
229 { 19, "Experimental Protocol" },
230 { IPX_PACKET_TYPE_WANBCAST, "NetBIOS Broadcast" },
231 { 21, "Experimental Protocol" },
232 { 22, "Experimental Protocol" },
233 { 23, "Experimental Protocol" },
234 { 24, "Experimental Protocol" },
235 { 25, "Experimental Protocol" },
236 { 26, "Experimental Protocol" },
237 { 27, "Experimental Protocol" },
238 { 28, "Experimental Protocol" },
239 { 29, "Experimental Protocol" },
240 { 30, "Experimental Protocol" },
241 { 31, "Experimental Protocol" },
246 ipxnet_to_string(const guint8 *ad)
248 guint32 addr = pntohl(ad);
249 return ipxnet_to_str_punct(addr, ' ');
252 /* We use a different representation of hardware addresses
253 * than ether_to_str(); we don't put punctuation between the hex
258 ipx_addr_to_str(guint32 net, const guint8 *ad)
260 static gchar str[3][8+1+MAXNAMELEN+1]; /* 8 digits, 1 period, NAME, 1 null */
264 if (cur == &str[0][0]) {
266 } else if (cur == &str[1][0]) {
272 name = get_ether_name_if_known(ad);
275 sprintf(cur, "%s.%s", get_ipxnet_name(net), name);
278 sprintf(cur, "%s.%s", get_ipxnet_name(net), ether_to_str_punct(ad, '\0'));
284 ipxnet_to_str_punct(const guint32 ad, char punct) {
285 static gchar str[3][12];
290 static const gchar hex_digits[16] = "0123456789ABCDEF";
291 static const guint32 octet_mask[4] =
292 { 0xff000000 , 0x00ff0000, 0x0000ff00, 0x000000ff };
294 if (cur == &str[0][0]) {
296 } else if (cur == &str[1][0]) {
305 octet = (ad & octet_mask[i]) >> ((3 - i) * 8);
306 *--p = hex_digits[octet&0xF];
308 *--p = hex_digits[octet&0xF];
319 dissect_ipx(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
321 proto_tree *ipx_tree;
323 guint8 ipx_type, ipx_hops;
324 guint16 ipx_checksum, ipx_length;
326 guint8 *ipx_snode, *ipx_dnode, *ipx_snet, *ipx_dnet;
328 guint16 ipx_dsocket, ipx_ssocket;
329 dissect_func_t *dissect;
330 guint32 ipx_dnet_val, ipx_snet_val;
332 /* Calculate here for use in pinfo and in tree */
333 ipx_dnet = (guint8*)&pd[offset+6];
334 ipx_snet = (guint8*)&pd[offset+18];
335 ipx_dnet_val = pntohl(ipx_dnet);
336 ipx_snet_val = pntohl(ipx_snet);
337 ipx_dsocket = pntohs(&pd[offset+16]);
338 ipx_ssocket = pntohs(&pd[offset+28]);
339 ipx_dnode = (guint8*)&pd[offset+10];
340 ipx_snode = (guint8*)&pd[offset+22];
341 ipx_type = pd[offset+5];
342 ipx_length = pntohs(&pd[offset+2]);
344 /* Length of IPX datagram plus headers above it. */
345 len = ipx_length + offset;
347 /* Set the payload and captured-payload lengths to the minima of
348 (the IPX length plus the length of the headers above it) and
349 the frame lengths. */
352 if (pi.captured_len > len)
353 pi.captured_len = len;
355 SET_ADDRESS(&pi.net_src, AT_IPX, 10, &pd[offset+18]);
356 SET_ADDRESS(&pi.src, AT_IPX, 10, &pd[offset+18]);
357 SET_ADDRESS(&pi.net_dst, AT_IPX, 10, &pd[offset+6]);
358 SET_ADDRESS(&pi.dst, AT_IPX, 10, &pd[offset+6]);
360 if (check_col(fd, COL_PROTOCOL))
361 col_add_str(fd, COL_PROTOCOL, "IPX");
362 if (check_col(fd, COL_INFO))
363 col_add_fstr(fd, COL_INFO, "%s (0x%04X)", port_text(ipx_dsocket),
367 ipx_checksum = pntohs(&pd[offset]);
368 ipx_hops = pd[offset+4];
370 ti = proto_tree_add_item(tree, proto_ipx, offset, 30, NULL);
371 ipx_tree = proto_item_add_subtree(ti, ett_ipx);
372 proto_tree_add_item(ipx_tree, hf_ipx_checksum, offset, 2, ipx_checksum);
373 proto_tree_add_item_format(ipx_tree, hf_ipx_len, offset+2, 2, ipx_length,
374 "Length: %d bytes", ipx_length);
375 proto_tree_add_item_format(ipx_tree, hf_ipx_hops, offset+4, 1, ipx_hops,
376 "Transport Control: %d hops", ipx_hops);
377 proto_tree_add_item(ipx_tree, hf_ipx_packet_type, offset+5, 1, ipx_type);
378 proto_tree_add_item(ipx_tree, hf_ipx_dnet, offset+6, 4, ipx_dnet_val);
379 proto_tree_add_item(ipx_tree, hf_ipx_dnode, offset+10, 6, ipx_dnode);
380 proto_tree_add_item_format(ipx_tree, hf_ipx_dsocket, offset+16, 2,
381 ipx_dsocket, "Destination Socket: %s (0x%04X)",
382 port_text(ipx_dsocket), ipx_dsocket);
383 proto_tree_add_item(ipx_tree, hf_ipx_snet, offset+18, 4, ipx_snet_val);
384 proto_tree_add_item(ipx_tree, hf_ipx_snode, offset+22, 6, ipx_snode);
385 proto_tree_add_item_format(ipx_tree, hf_ipx_ssocket, offset+28, 2,
386 ipx_ssocket, "Source Socket: %s (0x%04X)", port_text(ipx_ssocket),
392 case IPX_PACKET_TYPE_SPX:
393 dissect_spx(pd, offset, fd, tree);
396 case IPX_PACKET_TYPE_NCP:
397 /* Is the destination node 00:00:00:00:00:01 ? */
398 if (pntohl(ipx_dnode) == 0 && pntohs(ipx_dnode + 4) == 1)
399 nw_server_address = pntohl(ipx_dnet);
401 /* Is the source node 00:00:00:00:00:01 ? */
402 else if (pntohl(ipx_snode) == 0 && pntohs(ipx_snode + 4) == 1)
403 nw_server_address = pntohl(ipx_snet);
405 nw_server_address = 0;
407 dissect_ncp(pd, offset, fd, tree);
410 case IPX_PACKET_TYPE_WANBCAST:
411 case IPX_PACKET_TYPE_PEP:
412 if (ipx_dsocket == IPX_SOCKET_NETBIOS) {
413 dissect_nbipx(pd, offset, fd, tree);
416 /* else fall through */
418 case 0: /* IPX, fall through to default */
419 /* XXX - should type 0's be dissected as NBIPX
420 if they're aimed at the NetBIOS socket? */
422 dissect = port_func(ipx_dsocket);
424 dissect(pd, offset, fd, tree);
427 dissect = port_func(ipx_ssocket);
429 dissect(pd, offset, fd, tree);
432 dissect_data(pd, offset, fd, tree);
440 /* ================================================================= */
442 /* ================================================================= */
444 spx_conn_ctrl(u_char ctrl)
448 static struct conn_info conns[] = {
449 { 0x10, "End-of-Message" },
450 { 0x20, "Attention" },
451 { 0x40, "Acknowledgment Required"},
452 { 0x80, "System Packet"},
456 while (conns[i].text != NULL) {
457 if (conns[i].ctrl == ctrl) {
458 return conns[i].text;
466 spx_datastream(u_char type)
470 return "End-of-Connection";
472 return "End-of-Connection Acknowledgment";
474 return "Client-Defined";
479 dissect_spx(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
480 proto_tree *spx_tree;
483 if (check_col(fd, COL_PROTOCOL))
484 col_add_str(fd, COL_PROTOCOL, "SPX");
485 if (check_col(fd, COL_INFO))
486 col_add_str(fd, COL_INFO, "SPX");
489 ti = proto_tree_add_item(tree, proto_spx, offset, 12, NULL);
490 spx_tree = proto_item_add_subtree(ti, ett_spx);
492 proto_tree_add_item_format(spx_tree, hf_spx_connection_control,
495 "Connection Control: %s (0x%02X)",
496 spx_conn_ctrl(pd[offset]),
499 proto_tree_add_item_format(spx_tree, hf_spx_datastream_type,
502 "Datastream Type: %s (0x%02X)",
503 spx_datastream(pd[offset+1]),
506 proto_tree_add_item(spx_tree, hf_spx_src_id,
508 pntohs( &pd[offset+2] ));
510 proto_tree_add_item(spx_tree, hf_spx_dst_id,
512 pntohs( &pd[offset+4] ));
514 proto_tree_add_item(spx_tree, hf_spx_seq_nr,
516 pntohs( &pd[offset+6] ) );
518 proto_tree_add_item(spx_tree, hf_spx_ack_nr,
520 pntohs( &pd[offset+8] ) );
522 proto_tree_add_item(spx_tree, hf_spx_all_nr,
524 pntohs( &pd[offset+10] ) );
527 dissect_data(pd, offset, fd, tree);
531 /* ================================================================= */
533 /* ================================================================= */
535 dissect_ipxrip(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
536 proto_tree *rip_tree;
539 struct ipx_rt_def route;
542 char *rip_type[2] = { "Request", "Response" };
544 operation = pntohs(&pd[offset]) - 1;
546 if (check_col(fd, COL_PROTOCOL))
547 col_add_str(fd, COL_PROTOCOL, "IPX RIP");
548 if (check_col(fd, COL_PROTOCOL)) {
550 col_add_str(fd, COL_INFO, rip_type[operation]);
553 col_add_str(fd, COL_INFO, "Unknown Packet Type");
558 ti = proto_tree_add_item(tree, proto_ipxrip, offset, END_OF_FRAME, NULL);
559 rip_tree = proto_item_add_subtree(ti, ett_ipxrip);
562 proto_tree_add_text(rip_tree, offset, 2,
563 "RIP packet type: %s", rip_type[operation]);
565 if (operation == 0) {
566 proto_tree_add_item_hidden(rip_tree,
570 proto_tree_add_item_hidden(rip_tree,
577 proto_tree_add_text(rip_tree, offset, 2, "Unknown RIP packet type");
580 for (cursor = offset + 2; cursor < fd->cap_len; cursor += 8) {
581 memcpy(&route.network, &pd[cursor], 4);
582 route.hops = pntohs(&pd[cursor+4]);
583 route.ticks = pntohs(&pd[cursor+6]);
585 if (operation == IPX_RIP_REQUEST - 1) {
586 proto_tree_add_text(rip_tree, cursor, 8,
587 "Route Vector: %s, %d hop%s, %d tick%s",
588 ipxnet_to_string((guint8*)&route.network),
589 route.hops, route.hops == 1 ? "" : "s",
590 route.ticks, route.ticks == 1 ? "" : "s");
593 proto_tree_add_text(rip_tree, cursor, 8,
594 "Route Vector: %s, %d hop%s, %d tick%s (%d ms)",
595 ipxnet_to_string((guint8*)&route.network),
596 route.hops, route.hops == 1 ? "" : "s",
597 route.ticks, route.ticks == 1 ? "" : "s",
598 route.ticks * 1000 / 18);
606 /* ================================================================= */
608 /* ================================================================= */
610 server_type(guint16 type)
614 /* some of these are from ncpfs, others are from the book */
615 static struct server_info servers[] = {
617 { 0x0002, "User Group" },
618 { 0x0003, "Print Queue" },
619 { 0x0004, "File server" },
620 { 0x0005, "Job server" },
621 { 0x0007, "Print server" },
622 { 0x0008, "Archive server" },
623 { 0x0009, "Archive server" },
624 { 0x000a, "Job queue" },
625 { 0x000b, "Administration" },
626 { 0x0021, "NAS SNA gateway" },
627 { 0x0024, "Remote bridge" },
628 { 0x0026, "Bridge server" },
629 { 0x0027, "TCP/IP gateway" },
630 { 0x002d, "Time Synchronization VAP" },
631 { 0x002e, "Archive Server Dynamic SAP" },
632 { 0x0047, "Advertising print server" },
633 { 0x004b, "Btrieve VAP 5.0" },
634 { 0x004c, "SQL VAP" },
635 { 0x0050, "Btrieve VAP" },
636 { 0x0053, "Print Queue VAP" },
637 { 0x007a, "TES NetWare for VMS" },
638 { 0x0098, "NetWare access server" },
639 { 0x009a, "Named Pipes server" },
640 { 0x009e, "Portable NetWare Unix" },
641 { 0x0107, "NetWare 386" },
642 { 0x0111, "Test server" },
643 { 0x0133, "NetWare Name Service" },
644 { 0x0166, "NetWare management" },
645 { 0x023f, "SMS Testing and Development" },
646 { 0x026a, "NetWare management" },
647 { 0x026b, "Time synchronization" },
648 { 0x027b, "NetWare Management Agent" },
649 { 0x0278, "NetWare Directory server" },
650 { 0x030c, "HP LaserJet / Quick Silver" },
651 { 0x0355, "Arcada Software" },
652 { 0x0361, "NETINELO" },
653 { 0x037e, "Powerchute UPS Monitoring" },
654 { 0x03e1, "UnixWare Application Server" },
655 { 0x044c, "Archive" },
656 { 0x055d, "Attachmate SNA gateway" },
657 { 0x0610, "Adaptec SCSI Management" },
658 { 0x0640, "NT Server-RPC/GW for NW/Win95 User Level Sec" },
659 { 0x064e, "NT Server-IIS" },
660 { 0x0810, "ELAN License Server Demo" },
661 { 0x8002, "Intel NetPort Print Server" },
663 /* For any unidentified ones, I found a really big list of them at: */
664 /* http://www.inpnet.org/cnpweb/saplist.txt */
665 /* http://www.isi.edu/in-notes/iana/assignments/novell-sap-numbers */
670 while (servers[i].text != NULL) {
671 if (servers[i].type == type) {
672 return servers[i].text;
680 dissect_ipxsap(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
682 proto_tree *sap_tree, *s_tree;
685 struct sap_query query;
686 struct sap_server_ident server;
688 char *sap_type[4] = { "General Query", "General Response",
689 "Nearest Query", "Nearest Response" };
691 query.query_type = pntohs(&pd[offset]);
692 query.server_type = pntohs(&pd[offset+2]);
694 if (check_col(fd, COL_PROTOCOL))
695 col_add_str(fd, COL_PROTOCOL, "SAP");
696 if (check_col(fd, COL_INFO)) {
697 if (query.query_type >= 1 && query.query_type <= 4) {
698 col_add_str(fd, COL_INFO, sap_type[query.query_type - 1]);
701 col_add_str(fd, COL_INFO, "Unknown Packet Type");
706 ti = proto_tree_add_item(tree, proto_sap, offset, END_OF_FRAME, NULL);
707 sap_tree = proto_item_add_subtree(ti, ett_ipxsap);
709 if (query.query_type >= 1 && query.query_type <= 4) {
710 proto_tree_add_text(sap_tree, offset, 2, sap_type[query.query_type - 1]);
711 if ((query.query_type - 1) % 2) {
712 proto_tree_add_item_hidden(sap_tree,
716 proto_tree_add_item_hidden(sap_tree,
722 proto_tree_add_text(sap_tree, offset, 2,
723 "Unknown SAP Packet Type %d", query.query_type);
726 if (query.query_type == IPX_SAP_GENERAL_RESPONSE ||
727 query.query_type == IPX_SAP_NEAREST_RESPONSE) { /* responses */
729 for (cursor = offset + 2; (cursor + 64) <= fd->cap_len; cursor += 64) {
730 server.server_type = pntohs(&pd[cursor]);
731 memcpy(server.server_name, &pd[cursor+2], 48);
732 memcpy(&server.server_network, &pd[cursor+50], 4);
733 memcpy(&server.server_node, &pd[cursor+54], 6);
734 server.server_port = pntohs(&pd[cursor+60]);
735 server.intermediate_network = pntohs(&pd[cursor+62]);
737 ti = proto_tree_add_text(sap_tree, cursor+2, 48,
738 "Server Name: %s", server.server_name);
739 s_tree = proto_item_add_subtree(ti, ett_ipxsap_server);
741 proto_tree_add_text(s_tree, cursor, 2, "Server Type: %s (0x%04X)",
742 server_type(server.server_type), server.server_type);
743 proto_tree_add_text(s_tree, cursor+50, 4, "Network: %s",
744 ipxnet_to_string((guint8*)&pd[cursor+50]));
745 proto_tree_add_text(s_tree, cursor+54, 6, "Node: %s",
746 ether_to_str((guint8*)&pd[cursor+54]));
747 proto_tree_add_text(s_tree, cursor+60, 2, "Socket: %s (0x%04X)",
748 port_text(server.server_port), server.server_port);
749 proto_tree_add_text(s_tree, cursor+62, 2,
750 "Intermediate Networks: %d",
751 server.intermediate_network);
755 proto_tree_add_text(sap_tree, offset+2, 2, "Server Type: %s (0x%04X)",
756 server_type(query.server_type), query.server_type);
763 proto_register_ipx(void)
765 static hf_register_info hf_ipx[] = {
767 { "Checksum", "ipx.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
771 { "Length", "ipx.len", FT_UINT16, BASE_DEC, NULL, 0x0,
775 { "Transport Control (Hops)", "ipx.hops", FT_UINT8, BASE_DEC, NULL, 0x0,
778 { &hf_ipx_packet_type,
779 { "Packet Type", "ipx.packet_type", FT_UINT8, BASE_HEX, VALS(ipx_packet_type_vals),
784 { "Destination Network","ipx.dst.net", FT_IPXNET, BASE_NONE, NULL, 0x0,
788 { "Destination Node", "ipx.dst.node", FT_ETHER, BASE_NONE, NULL, 0x0,
792 { "Destination Socket", "ipx.dst.socket", FT_UINT16, BASE_HEX, NULL, 0x0,
796 { "Source Network","ipx.src.net", FT_IPXNET, BASE_NONE, NULL, 0x0,
800 { "Source Node", "ipx.src.node", FT_ETHER, BASE_NONE, NULL, 0x0,
804 { "Source Socket", "ipx.src.socket", FT_UINT16, BASE_HEX, NULL, 0x0,
808 static hf_register_info hf_spx[] = {
809 { &hf_spx_connection_control,
810 { "Connection Control", "spx.ctl",
811 FT_UINT8, BASE_HEX, NULL, 0x0,
814 { &hf_spx_datastream_type,
815 { "Datastream type", "spx.type",
816 FT_UINT8, BASE_HEX, NULL, 0x0,
820 { "Source Connection ID", "spx.src",
821 FT_UINT16, BASE_DEC, NULL, 0x0,
825 { "Destination Connection ID", "spx.dst",
826 FT_UINT16, BASE_DEC, NULL, 0x0,
830 { "Sequence Number", "spx.seq",
831 FT_UINT16, BASE_DEC, NULL, 0x0,
835 { "Acknowledgment Number", "spx.ack",
836 FT_UINT16, BASE_DEC, NULL, 0x0,
840 { "Allocation Number", "spx.alloc",
841 FT_UINT16, BASE_DEC, NULL, 0x0,
845 static hf_register_info hf_ipxrip[] = {
846 { &hf_ipxrip_request,
847 { "Request", "ipxrip.request",
848 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
849 "TRUE if IPX RIP request" }},
851 { &hf_ipxrip_response,
852 { "Response", "ipxrip.response",
853 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
854 "TRUE if IPX RIP response" }}
857 static hf_register_info hf_sap[] = {
859 { "Request", "sap.request",
860 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
861 "TRUE if SAP request" }},
864 { "Response", "sap.response",
865 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
866 "TRUE if SAP response" }}
868 static gint *ett[] = {
876 proto_ipx = proto_register_protocol ("Internetwork Packet eXchange", "ipx");
877 proto_register_field_array(proto_ipx, hf_ipx, array_length(hf_ipx));
879 proto_spx = proto_register_protocol ("Sequenced Packet eXchange", "spx");
880 proto_register_field_array(proto_spx, hf_spx, array_length(hf_spx));
882 proto_ipxrip = proto_register_protocol ("IPX Routing Information Protocol", "ipxrip");
883 proto_register_field_array(proto_ipxrip, hf_ipxrip, array_length(hf_ipxrip));
885 proto_sap = proto_register_protocol ("Service Advertisement Protocol", "sap");
886 proto_register_field_array(proto_sap, hf_sap, array_length(hf_sap));
888 proto_register_subtree_array(ett, array_length(ett));