198524Sfenner/* 298524Sfenner * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 398524Sfenner * The Regents of the University of California. All rights reserved. 498524Sfenner * 598524Sfenner * Redistribution and use in source and binary forms, with or without 698524Sfenner * modification, are permitted provided that: (1) source code distributions 798524Sfenner * retain the above copyright notice and this paragraph in its entirety, (2) 898524Sfenner * distributions including binary code include the above copyright notice and 998524Sfenner * this paragraph in its entirety in the documentation or other materials 1098524Sfenner * provided with the distribution, and (3) all advertising materials mentioning 1198524Sfenner * features or use of this software display the following acknowledgement: 1298524Sfenner * ``This product includes software developed by the University of California, 1398524Sfenner * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1498524Sfenner * the University nor the names of its contributors may be used to endorse 1598524Sfenner * or promote products derived from this software without specific prior 1698524Sfenner * written permission. 1798524Sfenner * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1898524Sfenner * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 1998524Sfenner * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20127668Sbms * 2198524Sfenner * From: NetBSD: print-arcnet.c,v 1.2 2000/04/24 13:02:28 itojun Exp 2298524Sfenner */ 2398524Sfenner 24276788Sdelphij#define NETDISSECT_REWORKED 2598524Sfenner#ifdef HAVE_CONFIG_H 2698524Sfenner#include "config.h" 2798524Sfenner#endif 2898524Sfenner 29127668Sbms#include <tcpdump-stdinc.h> 3098524Sfenner 3198524Sfenner#include "interface.h" 32214478Srpaulo#include "extract.h" 3398524Sfenner 34276788Sdelphij/* 35276788Sdelphij * from: NetBSD: if_arc.h,v 1.13 1999/11/19 20:41:19 thorpej Exp 36276788Sdelphij */ 37276788Sdelphij 38276788Sdelphij/* 39276788Sdelphij * Structure of a 2.5MB/s Arcnet header on the BSDs, 40276788Sdelphij * as given to interface code. 41276788Sdelphij */ 42276788Sdelphijstruct arc_header { 43276788Sdelphij uint8_t arc_shost; 44276788Sdelphij uint8_t arc_dhost; 45276788Sdelphij uint8_t arc_type; 46276788Sdelphij /* 47276788Sdelphij * only present for newstyle encoding with LL fragmentation. 48276788Sdelphij * Don't use sizeof(anything), use ARC_HDR{,NEW}LEN instead. 49276788Sdelphij */ 50276788Sdelphij uint8_t arc_flag; 51276788Sdelphij uint16_t arc_seqid; 52276788Sdelphij 53276788Sdelphij /* 54276788Sdelphij * only present in exception packets (arc_flag == 0xff) 55276788Sdelphij */ 56276788Sdelphij uint8_t arc_type2; /* same as arc_type */ 57276788Sdelphij uint8_t arc_flag2; /* real flag value */ 58276788Sdelphij uint16_t arc_seqid2; /* real seqid value */ 59276788Sdelphij}; 60276788Sdelphij 61276788Sdelphij#define ARC_HDRLEN 3 62276788Sdelphij#define ARC_HDRNEWLEN 6 63276788Sdelphij#define ARC_HDRNEWLEN_EXC 10 64276788Sdelphij 65276788Sdelphij/* RFC 1051 */ 66276788Sdelphij#define ARCTYPE_IP_OLD 240 /* IP protocol */ 67276788Sdelphij#define ARCTYPE_ARP_OLD 241 /* address resolution protocol */ 68276788Sdelphij 69276788Sdelphij/* RFC 1201 */ 70276788Sdelphij#define ARCTYPE_IP 212 /* IP protocol */ 71276788Sdelphij#define ARCTYPE_ARP 213 /* address resolution protocol */ 72276788Sdelphij#define ARCTYPE_REVARP 214 /* reverse addr resolution protocol */ 73276788Sdelphij 74276788Sdelphij#define ARCTYPE_ATALK 221 /* Appletalk */ 75276788Sdelphij#define ARCTYPE_BANIAN 247 /* Banyan Vines */ 76276788Sdelphij#define ARCTYPE_IPX 250 /* Novell IPX */ 77276788Sdelphij 78276788Sdelphij#define ARCTYPE_INET6 0xc4 /* IPng */ 79276788Sdelphij#define ARCTYPE_DIAGNOSE 0x80 /* as per ANSI/ATA 878.1 */ 80276788Sdelphij 81276788Sdelphij/* 82276788Sdelphij * Structure of a 2.5MB/s Arcnet header on Linux. Linux has 83276788Sdelphij * an extra "offset" field when given to interface code, and 84276788Sdelphij * never presents packets that look like exception frames. 85276788Sdelphij */ 86276788Sdelphijstruct arc_linux_header { 87276788Sdelphij uint8_t arc_shost; 88276788Sdelphij uint8_t arc_dhost; 89276788Sdelphij uint16_t arc_offset; 90276788Sdelphij uint8_t arc_type; 91276788Sdelphij /* 92276788Sdelphij * only present for newstyle encoding with LL fragmentation. 93276788Sdelphij * Don't use sizeof(anything), use ARC_LINUX_HDR{,NEW}LEN 94276788Sdelphij * instead. 95276788Sdelphij */ 96276788Sdelphij uint8_t arc_flag; 97276788Sdelphij uint16_t arc_seqid; 98276788Sdelphij}; 99276788Sdelphij 100276788Sdelphij#define ARC_LINUX_HDRLEN 5 101276788Sdelphij#define ARC_LINUX_HDRNEWLEN 8 102276788Sdelphij 103276788Sdelphijstatic int arcnet_encap_print(netdissect_options *, u_char arctype, const u_char *p, 10498524Sfenner u_int length, u_int caplen); 10598524Sfenner 106276788Sdelphijstatic const struct tok arctypemap[] = { 10798524Sfenner { ARCTYPE_IP_OLD, "oldip" }, 10898524Sfenner { ARCTYPE_ARP_OLD, "oldarp" }, 10998524Sfenner { ARCTYPE_IP, "ip" }, 11098524Sfenner { ARCTYPE_ARP, "arp" }, 11198524Sfenner { ARCTYPE_REVARP, "rarp" }, 11298524Sfenner { ARCTYPE_ATALK, "atalk" }, 11398524Sfenner { ARCTYPE_BANIAN, "banyan" }, 11498524Sfenner { ARCTYPE_IPX, "ipx" }, 11598524Sfenner { ARCTYPE_INET6, "ipv6" }, 11698524Sfenner { ARCTYPE_DIAGNOSE, "diag" }, 11798524Sfenner { 0, 0 } 11898524Sfenner}; 11998524Sfenner 12098524Sfennerstatic inline void 121276788Sdelphijarcnet_print(netdissect_options *ndo, const u_char *bp, u_int length, int phds, 122276788Sdelphij int flag, u_int seqid) 12398524Sfenner{ 12498524Sfenner const struct arc_header *ap; 12598524Sfenner const char *arctypename; 12698524Sfenner 12798524Sfenner 12898524Sfenner ap = (const struct arc_header *)bp; 12998524Sfenner 13098524Sfenner 131276788Sdelphij if (ndo->ndo_qflag) { 132276788Sdelphij ND_PRINT((ndo, "%02x %02x %d: ", 13398524Sfenner ap->arc_shost, 13498524Sfenner ap->arc_dhost, 135276788Sdelphij length)); 13698524Sfenner return; 13798524Sfenner } 13898524Sfenner 13998524Sfenner arctypename = tok2str(arctypemap, "%02x", ap->arc_type); 14098524Sfenner 14198524Sfenner if (!phds) { 142276788Sdelphij ND_PRINT((ndo, "%02x %02x %s %d: ", 14398524Sfenner ap->arc_shost, ap->arc_dhost, arctypename, 144276788Sdelphij length)); 14598524Sfenner return; 14698524Sfenner } 14798524Sfenner 14898524Sfenner if (flag == 0) { 149276788Sdelphij ND_PRINT((ndo, "%02x %02x %s seqid %04x %d: ", 15098524Sfenner ap->arc_shost, ap->arc_dhost, arctypename, seqid, 151276788Sdelphij length)); 15298524Sfenner return; 15398524Sfenner } 15498524Sfenner 15598524Sfenner if (flag & 1) 156276788Sdelphij ND_PRINT((ndo, "%02x %02x %s seqid %04x " 15798524Sfenner "(first of %d fragments) %d: ", 15898524Sfenner ap->arc_shost, ap->arc_dhost, arctypename, seqid, 159276788Sdelphij (flag + 3) / 2, length)); 16098524Sfenner else 161276788Sdelphij ND_PRINT((ndo, "%02x %02x %s seqid %04x " 16298524Sfenner "(fragment %d) %d: ", 16398524Sfenner ap->arc_shost, ap->arc_dhost, arctypename, seqid, 164276788Sdelphij flag/2 + 1, length)); 16598524Sfenner} 16698524Sfenner 16798524Sfenner/* 168127668Sbms * This is the top level routine of the printer. 'p' points 169127668Sbms * to the ARCNET header of the packet, 'h->ts' is the timestamp, 170146773Ssam * 'h->len' is the length of the packet off the wire, and 'h->caplen' 17198524Sfenner * is the number of bytes actually captured. 17298524Sfenner */ 173127668Sbmsu_int 174276788Sdelphijarcnet_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) 17598524Sfenner{ 17698524Sfenner u_int caplen = h->caplen; 17798524Sfenner u_int length = h->len; 17898524Sfenner const struct arc_header *ap; 17998524Sfenner 18098524Sfenner int phds, flag = 0, archdrlen = 0; 18198524Sfenner u_int seqid = 0; 18298524Sfenner u_char arc_type; 18398524Sfenner 184285275Spkelsey if (caplen < ARC_HDRLEN || length < ARC_HDRLEN) { 185276788Sdelphij ND_PRINT((ndo, "[|arcnet]")); 186127668Sbms return (caplen); 18798524Sfenner } 18898524Sfenner 18998524Sfenner ap = (const struct arc_header *)p; 19098524Sfenner arc_type = ap->arc_type; 19198524Sfenner 19298524Sfenner switch (arc_type) { 19398524Sfenner default: 19498524Sfenner phds = 1; 19598524Sfenner break; 19698524Sfenner case ARCTYPE_IP_OLD: 19798524Sfenner case ARCTYPE_ARP_OLD: 19898524Sfenner case ARCTYPE_DIAGNOSE: 19998524Sfenner phds = 0; 20098524Sfenner archdrlen = ARC_HDRLEN; 20198524Sfenner break; 20298524Sfenner } 20398524Sfenner 20498524Sfenner if (phds) { 205285275Spkelsey if (caplen < ARC_HDRNEWLEN || length < ARC_HDRNEWLEN) { 206276788Sdelphij arcnet_print(ndo, p, length, 0, 0, 0); 207276788Sdelphij ND_PRINT((ndo, "[|phds]")); 208127668Sbms return (caplen); 20998524Sfenner } 21098524Sfenner 21198524Sfenner if (ap->arc_flag == 0xff) { 212285275Spkelsey if (caplen < ARC_HDRNEWLEN_EXC || length < ARC_HDRNEWLEN_EXC) { 213276788Sdelphij arcnet_print(ndo, p, length, 0, 0, 0); 214276788Sdelphij ND_PRINT((ndo, "[|phds extended]")); 215127668Sbms return (caplen); 21698524Sfenner } 21798524Sfenner flag = ap->arc_flag2; 218214478Srpaulo seqid = EXTRACT_16BITS(&ap->arc_seqid2); 21998524Sfenner archdrlen = ARC_HDRNEWLEN_EXC; 22098524Sfenner } else { 22198524Sfenner flag = ap->arc_flag; 222214478Srpaulo seqid = EXTRACT_16BITS(&ap->arc_seqid); 22398524Sfenner archdrlen = ARC_HDRNEWLEN; 22498524Sfenner } 22598524Sfenner } 22698524Sfenner 22798524Sfenner 228276788Sdelphij if (ndo->ndo_eflag) 229276788Sdelphij arcnet_print(ndo, p, length, phds, flag, seqid); 23098524Sfenner 23198524Sfenner /* 232127668Sbms * Go past the ARCNET header. 23398524Sfenner */ 23498524Sfenner length -= archdrlen; 23598524Sfenner caplen -= archdrlen; 23698524Sfenner p += archdrlen; 23798524Sfenner 238127668Sbms if (phds && flag && (flag & 1) == 0) { 239127668Sbms /* 240127668Sbms * This is a middle fragment. 241127668Sbms */ 242127668Sbms return (archdrlen); 243127668Sbms } 24498524Sfenner 245276788Sdelphij if (!arcnet_encap_print(ndo, arc_type, p, length, caplen)) 246276788Sdelphij ND_DEFAULTPRINT(p, caplen); 247127668Sbms 248127668Sbms return (archdrlen); 249127668Sbms} 250127668Sbms 251127668Sbms/* 252127668Sbms * This is the top level routine of the printer. 'p' points 253127668Sbms * to the ARCNET header of the packet, 'h->ts' is the timestamp, 254146773Ssam * 'h->len' is the length of the packet off the wire, and 'h->caplen' 255127668Sbms * is the number of bytes actually captured. It is quite similar 256127668Sbms * to the non-Linux style printer except that Linux doesn't ever 257127668Sbms * supply packets that look like exception frames, it always supplies 258127668Sbms * reassembled packets rather than raw frames, and headers have an 259127668Sbms * extra "offset" field between the src/dest and packet type. 260127668Sbms */ 261127668Sbmsu_int 262276788Sdelphijarcnet_linux_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) 263127668Sbms{ 264127668Sbms u_int caplen = h->caplen; 265127668Sbms u_int length = h->len; 266127668Sbms const struct arc_linux_header *ap; 267127668Sbms 268127668Sbms int archdrlen = 0; 269127668Sbms u_char arc_type; 270127668Sbms 271285275Spkelsey if (caplen < ARC_LINUX_HDRLEN || length < ARC_LINUX_HDRLEN) { 272276788Sdelphij ND_PRINT((ndo, "[|arcnet]")); 273127668Sbms return (caplen); 27498524Sfenner } 27598524Sfenner 276127668Sbms ap = (const struct arc_linux_header *)p; 277127668Sbms arc_type = ap->arc_type; 278127668Sbms 279127668Sbms switch (arc_type) { 280127668Sbms default: 281127668Sbms archdrlen = ARC_LINUX_HDRNEWLEN; 282285275Spkelsey if (caplen < ARC_LINUX_HDRNEWLEN || length < ARC_LINUX_HDRNEWLEN) { 283276788Sdelphij ND_PRINT((ndo, "[|arcnet]")); 284127668Sbms return (caplen); 285127668Sbms } 286127668Sbms break; 287127668Sbms case ARCTYPE_IP_OLD: 288127668Sbms case ARCTYPE_ARP_OLD: 289127668Sbms case ARCTYPE_DIAGNOSE: 290127668Sbms archdrlen = ARC_LINUX_HDRLEN; 291127668Sbms break; 292127668Sbms } 293127668Sbms 294276788Sdelphij if (ndo->ndo_eflag) 295276788Sdelphij arcnet_print(ndo, p, length, 0, 0, 0); 296127668Sbms 297127668Sbms /* 298127668Sbms * Go past the ARCNET header. 299127668Sbms */ 300127668Sbms length -= archdrlen; 301127668Sbms caplen -= archdrlen; 302127668Sbms p += archdrlen; 303127668Sbms 304276788Sdelphij if (!arcnet_encap_print(ndo, arc_type, p, length, caplen)) 305276788Sdelphij ND_DEFAULTPRINT(p, caplen); 30698524Sfenner 307127668Sbms return (archdrlen); 30898524Sfenner} 30998524Sfenner 31098524Sfenner/* 31198524Sfenner * Prints the packet encapsulated in an ARCnet data field, 31298524Sfenner * given the ARCnet system code. 31398524Sfenner * 31498524Sfenner * Returns non-zero if it can do so, zero if the system code is unknown. 31598524Sfenner */ 31698524Sfenner 31798524Sfenner 318127668Sbmsstatic int 319276788Sdelphijarcnet_encap_print(netdissect_options *ndo, u_char arctype, const u_char *p, 32098524Sfenner u_int length, u_int caplen) 32198524Sfenner{ 32298524Sfenner switch (arctype) { 32398524Sfenner 32498524Sfenner case ARCTYPE_IP_OLD: 32598524Sfenner case ARCTYPE_IP: 326276788Sdelphij ip_print(ndo, p, length); 32798524Sfenner return (1); 32898524Sfenner 32998524Sfenner case ARCTYPE_INET6: 330276788Sdelphij ip6_print(ndo, p, length); 33198524Sfenner return (1); 33298524Sfenner 33398524Sfenner case ARCTYPE_ARP_OLD: 33498524Sfenner case ARCTYPE_ARP: 33598524Sfenner case ARCTYPE_REVARP: 336276788Sdelphij arp_print(ndo, p, length, caplen); 33798524Sfenner return (1); 33898524Sfenner 33998524Sfenner case ARCTYPE_ATALK: /* XXX was this ever used? */ 340276788Sdelphij if (ndo->ndo_vflag) 341276788Sdelphij ND_PRINT((ndo, "et1 ")); 342276788Sdelphij atalk_print(ndo, p, length); 34398524Sfenner return (1); 34498524Sfenner 345127668Sbms case ARCTYPE_IPX: 346276788Sdelphij ipx_print(ndo, p, length); 347127668Sbms return (1); 348127668Sbms 34998524Sfenner default: 35098524Sfenner return (0); 35198524Sfenner } 35298524Sfenner} 353146773Ssam 354146773Ssam/* 355146773Ssam * Local Variables: 356146773Ssam * c-style: bsd 357146773Ssam * End: 358146773Ssam */ 359146773Ssam 360