-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.c
162 lines (137 loc) · 3.81 KB
/
main.c
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#include "def.h"
#include "config.h"
#include "tcp_state.h"
#include "tcp_pcap.h"
#include "hash_table.h"
#include "malloc.h"
#include "log.h"
#include "cmd_options.h"
#include <stdlib.h>
#include <string.h>
#include <errno.h>
// #include <pcap.h>
#include <pcap/pcap.h>
#include <signal.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <net/ethernet.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
struct in_addr server;
pcap_t *pcap_handle;
struct hash_table_entry **hash_table;
static int pkt_counter = 0;
void cleanup();
static void handle_signal(int signo)
{
fprintf(stdout, "catch signo %d, finishing...\n", signo);
cleanup();
fprintf(stdout, "finished.\n");
exit(0);
}
static void register_signal()
{
if (signal(SIGINT, &handle_signal) == SIG_ERR) {
LOG(ERROR, "Couldn't register signal hanlder!\n");
exit(1);
}
if (signal(SIGTERM, &handle_signal) == SIG_ERR) { // "CTRL + \"
LOG(ERROR, "Couldn't register signal hanlder!\n");
exit(1);
}
}
//data structure prepare
void init()
{
pcap_handle = pcap_init();
if (inet_aton(server_ip, &server) != 1) {
LOG(ERROR, "Could not convert server ip to in_addr\n");
exit(1);
}
register_signal();//tie signal to handle_signal, mainly print some info
hash_table = new_hash_table();
}
void cleanup()
{
pcap_cleanup(pcap_handle);
cleanup_hash_table(hash_table);
}
static void parse_tcp_info(struct tcp_key *key, double time, struct tcphdr *th, int len, int dir)
{
// LOG(INFO, "time: %.6lf, len: %d, dir: %d\n", time, len, dir);
struct tcp_state * ts = find_ts_entry(hash_table, key);
//flow starts, insert_ts_entry
if (ts == NULL && IS_SYN(th) && dir == DIR_IN) {
ts = new_tcp_state(key, time); //see tcp_stat.c
insert_ts_entry(hash_table, ts);
}
if (ts != NULL) {
//update ts with info inside of th
tcp_state_machine(ts, th, len, time, dir);
if (ts->state == TCP_CLOSE || ts->state == TCP_CLOSING) {
delete_ts_entry(hash_table, ts);
// free_tcp_state(ts);
}
}
}
void handle_pcap()
{
struct pcap_pkthdr pph;
const u_char *packet;
while ((packet = pcap_next(pcap_handle, &pph))) { // pcap_next - read the next packet from a pcap_t
pkt_counter += 1;
if (pcap_limit > 0 && pkt_counter >= pcap_limit) {
LOG(INFO, "finished...\n");
exit(0);
}
double time = (double)pph.ts.tv_sec + (double)(pph.ts.tv_usec)/1000000;
int len = pph.caplen; // caplen is the true length of data captured
struct ip *ip_hdr = get_ip_hdr(packet, &len);
if (ip_hdr == NULL)
continue;
struct tcphdr *tcp_hdr = (struct tcphdr *)((u_char *)ip_hdr + ip_hdr->ip_hl*4);
int iphdr_len = ip_hdr->ip_hl*4;
int tcphdr_len = tcp_hdr->doff*4;
if (tcphdr_len > len) {
LOG(DEBUG, "tcp header is not captured completely.\n");
continue;
}
/* get tcp key */
int dir;
struct tcp_key key; // declare in tcp_base.h
if (memcmp(&ip_hdr->ip_src, &server, sizeof(server)) == 0) {
key.addr[0] = ip_hdr->ip_src;
key.addr[1] = ip_hdr->ip_dst;
key.port[0] = tcp_hdr->source;
key.port[1] = tcp_hdr->dest;
dir = DIR_OUT;
}
else {
key.addr[0] = ip_hdr->ip_dst;
key.addr[1] = ip_hdr->ip_src;
key.port[0] = tcp_hdr->dest;
key.port[1] = tcp_hdr->source;
dir = DIR_IN;
}
//data length
int payload_len = ntohs(ip_hdr->ip_len) - iphdr_len - tcphdr_len;
/* parse tcp info */
parse_tcp_info(&key, time, tcp_hdr, payload_len, dir);
}
}
int main(int argc, const char **argv)
{
struct timeval start_tv, end_tv;
unsigned long start_time, end_time;
gettimeofday(&start_tv, NULL);
start_time = start_tv.tv_sec * 1000000 + start_tv.tv_usec;
parse_cmd_options(argc, argv);//define in cmd_options.c
init();
handle_pcap();
cleanup();
gettimeofday(&end_tv, NULL);
end_time = end_tv.tv_sec * 1000000 + end_tv.tv_usec;
fprintf(stdout, "time_used:%lf\n", 1.0*(end_time - start_time)/1000000);
return 0;
}