45 #include <sys/timeb.h>
48 #include <sys/cdefs.h>
49 #include <flowmonexp/plugin_input.h>
50 #include <netinet/ip.h>
51 #include <netinet/ip6.h>
52 #include <netinet/ether.h>
60 #include <openssl/md5.h>
64 #define PRINTV(format, args...) do {if (VERBOSE) { fprintf(stdout, format, ##args); fflush(stdout); } } while (0)
67 #define PRINTD(format, args...) do {if (DEBUG) { fprintf(stdout, format, ##args); fflush(stdout); } } while (0)
70 #define PRINTA(format, args...) do {if (VERBOSE || DEBUG) { fprintf(stdout, format, ##args); fflush(stdout); } } while (0)
102 flow_record_getter_t **getter_list);
129 flow_record_t *update);
139 inline unsigned char *
getbuf(
int counter,
unsigned char *packets[40],
int min,
164 yy_size_t _yybytes_len,
209 unsigned char *benchmark_packets[40];
218 struct timespec startuptime;
228 static plugin_desc_t pcap_desc = {
230 "Plugin parse HTTP headers into flow\n"
232 " filter=y use default filter in plugin\n"
233 " filter=n don't use any filter\n"
234 " filterfile=filter.txt use filter in file\n"
235 " file must contain just one line with string representing pcap_filter\n"
236 " device=dev device to listen to\n"
237 " file=/path/file.pcap path to pcap file"
238 " benchmin=int Set range of packets for benchmarkin\n"
239 " benchmax=int Set range of packets for benchmarking\n"
240 " benchtick=int Set number of packets to pass between each line of output of benchmarking mode\n"
241 " debug=y/n Switch on/off debug mode (default: same as flowmonexp)"
242 " verbose=y/n switch on/off verbose mode (default: same as flowmonexp)",
255 inline unsigned char *
getbuf(
int counter,
unsigned char *packets[40],
int min,
258 return packets[min + (counter % (max - min + 1))];
281 char *ret = NULL, *filter = NULL;
290 file = fopen(path,
"r");
292 fprintf(stderr,
"Cannot open file \"%s\"", path);
302 fprintf(stderr,
"Cannot read file \"%s\"", path);
319 char *token, *value, *param;
323 if (params == NULL) {
324 fprintf(stderr,
"input-http-flow need parameters\n");
329 token = strtok(params,
",=");
330 while (token != NULL) {
335 PRINTA(
"param: %s\t", param);
336 PRINTA(
"value: %s\n", value);
337 if (strcmp(
"file", param) == 0) {
340 "BENCHMARK MODE forbids 'file' parameter\n Did you forgot to recompile with '--enable-benchmark' option?\n");
345 malloc((1 + strlen(value)) *
sizeof(
char));
346 strcpy(conf->
input, value);
347 }
else if (strcmp(
"device", param) == 0) {
350 "BENCHMARK MODE forbids 'device' parameter\n Did you forgot to recompile with '--enable-benchmark' option?\n");
355 malloc((1 + strlen(value)) *
sizeof(
char));
356 strcpy(conf->
input, value);
357 }
else if (strcmp(
"benchmin", param) == 0) {
360 "Supported only in benchmark mode. Did you forgot to recompile with '--enable-benchmark' option?\n");
364 }
else if (strcmp(
"benchmax", param) == 0) {
367 "Supported only in benchmark mode. Did you forgot to recompile with '--enable-benchmark' option?\n");
371 }
else if (strcmp(
"benchtick", param) == 0) {
374 "Supported only in benchmark mode. Did you forgot to recompile with '--enable-benchmark' option?\n");
378 }
else if (strcmp(
"filter", param) == 0) {
379 if (strcmp(value,
"y") == 0) {
381 }
else if (strcmp(value,
"n") == 0) {
385 " value of 'filter' parameter is not valid");
388 }
else if (strcmp(
"filterfile", param) == 0) {
393 PRINTV(
"Read from filter file : %s",
397 }
else if (strcmp(
"verbose", param) == 0) {
398 if (strcmp(value,
"y") == 0) {
400 }
else if (strcmp(value,
"n") == 0) {
404 " value of 'verbose' parameter is not valid");
406 }
else if (strcmp(
"debug", param) == 0) {
407 if (strcmp(value,
"y") == 0) {
409 }
else if (strcmp(value,
"n") == 0) {
413 " value of 'debug' parameter is not valid");
416 fprintf(stderr,
"Unknown parameter '%s'\n",
423 token = strtok(NULL,
",=");
432 char *position = (
char *)buf;
434 lex_strstr(position, buflen *
sizeof(
char), http);
442 int value_length_uint64(
void *
self, flow_record_t *r)
444 return sizeof(uint64_t);
451 int value_length_uint8(
void *
self, flow_record_t *r)
453 return sizeof(uint8_t);
460 int value_length_uint16(
void *
self, flow_record_t *r)
462 return sizeof(uint16_t);
469 int value_length_domain(
void *
self, flow_record_t *r)
478 int value_length_referer(
void *
self, flow_record_t *r)
487 int value_length_url(
void *
self, flow_record_t *r)
497 int validity_OK(
void *
self, flow_record_t *r)
506 int validity_by_valid(
void *
self, flow_record_t *r)
522 void value_fill_useragent(
void *
self, flow_record_t *record,
void *dst,
523 int len,
int to_network_byte_order)
527 record_universal_get(dst, &(pr->
useragent), 0,
sizeof(uint8_t), len,
528 to_network_byte_order);
540 void value_fill_domain(
void *
self, flow_record_t *record,
void *dst,
int len,
541 int to_network_byte_order)
545 record_universal_get(dst, &(pr->
domain), 0,
547 to_network_byte_order);
550 inline int min(
int x,
int y)
567 void value_fill_url(
void *
self, flow_record_t *record,
void *dst,
int len,
568 int to_network_byte_order)
572 record_universal_get(dst, &(pr->
url), 0,
URL_LENGTH *
sizeof(
char), len,
573 to_network_byte_order);
585 void value_fill_referer(
void *
self, flow_record_t *record,
void *dst,
int len,
586 int to_network_byte_order)
590 record_universal_get(dst, &(pr->
referer), 0,
592 to_network_byte_order);
604 void value_fill_method(
void *
self, flow_record_t *record,
void *dst,
int len,
605 int to_network_byte_order)
609 record_universal_get(dst, &(pr->
method), 0,
sizeof(uint8_t), len,
610 to_network_byte_order);
622 void value_fill_status(
void *
self, flow_record_t *record,
void *dst,
int len,
623 int to_network_byte_order)
627 record_universal_get(dst, &(pr->
status), 0,
sizeof(uint16_t), len,
628 to_network_byte_order);
640 void value_fill_header_count(
void *
self, flow_record_t *record,
void *dst,
int len,
641 int to_network_byte_order)
645 record_universal_get(dst, &(pr->
header_count), 0,
sizeof(uint16_t), len,
646 to_network_byte_order);
658 void value_fill_content_type(
void *
self, flow_record_t *record,
void *dst,
659 int len,
int to_network_byte_order)
663 record_universal_get(dst, &(pr->
content_type), 0,
sizeof(uint8_t), len,
664 to_network_byte_order);
674 flow_record_getter_t **getter_list)
676 PRINTD(
"Getter init started\n");
678 getter_add(getter_list,
"HTTP_USERAGENT",
sizeof(uint8_t),
679 plugin_private, &validity_by_valid, &value_length_uint8,
680 &value_fill_useragent);
681 getter_add(getter_list,
"HTTP_METHOD",
sizeof(uint8_t), plugin_private,
682 &validity_by_valid, &value_length_uint8, &value_fill_method);
683 getter_add(getter_list,
"HTTP_DOMAIN",
DOMAIN_LENGTH *
sizeof(
char),
684 plugin_private, &validity_by_valid, &value_length_domain,
686 getter_add(getter_list,
"HTTP_REFERER",
REFERER_LENGTH *
sizeof(
char),
687 plugin_private, &validity_by_valid, &value_length_referer,
688 &value_fill_referer);
689 getter_add(getter_list,
"HTTP_CONTENT_TYPE",
sizeof(uint8_t),
690 plugin_private, &validity_by_valid, &value_length_uint8,
691 &value_fill_content_type);
692 getter_add(getter_list,
"HTTP_URL",
URL_LENGTH *
sizeof(
char),
693 plugin_private, &validity_by_valid, &value_length_url,
695 getter_add(getter_list,
"HTTP_STATUS",
sizeof(uint16_t),
696 plugin_private, &validity_by_valid, &value_length_uint16,
698 getter_add(getter_list,
"HTTP_HEADER_COUNT",
sizeof(uint16_t),
699 plugin_private, &validity_by_valid, &value_length_uint8,
700 &value_fill_header_count);
702 PRINTD(
"Getter init finished\n");
715 if (retval == NULL) {
720 char errbuf[PCAP_ERRBUF_SIZE];
721 struct bpf_program fp;
729 for (
int x = 0; x < 40; x++) {
731 malloc(
PCAP_SIZE *
sizeof(
unsigned char));
734 sizeof(pkt1) /
sizeof(
unsigned char));
736 sizeof(pkt2) /
sizeof(
unsigned char));
738 sizeof(pkt3) /
sizeof(
unsigned char));
740 sizeof(pkt4) /
sizeof(
unsigned char));
742 sizeof(pkt5) /
sizeof(
unsigned char));
744 sizeof(pkt6) /
sizeof(
unsigned char));
746 sizeof(pkt7) /
sizeof(
unsigned char));
748 sizeof(pkt8) /
sizeof(
unsigned char));
750 sizeof(pkt9) /
sizeof(
unsigned char));
752 sizeof(pkt10) /
sizeof(
unsigned char));
754 sizeof(pkt11) /
sizeof(
unsigned char));
756 sizeof(pkt12) /
sizeof(
unsigned char));
758 sizeof(pkt13) /
sizeof(
unsigned char));
760 sizeof(pkt14) /
sizeof(
unsigned char));
762 sizeof(pkt15) /
sizeof(
unsigned char));
764 sizeof(pkt16) /
sizeof(
unsigned char));
766 sizeof(pkt17) /
sizeof(
unsigned char));
768 sizeof(pkt18) /
sizeof(
unsigned char));
770 sizeof(pkt19) /
sizeof(
unsigned char));
772 sizeof(pkt20) /
sizeof(
unsigned char));
774 sizeof(pkt21) /
sizeof(
unsigned char));
776 sizeof(pkt22) /
sizeof(
unsigned char));
778 sizeof(pkt23) /
sizeof(
unsigned char));
780 sizeof(pkt24) /
sizeof(
unsigned char));
782 sizeof(pkt25) /
sizeof(
unsigned char));
784 sizeof(pkt26) /
sizeof(
unsigned char));
786 sizeof(pkt27) /
sizeof(
unsigned char));
788 sizeof(pkt28) /
sizeof(
unsigned char));
790 sizeof(pkt29) /
sizeof(
unsigned char));
792 sizeof(pkt30) /
sizeof(
unsigned char));
794 sizeof(pkt31) /
sizeof(
unsigned char));
796 sizeof(pkt32) /
sizeof(
unsigned char));
798 sizeof(pkt33) /
sizeof(
unsigned char));
800 sizeof(pkt34) /
sizeof(
unsigned char));
802 sizeof(pkt35) /
sizeof(
unsigned char));
804 sizeof(pkt36) /
sizeof(
unsigned char));
806 sizeof(pkt37) /
sizeof(
unsigned char));
808 sizeof(pkt38) /
sizeof(
unsigned char));
810 sizeof(pkt39) /
sizeof(
unsigned char));
812 sizeof(pkt40) /
sizeof(
unsigned char));
819 PRINTV(
"HTTP input plugin init with args: %s\n", params);
821 retval->
data = data_offset;
832 if (parse_params(params, retval) != 0) {
839 PRINTA(
"http plugin opens file %s\n", retval->
input);
840 retval->
pcap = pcap_open_offline(retval->
input, errbuf);
842 PRINTA(
"http plugin opens live device %s\n", retval->
input);
848 if (retval->
pcap == NULL) {
849 fprintf(stderr,
"Unable to init pcap: %s\n", errbuf);
856 if (retval->
filter == 1) {
859 PRINTV(
"Setting up default filter\n");
869 fprintf(stderr,
"Couldn't parse filter %s: %s\n",
877 if (pcap_setfilter(retval->
pcap, &fp) == -1) {
878 fprintf(stderr,
"Couldn't install filter %s: %s\n",
880 pcap_geterr(retval->
pcap));
887 int datalink = pcap_datalink(retval->
pcap);
888 if (datalink != DLT_EN10MB) {
907 uint64_t plugin_input_get_flow(
void *plugin_private, flow_record_t *record)
911 struct pcap_pkthdr hdr;
919 struct timespec tmp1;
927 buf = (
unsigned char *)pcap_next(dev->
pcap, &hdr);
934 clock_gettime(CLOCK_REALTIME, &(dev->
startuptime));
939 clock_gettime(CLOCK_REALTIME, &tmp1);
941 printf(
"packets %ld | ", dev->
counter);
942 sec = (tmp1.tv_sec - (dev->
startuptime).tv_sec) + 1;
945 (tmp1.tv_nsec - dev->
startuptime.tv_nsec) / 1000000;
946 printf(
"time: %.3f | ", ((
double)msec) / 1000);
947 printf(
"%.2f packets/s\n",
948 ((
double)dev->
counter / ((
double)msec / 1000)));
958 if (buf == NULL && dev->
offline == 1) {
959 PRINTA(
"reached end of file\n");
973 record->flow_end = record->flow_start =
974 ((uint64_t) hdr.ts.tv_sec * 1000 * 1000 * 1000) +
975 ((uint64_t) hdr.ts.tv_usec * 1000);
979 hash = record_process_packet(buf, caplen, record);
986 if (record->l4.protocol != 6) {
987 return hash | FLOW_OK_BIT;
992 if (get_packet_data(&caplen2, &offset) == NULL) {
994 return hash | FLOW_OK_BIT;
998 if (caplen - 8 > offset) {
1001 return hash | FLOW_OK_BIT;
1011 memcpy(dev->
buffer, buf, caplen - offset);
1019 return hash | FLOW_OK_BIT;
1026 void plugin_process_getter_init(
void *plugin_private,
1027 flow_record_getter_t **getter_list)
1036 void plugin_process_create(
void *plugin_private, flow_record_t *record)
1045 void plugin_process_release(
void *plugin_private, flow_record_t *record,
1059 flow_record_t *update)
1061 http_record_t *original = PLUGIN_DATA(record, GLOBAL_FLOW_OFFSET);
1062 http_record_t *up = PLUGIN_DATA(update, GLOBAL_FLOW_OFFSET);
1065 if (up->
valid == 1) {
1067 if (original->
valid != 1) {
1080 static plugin_desc_t plugin_proc_desc = {
1082 "Controls if record is properly filled, if not, refills it from next packets in the flow",
1093 return &plugin_proc_desc;