profile: init profile stats
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
||||||
@@ -145,6 +146,11 @@ typedef struct Packet_ {
|
|||||||
int vlan_layer;
|
int vlan_layer;
|
||||||
} Packet;
|
} 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_file_path;
|
||||||
unsigned char *fp_output_file_path;
|
unsigned char *fp_output_file_path;
|
||||||
@@ -159,6 +165,12 @@ pcap_t *pcap_handle;
|
|||||||
int processed_packet;
|
int processed_packet;
|
||||||
int link_type;
|
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) {
|
void usage(void) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Usage: osfp_match [ ...options... ] [ 'filter rule' ]\n"
|
"Usage: osfp_match [ ...options... ] [ 'filter rule' ]\n"
|
||||||
@@ -172,13 +184,6 @@ void usage(void) {
|
|||||||
exit(1);
|
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 packet_decode_tcp(Packet *p, const unsigned char *data, unsigned int len)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
@@ -434,13 +439,16 @@ void example_detect(struct osfp_db *osfp_db, Packet *p)
|
|||||||
unsigned int tcph_len;
|
unsigned int tcph_len;
|
||||||
struct osfp_result *result = NULL;
|
struct osfp_result *result = NULL;
|
||||||
|
|
||||||
printf("Example ipv4 header detect: --------------------------\n");
|
|
||||||
|
|
||||||
iph = (struct iphdr *)p->iph;
|
iph = (struct iphdr *)p->iph;
|
||||||
ip6h = (struct ip6_hdr *)p->ip6h;
|
ip6h = (struct ip6_hdr *)p->ip6h;
|
||||||
tcph = (struct tcphdr *)p->tcph;
|
tcph = (struct tcphdr *)p->tcph;
|
||||||
tcph_len = tcph->doff << 2;
|
tcph_len = tcph->doff << 2;
|
||||||
|
|
||||||
|
osfp_profile_cycle(c1);
|
||||||
|
osfp_profile_cycle(c2);
|
||||||
|
|
||||||
|
|
||||||
|
osfp_profile_get_cycle(c1);
|
||||||
if (iph) {
|
if (iph) {
|
||||||
result = osfp_ipv4_identify(osfp_db, iph, tcph, tcph_len);
|
result = osfp_ipv4_identify(osfp_db, iph, tcph, tcph_len);
|
||||||
} else if (ip6h) {
|
} else if (ip6h) {
|
||||||
@@ -448,17 +456,28 @@ void example_detect(struct osfp_db *osfp_db, Packet *p)
|
|||||||
} else {
|
} else {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
osfp_profile_get_cycle(c2);
|
||||||
|
osfp_profile_counter_update(&identify_profile, c2 - c1);
|
||||||
|
|
||||||
|
identify_count++;
|
||||||
|
|
||||||
if (result == NULL) {
|
if (result == NULL) {
|
||||||
|
identify_failed_count++;
|
||||||
printf("osfp header match failed, erro: %s\n", "?");
|
printf("osfp header match failed, erro: %s\n", "?");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Connection info: %s:%d -> %s:%d\n", p->srcip, p->sp, p->dstip, p->dp);
|
result_os_count[result->likely_os_class]++;
|
||||||
printf("Most likely os class: %s\n", osfp_result_os_name_get(result));
|
|
||||||
|
|
||||||
printf("Details:\n");
|
char *json = osfp_result_score_detail_export(result);
|
||||||
printf("%s\n", 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:
|
exit:
|
||||||
if (result) {
|
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
|
// 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);
|
printf("--------------------------- processed packet count %d\n", ++processed_packet);
|
||||||
|
|
||||||
@@ -507,10 +529,35 @@ exit:
|
|||||||
return;
|
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 main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
signal(SIGINT, signal_handler);
|
||||||
|
signal(SIGTERM, signal_handler);
|
||||||
|
|
||||||
while ((r = getopt(argc, argv, "+f:i:r:o:d")) != -1) {
|
while ((r = getopt(argc, argv, "+f:i:r:o:d")) != -1) {
|
||||||
switch(r) {
|
switch(r) {
|
||||||
case 'f':
|
case 'f':
|
||||||
@@ -621,6 +668,8 @@ int main(int argc, char *argv[])
|
|||||||
osfp_log_level_set(OSFP_LOG_LEVEL_DEBUG);
|
osfp_log_level_set(OSFP_LOG_LEVEL_DEBUG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
osfp_profile_set(1);
|
||||||
|
|
||||||
struct osfp_db *osfp_db = osfp_db_new(fp_file_path);
|
struct osfp_db *osfp_db = osfp_db_new(fp_file_path);
|
||||||
if (osfp_db == NULL) {
|
if (osfp_db == NULL) {
|
||||||
printf("could not create osfp context. fingerprints file: %s\n", fp_file_path);
|
printf("could not create osfp context. fingerprints file: %s\n", fp_file_path);
|
||||||
|
|||||||
BIN
pcap/synmerge.pcap
Normal file
BIN
pcap/synmerge.pcap
Normal file
Binary file not shown.
24
src/osfp.c
24
src/osfp.c
@@ -94,6 +94,10 @@ char *osfp_result_score_detail_export(struct osfp_result *result)
|
|||||||
cJSON *array;
|
cJSON *array;
|
||||||
cJSON *os_score;
|
cJSON *os_score;
|
||||||
|
|
||||||
|
osfp_profile_cycle(c1);
|
||||||
|
osfp_profile_cycle(c2);
|
||||||
|
osfp_profile_get_cycle(c1);
|
||||||
|
|
||||||
if (result == NULL) {
|
if (result == NULL) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
@@ -139,6 +143,10 @@ exit:
|
|||||||
if (root) {
|
if (root) {
|
||||||
cJSON_Delete(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;
|
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_os_class_score os_class_score;
|
||||||
struct osfp_result *result;
|
struct osfp_result *result;
|
||||||
|
|
||||||
|
osfp_profile_cycle(c1);
|
||||||
|
osfp_profile_cycle(c2);
|
||||||
|
|
||||||
if (db == NULL || l3_hdr == NULL || l4_hdr == NULL || l4_hdr == 0) {
|
if (db == NULL || l3_hdr == NULL || l4_hdr == NULL || l4_hdr == 0) {
|
||||||
goto exit;
|
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);
|
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) {
|
if (ret != 0) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
osfp_profile_get_cycle(c1);
|
||||||
ret = osfp_score_db_score(db->score_db, 0, &fp, &os_class_score);
|
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) {
|
if (ret != 0) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
osfp_profile_get_cycle(c1);
|
||||||
result = osfp_result_build(&os_class_score);
|
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) {
|
if (result == NULL) {
|
||||||
goto exit;
|
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_os_class_score os_class_score;
|
||||||
struct osfp_result *result;
|
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;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,7 +245,7 @@ struct osfp_result *osfp_json_identify(struct osfp_db *db, const char *json_str)
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = osfp_fingerprint_from_json(&fp, json_str);
|
ret = osfp_fingerprint_from_json(&fp, (char *)json_str);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include "osfp.h"
|
#include "osfp.h"
|
||||||
|
|
||||||
|
unsigned int osfp_profile_enable;
|
||||||
|
|
||||||
const char *os_class_name[OSFP_OS_CLASS_MAX] = {
|
const char *os_class_name[OSFP_OS_CLASS_MAX] = {
|
||||||
OSFP_OS_CLASS_NAME_UNKNOWN,
|
OSFP_OS_CLASS_NAME_UNKNOWN,
|
||||||
OSFP_OS_CLASS_NAME_WINDOWS,
|
OSFP_OS_CLASS_NAME_WINDOWS,
|
||||||
@@ -12,6 +14,54 @@ const char *os_class_name[OSFP_OS_CLASS_MAX] = {
|
|||||||
OSFP_OS_CLASS_NAME_OTHERS
|
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 osfp_os_class_name_to_id(char *name)
|
||||||
{
|
{
|
||||||
enum osfp_os_class_id os_class;
|
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;
|
return os_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *osfp_os_class_id_to_name(enum osfp_os_class_id os_class)
|
|
||||||
{
|
|
||||||
return os_class_name[os_class];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -39,11 +39,35 @@ static inline unsigned long long osfp_rdtsc(void)
|
|||||||
return tsc.tsc_64;
|
return tsc.tsc_64;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern unsigned int osfp_profile_enable;
|
||||||
|
|
||||||
#define osfp_profile_cycle(x) volatile unsigned long long x = 0
|
#define osfp_profile_cycle(x) volatile unsigned long long x = 0
|
||||||
#define osfp_profile_get_cycle(x) do { \
|
#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)
|
} 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_BIT_U32(n) (1UL << (n))
|
||||||
|
|
||||||
#define OSFP_PERCENTILE 100
|
#define OSFP_PERCENTILE 100
|
||||||
@@ -171,7 +195,12 @@ struct osfp_db {
|
|||||||
void *score_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);
|
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
|
#endif
|
||||||
|
|||||||
@@ -88,6 +88,30 @@ static unsigned int compute_ip_ttl(unsigned int ip_ttl)
|
|||||||
return 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)
|
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;
|
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;
|
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 osfp_fingerprint_to_json_buf(struct osfp_fingerprint *fp, char *strbuf, unsigned int buf_len, unsigned int format)
|
||||||
{
|
{
|
||||||
int rlen = 0, ret, i;
|
int rlen = 0, ret, i;
|
||||||
@@ -222,214 +426,6 @@ exit:
|
|||||||
return ret;
|
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 osfp_fingerprinting(unsigned char *iph, unsigned char *tcph, unsigned int tcph_len, struct osfp_fingerprint *fp, unsigned int ip_version)
|
||||||
{
|
{
|
||||||
int ret = OSFP_EINVAL;
|
int ret = OSFP_EINVAL;
|
||||||
@@ -438,7 +434,7 @@ int osfp_fingerprinting(unsigned char *iph, unsigned char *tcph, unsigned int tc
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(fp, 0, sizeof(struct osfp_fingerprint));
|
fp->value_buffer_used = 0;
|
||||||
|
|
||||||
switch (ip_version) {
|
switch (ip_version) {
|
||||||
case 4:
|
case 4:
|
||||||
|
|||||||
@@ -43,20 +43,30 @@ struct osfp_fingerprint {
|
|||||||
unsigned int value_buffer_used;
|
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_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_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);
|
int osfp_fingerprinting(unsigned char *iph, unsigned char *tcph, unsigned int tcph_len, struct osfp_fingerprint *fp, unsigned int ip_version);
|
||||||
|
|
||||||
#ifdef UNITTEST
|
#ifdef UNITTEST
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ struct osfp_score_db_hash_data {
|
|||||||
struct osfp_score_db_hash_element *hash_head;
|
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;
|
int ret = -1, i;
|
||||||
unsigned int index;
|
unsigned int index;
|
||||||
@@ -55,7 +55,7 @@ exit:
|
|||||||
return ret;
|
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;
|
unsigned int index;
|
||||||
struct osfp_score_db_array_data *array_data = (struct osfp_score_db_array_data *)data;
|
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]);
|
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));
|
struct osfp_score_db_array_data *array_data = calloc(1, sizeof(struct osfp_score_db_array_data));
|
||||||
if (array_data == NULL) {
|
if (array_data == NULL) {
|
||||||
@@ -95,7 +95,7 @@ void *osfp_score_db_array_create(void)
|
|||||||
return (void *)array_data;
|
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;
|
struct osfp_score_db_array_data *array_data = (struct osfp_score_db_array_data *)data;
|
||||||
|
|
||||||
if (array_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;
|
int ret = -1, i;
|
||||||
struct osfp_score_db_hash_data *hash_data = (struct osfp_score_db_hash_data *)data;
|
struct osfp_score_db_hash_data *hash_data = (struct osfp_score_db_hash_data *)data;
|
||||||
@@ -142,7 +142,7 @@ exit:
|
|||||||
return ret;
|
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_data *hash_data = (struct osfp_score_db_hash_data *)data;
|
||||||
struct osfp_score_db_hash_element *element = NULL;
|
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;
|
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));
|
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_data *hash_data = (struct osfp_score_db_hash_data *)data;
|
||||||
struct osfp_score_db_hash_element *element = NULL;
|
struct osfp_score_db_hash_element *element = NULL;
|
||||||
struct osfp_score_db_hash_element *tmp = 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)
|
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;
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
struct osfp_os_class_score os_class_score = {0};
|
struct osfp_os_class_score os_class_score = {0};
|
||||||
@@ -278,7 +230,7 @@ exit:
|
|||||||
return ret;
|
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;
|
int ret = -1, i;
|
||||||
cJSON *field = NULL;
|
cJSON *field = NULL;
|
||||||
@@ -332,6 +284,54 @@ exit:
|
|||||||
return ret;
|
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 osfp_score_db_load(struct osfp_score_db *score_db, char *fp_file)
|
||||||
{
|
{
|
||||||
int ret = OSFP_EINVAL, i, count;
|
int ret = OSFP_EINVAL, i, count;
|
||||||
|
|||||||
Reference in New Issue
Block a user