Home | History | Annotate | Download | only in tcpdump
      1 /*
      2  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
      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  * From: NetBSD: print-arcnet.c,v 1.2 2000/04/24 13:02:28 itojun Exp
     22  */
     23 #ifndef lint
     24 static const char rcsid[] _U_ =
     25     "@(#) $Header: /tcpdump/master/tcpdump/print-arcnet.c,v 1.20 2005/04/06 21:32:38 mcr Exp $ (LBL)";
     26 #endif
     27 
     28 #ifdef HAVE_CONFIG_H
     29 #include "config.h"
     30 #endif
     31 
     32 #include <tcpdump-stdinc.h>
     33 
     34 #include <stdio.h>
     35 #include <pcap.h>
     36 
     37 #include "interface.h"
     38 #include "arcnet.h"
     39 
     40 static int arcnet_encap_print(u_char arctype, const u_char *p,
     41     u_int length, u_int caplen);
     42 
     43 struct tok arctypemap[] = {
     44 	{ ARCTYPE_IP_OLD,	"oldip" },
     45 	{ ARCTYPE_ARP_OLD,	"oldarp" },
     46 	{ ARCTYPE_IP,		"ip" },
     47 	{ ARCTYPE_ARP,		"arp" },
     48 	{ ARCTYPE_REVARP,	"rarp" },
     49 	{ ARCTYPE_ATALK,	"atalk" },
     50 	{ ARCTYPE_BANIAN,	"banyan" },
     51 	{ ARCTYPE_IPX,		"ipx" },
     52 	{ ARCTYPE_INET6,	"ipv6" },
     53 	{ ARCTYPE_DIAGNOSE,	"diag" },
     54 	{ 0, 0 }
     55 };
     56 
     57 static inline void
     58 arcnet_print(const u_char *bp, u_int length, int phds, int flag, u_int seqid)
     59 {
     60 	const struct arc_header *ap;
     61 	const char *arctypename;
     62 
     63 
     64 	ap = (const struct arc_header *)bp;
     65 
     66 
     67 	if (qflag) {
     68 		(void)printf("%02x %02x %d: ",
     69 			     ap->arc_shost,
     70 			     ap->arc_dhost,
     71 			     length);
     72 		return;
     73 	}
     74 
     75 	arctypename = tok2str(arctypemap, "%02x", ap->arc_type);
     76 
     77 	if (!phds) {
     78 		(void)printf("%02x %02x %s %d: ",
     79 			     ap->arc_shost, ap->arc_dhost, arctypename,
     80 			     length);
     81 			     return;
     82 	}
     83 
     84 	if (flag == 0) {
     85 		(void)printf("%02x %02x %s seqid %04x %d: ",
     86 			ap->arc_shost, ap->arc_dhost, arctypename, seqid,
     87 			length);
     88 			return;
     89 	}
     90 
     91 	if (flag & 1)
     92 		(void)printf("%02x %02x %s seqid %04x "
     93 			"(first of %d fragments) %d: ",
     94 			ap->arc_shost, ap->arc_dhost, arctypename, seqid,
     95 			(flag + 3) / 2, length);
     96 	else
     97 		(void)printf("%02x %02x %s seqid %04x "
     98 			"(fragment %d) %d: ",
     99 			ap->arc_shost, ap->arc_dhost, arctypename, seqid,
    100 			flag/2 + 1, length);
    101 }
    102 
    103 /*
    104  * This is the top level routine of the printer.  'p' points
    105  * to the ARCNET header of the packet, 'h->ts' is the timestamp,
    106  * 'h->len' is the length of the packet off the wire, and 'h->caplen'
    107  * is the number of bytes actually captured.
    108  */
    109 u_int
    110 arcnet_if_print(const struct pcap_pkthdr *h, const u_char *p)
    111 {
    112 	u_int caplen = h->caplen;
    113 	u_int length = h->len;
    114 	const struct arc_header *ap;
    115 
    116 	int phds, flag = 0, archdrlen = 0;
    117 	u_int seqid = 0;
    118 	u_char arc_type;
    119 
    120 	if (caplen < ARC_HDRLEN) {
    121 		printf("[|arcnet]");
    122 		return (caplen);
    123 	}
    124 
    125 	ap = (const struct arc_header *)p;
    126 	arc_type = ap->arc_type;
    127 
    128 	switch (arc_type) {
    129 	default:
    130 		phds = 1;
    131 		break;
    132 	case ARCTYPE_IP_OLD:
    133 	case ARCTYPE_ARP_OLD:
    134 	case ARCTYPE_DIAGNOSE:
    135 		phds = 0;
    136 		archdrlen = ARC_HDRLEN;
    137 		break;
    138 	}
    139 
    140 	if (phds) {
    141 		if (caplen < ARC_HDRNEWLEN) {
    142 			arcnet_print(p, length, 0, 0, 0);
    143 			printf("[|phds]");
    144 			return (caplen);
    145 		}
    146 
    147 		if (ap->arc_flag == 0xff) {
    148 			if (caplen < ARC_HDRNEWLEN_EXC) {
    149 				arcnet_print(p, length, 0, 0, 0);
    150 				printf("[|phds extended]");
    151 				return (caplen);
    152 			}
    153 			flag = ap->arc_flag2;
    154 			seqid = ntohs(ap->arc_seqid2);
    155 			archdrlen = ARC_HDRNEWLEN_EXC;
    156 		} else {
    157 			flag = ap->arc_flag;
    158 			seqid = ntohs(ap->arc_seqid);
    159 			archdrlen = ARC_HDRNEWLEN;
    160 		}
    161 	}
    162 
    163 
    164 	if (eflag)
    165 		arcnet_print(p, length, phds, flag, seqid);
    166 
    167 	/*
    168 	 * Go past the ARCNET header.
    169 	 */
    170 	length -= archdrlen;
    171 	caplen -= archdrlen;
    172 	p += archdrlen;
    173 
    174 	if (phds && flag && (flag & 1) == 0) {
    175 		/*
    176 		 * This is a middle fragment.
    177 		 */
    178 		return (archdrlen);
    179 	}
    180 
    181 	if (!arcnet_encap_print(arc_type, p, length, caplen))
    182 		default_print(p, caplen);
    183 
    184 	return (archdrlen);
    185 }
    186 
    187 /*
    188  * This is the top level routine of the printer.  'p' points
    189  * to the ARCNET header of the packet, 'h->ts' is the timestamp,
    190  * 'h->len' is the length of the packet off the wire, and 'h->caplen'
    191  * is the number of bytes actually captured.  It is quite similar
    192  * to the non-Linux style printer except that Linux doesn't ever
    193  * supply packets that look like exception frames, it always supplies
    194  * reassembled packets rather than raw frames, and headers have an
    195  * extra "offset" field between the src/dest and packet type.
    196  */
    197 u_int
    198 arcnet_linux_if_print(const struct pcap_pkthdr *h, const u_char *p)
    199 {
    200 	u_int caplen = h->caplen;
    201 	u_int length = h->len;
    202 	const struct arc_linux_header *ap;
    203 
    204 	int archdrlen = 0;
    205 	u_char arc_type;
    206 
    207 	if (caplen < ARC_LINUX_HDRLEN) {
    208 		printf("[|arcnet]");
    209 		return (caplen);
    210 	}
    211 
    212 	ap = (const struct arc_linux_header *)p;
    213 	arc_type = ap->arc_type;
    214 
    215 	switch (arc_type) {
    216 	default:
    217 		archdrlen = ARC_LINUX_HDRNEWLEN;
    218 		if (caplen < ARC_LINUX_HDRNEWLEN) {
    219 			printf("[|arcnet]");
    220 			return (caplen);
    221 		}
    222 		break;
    223 	case ARCTYPE_IP_OLD:
    224 	case ARCTYPE_ARP_OLD:
    225 	case ARCTYPE_DIAGNOSE:
    226 		archdrlen = ARC_LINUX_HDRLEN;
    227 		break;
    228 	}
    229 
    230 	if (eflag)
    231 		arcnet_print(p, length, 0, 0, 0);
    232 
    233 	/*
    234 	 * Go past the ARCNET header.
    235 	 */
    236 	length -= archdrlen;
    237 	caplen -= archdrlen;
    238 	p += archdrlen;
    239 
    240 	if (!arcnet_encap_print(arc_type, p, length, caplen))
    241 		default_print(p, caplen);
    242 
    243 	return (archdrlen);
    244 }
    245 
    246 /*
    247  * Prints the packet encapsulated in an ARCnet data field,
    248  * given the ARCnet system code.
    249  *
    250  * Returns non-zero if it can do so, zero if the system code is unknown.
    251  */
    252 
    253 
    254 static int
    255 arcnet_encap_print(u_char arctype, const u_char *p,
    256     u_int length, u_int caplen)
    257 {
    258 	switch (arctype) {
    259 
    260 	case ARCTYPE_IP_OLD:
    261 	case ARCTYPE_IP:
    262 	        ip_print(gndo, p, length);
    263 		return (1);
    264 
    265 #ifdef INET6
    266 	case ARCTYPE_INET6:
    267 		ip6_print(p, length);
    268 		return (1);
    269 #endif /*INET6*/
    270 
    271 	case ARCTYPE_ARP_OLD:
    272 	case ARCTYPE_ARP:
    273 	case ARCTYPE_REVARP:
    274 	  arp_print(gndo, p, length, caplen);
    275 		return (1);
    276 
    277 	case ARCTYPE_ATALK:	/* XXX was this ever used? */
    278 		if (vflag)
    279 			fputs("et1 ", stdout);
    280 		atalk_print(p, length);
    281 		return (1);
    282 
    283 	case ARCTYPE_IPX:
    284 		ipx_print(p, length);
    285 		return (1);
    286 
    287 	default:
    288 		return (0);
    289 	}
    290 }
    291 
    292 /*
    293  * Local Variables:
    294  * c-style: bsd
    295  * End:
    296  */
    297 
    298