xref: /freebsd/contrib/tcpdump/print-sll.c (revision 6b3455a7665208c366849f0b2b3bc916fb97516e)
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
22 static 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 
43 static inline void
44 sll_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  */
95 u_int
96 sll_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