mirror of
https://github.com/rzuasti/oott.git
synced 2026-07-08 19:21:54 +02:00
Deduce vendor from mDNS services for privacy MACs
Modern devices increasingly use randomized ("Private WiFi Address") MACs,
which are locally administered and have no real OUI, so the MAC-prefix
vendor lookup returns nothing. Such devices still advertise distinctive
mDNS service types, which we now use to deduce their vendor.
- Extend the mDNS parser to also capture PTR service types alongside
A-record hostnames.
- Add a service-type -> vendor mapping (data/mdns-service-vendor.json) and
a service_vendor_finder, using canonical vendor names so device-type
resolution still chains.
- Add utils::network::is_locally_administered to detect randomized MACs.
- In the mDNS scanner, fall back to service-based deduction only when the
OUI lookup is empty and the MAC is locally administered.
- Group the three finders under a new data module.
- Preserve a known vendor (and its derived device_type) when a later
sighting cannot deduce one, and suppress the spurious "vendor changed"
notification in that case.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
7fb457ca4a
commit
98a23aa7fd
@@ -7,11 +7,11 @@ use log::{debug, error, info, warn};
|
||||
use crate::db;
|
||||
use crate::device_finders::mdns;
|
||||
use crate::events;
|
||||
use crate::mac_vendor_finder;
|
||||
use crate::data::mac_vendor_finder;
|
||||
use crate::mdns_scanner_status;
|
||||
use crate::model::devices::Device;
|
||||
use crate::settings::get_settings;
|
||||
use crate::vendor_device_type_finder;
|
||||
use crate::data::vendor_device_type_finder;
|
||||
|
||||
/// Passively listen for mDNS/Bonjour announcements and feed discovered devices into the same
|
||||
/// pipeline used by the ARP scanner (devices table + events + notifications).
|
||||
@@ -38,18 +38,27 @@ pub async fn listen() -> Result<(), Box<dyn std::error::Error>> {
|
||||
IpAddr::V6(_) => continue, // the device model is IPv4-only
|
||||
};
|
||||
|
||||
let hostname = match mdns::parse_announcement(&buf[..len]).into_iter().next() {
|
||||
let announcement = mdns::parse_announcement(&buf[..len]);
|
||||
let hostname = match announcement.hostnames.into_iter().next() {
|
||||
Some(host) => host,
|
||||
None => continue,
|
||||
};
|
||||
|
||||
process_announcement(src_ip, hostname, interface.clone(), probe_timeout).await;
|
||||
process_announcement(
|
||||
src_ip,
|
||||
hostname,
|
||||
announcement.service_types,
|
||||
interface.clone(),
|
||||
probe_timeout,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
async fn process_announcement(
|
||||
src_ip: Ipv4Addr,
|
||||
hostname: String,
|
||||
service_types: Vec<String>,
|
||||
interface: Option<String>,
|
||||
probe_timeout: Duration,
|
||||
) {
|
||||
@@ -61,7 +70,12 @@ async fn process_announcement(
|
||||
}
|
||||
};
|
||||
|
||||
let vendor = mac_vendor_finder::find(mac.get(0..8).unwrap_or("").to_string());
|
||||
let mut vendor = mac_vendor_finder::find(mac.get(0..8).unwrap_or("").to_string());
|
||||
// Privacy MACs are locally administered and have no real OUI, so the lookup above fails.
|
||||
// Fall back to the vendor-specific mDNS services the device advertises.
|
||||
if vendor.is_empty() && crate::utils::network::is_locally_administered(&mac) {
|
||||
vendor = crate::data::service_vendor_finder::find(&service_types);
|
||||
}
|
||||
let mut device = Device::new(
|
||||
mac.clone(),
|
||||
src_ip.to_string(),
|
||||
|
||||
Reference in New Issue
Block a user