1 //
2 // Copyright (C) 2008-2011 Institute of Telematics, Karlsruhe Institute of Technology (KIT)
3 //
4 // This program is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License
6 // as published by the Free Software Foundation; either version 2
7 // of the License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 //
18
19 #include "IpPacket.h"
20 #include "TcpPacket.h"
21 #include "UdpPacket.h"
22
23 AnonPrimitive* IpPacket::anonTos = NULL;
24 AnonPrimitive* IpPacket::anonIdentifier = NULL;
25 AnonPrimitive* IpPacket::anonFlags = NULL;
26 AnonPrimitive* IpPacket::anonFragoffset = NULL;
27 AnonPrimitive* IpPacket::anonTtl = NULL;
28 AnonPrimitive* IpPacket::anonSourceip = NULL;
29 AnonPrimitive* IpPacket::anonDestip = NULL;
30 AnonPrimitive* IpPacket::anonOptions = NULL;
31
IpPacket(void)32 IpPacket::IpPacket(void)
33 {
34 options.buf = NULL;
35 options.size = 0;
36 memset (&header, 0, sizeof (IP_HEADER));
37 protocol = Packet::PROTO_IP;
38 }
39
~IpPacket(void)40 IpPacket::~IpPacket(void)
41 {
42 options.destroy ();
43 }
44
parsePacket()45 bool IpPacket::parsePacket()
46 {
47 memcpy (&header, buffer, sizeof (IP_HEADER));
48
49 //
50 // check for correct checksum
51 //
52
53 if (Configuration::instance()->getSetBadChecksumsToBad ()) {
54 uint16_t chksum = header.checksum;
55 header.checksum = 0;
56 this->checksumgood = (checksum (&header) == chksum);
57 header.checksum = chksum;
58 }
59
60 //
61 // correct some endianess stuff
62 //
63
64 header.totallen = swap16(header.totallen);
65 header.identification = swap16(header.identification);
66 header.flags_fragoffset = swap16(header.flags_fragoffset);
67 header.checksum = swap16(header.checksum);
68
69 //
70 // get the next transport layer protocol
71 //
72
73 nextProtocol = IpPacket::getTransportProtocol (header.protocol);
74
75 //
76 // check for correct header values to make sure the packet is not corrupt
77 // if is is corrupt we will stop the parsing here and return
78 //
79
80 if (! ( IP_HEADER_NO_OPTIONS_LEN <= getHeaderlength () &&
81 getHeaderlength() <= getTotallen() )) {
82
83 layersize = getSize ();
84 nextProtocol = Packet::PROTO_NONE;
85 options.size = 0;
86 options.buf = NULL;
87 return true;
88 }
89
90 //
91 // get the options, if any are provided
92 //
93
94 options.size = getHeaderlength () - IP_HEADER_NO_OPTIONS_LEN;
95 options.buf = NULL;
96
97 if (options.size > 0 && getSize () >= IP_HEADER_NO_OPTIONS_LEN + options.size) {
98 options.buf = (uint8_t*) malloc (options.size);
99 memcpy (options.buf, buffer + IP_HEADER_NO_OPTIONS_LEN, options.size);
100 } else
101 options.size = 0;
102
103 layersize = sizeof (IP_HEADER) + options.size;
104
105 //
106 // remove the ethernet padding. Otherwise
107 // it will be used as payload.
108 // the ethernet class will add it again
109 //
110
111 if (getSize () > getTotallen ())
112 this->size = getTotallen ();
113
114 return true;
115 }
116
checksum(PIP_HEADER ipheader)117 uint16_t IpPacket::checksum (PIP_HEADER ipheader)
118 {
119 return Packet::checksum ((uint8_t*)ipheader, sizeof (IP_HEADER));
120 }
121
getVersion()122 uint8_t IpPacket::getVersion ()
123 {
124 return IP_HEADER_VERSION (header.version_len);
125 }
126
getHeaderlength()127 uint8_t IpPacket::getHeaderlength ()
128 {
129 return IP_HEADER_LEN (header.version_len);
130 }
131
getTos()132 uint8_t IpPacket::getTos ()
133 {
134 return header.typeofservice;
135 }
136
getIdentification()137 uint16_t IpPacket::getIdentification ()
138 {
139 return header.identification;
140 }
141
getFlags()142 uint16_t IpPacket::getFlags ()
143 {
144 return IP_HEADER_FLAGS (header.flags_fragoffset);
145 }
146
getFragoffset()147 uint16_t IpPacket::getFragoffset ()
148 {
149 return IP_HEADER_FRAGOFFSET (header.flags_fragoffset);
150 }
151
getTtl()152 uint8_t IpPacket::getTtl ()
153 {
154 return header.ttl;
155 }
156
getProtocol()157 uint8_t IpPacket::getProtocol ()
158 {
159 return header.protocol;
160 }
161
getChecksum()162 uint16_t IpPacket::getChecksum ()
163 {
164 return header.checksum;
165 }
166
getSourceip()167 IP_ADDR IpPacket::getSourceip ()
168 {
169 IP_ADDR ret = {{0}};
170 memcpy (&ret, &header.sourceip, IP_ADDR_LEN);
171 return ret;
172 }
173
getDestip()174 IP_ADDR IpPacket::getDestip ()
175 {
176 IP_ADDR ret = {{0}};
177 memcpy (&ret, &header.destip, IP_ADDR_LEN);
178 return ret;
179 }
180
setVersion(uint8_t ver)181 void IpPacket::setVersion (uint8_t ver)
182 {
183 header.version_len = ((ver & 0xF) << 4) | (getHeaderlength() / 4);
184 }
185
setHeaderlength(uint8_t len)186 void IpPacket::setHeaderlength (uint8_t len)
187 {
188 header.version_len = (getVersion() << 4) | ((uint8_t)((len/4) & 0xF));
189 }
190
setTos(uint8_t tos)191 void IpPacket::setTos (uint8_t tos)
192 {
193 header.typeofservice = tos;
194 }
195
setIdentification(uint16_t ident)196 void IpPacket::setIdentification (uint16_t ident)
197 {
198 header.identification = ident;
199 }
200
setFlags(uint16_t flgs)201 void IpPacket::setFlags (uint16_t flgs)
202 {
203 header.flags_fragoffset = ((uint16_t)(flgs & 0x07) << 13) | getFragoffset();
204 }
205
setFragoffset(uint16_t fragoff)206 void IpPacket::setFragoffset (uint16_t fragoff)
207 {
208 header.flags_fragoffset = ((getFlags() & 0x07) << 13) | (0xD & fragoff);
209 }
210
setTtl(uint8_t tl)211 void IpPacket::setTtl (uint8_t tl)
212 {
213 header.ttl = tl;
214 }
215
setProtocol(uint8_t proto)216 void IpPacket::setProtocol (uint8_t proto)
217 {
218 header.protocol = proto;
219 }
220
setChecksum(uint16_t checks)221 void IpPacket::setChecksum (uint16_t checks)
222 {
223 header.checksum = checks;
224 }
225
setSourceip(IP_ADDR sip)226 void IpPacket::setSourceip (IP_ADDR sip)
227 {
228 memcpy (&header.sourceip, &sip, IP_ADDR_LEN);
229 }
230
setDestip(IP_ADDR dip)231 void IpPacket::setDestip (IP_ADDR dip)
232 {
233 memcpy (&header.destip, &dip, IP_ADDR_LEN);
234 }
235
getTotallen()236 uint16_t IpPacket::getTotallen ()
237 {
238 return header.totallen;
239 }
240
setTotallen(uint16_t totlen)241 void IpPacket::setTotallen (uint16_t totlen)
242 {
243 header.totallen = totlen;
244 }
245
assemblePacket()246 void IpPacket::assemblePacket()
247 {
248 if (nextPacket != NULL) {
249
250 // TCP and UDP packets need the source
251 // and dest IP addresses to calc their
252 // checksums. So we pass it over here
253 // where it is already transformed.
254
255 if (nextPacket->getProtocol() == Packet::PROTO_TCP) {
256 ((TcpPacket*)nextPacket)->setIpAddresses (getSourceip(), getDestip());
257 } else if (nextPacket->getProtocol() == Packet::PROTO_UDP) {
258 ((UdpPacket*)nextPacket)->setIpAddresses (getSourceip(), getDestip());
259 }
260
261 nextPacket->assemblePacket ();
262 }
263
264 int thissize = sizeof (IP_HEADER) + options.size;
265 int nextsize = nextPacket != NULL ? nextPacket->getSize() : 0;
266
267 setSize (thissize + nextsize);
268
269 if (nextPacket != NULL)
270 memcpy (buffer + thissize, nextPacket->getBuffer(), nextsize);
271
272 //
273 // adjust length
274 //
275
276 setHeaderlength (thissize);
277 setTotallen (thissize + nextsize);
278
279 //
280 // correct endianess for copying
281 //
282
283 header.totallen = swap16(header.totallen );
284 header.identification = swap16(header.identification );
285 header.flags_fragoffset = swap16(header.flags_fragoffset);
286 header.checksum = swap16(header.checksum );
287
288 //
289 // calc checksum or set to random if the value was incorrect
290 //
291
292 setChecksum (0);
293
294 if (Configuration::instance()->getReCalcChecksums ()) {
295
296 if (Configuration::instance()->getSetBadChecksumsToBad () && !checksumgood)
297 setChecksum (RandomNumberGenerator::generate ());
298 else
299 setChecksum (checksum (&header));
300
301 } // if (Configuration::instance()->getReCalcChecksums ())
302
303 //
304 // copy into out buffer
305 //
306
307 memcpy (buffer, &header, sizeof (IP_HEADER));
308 memcpy (buffer + sizeof (IP_HEADER), options.buf,options.size);
309
310 //
311 // convert endianess back
312 //
313
314 header.totallen = swap16(header.totallen );
315 header.identification = swap16(header.identification );
316 header.flags_fragoffset = swap16(header.flags_fragoffset);
317 header.checksum = swap16(header.checksum );
318 }
319
setOptions(uint8_t * buf,int len)320 void IpPacket::setOptions (uint8_t* buf, int len)
321 {
322 options.buf = (uint8_t*) realloc (options.buf, len);
323 options.size = len;
324 memcpy (options.buf, buf, len);
325 }
326
getOptions()327 Packet::PAYLOAD_BUFFER IpPacket::getOptions()
328 {
329 PAYLOAD_BUFFER retbuf;
330
331 retbuf.buf = (uint8_t*) malloc (options.size);
332 retbuf.size = options.size;
333
334 memcpy (retbuf.buf, options.buf, options.size);
335
336 return retbuf;
337 }
338
toString()339 string IpPacket::toString ()
340 {
341 ostringstream out;
342 Packet::PAYLOAD_BUFFER opts = getOptions ();
343
344 out << "IP packet" << std::endl
345 << "\tversion: \t" << (int)getVersion() << std::endl
346 << "\tlength: \t" << (int)getHeaderlength() << " bytes" << std::endl
347 << "\ttos: \t\t0x" << std::hex << std::setw(2) << std::setfill ('0')<< (int)getTos () << std::endl << std::dec
348 << "\ttotal length: \t" << getTotallen() << " bytes" << std::endl
349 << "\tident: \t\t0x" << std::hex << std::setw(4) << std::setfill ('0') << getIdentification () << std::endl << std::dec
350 << "\tflags: \t\t0x" << std::hex << std::setw(2) << std::setfill ('0') << getFlags () << std::endl << std::dec
351 << "\tfragoff: \t0x" << std::hex << std::setw(4) << std::setfill ('0') << getFragoffset () << std::endl << std::dec
352 << "\tttl: \t\t" << (int)getTtl() << std::endl
353 << "\tprotocol: \t0x" << std::hex << std::setw(2) << std::setfill ('0') << (int)getProtocol () << std::endl << std::dec
354 << "\tchecksum: \t0x" << std::hex << std::setw(4) << std::setfill ('0') << getChecksum () << std::endl << std::dec
355 << "\tsource ip: \t" << getSourceip().toString() << std::endl
356 << "\tdest ip: \t" << getDestip().toString() << std::endl
357 << "\toptions len: \t" << opts.size << std::endl
358 << "\toptions: \t" << opts.toString();
359
360 opts.destroy ();
361 return out.str ();
362 }
363
getMinProtocolSize()364 uint32_t IpPacket::getMinProtocolSize ()
365 {
366 return sizeof (IP_HEADER);
367 }
368
getTransportProtocol(uint8_t proto)369 Packet::PROTOCOL IpPacket::getTransportProtocol (uint8_t proto)
370 {
371 Packet::PROTOCOL nextproto = Packet::PROTO_DATA_PAYLOAD;
372
373 switch (proto) {
374 case IPTYPE_TCP: nextproto = Packet::PROTO_TCP; break;
375 case IPTYPE_UDP: nextproto = Packet::PROTO_UDP; break;
376 case IPTYPE_ICMP: nextproto = Packet::PROTO_ICMP; break;
377 case IPTYPE_IP: nextproto = Packet::PROTO_IP; break;
378 case IPTYPE_IPV6: nextproto = Packet::PROTO_IPV6; break;
379 default: nextproto = Packet::PROTO_DATA_PAYLOAD; break;
380 }
381
382 return nextproto;
383 }
384