#!/bin/tcc -run -lpci #include #include #include #include #include #include #include #include #include #include #define BUFFER_SIZE 256 void get_default_nic(char *nic) { struct ifaddrs *ifaddr, *ifa; int family; if (getifaddrs(&ifaddr) == -1) { perror("getifaddrs failed"); exit(EXIT_FAILURE); } for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr == NULL) continue; family = ifa->ifa_addr->sa_family; if (family == AF_INET && (ifa->ifa_flags & IFF_LOOPBACK) == 0) { strcpy(nic, ifa->ifa_name); break; } } freeifaddrs(ifaddr); } void get_link_speed(const char *nic, char *result) { int sockfd; struct ifreq ifr; struct ethtool_cmd edata; sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd == -1) { perror("socket failed"); exit(EXIT_FAILURE); } memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, nic, sizeof(ifr.ifr_name) - 1); ifr.ifr_data = (caddr_t) &edata; edata.cmd = ETHTOOL_GSET; if (ioctl(sockfd, SIOCETHTOOL, &ifr) == -1) { perror("ioctl failed"); close(sockfd); exit(EXIT_FAILURE); } close(sockfd); if (edata.speed == SPEED_1000) { strcpy(result, "1000Mb/s"); } else if (edata.speed == SPEED_100) { strcpy(result, "100Mb/s"); } else if (edata.speed == SPEED_10) { strcpy(result, "10Mb/s"); } else { strcpy(result, "Unknown"); } } void get_pci_id(const char *nic, char *pci_id) { int sockfd; struct ifreq ifr; struct ethtool_drvinfo drvinfo; sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd == -1) { perror("socket failed"); exit(EXIT_FAILURE); } memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, nic, sizeof(ifr.ifr_name) - 1); drvinfo.cmd = ETHTOOL_GDRVINFO; ifr.ifr_data = (caddr_t) &drvinfo; if (ioctl(sockfd, SIOCETHTOOL, &ifr) == -1) { perror("ioctl failed"); close(sockfd); exit(EXIT_FAILURE); } close(sockfd); strcpy(pci_id, drvinfo.bus_info); } void get_device_name(const char *pci_id, char *device_name) { struct pci_access *pacc; struct pci_dev *dev; char namebuf[1024]; pacc = pci_alloc(); pci_init(pacc); pci_scan_bus(pacc); for (dev = pacc->devices; dev; dev = dev->next) { pci_fill_info(dev, PCI_FILL_IDENT | PCI_FILL_BASES | PCI_FILL_CLASS); char dev_pci_id[BUFFER_SIZE]; snprintf(dev_pci_id, BUFFER_SIZE, "%04x:%02x:%02x.%d", dev->domain, dev->bus, dev->dev, dev->func); if (strcmp(dev_pci_id, pci_id) == 0) { pci_lookup_name(pacc, namebuf, sizeof(namebuf), PCI_LOOKUP_DEVICE, dev->vendor_id, dev->device_id); strcpy(device_name, namebuf); break; } } pci_cleanup(pacc); } int main() { char nic[BUFFER_SIZE] = {0}; char link_speed[BUFFER_SIZE] = {0}; char pci_id[BUFFER_SIZE] = {0}; char speed_value_str[BUFFER_SIZE] = {0}; char speed_unit[BUFFER_SIZE] = {0}; double speed_value; char device_name[BUFFER_SIZE] = {0}; // Get the default NIC interface name get_default_nic(nic); if (strlen(nic) == 0) { fprintf(stderr, "No suitable network interface found.\n"); exit(EXIT_FAILURE); } //printf("NIC interface: %s\n", nic); // Debug print // Get current link speed of interface get_link_speed(nic, speed_value_str); //printf("Link speed: %s\n", speed_value_str); // Debug print // Get the PCI ID for the NIC interface get_pci_id(nic, pci_id); //printf("PCI ID: %s\n", pci_id); // Debug print // Extract speed and unit sscanf(speed_value_str, "%lf%s", &speed_value, speed_unit); //printf("Speed value: %lf, Speed unit: %s\n", speed_value, speed_unit); // Debug print // Convert speed to a human-readable format if (strcmp(speed_unit, "Mb/s") == 0 && speed_value >= 1000) { speed_value /= 1000; strcpy(speed_unit, "Gb/s"); } // Check if PCI ID is found if (strlen(pci_id) == 0) { fprintf(stderr, "PCI ID not found for interface: %s\n", nic); exit(EXIT_FAILURE); } else { // Get the human-readable name of the device get_device_name(pci_id, device_name); //printf("Device name: %s\n", device_name); // Debug print } // Hee Hoo jank :) if (strlen(speed_value_str) > 0 && strlen(speed_unit) > 0) { printf("%s [%0.1lf %s]\n", device_name, speed_value, speed_unit); } else { printf("%s\n", device_name); } return 0; }