1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
|
================
TCPICK INTERNALS
================
updated to version 0.1.2
tcpick is a sniffer libcap-based.
tcpick keeps track of all connection using a special structure,
conn_t, used to keep in memory the connection:
stack.c:
struct conn_t
{
int status; /* 1 means SYN_SENT,
2 means SYN_RECEIVED,
3 means ESTABLISHED,
4 ??? FIXME
*/
u_int32_t client_ip; /* ip address of client */
u_int32_t server_ip; /* ip address of server */
u_int32_t client_seq;
u_int32_t server_seq;
u_int16_t client_port;
u_int16_t server_port;
u_int32_t client_seq_off;
u_int32_t server_seq_off;
int server_packets_num;
int client_data_size; /* size of all data transmitted from client*/
int server_data_size; /* size of all data transmitted from server*/
char *client_data; /* data */
char *server_data; /* data */
FILE *client_file;
FILE *server_file;
char *client_filename;
char *server_filename;
FILE *both_file;
int file_opened;
};
All connection tracked are kept in a special "stack" (but isn't
properly a stack) that I declared in that way:
stack.c:
struct conn_t ** stack;
it is a pointer to the first address of a block of free data of size
MAXCONN, allocated with calloc. Every address of this structure points
to a conn_t structure (allocated when a new connection is tracked).
After capturing data tcpick finds the data offset (skipping tcp
options) and passes the packet to the function verify():
stack.c:
int verify(struct ip *ippacket,
struct tcphdr *tcppacket,
u_char *payload, /* pointer to the data(offset)*/
int payload_len) /* data lenght */
the function verify() analyzes the tcp flags and calls the function
match():
stack.c:
int match(int status,
struct ip *ippacket,
struct tcphdr *tcppacket,
u_char *payload,
int payload_len)
the first argument is a "status" flag, that describes what kind of
flag are set. Then, there is a cycle that "scans" the "stack" seeking
for a conn_t that matches with the received packet. In that way, if
the packet matches with a conn_t structure, the status flag of the
structure is changed properly with this function:
stack.c:
int status_switch(struct conn_t * conn,int status)
status_switch, in that way, print on the terminal the new status of
the connection tracked, according to the status flag:
status==1 => SYN-SENT
status==2 => SYN-RECEIVED
status==3 => ESTABLISHED
status==4 => FIN-WAIT-1
(other statuses should be developed soon!)
If the connection is just ESTABLISHED (conn_ptr->status_flag==0)
the packet is passed to the function data_write():
stack.c:
int data_write(struct conn_t * conn_ptr,
u_int32_t data_off, /* offset from beginning */
u_char * payload,
int payload_len,
int part /* client (1) or server (2) ? */
)
where data_off is the actual seq field minus the first minus one:
data_off=(ntohl(tcppacket->seq)-ntohl((*stack_ptr)->server_seq))-1;
the purpose of data_write is simple: write the payload to memory.
Then, if the file_flag is set, these data are written to disk through
the function file_write():
stack.c:
int file_write(struct conn_t * conn_ptr,
u_int32_t data_off, /* offset from beginning */
u_char * payload,
int payload_len,
int part /* client (1) or server (2) ? */
)
Conclusions: tcpick requires people willing to debug/improve it,
do you wanna get involved? :)
|