indent dump_dns.c
[prads.git] / src / util-cxt.c
blob340c2489df4c6f4dec2f23821decccecb4e353ae
1 /*
2 * Author: Gurvinder Singh <gurvindersinghdahiya@gmail.com>
3 * Fikling by Kacper Wyoscki
5 * Created on January 16, 2010, 1:18 PM
6 */
8 #include "prads.h"
9 #include "cxt.h"
10 #include "util-cxt.h"
11 #include "util-cxt-queue.h"
12 #include <stddef.h>
14 void cxt_queue_init()
16 /* alloc hash memory */
17 uint32_t i = 0;
18 /* pre allocate conection trackers */
19 for (i = 0; i < CXT_DEFAULT_PREALLOC; i++) {
20 connection *cxt = connection_alloc();
21 if (cxt == NULL) {
22 printf("ERROR: connection_alloc failed: %s\n", strerror(errno));
23 exit(1);
25 cxt_enqueue(&cxt_spare_q,cxt);
29 /* Allocate a connection */
30 connection *connection_alloc(void)
32 connection *cxt;
34 cxt = calloc(1, sizeof(connection));
35 if(cxt == NULL) {
36 printf("calloc failed to allocate connection\n");
37 return NULL;
39 cxt->next = NULL;
40 cxt->prev = NULL;
41 cxt->hnext = NULL;
42 cxt->hprev = NULL;
43 cxt->c_asset = NULL;
44 cxt->s_asset = NULL;
46 return cxt;
49 /* free the memory of a connection tracker */
50 void connection_free(connection *cxt)
52 free(cxt);
55 inline
56 void cxt_update_dst (connection *cxt, packetinfo *pi)
58 cxt->d_tcpFlags |= (pi->tcph ? pi->tcph->t_flags : 0x00);
59 cxt->d_total_bytes += pi->packet_bytes;
60 cxt->d_total_pkts += 1;
61 cxt->last_pkt_time = pi->pheader->ts.tv_sec;
62 pi->sc = SC_SERVER;
63 if (!(cxt->check & CXT_DONT_CHECK_SERVER)
64 && (cxt->d_total_bytes > MAX_BYTE_CHECK
65 || cxt->d_total_pkts > MAX_PKT_CHECK)) {
66 cxt->check |= CXT_DONT_CHECK_SERVER; // Don't check
68 return;
71 inline
72 void cxt_update_src (connection *cxt, packetinfo *pi)
74 cxt->s_tcpFlags |= (pi->tcph ? pi->tcph->t_flags : 0x00);
75 cxt->s_total_bytes += pi->packet_bytes;
76 cxt->s_total_pkts += 1;
77 cxt->last_pkt_time = pi->pheader->ts.tv_sec;
78 pi->sc = SC_CLIENT;
79 if (!(cxt->check & CXT_DONT_CHECK_CLIENT)
80 && (cxt->s_total_bytes > MAX_BYTE_CHECK
81 || cxt->s_total_pkts > MAX_PKT_CHECK)) {
82 cxt->check |= CXT_DONT_CHECK_CLIENT; // Don't check
84 return;
87 inline void cxt_update (packetinfo *pi)
89 connection *cxt = NULL;
90 int ret = 0;
91 uint32_t hash;
92 /* get our hash bucket and lock it */
93 if (pi->ip4 != NULL) {
94 hash = CXT_HASH4(PI_IP4SRC(pi),PI_IP4DST(pi));
95 hash = hash % BUCKET_SIZE;
96 } else {
97 hash = CXT_HASH6(&PI_IP6SRC(pi),&PI_IP6DST(pi));
98 hash = hash % BUCKET_SIZE;
100 cxt = bucket[hash];
102 /* see if the bucket already has a connection */
103 if (cxt == NULL) {
104 printf ("bucket[%u] is empty...\n",hash);
106 /* no, so get a new one */
107 cxt = cxt_dequeue(&cxt_spare_q);
108 if (cxt == NULL) {
109 cxt = connection_alloc();
110 if (cxt == NULL) {
111 return;
114 /* these are protected by the bucket lock */
115 cxt->hnext = NULL;
116 cxt->hprev = NULL;
118 /* got one, initialize and return */
119 cxt_new(cxt,pi);
120 bucket[hash] = cxt; /* is this what is missing ???? */
121 cxt_requeue(cxt, NULL, &cxt_est_q);
122 cxt_update_src(cxt, pi);
123 pi->cxt = cxt;
124 return;
127 /* ok, we have a flow in the bucket. Let's find out if it is our flow */
128 /* see if this is the flow we are looking for */
129 if (pi->af == AF_INET) {
130 if (CMP_CXT4(cxt, PI_IP4SRC(pi), pi->s_port, PI_IP4DST(pi), pi->d_port)) {
131 cxt_update_src(cxt, pi);
132 ret = 1;
133 } else if (CMP_CXT4(cxt, PI_IP4DST(pi), pi->d_port, PI_IP4SRC(pi), pi->s_port)) {
134 cxt_update_dst(cxt, pi);
135 ret = 1;
137 } else if (pi->af == AF_INET6){
138 if (CMP_CXT6(cxt, &PI_IP6SRC(pi), pi->s_port, &PI_IP6DST(pi), pi->d_port)) {
139 cxt_update_src(cxt, pi);
140 ret = 1;
141 } else if (CMP_CXT6(cxt, &PI_IP6DST(pi), pi->d_port, &PI_IP6SRC(pi), pi->s_port)) {
142 cxt_update_dst(cxt, pi);
143 ret = 1;
147 if (ret == 0) {
148 connection *pcxt = NULL; /* previous connection */
150 while (cxt != NULL) {
151 pcxt = cxt; /* pf is not locked at this point */
152 cxt = cxt->hnext;
154 if (cxt == NULL) {
155 /* get us a new one and put it and the list tail */
156 cxt = pcxt->hnext = cxt_dequeue(&cxt_spare_q);
157 if (cxt == NULL) {
159 cxt = connection_alloc();
160 if (cxt == NULL) {
161 return;
165 cxt->hnext = NULL;
166 cxt->hprev = pcxt;
168 /* initialize and return */
169 cxt_new(cxt,pi);
170 cxt_requeue(cxt, NULL, &cxt_est_q);
172 cxt_update_src(cxt, pi);
173 pi->cxt = cxt;
174 return;
177 if (pi->af == AF_INET) {
178 if (CMP_CXT4(cxt, PI_IP4SRC(pi), pi->s_port, PI_IP4DST(pi), pi->d_port)) {
179 cxt_update_src(cxt, pi);
180 ret = 1;
181 } else if (CMP_CXT4(cxt, PI_IP4DST(pi), pi->d_port, PI_IP4SRC(pi), pi->s_port)) {
182 cxt_update_dst(cxt, pi);
183 ret = 1;
185 } else if (pi->af == AF_INET6) {
186 if (CMP_CXT6(cxt, &PI_IP6SRC(pi), pi->s_port, &PI_IP6DST(pi), pi->d_port)) {
187 cxt_update_src(cxt, pi);
188 ret = 1;
189 } else if (CMP_CXT6(cxt, &PI_IP6DST(pi), pi->d_port, &PI_IP6SRC(pi), pi->s_port)) {
190 cxt_update_dst(cxt, pi);
191 ret = 1;
194 if ( ret != 0) {
195 /* we found our flow, lets put it on top of the
196 * hash list -- this rewards active flows */
197 if (cxt->hnext) cxt->hnext->hprev = cxt->hprev;
198 if (cxt->hprev) cxt->hprev->hnext = cxt->hnext;
200 cxt->hnext = cxt;
201 cxt->hprev = NULL;
202 cxt->hprev = cxt;
203 cxt = cxt;
205 /* found our connection */
206 pi->cxt = cxt;
207 return;
210 /* not found, try the next... */
213 pi->cxt = cxt;
214 /* The 'root' connection was our connection, return it. */
215 return;
218 void free_queue()
220 connection *cxt;
222 while((cxt = cxt_dequeue(&cxt_spare_q))) {
223 connection_free(cxt);
226 while((cxt = cxt_dequeue(&cxt_est_q))) {
227 connection_free(cxt);
230 printf("\nqueue memory has been cleared");
233 /* initialize the connection from the first packet we see from it. */
235 void cxt_new (connection *cxt, packetinfo *pi)
237 printf("New connection...\n");
238 extern u_int64_t cxtrackerid;
239 cxtrackerid += 1;
241 cxt->cxid = cxtrackerid;
242 cxt->af = pi->af;
243 cxt->s_tcpFlags |= (pi->tcph ? pi->tcph->t_flags : 0x00);
244 cxt->s_total_bytes = pi->packet_bytes;
245 cxt->s_total_pkts = 1;
246 cxt->start_time = pi->pheader->ts.tv_sec;
247 cxt->last_pkt_time = pi->pheader->ts.tv_sec;
248 if(pi->af == AF_INET){
249 IP4ADDR(&cxt->s_ip) = PI_IP4SRC(pi);
250 IP4ADDR(&cxt->d_ip) = PI_IP4DST(pi);
251 }else{
252 cxt->s_ip = PI_IP6SRC(pi);
253 cxt->d_ip = PI_IP6DST(pi);
255 cxt->s_port = pi->s_port;
256 cxt->d_port = pi->d_port;
257 cxt->proto = (pi->ip4 ? pi->ip4->ip_p : pi->ip6->next);
258 cxt->check = 0x00;
259 cxt->c_asset = NULL;
260 cxt->s_asset = NULL;
261 cxt->reversed = 0;
262 pi->sc = SC_CLIENT;
265 void reverse_pi_cxt(packetinfo *pi)
267 uint8_t tmpFlags;
268 uint64_t tmp_pkts;
269 uint64_t tmp_bytes;
270 struct in6_addr tmp_ip;
271 uint16_t tmp_port;
272 connection *cxt;
274 cxt = pi->cxt;
276 /* First we chang the cxt */
277 /* cp src to tmp */
278 tmpFlags = cxt->s_tcpFlags;
279 tmp_pkts = cxt->s_total_pkts;
280 tmp_bytes = cxt->s_total_bytes;
281 tmp_ip = cxt->s_ip;
282 tmp_port = cxt->s_port;
284 /* cp dst to src */
285 cxt->s_tcpFlags = cxt->d_tcpFlags;
286 cxt->s_total_pkts = cxt->d_total_pkts;
287 cxt->s_total_bytes = cxt->d_total_bytes;
288 cxt->s_ip = cxt->d_ip;
289 cxt->s_port = cxt->d_port;
291 /* cp tmp to dst */
292 cxt->d_tcpFlags = tmpFlags;
293 cxt->d_total_pkts = tmp_pkts;
294 cxt->d_total_bytes = tmp_bytes;
295 cxt->d_ip = tmp_ip;
296 cxt->d_port = tmp_port;
298 /* Not taking any chances :P */
299 cxt->c_asset = cxt->s_asset = NULL;
300 cxt->check = 0x00;
302 /* Then we change pi */
303 if (pi->sc == SC_CLIENT) pi->sc = SC_SERVER;
304 else pi->sc = SC_CLIENT;