mirror of
https://github.com/pi-hole/FTL.git
synced 2024-10-26 16:52:18 +02:00
121 lines
3.3 KiB
C
121 lines
3.3 KiB
C
/* Pi-hole: A black hole for Internet advertisements
|
|
* (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
|
* Network-wide ad blocking via your own hardware.
|
|
*
|
|
* FTL Engine
|
|
* Network table routines
|
|
*
|
|
* This file is copyright under the latest version of the EUPL.
|
|
* Please see LICENSE file for your rights under this license. */
|
|
|
|
#include "FTL.h"
|
|
#define ARPCACHE "/proc/net/arp"
|
|
|
|
bool create_network_table(void)
|
|
{
|
|
bool ret;
|
|
// Create FTL table in the database (holds properties like database version, etc.)
|
|
ret = dbquery("CREATE TABLE network ( id INTEGER PRIMARY KEY NOT NULL, " \
|
|
"ip TEXT NOT NULL, " \
|
|
"hwaddr TEXT NOT NULL, " \
|
|
"interface TEXT NOT NULL, " \
|
|
"name TEXT, " \
|
|
"firstSeen INTEGER NOT NULL, " \
|
|
"lastSeen INTEGER NOT NULL, " \
|
|
"usesPihole BOOLEAN NOT NULL );");
|
|
if(!ret){ dbclose(); return false; }
|
|
|
|
// Update database version to 3
|
|
ret = db_set_FTL_property(DB_VERSION, 3);
|
|
if(!ret){ dbclose(); return false; }
|
|
|
|
return true;
|
|
}
|
|
|
|
// Read kernel's ARP cache using procfs
|
|
void read_arp_cache(void)
|
|
{
|
|
FILE* arpfp = NULL;
|
|
// Try to access the kernel's ARP cache
|
|
if((arpfp = fopen(ARPCACHE, "r")) == NULL)
|
|
{
|
|
logg("WARN: Opening of %s failed!", ARPCACHE);
|
|
logg(" Message: %s", strerror(errno));
|
|
return;
|
|
}
|
|
|
|
// Open database file
|
|
if(!dbopen())
|
|
{
|
|
logg("read_arp_cache() - Failed to open DB");
|
|
return;
|
|
}
|
|
|
|
// Prepare buffers
|
|
char * linebuffer = NULL;
|
|
size_t linebuffersize = 0;
|
|
char ip[100], mask[100], hwaddr[100], iface[100];
|
|
int type, flags, entries = 0;
|
|
time_t now = time(NULL);
|
|
|
|
// Read ARP cache line by line
|
|
while(getline(&linebuffer, &linebuffersize, arpfp) != -1)
|
|
{
|
|
int num = sscanf(linebuffer, "%99s 0x%x 0x%x %99s %99s %99s\n",
|
|
ip, &type, &flags, hwaddr, mask, iface);
|
|
|
|
// Skip header and empty lines
|
|
if (num < 4)
|
|
continue;
|
|
|
|
if (num == 5)
|
|
{
|
|
/*
|
|
* This happens for incomplete ARP entries for which there is
|
|
* no hardware address in the line. We don't use these
|
|
*/
|
|
//num = sscanf(linebuffer, "%s 0x%x 0x%x %99s %99s\n",
|
|
// ip, &type, &flags, mask, iface);
|
|
//hwaddr[0] = '\0';
|
|
}
|
|
|
|
entries++;
|
|
if(debug) logg("ARP (%i): %i %i %s %s %s <-> %s", num, type, flags, mask, iface, hwaddr, ip);
|
|
|
|
// Get ID of this device in our network database. If it cannot be found, then this is a new device
|
|
char querystr[256];
|
|
sprintf(querystr, "SELECT id FROM network WHERE ip = \"%s\" AND hwaddr = \"%s\";", ip, hwaddr);
|
|
int dbID = db_query_int(querystr);
|
|
|
|
if(dbID == -2)
|
|
{
|
|
// SQLite error
|
|
break;
|
|
}
|
|
else if(dbID == -1)
|
|
{
|
|
// Device not in database, add new entry
|
|
dbquery("INSERT INTO network "\
|
|
"(ip,hwaddr,interface,firstSeen,lastSeen,usesPihole) "\
|
|
"VALUES "\
|
|
"(\"%s\",\"%s\",\"%s\",%lu,%lu,false);",\
|
|
ip, hwaddr, iface, now, now);
|
|
}
|
|
else
|
|
{
|
|
// Device already known, update lastSeen
|
|
dbquery("UPDATE network "\
|
|
"SET lastSeen = %lu "\
|
|
"WHERE id = %i;",\
|
|
now, dbID);
|
|
}
|
|
|
|
}
|
|
|
|
// Close file handle
|
|
fclose(arpfp);
|
|
|
|
// Close database connection
|
|
dbclose();
|
|
}
|