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); | |
98 | if (payload != null) { | |
99 | payload.order(ByteOrder.BIG_ENDIAN); | |
100 | payload.position(0); | |
101 | } | |
102 | fPayload = payload; | |
103 | ||
104 | } else { | |
105 | fPayload = null; | |
106 | } | |
107 | ||
108 | // Find child | |
109 | fChildPacket = findChildPacket(); | |
110 | ||
111 | } | |
112 | ||
113 | @Override | |
114 | public @Nullable Packet getChildPacket() { | |
115 | return fChildPacket; | |
116 | } | |
117 | ||
118 | @Override | |
119 | public @Nullable ByteBuffer getPayload() { | |
120 | return fPayload; | |
121 | } | |
122 | ||
123 | /** | |
124 | * Getter method for the source MAC Address. | |
125 | * | |
126 | * @return The source MAC address. | |
127 | */ | |
128 | public byte[] getSourceMacAddress() { | |
5db5a3a4 | 129 | return checkNotNull(Arrays.copyOf(fSourceMacAddress, fSourceMacAddress.length)); |
5255c030 VP |
130 | } |
131 | ||
132 | /** | |
133 | * Getter method for the destination MAC Address. | |
134 | * | |
135 | * @return The destination MAC address. | |
136 | */ | |
137 | public byte[] getDestinationMacAddress() { | |
5db5a3a4 | 138 | return checkNotNull(Arrays.copyOf(fDestinationMacAddress, fDestinationMacAddress.length)); |
5255c030 VP |
139 | } |
140 | ||
141 | /** | |
142 | * Getter method for Ethertype. See | |
143 | * http://standards.ieee.org/develop/regauth/ethertype/eth.txt | |
144 | * | |
145 | * @return The Ethertype. This is used to determine the child packet.. | |
146 | */ | |
147 | public int getEthertype() { | |
148 | return fType; | |
149 | } | |
150 | ||
151 | @Override | |
152 | protected @Nullable Packet findChildPacket() throws BadPacketException { | |
153 | // TODO Add more protocols. | |
154 | ByteBuffer payload = fPayload; | |
155 | if (payload == null) { | |
156 | return null; | |
157 | } | |
158 | switch (fType) { | |
159 | case EthertypeHelper.ETHERTYPE_IPV4: | |
160 | return new IPv4Packet(getPcapFile(), this, payload); | |
161 | default: | |
162 | return new UnknownPacket(getPcapFile(), this, payload); | |
163 | } | |
164 | } | |
165 | ||
166 | @Override | |
167 | public String toString() { | |
168 | String string = getProtocol().getName() + ", Source: " + ConversionHelper.toMacAddress(fSourceMacAddress) + //$NON-NLS-1$ | |
169 | ", Destination: " + ConversionHelper.toMacAddress(fDestinationMacAddress) + ", Type: " + //$NON-NLS-1$ //$NON-NLS-2$ | |
170 | EthertypeHelper.toEtherType(fType) + "\n"; //$NON-NLS-1$ | |
171 | final Packet child = fChildPacket; | |
172 | if (child != null) { | |
173 | return string + child.toString(); | |
174 | } | |
175 | return string; | |
176 | } | |
177 | ||
178 | @Override | |
179 | public boolean validate() { | |
180 | // Not yet implemented. ATM, we consider that all packets are valid. | |
181 | // This is the case for all packets. | |
182 | // TODO Implement it. | |
183 | return true; | |
184 | } | |
185 | ||
186 | @Override | |
187 | public EthernetIIEndpoint getSourceEndpoint() { | |
188 | @Nullable EthernetIIEndpoint endpoint = fSourceEndpoint; | |
189 | if (endpoint == null) { | |
190 | endpoint = new EthernetIIEndpoint(this, true); | |
191 | } | |
192 | fSourceEndpoint = endpoint; | |
193 | return fSourceEndpoint; | |
194 | } | |
195 | ||
196 | @Override | |
197 | public EthernetIIEndpoint getDestinationEndpoint() { | |
198 | @Nullable EthernetIIEndpoint endpoint = fDestinationEndpoint; | |
199 | ||
200 | if (endpoint == null) { | |
201 | endpoint = new EthernetIIEndpoint(this, false); | |
202 | } | |
203 | fDestinationEndpoint = endpoint; | |
204 | return fDestinationEndpoint; | |
205 | } | |
206 | ||
207 | @Override | |
208 | public Map<String, String> getFields() { | |
5db5a3a4 | 209 | Map<String, String> map = fFields; |
5255c030 | 210 | if (map == null) { |
5db5a3a4 AM |
211 | ImmutableMap.Builder<String, String> builder = ImmutableMap.<String, String> builder(); |
212 | builder.put("Source MAC Address", ConversionHelper.toMacAddress(fSourceMacAddress)); //$NON-NLS-1$ | |
213 | builder.put("Destination MAC Address", ConversionHelper.toMacAddress(fDestinationMacAddress)); //$NON-NLS-1$ | |
214 | builder.put("Ethertype", String.valueOf(EthertypeHelper.toEtherType(fType))); //$NON-NLS-1$ | |
215 | ||
216 | fFields = checkNotNull(builder.build()); | |
217 | return fFields; | |
5255c030 VP |
218 | } |
219 | return map; | |
220 | } | |
221 | ||
222 | @Override | |
223 | public String getLocalSummaryString() { | |
224 | return "Src: " + ConversionHelper.toMacAddress(fSourceMacAddress) + " , Dst: " + ConversionHelper.toMacAddress(fDestinationMacAddress); //$NON-NLS-1$ //$NON-NLS-2$ | |
225 | } | |
226 | ||
227 | @Override | |
228 | protected String getSignificationString() { | |
229 | return "Source MAC: " + ConversionHelper.toMacAddress(fSourceMacAddress) + " , Destination MAC: " + ConversionHelper.toMacAddress(fDestinationMacAddress); //$NON-NLS-1$ //$NON-NLS-2$ | |
230 | } | |
231 | ||
232 | @Override | |
233 | public int hashCode() { | |
234 | final int prime = 31; | |
235 | int result = 1; | |
236 | final Packet child = fChildPacket; | |
237 | if (child != null) { | |
238 | result = prime * result + child.hashCode(); | |
239 | } else { | |
240 | result = prime * result; | |
241 | } | |
242 | result = prime * result + Arrays.hashCode(fDestinationMacAddress); | |
243 | final ByteBuffer payload = fPayload; | |
244 | if (payload != null) { | |
245 | result = prime * result + payload.hashCode(); | |
246 | } else { | |
247 | result = prime * result; | |
248 | } | |
249 | result = prime * result + Arrays.hashCode(fSourceMacAddress); | |
250 | result = prime * result + fType; | |
251 | return result; | |
252 | } | |
253 | ||
254 | @Override | |
255 | public boolean equals(@Nullable Object obj) { | |
256 | if (this == obj) { | |
257 | return true; | |
258 | } | |
259 | if (obj == null) { | |
260 | return false; | |
261 | } | |
262 | if (getClass() != obj.getClass()) { | |
263 | return false; | |
264 | } | |
265 | EthernetIIPacket other = (EthernetIIPacket) obj; | |
c10923a9 MK |
266 | if(!NonNullUtils.equalsNullable(fChildPacket, other.fChildPacket)) { |
267 | return false; | |
5255c030 VP |
268 | } |
269 | if (!Arrays.equals(fDestinationMacAddress, other.fDestinationMacAddress)) { | |
270 | return false; | |
271 | } | |
c10923a9 MK |
272 | if(!NonNullUtils.equalsNullable(fPayload, other.fPayload)) { |
273 | return false; | |
5255c030 | 274 | } |
c10923a9 | 275 | |
5255c030 VP |
276 | if (!Arrays.equals(fSourceMacAddress, other.fSourceMacAddress)) { |
277 | return false; | |
278 | } | |
279 | if (fType != other.fType) { | |
280 | return false; | |
281 | } | |
282 | return true; | |
283 | } | |
284 | ||
285 | } |