print-sll.c revision 127668
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#ifndef lint
22static const char rcsid[] _U_ =
23    "@(#) $Header: /tcpdump/master/tcpdump/print-sll.c,v 1.12.2.2 2003/11/16 08:51:44 guy Exp $ (LBL)";
24#endif
25
26#ifdef HAVE_CONFIG_H
27#include "config.h"
28#endif
29
30#include <tcpdump-stdinc.h>
31
32#include <stdio.h>
33#include <string.h>
34#include <pcap.h>
35
36#include "interface.h"
37#include "addrtoname.h"
38#include "ethertype.h"
39
40#include "ether.h"
41#include "sll.h"
42
43static inline void
44sll_print(register const struct sll_header *sllp, u_int length)
45{
46	u_short halen;
47
48	switch (ntohs(sllp->sll_pkttype)) {
49
50	case LINUX_SLL_HOST:
51		(void)printf("< ");
52		break;
53
54	case LINUX_SLL_BROADCAST:
55		(void)printf("B ");
56		break;
57
58	case LINUX_SLL_MULTICAST:
59		(void)printf("M ");
60		break;
61
62	case LINUX_SLL_OTHERHOST:
63		(void)printf("P ");
64		break;
65
66	case LINUX_SLL_OUTGOING:
67		(void)printf("> ");
68		break;
69
70	default:
71		(void)printf("? ");
72		break;
73	}
74
75	/*
76	 * XXX - check the link-layer address type value?
77	 * For now, we just assume 6 means Ethernet.
78	 * XXX - print others as strings of hex?
79	 */
80	halen = ntohs(sllp->sll_halen);
81	if (halen == 6)
82		(void)printf("%s ", etheraddr_string(sllp->sll_addr));
83
84	if (!qflag)
85		(void)printf("%s ", etherproto_string(sllp->sll_protocol));
86	(void)printf("%d: ", length);
87}
88
89/*
90 * This is the top level routine of the printer.  'p' points to the
91 * Linux "cooked capture" header of the packet, 'h->ts' is the timestamp,
92 * 'h->length' is the length of the packet off the wire, and 'h->caplen'
93 * is the number of bytes actually captured.
94 */
95u_int
96sll_if_print(const struct pcap_pkthdr *h, const u_char *p)
97{
98	u_int caplen = h->caplen;
99	u_int length = h->len;
100	register const struct sll_header *sllp;
101	u_short ether_type;
102	u_short extracted_ethertype;
103
104	if (caplen < SLL_HDR_LEN) {
105		/*
106		 * XXX - this "can't happen" because "pcap-linux.c" always
107		 * adds this many bytes of header to every packet in a
108		 * cooked socket capture.
109		 */
110		printf("[|sll]");
111		return (caplen);
112	}
113
114	sllp = (const struct sll_header *)p;
115
116	if (eflag)
117		sll_print(sllp, length);
118
119	/*
120	 * Go past the cooked-mode header.
121	 */
122	length -= SLL_HDR_LEN;
123	caplen -= SLL_HDR_LEN;
124	p += SLL_HDR_LEN;
125
126	ether_type = ntohs(sllp->sll_protocol);
127
128	/*
129	 * Is it (gag) an 802.3 encapsulation, or some non-Ethernet
130	 * packet type?
131	 */
132	extracted_ethertype = 0;
133	if (ether_type <= ETHERMTU) {
134		/*
135		 * Yes - what type is it?
136		 */
137		switch (ether_type) {
138
139		case LINUX_SLL_P_802_3:
140			/*
141			 * Ethernet_802.3 IPX frame.
142			 */
143			ipx_print(p, length);
144			break;
145
146		case LINUX_SLL_P_802_2:
147			/*
148			 * 802.2.
149			 * Try to print the LLC-layer header & higher layers.
150			 */
151			if (llc_print(p, length, caplen, NULL, NULL,
152			    &extracted_ethertype) == 0)
153				goto unknown;	/* unknown LLC type */
154			break;
155
156		default:
157		unknown:
158			/* ether_type not known, print raw packet */
159			if (!eflag)
160				sll_print(sllp, length + SLL_HDR_LEN);
161			if (extracted_ethertype) {
162				printf("(LLC %s) ",
163			       etherproto_string(htons(extracted_ethertype)));
164			}
165			if (!xflag && !qflag)
166				default_print(p, caplen);
167			break;
168		}
169	} else if (ether_encap_print(ether_type, p, length, caplen,
170	    &extracted_ethertype) == 0) {
171		/* ether_type not known, print raw packet */
172		if (!eflag)
173			sll_print(sllp, length + SLL_HDR_LEN);
174		if (!xflag && !qflag)
175			default_print(p, caplen);
176	}
177
178	return (SLL_HDR_LEN);
179}
180