]> The Tcpdump Group git mirrors - tcpdump/blob - print-ipx.c
Add program_name field in the netdissect_options structure
[tcpdump] / print-ipx.c
1 /*
2 * Copyright (c) 1994, 1995, 1996
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the University of California,
13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
16 * written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 *
21 * Format and print Novell IPX packets.
22 * Contributed by Brad Parker (brad@fcr.com).
23 */
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include <tcpdump-stdinc.h>
30
31 #include <stdio.h>
32
33 #include "netdissect.h"
34 #include "addrtoname.h"
35 #include "extract.h"
36
37 /* well-known sockets */
38 #define IPX_SKT_NCP 0x0451
39 #define IPX_SKT_SAP 0x0452
40 #define IPX_SKT_RIP 0x0453
41 #define IPX_SKT_NETBIOS 0x0455
42 #define IPX_SKT_DIAGNOSTICS 0x0456
43 #define IPX_SKT_NWLINK_DGM 0x0553 /* NWLink datagram, may contain SMB */
44 #define IPX_SKT_EIGRP 0x85be /* Cisco EIGRP over IPX */
45
46 /* IPX transport header */
47 struct ipxHdr {
48 uint16_t cksum; /* Checksum */
49 uint16_t length; /* Length, in bytes, including header */
50 uint8_t tCtl; /* Transport Control (i.e. hop count) */
51 uint8_t pType; /* Packet Type (i.e. level 2 protocol) */
52 uint16_t dstNet[2]; /* destination net */
53 uint8_t dstNode[6]; /* destination node */
54 uint16_t dstSkt; /* destination socket */
55 uint16_t srcNet[2]; /* source net */
56 uint8_t srcNode[6]; /* source node */
57 uint16_t srcSkt; /* source socket */
58 };
59
60 #define ipxSize 30
61
62 static const char *ipxaddr_string(uint32_t, const u_char *);
63 static void ipx_decode(netdissect_options *, const struct ipxHdr *, const u_char *, u_int);
64 static void ipx_sap_print(netdissect_options *, const u_short *, u_int);
65 static void ipx_rip_print(netdissect_options *, const u_short *, u_int);
66
67 /*
68 * Print IPX datagram packets.
69 */
70 void
71 ipx_print(netdissect_options *ndo, const u_char *p, u_int length)
72 {
73 const struct ipxHdr *ipx = (const struct ipxHdr *)p;
74
75 if (!ndo->ndo_eflag)
76 ND_PRINT((ndo, "IPX "));
77
78 ND_TCHECK(ipx->srcSkt);
79 ND_PRINT((ndo, "%s.%04x > ",
80 ipxaddr_string(EXTRACT_32BITS(ipx->srcNet), ipx->srcNode),
81 EXTRACT_16BITS(&ipx->srcSkt)));
82
83 ND_PRINT((ndo, "%s.%04x: ",
84 ipxaddr_string(EXTRACT_32BITS(ipx->dstNet), ipx->dstNode),
85 EXTRACT_16BITS(&ipx->dstSkt)));
86
87 /* take length from ipx header */
88 ND_TCHECK(ipx->length);
89 length = EXTRACT_16BITS(&ipx->length);
90
91 ipx_decode(ndo, ipx, p + ipxSize, length - ipxSize);
92 return;
93 trunc:
94 ND_PRINT((ndo, "[|ipx %d]", length));
95 }
96
97 static const char *
98 ipxaddr_string(uint32_t net, const u_char *node)
99 {
100 static char line[256];
101
102 snprintf(line, sizeof(line), "%08x.%02x:%02x:%02x:%02x:%02x:%02x",
103 net, node[0], node[1], node[2], node[3], node[4], node[5]);
104
105 return line;
106 }
107
108 static void
109 ipx_decode(netdissect_options *ndo, const struct ipxHdr *ipx, const u_char *datap, u_int length)
110 {
111 register u_short dstSkt;
112
113 dstSkt = EXTRACT_16BITS(&ipx->dstSkt);
114 switch (dstSkt) {
115 case IPX_SKT_NCP:
116 ND_PRINT((ndo, "ipx-ncp %d", length));
117 break;
118 case IPX_SKT_SAP:
119 ipx_sap_print(ndo, (const u_short *)datap, length);
120 break;
121 case IPX_SKT_RIP:
122 ipx_rip_print(ndo, (const u_short *)datap, length);
123 break;
124 case IPX_SKT_NETBIOS:
125 ND_PRINT((ndo, "ipx-netbios %d", length));
126 #ifdef TCPDUMP_DO_SMB
127 ipx_netbios_print(ndo, datap, length);
128 #endif
129 break;
130 case IPX_SKT_DIAGNOSTICS:
131 ND_PRINT((ndo, "ipx-diags %d", length));
132 break;
133 case IPX_SKT_NWLINK_DGM:
134 ND_PRINT((ndo, "ipx-nwlink-dgm %d", length));
135 #ifdef TCPDUMP_DO_SMB
136 ipx_netbios_print(ndo, datap, length);
137 #endif
138 break;
139 case IPX_SKT_EIGRP:
140 eigrp_print(ndo, datap, length);
141 break;
142 default:
143 ND_PRINT((ndo, "ipx-#%x %d", dstSkt, length));
144 break;
145 }
146 }
147
148 static void
149 ipx_sap_print(netdissect_options *ndo, const u_short *ipx, u_int length)
150 {
151 int command, i;
152
153 ND_TCHECK(ipx[0]);
154 command = EXTRACT_16BITS(ipx);
155 ipx++;
156 length -= 2;
157
158 switch (command) {
159 case 1:
160 case 3:
161 if (command == 1)
162 ND_PRINT((ndo, "ipx-sap-req"));
163 else
164 ND_PRINT((ndo, "ipx-sap-nearest-req"));
165
166 ND_TCHECK(ipx[0]);
167 ND_PRINT((ndo, " %s", ipxsap_string(ndo, htons(EXTRACT_16BITS(&ipx[0])))));
168 break;
169
170 case 2:
171 case 4:
172 if (command == 2)
173 ND_PRINT((ndo, "ipx-sap-resp"));
174 else
175 ND_PRINT((ndo, "ipx-sap-nearest-resp"));
176
177 for (i = 0; i < 8 && length > 0; i++) {
178 ND_TCHECK(ipx[0]);
179 ND_PRINT((ndo, " %s '", ipxsap_string(ndo, htons(EXTRACT_16BITS(&ipx[0])))));
180 if (fn_printzp(ndo, (const u_char *)&ipx[1], 48, ndo->ndo_snapend)) {
181 ND_PRINT((ndo, "'"));
182 goto trunc;
183 }
184 ND_TCHECK2(ipx[25], 10);
185 ND_PRINT((ndo, "' addr %s",
186 ipxaddr_string(EXTRACT_32BITS(&ipx[25]), (const u_char *)&ipx[27])));
187 ipx += 32;
188 length -= 64;
189 }
190 break;
191 default:
192 ND_PRINT((ndo, "ipx-sap-?%x", command));
193 break;
194 }
195 return;
196 trunc:
197 ND_PRINT((ndo, "[|ipx %d]", length));
198 }
199
200 static void
201 ipx_rip_print(netdissect_options *ndo, const u_short *ipx, u_int length)
202 {
203 int command, i;
204
205 ND_TCHECK(ipx[0]);
206 command = EXTRACT_16BITS(ipx);
207 ipx++;
208 length -= 2;
209
210 switch (command) {
211 case 1:
212 ND_PRINT((ndo, "ipx-rip-req"));
213 if (length > 0) {
214 ND_TCHECK(ipx[3]);
215 ND_PRINT((ndo, " %08x/%d.%d", EXTRACT_32BITS(&ipx[0]),
216 EXTRACT_16BITS(&ipx[2]), EXTRACT_16BITS(&ipx[3])));
217 }
218 break;
219 case 2:
220 ND_PRINT((ndo, "ipx-rip-resp"));
221 for (i = 0; i < 50 && length > 0; i++) {
222 ND_TCHECK(ipx[3]);
223 ND_PRINT((ndo, " %08x/%d.%d", EXTRACT_32BITS(&ipx[0]),
224 EXTRACT_16BITS(&ipx[2]), EXTRACT_16BITS(&ipx[3])));
225
226 ipx += 4;
227 length -= 8;
228 }
229 break;
230 default:
231 ND_PRINT((ndo, "ipx-rip-?%x", command));
232 break;
233 }
234 return;
235 trunc:
236 ND_PRINT((ndo, "[|ipx %d]", length));
237 }