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