]> The Tcpdump Group git mirrors - tcpdump/blob - print-sll.c
ad3b19cb59f454f968448c384aff0bed23f83dcc
[tcpdump] / print-sll.c
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[] =
23 "@(#) $Header: /tcpdump/master/tcpdump/print-sll.c,v 1.1 2000-12-21 10:43:22 guy Exp $ (LBL)";
24 #endif
25
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include <sys/param.h>
31 #include <sys/time.h>
32 #include <sys/socket.h>
33
34 struct mbuf;
35 struct rtentry;
36
37 #include <netinet/in.h>
38
39 #include <stdio.h>
40 #include <string.h>
41 #include <pcap.h>
42
43 #include "interface.h"
44 #include "addrtoname.h"
45 #include "ethertype.h"
46
47 #include "ether.h"
48 #include "sll.h"
49
50 const u_char *packetp;
51 const u_char *snapend;
52
53 static inline void
54 sll_print(register const u_char *bp, u_int length)
55 {
56 register const struct sll_header *sllp;
57 u_short halen;
58
59 sllp = (const struct sll_header *)bp;
60
61 switch (ntohs(sllp->sll_pkttype)) {
62
63 case LINUX_SLL_HOST:
64 (void)printf("< ");
65 break;
66
67 case LINUX_SLL_BROADCAST:
68 (void)printf("B ");
69 break;
70
71 case LINUX_SLL_MULTICAST:
72 (void)printf("M ");
73 break;
74
75 case LINUX_SLL_OTHERHOST:
76 (void)printf("P ");
77 break;
78
79 case LINUX_SLL_OUTGOING:
80 (void)printf("> ");
81 break;
82
83 default:
84 (void)printf("? ");
85 break;
86 }
87
88 /*
89 * XXX - check the link-layer address type value?
90 * For now, we just assume 6 means Ethernet.
91 * XXX - print others as strings of hex?
92 */
93 halen = ntohs(sllp->sll_halen);
94 if (halen == 6)
95 (void)printf("%s ", etheraddr_string(sllp->sll_addr));
96
97 if (!qflag)
98 (void)printf("%s ", etherproto_string(sllp->sll_protocol));
99 (void)printf("%d: ", length);
100 }
101
102 /*
103 * This is the top level routine of the printer. 'p' is the points
104 * to the ether header of the packet, 'h->tv' is the timestamp,
105 * 'h->length' is the length of the packet off the wire, and 'h->caplen'
106 * is the number of bytes actually captured.
107 */
108 void
109 sll_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
110 {
111 u_int caplen = h->caplen;
112 u_int length = h->len;
113 register const struct sll_header *sllp;
114 u_short pkttype;
115 struct ether_header ehdr;
116 u_short ether_type;
117 u_short extracted_ethertype;
118
119 ts_print(&h->ts);
120
121 if (caplen < SLL_HDR_LEN) {
122 /*
123 * XXX - this "can't happen" because "pcap-linux.c" always
124 * adds this many bytes of header to every packet in a
125 * cooked socket capture.
126 */
127 printf("[|sll]");
128 goto out;
129 }
130
131 sllp = (const struct sll_header *)p;
132
133 /*
134 * Fake up an Ethernet header for the benefit of printers that
135 * insist on "packetp" pointing to an Ethernet header.
136 */
137 pkttype = ntohs(sllp->sll_pkttype);
138
139 /* The source address is in the packet header */
140 memcpy(ehdr.ether_shost, sllp->sll_addr, ETHER_ADDR_LEN);
141
142 if (pkttype != LINUX_SLL_OUTGOING) {
143 /*
144 * We received this packet.
145 *
146 * We don't know the destination address, so
147 * we fake it - all 0's except that the
148 * bottommost bit of the bottommost octet
149 * is set for a unicast packet, all 0's except
150 * that the bottommost bit of the uppermost
151 * octet is set for a multicast packet, all
152 * 1's for a broadcast packet.
153 */
154 if (pkttype == LINUX_SLL_BROADCAST)
155 memset(ehdr.ether_dhost, 0xFF, ETHER_ADDR_LEN);
156 else {
157 memset(ehdr.ether_dhost, 0, ETHER_ADDR_LEN);
158 if (pkttype == LINUX_SLL_MULTICAST)
159 ehdr.ether_dhost[0] = 1;
160 else
161 ehdr.ether_dhost[ETHER_ADDR_LEN-1] = 1;
162 }
163 } else {
164 /*
165 * We sent this packet; we don't know whether it's
166 * broadcast, multicast, or unicast, so just make
167 * the destination address all 0's.
168 */
169 memset(ehdr.ether_dhost, 0, ETHER_ADDR_LEN);
170 }
171
172 if (eflag)
173 sll_print(p, length);
174
175 /*
176 * Some printers want to get back at the ethernet addresses,
177 * and/or check that they're not walking off the end of the packet.
178 * Rather than pass them all the way down, we set these globals.
179 */
180 packetp = p;
181 snapend = p + caplen;
182
183 length -= SLL_HDR_LEN;
184 caplen -= SLL_HDR_LEN;
185 p += SLL_HDR_LEN;
186
187 ether_type = ntohs(sllp->sll_protocol);
188
189 /*
190 * Is it (gag) an 802.3 encapsulation?
191 */
192 extracted_ethertype = 0;
193 if (ether_type <= ETHERMTU) {
194 /* Try to print the LLC-layer header & higher layers */
195 if (llc_print(p, length, caplen, ESRC(&ehdr), EDST(&ehdr),
196 &extracted_ethertype) == 0) {
197 /* ether_type not known, print raw packet */
198 if (!eflag)
199 sll_print(packetp, length);
200 if (extracted_ethertype) {
201 printf("(LLC %s) ",
202 etherproto_string(htons(extracted_ethertype)));
203 }
204 if (!xflag && !qflag)
205 default_print(p, caplen);
206 }
207 } else if (ether_encap_print(ether_type, p, length, caplen,
208 &extracted_ethertype) == 0) {
209 /* ether_type not known, print raw packet */
210 if (!eflag)
211 sll_print(p - SLL_HDR_LEN, length + SLL_HDR_LEN);
212 if (!xflag && !qflag)
213 default_print(p, caplen);
214 }
215 if (xflag)
216 default_print(p, caplen);
217 out:
218 putchar('\n');
219 }