xref: /netbsd-src/external/bsd/tcpdump/dist/print-ipx.c (revision 26ba0b503b498a5194a71ac319838b7f5497f3fe)
10f74e101Schristos /*
20f74e101Schristos  * Copyright (c) 1994, 1995, 1996
30f74e101Schristos  *	The Regents of the University of California.  All rights reserved.
40f74e101Schristos  *
50f74e101Schristos  * Redistribution and use in source and binary forms, with or without
60f74e101Schristos  * modification, are permitted provided that: (1) source code distributions
70f74e101Schristos  * retain the above copyright notice and this paragraph in its entirety, (2)
80f74e101Schristos  * distributions including binary code include the above copyright notice and
90f74e101Schristos  * this paragraph in its entirety in the documentation or other materials
100f74e101Schristos  * provided with the distribution, and (3) all advertising materials mentioning
110f74e101Schristos  * features or use of this software display the following acknowledgement:
120f74e101Schristos  * ``This product includes software developed by the University of California,
130f74e101Schristos  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
140f74e101Schristos  * the University nor the names of its contributors may be used to endorse
150f74e101Schristos  * or promote products derived from this software without specific prior
160f74e101Schristos  * written permission.
170f74e101Schristos  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
180f74e101Schristos  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
190f74e101Schristos  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
200f74e101Schristos  *
210f74e101Schristos  * Contributed by Brad Parker (brad@fcr.com).
220f74e101Schristos  */
230f74e101Schristos 
24dc860a36Sspz /* \summary: Novell IPX printer */
25dc860a36Sspz 
2611b3aaa1Schristos #include <sys/cdefs.h>
270f74e101Schristos #ifndef lint
28*26ba0b50Schristos __RCSID("$NetBSD: print-ipx.c,v 1.8 2024/09/02 16:15:31 christos Exp $");
290f74e101Schristos #endif
300f74e101Schristos 
31c74ad251Schristos #include <config.h>
320f74e101Schristos 
33c74ad251Schristos #include "netdissect-stdinc.h"
340f74e101Schristos 
350f74e101Schristos #include <stdio.h>
360f74e101Schristos 
37c74ad251Schristos #define ND_LONGJMP_FROM_TCHECK
38fdccd7e4Schristos #include "netdissect.h"
390f74e101Schristos #include "addrtoname.h"
400f74e101Schristos #include "extract.h"
410f74e101Schristos 
42b3a00663Schristos /* well-known sockets */
43b3a00663Schristos #define	IPX_SKT_NCP		0x0451
44b3a00663Schristos #define	IPX_SKT_SAP		0x0452
45b3a00663Schristos #define	IPX_SKT_RIP		0x0453
46b3a00663Schristos #define	IPX_SKT_NETBIOS		0x0455
47b3a00663Schristos #define	IPX_SKT_DIAGNOSTICS	0x0456
48b3a00663Schristos #define	IPX_SKT_NWLINK_DGM	0x0553	/* NWLink datagram, may contain SMB */
49b3a00663Schristos #define	IPX_SKT_EIGRP		0x85be	/* Cisco EIGRP over IPX */
500f74e101Schristos 
51b3a00663Schristos /* IPX transport header */
52b3a00663Schristos struct ipxHdr {
53c74ad251Schristos     nd_uint16_t	cksum;		/* Checksum */
54c74ad251Schristos     nd_uint16_t	length;		/* Length, in bytes, including header */
55c74ad251Schristos     nd_uint8_t	tCtl;		/* Transport Control (i.e. hop count) */
56c74ad251Schristos     nd_uint8_t	pType;		/* Packet Type (i.e. level 2 protocol) */
57c74ad251Schristos     nd_uint32_t	dstNet;		/* destination net */
58c74ad251Schristos     nd_mac_addr	dstNode;	/* destination node */
59c74ad251Schristos     nd_uint16_t	dstSkt;		/* destination socket */
60c74ad251Schristos     nd_uint32_t	srcNet;		/* source net */
61c74ad251Schristos     nd_mac_addr	srcNode;	/* source node */
62c74ad251Schristos     nd_uint16_t	srcSkt;		/* source socket */
63b3a00663Schristos };
64b3a00663Schristos 
65b3a00663Schristos #define ipxSize	30
66b3a00663Schristos 
67c74ad251Schristos static const char *ipxaddr_string(netdissect_options *, uint32_t, const u_char *);
68b3a00663Schristos static void ipx_decode(netdissect_options *, const struct ipxHdr *, const u_char *, u_int);
69c74ad251Schristos static void ipx_sap_print(netdissect_options *, const u_char *, u_int);
70c74ad251Schristos static void ipx_rip_print(netdissect_options *, const u_char *, u_int);
710f74e101Schristos 
720f74e101Schristos /*
730f74e101Schristos  * Print IPX datagram packets.
740f74e101Schristos  */
750f74e101Schristos void
76b3a00663Schristos ipx_print(netdissect_options *ndo, const u_char *p, u_int length)
770f74e101Schristos {
780f74e101Schristos 	const struct ipxHdr *ipx = (const struct ipxHdr *)p;
790f74e101Schristos 
80c74ad251Schristos 	ndo->ndo_protocol = "ipx";
81b3a00663Schristos 	if (!ndo->ndo_eflag)
82c74ad251Schristos 		ND_PRINT("IPX ");
830f74e101Schristos 
84c74ad251Schristos 	ND_PRINT("%s.%04x > ",
85c74ad251Schristos 		     ipxaddr_string(ndo, GET_BE_U_4(ipx->srcNet), ipx->srcNode),
86c74ad251Schristos 		     GET_BE_U_2(ipx->srcSkt));
870f74e101Schristos 
88c74ad251Schristos 	ND_PRINT("%s.%04x: ",
89c74ad251Schristos 		     ipxaddr_string(ndo, GET_BE_U_4(ipx->dstNet), ipx->dstNode),
90c74ad251Schristos 		     GET_BE_U_2(ipx->dstSkt));
910f74e101Schristos 
920f74e101Schristos 	/* take length from ipx header */
93c74ad251Schristos 	length = GET_BE_U_2(ipx->length);
940f74e101Schristos 
95c74ad251Schristos 	if (length < ipxSize) {
96c74ad251Schristos 		ND_PRINT("[length %u < %u]", length, ipxSize);
97c74ad251Schristos 		nd_print_invalid(ndo);
980f74e101Schristos 		return;
99c74ad251Schristos 	}
100c74ad251Schristos 	ipx_decode(ndo, ipx, p + ipxSize, length - ipxSize);
1010f74e101Schristos }
1020f74e101Schristos 
1030f74e101Schristos static const char *
104c74ad251Schristos ipxaddr_string(netdissect_options *ndo, uint32_t net, const u_char *node)
1050f74e101Schristos {
1060f74e101Schristos     static char line[256];
1070f74e101Schristos 
1080f74e101Schristos     snprintf(line, sizeof(line), "%08x.%02x:%02x:%02x:%02x:%02x:%02x",
109c74ad251Schristos 	    net, GET_U_1(node), GET_U_1(node + 1),
110c74ad251Schristos 	    GET_U_1(node + 2), GET_U_1(node + 3),
111c74ad251Schristos 	    GET_U_1(node + 4), GET_U_1(node + 5));
1120f74e101Schristos 
1130f74e101Schristos     return line;
1140f74e101Schristos }
1150f74e101Schristos 
116b3a00663Schristos static void
117b3a00663Schristos ipx_decode(netdissect_options *ndo, const struct ipxHdr *ipx, const u_char *datap, u_int length)
1180f74e101Schristos {
119c74ad251Schristos     u_short dstSkt;
1200f74e101Schristos 
121c74ad251Schristos     dstSkt = GET_BE_U_2(ipx->dstSkt);
1220f74e101Schristos     switch (dstSkt) {
1230f74e101Schristos       case IPX_SKT_NCP:
124c74ad251Schristos 	ND_PRINT("ipx-ncp %u", length);
1250f74e101Schristos 	break;
1260f74e101Schristos       case IPX_SKT_SAP:
127c74ad251Schristos 	ipx_sap_print(ndo, datap, length);
1280f74e101Schristos 	break;
1290f74e101Schristos       case IPX_SKT_RIP:
130c74ad251Schristos 	ipx_rip_print(ndo, datap, length);
1310f74e101Schristos 	break;
1320f74e101Schristos       case IPX_SKT_NETBIOS:
133c74ad251Schristos 	ND_PRINT("ipx-netbios %u", length);
134fdccd7e4Schristos #ifdef ENABLE_SMB
135b3a00663Schristos 	ipx_netbios_print(ndo, datap, length);
1360f74e101Schristos #endif
1370f74e101Schristos 	break;
1380f74e101Schristos       case IPX_SKT_DIAGNOSTICS:
139c74ad251Schristos 	ND_PRINT("ipx-diags %u", length);
1400f74e101Schristos 	break;
1410f74e101Schristos       case IPX_SKT_NWLINK_DGM:
142c74ad251Schristos 	ND_PRINT("ipx-nwlink-dgm %u", length);
143fdccd7e4Schristos #ifdef ENABLE_SMB
144b3a00663Schristos 	ipx_netbios_print(ndo, datap, length);
1450f74e101Schristos #endif
1460f74e101Schristos 	break;
1470f74e101Schristos       case IPX_SKT_EIGRP:
148b3a00663Schristos 	eigrp_print(ndo, datap, length);
1490f74e101Schristos 	break;
1500f74e101Schristos       default:
151c74ad251Schristos 	ND_PRINT("ipx-#%x %u", dstSkt, length);
1520f74e101Schristos 	break;
1530f74e101Schristos     }
1540f74e101Schristos }
1550f74e101Schristos 
156b3a00663Schristos static void
157c74ad251Schristos ipx_sap_print(netdissect_options *ndo, const u_char *ipx, u_int length)
1580f74e101Schristos {
1590f74e101Schristos     int command, i;
1600f74e101Schristos 
161c74ad251Schristos     command = GET_BE_U_2(ipx);
162*26ba0b50Schristos     ND_ICHECK_U(length, <, 2);
163c74ad251Schristos     ipx += 2;
1640f74e101Schristos     length -= 2;
1650f74e101Schristos 
1660f74e101Schristos     switch (command) {
1670f74e101Schristos       case 1:
1680f74e101Schristos       case 3:
1690f74e101Schristos 	if (command == 1)
170c74ad251Schristos 	    ND_PRINT("ipx-sap-req");
1710f74e101Schristos 	else
172c74ad251Schristos 	    ND_PRINT("ipx-sap-nearest-req");
1730f74e101Schristos 
174c74ad251Schristos 	ND_PRINT(" %s", ipxsap_string(ndo, htons(GET_BE_U_2(ipx))));
1750f74e101Schristos 	break;
1760f74e101Schristos 
1770f74e101Schristos       case 2:
1780f74e101Schristos       case 4:
1790f74e101Schristos 	if (command == 2)
180c74ad251Schristos 	    ND_PRINT("ipx-sap-resp");
1810f74e101Schristos 	else
182c74ad251Schristos 	    ND_PRINT("ipx-sap-nearest-resp");
1830f74e101Schristos 
184c74ad251Schristos 	for (i = 0; i < 8 && length != 0; i++) {
185c74ad251Schristos 	    ND_TCHECK_2(ipx);
186c74ad251Schristos 	    if (length < 2)
187c74ad251Schristos 		goto invalid;
188c74ad251Schristos 	    ND_PRINT(" %s '", ipxsap_string(ndo, htons(GET_BE_U_2(ipx))));
189c74ad251Schristos 	    ipx += 2;
190c74ad251Schristos 	    length -= 2;
191c74ad251Schristos 	    if (length < 48) {
192c74ad251Schristos 		ND_PRINT("'");
193c74ad251Schristos 		goto invalid;
1940f74e101Schristos 	    }
195c74ad251Schristos 	    nd_printjnp(ndo, ipx, 48);
196c74ad251Schristos 	    ND_PRINT("'");
197c74ad251Schristos 	    ipx += 48;
198c74ad251Schristos 	    length -= 48;
199c74ad251Schristos 	    /*
200c74ad251Schristos 	     * 10 bytes of IPX address.
201c74ad251Schristos 	     */
202c74ad251Schristos 	    ND_TCHECK_LEN(ipx, 10);
203c74ad251Schristos 	    if (length < 10)
204c74ad251Schristos 		goto invalid;
205c74ad251Schristos 	    ND_PRINT(" addr %s",
206c74ad251Schristos 		ipxaddr_string(ndo, GET_BE_U_4(ipx), ipx + 4));
207c74ad251Schristos 	    ipx += 10;
208c74ad251Schristos 	    length -= 10;
209c74ad251Schristos 	    /*
210c74ad251Schristos 	     * 2 bytes of socket and 2 bytes of number of intermediate
211c74ad251Schristos 	     * networks.
212c74ad251Schristos 	     */
213c74ad251Schristos 	    ND_TCHECK_4(ipx);
214c74ad251Schristos 	    if (length < 4)
215c74ad251Schristos 		goto invalid;
216c74ad251Schristos 	    ipx += 4;
217c74ad251Schristos 	    length -= 4;
2180f74e101Schristos 	}
2190f74e101Schristos 	break;
2200f74e101Schristos       default:
221c74ad251Schristos 	ND_PRINT("ipx-sap-?%x", command);
2220f74e101Schristos 	break;
2230f74e101Schristos     }
2240f74e101Schristos     return;
225c74ad251Schristos 
226c74ad251Schristos invalid:
227c74ad251Schristos     nd_print_invalid(ndo);
2280f74e101Schristos }
2290f74e101Schristos 
230b3a00663Schristos static void
231c74ad251Schristos ipx_rip_print(netdissect_options *ndo, const u_char *ipx, u_int length)
2320f74e101Schristos {
2330f74e101Schristos     int command, i;
2340f74e101Schristos 
235c74ad251Schristos     command = GET_BE_U_2(ipx);
236*26ba0b50Schristos     ND_ICHECK_U(length, <, 2);
237c74ad251Schristos     ipx += 2;
2380f74e101Schristos     length -= 2;
2390f74e101Schristos 
2400f74e101Schristos     switch (command) {
2410f74e101Schristos       case 1:
242c74ad251Schristos 	ND_PRINT("ipx-rip-req");
243c74ad251Schristos 	if (length != 0) {
244c74ad251Schristos 	    if (length < 8)
245c74ad251Schristos 		goto invalid;
246c74ad251Schristos 	    ND_PRINT(" %08x/%u.%u", GET_BE_U_4(ipx),
247c74ad251Schristos 			 GET_BE_U_2(ipx + 4), GET_BE_U_2(ipx + 6));
2480f74e101Schristos 	}
2490f74e101Schristos 	break;
2500f74e101Schristos       case 2:
251c74ad251Schristos 	ND_PRINT("ipx-rip-resp");
252c74ad251Schristos 	for (i = 0; i < 50 && length != 0; i++) {
253c74ad251Schristos 	    if (length < 8)
254c74ad251Schristos 		goto invalid;
255c74ad251Schristos 	    ND_PRINT(" %08x/%u.%u", GET_BE_U_4(ipx),
256c74ad251Schristos 			 GET_BE_U_2(ipx + 4), GET_BE_U_2(ipx + 6));
2570f74e101Schristos 
258c74ad251Schristos 	    ipx += 8;
2590f74e101Schristos 	    length -= 8;
2600f74e101Schristos 	}
2610f74e101Schristos 	break;
2620f74e101Schristos       default:
263c74ad251Schristos 	ND_PRINT("ipx-rip-?%x", command);
2640f74e101Schristos 	break;
2650f74e101Schristos     }
2660f74e101Schristos     return;
267c74ad251Schristos 
268c74ad251Schristos invalid:
269c74ad251Schristos     nd_print_invalid(ndo);
2700f74e101Schristos }
271