diff --git a/src/database/gravity-db.c b/src/database/gravity-db.c index 786569e33..cc7159f3c 100644 --- a/src/database/gravity-db.c +++ b/src/database/gravity-db.c @@ -337,7 +337,9 @@ static bool get_client_groupids(clientsData* client) { free(hwaddr); hwaddr = NULL; - logg("Skipping mock-device hardware address lookup"); + + if(config.debug & DEBUG_CLIENTS) + logg("Skipping mock-device hardware address lookup"); } // MAC address fallback: Try to synthesize MAC address from internal buffer @@ -348,7 +350,9 @@ static bool get_client_groupids(clientsData* client) snprintf(hwaddr, strlen, "%02X:%02X:%02X:%02X:%02X:%02X", client->hwaddr[0], client->hwaddr[1], client->hwaddr[2], client->hwaddr[3], client->hwaddr[4], client->hwaddr[5]); - logg("--> Obtained %s from internal ARP cache", hwaddr); + + if(config.debug & DEBUG_CLIENTS) + logg("--> Obtained %s from internal ARP cache", hwaddr); } } @@ -432,7 +436,8 @@ static bool get_client_groupids(clientsData* client) { free(hostname); hostname = NULL; - logg("Skipping empty host name lookup"); + if(config.debug & DEBUG_CLIENTS) + logg("Skipping empty host name lookup"); } } @@ -517,7 +522,8 @@ static bool get_client_groupids(clientsData* client) { free(interface); interface = 0; - logg("Skipping empty interface lookup"); + if(config.debug & DEBUG_CLIENTS) + logg("Skipping empty interface lookup"); } } diff --git a/src/database/network-table.c b/src/database/network-table.c index dd350aef1..40c648b00 100644 --- a/src/database/network-table.c +++ b/src/database/network-table.c @@ -1581,103 +1581,87 @@ void updateMACVendorRecords(void) dbclose(); } -char *__attribute__((malloc)) getDatabaseHostname(const char *ipaddr) +// Get hardware address of device identified by IP address +char *__attribute__((malloc)) getMACfromIP(const char *ipaddr) { - // Test if this is an IPv6 address - bool IPv6 = false; - if(ipaddr != NULL && strstr(ipaddr,":") != NULL) - { - IPv6 = true; - } - - // Do we want to resolve IPv4/IPv6 names at all? - if( (IPv6 && !config.resolveIPv6) || - (!IPv6 && !config.resolveIPv4)) - { - if(config.debug & DEBUG_RESOLVER) - { - logg(" ---> \"\" (configured to not resolve %s host names)", - IPv6 ? "IPv6" : "IPv4"); - } - return strdup(""); - } - // Open pihole-FTL.db database file if needed const bool db_already_open = FTL_DB_avail(); if(!db_already_open && !dbopen()) { - logg("getDatabaseHostname(\"%s\") - Failed to open DB", ipaddr); + logg("getMACfromIP(\"%s\") - Failed to open DB", ipaddr); return NULL; } // Prepare SQLite statement + // We request the most recent IP entry in case there an IP appears + // multiple times in the network_addresses table sqlite3_stmt *stmt = NULL; - const char *querystr = "SELECT name FROM network_addresses " - "WHERE name IS NOT NULL AND ip = ?;"; + const char *querystr = "SELECT hwaddr FROM network WHERE id = " + "(SELECT network_id FROM network_addresses " + "WHERE ip = ? GROUP BY ip HAVING max(lastSeen));"; int rc = sqlite3_prepare_v2(FTL_db, querystr, -1, &stmt, NULL); if( rc != SQLITE_OK ){ - logg("getDatabaseHostname(\"%s\") - SQL error prepare: %s", + logg("getMACfromIP(\"%s\") - SQL error prepare: %s", ipaddr, sqlite3_errstr(rc)); if(!db_already_open) dbclose(); - return strdup(""); + return NULL; } // Bind ipaddr to prepared statement if((rc = sqlite3_bind_text(stmt, 1, ipaddr, -1, SQLITE_STATIC)) != SQLITE_OK) { - logg("getDatabaseHostname(\"%s\"): Failed to bind ip: %s", + logg("getMACfromIP(\"%s\"): Failed to bind ip: %s", ipaddr, sqlite3_errstr(rc)); sqlite3_reset(stmt); sqlite3_finalize(stmt); if(!db_already_open) dbclose(); - return strdup(""); + return NULL; } - char *hostname = NULL; + char *hwaddr = NULL; rc = sqlite3_step(stmt); if(rc == SQLITE_ROW) { // Database record found (result might be empty) - hostname = strdup((char*)sqlite3_column_text(stmt, 0)); + hwaddr = strdup((char*)sqlite3_column_text(stmt, 0)); } else { // Not found or error (will be logged automatically through our SQLite3 hook) - hostname = strdup(""); + hwaddr = NULL; } + if(config.debug & DEBUG_DATABASE && hwaddr != NULL) + logg("Found database hardware address %s -> %s", ipaddr, hwaddr); + // Finalize statement and close database handle sqlite3_reset(stmt); sqlite3_finalize(stmt); if(!db_already_open) dbclose(); - return hostname; + return hwaddr; } -// Get hardware address of device identified by IP address -char *__attribute__((malloc)) getMACfromIP(const char *ipaddr) +// Get host name of device identified by IP address +char *__attribute__((malloc)) getNameFromIP(const char *ipaddr) { // Open pihole-FTL.db database file if needed const bool db_already_open = FTL_DB_avail(); if(!db_already_open && !dbopen()) { - logg("getMACfromIP(\"%s\") - Failed to open DB", ipaddr); + logg("getNameFromIP(\"%s\") - Failed to open DB", ipaddr); return NULL; } - // Prepare SQLite statement - // We request the most recent IP entry in case there an IP appears - // multiple times in the network_addresses table + // Check for a host name associated with the same IP address sqlite3_stmt *stmt = NULL; - const char *querystr = "SELECT hwaddr FROM network WHERE id = " - "(SELECT network_id FROM network_addresses " - "WHERE ip = ? GROUP BY ip HAVING max(lastSeen));"; + const char *querystr = "SELECT name FROM network_addresses WHERE name IS NOT NULL AND ip = ?;"; int rc = sqlite3_prepare_v2(FTL_db, querystr, -1, &stmt, NULL); if( rc != SQLITE_OK ){ - logg("getMACfromIP(\"%s\") - SQL error prepare: %s", + logg("getNameFromIP(\"%s\") - SQL error prepare: %s", ipaddr, sqlite3_errstr(rc)); if(!db_already_open) dbclose(); @@ -1687,7 +1671,7 @@ char *__attribute__((malloc)) getMACfromIP(const char *ipaddr) // Bind ipaddr to prepared statement if((rc = sqlite3_bind_text(stmt, 1, ipaddr, -1, SQLITE_STATIC)) != SQLITE_OK) { - logg("getMACfromIP(\"%s\"): Failed to bind ip: %s", + logg("getNameFromIP(\"%s\"): Failed to bind ip: %s", ipaddr, sqlite3_errstr(rc)); sqlite3_reset(stmt); sqlite3_finalize(stmt); @@ -1696,49 +1680,45 @@ char *__attribute__((malloc)) getMACfromIP(const char *ipaddr) return NULL; } - char *hwaddr = NULL; + char *name = NULL; rc = sqlite3_step(stmt); if(rc == SQLITE_ROW) { // Database record found (result might be empty) - hwaddr = strdup((char*)sqlite3_column_text(stmt, 0)); + name = strdup((char*)sqlite3_column_text(stmt, 0)); + + if(config.debug & DEBUG_DATABASE) + logg("Found database host name (same address) %s -> %s", ipaddr, name); } else { // Not found or error (will be logged automatically through our SQLite3 hook) - hwaddr = NULL; } - if(config.debug & DEBUG_DATABASE && hwaddr != NULL) - logg("Found database hardware address %s -> %s", ipaddr, hwaddr); - - // Finalize statement and close database handle + // Finalize statement sqlite3_reset(stmt); sqlite3_finalize(stmt); - if(!db_already_open) - dbclose(); - return hwaddr; -} - -// Get host name of device identified by IP address -char *__attribute__((malloc)) getNameFromIP(const char *ipaddr) -{ - // Open pihole-FTL.db database file if needed - const bool db_already_open = FTL_DB_avail(); - if(!db_already_open && !dbopen()) + // Return here if we found the name + if(name != NULL) { - logg("getNameFromIP(\"%s\") - Failed to open DB", ipaddr); - return NULL; + if(!db_already_open) + dbclose(); + + return name; } - // Prepare SQLite statement - sqlite3_stmt *stmt = NULL; - const char *querystr = "SELECT name FROM network_addresses WHERE name IS NOT NULL AND ip = ?;"; - int rc = sqlite3_prepare_v2(FTL_db, querystr, -1, &stmt, NULL); + // Nothing found for the exact IP address + // Check for a host name associated with the same device (but another IP address) + querystr = "SELECT name FROM network_addresses " + "WHERE name IS NOT NULL AND " + "network_id = (SELECT network_id FROM network_addresses " + "WHERE ip = ?) " + "ORDER BY lastSeen DESC LIMIT 1"; + rc = sqlite3_prepare_v2(FTL_db, querystr, -1, &stmt, NULL); if( rc != SQLITE_OK ){ logg("getNameFromIP(\"%s\") - SQL error prepare: %s", - ipaddr, sqlite3_errstr(rc)); + ipaddr, sqlite3_errstr(rc)); if(!db_already_open) dbclose(); return NULL; @@ -1748,7 +1728,7 @@ char *__attribute__((malloc)) getNameFromIP(const char *ipaddr) if((rc = sqlite3_bind_text(stmt, 1, ipaddr, -1, SQLITE_STATIC)) != SQLITE_OK) { logg("getNameFromIP(\"%s\"): Failed to bind ip: %s", - ipaddr, sqlite3_errstr(rc)); + ipaddr, sqlite3_errstr(rc)); sqlite3_reset(stmt); sqlite3_finalize(stmt); if(!db_already_open) @@ -1756,22 +1736,20 @@ char *__attribute__((malloc)) getNameFromIP(const char *ipaddr) return NULL; } - char *name = NULL; rc = sqlite3_step(stmt); if(rc == SQLITE_ROW) { // Database record found (result might be empty) name = strdup((char*)sqlite3_column_text(stmt, 0)); + + if(config.debug & DEBUG_DATABASE) + logg("Found database host name (same device) %s -> %s", ipaddr, name); } else { // Not found or error (will be logged automatically through our SQLite3 hook) name = NULL; } - - if(config.debug & DEBUG_DATABASE && name != NULL) - logg("Found database host name %s -> %s", ipaddr, name); - // Finalize statement and close database handle sqlite3_reset(stmt); sqlite3_finalize(stmt); diff --git a/src/database/network-table.h b/src/database/network-table.h index ebe0a272d..1c958435a 100644 --- a/src/database/network-table.h +++ b/src/database/network-table.h @@ -16,10 +16,9 @@ bool create_network_addresses_with_names_table(void); void parse_neighbor_cache(void); void updateMACVendorRecords(void); bool unify_hwaddr(void); -char* getDatabaseHostname(const char* ipaddr) __attribute__((malloc)); -char* __attribute__((malloc)) getMACfromIP(const char* ipaddr); -char* __attribute__((malloc)) getNameFromIP(const char* ipaddr); -char* __attribute__((malloc)) getIfaceFromIP(const char* ipaddr); +char *getMACfromIP(const char* ipaddr) __attribute__((malloc)); +char *getNameFromIP(const char* ipaddr) __attribute__((malloc)); +char *getIfaceFromIP(const char* ipaddr) __attribute__((malloc)); void resolveNetworkTableNames(void); #endif //NETWORKTABLE_H diff --git a/src/resolve.c b/src/resolve.c index a63909015..7bea2be7e 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -134,17 +134,6 @@ char *resolveHostname(const char *addr) IPv6 = true; } - if( (IPv6 && !config.resolveIPv6) || - (!IPv6 && !config.resolveIPv4)) - { - if(config.debug & DEBUG_RESOLVER) - { - logg(" ---> \"\" (configured to not resolve %s host names)", - IPv6 ? "IPv6" : "IPv4"); - } - return strdup(""); - } - // Initialize resolver subroutines if trying to resolve for the first time // res_init() reads resolv.conf to get the default domain name and name server // address(es). If no server is given, the local host is tried. If no domain @@ -285,6 +274,24 @@ static size_t resolveAndAddHostname(size_t ippos, size_t oldnamepos) char* oldname = strdup(getstr(oldnamepos)); unlock_shm(); + // Test if we want to resolve an IPv6 address + bool IPv6 = false; + if(strstr(ipaddr,":") != NULL) + { + IPv6 = true; + } + + if( (IPv6 && !config.resolveIPv6) || + (!IPv6 && !config.resolveIPv4)) + { + if(config.debug & DEBUG_RESOLVER) + { + logg(" ---> \"\" (configured to not resolve %s host names)", + IPv6 ? "IPv6" : "IPv4"); + } + return 0; + } + // Important: Don't hold a lock while resolving as the main thread // (dnsmasq) needs to be operable during the call to resolveHostname() char* newname = resolveHostname(ipaddr); @@ -294,7 +301,7 @@ static size_t resolveAndAddHostname(size_t ippos, size_t oldnamepos) if(strlen(newname) == 0 && config.names_from_netdb) { free(newname); - newname = getDatabaseHostname(ipaddr); + newname = getNameFromIP(ipaddr); } // Only store new newname if it is valid and differs from oldname @@ -318,7 +325,8 @@ static size_t resolveAndAddHostname(size_t ippos, size_t oldnamepos) logg("Not adding \"%s\" to buffer (unchanged)", oldname); } - free(newname); + if(newname != NULL) + free(newname); free(ipaddr); free(oldname);