Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.137.157.45] |
|
Сообщ.
#1
,
|
|
|
Откопал в сети функции поиска доступных интерфейсов по ip 4 и ip 6 (для ip 6 переделал из ip 4 сам):
const int BUF_SIZE = 4092; int lookup_addr_indx_ip_4(int indx, unsigned long *addr) { #ifdef WIN32 LPSOCKET_ADDRESS_LIST list = NULL; SOCKET sc = 0; char buf[BUF_SIZE]; int len = 0; int ret = 0; sc = socket(AF_INET, SOCK_RAW, IPPROTO_IP); if(sc == INVALID_SOCKET){ return (-1); } ret = WSAIoctl(sc, SIO_ADDRESS_LIST_QUERY, NULL, 0, buf, BUF_SIZE, (unsigned long *)&len, NULL, NULL); closesocket(sc); if(ret != 0 || len <= 0){ return(-2); } list = (LPSOCKET_ADDRESS_LIST) buf; if(list->iAddressCount <=0){ return (-3); } for(int i = 0; i <= indx && i < list->iAddressCount; ++i){ //нашли адрес if(i == indx){ memcpy(addr, &list->Address[i].lpSockaddr->sa_data[2],4); return (1); } } //адресов не осталось return (0); #else struct ifconf ifc; struct ifreq *ifr = NULL; char buf[BUF_SIZE]; int ret = 0; int off = 0; int cnt = 0; int cdx = 0; int sc = 0; sc = socket(AF_INET, SOCK_DGRAM, 0); if(sc < 0){ return (-1); } ifc.ifc_len = BUF_SIZE; ifc.ifc_buf = buf; ret = ioctl(sc, SIOCGIFCONF, &ifc); if(ret <0){ return (-2); } ifr = ifc.ifc_req; while(cnt < ifc.ifc_len && cdx <= indx){ if(ifr->ifr_addr.sa_family == AF_INET){ if(cdx == indx){ memcpy(addr, &ifr->ifr_addr.sa_data[2], 4); return (1); } ++cdx; } off = IFNAMSIZ + ifr->ifr_addr.sa_len; cnt += off; ((char*) ifr) += off; } close(sc); #endif return (0); } const int BUF_SIZE = 4092; int lookup_addr_indx_ip_6(int indx, sockaddr_in6 *addr) { #ifdef WIN32 LPSOCKET_ADDRESS_LIST list = NULL; SOCKET sc = 0; char buf[BUF_SIZE]; int len = 0; int ret = 0; sc = socket(AF_INET6, SOCK_RAW, IPPROTO_IP); if(sc == INVALID_SOCKET){ return (-1); } ret = WSAIoctl(sc, SIO_ADDRESS_LIST_QUERY, NULL, 0, buf, BUF_SIZE, (unsigned long *)&len, NULL, NULL); closesocket(sc); if(ret != 0 || len <= 0){ return(-2); } list = (LPSOCKET_ADDRESS_LIST) buf; if(list->iAddressCount <=0){ return (-3); } for(int i = 0; i <= indx && i < list->iAddressCount; ++i){ //нашли адрес if(i == indx){ memcpy(addr, list->Address[i].lpSockaddr,list->Address[i].iSockaddrLength); return (1);[attach=48013][/attach][attach=48013][/attach] } } //адресов не осталось return (0); #else struct ifconf ifc; struct ifreq *ifr = NULL; char buf[BUF_SIZE]; int ret = 0; int off = 0; int cnt = 0; int cdx = 0; int sc = 0; sc = socket(AF_INET6, SOCK_DGRAM, 0); if(sc < 0){ return (-1); } ifc.ifc_len = BUF_SIZE; ifc.ifc_buf = buf; ret = ioctl(sc, SIOCGIFCONF, &ifc); if(ret <0){ return (-2); } ifr = ifc.ifc_req; while(cnt < ifc.ifc_len && cdx <= indx){ if(ifr->ifr_addr.sa_family == AF_INET){ if(cdx == indx){ memcpy(addr, &ifr->ifr_addr.sa_data[2], 4); return (1); } ++cdx; } off = IFNAMSIZ + ifr->ifr_addr.sa_len; cnt += off; ((char*) ifr) += off; } close(sc); #endif return (0); } Для ip 6 находит 7 адресов на моём компьютера, но некоторые отличаются с "Сведения" Windows. Неплохо бы это ещё исправить. Прикреплённая картинка
Теперь из-за использования сырых сокетов (SOCK_RAW) программа в Windows 10 требует административных прав. Прошу предложить мне готовые функции для нахождения всех ip 4 и ip 6 адресов компьютера без использования сырых сокетов (SOCK_RAW). |
Сообщ.
#2
,
|
|
|
Вот для ipv4:
CStringA local_address; CStringA local_address_internet_address; char chInfo[64]; if (!gethostname(chInfo,sizeof(chInfo))) { hostent *sh; sh=gethostbyname((char*)&chInfo); if (sh!=NULL) { int nAdapter = 0; while ( sh->h_addr_list[nAdapter] ) { struct sockaddr_in adr; memcpy(&adr.sin_addr,sh->h_addr_list[nAdapter],sh->h_length); local_address += CStringA(inet_ntoa(adr.sin_addr)) + CStringA("\n"); nAdapter++; } } } if(local_address.GetLength()==0) { CString error(L"local_address.GetLength()==0"); ::MessageBox(0,error,CString(L"Error"),MB_ICONERROR); break; } //::MessageBox(0,CString(local_address),CString(L"Information"),MB_ICONINFORMATION); CStringA local_first_address; int pos_return = local_address.Find('\n'); if(pos_return!=0) { for(int local_counter=0;local_counter<pos_return;local_counter++) { local_first_address += local_address.GetAt(local_counter); } local_address = local_first_address; } Теперь надо сделать для ipv6. Добавлено Вот программа с сайта microsoft (я немного переделал): #include <winsock2.h> #include <ws2tcpip.h> #include <stdio.h> // link with Ws2_32.lib #pragma comment (lib, "Ws2_32.lib") int __cdecl main(int argc, char **argv) { //----------------------------------------- // Declare and initialize variables WSADATA wsaData; int iResult; INT iRetval; DWORD dwRetval; int i = 1; struct addrinfo *result = NULL; struct addrinfo *ptr = NULL; struct addrinfo hints; struct sockaddr_in *sockaddr_ipv4; // struct sockaddr_in6 *sockaddr_ipv6; LPSOCKADDR sockaddr_ip; wchar_t ipstringbuffer[46]; DWORD ipbufferlength = 46; // Validate the parameters if (argc != 3) { printf("usage: %s <hostname> <servicename>\n", argv[0]); printf("getaddrinfo provides protocol-independent translation\n"); printf(" from an ANSI host name to an IP address\n"); printf("%s example usage\n", argv[0]); printf(" %s www.contoso.com 0\n", argv[0]); return 1; } // Initialize Winsock iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); if (iResult != 0) { printf("WSAStartup failed: %d\n", iResult); return 1; } //-------------------------------- // Setup the hints address info structure // which is passed to the getaddrinfo() function ZeroMemory( &hints, sizeof(hints) ); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; printf("Calling getaddrinfo with following parameters:\n"); printf("\tnodename = %s\n", argv[1]); printf("\tservname (or port) = %s\n\n", argv[2]); //-------------------------------- // Call getaddrinfo(). If the call succeeds, // the result variable will hold a linked list // of addrinfo structures containing response // information dwRetval = getaddrinfo(argv[1], argv[2], &hints, &result); if ( dwRetval != 0 ) { printf("getaddrinfo failed with error: %d\n", dwRetval); WSACleanup(); return 1; } printf("getaddrinfo returned success\n"); // Retrieve each address and print out the hex bytes for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) { printf("getaddrinfo response %d\n", i++); printf("\tFlags: 0x%x\n", ptr->ai_flags); printf("\tFamily: "); switch (ptr->ai_family) { case AF_UNSPEC: printf("Unspecified\n"); break; case AF_INET: printf("AF_INET (IPv4)\n"); sockaddr_ipv4 = (struct sockaddr_in *) ptr->ai_addr; printf("\tIPv4 address %s\n", inet_ntoa(sockaddr_ipv4->sin_addr) ); break; case AF_INET6: printf("AF_INET6 (IPv6)\n"); // the InetNtop function is available on Windows Vista and later // sockaddr_ipv6 = (struct sockaddr_in6 *) ptr->ai_addr; // printf("\tIPv6 address %s\n", // InetNtop(AF_INET6, &sockaddr_ipv6->sin6_addr, ipstringbuffer, 46) ); // We use WSAAddressToString since it is supported on Windows XP and later sockaddr_ip = (LPSOCKADDR) ptr->ai_addr; // The buffer length is changed by each call to WSAAddresstoString // So we need to set it for each iteration through the loop for safety ipbufferlength = 46; iRetval = WSAAddressToString(sockaddr_ip, (DWORD) ptr->ai_addrlen, NULL, ipstringbuffer, &ipbufferlength ); if (iRetval) printf("WSAAddressToString failed with %u\n", WSAGetLastError() ); else wprintf(L"\tIPv6 address %s\n", ipstringbuffer); break; case AF_NETBIOS: printf("AF_NETBIOS (NetBIOS)\n"); break; default: printf("Other %ld\n", ptr->ai_family); break; } printf("\tSocket type: "); switch (ptr->ai_socktype) { case 0: printf("Unspecified\n"); break; case SOCK_STREAM: printf("SOCK_STREAM (stream)\n"); break; case SOCK_DGRAM: printf("SOCK_DGRAM (datagram) \n"); break; case SOCK_RAW: printf("SOCK_RAW (raw) \n"); break; case SOCK_RDM: printf("SOCK_RDM (reliable message datagram)\n"); break; case SOCK_SEQPACKET: printf("SOCK_SEQPACKET (pseudo-stream packet)\n"); break; default: printf("Other %ld\n", ptr->ai_socktype); break; } printf("\tProtocol: "); switch (ptr->ai_protocol) { case 0: printf("Unspecified\n"); break; case IPPROTO_TCP: printf("IPPROTO_TCP (TCP)\n"); break; case IPPROTO_UDP: printf("IPPROTO_UDP (UDP) \n"); break; default: printf("Other %ld\n", ptr->ai_protocol); break; } printf("\tLength of this sockaddr: %d\n", ptr->ai_addrlen); printf("\tCanonical name: %s\n", ptr->ai_canonname); } freeaddrinfo(result); WSACleanup(); return 0; } Прошу переделать в функцию. |