profile: init profile stats

This commit is contained in:
zhuzhenjun
2023-10-11 15:07:21 +08:00
parent 9056ffb00f
commit b7ee724244
8 changed files with 451 additions and 302 deletions

View File

@@ -3,6 +3,7 @@
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <signal.h>
#include <sys/socket.h>
@@ -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;
}
result_os_count[result->likely_os_class]++;
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", osfp_result_score_detail_export(result));
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
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);

BIN
pcap/synmerge.pcap Normal file

Binary file not shown.

View File

@@ -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;
}

View File

@@ -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];
}

View File

@@ -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 { \
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

View File

@@ -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:

View File

@@ -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

View File

@@ -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;