2 * Routines for NetWare's IPX
3 * Gilbert Ramirez <gram@verdict.uthscsa.edu>
5 * $Id: packet-ipx.c,v 1.34 1999/11/20 05:35:13 gram 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;
199 #define IPX_PACKET_TYPE_IPX 0
200 #define IPX_PACKET_TYPE_IPX_4 4
201 #define IPX_PACKET_TYPE_SPX 5
202 #define IPX_PACKET_TYPE_NCP 17
203 #define IPX_PACKET_TYPE_WANBCAST 20
205 static const value_string ipx_packet_type_vals[] = {
206 { IPX_PACKET_TYPE_IPX, "IPX" },
207 { IPX_PACKET_TYPE_IPX_4, "IPX" },
208 /* NetMon calls it "IPX" */
209 { IPX_PACKET_TYPE_SPX, "SPX" },
210 { 16, "Experimental Protocol" },
211 { IPX_PACKET_TYPE_NCP, "NCP" },
212 { 18, "Experimental Protocol" },
213 { 19, "Experimental Protocol" },
214 { IPX_PACKET_TYPE_WANBCAST, "NetBIOS Broadcast" },
215 /* NetMon calls it "WAN Broadcast" */
216 { 21, "Experimental Protocol" },
217 { 22, "Experimental Protocol" },
218 { 23, "Experimental Protocol" },
219 { 24, "Experimental Protocol" },
220 { 25, "Experimental Protocol" },
221 { 26, "Experimental Protocol" },
222 { 27, "Experimental Protocol" },
223 { 28, "Experimental Protocol" },
224 { 29, "Experimental Protocol" },
225 { 30, "Experimental Protocol" },
226 { 31, "Experimental Protocol" },
231 ipxnet_to_string(const guint8 *ad)
233 static gchar str[3][8+3+1]; /* 8 digits, 3 spaces, 1 null */
236 if (cur == &str[0][0]) {
238 } else if (cur == &str[1][0]) {
244 sprintf(cur, "%02X %02X %02X %02X", ad[0], ad[1], ad[2], ad[3]);
248 /* We use a different representation of hardware addresses
249 * than ether_to_str(); we don't put punctuation between the hex
254 ipx_addr_to_str(guint32 net, const guint8 *ad)
256 static gchar str[3][8+1+MAXNAMELEN+1]; /* 8 digits, 1 period, NAME, 1 null */
260 if (cur == &str[0][0]) {
262 } else if (cur == &str[1][0]) {
268 name = get_ether_name_if_known(ad);
271 sprintf(cur, "%X.%s", net, name);
274 sprintf(cur, "%X.%s", net, ether_to_str_punct(ad, '\0'));
280 dissect_ipx(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
282 proto_tree *ipx_tree;
284 guint8 ipx_type, ipx_hops;
285 guint16 ipx_checksum, ipx_length;
287 guint8 *ipx_snode, *ipx_dnode, *ipx_snet, *ipx_dnet;
289 gchar *str_dnet, *str_snet;
290 guint16 ipx_dsocket, ipx_ssocket;
291 dissect_func_t *dissect;
292 guint32 ipx_dnet_val, ipx_snet_val;
294 /* Calculate here for use in pinfo and in tree */
295 ipx_dnet = (guint8*)&pd[offset+6];
296 ipx_snet = (guint8*)&pd[offset+18];
297 str_dnet = ipxnet_to_string(ipx_dnet);
298 str_snet = ipxnet_to_string(ipx_snet);
299 ipx_dnet_val = pntohl(ipx_dnet);
300 ipx_snet_val = pntohl(ipx_snet);
301 ipx_dsocket = pntohs(&pd[offset+16]);
302 ipx_ssocket = pntohs(&pd[offset+28]);
303 ipx_dnode = (guint8*)&pd[offset+10];
304 ipx_snode = (guint8*)&pd[offset+22];
305 ipx_type = pd[offset+5];
306 ipx_length = pntohs(&pd[offset+2]);
308 /* Length of IPX datagram plus headers above it. */
309 len = ipx_length + offset;
311 /* Set the payload and captured-payload lengths to the minima of
312 (the IPX length plus the length of the headers above it) and
313 the frame lengths. */
316 if (pi.captured_len > len)
317 pi.captured_len = len;
319 SET_ADDRESS(&pi.net_src, AT_IPX, 10, &pd[offset+18]);
320 SET_ADDRESS(&pi.src, AT_IPX, 10, &pd[offset+18]);
321 SET_ADDRESS(&pi.net_dst, AT_IPX, 10, &pd[offset+6]);
322 SET_ADDRESS(&pi.dst, AT_IPX, 10, &pd[offset+6]);
324 if (check_col(fd, COL_PROTOCOL))
325 col_add_str(fd, COL_PROTOCOL, "IPX");
326 if (check_col(fd, COL_INFO))
327 col_add_fstr(fd, COL_INFO, "%s (0x%04X)", port_text(ipx_dsocket),
331 ipx_checksum = pntohs(&pd[offset]);
332 ipx_hops = pd[offset+4];
334 ti = proto_tree_add_item(tree, proto_ipx, offset, 30, NULL);
335 ipx_tree = proto_item_add_subtree(ti, ett_ipx);
336 proto_tree_add_item(ipx_tree, hf_ipx_checksum, offset, 2, ipx_checksum);
337 proto_tree_add_item_format(ipx_tree, hf_ipx_len, offset+2, 2, ipx_length,
338 "Length: %d bytes", ipx_length);
339 proto_tree_add_item_format(ipx_tree, hf_ipx_hops, offset+4, 1, ipx_hops,
340 "Transport Control: %d hops", ipx_hops);
341 proto_tree_add_item(ipx_tree, hf_ipx_packet_type, offset+5, 1, ipx_type);
342 proto_tree_add_item(ipx_tree, hf_ipx_dnet, offset+6, 4, ipx_dnet_val);
343 proto_tree_add_item(ipx_tree, hf_ipx_dnode, offset+10, 6, ipx_dnode);
344 proto_tree_add_item_format(ipx_tree, hf_ipx_dsocket, offset+16, 2,
345 ipx_dsocket, "Destination Socket: %s (0x%04X)",
346 port_text(ipx_dsocket), ipx_dsocket);
347 proto_tree_add_item(ipx_tree, hf_ipx_snet, offset+18, 4, ipx_snet_val);
348 proto_tree_add_item(ipx_tree, hf_ipx_snode, offset+22, 6, ipx_snode);
349 proto_tree_add_item_format(ipx_tree, hf_ipx_ssocket, offset+28, 2,
350 ipx_ssocket, "Source Socket: %s (0x%04X)", port_text(ipx_ssocket),
356 case IPX_PACKET_TYPE_SPX:
357 dissect_spx(pd, offset, fd, tree);
360 case IPX_PACKET_TYPE_NCP:
361 /* Is the destination node 00:00:00:00:00:01 ? */
362 if (pntohl(ipx_dnode) == 0 && pntohs(ipx_dnode + 4) == 1)
363 nw_server_address = pntohl(ipx_dnet);
365 /* Is the source node 00:00:00:00:00:01 ? */
366 else if (pntohl(ipx_snode) == 0 && pntohs(ipx_snode + 4) == 1)
367 nw_server_address = pntohl(ipx_snet);
369 nw_server_address = 0;
371 dissect_ncp(pd, offset, fd, tree);
374 case IPX_PACKET_TYPE_WANBCAST:
375 case IPX_PACKET_TYPE_IPX_4:
376 if (ipx_dsocket == IPX_SOCKET_NETBIOS) {
377 dissect_nbipx(pd, offset, fd, tree);
380 /* else fall through */
382 case 0: /* IPX, fall through to default */
383 /* XXX - should type 0's be dissected as NBIPX
384 if they're aimed at the NetBIOS socket? */
386 dissect = port_func(ipx_dsocket);
388 dissect(pd, offset, fd, tree);
391 dissect = port_func(ipx_ssocket);
393 dissect(pd, offset, fd, tree);
396 dissect_data(pd, offset, fd, tree);
404 /* ================================================================= */
406 /* ================================================================= */
408 spx_conn_ctrl(u_char ctrl)
412 static struct conn_info conns[] = {
413 { 0x10, "End-of-Message" },
414 { 0x20, "Attention" },
415 { 0x40, "Acknowledgment Required"},
416 { 0x80, "System Packet"},
420 while (conns[i].text != NULL) {
421 if (conns[i].ctrl == ctrl) {
422 return conns[i].text;
430 spx_datastream(u_char type)
434 return "End-of-Connection";
436 return "End-of-Connection Acknowledgment";
438 return "Client-Defined";
443 dissect_spx(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
444 proto_tree *spx_tree;
447 if (check_col(fd, COL_PROTOCOL))
448 col_add_str(fd, COL_PROTOCOL, "SPX");
449 if (check_col(fd, COL_INFO))
450 col_add_str(fd, COL_INFO, "SPX");
453 ti = proto_tree_add_item(tree, proto_spx, offset, 12, NULL);
454 spx_tree = proto_item_add_subtree(ti, ett_spx);
456 proto_tree_add_item_format(spx_tree, hf_spx_connection_control,
459 "Connection Control: %s (0x%02X)",
460 spx_conn_ctrl(pd[offset]),
463 proto_tree_add_item_format(spx_tree, hf_spx_datastream_type,
466 "Datastream Type: %s (0x%02X)",
467 spx_datastream(pd[offset+1]),
470 proto_tree_add_item(spx_tree, hf_spx_src_id,
472 pntohs( &pd[offset+2] ));
474 proto_tree_add_item(spx_tree, hf_spx_dst_id,
476 pntohs( &pd[offset+4] ));
478 proto_tree_add_item(spx_tree, hf_spx_seq_nr,
480 pntohs( &pd[offset+6] ) );
482 proto_tree_add_item(spx_tree, hf_spx_ack_nr,
484 pntohs( &pd[offset+8] ) );
486 proto_tree_add_item(spx_tree, hf_spx_all_nr,
488 pntohs( &pd[offset+10] ) );
491 dissect_data(pd, offset, fd, tree);
495 /* ================================================================= */
497 /* ================================================================= */
499 dissect_ipxrip(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
500 proto_tree *rip_tree;
503 struct ipx_rt_def route;
506 char *rip_type[2] = { "Request", "Response" };
508 operation = pntohs(&pd[offset]) - 1;
510 if (check_col(fd, COL_PROTOCOL))
511 col_add_str(fd, COL_PROTOCOL, "IPX RIP");
512 if (check_col(fd, COL_PROTOCOL)) {
514 col_add_str(fd, COL_INFO, rip_type[operation]);
517 col_add_str(fd, COL_INFO, "Unknown Packet Type");
522 ti = proto_tree_add_item(tree, proto_ipxrip, offset, END_OF_FRAME, NULL);
523 rip_tree = proto_item_add_subtree(ti, ett_ipxrip);
526 proto_tree_add_text(rip_tree, offset, 2,
527 "RIP packet type: %s", rip_type[operation]);
529 if (operation == 0) {
530 proto_tree_add_item_hidden(rip_tree,
534 proto_tree_add_item_hidden(rip_tree,
541 proto_tree_add_text(rip_tree, offset, 2, "Unknown RIP packet type");
544 for (cursor = offset + 2; cursor < fd->cap_len; cursor += 8) {
545 memcpy(&route.network, &pd[cursor], 4);
546 route.hops = pntohs(&pd[cursor+4]);
547 route.ticks = pntohs(&pd[cursor+6]);
549 if (operation == IPX_RIP_REQUEST - 1) {
550 proto_tree_add_text(rip_tree, cursor, 8,
551 "Route Vector: %s, %d hop%s, %d tick%s",
552 ipxnet_to_string((guint8*)&route.network),
553 route.hops, route.hops == 1 ? "" : "s",
554 route.ticks, route.ticks == 1 ? "" : "s");
557 proto_tree_add_text(rip_tree, cursor, 8,
558 "Route Vector: %s, %d hop%s, %d tick%s (%d ms)",
559 ipxnet_to_string((guint8*)&route.network),
560 route.hops, route.hops == 1 ? "" : "s",
561 route.ticks, route.ticks == 1 ? "" : "s",
562 route.ticks * 1000 / 18);
570 /* ================================================================= */
572 /* ================================================================= */
574 server_type(guint16 type)
578 /* some of these are from ncpfs, others are from the book */
579 static struct server_info servers[] = {
581 { 0x0002, "User Group" },
582 { 0x0003, "Print Queue" },
583 { 0x0004, "File server" },
584 { 0x0005, "Job server" },
585 { 0x0007, "Print server" },
586 { 0x0008, "Archive server" },
587 { 0x0009, "Archive server" },
588 { 0x000a, "Job queue" },
589 { 0x000b, "Administration" },
590 { 0x0021, "NAS SNA gateway" },
591 { 0x0024, "Remote bridge" },
592 { 0x0026, "Bridge server" },
593 { 0x0027, "TCP/IP gateway" },
594 { 0x002d, "Time Synchronization VAP" },
595 { 0x002e, "Archive Server Dynamic SAP" },
596 { 0x0047, "Advertising print server" },
597 { 0x004b, "Btrieve VAP 5.0" },
598 { 0x004c, "SQL VAP" },
599 { 0x0050, "Btrieve VAP" },
600 { 0x0053, "Print Queue VAP" },
601 { 0x007a, "TES NetWare for VMS" },
602 { 0x0098, "NetWare access server" },
603 { 0x009a, "Named Pipes server" },
604 { 0x009e, "Portable NetWare Unix" },
605 { 0x0107, "NetWare 386" },
606 { 0x0111, "Test server" },
607 { 0x0133, "NetWare Name Service" },
608 { 0x0166, "NetWare management" },
609 { 0x023f, "SMS Testing and Development" },
610 { 0x026a, "NetWare management" },
611 { 0x026b, "Time synchronization" },
612 { 0x027b, "NetWare Management Agent" },
613 { 0x0278, "NetWare Directory server" },
614 { 0x030c, "HP LaserJet / Quick Silver" },
615 { 0x0355, "Arcada Software" },
616 { 0x0361, "NETINELO" },
617 { 0x037e, "Powerchute UPS Monitoring" },
618 { 0x03e1, "UnixWare Application Server" },
619 { 0x044c, "Archive" },
620 { 0x055d, "Attachmate SNA gateway" },
621 { 0x0610, "Adaptec SCSI Management" },
622 { 0x0640, "NT Server-RPC/GW for NW/Win95 User Level Sec" },
623 { 0x064e, "NT Server-IIS" },
624 { 0x0810, "ELAN License Server Demo" },
625 { 0x8002, "Intel NetPort Print Server" },
627 /* For any unidentified ones, I found a really big list of them at: */
628 /* http://www.inpnet.org/cnpweb/saplist.txt */
629 /* http://www.isi.edu/in-notes/iana/assignments/novell-sap-numbers */
634 while (servers[i].text != NULL) {
635 if (servers[i].type == type) {
636 return servers[i].text;
644 dissect_ipxsap(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
646 proto_tree *sap_tree, *s_tree;
649 struct sap_query query;
650 struct sap_server_ident server;
652 char *sap_type[4] = { "General Query", "General Response",
653 "Nearest Query", "Nearest Response" };
655 query.query_type = pntohs(&pd[offset]);
656 query.server_type = pntohs(&pd[offset+2]);
658 if (check_col(fd, COL_PROTOCOL))
659 col_add_str(fd, COL_PROTOCOL, "SAP");
660 if (check_col(fd, COL_INFO)) {
661 if (query.query_type >= 1 && query.query_type <= 4) {
662 col_add_str(fd, COL_INFO, sap_type[query.query_type - 1]);
665 col_add_str(fd, COL_INFO, "Unknown Packet Type");
670 ti = proto_tree_add_item(tree, proto_sap, offset, END_OF_FRAME, NULL);
671 sap_tree = proto_item_add_subtree(ti, ett_ipxsap);
673 if (query.query_type >= 1 && query.query_type <= 4) {
674 proto_tree_add_text(sap_tree, offset, 2, sap_type[query.query_type - 1]);
675 if ((query.query_type - 1) % 2) {
676 proto_tree_add_item_hidden(sap_tree,
680 proto_tree_add_item_hidden(sap_tree,
686 proto_tree_add_text(sap_tree, offset, 2,
687 "Unknown SAP Packet Type %d", query.query_type);
690 if (query.query_type == IPX_SAP_GENERAL_RESPONSE ||
691 query.query_type == IPX_SAP_NEAREST_RESPONSE) { /* responses */
693 for (cursor = offset + 2; (cursor + 64) <= fd->cap_len; cursor += 64) {
694 server.server_type = pntohs(&pd[cursor]);
695 memcpy(server.server_name, &pd[cursor+2], 48);
696 memcpy(&server.server_network, &pd[cursor+50], 4);
697 memcpy(&server.server_node, &pd[cursor+54], 6);
698 server.server_port = pntohs(&pd[cursor+60]);
699 server.intermediate_network = pntohs(&pd[cursor+62]);
701 ti = proto_tree_add_text(sap_tree, cursor+2, 48,
702 "Server Name: %s", server.server_name);
703 s_tree = proto_item_add_subtree(ti, ett_ipxsap_server);
705 proto_tree_add_text(s_tree, cursor, 2, "Server Type: %s (0x%04X)",
706 server_type(server.server_type), server.server_type);
707 proto_tree_add_text(s_tree, cursor+50, 4, "Network: %s",
708 ipxnet_to_string((guint8*)&pd[cursor+50]));
709 proto_tree_add_text(s_tree, cursor+54, 6, "Node: %s",
710 ether_to_str((guint8*)&pd[cursor+54]));
711 proto_tree_add_text(s_tree, cursor+60, 2, "Socket: %s (0x%04X)",
712 port_text(server.server_port), server.server_port);
713 proto_tree_add_text(s_tree, cursor+62, 2,
714 "Intermediate Networks: %d",
715 server.intermediate_network);
719 proto_tree_add_text(sap_tree, offset+2, 2, "Server Type: %s (0x%04X)",
720 server_type(query.server_type), query.server_type);
727 proto_register_ipx(void)
729 static hf_register_info hf_ipx[] = {
731 { "Checksum", "ipx.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
735 { "Length", "ipx.len", FT_UINT16, BASE_DEC, NULL, 0x0,
739 { "Transport Control (Hops)", "ipx.hops", FT_UINT8, BASE_DEC, NULL, 0x0,
742 { &hf_ipx_packet_type,
743 { "Packet Type", "ipx.packet_type", FT_UINT8, BASE_HEX, VALS(ipx_packet_type_vals),
748 { "Destination Network","ipx.dst.net", FT_IPXNET, BASE_NONE, NULL, 0x0,
752 { "Destination Node", "ipx.dst.node", FT_ETHER, BASE_NONE, NULL, 0x0,
756 { "Destination Socket", "ipx.dst.socket", FT_UINT16, BASE_HEX, NULL, 0x0,
760 { "Source Network","ipx.src.net", FT_IPXNET, BASE_NONE, NULL, 0x0,
764 { "Source Node", "ipx.src.node", FT_ETHER, BASE_NONE, NULL, 0x0,
768 { "Source Socket", "ipx.src.socket", FT_UINT16, BASE_HEX, NULL, 0x0,
772 static hf_register_info hf_spx[] = {
773 { &hf_spx_connection_control,
774 { "Connection Control", "spx.ctl",
775 FT_UINT8, BASE_HEX, NULL, 0x0,
778 { &hf_spx_datastream_type,
779 { "Datastream type", "spx.type",
780 FT_UINT8, BASE_HEX, NULL, 0x0,
784 { "Source Connection ID", "spx.src",
785 FT_UINT16, BASE_DEC, NULL, 0x0,
789 { "Destination Connection ID", "spx.dst",
790 FT_UINT16, BASE_DEC, NULL, 0x0,
794 { "Sequence Number", "spx.seq",
795 FT_UINT16, BASE_DEC, NULL, 0x0,
799 { "Acknowledgment Number", "spx.ack",
800 FT_UINT16, BASE_DEC, NULL, 0x0,
804 { "Allocation Number", "spx.alloc",
805 FT_UINT16, BASE_DEC, NULL, 0x0,
809 static hf_register_info hf_ipxrip[] = {
810 { &hf_ipxrip_request,
811 { "Request", "ipxrip.request",
812 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
813 "TRUE if IPX RIP request" }},
815 { &hf_ipxrip_response,
816 { "Response", "ipxrip.response",
817 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
818 "TRUE if IPX RIP response" }}
821 static hf_register_info hf_sap[] = {
823 { "Request", "sap.request",
824 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
825 "TRUE if SAP request" }},
828 { "Response", "sap.response",
829 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
830 "TRUE if SAP response" }}
832 static gint *ett[] = {
840 proto_ipx = proto_register_protocol ("Internetwork Packet eXchange", "ipx");
841 proto_register_field_array(proto_ipx, hf_ipx, array_length(hf_ipx));
843 proto_spx = proto_register_protocol ("Sequenced Packet eXchange", "spx");
844 proto_register_field_array(proto_spx, hf_spx, array_length(hf_spx));
846 proto_ipxrip = proto_register_protocol ("IPX Routing Information Protocol", "ipxrip");
847 proto_register_field_array(proto_ipxrip, hf_ipxrip, array_length(hf_ipxrip));
849 proto_sap = proto_register_protocol ("Service Advertisement Protocol", "sap");
850 proto_register_field_array(proto_sap, hf_sap, array_length(hf_sap));
852 proto_register_subtree_array(ett, array_length(ett));