From 13721781f73b4efc2a8a5115c297581c1310d1bb Mon Sep 17 00:00:00 2001 From: zhuzhenjun Date: Thu, 26 Oct 2023 13:48:41 +0800 Subject: [PATCH] code: clean up --- CMakeLists.txt | 3 + example/osfp_example.c | 2 +- example/sample.c | 3 +- src/osfp.c | 171 ++------------------- src/osfp.h | 21 +-- src/osfp_common.c | 70 +++++++++ src/osfp_common.h | 26 +--- src/osfp_fingerprint.c | 11 +- src/osfp_fingerprint.h | 2 +- src/osfp_log.c | 5 + src/osfp_score_db.c | 16 +- src/osfp_score_db.h | 10 +- src/version.map | 10 +- test/test.c | 37 ++++- {src => third_party/cJSON}/cJSON.c | 0 {src => third_party/cJSON}/cJSON.h | 0 {src => third_party/uthash}/utarray.h | 0 {src => third_party/uthash}/uthash.h | 0 {src => third_party/uthash}/utlist.h | 0 {src => third_party/uthash}/utringbuffer.h | 0 {src => third_party/uthash}/utstack.h | 0 {src => third_party/uthash}/utstring.h | 0 22 files changed, 184 insertions(+), 203 deletions(-) rename {src => third_party/cJSON}/cJSON.c (100%) rename {src => third_party/cJSON}/cJSON.h (100%) rename {src => third_party/uthash}/utarray.h (100%) rename {src => third_party/uthash}/uthash.h (100%) rename {src => third_party/uthash}/utlist.h (100%) rename {src => third_party/uthash}/utringbuffer.h (100%) rename {src => third_party/uthash}/utstack.h (100%) rename {src => third_party/uthash}/utstring.h (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index e36fc36..97ad632 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,8 +31,11 @@ elseif(ENABLE_SANITIZE_THREAD) endif() # end of for ASAN +include_directories(${PROJECT_SOURCE_DIR}/third_party/cJSON/) +include_directories(${PROJECT_SOURCE_DIR}/third_party/uthash/) include_directories(${PROJECT_SOURCE_DIR}/src/) +aux_source_directory(${PROJECT_SOURCE_DIR}/third_party/cJSON/ SRCLIST) aux_source_directory(${PROJECT_SOURCE_DIR}/src SRCLIST) # Shared Library Output diff --git a/example/osfp_example.c b/example/osfp_example.c index 9d94015..28194b7 100644 --- a/example/osfp_example.c +++ b/example/osfp_example.c @@ -534,7 +534,7 @@ void process_packet(char *user, struct pcap_pkthdr *h, u_char *pkt) // tcp/ip header detect example for user int i; - for (i = 0; i < 1; i++) { + for (i = 0; i < 1000; i++) { example_detect(osfp_db, p); } diff --git a/example/sample.c b/example/sample.c index 4c926a9..f586759 100644 --- a/example/sample.c +++ b/example/sample.c @@ -1,4 +1,5 @@ -#include "stdio.h" +#include +#include #include "osfp.h" char iph[] = { diff --git a/src/osfp.c b/src/osfp.c index 1a23342..c43041f 100644 --- a/src/osfp.c +++ b/src/osfp.c @@ -1,3 +1,7 @@ +#include + +#include "cJSON.h" + #include "osfp_common.h" #include "osfp.h" @@ -5,67 +9,6 @@ #include "osfp_score_db.h" #include "osfp_log.h" -#define OSFP_LOWEST_SCORE_LIMIT 20 - -static struct osfp_result *osfp_result_build(struct osfp_os_class_score *os_class_score, const char *matched) -{ - int i; - unsigned int tmp_score; - unsigned int likely_score; - enum osfp_os_class_id likely_os_class; - struct osfp_result *result; - - result = calloc(1, sizeof(struct osfp_result)); - if (result == NULL) { - goto exit; - } - - likely_score = 0; - likely_os_class = OSFP_OS_CLASS_OTHERS; - - // likely os score - for (i = 0; i < OSFP_OS_CLASS_MAX; i++) { - tmp_score = os_class_score->scores[i]; - - if (likely_score < tmp_score) { - likely_score = tmp_score; - likely_os_class = i; - } - result->details[i].score = tmp_score; - } - - if (likely_score == OSFP_PERCENTILE) { - // prefiltered - ; - } else if (likely_score < OSFP_LOWEST_SCORE_LIMIT) { - // too low to tell os class - likely_os_class = OSFP_OS_CLASS_OTHERS; - } else { - // when the tied likely scores appear between win/apple-like/unix-like, we throw unknown - for (i = 0; i < OSFP_OS_CLASS_MAX; i++) { - if (likely_os_class == i) { - continue; - } - if (likely_score == os_class_score->scores[i]) { - if (likely_os_class == OSFP_OS_CLASS_LINUX && i == OSFP_OS_CLASS_ANDROID) { - continue; - } else if (likely_os_class == OSFP_OS_CLASS_MAC_OS && i == OSFP_OS_CLASS_IOS) { - continue; - } else { - likely_os_class = OSFP_OS_CLASS_UNKNOWN; - break; - } - } - } - } - - result->likely_os_class = likely_os_class; - result->matched = matched; - return result; -exit: - return NULL; -} - const char *osfp_result_os_name_get(struct osfp_result *result) { enum osfp_os_class_id os_class; @@ -157,7 +100,7 @@ void osfp_result_free(struct osfp_result *result) } } -struct osfp_result *osfp_ipv4_identify(struct osfp_db *db, struct iphdr* l3_hdr, struct tcphdr *l4_hdr, size_t l4_hdr_len) +struct osfp_result *osfp_ip_identify(struct osfp_db *db, unsigned char *l3_hdr, unsigned char *l4_hdr, unsigned int l4_hdr_len, unsigned int ip_version) { int ret; struct osfp_fingerprint fp; @@ -165,39 +108,24 @@ struct osfp_result *osfp_ipv4_identify(struct osfp_db *db, struct iphdr* l3_hdr, struct osfp_result *result; const char *matched; - osfp_profile_cycle(c1); - osfp_profile_cycle(c2); - if (db == NULL || l3_hdr == NULL || l4_hdr == NULL || l4_hdr_len == 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); + ret = osfp_fingerprinting(l3_hdr, l4_hdr, l4_hdr_len, &fp, ip_version); if (ret != 0) { goto exit; } - osfp_profile_get_cycle(c1); matched = osfp_score_db_prefilter(db->score_db, &fp, &os_class_score); - osfp_profile_get_cycle(c2); - osfp_profile_counter_update(&osfp_profile_prefilter, c2 - c1); if (matched == NULL) { - 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, matched); - osfp_profile_get_cycle(c2); - osfp_profile_counter_update(&osfp_profile_result_build, c2 - c1); if (result == NULL) { goto exit; } @@ -207,89 +135,14 @@ exit: return NULL; } +struct osfp_result *osfp_ipv4_identify(struct osfp_db *db, struct iphdr* l3_hdr, struct tcphdr *l4_hdr, size_t l4_hdr_len) +{ + return osfp_ip_identify(db, (unsigned char *)l3_hdr, (unsigned char *)l4_hdr, (unsigned int)l4_hdr_len, 4); +} + struct osfp_result *osfp_ipv6_identify(struct osfp_db *db, struct ip6_hdr* l3_hdr, struct tcphdr *l4_hdr, size_t l4_hdr_len) { - int ret; - struct osfp_fingerprint fp; - struct osfp_os_class_score os_class_score; - struct osfp_result *result; - const char *matched; - - osfp_profile_cycle(c1); - osfp_profile_cycle(c2); - - if (db == NULL || l3_hdr == NULL || l4_hdr == NULL || l4_hdr_len == 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, 6); - osfp_profile_get_cycle(c2); - osfp_profile_counter_update(&osfp_profile_fingerprinting, c2 - c1); - if (ret != 0) { - goto exit; - } - - osfp_profile_get_cycle(c1); - matched = osfp_score_db_prefilter(db->score_db, &fp, &os_class_score); - osfp_profile_get_cycle(c2); - osfp_profile_counter_update(&osfp_profile_prefilter, c2 - c1); - if (matched == NULL) { - 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, matched); - osfp_profile_get_cycle(c2); - osfp_profile_counter_update(&osfp_profile_result_build, c2 - c1); - if (result == NULL) { - goto exit; - } - - return result; -exit: - return NULL; -} - -struct osfp_result *osfp_json_identify(struct osfp_db *db, const char *json_str) -{ - int ret = OSFP_EINVAL; - struct osfp_fingerprint fp; - struct osfp_os_class_score os_class_score; - struct osfp_result *result; - const char *matched; - - if (db == NULL || json_str == NULL) { - goto exit; - } - - ret = osfp_fingerprint_from_json(&fp, (char *)json_str); - if (ret != 0) { - goto exit; - } - - matched = osfp_score_db_prefilter(db->score_db, &fp, &os_class_score); - if (matched == NULL) { - ret = osfp_score_db_score(db->score_db, 0, &fp, &os_class_score); - if (ret != 0) { - goto exit; - } - } - - result = osfp_result_build(&os_class_score, matched); - if (result == NULL) { - goto exit; - } - - return result; -exit: - return NULL; + return osfp_ip_identify(db, (unsigned char *)l3_hdr, (unsigned char *)l4_hdr, (unsigned int)l4_hdr_len, 6); } struct osfp_db *osfp_db_new(const char *fp_path) diff --git a/src/osfp.h b/src/osfp.h index bf01738..225f27c 100644 --- a/src/osfp.h +++ b/src/osfp.h @@ -32,6 +32,18 @@ struct osfp_db *osfp_db_new(const char *db_json_path); */ void osfp_db_free(struct osfp_db *db); +/** + * @brief 通过 IP 头部和 TCP 头部识别操作系统。 + * + * @param db 操作系统指纹库。 + * @param l3_hdr 指向 IP 头部的指针。 + * @param l4_hdr 指向 TCP 头部的指针。 + * @param l4_hdr_len TCP 头部的长度(注意:包含TCP选项部分)。 + * @param ip_version IP头版本号,4 或 6)。 + * @return 指向操作系统识别结果的指针。 + */ +struct osfp_result *osfp_ip_identify(struct osfp_db *db, unsigned char *l3_hdr, unsigned char *l4_hdr, unsigned int l4_hdr_len, unsigned int ip_version); + /** * @brief 通过 IPv4 头部和 TCP 头部识别操作系统。 * @@ -54,15 +66,6 @@ struct osfp_result *osfp_ipv4_identify(struct osfp_db *db, struct iphdr* l3_hdr, */ struct osfp_result *osfp_ipv6_identify(struct osfp_db *db, struct ip6_hdr* l3_hdr, struct tcphdr *l4_hdr, size_t l4_hdr_len); -/** - * @brief 通过 json 格式的指纹识别操作系统。 - * - * @param db 操作系统指纹库。 - * @param json_str 指纹字符串。 - * @return 指向操作系统识别结果的指针(注意:内存需要使用者释放)。 - */ -struct osfp_result *osfp_json_identify(struct osfp_db *db, const char *json_str); - /** * @brief 获取操作系统识别结果的操作系统名称。 * diff --git a/src/osfp_common.c b/src/osfp_common.c index 315fd88..6f6f596 100644 --- a/src/osfp_common.c +++ b/src/osfp_common.c @@ -1,3 +1,9 @@ +#include +#include +#include + +#include + #include "osfp_common.h" #include "osfp.h" @@ -41,6 +47,70 @@ enum osfp_os_class_id osfp_os_class_name_to_id(char *name) return OSFP_OS_CLASS_MAX; } +struct osfp_result *osfp_result_build(struct osfp_os_class_score *os_class_score, const char *matched) +{ + int i; + unsigned int tmp_score; + unsigned int likely_score; + enum osfp_os_class_id likely_os_class; + struct osfp_result *result; + + result = calloc(1, sizeof(struct osfp_result)); + if (result == NULL) { + goto exit; + } + + likely_score = 0; + likely_os_class = OSFP_OS_CLASS_OTHERS; + + // likely os score + for (i = 0; i < OSFP_OS_CLASS_MAX; i++) { + tmp_score = os_class_score->scores[i]; + + if (likely_score < tmp_score) { + likely_score = tmp_score; + likely_os_class = i; + } + result->details[i].score = tmp_score; + } + + // prefiltered + if (likely_score == OSFP_PERCENTILE) { + goto end; + } + + // too low to tell os class + if (likely_score < OSFP_LOWEST_SCORE_LIMIT) { + likely_os_class = OSFP_OS_CLASS_OTHERS; + goto end; + } + + // when the tied likely scores appear between win/apple-like/unix-like, we throw unknown + for (i = 0; i < OSFP_OS_CLASS_MAX; i++) { + if (likely_os_class == i) { + continue; + } + if (likely_score != os_class_score->scores[i]) { + continue; + } + if (likely_os_class == OSFP_OS_CLASS_LINUX && i == OSFP_OS_CLASS_ANDROID) { + continue; + } + if (likely_os_class == OSFP_OS_CLASS_MAC_OS && i == OSFP_OS_CLASS_IOS) { + continue; + } + likely_os_class = OSFP_OS_CLASS_UNKNOWN; + break; + } + +end: + result->likely_os_class = likely_os_class; + result->matched = matched; + return result; +exit: + return NULL; +} + 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", diff --git a/src/osfp_common.h b/src/osfp_common.h index 89da3da..6b2c367 100644 --- a/src/osfp_common.h +++ b/src/osfp_common.h @@ -1,27 +1,6 @@ #ifndef __OSFP_COMMON_H__ #define __OSFP_COMMON_H__ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "utarray.h" -#include "uthash.h" -#include "utlist.h" -#include "utringbuffer.h" -#include "utstack.h" -#include "utstring.h" - -#include "cJSON.h" - static inline unsigned long long osfp_rdtsc(void) { union { @@ -157,6 +136,7 @@ enum osfp_os_class_id { #define OSFP_OS_CLASS_FLAG_IOS OSFP_BIT_U32(OSFP_OS_CLASS_IOS) #define OSFP_OS_CLASS_FLAG_ANDROID OSFP_BIT_U32(OSFP_OS_CLASS_ANDROID) +#define OSFP_LOWEST_SCORE_LIMIT 20 enum osfp_error_code { OSFP_NOERR, @@ -169,6 +149,9 @@ enum osfp_error_code { OSFP_ERR_FINGERPRINTING_UNSUPPORTED, }; +struct osfp_os_class_score { + unsigned int scores[OSFP_OS_CLASS_MAX]; +}; /** * @brief 结构体用于 osfp_result 中的详细结果。 @@ -197,6 +180,7 @@ struct osfp_db { enum osfp_os_class_id osfp_os_class_name_to_id(char *name); const char *osfp_os_class_id_to_name(enum osfp_os_class_id os_class); +struct osfp_result *osfp_result_build(struct osfp_os_class_score *os_class_score, const char *matched); char *osfp_read_file(char *fp_file); #endif diff --git a/src/osfp_fingerprint.c b/src/osfp_fingerprint.c index 9652657..b7d985d 100644 --- a/src/osfp_fingerprint.c +++ b/src/osfp_fingerprint.c @@ -1,3 +1,9 @@ +#include +#include +#include + +#include "cJSON.h" + #include "osfp_common.h" #include "osfp.h" @@ -221,14 +227,17 @@ int osfp_fingerprint_to_json_buf(struct osfp_fingerprint *fp, char *strbuf, unsi return strlen(strbuf) + 1; } -struct osfp_fingerprint *osfp_fingerprint_from_cjson(cJSON *root) +struct osfp_fingerprint *osfp_fingerprint_from_cjson(void *cjson_obj) { int i; + cJSON *root; cJSON *field; void *value_ptr; unsigned int value_len; struct osfp_fingerprint *fp; + root = (cJSON *)cjson_obj; + if (root == NULL) { goto exit; } diff --git a/src/osfp_fingerprint.h b/src/osfp_fingerprint.h index 7a4fc88..3480a88 100644 --- a/src/osfp_fingerprint.h +++ b/src/osfp_fingerprint.h @@ -65,7 +65,7 @@ static inline unsigned int osfp_fingerprint_get_field_type(enum osfp_field_id fi return fp_fields[field_id].type; } -struct osfp_fingerprint *osfp_fingerprint_from_cjson(cJSON *root); +struct osfp_fingerprint *osfp_fingerprint_from_cjson(void *root); 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); diff --git a/src/osfp_log.c b/src/osfp_log.c index 66f28d2..4c7dc5b 100644 --- a/src/osfp_log.c +++ b/src/osfp_log.c @@ -1,3 +1,8 @@ +#include +#include +#include +#include + #include "osfp_common.h" #include "osfp_log.h" diff --git a/src/osfp_score_db.c b/src/osfp_score_db.c index 00a15a3..3e3f97c 100644 --- a/src/osfp_score_db.c +++ b/src/osfp_score_db.c @@ -1,3 +1,8 @@ +#include +#include + +#include "cJSON.h" + #include "osfp_common.h" #include "osfp.h" @@ -301,7 +306,7 @@ int osfp_score_db_score(struct osfp_score_db *score_db, unsigned int flags, stru continue; } - coefficient = OSFP_PERCENTILE / PERFECT_SCORE_EXPECTED_RATE * score_db->field_weight[i] / total_weight; + coefficient = fdb->coefficient; for (j = 0; j < OSFP_OS_CLASS_MAX; j++) { os_entry_count = score_db->os_entry_count[j]; @@ -510,10 +515,10 @@ struct osfp_score_db *osfp_score_db_create(void) continue; } - score_db->field_weight[i] = osfp_fingerprint_get_field_importance(i); + db->weight = osfp_fingerprint_get_field_importance(i); // tcp options ordered and tcp options overlap if (i != OSFP_FIELD_TCP_OPTIONS_ORDERED) { - score_db->total_weight += score_db->field_weight[i]; + score_db->total_weight += db->weight; } db->type = osfp_fingerprint_get_field_type(i); @@ -542,6 +547,11 @@ struct osfp_score_db *osfp_score_db_create(void) } } + for (i = 0; i < OSFP_FIELD_MAX; i++) { + db = &score_db->field_score_dbs[i]; + db->coefficient = (OSFP_PERCENTILE / PERFECT_SCORE_EXPECTED_RATE) * ((float)db->weight / (float)score_db->total_weight); + } + return score_db; exit: if (score_db) { diff --git a/src/osfp_score_db.h b/src/osfp_score_db.h index 8f6ef0b..1b6efd7 100644 --- a/src/osfp_score_db.h +++ b/src/osfp_score_db.h @@ -1,14 +1,12 @@ #ifndef __OSFP_SCORE_DB_H__ #define __OSFP_SCORE_DB_H__ +#include "uthash.h" + #include "osfp.h" #include "osfp_fingerprint.h" #include "osfp_common.h" -struct osfp_os_class_score { - unsigned int scores[OSFP_OS_CLASS_MAX]; -}; - struct osfp_field_value_count { unsigned int counts[OSFP_OS_CLASS_MAX]; }; @@ -18,6 +16,9 @@ struct osfp_field_score_db { unsigned int type; unsigned int entry_count; + unsigned int weight; + float coefficient; + void *data; void *(*create)(void); @@ -43,7 +44,6 @@ struct osfp_score_db { unsigned int os_entry_count[OSFP_OS_CLASS_MAX]; unsigned int total_weight; - unsigned int field_weight[OSFP_FIELD_MAX]; struct osfp_field_score_db field_score_dbs[OSFP_FIELD_MAX]; }; diff --git a/src/version.map b/src/version.map index 317c75d..54dd0a0 100644 --- a/src/version.map +++ b/src/version.map @@ -1,4 +1,12 @@ { - global: osfp*;GIT_VERSION_*; + global: + osfp_db_new; + osfp_db_free; + osfp_ip_identify; + osfp_ipv4_identify; + osfp_ipv6_identify; + osfp_result_os_name_get; + osfp_result_score_detail_export; + osfp_result_free; local: *; }; diff --git a/test/test.c b/test/test.c index c988439..944e1e5 100644 --- a/test/test.c +++ b/test/test.c @@ -3,6 +3,7 @@ #include #include #include +#include #include "cJSON.h" @@ -126,6 +127,40 @@ static void print_confusion_matrix(unsigned int *result, unsigned int os_class_m printf("miss rate: %u%%\n", 100 * missed / (matched + missed)); } +struct osfp_result *test_osfp_json_identify(struct osfp_db *db, const char *json_str) +{ + int ret = OSFP_EINVAL; + struct osfp_fingerprint fp; + struct osfp_os_class_score os_class_score; + struct osfp_result *result; + const char *matched; + + if (db == NULL || json_str == NULL) { + goto exit; + } + + ret = osfp_fingerprint_from_json(&fp, (char *)json_str); + if (ret != 0) { + goto exit; + } + + matched = osfp_score_db_prefilter(db->score_db, &fp, &os_class_score); + if (matched == NULL) { + ret = osfp_score_db_score(db->score_db, 0, &fp, &os_class_score); + if (ret != 0) { + goto exit; + } + } + + result = osfp_result_build(&os_class_score, matched); + if (result == NULL) { + goto exit; + } + + return result; +exit: + return NULL; +} void test_data_prepare() { @@ -229,7 +264,7 @@ void test_miss_rate() osfp_fingerprint_to_json_buf(&fp, str_buf, 2048, 0); fprintf(log_file_ptr, "%s\n", str_buf); - struct osfp_result *result = osfp_json_identify(osfp_db, fp_str); + struct osfp_result *result = test_osfp_json_identify(osfp_db, fp_str); if (result == NULL) { identify_failed_count++; continue; diff --git a/src/cJSON.c b/third_party/cJSON/cJSON.c similarity index 100% rename from src/cJSON.c rename to third_party/cJSON/cJSON.c diff --git a/src/cJSON.h b/third_party/cJSON/cJSON.h similarity index 100% rename from src/cJSON.h rename to third_party/cJSON/cJSON.h diff --git a/src/utarray.h b/third_party/uthash/utarray.h similarity index 100% rename from src/utarray.h rename to third_party/uthash/utarray.h diff --git a/src/uthash.h b/third_party/uthash/uthash.h similarity index 100% rename from src/uthash.h rename to third_party/uthash/uthash.h diff --git a/src/utlist.h b/third_party/uthash/utlist.h similarity index 100% rename from src/utlist.h rename to third_party/uthash/utlist.h diff --git a/src/utringbuffer.h b/third_party/uthash/utringbuffer.h similarity index 100% rename from src/utringbuffer.h rename to third_party/uthash/utringbuffer.h diff --git a/src/utstack.h b/third_party/uthash/utstack.h similarity index 100% rename from src/utstack.h rename to third_party/uthash/utstack.h diff --git a/src/utstring.h b/third_party/uthash/utstring.h similarity index 100% rename from src/utstring.h rename to third_party/uthash/utstring.h