print-sll.c revision 111726
1183873Sraj/*
2183873Sraj * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
3183873Sraj *	The Regents of the University of California.  All rights reserved.
4183873Sraj *
5183873Sraj * Redistribution and use in source and binary forms, with or without
6183873Sraj * modification, are permitted provided that: (1) source code distributions
7183873Sraj * retain the above copyright notice and this paragraph in its entirety, (2)
8183873Sraj * distributions including binary code include the above copyright notice and
9183873Sraj * this paragraph in its entirety in the documentation or other materials
10191954Skuriyama * provided with the distribution, and (3) all advertising materials mentioning
11185478Ssam * features or use of this software display the following acknowledgement:
12183873Sraj * ``This product includes software developed by the University of California,
13266328Sian * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14183873Sraj * the University nor the names of its contributors may be used to endorse
15183873Sraj * or promote products derived from this software without specific prior
16266328Sian * written permission.
17266328Sian * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18266328Sian * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19266328Sian * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20266328Sian */
21266331Sian#ifndef lint
22266328Sianstatic const char rcsid[] =
23266328Sian    "@(#) $Header: /tcpdump/master/tcpdump/print-sll.c,v 1.6.4.1 2002/06/01 23:51:16 guy Exp $ (LBL)";
24266328Sian#endif
25266328Sian
26266328Sian#ifdef HAVE_CONFIG_H
27191954Skuriyama#include "config.h"
28191954Skuriyama#endif
29191954Skuriyama
30191954Skuriyama#include <sys/param.h>
31183873Sraj#include <sys/time.h>
32191954Skuriyama#include <sys/socket.h>
33183873Sraj
34266328Sian#include <netinet/in.h>
35266328Sian
36266328Sian#include <stdio.h>
37266328Sian#include <string.h>
38183873Sraj#include <pcap.h>
39191954Skuriyama
40183873Sraj#include "interface.h"
41183873Sraj#include "addrtoname.h"
42183873Sraj#include "ethertype.h"
43183873Sraj
44191954Skuriyama#include "ether.h"
45191954Skuriyama#include "sll.h"
46266328Sian
47271339Sianstatic inline void
48266328Siansll_print(register const struct sll_header *sllp, u_int length)
49266328Sian{
50191954Skuriyama	u_short halen;
51271428Sian
52271428Sian	switch (ntohs(sllp->sll_pkttype)) {
53191954Skuriyama
54183873Sraj	case LINUX_SLL_HOST:
55185090Sraj		(void)printf("< ");
56185090Sraj		break;
57183873Sraj
58183873Sraj	case LINUX_SLL_BROADCAST:
59183873Sraj		(void)printf("B ");
60183873Sraj		break;
61183873Sraj
62183873Sraj	case LINUX_SLL_MULTICAST:
63183873Sraj		(void)printf("M ");
64183873Sraj		break;
65183873Sraj
66183873Sraj	case LINUX_SLL_OTHERHOST:
67183873Sraj		(void)printf("P ");
68183873Sraj		break;
69183873Sraj
70183873Sraj	case LINUX_SLL_OUTGOING:
71183873Sraj		(void)printf("> ");
72227730Sraj		break;
73227730Sraj
74227730Sraj	default:
75227730Sraj		(void)printf("? ");
76183873Sraj		break;
77266328Sian	}
78183873Sraj
79183873Sraj	/*
80183873Sraj	 * XXX - check the link-layer address type value?
81183873Sraj	 * For now, we just assume 6 means Ethernet.
82183873Sraj	 * XXX - print others as strings of hex?
83183873Sraj	 */
84183873Sraj	halen = ntohs(sllp->sll_halen);
85183873Sraj	if (halen == 6)
86183873Sraj		(void)printf("%s ", etheraddr_string(sllp->sll_addr));
87183873Sraj
88194845Sraj	if (!qflag)
89194845Sraj		(void)printf("%s ", etherproto_string(sllp->sll_protocol));
90220982Smav	(void)printf("%d: ", length);
91209131Sraj}
92235609Sgber
93235609Sgber/*
94235609Sgber * This is the top level routine of the printer.  'p' is the points
95209131Sraj * to the ether header of the packet, 'h->tv' is the timestamp,
96209131Sraj * 'h->length' is the length of the packet off the wire, and 'h->caplen'
97235609Sgber * is the number of bytes actually captured.
98209131Sraj */
99void
100sll_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
101{
102	u_int caplen = h->caplen;
103	u_int length = h->len;
104	register const struct sll_header *sllp;
105	u_short pkttype;
106	struct ether_header ehdr;
107	u_short ether_type;
108	u_short extracted_ethertype;
109
110	++infodelay;
111	ts_print(&h->ts);
112
113	if (caplen < SLL_HDR_LEN) {
114		/*
115		 * XXX - this "can't happen" because "pcap-linux.c" always
116		 * adds this many bytes of header to every packet in a
117		 * cooked socket capture.
118		 */
119		printf("[|sll]");
120		goto out;
121	}
122
123	sllp = (const struct sll_header *)p;
124
125	/*
126	 * Fake up an Ethernet header for the benefit of printers that
127	 * insist on "packetp" pointing to an Ethernet header.
128	 */
129	pkttype = ntohs(sllp->sll_pkttype);
130
131	/* The source address is in the packet header */
132	memcpy(ehdr.ether_shost, sllp->sll_addr, ETHER_ADDR_LEN);
133
134	if (pkttype != LINUX_SLL_OUTGOING) {
135		/*
136		 * We received this packet.
137		 *
138		 * We don't know the destination address, so
139		 * we fake it - all 0's except that the
140		 * bottommost bit of the bottommost octet
141		 * is set for a unicast packet, all 0's except
142		 * that the bottommost bit of the uppermost
143		 * octet is set for a multicast packet, all
144		 * 1's for a broadcast packet.
145		 */
146		if (pkttype == LINUX_SLL_BROADCAST)
147			memset(ehdr.ether_dhost, 0xFF, ETHER_ADDR_LEN);
148		else {
149			memset(ehdr.ether_dhost, 0, ETHER_ADDR_LEN);
150			if (pkttype == LINUX_SLL_MULTICAST)
151				ehdr.ether_dhost[0] = 1;
152			else
153				ehdr.ether_dhost[ETHER_ADDR_LEN-1] = 1;
154		}
155	} else {
156		/*
157		 * We sent this packet; we don't know whether it's
158		 * broadcast, multicast, or unicast, so just make
159		 * the destination address all 0's.
160		 */
161		memset(ehdr.ether_dhost, 0, ETHER_ADDR_LEN);
162	}
163
164	if (eflag)
165		sll_print(sllp, length);
166
167	/*
168	 * Some printers want to get back at the ethernet addresses,
169	 * and/or check that they're not walking off the end of the packet.
170	 * Rather than pass them all the way down, we set these globals.
171	 */
172	snapend = p + caplen;
173	/*
174	 * Actually, the only printers that use packetp are print-arp.c
175	 * and print-bootp.c, and they assume that packetp points to an
176	 * Ethernet header.  The right thing to do is to fix them to know
177	 * which link type is in use when they excavate. XXX
178	 */
179	packetp = (u_char *)&ehdr;
180
181	length -= SLL_HDR_LEN;
182	caplen -= SLL_HDR_LEN;
183	p += SLL_HDR_LEN;
184
185	ether_type = ntohs(sllp->sll_protocol);
186
187	/*
188	 * Is it (gag) an 802.3 encapsulation, or some non-Ethernet
189	 * packet type?
190	 */
191	extracted_ethertype = 0;
192	if (ether_type <= ETHERMTU) {
193		/*
194		 * Yes - what type is it?
195		 */
196		switch (ether_type) {
197
198		case LINUX_SLL_P_802_3:
199			/*
200			 * Ethernet_802.3 IPX frame.
201			 */
202			ipx_print(p, length);
203			break;
204
205		case LINUX_SLL_P_802_2:
206			/*
207			 * 802.2.
208			 * Try to print the LLC-layer header & higher layers.
209			 */
210			if (llc_print(p, length, caplen, ESRC(&ehdr),
211			    EDST(&ehdr), &extracted_ethertype) == 0)
212				goto unknown;	/* unknown LLC type */
213			break;
214
215		default:
216		unknown:
217			/* ether_type not known, print raw packet */
218			if (!eflag)
219				sll_print(sllp, length + SLL_HDR_LEN);
220			if (extracted_ethertype) {
221				printf("(LLC %s) ",
222			       etherproto_string(htons(extracted_ethertype)));
223			}
224			if (!xflag && !qflag)
225				default_print(p, caplen);
226			break;
227		}
228	} else if (ether_encap_print(ether_type, p, length, caplen,
229	    &extracted_ethertype) == 0) {
230		/* ether_type not known, print raw packet */
231		if (!eflag)
232			sll_print(sllp, length + SLL_HDR_LEN);
233		if (!xflag && !qflag)
234			default_print(p, caplen);
235	}
236	if (xflag)
237		default_print(p, caplen);
238 out:
239	putchar('\n');
240	--infodelay;
241	if (infoprint)
242		info(0);
243}
244