summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzhuzhenjun <[email protected]>2023-10-23 09:54:02 +0800
committerzhuzhenjun <[email protected]>2023-10-23 09:54:02 +0800
commit7a5b2e9f072649a13b7b800420a2bb23e34cbbfc (patch)
tree2f161fa3e8a2e59f6609fc92e3807d5fdda18d3c
parentc0cfa2e61df7b74e8f033bf484f3beda432baa01 (diff)
score_db: support hash prefilter
-rw-r--r--src/osfp.c27
-rw-r--r--src/osfp_common.c1
-rw-r--r--src/osfp_common.h1
-rw-r--r--src/osfp_fingerprint.c371
-rw-r--r--src/osfp_fingerprint.h1
-rw-r--r--src/osfp_score_db.c61
-rw-r--r--src/osfp_score_db.h11
7 files changed, 302 insertions, 171 deletions
diff --git a/src/osfp.c b/src/osfp.c
index e822436..5b933c5 100644
--- a/src/osfp.c
+++ b/src/osfp.c
@@ -43,7 +43,9 @@ static struct osfp_result *osfp_result_build(struct osfp_os_class_score *os_clas
}
}
- if (likely_score < OSFP_LOWEST_SCORE_LIMIT) {
+ if (likely_score == OSFP_PERCENTILE) {
+ ;
+ } else if (likely_score < OSFP_LOWEST_SCORE_LIMIT) {
likely_os_class = OSFP_OS_CLASS_OTHERS;
} else {
for (i = 0; i < OSFP_OS_CLASS_MAX; i++) {
@@ -183,11 +185,17 @@ struct osfp_result *osfp_ipv4_identify(struct osfp_db *db, struct iphdr* l3_hdr,
}
osfp_profile_get_cycle(c1);
- ret = osfp_score_db_score(db->score_db, 0, &fp, &os_class_score);
+ ret = osfp_score_db_prefilter(db->score_db, &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_counter_update(&osfp_profile_prefilter, c2 - c1);
+ if (ret <= 0) {
+ 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);
@@ -250,9 +258,12 @@ struct osfp_result *osfp_json_identify(struct osfp_db *db, const char *json_str)
goto exit;
}
- ret = osfp_score_db_score(db->score_db, 0, &fp, &os_class_score);
- if (ret != 0) {
- goto exit;
+ ret = osfp_score_db_prefilter(db->score_db, &fp, &os_class_score);
+ if (ret <= 0) {
+ 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);
diff --git a/src/osfp_common.c b/src/osfp_common.c
index bf7680e..914bf1d 100644
--- a/src/osfp_common.c
+++ b/src/osfp_common.c
@@ -15,6 +15,7 @@ const char *osfp_os_class_name[OSFP_OS_CLASS_MAX] = {
};
struct osfp_profile_counter osfp_profile_fingerprinting;
+struct osfp_profile_counter osfp_profile_prefilter;
struct osfp_profile_counter osfp_profile_score;
struct osfp_profile_counter osfp_profile_result_build;
struct osfp_profile_counter osfp_profile_result_export;
diff --git a/src/osfp_common.h b/src/osfp_common.h
index 810e7bc..ac7b404 100644
--- a/src/osfp_common.h
+++ b/src/osfp_common.h
@@ -59,6 +59,7 @@ struct osfp_profile_counter {
};
extern struct osfp_profile_counter osfp_profile_fingerprinting;
+extern struct osfp_profile_counter osfp_profile_prefilter;
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;
diff --git a/src/osfp_fingerprint.c b/src/osfp_fingerprint.c
index 05dc52e..1d28109 100644
--- a/src/osfp_fingerprint.c
+++ b/src/osfp_fingerprint.c
@@ -21,6 +21,27 @@
#define OSFP_FINGERPRINT_DEFAULT_OS_CLASS_NAME "OSFP_UNKNOWN"
+#define OSFP_FP_SET_FIELD(fp, field_id, v, l) do { \
+ (fp)->fields[(field_id)].name = osfp_fingerprint_get_field_name(field_id); \
+ (fp)->fields[(field_id)].enabled = 1; \
+ if ((fp)->value_buffer_used + (l) <= sizeof((fp)->value_buffer)) { \
+ memcpy(fp->value_buffer + (fp)->value_buffer_used, (v), (l)); \
+ (fp)->fields[(field_id)].value = (fp)->value_buffer + (fp)->value_buffer_used; \
+ (fp)->fields[(field_id)].value_len = (l); \
+ (fp)->value_buffer_used += (l); \
+ } else { \
+ (fp)->fields[(field_id)].value = NULL; \
+ (fp)->fields[(field_id)].value_len = 0; \
+ } \
+ } while (0)
+
+#define OSFP_FP_INIT_FIELD(fp, field_id) do { \
+ (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; \
+ } while (0)
+
struct osfp_tcp_opt {
unsigned char type;
unsigned char len;
@@ -44,7 +65,6 @@ struct osfp_fingerprint_field fp_fields[OSFP_FIELD_MAX] = {
{OSFP_FINGERPRINT_FIELD_NAME_OS, 0, OSFP_FIELD_TYPE_STRING, 0, NULL, 0},
};
-
static char *osfp_fingerprint_tcp_options_to_ordered(char *tcp_options, unsigned int len)
{
int i;
@@ -78,6 +98,168 @@ exit:
return NULL;
}
+int osfp_fingerprint_to_json_buf(struct osfp_fingerprint *fp, char *strbuf, unsigned int buf_len, unsigned int format)
+{
+ int rlen = 0, ret, i;
+ cJSON *root;
+
+ if (fp == NULL || strbuf == NULL || buf_len == 0) {
+ return 0;
+ }
+
+ strbuf[0] = 0;
+
+ root = cJSON_CreateObject();
+ if (root == NULL) {
+ return 0;
+ }
+
+ for (i = 0; i < OSFP_FIELD_MAX; i++) {
+ if (fp->fields[i].enabled) {
+ switch (fp_fields[i].type) {
+ case OSFP_FIELD_TYPE_UINT:
+ cJSON_AddNumberToObject(root, fp_fields[i].name, *(unsigned int *)fp->fields[i].value);
+ break;
+ case OSFP_FIELD_TYPE_STRING:
+ cJSON_AddStringToObject(root, fp_fields[i].name, (char *)fp->fields[i].value);
+ break;
+ default:
+ break;
+ }
+ } else {
+ cJSON_AddNullToObject(root, fp_fields[i].name);
+ }
+ }
+
+ if (!cJSON_PrintPreallocated(root, strbuf, buf_len, format)) {
+ return 0;
+ }
+
+ cJSON_Delete(root);
+
+ return strlen(strbuf) + 1;
+}
+
+struct osfp_fingerprint *osfp_fingerprint_from_cjson(cJSON *root)
+{
+ int i;
+ cJSON *field;
+ void *value_ptr;
+ unsigned int value_len;
+ struct osfp_fingerprint *fp;
+
+ if (root == NULL) {
+ goto exit;
+ }
+
+ fp = calloc(1, sizeof(struct osfp_fingerprint));
+ if (fp == NULL) {
+ goto exit;
+ }
+
+ for (i = 0; i < OSFP_FIELD_OS; i++) {
+ field = cJSON_GetObjectItem(root, osfp_fingerprint_get_field_name(i));
+ if (field == NULL) {
+ OSFP_FP_INIT_FIELD(fp, i);
+ continue;
+ }
+
+ switch (field->type) {
+ case cJSON_Number:
+ value_ptr = (void *)&field->valueint;
+ value_len = sizeof(field->valueint);
+ OSFP_FP_SET_FIELD(fp, i, value_ptr, value_len);
+ break;
+ case cJSON_String:
+ value_ptr = (void *)field->valuestring;
+ value_len = strlen(field->valuestring) + 1;
+ OSFP_FP_SET_FIELD(fp, i, value_ptr, value_len);
+ break;
+ case cJSON_NULL:
+ //printf("fingerprint parse error: %s\n%s\n", field->string, cJSON_Print(root));
+ break;
+ default:
+ goto exit;
+ }
+ }
+
+ OSFP_FP_INIT_FIELD(fp, OSFP_FIELD_OS);
+
+ return fp;
+exit:
+ if (fp) {
+ free(fp);
+ }
+ return NULL;
+}
+
+int osfp_fingerprint_from_json(struct osfp_fingerprint *fp, char *json_str)
+{
+ int ret, i;
+ cJSON *root;
+ cJSON *field;
+
+ void *value_ptr;
+ unsigned int value_len;
+
+ if (fp == NULL || json_str == NULL) {
+ goto exit;
+ }
+
+ memset(fp, 0, sizeof(struct osfp_fingerprint));
+
+ root = cJSON_Parse(json_str);
+ if (root == NULL) {
+ osfp_log_error("parse json: '%s'\n", json_str);
+ goto exit;
+ }
+
+ field = cJSON_GetObjectItem(root, osfp_fingerprint_get_field_name(OSFP_FIELD_TCP_OPTIONS_ORDERED));
+ if (field == NULL) {
+ field = cJSON_GetObjectItem(root, osfp_fingerprint_get_field_name(OSFP_FIELD_TCP_OPTIONS));
+ if (field) {
+ char *tcp_options_ordered_str = osfp_fingerprint_tcp_options_to_ordered(field->valuestring, strlen(field->valuestring));
+ if (tcp_options_ordered_str) {
+ cJSON_AddItemToObject(root, osfp_fingerprint_get_field_name(OSFP_FIELD_TCP_OPTIONS_ORDERED),
+ cJSON_CreateString(tcp_options_ordered_str));
+ free(tcp_options_ordered_str);
+ }
+ }
+ }
+
+ for (i = 0; i < OSFP_FIELD_OS; i++) {
+ field = cJSON_GetObjectItem(root, osfp_fingerprint_get_field_name(i));
+ if (field == NULL) {
+ goto exit;
+ }
+
+ switch (field->type) {
+ case cJSON_Number:
+ value_ptr = (void *)&field->valueint;
+ value_len = sizeof(field->valueint);
+ OSFP_FP_SET_FIELD(fp, i, value_ptr, value_len);
+ break;
+ case cJSON_String:
+ value_ptr = (void *)field->valuestring;
+ value_len = strlen(field->valuestring) + 1;
+ OSFP_FP_SET_FIELD(fp, i, value_ptr, value_len);
+ break;
+ case cJSON_NULL:
+ //printf("fingerprint parse error: %s\n%s\n", field->string, cJSON_Print(root));
+ break;
+ default:
+ goto exit;
+ }
+ }
+
+ ret = 0;
+exit:
+ if (root) {
+ cJSON_Delete(root);
+ }
+ return ret;
+}
+
static char option_to_ascii(unsigned char type)
{
switch (type) {
@@ -122,30 +304,6 @@ 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;
@@ -222,7 +380,7 @@ static int osfp_fingerprinting_tcp_option(unsigned char *opt_data, unsigned int
break;
}
tcp_mss = (unsigned int)ntohs(*(unsigned short *)opt->data);
- osfp_fingerprint_setup_field(fp, OSFP_FIELD_TCP_MSS, &tcp_mss, sizeof(tcp_mss));
+ OSFP_FP_SET_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;
@@ -234,7 +392,7 @@ static int osfp_fingerprinting_tcp_option(unsigned char *opt_data, unsigned int
break;
}
tcp_ws = (unsigned int)*(unsigned char *)opt->data;
- osfp_fingerprint_setup_field(fp, OSFP_FIELD_TCP_WINDOW_SCALING, &tcp_ws, sizeof(tcp_ws));
+ OSFP_FP_SET_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;
@@ -246,7 +404,7 @@ static int osfp_fingerprinting_tcp_option(unsigned char *opt_data, unsigned int
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));
+ OSFP_FP_SET_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;
@@ -273,8 +431,8 @@ static int osfp_fingerprinting_tcp_option(unsigned char *opt_data, unsigned int
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);
+ OSFP_FP_SET_FIELD(fp, OSFP_FIELD_TCP_OPTIONS, options, strlen(options) + 1);
+ OSFP_FP_SET_FIELD(fp, OSFP_FIELD_TCP_OPTIONS_ORDERED, options_ordered, strlen(options_ordered) + 1);
return 0;
exit:
@@ -299,16 +457,16 @@ static int osfp_fingerprinting_tcp(struct tcphdr *tcph, unsigned int tcph_len, s
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_FP_SET_FIELD(fp, OSFP_FIELD_TCP_OFF, &tcp_off, sizeof(tcp_off));
+ OSFP_FP_SET_FIELD(fp, OSFP_FIELD_TCP_WINDOW_SIZE, &tcp_window_size, sizeof(tcp_window_size));
+ OSFP_FP_SET_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);
+ OSFP_FP_INIT_FIELD(fp, OSFP_FIELD_TCP_TIMESTAMP);
+ OSFP_FP_INIT_FIELD(fp, OSFP_FIELD_TCP_TIMESTAMP_ECHO_REPLY);
+ OSFP_FP_INIT_FIELD(fp, OSFP_FIELD_TCP_WINDOW_SCALING);
+ OSFP_FP_INIT_FIELD(fp, OSFP_FIELD_TCP_MSS);
+ OSFP_FP_INIT_FIELD(fp, OSFP_FIELD_TCP_OPTIONS);
+ OSFP_FP_INIT_FIELD(fp, OSFP_FIELD_TCP_OPTIONS_ORDERED);
// tcp options
if (tcp_off > OSFP_TCP_HEADER_LEN) {
@@ -331,10 +489,10 @@ static int osfp_fingerprinting_ipv4(struct iphdr *iph, struct osfp_fingerprint *
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));
+ OSFP_FP_SET_FIELD(fp, OSFP_FIELD_IP_ID, &ip_id, sizeof(ip_id));
+ OSFP_FP_SET_FIELD(fp, OSFP_FIELD_IP_TOS, &ip_tos, sizeof(ip_tos));
+ OSFP_FP_SET_FIELD(fp, OSFP_FIELD_IP_TOTAL_LENGTH, &ip_total_length, sizeof(ip_total_length));
+ OSFP_FP_SET_FIELD(fp, OSFP_FIELD_IP_TTL, &ip_ttl, sizeof(ip_ttl));
return 0;
exit:
@@ -352,130 +510,17 @@ static int osfp_fingerprinting_ipv6(struct ip6_hdr *iph, struct osfp_fingerprint
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_FP_SET_FIELD(fp, OSFP_FIELD_IP_TOTAL_LENGTH, &ip_total_length, sizeof(ip_total_length));
+ OSFP_FP_SET_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);
+ OSFP_FP_INIT_FIELD(fp, OSFP_FIELD_IP_ID);
+ OSFP_FP_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;
- cJSON *root;
-
- if (fp == NULL || strbuf == NULL || buf_len == 0) {
- return 0;
- }
-
- strbuf[0] = 0;
-
- root = cJSON_CreateObject();
- if (root == NULL) {
- return 0;
- }
-
- for (i = 0; i < OSFP_FIELD_MAX; i++) {
- if (fp->fields[i].enabled) {
- switch (fp_fields[i].type) {
- case OSFP_FIELD_TYPE_UINT:
- cJSON_AddNumberToObject(root, fp_fields[i].name, *(unsigned int *)fp->fields[i].value);
- break;
- case OSFP_FIELD_TYPE_STRING:
- cJSON_AddStringToObject(root, fp_fields[i].name, (char *)fp->fields[i].value);
- break;
- default:
- break;
- }
- } else {
- cJSON_AddNullToObject(root, fp_fields[i].name);
- }
- }
-
- if (!cJSON_PrintPreallocated(root, strbuf, buf_len, format)) {
- return 0;
- }
-
- cJSON_Delete(root);
-
- return strlen(strbuf) + 1;
-}
-
-int osfp_fingerprint_from_json(struct osfp_fingerprint *fp, char *json_str)
-{
- int ret, i;
- cJSON *root;
- cJSON *field;
-
- void *value_ptr;
- unsigned int value_len;
-
- if (fp == NULL || json_str == NULL) {
- goto exit;
- }
-
- memset(fp, 0, sizeof(struct osfp_fingerprint));
-
- root = cJSON_Parse(json_str);
- if (root == NULL) {
- osfp_log_error("parse json: '%s'\n", json_str);
- goto exit;
- }
-
- field = cJSON_GetObjectItem(root, osfp_fingerprint_get_field_name(OSFP_FIELD_TCP_OPTIONS_ORDERED));
- if (field == NULL) {
- field = cJSON_GetObjectItem(root, osfp_fingerprint_get_field_name(OSFP_FIELD_TCP_OPTIONS));
- if (field) {
- char *tcp_options_ordered_str = osfp_fingerprint_tcp_options_to_ordered(field->valuestring, strlen(field->valuestring));
- if (tcp_options_ordered_str) {
- cJSON_AddItemToObject(root, osfp_fingerprint_get_field_name(OSFP_FIELD_TCP_OPTIONS_ORDERED),
- cJSON_CreateString(tcp_options_ordered_str));
- free(tcp_options_ordered_str);
- }
- }
- }
-
- for (i = 0; i < OSFP_FIELD_OS; i++) {
- if (!fp_fields[i].enabled) {
- continue;
- }
-
- field = cJSON_GetObjectItem(root, osfp_fingerprint_get_field_name(i));
- if (field == NULL) {
- goto exit;
- }
-
- switch (field->type) {
- case cJSON_Number:
- value_ptr = (void *)&field->valueint;
- value_len = sizeof(field->valueint);
- osfp_fingerprint_setup_field(fp, i, value_ptr, value_len);
- break;
- case cJSON_String:
- value_ptr = (void *)field->valuestring;
- value_len = strlen(field->valuestring) + 1;
- osfp_fingerprint_setup_field(fp, i, value_ptr, value_len);
- break;
- case cJSON_NULL:
- //printf("fingerprint parse error: %s\n%s\n", field->string, cJSON_Print(root));
- break;
- default:
- goto exit;
- }
- }
-
- ret = 0;
-exit:
- if (root) {
- cJSON_Delete(root);
- }
- return ret;
-}
-
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;
@@ -507,7 +552,7 @@ int osfp_fingerprinting(unsigned char *iph, unsigned char *tcph, unsigned int tc
goto exit;
}
- osfp_fingerprint_setup_field(fp, OSFP_FIELD_OS, OSFP_FINGERPRINT_DEFAULT_OS_CLASS_NAME, strlen(OSFP_FINGERPRINT_DEFAULT_OS_CLASS_NAME) + 1);
+ OSFP_FP_INIT_FIELD(fp, OSFP_FIELD_OS);
return 0;
exit:
@@ -531,7 +576,7 @@ int test_osfp_fingerprinting_ipv4(void)
};
char str_buf[2048] = "";
- const char *target = "{\"ip_id\":1,\"ip_tos\":0,\"ip_total_length\":52,\"ip_ttl\":128,\"tcp_off\":32,\"tcp_timestamp\":null,\"tcp_timestamp_echo_reply\":null,\"tcp_window_scaling\":8,\"tcp_window_size\":8192,\"tcp_flags\":2,\"tcp_mss\":1260,\"tcp_options\":\"M1260,N,W8,N,N,S,\",\"tcp_options_ordered\":\"MNWNNS\",\"os\":\"OSFP_UNKNOWN\"}";
+ const char *target = "{\"ip_id\":1,\"ip_tos\":0,\"ip_total_length\":52,\"ip_ttl\":128,\"tcp_off\":32,\"tcp_timestamp\":null,\"tcp_timestamp_echo_reply\":null,\"tcp_window_scaling\":8,\"tcp_window_size\":8192,\"tcp_flags\":2,\"tcp_mss\":1260,\"tcp_options\":\"M1260,N,W8,N,N,S,\",\"tcp_options_ordered\":\"MNWNNS\",\"os\":null}";
struct osfp_fingerprint fp = {0};
ret = osfp_fingerprinting(iph, tcph, 32, &fp, 4);
@@ -571,7 +616,7 @@ int test_osfp_fingerprinting_ipv6(void)
};
char str_buf[2048] = "";
- const char *target = "{\"ip_id\":1,\"ip_tos\":0,\"ip_total_length\":52,\"ip_ttl\":128,\"tcp_off\":32,\"tcp_timestamp\":null,\"tcp_timestamp_echo_reply\":null,\"tcp_window_scaling\":8,\"tcp_window_size\":8192,\"tcp_flags\":2,\"tcp_mss\":1260,\"tcp_options\":\"M1260,N,W8,N,N,S,\",\"tcp_options_ordered\":\"MNWNNS\",\"os\":\"OSFP_UNKNOWN\"}";
+ const char *target = "{\"ip_id\":1,\"ip_tos\":0,\"ip_total_length\":52,\"ip_ttl\":128,\"tcp_off\":32,\"tcp_timestamp\":null,\"tcp_timestamp_echo_reply\":null,\"tcp_window_scaling\":8,\"tcp_window_size\":8192,\"tcp_flags\":2,\"tcp_mss\":1260,\"tcp_options\":\"M1260,N,W8,N,N,S,\",\"tcp_options_ordered\":\"MNWNNS\",\"os\":null}";
struct osfp_fingerprint fp = {0};
ret = osfp_fingerprinting(iph, tcph, 32, &fp, 4);
diff --git a/src/osfp_fingerprint.h b/src/osfp_fingerprint.h
index 00806ae..f31ed16 100644
--- a/src/osfp_fingerprint.h
+++ b/src/osfp_fingerprint.h
@@ -65,6 +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);
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);
int osfp_fingerprinting(unsigned char *iph, unsigned char *tcph, unsigned int tcph_len, struct osfp_fingerprint *fp, unsigned int ip_version);
diff --git a/src/osfp_score_db.c b/src/osfp_score_db.c
index 5598537..6267163 100644
--- a/src/osfp_score_db.c
+++ b/src/osfp_score_db.c
@@ -251,6 +251,27 @@ static int osfp_score_db_load_entry(struct osfp_score_db *score_db, cJSON *entry
goto exit;
}
+ // prefileter
+ struct osfp_prefilter_hash_element *element = NULL;
+ struct osfp_fingerprint *fp = osfp_fingerprint_from_cjson(entry);
+ if (fp == NULL) {
+ goto exit;
+ }
+ HASH_FIND(hh, score_db->prefilter_head, fp->value_buffer, fp->value_buffer_used, element);
+ if (element == NULL) {
+ element = (struct osfp_prefilter_hash_element *)calloc(1, sizeof(struct osfp_prefilter_hash_element));
+ if (element == NULL) {
+ free(fp);
+ goto exit;
+ }
+
+ element->fp_json = cJSON_Print(entry);
+ element->fp = fp;
+ element->os_class = os_class;
+ HASH_ADD_KEYPTR(hh, score_db->prefilter_head, fp->value_buffer, fp->value_buffer_used, element);
+ }
+
+ // field score db
for (i = 0; i < OSFP_FIELD_OS; i++) {
db = &score_db->field_score_dbs[i];
if (db == NULL) {
@@ -391,6 +412,26 @@ exit:
return ret;
}
+int osfp_score_db_prefilter(struct osfp_score_db *score_db, struct osfp_fingerprint *fp, struct osfp_os_class_score *result_score)
+{
+ int ret;
+ struct osfp_prefilter_hash_element *element = NULL;
+
+ if (score_db->prefilter_head == NULL) {
+ return 0;
+ }
+
+ HASH_FIND(hh, score_db->prefilter_head, fp->value_buffer, fp->value_buffer_used, element);
+ if (element == NULL) {
+ return 0;
+ }
+
+ memset(result_score, 0, sizeof(struct osfp_os_class_score));
+ result_score->scores[element->os_class] = OSFP_PERCENTILE;
+
+ return 1;
+}
+
int osfp_score_db_score(struct osfp_score_db *score_db, unsigned int flags, struct osfp_fingerprint *fp, struct osfp_os_class_score *result_score)
{
int ret = OSFP_EINVAL, i, j;
@@ -410,6 +451,7 @@ int osfp_score_db_score(struct osfp_score_db *score_db, unsigned int flags, stru
goto exit;
}
+ // score
memset(result_score, 0, sizeof(struct osfp_os_class_score));
perfect_score = score_db->perfect_score;
@@ -539,8 +581,27 @@ void osfp_score_db_destroy(struct osfp_score_db *score_db)
{
int i;
struct osfp_field_score_db *db;
+ struct osfp_prefilter_hash_element *element = NULL;
+ struct osfp_prefilter_hash_element *tmp = NULL;
if (score_db) {
+ // prefilter
+ if (score_db->prefilter_head) {
+ HASH_ITER(hh, score_db->prefilter_head, element, tmp) {
+ HASH_DELETE(hh, score_db->prefilter_head, element);
+ if (element) {
+ if (element->fp) {
+ free(element->fp);
+ }
+ if (element->fp_json) {
+ free(element->fp_json);
+ }
+ free(element);
+ }
+ }
+ }
+
+ // field score db
for (i = 0; i < OSFP_FIELD_MAX; i++) {
db = &score_db->field_score_dbs[i];
if (db->destroy && db->data) {
diff --git a/src/osfp_score_db.h b/src/osfp_score_db.h
index 3ee9a84..b73427d 100644
--- a/src/osfp_score_db.h
+++ b/src/osfp_score_db.h
@@ -22,8 +22,18 @@ struct osfp_field_score_db {
struct osfp_os_class_score *(*match)(void *, void *, unsigned int);
};
+struct osfp_prefilter_hash_element {
+ struct osfp_fingerprint *fp;
+ char *fp_json;
+ unsigned int os_class;
+ UT_hash_handle hh;
+};
+
struct osfp_score_db {
unsigned int entry_count;
+
+ struct osfp_prefilter_hash_element *prefilter_head;
+
unsigned int perfect_score;
unsigned int os_class_entry_count[OSFP_OS_CLASS_MAX];
struct osfp_field_score_db field_score_dbs[OSFP_FIELD_MAX];
@@ -33,6 +43,7 @@ char *osfp_score_db_read_file(char *fp_file);
void osfp_score_db_debug_print(struct osfp_score_db *score_db);
int osfp_score_db_load(struct osfp_score_db *score_db, char *fp_file);
+int osfp_score_db_prefilter(struct osfp_score_db *score_db, struct osfp_fingerprint *fp, struct osfp_os_class_score *result_score);
int osfp_score_db_score(struct osfp_score_db *score_db, unsigned int flags, struct osfp_fingerprint *fp, struct osfp_os_class_score *result_score);
struct osfp_score_db *osfp_score_db_create(void);