1a90e161bSBill Fenner /* 2a90e161bSBill Fenner * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 3a90e161bSBill Fenner * The Regents of the University of California. All rights reserved. 4a90e161bSBill Fenner * 5a90e161bSBill Fenner * Redistribution and use in source and binary forms, with or without 6a90e161bSBill Fenner * modification, are permitted provided that: (1) source code distributions 7a90e161bSBill Fenner * retain the above copyright notice and this paragraph in its entirety, (2) 8a90e161bSBill Fenner * distributions including binary code include the above copyright notice and 9a90e161bSBill Fenner * this paragraph in its entirety in the documentation or other materials 10a90e161bSBill Fenner * provided with the distribution, and (3) all advertising materials mentioning 11a90e161bSBill Fenner * features or use of this software display the following acknowledgement: 12a90e161bSBill Fenner * ``This product includes software developed by the University of California, 13a90e161bSBill Fenner * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14a90e161bSBill Fenner * the University nor the names of its contributors may be used to endorse 15a90e161bSBill Fenner * or promote products derived from this software without specific prior 16a90e161bSBill Fenner * written permission. 17a90e161bSBill Fenner * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18a90e161bSBill Fenner * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19a90e161bSBill Fenner * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20a90e161bSBill Fenner * 21a90e161bSBill Fenner * From: NetBSD: print-arcnet.c,v 1.2 2000/04/24 13:02:28 itojun Exp 22a90e161bSBill Fenner */ 23a90e161bSBill Fenner 243340d773SGleb Smirnoff /* \summary: Attached Resource Computer NETwork (ARCNET) printer */ 253340d773SGleb Smirnoff 26*ee67461eSJoseph Mingrone #include <config.h> 27a90e161bSBill Fenner 28*ee67461eSJoseph Mingrone #include "netdissect-stdinc.h" 29a90e161bSBill Fenner 303340d773SGleb Smirnoff #include "netdissect.h" 3127df3f5dSRui Paulo #include "extract.h" 32a90e161bSBill Fenner 333c602fabSXin LI /* 343c602fabSXin LI * from: NetBSD: if_arc.h,v 1.13 1999/11/19 20:41:19 thorpej Exp 353c602fabSXin LI */ 363c602fabSXin LI 373c602fabSXin LI /* 383c602fabSXin LI * Structure of a 2.5MB/s Arcnet header on the BSDs, 393c602fabSXin LI * as given to interface code. 403c602fabSXin LI */ 413c602fabSXin LI struct arc_header { 42*ee67461eSJoseph Mingrone nd_uint8_t arc_shost; 43*ee67461eSJoseph Mingrone nd_uint8_t arc_dhost; 44*ee67461eSJoseph Mingrone nd_uint8_t arc_type; 453c602fabSXin LI /* 463c602fabSXin LI * only present for newstyle encoding with LL fragmentation. 473c602fabSXin LI * Don't use sizeof(anything), use ARC_HDR{,NEW}LEN instead. 483c602fabSXin LI */ 49*ee67461eSJoseph Mingrone nd_uint8_t arc_flag; 50*ee67461eSJoseph Mingrone nd_uint16_t arc_seqid; 513c602fabSXin LI 523c602fabSXin LI /* 533c602fabSXin LI * only present in exception packets (arc_flag == 0xff) 543c602fabSXin LI */ 55*ee67461eSJoseph Mingrone nd_uint8_t arc_type2; /* same as arc_type */ 56*ee67461eSJoseph Mingrone nd_uint8_t arc_flag2; /* real flag value */ 57*ee67461eSJoseph Mingrone nd_uint16_t arc_seqid2; /* real seqid value */ 583c602fabSXin LI }; 593c602fabSXin LI 603c602fabSXin LI #define ARC_HDRLEN 3 613c602fabSXin LI #define ARC_HDRNEWLEN 6 623c602fabSXin LI #define ARC_HDRNEWLEN_EXC 10 633c602fabSXin LI 643c602fabSXin LI /* RFC 1051 */ 653c602fabSXin LI #define ARCTYPE_IP_OLD 240 /* IP protocol */ 663c602fabSXin LI #define ARCTYPE_ARP_OLD 241 /* address resolution protocol */ 673c602fabSXin LI 683c602fabSXin LI /* RFC 1201 */ 693c602fabSXin LI #define ARCTYPE_IP 212 /* IP protocol */ 703c602fabSXin LI #define ARCTYPE_ARP 213 /* address resolution protocol */ 713c602fabSXin LI #define ARCTYPE_REVARP 214 /* reverse addr resolution protocol */ 723c602fabSXin LI 733c602fabSXin LI #define ARCTYPE_ATALK 221 /* Appletalk */ 743c602fabSXin LI #define ARCTYPE_BANIAN 247 /* Banyan Vines */ 753c602fabSXin LI #define ARCTYPE_IPX 250 /* Novell IPX */ 763c602fabSXin LI 773c602fabSXin LI #define ARCTYPE_INET6 0xc4 /* IPng */ 783c602fabSXin LI #define ARCTYPE_DIAGNOSE 0x80 /* as per ANSI/ATA 878.1 */ 793c602fabSXin LI 803c602fabSXin LI /* 813c602fabSXin LI * Structure of a 2.5MB/s Arcnet header on Linux. Linux has 823c602fabSXin LI * an extra "offset" field when given to interface code, and 833c602fabSXin LI * never presents packets that look like exception frames. 843c602fabSXin LI */ 853c602fabSXin LI struct arc_linux_header { 86*ee67461eSJoseph Mingrone nd_uint8_t arc_shost; 87*ee67461eSJoseph Mingrone nd_uint8_t arc_dhost; 88*ee67461eSJoseph Mingrone nd_uint16_t arc_offset; 89*ee67461eSJoseph Mingrone nd_uint8_t arc_type; 903c602fabSXin LI /* 913c602fabSXin LI * only present for newstyle encoding with LL fragmentation. 923c602fabSXin LI * Don't use sizeof(anything), use ARC_LINUX_HDR{,NEW}LEN 933c602fabSXin LI * instead. 943c602fabSXin LI */ 95*ee67461eSJoseph Mingrone nd_uint8_t arc_flag; 96*ee67461eSJoseph Mingrone nd_uint16_t arc_seqid; 973c602fabSXin LI }; 983c602fabSXin LI 993c602fabSXin LI #define ARC_LINUX_HDRLEN 5 1003c602fabSXin LI #define ARC_LINUX_HDRNEWLEN 8 1013c602fabSXin LI 1023c602fabSXin LI static int arcnet_encap_print(netdissect_options *, u_char arctype, const u_char *p, 103a90e161bSBill Fenner u_int length, u_int caplen); 104a90e161bSBill Fenner 1053c602fabSXin LI static const struct tok arctypemap[] = { 106a90e161bSBill Fenner { ARCTYPE_IP_OLD, "oldip" }, 107a90e161bSBill Fenner { ARCTYPE_ARP_OLD, "oldarp" }, 108a90e161bSBill Fenner { ARCTYPE_IP, "ip" }, 109a90e161bSBill Fenner { ARCTYPE_ARP, "arp" }, 110a90e161bSBill Fenner { ARCTYPE_REVARP, "rarp" }, 111a90e161bSBill Fenner { ARCTYPE_ATALK, "atalk" }, 112a90e161bSBill Fenner { ARCTYPE_BANIAN, "banyan" }, 113a90e161bSBill Fenner { ARCTYPE_IPX, "ipx" }, 114a90e161bSBill Fenner { ARCTYPE_INET6, "ipv6" }, 115a90e161bSBill Fenner { ARCTYPE_DIAGNOSE, "diag" }, 116*ee67461eSJoseph Mingrone { 0, NULL } 117a90e161bSBill Fenner }; 118a90e161bSBill Fenner 119*ee67461eSJoseph Mingrone static void 1203c602fabSXin LI arcnet_print(netdissect_options *ndo, const u_char *bp, u_int length, int phds, 121*ee67461eSJoseph Mingrone u_int flag, u_int seqid) 122a90e161bSBill Fenner { 123a90e161bSBill Fenner const struct arc_header *ap; 124a90e161bSBill Fenner const char *arctypename; 125a90e161bSBill Fenner 126*ee67461eSJoseph Mingrone ndo->ndo_protocol = "arcnet"; 127a90e161bSBill Fenner ap = (const struct arc_header *)bp; 128a90e161bSBill Fenner 1293c602fabSXin LI if (ndo->ndo_qflag) { 130*ee67461eSJoseph Mingrone ND_PRINT("%02x %02x %u: ", 131*ee67461eSJoseph Mingrone GET_U_1(ap->arc_shost), 132*ee67461eSJoseph Mingrone GET_U_1(ap->arc_dhost), 133*ee67461eSJoseph Mingrone length); 134a90e161bSBill Fenner return; 135a90e161bSBill Fenner } 136a90e161bSBill Fenner 137*ee67461eSJoseph Mingrone arctypename = tok2str(arctypemap, "%02x", GET_U_1(ap->arc_type)); 138a90e161bSBill Fenner 139a90e161bSBill Fenner if (!phds) { 140*ee67461eSJoseph Mingrone ND_PRINT("%02x %02x %s %u: ", 141*ee67461eSJoseph Mingrone GET_U_1(ap->arc_shost), 142*ee67461eSJoseph Mingrone GET_U_1(ap->arc_dhost), 143*ee67461eSJoseph Mingrone arctypename, 144*ee67461eSJoseph Mingrone length); 145a90e161bSBill Fenner return; 146a90e161bSBill Fenner } 147a90e161bSBill Fenner 148a90e161bSBill Fenner if (flag == 0) { 149*ee67461eSJoseph Mingrone ND_PRINT("%02x %02x %s seqid %04x %u: ", 150*ee67461eSJoseph Mingrone GET_U_1(ap->arc_shost), 151*ee67461eSJoseph Mingrone GET_U_1(ap->arc_dhost), 152*ee67461eSJoseph Mingrone arctypename, seqid, 153*ee67461eSJoseph Mingrone length); 154a90e161bSBill Fenner return; 155a90e161bSBill Fenner } 156a90e161bSBill Fenner 157a90e161bSBill Fenner if (flag & 1) 158*ee67461eSJoseph Mingrone ND_PRINT("%02x %02x %s seqid %04x " 159*ee67461eSJoseph Mingrone "(first of %u fragments) %u: ", 160*ee67461eSJoseph Mingrone GET_U_1(ap->arc_shost), 161*ee67461eSJoseph Mingrone GET_U_1(ap->arc_dhost), 162*ee67461eSJoseph Mingrone arctypename, seqid, 163*ee67461eSJoseph Mingrone (flag + 3) / 2, length); 164a90e161bSBill Fenner else 165*ee67461eSJoseph Mingrone ND_PRINT("%02x %02x %s seqid %04x " 166*ee67461eSJoseph Mingrone "(fragment %u) %u: ", 167*ee67461eSJoseph Mingrone GET_U_1(ap->arc_shost), 168*ee67461eSJoseph Mingrone GET_U_1(ap->arc_dhost), 169*ee67461eSJoseph Mingrone arctypename, seqid, 170*ee67461eSJoseph Mingrone flag/2 + 1, length); 171a90e161bSBill Fenner } 172a90e161bSBill Fenner 173a90e161bSBill Fenner /* 1745b0fe478SBruce M Simpson * This is the top level routine of the printer. 'p' points 1755b0fe478SBruce M Simpson * to the ARCNET header of the packet, 'h->ts' is the timestamp, 1761de50e9fSSam Leffler * 'h->len' is the length of the packet off the wire, and 'h->caplen' 177a90e161bSBill Fenner * is the number of bytes actually captured. 178a90e161bSBill Fenner */ 179*ee67461eSJoseph Mingrone void 1803c602fabSXin LI arcnet_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) 181a90e161bSBill Fenner { 182a90e161bSBill Fenner u_int caplen = h->caplen; 183a90e161bSBill Fenner u_int length = h->len; 184a90e161bSBill Fenner const struct arc_header *ap; 185a90e161bSBill Fenner 186*ee67461eSJoseph Mingrone int phds; 187*ee67461eSJoseph Mingrone u_int flag = 0, archdrlen = 0; 188a90e161bSBill Fenner u_int seqid = 0; 189a90e161bSBill Fenner u_char arc_type; 190a90e161bSBill Fenner 191*ee67461eSJoseph Mingrone ndo->ndo_protocol = "arcnet"; 192*ee67461eSJoseph Mingrone if (caplen < ARC_HDRLEN) { 193*ee67461eSJoseph Mingrone ndo->ndo_ll_hdr_len += caplen; 194*ee67461eSJoseph Mingrone nd_trunc_longjmp(ndo); 195a90e161bSBill Fenner } 196a90e161bSBill Fenner 197a90e161bSBill Fenner ap = (const struct arc_header *)p; 198*ee67461eSJoseph Mingrone arc_type = GET_U_1(ap->arc_type); 199a90e161bSBill Fenner 200a90e161bSBill Fenner switch (arc_type) { 201a90e161bSBill Fenner default: 202a90e161bSBill Fenner phds = 1; 203a90e161bSBill Fenner break; 204a90e161bSBill Fenner case ARCTYPE_IP_OLD: 205a90e161bSBill Fenner case ARCTYPE_ARP_OLD: 206a90e161bSBill Fenner case ARCTYPE_DIAGNOSE: 207a90e161bSBill Fenner phds = 0; 208a90e161bSBill Fenner archdrlen = ARC_HDRLEN; 209a90e161bSBill Fenner break; 210a90e161bSBill Fenner } 211a90e161bSBill Fenner 212a90e161bSBill Fenner if (phds) { 213*ee67461eSJoseph Mingrone if (caplen < ARC_HDRNEWLEN) { 2143c602fabSXin LI arcnet_print(ndo, p, length, 0, 0, 0); 215*ee67461eSJoseph Mingrone ND_PRINT(" phds"); 216*ee67461eSJoseph Mingrone ndo->ndo_ll_hdr_len += caplen; 217*ee67461eSJoseph Mingrone nd_trunc_longjmp(ndo); 218a90e161bSBill Fenner } 219a90e161bSBill Fenner 220*ee67461eSJoseph Mingrone flag = GET_U_1(ap->arc_flag); 221*ee67461eSJoseph Mingrone if (flag == 0xff) { 222*ee67461eSJoseph Mingrone if (caplen < ARC_HDRNEWLEN_EXC) { 2233c602fabSXin LI arcnet_print(ndo, p, length, 0, 0, 0); 224*ee67461eSJoseph Mingrone ND_PRINT(" phds extended"); 225*ee67461eSJoseph Mingrone ndo->ndo_ll_hdr_len += caplen; 226*ee67461eSJoseph Mingrone nd_trunc_longjmp(ndo); 227a90e161bSBill Fenner } 228*ee67461eSJoseph Mingrone flag = GET_U_1(ap->arc_flag2); 229*ee67461eSJoseph Mingrone seqid = GET_BE_U_2(ap->arc_seqid2); 230a90e161bSBill Fenner archdrlen = ARC_HDRNEWLEN_EXC; 231a90e161bSBill Fenner } else { 232*ee67461eSJoseph Mingrone seqid = GET_BE_U_2(ap->arc_seqid); 233a90e161bSBill Fenner archdrlen = ARC_HDRNEWLEN; 234a90e161bSBill Fenner } 235a90e161bSBill Fenner } 236a90e161bSBill Fenner 237a90e161bSBill Fenner 2383c602fabSXin LI if (ndo->ndo_eflag) 2393c602fabSXin LI arcnet_print(ndo, p, length, phds, flag, seqid); 240a90e161bSBill Fenner 241a90e161bSBill Fenner /* 2425b0fe478SBruce M Simpson * Go past the ARCNET header. 243a90e161bSBill Fenner */ 244a90e161bSBill Fenner length -= archdrlen; 245a90e161bSBill Fenner caplen -= archdrlen; 246a90e161bSBill Fenner p += archdrlen; 247a90e161bSBill Fenner 2485b0fe478SBruce M Simpson if (phds && flag && (flag & 1) == 0) { 2495b0fe478SBruce M Simpson /* 2505b0fe478SBruce M Simpson * This is a middle fragment. 2515b0fe478SBruce M Simpson */ 252*ee67461eSJoseph Mingrone ndo->ndo_ll_hdr_len += archdrlen; 253*ee67461eSJoseph Mingrone return; 254a90e161bSBill Fenner } 255a90e161bSBill Fenner 2563c602fabSXin LI if (!arcnet_encap_print(ndo, arc_type, p, length, caplen)) 2573c602fabSXin LI ND_DEFAULTPRINT(p, caplen); 258a90e161bSBill Fenner 259*ee67461eSJoseph Mingrone ndo->ndo_ll_hdr_len += archdrlen; 2605b0fe478SBruce M Simpson } 2615b0fe478SBruce M Simpson 2625b0fe478SBruce M Simpson /* 2635b0fe478SBruce M Simpson * This is the top level routine of the printer. 'p' points 2645b0fe478SBruce M Simpson * to the ARCNET header of the packet, 'h->ts' is the timestamp, 2651de50e9fSSam Leffler * 'h->len' is the length of the packet off the wire, and 'h->caplen' 2665b0fe478SBruce M Simpson * is the number of bytes actually captured. It is quite similar 2675b0fe478SBruce M Simpson * to the non-Linux style printer except that Linux doesn't ever 2685b0fe478SBruce M Simpson * supply packets that look like exception frames, it always supplies 2695b0fe478SBruce M Simpson * reassembled packets rather than raw frames, and headers have an 2705b0fe478SBruce M Simpson * extra "offset" field between the src/dest and packet type. 2715b0fe478SBruce M Simpson */ 272*ee67461eSJoseph Mingrone void 2733c602fabSXin LI arcnet_linux_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) 2745b0fe478SBruce M Simpson { 2755b0fe478SBruce M Simpson u_int caplen = h->caplen; 2765b0fe478SBruce M Simpson u_int length = h->len; 2775b0fe478SBruce M Simpson const struct arc_linux_header *ap; 2785b0fe478SBruce M Simpson 2795b0fe478SBruce M Simpson int archdrlen = 0; 2805b0fe478SBruce M Simpson u_char arc_type; 2815b0fe478SBruce M Simpson 282*ee67461eSJoseph Mingrone ndo->ndo_protocol = "arcnet_linux"; 283*ee67461eSJoseph Mingrone if (caplen < ARC_LINUX_HDRLEN) { 284*ee67461eSJoseph Mingrone ndo->ndo_ll_hdr_len += caplen; 285*ee67461eSJoseph Mingrone nd_trunc_longjmp(ndo); 2865b0fe478SBruce M Simpson } 2875b0fe478SBruce M Simpson 2885b0fe478SBruce M Simpson ap = (const struct arc_linux_header *)p; 289*ee67461eSJoseph Mingrone arc_type = GET_U_1(ap->arc_type); 2905b0fe478SBruce M Simpson 2915b0fe478SBruce M Simpson switch (arc_type) { 2925b0fe478SBruce M Simpson default: 2935b0fe478SBruce M Simpson archdrlen = ARC_LINUX_HDRNEWLEN; 294*ee67461eSJoseph Mingrone if (caplen < ARC_LINUX_HDRNEWLEN) { 295*ee67461eSJoseph Mingrone ndo->ndo_ll_hdr_len += caplen; 296*ee67461eSJoseph Mingrone nd_trunc_longjmp(ndo); 2975b0fe478SBruce M Simpson } 2985b0fe478SBruce M Simpson break; 2995b0fe478SBruce M Simpson case ARCTYPE_IP_OLD: 3005b0fe478SBruce M Simpson case ARCTYPE_ARP_OLD: 3015b0fe478SBruce M Simpson case ARCTYPE_DIAGNOSE: 3025b0fe478SBruce M Simpson archdrlen = ARC_LINUX_HDRLEN; 3035b0fe478SBruce M Simpson break; 3045b0fe478SBruce M Simpson } 3055b0fe478SBruce M Simpson 3063c602fabSXin LI if (ndo->ndo_eflag) 3073c602fabSXin LI arcnet_print(ndo, p, length, 0, 0, 0); 3085b0fe478SBruce M Simpson 3095b0fe478SBruce M Simpson /* 3105b0fe478SBruce M Simpson * Go past the ARCNET header. 3115b0fe478SBruce M Simpson */ 3125b0fe478SBruce M Simpson length -= archdrlen; 3135b0fe478SBruce M Simpson caplen -= archdrlen; 3145b0fe478SBruce M Simpson p += archdrlen; 3155b0fe478SBruce M Simpson 3163c602fabSXin LI if (!arcnet_encap_print(ndo, arc_type, p, length, caplen)) 3173c602fabSXin LI ND_DEFAULTPRINT(p, caplen); 3185b0fe478SBruce M Simpson 319*ee67461eSJoseph Mingrone ndo->ndo_ll_hdr_len += archdrlen; 320a90e161bSBill Fenner } 321a90e161bSBill Fenner 322a90e161bSBill Fenner /* 323a90e161bSBill Fenner * Prints the packet encapsulated in an ARCnet data field, 324a90e161bSBill Fenner * given the ARCnet system code. 325a90e161bSBill Fenner * 326a90e161bSBill Fenner * Returns non-zero if it can do so, zero if the system code is unknown. 327a90e161bSBill Fenner */ 328a90e161bSBill Fenner 329a90e161bSBill Fenner 3305b0fe478SBruce M Simpson static int 3313c602fabSXin LI arcnet_encap_print(netdissect_options *ndo, u_char arctype, const u_char *p, 332a90e161bSBill Fenner u_int length, u_int caplen) 333a90e161bSBill Fenner { 334a90e161bSBill Fenner switch (arctype) { 335a90e161bSBill Fenner 336a90e161bSBill Fenner case ARCTYPE_IP_OLD: 337a90e161bSBill Fenner case ARCTYPE_IP: 3383c602fabSXin LI ip_print(ndo, p, length); 339a90e161bSBill Fenner return (1); 340a90e161bSBill Fenner 341a90e161bSBill Fenner case ARCTYPE_INET6: 3423c602fabSXin LI ip6_print(ndo, p, length); 343a90e161bSBill Fenner return (1); 344a90e161bSBill Fenner 345a90e161bSBill Fenner case ARCTYPE_ARP_OLD: 346a90e161bSBill Fenner case ARCTYPE_ARP: 347a90e161bSBill Fenner case ARCTYPE_REVARP: 3483c602fabSXin LI arp_print(ndo, p, length, caplen); 349a90e161bSBill Fenner return (1); 350a90e161bSBill Fenner 351a90e161bSBill Fenner case ARCTYPE_ATALK: /* XXX was this ever used? */ 3523c602fabSXin LI if (ndo->ndo_vflag) 353*ee67461eSJoseph Mingrone ND_PRINT("et1 "); 3543c602fabSXin LI atalk_print(ndo, p, length); 355a90e161bSBill Fenner return (1); 356a90e161bSBill Fenner 3575b0fe478SBruce M Simpson case ARCTYPE_IPX: 3583c602fabSXin LI ipx_print(ndo, p, length); 3595b0fe478SBruce M Simpson return (1); 3605b0fe478SBruce M Simpson 361a90e161bSBill Fenner default: 362a90e161bSBill Fenner return (0); 363a90e161bSBill Fenner } 364a90e161bSBill Fenner } 365