int zmq::ip_resolver_t::resolve_nic_name (ip_addr_t *ip_addr_, const char *nic_) { int rc; bool found = false; const int max_attempts = 10; int iterations = 0; IP_ADAPTER_ADDRESSES *addresses = NULL; IP_ADAPTER_ADDRESSES *current_addresses = NULL; unsigned long out_buf_len = sizeof (IP_ADAPTER_ADDRESSES); do { addresses = static_cast<IP_ADAPTER_ADDRESSES *> (malloc (out_buf_len)); alloc_assert (addresses); rc = GetAdaptersAddresses (AF_UNSPEC, GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER, NULL, addresses, &out_buf_len); if (rc == ERROR_BUFFER_OVERFLOW) { free (addresses); addresses = NULL; } else { break; } iterations++; } while ((rc == ERROR_BUFFER_OVERFLOW) && (iterations < max_attempts)); if (rc == 0) { current_addresses = addresses; while (current_addresses) { char *if_name = NULL; char *if_friendly_name = NULL; int str_rc1, str_rc2; str_rc1 = get_interface_name (current_addresses->IfIndex, &if_name); str_rc2 = wchar_to_utf8 (current_addresses->FriendlyName, &if_friendly_name); // Find a network adapter by its "name" or "friendly name" if (((str_rc1 == 0) && (!strcmp (nic_, if_name))) || ((str_rc2 == 0) && (!strcmp (nic_, if_friendly_name)))) { // Iterate over all unicast addresses bound to the current network interface IP_ADAPTER_UNICAST_ADDRESS *unicast_address = current_addresses->FirstUnicastAddress; IP_ADAPTER_UNICAST_ADDRESS *current_unicast_address = unicast_address; while (current_unicast_address) { ADDRESS_FAMILY family = current_unicast_address->Address.lpSockaddr->sa_family; if (family == (options.ipv6 () ? AF_INET6 : AF_INET)) { memcpy ( ip_addr_, current_unicast_address->Address.lpSockaddr, (family == AF_INET) ? sizeof (struct sockaddr_in) : sizeof (struct sockaddr_in6)); found = true; break; } current_unicast_address = current_unicast_address->Next; } if (found) break; } if (str_rc1 == 0) free (if_name); if (str_rc2 == 0) free (if_friendly_name); current_addresses = current_addresses->Next; } free (addresses); } if (!found) { errno = ENODEV; return -1; } return 0; }
/** 获取可用网卡配置,仅仅选择启动的 ipv4的,非虚拟机的,ethernet */ bool get_all_netinfs(std::vector<NetInf> &nis) { nis.clear(); #ifdef WIN32 ULONG len = 16*1024; IP_ADAPTER_ADDRESSES *adapter = (IP_ADAPTER_ADDRESSES*)malloc(len); // 仅仅 ipv4 DWORD rc = GetAdaptersAddresses(AF_INET, 0, 0, adapter, &len); if (rc == ERROR_BUFFER_OVERFLOW) { adapter = (IP_ADAPTER_ADDRESSES*)realloc(adapter, len); rc = GetAdaptersAddresses(AF_INET, 0, 0, adapter, &len); } if (rc == 0) { IP_ADAPTER_ADDRESSES *p = adapter; while (p) { if ((p->IfType == IF_TYPE_ETHERNET_CSMACD || p->IfType == IF_TYPE_IEEE80211) && (p->OperStatus == IfOperStatusUp)) { // 仅仅考虑 ethernet 或者 wifi,并且活动的 // 不包括虚拟机的 mac std::string mac = conv_mac(p->PhysicalAddress, p->PhysicalAddressLength); if (!is_vm_mac(mac.c_str())) { NetInf ni; ni.macaddr = mac; IP_ADAPTER_UNICAST_ADDRESS *ip = p->FirstUnicastAddress; while (ip) { assert(ip->Address.lpSockaddr->sa_family == AF_INET); sockaddr_in *addr = (sockaddr_in*)ip->Address.lpSockaddr; ni.ips.push_back(inet_ntoa(addr->sin_addr)); ip = ip->Next; } nis.push_back(ni); } } p = p->Next; } free(adapter); } #else char buffer[8192]; struct ifconf ifc; struct ifreq ifr; int fd = socket(AF_INET, SOCK_DGRAM, 0); if(fd == -1) return false; ifc.ifc_len = sizeof(buffer); ifc.ifc_buf = buffer; if(ioctl(fd, SIOCGIFCONF, &ifc) == -1) return false; int count = ifc.ifc_len / sizeof(ifreq); struct ifreq *req = ifc.ifc_req; struct ifreq *end = req + count; for (; req != end; ++req) { strcpy(ifr.ifr_name, req->ifr_name); ioctl(fd, SIOCGIFFLAGS, &ifr); if (ifr.ifr_flags & IFF_LOOPBACK) continue; // lo sockaddr_in sin; sin.sin_addr = ((sockaddr_in&)req->ifr_addr).sin_addr; ioctl(fd, SIOCGIFHWADDR, &ifr); unsigned char mac_addr[6]; memcpy(mac_addr, ifr.ifr_hwaddr.sa_data, 6); NetInf ni; ni.ips.push_back(inet_ntoa(sin.sin_addr)); ni.macaddr = conv_mac(mac_addr, 6); nis.push_back(ni); } close(fd); #endif return true; }
/** * Get the MAC address of the first logical IP-enabled network interface * * @param out the output character array * @return CPL_OK on success or an error code */ cpl_return_t cpl_platform_get_mac_address(cpl_mac_address_t* out) { #ifdef __unix__ // From: http://stackoverflow.com/questions/1779715/how-to-get-mac-address-of-your-machine-using-a-c-program ifreq ifr; ifconf ifc; char buf[1024]; int success = 0; int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); if (sock == -1) return CPL_E_PLATFORM_ERROR; ifc.ifc_len = sizeof(buf); ifc.ifc_buf = buf; if (ioctl(sock, SIOCGIFCONF, &ifc) == -1) return CPL_E_PLATFORM_ERROR; ifreq* it = ifc.ifc_req; const ifreq* const end = it + (ifc.ifc_len / sizeof(ifreq)); for (; it != end; ++it) { strcpy(ifr.ifr_name, it->ifr_name); if (ioctl(sock, SIOCGIFFLAGS, &ifr) == 0) { if (! (ifr.ifr_flags & IFF_LOOPBACK)) { // don't count loopback if (ioctl(sock, SIOCGIFHWADDR, &ifr) == 0) { success = 1; break; } } } else { /* ignore error */ } } if (success && out) { memcpy(out, ifr.ifr_hwaddr.sa_data, 6); } if (!success) return CPL_E_NOT_FOUND; #elif defined(__APPLE__) /* * Adapted from GetMACAddress.c: * http://opensource.apple.com/source/DirectoryService * /DirectoryService-621/CoreFramework/Private/GetMACAddress.c * * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. */ kern_return_t kernResult = KERN_FAILURE; mach_port_t masterPort = MACH_PORT_NULL; CFMutableDictionaryRef classesToMatch = NULL; io_object_t intfService = MACH_PORT_NULL; io_object_t controllerService = MACH_PORT_NULL; io_iterator_t intfIterator = MACH_PORT_NULL; unsigned char macAddress[kIOEthernetAddressSize]; io_iterator_t *matchingServices = &intfIterator; UInt8 *MACAddress = macAddress; // Create an iterator with Primary Ethernet interface kernResult = IOMasterPort(MACH_PORT_NULL, &masterPort); if (kernResult != KERN_SUCCESS) return CPL_E_PLATFORM_ERROR; // Ethernet interfaces are instances of class kIOEthernetInterfaceClass classesToMatch = IOServiceMatching(kIOEthernetInterfaceClass); if (classesToMatch != NULL) { CFMutableDictionaryRef propertyMatch; propertyMatch = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionarySetValue(propertyMatch, CFSTR(kIOPrimaryInterface), kCFBooleanTrue); CFDictionarySetValue(classesToMatch, CFSTR(kIOPropertyMatchKey), propertyMatch); CFRelease(propertyMatch); kernResult = IOServiceGetMatchingServices(masterPort, classesToMatch, matchingServices); } // Given an iterator across a set of Ethernet interfaces, return the // MAC address of the first one. intfService = IOIteratorNext(intfIterator); if (intfService == MACH_PORT_NULL) { IOObjectRelease(intfIterator); return CPL_E_PLATFORM_ERROR; } CFDataRef MACAddressAsCFData = NULL; kernResult = IORegistryEntryGetParentEntry(intfService, kIOServicePlane, &controllerService); if (kernResult != KERN_SUCCESS || controllerService == MACH_PORT_NULL) { IOObjectRelease(intfService); IOObjectRelease(intfIterator); return CPL_E_PLATFORM_ERROR; } MACAddressAsCFData = (CFDataRef) IORegistryEntryCreateCFProperty( controllerService, CFSTR(kIOMACAddress), kCFAllocatorDefault, 0); if (MACAddressAsCFData != NULL) { CFDataGetBytes(MACAddressAsCFData, CFRangeMake(0, kIOEthernetAddressSize), MACAddress); CFRelease(MACAddressAsCFData); } else { IOObjectRelease(controllerService); IOObjectRelease(intfService); IOObjectRelease(intfIterator); return CPL_E_NOT_FOUND; } IOObjectRelease(controllerService); IOObjectRelease(intfService); IOObjectRelease(intfIterator); if (out) memcpy(out, macAddress, 6); #elif defined(_WINDOWS) PIP_ADAPTER_ADDRESSES AdapterAddresses; ULONG family = AF_UNSPEC; ULONG flags = 0; ULONG outBufLen = 0; bool success = false; DWORD dwRetVal = GetAdaptersAddresses(family, flags, NULL, NULL, &outBufLen); if (dwRetVal == ERROR_NO_DATA) return CPL_E_NOT_FOUND; if (dwRetVal == 0 && outBufLen == 0) return CPL_E_NOT_FOUND; if (dwRetVal != ERROR_BUFFER_OVERFLOW) return CPL_E_PLATFORM_ERROR; AdapterAddresses = (IP_ADAPTER_ADDRESSES*) malloc(sizeof(IP_ADAPTER_ADDRESSES) * outBufLen); if (AdapterAddresses == NULL) return CPL_E_INSUFFICIENT_RESOURCES; dwRetVal = GetAdaptersAddresses(family, flags, NULL, AdapterAddresses, &outBufLen); if (dwRetVal != 0) { free(AdapterAddresses); return CPL_E_PLATFORM_ERROR; } for (PIP_ADAPTER_ADDRESSES p = AdapterAddresses; p != NULL; p = p->Next) { if (p->IfType == IF_TYPE_SOFTWARE_LOOPBACK) continue; if (p->PhysicalAddressLength != 6 /* Ethernet */) continue; success = true; if (out) memcpy(out, p->PhysicalAddress, 6); break; } free(AdapterAddresses); if (!success) return CPL_E_NOT_FOUND; #else #error "Not implemented for this platform" #endif return CPL_OK; }