print-arcnet.c revision 146773
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#ifndef lint
24127668Sbmsstatic const char rcsid[] _U_ =
25146773Ssam    "@(#) $Header: /tcpdump/master/tcpdump/print-arcnet.c,v 1.20 2005/04/06 21:32:38 mcr Exp $ (LBL)";
2698524Sfenner#endif
2798524Sfenner
2898524Sfenner#ifdef HAVE_CONFIG_H
2998524Sfenner#include "config.h"
3098524Sfenner#endif
3198524Sfenner
32127668Sbms#include <tcpdump-stdinc.h>
3398524Sfenner
3498524Sfenner#include <stdio.h>
3598524Sfenner#include <pcap.h>
3698524Sfenner
3798524Sfenner#include "interface.h"
3898524Sfenner#include "arcnet.h"
3998524Sfenner
40127668Sbmsstatic int arcnet_encap_print(u_char arctype, const u_char *p,
4198524Sfenner    u_int length, u_int caplen);
4298524Sfenner
4398524Sfennerstruct tok arctypemap[] = {
4498524Sfenner	{ ARCTYPE_IP_OLD,	"oldip" },
4598524Sfenner	{ ARCTYPE_ARP_OLD,	"oldarp" },
4698524Sfenner	{ ARCTYPE_IP,		"ip" },
4798524Sfenner	{ ARCTYPE_ARP,		"arp" },
4898524Sfenner	{ ARCTYPE_REVARP,	"rarp" },
4998524Sfenner	{ ARCTYPE_ATALK,	"atalk" },
5098524Sfenner	{ ARCTYPE_BANIAN,	"banyan" },
5198524Sfenner	{ ARCTYPE_IPX,		"ipx" },
5298524Sfenner	{ ARCTYPE_INET6,	"ipv6" },
5398524Sfenner	{ ARCTYPE_DIAGNOSE,	"diag" },
5498524Sfenner	{ 0, 0 }
5598524Sfenner};
5698524Sfenner
5798524Sfennerstatic inline void
5898524Sfennerarcnet_print(const u_char *bp, u_int length, int phds, int flag, u_int seqid)
5998524Sfenner{
6098524Sfenner	const struct arc_header *ap;
6198524Sfenner	const char *arctypename;
6298524Sfenner
6398524Sfenner
6498524Sfenner	ap = (const struct arc_header *)bp;
6598524Sfenner
6698524Sfenner
6798524Sfenner	if (qflag) {
6898524Sfenner		(void)printf("%02x %02x %d: ",
6998524Sfenner			     ap->arc_shost,
7098524Sfenner			     ap->arc_dhost,
7198524Sfenner			     length);
7298524Sfenner		return;
7398524Sfenner	}
7498524Sfenner
7598524Sfenner	arctypename = tok2str(arctypemap, "%02x", ap->arc_type);
7698524Sfenner
7798524Sfenner	if (!phds) {
7898524Sfenner		(void)printf("%02x %02x %s %d: ",
7998524Sfenner			     ap->arc_shost, ap->arc_dhost, arctypename,
8098524Sfenner			     length);
8198524Sfenner			     return;
8298524Sfenner	}
8398524Sfenner
8498524Sfenner	if (flag == 0) {
8598524Sfenner		(void)printf("%02x %02x %s seqid %04x %d: ",
8698524Sfenner			ap->arc_shost, ap->arc_dhost, arctypename, seqid,
8798524Sfenner			length);
8898524Sfenner			return;
8998524Sfenner	}
9098524Sfenner
9198524Sfenner	if (flag & 1)
9298524Sfenner		(void)printf("%02x %02x %s seqid %04x "
9398524Sfenner			"(first of %d fragments) %d: ",
9498524Sfenner			ap->arc_shost, ap->arc_dhost, arctypename, seqid,
9598524Sfenner			(flag + 3) / 2, length);
9698524Sfenner	else
9798524Sfenner		(void)printf("%02x %02x %s seqid %04x "
9898524Sfenner			"(fragment %d) %d: ",
9998524Sfenner			ap->arc_shost, ap->arc_dhost, arctypename, seqid,
10098524Sfenner			flag/2 + 1, length);
10198524Sfenner}
10298524Sfenner
10398524Sfenner/*
104127668Sbms * This is the top level routine of the printer.  'p' points
105127668Sbms * to the ARCNET header of the packet, 'h->ts' is the timestamp,
106146773Ssam * 'h->len' is the length of the packet off the wire, and 'h->caplen'
10798524Sfenner * is the number of bytes actually captured.
10898524Sfenner */
109127668Sbmsu_int
110127668Sbmsarcnet_if_print(const struct pcap_pkthdr *h, const u_char *p)
11198524Sfenner{
11298524Sfenner	u_int caplen = h->caplen;
11398524Sfenner	u_int length = h->len;
11498524Sfenner	const struct arc_header *ap;
11598524Sfenner
11698524Sfenner	int phds, flag = 0, archdrlen = 0;
11798524Sfenner	u_int seqid = 0;
11898524Sfenner	u_char arc_type;
11998524Sfenner
12098524Sfenner	if (caplen < ARC_HDRLEN) {
12198524Sfenner		printf("[|arcnet]");
122127668Sbms		return (caplen);
12398524Sfenner	}
12498524Sfenner
12598524Sfenner	ap = (const struct arc_header *)p;
12698524Sfenner	arc_type = ap->arc_type;
12798524Sfenner
12898524Sfenner	switch (arc_type) {
12998524Sfenner	default:
13098524Sfenner		phds = 1;
13198524Sfenner		break;
13298524Sfenner	case ARCTYPE_IP_OLD:
13398524Sfenner	case ARCTYPE_ARP_OLD:
13498524Sfenner	case ARCTYPE_DIAGNOSE:
13598524Sfenner		phds = 0;
13698524Sfenner		archdrlen = ARC_HDRLEN;
13798524Sfenner		break;
13898524Sfenner	}
13998524Sfenner
14098524Sfenner	if (phds) {
14198524Sfenner		if (caplen < ARC_HDRNEWLEN) {
14298524Sfenner			arcnet_print(p, length, 0, 0, 0);
14398524Sfenner			printf("[|phds]");
144127668Sbms			return (caplen);
14598524Sfenner		}
14698524Sfenner
14798524Sfenner		if (ap->arc_flag == 0xff) {
14898524Sfenner			if (caplen < ARC_HDRNEWLEN_EXC) {
14998524Sfenner				arcnet_print(p, length, 0, 0, 0);
15098524Sfenner				printf("[|phds extended]");
151127668Sbms				return (caplen);
15298524Sfenner			}
15398524Sfenner			flag = ap->arc_flag2;
154127668Sbms			seqid = ntohs(ap->arc_seqid2);
15598524Sfenner			archdrlen = ARC_HDRNEWLEN_EXC;
15698524Sfenner		} else {
15798524Sfenner			flag = ap->arc_flag;
158127668Sbms			seqid = ntohs(ap->arc_seqid);
15998524Sfenner			archdrlen = ARC_HDRNEWLEN;
16098524Sfenner		}
16198524Sfenner	}
16298524Sfenner
16398524Sfenner
16498524Sfenner	if (eflag)
16598524Sfenner		arcnet_print(p, length, phds, flag, seqid);
16698524Sfenner
16798524Sfenner	/*
168127668Sbms	 * Go past the ARCNET header.
16998524Sfenner	 */
17098524Sfenner	length -= archdrlen;
17198524Sfenner	caplen -= archdrlen;
17298524Sfenner	p += archdrlen;
17398524Sfenner
174127668Sbms	if (phds && flag && (flag & 1) == 0) {
175127668Sbms		/*
176127668Sbms		 * This is a middle fragment.
177127668Sbms		 */
178127668Sbms		return (archdrlen);
179127668Sbms	}
18098524Sfenner
181127668Sbms	if (!arcnet_encap_print(arc_type, p, length, caplen))
18298524Sfenner		default_print(p, caplen);
183127668Sbms
184127668Sbms	return (archdrlen);
185127668Sbms}
186127668Sbms
187127668Sbms/*
188127668Sbms * This is the top level routine of the printer.  'p' points
189127668Sbms * to the ARCNET header of the packet, 'h->ts' is the timestamp,
190146773Ssam * 'h->len' is the length of the packet off the wire, and 'h->caplen'
191127668Sbms * is the number of bytes actually captured.  It is quite similar
192127668Sbms * to the non-Linux style printer except that Linux doesn't ever
193127668Sbms * supply packets that look like exception frames, it always supplies
194127668Sbms * reassembled packets rather than raw frames, and headers have an
195127668Sbms * extra "offset" field between the src/dest and packet type.
196127668Sbms */
197127668Sbmsu_int
198127668Sbmsarcnet_linux_if_print(const struct pcap_pkthdr *h, const u_char *p)
199127668Sbms{
200127668Sbms	u_int caplen = h->caplen;
201127668Sbms	u_int length = h->len;
202127668Sbms	const struct arc_linux_header *ap;
203127668Sbms
204127668Sbms	int archdrlen = 0;
205127668Sbms	u_char arc_type;
206127668Sbms
207127668Sbms	if (caplen < ARC_LINUX_HDRLEN) {
208127668Sbms		printf("[|arcnet]");
209127668Sbms		return (caplen);
21098524Sfenner	}
21198524Sfenner
212127668Sbms	ap = (const struct arc_linux_header *)p;
213127668Sbms	arc_type = ap->arc_type;
214127668Sbms
215127668Sbms	switch (arc_type) {
216127668Sbms	default:
217127668Sbms		archdrlen = ARC_LINUX_HDRNEWLEN;
218127668Sbms		if (caplen < ARC_LINUX_HDRNEWLEN) {
219127668Sbms			printf("[|arcnet]");
220127668Sbms			return (caplen);
221127668Sbms		}
222127668Sbms		break;
223127668Sbms	case ARCTYPE_IP_OLD:
224127668Sbms	case ARCTYPE_ARP_OLD:
225127668Sbms	case ARCTYPE_DIAGNOSE:
226127668Sbms		archdrlen = ARC_LINUX_HDRLEN;
227127668Sbms		break;
228127668Sbms	}
229127668Sbms
230127668Sbms	if (eflag)
231127668Sbms		arcnet_print(p, length, 0, 0, 0);
232127668Sbms
233127668Sbms	/*
234127668Sbms	 * Go past the ARCNET header.
235127668Sbms	 */
236127668Sbms	length -= archdrlen;
237127668Sbms	caplen -= archdrlen;
238127668Sbms	p += archdrlen;
239127668Sbms
240127668Sbms	if (!arcnet_encap_print(arc_type, p, length, caplen))
24198524Sfenner		default_print(p, caplen);
24298524Sfenner
243127668Sbms	return (archdrlen);
24498524Sfenner}
24598524Sfenner
24698524Sfenner/*
24798524Sfenner * Prints the packet encapsulated in an ARCnet data field,
24898524Sfenner * given the ARCnet system code.
24998524Sfenner *
25098524Sfenner * Returns non-zero if it can do so, zero if the system code is unknown.
25198524Sfenner */
25298524Sfenner
25398524Sfenner
254127668Sbmsstatic int
25598524Sfennerarcnet_encap_print(u_char arctype, const u_char *p,
25698524Sfenner    u_int length, u_int caplen)
25798524Sfenner{
25898524Sfenner	switch (arctype) {
25998524Sfenner
26098524Sfenner	case ARCTYPE_IP_OLD:
26198524Sfenner	case ARCTYPE_IP:
262146773Ssam	        ip_print(gndo, p, length);
26398524Sfenner		return (1);
26498524Sfenner
26598524Sfenner#ifdef INET6
26698524Sfenner	case ARCTYPE_INET6:
26798524Sfenner		ip6_print(p, length);
26898524Sfenner		return (1);
26998524Sfenner#endif /*INET6*/
27098524Sfenner
27198524Sfenner	case ARCTYPE_ARP_OLD:
27298524Sfenner	case ARCTYPE_ARP:
27398524Sfenner	case ARCTYPE_REVARP:
274146773Ssam	  arp_print(gndo, p, length, caplen);
27598524Sfenner		return (1);
27698524Sfenner
27798524Sfenner	case ARCTYPE_ATALK:	/* XXX was this ever used? */
27898524Sfenner		if (vflag)
27998524Sfenner			fputs("et1 ", stdout);
28098524Sfenner		atalk_print(p, length);
28198524Sfenner		return (1);
28298524Sfenner
283127668Sbms	case ARCTYPE_IPX:
284127668Sbms		ipx_print(p, length);
285127668Sbms		return (1);
286127668Sbms
28798524Sfenner	default:
28898524Sfenner		return (0);
28998524Sfenner	}
29098524Sfenner}
291146773Ssam
292146773Ssam/*
293146773Ssam * Local Variables:
294146773Ssam * c-style: bsd
295146773Ssam * End:
296146773Ssam */
297146773Ssam
298