opensync: Added support for local dhcp fingerprint decoding

- Support to decode dhcp fingerprint using a locally stored fingerbank database

Fixes: WIFI-433

Signed-off-by: Yashvardhan <yashvardhan@netexperience.com>
This commit is contained in:
Yashvardhan
2020-09-14 10:33:30 +00:00
committed by John Crispin
parent 9934f93701
commit 61ad8756b3
6 changed files with 5016 additions and 27 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
--- a/interfaces/opensync.ovsschema
+++ b/interfaces/opensync.ovsschema
@@ -2657,6 +2657,41 @@
@@ -2657,6 +2657,69 @@
"type": "integer"
}
}
@@ -38,6 +38,34 @@
+ "key": {
+ "type": "string"
+ }
+ }
+ },
+ "db_status": {
+ "type": {
+ "key": {
+ "type": "integer"
+ }
+ }
+ },
+ "device_name": {
+ "type": {
+ "key": {
+ "type": "string"
+ }
+ }
+ },
+ "device_type": {
+ "type": {
+ "key": {
+ "type": "integer"
+ }
+ }
+ },
+ "manuf_id": {
+ "type": {
+ "key": {
+ "type": "integer"
+ }
+ }
}
},

View File

@@ -0,0 +1,67 @@
/* SPDX-License-Identifier: BSD-3-Clause */
#ifndef _DHCP_FINGERPRINT_H_
#define _DHCP_FINGERPRINT_H_
#include "netifd.h"
#define MAX_DHCP_FINGERPRINT_OPTION_SEQ 256
#define MAX_FINGERPRINT_DEVICE_DESCRIPTION 256
#define MAX_DHCP_FINGERPRINT_LOCAL_DB 64
#define DHCP_FINGERPRINT_DB_FILE "/etc/dhcp_fingerprints.db"
typedef enum {
DHCP_FP_DB_SUCCESS = 0,
DHCP_FP_DB_FAILURE
} dhcp_fp_dbstatus_t;
typedef enum {
DHCP_FP_DEV_TYPE_MISC = 0,
DHCP_FP_DEV_TYPE_MOBILE = 1,
DHCP_FP_DEV_TYPE_PC = 2,
DHCP_FP_DEV_TYPE_PRINTER = 3,
DHCP_FP_DEV_TYPE_VIDEO = 4,
DHCP_FP_DEV_TYPE_GAME = 5,
DHCP_FP_DEV_TYPE_VOIP = 6,
DHCP_FP_DEV_TYPE_MONITORING = 7,
DHCP_FP_DEV_TYPE_MAX = 8
} dhcp_fp_devicetype_t;
typedef enum {
DHCP_FP_DEV_MANUF_MISC = 0,
DHCP_FP_DEV_MANUF_SAMSUNG = 1,
DHCP_FP_DEV_MANUF_APPLE = 2,
DHCP_FP_DEV_MANUF_GOOGLE = 3,
DHCP_FP_DEV_MANUF_HP = 4,
DHCP_FP_DEV_MANUF_INTEL = 5,
DHCP_FP_DEV_MANUF_MICROSOFT = 6,
DHCP_FP_DEV_MANUF_LG = 7,
DHCP_FP_DEV_MANUF_CANON = 8,
DHCP_FP_DEV_MANUF_BROTHER = 9,
DHCP_FP_DEV_MANUF_DELL = 10,
DHCP_FP_DEV_MANUF_LENOVO = 11,
DHCP_FP_DEV_MANUF_VIVO = 12,
DHCP_FP_DEV_MANUF_ALCATEL = 13,
DHCP_FP_DEV_MANUF_ZTE = 14,
DHCP_FP_DEV_MANUF_SONY = 15,
DHCP_FP_DEV_MANU_MAX = 16
} dhcp_fp_manufid_t;
typedef struct {
dhcp_fp_dbstatus_t db_status;
char option_seq[MAX_DHCP_FINGERPRINT_OPTION_SEQ];
char device_name[MAX_FINGERPRINT_DEVICE_DESCRIPTION];
dhcp_fp_devicetype_t device_type;
dhcp_fp_manufid_t manuf_id;
} dhcp_fp_data_t;
typedef struct {
int db_num;
dhcp_fp_data_t devices[MAX_DHCP_FINGERPRINT_LOCAL_DB];
int index;
}dhcp_fp_localdb_t;
bool dhcp_fp_db_lookup (dhcp_fp_data_t *fp_data, char *option_seq);
#endif

View File

@@ -0,0 +1,129 @@
/* SPDX-License-Identifier: BSD-3-Clause */
#include "netifd.h"
#include "dhcp_fingerprint.h"
dhcp_fp_localdb_t local_db;
bool dhcp_fp_db_lookup (dhcp_fp_data_t *fp_data, char *option_seq)
{
FILE *fp = NULL;
char *line = NULL;
int i, rd, rt, found = 0;
size_t len;
int dev_type, dev_manufid = 0;
memset(fp_data, 0, sizeof(dhcp_fp_data_t));
/* first, try to find it from local db */
for (i=0; i < local_db.db_num; i++) {
if (!strncmp(local_db.devices[i].option_seq, option_seq, MAX_DHCP_FINGERPRINT_OPTION_SEQ)) {
LOG(INFO, "found a match from db cache");
strcpy(fp_data->device_name, local_db.devices[i].device_name);
fp_data->device_type = local_db.devices[i].device_type;
fp_data->manuf_id = local_db.devices[i].manuf_id;
fp_data->db_status = local_db.devices[i].db_status;;
return true;
}
}
fp = fopen(DHCP_FINGERPRINT_DB_FILE, "r");
if (fp == NULL){
LOG(ERR, "fingerprints.conf file does not exist");
return false;
}
while ((rd = getline(&line, &len, fp)) != -1) {
if (rd < 0)
continue;
if (line[0] == '#')
continue;
if (rd -1 >= 0)
line[rd - 1] = '\0';
else continue;
if ((rt =strncmp(option_seq, &(line[0]), strlen(option_seq))) == 0) {
if ((rd = getline(&line, &len, fp)) < 0) {
LOG(ERR, "db file is in wrong format, device name");
goto db_lookup_exit;
}
if ((rd >= MAX_FINGERPRINT_DEVICE_DESCRIPTION) || (rd - 1 < 0)) {
LOG(ERR, "device name length from db:%d", rd);
goto db_lookup_exit;
}
line[rd - 1] = '\0';
strncpy(fp_data->device_name, &(line[0]), MAX_FINGERPRINT_DEVICE_DESCRIPTION);
fp_data->db_status = DHCP_FP_DB_SUCCESS;
if ((rd = getline(&line, &len, fp)) < 0) {
LOG(ERR, "db file is in wrong format, device type");
goto db_lookup_exit;
}
line[rd - 1] = '\0';
dev_type = atoi(&(line[0]));
if (dev_type >= DHCP_FP_DEV_TYPE_MAX) {
LOG(ERR, "db file is in wrong format, device type:%d", dev_type);
goto db_lookup_exit;
}
if ((rd = getline(&line, &len, fp)) < 0) {
LOG(ERR, "db file is in wrong format, manufacturer id");
goto db_lookup_exit;
}
line[rd - 1] = '\0';
dev_manufid = atoi(&(line[0]));
if (dev_manufid >= DHCP_FP_DEV_MANU_MAX) {
LOG(ERR, "db file is in wrong format, manufacturer id:%d", dev_manufid);
goto db_lookup_exit;
}
fp_data->device_type = dev_type;
fp_data->manuf_id = dev_manufid;
fp_data->db_status = DHCP_FP_DB_SUCCESS;
found = 1;
LOG(DEBUG, "match found, localDbEntries:%d, device_name:%s added to index:%d", local_db.db_num, fp_data->device_name, local_db.index-1);
break;
}
}
if (!found) {
LOGN("dhcp option seq not found in the db, seq=%s", option_seq);
fp_data->db_status = DHCP_FP_DB_FAILURE;
fp_data->manuf_id = DHCP_FP_DEV_MANUF_MISC;
fp_data->device_type = DHCP_FP_DEV_TYPE_MISC;
fp_data->device_name[0] = '\0';
}
/* store in the local database */
memcpy(local_db.devices[local_db.index].option_seq, option_seq, MAX_DHCP_FINGERPRINT_OPTION_SEQ);
strcpy(local_db.devices[local_db.index].device_name, fp_data->device_name);
local_db.devices[local_db.index].device_type = fp_data->device_type;
local_db.devices[local_db.index].manuf_id = fp_data->manuf_id;
local_db.devices[local_db.index].db_status = fp_data->db_status;
LOG(DEBUG, "db added, option_seq:%s, name:%s, numofDbEntry:%d , index=%d", option_seq, fp_data->device_name, local_db.db_num, local_db.index);
if (local_db.db_num < MAX_DHCP_FINGERPRINT_LOCAL_DB)
local_db.db_num++;
local_db.index++;
if (local_db.index >= MAX_DHCP_FINGERPRINT_LOCAL_DB)
local_db.index = 0;
return true;
db_lookup_exit:
fclose(fp);
free(line);
return false;
}

View File

@@ -2,21 +2,10 @@
#include "netifd.h"
#include "inet_conf.h"
#include "dhcp_fingerprint.h"
#include "ovsdb_sync.h"
#include "json_util.h"
/*
* WAR: Never populate DHCP_leased_IP with duplicate MAC entries, even if they
* exists in /tmp/dhcp.leases. In case there are two entries with the same MAC
* address, update DHCP_leased_IP with the most recent one.
*/
#define WAR_LEASE_UNIQUE_MAC
// Defines
#define MODULE_ID LOG_MODULE_ID_MAIN
#if defined(WAR_LEASE_UNIQUE_MAC)
#include "ds_tree.h"
#include "synclist.h"
@@ -24,6 +13,7 @@
struct dhcp_lease_node
{
struct osn_dhcp_server_lease dl_lease; /* Lease data */
dhcp_fp_data_t dl_fp_data; /* Fingerprint decode results */
bool dl_sync; /* Present on synclist */
bool dl_updated; /* Update pending */
ds_tree_node_t dl_tnode; /* tree node */
@@ -38,7 +28,8 @@ static ds_key_cmp_t osn_dhcp_server_lease_cmp;
static bool __netifd_dhcp_lease_notify(
void *data,
bool released,
struct osn_dhcp_server_lease *dl);
struct osn_dhcp_server_lease *dl,
dhcp_fp_data_t *fp_data);
/* ds_tree comparator */
int osn_dhcp_server_lease_cmp(void *_a, void *_b)
@@ -78,7 +69,7 @@ void *osn_dhcp_server_lease_sync(synclist_t *sync, void *_old, void *_new)
pnew->dl_sync = true;
/* Call the original lease handler */
__netifd_dhcp_lease_notify(dhcp_lease_synclist_data, false, &pnew->dl_lease);
__netifd_dhcp_lease_notify(dhcp_lease_synclist_data, false, &pnew->dl_lease, &pnew->dl_fp_data);
return _new;
}
@@ -86,7 +77,7 @@ void *osn_dhcp_server_lease_sync(synclist_t *sync, void *_old, void *_new)
pold->dl_sync = false;
/* Call the original lease handler */
__netifd_dhcp_lease_notify(dhcp_lease_synclist_data, true, &pold->dl_lease);
__netifd_dhcp_lease_notify(dhcp_lease_synclist_data, true, &pold->dl_lease, &pold->dl_fp_data);
/* Element removal */
return NULL;
@@ -103,7 +94,7 @@ void *osn_dhcp_server_lease_sync(synclist_t *sync, void *_old, void *_new)
*/
if (pold->dl_updated) {
pold->dl_updated = false;
__netifd_dhcp_lease_notify(dhcp_lease_synclist_data, false, &pold->dl_lease);
__netifd_dhcp_lease_notify(dhcp_lease_synclist_data, false, &pold->dl_lease, &pold->dl_fp_data);
}
return pold;
@@ -155,6 +146,7 @@ bool netifd_dhcp_lease_notify(
else if (node == NULL) {
node = calloc(1, sizeof(struct dhcp_lease_node));
node->dl_lease = *dl;
dhcp_fp_db_lookup(&node->dl_fp_data, dl->dl_fingerprint);
ds_tree_insert(&dhcp_lease_list, node, &node->dl_lease);
}
else {
@@ -181,17 +173,9 @@ bool netifd_dhcp_lease_notify(
bool __netifd_dhcp_lease_notify(
void *data,
bool released,
struct osn_dhcp_server_lease *dl)
struct osn_dhcp_server_lease *dl,
dhcp_fp_data_t *fp_data)
#else
/*
* This callback is called by libinet whenever a new DHCP lease is detected.
*/
bool netifd_dhcp_lease_notify(
void *data,
bool released,
struct osn_dhcp_server_lease *dl)
#endif
{
(void)data;
@@ -242,6 +226,18 @@ bool netifd_dhcp_lease_notify(
sdl.secondary_dns_exists = true;
snprintf(sdl.secondary_dns, sizeof(sdl.secondary_dns), PRI_osn_ip_addr, FMT_osn_ip_addr(dl->dl_secondarydns));
sdl.db_status_exists = true;
sdl.db_status = fp_data->db_status;
sdl.device_name_exists = true;
strscpy(sdl.device_name, fp_data->device_name, sizeof(sdl.device_name));
sdl.device_type_exists = true;
sdl.device_type = fp_data->device_type;
sdl.manuf_id_exists = true;
sdl.manuf_id = fp_data->manuf_id;
/* A lease time of 0 indicates that this entry should be deleted */
sdl.lease_time_exists = true;
if (released) {

View File

@@ -12,6 +12,7 @@ UNIT_SRC += src/main.c
UNIT_SRC += src/dhcp_lease.c
UNIT_SRC += src/inet_iface.c
UNIT_SRC += src/inet_conf.c
UNIT_SRC += src/dhcp_fingerprint.c
UNIT_CFLAGS := -I$(UNIT_PATH)/inc
UNIT_CFLAGS += -Isrc/lib/common/inc/