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 | ||
93d1d135 | 13 | package org.eclipse.linuxtools.internal.pcap.core.packet; |
5255c030 VP |
14 | |
15 | import java.nio.ByteBuffer; | |
16 | import java.util.Map; | |
17 | ||
18 | import org.eclipse.jdt.annotation.NonNull; | |
19 | import org.eclipse.jdt.annotation.Nullable; | |
93d1d135 | 20 | import org.eclipse.linuxtools.internal.pcap.core.endpoint.ProtocolEndpoint; |
c88feda9 | 21 | import org.eclipse.linuxtools.internal.pcap.core.protocol.PcapProtocol; |
93d1d135 AM |
22 | import org.eclipse.linuxtools.internal.pcap.core.protocol.ipv4.IPv4Packet; |
23 | import org.eclipse.linuxtools.internal.pcap.core.protocol.unknown.UnknownPacket; | |
24 | import org.eclipse.linuxtools.internal.pcap.core.trace.PcapFile; | |
5255c030 VP |
25 | |
26 | // TODO For all packets, make checks on dimension. | |
27 | // TODO maybe add a invalid packet type? | |
28 | ||
29 | /** | |
30 | * Abstract class that implements the methods that are common to every packets. | |
31 | * | |
32 | * @author Vincent Perot | |
33 | */ | |
34 | public abstract class Packet { | |
35 | ||
36 | /** Empty string */ | |
37 | protected static final String EMPTY_STRING = ""; //$NON-NLS-1$ | |
38 | ||
39 | /** The Pcap File to which this packet belong */ | |
40 | private final PcapFile fPcapFile; | |
41 | ||
42 | /** The parent packet of this packet */ | |
43 | private final @Nullable Packet fParentPacket; | |
44 | ||
45 | /** The protocol that this packet uses */ | |
c88feda9 | 46 | private final PcapProtocol fProtocol; |
5255c030 VP |
47 | |
48 | /** | |
49 | * Constructor of the Packet Class. | |
50 | * | |
51 | * @param file | |
52 | * The file to which this packet belongs. | |
53 | * @param parent | |
54 | * The parent packet of this packet. | |
55 | * @param protocol | |
56 | * The protocol of the packet. | |
57 | */ | |
c88feda9 | 58 | public Packet(PcapFile file, @Nullable Packet parent, PcapProtocol protocol) { |
5255c030 VP |
59 | fPcapFile = file; |
60 | fParentPacket = parent; | |
61 | fProtocol = protocol; | |
62 | } | |
63 | ||
64 | /** | |
65 | * Getter method for the Pcap File that contains this packet. | |
66 | * | |
67 | * @return The Pcap File. | |
68 | */ | |
69 | public PcapFile getPcapFile() { | |
70 | return fPcapFile; | |
71 | } | |
72 | ||
73 | /** | |
74 | * Method that returns the parent (encapsulating) packet of this packet. | |
75 | * This method returns null if the packet is a Pcap Packet (highest level of | |
76 | * encapsulation). | |
77 | * | |
78 | * @return The parent packet. | |
79 | */ | |
80 | public @Nullable Packet getParentPacket() { | |
81 | return fParentPacket; | |
82 | } | |
83 | ||
84 | /** | |
85 | * Method that returns the child (encapsulated) packet of this packet. This | |
86 | * method returns null if the packet is at the lowest level of | |
87 | * encapsulation. | |
88 | * | |
89 | * @return The child packet. | |
90 | */ | |
91 | public abstract @Nullable Packet getChildPacket(); | |
92 | ||
93 | /** | |
94 | * Getter method for the protocol of the packet. | |
95 | * | |
96 | * @return The protocol of the packet. | |
97 | */ | |
c88feda9 | 98 | public PcapProtocol getProtocol() { |
5255c030 VP |
99 | return fProtocol; |
100 | } | |
101 | ||
102 | /** | |
103 | * Getter method for the payload of the packet. Returns null if there is no | |
104 | * payload. | |
105 | * | |
106 | * @return the payload of the packet. | |
107 | */ | |
108 | public abstract @Nullable ByteBuffer getPayload(); | |
109 | ||
110 | /** | |
111 | * Method that looks for the packet that respects the specified protocol. It | |
112 | * will go through all the layers of encapsulation and return the wanted | |
113 | * packet, or null if the protocol is not present. | |
114 | * | |
115 | * @param protocol | |
116 | * The specified protocol. | |
117 | * @return The packet that respects the protocol. | |
118 | */ | |
c88feda9 | 119 | public final @Nullable Packet getPacket(PcapProtocol protocol) { |
5255c030 VP |
120 | |
121 | Packet wantedPacket = this; | |
122 | ||
123 | while (wantedPacket != null) { | |
124 | if (wantedPacket.getProtocol() == protocol) { | |
125 | return wantedPacket; | |
126 | } | |
127 | wantedPacket = wantedPacket.getParentPacket(); | |
128 | } | |
129 | wantedPacket = this.getChildPacket(); | |
130 | ||
131 | while (wantedPacket != null) { | |
132 | if (wantedPacket.getProtocol() == protocol) { | |
133 | return wantedPacket; | |
134 | } | |
135 | wantedPacket = wantedPacket.getChildPacket(); | |
136 | } | |
137 | ||
138 | return null; | |
139 | } | |
140 | ||
141 | /** | |
142 | * Method that looks if the protocol is contained in the packet, or in one | |
143 | * of the encapsulating/encapsulated packet. It will go through all the | |
144 | * layers of encapsulation and return true if it finds the specified | |
145 | * protocol, and false otherwise. * | |
146 | * | |
147 | * @param protocol | |
148 | * The specified protocol. | |
149 | * @return The presence of the protocol. | |
150 | */ | |
c88feda9 | 151 | public final boolean hasProtocol(PcapProtocol protocol) { |
5255c030 VP |
152 | |
153 | // TODO Verify inputs | |
154 | Packet wantedPacket = this; | |
155 | ||
156 | while (wantedPacket != null) { | |
157 | if (wantedPacket.getProtocol() == protocol) { | |
158 | return true; | |
159 | } | |
160 | wantedPacket = wantedPacket.getParentPacket(); | |
161 | } | |
162 | wantedPacket = this.getChildPacket(); | |
163 | ||
164 | while (wantedPacket != null) { | |
165 | if (wantedPacket.getProtocol() == protocol) { | |
166 | return true; | |
167 | } | |
168 | wantedPacket = wantedPacket.getChildPacket(); | |
169 | } | |
170 | ||
171 | return false; | |
172 | } | |
173 | ||
174 | /** | |
175 | * Method that returns the most encapsulated packet possible. If the global | |
176 | * packet contains the protocol Unknown, it will stop at the packet just | |
177 | * before this protocol. This is because the {@link UnknownPacket} can be | |
178 | * considered as plain payload. | |
179 | * | |
180 | * @return The most encapsulated packet. | |
181 | */ | |
182 | public Packet getMostEcapsulatedPacket() { | |
e20e3d49 | 183 | @NonNull Packet packet = this; |
c88feda9 | 184 | while (packet.getProtocol() != PcapProtocol.UNKNOWN) { |
5255c030 | 185 | Packet childPacket = packet.getChildPacket(); |
c88feda9 | 186 | if (childPacket == null || childPacket.getProtocol() == PcapProtocol.UNKNOWN) { |
5255c030 VP |
187 | break; |
188 | } | |
189 | packet = childPacket; | |
190 | } | |
191 | return packet; | |
192 | } | |
193 | ||
194 | /** | |
195 | * Method that look at the validity of the different fields (such as | |
196 | * checksum). This is protocol dependent and is used to identify bad | |
197 | * packets. | |
198 | * | |
199 | * @return The validity of the packet. | |
200 | */ | |
201 | public abstract boolean validate(); | |
202 | ||
203 | /** | |
204 | * Internal method that is used to find the child packet. This is protocol | |
205 | * dependent and must be implemented by each packet class. | |
206 | * | |
207 | * @return The child packet. | |
208 | * @throws BadPacketException | |
209 | * Thrown when the packet is erroneous. | |
210 | */ | |
211 | protected abstract @Nullable Packet findChildPacket() throws BadPacketException; | |
212 | ||
213 | /** | |
214 | * This method returns the source endpoint of this packet. The endpoint is | |
215 | * equivalent to the address of this packet, and is protocol dependent. For | |
216 | * instance, a UDP endpoint is the combination of the MAC address, the IP | |
217 | * address and the port number. | |
218 | * | |
219 | * @return The source endpoint of this packet. | |
220 | */ | |
221 | public abstract ProtocolEndpoint getSourceEndpoint(); | |
222 | ||
223 | /** | |
224 | * This method returns the destination endpoint of this packet. The endpoint | |
225 | * is equivalent to the address of this packet, and is protocol dependent. | |
226 | * For instance, a UDP endpoint is the combination of the MAC address, the | |
227 | * IP address and the port number. | |
228 | * | |
229 | * @return The destination endpoint of this packet. | |
230 | */ | |
231 | public abstract ProtocolEndpoint getDestinationEndpoint(); | |
232 | ||
233 | /** | |
234 | * Method that returns all the fields of the packet as a Map<Field ID, Field | |
235 | * Value>. All child classes of {@link Packet} must implement this method. | |
236 | * | |
237 | * @return All the packet fields as a map. | |
238 | */ | |
239 | public abstract Map<String, String> getFields(); | |
240 | ||
241 | /** | |
242 | * Method that returns a short summary of the local packet, such as the most | |
243 | * useful information. | |
244 | * | |
245 | * For instance, a possible summary string of an {@link IPv4Packet} can be: | |
246 | * "Src: 192.168.0.1, Dst: 192.168.1.12". | |
247 | * | |
248 | * @return A short summary of the local packet, as a string. | |
249 | */ | |
250 | public abstract String getLocalSummaryString(); | |
251 | ||
252 | /** | |
253 | * Method that returns the local meaning of a packet, based on its fields. | |
254 | * | |
255 | * For instance, a possible signification of an ARP packet can be: | |
256 | * "Who has 192.168.1.12? Tell 192.168.0.1". | |
257 | * | |
258 | * @return The local meaning of the packet, as a string. | |
259 | */ | |
260 | protected abstract String getSignificationString(); | |
261 | ||
262 | /** | |
263 | * Method that returns the global meaning of the packet. As such, it will | |
264 | * look for the most relevant packet and display its signification. | |
265 | * | |
266 | * For instance, a possible signification of an ARP packet can be: | |
267 | * "Who has 192.168.1.12? Tell 192.168.0.1". | |
268 | * | |
269 | * @return The meaning of the global packet, as a string. | |
270 | */ | |
271 | public final String getGlobalSummaryString() { | |
272 | Packet packet = this.getMostEcapsulatedPacket(); | |
273 | return packet.getSignificationString(); | |
274 | } | |
275 | ||
276 | @Override | |
277 | public abstract boolean equals(@Nullable Object obj); | |
278 | ||
279 | @Override | |
280 | public abstract int hashCode(); | |
281 | ||
282 | /** | |
283 | * Method that is used by child packet classes to verify if a bit is set. | |
284 | * | |
285 | * @param value | |
286 | * the byte containing the flags. | |
287 | * @param bit | |
288 | * the bit index. | |
289 | * @return Whether the bit is set or not. | |
290 | */ | |
291 | protected static final boolean isBitSet(byte value, int bit) { | |
292 | if (bit < 0 || bit > 7) { | |
293 | throw new IllegalArgumentException("The byte index is not valid!"); //$NON-NLS-1$ | |
294 | } | |
295 | return ((value >>> bit & 0b1) == 0b1); | |
296 | } | |
297 | } |