From b7ee7242443f011c4188f94a750e4db3338473f7 Mon Sep 17 00:00:00 2001 From: zhuzhenjun Date: Wed, 11 Oct 2023 15:07:21 +0800 Subject: [PATCH] profile: init profile stats --- example/osfp_example.c | 77 ++++++-- pcap/synmerge.pcap | Bin 0 -> 1090008 bytes src/osfp.c | 24 ++- src/osfp_common.c | 55 +++++- src/osfp_common.h | 33 +++- src/osfp_fingerprint.c | 414 ++++++++++++++++++++--------------------- src/osfp_fingerprint.h | 34 ++-- src/osfp_score_db.c | 116 ++++++------ 8 files changed, 451 insertions(+), 302 deletions(-) create mode 100644 pcap/synmerge.pcap diff --git a/example/osfp_example.c b/example/osfp_example.c index 146587e..2a53ac6 100644 --- a/example/osfp_example.c +++ b/example/osfp_example.c @@ -3,6 +3,7 @@ #include #include #include +#include #include @@ -145,6 +146,11 @@ typedef struct Packet_ { int vlan_layer; } Packet; +typedef struct EthernetHdr_ { + uint8_t eth_dst[6]; + uint8_t eth_src[6]; + uint16_t eth_type; +} __attribute__((__packed__)) EthernetHdr; unsigned char *fp_file_path; unsigned char *fp_output_file_path; @@ -159,6 +165,12 @@ pcap_t *pcap_handle; int processed_packet; int link_type; +struct osfp_profile_counter identify_profile; + +unsigned int identify_failed_count = 0; +unsigned int identify_count = 0; +unsigned int result_os_count[OSFP_OS_CLASS_MAX]; + void usage(void) { fprintf(stderr, "Usage: osfp_match [ ...options... ] [ 'filter rule' ]\n" @@ -172,13 +184,6 @@ void usage(void) { exit(1); } -typedef struct EthernetHdr_ { - uint8_t eth_dst[6]; - uint8_t eth_src[6]; - uint16_t eth_type; -} __attribute__((__packed__)) EthernetHdr; - - int packet_decode_tcp(Packet *p, const unsigned char *data, unsigned int len) { int ret = -1; @@ -434,13 +439,16 @@ void example_detect(struct osfp_db *osfp_db, Packet *p) unsigned int tcph_len; struct osfp_result *result = NULL; - printf("Example ipv4 header detect: --------------------------\n"); - iph = (struct iphdr *)p->iph; ip6h = (struct ip6_hdr *)p->ip6h; tcph = (struct tcphdr *)p->tcph; tcph_len = tcph->doff << 2; + osfp_profile_cycle(c1); + osfp_profile_cycle(c2); + + + osfp_profile_get_cycle(c1); if (iph) { result = osfp_ipv4_identify(osfp_db, iph, tcph, tcph_len); } else if (ip6h) { @@ -448,17 +456,28 @@ void example_detect(struct osfp_db *osfp_db, Packet *p) } else { goto exit; } + osfp_profile_get_cycle(c2); + osfp_profile_counter_update(&identify_profile, c2 - c1); + + identify_count++; if (result == NULL) { + identify_failed_count++; printf("osfp header match failed, erro: %s\n", "?"); goto exit; } - printf("Connection info: %s:%d -> %s:%d\n", p->srcip, p->sp, p->dstip, p->dp); - printf("Most likely os class: %s\n", osfp_result_os_name_get(result)); + result_os_count[result->likely_os_class]++; - printf("Details:\n"); - printf("%s\n", osfp_result_score_detail_export(result)); + char *json = osfp_result_score_detail_export(result); + + if (1) { + printf("Example ipv4 header detect: --------------------------\n"); + printf("Connection info: %s:%d -> %s:%d\n", p->srcip, p->sp, p->dstip, p->dp); + printf("Most likely os class: %s\n", osfp_result_os_name_get(result)); + printf("Details:\n"); + printf("%s\n", json); + } exit: if (result) { @@ -499,7 +518,10 @@ void process_packet(char *user, struct pcap_pkthdr *h, u_char *pkt) } // tcp/ip header detect example for user - example_detect(osfp_db, p); + int i; + for (i = 0; i < 1; i++) { + example_detect(osfp_db, p); + } printf("--------------------------- processed packet count %d\n", ++processed_packet); @@ -507,10 +529,35 @@ exit: return; } +static void signal_handler(int signum) +{ + printf("profile identify: avg: %lu max: %lu min: %lu curr: %lu total: %lu count: %lu\n", + identify_profile.total_cycle / identify_profile.count, + identify_profile.max_cycle, + identify_profile.min_cycle, + identify_profile.curr_cycle, + identify_profile.total_cycle, + identify_profile.count); + + osfp_profile_print_stats(); + + printf("total %u, failed %u\n", + identify_count, identify_failed_count); + int i; + for (i = 0; i < OSFP_OS_CLASS_MAX; i++) { + printf("%s: %u\n", osfp_os_class_id_to_name(i), result_os_count[i]); + } + + exit(0); +} + int main(int argc, char *argv[]) { int r; + signal(SIGINT, signal_handler); + signal(SIGTERM, signal_handler); + while ((r = getopt(argc, argv, "+f:i:r:o:d")) != -1) { switch(r) { case 'f': @@ -621,6 +668,8 @@ int main(int argc, char *argv[]) osfp_log_level_set(OSFP_LOG_LEVEL_DEBUG); } + osfp_profile_set(1); + struct osfp_db *osfp_db = osfp_db_new(fp_file_path); if (osfp_db == NULL) { printf("could not create osfp context. fingerprints file: %s\n", fp_file_path); diff --git a/pcap/synmerge.pcap b/pcap/synmerge.pcap new file mode 100644 index 0000000000000000000000000000000000000000..a3a9984cf5e73f00d004855aaaf84d1088e7e080 GIT binary patch literal 1090008 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 TfQRr99>PO-2oGNl{;2;C>!zaR literal 0 HcmV?d00001 diff --git a/src/osfp.c b/src/osfp.c index ec9a78f..e822436 100644 --- a/src/osfp.c +++ b/src/osfp.c @@ -94,6 +94,10 @@ char *osfp_result_score_detail_export(struct osfp_result *result) cJSON *array; cJSON *os_score; + osfp_profile_cycle(c1); + osfp_profile_cycle(c2); + osfp_profile_get_cycle(c1); + if (result == NULL) { goto exit; } @@ -139,6 +143,10 @@ exit: if (root) { cJSON_Delete(root); } + if (result_str) { + osfp_profile_get_cycle(c2); + osfp_profile_counter_update(&osfp_profile_result_export, c2 - c1); + } return result_str; } @@ -159,21 +167,33 @@ struct osfp_result *osfp_ipv4_identify(struct osfp_db *db, struct iphdr* l3_hdr, struct osfp_os_class_score os_class_score; struct osfp_result *result; + osfp_profile_cycle(c1); + osfp_profile_cycle(c2); + if (db == NULL || l3_hdr == NULL || l4_hdr == NULL || l4_hdr == 0) { goto exit; } + osfp_profile_get_cycle(c1); ret = osfp_fingerprinting((unsigned char *)l3_hdr, (unsigned char *)l4_hdr, (unsigned int)l4_hdr_len, &fp, 4); + osfp_profile_get_cycle(c2); + osfp_profile_counter_update(&osfp_profile_fingerprinting, c2 - c1); if (ret != 0) { goto exit; } + osfp_profile_get_cycle(c1); ret = osfp_score_db_score(db->score_db, 0, &fp, &os_class_score); + osfp_profile_get_cycle(c2); + osfp_profile_counter_update(&osfp_profile_score, c2 - c1); if (ret != 0) { goto exit; } + osfp_profile_get_cycle(c1); result = osfp_result_build(&os_class_score); + osfp_profile_get_cycle(c2); + osfp_profile_counter_update(&osfp_profile_result_build, c2 - c1); if (result == NULL) { goto exit; } @@ -190,7 +210,7 @@ struct osfp_result *osfp_ipv6_identify(struct osfp_db *db, struct ip6_hdr* l3_hd struct osfp_os_class_score os_class_score; struct osfp_result *result; - if (db == NULL || l3_hdr == NULL || l4_hdr == NULL) { + if (db == NULL || l3_hdr == NULL || l4_hdr == NULL || l4_hdr_len == 0) { goto exit; } @@ -225,7 +245,7 @@ struct osfp_result *osfp_json_identify(struct osfp_db *db, const char *json_str) goto exit; } - ret = osfp_fingerprint_from_json(&fp, json_str); + ret = osfp_fingerprint_from_json(&fp, (char *)json_str); if (ret != 0) { goto exit; } diff --git a/src/osfp_common.c b/src/osfp_common.c index ab76c67..fa80b34 100644 --- a/src/osfp_common.c +++ b/src/osfp_common.c @@ -2,6 +2,8 @@ #include "osfp.h" +unsigned int osfp_profile_enable; + const char *os_class_name[OSFP_OS_CLASS_MAX] = { OSFP_OS_CLASS_NAME_UNKNOWN, OSFP_OS_CLASS_NAME_WINDOWS, @@ -12,6 +14,54 @@ const char *os_class_name[OSFP_OS_CLASS_MAX] = { OSFP_OS_CLASS_NAME_OTHERS }; +struct osfp_profile_counter osfp_profile_fingerprinting; +struct osfp_profile_counter osfp_profile_score; +struct osfp_profile_counter osfp_profile_result_build; +struct osfp_profile_counter osfp_profile_result_export; + +void osfp_profile_counter_print(struct osfp_profile_counter *profile, const char *name) +{ + printf("profile %s: avg: %lu max: %lu min: %lu curr: %lu total: %lu count: %lu\n", + name, + profile->total_cycle / profile->count, + profile->max_cycle, + profile->min_cycle, + profile->curr_cycle, + profile->total_cycle, + profile->count); +} +void osfp_profile_counter_update(struct osfp_profile_counter *profile, unsigned long long curr_cycle) +{ + profile->count++; + profile->curr_cycle = curr_cycle; + profile->total_cycle += curr_cycle; + + if (profile->min_cycle == 0) { + profile->min_cycle = curr_cycle; + } else { + if (profile->min_cycle > curr_cycle) { + profile->min_cycle = curr_cycle; + } + } + + if (profile->max_cycle < curr_cycle) { + profile->max_cycle = curr_cycle; + } +} + +void osfp_profile_print_stats(void) +{ + osfp_profile_counter_print(&osfp_profile_fingerprinting, "fingerprinting"); + osfp_profile_counter_print(&osfp_profile_score, "score"); + osfp_profile_counter_print(&osfp_profile_result_build, "result_build"); + osfp_profile_counter_print(&osfp_profile_result_export, "result export"); +} + +void osfp_profile_set(unsigned int enabled) +{ + osfp_profile_enable = enabled; +} + enum osfp_os_class_id osfp_os_class_name_to_id(char *name) { enum osfp_os_class_id os_class; @@ -33,8 +83,3 @@ enum osfp_os_class_id osfp_os_class_name_to_id(char *name) return os_class; } -const char *osfp_os_class_id_to_name(enum osfp_os_class_id os_class) -{ - return os_class_name[os_class]; -} - diff --git a/src/osfp_common.h b/src/osfp_common.h index 023a2ee..3b25ba1 100644 --- a/src/osfp_common.h +++ b/src/osfp_common.h @@ -39,11 +39,35 @@ static inline unsigned long long osfp_rdtsc(void) return tsc.tsc_64; } +extern unsigned int osfp_profile_enable; + #define osfp_profile_cycle(x) volatile unsigned long long x = 0 #define osfp_profile_get_cycle(x) do { \ - x = osfp_rdtsc(); \ + if (__builtin_expect(!!(osfp_profile_enable), 0)) { \ + x = osfp_rdtsc(); \ + } else { \ + x = 0; \ + } \ } while(0) +struct osfp_profile_counter { + unsigned long long count; + unsigned long long curr_cycle; + unsigned long long max_cycle; + unsigned long long min_cycle; + unsigned long long total_cycle; +}; + +extern struct osfp_profile_counter osfp_profile_fingerprinting; +extern struct osfp_profile_counter osfp_profile_score; +extern struct osfp_profile_counter osfp_profile_result_build; +extern struct osfp_profile_counter osfp_profile_result_export; + +void osfp_profile_counter_update(struct osfp_profile_counter *profile, unsigned long long curr_cycle); +void osfp_profile_print_stats(void); +void osfp_profile_set(unsigned int enabled); + + #define OSFP_BIT_U32(n) (1UL << (n)) #define OSFP_PERCENTILE 100 @@ -171,7 +195,12 @@ struct osfp_db { void *score_db; // 分数数据库指针 }; -const char *osfp_os_class_id_to_name(enum osfp_os_class_id os_class); enum osfp_os_class_id osfp_os_class_name_to_id(char *name); +extern const char *os_class_name[OSFP_OS_CLASS_MAX]; +static inline const char *osfp_os_class_id_to_name(enum osfp_os_class_id os_class) +{ + return os_class_name[os_class]; +} + #endif diff --git a/src/osfp_fingerprint.c b/src/osfp_fingerprint.c index 3c212e6..6d4cc01 100644 --- a/src/osfp_fingerprint.c +++ b/src/osfp_fingerprint.c @@ -88,6 +88,30 @@ static unsigned int compute_ip_ttl(unsigned int ip_ttl) return ip_ttl; } +static void osfp_fingerprint_setup_field(struct osfp_fingerprint *fp, enum osfp_field_id field_id, void *value, unsigned int len) +{ + fp->fields[field_id].name = osfp_fingerprint_get_field_name(field_id); + fp->fields[field_id].enabled = 1; + + if (fp->value_buffer_used + len <= sizeof(fp->value_buffer)) { + memcpy(fp->value_buffer + fp->value_buffer_used, value, len); + fp->fields[field_id].value = fp->value_buffer + fp->value_buffer_used; + fp->fields[field_id].value_len = len; + fp->value_buffer_used += len; + } else { + fp->fields[field_id].value = NULL; + fp->fields[field_id].value_len = 0; + } +} + +static void osfp_fingerprint_init_field(struct osfp_fingerprint *fp, enum osfp_field_id field_id) +{ + fp->fields[field_id].name = osfp_fingerprint_get_field_name(field_id); + fp->fields[field_id].enabled = 0; + fp->fields[field_id].value = NULL; + fp->fields[field_id].value_len = 0; +} + static unsigned int decode_tcp_options(struct osfp_tcp_opt *tcp_opts, unsigned int max_opt_cnt, unsigned char *data, unsigned int len) { unsigned int offset = 0; @@ -125,6 +149,186 @@ static unsigned int decode_tcp_options(struct osfp_tcp_opt *tcp_opts, unsigned i return tcp_opt_cnt; } +static int osfp_fingerprinting_tcp_option(unsigned char *opt_data, unsigned int opt_len, struct osfp_fingerprint *fp) +{ + int ret,i; + + unsigned int tcp_mss; + unsigned int tcp_ws; + unsigned int tcp_ter; + unsigned int tcp_opt_cnt; + struct osfp_tcp_opt tcp_opts[OSFP_TCP_OPTMAX]; + + char options[OSFP_TCP_OPTLENMAX]; + char options_ordered[OSFP_TCP_OPTLENMAX]; + unsigned int offset = 0; + unsigned int maxoffset = sizeof(options) - 3; //for shortest "E," + unsigned int ordered_offset = 0; + unsigned int ordered_maxoffset = sizeof(options_ordered) - 1; + + if (opt_data == NULL || opt_len == 0 || fp == NULL) { + goto exit; + } + + tcp_opt_cnt = decode_tcp_options(tcp_opts, OSFP_TCP_OPTMAX, opt_data, opt_len); + + for (i = 0; i < tcp_opt_cnt && offset < maxoffset && ordered_offset < ordered_maxoffset; i++) { + struct osfp_tcp_opt *opt = &tcp_opts[i]; + + char letter = option_to_ascii(opt->type); + options[offset++] = letter; + options_ordered[ordered_offset++] = letter; + + switch (opt->type) { + case OSFP_TCP_OPT_EOL: + case OSFP_TCP_OPT_NOP: + break; + case OSFP_TCP_OPT_MSS: + if (opt->len != OSFP_TCP_OPT_MSS_LEN) { + break; + } + tcp_mss = (unsigned int)ntohs(*(unsigned short *)opt->data); + osfp_fingerprint_setup_field(fp, OSFP_FIELD_TCP_MSS, &tcp_mss, sizeof(tcp_mss)); + ret = snprintf(options + offset, sizeof(options), "%u", tcp_mss); + if (ret < 0 || offset + ret > maxoffset) { + break; + } + offset += ret; + break; + case OSFP_TCP_OPT_WSCALE: + if (opt->len != OSFP_TCP_OPT_WS_LEN) { + break; + } + tcp_ws = (unsigned int)*(unsigned char *)opt->data; + osfp_fingerprint_setup_field(fp, OSFP_FIELD_TCP_WINDOW_SCALING, &tcp_ws, sizeof(tcp_ws)); + ret = snprintf(options + offset, sizeof(options), "%u", tcp_ws); + if (ret < 0 || offset + ret > maxoffset) { + break; + } + offset += ret; + break; + case OSFP_TCP_OPT_TIMESTAMP: + if (opt->len != OSFP_TCP_OPT_TS_LEN) { + break; + } + tcp_ter = ntohl(*(unsigned int *)(opt->data + 4)); + osfp_fingerprint_setup_field(fp, OSFP_FIELD_TCP_TIMESTAMP_ECHO_REPLY, &tcp_ter, sizeof(tcp_ter)); + ret = snprintf(options + offset, sizeof(options), "%u", tcp_ter); + if (ret < 0 || offset + ret > maxoffset) { + break; + } + offset += ret; + break; + case OSFP_TCP_OPT_SACKOK: + case OSFP_TCP_OPT_SACK: + case OSFP_TCP_OPT_ECHO: + case OSFP_TCP_OPT_ECHOREPLY: + case OSFP_TCP_OPT_POCONN: + case OSFP_TCP_OPT_POSVC: + break; + default: + ret = snprintf(options + offset, sizeof(options), "%u", opt->type); + if (ret < 0 || offset + ret > maxoffset) { + break; + } + offset += ret; + } + + options[offset++] = ','; + options[offset] = 0; + options_ordered[ordered_offset] = 0; + } + + osfp_fingerprint_setup_field(fp, OSFP_FIELD_TCP_OPTIONS, options, strlen(options) + 1); + osfp_fingerprint_setup_field(fp, OSFP_FIELD_TCP_OPTIONS_ORDERED, options_ordered, strlen(options_ordered) + 1); + + return 0; +exit: + return -1; +} + +static int osfp_fingerprinting_tcp(struct tcphdr *tcph, unsigned int tcph_len, struct osfp_fingerprint *fp) +{ + unsigned int tcp_off; + unsigned int tcp_window_size; + unsigned int tcp_flags; + + if (tcph == NULL || tcph_len > OSFP_TCP_DATA_OFF_MAX || fp == NULL) { + goto exit; + } + + tcp_off = tcph->doff << 2; + tcp_window_size = ntohs(tcph->window); + tcp_flags = *((unsigned char *)&tcph->ack_seq + 5); + + if (tcp_off != tcph_len) { + goto exit; + } + + osfp_fingerprint_setup_field(fp, OSFP_FIELD_TCP_OFF, &tcp_off, sizeof(tcp_off)); + osfp_fingerprint_setup_field(fp, OSFP_FIELD_TCP_WINDOW_SIZE, &tcp_window_size, sizeof(tcp_window_size)); + osfp_fingerprint_setup_field(fp, OSFP_FIELD_TCP_FLAGS, &tcp_flags, sizeof(tcp_flags)); + + osfp_fingerprint_init_field(fp, OSFP_FIELD_TCP_TIMESTAMP); + osfp_fingerprint_init_field(fp, OSFP_FIELD_TCP_TIMESTAMP_ECHO_REPLY); + osfp_fingerprint_init_field(fp, OSFP_FIELD_TCP_WINDOW_SCALING); + osfp_fingerprint_init_field(fp, OSFP_FIELD_TCP_MSS); + osfp_fingerprint_init_field(fp, OSFP_FIELD_TCP_OPTIONS); + osfp_fingerprint_init_field(fp, OSFP_FIELD_TCP_OPTIONS_ORDERED); + + // tcp options + if (tcp_off > OSFP_TCP_HEADER_LEN) { + osfp_fingerprinting_tcp_option((unsigned char *)tcph + OSFP_TCP_HEADER_LEN, tcp_off - OSFP_TCP_HEADER_LEN, fp); + } + + return 0; +exit: + return -1; +} + +static int osfp_fingerprinting_ipv4(struct iphdr *iph, struct osfp_fingerprint *fp) +{ + if (iph == NULL || fp == NULL) { + goto exit; + } + + unsigned int ip_id = !!iph->id; + unsigned int ip_tos = iph->tos; + unsigned int ip_total_length = ntohs(iph->tot_len); + unsigned int ip_ttl = compute_ip_ttl(iph->ttl); + + osfp_fingerprint_setup_field(fp, OSFP_FIELD_IP_ID, &ip_id, sizeof(ip_id)); + osfp_fingerprint_setup_field(fp, OSFP_FIELD_IP_TOS, &ip_tos, sizeof(ip_tos)); + osfp_fingerprint_setup_field(fp, OSFP_FIELD_IP_TOTAL_LENGTH, &ip_total_length, sizeof(ip_total_length)); + osfp_fingerprint_setup_field(fp, OSFP_FIELD_IP_TTL, &ip_ttl, sizeof(ip_ttl)); + + return 0; +exit: + return -1; +} + +static int osfp_fingerprinting_ipv6(struct ip6_hdr *iph, struct osfp_fingerprint *fp) +{ + if (iph == NULL || fp == NULL) { + goto exit; + } + + //unsigned int ip_id = 0; + //unsigned int ip_tos = 0; + unsigned int ip_total_length = OSFP_IPV6_HEADER_LEN + ntohs(iph->ip6_ctlun.ip6_un1.ip6_un1_plen); + unsigned int ip_ttl = compute_ip_ttl(iph->ip6_ctlun.ip6_un1.ip6_un1_hlim); + + osfp_fingerprint_setup_field(fp, OSFP_FIELD_IP_TOTAL_LENGTH, &ip_total_length, sizeof(ip_total_length)); + osfp_fingerprint_setup_field(fp, OSFP_FIELD_IP_TTL, &ip_ttl, sizeof(ip_ttl)); + + osfp_fingerprint_init_field(fp, OSFP_FIELD_IP_ID); + osfp_fingerprint_init_field(fp, OSFP_FIELD_IP_TOS); + + return 0; +exit: + return -1; +} + int osfp_fingerprint_to_json_buf(struct osfp_fingerprint *fp, char *strbuf, unsigned int buf_len, unsigned int format) { int rlen = 0, ret, i; @@ -222,214 +426,6 @@ exit: return ret; } -unsigned int osfp_fingerprint_get_field_enabled(enum osfp_field_id field_id) -{ - return fp_fields[field_id].enabled; -} - -unsigned int osfp_fingerprint_get_field_importance(enum osfp_field_id field_id) -{ - return fp_fields[field_id].importance; -} - -const char *osfp_fingerprint_get_field_name(enum osfp_field_id field_id) -{ - return fp_fields[field_id].name; -} - -unsigned int osfp_fingerprint_get_field_type(enum osfp_field_id field_id) -{ - return fp_fields[field_id].type; -} - -void osfp_fingerprint_setup_field(struct osfp_fingerprint *fp, enum osfp_field_id field_id, void *value, unsigned int len) -{ - fp->fields[field_id].name = osfp_fingerprint_get_field_name(field_id); - fp->fields[field_id].enabled = 1; - - if (fp->value_buffer_used + len <= sizeof(fp->value_buffer)) { - memcpy(fp->value_buffer + fp->value_buffer_used, value, len); - fp->fields[field_id].value = fp->value_buffer + fp->value_buffer_used; - fp->fields[field_id].value_len = len; - fp->value_buffer_used += len; - } else { - fp->fields[field_id].value = NULL; - fp->fields[field_id].value_len = 0; - } -} - -int osfp_fingerprinting_tcp_option(unsigned char *opt_data, unsigned int opt_len, struct osfp_fingerprint *fp) -{ - int ret,i; - - unsigned int tcp_mss; - unsigned int tcp_ws; - unsigned int tcp_ter; - unsigned int tcp_opt_cnt; - struct osfp_tcp_opt tcp_opts[OSFP_TCP_OPTMAX]; - - char options[OSFP_TCP_OPTLENMAX]; - char options_ordered[OSFP_TCP_OPTLENMAX]; - unsigned int offset = 0; - unsigned int maxoffset = sizeof(options) - 3; //for shortest "E," - unsigned int ordered_offset = 0; - unsigned int ordered_maxoffset = sizeof(options_ordered) - 1; - - if (opt_data == NULL || opt_len == 0 || fp == NULL) { - goto exit; - } - - tcp_opt_cnt = decode_tcp_options(tcp_opts, OSFP_TCP_OPTMAX, opt_data, opt_len); - - for (i = 0; i < tcp_opt_cnt && offset < maxoffset && ordered_offset < ordered_maxoffset; i++) { - struct osfp_tcp_opt *opt = &tcp_opts[i]; - - char letter = option_to_ascii(opt->type); - options[offset++] = letter; - options_ordered[ordered_offset++] = letter; - - switch (opt->type) { - case OSFP_TCP_OPT_EOL: - case OSFP_TCP_OPT_NOP: - break; - case OSFP_TCP_OPT_MSS: - if (opt->len != OSFP_TCP_OPT_MSS_LEN) { - break; - } - tcp_mss = (unsigned int)ntohs(*(unsigned short *)opt->data); - osfp_fingerprint_setup_field(fp, OSFP_FIELD_TCP_MSS, &tcp_mss, sizeof(tcp_mss)); - ret = snprintf(options + offset, sizeof(options), "%u", tcp_mss); - if (ret < 0 || offset + ret > maxoffset) { - break; - } - offset += ret; - break; - case OSFP_TCP_OPT_WSCALE: - if (opt->len != OSFP_TCP_OPT_WS_LEN) { - break; - } - tcp_ws = (unsigned int)*(unsigned char *)opt->data; - osfp_fingerprint_setup_field(fp, OSFP_FIELD_TCP_WINDOW_SCALING, &tcp_ws, sizeof(tcp_ws)); - ret = snprintf(options + offset, sizeof(options), "%u", tcp_ws); - if (ret < 0 || offset + ret > maxoffset) { - break; - } - offset += ret; - break; - case OSFP_TCP_OPT_TIMESTAMP: - if (opt->len != OSFP_TCP_OPT_TS_LEN) { - break; - } - tcp_ter = ntohl(*(unsigned int *)(opt->data + 4)); - osfp_fingerprint_setup_field(fp, OSFP_FIELD_TCP_TIMESTAMP_ECHO_REPLY, &tcp_ter, sizeof(tcp_ter)); - ret = snprintf(options + offset, sizeof(options), "%u", tcp_ter); - if (ret < 0 || offset + ret > maxoffset) { - break; - } - offset += ret; - break; - case OSFP_TCP_OPT_SACKOK: - case OSFP_TCP_OPT_SACK: - case OSFP_TCP_OPT_ECHO: - case OSFP_TCP_OPT_ECHOREPLY: - case OSFP_TCP_OPT_POCONN: - case OSFP_TCP_OPT_POSVC: - break; - default: - ret = snprintf(options + offset, sizeof(options), "%u", opt->type); - if (ret < 0 || offset + ret > maxoffset) { - break; - } - offset += ret; - } - - options[offset++] = ','; - options[offset] = 0; - options_ordered[ordered_offset] = 0; - } - - osfp_fingerprint_setup_field(fp, OSFP_FIELD_TCP_OPTIONS, options, strlen(options) + 1); - osfp_fingerprint_setup_field(fp, OSFP_FIELD_TCP_OPTIONS_ORDERED, options_ordered, strlen(options_ordered) + 1); - - return 0; -exit: - return -1; -} - -int osfp_fingerprinting_tcp(struct tcphdr *tcph, unsigned int tcph_len, struct osfp_fingerprint *fp) -{ - unsigned int tcp_off; - unsigned int tcp_window_size; - unsigned int tcp_flags; - - if (tcph == NULL || tcph_len > OSFP_TCP_DATA_OFF_MAX || fp == NULL) { - goto exit; - } - - tcp_off = tcph->doff << 2; - tcp_window_size = ntohs(tcph->window); - tcp_flags = *((unsigned char *)&tcph->ack_seq + 5); - - if (tcp_off != tcph_len) { - goto exit; - } - - osfp_fingerprint_setup_field(fp, OSFP_FIELD_TCP_OFF, &tcp_off, sizeof(tcp_off)); - osfp_fingerprint_setup_field(fp, OSFP_FIELD_TCP_WINDOW_SIZE, &tcp_window_size, sizeof(tcp_window_size)); - osfp_fingerprint_setup_field(fp, OSFP_FIELD_TCP_FLAGS, &tcp_flags, sizeof(tcp_flags)); - - // tcp options - if (tcp_off > OSFP_TCP_HEADER_LEN) { - osfp_fingerprinting_tcp_option((unsigned char *)tcph + OSFP_TCP_HEADER_LEN, tcp_off - OSFP_TCP_HEADER_LEN, fp); - } - - return 0; -exit: - return -1; -} - -int osfp_fingerprinting_ipv4(struct iphdr *iph, struct osfp_fingerprint *fp) -{ - if (iph == NULL || fp == NULL) { - goto exit; - } - - unsigned int ip_id = !!iph->id; - unsigned int ip_tos = iph->tos; - unsigned int ip_total_length = ntohs(iph->tot_len); - unsigned int ip_ttl = compute_ip_ttl(iph->ttl); - - osfp_fingerprint_setup_field(fp, OSFP_FIELD_IP_ID, &ip_id, sizeof(ip_id)); - osfp_fingerprint_setup_field(fp, OSFP_FIELD_IP_TOS, &ip_tos, sizeof(ip_tos)); - osfp_fingerprint_setup_field(fp, OSFP_FIELD_IP_TOTAL_LENGTH, &ip_total_length, sizeof(ip_total_length)); - osfp_fingerprint_setup_field(fp, OSFP_FIELD_IP_TTL, &ip_ttl, sizeof(ip_ttl)); - - return 0; -exit: - return -1; -} - -int osfp_fingerprinting_ipv6(struct ip6_hdr *iph, struct osfp_fingerprint *fp) -{ - if (iph == NULL || fp == NULL) { - goto exit; - } - - //unsigned int ip_id = 0; - //unsigned int ip_tos = 0; - unsigned int ip_total_length = OSFP_IPV6_HEADER_LEN + ntohs(iph->ip6_ctlun.ip6_un1.ip6_un1_plen); - unsigned int ip_ttl = compute_ip_ttl(iph->ip6_ctlun.ip6_un1.ip6_un1_hlim); - - //osfp_fingerprint_setup_field(fp, OSFP_FIELD_IP_ID, &ip_id, sizeof(ip_id)); - //osfp_fingerprint_setup_field(fp, OSFP_FIELD_IP_TOS, &ip_tos, sizeof(ip_tos)); - osfp_fingerprint_setup_field(fp, OSFP_FIELD_IP_TOTAL_LENGTH, &ip_total_length, sizeof(ip_total_length)); - osfp_fingerprint_setup_field(fp, OSFP_FIELD_IP_TTL, &ip_ttl, sizeof(ip_ttl)); - - return 0; -exit: - return -1; -} - int osfp_fingerprinting(unsigned char *iph, unsigned char *tcph, unsigned int tcph_len, struct osfp_fingerprint *fp, unsigned int ip_version) { int ret = OSFP_EINVAL; @@ -438,7 +434,7 @@ int osfp_fingerprinting(unsigned char *iph, unsigned char *tcph, unsigned int tc goto exit; } - memset(fp, 0, sizeof(struct osfp_fingerprint)); + fp->value_buffer_used = 0; switch (ip_version) { case 4: diff --git a/src/osfp_fingerprint.h b/src/osfp_fingerprint.h index 59e697d..0584329 100644 --- a/src/osfp_fingerprint.h +++ b/src/osfp_fingerprint.h @@ -43,20 +43,30 @@ struct osfp_fingerprint { unsigned int value_buffer_used; }; +extern struct osfp_fingerprint_field fp_fields[OSFP_FIELD_MAX]; + +static inline unsigned int osfp_fingerprint_get_field_enabled(enum osfp_field_id field_id) +{ + return fp_fields[field_id].enabled; +} + +static inline unsigned int osfp_fingerprint_get_field_importance(enum osfp_field_id field_id) +{ + return fp_fields[field_id].importance; +} + +static inline const char *osfp_fingerprint_get_field_name(enum osfp_field_id field_id) +{ + return fp_fields[field_id].name; +} + +static inline unsigned int osfp_fingerprint_get_field_type(enum osfp_field_id field_id) +{ + return fp_fields[field_id].type; +} + int osfp_fingerprint_from_json(struct osfp_fingerprint *fp, char *json_str); int osfp_fingerprint_to_json_buf(struct osfp_fingerprint *fp, char *strbuf, unsigned int buf_len, unsigned int format); - -void osfp_fingerprint_setup_field(struct osfp_fingerprint *fp, enum osfp_field_id field_id, void *value, unsigned int len); - -const char *osfp_fingerprint_get_field_name(enum osfp_field_id field_id); -unsigned int osfp_fingerprint_get_field_enabled(enum osfp_field_id field_id); -unsigned int osfp_fingerprint_get_field_importance(enum osfp_field_id field_id); -unsigned int osfp_fingerprint_get_field_type(enum osfp_field_id field_id); - -int osfp_fingerprinting_tcp_option(unsigned char *pkt, unsigned int pktlen, struct osfp_fingerprint *fp); -int osfp_fingerprinting_tcp(struct tcphdr *tcph, unsigned int tcph_len, struct osfp_fingerprint *fp); -int osfp_fingerprinting_ipv4(struct iphdr *iph, struct osfp_fingerprint *fp); -int osfp_fingerprinting_ipv6(struct ip6_hdr *iph, struct osfp_fingerprint *fp); int osfp_fingerprinting(unsigned char *iph, unsigned char *tcph, unsigned int tcph_len, struct osfp_fingerprint *fp, unsigned int ip_version); #ifdef UNITTEST diff --git a/src/osfp_score_db.c b/src/osfp_score_db.c index 2e38cde..76b0ba6 100644 --- a/src/osfp_score_db.c +++ b/src/osfp_score_db.c @@ -26,7 +26,7 @@ struct osfp_score_db_hash_data { struct osfp_score_db_hash_element *hash_head; }; -int osfp_score_db_array_add(void *data, struct osfp_os_class_score *os_class_score, void *value, unsigned int len) +static int osfp_score_db_array_add(void *data, struct osfp_os_class_score *os_class_score, void *value, unsigned int len) { int ret = -1, i; unsigned int index; @@ -55,7 +55,7 @@ exit: return ret; } -struct osfp_os_class_score *osfp_score_db_array_match(void *data, void *value, unsigned int len) +static struct osfp_os_class_score *osfp_score_db_array_match(void *data, void *value, unsigned int len) { unsigned int index; struct osfp_score_db_array_data *array_data = (struct osfp_score_db_array_data *)data; @@ -77,7 +77,7 @@ struct osfp_os_class_score *osfp_score_db_array_match(void *data, void *value, u return &((array_data->array_head)[index]); } -void *osfp_score_db_array_create(void) +static void *osfp_score_db_array_create(void) { struct osfp_score_db_array_data *array_data = calloc(1, sizeof(struct osfp_score_db_array_data)); if (array_data == NULL) { @@ -95,7 +95,7 @@ void *osfp_score_db_array_create(void) return (void *)array_data; } -void osfp_score_db_array_destroy(void *data) { +static void osfp_score_db_array_destroy(void *data) { struct osfp_score_db_array_data *array_data = (struct osfp_score_db_array_data *)data; if (array_data) { @@ -106,7 +106,7 @@ void osfp_score_db_array_destroy(void *data) { } } -int osfp_score_db_hash_add(void *data, struct osfp_os_class_score *os_class_score, void *value, unsigned int len) +static int osfp_score_db_hash_add(void *data, struct osfp_os_class_score *os_class_score, void *value, unsigned int len) { int ret = -1, i; struct osfp_score_db_hash_data *hash_data = (struct osfp_score_db_hash_data *)data; @@ -142,7 +142,7 @@ exit: return ret; } -struct osfp_os_class_score *osfp_score_db_hash_match(void *data, void *value, unsigned int len) +static struct osfp_os_class_score *osfp_score_db_hash_match(void *data, void *value, unsigned int len) { struct osfp_score_db_hash_data *hash_data = (struct osfp_score_db_hash_data *)data; struct osfp_score_db_hash_element *element = NULL; @@ -163,12 +163,12 @@ struct osfp_os_class_score *osfp_score_db_hash_match(void *data, void *value, un return element->score; } -void *osfp_score_db_hash_create(void) +static void *osfp_score_db_hash_create(void) { return (void*)calloc(1, sizeof(struct osfp_score_db_hash_data)); } -void osfp_score_db_hash_destroy(void *data) { +static void osfp_score_db_hash_destroy(void *data) { struct osfp_score_db_hash_data *hash_data = (struct osfp_score_db_hash_data *)data; struct osfp_score_db_hash_element *element = NULL; struct osfp_score_db_hash_element *tmp = NULL; @@ -192,55 +192,7 @@ void osfp_score_db_hash_destroy(void *data) { } } -char *osfp_score_db_read_file(char *fp_file) -{ - int ret = -1; - char *file_buffer = NULL; - unsigned int file_len = 0; - FILE *fp = NULL; - struct stat st; - - if (0 > stat(fp_file, &st)) { - osfp_log_error("stat() failed on '%s'.\n", fp_file); - goto exit; - } - - if (st.st_size == 0) { - osfp_log_error("Empty file: '%s'.\n", fp_file); - goto exit; - } - - file_len = (unsigned int)st.st_size; - file_buffer = malloc(file_len + 1); - if (file_buffer == NULL) { - osfp_log_error("Not enough memory for file buffer. file name: '%s'\n",fp_file); - goto exit; - } - - fp = fopen(fp_file, "r"); - if (fp == NULL) { - osfp_log_error("Cannot open '%s' for reading.\n", fp_file); - goto exit; - } - - ret = fread(file_buffer, 1, file_len, fp); - if (ret < 0) { - osfp_log_error("fread() failed on '%s'.\n", fp_file); - free(file_buffer); - fclose(fp); - goto exit; - } - - fclose(fp); - - file_buffer[file_len] = 0; - - return file_buffer; -exit: - return NULL; -} - -int osfp_score_db_load_field(struct osfp_field_score_db *db, cJSON *field, enum osfp_os_class_id os_class) +static int osfp_score_db_load_field(struct osfp_field_score_db *db, cJSON *field, enum osfp_os_class_id os_class) { int ret = -1; struct osfp_os_class_score os_class_score = {0}; @@ -278,7 +230,7 @@ exit: return ret; } -int osfp_score_db_load_entry(struct osfp_score_db *score_db, cJSON *entry) +static int osfp_score_db_load_entry(struct osfp_score_db *score_db, cJSON *entry) { int ret = -1, i; cJSON *field = NULL; @@ -332,6 +284,54 @@ exit: return ret; } +char *osfp_score_db_read_file(char *fp_file) +{ + int ret = -1; + char *file_buffer = NULL; + unsigned int file_len = 0; + FILE *fp = NULL; + struct stat st; + + if (0 > stat(fp_file, &st)) { + osfp_log_error("stat() failed on '%s'.\n", fp_file); + goto exit; + } + + if (st.st_size == 0) { + osfp_log_error("Empty file: '%s'.\n", fp_file); + goto exit; + } + + file_len = (unsigned int)st.st_size; + file_buffer = malloc(file_len + 1); + if (file_buffer == NULL) { + osfp_log_error("Not enough memory for file buffer. file name: '%s'\n",fp_file); + goto exit; + } + + fp = fopen(fp_file, "r"); + if (fp == NULL) { + osfp_log_error("Cannot open '%s' for reading.\n", fp_file); + goto exit; + } + + ret = fread(file_buffer, 1, file_len, fp); + if (ret < 0) { + osfp_log_error("fread() failed on '%s'.\n", fp_file); + free(file_buffer); + fclose(fp); + goto exit; + } + + fclose(fp); + + file_buffer[file_len] = 0; + + return file_buffer; +exit: + return NULL; +} + int osfp_score_db_load(struct osfp_score_db *score_db, char *fp_file) { int ret = OSFP_EINVAL, i, count;