簡體   English   中英

如何在centos中從IP中的IP獲取以太網適配器名稱

[英]how to get Ethernet adapter name from IP in c in centos

有兩個以太網適配器,所以我有兩個不同的IP地址。 現在,我想用相應的IP查找適配器的名稱。 像,我有IP 192.168.10.1的Intel卡。 在沒有任何第三方安裝的情況下,如何使用C或C ++在centos(linux)中檢索此適配器名稱?

我需要找到制造商名稱(而不是eth0等。)。 該制造商列表位於“ /usr/share/hwdata/pci.ids”中,但是我無法使用IP地址映射該名稱。 我可以使用'lscpu |獲取適配器名稱列表。 grep“以太網””。 但是同樣出現了將名稱與IP地址映射的問題。

標准libc中有getifaddrs函數。 我從手冊頁修改了一個示例。

您無法從內核獲取名稱,但是它在/sys文件系統中提供了PCI ID。 您可以使用libpci將這些數字解析為文件名。 當前代碼不支持USB設備和子設備號。

#define _GNU_SOURCE     /* To get defns of NI_MAXSERV and NI_MAXHOST */
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <ifaddrs.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/if_link.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <limits.h>

#include <pci/pci.h>

/* PCI IDs are contained in /sys filesystem. */
unsigned long read_sysfs_uint(const char* ifa_name, const char* info) {
    char path[PATH_MAX];
    char buf[12];
    int fd;

    snprintf(path, PATH_MAX, "/sys/class/net/%s/device/%s", ifa_name, info);

    fd = open(path, O_RDONLY);
    if(fd == -1)
        return 0;

    if(read(fd, buf, 12) == -1) {
        close(fd);
        return 0;
    }

    close(fd);
    return strtoul(buf, NULL, 16);
}

/* Try to get PCI IDs and get PCI device name for it.
   XXX: doesn't check for subsystem's numbers */
void print_pci_ids(const char* ifa_name) {
    int vendor = (int) read_sysfs_uint(ifa_name, "vendor");
    int device = (int) read_sysfs_uint(ifa_name, "device");
    int subsystem_vendor = (int) read_sysfs_uint(ifa_name, "subsystem_vendor");
    int subsystem_device = (int) read_sysfs_uint(ifa_name, "subsystem_device");

    struct pci_access *pacc = pci_alloc();
    char namebuf[256];

    printf("PCI IDs: %x %x %x %x\n", vendor, device, subsystem_device, subsystem_vendor);

    pci_init(pacc);

    if(pci_lookup_name(pacc, namebuf, 256, 
                    PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE,
                    vendor, device)) {
        printf("PCI Name: %s\n", namebuf);
    }

    pci_cleanup(pacc);
}

int main(int argc, char *argv[])
{
    struct ifaddrs *ifaddr, *ifa;
    struct in_addr* ifa_inaddr;
    struct in_addr addr;
    int family, s, n;

    if(argc != 2) {
        fprintf(stderr, "Usage: getifaddr <IP>\n");
        return EXIT_FAILURE;
    }

    if (inet_aton(argv[1], &addr) == 0) {
        perror("inet_aton");
        return EXIT_FAILURE;
    }

    if (getifaddrs(&ifaddr) == -1) {
        perror("getifaddrs");
        return EXIT_FAILURE;
    }

    /* Walk through linked list, maintaining head pointer so we
        can free list later */

    for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) {
        if (ifa->ifa_addr == NULL)
            continue;

        /* We seek only for IPv4 addresses */
        if(ifa->ifa_addr->sa_family != AF_INET)
            continue;

        ifa_inaddr = &(((struct sockaddr_in*) ifa->ifa_addr)->sin_addr);
        if(memcmp(ifa_inaddr, &addr, sizeof(struct in_addr)) == 0) {
            printf("Interface: %s\n", ifa->ifa_name);
            print_pci_ids(ifa->ifa_name);
        }
    }

    freeifaddrs(ifaddr);
    return EXIT_SUCCESS;
}

使用libpci編譯(您需要安裝相應的devel軟件包):

$ gcc getifname.c -lpci -o ./getifname

以下是其用法示例:

$ ./getifname 
Usage: getifaddr <IP>
$ ./getifname  dlks
inet_aton: Success
$ ./getifname 127.0.0.1
Interface: lo
PCI IDs: 0 0 0 0
PCI Name: Device 0000:0000
$ ./getifname 192.168.13.144
Interface: wlan0
PCI IDs: 8086 88e 4060 8086
PCI Name: Intel Corporation Centrino Advanced-N 6235

我假設適配器名稱是eth0 / eth1 / etc。 而非制造商/型號。 如果是這樣,一種可能的解決方案(有點費解,但可以解決)將執行ifconfig sys調用並將其通過管道傳輸到文本文件。 從那里,您可以搜索文本文件以查找IP地址,然后從那里開始,因為輸出是恆定的,因此您可以僅使用IP的起始位置作為獲取適配器名稱的基礎。

這實際上有些棘手,因為linux沒有像Windows這樣的通用,通用驅動程序堆棧API-基本上可以歸結為3個選項:

  1. 讀取內核導出的特殊文件: https : //stackoverflow.com/a/5611176/351861
  2. 調用lspci並解析其輸出: http : //prefetch.net/articles/linuxpci.html
  3. 復制lspci的功能並實際編寫自己的應用程序,如您所見,您將需要幾個內核數據結構,例如pcimap_entry和諸如此類,但它應該是直接的,因為您可以從字面上竊取舊內核大師的知識: https:// github.com/gittup/pciutils/blob/gittup/ls-kernel.c

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM