Add tvbuff class.
[obnox/wireshark/wip.git] / packet-eth.c
1 /* packet-eth.c
2  * Routines for ethernet packet disassembly
3  *
4  * $Id: packet-eth.c,v 1.33 2000/05/11 08:15:08 gram Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@zing.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * 
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  * 
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  * 
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #ifdef HAVE_SYS_TYPES_H
31 # include <sys/types.h>
32 #endif
33
34 #include <glib.h>
35 #include "packet.h"
36 #include "etypes.h"
37 #include "resolv.h"
38 #include "packet-ipx.h"
39 #include "packet-isl.h"
40 #include "packet-llc.h"
41
42 extern const value_string etype_vals[];
43
44 /* protocols and header fields */
45 static int proto_eth = -1;
46 static int hf_eth_dst = -1;
47 static int hf_eth_src = -1;
48 static int hf_eth_len = -1;
49 static int hf_eth_type = -1;
50 static int hf_eth_addr = -1;
51
52 static gint ett_ieee8023 = -1;
53 static gint ett_ether2 = -1;
54
55 #define ETH_HEADER_SIZE 14
56
57 /* These are the Netware-ish names for the different Ethernet frame types.
58         EthernetII: The ethernet with a Type field instead of a length field
59         Ethernet802.2: An 802.3 header followed by an 802.3 header
60         Ethernet802.3: A raw 802.3 packet. IPX/SPX can be the only payload.
61                         There's not 802.2 hdr in this.
62         EthernetSNAP: Basically 802.2, just with 802.2SNAP. For our purposes,
63                 there's no difference between 802.2 and 802.2SNAP, since we just
64                 pass it down to dissect_llc(). -- Gilbert
65 */
66 #define ETHERNET_II     0
67 #define ETHERNET_802_2  1
68 #define ETHERNET_802_3  2
69 #define ETHERNET_SNAP   3
70
71 void
72 capture_eth(const u_char *pd, int offset, packet_counts *ld)
73 {
74   guint16    etype, length;
75   int     ethhdr_type;  /* the type of ethernet frame */
76
77   if (!BYTES_ARE_IN_FRAME(offset, ETH_HEADER_SIZE)) {
78     ld->other++;
79     return;
80   }
81   
82   etype = pntohs(&pd[offset+12]);
83
84         /* either ethernet802.3 or ethernet802.2 */
85   if (etype <= IEEE_802_3_MAX_LEN) {
86     length = etype;
87
88     /* Is there an 802.2 layer? I can tell by looking at the first 2
89        bytes after the 802.3 header. If they are 0xffff, then what
90        follows the 802.3 header is an IPX payload, meaning no 802.2.
91        (IPX/SPX is they only thing that can be contained inside a
92        straight 802.3 packet). A non-0xffff value means that there's an
93        802.2 layer inside the 802.3 layer */
94     if (pd[offset+14] == 0xff && pd[offset+15] == 0xff) {
95       ethhdr_type = ETHERNET_802_3;
96     }
97     else {
98       ethhdr_type = ETHERNET_802_2;
99     }
100
101     /* Oh, yuck.  Cisco ISL frames require special interpretation of the
102        destination address field; fortunately, they can be recognized by
103        checking the first 5 octets of the destination address, which are
104        01-00-0C-00-00 for ISL frames. */
105     if (pd[offset] == 0x01 && pd[offset+1] == 0x00 && pd[offset+2] == 0x0C
106         && pd[offset+3] == 0x00 && pd[offset+4] == 0x00) {
107       capture_isl(pd, offset, ld);
108       return;
109     }
110
111     /* Convert the LLC length from the 802.3 header to a total
112        frame length, by adding in the size of any data that preceded
113        the Ethernet header, and adding in the Ethernet header size,
114        and set the payload and captured-payload lengths to the minima
115        of the total length and the frame lengths. */
116     length += offset + ETH_HEADER_SIZE;
117     if (pi.len > length)
118       pi.len = length;
119     if (pi.captured_len > length)
120       pi.captured_len = length;
121   } else {
122     ethhdr_type = ETHERNET_II;
123   }
124   offset += ETH_HEADER_SIZE;
125
126   switch (ethhdr_type) {
127     case ETHERNET_802_3:
128       capture_ipx(pd, offset, ld);
129       break;
130     case ETHERNET_802_2:
131       capture_llc(pd, offset, ld);
132       break;
133     case ETHERNET_II:
134       capture_ethertype(etype, offset, pd, ld);
135       break;
136   }
137 }
138
139 void
140 dissect_eth(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
141 {
142   int        orig_captured_len;
143   guint16    etype, length;
144   proto_tree *fh_tree = NULL;
145   proto_item *ti;
146   int        ethhdr_type;       /* the type of ethernet frame */
147
148   if (!BYTES_ARE_IN_FRAME(offset, ETH_HEADER_SIZE)) {
149     dissect_data(pd, offset, fd, tree);
150     return;
151   }
152
153   orig_captured_len = pi.captured_len;
154
155   SET_ADDRESS(&pi.dl_src, AT_ETHER, 6, &pd[offset+6]);
156   SET_ADDRESS(&pi.src, AT_ETHER, 6, &pd[offset+6]);
157   SET_ADDRESS(&pi.dl_dst, AT_ETHER, 6, &pd[offset+0]);
158   SET_ADDRESS(&pi.dst, AT_ETHER, 6, &pd[offset+0]);
159
160   if (check_col(fd, COL_PROTOCOL))
161     col_add_str(fd, COL_PROTOCOL, "Ethernet");
162
163   etype = pntohs(&pd[offset+12]);
164
165         /* either ethernet802.3 or ethernet802.2 */
166   if (etype <= IEEE_802_3_MAX_LEN) {
167     length = etype;
168
169     /* Is there an 802.2 layer? I can tell by looking at the first 2
170        bytes after the 802.3 header. If they are 0xffff, then what
171        follows the 802.3 header is an IPX payload, meaning no 802.2.
172        (IPX/SPX is they only thing that can be contained inside a
173        straight 802.3 packet). A non-0xffff value means that there's an
174        802.2 layer inside the 802.3 layer */
175     if (pd[offset+14] == 0xff && pd[offset+15] == 0xff) {
176       ethhdr_type = ETHERNET_802_3;
177     }
178     else {
179       ethhdr_type = ETHERNET_802_2;
180     }
181
182     /* Oh, yuck.  Cisco ISL frames require special interpretation of the
183        destination address field; fortunately, they can be recognized by
184        checking the first 5 octets of the destination address, which are
185        01-00-0C-00-00 for ISL frames. */
186     if (pd[offset] == 0x01 && pd[offset+1] == 0x00 && pd[offset+2] == 0x0C
187         && pd[offset+3] == 0x00 && pd[offset+4] == 0x00) {
188       dissect_isl(pd, offset, fd, tree);
189       return;
190     }
191
192     if (check_col(fd, COL_INFO)) {
193       col_add_fstr(fd, COL_INFO, "IEEE 802.3 %s",
194                 (ethhdr_type == ETHERNET_802_3 ? "Raw " : ""));
195     }
196     if (tree) {
197
198         ti = proto_tree_add_protocol_format(tree, proto_eth, NullTVB, offset, ETH_HEADER_SIZE,
199                 "IEEE 802.3 %s", (ethhdr_type == ETHERNET_802_3 ? "Raw " : ""));
200
201         fh_tree = proto_item_add_subtree(ti, ett_ieee8023);
202
203         proto_tree_add_item(fh_tree, hf_eth_dst, NullTVB, offset+0, 6, &pd[offset+0]);
204         proto_tree_add_item(fh_tree, hf_eth_src, NullTVB, offset+6, 6, &pd[offset+6]);
205
206 /* add items for eth.addr filter */
207         proto_tree_add_item_hidden(fh_tree, hf_eth_addr, NullTVB, offset + 0, 6, &pd[offset+0]);
208         proto_tree_add_item_hidden(fh_tree, hf_eth_addr, NullTVB, offset + 6, 6, &pd[offset+6]);
209
210         proto_tree_add_item(fh_tree, hf_eth_len, NullTVB, offset+12, 2, length);
211     }
212
213     /* Convert the LLC length from the 802.3 header to a total
214        frame length, by adding in the size of any data that preceded
215        the Ethernet header, and adding in the Ethernet header size,
216        and set the payload and captured-payload lengths to the minima
217        of the total length and the frame lengths. */
218     length += offset + ETH_HEADER_SIZE;
219     if (pi.len > length)
220       pi.len = length;
221     if (pi.captured_len > length)
222       pi.captured_len = length;
223   } else {
224     ethhdr_type = ETHERNET_II;
225     if (check_col(fd, COL_INFO))
226       col_add_str(fd, COL_INFO, "Ethernet II");
227     if (tree) {
228
229         ti = proto_tree_add_protocol_format(tree, proto_eth, NullTVB, offset, ETH_HEADER_SIZE,
230                 "Ethernet II");
231
232         fh_tree = proto_item_add_subtree(ti, ett_ether2);
233
234         proto_tree_add_item(fh_tree, hf_eth_dst, NullTVB, offset+0, 6, &pd[offset+0]);
235         proto_tree_add_item(fh_tree, hf_eth_src, NullTVB, offset+6, 6, &pd[offset+6]);
236 /* add items for eth.addr filter */
237         proto_tree_add_item_hidden(fh_tree, hf_eth_addr, NullTVB, offset + 0, 6, &pd[offset+0]);
238         proto_tree_add_item_hidden(fh_tree, hf_eth_addr, NullTVB, offset + 6, 6, &pd[offset+6]);
239     }
240   }
241   offset += ETH_HEADER_SIZE;
242
243   switch (ethhdr_type) {
244     case ETHERNET_802_3:
245       dissect_ipx(pd, offset, fd, tree);
246       break;
247     case ETHERNET_802_2:
248       dissect_llc(pd, offset, fd, tree);
249       break;
250     case ETHERNET_II:
251       ethertype(etype, offset, pd, fd, tree, fh_tree, hf_eth_type);
252       break;
253   }
254 }
255
256 void
257 proto_register_eth(void)
258 {
259         static hf_register_info hf[] = {
260
261                 { &hf_eth_dst,
262                 { "Destination",        "eth.dst", FT_ETHER, BASE_NONE, NULL, 0x0,
263                         "Destination Hardware Address" }},
264
265                 { &hf_eth_src,
266                 { "Source",             "eth.src", FT_ETHER, BASE_NONE, NULL, 0x0,
267                         "Source Hardware Address" }},
268
269                 { &hf_eth_len,
270                 { "Length",             "eth.len", FT_UINT16, BASE_DEC, NULL, 0x0,
271                         "" }},
272
273                 /* registered here but handled in ethertype.c */
274                 { &hf_eth_type,
275                 { "Type",               "eth.type", FT_UINT16, BASE_HEX, VALS(etype_vals), 0x0,
276                         "" }},
277                 { &hf_eth_addr,
278                 { "Source or Destination Address", "eth.addr", FT_ETHER, BASE_NONE, NULL, 0x0,
279                         "Source or Destination Hardware Address" }}
280
281         };
282         static gint *ett[] = {
283                 &ett_ieee8023,
284                 &ett_ether2,
285         };
286
287         proto_eth = proto_register_protocol ("Ethernet", "eth" );
288         proto_register_field_array(proto_eth, hf, array_length(hf));
289         proto_register_subtree_array(ett, array_length(ett));
290 }