\r
int plibc_conv_to_win_path(const char *pszUnix, char *pszWindows);\r
\r
-/**\r
- * Enumerate all network adapters\r
- */\r
-void EnumNICs(PMIB_IFTABLE *pIfTable, PMIB_IPADDRTABLE *pAddrTable)\r
-{\r
- DWORD dwSize, dwRet;\r
+#define _IP_ADAPTER_UNICAST_ADDRESS_HEAD \\r
+ union { \\r
+ struct { \\r
+ ULONG Length; \\r
+ DWORD Flags; \\r
+ }; \\r
+ }; \\r
+\r
+#define _IP_ADAPTER_UNICAST_ADDRESS_BASE \\r
+ SOCKET_ADDRESS Address; \\r
+ IP_PREFIX_ORIGIN PrefixOrigin; \\r
+ IP_SUFFIX_ORIGIN SuffixOrigin; \\r
+ IP_DAD_STATE DadState; \\r
+ ULONG ValidLifetime; \\r
+ ULONG PreferredLifetime; \\r
+ ULONG LeaseLifetime;\r
+\r
+#define _IP_ADAPTER_UNICAST_ADDRESS_ADD_VISTA \\r
+ UINT8 OnLinkPrefixLength;\r
+\r
+\r
+#define _IP_ADAPTER_UNICAST_ADDRESS_DEFINE(suffix,addition) \\r
+typedef struct _IP_ADAPTER_UNICAST_ADDRESS##suffix { \\r
+ _IP_ADAPTER_UNICAST_ADDRESS_HEAD \\r
+ struct _IP_ADAPTER_UNICAST_ADDRESS##suffix *Next; \\r
+ _IP_ADAPTER_UNICAST_ADDRESS_BASE \\r
+ addition \\r
+} IP_ADAPTER_UNICAST_ADDRESS##suffix, *PIP_ADAPTER_UNICAST_ADDRESS##suffix;\r
+\r
+/* _IP_ADAPTER_UNICAST_ADDRESS_DEFINE(,) defined in w32api headers */\r
+_IP_ADAPTER_UNICAST_ADDRESS_DEFINE(_VISTA,_IP_ADAPTER_UNICAST_ADDRESS_ADD_VISTA)\r
+\r
+\r
+typedef struct _IP_ADAPTER_WINS_SERVER_ADDRESS {\r
+ union {\r
+ ULONGLONG Alignment;\r
+ struct {\r
+ ULONG Length;\r
+ DWORD Reserved;\r
+ };\r
+ };\r
+ struct _IP_ADAPTER_WINS_SERVER_ADDRESS *Next;\r
+ SOCKET_ADDRESS Address;\r
+} IP_ADAPTER_WINS_SERVER_ADDRESS, *PIP_ADAPTER_WINS_SERVER_ADDRESS, *PIP_ADAPTER_WINS_SERVER_ADDRESS_LH;\r
+\r
+typedef struct _IP_ADAPTER_GATEWAY_ADDRESS {\r
+ union {\r
+ ULONGLONG Alignment;\r
+ struct {\r
+ ULONG Length;\r
+ DWORD Reserved;\r
+ };\r
+ };\r
+ struct _IP_ADAPTER_GATEWAY_ADDRESS *Next;\r
+ SOCKET_ADDRESS Address;\r
+} IP_ADAPTER_GATEWAY_ADDRESS, *PIP_ADAPTER_GATEWAY_ADDRESS, *PIP_ADAPTER_GATEWAY_ADDRESS_LH;\r
+\r
+typedef UINT32 NET_IF_COMPARTMENT_ID;\r
+typedef GUID NET_IF_NETWORK_GUID;\r
+\r
+typedef enum _NET_IF_CONNECTION_TYPE {\r
+ NET_IF_CONNECTION_DEDICATED = 1,\r
+ NET_IF_CONNECTION_PASSIVE,\r
+ NET_IF_CONNECTION_DEMAND,\r
+ NET_IF_CONNECTION_MAXIMUM \r
+} NET_IF_CONNECTION_TYPE, *PNET_IF_CONNECTION_TYPE;\r
+\r
+typedef enum {\r
+ TUNNEL_TYPE_NONE = 0,\r
+ TUNNEL_TYPE_OTHER,\r
+ TUNNEL_TYPE_DIRECT,\r
+ TUNNEL_TYPE_6TO4,\r
+ TUNNEL_TYPE_ISATAP,\r
+ TUNNEL_TYPE_TEREDO,\r
+ TUNNEL_TYPE_IPHTTPS \r
+} TUNNEL_TYPE, *PTUNNEL_TYPE;\r
\r
- *pIfTable = NULL;\r
+/*\r
+A DUID consists of a two-octet type code represented in network byte\r
+ order, followed by a variable number of octets that make up the\r
+ actual identifier. A DUID can be no more than 128 octets long (not\r
+ including the type code).\r
+*/\r
+#define MAX_DHCPV6_DUID_LENGTH 130\r
+\r
+typedef union _NET_LUID {\r
+ ULONG64 Value;\r
+ struct {\r
+ ULONG64 Reserved :24;\r
+ ULONG64 NetLuidIndex :24;\r
+ ULONG64 IfType :16;\r
+ } Info;\r
+} NET_LUID, *PNET_LUID, IF_LUID;\r
+\r
+#define MAX_DNS_SUFFIX_STRING_LENGTH 246\r
+\r
+typedef struct _IP_ADAPTER_DNS_SUFFIX {\r
+ struct _IP_ADAPTER_DNS_SUFFIX *Next;\r
+ WCHAR String[MAX_DNS_SUFFIX_STRING_LENGTH];\r
+} IP_ADAPTER_DNS_SUFFIX, *PIP_ADAPTER_DNS_SUFFIX;\r
+\r
+\r
+\r
+#define _IP_ADAPTER_ADDRESSES_HEAD \\r
+ union { \\r
+ ULONGLONG Alignment; \\r
+ struct { \\r
+ ULONG Length; \\r
+ DWORD IfIndex; \\r
+ }; \\r
+ };\r
+\r
+#define _IP_ADAPTER_ADDRESSES_BASE \\r
+ PCHAR AdapterName; \\r
+ PIP_ADAPTER_UNICAST_ADDRESS FirstUnicastAddress; \\r
+ PIP_ADAPTER_ANYCAST_ADDRESS FirstAnycastAddress; \\r
+ PIP_ADAPTER_MULTICAST_ADDRESS FirstMulticastAddress; \\r
+ PIP_ADAPTER_DNS_SERVER_ADDRESS FirstDnsServerAddress; \\r
+ PWCHAR DnsSuffix; \\r
+ PWCHAR Description; \\r
+ PWCHAR FriendlyName; \\r
+ BYTE PhysicalAddress[MAX_ADAPTER_ADDRESS_LENGTH]; \\r
+ DWORD PhysicalAddressLength; \\r
+ DWORD Flags; \\r
+ DWORD Mtu; \\r
+ DWORD IfType; \\r
+ IF_OPER_STATUS OperStatus;\r
+\r
+#define _IP_ADAPTER_ADDRESSES_ADD_XPSP1 \\r
+ DWORD Ipv6IfIndex; \\r
+ DWORD ZoneIndices[16]; \\r
+ PIP_ADAPTER_PREFIX FirstPrefix; \\r
+\r
+\r
+#define _IP_ADAPTER_ADDRESSES_ADD_VISTA \\r
+ _IP_ADAPTER_ADDRESSES_ADD_XPSP1 \\r
+ ULONG64 TransmitLinkSpeed; \\r
+ ULONG64 ReceiveLinkSpeed; \\r
+ PIP_ADAPTER_WINS_SERVER_ADDRESS_LH FirstWinsServerAddress; \\r
+ PIP_ADAPTER_GATEWAY_ADDRESS_LH FirstGatewayAddress; \\r
+ ULONG Ipv4Metric; \\r
+ ULONG Ipv6Metric; \\r
+ IF_LUID Luid; \\r
+ SOCKET_ADDRESS Dhcpv4Server; \\r
+ NET_IF_COMPARTMENT_ID CompartmentId; \\r
+ NET_IF_NETWORK_GUID NetworkGuid; \\r
+ NET_IF_CONNECTION_TYPE ConnectionType; \\r
+ TUNNEL_TYPE TunnelType; \\r
+ SOCKET_ADDRESS Dhcpv6Server; \\r
+ BYTE Dhcpv6ClientDuid[MAX_DHCPV6_DUID_LENGTH]; \\r
+ ULONG Dhcpv6ClientDuidLength; \\r
+ ULONG Dhcpv6Iaid;\r
+\r
+#define _IP_ADAPTER_ADDRESSES_ADD_2008_OR_VISTASP1 \\r
+ _IP_ADAPTER_ADDRESSES_ADD_VISTA \\r
+ PIP_ADAPTER_DNS_SUFFIX FirstDnsSuffix;\r
+\r
+#define _IP_ADAPTER_ADDRESSES_DEFINE(suffix,addition) \\r
+typedef struct _IP_ADAPTER_ADDRESSES##suffix { \\r
+ _IP_ADAPTER_ADDRESSES_HEAD \\r
+ struct _IP_ADAPTER_ADDRESSES##suffix *Next; \\r
+ _IP_ADAPTER_ADDRESSES_BASE \\r
+ addition \\r
+} IP_ADAPTER_ADDRESSES##suffix, *PIP_ADAPTER_ADDRESSES##suffix;\r
+ \r
+\r
+/* _IP_ADAPTER_ADDRESSES_DEFINE(,) defined in w32api headers */\r
+_IP_ADAPTER_ADDRESSES_DEFINE(_XPSP1,_IP_ADAPTER_ADDRESSES_ADD_XPSP1)\r
+_IP_ADAPTER_ADDRESSES_DEFINE(_VISTA,_IP_ADAPTER_ADDRESSES_ADD_VISTA)\r
+_IP_ADAPTER_ADDRESSES_DEFINE(_2008_OR_VISTASP1,_IP_ADAPTER_ADDRESSES_ADD_2008_OR_VISTASP1)\r
+\r
+static int\r
+EnumNICs_IPv6_get_ifs_count (SOCKET s)\r
+{\r
+ DWORD dwret = 0, err;\r
+ int iret;\r
+ iret = WSAIoctl (s, SIO_ADDRESS_LIST_QUERY, NULL, 0, NULL, 0,\r
+ &dwret, NULL, NULL);\r
+ err = GetLastError ();\r
+ if (iret == SOCKET_ERROR && err == WSAEFAULT)\r
+ return dwret;\r
+ else if (iret == 0)\r
+ return 0;\r
+ return GNUNET_SYSERR;\r
+}\r
\r
- if (pAddrTable)\r
- *pAddrTable = NULL;\r
+static int\r
+EnumNICs_IPv6_get_ifs (SOCKET s, SOCKET_ADDRESS_LIST *inf, int size)\r
+{\r
+ int iret;\r
+ DWORD dwret = 0;\r
+ iret = WSAIoctl (s, SIO_ADDRESS_LIST_QUERY, NULL, 0, inf, size,\r
+ &dwret, NULL, NULL);\r
\r
- if (GNGetIfTable)\r
+ if (iret != 0 || dwret != size)\r
{\r
- dwSize = dwRet = 0;\r
+ /* It's supposed to succeed! And size should be the same */\r
+ return GNUNET_SYSERR;\r
+ }\r
+ return GNUNET_OK;\r
+}\r
\r
- *pIfTable = (MIB_IFTABLE *) GlobalAlloc(GPTR, sizeof(MIB_IFTABLE));\r
+#undef GNUNET_malloc\r
+#define GNUNET_malloc(a) HeapAlloc(GetProcessHeap (), HEAP_ZERO_MEMORY | \\r
+ HEAP_GENERATE_EXCEPTIONS, a)\r
\r
- /* Get size of table */\r
- if (GNGetIfTable(*pIfTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER)\r
- {\r
- GlobalFree(*pIfTable);\r
- *pIfTable = (MIB_IFTABLE *) GlobalAlloc(GPTR, dwSize);\r
- }\r
+#undef GNUNET_free\r
+#define GNUNET_free(a) HeapFree(GetProcessHeap (), 0, a)\r
\r
- if ((dwRet = GNGetIfTable(*pIfTable, &dwSize, 0)) == NO_ERROR &&\r
- pAddrTable)\r
- {\r
- DWORD dwIfIdx, dwSize = sizeof(MIB_IPADDRTABLE);\r
- *pAddrTable = (MIB_IPADDRTABLE *) GlobalAlloc(GPTR, dwSize);\r
+#undef GNUNET_free_non_null\r
+#define GNUNET_free_non_null(a) do { if ((a) != NULL) GNUNET_free(a); } while (0)\r
\r
- /* Make an initial call to GetIpAddrTable to get the\r
- necessary size */\r
- if (GNGetIpAddrTable(*pAddrTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER)\r
+static int\r
+EnumNICs_IPv4_get_ifs (SOCKET s, INTERFACE_INFO **inf, int *size)\r
+{\r
+ int iret;\r
+ DWORD dwret = 0;\r
+ DWORD error;\r
+ INTERFACE_INFO *ii = NULL;\r
+ DWORD ii_size = sizeof (INTERFACE_INFO) * 15;\r
+ while (TRUE)\r
+ {\r
+ if (ii_size >= sizeof (INTERFACE_INFO) * 1000)\r
+ return GNUNET_SYSERR;\r
+ ii = (INTERFACE_INFO *) GNUNET_malloc (ii_size);\r
+ dwret = 0;\r
+ iret = WSAIoctl (s, SIO_GET_INTERFACE_LIST, NULL, 0, ii, ii_size,\r
+ &dwret, NULL, NULL);\r
+ error = GetLastError ();\r
+ if (iret == SOCKET_ERROR)\r
+ {\r
+ if (error == WSAEFAULT)\r
{\r
- GlobalFree(*pAddrTable);\r
- *pAddrTable = (MIB_IPADDRTABLE *) GlobalAlloc(GPTR, dwSize);\r
+ GNUNET_free (ii);\r
+ ii_size *= 2;\r
+ continue;\r
}\r
- GNGetIpAddrTable(*pAddrTable, &dwSize, 0);\r
+ GNUNET_free (ii);\r
+ return GNUNET_SYSERR;\r
+ }\r
+ else\r
+ {\r
+ *inf = ii;\r
+ *size = dwret;\r
+ return GNUNET_OK;\r
}\r
}\r
+ return GNUNET_SYSERR;\r
+}\r
+\r
+int\r
+EnumNICs2 (INTERFACE_INFO **ifs4, int *ifs4_len, SOCKET_ADDRESS_LIST **ifs6)\r
+{\r
+ int result = 0;\r
+ SOCKET s4 = INVALID_SOCKET, s6 = INVALID_SOCKET;\r
+ DWORD dwret1 = 0, dwret2;\r
+ DWORD err1, err2;\r
+ int ifs4len = 0, ifs6len = 0;\r
+ INTERFACE_INFO *interfaces4 = NULL;\r
+ SOCKET_ADDRESS_LIST *interfaces6 = NULL;\r
+ SetLastError (0);\r
+ s4 = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);\r
+ err1 = GetLastError ();\r
+ SetLastError (0);\r
+ s6 = socket (AF_INET6, SOCK_STREAM, IPPROTO_TCP);\r
+ err2 = GetLastError ();\r
+ if (s6 != INVALID_SOCKET)\r
+ {\r
+ ifs6len = EnumNICs_IPv6_get_ifs_count (s6);\r
+ if (ifs6len > 0)\r
+ {\r
+ interfaces6 = (SOCKET_ADDRESS_LIST *) GNUNET_malloc (ifs6len);\r
+ result = EnumNICs_IPv6_get_ifs (s6, interfaces6, ifs6len) || result;\r
+ }\r
+ closesocket (s6);\r
+ s6 = INVALID_SOCKET;\r
+ }\r
+\r
+ if (s4 != INVALID_SOCKET)\r
+ {\r
+ result = EnumNICs_IPv4_get_ifs (s4, &interfaces4, &ifs4len) || result;\r
+ closesocket (s4);\r
+ s4 = INVALID_SOCKET;\r
+ }\r
+ if (ifs6len + ifs4len == 0)\r
+ goto error;\r
+\r
+ if (!result)\r
+ {\r
+ *ifs4 = interfaces4;\r
+ *ifs4_len = ifs4len;\r
+ *ifs6 = interfaces6;\r
+ return GNUNET_OK;\r
+ }\r
+error:\r
+ if (interfaces4 != NULL)\r
+ GNUNET_free (interfaces4);\r
+ if (interfaces6 != NULL)\r
+ GNUNET_free (interfaces6);\r
+ if (s4 != INVALID_SOCKET)\r
+ closesocket (s4);\r
+ if (s6 != INVALID_SOCKET)\r
+ closesocket (s6);\r
+ return GNUNET_SYSERR;\r
}\r
\r
/**\r
- * Lists all network interfaces in a combo box\r
- * Used by the basic GTK configurator\r
- *\r
- * @param callback function to call for each NIC\r
- * @param callback_cls closure for callback\r
+ * Returns GNUNET_OK on OK, GNUNET_SYSERR on error\r
*/\r
- int ListNICs(void (*callback) (void *, const char *, int), void * callback_cls)\r
+int\r
+EnumNICs3 (struct EnumNICs3_results **results, int *results_count)\r
{\r
- PMIB_IFTABLE pTable;\r
- PMIB_IPADDRTABLE pAddrTable;\r
- DWORD dwIfIdx, dwExternalNIC;\r
- IPAddr theIP;\r
-\r
- /* Determine our external NIC */\r
- theIP = inet_addr("192.0.34.166"); /* www.example.com */\r
- if ((! GNGetBestInterface) ||\r
- (GNGetBestInterface(theIP, &dwExternalNIC) != NO_ERROR))\r
+ DWORD dwRetVal = 0;\r
+ int count = 0;\r
+ ULONG flags = /*GAA_FLAG_INCLUDE_PREFIX |*/ GAA_FLAG_SKIP_ANYCAST |\r
+ GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER;\r
+ struct sockaddr_in6 examplecom6;\r
+ IPAddr examplecom;\r
+ DWORD best_interface = 0;\r
+ DWORD best_interface6 = 0;\r
+\r
+ int use_enum2 = 0;\r
+ INTERFACE_INFO *interfaces4 = NULL;\r
+ int interfaces4_len = 0;\r
+ SOCKET_ADDRESS_LIST *interfaces6 = NULL;\r
+\r
+ unsigned long outBufLen = sizeof (IP_ADAPTER_ADDRESSES);\r
+ IP_ADAPTER_ADDRESSES *pCurrentAddress = NULL;\r
+ IP_ADAPTER_ADDRESSES *pAddresses = (IP_ADAPTER_ADDRESSES *) GNUNET_malloc (outBufLen);\r
+\r
+ if (GetAdaptersAddresses (AF_UNSPEC, flags, NULL, pAddresses, &outBufLen)\r
+ == ERROR_BUFFER_OVERFLOW)\r
+ {\r
+ GNUNET_free (pAddresses);\r
+ pAddresses = (IP_ADAPTER_ADDRESSES *) GNUNET_malloc (outBufLen);\r
+ }\r
+\r
+ dwRetVal = GetAdaptersAddresses (AF_UNSPEC, flags, NULL, pAddresses, &outBufLen);\r
+\r
+ if (dwRetVal != NO_ERROR)\r
+ {\r
+ GNUNET_free (pAddresses);\r
+ return GNUNET_SYSERR;\r
+ }\r
+\r
+ if (pAddresses->Length < sizeof (IP_ADAPTER_ADDRESSES_VISTA))\r
+ {\r
+ use_enum2 = 1;\r
+\r
+ /* Enumerate NICs using WSAIoctl() */\r
+ if (GNUNET_OK != EnumNICs2 (&interfaces4, &interfaces4_len, &interfaces6))\r
+ {\r
+ GNUNET_free (pAddresses);\r
+ return GNUNET_SYSERR;\r
+ }\r
+ }\r
+\r
+ examplecom = inet_addr("192.0.34.166"); /* www.example.com */\r
+ if (GetBestInterface (examplecom, &best_interface) != NO_ERROR)\r
+ best_interface = 0;\r
+\r
+ if (GNGetBestInterfaceEx != NULL)\r
{\r
- dwExternalNIC = 0;\r
+ examplecom6.sin6_family = AF_INET6;\r
+ examplecom6.sin6_port = 0;\r
+ examplecom6.sin6_flowinfo = 0;\r
+ examplecom6.sin6_scope_id = 0;\r
+ inet_pton (AF_INET6, "2001:500:88:200:0:0:0:10",\r
+ (struct sockaddr *) &examplecom6.sin6_addr);\r
+ dwRetVal = GNGetBestInterfaceEx ((struct sockaddr *) &examplecom6,\r
+ &best_interface6);\r
+ if (dwRetVal != NO_ERROR)\r
+ best_interface6 = 0;\r
}\r
\r
- /* Enumerate NICs */\r
- EnumNICs(&pTable, &pAddrTable);\r
+ /* Give IPv6 a priority */\r
+ if (best_interface6 != 0)\r
+ best_interface = best_interface6;\r
\r
- if (pTable)\r
+ count = 0;\r
+ for (pCurrentAddress = pAddresses;\r
+ pCurrentAddress != NULL; pCurrentAddress = pCurrentAddress->Next)\r
{\r
- for(dwIfIdx=0; dwIfIdx <= pTable->dwNumEntries; dwIfIdx++)\r
+ if (pCurrentAddress->OperStatus == IfOperStatusUp)\r
{\r
- char szEntry[1001];\r
- DWORD dwIP = 0;\r
- int iItm;\r
- PIP_ADAPTER_INFO pAdapterInfo;\r
- PIP_ADAPTER_INFO pAdapter = NULL;\r
- DWORD dwRetVal = 0;\r
-\r
- /* Get IP-Address */\r
- int i;\r
- for(i = 0; i < pAddrTable->dwNumEntries; i++)\r
+ IP_ADAPTER_UNICAST_ADDRESS *unicast = NULL;\r
+ for (unicast = pCurrentAddress->FirstUnicastAddress; unicast != NULL;\r
+ unicast = unicast->Next)\r
{\r
- if (pAddrTable->table[i].dwIndex == pTable->table[dwIfIdx].dwIndex)\r
+ if ((unicast->Address.lpSockaddr->sa_family == AF_INET ||\r
+ unicast->Address.lpSockaddr->sa_family == AF_INET6) &&\r
+ (unicast->DadState == IpDadStateDeprecated ||\r
+ unicast->DadState == IpDadStatePreferred))\r
+ count += 1;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (count == 0)\r
+ {\r
+ *results = NULL;\r
+ *results_count = 0;\r
+ GNUNET_free (pAddresses);\r
+ GNUNET_free_non_null (interfaces4);\r
+ GNUNET_free_non_null (interfaces6);\r
+ return GNUNET_OK;\r
+ }\r
+\r
+ *results = (struct EnumNICs3_results *) GNUNET_malloc (\r
+ sizeof (struct EnumNICs3_results) * count);\r
+ *results_count = count;\r
+\r
+ count = 0;\r
+ for (pCurrentAddress = pAddresses;\r
+ pCurrentAddress != NULL; pCurrentAddress = pCurrentAddress->Next)\r
+ {\r
+ struct EnumNICs3_results *r;\r
+ IP_ADAPTER_UNICAST_ADDRESS *unicast = NULL;\r
+ if (pCurrentAddress->OperStatus != IfOperStatusUp)\r
+ continue;\r
+ for (unicast = pCurrentAddress->FirstUnicastAddress; unicast != NULL;\r
+ unicast = unicast->Next)\r
+ {\r
+ int i, j;\r
+ int mask_length = -1;\r
+ char dst[INET6_ADDRSTRLEN + 1];\r
+\r
+ if ((unicast->Address.lpSockaddr->sa_family != AF_INET &&\r
+ unicast->Address.lpSockaddr->sa_family != AF_INET6) ||\r
+ (unicast->DadState != IpDadStateDeprecated &&\r
+ unicast->DadState != IpDadStatePreferred))\r
+ continue;\r
+\r
+ r = &(*results)[count];\r
+ r->flags = 0;\r
+ if (pCurrentAddress->IfIndex > 0 &&\r
+ pCurrentAddress->IfIndex == best_interface &&\r
+ unicast->Address.lpSockaddr->sa_family == AF_INET)\r
+ r->is_default = 1;\r
+ else if (pCurrentAddress->Ipv6IfIndex > 0 &&\r
+ pCurrentAddress->Ipv6IfIndex == best_interface6 &&\r
+ unicast->Address.lpSockaddr->sa_family == AF_INET6)\r
+ r->is_default = 1;\r
+ else\r
+ r->is_default = 0;\r
+\r
+ /* Don't choose default interface twice */\r
+ if (r->is_default)\r
+ best_interface = best_interface6 = 0;\r
+\r
+ if (!use_enum2)\r
+ {\r
+ memcpy (&r->address, unicast->Address.lpSockaddr,\r
+ unicast->Address.iSockaddrLength);\r
+ memset (&r->mask, 0, sizeof (struct sockaddr));\r
+ mask_length = ((IP_ADAPTER_UNICAST_ADDRESS_VISTA *) unicast)->\r
+ OnLinkPrefixLength;\r
+ /* OnLinkPrefixLength is the number of leading 1s in the mask.\r
+ * OnLinkPrefixLength is available on Vista and later (hence use_enum2).\r
+ */\r
+ if (unicast->Address.lpSockaddr->sa_family == AF_INET)\r
{\r
- dwIP = pAddrTable->table[i].dwAddr;\r
- break;\r
+ struct sockaddr_in *m = (struct sockaddr_in *) &r->mask;\r
+ for (i = 0; i < mask_length; i++)\r
+ ((unsigned char *) &m->sin_addr)[i / 8] |= 0x80 >> (i % 8);\r
}\r
+ else if (unicast->Address.lpSockaddr->sa_family == AF_INET6)\r
+ {\r
+ struct sockaddr_in6 *m = (struct sockaddr_in6 *) &r->mask;\r
+ struct sockaddr_in6 *b = (struct sockaddr_in6 *) &r->broadcast;\r
+ for (i = 0; i < mask_length; i++)\r
+ ((unsigned char *) &m->sin6_addr)[i / 8] |= 0x80 >> (i % 8);\r
+ memcpy (&r->broadcast, &r->address, unicast->Address.iSockaddrLength);\r
+ for (i = mask_length; i < 128; i++)\r
+ ((unsigned char *) &b->sin6_addr)[i / 8] |= 0x80 >> (i % 8);\r
+ }\r
+ r->flags |= ENUMNICS3_MASK_OK;\r
}\r
-\r
- if (dwIP)\r
+ else\r
{\r
- BYTE bPhysAddr[MAXLEN_PHYSADDR];\r
- char *pszIfName = NULL;\r
- char dst[INET_ADDRSTRLEN];\r
-\r
- /* Get friendly interface name */\r
- pAdapterInfo = (IP_ADAPTER_INFO *) malloc(sizeof(IP_ADAPTER_INFO));\r
- ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO);\r
-\r
- /* Make an initial call to GetAdaptersInfo to get\r
- the necessary size into the ulOutBufLen variable */\r
- if (GGetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) {\r
- free(pAdapterInfo);\r
- pAdapterInfo = (IP_ADAPTER_INFO *) malloc (ulOutBufLen);\r
- }\r
-\r
- if ((dwRetVal = GGetAdaptersInfo( pAdapterInfo, &ulOutBufLen)) == NO_ERROR) {\r
- pAdapter = pAdapterInfo;\r
- while (pAdapter) {\r
- if (pTable->table[dwIfIdx].dwIndex == pAdapter->Index)\r
- {\r
- char szKey[251];\r
- long lLen = 250;\r
-\r
- sprintf(szKey, "SYSTEM\\CurrentControlSet\\Control\\Network\\"\r
- "{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection",\r
- pAdapter->AdapterName);\r
- pszIfName = (char *) malloc(251);\r
- if (QueryRegistry(HKEY_LOCAL_MACHINE, szKey, "Name", pszIfName,\r
- &lLen) != ERROR_SUCCESS)\r
- {\r
- free(pszIfName);\r
- pszIfName = NULL;\r
- }\r
- }\r
- pAdapter = pAdapter->Next;\r
- }\r
- }\r
- free(pAdapterInfo);\r
-\r
- /* Set entry */\r
- memset(bPhysAddr, 0, MAXLEN_PHYSADDR);\r
- memcpy(bPhysAddr,\r
- pTable->table[dwIfIdx].bPhysAddr,\r
- pTable->table[dwIfIdx].dwPhysAddrLen);\r
-\r
- snprintf(szEntry, 1000, "%s (%s - %I64u)",\r
- pszIfName ? pszIfName : (char *) pTable->table[dwIfIdx].bDescr,\r
- inet_ntop (AF_INET, &dwIP, dst, INET_ADDRSTRLEN),\r
- *((unsigned long long *) bPhysAddr));\r
- szEntry[1000] = 0;\r
-\r
- if (pszIfName)\r
- free(pszIfName);\r
-\r
- callback(callback_cls,\r
- szEntry, \r
- pAddrTable->table[dwIfIdx].dwIndex == dwExternalNIC);\r
+ int found = 0;\r
+ if (unicast->Address.lpSockaddr->sa_family == AF_INET)\r
+ {\r
+ for (i = 0; !found && i < interfaces4_len / sizeof (INTERFACE_INFO); i++)\r
+ {\r
+ struct sockaddr_in *m = (struct sockaddr_in *) &r->mask;\r
+ if (memcpy (&interfaces4[i].iiAddress.Address,\r
+ unicast->Address.lpSockaddr,\r
+ unicast->Address.iSockaddrLength) != 0)\r
+ continue;\r
+ found = 1;\r
+ memcpy (&r->address, &interfaces4[i].iiAddress.Address,\r
+ sizeof (struct sockaddr_in));\r
+ memcpy (&r->mask, &interfaces4[i].iiNetmask.Address,\r
+ sizeof (struct sockaddr_in));\r
+ for (mask_length = 0;\r
+ ((unsigned char *) &m->sin_addr)[mask_length / 8] &\r
+ 0x80 >> (mask_length % 8); mask_length++)\r
+ {\r
+ }\r
+ r->flags |= ENUMNICS3_MASK_OK;\r
+ }\r
+ }\r
+ else if (unicast->Address.lpSockaddr->sa_family == AF_INET6)\r
+ {\r
+ for (i = 0;\r
+ interfaces6 != NULL && !found && i < interfaces6->iAddressCount;\r
+ i++)\r
+ {\r
+ if (memcpy (interfaces6->Address[i].lpSockaddr,\r
+ unicast->Address.lpSockaddr,\r
+ unicast->Address.iSockaddrLength) != 0)\r
+ continue;\r
+ found = 1;\r
+ memcpy (&r->address, interfaces6->Address[i].lpSockaddr,\r
+ sizeof (struct sockaddr_in6));\r
+ /* TODO: Find a way to reliably get network mask for IPv6 on XP */\r
+ memset (&r->mask, 0, sizeof (struct sockaddr));\r
+ r->flags &= ~ENUMNICS3_MASK_OK;\r
+ }\r
+ }\r
+ if (!found)\r
+ {\r
+ DebugBreak ();\r
+ }\r
+ }\r
+ if (unicast->Address.lpSockaddr->sa_family == AF_INET)\r
+ {\r
+ struct sockaddr_in *m = (struct sockaddr_in *) &r->mask;\r
+ struct sockaddr_in *a = (struct sockaddr_in *) &r->address;\r
+ /* copy address to broadcast, then flip all the trailing bits not\r
+ * falling under netmask to 1,\r
+ * so we get, 192.168.0.255 from, say, 192.168.0.43 with mask == 24.\r
+ */\r
+ memcpy (&r->broadcast, &r->address, unicast->Address.iSockaddrLength);\r
+ for (i = mask_length; i < 32; i++)\r
+ ((unsigned char *) &m->sin_addr)[i / 8] |= 0x80 >> (i % 8);\r
+ r->flags |= ENUMNICS3_BCAST_OK;\r
+ r->addr_size = sizeof (struct sockaddr_in);\r
+ inet_ntop (AF_INET, &a->sin_addr, dst, INET_ADDRSTRLEN);\r
+ }\r
+ else if (unicast->Address.lpSockaddr->sa_family == AF_INET6)\r
+ {\r
+ struct sockaddr_in6 *a = (struct sockaddr_in6 *) &r->address;\r
+ /* for IPv6 broadcast is not defined, zero it down */\r
+ memset (&r->broadcast, 0, sizeof (struct sockaddr));\r
+ r->flags &= ~ENUMNICS3_BCAST_OK;\r
+ r->addr_size = sizeof (struct sockaddr_in6);\r
+ inet_ntop (AF_INET6, &a->sin6_addr, dst, INET6_ADDRSTRLEN);\r
}\r
+\r
+ i = 0;\r
+ i += snprintf (&r->pretty_name[i], 1000 - i > 0 ? 1000 - i : 0,\r
+ "%S (%s", pCurrentAddress->FriendlyName, dst);\r
+ for (j = 0; j < pCurrentAddress->PhysicalAddressLength; j++)\r
+ i += snprintf (&r->pretty_name[i], 1000 - i > 0 ? 1000 - i : 0,\r
+ "%s%02X",j > 0 ? ":" : " - ", pCurrentAddress->PhysicalAddress[j]);\r
+ i += snprintf (&r->pretty_name[i], 1000 - i > 0 ? 1000 - i : 0, ")");\r
+ r->pretty_name[1000] = '\0';\r
+ count += 1;\r
}\r
- GlobalFree(pAddrTable);\r
- GlobalFree(pTable);\r
}\r
\r
+ if (use_enum2)\r
+ {\r
+ GNUNET_free_non_null (interfaces4);\r
+ GNUNET_free_non_null (interfaces6);\r
+ }\r
+\r
+ GNUNET_free (pAddresses);\r
+ return GNUNET_OK;\r
+}\r
+\r
+void\r
+EnumNICs3_free (struct EnumNICs3_results *r)\r
+{\r
+ GNUNET_free (r);\r
+}\r
+\r
+\r
+/**\r
+ * Lists all network interfaces in a combo box\r
+ * Used by the basic GTK configurator\r
+ *\r
+ * @param callback function to call for each NIC\r
+ * @param callback_cls closure for callback\r
+ */\r
+int\r
+ListNICs (void (*callback) (void *, const char *, int), void * callback_cls)\r
+{\r
+ int r;\r
+ int i;\r
+ struct EnumNICs3_results *results = NULL;\r
+ int results_count;\r
+\r
+ r = EnumNICs3 (&results, &results_count);\r
+ if (r != GNUNET_OK)\r
+ return GNUNET_NO;\r
+\r
+ for (i = 0; i < results_count; i++)\r
+ callback (callback_cls, results[i].pretty_name, results[i].is_default);\r
+ GNUNET_free_non_null (results);\r
return GNUNET_YES;\r
}\r
\r