Commit | Line | Data |
---|---|---|
5255c030 VP |
1 | /******************************************************************************* |
2 | * Copyright (c) 2014 Ericsson | |
3 | * | |
4 | * All rights reserved. This program and the accompanying materials are | |
5 | * made available under the terms of the Eclipse Public License v1.0 which | |
6 | * accompanies this distribution, and is available at | |
7 | * http://www.eclipse.org/legal/epl-v10.html | |
8 | * | |
9 | * Contributors: | |
10 | * Vincent Perot - Initial API and implementation | |
11 | *******************************************************************************/ | |
12 | ||
71f2817f | 13 | package org.eclipse.tracecompass.internal.pcap.core.protocol.ethernet2; |
5255c030 | 14 | |
5db5a3a4 AM |
15 | import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull; |
16 | ||
5255c030 VP |
17 | import java.nio.ByteBuffer; |
18 | import java.nio.ByteOrder; | |
19 | import java.util.Arrays; | |
20 | import java.util.Map; | |
21 | ||
5255c030 | 22 | import org.eclipse.jdt.annotation.Nullable; |
c10923a9 | 23 | import org.eclipse.tracecompass.common.core.NonNullUtils; |
71f2817f AM |
24 | import org.eclipse.tracecompass.internal.pcap.core.packet.BadPacketException; |
25 | import org.eclipse.tracecompass.internal.pcap.core.packet.Packet; | |
26 | import org.eclipse.tracecompass.internal.pcap.core.protocol.PcapProtocol; | |
27 | import org.eclipse.tracecompass.internal.pcap.core.protocol.ipv4.IPv4Packet; | |
28 | import org.eclipse.tracecompass.internal.pcap.core.protocol.unknown.UnknownPacket; | |
29 | import org.eclipse.tracecompass.internal.pcap.core.trace.PcapFile; | |
30 | import org.eclipse.tracecompass.internal.pcap.core.util.ConversionHelper; | |
31 | import org.eclipse.tracecompass.internal.pcap.core.util.EthertypeHelper; | |
5255c030 VP |
32 | |
33 | import com.google.common.collect.ImmutableMap; | |
34 | ||
35 | /** | |
36 | * Class that represents an Ethernet II packet. This should be called an | |
37 | * Ethernet frame, but in order to keep the nomenclature consistent, this is | |
38 | * called a packet. | |
39 | * | |
40 | * @author Vincent Perot | |
41 | */ | |
42 | public class EthernetIIPacket extends Packet { | |
43 | ||
44 | private final @Nullable Packet fChildPacket; | |
45 | private final @Nullable ByteBuffer fPayload; | |
46 | ||
d6fca387 VP |
47 | /* We store MAC addresses as byte arrays since |
48 | * there is no standard java class to store them. */ | |
5255c030 VP |
49 | private final byte[] fSourceMacAddress; |
50 | private final byte[] fDestinationMacAddress; | |
d6fca387 | 51 | |
5255c030 VP |
52 | private final int fType; |
53 | ||
54 | private @Nullable EthernetIIEndpoint fSourceEndpoint; | |
55 | private @Nullable EthernetIIEndpoint fDestinationEndpoint; | |
56 | ||
5db5a3a4 | 57 | private @Nullable Map<String, String> fFields; |
5255c030 VP |
58 | |
59 | /** | |
60 | * Constructor of the Ethernet Packet class. | |
61 | * | |
62 | * @param file | |
63 | * The file that contains this packet. | |
64 | * @param parent | |
65 | * The parent packet of this packet (the encapsulating packet). | |
66 | * @param packet | |
67 | * The entire packet (header and payload). | |
68 | * @throws BadPacketException | |
69 | * Thrown when the packet is erroneous. | |
70 | */ | |
71 | public EthernetIIPacket(PcapFile file, @Nullable Packet parent, ByteBuffer packet) throws BadPacketException { | |
c88feda9 | 72 | super(file, parent, PcapProtocol.ETHERNET_II); |
5255c030 VP |
73 | |
74 | if (packet.array().length <= EthernetIIValues.ETHERNET_II_MIN_SIZE) { | |
75 | throw new BadPacketException("An Ethernet II packet can't be smaller than 14 bytes."); //$NON-NLS-1$ | |
76 | } | |
77 | ||
78 | // The endpoints are lazy loaded. They are defined in the get*Endpoint() | |
79 | // methods. | |
80 | fSourceEndpoint = null; | |
81 | fDestinationEndpoint = null; | |
82 | ||
83 | fFields = null; | |
84 | ||
85 | fDestinationMacAddress = new byte[EthernetIIValues.MAC_ADDRESS_SIZE]; | |
86 | fSourceMacAddress = new byte[EthernetIIValues.MAC_ADDRESS_SIZE]; | |
87 | packet.order(ByteOrder.BIG_ENDIAN); | |
88 | packet.position(0); | |
89 | packet.get(fDestinationMacAddress); | |
90 | packet.get(fSourceMacAddress); | |
91 | fType = ConversionHelper.unsignedShortToInt(packet.getShort()); | |
92 | ||
93 | // Get payload if it exists. | |
94 | if (packet.array().length - packet.position() > 0) { | |
95 | byte[] array = new byte[packet.array().length - packet.position()]; | |
96 | packet.get(array); | |
97 | ByteBuffer payload = ByteBuffer.wrap(array); | |
56b1f7d4 MAL |
98 | payload.order(ByteOrder.BIG_ENDIAN); |
99 | payload.position(0); | |
5255c030 VP |
100 | fPayload = payload; |
101 | ||
102 | } else { | |
103 | fPayload = null; | |
104 | } | |
105 | ||
106 | // Find child | |
107 | fChildPacket = findChildPacket(); | |
108 | ||
109 | } | |
110 | ||
111 | @Override | |
112 | public @Nullable Packet getChildPacket() { | |
113 | return fChildPacket; | |
114 | } | |
115 | ||
116 | @Override | |
117 | public @Nullable ByteBuffer getPayload() { | |
118 | return fPayload; | |
119 | } | |
120 | ||
121 | /** | |
122 | * Getter method for the source MAC Address. | |
123 | * | |
124 | * @return The source MAC address. | |
125 | */ | |
126 | public byte[] getSourceMacAddress() { | |
5db5a3a4 | 127 | return checkNotNull(Arrays.copyOf(fSourceMacAddress, fSourceMacAddress.length)); |
5255c030 VP |
128 | } |
129 | ||
130 | /** | |
131 | * Getter method for the destination MAC Address. | |
132 | * | |
133 | * @return The destination MAC address. | |
134 | */ | |
135 | public byte[] getDestinationMacAddress() { | |
5db5a3a4 | 136 | return checkNotNull(Arrays.copyOf(fDestinationMacAddress, fDestinationMacAddress.length)); |
5255c030 VP |
137 | } |
138 | ||
139 | /** | |
140 | * Getter method for Ethertype. See | |
141 | * http://standards.ieee.org/develop/regauth/ethertype/eth.txt | |
142 | * | |
143 | * @return The Ethertype. This is used to determine the child packet.. | |
144 | */ | |
145 | public int getEthertype() { | |
146 | return fType; | |
147 | } | |
148 | ||
149 | @Override | |
150 | protected @Nullable Packet findChildPacket() throws BadPacketException { | |
151 | // TODO Add more protocols. | |
152 | ByteBuffer payload = fPayload; | |
153 | if (payload == null) { | |
154 | return null; | |
155 | } | |
156 | switch (fType) { | |
157 | case EthertypeHelper.ETHERTYPE_IPV4: | |
158 | return new IPv4Packet(getPcapFile(), this, payload); | |
159 | default: | |
160 | return new UnknownPacket(getPcapFile(), this, payload); | |
161 | } | |
162 | } | |
163 | ||
164 | @Override | |
165 | public String toString() { | |
166 | String string = getProtocol().getName() + ", Source: " + ConversionHelper.toMacAddress(fSourceMacAddress) + //$NON-NLS-1$ | |
167 | ", Destination: " + ConversionHelper.toMacAddress(fDestinationMacAddress) + ", Type: " + //$NON-NLS-1$ //$NON-NLS-2$ | |
168 | EthertypeHelper.toEtherType(fType) + "\n"; //$NON-NLS-1$ | |
169 | final Packet child = fChildPacket; | |
170 | if (child != null) { | |
171 | return string + child.toString(); | |
172 | } | |
173 | return string; | |
174 | } | |
175 | ||
176 | @Override | |
177 | public boolean validate() { | |
178 | // Not yet implemented. ATM, we consider that all packets are valid. | |
179 | // This is the case for all packets. | |
180 | // TODO Implement it. | |
181 | return true; | |
182 | } | |
183 | ||
184 | @Override | |
185 | public EthernetIIEndpoint getSourceEndpoint() { | |
186 | @Nullable EthernetIIEndpoint endpoint = fSourceEndpoint; | |
187 | if (endpoint == null) { | |
188 | endpoint = new EthernetIIEndpoint(this, true); | |
189 | } | |
190 | fSourceEndpoint = endpoint; | |
191 | return fSourceEndpoint; | |
192 | } | |
193 | ||
194 | @Override | |
195 | public EthernetIIEndpoint getDestinationEndpoint() { | |
196 | @Nullable EthernetIIEndpoint endpoint = fDestinationEndpoint; | |
197 | ||
198 | if (endpoint == null) { | |
199 | endpoint = new EthernetIIEndpoint(this, false); | |
200 | } | |
201 | fDestinationEndpoint = endpoint; | |
202 | return fDestinationEndpoint; | |
203 | } | |
204 | ||
205 | @Override | |
206 | public Map<String, String> getFields() { | |
5db5a3a4 | 207 | Map<String, String> map = fFields; |
5255c030 | 208 | if (map == null) { |
4c4e2816 | 209 | ImmutableMap.Builder<String, String> builder = ImmutableMap.builder(); |
5db5a3a4 AM |
210 | builder.put("Source MAC Address", ConversionHelper.toMacAddress(fSourceMacAddress)); //$NON-NLS-1$ |
211 | builder.put("Destination MAC Address", ConversionHelper.toMacAddress(fDestinationMacAddress)); //$NON-NLS-1$ | |
212 | builder.put("Ethertype", String.valueOf(EthertypeHelper.toEtherType(fType))); //$NON-NLS-1$ | |
213 | ||
0e4f957e | 214 | fFields = builder.build(); |
5db5a3a4 | 215 | return fFields; |
5255c030 VP |
216 | } |
217 | return map; | |
218 | } | |
219 | ||
220 | @Override | |
221 | public String getLocalSummaryString() { | |
222 | return "Src: " + ConversionHelper.toMacAddress(fSourceMacAddress) + " , Dst: " + ConversionHelper.toMacAddress(fDestinationMacAddress); //$NON-NLS-1$ //$NON-NLS-2$ | |
223 | } | |
224 | ||
225 | @Override | |
226 | protected String getSignificationString() { | |
227 | return "Source MAC: " + ConversionHelper.toMacAddress(fSourceMacAddress) + " , Destination MAC: " + ConversionHelper.toMacAddress(fDestinationMacAddress); //$NON-NLS-1$ //$NON-NLS-2$ | |
228 | } | |
229 | ||
230 | @Override | |
231 | public int hashCode() { | |
232 | final int prime = 31; | |
233 | int result = 1; | |
234 | final Packet child = fChildPacket; | |
235 | if (child != null) { | |
236 | result = prime * result + child.hashCode(); | |
237 | } else { | |
238 | result = prime * result; | |
239 | } | |
240 | result = prime * result + Arrays.hashCode(fDestinationMacAddress); | |
241 | final ByteBuffer payload = fPayload; | |
242 | if (payload != null) { | |
243 | result = prime * result + payload.hashCode(); | |
244 | } else { | |
245 | result = prime * result; | |
246 | } | |
247 | result = prime * result + Arrays.hashCode(fSourceMacAddress); | |
248 | result = prime * result + fType; | |
249 | return result; | |
250 | } | |
251 | ||
252 | @Override | |
253 | public boolean equals(@Nullable Object obj) { | |
254 | if (this == obj) { | |
255 | return true; | |
256 | } | |
257 | if (obj == null) { | |
258 | return false; | |
259 | } | |
260 | if (getClass() != obj.getClass()) { | |
261 | return false; | |
262 | } | |
263 | EthernetIIPacket other = (EthernetIIPacket) obj; | |
c10923a9 MK |
264 | if(!NonNullUtils.equalsNullable(fChildPacket, other.fChildPacket)) { |
265 | return false; | |
5255c030 VP |
266 | } |
267 | if (!Arrays.equals(fDestinationMacAddress, other.fDestinationMacAddress)) { | |
268 | return false; | |
269 | } | |
c10923a9 MK |
270 | if(!NonNullUtils.equalsNullable(fPayload, other.fPayload)) { |
271 | return false; | |
5255c030 | 272 | } |
c10923a9 | 273 | |
5255c030 VP |
274 | if (!Arrays.equals(fSourceMacAddress, other.fSourceMacAddress)) { |
275 | return false; | |
276 | } | |
277 | if (fType != other.fType) { | |
278 | return false; | |
279 | } | |
280 | return true; | |
281 | } | |
282 | ||
283 | } |