6bdf0b257a697aea73b2b9536d4e09df895f91ad
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.h"
37 // TCP sequence numbers use clock arithmetic, these comparison functions take
39 #define SEQ_LT(a,b) ((int32_t)((a)-(b)) < 0)
40 #define SEQ_LEQ(a,b) ((int32_t)((a)-(b)) <= 0)
41 #define SEQ_GT(a,b) ((int32_t)((a)-(b)) > 0)
42 #define SEQ_GEQ(a,b) ((int32_t)((a)-(b)) >= 0)
46 * Compare two ConnectionKey structures
49 * true if each field of the structure is equal
52 bool connectionKeyEqual(const ConnectionKey
* const a
, const
53 ConnectionKey
* const b
)
55 if (a
->saddr
== b
->saddr
&& a
->daddr
== b
->daddr
&& a
->source
== b
->source
56 && a
->dest
== b
->dest
)
68 * Check if a packet is an acknowledge of another packet.
71 * ackSegment packet that is the confirmation
72 * ackedSegment packet that contains the original data, both packets have to
73 * come from the same direction of the same connection. Both
74 * messages have to contain TCP events.
76 bool isAcking(const Message
* const ackSegment
, const Message
* const
79 g_assert(ackSegment
->inE
->type
== TCP
);
80 g_assert(ackSegment
->outE
->type
== TCP
);
82 if (SEQ_GT(ackSegment
->inE
->event
.tcpEvent
->segmentKey
->ack_seq
,
83 ackedSegment
->inE
->event
.tcpEvent
->segmentKey
->seq
))
95 * Convert an IP address from 32 bit form to dotted quad
98 * str: A preallocated string of length >= 16
101 void convertIP(char* const str
, const uint32_t addr
)
103 strcpy(str
, inet_ntoa((struct in_addr
) {.s_addr
= addr
}));
108 * Print the content of a TCP Message structure
110 void printTCPSegment(const Message
* const segment
)
112 char saddr
[16], daddr
[16];
113 SegmentKey
* segmentKey
;
115 g_assert(segment
->inE
->type
== TCP
);
116 g_assert(segment
->inE
->event
.tcpEvent
->segmentKey
==
117 segment
->outE
->event
.tcpEvent
->segmentKey
);
119 segmentKey
= segment
->inE
->event
.tcpEvent
->segmentKey
;
121 convertIP(saddr
, segmentKey
->connectionKey
.saddr
);
122 convertIP(daddr
, segmentKey
->connectionKey
.daddr
);
123 g_debug("%s:%u to %s:%u tot_len: %u ihl: %u seq: %u ack_seq: %u doff: %u "
124 "ack: %u rst: %u syn: %u fin: %u", saddr
,
125 segmentKey
->connectionKey
.source
, daddr
, segmentKey
->connectionKey
.dest
,
126 segmentKey
->tot_len
, segmentKey
->ihl
, segmentKey
->seq
,
127 segmentKey
->ack_seq
, segmentKey
->doff
, segmentKey
->ack
, segmentKey
->rst
,
128 segmentKey
->syn
, segmentKey
->fin
);
133 * A GHashFunc for g_hash_table_new()
135 * This function is for indexing TCPEvents in unMatched lists. All fields of
136 * the corresponding SegmentKey must match for two keys to be equal.
142 * A hash of all fields in the SegmentKey
144 guint
ghfSegmentKeyHash(gconstpointer key
)
149 p
= (SegmentKey
*) key
;
151 a
= p
->connectionKey
.source
+ (p
->connectionKey
.dest
<< 16);
152 b
= p
->connectionKey
.saddr
;
153 c
= p
->connectionKey
.daddr
;
156 a
+= p
->ihl
+ (p
->tot_len
<< 8) + (p
->doff
<< 24);
161 a
+= p
->ack
+ (p
->rst
<< 8) + (p
->syn
<< 16) + (p
->fin
<< 24);
164 g_debug("segment key hash %p: %u", p
, c
);
171 * A GEqualFunc for g_hash_table_new()
173 * This function is for indexing TCPEvents in unMatched lists. All fields of
174 * the corresponding SegmentKey must match for two keys to be equal.
180 * TRUE if both values are equal
182 gboolean
gefSegmentKeyEqual(gconstpointer a
, gconstpointer b
)
184 const SegmentKey
* sA
, * sB
;
189 if (connectionKeyEqual(&sA
->connectionKey
, &sB
->connectionKey
) &&
190 sA
->ihl
== sB
->ihl
&&
191 sA
->tot_len
== sB
->tot_len
&&
192 sA
->seq
== sB
->seq
&&
193 sA
->ack_seq
== sB
->ack_seq
&&
194 sA
->doff
== sB
->doff
&&
195 sA
->ack
== sB
->ack
&&
196 sA
->rst
== sB
->rst
&&
197 sA
->syn
== sB
->syn
&&
200 g_debug("segment key equal %p %p: TRUE", sA
, sB
);
205 g_debug("segment key equal %p %p: FALSE", sA
, sB
);
212 * A GDestroyNotify function for g_hash_table_new_full()
217 void gdnDestroyEvent(gpointer data
)
221 event
->destroy(event
);
226 * A GDestroyNotify function for g_hash_table_new_full()
229 * data: GQueue* list[Packet]
231 void gdnTCPSegmentListDestroy(gpointer data
)
235 list
= (GQueue
*) data
;
237 g_debug("XXXX gdnTCPSegmentListDestroy\n");
239 g_queue_foreach(list
, &gfTCPSegmentDestroy
, NULL
);
245 * A GFunc for g_queue_foreach()
248 * data Message*, TCP message to destroy
251 void gfTCPSegmentDestroy(gpointer data
, gpointer user_data
)
253 g_debug("XXXX gfTCPSegmentDestroy\n");
254 destroyTCPSegment((Message
*) data
);
259 * Free the memory used by a TCP Message and the memory of all its associated
263 * segment TCP Message to destroy
265 void destroyTCPSegment(Message
* const segment
)
267 TCPEvent
* inE
, *outE
;
269 g_debug("XXXX destroyTCPSegment");
270 segment
->print(segment
);
272 g_assert(segment
->inE
!= NULL
&& segment
->outE
!= NULL
);
273 g_assert(segment
->inE
->type
== TCP
&& segment
->outE
->type
== TCP
);
274 inE
= segment
->inE
->event
.tcpEvent
;
275 outE
= segment
->outE
->event
.tcpEvent
;
276 g_assert(inE
->segmentKey
== outE
->segmentKey
);
278 outE
->segmentKey
= NULL
;
280 destroyTCPEvent(segment
->inE
);
281 destroyTCPEvent(segment
->outE
);
288 * Free the memory used by a TCP Exchange and the memory of SOME of its
289 * associated resources. The message is not destroyed. Use destroyTCPSegment()
293 * exchange TCP Exchange to destroy. The .message must be NULL
295 void destroyTCPExchange(Exchange
* const exchange
)
297 g_assert(exchange
->message
== NULL
);
299 if (exchange
->acks
!= NULL
)
301 g_queue_foreach(exchange
->acks
, &gfTCPSegmentDestroy
, NULL
);
302 g_queue_free(exchange
->acks
);
310 * Free the memory used by a TCP Event and its associated resources
312 void destroyTCPEvent(Event
* const event
)
314 g_assert(event
->type
== TCP
);
316 if (event
->event
.tcpEvent
->segmentKey
!= NULL
)
318 free(event
->event
.tcpEvent
->segmentKey
);
320 free(event
->event
.tcpEvent
);
321 event
->event
.tcpEvent
= NULL
;
327 * Free the memory used by a base Event
329 void destroyEvent(Event
* const event
)
331 g_assert(event
->event
.tcpEvent
== NULL
);
338 * Free the memory used by a UDP Event and its associated resources
340 void destroyUDPEvent(Event
* const event
)
342 g_assert(event
->type
== UDP
);
344 if (event
->event
.udpEvent
->datagramKey
!= NULL
)
346 free(event
->event
.udpEvent
->datagramKey
);
348 free(event
->event
.udpEvent
);
349 event
->event
.udpEvent
= NULL
;
355 * A GCompareFunc for g_queue_find_custom()
358 * a Message* acked packet
359 * b Message* ack packet
364 gint
gcfTCPSegmentAckCompare(gconstpointer a
, gconstpointer b
)
366 if (isAcking((const Message
*) b
, (const Message
*) a
))
378 * A GHashFunc for g_hash_table_new()
380 * Hash TCP connection keys. Here are a few possible implementations:
382 * 2.4 kernels used tcp_hashfn()
384 * I've seen something about an XOR hash:
385 * http://tservice.net.ru/~s0mbre/blog/2006/05/14#2006_05_14:
386 * unsigned int h = (laddr ^ lport) ^ (faddr ^ fport);
391 * In 2.6 kernels, inet_ehashfn() handles connection hashing with the help of
392 * Jenkins hashing, jhash.h
394 * This function uses jenkins hashing. The hash is not the same for packets in
395 * opposite directions of the same connection. (Hence the name
396 * connection*key*hash)
401 guint
ghfConnectionKeyHash(gconstpointer key
)
403 ConnectionKey
* connectionKey
;
406 connectionKey
= (ConnectionKey
*) key
;
408 a
= connectionKey
->source
+ (connectionKey
->dest
<< 16);
409 b
= connectionKey
->saddr
;
410 c
= connectionKey
->daddr
;
418 * A GEqualFunc for g_hash_table_new()
421 * a, b ConnectionKey*
424 * TRUE if both values are equal
426 gboolean
gefConnectionKeyEqual(gconstpointer a
, gconstpointer b
)
428 // Two packets in the same direction
429 if (connectionKeyEqual((const ConnectionKey
*) a
, (const ConnectionKey
*) b
))
441 * A GDestroyNotify function for g_hash_table_new_full()
444 * data: ConnectionKey*
446 void gdnConnectionKeyDestroy(gpointer data
)
448 free((ConnectionKey
*) data
);
453 * A GHashFunc for g_hash_table_new()
458 guint
ghfDatagramKeyHash(gconstpointer key
)
460 DatagramKey
* datagramKey
;
463 datagramKey
= (DatagramKey
*) key
;
465 a
= datagramKey
->saddr
;
466 b
= datagramKey
->daddr
;
467 c
= datagramKey
->source
+ (datagramKey
->dest
<< 16);
470 a
+= datagramKey
->ulen
; // 16 bits left here
471 b
+= *((uint32_t*) datagramKey
->dataKey
);
472 c
+= *((uint32_t*) ((void*) datagramKey
->dataKey
+ 4));
480 * A GEqualFunc for g_hash_table_new()
486 * TRUE if both values are equal
488 gboolean
gefDatagramKeyEqual(gconstpointer a
, gconstpointer b
)
490 const DatagramKey
* dA
, * dB
;
492 dA
= (DatagramKey
*) a
;
493 dB
= (DatagramKey
*) b
;
495 if (dA
->saddr
== dB
->saddr
&& dA
->daddr
== dB
->daddr
&&
496 dA
->source
== dB
->source
&& dA
->dest
== dB
->dest
&&
497 dA
->ulen
== dB
->ulen
&&
498 memcmp(dA
->dataKey
, dB
->dataKey
, sizeof(dA
->dataKey
)) == 0)
510 * A GDestroyNotify function for g_hash_table_new_full()
515 void gdnDestroyDatagramKey(gpointer data
)
517 free((DatagramKey
*) data
);
522 * A GDestroyNotify function for g_hash_table_new_full()
527 void gdnDestroyBroadcast(gpointer data
)
529 destroyBroadcast((Broadcast
*) data
);
534 * Free a Broadcast struct and its associated ressources
537 * broadcast: Broadcast*
539 void destroyBroadcast(Broadcast
* const broadcast
)
541 g_queue_foreach(broadcast
->events
, &gfDestroyEvent
, NULL
);
542 g_queue_free(broadcast
->events
);
548 * A GFunc for g_queue_foreach()
554 void gfDestroyEvent(gpointer data
, gpointer user_data
)
558 event
->destroy(event
);
562 /* Subtract two WallTime structs
568 * The result of tA - tB, as a double. This may incur a loss of
571 double wallTimeSub(const WallTime
const* tA
, const WallTime
const* tB
)
573 return (double) tA
->seconds
- tB
->seconds
+ ((double) tA
->nanosec
- tB
->nanosec
) / 1e9
;
578 * Allocate and copy a base event
581 * newEvent: new event, pointer will be updated
582 * event: event to copy
584 void copyEvent(const Event
* const event
, Event
** const newEvent
)
586 g_assert(event
->event
.tcpEvent
== NULL
);
588 *newEvent
= malloc(sizeof(Event
));
589 memcpy(*newEvent
, event
, sizeof(Event
));
594 * Allocate and copy a TCP event
597 * newEvent: new event, pointer will be updated
598 * event: event to copy
600 void copyTCPEvent(const Event
* const event
, Event
** const newEvent
)
602 g_assert(event
->type
== TCP
);
604 *newEvent
= malloc(sizeof(Event
));
605 memcpy(*newEvent
, event
, sizeof(Event
));
607 (*newEvent
)->event
.tcpEvent
= malloc(sizeof(TCPEvent
));
608 memcpy((*newEvent
)->event
.tcpEvent
, event
->event
.tcpEvent
,
611 (*newEvent
)->event
.tcpEvent
->segmentKey
= malloc(sizeof(SegmentKey
));
612 memcpy((*newEvent
)->event
.tcpEvent
->segmentKey
,
613 event
->event
.tcpEvent
->segmentKey
, sizeof(SegmentKey
));
618 * Allocate and copy a UDP event
621 * newEvent: new event, pointer will be updated
622 * event: event to copy
624 void copyUDPEvent(const Event
* const event
, Event
** const newEvent
)
626 g_assert(event
->type
== UDP
);
628 *newEvent
= malloc(sizeof(Event
));
629 memcpy(*newEvent
, event
, sizeof(Event
));
631 (*newEvent
)->event
.udpEvent
= malloc(sizeof(UDPEvent
));
632 memcpy((*newEvent
)->event
.udpEvent
, event
->event
.udpEvent
,
635 (*newEvent
)->event
.udpEvent
->datagramKey
= malloc(sizeof(DatagramKey
));
636 memcpy((*newEvent
)->event
.udpEvent
->datagramKey
,
637 event
->event
.udpEvent
->datagramKey
, sizeof(DatagramKey
));
642 * A GFunc for g_queue_foreach()
645 * data Event*, event to add
646 * user_data GArray*, array to add to
648 void gfAddEventToArray(gpointer data
, gpointer user_data
)
650 g_array_append_val((GArray
*) user_data
, data
);
This page took 0.043117 seconds and 3 git commands to generate.