#include <glib.h>
#include <epan/packet.h>
-#include <epan/ipproto.h>
+#include <epan/to_str.h>
+#include <epan/emem.h>
#include <epan/dissectors/packet-tcp.h>
#include "follow.h"
#include <epan/conversation.h>
#define MAX_IPADDR_LEN 16
typedef struct _tcp_frag {
- gulong seq;
- gulong len;
- gulong data_len;
+ guint32 seq;
+ guint32 len;
+ guint32 data_len;
gchar *data;
struct _tcp_frag *next;
} tcp_frag;
+WS_DLL_PUBLIC_DEF
FILE* data_out_file = NULL;
gboolean empty_tcp_stream;
gboolean incomplete_tcp_stream;
-static guint32 tcp_stream_to_follow;
+static guint32 tcp_stream_to_follow = 0;
static guint8 ip_address[2][MAX_IPADDR_LEN];
static guint port[2];
static guint bytes_written[2];
static gboolean is_ipv6 = FALSE;
-static int check_fragments( int, tcp_stream_chunk *, gulong );
+static int check_fragments( int, tcp_stream_chunk *, guint32 );
static void write_packet_data( int, tcp_stream_chunk *, const char * );
void
}
}
-/* this will build libpcap filter text that will only
+/* This will build a display filter text that will only
pass the packets related to the stream. There is a
chance that two streams could intersect, but not a
very good one */
-char*
-build_follow_filter( packet_info *pi ) {
+gchar*
+build_follow_conv_filter( packet_info *pi ) {
char* buf;
int len;
conversation_t *conv=NULL;
struct tcp_analysis *tcpd;
+ wmem_list_frame_t* protos;
+ int proto_id;
+ const char* proto_name;
+ gboolean is_tcp = FALSE, is_udp = FALSE;
+
+ protos = wmem_list_head(pi->layers);
+
+ /* walk the list of a available protocols in the packet to
+ figure out if any of them affect context sensitivity */
+ while (protos != NULL)
+ {
+ proto_id = GPOINTER_TO_INT(wmem_list_frame_data(protos));
+ proto_name = proto_get_protocol_filter_name(proto_id);
+
+ if (!strcmp(proto_name, "tcp")) {
+ is_tcp = TRUE;
+ } else if (!strcmp(proto_name, "udp")) {
+ is_udp = TRUE;
+ }
+
+ protos = wmem_list_frame_next(protos);
+ }
if( ((pi->net_src.type == AT_IPv4 && pi->net_dst.type == AT_IPv4) ||
(pi->net_src.type == AT_IPv6 && pi->net_dst.type == AT_IPv6))
- && pi->ipproto == IP_PROTO_TCP
- && (conv=find_conversation(pi->fd->num, &pi->src, &pi->dst, pi->ptype,
+ && is_tcp && (conv=find_conversation(pi->fd->num, &pi->src, &pi->dst, pi->ptype,
pi->srcport, pi->destport, 0)) != NULL ) {
/* TCP over IPv4 */
tcpd=get_tcp_conversation_data(conv, pi);
}
}
else if( pi->net_src.type == AT_IPv4 && pi->net_dst.type == AT_IPv4
- && pi->ipproto == IP_PROTO_UDP ) {
+ && is_udp ) {
/* UDP over IPv4 */
buf = g_strdup_printf(
"(ip.addr eq %s and ip.addr eq %s) and (udp.port eq %d and udp.port eq %d)",
- ip_to_str( pi->net_src.data),
- ip_to_str( pi->net_dst.data),
+ ip_to_str((const guint8 *)pi->net_src.data),
+ ip_to_str((const guint8 *)pi->net_dst.data),
pi->srcport, pi->destport );
len = 4;
is_ipv6 = FALSE;
}
else if( pi->net_src.type == AT_IPv6 && pi->net_dst.type == AT_IPv6
- && pi->ipproto == IP_PROTO_UDP ) {
+ && is_udp ) {
/* UDP over IPv6 */
buf = g_strdup_printf(
"(ipv6.addr eq %s and ipv6.addr eq %s) and (udp.port eq %d and udp.port eq %d)",
static address tcp_addr[2];
static gboolean find_tcp_index;
+gchar*
+build_follow_index_filter(void) {
+ gchar *buf;
+
+ find_tcp_addr = TRUE;
+ buf = g_strdup_printf("tcp.stream eq %d", tcp_stream_to_follow);
+ return buf;
+}
+
/* select a tcp stream to follow via it's address/port pairs */
gboolean
follow_tcp_addr(const address *addr0, guint port0,
return FALSE;
}
+ if (indx > get_tcp_stream_count()) {
+ return FALSE;
+ }
+
find_tcp_addr = TRUE;
tcp_stream_to_follow = indx;
memset(ip_address, 0, sizeof ip_address);
return TRUE;
}
+guint32
+get_follow_tcp_index(void) {
+ return tcp_stream_to_follow;
+}
+
/* here we are going to try and reconstruct the data portion of a TCP
session. We will try and handle duplicates, TCP fragments, and out
of order packets in a smart way. */
static tcp_frag *frags[2] = { 0, 0 };
-static gulong seq[2];
+static guint32 seq[2];
static guint8 src_addr[2][MAX_IPADDR_LEN];
static guint src_port[2] = { 0, 0 };
void
-reassemble_tcp( guint32 tcp_stream, gulong sequence, gulong acknowledgement,
- gulong length, const char* data, gulong data_length,
+reassemble_tcp( guint32 tcp_stream, guint32 sequence, guint32 acknowledgement,
+ guint32 length, const char* data, guint32 data_length,
int synflag, address *net_src, address *net_dst,
- guint srcport, guint dstport) {
+ guint srcport, guint dstport, guint32 packet_num) {
guint8 srcx[MAX_IPADDR_LEN], dstx[MAX_IPADDR_LEN];
int src_index, j, first = 0, len;
- gulong newseq;
+ guint32 newseq;
tcp_frag *tmp_frag;
tcp_stream_chunk sc;
port[0] = srcport;
memcpy(ip_address[1], net_dst->data, net_dst->len);
port[1] = dstport;
+ if (net_src->type == AT_IPv6 && net_dst->type == AT_IPv6) {
+ is_ipv6 = TRUE;
+ } else {
+ is_ipv6 = FALSE;
+ }
}
/* Check to see if we have seen this source IP and port before.
/* Initialize our stream chunk. This data gets written to disk. */
memcpy(sc.src_addr, srcx, len);
- sc.src_port = srcport;
- sc.dlen = data_length;
+ sc.src_port = srcport;
+ sc.dlen = data_length;
+ sc.packet_num = packet_num;
/* now that we have filed away the srcs, lets get the sequence number stuff
figured out */
info than we have already seen */
newseq = sequence + length;
if( newseq > seq[src_index] ) {
- gulong new_len;
+ guint32 new_len;
/* this one has more than we have seen. let's get the
payload that we have not seen. */
}
else {
/* out of order packet */
- if(data_length > 0 && ((glong)(sequence - seq[src_index]) > 0) ) {
+ if(data_length > 0 && GT_SEQ(sequence, seq[src_index]) ) {
tmp_frag = (tcp_frag *)g_malloc( sizeof( tcp_frag ) );
tmp_frag->data = (gchar *)g_malloc( data_length );
tmp_frag->seq = sequence;
/* here we search through all the frag we have collected to see if
one fits */
static int
-check_fragments( int idx, tcp_stream_chunk *sc, gulong acknowledged ) {
+check_fragments( int idx, tcp_stream_chunk *sc, guint32 acknowledged ) {
tcp_frag *prev = NULL;
tcp_frag *current;
- gulong lowest_seq;
+ guint32 lowest_seq;
gchar *dummy_str;
current = frags[idx];
if( current ) {
lowest_seq = current->seq;
while( current ) {
- if( (glong)(lowest_seq - current->seq) > 0 ) {
+ if( GT_SEQ(lowest_seq, current->seq) ) {
lowest_seq = current->seq;
}
if( current->seq < seq[idx] ) {
- gulong newseq;
+ guint32 newseq;
/* this sequence number seems dated, but
check the end to make sure it has no more
info than we have already seen */
newseq = current->seq + current->len;
if( newseq > seq[idx] ) {
- gulong new_pos;
+ guint32 new_pos;
/* this one has more than we have seen. let's get the
payload that we have not seen. This happens when
prev = current;
current = current->next;
}
- if( (glong)(acknowledged - lowest_seq) > 0 ) {
+ if( GT_SEQ(acknowledged, lowest_seq) ) {
/* There are frames missing in the capture file that were seen
* by the receiving host. Add dummy stream chunk with the data
* "[xxx bytes missing in capture file]".