1 /*
2 ettercap -- connection list handling module
3
4 Copyright (C) ALoR & NaGA
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20 */
21
22 #include <ec.h>
23 #include <ec_threads.h>
24 #include <ec_packet.h>
25 #include <ec_proto.h>
26 #include <ec_hook.h>
27 #include <ec_conntrack.h>
28 #include <ec_hash.h>
29 #include <ec_sleep.h>
30 #include <ec_geoip.h>
31
32 /* globals */
33
34 /* the hash table used to index the tailq */
35 struct conn_hash_search {
36 struct conn_tail *cl;
37 LIST_ENTRY(conn_hash_search) next;
38 };
39
40 #define TABBIT 10 /* 2^10 bit tab entries: 1024 LISTS */
41 #define TABSIZE (1 << TABBIT)
42 #define TABMASK (TABSIZE - 1)
43
44 /*
45 * the connection list.
46 * this list is created adding new element in the tail.
47 * the search method is established in the search function.
48 * an hash table is used and it is double-linked with the
49 * tailq so from each element you can delete the corresponding
50 * in the tailq or viceversa
51 */
52 static TAILQ_HEAD(conn_head, conn_tail) conntrack_tail_head = TAILQ_HEAD_INITIALIZER(conntrack_tail_head);
53 static LIST_HEAD(, conn_hash_search) conntrack_search_head[TABSIZE];
54
55 /* global mutex on connections list */
56
57 static pthread_mutex_t conntrack_mutex = PTHREAD_MUTEX_INITIALIZER;
58 #define CONNTRACK_LOCK do{ pthread_mutex_lock(&conntrack_mutex); }while(0)
59 #define CONNTRACK_UNLOCK do{ pthread_mutex_unlock(&conntrack_mutex); }while(0)
60
61 /* protos */
62
63 void __init conntrack_init(void);
64
65 static void conntrack_parse(struct packet_object *po);
66 static u_int32 conntrack_hash(struct packet_object *po);
67 static struct conn_object *conntrack_search(struct packet_object *po);
68 static void conntrack_update(struct conn_object *co, struct packet_object *po);
69 static void conntrack_add(struct packet_object *po);
70 static void conntrack_del(struct conn_object *co);
71 static int conntrack_match(struct conn_object *co, struct packet_object *po);
72 void conntrack_hook(struct conn_object *co, struct packet_object *po);
73
74 /************************************************/
75
76 /*
77 * add the hook function
78 */
conntrack_init(void)79 void __init conntrack_init(void)
80 {
81 /* receive all the top half packets */
82 hook_add(HOOK_DISPATCHER, &conntrack_parse);
83 }
84
85 /*
86 * the conntrack main()
87 */
conntrack_parse(struct packet_object * po)88 static void conntrack_parse(struct packet_object *po)
89 {
90 struct conn_object *conn;
91
92 CONNTRACK_LOCK;
93
94 /* search if the connection already exists */
95 conn = conntrack_search(po);
96
97 /* update if it was found, else add to the list */
98 if (conn)
99 conntrack_update(conn, po);
100 else
101 conntrack_add(po);
102
103 CONNTRACK_UNLOCK;
104 }
105
106 /*
107 * calculate the hash for a packet object
108 */
conntrack_hash(struct packet_object * po)109 static u_int32 conntrack_hash(struct packet_object *po)
110 {
111 u_int32 hash_array[3];
112
113 /*
114 * put them in an array and then compute the hash on the array.
115 * use XOR on src and dst because the hash must be equal for
116 * packets from dst to src and viceversa
117 */
118 hash_array[0] = fnv_32((u_char *)&po->L3.src, sizeof(struct ip_addr)) ^
119 fnv_32((u_char *)&po->L3.dst, sizeof(struct ip_addr));
120 hash_array[1] = po->L4.src ^ po->L4.dst;
121 hash_array[2] = po->L4.proto;
122
123 /* compute the resulting hash */
124 return fnv_32((u_char *)&hash_array, sizeof(hash_array)) & TABMASK;
125 }
126
127 /*
128 * search the connection in the connection table
129 * and return the pointer.
130 */
conntrack_search(struct packet_object * po)131 static struct conn_object *conntrack_search(struct packet_object *po)
132 {
133 struct conn_hash_search *cs;
134 u_int32 h;
135
136 /* use the hash table to find the connection in the tailq */
137 h = conntrack_hash(po);
138
139 LIST_FOREACH(cs, &conntrack_search_head[h], next) {
140 if (conntrack_match(cs->cl->co, po) == E_SUCCESS) {
141 return cs->cl->co;
142 }
143 }
144
145 return NULL;
146 #if 0
147 struct conn_tail *cl;
148
149 /* search in the list sequentially */
150 TAILQ_FOREACH(cl, &conntrack_tail_head, next) {
151 if (conntrack_match(cl->co, po) == E_SUCCESS) {
152 return cl->co;
153 }
154 }
155
156 return NULL;
157 #endif
158 }
159
160
161 /*
162 * update the variable parameters in the connection struct.
163 * the status, the buffer and the timestamp will be updated
164 */
conntrack_update(struct conn_object * co,struct packet_object * po)165 static void conntrack_update(struct conn_object *co, struct packet_object *po)
166 {
167 /* update the timestamp */
168 gettimeofday(&co->ts, 0);
169
170 /* update the status for TCP conn */
171 if (po->L4.flags & TH_SYN)
172 co->status = CONN_OPENING;
173 else if (po->L4.flags & TH_FIN)
174 co->status = CONN_CLOSING;
175 else if (po->L4.flags & TH_ACK) {
176 /* syn + ack, ack */
177 if (co->status == CONN_OPENING )
178 co->status = CONN_OPEN;
179 /* fin + ack, ack */
180 else if (co->status == CONN_CLOSING)
181 co->status = CONN_CLOSED;
182 }
183
184 if (po->L4.flags & TH_PSH)
185 co->status = CONN_ACTIVE;
186
187 if (po->L4.flags & TH_RST)
188 co->status = CONN_KILLED;
189
190 /* update the buffer */
191 connbuf_add(&co->data, po);
192
193
194 /* update the status for UDP conn */
195 if (po->L4.proto == NL_TYPE_UDP)
196 co->status = CONN_ACTIVE;
197
198 /*
199 * update the byte count
200 * use DATA.len and not DATA.disp_len to have an
201 * effective count of byte trasferred, disp_data
202 * may be longer or shorted than DATA.data
203 */
204 co->xferred += po->DATA.len;
205 if(!ip_addr_cmp(&co->L3_addr1, &po->L3.src))
206 co->tx += po->DATA.len;
207 else
208 co->rx += po->DATA.len;
209
210 /*
211 * update the flags:
212 * if the packet was modified or dropped, the connection
213 * must be marked as well.
214 */
215 if (po->flags & PO_MODIFIED || po->flags & PO_DROPPED)
216 co->flags |= CONN_MODIFIED;
217
218 /*
219 * update the password
220 * always overwrite the old one, a better one may
221 * has been collected...
222 */
223 if (po->DISSECTOR.user) {
224 SAFE_FREE(co->DISSECTOR.user);
225 SAFE_FREE(co->DISSECTOR.pass);
226 SAFE_FREE(co->DISSECTOR.info);
227 co->DISSECTOR.user = strdup(po->DISSECTOR.user);
228 if (po->DISSECTOR.pass)
229 co->DISSECTOR.pass = strdup(po->DISSECTOR.pass);
230 if (po->DISSECTOR.info)
231 co->DISSECTOR.info = strdup(po->DISSECTOR.info);
232 }
233
234 /* execute the hookpoint */
235 conntrack_hook(co, po);
236 }
237
238
239 /*
240 * create a new entry in the tail
241 */
conntrack_add(struct packet_object * po)242 static void conntrack_add(struct packet_object *po)
243 {
244 struct conn_tail *cl;
245 struct conn_hash_search *cs;
246
247 DEBUG_MSG("conntrack_add: NEW CONNECTION");
248
249 /* alloc the list element */
250 SAFE_CALLOC(cl, 1, sizeof(struct conn_tail));
251
252 /* alloc the conn object in the element */
253 SAFE_CALLOC(cl->co, 1, sizeof(struct conn_object));
254
255 /*
256 * here we create the connection.
257 * this is the first packet seen...
258 * addr1 will be the source and addr2 the dest
259 */
260
261 /* fill the addresses */
262 memcpy(&cl->co->L2_addr1, &po->L2.src, MEDIA_ADDR_LEN);
263 memcpy(&cl->co->L2_addr2, &po->L2.dst, MEDIA_ADDR_LEN);
264
265 memcpy(&cl->co->L3_addr1, &po->L3.src, sizeof(struct ip_addr));
266 memcpy(&cl->co->L3_addr2, &po->L3.dst, sizeof(struct ip_addr));
267
268 /* copy the port */
269 cl->co->L4_addr1 = po->L4.src;
270 cl->co->L4_addr2 = po->L4.dst;
271 cl->co->L4_proto = po->L4.proto;
272
273 /* initialize the connection buffer */
274 connbuf_init(&cl->co->data, EC_GBL_CONF->connection_buffer);
275
276 /* update the connection entry */
277 conntrack_update(cl->co, po);
278
279 /* alloc the hash table element */
280 SAFE_CALLOC(cs, 1, sizeof(struct conn_hash_search));
281
282 /* set the pointer to the list */
283 cs->cl = cl;
284
285 /*
286 * set the pointer to the element in the hash table
287 * it is used when a connection is deleted because
288 * even the element in the hash table must be deleted
289 */
290 cl->cs = cs;
291
292 /* insert the new connection in the tail */
293 TAILQ_INSERT_TAIL(&conntrack_tail_head, cl, next);
294 /* insert the new connection in the tail */
295 LIST_INSERT_HEAD(&conntrack_search_head[conntrack_hash(po)], cs, next);
296 }
297
298 /*
299 * is the packet object belonging to this connection ?
300 */
conntrack_match(struct conn_object * co,struct packet_object * po)301 static int conntrack_match(struct conn_object *co, struct packet_object *po)
302 {
303 /* different protocol, they don't match */
304 if (co->L4_proto != po->L4.proto)
305 return -E_INVALID;
306
307 /* match it in one way... */
308 if (!ip_addr_cmp(&co->L3_addr1, &po->L3.src) &&
309 !ip_addr_cmp(&co->L3_addr2, &po->L3.dst) &&
310 co->L4_addr1 == po->L4.src &&
311 co->L4_addr2 == po->L4.dst)
312 return E_SUCCESS;
313
314 /* ...and in the other */
315 if (!ip_addr_cmp(&co->L3_addr1, &po->L3.dst) &&
316 !ip_addr_cmp(&co->L3_addr2, &po->L3.src) &&
317 co->L4_addr1 == po->L4.dst &&
318 co->L4_addr2 == po->L4.src)
319 return E_SUCCESS;
320
321 return -E_NOMATCH;
322 }
323
324 /*
325 * erase a connection object
326 */
conntrack_del(struct conn_object * co)327 static void conntrack_del(struct conn_object *co)
328 {
329 struct ct_hook_list *h, *tmp;
330
331 /* remove the hooks */
332 SLIST_FOREACH_SAFE(h, &co->hook_head, next, tmp) {
333 SLIST_REMOVE(&co->hook_head, h, ct_hook_list, next);
334 SAFE_FREE(h);
335 }
336
337 /* wipe the associated buffer */
338 connbuf_wipe(&co->data);
339
340 SAFE_FREE(co);
341 }
342
343 /*
344 * erase the whole connections list
345 */
conntrack_purge(void)346 void conntrack_purge(void)
347 {
348 struct conn_tail *cl, *tmp;
349
350 DEBUG_MSG("conntrack_purge");
351
352 TAILQ_FOREACH_SAFE(cl, &conntrack_tail_head, next, tmp) {
353 /* don't erase the connection if it is viewed */
354 if (cl->co->flags & CONN_VIEWING)
355 continue;
356
357 CONNTRACK_LOCK;
358
359 /* wipe the connection */
360 conntrack_del(cl->co);
361 /* remove the element in the hash table */
362 LIST_REMOVE(cl->cs, next);
363 SAFE_FREE(cl->cs);
364 /* remove the element in the tailq */
365 TAILQ_REMOVE(&conntrack_tail_head, cl, next);
366 SAFE_FREE(cl);
367
368 CONNTRACK_UNLOCK;
369 }
370
371 }
372
373
EC_THREAD_FUNC(conntrack_timeouter)374 EC_THREAD_FUNC(conntrack_timeouter)
375 {
376 struct timeval ts;
377 struct timeval diff;
378 struct conn_tail *cl;
379 struct conn_tail *tmp = NULL;
380 size_t sec;
381
382 /* variable not used */
383 (void) EC_THREAD_PARAM;
384
385 /* initialize the thread */
386 ec_thread_init();
387
388 DEBUG_MSG("conntrack_timeouter: activated !");
389
390 LOOP {
391
392 /*
393 * sleep for the maximum time possible
394 * (determined as the minumum of the timeouts)
395 */
396 sec = MIN(EC_GBL_CONF->connection_idle, EC_GBL_CONF->connection_timeout);
397
398 DEBUG_MSG("conntrack_timeouter: sleeping for %lu sec", (unsigned long)sec);
399
400 /* always check if a cancel is requested */
401 CANCELLATION_POINT();
402
403 ec_usleep(SEC2MICRO(sec));
404
405 DEBUG_MSG("conntrack_timeouter: woke up");
406
407 /* get current time */
408 gettimeofday(&ts, NULL);
409
410 /*
411 * the timeouter is the only thread that erase a connection
412 * so we are sure that the list will be consistent till the
413 * end.
414 * we can lock and unlock every time we handle an element of
415 * the list to permit the conntrack functions to operate on the
416 * list even when timeouter goes thru the list
417 */
418 TAILQ_FOREACH_SAFE(cl, &conntrack_tail_head, next, tmp) {
419
420 /* don't erase the connection if it is viewed */
421 if (cl->co->flags & CONN_VIEWING)
422 continue;
423
424 CONNTRACK_LOCK;
425
426 /* calculate the difference */
427 time_sub(&ts, &cl->co->ts, &diff);
428
429 /*
430 * update it only if the staus is active,
431 * all the other status must be left as they are
432 */
433 if (cl->co->status == CONN_ACTIVE && diff.tv_sec >= EC_GBL_CONF->connection_idle)
434 cl->co->status = CONN_IDLE;
435
436 /* delete the timeouted connections */
437 if (diff.tv_sec >= EC_GBL_CONF->connection_timeout) {
438 /* wipe the connection */
439 conntrack_del(cl->co);
440 /* remove the element in the hash table */
441 LIST_REMOVE(cl->cs, next);
442 SAFE_FREE(cl->cs);
443 /* remove the element in the tailq */
444 TAILQ_REMOVE(&conntrack_tail_head, cl, next);
445 SAFE_FREE(cl);
446 }
447
448 CONNTRACK_UNLOCK;
449
450 CANCELLATION_POINT();
451 }
452 }
453
454 return NULL;
455 }
456
457
458 /*
459 * add the fucntion 'func' to the hookpoint of the
460 * connection owning the packet object
461 */
conntrack_hook_packet_add(struct packet_object * po,void (* func)(struct packet_object * po))462 int conntrack_hook_packet_add(struct packet_object *po, void (*func)(struct packet_object *po))
463 {
464 struct conn_object *conn;
465
466 CONNTRACK_LOCK;
467
468 /* search the connection already exists */
469 conn = conntrack_search(po);
470
471 /*
472 * if the connection already exist, add the hook function
473 * else create the entry for the connection and add the hook
474 * this is useful to add hooks for future connections
475 */
476
477 /* create the fake connection */
478 if (!conn) {
479
480 DEBUG_MSG("conntrack_hook_packet_add: ephemeral connection");
481 conntrack_add(po);
482 conn = conntrack_search(po);
483 }
484
485 /* add the hook point */
486 if (conn) {
487 struct ct_hook_list *h;
488
489 DEBUG_MSG("conntrack_hook_packet_add: existing connection");
490
491 SAFE_CALLOC(h, 1, sizeof(struct ct_hook_list));
492
493 /* set the hook function */
494 h->func = func;
495
496 SLIST_INSERT_HEAD(&conn->hook_head, h, next);
497
498 CONNTRACK_UNLOCK;
499 return E_SUCCESS;
500 }
501
502 CONNTRACK_UNLOCK;
503
504 return -E_NOTFOUND;
505 }
506
507
508 /*
509 * removes a hook from a connection
510 */
conntrack_hook_packet_del(struct packet_object * po,void (* func)(struct packet_object * po))511 int conntrack_hook_packet_del(struct packet_object *po, void (*func)(struct packet_object *po))
512 {
513 struct conn_object *conn;
514
515 DEBUG_MSG("conntrack_hook_packet_del");
516
517 CONNTRACK_LOCK;
518
519 /* search the connection already exists */
520 conn = conntrack_search(po);
521
522 /* remove the hook function only if the connection exists */
523 if (conn) {
524 struct ct_hook_list *h;
525
526 SLIST_FOREACH(h, &conn->hook_head, next) {
527 if (h->func == func) {
528 SLIST_REMOVE(&conn->hook_head, h, ct_hook_list, next);
529 SAFE_FREE(h);
530 break;
531 }
532 }
533
534 CONNTRACK_UNLOCK;
535 return E_SUCCESS;
536 }
537
538 CONNTRACK_UNLOCK;
539
540 return -E_NOTFOUND;
541 }
542
543 /*
544 * add the fucntion 'func' to the hookpoint of the
545 * connection 'co'
546 */
conntrack_hook_conn_add(struct conn_object * co,void (* func)(struct packet_object * po))547 int conntrack_hook_conn_add(struct conn_object *co, void (*func)(struct packet_object *po))
548 {
549 struct ct_hook_list *h;
550
551 CONNTRACK_LOCK;
552
553 /* add the hook point */
554
555 DEBUG_MSG("conntrack_hook_conn_add");
556
557 SAFE_CALLOC(h, 1, sizeof(struct ct_hook_list));
558
559 /* set the hook function */
560 h->func = func;
561
562 SLIST_INSERT_HEAD(&co->hook_head, h, next);
563
564 CONNTRACK_UNLOCK;
565
566 return E_SUCCESS;
567 }
568
569
570 /*
571 * removes a hook from a connection
572 */
conntrack_hook_conn_del(struct conn_object * co,void (* func)(struct packet_object * po))573 int conntrack_hook_conn_del(struct conn_object *co, void (*func)(struct packet_object *po))
574 {
575 struct ct_hook_list *h;
576
577 DEBUG_MSG("conntrack_hook_conn_del");
578
579 CONNTRACK_LOCK;
580
581 SLIST_FOREACH(h, &co->hook_head, next) {
582 if (h->func == func) {
583 SLIST_REMOVE(&co->hook_head, h, ct_hook_list, next);
584 SAFE_FREE(h);
585 break;
586 }
587 }
588
589 CONNTRACK_UNLOCK;
590 return E_SUCCESS;
591 }
592
593
594 /*
595 * executes the hook point
596 */
conntrack_hook(struct conn_object * co,struct packet_object * po)597 void conntrack_hook(struct conn_object *co, struct packet_object *po)
598 {
599 struct ct_hook_list *h;
600
601 /* pass the po to all the hooked functions */
602 SLIST_FOREACH(h, &co->hook_head, next) {
603 h->func(po);
604 }
605
606 }
607
608 /*
609 * fill the desc and return the next/prev element
610 */
conntrack_print(int mode,void * list,char ** desc,size_t len)611 void * conntrack_print(int mode, void *list, char **desc, size_t len)
612 {
613 struct conn_tail *c = (struct conn_tail *)list;
614 struct conn_tail *cl;
615 char src[MAX_ASCII_ADDR_LEN];
616 char dst[MAX_ASCII_ADDR_LEN];
617 char proto[2], status[8], flags[2];
618 #ifdef HAVE_GEOIP
619 size_t slen;
620 #endif
621
622 /* NULL is used to retrieve the first element */
623 if (list == NULL)
624 return TAILQ_FIRST(&conntrack_tail_head);
625
626 /* the caller wants the description */
627 if (desc != NULL) {
628
629 /* IP address to string */
630 ip_addr_ntoa(&c->co->L3_addr1, src);
631 ip_addr_ntoa(&c->co->L3_addr2, dst);
632
633 /* determine the protocol */
634 conntrack_protostr(c->co, proto, sizeof(proto));
635
636 /* determine the status */
637 conntrack_statusstr(c->co, status, sizeof(status));
638
639 /* determine the flags */
640 conntrack_flagstr(c->co, flags, sizeof(flags));
641
642 snprintf(*desc, len, "%1s %15s:%-5d - %15s:%-5d %1s %s TX: %lu RX: %lu",
643 flags, src, ntohs(c->co->L4_addr1), dst, ntohs(c->co->L4_addr2),
644 proto, status, (unsigned long)c->co->tx, (unsigned long)c->co->rx);
645
646 #ifdef HAVE_GEOIP
647 /* determine current string length */
648 slen = strlen(*desc);
649
650 /* check if enough space is available to append the GeoIP info */
651 if (len - slen > 14 && EC_GBL_CONF->geoip_support_enable) {
652 snprintf(*desc + slen, len - slen, ", CC: %2s > %2s",
653 geoip_ccode_by_ip(&c->co->L3_addr1),
654 geoip_ccode_by_ip(&c->co->L3_addr2));
655 }
656 #endif
657 }
658
659 /* return the next/prev/current to the caller */
660 switch (mode) {
661 case -1:
662 return TAILQ_PREV(c, conn_head, next);
663 break;
664 case +1:
665 return TAILQ_NEXT(c, next);
666 break;
667 case 0:
668 /* if exists in the list, return it */
669 TAILQ_FOREACH(cl, &conntrack_tail_head, next) {
670 if (cl == c)
671 return c;
672 }
673 /* else, return NULL */
674 return NULL;
675 default:
676 return list;
677 break;
678 }
679
680 return NULL;
681 }
682
683 /*
684 * copy the connection object pointer to conn and return the next/prev element
685 */
conntrack_get(int mode,void * list,struct conn_object ** conn)686 void * conntrack_get(int mode, void *list, struct conn_object **conn)
687 {
688 struct conn_tail *c = (struct conn_tail *)list;
689 struct conn_tail *cl;
690
691 /* NULL is used to retrieve the first element */
692 if (list == NULL)
693 return TAILQ_FIRST(&conntrack_tail_head);
694
695 /* the caller wants the connection object */
696 if (conn != NULL)
697 *conn = c->co;
698
699 /* return the next/prev/current to the caller */
700 switch (mode) {
701 case -1:
702 return TAILQ_PREV(c, conn_head, next);
703 break;
704 case +1:
705 return TAILQ_NEXT(c, next);
706 break;
707 case 0:
708 /* if exists in the list, return it */
709 TAILQ_FOREACH(cl, &conntrack_tail_head, next) {
710 if (cl == c)
711 return c;
712 }
713 /* else, return NULL */
714 return NULL;
715 default:
716 return list;
717 break;
718 }
719
720 return NULL;
721 }
722
723
724 /*
725 * copies the protocol string of a given connection object into pstr
726 * E_SUCCESS is returned on success
727 * -E_INVALID is returned if parameters are not initialized
728 */
conntrack_protostr(struct conn_object * conn,char * pstr,int len)729 int conntrack_protostr(struct conn_object *conn, char *pstr, int len)
730 {
731 if (pstr == NULL || conn == NULL)
732 return -E_INVALID;
733
734 memset(pstr, 0, len);
735
736 switch (conn->L4_proto) {
737 case NL_TYPE_UDP:
738 strncpy(pstr, "UDP", len - 1);
739 break;
740 case NL_TYPE_TCP:
741 strncpy(pstr, "TCP", len - 1);
742 break;
743 default:
744 strncpy(pstr, " ", len - 1);
745 }
746
747 return E_SUCCESS;
748 }
749
750 /*
751 * copies the flags string of a given connection object into pstr
752 * E_SUCCESS is returned on success
753 * -E_INVALID is returned if parameters are not initialized
754 */
conntrack_flagstr(struct conn_object * conn,char * pstr,int len)755 int conntrack_flagstr(struct conn_object *conn, char *pstr, int len)
756 {
757 if (pstr == NULL || conn == NULL)
758 return -E_INVALID;
759
760 memset(pstr, 0, len);
761
762 /*
763 * account collection has precedence over injection/modification
764 */
765 if (conn->flags & CONN_MODIFIED)
766 strncpy(pstr, "M", len - 1);
767
768 if (conn->flags & CONN_INJECTED)
769 strncpy(pstr, "I", len - 1);
770
771 if (conn->DISSECTOR.user)
772 strncpy(pstr, "*", len - 1);
773
774 return E_SUCCESS;
775 }
776
777
778 /*
779 * copies the status string of a given connection object into pstr
780 * E_SUCCESS is returned on success
781 * -E_INVALID is returned if parameters are not initialized
782 */
conntrack_statusstr(struct conn_object * conn,char * pstr,int len)783 int conntrack_statusstr(struct conn_object *conn, char *pstr, int len)
784 {
785 if (pstr == NULL || conn == NULL)
786 return -E_INVALID;
787
788 memset(pstr, 0, len);
789
790 /* determine the status */
791 switch (conn->status) {
792 case CONN_IDLE:
793 strncpy(pstr, "idle ", len - 1);
794 break;
795 case CONN_OPENING:
796 strncpy(pstr, "opening", len - 1);
797 break;
798 case CONN_OPEN:
799 strncpy(pstr, "open ", len - 1);
800 break;
801 case CONN_ACTIVE:
802 strncpy(pstr, "active ", len - 1);
803 break;
804 case CONN_CLOSING:
805 strncpy(pstr, "closing", len - 1);
806 break;
807 case CONN_CLOSED:
808 strncpy(pstr, "closed ", len - 1);
809 break;
810 case CONN_KILLED:
811 strncpy(pstr, "killed ", len - 1);
812 break;
813 }
814
815 return E_SUCCESS;
816 }
817
818 /*
819 * copies the country codes of a given connection object into pstr
820 * E_SUCCESS is returned on success
821 * -E_INVALID is returned if parameters are not initialized
822 * -E_INITFAIL if geoip API is not initialized properly
823 */
conntrack_countrystr(struct conn_object * conn,char * pstr,int len)824 int conntrack_countrystr(struct conn_object *conn, char *pstr, int len)
825 {
826 #ifdef HAVE_GEOIP
827 const char *ccode_src, *ccode_dst = NULL;
828 #endif
829
830 if (pstr == NULL || conn == NULL || len < 8)
831 return -E_INVALID;
832
833 #ifdef HAVE_GEOIP
834 if (!EC_GBL_CONF->geoip_support_enable)
835 return -E_INITFAIL;
836
837 if ((ccode_src = geoip_ccode_by_ip(&conn->L3_addr1)) == NULL)
838 return -E_INITFAIL;
839
840 if ((ccode_dst = geoip_ccode_by_ip(&conn->L3_addr2)) == NULL)
841 return -E_INITFAIL;
842
843 snprintf(pstr, len, "%2s > %2s", ccode_src, ccode_dst);
844 #endif
845
846 return E_SUCCESS;
847 }
848
849 /* EOF */
850
851 // vim:ts=3:expandtab
852
853