1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2009 Benjamin Poirier <benjamin.poirier@polymtl.ca>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
23 #include <arpa/inet.h>
34 #include "data_structures_tcp.h"
38 #define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format)
41 // TCP sequence numbers use clock arithmetic, these comparison functions take
43 #define SEQ_LT(a,b) ((int32_t)((a)-(b)) < 0)
44 #define SEQ_LEQ(a,b) ((int32_t)((a)-(b)) <= 0)
45 #define SEQ_GT(a,b) ((int32_t)((a)-(b)) > 0)
46 #define SEQ_GEQ(a,b) ((int32_t)((a)-(b)) >= 0)
50 * Compare two ConnectionKey structures
53 * true if each field of the structure is equal
56 bool connectionKeyEqual(const ConnectionKey
* const a
, const
57 ConnectionKey
* const b
)
59 if (a
->saddr
== b
->saddr
&& a
->daddr
== b
->daddr
&& a
->source
== b
->source
60 && a
->dest
== b
->dest
)
72 * Check if a packet is an acknowledge of another packet.
75 * ackPacket packet that is the confirmation
76 * ackedPacket packet that contains the original data, both packets have to
77 * come from the same direction of the same connection
79 bool isAcking(const Packet
* const ackPacket
, const Packet
* const
82 if (SEQ_GT(ackPacket
->inE
->packetKey
->ack_seq
,
83 ackedPacket
->inE
->packetKey
->seq
))
95 * Convert an IP address from 32 bit form to dotted quad
98 * str: A preallocated string of length >= 17
101 void convertIP(char* const str
, const uint32_t addr
)
103 struct in_addr iaddr
;
105 iaddr
.s_addr
= htonl(addr
);
106 strcpy(str
, inet_ntoa(iaddr
));
111 * Print the content of a Packet structure
113 void printPacket(const Packet
* const packet
)
115 char saddr
[17], daddr
[17];
116 PacketKey
* packetKey
;
118 packetKey
= packet
->inE
->packetKey
;
120 convertIP(saddr
, packetKey
->connectionKey
.saddr
);
121 convertIP(daddr
, packetKey
->connectionKey
.daddr
);
122 g_debug("%s:%u to %s:%u tot_len: %u ihl: %u seq: %u ack_seq: %u doff: %u "
123 "ack: %u rst: %u syn: %u fin: %u", saddr
,
124 packetKey
->connectionKey
.source
, daddr
, packetKey
->connectionKey
.dest
,
125 packetKey
->tot_len
, packetKey
->ihl
, packetKey
->seq
,
126 packetKey
->ack_seq
, packetKey
->doff
, packetKey
->ack
, packetKey
->rst
,
127 packetKey
->syn
, packetKey
->fin
);
132 * A GHashFunc for g_hash_table_new()
134 * This function is for indexing netEvents in unMatched lists. All fields of
135 * the corresponding packet must match for two keys to be equal.
140 guint
ghfPacketKeyHash(gconstpointer key
)
147 a
= p
->connectionKey
.source
+ (p
->connectionKey
.dest
<< 16);
148 b
= p
->connectionKey
.saddr
;
149 c
= p
->connectionKey
.daddr
;
152 a
+= p
->ihl
+ (p
->tot_len
<< 8) + (p
->doff
<< 24);
157 a
+= p
->ack
+ (p
->rst
<< 8) + (p
->syn
<< 16) + (p
->fin
<< 24);
165 * A GEqualFunc for g_hash_table_new()
167 * This function is for indexing netEvents in unMatched lists. All fields of
168 * the corresponding packet must match for two keys to be equal.
174 * TRUE if both values are equal
176 gboolean
gefPacketKeyEqual(gconstpointer a
, gconstpointer b
)
178 const PacketKey
* pA
, * pB
;
180 pA
= ((PacketKey
*) a
);
181 pB
= ((PacketKey
*) b
);
183 if (connectionKeyEqual(&pA
->connectionKey
, &pB
->connectionKey
) &&
184 pA
->ihl
== pB
->ihl
&&
185 pA
->tot_len
== pB
->tot_len
&&
186 pA
->seq
== pB
->seq
&&
187 pA
->ack_seq
== pB
->ack_seq
&&
188 pA
->doff
== pB
->doff
&&
189 pA
->ack
== pB
->ack
&&
190 pA
->rst
== pB
->rst
&&
191 pA
->syn
== pB
->syn
&&
204 * A GDestroyNotify function for g_hash_table_new_full()
209 void gdnDestroyNetEvent(gpointer data
)
211 destroyNetEvent((NetEvent
*) data
);
216 * A GDestroyNotify function for g_hash_table_new_full()
219 * data: GQueue* list[Packet]
221 void gdnPacketListDestroy(gpointer data
)
225 list
= (GQueue
*) data
;
227 g_debug("XXXX gdnPacketListDestroy\n");
229 g_queue_foreach(list
, &gfPacketDestroy
, NULL
);
235 * A GFunc for g_queue_foreach()
238 * data Packet*, packet to destroy
241 void gfPacketDestroy(gpointer data
, gpointer user_data
)
243 g_debug("XXXX gfPacketDestroy\n");
244 destroyPacket((Packet
*) data
);
249 * Free the memory used by a Packet and the memory of all its associated
252 void destroyPacket(Packet
* const packet
)
254 g_debug("XXXX destroyPacket ");
258 g_assert(packet
->inE
!= NULL
&& packet
->outE
!= NULL
&&
259 packet
->inE
->packetKey
== packet
->outE
->packetKey
);
261 packet
->outE
->packetKey
= NULL
;
263 destroyNetEvent(packet
->inE
);
264 destroyNetEvent(packet
->outE
);
266 if (packet
->acks
!= NULL
)
268 g_queue_foreach(packet
->acks
, &gfPacketDestroy
, NULL
);
269 g_queue_free(packet
->acks
);
277 * Free the memory used by a NetEvent
279 void destroyNetEvent(NetEvent
* const event
)
281 g_debug("XXXX destroyNetEvent\n");
283 if (event
->packetKey
!= NULL
)
285 free(event
->packetKey
);
292 * A GCompareFunc for g_queue_find_custom()
295 * a Packet* acked packet
296 * b Packet* ack packet
301 gint
gcfPacketAckCompare(gconstpointer a
, gconstpointer b
)
303 if (isAcking((const Packet
*) b
, (const Packet
*) a
))
315 * A GHashFunc for g_hash_table_new()
317 * Hash TCP connection keys. Here are a few possible implementations:
319 * 2.4 kernels used tcp_hashfn()
321 * I've seen something about an XOR hash:
322 * http://tservice.net.ru/~s0mbre/blog/2006/05/14#2006_05_14:
323 * unsigned int h = (laddr ^ lport) ^ (faddr ^ fport);
328 * In 2.6 kernels, inet_ehashfn() handles connection hashing with the help of
329 * Jenkins hashing, jhash.h
331 * This function uses jenkins hashing. The hash is not the same for packets in
332 * opposite directions of the same connection. (Hence the name
333 * connection*key*hash)
338 guint
ghfConnectionKeyHash(gconstpointer key
)
340 ConnectionKey
* connectionKey
;
343 connectionKey
= (ConnectionKey
*) key
;
345 a
= connectionKey
->source
+ (connectionKey
->dest
<< 16);
346 b
= connectionKey
->saddr
;
347 c
= connectionKey
->daddr
;
355 * A GEqualFunc for g_hash_table_new()
358 * a, b ConnectionKey*
361 * TRUE if both values are equal
363 gboolean
gefConnectionKeyEqual(gconstpointer a
, gconstpointer b
)
365 // Two packets in the same direction
366 if (connectionKeyEqual((const ConnectionKey
*) a
, (const ConnectionKey
*) b
))
378 * A GDestroyNotify function for g_hash_table_new_full()
381 * data: ConnectionKey*
383 void gdnConnectionKeyDestroy(gpointer data
)
385 free((ConnectionKey
*) data
);
This page took 0.038678 seconds and 5 git commands to generate.