You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在C/C++中基于libtins从MAC地址获取厂商OUI及设备名称

Hey there! Great progress so far with your libtins network scanner. Let's expand it to add MAC vendor OUI lookup and device name resolution (like DESKTOP-TO5P0BD). Here's how to implement both features step by step:

1. 获取MAC厂商OUI信息

OUI (Organizationally Unique Identifier) is the first 3 bytes of a MAC address, mapping directly to a hardware vendor. You'll need a lookup table for this—we'll start with an embedded local map for simplicity, and you can expand it later with a full OUI dataset.

Step 1: Create an OUI lookup map

Add this static or global map to your code (you can populate it with more OUIs as needed):

#include <unordered_map>
#include <string>

static std::unordered_map<std::string, std::string> oui_database = {
    {"00:1A:2B", "Intel Corporate"},
    {"00:1C:42", "Apple, Inc."},
    {"00:0C:29", "VMware, Inc."},
    {"00:22:68", "Dell Inc."},
    // Add more OUIs from public datasets (like IEEE's official list)
};

Step 2: Extract and look up the OUI

Modify your code to pull the first 3 segments of the MAC address and match it to the vendor:

// Convert MAC address to string format
std::string mac_str = arp.sender_hw_addr().to_string();
// Extract OUI (first 3 segments: "xx:xx:xx")
std::string oui = mac_str.substr(0, 8);

// Get vendor name
std::string vendor = "Unknown Vendor";
auto oui_match = oui_database.find(oui);
if (oui_match != oui_database.end()) {
    vendor = oui_match->second;
}
2. 获取设备名称

There are two reliable ways to get a device's name on a local network: reverse DNS lookup (universal) or NetBIOS query (ideal for Windows devices). Let's cover both.

Option A: Reverse DNS Lookup (Cross-Platform)

Use the standard socket API's getnameinfo function to resolve an IP to a hostname:

#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
// For Windows, replace with <winsock2.h> and <ws2tcpip.h>

std::string get_device_name(const Tins::IPv4Address& ip) {
    struct sockaddr_in sa;
    char host_buffer[NI_MAXHOST];
    
    memset(&sa, 0, sizeof(sa));
    sa.sin_family = AF_INET;
    sa.sin_addr.s_addr = ip.to_uint();
    
    // Attempt to resolve the IP to a hostname
    if (getnameinfo((struct sockaddr*)&sa, sizeof(sa), host_buffer, NI_MAXHOST, nullptr, 0, NI_NAMEREQD) == 0) {
        return std::string(host_buffer);
    }
    return "Unknown Device";
}

Option B: NetBIOS Name Query (Libtins-Based)

Libtins supports crafting NetBIOS queries, which work great for fetching Windows device names directly from the local network:

#include <Tins/PDU.h>
#include <Tins/IP.h>
#include <Tins/UDP.h>
#include <Tins/NetBIOS.h>

std::string query_netbios_name(const Tins::IPv4Address& target_ip, Tins::NetworkInterface& iface) {
    // Craft a NetBIOS workstation name query
    Tins::NetBIOS nb_query;
    nb_query.type(Tins::NetBIOS::NAME_QUERY);
    nb_query.question_name("*<00>");

    // Build the UDP/IP packet
    Tins::UDP udp;
    udp.dport(137); // NetBIOS name service port
    udp.sport(rand() % 65535 + 1024); // Random high port

    Tins::IP ip;
    ip.dst_addr(target_ip);
    ip.src_addr(iface.ipv4_address());

    auto pdu = ip / udp / nb_query;

    // Send query and wait for response (500ms timeout)
    auto response = Tins::PacketSender().send_recv(pdu, iface, 500);
    if (response) {
        const Tins::NetBIOS* nb_response = response->find_pdu<Tins::NetBIOS>();
        if (nb_response && nb_response->type() == Tins::NetBIOS::NAME_QUERY_RESPONSE) {
            return nb_response->answer_name();
        }
    }
    return "Unknown Device";
}
3. Integrate into Your Existing Code

Update your ARP reply handling logic to include the new features—you'll also want to modify your addresses map to store vendor and device name data:

// Update your addresses map type to store more info
using DeviceInfo = std::tuple<Tins::HWAddress<6>, std::string, std::string>;
std::unordered_map<Tins::IPv4Address, DeviceInfo> addresses;

// Retrieve the ARP layer info
const Tins::ARP& arp = pdu.rfind_pdu<Tins::ARP>();
std::cout << "Found :" << arp.sender_ip_addr() << ", " << arp.sender_hw_addr() << std::endl;

// Checking if it is an ARP reply?
if (arp.opcode() == Tins::ARP::REPLY) {
    auto iter = addresses.find(arp.sender_ip_addr());
    if (iter == addresses.end()) {
        // Get vendor info
        std::string mac_str = arp.sender_hw_addr().to_string();
        std::string oui = mac_str.substr(0, 8);
        std::string vendor = "Unknown Vendor";
        auto oui_match = oui_database.find(oui);
        if (oui_match != oui_database.end()) {
            vendor = oui_match->second;
        }

        // Get device name (choose either reverse DNS or NetBIOS)
        Tins::IPv4Address ip = arp.sender_ip_addr();
        Tins::NetworkInterface iface(ip);
        std::string device_name = get_device_name(ip);
        // Or use NetBIOS: std::string device_name = query_netbios_name(ip, iface);

        // Print and save the full device info
        std::cout << "saving " << arp.sender_ip_addr() << ", " << arp.sender_hw_addr() 
                  << ", Vendor: " << vendor << ", Device Name: " << device_name << std::endl;
        addresses.insert({ ip, {arp.sender_hw_addr(), vendor, device_name} });
    } else {
        std::cout << "already seen " << arp.sender_ip_addr() << ", " << arp.sender_hw_addr() << std::endl;
        // Check for MAC address conflicts
        if (arp.sender_hw_addr() != std::get<0>(iter->second)) {
            std::cout << "[WARNING] " << arp.sender_ip_addr() << " is at " << std::get<0>(iter->second) 
                      << " but also at " << arp.sender_hw_addr() << std::endl;
        }
    }
}

Quick Notes:

  • For a full OUI database, you can download the official IEEE OUI CSV and parse it into your map at startup.
  • NetBIOS queries work best on Windows-dominated local networks, while reverse DNS is more universal (but depends on proper DNS setup).
  • On Windows, link against ws2_32.lib to use socket functions.

内容的提问来源于stack exchange,提问作者Gwiza Erick

火山引擎 最新活动