This commit is contained in:
zhuzhenjun
2023-09-22 15:59:40 +08:00
parent 91e6b79afc
commit 554867aa4e
16 changed files with 73081 additions and 344 deletions

View File

@@ -15,9 +15,9 @@
#include <pcap.h>
#include "libosfp.h"
#include "libosfp_fingerprint.h"
#include "libosfp_score_db.h"
#define DEFAULT_FP_FILE "./fp.json"
#define DEFAULT_FP_FILE_PATH "./fp.json"
#define ETHERNET_HEADER_LEN 14
#define VLAN_HEADER_LEN 4
@@ -131,6 +131,9 @@ typedef struct Packet_ {
struct ipv6hdr *ip6h;
struct tcphdr *tcph;
char srcip[46];
char dstip[46];
Address src;
Address dst;
union {
@@ -154,7 +157,10 @@ typedef struct Packet_ {
} Packet;
unsigned char *fp_file;
unsigned char *fp_file_path;
unsigned char *fp_output_file_path;
FILE *fingerprinting_output_fp;
unsigned char *if_name;
unsigned char *pcap_file_name;
unsigned char *bpf_string;
@@ -172,7 +178,7 @@ void usage(void) {
" -i iface - listen on the specified network interface\n"
" -r file - read offline pcap data from a given file\n"
" -f file - read fingerprint database from 'file' (%s)\n",
DEFAULT_FP_FILE);
DEFAULT_FP_FILE_PATH);
exit(1);
}
@@ -427,50 +433,39 @@ const char *PrintInet(int af, const void *src, char *dst, socklen_t size)
return NULL;
}
void example_header_match(libosfp_context_t *libosfp_context, Packet *p)
void example_detect(libosfp_context_t *libosfp_context, Packet *p)
{
// tcp/ip header match
int ret;
char str_buf[1024];
unsigned char *iph = (unsigned char *)(p->iph != NULL ? (void *)p->iph : (void *)p->ip6h);
unsigned char *tcph = (unsigned char *)p->tcph;
libosfp_result_t result;
unsigned int os_class_flags = LIBOSFP_OS_CLASS_FLAG_WINDOWS | LIBOSFP_OS_CLASS_FLAG_LINUX | LIBOSFP_OS_CLASS_FLAG_MAC_OS;
printf("Example header match: --------------------------\n");
printf("Example header detect: --------------------------\n");
ret = libosfp_header_match(libosfp_context, iph, tcph, &result);
ret = libosfp_detect(libosfp_context, os_class_flags, iph, tcph, &result);
if (ret != 0) {
printf("libosfp header match failed, erro: %s\n", "?");
goto exit;
}
char srcip[46] = {0}, dstip[46] = {0};
Port sp, dp;
if (p->iph) {
PrintInet(AF_INET, (const void *)&(p->src.addr_data32[0]), srcip, sizeof(srcip));
PrintInet(AF_INET, (const void *)&(p->dst.addr_data32[0]), dstip, sizeof(dstip));
} else if (p->ip6h) {
PrintInet(AF_INET6, (const void *)&(p->src.address), srcip, sizeof(srcip));
PrintInet(AF_INET6, (const void *)&(p->dst.address), dstip, sizeof(dstip));
}
sp = p->sp;
dp = p->dp;
printf("Connection info: %s:%d -> %s:%d\n", srcip, sp, dstip, dp);
printf("Connection info: %s:%d -> %s:%d\n", p->srcip, p->sp, p->dstip, p->dp);
printf("Most likely os class: %s\n", libosfp_result_likely_os_class_name_get(&result));
printf("Likely score: %u/100\n", libosfp_result_likely_os_class_score_get(&result));
printf("Likely score: %u/100\n", result.score.likely_score);
libosfp_result_to_buf(&result, str_buf, sizeof(str_buf));
fprintf(stdout, "%s\n", str_buf);
printf("Details:\n");
if (libosfp_result_to_buf(&result, str_buf, sizeof(str_buf))) {
printf("%s", str_buf);
}
exit:
return;
}
void example_fingerprint_match(libosfp_context_t *libosfp_context, Packet *p)
void example_detect_fingerprint(libosfp_context_t *libosfp_context, Packet *p)
{
// fingerprint match
int ret;
char str_buf[1024];
@@ -479,8 +474,9 @@ void example_fingerprint_match(libosfp_context_t *libosfp_context, Packet *p)
libosfp_result_t result;
libosfp_fingerprint_t fp;
printf("Example fingerprint match: --------------------------\n");
// fingerprinting
printf("Example fingerprint detect: --------------------------\n");
memset(&fp, 0, sizeof(libosfp_fingerprint_t));
ret = libosfp_fingerprinting(iph, tcph, &fp);
if (ret != 0) {
printf("libosfp fingerprinting failed\n");
@@ -488,20 +484,31 @@ void example_fingerprint_match(libosfp_context_t *libosfp_context, Packet *p)
}
libosfp_fingerprint_to_json_buf(&fp, str_buf, sizeof(str_buf));
fprintf(stdout, "%s\n", str_buf);
printf("%s\n", str_buf);
ret = libosfp_score_db_score(libosfp_context, &fp, &result);
// output fingerprint with connection info line
if (fingerprinting_output_fp) {
fprintf(fingerprinting_output_fp, "Connection info: %s:%d -> %s:%d\n", p->srcip, p->sp, p->dstip, p->dp);
fprintf(fingerprinting_output_fp, "%s\n", str_buf);
fflush(fingerprinting_output_fp);
}
// score
memset(&result, 0, sizeof(libosfp_result_t));
ret = libosfp_score_db_score(libosfp_context->score_db, 0, &fp, &result.score);
if (ret != 0) {
printf("libosfp fingerprint score failed, error: %d\n", ret);
goto exit;
}
printf("Connection info: %s\n", "");
printf("Connection info: %s:%d -> %s:%d\n", p->srcip, p->sp, p->dstip, p->dp);
printf("Most likely os class: %s\n", libosfp_result_likely_os_class_name_get(&result));
printf("Likely score: %u/100\n", libosfp_result_likely_os_class_score_get(&result));
printf("Likely score: %u/100\n", result.score.likely_score);
libosfp_result_to_buf(&result, str_buf, sizeof(str_buf));
fprintf(stdout, "%s\n", str_buf);
printf("Details:\n");
if (libosfp_result_to_buf(&result, str_buf, sizeof(str_buf))) {
printf("%s", str_buf);
}
exit:
return;
@@ -524,9 +531,19 @@ void process_packet(char *user, struct pcap_pkthdr *h, u_char *pkt)
goto exit;
}
example_header_match(libosfp_context, p);
if (p->iph) {
PrintInet(AF_INET, (const void *)&(p->src.addr_data32[0]), p->srcip, sizeof(p->srcip));
PrintInet(AF_INET, (const void *)&(p->dst.addr_data32[0]), p->dstip, sizeof(p->dstip));
} else if (p->ip6h) {
PrintInet(AF_INET6, (const void *)&(p->src.address), p->srcip, sizeof(p->srcip));
PrintInet(AF_INET6, (const void *)&(p->dst.address), p->dstip, sizeof(p->dstip));
}
example_fingerprint_match(libosfp_context, p);
// fingerprint detect example for libosfp developer
example_detect_fingerprint(libosfp_context, p);
// tcp/ip header detect example for user
example_detect(libosfp_context, p);
printf("--------------------------- processed packet count %d\n", ++processed_packet);
@@ -538,14 +555,14 @@ int main(int argc, char *argv[])
{
int r;
while ((r = getopt(argc, argv, "+f:i:r:")) != -1) {
while ((r = getopt(argc, argv, "+f:i:r:o:")) != -1) {
switch(r) {
case 'f':
if (fp_file) {
if (fp_file_path) {
printf("Multiple -f options not supported.\n");
exit(1);
}
fp_file = (unsigned char*)optarg;
fp_file_path = (unsigned char*)optarg;
break;
case 'i':
if (if_name) {
@@ -561,6 +578,13 @@ int main(int argc, char *argv[])
}
pcap_file_name = (unsigned char*)optarg;
break;
case 'o':
if (fp_output_file_path) {
printf("Multiple -o options not supported.\n");
exit(1);
}
fp_output_file_path = (unsigned char*)optarg;
break;
default:
usage();
break;
@@ -576,6 +600,15 @@ int main(int argc, char *argv[])
}
}
// fingerprinting out file create
if (fp_output_file_path) {
fingerprinting_output_fp = fopen(fp_output_file_path, "a+");
if (!fingerprinting_output_fp) {
printf("No such file: %s\n", fp_output_file_path);
exit(1);
}
}
// prepare pcap handle
char pcap_err[PCAP_ERRBUF_SIZE];
@@ -621,13 +654,14 @@ int main(int argc, char *argv[])
link_type = pcap_datalink(pcap_handle);
// create libosfp context
if (fp_file == NULL) {
fp_file = DEFAULT_FP_FILE;
if (fp_file_path == NULL) {
fp_file_path = DEFAULT_FP_FILE_PATH;
}
libosfp_context_t *libosfp_context = libosfp_context_create(fp_file);
//libosfp_context_t *libosfp_context = libosfp_context_create(fp_file_path);
libosfp_context_t *libosfp_context = libosfp_context_create(NULL);
if (libosfp_context == NULL) {
printf("could not create libosfp context. fingerprints file: %s\n", fp_file);
printf("could not create libosfp context. fingerprints file: %s\n", fp_file_path);
exit(1);
}
@@ -635,9 +669,12 @@ int main(int argc, char *argv[])
r = libosfp_context_setup(libosfp_context);
if (r != LIBOSFP_NOERR) {
printf("could not setup libosfp context. error: %d\n", LIBOSFP_NOERR);
libosfp_context_destroy(libosfp_context);
exit(1);
}
libosfp_score_db_debug_print(libosfp_context->score_db);
// loop
while (1) {
int r = pcap_dispatch(pcap_handle, 0, (pcap_handler)process_packet, (void*)libosfp_context);
@@ -647,7 +684,7 @@ int main(int argc, char *argv[])
}
}
// create libosfp context
// destroy libosfp context
libosfp_context_destroy(libosfp_context);
return 0;

72594
fp.json Normal file

File diff suppressed because it is too large Load Diff

38
gen_c.sh Executable file
View File

@@ -0,0 +1,38 @@
#!/bin/bash
which jq >& /dev/null || (echo "error: ${0} require system command \"jq\"." && exit)
DEFAULT_FINGERPRINTS=$1
if [[ ${DEFAULT_FINGERPRINTS} == "" ]]; then
DEFAULT_FINGERPRINTS="./fp.json"
fi
C_FILE_PATH=$2
if [[ ${DEFAULT_FILE_PATH} == "" ]]; then
C_FILE_PATH=src
fi
C_INCLUDE_FILE="${C_FILE_PATH}/libosfp_default_fingerprints.h"
C_SOURCE_FILE="${C_FILE_PATH}/libosfp_default_fingerprints.c"
cat > ${C_INCLUDE_FILE} <<EOF
// File generated by gen_c.sh
#ifndef _LIBOSFP_DEFAULT_FINGERPRINTS_H__
#define _LIBOSFP_DEFAULT_FINGERPRINTS_H__
extern const char *g_default_fingerprints;
#endif
EOF
cat > ${C_SOURCE_FILE} <<EOF
// File generated by gen_c.sh
const char *g_default_fingerprints =
EOF
jq -c . ${DEFAULT_FINGERPRINTS} | jq -R >> ${C_SOURCE_FILE}
cat >> ${C_SOURCE_FILE} <<EOF
;
EOF

View File

@@ -9,10 +9,16 @@ libosfp_la_SOURCES = \
utstring.h \
cJSON.h \
cJSON.c \
libosfp_common.h \
libosfp_common.c \
libosfp_default_fingerprints.h \
libosfp_default_fingerprints.c \
libosfp.h \
libosfp.c \
libosfp_fingerprint.h \
libosfp_fingerprint.c \
libosfp_log.h \
libosfp_log.c \
libosfp_score_db.h \
libosfp_score_db.c

View File

@@ -1,77 +1,8 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <malloc.h>
#include <linux/in.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/tcp.h>
#include "libosfp.h"
#include "libosfp_fingerprint.h"
#include "libosfp_score_db.h"
#include "libosfp_log.h"
#define LIBOSFP_OS_CLASS_NAME_WINDOWS "Windows"
#define LIBOSFP_OS_CLASS_NAME_LINUX "Linux"
#define LIBOSFP_OS_CLASS_NAME_MAC_OS "Mac OS"
#define LIBOSFP_OS_CLASS_NAME_IOS "iOS"
#define LIBOSFP_OS_CLASS_NAME_ANDROID "Android"
#define LIBOSFP_WRITE_STRING_TO_BUF(ret, buf, size, off, ...) do { \
ret = snprintf((char *)buf + off, \
size - off, \
__VA_ARGS__); \
if (ret >= 0) { \
if ( (off + ret) >= size) { \
off = size - 1; \
} else { \
off += ret; \
} \
} \
} while (0)
const char *os_class_name[LIBOSFP_OS_CLASS_MAX] = {
LIBOSFP_OS_CLASS_NAME_WINDOWS,
LIBOSFP_OS_CLASS_NAME_LINUX,
LIBOSFP_OS_CLASS_NAME_MAC_OS,
LIBOSFP_OS_CLASS_NAME_IOS,
LIBOSFP_OS_CLASS_NAME_ANDROID
};
libosfp_os_class_id_t libosfp_os_class_name_to_id(char *name)
{
libosfp_os_class_id_t os_class;
if (0 == strncmp(name, LIBOSFP_OS_CLASS_NAME_WINDOWS, strlen(LIBOSFP_OS_CLASS_NAME_WINDOWS))) {
os_class = LIBOSFP_OS_CLASS_WINDOWS;
} else if (0 == strncmp(name, LIBOSFP_OS_CLASS_NAME_LINUX, strlen(LIBOSFP_OS_CLASS_NAME_LINUX))) {
os_class = LIBOSFP_OS_CLASS_Linux;
} else if (0 == strncmp(name, LIBOSFP_OS_CLASS_NAME_MAC_OS, strlen(LIBOSFP_OS_CLASS_NAME_MAC_OS))) {
os_class = LIBOSFP_OS_CLASS_MAC_OS;
} else if (0 == strncmp(name, LIBOSFP_OS_CLASS_NAME_IOS, strlen(LIBOSFP_OS_CLASS_NAME_IOS))) {
os_class = LIBOSFP_OS_CLASS_IOS;
} else if (0 == strncmp(name, LIBOSFP_OS_CLASS_NAME_ANDROID, strlen(LIBOSFP_OS_CLASS_NAME_ANDROID))) {
os_class = LIBOSFP_OS_CLASS_ANDROID;
} else {
os_class = LIBOSFP_OS_CLASS_MAX;
}
return os_class;
}
const char *libosfp_os_class_id_to_name(libosfp_os_class_id_t os_class)
{
if (os_class < 0 || os_class >= LIBOSFP_OS_CLASS_MAX) {
return NULL;
}
return os_class_name[os_class];
}
const char *libosfp_result_likely_os_class_name_get(libosfp_result_t *result)
{
libosfp_os_class_id_t os_class;
@@ -80,50 +11,45 @@ const char *libosfp_result_likely_os_class_name_get(libosfp_result_t *result)
return NULL;
}
os_class = result->likely_os_class;
os_class = result->score.likely_os_class;
if (os_class < 0 || os_class >= LIBOSFP_OS_CLASS_MAX) {
return NULL;
}
return os_class_name[os_class];
}
unsigned int libosfp_result_likely_os_class_score_get(libosfp_result_t *result)
{
if (result == NULL) {
return 0;
}
return result->likely_score;
return libosfp_os_class_id_to_name(os_class);
}
int libosfp_result_to_buf(libosfp_result_t *result, char *strbuf, unsigned int buf_len)
{
int ret, offset = 0, i;
libosfp_os_class_id_t likely_os_class;
if (result == NULL || strbuf == NULL || buf_len == 0) {
return 0;
}
likely_os_class = result->score.likely_os_class;
if (likely_os_class < 0 || likely_os_class >= LIBOSFP_OS_CLASS_MAX) {
return 0;
}
LIBOSFP_WRITE_STRING_TO_BUF(ret, strbuf, buf_len, offset,
"Most likely os class: %s\nLikely score: %u/100\n",
os_class_name[result->likely_os_class], result->likely_score);
LIBOSFP_WRITE_STRING_TO_BUF(ret, strbuf, buf_len, offset,"Details:\n");
libosfp_os_class_id_to_name(likely_os_class), result->score.likely_score);
for (i = 0; i < LIBOSFP_OS_CLASS_MAX; i++) {
LIBOSFP_WRITE_STRING_TO_BUF(ret, strbuf, buf_len, offset,"%s score: %u\n",
os_class_name[i], result->score.os_class_score[i]);
libosfp_os_class_id_to_name(i), result->score.os_class_score[i]);
}
exit:
return offset;
}
libosfp_error_code_t libosfp_header_match(libosfp_context_t *libosfp_context, unsigned char *ip_hdr, unsigned char *tcp_hdr, libosfp_result_t *result)
libosfp_error_code_t libosfp_detect(libosfp_context_t *libosfp_context, unsigned int flags, unsigned char *ip_hdr, unsigned char *tcp_hdr, libosfp_result_t *result)
{
int ret = LIBOSFP_EINVAL;
libosfp_fingerprint_t fp = {0};
libosfp_fingerprint_t fp;
if (libosfp_context == NULL || ip_hdr == NULL || tcp_hdr == NULL || result == NULL) {
goto exit;
@@ -134,7 +60,7 @@ libosfp_error_code_t libosfp_header_match(libosfp_context_t *libosfp_context, un
goto exit;
}
ret = libosfp_score_db_score(libosfp_context, &fp, result);
ret = libosfp_score_db_score(libosfp_context->score_db, flags, &fp, &result->score);
if (ret != 0) {
goto exit;
}
@@ -164,20 +90,22 @@ exit:
libosfp_context_t *libosfp_context_create(char *fp_file)
{
libosfp_context_t *libosfp_context = NULL;
libosfp_context_t *libosfp_context;
if (fp_file == NULL || 0 != access(fp_file, R_OK)) {
goto exit;
}
libosfp_context = malloc(sizeof(libosfp_context_t));
libosfp_context = calloc(1, sizeof(libosfp_context_t));
if (libosfp_context == NULL) {
goto exit;
}
libosfp_context->fp_file = strdup((const char*)fp_file);
if (libosfp_context->fp_file == NULL) {
goto exit;
if (fp_file != NULL) {
if (0 != access(fp_file, R_OK)) {
goto exit;
}
libosfp_context->fp_file = strdup((const char*)fp_file);
if (libosfp_context->fp_file == NULL) {
goto exit;
}
}
libosfp_context->score_db = (void *)libosfp_score_db_create();

View File

@@ -1,32 +1,10 @@
#ifndef __LIBOSFP_H__
#define __LIBOSFP_H__
typedef enum libosfp_error_code {
LIBOSFP_NOERR,
LIBOSFP_EINVAL,
LIBOSFP_ERR_READ_FILE,
LIBOSFP_ERR_PARSE_FILE,
} libosfp_error_code_t;
typedef enum libosfp_os_class_id {
LIBOSFP_OS_CLASS_WINDOWS,
LIBOSFP_OS_CLASS_Linux,
LIBOSFP_OS_CLASS_MAC_OS,
LIBOSFP_OS_CLASS_IOS,
LIBOSFP_OS_CLASS_ANDROID,
LIBOSFP_OS_CLASS_MAX,
} libosfp_os_class_id_t;
typedef struct libosfp_score {
unsigned int os_class_score[LIBOSFP_OS_CLASS_MAX];
} libosfp_score_t;
#include "libosfp_common.h"
typedef struct libosfp_result {
enum libosfp_error_code err;
enum libosfp_os_class_id likely_os_class; // top rated os class
unsigned int likely_score;
unsigned int perfect_score;
libosfp_score_t score;
libosfp_score_t score;
} libosfp_result_t;
typedef struct libosfp_context {
@@ -34,15 +12,10 @@ typedef struct libosfp_context {
void *score_db;
} libosfp_context_t;
libosfp_os_class_id_t libosfp_os_class_name_to_id(char *name);
const char *libosfp_os_class_id_to_name(libosfp_os_class_id_t os_class);
int libosfp_result_to_buf(libosfp_result_t *result, char *strbuf, unsigned int buf_len);
unsigned int libosfp_result_likely_os_class_score_get(libosfp_result_t *result);
const char *libosfp_result_likely_os_class_name_get(libosfp_result_t *result);
libosfp_error_code_t libosfp_header_match(libosfp_context_t *libosfp_context, unsigned char *ip_hdr, unsigned char *tcp_hdr, libosfp_result_t *result);
libosfp_error_code_t libosfp_detect(libosfp_context_t *libosfp_context, unsigned int flags, unsigned char *ip_hdr, unsigned char *tcp_hdr, libosfp_result_t *result);
libosfp_error_code_t libosfp_context_setup(libosfp_context_t *libosfp_context);
libosfp_context_t *libosfp_context_create(char *fp_file);
void libosfp_context_destroy(libosfp_context_t *libosfp_context);

36
src/libosfp_common.c Normal file
View File

@@ -0,0 +1,36 @@
#include "libosfp_common.h"
const char *os_class_name[LIBOSFP_OS_CLASS_MAX] = {
LIBOSFP_OS_CLASS_NAME_WINDOWS,
LIBOSFP_OS_CLASS_NAME_LINUX,
LIBOSFP_OS_CLASS_NAME_MAC_OS,
LIBOSFP_OS_CLASS_NAME_IOS,
LIBOSFP_OS_CLASS_NAME_ANDROID
};
libosfp_os_class_id_t libosfp_os_class_name_to_id(char *name)
{
libosfp_os_class_id_t os_class;
if (0 == strncmp(name, LIBOSFP_OS_CLASS_NAME_WINDOWS, strlen(LIBOSFP_OS_CLASS_NAME_WINDOWS))) {
os_class = LIBOSFP_OS_CLASS_WINDOWS;
} else if (0 == strncmp(name, LIBOSFP_OS_CLASS_NAME_LINUX, strlen(LIBOSFP_OS_CLASS_NAME_LINUX))) {
os_class = LIBOSFP_OS_CLASS_LINUX;
} else if (0 == strncmp(name, LIBOSFP_OS_CLASS_NAME_MAC_OS, strlen(LIBOSFP_OS_CLASS_NAME_MAC_OS))) {
os_class = LIBOSFP_OS_CLASS_MAC_OS;
} else if (0 == strncmp(name, LIBOSFP_OS_CLASS_NAME_IOS, strlen(LIBOSFP_OS_CLASS_NAME_IOS))) {
os_class = LIBOSFP_OS_CLASS_IOS;
} else if (0 == strncmp(name, LIBOSFP_OS_CLASS_NAME_ANDROID, strlen(LIBOSFP_OS_CLASS_NAME_ANDROID))) {
os_class = LIBOSFP_OS_CLASS_ANDROID;
} else {
os_class = LIBOSFP_OS_CLASS_MAX;
}
return os_class;
}
const char *libosfp_os_class_id_to_name(libosfp_os_class_id_t os_class)
{
return os_class_name[os_class];
}

142
src/libosfp_common.h Normal file
View File

@@ -0,0 +1,142 @@
#ifndef __LIBOSFP_COMMON_H__
#define __LIBOSFP_COMMON_H__
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <malloc.h>
#include <stdarg.h>
#include <time.h>
#include <linux/in.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/tcp.h>
#include <sys/fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "utarray.h"
#include "uthash.h"
#include "utlist.h"
#include "utringbuffer.h"
#include "utstack.h"
#include "utstring.h"
#include "cJSON.h"
#define LIBOSFP_OS_CLASS_NAME_WINDOWS "Windows"
#define LIBOSFP_OS_CLASS_NAME_LINUX "Linux"
#define LIBOSFP_OS_CLASS_NAME_MAC_OS "Mac OS"
#define LIBOSFP_OS_CLASS_NAME_IOS "iOS"
#define LIBOSFP_OS_CLASS_NAME_ANDROID "Android"
#define LIBOSFP_TCP_OPTLENMAX 64
#define LIBOSFP_TCP_OPTMAX 20
#define LIBOSFP_ETHERNET_HEADER_LEN 14
#define LIBOSFP_VLAN_HEADER_LEN 4
#define LIBOSFP_IPV4_HEADER_LEN 20
#define LIBOSFP_IPV6_HEADER_LEN 40
#define LIBOSFP_TCP_HEADER_LEN 20
//# TCP Options (opt_type) - http://www.iana.org/assignments/tcp-parameters
#define LIBOSFP_TCP_OPT_EOL 0 //# end of option list
#define LIBOSFP_TCP_OPT_NOP 1 //# no operation
#define LIBOSFP_TCP_OPT_MSS 2 //# maximum segment size
#define LIBOSFP_TCP_OPT_WSCALE 3 //# window scale factor, RFC 1072
#define LIBOSFP_TCP_OPT_SACKOK 4 //# SACK permitted, RFC 2018
#define LIBOSFP_TCP_OPT_SACK 5 //# SACK, RFC 2018
#define LIBOSFP_TCP_OPT_ECHO 6 //# echo (obsolete), RFC 1072
#define LIBOSFP_TCP_OPT_ECHOREPLY 7 //# echo reply (obsolete), RFC 1072
#define LIBOSFP_TCP_OPT_TIMESTAMP 8 //# timestamps, RFC 1323
#define LIBOSFP_TCP_OPT_POCONN 9 //# partial order conn, RFC 1693
#define LIBOSFP_TCP_OPT_POSVC 10 //# partial order service, RFC 1693
#define LIBOSFP_TCP_OPT_CC 11 //# connection count, RFC 1644
#define LIBOSFP_TCP_OPT_CCNEW 12 //# CC.NEW, RFC 1644
#define LIBOSFP_TCP_OPT_CCECHO 13 //# CC.ECHO, RFC 1644
#define LIBOSFP_TCP_OPT_ALTSUM 14 //# alt checksum request, RFC 1146
#define LIBOSFP_TCP_OPT_ALTSUMDATA 15 //# alt checksum data, RFC 1146
#define LIBOSFP_TCP_OPT_SKEETER 16 //# Skeeter
#define LIBOSFP_TCP_OPT_BUBBA 17 //# Bubba
#define LIBOSFP_TCP_OPT_TRAILSUM 18 //# trailer checksum
#define LIBOSFP_TCP_OPT_MD5 19 //# MD5 signature, RFC 2385
#define LIBOSFP_TCP_OPT_SCPS 20 //# SCPS capabilities
#define LIBOSFP_TCP_OPT_SNACK 21 //# selective negative acks
#define LIBOSFP_TCP_OPT_REC 22 //# record boundaries
#define LIBOSFP_TCP_OPT_CORRUPT 23 //# corruption experienced
#define LIBOSFP_TCP_OPT_SNAP 24 //# SNAP
#define LIBOSFP_TCP_OPT_TCPCOMP 26 //# TCP compression filter
#define LIBOSFP_TCP_OPT_MAX 27 //# Quick-Start Response
#define LIBOSFP_TCP_OPT_USRTO 28 //# User Timeout Option (also, other known unauthorized use) [***][1] [RFC5482]
#define LIBOSFP_TCP_OPT_AUTH 29 //# TCP Authentication Option (TCP-AO) [RFC5925]
#define LIBOSFP_TCP_OPT_MULTIPATH 30 //# Multipath TCP (MPTCP)
#define LIBOSFP_TCP_OPT_FASTOPEN 34 //# TCP Fast Open Cookie [RFC7413]
#define LIBOSFP_TCP_OPY_ENCNEG 69 //# Encryption Negotiation (TCP-ENO) [RFC8547]
#define LIBOSFP_TCP_OPT_EXP1 253 //# RFC3692-style Experiment 1 (also improperly used for shipping products)
#define LIBOSFP_TCP_OPT_EXP2 254 //# RFC3692-style Experiment 2 (also improperly used for shipping products)
#define LIBOSFP_TCP_OPT_SACKOK_LEN 2
#define LIBOSFP_TCP_OPT_WS_LEN 3
#define LIBOSFP_TCP_OPT_TS_LEN 10
#define LIBOSFP_TCP_OPT_MSS_LEN 4
#define LIBOSFP_TCP_OPT_SACK_MIN_LEN 10 /* hdr 2, 1 pair 8 = 10 */
#define LIBOSFP_TCP_OPT_SACK_MAX_LEN 34 /* hdr 2, 4 pair 32= 34 */
#define LIBOSFP_TCP_OPT_TFO_MIN_LEN 4 /* kind, len, 2 bytes cookie: 4 */
#define LIBOSFP_TCP_OPT_TFO_MAX_LEN 18 /* kind, len, 18 */
#define LIBOSFP_WRITE_STRING_TO_BUF(ret, buf, size, off, ...) do { \
ret = snprintf((char *)buf + off, \
size - off, \
__VA_ARGS__); \
if (ret >= 0) { \
if ( (off + ret) >= size) { \
off = size - 1; \
} else { \
off += ret; \
} \
} \
} while (0)
#define LIBOSFP_BIT_U32(n) (1UL << (n))
typedef enum libosfp_error_code {
LIBOSFP_NOERR,
LIBOSFP_EINVAL,
LIBOSFP_ENOMEM,
LIBOSFP_ERR_SCORE_DB_READ_FILE,
LIBOSFP_ERR_SCORE_DB_PARSE_FILE,
LIBOSFP_ERR_SCORE_DB_UNSUPPORTED,
LIBOSFP_ERR_FINGERPRINTING_UNSUPPORTED,
} libosfp_error_code_t;
typedef enum libosfp_os_class_id {
LIBOSFP_OS_CLASS_WINDOWS,
LIBOSFP_OS_CLASS_LINUX,
LIBOSFP_OS_CLASS_MAC_OS,
LIBOSFP_OS_CLASS_IOS,
LIBOSFP_OS_CLASS_ANDROID,
LIBOSFP_OS_CLASS_MAX,
} libosfp_os_class_id_t;
#define LIBOSFP_OS_CLASS_FLAG_WINDOWS LIBOSFP_BIT_U32(LIBOSFP_OS_CLASS_WINDOWS)
#define LIBOSFP_OS_CLASS_FLAG_LINUX LIBOSFP_BIT_U32(LIBOSFP_OS_CLASS_LINUX)
#define LIBOSFP_OS_CLASS_FLAG_MAC_OS LIBOSFP_BIT_U32(LIBOSFP_OS_CLASS_MAC_OS)
#define LIBOSFP_OS_CLASS_FLAG_IOS LIBOSFP_BIT_U32(LIBOSFP_OS_CLASS_IOS)
#define LIBOSFP_OS_CLASS_FLAG_ANDROID LIBOSFP_BIT_U32(LIBOSFP_OS_CLASS_ANDROID)
typedef struct libosfp_score {
unsigned int likely_os_class;
unsigned int likely_score;
unsigned int os_class_score[LIBOSFP_OS_CLASS_MAX];
} libosfp_score_t;
libosfp_os_class_id_t libosfp_os_class_name_to_id(char *name);
const char *libosfp_os_class_id_to_name(libosfp_os_class_id_t os_class);
#endif

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,5 @@
// File generated by gen_c.sh
#ifndef _LIBOSFP_DEFAULT_FINGERPRINTS_H__
#define _LIBOSFP_DEFAULT_FINGERPRINTS_H__
extern const char *g_default_fingerprints;
#endif

View File

@@ -1,25 +1,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <malloc.h>
#include <linux/in.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/tcp.h>
#include "cJSON.h"
#include "libosfp.h"
#include "libosfp_common.h"
#include "libosfp_fingerprint.h"
#include "libosfp_log.h"
#define LIBOSFP_ETHERNET_HEADER_LEN 14
#define LIBOSFP_VLAN_HEADER_LEN 4
#define LIBOSFP_IPV4_HEADER_LEN 20
#define LIBOSFP_IPV6_HEADER_LEN 40
#define LIBOSFP_TCP_HEADER_LEN 20
#define LIBOSFP_FINGERPRINT_FIELD_NAME_IP_ID "ip_id"
#define LIBOSFP_FINGERPRINT_FIELD_NAME_IP_TOS "ip_tos"
@@ -36,6 +18,7 @@
#define LIBOSFP_FINGERPRINT_FIELD_NAME_TCP_OPTIONS_ORDERED "tcp_options_ordered"
#define LIBOSFP_FINGERPRINT_FIELD_NAME_OS "os"
#define LIBOSFP_FINGERPRINT_DEFAULT_OS_CLASS_NAME "LIBOSFP_UNKNOWN"
typedef struct libosfp_tcp_opt {
unsigned char type;
@@ -98,7 +81,7 @@ static unsigned int compute_ip_ttl(unsigned int ip_ttl)
ip_ttl = 64;
} else if (ip_ttl > 64 && ip_ttl <= 128) {
ip_ttl = 128;
} else if (ip_ttl > 128) {
} else {
ip_ttl = 255;
}
return ip_ttl;
@@ -109,11 +92,11 @@ static unsigned int decode_tcp_options(libosfp_tcp_opt_t *tcp_opts, unsigned int
unsigned int offset = 0;
unsigned int tcp_opt_cnt = 0;
while (offset < len && tcp_opt_cnt < max_opt_cnt) {
unsigned char type;
unsigned char olen;
unsigned char *odata;
unsigned char type;
unsigned char olen;
unsigned char *odata;
while (offset < len && tcp_opt_cnt < max_opt_cnt) {
type = *(data + offset);
if (type == LIBOSFP_TCP_OPT_EOL || type == LIBOSFP_TCP_OPT_NOP) {
@@ -217,15 +200,9 @@ void libosfp_fingerprint_setup_field(libosfp_fingerprint_t *fp, libosfp_field_id
}
}
void libosfp_fingerprinting_tcp_option(unsigned char *pkt, unsigned int pktlen, libosfp_fingerprint_t *fp)
void libosfp_fingerprinting_tcp_option(unsigned char *opt_data, unsigned int opt_len, libosfp_fingerprint_t *fp)
{
int ret,i;
char options[LIBOSFP_TCP_OPTLENMAX];
char options_ordered[LIBOSFP_TCP_OPTLENMAX];
unsigned int maxoffset = sizeof(options) - 3;
unsigned int ordered_maxoffset = sizeof(options_ordered) - 1;
unsigned int offset = 0;
unsigned int ordered_offset = 0;
unsigned int tcp_mss;
unsigned int tcp_ws;
@@ -233,7 +210,14 @@ void libosfp_fingerprinting_tcp_option(unsigned char *pkt, unsigned int pktlen,
unsigned int tcp_opt_cnt;
libosfp_tcp_opt_t tcp_opts[LIBOSFP_TCP_OPTMAX];
tcp_opt_cnt = decode_tcp_options(tcp_opts, LIBOSFP_TCP_OPTMAX, pkt, pktlen);
char options[LIBOSFP_TCP_OPTLENMAX];
char options_ordered[LIBOSFP_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;
tcp_opt_cnt = decode_tcp_options(tcp_opts, LIBOSFP_TCP_OPTMAX, opt_data, opt_len);
for (i = 0; i < tcp_opt_cnt && offset < maxoffset && ordered_offset < ordered_maxoffset; i++) {
libosfp_tcp_opt_t *opt = &tcp_opts[i];
@@ -324,7 +308,7 @@ int libosfp_fingerprinting_tcp(struct tcphdr *tcph, libosfp_fingerprint_t *fp)
// tcp options
if (tcp_off > LIBOSFP_TCP_HEADER_LEN) {
libosfp_fingerprinting_tcp_option((unsigned char *)tcph + LIBOSFP_TCP_HEADER_LEN, tcp_off - LIBOSFP_TCP_HEADER_LEN, fp);
libosfp_fingerprinting_tcp_option((unsigned char *)tcph + LIBOSFP_TCP_HEADER_LEN, 20 + tcp_off - LIBOSFP_TCP_HEADER_LEN, fp);
}
return 0;
@@ -376,7 +360,8 @@ exit:
int libosfp_fingerprinting(unsigned char *iph, unsigned char *tcph, libosfp_fingerprint_t *fp)
{
int ret, ip_version;
int ret = LIBOSFP_EINVAL;
int ip_version;
if (iph == NULL || tcph == NULL || fp == NULL) {
goto exit;
@@ -407,7 +392,7 @@ int libosfp_fingerprinting(unsigned char *iph, unsigned char *tcph, libosfp_fing
goto exit;
}
libosfp_fingerprint_setup_field(fp, LIBOSFP_FIELD_OS, "", strlen("") + 1);
libosfp_fingerprint_setup_field(fp, LIBOSFP_FIELD_OS, LIBOSFP_FINGERPRINT_DEFAULT_OS_CLASS_NAME, strlen(LIBOSFP_FINGERPRINT_DEFAULT_OS_CLASS_NAME) + 1);
return 0;
exit:

View File

@@ -1,59 +1,8 @@
#ifndef __LIBOSFP_FINGERPRINT_H__
#define __LIBOSFP_FINGERPRINT_H__
#include "libosfp.h"
#define LIBOSFP_FINGERPRINT_VALUE_BUFFER_MAX 128
#define LIBOSFP_TCP_OPTLENMAX 64
#define LIBOSFP_TCP_OPTMAX 20
//# TCP Options (opt_type) - http://www.iana.org/assignments/tcp-parameters
#define LIBOSFP_TCP_OPT_EOL 0 //# end of option list
#define LIBOSFP_TCP_OPT_NOP 1 //# no operation
#define LIBOSFP_TCP_OPT_MSS 2 //# maximum segment size
#define LIBOSFP_TCP_OPT_WSCALE 3 //# window scale factor, RFC 1072
#define LIBOSFP_TCP_OPT_SACKOK 4 //# SACK permitted, RFC 2018
#define LIBOSFP_TCP_OPT_SACK 5 //# SACK, RFC 2018
#define LIBOSFP_TCP_OPT_ECHO 6 //# echo (obsolete), RFC 1072
#define LIBOSFP_TCP_OPT_ECHOREPLY 7 //# echo reply (obsolete), RFC 1072
#define LIBOSFP_TCP_OPT_TIMESTAMP 8 //# timestamps, RFC 1323
#define LIBOSFP_TCP_OPT_POCONN 9 //# partial order conn, RFC 1693
#define LIBOSFP_TCP_OPT_POSVC 10 //# partial order service, RFC 1693
#define LIBOSFP_TCP_OPT_CC 11 //# connection count, RFC 1644
#define LIBOSFP_TCP_OPT_CCNEW 12 //# CC.NEW, RFC 1644
#define LIBOSFP_TCP_OPT_CCECHO 13 //# CC.ECHO, RFC 1644
#define LIBOSFP_TCP_OPT_ALTSUM 14 //# alt checksum request, RFC 1146
#define LIBOSFP_TCP_OPT_ALTSUMDATA 15 //# alt checksum data, RFC 1146
#define LIBOSFP_TCP_OPT_SKEETER 16 //# Skeeter
#define LIBOSFP_TCP_OPT_BUBBA 17 //# Bubba
#define LIBOSFP_TCP_OPT_TRAILSUM 18 //# trailer checksum
#define LIBOSFP_TCP_OPT_MD5 19 //# MD5 signature, RFC 2385
#define LIBOSFP_TCP_OPT_SCPS 20 //# SCPS capabilities
#define LIBOSFP_TCP_OPT_SNACK 21 //# selective negative acks
#define LIBOSFP_TCP_OPT_REC 22 //# record boundaries
#define LIBOSFP_TCP_OPT_CORRUPT 23 //# corruption experienced
#define LIBOSFP_TCP_OPT_SNAP 24 //# SNAP
#define LIBOSFP_TCP_OPT_TCPCOMP 26 //# TCP compression filter
#define LIBOSFP_TCP_OPT_MAX 27 //# Quick-Start Response
#define LIBOSFP_TCP_OPT_USRTO 28 //# User Timeout Option (also, other known unauthorized use) [***][1] [RFC5482]
#define LIBOSFP_TCP_OPT_AUTH 29 //# TCP Authentication Option (TCP-AO) [RFC5925]
#define LIBOSFP_TCP_OPT_MULTIPATH 30 //# Multipath TCP (MPTCP)
#define LIBOSFP_TCP_OPT_FASTOPEN 34 //# TCP Fast Open Cookie [RFC7413]
#define LIBOSFP_TCP_OPY_ENCNEG 69 //# Encryption Negotiation (TCP-ENO) [RFC8547]
#define LIBOSFP_TCP_OPT_EXP1 253 //# RFC3692-style Experiment 1 (also improperly used for shipping products)
#define LIBOSFP_TCP_OPT_EXP2 254 //# RFC3692-style Experiment 2 (also improperly used for shipping products)
#define LIBOSFP_TCP_OPT_SACKOK_LEN 2
#define LIBOSFP_TCP_OPT_WS_LEN 3
#define LIBOSFP_TCP_OPT_TS_LEN 10
#define LIBOSFP_TCP_OPT_MSS_LEN 4
#define LIBOSFP_TCP_OPT_SACK_MIN_LEN 10 /* hdr 2, 1 pair 8 = 10 */
#define LIBOSFP_TCP_OPT_SACK_MAX_LEN 34 /* hdr 2, 4 pair 32= 34 */
#define LIBOSFP_TCP_OPT_TFO_MIN_LEN 4 /* kind, len, 2 bytes cookie: 4 */
#define LIBOSFP_TCP_OPT_TFO_MAX_LEN 18 /* kind, len, 18 */
typedef enum libosfp_field_id {
LIBOSFP_FIELD_IP_ID,
LIBOSFP_FIELD_IP_TOS,
@@ -99,8 +48,13 @@ char *libosfp_fingerprint_get_field_name(libosfp_field_id_t field_id);
unsigned int libosfp_fingerprint_get_field_enabled(libosfp_field_id_t field_id);
unsigned int libosfp_fingerprint_get_field_importance(libosfp_field_id_t field_id);
unsigned int libosfp_fingerprint_get_field_type(libosfp_field_id_t field_id);
int libosfp_fingerprint_to_json_buf(libosfp_fingerprint_t *fp, char *strbuf, unsigned int buf_len);
void libosfp_fingerprint_setup_field(libosfp_fingerprint_t *fp, libosfp_field_id_t field_id, void *value, unsigned int len);
void libosfp_fingerprinting_tcp_option(unsigned char *pkt, unsigned int pktlen, libosfp_fingerprint_t *fp);
int libosfp_fingerprinting_tcp(struct tcphdr *tcph, libosfp_fingerprint_t *fp);
int libosfp_fingerprinting_ipv4(struct iphdr *iph, libosfp_fingerprint_t *fp);
int libosfp_fingerprinting_ipv6(struct ipv6hdr *iph, libosfp_fingerprint_t *fp);
int libosfp_fingerprinting(unsigned char *iphdr, unsigned char *tcphdr, libosfp_fingerprint_t *fp);
#endif

View File

@@ -1,9 +1,4 @@
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <time.h>
#include "libosfp.h"
#include "libosfp_common.h"
#include "libosfp_log.h"
/* The maximum length of the log message */
@@ -24,22 +19,22 @@ void libosfp_log_message(unsigned int x, const char *file, const int line, const
switch (x) {
case LIBOSFP_LOG_LEVEL_DEBUG:
snprintf(buffer, sizeof(buffer), "[%s][DEBUG][%s:%d %s] %s", log_time_buf, file, line, func, msg);
snprintf(buffer, sizeof(buffer), "[%s][DEBUG][%s:%d %s] %s\n", log_time_buf, file, line, func, msg);
break;
case LIBOSFP_LOG_LEVEL_INFO:
snprintf(buffer, sizeof(buffer), "[%s][INFO][%s:%d %s] %s", log_time_buf, file, line, func, msg);
snprintf(buffer, sizeof(buffer), "[%s][INFO][%s:%d %s] %s\n", log_time_buf, file, line, func, msg);
break;
case LIBOSFP_LOG_LEVEL_WARNING:
snprintf(buffer, sizeof(buffer), "[%s][WARN][%s:%d %s] %s", log_time_buf, file, line, func, msg);
snprintf(buffer, sizeof(buffer), "[%s][WARN][%s:%d %s] %s\n", log_time_buf, file, line, func, msg);
break;
case LIBOSFP_LOG_LEVEL_ERROR:
snprintf(buffer, sizeof(buffer), "[%s][ERROR][%s:%d %s] %s", log_time_buf, file, line, func, msg);
snprintf(buffer, sizeof(buffer), "[%s][ERROR][%s:%d %s] %s\n", log_time_buf, file, line, func, msg);
break;
}
}
void libosfp_log(unsigned int x, const char *file, const char *func, const int line, const char *fmt, ...)
void libosfp_log(unsigned int x, const char *file, const int line, const char *func, const char *fmt, ...)
{
if (libosfp_log_level >= x ) {
char msg[LIBOSFP_MAX_LOG_MSG_LEN];

View File

@@ -8,13 +8,17 @@ typedef enum libosfp_log_level {
LIBOSFP_LOG_LEVEL_ERROR
} libosfp_log_level_t;
#ifndef DEBUG
#define libosfp_log_debug(...) do { } while (0)
#else
#define libosfp_log_debug(...) libosfp_log(LIBOSFP_LOG_LEVEL_DEBUG, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
#endif
#define libosfp_log_info(...) libosfp_log(LIBOSFP_LOG_LEVEL_INFO, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
#define libosfp_log_warning(...) libosfp_log(LIBOSFP_LOG_LEVEL_WARNING, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
#define libosfp_log_error(...) libosfp_log(LIBOSFP_LOG_LEVEL_ERROR, __FILE__, __LINE__, __FUNCTION__,__VA_ARGS__)
void libosfp_log_level_set(libosfp_log_level_t level);
void libosfp_log(unsigned int x, const char *file, const char *func, const int line, const char *fmt, ...);
void libosfp_log(unsigned int x, const char *file, const int line, const char *func, const char *fmt, ...);
#endif

View File

@@ -1,26 +1,12 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <malloc.h>
#include "libosfp_common.h"
#include <linux/in.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/tcp.h>
#include <sys/fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "uthash.h"
#include "cJSON.h"
#include "libosfp.h"
#include "libosfp_fingerprint.h"
#include "libosfp_default_fingerprints.h"
#include "libosfp_score_db.h"
#include "libosfp_log.h"
#define LIBOSFP_PERCENTILE 100
#define LIBOSFP_SCORE_DB_FIELD_UINT_VALUE_MAX 65536
typedef struct libosfp_score_db_array_data {
@@ -353,25 +339,34 @@ exit:
int libosfp_score_db_load(libosfp_score_db_t *score_db, char *fp_file)
{
int ret = LIBOSFP_EINVAL, i;
char *file_buffer;
const char *file_buffer;
libosfp_field_score_db_t *field_score_db;
cJSON *root = NULL;
cJSON *entry = NULL;
if (score_db == NULL || fp_file == NULL) {
if (score_db == NULL) {
goto exit;
}
file_buffer = libosfp_score_db_read_file(fp_file);
if (file_buffer == NULL) {
ret = LIBOSFP_ERR_READ_FILE;
goto exit;
if (fp_file == NULL) {
file_buffer = g_default_fingerprints;
} else {
file_buffer = (const char *)libosfp_score_db_read_file(fp_file);
if (file_buffer == NULL) {
ret = LIBOSFP_ERR_SCORE_DB_READ_FILE;
goto exit;
}
}
root = cJSON_Parse(file_buffer);
if (file_buffer != g_default_fingerprints) {
free((char*)file_buffer);
}
if (root == NULL) {
ret = LIBOSFP_ERR_PARSE_FILE;
ret = LIBOSFP_ERR_SCORE_DB_PARSE_FILE;
goto exit;
}
@@ -389,7 +384,7 @@ int libosfp_score_db_load(libosfp_score_db_t *score_db, char *fp_file)
if (entry) {
ret = libosfp_score_db_load_entry(score_db, entry);
if (ret != 0) {
printf("json entry load failed.\n%s\n", cJSON_Print(entry));
libosfp_log_debug("json entry load failed.\n%s\n", cJSON_Print(entry));
continue;
}
}
@@ -397,54 +392,58 @@ int libosfp_score_db_load(libosfp_score_db_t *score_db, char *fp_file)
cJSON_Delete(root);
return 0;
return LIBOSFP_NOERR;
exit:
return ret;
}
int libosfp_score_db_score(libosfp_context_t *libosfp_context, libosfp_fingerprint_t *fp, libosfp_result_t *result)
int libosfp_score_db_score(libosfp_score_db_t *score_db, unsigned int flags, libosfp_fingerprint_t *fp, libosfp_score_t *result_score)
{
int ret = -1, i, j;
void *field_value;
int ret = LIBOSFP_EINVAL, i, j;
unsigned int os_class_score;
unsigned int likely_score;
unsigned int perfect_score;
unsigned int entry_count;
unsigned int importance;
unsigned int field_len;
libosfp_score_t *score;
libosfp_score_db_t *score_db;
libosfp_score_t *matched_score;
libosfp_os_class_id_t likely_os_class;
libosfp_fingerprint_field_t *field;
libosfp_field_score_db_t *field_score_db;
if (libosfp_context == NULL || fp == NULL || result == NULL) {
if (score_db == NULL || fp == NULL || result_score == NULL) {
goto exit;
}
memset(result, 0, sizeof(libosfp_result_t));
memset(result_score, 0, sizeof(libosfp_score_t));
score_db = (libosfp_score_db_t*)libosfp_context->score_db;
perfect_score = score_db->perfect_score;
if (perfect_score == 0) {
goto exit;
}
for (i = 0; i < LIBOSFP_FIELD_MAX; i++) {
if (!fp->fields[i].enabled) {
continue;
}
field_score_db = &score_db->field_score_dbs[i];
if (!field_score_db->enabled) {
continue;
}
field_value = fp->fields[i].value;
field_len = fp->fields[i].value_len;
field = &fp->fields[i];
if (!field->enabled) {
continue;
}
score = libosfp_score_db_filed_match(field_score_db, field_value, field_len);
if (score == NULL) {
matched_score = libosfp_score_db_filed_match(field_score_db, field->value, field->value_len);
if (matched_score == NULL) {
continue;
}
importance = libosfp_fingerprint_get_field_importance(i);
for (j = 0; j < LIBOSFP_OS_CLASS_MAX; j++) {
result->score.os_class_score[j] += score->os_class_score[j] * importance;
if (0 == flags || flags & LIBOSFP_BIT_U32(j)) {
result_score->os_class_score[j] += matched_score->os_class_score[j] * importance / perfect_score;
}
}
if (i == LIBOSFP_FIELD_TCP_OPTIONS) {
@@ -452,66 +451,103 @@ int libosfp_score_db_score(libosfp_context_t *libosfp_context, libosfp_fingerpri
}
}
likely_score = result_score->likely_score;
likely_os_class = result_score->likely_os_class;
perfect_score = score_db->perfect_score;
result->perfect_score = perfect_score;
for (j = 0; j < LIBOSFP_OS_CLASS_MAX; j++) {
entry_count = score_db->os_class_entry_count[j];
os_class_score = result->score.os_class_score[j];
for (i = 0; i < LIBOSFP_OS_CLASS_MAX; i++) {
entry_count = score_db->os_class_entry_count[i];
os_class_score = result_score->os_class_score[i];
if (entry_count == 0 || perfect_score == 0) {
continue;
}
os_class_score = 100 * os_class_score / entry_count;
os_class_score = (unsigned int)((float)os_class_score / (float)perfect_score);
// calc percentile score
os_class_score = (LIBOSFP_PERCENTILE * os_class_score) / entry_count;
if (result->likely_score < os_class_score) {
result->likely_score = os_class_score;
result->likely_os_class = j;
// calc likely os class and score
if (likely_score < os_class_score) {
likely_score = os_class_score;
likely_os_class = i;
}
result->score.os_class_score[j] = os_class_score;
result_score->os_class_score[i] = os_class_score;
}
return 0;
result_score->likely_score = likely_score;
result_score->likely_os_class = likely_os_class;
return LIBOSFP_NOERR;
exit:
return ret;
}
void libosfp_score_db_debug_print(libosfp_score_db_t *score_db)
{
int i;
printf("score_db:\n");
printf("entry_count: %u\n", score_db->entry_count);
printf("perfect_score: %u\n", score_db->perfect_score);
for (i = 0; i < LIBOSFP_OS_CLASS_MAX; i++) {
const char *name = libosfp_os_class_id_to_name(i);
printf("os class %p ", name);
printf("entry_count: %u\n", score_db->os_class_entry_count[i]);
printf("os class %s entry_count: %u\n", libosfp_os_class_id_to_name(i), score_db->os_class_entry_count[i]);
}
for (i = 0; i < LIBOSFP_FIELD_MAX; i++) {
printf("field %s enabled: %u\n", libosfp_fingerprint_get_field_name(i), score_db->field_score_dbs[i].enabled);
printf("field %s type: %u\n", libosfp_fingerprint_get_field_name(i), score_db->field_score_dbs[i].type);
printf("field %s entry_count: %u\n", libosfp_fingerprint_get_field_name(i), score_db->field_score_dbs[i].entry_count);
printf("field %s enabled: %p\n", libosfp_fingerprint_get_field_name(i), score_db->field_score_dbs[i].data);
}
}
libosfp_score_db_t *libosfp_score_db_create(void)
{
int ret = -1, i;
int i;
libosfp_score_db_t *score_db;
libosfp_field_score_db_t *db;
score_db = calloc(1, sizeof(libosfp_score_db_t));
if (score_db == NULL) {
goto exit;
}
for (i = 0; i < LIBOSFP_FIELD_MAX; i++) {
db = &score_db->field_score_dbs[i];
db->enabled = libosfp_fingerprint_get_field_enabled(i);
db->type = libosfp_fingerprint_get_field_type(i);
switch (score_db->field_score_dbs[i].type) {
db->enabled = libosfp_fingerprint_get_field_enabled(i);
if (!db->enabled) {
libosfp_log_warning("field disabled: %s", "");
continue;
}
db->type = libosfp_fingerprint_get_field_type(i);
switch (db->type) {
case LIBOSFP_FIELD_TYPE_UINT:
score_db->field_score_dbs[i].create = libosfp_score_db_array_create;
score_db->field_score_dbs[i].destroy = libosfp_score_db_array_destroy;
score_db->field_score_dbs[i].add = libosfp_score_db_array_add;
score_db->field_score_dbs[i].match = libosfp_score_db_array_match;
db->create = libosfp_score_db_array_create;
db->destroy = libosfp_score_db_array_destroy;
db->add = libosfp_score_db_array_add;
db->match = libosfp_score_db_array_match;
break;
case LIBOSFP_FIELD_TYPE_STRING:
score_db->field_score_dbs[i].create = libosfp_score_db_hash_create;
score_db->field_score_dbs[i].destroy = libosfp_score_db_hash_destroy;
score_db->field_score_dbs[i].add = libosfp_score_db_hash_add;
score_db->field_score_dbs[i].match = libosfp_score_db_hash_match;
db->create = libosfp_score_db_hash_create;
db->destroy = libosfp_score_db_hash_destroy;
db->add = libosfp_score_db_hash_add;
db->match = libosfp_score_db_hash_match;
break;
default:
libosfp_log_debug("unsupported type: %u", db->type);
goto exit;
}
db->data = score_db->field_score_dbs[i].create();
db->data = db->create();
if (db->data == NULL) {
continue;
libosfp_log_debug("create failed. field: %s", libosfp_fingerprint_get_field_name(i));
goto exit;
}
}

View File

@@ -1,7 +1,7 @@
#ifndef __LIBOSFP_SCORE_DB_H__
#define __LIBOSFP_SCORE_DB_H__
#include "libosfp.h"
#include "libosfp_common.h"
#include "libosfp_fingerprint.h"
typedef struct libosfp_field_score_db {
@@ -25,10 +25,10 @@ typedef struct libosfp_score_db {
} libosfp_score_db_t;
int libosfp_score_db_load(libosfp_score_db_t *score_db, char *fp_file);
int libosfp_score_db_score(libosfp_context_t *libosfp_context, libosfp_fingerprint_t *fp, libosfp_result_t *result);
int libosfp_score_db_score(libosfp_score_db_t *score_db, unsigned int flags, libosfp_fingerprint_t *fp, libosfp_score_t *result);
void libosfp_score_db_debug_print(libosfp_score_db_t *score_db);
libosfp_score_db_t *libosfp_score_db_create(void);
void libosfp_score_db_destroy(libosfp_score_db_t *score_db);
#endif